diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..50763c6b0 --- /dev/null +++ b/.clang-format @@ -0,0 +1,114 @@ +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: DontAlign +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: false +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BreakBeforeBraces: Custom +BraceWrapping: + AfterClass: true + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: All +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: AfterColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: None +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +RawStringFormats: + - Delimiters: [pb] + Language: TextProto + BasedOnStyle: google +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: true +SpacesInSquareBrackets: false +Standard: Cpp03 +TabWidth: 8 +UseTab: Never +... + diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..d525cfd1e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,46 @@ +name: Build + +on: [push, pull_request] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally + # well on Windows or Mac. You can convert this to a matrix build if you need + # cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Create Build Environment + # Some projects don't allow in-source building, so create a separate build directory + # We'll use this as our working directory for all subsequent commands + run: cmake -E make_directory ${{github.workspace}}/build + + - name: Configure CMake + # Use a bash shell so we can use the same syntax for environment variable + # access regardless of the host operating system + shell: bash + working-directory: ${{github.workspace}}/build + # Note the current convention is to use the -S and -B options here to specify source + # and build directories, but this is only available with CMake 3.13 and higher. + # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE + + - name: Build + working-directory: ${{github.workspace}}/build + shell: bash + # Execute the build. You can specify a specific target with "--target " + run: cmake --build . --config $BUILD_TYPE + + - name: Test + working-directory: ${{github.workspace}}/build + shell: bash + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest -C $BUILD_TYPE diff --git a/.gitignore b/.gitignore index 668e78805..d6244bd7e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,14 +9,21 @@ targets/ release/ debug/ +# ignore any files under build directories +build/ +_build/ + # test results *.out *.vtu *.pvd *.out.* +*.out-* t3d.bmf* perf.data* *.orig +*.vtk +*_out.* # documentation aux-files. *.aux diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..aecfec5a1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "extern/pybind11"] + path = extern/pybind11 + url = https://github.com/pybind/pybind11.git + branch = stable diff --git a/.travis.yml b/.travis.yml index 74aeb51e7..3b7484f7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,33 @@ language: cpp +os: linux +dist: focal +#sudo: required +before_install: + - PYCMD=$(which python3) + - echo $PYCMD + - sudo -H $PYCMD -m pip install --upgrade pip + #- sudo -H $PYCMD -m pip install --upgrade pytest + - git clone https://github.com/pybind/pybind11.git; cd pybind11; git checkout stable; cd .. +install: + - echo $PYCMD + - cd pybind11; mkdir build; cd build; cmake .. -DPYTHON_EXECUTABLE=$PYCMD; sudo make install; cd ../.. script: - - CXX=g++-4.8 cmake -DUSE_PYTHON_BINDINGS=ON . - - make + - echo $PYCMD + - cmake -DPYTHON_EXECUTABLE=$PYCMD -DUSE_PYBIND_BINDINGS=ON -DUSE_PYTHON_EXTENSION=ON -DENABLE_COVERAGE:BOOL=TRUE . + - make -j 2 - make test -sudo: false + #Comment out various unrelated messages + #- bash <(curl -s https://codecov.io/bash) + addons: apt: sources: - ubuntu-toolchain-r-test packages: - - libboost-python-dev - - g++-4.8 + #- g++-9 - binutils-gold + - python3 + - python3-pip + - python3-dev + - python3-setuptools + - python3-pytest diff --git a/CMakeLists.txt b/CMakeLists.txt index 9edc370a7..0c12b1f5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,27 +1,54 @@ -cmake_minimum_required (VERSION 2.8.7) # >= 2.8.8 necessary for $ +cmake_minimum_required (VERSION 3.1) include (CheckSymbolExists) include (CheckCXXSymbolExists) include (CheckIncludeFiles) include (CheckIncludeFileCXX) include (CheckCXXSourceCompiles) include (GenerateExportHeader) -include (UsePkgConfig) include (ProcessorCount) +# Use ccache if available. Needs to be performed early for it to work with cmake. +find_program(CCACHE_PROGRAM ccache) +if(CCACHE_PROGRAM) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") +endif() + project (oofem CXX C) set (oofem_VERSION_MAJOR 2) -set (oofem_VERSION_MINOR 4) +set (oofem_VERSION_MINOR 6) set (oofem_VERSION_PATCH 0) # Unused set (oofem_HOMEPAGE "http://www.oofem.org") set (bp_HOMEPAGE "http://ksm.fsv.cvut.cz/%7Ebp/bp.html") -set (oofem_COPYRIGHT "Copyright (C) 1994-2017 Borek Patzak") -set (oofem_EMAIL "info@oofem.org") +string(TIMESTAMP YEAR "%Y") +set (oofem_COPYRIGHT "Copyright (C) 1994-${YEAR} Borek Patzak") +set (oofem_EMAIL "oofem@fsv.cvut.cz") + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") # Default is debug build if (NOT CMAKE_BUILD_TYPE) set (CMAKE_BUILD_TYPE Debug) endif () +function(add_git_submodule dir) +# add a Git submodule directory to CMake, assuming the +# Git submodule directory is a CMake project. +# +# Usage: in CMakeLists.txt +# +# include(AddGitSubmodule.cmake) +# add_git_submodule(mysubmod_dir) + find_package(Git REQUIRED) + if(NOT EXISTS ${dir}/CMakeLists.txt) + execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive -- ${dir} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + #COMMAND_ERROR_IS_FATAL ANY #cmake 3.19 + ) + endif() + add_subdirectory(${dir}) +endfunction(add_git_submodule) + + if (MSVC) add_definitions (-D_USE_MATH_DEFINES) set (CMAKE_REQUIRED_DEFINITIONS "-D_USE_MATH_DEFINES") @@ -34,16 +61,13 @@ else () set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fPIC") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fPIC") endif () -# Check with more compilers as time go on -if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCXX) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -elseif (MSVC) - # Nothing to do for MSVC. -endif () -set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") +set (CMAKE_CXX_STANDARD 17) + +set (CMAKE_CXX_FLAGS_DEBUG "-DDEBUG ${CMAKE_CXX_FLAGS_DEBUG}") +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set (CMAKE_CXX_FLAGS_DEBUG "-O0 -Wsuggest-override ${CMAKE_CXX_FLAGS_DEBUG}") +endif() set (CMAKE_CXX_FLAGS_PROFILING "${CMAKE_CXX_FLAGS_PROFILING} -O2 -pg") ####################################################################### @@ -52,8 +76,8 @@ set (CMAKE_CXX_FLAGS_PROFILING "${CMAKE_CXX_FLAGS_PROFILING} -O2 -pg") set (SLEPC_DIR CACHE PATH "Manual SLEPc directory") set (X11_DIR CACHE PATH "Manual X11 directory (OOFEG)") set (TINYXML2_DIR CACHE PATH "Manual TinyXML-2 directory (CEMHYD only)") -set (MY_PETSC_DIR CACHE PATH "Manual PETSc directory") -set (MY_PETSC_ARCH CACHE STRING "Manual PETSc arch name (e.g. linux-gnu-cxx-opt)") +#set (PETSC_DIR CACHE PATH "Manual PETSc directory") +set (PETSC_ARCH CACHE STRING "Manual PETSc arch name (e.g. linux-gnu-cxx-opt)") set (MPI_DIR CACHE PATH "Manual MPI directory") set (VTK_DIR CACHE PATH "Manual VTK directory (For binary VTU export)") set (LAPACK_DIR CACHE PATH "Manual LAPACK directory") @@ -65,19 +89,19 @@ set (METIS_DIR CACHE PATH "Manual Metis directory (Load balancing)") set (PARMETIS_DIR CACHE PATH "Manual ParMetis directory (Load balancing)") #intel mkl pardiso set (INTEL_MKL_PARDISO_DIR CACHE PATH "Manual mkl pardiso directory (sparse direct solver)") +set (INTEL_ONEAPI_DIR CACHE PATH "Manual path to oneAPI install directory (sparse direct solver)") #pardiso-project.org set (PARDISO_ORG_DIR CACHE PATH "Manual pardiso-project.org directory (sparse direct solver)") +set (PARDISO_ORG_LIB CACHE PATH "Manual pardiso-project.org library's name with complete path (sparse direct solver)") #set (BOOST_DIR CACHE PATH "Manual Boost directory") +set (PYBIND_DIR CACHE PATH "Manual pybind11 directory") ####################################################################### ######################## Options ###################################### ####################################################################### option (USE_OOFEG "Enable OOFEG" OFF) -if (${CMAKE_VERSION} VERSION_GREATER "2.8.7") # Compability with older version of cmake - option (USE_SHARED_LIB "Build shared library" ON) -else () - set (USE_SHARED_LIB OFF) -endif () +option (USE_SHARED_LIB "Build shared library" ON) +option (USE_MFRONT "Build shared library" OFF) # Parallel stuff option (USE_PARALLEL "Enable parallel support" OFF) @@ -88,9 +112,10 @@ option (USE_OPENMP "Compile with OpenMP support (for parallel assembly)" OFF) option (USE_DSS "Enable DSS module" OFF) # No reason to use this option (USE_IML "Enable iml++ solvers" OFF) # or this option (USE_SPOOLES "Enable SPOOLES-solver" OFF) # or this -option (USE_INTEL_MKLPARDISO "Enable MKLPARDISO solver support" OFF) +option (USE_INTEL_MKL_PARDISO "Enable MKLPARDISO solver support" OFF) +option (USE_ONEAPI "Enable OneMKL solver support via OneAPI" OFF) option (USE_PARDISO_ORG "Enable PARDISO-project.org solver support" OFF) -option (USE_PETSC "Enable PETSc support (required for parallel)" OFF) +option (USE_PETSC "Enable PETSc support (specify PETSC_DIR and/or PETSC_ARCH if needed)" OFF) option (USE_SLEPC "Enable SLEPc support" OFF) option (USE_LAPACK "Use LAPACK" OFF) option (USE_SUPERLU_MT "Use SUPERLU_MT" OFF) @@ -105,38 +130,43 @@ option (USE_PFEM "Enable PFEM module" OFF) option (USE_TM "Enable heat/mass transfer module" ON) option (USE_CEMHYD "Enable CemHyd support" OFF) option (USE_T3D "Enable T3D support" OFF) -#option (USE_BOOST "Enable Boost" OFF) -option (USE_PYTHON_BINDINGS "Enable Python bidings (OOFEM usable from Python). Implies USE_PYTHON." OFF) -option (USE_PYTHON "Enable Python to be used inside OOFEM (e.g. userdef Dirichlet BCs)" OFF) +option (USE_BOOSTPYTHON_BINDINGS "Rather obsolete, use USE_PYBIND_BINDINGS. Enable Python bidings using boost (OOFEM callable from Python)." OFF) +option (USE_PYBIND_BINDINGS "Enable Python Pybind11 bindings (OOFEM callable from Python and vice versa)." OFF) +option (USE_PYTHON_EXTENSION "Enable Python extension for exposing C++ code to python. Uses Python.h library." OFF) +option (USE_HDF5 "HDF5 support" OFF) +option (USE_MPM "Enable experimental multiphysics module" OFF) if (USE_PARALLEL) add_definitions (-D__PARALLEL_MODE) set (USE_MPI ON) endif () +# Enable coverage testing +if (CMAKE_COMPILER_IS_GNUCC) + option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" FALSE) + + if (ENABLE_COVERAGE) + add_compile_options(--coverage -O0) + list (APPEND EXT_LIBS --coverage) + endif() +endif () + ####################################################################### ######################## Internal libraries ########################### ####################################################################### # I believe the subdirs should be used when including instead. +include_directories ("${oofem_SOURCE_DIR}/src") include_directories ("${oofem_SOURCE_DIR}/src/oofemlib") include_directories ("${oofem_SOURCE_DIR}/src/oofemlib/T3d/src") include_directories ("${oofem_BINARY_DIR}") # Is there really any reason not to compile all of them? Some has cross dependencies. -if (${CMAKE_VERSION} VERSION_LESS "2.8.8") - list (APPEND LIBS core) -else () - list (APPEND LIBS $) -endif () +list (APPEND LIBS $) if (USE_FM) include_directories ("${oofem_SOURCE_DIR}/src/fm") add_definitions (-D__FM_MODULE) - if (${CMAKE_VERSION} VERSION_LESS "2.8.8") - list (APPEND LIBS fm) - else () - list (APPEND LIBS $) - endif () + list (APPEND LIBS $) list (APPEND MODULE_LIST "fm") if (USE_PFEM) add_definitions (-D__PFEM_MODULE) @@ -146,11 +176,7 @@ endif () if (USE_TM) include_directories ("${oofem_SOURCE_DIR}/src/tm") add_definitions (-D__TM_MODULE) - if (${CMAKE_VERSION} VERSION_LESS "2.8.8") - list (APPEND LIBS tm) - else () - list (APPEND LIBS $) - endif () + list (APPEND LIBS $) list (APPEND MODULE_LIST "tm") if (USE_CEMHYD) add_definitions (-D__CEMHYD_MODULE) @@ -161,11 +187,7 @@ endif () if (USE_SM) include_directories ("${oofem_SOURCE_DIR}/src/sm") add_definitions (-D__SM_MODULE) - if (${CMAKE_VERSION} VERSION_LESS "2.8.8") - list (APPEND LIBS sm) - else () - list (APPEND LIBS $) - endif () + list (APPEND LIBS $) list (APPEND MODULE_LIST "sm") if (NOT MSVC AND NOT MINGW) @@ -182,11 +204,7 @@ endif () if (USE_DSS) include_directories ("${oofem_SOURCE_DIR}/src/dss") - if (${CMAKE_VERSION} VERSION_LESS "2.8.8") - list (APPEND LIBS dss) - else () - list (APPEND LIBS $) - endif () + list (APPEND LIBS $) list (APPEND MODULE_LIST "dss") endif () @@ -200,6 +218,14 @@ if (USE_OPENMP) endif () endif () +if (USE_MPM) + include_directories ("${oofem_SOURCE_DIR}/src/mpm") + add_definitions (-D__MPM_MODULE) + list (APPEND LIBS $) + list (APPEND MODULE_LIST "mpm") +endif () + + if (USE_OOFEG) add_definitions (-D__OOFEG) @@ -272,7 +298,7 @@ if (USE_SUPERLU_MT) include_directories("${SUPERLU_MT_DIR}") set (CMAKE_REQUIRED_INCLUDES "${SUPERLU_MT_DIR}") add_definitions (-D__SuperLU_MT_MODULE) - check_include_file_cxx ("SUPERLU_MT/include/slu_mt_ddefs.h" HAVE_SUPERLU_MT_DDEFS_H) + check_include_file_cxx ("${SUPERLU_MT_DIR}/include/slu_mt_ddefs.h" HAVE_SUPERLU_MT_DDEFS_H) if (NOT HAVE_SUPERLU_MT_DDEFS_H) message (FATAL_ERROR "Necessary SUPERLU_MT headers not found; refer to CMakeLists.txt for details") endif () @@ -320,14 +346,17 @@ if (USE_METIS) endif () if (USE_PARDISO_ORG) - if (PARDISO_ORG_DIR) - find_library (PARDISO_ORG_LIB pardiso PATH "${PARDISO_ORG_DIR}") - else () - find_library (PARDISO_ORG_LIB pardiso) + if (NOT PARDISO_ORG_LIB) + if (PARDISO_ORG_DIR) + find_library (PARDISO_ORG_LIB pardiso PATH "${PARDISO_ORG_DIR}") + else () + find_library (PARDISO_ORG_LIB pardiso) + endif () endif () if (${PARDISO_ORG_LIB} STREQUAL "PARDISO_ORG_LIB-NOTFOUND") message (FATAL_ERROR "Pardiso library not found") endif () + message(STATUS "PARDISO_ORG_LIB = ${PARDISO_ORG_LIB}") list (APPEND EXT_LIBS ${PARDISO_ORG_LIB} blas lapack gfortran pthread) set (CMAKE_CXX_COMPILE_FLAGS "${CMAKE_CXX_COMPILES_FLAGS} -fopenmp") set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fopenmp" ) @@ -354,10 +383,98 @@ if (USE_INTEL_MKL_PARDISO) list (APPEND MODULE_LIST "MKLPARDISO") endif () +if (USE_ONEAPI) + if (USE_INTEL_MKL_PARDISO) + message (FATAL_ERROR "Can't use both OneMKL and classic Intel MKL (disable USE_INTEL_MKL_PARDISO option)") + endif() + + message(STATUS "Seeking OneAPI libraries...") + if (WIN32) + # Windows machine must use Intel OpenMP (libiomp5) for OneAPI + list(APPEND MKL_LIBS "mkl_core" "mkl_intel_lp64" "mkl_intel_thread" "libiomp5md") + else() + list(APPEND MKL_LIBS "mkl_core" "mkl_intel_lp64" "mkl_intel_thread" "pthread") + endif () + foreach (f ${MKL_LIBS}) + # OneAPI installation directory + if (INTEL_ONEAPI_DIR) + # user provided OneAPI directory + message(STATUS "User has provided OneAPI installation directory...") + set(oneapiDir ${INTEL_ONEAPI_DIR}) + elseif (WIN32) + # Windows + set(oneapiDir "C:/Program Files (x86)/Intel/oneAPI") + else() + # MacOS or Linux + set(oneapiDir "/opt/intel/oneapi") + endif() + + # library directory + # an alternative could be obtaining from OneAPI's Environment variables + if (WIN32) + # Windows + set(oneapiMklDir "${oneapiDir}/mkl/latest") + set(oneapiMklLibDir "${oneapiMklDir}/lib/intel64") + set(oneapiLibDir + "${oneapiDir}/compiler/latest/windows/compiler/lib/intel64") + elseif(APPLE) + # MacOS + set(oneapiMklDir "${oneapiDir}/mkl/latest") + set(oneapiMklLibDir "${oneapiMklDir}/lib") + set(oneapiLibDir "") + elseif(UNIX) + # Linux (not tested) + set(oneapiMklDir "${oneapiDir}/mkl/latest") + set(oneapiMklLibDir "${oneapiMklDir}/lib/intel64_lin") + set(oneapiLibDir "") + endif() + + message(STATUS " Seeking for ${f} in: ${oneapiMklLibDir};${oneapiLibDir}...") + find_library (${f}_LIB ${f} HINTS "${oneapiMklLibDir}" "${oneapiLibDir}" DOC "MKLPARDISO (library)") + include_directories ("${oneapiMklDir}/include") + + if (${${f}_LIB} STREQUAL "${f}_LIB-NOTFOUND") + message (FATAL_ERROR "OneAPI ${f} library not found") + else() + message (STATUS " OK: ${f} library successfully found at ${${f}_LIB}") + endif () + list (APPEND EXT_LIBS ${${f}_LIB}) + endforeach () + list (APPEND MODULE_LIST "MKLPARDISO") +endif () + + if (USE_SLEPC) - if (SLEPC_DIR) - find_library (SLEPC_LIBS slepc PATH "${SLEPC_DIR}/lib") + set (USE_PETSC ON) +endif () + + +if (USE_PETSC) + if (NOT "${PETSC_DIR}") + # setting defaults for typical linux environments: + #file (GLOB paths "/usr/lib/petscdir/*.*.*") + #list (GET paths 0 PETSC_DIR) + #message ("***************** PETSC_DIR: ${PETSC_DIR}") + endif () + if (NOT "${PETSC_ARCH}") + #file (GLOB children RELATIVE ${PETSC_DIR} "${PETSC_DIR}/*") + #list (GET children 0 PETSC_ARCH) + #message ("***************** PETSC_ARCH: ${PETSC_ARCH}") + endif () + find_package (PETSc) + # find_package(PETSc COMPONENTS CXX) + include_directories (${PETSC_INCLUDES}) + list (APPEND EXT_LIBS ${PETSC_LIBRARIES}) + list (APPEND MODULE_LIST "PETSc") + set (USE_MPI ON) + add_definitions (-D__PETSC_MODULE) +endif () + +if (USE_SLEPC) + if (SLEPC_DIR) + find_library (SLEPC_LIBS slepc PATH "${SLEPC_DIR}/${PETSC_ARCH}/lib") include_directories ("${SLEPC_DIR}/include") + include_directories ("${SLEPC_DIR}/${PETSC_ARCH}/include") else () find_library (SLEPC_LIBS slepc) endif () @@ -370,42 +487,6 @@ if (USE_SLEPC) add_definitions (-D__SLEPC_MODULE) endif () -if (USE_PETSC) - # A real PETScConfig.cmake file would have been nice to use: - #find_package (PETSc 3.3 HINTS "${MY_PETSC_DIR}/${MY_PETSC_ARCH}") - - # Have to use pkgconfig information - find_package (PkgConfig REQUIRED) - - set (ENV{PKG_CONFIG_PATH} "${MY_PETSC_DIR}/${MY_PETSC_ARCH}/lib64/pkgconfig:${MY_PETSC_DIR}/${MY_PETSC_ARCH}/lib/pkgconfig") - pkg_check_modules (PC_PETSC REQUIRED PETSc) - include_directories (${PC_PETSC_INCLUDE_DIRS}) - - # Find the actual libraries: - foreach (f ${PC_PETSC_LIBRARIES}) - find_library (${f}_LIBRARY NAMES ${f} lib${f} - HINTS - ${PC_PETSC_LIBRARY_DIRS} - ) - list (APPEND EXT_LIBS ${${f}_LIBRARY}) - endforeach () - # Currently unused flags: - # PC_PETSC_LDFLAGS ... all required linker flags - # PC_PETSC_LDFLAGS_OTHER ... all other linker flags - # PC_PETSC_CFLAGS ... all required cflags - # PC_PETSC_CFLAGS_OTHER ... the other compiler flags - - #find_package (PETSc REQUIRED HINTS "${MY_PETSC_DIR}/${MY_PETSC_ARCH}/conf") - #include_directories ("${MY_PETSC_DIR}/include" "${MY_PETSC_DIR}/${MY_PETSC_ARCH}/include" ${PETSC_INCLUDE_PATH}) - #find_library (PETSC_LIB petsc PATH "${MY_PETSC_DIR}/${MY_PETSC_ARCH}/lib/") - #if (${PETSC_LIB} STREQUAL "PETSC_LIB-NOTFOUND") - # message (FATAL_ERROR "PETSc library not found") - #endif () - #list (APPEND EXT_LIBS ${PETSC_LIB} ${PETSC_PACKAGE_LIBS}) - list (APPEND MODULE_LIST "PETSc") - set (USE_MPI ON) - add_definitions (-D__PETSC_MODULE) -endif () if (USE_MPI) if (MPI_DIR) @@ -450,6 +531,12 @@ if (USE_TRIANGLE) list (APPEND MODULE_LIST "Triangle") endif () +if (USE_HDF5) + find_package(HDF5 REQUIRED "CXX") + include_directories(${HDF5_INCLUDE_DIRS}) + list (APPEND EXT_LIBS ${HDF5_LIBRARIES} ${HDF5_HL_LIBRARIES}) +endif () + if (USE_TINYXML) if (TINYXML2_DIR) include_directories (${TINYXML2_DIR}) @@ -489,29 +576,69 @@ if (USE_SPOOLES) list (APPEND MODULE_LIST "SPOOLES") endif () -# We need the interpreter for the test suite. -find_package(PythonInterp "2.7") - -if (USE_PYTHON_BINDINGS OR USE_PYTHON) +if (USE_PYTHON_EXTENSION OR USE_BOOSTPYTHON_BINDINGS) # PythonLibs in cmake is bugged, have to try and rely on PythonInterp to get the suitable major and minor versions. - set (CMAKE_LIBRARY_DIR ${PYTHON_DIR}) - find_package(PythonInterp "2.7" REQUIRED) - find_package(PythonLibs "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" REQUIRED) - include_directories (${PYTHON_INCLUDE_DIRS}) - list (APPEND EXT_LIBS ${PYTHON_LIBRARIES}) + #set (CMAKE_LIBRARY_DIR ${PYTHON_DIR}) + #Print if set up manually + message(STATUS "PYTHON_LIBRARY = ${Python3_LIBRARIES}") + message(STATUS "PYTHON_EXECUTABLE = ${Python3_EXECUTABLE}") + message(STATUS "PYTHON_INCLUDE_DIR = ${Python3_INCLUDE_DIRS}") + find_package (Python3 COMPONENTS Interpreter Development) +# find_package(PythonInterp "3" REQUIRED) +# find_package(PythonLibs "${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}" REQUIRED) + include_directories (${Python3_INCLUDE_DIRS}) + list (APPEND EXT_LIBS ${Python3_LIBRARIES}) list (APPEND MODULE_LIST "Python") - add_definitions(-D__PYTHON_MODULE) - - #if (USE_PYTHON_BINDINGS) - # require boost_python also for python stuff by itself - find_package(Boost COMPONENTS "python-py${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}" REQUIRED) + if(USE_PYTHON_EXTENSION) + add_definitions(-D_PYTHON_EXTENSION) + endif () + + if(USE_BOOSTPYTHON_BINDINGS) + # require boost_python also for python stuff by itself + find_package(Boost COMPONENTS "python-py${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR}" REQUIRED) include_directories (${Boost_INCLUDE_DIRS}) list (APPEND EXT_LIBS ${Boost_LIBRARIES}) - add_definitions(-DBOOST_PYTHON) - #endif () + add_definitions(-D_BOOSTPYTHON_BINDINGS) + endif () endif () +if(WIN32) + set(PYTHON_MODULE_EXTENSION ".pyd") +else() + set(PYTHON_MODULE_EXTENSION ".so") +endif() + + +if (USE_PYBIND_BINDINGS) + #build pybind11 bindings + find_package(Python COMPONENTS Interpreter Development) + #find_package(pybind11 CONFIG) + add_git_submodule(extern/pybind11) + if (PYBIND_DIR) + message(STATUS "PYBIND_DIR = ${PYBIND_DIR}") + include_directories (${PYBIND_DIR})#Need also to manually set it up since it can be anywhere + endif () + include_directories (${pybind11_INCLUDE_DIR} ${Python_INCLUDE_DIRS}) + list (APPEND EXT_LIBS ${Python_LIBRARIES}) + pybind11_add_module(oofempy THIN_LTO ${oofem_SOURCE_DIR}/bindings/python/oofem.cpp ${PYBIND11_HEADERS}) + target_link_libraries(oofempy PRIVATE liboofem) + set_target_properties (oofempy PROPERTIES SUFFIX "${PYTHON_MODULE_EXTENSION}") + + # Make sure pytest is found or produce a fatal error + if(NOT PYTEST_FOUND) + execute_process(COMMAND ${Python_EXECUTABLE} -c "import pytest; print(pytest.__version__)" + RESULT_VARIABLE pytest_not_found OUTPUT_VARIABLE pytest_version ERROR_QUIET) + if(pytest_not_found) + message(FATAL_ERROR "Running the tests requires pytest. Please install it manually" + " (try: ${Python_EXECUTABLE} -m pip install pytest)") + endif() + set(PYBIND11_PYTEST_FOUND TRUE CACHE INTERNAL "") + add_definitions(-D_PYBIND_BINDINGS) + endif() + set (USE_SHARED_LIB ON) +endif() + ####################################################################### ######################## Configuration ################################ ####################################################################### @@ -519,15 +646,13 @@ site_name (HOST_NAME) set (HOST_TYPE "${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_SYSTEM_NAME}") # This should be renamed TARGET_TYPE. set (BUILDNAME "OOFEM(${MODULE_LIST})-${HOST_TYPE}-${HOST_NAME}") -check_include_file_cxx ("unistd.h" HAVE_UNISTD_H) check_include_file_cxx ("execinfo.h" HAVE_EXECINFO_H) -check_cxx_symbol_exists ("access" "unistd.h" HAVE_ACCESS) check_cxx_symbol_exists ("cbrt" "cmath" HAVE_CBRT) check_cxx_symbol_exists ("isnan" "cmath" HAVE_ISNAN) if (USE_SHARED_LIB) set (OOFEM_EXPORT_HEADER "#include \"oofem_export.h\"") # For consistant library on linux and windows platforms. - add_compiler_export_flags (LIBOOFEM_EXPORT_CFLAGS) + #add_compiler_export_flags (LIBOOFEM_EXPORT_CFLAGS) else () set (OOFEM_EXPORT_HEADER "#define OOFEM_EXPORT\n#define OOFEM_NO_EXPORT") endif () @@ -540,12 +665,7 @@ configure_file ( ######################## Targets ###################################### ####################################################################### # Subtargets -if (${CMAKE_VERSION} VERSION_LESS "2.8.8") - # This won't work on windows, but windows users should have newer version than 2.8.7) - set (LIB_TYPE SHARED) -else () - set (LIB_TYPE OBJECT) -endif () +set (LIB_TYPE OBJECT) add_subdirectory ("${oofem_SOURCE_DIR}/src/oofemlib") if (USE_DSS) add_subdirectory ("${oofem_SOURCE_DIR}/src/dss") @@ -559,11 +679,15 @@ endif () if (USE_FM) add_subdirectory ("${oofem_SOURCE_DIR}/src/fm") endif () +if (USE_MPM) + add_subdirectory ("${oofem_SOURCE_DIR}/src/mpm") +endif () set (oofempy) -if (USE_PYTHON_BINDINGS) - set (oofempy ${oofem_SOURCE_DIR}/bindings/python/oofemlib.cpp) +if (USE_BOOSTPYTHON_BINDINGS) + set (oofempy ${oofem_SOURCE_DIR}/bindings/Deprecated/python/oofemlib.cpp) endif () + # Main targets if (USE_SHARED_LIB) add_library (liboofem @@ -598,6 +722,12 @@ if (USE_SHARED_LIB) set_target_properties (tm PROPERTIES COMPILE_FLAGS ${LIBOOFEM_EXPORT_CFLAGS}) endif () endif() + if (USE_MPM) + set_target_properties (mpm PROPERTIES COMPILE_DEFINITIONS "liboofem_EXPORTS") + if (NOT "${LIBOOFEM_EXPORT_CFLAGS}" STREQUAL "") + set_target_properties (mpm PROPERTIES COMPILE_FLAGS ${LIBOOFEM_EXPORT_CFLAGS}) + endif () +endif() generate_export_header (liboofem BASE_NAME OOFEM @@ -606,25 +736,25 @@ endif () # OOFEM target if (USE_SHARED_LIB) # Prefer dynamic lib if available. - add_executable (oofem ${oofem_SOURCE_DIR}/src/main/main.C) - target_link_libraries (oofem liboofem) -elseif (${CMAKE_VERSION} VERSION_LESS "2.8.8") # Hackish backwards compatibility - add_executable (oofem ${oofem_SOURCE_DIR}/src/main/main.C) - target_link_libraries (oofem ${LIBS} ${EXT_LIBS}) + add_executable (oofem ${oofem_SOURCE_DIR}/src/main/main.C) + target_link_libraries (oofem liboofem) else () - add_executable (oofem ${oofem_SOURCE_DIR}/src/main/main.C ${LIBS}) - target_link_libraries (oofem ${EXT_LIBS}) + add_executable (oofem ${oofem_SOURCE_DIR}/src/main/main.C ${LIBS}) + target_link_libraries (oofem ${EXT_LIBS}) endif () + install (TARGETS oofem DESTINATION bin) +if (USE_MFRONT) + find_package (MFrontGenericInterface REQUIRED) + target_link_libraries(oofem mgis::MFrontGenericInterface) +endif () + if (USE_OOFEG) # OOFEG target: if (USE_SHARED_LIB) add_executable (oofeg ${oofem_SOURCE_DIR}/src/main/oofeg.C) target_link_libraries (oofeg liboofem) - elseif (${CMAKE_VERSION} VERSION_LESS "2.8.8") # Hackish backwards compatibility - add_executable (oofeg ${oofem_SOURCE_DIR}/src/main/oofeg.C) - target_link_libraries (oofeg ${LIBS} ${EXT_LIBS}) else () add_executable (oofeg ${oofem_SOURCE_DIR}/src/main/oofeg.C ${LIBS}) target_link_libraries (oofeg ${EXT_LIBS}) @@ -632,15 +762,22 @@ if (USE_OOFEG) install(TARGETS oofeg DESTINATION bin) endif () +add_executable(liboofem_benchmark ${oofem_SOURCE_DIR}/src/main/benchmark.C) +set_target_properties(liboofem_benchmark PROPERTIES EXCLUDE_FROM_ALL TRUE) +target_link_libraries (liboofem_benchmark liboofem benchmark) + # Example of using liboofem with dynamic input record: -add_executable(beam01 ${oofem_SOURCE_DIR}/bindings/oofemlib/beam01.C) -set_target_properties(beam01 PROPERTIES EXCLUDE_FROM_ALL TRUE) -target_link_libraries (beam01 liboofem) +add_executable(beam2d_1 ${oofem_SOURCE_DIR}/bindings/oofemlib/beam2d_1.C) +set_target_properties(beam2d_1 PROPERTIES EXCLUDE_FROM_ALL TRUE) +target_link_libraries (beam2d_1 liboofem) add_executable(hexgrid ${oofem_SOURCE_DIR}/bindings/oofemlib/hexgrid.C) set_target_properties(hexgrid PROPERTIES EXCLUDE_FROM_ALL TRUE) target_link_libraries (hexgrid liboofem) +add_executable(dream3d_analysis ${oofem_SOURCE_DIR}/bindings/oofemlib/dream3d_analysis.C) +set_target_properties(dream3d_analysis PROPERTIES EXCLUDE_FROM_ALL TRUE) +target_link_libraries(dream3d_analysis liboofem) # CppCheck target (not built by default) add_custom_target(cppcheck) @@ -728,49 +865,61 @@ endif () if (USE_SM) file (GLOB sm_tests RELATIVE "${oofem_TEST_DIR}/sm" "${oofem_TEST_DIR}/sm/*.in") foreach (case ${sm_tests}) - add_test (NAME "test_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/sm COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "test_sm_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/sm COMMAND ${oofem_cmd} "-f" ${case}) + endforeach (case) + + file (GLOB sm_tests RELATIVE "${oofem_TEST_DIR}/sm" "${oofem_TEST_DIR}/sm/*.sh") + foreach (case ${sm_tests}) + add_test (NAME "test_sm_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/sm COMMAND bash ${case} ${oofem_cmd}) endforeach (case) endif () if (USE_FM) file (GLOB fm_tests RELATIVE "${oofem_TEST_DIR}/fm" "${oofem_TEST_DIR}/fm/*.in") foreach (case ${fm_tests}) - add_test (NAME "test_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/fm COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "test_fm_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/fm COMMAND ${oofem_cmd} "-f" ${case}) endforeach (case) endif() if (USE_TM) file (GLOB tm_tests RELATIVE "${oofem_TEST_DIR}/tm" "${oofem_TEST_DIR}/tm/*.in") foreach (case ${tm_tests}) - add_test (NAME "test_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/tm COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "test_tm_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/tm COMMAND ${oofem_cmd} "-f" ${case}) endforeach (case) endif() if (USE_TM AND USE_SM) file (GLOB tmsm_tests RELATIVE "${oofem_TEST_DIR}/tmsm" "${oofem_TEST_DIR}/tmsm/*.in") foreach (case ${tmsm_tests}) - add_test (NAME "test_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/tmsm COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "test_tmsm_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/tmsm COMMAND ${oofem_cmd} "-f" ${case}) endforeach (case) endif() if (USE_TM AND USE_FM) file (GLOB tmfm_tests RELATIVE "${oofem_TEST_DIR}/tmfm" "${oofem_TEST_DIR}/tmfm/*.in") foreach (case ${tmfm_tests}) - add_test (NAME "test_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/tmfm COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "test_tmfm_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/tmfm COMMAND ${oofem_cmd} "-f" ${case}) endforeach (case) endif() if (USE_TM AND USE_CEMHYD) file (GLOB tmcemhyd_tests RELATIVE "${oofem_TEST_DIR}/tmcemhyd" "${oofem_TEST_DIR}/tmcemhyd/*.in") foreach (case ${tmcemhyd_tests}) - add_test (NAME "test_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/tmcemhyd COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "test_tm_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/tmcemhyd COMMAND ${oofem_cmd} "-f" ${case}) endforeach (case) endif() if (USE_FM AND USE_PFEM) file (GLOB fmpfem_tests RELATIVE "${oofem_TEST_DIR}/fmpfem" "${oofem_TEST_DIR}/fmpfem/*.in") foreach (case ${fmpfem_tests}) - add_test (NAME "test_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/fmpfem COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "test_fm_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/fmpfem COMMAND ${oofem_cmd} "-f" ${case}) + endforeach (case) +endif() + +if (USE_SM AND USE_MFRONT) + file (GLOB smmfront_tests RELATIVE "${oofem_TEST_DIR}/smmfront" "${oofem_TEST_DIR}/smmfront/*.in") + foreach (case ${smmfront_tests}) + add_test (NAME "test_sm_${case}" WORKING_DIRECTORY ${oofem_TEST_DIR}/smmfront COMMAND ${oofem_cmd} "-f" ${case}) endforeach (case) endif() @@ -782,44 +931,47 @@ set (oofem_BENCHMARK_DIR "${oofem_SOURCE_DIR}/tests/benchmark") if (USE_TM AND USE_SM AND USE_DSS AND USE_IML) file (GLOB tmsmdssiml_benchmark RELATIVE "${oofem_BENCHMARK_DIR}/tmsmdssiml" "${oofem_BENCHMARK_DIR}/tmsmdssiml/*.in") foreach (case ${tmsmdssiml_benchmark}) - add_test (NAME "benchmark_${case}" WORKING_DIRECTORY ${oofem_BENCHMARK_DIR}/tmsmdssiml COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "benchmark_tmsm_${case}" WORKING_DIRECTORY ${oofem_BENCHMARK_DIR}/tmsmdssiml COMMAND ${oofem_cmd} "-f" ${case}) endforeach (case) endif() if (USE_FM) file (GLOB fm_benchmark RELATIVE "${oofem_BENCHMARK_DIR}/fm" "${oofem_BENCHMARK_DIR}/fm/*.in") foreach (case ${fm_benchmark}) - add_test (NAME "benchmark_${case}" WORKING_DIRECTORY ${oofem_BENCHMARK_DIR}/fm COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "benchmark_fm_${case}" WORKING_DIRECTORY ${oofem_BENCHMARK_DIR}/fm COMMAND ${oofem_cmd} "-f" ${case}) endforeach (case) endif() if (USE_SM) file (GLOB sm_benchmark RELATIVE "${oofem_BENCHMARK_DIR}/sm" "${oofem_BENCHMARK_DIR}/sm/*.in") foreach (case ${sm_benchmark}) - add_test (NAME "benchmark_${case}" WORKING_DIRECTORY ${oofem_BENCHMARK_DIR}/sm COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "benchmark_sm_${case}" WORKING_DIRECTORY ${oofem_BENCHMARK_DIR}/sm COMMAND ${oofem_cmd} "-f" ${case}) endforeach (case) endif() if (USE_TM) file (GLOB tm_benchmark RELATIVE "${oofem_BENCHMARK_DIR}/tm" "${oofem_BENCHMARK_DIR}/tm/*.in") foreach (case ${tm_benchmark}) - add_test (NAME "benchmark_${case}" WORKING_DIRECTORY ${oofem_BENCHMARK_DIR}/tm COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "benchmark_tm_${case}" WORKING_DIRECTORY ${oofem_BENCHMARK_DIR}/tm COMMAND ${oofem_cmd} "-f" ${case}) endforeach (case) endif() if (USE_FM AND USE_SM AND USE_PFEM) file (GLOB fmpfem_benchmark RELATIVE "${oofem_BENCHMARK_DIR}/fmpfem" "${oofem_BENCHMARK_DIR}/fmpfem/*.in") foreach (case ${fmpfem_benchmark}) - add_test (NAME "benchmark_${case}" WORKING_DIRECTORY ${oofem_BENCHMARK_DIR}/fmpfem COMMAND ${oofem_cmd} "-f" ${case}) + add_test (NAME "benchmark_fm_${case}" WORKING_DIRECTORY ${oofem_BENCHMARK_DIR}/fmpfem COMMAND ${oofem_cmd} "-f" ${case}) endforeach (case) -endif() - +endif() + # Custom targets for test and benchmarks (which can conveniently be accessed from IDEs) -ProcessorCount(N) +#ProcessorCount(N) if (N EQUAL 0) set (N 1) endif () +if (USE_OPENMP) # OPENMP will use all processors by default + set (N 1) +endif () if (MSVC) add_custom_target (tests COMMAND ${CMAKE_CTEST_COMMAND} "-j${N}" "-R" "^test" "-C" "Debug") @@ -831,6 +983,12 @@ else () add_custom_target (benchmarks COMMAND ${CMAKE_CTEST_COMMAND} "-j${N}" "-R" "^benchmark") endif () +######################## Tests of Python bindings ######################################## +if (USE_PYBIND_BINDINGS) + add_test (NAME "test_python_pybind11_bindings" WORKING_DIRECTORY ${oofem_SOURCE_DIR}/bindings/python COMMAND ${Python_EXECUTABLE} "-m" "pytest" ${oofem_SOURCE_DIR}/bindings/python) + set_tests_properties("test_python_pybind11_bindings" PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_BINARY_DIR}") +endif() + ####################################################################### ######################## Packing ###################################### diff --git a/ChangeLog b/ChangeLog index 9408a2ad6..6d770f9ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2017-12-30 Borek Patzak + * OOFEM 2.5 released + * Added support for other sparse matrix storage schemes in nlinear dynamic problem + * Adding linear and quadratic wedge elements for transport + * unv2oofem python3 support, added support for sets + * boundarysurfaceload support for cct element + * Implementation of quasicontinuum + * PARDISO_ORG sparse solver supported + * Adding support of artificial drillStiffness and layered cross-section on MITC element. + * Adding SuperLU_MT interface, new -p option to set number of threads + * 2D eikonal nonlocal damage model + * Added new material models for concrete: ConcreteFCM, FRCFCM and FRCFCMNL + * Unified boundary load evaluation + * Adding linear nodal spring element, linear line-distributed spring element + * Added subsoil elements + + +2016-02-15 Borek Patzak + + * OOFEM 2.4 released + * Added new StaticStructural, TransientTransport, and Warping analyses, as well as new Particle FEM CFD submodule + * MKL Pardiso solver support with optimized CSC implementation, support for block matrices in PETSc + * New structural elements: MITC4 and trshell02 shells, 3D plane stress Almann element + * Added support for global condensation (fixes many issues on beam elements) + * And many improvements and bug-fixes + 2014-02-12 Borek Patzak * OOFEM 2.3 released. diff --git a/README b/README index ee48f12b3..3ab3bf84e 100644 --- a/README +++ b/README @@ -9,11 +9,11 @@ OOFEM : Object Oriented Finite Element Code - Copyright (C) 1993 - 2013 Borek Patzak + Copyright (C) 1993 - 2017 Borek Patzak Czech Technical University, Faculty of Civil Engineering, Department of Mechanics, 166 29 Prague, Czech Republic - www.oofem.org e-mail: info@oofem.org + www.oofem.org e-mail: oofem@fsv.cvut.cz This program is free software; you can redistribute it and/or modify @@ -199,7 +199,7 @@ more documentation, manuals and new versions. Bugs ============================================================================== -Please mail all bug reports and suggestions to [info@oofem.org]. I will try to +Please mail all bug reports and suggestions to [oofem@fsv.cvut.cz]. I will try to give satisfaction, if the time is at least partially on my side. diff --git a/README.md b/README.md new file mode 100644 index 000000000..d22ca1856 --- /dev/null +++ b/README.md @@ -0,0 +1,124 @@ +# OOFEM.org +![Build workflow](https://github.com/oofem/oofem/actions/workflows/build.yml/badge.svg) +[![License: LGPL v2.1](https://img.shields.io/badge/License-LGPL%20v2.1-blue.svg)](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4339630.svg)](https://doi.org/10.5281/zenodo.4339630) + + +OOFEM is parallel, object-oriented finite element code for solving mechanical, transport and fluid mechanics problems. + +OOFEM is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. + +Copyright (C) 1993 - 2021 Borek Patzak + +## Getting Started +### What is here +The source directory tree holds source code to the OOFEM package. +``` + OOFEM_TOP_DIR + | + |-- doc - contains the "User's guide", sources to generate "Reference manual", + | documents describing the input file specifications, element and + | material libraries, and other useful documents. + | + |-- src - source files of all oofem modules + | | + | |-- oofemlib - sources of the core part of OOFEM, the OOFEMlib module. + | | + | |-- sm - sources of structural analysis module. + | | + | |-- tm - sources of transport problem module. + | | + | |-- fm - sources of fluid mechanics module. + | | + | |-- dss - includes the sources for Direct Sparse Solver (DSS), + | | contributed by R. Vondracek) + | | + | |-- main - contains the sources of main() and implementation of some + | global functions for oofem, oofeg. + | + |-- tools - sources for several utility programs. + | + |-- tests - contains several tests, which are useful to verify + | the program functionality. + | + |-- bindings - holds sources to generate OOFEM bindings to Python programming language. +``` + + +### Pre-requisites + +* The oofem requires the CMake cross-platform build system and C++ compiler with STL support (Standard Template Library). + +* The oofem contains interface to IML++ library. It is the C++ templated library of modern iterative methods for solving both symmetric and +non-symmetric linear systems of equations, written by Roldan Pozo. It can be downloaded from http://math.nist.gov/iml++/. + +* Parallel support for distributed memory requires MPI library to be installed. If you do not have any, we recommend to use Open MPI. +This is a freely available, high-performance, and portable implementation of MPI (http://www.open-mpi.org/). + +* For high performance linear solvers, OOFEM can use [PETSc](https://www.mcs.anl.gov/petsc/), [SuperLU](http://crd-legacy.lbl.gov/~xiaoye/SuperLU/), MKL [Pardiso](https://software.intel.com/en-us/mkl-developer-reference-fortran-intel-mkl-pardiso-parallel-direct-sparse-solver-interface) or [Pardiso-project.org]( http://www.pardiso-project.org/) solvers. + +* For high performance eigenvalue solvers, oofem uses SLEPc. The toolkit can be downloaded from SLEPc project home page +(http://www.grycap.upv.es/slepc). + +## Installation + +* unpack sources +* create an out-of-tree build directory +``` + mkdir -p ~/build/debug +``` +* configure the target +``` + cd ~/build/debug; cmake PATH_TO_OOFEM_SOURCES +``` + where PATH_TO_OOFEM_SOURCES is the path to OOFEM source directory, + created in step 0 (~/oofem-2.2, for example). +* compile OOFEM +``` + make +``` + +### Running the tests +To run the tests, go to your build directory and run ctest +``` +ctest +``` + + +### Additional instructions +* Instead of cmake you can use ccmake which uses an ncurses interface, + or cmake-gui for a GUI. Use the command make help for a list of all targets. + +* You can find detailed installation (including installation on Windows) + instruction on OOFEM wiki (http://www.oofem.org/wiki/doku.php?id=installation) + +* To get support check out oofem wiki (www.oofem.org/wiki) and + oofem forum (www.oofem.org/forum) as well. + + +### Running oofem +The oofem program prints out the available options when run without +any option. To run a specific job, you can enter +``` +oofem -f input_file_name +``` +## Documentation +You may find OOFEM documentation [here](http://oofem.org/en/manual). + + + +## Further information +Please consult oofem home page (http://www.oofem.org) for +more documentation, manuals and new versions. + +## Authors + +See the list of [contributors](http://www.oofem.org/doku.php?id=en:credits) who participated in this project. + +## Acknowledgments +http://www.oofem.org/doku.php?id=en:funding + + + + diff --git a/VERSION b/VERSION index 6b4950e3d..c0868c581 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.4 +2.6.devel diff --git a/bindings/python/README b/bindings/Deprecated/python/README similarity index 89% rename from bindings/python/README rename to bindings/Deprecated/python/README index f0c8413ab..602df4c23 100644 --- a/bindings/python/README +++ b/bindings/Deprecated/python/README @@ -32,10 +32,13 @@ */ This directory contains sources to generate OOFEM bindings to Python programming language. +Currently, Python version 3.x is supported, small changes are required for old Python 2.x. The boost.python library is required to be installed. To compile oofem python module, set "USE_PYTHON_BINDINGS" to "ON" when configuring -oofem target using cmake. +oofem target using cmake. Also, if needed, set corresponding -DPYTHON_EXECUTABLE +-DPYTHON_INCLUDE_DIR and -DPYTHON_LIBRARY. This is useful when more Python versions are available. + For testing the bindings, the liboofem.so file must be somewhere where python looks for modules. This can be done e.g. by symlinking to the .so in the build directory by diff --git a/bindings/python/patch100.in b/bindings/Deprecated/python/inputs/patch100.in similarity index 100% rename from bindings/python/patch100.in rename to bindings/Deprecated/python/inputs/patch100.in diff --git a/bindings/Deprecated/python/inputs/tmpatch05.in b/bindings/Deprecated/python/inputs/tmpatch05.in new file mode 100644 index 000000000..62c99ce73 --- /dev/null +++ b/bindings/Deprecated/python/inputs/tmpatch05.in @@ -0,0 +1,28 @@ +tmpatch05.out +Patch test of Quad1_ht elements. Convection as the Newton law (Cauchy's b.c.) via a heat transfer coefficient. +StationaryProblem nsteps 1 nmodules 1 +errorcheck +#vtkxml tstep_all domain_all primvars 1 6 vars 1 56 stype 1 +domain HeatTransfer +OutputManager tstep_all dofman_all element_all +ndofman 6 nelem 2 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 3 +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 2.0 0.0 0.0 +node 3 coords 3 0.0 1.0 0.0 +node 4 coords 3 2.0 1.0 0.0 +node 5 coords 3 0.0 8.0 0.0 +node 6 coords 3 2.0 8.0 0.0 +quad1ht 1 nodes 4 1 2 4 3 +quad1ht 2 nodes 4 4 6 5 3 +SimpleTransportCS 1 mat 1 set 1 thickness 0.15 +IsoHeat 1 d 0. k 3.0 c 1.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 10 values 1 0.0 set 2 +#BoundaryCondition 1 loadTimeFunction 1 dofs 1 10 values 1 15.0 set 3 +#Newton bc +constantedgeload 2 loadTimeFunction 1 components 1 15.0 properties 1 a 0.8 loadtype 3 set 3 +ConstantFunction 1 f(t) 1.0 +Set 1 elementranges {(1 2)} +Set 2 nodes 2 1 2 +Set 3 elementedges 2 2 2 + + diff --git a/bindings/python/tmpatch42.in b/bindings/Deprecated/python/inputs/tmpatch42.in similarity index 100% rename from bindings/python/tmpatch42.in rename to bindings/Deprecated/python/inputs/tmpatch42.in diff --git a/bindings/python/oofemReader.py b/bindings/Deprecated/python/oofemReader.py similarity index 100% rename from bindings/python/oofemReader.py rename to bindings/Deprecated/python/oofemReader.py diff --git a/bindings/python/oofemlib.cpp b/bindings/Deprecated/python/oofemlib.cpp similarity index 91% rename from bindings/python/oofemlib.cpp rename to bindings/Deprecated/python/oofemlib.cpp index 229bd8207..63fbd94bb 100644 --- a/bindings/python/oofemlib.cpp +++ b/bindings/Deprecated/python/oofemlib.cpp @@ -88,14 +88,14 @@ namespace bp = boost::python; #include "gausspoint.h" #include "internalstatetype.h" #include "matresponsemode.h" -#include "Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "matstatus.h" -#include "Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "exportmodulemanager.h" #include "outputmanager.h" #include "classfactory.h" -#include "Materials/structmatsettable.h" +#include "sm/Materials/structmatsettable.h" #include @@ -136,8 +136,6 @@ routine at the end. If converters are missing for some type (such as std::vector added at the end by simply instantiating these templates with the respective argument. */ - - // copied from https://github.com/eudoxos/minieigen/blob/master/src/converters.hpp (written by myself) template bool pySeqItemCheck(PyObject* o, int i){ return bp::extract(bp::object(bp::handle<>(PySequence_GetItem(o,i)))).check(); } @@ -146,7 +144,8 @@ T pySeqItemExtract(PyObject* o, int i){ return bp::extract(bp::object(bp::han // AnyArray will be FloatArray or IntArray, Scalar is double or int template -struct custom_AnyArray_from_sequence{ +struct custom_AnyArray_from_sequence +{ custom_AnyArray_from_sequence(){ bp::converter::registry::push_back(&convertible,&construct,bp::type_id()); } static void* convertible(PyObject* obj_ptr){ // dont check size, since FloatArray/IntArray are always dynamic-sized @@ -170,7 +169,8 @@ struct custom_AnyArray_from_sequence{ // copied from https://github.com/woodem/woo/blob/master/lib/pyutil/converters.hpp (written by myself) /*** python sequence to std::vector ***/ template -struct custom_vector_from_seq{ +struct custom_vector_from_seq +{ custom_vector_from_seq(){ bp::converter::registry::push_back(&convertible,&construct,bp::type_id >()); } static void* convertible(PyObject* obj_ptr){ // the second condition is important, for some reason otherwise there were attempted conversions of Body to list which failed afterwards. @@ -187,8 +187,9 @@ struct custom_vector_from_seq{ }; /*** std::vector to python list ***/ template -struct custom_vector_to_list{ - static PyObject* convert(const vector& v){ +struct custom_vector_to_list +{ + static PyObject* convert(const vector& v) { bp::list ret; for(const containedType& e: v) ret.append(e); return bp::incref(ret.ptr()); } @@ -196,13 +197,13 @@ struct custom_vector_to_list{ /** shorthand for registering both converter above **/ template -void converters_cxxVector_pyList_2way(){ +void converters_cxxVector_pyList_2way() +{ custom_vector_from_seq(); bp::to_python_converter,custom_vector_to_list>(); }; - /***************************************************** * FloatArray *****************************************************/ @@ -256,7 +257,7 @@ void pyclass_FloatArray() .def("computeSquaredNorm", &FloatArray::computeSquaredNorm, "Computes the square of the norm") .def("sum", &FloatArray::sum, "Computes the sum of receiver values") - .def("__str__", &FloatArray_str,"Return printable representation.") + .def("__str__", &FloatArray_str,"Return printable representation.") .def("__len__", &FloatArray::giveSize, "Returns the size of receiver") .def("__getitem__", &FloatArray::__getitem__, "Coefficient access function. Provides 0-based indexing access") @@ -350,68 +351,62 @@ void pyclass_IntArray() *****************************************************/ struct PySparseMtrx : SparseMtrx, wrapper { - PySparseMtrx() : SparseMtrx() {} - PySparseMtrx(int n, int m): SparseMtrx(n,m) {} + PySparseMtrx(int n=0, int m=0): SparseMtrx(n,m) {} - SparseMtrx *GiveCopy() const { - return this->get_override("GiveCopy")(); - } - - void times(const FloatArray &x, FloatArray &answer) const { + void times(const FloatArray &x, FloatArray &answer) const override { this->get_override("times")(); } - void times(double x) { + void times(double x) override { this->get_override("times")(); } - - int buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme& s) { + int buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme& s) override { return this->get_override("buildInternalStructure")(eModel, di, s); } - int buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme& r, const UnknownNumberingScheme &s) { + int buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme& r, const UnknownNumberingScheme &s) override { if (override f = this->get_override("buildInternalStructure")) {return f(eModel, di, r, s);} return this->get_override("buildInternalStructure")(eModel, di, r, s); } - int assemble(const IntArray &loc, const FloatMatrix &mat) { + int assemble(const IntArray &loc, const FloatMatrix &mat) override { return this->get_override("assemble")(); } - int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) { + int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) override { return this->get_override("assemble")(); } - bool canBeFactorized() const { + bool canBeFactorized() const override { return this->get_override("canBeFactorized")(); } - void zero() { + void zero() override { this->get_override("zero")(); } - double &at(int i, int j) { + double &at(int i, int j) override { return this->get_override("at")(); } - double at(int i, int j) const { + double at(int i, int j) const override { return this->get_override("at")(); } - void toFloatMatrix(FloatMatrix &answer) const { + void toFloatMatrix(FloatMatrix &answer) const override { this->get_override("toFloatMatrix")(); } - void printYourself() const { + void printYourself() const override { this->get_override("printYourself")(); } - SparseMtrxType giveType() const { + SparseMtrxType giveType() const override { return this->get_override("giveType")(); } - bool isAsymmetric() const { + bool isAsymmetric() const override { return this->get_override("isAsymmetric")(); } @@ -419,7 +414,7 @@ struct PySparseMtrx : SparseMtrx, wrapper return this->get_override("trans_mult")(); } - const char *giveClassName() const { + const char *giveClassName() const override { return this->get_override("giveClassName")(); } }; @@ -464,7 +459,8 @@ void pyclass_SpatialLocalizer() } -void pyclass_UnknownNumberingScheme(){ +void pyclass_UnknownNumberingScheme() +{ class_("UnknownNumberingScheme",no_init) .def("giveDofEquationNumber",pure_virtual(&UnknownNumberingScheme::giveDofEquationNumber)) .def("giveRequiredNumberOfDomainEquation",&UnknownNumberingScheme::giveRequiredNumberOfDomainEquation) @@ -490,42 +486,42 @@ void pyclass_EngngModelContext() class PyEngngModel : public EngngModel, public wrapper { public: - //PyEngngModel(int i) : EngngModel(i, NULL) {} - PyEngngModel(int i, EngngModel *_master = NULL) : EngngModel(i, _master) {} + //PyEngngModel(int i) : EngngModel(i, nullptr) {} + PyEngngModel(int i, EngngModel *_master = nullptr) : EngngModel(i, _master) {} - void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *atTime) { + void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *atTime) override { this->get_override("printDofOutputAt")(); } - void solveYourself() { + void solveYourself() override { if (override f = this->get_override("solveYourself")) {f();return;} EngngModel::solveYourself(); } - void solveYourselfAt(TimeStep *t) { + void solveYourselfAt(TimeStep *t) override { if (override f = this->get_override("solveYourselfAt")) {f(t); return;} EngngModel::solveYourselfAt(t); } - void terminate(TimeStep *t) { + void terminate(TimeStep *t) override { if (override f = this->get_override("terminate")) {f(t); return;} EngngModel::terminate(t); } - void updateYourself(TimeStep *t) { + void updateYourself(TimeStep *t) override { if (override f = this->get_override("updateYourself")) {f(t); return;} EngngModel::updateYourself(t); } - TimeStep* giveNextStep() { + TimeStep* giveNextStep() override { if (override f = this->get_override("giveNextStep")) {return f();} return this->get_override("giveNextStep")(); } - void default_solveYourself() {return this->EngngModel::solveYourself();} - void default_solveYourselfAt(TimeStep* t) {return this->EngngModel::solveYourselfAt(t);} - void default_terminate(TimeStep* t) {return this->EngngModel::terminate(t);} - void default_updateYourself(TimeStep* t) {return this->EngngModel::updateYourself(t);} - TimeStep* default_giveNextStep() {return this->EngngModel::giveNextStep();} - MetaStep* default_giveMetaStep(int i) {return this->EngngModel::giveMetaStep(i);} + void default_solveYourself() { return this->EngngModel::solveYourself(); } + void default_solveYourselfAt(TimeStep* t) { return this->EngngModel::solveYourselfAt(t); } + void default_terminate(TimeStep* t) { return this->EngngModel::terminate(t); } + void default_updateYourself(TimeStep* t) { return this->EngngModel::updateYourself(t); } + TimeStep* default_giveNextStep() { return this->EngngModel::giveNextStep(); } + MetaStep* default_giveMetaStep(int i) { return this->EngngModel::giveMetaStep(i); } }; void pyclass_EngngModel() @@ -572,9 +568,9 @@ void pyclass_EngngModel() ; } -EngngModel *InstanciateProblem_1 (DataReader *dr, problemMode mode, int contextFlag) +EngngModel *InstanciateProblem_1 (DataReader &dr, problemMode mode, int contextFlag) { - return InstanciateProblem (dr, mode, contextFlag, 0); + return InstanciateProblem(dr, mode, contextFlag).release(); } @@ -599,7 +595,7 @@ class PyExportModule : public ExportModule, public wrapper public: PyExportModule(int i, EngngModel * e) : ExportModule(i, e) {} - void doOutput(TimeStep *tStep, bool forcedOutput=false) { + void doOutput(TimeStep *tStep, bool forcedOutput=false) override { this->get_override("doOutput")(); } @@ -621,17 +617,17 @@ void pyclass_ExportModule() *****************************************************/ struct PyDataReader : DataReader, wrapper { - InputRecord *giveInputRecord(InputRecordType irType, int recordId) + InputRecord &giveInputRecord(InputRecordType irType, int recordId) override { return this->get_override("giveInputRecord")(); } - void finish() { + void finish() override { this->get_override("finish")(); } - const char *giveDataSourceName() const { - return this->get_override("giveDataSourceName")(); + std :: string giveReferenceName() const override { + return this->get_override("giveReferenceName")(); } }; @@ -700,13 +696,13 @@ void pyclass_Domain() .def("resizeInitialConditions", &Domain::resizeInitialConditions) .def("resizeFunctions", &Domain::resizeFunctions) - .def("setDofManager", &Domain::setDofManager) - .def("setElement", &Domain::setElement) - .def("setCrossSection", &Domain::setCrossSection) - .def("setMaterial", &Domain::setMaterial) - .def("setBoundaryCondition", &Domain::setBoundaryCondition) - .def("setInitialCondition", &Domain::setInitialCondition) - .def("setFunction", &Domain::setFunction) + .def("setDofManager", &Domain::py_setDofManager) + .def("setElement", &Domain::py_setElement) + .def("setCrossSection", &Domain::py_setCrossSection) + .def("setMaterial", &Domain::py_setMaterial) + .def("setBoundaryCondition", &Domain::py_setBoundaryCondition) + .def("setInitialCondition", &Domain::py_setInitialCondition) + .def("setFunction", &Domain::py_setFunction) .def("checkConsistency", &Domain::checkConsistency) .def("giveConnectivityTable", &Domain::giveConnectivityTable, return_internal_reference<>()) @@ -757,7 +753,7 @@ class PyDofManager : public DofManager, public wrapper } DofManager::giveUnknownVector(answer, dofMask, mode, stepN); } - bool computeL2GTransformation(FloatMatrix &answer, const IntArray &dofIDArry) { + bool computeL2GTransformation(FloatMatrix &answer, const IntArray &dofIDArry) override { if (override f = this->get_override("computeL2GTransformation")) { return f(answer, dofIDArry); } return DofManager::computeL2GTransformation(answer, dofIDArry); } @@ -766,12 +762,12 @@ class PyDofManager : public DofManager, public wrapper { return this->DofManager::giveUnknownVector(answer, dofMask, mode, stepN, padding); } }; - void (DofManager::*giveUnknownVector_1)(FloatArray &answer, const IntArray &dofMask, ValueModeType mode, TimeStep *stepN, bool padding) = &DofManager::giveUnknownVector; +void (DofManager::*giveUnknownVector_1)(FloatArray &answer, const IntArray &dofMask, ValueModeType mode, TimeStep *stepN, bool padding) = &DofManager::giveUnknownVector; void pyclass_DofManager() { class_, boost::noncopyable>("DofManager", no_init) - .def("hasCoordinates", &DofManager::hasCoordinates) + //.def("hasCoordinates", &DofManager::hasCoordinates) // TODO return type (copy rather than pointer?) .def("giveCoordinates", &DofManager::giveCoordinates, return_internal_reference<>()) .add_property("coordinates", make_function(&DofManager::giveCoordinates, return_internal_reference<>())) @@ -796,22 +792,19 @@ class PyElement : public Element, public wrapper public: PyElement (int n, Domain *d) : Element (n,d) {} - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) { + void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) override { this->get_override("giveCharacteristicMatrix")(); } - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) { + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override { this->get_override("giveCharacteristicVector")(); } - virtual double giveCharacteristicValue(CharType, TimeStep *) { + double giveCharacteristicValue(CharType, TimeStep *) override { return this->get_override("giveCharacteristicValue")(); } - virtual void giveDefaultDofManDofIDMask(int inode, IntArray &answer) const { - this->get_override("giveDefaultDofManDofIDMask")(); - } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const { + void giveDofManDofIDMask(int inode, IntArray &answer) const override { this->get_override("giveDofManDofIDMask")(); } @@ -819,9 +812,6 @@ class PyElement : public Element, public wrapper ValueModeType mode, TimeStep *atTime) { return this->get_override("evaluateAt")(answer, coords,mode,atTime); } - - - }; @@ -896,8 +886,8 @@ void pyclass_Material() struct PyStructuralMaterial : StructuralMaterial , wrapper { PyStructuralMaterial(int i, Domain *d) : StructuralMaterial(i,d) {} - void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) { - if (override f = this->get_override("giveRealStressVector")) { f(answer,gp,reducedStrain,tStep);} + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) override { + if (override f = this->get_override("giveRealStressVector")) { f(answer,gp,reducedStrain,tStep); } this->get_override("giveRealStressVector")(answer,gp,reducedStrain,tStep); } }; @@ -966,7 +956,7 @@ void pyclass_BoundaryCondition() struct PyLoad : Load , wrapper { PyLoad(int i, Domain *d) : Load(i,d) {} - void computeValueAt(FloatArray &answer, TimeStep *tStep, FloatArray &coords, ValueModeType mode) { + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override { if (override f = this->get_override("computeValueAt")) { f(answer,tStep,coords,mode);} this->get_override("computeValueAt")(answer,tStep,coords,mode); } @@ -1070,17 +1060,17 @@ class PyField : public Field, public wrapper public: PyField (FieldType b): Field(b) {} int evaluateAt(FloatArray &answer, FloatArray &coords, - ValueModeType mode, TimeStep *atTime) { + ValueModeType mode, TimeStep *atTime) override { return this->get_override("evaluateAt")(answer, coords,mode,atTime); } int evaluateAt(FloatArray &answer, DofManager* dman, - ValueModeType mode, TimeStep *atTime) { + ValueModeType mode, TimeStep *atTime) override { return this->get_override("evaluateAt")(answer,dman,mode,atTime); } - contextIOResultType saveContext(DataStream &stream, ContextMode mode) { + void saveContext(DataStream &stream, ContextMode mode) override { return this->get_override("saveContext")(stream, mode); } - contextIOResultType restoreContext(DataStream *stream, ContextMode mode) { + void restoreContext(DataStream &stream, ContextMode mode) override { return this->get_override("restoreContext")(stream, mode); } }; @@ -1105,13 +1095,15 @@ FloatArray Field_evaluateAtPos(Field* field, FloatArray& coords, ValueModeType m #endif // raise exception if there is a problem -FloatArray Field_evaluateAtDman(Field* field, DofManager* dman, ValueModeType mode, TimeStep* atTime){ +FloatArray Field_evaluateAtDman(Field* field, DofManager* dman, ValueModeType mode, TimeStep* atTime) +{ FloatArray answer; int err=field->evaluateAt(answer,dman,mode,atTime); if(err) throw std::runtime_error("Error evaluating field at given DofManager."); return answer; } -FloatArray Field_evaluateAtPos(Field* field, FloatArray coords, ValueModeType mode, TimeStep* atTime){ +FloatArray Field_evaluateAtPos(Field* field, FloatArray coords, ValueModeType mode, TimeStep* atTime) +{ FloatArray answer; int err=field->evaluateAt(answer,coords,mode,atTime); if(err) throw std::runtime_error("Error evaluating field at given position."); @@ -1133,7 +1125,7 @@ void pyclass_Field() class_("Field", no_init) .def("evaluateAtPos",Field_evaluateAtPos,(bp::arg("coords"),bp::arg("mode")=VM_Unknown,bp::arg("atTime")=bp::object())) /* - making atTime=py::object() (i.e. NULL) by default leads to crash, look at that better; + making atTime=py::object() (i.e. nullptr) by default leads to crash, look at that better; the default should use the current timestep or anything that is meaningful; mandatory for now */ .def("evaluateAtDman",Field_evaluateAtDman,(bp::arg("dman"),bp::arg("mode"),bp::arg("atTime"))) @@ -1420,11 +1412,13 @@ e.g. in function: */ OOFEMTXTInputRecord makeOOFEMTXTInputRecordFrom(bp::dict &kw) { - bp::dict temp(import("__main__").attr("__dict__")); + //bp::dict temp(import("__main__").attr("__dict__")); + //Python3 + bp::object temp(import("__main__").attr("__dict__")); temp["kw"] = kw; str command = "ret = ''\n" - "for key,val in kw.iteritems():\n" // iterate over key,val pairs + "for key,val in kw.items():\n" // iterate over key,val pairs " if key.lower()=='number' or key.lower()=='domain': continue\n" // do not include "number" and "domain" kws " if key=='f_t': key='f(t)'\n" // handle f(t) loadTimeFunction field name " ret += ' %s'%key\n" // add key @@ -1435,10 +1429,12 @@ OOFEMTXTInputRecord makeOOFEMTXTInputRecordFrom(bp::dict &kw) " for v in val:\n" // and then its values " if isinstance(v,(int,float,str)): ret += ' %s'%v\n" // int, float, str " else: ret += ' %d'%(v.giveNumber())\n" // or any other object, that have giveNumber method (e.g. nodes can be passed to elemnt function as they are, without the need of extracting their numbers first - " else: ret += ' %d'%(val.giveNumber())\n" // add arbitrary object with giveNumber method + " else: ret += ' %d'%(val.giveNumber())\n\n" // add arbitrary object with giveNumber method "ret = ret.lower()\n" // finally make it lower case - "print ret\n" + "print(ret)\n" ; + + //Execute Python commands using boost::python::exec() exec(command,temp,temp); // extract string from globals["ret"], convert it to char* and return OOFEMTXTInputRecord from it //return OOFEMTXTInputRecord( ( extract(temp["ret"])() ).c_str() ); @@ -1484,17 +1480,11 @@ object engngModel(bp::tuple args, bp::dict kw) //args string aClass = extract(args[0])(); int number = len(args)>1? extract(args[1])() : 0; - EngngModel* master = len(args)>2? extract(args[2])() : NULL; - EngngModel *engngm = classFactory.createEngngModel(aClass.c_str(),number,master); - if (engngm==NULL) { OOFEM_LOG_ERROR("engngModel: wrong input data"); } + EngngModel* master = len(args)>2? extract(args[2])() : nullptr; + std::unique_ptr engngm = classFactory.createEngngModel(aClass.c_str(),number,master); + if ( !engngm ) { OOFEM_LOG_ERROR("engngModel: wrong input data"); } OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); - engngm->initializeFrom(&ir); // instanciateYourself - if ( ir.hasField(_IFT_EngngModel_nmsteps) ) { - OOFEM_LOG_ERROR("engngModel: simulation with metasteps is not (yet) supported in Python"); - } else { - engngm->instanciateDefaultMetaStep(&ir); - } ///@todo Output filename isn't stored like this (and has never been!)!? string outFile; if ( ir.hasField("outfile") ) { @@ -1504,9 +1494,17 @@ object engngModel(bp::tuple args, bp::dict kw) } //engngm->Instanciate_init(outFile.c_str(), engngm->giveNumberOfDomains()); engngm->letOutputBaseFileNameBe(outFile); + engngm->initializeFrom(ir); + + if ( ir.hasField(_IFT_EngngModel_nmsteps) ) { + OOFEM_LOG_ERROR("engngModel: simulation with metasteps is not (yet) supported in Python"); + } else { + engngm->instanciateDefaultMetaStep(ir); + } + engngm->Instanciate_init(); // - object ret = object(ptr(engngm)); + object ret = object(ptr(engngm.release())); /* ???????????????????? // sets the last created engngModel as default one for further script temp_global["defaultEngngModel"] = ret; @@ -1531,19 +1529,19 @@ object domain(bp::tuple args, bp::dict kw) // args int number = len(args)>0? extract(args[0])() : 0; int serialNumber = len(args)>1? extract(args[1])() : 0; - EngngModel *engngModel = len(args)>2? extract(args[2])() : NULL; + EngngModel *engngModel = len(args)>2? extract(args[2])() : nullptr; domainType dType = len(args)>3? extract(args[3])() : _unknownMode; - Domain *d = new Domain(number,serialNumber,engngModel); + auto d = std::make_unique(number,serialNumber,engngModel); d->setDomainType(dType); // output manager record OOFEMTXTInputRecord omir = makeOutputManagerOOFEMTXTInputRecordFrom(kw); - d->giveOutputManager()->initializeFrom(&omir); - object ret = object(ptr(d)); + d->giveOutputManager()->initializeFrom(omir); + object ret = object(ptr(d.release())); /* ???????????????????? // sets the last created domain as default one for furtherscript temp_global["defaultDomain"] = ret; ???????????????????? */ - return object(ptr(d)); + return ret; } @@ -1557,28 +1555,28 @@ object element(bp::tuple args, bp::dict kw) string aClass = extract(args[0])(); // extracts values from args if they are specified int number = len(args)>1? extract(args[1])() : 0; - Domain *domain = len(args)>2? extract(args[2])() : NULL; + Domain *domain = len(args)>2? extract(args[2])() : nullptr; /* ???????????????? // if no material is specified, set it to 1 if (!kw.has_key("mat")) { kw["mat"] = 1; } // if no cross section is specified, set it to 1 if (!kw.has_key("crosssect")) { kw["crosssect"] = 1; } // if no domain is specified and one already exists in the script, use that one - if (domain == NULL && temp_global.has_key("defaultDomain")) { domain = extract(temp_global["defaultDomain"])(); } - if (domain==NULL) { LOG_ERROR(oofem_errLogger,"wrong Domain"); } + if (domain == nullptr && temp_global.has_key("defaultDomain")) { domain = extract(temp_global["defaultDomain"])(); } + if (domain==nullptr) { LOG_ERROR(oofem_errLogger,"wrong Domain"); } ???????????????????? */ // create Element (convert aClass to char* - expected by classFactory.createElement) - Element *elem = classFactory.createElement(aClass.c_str(),number,domain); - // if elem==NULL, something was wrong - if (elem==NULL) { OOFEM_LOG_ERROR("element: wrong input data"); } + auto elem = classFactory.createElement(aClass.c_str(),number,domain); + // if elem==nullptr, something was wrong + if (!elem) { OOFEM_LOG_ERROR("element: wrong input data"); } // sets globalNumber == number befor initializeFrom elem->setGlobalNumber(number); // construct OOFEMTXTInputRecord from bp::dict **kw OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); // pass input record to elem - elem->initializeFrom(&ir); + elem->initializeFrom(ir); // convert element to PyObject (expected by raw_function, which enables fun(*args,**kw) syntax in python) - return object(ptr(elem)); + return object(ptr(elem.release())); } // auxiliary constructor for specific element type (name is passed as first argument) @@ -1600,13 +1598,13 @@ object dofManager(bp::tuple args, bp::dict kw) { string aClass = extract(args[0])(); int number = len(args)>1? extract(args[1])() : 0; - Domain *domain = len(args)>2? extract(args[2])() : NULL; - DofManager *dofMan = classFactory.createDofManager(aClass.c_str(),number,domain); - if (dofMan==NULL) { OOFEM_LOG_ERROR("dofManager: wrong input data"); } + Domain *domain = len(args)>2? extract(args[2])() : nullptr; + auto dofMan = classFactory.createDofManager(aClass.c_str(),number,domain); + if (!dofMan) { OOFEM_LOG_ERROR("dofManager: wrong input data"); } dofMan->setGlobalNumber(number); OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); - dofMan->initializeFrom(&ir); - return object(ptr(dofMan)); + dofMan->initializeFrom(ir); + return object(ptr(dofMan.release())); } object createDofManagerOfType(const char* type, bp::tuple args, bp::dict kw) @@ -1625,12 +1623,12 @@ object generalBoundaryCondition(bp::tuple args, bp::dict kw) { string aClass = extract(args[0])(); int number = len(args)>1? extract(args[1])() : 0; - Domain *domain = len(args)>2? extract(args[2])() : NULL; - GeneralBoundaryCondition *bc = classFactory.createBoundaryCondition(aClass.c_str(),number,domain); - if (bc==NULL) { OOFEM_LOG_ERROR("generalBoundaryCondition: wrong input data"); } + Domain *domain = len(args)>2? extract(args[2])() : nullptr; + auto bc = classFactory.createBoundaryCondition(aClass.c_str(),number,domain); + if (!bc) { OOFEM_LOG_ERROR("generalBoundaryCondition: wrong input data"); } OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); - bc->initializeFrom(&ir); - return object(ptr(bc)); + bc->initializeFrom(ir); + return object(ptr(bc.release())); } object CreateBCOfType(const char* type, bp::tuple args, bp::dict kw) @@ -1651,12 +1649,12 @@ object material(bp::tuple args, bp::dict kw) { string aClass = extract(args[0])(); int number = len(args)>1? extract(args[1])() : 0; - Domain *domain = len(args)>2? extract(args[2])() : NULL; - Material *mat = classFactory.createMaterial(aClass.c_str(),number,domain); - if (mat==NULL) { OOFEM_LOG_ERROR("material: wrong input data"); } + Domain *domain = len(args)>2? extract(args[2])() : nullptr; + auto mat = classFactory.createMaterial(aClass.c_str(),number,domain); + if (!mat) { OOFEM_LOG_ERROR("material: wrong input data"); } OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); - mat->initializeFrom(&ir); - return object(ptr(mat)); + mat->initializeFrom(ir); + return object(mat); } object CreateMaterialOfType(const char* type, bp::tuple args, bp::dict kw) @@ -1674,12 +1672,12 @@ object crossSection(bp::tuple args, bp::dict kw) { string aClass = extract(args[0])(); int number = len(args)>1? extract(args[1])() : 0; - Domain *domain = len(args)>2? extract(args[2])() : NULL; - CrossSection *cs = classFactory.createCrossSection(aClass.c_str(),number,domain); - if (cs==NULL) { OOFEM_LOG_ERROR("crossSection: wrong input data"); } + Domain *domain = len(args)>2? extract(args[2])() : nullptr; + auto cs = classFactory.createCrossSection(aClass.c_str(),number,domain); + if (!cs) { OOFEM_LOG_ERROR("crossSection: wrong input data"); } OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); - cs->initializeFrom(&ir); - return object(ptr(cs)); + cs->initializeFrom(ir); + return object(cs); } object CreateCrossSectionOfType(const char* type, bp::tuple args, bp::dict kw) @@ -1698,12 +1696,12 @@ object loadTimeFunction(bp::tuple args, bp::dict kw) { string aClass = extract(args[0])(); int number = len(args)>1? extract(args[1])() : 0; - Domain *domain = len(args)>2? extract(args[2])() : NULL; - Function *ltf = classFactory.createFunction(aClass.c_str(),number,domain); - if (ltf==NULL) { OOFEM_LOG_ERROR("function: wrong input data"); } + Domain *domain = len(args)>2? extract(args[2])() : nullptr; + auto ltf = classFactory.createFunction(aClass.c_str(),number,domain); + if (!ltf) { OOFEM_LOG_ERROR("function: wrong input data"); } OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); - ltf->initializeFrom(&ir); - return object(ptr(ltf)); + ltf->initializeFrom(ir); + return object(ltf); } object CreateLoadTimeFunctionOfType(const char* type, bp::tuple args, bp::dict kw) @@ -1722,12 +1720,12 @@ object exportModule(bp::tuple args, bp::dict kw) { string aClass = extract(args[0])(); int number = len(args)>1? extract(args[1])() : 0; - EngngModel *engngm = len(args)>2? extract(args[2])() : NULL; - ExportModule *module = classFactory.createExportModule(aClass.c_str(),number,engngm); - if (module==NULL) { OOFEM_LOG_ERROR("exportModule: wrong input data"); } + EngngModel *engngm = len(args)>2? extract(args[2])() : nullptr; + auto module = classFactory.createExportModule(aClass.c_str(),number,engngm); + if (!module) { OOFEM_LOG_ERROR("exportModule: wrong input data"); } OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); - module->initializeFrom(&ir); - return object(ptr(module)); + module->initializeFrom(ir); + return object(module); } object CreateExportModuleOfType(const char* type, bp::tuple args, bp::dict kw) @@ -1866,4 +1864,5 @@ BOOST_PYTHON_MODULE (liboofem) def("exportModule", raw_function(exportModule,1)); def("vtkxml", raw_function(vtkxml,0)); } + } // end namespace oofem diff --git a/bindings/python/test-uniformgridfield-plot.py b/bindings/Deprecated/python/test-uniformgridfield-plot.py similarity index 100% rename from bindings/python/test-uniformgridfield-plot.py rename to bindings/Deprecated/python/test-uniformgridfield-plot.py diff --git a/bindings/python/test-uniformgridfield.py b/bindings/Deprecated/python/test-uniformgridfield.py similarity index 94% rename from bindings/python/test-uniformgridfield.py rename to bindings/Deprecated/python/test-uniformgridfield.py index 0a6c79d80..15fa8d0aa 100644 --- a/bindings/python/test-uniformgridfield.py +++ b/bindings/Deprecated/python/test-uniformgridfield.py @@ -11,7 +11,7 @@ #ugrid.setValues([15,15,15,15,15,15,15,15,15]) print (ugrid.evaluateAtPos((0.5,0.2))) -dr = liboofem.OOFEMTXTDataReader("tmpatch05.in") +dr = liboofem.OOFEMTXTDataReader("inputs/tmpatch05.in") transpModel = liboofem.InstanciateProblem(dr,liboofem.problemMode._processor,0) transpModel.checkProblemConsistency() diff --git a/bindings/Deprecated/python/test1.py b/bindings/Deprecated/python/test1.py new file mode 100644 index 000000000..b03004cc3 --- /dev/null +++ b/bindings/Deprecated/python/test1.py @@ -0,0 +1,42 @@ +from __future__ import print_function +import liboofem + +a = liboofem.FloatArray(2) +b = liboofem.FloatArray(4) +ind = liboofem.IntArray(2) + +print("\nTesting vectors, matrices and localization") +a.zero(); +b.zero(); +a[0]=10.0; +a[1]=15.0; +print(a[0], a[1]) +a.printYourself(); + +c = liboofem.FloatArray(a) +print(c[0], c[1]) +c.printYourself() + +d = liboofem.FloatMatrix(2,2) +d.beUnitMatrix() +d[0,1]=1.0 +d.printYourself() + +b.beProductOf(d,a) +b.printYourself() + +b.resize(4) +b.zero() +ind[0]=1 +ind[1]=3 +b.assemble(a,ind) +b.printYourself() + +print("\nSolving inputs/patch100.in") +dr=liboofem.OOFEMTXTDataReader("inputs/patch100.in") +problem=liboofem.InstanciateProblem(dr,liboofem.problemMode._processor,0) +problem.checkProblemConsistency() +problem.setRenumberFlag() +problem.solveYourself() +problem.terminateAnalysis() +print("\nProblem solved") diff --git a/bindings/python/test2.py b/bindings/Deprecated/python/test2.py similarity index 76% rename from bindings/python/test2.py rename to bindings/Deprecated/python/test2.py index 41868465c..931836f34 100644 --- a/bindings/python/test2.py +++ b/bindings/Deprecated/python/test2.py @@ -12,8 +12,9 @@ # domain (if no engngModel specified to domain, it is asigned to the last one created) domain = liboofem.domain(1, 1, problem, liboofem.domainType._2dBeamMode, tstep_all=True, dofman_all=True, element_all=True) problem.setDomain(1, domain, True) +#Current implementation does not read modules, no output is created vtkxmlModule = liboofem.vtkxml(1,problem,tstep_all=True,vars=[1,4],primvars=[1]) - +#domain.giveEngngModel().giveExportModuleManager() # time functions (time functions parameter f(t) has to be written as f_t - due to the parenthesis, otherwise all kw keys match oofem input file ones) # if no domain specified, ltf is asigned to the last one created (valid for all FEMComponents classes) @@ -34,12 +35,12 @@ # nodes # if one value is passed as parameter where oofem expects array of values, it must be passed as tuple or list (see load in n4) -n1 = liboofem.node(1, domain, coords=(0., 0.,0. ), bc=(0,1,0)) -n2 = liboofem.node(2, domain, coords=(2.4,0.,0. ), bc=(0,0,0)) -n3 = liboofem.node(3, domain, coords=(3.8,0.,0. ), bc=(0,0,bc1)) -n4 = liboofem.node(4, domain, coords=(5.8,0.,1.5), bc=(0,0,0), load=(4,)) -n5 = liboofem.node(5, domain, coords=(7.8,0.,3.0), bc=(0,1,0)) -n6 = liboofem.node(6, domain, coords=(2.4,0.,3.0), bc=(bc1,1,bc2)) +n1 = liboofem.node(1, domain, coords=(0., 0., 0. ), bc=(0,1,0)) +n2 = liboofem.node(2, domain, coords=(2.4, 0., 0. ), bc=(0,0,0)) +n3 = liboofem.node(3, domain, coords=(3.8, 0., 0. ), bc=(0,0,bc1)) +n4 = liboofem.node(4, domain, coords=(5.8, 0., 1.5), bc=(0,0,0), load=(4,)) +n5 = liboofem.node(5, domain, coords=(7.8, 0., 3.0), bc=(0,1,0)) +n6 = liboofem.node(6, domain, coords=(2.4, 0., 3.0), bc=(bc1,1,bc2)) nodes = (n1, n2, n3, n4, n5, n6) # material and cross section @@ -57,22 +58,27 @@ # add eveything to domain (resize container first to save some time, but it is not necessary 0 see ltfs) domain.resizeDofManagers(len(nodes)) for n in nodes: - domain.setDofManager(n.number, n) + domain.setDofManager(n.number, n) domain.resizeElements(len(elems)) for e in elems: - domain.setElement(e.number, e) + domain.setElement(e.number, e) +domain.resizeMaterials(1) domain.setMaterial(1, mat) +domain.resizeCrossSectionModels(1) domain.setCrossSection(1, cs) domain.resizeBoundaryConditions(len(bcs)) for bc in bcs: - domain.setBoundaryCondition(bc.number, bc) + domain.setBoundaryCondition(bc.number, bc) +domain.resizeFunctions(len(ltfs)) for ltf in ltfs: - domain.setFunction(ltf.number, ltf) + domain.setFunction(ltf.number, ltf) -problem.checkProblemConsistency(); -problem.init(); -problem.postInitialize(); -problem.setRenumberFlag(); -problem.solveYourself(); -problem.terminateAnalysis(); +print("\nSolving problem") +problem.checkProblemConsistency() +problem.init() +problem.postInitialize() +problem.setRenumberFlag() +problem.solveYourself() +problem.terminateAnalysis() +print("\nProblem solved") diff --git a/bindings/Deprecated/python/test3.py b/bindings/Deprecated/python/test3.py new file mode 100644 index 000000000..549db752d --- /dev/null +++ b/bindings/Deprecated/python/test3.py @@ -0,0 +1,35 @@ +#from __future__ import print_function +import liboofem + +dr=liboofem.OOFEMTXTDataReader("inputs/tmpatch42.in") +problem=liboofem.InstanciateProblem(dr,liboofem.problemMode._processor,0) +problem.checkProblemConsistency() +problem.setRenumberFlag() +problem.solveYourself() +problem.terminateAnalysis() +timeStep=problem.giveCurrentStep() + +t=liboofem.FieldType.FT_Temperature +f=problem.giveField(liboofem.FieldType(t),timeStep) +print("Time:", timeStep.targetTime, "name:", t,"reference:",str(f)) + +print('Number of domains:',problem.giveNumberOfDomains()) +domain=problem.giveDomain(1) +print('Domain', domain) +elem=domain.giveElement(3) +print('Element type',elem.giveGeometryType()) + +f=problem.giveField(liboofem.FieldType(t),timeStep) +print('Field at time',timeStep.targetTime,'type',t, f) + +for d in range(1,domain.giveNumberOfDofManagers()+1): #Nodes + dof=domain.giveDofManager(d) + cc=dof.giveCoordinates() + valueModeType=liboofem.ValueModeType.VM_Total + val=f.evaluateAtDman(dof,mode=valueModeType,atTime=timeStep) + print('DofManager #%d at' % dof.giveNumber(), [cc[i] for i in range(len(cc))], "value", val) + +for el in range(1,domain.giveNumberOfElements()+1): #Elements + elem=domain.giveElement(el) + gt=elem.giveGeometryType() + print('Element %d Nodes' % elem.giveNumber(), [elem.giveDofManager(i+1).giveNumber() for i in range(elem.numberOfDofManagers)]) diff --git a/bindings/oofemlib/README b/bindings/oofemlib/README index 5c9b22004..0371e19d9 100644 --- a/bindings/oofemlib/README +++ b/bindings/oofemlib/README @@ -1,3 +1,17 @@ The sources in this directory illustrate the use of oofemlib from external C/C++ applications. +beam2d_1.C -> 2d beam example (see InputManual, section examples for reference) -beam01.C -> 2d beam example (see InputManual, section examples for reference) +You may try following compilation and linking on Linux machines, demonstrating the concept. The +prerequisite is existent library liboofem.so (in this case located under ../../default) + +Compilation: +g++ -c -I../../src/oofemlib -I../../src -I../../default beam2d_1.C -o beam2d_1.o + +Linking: +g++ beam2d_1.o -L../../default -loofem -o beam2d_1 + +Running (you may need to create a symlink to liboofem.so to current directory): +./beam2d_1 + +Sometimes, it is necessary to specify path to shared library explicitly +export LD_LIBRARY_PATH=. diff --git a/bindings/oofemlib/beam01.C b/bindings/oofemlib/beam2d_1.C similarity index 51% rename from bindings/oofemlib/beam01.C rename to bindings/oofemlib/beam2d_1.C index c5d29d1b2..bfab24553 100644 --- a/bindings/oofemlib/beam01.C +++ b/bindings/oofemlib/beam2d_1.C @@ -4,17 +4,16 @@ #include "intarray.h" #include "floatarray.h" - // Optional (only need the input fields defines) -#include "../sm/EngineeringModels/linearstatic.h" -#include "../sm/CrossSections/simplecrosssection.h" -#include "../sm/Materials/isolinearelasticmaterial.h" -#include "../sm/Elements/Bars/truss2d.h" +#include "sm/EngineeringModels/linearstatic.h" +#include "sm/CrossSections/simplecrosssection.h" +#include "sm/Materials/isolinearelasticmaterial.h" +#include "sm/Elements/Bars/truss2d.h" #include "generalboundarycondition.h" -#include "../sm/Elements/Beams/beam2d.h" +#include "sm/Elements/Beams/beam2d.h" #include "constantedgeload.h" #include "nodalload.h" -#include "../sm/Loads/structtemperatureload.h" +#include "sm/Loads/structtemperatureload.h" #include "peakfunction.h" #include "node.h" #include "outputmanager.h" @@ -25,43 +24,43 @@ using namespace oofem; int main(int argc, char *argv[]) { - DynamicDataReader myData; - DynamicInputRecord *myInput; + DynamicDataReader myData("beam2d_1-anyName"); + std::unique_ptr myInput; //Output File - myData.setOutputFileName("beam01.out"); + myData.setOutputFileName("beam2d_1.out"); //Description myData.setDescription("My custom beam problem"); //Problem - myInput = new DynamicInputRecord(_IFT_LinearStatic_Name); + myInput = std::make_unique(_IFT_LinearStatic_Name); myInput->setField(0, _IFT_EngngModel_lstype); myInput->setField(0, _IFT_EngngModel_smtype); myInput->setField(3, _IFT_EngngModel_nsteps); - myData.insertInputRecord(DataReader::IR_emodelRec, myInput); + myData.insertInputRecord(DataReader::IR_emodelRec, std::move(myInput)); //Domain ///@todo Remove this. - myInput = new DynamicInputRecord(); + myInput = std::make_unique(); std::string help = "2dbeam"; // myInput->setRecordKeywordField("domain", 1); myInput->setField(help, _IFT_Domain_type); - myData.insertInputRecord(DataReader::IR_domainRec, myInput); + myData.insertInputRecord(DataReader::IR_domainRec, std::move(myInput)); //Output ///@todo Make this a normal export module. - myInput = new DynamicInputRecord(); + myInput = std::make_unique(); //myInput->setRecordKeywordField(_IFT_OutputManager_name, 1); myInput->setField(_IFT_OutputManager_Name); myInput->setField(_IFT_OutputManager_tstepall); myInput->setField(_IFT_OutputManager_dofmanall); myInput->setField(_IFT_OutputManager_elementall); - myData.insertInputRecord(DataReader::IR_outManRec, myInput); + myData.insertInputRecord(DataReader::IR_outManRec, std::move(myInput)); //Components size record ///@todo This should probably have "domain 1" in the beginning. Makes sense. - myInput = new DynamicInputRecord(); + myInput = std::make_unique(); myInput->setField(6, _IFT_Domain_ndofman); myInput->setField(5, _IFT_Domain_nelem); myInput->setField(1, _IFT_Domain_ncrosssect); @@ -69,8 +68,8 @@ int main(int argc, char *argv[]) myInput->setField(6, _IFT_Domain_nbc); myInput->setField(0, _IFT_Domain_nic); myInput->setField(3, _IFT_Domain_nfunct); - myInput->setField(4, _IFT_Domain_nset); - myData.insertInputRecord(DataReader::IR_domainCompRec, myInput); + myInput->setField(7, _IFT_Domain_nset); + myData.insertInputRecord(DataReader::IR_domainCompRec, std::move(myInput)); //Nodes myData.insertInputRecord(DataReader::IR_dofmanRec, CreateNodeIR(1, _IFT_Node_Name, {0.0, 0.0, 0.0})); @@ -81,124 +80,143 @@ int main(int argc, char *argv[]) myData.insertInputRecord(DataReader::IR_dofmanRec, CreateNodeIR(6, _IFT_Node_Name, {2.4, 0.0, 3.0})); //Elements - DynamicInputRecord* beam; + std::unique_ptr beam; beam = CreateElementIR(1, _IFT_Beam2d_Name, {1, 2}); - beam->setField(IntArray{3, 1}, _IFT_Element_boundaryload); - beam->setField(IntArray{5}, _IFT_Element_bodyload); - myData.insertInputRecord(DataReader::IR_elemRec, beam); + //beam->setField(IntArray{3, 1}, _IFT_Element_boundaryload);//moved to set + //beam->setField(IntArray{5}, _IFT_Element_bodyload); //moved to set + myData.insertInputRecord(DataReader::IR_elemRec, std::move(beam)); beam = CreateElementIR(2, _IFT_Beam2d_Name, {2, 3}); beam->setField(IntArray{6}, _IFT_Beam2d_dofstocondense); - beam->setField(IntArray{5}, _IFT_Element_bodyload); - myData.insertInputRecord(DataReader::IR_elemRec, beam); + //beam->setField(IntArray{5}, _IFT_Element_bodyload); //moved to set + myData.insertInputRecord(DataReader::IR_elemRec, std::move(beam)); beam = CreateElementIR(3, _IFT_Beam2d_Name, {3, 4}); beam->setField(IntArray{3}, _IFT_Beam2d_dofstocondense); - myData.insertInputRecord(DataReader::IR_elemRec, beam); + myData.insertInputRecord(DataReader::IR_elemRec, std::move(beam)); beam = CreateElementIR(4, _IFT_Beam2d_Name, {4, 5}); - myData.insertInputRecord(DataReader::IR_elemRec, beam); + myData.insertInputRecord(DataReader::IR_elemRec, std::move(beam)); beam = CreateElementIR(5, _IFT_Beam2d_Name, {6, 2}); beam->setField(IntArray{6}, _IFT_Beam2d_dofstocondense); - myData.insertInputRecord(DataReader::IR_elemRec, beam); + myData.insertInputRecord(DataReader::IR_elemRec, std::move(beam)); //CrossSection - myInput = new DynamicInputRecord(_IFT_SimpleCrossSection_Name, 1); + myInput = std::make_unique(_IFT_SimpleCrossSection_Name, 1); myInput->setField(1, _IFT_CrossSection_SetNumber); - myInput->setField(1, _IFT_SimpleCrossSection_MaterialNumber); - myInput->setField(0.162, _IFT_SimpleCrossSection_area); + myInput->setField(1.e+8, _IFT_SimpleCrossSection_area); myInput->setField(0.0039366, _IFT_SimpleCrossSection_iy); myInput->setField(1.e18, _IFT_SimpleCrossSection_shearcoeff); myInput->setField(0.54, _IFT_SimpleCrossSection_thick); - myData.insertInputRecord(DataReader::IR_crosssectRec, myInput); + myInput->setField(1, _IFT_SimpleCrossSection_MaterialNumber); + myInput->setField(1, _IFT_CrossSection_SetNumber); + myData.insertInputRecord(DataReader::IR_crosssectRec, std::move(myInput)); //Material - myInput = new DynamicInputRecord(_IFT_IsotropicLinearElasticMaterial_Name, 1); + myInput = std::make_unique(_IFT_IsotropicLinearElasticMaterial_Name, 1); myInput->setField(1.0, _IFT_Material_density); myInput->setField(30.e6, _IFT_IsotropicLinearElasticMaterial_e); myInput->setField(0.2, _IFT_IsotropicLinearElasticMaterial_n); myInput->setField(1.2e-5, _IFT_IsotropicLinearElasticMaterial_talpha); - myData.insertInputRecord(DataReader::IR_matRec, myInput); + myData.insertInputRecord(DataReader::IR_matRec, std::move(myInput)); //Boundary Conditions - myInput = new DynamicInputRecord(_IFT_BoundaryCondition_Name, 1); + myInput = std::make_unique(_IFT_BoundaryCondition_Name, 1); myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); myInput->setField(FloatArray{0.}, _IFT_BoundaryCondition_values); myInput->setField(IntArray{D_w}, _IFT_GeneralBoundaryCondition_dofs); - myData.insertInputRecord(DataReader::IR_bcRec, myInput); + myInput->setField(4, _IFT_GeneralBoundaryCondition_set); + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_BoundaryCondition_Name, 2); + myInput = std::make_unique(_IFT_BoundaryCondition_Name, 2); myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); myInput->setField(FloatArray{0.}, _IFT_BoundaryCondition_values); myInput->setField(IntArray{R_v}, _IFT_GeneralBoundaryCondition_dofs); - myData.insertInputRecord(DataReader::IR_bcRec, myInput); + myInput->setField(5, _IFT_GeneralBoundaryCondition_set); + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_BoundaryCondition_Name, 6); + myInput = std::make_unique(_IFT_BoundaryCondition_Name, 3); myInput->setField(2, _IFT_GeneralBoundaryCondition_timeFunct); myInput->setField(FloatArray{0., 0., -0.006e-3}, _IFT_BoundaryCondition_values); myInput->setField(IntArray{D_u, D_w, R_v}, _IFT_GeneralBoundaryCondition_dofs); - myInput->setField(4, _IFT_GeneralBoundaryCondition_set); - myData.insertInputRecord(DataReader::IR_bcRec, myInput); - + myInput->setField(6, _IFT_GeneralBoundaryCondition_set); + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); //Loads - myInput = new DynamicInputRecord(_IFT_ConstantEdgeLoad_Name, 3); + myInput = std::make_unique(_IFT_ConstantEdgeLoad_Name, 4); myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); myInput->setField(FloatArray{0.0, 10.0, 0.0}, _IFT_Load_components); myInput->setField(3, _IFT_BoundaryLoad_loadtype); - myData.insertInputRecord(DataReader::IR_bcRec, myInput); + myInput->setField(3, _IFT_GeneralBoundaryCondition_set); + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_NodalLoad_Name, 4); + myInput = std::make_unique(_IFT_NodalLoad_Name, 5); myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); myInput->setField(FloatArray{-18.0, 24.0, 0.0}, _IFT_Load_components); myInput->setField(IntArray{1, 3, 5}, _IFT_GeneralBoundaryCondition_dofs); - myInput->setField(3, _IFT_GeneralBoundaryCondition_set); - myData.insertInputRecord(DataReader::IR_bcRec, myInput); + myInput->setField(2, _IFT_GeneralBoundaryCondition_set); + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_StructuralTemperatureLoad_Name, 5); + myInput = std::make_unique(_IFT_StructuralTemperatureLoad_Name, 6); myInput->setField(3, _IFT_GeneralBoundaryCondition_timeFunct); myInput->setField(FloatArray{30.0, -20.0}, _IFT_Load_components); - myData.insertInputRecord(DataReader::IR_bcRec, myInput); + myInput->setField(7, _IFT_GeneralBoundaryCondition_set); + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); //Functions - myInput = new DynamicInputRecord(_IFT_PeakFunction_Name, 1); + myInput = std::make_unique(_IFT_PeakFunction_Name, 1); myInput->setField(1.0, _IFT_PeakFunction_t); myInput->setField(1.0, _IFT_PeakFunction_ft); - myData.insertInputRecord(DataReader::IR_funcRec, myInput); + myData.insertInputRecord(DataReader::IR_funcRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_PeakFunction_Name, 2); + myInput = std::make_unique(_IFT_PeakFunction_Name, 2); myInput->setField(2.0, _IFT_PeakFunction_t); myInput->setField(1.0, _IFT_PeakFunction_ft); - myData.insertInputRecord(DataReader::IR_funcRec, myInput); + myData.insertInputRecord(DataReader::IR_funcRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_PeakFunction_Name, 3); + myInput = std::make_unique(_IFT_PeakFunction_Name, 3); myInput->setField(3.0, _IFT_PeakFunction_t); myInput->setField(1.0, _IFT_PeakFunction_ft); - myData.insertInputRecord(DataReader::IR_funcRec, myInput); + myData.insertInputRecord(DataReader::IR_funcRec, std::move(myInput)); //Sets - myInput = new DynamicInputRecord(_IFT_Set_Name, 1); + myInput = std::make_unique(_IFT_Set_Name, 1); myInput->setField(IntArray{1, 2, 3, 4, 5}, _IFT_Set_elements); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 2); - myInput->setField(IntArray{1, 5}, _IFT_Set_nodes); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myInput = std::make_unique(_IFT_Set_Name, 2); + myInput->setField(IntArray{1, 4}, _IFT_Set_nodes); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 3); + myInput = std::make_unique(_IFT_Set_Name, 3); + myInput->setField(IntArray{1, 1}, _IFT_Set_elementEdges); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_Set_Name, 4); + myInput->setField(IntArray{1,5}, _IFT_Set_nodes); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_Set_Name, 5); myInput->setField(IntArray{3}, _IFT_Set_nodes); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 4); + myInput = std::make_unique(_IFT_Set_Name, 6); myInput->setField(IntArray{6}, _IFT_Set_nodes); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + myInput = std::make_unique(_IFT_Set_Name, 7); + myInput->setField(IntArray{1,2}, _IFT_Set_elements); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + // Writing to file (to verify, and for backups) - myData.writeToFile("beam01.in"); + myData.writeToFile("beam2d_1.in"); - EngngModel *em = InstanciateProblem(&myData, _processor, 0); - em->solveYourself(); + auto em = InstanciateProblem(myData, _processor, 0); myData.finish(); + em->solveYourself(); + + //example of accessing nodal coordinates + em->giveDomain(1)->giveDofManager(2)->giveCoordinates().printYourself(); } diff --git a/bindings/oofemlib/dream3d_analysis.C b/bindings/oofemlib/dream3d_analysis.C new file mode 100644 index 000000000..f8fdbfb77 --- /dev/null +++ b/bindings/oofemlib/dream3d_analysis.C @@ -0,0 +1,588 @@ +#include "util.h" +#include "dynamicinputrecord.h" +#include "dynamicdatareader.h" +#include "intarray.h" +#include "floatarray.h" +#include "timer.h" + +// Optional (only need the input fields defines) +#include "tm/EngineeringModels/stationarytransportproblem.h" +#include "nrsolver.h" +#include "tm/simpletransportcrosssection.h" +#include "tm/Materials/isoheatmat.h" +#include "tm/Elements/brick1_ht.h" +#include "tm/BoundaryCondition/transportgradientdirichlet.h" +#include "tm/BoundaryCondition/transportgradientneumann.h" +#include "tm/BoundaryCondition/transportgradientperiodic.h" +#include "modulemanager.h" +#include "exportmodule.h" +#include "vtkxmlexportmodule.h" +#include "generalboundarycondition.h" +#include "constantfunction.h" +#include "node.h" +#include "outputmanager.h" +#include "boundarycondition.h" +#include "set.h" + +#include "tm/BoundaryCondition/transportgradientneumann.h" +#include "tm/BoundaryCondition/transportgradientdirichlet.h" +#include "tm/BoundaryCondition/transportgradientperiodic.h" + +#include +#include + +#include + +#ifdef __PETSC_MODULE +#include +#endif + +using namespace oofem; +using namespace H5; + + +class OOFEM_EXPORT BasicInputRecord : public InputRecord +{ +public: + std::unique_ptr clone() const override { return std::unique_ptr(); } + std :: string giveRecordAsString() const override { return ""; } + void giveField(int &answer, InputFieldType id) override { } + void giveField(double &answer, InputFieldType id) override { } + void giveField(bool &answer, InputFieldType id) override { } + void giveField(std :: string &answer, InputFieldType id) override { } + void giveField(FloatArray &answer, InputFieldType id) override { } + void giveField(IntArray &answer, InputFieldType id) override { } + void giveField(FloatMatrix &answer, InputFieldType id) override { } + void giveField(std :: vector< std :: string > &answer, InputFieldType id) override { } + void giveField(Dictionary &answer, InputFieldType id) override { } + void giveField(std :: list< Range > &answer, InputFieldType id) override { } + void giveField(ScalarFunction &function, InputFieldType id) override { } + void printYourself() override {} + void finish(bool wrn = true) override {} +}; + +class OOFEM_EXPORT BasicNodeInputRecord : public BasicInputRecord +{ +protected: + int recordNumber; + FloatArray coords; + +public: + BasicNodeInputRecord(int num, FloatArray coords): recordNumber(num), coords(std::move(coords)) { } + virtual ~BasicNodeInputRecord() {} + + void giveRecordKeywordField(std :: string &answer, int &value) override { answer = "node"; value = recordNumber; } + void giveRecordKeywordField(std :: string &answer) override { answer = "node"; } + void giveField(FloatArray &answer, InputFieldType id) override { + if (std::string(id) == _IFT_Node_coords) answer = coords; + else throw MissingKeywordInputException(this*, id, recordNumber); + } + + bool hasField(InputFieldType id) override { return std::string(id) == _IFT_Node_coords; } +}; + + +class OOFEM_EXPORT BasicElementInputRecord : public BasicInputRecord +{ +protected: + int recordNumber; + IntArray enodes; + +public: + BasicElementInputRecord(int num, IntArray enodes): recordNumber(num), enodes(std::move(enodes)) { } + virtual ~BasicElementInputRecord() {} + + void giveRecordKeywordField(std :: string &answer, int &value) override { answer = _IFT_Brick1_ht_Name; value = recordNumber; } + void giveRecordKeywordField(std :: string &answer) override { answer = _IFT_Brick1_ht_Name; } + void giveField(IntArray &answer, InputFieldType id) override { + if (std::string(id) == _IFT_Element_nodes) answer = enodes; + else throw MissingKeywordInputException(this*, id, recordNumber); + } + + bool hasField(InputFieldType id) override { return std::string(id) == _IFT_Element_nodes; } +}; + + +class OOFEM_EXPORT DeactivatedElementInputRecord : public BasicElementInputRecord +{ +public: + DeactivatedElementInputRecord(int num, IntArray enodes): BasicElementInputRecord(num, enodes) { } + virtual ~DeactivatedElementInputRecord() {} + + virtual void giveField(IntArray &answer, InputFieldType id) { + if (std::string(id) == _IFT_Element_nodes) answer = enodes; + else throw MissingKeywordInputException(this*, id, recordNumber); + } + virtual void giveField(int &answer, InputFieldType id) { + if (std::string(id) == _IFT_Element_activityTimeFunction) answer = 2; + else if (std::string(id) == _IFT_Element_nip) answer = 0; + else throw MissingKeywordInputException(this*, id, recordNumber); + } + virtual bool hasField(InputFieldType id) { return std::string(id) == _IFT_Element_activityTimeFunction || + std::string(id) == _IFT_Element_nip || std::string(id) == _IFT_Element_nodes; } +}; + + + +inline int nC(int nX, int nY, int nZ, const IntArray &n) +{ + return nX + nY*n[0] + nZ*n[1]*n[0]; +} + +FloatArray read_float_dataset(const DataSet &d) +{ + auto dspace = d.getSpace(); + hsize_t dims[2]; + auto rank = dspace.getSimpleExtentDims(dims, nullptr); + if (rank != 1) { OOFEM_ERROR("Dataset is not 1D"); } + FloatArray x((int)dims[0]); + d.read(x.givePointer(), PredType::NATIVE_DOUBLE, dspace); + return x; +} + + +IntArray read_int_dataset(const DataSet &d) +{ + auto dspace = d.getSpace(); + hsize_t dims[2]; + auto rank = dspace.getSimpleExtentDims(dims, nullptr); + if (rank != 1) { OOFEM_ERROR("Dataset is not 1D"); } + IntArray x((int)dims[0]); + d.read(x.givePointer(), PredType::NATIVE_INT, dspace); + return x; +} + + +int main(int argc, char *argv[]) +{ +#ifdef __PARALLEL_MODE + #ifdef __USE_MPI + int rank; + MPI_Init(& argc, & argv); + MPI_Comm_rank(MPI_COMM_WORLD, & rank); + #endif +#endif +#ifdef __PETSC_MODULE + PetscInitialize(& argc, & argv, PETSC_NULL, PETSC_NULL); +#endif + + std :: string filename = argv[1]; + std :: string name = argv[2]; + std :: string bc = argv[3]; + int tangentProblem = atoi(argv[4]); + + printf("Input: %s\n", filename.c_str()); + printf("Ouput basename: %s\n", name.c_str()); + printf("BC type: %s\n", bc.c_str()); + printf("tangent problem: %d\n", tangentProblem); + // elname, w = _Hex21Stokes_Name, 3 + // elname, w = _Q27Space_Name, 3 + // elname, w = _IFT_LSpace_Name, 2 + // elname, w = _IFT_QBrick1_ht_Name, 3 + std :: string elname = _IFT_Brick1_ht_Name; + + std :: unique_ptr< EngngModel > em; + + { + Timer timer; + timer.startTimer(); + DynamicDataReader myData("dream3d_analysis"); + + std::unique_ptr myInput; + myData.setOutputFileName(name + ".out"); + myData.setDescription("Internally generated hex grid from Dream3D file"); + + // Read the file with all inclusions: + H5File file(filename, H5F_ACC_RDONLY ); + Group voxel_data = file.openGroup("DataContainers/VoxelDataContainer"); + Group simpl_geometry = voxel_data.openGroup("_SIMPL_GEOMETRY"); + Group cell_data = voxel_data.openGroup("CellData"); + IntArray nelem = read_int_dataset(simpl_geometry.openDataSet("DIMENSIONS")); + IntArray n = nelem; n.add(1); + FloatArray spacing = read_float_dataset(simpl_geometry.openDataSet("SPACING")); + IntArray phases = read_int_dataset(cell_data.openDataSet("Phases")); + //IntArray grain_ids = read_int_data(cell_data.openDataSet("GrainIds")); + //std::vector< FloatMatrix > euler_angles = read_matrix_data(cell_data.openDataSet("EulerAngles")); + file.close(); + + FloatArray rveSize = {spacing[0]*nelem[0], spacing[1]*nelem[1], spacing[2]*nelem[2]}; + + printf("%s: Number of voxels = %d\n", name.c_str(), nelem[0] * nelem[1] * nelem[2]); + rveSize.printYourself("rve size"); + + //Problem + myInput = std::make_unique(_IFT_StationaryTransportProblem_Name); + myInput->setField(1, _IFT_EngngModel_nsteps); + myInput->setField(1e-6, _IFT_NRSolver_rtolf); + myInput->setField(3, _IFT_EngngModel_lstype); + myInput->setField(7, _IFT_EngngModel_smtype); + myInput->setField(1, _IFT_ModuleManager_nmodules); + myInput->setField(_IFT_EngngModel_suppressOutput); + myInput->setField(_IFT_StationaryTransportProblem_keepTangent); + myData.insertInputRecord(DataReader::IR_emodelRec, std::move(myInput)); + + // VTKXML tstep_all domain_all primvars 1 6 cellvars 3 103 56 41' + myInput = std::make_unique(_IFT_VTKXMLExportModule_Name); + myInput->setField(_IFT_ExportModule_tstepall); + myInput->setField(_IFT_ExportModule_domainall); + myInput->setField(IntArray{6}, _IFT_VTKXMLExportModule_primvars); + myInput->setField(IntArray{103, 56, 41}, _IFT_VTKXMLExportModule_cellvars); + myData.insertInputRecord(DataReader::DataReader::IR_expModuleRec, std::move(myInput)); + + //Domain + ///@todo Remove this. + myInput = std::make_unique(); + std::string help = "3d"; + // myInput->setRecordKeywordField("domain", 1); + myInput->setField(help, _IFT_Domain_type); + myData.insertInputRecord(DataReader::IR_domainRec, std::move(myInput)); + + //Output + ///@todo Remove this. + myInput = std::make_unique(); + //myInput->setRecordKeywordField(_IFT_OutputManager_name, 1); + myInput->setField(_IFT_OutputManager_Name); + myData.insertInputRecord(DataReader::IR_outManRec, std::move(myInput)); + + //Components size record + myInput = std::make_unique(); + myInput->setField(n[0]*n[1]*n[2], _IFT_Domain_ndofman); + myInput->setField(nelem[0]*nelem[1]*nelem[2], _IFT_Domain_nelem); + myInput->setField(2, _IFT_Domain_ncrosssect); + myInput->setField(2, _IFT_Domain_nmat); + myInput->setField(2, _IFT_Domain_nbc); + myInput->setField(0, _IFT_Domain_nic); + myInput->setField(2, _IFT_Domain_nfunct); + myInput->setField(12, _IFT_Domain_nset); + myInput->setField(3, _IFT_Domain_numberOfSpatialDimensions); + myData.insertInputRecord(DataReader::IR_domainCompRec, std::move(myInput)); + + //Nodes + for (int nz = 0; nz < n[2]; ++nz) { + for (int ny = 0; ny < n[1]; ++ny) { + for (int nx = 0; nx < n[0]; ++nx) { + int node = nC(nx, ny, nz, n) + 1; +#if 1 + myData.insertInputRecord(DataReader::IR_dofmanRec, CreateNodeIR(node, _IFT_Node_Name, + {nx * spacing[0] - rveSize[0] * 0.5, + ny * spacing[1] - rveSize[1] * 0.5, + nz * spacing[2] - rveSize[2] * 0.5})); +#else + auto x = std::make_unique(node, + {nx * spacing[0] - rveSize[0] * 0.5, + ny * spacing[1] - rveSize[1] * 0.5, + nz * spacing[2] - rveSize[2] * 0.5}); + + myData.insertInputRecord(DataReader::IR_dofmanRec, std::move(x)); +#endif + } + } + } + + IntArray co_nodes(n[0]*n[1]*n[2]); + + // It would be exceedingly painful to renumber everything based on the WC elements, so lets just deactive them. + // This way, no special considerations are needed in the BC code either. + //Elements + IntArray enode_base = {n[0]*n[1]+n[2], n[0]*n[1]+n[0]+1, n[0]*n[1] + 1, n[1]*n[0], n[0], n[0]+1, 1, 0}; + for (int eZ = 0; eZ < nelem[2]; ++eZ) { + for (int eY = 0; eY < nelem[1]; ++eY) { + for (int eX = 0; eX < nelem[0]; ++eX) { + int e = nC(eX, eY, eZ, nelem) + 1; + //printf("e = %d\n", e); + IntArray enodes = enode_base; + enodes.add(nC(eX, eY, eZ, n) + 1); +#if 1 + auto eir = CreateElementIR(e, elname.c_str(), enodes); + if ( phases.at(e) != 1 ) { // Not Co phase, so lets deactivate + eir->setField(2, _IFT_Element_activityTimeFunction); + } else { + for ( auto node : enodes ) + co_nodes.at(node) = 1; + } + myData.insertInputRecord(DataReader::IR_elemRec, std::move(eir)); +#else + if ( phases.at(e) != 1 ) { // Not Co phase, so lets deactivate + myData.insertInputRecord(DataReader::IR_elemRec, std::make_unique(e, enodes)); + //eir->setField(2, _IFT_Element_activityTimeFunction); + } else { + myData.insertInputRecord(DataReader::IR_elemRec, std::make_unique(e, enodes)); + for ( auto node : enodes ) + co_nodes.at(node) = 1; + } +#endif + } + } + } + + // Special concern for b.c. If Dirichlet, then we must allow the boundary nodes to be free. + // For periodic b.c. then we must mark the master surface (+z,+y,+x side) to Co nodes, as well as free up the slaves (they follow the master anyway). + // Here, only periodic is supported: + // X-Y plane: + for (int ny = 0; ny < n[1]; ++ny) + for (int nx = 0; nx < n[0]; ++nx) + if ( co_nodes[nC(nx, ny, n[2]-1, n)] != 0 ) + co_nodes[nC(nx, ny, 0, n)] = 1; + // X-Z plane: + for (int nz = 0; nz < n[2]; ++nz) + for (int nx = 0; nx < n[0]; ++nx) + if ( co_nodes[nC(nx, n[1]-1, nz, n)] != 0 ) + co_nodes[nC(nx, 0, nz, n)] = 1; + // Y-Z plane: + for (int nz = 0; nz < n[2]; ++nz) + for (int ny = 0; ny < n[1]; ++ny) + if ( co_nodes[nC(n[0]-1, ny, nz, n)] != 0 ) + co_nodes[nC(0, ny, nz, n)] = 1; + + // Free all slaves: + for (int ny = 0; ny < n[1]; ++ny) + for (int nx = 0; nx < n[0]; ++nx) + co_nodes[nC(nx, ny, n[2]-1, n)] = 1; + for (int nz = 0; nz < n[2]; ++nz) + for (int nx = 0; nx < n[0]; ++nx) + co_nodes[nC(nx, n[1]-1, nz, n)] = 1; + for (int nz = 0; nz < n[2]; ++nz) + for (int ny = 0; ny < n[1]; ++ny) + co_nodes[nC(n[0]-1, ny, nz, n)] = 1; + + //Sets + IntArray xp; // x+ + xp.preallocate(2*nelem[2]*nelem[1]); + for (int ez = 0; ez < nelem[2]; ++ez) + for (int ey = 0; ey < nelem[1]; ++ey) + xp.followedBy({nC(nelem[0]-1, ey, ez, nelem)+1, 4}); + + IntArray xm; // x- + xm.preallocate(2*nelem[2]*nelem[1]); + for (int ez = 0; ez < nelem[2]; ++ez) + for (int ey = 0; ey < nelem[1]; ++ey) + xm.followedBy({nC(0, ey, ez, nelem)+1, 6}); + + IntArray yp; // y+ + yp.preallocate(2*nelem[2]*nelem[0]); + for (int ez = 0; ez < nelem[2]; ++ez) + for (int ex = 0; ex < nelem[0]; ++ex) + yp.followedBy({nC(ex, nelem[1]-1, ez, nelem)+1, 3}); + + IntArray ym; // y- + ym.preallocate(2*nelem[2]*nelem[0]); + for (int ez = 0; ez < nelem[2]; ++ez) + for (int ex = 0; ex < nelem[0]; ++ex) + ym.followedBy({nC(ex, 0, ez, nelem)+1, 5}); + + IntArray zp; // z+ + zp.preallocate(2*nelem[1]*nelem[0]); + for (int ey = 0; ey < nelem[1]; ++ey) + for (int ex = 0; ex < nelem[0]; ++ex) + zp.followedBy({nC(ex, ey, nelem[2]-1, nelem)+1, 1}); + + IntArray zm; // z- + zm.preallocate(2*nelem[1]*nelem[0]); + for (int ey = 0; ey < nelem[1]; ++ey) + for (int ex = 0; ex < nelem[0]; ++ex) + zm.followedBy({nC(ex, ey, 0, nelem)+1, 2}); + + myInput = std::make_unique(_IFT_Set_Name, 1); + myInput->setField(xm, _IFT_Set_elementBoundaries); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_Set_Name, 2); + myInput->setField(ym, _IFT_Set_elementBoundaries); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_Set_Name, 3); + myInput->setField(zm, _IFT_Set_elementBoundaries); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_Set_Name, 4); + myInput->setField(xp, _IFT_Set_elementBoundaries); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_Set_Name, 5); + myInput->setField(yp, _IFT_Set_elementBoundaries); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_Set_Name, 6); + myInput->setField(zp, _IFT_Set_elementBoundaries); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + // Set of WC only nodes which gets prescribed as to not cause trouble! + IntArray wc_nodes_index; + co_nodes.add(-1); wc_nodes_index.findNonzeros(co_nodes); + myInput = std::make_unique(_IFT_Set_Name, 7); + myInput->setField(wc_nodes_index, _IFT_Set_nodes); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + IntArray totm, totp, tot; + totm.followedBy(xm); + totm.followedBy(ym); + totm.followedBy(zm); + + totp.followedBy(xp); + totp.followedBy(yp); + totp.followedBy(zp); + + tot.followedBy(totm); + tot.followedBy(totp); + + myInput = std::make_unique(_IFT_Set_Name, 8); + myInput->setField(tot, _IFT_Set_elementBoundaries); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_Set_Name, 9); + myInput->setField(totp, _IFT_Set_elementBoundaries); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_Set_Name, 10); + myInput->setField(totm, _IFT_Set_elementBoundaries); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + IntArray tmp, co_elems, wc_elems; + tmp = phases; tmp.add(-1); wc_elems.findNonzeros(tmp); + tmp = phases; tmp.add(-2); co_elems.findNonzeros(tmp); + + myInput = std::make_unique(_IFT_Set_Name, 11); + myInput->setField(co_elems, _IFT_Set_elements); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_Set_Name, 12); + myInput->setField(wc_elems, _IFT_Set_elements); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_SimpleTransportCrossSection_Name, 1); + myInput->setField(1, _IFT_SimpleTransportCrossSection_material); + myInput->setField(11, _IFT_CrossSection_SetNumber); + myData.insertInputRecord(DataReader::IR_crosssectRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_SimpleTransportCrossSection_Name, 2); + myInput->setField(2, _IFT_SimpleTransportCrossSection_material); + myInput->setField(12, _IFT_CrossSection_SetNumber); + myData.insertInputRecord(DataReader::IR_crosssectRec, std::move(myInput)); + + //Material + myInput = std::make_unique(_IFT_IsotropicHeatTransferMaterial_Name, 1); + myInput->setField(ScalarFunction(1.0), _IFT_IsotropicHeatTransferMaterial_k); + myInput->setField(ScalarFunction(1.0), _IFT_IsotropicHeatTransferMaterial_c); + myInput->setField(1.0, _IFT_Material_density); + myData.insertInputRecord(DataReader::IR_matRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_IsotropicHeatTransferMaterial_Name, 2); + myInput->setField(ScalarFunction(0.0), _IFT_IsotropicHeatTransferMaterial_k); + myInput->setField(ScalarFunction(1.0), _IFT_IsotropicHeatTransferMaterial_c); + myInput->setField(1.0, _IFT_Material_density); + myData.insertInputRecord(DataReader::IR_matRec, std::move(myInput)); + + //Boundary Conditions + if ( bc == "d" or bc == "md" ) { + myInput = std::make_unique(_IFT_TransportGradientDirichlet_Name, 1); + myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); + myInput->setField(IntArray{10}, _IFT_GeneralBoundaryCondition_dofs); + myInput->setField(FloatArray{0., 0., 0.}, _IFT_TransportGradientDirichlet_centerCoords); + myInput->setField(FloatArray{0., 0., 1.}, _IFT_TransportGradientDirichlet_gradient); + myInput->setField(8, _IFT_GeneralBoundaryCondition_set); + if ( bc == "md" ) { + myInput->setField(IntArray{1, 2, 3, 4, 5, 6}, _IFT_TransportGradientDirichlet_surfSets); + myInput->setField(_IFT_TransportGradientDirichlet_tractionControl); + } + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); + } else if ( bc == "n" or bc == "mn" ) { + myInput = std::make_unique(_IFT_TransportGradientNeumann_Name, 1); + myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); + myInput->setField(IntArray{10}, _IFT_GeneralBoundaryCondition_dofs); + myInput->setField(FloatArray{0., 0., 0.}, _IFT_TransportGradientNeumann_centerCoords); + myInput->setField(FloatArray{0., 0., 1.}, _IFT_TransportGradientNeumann_gradient); + + myInput->setField(IntArray{1, 2, 3, 4, 5, 6}, _IFT_TransportGradientNeumann_surfSets); + if ( bc == "mn" ) { + myInput->setField(_IFT_TransportGradientNeumann_dispControl); + } + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); + } else if ( bc == "p" ) { + myInput = std::make_unique(_IFT_TransportGradientPeriodic_Name, 1); + myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); + myInput->setField(IntArray{10}, _IFT_GeneralBoundaryCondition_dofs); + myInput->setField(FloatArray{0., 0., 0.}, _IFT_TransportGradientPeriodic_centerCoords); + myInput->setField(FloatArray{0., 0., 1.}, _IFT_TransportGradientPeriodic_gradient); + + myInput->setField(rveSize, _IFT_TransportGradientPeriodic_jump); + myInput->setField(9, _IFT_GeneralBoundaryCondition_set); + myInput->setField(10, _IFT_TransportGradientPeriodic_masterSet); + + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); + } else { + OOFEM_ERROR("Unrecognized bc type, must be d, md, n, mn, or p"); + } + + // Fixing WC-only nodes + myInput = std::make_unique(_IFT_BoundaryCondition_Name, 2); + myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); + myInput->setField(FloatArray{0.}, _IFT_BoundaryCondition_values); + myInput->setField(IntArray{T_f}, _IFT_GeneralBoundaryCondition_dofs); + myInput->setField(7, _IFT_GeneralBoundaryCondition_set); + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); + + //Functions + myInput = std::make_unique(_IFT_ConstantFunction_Name, 1); + myInput->setField(1.0, _IFT_ConstantFunction_f); + myData.insertInputRecord(DataReader::IR_funcRec, std::move(myInput)); + + myInput = std::make_unique(_IFT_ConstantFunction_Name, 2); + myInput->setField(0.0, _IFT_ConstantFunction_f); + myData.insertInputRecord(DataReader::IR_funcRec, std::move(myInput)); + + timer.stopTimer(); + printf("Mesh generation time %.3f s\n", timer.getWtime()); + // Writing to file (to verify, and for backups) + //myData.writeToFile((name + "_debug.in").c_str()); + + printf("Initializing problem\n"); + timer.startTimer(); + em = InstanciateProblem(myData, _processor, 0); + + myData.finish(); + timer.stopTimer(); + printf("Instanciation time %.3f s\n", timer.getWtime()); + } + + //std::cin.get(); + + Timer timer; + timer.startTimer(); + printf("Starting analysis\n"); + if ( !tangentProblem ) { + em->solveYourself(); + } else { + printf("Solving tangent problem\n"); + TimeStep *tStep = em->giveNextStep(); + FloatMatrix tangent; + if ( dynamic_cast< TransportGradientNeumann* >( em->giveDomain(1)->giveBc(1) ) ) { + dynamic_cast< TransportGradientNeumann* >( em->giveDomain(1)->giveBc(1) )->computeTangent(tangent, tStep); + } else if ( dynamic_cast< TransportGradientDirichlet* >( em->giveDomain(1)->giveBc(1) ) ) { + dynamic_cast< TransportGradientDirichlet* >( em->giveDomain(1)->giveBc(1) )->computeTangent(tangent, tStep); + } else if ( dynamic_cast< TransportGradientPeriodic* >( em->giveDomain(1)->giveBc(1) ) ) { + dynamic_cast< TransportGradientPeriodic* >( em->giveDomain(1)->giveBc(1) )->computeTangent(tangent, tStep); + } + tangent.printYourself("tangent"); + + std :: ofstream fout(em->giveOutputBaseFileName() + ".data", std :: ios :: out); + fout.setf(std::ios::scientific); + fout.precision(6); + for ( int i = 0; i < tangent.giveNumberOfRows(); ++i ) { + for ( int j = 0; j < tangent.giveNumberOfColumns(); ++j ) { + fout << tangent(i, j) << " "; + } + fout << "\n"; + } + fout.close(); + } + + timer.stopTimer(); + printf("Compute time %.3f s\n", timer.getWtime()); + +#ifdef __PETSC_MODULE + PetscFinalize(); +#endif +#ifdef __USE_MPI + MPI_Finalize(); +#endif +} diff --git a/bindings/oofemlib/hexgrid.C b/bindings/oofemlib/hexgrid.C index 8c665c2c9..a388ba87d 100644 --- a/bindings/oofemlib/hexgrid.C +++ b/bindings/oofemlib/hexgrid.C @@ -6,14 +6,14 @@ #include "timer.h" // Optional (only need the input fields defines) -#include "../tm/stationarytransportproblem.h" +#include "tm/EngineeringModels/stationarytransportproblem.h" #include "nrsolver.h" -#include "../tm/simpletransportcrosssection.h" -#include "../tm/isoheatmat.h" -#include "../tm/brick1_ht.h" -#include "../tm/transportgradientdirichlet.h" -#include "../tm/transportgradientneumann.h" -#include "../tm/transportgradientperiodic.h" +#include "tm/simpletransportcrosssection.h" +#include "tm/Materials/isoheatmat.h" +#include "tm/Elements/brick1_ht.h" +#include "tm/BoundaryCondition/transportgradientdirichlet.h" +#include "tm/BoundaryCondition/transportgradientneumann.h" +#include "tm/BoundaryCondition/transportgradientperiodic.h" #include "modulemanager.h" #include "exportmodule.h" #include "vtkxmlexportmodule.h" @@ -24,9 +24,9 @@ #include "boundarycondition.h" #include "set.h" -#include "../tm/transportgradientneumann.h" -#include "../tm/transportgradientdirichlet.h" -#include "../tm/transportgradientperiodic.h" +#include "tm/BoundaryCondition/transportgradientneumann.h" +#include "tm/BoundaryCondition/transportgradientdirichlet.h" +#include "tm/BoundaryCondition/transportgradientperiodic.h" #include #include @@ -86,8 +86,8 @@ int main(int argc, char *argv[]) int tangentProblem = atoi(argv[8]); FloatArray rvePosition; - DynamicDataReader myData; - DynamicInputRecord *myInput; + DynamicDataReader myData("hexgrid"); + std::unique_ptr myInput; // Read the file with all inclusions: std :: ifstream datafile(inclusion_file, std :: ios :: binary); @@ -131,7 +131,7 @@ int main(int argc, char *argv[]) myData.setDescription("Internally generated hex grid"); //Problem - myInput = new DynamicInputRecord(_IFT_StationaryTransportProblem_Name); + myInput = std::make_unique(_IFT_StationaryTransportProblem_Name); myInput->setField(1, _IFT_EngngModel_nsteps); myInput->setField(1e-6, _IFT_NRSolver_rtolf); myInput->setField(3, _IFT_EngngModel_lstype); @@ -139,32 +139,32 @@ int main(int argc, char *argv[]) myInput->setField(1, _IFT_ModuleManager_nmodules); myInput->setField(_IFT_EngngModel_suppressOutput); myInput->setField(_IFT_StationaryTransportProblem_keepTangent); - myData.insertInputRecord(DataReader::IR_emodelRec, myInput); + myData.insertInputRecord(DataReader::IR_emodelRec, std::move(myInput)); // VTKXML tstep_all domain_all primvars 1 6 cellvars 3 103 56 41' - myInput = new DynamicInputRecord(_IFT_VTKXMLExportModule_Name); + myInput = std::make_unique(_IFT_VTKXMLExportModule_Name); myInput->setField(_IFT_ExportModule_tstepall); myInput->setField(_IFT_ExportModule_domainall); myInput->setField(IntArray{6}, _IFT_VTKXMLExportModule_primvars); myInput->setField(IntArray{103, 56, 41}, _IFT_VTKXMLExportModule_cellvars); - myData.insertInputRecord(DataReader::DataReader::IR_expModuleRec, myInput); + myData.insertInputRecord(DataReader::DataReader::IR_expModuleRec, std::move(myInput)); //Domain ///@todo Remove this. - myInput = new DynamicInputRecord(); + myInput = std::make_unique(); std::string help = "3d"; // myInput->setRecordKeywordField("domain", 1); myInput->setField(help, _IFT_Domain_type); - myData.insertInputRecord(DataReader::IR_domainRec, myInput); + myData.insertInputRecord(DataReader::IR_domainRec, std::move(myInput)); //Output - myInput = new DynamicInputRecord(); + myInput = std::make_unique(); //myInput->setRecordKeywordField(_IFT_OutputManager_name, 1); myInput->setField(_IFT_OutputManager_Name); - myData.insertInputRecord(DataReader::IR_outManRec, myInput); + myData.insertInputRecord(DataReader::IR_outManRec, std::move(myInput)); //Components size record - myInput = new DynamicInputRecord(); + myInput = std::make_unique(); myInput->setField(n*n*n, _IFT_Domain_ndofman); myInput->setField(nelem*nelem*nelem, _IFT_Domain_nelem); myInput->setField(2, _IFT_Domain_ncrosssect); @@ -174,7 +174,7 @@ int main(int argc, char *argv[]) myInput->setField(1, _IFT_Domain_nfunct); myInput->setField(12, _IFT_Domain_nset); myInput->setField(3, _IFT_Domain_numberOfSpatialDimensions); - myData.insertInputRecord(DataReader::IR_domainCompRec, myInput); + myData.insertInputRecord(DataReader::IR_domainCompRec, std::move(myInput)); //Nodes for (int nz = 0; nz < n; ++nz) { @@ -303,33 +303,33 @@ int main(int argc, char *argv[]) zm.followedBy({e, 2}); } - myInput = new DynamicInputRecord(_IFT_Set_Name, 1); + myInput = std::make_unique(_IFT_Set_Name, 1); myInput->setField(xm, _IFT_Set_elementBoundaries); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 2); + myInput = std::make_unique(_IFT_Set_Name, 2); myInput->setField(ym, _IFT_Set_elementBoundaries); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 3); + myInput = std::make_unique(_IFT_Set_Name, 3); myInput->setField(zm, _IFT_Set_elementBoundaries); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 4); + myInput = std::make_unique(_IFT_Set_Name, 4); myInput->setField(xp, _IFT_Set_elementBoundaries); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 5); + myInput = std::make_unique(_IFT_Set_Name, 5); myInput->setField(yp, _IFT_Set_elementBoundaries); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 6); + myInput = std::make_unique(_IFT_Set_Name, 6); myInput->setField(zp, _IFT_Set_elementBoundaries); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 7); + myInput = std::make_unique(_IFT_Set_Name, 7); myInput->setField(IntArray{(n*n*n + n*n + n) / 2}, _IFT_Set_nodes); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); IntArray totm, totp, tot; totm.followedBy(xm); @@ -343,17 +343,17 @@ int main(int argc, char *argv[]) tot.followedBy(totm); tot.followedBy(totp); - myInput = new DynamicInputRecord(_IFT_Set_Name, 8); + myInput = std::make_unique(_IFT_Set_Name, 8); myInput->setField(tot, _IFT_Set_elementBoundaries); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 9); + myInput = std::make_unique(_IFT_Set_Name, 9); myInput->setField(totp, _IFT_Set_elementBoundaries); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 10); + myInput = std::make_unique(_IFT_Set_Name, 10); myInput->setField(totm, _IFT_Set_elementBoundaries); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); // Check for inclusions: auto rveInclusions = getInclusionsInBox(rvePosition, rveSize, inclusions); @@ -368,7 +368,7 @@ int main(int argc, char *argv[]) bool found = false; for ( auto &inc : rveInclusions ) - if ( c.distance(inc.first) <= inc.second ) { + if ( distance(c, inc.first) <= inc.second ) { found = true; break; } @@ -379,38 +379,38 @@ int main(int argc, char *argv[]) } printf("Final inclusion fraction: %.3f\n", (double)emat2.giveSize() / (nelem * nelem * nelem)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 11); + myInput = std::make_unique(_IFT_Set_Name, 11); myInput->setField(emat1, _IFT_Set_elements); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_Set_Name, 12); + myInput = std::make_unique(_IFT_Set_Name, 12); myInput->setField(emat2, _IFT_Set_elements); - myData.insertInputRecord(DataReader::IR_setRec, myInput); + myData.insertInputRecord(DataReader::IR_setRec, std::move(myInput)); //CrossSection for ( int i = 1; i <= 2; ++i ) { - myInput = new DynamicInputRecord(_IFT_SimpleTransportCrossSection_Name, i); + myInput = std::make_unique(_IFT_SimpleTransportCrossSection_Name, i); myInput->setField(i, _IFT_SimpleTransportCrossSection_material); myInput->setField(10 + i, _IFT_CrossSection_SetNumber); - myData.insertInputRecord(DataReader::IR_crosssectRec, myInput); + myData.insertInputRecord(DataReader::IR_crosssectRec, std::move(myInput)); } //Material - myInput = new DynamicInputRecord(_IFT_IsotropicHeatTransferMaterial_Name, 1); + myInput = std::make_unique(_IFT_IsotropicHeatTransferMaterial_Name, 1); myInput->setField(1.0, _IFT_IsotropicHeatTransferMaterial_k); myInput->setField(1.0, _IFT_IsotropicHeatTransferMaterial_c); myInput->setField(1.0, _IFT_Material_density); - myData.insertInputRecord(DataReader::IR_matRec, myInput); + myData.insertInputRecord(DataReader::IR_matRec, std::move(myInput)); - myInput = new DynamicInputRecord(_IFT_IsotropicHeatTransferMaterial_Name, 2); + myInput = std::make_unique(_IFT_IsotropicHeatTransferMaterial_Name, 2); myInput->setField(k, _IFT_IsotropicHeatTransferMaterial_k); myInput->setField(1.0, _IFT_IsotropicHeatTransferMaterial_c); myInput->setField(1.0, _IFT_Material_density); - myData.insertInputRecord(DataReader::IR_matRec, myInput); + myData.insertInputRecord(DataReader::IR_matRec, std::move(myInput)); //Boundary Conditions - if ( bc == "d" or bc == "md" ) { - myInput = new DynamicInputRecord(_IFT_TransportGradientDirichlet_Name, 1); + if ( bc == "d" || bc == "md" ) { + myInput = std::make_unique(_IFT_TransportGradientDirichlet_Name, 1); myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); myInput->setField(IntArray{10}, _IFT_GeneralBoundaryCondition_dofs); myInput->setField(FloatArray{0., 0., 0.}, _IFT_TransportGradientDirichlet_centerCoords); @@ -420,9 +420,9 @@ int main(int argc, char *argv[]) myInput->setField(IntArray{1, 2, 3, 4, 5, 6}, _IFT_TransportGradientDirichlet_surfSets); myInput->setField(_IFT_TransportGradientDirichlet_tractionControl); } - myData.insertInputRecord(DataReader::IR_bcRec, myInput); - } else if ( bc == "n" or bc == "mn" ) { - myInput = new DynamicInputRecord(_IFT_TransportGradientNeumann_Name, 1); + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); + } else if ( bc == "n" || bc == "mn" ) { + myInput = std::make_unique(_IFT_TransportGradientNeumann_Name, 1); myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); myInput->setField(IntArray{10}, _IFT_GeneralBoundaryCondition_dofs); myInput->setField(FloatArray{0., 0., 0.}, _IFT_TransportGradientNeumann_centerCoords); @@ -432,9 +432,9 @@ int main(int argc, char *argv[]) if ( bc == "mn" ) { myInput->setField(_IFT_TransportGradientNeumann_dispControl); } - myData.insertInputRecord(DataReader::IR_bcRec, myInput); + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); } else if ( bc == "p" ) { - myInput = new DynamicInputRecord(_IFT_TransportGradientPeriodic_Name, 1); + myInput = std::make_unique(_IFT_TransportGradientPeriodic_Name, 1); myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); myInput->setField(IntArray{10}, _IFT_GeneralBoundaryCondition_dofs); myInput->setField(FloatArray{0., 0., 0.}, _IFT_TransportGradientPeriodic_centerCoords); @@ -444,21 +444,21 @@ int main(int argc, char *argv[]) myInput->setField(9, _IFT_GeneralBoundaryCondition_set); myInput->setField(10, _IFT_TransportGradientPeriodic_masterSet); - myData.insertInputRecord(DataReader::IR_bcRec, myInput); + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); } - myInput = new DynamicInputRecord(_IFT_BoundaryCondition_Name, 2); + myInput = std::make_unique(_IFT_BoundaryCondition_Name, 2); myInput->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); myInput->setField(FloatArray{0.}, _IFT_BoundaryCondition_values); myInput->setField(IntArray{T_f}, _IFT_GeneralBoundaryCondition_dofs); /// @note If the mesh doesn't have a "center" node, then the centerCoords need to be changed to reflect this fixed point! /// Fixing the center point should only be done for Neumann b.c.s, though not actually needed with KSP-solvers. myInput->setField(0, _IFT_GeneralBoundaryCondition_set); - myData.insertInputRecord(DataReader::IR_bcRec, myInput); + myData.insertInputRecord(DataReader::IR_bcRec, std::move(myInput)); //Functions - myInput = new DynamicInputRecord(_IFT_ConstantFunction_Name, 1); + myInput = std::make_unique(_IFT_ConstantFunction_Name, 1); myInput->setField(1.0, _IFT_ConstantFunction_f); - myData.insertInputRecord(DataReader::IR_funcRec, myInput); + myData.insertInputRecord(DataReader::IR_funcRec, std::move(myInput)); timer.stopTimer(); printf("Mesh generation time %.3f s\n", timer.getUtime()); @@ -467,7 +467,7 @@ int main(int argc, char *argv[]) printf("Initializing problem\n"); timer.startTimer(); - EngngModel *em = InstanciateProblem(&myData, _processor, 0); + auto em = InstanciateProblem(myData, _processor, 0); timer.stopTimer(); printf("Instanciation time %.3f s\n", timer.getUtime()); printf("Starting analysis\n"); diff --git a/bindings/python/README.md b/bindings/python/README.md new file mode 100644 index 000000000..c31542308 --- /dev/null +++ b/bindings/python/README.md @@ -0,0 +1,42 @@ +# Welcome to OOFEM Python Bindings + +OOFEM is parallel, object-oriented finite element code for solving mechanical, transport and fluid mechanics problems. + +OOFEM is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. + +Copyright (C) 1993 - 2021 Borek Patzak + + +This directory contains sources to generate OOFEM bindings to Python programming language using Pybind11. +To generate the binding, the pybind11 is required to be installed. Python module pytest is required as well. + +## Prerequisites +``` +pip3 install pybind11 +``` + +Sometimes it happens that running any example raises an error: +expected constructor, destructor, or type conversion before ‘(’ token PYBIND11_MODULE(oofempy, m) { + +In such a case, install pybind11 rather from source: +``` +git clone https://github.com/pybind/pybind11.git; cd pybind11; pip3 install +``` + +For examples, please go to tests or examples subdirectories. + +## Configuration +To build python bindings, one has to configure OOFEM. In particular, +set USE_PYTHON_BINDINGS to ON + + +## Running the tests +``` +export PYTHONPATH=. +python3 -m pytest /path/to/oofem.git/bindings/python/tests +``` + +## Generating documentation +``` +cd oofem.git/bindings/python2/docs; make html +``` \ No newline at end of file diff --git a/bindings/python/docs/Makefile b/bindings/python/docs/Makefile new file mode 100644 index 000000000..d4bb2cbb9 --- /dev/null +++ b/bindings/python/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/bindings/python/docs/advanced/basicclasses.rst b/bindings/python/docs/advanced/basicclasses.rst new file mode 100644 index 000000000..35bc0c672 --- /dev/null +++ b/bindings/python/docs/advanced/basicclasses.rst @@ -0,0 +1,45 @@ +Using OOFEM Classes +################### + +The binding code is generated for all fundamental classes of OOFEM. +This section presents the simple use cases, where selected OOFEM classes are used directly in python code. + +OOFEm comes with built in representation of vectors and matrices. The full feature Python interface is provided in terms of all methods, but also the convenience constructors (from any sequence) and usual operators are provided. + +.. code-block:: pycon + + $ python3 + Python 2.7.10 (default, Aug 22 2015, 20:33:39) + Python 3.6.8 (default, Oct 7 2019, 12:59:55) + [GCC 8.3.0] on linux + Type "help", "copyright", "credits" or "license" for more information. + >>> import oofempy + >>> a = oofempy.FloatArray((1.0, 2.0, 3.0)) + >>> b = oofempy.FloatArray((0.0, -1.0, 1.0)) + >>> c = a+b + >>> print (c) + + >>> c += a + +The following example illustrates how to use FloatMatrix class to solve simple linear system + +.. code-block:: pycon + + $ python3 + >>> import oofempy + >>> A = oofempy.FloatMatrix(3,3) + >>> A.beUnitMtrx() + >>> A[0,1]=-2. + >>> A[1,2]=3 + >>> A.printYourself() + FloatMatrix with dimensions : 3 3 + 1.000e+00 -2.000e+00 0.000e+00 + 0.000e+00 1.000e+00 3.000e+00 + 0.000e+00 0.000e+00 1.000e+00 + >>> b=oofempy.FloatArray((-3, 11, 3)) + >>> x = oofempy.FloatArray(3) + >>> A.solveForRhs(b, x, False) + >>> print (x) + + + diff --git a/bindings/python/docs/advanced/buildingproblem.rst b/bindings/python/docs/advanced/buildingproblem.rst new file mode 100644 index 000000000..a27908448 --- /dev/null +++ b/bindings/python/docs/advanced/buildingproblem.rst @@ -0,0 +1,100 @@ +Creating OOFEM model +#################### + +Creating model from input file +============================== +The problem can be instatiated form a stadard oofem input file, as illustrated form the following example + +.. code-block:: pycon + + $ python3 + Python 2.7.10 (default, Aug 22 2015, 20:33:39) + Python 3.6.8 (default, Oct 7 2019, 12:59:55) + [GCC 8.3.0] on linux + Type "help", "copyright", "credits" or "license" for more information. + >>> import oofempy + >>> dr=oofempy.OOFEMTXTDataReader("patch010.in") + >>> problem=oofempy.InstanciateProblem(dr, oofempy.problemMode.processor, False, None, False) + + +After that, the problem and its components can be manipulated from python3 + +.. code-block:: pycon + + >>> problem.init() + >>> problem.solveYourself() + Computing initial guess + StaticStructural :: solveYourselfAt - Solving step 1, metastep 1, (neq = 3) + NRSolver: Iteration ForceError + ---------------------------------------------------------------------------- + NRSolver: 0 D_u: 0.000e+00 + Checking rules... + EngngModel info: user time consumed by solution step 1: 0.00s + >>> problem.terminateAnalysis() + ANALYSIS FINISHED + Real time consumed: 000h:00m:45s + User time consumed: 000h:00m:00s + +Building model from script +========================== +It is also possible to create individual problem components directly from Python, as illustrated in the following code + +.. code-block:: python3 + + import oofempy + import util # some utility functions + problem = oofempy.linearStatic(nSteps=1, outFile="test2.out") # engngModel + domain = oofempy.domain(1, 1, problem, oofempy.domainType._2dBeamMode, tstep_all=True, dofman_all=True, element_all=True) # domain aka mesh + problem.setDomain(1, domain, True) # associate domain to the problem + + +One can create individual components directly from python. The convenience constructors accepting all keyword-value pairs of component records are provided. + +.. code-block:: python3 + + # load time function + ltf1 = oofempy.peakFunction(1, domain, t=1, f_t=1) + ltfs = (ltf1, ) + # boundary conditions + # loadTimeFunction parameter can be specified as int value or as LoadTimeFunction itself (valid for all objects with giveNumber() method) + bc1 = oofempy.boundaryCondition( 1, domain, loadTimeFunction=1, prescribedValue=0.0) + nLoad = oofempy.nodalLoad( 2, domain, loadTimeFunction=1, components=(-18.,24.,0.)) + bcs = (bc1, nLoad) + +Next we create nodes and other components. See, that reference to other components can be specified by the component number of by passing the object itself. + +.. code-block:: python3 + + # nodes + # if one value is passed as parameter where oofem expects array of values, it must be passed as tuple or list (see load in n4) + n1 = oofempy.node(1, domain, coords=(0., 0., 0. ), bc=(1,1,1)) + n2 = oofempy.node(2, domain, coords=(2.4, 0., 0. ), bc=(0,0,0), load = (nLoad,)) + nodes = (n1, n2) + # material and cross section + mat = oofempy.isoLE(1, domain, d=1., E=30.e6, n=0.2, tAlpha=1.2e-5) + cs = oofempy.simpleCS(1, domain, area=0.162, Iy=0.0039366, beamShearCoeff=1.e18, thick=0.54) + # elements + e1 = oofempy.beam2d(1, domain, nodes=(1,n2), mat=1, crossSect=1) + elems = (e1, ) + # add eveything to domain + util.setupDomain (domain, nodes, elems, (mat,), (cs,), bcs, ltfs, ()) + +After setting up the problem we can solve it. + +.. code-block:: pycon + + >>> print("\nSolving problem") + Solving problem + >>> problem.checkProblemConsistency() + >>> problem.init() + >>> problem.postInitialize() + >>> problem.setRenumberFlag() + >>> problem.solveYourself() + Solving ... + EngngModel info: user time consumed by solution step 1: 0.00s + >>> problem.terminateAnalysis() + ANALYSIS FINISHED + Real time consumed: 000h:00m:00s + User time consumed: 000h:00m:00s + +The more elaborated example can be found in test_2.py (https://github.com/oofem/oofem/blob/master/bindings/python/tests/test_2.py). \ No newline at end of file diff --git a/bindings/python/docs/advanced/customclasses.rst b/bindings/python/docs/advanced/customclasses.rst new file mode 100644 index 000000000..b6d25a1b5 --- /dev/null +++ b/bindings/python/docs/advanced/customclasses.rst @@ -0,0 +1,165 @@ +Extending OOFEM in Python +######################### + +The python interface allows user to define custom derived classes in Python and inject them inside oofem. +We first illustate the concept on defining user defined time function (called MyFunc) in Python. The class should be derived from corresponding oofem base class (Function). +It is necessary to implement at least methods to evaluate the function value (evaluateAtTime) and its derivatives (evaluateVelocityAtTime and evaluateAccelerationAtTime). + +.. code-block:: python3 + + import oofempy + class MyFunc(oofempy.Function): + def __init__(self, num, domain): + oofempy.Function.__init__(self, num, domain) + def evaluateAtTime (self, t): + return 2.5*t + def evaluateVelocityAtTime(self, t): + return 0.0; + def evaluateAccelerationAtTime(self, t): + return 0.0; + +After the definition, we can directly use the MyFunc class in the problem setup: + +.. code-block:: python3 + + problem = oofempy.linearStatic(nSteps=1, outFile="test3.out") + domain = oofempy.domain(1, 1, problem, oofempy.domainType._1dTrussMode, tstep_all=True, dofman_all=True, element_all=True) + problem.setDomain(1, domain, True) + ltf1 = oofempy.peakFunction(1, domain, t=1, f_t=1) + ltf2 = MyFunc(2, domain) # use custom ltf here + ltfs = (ltf1, ltf2) + # boundary conditions + bc1 = oofempy.boundaryCondition( 1, domain, loadTimeFunction=1, prescribedValue=0.0) + n2 = oofempy.nodalLoad( 2, domain, loadTimeFunction=2, components=(1.,), dofs=(1,)) + bcs = (bc1, n2) + #nodes + n1 = oofempy.node(1, domain, coords=(0., 0., 0. ), bc=(bc1,)) + n2 = oofempy.node(2, domain, coords=(2.4, 0., 0. ), load=(n2,)) + nodes = (n1, n2) + # material and cross section + mat = oofempy.isoLE(1, domain, d=1., E=30.e6, n=0.2, tAlpha=1.2e-5) + cs = oofempy.simpleCS(1, domain, area=0.5, Iy=0.0, beamShearCoeff=1.e18, thick=0.5) + # elements + e1 = oofempy.truss1d(1, domain, nodes=(1,n2), mat=1, crossSect=1) + elems = (e1,) + # add eveything to domain (resize container first to save some time, but it is not necessary 0 see ltfs) + domain.setup(nodes, elems, (mat,), (cs,), bcs, ltfs, (,)) + + problem.checkProblemConsistency() + problem.init() + problem.postInitialize() + problem.solveYourself() + problem.terminateAnalysis() + print("\nProblem solved") + +Follow https://github.com/oofem/oofem/blob/master/bindings/python/tests/test_3.py for a full example. + +Custom element +-------------- +This section illustrates how to implement custom element in Python. In this case, we are implementing element for structural analysis, so it should be derived from cooresponding oofem base class, which is StructuralElement in this case. +There are various options how to implement an element. The simplest option is to directly define how to evaluate element stifness matrix and internal force vector. Additional functuos to determine degrees of freedom required by the element anre also to be provided. +Other possibilities exists, for example one can rely on default implementation of StructuralElement to evalaute stifness matrix, but then methods delivering strain-displacement and constituve matrix have to be provided together with element integration rules. For details, please consult oofem manuals. + +.. code-block:: python3 + + import oofempy + class MyElement(oofempy.StructuralElement): + def __init__(self, num, domain): + oofempy.StructuralElement.__init__(self, num, domain) + self.setNumberOfDofManagers(2) + def computeStiffnessMatrix(self, answer, rMode, tStep): + answer.resize(2,2); + answer[0,0] = 1.0; + answer[0,1] = -1.0; + answer[1,0] = 1.0; + answer[1,1] = -1.0; + def computeBmatrixAt(self, gp, answer, lowerIndx, upperIndx): + answer.resize(1,2); + answer[0,0]=-1.0; + answer[0,1]=1.0; + def giveInternalForcesVector(self, answer, tStep, useUpdatedGpRecord): + u = oofempy.FloatArray() + k = oofempy.FloatMatrix(2,2) + self.computeVectorOf(oofempy.ValueModeType.VM_Total, tStep, u) + self.computeStiffnessMatrix(k, oofempy.CharType.StiffnessMatrix, tStep) + answer.beProductOf (k, u) + def giveNumberOfDofs(self): + return 2; + def computeNumberOfDofs(self): + return 2; + def giveDofManDofIDMask(self, inode, answer): + print ("giveDofManDofIDMask for %d"%(inode,)) + print (answer) + answer.resize(1) + answer[0] = oofempy.DofIDItem.D_u + #answer.pY() + print(answer) + def giveClassName(self): + return "MyElement" + def giveInputRecordName(self): + return "MyElement" + +The element can again added into domain and used from oofem + +.. code-block:: python3 + + # nodes + n1 = oofempy.node(1, domain, coords=(0., 0., 0. ), bc=(bc1,)) + n2 = oofempy.node(2, domain, coords=(2.4, 0., 0. ), load=(n2,)) + nodes = (n1, n2) + # elements + e1 = MyElement(1, domain) # additinal entries should go to to the custom element constructor + e1.setDofManagers((1,2)) + ir = oofempy.OOFEMTXTInputRecord() + ir.setRecordString ("nodes 2 1 2 mat 1 crosssect 1") + # pass input record to elem + e1.initializeFrom(ir) + elems = (e1,) + ... + +You can follow https://github.com/oofem/oofem/blob/master/bindings/python/tests/test_3.py for a complete illustration. + +Custom material +--------------- +This section illustrates how to implement custom constitutive model in Python. +First we have to define Python class implementing the model derived from corresponding oofem class. In this case, we are going to implement constututive model for structural analysis, so we derive our class from StructuralMaterial. +The presented implementation is mininimalistic one, we overload or define just methods to support 1d stress strain state, by overriding give1dStiffnessMatrix and giveRealStressVector_1d methods, that simply returns constitutive matrix and evaluate 1d stress from given strain. The more elaborate implementation would be necessary to support sevaral stress-strain modes, nonlinear materials (need to create custom status to track history variables). For more details, please refer to oofem programmer's manual. +Each matteril model must define its material status contatining its internal state variables. Even if material models does not need to track internal variables, it should provide status. In such case, it is sufficient to create instance of StructuralMaterialStatus. In oofem, the method responsible for status creation is CreateStatus, that would normally be overriden in Python as well. However, doe to the issue in Pybind11 (https://github.com/pybind/pybind11/issues/1962) this is not yet possible. The workaroud is to override giveStatus, as illustrate in the following example. + +.. code-block:: python3 + + class MyMaterial(oofempy.StructuralMaterial): + def __init__(self, num, domain): + oofempy.StructuralMaterial.__init__(self, num, domain) + self.k = 1.5; + def giveClassName(self): + return "MyMaterial" + def giveInputRecordName(self): + return "MyElement" + # Overloading this method is not yet possible in pybind11 + # see https://github.com/pybind/pybind11/issues/1962 + # However a workaround is to override giveStatus, see below + def CreateStatus(self, gp): + return oofempy.StructuralMaterialStatus (gp) + def give1dStressStiffMtrx(self, answer, mode, gp, tStep): + answer.resize(1,1) + answer[0,0] = self.k + return + def giveRealStressVector_1d (self, answer, gp, reducedStrain, tStep): + answer.resize(1) + answer[0] = self.k * reducedStrain[0] + status = self.giveStatus(gp) + status.letTempStrainVectorBe(reducedStrain); + status.letTempStressVectorBe(answer); + return + def giveStatus (self, gp): + print ("getStatus") + if (gp.giveMaterialStatus() is None): + print ("getStatus creating") + status = oofempy.StructuralMaterialStatus (gp) + gp.setMaterialStatus(status) + return gp.giveMaterialStatus() + + +You can follow https://github.com/oofem/oofem/blob/master/bindings/python/tests/test_4.py for a complete illustration. + diff --git a/bindings/python/docs/basics.rst b/bindings/python/docs/basics.rst new file mode 100644 index 000000000..ab437f7ec --- /dev/null +++ b/bindings/python/docs/basics.rst @@ -0,0 +1,70 @@ + +First Steps +########### + +This section covers the basic usage of oofem python bindings. +It covers the installation, consisting of generating the python bindings and demonstrates the basic usage. + +Installation +============ + +Prerequisities +-------------- +The python bindings require pybind11 (https://pybind11.readthedocs.io/en/stable/). Pybind11 requires **python-dev** or **python3-dev** packages as +well as **cmake**. The recommended procedure to install pybind11 is to clone pybind11 github repository + +.. code-block:: bash + + git clone https://github.com/pybind/pybind11.git + cd pybind11 + mkdir build + cd build + cmake .. + make check -j 4 + make install + +Generate binding code +--------------------- +Configure oofem target to build python bindings + +.. code-block:: bash + + cd oofem.build + cmake path_to_oofem_git_repository -D USE_PYTHON_BINDINGS=ON + make + +Building the above project will produce a binary module file that can be imported to Python. + +Basic usage +=========== +In the previous section we have built the oofem python module. Assuming that the compiled module is located in the +current directory, the following interactive Python session shows how to +load and execute the example: + +.. code-block:: pycon + + $ python3 + Python 2.7.10 (default, Aug 22 2015, 20:33:39) + Python 3.6.8 (default, Oct 7 2019, 12:59:55) + [GCC 8.3.0] on linux + Type "help", "copyright", "credits" or "license" for more information. + >>> import oofempy + >>> dr=oofempy.OOFEMTXTDataReader("patch010.in") + >>> problem=oofempy.InstanciateProblem(dr, oofempy.problemMode.processor, False, None, False) + >>> problem.init() + >>> problem.solveYourself() + Computing initial guess + StaticStructural :: solveYourselfAt - Solving step 1, metastep 1, (neq = 3) + NRSolver: Iteration ForceError + ---------------------------------------------------------------------------- + NRSolver: 0 D_u: 0.000e+00 + Checking rules... + EngngModel info: user time consumed by solution step 1: 0.00s + >>> problem.terminateAnalysis() + ANALYSIS FINISHED + Real time consumed: 000h:00m:45s + User time consumed: 000h:00m:00s + + + + diff --git a/bindings/python/docs/conf.py b/bindings/python/docs/conf.py new file mode 100644 index 000000000..e1baa458c --- /dev/null +++ b/bindings/python/docs/conf.py @@ -0,0 +1,57 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- 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 sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'OOFEM Python bindings' +copyright = '2019, BoÅ™ek Patzák' +author = 'BoÅ™ek Patzák' + +# The full version, including alpha/beta/rc tags +release = '1.0' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# 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 = ['_build', 'Thumbs.db', '.DS_Store'] + + +# -- 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 = 'classic' + +# 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'] + +master_doc = 'index' \ No newline at end of file diff --git a/bindings/python/docs/index.rst b/bindings/python/docs/index.rst new file mode 100644 index 000000000..421b50540 --- /dev/null +++ b/bindings/python/docs/index.rst @@ -0,0 +1,26 @@ +.. OOFEM Python bindings documentation master file, created by + sphinx-quickstart on Wed Oct 16 08:56:19 2019. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to OOFEM Python bindings documentation! +================================================= + +.. toctree:: + :caption: Content + :maxdepth: 2 + + basics + + advanced/basicclasses + advanced/buildingproblem + advanced/customclasses + + postprocessing + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/bindings/python/docs/make.bat b/bindings/python/docs/make.bat new file mode 100644 index 000000000..2119f5109 --- /dev/null +++ b/bindings/python/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/bindings/python/docs/postprocessing.rst b/bindings/python/docs/postprocessing.rst new file mode 100644 index 000000000..50ff46093 --- /dev/null +++ b/bindings/python/docs/postprocessing.rst @@ -0,0 +1,83 @@ + +Postprocessing +############## + +This section covers the basic postprocessing when using oofem python bindings. + +One can always directly access results using oofem API after solving each solution step. +Another option consist of using existing or developing custom export module. +OOFEM comes with many built-in export modules to produce output in desired format. + +In the following sections, we will cover some techniques in more detail. + +VTK postprocessing +================== +This section illustrates how to query the data from oofem in python and use vtk library to visualize the results. + +Prerequisites +-------------- +Here we will use pyvista python module (https://pyvista-doc.readthedocs.io/en/latest/) to interface with Visualization toolkit (VTK). +The recommended procedure to install pyvista is to use python package installer: + +.. code-block:: bash + + pip install pyvista + +The approach uses built-in vtkmemory export module. This module allows in memory pythonic access to oofem grid data and variables. +First, we use existing model. The model is read from input file and solved: + +.. code-block:: python3 + + import oofempy + import numpy as np + import pyvista as pv + + dr=oofempy.OOFEMTXTDataReader("concrete_3point.in") + problem=oofempy.InstanciateProblem(dr, oofempy.problemMode.processor, False, None, False) + problem.init() + problem.solveYourself() + +Next, we create instance of oofem vtkmemory export module and associate it to our problem. +The constructor allows to filter the output to specific solution steps +(here we use ``tstep_all=True`` to match all solution steps) and allows to select variables to export +(we request dipslacement vector as primary variables, stress and strain tensors as internal +variables and element number as cell variables, see oofem Input manual for details). + +Further, the module is initialized and output is prepared. + +.. code-block:: python3 + + vtkxmlPy = oofempy.vtkmemory(1, problem, domain_all=True, tstep_all=True, dofman_all=True, element_all=True, vars=(1,4), primvars=(1,), cellvars = (47,), stype=1, pythonExport=1) + vtkxmlPy.initialize() + vtkxmlPy.doOutput(problem.giveCurrentStep(), False) + +The vtkmemory module allows in memory access to so called VTKPieces, objects representing piece (subset of mesh) to visualize. +VTKPieces contain all needed information and data about piece geometry, connectivity and about exported variables. +We start looping over the pieces, request data needed to instanciate pyvista UnstructuredGrid instance and +attach exported variables to it. + +.. code-block:: python3 + + for p in vtkxmlPy.getVTKPieces(): + #p = vtkxmlPy.getVTKPieces()[0] + print ("Piece:", p) + print(p.getVertices()) + print(p.getCellConnectivity()) + print(p.getCellTypes(vtkxmlPy)) + disp = p.getPrimaryVertexValues(oofempy.UnknownType.DisplacementVector) + sig = p.getInternalVertexValues(oofempy.InternalStateType.IST_StressTensor) + sigx = sig[:, 0] + + grid = pv.UnstructuredGrid(p.getCellConnectivity(), p.getCellTypes(vtkxmlPy), p.getVertices()) + grid.point_arrays['Sigma_xx'] = sigx + grid['Disp'] = disp + print(grid.active_vectors) + warped = grid.warp_by_vector('Disp', factor=1000.) + p = pv.Plotter() + p.add_mesh(warped, scalars='Sigma_xx') + p.add_mesh(grid, style='wireframe', color='black') + p.set_viewup((0,1,0)) + p.show() + problem.terminateAnalysis() + +You can follow https://github.com/oofem/oofem/blob/master/bindings/python/examples/vtkdemo.py for a full example. \ No newline at end of file diff --git a/bindings/python/examples/concrete_3point.in b/bindings/python/examples/concrete_3point.in new file mode 100644 index 000000000..dfb6c4993 --- /dev/null +++ b/bindings/python/examples/concrete_3point.in @@ -0,0 +1,1346 @@ +concrete_3point.out +Test: 3-point bending, triangular elements, 1 loaded point +StaticStructural nsteps 4 solverType "calm" stepLength 0.025 rtolf 1e-4 Psi 0.0 MaxIter 200 reqIterations 80 HPC 2 1 2 stiffmode 1 nmodules 1 +errorcheck +domain 2dPlaneStress +# +# zkracena verze vypoctu z me disertace +# +#Monitored 2 +#1 node 1 displacement 2 * +#2 node 1 force 2 * +#** +# +OutputManager tstep_all dofman_all element_all +ndofman 444 nelem 799 ncrosssect 2 nmat 2 nbc 3 nic 0 nltf 1 nset 5 +node 1 coords 2 1000.000000 500.000000 +node 2 coords 2 900.000000 0.000000 +node 3 coords 2 850.755859 0.000000 +node 4 coords 2 796.661743 0.000000 +node 5 coords 2 736.054993 0.000000 +node 6 coords 2 667.393921 0.000000 +node 7 coords 2 589.319580 0.000000 +node 8 coords 2 500.725708 0.000000 +node 9 coords 2 400.839996 0.000000 +node 10 coords 2 289.309998 0.000000 +node 11 coords 2 166.261612 0.000000 +node 12 coords 2 0.000000 0.000000 +node 13 coords 2 900.000000 500.000000 +node 14 coords 2 900.000000 475.552399 +node 15 coords 2 900.000000 451.711365 +node 16 coords 2 900.000000 428.109802 +node 17 coords 2 900.000000 404.331390 +node 18 coords 2 900.000000 380.010651 +node 19 coords 2 900.000000 354.926605 +node 20 coords 2 900.000000 329.090668 +node 21 coords 2 900.000000 302.784180 +node 22 coords 2 900.000000 276.469330 +node 23 coords 2 900.000000 250.563370 +node 24 coords 2 900.000000 225.213165 +node 25 coords 2 900.000000 200.219864 +node 26 coords 2 900.000000 175.101700 +node 27 coords 2 900.000000 149.182297 +node 28 coords 2 900.000000 121.635910 +node 29 coords 2 900.000000 91.484993 +node 30 coords 2 900.000000 57.568787 +node 31 coords 2 875.552429 500.000000 +node 32 coords 2 848.563599 500.000000 +node 33 coords 2 818.458130 500.000000 +node 34 coords 2 784.570496 500.000000 +node 35 coords 2 746.113525 500.000000 +node 36 coords 2 702.149414 500.000000 +node 37 coords 2 651.572083 500.000000 +node 38 coords 2 593.115417 500.000000 +node 39 coords 2 525.405273 500.000000 +node 40 coords 2 447.074524 500.000000 +node 41 coords 2 356.944366 500.000000 +node 42 coords 2 254.240860 500.000000 +node 43 coords 2 138.775726 500.000000 +node 44 coords 2 0.000000 500.000000 +node 45 coords 2 0.000000 360.076019 +node 46 coords 2 0.000000 219.966446 +node 47 coords 2 0.000000 109.983208 +node 48 coords 2 878.935547 473.539581 +node 49 coords 2 879.723022 443.877136 +node 50 coords 2 881.672485 419.235260 +node 51 coords 2 881.968079 392.962646 +node 52 coords 2 882.365784 368.033539 +node 53 coords 2 877.727966 236.751816 +node 54 coords 2 878.186951 215.276642 +node 55 coords 2 874.857788 189.177475 +node 56 coords 2 880.654297 343.041534 +node 57 coords 2 876.252563 317.506744 +node 58 coords 2 872.579651 289.776947 +node 59 coords 2 873.226990 263.396057 +node 60 coords 2 877.151672 162.014923 +node 61 coords 2 848.464172 470.395142 +node 62 coords 2 848.601562 440.401703 +node 63 coords 2 875.659790 137.510849 +node 64 coords 2 848.940186 411.388306 +node 65 coords 2 848.531494 383.558624 +node 66 coords 2 848.861389 204.232742 +node 67 coords 2 848.091736 227.235229 +node 68 coords 2 847.064941 356.830475 +node 69 coords 2 846.441711 250.595291 +node 70 coords 2 846.571838 178.505997 +node 71 coords 2 844.655884 329.850952 +node 72 coords 2 842.540283 301.936462 +node 73 coords 2 843.256592 275.166138 +node 74 coords 2 816.255310 468.365448 +node 75 coords 2 816.262451 435.483826 +node 76 coords 2 872.458435 101.911865 +node 77 coords 2 842.928711 153.343430 +node 78 coords 2 816.013123 403.608765 +node 79 coords 2 813.471558 374.514862 +node 80 coords 2 818.597961 216.517319 +node 81 coords 2 821.992676 237.732895 +node 82 coords 2 834.844788 120.387291 +node 83 coords 2 821.167969 193.690567 +node 84 coords 2 810.729187 345.419067 +node 85 coords 2 816.604797 259.828278 +node 86 coords 2 806.842957 168.979385 +node 87 coords 2 809.296021 314.220154 +node 88 coords 2 809.550354 282.029755 +node 89 coords 2 780.887268 468.643555 +node 90 coords 2 785.898254 429.370361 +node 91 coords 2 868.350830 61.739170 +node 92 coords 2 780.995239 398.208496 +node 93 coords 2 775.076355 368.068146 +node 94 coords 2 825.469543 83.332481 +node 95 coords 2 802.078735 141.094971 +node 96 coords 2 787.066162 194.222366 +node 97 coords 2 790.452942 226.194199 +node 98 coords 2 800.622681 245.997971 +node 99 coords 2 773.470825 331.750275 +node 100 coords 2 781.631470 253.296783 +node 101 coords 2 775.877136 290.544647 +node 102 coords 2 747.559753 461.154175 +node 103 coords 2 778.143799 103.791527 +node 104 coords 2 761.883972 148.253647 +node 105 coords 2 746.057556 429.100983 +node 106 coords 2 735.982788 404.722595 +node 107 coords 2 735.116577 359.037048 +node 108 coords 2 757.724792 208.741913 +node 109 coords 2 736.450439 310.305573 +node 110 coords 2 745.335266 258.583069 +node 111 coords 2 706.334167 453.328369 +node 112 coords 2 695.904480 401.934631 +node 113 coords 2 826.071960 35.569450 +node 114 coords 2 696.396362 335.902557 +node 115 coords 2 696.605164 278.509155 +node 116 coords 2 772.449646 54.619114 +node 117 coords 2 656.613525 369.914612 +node 118 coords 2 647.650024 302.002625 +node 119 coords 2 710.163330 221.670105 +node 120 coords 2 723.195557 78.650360 +node 121 coords 2 644.417419 433.159637 +node 122 coords 2 603.972534 353.860321 +node 123 coords 2 721.421997 153.109589 +node 124 coords 2 646.269104 233.199844 +node 125 coords 2 663.017700 177.478485 +node 126 coords 2 666.024109 118.539635 +node 127 coords 2 588.308105 257.428131 +node 128 coords 2 593.009644 159.887482 +node 129 coords 2 565.205383 418.769379 +node 130 coords 2 610.272583 70.090065 +node 131 coords 2 521.244751 320.242615 +node 132 coords 2 673.864868 59.946304 +node 133 coords 2 471.461456 402.520386 +node 134 coords 2 512.435486 85.804222 +node 135 coords 2 508.782654 205.401779 +node 136 coords 2 367.033264 420.028564 +node 137 coords 2 414.052185 296.122314 +node 138 coords 2 417.513306 142.334641 +node 139 coords 2 300.743744 220.636261 +node 140 coords 2 308.723083 96.996696 +node 141 coords 2 303.593323 367.699310 +node 142 coords 2 166.868607 151.789566 +node 143 coords 2 203.365555 422.039856 +node 144 coords 2 213.101395 270.257965 +node 145 coords 2 118.057777 319.183533 +node 146 coords 2 987.500000 0.000000 +node 147 coords 2 943.750000 0.000000 +node 148 coords 2 987.500000 200.000000 +node 149 coords 2 987.500000 181.928055 +node 150 coords 2 987.500000 163.477005 +node 151 coords 2 987.500000 144.086121 +node 152 coords 2 987.500000 123.124710 +node 153 coords 2 987.500000 99.854897 +node 154 coords 2 987.500000 73.386528 +node 155 coords 2 987.500000 42.629635 +node 156 coords 2 1012.500000 200.000000 +node 157 coords 2 1012.500000 181.928055 +node 158 coords 2 1012.500000 163.477005 +node 159 coords 2 1012.500000 144.086121 +node 160 coords 2 1012.500000 123.124710 +node 161 coords 2 1012.500000 99.854897 +node 162 coords 2 1012.500000 73.386528 +node 163 coords 2 1012.500000 42.629635 +node 164 coords 2 1012.500000 0.000000 +node 165 coords 2 1056.250000 0.000000 +node 166 coords 2 1100.000000 0.000000 +node 167 coords 2 1100.000000 500.000000 +node 168 coords 2 1100.000000 475.552399 +node 169 coords 2 1100.000000 451.711365 +node 170 coords 2 1100.000000 428.109802 +node 171 coords 2 1100.000000 404.331390 +node 172 coords 2 1100.000000 380.010651 +node 173 coords 2 1100.000000 354.926605 +node 174 coords 2 1100.000000 329.090668 +node 175 coords 2 1100.000000 302.784180 +node 176 coords 2 1100.000000 276.469330 +node 177 coords 2 1100.000000 250.563370 +node 178 coords 2 1100.000000 225.213165 +node 179 coords 2 1100.000000 200.219864 +node 180 coords 2 1100.000000 175.101700 +node 181 coords 2 1100.000000 149.182297 +node 182 coords 2 1100.000000 121.635910 +node 183 coords 2 1100.000000 91.484993 +node 184 coords 2 1100.000000 57.568787 +node 185 coords 2 1082.176392 500.000000 +node 186 coords 2 1064.352661 500.000000 +node 187 coords 2 1044.223633 500.000000 +node 188 coords 2 1024.911743 500.000000 +node 189 coords 2 986.941711 500.000000 +node 190 coords 2 967.353149 500.000000 +node 191 coords 2 946.701721 500.000000 +node 192 coords 2 924.447632 500.000000 +node 193 coords 2 995.226074 485.178650 +node 194 coords 2 1012.406921 487.741211 +node 195 coords 2 1010.528259 472.557617 +node 196 coords 2 977.630188 483.531677 +node 197 coords 2 1032.321899 481.204865 +node 198 coords 2 967.473938 195.405930 +node 199 coords 2 965.682495 176.083801 +node 200 coords 2 1029.443604 193.593475 +node 201 coords 2 1032.429443 175.001572 +node 202 coords 2 1077.117920 474.846375 +node 203 coords 2 961.851135 156.427612 +node 204 coords 2 1037.242310 155.810181 +node 205 coords 2 1053.166138 472.292999 +node 206 coords 2 1029.509033 463.096985 +node 207 coords 2 990.405945 468.713989 +node 208 coords 2 969.334961 465.930023 +node 209 coords 2 944.130981 190.999908 +node 210 coords 2 968.884277 215.280746 +node 211 coords 2 1026.922974 210.883835 +node 212 coords 2 1056.321045 184.929230 +node 213 coords 2 955.619019 482.172150 +node 214 coords 2 1005.271240 455.373047 +node 215 coords 2 983.742615 450.788544 +node 216 coords 2 1019.864929 441.965698 +node 217 coords 2 998.120422 436.159088 +node 218 coords 2 1042.267822 449.985809 +node 219 coords 2 1012.718750 421.387146 +node 220 coords 2 976.156677 431.791229 +node 221 coords 2 1035.290771 427.096069 +node 222 coords 2 1028.911133 407.151947 +node 223 coords 2 991.030579 416.314667 +node 224 coords 2 967.165710 412.047974 +node 225 coords 2 960.914062 447.520905 +node 226 coords 2 1007.131104 400.679077 +node 227 coords 2 983.296021 395.717682 +node 228 coords 2 956.396057 391.342438 +node 229 coords 2 950.896240 428.305267 +node 230 coords 2 936.503967 444.873169 +node 231 coords 2 944.597900 463.845764 +node 232 coords 2 956.394958 136.927322 +node 233 coords 2 1043.991455 137.356750 +node 234 coords 2 941.205505 170.521545 +node 235 coords 2 1058.952515 168.587601 +node 236 coords 2 920.450745 186.046021 +node 237 coords 2 946.429810 211.046539 +node 238 coords 2 952.278015 231.026642 +node 239 coords 2 988.418396 222.476959 +node 240 coords 2 1007.424438 216.510345 +node 241 coords 2 1051.418701 204.558533 +node 242 coords 2 1079.250244 195.155945 +node 243 coords 2 1087.505615 174.344360 +node 244 coords 2 1057.653564 430.395721 +node 245 coords 2 1054.713623 412.680389 +node 246 coords 2 1026.432739 384.030426 +node 247 coords 2 1000.768250 378.818512 +node 248 coords 2 973.731995 373.924377 +node 249 coords 2 938.749756 408.230347 +node 250 coords 2 921.776184 425.422058 +node 251 coords 2 912.710693 440.147705 +node 252 coords 2 917.521118 462.732758 +node 253 coords 2 926.983887 479.979340 +node 254 coords 2 975.684875 236.716583 +node 255 coords 2 999.082764 239.828796 +node 256 coords 2 1024.018433 232.261124 +node 257 coords 2 1049.034302 226.144836 +node 258 coords 2 1060.418701 451.444458 +node 259 coords 2 1083.553345 416.437531 +node 260 coords 2 1047.703857 392.467865 +node 261 coords 2 982.441406 256.932556 +node 262 coords 2 929.063965 148.961975 +node 263 coords 2 1073.307129 151.210266 +node 264 coords 2 915.119995 163.165970 +node 265 coords 2 919.455444 209.200424 +node 266 coords 2 924.790894 226.286865 +node 267 coords 2 937.377686 248.389160 +node 268 coords 2 1078.673096 213.751343 +node 269 coords 2 1021.221741 361.641235 +node 270 coords 2 990.817810 355.482697 +node 271 coords 2 945.290527 370.072388 +node 272 coords 2 924.036133 387.010193 +node 273 coords 2 909.757202 405.091034 +node 274 coords 2 959.214844 252.611908 +node 275 coords 2 1072.016602 238.814331 +node 276 coords 2 1081.398438 433.300751 +node 277 coords 2 1074.966797 395.830231 +node 278 coords 2 1053.369385 369.695251 +node 279 coords 2 963.811096 277.387909 +node 280 coords 2 1001.172424 265.209076 +node 281 coords 2 1045.218994 249.671188 +node 282 coords 2 913.870850 240.086990 +node 283 coords 2 943.994446 275.708740 +node 284 coords 2 1005.726135 334.523438 +node 285 coords 2 961.448975 351.153381 +node 286 coords 2 1080.038940 451.394623 +node 287 coords 2 954.224243 302.027008 +node 288 coords 2 983.218445 286.663422 +node 289 coords 2 1011.245728 289.483398 +node 290 coords 2 1018.799927 249.004593 +node 291 coords 2 1070.409058 264.684265 +node 292 coords 2 1024.867065 267.400421 +node 293 coords 2 956.039001 116.355095 +node 294 coords 2 1044.157227 116.563545 +node 295 coords 2 927.773071 348.063721 +node 296 coords 2 1084.945190 377.873749 +node 297 coords 2 920.698547 265.501770 +node 298 coords 2 1040.048584 343.120422 +node 299 coords 2 979.223328 332.450012 +node 300 coords 2 926.174683 293.845520 +node 301 coords 2 988.511475 308.533844 +node 302 coords 2 1044.543701 276.318115 +node 303 coords 2 924.614075 129.073639 +node 304 coords 2 1075.804810 129.484131 +node 305 coords 2 948.893188 327.307159 +node 306 coords 2 920.701599 325.041077 +node 307 coords 2 913.871460 367.860107 +node 308 coords 2 1071.787964 347.240601 +node 309 coords 2 1019.910950 314.808044 +node 310 coords 2 1070.689209 292.329987 +node 311 coords 2 967.301086 314.902802 +node 312 coords 2 1040.229858 297.748260 +node 313 coords 2 1054.807251 320.261871 +node 314 coords 2 939.247253 95.716988 +node 315 coords 2 1060.854980 95.819145 +node 316 coords 2 1078.490112 318.511322 +node 317 coords 2 1085.096436 106.766518 +node 318 coords 2 915.026184 106.645897 +node 319 coords 2 937.530762 60.522198 +node 320 coords 2 1062.486206 60.539227 +node 321 coords 2 1149.244141 0.000000 +node 322 coords 2 1203.338257 0.000000 +node 323 coords 2 1263.944946 0.000000 +node 324 coords 2 1332.606079 0.000000 +node 325 coords 2 1410.680420 0.000000 +node 326 coords 2 1499.274292 0.000000 +node 327 coords 2 1599.160034 0.000000 +node 328 coords 2 1710.689941 0.000000 +node 329 coords 2 1833.738403 0.000000 +node 330 coords 2 2000.000000 0.000000 +node 331 coords 2 2000.000000 500.000000 +node 332 coords 2 2000.000000 360.076019 +node 333 coords 2 2000.000000 219.966446 +node 334 coords 2 2000.000000 109.983208 +node 335 coords 2 1124.447632 500.000000 +node 336 coords 2 1151.436401 500.000000 +node 337 coords 2 1181.541870 500.000000 +node 338 coords 2 1215.429443 500.000000 +node 339 coords 2 1253.886475 500.000000 +node 340 coords 2 1297.850586 500.000000 +node 341 coords 2 1348.427856 500.000000 +node 342 coords 2 1406.884521 500.000000 +node 343 coords 2 1474.594727 500.000000 +node 344 coords 2 1552.925537 500.000000 +node 345 coords 2 1643.055542 500.000000 +node 346 coords 2 1745.759155 500.000000 +node 347 coords 2 1861.224243 500.000000 +node 348 coords 2 1124.791504 473.150757 +node 349 coords 2 1120.852905 443.723083 +node 350 coords 2 1117.790527 418.775146 +node 351 coords 2 1118.929565 394.277679 +node 352 coords 2 1123.238770 369.661591 +node 353 coords 2 1127.120728 238.010040 +node 354 coords 2 1121.929932 211.645859 +node 355 coords 2 1119.058105 189.061020 +node 356 coords 2 1127.550659 342.637787 +node 357 coords 2 1128.829102 316.139465 +node 358 coords 2 1129.120483 289.808868 +node 359 coords 2 1128.689087 263.819611 +node 360 coords 2 1119.519409 163.294540 +node 361 coords 2 1152.309204 470.280548 +node 362 coords 2 1151.649048 440.322754 +node 363 coords 2 1123.103271 137.603134 +node 364 coords 2 1151.580566 411.662231 +node 365 coords 2 1153.503540 384.205597 +node 366 coords 2 1155.291992 225.967484 +node 367 coords 2 1151.760986 202.510925 +node 368 coords 2 1156.593140 357.193085 +node 369 coords 2 1157.437500 251.228516 +node 370 coords 2 1152.105591 178.212372 +node 371 coords 2 1158.940063 330.115356 +node 372 coords 2 1159.750488 303.296387 +node 373 coords 2 1159.200684 276.942566 +node 374 coords 2 1183.960938 468.381989 +node 375 coords 2 1184.056152 435.717224 +node 376 coords 2 1126.445068 101.583275 +node 377 coords 2 1154.675171 152.973236 +node 378 coords 2 1184.799438 404.114380 +node 379 coords 2 1188.068848 375.120972 +node 380 coords 2 1185.451782 237.918823 +node 381 coords 2 1187.036499 210.783676 +node 382 coords 2 1161.469727 118.961800 +node 383 coords 2 1184.633301 190.287369 +node 384 coords 2 1191.240723 346.546783 +node 385 coords 2 1188.960693 262.856628 +node 386 coords 2 1192.842041 167.363571 +node 387 coords 2 1192.626709 317.668457 +node 388 coords 2 1191.657837 289.526489 +node 389 coords 2 1219.159912 469.057465 +node 390 coords 2 1214.212524 430.472229 +node 391 coords 2 1130.914307 61.451527 +node 392 coords 2 1219.229736 399.527435 +node 393 coords 2 1225.549316 369.566223 +node 394 coords 2 1170.801392 81.614143 +node 395 coords 2 1191.372925 137.235779 +node 396 coords 2 1217.119873 244.449188 +node 397 coords 2 1213.812256 217.421432 +node 398 coords 2 1224.574829 184.326660 +node 399 coords 2 1227.982544 335.316132 +node 400 coords 2 1221.478882 272.338654 +node 401 coords 2 1227.010864 301.457672 +node 402 coords 2 1251.377563 463.743286 +node 403 coords 2 1213.358765 98.868065 +node 404 coords 2 1234.578857 139.198700 +node 405 coords 2 1252.513672 432.520782 +node 406 coords 2 1262.325439 407.286957 +node 407 coords 2 1264.948730 361.026703 +node 408 coords 2 1250.158569 246.689728 +node 409 coords 2 1248.804565 209.647751 +node 410 coords 2 1265.209961 316.400787 +node 411 coords 2 1260.795166 274.527466 +node 412 coords 2 1289.951538 460.572174 +node 413 coords 2 1298.881836 400.942444 +node 414 coords 2 1286.037109 227.026077 +node 415 coords 2 1274.624390 161.491501 +node 416 coords 2 1172.101807 34.679230 +node 417 coords 2 1306.548218 339.847809 +node 418 coords 2 1299.368652 284.286194 +node 419 coords 2 1221.695068 51.239086 +node 420 coords 2 1350.985352 373.583923 +node 421 coords 2 1355.821899 307.292786 +node 422 coords 2 1273.187866 75.416862 +node 423 coords 2 1332.421387 443.353424 +node 424 coords 2 1337.813477 190.508255 +node 425 coords 2 1391.044678 434.869781 +node 426 coords 2 1413.319824 347.390778 +node 427 coords 2 1337.720581 250.484726 +node 428 coords 2 1405.597900 251.706940 +node 429 coords 2 1332.132080 97.178467 +node 430 coords 2 1476.265869 415.445618 +node 431 coords 2 1409.577393 150.866302 +node 432 coords 2 1486.907959 313.453979 +node 433 coords 2 1405.307251 54.092819 +node 434 coords 2 1480.769287 200.065903 +node 435 coords 2 1500.357056 75.825050 +node 436 coords 2 1577.891235 379.612183 +node 437 coords 2 1564.580566 111.634193 +node 438 coords 2 1574.510254 247.320145 +node 439 coords 2 1686.707886 280.033295 +node 440 coords 2 1705.557983 387.724518 +node 441 coords 2 1832.817993 323.428925 +node 442 coords 2 1648.067993 107.169945 +node 443 coords 2 1843.716675 140.241135 +node 444 coords 2 1750.158691 168.393570 +#** +# +#Element 799 +# +#TrPlaneStress2d Elements +# +TrPlaneStress2d 1 nodes 3 14 48 15 +TrPlaneStress2d 2 nodes 3 15 49 16 +TrPlaneStress2d 3 nodes 3 16 50 17 +TrPlaneStress2d 4 nodes 3 13 31 14 +TrPlaneStress2d 5 nodes 3 17 51 18 +TrPlaneStress2d 6 nodes 3 18 52 19 +TrPlaneStress2d 7 nodes 3 23 53 24 +TrPlaneStress2d 8 nodes 3 24 54 25 +TrPlaneStress2d 9 nodes 3 25 55 26 +TrPlaneStress2d 10 nodes 3 19 56 20 +TrPlaneStress2d 11 nodes 3 20 57 21 +TrPlaneStress2d 12 nodes 3 21 58 22 +TrPlaneStress2d 13 nodes 3 22 59 23 +TrPlaneStress2d 14 nodes 3 26 60 27 +TrPlaneStress2d 15 nodes 3 48 49 15 +TrPlaneStress2d 16 nodes 3 48 61 49 +TrPlaneStress2d 17 nodes 3 14 31 48 +TrPlaneStress2d 18 nodes 3 49 50 16 +TrPlaneStress2d 19 nodes 3 49 62 50 +TrPlaneStress2d 20 nodes 3 27 63 28 +TrPlaneStress2d 21 nodes 3 32 48 31 +TrPlaneStress2d 22 nodes 3 50 51 17 +TrPlaneStress2d 23 nodes 3 50 64 51 +TrPlaneStress2d 24 nodes 3 51 52 18 +TrPlaneStress2d 25 nodes 3 51 65 52 +TrPlaneStress2d 26 nodes 3 54 55 25 +TrPlaneStress2d 27 nodes 3 54 66 55 +TrPlaneStress2d 28 nodes 3 24 53 54 +TrPlaneStress2d 29 nodes 3 53 67 54 +TrPlaneStress2d 30 nodes 3 52 56 19 +TrPlaneStress2d 31 nodes 3 52 68 56 +TrPlaneStress2d 32 nodes 3 23 59 53 +TrPlaneStress2d 33 nodes 3 59 69 53 +TrPlaneStress2d 34 nodes 3 55 60 26 +TrPlaneStress2d 35 nodes 3 55 70 60 +TrPlaneStress2d 36 nodes 3 56 57 20 +TrPlaneStress2d 37 nodes 3 56 71 57 +TrPlaneStress2d 38 nodes 3 57 58 21 +TrPlaneStress2d 39 nodes 3 57 72 58 +TrPlaneStress2d 40 nodes 3 58 59 22 +TrPlaneStress2d 41 nodes 3 58 73 59 +TrPlaneStress2d 42 nodes 3 61 62 49 +TrPlaneStress2d 43 nodes 3 61 74 62 +TrPlaneStress2d 44 nodes 3 48 32 61 +TrPlaneStress2d 45 nodes 3 62 64 50 +TrPlaneStress2d 46 nodes 3 62 75 64 +TrPlaneStress2d 47 nodes 3 28 76 29 +TrPlaneStress2d 48 nodes 3 33 61 32 +TrPlaneStress2d 49 nodes 3 60 63 27 +TrPlaneStress2d 50 nodes 3 60 77 63 +TrPlaneStress2d 51 nodes 3 64 65 51 +TrPlaneStress2d 52 nodes 3 64 78 65 +TrPlaneStress2d 53 nodes 3 65 68 52 +TrPlaneStress2d 54 nodes 3 65 79 68 +TrPlaneStress2d 55 nodes 3 67 66 54 +TrPlaneStress2d 56 nodes 3 67 80 66 +TrPlaneStress2d 57 nodes 3 53 69 67 +TrPlaneStress2d 58 nodes 3 69 81 67 +TrPlaneStress2d 59 nodes 3 63 76 28 +TrPlaneStress2d 60 nodes 3 63 82 76 +TrPlaneStress2d 61 nodes 3 66 70 55 +TrPlaneStress2d 62 nodes 3 66 83 70 +TrPlaneStress2d 63 nodes 3 68 71 56 +TrPlaneStress2d 64 nodes 3 68 84 71 +TrPlaneStress2d 65 nodes 3 59 73 69 +TrPlaneStress2d 66 nodes 3 73 85 69 +TrPlaneStress2d 67 nodes 3 70 77 60 +TrPlaneStress2d 68 nodes 3 70 86 77 +TrPlaneStress2d 69 nodes 3 71 72 57 +TrPlaneStress2d 70 nodes 3 71 87 72 +TrPlaneStress2d 71 nodes 3 72 73 58 +TrPlaneStress2d 72 nodes 3 72 88 73 +TrPlaneStress2d 73 nodes 3 74 75 62 +TrPlaneStress2d 74 nodes 3 74 89 75 +TrPlaneStress2d 75 nodes 3 61 33 74 +TrPlaneStress2d 76 nodes 3 75 78 64 +TrPlaneStress2d 77 nodes 3 75 90 78 +TrPlaneStress2d 78 nodes 3 29 91 30 +TrPlaneStress2d 79 nodes 3 34 74 33 +TrPlaneStress2d 80 nodes 3 78 79 65 +TrPlaneStress2d 81 nodes 3 78 92 79 +TrPlaneStress2d 82 nodes 3 79 84 68 +TrPlaneStress2d 83 nodes 3 79 93 84 +TrPlaneStress2d 84 nodes 3 76 91 29 +TrPlaneStress2d 85 nodes 3 76 94 91 +TrPlaneStress2d 86 nodes 3 77 82 63 +TrPlaneStress2d 87 nodes 3 77 95 82 +TrPlaneStress2d 88 nodes 3 80 83 66 +TrPlaneStress2d 89 nodes 3 80 96 83 +TrPlaneStress2d 90 nodes 3 67 81 80 +TrPlaneStress2d 91 nodes 3 81 97 80 +TrPlaneStress2d 92 nodes 3 69 85 81 +TrPlaneStress2d 93 nodes 3 85 98 81 +TrPlaneStress2d 94 nodes 3 83 86 70 +TrPlaneStress2d 95 nodes 3 83 96 86 +TrPlaneStress2d 96 nodes 3 84 87 71 +TrPlaneStress2d 97 nodes 3 84 99 87 +TrPlaneStress2d 98 nodes 3 73 88 85 +TrPlaneStress2d 99 nodes 3 88 100 85 +TrPlaneStress2d 100 nodes 3 87 88 72 +TrPlaneStress2d 101 nodes 3 87 101 88 +TrPlaneStress2d 102 nodes 3 89 90 75 +TrPlaneStress2d 103 nodes 3 89 102 90 +TrPlaneStress2d 104 nodes 3 74 34 89 +TrPlaneStress2d 105 nodes 3 82 94 76 +TrPlaneStress2d 106 nodes 3 82 103 94 +TrPlaneStress2d 107 nodes 3 86 95 77 +TrPlaneStress2d 108 nodes 3 86 104 95 +TrPlaneStress2d 109 nodes 3 90 92 78 +TrPlaneStress2d 110 nodes 3 90 105 92 +TrPlaneStress2d 111 nodes 3 92 93 79 +TrPlaneStress2d 112 nodes 3 92 106 93 +TrPlaneStress2d 113 nodes 3 93 99 84 +TrPlaneStress2d 114 nodes 3 93 107 99 +TrPlaneStress2d 115 nodes 3 35 89 34 +TrPlaneStress2d 116 nodes 3 80 97 96 +TrPlaneStress2d 117 nodes 3 97 108 96 +TrPlaneStress2d 118 nodes 3 108 104 96 +TrPlaneStress2d 119 nodes 3 97 100 108 +TrPlaneStress2d 120 nodes 3 81 98 97 +TrPlaneStress2d 121 nodes 3 98 100 97 +TrPlaneStress2d 122 nodes 3 98 85 100 +TrPlaneStress2d 123 nodes 3 99 101 87 +TrPlaneStress2d 124 nodes 3 99 109 101 +TrPlaneStress2d 125 nodes 3 88 101 100 +TrPlaneStress2d 126 nodes 3 101 110 100 +TrPlaneStress2d 127 nodes 3 102 105 90 +TrPlaneStress2d 128 nodes 3 102 111 105 +TrPlaneStress2d 129 nodes 3 89 35 102 +TrPlaneStress2d 130 nodes 3 104 86 96 +TrPlaneStress2d 131 nodes 3 111 106 105 +TrPlaneStress2d 132 nodes 3 106 92 105 +TrPlaneStress2d 133 nodes 3 102 35 111 +TrPlaneStress2d 134 nodes 3 91 3 30 +TrPlaneStress2d 135 nodes 3 95 103 82 +TrPlaneStress2d 136 nodes 3 95 104 103 +TrPlaneStress2d 137 nodes 3 106 107 93 +TrPlaneStress2d 138 nodes 3 106 112 107 +TrPlaneStress2d 139 nodes 3 94 113 91 +TrPlaneStress2d 140 nodes 3 107 109 99 +TrPlaneStress2d 141 nodes 3 107 114 109 +TrPlaneStress2d 142 nodes 3 109 110 101 +TrPlaneStress2d 143 nodes 3 109 115 110 +TrPlaneStress2d 144 nodes 3 110 108 100 +TrPlaneStress2d 145 nodes 3 36 111 35 +TrPlaneStress2d 146 nodes 3 103 116 94 +TrPlaneStress2d 147 nodes 3 112 114 107 +TrPlaneStress2d 148 nodes 3 112 117 114 +TrPlaneStress2d 149 nodes 3 106 111 112 +TrPlaneStress2d 150 nodes 3 113 3 91 +TrPlaneStress2d 151 nodes 3 94 116 113 +TrPlaneStress2d 152 nodes 3 116 4 113 +TrPlaneStress2d 153 nodes 3 2 30 3 +TrPlaneStress2d 154 nodes 3 114 115 109 +TrPlaneStress2d 155 nodes 3 114 118 115 +TrPlaneStress2d 156 nodes 3 115 119 110 +TrPlaneStress2d 157 nodes 3 103 120 116 +TrPlaneStress2d 158 nodes 3 37 111 36 +TrPlaneStress2d 159 nodes 3 104 120 103 +TrPlaneStress2d 160 nodes 3 111 121 112 +TrPlaneStress2d 161 nodes 3 3 113 4 +TrPlaneStress2d 162 nodes 3 117 118 114 +TrPlaneStress2d 163 nodes 3 117 122 118 +TrPlaneStress2d 164 nodes 3 112 121 117 +TrPlaneStress2d 165 nodes 3 121 122 117 +TrPlaneStress2d 166 nodes 3 119 108 110 +TrPlaneStress2d 167 nodes 3 119 123 108 +TrPlaneStress2d 168 nodes 3 108 123 104 +TrPlaneStress2d 169 nodes 3 118 124 115 +TrPlaneStress2d 170 nodes 3 115 124 119 +TrPlaneStress2d 171 nodes 3 124 125 119 +TrPlaneStress2d 172 nodes 3 120 5 116 +TrPlaneStress2d 173 nodes 3 111 37 121 +TrPlaneStress2d 174 nodes 3 119 125 123 +TrPlaneStress2d 175 nodes 3 125 126 123 +TrPlaneStress2d 176 nodes 3 4 116 5 +TrPlaneStress2d 177 nodes 3 38 121 37 +TrPlaneStress2d 178 nodes 3 122 127 118 +TrPlaneStress2d 179 nodes 3 126 120 123 +TrPlaneStress2d 180 nodes 3 125 128 126 +TrPlaneStress2d 181 nodes 3 104 123 120 +TrPlaneStress2d 182 nodes 3 118 127 124 +TrPlaneStress2d 183 nodes 3 127 128 124 +TrPlaneStress2d 184 nodes 3 124 128 125 +TrPlaneStress2d 185 nodes 3 5 120 6 +TrPlaneStress2d 186 nodes 3 39 129 38 +TrPlaneStress2d 187 nodes 3 128 130 126 +TrPlaneStress2d 188 nodes 3 122 131 127 +TrPlaneStress2d 189 nodes 3 6 130 7 +TrPlaneStress2d 190 nodes 3 130 132 126 +TrPlaneStress2d 191 nodes 3 40 133 39 +TrPlaneStress2d 192 nodes 3 126 132 120 +TrPlaneStress2d 193 nodes 3 132 6 120 +TrPlaneStress2d 194 nodes 3 132 130 6 +TrPlaneStress2d 195 nodes 3 129 121 38 +TrPlaneStress2d 196 nodes 3 39 133 129 +TrPlaneStress2d 197 nodes 3 133 131 129 +TrPlaneStress2d 198 nodes 3 128 134 130 +TrPlaneStress2d 199 nodes 3 131 135 127 +TrPlaneStress2d 200 nodes 3 122 129 131 +TrPlaneStress2d 201 nodes 3 128 135 134 +TrPlaneStress2d 202 nodes 3 135 128 127 +TrPlaneStress2d 203 nodes 3 122 121 129 +TrPlaneStress2d 204 nodes 3 7 134 8 +TrPlaneStress2d 205 nodes 3 41 136 40 +TrPlaneStress2d 206 nodes 3 130 134 7 +TrPlaneStress2d 207 nodes 3 131 137 135 +TrPlaneStress2d 208 nodes 3 40 136 133 +TrPlaneStress2d 209 nodes 3 136 137 133 +TrPlaneStress2d 210 nodes 3 137 138 135 +TrPlaneStress2d 211 nodes 3 131 133 137 +TrPlaneStress2d 212 nodes 3 138 134 135 +TrPlaneStress2d 213 nodes 3 138 9 134 +TrPlaneStress2d 214 nodes 3 8 134 9 +TrPlaneStress2d 215 nodes 3 42 136 41 +TrPlaneStress2d 216 nodes 3 137 139 138 +TrPlaneStress2d 217 nodes 3 139 140 138 +TrPlaneStress2d 218 nodes 3 137 141 139 +TrPlaneStress2d 219 nodes 3 9 140 10 +TrPlaneStress2d 220 nodes 3 9 138 140 +TrPlaneStress2d 221 nodes 3 140 142 10 +TrPlaneStress2d 222 nodes 3 47 142 46 +TrPlaneStress2d 223 nodes 3 12 11 47 +TrPlaneStress2d 224 nodes 3 137 136 141 +TrPlaneStress2d 225 nodes 3 136 42 141 +TrPlaneStress2d 226 nodes 3 43 143 42 +TrPlaneStress2d 227 nodes 3 139 142 140 +TrPlaneStress2d 228 nodes 3 141 144 139 +TrPlaneStress2d 229 nodes 3 10 142 11 +TrPlaneStress2d 230 nodes 3 144 142 139 +TrPlaneStress2d 231 nodes 3 141 143 144 +TrPlaneStress2d 232 nodes 3 143 145 144 +TrPlaneStress2d 233 nodes 3 143 141 42 +TrPlaneStress2d 234 nodes 3 142 47 11 +TrPlaneStress2d 235 nodes 3 44 45 43 +TrPlaneStress2d 236 nodes 3 46 145 45 +TrPlaneStress2d 237 nodes 3 46 142 145 +TrPlaneStress2d 238 nodes 3 145 43 45 +TrPlaneStress2d 239 nodes 3 43 145 143 +TrPlaneStress2d 240 nodes 3 145 142 144 +TrPlaneStress2d 241 nodes 3 189 193 1 +TrPlaneStress2d 242 nodes 3 193 194 1 +TrPlaneStress2d 243 nodes 3 194 188 1 +TrPlaneStress2d 244 nodes 3 193 195 194 +TrPlaneStress2d 245 nodes 3 189 196 193 +TrPlaneStress2d 246 nodes 3 194 197 188 +TrPlaneStress2d 247 nodes 3 148 198 149 +TrPlaneStress2d 248 nodes 3 149 199 150 +TrPlaneStress2d 249 nodes 3 157 200 156 +TrPlaneStress2d 250 nodes 3 158 201 157 +TrPlaneStress2d 251 nodes 3 185 168 167 +TrPlaneStress2d 252 nodes 3 186 202 185 +TrPlaneStress2d 253 nodes 3 150 203 151 +TrPlaneStress2d 254 nodes 3 159 204 158 +TrPlaneStress2d 255 nodes 3 188 197 187 +TrPlaneStress2d 256 nodes 3 190 196 189 +TrPlaneStress2d 257 nodes 3 187 205 186 +TrPlaneStress2d 258 nodes 3 195 197 194 +TrPlaneStress2d 259 nodes 3 195 206 197 +TrPlaneStress2d 260 nodes 3 193 207 195 +TrPlaneStress2d 261 nodes 3 196 207 193 +TrPlaneStress2d 262 nodes 3 196 208 207 +TrPlaneStress2d 263 nodes 3 198 199 149 +TrPlaneStress2d 264 nodes 3 198 209 199 +TrPlaneStress2d 265 nodes 3 148 210 198 +TrPlaneStress2d 266 nodes 3 200 211 156 +TrPlaneStress2d 267 nodes 3 157 201 200 +TrPlaneStress2d 268 nodes 3 201 212 200 +TrPlaneStress2d 269 nodes 3 190 213 196 +TrPlaneStress2d 270 nodes 3 206 205 197 +TrPlaneStress2d 271 nodes 3 195 214 206 +TrPlaneStress2d 272 nodes 3 207 214 195 +TrPlaneStress2d 273 nodes 3 208 215 207 +TrPlaneStress2d 274 nodes 3 196 213 208 +TrPlaneStress2d 275 nodes 3 214 216 206 +TrPlaneStress2d 276 nodes 3 207 215 214 +TrPlaneStress2d 277 nodes 3 215 217 214 +TrPlaneStress2d 278 nodes 3 216 218 206 +TrPlaneStress2d 279 nodes 3 214 217 216 +TrPlaneStress2d 280 nodes 3 217 219 216 +TrPlaneStress2d 281 nodes 3 215 220 217 +TrPlaneStress2d 282 nodes 3 218 205 206 +TrPlaneStress2d 283 nodes 3 216 221 218 +TrPlaneStress2d 284 nodes 3 219 221 216 +TrPlaneStress2d 285 nodes 3 219 222 221 +TrPlaneStress2d 286 nodes 3 217 223 219 +TrPlaneStress2d 287 nodes 3 220 223 217 +TrPlaneStress2d 288 nodes 3 220 224 223 +TrPlaneStress2d 289 nodes 3 215 225 220 +TrPlaneStress2d 290 nodes 3 219 226 222 +TrPlaneStress2d 291 nodes 3 223 226 219 +TrPlaneStress2d 292 nodes 3 223 227 226 +TrPlaneStress2d 293 nodes 3 224 227 223 +TrPlaneStress2d 294 nodes 3 224 228 227 +TrPlaneStress2d 295 nodes 3 220 229 224 +TrPlaneStress2d 296 nodes 3 225 229 220 +TrPlaneStress2d 297 nodes 3 225 230 229 +TrPlaneStress2d 298 nodes 3 215 208 225 +TrPlaneStress2d 299 nodes 3 208 231 225 +TrPlaneStress2d 300 nodes 3 151 232 152 +TrPlaneStress2d 301 nodes 3 160 233 159 +TrPlaneStress2d 302 nodes 3 191 213 190 +TrPlaneStress2d 303 nodes 3 199 203 150 +TrPlaneStress2d 304 nodes 3 199 234 203 +TrPlaneStress2d 305 nodes 3 158 204 201 +TrPlaneStress2d 306 nodes 3 204 235 201 +TrPlaneStress2d 307 nodes 3 209 234 199 +TrPlaneStress2d 308 nodes 3 209 236 234 +TrPlaneStress2d 309 nodes 3 198 237 209 +TrPlaneStress2d 310 nodes 3 210 237 198 +TrPlaneStress2d 311 nodes 3 210 238 237 +TrPlaneStress2d 312 nodes 3 148 239 210 +TrPlaneStress2d 313 nodes 3 211 240 156 +TrPlaneStress2d 314 nodes 3 200 241 211 +TrPlaneStress2d 315 nodes 3 212 241 200 +TrPlaneStress2d 316 nodes 3 212 242 241 +TrPlaneStress2d 317 nodes 3 201 235 212 +TrPlaneStress2d 318 nodes 3 235 243 212 +TrPlaneStress2d 319 nodes 3 221 244 218 +TrPlaneStress2d 320 nodes 3 222 245 221 +TrPlaneStress2d 321 nodes 3 226 246 222 +TrPlaneStress2d 322 nodes 3 227 247 226 +TrPlaneStress2d 323 nodes 3 228 248 227 +TrPlaneStress2d 324 nodes 3 224 249 228 +TrPlaneStress2d 325 nodes 3 229 249 224 +TrPlaneStress2d 326 nodes 3 229 250 249 +TrPlaneStress2d 327 nodes 3 230 250 229 +TrPlaneStress2d 328 nodes 3 230 251 250 +TrPlaneStress2d 329 nodes 3 225 231 230 +TrPlaneStress2d 330 nodes 3 231 252 230 +TrPlaneStress2d 331 nodes 3 208 213 231 +TrPlaneStress2d 332 nodes 3 191 253 213 +TrPlaneStress2d 333 nodes 3 210 254 238 +TrPlaneStress2d 334 nodes 3 239 254 210 +TrPlaneStress2d 335 nodes 3 239 255 254 +TrPlaneStress2d 336 nodes 3 148 240 239 +TrPlaneStress2d 337 nodes 3 240 255 239 +TrPlaneStress2d 338 nodes 3 240 148 156 +TrPlaneStress2d 339 nodes 3 211 256 240 +TrPlaneStress2d 340 nodes 3 241 257 211 +TrPlaneStress2d 341 nodes 3 244 258 218 +TrPlaneStress2d 342 nodes 3 221 245 244 +TrPlaneStress2d 343 nodes 3 245 259 244 +TrPlaneStress2d 344 nodes 3 222 260 245 +TrPlaneStress2d 345 nodes 3 230 252 251 +TrPlaneStress2d 346 nodes 3 252 15 251 +TrPlaneStress2d 347 nodes 3 231 253 252 +TrPlaneStress2d 348 nodes 3 255 261 254 +TrPlaneStress2d 349 nodes 3 256 255 240 +TrPlaneStress2d 350 nodes 3 211 257 256 +TrPlaneStress2d 351 nodes 3 258 205 218 +TrPlaneStress2d 352 nodes 3 192 253 191 +TrPlaneStress2d 353 nodes 3 192 14 253 +TrPlaneStress2d 354 nodes 3 203 232 151 +TrPlaneStress2d 355 nodes 3 203 262 232 +TrPlaneStress2d 356 nodes 3 159 233 204 +TrPlaneStress2d 357 nodes 3 233 263 204 +TrPlaneStress2d 358 nodes 3 234 262 203 +TrPlaneStress2d 359 nodes 3 234 264 262 +TrPlaneStress2d 360 nodes 3 204 263 235 +TrPlaneStress2d 361 nodes 3 263 243 235 +TrPlaneStress2d 362 nodes 3 209 265 236 +TrPlaneStress2d 363 nodes 3 237 265 209 +TrPlaneStress2d 364 nodes 3 237 266 265 +TrPlaneStress2d 365 nodes 3 238 266 237 +TrPlaneStress2d 366 nodes 3 238 267 266 +TrPlaneStress2d 367 nodes 3 242 268 241 +TrPlaneStress2d 368 nodes 3 212 243 242 +TrPlaneStress2d 369 nodes 3 243 179 242 +TrPlaneStress2d 370 nodes 3 246 260 222 +TrPlaneStress2d 371 nodes 3 226 247 246 +TrPlaneStress2d 372 nodes 3 247 269 246 +TrPlaneStress2d 373 nodes 3 227 248 247 +TrPlaneStress2d 374 nodes 3 248 270 247 +TrPlaneStress2d 375 nodes 3 228 271 248 +TrPlaneStress2d 376 nodes 3 249 272 228 +TrPlaneStress2d 377 nodes 3 250 273 249 +TrPlaneStress2d 378 nodes 3 251 16 250 +TrPlaneStress2d 379 nodes 3 253 231 213 +TrPlaneStress2d 380 nodes 3 254 274 238 +TrPlaneStress2d 381 nodes 3 241 268 257 +TrPlaneStress2d 382 nodes 3 268 275 257 +TrPlaneStress2d 383 nodes 3 244 276 258 +TrPlaneStress2d 384 nodes 3 259 276 244 +TrPlaneStress2d 385 nodes 3 259 170 276 +TrPlaneStress2d 386 nodes 3 245 277 259 +TrPlaneStress2d 387 nodes 3 260 277 245 +TrPlaneStress2d 388 nodes 3 260 278 277 +TrPlaneStress2d 389 nodes 3 261 274 254 +TrPlaneStress2d 390 nodes 3 261 279 274 +TrPlaneStress2d 391 nodes 3 255 280 261 +TrPlaneStress2d 392 nodes 3 257 281 256 +TrPlaneStress2d 393 nodes 3 267 282 266 +TrPlaneStress2d 394 nodes 3 238 274 267 +TrPlaneStress2d 395 nodes 3 274 283 267 +TrPlaneStress2d 396 nodes 3 269 278 246 +TrPlaneStress2d 397 nodes 3 247 270 269 +TrPlaneStress2d 398 nodes 3 270 284 269 +TrPlaneStress2d 399 nodes 3 248 285 270 +TrPlaneStress2d 400 nodes 3 276 286 258 +TrPlaneStress2d 401 nodes 3 279 283 274 +TrPlaneStress2d 402 nodes 3 279 287 283 +TrPlaneStress2d 403 nodes 3 261 288 279 +TrPlaneStress2d 404 nodes 3 280 288 261 +TrPlaneStress2d 405 nodes 3 280 289 288 +TrPlaneStress2d 406 nodes 3 255 290 280 +TrPlaneStress2d 407 nodes 3 281 290 256 +TrPlaneStress2d 408 nodes 3 290 255 256 +TrPlaneStress2d 409 nodes 3 257 275 281 +TrPlaneStress2d 410 nodes 3 275 291 281 +TrPlaneStress2d 411 nodes 3 280 292 289 +TrPlaneStress2d 412 nodes 3 290 292 280 +TrPlaneStress2d 413 nodes 3 290 281 292 +TrPlaneStress2d 414 nodes 3 152 293 153 +TrPlaneStress2d 415 nodes 3 161 294 160 +TrPlaneStress2d 416 nodes 3 169 286 170 +TrPlaneStress2d 417 nodes 3 169 202 286 +TrPlaneStress2d 418 nodes 3 202 205 286 +TrPlaneStress2d 419 nodes 3 202 186 205 +TrPlaneStress2d 420 nodes 3 170 259 171 +TrPlaneStress2d 421 nodes 3 16 251 15 +TrPlaneStress2d 422 nodes 3 17 273 16 +TrPlaneStress2d 423 nodes 3 187 197 205 +TrPlaneStress2d 424 nodes 3 236 264 234 +TrPlaneStress2d 425 nodes 3 236 26 264 +TrPlaneStress2d 426 nodes 3 266 24 265 +TrPlaneStress2d 427 nodes 3 246 278 260 +TrPlaneStress2d 428 nodes 3 271 285 248 +TrPlaneStress2d 429 nodes 3 271 295 285 +TrPlaneStress2d 430 nodes 3 228 272 271 +TrPlaneStress2d 431 nodes 3 249 273 272 +TrPlaneStress2d 432 nodes 3 273 18 272 +TrPlaneStress2d 433 nodes 3 250 16 273 +TrPlaneStress2d 434 nodes 3 268 178 275 +TrPlaneStress2d 435 nodes 3 277 171 259 +TrPlaneStress2d 436 nodes 3 278 296 277 +TrPlaneStress2d 437 nodes 3 283 297 267 +TrPlaneStress2d 438 nodes 3 284 298 269 +TrPlaneStress2d 439 nodes 3 270 299 284 +TrPlaneStress2d 440 nodes 3 286 205 258 +TrPlaneStress2d 441 nodes 3 276 170 286 +TrPlaneStress2d 442 nodes 3 287 300 283 +TrPlaneStress2d 443 nodes 3 279 288 287 +TrPlaneStress2d 444 nodes 3 289 301 288 +TrPlaneStress2d 445 nodes 3 291 302 281 +TrPlaneStress2d 446 nodes 3 275 177 291 +TrPlaneStress2d 447 nodes 3 292 302 289 +TrPlaneStress2d 448 nodes 3 292 281 302 +TrPlaneStress2d 449 nodes 3 168 202 169 +TrPlaneStress2d 450 nodes 3 171 296 172 +TrPlaneStress2d 451 nodes 3 296 173 172 +TrPlaneStress2d 452 nodes 3 178 268 179 +TrPlaneStress2d 453 nodes 3 13 14 192 +TrPlaneStress2d 454 nodes 3 15 252 14 +TrPlaneStress2d 455 nodes 3 18 273 17 +TrPlaneStress2d 456 nodes 3 25 265 24 +TrPlaneStress2d 457 nodes 3 202 168 185 +TrPlaneStress2d 458 nodes 3 232 293 152 +TrPlaneStress2d 459 nodes 3 232 303 293 +TrPlaneStress2d 460 nodes 3 160 294 233 +TrPlaneStress2d 461 nodes 3 294 304 233 +TrPlaneStress2d 462 nodes 3 253 14 252 +TrPlaneStress2d 463 nodes 3 262 303 232 +TrPlaneStress2d 464 nodes 3 262 27 303 +TrPlaneStress2d 465 nodes 3 233 304 263 +TrPlaneStress2d 466 nodes 3 304 181 263 +TrPlaneStress2d 467 nodes 3 264 27 262 +TrPlaneStress2d 468 nodes 3 265 25 236 +TrPlaneStress2d 469 nodes 3 242 179 268 +TrPlaneStress2d 470 nodes 3 282 24 266 +TrPlaneStress2d 471 nodes 3 282 23 24 +TrPlaneStress2d 472 nodes 3 282 297 23 +TrPlaneStress2d 473 nodes 3 282 267 297 +TrPlaneStress2d 474 nodes 3 285 299 270 +TrPlaneStress2d 475 nodes 3 285 305 299 +TrPlaneStress2d 476 nodes 3 295 305 285 +TrPlaneStress2d 477 nodes 3 295 306 305 +TrPlaneStress2d 478 nodes 3 271 307 295 +TrPlaneStress2d 479 nodes 3 296 171 277 +TrPlaneStress2d 480 nodes 3 278 308 296 +TrPlaneStress2d 481 nodes 3 283 300 297 +TrPlaneStress2d 482 nodes 3 300 22 297 +TrPlaneStress2d 483 nodes 3 298 278 269 +TrPlaneStress2d 484 nodes 3 284 309 298 +TrPlaneStress2d 485 nodes 3 299 301 284 +TrPlaneStress2d 486 nodes 3 301 287 288 +TrPlaneStress2d 487 nodes 3 289 309 301 +TrPlaneStress2d 488 nodes 3 291 310 302 +TrPlaneStress2d 489 nodes 3 297 22 23 +TrPlaneStress2d 490 nodes 3 305 311 299 +TrPlaneStress2d 491 nodes 3 310 312 302 +TrPlaneStress2d 492 nodes 3 312 289 302 +TrPlaneStress2d 493 nodes 3 312 309 289 +TrPlaneStress2d 494 nodes 3 173 308 174 +TrPlaneStress2d 495 nodes 3 176 291 177 +TrPlaneStress2d 496 nodes 3 177 275 178 +TrPlaneStress2d 497 nodes 3 179 243 180 +TrPlaneStress2d 498 nodes 3 180 243 181 +TrPlaneStress2d 499 nodes 3 19 307 18 +TrPlaneStress2d 500 nodes 3 20 306 19 +TrPlaneStress2d 501 nodes 3 26 236 25 +TrPlaneStress2d 502 nodes 3 27 264 26 +TrPlaneStress2d 503 nodes 3 272 307 271 +TrPlaneStress2d 504 nodes 3 272 18 307 +TrPlaneStress2d 505 nodes 3 287 306 300 +TrPlaneStress2d 506 nodes 3 306 287 305 +TrPlaneStress2d 507 nodes 3 295 19 306 +TrPlaneStress2d 508 nodes 3 307 19 295 +TrPlaneStress2d 509 nodes 3 308 173 296 +TrPlaneStress2d 510 nodes 3 278 298 308 +TrPlaneStress2d 511 nodes 3 309 313 298 +TrPlaneStress2d 512 nodes 3 284 301 309 +TrPlaneStress2d 513 nodes 3 291 176 310 +TrPlaneStress2d 514 nodes 3 311 301 299 +TrPlaneStress2d 515 nodes 3 311 287 301 +TrPlaneStress2d 516 nodes 3 305 287 311 +TrPlaneStress2d 517 nodes 3 310 313 312 +TrPlaneStress2d 518 nodes 3 313 308 298 +TrPlaneStress2d 519 nodes 3 309 312 313 +TrPlaneStress2d 520 nodes 3 153 314 154 +TrPlaneStress2d 521 nodes 3 162 315 161 +TrPlaneStress2d 522 nodes 3 174 316 175 +TrPlaneStress2d 523 nodes 3 175 310 176 +TrPlaneStress2d 524 nodes 3 181 304 182 +TrPlaneStress2d 525 nodes 3 21 306 20 +TrPlaneStress2d 526 nodes 3 22 300 21 +TrPlaneStress2d 527 nodes 3 28 303 27 +TrPlaneStress2d 528 nodes 3 303 314 293 +TrPlaneStress2d 529 nodes 3 314 153 293 +TrPlaneStress2d 530 nodes 3 294 315 304 +TrPlaneStress2d 531 nodes 3 294 161 315 +TrPlaneStress2d 532 nodes 3 313 316 308 +TrPlaneStress2d 533 nodes 3 313 310 316 +TrPlaneStress2d 534 nodes 3 182 317 183 +TrPlaneStress2d 535 nodes 3 29 318 28 +TrPlaneStress2d 536 nodes 3 316 310 175 +TrPlaneStress2d 537 nodes 3 174 308 316 +TrPlaneStress2d 538 nodes 3 154 319 155 +TrPlaneStress2d 539 nodes 3 163 320 162 +TrPlaneStress2d 540 nodes 3 314 319 154 +TrPlaneStress2d 541 nodes 3 314 29 319 +TrPlaneStress2d 542 nodes 3 162 320 315 +TrPlaneStress2d 543 nodes 3 320 183 315 +TrPlaneStress2d 544 nodes 3 183 320 184 +TrPlaneStress2d 545 nodes 3 30 319 29 +TrPlaneStress2d 546 nodes 3 263 181 243 +TrPlaneStress2d 547 nodes 3 300 306 21 +TrPlaneStress2d 548 nodes 3 182 304 317 +TrPlaneStress2d 549 nodes 3 304 315 317 +TrPlaneStress2d 550 nodes 3 318 303 28 +TrPlaneStress2d 551 nodes 3 318 314 303 +TrPlaneStress2d 552 nodes 3 315 183 317 +TrPlaneStress2d 553 nodes 3 318 29 314 +TrPlaneStress2d 554 nodes 3 319 147 155 +TrPlaneStress2d 555 nodes 3 163 165 320 +TrPlaneStress2d 556 nodes 3 155 147 146 +TrPlaneStress2d 557 nodes 3 164 165 163 +TrPlaneStress2d 558 nodes 3 147 30 2 +TrPlaneStress2d 559 nodes 3 166 184 165 +TrPlaneStress2d 560 nodes 3 320 165 184 +TrPlaneStress2d 561 nodes 3 30 147 319 +TrPlaneStress2d 562 nodes 3 169 348 168 +TrPlaneStress2d 563 nodes 3 170 349 169 +TrPlaneStress2d 564 nodes 3 171 350 170 +TrPlaneStress2d 565 nodes 3 167 168 335 +TrPlaneStress2d 566 nodes 3 172 351 171 +TrPlaneStress2d 567 nodes 3 173 352 172 +TrPlaneStress2d 568 nodes 3 178 353 177 +TrPlaneStress2d 569 nodes 3 179 354 178 +TrPlaneStress2d 570 nodes 3 180 355 179 +TrPlaneStress2d 571 nodes 3 174 356 173 +TrPlaneStress2d 572 nodes 3 175 357 174 +TrPlaneStress2d 573 nodes 3 176 358 175 +TrPlaneStress2d 574 nodes 3 177 359 176 +TrPlaneStress2d 575 nodes 3 181 360 180 +TrPlaneStress2d 576 nodes 3 348 335 168 +TrPlaneStress2d 577 nodes 3 169 349 348 +TrPlaneStress2d 578 nodes 3 349 361 348 +TrPlaneStress2d 579 nodes 3 170 350 349 +TrPlaneStress2d 580 nodes 3 350 362 349 +TrPlaneStress2d 581 nodes 3 335 348 336 +TrPlaneStress2d 582 nodes 3 182 363 181 +TrPlaneStress2d 583 nodes 3 171 351 350 +TrPlaneStress2d 584 nodes 3 351 364 350 +TrPlaneStress2d 585 nodes 3 172 352 351 +TrPlaneStress2d 586 nodes 3 352 365 351 +TrPlaneStress2d 587 nodes 3 354 353 178 +TrPlaneStress2d 588 nodes 3 354 366 353 +TrPlaneStress2d 589 nodes 3 179 355 354 +TrPlaneStress2d 590 nodes 3 355 367 354 +TrPlaneStress2d 591 nodes 3 173 356 352 +TrPlaneStress2d 592 nodes 3 356 368 352 +TrPlaneStress2d 593 nodes 3 353 359 177 +TrPlaneStress2d 594 nodes 3 353 369 359 +TrPlaneStress2d 595 nodes 3 180 360 355 +TrPlaneStress2d 596 nodes 3 360 370 355 +TrPlaneStress2d 597 nodes 3 174 357 356 +TrPlaneStress2d 598 nodes 3 357 371 356 +TrPlaneStress2d 599 nodes 3 175 358 357 +TrPlaneStress2d 600 nodes 3 358 372 357 +TrPlaneStress2d 601 nodes 3 176 359 358 +TrPlaneStress2d 602 nodes 3 359 373 358 +TrPlaneStress2d 603 nodes 3 361 336 348 +TrPlaneStress2d 604 nodes 3 349 362 361 +TrPlaneStress2d 605 nodes 3 362 374 361 +TrPlaneStress2d 606 nodes 3 350 364 362 +TrPlaneStress2d 607 nodes 3 364 375 362 +TrPlaneStress2d 608 nodes 3 336 361 337 +TrPlaneStress2d 609 nodes 3 183 376 182 +TrPlaneStress2d 610 nodes 3 181 363 360 +TrPlaneStress2d 611 nodes 3 363 377 360 +TrPlaneStress2d 612 nodes 3 351 365 364 +TrPlaneStress2d 613 nodes 3 365 378 364 +TrPlaneStress2d 614 nodes 3 352 368 365 +TrPlaneStress2d 615 nodes 3 368 379 365 +TrPlaneStress2d 616 nodes 3 366 369 353 +TrPlaneStress2d 617 nodes 3 366 380 369 +TrPlaneStress2d 618 nodes 3 354 367 366 +TrPlaneStress2d 619 nodes 3 367 381 366 +TrPlaneStress2d 620 nodes 3 182 376 363 +TrPlaneStress2d 621 nodes 3 376 382 363 +TrPlaneStress2d 622 nodes 3 355 370 367 +TrPlaneStress2d 623 nodes 3 370 383 367 +TrPlaneStress2d 624 nodes 3 356 371 368 +TrPlaneStress2d 625 nodes 3 371 384 368 +TrPlaneStress2d 626 nodes 3 369 373 359 +TrPlaneStress2d 627 nodes 3 369 385 373 +TrPlaneStress2d 628 nodes 3 360 377 370 +TrPlaneStress2d 629 nodes 3 377 386 370 +TrPlaneStress2d 630 nodes 3 357 372 371 +TrPlaneStress2d 631 nodes 3 372 387 371 +TrPlaneStress2d 632 nodes 3 358 373 372 +TrPlaneStress2d 633 nodes 3 373 388 372 +TrPlaneStress2d 634 nodes 3 374 337 361 +TrPlaneStress2d 635 nodes 3 362 375 374 +TrPlaneStress2d 636 nodes 3 375 389 374 +TrPlaneStress2d 637 nodes 3 364 378 375 +TrPlaneStress2d 638 nodes 3 378 390 375 +TrPlaneStress2d 639 nodes 3 337 374 338 +TrPlaneStress2d 640 nodes 3 184 391 183 +TrPlaneStress2d 641 nodes 3 365 379 378 +TrPlaneStress2d 642 nodes 3 379 392 378 +TrPlaneStress2d 643 nodes 3 368 384 379 +TrPlaneStress2d 644 nodes 3 384 393 379 +TrPlaneStress2d 645 nodes 3 183 391 376 +TrPlaneStress2d 646 nodes 3 391 394 376 +TrPlaneStress2d 647 nodes 3 363 382 377 +TrPlaneStress2d 648 nodes 3 382 395 377 +TrPlaneStress2d 649 nodes 3 380 385 369 +TrPlaneStress2d 650 nodes 3 380 396 385 +TrPlaneStress2d 651 nodes 3 366 381 380 +TrPlaneStress2d 652 nodes 3 381 397 380 +TrPlaneStress2d 653 nodes 3 367 383 381 +TrPlaneStress2d 654 nodes 3 383 398 381 +TrPlaneStress2d 655 nodes 3 370 386 383 +TrPlaneStress2d 656 nodes 3 386 398 383 +TrPlaneStress2d 657 nodes 3 371 387 384 +TrPlaneStress2d 658 nodes 3 387 399 384 +TrPlaneStress2d 659 nodes 3 385 388 373 +TrPlaneStress2d 660 nodes 3 385 400 388 +TrPlaneStress2d 661 nodes 3 372 388 387 +TrPlaneStress2d 662 nodes 3 388 401 387 +TrPlaneStress2d 663 nodes 3 389 338 374 +TrPlaneStress2d 664 nodes 3 375 390 389 +TrPlaneStress2d 665 nodes 3 390 402 389 +TrPlaneStress2d 666 nodes 3 376 394 382 +TrPlaneStress2d 667 nodes 3 394 403 382 +TrPlaneStress2d 668 nodes 3 377 395 386 +TrPlaneStress2d 669 nodes 3 395 404 386 +TrPlaneStress2d 670 nodes 3 378 392 390 +TrPlaneStress2d 671 nodes 3 392 405 390 +TrPlaneStress2d 672 nodes 3 379 393 392 +TrPlaneStress2d 673 nodes 3 393 406 392 +TrPlaneStress2d 674 nodes 3 384 399 393 +TrPlaneStress2d 675 nodes 3 399 407 393 +TrPlaneStress2d 676 nodes 3 338 389 339 +TrPlaneStress2d 677 nodes 3 396 400 385 +TrPlaneStress2d 678 nodes 3 396 408 400 +TrPlaneStress2d 679 nodes 3 380 397 396 +TrPlaneStress2d 680 nodes 3 397 409 396 +TrPlaneStress2d 681 nodes 3 381 398 397 +TrPlaneStress2d 682 nodes 3 398 409 397 +TrPlaneStress2d 683 nodes 3 387 401 399 +TrPlaneStress2d 684 nodes 3 401 410 399 +TrPlaneStress2d 685 nodes 3 400 401 388 +TrPlaneStress2d 686 nodes 3 400 411 401 +TrPlaneStress2d 687 nodes 3 402 339 389 +TrPlaneStress2d 688 nodes 3 390 405 402 +TrPlaneStress2d 689 nodes 3 405 412 402 +TrPlaneStress2d 690 nodes 3 412 339 402 +TrPlaneStress2d 691 nodes 3 405 406 412 +TrPlaneStress2d 692 nodes 3 405 392 406 +TrPlaneStress2d 693 nodes 3 184 321 391 +TrPlaneStress2d 694 nodes 3 382 403 395 +TrPlaneStress2d 695 nodes 3 403 404 395 +TrPlaneStress2d 696 nodes 3 393 407 406 +TrPlaneStress2d 697 nodes 3 407 413 406 +TrPlaneStress2d 698 nodes 3 409 408 396 +TrPlaneStress2d 699 nodes 3 409 414 408 +TrPlaneStress2d 700 nodes 3 414 411 408 +TrPlaneStress2d 701 nodes 3 411 400 408 +TrPlaneStress2d 702 nodes 3 409 415 414 +TrPlaneStress2d 703 nodes 3 391 416 394 +TrPlaneStress2d 704 nodes 3 404 398 386 +TrPlaneStress2d 705 nodes 3 404 415 398 +TrPlaneStress2d 706 nodes 3 399 410 407 +TrPlaneStress2d 707 nodes 3 410 417 407 +TrPlaneStress2d 708 nodes 3 401 411 410 +TrPlaneStress2d 709 nodes 3 411 418 410 +TrPlaneStress2d 710 nodes 3 339 412 340 +TrPlaneStress2d 711 nodes 3 394 419 403 +TrPlaneStress2d 712 nodes 3 413 412 406 +TrPlaneStress2d 713 nodes 3 407 417 413 +TrPlaneStress2d 714 nodes 3 417 420 413 +TrPlaneStress2d 715 nodes 3 416 419 394 +TrPlaneStress2d 716 nodes 3 416 322 419 +TrPlaneStress2d 717 nodes 3 391 321 416 +TrPlaneStress2d 718 nodes 3 321 184 166 +TrPlaneStress2d 719 nodes 3 398 415 409 +TrPlaneStress2d 720 nodes 3 410 418 417 +TrPlaneStress2d 721 nodes 3 418 421 417 +TrPlaneStress2d 722 nodes 3 411 414 418 +TrPlaneStress2d 723 nodes 3 419 422 403 +TrPlaneStress2d 724 nodes 3 340 412 341 +TrPlaneStress2d 725 nodes 3 403 422 404 +TrPlaneStress2d 726 nodes 3 413 423 412 +TrPlaneStress2d 727 nodes 3 322 416 321 +TrPlaneStress2d 728 nodes 3 415 424 414 +TrPlaneStress2d 729 nodes 3 420 423 413 +TrPlaneStress2d 730 nodes 3 420 425 423 +TrPlaneStress2d 731 nodes 3 417 421 420 +TrPlaneStress2d 732 nodes 3 421 426 420 +TrPlaneStress2d 733 nodes 3 418 427 421 +TrPlaneStress2d 734 nodes 3 419 323 422 +TrPlaneStress2d 735 nodes 3 423 341 412 +TrPlaneStress2d 736 nodes 3 323 419 322 +TrPlaneStress2d 737 nodes 3 341 425 342 +TrPlaneStress2d 738 nodes 3 404 422 415 +TrPlaneStress2d 739 nodes 3 414 427 418 +TrPlaneStress2d 740 nodes 3 414 424 427 +TrPlaneStress2d 741 nodes 3 424 428 427 +TrPlaneStress2d 742 nodes 3 415 429 424 +TrPlaneStress2d 743 nodes 3 426 425 420 +TrPlaneStress2d 744 nodes 3 426 430 425 +TrPlaneStress2d 745 nodes 3 421 428 426 +TrPlaneStress2d 746 nodes 3 425 341 423 +TrPlaneStress2d 747 nodes 3 427 428 421 +TrPlaneStress2d 748 nodes 3 429 431 424 +TrPlaneStress2d 749 nodes 3 415 422 429 +TrPlaneStress2d 750 nodes 3 324 422 323 +TrPlaneStress2d 751 nodes 3 342 430 343 +TrPlaneStress2d 752 nodes 3 424 431 428 +TrPlaneStress2d 753 nodes 3 430 342 425 +TrPlaneStress2d 754 nodes 3 426 432 430 +TrPlaneStress2d 755 nodes 3 429 433 431 +TrPlaneStress2d 756 nodes 3 431 434 428 +TrPlaneStress2d 757 nodes 3 325 433 324 +TrPlaneStress2d 758 nodes 3 422 324 429 +TrPlaneStress2d 759 nodes 3 429 324 433 +TrPlaneStress2d 760 nodes 3 343 430 344 +TrPlaneStress2d 761 nodes 3 426 428 432 +TrPlaneStress2d 762 nodes 3 433 435 431 +TrPlaneStress2d 763 nodes 3 434 432 428 +TrPlaneStress2d 764 nodes 3 432 436 430 +TrPlaneStress2d 765 nodes 3 431 435 434 +TrPlaneStress2d 766 nodes 3 433 326 435 +TrPlaneStress2d 767 nodes 3 435 437 434 +TrPlaneStress2d 768 nodes 3 326 433 325 +TrPlaneStress2d 769 nodes 3 344 436 345 +TrPlaneStress2d 770 nodes 3 436 344 430 +TrPlaneStress2d 771 nodes 3 432 438 436 +TrPlaneStress2d 772 nodes 3 437 438 434 +TrPlaneStress2d 773 nodes 3 435 327 437 +TrPlaneStress2d 774 nodes 3 438 439 436 +TrPlaneStress2d 775 nodes 3 432 434 438 +TrPlaneStress2d 776 nodes 3 327 435 326 +TrPlaneStress2d 777 nodes 3 345 440 346 +TrPlaneStress2d 778 nodes 3 439 440 436 +TrPlaneStress2d 779 nodes 3 439 441 440 +TrPlaneStress2d 780 nodes 3 438 442 439 +TrPlaneStress2d 781 nodes 3 328 442 327 +TrPlaneStress2d 782 nodes 3 333 443 334 +TrPlaneStress2d 783 nodes 3 334 329 330 +TrPlaneStress2d 784 nodes 3 442 444 439 +TrPlaneStress2d 785 nodes 3 438 437 442 +TrPlaneStress2d 786 nodes 3 346 441 347 +TrPlaneStress2d 787 nodes 3 345 436 440 +TrPlaneStress2d 788 nodes 3 441 346 440 +TrPlaneStress2d 789 nodes 3 439 444 441 +TrPlaneStress2d 790 nodes 3 444 443 441 +TrPlaneStress2d 791 nodes 3 437 327 442 +TrPlaneStress2d 792 nodes 3 444 328 443 +TrPlaneStress2d 793 nodes 3 329 443 328 +TrPlaneStress2d 794 nodes 3 442 328 444 +TrPlaneStress2d 795 nodes 3 331 347 332 +TrPlaneStress2d 796 nodes 3 332 441 333 +TrPlaneStress2d 797 nodes 3 443 329 334 +TrPlaneStress2d 798 nodes 3 333 441 443 +TrPlaneStress2d 799 nodes 3 347 441 332 +#** +# +# +SimpleCS 1 thick 1.0 material 1 set 1 +SimpleCS 2 thick 1.0 material 2 set 2 +# +IsoLE 1 d 2500.000000 E 20.e3 n 0.200000 tAlpha 0.000012 +Concrete3 2 d 0. E 20.e3 n 0.2 Gf 0.1 Ft 2.5 tAlpha 0.000012 +# +BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 3 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0. set 4 +#BoundaryCondition 3 loadTimeFunction 2 dofs 1 2 values 1 -0.025 set 5 +NodalLoad 3 loadTimeFunction 1 dofs 2 1 2 Components 2 0. -1.0 set 5 reference +ConstantFunction 1 f(t) 2.0 +Set 1 elementranges {(1 240) (562 799)} +Set 2 elementranges {(241 561)} +Set 3 nodes 1 12 +Set 4 nodes 1 330 +Set 5 nodes 1 1 +# +# +# +#%BEGIN_CHECK% tolerance 1.e-6 +## check load levels +#LOADLEVEL tStep 1 value 6.105389 +#LOADLEVEL tStep 2 value 12.210779 +#LOADLEVEL tStep 3 value 18.160715 +#LOADLEVEL tStep 4 value 23.798851 +#LOADLEVEL tStep 5 value 28.987424 +#LOADLEVEL tStep 6 value 33.733775 +#LOADLEVEL tStep 7 value 38.101680 +#LOADLEVEL tStep 8 value 41.454458 +#LOADLEVEL tStep 9 value 43.523632 +#LOADLEVEL tStep 10 value 43.944412 +#LOADLEVEL tStep 11 value 40.616307 +#LOADLEVEL tStep 12 value 35.640997 +#LOADLEVEL tStep 13 value 33.458921 +#LOADLEVEL tStep 14 value 30.429273 +#LOADLEVEL tStep 15 value 28.534107 +#LOADLEVEL tStep 16 value 26.685269 +#LOADLEVEL tStep 17 value 25.713360 +#LOADLEVEL tStep 18 value 23.581970 +#LOADLEVEL tStep 19 value 22.329408 +#LOADLEVEL tStep 20 value 21.473918 +## check node displacement at final step +#NODE tStep 1 number 1 dof 2 unknown d value -2.50000000e-02 tolerance 1.e-9 +#NODE tStep 2 number 1 dof 2 unknown d value -5.00000000e-02 tolerance 1.e-9 +#NODE tStep 3 number 1 dof 2 unknown d value -7.50000000e-02 tolerance 1.e-9 +#NODE tStep 4 number 1 dof 2 unknown d value -1.00000000e-01 tolerance 1.e-9 +#NODE tStep 5 number 1 dof 2 unknown d value -1.25000000e-01 tolerance 1.e-9 +#NODE tStep 6 number 1 dof 2 unknown d value -1.50000000e-01 tolerance 1.e-9 +#NODE tStep 7 number 1 dof 2 unknown d value -1.75000000e-01 tolerance 1.e-9 +#NODE tStep 8 number 1 dof 2 unknown d value -2.00000000e-01 tolerance 1.e-9 +#NODE tStep 9 number 1 dof 2 unknown d value -2.23529412e-01 tolerance 1.e-9 +#NODE tStep 10 number 1 dof 2 unknown d value -2.48506881e-01 tolerance 1.e-9 +#NODE tStep 11 number 1 dof 2 unknown d value -2.73484350e-01 tolerance 1.e-9 +#NODE tStep 12 number 1 dof 2 unknown d value -2.88622210e-01 tolerance 1.e-9 +#NODE tStep 13 number 1 dof 2 unknown d value -2.99732566e-01 tolerance 1.e-9 +#NODE tStep 14 number 1 dof 2 unknown d value -3.11434890e-01 tolerance 1.e-9 +#NODE tStep 15 number 1 dof 2 unknown d value -3.23957999e-01 tolerance 1.e-9 +#NODE tStep 16 number 1 dof 2 unknown d value -3.37148350e-01 tolerance 1.e-9 +#NODE tStep 17 number 1 dof 2 unknown d value -3.51381985e-01 tolerance 1.e-9 +#NODE tStep 18 number 1 dof 2 unknown d value -3.65945211e-01 tolerance 1.e-9 +#NODE tStep 19 number 1 dof 2 unknown d value -3.80153237e-01 tolerance 1.e-9 +#NODE tStep 20 number 1 dof 2 unknown d value -3.96213669e-01 tolerance 1.e-9 +## +## +## check some arbitrary element +#ELEMENT tStep 10 number 338 gp 1 keyword 4 component 1 value 1.93951745e-03 tolerance 1.e-8 +#ELEMENT tStep 10 number 338 gp 1 keyword 4 component 2 value 1.26544635e-05 tolerance 1.e-8 +#ELEMENT tStep 10 number 338 gp 1 keyword 4 component 6 value 3.40924245e-04 tolerance 1.e-8 +#ELEMENT tStep 10 number 338 gp 1 keyword 1 component 1 value 1.01732715e+00 tolerance 1.e-8 +#ELEMENT tStep 10 number 338 gp 1 keyword 1 component 2 value 1.65217303e-01 tolerance 1.e-8 +#ELEMENT tStep 10 number 338 gp 1 keyword 1 component 6 value 7.53828658e-02 tolerance 1.e-8 +## +#ELEMENT tStep 20 number 338 gp 1 keyword 4 component 1 value 6.49791757e-03 tolerance 1.e-8 +#ELEMENT tStep 20 number 338 gp 1 keyword 4 component 2 value 6.02559845e-05 tolerance 1.e-8 +#ELEMENT tStep 20 number 338 gp 1 keyword 4 component 6 value 1.92610989e-03 tolerance 1.e-8 +#ELEMENT tStep 20 number 338 gp 1 keyword 1 component 1 value -3.38740932e-02 tolerance 1.e-8 +#ELEMENT tStep 20 number 338 gp 1 keyword 1 component 2 value -1.58065960e+00 tolerance 1.e-8 +#ELEMENT tStep 20 number 338 gp 1 keyword 1 component 6 value 2.31394491e-01 tolerance 1.e-8 +#%END_CHECK% diff --git a/bindings/python/examples/vtkdemo.py b/bindings/python/examples/vtkdemo.py new file mode 100644 index 000000000..c63b2fb10 --- /dev/null +++ b/bindings/python/examples/vtkdemo.py @@ -0,0 +1,35 @@ +import oofempy +import numpy as np +import pyvista as pv + +dr=oofempy.OOFEMTXTDataReader("concrete_3point.in") +problem=oofempy.InstanciateProblem(dr, oofempy.problemMode.processor, False, None, False) +problem.init() +problem.solveYourself() +vtkxmlPy = oofempy.vtkmemory(1, problem, domain_all=True, tstep_all=True, dofman_all=True, element_all=True, vars=(1,4), primvars=(1,), cellvars = (47,), stype=1, pythonExport=1) +vtkxmlPy.initialize() +vtkxmlPy.doOutput(problem.giveCurrentStep(), False) + +for p in vtkxmlPy.getVTKPieces(): +#p = vtkxmlPy.getVTKPieces()[0] + print ("Piece:", p) + print(p.getVertices()) + print(p.getCellConnectivity()) + print(p.getCellTypes(vtkxmlPy)) + disp = p.getPrimaryVertexValues(oofempy.UnknownType.DisplacementVector) + sig = p.getInternalVertexValues(oofempy.InternalStateType.IST_StressTensor) + sigx = sig[:, 0] + + grid = pv.UnstructuredGrid(p.getCellConnectivity(), p.getCellTypes(vtkxmlPy), p.getVertices()) + grid.point_arrays['Sigma_xx'] = sigx + grid['Disp'] = disp + print(grid.active_vectors) + warped = grid.warp_by_vector('Disp', factor=1000.) + p = pv.Plotter() + p.add_mesh(warped, scalars='Sigma_xx') + p.add_mesh(grid, style='wireframe', color='black') + p.set_viewup((0,1,0)) + p.show() +problem.terminateAnalysis() + + diff --git a/bindings/python/oofem.cpp b/bindings/python/oofem.cpp new file mode 100644 index 000000000..246c16532 --- /dev/null +++ b/bindings/python/oofem.cpp @@ -0,0 +1,1719 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include //Conversion for lists +#include +namespace py = pybind11; + +#include + +#include "floatarray.h" +#include "floatmatrix.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" +#include "intarray.h" + +#include "femcmpnn.h" +#include "timestep.h" +#include "domain.h" +#include "engngm.h" +#include "staggeredproblem.h" +#include "dof.h" +#include "dofmanager.h" +#include "element.h" +#include "Elements/structuralelement.h" +#include "datastream.h" +#include "timediscretizationtype.h" +#include "statecountertype.h" + +#include "generalboundarycondition.h" +#include "boundarycondition.h" +#include "initialcondition.h" +#include "function.h" +#include "material.h" +#include "integrationpointstatus.h" +#include "matstatus.h" +#include "Materials/structuralmaterial.h" +#include "Materials/structuralms.h" + +#include "crosssection.h" +#include "sparsemtrx.h" + +#include "field.h" +#include "feinterpol.h" +#include "util.h" +#include "datareader.h" +#include "oofemtxtdatareader.h" +#include "valuemodetype.h" +#include "dofiditem.h" +#include "timer.h" + +#include "classfactory.h" + +#include "chartype.h" +#include "elementgeometrytype.h" +#include "internalstatetype.h" + +#include "integrationrule.h" +#include "gausspoint.h" +#include "inputrecord.h" +#include "dynamicinputrecord.h" + +#include "classfactory.h" +#include "unknownnumberingscheme.h" +#include "vtkxmlexportmodule.h" +#include "vtkmemoryexportmodule.h" +#include "homexportmodule.h" + +#include "uniformgridfield.h" +#include "unstructuredgridfield.h" +#include "dofmanvalfield.h" +#include "pythonfield.h" +#include +#include "oofemutil.h" +#ifdef _OPENMP +#include +#endif + +//test +void test (oofem::Element& e) { + oofem::IntArray a = {1,2,3}; + + e.giveDofManDofIDMask (1, a); + fprintf (stderr, "test:"); + a.printYourself(); +} + +/* + Trampoline classes +*/ +template class PyFemComponent : public FemComponentBase { +public: + using FemComponentBase::FemComponentBase; +}; + + +template class PyElement : public PyFemComponent { +//template class PyElement : public ElementBase { + // inherit the constructor +public: + using PyFemComponent::PyFemComponent; + // trampoline (need one for each virtual method) + int giveNumberOfDofs() override { + PYBIND11_OVERLOAD (int, ElementBase, giveNumberOfDofs,); + } + int computeNumberOfDofs() override { + PYBIND11_OVERLOAD (int, ElementBase, computeNumberOfDofs,); + } + + int giveNumberOfInternalDofManagers() const override { + PYBIND11_OVERLOAD (int, ElementBase, giveNumberOfInternalDofManagers,); + } + oofem::DofManager *giveInternalDofManager(int i) const override { + PYBIND11_OVERLOAD (oofem::DofManager*, ElementBase, giveInternalDofManager,i); + } + void giveCharacteristicMatrix(oofem::FloatMatrix &answer, oofem::CharType type, oofem::TimeStep *tStep) override { + PYBIND11_OVERRIDE (void, ElementBase, giveCharacteristicMatrix,std::ref(answer),type, tStep); + } + void giveCharacteristicVector(oofem::FloatArray &answer, oofem::CharType type, oofem::ValueModeType mode, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, ElementBase, giveCharacteristicVector,std::ref(answer), type, mode, tStep); + } + double giveCharacteristicValue(oofem::CharType type, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD (double, ElementBase, giveCharacteristicValue, type, tStep); + } + bool computeGtoLRotationMatrix(oofem::FloatMatrix &answer) override { + PYBIND11_OVERLOAD (bool, ElementBase, computeGtoLRotationMatrix,std::ref(answer)); + } + void giveDofManDofIDMask(int inode, oofem::IntArray &answer) const override { + PYBIND11_OVERLOAD (void, ElementBase, giveDofManDofIDMask, inode, std::ref(answer)); + } + + void giveInternalDofManDofIDMask(int inode, oofem::IntArray &answer) const override { + PYBIND11_OVERLOAD (void, ElementBase, giveInternalDofManDofIDMask,inode, std::ref(answer)); + } + double computeVolumeAround(oofem::GaussPoint *gp) override { + PYBIND11_OVERLOAD (double, ElementBase, computeVolumeAround, gp); + } + oofem::FEInterpolation *giveInterpolation() const override { + PYBIND11_OVERLOAD (oofem::FEInterpolation*, ElementBase, giveInterpolation,); + } + void printOutputAt(FILE *file, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, ElementBase, printOutputAt, file, tStep); + } + void postInitialize() override { + PYBIND11_OVERLOAD (void, ElementBase, postInitialize,); + } + oofem::MaterialMode giveMaterialMode() override { + PYBIND11_OVERLOAD (oofem::MaterialMode, ElementBase, giveMaterialMode,); + } + const char *giveClassName() const override { + PYBIND11_OVERLOAD_PURE (const char*, ElementBase, giveClassName,); + } + const char *giveInputRecordName() const override { + PYBIND11_OVERLOAD_PURE (const char*, ElementBase, giveInputRecordName,); + } + }; + + template class PyStructuralElement : public PyElement { + // inherit the constructor + public: + using PyElement::PyElement; + // trampoline (need one for each virtual method) + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, StructuralElementBase, computeMassMatrix, std::ref(answer), tStep); + } + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, StructuralElementBase, computeStiffnessMatrix, std::ref(answer), rMode, tStep); + } + void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, StructuralElementBase, computeInitialStressMatrix, std::ref(answer), tStep); + } + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override { + PYBIND11_OVERLOAD_PURE (void, StructuralElementBase, computeStressVector, std::ref(answer), std::ref(strain), gp, tStep); + } + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override { + PYBIND11_OVERLOAD_PURE (void, StructuralElementBase, computeBmatrixAt, gp, std::ref(answer), lowerIndx, upperIndx); + } + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override { + PYBIND11_OVERLOAD (void, StructuralElementBase, computeNmatrixAt, iLocCoord, std::ref(answer)); + } + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp,TimeStep *tStep) override { + PYBIND11_OVERLOAD_PURE (void, StructuralElementBase, computeConstitutiveMatrixAt, std::ref(answer), rMode, gp, tStep); + } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { + PYBIND11_OVERLOAD (void, StructuralElementBase, giveInternalForcesVector, std::ref(answer), tStep, useUpdatedGpRecord); + } + }; + + + template class PyEngngModel : public EngngModelBase { + // inherit the constructor + public: + using EngngModelBase::EngngModelBase; + // trampoline (need one for each virtual method) + void solveYourself() override { + PYBIND11_OVERLOAD_PURE( void, EngngModelBase, solveYourself,); + } + void solveYourselfAt(TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, EngngModelBase, solveYourselfAt, tStep); + } + void terminate(TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, EngngModelBase, terminate, tStep); + } + void doStepOutput(TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, EngngModelBase, doStepOutput, tStep); + } + void updateYourself(TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, EngngModelBase, updateYourself, tStep); + } + void initializeYourself(TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, EngngModelBase, initializeYourself, tStep); + } + int giveNumberOfDomainEquations(int di, const UnknownNumberingScheme &num) override { + PYBIND11_OVERLOAD (int, EngngModelBase, giveNumberOfDomainEquations, di, num); + } + double giveUnknownComponent(ValueModeType vm, TimeStep *t, Domain *domain, Dof *d) override { + PYBIND11_OVERLOAD (double, EngngModelBase, giveUnknownComponent, vm,t,domain,d); + } + // virtual FieldPtr giveField (FieldType key, TimeStep *) { return FieldPtr();} + int instanciateYourself(DataReader &dr, InputRecord &ir, const char *outFileName, const char *desc) override { + PYBIND11_OVERLOAD (int, EngngModelBase, instanciateYourself, dr, ir, outFileName, desc); + } + void initializeFrom(InputRecord &ir) override { + PYBIND11_OVERLOAD (void, EngngModelBase, initializeFrom, ir); + } + int instanciateDefaultMetaStep(InputRecord &ir) override { + PYBIND11_OVERLOAD (int, EngngModelBase, instanciateDefaultMetaStep, ir); + } + void updateAttributes(MetaStep *mStep) override { + PYBIND11_OVERLOAD (void, EngngModelBase, updateAttributes, mStep); + } + TimeStep *giveCurrentStep(bool force = false) override { + PYBIND11_OVERLOAD (TimeStep*, EngngModelBase, giveCurrentStep, force); + } + TimeStep *givePreviousStep(bool force = false) override { + PYBIND11_OVERLOAD (TimeStep*, EngngModelBase, givePreviousStep, force); + } + TimeStep *giveNextStep() override { + PYBIND11_OVERLOAD (TimeStep*, EngngModelBase, giveNextStep, ); + } + TimeStep *giveSolutionStepWhenIcApply(bool force = false) override { + PYBIND11_OVERLOAD (TimeStep*, EngngModelBase, giveSolutionStepWhenIcApply, force); + } + int giveNumberOfFirstStep(bool force = false) override { + PYBIND11_OVERLOAD (int, EngngModelBase, giveNumberOfFirstStep, force); + } + double giveEndOfTimeOfInterest() override { + PYBIND11_OVERLOAD (double, EngngModelBase, giveEndOfTimeOfInterest, ); + } + void updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) override { + PYBIND11_OVERLOAD (void, EngngModelBase, updateSolution, solutionVector, tStep, d); + } + void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) override { + PYBIND11_OVERLOAD (void, EngngModelBase, updateComponent, tStep, cmpn, d); + } + void updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) override { + PYBIND11_OVERLOAD (void, EngngModelBase, updateInternalRHS, answer, tStep, d, eNorm); + } + void updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) override { + PYBIND11_OVERLOAD (void, EngngModelBase, updateMatrix, mat, tStep, d); + } + void initStepIncrements() override { + PYBIND11_OVERLOAD (void, EngngModelBase, initStepIncrements, ); + } + int forceEquationNumbering() override { + PYBIND11_OVERLOAD (int, EngngModelBase, forceEquationNumbering, ); + } + int requiresUnknownsDictionaryUpdate() override { + PYBIND11_OVERLOAD (int, EngngModelBase, requiresUnknownsDictionaryUpdate, ); + } + bool requiresEquationRenumbering(TimeStep *tStep) override { + PYBIND11_OVERLOAD (bool, EngngModelBase, requiresEquationRenumbering, tStep); + } + void updateDofUnknownsDictionary(DofManager *dm, TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, EngngModelBase, updateDofUnknownsDictionary, dm, tStep); + } + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override { + PYBIND11_OVERLOAD (int, EngngModelBase, giveUnknownDictHashIndx, mode, tStep); + } + void assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma, const UnknownNumberingScheme &s, Domain *domain) override { + PYBIND11_OVERLOAD (void, EngngModelBase, assemble, answer, tStep, ma, s, domain ); + } + void assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, Domain *domain) override { + PYBIND11_OVERLOAD (void, EngngModelBase, assemble, answer, tStep, ma, r_s, c_s, domain); + } + int checkConsistency() override { + PYBIND11_OVERLOAD (int, EngngModelBase, checkConsistency, ); + } + int checkProblemConsistency() override { + PYBIND11_OVERLOAD (int, EngngModelBase, checkProblemConsistency, ); + } + void init() override { + PYBIND11_OVERLOAD (void, EngngModelBase, init, ); + } + void postInitialize() override { + PYBIND11_OVERLOAD (void, EngngModelBase, postInitialize, ); + } + void printOutputAt(FILE *file, TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, EngngModelBase, printOutputAt, file, tStep); + } + void printOutputAt(FILE *file, TimeStep *tStep, const IntArray &nodeSets, const IntArray &elementSets) override { + PYBIND11_OVERLOAD (void, EngngModelBase, printOutputAt, file, tStep, nodeSets, elementSets); + } + const char *giveClassName() const override { + PYBIND11_OVERLOAD_PURE (const char*, EngngModelBase, giveClassName, ); + } + bool isElementActivated( int elemNum ) override { + PYBIND11_OVERLOAD (bool, EngngModelBase, isElementActivated, elemNum); + } + bool isElementActivated( Element *e ) override { + PYBIND11_OVERLOAD (bool, EngngModelBase, isElementActivated, e); + } + }; + + + template class PyIntegrationPointStatus : public IntegrationPointStatusBase { + // inherit the constructor + public: + using IntegrationPointStatusBase::IntegrationPointStatusBase; + // trampoline (need one for each virtual method) + const char *giveClassName() const override { + PYBIND11_OVERLOAD_PURE (const char*, IntegrationPointStatusBase, giveClassName,); + } + }; + + template class PyMaterialStatus : public PyIntegrationPointStatus { + // inherit the constructor + public: + using PyIntegrationPointStatus::PyIntegrationPointStatus; + // trampoline (need one for each virtual method) + void printOutputAt(FILE *file, TimeStep *tStep) const override { + PYBIND11_OVERLOAD (void, MaterialStatusBase, printOutputAt, file, tStep); + } + void initTempStatus() override { + PYBIND11_OVERLOAD (void, MaterialStatusBase, initTempStatus, ); + } + void updateYourself(TimeStep *tStep) override { + PYBIND11_OVERLOAD (void, MaterialStatusBase, updateYourself, tStep); + } + bool giveMaterialProperty(int propID, double &value) override { + PYBIND11_OVERLOAD (bool, MaterialStatusBase, giveMaterialProperty, propID, std::ref(value)); + } + void setMaterialProperty(int propID, double value) override { + PYBIND11_OVERLOAD (void, MaterialStatusBase, setMaterialProperty, propID, value); + } + + }; + + template class PyStructuralMaterialStatus : public PyMaterialStatus { + // inherit the constructor + using PyMaterialStatus::PyMaterialStatus; + }; + + + template class PyMaterial : public MaterialBase { + // inherit the constructor + using MaterialBase::MaterialBase; + // trampoline (need one for each virtual method) + bool isCharacteristicMtrxSymmetric(oofem::MatResponseMode rMode) const override { + PYBIND11_OVERLOAD(bool, MaterialBase, isCharacteristicMtrxSymmetric, rMode); + } + double give(int aProperty, oofem::GaussPoint *gp) const override { + PYBIND11_OVERLOAD(bool, MaterialBase, give, aProperty, gp); + } + bool hasProperty(int aProperty, oofem::GaussPoint *gp) const override { + PYBIND11_OVERLOAD(bool, MaterialBase, hasProperty, aProperty, gp); + } + void modifyProperty(int aProperty, double value, oofem::GaussPoint *gp) override { + PYBIND11_OVERLOAD(void, MaterialBase, modifyProperty, aProperty, value, gp); + } + bool hasMaterialModeCapability(oofem::MaterialMode mode) const override { + PYBIND11_OVERLOAD(bool, MaterialBase, hasMaterialModeCapability, mode); + } + bool hasCastingTimeSupport() const override { + PYBIND11_OVERLOAD(bool, MaterialBase, hasCastingTimeSupport, ); + } + int setIPValue(const oofem::FloatArray &value, oofem::GaussPoint *gp, oofem::InternalStateType type) override { + PYBIND11_OVERLOAD(int, MaterialBase, setIPValue, std::ref(value), gp, type); + } + int giveIPValue(oofem::FloatArray &answer, oofem::GaussPoint *gp, oofem::InternalStateType type, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD(int, MaterialBase, giveIPValue, std::ref(answer), gp, type, tStep); + } + void initializeFrom(oofem::InputRecord &ir) override { + PYBIND11_OVERLOAD(void, MaterialBase, initializeFrom, ir); + } + //virtual void saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); + //virtual void restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); + int checkConsistency() override { + PYBIND11_OVERLOAD(int, MaterialBase, checkConsistency, ); + } + void restoreConsistency(oofem::GaussPoint *gp) override { + PYBIND11_OVERLOAD(void, MaterialBase, restoreConsistency, gp); + } + int initMaterial(oofem::Element *element) override { + PYBIND11_OVERLOAD(int, MaterialBase, initMaterial, element); + } + /* + /// Exposing the following won't work (opeened issue https://github.com/pybind/pybind11/issues/1962) + /// However, giveStatus can be overriden and can create and set status properly. See test4.py. + std::unique_ptr CreateStatus(oofem::GaussPoint *gp) const override { + PYBIND11_OVERLOAD(std::unique_ptr, MaterialBase, CreateStatus, gp); + } + */ + + oofem::MaterialStatus* giveStatus (oofem::GaussPoint* gp) const override { + PYBIND11_OVERLOAD(oofem::MaterialStatus*, MaterialBase, giveStatus, gp); + } + void initTempStatus(oofem::GaussPoint *gp) const override { + PYBIND11_OVERLOAD(void, MaterialBase, initTempStatus, gp); + } + const char *giveClassName() const override { + PYBIND11_OVERLOAD_PURE (const char*, MaterialBase, giveClassName,); + } + const char *giveInputRecordName() const override { + PYBIND11_OVERLOAD_PURE (const char*, MaterialBase, giveInputRecordName,); + } + + + }; + + + class PyField : public oofem::Field { + // inherit the constructor + using oofem::Field::Field; + // trampoline (need one for each virtual method + int evaluateAt(oofem::FloatArray &answer, const oofem::FloatArray &coords, + oofem::ValueModeType mode, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD_PURE(int, oofem::Field, evaluateAt, std::ref(answer), coords, mode, tStep); + } + int evaluateAt(oofem::FloatArray &answer, oofem::DofManager *dman, + oofem::ValueModeType mode, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD_PURE(int, oofem::Field, evaluateAt, std::ref(answer), dman, mode, tStep); + } + const char *giveClassName() const override { + PYBIND11_OVERLOAD_PURE(const char*, oofem::Field, giveClassName, ); + } + void saveContext(DataStream &stream) override { + PYBIND11_OVERLOAD_PURE(void, oofem::Field, saveContext, stream); + } + void restoreContext(DataStream &stream) override { + PYBIND11_OVERLOAD_PURE(void, oofem::Field, restoreContext, stream); + } + + + + }; + + + template class PyStructuralMaterial : public PyMaterial { + // inherit the constructor + using PyMaterial::PyMaterial; + // trampoline (need one for each virtual method) + bool hasMaterialModeCapability(oofem::MaterialMode mode) const override { + PYBIND11_OVERLOAD(bool, StructuralMaterialBase, hasMaterialModeCapability, mode); + } + const char *giveClassName() const override { + PYBIND11_OVERLOAD(const char*, StructuralMaterialBase, giveClassName, ); + } + void initializeFrom(oofem::InputRecord &ir) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, initializeFrom, ir); + } + void giveInputRecord(oofem::DynamicInputRecord &input) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, giveInputRecord, input); + } + void giveStiffnessMatrix(oofem::FloatMatrix &answer, oofem::MatResponseMode mode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, giveStiffnessMatrix, std::ref(answer), mode, gp, tStep); + } + void giveRealStressVector (oofem::FloatArray &answer, oofem::GaussPoint *gp, const oofem::FloatArray &reducedStrain, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, giveRealStressVector, std::ref(answer), gp, reducedStrain, tStep); + } + oofem::FloatArrayF<6> giveRealStressVector_3d(const oofem::FloatArrayF<6> &E, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + FloatArray strain = E; + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_3d, strain, gp, tStep); + } + /// Default implementation relies on giveRealStressVector_3d + oofem::FloatArrayF<4> giveRealStressVector_PlaneStrain(const oofem::FloatArrayF<4> &reducedE, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + FloatArray strain = reducedE; + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_PlaneStrain, strain, gp, tStep); + } + /// Iteratively calls giveRealStressVector_3d to find the stress controlled equal to zero· + oofem::FloatArray giveRealStressVector_StressControl(const oofem::FloatArray &reducedE, const oofem::IntArray &strainControl, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_StressControl, reducedE, strainControl, gp, tStep); + } + oofem::FloatArray giveRealStressVector_ShellStressControl(const oofem::FloatArray &reducedE, const oofem::IntArray &strainControl, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_ShellStressControl, reducedE, strainControl, gp, tStep); + } + /// Default implementation relies on giveRealStressVector_StressControl + oofem::FloatArrayF<3> giveRealStressVector_PlaneStress(const oofem::FloatArrayF<3> &reducedE, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + oofem::FloatArray strain = reducedE; + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_PlaneStress, strain, gp, tStep); + } + /// Default implementation relies on giveRealStressVector_StressControl + oofem::FloatArrayF<1> giveRealStressVector_1d(const oofem::FloatArrayF<1> &reducedE, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + oofem::FloatArray strain = reducedE; + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_1d, strain, gp, tStep); + } + /// Default implementation relies on giveRealStressVector_StressControl + oofem::FloatArrayF<2> giveRealStressVector_Warping(const oofem::FloatArrayF<2> &reducedE, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + oofem::FloatArray strain = reducedE; + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_Warping, strain, gp, tStep); + } + /// Default implementation relies on giveRealStressVector_StressControl + oofem::FloatArrayF<2> giveRealStressVector_2dBeamLayer(const oofem::FloatArrayF<2> &reducedE, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + oofem::FloatArray strain = reducedE; + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_2dBeamLayer, strain, gp, tStep); + } + /// Default implementation relies on giveRealStressVector_StressControl + oofem::FloatArrayF<5> giveRealStressVector_PlateLayer(const oofem::FloatArrayF<5> &reducedE, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + oofem::FloatArray strain = reducedE; + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_PlateLayer, strain, gp, tStep); + } + /// Default implementation relies on giveRealStressVector_StressControl + oofem::FloatArrayF<3> giveRealStressVector_Fiber(const oofem::FloatArrayF<3> &reducedE, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + oofem::FloatArray strain = reducedE; + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_Fiber, strain, gp, tStep); + } + oofem::FloatArrayF<3> giveRealStressVector_2dPlateSubSoil(const oofem::FloatArrayF<3> &reducedE, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + oofem::FloatArray strain = reducedE; + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_2dPlateSubSoil, strain, gp, tStep); + } + oofem::FloatArrayF<6> giveRealStressVector_3dBeamSubSoil(const oofem::FloatArrayF<6> &reducedE, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + oofem::FloatArray strain = reducedE; + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveRealStressVector_3dBeamSubSoil, strain, gp, tStep); + } + oofem::FloatArrayF<9> giveFirstPKStressVector_3d(const oofem::FloatArrayF<9> &reducedF, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveFirstPKStressVector_3d, reducedF, gp, tStep); + } + /// Default implementation relies on giveFirstPKStressVector_3d + oofem::FloatArrayF<5> giveFirstPKStressVector_PlaneStrain(const oofem::FloatArrayF<5> &reducedF, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveFirstPKStressVector_PlaneStrain, reducedF, gp, tStep); + } + /// Default implementation relies on giveFirstPKStressVector_3d + oofem::FloatArrayF<4> giveFirstPKStressVector_PlaneStress(const oofem::FloatArrayF<4> &reducedF, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveFirstPKStressVector_PlaneStress, reducedF, gp, tStep); + } + /// Default implementation relies on giveFirstPKStressVector_3d + oofem::FloatArrayF<1> giveFirstPKStressVector_1d(const oofem::FloatArrayF<1> &reducedF, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveFirstPKStressVector_1d, reducedF, gp, tStep); + } + + void giveCauchyStressVector_3d(oofem::FloatArray &answer, oofem::GaussPoint *gp, const oofem::FloatArray &reducedF, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, giveCauchyStressVector_3d, std::ref(answer), gp, reducedF, tStep); + } + void giveCauchyStressVector_PlaneStrain(oofem::FloatArray &answer, oofem::GaussPoint *gp, const oofem::FloatArray &reducedF, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, giveCauchyStressVector_PlaneStrain, std::ref(answer), gp, reducedF, tStep); + } + void giveCauchyStressVector_PlaneStress(oofem::FloatArray &answer, oofem::GaussPoint *gp, const oofem::FloatArray &reducedF, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, giveCauchyStressVector_PlaneStress, std::ref(answer), gp, reducedF, tStep); + } + void giveCauchyStressVector_1d(oofem::FloatArray &answer, oofem::GaussPoint *gp, const oofem::FloatArray &reducedF, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, giveCauchyStressVector_1d, std::ref(answer), gp, reducedF, tStep); + } + + oofem::FloatArrayF<6> giveThermalDilatationVector(oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, giveThermalDilatationVector, gp, tStep); + } + oofem::FloatArray computeStressIndependentStrainVector(oofem::GaussPoint *gp, oofem::TimeStep *tStep, oofem::ValueModeType mode) const override { + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, computeStressIndependentStrainVector, gp, tStep, mode); + } +#if 0 + // I don't think this method ought to be overloaded / Mikael + oofem::FloatArrayF<6> computeStressIndependentStrainVector_3d(oofem::GaussPoint *gp, oofem::TimeStep *tStep, oofem::ValueModeType mode) const override { + PYBIND11_OVERLOAD(oofem::FloatArray, StructuralMaterialBase, computeStressIndependentStrainVector_3d, gp, tStep, mode); + } +#endif + + oofem::FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(oofem::MatResponseMode mode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatMatrix, StructuralMaterialBase, give3dMaterialStiffnessMatrix, mode, gp, tStep); + } + oofem::FloatMatrixF<9,9> give3dMaterialStiffnessMatrix_dPdF(oofem::MatResponseMode mode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatMatrix, StructuralMaterialBase, give3dMaterialStiffnessMatrix_dPdF, mode, gp, tStep); + } + void give3dMaterialStiffnessMatrix_dCde(oofem::FloatMatrix &answer, oofem::MatResponseMode mode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, give3dMaterialStiffnessMatrix_dCde, std::ref(answer), mode, gp, tStep); + } + + FloatMatrixF<3,3> givePlaneStressStiffMtrx(oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatMatrix, StructuralMaterialBase, givePlaneStressStiffMtrx, mmode, gp, tStep); + } + oofem::FloatMatrixF<4,4> givePlaneStressStiffnessMatrix_dPdF(oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatMatrix, StructuralMaterialBase, givePlaneStressStiffnessMatrix_dPdF, mmode, gp, tStep); + } + void givePlaneStressStiffMtrx_dCde(oofem::FloatMatrix &answer, oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, givePlaneStressStiffMtrx_dCde, std::ref(answer), mmode, gp, tStep); + } + + oofem::FloatMatrixF<4,4> givePlaneStrainStiffMtrx(oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatMatrix, StructuralMaterialBase, givePlaneStrainStiffMtrx, mmode, gp, tStep); + } + oofem::FloatMatrixF<5,5> givePlaneStrainStiffnessMatrix_dPdF(oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatMatrix, StructuralMaterialBase, givePlaneStrainStiffnessMatrix_dPdF, mmode, gp, tStep); + } + void givePlaneStrainStiffMtrx_dCde(oofem::FloatMatrix &answer, oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, givePlaneStrainStiffMtrx_dCde, std::ref(answer), mmode, gp, tStep); + } + + oofem::FloatMatrixF<1,1> give1dStressStiffMtrx(oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatMatrix, StructuralMaterialBase, give1dStressStiffMtrx, mmode, gp, tStep); + } + + oofem::FloatMatrixF<1,1> give1dStressStiffnessMatrix_dPdF(oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatMatrix, StructuralMaterialBase, give1dStressStiffnessMatrix_dPdF, mmode, gp, tStep); + } + void give1dStressStiffMtrx_dCde(oofem::FloatMatrix &answer, oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) override { + PYBIND11_OVERLOAD(void, StructuralMaterialBase, give1dStressStiffMtrx_dCde, std::ref(answer), mmode, gp, tStep); + } + + oofem::FloatMatrixF<2,2> give2dBeamLayerStiffMtrx(oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatMatrix, StructuralMaterialBase, give2dBeamLayerStiffMtrx, mmode, gp, tStep); + } + oofem::FloatMatrixF<3,3> give2dPlateSubSoilStiffMtrx(oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatMatrix, StructuralMaterialBase, give2dPlateSubSoilStiffMtrx, mmode, gp, tStep); + } + oofem::FloatMatrixF<6,6> give3dBeamSubSoilStiffMtrx(oofem::MatResponseMode mmode, oofem::GaussPoint *gp, oofem::TimeStep *tStep) const override { + PYBIND11_OVERLOAD(oofem::FloatMatrix, StructuralMaterialBase, give3dBeamSubSoilStiffMtrx, mmode, gp, tStep); + } + }; + + /** + * @brief Initializes some global oofem options (typically controlled from command-line) + * + */ + void init(int logLevel=2, int numberOfThreads=0) { + oofem::oofem_logger.setLogLevel(logLevel); + if ( numberOfThreads > 0 ) { +#ifdef _OPENMP + omp_set_num_threads (numberOfThreads); +#else + fprintf(stderr, "\nCan't use -t, not compiled with OpenMP support\a\n\n"); +#endif + } + } + + + +PYBIND11_MODULE(oofempy, m) { + m.doc() = "oofem python bindings module"; // optional module docstring + + m.def("init", &init, py::arg("logLevel")=2, py::arg("numberOfThreads")=0, "Initializes some global oofem options (typically controlled from command-line)"); + + py::class_(m, "FloatArray") + .def(py::init(), py::arg("n")=0) + .def(py::init([](py::sequence s){ + oofem::FloatArray* ans = new oofem::FloatArray((int) py::len(s)); + for (unsigned int i=0; i(); + } + return ans; + } + )) + .def("printYourself", (void (oofem::FloatArray::*)() const) &oofem::FloatArray::printYourself, "Prints receiver") + .def("printYourself", (void (oofem::FloatArray::*)(const std::string &) const) &oofem::FloatArray::printYourself, "Prints receiver") + .def("pY", &oofem::FloatArray::pY) + .def("__setitem__", [](oofem::FloatArray &s, size_t i, double v) { + s[i] = v; + }) + .def("__getitem__", [](const oofem::FloatArray &s, size_t i) { + if (i >= (size_t) s.giveSize()) throw py::index_error(); + return s[i]; + }) + .def("__repr__", + [](const oofem::FloatArray &s) { + std::ostringstream streamObj; + std::string strObj; + std::string a = " 40 ) { + a.append("..."); + break; + } else { + streamObj.str(""); + streamObj.clear(); + streamObj << s[i];//convert to scientific notation if necessary + strObj = streamObj.str(); + a.append(strObj); + //a.append(std::to_string(s[i])); + a.append(", "); + } + } + a.append("}>"); + return a; + }) + .def("resize", &oofem::FloatArray::resize) + .def("assemble", &oofem::FloatArray::assemble) + .def("distance", (double (oofem::FloatArray::*)(const oofem::FloatArray &) const) &oofem::FloatArray::distance) + .def("normalize", &oofem::FloatArray::normalize) + .def("computeNorm", &oofem::FloatArray::computeNorm) + .def("product", &oofem::FloatArray::product) + .def("zero", &oofem::FloatArray::zero) + .def("beProductOf", &oofem::FloatArray::beProductOf) + + // expose FloatArray operators + .def(py::self + py::self) + .def(py::self - py::self) + .def(py::self * float()) + .def(float() * py::self) + .def(py::self += py::self) + .def(py::self -= py::self) + .def(py::self *= float()) + ; + py::implicitly_convertible(); + + py::class_(m, "FloatMatrix") + .def(py::init<>()) + .def(py::init()) + .def("printYourself", (void (oofem::FloatMatrix::*)() const) &oofem::FloatMatrix::printYourself, "Prints receiver") + .def("printYourself", (void (oofem::FloatMatrix::*)(const std::string &) const) &oofem::FloatMatrix::printYourself, "Prints receiver") + .def("pY", &oofem::FloatMatrix::pY) + .def("__setitem__", [](oofem::FloatMatrix &s, py::tuple indx, double v) { + s(((py::handle)(indx[0])).cast(), ((py::handle)(indx[1])).cast()) = v; + }) + .def("__getitem__", [](const oofem::FloatMatrix &s, py::tuple indx) { + if (((py::handle)(indx[0])).cast() >= s.giveNumberOfRows()) throw py::index_error(); + if (((py::handle)(indx[1])).cast() >= s.giveNumberOfColumns()) throw py::index_error(); + return s(((py::handle)(indx[0])).cast(), ((py::handle)(indx[1])).cast()); + }) + .def("__repr__", + [](const oofem::FloatMatrix &s) { + std::string a = " 40 ) { + a.append("..."); + break; + } else { + a.append(std::to_string(s(i,j))); + a.append(" "); + } + } + a.append("; "); + } + a.append("}>"); + return a; + }) + .def("resize", &oofem::FloatMatrix::resize) + .def("isSquare", &oofem::FloatMatrix::isSquare) + .def("assemble", (void (oofem::FloatMatrix::*)(const FloatMatrix &, const IntArray &)) &oofem::FloatMatrix::assemble, "Assembles the contribution to the receiver") + .def("assemble", (void (oofem::FloatMatrix::*)(const FloatMatrix &, const IntArray &, const IntArray&)) &oofem::FloatMatrix::assemble, "Assembles the contribution to the receiver") + .def("computeFrobeniusNorm", &oofem::FloatMatrix::computeFrobeniusNorm) + .def("computeNorm", &oofem::FloatMatrix::computeNorm) + .def("beDiagonal", &oofem::FloatMatrix::beDiagonal) + .def("giveTrace", &oofem::FloatMatrix::giveTrace) + .def("giveDeterminant", &oofem::FloatMatrix::giveDeterminant) + .def("zero", &oofem::FloatMatrix::zero) + .def("beUnitMatrix", &oofem::FloatMatrix::beUnitMatrix) + .def("beTranspositionOf", &oofem::FloatMatrix::beTranspositionOf) + .def("beProductOf", &oofem::FloatMatrix::beProductOf) + .def("addProductOf", &oofem::FloatMatrix::addProductOf) + .def("addTProductOf", &oofem::FloatMatrix::addTProductOf) + .def("beTProductOf", &oofem::FloatMatrix::beTProductOf) + .def("beProductTOf", &oofem::FloatMatrix::beProductTOf) + .def("beDyadicProductOf", &oofem::FloatMatrix::beDyadicProductOf) + .def("beInverseOf", &oofem::FloatMatrix::beInverseOf) + .def("solveForRhs", (bool (oofem::FloatMatrix::*)(const FloatArray &, FloatArray &, bool)) &oofem::FloatMatrix::solveForRhs) + .def("solveForRhs", (bool (oofem::FloatMatrix::*)(const FloatMatrix &, FloatMatrix &, bool)) &oofem::FloatMatrix::solveForRhs) + .def("plusProductSymmUpper", &oofem::FloatMatrix::plusProductSymmUpper) + .def("plusDyadSymmUpper", &oofem::FloatMatrix::plusDyadSymmUpper) + .def("plusProductUnsym", &oofem::FloatMatrix::plusProductUnsym) + .def("plusDyadUnsym", &oofem::FloatMatrix::plusDyadUnsym) + // expose FloatArray operators + .def(py::self + py::self) + .def(py::self - py::self) + .def(py::self * py::self) + .def(py::self * FloatArray()) + .def(py::self += py::self) + .def(py::self -= py::self) + ; + + py::class_(m, "IntArray") + + .def(py::init(), py::arg("n")=0) + .def(py::init()) + .def(py::init([](py::sequence s){ + oofem::IntArray* ans = new oofem::IntArray((int) py::len(s)); + for (unsigned int i=0; i(); + } + return ans; + } + )) + .def("resize", &oofem::IntArray::resize) + .def("clear", &oofem::IntArray::clear) + .def("preallocate", &oofem::IntArray::preallocate) + .def("followedBy", (void (oofem::IntArray::*)(int , int)) &oofem::IntArray::followedBy, "Appends number to receiver") + .def("followedBy", (void (oofem::IntArray::*)(const oofem::IntArray& , int)) &oofem::IntArray::followedBy, "Appends array to receiver") + .def("isEmpty", &oofem::IntArray::isEmpty) + .def("containsOnlyZeroes", &oofem::IntArray::containsOnlyZeroes) + .def("containsSorted", &oofem::IntArray::containsSorted) + .def("insertSorted", &oofem::IntArray::insertSorted) + .def("eraseSorted", &oofem::IntArray::eraseSorted) + .def("findFirstIndexOf", &oofem::IntArray::findFirstIndexOf, "Finds index of first occurrence of given value in array") + .def("contains", &oofem::IntArray::contains) + .def("sort", &oofem::IntArray::sort) + .def("zero", &oofem::IntArray::zero) + .def("pY", &oofem::IntArray::pY) + .def("__repr__", + [](const oofem::IntArray &s) { + std::string a = " 40 ) { + a.append("..."); + break; + } else { + a.append(std::to_string(s[i])); + a.append(", "); + } + } + a.append("}>"); + return a; + }) + .def("__setitem__", [](oofem::IntArray &s, size_t i, int v) { + s[i] = v; + }) + .def("__getitem__", [](const oofem::IntArray &s, size_t i) { + if (i >= (size_t) s.giveSize()) throw py::index_error(); + return s[i]; + }) + + ; + py::implicitly_convertible(); + + + py::class_(m, "DataReader") + ; + + py::class_(m, "OOFEMTXTDataReader") + .def(py::init()) + ; + + + py::class_(m, "InputRecord") + ; + + typedef const char *InputFieldType; + py::class_(m, "DynamicInputRecord") + .def(py::init(), py::arg("answer") = "", py::arg("value")=0) + .def("finish", &oofem::DynamicInputRecord::finish, py::arg("wrn")=true) + .def("setRecordKeywordField", &oofem::DynamicInputRecord::setRecordKeywordField) + .def("setRecordKeywordNumber", &oofem::DynamicInputRecord::setRecordKeywordNumber) + .def("setField", (void (oofem::DynamicInputRecord::*)(int, InputFieldType)) &oofem::DynamicInputRecord::setField) + .def("setField", (void (oofem::DynamicInputRecord::*)(double, InputFieldType)) &oofem::DynamicInputRecord::setField) + .def("setField", (void (oofem::DynamicInputRecord::*)(bool, InputFieldType)) &oofem::DynamicInputRecord::setField) + .def("setField", (void (oofem::DynamicInputRecord::*)(std::string, InputFieldType)) &oofem::DynamicInputRecord::setField) + .def("setField", (void (oofem::DynamicInputRecord::*)(oofem::FloatArray, InputFieldType)) &oofem::DynamicInputRecord::setField) + .def("setField", (void (oofem::DynamicInputRecord::*)(oofem::FloatMatrix, InputFieldType)) &oofem::DynamicInputRecord::setField) + .def("setField", (void (oofem::DynamicInputRecord::*)(oofem::FloatMatrix, InputFieldType)) &oofem::DynamicInputRecord::setField) + .def("setField", (void (oofem::DynamicInputRecord::*)(oofem::IntArray, InputFieldType)) &oofem::DynamicInputRecord::setField) + .def("setField", (void (oofem::DynamicInputRecord::*)(std::vector, InputFieldType)) &oofem::DynamicInputRecord::setField) + .def("setField", (void (oofem::DynamicInputRecord::*)(InputFieldType)) &oofem::DynamicInputRecord::setField) + ; + + py::class_(m, "OOFEMTXTInputRecord") + .def(py::init<>()) + .def(py::init()) + .def("finish", &oofem::OOFEMTXTInputRecord::finish, py::arg("wrn")=true) + .def("setRecordString", &oofem::OOFEMTXTInputRecord::setRecordString) + ; + + + py::class_>(m, "FEMComponent") + .def("giveClassName", &oofem::FEMComponent::giveClassName) + .def("giveInputRecordName", &oofem::FEMComponent::giveInputRecordName) + .def("giveDomain", &oofem::FEMComponent::giveDomain, py::return_value_policy::reference) + .def("setDomain", &oofem::FEMComponent::setDomain) + .def("giveNumber", &oofem::FEMComponent::giveNumber) + .def("setNumber", &oofem::FEMComponent::setNumber) + .def("checkConsistency", &oofem::FEMComponent::checkConsistency) + .def("printYourself", &oofem::FEMComponent::printYourself) + .def_property_readonly("number", &oofem::FEMComponent::giveNumber) + + ; + + py::class_(m, "MetaStep") + .def("setNumberOfSteps", &oofem::MetaStep::setNumberOfSteps) + .def("giveNumberOfSteps", &oofem::MetaStep::giveNumberOfSteps) + ; + + py::class_(m, "TimeStep") + .def(py::init()) + .def("giveNumber", &oofem::TimeStep::giveNumber) + .def("giveTargetTime", &oofem::TimeStep::giveTargetTime) + .def("giveIntrinsicTime", &oofem::TimeStep::giveIntrinsicTime) + .def("giveTimeIncrement", &oofem::TimeStep::giveTimeIncrement) + .def("setTimeIncrement", &oofem::TimeStep::setTimeIncrement) + .def("setTime", &oofem::TimeStep::setTime) + .def("setTargetTime", &oofem::TimeStep::setTargetTime) + .def("setIntrinsicTime", &oofem::TimeStep::setIntrinsicTime) + .def("isNotTheLastStep", &oofem::TimeStep::isNotTheLastStep) + .def("isTheFirstStep", &oofem::TimeStep::isTheFirstStep) + .def("isTheCurrentTimeStep", &oofem::TimeStep::isTheCurrentTimeStep) + ; + + py::class_(m, "FieldManager") + .def("registerField", &oofem::FieldManager::registerField, py::keep_alive<1, 2>()) + ; + + py::class_(m, "EngngModelContext") + .def("giveFieldManager", &oofem::EngngModelContext::giveFieldManager, py::return_value_policy::reference) + + ; + + py::class_>(m, "EngngModel") + .def(py::init()) + .def("giveDomain", &oofem::EngngModel::giveDomain, py::return_value_policy::reference) + .def("setDomain", &oofem::EngngModel::setDomain, py::keep_alive<1, 3>()) + .def("giveNumberOfDomains", &oofem::EngngModel::giveNumberOfDomains) + .def("setNumberOfDomains", &oofem::EngngModel::setNumberOfDomains) + .def("giveMetaStep", &oofem::EngngModel::giveMetaStep, py::return_value_policy::reference) + .def("terminateAnalysis", &oofem::EngngModel::terminateAnalysis) + .def("terminate", &oofem::EngngModel::terminate) + .def("solveYourself", &oofem::EngngModel::solveYourself) + .def("solveYourselfAt", &oofem::EngngModel::solveYourselfAt) + .def("terminate",&oofem::EngngModel::terminate) + .def("giveField", &oofem::EngngModel::giveField) + .def("giveLoadLevel", &oofem::EngngModel::giveLoadLevel) + //.def("giveCurrentStep", &oofem::EngngModel::giveCurrentStep, py::return_value_policy::reference) + .def("giveCurrentStep", &oofem::EngngModel::giveCurrentStep, py::return_value_policy::reference, py::arg("force") = false) + .def("givePreviousStep", &oofem::EngngModel::givePreviousStep, py::return_value_policy::reference) + .def("giveNextStep", &oofem::EngngModel::giveNextStep, py::return_value_policy::reference) + .def("giveNumberOfSteps", &oofem::EngngModel::giveNumberOfSteps, py::arg("force")=false) + .def("giveUnknownComponent", &oofem::EngngModel::giveUnknownComponent) + .def("checkProblemConsistency", &oofem::EngngModel::checkProblemConsistency) + .def("giveTimer", &oofem::EngngModel::giveTimer, py::return_value_policy::reference) + .def("init", &oofem::EngngModel::init) + .def("initializeYourself", &oofem::EngngModel::initializeYourself) + .def("initMetaStepAttributes", &oofem::EngngModel::initMetaStepAttributes) + .def("preInitializeNextStep", &oofem::EngngModel::preInitializeNextStep) + .def("updateYourself", &oofem::EngngModel::updateYourself) + .def("postInitialize", &oofem::EngngModel::postInitialize) + .def("setRenumberFlag", &oofem::EngngModel::setRenumberFlag) + .def("giveContext", &oofem::EngngModel::giveContext, py::return_value_policy::reference) + .def("forceEquationNumbering", py::overload_cast(&oofem::EngngModel::forceEquationNumbering)) + .def("forceEquationNumbering", py::overload_cast<>(&oofem::EngngModel::forceEquationNumbering)) + .def("giveNumberOfDomainEquations", &oofem::EngngModel::giveNumberOfDomainEquations) + .def("Instanciate_init", &oofem::EngngModel::Instanciate_init) + .def_property("ndomains", &oofem::EngngModel::getNumberOfDomains, &oofem::EngngModel::setNumberOfDomains) + ; + + py::class_(m, "StaggeredProblem") + .def("giveSlaveProblem", &oofem::StaggeredProblem::giveSlaveProblem, py::return_value_policy::reference) + .def("giveTimeControl", &oofem::StaggeredProblem::giveTimeControl, py::return_value_policy::reference) + ; + + py::class_(m, "Domain") + .def(py::init()) + .def("giveNumber", &oofem::Domain::giveNumber) + .def("setNumber", &oofem::Domain::setNumber) + .def("giveDofManager", &oofem::Domain::giveDofManager, py::return_value_policy::reference) + //.def("giveDofManagers", &oofem::Domain::giveDofManagers) + .def("giveElement", &oofem::Domain::giveElement, py::return_value_policy::reference) + //.def("giveElements", &oofem::Domain::giveElements, py::return_value_policy::reference) + .def("giveGlobalDofManager", &oofem::Domain::giveGlobalDofManager, py::return_value_policy::reference) + .def("giveNumberOfElements", &oofem::Domain::giveNumberOfElements) + .def("giveNumberOfDofManagers", &oofem::Domain::giveNumberOfDofManagers) + .def("giveNumberOfBoundaryConditions", &oofem::Domain::giveNumberOfBoundaryConditions) + .def("giveNumberOfFunctions", &oofem::Domain::giveNumberOfFunctions) + .def("giveNumberOfMaterialModels", &oofem::Domain::giveNumberOfMaterialModels) + .def("giveNumberOfCrossSectionModels", &oofem::Domain::giveNumberOfCrossSectionModels) + .def("giveNumberOfInitialConditions", &oofem::Domain::giveNumberOfInitialConditions) + .def("giveNumberOfRegions", &oofem::Domain::giveNumberOfRegions) + .def("giveNumberOfNonlocalBarriers", &oofem::Domain::giveNumberOfNonlocalBarriers) + .def("giveNumberOfSets", &oofem::Domain::giveNumberOfSets) + .def("giveBc", &oofem::Domain::giveBc, py::return_value_policy::reference) + .def("giveIc", &oofem::Domain::giveIc, py::return_value_policy::reference) + .def("giveFunction", &oofem::Domain::giveFunction, py::return_value_policy::reference) + .def("giveMaterial", &oofem::Domain::giveMaterial, py::return_value_policy::reference) + .def("giveCrossSection", &oofem::Domain::giveCrossSection, py::return_value_policy::reference) + .def("resizeDofManagers", &oofem::Domain::resizeDofManagers) + .def("setDofManager", &oofem::Domain::py_setDofManager, py::keep_alive<0, 2>()) + .def("resizeElements", &oofem::Domain::resizeElements) + .def("setElement", &oofem::Domain::py_setElement, py::keep_alive<0, 2>()) + .def("resizeMaterials", &oofem::Domain::resizeMaterials) + .def("setMaterial", &oofem::Domain::py_setMaterial, py::keep_alive<0, 2>()) + .def("resizeCrossSectionModels", &oofem::Domain::resizeCrossSectionModels) + .def("setCrossSection", &oofem::Domain::py_setCrossSection, py::keep_alive<0, 2>()) + .def("resizeBoundaryConditions", &oofem::Domain::resizeBoundaryConditions) + .def("setBoundaryCondition", &oofem::Domain::py_setBoundaryCondition, py::keep_alive<0, 2>()) + .def("resizeInitialConditions", &oofem::Domain::resizeInitialConditions) + .def("setInitialCondition", &oofem::Domain::py_setInitialCondition, py::keep_alive<0, 2>()) + .def("resizeFunctions", &oofem::Domain::resizeFunctions) + .def("setFunction", &oofem::Domain::py_setFunction, py::keep_alive<0, 2>()) + .def("resizeSets", &oofem::Domain::resizeSets) + .def("setSet", &oofem::Domain::py_setSet, py::keep_alive<0, 2>()) + ; + + py::class_(m, "Dof") + .def("giveDofManNumber", &oofem::Dof::giveDofManNumber) + .def("giveDofManager", &oofem::Dof::giveDofManager, py::return_value_policy::reference) + .def("giveDofManGlobalNumber", &oofem::Dof::giveDofManGlobalNumber) + .def("giveUnknown", (double (oofem::Dof::*)(oofem::ValueModeType, oofem::TimeStep*)) &oofem::Dof::giveUnknown) + .def("giveDofID", &oofem::Dof::giveDofID) + .def("printYourself", &oofem::Dof::printYourself) + .def("giveEquationNumber", &oofem::Dof::giveEquationNumber) + ; + + py::class_(m, "DofManager") + .def("giveDofWithID", &oofem::DofManager::giveDofWithID, py::return_value_policy::reference) + .def("giveNumberOfDofs", &oofem::DofManager::giveNumberOfDofs) + .def("giveUnknownVector", (void (oofem::DofManager::*)(oofem::FloatArray&, const oofem::IntArray&, oofem::ValueModeType, oofem::TimeStep*, bool)) &oofem::DofManager::giveUnknownVector) + .def("givePrescribedUnknownVector", &oofem::DofManager::givePrescribedUnknownVector) + .def("giveCoordinates", &oofem::DofManager::giveCoordinates, py::return_value_policy::reference) + .def("appendDof", &oofem::DofManager::appendDof, py::keep_alive<1, 2>()) + .def("removeDof", &oofem::DofManager::removeDof) + .def("hasDofID", &oofem::DofManager::hasDofID) + .def("giveGlobalNumber", &oofem::DofManager::giveGlobalNumber) + ; + + /* + Element + */ + + py::class_>(m, "Element") + .def(py::init()) + .def("giveLocationArray", (void (oofem::Element::*)(oofem::IntArray &, const oofem::UnknownNumberingScheme &, oofem::IntArray *dofIds) const) &oofem::Element::giveLocationArray) + .def("giveLocationArray", (void (oofem::Element::*)(oofem::IntArray &, const oofem::IntArray &, const oofem::UnknownNumberingScheme &, oofem::IntArray *) const) &oofem::Element::giveLocationArray) + .def("giveCharacteristicMatrix", &oofem::Element::giveCharacteristicMatrix) + .def("giveCharacteristicVector", &oofem::Element::giveCharacteristicVector) + //.def("giveCharacteristicValue", &oofem::Element::giveCharacteristicValue) + .def("computeVectorOf", (void (oofem::Element::*)(oofem::ValueModeType , oofem::TimeStep *, oofem::FloatArray &)) &oofem::Element::computeVectorOf) + .def("computeVectorOf", (void (oofem::Element::*)(const oofem::IntArray &, oofem::ValueModeType , oofem::TimeStep*, oofem::FloatArray &, bool)) &oofem::Element::computeVectorOf) + .def("computeVectorOfPrescribed", (void (oofem::Element::*)(oofem::ValueModeType , oofem::TimeStep *, oofem::FloatArray &)) &oofem::Element::computeVectorOfPrescribed) + .def("computeVectorOfPrescribed", (void (oofem::Element::*)(const oofem::IntArray &, oofem::ValueModeType , oofem::TimeStep *, oofem::FloatArray & )) &oofem::Element::computeVectorOfPrescribed) + .def("giveDofManagerNumber", &oofem::Element::giveDofManagerNumber) + .def("giveDofManArray", &oofem::Element::giveDofManArray, py::return_value_policy::reference) + .def("giveDofManager", &oofem::Element::giveDofManager, py::return_value_policy::reference) + .def("giveMaterial", &oofem::Element::giveMaterial, py::return_value_policy::reference) + .def("giveCrossSection", &oofem::Element::giveCrossSection, py::return_value_policy::reference) + .def("giveMaterialNumber", &oofem::Element::giveMaterialNumber) + .def("giveNumberOfDofManagers", &oofem::Element::giveNumberOfDofManagers) + .def("giveNumberOfNodes", &oofem::Element::giveNumberOfNodes) + .def("giveRegionNumber", &oofem::Element::giveRegionNumber) + .def("giveNode", &oofem::Element::giveNode) + .def("updateYourself", &oofem::Element::updateYourself) + .def("isActivated", &oofem::Element::isActivated) + .def("isCast", &oofem::Element::isCast) + .def("giveGeometryType", &oofem::Element::giveGeometryType) + .def("giveIntegrationRule", &oofem::Element::giveIntegrationRule, py::return_value_policy::reference) + .def("giveDefaultIntegrationRulePtr", &oofem::Element::giveDefaultIntegrationRulePtr, py::return_value_policy::reference) + .def("giveIPValue", &oofem::Element::giveIPValue) + .def("giveLabel", &oofem::Element::giveLabel) + .def("initializeFrom", &oofem::Element::initializeFrom) + .def("postInitialize", &oofem::Element::postInitialize) + .def("setDofManagers", &oofem::Element::setDofManagers) + .def("setNumberOfDofManagers", &oofem::Element::setNumberOfDofManagers) + .def("giveDofManDofIDMask", &oofem::Element::giveDofManDofIDMask) + .def("getActivityTimeFunctionNumber", &oofem::Element::getActivityTimeFunctionNumber) + .def("setActivityTimeFunctionNumber", &oofem::Element::setActivityTimeFunctionNumber) + ; + + py::class_>(m, "StructuralElement") + .def(py::init()) + .def("giveDofManDofIDMask", &oofem::StructuralElement::giveDofManDofIDMask) + ; + + + py::class_(m, "GeneralBoundaryCondition") + .def("getIsImposedTimeFunctionNumber", &oofem::GeneralBoundaryCondition::getIsImposedTimeFunctionNumber) + .def("setIsImposedTimeFunctionNumber", &oofem::GeneralBoundaryCondition::setIsImposedTimeFunctionNumber) + ; + + + py::class_(m, "BoundaryCondition") + .def("setPrescribedValue", &oofem::BoundaryCondition::setPrescribedValue) + ; + + py::class_(m, "InitialCondition") + ; + +// py::class_(m, "Timer") +// ; + + py::class_ (m, "EngngModelTimer") + .def("startTimer", &oofem::EngngModelTimer::startTimer) + .def("stopTimer", &oofem::EngngModelTimer::stopTimer) + .def("getUtime", &oofem::EngngModelTimer::getUtime) + ; + + py::enum_(m, "EngngModelTimerType") + .value("EMTT_AnalysisTimer", oofem::EngngModelTimer::EMTT_AnalysisTimer) + .value("EMTT_SolutionStepTimer", oofem::EngngModelTimer::EMTT_SolutionStepTimer) + .value("EMTT_NetComputationalStepTimer", oofem::EngngModelTimer::EMTT_NetComputationalStepTimer) + .value("EMTT_LoadBalancingTimer", oofem::EngngModelTimer::EMTT_LoadBalancingTimer) + .value("EMTT_DataTransferTimer", oofem::EngngModelTimer::EMTT_DataTransferTimer) + .value("EMTT_LastTimer", oofem::EngngModelTimer::EMTT_LastTimer) + .export_values() + ; + + + /* + Function class + */ + + /* Trampoline classes allowing to define custom derived types from within Python */ + class PyFunction : public oofem::Function { + // inherit the constructor + using oofem::Function::Function; + // trampoline (need one for each virtual method) + double evaluateAtTime(double t) override { + PYBIND11_OVERLOAD ( + double, // return type + oofem::Function, // parent class + evaluateAtTime, // name of method in c++ (must match python name) + t // argument(s) + ); + } + double evaluateVelocityAtTime(double t) override { + PYBIND11_OVERLOAD_PURE( + double, + oofem::Function, + evaluateVelocityAtTime, + t + ) + } + double evaluateAccelerationAtTime(double t) override { + PYBIND11_OVERLOAD_PURE( + double, + oofem::Function, + evaluateAccelerationAtTime, + t + ) + } + const char* giveClassName() const override { + PYBIND11_OVERLOAD_PURE( + const char*, + oofem::Function, + giveClassName, + ) + } + const char* giveInputRecordName() const override { + PYBIND11_OVERLOAD_PURE( + const char*, + oofem::Function, + giveInputRecordName, + ) + } + + + }; + + py::class_(m, "Function") + .def(py::init()) + .def("evaluate", (double (oofem::Function::*)(TimeStep *, ValueModeType)) &oofem::Function::evaluate) + //abstract services + .def ("evaluateAtTime", &oofem::Function::evaluateAtTime) + .def ("evaluateVelocityAtTime", &oofem::Function::evaluateVelocityAtTime) + .def ("evaluateAccelerationAtTime", &oofem::Function::evaluateVelocityAtTime) + ; + + py::class_>(m, "IntegrationPointStatus") + .def(py::init()) + .def("giveClassName", &oofem::IntegrationPointStatus::giveClassName) + ; + py::class_>(m, "MaterialStatus") + .def(py::init()) + ; + + py::class_>(m, "StructuralMaterialStatus") + .def(py::init()) + .def("giveStrainVector", &oofem::StructuralMaterialStatus::giveStrainVector) + .def("giveStressVector", &oofem::StructuralMaterialStatus::giveStressVector) + .def("letTempStressVectorBe", &oofem::StructuralMaterialStatus::letTempStressVectorBe) + .def("letTempStrainVectorBe", &oofem::StructuralMaterialStatus::letTempStrainVectorBe) + ; + + py::class_(m, "Material") + .def("giveStatus", &oofem::Material::giveStatus, py::return_value_policy::reference) + .def("CreateStatus", &oofem::Material::CreateStatus, py::return_value_policy::reference) + .def("giveIPValue", &oofem::Material::giveIPValue) + ; + + py::class_>(m, "StructuralMaterial") + .def(py::init()) + .def("giveStatus", &oofem::StructuralMaterial::giveStatus, py::return_value_policy::reference) + .def("CreateStatus", &oofem::StructuralMaterial::CreateStatus, py::return_value_policy::reference) + ; + + py::class_(m, "CrossSection") + ; + + py::class_(m, "Set") + ; + + + py::class_(m, "UnknownNumberingScheme") + .def("init", &oofem::UnknownNumberingScheme::init) + .def("giveDofEquationNumber", &oofem::UnknownNumberingScheme::giveDofEquationNumber) + ; + + py::class_(m,"EModelDefaultEquationNumbering") + .def(py::init<>()) + ; + + py::class_(m, "IntegrationRule") + .def("giveNumberOfIntegrationPoints", &oofem::IntegrationRule::giveNumberOfIntegrationPoints) + .def("getIntegrationPoint", &oofem::IntegrationRule::getIntegrationPoint, py::return_value_policy::reference) + ; + py::class_(m, "GaussPoint") + .def ("giveMaterialStatus", (const oofem::IntegrationPointStatus* (oofem::GaussPoint::*)() const) &oofem::GaussPoint::giveMaterialStatus, py::return_value_policy::reference) + .def ("setMaterialStatus", (oofem::IntegrationPointStatus* (oofem::GaussPoint::*)(oofem::IntegrationPointStatus*)) &oofem::GaussPoint::setMaterialStatus, py::keep_alive<0, 2>()) + ; + + py::class_(m, "ExportModule") + .def("initialize", &oofem::ExportModule::initialize) + .def("doOutput", &oofem::ExportModule::doOutput) + .def("terminate", &oofem::ExportModule::terminate) + ; + + py::class_(m, "HOMExportModule") + ; + + py::class_(m, "VTKPiece") + .def("giveNumberOfNodes", &oofem::VTKPiece::giveNumberOfNodes) + .def("giveNodeCoords", &oofem::VTKPiece::giveNodeCoords) + .def("giveNumberOfCells", &oofem::VTKPiece::giveNumberOfCells) + .def("giveCellConnectivity", &oofem::VTKPiece::giveCellConnectivity) + .def("giveCellType", &oofem::VTKPiece::giveCellType) + .def("giveCellOffset", &oofem::VTKPiece::giveCellOffset) + .def("givePrimaryVarInNode", &oofem::VTKPiece::givePrimaryVarInNode) + .def("giveInternalVarInNode", &oofem::VTKPiece::giveInternalVarInNode) + .def("giveCellVar", &oofem::VTKPiece::giveCellVar) + + .def("getVertices", &oofem::VTKPiece::getVertices, py::return_value_policy::move) + .def("getCellConnectivity", &oofem::VTKPiece::getCellConnectivity, py::return_value_policy::move) + .def("getCellTypes", &oofem::VTKPiece::getCellTypes, py::return_value_policy::move) + .def("getPrimaryVertexValues", &oofem::VTKPiece::getPrimaryVertexValues, py::return_value_policy::move) + .def("getInternalVertexValues", &oofem::VTKPiece::getInternalVertexValues, py::return_value_policy::move) + .def("getCellValues", &oofem::VTKPiece::getCellValues, py::return_value_policy::move) + ; + + py::class_(m, "VTKBaseExportModule") + ; + + py::class_(m, "VTKXMLExportModule") + .def("getVTKPieces", &oofem::VTKXMLExportModule::getVTKPieces, py::return_value_policy::reference) + ; + + py::class_(m, "VTKMemoryExportModule") + .def("getVTKPieces", &oofem::VTKMemoryExportModule::getVTKPieces, py::return_value_policy::reference) + ; + + py::class_(m, "SparseMtrx") + .def("giveNumberOfRows", &oofem::SparseMtrx::giveNumberOfRows) + .def("giveNumberOfColumns", &oofem::SparseMtrx::giveNumberOfColumns) + .def("times", (void (oofem::SparseMtrx::*)(const FloatArray&, FloatArray&)const) &oofem::SparseMtrx::times) + .def("timesT", (void (oofem::SparseMtrx::*)(const FloatArray &, FloatArray &)const) &oofem::SparseMtrx::timesT) + .def("times", (void (oofem::SparseMtrx::*)(const FloatMatrix &, FloatMatrix &)const) &oofem::SparseMtrx::times) + .def("timesT", (void (oofem::SparseMtrx::*)(const FloatMatrix &, FloatMatrix &)const) &oofem::SparseMtrx::timesT) + .def("times", (void (oofem::SparseMtrx::*)(double)) &oofem::SparseMtrx::times) + .def("add", &oofem::SparseMtrx::add) + .def("addDiagonal", &oofem::SparseMtrx::addDiagonal) + .def("buildInternalStructure", (int (oofem::SparseMtrx::*)(EngngModel *, int , int , const IntArray &, const IntArray &)) &oofem::SparseMtrx::buildInternalStructure) + .def("buildInternalStructure", (int (oofem::SparseMtrx::*)(EngngModel *, int , const UnknownNumberingScheme &)) &oofem::SparseMtrx::buildInternalStructure) + .def("buildInternalStructure", (int (oofem::SparseMtrx::*)(EngngModel *, int , const UnknownNumberingScheme &,const UnknownNumberingScheme &)) &oofem::SparseMtrx::buildInternalStructure) + .def("assemble", (int (oofem::SparseMtrx::*)(const IntArray &, const FloatMatrix &))&oofem::SparseMtrx::assemble) + .def("assemble", (int (oofem::SparseMtrx::*)(const IntArray &, const IntArray &, const FloatMatrix &))&oofem::SparseMtrx::assemble) + .def("at", (double (oofem::SparseMtrx::*)(int , int )const) &oofem::SparseMtrx::at) + .def("at", (double& (oofem::SparseMtrx::*)(int , int )) &oofem::SparseMtrx::at) + .def("printYourself", &oofem::SparseMtrx::printYourself) + ; + + + py::class_(m, "ClassFactory") + .def("createElement", &oofem::ClassFactory::createElement) + .def("createEngngModel", &oofem::ClassFactory::createEngngModel) + ; + + m.def("getClassFactory", &oofem::GiveClassFactory, py::return_value_policy::reference); + m.def("InstanciateProblem", &oofem::InstanciateProblem); + //std::unique_ptr InstanciateProblem(DataReader &dr, problemMode mode, int contextFlag, EngngModel *master = 0, bool parallelFlag = false); + + py::enum_(m, "FieldType") + .value("FT_Unknown", oofem::FieldType::FT_Unknown) + .value("FT_Velocity", oofem::FieldType::FT_Velocity) + .value("FT_Displacements", oofem::FieldType::FT_Displacements) + .value("FT_VelocityPressure", oofem::FieldType::FT_VelocityPressure) + .value("FT_Pressure", oofem::FieldType::FT_Pressure) + .value("FT_Temperature", oofem::FieldType::FT_Temperature) + .value("FT_HumidityConcentration", oofem::FieldType::FT_HumidityConcentration) + .value("FT_TransportProblemUnknowns", oofem::FieldType::FT_TransportProblemUnknowns) + .value("FT_TemperatureAmbient", oofem::FieldType::FT_TemperatureAmbient) + ; + + + py::enum_(m, "UnknownType") + .value("DisplacementVector", oofem::UnknownType::DisplacementVector) + .value("Temperature", oofem::UnknownType::Temperature) + ; + + py::enum_(m, "ValueModeType") + .value("VM_Unknown", oofem::ValueModeType::VM_Unknown) + .value("VM_Total", oofem::ValueModeType::VM_Total) + .value("VM_Velocity", oofem::ValueModeType::VM_Velocity) + .value("VM_Acceleration", oofem::ValueModeType::VM_Acceleration) + .value("VM_Incremental", oofem::ValueModeType::VM_Incremental) + .value("VM_RhsTotal", oofem::ValueModeType::VM_RhsTotal) + .value("VM_RhsIncremental", oofem::ValueModeType::VM_RhsIncremental) + .value("VM_RhsInitial", oofem::ValueModeType::VM_RhsInitial) + .value("VM_Intermediate", oofem::ValueModeType::VM_Intermediate) + .value("VM_TotalIntrinsic", oofem::ValueModeType::VM_TotalIntrinsic) + ; + + py::enum_(m, "DofIDItem") + .value("Undef", oofem::DofIDItem::Undef) + .value("D_u", oofem::DofIDItem::D_u) + .value("D_v", oofem::DofIDItem::D_v) + .value("D_w", oofem::DofIDItem::D_w) + .value("R_u", oofem::DofIDItem::R_u) + .value("R_v", oofem::DofIDItem::R_v) + .value("R_w", oofem::DofIDItem::R_w) + .value("V_u", oofem::DofIDItem::V_u) + .value("V_v", oofem::DofIDItem::V_v) + .value("V_w", oofem::DofIDItem::V_w) + .value("T_f", oofem::DofIDItem::T_f) + .value("P_f", oofem::DofIDItem::P_f) + .value("G_0", oofem::DofIDItem::G_0) + .value("G_1", oofem::DofIDItem::G_1) + .value("C_1", oofem::DofIDItem::C_1) + .value("W_u", oofem::DofIDItem::W_u) + .value("W_v", oofem::DofIDItem::W_v) + .value("W_w", oofem::DofIDItem::W_w) + .value("Gamma", oofem::DofIDItem::Gamma) + .value("D_u_edge_const", oofem::DofIDItem::D_u_edge_const) + .value("D_u_edge_lin", oofem::DofIDItem::D_u_edge_lin) + .value("D_v_edge_const", oofem::DofIDItem::D_v_edge_const) + .value("D_v_edge_lin", oofem::DofIDItem::D_v_edge_lin) + .value("Warp_PsiTheta", oofem::DofIDItem::Warp_PsiTheta) + .value("Warp_Theta", oofem::DofIDItem::Warp_Theta) + .value("LMP_u", oofem::DofIDItem::LMP_u) + .value("LMP_v", oofem::DofIDItem::LMP_v) + .value("LMP_w", oofem::DofIDItem::LMP_w) + .value("Trac_u", oofem::DofIDItem::Trac_u) + .value("Trac_v", oofem::DofIDItem::Trac_v) + .value("Trac_w", oofem::DofIDItem::Trac_w) + ; + + py::enum_(m, "problemMode") + .value("processor", oofem::problemMode::_processor) + .value("postProcessor", oofem::problemMode::_postProcessor) + ; + + py::enum_(m, "domainType") + .value("_unknownMode", oofem::domainType::_unknownMode) + .value("_2dPlaneStressMode", oofem::domainType::_2dPlaneStressMode) + .value("_PlaneStrainMode", oofem::domainType::_PlaneStrainMode) + .value("_2dPlaneStressRotMode", oofem::domainType::_2dPlaneStressRotMode) + .value("_3dMode", oofem::domainType::_3dMode) + .value("_3dAxisymmMode", oofem::domainType::_3dAxisymmMode) + .value("_2dMindlinPlateMode", oofem::domainType::_2dMindlinPlateMode) + .value("_3dDegeneratedShellMode", oofem::domainType::_3dDegeneratedShellMode) + .value("_3dShellMode", oofem::domainType::_3dShellMode) + .value("_2dTrussMode", oofem::domainType::_2dTrussMode) + .value("_1dTrussMode", oofem::domainType::_1dTrussMode) + .value("_2dBeamMode", oofem::domainType::_2dBeamMode) + .value("_HeatTransferMode", oofem::domainType::_HeatTransferMode) + .value("_Mass1TransferMode", oofem::domainType::_Mass1TransferMode) + .value("_HeatMass1Mode", oofem::domainType::_HeatMass1Mode) + .value("_2dIncompressibleFlow", oofem::domainType::_2dIncompressibleFlow) + .value("_3dIncompressibleFlow", oofem::domainType::_3dIncompressibleFlow) + .value("_2dLatticeMode", oofem::domainType::_2dLatticeMode) + .value("_2dLatticeMassTransportMode", oofem::domainType::_2dLatticeMassTransportMode) + .value("_3dLatticeMode", oofem::domainType::_3dLatticeMode) + .value("_3dLatticeMassTransportMode", oofem::domainType::_3dLatticeMassTransportMode) + .value("_2dLatticeHeatTransferMode", oofem::domainType::_2dLatticeHeatTransferMode) + .value("_3dLatticeHeatTransferMode", oofem::domainType::_3dLatticeHeatTransferMode) + .value("_3dDirShellMode", oofem::domainType::_3dDirShellMode) + .value("_WarpingMode", oofem::domainType::_WarpingMode) + ; + + + + py::enum_(m, "CharType") + .value("UnknownCharType", oofem::CharType::UnknownCharType) + .value("StiffnessMatrix", oofem::CharType::StiffnessMatrix) + .value("TangentStiffnessMatrix", oofem::CharType::TangentStiffnessMatrix) + .value("SecantStiffnessMatrix", oofem::CharType::SecantStiffnessMatrix) + .value("ElasticStiffnessMatrix", oofem::CharType::ElasticStiffnessMatrix) + .value("MassMatrix", oofem::CharType::MassMatrix) + .value("LumpedMassMatrix", oofem::CharType::LumpedMassMatrix) + .value("ConductivityMatrix", oofem::CharType::ConductivityMatrix) + .value("CapacityMatrix", oofem::CharType::CapacityMatrix) + .value("InitialStressMatrix", oofem::CharType::InitialStressMatrix) + .value("ExternalForcesVector", oofem::CharType::ExternalForcesVector) + .value("InternalForcesVector", oofem::CharType::InternalForcesVector) + .value("LastEquilibratedInternalForcesVector", oofem::CharType::LastEquilibratedInternalForcesVector) + .value("InertiaForcesVector", oofem::CharType::InertiaForcesVector) + .value("AuxVelocityLhs", oofem::CharType::AuxVelocityLhs) + .value("VelocityLhs", oofem::CharType::VelocityLhs) + .value("PressureGradientMatrix", oofem::CharType::PressureGradientMatrix) + .value("DivergenceMatrix", oofem::CharType::DivergenceMatrix) + .value("VelocityLaplacianMatrix", oofem::CharType::VelocityLaplacianMatrix) + .value("PressureLaplacianMatrix", oofem::CharType::PressureLaplacianMatrix) + .value("StabilizationMassMatrix", oofem::CharType::StabilizationMassMatrix) + .value("PressureGradientVector", oofem::CharType::PressureGradientVector) + .value("MassVelocityVector", oofem::CharType::MassVelocityVector) + .value("MassAuxVelocityVector", oofem::CharType::MassAuxVelocityVector) + .value("LaplacePressureVector", oofem::CharType::LaplacePressureVector) + .value("LaplaceVelocityVector", oofem::CharType::LaplaceVelocityVector) + .value("DivergenceAuxVelocityVector", oofem::CharType::DivergenceAuxVelocityVector) + .value("DivergenceVelocityVector", oofem::CharType::DivergenceVelocityVector) + ; + + py::enum_(m, "Element_Geometry_Type") + .value("EGT_point", oofem::Element_Geometry_Type::EGT_point) + .value("EGT_line_1", oofem::Element_Geometry_Type::EGT_line_1) + .value("EGT_line_2", oofem::Element_Geometry_Type::EGT_line_2) + .value("EGT_triangle_1", oofem::Element_Geometry_Type::EGT_triangle_1) + .value("EGT_triangle_2", oofem::Element_Geometry_Type::EGT_triangle_2) + .value("EGT_quad_1", oofem::Element_Geometry_Type::EGT_quad_1) + .value("EGT_quad_1_interface", oofem::Element_Geometry_Type::EGT_quad_1_interface) + .value("EGT_quad_21_interface", oofem::Element_Geometry_Type::EGT_quad_21_interface) + .value("EGT_quad_2", oofem::Element_Geometry_Type::EGT_quad_2) + .value("EGT_quad9_2", oofem::Element_Geometry_Type::EGT_quad9_2) + .value("EGT_tetra_1", oofem::Element_Geometry_Type::EGT_tetra_1) + .value("EGT_tetra_2", oofem::Element_Geometry_Type::EGT_tetra_2) + .value("EGT_hexa_1", oofem::Element_Geometry_Type::EGT_hexa_1) + .value("EGT_hexa_2", oofem::Element_Geometry_Type::EGT_hexa_2) + .value("EGT_hexa_27", oofem::Element_Geometry_Type::EGT_hexa_27) + .value("EGT_wedge_1", oofem::Element_Geometry_Type::EGT_wedge_1) + .value("EGT_wedge_2", oofem::Element_Geometry_Type::EGT_wedge_2) + .value("EGT_Composite", oofem::Element_Geometry_Type::EGT_Composite) + .value("EGT_unknown", oofem::Element_Geometry_Type::EGT_unknown) + ; + + py::enum_(m, "InternalStateType") + .value("IST_Undefined", oofem::InternalStateType::IST_Undefined) + .value("IST_StressTensor", oofem::InternalStateType::IST_StressTensor) + .value("IST_PrincipalStressTensor", oofem::InternalStateType::IST_PrincipalStressTensor) + .value("IST_PrincipalStressTempTensor", oofem::InternalStateType::IST_PrincipalStressTempTensor) + .value("IST_StrainTensor", oofem::InternalStateType::IST_StrainTensor) + .value("IST_PrincipalStrainTensor", oofem::InternalStateType::IST_PrincipalStrainTensor) + .value("IST_PrincipalStrainTempTensor", oofem::InternalStateType::IST_PrincipalStrainTempTensor) + .value("IST_BeamForceMomentTensor", oofem::InternalStateType::IST_BeamForceMomentTensor) + .value("IST_BeamStrainCurvatureTensor", oofem::InternalStateType::IST_BeamStrainCurvatureTensor) + .value("IST_ShellMomentTensor", oofem::InternalStateType::IST_ShellMomentTensor) + .value("IST_ShellForceTensor", oofem::InternalStateType::IST_ShellForceTensor) + .value("IST_CurvatureTensor", oofem::InternalStateType::IST_CurvatureTensor) + .value("IST_DisplacementVector", oofem::InternalStateType::IST_DisplacementVector) + .value("IST_DamageTensor", oofem::InternalStateType::IST_DamageTensor) + .value("IST_DamageInvTensor", oofem::InternalStateType::IST_DamageInvTensor) + .value("IST_PrincipalDamageTensor", oofem::InternalStateType::IST_PrincipalDamageTensor) + .value("IST_PrincipalDamageTempTensor", oofem::InternalStateType::IST_PrincipalDamageTempTensor) + .value("IST_CrackState", oofem::InternalStateType::IST_CrackState) + .value("IST_StressTensorTemp", oofem::InternalStateType::IST_StressTensorTemp) + .value("IST_StrainTensorTemp", oofem::InternalStateType::IST_StrainTensorTemp) + .value("IST_ShellForceTensorTemp", oofem::InternalStateType::IST_ShellForceTensorTemp) + .value("IST_ShellMomentTensorTemp", oofem::InternalStateType::IST_ShellMomentTensorTemp) + .value("IST_CurvatureTensorTemp", oofem::InternalStateType::IST_CurvatureTensorTemp) + .value("IST_DisplacementVectorTemp", oofem::InternalStateType::IST_DisplacementVectorTemp) + .value("IST_DamageTensorTemp", oofem::InternalStateType::IST_DamageTensorTemp) + .value("IST_DamageInvTensorTemp", oofem::InternalStateType::IST_DamageInvTensorTemp) + .value("IST_CrackStateTemp", oofem::InternalStateType::IST_CrackStateTemp) + .value("IST_PlasticStrainTensor", oofem::InternalStateType::IST_PlasticStrainTensor) + .value("IST_PrincipalPlasticStrainTensor", oofem::InternalStateType::IST_PrincipalPlasticStrainTensor) + .value("IST_CylindricalStressTensor", oofem::InternalStateType::IST_CylindricalStressTensor) + .value("IST_CylindricalStrainTensor", oofem::InternalStateType::IST_CylindricalStrainTensor) + .value("IST_MaxEquivalentStrainLevel", oofem::InternalStateType::IST_MaxEquivalentStrainLevel) + .value("IST_ErrorIndicatorLevel", oofem::InternalStateType::IST_ErrorIndicatorLevel) + .value("IST_InternalStressError", oofem::InternalStateType::IST_InternalStressError) + .value("IST_PrimaryUnknownError", oofem::InternalStateType::IST_PrimaryUnknownError) + .value("IST_RelMeshDensity", oofem::InternalStateType::IST_RelMeshDensity) + .value("IST_MicroplaneDamageValues", oofem::InternalStateType::IST_MicroplaneDamageValues) + .value("IST_Temperature", oofem::InternalStateType::IST_Temperature) + .value("IST_MassConcentration_1", oofem::InternalStateType::IST_MassConcentration_1) + .value("IST_HydrationDegree", oofem::InternalStateType::IST_HydrationDegree) + .value("IST_Humidity", oofem::InternalStateType::IST_Humidity) + .value("IST_Velocity", oofem::InternalStateType::IST_Velocity) + .value("IST_Pressure", oofem::InternalStateType::IST_Pressure) + .value("IST_VOFFraction", oofem::InternalStateType::IST_VOFFraction) + .value("IST_Density", oofem::InternalStateType::IST_Density) + .value("IST_MaterialInterfaceVal", oofem::InternalStateType::IST_MaterialInterfaceVal) + .value("IST_MaterialNumber", oofem::InternalStateType::IST_MaterialNumber) + .value("IST_ElementNumber", oofem::InternalStateType::IST_ElementNumber) + .value("IST_BoneVolumeFraction", oofem::InternalStateType::IST_BoneVolumeFraction) + .value("IST_PlasStrainEnerDens", oofem::InternalStateType::IST_PlasStrainEnerDens) + .value("IST_ElasStrainEnerDens", oofem::InternalStateType::IST_ElasStrainEnerDens) + .value("IST_TotalStrainEnerDens", oofem::InternalStateType::IST_TotalStrainEnerDens) + .value("IST_DamageScalar", oofem::InternalStateType::IST_DamageScalar) + .value("IST_MaterialOrientation_x", oofem::InternalStateType::IST_MaterialOrientation_x) + .value("IST_MaterialOrientation_y", oofem::InternalStateType::IST_MaterialOrientation_y) + .value("IST_MaterialOrientation_z", oofem::InternalStateType::IST_MaterialOrientation_z) + .value("IST_TemperatureFlow", oofem::InternalStateType::IST_TemperatureFlow) + .value("IST_MassConcentrationFlow_1", oofem::InternalStateType::IST_MassConcentrationFlow_1) + .value("IST_HumidityFlow", oofem::InternalStateType::IST_HumidityFlow) + .value("IST_CrackStatuses", oofem::InternalStateType::IST_CrackStatuses) + .value("IST_CrackedFlag", oofem::InternalStateType::IST_CrackedFlag) + .value("IST_CrackDirs", oofem::InternalStateType::IST_CrackDirs) + .value("IST_CumPlasticStrain", oofem::InternalStateType::IST_CumPlasticStrain) + .value("IST_CumPlasticStrain_2", oofem::InternalStateType::IST_CumPlasticStrain_2) + .value("IST_StressWorkDensity", oofem::InternalStateType::IST_StressWorkDensity) + .value("IST_DissWorkDensity", oofem::InternalStateType::IST_DissWorkDensity) + .value("IST_FreeEnergyDensity", oofem::InternalStateType::IST_FreeEnergyDensity) + .value("IST_ThermalConductivityIsotropic", oofem::InternalStateType::IST_ThermalConductivityIsotropic) + .value("IST_HeatCapacity", oofem::InternalStateType::IST_HeatCapacity) + .value("IST_AverageTemperature", oofem::InternalStateType::IST_AverageTemperature) + .value("IST_YoungModulusVirginPaste", oofem::InternalStateType::IST_YoungModulusVirginPaste) + .value("IST_PoissonRatioVirginPaste", oofem::InternalStateType::IST_PoissonRatioVirginPaste) + .value("IST_YoungModulusConcrete", oofem::InternalStateType::IST_YoungModulusConcrete) + .value("IST_PoissonRatioConcrete", oofem::InternalStateType::IST_PoissonRatioConcrete) + .value("IST_VolumetricPlasticStrain", oofem::InternalStateType::IST_VolumetricPlasticStrain) + .value("IST_DeviatoricStrain", oofem::InternalStateType::IST_DeviatoricStrain) + .value("IST_DeviatoricStress", oofem::InternalStateType::IST_DeviatoricStress) + .value("IST_Viscosity", oofem::InternalStateType::IST_Viscosity) + .value("IST_CharacteristicLength", oofem::InternalStateType::IST_CharacteristicLength) + .value("IST_DeviatoricStrainMeasure", oofem::InternalStateType::IST_DeviatoricStrainMeasure) + .value("IST_DeviatoricStressMeasure", oofem::InternalStateType::IST_DeviatoricStressMeasure) + .value("IST_vonMisesStress", oofem::InternalStateType::IST_vonMisesStress) + .value("IST_CrackVector", oofem::InternalStateType::IST_CrackVector) + .value("IST_PressureGradient", oofem::InternalStateType::IST_PressureGradient) + .value("IST_DissWork", oofem::InternalStateType::IST_DissWork) + .value("IST_DeltaDissWork", oofem::InternalStateType::IST_DeltaDissWork) + .value("IST_StressCapPos", oofem::InternalStateType::IST_StressCapPos) + .value("IST_TangentNorm", oofem::InternalStateType::IST_TangentNorm) + .value("IST_Tangent", oofem::InternalStateType::IST_Tangent) + .value("IST_DirectorField", oofem::InternalStateType::IST_DirectorField) + .value("IST_CrackWidth", oofem::InternalStateType::IST_CrackWidth) + .value("IST_DeformationGradientTensor", oofem::InternalStateType::IST_DeformationGradientTensor) + .value("IST_FirstPKStressTensor", oofem::InternalStateType::IST_FirstPKStressTensor) + .value("IST_XFEMEnrichment", oofem::InternalStateType::IST_XFEMEnrichment) + .value("IST_XFEMNumIntersecPoints", oofem::InternalStateType::IST_XFEMNumIntersecPoints) + .value("IST_XFEMLevelSetPhi", oofem::InternalStateType::IST_XFEMLevelSetPhi) + .value("IST_Maturity", oofem::InternalStateType::IST_Maturity) + .value("IST_CauchyStressTensor", oofem::InternalStateType::IST_CauchyStressTensor) + .value("IST_InterfaceJump", oofem::InternalStateType::IST_InterfaceJump) + .value("IST_InterfaceTraction", oofem::InternalStateType::IST_InterfaceTraction) + .value("IST_InterfaceFirstPKTraction", oofem::InternalStateType::IST_InterfaceFirstPKTraction) + .value("IST_StressTensor_Reduced", oofem::InternalStateType::IST_StressTensor_Reduced) + .value("IST_StrainTensor_Reduced", oofem::InternalStateType::IST_StrainTensor_Reduced) + .value("IST_CrossSectionNumber", oofem::InternalStateType::IST_CrossSectionNumber) + .value("IST_ShellStrainTensor", oofem::InternalStateType::IST_ShellStrainTensor) + .value("IST_AbaqusStateVector", oofem::InternalStateType::IST_AbaqusStateVector) + .value("IST_AutogenousShrinkageTensor", oofem::InternalStateType::IST_AutogenousShrinkageTensor) + .value("IST_DryingShrinkageTensor", oofem::InternalStateType::IST_DryingShrinkageTensor) + .value("IST_TotalShrinkageTensor", oofem::InternalStateType::IST_TotalShrinkageTensor) + .value("IST_ThermalStrainTensor", oofem::InternalStateType::IST_ThermalStrainTensor) + .value("IST_CreepStrainTensor", oofem::InternalStateType::IST_CreepStrainTensor) + .value("IST_TensileStrength", oofem::InternalStateType::IST_TensileStrength) + .value("IST_ResidualTensileStrength", oofem::InternalStateType::IST_ResidualTensileStrength) + .value("IST_LocalEquivalentStrain", oofem::InternalStateType::IST_LocalEquivalentStrain) + .value("IST_CrackIndex", oofem::InternalStateType::IST_CrackIndex) + .value("IST_EigenStrainTensor", oofem::InternalStateType::IST_EigenStrainTensor) + .value("IST_CrackStrainTensor", oofem::InternalStateType::IST_CrackStrainTensor) + .value("IST_2ndCrackWidth", oofem::InternalStateType::IST_2ndCrackWidth) + .value("IST_2ndCrackVector", oofem::InternalStateType::IST_2ndCrackVector) + .value("IST_3rdCrackWidth", oofem::InternalStateType::IST_3rdCrackWidth) + .value("IST_3rdCrackVector", oofem::InternalStateType::IST_3rdCrackVector) + .value("IST_FiberStressLocal", oofem::InternalStateType::IST_FiberStressLocal) + .value("IST_FiberStressNL", oofem::InternalStateType::IST_FiberStressNL) + .value("IST_EnergyMassCapacity", oofem::InternalStateType::IST_EnergyMassCapacity) + .value("IST_PrincStressVector1", oofem::InternalStateType::IST_PrincStressVector1) + .value("IST_PrincStressVector2", oofem::InternalStateType::IST_PrincStressVector2) + .value("IST_PrincStressVector3", oofem::InternalStateType::IST_PrincStressVector3) + .value("IST_InterfaceNormal", oofem::InternalStateType::IST_InterfaceNormal) + .value("IST_MomentTensor", oofem::InternalStateType::IST_MomentTensor) + .value("IST_MomentTensorTemp", oofem::InternalStateType::IST_MomentTensorTemp) + .value("IST_YieldStrength", oofem::InternalStateType::IST_YieldStrength) + .value("IST_ElasticStrainTensor", oofem::InternalStateType::IST_ElasticStrainTensor) + .value("IST_MoistureContent", oofem::InternalStateType::IST_MoistureContent) + .value("IST_CrackStatusesTemp", oofem::InternalStateType::IST_CrackStatusesTemp) + .value("IST_CrackSlip", oofem::InternalStateType::IST_CrackSlip) + .value("IST_EquivalentTime", oofem::InternalStateType::IST_EquivalentTime) + .value("IST_IncrementCreepModulus", oofem::InternalStateType::IST_IncrementCreepModulus) + ; + + py::register_exception(m, "InputException"); + py::register_exception(m, "MissingKeywordInputException"); + py::register_exception(m, "BadFormatInputException"); + py::register_exception(m, "ValueInputException"); + + + + py::enum_(m, "MatResponseMode") + .value("TangentStiffness", oofem::MatResponseMode::TangentStiffness) + .value("SecantStiffness", oofem::MatResponseMode::SecantStiffness) + .value("ElasticStiffness", oofem::MatResponseMode::ElasticStiffness) + .value("Conductivity", oofem::MatResponseMode::Conductivity) + .value("Conductivity_ww", oofem::MatResponseMode::Conductivity_ww) + .value("Conductivity_hh", oofem::MatResponseMode::Conductivity_hh) + .value("Conductivity_hw", oofem::MatResponseMode::Conductivity_hw) + .value("Conductivity_wh", oofem::MatResponseMode::Conductivity_wh) + .value("Capacity", oofem::MatResponseMode::Capacity) + .value("Capacity_ww", oofem::MatResponseMode::Capacity_ww) + .value("Capacity_hh", oofem::MatResponseMode::Capacity_hh) + .value("Capacity_hw", oofem::MatResponseMode::Capacity_hw) + .value("Capacity_wh", oofem::MatResponseMode::Capacity_wh) + .value("IntSource", oofem::MatResponseMode::IntSource) + .value("IntSource_ww", oofem::MatResponseMode::IntSource_ww) + .value("IntSource_hh", oofem::MatResponseMode::IntSource_hh) + .value("IntSource_hw", oofem::MatResponseMode::IntSource_hw) + .value("IntSource_wh", oofem::MatResponseMode::IntSource_wh) + ; + + py::enum_(m,"TimeDiscretizationType") + .value("TD_Unspecified", oofem::TimeDiscretizationType::TD_Unspecified) + .value("TD_ThreePointBackward", oofem::TimeDiscretizationType::TD_ThreePointBackward) + .value("TD_TwoPointBackward", oofem::TimeDiscretizationType::TD_TwoPointBackward) + .value("TD_Newmark", oofem::TimeDiscretizationType::TD_Newmark) + .value("TD_Wilson", oofem::TimeDiscretizationType::TD_Wilson) + .value("TD_Explicit", oofem::TimeDiscretizationType::TD_Explicit) + ; + + m.def("linearStatic", &linearStatic, py::return_value_policy::move); + m.def("staticStructural", &staticStructural, py::return_value_policy::move); + m.def("domain", &domain, py::return_value_policy::move); + m.def("truss1d", &truss1d, py::return_value_policy::move); + m.def("beam2d", &beam2d, py::return_value_policy::move); + m.def("trPlaneStress2d", &trPlaneStress2d, py::return_value_policy::move); + m.def("planeStress2d", &planeStress2d, py::return_value_policy::move); + m.def("transientTransport", &transientTransport, py::return_value_policy::move); + m.def("qBrick1ht", &qBrick1ht, py::return_value_policy::move); + m.def("lspace", &lspace, py::return_value_policy::move); + m.def("tr1ht", &tr1ht, py::return_value_policy::move); + m.def("quad1ht", &quad1ht, py::return_value_policy::move); + m.def("qquad1ht", &qquad1ht, py::return_value_policy::move); + + m.def("node", &node, py::return_value_policy::move); + m.def("boundaryCondition", &boundaryCondition, py::return_value_policy::move); + m.def("initialCondition", &initialCondition, py::return_value_policy::move); + m.def("constantEdgeLoad", &constantEdgeLoad, py::return_value_policy::move); + m.def("constantSurfaceLoad", &constantSurfaceLoad, py::return_value_policy::move); + m.def("DeadWeight", &deadWeight, py::return_value_policy::move); + m.def("nodalLoad", &nodalLoad, py::return_value_policy::move); + m.def("structTemperatureLoad", &structTemperatureLoad, py::return_value_policy::move); + m.def("structEigenstrainLoad", &structEigenstrainLoad, py::return_value_policy::move); + m.def("isoLE", &isoLE, py::return_value_policy::move); + m.def("idm1", &idm1, py::return_value_policy::move); + m.def("isoHeat", &isoHeat, py::return_value_policy::move); + m.def("j2mat", &j2mat, py::return_value_policy::move); + m.def("steel1", &steel1, py::return_value_policy::move); + + m.def("simpleCS", &simpleCS, py::return_value_policy::move); + m.def("simpleTransportCS", &simpleTransportCS, py::return_value_policy::move); + m.def("peakFunction", &peakFunction, py::return_value_policy::move); + m.def("constantFunction", &constantFunction, py::return_value_policy::move); + m.def("piecewiseLinFunction", &piecewiseLinFunction, py::return_value_policy::move); + m.def("vtkxml", &vtkxml, py::return_value_policy::move); + m.def("vtkmemory", &vtkmemory, py::return_value_policy::move); + m.def("homExport", &homExport, py::return_value_policy::move); + m.def("createSet", &createSet, py::return_value_policy::move); + + +//std::shared_ptr + py::class_>(m, "Field") + .def(py::init()) +// .def("evaluateAt", (int (oofem::Field::*)(oofem::FloatArray &answer, const oofem::FloatArray &coords, oofem::ValueModeType mode, oofem::TimeStep *tStep)) &oofem::Field::evaluateAt) + + .def("evaluateAt", [](oofem::FloatArray &answer, const oofem::FloatArray &coords, oofem::ValueModeType mode, oofem::TimeStep *tStep){ + return std::make_tuple(answer,coords);//TODO-how to invoke the function if it does not exist yet? + }) + .def("giveType", &oofem::Field::giveType) + .def("setType", &oofem::Field::setType) + ; + + py::class_>(m, "UniformGridField") + .def(py::init<>()) + .def("setGeometry", &oofem::UniformGridField::setGeometry) + .def("setValues", &oofem::UniformGridField::setValues) + ; + + py::class_>(m, "UnstructuredGridField") + .def(py::init(), py::arg().noconvert(), py::arg().noconvert(), py::arg("octreeOriginShift") = 0.0) + .def("addVertex", &oofem::UnstructuredGridField::addVertex) + .def("setVertexValue", &oofem::UnstructuredGridField::setVertexValue) + ; + + py::class_>(m, "DofManValueField") + .def(py::init()) + .def(py::init(), py::arg().noconvert(), py::arg().noconvert(), py::arg().noconvert(), py::arg("engngModel")="transienttransport", py::arg("domainDofsDefaults")="heattransfer") + .def("addNode", &oofem::DofManValueField::addNode ) + .def("addElement", &oofem::DofManValueField::addElement ) + .def("setDofManValue", &oofem::DofManValueField::setDofManValue ) + .def("getNodeCoordinates", &oofem::DofManValueField::getNodeCoordinates ) + ; + + +//depends on Python.h +#ifdef _PYBIND_BINDINGS + py::class_>(m, "PythonField") + .def(py::init<>()) + .def("setModuleName", &oofem::PythonField::setModuleName) + .def("setFunctionName", &oofem::PythonField::setFunctionName) + ; +#endif + + + m.def("test", &test); + } diff --git a/bindings/python/oofemutil.h b/bindings/python/oofemutil.h new file mode 100644 index 000000000..60f929485 --- /dev/null +++ b/bindings/python/oofemutil.h @@ -0,0 +1,404 @@ +#include +#include +namespace py = pybind11; +#include +#include +// for alternative tokens like 'or' +#include + +#include "oofemtxtdatareader.h" +#include "classfactory.h" +#include "logger.h" +#include "domain.h" +#include "outputmanager.h" +#include "modulemanager.h" +#include "set.h" + + +#ifdef _MSC_VER +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + +using namespace oofem; + +oofem::OOFEMTXTInputRecord makeOOFEMTXTInputRecordFrom(py::kwargs &kw) +{ + py::dict tmp; + std::string rec; + std::string space= " "; + + for (auto item: kw) { + std::string key = std::string(py::str(item.first)); + py::handle value = item.second; + if ((strcasecmp(std::string(key).c_str(), "number") == 0) or (strcasecmp(std::string(key).c_str(), "domain") == 0)) + continue; + if (key=="f_t") key="f(t)"; // handle f(t) loadTimeFunction field name + rec.append(space); + rec.append(key); + if (PyBool_Check(value.ptr())) { + // printf ("huhu\n"); + ; + } else if (PyNumber_Check(value.ptr()) or PyUnicode_Check(value.ptr())) { + PyObject* repr = PyObject_Str(value.ptr()); //PyObject_Repr puts single quotes around + PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~"); + const char*bytes = PyBytes_AS_STRING(str) ; + rec.append(space); + rec.append(bytes); + Py_XDECREF(repr); + Py_XDECREF(str); + } else if (PySequence_Check(value.ptr())) { + PyObject *iterator = PyObject_GetIter(value.ptr()); + PyObject *item; + if (iterator == NULL) { + ; /* propagate error */ + } + unsigned int size = PySequence_Length(value.ptr()); + rec.append(space); + rec.append(std::to_string(size)); + + while ((item = PyIter_Next(iterator))) { + /* do something with item */ + + if (PyNumber_Check(item) || PyUnicode_Check(item)) { + PyObject* repr = PyObject_Repr(item); + PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~"); + const char*bytes = PyBytes_AS_STRING(str) ; + rec.append(space); + rec.append(bytes); + Py_XDECREF(repr); + Py_XDECREF(str); + + } else { + // todo: error handling when conversion fails + py::handle h = item; // handle case when reference to object given; check reference counting + auto o = h.cast(); + oofem::FEMComponent* f = o.cast (); + rec.append(space); + rec.append(std::to_string(f->giveNumber())); + + + //makeOOFEMTXTValueentryFrom (item); + + } + Py_DECREF(item); + } + + Py_DECREF(iterator); + } else { // handle case when reference to object given; check reference counting + // todo: error handling when conversion fails + py::handle h = value; + auto o = h.cast(); + oofem::FEMComponent* f = o.cast (); + rec.append(space); + rec.append(std::to_string(f->giveNumber())); + } + /* + if (PyErr_Occurred()) { + // propagate error + } else { + // continue doing useful work + } + */ + } + transform(rec.begin(), rec.end(), rec.begin(), ::tolower); // convert to lowercase, text probably in "" should not be converted (like filenames) +// std::cout << rec << std::endl; + oofem::OOFEMTXTInputRecord answer(0, rec) ; + return answer; +} + +oofem::OOFEMTXTInputRecord makeOutputManagerOOFEMTXTInputRecordFrom(py::kwargs kw) +{ + py::kwargs kw2; + + for (auto item: kw) { + std::string key = std::string(py::str(item.first)); + py::handle value = item.second; + + transform(key.begin(), key.end(), key.begin(), ::tolower); + + if (key=="tstep_all" || key=="tstep_step" || key=="tsteps_out" || key=="dofman_all" || key=="dofman_output" || key=="dofman_except" || key=="element_all" || key=="element_output" || key=="element_except" || key=="pythonexport") { + kw2[key.c_str()] = value; + } + kw2[""] = "outputmanager"; + } + return makeOOFEMTXTInputRecordFrom(kw); + +} + + +/***************************************************** +* EngngModel +*****************************************************/ + +py::object createEngngModelOfType(const char* type, py::args args, py::kwargs kw) +{ + //args + int number = len(args)>0? PyLong_AsUnsignedLong(args[0].ptr()) : 0; + oofem::EngngModel* master = len(args)>1? args[1].cast() : nullptr; + std::unique_ptr engngm = classFactory.createEngngModel(type,number,master); + if ( !engngm ) { oofem::OOFEM_LOG_ERROR("engngModel: wrong input data"); } + oofem::OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); + // instanciateYourself + ///@todo Output filename isn't stored like this (and has never been!)!? + std::string outFile; + if ( ir.hasField("outfile") ) { + ir.giveField(outFile, "outfile"); + } else { + outFile = "oofem.out.XXXXXX"; + } + + //engngm->Instanciate_init(outFile.c_str(), engngm->giveNumberOfDomains()); + engngm->letOutputBaseFileNameBe(outFile); + engngm->initializeFrom(ir); + + if ( ir.hasField(_IFT_EngngModel_nmsteps) ) { + oofem::OOFEM_LOG_ERROR("engngModel: simulation with metasteps is not (yet) supported in Python"); + } else { + engngm->instanciateDefaultMetaStep(ir); + } + + engngm->Instanciate_init(); + // + py::object ret = py::cast(engngm.release()); + /* ???????????????????? + // sets the last created engngModel as default one for further script + temp_global["defaultEngngModel"] = ret; + ???????????????????? */ + return ret; +} + +py::object linearStatic(py::args args, py::kwargs kw) { return createEngngModelOfType("linearstatic", args, kw); } + +py::object staticStructural(py::args args, py::kwargs kw) { return createEngngModelOfType("staticstructural", args, kw); } + +py::object transientTransport(py::args args, py::kwargs kw) { return createEngngModelOfType("transienttransport", args, kw); } + + + +/***************************************************** +* Domain +*****************************************************/ +py::object domain(py::args args, py::kwargs kw) +{ + // args + int number = len(args)>0? PyLong_AsUnsignedLong(args[0].ptr()) : 0; + int serialNumber = len(args)>1? PyLong_AsUnsignedLong(args[1].ptr()) : 0; + EngngModel *engngModel = len(args)>2? args[2].cast() : nullptr; + domainType dType = len(args)>3? args[3].cast(): oofem::domainType::_unknownMode; + auto d = std::make_unique(number,serialNumber,engngModel); + d->setDomainType(dType); + // output manager record + oofem::OOFEMTXTInputRecord omir = makeOutputManagerOOFEMTXTInputRecordFrom(kw); + d->giveOutputManager()->initializeFrom(omir); + py::object ret = py::cast(d.release()); + /* ???????????????????? + // sets the last created domain as default one for furtherscript + temp_global["defaultDomain"] = ret; + ???????????????????? */ + return ret; +} + +/***************************************************** +* Element +*****************************************************/ +py::object createElementOfType(const char* type, py::args args, py::kwargs kw) +{ + + // extracts values from args if they are specified + int number = len(args)>0?PyLong_AsUnsignedLong(args[0].ptr()):0; + oofem::Domain* domain = len(args)>1? args[1].cast() : nullptr; + /* ???????????????? + // if no material is specified, set it to 1 + if (!kw.has_key("mat")) { kw["mat"] = 1; } + // if no cross section is specified, set it to 1 + if (!kw.has_key("crosssect")) { kw["crosssect"] = 1; } + // if no domain is specified and one already exists in the script, use that one + if (domain == nullptr && temp_global.has_key("defaultDomain")) { domain = extract(temp_global["defaultDomain"])(); } + if (domain==nullptr) { LOG_ERROR(oofem_errLogger,"wrong Domain"); } + ???????????????????? */ + // create Element (convert aClass to char* - expected by classFactory.createElement) + auto elem = oofem::classFactory.createElement(type,number,domain); + // if elem==nullptr, something was wrong + if (!elem) { oofem::OOFEM_LOG_ERROR("element: wrong input data"); } + // sets globalNumber == number befor initializeFrom + elem->setGlobalNumber(number); + // construct OOFEMTXTInputRecord from bp::dict **kw + oofem::OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); + // pass input record to elem + elem->initializeFrom(ir); + // convert element to PyObject (expected by raw_function, which enables fun(*args,**kw) syntax in python) + return py::cast(elem.release()); +} + +// specific elements +py::object beam2d(py::args args, py::kwargs &kw) { return createElementOfType("beam2d",args,kw); } +py::object truss1d(py::args args, py::kwargs &kw) { return createElementOfType("truss1d",args,kw); } +py::object trPlaneStress2d(py::args args, py::kwargs &kw) { return createElementOfType("trplanestress2d",args,kw); } +py::object planeStress2d(py::args args, py::kwargs &kw) { return createElementOfType("planestress2d",args,kw); } +py::object qBrick1ht(py::args args, py::kwargs &kw) { return createElementOfType("qbrick1ht",args,kw); } +py::object lspace(py::args args, py::kwargs &kw) { return createElementOfType("lspace",args,kw); } +py::object tr1ht(py::args args, py::kwargs &kw) { return createElementOfType("tr1ht",args,kw); } +py::object quad1ht(py::args args, py::kwargs &kw) { return createElementOfType("quad1ht",args,kw); } +py::object qquad1ht(py::args args, py::kwargs &kw) { return createElementOfType("qquad1ht",args,kw); } + + + + +/***************************************************** +* DofManager +*****************************************************/ + +py::object createDofManagerOfType(const char*type, py::args args, py::kwargs &kw) +{ + unsigned long number = len(args)>0?PyLong_AsUnsignedLong(args[0].ptr()):0; + oofem::Domain* domain = len(args)>1? args[1].cast() : nullptr; + auto dofMan = oofem::classFactory.createDofManager(type,number,domain); + if (!dofMan) { oofem::OOFEM_LOG_ERROR("dofManager: wrong input data"); } + dofMan->setGlobalNumber(number); + OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); + dofMan->initializeFrom(ir); + return py::cast(dofMan.release()); +} + + +py::object node(py::args args, py::kwargs kw) { return createDofManagerOfType("node",args,kw); } + + +/***************************************************** +* GeneralBoundaryCondition +*****************************************************/ +// generalBoundaryCondition(aClass,domain=defaultDomain,**kw) +py::object createGeneralBoundaryConditionOfType(const char* type, py::args args, py::kwargs kw) +{ + int number = len(args)>0?PyLong_AsUnsignedLong(args[0].ptr()):0; + oofem::Domain* domain = len(args)>1? args[1].cast() : nullptr; + auto bc = oofem::classFactory.createBoundaryCondition(type,number,domain); + if (!bc) { oofem::OOFEM_LOG_ERROR("generalBoundaryCondition: wrong input data"); } + oofem::OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); + bc->initializeFrom(ir); + return py::cast(bc.release()); +} + +py::object boundaryCondition(py::args args, py::kwargs kw) { return createGeneralBoundaryConditionOfType("boundarycondition",args,kw); } +py::object constantEdgeLoad(py::args args, py::kwargs kw) { return createGeneralBoundaryConditionOfType("constantedgeload",args,kw); } +py::object nodalLoad(py::args args, py::kwargs kw) { return createGeneralBoundaryConditionOfType("nodalload",args,kw); } +py::object structTemperatureLoad(py::args args, py::kwargs kw) { return createGeneralBoundaryConditionOfType("structtemperatureload",args,kw); } +py::object structEigenstrainLoad(py::args args, py::kwargs kw) { return createGeneralBoundaryConditionOfType("structEigenstrainLoad",args,kw); } +py::object constantSurfaceLoad(py::args args, py::kwargs kw) { return createGeneralBoundaryConditionOfType("constantsurfaceload",args,kw); } +py::object deadWeight(py::args args, py::kwargs kw) { return createGeneralBoundaryConditionOfType("DeadWeight",args,kw); } + + +/***************************************************** +* InitialCondition +*****************************************************/ +py::object createInitialConditionOfType(const char* type, py::args args, py::kwargs kw) +{ + int number = len(args)>0?PyLong_AsUnsignedLong(args[0].ptr()):0; + oofem::Domain* domain = len(args)>1? args[1].cast() : nullptr; + auto ic = oofem::classFactory.createInitialCondition(type,number,domain); + if (!ic) { oofem::OOFEM_LOG_ERROR("initialCondition: wrong input data"); } + oofem::OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); + ic->initializeFrom(ir); + return py::cast(ic.release()); +} + +py::object initialCondition(py::args args, py::kwargs kw) { return createInitialConditionOfType("initialcondition",args,kw); } + + +/***************************************************** +* Material +*****************************************************/ +py::object createMaterialOfType(const char* type, py::args args, py::kwargs kw) +{ + int number = len(args)>0?PyLong_AsUnsignedLong(args[0].ptr()):0; + oofem::Domain* domain = len(args)>1? args[1].cast() : nullptr; + auto mat = oofem::classFactory.createMaterial(type,number,domain); + if (!mat) { oofem::OOFEM_LOG_ERROR("material: wrong input data"); } + oofem::OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); + mat->initializeFrom(ir); + return py::cast(mat.release()); +} + +py::object isoLE(py::args args, py::kwargs kw) { return createMaterialOfType("isole",args,kw); } +py::object idm1(py::args args, py::kwargs kw) { return createMaterialOfType("idm1",args,kw); } +py::object isoHeat(py::args args, py::kwargs kw) { return createMaterialOfType("isoheat",args,kw); } +py::object j2mat(py::args args, py::kwargs kw) { return createMaterialOfType("j2mat",args,kw); } +py::object steel1(py::args args, py::kwargs kw) { return createMaterialOfType("steel1",args,kw); } + + +/***************************************************** +* CrossSection +*****************************************************/ +py::object createCrossSectionOfType(const char* type, py::args args, py::kwargs kw) +{ + int number = len(args)>0?PyLong_AsUnsignedLong(args[0].ptr()):0; + oofem::Domain* domain = len(args)>1? args[1].cast() : nullptr; + auto cs = oofem::classFactory.createCrossSection(type,number,domain); + if (!cs) { oofem::OOFEM_LOG_ERROR("crossSection: wrong input data"); } + oofem::OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); + cs->initializeFrom(ir); + return py::cast(cs.release()); +} + +py::object simpleCS(py::args args, py::kwargs kw) { return createCrossSectionOfType("simplecs",args,kw); } +py::object simpleTransportCS(py::args args, py::kwargs kw) { return createCrossSectionOfType("simpletransportcs",args,kw); } + + + +/***************************************************** +* LoadTimeFunction +*****************************************************/ +py::object createLoadTimeFunctionOfType(const char* type, py::args args, py::kwargs kw) +{ + int number = len(args)>0?PyLong_AsUnsignedLong(args[0].ptr()):0; + oofem::Domain* domain = len(args)>1? args[1].cast() : nullptr; + auto ltf = oofem::classFactory.createFunction(type,number,domain); + if (!ltf) { oofem::OOFEM_LOG_ERROR("function: wrong input data"); } + oofem::OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); + ltf->initializeFrom(ir); + return py::cast(ltf.release()); +} + +py::object peakFunction(py::args args, py::kwargs kw) { return createLoadTimeFunctionOfType("peakfunction",args,kw); } + +py::object constantFunction(py::args args, py::kwargs kw) { return createLoadTimeFunctionOfType("constantfunction",args,kw); } + +py::object piecewiseLinFunction(py::args args, py::kwargs kw) { return createLoadTimeFunctionOfType("piecewiselinfunction",args,kw); } + + +/***************************************************** +* ExportModule +*****************************************************/ +py::object createExportModuleOfType(const char* type, py::args args, py::kwargs kw) +{ + int number = len(args)>0?PyLong_AsUnsignedLong(args[0].ptr()):0; + oofem::EngngModel *engngModel = len(args)>1? args[1].cast() : nullptr; + auto module = oofem::classFactory.createExportModule(type,number,engngModel); + if (!module) { oofem::OOFEM_LOG_ERROR("exportModule: wrong input data"); } + oofem::OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); + module->initializeFrom(ir); + module->initialize(); + engngModel->giveExportModuleManager()->registerModule(module); + return py::cast(engngModel->giveExportModuleManager()->giveModule(engngModel->giveExportModuleManager()->giveNumberOfModules())); +} + +py::object vtkxml(py::args args, py::kwargs kw) { return createExportModuleOfType("vtkxml",args,kw); } +py::object homExport(py::args args, py::kwargs kw) { return createExportModuleOfType("hom",args,kw); } +py::object vtkmemory(py::args args, py::kwargs kw) { return createExportModuleOfType("vtkmemory",args,kw); } + +/***************************************************** +* Sets +*****************************************************/ +py::object createSetOfType(const char* type, py::args args, py::kwargs kw) +{ + int number = len(args)>0?PyLong_AsUnsignedLong(args[0].ptr()):0; + oofem::Domain* domain = len(args)>1? args[1].cast() : nullptr; + std::unique_ptr setP = std::make_unique(number, domain); + if ( !setP ) { oofem::OOFEM_LOG_ERROR("Couldn't create set: %d", number); } + oofem::OOFEMTXTInputRecord ir = makeOOFEMTXTInputRecordFrom(kw); + setP->initializeFrom(ir); + return py::cast(setP.release()); +} + +py::object createSet(py::args args, py::kwargs kw) { return createSetOfType("set",args,kw); } diff --git a/bindings/python/test.py b/bindings/python/test.py deleted file mode 100644 index 1471049ba..000000000 --- a/bindings/python/test.py +++ /dev/null @@ -1,39 +0,0 @@ -import liboofem - -a = liboofem.FloatArray(2); -b = liboofem.FloatArray(4); -ind = liboofem.IntArray(2); - -a.zero(); -b.zero(); -a[1]=15.0; -a[0]=10.0; -print a[0], a[1]; -a.printYourself(); - -c = liboofem.FloatArray(a) -print c[0], c[1]; -c.printYourself(); - -d = liboofem.FloatMatrix(2,2); -d.beUnitMatrix(); -d[0,1]=1.0; -d.printYourself(); - -b.beProductOf(d,a); -b.printYourself(); - -b.resize(4); -b.zero(); -ind[0]=1; -ind[1]=3; -b.assemble(a,ind); -b.printYourself(); - - -dr=liboofem.OOFEMTXTDataReader("patch100.in"); -problem=liboofem.InstanciateProblem(dr,liboofem.problemMode._processor,0); -problem.checkProblemConsistency(); -problem.setRenumberFlag(); -problem.solveYourself(); -problem.terminateAnalysis(); diff --git a/bindings/python/test3.py b/bindings/python/test3.py deleted file mode 100644 index 9fe279938..000000000 --- a/bindings/python/test3.py +++ /dev/null @@ -1,53 +0,0 @@ -from __future__ import print_function -import liboofem -dr=liboofem.OOFEMTXTDataReader("tmpatch42.in") -pb=liboofem.InstanciateProblem(dr,liboofem.problemMode._processor,0) -pb.checkProblemConsistency() -pb.setRenumberFlag() -pb.solveYourself() -pb.terminateAnalysis() -ts=pb.giveCurrentStep() - -for t in liboofem.FieldType.FT_Temperature,liboofem.FieldType.FT_HumidityConcentration: - f=pb.giveField(liboofem.FieldType(t),ts) - print(ts.targetTime,t,str(f)) - -#fm=pb.giveContext().giveFieldManager() -#print fm -#print fm.giveRegisteredKeys() -# why is this one None? -#print fm.giveField(liboofem.FieldType.FT_Displacements) -#for i in range(100): -# print fm.giveField(liboofem.FieldType(i)) - -print('Number of domains:',pb.giveNumberOfDomains()) -# everything starts at 1 -do=pb.giveDomain(1) -print('Domain',do) -e=do.giveElement(3) -print('Element type',e.giveGeometryType()) -for t in liboofem.FieldType.FT_Temperature,: #,liboofem.FieldType.FT_HumidityConcentration: - f=pb.giveField(liboofem.FieldType(t),ts) - print('Field at time',ts.targetTime,'type',t,str(f)) -ne=do.giveNumberOfElements() -nd=do.giveNumberOfDofManagers() - -# vertices -for d in range(1,nd+1): - dof=do.giveDofManager(d) - # print dof - cc=dof.giveCoordinates() - print('DofManager #%d at '%(d-1),[cc[i] for i in range(len(cc))]) - # for vmt in liboofem.ValueModeType.VM_Total,liboofem.ValueModeType.VM_Unknown,liboofem.ValueModeType.VM_Velocity,liboofem.ValueModeType.VM_Acceleration,liboofem.ValueModeType.VM_Incremental: - vmt=liboofem.ValueModeType.VM_Total - val=f.evaluateAtDman(dof,mode=vmt,atTime=ts) - if len(val): print(' value',vmt,len(val),val) - else: print (' (zero-length array read from this DoF manager)') -# elements -for ei in range(1,ne+1): - e=do.giveElement(ei) - gt=e.giveGeometryType() - nn=e.numberOfDofManagers - for n in range(1,nn+1): - dmn=e.giveDofManager(n) - print('Element %d, DOF #%d -> node %d'%(ei-1,n-1,dmn.giveNumber())) diff --git a/bindings/python/tests/test_1.py b/bindings/python/tests/test_1.py new file mode 100644 index 000000000..93afcd65f --- /dev/null +++ b/bindings/python/tests/test_1.py @@ -0,0 +1,55 @@ +import oofempy + + +def test_1(): + a = oofempy.FloatArray((1.0, 2.0, 3.0)) + b = oofempy.FloatArray((0.0, -1.0, 1.0)) + x = oofempy.FloatArray(3) + + c = a+b + assert (round(c[0] - 1.0, 6) == 0), "Error in a+b" + assert (round(c[1] - 1.0, 6) == 0) + assert (round(c[2] - 4.0, 6) == 0) + + c += a + assert (round(c[0]-2.0, 6) == 0) + assert (round(c[1]-3.0, 6) == 0) + assert (round(c[2]-7.0, 6) == 0) + + d = a-b + assert (round(d[0]-1.0, 6) == 0) + assert (round(d[1]-3.0, 6) == 0) + assert (round(d[2]-2.0, 6) == 0) + + d -= a + assert (round(d[0]-0.0, 6) == 0) + assert (round(d[1]-1.0, 6) == 0) + assert (round(d[2]+1.0, 6) == 0) + + print(a) + print(d) + + A = oofempy.FloatMatrix(3,3) + A.beUnitMatrix() + + det = A.giveDeterminant() + assert (round (det - 1.0, 6) == 0), "Error in geveDeterminant" + + A.solveForRhs(a, x, False); + assert (round(x[0]-1.0, 6) == 0) + assert (round(x[1]-2.0, 6) == 0) + assert (round(x[2]-3.0, 6) == 0) + + print(x) + + Ainv = oofempy.FloatMatrix(3,3); + Ainv.beInverseOf(A) + y = Ainv*x + + assert (round(y[0]-1.0, 6) == 0) + assert (round(y[1]-2.0, 6) == 0) + assert (round(y[2]-3.0, 6) == 0) + print(y) + +if __name__ == "__main__": + test_1() \ No newline at end of file diff --git a/bindings/python/tests/test_2.py b/bindings/python/tests/test_2.py new file mode 100644 index 000000000..26da913eb --- /dev/null +++ b/bindings/python/tests/test_2.py @@ -0,0 +1,71 @@ +import oofempy +import util + +def test_2(): + + # engngModel + problem = oofempy.linearStatic(nSteps=3, outFile='test_2.out') + + # domain (if no engngModel specified to domain, it is asigned to the last one created) + domain = oofempy.domain(1, 1, problem, oofempy.domainType._2dBeamMode, tstep_all=True, dofman_all=True, element_all=True) + problem.setDomain(1, domain, True) + + ltf1 = oofempy.peakFunction(1, domain, t=1, f_t=1) + ltf2 = oofempy.peakFunction(2, domain, t=2, f_t=1) + ltf3 = oofempy.peakFunction(3, domain, t=3, f_t=1) + ltfs = (ltf1, ltf2, ltf3) + + # boundary conditions + # loadTimeFunction parameter can be specified as int value or as LoadTimeFunction itself (valid for all objects with giveNumber() method) + bc1 = oofempy.boundaryCondition( 1, domain, loadTimeFunction=1, prescribedValue=0.0) + bc2 = oofempy.boundaryCondition( 2, domain, loadTimeFunction=2, prescribedValue=-.006e-3) + eLoad = oofempy.constantEdgeLoad( 3, domain, loadTimeFunction=1, components=(0.,10.,0.), loadType=3, ndofs=3) + nLoad = oofempy.nodalLoad( 4, domain, loadTimeFunction=1, components=(-18.,24.,0.)) + tLoad = oofempy.structTemperatureLoad(5, domain, loadTimeFunction=3, components=(30.,-20.)) + bcs = (bc1, bc2, eLoad, nLoad, tLoad) + + # nodes + # if one value is passed as parameter where oofem expects array of values, it must be passed as tuple or list (see load in n4) + n1 = oofempy.node(1, domain, coords=(0., 0., 0. ), bc=(0,1,0)) + n2 = oofempy.node(2, domain, coords=(2.4, 0., 0. ), bc=(0,0,0)) + n3 = oofempy.node(3, domain, coords=(3.8, 0., 0. ), bc=(0,0,bc1)) + n4 = oofempy.node(4, domain, coords=(5.8, 0., 1.5), bc=(0,0,0), load=(4,)) + n5 = oofempy.node(5, domain, coords=(7.8, 0., 3.0), bc=(0,1,0)) + n6 = oofempy.node(6, domain, coords=(2.4, 0., 3.0), bc=(bc1,1,bc2)) + nodes = (n1, n2, n3, n4, n5, n6) + + # material and cross section + mat = oofempy.isoLE(1, domain, d=1., E=30.e6, n=0.2, tAlpha=1.2e-5) + cs = oofempy.simpleCS(1, domain, area=0.162, Iy=0.0039366, beamShearCoeff=1.e18, thick=0.54) + + # elements + e1 = oofempy.beam2d(1, domain, nodes=(1,n2), mat=1, crossSect=1, boundaryLoads=(3,1), bodyLoads=(5,)) + e2 = oofempy.beam2d(2, domain, nodes=(2,3), mat=mat, crossSect=1, DofsToCondense=(6,), bodyLoads=[tLoad]) + e3 = oofempy.beam2d(3, domain, nodes=(n3,4), mat=1, crossSect=cs, dofstocondense=[3]) + e4 = oofempy.beam2d(4, domain, nodes=(n4,n5), mat=mat, crossSect=cs) + e5 = oofempy.beam2d(5, domain, nodes=(n6,2), mat=1, crossSect=1, DofsToCondense=(6,)) + elems = (e1, e2, e3, e4, e5) + + # add eveything to domain (resize container first to save some time, but it is not necessary 0 see ltfs) + util.setupDomain(domain, nodes, elems, (cs,), (mat,), bcs, (), ltfs, ()) + + print("\nSolving problem") + problem.checkProblemConsistency() + problem.init() + problem.postInitialize() + problem.setRenumberFlag() + problem.solveYourself() + + #check solution + u1 = problem.giveUnknownComponent (oofempy.ValueModeType.VM_Total, problem.giveCurrentStep(False), domain, domain.giveDofManager(1).giveDofWithID(oofempy.DofIDItem.D_u)) + print (u1) + assert (round (u1+8.64000000e-04, 8) == 0), "Node 1 dof 1 displacement check failed" + u4 = problem.giveUnknownComponent (oofempy.ValueModeType.VM_Total, problem.giveCurrentStep(False), domain, domain.giveDofManager(4).giveDofWithID(oofempy.DofIDItem.D_u)) + assert (round (u4-9.47333333e-04, 8) == 0), "Node 4 dof 1 displacement check failed" + + + problem.terminateAnalysis() + print("\nProblem solved") + +if __name__ == "__main__": + test_2() diff --git a/bindings/python/tests/test_3.py b/bindings/python/tests/test_3.py new file mode 100644 index 000000000..45393d157 --- /dev/null +++ b/bindings/python/tests/test_3.py @@ -0,0 +1,112 @@ +# +# this example illustrates the user defined function in python injected into oofem +# +# +import oofempy +import util + +class MyFunc(oofempy.Function): + def __init__(self, num, domain): + oofempy.Function.__init__(self, num, domain) + def evaluateAtTime (self, t): + return 2.5*t + def evaluateVelocityAtTime(self, t): + return 0.0; + def evaluateAccelerationAtTime(self, t): + return 0.0; + +class MyElement(oofempy.StructuralElement): + def __init__(self, num, domain): + oofempy.StructuralElement.__init__(self, num, domain) + self.setNumberOfDofManagers(2) + def computeStiffnessMatrix(self, answer, rMode, tStep): + answer.resize(2,2); + answer[0,0] = 1.0; + answer[0,1] = -1.0; + answer[1,0] = 1.0; + answer[1,1] = -1.0; + def computeBmatrixAt(self, gp, answer, lowerIndx, upperIndx): + answer.resize(1,2); + answer[0,0]=-1.0; + answer[0,1]=1.0; + def giveInternalForcesVector(self, answer, tStep, useUpdatedGpRecord): + u = oofempy.FloatArray() + k = oofempy.FloatMatrix(2,2) + self.computeVectorOf(oofempy.ValueModeType.VM_Total, tStep, u) + self.computeStiffnessMatrix(k, oofempy.CharType.StiffnessMatrix, tStep) + answer.beProductOf (k, u) + def giveNumberOfDofs(self): + return 2; + def computeNumberOfDofs(self): + return 2; + def giveDofManDofIDMask(self, inode, answer): + answer.resize(1) + answer[0] = oofempy.DofIDItem.D_u +# def printOutputAt(self, f, tStep): +# fint = oofempy.FloatArray() +# self.giveInternalForcesVector(fint, tStep, false) +# fint.py() + def giveClassName(self): + return "MyElement" + def giveInputRecordName(self): + return "MyElement" + +def test_3(): + # engngModel + problem = oofempy.linearStatic(nSteps=1, outFile="test_3.out") + + # domain (if no engngModel specified to domain, it is asigned to the last one created) + domain = oofempy.domain(1, 1, problem, oofempy.domainType._1dTrussMode, tstep_all=True, dofman_all=True, element_all=True) + problem.setDomain(1, domain, True) + + ltf1 = oofempy.peakFunction(1, domain, t=1, f_t=1) + ltf2 = MyFunc(2, domain) # use custom ltf here + ltfs = (ltf1, ltf2) + + # boundary conditions + # loadTimeFunction parameter can be specified as int value or as LoadTimeFunction itself (valid for all objects with giveNumber() method) + bc1 = oofempy.boundaryCondition( 1, domain, loadTimeFunction=1, prescribedValue=0.0) + n2 = oofempy.nodalLoad( 2, domain, loadTimeFunction=2, components=(1.,), dofs=(1,)) + bcs = (bc1, n2) + + # nodes + # if one value is passed as parameter where oofem expects array of values, it must be passed as tuple or list (see load in n4) + n1 = oofempy.node(1, domain, coords=(0., 0., 0. ), bc=(bc1,)) + n2 = oofempy.node(2, domain, coords=(2.4, 0., 0. ), load=(n2,)) + nodes = (n1, n2) + + # material and cross section + mat = oofempy.isoLE(1, domain, d=1., E=30.e6, n=0.2, tAlpha=1.2e-5) + cs = oofempy.simpleCS(1, domain, area=0.5, Iy=0.0, beamShearCoeff=1.e18, thick=0.5) + + # elements + #e1 = oofempy.truss1d(1, domain, nodes=(1,n2), mat=1, crossSect=1) + e1 = MyElement(1, domain) + e1.setDofManagers((1,2)) + # construct OOFEMTXTInputRecord from bp::dict **kw + ir = oofempy.OOFEMTXTInputRecord() + ir.setRecordString ("nodes 2 1 2 mat 1 crosssect 1") + # pass input record to elem + e1.initializeFrom(ir) + elems = (e1,) + + # setup domain + util.setupDomain (domain, nodes, elems, (cs,), (mat,), bcs, (), ltfs, ()) + + print("\nSolving problem") + problem.checkProblemConsistency() + problem.init() + problem.postInitialize() + problem.setRenumberFlag() + problem.solveYourself() + + #check solution + u2 = problem.giveUnknownComponent (oofempy.ValueModeType.VM_Total, problem.giveCurrentStep(False), domain, domain.giveDofManager(2).giveDofWithID(oofempy.DofIDItem.D_u)) + assert (round (u2+2.5, 8) == 0), "Node 2 dof 1 displacement check failed" + + problem.terminateAnalysis() + print("\nProblem solved") + + +if __name__ == "__main__": + test_3() diff --git a/bindings/python/tests/test_4.py b/bindings/python/tests/test_4.py new file mode 100644 index 000000000..58cf75c4d --- /dev/null +++ b/bindings/python/tests/test_4.py @@ -0,0 +1,110 @@ +# +# this example illustrates the user defined material model in python injected into oofem +# +# +import oofempy +import util + +class MyMaterial(oofempy.StructuralMaterial): + def __init__(self, num, domain): + oofempy.StructuralMaterial.__init__(self, num, domain) + self.k = 1.5; + def giveClassName(self): + return "MyMaterial" + def giveInputRecordName(self): + return "MyElement" + # Overloading this method is not yet possible in pybind11 + # see https://github.com/pybind/pybind11/issues/1962 + # However a workaround is to override giveStatus, see below + def CreateStatus(self, gp): + return oofempy.StructuralMaterialStatus (gp) + def give1dStressStiffMtrx(self, mode, gp, tStep): + answer = oofempy.FloatMatrix(1,1) + answer[0,0] = self.k + return answer; + def giveRealStressVector_1d(self, reducedStrain, gp, tStep): + answer = oofempy.FloatArray(1) + answer[0] = self.k * reducedStrain[0] + status = self.giveStatus(gp) + status.letTempStrainVectorBe(reducedStrain); + status.letTempStressVectorBe(answer); + return answer; + def giveStatus (self, gp): + print ("getStatus") + if (gp.giveMaterialStatus() is None): + print ("getStatus creating") + status = oofempy.StructuralMaterialStatus (gp) + gp.setMaterialStatus(status) + return gp.giveMaterialStatus() + +def test_4(): + # engngModel + problem = oofempy.linearStatic(nSteps=1, outFile="test_4.out") + + # domain (if no engngModel specified to domain, it is asigned to the last one created) + domain = oofempy.domain(1, 1, problem, oofempy.domainType._1dTrussMode, tstep_all=True, dofman_all=True, element_all=True) + problem.setDomain(1, domain, True) + + ltf1 = oofempy.peakFunction(1, domain, t=1, f_t=1) + ltfs = (ltf1, ) + + # boundary conditions + # loadTimeFunction parameter can be specified as int value or as LoadTimeFunction itself (valid for all objects with giveNumber() method) + bc1 = oofempy.boundaryCondition( 1, domain, loadTimeFunction=1, prescribedValue=0.0) + n2 = oofempy.nodalLoad( 2, domain, loadTimeFunction=1, components=(1.,), dofs=(1,)) + bcs = (bc1, n2) + + # nodes + # if one value is passed as parameter where oofem expects array of values, it must be passed as tuple or list (see load in n4) + n1 = oofempy.node(1, domain, coords=(0., 0., 0. ), bc=(bc1,)) + n2 = oofempy.node(2, domain, coords=(2.4, 0., 0. ), load=(n2,)) + nodes = (n1, n2) + + # material and cross section + #mat = oofempy.isoLE(1, domain, d=1., E=30.e6, n=0.2, tAlpha=1.2e-5) + mat = MyMaterial(1, domain) + cs = oofempy.simpleCS(1, domain, area=0.5, Iy=0.0, beamShearCoeff=1.e18, thick=0.5) + + # elements + e1 = oofempy.truss1d(1, domain, nodes=(1,n2), mat=1, crossSect=1) + # construct OOFEMTXTInputRecord from bp::dict **kw + elems = (e1,) + + # setup domain + util.setupDomain (domain, nodes, elems, (cs,), (mat,), bcs, (), ltfs, ()) + + print("\nSolving problem") + problem.checkProblemConsistency() + problem.init() + problem.postInitialize() + + # Test user defined material model + a =oofempy.FloatArray((1.0,)) + ans=oofempy.FloatArray() + + rule=e1.giveDefaultIntegrationRulePtr() + rule=e1.giveIntegrationRule(0) + #print(rule) + gp = rule.getIntegrationPoint(0) + #print(gp) + #print(mat.giveStatus(gp)) + ans = domain.giveMaterial(1).giveRealStressVector_1d(a, rule.getIntegrationPoint(0), None) + #ans.pY() + assert (round(ans[0]-1.5, 8) == 0), "Stress value error" + + problem.setRenumberFlag() + problem.solveYourself() + + #check solution + u2 = problem.giveUnknownComponent (oofempy.ValueModeType.VM_Total, problem.giveCurrentStep(False), domain, domain.giveDofManager(2).giveDofWithID(oofempy.DofIDItem.D_u)) + assert (round (u2-3.2, 8) == 0), "Node 2 dof 1 displacement check failed" + + + problem.terminateAnalysis() + print("\nProblem solved") + + + +if __name__ == "__main__": + test_4() + diff --git a/bindings/python/tests/test_5.py b/bindings/python/tests/test_5.py new file mode 100644 index 000000000..dce334f4a --- /dev/null +++ b/bindings/python/tests/test_5.py @@ -0,0 +1,109 @@ +# this example illustrates an injection of external temperature field during runtime +import oofempy +import util + +#Function returning temperature. +def evalField(coords, mode, tStep): + val = 10.*tStep.giveNumber()*coords[0] + print("Evaluating field at %f,%f. Assigning temperature %f" % (coords[0], coords[1], val)) + return (val,) #Return list of len 1 + + +def test_5(): + # engngModel + problem = oofempy.staticStructural(nSteps=3, outFile="test_5.out") + + # domain (if no engngModel specified to domain, it is asigned to the last one created) + domain = oofempy.domain(1, 1, problem, oofempy.domainType._2dPlaneStressMode, tstep_all=True, dofman_all=True, element_all=True) + problem.setDomain(1, domain, True) + + ltf1 = oofempy.constantFunction(1, domain, f_t=1.) + ltf2 = oofempy.piecewiseLinFunction(2, domain, t=(1., 5.), f_t= (0., 4.)) + ltfs = (ltf1,ltf2) + + # boundary conditions + bc1 = oofempy.boundaryCondition(1, domain, loadTimeFunction=1, prescribedValue=0.0) + n2 = oofempy.nodalLoad(2, domain, loadTimeFunction=2, components=(0.,0.), dofs=(1,2)) + bcs = (bc1, n2) + + # nodes + n1 = oofempy.node(1, domain, coords=(0., 0., 0. ), bc=(bc1,bc1)) + n2 = oofempy.node(2, domain, coords=(2.4, 0., 0. ), bc=(0,bc1)) + n3 = oofempy.node(3, domain, coords=(2.4, 0.8, 0.), load=(n2,) ) + nodes = (n1,n2,n3) + + # material and cross section + mat = oofempy.isoLE(1, domain, d=1., E=30.e3, n=0.2, tAlpha=1.2e-5) + cs = oofempy.simpleCS(1, domain, thick=0.5, material=1, set=1) + + # elements - assign through sets + e1 = oofempy.trPlaneStress2d(1, domain, nodes=(1,2,3)) + elems = (e1,) + + set1 = oofempy.createSet(1, domain, elements=(1,)) #Ettringite + + # setup domain + util.setupDomain(domain, nodes, elems, (cs,), (mat,), bcs, (), ltfs, (set1,)) + + # add export module for outputting regular VTU files - automatically registered + vtkxml = oofempy.vtkxml(1, problem, domain_all=True, tstep_all=True, dofman_all=True, element_all=True, vars=(56,), primvars=(6,), stype=1, pythonExport=0) + + # add export module for outputting python lists with values - automatically registered + vtkPy = oofempy.vtkmemory(1, problem, domain_all=True, tstep_all=True, dofman_all=True, element_all=True, vars=(56,37), primvars=(6,), cellvars = (47,103), stype=1, pythonExport=1) + + #add homogenization module - automatically registered + homPy1 = oofempy.homExport(3, problem, tstep_all=True, ists=(1,4), regionsets=(1,)) + + + + print("\nSolving problem") + problem.checkProblemConsistency() + problem.init() + problem.postInitialize() + problem.giveTimer().startTimer(oofempy.EngngModelTimerType.EMTT_AnalysisTimer) + activeMStep = problem.giveMetaStep(1) + problem.initMetaStepAttributes(activeMStep); + + #Create dummy temperature field, define from where to obtain the values + f = oofempy.PythonField() + f.setModuleName('test_5') + f.setFunctionName('evalField') + context = problem.giveContext() + field_man = context.giveFieldManager() + #register field so OOFEM knows of external temperature. In every iteration, it calls PythonField::evaluateAt() which propagates further to evalField() + field_man.registerField(f, oofempy.FieldType.FT_Temperature) + + for timeStep in range(3): + problem.preInitializeNextStep() + problem.giveNextStep() + currentStep = problem.giveCurrentStep() + problem.initializeYourself( currentStep ) + problem.solveYourselfAt( currentStep ) + problem.updateYourself( currentStep ) + problem.terminate( currentStep ) + print("TimeStep %d finished" % (timeStep)) + + for p in vtkPy.getVTKPieces(): + print ("Piece:", p) + print("Vertices:", p.getVertices()) + print("Cells:", p.getCellConnectivity()) + print("CellTypes:", p.getCellTypes(vtkPy)) + temperature = p.getPrimaryVertexValues(oofempy.UnknownType.Temperature); + print ("Temperature:", temperature) + + problem.terminateAnalysis() + + ##check solution + v3 = problem.giveUnknownComponent(oofempy.ValueModeType.VM_Total, problem.giveCurrentStep(False), domain, domain.giveDofManager(3).giveDofWithID(oofempy.DofIDItem.D_v)) + assert (round (v3-4.608e-4, 8) == 0), "Node 3 dof 2 displacement check failed" + + + t1 = temperature[0][0] + assert (round (t1-48.0000, 4) == 0), "Export of primary field failed" + + problem.terminateAnalysis() + print("\nProblem solved") + + +if __name__ == "__main__": + test_5() diff --git a/bindings/python/tests/test_6.py b/bindings/python/tests/test_6.py new file mode 100644 index 000000000..79a448473 --- /dev/null +++ b/bindings/python/tests/test_6.py @@ -0,0 +1,73 @@ +# this example illustrates an injection of external temperature field during runtime +import oofempy +import util + + +def test_6(): + # engngModel + problem = oofempy.staticStructural(nSteps=1, outFile="test_6.out") + + # domain (if no engngModel specified to domain, it is asigned to the last one created) + domain = oofempy.domain(1, 1, problem, oofempy.domainType._3dMode, tstep_all=True, dofman_all=True, element_all=True) + problem.setDomain(1, domain, True) + # load time functions + ltf1 = oofempy.constantFunction(1, domain, f_t=1.) + ltfs = (ltf1,) + # boundary conditions + bc1 = oofempy.boundaryCondition(1, domain, loadTimeFunction=1, prescribedValue=0.0) + dw = oofempy.DeadWeight(2, domain, loadTimeFunction = 1, components=(0.,0.,-10.0)) + bcs = (bc1, dw) + # nodes + n1 = oofempy.node(1, domain, coords=(0., 0., 2. )) + n2 = oofempy.node(2, domain, coords=(0., 2., 2. )) + n3 = oofempy.node(3, domain, coords=(2., 2., 2. )) + n4 = oofempy.node(4, domain, coords=(2., 0., 2. )) + n5 = oofempy.node(5, domain, coords=(0., 0., 0. ), bc=(bc1, bc1, bc1)) + n6 = oofempy.node(6, domain, coords=(0., 2., 0. ), bc=( 0, 0, bc1) ) + n7 = oofempy.node(7, domain, coords=(2., 2., 0. ), bc=( 0, 0, bc1)) + n8 = oofempy.node(8, domain, coords=(2., 0., 0. ), bc=( 0, bc1, bc1)) + # + nodes = (n1,n2,n3,n4,n5,n6,n7,n8) + # material and cross section + mat = oofempy.isoLE(1, domain, d=2., E=100., n=0.01, tAlpha=1.2e-5) + cs = oofempy.simpleCS(1, domain) + # elements - assign through sets + e1 = oofempy.lspace(1, domain, nodes=(1,2,3,4,5,6,7,8), mat=1, crossSect = 1, bodyloads = (dw,)) + elems = (e1,) + #sets + set1 = oofempy.createSet(1, domain, elements=(1,)) + # setup domain + util.setupDomain(domain, nodes, elems, (cs,), (mat,), bcs, (), ltfs, (set1,)) + # add export module for outputting regular VTU files - automatically registered +# vtkxml = oofempy.vtkxml(1, problem, domain_all=True, tstep_all=True, dofman_all=True, element_all=True, vars=(56,), primvars=(6,), stype=1, pythonExport=0) + + # add export module for outputting python lists with values - automatically registered + print("\nSolving problem") + problem.checkProblemConsistency() + problem.init() + problem.postInitialize() + problem.giveTimer().startTimer(oofempy.EngngModelTimerType.EMTT_AnalysisTimer) + activeMStep = problem.giveMetaStep(1) + problem.initMetaStepAttributes(activeMStep); + + for timeStep in range(1): + problem.preInitializeNextStep() + problem.giveNextStep() + currentStep = problem.giveCurrentStep() + problem.initializeYourself( currentStep ) + problem.solveYourselfAt( currentStep ) + problem.updateYourself( currentStep ) + problem.terminate( currentStep ) + print("TimeStep %d finished" % (timeStep)) + + #check solution + w3 = problem.giveUnknownComponent(oofempy.ValueModeType.VM_Total, problem.giveCurrentStep(False), domain, domain.giveDofManager(1).giveDofWithID(oofempy.DofIDItem.D_w)) + assert (round (w3+4.000e-1, 8) == 0), "Node 1 dof 3 displacement check failed" + + + problem.terminateAnalysis() + print("\nProblem solved") + + +if __name__ == "__main__": + test_6() diff --git a/bindings/python/util.py b/bindings/python/util.py new file mode 100644 index 000000000..31d0b8e53 --- /dev/null +++ b/bindings/python/util.py @@ -0,0 +1,41 @@ +import oofempy + +# +# Initializes domain with given sequences of nodes, elements, ..... +# +def setupDomain (domain, nodes, elems, css, mats, bcs, ics, ltfs, sets): + + domain.resizeDofManagers(len(nodes)) # process nodes + for n in nodes: + domain.setDofManager(n.number, n) + + domain.resizeElements(len(elems)) # process elements + for e in elems: + domain.setElement(e.number, e) + + domain.resizeCrossSectionModels(len(css)) #process cross sections + for c in css: + domain.setCrossSection(c.number, c) + + domain.resizeMaterials(len(mats)) # process materials + for m in mats: + domain.setMaterial(m.number, m) + + domain.resizeBoundaryConditions(len(bcs)) #process boundary conditions + for bc in bcs: + domain.setBoundaryCondition(bc.number, bc) + + domain.resizeInitialConditions(len(ics)) #process initial conditions + for ic in ics: + domain.setInitialCondition(ic.number, ic) + + domain.resizeFunctions(len(ltfs)) # process (load time) functions + for ltf in ltfs: + domain.setFunction(ltf.number, ltf) + + domain.resizeSets(len(sets)) # process sets + for s in sets: + domain.setSet(s.number, s) + + return + diff --git a/cmake/Modules/CorrectWindowsPaths.cmake b/cmake/Modules/CorrectWindowsPaths.cmake new file mode 100644 index 000000000..09bcdd67d --- /dev/null +++ b/cmake/Modules/CorrectWindowsPaths.cmake @@ -0,0 +1,14 @@ +# CorrectWindowsPaths - this module defines one macro +# +# CONVERT_CYGWIN_PATH( PATH ) +# This uses the command cygpath (provided by cygwin) to convert +# unix-style paths into paths useable by cmake on windows + +macro (CONVERT_CYGWIN_PATH _path) + if (WIN32) + EXECUTE_PROCESS(COMMAND cygpath.exe -m ${${_path}} + OUTPUT_VARIABLE ${_path}) + string (STRIP ${${_path}} ${_path}) + endif (WIN32) +endmacro (CONVERT_CYGWIN_PATH) + diff --git a/cmake/Modules/FindPETSc.cmake b/cmake/Modules/FindPETSc.cmake new file mode 100644 index 000000000..dc94a13fb --- /dev/null +++ b/cmake/Modules/FindPETSc.cmake @@ -0,0 +1,337 @@ +# - Try to find PETSc +# Once done this will define +# +# PETSC_FOUND - system has PETSc +# PETSC_INCLUDES - the PETSc include directories +# PETSC_LIBRARIES - Link these to use PETSc +# PETSC_COMPILER - Compiler used by PETSc, helpful to find a compatible MPI +# PETSC_DEFINITIONS - Compiler switches for using PETSc +# PETSC_MPIEXEC - Executable for running MPI programs +# PETSC_VERSION - Version string (MAJOR.MINOR.SUBMINOR) +# +# Usage: +# find_package(PETSc COMPONENTS CXX) - required if build --with-clanguage=C++ --with-c-support=0 +# find_package(PETSc COMPONENTS C) - standard behavior of checking build using a C compiler +# find_package(PETSc) - same as above +# +# Setting these changes the behavior of the search +# PETSC_DIR - directory in which PETSc resides +# PETSC_ARCH - build architecture +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + +set(PETSC_VALID_COMPONENTS + C + CXX) + +if(NOT PETSc_FIND_COMPONENTS) + set(PETSC_LANGUAGE_BINDINGS "C") +else() + # Right now, this is designed for compatability with the --with-clanguage option, so + # only allow one item in the components list. + list(LENGTH ${PETSc_FIND_COMPONENTS} components_length) + if(${components_length} GREATER 1) + message(FATAL_ERROR "Only one component for PETSc is allowed to be specified") + endif() + # This is a stub for allowing multiple components should that time ever come. Perhaps + # to also test Fortran bindings? + foreach(component ${PETSc_FIND_COMPONENTS}) + list(FIND PETSC_VALID_COMPONENTS ${component} component_location) + if(${component_location} EQUAL -1) + message(FATAL_ERROR "\"${component}\" is not a valid PETSc component.") + else() + list(APPEND PETSC_LANGUAGE_BINDINGS ${component}) + endif() + endforeach() +endif() + +function (petsc_get_version) + if (EXISTS "${PETSC_DIR}/include/petscversion.h") + file (STRINGS "${PETSC_DIR}/include/petscversion.h" vstrings REGEX "#define PETSC_VERSION_(RELEASE|MAJOR|MINOR|SUBMINOR|PATCH) ") + foreach (line ${vstrings}) + string (REGEX REPLACE " +" ";" fields ${line}) # break line into three fields (the first is always "#define") + list (GET fields 1 var) + list (GET fields 2 val) + set (${var} ${val} PARENT_SCOPE) + set (${var} ${val}) # Also in local scope so we have access below + endforeach () + if (PETSC_VERSION_RELEASE) + set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}p${PETSC_VERSION_PATCH}" PARENT_SCOPE) + else () + # make dev version compare higher than any patch level of a released version + set (PETSC_VERSION "${PETSC_VERSION_MAJOR}.${PETSC_VERSION_MINOR}.${PETSC_VERSION_SUBMINOR}.99" PARENT_SCOPE) + endif () + else () + message (SEND_ERROR "PETSC_DIR can not be used, ${PETSC_DIR}/include/petscversion.h does not exist") + endif () +endfunction () + +find_path (PETSC_DIR include/petsc.h + HINTS ENV PETSC_DIR + PATHS + # Debian paths + /usr/lib/petsc + /usr/lib/petscdir/3.7.5 /usr/lib/petscdir/3.7 + /usr/lib/petscdir/3.5 + /usr/lib/petscdir/3.4.2 /usr/lib/petscdir/3.4 + /usr/lib/petscdir/3.3 /usr/lib/petscdir/3.2 /usr/lib/petscdir/3.1 + /usr/lib/petscdir/3.0.0 /usr/lib/petscdir/2.3.3 /usr/lib/petscdir/2.3.2 + # MacPorts path + /opt/local/lib/petsc + $ENV{HOME}/petsc + DOC "PETSc Directory") + +find_program (MAKE_EXECUTABLE NAMES make gmake) + +if (PETSC_DIR AND NOT PETSC_ARCH) + set (_petsc_arches + $ENV{PETSC_ARCH} # If set, use environment variable first + linux-gnu-c-debug linux-gnu-c-opt # Debian defaults + x86_64-unknown-linux-gnu i386-unknown-linux-gnu) + set (petscconf "NOTFOUND" CACHE FILEPATH "Cleared" FORCE) + foreach (arch ${_petsc_arches}) + if (NOT PETSC_ARCH) + find_path (petscconf petscconf.h + HINTS ${PETSC_DIR} + PATH_SUFFIXES ${arch}/include bmake/${arch} + NO_DEFAULT_PATH) + if (petscconf) + set (PETSC_ARCH "${arch}" CACHE STRING "PETSc build architecture") + endif (petscconf) + endif (NOT PETSC_ARCH) + endforeach (arch) + set (petscconf "NOTFOUND" CACHE INTERNAL "Scratch variable" FORCE) +endif (PETSC_DIR AND NOT PETSC_ARCH) + +set (petsc_slaves LIBRARIES_SYS LIBRARIES_VEC LIBRARIES_MAT LIBRARIES_DM LIBRARIES_KSP LIBRARIES_SNES LIBRARIES_TS + INCLUDE_DIR INCLUDE_CONF) +include (FindPackageMultipass) +find_package_multipass (PETSc petsc_config_current + STATES DIR ARCH + DEPENDENTS INCLUDES LIBRARIES COMPILER MPIEXEC ${petsc_slaves}) + +# Determine whether the PETSc layout is old-style (through 2.3.3) or +# new-style (>= 3.0.0) +if (EXISTS "${PETSC_DIR}/${PETSC_ARCH}/lib/petsc/conf/petscvariables") # > 3.5 + set (petsc_conf_rules "${PETSC_DIR}/lib/petsc/conf/rules") + set (petsc_conf_variables "${PETSC_DIR}/lib/petsc/conf/variables") +elseif (EXISTS "${PETSC_DIR}/${PETSC_ARCH}/include/petscconf.h") # > 2.3.3 + set (petsc_conf_rules "${PETSC_DIR}/conf/rules") + set (petsc_conf_variables "${PETSC_DIR}/conf/variables") +elseif (EXISTS "${PETSC_DIR}/bmake/${PETSC_ARCH}/petscconf.h") # <= 2.3.3 + set (petsc_conf_rules "${PETSC_DIR}/bmake/common/rules") + set (petsc_conf_variables "${PETSC_DIR}/bmake/common/variables") +elseif (PETSC_DIR) + message (SEND_ERROR "The pair PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} do not specify a valid PETSc installation") +endif () + +if (petsc_conf_rules AND petsc_conf_variables AND NOT petsc_config_current) + petsc_get_version() + + # Put variables into environment since they are needed to get + # configuration (petscvariables) in the PETSc makefile + set (ENV{PETSC_DIR} "${PETSC_DIR}") + set (ENV{PETSC_ARCH} "${PETSC_ARCH}") + + # A temporary makefile to probe the PETSc configuration + set (petsc_config_makefile "${PROJECT_BINARY_DIR}/Makefile.petsc") + file (WRITE "${petsc_config_makefile}" +"## This file was autogenerated by FindPETSc.cmake +# PETSC_DIR = ${PETSC_DIR} +# PETSC_ARCH = ${PETSC_ARCH} +include ${petsc_conf_rules} +include ${petsc_conf_variables} +show : +\t-@echo -n \${\${VARIABLE}} +") + + macro (PETSC_GET_VARIABLE name var) + set (${var} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) + execute_process (COMMAND ${MAKE_EXECUTABLE} --no-print-directory -f ${petsc_config_makefile} show VARIABLE=${name} + OUTPUT_VARIABLE ${var} + RESULT_VARIABLE petsc_return) + endmacro (PETSC_GET_VARIABLE) + petsc_get_variable (PETSC_LIB_DIR petsc_lib_dir) + petsc_get_variable (PETSC_EXTERNAL_LIB_BASIC petsc_libs_external) + petsc_get_variable (PETSC_CCPPFLAGS petsc_cpp_line) + petsc_get_variable (PETSC_INCLUDE petsc_include) + petsc_get_variable (PCC petsc_cc) + petsc_get_variable (PCC_FLAGS petsc_cc_flags) + petsc_get_variable (MPIEXEC petsc_mpiexec) + # We are done with the temporary Makefile, calling PETSC_GET_VARIABLE after this point is invalid! + file (REMOVE ${petsc_config_makefile}) + + include (ResolveCompilerPaths) + # Extract include paths and libraries from compile command line + resolve_includes (petsc_includes_all "${petsc_cpp_line}") + + #on windows we need to make sure we're linking against the right + #runtime library + if (WIN32) + if (petsc_cc_flags MATCHES "-MT") + set(using_md False) + foreach(flag_var + CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + if(${flag_var} MATCHES "/MD") + set(using_md True) + endif(${flag_var} MATCHES "/MD") + endforeach(flag_var) + if(${using_md} MATCHES "True") + message(WARNING "PETSc was built with /MT, but /MD is currently set. + See http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F") + endif(${using_md} MATCHES "True") + endif (petsc_cc_flags MATCHES "-MT") + endif (WIN32) + + include (CorrectWindowsPaths) + convert_cygwin_path(petsc_lib_dir) + message (STATUS "petsc_lib_dir ${petsc_lib_dir}") + + macro (PETSC_FIND_LIBRARY suffix name) + set (PETSC_LIBRARY_${suffix} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) # Clear any stale value, if we got here, we need to find it again + if (WIN32) + set (libname lib${name}) #windows expects "libfoo", linux expects "foo" + else (WIN32) + set (libname ${name}) + endif (WIN32) + find_library (PETSC_LIBRARY_${suffix} NAMES ${libname} HINTS ${petsc_lib_dir} NO_DEFAULT_PATH) + set (PETSC_LIBRARIES_${suffix} "${PETSC_LIBRARY_${suffix}}") + mark_as_advanced (PETSC_LIBRARY_${suffix}) + endmacro (PETSC_FIND_LIBRARY suffix name) + + # Look for petscvec first, if it doesn't exist, we must be using single-library + petsc_find_library (VEC petscvec) + if (PETSC_LIBRARY_VEC) + petsc_find_library (SYS "petscsys;petsc") # libpetscsys is called libpetsc prior to 3.1 (when single-library was introduced) + petsc_find_library (MAT petscmat) + petsc_find_library (DM petscdm) + petsc_find_library (KSP petscksp) + petsc_find_library (SNES petscsnes) + petsc_find_library (TS petscts) + macro (PETSC_JOIN libs deps) + list (APPEND PETSC_LIBRARIES_${libs} ${PETSC_LIBRARIES_${deps}}) + endmacro (PETSC_JOIN libs deps) + petsc_join (VEC SYS) + petsc_join (MAT VEC) + petsc_join (DM MAT) + petsc_join (KSP DM) + petsc_join (SNES KSP) + petsc_join (TS SNES) + petsc_join (ALL TS) + else () + set (PETSC_LIBRARY_VEC "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) # There is no libpetscvec + petsc_find_library (SINGLE petsc) + if (NOT PETSC_LIBRARY_SINGLE) + petsc_find_library (SINGLE petsc_real) + endif () + if (NOT PETSC_LIBRARY_SINGLE) + petsc_find_library (SINGLE petsc_complex) + endif () + foreach (pkg SYS VEC MAT DM KSP SNES TS ALL) + set (PETSC_LIBRARIES_${pkg} "${PETSC_LIBRARY_SINGLE}") + endforeach () + endif () + if (PETSC_LIBRARY_TS) + message (STATUS "Recognized PETSc install with separate libraries for each package") + else () + message (STATUS "Recognized PETSc install with single library for all packages") + endif () + + include(Check${PETSC_LANGUAGE_BINDINGS}SourceRuns) + macro (PETSC_TEST_RUNS includes libraries runs) + if(${PETSC_LANGUAGE_BINDINGS} STREQUAL "C") + set(_PETSC_ERR_FUNC "CHKERRQ(ierr)") + elseif(${PETSC_LANGUAGE_BINDINGS} STREQUAL "CXX") + set(_PETSC_ERR_FUNC "CHKERRXX(ierr)") + endif() + if (PETSC_VERSION VERSION_GREATER 3.1) + set (_PETSC_TSDestroy "TSDestroy(&ts)") + else () + set (_PETSC_TSDestroy "TSDestroy(ts)") + endif () + + set(_PETSC_TEST_SOURCE " +static const char help[] = \"PETSc test program.\"; +#include +int main(int argc,char *argv[]) { + PetscErrorCode ierr; + TS ts; + + ierr = PetscInitialize(&argc,&argv,0,help);${_PETSC_ERR_FUNC}; + ierr = TSCreate(PETSC_COMM_WORLD,&ts);${_PETSC_ERR_FUNC}; + ierr = TSSetFromOptions(ts);${_PETSC_ERR_FUNC}; + ierr = ${_PETSC_TSDestroy};${_PETSC_ERR_FUNC}; + ierr = PetscFinalize();${_PETSC_ERR_FUNC}; + return 0; +} +") + multipass_source_runs ("${includes}" "${libraries}" "${_PETSC_TEST_SOURCE}" ${runs} "${PETSC_LANGUAGE_BINDINGS}") + if (${${runs}}) + set (PETSC_EXECUTABLE_RUNS "YES" CACHE BOOL + "Can the system successfully run a PETSc executable? This variable can be manually set to \"YES\" to force CMake to accept a given PETSc configuration, but this will almost always result in a broken build. If you change PETSC_DIR, PETSC_ARCH, or PETSC_CURRENT you would have to reset this variable." FORCE) + endif (${${runs}}) + endmacro (PETSC_TEST_RUNS) + + + find_path (PETSC_INCLUDE_DIR petscts.h HINTS "${PETSC_DIR}" PATH_SUFFIXES include NO_DEFAULT_PATH) + find_path (PETSC_INCLUDE_CONF petscconf.h HINTS "${PETSC_DIR}" PATH_SUFFIXES "${PETSC_ARCH}/include" "bmake/${PETSC_ARCH}" NO_DEFAULT_PATH) + mark_as_advanced (PETSC_INCLUDE_DIR PETSC_INCLUDE_CONF) + set (petsc_includes_minimal ${PETSC_INCLUDE_CONF} ${PETSC_INCLUDE_DIR}) + + petsc_test_runs ("${petsc_includes_minimal}" "${PETSC_LIBRARIES_TS}" petsc_works_minimal) + if (petsc_works_minimal) + message (STATUS "Minimal PETSc includes and libraries work. This probably means we are building with shared libs.") + set (petsc_includes_needed "${petsc_includes_minimal}") + else (petsc_works_minimal) # Minimal includes fail, see if just adding full includes fixes it + petsc_test_runs ("${petsc_includes_all}" "${PETSC_LIBRARIES_TS}" petsc_works_allincludes) + if (petsc_works_allincludes) # It does, we just need all the includes ( + message (STATUS "PETSc requires extra include paths, but links correctly with only interface libraries. This is an unexpected configuration (but it seems to work fine).") + set (petsc_includes_needed ${petsc_includes_all}) + else (petsc_works_allincludes) # We are going to need to link the external libs explicitly + resolve_libraries (petsc_libraries_external "${petsc_libs_external}") + foreach (pkg SYS VEC MAT DM KSP SNES TS ALL) + list (APPEND PETSC_LIBRARIES_${pkg} ${petsc_libraries_external}) + endforeach (pkg) + petsc_test_runs ("${petsc_includes_minimal}" "${PETSC_LIBRARIES_TS}" petsc_works_alllibraries) + if (petsc_works_alllibraries) + message (STATUS "PETSc only need minimal includes, but requires explicit linking to all dependencies. This is expected when PETSc is built with static libraries.") + set (petsc_includes_needed ${petsc_includes_minimal}) + else (petsc_works_alllibraries) + # It looks like we really need everything, should have listened to Matt + set (petsc_includes_needed ${petsc_includes_all}) + petsc_test_runs ("${petsc_includes_all}" "${PETSC_LIBRARIES_TS}" petsc_works_all) + if (petsc_works_all) # We fail anyways + message (STATUS "PETSc requires extra include paths and explicit linking to all dependencies. This probably means you have static libraries and something unexpected in PETSc headers.") + else (petsc_works_all) # We fail anyways + message (STATUS "PETSc could not be used, maybe the install is broken.") + endif (petsc_works_all) + endif (petsc_works_alllibraries) + endif (petsc_works_allincludes) + endif (petsc_works_minimal) + + # We do an out-of-source build so __FILE__ will be an absolute path, hence __INSDIR__ is superfluous + if (${PETSC_VERSION} VERSION_LESS 3.1) + set (PETSC_DEFINITIONS "-D__SDIR__=\"\"" CACHE STRING "PETSc definitions" FORCE) + else () + set (PETSC_DEFINITIONS "-D__INSDIR__=" CACHE STRING "PETSc definitions" FORCE) + endif () + # Sometimes this can be used to assist FindMPI.cmake + set (PETSC_MPIEXEC ${petsc_mpiexec} CACHE FILEPATH "Executable for running PETSc MPI programs" FORCE) + set (PETSC_INCLUDES ${petsc_includes_needed} CACHE STRING "PETSc include path" FORCE) + set (PETSC_LIBRARIES ${PETSC_LIBRARIES_ALL} CACHE STRING "PETSc libraries" FORCE) + set (PETSC_COMPILER ${petsc_cc} CACHE FILEPATH "PETSc compiler" FORCE) + # Note that we have forced values for all these choices. If you + # change these, you are telling the system to trust you that they + # work. It is likely that you will end up with a broken build. + mark_as_advanced (PETSC_INCLUDES PETSC_LIBRARIES PETSC_COMPILER PETSC_DEFINITIONS PETSC_MPIEXEC PETSC_EXECUTABLE_RUNS) +endif () + +include (FindPackageHandleStandardArgs) +find_package_handle_standard_args (PETSc + "PETSc could not be found. Be sure to set PETSC_DIR and PETSC_ARCH." + PETSC_INCLUDES PETSC_LIBRARIES PETSC_EXECUTABLE_RUNS) diff --git a/cmake/Modules/FindPackageMultipass.cmake b/cmake/Modules/FindPackageMultipass.cmake new file mode 100644 index 000000000..fbf06a7f0 --- /dev/null +++ b/cmake/Modules/FindPackageMultipass.cmake @@ -0,0 +1,106 @@ +# PackageMultipass - this module defines two macros +# +# FIND_PACKAGE_MULTIPASS (Name CURRENT +# STATES VAR0 VAR1 ... +# DEPENDENTS DEP0 DEP1 ...) +# +# This function creates a cache entry _CURRENT which +# the user can set to "NO" to trigger a reconfiguration of the package. +# The first time this function is called, the values of +# _VAR0, ... are saved. If _CURRENT +# is false or if any STATE has changed since the last time +# FIND_PACKAGE_MULTIPASS() was called, then CURRENT will be set to "NO", +# otherwise CURRENT will be "YES". IF not CURRENT, then +# _DEP0, ... will be FORCED to NOTFOUND. +# Example: +# find_path (FOO_DIR include/foo.h) +# FIND_PACKAGE_MULTIPASS (Foo foo_current +# STATES DIR +# DEPENDENTS INCLUDES LIBRARIES) +# if (NOT foo_current) +# # Make temporary files, run programs, etc, to determine FOO_INCLUDES and FOO_LIBRARIES +# endif (NOT foo_current) +# +# MULTIPASS_SOURCE_RUNS (Name INCLUDES LIBRARIES SOURCE RUNS LANGUAGE) +# Always runs the given test, use this when you need to re-run tests +# because parent variables have made old cache entries stale. The LANGUAGE +# variable is either C or CXX indicating which compiler the test should +# use. +# MULTIPASS_C_SOURCE_RUNS (Name INCLUDES LIBRARIES SOURCE RUNS) +# DEPRECATED! This is only included for backwards compatability. Use +# the more general MULTIPASS_SOURCE_RUNS instead. +# Always runs the given test, use this when you need to re-run tests +# because parent variables have made old cache entries stale. + +macro (FIND_PACKAGE_MULTIPASS _name _current) + string (TOUPPER ${_name} _NAME) + set (_args ${ARGV}) + list (REMOVE_AT _args 0 1) + + set (_states_current "YES") + list (GET _args 0 _cmd) + if (_cmd STREQUAL "STATES") + list (REMOVE_AT _args 0) + list (GET _args 0 _state) + while (_state AND NOT _state STREQUAL "DEPENDENTS") + # The name of the stored value for the given state + set (_stored_var PACKAGE_MULTIPASS_${_NAME}_${_state}) + if (NOT "${${_stored_var}}" STREQUAL "${${_NAME}_${_state}}") + set (_states_current "NO") + endif (NOT "${${_stored_var}}" STREQUAL "${${_NAME}_${_state}}") + set (${_stored_var} "${${_NAME}_${_state}}" CACHE INTERNAL "Stored state for ${_name}." FORCE) + list (REMOVE_AT _args 0) + list (GET _args 0 _state) + endwhile (_state AND NOT _state STREQUAL "DEPENDENTS") + endif (_cmd STREQUAL "STATES") + + set (_stored ${_NAME}_CURRENT) + if (NOT ${_stored}) + set (${_stored} "YES" CACHE BOOL "Is the configuration for ${_name} current? Set to \"NO\" to reconfigure." FORCE) + set (_states_current "NO") + endif (NOT ${_stored}) + + set (${_current} ${_states_current}) + if (NOT ${_current} AND PACKAGE_MULTIPASS_${_name}_CALLED) + message (STATUS "Clearing ${_name} dependent variables") + # Clear all the dependent variables so that the module can reset them + list (GET _args 0 _cmd) + if (_cmd STREQUAL "DEPENDENTS") + list (REMOVE_AT _args 0) + foreach (dep ${_args}) + set (${_NAME}_${dep} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) + endforeach (dep) + endif (_cmd STREQUAL "DEPENDENTS") + set (${_NAME}_FOUND "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) + endif () + set (PACKAGE_MULTIPASS_${name}_CALLED YES CACHE INTERNAL "Private" FORCE) +endmacro (FIND_PACKAGE_MULTIPASS) + + +macro (MULTIPASS_SOURCE_RUNS includes libraries source runs language) + include (Check${language}SourceRuns) + # This is a ridiculous hack. CHECK_${language}_SOURCE_* thinks that if the + # *name* of the return variable doesn't change, then the test does + # not need to be re-run. We keep an internal count which we + # increment to guarantee that every test name is unique. If we've + # gotten here, then the configuration has changed enough that the + # test *needs* to be rerun. + if (NOT MULTIPASS_TEST_COUNT) + set (MULTIPASS_TEST_COUNT 00) + endif (NOT MULTIPASS_TEST_COUNT) + math (EXPR _tmp "${MULTIPASS_TEST_COUNT} + 1") # Why can't I add to a cache variable? + set (MULTIPASS_TEST_COUNT ${_tmp} CACHE INTERNAL "Unique test ID") + set (testname MULTIPASS_TEST_${MULTIPASS_TEST_COUNT}_${runs}) + set (CMAKE_REQUIRED_INCLUDES ${includes}) + set (CMAKE_REQUIRED_LIBRARIES ${libraries}) + if(${language} STREQUAL "C") + check_c_source_runs ("${source}" ${testname}) + elseif(${language} STREQUAL "CXX") + check_cxx_source_runs ("${source}" ${testname}) + endif() + set (${runs} "${${testname}}") +endmacro (MULTIPASS_SOURCE_RUNS) + +macro (MULTIPASS_C_SOURCE_RUNS includes libraries source runs) + multipass_source_runs("${includes}" "${libraries}" "${source}" ${runs} "C") +endmacro (MULTIPASS_C_SOURCE_RUNS) diff --git a/cmake/Modules/LICENSE b/cmake/Modules/LICENSE new file mode 100644 index 000000000..49bac9892 --- /dev/null +++ b/cmake/Modules/LICENSE @@ -0,0 +1,23 @@ +Copyright $(git shortlog -s) +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/cmake/Modules/ResolveCompilerPaths.cmake b/cmake/Modules/ResolveCompilerPaths.cmake new file mode 100644 index 000000000..54787fa38 --- /dev/null +++ b/cmake/Modules/ResolveCompilerPaths.cmake @@ -0,0 +1,105 @@ +# ResolveCompilerPaths - this module defines two macros +# +# RESOLVE_LIBRARIES (XXX_LIBRARIES LINK_LINE) +# This macro is intended to be used by FindXXX.cmake modules. +# It parses a compiler link line and resolves all libraries +# (-lfoo) using the library path contexts (-L/path) in scope. +# The result in XXX_LIBRARIES is the list of fully resolved libs. +# Example: +# +# RESOLVE_LIBRARIES (FOO_LIBRARIES "-L/A -la -L/B -lb -lc -ld") +# +# will be resolved to +# +# FOO_LIBRARIES:STRING="/A/liba.so;/B/libb.so;/A/libc.so;/usr/lib/libd.so" +# +# if the filesystem looks like +# +# /A: liba.so libc.so +# /B: liba.so libb.so +# /usr/lib: liba.so libb.so libc.so libd.so +# +# and /usr/lib is a system directory. +# +# Note: If RESOLVE_LIBRARIES() resolves a link line differently from +# the native linker, there is a bug in this macro (please report it). +# +# RESOLVE_INCLUDES (XXX_INCLUDES INCLUDE_LINE) +# This macro is intended to be used by FindXXX.cmake modules. +# It parses a compile line and resolves all includes +# (-I/path/to/include) to a list of directories. Other flags are ignored. +# Example: +# +# RESOLVE_INCLUDES (FOO_INCLUDES "-I/A -DBAR='\"irrelevant -I/string here\"' -I/B") +# +# will be resolved to +# +# FOO_INCLUDES:STRING="/A;/B" +# +# assuming both directories exist. +# Note: as currently implemented, the -I/string will be picked up mistakenly (cry, cry) +include (CorrectWindowsPaths) + +macro (RESOLVE_LIBRARIES LIBS LINK_LINE) + string (REGEX MATCHALL "((-L|-l|-Wl)([^\" ]+|\"[^\"]+\")|[^\" ]+\\.(a|so|dll|lib))" _all_tokens "${LINK_LINE}") + set (_libs_found "") + set (_directory_list "") + foreach (token ${_all_tokens}) + if (token MATCHES "-L([^\" ]+|\"[^\"]+\")") + # If it's a library path, add it to the list + string (REGEX REPLACE "^-L" "" token ${token}) + string (REGEX REPLACE "//" "/" token ${token}) + convert_cygwin_path(token) + list (APPEND _directory_list ${token}) + elseif (token MATCHES "^(-l([^\" ]+|\"[^\"]+\")|[^\" ]+\\.(a|so|dll|lib))") + # It's a library, resolve the path by looking in the list and then (by default) in system directories + if (WIN32) #windows expects "libfoo", linux expects "foo" + string (REGEX REPLACE "^-l" "lib" token ${token}) + else (WIN32) + string (REGEX REPLACE "^-l" "" token ${token}) + endif (WIN32) + set (_root "") + if (token MATCHES "^/") # We have an absolute path + #separate into a path and a library name: + string (REGEX MATCH "[^/]*\\.(a|so|dll|lib)$" libname ${token}) + string (REGEX MATCH ".*[^${libname}$]" libpath ${token}) + convert_cygwin_path(libpath) + set (_directory_list ${_directory_list} ${libpath}) + set (token ${libname}) + endif (token MATCHES "^/") + set (_lib "NOTFOUND" CACHE FILEPATH "Cleared" FORCE) + find_library (_lib ${token} HINTS ${_directory_list} ${_root}) + if (_lib) + string (REPLACE "//" "/" _lib ${_lib}) + list (APPEND _libs_found ${_lib}) + else (_lib) + message (STATUS "Unable to find library ${token}") + endif (_lib) + endif (token MATCHES "-L([^\" ]+|\"[^\"]+\")") + endforeach (token) + set (_lib "NOTFOUND" CACHE INTERNAL "Scratch variable" FORCE) + # only the LAST occurence of each library is required since there should be no circular dependencies + if (_libs_found) + list (REVERSE _libs_found) + list (REMOVE_DUPLICATES _libs_found) + list (REVERSE _libs_found) + endif (_libs_found) + set (${LIBS} "${_libs_found}") +endmacro (RESOLVE_LIBRARIES) + +macro (RESOLVE_INCLUDES INCS COMPILE_LINE) + string (REGEX MATCHALL "-I([^\" ]+|\"[^\"]+\")" _all_tokens "${COMPILE_LINE}") + set (_incs_found "") + foreach (token ${_all_tokens}) + string (REGEX REPLACE "^-I" "" token ${token}) + string (REGEX REPLACE "//" "/" token ${token}) + convert_cygwin_path(token) + if (EXISTS ${token}) + list (APPEND _incs_found ${token}) + else (EXISTS ${token}) + message (STATUS "Include directory ${token} does not exist") + endif (EXISTS ${token}) + endforeach (token) + list (REMOVE_DUPLICATES _incs_found) + set (${INCS} "${_incs_found}") +endmacro (RESOLVE_INCLUDES) diff --git a/do_release b/do_release index 59cee6c4b..f522611df 100644 --- a/do_release +++ b/do_release @@ -1,6 +1,6 @@ BACKUP_NAME=oofem.tar.gz -DOC_RELEASE_FILES="elementlibmanual/elementlibmanual.pdf paper-actap/paper-actap.pdf extractorInput/extractorInput.pdf matlibmanual/matlibmanual.pdf oofemInput/oofemInput.pdf programmer/programmer.pdf" -DOC_DIRS="doc/elementlibmanual doc/paper-actap doc/extractorInput doc/matlibmanual doc/oofemInput doc/programmer" +DOC_RELEASE_FILES="elementlibmanual/elementlibmanual.pdf paper-actap/paper-actap.pdf extractorInput/extractorInput.pdf matlibmanual/matlibmanual.pdf oofemInput/oofemInput.pdf programmer/programmer.pdf theorymanual/theorymanual.pdf" +DOC_DIRS="doc/elementlibmanual doc/paper-actap doc/extractorInput doc/matlibmanual doc/oofemInput doc/programmer doc/theorymanual" if [ -z $1 ] then diff --git a/doc/README b/doc/README index b31782e0e..e3f867154 100644 --- a/doc/README +++ b/doc/README @@ -60,6 +60,10 @@ OOFEM_DOC_DIR |-- refman - oofem regerence manual | |-- extractorInput - documentation of extractor tool +| +|--usermanual - oofem user manual +| +|--theorymanual - theory manual [2] Pre-requisites @@ -74,6 +78,8 @@ The latex, htlatex, and latex2html instalation is required to generate both post The compiled Reference Manual itself is not included in release due to its size. It can be accessed online from oofem home page. +User and Theory manuals require Sphinx (Python documantation generator, https://www.sphinx-doc.org) to be installed. + [3] Generating documentation from sources ============================================================================== @@ -88,6 +94,8 @@ To generate reference manual (in refman subdir), the doxygen (doxygen package) and graphviz (graphviz package) tools are required. Note that only html version of reference manual is supported now. 1) To generate reference manaual in html, use "make html" + +To generate user and theory manuals, use "make html! or "make latexpdf". [4] Bugs ============================================================================== diff --git a/doc/elementlibmanual/elementlibmanual.tex b/doc/elementlibmanual/elementlibmanual.tex index 4fd04be11..696f9e144 100644 --- a/doc/elementlibmanual/elementlibmanual.tex +++ b/doc/elementlibmanual/elementlibmanual.tex @@ -22,7 +22,7 @@ \usepackage{tikz} \usepackage{hyperref} \usepackage[top=0.1\paperheight, bottom=0.1\paperheight, left=0.1\paperwidth, right=0.1\paperwidth]{geometry} -\usepackage[backend=biber]{biblatex} +%\usepackage[backend=biber]{biblatex} \usepackage{ifthen} \usetikzlibrary{external} @@ -51,11 +51,12 @@ \input{../include/include.tex} %% fix for \blx@shorthands as this was removed from current biblatex version -%\makeatletter -%\@ifpackageloaded{tex4ht}{ -% \def\blx@shorthands{} -%} -%\makeatother +\makeatletter +\@ifpackageloaded{tex4ht}{ + \def\blx@shorthands{} +% \def\blx@unitmark{} +} +\makeatother \renewcommand{\topfraction}{0.99} % 99% of page top can be a float \renewcommand{\bottomfraction}{0.99} % 99% of page bottom can be a float @@ -123,7 +124,7 @@ {\setcounter{nelpar}{1}Parameters&{#1}}% \\% } -\newcommand{\elementDescription}[2]{{#1} & {#2}\\ } +\newcommand{\elementDescription}[2]{{#1} & {#2}\\} \newcommand{\ignore}[1]{} @@ -133,7 +134,7 @@ \newcommand{\recentry}[2]{\ifthenelse{\value{rcc}>0}{&$\backslash$ \\}{\setcounter{rcc}{1}}{#1}&{#2}} -\addbibresource{References.bib} +%\addbibresource{References.bib} \begin{document} @@ -234,7 +235,15 @@ \subsubsection{Truss 3D element} \label{Truss3d} Two node linear isoparametric truss element for 3D analysis. The -element geometry is specified in (x,y,z) plane. The element features are summarized in Table~\ref{truss3dsummary}. +element geometry is specified in (x,y,z) space. The element features are summarized in Table~\ref{truss3dsummary}. + +\begin{figure}[htb] + \centering + \begin{makeimage} + \input{truss3d.tikz} + \end{makeimage} + \caption{Truss3d element in (x,y,z) space.} +\end{figure} \begin{elementsummary}{truss3d}{3D truss element}{-}{truss3d element summary}{truss3dsummary} @@ -343,10 +352,12 @@ \subsubsection{Beam3d element} %----------------------------------------------------------------------------------------------- \clearpage -\subsection{LatticeElements} -\subsubsection{Lattice2d} +\subsection{Lattice elements} +\subsubsection{Lattice2d element} Represents two-node lattice element. Each node has 3 degrees of freedom. -The element is defined in x,y plane. The element features are summarized in Table~\ref{lattice2dsummary}. +The element is based on the Rigid Body Spring Model originally developed by Kawai and later delveloped by Bolander for modelling fracture in concrete. The main idea is to model the elastic and inelastic response of a connection of two nodes by a set of springs located at the contact facet of two rigid bodies, which is the mid-cross-section of the element. Displacement jumps are computed at the mid-cross-section, which are smeared out over the element length in the form of strains. +The element is defined in x,y plane (see Figure~\ref{lattice2dfig}). +The element features are summarized in Table~\ref{lattice2dsummary}. \begin{figure}[htb] \centering @@ -357,13 +368,125 @@ \subsubsection{Lattice2d} \label{lattice2dfig} \end{figure} -\begin{elementsummary}{lattice2d}{Lattice element}{\field{thick}{rn} \field{width}{rn} \field{gpCoords}{ra}}{lattice2d element summary}{lattice2dsummary} +\begin{elementsummary}{lattice2d}{2d lattice element}{\field{thick}{rn} \field{width}{rn} \field{gpCoords}{ra}}{lattice2d element summary}{lattice2dsummary} \elementParam{\param{thick}: defines the out of plane ($z$-direction) thickness} \elementParam{\param{width}: defines the width of the midpoint cross-section in the $x$-$y$ plane with the point $C$ at its centre} \elementParam{\param{gpCooords}: array of the coordinates of the integration point $C$ in the global coordinate system} \elementDescription{Unknowns}{Three dofs ($u$-displacement, $v$-displacement, $w$-rotation) are required in each node.} \end{elementsummary} +The theory of lattice2d is described in the paper ``P. Grassl and M. Jir\'{a}sek. Meso-scale approach to modelling the fracture process zone of concrete subjected to uniaxial tension. International Journal of Solids and Structures. Volume 47, Issues 7-8, pp. 957-968, 2010.'' + +\subsubsection{Lattice2dBoundary element} +Represents three-node lattice element for boundary of 2d periodic cells. The first two nodes have 3 degrees of freedom as for the element lattice2d. The third node is used to control the loading of the periodic cell. It has three components which are displacements, which are produces of the macroscopic (average) strain components and length of the peridodic cell as $aE_{xx}$, $bE_{xx}$ and $bG_{xy}$ and the length of the periodic cell. The DOFs of the node that lies outside the periodic are computed from those of the periodic image inside the cell and the DOFs at the third node (Figure~\ref{lattice2dboundaryfig}). The coordinates $x$ and $y$ of the third node are the lengths $a$ and $b$ of the periodic cell, respectively. The element is defined in x,y plane. The strain components at the additional node have the meaning of average strains in the periodic cell. The specific input parameters for this element in addition to those used for lattice2d are shown in Table~\ref{lattice2dboundarysummary}. +\begin{figure}[htb] + \centering + \includegraphics[width=0.4\textwidth]{./lattice2dboundaryfig.pdf} + \caption{Lattice2dboundary element. Elements with cross boundary of periodic cell use DOFs of node inside cell and average strain values of periodic cell.} + \label{lattice2dboundaryfig} +\end{figure} + +\begin{elementsummary}{lattice2dboundary}{2d lattice boundary element}{\field{location}{in}}{lattice2dboundary element summary}{lattice2dboundarysummary} + +\elementParam{\param{location}: number between 1 and 8 which specifies the location of the node with respect to the periodic cell.} + +\elementDescription{Unknowns}{Nine DOFs are required, which are $u$-displacement, $v$-displacement and $w$-rotation at nodes 1 and 2, and $aE_{xx}$, $bE_{yy}$ and $bG_{xy}$ at node 3.} +\elementDescription{Reference}{\cite{GraJir10}} +\end{elementsummary} + +\subsubsection{Lattice3d element} +Lattice3d represents a two-node 3d lattice element. Each node has six degrees of freedom as shown in Figure~\ref{lattice3dfig}. +The element is based on the Rigid Body Spring Model originally developed by Kawai and later delveloped by Bolander for modelling fracture in concrete. The main idea is to model the elastic and inelastic response of a connection of two nodes by a set of springs located at the contact facet of two rigid bodies, which is the mid-cross-section of the element. The properties of the mid-cross-section are internally computed from its vertices which are given as input in the global coordinate sytem. Displacement jumps are computed at the mid-cross-section, which are smeared out over the element length in the form of strains. +The input parameters for this element are shown in Table~\ref{lattice3dsummary}. + +\begin{figure}[htb] + \centering + \includegraphics[width=0.3\textwidth]{./lattice3d.pdf} + \caption{Lattice3d element. Node numbering, DOF numbering, cross-section vertices and local coordinate system at integration point $C$.} + \label{lattice3dfig} +\end{figure} + +\begin{elementsummary}{lattice3d}{3d lattice element}{\field{polycoords}{ra} \field{couplingflag}{in} \field{couplingnumbers}{ra} \field{pressures}{ra} \field{mlength}{rn}}{lattice3d element summary}{lattice3dsummary} +\elementParam{\param{polycooords}: array of the coordinates of the vertices of the mid-cross-section of the lattice element in the global coordinate system.} +\elementParam{\param{couplingflag}: flag (optional parameter. Default is 0) which activates coupling with a transport lattice element.} +\elementParam{\param{couplingnumbers}: array of numbers of transport lattice elements (optional parameter), which are coupled with the 3d lattice element.} +\elementParam{\param{pressures}: array of pressure values (optional parameter), which are used to consider influence of fluid pressure on mechanical response.} +\elementParam{\param{mlength}: minimum length (optional parameter) is used to check if the cross-section of the element is not too small. Default value is 1.e-20.} +\elementDescription{Unknowns}{Six dofs ($u$-displacement, $v$-displacement, $w$-displacement, $u$-rotation, $v$-rotation and $w$-rotation) are required in each node.} +\elementDescription{Reference}{\cite{GraBol16}} +\end{elementsummary} + + +\subsubsection{Lattice3dBoundary element} +This element represents a three-noded 3d lattice element for boundaries of 3d periodic cells. The first two nodes have 6 degrees of freedom as for the element lattice3d. The third node is used to control the loading of the periodic cell using three normal ($aE_{xx}$, $bE_{yy}$ and $zE_{zz}$) and three shear strain ($cG_{yz}$, $cG_{xz}$, $bG_{xy}$) components. Here, $a$, $b$ and $c$ are the three dimensions of the periodic cell. The DOFs of the node that lies outside the periodic are computed from those of the periodic image inside the cell and the DOFs at the third node (Figure~\ref{lattice3dboundaryfig}). The connection between periodic nodes is defined as +\begin{equation} + \mathbf{x}^{'} = \mathbf{M} \mathbf{x} +\end{equation} +Here, $\mathbf{x}^{'}$ and $\mathbf{x}$ are the nodes inside and outside, respectively, and $\mathbf{M}$ is the translation matrix, for which the input is provided in the form of a location parameter as shown in Table~\ref{lattice3dboundarysummary}. + +\begin{figure}[htb] + \centering + \includegraphics[width=0.6\textwidth]{./lattice3dboundaryfig.pdf} + \caption{Lattice3dboundary element. Elements with cross boundary of periodic cell use DOFs of node inside cell and average strain values of periodic cell.} + \label{lattice3dboundaryfig} +\end{figure} + +\begin{elementsummary}{lattice3dboundary}{3d lattice boundary element}{\field{location}{in}}{lattice3dboundary element summary}{lattice3dboundarysummary} +\elementParam{\param{location}: array of two numbers between number between 1 and 26, which specifies the location of the two nodes with respect to the 3d periodic cell.} +\elementDescription{Unknowns}{Six dofs ($u$-displacement, $v$-displacement, $w$-displacement, $u$-rotation, $v$-rotation and $w$-rotation) are required in each of the first two node. Node 3 requires the 6 quantities to control the periodic cell $aE_{xx}$, $bE_{yy}$, $zE_{zz}$, $cG_{yz}$, $cG_{xz}$ and $bG_{xy}$ } +\elementDescription{Reference}{\cite{AthWheGra18}} +\end{elementsummary} + +\subsubsection{Latticelink3d element} +This element represents a two-node 3d link element connecting 3d beam and 3d lattice elements. Each node has six degrees of freedom. +The input parameters for this element are shown in Table~\ref{latticelink3dsummary}. + +\begin{elementsummary}{latticelink3d}{3d lattice link element}{\field{length}{rn} \field{diameter}{rn} \field{dirvector}{ra} \field{l\_end}{rn}}{latticelink3d element summary}{latticelink3dsummary} +\elementParam{\param{length}: bond length} +\elementParam{\param{diameter}: diameter } +\elementParam{\param{dirvector}: direction vector in which bond-slip occurs.} +\elementParam{\param{l\_end}: array of pressure values (optional parameter), which are used to consider influence of fluid pressure on mechanical response.} +\elementParam{\param{mlength}: minimum length (optional parameter) is used to check if the cross-section of the element is not too small. Default value is 1.e-20.} +\elementDescription{Unknowns}{Six dofs ($u$-displacement, $v$-displacement, $w$-displacement, $u$-rotation, $v$-rotation and $w$-rotation) are required in each node.} +\elementDescription{Reference}{\cite{GraAnt19}} +\end{elementsummary} + +\subsubsection{Latticelink3dboundary element} +Represents three-node 3d boundary link element connecting 3d beam and 3d lattice elements. The first two nodes have the same meaning as for latticelink3d. The third node is used to control the loading of the periodic cell using three normal (xx, yy and zz) and three shear strain (yz, xz, xy) components. +The specific input parameters for this element in addition of those for latticelink3d are shown in Table~\ref{latticelink3dboundarysummary}. + +\begin{elementsummary}{latticelink3dboundary}{3d lattice link boundary element}{{ \field{location}{in} }{rn}}{latticelink3dboundary element summary}{latticelink3dboundarysummary} +\elementParam{\param{location}: } +\elementDescription{Unknowns}{Six dofs ($u$-displacement, $v$-displacement, $w$-displacement, $u$-rotation, $v$-rotation and $w$-rotation) are required in each node.} +\elementDescription{Reference}{\cite{GraAnt19}} +\end{elementsummary} + + \subsubsection{Latticeframe3d element} + Latticeframe3d represents a two-node linear 3d frame element. Each node has six degrees of freedom, namely three translations and three rotations. The element is based on the link between rigid body spring and Timoshenko frame models. The main idea is to model the elastic and inelastic response of a connection of two nodes by a set of springs located at the contact facet of two rigid bodies. Displacement jumps are computed at the contact facet, which are smeared out over the element length in the form of strains. The input parameters for this element are shown in Table ~\ref{latticeframe3dsummary}. For the computation of the nodal forces, the initial configuration is used. +%% \begin{figure}[htb] +%% \centering +%% \includegraphics[width=0.3\textwidth]{./latticeframe.png} +%% \includegraphics[width=0.3\textwidth]{./latticeframe1.png} +%% \caption{latticeframe3d element. Node numbering, DOF numbering, cross-section vertices and local coordinate system at integration point.} +%% \label{latticeframe3dfig} +%% \end{figure} + + \begin{elementsummary}{latticeframe3d}{3d lattice frame element}{{ \field{zaxis}{ra} }{rn}}{latticeframe3d element summary}{latticeframe3dsummary} +\elementParam{\param{zaxis}: z-axis of local coordinate system } +\elementDescription{CS properties}{Area, inertia moment along y and z axis (\param{iy} and \param{iz} parameters), torsion inertia moment (\param{ik} parameter) and either cross section area shear correction factor (\param{beamshearcoeff} parameter) or equivalent shear areas (\param{shearareay} and \param{shearareaz} parameters) are required. These cross section properties are assumed to be defined in local coordinate system of element.} +\elementDescription{Unknowns}{Six dofs ($u$-displacement, $v$-displacement, $w$-displacement, $u$-rotation, $v$-rotation and $w$-rotation) are required in each node.} +\elementDescription{Reference}{\cite{Toi91, Toi93}} +\end{elementsummary} + + \subsubsection{Latticeframe3dnl element} + Latticeframe3dnl represents a two-node nonlinear 3d frame element. Each node has six degrees of freedom, namely three translations and three rotations. The element is based on the link between rigid body spring and Timoshenko frame models. The main idea is to model the elastic and inelastic response of a connection of two nodes by a set of springs located at the contact facet of two rigid bodies. Displacement jumps are computed at the contact facet considering the incrementally deformed geometry, which are smeared out over the element length in the form of strains. The input parameters for this element are shown in Table ~\ref{latticeframe3dnlsummary}. For the computation of the nodal forces, the incrementally deformed configuration is used. At the start of each step the local co-ordinate system is updated with the displacements of the previous step. + + \begin{elementsummary}{latticeframe3dnl}{3d lattice frame element}{{ \field{zaxis}{ra} }{rn}}{latticeframe3d element summary}{latticeframe3dnlsummary} +\elementParam{\param{zaxis}: z-axis of local coordinate system } +\elementDescription{CS properties}{Area, inertia moment along y and z axis (\param{iy} and \param{iz} parameters), torsion inertia moment (\param{ik} parameter) and either cross section area shear correction factor (\param{beamshearcoeff} parameter) or equivalent shear areas (\param{shearareay} and \param{shearareaz} parameters) are required. These cross section properties are assumed to be defined in local coordinate system of element.} +\elementDescription{Unknowns}{Six dofs ($u$-displacement, $v$-displacement, $w$-displacement, $u$-rotation, $v$-rotation and $w$-rotation) are required in each node.} +\elementDescription{Reference}{\cite{Toi91, Toi93, AbdGra23}} +\end{elementsummary} %----------------------------------------------------------------------------------------------- \clearpage @@ -825,7 +948,7 @@ \subsection{Plate \& Shell Elements} -\subsubsection {tr\_shell01 element} +\subsubsection {tr\_shell11 element} Combination of CCT3D plate element (Mindlin hypothesis) with triangular plane stress element for membrane behavior. It comes with complete set of 6 DOFs per node. The element features are summarized in Table~\ref{trshell01summary}. @@ -834,14 +957,14 @@ \subsection{Plate \& Shell Elements} \begin{makeimage} \input{trshell_lin.tikz} \end{makeimage} - \caption{Geometry of tr\_shell01 element.} + \caption{Geometry of tr\_shell11 element.} \end{figure} -\begin{elementsummary}{tr\_shell01}{Triangular shell element combining CCT3D plate element (Mindlin hypothesis) with triangular plane stress element with rotational DOFs}{-}{tr\_shell01 element summary}{trshell01summary} +\begin{elementsummary}{tr\_shell11}{Triangular shell element combining CCT3D plate element (Mindlin hypothesis) with triangular plane stress element with rotational DOFs}{-}{tr\_shell01 element summary}{trshell01summary} %\elementParam{\param{NIP}: allows to set the number of integration points for integration of membrane terms.} \elementDescription{Unknowns}{Six dofs (u,v,w-displacements and u,v,w rotations) are in general required in each node.} \elementDescription{Approximation}{See description of cct and trplanstrrot elements} -\elementDescription{Integration}{Integration of all terms using one point formula.} +\elementDescription{Integration}{Four point integration, reduced integration of strain associated to normal rotation and shear terms.} \elementDescription{Features}{Layered cross section support.} \elementDescription{CS properties}{Cross section thickness is required.} \elementDescription{Loads}{Body loads are supported. Boundary loads are supported (only surface loads).} @@ -856,6 +979,7 @@ \subsection{Plate \& Shell Elements} Please note, for example, that bending moment $m_x$ is defined as $m_x=\int \sigma_x z\ dz$, so it acts along the y-axis and positive value causes tension in bottom layer.} \elementDescription{Nlgeo}{0.} \elementDescription{Status}{Reliable} +\elementDescription{Tests}{sm/trshell11\_1.in} \end{elementsummary} @@ -882,6 +1006,7 @@ \subsection{Plate \& Shell Elements} Please note, for example, that bending moment $m_x$ is defined as $m_x=\int \sigma_x z\ dz$, so it acts along the y-axis and positive value causes tension in bottom layer.} \elementDescription{Nlgeo}{0.} \elementDescription{Status}{-} +\elementDescription{Note}{Works only with linear material models, as bending and membrane actions are uncoupled} \end{elementsummary} @@ -1256,14 +1381,13 @@ \subsection{Interface elements} \paragraph{Ordering convention:} All inerface elements have \emph{plus}-side and a \emph{minus}-side and all nodes should first be specified for the minus-side and then the plus-side. The normal to the interface is defined to point from the minus-side to the-plus side. Direction of normal vector on an element specifies normal stress/cohesion across the element. It is assumed that normal jump, normal traction are at the first position of corresponding vectors. Stiffness matrix in local coordinates has always on position 1,1 normal stiffness and then shear stiffness. -\subsubsection{IntElPoint} -\subsubsection{Interface1d element} +\subsubsection{IntElPoint, Interface1d elements} Implementation of one dimensional (slip) interface element. This element connects two separate nodes and the interaction is governed by a one-dimensional slip law. This law determines the force acting between the nodes as a function on their relative displacement in the slip direction. The element can be used in 1D, 2D, and 3D (default) and its features are summarized in Table~\ref{Interface1dsummary}. -\begin{elementsummary}{Interface1d}{One dimensional (slip) interface element}{\optField{refnode}{in} \optField{normal}{ra}}{Interface1d element summary}{Interface1dsummary} +\begin{elementsummary}{IntElPoint, Interface1d (deprecated)}{One dimensional (slip) interface element}{\optField{refnode}{in} \optField{normal}{ra}}{IntElPoint element summary}{Interface1dsummary} \elementParam{\param{refnode}: determines the reference node, which is used to specify a reference direction (the direction vector is obtained by subtracting the coordinates of the first node from the reference node).} \elementParam{\param{normal}: The reference direction can be directly specified by the optional parameter \param{normal}. Although both \param{refnode} and \param{normal} are optional, at least one of them must be specified.} @@ -1279,11 +1403,9 @@ \subsubsection{Interface1d element} \elementDescription{Note}{Element requires material model with \_1dInterface support.} \end{elementsummary} -\subsubsection{IntElLine1 element} -\subsubsection{Interface2dlin element} +\subsubsection{IntElLine1, Interface2dlin elements} Implementation of a two dimensional line element with a linear approximation of the displacement jump. -The element can be used to tie together two element edges and is defined by four nodes - two on each edge. Note that, the nodes along the interface are doubled, each couple with identical coordinates. Nodes on the negative side are numbered first, followed by nodes on the positive part. Requires material model with \_2dInterface support. The element features are summarized in Table~\ref{Interface2dlinsummary}. - +The element can be used to tie together two element edges and is defined by four nodes - two on each edge. Note that, the nodes along the interface are doubled, each couple with identical coordinates. Nodes on the negative side are numbered first, followed by nodes on the positive part. Requires material model with \_2dInterface support. The element features are summarized in Table~\ref{IntElLine1}. \begin{figure}[htb] \centering \begin{makeimage} @@ -1293,7 +1415,7 @@ \subsubsection{Interface2dlin element} \label{interf2d_lin_fig} \end{figure} -\begin{elementsummary}{Interface2dlin}{2D interface element with linear approximation}{\optField{axisymmode}{}}{Interface2dlin element summary}{Interface2dlinsummary} +\begin{elementsummary}{IntElLine1, Interface2dlin(deprecated) }{2D interface element with linear approximation}{\optField{axisymmode}{}}{IntElLine1 element summary}{IntElLine1} \elementParam{\param{axisymmode}: Flag controlling axisymmetric mode (integration over unit circumferential angle).} \elementDescription{Unknowns}{Two dofs (u-displacement, v-displacement) are required in each node.} \elementDescription{Approximation}{Linear approximation of displacements and geometry.} @@ -1307,9 +1429,9 @@ \subsubsection{Interface2dlin element} \end{elementsummary} -\subsubsection{Interface2dquad element} +\subsubsection{IntElLine2, Interface2dquad elements} Implementation of a two dimensional interface element with quadratic -approximation of displacement field. Can be used to glue together two elements with quadratic displacement approximation along the shared edge. Note, that the nodes along the interface are doubled, each couple with identical coordinates. Nodes on the negative side are numbered first, followed by nodes on the positive part. Requires material model with \_2dInterface support. The element features are summarized in Table~\ref{Interface2dquadsummary}. +approximation of displacement field. Can be used to glue together two elements with quadratic displacement approximation along the shared edge. Note, that the nodes along the interface are doubled, each couple with identical coordinates. Nodes on the negative side are numbered first, followed by nodes on the positive part. Requires material model with \_2dInterface support. The element features are summarized in Table~\ref{IntElLine2}. \begin{figure}[htb] \centering @@ -1320,7 +1442,7 @@ \subsubsection{Interface2dquad element} \label{interf2d_quad_fig} \end{figure} -\begin{elementsummary}{Interface2dquad}{2D interface element with quadratic approximation}{\optField{axisymmode}{}}{Interface2dquad element summary}{Interface2dquadsummary} +\begin{elementsummary}{IntElLine2, Interface2dquad (deprecated)}{2D interface element with quadratic approximation}{\optField{axisymmode}{}}{IntElLine2 element summary}{IntElLine2} \elementParam{\param{axisymmode}: Flag controlling axisymmetric mode (integration over unit circumferential angle).} \elementDescription{Unknowns}{Two dofs (u-displacement, v-displacement) are required in each node.} \elementDescription{Approximation}{Quadratic approximation of displacements and geometry.} @@ -1333,7 +1455,7 @@ \subsubsection{Interface2dquad element} \elementDescription{Note}{Element requires material model with \_2dInterface support.} \end{elementsummary} -\subsubsection{Interface3dtrlin element} +\subsubsection{IntElSurfTr1, Interface3dtrlin elements} Implementation of a three dimensional interface element with linear approximation of displacement field. Can be used to glue together two elements with linear displacement approximation along the shared triangular surface. Note, that the nodes along the interface are doubled, each couple with identical coordinates. Nodes on the negative surface are numbered first, followed by nodes on the positive part. The numbering of surface nodes on positive surface (+) determines the positive normal (right hand rule). Requires material model with \_3dInterface support. The element features are summarized in Table~\ref{Interface3dtrlinsummary}. @@ -1346,7 +1468,7 @@ \subsubsection{Interface3dtrlin element} \label{interf3d_lin_fig} \end{figure} -\begin{elementsummary}{Interface3dtrlin}{3D interface element with linear approximation}{-}{Interface3dtrlin element summary}{Interface3dtrlinsummary} +\begin{elementsummary}{IntElSurfTr1, Interface3dtrlin (deprecated)}{3D interface element with linear approximation}{-}{IntElSurfTr1 element summary}{Interface3dtrlinsummary} %\elementParam{\param{refnode}: determines the reference node, which is used to specify a reference direction (the direction vector is obtained by subtracting the coordinates of the first node from the reference node).} \elementDescription{Unknowns}{Three dofs (u-displacement, v-displacement, w-displacement) are required in each node.} \elementDescription{Approximation}{Linear approximation of displacements and geometry.} @@ -1359,6 +1481,33 @@ \subsubsection{Interface3dtrlin element} \elementDescription{Note}{Element requires material model with \_3dInterface support.} \end{elementsummary} +\subsubsection{IntElSurfQuad1 element} +Implementation of a three dimensional interface element with linear +approximation of displacement field. Can be used to glue together two elements with linear displacement approximation along the shared quad surface. Note, that the nodes along the interface are doubled, each couple with identical coordinates. Nodes on the negative surface are numbered first, followed by nodes on the positive part. The numbering of surface nodes on positive surface (+) determines the positive normal (right hand rule). Requires material model with \_3dInterface support. The element features are summarized in Table~\ref{Interface3dquadlinsummary}. + +\begin{figure}[htb] + \centering + \begin{makeimage} + \input{interf3dquad_lin.tikz} + \end{makeimage} + \caption{IntElSurfQuad1 element with linear interpolation. Definition and node numbering convention} + \label{interf3dquad_lin_fig} +\end{figure} + +\begin{elementsummary}{IntElSurfQuad1}{3D interface element with linear approximation}{-}{IntElSurfQuad1 element summary}{Interface3dquadlinsummary} +%\elementParam{\param{refnode}: determines the reference node, which is used to specify a reference direction (the direction vector is obtained by subtracting the coordinates of the first node from the reference node).} +\elementDescription{Unknowns}{Three dofs (u-displacement, v-displacement, w-displacement) are required in each node.} +\elementDescription{Approximation}{Linear approximation of displacements and geometry.} +\elementDescription{Integration}{Full integration of all components using one point integration formula.} +\elementDescription{Features}{-} +\elementDescription{CS properties}{-} +\elementDescription{Loads}{-} +\elementDescription{Nlgeo}{0} +\elementDescription{Status}{Reliable} +\elementDescription{Note}{Element requires material model with \_3dInterface support.} +\end{elementsummary} + + %----------------------------------------------------------------------------------------------- \clearpage \subsection{Free warping analysis elements} @@ -1484,8 +1633,10 @@ \subsubsection{LumpedMass element} A different mass and rotary inertia may be assigned to each coordinate direction. At present, individual mass/inertia components can be specified for every degree of freedom of element node. Only displacement and rotational degrees od freedom are considered. The element features are summarized in Table~\ref{LumpedMasssummary}. \begin{elementsummary}{LumpedMass}{Lumped mass element}{\field{components}{ra}}{LumpedMass element summary}{LumpedMasssummary} -\elementParam{\param{components}: allows to specify additional concentrated mass components (Force*Time$^2$/Length) and rotary inertias (Force*Length*Time$^2$) about the nodal coordinate axes. Only displacement and rotational degrees of freedom are considered. The individual DOFs are ordered according to following rule: first, displacement degrees of freedom in the direction of x,y, and z axes (if any), followed by rotational DOFs around x,y, and z axes (if any).} -\elementDescription{Unknowns}{Only displacement and roational DOFs are considered ($D_u$, $D_v$, $D_w$, $R_u$, $R_v$, and $R_w$).} +\elementParam{\param{components}: allows to specify additional concentrated mass components (Force*Time$^2$/Length) and rotary inertias (Force*Length*Time$^2$) about the nodal coordinate axes.} +\elementParam{\param{dofs}: dofs to which the components apply. +} +\elementDescription{Unknowns}{As specified by \param{dofs}.} \elementDescription{Approximation}{-} \elementDescription{Integration}{-} \elementDescription{Features}{-} @@ -1560,7 +1711,7 @@ \subsection{Geometric nonlinear analysis} \end{equation} Thus, for an element to support large deformations (in addition to small deformation) it needs only to implement the $\mathbf{B}_H$ matrix. Similar to the regular \textbf{B} matrix, which gives the strains in Voigt form when multiplied with the solution vector $\textbf{a}$, -$\textbf{B}_H$ should give the displcement gradient in Voigt form with 9 components for a full 3D state. +$\textbf{B}_H$ should give the displacement gradient in Voigt form with 9 components for a full 3D state. % \begin{table} \centering @@ -1579,6 +1730,44 @@ \subsection{Geometric nonlinear analysis} %----------------------------------------------------------------------------------------------- \clearpage \section{Elements for Transport problems (TM Module)} +\subsection{1D Elements} +\subsubsection{Line1ht element} +\label{Line1ht} +Two node linear isoparametric element for for heat transfer problems. Each node has 1 degree of freedom. +The cross section property ``area'' is requested from the cross section. The +element geometry is specified in (x,y,z) plane. The element features are summarized in Table~\ref{Line1htsummary}. +Stabilization through lumped capacity matrix is suggested in transient transport problems, using \entKeywordInst{lumped}. + +\begin{figure}[htb] + \centering + \begin{makeimage} + \input{truss3d.tikz} + \end{makeimage} + \caption{Line1ht element in (x,y,z) space.} +\end{figure} + +\begin{elementsummary}{Line1ht}{Line (truss-like) finite element with linear approximation for heat transfer problems}{-}{Line1ht element summary}{Line1htsummary} +%\elementParam{\param{NIP}: allows to change the default number of integration point used.} +\elementDescription{Unknowns}{Single dof (T\_f - temperature) is required in each node.} +\elementDescription{Approximation}{Linear approximation of temperature.} +\elementDescription{Integration}{Integration using one point gauss integration formula.} +\elementDescription{Loads}{Body loads are supported. Boundary loads are unsupported.} +\elementDescription{Features}{-} +\elementDescription{CS properties}{Area} +\elementDescription{Status}{Reliable} +\end{elementsummary} + +\subsubsection{Line1mt element} +Line (truss-like) finite element with linear approximation of moisture. +Other features are the same as for Line1ht in Section~\ref{Line1ht}. + +\subsubsection{Line1hmt element} +Line (truss-like) finite element with linear approximations of temperature and moisture. +Other features are the same as for Tr1ht in Section~\ref{Line1ht}. + + + + \subsection{2D Elements} \subsubsection{Tr1ht element} \label{Tr1ht} @@ -1629,7 +1818,7 @@ \subsubsection{Quad1ht element} Problem should be defined in x,y plane. The cross section thickness property is requested form cross section model. The nodes should be numbered anti-clockwise (positive rotation around -z-axis). The element features are summarized in Table~\ref{Quad1htsummary}. +z-axis). The element features are summarized in Table~\ref{Quad1htsummary}. \begin{figure}[htb] \centering @@ -1668,11 +1857,26 @@ \subsubsection{Quad1mt element} \subsubsection{Quad1hmt element} Represents isoparametric four-node quadrilateral finite element for -heat and mass (one constituent) transfer problems. +heat and mass (one constituent) transport problems. Two dofs (T\_f - temperature and C\_1 - concentration) are required in each node. Linear approximation of temperature and mass concentration. Other features are similar to Quad1 element, see section \ref{Quad1ht}. +\subsubsection{QQuad1ht element} +\label{QQuad1ht} +Represents isoparametric quadratic eight-node quadrilateral finite element for +heat transfer problems. Each node has 1 degree of freedom. +Problem should be defined in x,y plane. The cross section thickness +property is requested form the cross section model. +The nodes should be numbered anti-clockwise (positive rotation around +z-axis), see fig.~\ref{qplanstrssfig}. The element has the same features as in Table~\ref{Quad1htsummary}. + +\subsubsection{QQuad1mt element} +Element for mass transport problems, see the parent element in sec.~\ref{QQuad1ht}. + +\subsubsection{QQuad1hmt element} +Element for heat and mass transport problems, see the parent element in sec.~\ref{QQuad1ht}. + %----------------------------------------------------------------------------------------------- \clearpage \subsection{Axisymmetric Elements} @@ -1767,6 +1971,10 @@ \subsubsection{QBrick1ht - quadratic hexahedral 3D element}\label{QBrick1ht_elem \elementDescription{Status}{} \end{elementsummary} +\subsubsection{QBrick1mt - quadratic hexahedral 3D element} +The same element as QBrick1ht for mass transfer problems, see \ref{QBrick1ht_element}. +Linear approximation of mass concentration. + \subsubsection{QBrick1hmt - quadratic hexahedral 3D element} The same element as QBrick1ht for heat and mass (one constituent) transfer problems. @@ -2056,8 +2264,19 @@ \subsubsection{Tet1\_3D\_SUPG element} % References; -\printbibliography - +%\printbibliography + +\begin{thebibliography}{99} +\bibitem{RobertCook1989} R. D. Cook and D. S. Malkus and M. E. Plesha, ``Concepts and Applications of Finite Element Analysis'', Third Edition, isbn: 0-471-84788-7, 1989. +\bibitem{BittnarSejnoha1996} Z. Bittnar and J. Sejnoha, ``Numerical Methods in Structural Mechanics'',Thomas Telford,isbn:978-0784401705, 1996. +\bibitem{RagnarLarsson2011} R. Larsson and J. Mediavilla and M. Fagerström, ``Dynamic fracture modeling in shell structures based on XFEM'', International Journal for Numerical Methods in Engineering, vol. 86, no. 4-5, 499--527, 2011. +\bibitem{GraJir10} P. Grassl and M. Jir\'{a}sek, ``Meso-scale approach to modelling the fracture process zone of concrete subjected to uniaxial tension'', International Journal of Solids and Structures, vol. 47, iss. 7-8, pp. 957-968, 2010.. +\bibitem{GraBol16} P. Grassl, J. Bolander, ``Three-Dimensional Network Model for Coupling of Fracture and Mass Transport in Quasi-Brittle Geomaterials'', Materials, 9, 782, 2016 +\bibitem{AthWheGra18} I. Athanasiadis, S. Wheeler and P. Grassl. ``Hydro-mechanical network modelling of particulate composites'', International Journal of Solids and Structures, vol. 130-131, pp. 49-60, 2018. +\bibitem{GraAnt19} P. Grassl and A. Antonelli. ``3D network modelling of fracture processes in fibre-reinforced geomaterials'', International Journal of Solids and Structures, vol. 156-157, pp. 234-242, 2019. +\bibitem{Toi91} Y. Toi. ``Shifted integration technique in oneâ€dimensional plastic collapse analysis using linear and cubic finite elements'', International Journal for Numerical Methods in Engineering 31, no. 8, pp. 1537-1552, 1991. +\bibitem{AbdGra23} G. Abdelrhim and P. Grassl. ``On a geometric nonlinear Timoshenko frame element with material nonlinearity'', Annual Conference of the UK Association for Computational Mechanics (UKACM), The University of Warwick, UK, 19-21 April 2023. +\end{thebibliography} \end{document} diff --git a/doc/elementlibmanual/interf3dquad_lin.tikz b/doc/elementlibmanual/interf3dquad_lin.tikz new file mode 100644 index 000000000..859fe40e0 --- /dev/null +++ b/doc/elementlibmanual/interf3dquad_lin.tikz @@ -0,0 +1,39 @@ +\begin{tikzpicture}[scale=5,>=stealth, + x={(1cm,0cm)}, y={(-0.5cm,-0.5cm)}, z={(0cm,1cm)}] + \tikzstyle{elemnode} = [solid,draw,thin,circle,inner sep=1,fill=white] + + \begin{scope} + %\draw[->] (-0.05,0,0) -- (0.5,0,0) node[at end, below] {$x_g$}; + %\draw[->] (0,-0.05,0) -- (0,0.5,0) node[at end, below] {$y_g$}; + %\draw[->] (0,0,-0.05) -- (0,0,0.25) node[at end, right] {$z_g$}; + \end{scope} + + \begin{scope}[xshift=-2.5] + \draw[dotted] (0,0,0) -- (-1,0,0) (0,0,1) -- (0,0,0) -- (0,1,0) ; + \draw[dotted] (-1,0,1) -- (-1,0,0) -- (-1,1,0) ; + \draw[dashed] (-1,1,0) -- (0,1,0) -- (0,1,1) -- (-1,1,1) -- cycle; + \draw[dashed] (-1,1,1) -- (-1,0,1) -- (0,0,1) -- (0,1,1) -- cycle; + \end{scope} + + \begin{scope}[xshift=5] + \draw[dotted] (0,0,0) -- (1,0,0) (0,0,1) -- (0,0,0) -- (0,1,0); + \draw[dotted] (1,0,1) -- (1,0,0) -- (1,1,0) ; + \draw[dashed] (1,1,0) -- (0,1,0) -- (0,1,1) -- (1,1,1) -- cycle; + \draw[dashed] (1,1,1) -- (1,0,1) -- (0,0,1) -- (0,1,1) -- cycle; + \end{scope} + + \draw[fill=red,opacity=0.05] (0,0,0) -- (0,1,0) -- (0,1,1) -- (0,1,1) -- (0,0,1) --cycle; + \draw[thick,red] (0,0,0) node[elemnode] {} node[left] {1} + -- (0,1,0) node[elemnode] {} node[below] {4} + -- (0,1,1) node[elemnode] {} node[above] {3} + -- (0,0,1) node[elemnode] {} node[above] {2} + -- cycle node[draw,circle,inner sep=0] at (0,0.5,0.5) {\scriptsize $-$}; + + \draw[fill=black,opacity=0.1,xshift=2.5] (0,0,0) -- (0,1,0) -- (0,1,1) -- (0,0,1) -- cycle; + \draw[thick,xshift=2.5] (0,0,0) node[elemnode] {} node[right] {5} + -- (0,1,0) node[elemnode] {} node[below] {8} + -- (0,1,1) node[elemnode] {} node[above] {7} + -- (0,0,1) node[elemnode] {} node[above] {6} + -- cycle node[draw,circle,inner sep=0] at (0,0.5,0.5) {\scriptsize $+$}; + +\end{tikzpicture} diff --git a/doc/elementlibmanual/lattice2dboundaryfig.pdf b/doc/elementlibmanual/lattice2dboundaryfig.pdf new file mode 100644 index 000000000..f21413a18 Binary files /dev/null and b/doc/elementlibmanual/lattice2dboundaryfig.pdf differ diff --git a/doc/elementlibmanual/lattice2dboundaryfig.svg b/doc/elementlibmanual/lattice2dboundaryfig.svg new file mode 100644 index 000000000..368de9127 --- /dev/null +++ b/doc/elementlibmanual/lattice2dboundaryfig.svg @@ -0,0 +1,855 @@ + +image/svg+xml  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/elementlibmanual/lattice3d.pdf b/doc/elementlibmanual/lattice3d.pdf new file mode 100644 index 000000000..7e6b52ab1 Binary files /dev/null and b/doc/elementlibmanual/lattice3d.pdf differ diff --git a/doc/elementlibmanual/lattice3d.svg b/doc/elementlibmanual/lattice3d.svg new file mode 100644 index 000000000..e1a275b92 --- /dev/null +++ b/doc/elementlibmanual/lattice3d.svg @@ -0,0 +1,3373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/elementlibmanual/lattice3dboundaryfig.pdf b/doc/elementlibmanual/lattice3dboundaryfig.pdf new file mode 100644 index 000000000..739450b74 Binary files /dev/null and b/doc/elementlibmanual/lattice3dboundaryfig.pdf differ diff --git a/doc/elementlibmanual/lattice3dboundaryfig.svg b/doc/elementlibmanual/lattice3dboundaryfig.svg new file mode 100644 index 000000000..fc8665d7c --- /dev/null +++ b/doc/elementlibmanual/lattice3dboundaryfig.svg @@ -0,0 +1,1180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/elementlibmanual/makefile b/doc/elementlibmanual/makefile index 4cf31be00..d5f54d485 100644 --- a/doc/elementlibmanual/makefile +++ b/doc/elementlibmanual/makefile @@ -19,7 +19,7 @@ ps: pdf pdf: rm -f *.toc *.lot *.aux pdflatex -shell-escape elementlibmanual - biber elementlibmanual + # biber elementlibmanual pdflatex -shell-escape elementlibmanual @@ -34,4 +34,5 @@ endif clean: rm -fr html - rm -f *.aux *.dvi *.lof *.log *.toc *.dpth + rm -f *.aux *.dvi *.lof *.log *.toc *.dpth + rm -f elementlibmanual-figure* diff --git a/doc/elementlibmanual/truss3d.tikz b/doc/elementlibmanual/truss3d.tikz new file mode 100644 index 000000000..b1338169e --- /dev/null +++ b/doc/elementlibmanual/truss3d.tikz @@ -0,0 +1,16 @@ +\begin{tikzpicture}[scale=7,>=stealth] + \tikzstyle{elemnode} = [draw=black,thick,fill=white,circle,inner sep=1] + \newcommand{\trusslength}{0.5}; + + \begin{scope} + \draw[->] (-0.05,0,0) -- (0.5,0,0) node[at end, below] {$x_g$}; + \draw[->] (0,-0.05,0) -- (0,0.5,0) node[at end, below right] {$y_g$}; + \draw[->] (0,0,-0.05) -- (0,0,0.5) node[at end, right] {$z_g$}; + \end{scope} + + \draw[very thick] (0.1,0.1) -- +(30:\trusslength) + node[elemnode,at start] {} node[at start,yshift=2,above left] {1} + node[elemnode,at end] {} node[at end,yshift=2,above left] {2}; + %\draw[dotted,->] (0.1,0.1)++(-30:0.42) -- +(-30:0.1) node[below] {$X_1$}; + %\draw[dotted,->] (a)++(-30-90:0.02) -- +(-120:0.1) node[right] {$Z_1$}; +\end{tikzpicture} diff --git a/doc/makefile b/doc/makefile index 738269b06..f9ff4c737 100644 --- a/doc/makefile +++ b/doc/makefile @@ -9,22 +9,26 @@ html: cd matlibmanual; make html cd programmer; make html cd refman; make html + cd theorymanual; make html + cd usermanual; make html ps: cd elementlibmanual; make ps - cd oofemInput; make ps cd paper-actap; make ps cd extractorInput; make ps cd matlibmanual; make ps cd programmer; make ps + cd theorymanual; make ps pdf: cd elementlibmanual; make pdf - cd oofemInput; make pdf + cd oofemInput; make latexpdf cd paper-actap; make pdf cd extractorInput; make pdf cd matlibmanual; make pdf cd programmer; make pdf + cd theorymanual; make pdf + cd usermanual; make latexpdf www-install: ifdef INSTALLDIR @@ -36,6 +40,8 @@ ifdef INSTALLDIR cd matlibmanual; make www-install cd programmer; make www-install cd refman; make www-install + cd theorymanual; make www-install + cd usermanual; make www-install else echo "INSTALLDIR not defined" endif @@ -49,3 +55,4 @@ clean: cd matlibmanual; make clean cd programmer; make clean cd refman; make clean + cd theorymanual; make clean diff --git a/doc/matlibmanual/bondceb_diag.eps b/doc/matlibmanual/bondceb_diag.eps new file mode 100644 index 000000000..c694bf81f --- /dev/null +++ b/doc/matlibmanual/bondceb_diag.eps @@ -0,0 +1,326 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: cairo 1.15.12 (http://cairographics.org) +%%CreationDate: Fri Sep 21 13:57:30 2018 +%%Pages: 1 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%BoundingBox: 369 590 560 763 +%%EndComments +%%BeginProlog +50 dict begin +/q { gsave } bind def +/Q { grestore } bind def +/cm { 6 array astore concat } bind def +/w { setlinewidth } bind def +/J { setlinecap } bind def +/j { setlinejoin } bind def +/M { setmiterlimit } bind def +/d { setdash } bind def +/m { moveto } bind def +/l { lineto } bind def +/c { curveto } bind def +/h { closepath } bind def +/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto + 0 exch rlineto 0 rlineto closepath } bind def +/S { stroke } bind def +/f { fill } bind def +/f* { eofill } bind def +/n { newpath } bind def +/W { clip } bind def +/W* { eoclip } bind def +/BT { } bind def +/ET { } bind def +/BDC { mark 3 1 roll /BDC pdfmark } bind def +/EMC { mark /EMC pdfmark } bind def +/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def +/Tj { show currentpoint cairo_store_point } bind def +/TJ { + { + dup + type /stringtype eq + { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse + } forall + currentpoint cairo_store_point +} bind def +/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore + cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def +/Tf { pop /cairo_font exch def /cairo_font_matrix where + { pop cairo_selectfont } if } bind def +/Td { matrix translate cairo_font_matrix matrix concatmatrix dup + /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point + /cairo_font where { pop cairo_selectfont } if } bind def +/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def + cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def +/g { setgray } bind def +/rg { setrgbcolor } bind def +/d1 { setcachedevice } bind def +/cairo_data_source { + CairoDataIndex CairoData length lt + { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def } + { () } ifelse +} def +/cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def +/cairo_image { image cairo_flush_ascii85_file } def +/cairo_imagemask { imagemask cairo_flush_ascii85_file } def +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%PageBoundingBox: 369 590 560 763 +%%EndPageSetup +q 369 590 191 173 rectclip +1 0 0 -1 0 842 cm q +0 g +0.850394 w +0 J +0 j +[] 0.0 d +4 M q 1 0 0 1 0 0 cm +396.879 237.477 m 551.434 237.477 l S Q +542.93 237.477 m 539.527 240.879 l 551.434 237.477 l 539.527 234.074 l +h +542.93 237.477 m f* +0.907087 w +q -1 0 0 -1 0 0 cm +-542.93 -237.477 m -539.527 -240.879 l -551.434 -237.477 l -539.527 -234.074 + l h +-542.93 -237.477 m S Q +0.850394 w +q 1 0 0 1 0 0 cm +396.879 237.477 m 396.879 82.922 l S Q +396.879 91.426 m 400.281 94.828 l 396.879 82.922 l 393.477 94.828 l h +396.879 91.426 m f* +0.907087 w +q 0 1 -1 0 0 0 cm +91.426 -396.879 m 94.828 -400.281 l 82.922 -396.879 l 94.828 -393.477 l + h +91.426 -396.879 m S Q +0.850394 w +q 1 0 0 1 0 0 cm +507.113 240.023 m 507.113 234.93 l S Q +q 1 0 0 1 0 0 cm +394.332 207.074 m 399.426 207.074 l S Q +q 1 0 0 1 0 0 cm +394.332 144.668 m 399.426 144.668 l S Q +0.425197 w +[ 1.700787 1.700787] 0 d +q 1 0 0 1 0 0 cm +507.113 237.477 m 507.113 144.668 l S Q +[ 1.700787 1.700787] 0 d +q 1 0 0 1 0 0 cm +466.598 237.477 m 466.598 144.668 l S Q +[ 1.700787 1.700787] 0 d +q 1 0 0 1 0 0 cm +426.086 237.477 m 426.086 144.668 l S Q +[ 1.700787 1.700787] 0 d +q 1 0 0 1 0 0 cm +396.879 207.074 m 507.113 207.074 l S Q +[ 1.700787 1.700787] 0 d +q 1 0 0 1 0 0 cm +396.879 144.668 m 426.086 144.668 l S Q +[ 1.700787 1.700787] 0 d +q 1 0 0 1 0 0 cm +466.598 144.668 m 507.113 144.668 l S Q +1.417323 w +[] 0.0 d +q 1 0 0 1 0 0 cm +426.086 144.668 m 466.598 144.668 l 507.113 207.074 l 536.16 207.074 l S Q +q 1 0 0 1 0 0 cm +396.879 237.477 m 403.125 152.691 426.086 144.668 426.086 144.668 c S Q +0.850394 w +q 1 0 0 1 0 0 cm +466.598 240.023 m 466.598 234.93 l S Q +q 1 0 0 1 0 0 cm +426.086 240.023 m 426.086 234.93 l S Q +431.633 245.32 m 431.312 245.336 431.07 245.602 431.07 245.863 c 431.07 + 246.031 431.18 246.219 431.445 246.219 c 431.707 246.219 431.988 246.012 + 431.988 245.543 c 431.988 245 431.48 244.512 430.562 244.512 c 428.988 +244.512 428.539 245.73 428.539 246.258 c 428.539 247.195 429.418 247.363 + 429.773 247.438 c 430.395 247.57 431.012 247.699 431.012 248.355 c 431.012 + 248.656 430.75 249.668 429.305 249.668 c 429.137 249.668 428.219 249.668 + 427.938 249.031 c 428.406 249.086 428.707 248.73 428.707 248.395 c 428.707 + 248.133 428.5 247.98 428.258 247.98 c 427.938 247.98 427.582 248.227 427.582 + 248.77 c 427.582 249.445 428.273 249.93 429.289 249.93 c 431.238 249.93 + 431.707 248.488 431.707 247.945 c 431.707 247.512 431.48 247.211 431.332 + 247.082 c 431.012 246.742 430.656 246.668 430.133 246.574 c 429.699 246.48 + 429.23 246.387 429.23 245.844 c 429.23 245.508 429.512 244.773 430.562 +244.773 c 430.863 244.773 431.461 244.867 431.633 245.32 c h +431.633 245.32 m f +435.359 246.27 m 435.359 246.043 435.359 246.043 435.117 246.043 c 434.574 + 246.566 433.824 246.566 433.484 246.566 c 433.484 246.867 l 433.672 246.867 + 434.234 246.867 434.688 246.645 c 434.688 250.898 l 434.688 251.18 434.688 + 251.293 433.859 251.293 c 433.543 251.293 l 433.543 251.594 l 433.691 251.594 + 434.723 251.555 435.023 251.555 c 435.285 251.555 436.336 251.594 436.523 + 251.594 c 436.523 251.293 l 436.203 251.293 l 435.359 251.293 435.359 251.18 + 435.359 250.898 c h +435.359 246.27 m f +511.688 245.234 m 511.367 245.254 511.125 245.516 511.125 245.777 c 511.125 + 245.945 511.234 246.133 511.5 246.133 c 511.762 246.133 512.043 245.93 +512.043 245.461 c 512.043 244.914 511.535 244.43 510.617 244.43 c 509.043 + 244.43 508.594 245.648 508.594 246.172 c 508.594 247.109 509.473 247.277 + 509.828 247.352 c 510.449 247.484 511.066 247.617 511.066 248.273 c 511.066 + 248.57 510.805 249.586 509.359 249.586 c 509.191 249.586 508.273 249.586 + 507.992 248.945 c 508.461 249.004 508.762 248.648 508.762 248.309 c 508.762 + 248.047 508.555 247.898 508.312 247.898 c 507.992 247.898 507.637 248.141 + 507.637 248.684 c 507.637 249.359 508.328 249.848 509.344 249.848 c 511.293 + 249.848 511.762 248.402 511.762 247.859 c 511.762 247.43 511.535 247.129 + 511.387 246.996 c 511.066 246.66 510.711 246.586 510.188 246.492 c 509.754 + 246.398 509.285 246.305 509.285 245.758 c 509.285 245.422 509.566 244.691 + 510.617 244.691 c 510.918 244.691 511.516 244.785 511.688 245.234 c h +511.688 245.234 m f +514.91 248.715 m 515.566 248.715 516.035 249.164 516.035 250.066 c 516.035 + 251.098 515.414 251.414 514.945 251.414 c 514.609 251.414 513.859 251.32 + 513.52 250.816 c 513.914 250.816 514.008 250.535 514.008 250.348 c 514.008 + 250.082 513.801 249.895 513.539 249.895 c 513.316 249.895 513.07 250.047 + 513.07 250.383 c 513.07 251.172 513.934 251.676 514.945 251.676 c 516.109 + 251.676 516.914 250.891 516.914 250.066 c 516.914 249.41 516.391 248.754 + 515.473 248.566 c 516.332 248.246 516.652 247.629 516.652 247.102 c 516.652 + 246.445 515.902 245.957 514.965 245.957 c 514.047 245.957 513.332 246.41 + 513.332 247.082 c 513.332 247.363 513.52 247.516 513.766 247.516 c 514.027 + 247.516 514.195 247.328 514.195 247.102 c 514.195 246.859 514.027 246.672 + 513.766 246.652 c 514.066 246.297 514.629 246.203 514.945 246.203 c 515.32 + 246.203 515.848 246.391 515.848 247.102 c 515.848 247.457 515.734 247.852 + 515.508 248.098 c 515.246 248.414 515.004 248.434 514.59 248.473 c 514.383 + 248.488 514.363 248.488 514.328 248.488 c 514.309 248.488 514.234 248.508 + 514.234 248.602 c 514.234 248.715 514.309 248.715 514.457 248.715 c h +514.91 248.715 m f +471.277 245.32 m 470.957 245.336 470.715 245.602 470.715 245.863 c 470.715 + 246.031 470.828 246.219 471.09 246.219 c 471.352 246.219 471.633 246.012 + 471.633 245.543 c 471.633 245 471.129 244.512 470.207 244.512 c 468.633 + 244.512 468.184 245.73 468.184 246.258 c 468.184 247.195 469.066 247.363 + 469.422 247.438 c 470.039 247.57 470.66 247.699 470.66 248.355 c 470.66 + 248.656 470.395 249.668 468.953 249.668 c 468.785 249.668 467.863 249.668 + 467.582 249.031 c 468.051 249.086 468.352 248.73 468.352 248.395 c 468.352 + 248.133 468.145 247.98 467.902 247.98 c 467.582 247.98 467.227 248.227 +467.227 248.77 c 467.227 249.445 467.922 249.93 468.934 249.93 c 470.883 + 249.93 471.352 248.488 471.352 247.945 c 471.352 247.512 471.129 247.211 + 470.977 247.082 c 470.66 246.742 470.301 246.668 469.777 246.574 c 469.348 + 246.48 468.879 246.387 468.879 245.844 c 468.879 245.508 469.16 244.773 + 470.207 244.773 c 470.508 244.773 471.109 244.867 471.277 245.32 c h +471.277 245.32 m f +476.43 250.074 m 476.148 250.074 l 476.133 250.262 476.039 250.75 475.926 + 250.824 c 475.867 250.879 475.23 250.879 475.102 250.879 c 473.562 250.879 + l 474.445 250.113 474.742 249.867 475.23 249.473 c 475.852 248.988 476.43 + 248.461 476.43 247.676 c 476.43 246.66 475.551 246.043 474.48 246.043 c + 473.449 246.043 472.738 246.773 472.738 247.543 c 472.738 247.957 473.094 + 248.012 473.188 248.012 c 473.375 248.012 473.617 247.863 473.617 247.562 + c 473.617 247.41 473.562 247.113 473.133 247.113 c 473.395 246.531 473.957 + 246.344 474.352 246.344 c 475.195 246.344 475.625 247 475.625 247.676 c + 475.625 248.406 475.102 248.969 474.836 249.27 c 472.832 251.273 l 472.738 + 251.348 472.738 251.367 472.738 251.594 c 476.188 251.594 l h +476.43 250.074 m f +384.812 197.32 m 386.82 197.32 l 386.969 197.32 387.398 197.32 387.398 +196.91 c 387.398 196.629 387.156 196.629 386.914 196.629 c 383.574 196.629 + l 383.332 196.629 382.863 196.629 382.336 197.191 c 381.945 197.621 381.605 + 198.203 381.605 198.258 c 381.605 198.277 381.605 198.391 381.758 198.391 + c 381.852 198.391 381.867 198.336 381.945 198.242 c 382.523 197.32 383.219 + 197.32 383.461 197.32 c 384.457 197.32 l 383.293 201.164 l 383.238 201.297 + 383.164 201.559 383.164 201.598 c 383.164 201.727 383.258 201.934 383.52 + 201.934 c 383.914 201.934 383.969 201.598 384.008 201.41 c h +384.812 197.32 m f +388.238 200.277 m 389.289 200.277 l 389.289 199.977 l 388.203 199.977 l + 388.203 199.039 l 388.203 198.27 388.652 197.934 389.008 197.934 c 389.082 + 197.934 389.176 197.934 389.254 197.973 c 389.141 198.027 389.066 198.16 + 389.066 198.309 c 389.066 198.535 389.234 198.684 389.457 198.684 c 389.684 + 198.684 389.852 198.535 389.852 198.309 c 389.852 197.934 389.477 197.691 + 389.027 197.691 c 388.371 197.691 387.602 198.16 387.602 199.039 c 387.602 + 199.977 l 386.891 199.977 l 386.891 200.277 l 387.602 200.277 l 387.602 + 202.922 l 387.602 203.277 387.527 203.277 386.984 203.277 c 386.984 203.578 + l 387.02 203.578 387.602 203.539 387.941 203.539 c 388.297 203.539 388.672 + 203.559 389.027 203.578 c 389.027 203.277 l 388.859 203.277 l 388.238 203.277 + 388.238 203.184 388.238 202.902 c h +388.238 200.277 m f +372.215 137.551 m 374.219 137.551 l 374.371 137.551 374.801 137.551 374.801 + 137.141 c 374.801 136.859 374.559 136.859 374.312 136.859 c 370.977 136.859 + l 370.73 136.859 370.262 136.859 369.738 137.422 c 369.344 137.852 369.008 + 138.434 369.008 138.488 c 369.008 138.508 369.008 138.621 369.156 138.621 + c 369.25 138.621 369.27 138.566 369.344 138.473 c 369.926 137.551 370.621 + 137.551 370.863 137.551 c 371.855 137.551 l 370.695 141.395 l 370.637 141.527 + 370.562 141.789 370.562 141.828 c 370.562 141.957 370.656 142.164 370.918 + 142.164 c 371.312 142.164 371.371 141.828 371.406 141.641 c h +372.215 137.551 m f +380.797 141.277 m 380.797 140.547 380.422 140.113 379.539 140.113 c 378.867 + 140.113 378.414 140.469 378.191 140.902 c 378.023 140.301 377.57 140.113 + 376.973 140.113 c 376.277 140.113 375.848 140.488 375.602 140.938 c 375.602 + 140.113 l 374.367 140.207 l 374.367 140.508 l 374.93 140.508 375.004 140.562 + 375.004 140.977 c 375.004 143.152 l 375.004 143.508 374.91 143.508 374.367 + 143.508 c 374.367 143.809 l 374.383 143.809 374.965 143.77 375.32 143.77 + c 375.621 143.77 376.203 143.809 376.277 143.809 c 376.277 143.508 l 375.734 + 143.508 375.66 143.508 375.66 143.152 c 375.66 141.633 l 375.66 140.77 +376.352 140.359 376.898 140.359 c 377.477 140.359 377.555 140.809 377.555 + 141.238 c 377.555 143.152 l 377.555 143.508 377.477 143.508 376.934 143.508 + c 376.934 143.809 l 376.953 143.809 377.535 143.77 377.891 143.77 c 378.191 + 143.77 378.773 143.809 378.848 143.809 c 378.848 143.508 l 378.305 143.508 + 378.227 143.508 378.227 143.152 c 378.227 141.633 l 378.227 140.77 378.922 + 140.359 379.465 140.359 c 380.047 140.359 380.121 140.809 380.121 141.238 + c 380.121 143.152 l 380.121 143.508 380.047 143.508 379.504 143.508 c 379.504 + 143.809 l 379.523 143.809 380.102 143.77 380.461 143.77 c 380.758 143.77 + 381.34 143.809 381.414 143.809 c 381.414 143.508 l 380.871 143.508 380.797 + 143.508 380.797 143.152 c h +380.797 141.277 m f +385.5 141.559 m 385.5 141.125 385.5 140.809 385.105 140.488 c 384.77 140.207 + 384.375 140.078 383.871 140.078 c 383.082 140.078 382.52 140.375 382.52 + 140.883 c 382.52 141.164 382.707 141.297 382.934 141.297 c 383.156 141.297 + 383.324 141.125 383.324 140.902 c 383.324 140.77 383.25 140.582 383.027 + 140.527 c 383.324 140.32 383.812 140.32 383.852 140.32 c 384.32 140.32 +384.844 140.621 384.844 141.332 c 384.844 141.578 l 384.375 141.594 383.832 + 141.633 383.215 141.859 c 382.465 142.121 382.238 142.59 382.238 142.965 + c 382.238 143.676 383.102 143.883 383.699 143.883 c 384.355 143.883 384.75 + 143.508 384.938 143.188 c 384.957 143.527 385.184 143.844 385.574 143.844 + c 385.594 143.844 386.402 143.844 386.402 143.059 c 386.402 142.59 l 386.121 + 142.59 l 386.121 143.039 l 386.121 143.133 386.121 143.527 385.801 143.527 + c 385.5 143.527 385.5 143.133 385.5 143.039 c h +384.844 142.625 m 384.844 143.434 384.133 143.656 383.758 143.656 c 383.324 + 143.656 382.934 143.375 382.934 142.965 c 382.934 142.496 383.324 141.859 + 384.844 141.801 c h +384.844 142.625 m f +389.367 141.934 m 389.367 141.934 389.312 141.859 389.312 141.859 c 389.312 + 141.82 389.855 141.238 389.93 141.164 c 390.23 140.828 390.512 140.508 +391.188 140.508 c 391.188 140.207 l 390.941 140.227 390.699 140.246 390.473 + 140.246 c 390.23 140.246 389.891 140.227 389.648 140.207 c 389.648 140.508 + l 389.781 140.527 389.816 140.621 389.816 140.695 c 389.816 140.715 389.816 + 140.844 389.688 140.977 c 389.105 141.633 l 388.41 140.844 l 388.316 140.75 + 388.316 140.715 388.316 140.676 c 388.316 140.562 388.43 140.508 388.543 + 140.508 c 388.543 140.207 l 388.242 140.227 387.922 140.246 387.605 140.246 + c 387.359 140.246 387.043 140.227 386.797 140.207 c 386.797 140.508 l 387.172 + 140.508 387.398 140.508 387.625 140.75 c 388.656 141.953 l 388.672 141.969 + 388.73 142.027 388.73 142.047 c 388.73 142.062 388.094 142.758 388.016 +142.852 c 387.699 143.188 387.418 143.488 386.762 143.508 c 386.762 143.809 + l 387.004 143.789 387.191 143.77 387.453 143.77 c 387.699 143.77 388.035 + 143.789 388.281 143.809 c 388.281 143.508 l 388.188 143.488 388.109 143.434 + 388.109 143.32 c 388.109 143.152 388.203 143.039 388.336 142.906 c 388.938 + 142.25 l 389.648 143.094 l 389.816 143.266 389.816 143.281 389.816 143.34 + c 389.816 143.488 389.629 143.508 389.594 143.508 c 389.594 143.809 l 389.668 + 143.809 390.266 143.77 390.531 143.77 c 390.793 143.77 391.074 143.789 +391.336 143.809 c 391.336 143.508 l 390.773 143.508 390.719 143.453 390.512 + 143.246 c h +389.367 141.934 m f +385.316 80.227 m 387.32 80.227 l 387.473 80.227 387.902 80.227 387.902 +79.812 c 387.902 79.531 387.66 79.531 387.414 79.531 c 384.078 79.531 l +383.836 79.531 383.367 79.531 382.84 80.094 c 382.445 80.523 382.109 81.105 + 382.109 81.164 c 382.109 81.18 382.109 81.293 382.258 81.293 c 382.352 +81.293 382.371 81.238 382.445 81.145 c 383.027 80.227 383.723 80.227 383.965 + 80.227 c 384.961 80.227 l 383.797 84.07 l 383.742 84.199 383.664 84.461 + 383.664 84.5 c 383.664 84.633 383.758 84.836 384.023 84.836 c 384.414 84.836 + 384.473 84.5 384.508 84.312 c h +385.316 80.227 m f +559.285 246.148 m 558.969 246.168 558.723 246.43 558.723 246.695 c 558.723 + 246.863 558.836 247.051 559.098 247.051 c 559.363 247.051 559.645 246.844 + 559.645 246.375 c 559.645 245.832 559.137 245.344 558.219 245.344 c 556.645 + 245.344 556.191 246.562 556.191 247.086 c 556.191 248.023 557.074 248.195 + 557.43 248.27 c 558.051 248.398 558.668 248.531 558.668 249.188 c 558.668 + 249.488 558.406 250.5 556.961 250.5 c 556.793 250.5 555.875 250.5 555.594 + 249.863 c 556.062 249.918 556.363 249.562 556.363 249.227 c 556.363 248.961 + 556.156 248.812 555.91 248.812 c 555.594 248.812 555.238 249.055 555.238 + 249.602 c 555.238 250.273 555.93 250.762 556.941 250.762 c 558.895 250.762 + 559.363 249.32 559.363 248.773 c 559.363 248.344 559.137 248.043 558.988 + 247.914 c 558.668 247.574 558.312 247.5 557.785 247.406 c 557.355 247.312 + 556.887 247.219 556.887 246.676 c 556.887 246.336 557.168 245.605 558.219 + 245.605 c 558.52 245.605 559.117 245.699 559.285 246.148 c h +559.285 246.148 m f +Q Q +showpage +%%Trailer +end +%%EOF diff --git a/doc/matlibmanual/bondceb_diag.pdf b/doc/matlibmanual/bondceb_diag.pdf new file mode 100644 index 000000000..2886e50a5 Binary files /dev/null and b/doc/matlibmanual/bondceb_diag.pdf differ diff --git a/doc/matlibmanual/matlibmanual.tex b/doc/matlibmanual/matlibmanual.tex index 58c4ff493..14aeb36d3 100644 --- a/doc/matlibmanual/matlibmanual.tex +++ b/doc/matlibmanual/matlibmanual.tex @@ -264,7 +264,36 @@ \subsubsection{General anisotropic linear elastic material - AnisoLE} %\end{center} \end{table} -\subsubsection{Hyperelastic material - HyperMat} +\subsubsection{1D linear elastic material with different tension and compression stiffness - isoAxysymm1D} +\label{isoaxysymm1d} +Bi-linear material model for 1D elasticity, with different elastic moduli in tension and compression. The model parameters are summarized +in Tab.~\ref{isoaxysymm1d_table}. + +\begin{table}[!htb] +%\begin{center} +\begin{mmt} +\hline +Description & Bi-Linear elastic material\\ +\hline +Record Format & \descitem{IsoAxysymm1D} \elemparam{num}{in} +\elemparam{d}{rn} \elemparam{Et}{rn} \elemparam{Ec}{rn} +\elemparam{tAlpha}{rn} [\elemparam{m}{rn}]\\ +Parameters &- \param{num} material model number\\ +&- \param{d} material density\\ +&- \param{Et} Modulus of elasticity in tension\\ +&- \param{Ec} Modulus of elasticity in compression\\ +&- \param{tAlpha} thermal dilatation coefficient\\ +&- \param{m} optional regularization coefficient, default value set to 15, higher value makes response close to trully bilinear\\ +Supported modes& 1dMat\\ +Features & Adaptivity support\\ +\hline +\end{mmt} +\caption{Bi-Linear Elastic Material - summary.} +\label{isoaxysymm1d_table} +%\end{center} +\end{table} + +\subsubsection{Hyperelastic material - Simo-Pister Material} This material model can describe elastic behavior at large strains. A hyperelastic model postulates the existence of free energy potential. Existence of the potential implies reversibility of deformations and no energy dissipation during loading process. Here we use the free energy function introduced in \cite{SimoHughes} \begin{equation}\label{freeEnergy} @@ -283,7 +312,7 @@ \subsubsection{Hyperelastic material - HyperMat} \hline Description & Hyperelastic material\\ \hline -Record Format & \descitem{HyperMat} \elemparam{}{in} +Record Format & \descitem{SimoPisterMat} \elemparam{}{in} \elemparam{d}{rn} \elemparam{K}{rn} \elemparam{G}{rn} \\ Parameters &- \param{} material number\\ &- \param{d} material density\\ @@ -342,7 +371,7 @@ \subsubsection{Hyperelastic material - Compressible Mooney-Rivlin} \hline Description & Mooney-Rivlin\\ \hline - Record Format & \descitem{MooneyRivlin} \elemparam{}{in} + Record Format & \descitem{MooneyRivlinCompressibleMat} \elemparam{}{in} \elemparam{d}{rn} \elemparam{K}{rn} \elemparam{C1}{rn} \elemparam{C2}{rn}\\ Parameters &- \param{} material number\\ &- \param{d} material density\\ @@ -359,6 +388,66 @@ \subsubsection{Hyperelastic material - Compressible Mooney-Rivlin} + +\subsubsection{Hyperelastic material - Compressible Ogden} +The Ogden strain energy function is expressed by +\begin{equation}\label{freeEnergyOgdenDeviatoricStretch} +\rho_0 \psi = \sum_{I=1}^N \frac{\mu_I}{\alpha_I} \left( \bar{\lambda}_1^{\alpha_I}+\bar{\lambda}_2^{\alpha_I}+\bar{\lambda}_3^{\alpha_I}-3\right)+ U(J) +\end{equation} +where $\mu_I$ and $\alpha_I$ are material constants, $U(J)$ is the volumetric part of energy, $J$ is the Jacobian (determinant of the deformation gradient, corresponding to the ratio of the current and initial volume), $\bar{\lambda}_i = J^{-\frac{1}{3}} {\lambda}_i$ are the deviatoric stretches. + +The model description and parameters are summarized in Tab.~\ref{CompressibleOgden_table}. +\begin{table}[!htb] + %\begin{center} + \begin{mmt} + \hline + Description & Ogden material\\ + \hline + Record Format & \descitem{OgdenCompressibleMat} \elemparam{}{in} + \elemparam{d}{rn} \elemparam{K}{rn} \elemparam{alpha}{ra} \elemparam{mu}{ra}\\ + Parameters &- \param{} material number\\ + &- \param{d} material density\\ + &- \param{K} bulk modulus\\ + &- \param{alpha} array of material constants\\ + &- \param{mu} array of material constants\\ + alpha and mu have to have the same size\\ + \hline + \end{mmt} + \caption{Compressible Ogden material - summary.} + \label{CompressibleOgden_table} + %\end{center} +\end{table} + + +\subsubsection{Hyperelastic material - Blatz-Ko} +The Mooney-Rivlin strain energy function is expressed by +\begin{equation}\label{freeEnergyBlatzKo} +\rho_0 \psi = \frac{\mu}{2}\left(\frac{I_2}{I_3} + 2\sqrt{I_3}-5 \right) +\end{equation} +where $\mu$ is initial shear modulus, $I_2$ and $I_3$ are the second and third invariants of the Cauchy-Green tensor $\mbf{C}$. + +The model description and parameters are summarized in Tab.~\ref{BlatzKo_table}. +\begin{table}[!htb] + %\begin{center} + \begin{mmt} + \hline + Description & Blatz-Ko material\\ + \hline + Record Format & \descitem{blatzkomat} \elemparam{}{in} + \elemparam{d}{rn} \elemparam{mu}{rn}\\ + Parameters &- \param{} material number\\ + &- \param{d} material density\\ + &- \param{mu} shear modulus\\ + $\nu$ is fixed to 0.25\\ + \hline + \end{mmt} + \caption{Blatz-Ko material - summary.} + \label{BlatzKo_table} + %\end{center} +\end{table} + + + \subsection{Winkler-Pasternak model} Implementation of 2D winkler-pasternak model for plate (and potentially beam) subsoil model. \begin{table}[!htb] @@ -682,7 +771,7 @@ \subsubsection{Mises plasticity model with isotropic damage - MisesMat} \begin{equation}\label{VMcumPlasStrain} \dot{\kappa} = \| \epspd \|, \end{equation} -the linear hardening law +the linear hardening law (for \param{htype} = 0) \begin{equation}\label{VMlinearHardeningLaw} \sigma_Y(\kappa) = \sigma_0 + H\kappa, \end{equation} @@ -718,13 +807,16 @@ \subsubsection{Mises plasticity model with isotropic damage - MisesMat} Description & Mises plasticity model with isotropic hardening\\ \hline Record Format & \descitem{MisesMat} \elemparam{}{in} -\elemparam{d}{rn} \elemparam{E}{rn} \elemparam{n}{rn} \elemparam{sig0}{rn} \elemparam{H}{rn} \elemparam{omega\_crit}{rn}\elemparam{a}{rn}\\ +\elemparam{d}{rn} \elemparam{E}{rn} \elemparam{n}{rn} \elemparam{sig0}{rn} \elemparam{H}{rn} \optelemparam{htype}{in} \optelemparam{h\_eps}{ra} \optelemparam{h(eps)}{ra} \elemparam{omega\_crit}{rn}\elemparam{a}{rn}\\ Parameters &- \param{} material number\\ &- \param{d} material density\\ &- \param{E} Young's modulus\\ &- \param{n} Poisson's ratio\\ -&- \param{sig0} initial yield stress in uniaxial tension (compression)\\ -&- \param{H} hardening modulus (can be negative in the case of plastic softening)\\ +&- \param{sig0} initial yield stress in uniaxial tension (compression) (Required if htype = 0, which is default)\\ +&- \param{H} hardening modulus (can be negative in the case of plastic softening) (Required if htype = 0, which is default)\\ +&- \param{htype} hardening type (Optional parameter. Default = 0)\\ +&- \param{h\_eps} array of plastic strains (Required if htype = 1)\\ +&- \param{h(eps)} array of yield stresses (Required if htype = 1)\\ &- \param{omega\_crit} critical damage in damage law (\ref{damagelawmp})\\ &- \param{a} exponent in damage law (\ref{damagelawmp})\\ Supported modes& 1dMat, PlaneStrain, 3dMat, 3dMatF\\ @@ -1311,7 +1403,7 @@ \subsubsection{Smeared rotating crack model - Concrete3} &- \param{Gf} fracture energy\\ &- \param{Ft} tension strength\\ &- \param{exp\_soft} determines the type of softening (0 = -exponential, 1 = linear)\\ +linear, 1 = exponential, 2 = Hordijk)\\ &- \param{tAlpha} thermal dilatation coefficient\\ Supported modes& 3dMat, PlaneStress, PlaneStrain, 1dMat, 2dPlateLayer, 2dBeamLayer, 3dShellLayer\\ @@ -1753,6 +1845,105 @@ \subsubsection{Isotropic damage model for tensile failure - Idm1} \varepsilon_3&=&\varepsilon_1\exp\left(-\frac{1}{m}\left(\frac{\varepsilon_1}{\varepsilon_p}\right)^m\right) \label{eqparams3} \end{eqnarray} +\item +{\bf Trilinear softening} is a special formulation proposed by Prof. Gálvez's group to cope with fibre reinforced concrete fracture \cite{AlbGal17}. It is formulated for an embedded crack model and it is expressed in terms of crack opening ($w$). This approach uses a trilinear softening diagram that helps reproducing the FRC behaviour; this diagram is defined by four points: $t$, $k$, $r$ and $f$ that are related to specific properties of concrete, fibres and the fibre proportion. +In order to adapt the original formulation to the \texttt{idm1}, which uses damage $\omega$ as the driving parameter of fracture, instead of crack opening $w$, the correspondence between both must be taken into account. Figure \ref{fig:diagram_sigmaVSw_and_sigmaVSepsilon} shows the trilinear diagram expressed in terms of the crack opening $w$ (left) and in terms of the equivalent strain $\varepsilon$ (right). + +\begin{figure}[htb] + \centering + \includegraphics[width=\textwidth]{trilinear_diagram_sigmaVSw_and_sigmaVSepsilon.eps} + \caption{Trilinear softening diagram expressed in terms of the crack opening ($w$) and expressed in terms of strain.} + \label{fig:diagram_sigmaVSw_and_sigmaVSepsilon} +\end{figure} + +The inelastic strain $\varepsilon_c$ is the difference between the total strain $\varepsilon$ and the elastic strain $\varepsilon/E$, thus: +\[ +\varepsilon_c = \varepsilon - \dfrac{\sigma}{E} +\] + +If $\sigma$ is obtained by using the damage parameter ($\omega$) , it can be expressed as follows: +\begin{equation} +\sigma = (1-\omega) E \varepsilon +\label{eq:sigma} +\end{equation} + + +Therefore, the inelastic strain can be written as: + +\[ +\varepsilon_c = \varepsilon - \dfrac{1}{E}\left( (1-\omega) E \varepsilon\right) \quad \Rightarrow \quad \varepsilon_c = \varepsilon - (1- \omega) \varepsilon = \omega \varepsilon +\] + +Thus, crack opening ($w$) is related to damage ($\omega$) through\footnote{Note that $\omega$ represents damage and $w$ represents crack opening. }: + +\begin{equation} +w = h \varepsilon_c = h \omega \varepsilon +\label{eq:w} +\end{equation} + + + +\noindent where $h$ stands for the effective thickness of the crack band, which is estimated by projecting the finite elmeent onto the direction of the maximum principal strain at the onset of damage. + +Hereafter, the expressions of damage ($\omega$) are obtained for each section of the softening diagram (before damage develops, damage between points $t$ and $k$, between points $k$ and $r$, between points $r$ and $f$ and, finally, after damage has fully developed). +\begin{itemize} + \item {\bf Case 1: $\varepsilon \leq \varepsilon_0$ :} + In this case, damage has not started, thus: + \[ + \omega=0 + \] + And its derivative: + \[ + \dfrac{\partial \omega}{\partial \varepsilon}=0 + \] + \item {\bf Case 2: $\varepsilon_0 \le \varepsilon \leq \varepsilon_k$ :} + Referred to the $\sigma-w$ diagram: + \[ + \sigma = f_t + w \dfrac{f_k -f_t}{w_k} + \] + therefore, since $f_t = E \varepsilon_0$ and using expressions \eqref{eq:sigma} and \eqref{eq:w}: + + \begin{align*} + \omega = \dfrac{E}{E + h \left(\dfrac{f_k-f_t}{w_k}\right) } - \dfrac{E \varepsilon_0}{\varepsilon\left[E + h\left(\dfrac{f_k-f_t}{w_k}\right) \right]} + \end{align*} + And its derivative: + \[ + \dfrac{\partial \omega}{\partial \varepsilon}=\dfrac{E \varepsilon_0}{E + h \left(\dfrac{f_k-f_t}{w_k}\right) } \cdot \dfrac{1}{\varepsilon^2} + \] + \item {\bf Case 3: $\varepsilon_k \le \varepsilon \leq \varepsilon_r$ :} + Referred to the $\sigma-w$ diagram: + \[ + \sigma = f_k + (w-w_k) \left(\dfrac{f_r -f_k}{w_r - w_k} \right) + \] + therefore, using expressions \eqref{eq:sigma} and \eqref{eq:w}: + + \begin{align*} + \omega = \dfrac{E}{E + h \left(\dfrac{f_r-f_k}{w_r - w_k}\right) } +\dfrac{1}{\varepsilon} \cdot \dfrac{w_k \left(\dfrac{f_r-f_k}{w_r - w_k}\right) - f_k}{E + h \left(\dfrac{f_r-f_k}{w_r - w_k}\right) } + \end{align*} + And its derivative: + \[ + \dfrac{\partial \omega}{\partial \varepsilon}=- \dfrac{w_k \left(\dfrac{f_r-f_k}{w_r - w_k}\right) - f_k}{E + h \left(\dfrac{f_r-f_k}{w_r - w_k}\right) } \cdot \dfrac{1}{\varepsilon^2} + \] + \item {\bf Case 4: $\varepsilon_r \le \varepsilon \leq \varepsilon_f$ :} + Referred to the $\sigma-w$ diagram: + \[ + \sigma = f_r + (w-w_r) \left(\dfrac{-f_r}{w_f - w_r} \right) + \] + therefore, using expressions \eqref{eq:sigma} and \eqref{eq:w}: + + \begin{align*} + \omega = \dfrac{E}{E + h \left(\dfrac{ -f_r}{w_f - w_r} \right) } +\dfrac{1}{\varepsilon} \cdot \dfrac{w_r \left(\dfrac{ -f_r}{w_f - w_r} \right) - f_r}{E + h \left(\dfrac{ -f_r}{w_f - w_r} \right) } + \end{align*} + And its derivative: + \[ + \dfrac{\partial \omega}{\partial \varepsilon}=- \dfrac{w_r \left(\dfrac{ -f_r}{w_f - w_r} \right) - f_r}{E + h \left(\dfrac{ -f_r}{w_f - w_r} \right) } \cdot \dfrac{1}{\varepsilon^2} + \] + \item {\bf Case 5: $\varepsilon \geq \varepsilon_f$ :} + In this case, damage is fully developed: + \[ + \omega=1 + \] +\end{itemize} \end{itemize} Note that parameter {\it damlaw} determines which type of damage law @@ -1847,6 +2038,7 @@ \subsubsection{Isotropic damage model for tensile failure - Idm1} \item[5 -] smooth stress-strain curve with parameters e0 and md \item[6 -] disable damage (dummy linear elastic material) \item[7 -] extended smooth damage law (\ref{eq:damageEvol}) with parameters ft, ep, e1, e2, nd +\item[11 -] trilinear softening diagram with (e0, w\_k, w\_r, w\_f, f\_k, f\_r) \end{itemize}\\ &- \param{e0} strain at peak stress (for damage laws 0,1,2,3), limit elastic strain (for damage law 4), characteristic strain (for damage law 5)\\ &- \param{wf} parameter controling ductility, has the meaning of crack opening (for damage laws 0 and 1)\\ @@ -1871,6 +2063,11 @@ \subsubsection{Isotropic damage model for tensile failure - Idm1} (its value is between 0 and 0.999999 (default), and it affects only the secant stiffness but not the stress)\\ &- \param{checkSnapBack} parameter for snap back checking, 0 no check, 1 check (default)\\ +&- \param{w\_k} crack opening of point $k$ in the trilinear diagram (see Fig. \ref{fig:diagram_sigmaVSw_and_sigmaVSepsilon})\\ +&- \param{w\_r} crack opening of point $r$ in the trilinear diagram (see Fig. \ref{fig:diagram_sigmaVSw_and_sigmaVSepsilon})\\ +&- \param{w\_f} crack opening of point $f$ in the trilinear diagram (see Fig. \ref{fig:diagram_sigmaVSw_and_sigmaVSepsilon})\\ +&- \param{f\_k} cohesive stress of point $k$ in the trilinear diagram (see Fig. \ref{fig:diagram_sigmaVSw_and_sigmaVSepsilon})\\ +&- \param{f\_r} cohesive stress of point $r$ in the trilinear diagram (see Fig. \ref{fig:diagram_sigmaVSw_and_sigmaVSepsilon})\\ Supported modes& 3dMat, PlaneStress, PlaneStrain, 1dMat\\ Features & Adaptivity support\\ \hline @@ -2566,7 +2763,7 @@ \subsubsection{Mazars damage model for concrete - MazarsModel} $ of tension damage evolution law is used, if equal 1, the modified law used which asymptotically tends to zero -$g_t = 1.0-(\varepsilon_0/\kappa)*\exp((\varepsilon_0-\kappa)/A_t)$\\ +$g_t = 1.0-(\varepsilon_0/\kappa)*\exp((\varepsilon_0-\kappa)/\varepsilon_f)$\\ &- \param{tAlpha} thermal dilatation coefficient\\ &- \param{equivstraintype} see Tab.~\ref{id_table}\\ &- \param{maxOmega} limit maximum damage, use for convergency improvement\\ @@ -2918,7 +3115,10 @@ \subsubsection{B3 and MPS models for concrete creep with aging} Equation (\ref{eq:mps_viscosity}) differs from the one presented in the original work; it replaces the differential equation for microprestress, which is not used here. The evolution of viscosity can be captured directly, without the need for microprestress. What matters is only the relative humidity and temperature and their rates. Parameters $c_0$ and $k_1$ of the original MPS theory are replaced by $\mu_S = c_0 T_0^{p-1} k_1^{p-1} q_4 (p-1)^p$. -The initial value of viscosity is defined as $\eta(t_0) = t_0/q_4$, where $t_0$ is age of concrete at the onset drying or when the temperature starts changing. +The initial value of viscosity is defined as $\eta(t_0) = t_0/q_4$, +where $t_0$ is age of concrete at the onset drying or when the +temperature starts changing, in the present implementation it is set +$relMatAge$ which corresponds to the material age when the material is cast. %%%% MODIFIED TIMES %%%% As mentioned above, under variable humidity and temperature conditions the physical time $t$ in function $v(t)$ describing evolution of the solidified volume is replaced by the equivalent time $t_e$. In a similar spirit, $t$ is replaced by the solidification time $t_s$ in the equation describing creep of the solidifying constituent, and by the reduced time $t_r$ in equation $\mbox{d} \varepsilon_f / \mbox{d} t_r = \sigma / \eta(t)$ relating the flow strain rate to the stress. @@ -3327,7 +3527,8 @@ \subsubsection{B3 and MPS models for concrete creep with aging} % % % MPS -\elemparam{t0}{rn} \elemparam{ksh}{rn} +%\elemparam{t0}{rn} +\elemparam{ksh}{rn} \optelemparam{mus}{rn} \elemparam{k3}{rn} % \optelemparam{alphaE}{rn} \optelemparam{alphaR}{rn} \optelemparam{alphaS}{rn} @@ -3351,13 +3552,15 @@ \subsubsection{B3 and MPS models for concrete creep with aging} &- \param{mode} optional parameter; if $mode = 0$ (default), parameters $q1-q4$ are predicted from composition of the concrete mixture (parameters fc, cc, w/c, a/c and stiffnessfactor need to be specified). Otherwise values of parameters $q1-q4$ are expected.\\ &- \param{CoupledAnalysisType} $0=$ basic creep; $1=$ (default) drying creep, shrinkage, temperature transient creep and creep at elevated temperature; $2=$ drying creep, shrinkage; $3=$ temperature transient creep and creep at elevated temperature; for choice \# 1, 2, 3 the problem must be run as a staggered problem with preceding analysis of humidity and/or temperature distribution; -Following parameters must be specified: \param{t0}, \param{mus} or \param{k3} (according to exponent \param{p}), \param{kTm} (compulsory for choice \#3 otherwise optional)\\ +Following parameters must be specified: %\param{t0}, +\param{mus} or \param{k3} (according to exponent \param{p}), \param{kTm} (compulsory for choice \#3 otherwise optional)\\ % &- \param{lambda0} scaling factor equal to 1.0 day in time units of analysis (e.g. 86400 if the analysis runs in seconds)\\ &- \param{begoftimeofinterest} lower boundary of time interval with good approximation of the compliance function; default value = 0.01 $lambda0$\\ &- \param{endoftimeofinterest} upper boundary of time interval with good approximation of the compliance function; default value = 10000. $lambda0$\\ &- \param{timefactor} scaling factor, for mps material must be equal to 1.0\\ -&- \param{relMatAge} relative material age\\ +&- \param{relMatAge} relative material age = age at time when the material is +cast in the structure \\ % \hline \end{mmt} @@ -3379,7 +3582,7 @@ \subsubsection{B3 and MPS models for concrete creep with aging} &- \param{mus} parameter governing to the evolution of viscosity; for exponent $p=2$, $\mu_S = c_0 c_1 q_4$ [Pa$^{-1}$ s$^{-1}$] \\ &- \param{k3} dimensionless parameter governing to the evolution of viscosity replacing \param{mus} in the special case when $p > 100$ (then $p$ is automatically set to $\infty$ which is equivalent to $p\_tilde = 1$)\\ &- \param{ksh} parameter relating rate of shrinkage to rate of humidity [-], default value is 0.0, i.e. no shrinkage\\ -&- \param{t0} time of the first temperature or humidity change\\ +%&- \param{t0} time of the first temperature or humidity change\\ &- \param{alphaE} constant, default value 10.\\ &- \param{alphaR} constant, default value 0.1\\ &- \param{alphaS} constant, default value 0.1\\ @@ -3698,7 +3901,7 @@ \subsubsection{Damage-plastic model for concrete - ConcreteDPM} \label{sec:cdpm} It belongs to the class of damage-plastic models with yield condition formulated in terms of the effective stress $\bar{\vsig}=\mD_e:(\veps-\veps_p)$. The stress-strain law is postulated in the form -\beq +\beq\label{cdpm1-1} \vsig = (1-\omega)\bar{\vsig}=(1-\omega)\mD_e:(\veps-\veps_p) \eeq where $\mD_e$ is the elastic stiffness tensor @@ -4000,7 +4203,8 @@ \subsubsection{Damage-plastic model for concrete - ConcreteDPM} \label{sec:cdpm} If the element is too large, it may become too brittle and local snap-back occurs in the stress-strain diagram, which is not acceptable. In such a case, an error message is issued and the program execution -is terminated. The maximum admissible element size +is terminated. The maximum admis +sible element size \begin{equation} h_{\max} = \frac{EG_f}{f_t^2} = \frac{Ew_f}{f_t} \end{equation} @@ -4011,38 +4215,91 @@ \subsubsection{Damage-plastic model for concrete - ConcreteDPM} \label{sec:cdpm} For instance, if the element is a cube of edge length 100 mm, its effective size in the direction of the body diagonal can be 173 mm. -\subsubsection{CDPM2} +\subsubsection{Damage-plastic model for concrete - CDPM2} This model is an extension of the ConcreteDPM presented in \ref{sec:cdpm}. -CDPM2 has been developed by Grassl, Xenos, Nystr\"{o}m, Rempling and Gylltoft for modelling the failure of concrete for both static and dynamic loading. It is is described in detail in \cite{GraXenNys13}. -The main differences between CDPM2 and ConcreteDPM are that in CDPM2 the plasticity part exhibits hardening once damage is active. Furthermore, two independent damage parameters describing tensile and compressive damage are introduced. -The parameters of CDPM2 are summarised in Tab.~\ref{cdpm2_table} - -The stress for the anisotropic damage plasticity model (ISOFLAG=0) is defined as -\begin{equation} -\boldsymbol{\sigma} = \left(1-\omega_{\rm t}\right) \bar{\boldsymbol{\sigma}}_{\rm t} + \left(1-\omega_{\rm c}\right) \bar{\boldsymbol{\sigma}}_{\rm c} -\end{equation} -where $\bar{\boldsymbol{\sigma}}_{\rm t}$ and $\bar{\boldsymbol{\sigma}}_{\rm c}$ are the positive and negative parts of the effective stress tensor $\bar{\boldsymbol{\sigma}}$, respectively, and $\omega_{\rm t}$ and $\omega_{\rm c}$ are two scalar damage variables, ranging from 0 (undamaged) to 1 (fully damaged). +CDPM2 has been developed by Grassl and coworkers for modelling the failure of concrete for both static and dynamic loading. It is is described in detail in \cite{GraXenNys13}. +The main differences between CDPM2 and ConcreteDPM are that in CDPM2 +\begin{itemize} +\item the plasticity part exhibits hardening once damage is active, +\item two independent damage parameters, which describe tensile and compressive damage, are introduced. +\end{itemize} +These extensions provide more flexibility, and the shapes +of stress-strain curves under various loading scenarios, including unloading, can be better adapted. The price to pay +is an increased number of parameters and thus more difficult calibration. -The stress for the isotropic damage plasticity model (ISOFLAG=1) is defined as +CDPM2 deals with the same definition of effective stress as ConcreteDPM, namely \begin{equation} -\boldsymbol{\sigma} = \left(1-\omega_{\rm t}\right) \bar{\boldsymbol{\sigma}} -\end{equation} -The effective stress $\bar{\boldsymbol{\sigma}}$ is defined according to the damage mechanics convention as + \bar{\boldsymbol{\sigma}} = \boldsymbol{D}_e:(\boldsymbol{\varepsilon}-\boldsymbol{\varepsilon}_p) +\end{equation} +which means that the effective stress is computed using the plastic part of the model. +The effect of damage is incorporated in the transformation from effective to nominal stress. +While ConcreteDPM uses a simple reduction factor $1-\omega$ (see (\ref{cdpm1-1})), CDPM2 splits the +effective stress into the positive part, $\bar{\boldsymbol{\sigma}}_{\rm t}$, +and the negative part, $\bar{\boldsymbol{\sigma}}_{\rm c}$, and then uses +two damage variables, $\omega_t$ and $\omega_c$ (for tension and for compression). +The nominal stress is thus evaluated as +\begin{equation}\label{cdpm2:efftonominal} + \boldsymbol{\sigma} = \left(1-\omega_{\rm t}\right) \bar{\boldsymbol{\sigma}}_{\rm t} + \left(1-\omega_{\rm c}\right) \bar{\boldsymbol{\sigma}}_{\rm c} +\end{equation} +The values of $\omega_{\rm t}$ and $\omega_{\rm c}$ range from 0 (undamaged) to 1 (fully damaged). +The decomposition of the effective stress tensor into the positive and negative parts is based +on principal values. If $\bar{\sigma}_I$, $I=1,2,3$, are the principal effective stresses and $\boldsymbol{n}_I$, +$I=1,2,3$, are the corresponding principal directions, the effective stress tensor \begin{equation} -\bar{\boldsymbol{\sigma}} = \mathbf{D}_{\rm e} : \left(\boldsymbol{\varepsilon} - \boldsymbol{\varepsilon}_{\rm p}\right) + \bar{\boldsymbol{\sigma}} = \sum_{I=1}^3 \bar{\sigma}_I\,\boldsymbol{n}_I\otimes\boldsymbol{n}_I \end{equation} +is decomposed into +\begin{eqnarray} + \bar{\boldsymbol{\sigma}}_t &=& \sum_{I=1}^3 \langle\bar{\sigma}_I\,\rangle\boldsymbol{n}_I\otimes\boldsymbol{n}_I \\ + \bar{\boldsymbol{\sigma}}_c &=& -\sum_{I=1}^3 \langle-\bar{\sigma}_I\,\rangle\boldsymbol{n}_I\otimes\boldsymbol{n}_I +\end{eqnarray} +where $\langle\ldots\rangle$ are Macaulay brackets (positive-part operator). -\noindent\textbf{Plasticity:} - -The yield surface is described by the Haigh-Westergaard coordinates: the volumetric effective stress $\sigma_{\rm V}$, the norm of the deviatoric effective stress $\rho$ and the Lode angle $\theta$. The yield surface is +%Let us now describe in more detail the {\bf plastic part} of the model. +The {\bf yield condition} is formulated in terms of the effective +stress $\bar{\boldsymbol{\sigma}}$ and therefore is unaffected by damage. +The yield function is given by \begin{equation} \label{eqcdpm2:yieldSurface} \begin{split} & f_{\rm p}(\bar{\sigma}_{\rm V},\bar\rho,\bar\theta;\kappa_{\rm p})= \left\{\left[1-q_{\rm{h1}}(\kappa_{\rm p})\right]\left( \frac{\bar{\rho}} {\sqrt{6}f_{\rm c}} + \frac{\bar{\sigma}_{\rm V}} {f_{\rm c}} \right)^2 + \sqrt{\frac{3}{2}} \frac {\bar{\rho}}{f_{\rm c}} \right\}^2 \\ & +m_0 q^2_{\rm{h1}}(\kappa_{\rm p})q_{\rm{h2}}(\kappa_{\rm p}) \left[\frac{\bar{\rho} }{\sqrt{6}f_{\rm c}}r(\cos{\bar{\theta}}) + \frac{\bar{\sigma}_{\rm V}}{f_{\rm c}} \right] - q_{\rm{h1}}^2(\kappa_{\rm p}) q_{{\rm h2}}^2(\kappa_{\rm p}) \end{split} \end{equation} -It depends also on the hardening variable $\kappa_{\rm p}$ (which enters through the dimensionless variables $q_{\rm h1}$ and $q_{\rm h2}$). Parameter $f_{\rm c}$ is the uniaxial compressive strength. For $q_{\rm h2} = 1$, the yield function is identical to the one of CDPM. +where $\bar\sigma_{\rm V}$ is the volumetric effective stress, $\bar\rho$ is the norm of the deviatoric effective stress +and $\bar\theta$ is the Lode angle (another invariant of the effective +stress tensor). +Parameter $f_{\rm c}$ is the uniaxial compressive strength. +Evolution of the +yield surface is controlled by two dimensionless stress-like hardening variables, +$q_{h1}$ and $q_{h2}$, which are considered as functions of one +dimensionless strain-like hardening variable, $\kappa_p$. +The {\bf hardening laws} read +\begin{eqnarray} \nonumber +q_{\rm h1}(\kappa_{\rm p}) &=& +\left \{ \begin{array}{ll} q_{\rm h0} + \left(1-q_{\rm h0}\right) \left( \kappa_{\rm p}^3 - 3 \kappa_{\rm p}^2 + 3 \kappa_{\rm p} \right) - H_{\rm p} \left(\kappa_{\rm p}^3 - 3 \kappa_{\rm p}^2 + 2 \kappa_{\rm p}\right) & \mbox{if $\kappa_{\rm p} < 1$} \\ +1 & \mbox{if $\kappa_{\rm p} \ge 1$} +\end{array} +\right. +\\ \label{eq:hardeningLawOne} \\ +q_{\rm h2}(\kappa_{\rm p}) &=& \left \{ \begin{array}{ll} 1 & \mbox{if $\kappa_{\rm p} < 1$} \\ +1 + H_{\rm p} (\kappa_{\rm p} - 1) & \mbox{if $\kappa_{\rm p} \ge 1$} +\end{array} +\right. +\label{eq:hardeningLawTwo} +\end{eqnarray} +During the initial stage of +hardening, $\kappa_p$ grows from 0 to 1, $q_{h1}$ grows from +its initial value $q_{h0}$ to 1 while $q_{h2}$ remains equal to 1. +No damage is induced and the yield surface is expanding. A change +of behavior occurs when $\kappa_p$ becomes equal to 1. For the +original ConcreteDPM model, there would not be any further evolution +of the yield surface. In CDPM2, linear hardening with constant +plastic modulus $H_p$ is assumed. Variable $q_{h1}$ remains equal to 1 +while $q_{h2}$ grows proportionally to the increments of $\kappa_p$. +If $H_p$ is set to zero (i.e., $q_{\rm h2}$ remains equal to 1), +the same behavior as for the ConcreteDPM is obtained. + The shape of the deviatoric section is controlled by the Willam-Warnke function \begin{equation} \label{eq:rFunction} \begin{split} @@ -4056,91 +4313,308 @@ \subsubsection{CDPM2} \end{equation} where $f_{\rm t}$ is the tensile strength. -The flow rule (\ref{eq:flowRule}) is split into a volumetric and a deviatoric part, i.e., the gradient of the plastic potential is decomposed as +{\bf Hardening variable} $\kappa_p$ is a generalized form of +cumulative plastic strain. Its rate corresponds to the rate +of the norm of plastic strain rate scaled by a factor that +depends on the stress state. This is described by the evolution +equation +\begin{equation} + \dot{\kappa}_p =\frac{\Vert\dot{\boldsymbol{\varepsilon}}_p\Vert}{x_h(\bar{\sigma}_V)}\left(2\cos\bar{\theta}\right)^2 +\end{equation} +in which $\bar{\sigma}_V$ is the hydrostatic part of effective stress +and $\bar{\theta}$ is the Lode angle. Function $x_h$ has a complicated form, designed such that +$\kappa_p$ grows faster for positive hydrostatic stress and more slowly +under negative hydrostatic stress. Consequently, the material response +is brittle in tension and less brittle or even ductile in compression, +especially under confinement. The form of function $x_h$ suggested +in \cite{GraXenNys13} is +\begin{equation}\label{eq:xh} +x_h(\bar{\sigma}_V) = \left\{\begin{array}{ll} +A_h-(A_h-B_h)\exp(-R_h(\bar{\sigma}_V)/C_h) & \hskip 10mm \mbox{if } R_h(\bar{\sigma}_V) \ge 0 +\\[3mm] +D_h + E_h\exp(R_h(\bar{\sigma}_V)/F_h) & \hskip 10mm \mbox{if } R_h(\bar{\sigma}_V) < 0 +\end{array}\right. +\end{equation} +where +\begin{equation} + R_h(\bar{\sigma}_V) = -\frac{\bar{\sigma}_V}{f_c}-\frac{1}{3} +\end{equation} +At the peak of the +uniaxial compressive stress-strain curve, we have $\bar{\sigma}_V=-f_c/3$ +and thus $R_h=0$. Positive values of $R_h$ correspond to confined +compression. Under compression with no confinement, $x_h$ is equal to $B_h$, and under high confinement +it is close to $A_h$. Parameter $C_h$ controls the transition from +$B_h$ to $A_h$ and if it is high, the transition occurs at higher +compressive stresses. In this way, parameters $A_h$, $B_h$ and $C_h$ +can be used to tune up the sensitivity of the model to confining +stresses. Parameter $D_h$ affects the behavior under combined +tension and compression, or under uniaxial or multiaxial tension. + +Parameters $E_h$ and $F_h$ are not considered as independent. +To ensure a smooth transition between cases with positive and +negative $R_h$, they need to be set to $E_h=B_h-D_h$ and +$F_h=(B_h-D_h)C_h/(A_h-B_h)$. Note that all these parameters +are dimensionless. In \cite{GraXenNys13} it was suggested to +calibrate parameters $A_h$, $B_h$, $C_h$ and $D_h$ from the strains +at peak stress under uniaxial tension, uniaxial compression and triaxial +compression. Of course, four parameters cannot be uniquely +determined from just three experimental values. It is desirable to +use experimental data for triaxial compression at +several levels of confinement. From the foregoing discussion of the role +of individual parameters it follows that $A_h$ should be greater +than $B_h$, to obtain a positive effect of confinement on ductility, +and parameter $D_h$ should be smaller than $B_h$, to get a more brittle behavior +in tension than in compression. + +The {\bf flow rule} is postulated in the non-associated format (\ref{eq:flowRuleDPM}) +with a plastic potential given by the same expression (\ref{eq:plasticPotential}) +as for the ConcreteDPM model, just with hardening variable $q_h$ formally replaced by $q_{h1}$. +The direction of plastic flow is given by the gradient of the plastic potential, +and it can be split into the volumetric and deviatoric parts: % \begin{equation}\label{eq:generalFlow} -\mathbf{m} = \dfrac{\partial g}{\partial \bar{\boldsymbol{\sigma}} } = \frac{\partial g}{\partial \bar{\sigma}_{\rm V}} \frac{\partial \bar{\sigma}_{\rm V}}{\partial \bar{\boldsymbol{\sigma}}} + \frac{\partial g}{\partial \bar{\rho}} \frac{\partial \bar{\rho} }{\partial \bar{\boldsymbol{\sigma}}} +\boldsymbol{m} = \dfrac{\partial g}{\partial \bar{\boldsymbol{\sigma}} } = \frac{\partial g}{\partial \bar{\sigma}_{\rm V}} \frac{\partial \bar{\sigma}_{\rm V}}{\partial \bar{\boldsymbol{\sigma}}} + \frac{\partial g}{\partial \bar{\rho}} \frac{\partial \bar{\rho} }{\partial \bar{\boldsymbol{\sigma}}} \end{equation} Taking into account that $\partial\bar{\sigma}_{\rm V}/\partial\bar{\boldsymbol{\sigma}}=\boldsymbol{\delta}/3$ and $\partial\bar{\rho}/\partial\bar{\boldsymbol{\sigma}}=\bar{\mbf{s}}/\bar\rho$, restricting attention to the post-peak regime (in which $q_{\rm h1} = 1$) and differentiating the plastic potential (\ref{eq:plasticPotential}), we rewrite equation (\ref{eq:generalFlow}) as \begin{equation}\label{eq:detailedFlow} \mbf{m} = \dfrac{\partial g}{\partial \bar{\boldsymbol{\sigma}}} = \frac{{\partial}{m_{\rm g}}}{{\partial}{\bar{\sigma}_{\rm V}}} \frac{\boldsymbol{\delta}}{3f_{\rm c}} + \left(\frac{3}{f_{\rm c}} + \frac{m_0}{\sqrt{6}\bar\rho} \right)\frac{\bar{\mbf{s}}}{f_{\rm c}} \end{equation} -The flow rule is non-associative which means that the direction of the plastic flow is not normal to the yield surface. This is important for concrete since an associative flow rule would give an overestimated maximum stress for passive confinement. +Since the flow rule is non-associative, the direction of the plastic flow is not normal to the yield surface. This is important for concrete since an associative flow rule would give an overestimated maximum stress for passive confinement. -The dimensionless variables $q_{\rm h1}$ and $q_{\rm h2}$ that appear in (\ref{eq:yieldSurface}), (\ref{eq:plasticPotential}) and (\ref{eq:mg}) are functions of the hardening variable $\kappa_{\rm p}$. They control the evolution of the size and shape of the yield surface and plastic potential. -The first hardening law $q_{\rm h1}$ is -% -\begin{equation} \label{eq:hardeningLawOne} -q_{\rm h1}(\kappa_{\rm p}) = -\left \{ \begin{array}{ll} q_{\rm h0} + \left(1-q_{\rm h0}\right) \left( \kappa_{\rm p}^3 - 3 \kappa_{\rm p}^2 + 3 \kappa_{\rm p} \right) - H_{\rm p} \left(\kappa_{\rm p}^3 - 3 \kappa_{\rm p}^2 + 2 \kappa_{\rm p}\right) & \mbox{if $\kappa_{\rm p} < 1$} \\ -1 & \mbox{if $\kappa_{\rm p} \ge 1$} -\end{array} -\right. -\end{equation} -% -The second hardening law $q_{\rm h2}$ is given by -\begin{equation} \label{eq:hardeningLawTwo} -q_{\rm h2}(\kappa_{\rm p}) = \left \{ \begin{array}{ll} 1 & \mbox{if $\kappa_{\rm p} < 1$} \\ -1 + H_{\rm p} (\kappa_{\rm p} - 1) & \mbox{if $\kappa_{\rm p} \ge 1$} -\end{array} -\right. + +{\bf Damage} is initiated when the equivalent strain reaches the threshold $\varepsilon_{0} = f_{\rm t}/E$, +which represents the limit elastic strain under uniaxial tension. +The evolution of damage variables depends +on certain internal variables linked to the elastic and plastic strains +computed using the plastic part of the model. + +The {\bf tensile damage} variable $\omega_t$ is a function of three auxiliary +internal variables, $\kappa_{dt}$, $\kappa_{dt1}$ and $\kappa_{dt2}$. +Variable $\kappa_{dt}$ is the maximum previously reached value of +equivalent strain +\begin{equation}\label{cdpm2:eps} +\tilde\varepsilon = \frac{\varepsilon_0m_0}{2}\left(\frac{\bar\rho r(\cos\bar\theta)}{\sqrt{6}f_c}+\frac{\bar\sigma_V}{f_c}\right) + \sqrt{\frac{\varepsilon_0^2m_0^2}{4}\left(\frac{\bar\rho r(\cos\bar\theta)}{\sqrt{6}f_c}+\frac{\bar\sigma_V}{f_c}\right)^2+\frac{3\varepsilon_0^2\bar\rho^2}{2f_c^2}} \end{equation} +where $r$ is the function of the Lode angle specified in (\ref{eq:rFunction}) and $m_0$ is the friction parameter specified in (\ref{eq:frictionM}). +Expression (\ref{cdpm2:eps}) has been derived from the yield condition $f_{\rm p} = 0$ by setting $q_{\rm {h1}}=1$ and $q_{\rm{h2}} = \tilde{\varepsilon}/\varepsilon_{0}$, +which leads to a quadratic equation. -The evolution law for the hardening variable, +Variables $\kappa_{dt1}$ and $\kappa_{dt2}$ are defined by the rate equations +\begin{eqnarray} +\dot\kappa_{dt1} &=& \left\{\begin{array}{ll} +\displaystyle\frac{\Vert\dot{\boldsymbol\varepsilon}_p\Vert}{x_s(\bar\rho,\bar\sigma_V)} & \hskip 10mm \mbox{if } \dot\kappa_{dt}>0\;\mbox{ and }\; \kappa_{dt}\ge \varepsilon_0 +\\[3mm] +0 & \hskip 10mm \mbox{if } \dot\kappa_{dt}=0\;\mbox{ or }\; \kappa_{dt}< \varepsilon_0 +\end{array}\right. +\\ +\dot\kappa_{dt2} &=& \frac{\dot\kappa_{dt}}{x_s(\bar\rho,\bar\sigma_V)} +\end{eqnarray} +where +\begin{equation}\label{eq:xs2} + x_s(\bar\rho,\bar\sigma_V) = + 1+(A_s-1)\frac{\sqrt{6}\langle-\bar\sigma_V\rangle}{\bar\rho} +\end{equation} +is a ductility measure. For positive hydrostatic stress $\bar\sigma_V$, +we have $\langle-\bar\sigma_V\rangle=0$ and $x_s=1$. Under compression, +$x_s$ increases (provided that parameter $A_s$ is greater than 1), +which slows down the evolution of variables $\kappa_{dt1}$ and $\kappa_{dt2}$ +and consequently of damage. For uniaxial compression, we have +$\bar\sigma_V/\bar\rho=-1/\sqrt{6}$ and formula (\ref{eq:xs2}) gives $x_s=A_s$. + +The specific form of the dependence of damage variable $\omega_t$ on +$\kappa_{dt}$, $\kappa_{dt1}$ and $\kappa_{dt2}$ is dictated by the desired +shape of the softening part of the uniaxial tensile stress-strain diagram. +For instance, bilinear softening is obtained with +\begin{equation}\label{cdpm2:omegat} + \omega_t = \left\{\begin{array}{ll} + \dfrac{(E\kappa_{dt}-f_t)\varepsilon_{f1}-(\sigma_1-f_t)\kappa_{dt1}}{E\kappa_{dt}\varepsilon_{f1}+(\sigma_1-f_t)\kappa_{dt2}} & \hskip 10mm \mbox{ if } 0\le\kappa_{dt1}+\omega_t\kappa_{dt2}\le\varepsilon_{f1} + \\[3mm] + \dfrac{E\kappa_{dt}(\varepsilon_f-\varepsilon_{f1})+\sigma_1(\kappa_{dt1}-\varepsilon_f)}{E\kappa_{dt}(\varepsilon_f-\varepsilon_{f1})-\sigma_1\kappa_{dt2}} & \hskip 10mm \mbox{ if } \varepsilon_{f1}<\kappa_{dt1}+\omega_t\kappa_{dt2}\le\varepsilon_{f} + \\[3mm] + 0 & \hskip 10mm \mbox{ if } \varepsilon_{f}<\kappa_{dt1}+\omega_t\kappa_{dt2} + \end{array}\right. +\end{equation} +where $\varepsilon_{f1}$ and $\sigma_1$ is the strain and stress at the knee point +of the softening diagram (where the two linear segments meet), and $\varepsilon_{f}$ +is the strain at which the stress vanishes. The choice of a bilinear softening +diagram for tension makes it possible to obtain a steep initial descent +followed by a long tail, which would not be that easy with the exponential diagram +used in the ConcreteDPM model. In the local version of the model, objectivity +with respect to mesh size must be enforced by adjustment of the softening diagram. +Numerical parameters $\varepsilon_{f1}$ and $\varepsilon_{f}$ are then derived from material +parameters $w_{f1}$ and $w_f$ that define the cohesive law in terms of the dependence of stress +on crack opening, $w$. Transformation of crack opening into the smeared cracking strain +then leads to parameters $\varepsilon_{f1}=w_{f1}/h$ and $\varepsilon_{f}=w_f/h$ where +$h$ is the estimated thickness of the computationally resolved localized band. + +The {\bf compressive damage} variable $\omega_c$ is a function of three auxiliary +internal variables, $\kappa_{dc}$, $\kappa_{dc1}$ and $\kappa_{dc2}$. +Variable $\kappa_{dc}$ is defined by the rate equation \begin{equation} -\dot{\kappa}_{\rm {p}} = \frac {\| \dot{\veps_{\rm{p}}}\|}{x_{\rm{h}}\left(\bar{\sigma}_{\rm V} \right)} \left(2 \cos{\bar{\theta}}\right)^2 = \frac {\dot{\lambda} \| \mbf{m}\|}{x_{\rm{h}}\left(\bar{\sigma}_{\rm V} \right)} \left(2\cos{\bar{\theta}}\right)^2 + \dot\kappa_{dc} = \alpha_c\dot{\tilde\varepsilon} \end{equation} -sets the rate of the hardening variable equal to the norm of the plastic strain rate scaled by a hardening ductility measure, which is identical to the one used for the CDPM. - -\noindent\textbf{Damage:} - -Damage is initiated when the maximum equivalent strain in the history of the material reaches the threshold $\varepsilon_{0} = f_{\rm t}/E$. -This expression is determined from the yield surface ($f_{\rm p} = 0$) by setting $q_{\rm {h1}}=1$ and $q_{\rm{h2}} = \tilde{\varepsilon}/\varepsilon_{0}$. -From this quadratic equation for $\tilde{\varepsilon}$, the equivalent strain is determined as +where $\tilde\varepsilon$ is the already defined equivalent strain, and +the scaling factor $\alpha_c$ depends on the type of stress state +and is given by \begin{equation} -\tilde{\varepsilon} = \dfrac{\varepsilon_0 m_0}{2} \left(\dfrac{\bar{\rho}}{\sqrt{6} f_{\rm c}} r\left(\cos\theta\right) + \dfrac{\bar{\sigma}_{\rm V}}{f_{c}}\right) + \sqrt{\dfrac{\varepsilon_0^2 m_0^2}{4} \left(\dfrac{\bar{\rho}}{\sqrt{6}f_{\rm c}} r\left(\cos\theta\right) + \dfrac{\bar{\sigma}_{\rm V}}{f_{\rm c}}\right)^2 + \dfrac{3 \varepsilon_0^2 \bar{\rho}^2}{2 f_{\rm c}^2}} + \alpha_c = \frac{\sum_{I=1}^3 \langle-\bar\sigma_I\rangle^2}{\sum_{I=1}^3 \bar\sigma_I^2} \end{equation} +If all principal effective stresses $\sigma_I$ are positive (or at least non-negative), +we have $\alpha_c=0$, and if all principal effective stresses are negative (or at least non-positive), +we have $\alpha_c=1$. For the zero stress state, $\alpha_c$ is undefined, but for that +particular state it is not needed. -Tensile damage is described by a stress-inelastic displacement law. For linear and exponential damage type the stress value $f_{\rm t}$ and the displacement value $w_{\rm f}$ must be defined. For the bi-linear type two additional parameters $f_{\rm t1}$ and $w_{\rm f1}$ are required. - -For the compressive damage variable, an evolution based on an exponential stress-inelastic strain law is used. The stress versus inelastic strain in the softening regime in compression is -\begin{equation} +Two other auxiliary internal variables that affect compressive damage are defined by the rate equations +\begin{eqnarray} +\dot\kappa_{dc1} &=& \left\{\begin{array}{ll} +\displaystyle\frac{\alpha_c\beta_c\vert\dot{\boldsymbol\varepsilon}_p\vert}{x_s} & \hskip 10mm \mbox{if } \dot\kappa_{dt}>0\;\mbox{ and }\; \kappa_{dt}\ge \varepsilon_0 +\\[3mm] +0 & \hskip 10mm \mbox{if } \dot\kappa_{dt}=0\;\mbox{ or }\; \kappa_{dt}< \varepsilon_0 +\end{array}\right. +\\ +\dot\kappa_{dc2} &=& \frac{\dot\kappa_{dc}}{x_s} +\end{eqnarray} +where factor +\begin{equation}\label{cdpm2:betac} + \beta_c =\frac{f_tq_{h2}\sqrt{2/3}}{\bar\rho\sqrt{1+2D_f^2}} +\end{equation} +depends on the plastic hardening variable $q_{h2}$ and +effective stress invariant $\bar\rho$ and provides a smooth transition +from pure damage to damage-plastic softening, which can occur during cyclic +loading. The dependence of the compressive damage $\omega_c$ on the internal +variables is defined such that the relation between the stress and the inelastic strain, $\varepsilon_{\rm i}$, +under uniaxial compression is exponential and is given by +\begin{equation}\label{cdpm2:sigma} +\begin{array}{ll} +\sigma = f_{\rm c} \exp\left(-\dfrac{\varepsilon_{\rm i}}{\varepsilon_{\rm fc}}\right) & \mbox{if $0 < \varepsilon_{\rm i}$} +\end{array} +\end{equation} +where $\varepsilon_{\rm fc}$ is a parameter controls the initial inclination of the softening curve. +The inelastic strain is defined as the difference between the total strain, $\varepsilon$, and the elastic strain, $\sigma/E$. +Replacing $\sigma$ bythe right-hand side of (\ref{cdpm2:sigma}), we obtain a nonlinear equation +\begin{equation}\label{cdpm2:epsi} \begin{array}{ll} -\sigma = f_{\rm t} \exp\left(-\dfrac{\varepsilon_{\rm i}}{\varepsilon_{\rm fc}}\right) & \mbox{if $0 < \varepsilon_{\rm i}$} +\varepsilon_{\rm i} + \dfrac{f_{\rm c}}{E} \exp\left(-\dfrac{\varepsilon_{\rm i}}{\varepsilon_{\rm fc}}\right) = \varepsilon \end{array} \end{equation} -where $\varepsilon_{\rm fc}$ is an inelastic strain threshold which controls the initial inclination of the softening curve. The use of different damage evolution for tension and compression is one important improvement over CDPM. +from which $\varepsilon_{\rm i}$ can be evaluated iteratively if the total strain $\varepsilon$ is given. +The use of different damage evolution rules for tension and compression is one important improvement over ConcreteDPM. +In contrast to tension, the evolution law for compressive damage is considered to be independent of the +element size, since compressive failure is often characterized by mesh-independent zones of damage growth. + +\begin{table} [!h] + \caption{Summary of parameters of CDPM2} + \label{CDPM2-params} + \centering + \begin{tabular}{ | c | c | c | c | c |} +\hline +parameter & OOFEM & unit & default & meaning \\ + & identifier & & value & \\ +\hline +$E$ & E & Pa & & Young's modulus\\ +$\nu$ & n & - & & Poisson's ratio \\ +$f_t$ & ft & Pa & & uniaxial tensile strength \\ +$f_c$ & fc & Pa & & uniaxial compression strength \\ +$w_f$ & wf & m & & critical crack opening\\ +%$G_{ft}$ & & J/m$^2$ & & tensile fracture energy \\ +$e$ & ecc & - & 0.525 & eccentricity, eq.~(\ref{eq:rFunction})--(\ref{eq:frictionM}) \\ +$q_{h0}$ & kinit & - & 0.3 & initial value of hardening variable $q_{h1}$, eq.~(\ref{eq:hardeningLawOne})\\ +$H_p$ & hp & - & 0.5 & hardening modulus (for the last stage, eq.~(\ref{eq:hardeningLawTwo}))\\ +$D_f$ & dilation & - & 0.85 & dilation factor, eq.~(\ref{cdpm2:betac}) \\ +$A_h$ & Ahard & - & 0.08 & hardening parameter, eq.~(\ref{eq:xh})\\ +$B_h$ & Bhard & - & 0.003 & hardening parameter, eq.~(\ref{eq:xh}) \\ +$C_h$ & Chard & - & 2 & hardening parameter, eq.~(\ref{eq:xh}) \\ +$D_h$ & Dhard & - & $10^{-6}$ & hardening parameter, eq.~(\ref{eq:xh}) \\ +$A_s$ & Asoft & - & 15 & softening parameter, eq.~(\ref{eq:xs})\\ +$\varepsilon_{fc}$ & efc & - &$10^{-4}$ & softening parameter for compression, eq.~(\ref{cdpm2:sigma}) \\ + & stype & & 1 & type of softening (1=bilinear) \\ +$w_{f1}/w_f$ & wf1 & - & 0.15 & softening parameter for tension\\ +$\sigma_1/f_t$ & ft1 & - & 0.3 & softening parameter for tension, eq.~(\ref{cdpm2:omegat})\\ +\hline + \end{tabular} +\end{table} -The history variables $\kappa_{\rm dt1}$, $\kappa_{\rm dt2}$, $\kappa_{\rm dc1}$ and $\kappa_{\rm dc2}$ depend on a ductility measure $x_{\rm s}$, which takes into account the influence of multiaxial stress states on the damage evolution. -This ductility measure is given by +From the presented description of the model equations, +it is clear that CDPM2 uses a large number of parameters. In \cite{GraXenNys13} +it was recommended to adjust only a few basic parameters, most of which have +a certain physical meaning, and to set all the other parameters to their +default values. The physical parameters that can be adjusted depending on +the specific type of concrete are Young's modulus, Poisson's ratio, uniaxial +tensile and compression strengths, and the critical crack opening, +which controls the tensile fracture energy. +A summary of all model parameters and of their recommended default values +is provided in Table~\ref{CDPM2-params}. The table shows the symbol used for the parameter +in equations describing the theoretical background and also the corresponding identifier +used in OOFEM input files. + +Parameters listed on the first five lines of Table~\ref{CDPM2-params} +must be specified by the user. Parameter $w_f$ corresponds to the opening +of a cohesive crack at which the stress transmitted by the crack vanishes. +It is closely related to the tensile fracture energy, $G_{Ft}$. +The shape of the cohesive curve for tensile failure is affected by +the choice of the type of softening. The default choice is bilinear +softening, which requires, in addition to $f_t$ and $w_f$, two more +parameters that control the position of the point at which the slope +of the diagram changes. This point is characterized by crack opening $w_{f1}$ +and stress $\sigma_1$, but the input parameters for OOFEM are dimensionless +ratios $w_{f1}/w_f$ and $\sigma_1/f_t$ with default values 0.15 and 0.3. +In general, the fracture energy is evaluated as $G_{Ft}=(f_tw_{f1} +\sigma_1 w_f)/2$, and for the default values this gives $G_{Ft}=f_tw_f/4.444$, +which means that parameter $w_f$ can be evaluated from the tensile strength +and fracture energy using formula $w_f=4.444\,G_{Ft}/f_t$. + +The eccentricity parameter $e$ could be evaluated from $f_t$ and $f_c$ +combined with the biaxial compression strength, $f_{bc}$, using formula \begin{equation} -x_{\rm s} = 1+ \left(A_{\rm s}-1\right) R_{\rm s} +e= \frac{1+\epsilon}{2-\epsilon} \end{equation} -where $R_{\rm s}$ is +where \begin{equation} -R_{\rm s} = \left \{ \begin{array}{ll} -\dfrac{\sqrt{6} \bar{\sigma}_{\rm V}}{\bar{\rho}} & \mbox{if $\bar{\sigma}_{\rm V} \leq 0$} \\ - 0 & \mbox{if $\bar{\sigma}_{\rm V} > 0$} \end{array} \right. +\epsilon=\frac{f_t}{f_{bc}}\frac{f_{bc}^2-f_c^2}{f_c^2-f_t^2} \end{equation} -and $A_{\rm s}$ is a model parameter. - -\noindent\textbf{Strain rate:} +The default value is not mentioned in \cite{GraXenNys13}; +in OOFEM it is taken as $e=0.525$. + +Parameter $H_p$ is a dimensionless hardening modulus that sets the +ratio between the increments of variables $q_{h2}$ and $\kappa_p$ +during the last stage of the plastic hardening process. +The value recommended in \cite{GraXenNys13} is $H_p=0.01$, +but the default value used in OOFEM is 0.5. -Concrete is strongly rate dependent. If the loading rate is increased, the tensile and compressive strength increase and are more prominent in tension then in compression. The dependency is taken into account by an additional variable $alpha_{\rm r}$. The rate dependency is included by scaling both the equivalent strain rate and the inelastic strain. The rate parameter is defined by +The dilation parameter $D_f$ controls the ratio between the transversal +and axial plastic strain rates in uniaxial compression and thus can +be used to control the volumetric expansion in the softening regime. +The default value is set to 0.85, as suggested in \cite{GraJir}, +which means that the transversal plastic strain rate will be $-0.85$ times the (negative) axial plastic strain rate. + +The default values of $q_{h0}=0.3$, $A_h=0.08$, $B_h=0.003$, $C_h=2$, $D_h=10^{-6}$ +and $\varepsilon_{fc}=10^{-4}$ are taken from \cite{GraXenNys13}. +Parameter $A_s$ was varied in \cite{GraXenNys13} +in the range from 1.5 to 15. In OOFEM, the default value of $A_s$ is taken as 15, which was recommended in \cite{GraJir}. + +Concrete is strongly {\bf rate-dependent}. If the loading rate is increased, the tensile and compressive strength increase and are more prominent in tension then in compression. The dependency of the stress-strain response on the dynamic increase factor is taken into account by an additional variable $\alpha_{\rm r}$. The rate dependency is included by scaling both the equivalent strain rate and the inelastic strain. The rate parameter is defined by \begin{equation} \alpha_{\rm r}=(1-X) \alpha_{\rm rt} + X \alpha_{\rm rc} \end{equation} where $X$ is the continuous compression measure (= 1 means only compression, = 0 means only tension). +The dynamic increase factor (DIF) for strength is computed according to Model Code 2010. -The functions $\alpha_{\rm rt}$ and $\alpha_{\rm rc}$ depend on the input parameter $f_{\rm c0}$. A recommended value for $f_{\rm c0}$ is 10~MPa. +The {\bf parameters of CDPM2} for OOFEM input file are summarised in Tab.~\ref{cdpm2_table}. +By default, two damage variables are used, i.e., the effective stress is transformed into +nominal stress using equation (\ref{cdpm2:efftonominal}). If parameter {\em damflag} is set to 3, +only $\omega_t$ is used and the effective stress is reduced by $1-\omega_t$. -\begin{table}[!htb] + +\begin{htmlonly} +\begin{longtable}{|l|l|} +\end{htmlonly} +\begin{longtable}{|l|p{9cm}|} %\begin{center} -\begin{mmt} +%\begin{mmt} \hline Description & CDPM2\\ \hline -Record Format & \descitem{con2dpm} \elemparam{d}{rn} \elemparam{E}{rn} \elemparam{n}{rn} \elemparam{tAlpha}{rn} \elemparam{ft}{rn} \elemparam{fc}{rn} \elemparam{wf}{rn} [\elemparam{stype}{in}] [\elemparam{ft1}{rn}] [\elemparam{wf1}{rn}] [\elemparam{efc}{rn}] [\elemparam{ecc}{rn}] [\elemparam{kinit}{rn}] [\elemparam{Ahard}{rn}] [\elemparam{Bhard}{rn}] [\elemparam{Chard}{rn}] [\elemparam{Dhard}{rn}] [\elemparam{Asoft}{rn}] [\elemparam{helem}{rn}] [\elemparam{dilation}{rn}] [\elemparam{hp}{rn}] [\elemparam{isoflag}{in}] [\elemparam{rateflag}{in}] \elemparam{fcZero}{in} [\elemparam{yieldtol}{rn}] [\elemparam{newtoniter}{in}] \\ +Record Format & \descitem{con2dpm} \elemparam{d}{rn} \elemparam{E}{rn} \elemparam{n}{rn} \elemparam{tAlpha}{rn} \elemparam{ft}{rn} \elemparam{fc}{rn} \elemparam{wf}{rn} [\elemparam{stype}{in}] [\elemparam{ft1}{rn}] [\elemparam{wf1}{rn}] [\elemparam{efc}{rn}] [\elemparam{ecc}{rn}] [\elemparam{kinit}{rn}] [\elemparam{Ahard}{rn}] [\elemparam{Bhard}{rn}] [\elemparam{Chard}{rn}] [\elemparam{Dhard}{rn}] [\elemparam{Asoft}{rn}] [\elemparam{helem}{rn}] [\elemparam{dilation}{rn}] [\elemparam{hp}{rn}] [\elemparam{damflag}{in}] [\elemparam{sratetype}{in}] \elemparam{eratetype}{in} [\elemparam{yieldtol}{rn}] [\elemparam{newtoniter}{in}] \\ Parameters &- \param{d} material density\\ &- \param{E} Young modulus\\ &- \param{n} Poisson ratio\\ @@ -4167,20 +4641,28 @@ \subsubsection{CDPM2} &- \param{helem} element size $h$, optional (if not specified, the actual element size is used)\\ &- \param{dilation} dilation factor, optional, default value 0.85\\ &- \param{hp} hardening modulus, optional, default value 0.5\\ -&- \param{isoflag} flag which allows for the use of only one damage parameter if set to 1, default value 0\\ -&- \param{rateflag} flag which allows for the consideration of the effect of strain rates if set to 1, default value 0\\ -&- \param{fcZero} Input parameter for modelling the effect of strain value. Recommended value $10$~MPa. Only if rateflag=1, \param{fcZero} has to be specified.\\ +&- \param{damflag} flag which allows for the use of different damage formulations. Default value is 1. If set to zero, no damage is used. If set to 3, only the tensile damage varialbe is used.\\ +&- \param{sratetype} Dynamic increase factor (DIF) for strength +\begin{itemize}\setlength{\itemsep}{-3pt} +\item[0 -] DIF = 1 (no rate effect) +\item[1 -] First branch of Model Code 2010 DIF for strength. +\item[2 -] First and second branch of Model Code 2010 DIF for strength +\end{itemize}\\ +&- \param{eratetype} Dynamic increase factor (DIF) for fracture energy. Only used if sratetype is not equal to 0. +\begin{itemize}\setlength{\itemsep}{-3pt} +\item[0 -] DIF = 1 +\item[1 -] DIF from sratetype +\item[2 -] DIF squared from sratetype +\end{itemize}\\ &- \param{yieldtol} tolerance for the implicit stress return algorithm, optional, default value $1 \times 10^{-6}$\\ &- \param{newtoniter} maximum number of iterations in the implicit stress return algorithm, optional, default value 100\\ -Supported modes& 3dMat, PlaneStrain\\ +Supported modes& 3dMat, PlaneStrain, 1dMat\\ \hline -\end{mmt} +%\end{mmt} \caption{CDPM2 -- summary.} \label{cdpm2_table} %\end{center} -\end{table} - - +\end{longtable} \subsubsection{Fixed crack model for concrete - ConcreteFCM} @@ -4285,6 +4767,264 @@ \subsubsection{Fixed crack model for concrete - ConcreteFCM} \label{concrete_fcm_table} \end{longtable} + +\subsubsection{Viscoelastic fixed crack model for concrete - ConcreteFCMViscoelastic} +\label{concreteFCMViscoelastic} + +The material model ``ConcreteFcmViscoelastic'' has been developed in order to +realistically capture the time-dependent behavior of cementitious materials +with the possibility of tensile cracking. +The model allows to link an arbitrary +viscoelastic material model present in OOFEM with the model "ConcreteFCM" for +tensile failure with fixed (not rotating) orientation of cracks +developed for concrete. The material model assumes an additive split of the total deformation +into the viscoelastic and cracking part. The viscoelastic material handles the +stress-independent strains, i.e. shrinkage and thermal dilation. + +\subsubsection*{Incremental stiffness matrix} +In the case of an elastic (initial) stiffness or uncracked material, the +stiffness matrix $\bar{\mbf{D}}_{ve}$ is evaluated as the product of incremental stiffness of the +viscoelastic material $\bar{E}$ and the unit elastic +stiffness matrix $\mbf{D}_v$. +The evaluation of the incremental modulus $\bar{E}$ is +computationally demanding, therefore within one time step it is stored +in the material status. The value of stiffness depends on the history + of relative humidity and temperature at given Gauss point and + depends entirely on the viscoelastic material. + + +Secant stiffness matrix is obtained by adding the secant compliance of +the cohesive cracks to the viscoelastic compliance matrix and by subsequent +inversion of the result. +% +\begin{equation} +\mbf{D} = \left( \bar{\mbf{D}}^{-1}_{ve} + \mbf{D}^{-1}_{cr} \right)^{-1} +\end{equation} + +Tangent stiffness matrix is computed as +\begin{equation} +\mbf{D} = \bar{\mbf{D}}_{ve} - \bar{\mbf{D}}_{ve} \left(\bar{\mbf{D}}_{ve} + \mbf{D}_{cr} \right)^{-1} \bar{\mbf{D}}_{ve} +\end{equation} +where $\mbf{D}_{cr}$ is the tangent stiffness of the cracked material. + +The secant and tangent matrix are constructed in the local +coordinate system corresponding to the orientation of the cracks and +then are rotated to the global +coordinate system. The individual components of $\mbf{D}_{cr}$ are managed by +\emph{ConcreteFCM} material model. + +\subsubsection*{Algorithm for stress evaluation} +% +The stress evaluation algorithm can be decomposed into 3 subsequent steps: +% +\begin{enumerate} + +\item Call the viscoelastic material to compute the stress-dependent strain increment +\begin{equation} +\Delta \varepsilon_\sigma = \Delta \varepsilon - \Delta \varepsilon'' +- \Delta \varepsilon_{sh} - \Delta \varepsilon_T +\end{equation} +where $\Delta \varepsilon$ is the total strain increment, $\Delta +\varepsilon''$ is the strain increment due to creep, $\Delta +\varepsilon_{sh}$ is the shrinkage increment, and $\Delta +\varepsilon_T$ is the thermal dilation increment. + +\item Call the fixed-crack material to compute the new stress vector + $\sigma_{i+1}$ + fulfilling the nonlinear equation +% + \begin{equation} +\sigma_{i+1} = \sigma_{i} + \bar{\mbf{D}}_{ve} \left ( \Delta +\varepsilon_\sigma - \Delta +\varepsilon_{cr} \right) + \end{equation} + % +where $\sigma_{i}$ is the old stress vector and $\Delta +\varepsilon_{cr}$ is the increment of crack strain, and update the new crack strain vector + \begin{equation} +\varepsilon_{cr,i+1} = \varepsilon_{cr,i} + \Delta \varepsilon_{cr} + \end{equation} + +\item Pass the difference of the total strain and the cracking strain + to the viscoelastic material and perform a regular viscoelastic step. +% +\begin{equation} +\sigma_{i+1} = \sigma_{i} + \bar{\mbf{D}}_{ve} \left ( \Delta +\varepsilon - \Delta \varepsilon_{cr} - \Delta \varepsilon'' +- \Delta \varepsilon_{sh} - \Delta \varepsilon_T \right) +\end{equation} +% +\end{enumerate} + + +\vspace{1em} +Before the onset of cracking, the material is modeled as isotropic +linear viscoelastic characterized by its compliance function, Poisson's +ratio, and the evolution of shrinkage which can depend both on +equivalent time and change in relative humidity provided that the +problem is solved as coupled. + +Cracking is initiated when principal stress reaches tensile +strength. Further loading is governed by a softening law. Proper +amount energy dissipation is guaranteed by the crack-band approach, +the width of the crack band is given by the size of the finite element +projected in the direction of the principal stress. + +Multiple cracking is allowed, the maximum number of cracks is controlled by \param{ncracks} parameter. Only mutually perpendicular cracks are supported. If cracking occurs in more directions, the behavior on the crack planes is considered to be independent. +The secant stiffness is used for unloading and reloading. In +compression regime full stiffness is restored. + +It is worth emphasizing that the status of the viscoelastic material +tracks and keeps only a part of the total deformation equal to the +difference of the total strain and the cracking strain. + + +\subsubsection*{Evolution of tensile strength and fracture energy} + +The current implementation supports both constant and time-evolving +values of tensile strength and fracture energy. +\textbf{Constant} values are used when the keyword \param{timeDepFracturing} +is missing in the definition of the material. Then, the values are taken directly from the +\emph{ConcreteFCM} material (keywords \param{ft} and \param{gf}). +On the other hand, when the flag \texttt{timeDepFracturing} is present +in the material definition, the tensile strength and fracture energy +is \textbf{time-evolving}. In that case, the values of \param{ft} and \param{gf} +are ignored, and the value of parameter $s$ (\param{fib\_s}), and the mean +value of the compressive strength $f_{cm,28}$ (\param{fcm28}) need to be +provided and serve for the prediction of $f_t(t)$ and $G_F(t)$. +Yet, it is possible to +override the predicted 28-day values by providing the fields +\param{ft28} and \param{gf28}. +% +It must be noted that once the tensile stress exceeds the current +value of tensile strength, the time development of the properties is +terminated on the particular crack plane. + +Mean value of the uniaxial compressive strength at specific time which +is used for evaluation of the tensile strength and fracture energy is +computed using expressions (5.1-50) and (5.1-51) in \emph{fib}~MC2010 \cite{fib:2010}: +\begin{equation} +f_{cm}(t_e) = \exp \left[ s \left( 1. - \sqrt{28/t_e} \right) \right] f_{cm,28} +\end{equation} +in which $s$ is a coefficient reflecting cement type (table +5.1-9), $t_e$ is the equivalent time from the viscoelastic model, and +$f_{cm,28}$ is the mean value of the uniaxial compressive strength at +the age of 28 days. + +Current value of tensile strength $f_{ctm}(t)$ at time $t$ is computed from the compressive +strength at corresponding age, similarly to section 5.1.5.1 in +MC2010. The difference is that in MC2010 both tensile strength and fracture energy +are treated as non-aging and are evaluated from $f_{cm,28}$. +In the following expressions the $f_{cm}$ and $f_{ctm}$ are in MPa. +\begin{equation} +f_{ctm}(t_e) = 2.12 \: \ln \left(1 + 0.1 f_{cm}(t_e) \right) \: \dots \: +\mathrm{for \:} f_{cm} \geq 58\:\mathrm{MPa} +\end{equation} +% +\begin{equation} +f_{ctm}(t_e) = 0.3 \left(f_{cm}(t_e)-8 \right)^{2/3} \: \dots \: +\mathrm{for \:} 20 \leq f_{cm} \leq 58\:\mathrm{MPa} +\end{equation} +% +\begin{equation} +f_{ctm}(t_e) = 0.07862 \: f_{cm} \: \dots \: +\mathrm{for \:} f_{cm} \leq 20 \: \mathrm{MPa} +\end{equation} +% +The value of fracture energy at the age of 28 days is computed +accordingly to section 5.1.5.2 in MC2010 +\begin{equation} +G_F = 73 \left( f_{cm,28} \right)^{0.18} +\end{equation} +% +in this equation $G_F$ is in N/m and the compressive strength is in MPa. +% +Here, the time development of fracture energy is chosen to be the same as +the tensile strength +\begin{equation} +G_F(t) = G_F \frac{f_{ctm}(t)}{f_{ctm}(28)} +\end{equation} + + +%begin{latexonly} +\begin{longtable}{|l|p{9cm}|} +%end{latexonly} +\hline +Description & Viscoelastic fixed crack model for concrete\\ +\hline +Record Format & \descitem{ConcreteFCMViscoelastic} +\elemparam{viscoMat}{in} +\elemparam{gf}{rn} +\elemparam{ft}{rn} +\optelemstring{timeDepFracturing} +\optelemparam{fib\_s}{rn} +\optelemparam{fcm28}{rn} +\optelemparam{timefactor}{rn} +\optelemparam{stiffnessfactor}{rn} +\optelemparam{gf28}{rn} +\optelemparam{ft28}{rn} +\\ +Parameters &- \param{} material model number\\ +&- \param{viscoMat} number of the slave viscoelastic material\\ +&- \param{ft} tensile strength - constant value\\ +&- \param{gf} fracture energy - constant value\\ +&- \param{timeDepFracturing} flag to activate evolving $f_t$ and $G_f$ +according to \emph{fib MC2010}\\ +&- \param{fib\_s} strength class of cement coefficient (Table 5.1-9 in +fib MC2010)\\ +&- \param{fcm28} 28-day mean compressive strength of concrete used for +prediction and evolution of $f_t$ and $G_f$\\ +&- \param{timefactor} time transformation factor, 1 for days, +86400 for seconds etc.\\ +&- \param{stiffnessfactor} stiffness transformation factor, 1 for Pa, +1.e6 for MPa etc.\\ +&- \param{ft28} overrides predicted tensile strength\\ +&- \param{gf28} overrides predicted fracture energy\\ +Supported modes& 3dMat, PlaneStress, PlaneStrain\\ +\hline +\caption{Viscoelastic fixed crack model for concrete -- summary.} +\label{concretefcmviscoelastic_table} +\end{longtable} +% +\subsubsection*{Examples} +The following lines show a sample syntax specifying the viscoelastic +fixed crack model with the compliance defined by the MPS model. +Volume density is 24 kN/m$^3$, thermal dilation coefficient +$12\times10^{-6}$ K$^{-1}$, Poisson's ratio~0.2, +fracture energy $G_f$ and tensile strength $f_t$ predicted from the +mean compressive strength $f_{cm} = 30$~MPa (defined ft and gf are +discarded, to override use keywords ft28 and gf28), +exponential softening, maximum 2 perpendicular tensile cracks, +constant shear factor coefficient, $sf = 20.$, +all cracks contribute to the shear stiffness, +shear strength equal to $f_t$, numerical stiffness factors 1e-3, +number of viscoelastic material is 2. +The analysis uses [m], [MPa], [MN], and [day]:\\ +% +\noindent +\texttt{ + ConcreteFcmViscoelastic 1 d 24.e-3 talpha 0. E 30000. n 0.2\\ + Gf 100.e-6 ft 2. softtype 1 sheartype 2 sf 20.\\ + multiplecrackshear shearstrengthtype 1 ncracks 2\\ + shearCoeffNumer 0.001 normalCoeffNumer 0.001 viscomat 2\\ + timeDepFracturing fib\_s 0.20 fcm28 30. timeFactor 1.\\ + stiffnessFactor 1.e6} + +The viscoelastic material can be defined e.g. by the following +listing. Note that the coefficient of thermal expansion is zero in +ConcreteFcmViscoelastic and nonzero in the viscoelastic material which +handles all stress-independent strains. Also note same values of the Poisson's ratio. + +\noindent +\texttt{mps 2 d 24.e-3 n 0.2 talpha 12.e-6 referencetemperature 296.\\ + mode 0 fc 30. cc 340. w/c 0.523 a/c 5.28 stiffnessfactor 1.e6 \\ + timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 \\ + endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 \\ + ksh 0.0 k3 35. p 1000.} + + + + \subsubsection{Fixed crack model for fiber reinforced composites - FRCFCM} This material model is an extension of the ConcreteFCM described in Section~\ref{concreteFCM}. @@ -4853,7 +5593,8 @@ \subsubsection{Simple interface material - obsolete} In the normal direction, the response is linear elastic, but with different stiffnesses in tension and in compression (stiffness \param{kn} in compression, \param{kn}*\param{stiffcoeff} in tension). By setting \param{kn} to a high value, the penetration (overlap) can be reduced, in the sense of the penalty approach. By setting \param{stiffcoeff} to 0, free opening -of the gap can be allowed. +of the gap can be allowed. + The shear response is elastoplastic, with the yield limit dependent on the normal traction. Crosssection's width, height or area have no influence on the results. The magnitude of the shear traction $\vsig_T$ must not exceed the yield limit computed according to a Coulomb-like friction law as the product of the (negative part of) @@ -4864,6 +5605,15 @@ \subsubsection{Simple interface material - obsolete} $\sigma_N$ is computed multiplying a known normal strain and a known stiffness in tension or in compression. +If \param{regularized} is set to true, the regularized version of the model is used. The regularization parameter \param{m} allows to controll, how close to original formulation the regularized model is. The defaukt value is 15, the higher value the closer resposes are. The regularized version has following form: +\begin{eqnarray} +\sigma_N &=& 0.5 k_n(\delta_0+\delta_n)- + \del{0.5 k_n}{m}\log(|(\cosh(m(\delta_0+\delta_n))|)+\\ + &+&c\left(0.5 k_n(\delta_0+\delta_n)+ + \del{0.5 k_n}{m}\log(|(\cosh(m(\delta_0+\delta_n)))|)\right) +\end{eqnarray} +where $c$ is ratio of tensile/compressive stiffness (\param{stiffcoeff}), $\delta_0$ normal clearance, $\delta_n$ normal strain (jump), and $m$ denoting the regularization coefficient. Consistent tangent stiffness is computed by differentiating the above relation. + The shear elastic stiffness is assumed to be \param{kn} (i.e., equal to the normal stiffness). If the normal traction is tensile or zero, no shear traction can be transmitted by the interface. @@ -4886,6 +5636,8 @@ \subsubsection{Simple interface material - obsolete} &- \param{fc} friction coefficient\\ &- \param{stiffcoeff} ratio (tensile stiffness / compression stiffness)\\ &- \param{normalClearance} free distance within element\\ +&- \param{regularized} when true use regularized formulation (Default is False)\\ +&- \param{m} regularization coefficient $m$ (default value is 15)\\ Supported modes& \_1dInterface\\ \hline @@ -4906,98 +5658,518 @@ \subsubsection{Simple interface material - obsolete} \label{SimpleInterfaceMat} \end{figure} -\subsection{Material models for lattice elements} +\subsubsection{Bond-slip model for reinforced concrete - BondCEB} -Lattice elements have to be used with material models describing the constitutive behavior in the form of vector of tractions and strains determined from displacement jumps smeared out over the element length. +The complex steel/concrete interaction can be modelled with a bond-slip relation, which describes the bond stress (tangential interface traction), $\tau$, in terms of the relative reinforcement slip (tangential interface jump), $s$. This interface material model is based on the local bond--slip relationship for reinforced concrete under good bond conditions outlined in the the \textit{fib} Model Code for Concrete Structures 2010 \cite{fib:2010}. +In general, the model is formulated in terms of the interface traction vector \mbf{t} and the interface jump vector \mbf{\delta}. +In the model, the interface is assumed to have only elastic stiffness $k_\text{n}$ in the normal direction. The normal interface traction is then evaluated elastically from the normal interface jump, i.e. $t_\text{n} = k_\text{n} \delta_\text{n}$. The tangential traction $t_\text{t} = \tau$ is evaluated from the user-specified function $\tau (s)$, see Figure~\ref{BondCEB}: -\subsubsection{Latticedamage2d} -This is a damage lattice material used together with latticedamage2d elements. -It uses a scalar damage relationship of the form \begin{equation} -\boldsymbol{\sigma} = \left(1-\omega\right) \mathbf{D}_{\rm e} \boldsymbol{\varepsilon} +\tau (s) = \begin{cases} + \tau_\text{max} \left( \dfrac{s}{s_1} \right) ^ \alpha & \text{for } 0 \leq s \leq s_1, \\ + \tau_\text{max} & \text{for } s_1 < s \leq s_2, \\ + \tau_\text{max} - \dfrac{\left( \tau_\text{max} - \tau_\text{f} \right) \left(s-s_2 \right)}{\left( s_3 - s_2 \right)} & \text{for } s_2 < s \leq s_3, \\ + \tau_\text{f} & \text{for } s > s_3. + \end{cases} \end{equation} -where $\boldsymbol{\sigma} = \left( \sigma_{\rm n}, \sigma_{\rm t}, \sigma_{\rm \phi}\right)^{T}$ is a vector of tractions and $\boldsymbol{\varepsilon} = \left( \varepsilon_{\rm n}, \varepsilon_{\rm t}, \varepsilon_{\rm \phi}\right)^{T}$ is a vector of strains obtained from displacement jumps smeared over the element length. -Furthermore, $\omega$ is the damage variable varying from 0 (undamaged) to 1 (fully damaged). -Also, $\mathbf{D}_{\rm e}$ is the elastic stiffness matrix which is based on the elastic modulus of the lattice material $E$, and a parameter $\gamma$ which is the ratio of the modulus of the shear and normal direction. -The strength envelope is elliptic (Figure~\ref{StrengthLatticeDamage2d}) and determined by three parameters, $f_{\rm t}$, $f_{\rm q}$ and $f_{\rm c}$. The evolution of the damage variable $\omega$ is controlled by normal stress-normal crack opening law. The three possible laws are linear, bilinear and exponential (Figure~\ref{SofteningLatticeDamage2d}). + +\noindent For an exponent $\alpha$ smaller than 1 (default value 0.4), the initial tangential stiffness of the interface, $k_\text{s}$, is undefined and cannot be used in numerical computations. Therefore, this stiffness needs to be specified manually. Should the provided stiffness be smaller than $k_\text{n} = \dfrac{\tau_\text{max}}{s_1}$, it will be automatically adjusted to this value. Note that only elastic tangent stiffness is supported. Hence, in 2D the tangent stiffness matrix takes the form +\begin{equation} +\dfrac{\partial \mbf{t}}{\partial \mbf{\delta}}= \left[ \begin{array}{cc} +\dfrac{\partial t_\text{n}}{\partial \delta_\text{n}} & +\dfrac{\partial t_\text{n}}{\partial s} \\ +\dfrac{\partial \tau}{\partial \delta_\text{n}} & \dfrac{\partial \tau}{\partial s} +\end{array} \right] = +\left[ \begin{array}{cc} +k_\text{n} & 0 \\ 0 & k_\text{s} +\end{array} \right] +\end{equation} +Model description and the input parameters are summarized in Tab.~\ref{bondceb_table}. \begin{figure}[!htb] \begin{htmlonly} - \centerline{\includegraphics[width=0.7\textwidth]{figStrengthLatticeDamage2d.eps}} + \centerline{\includegraphics[width=0.7\textwidth]{bondceb_diag.eps}} \end{htmlonly} %begin{latexonly} - \centerline{\includegraphics[width=0.7\textwidth]{figStrengthLatticeDamage2d}} -%end{latexonly} - \caption{Strength envelope of LatticeDamage2d.} - \label{StrengthLatticeDamage2d} -\end{figure} - - -\begin{figure}[!htb] -\begin{tabular}{ccc} -%\begin{htmlonly} -% \includegraphics[width=0.7\textwidth]{figSofteningLatticeDamage2da.eps} & \includegraphics[width=0.7\textwidth]{figSofteningLatticeDamage2db.eps} & \includegraphics[width=0.7\textwidth]{figSofteningLatticeDamage2dc.eps}\\ -%\end{htmlonly} -%begin{latexonly} -\includegraphics[width=0.3\textwidth]{figSofteningLatticeDamage2da} & \includegraphics[width=0.3\textwidth]{figSofteningLatticeDamage2db} & \includegraphics[width=0.3\textwidth]{figSofteningLatticeDamage2dc}\\ + \centerline{\includegraphics[width=0.5\textwidth]{bondceb_diag}} %end{latexonly} -(a) & (b) & (c) -\end{tabular} - \caption{Softening types of LatticeDamage2d: (a) linear softening, (b) bilinear softening, (c) exponential softening.} - \label{SofteningLatticeDamage2d} + \caption{Bond stress ($\tau$) - reinforcement slip ($s$) diagram for BondCEB model.} + \label{BondCEB} \end{figure} -The model parameters are summarised in Tab.~\ref{latticedamage2d_table}. \begin{table}[!htb] %\begin{center} \begin{mmt} \hline -Description & Saclar damage model for lattice2d \\ +Description & Bond-slip model for reinforced concrete\\ \hline -Record Format & \descitem{latticedamage2d} \elemparam{}{in} -\elemparam{d}{rn} \elemparam{talpha}{rn} \elemparam{e}{rn} \elemparam{a1}{rn} \elemparam{a2}{rn} \elemparam{e0}{rn} \elemparam{coh}{rn} \elemparam{ec}{rn} \elemparam{stype}{rn} \elemparam{wf}{rn} \elemparam{wf1}{rn} \\ +Record Format & \descitem{bondceb} \elemparam{}{in} +\elemparam{kn}{rn} \elemparam{ks}{rn} \elemparam{s1}{rn} \elemparam{s2}{rn} \elemparam{s3}{rn} \elemparam{taumax}{rn} \optelemparam{tauf}{rn} \optelemparam{alpha}{rn}\\ Parameters &- \param{} material number\\ -&- \param{d} material density\\ -&- \param{talpha} Thermal exansion coefficient\\ -&- \param{e} normal modulus of lattice material\\ -&- \param{a1} ratio of shear and normal modulus\\ -&- \param{a2} ratio of rotational and normal modulus. Optional parameter. Default is 1.\\ -&- \param{e0} strain at tensile strength: $f_{\rm t}/E$\\ -&- \param{coh} ratio of shear and tensile strength: $f_{\rm q}/f_{\rm t}$\\ -&- \param{ec} ratio of compressive and tensile strength: $f_{\rm c}/f_{\rm t}$\\ -&- \param{stype} softening types: 1-linear, 2-bilinear and 3-exponential\\ -&- \param{wf} displacement threshold related to fracture energy used in all three softening types.\\ +&- \param{kn} interface elastic normal stiffness\\ +&- \param{ks} interface elastic tangential (shear) stiffness\\ +&- \param{s1} characteristic slip value\\ +&- \param{s2} characteristic slip value\\ +&- \param{s3} characteristic slip value\\ +&- \param{taumax} maximum bond stress\\ +&- \param{tauf} residual bond stress at reinforcement pull-out\\ +&- \param{alpha} bond-slip curve parameter (exponent)\\ -Supported modes& 2dlattice\\ +Supported modes& \_2dInterface, \_3dInterface\\ \hline \end{mmt} -\caption{Scalar damage model for 2d lattice elements -- summary.} -\label{latticedamage2d_table} +\caption{Bond-slip model for reinforced concrete -- summary.} +\label{bondceb_table} %\end{center} \end{table} +\subsubsection{Slip model for trusses and beams} +This is an elasto-plastic model for slip between reinforcement modelled as three-dimensional beam or truss elements and matrix elements. The theory of the model is described in the paper \textit{Upscaling of three-dimensional reinforced concrete representative volume elements to effective beam and plate models. A Sciegaj, P Grassl, F Larsson, K Runesson, K Lundgren. International Journal of Solids and Structures 202, 835-853} The model parameters are summarised in Tab.~\ref{linkslip_table}. -\subsection{Material models for steel relaxation} +\begin{table}[!htb] +\begin{mmt} +\hline +Description & Slip model \\ +\hline +Record Format & \descitem{linkslip} \elemparam{}{in} +\elemparam{kn}{rn} \elemparam{ks}{rn} \elemparam{s1}{rn} \elemparam{s2}{rn} \elemparam{s3}{rn} \elemparam{taumax}{rn} \optelemparam{tauf}{rn} \optelemparam{alpha}{rn}\\ +Parameters &- \param{} material number\\ +&- \param{ka} interface elastic axial stiffness (in the direction of slip)\\ +&- \param{kl} interface elastic lateral stiffness\\ +&- \param{s1} characteristic slip value\\ +&- \param{s2} characteristic slip value\\ +&- \param{s3} characteristic slip value\\ +&- \param{taumax} maximum bond stress\\ +&- \param{tauf} residual bond stress at reinforcement pull-out\\ +&- \param{alpha} bond-slip curve parameter (exponent)\\ -\subsubsection{Model for relaxation of prestressing steel - SteelRelaxMat} -This section describes the implementation of the material model for -steel relaxation given in Eurocode 2 (the same as in Model Code 2010) -and in Ba\v{z}ant and Yu (J. of Eng. Mech, 2013) which reduces to the first model under -constant strain. At variable strain history the first model uses the -approach employing the so-called {\sl{equivalent time}} approach -described in Annex D in the Eurocode 2. +Supported modes & \_3dInterface\\ +\hline +\end{mmt} +\caption{Slip model for truss and beam elements -- summary.} +\label{linkslip_table} +%\end{center} +\end{table} -The current implementation takes into account only prestress losses -due to steel relaxation, other losses (e.g. slip at anchorage, -thermal dilation, friction, etc.) need to be treated separately. The same holds -for the stress transfer from prestressing reinforcement to concrete in -the region called {\sl{transmission length}}. On the other hand, -losses due to sequential prestressing, elastic deformation and both -short-time and long-time creep and shrinkage are taken into account -automatically provided that a suitable material model is chosen for -concrete. -In the first approach the stress on the end of the time step is + + +\subsection{Material models for lattice elements} + +Lattice elements have to be used with material models describing the constitutive behaviour in the form of vector of tractions and rotational stress components, and strains and rotational strain components determined from displacement jumps smeared out over the element length. + +\subsubsection{Linear elastic lattice model} +This is a linear elastic material used together with lattice elements. +It uses a stress strain law of the form +\begin{equation} +\boldsymbol{\sigma} = \mathbf{D}_{\rm e} \boldsymbol{\varepsilon} +\end{equation} +where $\boldsymbol{\sigma}$ is a vector of tractions and rotational components, and $\boldsymbol{\varepsilon}$ is a vector of strains obtained from displacement jumps smeared over the element length and rotational components. +Furthermore, $\mathbf{D}_{\rm e}$ is the elastic stiffness matrix which is based on the elastic modulus of the lattice material $E$, and a parameter $a_1$ which is the ratio of the modulus of the shear and normal direction. There is the option to include a rotational stiffness. The model parameters are summarised in Tab.~\ref{latticelinearelastic_table}. + +\begin{table}[!htb] +\begin{mmt} +\hline +Description & Linear elastic model for lattice elements \\ +\hline +Record Format & \descitem{latticelinearelastic} \elemparam{}{in} +\elemparam{d}{rn} \optelemparam{talpha}{rn} \optelemparam{calpha}{rn} \elemparam{e}{rn} \optelemparam{a1}{rn} \optelemparam{a2}{rn}\\ +Parameters &- \param{} material number\\ +&- \param{d} material density\\ +&- \optparam{talpha} Thermal strain expansion coefficient. Default is 0.\\ +&- \optparam{calpha} Thermal displacement expansion coefficient. Default is 0.\\ +&- \param{e} Young's modulus of the equivalent lattice material\\ +&- \optparam{a1} ratio of shear and normal modulus. Default is 1.\\ +&- \optparam{a2} ratio of rotational and normal modulus. Default is 1.\\ +Supported modes & 2dlattice, 3dlattice\\ +\hline +\end{mmt} +\caption{Linear elastic material model for lattice elements -- summary.} +\label{latticelinearelastic_table} +\end{table} + +\subsubsection{Scalar damage lattice model} +This is a scalar damage material model used together with lattice elements. +It uses a scalar damage model, which results in a stress-strain law of the form +\begin{equation} +\boldsymbol{\sigma} = \left(1-\omega\right) \mathbf{D}_{\rm e} \boldsymbol{\varepsilon} +\end{equation} +where $\boldsymbol{\sigma}$ is a vector of tractions and rotational components, and $\boldsymbol{\varepsilon}$ is a vector of strains obtained from displacement jumps smeared over the element length and rotational components. +Furthermore, $\omega$ is the damage variable varying from 0 (undamaged) to 1 (fully damaged). +Also, $\mathbf{D}_{\rm e}$ is the elastic stiffness matrix which is based on the elastic modulus of the lattice material $E$, and a parameter $a_1$ which is the ratio of the modulus of the shear and normal direction. +The strength envelope (onset of damage) is elliptic and determined by three parameters, $f_{\rm t}$, $f_{\rm q}$ and $f_{\rm c}$. The evolution of the damage variable $\omega$ is controlled by normal stress-normal crack opening law. The three possible laws are linear, bilinear and exponential. + +This simple damage material model for lattice elements has been used in many recent articles. For instance, the two dimensional version has been used in \textit{P. Grassl and M. Jir\'{a}sek. "Meso-scale approach to modelling the fracture process zone of concrete subjected to uniaxial tension". International Journal of Solids and Structures. Volume 47, Issues 7-8, pp. 957-968, 2010}. An example of an application of the three dimensional version of the model is found in \textit{P. Grassl, J. Bolander. "Three-Dimensional Network Model for Coupling of Fracture and Mass Transport in Quasi-Brittle Geomaterials", Materials, 9, 782, 2016}. + +The model parameters are summarised in Tab.~\ref{latticedamage_table}. +\begin{table}[!htb] +%\begin{center} +\begin{mmt} +\hline +Description & Scalar damage model for lattice elements \\ +\hline +Record Format & \descitem{latticedamage} \elemparam{}{in} +\elemparam{d}{rn} \optelemparam{talpha}{rn} \elemparam{e}{rn} \optelemparam{a1}{rn} \optelemparam{a2}{rn} \optelemparam{e0}{rn} \optelemparam{coh}{rn} \optelemparam{ec}{rn} \optelemparam{stype}{rn} \optelemparam{wf}{rn} \optelemparam{wf1}{rn} \\ +Parameters &- \param{} material number\\ +&- \param{d} material density\\ +&- \optparam{talpha} Thermal strain expansion coefficient. Default i 0.\\ +&- \optparam{calpha} thermal displacement expansion coefficient. Default is 0.\\ +&- \param{e} normal modulus of lattice material\\ +&- \optparam{a1} ratio of shear and normal modulus. Default is 1.\\ +&- \optparam{a2} ratio of rotational and normal modulus. Default is 1.\\ +&- \param{e0} strain at tensile strength: $f_{\rm t}/E$\\ +&- \param{coh} ratio of shear and tensile strength: $f_{\rm q}/f_{\rm t}$\\ +&- \param{ec} ratio of compressive and tensile strength: $f_{\rm c}/f_{\rm t}$\\ +&- \optparam{stype} softening types: 1-linear, 2-bilinear and 3-exponential. Default is 1.\\ +&- \param{wf} displacement threshold related to fracture energy used in all three softening types.\\ +&- \optparam{wf1} displacement threshold related to softening type 2. Default is wf1=0.15 wf.\\ +&- \optparam{e01} strain threshold related to softening type 2. Default is wf1=0.15 wf\\ +&- \optparam{bio} Biot's coefficient.\\ +&- \optparam{btype} Type to consider how Biot's coefficient changes with crack opening.\\ + +Supported modes& 2dlattice, 3dlattice\\ +\hline +\end{mmt} +\caption{Scalar damage model for lattice elements -- summary.} +\label{latticedamage_table} +%\end{center} +\end{table} + +\subsubsection{Plasticity damage lattice model} + +This combined plasticity damage model for lattice elements has been developed to describe the failure process of geomaterials such as concrete and rock. The plasticity part is based on the effective stress and damage is evaluated by the plastic strain. The model was first introduced in \cite{GraDav11} without hardening and then extended to hardening in \cite{AthWheGra18}. + +The main stress-strain law has the form +\begin{equation} +\boldsymbol{\sigma} = \left(1-\omega\right) \mathbf{D}_{\rm e} \left(\boldsymbol{\varepsilon}-\boldsymbol{\varepsilon}_{\rm p} \right) +\end{equation} +where $\boldsymbol{\sigma}$ is a vector of tractions and rotational components, $\omega$ is the damage variable and $\mathbf{D}_{\rm e}$ is the elastic stiffness matrix, $\boldsymbol{\varepsilon}$ is a vector of strains obtained from displacement jumps smeared over the element length and rotational components and $\boldsymbol{\varepsilon}_{\rm p}$ are the plastic strains. + +The plasticity part is based on the effective stresses and uses only a subset of the strains and stresses which are the normal stress $\sigma_{\rm n}$ and the two shear stresses $\sigma_{\rm s}$ and $\sigma_{\rm t}$. The yield surface is composed of two ellipse which are arranged so that the transition of the two ellipses is smooth (Figure~\ref{plastdamyieldfig}). +% +\begin{figure}[htb] + \centering + \includegraphics[width=0.6\textwidth]{./plastdamyieldfig.pdf} + \caption{Latticeplastdam yield surface, which is composed of ellipse with a smooth transition.} + \label{plastdamyieldfig} +\end{figure} +% +The resulting yield function $f$ is +\begin{equation} +f = \left\{ \begin{array}{l} \alpha^2\bar{\sigma}_{\rm n}^2 + 2 \dfrac{\alpha^2\left(f_{\rm c} - \alpha \beta f_{\rm t}\right)}{\left(1+\alpha \beta\right)} q \bar{\sigma}_{\rm n} + \bar{\sigma}_{\rm q}^2 - \dfrac{2 \alpha^2 f_{\rm c}f_{\rm t} + \alpha^2 \left(1-\alpha \beta \right) f_{\rm t}^2}{1+\alpha \beta} q^2 \\ \mbox{if $\bar{\sigma}_{\rm n} \geq -\dfrac{f_{\rm c} - \alpha \beta f_{\rm t}}{1+\alpha \beta} q$} \vspace{0.5cm}\\ + \dfrac{\bar{\sigma}_{\rm n}^2}{\beta^2} + 2 \dfrac{f_{\rm c} - \alpha \beta f_{\rm t}}{\beta^2 \left(1+\alpha \beta \right)} q \bar{\sigma}_{\rm n} + \bar{\sigma}_{\rm q}^2 + \dfrac{\left(1-\alpha \beta\right) f_{\rm c}^2 -2 \alpha \beta f_{\rm c} f_{\rm t} }{\beta^2 \left(1+\alpha \beta \right)} q^2\\ \mbox{if $\bar{\sigma}_{\rm n} < - \dfrac{f_{\rm c} - \alpha \beta f_{\rm t}}{1+\alpha \beta} q$} \end{array} \right. + \end{equation} +here parameters $\alpha$ and $\beta$ are the slopes, and $f_{\rm c}$ and $f_{\rm t}$ are the strength parameters shown in Figure~\ref{plastdamyieldfig}. The hardening function $q$ controls the shape of the yield function. + +The model parameters are summarised in Tab.~\ref{latticeplastdam_table}. + +\begin{table}[!htb] +%\begin{center} +\begin{mmt} +\hline +Description & Combined plasticity damage model for lattice elements \\ +\hline +Record Format & \descitem{latticeplastdam} \elemparam{}{in} +\elemparam{d}{rn} \optelemparam{talpha}{rn} \optelemparam{calpha}{rn} \elemparam{e}{rn} \optelemparam{a1}{rn} \optelemparam{a2}{rn} \elemparam{ft}{rn} \elemparam{fc}{rn} \optelemparam{angle1}{rn} \optelemparam{angle2}{rn} \optelemparam{flow}{rn} \optelemparam{stype}{rn} \elemparam{wf}{rn} \optelemparam{ft1}{rn} \optelemparam{wf1}{rn} \optelemparam{ahard}{rn} \optelemparam{damage}{in} \optelemparam{sub}{in} \optelemparam{tol}{rn} \optelemparam{iter}{in}\\ +Parameters &- \param{} material number\\ +&- \param{d} material density\\ +&- \optparam{talpha} Thermal expansion coefficient. Default is 0.\\ +&- \optparam{calpha} thermal displacement expansion coefficient. Optional parameter. Default is 0.\\ +&- \param{e} modulus of the equivalent lattice material\\ +&- \optparam{a1} ratio of shear and normal modulus. Default is 1.\\ +&- \optparam{a2} ratio of rotational and normal modulus. Default is 1.\\ +&- \param{ft} tensile strength\\ +&- \param{fc} compressive strength\\ +&- \optparam{angle1} ratio of compressive and tensile strength. Default is 0.5\\ +&- \optparam{angle2} ratio of compressive and tensile strength. Default is 0.5\\ +&- \optparam{flow} ratio of compressive and tensile strength. Default is 0.25\\ +&- \optparam{stype} softening types: 0-exponential, 1-bilinear. Default is 0\\ +&- \param{wf} displacement threshold related to fracture energy used in both softening types.\\ +&- \optparam{wf1} displacement threshold related to softening type 1. Default is wf1=0.1 wf.\\ +&- \optparam{ft1} stress threshold related to softening type 1. Optional parameter. Default is ft1=0.15 ft.\\ +&- \optparam{ahard} displacement threshold related to fracture energy used in all three softening types. Default value is 0.1\\ +&- \optparam{damage} flag to switch on and off damage. Default value is 1, which considers damage.\\ +&- \optparam{sub} maximum number of subincrementations in the plasticity part. Default is 10.\\ +&- \optparam{tol} tolerance for the newton iteration of the plasticity part. Default value is 1.e-6.\\ +&- \optparam{iter} maximum number of iterations for the stress return of the plasticity model. Default is 100.\\ + +Supported modes& 3dlattice\\ +\hline +\end{mmt} +\caption{Plasticity damage model for lattice elements -- summary.} +\label{latticeplastdam_table} +%\end{center} +\end{table} + + +\subsubsection{Slip lattice model} +This is an elasto-plastic model for slip between fibres modelled three-dimensional beam elements and lattice link elements. The theory of the model is described in the paper \textit{P. Grassl and A. Antonelli. "3D network modelling of fracture processes in fibre-reinforced geomaterials", International Journal of Solids and Structures, vol. 156-157, Pages 234-242, 2019.} The model parameters are summarised in Tab.~\ref{latticeslip_table}. + +\begin{table}[!htb] +\begin{mmt} +\hline +Description & Slip model for lattice elements \\ +\hline +Record Format & \descitem{latticeslip} \elemparam{}{in} +\elemparam{d}{rn} \optelemparam{talpha}{rn} \optelemparam{calpha}{rn} \elemparam{e}{rn} \optelemparam{a1}{rn} \optelemparam{a2}{rn} \elemparam{t0}{rn}\\ +Parameters &- \param{} material number\\ +&- \param{d} material density\\ +&- \optparam{talpha} Thermal expansion coefficient. Default is 0.\\ +&- \optparam{calpha} thermal displacement expansion coefficient. Optional parameter. Default is 0.\\ +&- \param{e} modulus of the equivalent lattice material\\ +&- \optparam{a1} ratio of shear and normal modulus. Default is 1000.\\ +&- \optparam{a2} ratio of rotational and normal modulus. Default is 1000.\\ +&- \param{t0} limit of stress in slip direction\\ + +Supported modes & 3dlattice\\ +\hline +\end{mmt} +\caption{Slip model for lattice elements -- summary.} +\label{latticeslip_table} +%\end{center} +\end{table} + + +\subsubsection{Bond lattice model} +This is an elasto-plastic model for modelling the bond between two parts modelled with three dimensional lattice elements. +The stress-strain law has the form +\begin{equation} +\boldsymbol{\sigma} = \mathbf{D}_{\rm e} \left(\boldsymbol{\varepsilon}-\boldsymbol{\varepsilon}_{\rm p} \right) +\end{equation} +where $\boldsymbol{\sigma}$ is a vector of tractions and rotational components, $\mathbf{D}_{\rm e}$ is the elastic stiffness matrix, $\boldsymbol{\varepsilon}$ is a vector of strains obtained from displacement jumps smeared over the element length and rotational components and $\boldsymbol{\varepsilon}_{\rm p}$ are the plastic strains. + +The theory of the model is described in the paper \textit{P. Grassl and T. Davies. "Lattice modelling of corrosion induced cracking and bond in reinforced concrete". Cement and Concrete Composites, Volume 33, pp. 918-924, 2011}. + +The model parameters are summarised in Tab.~\ref{latticebond_table}. + +\begin{table}[!htb] +\begin{mmt} +\hline +Description & Bond model for lattice elements \\ +\hline +Record Format & \descitem{latticebondplast} \elemparam{}{in} +\elemparam{d}{rn} \optelemparam{talpha}{rn} \optelemparam{calpha}{rn} \elemparam{e}{rn} \optelemparam{a1}{rn} \optelemparam{a2}{rn} \elemparam{fc}{rn} \elemparam{angle1}{rn} \elemparam{ef}{rn} \elemparam{sub}{in} \elemparam{iter}{in} \elemparam{tol}{rn}\\ +Parameters &- \param{} material number\\ +&- \param{d} material density\\ +&- \optparam{talpha} Thermal expansion coefficient. Default is 0.\\ +&- \optparam{calpha} thermal displacement expansion coefficient. Optional parameter. Default is 0.\\ +&- \param{e} modulus of the equivalent lattice material\\ +&- \optparam{a1} ratio of shear and normal modulus. Default is 1.\\ +&- \optparam{a2} ratio of rotational and normal modulus. Default is 1.\\ +&- \param{fc} compressive strength\\ +&- \param{angle1} friction angle\\ +&- \optparam{ef} strain threshold to control hardening\\ +&- \optparam{sub} maximum number of subincrementations\\ +&- \optparam{iter} maximum number of newton iterations\\ +&- \optparam{tol} tolerance for newton method\\ + +Supported modes & 3dlattice\\ +\hline +\end{mmt} +\caption{Bond plasticity model for lattice elements -- summary.} +\label{latticebond_table} +%\end{center} +\end{table} + +\subsubsection{Viscoelastic lattice model} + +This model combines a viscoelastic model, described in previous sections, with a linear elastic lattice material. Two material entries are used. One is for the viscoelastic lattice model and the other is for the viscoelastic model of choice. + +The model description and parameters are summarized in Tab.~\ref{latticeviscoelastic_table}. + +\begin{table}[!htb] +\begin{mmt} +\hline +Description & Viscoelastic lattice model\\ +\hline +Record Format & \descitem{latticeviscoelastic} \elemparam{}{in} +\elemparam{viscomat}{in} \elemparam{d}{rn} \optelemparam{talpha}{rn} \optelemparam{calpha}{rn} \elemparam{e}{rn} \optelemparam{a1}{rn} \optelemparam{a2}{rn}\\ +Parameters &- \param{} material number\\ +&- \param{viscomat} material number for viscoelastic model\\ +&- \param{d} material density\\ +&- \optparam{talpha} Thermal strain expansion coefficient. Default is 0.\\ +&- \optparam{calpha} Thermal displacement expansion coefficient. Default is 0.\\ +&- \param{e} Young's modulus of the equivalent lattice material\\ +&- \optparam{a1} ratio of shear and normal modulus. Default is 1.\\ +&- \optparam{a2} ratio of rotational and normal modulus. Default is 1.\\ +Supported modes & 2dlattice, 3dlattice\\ +\hline +\end{mmt} +\caption{Visco elastic material model for lattice elements -- summary.} +\label{latticeviscoelastic_table} +\end{table} + + +\subsubsection{Viscoelastic damage lattice model} + +This model combines a viscoelastic model, described in previous sections, with a damage lattice material model. Two material entries are used. One is for the viscoelastic extension of the damage lattice model and the other is for the viscoelastic model of choice. + +The model description and parameters are summarized in Tab.~\ref{latticedamageviscoelastic_table}. + +\begin{table}[!htb] +\begin{mmt} +\hline +Description & Viscoelastic damage lattice model\\ +\hline +Record Format & \descitem{latticedamageviscoelastic} \elemparam{}{in} +\elemparam{viscomat}{in} \elemparam{timefactor}{rn} \elemparam{d}{rn} \optelemparam{talpha}{rn} \optelemparam{calpha}{rn} \elemparam{e}{rn} \optelemparam{a1}{rn} \optelemparam{a2}{rn} \optelemparam{e0}{rn} \optelemparam{coh}{rn} \optelemparam{ec}{rn} \optelemparam{stype}{rn} \optelemparam{wf}{rn} \optelemparam{wf1}{rn}\\ +Parameters &- \param{} material number\\ +&- \param{viscomat} material number for viscoelastic model\\ +&- \param{d} material density\\ +&- \optparam{talpha} Thermal strain expansion coefficient. Default is 0.\\ +&- \optparam{calpha} Thermal displacement expansion coefficient. Default is 0.\\ +&- \param{e} Young's modulus of the equivalent lattice material\\ +&- \optparam{a1} ratio of shear and normal modulus. Default is 1.\\ +&- \optparam{a2} ratio of rotational and normal modulus. Default is 1.\\ +&- \param{e0} strain at tensile strength: $f_{\rm t}/E$\\ +&- \param{coh} ratio of shear and tensile strength: $f_{\rm q}/f_{\rm t}$\\ +&- \param{ec} ratio of compressive and tensile strength: $f_{\rm c}/f_{\rm t}$\\ +&- \optparam{stype} softening types: 1-linear, 2-bilinear and 3-exponential. Default is 1.\\ +&- \param{wf} displacement threshold related to fracture energy used in all three softening types.\\ +&- \optparam{wf1} displacement threshold related to softening type 2. Default is wf1=0.15 wf.\\ +&- \optparam{e01} strain threshold related to softening type 2. Default is wf1=0.15 wf\\ +&- \optparam{bio} Biot's coefficient.\\ +&- \optparam{btype} Type to consider how Biot's coefficient changes with crack opening.\\ +Supported modes & 2dlattice, 3dlattice\\ +\hline +\end{mmt} +\caption{Damage visco elastic material model for lattice elements -- summary.} +\label{latticedamageviscoelastic_table} +\end{table} + +\subsubsection{Viscoelastic plasticity damage lattice model} + +This model combines a viscoelastic model, described in previous sections, with a plasticity damage lattice material model. Two material entries are used. One is for the viscoelastic extension of the plasticity damage lattice model and the other is for the viscoelastic model of choice. + +The model description and parameters are summarized in Tab.~\ref{latticeplasticdamageviscoelastic_table}. + +\begin{table}[!htb] +\begin{mmt} +\hline +Description & Plasticity-damage viscoelastic lattice model\\ +\hline +Record Format & \descitem{latticeplasticitydamageviscoelastic} \elemparam{}{in} +\elemparam{viscomat}{in} \elemparam{timefactor}{rn} \elemparam{d}{rn} \optelemparam{talpha}{rn} \optelemparam{calpha}{rn} \elemparam{e}{rn} \optelemparam{a1}{rn} \optelemparam{a2}{rn} \elemparam{ft}{rn} \elemparam{fc}{rn} \optelemparam{angle1}{rn} \optelemparam{angle2}{rn} \optelemparam{flow}{rn} \optelemparam{stype}{rn} \elemparam{wf}{rn} \optelemparam{ft1}{rn} \optelemparam{wf1}{rn} \optelemparam{ahard}{rn} \optelemparam{damage}{in} \optelemparam{sub}{in} \optelemparam{tol}{rn} \optelemparam{iter}{in}\\ +Parameters &- \param{} material number\\ +&- \param{viscomat} material number for viscoelastic material\\ +&- \param{d} material density\\ +&- \optparam{talpha} Thermal strain expansion coefficient. Default is 0.\\ +&- \optparam{calpha} Thermal displacement expansion coefficient. Default is 0.\\ +&- \param{e} Young's modulus of the equivalent lattice material\\ +&- \optparam{a1} ratio of shear and normal modulus. Default is 1.\\ +&- \optparam{a2} ratio of rotational and normal modulus. Default is 1.\\ +&- \param{ft} tensile strength\\ +&- \param{fc} compressive strength\\ +&- \optparam{angle1} ratio of compressive and tensile strength. Default is 0.5\\ +&- \optparam{angle2} ratio of compressive and tensile strength. Default is 0.5\\ +&- \optparam{flow} ratio of compressive and tensile strength. Default is 0.25\\ +&- \optparam{stype} softening types: 0-exponential, 1-bilinear. Default is 0\\ +&- \param{wf} displacement threshold related to fracture energy used in both softening types.\\ +&- \optparam{wf1} displacement threshold related to softening type 1. Default is wf1=0.1 wf.\\ +&- \optparam{ft1} stress threshold related to softening type 1. Optional parameter. Default is ft1=0.15 ft.\\ +&- \optparam{ahard} displacement threshold related to fracture energy used in all three softening types. Default value is 0.1\\ +&- \optparam{damage} flag to switch on and off damage. Default value is 1, which considers damage.\\ +&- \optparam{sub} maximum number of subincrementations in the plasticity part. Default is 10.\\ +&- \optparam{tol} tolerance for the newton iteration of the plasticity part. Default value is 1.e-6.\\ +&- \optparam{iter} maximum number of iterations for the stress return of the plasticity model. Default is 100.\\ +Supported modes & 3dlattice\\ +\hline +\end{mmt} +\caption{Plasticity-damage viscoelastic material model for lattice elements -- summary.} +\label{latticeplasticdamageviscoelastic_table} +\end{table} + +\subsubsection{Plasticity lattice model for steel} + +This is a Plasticity material used together with lattice elements.It has bean developed to describe the failure process failure of steel frame member. +The stress-strain law has the form +\begin{equation} +\boldsymbol{\sigma} = \mathbf{D}_{\rm e} \left(\boldsymbol{\varepsilon}-\boldsymbol{\varepsilon}_{\rm p} \right) +\end{equation} +where $\boldsymbol{\sigma}$ is a vector of tractions and rotational components, $\mathbf{D}_{\rm e}$ is the elastic stiffness matrix, $\boldsymbol{\varepsilon}$ is a vector of strains obtained from displacement jumps smeared over the element length and rotational components and $\boldsymbol{\varepsilon}_{\rm p}$ are the plastic strains. The model parameters are summarised in Table \ref{latticeframesteelplastic_table}. +\begin{table}[!htb] + \centering +\begin{tabular}{|l|l|} +\hline +Description & Plasticity lattice model for steel \\ +\hline +Record Format & \descitem{latticeframesteelplastic} $\elemparam{}_{(in)}$ +$\elemparam{d}_{(rn)}$ $\optelemparam{talpha}_{(rn)}$ $\elemparam{e}_{(rn)}$ $\optelemparam{n}_{(rn)}$ $\optelemparam{nx0}_{(rn)}$ $\optelemparam{mx0}_{(rn)}$\\ &$\optelemparam{my0}_{(rn)}$ $\optelemparam{mz0}_{(rn)}$ $\elemparam{sub}_{(in)}$ $\elemparam{iter}_{(in)}$ $\elemparam{tol}_{(rn)}$\\ +Parameters &- \param{} material number\\ +&- $\param{d}$ material density\\ +&- $\optparam{talpha}$ Thermal expansion coefficient. Default is 0.\\ +&- $\optparam{e}$ Young's modulus of the lattice material.\\ +&- $\param{n}$ Poisson's ratio of the material that the beam element is made of.\\ +&- $\optparam{nx0}$ ultimate capacity under pure axialloads.\\ +&- $\optparam{mx0}$ ultimate capacity under pure moment about $x$.\\ +&- $\optparam{my0}$ ultimate capacity under pure moment about $y$.\\ +&- $\optparam{mz0}$ ultimate capacity under pure moment about $z$.\\ +&- $\optparam{sub}$ maximum number of subincrementations.\\ +&- $\optparam{iter}$ maximum number of newton iterations.\\ +&- $\optparam{tol}$ tolerance for newton method.\\ +Supported modes & 3dlattice\\ + +\hline +\end{tabular} + +\caption{Plasticity steel model for lattice elements -- summary.} +\label{latticeframesteelplastic_table} +%\end{center} + \end{table} +The nonlinear response of the beam element is given directly as an relationship between internal force and strain. The basic equations include an additive decomposition of total strain into elastic part and plastic part + +\begin{equation} +\boldsymbol{\varepsilon} = \boldsymbol{\varepsilon}_{\rm e}-\boldsymbol{\varepsilon}_{\rm p} +\end{equation} + +Trail stress +\begin{equation} + \sigma_{n+1}^{tr} =D^e (\varepsilon_{n+1} - \varepsilon_n^p) +\end{equation} + +The yield function +\begin{equation} +(\frac{N_x}{N_0})^2+ (\frac{M_x}{M_{x0}} )^2+ (\frac{M_y}{M_{y0}} )^2+ (\frac{M_z}{M_{z0}} )^2- 1 = 0 +\end{equation} + +where $M$, $M y$ , $N$ and $M$ , are the two components of bending moment, an axial force and +a torsional moment, respectively. The subscript 0 indicates a fully plastic value under the +condition that each component of resultant forces acts independently on a cross-section of +a member. +\\ +loading-unloading conditions + +loading-unloading conditions +\begin{equation} +f(\bar{\vsig},\kappa)\le 0 \qquad \dot{\lambda}\geq 0 \qquad \dot{\lambda}f(\bar{\vsig},\kappa)=0, +\end{equation} +evolution law for plastic strain +\begin{equation} +\dot{\veps}_{\rm{p}} = \dot{\lambda} \frac{\partial f}{\partial \bar{\vsig}}, +\end{equation} + + +\subsection{Material models for steel relaxation} + +\subsubsection{Model for relaxation of prestressing steel - SteelRelaxMat} +This section describes the implementation of the material model for +steel relaxation given in Eurocode 2 (the same as in Model Code 2010) +and in Ba\v{z}ant and Yu (J. of Eng. Mech, 2013) which reduces to the first model under +constant strain. At variable strain history the first model uses the +approach employing the so-called {\sl{equivalent time}} approach +described in Annex D in the Eurocode 2. + +The current implementation takes into account only prestress losses +due to steel relaxation, other losses (e.g. slip at anchorage, +thermal dilation, friction, etc.) need to be treated separately. The same holds +for the stress transfer from prestressing reinforcement to concrete in +the region called {\sl{transmission length}}. On the other hand, +losses due to sequential prestressing, elastic deformation and both +short-time and long-time creep and shrinkage are taken into account +automatically provided that a suitable material model is chosen for +concrete. + +In the first approach the stress on the end of the time step is explicitly given by the current stress, prestressing level and the cumulative value of prestress losses. On the other hand, in Ba\v{z}ant's approach it is necessary to iterate on the material point @@ -5041,13 +6213,13 @@ \subsubsection{Model for relaxation of prestressing steel - SteelRelaxMat} \hline Description & SteelRelaxMat model for relaxation of prestressing reinforcement\\ \hline -Record Format & \descitem{SteelRelaxMat} +Record Format & \descitem{SteelRelaxMat} \elemparam{d}{rn} \elemparam{E}{rn} \elemparam{reinfClass}{in} \optelemparam{timeFactor}{rn} -\elemparam{charStrength}{rn} -\elemparam{approach}{in} +\elemparam{charStrength}{rn} +\elemparam{approach}{in} \optelemparam{k1}{rn} \optelemparam{k2}{rn} \optelemparam{rho1000}{rn} @@ -5087,6 +6259,52 @@ \subsubsection{Model for relaxation of prestressing steel - SteelRelaxMat} \end{table} +\subsection{User-defined material models using MFront} +A user-defined material created with MFront can be used if MGIS is installed +\newline +(https://github.com/thelfer/MFrontGenericInterfaceSupport) and linked to OOFEM with cmake before the compilation. +Run cmake with following flags and specify the location of the MGIS cmake files: +\newline +\verb|-DUSE_MFRONT=ON -DMFrontGenericInterface_DIR=/path/to/mgis/cmake/| +\newline +Once OOFEM is compiled with this setting, the file /tests/smmfront/mfront01.in will be included in the tests. +It requires the file +\newline +/tests/smmfront/plasticityIsotropicLinearHardeningPlasticity.mfront to be processed by MFront before the tests are run. +\newline +See /tests/smmfront/readme\_install.txt for more detailed instructions. + +\begin{table}[!htb] +%\begin{center} +\begin{mmt} +\hline +Description & MFrontUserMaterial allows use of user-defined material models based on MFront\\ +\hline +Record Format & \descitem{MFrontUserMaterial} +\elemparam{d}{rn} +\elemparam{modelname}{s} +\elemparam{libpath}{s} +\elemparam{properties}{dc}\\ +Parameters &- \param{num} material model number\\ +&- \param{d} specific weight\\ +&- \param{modelname} name of the material model from the shared library to be used \\ +&- \param{libpath} path to the shared library of the material created with MFront \\ +&- \param{properties} are not used now, which yields in "properties~0" on input for now \\ + +Supported modes& 3dMat\\ +\hline +\end{mmt} +\caption{MFrontUserMaterial material model -- summary.} +\label{MFrontUserMaterial_table} +%\end{center} +\end{table} + + + + + + + \clearpage \section{Material Models for Transport Problems} @@ -5238,8 +6456,7 @@ \subsection{Nonlinear isotropic material for moisture transport -- NlIsoMoisture k(h) \frac{\partial h}{\partial t} = \nabla \cdot \left[ c(h) \nabla h \right] + w_n \frac{\ud \alpha}{\ud t} \end{equation} where -$k(h)$ [kg/m$^3$] is the humidity-dependent moisture capacity (derivative of -the moisture content with respect to the relative humidity), $c(h)$ +$k(h)$ [kg/m$^3$] is the humidity-dependent moisture capacity ($k(h)=\frac{\partial w}{\partial h}$ which is derivative of the moisture content $w(h)$ [kg/m$^3$] with respect to the relative humidity), $c(h)$ [kg/m/s] is the moisture permeability and the sink term $w_n \frac{\ud \alpha}{\ud t}$ corresponds to non-evaporable water loss due to hydration. $w_n$ is non-evaporable water content for complete hydration per m$^3$ [kg/m$^3$] and $\alpha$ is degree of hydration [-]. @@ -5253,7 +6470,9 @@ \subsection{Nonlinear isotropic material for moisture transport -- NlIsoMoisture \item {\bf Linear} isotherm ($isothermType=0$) is characterized only by its -slope given by parameter $moistureCapacity$. +slope given by parameter \emph{capa}. The isotherm can be +shifted vertically, this is done by \emph{isooffset} which has a +meaning of moisture content at zero relative humidity. \item {\bf Piecewise linear} isotherm ($isothermType=1$) is defined by two @@ -5310,7 +6529,18 @@ \subsection{Nonlinear isotropic material for moisture transport -- NlIsoMoisture be found in \cite{Xi}. Note that these formulae hold quite accurately for cement paste only; a reduction of the moisture ratio is necessary if the isotherm -should be applied for concrete. +should be applied for concrete. + +\item +{\bf Bilinear} isotherm ($isothermType=6$) is defined by its +moisture capacity \emph{capa} for relative humidity less than +\emph{hx}. Parameter \emph{wf} defines moisture content at full +saturation, $h = 1$. Convergence is substantially improved by a smooth transition on +interval $(hx-dx, hx+dx)$. +Similarly to the linear isotherm the moisture content can be +adjusted by parameter \emph{isooffset}. + + \end{enumerate} The present implementation covers three functions for @@ -5367,6 +6597,7 @@ \subsection{Nonlinear isotropic material for moisture transport -- NlIsoMoisture \optelemparam{dd}{rn} \optelemparam{wf}{rn} \optelemparam{b}{rn} \optelemparam{uh}{rn} \optelemparam{A}{rn} \optelemparam{nn}{rn} \optelemparam{c}{rn} \optelemparam{k}{rn} \optelemparam{Vm}{rn} +\optelemparam{hx}{rn} \optelemparam{dx}{rn} \optelemparam{perm\_h}{ra} \optelemparam{perm\_c(h)}{ra} \optelemparam{c1}{rn} \optelemparam{n}{rn} \optelemparam{alpha0}{rn} \optelemparam{hc}{rn} \optelemparam{alphah}{rn} @@ -5375,18 +6606,21 @@ \subsection{Nonlinear isotropic material for moisture transport -- NlIsoMoisture \\ Parameters &- \param{num} material model number \\ &- \param{d} material density \\ -&- \param{isothermType} isotherm function as listed above (0, 1, ...5) +&- \param{isothermType} isotherm function as listed above (0, 1, ...6) \\ &- \param{permeabilityType} moisture permeability function as listed above (0, 1, 2) \\ &- \param{rhodry} [kg/m$^3$] density of dry material (for $isothermType=4$ and 5) \\ -&- \param{capa} [kg/m$^3$] moisture capacity (for $isothermType=0$) \\ +&- \param{capa} [kg/m$^3$] moisture capacity (for $isothermType=0$ and +6) \\ +&- \param{isooffset} [kg/m$^3$] moisture capacity at zero relative +humidity (for $isothermType=0$ and 6) \\ &- \param{iso\_h} [-] humidity array (for $isothermType=1$) \\ &- \param{iso\_w(h)} [kg/m$^3$] moisture content array (for $isothermType=1$) \\ &- \param{dd} [-] parameter (for $isothermType=2$)\\ &- \param{wf} [kg/m$^3$] is the moisture content at free saturation -(for $isothermType=3$) \\ +(for $isothermType=3$ and 6) \\ &- \param{b} [-] parameter (for $isothermType=3$) \\ &- \param{uh} [kg/kg] maximum hygroscopically bound water by adsorption (for $isothermType=4$) \\ @@ -5395,7 +6629,8 @@ \subsection{Nonlinear isotropic material for moisture transport -- NlIsoMoisture &- \param{Vm} (for $isothermType=5$) \\ &- \param{k} (for $isothermType=5$) \\ &- \param{C} (for $isothermType=5$) \\ -&- \param{perm\_h} [-] humidity array (for $permeabilityType=0$) \\ +&- \param{hx} [-] transition relative humidity (for $isothermType=6$) \\ +&- \param{dx} [-] length of the smooth transition (for $isothermType=6$) \\ &- \param{perm\_c(h)} [kg m$^{-1}$ s$^{-1}$] moisture permeability array (for $permeabilityType=0$) \\ &- \param{c1} [kg m$^{-1}$ s$^{-1}$] moisture permeability at full @@ -6031,514 +7266,8 @@ \subsection{FE\textsuperscript{2} fluid - FE2FluidMaterial} \clearpage -\section{Material Drivers - Theory \& Application} -The purpose of this section is to present the theoretical backgroung -of some handy general purpose algorithms, that are provided in oofem in the -form of general material base classes. They can significantly -facilitate the implementation of particular material models that are -based on such concepts. Typical example can be a general purpose -plasticity class, that implements general stress return and stifness -matrix evaluation algorithms, based on provided methods for computing -yield functions and corresponding derivatives. Particular -models are simply derived from the base classes, inheriting -common algorithms. - - - -\subsection{Multisurface plasticity driver - MPlasticMaterial class} - -In this section, a general multisurface plasticity theory with -hardening/softening is reviewed. The presented algorithms are -implemented in MPlasticMaterial class. - -\subsubsection{Plasticity overview} -Let $\mbf{\sigma},\e, {\rm and}\ \ep$ be the stress, total strain, and plastic strain vectors, respectively. -It is assumed that the total strain is decomposed into reversible elastic and irreversible plastic parts -\begin{equation} - \e = \e^e + \ep -\end{equation} -The elastic response is characterized in terms of elastic constitutive matrix $\mbf{D}$ as -\begin{equation} -\label{el1} -\mbf{\sigma}=\mbf{D}\e^e = \mbf{D}(\mbf{\varepsilon}-\ep) -\end{equation} -As long as the stress remains inside the elastic domain, the deformation process is purely elastic and the plastic strain does not change. -It is assumed that the elastic domain, denoted as $IE$ is bounded by a composite yield surface. It is defined as -\begin{equation} -IE=\{(\mbf{\sigma},\mbf{\kappa})|f_i(\mbf{\sigma},\mbf{\kappa})<0, \rm{for\ all\ }i\in\{1,\cdots,m\}\} -\end{equation} -where $f_i(\mbf{\sigma},\mbf{\kappa})$ are $m\ge1$ yield functions intersecting in a possibly non-smooth fashion. The -vector $\mbf{\kappa}$ contains internal variables controlling the evolution of yield surfaces (amount of hardening or softening). -The evolution of plastic strain $\ep$ is expressed in Koiter's form. Assuming the non-associated plasticity, this reads -\begin{equation} -\label{epe} -\epd=\sum^{m}_{i=1} \lambda^i \partial_{\mbf{\sigma}}g_i(\mbf{\sigma},\mbf{\kappa}) -\end{equation} -where $g_i$ are plastic potential functions. The $\lambda^i$ are referred as plastic consistency parameters, which satisfy the following Kuhn-Tucker conditions -\begin{equation} -\label{ktc} -\lambda^i\ge0,\;f_i\le0,\;{\rm and}\ \lambda^i f_i=0 -\end{equation} -These conditions imply that in the elastic regime the yield function must remain negative and the rate of the plastic multiplier is zero (plastic strain remains constant) while in the plastic regime the yield function must be equal to zero (stress remains on the surface) and the rate of the plastic multiplier is positive. -The evolution of vector of internal hardening/softening variables $\mbf{\kappa}$ is expressed in terms of a general -hardening/softening law of the form -\begin{equation} -\dot{\mbf{\kappa}} = \dot{\mbf{\kappa}}(\sig, \mbf{\lambda}) -\end{equation} -where $\mbf{\lambda}$ is the vector of plastic consistency parameters $\lambda_i$. - - - -\subsubsection{Closest-point return algorithm} -Let us assume, that at time $t_n$ the total and plastic strain vectors and internal variables are known -$$ -\{\mbf{\varepsilon}_n, \mbf{\varepsilon}^p_n, \mbf{\kappa}_n\}\ {\rm given\ at}\ t_n -$$ -By applying an implicit backward Euler difference scheme to the evolution equations (\ref{el1} and \ref{epe}) -and making use of the initial conditions the following discrete non-linear system is obtained -\begin{eqnarray} -\e_{n+1}&=&\e_n+\Delta\e\\ -\label{del} -\sig_{n+1}&=&\mbf{D}(\e_{n+1}-\ep_{n+1})\\ -\label{dep} -\ep_{n+1}&=&\ep_{n}+\sum\lambda^i\partial_{\sig} g_i(\sig_{n+1}, \mbf{\kappa}_{n+1}) -\end{eqnarray} -In addition, the discrete counterpart of the Kuhn-Tucker conditions becomes -\begin{eqnarray} -\label{dktc} -f_i(\sig_{n+1}, \mbf{\kappa}_{n+1}) &=& 0\\ -\lambda^i_{n+1} &\ge& 0\\ -\lambda^i_{n+1} f_i(\sig_{n+1}, \mbf{\kappa}_{n+1})&=& 0 -\end{eqnarray} -In the standard displacement-based finite element analysis, the strain evolution is determined by the displacement increments computed on the structural level. The basic task on the level of a material point is to evaluate the stress evolution generated by strain history. -According to this, the strain driven algorithm is assumed, i.e. that the total strain $\e_{n+1}$ is given. -Then, the Kuhn-Tucker conditions determine whether a constraint is active. The set of active constraints is denoted as $J_{act}$ and is defined as -\begin{equation} -J_{act}=\{\beta\in\{1,\cdots,m\}|f_\beta=0\ \&\ \dot{f}_\beta=0\} -\end{equation} -Let's start with the definition of the residual of plastic flow -\begin{equation} -\label{rpf} -\mbf{R}_{n+1}=-\ep_{n+1}+\ep_{n}+\sum_{j\in J_{act}}\lambda^j_{n+1}\partial_\sigma g_{n+1} -\end{equation} -By noting that total strain $\e_{n+1}$ is fixed during the increment we can express the plastic strain increment using (\ref{el1}) as -\begin{equation} -\Delta\ep_{n+1} = -\mbf{D}\Delta\sig_{n+1} -\end{equation} -The linearization of the plastic flow residual (\ref{rpf}) yields\footnote{For brevity, the simplified notation is introduced: $f=f(\sig,\mbf{\kappa}),\ g=g(\sig,\ \mbf{\kappa}),\ \mbf{\kappa}=\mbf{\kappa}(\sig,\lambda)$, and subscript $n+1$ is omitted.} -\begin{eqnarray} -\nonumber -&&\mbf{R}+\mbf{D}^{-1}\Delta\sig+\sum\lambda\partial_{\sigma\sigma}g\Delta\sig+\\ -&&+\sum\lambda\partial_{\sigma\kappa}g\cdot(\partial_\sigma\kappa\Delta\sig+\partial_\lambda\kappa\Delta\lambda)+\sum\Delta\lambda\partial_{\sigma}g =0 -\end{eqnarray} -From the previous equation, the stress increment $\Delta\sig$ can be expressed as -\begin{equation} -\label{dsig} -\Delta\sig=-\mbf{H}^{-1}\left(\mbf{R}+\sum\Delta\lambda\partial_{\sigma}g+\sum\lambda\partial_{\sigma\kappa}g\partial_{\lambda}\kappa\Delta\lambda\right) -\end{equation} -where $\mbf{H}$ is algorithmic moduli defined as -\begin{equation} -\mbf{H}=\left[\mbf{D}^{-1}+\sum\lambda\partial_{\sigma\sigma}g+\sum\lambda\partial_{\sigma\kappa}g\partial_{\sigma}\kappa\right] -\end{equation} -Differentiation of active discrete consistency conditions (\ref{dktc}) yields -\begin{equation} -\label{ddyc} -\mbf{f}+\partial_{\sigma}\mbf{f}\Delta\sig+\partial_{\kappa}\mbf{f} (\partial_\sigma\kappa\Delta\sig+\partial_\lambda\kappa\Delta\lambda) =0 -\end{equation} -Finally, by combining equations (\ref{dsig}) and (\ref{ddyc}), one can obtain expression for incremental vector of consistency parameters $\Delta\mbf{\lambda}$ -\begin{equation} -\left[\mbf{V}^T\mbf{H}^{-1}\mbf{U}-\partial_{\kappa}\mbf{f}\partial_{\lambda}\mbf{\kappa}\right]\Delta\mbf{\lambda}=\mbf{f}-\mbf{V}^T\mbf{H}^{-1}\mbf{R} -\end{equation} -where the matrices $\mbf{U}$ and $\mbf{V}$ are defined as -\begin{eqnarray} -\mbf{U} &=& \left[\partial_{\sigma}\mbf{g}+\sum\lambda\partial_{\sigma\kappa}g\partial_{\lambda}\kappa\right]\\ -\mbf{V} &=& \left[\partial_{\sigma}\mbf{f}+\partial_{\kappa}\mbf{f}\partial_{\sigma}\kappa\right] -\end{eqnarray} - -Before presenting the final return mapping algorithm, the algorithm for determination of the active constrains should be discussed. A yield surface $f_{i,n+1}$ is active if $\lambda^i_{n+1} > 0$. A systematic enforcement of the discrete Kuhn-Tucker condition (\ref{dktc}), which relies on the solution of return mapping algorithm, then serves as the basis for determining the active constraints. The starting point in enforcing (\ref{dktc}) is to define the trial set -\begin{equation} - J^{trial}_{act}=\{j\in\{1,\cdots,m\}|f^{trial}_{j,n+1} > 0\} -\end{equation} -where $J_{act}\subseteq J_{act}^{trial}$. Two different procedures can be adopted to determine the final set $J_{act}$. The conceptual procedure is as follows -\begin{itemize} - \item - Solve the closest point projection with $J_{act}=J_{act}^{trial}$ to obtain final stresses, along with $\lambda^i_{n+1},\ i\in J_{act}^{trial}$. -\item -Check the sign of $\lambda^i_{n+1}$. If $\lambda^i_{n+1} <0$, for some $i\in J_{act}^{trial}$, drop the $i-$th constrain from the active set and goto first point. Otherwise exit. -\end{itemize} - -In the procedure 2, the working set $J_{act}^{trial}$ is allowed to change within the iteration process, as follows -\begin{itemize} -\item -Let $J_{act}^{(k)}$ be the working set at the k-th iteration. Compute increments $\Delta\lambda^{i,(k)}_{n+1},\ i\in J_{act}^{(k)}$. -\item -Update and check the signs of $\Delta\lambda^{i,(k)}_{n+1}$. If $\Delta\lambda^{i,(k)}_{n+1} < 0$, drop the i-th constrain from the active set $J_{act}^{(k)}$ and restart the iteration. Otherwise continue with next iteration. -\end{itemize} -If the consistency parameters $\Delta\lambda^{i}$ can be shown to increase monotonically within the return mapping algorithm, the the latter procedure is preferred since it leads to more efficient computer implementation. - -The overall algorithm is convergent, first order accurate and unconditionally stable. -The general algorithm is summarized in Tab.~\ref{closespointalgo}. - -\begin{table} -\label{closespointalgo} -{\small -\begin{enumerate} -\item - Elastic predictor - - \begin{enumerate} - \item - Compute Elastic predictor (assume frozen plastic flow)\\ - $\sig^{trial}_{n+1} = \mbf{D}\left(\e_{n+1}-\ep_{n}\right)$\\ - $f^{trial}_{i,n+1}=f_i(\sig^{trial}_{n+1},\kap_{n}),\ \rm{for}\ i\in\{1,\cdots,m\}$ - \item - Check for plastic processes - IF $f^{trial}_{i,n+1}\le 0$ for all $i\in\{1,\cdots,m\}$ THEN: - \begin{itemize} -\item[] - Trial state is the final state, EXIT. - \end{itemize} - ELSE: - \begin{itemize} - \item[] -$J^{(0)}_{act}=\{i\in\{1,\cdots,m\}|f^{trial}_{i,n+1} > 0\}$ - \item[] -$\e^{p(0)}_{n+1}=\ep_n,\ \kap^{(0)}_{n+1}=\kap_n,\ \lambda^{i(0)}_{n+1}=0$ - \end{itemize} - ENDIF -\end{enumerate} - -\item - Plastic Corrector - \begin{enumerate} - \item[(c)] - Evaluate plastic strain residual - \begin{itemize} - \item[] -$\sig^{(k)}_{n+1} = \mbf{D}\left(\e_{n+1}-\e^{p(k)}_{n+1}\right)$ - \item[] -$\mbf{R}^{(k)}_{n+1}=-\e^{p(k)}_{n+1}+\ep_n+\sum\lambda^{i(k)}_{n+1}\partial_{\sigma}g_i$ - \end{itemize} - \item[(d)] - Check convergence - \begin{itemize} - \item[] -$f^{(k)}_{i,n+1}=f_i(\sig^{(k)}_{n+1},\kap^{(k)}_{n+1})$ - \item[] -if $f^{(k)}_{i,n+1} < TOL$, for all $i\in J^{(k)}_{act}$ and $\Vert\mbf{R}^{(k)}_{n+1}\Vert + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + +   +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/matlibmanual/trilinear_diagram_sigmaVSw_and_sigmaVSepsilon.eps b/doc/matlibmanual/trilinear_diagram_sigmaVSw_and_sigmaVSepsilon.eps new file mode 100644 index 000000000..8d290224c --- /dev/null +++ b/doc/matlibmanual/trilinear_diagram_sigmaVSw_and_sigmaVSepsilon.eps @@ -0,0 +1,1838 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: cairo 1.16.0 (https://cairographics.org) +%%CreationDate: Thu Apr 28 09:53:40 2022 +%%Pages: 1 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%BoundingBox: 1 1 442 160 +%%EndComments +%%BeginProlog +50 dict begin +/q { gsave } bind def +/Q { grestore } bind def +/cm { 6 array astore concat } bind def +/w { setlinewidth } bind def +/J { setlinecap } bind def +/j { setlinejoin } bind def +/M { setmiterlimit } bind def +/d { setdash } bind def +/m { moveto } bind def +/l { lineto } bind def +/c { curveto } bind def +/h { closepath } bind def +/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto + 0 exch rlineto 0 rlineto closepath } bind def +/S { stroke } bind def +/f { fill } bind def +/f* { eofill } bind def +/n { newpath } bind def +/W { clip } bind def +/W* { eoclip } bind def +/BT { } bind def +/ET { } bind def +/BDC { mark 3 1 roll /BDC pdfmark } bind def +/EMC { mark /EMC pdfmark } bind def +/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def +/Tj { show currentpoint cairo_store_point } bind def +/TJ { + { + dup + type /stringtype eq + { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse + } forall + currentpoint cairo_store_point +} bind def +/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore + cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def +/Tf { pop /cairo_font exch def /cairo_font_matrix where + { pop cairo_selectfont } if } bind def +/Td { matrix translate cairo_font_matrix matrix concatmatrix dup + /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point + /cairo_font where { pop cairo_selectfont } if } bind def +/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def + cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def +/g { setgray } bind def +/rg { setrgbcolor } bind def +/d1 { setcachedevice } bind def +/cairo_data_source { + CairoDataIndex CairoData length lt + { CairoData CairoDataIndex get /CairoDataIndex CairoDataIndex 1 add def } + { () } ifelse +} def +/cairo_flush_ascii85_file { cairo_ascii85_file status { cairo_ascii85_file flushfile } if } def +/cairo_image { image cairo_flush_ascii85_file } def +/cairo_imagemask { imagemask cairo_flush_ascii85_file } def +%%EndProlog +%%BeginSetup +%%BeginResource: font CMMI9 +%!PS-AdobeFont-1.0: CMMI9 003.002 +%%Title: CMMI9 +%Version: 003.002 +%%CreationDate: Mon Jul 13 16:17:00 2009 +%%Creator: David M. Jones +%Copyright: Copyright (c) 1997, 2009 American Mathematical Society +%Copyright: (), with Reserved Font Name CMMI9. +% This Font Software is licensed under the SIL Open Font License, Version 1.1. +% This license is in the accompanying file OFL.txt, and is also +% available with a FAQ at: http://scripts.sil.org/OFL. +%%EndComments + +11 dict begin +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def +/FontName /f-0-0 def +/FontBBox {-29 -250 1075 750 }readonly def +/PaintType 0 def +/FontInfo 10 dict dup begin +/version (003.002) readonly def +/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMMI9.) readonly def +/FullName (CMMI9) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.04 def +/isFixedPitch false def +/UnderlinePosition -100 def +/UnderlineThickness 50 def +/ascent 750 def +end readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 119 /w put +readonly def +currentdict end +currentfile eexec +f983ef0097ece61cf3a79690d73bfb4b0027b6f3b53cc32be64063d04d328b49c17a62c396cfc8 +17b9fcb732c3b0aeb6264b2a70f62fbfc397eea8d069af80a71b775145f9842057f969d124e630 +1a760710a5c51e8981851fbcf7f1cd1f2ab78db91af2a6f264e41cc2cdecf450a3a33c89fa447b +8bad4068cb8d7d37adaa4caab8f72cc26b024348ef8708a0ab6ee56d73f035ac9b506c91fcafc2 +40791cc10b1b0ca42c87a24a69e83f61a20432744f7d79437b93825d955cee80718831f56e0254 +0ae4b3a70b9dda35ca4fbcabfbc50a4cafca7423203cf03b8e9eafb091f06b2741ada33c61933f +a93b918174bf191acc4bd38d2bc95e7bb73103fd5838d75247e2b33a3bc77eec278208e4bd14db +2f430c39cd62a368ee42809bb9c7cc4816d5a73146e7d17c2db11b1ddf51497c91003027a94cda +684a216760721d77ff42856913226acb19f9c2e1ae9ce63650bf83c2f1132ae45491e3e8859c3c +f7358adbeeb1cb4948c127d660bb5d4a13d3d89eb9491421b63117e506912bbceb08d5b2f853b1 +a271e0d553a86049a49391c070cf0d658cc0ca177fc5d83bb16aff073413f7ae681463ebfc92a6 +4a30f90186c1e380ebd3e425b8c3a204236c2c814986be03c35dd47f8f58e0ab9d4d6ca3bc19a5 +ac3b9f542a0ff1ee219992dfaadf75ef6122014fe42945d19cca9903279566066824b1d077ec74 +5c79a7623990b87fab105493be3eaf86dab672f42b8d1119282e3a4245233936eacdc2ebcc9302 +06a865a4caec1b8efc9e0e4bc99701981e4ede3d062a505cd1a3b77056acf49371517dd3d0007f +8ecfe0ed6ffe8cc09208f3e43bcb9d8f8c0b13d1b92da827ad833b95519a71e8c7e6fefc6703f1 +1566bd657341982c027ebd84e72b8e52fb6f4b8064b8ae596aee8102ae30ae4f671a39705cadca +2e7df6142e7ce0bc2258f076a4c31b712e52be313c9282b38e9b1c137fed216e22d27f45841842 +57b6bfb7b6117d7c490c87291c1be54e7149af65f472e8d444aeee77f25e5c3aebe146b9627bd1 +6e19f9c28f26246ee5fec562478fe417f0e09601b0cce040a95c1d288b07b35b12562e6be85e76 +2b122cf74ee630f39620a509e143f76415606e1d26cf6d7335e3ff00db2fbaf368b45d4b2f2784 +d209325cb794f1bacd0afb654f262cbf73404c650eb2bbe0677f7aaa3e541f03bcf854c69526fa +2064e4922949988a1865c5b849eb5a3e1a55bfda46e01828e7fb640b8b66de44e7b338b8ab8090 +8253dcb3e38eba52dc0104f99bd2e361b8e55107f8ade2241455e3939123c47de5287d02b855b9 +24fe084ae967c60b4a664e02297b56d48da883a604d382c879c1f00f058a5848c7d64b023bcf9d +1279f8d51edeb31494a79fef8c4d3d8fadb0967e73fbc87adcf14b0b905aea53c7e43336523d95 +0f85f6f48d24d2eae659c7b62ba3411c6f4aa3148d840e11fe61dea471ffe3bff12b2da4e0385d +cc9d1cff6f7a467369e5636453b2009df45732742c8d658c1b68e0ccec40a713ddc8676c90ed43 +0300a298883a7e13385589d0e8538b0b4b1df04ec77642b471d42d916179672a8049747dfe0041 +a2e569b41f91449d6e956a70156472db8d4d3a76932271fd1aba0c2c282e5a2a770d0a753a9f34 +3b7e11a8a7483eae30adc08f9b958f1a99b9da9154ee37c0a38945a4a244763749b8973c93be26 +f07fb4c2ed1500af8f4d6d8598d6bce547885af33f89b16306f07871ebb62d0681e00cba68f7d9 +e12789c4ea613ebe8be47fa38b4c9b3b8a1fd4550cbc66e18b15bb824d95a30f0a893a96549288 +9f7732a0717b8857e952b629152c5bca6d8648114f5be9ccb4a890d2a754294c18f5fa660f93fc +7361962901b6d42ef66aa10b3c22413a7c5a8e369328099e731ff22eeb7755974032602c379b91 +42a60e9d977844b97359c3f7783ebda220d4770e7901eba89a6c92bff4c07a6fad401af8ce2be7 +0240805cb9b50ce7abc5792cee342f8a3ab8b338ab3d104579f42f69c9ec2f6e26d654ad085b3e +a8a96527c59d90127d484ab692a7ede7e61625d8481b5713052bb8276c7ab4721f69c783dfacb3 +ba4d85a2b9a8271a979f3c445ae51a57939b80c24fe0c9e629cdf1d7a5d17072363b9392d86712 +89a50288bc609c1a5698566722fcf4111311c5d7232e590168496eca028852e0afbbd874dd4434 +d2f47ffa60af39d15514916a00e72d68ad9e29bcf6921af00193faa58435e11fd3729c08c94bc6 +6afc2fb5be106cb570e9e9341a69aff1903bfbfaf4a9f66dc28b4ee2b204b6ea3674ae61f3039c +ce8bffe374cbbef99fa56f979d4d252b2a147039db71534ce7c34d618b3a05c38a793b16029822 +b425b2629c40a7c00cbd372baee0f40dbe017c0befd52b92e10b188a68e98c134613777a527030 +d6c77726cf4ee575943c120ab252dcc9d3b56b32f32802814a050637dc7663459e0c6574eeac62 +89c82e945373f6d547d6f6c88119a726f678bd70878bc863c6991e7248ca4c3e21feae72b85268 +d0bfdb5a777598ccead86d7859a2c209e22fa37441c7aeb5e234ff5427a4aae538d00b5e3e7932 +64463522d62fe33967ab354c6dd228acee707bc9e5a292911e9ebaef5d5bb3383e5867420b8097 +50d53ce3d4cda25a9b08f8c4d51e635f95232b4389f9cb33c1c5978521a79bff9938743c40fbdd +39b9780c473c3d167b5d6164b48bfcb84635749571402abdfbaede69d1f35a48e3a2589713580b +b99f5e722d20b1fa0a00d07e0d3538eb6a758f6e378412d1f4d0c03951c1eeae998b4222917a29 +e07532fc331762650d67089090c0fa1bcc67ee8a5ac478cb555fd896ce46814aa2210c6e360dc3 +9c504fd008424c36d79fc9949c747685607e04ebb038222715aa4de1f94dba83cd656483676e79 +407c050ac41f2530eb8c02cf079610533f7374393c93b8654178c55c713677ba85be23ef60afed +1b936318e3c62afcfc0be3ee2218a8f14ecabef4487912bd772106d25c9a604342032513147e8b +a0b2d324bdd50f560c6f0dede799d4139bb6f97d1e49e344687352065ab7b2e5e4ff4b31170af5 +2646d8e331b130e73aee4634943fb9a48bb25e9542f50506deadfded1c223f415f352fcc5ed95d +3aa6668e13f53b9e0fea41e82cd9fb3c403c31671a28bd9c2bc85c0e8a8d07cfd5c48822c1eecc +3ad9e5a52b23f69058a25a943fb457457a2a6cfe0ebb7c66e559ed04f5ebf468494c7b08f63d4d +9706ca349daa58cc4717185791e32ac48fd90bffcfad8928f5ada49c15c4bee155e133075ee1c2 +54da675dfca746f15789b42aa05650e9b4055d5ab9bbb28aca90cb6d71e1ce00f37029b78c5ce7 +8d1058e089a2ddc5ae8dd9a8b56ebe265377fefe8bbd8c346c6d65144386a33769f262820fc683 +dad25d756fe9aebeec19ae9663d67146aced91a537ef2b97be979c35f0be5454e967c60b4a223c +8a7a03521dd91b36a06a4d669745d20967ee03099ecb492bfc0d231fc042a3b1830ccb649e8e9a +2765047d7c25da0256feddb9d1e853b276ba2185a03e4c9996a2944ef0e3f5c38833e4332bcc01 +3cb8196eceeb9483a063480d2afbd3109343daec4d39c92cdac3e5de96059c6b3517127230585e +ebe267d92e5af63b86f505ddc1dd25045f4bdbefed2bce82c48e44f60ae1fa84e9e2f15642fbbb +7931db3380ad672f27e2519057b90c993592cb6bfa4501c5afe2f5f5077c2b1e14a05c376c3c62 +c62fe4ac1453a64ac0803bd23b528ae50e87b556c0ed4785e95ad61fdfd42053b6f1d2acf1c97d +26d5d8c42383df77b31873feb221bcade2d1c40fd1774c9e296eba6aed78e0ea90eebe0d607684 +9dc47cf92e6a29bab612092f55c928396c73e73c4cab18da8f8f98de2ec6e10516e547383dc53e +30d84c5f659ebdf14661a6b085e581e22ab6bf28fd9cccecf78871a055dac7c42dd10533d3826b +ca9a970c22bcafa59905363efd2de90a1cf53eb976c987aef00ae156843b44f6fb0765e20d9e41 +61751a2e5630ab7c5f92e937ddc8609dfb936c41743c9fe47f53152637d72e4005b05e973aff37 +76f6f996cbe9d6e3cceda0056b39c12d6e1de81e77c15ad82d7056a33bc184f7828080835d92ad +95815f5602dba1125caca06d51bacda8cb48f5277ffcb8c2c3e729dfe31e1e75ea007c9436393b +2ae94e8656cc3fa20e3434416a90ef1eb8ef1d35083b119d2838122dcb9f2f1954f342199f062f +d7ed2cb113620524c738d0c3967d9e62506553a6bdb1ceed3d3e663625e2d9155059479b6d9da8 +dc51af126f408825b1d0509b78e70f5a74b7758198ebd23edaa049383333d07377879331b6c7ba +b531eaddcf143de7e460f473ffa7dfde25e6694ee818107bf0ffbd1fe7c5a88883bf860826239d +672dd8fec3b215d77ed7561c04a40c2e0584af51fb49202f42bdfc0c7e7cf111614e97f8ea090d +431fb8a4db2b4487af472b3c131e5250567fb80f08b1183b2390ab9c4dda5954aa66f622e45dfa +ba2ee237d059f0e57383cc4a2543cb50132c76e88f110c3738d91d7081ae2328a9c02e1daf6dd9 +b325d6b0255087948aa06578b2b3b7cbdc636ee8c93ec43c2f7853780f0c86c52bab0879a09f08 +c544e20e264f18ca60f3086300c3fe76dc7d640fc2d6a57ff36049d7d5e554493a02c57000d573 +678f6cd785c5755678618c5762a29af4d14031d07385054f7fb705b9996a38b04069e44b625ef1 +c754ea1c8c246df0f89880366511e9b5eef6003565c5e54a307cec3b95441038ea4c1086cb5553 +787edcb032832bb8490f4468cfa830bbca5d3cdf457a01cc6f845aebfa2b69625b9e4ab3140d05 +9b710736bbb9a4a77064ae0f1a47d58055fdd64042bfab34d3862edbdb96af196294bf154af1f3 +edc574bccea8e44b10f12067924fccfda8bf501595af1901b5082a9b52619f9f3ff8fe3a499f47 +1b3b8de98d6681d519b48d131beecb9984350340d130c8f8f5468ca13747667198d758e8413658 +8032718a0fd1b4b8eb191934d62b6ea14ea120b74faa1fc6adf20853c17970a97684f96a4897d5 +edef58154272a66123c9aa721b9c70fbe3c134ede9fe0d128aa0521fbd7963f40aa0e6e1cc9974 +e02b7de6bb087b8434322dd53f18e8930ca106283ce3b593764b5cf2477f723d21ba958a47103f +fcfd7bc117046af3b1d0b1428ccb514c9b99ec34bd96b3358015338797eb6e03973eb3b4922877 +de3a368fe43bcf0033627cee8f72893d420f70f4db14b1513957c292324c8e4e95ac03f93763e2 +875e31e020db857f4e984740972fabdb8294621cf8eb5f9c7c639ffbc5ace82b7081d2d6762a37 +666a83b86d662deb21ea6f55dcc06e284bb9b37288582a04493dc28c7e972304cffc57c91c3e67 +ef874e130e8474068950290d76cfbc454eb781e7c4b43ab4cc7773c02218b0eefc777e18e5d572 +f9d2658abd199963766f9962f0a7086c600be688f81c74cccafedd3f2bb8da0a25562b7105aa00 +d1e54efe181c3735b98c8c8b242669fc34ead710180d4c1bb0c6c4f8f3b46b5933d761f0ffb3d1 +2f7eb08716daa08f91bed4b2f9b051bc110441398288df6d77f92a960ce10f87dc4b17dbec658c +d7ebaafdbcca8ac892b5cb13ab0f9cb0d614dca46c1488206e2e01716fe1e1ff2244ef661f1c89 +ee81f63c7d33f695cbad711e97546e0581136d7dd2e4739fe9deabd38d0e3e9d65a65f02fd6b63 +27de043fcd2e1ab5428ba965290c38d5b1f8dc8d3dc696ad5111466e2b1984c65515efddd0d6b5 +db9f005a49e22f7de9f51b661894774d75cf9245fecdb059c17bfc0fa0668ba65c1107eaba293e +edeeada10c357cae7899a9a99eba84aeac6c240e44184800c7e45ba664fe0f5a668fe3361910af +decb7fa18b734aae22fab0056fb2a33443511cb5ff656d39b81f2d910cefe1fe810788b0d22917 +f0e9e3e0c3643d9afe9e024930c60e82ffc57ebac73a19815ea18f0778057df290d36709f9b4d9 +61448358a00de19b03735f91aba3e1abfc4f33cfbc23affb383ee34c6db6dc7a42052b65ba3e1a +e70e2917c9770c8894f901f233e46258e0d7b6674f09a4be5475913e6c1ae8393c31420c8db6d4 +37dc21ea5d3f4b829d468aee35a64cea600741cb8eb33eb84b21c5b5729abe6c0c24a63b4c0c37 +e94009f297f3e90391abf606cf97a1bb2624249c82b1e44911b59f6af21e9849a838d506f97453 +918ba82af9efac44189889f940c23de954016f768d333de28a251f1c0976a0fce6edfe88ce3f08 +df163e65ca795b92d421e0c2554833c37c1ace4701e4b50f71d988d41163117ac6ab7bedd6ff76 +c98bcfed2089b6bca6ec51f30a08e86cfe5bc959adc815208c0d12ffaba6be51b6d4529800d4e8 +34c0d47594d39f8b291bf92f71fd11bb8305d76f337f64060a55d7b815282e690205e193db7c82 +2f26c3c21e61f5556838f66b9f20b681fc4a4421e972d8de8da05f8cef8473ca23dcd1b19a055e +de0850a815b15f832eedf033e8fc8fb886119e0b8c7303602be2bb0f127bf3794d4ef282182f90 +a4d224e887c10c5964f8c3d0a59f20c771d857d76580a8b8d9fd61702312268fed849be8d34409 +9f7d82764d2910d5bbec4283f58b65c7c9b9241418ca7ed4d6064ccd2ae5e1d3e207f9d27978d6 +838731d6ad5cfbe02dde68458f4bd395ef3fe8ea3562ca2bbc399fdd28d926d8e7444eb42de483 +024977d256fa5358635a384b00deb521206cd4eadbabf4a788500e5ccf7e49552d8a25d07fd538 +7c337d215d7e40953b3da41a67745a777ea80dfac235411775743da23e753b012ccae93f1fffce +847e0314401cba79d55f75c98a29e0d3ff4d544e7cf6f1618974b6bd381fbf8b98210a27661905 +48898f52a29fec8c986de8b8f126f7389aa56d16c6ae3e80a801655cb17a37d2ff4db06149088b +7c04a07cb12c83a1079e7f15044ad151e68783a5194ae2499ec22c52aa353540e0d05f00d66413 +e16e527d960e567fca68b3792dd0ea479a26f928553b86ee12e28aa4f1b54f6b499aa694e35251 +453f222fcf365e8eccccba4241d9d5b2472c25dac46abd3a7fb97f2051639b4f2b110fd6c35c7d +a872631d60d117c0401e8d456156f5a34b49897caf13b6b2e15f738cd834bec2fac48641da6cad +000c231a03575d37d2629f7a7232004619b9c3077d48e053d38c99dcff15d301000c435bd6adbe +51e775e0fa1f2bfa1ee723a6ee4ed849aedb8f7aa4129d8767d813a93db20f2328c2e1fe0aaa69 +6477bbdd001abf819e9280b0387db782e817862e6777e3fc41a5dc4817abf9a143d86fc1ae6d68 +2bba45e5d29cfd9da24cb952e4c547750a80d039582fc2d65e2138397055f117f1f4bcc7a9d017 +8afde548f90f68f0494a274b2da5a78728d82c8d5589c9a2b271a43b95a66f1d614aa3d9ed5cc1 +984237a253d217a476cc814cb1f4e83bc0edd3f09b1e71a1539fd2c1fa23cdd9d138152d5d7fd4 +121fb81f7f1a4aee9f632075cc83f5039ffcbaba5033f161e32031bb13db9937e88f7775bca514 +83151d210deb2cfc3830a410851d1c2bc5b0f65e3d2af142caf0551f3a7237a2a6490d22698928 +fe431a210362fed70cc4a86bb7546df3d53e38dbbc8223286e14cf241273a4d862abc724d4594b +43561612f93fedb24200e8d235cc696d54e9c7403705674f60bcbb12b9cfcdfb4f074463d15973 +a87dce08774416228694668941ee9b04b3adff2e6549467e812b5724a41a9eece891bea081c4ad +b53e3574b2a18d98923fd8d355f4c4f304331eac9f6756725dc24439e886c414897db9ae685746 +5775b037832811cd1c6bff4c4d76b783cf258e393c7ba99476f20419ecf751a04ecff3badae6ed +e996943dbd0a2eb45fe7328e735d3c99a3022483e6546e56021a40566de91910f2aaa8cdd72a7e +46709074a20e12752c52351676b60003101a3025175b14083cddb32b1a169556336f29d105f128 +2241dc2a34ca9cfbdba9cf1577a98432a85d18e04bc5411d262daea310a7de740a067be3b54a89 +d7c733395fd3d562c24acf24b8a4b704f002566d56133592179e525671c075dd53a5a8af3549d5 +7066db01f7746d4e2728c74bfb60d38c2aa551d33720eeb7ddc8c75b83b9627429f26f386e6c5f +9e67a5edfa4d3e03be5e5f3ccc38dbc5eac851e1eb7a8a08264e0bb9f48391dd498d4054e7c3f8 +dbd35ac3167429dac7aee3473ee0bd3401348f5496e56e39ec274dc1813f061062119c18e18ff8 +665791a55042068e73ef00cf85aed1fdae6a5d8aadc9d75d582827dae621d1a1cc1f4dfe512aff +08871b47536df90bfee9ea2197009cb8e5127c17a59a39fc22ede37e6fbe21bd391345eb15387e +9ed698813a003cd20d12bf292eaf5e2bc87c96aa4a169977c1b8c6950d4c7adc87b77a479c2498 +e2ee54f4f0da7755a2466c82a7f5192f47c5eb5c6fb424e265df70f26e145c6510eccc9b2f3db6 +a3a946c9285ecb9a45178bb872886b3a756991a8af120f8edf46a63ba5bc57573ebff906bfde56 +c5ddbc393689753681c3d79faecc9ff1498cdc1d57c5a20ccf +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark + +%%EndResource +%%BeginResource: font CMMI9 +%!PS-AdobeFont-1.0: CMMI9 003.002 +%%Title: CMMI9 +%Version: 003.002 +%%CreationDate: Mon Jul 13 16:17:00 2009 +%%Creator: David M. Jones +%Copyright: Copyright (c) 1997, 2009 American Mathematical Society +%Copyright: (), with Reserved Font Name CMMI9. +% This Font Software is licensed under the SIL Open Font License, Version 1.1. +% This license is in the accompanying file OFL.txt, and is also +% available with a FAQ at: http://scripts.sil.org/OFL. +%%EndComments + +11 dict begin +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def +/FontName /f-0-1 def +/FontBBox {-29 -250 1075 750 }readonly def +/PaintType 0 def +/FontInfo 10 dict dup begin +/version (003.002) readonly def +/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMMI9.) readonly def +/FullName (CMMI9) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.04 def +/isFixedPitch false def +/UnderlinePosition -100 def +/UnderlineThickness 50 def +/ascent 750 def +end readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 1 /sigma put +dup 2 /epsilon put +readonly def +currentdict end +currentfile eexec +f983ef0097ece61cf3a79690d73bfb4b0027b6f3b53cc32be64063d04d328b49c17a62c396cfc8 +17b9fcb732c3b0aeb6264b2a70f62fbfc397eea8d069af80a71b775145f9842057f969d124e630 +1a760710a5c51e8981851fbcf7f1cd1f2ab78db91af2a6f264e41cc2cdecf450a3a33c89fa447b +8bad4068cb8d7d37adaa4caab8f72cc26b024348ef8708a0ab6ee56d73f035ac9b506c91fcafc2 +40791cc10b1b0ca42c87a24a69e83f61a20432744f7d79437b93825d955cee80718831f56e0254 +0ae4b3a70b9dda35ca4fbcabfbc50a4cafca7423203cf03b8e9eafb091f06b2741ada33c61933f +a93b918174bf191acc4bd38d2bc95e7bb73103fd5838d75247e2b33a3bc77eec278208e4bd14db +2f430c39cd62a368ee42809bb9c7cc4816d5a73146e7d17c2db11b1ddf51497c91003027a94cda +684a216760721d77ff42856913226acb19f9c2e1ae9ce63650bf83c2f1132ae45491e3e8859c3c +f7358adbeeb1cb4948c127d660bb5d4a13d3d89eb9491421b63117e506912bbceb08d5b2f853b1 +a271e0d553a86049a49391c070cf0d658cc0ca177fc5d83bb16aff073413f7ae681463ebfc92a6 +4a30f90186c1e380ebd3e425b8c3a204236c2c814986be03c35dd47f8f58e0ab9d4d6ca3bc19a5 +ac3b9f542a0ff1ee219992dfaadf75ef6122014fe42945d19cca9903279566066824b1d077ec74 +5c79a7623990b87fab105493be3eaf86dab672f42b8d1119282e3a4245233936eacdc2ebcc9302 +06a865a4caec1b8efc9e0e4bc99701981e4ede3d062a505cd1a3b77056acf49371517dd3d0007f +8ecfe0ed6ffe8cc09208f3e43bcb9d8f8c0b13d1b92da827ad833b95519a71e8c7e6fefc6703f1 +1566bd657341982c027ebd84e72b8e52fb6f4b8064b8ae596aee8102ae30ae4f671a39705cadca +2e7df6142e7ce0bc2258f076a4c31b712e52be313c9282b38e9b1c137fed216e22d27f45841842 +57b6bfb7b6117d7c490c87291c1be54e7149af65f472e8d444aeee77f25e5c3aebe146b9627bd1 +6e19f9c28f26246ee5fec562478fe417f0e09601b0cce040a95c1d288b07b35b12562e6be85e76 +2b122cf74ee630f39620a509e143f76415606e1d26cf6d7335e3ff00db2fbaf368b45d4b2f2784 +d209325cb794f1bacd0afb654f262cbf73404c650eb2bbe0677f7aaa3e541f03bcf854c69526fa +2064e4922949988a1865c5b849eb5a3e1a55bfda46e01828e7fb640b8b66de44e7b338b8ab8090 +8253dcb3e38eba52dc0104f99bd2e361b8e55107f8ade2241455e3939123c47de5287d02b855b9 +24fe084ae967c60b4a664e02297b56d48da883a604d382c879c1f00f058a5848c7d64b023bcf9d +1279f8d51edeb31494a79fef8c4d3d8fadb0967e73fbc87adcf14b0b905aea53c7e43336523d95 +0f85f6f48d24d2eae659c7b62ba3411c6f4aa3148d840e11fe61dea471ffe3bff12b2da4e0385d +cc9d1cff6f7a467369e5636453b2009df45732742c8d658c1b68e0ccec40a713ddc8676c90ed43 +0300a298883a7e13385589d0e8538b0b4b1df04ec77642b471d42d916179672a8049747dfe0041 +a2e569b41f91449d6e956a70156472db8d4d3a76932271fd1aba0c2c282e5a2a770d0a753a9f34 +3b7e11a8a7483eae30adc08f9b958f1a99b9da9154ee37c0a38945a4a244763749b8973c93be26 +f07fb4c2ed1500af8f4d6d8598d6bce547885af33f89b16306f07871ebb62d0681e00cba68f7d9 +e12789c4ea613ebe8be47fa38b4c9b3b8a1fd4550cbc66e18b15bb824d95a30f0a893a96549288 +9f7732a0717b8857e952b629152c5bca6d8648114f5be9ccb4a890d2a754294c18f5fa660f93fc +7361962901b6d42ef66aa10b3c22413a7c5a8e369328099e731ff22eeb7755974032602c379b91 +42a60e9d977844b97359c3f7783ebda220d4770e7901eba89a6c92bff4c07a6fad401af8ce2be7 +0240805cb9b50ce7abc5792cee342f8a3ab8b338ab3d104579f42f69c9ec2f6e26d654ad085b3e +a8a96527c59d90127d484ab692a7ede7e61625d8481b5713052bb8276c7ab4721f69c783dfacb3 +ba4d85a2b9a8271a979f3c445ae51a57939b80c24fe0c9e629cdf1d7a5d17072363b9392d86712 +89a50288bc609c1a5698566722fcf4111311c5d7232e590168496eca028852e0afbbd874dd4434 +d2f47ffa60af39d15514916a00e72d68ad9e29bcf6921af00193faa58435e11fd3729c08c94bc6 +6afc2fb5be106cb570e9e9341a69aff1903bfbfaf4a9f66dc28b4ee2b204b6ea3674ae61f3039c +ce8bffe374cbbef99fa56f979d4d252b2a147039db71534ce7c34d618b3a05c38a793b16029822 +b425b2629c40a7c00cbd372baee0f40dbe017c0befd52b92e10b188a68e98c134613777a527030 +d6c77726cf4ee575943c120ab252dcc9d3b56b32f32802814a050637dc7663459e0c6574eeac62 +89c82e945373f6d547d6f6c88119a726f678bd70878bc863c6991e7248ca4c3e21feae72b85268 +d0bfdb5a777598ccead86d7859a2c209e22fa37441c7aeb5e234ff5427a4aae538d00b5e3e7932 +64463522d62fe33967ab354c6dd228acee707bc9e5a292911e9ebaef5d5bb3383e5867420b8097 +50d53ce3d4cda25a9b08f8c4d51e635f95232b4389f9cb33c1c5978521a79bff9938743c40fbdd +39b9780c473c3d167b5d6164b48bfcb84635749571402abdfbaede69d1f35a48e3a2589713580b +b99f5e722d20b1fa0a00d07e0d3538eb6a758f6e378412d1f4d0c03951c1eeae998b4222917a29 +e07532fc331762650d67089090c0fa1bcc67ee8a5ac478cb555fd896ce46814aa2210c6e360dc3 +9c504fd008424c36d79fc9949c747685607e04ebb038222715aa4de1f94dba83cd656483676e79 +407c050ac41f2530eb8c02cf079610533f7374393c93b8654178c55c713677ba85be23ef60afed +1b936318e3c62afcfc0be3ee2218a8f14ecabef4487912bd772106d25c9a604342032513147e8b +a0b2d324bdd50f560c6f0dede799d4139bb6f97d1e49e344687352065ab7b2e5e4ff4b31170af5 +2646d8e331b130e73aee4634943fb9a48bb25e9542f50506deadfded1c223f415f352fcc5ed95d +3aa6668e13f53b9e0fea41e82cd9fb3c403c31671a28bd9c2bc85c0e8a8d07cfd5c48822c1eecc +3ad9e5a52b23f69058a25a943fb457457a2a6cfe0ebb7c66e559ed04f5ebf468494c7b08f63d4d +9706ca349daa58cc4717185791e32ac48fd90bffcfad8928f5ada49c15c4bee155e133075ee1c2 +54da675dfca746f15789b42aa05650e9b4055d5ab9bbb28aca90cb6d71e1ce00f37029b78c5ce7 +8d1058e089a2ddc5ae8dd9a8b56ebe265377fefe8bbd8c346c6d65144386a33769f262820fc683 +dad25d756fe9aebeec19ae9663d67146aced91a537ef2b97be979c35f0be5454e967c60b4a223c +8a7a03521dd91b36a06a4d669745d20967ee03099ecb492bfc0d231fc042a3b1830ccb649e8e9a +2765047d7c25da0256feddb9d1e853b276ba2185a03e4c9996a2944ef0e3f5c38833e4332bcc01 +3cb8196eceeb9483a063480d2afbd3109343daec4d39c92cdac3e5de96059c6b3517127230585e +ebe267d92e5af63b86f505ddc1dd25045f4bdbefed2bce82c48e44f60ae1fa84e9e2f15642fbbb +7931db3380ad672f27e2519057b90c993592cb6bfa4501c5afe2f5f5077c2b1e14a05c376c3c62 +c62fe4ac1453a64ac0803bd23b528ae50e87b556c0ed4785e95ad61fdfd42053b6f1d2acf1c97d +26d5d8c42383df77b31873feb221bcade2d1c40fd1774c9e296eba6aed78e0ea90eebe0d607684 +9dc47cf92e6a29bab612092f55c928396c73e73c4cab18da8f8f98de2ec6e10516e547383dc53e +30d84c5f659ebdf14661a6b085e581e22ab6bf28fd9cccecf78871a055dac7c42dd10533d3826b +ca9a970c22bcafa59905363efd2de90a1cf53eb976c987aef00ae156843b44f6fb0765e20d9e41 +61751a2e5630ab7c5f92e937ddc8609dfb936c41743c9fe47f53152637d72e4005b05e973aff37 +76f6f996cbe9d6e3cceda0056b39c12d6e1de81e77c15ad82d7056a33bc184f7828080835d92ad +95815f5602dba1125caca06d51bacda8cb48f5277ffcb8c2c3e729dfe31e1e75ea007c9436393b +2ae94e8656cc3fa20e3434416a90ef1eb8ef1d35083b119d2838122dcb9f2f1954f342199f062f +d7ed2cb113620524c738d0c3967d9e62506553a6bdb1ceed3d3e663625e2d9155059479b6d9da8 +dc51af126f408825b1d0509b78e70f5a74b7758198ebd23edaa049383333d07377879331b6c7ba +b531eaddcf143de7e460f473ffa7dfde25e6694ee818107bf0ffbd1fe7c5a88883bf860826239d +672dd8fec3b215d77ed7561c04a40c2e0584af51fb49202f42bdfc0c7e7cf111614e97f8ea090d +431fb8a4db2b4487af472b3c131e5250567fb80f08b1183b2390ab9c4dda5954aa66f622e45dfa +ba2ee237d059f0e57383cc4a2543cb50132c76e88f110c3738d91d7081ae2328a9c02e1daf6dd9 +b325d6b0255087948aa06578b2b3b7cbdc636ee8c93ec43c2f7853780f0c86c52bab0879a09f08 +c544e20e264f18ca60f3086300c3fe76dc7d640fc2d6a57ff36049d7d5e554493a02c57000d573 +678f6cd785c5755678618c5762a29af4d14031d07385054f7fb705b9996a38b04069e44b625ef1 +c754ea1c8c246df0f89880366511e9b5eef6003565c5e54a307cec3b95441038ea4c1086cb5553 +787edcb032832bb8490f4468cfa830bbca5d3cdf457a01cc6f845aebfa2b69625b9e4ab3140d05 +9b710736bbb9a4a77064ae0f1a47d58055fdd64042bfab34d3862edbdb96af196294bf154af1f3 +edc574bccea8e44b10f12067924fccfda8bf501595af1901b5082a9b52619f9f3ff8fe3a499f47 +1b3b8de98d6681d519b48d131beecb9984350340d130c8f8f5468ca13747667198d758e8413658 +8032718a0fd1b4b8eb191934d62b6ea14ea120b74faa1fc6adf20853c17970a97684f96a4897d5 +edef58154272a66123c9aa721b9c70fbe3c134ede9fe0d128aa0521fbd7963f40aa0e6e1cc9974 +e02b7de6bb087b8434322dd53f18e8930ca106283ce3b593764b5cf2477f723d21ba958a47103f +fcfd7bc117046af3b1d0b1428ccb514c9b99ec34bd96b3358015338797eb6e03973eb3b4922877 +de3a368fe43bcf0033627cee8f72893d420f70f4db14b1513957c292324c8e4e95ac03f93763e2 +875e31e020db857f4e984740972fabdb8294621cf8eb5f9c7c639ffbc5ace82b7081d2d6762a37 +666a83b86d662deb21ea6f55dcc06e284bb9b37288582a04493dc28c7e972304cffc57c91c3e67 +ef874e130e8474068950290d76cfbc454eb781e7c4b43ab4cc7773c02218b0eefc777e18e5d572 +f9d2658abd199963766f9962f0a7086c600be688f81c74cccafedd3f2bb8da0a25562b7105aa00 +d1e54efe181c3735b98c8c8b242669fc34ead710180d4c1bb0c6c4f8f3b46b5933d761f0ffb3d1 +2f7eb08716daa08f91bed4b2f9b051bc110441398288df6d77f92a960ce10f87dc4b17dbec658c +d7ebaafdbcca8ac892b5cb13ab0f9cb0d614dca46c1488206e2e01716fe1e1ff2244ef661f1c89 +ee81f63c7d33f695cbad711e97546e0581136d7dd2e4739fe9deabd38d0e3e9d65a65f02fd6b63 +27de043fcd2e1ab5428ba965290c38d5b1f8dc8d3dc696ad5111466e2b1984c65515efddd0d6b5 +db9f005a49e22f7de9f51b661894774d75cf9245fecdb059c17bfc0fa0668ba65c1107eaba293e +edeeada10c357cae7899a9a99eba84aeac6c240e44184800c7e45ba664fe0f5a668fe3361910af +decb7fa18b734aae22fab0056fb2a33443511cb5ff656d39b81f2d910cefe1fe810788b0d22917 +f0e9e3e0c3643d9afe9e024930c60e82ffc57ebac73a19815ea18f0778057df290d36709f9b4d9 +61448358a00de19b03735f91aba3e1abfc4f33cfbc23affb383ee34c6db6dc7a42052b65ba3e1a +e70e2917c9770c8894f901f233e46258e0d7b6674f09a4be5475913e6c1ae8393c31420c8db6d4 +37dc21ea5d3f4b829d468aee35a64cea600741cb8eb33eb84b21c5b5729abe6c0c24a63b4c0c37 +e94009f297f3e90391abf606cf97a1bb2624249c82b1e44911b59f6af21e9849a838d506f97453 +918ba82af9efac44189889f940c23de954016f768d333de28a251f1c0976a0fce6edfe88ce3f08 +df163e65ca795b92d421e0c2554833c37c1ace4701e4b50f71d988d41163117ac6ab7bedd6ff76 +c98bcfed2089b6bca6ec51f30a08e86cfe5bc959adc815208c0d12ffaba6be51b6d4529800d4e8 +34c0d47594d39f8b291bf92f71fd11bb8305d76f337f64060a55d7b815282e690205e193db7c82 +2f26c3c21e61f5556838f66b9f20b681fc4a4421e972d8de8da05f8cef8473ca23dcd1b19a055e +de0850a815b15f832eedf033e8fc8fb886119e0b8c7303602be2bb0f127bf3794d4ef282182f90 +a4d224e887c10c5964f8c3d0a59f20c771d857d76580a8b8d9fd61702312268fed849be8d34409 +9f7d82764d2910d5bbec4283f58b65c7c9b9241418ca7ed4d6064ccd2ae5e1d3e207f9d27978d6 +838731d6ad5cfbe02dde68458f4bd395ef3fe8ea3562ca2bbc399fdd28d926d8e7444eb42de483 +024977d256fa5358635a384b00deb521206cd4eadbabf4a788500e5ccf7e49552d8a25d07fd538 +7c337d215d7e40953b3da41a67745a777ea80dfac235411775743da23e753b012ccae93f1fffce +847e0314401cba79d55f75c98a29e0d3ff4d544e7cf6f1618974b6bd381fbf8b98210a27661905 +48898f52a29fec8c986de8b8f126f7389aa56d16c6ae3e80a801655cb17a37d2ff4db06149088b +7c04a07cb12c83a1079e7f15044ad151e68783a5194ae2499ec22c52aa353540e0d05f00d66413 +e16e527d960e567fca68b3792dd0ea479a26f928553b86ee12e28aa4f1b54f6b499aa694e35251 +453f222fcf365e8eccccba4241d9d5b2472c25dac46abd3a7fb97f2051639b4f2b110fd6c35c7d +a872631d60d117c0401e8d456156f5a34b49897caf13b6b2e15f738cd834bec2fac48641da6cad +000c231a03575d37d2629f7a7232004619b9c3077d48e053d38c99dcff15d301000c435bd6adbe +51e775e0fa1f2bfa1ee723a6ee4ed849aedb8f7aa4129d8767d813a93db20f2328c2e1fe0aaa69 +6477bbdd001abf819e9280b0387db782e817862e6777e3fc41a5dc4817abf9a143d86fc1ae6d68 +2bba45e5d29cfd9da24cb952e4c547750a80d039582fc2d65e2138397055f117f1f4bcc7a9d017 +8afde548f90f68f0494a274b2da5a78728d82c8d5589c9a2b271a43b95a66f1d614aa3d9ed5cc1 +984237a253d217a476cc814cb1f4e83bc0edd3f09b1e71a1539fd2c1fa23cdd9d138152d5d7fd4 +121fb81f7f1a4aee9f632075cc83f5039ffcbaba5033f161e32031bb13db9937e88f7775bca514 +83151d210deb2cfc3830a410851d1c2bc5b0f65e3d2af142caf0551f3a7237a2a6490d22698928 +fe431a210362fed70cc4a86bb7546df3d53e38dbbc8223286e14cf241273a4d862abc724d4594b +43561612f93fedb24200e8d235cc696d54e9c7403705674f60bcbb12b9cfcdfb4f074463d15973 +a87dce08774416228694668941ee9b04b3adff2e6549467e812b5724a41a9eece891bea081c4ad +b53e3574b2a18d98923fd8d355f4c4f304331eac9f6756725dc24439e886c414897db9ae685746 +5775b037832811cd1c6bff4c4d76b783cf258e393c7ba99476f20419ecf751a04ecff3badae6ed +e996943dbd0a2eb45fe7328e735d3c99a3022483e6546e56021a40566de91910f2aaa8cdd72a7e +46709074a20e12752c52351676b60003101a3025175b14083cddb32b1a169556336f29d105f128 +2241dc2a34ca9cfbdba9cf1577a98432a85d18e04bc5411d262daea310a7de740a067be3b54a89 +d639582a2a150d1102112646c28ee4530824cb32f07d894c22371066d456e4c5dd727a24c17721 +4ceec1932abc19cefb01a964f7fec8e96df0029e23a2fdea4f5ebce4b34b65f611ced924223811 +a4a4c8360d3c0cb42891cb04675f937ba70cfc941e824c08e19080146f5a8db2a237b4ff6cebd7 +a031c61cef1d129af937a4878fd1b2e6eabe8ebce9f63583a2a9d9864406bdda4faa9f820938f7 +f4ee271f49690cb0f278cf393e47b80826070e54b84022b9444f26c049cc42a10777dca2d4b716 +4a881ad662bcc48ca4d8bc9bf7373148711559651182b35f2f286256c49902f4bfd172eb80a6f2 +3a9092c9c43cbd4026b2e2001c2fd72c5dc8bd8b5ef954658c9537b065fb54d5a5a23f829fa749 +d966d570b5b4e1e996535f6c1548e53aeb745abeede8095e56d78bccc758377f1f7c9410152fa3 +b3c77b43206a4f740a66d394303601cf4fcba926475043e83a4d7aa342c75578a14388a5fce6e2 +3852b161bb809f328c1d44df6ea6dfedd10885ed4a09d5f97ce18cc1ea8a86d6e8859e680de255 +32da72cd8dcb10f8f030564012efbe58fbf0d228c5c0fbb6003e4e95ca95a278e8d31874d1ab2c +d002fa897774f526b5d2fd47779c2b91759ff6d8b687212b52d1a80153c89a05b8b24aef8b1d8b +d43c8e37748f9a1e45 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark + +%%EndResource +%%BeginResource: font CMR9 +%!PS-AdobeFont-1.0: CMR9 003.002 +%%Title: CMR9 +%Version: 003.002 +%%CreationDate: Mon Jul 13 16:17:00 2009 +%%Creator: David M. Jones +%Copyright: Copyright (c) 1997, 2009 American Mathematical Society +%Copyright: (), with Reserved Font Name CMR9. +% This Font Software is licensed under the SIL Open Font License, Version 1.1. +% This license is in the accompanying file OFL.txt, and is also +% available with a FAQ at: http://scripts.sil.org/OFL. +%%EndComments + +11 dict begin +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def +/FontName /f-1-0 def +/FontBBox {-39 -250 1036 750 }readonly def +/PaintType 0 def +/FontInfo 9 dict dup begin +/version (003.002) readonly def +/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMR9.) readonly def +/FullName (CMR9) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle 0 def +/isFixedPitch false def +/UnderlinePosition -100 def +/UnderlineThickness 50 def +end readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 44 /comma put +dup 67 /C put +dup 69 /E put +dup 97 /a put +dup 99 /c put +dup 101 /e put +dup 103 /g put +dup 104 /h put +dup 105 /i put +dup 107 /k put +dup 108 /l put +dup 110 /n put +dup 111 /o put +dup 112 /p put +dup 113 /q put +dup 114 /r put +dup 115 /s put +dup 116 /t put +dup 117 /u put +dup 118 /v put +dup 175 /macron put +readonly def +currentdict end +currentfile eexec +f983ef0097ece61cf3a79690d73bfb4b0027b78229ecae63571dca5d489f77bdeee69161ac65b8 +1a171acfec6a38e69dd162ea7d456fbeadb28c016db3bfa3a91b731dd3d89e31936de5e0ebbee4 +d9bf15a1d35b3bfa43ade27c55337a53e8117722f41ae71510be6095ec8fcc4480cf4d4b3c8a65 +dec16f24a875f2c200388e757c8d066a3bd39db828e62e2d3d19908b221b8f5b58f7a6a2ebb901 +d705aee915d9f92114c59f6a9124885e77bd754ad8dacd1e7fa44ef6a4733c0ef482d5f4f7788b +0d58fe7cceea728243b0a6d07c975363fe2f68dc120d39bc1437b4ac6e91b4f1adcd675ae140b6 +f59a96ca858bbd5c861ee4d4da5cd8c0810bbf81fb77d72f04692826e26e06411cd5bf235072b9 +a22bff0b022257caea6b35a80f6584f84fb25d2b12b487b1236b8083311acbbfb88875ce5a0b84 +e073c79599d0d3b9392eac002fcafe8ada878d8d2bec5421b9160e45af9b46a19e73a54c5b9ce3 +2803d72f6b9dae6b0944396c7ad95c5b2f6a26cdbe209a7acf1e74b3a9ab21aadbb523c622b789 +a8a7e62071c562985d7d7d42de982268159addc0b0b14d3d4554c96eeb10066785de34005812a5 +c0724d142cbc089a2823a44be053075f0a10a1af7869c45d5d6aefb702e659aac511842a68f17b +36352b1091b636a38e3878993e00c2b94383a02a3e6f83ec0f29abd7f27ddff55aa5b99b807599 +a3a01afb2de5c8583e5a5f52b8dac3ae92d99078716f006f8f0d8690bed1ba33c0e539c783107d +04c5a0f96922d91f9f08a8e6842fae0d8f6428bba51b5d6e4f2c9319de56fb5a3a5356c50f2abf +fd47a16bd01495208867b0c669047bd2472820ca588efac7907cdc6e26d7aac3aa1a8befec0b98 +87e6259ac36e0e67b6602b2c3932175e273cc0b230c21af167c915b09cea2d3bd1716c16720fbc +9911c60bde378180c411260628b4a842ba1f47e0353f965fa91f9f1a25287f8de5f2eec7dac80f +5bb0bc7fb70c55b33c825e595a541f509f0e7bb1a827f4e6b0ea42ecdc110333bf968c3f96b4be +ba2b49f022edbc32dd5a1e0cd1a2354354447c71963ac7054137e2eeb35168bf6432fb7e2a9999 +0d04fd9249e2658eb0e0714f3fe3e104cc29e7aae722d7048606cbdd0af52fbe809b19290d738e +a81fc869f8cc7dc2b20f30ed10fe05e61bc80340f8f677f2be54209edda255db1cbf81e18fb83d +c34b12d6d1bc653cceacb5262b6f756073b85feada4706baecf93f5e31b9e4d34b1268c3597312 +9ac0aeaa72997c22e4ddd0cd4b13813c071f930cc7720ed61c53a2a8c92b691f0565dfaceb6faa +3efbed85229763afeb2279e9ca5db493a725d6aad5bb631d9c72cc668a31925432da1f13242638 +4530b9c64387ca01eda7d7673b1d879eefae47ab5c7dd24c4b8edc618645cad44600a46d252b52 +b0c757391aac4cae6d07d71ac56925b145d0d481355a5af596c1c62b553af0698b066618149868 +cb55664a39df2cc74cc37037b9593f32b1389b3e1d3046b4d767bcb1bb41fd78687f94e0c0bf9e +6f7abd8af4217b3854eaaaee81663fa5ffedf2d2b4eee7d3be79e740d208975b4e2e9b2004530a +471f505f3b3656b3b9fd0a9b703e5dd061cb0ae97fb361a37e1a3a456d148fa3ef403888851c8a +5460bef5d440857d021171956ca6f2d5f5497f37034d5096cee190e0c0ac9056fbed82b4dc4fe9 +8cb2e8be03db885718a774fddb6b7b3ca45d17f8690fd31b52b634168077074aed51e2171c306f +e35b7789794f7a00ac8d19877cf25f06bbb645a1c4d1e06fe0e626c4b152d776c9ff02b1697f96 +abf88a0aa66843eab9a17ca9212d41ede982f4cf08b01f4172d83fa7ab629f765c93e3f5a63b00 +2d9173d24f6a84b9db269fbacee36c956a256ee3276fa2460229a3f5189b9005aef37d1cb4c465 +8c50ab73927d28bb065084c1fc4013c7e3b05812e0b3f7f1f271f8fa2e2a7fa8df660333a5068c +663dd7038bfd50b812c862e41aafa867109461891976d32346e5f1d7a01eb90bc66bd2736fd389 +7ee769f8fbc6a905995251be201fb9428bb0b333a933830b5e29e7f568429924a8af13123122c1 +fa33abb0378d94e05f056acf91aadea48e5864a02ec02c90a01fcafd26cb83a2a6be37364a31de +c69748a969c8274647583c97b70941083940cd083d1b0f530009e91f7f03853a3b219b0ee8c3fe +8f35f02f0e072b8248d729bdc5578c13e8ac6bc16c678f46cd8046f608672d0eb598c95f467ef2 +d7fe5ffa3604c5b0cb663f6c8ffa1b46b6a8e136b0910c4603b64190e2f327629ae5b82aca844a +b1bd131e1b5ef90f2679a94e11a806109a0deaa20b159794540c3536398de32e2368afe0b627fe +7c0f8fbb330ebd044d992ae98e5c5aea577ef6880dd64ef5258fda50196a989fe1552ee8a0fb9f +2dd050288cea4ba60ccadf78590622130c70c1654027ee84ff143ae78cf72f15aa7d5c1cc28ac1 +156bd0059b7cfdd511633a461ed71aa362f82ab482c56b63bd2703ec350a9d3b4c60823ed8bf32 +acee1d72ee0c518b20dce01b6aae986e91bf95968e907d74bb051d21e01d8699415d125d9d3f3a +1d28dcba9943d8af507b9e092b5d2860a12d995135bb9b58c5d03813d905266b374d8325f07ac5 +fd439c57ca844f48a185d436961e30d2fe1363289aa5c48d55debe81b3657d782aa4bba0dca098 +fb439d2ca1a056218ef988dd884ff24b72f212d6c5472b9c4a1235b9f7dd069a568584d8418cfd +29d8a29ad2ddad2e3f5895baa199f481e3078e6f058c526b09e11fa6f12ad17ec1f5492f61dfe5 +eaefffdc1e607e9d52f74fbffddd88d3267518da35ba402aa7a55a22c5e22e3447e19c5bf01d30 +7c8fa48c6bb8734275a160044a81ab43ebbc6e6d1b9cf08a831f17eb5f2acf40416f29f226872b +36f953970b7ca167b1c7cc698a9b661e4660790ce8be022a9de103dc008369729d262cbe64b983 +ab0fc35c886b09decff9b3a167afabff127ee9bc9d42304b99cd827c5dbc120e5bb400238d5877 +752fc3f015f0a78299d4411254fcdd2a09ebf2599c15b53cadc2a6ea8ea4f092e800a84b9822b5 +62ea175d52798211789a32d33c0e47d61d4bcda7ab4ddd9e1d59a843d9c4504947ffb01946ca61 +f2ac5beb30eb78b4cc02ece2668afd047f21a61bb94a9f498c9fe5cde8579026cbbca2d8d3edf8 +bf5ecee3c12650532dcc826df77c0eb1fa3b8f45867ef859b4d11b986bb9516f2e8c54185078cb +dd23e1d32fb3a08a35f7cd97e8fa0f171c92f32a8ff6482df0d448bb988873898abd4a3ebaedd8 +d941e633ec5516d8eb9d6c33fdbbebe5fc97e51008e447c703ed6e7a3254f86fa286636f69c595 +72d772e5ef03430ffeead60c1e9b29d32fe9e7b1fc86ae45a168b84259a8598dbc619485ae38e0 +413c8b92056fe1e2db617e198ef3ff8556198f8e3a3a5f22e8c09eb6819beb68c0d6a12ca4d9fb +cd5ca14940fe9d78f8313443e1c4e7e8d3a0caa4d0f515c01860403e1bef683107010769fbc182 +fb2a9a24749e38721dd36142f882f24dbda36f20a77291d5ed1263f8136561997eb935c04604b6 +e0931b07f0c7a58f9a1ccd51362340c004a73a90c93ac5b142984ade76be67bf8423006a918f93 +67e746b524031771f5da92852dd16c9df6c5f78bfc23ea0913440bcad9c7132e271920d0a525d1 +77d19f776a988ec2610457d667e3e3dafe75efdcf31dbd9360b8824c6c5dc16f0963fedd7acada +46c10543b1dec7c019afff410886e0a5cf1445ff59a03b45306bc4ed807e74bcb387adc6137788 +4b23978295f8381e07076b829cc1eb44bd703cbfe4d7444bc2dc50fc04cefe2e20a9c0524439b0 +68a8b374e562e540786de02ef380803224dc891b0a685a386c5508c5fb3787d4d3f3bf145bb666 +ea65bb72fa71e783f7cbc2584cd19ff8437c5db97071721cb6c910e4a926df5b67767b32d57ff0 +d04ff2a3d3642b860d9e37723bd73d43ddee9f37c2c226808f2ddaef07ffef983dd38c17cf5c52 +0268a4d01a14180e984c8029a1622ae07e3eab034ee399fb9a405f6aef7b50534390eb2a0c4211 +0852ef0eed0b7ba10412904a865b337de98126a004ba9abb4f764aa220e09f1b075563022d2c77 +99a4f277142630bd79d4e5b6d9259c515851412523c4b4866f3a73754062d8efa6e3476804e94e +2839bb25d7f69b3bb5e415979d3d85e19db36a8d953ad34970fa6bb3c2116dd0702eafe26f6aef +d66a1883a044da4c3b9178366a5ab0f9f54cee64073aaf81a4c7820991cb6d97e79ba1eb5dfa2f +3ac5643a01ee5d36b4b7516b0c5f98e4ba057a0547870d9c7eb55d0db9842425be7bda8f725f94 +e8eeb71a1d0ee4c4f0450d99827154b9654a01a1405cb9820b0e2cfa5832d6a3539cafb0a2117c +eb79d450bba4d6b02ab5bd74087234b01501cb79f6052ef8447e9ea7699db67ee105eff80943f2 +6a3acd7a4ca1735ea65e78796eaefa57cde1bb51cd95278ebbc7c90ed0d2b0b1d548c77ec2fb5b +4e590d860a3de794d9a02c38c7d9fd826898dbedc527895d1f6c8a4c8152a5f7cdb0afd80883c5 +0d499aa61f09b813f0538482e79b40dd626b7944d9ee6cc0d47b09044e6537d08b25ac23e32bb2 +024d44ef248dcc83240a93e8762687be9deabc3ac8f82f10326036e308767537fec8625b29297a +c3a035ac027b607881e706aff02aa0ac98b624a19595701149f37d20afedff61fa218b0d9d3cb8 +196b5a0e28e6673ba8af710e03eeb447f179ed4c8a32d16a0e9d999f217cdb5e348e87f9ed4d7a +fc2a6105fdea21c780afda0b6fb059f89e2dd6fedeabedd069e74697199e3c0db8bf4eff516472 +195bdad7d6206a9f6377e0bac79abbdcd35e6c4a67c65c90f5e9199baa83476380120cd02ef6d1 +b7a48799db4aabff356dd2e6b1e5a66e1ca9c06d4bd7c4ed6d875b2980848211b2fc5735366f86 +a7618f6ea9fb899547f18e0e9dbbb247b1e945446020e6e2e8a4cc757749715736336294ccc469 +734b0e43d17020d4d2b526bbf7052a32b28a3bb8718781afdaa56c2ebf27c46f9713f6edec8e70 +d6bfc681c64963c6d2c563e9b6081641dddf8a1acf385a85b8373add3fc2e28a39ccf1ffb63d5f +b4d31baed8d69ccfaaa9a7dba5adbd5c5c61151bfc9e15f7a08df01414b8a460ef6fb20b865ff3 +646c822baab0aef57b91c49418394c01f1bb1a2042ef65c4d33f6d3727282aad9733cdb2845f91 +00a4c8e36c64fe4b19a9235a7f7660c262bce7e6c50e4c87471aa3b4d8d79961ee657eb33b57f3 +439d336c16210e4c85fd17cba60af5d65610ed71e50b4839b612e012b2d714b79fa36fc76ab79a +861f216ddc352cc73215ce63b5b66afff0d0ade952326a2b20c69fcdea2729efb0bc8b5be789bd +824ec8c6f2db20791e680bfd52ea2c79ea317c3286b93e548d29915f3672ea4b4563b6c4e7174d +8ad05631e418d87560fd166242a2886a2ca69d7af1b37554a275c5169f510c221e58f92f28dfc5 +0a22e6090099436ecba0e60c7fd4caa53b50cb1e3a41868612b6d23d58acf68203616b5ab5322e +f072842f8250655a7195e55673b7ad017061485da71c925ebfc79894acdabc09a6cfae30e4fbb3 +8259683cb0d4cd503d64417881c7d71dd063f8b4b4547ce0774881d71425ebe391d91e35e3d496 +3c7e25f8be109a5551747137d071eb255ea7db66df4a60c22ecb294fc0585b8519426c2538bf09 +d3cd2ff840a4e503e4b612c58c62da213e585997f2ae888d00f616dd6622ebc4b9d1b4ed8c2ab4 +10523c242193d5a14f04cdeba92fe1464ba14742b8777f58731356c6fae67287989898bcd2b3e3 +c1345ed18c06e135743c7a30c5388dc6fdfadfdc6d79462a0b750c783e03ce24c3a843d5a04188 +622d65fff6a7bcf7c41509428f3eb28ef07d7d08b662535d5c632916665fa14fd44d1fe3a4b28b +297b05174084c446288153b1089c4dfaff6f333a463390c8b87463f940360188663a0c3d007c05 +20e45d15278e13dad8826160bb7f2a38c91480d13addf1c034f119d084431554aed1d9ef56e74f +ef064002962479f7088fed8eb6d834e6967a95ce0db3cae8441fd6d38156777738f2d26e0cf226 +b6296f1271f1e7b17072327ec418236a75b0ee0d5ee78dabce7c28f134927a7b8dbe7bec5d5a9c +541b7733f0432304237298b479a29db75c80601f16a35b9ec02ba42fd2a3dfd2b228cfdf34eec4 +70703231b2a3782d224f0e3f37f1f466fa50dc29fca87d508333ca25383d8b0feb72b31f71c1ec +3295fbf80adc9bca5eea4b2335f8c0e720885d3c75af3de52e320f6d3eeb2b2af3a4e18e177e5b +b42c1cfc72caa68f1ee145fdc21f0923f41ed158def43a9cd2a0f1cf85a2839ead8ba72d5b1d5c +7da173b42fb34408d029b8757c611b924e12f439fc97e436198f5f94343612804f3e3d02331a41 +cdb5b9ab94a62c5ed03d9b843a42f68234813d9cf4345184abcec876e4e0c77162a59f330b4a6b +231f9e9b2c72ebc87891f7716c5520b2585eca206311057496163aab387f12b594cc57ac4c23a3 +1a685de28a5cb7b4a4f36ed200687bd17cbc4929d7ba086ae2dc73349b0ecced072951af6bdebb +674e1ba52a6fe541bfabaab4d987542a6e8b0f7fb8073122256498a34eb818d75ef926325747f1 +4ccb580e8635171c5948adb05d890186678d3261335e5d77ace5a6ae7d507fa37e178e5d964952 +df7be3a8eada39ea6769416238577b2242d54e440cbb9638b7516d75664af6f7fe9723b5ea645b +29a7699f56e25fc97ab3b9be0c3628bfedcde7f298dde7ea9b57610e1884c18de2863b6185b56a +6d13810f07532ffb0e2b611e64f7d97ca3dc711ba4b77cb743712093af02b25108ba00ffa7e67b +87cb0eb1e80602a9d6ab33f1fdfea66716c25306cb25a6dab14c9156623ed43adacddf14eacb6e +16a44d9f3d064dbe381d877c11a2309d2d6f9b93e213b2c82cbca64ee6118bb524a5caf8d74fb5 +b06c57ba8f31244113a58fc471bd0b5b4649c3dde0bdb68213ea95a0933bd65e2c5e8d4c817674 +5e0f08a5d4863077b82aa5f30d7af46ed457cf8482385fc77301441c81c79c66b91cdb49075cb3 +cc4350accd86d9d2037a5080b461c4e3f39df301992ffb550e53cb081444cc2dac8313b611437e +e8ad893d11e91e9ed47170ac0dbf5ae40a57145f7a4f24941ebd94c7030a02383024b1b4dfcfcf +6bfd22416d3261414700bbcfe3c6f51ef12af5e3f05b2d273737afe1590d27256bec278b164098 +8db2d9249b78b433c21f2963fa015135c1322fd5fa665cda374073081668bc41b13886eedd4b4f +7c68e148b3c3933a6c8703826d66d741a3993b8b96da4143302e1eeb5ec4a263a5a059d736485e +58c39438b1068923661eb061c54aa7036305f7bce6e6cb7edaed98ce03a67faeb1a9139efff507 +9cc765b94756835632ae1c62e1731e9507cc89c1941f337184d2bbce513489f7c6410ce1c0667f +c9624dbaacb2c8d8ec0b8e48b86c68af52ee4fb2a6302e6b9356066baad4c6f402a1b587ae7cf4 +2dba29f3ac0dd0d9b57bc6455dca215595e10e9587bbcd745a7860f80b12c414822251d47de25b +8b91c4bfc7d4a9ffbafc46f8fd8c9196010bdffadf10b0c93110751b422026b516c19921466518 +ac29a08d16aedda7f6ee6179ca7f427860bc7869a8a4c3a36a1606da6755e83cad2a57296a9fc4 +77962bb0c5d2bee728c86830bfb57d3d9a14521401d098e25dc0d2e9e5bfe8c0bc57520d3a2651 +b9f77673adb824eddd4e1ae223baec88b56350720c69f70649328bb57fbe9aec4f0ef08a56bff2 +432a5b7d13ad92a22a2a6c7b928032d2b8fdaaa92a3b4c35358eac006a594afcb8bce9a5000eb4 +4815f9eb1d0a72ff3f5d09a96c1fa7fa6979c0aea23547ca8092d64be463091e2ae2cad6cac1a5 +9a6c316d1bfc71e53f25b267cd29c06d1c6c4890a019acb4b2f537db6411a8f8c0078a809559da +659c579a032838e66b747bbaffd1411f457a4680d154e0955df11933b2468e93e809536e9087cc +266ba6855df56c55b5e28503b6bcfa849602a165487b712459d24bf2f6c8339394fae1ac7231ba +a719b9270d1035ab3d226eff827936992bb7c6770a3620a6d219279eab93357bb4a1ebc0863ac0 +effb340bcb3be968be81a8df4404bd23132484c3f2c2638a5a2584dea7cd767c726e7bf208b0d6 +dbc3bed3a87a1100f4a0aa18851bb9b180dc2074e44ae5c3735d555e8577d02396987a1acc185e +ec7cbe9b45337fb7ebd2f1d7ff4a5199b53d4d02872b572eee2ea522f9bb1a6e00422f072e4de1 +d51e2f8b3ca63df30af50b62e4e6c74df3fecc7849276a1aaa5f9e1fbc7187f9cb2c3f8071abb7 +405130dc6ab0708ea9072f7f9b2b3d5495b799c5eccf5cd7c6ddd57be662f1046ef3a14b0f6205 +11e82eb031f9cf98af9f0ce25738cfefbcf081648f91b24109ac7ed5744da02dedbd5ec1e16f20 +6873fc2fd6adc50a5084afa8a975db33940a96899ef0ca994cf6781f0645f46cfbc3800c3abc0d +0e1b43c7da1a9ab3c09dd382b6548c0f0bee9ec6ba7042673131aba15b45ce0008ce637ece0d9c +97d03fa54726d986a7b5b8ddc6f100229ef632aa120ece628f876730f4281310a0aa4b7d1f73b1 +25c8e0a4eeda9b8aec230d94ac746035219107eee8b960400a49c0599c058e7c03a4bd4077d981 +abb8022e13c0e2646cd4a56fe3a5ce284239bf55fe4a4583171121306593cbada66c94fd9dd496 +f142bc2afbc406006bc2c8ae9ba981cde23221bec59c71aac49aad2c4331b7eb47739a0c92ef6e +c7a633fd365c9a2da590f56c81de68fd60eabf2a03bab0e5d1c5fa8384c3e57aa48b1dee051c41 +2cfcd68b063d1378cf6eb1b0e41b5d6ac7823f0ee79f960682d8d305dbcaf0be1d753c48c8f677 +55eba2f10ae2c11e49ac27dcd8eff615b35dd4edc0a3e00ed422019ff91d6d31569e4ede81f91b +653225be4ea995b1b681b2469678ea8b36f7266430c2d75f2fd202ac886117ec172d0cc243ec9f +63ae1ce96c8602995022c723ebd5c08ed483fdf53fe8cd6f29478517d5f8eb557457d871554a07 +e4488b909e6186d3ae072bd8bba2e3a549436a9ecf7a6203040a3cf844d40ab9c31d679a9ed361 +ca8c5be527a85e2749ab3fee693d5c98d46ce9bb678d5471d80a6ed1ff43a6f26f6e8ac8ac9af5 +254741f8430f4a0e99fde7e35b7f3fe14d1050e309d39152e3b31e6531336aae9b4b5719ac375b +8bae6b9ed3be818a3feddf49ce291a84be64d745c023e2e74bf8849a658c3bcc99cf82e6bde9b9 +18fd2a30e3270173d3810490167be5425bebfce55df5e079d83084f00dca927101e1691348ec57 +bea6a5c997939f2146872bcfcb1d154d34adde4ec8ec814a2d704549fcd902c804cb8bff995bde +d46d78f7d1f00694169c87e84553fd6ecba6ee14e26ecdfb5fba0e849a8a81e131e6834a8e58bc +8f8bd8d605e7733ea61922ea76375cfebbfab984d702fca931a0b0dc611d72ca3f9a4e96921a9a +afa8f1118e37816987fed0c2ea8335e05c4ec39f35ac5f1f4360bd4cbebc25e6e7665b6c54e531 +170414b1575097eb91d837890e449c1b9638d8669c78ad710cc23b42b72beb79bfa89e7aa982a1 +9b06aa084b78cf494795650407d17b0431a473ad3ab49c38f81d5a2ef30c98410468d0f01420f2 +567466f51ac74c3980b06ef8efbd085ea717cdddafb2b6282ab6433f624733533e20c1c7b06960 +92f29c7f5660d21d729a2790666bc155cac89356e333f41b244bc17739b279109ebb818949b1a1 +736799d9c0d113e918745be7762c20b48d7b316ccc771a808ca72bba3636846af6e42f1ea6189f +eda1286213d9183ac331ffef7a8a72921d3ace93769313acf3b0da44e60296bb08ed390915eec6 +667b875a51e9bbed3c9e3992c0b7a34e79f12361b32827b8a492e48dc8b05452898f86739b55bb +ab39335b90aa67a5239cd5f27768e3e3d1c71500f39de0e8fb9158a2bee96a77015ffa21942337 +e773d3ca827c4964ceb71d964fd703109718cd64e97f40349bc8911e9e114a4bc1e3c680a785f9 +3d1533e10b9269c5902fb9ab21f96fefbbc84b2de9c8ac6cec73b064ce9f69470b0122d21ac94b +8d395b3cdfdb52e9235e27536c46eb467f642ca2bf5980a7ed3b66d13747840c2acef75a73f508 +b331e956f6de6dbe62c4ae44b429cb04620d447295a362916b6bff9eaa72e48ac7b8f80d34898e +ec965d13728094bc9656192f09e0bba33141568aedcb9ad3e6b3ab0cec0ec956b59e9bcfd6ce1c +c3e8d472f1a51b8b48ea7193c3925ddb03e944dd52d56eb9cf0cf4c0093dcf7885fbe5f230e319 +14dd31971334df8c685b1f1c07887b65b970785d1e0388745031f094ba705551c7711d5a212985 +3d3c36e14907fab018e81c369478b9a88deab8bc7f3ed8c899cd6b3c5768ee7a3386612e9c7027 +0cfc4570306d6e7a8d21484659b7d610e49dd180b131dfa26622b1d06b6003576a99706cf7e28e +5bd05373f2ee452985d29f4526ba70a667246d4273d00e2f55776c2401f0d4d70fa978ad316aab +02cc5d05b502f0692cee775e9ef54725fcc811650c652b66b88345e8ba1e46b054f6b8fefc448d +36f9c447c2a80c087103ae9886c7c2cc8a35534e69bb7f8b76a647505d64a78766f045cc2b97c6 +bc1500279ae8fc82049ade4e62d2b41f64891cd332cc2aa4266b6dcf7bfc6903d8e1b400bab9fd +d549ac108543b7b599a31fb7b63ce0f674ffc9f569c0920eccb0045381628f5403b14fc0296cd8 +c7c4e6151c885972a387087bcd933480656a005f46276ee99e0647cea10ec7b843c719c537a113 +e8750f5d0d76f0ee6a52f981736d109d44b0788eb23b99366ac5e581435e3da76f0e4843aa04f0 +920b576b3874e40694e8362c6e50e8724d0b15406e20cece02aa8dc509956532cf3b5bfe1c2bf2 +f2abb91539ee2a7ccb67b54bbfa02b7682de5ff264fbb3dad97e64d2b960819fdb4957fa5c979e +118a2807cda3319a8a3c08058f31bc3cd02c00af43cf79501c63da57f656a8575274e7b031fcef +4044aceeb94cdbedb45e2b0f6fcc3ae76dbc015a4f323b140ddcb464c52551bc65daecdd624627 +b7b1f142eda04bc333e67682b9febfc37b3afbb141634fa9052304a3311e148137e8a7fb18b8c4 +d6dfe412a739039735c4d065ba92d05a44ed7e23f2bd1bda70f28bb4357ffe7c5802e915abc77d +bd8867aa67efe810d1e6177b02fb951b542b424c0f725a00cd9a2cfbe3c2cbfb23b0501706870f +c7b81ad222ea2963954f2e65342fde5322e4650aa310978cb3e346b8829536b874138dc1e92129 +1b94388a8ef1fa50d178e5dc006de6a1840b990ed8c925e0e4f881b759c62339e1128d72e9ad2c +bc96d6c2f8069903eeeca8629ff633a4cf423526d5c0fcb0cb3d30e291e4169df804d32c0fbb3a +69cc50d644d4718e09458127bc6a70435531812ce26fc11cd9cc3227409632a7407d920394e41e +7717154e105fe413a48428019936820f3fcf02060504a8e3f621518e2685d609750f7013045278 +28fd8a4293cb2c484acaa2c1ca15f4b7769c8eb406286039e75042d5331d7c8d1aafa19c052529 +3fc9d69991407e7897830ec57b3c42f2d00111c01669407c1a411e455ced82a88e8de9db032f4b +6e2f90b7b6ddd967947d7ed4540c307548942ffbdbf9be8b0bd5a10a20e46cc67de2d1f9bcc09b +ba6d893f7fd1ada1bf4da179b9fae4c2abd96c63d7367409adb0b616734a0d2134c87f7156d2e5 +d82c74ef6a65d2d3e39b84ba8dc5c2e8bca0105e27c3a284187c85966cb71f7018e51ca2b6318c +ff1a31946be0f958778f6148e0c3c4d3bd739818cb2385e4df40d10986f5ae56ca3e3254868d8e +73f23e0f7752e2de1b0cbf4a8e98209d58e282a28169f4888803d0b092b67600798e1356f9d2d5 +7ffa6ec898a8cb809d08880ef6ea025b5ff43de1052b620454f22fd23315f4afb68815e334c0ae +83ae4ff7efe03753a5cb1a0877202487944a1fc201c663c1b1b5169fd090422b2e994b8b638c49 +1c0f45e378a00831a6e38714a581854ef1e653156d215b6563371f4896790b5dabf9cde7f1465d +b5c8a349a8bdf8220110c6579114a257490ef567be1f4e4bca63aeb923f981b56d7251c9dba8ca +1ae0e994b276db1b791c6e0a8086692cf3ce74cc09639bd0136271a0b50bd4d8b02df51bb4c18b +05db86884371476a16461cae145e3ee32a472cbbf6d78a811f4230f91e8e3e6cad943412251e69 +ba5f423d893b688d7846d0acdd8edb0dced11ba703c89287f695eee75352d81d4cd0774504062a +8f335e5352878d07dcdb4c58f3ef2f39c1957bec8c049bf56b53806160270db7e31ce92cb1d968 +64511a49d8b1911454603162159a300f8edb5b3e5f7382f7b3fbfe56bb34501eaa0ed25a3e4c2a +abf2dc5e1d32c2d49ed1a798e5e64581308d824bdd66db01f770342d1d95a4bb66f40fd286d9d0 +8b86ca2e9b549cf06783394f35e5932f471611888acdd47bd9476fc5da3fe5ada7545332bced09 +c8ec45334d1c11dfe24ab7a3fd7067dac4e93b418614ce47acc3cc49d06323e7d2d64f1ee4d4f3 +9c9930935b1dc43eab2e8c87ef886bb8921a37ba4260dbfdea5e30802d497d956a35ae1b7a5ff8 +404c5c8323923086136521c4ad125be292fa9f7524f6a2e043af533707104e1bedd2583613c437 +9c2d4aa128a0a7532f599dfa38de894dce49f0968292878599b83b3c45fb0870799beeda55dd2d +a208eeb73bf979b76603c4a5e8cf59b4b26c14e9e426718a349497402ecb13bd3ef392f1dd5dd4 +f16273e245712374c94b30a3af888c5530be1f974629b4ca23af7b3f58c7a48e5956aac98e81bd +d3340e6b1092f8c44a3b0d0c6327b78b8b39f693511103e78b943b79cba4ae9425e6f5ac605b13 +a080071b92851ee6a14bf6cdf832cbfd5d7acfc4749333db721548266b2d454525b4d44ddcb34c +ab304f6aa66aec611952ab4d28f3a962eb34879b841ab25bc75320fb16b6df30159ab3e0dc8a85 +8bffc9a54c6e8b27699907987ce2c1244bdd38db5710ebfe00ecc9d836f13e1c6eec06ccf4afa3 +9de606426fb9cca115518f711becf8cbb87335b496bba22630ee9a3bd6e6830d8b7d604881d58f +8ffbe6aadf078819a6a7bfb4cbe0dd352b0f83ba2288c215f55b34f963e5337d74678b390da040 +a62eb09f1dd2784d86c11f412f0fc37289e28861e2220442c1b8393eb65a7c69fc6c179d5648eb +32c0c72e824c262cf43a64830508c06488701cdac88aa934632c3ae3cd862dd3b0a210821e4a62 +3ca5f264c95637f1f365ff8bde1ca21c3b7249fcfc352cd92ad88806a6cd113ef8ecb31b8d5bf3 +5f7d23bb11bd929f363b6e721ae9a36fc4958e8f60fc5fe8108aae353eabfea212db25be037500 +39dd22c1865d0c2083a77194c7da4aa6df8a1f5500556631bbad4aba914e +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark + +%%EndResource +%%BeginResource: font CMMI10 +%!PS-AdobeFont-1.0: CMMI10 003.002 +%%Title: CMMI10 +%Version: 003.002 +%%CreationDate: Mon Jul 13 16:17:00 2009 +%%Creator: David M. Jones +%Copyright: Copyright (c) 1997, 2009 American Mathematical Society +%Copyright: (), with Reserved Font Name CMMI10. +% This Font Software is licensed under the SIL Open Font License, Version 1.1. +% This license is in the accompanying file OFL.txt, and is also +% available with a FAQ at: http://scripts.sil.org/OFL. +%%EndComments + +11 dict begin +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def +/FontName /f-2-0 def +/FontBBox {-32 -250 1048 750 }readonly def +/PaintType 0 def +/FontInfo 10 dict dup begin +/version (003.002) readonly def +/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMMI10.) readonly def +/FullName (CMMI10) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.04 def +/isFixedPitch false def +/UnderlinePosition -100 def +/UnderlineThickness 50 def +/ascent 750 def +end readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 102 /f put +dup 119 /w put +readonly def +currentdict end +currentfile eexec +f983ef0097ece61cf3a79690d73bfb4b0027b6f3b53cc32be64063d04d328b49c17a62c396cfc8 +17b9fcb732c3b0aeb6264b2a70f62fbfc397eea8d069af80a71b775145f9842057f969d124e630 +1a760710a5c51e8981851fbcf7f1cd1f2ab78db91af2a6f264e41cc2cdecf450a3a33c89fa447b +8bad4068cb8d7d37adaa4caab8f72cc26b024348ef8708a0ab6ee56d73f035ac9b506c91fcafc2 +40791cc10b1b0ca42c87a24a69e83f61a20432744f7d79437b93825d955cee80718831f56e0254 +0ae4b3a70b9dda35ca4fbcabfbc50a4cafca7423203cf03b8e9eafb091f06b2741ada33c61933f +ab98ef2fd54411c6564b030947ac99cf02f4194b6e0af84cefdc23c1b2886506402a156f0946dd +e0f96a087eea2ac27fe5bdf35b5340fc78f4deda8c9d11d98c0f5e55a92c96eda070164da36646 +45cf37d0d548891f41c633b2cf39f3681ca5b295c862e21d4e3d461f0604fc3557ead3f103b7cd +e8788062ee55dd643ebf68f02de9509a711b769bbaa2f977c0c79c626050e6cc409496ca36999e +1ff008ca97815500e97752078d0286a73dfc1d55e84337b5eccb366bbff2cba70847a15deffc9a +b9465907d667d2583fc8cc9a1b753fb839c71d02786b206edb49d1f1e1222f15e35c63c1308f9b +5a012747cde52cb2b9eb0c6805b3b05040b32dbc7e380ce5ed54283fdc2eb2b9eb0c6805a609d5 +bc292019eb65c765ddae5d9f5a6193a059c6d7674fd34664fff5fc0442f1fab44943e0f74ea3c6 +00960734464cdc627ab1f56d3b620c7d61e434c0469999ad8a683b008d4318a044a01a6ee5c4de +a893d727949247b65a100468185591755ad88509374ea309c172fa8fae1f28ce2d6b478e29984e +142bd328cb3db08eb3c0798faa3c961089be48cd68ef446a7e7486cdf303862f2c49a504f01157 +77979c3cdf97f2fda864e361612983097ae515ccdd43cc4e7c2832837b2730cedbc00213c1640c +bd6db49d0d729017e5a45b2eb6c10992f4274c8fa188470c82b5623f4607dff4afd5892cb6cd5d +85a03022b4d80fc1c3e271c4a3d53241988b6c9c1dcef7a0f9f19281c2a01c858d43fcd28c360e +5aab9ba5d4dea4db85e3a26cc0e8d7defad8c9976dd7d45d9879880dec2766c6d613450cdb6c87 +a690dca9298b59923709795bce1cb2a7f1e3c7888ad49ad9f12090fc5371ea8016b7c0da013dcb +ae8ee5985b69391d249998fdba8da313ec5788b0abdeefaa9239c4edcbb4b311939899a0646a40 +31ef6d0f32a9642bb52ea218982daa9fb54679a769dd0ce17187f09b1dec550179a9f8ba81883a +fe662ef681b2811e81e3e459cbc8e5a6ed948602df36cb16ac7dc8197ef5d0123780e1f4e614fd +8d60f5f6c69ad7377806b6f64aeaa409fbb41dd3ccead8d56e06ee86cac471c474e1e1b727a0b0 +18c82b41297c09366a3f891de3b9807b62b6b3823d7636f6df7ba6884d206dd39e8c56bc07e542 +8d35af43481b160d66572f2eeea2971e9a4744fd79897ba8f917018578e438f98aedcb8a073cf6 +79cd7e52f77385a5b336fa80be78fff9705ef282270f7b516eb7d163181c4cffed31a5553007ec +327cef977efeded1342c72944f456f78d41d031fa614a8eb118a653e1a77fbff5c0e58f38d44a7 +9124a9328900d44e67cf410869f1c45f1012079ab637f81356d9cf0e9b3dfa9e84fe0f296b85ca +ef4ed92097e52b9e71c17c6f8f7637f23fb60abe23521a3907d3442ef45562aee24aecab21b42b +9b24e22a0e58b33aad59fd9ceb08743b270c653b372650e67ab556369259ec5356c846ffe63e57 +a421bd03c0e25a4c2a2abe0cc24d234b41fd269deeb6af086c4f12794dcd5e2485a4831d60ce1c +6305e0ce6b18fba63a71c3c1a88b4aa621cf9c1a2c5c235d433725d14acd1d0a7fe0c8dbd88a46 +ca104f08806a8b0fc6a315fe9e4ab19ffd534cd281ddfe35664c24b7a6e4b9c1d6faab46c4b81a +dadfd591a3cae35e7684a2ee95ab6881a9ca351704023561d3d9b4214137112bd8b64d9085474e +e78cb85ae23d179c21f8efe8baf050d88ecf0f422bf0c15f102b5ec92484ae51d50e5705fb8b28 +e62db9f8c32d691cf9cb209a50494acd6e55990d15c6a130ca5a094503712a5db0655f4383cbe5 +785702c3b95e6acff0d6d1bb86c5562b71d366c068e0df346ea2fdce1d673a78d04a3dc88377ff +ae336a2ab2cde346d17e7962de2438f4b5e608cc9707f2d560dbb9c4786970d8df05b47c81eed8 +f26573b38e1dca64f4b772f49554f24bf63e95b6b2b952f2807f3b35ce45c689a9fc7bc36e6413 +619bcf52bb1cd0c752640dd4dc6104390a7546dbeceb7a2ef1a04bbdd5ed4b730fbc610bc590ee +309c3c49b5e3c9be27369fbfb0526ebcab6bde96c9ffb87eb7bc4361381e0f4472f87b4c17fe35 +cb93ea3fd8ec25f49c92476875986527b7dc4093ac056e5821c44d7fd4e2cc32423ea320d5f6c9 +38e04ccc1c259fc57282a2a876ae3062aeebd3efcf06b72d8bc51eeaa8cabaff8961327318f53e +8e0136d64c169cb4190942dcc3d7af79ee0575101ea563a9fe85dbc6f3611a926f77f33af26690 +9cf5647f64a55b285cf54b5b334d0d0011dba80af1eb7c37b0410072d90429b7db7db6ada180d3 +202c6ad7057c7b5fd5f59578a17ce04b12d8b8de2c55fef874bfea8d9825b5ee233a8ad91cd8c9 +56234b1dd4407eea57d4bf78b89f124d0637e3a9a7223b6c73fd93a687528e38c608f62298a60f +08c11b62a9fa39068feeb9b5646e84d422aa835556761d1459386adeba9fed5b74e2d78f695c49 +f9d829dd85b9641fab34cbaa49e3f306ebb3687b1bb5c764495943074e2dab0c4513bd1d14ea2f +5fc1069df238f0b38cfdcc7ab9e945374cb6f45c740dc95f8e6c82fc3247e14bf27443e4c0ecc1 +09873c1e51f325d8d52338d5cbc8982fff68fb5fb92f11783bd6cf9b2307a2802eb9e68321a10d +4431ec6a9e4b6d5ae394f2ec0e8b53385143802f018edb580ebfa5d0406bbaf8dc681185582862 +2626125e293c47204bf307b1bcd649ebf20be0ae42b0364b37300da60de0649e2150e70614d024 +a3d2f75bd9a886f78c71b59b6754a0bf7aa2f76f920ab9c0f1cd1bd531dd25e6c2a3e3bc8da49b +1c1ef82b4737cb81b0510d551f844adfc80a55301c8310f9d103c489c90a44f84f47b6f1b8d474 +366071ca1522215ace0d842767ab2c961d1c9b32bb886714945aafccfe513743f5f5c44dc1cfec +eca538472511896c85b2c9126173c12d4b2b36c4b62cae0e746c0211eefb8a8fccb473bc50fb48 +a3c3e6946016908e5f4f4914fdfeedf1186f12a39f13131629ab408fb2e0dd186c257ca3dac07b +e9a7528c725db8a93d52ae0c10e4d290aef73c7fb2ca6bf922423eb71a8c59526e3d73e057d627 +9630dde8906b795562f4396c0869a20694370f2696b00fe2f96369b26d56b34a0fe7ad376519d1 +b8a50598b2d5a60004a3b7c89218aa9ffc1e5e74ecc4885c517c0627b58b60b136f651c1d48f38 +8fb9351fc5c46dd3c4bbcb7dcfd01e6ddd4063bff55a34d64c55599a82417717eb593ed428b677 +50972bba8252c31507bdd7435abe4b4edbe81b312cc5f91a1f9237ee9c278d11b51833f65260e3 +bd0410699d0a0b8c613152578fac985028eec5f10e8b9bfd680cb0bb53b8e93ad0fa3a749cc223 +bd356319fb1b6c6ec397d22248f0891ec1b60e84e89886212fe1b41d5c2b6345d4ba2340306efc +811586e06ab7ee765e93c50b873fd48870769d1d218a10952a9856b4b51445fb82a7928dce5fe1 +805b19b99d5378cc9271c4722e47a09a9278ff244bb280cca6a828cd0901ae75f5ba1f87e73253 +984d7ae66515141e34d90e770992a0736e3d042b304271e207db1f282b2dff4388e48eaad733aa +746fda33c9d9c7c9fdc090b4b2876fe4645c0bb822ce40d581c7625f9ec0de5dc6a0669412e971 +2507139fc3652c35523afaff01d3bd63a1e2c8a53b9ee0543fc505902e8fe0c23f72d824e951c4 +0a6483cd8a12a5b29f7c799309d17386917861acc27c200aaa34cb2a104dba07eb4ddf5e4099e3 +57d625394728dc83e1d722f3cc1ae7598f169e9c9a2c1e7250715dae8660ae119d8e29323faea6 +13c0d31c0c1d4005f2bfcc2d7913f8a0e18d1da390e2f1d3e28d6eddd09c93d019d608911baf7b +ce79557b1397975e38e906b695b6ae1c22af047dbc1d7d08744f182b2263e14a75b843ddd8f990 +078410973d7cff56e897245a224a1ddbfaed2d848ded109648d42da10219fa6358bce77565464a +e52af167fabc06c11e6726fc233d0144d35ab68c7269ed2778017ab4ac15639d2588952fa22550 +e273df724abf514d1f0364a1e2a7d9cdb4e356494de3af6125d3cc6d2ddba01ab92d36216a0505 +b4c0fbe46ad4674d8bb51e7520fb4403bbae43bd6a69e475eff0ed4f71d865f6d3bf6e3ed57508 +07de076c0b1f59083d488ad5fefe10d1cb93a0f4f110e45a80bbb00bf408c96bc6347922332f32 +20cf474b66fe1904fab3e58c9ed0b4cc7215665ea72ea2f7212e7927877fe71070d4ebfbe97a37 +5a8784640dec93f6d6eedb7224873e8fbef31c40622d385f6ee43cc6c5720d3df72065155d58eb +d21f2c93f323e9e0cdc35ac43330f9ccbcebd9415173e5304db65d3dcc4a8158b8a838ce7e0bcc +4f4bffeb9333eb9a28cdab15cf3256ae784884eb1fec9b65328a0a26d0c8edfd3213384b367fab +9829a4a1823e223a3fab405e51593700fadd42352144f1b648bf7bdd217172ca43066e2632ddf3 +77a535b0d855ae8120a97e0c907967c36e88b9da5596676c9bc1fe9449bdae8ed6ed101ca70798 +afb9b9ee1b357fbd0846af20d3f4e64ad7793501a0f52ca0710d5588c8a7900f9f58164d8e5174 +a413764ed0b2630585c09c66a62e3ac562e06f2572fba273f8f2f62b50f2fb21040d12f607db04 +0076159fa283a42c653614cac50f6d929c6d69b7ba331f2bae21b1e25c2937b5404f6ff789b73d +b70cd06e32f5658dc2ccd53d40acea5b19e4019263058c333d81e6f99741a86d21bda9c6a6680b +35fdc036ae2379b16e7549afa7ede71c3e23df721ea9f4580d8c516832677fde26b79ce1a92246 +7086e293b003c9f725663ff089da8855c5fd232612fc0434c25b759debaa039a658a8f291261a1 +1e58460247bd0a03d3cbaa7b005d605030d42daeb1914ec78ffa012e5a416ba91a877872a48936 +2909cb20cc859f032e305be4e1e2510803c3f475ceda2c3dc8ef409faf1e260240d9eeaeae853d +f289471f6206a91d7e7a24b3568ecfff34269dc13fb9cc71850093db85bea6c890ed3ba5f8220b +7516353a9b9a7ae11bb69b37827e6036602b536a8142d4524afe7b951125c1243d3c8845a38afb +7bba584219487cd88b302487e502d5911d79eab6cc2070ab47d5bd927b0a835cdcf0362c8bc0db +3b45ad85aa6434de49b32bbb5bd180ab18c98b8e9538089552b3600a532fd24769c35281f3d605 +85e75988a305f1278f6f2a5ee0405d0f30b6770af0364f4d982c07d607ffa4d55cb773d92f9b0e +163934e801ccd9a23b47930a57cae509c9e021d67c3e08ba173f8274b6b1fc1a53305dc998c657 +6ef045e84fc0bb391e971d75d69cf507daf86967bfca7f098be6f9f19ae1b72c433826094601fc +acae2fdfe2773bdffc19616ad0e1da13b6575b5e949bee16f4198ce82df7bdb5a0e5411acca8d7 +4cfa1f7fb2f0b696de35d3810e090f2bb036bf80aa77d8e71140005a3014d736d4338ead5b3ce7 +760b0008c418c80508c44b9e5e8b58b6b770cfbd7aff85631cca1eacb7836580f3d889d9055ff8 +08f29cef9ebff7ff904f89d6655dd9a7097e2a27c19a0c47e710fe7143a2ee1e642da6af560630 +5c2abca4db9ae966057c124757b094b5b1226702b1a7fa4f082f8f1bbf841abbc29f760ed72e04 +746ec76895d4d5d78d2e09b73e0b6cad2cbf7b2583c1b6aed6b208dd582795177df4976908582a +253ce329af84db80d2ddb23c02c659f99c0bd70849b40c4bee2c41c3118e5444cbe7de1e57da26 +8c9c6e0da8f2fc33d7193f0f4ecb83dfbb9bec8d0098c10134fc5c2700a90a9f0707ad75762fb0 +63f620b691c478ff88f78b486e7fa772c06e3f86b94555d981ed92fdf2ab8df1b9c1f9aca18009 +8d876e0b5a1f44d53a4341ad0c3c0837b8a595932efbeceba6bdeffbee967e474e173f99907168 +9c1a7e23255d793557a022726053b5bdbc9c333926d714ff8d6261e492df9c905dd66dd1b7e17e +714a44c1e073deadf6a250b765872bf96e047b297580c27ad1714d8a2ce93346d0a972cba8bae0 +26bc1646f8fed5c9a3366e73a2a65fe7fbed4a8447ba4cef3f25e20eec13f5448dab2b1768be14 +a2f1fe90117079de58883a86e7759a3f8723901e70ed76dfdab6db2a2597f3cded02e1418e33ef +2fc5eb86072ba97db0b4a87bf21354eb8fa680bd07fbafcf8cb2fa44a9bad1ec8d5692b12a0390 +e550e272449546a95aea075538359df87234050bf5b6fa86634e628dce90f5947772b834d3dcb5 +bbfef9f5faccac5ea302813fa76a0c7e8d4a6904110e7d164fdda1f2f9e867052945e5697f3e7b +3f3e44a159fdbb940d942c43520b6760dad2d26e5568604eaf88278a7842315d062bc8b723d19b +35d5913264c3313d68f88a1f063d0c1b5d51296c7c2878c5a016c6adb672f6148ea484b4356477 +94900efc313ca6fb90d3165695c194440f715875b1817b511a9255d75a7ec5343baf3115503e2b +7b7550688caa306b175b35f1a17d821f4168e5f8caa50058e5700eca8751c8446a91c1ef58e6d8 +de3dc3d7f89facf39e5063c470f80c7d740fc48d67a51eb34adb4bf49f04166e3c8cc5edba3268 +4d760cf5de8e3b15fb7c922bb6866719f75f5e4b35fe0bcfc50117e820a707a9d45377bcbb9b50 +57c58d4d9ed248becb7d749ceaa982166f4e8fb3617654d46da66f2766ffd0404adc348bbe5cb7 +8623985f7bfe0b05c802f028d9f4a944f3077e85eb1e953656f07be40f600f17273a582064e98c +77b6ed4f49b086e2e83e8e7dbe8cd9da174b49171822ca13ecd8ed6cadad41e56bae142c7ea81c +e7041b17ce25ecc4e7b836a6d2831da602b8e74347810ee746cff2019ac296c137e34d2078d6cd +89d12714fa8056c200294b7d43a678eec4b09c0dfbebc9899763b21f281a278d4a67701db89d78 +6acabde84a78a9647f68ca1f1d96237ba5496e840c270c2dc9320668eb83864c340dc520d9de1f +6c6035efd0273406a14dba72d0d484cf006f559c114020aca0bc9e1822efdfec07866913956d0b +f90c5b0f96b6c17799153e59603fb415cbac3aad5512eda753de8ea7b4ffe9135a8c70416899f5 +b6d1765b03acac1f8f970bf2d937ae6bcb694dbd3df0db2b53fcfdb8eedfbc7bb80246f7173b31 +93c0fd9bb5c1f2c3b3a9aa1b4ea166322660dd848c4922fa4fee272ba1ae64beeeb19cc875b268 +712aff8d4f245c2f081ede4e619321f341b217198e7a7b6b39b5a13807cb970ad03277fdbdbf29 +235c600e20ccd4d4153a4601248829f857509717222c2c9535e05debdede4dade6ddcb343c2e71 +5573b2182af3875528120b42dfda773ced4e091f4e99fc1c8f33832569adb8233c781b31ff3786 +8723d053307300f1e113e908473fbe39ed75a931c290e7efaf4c89d4cd22f63852ec30831d61d1 +de3815a6d18fbcd15f28eea75ae50bd0b237e8cb0870cac5ddc13da58dbd060d3193fc92e6c4ce +f3bcfd81ce6b3679bfc5855796cdfa8a26d63a659a2ff7a1a7e318a7f76ff80e846a2d647d38e8 +27ffaf54bd5a9221eeb416a475eabf4ef0409b1ca55a851c245bf7207aa06f542de6dff18dedae +45ebd5df41c9716f9f265e0f76ff738e8b1365d83a50d5e6ec8124003f416efe2f6d0f7804ac7c +59f19265b3d1d20ec202d2a8f04cfaaebcf61da57b1dc67a714a16a2692ba82c5058af93c2ae5d +9d1f87b638c5b191eb96bd1ccaa8346e61cbe333984dc3dd511d8a6c7cecb703091db94f945ed9 +abae8f8741dadc74a02769e5a0afb87ac17d08346179d17c57a81fd3a4716d2fc8caf05a6c85c1 +81c9532d228521154c27ca5e7f2a6ae9c67e7c489349486160017ac492fd9e3194652933fbc28e +67ae3eef30568919759fb1bdb0047efafcd5a51f078f3b1970254b1f4798fe2ba43278fcae54a4 +af1b648397024e3484f01a601ab4869834eb08e9101d16dff4886d5cf93ab63fa54c2a2a051495 +4420f130ca83efd3199ce399c5ab3fee55d1cdef0b0d712434e37a4860397c8e1990fa3f97f2f2 +8e2c271b933a0776936e968170273abc684d5803324aba7f6f31daac9f5763eb8c7de746bc65c4 +d78ec4083ab2db415474c1b579f14d9c638761cd0aa12d7a41a70a65db03b057e340e58d846ee8 +642f4a98c49f0ed3ce1f48a69bf5c3bb2bfdfbb9cea90431838a41efa04abb0f766e37003ef827 +1955f36dd28f2b0737f2849f6a9b3cf5cc49a481cc66bbe079cdec206d3a17171cbadeed293436 +43d8a5234cc0e75ea0a6c851607d7a9150b5abdb697f8b602aa44ac66772a6101917bd33198813 +ebbdc780695619803168a49913f2515a51dedcc4a1679948f3f85c5d8ddd4f1575b3b36d6caa35 +3b90536710915e1ad5e170a98219419d972deb8e13710580f65141d7ef5a57ab1dd7cb644a74eb +9fe50f32bffb297fa3024e2182daddee67151542f11d1bbe070a54a7bb37dbe47fed6b8049dc64 +44ab58bfbcc59b40c5b4c376e20b6f98508088bdcf699a6e4ef2f251b6f8dd94c52004bed51587 +c7ae571e0001dd1e456310b7cd0cf19eae56f3ff81550fc72295add56a336686a76340cc5ae3 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark + +%%EndResource +%%BeginResource: font CMMI10 +%!PS-AdobeFont-1.0: CMMI10 003.002 +%%Title: CMMI10 +%Version: 003.002 +%%CreationDate: Mon Jul 13 16:17:00 2009 +%%Creator: David M. Jones +%Copyright: Copyright (c) 1997, 2009 American Mathematical Society +%Copyright: (), with Reserved Font Name CMMI10. +% This Font Software is licensed under the SIL Open Font License, Version 1.1. +% This license is in the accompanying file OFL.txt, and is also +% available with a FAQ at: http://scripts.sil.org/OFL. +%%EndComments + +11 dict begin +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def +/FontName /f-2-1 def +/FontBBox {-32 -250 1048 750 }readonly def +/PaintType 0 def +/FontInfo 10 dict dup begin +/version (003.002) readonly def +/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMMI10.) readonly def +/FullName (CMMI10) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.04 def +/isFixedPitch false def +/UnderlinePosition -100 def +/UnderlineThickness 50 def +/ascent 750 def +end readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 1 /epsilon put +readonly def +currentdict end +currentfile eexec +f983ef0097ece61cf3a79690d73bfb4b0027b6f3b53cc32be64063d04d328b49c17a62c396cfc8 +17b9fcb732c3b0aeb6264b2a70f62fbfc397eea8d069af80a71b775145f9842057f969d124e630 +1a760710a5c51e8981851fbcf7f1cd1f2ab78db91af2a6f264e41cc2cdecf450a3a33c89fa447b +8bad4068cb8d7d37adaa4caab8f72cc26b024348ef8708a0ab6ee56d73f035ac9b506c91fcafc2 +40791cc10b1b0ca42c87a24a69e83f61a20432744f7d79437b93825d955cee80718831f56e0254 +0ae4b3a70b9dda35ca4fbcabfbc50a4cafca7423203cf03b8e9eafb091f06b2741ada33c61933f +ab98ef2fd54411c6564b030947ac99cf02f4194b6e0af84cefdc23c1b2886506402a156f0946dd +e0f96a087eea2ac27fe5bdf35b5340fc78f4deda8c9d11d98c0f5e55a92c96eda070164da36646 +45cf37d0d548891f41c633b2cf39f3681ca5b295c862e21d4e3d461f0604fc3557ead3f103b7cd +e8788062ee55dd643ebf68f02de9509a711b769bbaa2f977c0c79c626050e6cc409496ca36999e +1ff008ca97815500e97752078d0286a73dfc1d55e84337b5eccb366bbff2cba70847a15deffc9a +b9465907d667d2583fc8cc9a1b753fb839c71d02786b206edb49d1f1e1222f15e35c63c1308f9b +5a012747cde52cb2b9eb0c6805b3b05040b32dbc7e380ce5ed54283fdc2eb2b9eb0c6805a609d5 +bc292019eb65c765ddae5d9f5a6193a059c6d7674fd34664fff5fc0442f1fab44943e0f74ea3c6 +00960734464cdc627ab1f56d3b620c7d61e434c0469999ad8a683b008d4318a044a01a6ee5c4de +a893d727949247b65a100468185591755ad88509374ea309c172fa8fae1f28ce2d6b478e29984e +142bd328cb3db08eb3c0798faa3c961089be48cd68ef446a7e7486cdf303862f2c49a504f01157 +77979c3cdf97f2fda864e361612983097ae515ccdd43cc4e7c2832837b2730cedbc00213c1640c +bd6db49d0d729017e5a45b2eb6c10992f4274c8fa188470c82b5623f4607dff4afd5892cb6cd5d +85a03022b4d80fc1c3e271c4a3d53241988b6c9c1dcef7a0f9f19281c2a01c858d43fcd28c360e +5aab9ba5d4dea4db85e3a26cc0e8d7defad8c9976dd7d45d9879880dec2766c6d613450cdb6c87 +a690dca9298b59923709795bce1cb2a7f1e3c7888ad49ad9f12090fc5371ea8016b7c0da013dcb +ae8ee5985b69391d249998fdba8da313ec5788b0abdeefaa9239c4edcbb4b311939899a0646a40 +31ef6d0f32a9642bb52ea218982daa9fb54679a769dd0ce17187f09b1dec550179a9f8ba81883a +fe662ef681b2811e81e3e459cbc8e5a6ed948602df36cb16ac7dc8197ef5d0123780e1f4e614fd +8d60f5f6c69ad7377806b6f64aeaa409fbb41dd3ccead8d56e06ee86cac471c474e1e1b727a0b0 +18c82b41297c09366a3f891de3b9807b62b6b3823d7636f6df7ba6884d206dd39e8c56bc07e542 +8d35af43481b160d66572f2eeea2971e9a4744fd79897ba8f917018578e438f98aedcb8a073cf6 +79cd7e52f77385a5b336fa80be78fff9705ef282270f7b516eb7d163181c4cffed31a5553007ec +327cef977efeded1342c72944f456f78d41d031fa614a8eb118a653e1a77fbff5c0e58f38d44a7 +9124a9328900d44e67cf410869f1c45f1012079ab637f81356d9cf0e9b3dfa9e84fe0f296b85ca +ef4ed92097e52b9e71c17c6f8f7637f23fb60abe23521a3907d3442ef45562aee24aecab21b42b +9b24e22a0e58b33aad59fd9ceb08743b270c653b372650e67ab556369259ec5356c846ffe63e57 +a421bd03c0e25a4c2a2abe0cc24d234b41fd269deeb6af086c4f12794dcd5e2485a4831d60ce1c +6305e0ce6b18fba63a71c3c1a88b4aa621cf9c1a2c5c235d433725d14acd1d0a7fe0c8dbd88a46 +ca104f08806a8b0fc6a315fe9e4ab19ffd534cd281ddfe35664c24b7a6e4b9c1d6faab46c4b81a +dadfd591a3cae35e7684a2ee95ab6881a9ca351704023561d3d9b4214137112bd8b64d9085474e +e78cb85ae23d179c21f8efe8baf050d88ecf0f422bf0c15f102b5ec92484ae51d50e5705fb8b28 +e62db9f8c32d691cf9cb209a50494acd6e55990d15c6a130ca5a094503712a5db0655f4383cbe5 +785702c3b95e6acff0d6d1bb86c5562b71d366c068e0df346ea2fdce1d673a78d04a3dc88377ff +ae336a2ab2cde346d17e7962de2438f4b5e608cc9707f2d560dbb9c4786970d8df05b47c81eed8 +f26573b38e1dca64f4b772f49554f24bf63e95b6b2b952f2807f3b35ce45c689a9fc7bc36e6413 +619bcf52bb1cd0c752640dd4dc6104390a7546dbeceb7a2ef1a04bbdd5ed4b730fbc610bc590ee +309c3c49b5e3c9be27369fbfb0526ebcab6bde96c9ffb87eb7bc4361381e0f4472f87b4c17fe35 +cb93ea3fd8ec25f49c92476875986527b7dc4093ac056e5821c44d7fd4e2cc32423ea320d5f6c9 +38e04ccc1c259fc57282a2a876ae3062aeebd3efcf06b72d8bc51eeaa8cabaff8961327318f53e +8e0136d64c169cb4190942dcc3d7af79ee0575101ea563a9fe85dbc6f3611a926f77f33af26690 +9cf5647f64a55b285cf54b5b334d0d0011dba80af1eb7c37b0410072d90429b7db7db6ada180d3 +202c6ad7057c7b5fd5f59578a17ce04b12d8b8de2c55fef874bfea8d9825b5ee233a8ad91cd8c9 +56234b1dd4407eea57d4bf78b89f124d0637e3a9a7223b6c73fd93a687528e38c608f62298a60f +08c11b62a9fa39068feeb9b5646e84d422aa835556761d1459386adeba9fed5b74e2d78f695c49 +f9d829dd85b9641fab34cbaa49e3f306ebb3687b1bb5c764495943074e2dab0c4513bd1d14ea2f +5fc1069df238f0b38cfdcc7ab9e945374cb6f45c740dc95f8e6c82fc3247e14bf27443e4c0ecc1 +09873c1e51f325d8d52338d5cbc8982fff68fb5fb92f11783bd6cf9b2307a2802eb9e68321a10d +4431ec6a9e4b6d5ae394f2ec0e8b53385143802f018edb580ebfa5d0406bbaf8dc681185582862 +2626125e293c47204bf307b1bcd649ebf20be0ae42b0364b37300da60de0649e2150e70614d024 +a3d2f75bd9a886f78c71b59b6754a0bf7aa2f76f920ab9c0f1cd1bd531dd25e6c2a3e3bc8da49b +1c1ef82b4737cb81b0510d551f844adfc80a55301c8310f9d103c489c90a44f84f47b6f1b8d474 +366071ca1522215ace0d842767ab2c961d1c9b32bb886714945aafccfe513743f5f5c44dc1cfec +eca538472511896c85b2c9126173c12d4b2b36c4b62cae0e746c0211eefb8a8fccb473bc50fb48 +a3c3e6946016908e5f4f4914fdfeedf1186f12a39f13131629ab408fb2e0dd186c257ca3dac07b +e9a7528c725db8a93d52ae0c10e4d290aef73c7fb2ca6bf922423eb71a8c59526e3d73e057d627 +9630dde8906b795562f4396c0869a20694370f2696b00fe2f96369b26d56b34a0fe7ad376519d1 +b8a50598b2d5a60004a3b7c89218aa9ffc1e5e74ecc4885c517c0627b58b60b136f651c1d48f38 +8fb9351fc5c46dd3c4bbcb7dcfd01e6ddd4063bff55a34d64c55599a82417717eb593ed428b677 +50972bba8252c31507bdd7435abe4b4edbe81b312cc5f91a1f9237ee9c278d11b51833f65260e3 +bd0410699d0a0b8c613152578fac985028eec5f10e8b9bfd680cb0bb53b8e93ad0fa3a749cc223 +bd356319fb1b6c6ec397d22248f0891ec1b60e84e89886212fe1b41d5c2b6345d4ba2340306efc +811586e06ab7ee765e93c50b873fd48870769d1d218a10952a9856b4b51445fb82a7928dce5fe1 +805b19b99d5378cc9271c4722e47a09a9278ff244bb280cca6a828cd0901ae75f5ba1f87e73253 +984d7ae66515141e34d90e770992a0736e3d042b304271e207db1f282b2dff4388e48eaad733aa +746fda33c9d9c7c9fdc090b4b2876fe4645c0bb822ce40d581c7625f9ec0de5dc6a0669412e971 +2507139fc3652c35523afaff01d3bd63a1e2c8a53b9ee0543fc505902e8fe0c23f72d824e951c4 +0a6483cd8a12a5b29f7c799309d17386917861acc27c200aaa34cb2a104dba07eb4ddf5e4099e3 +57d625394728dc83e1d722f3cc1ae7598f169e9c9a2c1e7250715dae8660ae119d8e29323faea6 +13c0d31c0c1d4005f2bfcc2d7913f8a0e18d1da390e2f1d3e28d6eddd09c93d019d608911baf7b +ce79557b1397975e38e906b695b6ae1c22af047dbc1d7d08744f182b2263e14a75b843ddd8f990 +078410973d7cff56e897245a224a1ddbfaed2d848ded109648d42da10219fa6358bce77565464a +e52af167fabc06c11e6726fc233d0144d35ab68c7269ed2778017ab4ac15639d2588952fa22550 +e273df724abf514d1f0364a1e2a7d9cdb4e356494de3af6125d3cc6d2ddba01ab92d36216a0505 +b4c0fbe46ad4674d8bb51e7520fb4403bbae43bd6a69e475eff0ed4f71d865f6d3bf6e3ed57508 +07de076c0b1f59083d488ad5fefe10d1cb93a0f4f110e45a80bbb00bf408c96bc6347922332f32 +20cf474b66fe1904fab3e58c9ed0b4cc7215665ea72ea2f7212e7927877fe71070d4ebfbe97a37 +5a8784640dec93f6d6eedb7224873e8fbef31c40622d385f6ee43cc6c5720d3df72065155d58eb +d21f2c93f323e9e0cdc35ac43330f9ccbcebd9415173e5304db65d3dcc4a8158b8a838ce7e0bcc +4f4bffeb9333eb9a28cdab15cf3256ae784884eb1fec9b65328a0a26d0c8edfd3213384b367fab +9829a4a1823e223a3fab405e51593700fadd42352144f1b648bf7bdd217172ca43066e2632ddf3 +77a535b0d855ae8120a97e0c907967c36e88b9da5596676c9bc1fe9449bdae8ed6ed101ca70798 +afb9b9ee1b357fbd0846af20d3f4e64ad7793501a0f52ca0710d5588c8a7900f9f58164d8e5174 +a413764ed0b2630585c09c66a62e3ac562e06f2572fba273f8f2f62b50f2fb21040d12f607db04 +0076159fa283a42c653614cac50f6d929c6d69b7ba331f2bae21b1e25c2937b5404f6ff789b73d +b70cd06e32f5658dc2ccd53d40acea5b19e4019263058c333d81e6f99741a86d21bda9c6a6680b +35fdc036ae2379b16e7549afa7ede71c3e23df721ea9f4580d8c516832677fde26b79ce1a92246 +7086e293b003c9f725663ff089da8855c5fd232612fc0434c25b759debaa039a658a8f291261a1 +1e58460247bd0a03d3cbaa7b005d605030d42daeb1914ec78ffa012e5a416ba91a877872a48936 +2909cb20cc859f032e305be4e1e2510803c3f475ceda2c3dc8ef409faf1e260240d9eeaeae853d +f289471f6206a91d7e7a24b3568ecfff34269dc13fb9cc71850093db85bea6c890ed3ba5f8220b +7516353a9b9a7ae11bb69b37827e6036602b536a8142d4524afe7b951125c1243d3c8845a38afb +7bba584219487cd88b302487e502d5911d79eab6cc2070ab47d5bd927b0a835cdcf0362c8bc0db +3b45ad85aa6434de49b32bbb5bd180ab18c98b8e9538089552b3600a532fd24769c35281f3d605 +85e75988a305f1278f6f2a5ee0405d0f30b6770af0364f4d982c07d607ffa4d55cb773d92f9b0e +163934e801ccd9a23b47930a57cae509c9e021d67c3e08ba173f8274b6b1fc1a53305dc998c657 +6ef045e84fc0bb391e971d75d69cf507daf86967bfca7f098be6f9f19ae1b72c433826094601fc +acae2fdfe2773bdffc19616ad0e1da13b6575b5e949bee16f4198ce82df7bdb5a0e5411acca8d7 +4cfa1f7fb2f0b696de35d3810e090f2bb036bf80aa77d8e71140005a3014d736d4338ead5b3ce7 +760b0008c418c80508c44b9e5e8b58b6b770cfbd7aff85631cca1eacb7836580f3d889d9055ff8 +08f29cef9ebff7ff904f89d6655dd9a7097e2a27c19a0c47e710fe7143a2ee1e642da6af560630 +5c2abca4db9ae966057c124757b094b5b1226702b1a7fa4f082f8f1bbf841abbc29f760ed72e04 +746ec76895d4d5d78d2e09b73e0b6cad2cbf7b2583c1b6aed6b208dd582795177df4976908582a +253ce329af84db80d2ddb23c02c659f99c0bd70849b40c4bee2c41c3118e5444cbe7de1e57da26 +8c9c6e0da8f2fc33d7193f0f4ecb83dfbb9bec8d0098c10134fc5c2700a90a9f0707ad75762fb0 +63f620b691c478ff88f78b486e7fa772c06e3f86b94555d981ed92fdf2ab8df1b9c1f9aca18009 +8d876e0b5a1f44d53a4341ad0c3c0837b8a595932efbeceba6bdeffbee967e474e173f99907168 +9c1a7e23255d793557a022726053b5bdbc9c333926d714ff8d6261e492df9c905dd66dd1b7e17e +714a44c1e073deadf6a250b765872bf96e047b297580c27ad1714d8a2ce93346d0a972cba8bae0 +26bc1646f8fed5c9a3366e73a2a65fe7fbed4a8447ba4cef3f25e20eec13f5448dab2b1768be14 +a2f1fe90117079de58883a86e7759a3f8723901e70ed76dfdab6db2a2597f3cded02e1418e33ef +2fc5eb86072ba97db0b4a87bf21354eb8fa680bd07fbafcf8cb2fa44a9bad1ec8d5692b12a0390 +e550e272449546a95aea075538359df87234050bf5b6fa86634e628dce90f5947772b834d3dcb5 +bbfef9f5faccac5ea302813fa76a0c7e8d4a6904110e7d164fdda1f2f9e867052945e5697f3e7b +3f3e44a159fdbb940d942c43520b6760dad2d26e5568604eaf88278a7842315d062bc8b723d19b +35d5913264c3313d68f88a1f063d0c1b5d51296c7c2878c5a016c6adb672f6148ea484b4356477 +94900efc313ca6fb90d3165695c194440f715875b1817b511a9255d75a7ec5343baf3115503e2b +7b7550688caa306b175b35f1a17d821f4168e5f8caa50058e5700eca8751c8446a91c1ef58e6d8 +de3dc3d7f89facf39e5063c470f80c7d740fc48d67a51eb34adb4bf49f04166e3c8cc5edba3268 +4d760cf5de8e3b15fb7c922bb6866719f75f5e4b35fe0bcfc50117e820a707a9d45377bcbb9b50 +57c58d4d9ed248becb7d749ceaa982166f4e8fb3617654d46da66f2766ffd0404adc348bbe5cb7 +8623985f7bfe0b05c802f028d9f4a944f3077e85eb1e953656f07be40f600f17273a582064e98c +77b6ed4f49b086e2e83e8e7dbe8cd9da174b49171822ca13ecd8ed6cadad41e56bae142c7ea81c +e7041b17ce25ecc4e7b836a6d2831da602b8e74347810ee746cff2019ac296c137e34d2078d6cd +89d12714fa8056c200294b7d43a678eec4b09c0dfbebc9899763b21f281a278d4a67701db89d78 +6acabde84a78a9647f68ca1f1d96237ba5496e840c270c2dc9320668eb83864c340dc520d9de1f +6c6035efd0273406a14dba72d0d484cf006f559c114020aca0bc9e1822efdfec07866913956d0b +f90c5b0f96b6c17799153e59603fb415cbac3aad5512eda753de8ea7b4ffe9135a8c70416899f5 +b6d1765b03acac1f8f970bf2d937ae6bcb694dbd3df0db2b53fcfdb8eedfbc7bb80246f7173b31 +93c0fd9bb5c1f2c3b3a9aa1b4ea166322660dd848c4922fa4fee272ba1ae64beeeb19cc875b268 +712aff8d4f245c2f081ede4e619321f341b217198e7a7b6b39b5a13807cb970ad03277fdbdbf29 +235c600e20ccd4d4153a4601248829f857509717222c2c9535e05debdede4dade6ddcb343c2e71 +5573b2182af3875528120b42dfda773ced4e091f4e99fc1c8f33832569adb8233c781b31ff3786 +8723d053307300f1e113e908473fbe39ed75a931c290e7efaf4c89d4cd22f63852ec30831d61d1 +de3815a6d18fbcd15f28eea75ae50bd0b237e8cb0870cac5ddc13da58dbd060d3193fc92e6c4ce +f3bcfd81ce6b3679bfc5855796cdfa8a26d63a659a2ff7a1a7e318a7f76ff80e846a2d647d38e8 +27ffaf54bd5a9221eeb416a475eabf4ef0409b1ca55a851c245bf7207aa06f542de6dff18dedae +45ebd5df41c9716f9f265e0f76ff738e8b1365d83a50d5e6ec8124003f416efe2f6d0f7804ac7c +59f19265b3d1d20ec202d2a8f04cfaaebcf61da57b1dc67a714a16a2692ba82c5058af93c2ae5d +9d1f87b638c5b191eb96bd1ccaa8346e61cbe333984dc3dd511d8a6c7cecb703091db94f945ed9 +aa9f5cef4ee6e65728d65bd56370d88626f7977aad94a80d9ce029be0127d82d914e3503cda7f0 +2f1f10f5d5fddc58499a56677e07c8ebbba19755c85371fc978acc41403c968f31dae2cc2a807c +420f78ae06f1eb78c02aa524ca3d54da7c4032973af33a9b3687e6209809db9b2a02c9a43b4b6b +acb138c94f101628a488984264b26069f0c3f490bce8c60be5fe2fb1681e7f6aba02a96e79f789 +d4483cf1ef9aec40827d1717a5d52099b3d37fff5fb7a7f7902f9f79fee2921e47ede6f1549f49 +4833302ff502636faa2f03691b7dc265318adb1270f2f506d01827fbb788948216312c7b2f04a3 +3fa660cd4e719c6f9bf8e33782cd0c2db36cefbc3054ba22f40f1428d99d708fa916faf8318190 +b5ada93e38870516efc6416590575d8229c581eb481e9a64b06cd05e0051d4683aad0c79a953bc +555395eb2ff16731687867d9ef0c09272ec0f7939e227f6ae6f206f9e24e52 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark + +%%EndResource +%%BeginResource: font CMMI7 +%!PS-AdobeFont-1.0: CMMI7 003.002 +%%Title: CMMI7 +%Version: 003.002 +%%CreationDate: Mon Jul 13 16:17:00 2009 +%%Creator: David M. Jones +%Copyright: Copyright (c) 1997, 2009 American Mathematical Society +%Copyright: (), with Reserved Font Name CMMI7. +% This Font Software is licensed under the SIL Open Font License, Version 1.1. +% This license is in the accompanying file OFL.txt, and is also +% available with a FAQ at: http://scripts.sil.org/OFL. +%%EndComments + +11 dict begin +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def +/FontName /f-3-0 def +/FontBBox {-1 -250 1171 750 }readonly def +/PaintType 0 def +/FontInfo 10 dict dup begin +/version (003.002) readonly def +/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMMI7.) readonly def +/FullName (CMMI7) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle -14.04 def +/isFixedPitch false def +/UnderlinePosition -100 def +/UnderlineThickness 50 def +/ascent 750 def +end readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 102 /f put +dup 107 /k put +dup 114 /r put +dup 116 /t put +readonly def +currentdict end +currentfile eexec +f983ef0097ece61cf3a79690d73bfb4b0027b6f3b53cc32be64063d04d328b49c17a62c396cfc8 +17b9fcb732c3b0aeb6264b2a70f62fbfc397eea8d069af80a71b775145f9842057f969d124e630 +1a760710a5c51e8981851fbcf7f1cd1f2ab78db91af2a6f264e41cc2cdecf450a3a33c89fa447b +8bad4068cb8d7d37adaa4caab8f72cc26b024348ef8708a0ab6ee56d73f035ac9b506c91fcafc2 +40791cc10b1b0ca42c87a24a69e83f61a20432744f7d79437b93825d955cee80718831f56e0254 +0ae4b3a70b9dda35ca4fbcabfbc50a4cafca7423203e4c32daabc53c5c9176259f5577f448eb04 +19fb1f995e26b695448ae1b5b4698f36e180b5f489925f090c8c7a950833922d9cc464857975f9 +f32ab824eff4584575cb2826051232924d9d3e7d73ab1273b03ec3d7c9eea9c8a55c4b66336e32 +d80401bed0debc4f965d6c4aa76d4db6713674f559788557528b2ee7e9d12075bbf0dfd327b427 +c101a932de4f1af17b4a7afd4bfd1beb04a9e165fcf9eedf112b614313b4f4c46fd95582aab8b3 +3b74fe33bcc6ce01ae4606b8199fe9e9dea40c8015c3bede3f77f31b2adf122ab542d86836f94c +683abb9ae9991ce6f9e36cf35acdefdc4618476fa5d49f444c55d10e052d62602419dad387d129 +66efaa68a6528aca9fbc2fc910db86d1482d0f54a60c409b0f340e130508c53b822d1b76997e86 +71be9537e48c1e20e3d017f40b7409141c88513ea8734a87c69af3f669e1a52367e9fa052cb5fd +31c984f11cc12432b596d9b851b87a83e10c2e201f0a98f929fe90b413b810ebd4b6be0e3354fa +249805f489868081c5d5be0739aaa4adeb88cf98457912778ef57b46563c1154c684f5b8b3ba96 +efba33ebd798baf4af3ea237690644943774eea53399c49c0a2ae78004a98b9fa3149e5f27392b +79b585e22946ee5853d5b6863d344ed72fbab2da595b54177a867a163d0f4fff1831c3d589a918 +47b2d7da4e7c1de71b807c6cbb21a7216097213a1b417d50ba3ea708bbf8197adaace2cf367f56 +34cd5be3224deaf75386e9c177f6894354a0f56d0bb788834eb4e9c12c9912f12321e17e70ae1d +eb9ebcae20462aa03fc8f6e4967a7143ab30c947146588722758be697bd10ef2d9d0a7f1682c89 +57b68f995027f1f0aa914a71f3c80d3a9cfa6e1678b4cb851b1543c3b681551c51c324b5e98004 +5ca101e13d69768ed2249ff39e8fdcf0f33c7d3dc9a9d13d24a98d1e4d79b73c34b15986ffc4ee +b66f9001888c4f7e4c43da890b62bc085171800787200358a12bfeaabbd8d18213fe827e2aa58d +1dedc5c11201b4a1473055bdf6f7afcb5d88895db6feaeedc0b352fcf1bcdc3cfec9297c347d5b +a699075f075d57d8fcf2bdb673b5980e89d31e497e38287c2dce8af698c74db56c87f8d5b5366d +2f92bf11cfdd814c1f90aa167d55274974bb5462c699505ea4a3c3f655e4010900cb5b7c4b9015 +cbcbb0426692a68dcaac3a9c935a2ab5b09b2afd24c05873a6a994ab78e1729b07e2fb31f1c32c +13e2ca8b46d24924f79a421f09594eb51dc155b86954b27ef402e2c2b398e876f20060416c4342 +38e69201f4c996fdf829926c5b66eb5beadfcde7654e95c827c7bc0bc07eaaaf3c991751ec1568 +e5ac5462b00c4caba3d09818dbad987d072147d3b7cdedd924472dde17d7fca3fc451f4e2a1176 +7370a463d6733e2c22bf29c23540e797ddcd09996b170945a2ee198991b487af6790303b808d92 +b6ff7d79f94890e1b8eed22410c62f0b7c9558543074a2b0b17c398ad692a845181dab820b2a6c +10818b77fe742ad060e7adaaca5613903f560a5adc9d3f91666dcad54958f402f7e9315d9c6866 +03779b4bac622c66f1b55ba1f089e7a5250bf1af9d97928aed8d255d9d777d6c6522bfa89a509a +b3d62a94db8a5e683838f03d035b233c9bc54f45d36679103ea250971d8a0fb7caac1eee9f998a +00d699503e1901f85467652a3f600ce79152fd73cb9c8b9cd2cfa4ecf1ff0cc0b6ce2d74d2050c +3a882090cd3cd026abda7e9a0fee819d2e72415ee599f884e09a98f4d61312f2a18eb40871ddd7 +2495c517fc56a41aee6a6b63f27524c185a086140cc6aefb66a85851e1ae975472741e15d5f0a8 +9abd0055f02438574d3c265ef08ff95a0a0c242539d3a4f823bfba37f19115609137e8d41e9771 +d0d159f9fa9d8bea4ad12329fc048f9b878f80e09e6f0a602ee1898d518ed8d3f5a61bf6bdc840 +653d9f3422896e05281332ec9a07760ef4f75e925b32630dfda0683a4ae6cb13611c17cac78c03 +94493e7c2abeb5d3cb24ff28bdcd4fb511220525474acd62afa3e66498d3e51be4c9cdd9e68250 +2f0dd62d89bc601e717ccc7d1471d3a12fbdc14507963a5c0cc980b67f5e0acbf1b752c52f3ca0 +7470e3453e44a12a0b40fbfe8da181de74d45521d9ba48731a2b4e885d5c01b324307b78904d87 +7e227117afda55e2eb038758fbeb8e20088ce203da1c6a14c700859b9cb0a3034fa87d82309a5d +3ff801773900a0072c385b4963a806bd3e1992e3e7dea99be56bb415cbad4280c85d0dc38ca0da +440e9fb1d2fb817f10a0d57c2e452ae4b17b8566ba07eee03cbff9549218909e8b63923e9219c4 +ee2a8f50d914a0a4b960f4a685781966f7eb77dac76f0963eef5b519761014af532fe5e565ec00 +e4f97d80b9257e554f9c7638eb3bb17c2f4b74f9b0cb11f6c03396771158833b27f3bf417c725e +e606ef74f8095596f4a73cf0d219e4312a52d9c06c6ae8ec0f40d726e9ecedf7409128752f75e6 +931129f4dbbde68fd333c9f64565891425fa5d47d07dbe759289617d864d10acac1b5035cadb2c +3ddefa26fdd9dfeb3d2fdf2b3a4aae6dbc9d9ff26ab4eba2138fc1df4c2f32d32d1cf3377b65e0 +e7c06cb3101e9c2d151a6bc9b456a93341ebb19b4769cd684fc4c34e4c6da53523799961a47a95 +8422545d5c67c6edd4ed12d5c61dfe7b9e42836988de2e59ed363060482accc2a6a60a12c99902 +0d981869a21e1a490f6783a1777d0678debf8ffb6b32f34128b2d3aad6a335fddaac7103c46933 +a0e2dbfd880a775363803f6fcc8c96f66901fd4ea8402ab70fc1c142b89a6068e3d29f523994cd +819265669f862e19760bb245546871387529a04f3cd3d3ec00d322926d44205a40a9d57548cf19 +e0dc3cb2586a72a5e6858677bd742e8c1887baa42b8ae6b1f437ae8f300de1f4d8d1281185134c +beefbcc4c896702098c97beb961f1cb5e1441d3a4ecd4c490880dc19fb0df736069ec3a72bd077 +93b9b4495c6a55c9692a0b21a720e7ccbba8650f3808b72283c45dfd7811f4d4e794d455a8451e +bdfe9fe294d14e2353ea9c00230c5285e9be7f32849decbff16451e79e052ccbf956383ad904c0 +9bd34a1c61423400d7cb02e88d2a908fdec9edfa90c981bd5b540233f737634906c7079e7748d3 +7e00cd7944c912311371d4189fda2b4f48645fb7914a7bc2563df97a7e431e52dbf105c33dbe79 +4bfb3efb203752d30889ce61e1362d030c23a32102faf1246a2ea80449b6a3c280835552118b20 +24a36dfe7e793ed933a675c1dfafe1de9e29d3aefb9d03195e45380ef9abf17fb624651ce0dfe3 +4b72c45d688e631b355b3fbb5c50811128a7480c0686f17e651b9ff6b869e342d882b1f216fc13 +590cb94534aa78687ce45e6d78e79ec0d5ba5496333b0c522afefb1b5dd43e468148ef57aaee3c +00ab23ab9b0d0c5da336bb363d432360f899f9dd433f84e80987c60c8091a67c4fca76db876bff +181bb618327e68c061308cefa0a3e5a794924428796f0163e4370ec3cdab1ad1e1e9041d4cca8c +e250f79f5e48ce29605c0f37c011de30599b77345accf491538336847d17d71d7d25be9a514bcb +b427a4911f963cb38eb317e183294002f8c15313e89f584a9e8a0ad7f9693f14e29b49eca94b67 +8ae0fdb4cc64ffbaebe2aef08f7d8d044a81d98056cb92b8c58e455e878493dd97eaab2b7f12f3 +36578cbd077d4943e10468a24678002c651f408e40dd6b27c32015757b4243215809df1a223cfb +6fcecca001031d668ab13dc924a14998cf2a56f06870f724921f5ebc92ef3611cc1672298fd561 +22a71c59d995987d736ec5a23f04e066ceff6a0dfdf2e39451d8643b426463d2ec42002828ad8d +230238c46ff88e1abdc857e3d836418b59cc21e9353c43e98f755f1208871d13e3bd1fc78c0d69 +0d32951099cc3cef99d26166c3f46a5f14b8c9cea1d798e5437c34ad87f4ea4ee8a8c832adbb78 +52b95dac37b3d133be93caf47b6b23fed161719a0444f1d7f7487b101a90a5acce95a06e8e8978 +8ba4f034561eb96018c32a35c34054e2746cafebfa807a77ab4b3ab095fb1e21de1c5f71c91d15 +393d7804e19f69d62fee85f48769cce52811bc991bccaa8a14caced77742c70a9ac72bbee8402e +ff12977aee4baeb2fc4415976ba7f82d9f00037c860a6c4e30b9eaf8a41b5af69d9bedda873c02 +2e46c8e3a9d66af691a39bf46911f16918d7628ff152a81faedddad44d648ddc176f656d215f39 +9c8c4958dde6c82ab15faa3988d9314d5fb7e4d2bb074e9ad8d64327ffc3c6e011bf1fa2fc7ac9 +0aeb9eaa2379b6584dcce684e0aa4be43a45d52fbd9e53920feeb0d6853dc2570d806cd85f1200 +bbad372aab1bf230c5564e79c73b032deb1c22f93b43c35d9540bde9751b88e1bec3f0e1d1ffa7 +02b8e98ef393729439e8e27b4abe89baddff4c24ee142223466c27f3b93f001334e262b3fe6936 +49ae6267977e48c8edb4c5ca6a6fa9c6b194aadaf1b7a8f90ae088a10986718b8cd7e36ebbe518 +94e43b2d82449e8cf3079bf3f819dff89421281e3f54526f0d67f6ed9554074e053579bda748de +df79471f3dc8fc2b3e83c91c77f0628cebd119820345375d442e38cbdc2106735bc44f8fe699c0 +2c8dddfe10ad9e44e3f3d1f01bf547396d95108a7338177400a1f5473cb7af7ac4576c67cd57c3 +a7e74e1fb22cd9076dff26e73c9e6f3c6b7205e4b4fdabf8ae25ab2aef0a35df4cf8d9eb5b2202 +770f8ac2fb3c40161ba70b4e25fce3fc0b3592b7cf3df1ced24dd84348fb5b81e8fc47b477e9df +9bd2b8f3a7354086ea146ccb66173d88a2bbffea215532d111fcd25e8af065e3cb03f527c0e46c +34de39e0f23946dd366e7c8f0bca6816e9e2ad2ffc4a8c31d68a57158d67525410d1ac390b88ab +48efe2f1c35a2fb30924dbb72379dd1ce2bf19c33e47bbf31c852dd2e7397895fcead90e7272cf +cedc70bd1808be257d7fd10282ebe9e5cebe3a9ac2a11695ee0639cea8085e02d1792db3643b56 +20c6b695d459f746d38af29611e0610ca79f9dd210714bcc89b4ce4528206e4180751bb47d22c7 +8282d128e1630201979413c3c4657eb33aa9773fac04fea7f8cfa3c89308fe3c07c9c06ed77e75 +da768d2d838ed2a4bc6193595c75a80d39be25eae60260dbac7d2ef6389c00d5ab594cd59604d3 +878cf6eb6a06dbcddc24ad287d087f661a846a667d49d1a7dc1a0064cd3d4ee6dc6c38117a0859 +006780828a819a2b1c1a70d520240e2fa252458696fbeacd3bd354caa3f8375bc24929ffc6694c +4b5f9c52e41c21cc1ee94e9b9855a9d5e125f11c75cd996fd31d50c0d8971222a6a2e67dedb190 +28969044b666572da630cc3676d5ce3f79b2f993ad5a90f59a4c884c5ee8d0feebfe5ad93232f6 +87d6b1536fa58be36acec7135452b34dad37224763b48be692ad3dec8708af788500cb89dbe073 +75d66b4fefde33451365fb85d8f4c3410aa458bba8637b6679f356087219dd76567ed3289601d5 +768ba93d4fc46708b36040a353d580c635b78114e03ef8825972e607deede379f4086c75d7e380 +9af3df3d28d10bdf8e89a187a175f0ddc8b552cead06afae309dfe2d1f50a7ebc526dde3abc0f9 +2ebdc6618374e63f0eb99ba419a9b8d7fc64b9859a1a37c006e0449aa8db8b89730348c71c7e00 +bbb2a5d61e7614bfcc44fa74b79dd789d9faa0f0c3797eeac73df6c79992db6925277bd3579f68 +a30edeccdc6f2f9fc811b600fc65856a5ec970e9c94f43b439eefa923cbe7b85e1400375502c75 +738f14d53d9a1b182c007cb2ecb23db28e5fa8e1cee1871accd1e8a1c576c4ef224fd77bd8bf71 +f04dbf0e9481b5c7f1b97a57d42edfc9335204fbaec1d459142b9a652ada01e8d0501066695526 +ee3687249a003d48d3bc42a59602128a203845bdd5359aae213be3c7a0b34f5bee840624e44b0a +e9b6a36e63e049c048a7e2d7e1e9b0c4323963e288f07b161ea8527b7c0997e89917643c5e9b74 +a68853db9a1815f49167c3b04b2a85ebb8e9f91148025651ce03ee31870dd62aae83715b2ea525 +f4b8821506d5e1dae2727f2e3554a9dfae92ff30b1a1d96785355e338d9878f75c601979758161 +53ec1a941f674b24d80bb6f8404807d77614171ed0aaed43a14c54cf81acd74dfb40b2e2a4555e +7f17dfd5d18bfc73a9143396203bf756e4f88808d0bcf2027504927a38ab6b63e82c2e5208387d +04ea01ecf8c190e40d05ca1e91138e332a743500b69912906c0a13beaaafa801a8a17931c47ed7 +66d49eb017b5467ec5823c68d135cee848b830c0c4e6b96d4560e5e1242dbe87f60310aa906622 +7fc10eb1f35c344fd7e8b954cffbcfc7c9b1ff5eef179e29d7ee3f3bf63834d5c19bad23aaa4cf +a660091594d228a347767af9e57b0c2c521e1fe18bcb271e899d2534f5b62de75800c9e1074666 +a85fda8f762f38c8445f259070a6d6b6b2209b77166ac471118bd2c39d228007d270fd622dfbea +29cdfa2d330c8fcc4c72eaa5771056069c831ea95b52172a4b8d136f790f27266b67a859ad2eb5 +cf5a20b6a39274baf31e02e1c487f59ea0ad622dd509438c43a4e110173268195db4b49c02fd6d +98730be322f0d727d42252c37a1b907453b9d7e789f0e1499f3edfc44554b541383ff294df1058 +a9164ed1c453cda563dea3c3fe95a66eb02f80ea4b7e28af9238176e2beadf60addda4869909be +700f2eb0d73de20b65c2e0cd2715350c4cac15aceec0a0861028c4a0f5e6b18ee47be415d88bab +fa7f7e9c6274b1a72353b128545c8955b6a61fab002b95cf69949c3beb283a30ac348e5b25476c +ce03aca0cc4a062d66bb985378da7fa79fda0d46eeeb6b792df37d9cb9e10d51bfa3c9570e33e6 +8326824e6c180c152b82545b2465aa21ce44006a5e5d986a4ad27d9eee3f9171e12294a0cfa034 +343a7ece3617291cef7c8d1591109503311c24170544c96f0bbc68dee4ae9c92ce237f94228d24 +ed46e254967016d46398f3dd645a352754015f757c913b5790e2c601f75dbd80c78f6adcd07107 +08ee348d11a4b2742e40327ebecafa44d67969eacae402b808b40f482d7b8d14c29159f0646e3e +1100cba1674478062c89801edc767a5da780f8b6a9eb941f550400895f82f1a1bd6e0769f17bca +2e7997d3a9d2a27997671791b780055211094c20f718245d5752e8364e924303f18abc6e27b983 +b2003fba4de22c818526665c3cbcc4dc65b35d61c57f851fed9b4aa7f5bc44458369cc0ead6ed6 +d1c0999e42b7f730083986f42915df5ca58b9d9a78ae9b70eb8454c834922374f26faffc48a938 +450406ceb976e87ae3d00bcf496450a4701c7784474d381791dc54ee5073a287b4d31616a822e1 +25aca839f59427abbdcdc3fe8226c3366ca1f303e16ba85a3f265b7e835828914ba5fcaf6cc00f +92bc86cbeb0e86503d533ce6dc487443f08102feecd01ee1425bef03bfff4152b42db3bc1334ea +5e1d534487cbc1f5abfd954c88c94cf3ebdcb6168565d4b026c0afd5f3eebc6f06e7855b4c847f +33e892d235e0b4b5fb1029c16fe8a1ed66ab8c00527ff9505c34982759c289c8fac60d941c2768 +d80733e4d665d512cfc9ae765b71717c6343b51553790303bc2b3446b562b2f74ce4b59f9895ec +df597bae4d4700a54726d906483c64557b68891869c430249969238fc881601b9eecd1efe20d24 +90677c7e3646fd697fd45e699a18ce39b3ff85ad7fdc46fff208660ec066319191d8b164ccd54e +34be121e0a5aaa3807f3258589761269de4e91cd3808e78e8b25a94b4dfb298c96f01f0674965f +ea5c3af623b0742ed3d23436532bfccba6d75cef13a92ec15dcf927eb683e41ba804c29f40db32 +fa600f99dfbbf91143da3b73f31e2acac41e7a2d9c3c669d62ec700a5347184db00a44ebdd04d9 +cea530b9867d484905156435e92722e634b13a9f89b86758644e0e98a62f05d7904c1757eee7fa +ee31d6a4f71495850302c7a0e32d47db00aded49efb7fbedee0aa3ca1e2bd7dbaf99bada3448b4 +ea1b8a3e50a9f54594215576008e173518954dbd2c212d2cad8049d6476bf2e25042e8d0f7bf8b +a39b94b5b44c8022ff0b610ba030ca127ed7c7c54ca4ac857cfdb6e8afd9ee5874b55f06f76a92 +ca72798785c12960def32f15cd6f52b075660eaddddd321fd32bf547cbdad8497340fdc42ebbb4 +f9370ecef09b0efd2cd0c526faff4bfd1bca4575effbc152748094efe52be7c3c7b2d6b329ac1b +49ceb65069d0b8784a17050a2fcf44872c6219d8cd19512429a357046501087a033d940321b39d +3bfa91715a50673d3894c53a6a0777fc1ac976e80b9ee65fd08fa6c825f24eb1daa1659a831866 +61a8755053dfc027c47c898e0f63b9e1219db3c3f8e303919373dcbb5a277ed402286e4474a69c +8192ec0a82dab244253b8fdb8adc1b9ee1d4e809b53cf518909fc00482ab24f91409b60b9a58cf +9bb1acca164c004fb393856baa075dd5d2d2dac38a651c6976d25c138bd715d4f3f2fca4ef009e +e31b3e7649fc71fd8d496f9ab028a0bd129c07c5e4e57e640741190f98000c0d03fd83321b1014 +67b3422e452df7b1bfda8eedf5d108256af342516b9e32e904698f1840819f619c9dca0a9bcba1 +e3bf115f49f7ed0545882a5af4174a33f892de5c5c04bbbccff9917d8eed5729e642ec5ebf60e1 +31ed9ae9ae5138fa5532347cb99e5722d25796d8698bc46c3b0cca8ed8b856b903b0c55510f33f +8a4cd642b958ba51377909b425cb40432de7e05f9345d85d6e055ff796e806d884c6ec2e761aba +907867310bce95d1124e9f4ee541c6893f16d80908097722ae684066a1f73b613c5409822df9e2 +306b9951dcfffe4e9c5f7fb835b2afaaeecfccdee012499a2e4fd9fb9f74b3ad165bcc39dd6b76 +db7abf03a6a25a4e34718a5a13ac381a6e983112896068e1c0dc4c4b748a758e934325becbaef2 +00efaa5290f2f39022778273905e74fd97caf3be6884b9bc3e1c51fef0f4af3bf71339e04420f7 +b6f5 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark + +%%EndResource +%%BeginResource: font CMR7 +%!PS-AdobeFont-1.0: CMR7 003.002 +%%Title: CMR7 +%Version: 003.002 +%%CreationDate: Mon Jul 13 16:17:00 2009 +%%Creator: David M. Jones +%Copyright: Copyright (c) 1997, 2009 American Mathematical Society +%Copyright: (), with Reserved Font Name CMR7. +% This Font Software is licensed under the SIL Open Font License, Version 1.1. +% This license is in the accompanying file OFL.txt, and is also +% available with a FAQ at: http://scripts.sil.org/OFL. +%%EndComments + +11 dict begin +/FontType 1 def +/FontMatrix [0.001 0 0 0.001 0 0 ]readonly def +/FontName /f-4-0 def +/FontBBox {-27 -250 1122 750 }readonly def +/PaintType 0 def +/FontInfo 9 dict dup begin +/version (003.002) readonly def +/Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050\051, with Reserved Font Name CMR7.) readonly def +/FullName (CMR7) readonly def +/FamilyName (Computer Modern) readonly def +/Weight (Medium) readonly def +/ItalicAngle 0 def +/isFixedPitch false def +/UnderlinePosition -100 def +/UnderlineThickness 50 def +end readonly def +/Encoding 256 array +0 1 255 {1 index exch /.notdef put} for +dup 48 /zero put +readonly def +currentdict end +currentfile eexec +f983ef0097ece61cf3a79690d73bfb4b0027b78229ecae63571dca5d489f77bdeee69161ac65b8 +1a171acfec6a38e69dd162ea7d456fbeadb28c016db3bfa3a91b731dd3d89e31936de5e0ebbee4 +d9bf15a1d35b3bfa43ade27c55337a53e8117722f41ae71510be6095ec8fcc4480cf4d4b3c8a65 +dec16f24a875f2c200388e757c8d066a3bd39db828e62e2d3d19908b221b8f5b58f7a6a2ebb901 +d705aee915d9f92114c59f6a9124885e77bd754ad8dacd1e7fa44ef6a4733c0ef482d5f4f7788b +0d58fe7cceea728243b0a6d07c975363fe2f68dc10b074265887a0fc21340f56f39f120ee55250 +8e298a788ce801177e19a376794686e84610dae79706c4403e70daff0206fa975187e5a396384f +0737e50b76abf5edb14b3060d7f53b7cfddfe49b75c6dff02ad1293bb8ff494018ad774ba7a7dc +e1ba6f02b468a1b2a3e4e18e7771d797c2e4ca9ddc34061c54b2b2d164da7ec923ddf81d85d323 +9b066896d85b0bb67db8d71ca7d331e1b23af9f683c1436aee05570c1a7068d43b86239b3d64f9 +c541d8a810500014b4ab130e93e9661576ade6006680a3608552c7bc09af195c022d8f7f12b008 +292036785f53a56509e793c70b125a7a10cad6f0d082c65743efd4f32f21e5d544adbf0be627d3 +5b1b93a14c80df0a4be0a1b654a877e5b8d7a2d86a7f75990b6a981812b08e9cf6d9df240631e4 +9ca0584bd57115a4a23d2940327ebed6299995397808bacd2566154a0a1cbd25372ebf67cc513a +413cff5f44ac11fdf9dd4c55f0e93c91293fdb3644e3defa308dceba74384c628b51053adb3777 +ec6c08f2016b383beba5e9a097a32cb46fafcb544b68e558617c6046504861f33572a5beafeb41 +99f4c805dd2554d818702a10ea5381c0f854bb6daf4348c689c16092cb0e6a20c7832469c98315 +a26e8c7f31583db863c8f43c7b51b197bfdf4624d1051e08a0dce2e8003cc8741b73677cb94ad0 +6194c473a61900f0067f7147ba1dcbbbbdc54e7e1bb3f8dae973e48374dd794bdf85dc4b67d024 +87bb9452c35fa1a54119bd316606ad39bb1abd0fe379884eccdc929c06cf1308945304c3d9be5e +83ce75f1f22bcba2c43281abd11393ce33fc4f08213b6c534eefff62fad7c51d42542335727056 +0eb4d239a99148ad18c11422aeed639cda0d7d3b32b98b1bd0e315b4b0bb69ffbfac125dc4e878 +00053f63d3c7f9e31dbb1244c43a5e266d3f77726fe49f53ff79f683ff30978019cb1f13992bb2 +15a8f67722b1c17ac3c973b097153f3f1ff46ff65e8e6750f326afc4c3408d56bd80c2be341243 +814e3b51e576fb1d3d5a16a438005ec9daf6c841dea703938403c80237ab8514d4e11839d7f4d6 +13dadec3aeabb0d2a7eb9bb841bf4255642abd2cbc61e9df4e6b8985cdb4f722dfaa67e775bc81 +67d5506c6d8a7d8c5db3b4b6f02e977cf02ecb5ba18526a666640b6377e3f88cdfac08204c2975 +3c6a799e86d8fefe2e962220736dfff77f2c88029606468483d77a27e70b8683ed95b2b6e14775 +72331a6030294c172bbe68b2c78e7837d6f9b18ba86d037028a819709a03a1ade46fd4c912d4b8 +587f0356bb53a42992c03158a36ba4b9456ac0b439fc5d05fa4ffd91d230ac57dd35797b5591d0 +cfbebed15809d5f654f3517f6f6427885669d0fa5ef9691ee2048cbeca73e2f48a59e54c609959 +4827ccc991023091dadb2662a6aefec4401536876f576daf1f1857bd5ba15b24b8cef3a0e7c06a +1fef4d9db5f8c271f24d0ecaf5a88c326071ff1ebd4cf11628456620ad608dc4379c18c6a6b4f9 +a7f905dd95ce541ef16fcb0a26b7567eb48a154e681c948f4c2999cfbe5ecd92d9b5f4b56228f7 +4ba739552958ff3fe3684393ca3c1c66ebf0c93a01858c6415bbf52d5345c03cb0405b86983b16 +8403f60760959d07d556f96658cd17e3e4bd1570281b32c3ce90baa23a13127a483c39a63b8b72 +1a953cbb13e0348f217a384ec17e41654f38c4750c5c20bfa9c984bb5c105bfa1d89b7f06140c3 +0b13f053bd72a2920680c1d007fae4c6466df7c2771321f8c22aa375e561807daa4297ea66e91f +3398dec44330942be8db61e198d816361b2c208384db56724dbb12281ffa1b26ac1c5a6e86bf24 +0e2ecbb55d83e21e8922b2b68cecb597cfe206232b325b8a00724b8897f0717b273637a0585978 +d91e095655ad507b914134de042d6f8f18a93be428983172e921d628ebfd54318f9694e5f6dc5f +3730a98e83cc7a1caf271e8d6526c739ea996b1fb3742ab2962c42277d52dff387c4a6b90bdfb9 +ed5ae7d1fdf4839952ed7bda493f7058dfadf674fdad1608fd57864bab0fcbf5a0d64fea1281f6 +50e1adb75b5da7169e258483109a8c343de9dd470962609c52cc1bdba22d998c2214749807a3f4 +8f713c84d61d030726d042a9c831b1ae232ebaaa301348542c76c54b4b446d055335453c74a1c3 +fa54f8f2a1152d322ad869ec20510fb81f744807b2e38d26c288a618c6d1a70bf44dc5127170e0 +384327dfc0b56cf424371bd119cbe04360d6c9325abd67cbe3c5a26468483a678caa81840c7f60 +f28f2cec9b83e65bea05899b96b3c4f251ec2b0106e77fefc28c2111d5719982378ed6bc8485f5 +2791cf0050d6fad3e14809900473c9b4e8fde806416543ccd0c9aaf05a279b70f9fadd47341801 +7ce35d3324fae6658134c77cbfdd21b9808b93470474858f7ef2a0ed218d8321230eea9e537c7f +a9dda0c53819dd47367e42cfb2cfcec0e8979c22506a4d505f6c0cb2bdd6903146a7442594549c +ea033224cb46df42e7b4fb0fa13a774bc554d7c3b68fc3dc99b225dd5a36ec3174a42ba2d15c7e +d8dc6599ac6ade3394600b2c41269eb464c4e05ced20db740b1ae7d865e728cdf40f2061ef9b85 +162d62301db6c94ce584fdf18746434f167bb78eef6be2ed49064575b13ec2e19a8d602f688748 +fc5df6835a5f3266b981f24ef03c4aca0ea5f526ecc2f4d8c2f6105017f67c1b393c2dc6fb7e63 +a68c91a482a2dd4d7c6f58263b73cb50e0581c886a574cdb31975427584e18e50d37f45319c000 +88d105a1ed7f5f2d5c287ceeb74051c3161e0ae68500abec4d907e6ee19be9476519189176af93 +026f82ad87427151edb4f3226db949a45f398b7a62b8f32bf77eb87ffb33b64a22a32bb4c6b60b +5a56cbaea0b08965c52c25ed0833abc52b4587459dc7b0e1ee7153f15d9e2c4d369a05abef2e6a +feeb8c9d31a3b033a662eaec78eaefbbce357f7cc31e2b9974719e970a9b549bd12ac7266c4546 +167e4ac4169532770137e533106a1ba4f4f3f578a03b0c5de2841496b614f6ade8e39f8e8bbcf0 +ca1e301364552fa4a6896072768b1c7de9bacc21fa88aa8ebe56ede420dd5c44b54d0d78c85aa3 +9989e150ec34e89fd362af149f340e1ee379a4d7949d587c51645c3302ef2524d23794e8f021ff +5caecb6540465fd71da7e25e8659bdb8c6e2febe3f128c945eadb46976bcaf202dbafc1ee9f643 +9ac3ad2fb2333211a06e87428076facb226db6ccb64eb60b4fc528e4531f0b0b86c3e890d7f386 +a1db6e72a7f362d4521426b8d8c399035f76ea0eac84132c9094064533d519a991a54db6e9ab61 +437d1db428d705b7dac182f167a64bb5fb94dbb581b91d9d751883e8e425910b4bce508b14a6f4 +1fc16fe4917dc4ab7d8a4f9cf29cd51cd2ecffd55cd6f3df503372f891be5c7106e5d5bff968e4 +776b750f91e5b88b7e1d0b3c597d2a94ad89538391da210d3c3db26f8657c3751e95fb0d6e9911 +9d581e16b53149aaec51aacf45458495dd7d8f2d3add67e521b97fc914d01efc7916f2c78a8150 +37b5ac4fbf8e511182d18f3bd967ab2de2b302a629f5b3ac5d84ccad8c36398ba5230fcdd1cce8 +3e52746722b8e7fcb614925f15f1c68ebaa9efe9da6bc307cf339baa9c8837daba76c8f64c69e3 +568de91f5b8bffe27bd8ee6316c015a1da7209614528ba692c3a0f44d16327f282d34e21eb53b1 +afcc0a8a3f3175e42cfbaf685a93f0584c6b52d9af562d3993e063499dad4ce315379a7a3aa807 +81def910335e1d0c1e1ca9e14580401fa21780cde5ab174b9934dd409ae9aef0594783a32dce83 +27460a05c88e1ae04384a0d4911b5dfc40e150293bbd4991a6b79c1327bf5f02f6823a3847d9c4 +5d13983fe7d193fe295747a08ff970e85c7ae9e3c851d8027f2574ac6020a06f50b47292082608 +95da8425a2ed1655eb7b31912918ee8b1ab297179278539ecac32632f7853b83d14d10edc97e93 +909da4868869d7b0e947c3470fd69b5460e30217c10cb55c460c801082820dafadb3d7bcda6f2c +b87bcf8eea71b3b73afbfb8600ecb4bfe0d658c1abfb521ae0804cdca8f43fecf9905a77fcfd2f +61e96f3092c947c390a83bc1c5f36d22b5fd549de540865e77fd4e23c981fcc606037a84511e02 +93c6eb04aa91e7295206c8d773c4ac4a241cda1dcce1e372b72766fa7e0c4d026c1af9a6404332 +0dd8536de5c8f397aa31439961fa1deafc076614b3b92cbef8655deb6cd47748c0914fff013ac0 +88a388cb719e013cb7346a904631e58f906251dd61e07d817e172879bdbfe9ef245d28acf9f017 +e3bfcd2e110dbadc02568f30e31a150ae5abaecdd756c70a9ac72bf56e54d10b5433076fe8cae8 +e8c5871b7a90f3b65e82e2655aaf6aa6270c5a8abf68d02be079da9061d37f57f401c544b7f43f +a0d2f42bcaa5177464d16970a3cad42f0dad07d86580c01618776d11d2e86b0051ebc75b69ddd2 +54050f40cb7f63b1240020c2cd68ea04d3043142cba72e182b6365b8d7cfbdec4d96fa10b5d3d3 +6dd3c49eab2001353c2574d0f608df80437002c26bfd5b5eeb6d3d2b30ee592046b254c3593e90 +96e9488bcaaa916b71900e00fb83b041e287b6e9b74f3f0de16a08d5b60b3ae766946194991309 +98af74bd8a53cb4432d3073c0065abfea0dc688019a33dacc2e6333ce0b479ec0ffcfd24990a3c +c682ef878d455d805724e0213726c099ab174c9640f7b64d6f4247fe665652131e9babd8f1daa4 +676e66fdc24d6b4c485b4edcea174a854b4061f2122db55d98ec279ffb5cdeb8f5eedf25ff1b23 +3aaf14b34e418f7ae40c71191bf35aa1057a4a448f419225df16c68f6e9e912c91563b18b98d83 +52e78e8d382b61139f6debf7bcfe5e19ea7c6f029258556a5f0ce687b0b4c13700fb8056bf9d05 +952de15e341c2e5cc35558dac81e472ec5cecb7d218ced5a658f9dda3e36c9d8e6ee28b48c16a0 +608c86cfb2bda589e128e9f4776f4128fcd785ef81ebb678efabbc85979e79f35d796d6b924220 +6898e23b32809415e181d1771290c679a0e31628f3e10e09140daea1f7ccdbd87c8bfacd1097ba +2194d9759796a3b9a0b8a2b938cd1500a8b719db204f9ce5201c319adb541d77d0f74e12209731 +a2eef25ef407643d418faf5448a7b891a295902b99d7950ac84bb12e42ddd996515c0d16e543b6 +5d3dcc601c7ec18d7b603feb8b975d4143d4579069ab86a6e4393786c07e9974cd3d5568c9c849 +48bd659cd2b91c2e026924487674ac4fab16848c2549c5cd4030ac7a790af2919dab1c78ddd772 +c70dde28251a9696aa2a6bbffdf9e30518495788c60ed9a28248b2baed87e2624ffcc770b6dccb +d101a447e95ed86581ac352ffb853332134a69ca5c0276ba3af752312e59b61b1abfda9b5aa219 +f8fc46dde55c9f596c37f97cea70cba7b2275dbb259f41a299a8bbdbc85cfbd7ab9b32d98dada7 +edcf145d7972d9cc7c6a9074786c0d1bfd1c6cfa7341ad3307ac6284680573f3dfc5d1fabb94ca +1618d8cf9ef72f0a0d00f38391f7c26e19fb06847d2e712eab385ebc0a4c31556b10e491e71bf2 +b3c70bd47351fc152b31b3a8582c999b0737d7e6db7bb175bd52013aac30719210db84573d7233 +38cf32388fa4c6929532d29f8a15145b97d40b6a5886a4379a43dc11981356a0e07765072d0820 +6e14db68501469a363e36966a9c7ca592d8f643a001900449cd0adbb7112bc8abc0de50f1b012f +3787de9bec01ef8da09d0caddab75246ab49aaa56f8648a1f8dd1f609e91b86198dedfd24dccc8 +661064d0bf68f9bda35746db4f602f04ef5b0217afbeede6755e0630c36a9eeb772969e25da52e +8755c7bb71888874e5e0cdde8f339638d943738178c43818552372287aaa0460f7034e61f13860 +a544a234b1f12add841f7f961b4984142fe996925cef18e1ce3c74d1cbeb0edee72d52412a5040 +ea0ef581a887657d817945b4e703ad7b28f1fe2eaddb1bdecf0a12b3f4633f45369a3a55ba0f5d +89b454d933abd4531a34a8cc8af1c4511d0b2f2a0ba4adb9b1853320a7c239270223e8e25eaaa6 +b4b97829833e04c4f96c6426cf48e7e9ccfcc573bd2efc8be07afe79ee8c20126f86807f266107 +81c66c0f355c0272fbbe849db7b20997c75d34b8e9b2f08d8f662042a2f69742da07ec93c3fd7a +0ff5372cd321960ad41a5e95507deef883279ab8643817c26ed0819d354d9c1a43466a9a43ccf8 +26752fe74606107c98c5c5ac29ce19edbf18d539692ae505bf8d017550d4a80df1830485cd16bd +7a3ae945b983cadaae1e2e5b068cbc1ac55e7d83e5575b8edd8d902a857c8ba035972b824c3fd4 +8f0d0894f61939a1883bc76927fae38f263223a26e3e750e865ff07b76eeae83619c65d39d4b59 +8081c0e1935fa65ba5954cfe99269c163e0f29504665c4aa5a52a94b4cdc9dad6892b8daffdee5 +d66b22b6fbb0776acd384ed33f3e77dc629e8f213843fde48bcfa2aaabad92935972afc54416df +ec545166bb0866a06db4ce2ac9e4cdf824eb31e3ede92d45f8e084291d764821838efb19b8a997 +4e13d88c3de3b81f47082de466570554f0169c9bfdc018e79ecfb9f0b0bc32f7dcdd8f2a066f6c +f59be2bbe6ec5aa94e2b21c8cd7e68222d1ef0fe1b6d395ed4049c503496f40f236b4b93a0e21e +2520680553859ca466c2cc99515580b2f9797c69ef0cbc2f43234080d70d2329aec93c25f3777f +8cbe8b299a3ce8d7769917cbcbd973748f13ef97dfe2c3e8743e1d8836c28ad2ee6d3dcc145251 +96eab6e439af7a4e35ba1b814da1047176e07fd8c1e7324b9b86d9305cc755768dcee6b8c58394 +4b9a1b7f9350aa1a6a2e57ea6280fbc0a9b19a31c50c23341c30dd0b05b989f09b8eb2d864aeb9 +1d441094bfa0554aad3ba8d5285809b63bfccff0e800ccf2c5247495091b79e30f83852eb7707d +482cc9853a0fd037ea49eef23d11d6062b771326d785c414fb336cf13b097ee43e966142ce8bdc +ad41a1ac7796514dbf700f48d5a3afef282ae4fc818abc0ac30a48cefb60385d9f6b6a7863e775 +1526439eee428dde65cb98e5153a7834c07c48c90272db1d92d200e5679ba966bececb4b773a43 +f93578db144bd8d4aa5e0d3b3a2b825ef680287f8713a93e3620bc63d42648de02469b13fb26b0 +641dde1743df42419c92101ba58eae5c49aa339a914a27acb704a8bb822e0bca27ca11e67f4bf0 +8d980d22c23f5e9852e2d5743a103f250de7ff3da117c59f63c197871ed781bd3214050594e514 +a0ed9547ec6cf8b1438391f0ad9baa9498860f4880e2f16c582c274d18ee6bee848ec731ced5a0 +58aca6a9a1f3664f30a710c0e8481c6da98ab3effbd2ce70e6c6848c9765d39aa8913540378a65 +675b3d7b5e89a0b2d9df600b499a6ae01486ab6875db2ba1593dda8843bb204052ef7b957ecc41 +062b382744979f0ff1256c838e93bbdd17f0ad907a3b62b5fff4541039d55286919768aefdeed6 +51a3e5db9e603cd08e094f4e4f63124f7c133e259fdd48c661bc11d959929aa7b88d7f19b4904f +b3ce49f48c270a1adf85a246b207246a7dc70c99b7db7a7f4daca8c27f54d9d00aedb5c7df36c9 +bdf01077572bff7414170fdc92ff8f7970ce5eef54a2aa6dacf72875a14b29d78a261d590f50b9 +4eb38efe5ce0e77ab149905b11ba173ce62e6fa074c23c52908c76364ca39d7c5fa400fd5f096f +e012d47912d89a2812baa355be421889d348c5c821c0d1a8ecaaa8cb3fe4ff4034416c03d9795e +46fcb0ec814798cc8b0bf5e0783f3eaef0e1624aa2596226214f6ed732f991d18cd0c63210397e +a87823598c9b616ede13c564039bca7b29c0a9bc72c39dca00738e0aa886cb4a5bcce26681ffc3 +2a15d64d2d402d24a799fd0589c3c9ebb88fc8115b83a4e1a517b7eb333c473fcce8ec8ab68394 +506aef85d6acf596909b587b850a8ffdfbbe1a5415b26f376a3d28b9e2e6607913fbd8ce3fcaec +e08d39c516e613a597b44bb4d22e8ae59e150675c3fcc94c4a8ff4769bb38a608f56bb2364659e +f2176e9149db57854bb514f67825af8b62b57d6c +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +cleartomark + +%%EndResource +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%PageBoundingBox: 1 1 442 160 +%%EndPageSetup +q 1 1 441 159 rectclip +1 0 0 -1 0 160 cm q +0 g +0.4 w +0 J +1 j +[] 0.0 d +10 M 26 129 m 26 1 l S +26 1 m 23.668 8 l 28.332 8 l h +26 1 m f* +26 1 m 23.668 8 l 28.332 8 l h +26 1 m S +26 129 m 201.641 129 l S +201.641 129 m 194.641 126.668 l 194.641 131.332 l h +201.641 129 m f* +201.641 129 m 194.641 126.668 l 194.641 131.332 l h +201.641 129 m S +BT +8.9664 0 0 -8.9664 15.555 5.163 Tm +/f-0-1 1 Tf +<01>Tj +/f-1-0 1 Tf +6.45443 -16.943924 Td +[(Crac)29(k)-343(op)-30(ening,)]TJ +/f-0-0 1 Tf +[()-349(w)]TJ +ET +0 0 1 rg +0.8 w +26 17 m 42 97 l 106 81 l 170 129 l S +27.801 17 m 27.801 14.602 24.199 14.602 24.199 17 c 24.199 19.398 27.801 + 19.398 27.801 17 c h +27.801 17 m f* +43.801 97 m 43.801 94.602 40.199 94.602 40.199 97 c 40.199 99.398 43.801 + 99.398 43.801 97 c h +43.801 97 m f* +107.801 81 m 107.801 78.602 104.199 78.602 104.199 81 c 104.199 83.398 +107.801 83.398 107.801 81 c h +107.801 81 m f* +171.801 129 m 171.801 126.602 168.199 126.602 168.199 129 c 168.199 131.398 + 171.801 131.398 171.801 129 c h +171.801 129 m f* +0 g +0.4 w +234 129 m 234 1 l S +234 1 m 231.668 8 l 236.332 8 l h +234 1 m f* +234 1 m 231.668 8 l 236.332 8 l h +234 1 m S +234 129 m 442 129 l S +442 129 m 435 126.668 l 435 131.332 l h +442 129 m f* +442 129 m 435 126.668 l 435 131.332 l h +442 129 m S +BT +8.9664 0 0 -8.9664 223.555 5.163 Tm +/f-0-1 1 Tf +<01>Tj +ET +0 0 1 rg +0.8 w +250 17 m 266 97 l 339.691 81 l 425.828 129 l S +251.801 17 m 251.801 14.602 248.199 14.602 248.199 17 c 248.199 19.398 +251.801 19.398 251.801 17 c h +251.801 17 m f* +267.801 97 m 267.801 94.602 264.199 94.602 264.199 97 c 264.199 99.398 +267.801 99.398 267.801 97 c h +267.801 97 m f* +341.488 81 m 341.488 78.602 337.891 78.602 337.891 81 c 337.891 83.398 +341.488 83.398 341.488 81 c h +341.488 81 m f* +427.629 129 m 427.629 126.602 424.027 126.602 424.027 129 c 424.027 131.398 + 427.629 131.398 427.629 129 c h +427.629 129 m f* +0.4 w +[ 1 3] 0 d +106 81 m 106 129 l S +[ 1 3] 0 d +42 97 m 42 129 l S +[ 1 3] 0 d +106 81 m 26 81 l S +[ 1 3] 0 d +42 97 m 26 97 l S +BT +9.9626 0 0 -9.9626 13.3982 18.973 Tm +/f-2-0 1 Tf +(f)Tj +6.9738 0 0 -6.9738 18.2762 20.467 Tm +/f-3-0 1 Tf +(t)Tj +9.9626 0 0 -9.9626 13.3982 82.973 Tm +/f-2-0 1 Tf +(f)Tj +6.9738 0 0 -6.9738 18.2762 84.467 Tm +/f-3-0 1 Tf +(r)Tj +9.9626 0 0 -9.9626 13.3982 98.973 Tm +/f-2-0 1 Tf +(f)Tj +6.9738 0 0 -6.9738 18.2762 100.467 Tm +/f-3-0 1 Tf +(k)Tj +9.9626 0 0 -9.9626 36.1728 138.31 Tm +/f-2-0 1 Tf +(w)Tj +6.9738 0 0 -6.9738 43.3048 139.804 Tm +/f-3-0 1 Tf +(k)Tj +9.9626 0 0 -9.9626 100.1728 138.31 Tm +/f-2-0 1 Tf +(w)Tj +6.9738 0 0 -6.9738 107.3048 139.804 Tm +/f-3-0 1 Tf +(r)Tj +9.9626 0 0 -9.9626 164.1728 138.314 Tm +/f-2-0 1 Tf +(w)Tj +6.9738 0 0 -6.9738 171.3048 139.808 Tm +/f-3-0 1 Tf +(f)Tj +ET +0.8 w +[] 0.0 d +250 17 m 234 129 l S +BT +9.9626 0 0 -9.9626 420 138.314 Tm +/f-2-1 1 Tf +<01>Tj +6.9738 0 0 -6.9738 424.646 139.808 Tm +/f-3-0 1 Tf +(f)Tj +ET +0.4 w +[ 1 3] 0 d +339.691 81 m 339.691 129 l S +[ 1 3] 0 d +266 97 m 266 129 l S +[ 1 3] 0 d +266 97 m 234 97 l S +[ 1 3] 0 d +339.691 81 m 234 81 l S +[ 1 3] 0 d +250 17 m 234 17 l S +BT +9.9626 0 0 -9.9626 221.398 18.973 Tm +/f-2-0 1 Tf +(f)Tj +6.9738 0 0 -6.9738 226.276 20.467 Tm +/f-3-0 1 Tf +(t)Tj +9.9626 0 0 -9.9626 221.398 82.973 Tm +/f-2-0 1 Tf +(f)Tj +6.9738 0 0 -6.9738 226.276 84.467 Tm +/f-3-0 1 Tf +(r)Tj +9.9626 0 0 -9.9626 221.398 98.973 Tm +/f-2-0 1 Tf +(f)Tj +6.9738 0 0 -6.9738 226.276 100.467 Tm +/f-3-0 1 Tf +(k)Tj +9.9626 0 0 -9.9626 333.863 138.31 Tm +/f-2-1 1 Tf +<01>Tj +6.9738 0 0 -6.9738 338.509 139.804 Tm +/f-3-0 1 Tf +(r)Tj +9.9626 0 0 -9.9626 260.173 138.31 Tm +/f-2-1 1 Tf +<01>Tj +6.9738 0 0 -6.9738 264.819 139.804 Tm +/f-3-0 1 Tf +(k)Tj +ET +[ 1 3] 0 d +250 17 m 250 129 l S +BT +9.9626 0 0 -9.9626 244.173 138.31 Tm +/f-2-1 1 Tf +<01>Tj +6.9738 0 0 -6.9738 248.819 139.804 Tm +/f-4-0 1 Tf +(0)Tj +ET +0 g +BT +8.9664 0 0 -8.9664 281.428 157.089 Tm +/f-1-0 1 Tf +[(Equiv)56(alen)28(t)-343(strain,)-411(\257)]TJ +/f-0-1 1 Tf +[<>574<02>]TJ +0 -8.9664 -8.9664 0 7.443701 110.152 Tm +/f-1-0 1 Tf +[(Cohesiv)28(e)-343(stress,)]TJ +/f-0-1 1 Tf +[<>-348<01>]TJ +/f-1-0 1 Tf +0 -23.197749 Td +[(Cohesiv)28(e)-343(stress,)]TJ +/f-0-1 1 Tf +[<>-348<01>]TJ +ET +Q Q +showpage +%%Trailer +end +%%EOF diff --git a/doc/oofemInput/Makefile b/doc/oofemInput/Makefile new file mode 100644 index 000000000..bbfc411d5 --- /dev/null +++ b/doc/oofemInput/Makefile @@ -0,0 +1,29 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build +RCP = scp + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +www-install: +ifdef INSTALLDIR + cd _build; $(RCP) -r html $(INSTALLDIR)/resources/doc/oofemInput + cd _build; $(RCP) -r latex/OOFEMInputManual.pdf $(INSTALLDIR)/resources/doc/oofemInput +else + echo "INSTALLDIR not defined" +endif + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/oofemInput/_static/custom.css b/doc/oofemInput/_static/custom.css new file mode 100644 index 000000000..faea178ed --- /dev/null +++ b/doc/oofemInput/_static/custom.css @@ -0,0 +1,3 @@ +.wy-nav-content { + max-width: 75% !important; +} \ No newline at end of file diff --git a/doc/oofemInput/about.rst b/doc/oofemInput/about.rst new file mode 100644 index 000000000..2fbd6c06e --- /dev/null +++ b/doc/oofemInput/about.rst @@ -0,0 +1,7 @@ +About +===== + + This manual is part of OOFEM documentation project. OOFEM is open source finite element solver which has been originally developped at + Department of Mechanics of Faculty of Civil Engineering, Czech Technical University in Prague, Czech Republic. + + For more information about oofem, please wisit www.oofem.org diff --git a/doc/oofemInput/analysisrecords.rst b/doc/oofemInput/analysisrecords.rst new file mode 100644 index 000000000..3fe17e1a1 --- /dev/null +++ b/doc/oofemInput/analysisrecords.rst @@ -0,0 +1,1118 @@ + +.. _AnalysisRecord: + +Analysis record +=============== + +This record describes the type of analysis, which should be performed. +The analysis record can be splitted into optional meta-step input +records (see below). Then certain attributes originally in analysis +record can be specified independently for each meta-step. This is marked +by adding “M†superscript to keyword. Then the attribute format is +``Keyword^M`` #(type). + +The general format of this record can be specified using + +- | “standard-syntax†+ | ``nsteps #(in)`` [``renumber #(in)``] + [``profileopt #(in)``] ``attributes #(string)`` + [``ninitmodules #(in)``] [``nmodules #(in)``] + [``nxfemman #(in)``] + +- | “meta step-syntax†+ | ``nmsteps #(in)`` [``ninitmodules #(in)``] + [``nmodules #(in)``] [``nxfemman #(in)``] + | immediately followed by ``nmsteps`` meta step records with the + following syntax: + | ``nsteps #(in)`` ``attributes #(string)`` + | The ``nmsteps`` parameter determines the number of “metastepsâ€. The + meta step represent sequence of solution steps with common + attributes. There is expected to be ``nmsteps`` subsequent metastep + records. The meaning of meta step record parameters (or analysis + record parameters in “standard syntaxâ€) is following: + + - ``nsteps`` - determines number of subsequent solution steps within + metastep. + + - ``renumber`` - Turns out renumbering after each time step. + Necessary when Dirichlet boundary conditions change during + simulation. Can also be turned out by the executeable flag + ``-rn``. + + - ``profileopt`` - Nonzero value turns on the equation renumbering + to optimize the profile of characteristic matrix (uses Sloan + algorithm). By default, profile optimization is not performed. It + will not work in parallel mode. + + - ``attributes`` - contains the metastep related attributes of + analysis (and solver), which are valid for corresponding solution + steps within meta step. If used in standard syntax, the attributes + are valid for all solution step. + + - ``ninitmodules`` - number of initialization module records for + given problem. The initialization modules are specified after meta + step section (or after analysis record, if no metasteps are + present). Initialization modules allow to initialize the state + variables by values previously computed by external software. The + available initialization modules are described in section + :ref:`InitModulesSec`. + + - ``nmodules`` - number of export module records for given problem. + The export modules are specified after initialization modules. + Export modules allow to export computed data into external + software for postprocessing. The available export modules are + described in section :ref:`ExportModulesSec`. + + - ``nxfemman`` - 1 implies that an XFEM manager is created, 0 + implies that no XFEM manager is created. The XFEM manager stores a + list of enrichment items. The syntax of the XFEM manager record + and related records is described in section + :ref:`XFEMManagerRecords`. + + - ``eetype`` - optional error estimator type used for the problem. + Used for adaptive analysis, but can also be used to compute and + write error estimates to the output files. See adaptive + engineering models for details. + +Not all of analysis types support the metastep syntax, and if not +mentioned, the standard-syntax is expected. Currently, supported +analysis types are + +- Linear static analysis, see section :ref:`LinearStatic`, + +- Eigen value dynamic, see section :ref:`EigenValueDynamic`, + +- Direct explicit nonlinear dynamics, see section + :ref:`NlDEIDynamic`, + +- Direct explicit (linear) dynamics, see section + :ref:`DEIDynamic`, + +- Implicit linear dynamic, see section :ref:`DIIDynamic`, + +- Incremental **linear** static problem, see section + :ref:`IncrementalLinearStatic`, + +- Non-linear static analysis, see section :ref:`NonLinearStatic`. + +- Dymmy problem, see section :ref:`DummyEngngModel` + +Structural Problems +------------------- + +.. _StaticStructural: + +StaticStructural +~~~~~~~~~~~~~~~~ + +``StaticStructural`` ``nsteps #(in)`` [``deltat #(...)``] [``prescribedtimes #(...)``] [``stiffmode #(...)``] [``nonlocalext #(...)``] [``sparselinsolverparams #(...)``] + +Static structural analysis. Can be used to solve linear and nonlinear +static structural problems, supporting changes in boundary conditions +(applied load and supports). The problem can be solved under direct load +or displacement control, indirect control, or by their arbitrary +combination. Note, that the individual solution steps are used to +describe the history of applied incremental loading. The load cases are +not supported, for each load case the new analysis has to be performed. +To analyze linear static problem with multiple load combinations, please +use LinearStatic solver. + +By default all material nonlinearities will be taken into account, +geometrical not. To include geometrically nonlinear effect one must +specify level of non-linearity in element records. + +The ``sparselinsolverparams`` parameter describes the sparse linear +solver attributes and is explained in section +:ref:`sparselinsolver`. The optional parameter ``deltat`` defines +the length of time step (equal to 1.0 by default). The times +corresponding to individual solution times can be specified using +optional parameter ``prescribedtimes``, allowing to input array of +discrete solution times, the number of solution steps is then equal to +the size of this array. . + +.. _LinearStatic: + +Linear static analysis +~~~~~~~~~~~~~~~~~~~~~~ + +``LinearStatics`` ``nsteps #(in)`` [``sparselinsolverparams #(...)``] [``sparselinsolverparams #(...)``] + +Linear static analysis. Parameter ``nsteps`` indicates the number of +loading cases. Problem supports multiple load cases, where number of +load cases correspods to number of solution steps, individual load +vectors are formed in individual time-steps. However, the static system +is assumed to be the same for all load cases. For each load case an +auxiliary time-step is generated with time equal to load case number. + +The ``sparselinsolverparams`` parameter describes the sparse linear +solver attributes and is explained in section +:ref:`sparselinsolver`. + +.. _Pdelta: + +Pdelta +~~~~~~~~~~~~~~~ + +``pdelta`` ``nsteps 1`` ``rtolv #(rn)`` [``maxiter #(in)``] ``lumped #(in)`` [``sparselinsolverparams #(...)``] + +Performs P-delta analysis, a kind of geometrically nonliner analysis, where the effects of axial (normal) forces is considered on deformed configuration. It solves the following nonlinear equation: :math:`(\boldsymbol{K}+\boldsymbol{Ks}(\boldsymbol{r}))\boldsymbol{r} += \boldsymbol{f}`, where :math:`\boldsymbol{K}` is stifness matrix, :math:`\boldsymbol{Ks}` is initial stress matrix, :math:`\boldsymbol{r}` is displacement vector and :math:`\boldsymbol{f}` is load vector. +Relative convergence tolerance is specified using ``rtolv`` +parameter ans max number of iterations can be set using ``maxiter`` parameter (with 100 as defult value). By default, lumped initial stress matrix is used, consistent initial stress matrix can be used when setting ``lumped`` parameter value to zero. + +The ``sparselinsolverparams`` parameter describes the sparse linear +solver attributes and is explained in section +:ref:`sparselinsolver`. + + +.. _EigenValueDynamic: + +EigenValueDynamic +~~~~~~~~~~~~~~~~~ + +``EigenValueDynamic`` ``nroot #(in)`` ``rtolv #(rn)`` [``eigensolverparams #(...)``] + +Represents the eigen value dynamic analysis. Only ``nroot`` smallest +eigenvalues and corresponding eigenvectors will be computed. Relative +convergence criteria is governed using ``rtolv`` parameter. + +The ``eigensolverparams`` parameter describes the sparse linear solver +attributes and is explained in section :ref:`eigensolverssection`. + +.. _NlDEIDynamic: + +NlDEIDynamic +~~~~~~~~~~~~ + +``NlDEIDynamic`` ``nsteps #(in)`` ``dumpcoef #(rn)`` [``deltaT #(rn)``] + +Represents the direct explicit nonlinear dynamic integration. The +central difference method with diagonal mass matrix is used, damping +matrix is assumed to be proportional to mass matrix, +:math:`\boldsymbol{C} += \mathrm{dumpcoef} * \boldsymbol{M}`, where :math:`\boldsymbol{M}` is +diagonal mass matrix. Parameter ``nsteps`` specifies how many time steps +will be analyzed. ``deltaT`` is time step length used for integration, +which may be reduced by program in order to satisfy solution stability +conditions. Parameter ``reduct`` is a scaling factor (smaller than 1), +which is multiplied with the determined step length adjusted by the +program. If ``deltaT`` is reduced internally, then ``nsteps`` is +adjusted so that the total analysis time remains the same. + +| The parallel version has the following additional syntax: +| &\ :math:`\langle`\ [``nonlocalext``]\ :math:`\rangle`\ & + +.. _DEIDynamic: + +DEIDynamic +~~~~~~~~~~ + +``DEIDynamic`` ``nsteps #(in)`` ``dumpcoef #(rn)`` [``deltaT #(rn)``] + +Represent the **linear** explicit integration scheme for dynamic problem +solution. The central difference method with diagonal mass matrix is +used, damping matrix is assumed to be proportional to mass matrix, +:math:`\boldsymbol{C} = \mathrm{dumpcoef} * \boldsymbol{M}`, where +:math:`\boldsymbol{M}` is diagonal mass matrix. ``deltaT`` is time step +length used for integration, which may be reduced by program in order to +satisfy solution stability conditions. Parameter ``nsteps`` specifies +how many time steps will be analyzed. + +.. _DIIDynamic: + +DIIDynamic +~~~~~~~~~~ + +``DIIDynamic`` ``nsteps #(in)`` ``deltaT #(rn)`` [``ddtscheme #(in)``] [``gamma #(rn)``] [``beta #(rn)``] [``eta #(rn)``] [``delta #(rn)``] [``theta #(rn)``] + +Represents direct implicit integration of linear dynamic problems. Solution procedure described in Solution procedure described in +K. Subbaraj and M. A. Dokainish, A SURVEY OF DIRECT TIME-INTEGRATION METHODS IN COMPUTATIONAL STRUCTURAL DYNAMICS - II. IMPLICIT METHODS, +Computers & Structures Vol. 32. No. 6. pp. 1387-1401, 1989. + +Parameter ``ddtscheme`` determines integration scheme, as defined in src/oofemlib/timediscretizationtype.h (TD_ThreePointBackward=0 (default), TD_TwoPointBackward = 1, +TD_Newmark = 2, TD_Wilson = 3, TD_Explicit = 4). + +Parameters ``beta`` and ``gamma`` determine the stability and acuracy of the integration algorithm, both have zero values as default. For ``gamma=0.5`` and ``beta = l/6``, the linear acceleration method is obtained. Unconditional stability is obtained, when :math:`2\beta \ge \gamma \ge 1/2`. +The dafault values are ``beta=0.25`` and ``gamma=0.5``. The Wilson-theta metod requires additional ``theta`` parameter with default value equal to 1.37. +The damping is assumed to be modeled as Rayleigh damping :math:`\boldsymbol{C} = \eta \boldsymbol{M} + \delta \boldsymbol{K}`. + +.. _IncrementalLinearStatic: + +IncrementalLinearStatic +~~~~~~~~~~~~~~~~~~~~~~~ + +``IncrementalLinearStatic`` ``endOfTimeOfInterest #(rn)`` ``prescribedTimes #(ra)`` + +Represents incremental **linear** static problem. The problem is solved +as series of linear solutions and is intended to be used for solving +linear creep problems or incremental perfect plasticity. + +Supports the changes of static scheme (applying, removing and changing +boundary conditions) during the analysis. + +Response is computed in times defined by ``prescribedTimes`` array. +These times should include times, when generally the boundary conditions +are changing, and in other times of interest. (For linear creep +analysis, the values should be uniformly distributed on log-time scale, +if no change in loading or boundary conditions). The time at the end of +interested is specified using ``endOfTimeOfInterest`` parameter. + +.. _NonLinearStatic: + +NonLinearStatic +~~~~~~~~~~~~~~~ + +| **NonLinearStatic** +| Non-linear static analysis. The problem can be solved under direct + load or displacement control, indirect control, or by their arbitrary + combination. By default all material nonlinearities will be included, + geometrical not. To include geometrically nonlinear effect one must + specify level of non-linearity in element records. There are two + different ways, how to specify the parameters - the extended and + standard syntax. + +Extended syntax +^^^^^^^^^^^^^^^ + +The extended syntax uses the “metastep†concept and has the following +format: + +``NonLinearStatic`` [``nmsteps #(in)``] ``nsteps #(in)`` [``contextOutputStep #(in)``] [``sparselinsolverparams #(string)``] [``nonlinform #(in)``] <[``nonlocstiff #(in)``]> +<[``nonlocalext``]> <[``loadbalancing``]> + +This record +is immediately followed by metastep records with the format described +below. The analysis parameters have following meaning + +- ``nmsteps`` - determines the number of “metastepsâ€, default is 1. + +- ``nsteps`` - determines number of solution steps. + +- ``contextOutputStep`` - causes the context file to be created for + every contextOutputStep-th step and when needed. Useful for + postprocessing. + +- The ``sparselinsolverparams`` parameter describes the sparse linear + solver attributes and is explained in section + :ref:`sparselinsolver`. + +- ``nonlinform`` - formulation of non-linear problem. If == 1 + (default), total Lagrangian formulation in undeformed original shape + is used (first-order theory). If == 2, the equlibrated displacements + are added to original ones and updated in each time step + (second-order theory). + +- + +| The metastep record has the following general syntax: +| ``nsteps #(in)`` [``controlmode #(in)``] [``deltat #(rn)``] + [``stiffmode #(in)``] [``refloadmode #(in)``] + ``solverParams #()`` [``sparselinsolverparams #(string)``] + [``donotfixload #()``] + +where + +- ``controlmode`` - determines the type of solution control used for + corresponding meta step. if == 0 then indirect control will be used + to control solution process (arc-length method, default). if == 1 + then direct displacement or load control will be used (Newton-Raphson + solver). In the later mode, one can apply the prescribed load + increments as well as control displacements. + +- ``deltaT`` - is time step length. If not specified, it is set equal + to 1,0. Each solution step has associated the corresponding intrinsic + time, at which the loading is generated. The ``deltaT`` determines + the spacing between solution steps on time scale. + +- ``stiffMode`` - If == 0 (default) then tangent stiffness will be used + at new step beginning and whenever numerical method will ask for + stiffness update. If == 1 the use of secant tangent will be forced. + The secant stiffness will be used at new step beginning and whenever + numerical method will ask for stiffness update. If == 2 then original + elastic stiffness will be used during the whole solution process. + +- The ``refloadmode`` parameter determines how the reference force load + vector is obtained from given totalLoadVector and initialLoadVector. + The initialLoadVector describes the part of loading which does not + scale. Works only for force loading, other non-force components + (temperature, prescribed displacements should always given in total + values). If ``refloadmode`` is 0 (rlm_total, default) then the + reference incremental load vector is defined as totalLoadVector + assembled at given time. If ``refloadmode`` is 1 (rlm_inceremental) + then the reference load vector is obtained as incremental load vector + at given time. + +- ``solverParams`` - parameters of solver. The solver type is + determined using ``controlmode``. + +- The ``sparselinsolverparams`` parameter describes the sparse linear + solver attributes and is explained in section + :ref:`sparselinsolver`. + +- By default, reached load at the end of metastep will be maintained in + subsequent steps as fixed, non scaling load and load level will be + reset to zero. This can be changed using keyword ``donotfixload``, + which if present, causes the loading to continue, not resetting the + load level. For the indirect control the reached loading will not be + fixed, however, the new reference loading vector will be assembled + for the new metastep. + +| The direct control corresponds to ``controlmode``\ =1 and the + Newton-Raphson solver is used. Under the direct control, the total + load vector assembled for specific solution step represents the load + level, where equilibrium is searched. The implementation supports also + displacement control - it is possible to prescribe one or more + displacements by applying “quasi prescribed†boundary + condition(s). The load level then represents the time, where the + equilibrium has been found. The Newton-Raphson solver parameters + (``solverParams``) for load-control are: +| ``maxiter #(in)`` [``minsteplength #(in)``] + [``minIter #(in)``] [``manrmsteps #(in)``] [``ddm #(ia)``] + [``ddv #(ra)``] [``ddltf #(in)``] [``linesearch #(in)``] + [``lsearchamp #(rn)``] [``lsearchmaxeta #(rn)``] + [``lsearchtol #(rn)``] [``nccdg #(in)`` ``ccdg1 #(ia)`` + ``ccdgN #(ia)`` ] ``rtolv #(rn)`` [``rtolf #(rn)``] + [``rtold #(tn)``] [``initialGuess #(rn)``] where + +- ``maxiter`` determines the maximum number of iterations allowed to + reach equilibrium. If equilibrium is not reached, the step length + (corresponding to time) is reduced. + +- ``minsteplength`` parameter is the minimum step length allowed. + +- ``minIter`` - minimum number of iterations which always proceed + during the iterative solution. + +- If ``manrmsteps`` parameter is nonzero, then the modified N-R scheme + is used, with the stiffness updated after ``manrmsteps`` steps. + +- ``ddm`` is array specifying the degrees of freedom, which + displacements are controlled. Let the number of these DOFs is N. The + format of ``ddm`` array is 2*N dofman1 idof1 dofman2 idof2 ... + dofmanN idofN, where the dofmani is the number of i-th dof manager + and idofi is the corresponding DOF number. + +- ``ddv`` is array of relative weights of controlled displacements, the + size should be equal to N. The actual value of prescribed dofs is + defined as a product of its weight and the value of load time + function specified using ``ddltf`` parameter (see below). + +- ``ddltf`` number of load time function, which is used to evaluate the + actual displacements of controlled dofs. + +- ``linesearch`` nonzero value turns on line search algorithm. The + ``lsearchtol`` defines tolerance (default value is 0.8), + amplification factor can be specified using ``lsearchamp`` parameter + (should be in interval :math:`(1,10)`), and parameter + ``lsearchmaxeta`` defines maximum limit on the length of iterative + step (allowed range is :math:`(1.5,15)`). + +- ``nccdg`` allows to define one or more DOF groups, that are used for + evaluation of convergence criteria. Each DOF is checked if it is a + member of particular group and in this case its contribution is taken + into account when evaluating the convergence criteria for that group. + By default, if ``nccdg`` is not specified, one group containing all + DOF types is created. The value of ``nccdg`` parameter defines the + number of DOF type groups. For each group, the corresponding DOF + types need to be specified using ``ccdg#`` parameter, where ’#’ + should be replaced by group number (numbering starts from 1). This + array contains the DofIDItem values, that identify the physical + meaning of DOFs in the group. The values and their physical meaning + is defined by DofIDItem enum type (see src/oofemlib/dofiditem.h for + reference). + +- ``rtolv`` determines relative convergence norm (both for displacement + iterative change vector and for residual unbalanced force vector). + Optionally, the ``rtolf`` and ``rtold`` parameters can be used to + define independent relative convergence crteria for unbalanced forces + and displacement iterative change. If the default convergence + criteria is used, the parameters ``rtolv``,\ ``rtolf``, and ``rtold`` + are real values. If the convergence criteria DOF groups are used (see + bellow the description of ``nccdg`` parameter) then they should be + specified as real valued arrays of ``nccdg`` size, and individual + values define relative convergence criteria for each individual dof + group. + +- ``initialGuess`` is an optional parameter with default vaue 0, for + which the first iteration of each step starts from the previously + converged state and applies the prescribed displacement increments. + This can lead to very high strains in elements connected to the nodes + with changing prescribed displacements and the state can be far from + equilibrium, which may results into slow convergence and strain + localization near the boundary. If ``initialGuess`` is set to 1, the + contribution of the prescribed displacement increments to the + internal nodal forces is linearized and moved to the right-hand side, + which often results into an initial solution closer to equilibrium. + For instance, if the step is actually elastic, equilibrium is fully + restored after the second iteration, while the default method may + require more iterations. + +| The indirect solver corresponds to ``controlmode``\ =0 and the CALM + solver is used. The value of reference load vector is determined by + ``refloadmode`` parameter mentioned above at the first step of each + metastep. However, the user must ensure that the same value of + reference load vector could be obtained for all solution steps of + particular metastep (this is necessary for restart and adaptivity to + work). The corresponding meta step solver parameters + (``solverParams``) are: +| ``Psi #(rn)`` ``MaxIter #(in)`` ``stepLength #(rn)`` + [``minStepLength #(in)``] [``initialStepLength #(rn)``] + [``forcedInitialStepLength #(rn)``] [``reqIterations #(in)``] + [``maxrestarts #(in)``] [``minIter #(in)``] + [``manrmsteps #(in)``] [``hpcmode #(in)``] [``hpc #(ia)``] + [``hpcw #(ra)``] [``linesearch #(in)``] [``lsearchamp #(rn)``] + [``lsearchmaxeta #(rn)``] [``lsearchtol #(rn)``] [``nccdg #(in)`` + ``ccdg1 #(ia)`` ... ``ccdgN #(ia)``] ``rtolv #(rn)`` + [``rtolf #(rn)``] [``rtold #(rn)``] [``pert #(ia)``] + [``pertw #(ra)``] [``rpa #(rn)``] [``rseed #(in)``] where + +- ``Psi`` - CALM :math:`\Psi` control parameter. For :math:`\Psi` = 0 + displacement control is applied. For nonzero values the load control + applies together with displacement control (ALM). For large + :math:`\Psi` load control apply. + +- ``MaxIter`` - determines the maximum number of iteration allowed to + reach equilibrium state. If this limit is reached, restart follows + with smaller step length. + +- ``stepLength`` - determines the maximum value of arc-length (step + length). + +- ``minStepLength`` - minimum step length. The step length will never + be smaller. If convergence problems are encountered and step length + cannot be decreased, computation terminates. + +- ``initialsteplength`` - determines the initial step length (the + arc-length). If not provided, the maximum step length (determined by + ``stepLength`` parameter) will be used as the value of initial step + length. + +- ``forcedInitialStepLength`` - When simulation is restarted, the last + predicted step length is used. Use ``forcedInitialStepLength`` + parameter to override the value of step length. This parameter will + also override the value of initial step length set by + ``initialsteplength`` parameter. + +- ``reqIterations`` - approximate number of iterations controlled by + changing the step length. + +- ``maxrestarts`` - maximum number of restarting computation when + convergence not reached up to ``MaxIter``. + +- ``minIter`` - minimum number of iterations which always proceed + during the iterative solution. ``reqIterations`` are set to be the + same, ``MaxIter`` are increased if lower. + +- ``manrmsteps`` - Forces the use of accelerated Newton Raphson method, + where stiffness is updated after ``manrmsteps`` steps. By default, + the modified NR method is used (no stiffness update). + +- ``hpcmode`` Parameter determining the alm mode. Possible values are: + 0 - (default) full ALM with quadratic constrain and all dofs, 1 - + (default, if ``hpc`` parameter used) full ALM with quadratic + constrain, taking into account only selected dofs (see ``hpc`` + param), 2 - linearized constrain in displacements only, taking into + account only selected dofs with given weight (see ``hpc`` and + ``hpcw`` parameters). + +- ``hpc`` - Special parameter for Hyper-plane control, when only + selected DOFs are taken account in ALM step length condition. + Important mainly for material nonlinear problems with strong + localization. This array selects the degrees of freedom, which + displacements are controlled. Let the number of these DOFs be N. The + format of ``ddm`` array is 2*N dofman1 idof1 dofman2 idof2 ... + dofmanN idofN, where the dofmani is the number of i-th dof manager + and idofi is the corresponding DOF number. + +- ``hpcw`` Array of DOF weights in linear constraint. The dof ordering + is determined by ``hpc`` parameter, the size of the array should be + N. + +- ``linesearch`` nonzero value turns on line search algorithm. The + ``lsearchtol`` defines tolerance, amplification factor can be + specified using ``lsearchamp`` parameter (should be in interval + :math:`(1,10)`), and parameter ``lsearchmaxeta`` defines maximum + limit on the length of iterative step (allowed range is + :math:`(1.5,15)`). + +- ``nccdg`` allows to define one or more DOF groups, that are used for + evaluation of convergence criteria. Each DOF is checked if it is a + member of particular group and in this case its contribution is taken + into account when evaluating the convergence criteria for that group. + By default, if ``nccdg`` is not specified, one group containing all + DOF types is created. The value of ``nccdg`` parameter defines the + number of DOF type groups. For each group, the corresponding DOF + types need to be specified using ``ccdg#`` parameter, where ’#’ + should be replaced by group number (numbering starts from 1). This + array contains the DofIDItem values, that identify the physical + meaning of DOFs in the group. The values and their physical meaning + is defined by DofIDItem enum type (see src/oofemlib/dofiditem.h for + reference). + +- ``rtolv`` determines relative convergence norm (both for displacement + iterative change vector and for residual unbalanced force vector). + Optionally, the ``rtolf`` and ``rtold`` parameters can be used to + define independent relative convergence crteria for unbalanced forces + and displacement iterative change. If the default convergence + criteria is used, the parameters ``rtolv``,\ ``rtolf``, and ``rtold`` + are real values. If the convergence criteria DOF groups are used (see + bellow the description of ``nccdg`` parameter) then they should be + specified as real valued arrays of ``nccdg`` size, and individual + values define relative convergence criteria for each individual dof + group. + +- ``pert`` Array specifying DOFs that should be perturbed after the + first iteration of each step. Let the number of these DOFs be M. The + format of ``ddm`` array is 2*M dofman1 idof1 dofman2 idof2 ... + dofmanN idofN, where the dofmani is the number of i-th dof manager + and idofi is the corresponding DOF number. + +- ``pertw`` Array of DOF perturbations. The dof ordering is determined + by ``pert`` parameter, the size of the array should be M. + +- ``rpa`` Amplitude of random perturbation that is applied to each DOF. + +- ``rseed`` Seed for the random generator that generates random + perturbations. + +Standard syntax +^^^^^^^^^^^^^^^ + +| In this case, all parameters (for analysis as well as for the solver) + are supplied in analysis record. The default meta step is created for + all solution steps required. Then the meta step attributes are + specified within analysis record. The format of analysis record is + then following +| ``NonLinearStatic`` ``nsteps #(in)`` [``nonlocstiff #(in)``] + [``contextOutputStep #(in)``] [``controlmode #(in)``] + [``deltat`` #(rn)``] ``rtolv #(rn)`` [``stiffmode #(in)``] + ``lstype #(in)`` ``smtype #(in)`` + ``solverParams #()`` [``nonlinform #(in)``] + <[``nonlocstiff #(in)``]> <[``nonlocalext``]> <[``loadbalancing``] + +The meaning of parameters is the same as for extended syntax. + +Parameter ``lstype`` allows to select the solver for the linear system +of equations. Parameter ``smtype`` allows to select the sparse matrix +storage scheme. The scheme should be compatible with the solver type. +See section :ref:`sparselinsolver` for further details. + +.. _AdaptiveLinearStatic: + +Adaptive linear static +~~~~~~~~~~~~~~~~~~~~~~ + +``Adaptlinearstatic`` ``nsteps #(in)`` [``sparselinsolverparams #(...)``] +[``meshpackage #(in)``] ``errorestimatorparams #(...)`` + +Adaptive +linear static analysis. Multiple loading cases are not supported. Due to +linearity of a problem, the complete reanalysis from the beginning is +done after adaptive remeshing. After first step the error is estimated, +information about required density is generated (using mesher interface) +and solution terminates. If the error criteria is not satisfied, then +the new mesh and corresponding input file is generated and new analysis +should be performed until the error is acceptable. Currently, the +available error estimator for linear problems is Zienkiewicz-Zhu. Please +note, that adaptive framework requires specific functionality provided +by elements and material models. For details, see element and material +model manuals. + +- Parameter ``nsteps`` indicates the number of loading cases. Should be + set to 1. + +- The ``sparselinsolverparams`` parameter describes the sparse linear + solver attributes and is explained in section + :ref:`sparselinsolver`. + +- The ``meshpackage`` parameter selects the mesh package interface, + which is used to generate information about required mesh density for + new remeshing. The supported interfaces are explained in section + :ref:`meshpackages`. By default, the T3d interface is used. + +- The ``errorerestimatorparams`` parameter contains the parameters of + Zienkiewicz Zhu Error Estimator. These are described in section + :ref:`errorestimators`. + +Adaptive nonlinear static +~~~~~~~~~~~~~~~~~~~~~~~~~ + +``Adaptnlinearstatic`` ``Nonlinearstaticparams #()`` [``equilmc #(in)``] +[``meshpackage #(in)``] [``eetype #(in)``] ``errorestimatorparams #(...)`` + +Represents Adaptive Non-LinearStatic problem. Solution is performed as a +series of increments (loading or displacement). The error is estimated +at the end of each load increment (after equilibrium is reached), and +based on reached error, the computation continues, or the new mesh +densities are generated and solution stops. Then the new discretization +should be generated. The truly adaptive approach is supported, so the +computation can be restarted from the last step (see section +:ref:`running-the-code`), solution is mapped to new mesh (separate +solution step) and new load increment is applied. Of course, one can +start the analysis from the very beginning using new mesh. Currently, +the available estimators/indicators include only linear Zienkiewicz-Zhu +estimator and scalar error indicator. Please note, that adaptive +framework requires specific functionality provided by elements and +material models. For details, see element and material model manuals. + +- Set of parameters ``Nonlinearstaticparams`` are related to nonlinear + analysis. They are described in section :ref:`NonLinearStatic`. + +- Parameter ``equilmc`` determines, whether after mapping of primary + and internal variables to new mesh the equilibrium is restored or not + before new load increment is applied. The possible values are: 0 + (default), when no equilibrium is restored, and 1 forcing the + equilibrium to be restored before applying new step. + +- The ``meshpackage`` parameter selects the mesh package interface, + which is used to generate information about required mesh density for + new remeshing. The supported interfaces are explained in section + :ref:`meshpackages`. By default, the T3d interface is used. + +- Parameter ``eetype`` determines the type of error estimator/indicator + to be used. The parameters ``errorestimatorparams`` represent set of + parameters corresponding to selected error estimator. For + description, follow to section :ref:`errorestimators`. + +.. _FreeWarping: + +Free warping analysis +~~~~~~~~~~~~~~~~~~~~~ + +``FreeWarping`` ``nsteps #(in)`` + +Free warping analysis computes the deplanation function of cross section +with arbitrary shape. It is done by solving the Laplace’s equation with +automatically generated boundary conditions corresponding to the free +warping problem. + +This type of analysis supports only ``TrWarp`` elements and +``WarpingCS`` cross sections. One external node must be defined for each +warping cross section. The coordinates of this node can be arbitrary but +this node must be defined with parametr ``DofIDMask 1 24`` and one +boundary condition which represents relative twist acting on +corresponding warping cross section. No additional loads make sence in +free warping analysis. + +Parameter ``nsteps`` indicates the number of loading cases. Series of +loading cases is maintained as sequence of time-steps. For each load +case an auxiliary time-step is generated with time equal to load case +number. Load vectors for each load case are formed as load vectors at +this auxiliary time. + +Transport Problems +------------------ + +.. _StationaryTransport: + +Stationary transport problem +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``StationaryProblem`` ``nsteps #(in)`` [``sparselinsolverparams #(...)``] [``exportfields #(ia)``] + +Stationary transport problem. Series of loading cases is maintained as +sequence of time-steps. For each load case an auxiliary time-step is +generated with time equal to load case number. Load vectors for each +load case are formed as load vectors at this auxiliary time. The +``sparselinsolverparams`` parameter describes the sparse linear solver +attributes and is explained in section :ref:`sparselinsolver`. + +If the present problem is used within the context of staggered-like +analysis, the temperature field obtained by the solution can be exported +and made available to any subsequent analyses. For example, temperature +field obtained by present analysis can be taken into account in +subsequent mechanical analysis. To allow this, the temperature must be +“exportedâ€. This can be done by adding array ``exportfields``. This +array contains the field identifiers, which tell the problem to register +its primary unknowns under given identifiers. See file field.h. Then the +subsequent analyses can get access to exported fields and take them into +account, if they support such feature. + +.. _TransientTransport: + +Transient transport problem +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``TransientTransport`` ``nsteps #(in)`` ``deltaT #(rn)`` *or* ``dTfunction #(in)`` *or* ``prescribedtimes #(ra)`` +``alpha #(rn)`` [``initT #(rn)``] [``lumped``] +[``keeptangent``] [``exportfields #(ia)``] + +**Nonlinear** implicit integration scheme for transient transport +problems. The generalized midpoint rule (sometimes called +:math:`\alpha`-method) is used for time discretization, with alpha +parameter, which has limits :math:`0\le\alpha\le1`. For :math:`\alpha=0` +explicit Euler forward method is obtained, for :math:`\alpha=0.5` +implicit trapezoidal rule is recovered, which is unconditionally stable, +second-order accurate in :math:`\Delta t`, and :math:`\alpha=1.0` yields +implicit Euler backward method, which is unconditionally stable, and +first-order accurate in :math:`\Delta t`. ``deltaT`` is time step length +used for integration, ``nsteps`` parameter specifies number of time +steps to be solved. It is possible to define ``dTfunction`` with a +number referring to corresponding time function, see +section :ref:`TimeFunctionsRecords`. Variable time step is +advantageous when calculating large time intervals. + +The ``initT`` sets the initial time for integration, 0. by default. If +``lumped`` is set, then the stabilization of numerical algorithm using +lumped capacity matrix will be used, reducing the initial oscillations. +See section :ref:`StationaryTransport` for an explanation on +``exportfields``. + +This transport problem supports sets and changes in number of equations. +It is possible to impose/remove Dirichlet boundary conditions during +solution. + +.. _LinearTransientTransport: + +Transient transport problem - linear case - obsolete +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``NonStationaryProblem`` ``nsteps #(in)`` ``deltaT #(rn)`` | +``deltaTfunction #(in)`` ``alpha #(rn)`` [``initT #(rn)``] +[``lumpedcapa``] [``sparselinsolverparams #(..)``] +[``exportfields #(ia)``] [``changingProblemSize``] + +**Linear** implicit integration scheme for transient transport problems. +The generalized midpoint rule (sometimes called :math:`\alpha`-method) +is used for time discretization, with alpha parameter, which has limits +:math:`0\le\alpha\le1`. For :math:`\alpha=0` explicit Euler forward +method is obtained, for :math:`\alpha=0.5` implicit trapezoidal rule is +recovered, which is unconditionally stable, second-order accurate in +:math:`\Delta t`, and :math:`\alpha=1.0` yields implicit Euler backward +method, which is unconditionally stable, and first-order accurate in +:math:`\Delta t`. ``deltaT`` is time step length used for integration, +``nsteps`` parameter specifies number of time steps to be solved. It is +possible to define ``deltaTfunction`` with a number referring to +corresponding time function, see +section :ref:`TimeFunctionsRecords`. Variable time step is +advantageous when calculating large time intervals. It is strongly +suggested to use nonlinear transport solver due to stability reasons, +see section :ref:`TransientTransport`. + +The ``initT`` sets the initial time for integration, 0 by default. If +``lumpedcapa`` is set, then the stabilization of numerical algorithm +using lumped capacity matrix will be used, reducing the initial +oscillations. See section :ref:`StationaryTransport` for an +explanation on ``exportfields``. + +This linear transport problem supports changes in number of equations. +It is possible to impose/remove Dirichlet boundary conditions during +solution. This feature is enabled with ``changingProblemSize``, which +ensures storing solution values on nodes (DoFs) directly. If the problem +does not grow/decrease during solution, it is more efficient to use +conventional solution strategy and the parameter should not be +mentioned. + +Note: This problem type **requires transport module** and it can be used +only when this module is included in your oofem configuration. + +.. _TransientTransport2: + +Transient transport problem - nonlinear case - obsolete +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``NlTransientTransportProblem`` ``nsteps #(in)`` ``deltaT #(rn)`` | +``deltaTfunction #(in)`` ``alpha #(rn)`` [``initT #(rn)``] +[``lumpedcapa #()``] [``nsmax #(in)``] ``rtol #(rn)`` +[``manrmsteps #(in)``] [``sparselinsolverparams #(...)``] +[``exportfields #(ia)``] [``changingProblemSize``] + +Implicit integration scheme for transient transport problems. The +generalized midpoint rule (sometimes called :math:`\alpha`-method) is +used for time discretization, with alpha parameter, which has limits +:math:`0\le\alpha\le1`. For :math:`\alpha=0` explicit Euler forward +method is obtained, for :math:`\alpha=0.5` implicit trapezoidal rule is +recovered, which is unconditionally stable, second-order accurate in +:math:`\Delta t`, and :math:`\alpha=1.0` yields implicit Euler backward +method, which is unconditionally stable, and first-order accurate in +:math:`\Delta t`. See matlibmanual.pdf for solution algorithm. + +``deltaT`` is time step length used for integration, ``nsteps`` +parameter specifies number of time steps to be solved. For +``deltaTfunction`` and ``initT`` see +section :ref:`LinearTransientTransport`. Parameter ``maxiter`` +determines the maximum number of iterations allowed to reach equilibrium +(default is 30). Norms of residual physical quantity (heat, mass) +described by solution vector and the change of solution vector are +determined in each iteration. The convergence is reached, when the norms +are less than the value given by ``rtol``. If ``manrmsteps`` parameter +is nonzero, then the modified N-R scheme is used, with the left-hand +side matrix updated after ``manrmsteps`` steps. ``nsmax`` maximum number +of iterations per time step, default is 30. If ``lumpedcapa`` is set, +then the stabilization of numerical algorithm using lumped capacity +matrix will be used, reducing the initial oscillations. + +See the Section :ref:`StationaryTransport` for an explanation on +``exportfields``. The meaning of ``changingProblemSize`` is given in +Section :ref:`LinearTransientTransport`. + +Note: This problem type **requires transport module** and it can be used +only when this module is included in your oofem configuration. + +Fluid Dynamic Problems +---------------------- + +.. _cbsIncomp: + +Transient incompressible flow - CBS Algorithm +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``CBS`` ``nsteps #(in)`` ``deltaT #()`` [``theta1 #(in)``] +[``theta2 #(in)``] [``cmflag #(in)``] [``scaleflag #(in)`` +``lscale #(in)`` ``uscale #(in)`` ``dscale #(in)``] [``lstype #(in)``] +[``smtype #(in)``] + +Solves the transient incompressible flow using algorithm based on +Characteristics Based Split (CBS, for reference see O.C.Zienkiewics and +R.L.Taylor: The Finite Element Method, 3rd volume, +Butterworth-Heinemann, 2000). At present, only semi-implicit form of the +algorithm is available and energy equation, yielding the temperature +field, is not solved. Parameter ``nsteps`` determines number of solution +steps. Parameter ``deltaT`` is time step length used for integration. +This time step will be automatically adjusted to satisfy integration +stability limits +:math:`\Delta t \le {\frac{h}{\vert\boldsymbol{u}\vert}}` and +:math:`\Delta t \le {\frac{h^2}{2\nu}}`, if necessary. Parameters +``theta1`` and ``theta2`` are integration constants, +:math:`\theta_1, \theta_2 \in \langle{\frac12}, 1\rangle`. If ``cmflag`` +is given a nonzero value, then consistent mass matrix will be used +instead of (default) lumped one. + +The characteristic equations can be solved in non-dimensional form. To +enable this, the ``scaleflag`` should have a nonzero value, and the +following parameters should be provided: ``lscale``, ``uscale``, and +``dscale`` representing typical length, velocity, and density scales. + +Parameter ``lstype`` allows to select the solver for the linear system +of equations. Parameter ``smtype`` allows to select the sparse matrix +storage scheme. The scheme should be compatible with the solver type. +See section :ref:`sparselinsolver` for further details. + +.. _supgIncomp: + +Transient incompressible flow SUPG/PSPG Algorithm +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``SUPG`` ``nsteps #(in)`` ``deltaT #(rn)`` ``rtolv #(rn)`` +[``atolv #(rn)``] [``stopmaxiter #(in)``] [``alpha #(rn)``] +[``cmflag #(in)``] [``deltatltf #(in)``] [``miflag #(in)``] +[``scaleflag #(in)`` ``lscale #(in)`` ``uscale #(in)`` +``dscale #(in)``] [``lstype #(in)``] [``smtype #(in)``] + +Solves the transient incompressible flow using stabilized formulation +based on SUPG and PSPG stabilization terms. The stabilization provides +stability and accuracy in the solution of advection-dominated problems +and permits usage of equal-order interpolation functions for velocity +and pressure. Furthermore, stabilized formulation significantly improves +convergence rate in iterative solution of large nonlinear systems of +equations. + +By changing the value :math:`\alpha`, different methods from +“Generalized mid-point family†can be chosen, i.e., Forward Euler +(:math:`\alpha=0`), Midpoint rule (:math:`\alpha=0.5`), Galerkin +(:math:`\alpha=2/3`), and Backward Euler (:math:`\alpha=1`). Except the +first one, all the methods are implicit and require matrix inversion for +solution. Some results form an energy method analysis suggest +unconditional stability for :math:`\alpha\ge 0.5` for the generalized +mid-point family. As far as accuracy is concerned, the midpoint rule is +to be generally preferred. + +Parameter ``nsteps`` determines number of solution steps. Parameter +``deltaT`` is time step length used for integration. Alternatively, the +load time function can be used to determine time step length for +particular solution step. The load time function number is determined by +parameter ``deltatltf`` and its value evaluated for solution step number +should yield the step length. + +Parameters ``rtolv`` and ``atolv`` allow to specify relative and +absolute errors norms for residual vector. The equilibrium iteration +process will stopped when both error limits are satisfied or when the +number of iteration exceeds the value given by parameter +``stopmaxiter``. + +If ``cmflag`` is given a nonzero value, then consistent mass matrix will +be used instead of (default) lumped one. + +The algorithm allows to solve the flow of two immiscible fluids in fixed +spatial domain (currently only in 2d). This can be also used for solving +free surface problems, where one of the fluids should represent air. To +enable multi-fluid analysis, user should set parameter ``miflag``. The +supported values are described in +section :ref:`materialinterfaces`. Please note, that the initial +distribution of reference fluid volume should be provided as well as +constitutive models for both fluids. + +The characteristic equations can be solved in non-dimensional form. To +enable this, the ``scaleflag`` should have a nonzero value, and the +following parameters should be provided: ``lscale``, ``uscale``, and +``dscale`` representing typical length, velocity, and density scales. + +Parameter ``lstype`` allows to select the solver for the linear system +of equations. Parameter ``smtype`` allows to select the sparse matrix +storage scheme. Please note that the present algorithm leads to a +non-symmetric matrix. The scheme should be compatible with the solver +type. See section :ref:`sparselinsolver` for further details. + +.. _pfemIncomp: + +Transient incompressible flow (PFEM Algorithm) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``PFEM`` ``nsteps #(in)`` ``deltaT #(rn)`` ``material #(in)`` +``cs #(in)`` ``pressure #(in)`` [``mindeltat #(rn)``] +[``maxiter #(in)``] [``rtolv #(rn)``] [``rtolp #(rn)``] +[``alphashapecoef #(rn)``] [``removalratio #(rn)``] +[``scheme #(in)``] [``lstype #(in)``] [``smtype #(in)``] + +Solves the transient incompressible flow using particle finite element +method based on the Lagrangian formulation of Navier-Stokes equations. + +Mesh nodes are represented by +PFEMParticles (see :ref:`pfemparticles`), which can freely +move and even separate from the main domain. To integrate governing +equations in each solution step, a temporary mesh, built from particles, +is needed. The mesh is rebuilt from scratch in each solution step to +prevent large distortion of elements. Paramters ``cs`` and ``material`` +assign types from cross section and material record to created elements. +Thus, the problem is defined without any elements in the input file. + +Mesh is generated using Delaunay triangulation and Alpha shape technique +for the identification of the free surface. The parameter +``alphashapecoef`` should reflect initial distribution of PFEMParticles. +Value approximately equal to 1,5-multiple of shortest distance of two +neighboring particles has been found well. On the free surface the +zero-pressure boundary condition is enforced. This must be defined in +boundary condition record under the number defined by ``pressure``. + +Parameter ``scheme`` controls whether the equation system for the +components of the auxiliary velocity is solved explicitly (0) or +implicitly (1). The last is the default option. + +Parameter ``nsteps`` determines number of solution steps. Parameter +``deltaT`` is time step length used for integration. To ensure numerical +stability, step length is adapted upon mesh geometry and velocity of +paricular nodes. To avoid to short time length a minimal size can be +defined by ``mindeltat``. Alternatively prescribing limit +``removalratio`` of the element edge length too close particles can be +removed from solution. + +Optional parameters ``rtolv`` and ``rtolp`` allow to specify relative +norms for velocity and pressure difference of two subsequent iteration +step. Default values are 1.e-8. By default maximal 50 iterations are +performed, if not specified by ``maxiter``. + +Parameter ``lstype`` allows to select the solver for the linear system +of equations. Parameter ``smtype`` allows to select the sparse matrix +storage scheme. Please note that the present algorithm leads to a +non-symmetric matrix. The scheme should be compatible with the solver +type. See section :ref:`sparselinsolver` for further details. + +Coupled Problems +---------------- + +.. _staggeredproblem: + +Staggered Problem +~~~~~~~~~~~~~~~~~ + +``StaggeredProblem`` (``nsteps #(in)`` ``deltaT #(rn))`` :math:`|` +``timeDefinedByProb #(in)`` ``prob1 #(s)`` ``prob2 #(s)`` +[``stepMultiplier #(rn)``] + +Represent so-called staggered analysis. This can be described as an +sequence of sub-problems, where the result of some sub-problem in the +sequence can depend on results of previous sub-problems in sequence. +Typical example is heat transfer analysis followed by mechanical +analysis taking into account the temperature field generated by the heat +transfer analysis. Similar analysis can be done when coupling moisture +transport with concrete drying strain. + +The actual implementation supports only sequence of two sub-problems. +The sub-problems are described using sub-problem input files. The syntax +of sub-problem input file is the same as for standalone problem. The +only addition is that sub-problems should export their solution fields +so that they became available for subsequent sub-problems. See the +Section :ref:`StationaryTransport`. + +The subproblem input files are described using ``prob1`` and ``prob2`` +parameters, which are strings containing a path to sub-problem input +files, the ``prob1`` contains input file path of the first sub-problem, +which runs first for each solution step, the ``prob2`` contains input +file path of the second sub-problem. + +There are two options how to control a time step sequence. The first +approach uses ``timeDefinedByProb`` which uses time sequence from the +corresponding subproblem. The subproblem may specify arbitrary loading +steps and allows high flexibility. The second approach uses the +staggered problem to take control over time. Therefore any sub-problem +time-stepping parameters are ignored (even if they are required by +sub-problem input syntax) and only staggered-problem parameters are +relevant. ``deltaT`` is than a time step length used for integration, +``nsteps`` parameter specifies number of time steps to be solved. +``stepMultiplier`` multiplies all times with a given constant. Default +is 1. + +Note: This problem type **is included in transport module** and it can +be used only when this module is configured. Note: All material models +derived from StructuralMaterial base will take into account the external +registered temperature field, if provided. + +.. _fluidstructureproblem: + +FluidStructure Problem +~~~~~~~~~~~~~~~~~~~~~~ + +``FluidStructureProblem`` ``nsteps #(in)`` ``deltaT #(rn)`` ``prob1 #(s)`` +``prob2 #(s)`` [``maxiter #(in)``] [``rtolv #(rn)``] +[``rtolp #(rn)``] + +Represents a fluid-structure analysis based on StaggeredProblem but +providing iterative synchronization of sub-problems. The implementation +uses the the PFEM model :ref:`pfemIncomp` for the fluid part. +For the structural part a full dynamic analysis using implicit direct +integration DIIDynamic :ref:`DIIDynamic` is considered. + +The coupling of both phases is based on the idea of enforcing +compatibility on the interface. Special fluid particle are attached to +every structural node on the interface that can be hit by the fluid. +These special particles have no degrees of freedom associated, so no +equations are solved on them. However, their movement is fully +determined by associated structural nodes. Their velocities governed by +the solid part affect the fluid equation naturally. + +This iterative procedure is based on the so-called Dirichlet-Neumann +approach. Dirichlet boundary conditions are the prescribed velocities on +the fluid side of the interface, whereas applied forces on the +structural side represent the Neumann boundary conditions. + +The convergence criterion is based on the difference of the pressure and +velocity values on the interface from the subsequent iterative steps. +Once they are smaller than prescribed tolerance, the iteration is +terminated and solution can proceed to the next step. + +The subproblem input files are described using ``prob1`` and ``prob2`` +parameters, which are strings containing a path to sub-problem input +files, the ``prob1`` contains input file path of the first sub-problem, +which runs first for each solution step, the ``prob2`` contains input +file path of the second sub-problem. The time step sequence is +controlled by the number of steps ``nsteps`` and the time step length +``deltaT``. + +Optional parameters ``rtolv`` and ``rtolp`` allow to specify relative +norms for velocity and pressure differnce of two subsequent iteration +step. Default values are 1.e-3. By default maximal 50 iterations are +performed, if not specified by ``maxiter``. + +Note: This problem type **is included in PFEM module** and it can be +used only when this module is configured. + +.. _DummyEngngModel: + +DummyEngngModel +~~~~~~~~~~~~~~~~ + +``Dummy`` ``nnmodules #(in)`` + +Represents a dummy model, whch is not capable to perform any analysis. +Its intended use is to invoke the configured export modules, +so that the problem geometry can be exported without requiring to actually solve the problem. diff --git a/doc/oofemInput/apendices.rst b/doc/oofemInput/apendices.rst new file mode 100644 index 000000000..3e93ccc63 --- /dev/null +++ b/doc/oofemInput/apendices.rst @@ -0,0 +1,662 @@ + + +Appendix +======== + +.. _sparselinsolver: + +Sparse linear solver parameters +------------------------------- + +| The sparselinsolverparams field has the following general syntax: +| [``lstype #(in)``] [``smtype #(in)``] ``solverParams #(string)`` + +where parameter ``lstype`` allows to select the solver for the linear system of equations. Currently +supported values are 0 (default) for a direct solver (ST_Direct), 1 +for an Iterative Method Library (IML) solver (ST_IML), 2 for a Spooles +direct solver, 3 for Petsc library family of solvers, and 4 for a +DirectSparseSolver (ST_DSS). Parameter ``smtype`` allows to select the +sparse matrix storage scheme. The scheme should be compatible with the +solver type. Currently supported values (marked as “idâ€) are +summarized in table :ref:`linsolvstoragecompattable`. The 0 +value is default and selects the symmetric skyline (SMT_Skyline). +Possible storage formats include unsymmetric skyline (SMT_SkylineU), +compressed column (SMT_CompCol), dynamically growing compressed column +(SMT_DynCompCol), symmetric compressed column (SMT_SymCompCol), +spooles library storage format (SMT_SpoolesMtrx), PETSc library matrix +representation (SMT_PetscMtrx, a sparse serial/parallel matrix in AIJ +format), and DSS compatible matrix representations (SMT_DSS). The +allowed ``lstype`` and ``smtype`` combinations are summarized in the +table :ref:`linsolvstoragecompattable`, +together with solver parameters related to specific solver. + + + +.. raw:: latex + + \begin{landscape} + +.. _linsolvstoragecompattable: +.. table:: Solver and storage scheme compatibility. + + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |Storage format |``smtype id``| ``lstype (id)`` | + +================+=============+==========+=======+===========+=========+=======+==============+==============+ + | | id |Direct (0)|IML (1)|Spooles (2)|Petsc (3)|DSS (4)|MKLPardiso (6)|SuperLU_MT (7)| + | | | | | | | |Pardiso.org(8)| | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |SMT_Skyline | 0 | + | + | | | | | | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |SMT_SkylineU | 1 | + | + | | | | | | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |SMT_CompCol | 2 | | + | | | | + | + | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |SMT_DynCompCol | 3 | | + | | | | | | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |SMT_SymCompCol | 4 | | + | | | | | | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |SMT_DynCompRow | 5 | | + | | | | | | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |SMT_SpoolesMtrx | 6 | | | + | | | | | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |SMT_PetscMtrx | 7 | | | | + | | | | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |SMT_DSS_sym_LDL | 8 | | | | | | | + | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |SMT_DSS_sym_LL | 9 | | | | | | | + | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + |SMT_DSS_unsym_LU| 10 | | | | | | | + | + +----------------+-------------+----------+-------+-----------+---------+-------+--------------+--------------+ + +.. raw:: latex + + \end{landscape} + +The solver parameters in ``solverParams`` depend on the solver type and +are summarized in table +(sparsesolverparams_). + +.. _sparsesolverparams: + +.. table:: Solver parameters. + + ==================== == ======================================================================= + Solver type id Solver parameters/notes + ==================== == ======================================================================= + ST_Direct 0 + ST_IML 1 [``stype`` #(in)] ``lstol`` #(rn) ``lsiter`` #(in)\ ``lsprecond`` #(in) + \ [``precondattributes`` #(string)] + \ Included in OOFEM, requires to compile with USE_IML + ST_Spooles 2 [``msglvl`` #(in)] [``msgfile`` #(s)] + \ http://www.netlib.org/linalg/spooles/spooles.2.2.html + ST_Petsc 3 See Petsc manual, for details + ST_DSS 4 Sparse direct solver, included in OOFEM + \ Requires to compile with USE_DSS + ST_MKLPardiso 6 Requires Intel MKL Pardiso + ST_SuperLU_MT 7 SuperLU for shared memory machines + \ http://crd-legacy.lbl.gov/ xiaoye/SuperLU/ + ST_PardisoProjectOrg 8 Requires Pardiso solver(http://www.pardiso-project.org/) + ==================== == ======================================================================= + +In case of ``ST_PETSC``, the user can set several run-time options, e.g., + ``-ksp\_type`` ``[cg, gmres, bicg, bcgs]`` + ``-pc\_type`` ``[jacobi, bjacobi,none,ilu,...]`` + ``-ksp\_monitor`` ``-ksp\_rtol #`` ``-ksp\_view`` ``-ksp\_converged_reason``. + These options will override those that are default (PETSC KSPSetFromOptions() routine is called after any other customization + routines).} + +The ``stype`` allows to select particular iterative solver from IML +library, currently supported values are 0 (default) for +Conjugate-Gradient solver, 1 for GMRES solver. Parameter ``lstol`` +represents the maximum value of residual after the final iteration and +the ``lsiter`` is maximum number of iteration for iterative solver. The +``precondattributes`` parameters contains the optional preconditioner +parameters. The ``lsprecond`` parameter determines the type of +preconditioner to be used. The possible values of ``lsprecond`` together +with supported storage schemes and their descriptions are summarized in +table :ref:`precondtable`. + +.. _precondtable: + +.. table:: Preconditioning summary. + + ============ == ================== ========================================= + Precond type id Compatible storage Description and parameters + ============ == ================== ========================================= + IML_VoidPrec 0 all No preconditioning + IML_DiagPrec 1 all Diagonal preconditioning + IML_ILUPrec 2 SMT_CompCol Incomplete LU Decomposition + \ SMT_DynCompCol with no fill up + IML_ILUPrec 3 SMT_DynCompRow Incomplete LU (ILUT) with + \ fillup. + \ The ``precondattributes`` are: + \ [``droptol`` #(rn)] [``partfill`` #(in)]. + \ ``droptol`` dropping tolerance + \ ``partfill`` level of fill-up + IML_ICPrec 4 SMT_SymCompCol Incomplete Cholesky + \ SMT_CompCol with no fill up + ============ == ================== ========================================= + +.. _eigensolverssection: + +Eigen value solvers +------------------- + +| The eigensolverparams field has the following general syntax: +| ``stype #(in)`` [``smtype #(in)``] ``solverParams #(string)`` + where parameter ``stype`` allows to + select solver type. Parameter ``smtype`` allows to select sparse + matrix storage scheme. The scheme should be compatible with solver + type. Currently supported values of ``stype`` are summarized in + table :ref:`eigenvaluesolverparamtable`. + +.. _eigenvaluesolverparamtable: + +.. table:: Eigen Solver parameters. + + ================== =========== ===================== + Solver type stype id solver parameters + Subspace Iteration 0 (default) + Inverse Iteration 1 + SLEPc solver 2 requires “smtype 7†+ see also SLEPc manual + ================== =========== ===================== + +.. _dynamicloadbalancing: + +| There are in general two basic factors causing load imbalance between + individual subdomains: (i) one comming from application nature, such + as switching from linear to nonlinear response in certain regions or + local adaptive refinment, and (ii) external factors, caused by + resourse realocation, typical for nondedicated cluster environments, + where indivudual processors are shared by different applications and + users, leading to time variation in allocated processing power. The + load balance recovery is achieved by repartitioning of the problem + domain and transferring the work (represented typically by finite + elements) from one subdomain to another. This section describes the + structure and syntax of parameters related to dynamic load balancing. + The corresponding part of analysis record has the following general + syntax: +| [``lbflag #(in)``] [``forcelb1 #(in)``] [``wtp #(ia)``] + [``lbstep #(in)``] [``relwct #(rn)``] [``abswct #(rn)``] + [``minwct #(rn)``] + +where the parameters have following meaning: + +- ``lbflag``, when set to nonzero value activates the dynamic load + balancing. Default value is zero. + +- ``forcelb1`` forces the load rebalancing after the first solution + step, when set to nonzero value. + +- ``wtp`` allows to activate optional load balancing plugins. At + present, the only supported value is 1, that activates nonlocal + plugin, necessary for nonlocal averaging to work properly when + dynamic load balancing is active. + +- ``lbstep`` rebalancing, if needed, is performed only every lbstep + solution step. Default value is 1 (recover balance after every step, + if necessary). + +- ``relwcr`` sets relative wall-clock imbalance treshold. When achieved + relative imbalance between wall clock solution time of individual + processors is greater than provided treshold, the rebalancing + procedure will be activated. + +- ``abswct`` sets absolute wall-clock imbalance treshold. When achieved + absolute imbalance between wall clock solution time of individual + processors is greater than provided treshold, the rebalancing + procedure will be activated. + +- ``minwct`` minimum absolute imbalance to perform relative imbalance + check using ``relwcr`` parameter, otherwise only absolute check is + done. Default value is 0. + +At present, the load balancing support requires ParMETIS module to be +configured and compiled. + +.. _errorestimators: + +Error estimators and indicators +------------------------------- + +The currently supported values of ``eetype`` are in table +:ref:`eetypestable`. + +- EET_SEI - Represents scalar error indicator. It indicates element + error based on the value of some suitable scalar value (for example + damage level, plastic strain level) obtained from the element + integration points and corresponding material model. + +- EET_ZZEE - The implementation of Zienkiewicz Zhu Error Estimator. It + requires the special element algorithms, which may not be available + for all element types. + + Please note, that in the actual version, the error on the element + level is evaluated using default integration rule. For example, in + case of ZZ error estimator, the error (L2 or energy norm) is + evaluated from the difference of computed and “recovered†stresses, + which are approximated using the same interpolation functions as + displacements). Therefore, in many cases, the default integration + rule order is not sufficient and higher integration must be used on + elements (consult element library manual and related NIP parameter). + +- EET_CZZSI - The implementation of combined criteria: Zienkiewicz Zhu + Error Estimator for elastic regime and scalar error indicator in + non-linear regime. + +.. _eetypestable: + +.. table:: Supported error estimators and indicators. + + ========================= ========== + Error estimator/indicator ``eetype`` + ========================= ========== + EET_SEI 0 + EET_ZZEE 1 + EET_CZZSI 2 + ========================= ========== + +The sets of parameters (``errorestimatorparams`` field) used to +configure each error estimator are different + +- | ``EET_SEI`` + | [``regionskipmap #(ia)``] ``vartype #(in)`` + ``minlim #(rn)`` ``maxlim #(rn)`` ``mindens #(rn)`` + ``maxdens #(rn)`` ``defdens #(rn)`` + [``remeshingdensityratio #(rn)``] + + - ``regionskipmap`` parameter allows to skip some regions. The error + is not evaluated in these regions and default mesh density is + used. The size of this array should be equal to number of regions + and nonzero entry indicates region to skip. + + - ``vartype`` parameter determines the type of internal variable to + be used as error indicator. Currently supported value is 1, + representing damage based indicator. + + - If the indicator value is in range given by parameters + (``minlim``, ``maxlim``) then the proposed mesh density is + linearly interpolated within range given by parameters + (``mindens``, ``maxdens``). If indicator value is less than value + of ``minlim`` parameter then value of ``defdens`` parameter is + used as required density, if it is larger than ``maxlim`` then + ``maxdens`` is used as required density. + + - ``remeshingdensityratio`` parameter determines the allowed ratio + between proposed density and actual density. The remeshing is + forced, whenever the actual ratio is smaller than this value. + Default value is equal to 0.80. + +- | ``EET_ZZEE`` + | [``regionskipmap #(ia)``] ``normtype #(in)`` + ``requirederror #(rn)`` ``minelemsize #(rn)`` + + - ``regionskipmap`` parameter allows to skip some regions. The error + is not evaluated in these regions and default mesh density is + used. The size of this array should be equal to number of regions + and nonzero entry indicates region to skip. + + - ``normtype`` Allows select the type of norm used in evaluation of + error. Default value is to use L2 norm (equal to 0), value equal + to 1 uses the energy norm. + + - ``requirederror`` parameter determines the required error to + obtain (in percents/100). + + - minelemsize parameter allows to set minimum limit on element size. + +- EET_CZZSI - combination of parameters for EET_SEI and EET_ZZEE; the + in elastic regions are driven using EET_SEI, the elastic are driven + by EET_ZZEE. + +.. _materialinterfaces: + +Material interfaces +------------------- + +The material interfaces are used to represent and track the position of +various interfaces on fixed grids. Typical examples include free +surface, evolving interface between two materials, etc. Available +representations include: + +======== ====== ============= +MI miflag Compatibility +======== ====== ============= +LEPlic 0 2D triangular +LevelSet 1 2D triangular +======== ====== ============= + +- | LEPlic- representation based on Volume-Of-Fluid approach; the + initial distribution of VOF fractions should be specified for each + element (see element manual) + | [``refvol #(rn)``] + + - parameter ``refvol`` allows to set initial volume of reference + fluid, then the reference volume is computed in each step and + printed, so the accuracy and mass conservation can be monitored. + +- | LevelSet- level set based representation + | ``levelset #(ra)`` OR ``refmatpolyx #(ra)`` ``refmatpolyy #(ra)`` + | [``lsra #(in)``] [``rdt #(rn)``] [``rerr #(rn)``] + + - ``levelset`` allows to specify the initial level set values for + all nodes directly. The size should be equal to total number of + nodes within the domain. + + - Parameters ``refmatpolyx`` and ``refmatpolyy`` allow to initialize + level set by specifying interface geometry as 2d polygon. Then + polygon describes the initial zero level set, and level set values + are then defined as signed distance from this polygon. Positive + values are on the left side when walking along polygon. The + parameter ``refmatpolyx`` specifies the x-coordinates of polygon + vertices, parameter ``refmatpolyy`` y-corrdinates. Please note, + that level set must be initialized, either using ``levelset`` + parameter or using ``refmatpolyx`` and ``refmatpolyy``. + + - Parameter ``lsra`` allows to select level set reinitialization + algorithm. Currently supported values are 0 (no + re-initialization), 1 (re-initializes the level set representation + by solving + :math:`d_{\tau} = S(\phi)(1-\vert\boldsymbol{\nabla}d\vert)` to + steady state, default), 2 (uses fast marching method to build + signed distance level set representation). + + - Parameters ``rdt`` ``rerr`` are used to control reinitialization + algorithm for ``lsra`` = 0. ``rdt`` allows to change time step of + integration algorithm and parameter ``rerr`` allows to change + default error limit used to detect steady state. + +.. _meshpackages: + +Mesh generator interfaces +------------------------- + +The mesh generator interface is responsible to provide a link to +specific mesh generator. The supported values of ``meshpackage`` +parameter are + +- MPT_T3D: ``meshpackage`` = 0. T3d mesh interface. Default. Supports + both 1d, 2d (triangles) and 3d (tetrahedras) meshes. Reliable. + +- MPT_TARGE2: ``meshpackage`` = 1. Interface to Targe2 2D mesh + generator. + +- MPT_SUBDIVISION: ``meshpackage``\ =3. Built-in subdivision algorithm. + Supports triangular 2D and tetrahedral 3D meshes. Can operate in + parallel mode. + +.. _InitModulesSec: + +Initialization modules +---------------------- + +| Initialization modules allow to initialize the state variables using + data previously computed by external software. The number of + initialization module records is specified in analysis record using + ``ninitmodules`` parameter (see the initial part of section + :ref:`AnalysisRecord`. The general format is the following: + +| ``EntType`` ``initfile #(string)`` + The file name following the keyword + “initfile†specifies the path to the file that contains the + initialization data and should be given without quotes. + +Currently, the only supported initialization module is + +- Gauss point initialization module + + | ``GPInitModule`` ``initfile #(string)`` + | + | - Each Gauss point is represented by one line in the initialization file. + | - The Gauss points should be given in a specific order, based on the + element number and the Gauss point number, in agreement with the + mesh specified in later sections. + + |- Each line referring to a Gauss point should contain the following data: + ``elnum #(in)`` ``gpnum #(in)`` ``coords #(ra)`` + ``ng #(in)`` ``var_1_id #(in)`` ``values_1 #(ra)`` ``...`` ``var_ng_id #(in)`` ``values_ng #(ra)`` + + - ``elnum`` is the element number + + - ``gpnum`` is the Gauss point number + + - ``coords`` are the coordinates of the Gauss point + + - ``ng`` is the number of groups of variables that will follow + + - ``var_1_id`` is the identification number of variable group number + 1 (according to the definitions in internalstatetype.h) + + - ``values_1`` are the values of variables in group number 1 + + - ``var_ng_id`` is the identification number of variable group number ng + + - ``values_ng`` are the values of variables in group number ng + + - | Example: + | ``37 4 3 0.02 0.04 0.05 3 52 1 0.23 62 1 0.049 1 6 0 -2.08e+07 0 0 0 0`` + means that Gauss point number 4 of element number 37 has + coordinates :math:`x=0.02`, :math:`y=0.04` and :math:`z=0.05` + and the initial values are specified for 3 groups of variables; + the first group (variable ID 52) is of type IST_DamageScalar + (see internalstatetype.h) and contains 1 variable (since it is a + scalar) with value 0.23; + the second group (ID 62) is of type IST_CumPlasticStrain and + contains 1 variable with value 0.049; + the third group is of type IST_StressTensor and contains 6 + variables (stress components :math:`\sigma_x`, :math:`\sigma_y`, + etc.) with values 0, -2.08e+07, 0, 0, 0, 0 + +.. _ExportModulesSec: + +Export modules +-------------- + +| Export modules allow to export computed data into external software + for post-processing. The number of export module records is specified + in analysis record using ``nmodules`` parameter (see the initial part + of section AnalysisRecord_. The general format is the + following: +| ``EntType`` [``tstep_all``] [``tstep_step #(in)``] [``tsteps_out #(rl)``] + [``subtsteps_out #(in)``] [``domain_all``] + [``domain_mask #(in)``] [``regionsets #(ia)``] + [``timeScale #(rn)``] + +| To select all solution steps, in which output will be performed, use + ``tstep_all``. To select each ``tstep_step``-nth step, use + ``tstep_step`` parameter. In order to select only specific solution + steps, the ``tsteps_out`` list can be specified, supplying solution step + number list in which output will be done. To select output for all + domain of the problem the ``domain_all`` keyword can be used. To select + only specific domains, ``domain_mask`` array can be used, where the + values of the array specify the domain numbers to be exported. If the + parameter ``subtsteps_out`` = 1, it turns on the export of intermediate + results, for example during the substepping or individual equilibrium + iterations. This option requires support from the solver. + +The export is done on region basis, on each region, the nodal + recovery is performed independently and results are exported in a + separate piece. This allows to take into account for + discntinuities, or to export variables defined only by particular + material model. The region volumes are defined using sets + containing individual elements. By default the one region is + created, containing all element in the problem domain. The + optional parameter ``regionsets`` allows to use user-defined. The + individual values refer to numbers (ids) of domain sets. Note, + that regions are determined solely using elements. + + vtkxml tstep_all cellvars 1 46 vars 1 1 primvars 1 1 stype 2 + regionsets 2 1 2 + +Optional parameter ``timeScale`` scales time in output. In transport problem, basic + units are seconds. Setting timeScale = 2.777777e-4 (=1/3600.) + converts all time data in vtkXML from seconds to hours. + + +Currently, the supported export modules are following + +- VTK export, **DEPRECATED - Use VTKXML** + + ``vtk`` [``vars #(ia)``] [``primvars #(ia)``] [``cellvars #(ia)``] + [``stype #(in)``] [``regionstoskip #(ia)``] + + ``vtkxml`` [``vars #(ia)``] [``primvars #(ia)``] [``cellvars #(ia)``] + [``ipvars #(ia)``] [``stype #(in)``] + + - The vtk module is obsolete, use vtkxml instead. Vtkxml allows to + export results recovered on region by region basis and has more + features. + + - The array ``vars`` contains identifiers for those internal + variables which are to be exported. These variables will be + smoothed and transfered to nodes. The id values are defined by + InternalStateType enumeration, which is defined in include file + “src/oofemlib/internalstatetype.hâ€. + + - The array ``primvars`` contains identifiers of primary variables + to be exported. The possible values correspond to the values of + enumerated type UnknownType, which is again defined in + “src/oofemlib/unknowntype.hâ€. Please note, that the values + corresponding to enumerated type values start from zero, if not + specified directly and that not all values are supported by + particular material model or analysis type. + + - The array ``cellvars`` contains identifiers of constant variables + defined on an element (cell), e.g. a material number. Identifier + numbers are specified in “src/oofemlib/internalstatetype.hâ€. + + - The array ``ipvars`` contains identifiers for those internal + variables which are to be exported. These variables will be + directly exported (no smoothing) as point dataset, where each + point corresponds to individual integration point. A separate vtu + file for these raw, point data will be created. The id values are + defined by InternalStateType enumeration, which is defined in + include file “src/oofemlib/internalstatetype.hâ€. + + - The parameter ``stype`` allows to select smoothing procedure for + internal variables, which is used to compute nodal values from + values in integration points. The supported values are :math:`0` + for simple nodal averageing (generally supported only by + triangular and tetrahedral elements), :math:`1` for Zienkiewicz + Zhu recovery (default), and :math:`2` for Superconvergent Patch + Recovery (SPR, based on least square fitting). + + +- VTK pfem (particle FEM) export. Exports particle positions to vtk as a point dataset. + + ``vtkpfem`` [``vars #(ia)``] [``primvars #(ia)``] [``cellvars #(ia)``] + [``ipvars #(ia)``] [``stype #(in)``] + +- VTK memory export. This module is not producing any output, but prepares necessary data structures to suport vtk export or vtk visualization. It is used by Python interface to access vtk datasets. + + ``vtkmemory`` [``vars #(ia)``] [``primvars #(ia)``] [``cellvars #(ia)``] [``ipvars #(ia)``] + +- VTK xfem export module. Exports xfem related data. The data exported are determined + by XfemManager vtkExportFields parameter (see ``exportfields`` keyword). + + ``vtkxmlxfem`` + +- Homogenization of IP quantities in the global coordinate system (such + as stress, strain, damage, heat flow). Corresponding IP quantities + are summed and averaged over the volume. It is possible to select + region sets from which the averaging occurs. The averaging works for + all domains with an extension to trusses. A truss is considered as a + volume element with oriented stress and strain components along the + truss axis. The transformation to global components occurs before + averaging. + + ``hom`` ``ists #(ia)`` [``scale #(rn)``] [``regionSets #(ia)``] + [``strain_energy``] + + - An integer array ``ists`` specifies internal state types for + export which are defined in internalstatetype.h file. + + - The parameter ``scale`` multiplies all averaged IP quantities. + ``scale``\ =1 by default. + + - An integer array ``regionSets`` specifies region sets for + averaging. All domain is averaged by default. + + - ``strain_energy`` calculates strain energy over selected elements + (defined by sets) by + + .. math:: W^*=\int_V \int \sigma \mathrm{d} (\varepsilon-\varepsilon_{eig}) \mathrm{d} V + + where :math:`\sigma` is the stress tensor, :math:`\varepsilon` + stands for the strain tensor and :math:`\varepsilon_{eig}` is + eigenstrain tensor (originates from temperature load or prescribed + eigenstrain). Strain energy increment and total strain energy is + reported in each step. The integration uses mid-point rule for + stress and yields exact results for linear elastic materials. + +- Gauss point export is useful if one needs to plot a certain variable + (such as damage) as a function of a spatial coordinate using tools + like gnuplot. It generates files with data organized in columns, each + row representing one Gauss point. In this way, one can plot e.g. the + damage distribution along a one-dimensional bar. + ``gpexportmodule`` [``vars #(ia)``] [``ncoords #(in)``] + + - The array ``vars`` contains identifiers for those internal + variables which are to be exported. The id values are defined by + InternalStateType enumeration, which is defined in include file + “src/oofemlib/internalstatetype.hâ€. + + - Parameter ``ncoords`` specifies the number of spatial coordinates + to be exported at each Gauss point. Depending on the spatial + dimension of the domain, the points can have one, two or three + coordinates. If ``ncoords`` is set to -1, only those coordinates + that are actually used are exported. If ``ncoords`` is set to 0, + no coordinates are exported. If ``ncoords`` is set to a positive + integer, exactly ``ncoords`` coordinates are exported. If + ``ncoords`` exceeds the actual number of coordinates, the actual + coordinates are supplemented by zeros. For instance, if we deal + with a 2D problem, the actual number of coordinates is 2. For + ``ncoords``\ =3, the two actual coordinates followed by 0 will be + exported. For ``ncoords``\ =1, only the first coordinate will be + exported. + + The Gauss point export module creates a file with extension “gp†+ after each step for which the output is performed. This file contains + a header with lines starting by the symbol #, followed by the actual + data section. Each data line corresponds to one Gauss point and + contains the following data: + + #. element number, + + #. material number, + + #. Gauss point number, + + #. contributing volume around Gauss point, + + #. Gauss point global coordinates (written as a real array of length + ``ncoords``), + + #. internal variables according to the specification in ``vars`` + (each written as a real array of the corresponding length). + + | Example: + ``GPExportModule 1 tstep_step 100 domain_all ncoords 2 vars 5 4 13 31 64 65`` + + means that the \*.gp file will be written after each 100 steps and + will contain for each of the Gauss points in the entire domain its + 2 coordinates and also internal variables of type 4, 13, 31, 64 and + 65, which are the strain tensor, damage tensor, maximum equivalent + strain level, stress work density and dissipated work density. Of + course, the material model must be able to deliver such variables. + The size of the strain tensor depends on the spatial dimension, and + the size of the damage tensor depends on the spatial dimension and + type of model (e.g., for a simple isotropic damage model it will + have just 1 component while for an anisotropic damage model it may + have more). The other variables in this example are scalars, but + they will be written as arrays of length 1, so the actual value + will always be preceded by “1†as the length of the array. Since + certain internal variables have the meaning of densities (per unit + volume or area, again depending on the spatial dimension), it is + useful to have access to the contributing volume of the Gauss + point. The product of this contributing volume and the density + gives an additive contribution to the total value of the + corresponding variable. This can be exploited e.g. to evaluate the + total dissipated energy over the entire domain. + diff --git a/doc/oofemInput/conf.py b/doc/oofemInput/conf.py new file mode 100644 index 000000000..8ba105450 --- /dev/null +++ b/doc/oofemInput/conf.py @@ -0,0 +1,68 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- 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 sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'OOFEM Input Manual' +copyright = '2021, BoÅ™ek Patzák' +author = 'BoÅ™ek Patzák' + +# The full version, including alpha/beta/rc tags +release = '1.0' + + +# -- General configuration --------------------------------------------------- + +# 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.imgconverter'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# 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 = ['_build', 'Thumbs.db', '.DS_Store'] + + +# -- 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 = 'classic' + +# Add/Update "html_theme_options" like this on your conf.py +html_theme_options = {'body_max_width': '100%'} + +# 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_css_files = [ +# 'custom.css', +#] + +master_doc = 'index' + +latex_elements = { + + 'preamble': r'''\usepackage{lscape}''' +} \ No newline at end of file diff --git a/doc/oofemInput/domainrecords.rst b/doc/oofemInput/domainrecords.rst new file mode 100644 index 000000000..0a139b6bc --- /dev/null +++ b/doc/oofemInput/domainrecords.rst @@ -0,0 +1,1076 @@ + +.. _DomainRecord: + +Domain record(s) +================ + +This set of records describes the whole domain and its type. Depending +on the type of problem, there may be one or several domain records. If +not indicated, one domain record is default for all problem types. + +| The domain type is used to resolve the default number of DOFs in node + and their physical meaning. Format is following +| ``domain`` ``domainType`` +| The ``domainType`` can be one from the following + +- The ``2dPlaneStress`` and ``2d-Truss`` modes declare two default dofs + per node (u-displacement, v-displacement), + +- The ``3d`` mode declares three default dofs per node (u-displacement, + v-displacement, w-displacement), + +- The ``2dMindlinPlate`` mode declares three default dofs per node + (w-displacent, u-rotation, v-rotation). Strain vector contains + :math:`\kappa_{xx}`, :math:`\kappa_{yy}`, :math:`\kappa_{xy}`, + :math:`\gamma_{xz}`, :math:`\gamma_{yz}`. Stress vector contains + :math:`m_{xx}`, :math:`m_{yy}`, :math:`m_{xy}`, :math:`q_{xz}`, + :math:`q_{yz}`. + +- The ``3dShell`` mode declares six default dofs per node (displacement + and rotation along each axis). + +- The ``2dBeam`` mode declares three default dofs per node + (u-displacement, w-displacement, v-rotation). + +- The ``2dIncompFlow`` mode declares three default dofs per node + (u-velocity, v-velocity, and pressure). The default number of dofs + per node as well as their physical meaning can be overloaded in + particular dof manager record (see section + :ref:`NodeElementSideRecords`). + + The further records describe particular domain components - + OutputManagers, DofManagers, Elements, CrossSection models, Material + Models, Boundary and Initial Conditions and Load time functions. + +.. _OutputManagerRecord: + +Output manager record +--------------------- + +| The output manager controls output. It can filter output to specific + solution steps, and within these selected steps allows also to filter + output only to specific dof managers and elements. The format of + output manager record is +| [``tstep_all``] [``tstep_step #(in)``] [``tsteps_out #(rl)``] + [``dofman_all``] [``dofman_output #(rl)``] + [``dofman_except #(rl)``] [``element_all``] + [``element_output #(rl)``] [``element_except #(rl)``] + +| To select all solution steps, in which output will be performed, use + ``tstep_all``. To select each ``tstep_step``-nth step, use + ``tstep_step`` parameter. In order to select only specific solution + steps, the ``tsteps_out``\ list can be specified, supplying solution + step number list in which output will be done. The combination of + ``tstep_step`` and ``tsteps_out`` parameters is allowed. + +| Output manager allows also to filter output to only specific dof + managers and elements. If these specific members are selected, the + output happens only in selected solution steps. The ``dofman_all`` and + ``element_all`` parameters select all dof managers or elements + respectively. Parameter arrays ``dofman_output`` and + ``element_output`` allow to select only specific members. Numbers of + selected members are then contained in ``dofman_output`` or + ``element_output`` lists respectively. The previously selected members + can be explicitly de-selected by specifying their component numbers in + ``dofman_except`` or ``element_except`` lists. A few examples: +| ``dofman_output {1 3}`` prints nodes 1,3 +| ``dofman_output {(1 3)}`` prints nodes 1,2,3 +| ``element_output {1 3}`` prints elements 1,3 +| ``element_output {(1 3)}`` prints elements 1,2,3 +| ``element_output {(1 3) 5 6}`` prints elements 1,2,3,5,6 + +.. _ComponentsSizeRecord: + +Components size record +---------------------- + +| This record describes the number of components in related domain. The + particular records will follow immediately in input file. The general + format is: +| ``ndofman #(in)`` ``nelem #(in)`` + ``ncrosssect #(in)`` ``nmat #(in)`` ``nbc #(in)`` + ``nic #(in)`` ``nltf #(in)`` [``nbarrier #(in)``] + where + ``ndofman`` represents number of dof managers (e.g. nodes) and their + associated records, ``nelem`` represents number of elements and their + associated records, ``ncrosssect`` is number of cross sections and + their records, ``nmatdnMat`` is number of material models and their + records, ``nbc`` represents number of boundary conditions (including + loads) and their records, ``nic`` parameter determines the number of + initial conditions, and ``nltf`` represents number of time functions + and their associated records. The optional parameter ``nbarrier`` + represents the number of nonlocal barriers and their records. If not + specified, no barriers are assumed. + +.. _NodeElementSideRecords: + +Dof manager records +------------------- + +These records describe individual DofManager records (i.e. nodes or +element sides (if they manage some DOFs)). The general format is +following: + +``DofManagerType`` ``#(in)`` [``load #(ra)``] [``DofIDMask #(ia)``] +[``bc #(ia)``] [``ic #(ia)``] [``doftype #(ia)`` +``masterMask #(ia)``] <[``shared``]> +:math:`|` <[``remote``]> :math:`|` <[``null``]> +<[``partitions #(ia)``]> + +The order +of particular records is optional, the dof manager number is determined +by (``#(in)`` parameter. The numbering of individual dof managers +is arbitrary, it could be even non-continuous. In this context, one +could think of dof manager number as a label that is assigned to +individual dof manager and by which the dof manager is referenced. + +By default, the nodal DOFs are determined by asking all the connected +elements. Specifying additional dofs can be done using the using the +``DofIDMask`` array which determines their physical interpretation. Each +item of ``DofIDMask`` array describes the physical meaning of +corresponding DOF in dof manager. Currently the following values are +supported: {u-displacement=1, v-displacement=2, w-displacement=3, +u-rotation=4, v-rotation=5, w-rotation=6, u-velocity=7, v-velocity=8, +w-velocity=9, temperature=10, pressure=11, special dofs for +gradient-type constitutive models=12 and 13, mass concentration=14, +special dofs for extended finite elements (XFEM)=15–30}. **It is not +allowed to have two DOFs with the same physical meaning in the same +DofManager.** + +The applied primary (Dirichlet) boundary conditions are specified using +"bc" record, while natural boundary conditions using "load" parameter. + +- The size of "bc" array (primary bc) should be equal to number of DOFs + in dof manager and i-th value relates to i-th DOF - the ordering and + physical meaning of DOFs is determined by domain record and can be + optionally specified for each dof manager individually (see next + paragraph). The values of this array are corresponding boundary + condition record numbers or zero, if no primary bc is applied to + corresponding DOF. The compatible boundary condition type are + required: primary conditions require "BoundaryCondition" records. + +- The load "array" contains record numbers of natural boundary + conditions that are applied. The required record type for natural + condition is "NodalLoad". The actual value is the summation of all + contributions, if more than one natural bc is applied. See section on + boundary conditions for the syntax. Please note, that the values of + natural bc for individual DOFs are specified in its record, not in + dofmanager record. + +By default, if "bc" and/or "load" parameters are omitted, no primary +and/or natural bc are applied. Analogously, initial conditions are +represented using ``ic`` array. The size of ``ic`` array should be equal +to number of DOFs in dof manager. The values of this array are +corresponding initial condition record numbers or zero, if no initial +condition is applied to corresponding DOF (in this case zero value is +assumed as value of initial condition). + +Parameters ``dofType`` and ``masterMask`` allows to connect some dof +manager’s dofs (so-called “slave†dofs) to corresponding dof (according +to their physical meaning) of another dof manager (so-called “master†+dof). The master slave principle allows for example simple modeling of +structure hinges, where multiple elements are connected by introducing +multiple nodes (with same coordinates) sharing the same displacement +dofs and each one possessing their own rotational dofs. Parameter +``dofType`` determines the type of (slave) dof to create. Currently +supported values are 0 for master DOF, 1 for simpleSlave DOF (linked to +another single master DOF), and 2 for general slave dof, that can depend +on different DOFs belonging to different dof managers. If ``dofType`` is +not specified, then by default all DOFs are created as master DOFs. If +provided, masterMask is also required. The meaning of ``masterMask`` +parameter is depending on type of particular dofManager, and will be +described in corresponding sections. + +Supported DofManagerType keywords are + +- Node record + + | ``Node`` ``coords #(ra)`` [``lcs #(ra)``] + | Represent an abstraction for finite element node. The node + coordinates in space (given by global coordinate system) are + described using ``coords`` attribute. This array contains x, y and + possibly z (depends on problem under consideration) coordinate of + node. By default, the coordinate system in node is global + coordinate system. User defined local coordinate system in node is + described using ``lcs`` array. This array contains six numbers, + where the first three numbers represent a directional vector of the + local x-axis, and the next three numbers represent a directional + vector of the local y-axis. The local z-axis is determined using a + vector product. A right-hand coordinate system is assumed. If user + defined local coordinate system in node is specified, then the + boundary conditions and applied loading are specified in this local + coordinate system. The reactions and displacements are also in + ``lcs`` system at the output. + + The node can create only master DOFs and SimpleSlave DOFs, so the + allowable values of ``dofType`` array are in range 0,1. For the Node + dof manager, the ``masterMask`` is the array of size equal to number + of DOFs, and the i-th value determines the master dof manager, to + which i-th dof is directly linked (the dof with same physical meaning + are linked together). The local coordinate system in node with same + linked dofs is supported, but it should be exactly the same as on + master. + +- Rigid arm record + + | ``RigidArmNode`` ``coords #(ra)`` ``master #(in)`` + [``masterMask #(ia)``] [``lcs #(ra)``] + | Represent node connected to other node (called master) using rigid + arm. Rigid arm node DOFs can be linked to master (via rigid arm + transformation) or can be independent. The rigid arm node allows to + avoid very stiff elements used for modelling the rigid-arm + connection. The rigid arm node maps its dofs to master dofs using + simple transformations (small rotations are assumed). Therefore, + the contribution to rigid arm node can be localized directly to + master related equations. The rigid arm node can not have its own + boundary or initial conditions, they are determined completely from + master dof conditions. Currently it is possible to map only certain + dofs - see ``dofType``. Linked DOFs should have dofType value equal + to 2, non-linked (primary) DOFs 0. + + Rigid arm node can be loaded independently of master. The node + coordinates in space (given by global coordinate system) are + described using ``coords`` field. This array contains x, y and + possibly z (depends on problem under consideration) coordinate of + node. The ``master`` parameter is the master node number, to which + rigid arm node dofs are mapped. The rigid arm node and master can + have arbitrary local coordinate systems (if not specified, global + one is assumed). + + The optional parameter ``masterMask`` allows to specify how + particular mapped DOF depends on master DOFs. The size of + ``masterMask`` array should be equal to number of DOFs. For all + linked DOFs (with corresponding dofType value equal to 2) the + corresponding value of ``masterMask`` array should be 1. + + The local coordinate system in rigid arm node is supported, the + coordinate system in master and slave can be different. If no lcs is + set, global one is assumed.the global cs applies. + +- Hanging node + + ``HangingNode`` ``coords #(ra)`` ``dofType #(in)`` + [``masterElement #(in)``] [``masterRegion #(in)``] + + Hanging node is connected to an a master element using generalized + interpolation. Hanging node posses no degrees of freedom (except + unlined dofs) - all values are interpolated from corresponding master + elements and its DOFs. arbitrary FE mesh of concrete specimen or to + facilitate the local refinement of FE mesh. The hanging nodes can be + in a chain. + + The contributions of hanging node are localized directly to master + related equations. The hanging node can have its own boundary or + initial conditions, but only for primary unlinked DOFs. For linked + DOFs, these conditions are determined completely from master DOF + conditions. The local coordinate system should be same for all master + nodes. The hanging node can be loaded independently of its master. + + Values of array ``dofType`` can have following values: 0-primary DOF, + 2-linked DOF. + + The value of ``masterElement`` specifies the element number to which + the hanging node is attached. The node can be attached to any + arbitrary coordinate within the master element. The element must + support the necessary interpolation classes. The same interpolation + for unknowns and geometry is assumed. + + The no (or -1) value for ``masterElement`` is supplied, then the node + will locate the element closest to its coordinate. If no (or zero) + value for ``masterRegion`` is supplied, then all regions will be + searched, otherwise only the elements in cross section with number + ``masterRegion``. If ``masterElement`` is directly supplied + ``masterRegion`` is unused. + +- Slave node + + ``SlaveNode`` ``coords #(ra)`` ``dofType #(in)`` + ``masterDofMan #(ia)`` ``weights #(ra)`` + + Works identical to hanging node, but the weights (``weights``) are + not computed from any element, but given explicitly, as well as the + connected dof managers (``masterDMan``). + +- General Slave node + + ``GeneralSlaveNode`` ``coords #(ra)`` ``dofType #(ia)`` + ``masterSizes #(ia)`` ``masterList #(ia)`` ``masterWeights #(ra)`` + + Generalization of SlaveNode; Meaning of ``dofType`` is the same as for SlaveNode or HangingNode, i.e., 0 means primary DOF, while + 2 means linked DOF. Array ``masteSizes`` specifies number of master dofs for each slave dof. Array ``masterList`` specifies master nodes and their dofs for all the slave dofs. Finally, ``masterList`` provides the associated weights. + + +- Element side + + | ``ElementSide`` + | Represents an abstraction for element side, which holds some + unknowns. + +.. _pfemparticles: + +- PFEMParticle + + | ``PFEMParticle`` ``coords #(ra)`` + | Represent the particle used in PFEM analysis. + +.. _interactionparticle: + +- InteractionPFEMParticle + + | ``InteractionPFEMParticle`` ``coords #(ra)`` ``bc #(ia)`` + ``coupledNode #(in)`` + | Represent a special particle used in the PFEM-part of the + FluidStructureProblem. The particle is attached to ``coupledNode`` + from the structural counter part. + InteractionBoundaryCondition (see :ref:`interactionbc`) + must be prescribed under ``bc`` to access the velocities from solid + nodes. + +.. _ElementsRecords: + +Element records +--------------- + +These records specify a description of particular elements. The general +format is following: + +``ElementType`` ``#(in)`` ``mat #(in)`` ``crossSect #(in)`` +``nodes #(ia)`` [``bodyLoads #(ia)``] [``boundaryLoads #(ia)``] +[``activityltf #(in)``] [``lcs #(ra)``] +<[``partitions #(ia)``]> <[``remote``]> + +The order of element records is optional, the element number is +determined by ``#(in)`` parameter. The numbering of individual +elements is arbitrary, it could be even non-continuous. In this context, +one could think of element number as a label that is assigned to +individual elements and by which the element is referenced. + +Element material is described by parameter ``mat``, which contains +corresponding material record number. Element cross section is +determined by cross section with ``crossSect`` record number. Element +dof managers (nodes, sides, etc.) defining element geometry are +specified using ``nodes`` array. + +Body load acting on element is specified using ``bodyLoads`` array. +Components of this array are corresponding load record numbers. The +loads should have the proper type (body load type), otherwise error will +be generated. + +Boundary load acting on element boundary is specified using +``boundaryLoads`` array. The format of this array is + +.. math:: 2\cdot size \; lnum(1)~id(1)~\dots~lnum(size)~id(size), + +where :math:`size` is total number of loadings applied to element, +:math:`lnum(i)` is the applied load number, and :math:`id(i)` is the +corresponding entity number, to which the load is applied (for example a +side or a surface number). The entity numbering is element dependent and +is described in element specific sections. The applied loads must be of +proper type (boundary load type), otherwise error is generated. + +The support for element insertion and removal during the analysis is +provided. One can specify optional time function (identified by its id +using ``activityltf`` parameter). The nonzero value of this time +function indicates, whether the element is active (nonzero value, the +default) or inactive (zero value) at particulat solution step. Tested +for structural and transport elements. This feature allows considering +temperature evolution of layered casting of concrete, where certain +layers needs to be inactive before they are cast. See a corresponding +example in oofem tests how to enforce hydrating material model, boundary +conditions and element activity acting concurrently. + +Orientation of local coordinates can be specified using ``lcs`` array. +This array contains six numbers, where the first three numbers represent +a directional vector of local x-axis, and the next three numbers +represent a directional vector of local y-axis. The local z-axis is +determined using the vector product. The ``lcs`` array on the element is +particularly useful for modeling of orthotropic materials which follow +the element orientation. On a beam or truss element, the ``lcs`` array +has no effect and the 1D element orientation is aligned with the global +:math:`xx` component. + +Available material models, their outline and corresponding parameters +are described in separate **Element Library Manual.** + +.. _SetRecords: + +Set records +----------- + +Sets specify regions of the geometry as a combination of volumes, +surfaces, edges, and nodes. The main usage of sets are to connect +regions of elements to a given cross section or apply a boundary +condition, though sets can be used for many other things as well. + +``Set`` ``#(in)`` [``elements #(ia)``] [``elementranges #(rl)``] +[``allElements``] [``nodes #(ia)``] [``noderanges #(rl)``] [``allNodes``] +[``elementboundaries #(ia)``] [``elementedges #(ia)``] + +Volumes (elements) and nodes can be specified using either a list, +``elements``, ``nodes``, or with a range list ``elementranges``, +``noderanges``. Edges ``elementedges``, and surfaces +``elementboundaries``, are specified in a interleaved list, every other +number specifying the element, and edge/surface number (the total length +of the list being twice the number of surfaces/edges). The internal +numbering of edges/surfaces is available in the **Element Library +Manual**. + +Note that edge loads (singular loads given in “newton per length†(or +equivalent), should be applied to ``elementedges``, surface loads +“newton per area†on ``elementboundaries``, and bulk loads “newton per +volume†on ``elements``. + +Example 1: A deadweight (gravity) load would be applied to the +``elements`` in a set, while a distributed line load would be applied to +the midline “edge†of the beam element, thus should be applied to a +``elementedges`` set. In the latter case, the midline of the beam is +defined as the first (and only) “edge†of the beam. + +Example 2: Axisymmetric structural element analysis: A deadweight load +would be applied to ``elements`` in a set. A external pressure would be +defined as a surface load an be applied to the ``elementboundaries`` in +a set. The element integrates the load (analytically) around the axis, +so the load would still count as a surface load. + +.. _CrossSectionRecords: + +Cross section records +--------------------- + +These records specify a cross section model descriptions. The general +format is following: + +``CrossSectType`` ``#(in)`` + +The order of particular cross section records is optional, cross section +model number is determined by ``#(in)`` parameter. The numbering +should start from one and should end at n, where n is the number of +records. + +The crossSectType keyword can be one from following possibilities + +- | Integral cross section with constant properties + | ``SimpleCS`` [``thick #(rn)``] [``width #(rn)``] [``area #(rn)``] + [``iy #(rn)``] [``iz #(rn)``] [``ik #(rn)``] + [``shearareay #(rn)``] [``shearareaz #(rn)``] + ``beamshearcoeff #(rn)`` + | Represents integral type of cross section model. In current + implementation, such cross section is described using cross section + thick (``thickVal``) and width (``widthVal``). For some problems + (for example 3d), the corresponding volume and cross section + dimensions are determined using element geometry, and then you can + omit some (or all) parameters (refer to documentation of individual + elements for required cross section properties). Parameter ``area`` + allows to set cross section area, parameters ``iz``, ``iz``, and + ``ik`` represent inertia moment along y and z axis and Saint-Venant torsional + constant. Parameter ``beamshearcoeff`` allows to set shear + correction factor, or equivalent shear areas (``shearareay`` and + ``shearareaz`` parameters) can be provided. These cross section + properties are assumed to be defined in local coordinate system of + element. + +- | Integral cross section with variable properties + | ``VariableCS`` [``thick #(expr)``] [``width #(expr)``] [``area #(expr)``] + [``iy #(expr)``] [``iz #(expr)``] [``ik #(expr)``] + [``shearareay #(expr)``] [``shearareaz #(expr)``] + | Represents integral type of cross section model, where individual + cross section parameters can be expressed as an arbitrary function + of global coordinates x,y,z. Similar to SimpleCS, for some problems + (for example 3d), the corresponding volume and cross section + dimensions are determined using element geometry, then you can omit + many (or some) parameters (refer to documentation of individual + elements for required cross section properties). Parameter ``area`` + allows to set cross section area, parameters ``iz``, ``iz``, and + ``ik`` represent inertia moment along y and z axis and Saint-Venant torsional + constant. Parameters (``shearareay`` and ``shearareaz`` + determine shear area, which is required by beam and plate elements. + All cross section properties are assumed to be defined in local + coordinate system of element. + +- | Layered cross section + | ``LayeredCS`` ``nLayers #(in)`` ``LayerMaterials #(ia)`` + ``Thicks #(ra)`` ``Widths #(ra)`` [``midSurf #(rn)``] [``nintegrationpoints #(in)``] [``layerintegrationpoints #(ia)``] [``beamshearcoeffxz #(rn)``] + | Represents the layered cross section model, based on geometrical + hypothesis, that cross sections remain planar after deformation. + Number of layers is determined by ``nLayers`` parameter. Materials + for each layer are specified by ``LayerMaterials`` array. For each + layer is necessary to input geometrical characteristic, thick - + using ``Thicks`` array, and width - using ``Widths`` array. + Position of mid surface is determined by its distance from bottom + of cross section using ``midSurf`` parameter (normal and momentum + forces are then computed with regard to it’s position, by default it is located at average thickness position). + The number of integration points per layer can be specified using ``nintegrationpoints`` parameter, default is one integration point. It is also possible to set up different number of integration points per individual layer using ``layerintegrationpoints`` array, where its size should be equal to number of layers configured. The ``layerintegrationspoints`` parameter overrides the ``nitengrationpoints`` setting. The Gauss integration rule is used for setting up integration points in each layer. + | The optional parameter ``beamshearcoeffxz`` allows to set shear correction factor for 2D beam sections, + controlling shear effective area used to evaluate shear force (default value is 1.0). + Elements using this cross section model must implement layered cross section + extension. For information see element library manual. + +- | Fibered cross section + | ``FiberedCS`` ``nfibers #(in)`` ``fibermaterials #(ia)`` + ``thicks #(ra)`` ``widths #(ra)`` ``thick #(rn)`` + ``width #(rn)`` ``fiberycentrecoords #(ra)`` + ``fiberzcentrecoords #(ra)`` + | Cross section represented as a set of rectangular fibers. It is + based on geometrical hypothesis, that cross sections remain planar + after deformation (3d generalization of layered approach for + beams). Paramater ``nfibers`` determines the number of fibers that + together form the overall cross section. The model requires to + specify a material model corresponding to particular fiber using + ``fibermaterials`` array. This array should contain for each fibre + corresponding material model number (the material model specified + on element level has no meaning in this particular case). **The + geometry of cross section is determined from fiber dimensions and + fiber positions, all input in local coordinate system of the beam + (yz plane).** The thick and width of each fiber are determined + using ``thicks`` and ``widths`` arrays. The overall thick and width + are specified using parameters ``thick`` and ``width``. Positions + of particular fibers are specified by providing coordinates of + center of each fiber using ``fiberycentrecoords`` array for + y-coordinates and ``fiberzcentrecoords`` array for z-coordinates. + +- | Warping cross section + | ``WarpingCS`` ``WarpingNode #(in)`` + | Represents the cross section for Free warping analysis, see section + :ref:`FreeWarping`. The ``WarpingNode`` parametr defines the + number of external node with prescribed boundary condition which + corresponds to the relative twist of warping cross section. + +.. _MaterialTypeRecords: + +Material type records +--------------------- + +These records specify a material model description. The general format +is following: + +``MaterialType`` ``#(in)`` ``d #(rn)`` + +The order of particular material records is optional, the material +number is determined by ``#(in)`` parameter. The numbering should +start from one and should end at n, where n is the number of records. +Material density is compulsory parameter and it’s value is given by +``d`` parameter. + +Available material models, their outline and corresponding parameters +are described in separate **Material Library Manual**. + +.. _NonlocalBarrierRecords: + +Nonlocal barrier records +------------------------ + +Nonlocal material models of integral type are based on replacement of +certain suitable local quantity in local constitutive law by their +nonlocal counterparts, that are obtained as weighted average over some +characteristic volume. The weighted average is computed as a sum of a +remote value multiplied by weight function value. The weight function +typically depend on a distance between remote and receiver points and +decreases with increasing distance. In some cases, it is necessary to +disregard mutual interaction between some points (for example if they +are on the opposite sides of a thin notch, which prevents the nonlocal +interactions to take place). The barriers are the way how to introduce +these constrains. The barrier represent a curve (in 2D) or surface (in +3D). When the line connecting receiver and remote point intersects a +barrier, the barriers is activated and the corresponding interaction is +not taken into account. + +Currently, the supported barrier types are following: + +- Polyline barrier + + | ``polylinebarrier`` ``#(in)`` ``vertexnodes #(ia)`` [``xcoordindx #(in)``] + [``ycoordindx #(in)``] + | This represents a polyline barrier for 2D problems. Barrier is a + polyline, defined as a sequence of nodes representing vertices. The + vertices are specified using parameter ``vertexnodes`` array, which + contains the node numbers. The optional parameters ``xcoordindx`` + and ``ycoordindx`` allow to select the plane (xy, yz, or xz), where + the barrier is defined. The ``xcoordindx`` is the first coordinate + index, ``ycoordindx`` is the second. The default values are 1 for + ``xcoordindx`` and 2 for ``ycoordindx``, representing barrier in xy + plane. + +- Symmetry barrier + + | ``symmetrybarrier`` ``#(in)`` ``origin #(ra)`` ``normals #(ra)`` + ``activemask #(ia)`` + | Implementation of symmetry barier, that allows to specify up to + three planes (orthogonal ones) of symmetry. This barrier allows to + model the symmetry of the averaged field on the boundary without + the need of modeling the other part of structure across the plane + of symmetry. It is based on modifying the integration weights of + source points to take into account the symmetry. The potential + symmetry planes are determined by specifying orthogonal + right-handed coordinate system, where axes represent the normals of + corresponding symmetry planes. Parameter ``origin`` determines the + origin of the coordinate system, the ``normals`` array contains + three components of x-axis direction vector, followed by three + components of y-axis direction vector (expressed in global + coordinate system). The z-axis is determined from the orthogonality + conditions. Parameter ``activemask`` allows to specify active + symmetry planes; i-th nonzero value activates the symmetry barrier + for plane with normal determined by corresponding coordinate axis + (x=1, y=2, z=3). + +.. _LoadBoundaryInitialConditions: + +Load and boundary conditions +---------------------------- + +These records specify description of boundary conditions. The general +format is following: + +``EntType`` ``#(in)`` ``loadTimeFunction #(in)`` [``valType #(in)``] +[``dofs #(ia)``] [``isImposedTimeFunction #(in)``] + +The order of particular records is optional, boundary condition number +is determined by ``#(in)`` parameter. The numbering should start +from one and should end at n, where n is the number of records. Time +function value (given by ``loadTimeFunction`` parameter) is a +multiplier, using which each component (value of loading or value of +boundary condition) describes its time variation. The optional parameter +``valType`` allows to determine the physical meaning of bc value, which +is sometimes required. Supported values are (1 - temperature, 2 - +force/traction, 3 - pressure, 4 - humudity, 5 - velocity, 6 - +displacement). Another optional parameter ``dofs`` is used to determine +which dofs the boundary condition should act upon. It is not relevant +for all BCs.. + +The nonzero value of ``isImposedTimeFunction`` time function indicates +that given boundary condition is active, zero value indicates not active +boundary condition in given time (the bc does not exist). By default, +the boundary condition applies at any time. + +Currently, EntType keyword can be one from + +- Dirichlet boundary condition + + ``BoundaryCondition`` ``prescribedvalue #(rn)`` [``d #(rn)``] + + Represents boundary condition. Prescribed value is specified using + ``prescribedvalue`` parameter. The physical meaning of value is fully + determined by corresponding DOF. Optionally, the prescribed value can + be specified using ``d`` parameter. It is introduced for + compatibility reasons. If ``prescribedvalue`` is specified, then + ``d`` is ignored. + +- Prescribed gradient boundary condition (Dirichlet type) + + ``PrescribedGradient`` ``gradient #(rm)`` [``cCoords #(ra)``] + + Prescribes :math:`v_i = d_{ij}(x_j-\bar{x}_j)` or + :math:`s = d_{1j}(x_j - \bar{x}_j)` where :math:`v_i` are primary + unknowns, :math:`x_j` is the coordinate of the node, :math:`\bar x` + is ``cCoords`` and :math:`d` is ``gradient``. The parameter + ``cCoords`` defaults to zero. This is typical boundary condition in + multiscale analysis where :math:`d = \partial_x s` would a + macroscopic gradient at the integration point, i.e. this is a + boundary condition for prolongation. It is also convenient to use + when one wants to test a arbitrary specimen for shear. + +- Mixed prescribed gradient / pressure boundary condition (Active type) + + ``MixedGradientPressure`` ``devGradient #(ra)`` ``pressure #(rn)`` + [``cCoord #(ra)``] + + All boundary conditions of ensures that the deviatoric gradient and + pressure is at least weakly fullfilled on the prescribed domain. They + are used for computational homogenization of incompressible flow or + elasticity problems. + +- Mixed prescribed gradient / pressure boundary condition (Weakly + periodic type) + + ``MixedGradientPressureWeaklyPeriodic`` ``order #(rn)`` + + Prescribes a periodic constant (unknown) stress tensor along the + specified boundaries. For ``order`` set to 1, one obtains the same + results as the Neumann boundary condition. + +- Mixed prescribed gradient / pressure boundary condition (Neumann + type) + + ``MixedGradientPressureNeumann`` + + Prescribes a constant (unknown) deviatoric stress tensor along the + specified boundaries. Additional unknowns appears, + :math:`\boldsymbol{\sigma}_\mathrm{dev}`, which is handled by the + boundary condition itself (no control from the input file). The input + devGradient is weakly fulfilled (homogenized over the elementsides). + As with the the Dirichlet type, the volumetric gradient is free. This + is useful in multiscale computations of RVE’s that experience + incompressible behavior, typically fluid problems. In that case, the + element sides should cover the entire RVE boundary. It is also + convenient to use when one wants to test a arbitrary specimen for + shear, with a free volumetric part (in which case the pressure is set + to zero). Symmetry is not assumed, so rigid body rotations are + removed, but translations need to be prescribed separately. + +- Mixed prescribed gradient / pressure boundary condition (Dirichlet + type) + + ``MixedGradientPressureDirichlet`` + + Prescribes + :math:`v_i = d_{\mathrm{dev},ij}(x_j-\bar{x}_j) + d_\mathrm{vol}(x_i-\bar{x}_i)`, + and a pressure :math:`p`. where :math:`v_i` are primary unknowns, + :math:`x_j` is the coordinate of the node, :math:`\bar x` is + ``cCoords`` and :math:`d_\mathrm{dev}` is ``devGradient``. The + parameter ``cCoords`` defaults to zero. An additional unknown + appears, :math:`d_\mathrm{vol}`, which is handled by the boundary + condition itself (no control from the input file). This unknown is in + a way related to the applied pressure. This is useful in multiscale + computations of RVE’s that experience incompressible behavior, + typically fluid problems. It is also convenient to use when one wants + to test a arbitrary specimen for shear, with a free volumetric part + (in which case the pressure is set to zero). + +- Nodal fluxes (loads) + ``NodalLoad`` ``components #(ra)`` [``cstype #(in)``] + Concentrated nodal load. The components of nodal load vector are + given by ``components`` parameter. The size of this vector + corresponds to a total number of nodal DOFs, and i-th value + corresponds to i-th DOF in associated dof manager. The load can be + defined in global coordinate system (``cstype`` = 0) or in entity - + specific local coordinate system (``cstype`` = 1, default). + +- ``PrescribedTractionPressureBC`` + + Represents pressure boundary condition (of Dirichlet type) due to + prescribed tractions. In CBS algorithm formulation the prescribed + traction boundary condition leads indirectly to pressure boundary + condition in corresponding nodes. This boundary condition implements + this pressure bc. The value of bc is determined from applied + tractions, that should be specified on element edges/surfaces using + suitable boundary loads. + +- Linear constraint boundary condition + + ``LinearConstraintBC`` ``weights #(ra)`` [``weightsLtf #(ia)``] + ``dofmans #(in)`` ``dofs #(in)`` ``rhs #(rn)`` + [``rhsLtf #(in)``] ``lhstype #(ia)`` ``rhsType #(ia)`` + + This boundary condition implements a linear constraint in the form + :math:`\sum_i w_ir_i = c`, where :math:`r_i` are unknowns related to + DOFs determined by ``dofmans`` and ``dofs``, the weights are + determined by ``weights`` and ``weightsLtf``. The constant is + determined by ``rhs`` and ``rhsLtf`` parameters. This boundary + condition is introduced as additional stationary condition using + Lagrange multiplier, which is an additional degree of freedom + introduced by this boundary condition. + + The individual DOFs are determined using dof manager numbers + (``dofmans`` array) and corresponding DOF indices (``dofs``). The + weights corresponding to participating DOFs are specified using + ``weights`` array. The weights are multiplied by value returned by + load time function, associated to individual weight using optional + ``weightsLtf`` array. By default, all weights are set to 1. The + constant :math:`c` is determined by ``rhs`` parameter and it is + multiplied by the value of load time function, specified using + ``rhsLtf`` parameter, or by 1 by default. The characteristic + component, to which this boundary condition contributes must be + identified using ``lhstype`` and ``rhsType`` parameters, values of + which are corresponding to CharType enum. The left hand side + contribution is assembled into terms identified by ``lhstype``. The + rhs contribution is assembled into the term identified by ``rhsType`` + parameter. Note, that multiple values are allowed, this allows to + select all variants of stifness matrix, for example. Note, that the + size of ``dofmans``, ``dofs``, ``weights``, ``weightsLtf`` arrays + should be equal. + +.. _interactionbc: + +- InteractionBoundaryCondition + + ``InteractionBoundaryCondition`` + + Is a special boundary condition prescribed on + InteractionPFEMParticles (see interactionparticle_ + in the PFEM part of the FluidStructureProblem. This sort of particles + is regarded as it would have prescribed velocities, but the values + change dynamically, as the solid part deforms. The velocities are + obtained from coupled structural nodes. + +- Body loads + + - Volume flux (load) + + | ``DeadWeight`` ``components #(ra)`` + | Represents dead weight loading applied on element volume (for + structural elements). For transport problems, it represents the + internal source, i.e. the rate of (heat) generated per unit volume. + The magnitude of load for specific i-th DOF is computed as product + of material density, corresponding volume and i-th member of + ``components`` array. + + - Structural temperature load + + ``StructTemperatureLoad`` ``components #(ra)`` + + Represents temperature loading imposed to some elements. The members + of ``components`` array represent the change of temperature (or + change of temperature gradient) corresponding to specific element + strain components. See element library manual for details. + + - Structural eigenstrain load + ``StructEigenstrainLoad`` ``components #(ra)`` + + Prescribes eigenstrain (or stress-free + strain) to a structural element. The array of ``components`` is + defined in the global coordinate system. The number of components + corresponds to a material mode, e.g. plane stress has three + components and 3D six. Periodic boundary conditions can be imposed + using eigenstrains and master-slave nodes. Consider decomposition of + strain into average and fluctuating par + .. math:: \boldsymbol{\varepsilon}(\boldsymbol{x}) = \langle \boldsymbol{\varepsilon} \rangle + \boldsymbol{\varepsilon}^*(\boldsymbol{x}) + + where :math:`\langle \boldsymbol{\varepsilon} \rangle` can be imposed + as eigenstrain over the domain and the solution gives the fluctuating + part :math:`\boldsymbol{\varepsilon}^*(\boldsymbol{x})`. Master-slave + nodes have to interconnect opposing boundary nodes of a unit cell. + +- Boundary loads + - Constant edge fluxes (load) + + ``ConstantEdgeLoad`` ``loadType #(in)`` ``components #(ra)`` + [``dofexcludemask #(ia)``] [``csType #(in)``] + [``properties #(dc)``] [``propertytf #(dc)``] + + - Constant surface fluxes (load) + + ``ConstantSurfaceLoad`` ``loadType #(in)`` ``components #(ra)`` + [``dofexcludemask #(ia)``] [``csType #(in)``] + [``properties #(dc)``] [``propertytf #(dc)``] + + Represent constant edge/surface loads or boundary conditions. + Parameter ``loadType`` distinguishes the type of boundary condition. + Supported values are specified in bctype.h: + + * ``loadType`` = 2 prescribed flux input (Neumann boundary + condition), + + * ``loadType`` = 3 uniform distributed load or the convection + (Newton) BC. Parameter ``components`` contains the environmental + values (temperature of the environment) corresponding to element + unknowns, and ``properties`` dictionary should contain value of + transfer (convection) coefficient (assumed to be a constant) under + the key ’a’, + + * ``loadType`` = 7 specifies radiative boundary condition + (Stefan-Boltzmann). It requires to specify emmisivity + :math:`\varepsilon\in\langle 0,1\rangle`, the ``components`` array + contains the environmental values (temperature of the + environment). Default units are Celsius. Optional parameter + ``temperOffset`` = 0 can be used to calculate in Kelvin. + + + If the boundary condition corresponds to distributed force load, the + ``components`` array contains components of distributed load + corresponding to element unknowns. The load is specified for all DOFs + of object to which is associated. For some types of boundary + conditions the zero value of load does not mean that the load is not + applied (Newton’s type of bc, for example). Then some mask, which + allows to exclude specific dofs is necessary. The ``dofexcludemask`` + parameter is introduced to alow this. It should have the same size as + ``components`` array, and by default is filled with zeroes. If some + value of dofExcludeMask is set to nonzero, then the corresponding + componentArray is set to zero and load is not applied for this DOF. + If the boundary condition corresponds to prescribed flux input, then + the ``components`` array contains the components of prescribed input + flux corresponding to element unknowns. + + The properties can vary in time. Each property can have associated + time function which determines its time variation. The time functions + are set up using optional ``propertytf`` dictionary, containing for + selected properties the corresponding time function number. The time + function must be registered under the same key as in ``properties`` + dictionary. The property value is then computed by product of + property value (determined by ``properties``) and corresponding time + function evaluated at given time. If no time function provided for + particula property, a unit constant function is assumed. + + The load can be defined in global coordinate system (``csType`` = 0, + default) or in entity - specific local coordinate system (``csType`` + = 1). + + - Linear edge flux (load) + + ``LinearEdgeLoad`` ``loadType #(in)`` ``components #(ra)`` + [``dofexcludemask #(ia)``] [``csType #(in)``] + + Represents linear edge load. The meanings of parameters ``csType`` + and ``loadType`` are the same as for **ConstantEdgeLoad**. In + ``components`` array are stored load components for corresponding + unknowns at the beginning of edge, followed by values valid for end + of edge. The load can be defined in global coordinate system + (``csType`` = 0, default) or in entity - specific local coordinate + system (``csType`` = 1). + + - InteractionLoad + + ``InteractionLoad`` ``ndofs #(in)`` ``loadType #(in)`` + ``Components #(ra)`` [``csType #(in)``] + ``coupledparticles #(ia)`` + + Represents a fluid pressure induced load in the solid part of the + FluidStructureProblem. The meanings of parameters ``ndofs``, + ``csType``, and ``loadType`` are the same as for **LinearEdgeLoad**. + In ``Components`` array are stored load components for corresponding + unknowns at the beginning of edge (``ndofs`` values), followed by + values valid for end of edge (``ndofs`` values). The load should be + defined in global coordinate system (``csType`` = 0) as it acts in + normal direction of the edge. Array ``coupledparticles`` assign + PFEMParticles from the fluid part of the problem providing fluid + pressure. + +.. _InitialConditions: + +Initial conditions +------------------ + +These records specify description of initial conditions. The general +format is following: + +``InitialCondition`` ``#(in)`` ``conditions #(dc)`` +The order of particular +records is optional, load, boundary or initial condition number is +determined by (``num``\ #)(in) parameter. The numbering should start +from one and should end at n, where n is the number of records. Initial +parameters are listed in ``conditions`` dictionary using keys followed +by their initial values. Now ’v’ key represents velocity and ’a’ key +represents acceleration. + +.. _TimeFunctionsRecords: + +Time functions records +---------------------- + +These records specify description of time functions, which generally +describe time variation of components during solution. The general +format is following: + +``TimeFunctType`` ``#(in)`` [``initialValue #(rn)``] + +The order of these records is optional, time function number is +determined by ``#(in)`` parameter. The ``initialValue`` parameter +allows to control the way, how increment of receiver is evaluated for +the first solution step. This first solution step increment is evaluated +as the difference of value of receiver at this first step and given +initial value (which is by default set to zero). The increments of +receiver in subsequent steps are computed as a difference between +receiver evaluated at given solution step and in previous step. + +The numbering should start from one and should end at n, where n is the +number of records. + +Currently, TimeFunctType keyword can be one from + +- Constant function + + ``ConstantFunction`` ``f(t) #(rn)`` + + Represents the constant time function, with value ``f(t)``. + +- Peak function + + ``PeakFunction`` ``t #(rn)`` ``f(t) #(rn)`` + + Represents peak time function. If time is equal to ``t`` value, then + the value of time function is given by ``f(t)`` value, otherwise zero + value is returned. + +- Piecewise function + + ``PiecewiseLinFunction`` [``nPoints #(in)`` ``t #(ra)`` ``f(t) #(ra)``] [ + ``datafile #("string")``] + + Represents the piecewise time function. The particular time values in + ``t`` array should be sorted according to time scale. Corresponding + time function values are in ``f(t)`` array. Value for time, which is + not present in ``t`` is computed using liner interpolation scheme. + Number of time-value pairs is in ``nPoints`` parameter. + + The second alternative allows reading input data from an external + ASCII file. A hash commented line (#) is skipped during reading. File + name should be eclosed with " ". + +- Heaviside-like time function + + ``HeavisideLTF`` ``origin #(rn)`` ``value #(rn)`` + + Up to time, given by parameter ``origin``, the value of time function + is zero. If time greater than ``origin`` parameter, the value is + equal to parameter ``value`` value. + +- User defined + + ``UsrDefLTF`` ``f(t) #(expr)`` [``dfdt(t) #(expr)``] + [``d2fdt2(t) #(expr)``] + + Represents user defined time function. The expressions can depend on + “t†parameter, for which actual time will be substituted and + expression evaluated. The function is defined using ``f(t)`` + parameter, and optionally, its first and second time derivatives + using ``dfdt(t)`` and ``d2fdt2(t)`` parameters. The first and second + derivatives may be required, this depend on type of analysis. + + Very general, but relatively slow. + +.. _XFEMManagerRecords: + +Xfem manager record and associated records +------------------------------------------ + +| This record specifies the number of enrichment items and simulation + options common for all enrichment items. Functions used for enrichment + (e.g. Heaviside, abs or branch functions) are not specified here, they + are specified for each enrichment item separately. The same holds for + the geometrical representation of each enrichment item (e.g. a polygon + line or a circle). Currently, OOFEM supports XFEM simulations of + cracks and material interfaces in 2D. The input format for the XFEM + manager is: +| ``XfemManager`` ``numberofenrichmentitems #(in)`` + ``numberofgppertri #(in)`` ``debugvtk #(in)`` + ``vtkexport #(in)`` ``exportfields #(in)`` + + where + ``numberofenrichmentitems`` represents number of enrichment items, + ``numberofgppertri`` denotes the number of Gauss points in each + subtriangle of a cut element (default 12) and ``debugvtk`` controls if + additional debug vtk files should be written (1 activates the option, + 0 is default). + +| The specification of an enrichment item may consist of several lines, + see e.g. the test *sm/xFemCrackValBranch.in*. First, the enrichment + item type is specified together with some optional parameters + according to +| ``EntType`` ``#(in)`` ``enrichmentfront #(in)`` ``propagationlaw #(in)`` + + where ``enrichmentfront`` specifies an + enrichment front (we may for example employ branch functions at a + crack tip and Heaviside enrichment along the rest of the crack, hence + the “front†of the enrichment is treated separately) and + ``propagationlaw`` specifies a rule for crack propagation (this + feature is still highly experimental though). Specification of an + ``enrichmentfront`` and a ``propagationlaw`` is optional. + +| The next line specifies the enrichment function to be used: +| ``EntType`` ``#(in)`` + +| This is followed by a line specifying the geometric description (e.g. + a polygon line or a circle) according to +| ``EntType`` ``#(in)`` ``extra attributes`` + where the number and type of extra + attributes to specify will vary depending on the geometry chosen, e.g. + center and radius for a circle or a number of points for a polygon + line. + +| If an enrichment front was specified previously, the type and + properties of the enrichment front are specified on the next line + according to +| ``EntType`` ``#(in)`` ``extra attributes`` + +| If a propagation law was specified previously, it’s type and + properties are also specified on a separate line according to +| ``EntType`` ``#(in)`` ``extra attributes`` + diff --git a/doc/oofemInput/examples.rst b/doc/oofemInput/examples.rst new file mode 100644 index 000000000..0c691460b --- /dev/null +++ b/doc/oofemInput/examples.rst @@ -0,0 +1,295 @@ +Examples +======== + +Beam structure +-------------- + +This example for a simple beam structure gives basic overview of the +input file (found under tests/sm/beam2d_1.in). Structure geometry and +its constitutive and geometrical properties are shown in Fig. +(ex01_). The linear static analysis is required, the influence +of shear is neglected. + +.. figure:: figs/ex01.pdf + :alt: Example 1 - beam2d_1.in + :name: ex01 + :width: 70.0% + + Example 1 - beam2d_1.in + +:: + + beam2d_1.out + Simple Beam Structure - linear analysis + #only momentum influence to the displacements is taken into account + #beamShearCoeff is artificially enlarged. + StaticStructural nsteps 3 nmodules 0 + domain 2dBeam + OutputManager tstep_all dofman_all element_all + ndofman 6 nelem 5 ncrosssect 1 nmat 1 nbc 6 nic 0 nltf 3 nset 7 + node 1 coords 3 0. 0. 0. + node 2 coords 3 2.4 0. 0. + node 3 coords 3 3.8 0. 0. + node 4 coords 3 5.8 0. 1.5 + node 5 coords 3 7.8 0. 3.0 + node 6 coords 3 2.4 0. 3.0 + Beam2d 1 nodes 2 1 2 + Beam2d 2 nodes 2 2 3 DofsToCondense 1 6 + Beam2d 3 nodes 2 3 4 DofsToCondense 1 3 + Beam2d 4 nodes 2 4 5 + Beam2d 5 nodes 2 6 2 DofsToCondense 1 6 + SimpleCS 1 area 1.e8 Iy 0.0039366 beamShearCoeff 1.e18 thick 0.54 material 1 set 1 + IsoLE 1 d 1. E 30.e6 n 0.2 tAlpha 1.2e-5 + BoundaryCondition 1 loadTimeFunction 1 dofs 1 3 values 1 0.0 set 4 + BoundaryCondition 2 loadTimeFunction 1 dofs 1 5 values 1 0.0 set 5 + BoundaryCondition 3 loadTimeFunction 2 dofs 3 1 3 5 values 3 0.0 0.0 -0.006e-3 set 6 + ConstantEdgeLoad 4 loadTimeFunction 1 Components 3 0.0 10.0 0.0 loadType 3 set 3 + NodalLoad 5 loadTimeFunction 1 dofs 3 1 3 5 Components 3 -18.0 24.0 0.0 set 2 + StructTemperatureLoad 6 loadTimeFunction 3 Components 2 30.0 -20.0 set 7 + PeakFunction 1 t 1.0 f(t) 1. + PeakFunction 2 t 2.0 f(t) 1. + PeakFunction 3 t 3.0 f(t) 1. + Set 1 elementranges {(1 5)} + Set 2 nodes 1 4 + Set 3 elementedges 2 1 1 + Set 4 nodes 2 1 5 + Set 5 nodes 1 3 + Set 6 nodes 1 6 + Set 7 elements 2 1 2 + +Plane stress example +-------------------- + +.. figure:: figs/ex02.pdf + :alt: Example 2 + :name: ex02 + :width: 70.0% + + Example 2 + + +:: + + patch100.out + Patch test of PlaneStress2d elements -> pure compression + LinearStatic nsteps 1 + domain 2dPlaneStress + OutputManager tstep_all dofman_all element_all + ndofman 8 nelem 5 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 3 + node 1 coords 3 0.0 0.0 0.0 + node 2 coords 3 0.0 4.0 0.0 + node 3 coords 3 2.0 2.0 0.0 + node 4 coords 3 3.0 1.0 0.0 + node 5 coords 3 8.0 0.8 0.0 + node 6 coords 3 7.0 3.0 0.0 + node 7 coords 3 9.0 0.0 0.0 + node 8 coords 3 9.0 4.0 0.0 + PlaneStress2d 1 nodes 4 1 4 3 2 NIP 1 + PlaneStress2d 2 nodes 4 1 7 5 4 NIP 1 + PlaneStress2d 3 nodes 4 4 5 6 3 NIP 1 + PlaneStress2d 4 nodes 4 3 6 8 2 NIP 1 + PlaneStress2d 5 nodes 4 5 7 8 6 NIP 1 + Set 1 elementranges {(1 5)} + Set 2 nodes 2 1 2 + Set 3 nodes 2 7 8 + SimpleCS 1 thick 1.0 width 1.0 material 1 set 1 + IsoLE 1 d 0. E 15.0 n 0.25 talpha 1.0 + BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 1 0.0 set 2 + BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0.0 set 3 + NodalLoad 3 loadTimeFunction 1 dofs 2 1 2 components 2 2.5 0.0 set 3 + ConstantFunction 1 f(t) 1.0 + +Examples - parallel mode +------------------------ + +Node-cut example +~~~~~~~~~~~~~~~~ + +The example shows explicit direct integration analysis of simple +structure with two DOFs. The geometry and partitioning is sketched in +fig.(nodecut-ex01_). + +.. figure:: figs/poofem_ex01.pdf + :alt: Node-cut partitioning example: (a) whole geometry, (b) partition 0, (c) partition 1. + :name: nodecut-ex01 + :width: 70.0% + + Node-cut partitioning example: (a) whole geometry, (b) partition 0, + (c) partition 1. + +:: + + # + # partition 0 + # + partest.out.0 + Parallel test of explicit oofem computation + # + NlDEIDynamic nsteps 3 dumpcoef 0.0 deltaT 1.0 + domain 2dTruss + # + OutputManager tstep_all dofman_all element_all + ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 4 + # + Node 1 coords 3 0. 0. 0. + Node 2 coords 3 0. 0. 2. Shared partitions 1 1 + Truss2d 1 nodes 2 1 2 + Set 1 elements 1 1 + Set 2 nodes 2 1 2 + Set 3 nodes 1 1 + Set 4 nodes 0 + SimpleCS 1 thick 0.1 width 10.0 material 1 set 1 + IsoLE 1 tAlpha 0.000012 d 10.0 E 1.0 n 0.2 + BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 2 + BoundaryCondition 2 loadTimeFunction 1 dofs 1 3 values 1 0.0 set 3 + NodalLoad 3 loadTimeFunction 1 dofs 2 1 3 components 2 0. 1.0 set 4 + ConstantFunction 1 f(t) 1.0 + + # + # partition 1 + # + partest.out.1 + Parallel test of explicit oofem computation + # + NlDEIDynamic nsteps 3 dumpcoef 0.0 deltaT 1.0 + domain 2dTruss + # + OutputManager tstep_all dofman_all element_all + ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 4 + # + Node 2 coords 3 0. 0. 2. Shared partitions 1 0 + Node 3 coords 3 0. 0. 4. + Truss2d 2 nodes 2 2 3 + Set 1 elements 1 2 + Set 2 nodes 2 2 3 + Set 3 nodes 0 + Set 4 nodes 1 3 + SimpleCS 1 thick 0.1 width 10.0 material 1 set 1 + IsoLE 1 tAlpha 0.000012 d 10.0 E 1.0 n 0.2 + BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 2 + BoundaryCondition 2 loadTimeFunction 1 dofs 1 3 values 1 0.0 set 3 + NodalLoad 3 loadTimeFunction 1 dofs 2 1 3 components 2 0. 1.0 set 4 + ConstantFunction 1 f(t) 1.0 + +Element-cut example +~~~~~~~~~~~~~~~~~~~ + +The example shows explicit direct integration analysis of simple +structure with two DOFs. The geometry and partitioning is sketched in +fig. (nodecut-ex01_). + +.. figure:: figs/poofem_ex02.pdf + :alt: Element-cut partitioning example: (a) whole geometry, (b) partition 0, (c) partition 1. + :name: elmentcut-ex02 + :width: 70.0% + + Element-cut partitioning example: (a) whole geometry, (b) + partition 0, (c) partition 1. + + +:: + + # + # partition 0 + # + partest2.out.0 + Parallel test of explicit oofem computation + # + NlDEIDynamic nsteps 5 dumpcoef 0.0 deltaT 1.0 + domain 2dTruss + # + OutputManager tstep_all dofman_all element_all + ndofman 3 nelem 2 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 4 + # + Node 1 coords 3 0. 0. 0. + Node 2 coords 3 0. 0. 2. + Node 3 coords 3 0. 0. 4. Remote partitions 1 1 + Truss2d 1 nodes 2 1 2 + Truss2d 2 nodes 2 2 3 + Set 1 elements 2 1 2 + Set 2 nodes 3 1 2 3 + Set 3 nodes 1 1 + Set 4 nodes 1 3 + SimpleCS 1 thick 0.1 width 10.0 material 1 set 1 + IsoLE 1 tAlpha 0.000012 d 10.0 E 1.0 n 0.2 + BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 2 + BoundaryCondition 2 loadTimeFunction 1 dofs 1 3 values 1 0.0 set 3 + NodalLoad 3 loadTimeFunction 1 dofs 2 1 3 components 2 0. 1.0 set 4 + ConstantFunction 1 f(t) 1.0 + + + # + # partition 1 + # + partest2.out.1 + Parallel test of explicit oofem computation + # + NlDEIDynamic nsteps 5 dumpcoef 0.0 deltaT 1.0 + domain 2dTruss + # + OutputManager tstep_all dofman_all element_all + ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 4 + # + Node 2 coords 3 0. 0. 2 Remote partitions 1 0 + Node 3 coords 3 0. 0. 4 + Truss2d 2 nodes 2 2 3 + Set 1 elements 1 2 + Set 2 nodes 2 2 3 + Set 3 nodes 0 + Set 4 nodes 1 3 + SimpleCS 1 thick 0.1 width 10.0 material 1 set 1 + IsoLE 1 tAlpha 0.000012 d 10.0 E 1.0 n 0.2 + BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 2 + BoundaryCondition 2 loadTimeFunction 1 dofs 1 3 values 1 0.0 set 3 + NodalLoad 3 loadTimeFunction 1 dofs 2 1 3 components 2 0. 1.0 set 4 + ConstantFunction 1 f(t) 1.0 + +Figures +------- + +.. figure:: figs/nodecut0cb.pdf + :alt: Node-cut partitioning. + :name: nodecut + + + Node-cut partitioning. + + +.. figure:: figs/nodecut1cb.pdf + :alt: Node-cut partitioning - local constitutive mode. + :name: nodecut-lm + + + Node-cut partitioning - local constitutive mode. + + +.. figure:: figs/nodecutnonloc1.pdf + :alt: Node-cut partitioning - nonlocal constitutive mode. + :name: nodecut-nlm + + + Node-cut partitioning - nonlocal constitutive mode. + + +.. figure:: figs/elementcut0.pdf + :alt: Element-cut partitioning. + :name: elmentcut + + + Element-cut partitioning. + + +.. figure:: figs/elementcut1.pdf + :alt: Element-cut partitioning, local constitutive mode. + :name: elmentcut-lm + + + Element-cut partitioning, local constitutive mode. + + +.. [1] + Hovewer, the problem does not support the changes of static system. + But it is possible to apply direct displacement control without + requiring BC applied (see nrsolver documentation). Therefore it is + possible to combine direct displacement control with direct load + control or indirect control. diff --git a/doc/oofemInput/elementcut0.eps b/doc/oofemInput/figs/elementcut0.eps similarity index 100% rename from doc/oofemInput/elementcut0.eps rename to doc/oofemInput/figs/elementcut0.eps diff --git a/doc/oofemInput/elementcut0.pdf b/doc/oofemInput/figs/elementcut0.pdf similarity index 100% rename from doc/oofemInput/elementcut0.pdf rename to doc/oofemInput/figs/elementcut0.pdf diff --git a/doc/oofemInput/elementcut1.eps b/doc/oofemInput/figs/elementcut1.eps similarity index 100% rename from doc/oofemInput/elementcut1.eps rename to doc/oofemInput/figs/elementcut1.eps diff --git a/doc/oofemInput/elementcut1.pdf b/doc/oofemInput/figs/elementcut1.pdf similarity index 100% rename from doc/oofemInput/elementcut1.pdf rename to doc/oofemInput/figs/elementcut1.pdf diff --git a/doc/oofemInput/ex01.eps b/doc/oofemInput/figs/ex01.eps similarity index 100% rename from doc/oofemInput/ex01.eps rename to doc/oofemInput/figs/ex01.eps diff --git a/doc/oofemInput/ex01.pdf b/doc/oofemInput/figs/ex01.pdf similarity index 100% rename from doc/oofemInput/ex01.pdf rename to doc/oofemInput/figs/ex01.pdf diff --git a/doc/oofemInput/ex02.eps b/doc/oofemInput/figs/ex02.eps similarity index 100% rename from doc/oofemInput/ex02.eps rename to doc/oofemInput/figs/ex02.eps diff --git a/doc/oofemInput/ex02.pdf b/doc/oofemInput/figs/ex02.pdf similarity index 100% rename from doc/oofemInput/ex02.pdf rename to doc/oofemInput/figs/ex02.pdf diff --git a/doc/oofemInput/geo.eps b/doc/oofemInput/figs/geo.eps similarity index 100% rename from doc/oofemInput/geo.eps rename to doc/oofemInput/figs/geo.eps diff --git a/doc/oofemInput/geo.pdf b/doc/oofemInput/figs/geo.pdf similarity index 100% rename from doc/oofemInput/geo.pdf rename to doc/oofemInput/figs/geo.pdf diff --git a/doc/oofemInput/nodecut0cb.eps b/doc/oofemInput/figs/nodecut0cb.eps similarity index 100% rename from doc/oofemInput/nodecut0cb.eps rename to doc/oofemInput/figs/nodecut0cb.eps diff --git a/doc/oofemInput/nodecut0cb.pdf b/doc/oofemInput/figs/nodecut0cb.pdf similarity index 100% rename from doc/oofemInput/nodecut0cb.pdf rename to doc/oofemInput/figs/nodecut0cb.pdf diff --git a/doc/oofemInput/nodecut1cb.eps b/doc/oofemInput/figs/nodecut1cb.eps similarity index 100% rename from doc/oofemInput/nodecut1cb.eps rename to doc/oofemInput/figs/nodecut1cb.eps diff --git a/doc/oofemInput/nodecut1cb.pdf b/doc/oofemInput/figs/nodecut1cb.pdf similarity index 100% rename from doc/oofemInput/nodecut1cb.pdf rename to doc/oofemInput/figs/nodecut1cb.pdf diff --git a/doc/oofemInput/nodecutnonloc1.eps b/doc/oofemInput/figs/nodecutnonloc1.eps similarity index 100% rename from doc/oofemInput/nodecutnonloc1.eps rename to doc/oofemInput/figs/nodecutnonloc1.eps diff --git a/doc/oofemInput/nodecutnonloc1.pdf b/doc/oofemInput/figs/nodecutnonloc1.pdf similarity index 100% rename from doc/oofemInput/nodecutnonloc1.pdf rename to doc/oofemInput/figs/nodecutnonloc1.pdf diff --git a/doc/oofemInput/oofem-logo-contour.eps b/doc/oofemInput/figs/oofem-logo-contour.eps similarity index 100% rename from doc/oofemInput/oofem-logo-contour.eps rename to doc/oofemInput/figs/oofem-logo-contour.eps diff --git a/doc/oofemInput/oofem-logo-contour.pdf b/doc/oofemInput/figs/oofem-logo-contour.pdf similarity index 100% rename from doc/oofemInput/oofem-logo-contour.pdf rename to doc/oofemInput/figs/oofem-logo-contour.pdf diff --git a/doc/oofemInput/poofem_ex01.eps b/doc/oofemInput/figs/poofem_ex01.eps similarity index 100% rename from doc/oofemInput/poofem_ex01.eps rename to doc/oofemInput/figs/poofem_ex01.eps diff --git a/doc/oofemInput/poofem_ex01.pdf b/doc/oofemInput/figs/poofem_ex01.pdf similarity index 100% rename from doc/oofemInput/poofem_ex01.pdf rename to doc/oofemInput/figs/poofem_ex01.pdf diff --git a/doc/oofemInput/poofem_ex02.eps b/doc/oofemInput/figs/poofem_ex02.eps similarity index 100% rename from doc/oofemInput/poofem_ex02.eps rename to doc/oofemInput/figs/poofem_ex02.eps diff --git a/doc/oofemInput/poofem_ex02.pdf b/doc/oofemInput/figs/poofem_ex02.pdf similarity index 100% rename from doc/oofemInput/poofem_ex02.pdf rename to doc/oofemInput/figs/poofem_ex02.pdf diff --git a/doc/oofemInput/index.rst b/doc/oofemInput/index.rst new file mode 100644 index 000000000..a81f076b4 --- /dev/null +++ b/doc/oofemInput/index.rst @@ -0,0 +1,13 @@ + +OOFEM Input Manual +================== +.. toctree:: + :caption: Content + :maxdepth: 2 + + introduction + analysisrecords + domainrecords + apendices + examples + about \ No newline at end of file diff --git a/doc/oofemInput/introduction.rst b/doc/oofemInput/introduction.rst new file mode 100644 index 000000000..01454fb75 --- /dev/null +++ b/doc/oofemInput/introduction.rst @@ -0,0 +1,257 @@ + +Introduction +============ + +This manual describes in details the format and structure of OOFEM text +input file. Input file can be prepared in any text editor or can be +generated by a conversion program or FEM pre-processor. + +.. _running-the-code: + +Running the code +---------------- + +| The program can be executed by typing +| ``oofem [option [parameter]] ...`` +| on the command line prompt with the following command line options: + +=========== ================================================================================================================================================================================================================================================================================================================================================ +-v Prints oofem version. +-f path Path to oofem input file name, if not present, program interactively reads this parameter. +-r int Restarts the analysis from given solution step. The corresponding context file (\*.osf) must exist. +-rn Turns on the equation renumbering. Default is off. +-ar int Restarts the adaptive computation from given solution step. Requires the corresponding context file (\*.osf) and domain input file (\*.din) to exists. The domain input file describes the new mesh, its syntax is identical to syntax of input file, but it does not contains the output file record, job description record and analysis record. +-l int Sets treshold for log messages (Errors=0, Warnings=1, Relevant=2, Info=3, Debug=4). +-qo path Redirect the standard output stream (stdout) to given file. +-qe path Redirect standard error stream (stderr) to given file. +-c Forces the creation of context file for each solution step. +-t int Determines the number of threads to use (requires OpenMP support compiled) +-p Runs in parallel mode using MPI (requires MPI support compiled) +=========== ================================================================================================================================================================================================================================================================================================================================================ + +| To execute OOFEM program in parallel MPI mode (indicated by the -p flag), users must know the procedure for executing/scheduling MPI jobs on the particular system(s). For instance, when using the MPICH implementation of MPI and many others, the following command initiates a program that uses eight processors: +| ``mpirun -np 8 oofem -p program_options`` + + + +Syntax and general rules +------------------------ + +Input file is composed of records. In the current implementation, each +record is represented by one line in input file. The order of records in +file is compulsory, and it has following structure: + +#. output file record, see section :ref:`OutputFileRecord`, + +#. job description record, see section :ref:`JobDescriptionRecord`, + +#. analysis record, see section :ref:`AnalysisRecord`, + +#. domain record, see section :ref:`DomainRecord`, + +#. output manager record, see section :ref:`OutputManagerRecord`, + +#. components size record, see section :ref:`ComponentsSizeRecord`, + +#. node record(s), see section :ref:`NodeElementSideRecords`, + +#. element record(s), see section :ref:`ElementsRecords`, + +#. set record(s), see section :ref:`SetRecords`, + +#. cross section record(s), see section :ref:`CrossSectionRecords`, + +#. material type record(s), see section :ref:`MaterialTypeRecords`, + +#. nonlocal barriers record(s), see section + :ref:`NonlocalBarrierRecords`, + +#. load, boundary conditions record(s), see section + :ref:`LoadBoundaryInitialConditions`, + +#. initial conditions record(s), see section + :ref:`InitialConditions`, + +#. time functions record(s), see section + :ref:`TimeFunctionsRecords`. + +#. optional xfem manager and associated record(s), see section + :ref:`XFEMManagerRecords` + +When input line begins with ’#’ character, then it is ignored by the +parser and can serve as a comment inside input file. + +The individual records consist of record keyword followed by one or more +attributes. Each attribute is identified by its keyword, which can be +followed by attribute value(s). Some attributes have no values. The +order of attributes in the record is optional. + +Sometimes, the record keyword itself can be variable, taking on a +restricted range of possible values. As an example, OOFEM has element +record, desribing particulat element, and record keyword determines the +particular element type. In this case, the record keyword is preceded by +star. We call such record keyword as entity keyword. The possible +substitutions for entity keyword are typed using ``Typewriter`` font +family. Often, some attributes are specific to particular entity +keyword. Then the general format of record is described and entity +specific attributes are described separately. The possible attributes +are then union of general and entity specific attributes. + +:: + + # nodal records + Node 1 coords 3 0. 0. 0. + Node 2 coords 3 0. 0. 2. dofidmask 3 1 2 3 + # element record + Truss2d 1 nodes 2 1 2 crossSect 1 + +Each attribute value has a specific type, which describe its size and +layout. To describe the type of an attribute, the following notation is +used: ``Keyword #(type)``, where type determines the attribute type and +# is the placeholder for the attribute value. The possible types of +attribute values are following: + +- **in** - integer number. + + :: + + val1 25 + +- **rn** - real number. + + :: + + val2 -0.234e-3 + +- **ch** - character (usually for description of unknown type (’d’ for + displacement, ’t’ for temperature, etc.). + + :: + + val3 t + +- **ia** - integer array. The format of integer array is + ``size val(1) ... val(size)``, where size, val(1),...,val(size) are + integer numbers. Values are separated by one or more spaces. As an + example, consider the integer array attribute called + ``nodes``\ :math:`=\{1,4,23\}`: + + :: + + nodes 3 1 4 23 + +- **ra** - real array. The format of real array is + ``size val(1) ... val(size)``, where size is integer number and val(1), + ..., val(size) are real numbers. Values are separated by one or more + spaces. As an example, consider the real array attribute called + ``coords``\ :math:`=\{1.0,2.0,3.0\}`: + + :: + + coords 3 1.0 2.0 3.0 + +- | **rm** - real matrix, format of real matrix is + | ``rows columns {val(1,1) val(1,2) ...; val(2,1) ...}``, where “rows†+ and “columns†are integer numbers and val(1,1), ..., are real + numbers. Columns are seperated by space or comma and lines by + semicolon. As an example, consider the real matrix attribute called + :math:`\texttt{mat1}=\left[\begin{array}{ccc}1.0&-1.0&0.0\\2.0&2.5&5.0\end{array}\right]`: + + :: + + mat1 2 3 \{1.0 -1.0; 0.0 2.0; 2.5 5.0\} + +- **dc** - dictionary. Dictionary consist of pairs, each pair has key + (character type) and its associated value (integer type). Format of + dictionary is ``size key(1) val(1) ... key(size) val(size)``, where + size is integer number, key(1),...,key(size) are single character + values, and val(1), ..., val(size) are real numbers. Values are + separated by one or more spaces; + + :: + + dict1 2 a 1.0 v 0.0 + +- **rl** - range list. Range list syntax is { number1 .. numberN + (start1 end1) (start2 end2)}. The enclosing brackets are compulsory. + The range list represent list of integer values. Single values can be + specified using single values (number1, .., NumberN). The range of + values (all numbers from startI to endI including startI and endI can + be specified using range value in the form (startI endI). The range + is described using its start and end values enclosed in parenthesis. + Any number of ranges and single values can be used to specify range + list. + + :: + + range1 { 1 7 8 (10 20) (25 30) } + +- **et** - entity type. For example, it describes the finite element + type. Possible type values are mentioned in specific sections. + +- **s** - character string. The string have to be enclosed in quotes + ("") following after corresponding keyword. + + :: + + string1 ``string example'' + +- **expr** - function expression. The expression have to be enclosed in + quotes (""). The expression is evaluated by internal parser and + represent mathematical expressions as a function of certain + variables. The variable names and meaning are described in specific + sections. The usual arithmetic operators like -,+,*,/ are supported + and their evaluation order is taken into account. The evaluation + order can be changed using parenthesis. Several built-in functions + are supported (sqrt, sin, cos, tan, atan, asin and acos) - these must + be typed using lowercase letters and their arguments must be enclosed + in parenthesis. + + :: + + expr1 ``2.0*sin(t)/3.0'' + +| The general format of record is +| [``attribute1_keyword #(type)``] ``...`` + [``attributeXX_keyword #(type)``] + +The keywords and their values are separated by one or more spaces. +Please note, that a single record cooresponds to one input line in input +file. + +When some attribute is enclosed in brackets [ ], then it’s use is +optional and often overwrites the default behavior or adds additional +(but optional) information or property (for example adds a loading to +node). + +| Example of input record. +| As an example, consider the following record description: +| ``Particle`` ``color #(in)`` ``mass #(rn)`` ``coords #(ra)`` + ``name #(s)`` + The following listing shows the corresponding, + properly formatted, input record: + +:: + + Particle 2 color 5 mass 0.18 coords 3 0.0 1.0 2.0 name "P1_36" + +Output and Job description Records +================================== + +.. _OutputFileRecord: + +Output file record +------------------ + +This record has no keywords and contains a character string, which +describes the path to output file. If the file with the same name +exists, it will be overwritten. + +.. _JobDescriptionRecord: + +Job description record +---------------------- + +This record has no keywords and contains a character string, which +describes the job. This description will appear in the output file. + diff --git a/doc/oofemInput/latex2html-init b/doc/oofemInput/old/latex2html-init similarity index 100% rename from doc/oofemInput/latex2html-init rename to doc/oofemInput/old/latex2html-init diff --git a/doc/oofemInput/latex2html-init.shtml b/doc/oofemInput/old/latex2html-init.shtml similarity index 100% rename from doc/oofemInput/latex2html-init.shtml rename to doc/oofemInput/old/latex2html-init.shtml diff --git a/doc/oofemInput/makefile b/doc/oofemInput/old/makefile similarity index 100% rename from doc/oofemInput/makefile rename to doc/oofemInput/old/makefile diff --git a/doc/oofemInput/oofemInput.tex b/doc/oofemInput/old/oofemInput.tex similarity index 92% rename from doc/oofemInput/oofemInput.tex rename to doc/oofemInput/old/oofemInput.tex index 0fc366295..8102ada84 100644 --- a/doc/oofemInput/oofemInput.tex +++ b/doc/oofemInput/old/oofemInput.tex @@ -1,4 +1,4 @@ -\documentclass[a4paper]{article} +\documentclass[a4paper]{report} \usepackage{amsmath} \usepackage{ifluatex} \ifluatex @@ -56,10 +56,23 @@ \newcommand{\entKeywordWithVal}[2]{*\textbf{#1}~\#{\tiny(#2)}} % For general keywords, e.g. ``engnmodel'' \newcommand{\entKeywordInstWithVal}[2]{\textbf{#1}~\#{\tiny(#2)}} % For specific keywords, e.g. ``nlinearstatic'' +%editing macros +\newcommand{\missing}[1]{} +\definecolor{gray}{rgb}{0.5, 0.5, 0.5} +\definecolor{Navy}{rgb}{0.0, 0.0, 0.5} % macros for items related to parallel -\newcommand{\Pmode}[1]{{\sffamily #1}} -\newcommand{\Pparam}[1]{\param{#1}} -\newcommand{\oofemParallel}[1]{$\langle${#1}$\rangle$} +\begin{htmlonly} + % no xcolor support in latex2html + \newcommand{\Pmode}[1]{\sffamily {#1}} + \newcommand{\Pparam}[1]{\param{#1}} + \newcommand{\oofemParallel}[1]{{$\langle${#1}$\rangle$}} +\end{htmlonly} +%begin{latexonly} + \newcommand{\Pmode}[1]{\sffamily \color{Navy} {#1}} + \newcommand{\Pparam}[1]{\param{#1}} + \newcommand{\oofemParallel}[1]{{$\langle${#1}$\rangle$}} +%end{latexonly} + \newcommand{\PentKeyword}[1]{\oofemParallel{\entKeyword{#1}}} \newcommand{\PentKeywordInst}[1]{\oofemParallel{\entKeywordInst{#1}}} \newcommand{\Pfield}[2]{\oofemParallel{\field{#1}{#2}}} @@ -69,6 +82,7 @@ \definecolor{lightgray}{gray}{0.9} \newcolumntype{R}{>{\raggedleft\arraybackslash}X}% + \begin{htmlonly} %\newenvironment{record}[1][]{\rowcolors{1}{lightgray}{lightgray}\begin{tabular}{|ll}}{\end{tabular}\\} \newenvironment{record}[1][]{\begin{tabular}{|ll}}{\end{tabular}\\} @@ -138,7 +152,7 @@ \newpage \tableofcontents \newpage -\section{Introduction} +\chapter{Introduction} This manual describes in details the format and structure of OOFEM text input file. Input file can be prepared in any text editor or can be generated by a conversion program or FEM pre-processor. @@ -361,7 +375,7 @@ \section{Syntax and general rules} \end{lstlisting} - +\chapter{Output and Job description Records} \section{Output file record} \label{_OutputFileRecord} This record has no keywords and contains a character string, which @@ -374,7 +388,7 @@ \section{Job description record} describes the job. This description will appear in the output file. -\section{Analysis record} +\chapter{Analysis record} \label{_AnalysisRecord} This record describes the type of analysis, which should be performed. The analysis record can be splitted into optional meta-step input records (see below). @@ -399,11 +413,12 @@ \section{Analysis record} \recentry{}{\optField{ninitmodules}{in}} \recentry{}{\optField{nmodules}{in}} \recentry{}{\optField{nxfemman}{in}} - \end{record} + \end{record}\\ immediately followed by \param{nmsteps} meta step records with the following syntax:\\ \begin{record}[0.9\textwidth] \recentry{}{\field{nsteps}{in} \field{attributes}{string}} - \end{record} + \end{record}\\ + The \param{nmsteps} parameter determines the number of ``metasteps''. The meta step represent sequence of solution steps with common attributes. There is expected to be \param{nmsteps} subsequent metastep records. @@ -458,6 +473,38 @@ \section{Analysis record} \item Non-linear static analysis, see section \ref{NonLinearStatic}. \end{itemize} +\section{Structural Problems} +\subsection{StaticStructural} +\label{StaticStructural} +\begin{record} + \recentry{\entKeywordInst{StaticStructural}}{\field{nsteps}{in}} + \recentry{}{\optField{deltat}{...}} + \recentry{}{\optField{prescribedtimes}{...}} + \recentry{}{\optField{stiffmode}{...}} + \recentry{}{\optField{nonlocalext}{...}} + \recentry{}{\optField{sparselinsolverparams}{...}} +\end{record} + +Static structural analysis. Can be used to solve linear and nonlinear static structural problems, supporting changes in boundary conditions (applied load and supports). +The problem can be solved under direct load or displacement control, indirect control, or by +their arbitrary combination. +Note, that the individual solution steps are used to describe the history of applied incremental loading. The load cases are not supported, for each load case the new analysis has to be performed. To analyze linear static problem with multiple load combinations, please use LinearStatic solver. + +By default all material nonlinearities will be taken into account, geometrical not. +To include geometrically nonlinear effect one must specify level of non-linearity in element records. + +The \param{sparselinsolverparams} parameter describes the sparse +linear solver attributes and is explained in section \ref{sparselinsolver}. +\Pmode{Can be used in parallel mode. The input record must be the same + for all processors. At present, parallel version requires PETSc module.} +The optional parameter \param{deltat} defines the length of time step (equal to 1.0 by default). The times corresponding to individual solution times can be specified using optional parameter \param{prescribedtimes}, allowing to input array of discrete solution times, the number of solution steps is then equal to the size of this array. +\Pmode{The \param{nonlocalext} turns on the nonlocal constitutive +extension. The extension considers a band of remote elements involved +in computation of nonlocal variables (see fig. \ref{nodecut-nlm} illustrating +this approach for node-cut partitioning)}. + +\missing{Metasteps support} + \subsection{Linear static analysis} \label{LinearStatic} \begin{record} @@ -468,11 +515,8 @@ \subsection{Linear static analysis} Linear static analysis. Parameter \param{nsteps} indicates the number of loading cases. -Series of loading cases is maintained as sequence of time-steps. -For each load case an auxiliary time-step is generated with time -equal to load case number. -Load vectors for each load case are formed as load vectors at -this auxiliary time. +Problem supports multiple load cases, where number of load cases correspods to number of solution steps, individual load vectors are formed in individual time-steps. +However, the static system is assumed to be the same for all load cases. For each load case an auxiliary time-step is generated with time equal to load case number. The \param{sparselinsolverparams} parameter describes the sparse linear solver attributes and is explained in section \ref{sparselinsolver}. @@ -527,10 +571,11 @@ \subsection{NlDEIDynamic} The central difference method with diagonal mass matrix is used, damping matrix is assumed to be proportional to mass matrix, $\mbf{C} = \mathrm{dumpcoef} * \mbf{M}$, where -$\mbf{M}$ is diagonal mass matrix. \param{deltaT} is time step length used for -integration, which may be reduced by program in order to satisfy -solution stability conditions. Parameter \param{nsteps} specifies -how many time steps will be analyzed. +$\mbf{M}$ is diagonal mass matrix. +Parameter \param{nsteps} specifies how many time steps will be analyzed. +\param{deltaT} is time step length used for integration, which may be reduced by program in order to satisfy solution stability conditions. +Parameter \param{reduct} is a scaling factor (smaller than 1), which is multiplied with the determined step length adjusted by the program. +If \param{deltaT} is reduced internally, then \param{nsteps} is adjusted so that the total analysis time remains the same. The parallel version has the following additional syntax:\\ \\ \begin{record} @@ -896,6 +941,12 @@ \subsubsection{Standard syntax} \end{record} The meaning of parameters is the same as for extended syntax. +Parameter \param{lstype} allows to select the solver for the linear system of +equations. Parameter \param{smtype} allows to select the sparse matrix storage +scheme. The scheme should be compatible with the solver type. See section +\ref{sparselinsolver} for further details. + + % \subsection{Adaptive linear static} \label{AdaptiveLinearStatic} @@ -1000,7 +1051,10 @@ \subsection{Free warping analysis} Load vectors for each load case are formed as load vectors at this auxiliary time. +\missing{QClinearStatic} + +\section{Transport Problems} \subsection{Stationary transport problem} \label{StationaryTransport} @@ -1031,7 +1085,45 @@ \subsection{Stationary transport problem} Then the subsequent analyses can get access to exported fields and take them into account, if they support such feature. -\subsection{Transient transport problem - linear case} +\subsection{Transient transport problem} +\label{TransientTransport} + +\begin{record} + \recentry{\entKeywordInst{TransientTransport}}{\field{nsteps}{in}} + \recentry{}{\field{deltaT}{rn} $|$ \field{dTfunction}{in} $|$ {\field{prescribedtimes}{ra}}} + \recentry{}{\field{alpha}{rn}} + \recentry{}{\optField{initT}{rn}} + \recentry{}{\optFieldnotype{lumped}} + \recentry{}{\optFieldnotype{keeptangent}} + \recentry{}{\optField{exportfields}{ia}} +\end{record} + +\textbf{Nonlinear} implicit +integration scheme for transient transport problems. The generalized +midpoint rule (sometimes called $\alpha$-method) is used for time discretization, with alpha parameter, +which has limits $0\le\alpha\le1$. For $\alpha=0$ explicit Euler +forward method is obtained, for $\alpha=0.5$ implicit trapezoidal rule +is recovered, which is unconditionally stable, second-order accurate +in $\Delta t$, and $\alpha=1.0$ yields implicit Euler backward method, +which is unconditionally stable, and first-order accurate +in $\Delta t$. \param{deltaT} is time step length used for +integration, \param{nsteps} parameter specifies +number of time steps to be solved. It is possible to define \param{dTfunction} +with a number referring to corresponding time function, see section~\ref{_TimeFunctionsRecords}. +Variable time step is advantageous when calculating large time intervals. + +The \param{initT} sets the initial time for integration, 0. by default. +If \param{lumped} is set, then the stabilization of numerical +algorithm using lumped capacity matrix will be used, reducing the +initial oscillations. +See section \ref{StationaryTransport} for an explanation on +\param{exportfields}. + +This transport problem supports sets and changes in number of equations. It is possible to impose/remove Dirichlet boundary conditions during solution. + + + +\subsection{Transient transport problem - linear case - obsolete} \label{LinearTransientTransport} \begin{record} @@ -1076,7 +1168,10 @@ \subsection{Transient transport problem - linear case} can be used only when this module is included in your oofem configuration. -\subsection{Transient transport problem - nonlinear case} + + + +\subsection{Transient transport problem - nonlinear case - obsolete} \label{TransientTransport} \begin{record} @@ -1125,6 +1220,7 @@ \subsection{Transient transport problem - nonlinear case} can be used only when this module is included in your oofem configuration. +\section{Fluid Dynamic Problems} \subsection{Transient incompressible flow - CBS Algorithm} \label{cbsIncomp} \begin{record} @@ -1157,9 +1253,9 @@ \subsection{Transient incompressible flow - CBS Algorithm} \param{uscale}, and \param{dscale} representing typical length, velocity, and density scales. -Parameter \param{lstype} allows to select solver for linear system of -equations. Parameter \param{smtype} allows to select sparse matrix storage -scheme. The scheme should be compatible with solver type. See section +Parameter \param{lstype} allows to select the solver for the linear system of +equations. Parameter \param{smtype} allows to select the sparse matrix storage +scheme. The scheme should be compatible with the solver type. See section \ref{sparselinsolver} for further details. \subsection{Transient incompressible flow\\SUPG/PSPG Algorithm} @@ -1227,11 +1323,10 @@ \subsection{Transient incompressible flow\\SUPG/PSPG Algorithm} \param{uscale}, and \param{dscale} representing typical length, velocity, and density scales. -Parameter \param{lstype} allows to select solver for linear system of -equations. Parameter \param{smtype} allows to select sparse matrix storage -scheme. Please note, that the present algorithm leads to a -non-symmetrical system -matrix. The scheme should be compatible with solver type. See section +Parameter \param{lstype} allows to select the solver for the linear system of +equations. Parameter \param{smtype} allows to select the sparse matrix storage +scheme. Please note that the present algorithm leads to a +non-symmetric matrix. The scheme should be compatible with the solver type. See section \ref{sparselinsolver} for further details. \subsection{Transient incompressible flow\\PFEM Algorithm} @@ -1289,116 +1384,14 @@ \subsection{Transient incompressible flow\\PFEM Algorithm} step. Default values are 1.e-8. By default maximal 50 iterations are performed, if not specified by \param{maxiter}. -Parameter \param{lstype} allows to select solver for linear system of -equations. Parameter \param{smtype} allows to select sparse matrix storage -scheme. Please note, that the present algorithm leads to a -non-symmetrical system -matrix. The scheme should be compatible with solver type. See section +Parameter \param{lstype} allows to select the solver for the linear system of +equations. Parameter \param{smtype} allows to select the sparse matrix storage +scheme. Please note that the present algorithm leads to a +non-symmetric matrix. The scheme should be compatible with the solver type. See section \ref{sparselinsolver} for further details. -\subsubsection{Lagrangian governing equations of incompressible fluid} -The Particle finite element method (PFEM) is based on the Lagrangian form of the Navier-Stokes equation for incompressible Newtonian fluids. Assuming the density does not change in time for an incompressible fluid, the continuity equation reduces to zero requirements for the divergence of the velocity. The Navier-Stokes equations take the form -\begin{eqnarray} -\rho\pard{\mbf{u}}{t} &=& \rho\mbf{b} + \nabla\cdot\mbf{\sigma} \label{eq:navier-stokes2}\;,\\ -\nabla\cdot\mbf{u} &=& 0\;. \label{eq:navier-stokes2b} -\end{eqnarray} -For the deviatoric stress in Newtonian fluids a linear dependency of stress tensor and strain rate tensor is adopted and for the Newtonian fluids. Considering the incompressibility of the fluid, the Cauchy stress reads -\begin{equation}\label{eq:stokes} -\mbf{\sigma}=-p\mbf{I} + 2\mu \nabla^s\mbf{u}\;. -\end{equation} -This equation is known as \emph{Stokes' law} and its Cartesian form writes -\begin{equation} -\sigma_{ij}=-p\delta_{ij}+\mu\left(\pard{u_i}{x_j}+\pard{u_j}{x_i}\right)\;. -\end{equation} -\par -Substituting the expression of Cauchy stress from Stokes' law~(\ref{eq:stokes}) into the momentum equation~(\ref{eq:navier-stokes2}) and rewriting gives -\begin{equation} -\rho\pard{\mbf{u}}{t} = \rho\mbf{b} + \mu\nabla^2\mbf{u} - \nabla p\;.\label{eq:momentum} -\end{equation} -\par -The governing equations of the mass~(\ref{eq:navier-stokes2b}) and momentum conservation~(\ref{eq:momentum}) form can be written in the Cartesian form for the individual component $i$ using Einstein summation convention -\begin{eqnarray} -\rho \pard{u_i}{t} &=& - \frac{\partial}{\partial x_i}p+\mu\frac{\partial}{\partial x_j}\left(\frac{\partial u_i}{\partial x_j}\right)+\rho b_i \;, \label{eq:mb}\\ -\pard{u_i}{x_i} &=& 0\;. -\end{eqnarray} -The equations are accompanied by a set of standard boundary conditions imposed on the complementary parts of the domain boundary -\begin{eqnarray} - \tau_{ij}\nu_j - p\nu_i &=& \bar \sigma_{ni} \qquad \mbox{on } \Gamma_{\sigma}\;, \\ - u_i\nu_i &=& \bar u_n \qquad\; \mbox{on } \Gamma_n\;, \\ - u_i\zeta_i &=& \bar u_t \qquad\;\, \mbox{on } \Gamma_t\;, -\end{eqnarray} -where $\nu$ or $n$ denotes the normal direction to the boundary and $\zeta$ or $t$ the tangential one. The bar sign over a quantity $\bar x$ stands for its prescribed value. - -\subsubsection{Time discretization} -For the time discretization of the momentum equation, a general trapezoid rule can be adopted. Using this rule, the time derivative of a generic function $\phi$ can be approximated by following equation -\begin{equation} -[\phi(x,t)]^{n+\theta} = \theta\phi(x,t^{n+1})+(1-\theta)\phi(x,t^n)=\theta\phi^{n+1}+(1-\theta)\phi^n\;. -\end{equation} -Rewriting the time derivative on the left hand side of the momentum balance~(\ref{eq:mb}) as a finite difference in time and applying the trapezoidal rule on the right hand side, we obtain -\begin{equation}\label{eq:momentum-general} - \rho\pard{u_i}{t} \approx \rho\frac{u^{n+1}_i-u^n_i}{\Delta t}= \left[ - \frac{\partial}{\partial x_i}p+\mu\frac{\partial}{\partial x_j}\left(\frac{\partial u_i}{\partial x_j}\right)+\rho b_i\right]^{n+\theta}\;. -\end{equation} -The parameter $\theta$ can take values from the interval $[0,1]$. The approximation is considered as a weighted average of the derivative values in the time step $n$ and $n+1$. Using a specific value of the $\theta$ parameter, well-known methods can be recovered: The explicit Euler method $\theta=0$, the backward Euler for $\theta=1$ or the Crank-Nicolson method $\theta=1/2$. The current implemantation of PFEM allows the use of explicit and backward (implicit) method. - -\subsubsection{Fractional step scheme} -Beside the three velocity components, the discretized momentum balance equations~(\ref{eq:momentum-general}) for a three dimensional case includes pressure as a coupling variable. A possible approach to decouple them is the application of so-called \emph{fractional step method}. The main idea of this method consists in introducing an intermediate velocity as supplementary variable and splitting the momentum equation. The modification introduced by R.Codina~\cite{Codina01} splits the the discretized time step is split into two sub-steps. The implicit part of the pressure is avoided and assigned to the second step. -\begin{equation} - \pard{u_i}{t} \approx \frac{u^{n+1}_i-u^n_i}{\Delta t}=\frac{u^{n+1}_i-u^*_i+u^*_i-u^n_i}{\Delta t}= \left[ - \frac{1}{\rho}\frac{\partial}{\partial x_i}p+\frac{\mu}{\rho}\frac{\partial}{\partial x_j}\left(\frac{\partial u_i}{\partial x_j}\right)+b_i\right]^{n+\theta}\;. -\end{equation} -where the intermediate velocity $u^*_i$ is introduced. Splitting the equation in the following manner gives the expression for the unknown velocities -\begin{eqnarray}\label{rce:uistar} - u^*_i &=& u^n_i+b_i\Delta t - \frac{\Delta t}{\rho}\pard{}{x_i}\gamma p^n+\frac{\Delta t\mu}{\rho}\pard{}{x_j}\left(\pard{u^{n+\theta}_i}{x_j}\right)\;,\\ - u^{n+1}_i &=& u^*_i- \frac{\Delta t}{\rho}\pard{}{x_i}(p^{n+1}-\gamma p^n)\;. \label{eq:uin1} -\end{eqnarray} - -The pressure split is here introduced by the new parameter $\gamma$ defining the amount of splitting and can take values from 0 to 1. The body loads are considered to be constant over time step. -\par -In a similar way, the fractional step method is applied on the mass conservation equation. Here, the time derivative of density would be approximated. As we examine an incompressible flow, whose density does not change in time, merely the intermediate velocity term is incorporated in the divergence of the velocity. -\begin{equation} - \pard{(u^{n+1}_i-u^*_i+u^*_i)}{x_i} = 0 \;, -\end{equation} -which can be decomposed into two sub-equations - -\begin{eqnarray}\label{rce:mass} - \pard{u^*_i}{x_i} &=& 0 \\ - \pard{(u^{n+1}_i-u^*_i)}{x_i} &=& 0\;. -\end{eqnarray} - -By substituting for the velocity difference into the equation~(\ref{eq:uin1}) we obtain -\begin{equation} -\pard{}{x_i}(u^{n+1}_i - u^*_i) = \pard{}{x_i}\left(-\frac{\Delta t}{\rho}\pard{}{x_i}(p^{n+1}-\gamma p^n)\right)\;. -\end{equation} -Now we can sum the separated mass equations together. This operation gives the coupled mass-momentum equation -\begin{equation} - \pard{u^*_i}{x_i} - \frac{\Delta t}{\rho}\frac{\partial^2}{\partial x^2_i}(p^{n+1}-\gamma p^n) = 0\;. -\end{equation} -The final set of equations reads -\begin{eqnarray} -u^*_i &=& u^n_i+b_i\Delta t - \frac{\Delta t}{\rho}\pard{}{x_i}\gamma p^n+\frac{\Delta t\mu}{\rho}\pard{}{x_j}\left(\pard{u^{n+\theta}_i}{x_j}\right)\;,\\ -\frac{\partial^2}{\partial x^2_i}(p^{n+1}) &=& \frac{\rho}{\Delta t}\pard{u^*_i}{x_i}+\frac{\partial^2}{\partial x^2_i}(\gamma p^n)\;, \\ -u^{n+1}_i &=& u^*_i- \frac{\Delta t}{\rho}\pard{}{x_i}(p^{n+1}-\gamma p^n)\;. -\end{eqnarray} -\par -The above PFEM formulation is based on the paper by Idelsohn, O\~nate and Del Pin~\cite{Idelsohn04}. The authors described an approach using arbitrary time discretization scheme and pressure split factor. Their choice of implicit scheme $\theta = 1$ was motivated by better convergence properties, whereas the decision for $\gamma = 0$ leading to greater pressure split was driven by better pressure stabilization. -\subsubsection{Spatial discretization} -The unknown functions of velocity and pressure are approximated using equal order interpolation for all variables in the final configuration -\begin{eqnarray} -u_i&=&\mbf{N}^T(X,t)\mbf{U}_i\\ -p&=&\mbf{N}^T(X,t)\mbf{P} \;. -\end{eqnarray} -By applying the Galerkin weighted residual method on the splitted governing equations, following system of linear algebraic equations is obtained -\begin{eqnarray} -\mbf{M}\mbf{U}^* &=& \mbf{M}\mbf{U}^n + \Delta t\mbf{F} - \frac{\Delta t\mu}{\rho}\mbf{K}\mbf{U}^{n+\theta}\;,\label{eq:systemA} \\ -\mbf{L}\mbf{P}^{n+1} &=&\frac{\rho}{\Delta t}\left(\mbf{G}^T\mbf{U}^*-\hat{\mbf{U}}\right) \;, \label{eq:systemB} \\ -\mbf{M}\mbf{U}^{n+1} &=& \mbf{M}\mbf{U}^* - \frac{\rho}{\Delta t}\mbf{G}\mbf{P}^{n+1} \;.\label{eq:systemC} -\end{eqnarray} -\par -The matrix $\mbf{M}$ denotes the mass matrix in a lumped form, whereas the vector $\mbf{F}$ stands for the load vector. The matrix $\mbf{G}$ represents the gradient operator, which is the transposition of the divergence operator denoted simply as $\mbf{G}^T$. Matrices $\mbf{K}$ and $\mbf{L}$ are build in a similar way however noted differently. Both mean the Laplacian operator. Due to its common use in computational mechanics, the classical notation of the stiffness matrix $\mbf{K}$ is used. Prescribed velocity components are enclosed in vector $\hat{\mbf{U}}$. -\par -In each computational time step, an iteration is performed until the equilibrium is reached. Depending on the value of $\theta$ used, the equation system for the components of the auxiliary velocity $U^*_i$~(\ref{eq:systemA}) can be solved either explicitly $\theta = 0$ or implicitly $\theta \neq 0$. Then, the calculated values of the auxiliary velocity are used as input for the pressure computation~(\ref{eq:systemB}). The last system of equations~(\ref{eq:systemC}) determines the velocity values at the end of the time step, taking auxiliary velocities and pressure or pressure increments into account. -\par -Let us summarize the iterative step. The position of the particles at the end of the previous time step is known, as well as the the value of the velocity $u^n$ and pressure $p^n$. The set of governing equations is build up for the unknowns at the end of the solution step $\theta^{n+1}$, however based on the geometry of the previous step. The changes in the position are neglected. Once the convergence is reached, the final position is computed from the old one modified by the displacement due to obtained velocity. After that, solution can proceed to the next time step. +\section{Coupled Problems} \subsection{Staggered Problem} \label{staggeredproblem} \begin{record} @@ -1495,1629 +1488,1649 @@ \subsection{FluidStructure Problem} Note: This problem type \textbf{is included in PFEM module} and it can be used only when this module is configured. -\subsection{Sparse linear solver parameters} -\label{sparselinsolver} -The sparselinsolverparams field has the following general syntax:\\ + +\chapter{Domain record(s)} +\label{_DomainRecord} +This set of records describes the whole domain and its type. Depending +on the type of problem, there may be one or several domain records. If not +indicated, one domain record is default for all problem types. + +The domain type is used to resolve the +default number of DOFs in node and their physical meaning. Format is following\\ \begin{record} - \recentry{\hspace{20mm}}{\optField{lstype$^M$}{in}} - \recentry{}{\optField{smtype}{in}} - \recentry{}{\field{solverParams$^M$}{string}} -\end{record} -where parameter \param{lstype} allows to select solver for linear system of -equations. Currently supported values are 0 (default) for direct solver -(ST\_Direct), 1 for Iterative Method Library (IML) solver (ST\_IML), -2 for Spooles direct solver, 3 for Petsc -library family of solvers, and 4 for DirectSparseSolver (ST\_DSS). -Parameter \param{smtype} allows to select sparse matrix storage -scheme. The scheme should be compatible with solver type. -Currently supported values (marked as ``id'') are summarized in table -(\ref{linsolvstoragecompattable}). The 0 value is default and selects -the symmetric skyline (SMT\_Skyline). Ther possible storage formats -include unsymmetric skyline (SMT\_SkylineU), -compressed column (SMT\_CompCol), dynamically growing compressed -column (SMT\_DynCompCol), symmetric compressed column -(SMT\_SymCompCol), spooles library storage format (SMT\_SpoolesMtrx), -PETSc library matrix representation (SMT\_PetscMtrx, a sparse -serial/parallel matrix in AIJ format), and DSS compatible matrix -representations (SMT\_DSS\_*). -The allowed \param{lstype} and \param{smtype} combinations are -summarized in the table (\ref{linsolvstoragecompattable}), together -with solver parameters related to specific solver. + \recentry{\fieldnotype{domain}}{\entKeyword{domainType}} +\end{record}\\ +The \entKeyword{domainType} can be one from the following +\begin{itemize} +\item The \entKeywordInst{2dPlaneStress} and \entKeywordInst{2d-Truss} +modes declare two default dofs per node (u-displacement, v-displacement), +\item The \entKeywordInst{3d} mode declares three default dofs per +node (u-displacement, v-displacement, w-displacement), +\item The \entKeywordInst{2dMindlinPlate} mode declares three default +dofs per node (w-displacent, u-rotation, v-rotation). Strain vector contains +$\kappa_{xx}$, $\kappa_{yy}$, $\kappa_{xy}$, $\gamma_{xz}$, $\gamma_{yz}$. Stress vector +contains $m_{xx}$, $m_{yy}$, $m_{xy}$, $q_{xz}$, $q_{yz}$. -\begin{table}[ht] -\begin{center} -%%\scalebox{0.50}{ -\begin{tabular}{|l|c|c|c|c|c|c|c|c|} -\hline -Storage format & id & \multicolumn{5}{c|}{Sparse solver, \param{lstype}} \\ -\hline -& \param{smtype} & \tiny{Direct (0)} &\tiny{IML (1)} - &\tiny{Spooles (2)}& \tiny{Petsc (3)}& \tiny{DSS (4)}& \tiny{MKLPardiso (6)}& \tiny{SuperLU\_MT (7)}\\ -\hline -\small{SMT\_Skyline} & 0&+&+& & & & &\\ -\small{SMT\_SkylineU} & 1&+&+& & & & & \\ -\small{SMT\_CompCol} & 2& &+& & & &+&+\\ -\small{SMT\_DynCompCol} & 3& &+& & & & & \\ -\small{SMT\_SymCompCol} & 4& &+& & & & & \\ -\small{SMT\_DynCompRow} & 5& &+& & & & & \\ -\small{SMT\_SpoolesMtrx} & 6& & &+& & & & \\ -\small{SMT\_PetscMtrx } & 7& & & &+& & & \\ -\small{SMT\_DSS\_sym\_LDL} & 8& & & & &+ & &\\ -\small{SMT\_DSS\_sym\_LL} & 9& & & & &+ & &\\ -\small{SMT\_DSS\_unsym\_LU}&10& & & & &+ & &\\ -\hline -\end{tabular} -%%} -\caption{Solver and storage scheme compatibility.} -\label{linsolvstoragecompattable} -\end{center} -\end{table} +\item The \entKeywordInst{3dShell} mode declares six default dofs +per node (displacement and rotation along each axis). +\item The \entKeywordInst{2dBeam} mode declares three default dofs per +node (u-displacement, w-displacement, v-rotation). +\item The \entKeywordInst{2dIncompFlow} mode declares three default + dofs per node (u-velocity, v-velocity, and pressure). +The default number of dofs per node as well as their physical meaning +can be overloaded in particular dof manager record (see section +\ref{_NodeElementSideRecords}). -The solver parameters in \param{solverParams} depend on the solver -type and are summarized in table (\ref{sparsesolverparams}). +The further records describe particular domain components - +OutputManagers, DofManagers, Elements, CrossSection models, Material +Models, Boundary and Initial Conditions and Load time functions. -\begin{table}[ht] -\begin{center} -\begin{tabular}{|l|l|l|} -\hline -Solver type & id & Solver parameters \\ -\hline -ST\_Direct &0&\\ -ST\_IML &1& \optField{stype}{in} \field{lstol}{rn} \field{lsiter}{in} -\field{lsprecond}{in}\\ - & & \optField{precondattributes}{string}\\ - -ST\_Spooles &2& \optField{msglvl}{in} \optField{msgfile}{s}\\ -ST\_Petsc &3& see Petsc manual, for details\footnotemark\\ -ST\_DSS &4& \\ -ST\_MKLPardiso&6&\\ -ST\_SuperLU\_MT&7\\ -\hline -\end{tabular} -\caption{Solver parameters.} -\label{sparsesolverparams} -\end{center} -\end{table} -\footnotetext[2]{User can set several run-time options, e.g., - \mbox{-ksp\_type}~$[$cg, gmres, bicg, bcgs$]$ - \mbox{-pc\_type}~$[$jacobi, bjacobi,none,ilu,...$]$ - \mbox{-ksp\_monitor} \mbox{-ksp\_rtol}~$<$rtol$>$ \mbox{-ksp\_view} \mbox{-ksp\_converged\_reason}. - These options will override those that are default (PETSC KSPSetFromOptions() routine is called after any other customization - routines).} -The \param{stype} allows to select particular iterative solver from IML library, currently supported values are 0 (default) for Conjugate-Gradient solver, 1 for GMRES solver. Parameter \param{lstol} represents the maximum value of residual after the -final iteration and the \param{lsiter} is maximum number of iteration for iterative solver. -The \param{precondattributes} parameters contains the optional -preconditioner parameters. -The \param{lsprecond} parameter determines the type of preconditioner to be -used. The possible values of \param{lsprecond} together with supported -storage schemes and their descriptions are summarized in table -(\ref{precondtable}). +\end{itemize} -\begin{table}[ht] -\begin{center} -\begin{tabular}{|l|l|l|l|} -\hline -Precond type & id & Compatible storage & Description and parameters \\ -\hline\hline -IML\_VoidPrec &0& all & No preconditioning\\ -\hline -IML\_DiagPrec &1& all & Diagonal preconditioning\\ -\hline -IML\_ILUPrec &2& SMT\_CompCol & Incomplete LU Decomposition\\ - & & SMT\_DynCompCol&with no fill up\\ -\hline -IML\_ILUPrec &3& SMT\_DynCompRow & Incomplete LU (ILUT) with\\ - & & & fillup. \\ - & & & The \param{precondattributes} are:\\ - & & & \optField{droptol}{rn} \optField{partfill}{in}.\\ - & & & \param{droptol} dropping tolerance\\ - & & & \param{partfill} level of fill-up\\ -\hline -IML\_ICPrec &4& SMT\_SymCompCol&Incomplete Cholesky\\ - & & SMT\_CompCol &with no fill up\\ -\hline -\end{tabular} -\caption{Preconditioning summary.} -\label{precondtable} -\end{center} -\end{table} -\subsection{Eigen value solvers} -\label{eigensolverssection} -The eigensolverparams field has the following general syntax:\\ +\section{Output manager record} +\label{_OutputManagerRecord} +The output manager controls output. It can filter output to specific +solution steps, and within these selected steps allows also to filter +output only to specific dof managers and elements. The format of +output manager record is \\ \begin{record} - \recentry{\hspace{20mm}}{\optField{stype$^M$}{in}} - \recentry{}{\optField{smtype}{in}} - \recentry{}{\field{solverParams$^M$}{string}} + \recentry{\entKeywordInst{OutputManager}}{[\fieldnotype{tstep\_all}]} + \recentry{}{\optField{tstep\_step}{in}} + \recentry{}{\optField{tsteps\_out}{rl}} + \recentry{}{[\fieldnotype{dofman\_all}]} + \recentry{}{\optField{dofman\_output}{rl}} + \recentry{}{\optField{dofman\_except}{rl}} + \recentry{}{[\fieldnotype{element\_all}]} + \recentry{}{\optField{element\_output}{rl}} + \recentry{}{\optField{element\_except}{rl}} \end{record} -where parameter \param{stype} allows to select solver type. Parameter \param{smtype} allows to select sparse matrix storage -scheme. The scheme should be compatible with solver type. Currently supported values of \param{stype} are summarized in table~\ref{eigenvaluesolverparamtable}. +To select all solution steps, in which output will be performed, use +\param{tstep\_all}. To select each \param{tstep\_step}-nth step, use +\param{tstep\_step} parameter. In order to select only specific +solution steps, the \param{tsteps\_out}list can be specified, +supplying solution step number list in which output will be done. +The combination of \param{tstep\_step} and +\param{tsteps\_out} parameters is allowed. -\begin{table}[ht] -\begin{center} -%%\scalebox{0.50}{ -\begin{tabular}{|l|l|l|} -\hline -Solver type & stype id & solver parameters \\ -Subspace Iteration & 0 (default) & \\ -Inverse Iteration& 1 & \\ -SLEPc solver& 2 & requires ``smtype 7''\\ -&& see also SLEPc manual \\ -\hline -\end{tabular} -\caption{Eigen Solver parameters.} -\label{eigenvaluesolverparamtable} -\end{center} -\end{table} +Output manager allows also to filter output to only specific dof +managers and elements. If these specific members are selected, the +output happens only in selected solution steps. +The \param{dofman\_all} and \param{element\_all} parameters select +all dof managers or elements respectively. Parameter arrays +\param{dofman\_output} and \param{element\_output} allow to select +only specific members. Numbers of selected members are then contained +in \param{dofman\_output} or \param{element\_output} lists +respectively. The previously selected members can be explicitly +de-selected by specifying their component numbers in \param{dofman\_except} or +\param{element\_except} lists. A few examples:\\ +\param{dofman\_output} \{1 3\}~~~prints nodes 1,3\\ +\param{dofman\_output} \{(1 3)\}~~~prints nodes 1,2,3\\ +\param{element\_output} \{1 3\}~~~prints elements 1,3\\ +\param{element\_output} \{(1 3)\}~~~prints elements 1,2,3\\ +\param{element\_output} \{(1 3) 5 6\}~~~prints elements 1,2,3,5,6\\ +\subsection{Components size record} +\label{_ComponentsSizeRecord} +This record describes the number of components in related domain. The +particular records will follow immediately in input file. The general format is:\\ +\begin{record} + \recentry{}{\field{ndofman}{in}} + \recentry{}{\field{nelem}{in}} + \recentry{}{\field{ncrosssect}{in}} + \recentry{}{\field{nmat}{in}} + \recentry{}{\field{nbc}{in}} + \recentry{}{\field{nic}{in}} + \recentry{}{\field{nltf}{in}} + \recentry{}{\optField{nbarrier}{in}} +\end{record} +where \param{ndofman} represents number of dof managers (e.g. nodes) and their associated records, +\param{nelem} represents number of elements and their associated records, \param{ncrosssect} is +number of cross sections and their records, \param{nmatdnMat}{} is number of material +models and their records, \param{nbc}{} represents number of boundary +conditions (including loads) and their +records, \param{nic} parameter determines the number of initial +conditions, and \param{nltf} represents number of time functions and +their associated records. The optional parameter \param{nbarrier} +represents the number of nonlocal barriers and their records. If not +specified, no barriers are assumed. -\subsection{\Pmode{Dynamic load balancing parameters}} -\label{dynamicloadbalancing} -There are in general two basic factors causing load imbalance between individual subdomains: (i) one comming from application nature, such as switching from linear to nonlinear response in certain regions or local adaptive refinment, and (ii) external factors, caused by resourse realocation, typical for nondedicated cluster environments, where indivudual processors are shared by different applications and users, leading to time variation in allocated processing power. The load balance recovery is achieved by repartitioning of the problem domain and transferring the work (represented typically by finite elements) from one subdomain to another. -This section describes the structure and syntax of parameters related to dynamic load balancing. -The corresponding part of analysis record has the following general syntax:\\ +\section{Dof manager records} +\label{_NodeElementSideRecords} +These records describe individual DofManager records (i.e. nodes or element sides (if they manage some DOFs)). The general format is following: \noindent \begin{record} - \recentry{\hspace{20mm}}{\optField{lbflag$^M$}{in}} - \recentry{}{\optField{forcelb1}{in}} - \recentry{}{\optField{wtp}{ia}} - \recentry{}{\optField{lbstep}{in}} - \recentry{}{\optField{relwct}{rn}} - \recentry{}{\optField{abswct}{rn}} - \recentry{}{\optField{minwct}{rn}} + \recentry{\entKeyword{DofManagerType}}{\componentNum} + \recentry{}{[\field{load}{ra}]} + \recentry{}{[\field{DofIDMask}{ia}]} + \recentry{}{\optField{bc}{ia}} + \recentry{}{\optField{ic}{ia}} + \recentry{}{[\field{doftype}{ia} \field{masterMask}{ia}]} + \recentry{}{\PoptFieldnotype{shared} $|$ \PoptFieldnotype{remote} $|$ \PoptFieldnotype{null}} + \recentry{}{\PoptField{partitions}{ia}} \end{record} -where the parameters have following meaning: -\begin{itemize} -\item \param{lbflag}, when set to nonzero value activates the dynamic load balancing. Default value is zero. -\item \param{forcelb1} forces the load rebalancing after the first solution step, when set to nonzero value. -\item \param{wtp} allows to activate optional load balancing plugins. At present, the only supported value is 1, that activates nonlocal plugin, necessary for nonlocal averaging to work properly when dynamic load balancing is active. -\item \param{lbstep} rebalancing, if needed, is performed only every lbstep solution step. -Default value is 1 (recover balance after every step, if necessary). -\item \param{relwcr} sets relative wall-clock imbalance treshold. When achieved relative imbalance between wall clock solution time of individual processors is greater than provided treshold, the rebalancing procedure will be activated. -\item \param{abswct} sets absolute wall-clock imbalance treshold. When achieved absolute imbalance between wall clock solution time of individual processors is greater than provided treshold, the rebalancing procedure will be activated. -\item \param{minwct} minimum absolute imbalance to perform relative imbalance check using \param{relwcr} parameter, otherwise only absolute check is done. Default value is 0. -\end{itemize} -At present, the load balancing support requires ParMETIS module to be configured and compiled. - - -% -\subsection{Error estimators and indicators} -\label{errorestimators} -The currently supported values of \param{eetype} are in table -\ref{eetypestable}. -\begin{itemize} -\item -EET\_SEI - Represents scalar error indicator. -It indicates element error based on the value of some suitable scalar -value (for example damage level, plastic strain level) obtained from the -element integration points and corresponding material model. -\item -EET\_ZZEE - The implementation of Zienkiewicz Zhu Error -Estimator. It requires the special element algorithms, which may not -be available for all element types. - -Please note, that in the actual version, the error on the element level is evaluated using default integration rule. For example, in case of ZZ error estimator, the error (L2 or energy norm) is evaluated from the difference of computed and ``recovered'' stresses, which are approximated using the same interpolation functions as displacements). Therefore, in many cases, the default integration rule order is not sufficient and higher integration must be used on elements (consult element library manual and related NIP parameter). +The order of particular records is optional, the dof manager number is determined by \componentNum\ parameter. +The numbering of individual dof managers is arbitrary, it could be even non-continuous. In this context, one could think of dof manager number as a label that is assigned to individual dof manager and by which the dof manager is referenced. +\Pmode{In parallel mode, the label represents a global id across all partitions.} -\item -EET\_CZZSI - The implementation of combined criteria: Zienkiewicz Zhu Error Estimator for elastic regime and -scalar error indicator in non-linear regime. -\end{itemize} -\begin{table}[ht] -\begin{center} -\begin{tabular}{|l|l|} -\hline -Error estimator/indicator & \param{eetype}\\ -\hline -EET\_SEI & 0 \\ -EET\_ZZEE& 1 \\ -EET\_CZZSI& 2\\ -\hline -\end{tabular} -\caption{Supported error estimators and indicators.} -\label{eetypestable} -\end{center} -\end{table} +By default, the nodal DOFs are determined by asking all the connected elements. Specifying additional dofs can be done using the using the \param{DofIDMask} array which determines their physical interpretation. +Each item of \param{DofIDMask} array describes the physical meaning of corresponding DOF in dof manager. Currently the following values are supported: \{u-displacement=1, v-displacement=2, w-displacement=3, u-rotation=4, v-ro\-ta\-tion=5, w-rotation=6, u-velocity=7, v-velocity=8, w-velocity=9, temperature=10, pressure=11, special dofs for gradient-type constitutive models=12 and 13, mass concentration=14, special dofs for extended finite elements (XFEM)=15--30\}. +\textbf{It is not allowed to have two DOFs with the same physical meaning in the same DofManager.} -The sets of parameters (\param{errorestimatorparams} field) used to -configure each error estimator are different -\begin{itemize} -\item -EET\_SEI\\ -\begin{record}[0.9\textwidth] - \recentry{\hspace{2cm}}{\optField{regionskipmap}{ia}} - \recentry{}{\field{vartype}{in}} - \recentry{}{\field{minlim}{rn} \field{maxlim}{rn}} - \recentry{}{\field{mindens}{rn} \field{maxdens}{rn} \field{defdens}{rn}} - \recentry{}{\optField{remeshingdensityratio}{rn}} -\end{record} +The applied primary (Dirichlet) boundary conditions are specified using +"bc" record, while natural boundary conditions using "load" parameter. \begin{itemize} -\item \param{regionskipmap} parameter allows to skip some regions. The -error is not evaluated in these regions and default mesh density is -used. The size of this array should be equal to number of regions and -nonzero entry indicates region to skip. -\item \param{vartype} parameter determines the type of internal -variable to be used as error indicator. Currently supported value is -1, representing damage based indicator. -\item If the indicator value is in range given by parameters (\param{minlim}, - \param{maxlim}) then the proposed mesh density is linearly -interpolated within range given by parameters (\param{mindens}, \param{maxdens}). If -indicator value is less than value of \param{minlim} parameter then -value of \param{defdens} parameter is used as -required density, if it is larger than \param{maxlim} then -\param{maxdens} is used as required density. -\item -\param{remeshingdensityratio} parameter determines the allowed ratio -between proposed density and actual density. -The remeshing is forced, whenever the actual ratio is smaller than -this value. Default value is equal to 0.80. +\item The size of "bc" array (primary bc) should be equal to number of DOFs in dof manager and i-th value relates to i-th DOF - the ordering and physical meaning of DOFs is determined by domain record and can be optionally specified for each dof manager individually (see next paragraph). The values of this array are corresponding boundary condition record numbers or zero, if no primary bc is applied to corresponding DOF. The compatible boundary condition type are required: primary conditions require "BoundaryCondition" records. +\item The load "array" contains record numbers of natural boundary conditions that are applied. The required record type for natural condition is "NodalLoad". The actual value is the summation of all contributions, if more than one natural bc is applied. See section on boundary conditions for the syntax. Please note, that the values of natural bc for individual DOFs are specified in its record, not in dofmanager record. \end{itemize} -\item -EET\_ZZEE\\ -\begin{record}[0.9\textwidth] - \recentry{\hspace{2cm}}{\optField{regionskipmap}{ia}} - \recentry{}{\field{normtype}{in}} - \recentry{}{\field{requirederror}{rn}} - \recentry{}{\field{minelemsize}{rn}} -\end{record} -\begin{itemize} -\item \param{regionskipmap} parameter allows to skip some regions. The -error is not evaluated in these regions and default mesh density is -used. The size of this array should be equal to number of regions and -nonzero entry indicates region to skip. -\item \param{normtype} Allows select the type of norm used in -evaluation of error. Default value is to use L2 norm (equal to 0), -value equal to 1 uses the energy norm. -\item \param{requirederror} parameter determines the required error to -obtain (in percents/100). -\item{minelemsize} parameter allows to set minimum limit on element size. -\end{itemize} -\item -EET\_CZZSI - combination of parameters for EET\_SEI and EET\_ZZEE; the -in elastic regions are driven using EET\_SEI, the elastic are driven -by EET\_ZZEE. -\end{itemize} +By default, if "bc" and/or "load" parameters are omitted, no primary and/or natural bc are applied. Analogously, initial conditions are represented using \param{ic} array. The size of \param{ic} array should be equal to number of DOFs in dof manager. The values of this array are corresponding initial condition record numbers or zero, if no initial condition is applied to corresponding DOF (in this case zero value is assumed as value of initial condition). +Parameters \param{dofType} and \param{masterMask} allows to connect some dof manager's dofs +(so-called ``slave'' dofs) +to corresponding dof (according to their physical meaning) of another +dof manager (so-called ``master'' dof). The master slave principle +allows for example simple modeling of structure hinges, where multiple +elements are connected by introducing multiple nodes (with same +coordinates) sharing the same displacement dofs and each one possessing +their own rotational dofs. +Parameter +\param{dofType} determines the type of (slave) dof to +create. Currently supported values are 0 for master DOF, 1 for simpleSlave DOF (linked to another single master DOF), and 2 for general +slave dof, that can depend on different DOFs belonging to different +dof managers. +If \param{dofType} is not specified, then by default all DOFs are +created as master DOFs. If provided, masterMask is also required. +The meaning of \param{masterMask} parameter is +depending on type of particular dofManager, and will be described in +corresponding sections. -\subsection{Material interfaces} -\label{materialinterfaces} -The material interfaces are used to represent and track the position of -various interfaces on fixed grids. Typical examples include free surface, -evolving interface between two materials, etc. -Available representations include: +\Pmode{ +The \param{shared} indicates, that dofmanager is shared by +neighboring partitions. The contributions from all contributing +domains are summed. Typical for node cut algorithm (see figures \ref{nodecut-lm} +and \ref{nodecut-nlm}). -\begin{tabular}{|l|l|l|} -\hline -MI & miflag & Compatibility \\ -\hline -LEPlic & 0 & 2D triangular \\ -LevelSet & 1 & 2D triangular \\ -\hline -\end{tabular} +Remote DofManager is indicated by \param{remote} parameter. +Then DofManager in active domain is only mirror of some remote +DofManager and it is necessary to copy remote values into local +ones. Typical for element cut (see fig. \ref{elmentcut-lm}). +The \param{null} parameter indicates so-called null DofManager. The +null DofManager should be shared only by remote elements (these are +only introduced for nonlocal constitutive model to allow effective +local averaging, so only local material value to be averaged are +transferred for these remote elements). Null nodes are therefore used +only for computing real integration point coordinates of remote +elements and there is no reason to maintain their unknowns (they have +no equation number assigned, see fig. \ref{nodecut-nlm}). They do not +contribute to local partition governing equation. +Only one of the \param{null} \param{remote} \param{shared} parameters can +be used for particular DofManagers. If no one is used, the DofManager +is maintained as local for particular partition. -\begin{itemize} -\item LEPlic- representation based on Volume-Of-Fluid approach; the initial distribution of VOF fractions should be specified for each element (see element manual)\\ - \begin{record}[0.9\textwidth] - \recentry{}{\optField{refvol}{rn}} - \end{record} -\begin{itemize} -\item -parameter \param{refvol} allows to set initial volume of reference fluid, then the reference volume is computed in each step and printed, so the accuracy and mass conservation can be monitored. -\end{itemize} -\item -LevelSet- level set based representation\\ -\begin{record}[0.9\textwidth] - \recentry{}{\mbox{[\field{levelset}{ra} OR \field{refmatpolyx}{ra} \field{refmatpolyy}{ra}]}} - \recentry{}{\optField{lsra}{in} \optField{rdt}{rn} \optField{rerr}{rn}} -\end{record} -\begin{itemize} -\item \param{levelset} allows to specify the initial level set values for all nodes directly. The size should be equal to total number of nodes within the domain. -\item Parameters \param{refmatpolyx} and \param{refmatpolyy} allow to initialize level set by specifying interface geometry as 2d polygon. Then polygon describes the initial zero level set, and level set values are then defined as signed distance from this polygon. Positive values are on the left side when walking along polygon. The parameter \param{refmatpolyx} specifies the x-coordinates of polygon vertices, parameter \param{refmatpolyy} y-corrdinates. Please note, that level set must be initialized, either using \param{levelset} parameter or using \param{refmatpolyx} and \param{refmatpolyy}. -\item Parameter \param{lsra} allows to select level set reinitialization algorithm. Currently supported values are 0 (no re-initialization), 1 (re-initializes the level set representation by solving $d_{\tau} = S(\phi)(1-\vert\grad d\vert)$ to steady state, default), 2 (uses fast marching method to build signed distance level set representation). -\item Parameters \param{rdt} \param{rerr} are used to control reinitialization algorithm for \param{lsra} = 0. \param{rdt} allows to change time step of integration algorithm and parameter \param{rerr} allows to change default error limit used to detect steady state. -\end{itemize} -\end{itemize} +The list of remote partitions sharing corresponding DofManager or list +containing remote partition containing remote DofManager counterpart is +specified using \param{partitions} parameter. The local partition +should not be included in the list. +The slaves are allowed, but masters have to be in the same +partition. The masters can be again remote copies. +} -\subsection{Mesh generator interfaces} -\label{meshpackages} -The mesh generator interface is responsible to provide a link to -specific mesh generator. The supported values of \param{meshpackage} -parameter are -\begin{itemize} -\item -MPT\_T3D: \param{meshpackage} = 0. T3d mesh interface. Default. Supports both 1d, 2d -(triangles) and 3d (tetrahedras) meshes. Reliable. -\item -MPT\_TARGE2: \param{meshpackage} = 1. Interface to Targe2 2D -mesh generator. -\item -MPT\_SUBDIVISION: \param{meshpackage}=3. Built-in subdivision algorithm. Supports triangular 2D and tetrahedral 3D meshes. Can operate in parallel mode. -\end{itemize} -% -\subsection{Initialization modules} -\label{InitModulesSec} -Initialization modules allow to initialize the state variables using data -previously computed by external software. The number of initialization module records is specified in -analysis record using \param{ninitmodules} parameter (see the initial part of section \ref{_AnalysisRecord}). The general format -is the following:\\ -\begin{record} - \recentry{\entKeyword{EntType}}{\field{initfile}{string}} -\end{record} -The file name following the keyword ``initfile'' specifies -the path to the file that contains the initialization data -and should be given without quotes. -Currently, the only supported initialization module is +Supported DofManagerType keywords are \begin{itemize} -\item Gauss point initialization module +\item Node record \begin{record}[0.9\textwidth] - \recentry{GPInitModule}{\field{initfile}{string}} \end{record} -\begin{itemize} -\item -Each Gauss point is represented by one line in the initialization file. -\item -The Gauss points should be given in a specific order, based on the element number and the Gauss point number, in agreement with the mesh specified in later sections. -\item -Each line referring to a Gauss point should contain the following data: - -\begin{record} - \recentry{}{\field{elnum}{in} \field{gpnum}{in} \field{coords}{ra} \field{ng}{in}} - \recentry{}{\field{var\_1\_id}{in} \field{values\_1}{ra}} - \recentry{}{ ...} - \recentry{}{\field{var\_ng\_id}{in} \field{values\_ng}{ra}} -\end{record} - \item \param{elnum} is the element number - \item \param{gpnum} is the Gauss point number - \item \param{coords} are the coordinates of the Gauss point - \item \param{ng} is the number of groups of variables that will follow - \item \param{var\_1\_id} is the identification number of variable group number 1 (according to the definitions in internalstatetype.h) - \item \param{values\_1} are the values of variables in group number 1 - \item \param{var\_ng\_id} is the identification number of variable group number ng - \item \param{values\_ng} are the values of variables in group number ng -\item Example:\\ \mbox{``37 4 3 0.02 0.04 0.05 3 52 1 0.23 62 1 0.049 1 6 0 -2.08e+07 0 0 0 0''} means that Gauss point number 4 of element number 37 has coordinates $x=0.02$, $y=0.04$ and $z=0.05$ and the initial values are specified for 3 groups of variables;\\ -the first group (variable ID 52) is of type IST\_DamageScalar (see internalstatetype.h) and contains 1 variable (since it is a scalar) with value 0.23;\\ - the second group (ID 62) is of type IST\_CumPlasticStrain -and contains 1 variable with value 0.049;\\ - the third group is of type IST\_StressTensor -and contains 6 variables (stress components $\sigma_x$, $\sigma_y$, etc.) with values -0, -2.08e+07, 0, 0, 0, 0 -\end{itemize} -\end{itemize} - -\subsection{Export modules} -\label{ExportModulesSec} -Export modules allow to export computed data into external software for -post-processing. The number of export module records is specified in -analysis record using \param{nmodules} parameter (see the initial part of section \ref{_AnalysisRecord}). The general format -is the following:\\ -\begin{record} - \recentry{\entKeyword{EntType}}{[\fieldnotype{tstep\_all}]} - \recentry{}{\optField{tstep\_step}{in}} - \recentry{}{\optField{tsteps\_out}{rl}} - \recentry{}{\optField{subtsteps\_out}{in}} - \recentry{}{[\fieldnotype{domain\_all}]} - \recentry{}{\optField{domain\_mask}{in}} -\end{record} + \recentry{\entKeywordInst{Node}}{\field{coords}{ra}} + \recentry{}{[\field{lcs}{ra}]} +\end{record}\\ +Represent an abstraction for finite element node. +The node coordinates in space (given by global coordinate system) are described +using \param{coords} attribute. This array contains x, y and possibly z +(depends on problem under consideration) coordinate of node. +By default, the coordinate system in node is global coordinate system. +User defined local coordinate system in node is described using \param{lcs} array. This +array contains six numbers, where the first three numbers represent +a directional vector of the local x-axis, and the next three numbers represent +a directional vector of the local y-axis. The local z-axis is determined +using a vector product. A right-hand coordinate system is assumed. +If user defined local coordinate system in node is specified, then the +boundary conditions and applied loading are specified in this local coordinate system. +The reactions and displacements are also in \param{lcs} system at the output. -To select all solution steps, in which output will be performed, use -\param{tstep\_all}. To select each \param{tstep\_step}-nth step, use -\param{tstep\_step} parameter. In order to select only specific -solution steps, the \param{tsteps\_out} list can be specified, -supplying solution step number list in which output will be done. -To select output for all domain of the problem the \param{domain\_all} -keyword can be used. To select only specific domains, -\param{domain\_mask} array can be used, where the values of the array -specify the domain numbers to be exported. -If the parameter \param{subtsteps\_out} = 1, it turns on the export of intermediate results, -for example during the substepping or individual equilibrium iterations. This option requires support from the solver. +The node can create only master DOFs and SimpleSlave DOFs, so the +allowable values of \param{dofType} array are in range {0,1}. +For the Node dof manager, the \param{masterMask} is the array of size +equal to number of DOFs, and the i-th value determines the +master dof manager, to which i-th dof is directly linked (the dof with +same physical meaning are linked together). +The local coordinate +system in node with same linked dofs is supported, but it should be exactly the +same as on master. -Currently, the supported export modules are following -\begin{itemize} -\item VTK export, \textbf{DEPRECATED - Use VTKXML} + +\item Rigid arm record \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{vtk}}{\optField{vars}{ia}} - \recentry{}{\optField{primvars}{ia}} - \recentry{}{\optField{cellvars}{ia}} - \recentry{}{\optField{stype}{in}} - \recentry{}{\optField{regionstoskip}{ia}} -\end{record} + \recentry{\entKeywordInst{RigidArmNode}}{\field{coords}{ra}} + \recentry{}{\field{master}{in}} + \recentry{}{\optField{masterMask}{ia}} + \recentry{}{[\field{lcs}{ra}]} +\end{record}\\ +Represent node connected to other node (called master) using rigid +arm. Rigid arm node DOFs can be linked to master (via rigid arm transformation) or can be independent. The rigid arm node allows to avoid very +stiff elements used for modelling the rigid-arm connection. +The rigid arm node maps its dofs to master dofs using simple transformations +(small rotations are assumed). Therefore, the contribution to rigid +arm node can be localized directly to master related equations. +{\em The rigid arm node can not have its own boundary or initial conditions, they are +determined completely from master dof conditions. Currently it is +possible to map only certain dofs - see \param{dofType}. Linked DOFs +should have dofType value equal to 2, non-linked (primary) DOFs 0.} +Rigid arm node can be loaded +independently of master. The node coordinates in space (given by +global coordinate system) are described using \param{coords} +field. This array contains x, y and possibly z (depends on problem +under consideration) coordinate of node. The \param{master} parameter is the +master node number, to which rigid arm node dofs are mapped. +The rigid arm node and master can have arbvitrary local coordinate systems (if not specified, global one is assumed). -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{vtkxml}}{\optField{vars}{ia}} - \recentry{}{\optField{primvars}{ia}} - \recentry{}{\optField{cellvars}{ia}} - \recentry{}{\optField{ipvars}{ia}} - \recentry{}{\optField{stype}{in}} - \recentry{}{\optField{regionsets}{ia}} - \recentry{}{\optField{timeScale}{rn}} -\end{record} +The optional parameter \param{masterMask} allows to specify how +particular mapped DOF depends on master DOFs. The size of \param{masterMask} array +should be equal to number of DOFs. For all linked DOFs (with +corresponding dofType value equal to 2) the corresponding value of +\param{masterMask} array should be 1. -\begin{itemize} -\item The vtk module is obsolete, use vtkxml instead. Vtkxml allows to export results recovered on region by region basis and has more features. +The local coordinate system in rigid arm node is supported, +the coordinate system in master and slave can be different. +If no lcs is set, global one is assumed.the global cs applies. -\item The array \param{vars} contains identifiers for those internal -variables which are to be exported. These variables will be smoothed and transfered to nodes. The id values are defined by -InternalStateType enumeration, which is defined in include file -``src/oofemlib/internal\-statetype.h''. +\item Hanging node -\item The array \param{primvars} -contains identifiers of primary variables to be exported. -The possible values correspond to the values of enumerated type -UnknownType, which is again defined in ``src/oofemlib/unknown\-type.h''. -Please note, that the values corresponding to enumerated type values -start from zero, if not specified directly and that not all values are -supported by particular material model or analysis type. +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{HangingNode}}{\field{coords}{ra}} + \recentry{}{\field{dofType}{in}} + \recentry{}{\optField{masterElement}{in}} + \recentry{}{\optField{masterRegion}{in}} +\end{record} -\item The array \param{cellvars} contains identifiers of constant variables defined -on an element (cell), e.g. a material number. Identifier numbers are specified in -``src/oofemlib/internalstatetype.h''. +Hanging node is connected to an a master element using generalized interpolation. +Hanging node posses no degrees of freedom (except unlined dofs) - all values are +interpolated from corresponding master elements and its DOFs. +arbitrary FE mesh of concrete specimen or to facilitate the local +refinement of FE mesh. The hanging nodes can be in a chain. -\item The array \param{ipvars} contains identifiers for those internal -variables which are to be exported. These variables will be directly exported (no smoothing) as point dataset, where each point corresponds to individual integration point. A separate vtu file for these raw, point data will be created. -The id values are defined by -InternalStateType enumeration, which is defined in include file -``src/oofemlib/internal\-statetype.h''. +The contributions of hanging node are localized directly to master related equations. +The hanging node can have its own boundary or initial conditions, but +only for primary unlinked DOFs. For linked DOFs, these conditions are +determined completely from master DOF conditions. +The local coordinate system should be same for all master nodes. +The hanging node can be loaded independently of its master. +Values of array \param{dofType} can have following values: +0-primary DOF, 2-linked DOF. -\item The parameter \param{stype} allows to select smoothing procedure for -internal variables, which is used to compute nodal values from values -in integration points. The supported values are $0$ for simple nodal averageing (generally supported only by triangular and tetrahedral elements), $1$ for Zienkiewicz Zhu recovery (default), and $2$ for Superconvergent Patch Recovery (SPR, based on least square fitting). +The value of \param{masterElement} specifies the element number to which the hanging node is attached. +The node can be attached to any arbitrary coordinate within the master element. +The element must support the necessary interpolation classes. +The same interpolation for unknowns and geometry is assumed. -\item The export is done on region basis, on each region, the nodal recovery is performed independently and results are exported in a separate piece. This allows to take into account for discntinuities, or to export variables defined only by particular material model. The region volumes are defined using sets containing individual elements. By default the one region is created, containing all element in the problem domain. The optional parameter \param{regionsets} allows to use user-defined. The individual values refer to numbers (ids) of domain sets. Note, that regions are determined solely using elements. +The no (or -1) value for \param{masterElement} is supplied, then the node will locate the element closest to its coordinate. +If no (or zero) value for \param{masterRegion} is supplied, then all regions will be searched, +otherwise only the elements in cross section with number \param{masterRegion}. +If \param{masterElement} is directly supplied \param{masterRegion} is unused. -{\footnotesize vtkxml tstep\_all cellvars 1 46 vars 1 1 primvars 1 1 stype 2 regionsets 2 1 2} +\item Slave node -\item \param{timeScale} scales time in output. In transport problem, basic units are seconds. Setting timeScale = 2.777777e-4 (=1/3600.) converts all time data in vtkXML from seconds to hours. +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{SlaveNode}}{\field{coords}{ra}} + \recentry{}{\field{dofType}{in}} + \recentry{}{\field{masterDofMan}{ia}} + \recentry{}{\field{weights}{ra}} +\end{record} -\end{itemize} +Works identical to hanging node, but the weights (\param{weights}) are not computed from any element, +but given explicitly, as well as the connected dof managers (\param{masterDMan}). -By default vtk and vtkxml modules perform recovery over the whole domain. The VTKXML module can operate in region-by-region mode (see \param{nvr} and \param{vrmap} parameters). In this case, the smoothing is performed only over particular virtual region, where only elements in this virtual region participate. +\item Element side -\item Homogenization of IP quantities in the global coordinate system (such as stress, strain, damage, heat flow). Corresponding IP quantities are summed and averaged over the volume. It is possible to select region sets from which the averaging occurs. The averaging works for all domains with an extension to trusses. A truss is considered as a volume element with oriented stress and strain components along the truss axis. The transformation to global components occurs before averaging. +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{ElementSide}}{} +\end{record}\\ +Represents an abstraction for element side, which holds some unknowns. + +\item PFEMParticle \label{pfemparticles} \begin{record}[0.9\textwidth] - \recentry{}{\field{ists}{ia}} - \recentry{}{\optField{scale}{rn}} - \recentry{}{\optField{regionSets}{ia}} -\end{record} -\begin{itemize} + \recentry{\entKeywordInst{PFEMParticle}}{\field{coords}{ra}} +\end{record}\\ +Represent the particle used in PFEM analysis. -\item An integer array \param{ists} specifies internal state types for export which are defined in internalstatetype.h file. +\item InteractionPFEMParticle \label{interactionparticle} -\item The parameter \param{scale} multiplies all averaged IP quantities. \param{scale}=1 by default. +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{InteractionPFEMParticle}}{\field{coords}{ra}} + \recentry{}{\field{bc}{ia}} + \recentry{}{\field{coupledNode}{in}} +\end{record}\\ +Represent a special particle used in the PFEM-part of the FluidStructureProblem. The particle is +attached to \param{coupledNode} from the structural counter part. InteractionBoundaryCondition~\ref{interactionbc} must be prescribed under \param{bc} to access the velocities from solid nodes. -\item An integer array \param{regionSets} specifies region sets for averaging. All domain is averaged by default. \end{itemize} -\item Gauss point export is useful if one needs to plot a certain variable -(such as damage) as a function of a spatial coordinate using tools like -gnuplot. It generates files with data organized in columns, each row -representing one Gauss point. In this way, one can plot e.g.\ the damage -distribution along a one-dimensional bar. +\section{Element records} +\label{_ElementsRecords} +These records specify a description of particular elements. The +general format is following: -\begin{record}[0.9\textwidth] - \recentry{gpexportmodule}{\optField{vars}{ia}} - \recentry{}{\optField{ncoords}{in}} +\noindent +\begin{record} + \recentry{\entKeyword{ElementType}}{\componentNum} + \recentry{}{\field{mat}{in} \field{crossSect}{in} \field{nodes}{ia}} + \recentry{}{\optField{bodyLoads}{ia} \optField{boundaryLoads}{ia}} + \recentry{}{\optField{activityltf}{in} \optField{lcs}{ra}} + \recentry{}{\PoptField{partitions}{ia} \PoptFieldnotype{remote}} \end{record} -\begin{itemize} -\item The array \param{vars} contains identifiers for those internal -variables which are to be exported. The id values are defined by -InternalStateType enumeration, which is defined in include file -``src/oofemlib/internal\-statetype.h''. -\item Parameter \param{ncoords} specifies the number of spatial coordinates to be exported at each Gauss point. Depending on the spatial dimension of the -domain, the points can have one, two or three coordinates. If \param{ncoords} -is set to -1, only those coordinates that are actually used are exported. - If \param{ncoords} is set to 0, no coordinates are exported. -If \param{ncoords} -is set to a positive integer, exactly \param{ncoords} coordinates are exported. -If \param{ncoords} exceeds the actual number of coordinates, the actual -coordinates are supplemented by zeros. For instance, if we deal with a 2D -problem, the actual number of coordinates is 2. For \param{ncoords}=3, -the two actual coordinates followed by 0 will be exported. -For \param{ncoords}=1, only the first coordinate will be exported. -\end{itemize} -The Gauss point export module creates a file with extension ``gp'' -after each step for which the output is performed. This file contains -a header with lines starting by the symbol \#, followed by the actual data -section. -Each data line corresponds to one Gauss point and contains the following -data: -\begin{enumerate} -\item element number, - \item material number, - \item Gauss point number, - \item contributing volume around Gauss point, -\item Gauss point global coordinates (written as a real array of length \param{ncoords}), -\item internal variables according to the specification in \param{vars} (each written as a real array of the corresponding length). -\end{enumerate} -Example:\\ -``GPExportModule 1 tstep\_step 100 domain\_all ncoords 2 vars 5 4 13 31 64 65'' -\\ -means that the *.gp file will be written after each 100 steps and will contain -for each of the Gauss points in the entire domain its 2 coordinates and also internal -variables of type 4, 13, 31, 64 and 65, which are the strain tensor, damage tensor, maximum equivalent strain level, stress work density and dissipated work density. Of course, the material model must be able to deliver such variables. -The size of the strain tensor depends on the spatial dimension, and the size -of the damage tensor depends on the spatial dimension and type of model -(e.g., for a simple isotropic damage model it will have just 1 component -while for an anisotropic damage model it may have more). The other variables -in this example are scalars, but they will be written as arrays of length 1, -so the actual value will always be preceded by ``1'' as the length of the array. Since certain internal variables have the meaning of densities (per unit volume -or area, again depending on the spatial dimension), it is useful to have -access to the contributing volume of the Gauss point. The product of this -contributing volume and the density gives an additive contribution to the -total value of the corresponding variable. This can be exploited e.g.\ to -evaluate the total dissipated energy over the entire domain. -\end{itemize} +The order of element records is optional, the element number is determined by \componentNum\ parameter. +The numbering of individual elements is arbitrary, it could be even non-continuous. In this context, one could think of element number as a label that is assigned to individual elements and by which the element is referenced. +\Pmode{In parallel mode, the label represents a global id across all partitions.} -\section{Domain record(s)} -\label{_DomainRecord} -This set of records describes the whole domain and its type. Depending -on the type of problem, there may be one or several domain records. If not -indicated, one domain record is default for all problem types. +Element +material is described by parameter \param{mat}, which contains corresponding +material record number. Element cross +section is determined by cross section with \param{crossSect} +record number. Element dof managers (nodes, sides, etc.) defining element geometry are specified using +\param{nodes} array. -The domain type is used to resolve the -default number of DOFs in node and their physical meaning. Format is following\\ -\begin{record} - \recentry{\fieldnotype{domain}}{\entKeyword{domainType}} -\end{record}\\ -The \entKeyword{domainType} can be one from the following -\begin{itemize} -\item The \entKeywordInst{2dPlaneStress} and \entKeywordInst{2d-Truss} -modes declare two default dofs per node (u-displacement, v-displacement), -\item The \entKeywordInst{3d} mode declares three default dofs per -node (u-displacement, v-displacement, w-displacement), -\item The \entKeywordInst{2dMindlinPlate} mode declares three default -dofs per node (w-displacent, u-rotation, v-rotation). Strain vector contains -$\kappa_{xx}$, $\kappa_{yy}$, $\kappa_{xy}$, $\gamma_{xz}$, $\gamma_{yz}$. Stress vector -contains $m_{xx}$, $m_{yy}$, $m_{xy}$, $q_{xz}$, $q_{yz}$. +Body load acting on element is specified using \param{bodyLoads} array. Components +of this array are corresponding load record numbers. The loads should +have the proper type (body load type), otherwise error will be generated. + +Boundary load acting on element boundary is specified using +\param{boundaryLoads} array. The format of this array is +\begin{displaymath} +2\cdot size \; lnum(1)~id(1)~\dots~lnum(size)~id(size), +\end{displaymath} +where $size$ is total number of loadings applied to element, +$lnum(i)$ is the applied load number, and $id(i)$ +is the corresponding entity number, to which the load is applied (for example +a side or a surface number). The entity numbering is element dependent and +is described in element specific sections. The applied loads must be +of proper type (boundary load type), otherwise error is generated. -\item The \entKeywordInst{3dShell} mode declares six default dofs -per node (displacement and rotation along each axis). -\item The \entKeywordInst{2dBeam} mode declares three default dofs per -node (u-displacement, w-displacement, v-rotation). -\item The \entKeywordInst{2dIncompFlow} mode declares three default - dofs per node (u-velocity, v-velocity, and pressure). -The default number of dofs per node as well as their physical meaning -can be overloaded in particular dof manager record (see section -\ref{_NodeElementSideRecords}). +The support for element insertion and removal during the analysis is provided. One can specify optional time function (identified by its id using \param{activityltf} parameter). The nonzero value of this time function indicates, whether the element is active (nonzero value, the default) or inactive (zero value) at particulat solution step. Tested for structural and transport elements. This feature allows considering temperature evolution of layered casting of concrete, where certain layers needs to be inactive before they are cast. See a corresponding example in oofem +tests how to enforce hydrating material model, boundary conditions and element activity acting concurrently. -The further records describe particular domain components - -OutputManagers, DofManagers, Elements, CrossSection models, Material -Models, Boundary and Initial Conditions and Load time functions. +Orientation of local coordinates can be specified using \param{lcs} array. This array contains six numbers, +where the first three numbers represent a directional vector of local +x-axis, and the next three numbers represent a directional vector of local +y-axis. The local z-axis is determined using the vector product. The \param{lcs} array on the element is particularly useful for modeling of orthotropic materials which follow the element orientation. On a beam or truss element, the \param{lcs} array has no effect and the 1D element orientation is aligned with the global $xx$ component. -\end{itemize} +\Pmode{ +The \param{remote} forces the element to be remote element. Remote +element does not contribute to local partition governing equation. +They are introduced in order to implement band of elements involved +in computation of nonlocal variables (see fig. \ref{nodecut-nlm} illustrating +this approach for node-cut partitioning). They role is to provide +local mirror of corresponding remote partition element integration point values which undergo +nonlocal averaging on local partition. +%This mirroring will lead to +%minimized communication pattern when exchanging remote element data, +%because values are transferred only once, instead of fine grain +%communication when each local element possibly requests its remote +%data over network. +If not used, element is assumed to be local partition element. +When \param{remote} is used, the \param{partitions} parameter should +contain remote partition number, where +corresponding element is local (this array should have size equal to one). +} -\subsection{Output manager record} -\label{_OutputManagerRecord} -The output manager controls output. It can filter output to specific -solution steps, and within these selected steps allows also to filter -output only to specific dof managers and elements. The format of -output manager record is \\ -\begin{record} - \recentry{\entKeywordInst{OutputManager}}{[\fieldnotype{tstep\_all}]} - \recentry{}{\optField{tstep\_step}{in}} - \recentry{}{\optField{tsteps\_out}{rl}} - \recentry{}{[\fieldnotype{dofman\_all}]} - \recentry{}{\optField{dofman\_output}{rl}} - \recentry{}{\optField{dofman\_except}{rl}} - \recentry{}{[\fieldnotype{element\_all}]} - \recentry{}{\optField{element\_output}{rl}} - \recentry{}{\optField{element\_except}{rl}} -\end{record} -To select all solution steps, in which output will be performed, use -\param{tstep\_all}. To select each \param{tstep\_step}-nth step, use -\param{tstep\_step} parameter. In order to select only specific -solution steps, the \param{tsteps\_out}list can be specified, -supplying solution step number list in which output will be done. -The combination of \param{tstep\_step} and -\param{tsteps\_out} parameters is allowed. +Available material models, their outline and +corresponding parameters are described in separate \textbf{Element Library Manual.} -Output manager allows also to filter output to only specific dof -managers and elements. If these specific members are selected, the -output happens only in selected solution steps. -The \param{dofman\_all} and \param{element\_all} parameters select -all dof managers or elements respectively. Parameter arrays -\param{dofman\_output} and \param{element\_output} allow to select -only specific members. Numbers of selected members are then contained -in \param{dofman\_output} or \param{element\_output} lists -respectively. The previously selected members can be explicitly -de-selected by specifying their component numbers in \param{dofman\_except} or -\param{element\_except} lists. A few examples:\\ -\param{dofman\_output} \{1 3\}~~~prints nodes 1,3\\ -\param{dofman\_output} \{(1 3)\}~~~prints nodes 1,2,3\\ -\param{element\_output} \{1 3\}~~~prints elements 1,3\\ -\param{element\_output} \{(1 3)\}~~~prints elements 1,2,3\\ -\param{element\_output} \{(1 3) 5 6\}~~~prints elements 1,2,3,5,6\\ -\subsection{Components size record} -\label{_ComponentsSizeRecord} -This record describes the number of components in related domain. The -particular records will follow immediately in input file. The general format is:\\ -\begin{record} - \recentry{}{\field{ndofman}{in}} - \recentry{}{\field{nelem}{in}} - \recentry{}{\field{ncrosssect}{in}} - \recentry{}{\field{nmat}{in}} - \recentry{}{\field{nbc}{in}} - \recentry{}{\field{nic}{in}} - \recentry{}{\field{nltf}{in}} - \recentry{}{\optField{nbarrier}{in}} -\end{record} -where \param{ndofman} represents number of dof managers (e.g. nodes) and their associated records, -\param{nelem} represents number of elements and their associated records, \param{ncrosssect} is -number of cross sections and their records, \param{nmatdnMat}{} is number of material -models and their records, \param{nbc}{} represents number of boundary -conditions (including loads) and their -records, \param{nic} parameter determines the number of initial -conditions, and \param{nltf} represents number of time functions and -their associated records. The optional parameter \param{nbarrier} -represents the number of nonlocal barriers and their records. If not -specified, no barriers are assumed. +\section{Set records} +\label{_SetRecords} -\subsection{Dof manager records} -\label{_NodeElementSideRecords} -These records describe individual DofManager records (i.e. nodes or element sides (if they manage some DOFs)). The general format is following: +Sets specify regions of the geometry as a combination of volumes, surfaces, edges, and nodes. +The main usage of sets are to connect regions of elements to a given cross section or apply a boundary condition, though sets can be used for many other things as well. -\noindent -\begin{record} - \recentry{\entKeyword{DofManagerType}}{\componentNum} - \recentry{}{[\field{load}{ra}]} - \recentry{}{[\field{DofIDMask}{ia}]} - \recentry{}{\optField{bc}{ia}} - \recentry{}{\optField{ic}{ia}} - \recentry{}{[\field{doftype}{ia} \field{masterMask}{ia}]} - \recentry{}{\PoptFieldnotype{shared} $|$ \PoptFieldnotype{remote} $|$ \PoptFieldnotype{null}} - \recentry{}{\PoptField{partitions}{ia}} +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{Set}}{\componentNum} + \recentry{}{\optField{elements}{ia} \optField{elementranges}{rl} \optional{allElements}} + \recentry{}{\optField{nodes}{ia} \optField{noderanges}{rl} \optional{allNodes}} + \recentry{}{\optField{elementboundaries}{ia} \optField{elementedges}{ia}} \end{record} -The order of particular records is optional, the dof manager number is determined by \componentNum\ parameter. -The numbering of individual dof managers is arbitrary, it could be even non-continuous. In this context, one could think of dof manager number as a label that is assigned to individual dof manager and by which the dof manager is referenced. -\Pmode{In parallel mode, the label represents a global id across all partitions.} +Volumes (elements) and nodes can be specified using either a list, \param{elements}, \param{nodes}, or with a range list \param{elementranges}, \param{noderanges}. +Edges \param{elementedges}, and surfaces \param{elementboundaries}, are specified in a interleaved list, every other number specifying the element, and edge/surface number (the total length of the list being twice the number of surfaces/edges). +The internal numbering of edges/surfaces is available in the \textbf{Element Library Manual}. -By default, the nodal DOFs are determined by asking all the connected elements. Specifying additional dofs can be done using the using the \param{DofIDMask} array which determines their physical interpretation. -Each item of \param{DofIDMask} array describes the physical meaning of corresponding DOF in dof manager. Currently the following values are supported: \{u-displacement=1, v-displacement=2, w-displacement=3, u-rotation=4, v-ro\-ta\-tion=5, w-rotation=6, u-velocity=7, v-velocity=8, w-velocity=9, temperature=10, pressure=11, special dofs for gradient-type constitutive models=12 and 13, mass concentration=14, special dofs for extended finite elements (XFEM)=15--30\}. -\textbf{It is not allowed to have two DOFs with the same physical meaning in the same DofManager.} - -The applied primary (Dirichlet) boundary conditions are specified using -"bc" record, while natural boundary conditions using "load" parameter. -\begin{itemize} -\item The size of "bc" array (primary bc) should be equal to number of DOFs in dof manager and i-th value relates to i-th DOF - the ordering and physical meaning of DOFs is determined by domain record and can be optionally specified for each dof manager individually (see next paragraph). The values of this array are corresponding boundary condition record numbers or zero, if no primary bc is applied to corresponding DOF. The compatible boundary condition type are required: primary conditions require "BoundaryCondition" records. -\item The load "array" contains record numbers of natural boundary conditions that are applied. The required record type for natural condition is "NodalLoad". The actual value is the summation of all contributions, if more than one natural bc is applied. See section on boundary conditions for the syntax. Please note, that the values of natural bc for individual DOFs are specified in its record, not in dofmanager record. -\end{itemize} +Note that edge loads (singular loads given in ``newton per length'' (or equivalent), should be applied to \param{elementedges}, surface loads ``newton per area'' on \param{elementboundaries}, and bulk loads ``newton per volume'' on \param{elements}. -By default, if "bc" and/or "load" parameters are omitted, no primary and/or natural bc are applied. Analogously, initial conditions are represented using \param{ic} array. The size of \param{ic} array should be equal to number of DOFs in dof manager. The values of this array are corresponding initial condition record numbers or zero, if no initial condition is applied to corresponding DOF (in this case zero value is assumed as value of initial condition). +Example 1: A deadweight (gravity) load would be applied to the \param{elements} in a set, while a distributed line load would be applied to the midline ``edge'' of the beam element, thus should be applied to a \param{elementedges} set. In the latter case, the midline of the beam is defined as the first (and only) ``edge'' of the beam. -Parameters \param{dofType} and \param{masterMask} allows to connect some dof manager's dofs -(so-called ``slave'' dofs) -to corresponding dof (according to their physical meaning) of another -dof manager (so-called ``master'' dof). The master slave principle -allows for example simple modeling of structure hinges, where multiple -elements are connected by introducing multiple nodes (with same -coordinates) sharing the same displacement dofs and each one possessing -their own rotational dofs. -Parameter -\param{dofType} determines the type of (slave) dof to -create. Currently supported values are 0 for master DOF, 1 for simpleSlave DOF (linked to another single master DOF), and 2 for general -slave dof, that can depend on different DOFs belonging to different -dof managers. -If \param{dofType} is not specified, then by default all DOFs are -created as master DOFs. If provided, masterMask is also required. -The meaning of \param{masterMask} parameter is -depending on type of particular dofManager, and will be described in -corresponding sections. +Example 2: Axisymmetric structural element analysis: A deadweight load would be applied to \param{elements} in a set. A external pressure would be defined as a surface load an be applied to the \param{elementboundaries} in a set. The element integrates the load (analytically) around the axis, so the load would still count as a surface load. -\Pmode{ -The \param{shared} indicates, that dofmanager is shared by -neighboring partitions. The contributions from all contributing -domains are summed. Typical for node cut algorithm (see figures \ref{nodecut-lm} -and \ref{nodecut-nlm}). -Remote DofManager is indicated by \param{remote} parameter. -Then DofManager in active domain is only mirror of some remote -DofManager and it is necessary to copy remote values into local -ones. Typical for element cut (see fig. \ref{elmentcut-lm}). -The \param{null} parameter indicates so-called null DofManager. The -null DofManager should be shared only by remote elements (these are -only introduced for nonlocal constitutive model to allow effective -local averaging, so only local material value to be averaged are -transferred for these remote elements). Null nodes are therefore used -only for computing real integration point coordinates of remote -elements and there is no reason to maintain their unknowns (they have -no equation number assigned, see fig. \ref{nodecut-nlm}). They do not -contribute to local partition governing equation. -Only one of the \param{null} \param{remote} \param{shared} parameters can -be used for particular DofManagers. If no one is used, the DofManager -is maintained as local for particular partition. +\section{Cross section records} +\label{_CrossSectionRecords} +These records specify a cross section model descriptions. The general format is +following: -The list of remote partitions sharing corresponding DofManager or list -containing remote partition containing remote DofManager counterpart is -specified using \param{partitions} parameter. The local partition -should not be included in the list. -The slaves are allowed, but masters have to be in the same -partition. The masters can be again remote copies. -} +\begin{record}[0.9\textwidth] + \recentry{\entKeyword{CrossSectType}}{\componentNum} +\end{record} +The order of particular cross section records is optional, cross section model number is determined by \componentNum\ parameter. +The numbering should start from one and should end at n, where n is the number of records. -Supported DofManagerType keywords are +The crossSectType keyword can be one from following possibilities \begin{itemize} -\item Node record +\item +Integral cross section with constant properties\\ +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{SimpleCS}}{\optField{thick}{rn} \optField{width}{rn} \optField{area}{rn}} + \recentry{}{\optField{iy}{rn} \optField{iz}{rn} \optField{ik}{rn}} + \recentry{}{\optField{shearareay}{rn} \optField{shearareaz}{rn} \field{beamshearcoeff}{rn}} +\end{record}\\ +Represents integral type of cross section model. In current +implementation, such cross section is described using cross section +thick (\param{thickVal}) and width (\param{widthVal}). For some +problems (for example 3d), the corresponding volume and cross section dimensions are +determined using element geometry, and then you can omit some (or all) parameters (refer to documentation of individual elements for required cross section properties). Parameter \param{area} allows to set cross section area, parameters \param{iz}, \param{iz}, and \param{ik} represent +inertia moment along y and z axis and torsion inertia moment. Parameter \param{beamshearcoeff} allows to set shear correction factor, or equivalent +shear areas (\param{shearareay} and \param{shearareaz} parameters) can be provided. +These cross section properties are assumed to be defined in local coordinate system of element.\\ + +\item +Integral cross section with variable properties\\ +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{VariableCS}}{\optField{thick}{expr} \optField{width}{expr} \optField{area}{expr}} + \recentry{}{\optField{iy}{expr} \optField{iz}{expr} \optField{ik}{expr}} + \recentry{}{\optField{shearareay}{expr} \optField{shearareaz}{expr} } +\end{record}\\ +Represents integral type of cross section model, where individual cross section parameters can be expressed as an arbitrary function of global coordinates x,y,z. Similar to SimpleCS, for some problems (for example 3d), the corresponding volume and cross section dimensions are +determined using element geometry, then you can omit many (or some) parameters (refer to documentation of individual elements for required cross section properties). +Parameter \param{area} allows to set cross section area, parameters \param{iz}, \param{iz}, and \param{ik} represent +inertia moment along y and z axis and torsion inertia moment. Parameters (\param{shearareay} and \param{shearareaz} determine shear area, which is required by beam and plate elements. All cross section properties are assumed to be defined in local coordinate system of element.\\ + +\item +Layered cross section \\ +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{LayeredCS}}{\field{nLayers}{in}} + \recentry{}{\field{LayerMaterials}{ia}} + \recentry{}{\field{Thicks}{ra} \field{Widths}{ra}} + \recentry{}{\field{mid\-Surf}{rn}} +\end{record}\\ +Represents the layered cross section model, based on +geometrical hypothesis, that cross sections remain planar after +deformation. Number of layers is +determined by \param{nLayers} parameter. Materials for each +layer are specified by \param{LayerMaterials} array. For each layer is +necessary to input +geometrical characteristic, thick - using \param{Thicks} array, and +width - using +\param{Widths} array. Position of mid surface is determined by its +distance from +bottom of cross section using \param{mid\-Surf} parameter (normal and +momentum forces are then computed with regard to it's position). +Elements using this cross section model must implement layered cross +section extension. For information see element library manual. +\item +Fibered cross section\\ +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{FiberedCS}}{\field{nfibers}{in} \field{fibermaterials}{ia}} + \recentry{}{\field{thicks}{ra} \field{widths}{ra} \field{thick}{rn} \field{width}{rn}} + \recentry{}{\field{fiberycentrecoords}{ra} \field{fiberzcentrecoords}{ra}} +\end{record}\\ +Cross section represented as a set of rectangular fibers. It is based on +geometrical hypothesis, that cross sections remain planar after +deformation (3d generalization of layered approach for beams). +Paramater \param{nfibers} determines the number of fibers that together form the overall cross section. +The model requires to specify a material model corresponding to particular fiber using \param{fibermaterials} array. This array should contain for each fibre corresponding material model number (the material model specified on element level has no meaning in this particular case). +\textbf{The geometry of cross section is determined from fiber dimensions and fiber positions, all input in local coordinate system of the beam (yz plane).} The thick and width of each fiber are determined using \param{thicks} and \param{widths} arrays. The overall thick and width are specified using parameters \param{thick} and \param{width}. Positions of particular fibers are specified by providing coordinates of center of each fiber using \param{fiberycentrecoords} array for y-coordinates and \param{fiberzcentrecoords} array for z-coordinates. +%%\item \entKeywordInst{HeatCS} \field{thick}{rn} +%%\field{width}{rn}\\ +%%Represents cross section abstraction for heat transfer problems. +%%The input parameters are: thick - determined using \param{thick} parameter +%%and width - determined using \param{width} parameter of cross section. +\item +Warping cross section \\ \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{Node}}{\field{coords}{ra}} - \recentry{}{[\field{lcs}{ra}]} -\end{record} -Represent an abstraction for finite element node. -The node coordinates in space (given by global coordinate system) are described -using \param{coords} attribute. This array contains x, y and possibly z -(depends on problem under consideration) coordinate of node. -By default, the coordinate system in node is global coordinate system. -User defined local coordinate system in node is described using \param{lcs} array. This -array contains six numbers, where the first three numbers represent -a directional vector of the local x-axis, and the next three numbers represent -a directional vector of the local y-axis. The local z-axis is determined -using a vector product. A right-hand coordinate system is assumed. -If user defined local coordinate system in node is specified, then the -boundary conditions and applied loading are specified in this local coordinate system. -The reactions and displacements are also in \param{lcs} system at the output. - -The node can create only master DOFs and SimpleSlave DOFs, so the -allowable values of \param{dofType} array are in range {0,1}. -For the Node dof manager, the \param{masterMask} is the array of size -equal to number of DOFs, and the i-th value determines the -master dof manager, to which i-th dof is directly linked (the dof with -same physical meaning are linked together). -The local coordinate -system in node with same linked dofs is supported, but it should be exactly the -same as on master. +\recentry{\entKeywordInst{WarpingCS}}{\field{WarpingNode}{in}} +\end{record}\\ +Represents the cross section for Free warping analysis, see section \ref{FreeWarping}. The \param{WarpingNode} parametr defines the number of external node with prescribed boundary condition which corresponds to the relative twist of warping cross section. +\end{itemize} -\item Rigid arm record +\section{Material type records} +\label{_MaterialTypeRecords} +These records specify a material model description. The general format is +following: -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{RigidArmNode}}{\field{coords}{ra}} - \recentry{}{\field{master}{in}} - \recentry{}{\optField{masterMask}{ia}} - \recentry{}{[\field{lcs}{ra}]} +\noindent +\begin{record} + \recentry{\entKeyword{MaterialType}}{\componentNum\ \field{d}{rn}} \end{record} -Represent node connected to other node (called master) using rigid -arm. Rigid arm node DOFs can be linked to master (via rigid arm transformation) or can be independent. The rigid arm node allows to avoid very -stiff elements used for modelling the rigid-arm connection. -The rigid arm node maps its dofs to master dofs using simple transformations -(small rotations are assumed). Therefore, the contribution to rigid -arm node can be localized directly to master related equations. -{\em The rigid arm node can not have its own boundary or initial conditions, they are -determined completely from master dof conditions. Currently it is -possible to map only certain dofs - see \param{dofType}. Linked DOFs -should have dofType value equal to 2, non-linked (primary) DOFs 0.} -Rigid arm node can be loaded -independently of master. The node coordinates in space (given by -global coordinate system) are described using \param{coords} -field. This array contains x, y and possibly z (depends on problem -under consideration) coordinate of node. The \param{master} parameter is the -master node number, to which rigid arm node dofs are mapped. -The rigid arm node and master can have arbvitrary local coordinate systems (if not specified, global one is assumed). +The order of particular material records is optional, the material number is determined by \componentNum\ parameter. +The numbering should start from one and should end at n, where n is the number of records. +Material density is compulsory parameter and it's value is given by +\param{d} parameter. -The optional parameter \param{masterMask} allows to specify how -particular mapped DOF depends on master DOFs. The size of \param{masterMask} array -should be equal to number of DOFs. For all linked DOFs (with -corresponding dofType value equal to 2) the corresponding value of -\param{masterMask} array should be 1. +Available material models, their outline and +corresponding parameters are described in separate \textbf{Material Library Manual}. -The local coordinate system in rigid arm node is supported, -the coordinate system in master and slave can be different. -If no lcs is set, global one is assumed.the global cs applies. +\section{Nonlocal barrier records} +\label{_NonlocalBarrierRecords} +Nonlocal material models of integral type are based on replacement of +certain suitable local quantity in local constitutive law by their +nonlocal counterparts, that are obtained as weighted average over +some characteristic volume. The weighted average is computed as a sum +of a remote value multiplied by weight function value. The weight +function typically depend on a distance between remote and receiver +points and decreases with increasing distance. In some cases, it is +necessary to disregard mutual interaction between some points (for +example if they are on the opposite sides of a thin notch, which +prevents the nonlocal interactions to take place). The barriers are +the way how to introduce these constrains. The barrier represent a +curve (in 2D) or surface (in 3D). When the line connecting receiver and +remote point intersects a barrier, the barriers is activated and the +corresponding interaction is not taken into account. -\item Hanging node +Currently, the supported barrier types are following: +\begin{itemize} +\item + Polyline barrier \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{HangingNode}}{\field{coords}{ra}} - \recentry{}{\field{dofType}{in}} - \recentry{}{\optField{masterElement}{in}} - \recentry{}{\optField{masterRegion}{in}} -\end{record} + \recentry{\entKeywordInst{polylinebarrier}}{\componentNum\ \field{vertexnodes}{ia}} + \recentry{}{\optField{xcoordindx}{in} \optField{ycoordindx}{in}} +\end{record}\\ +This represents a polyline barrier for 2D problems. Barrier is a +polyline, defined as a sequence of nodes representing vertices. +The vertices are specified using parameter \param{vertexnodes} array, +which contains the node numbers. The optional parameters +\param{xcoordindx} and \param{ycoordindx} allow to select the plane +(xy, yz, or xz), where the barrier is defined. The \param{xcoordindx} is the +first coordinate index, \param{ycoordindx} is the second. The default values +are 1 for \param{xcoordindx} and 2 for \param{ycoordindx}, representing barrier in xy plane. +\item Symmetry barrier -Hanging node is connected to an a master element using generalized interpolation. -Hanging node posses no degrees of freedom (except unlined dofs) - all values are -interpolated from corresponding master elements and its DOFs. -arbitrary FE mesh of concrete specimen or to facilitate the local -refinement of FE mesh. The hanging nodes can be in a chain. +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{symmetrybarrier}}{\componentNum\ \field{origin}{ra}} + \recentry{}{\field{normals}{ra} \field{activemask}{ia}} +\end{record}\\ +Implementation of symmetry barier, that allows to specify up to three planes (orthogonal ones) of symmetry. +This barrier allows to model the symmetry of the averaged field on the boundary without +the need of modeling the other part of structure across the plane of symmetry. +It is based on modifying the integration weights of source points to take into account +the symmetry. +The potential symmetry planes are determined by specifying orthogonal right-handed coordinate system, +where axes represent the normals of corresponding symmetry planes. +Parameter \param{origin} determines the origin of the coordinate system, the \param{normals} array +contains three components of x-axis direction vector, +followed by three components of y-axis direction vector (expressed in global coordinate system). +The z-axis is determined from the orthogonality conditions. +Parameter \param{activemask} allows to specify active symmetry planes; i-th nonzero value activates the symmetry barrier for plane +with normal determined by corresponding coordinate axis (x=1, y=2, z=3). +\end{itemize} -The contributions of hanging node are localized directly to master related equations. -The hanging node can have its own boundary or initial conditions, but -only for primary unlinked DOFs. For linked DOFs, these conditions are -determined completely from master DOF conditions. -The local coordinate system should be same for all master nodes. -The hanging node can be loaded independently of its master. +\section{Load and boundary conditions} +\label{_LoadBoundaryInitialConditions} +These records specify description of boundary conditions. The general format is +following: -Values of array \param{dofType} can have following values: -0-primary DOF, 2-linked DOF. +\noindent +\begin{record} + \recentry{\entKeyword{EntType}}{\componentNum} + \recentry{}{\field{loadTimeFunction}{in}} + \recentry{}{\optField{valType}{in} \optField{dofs}{ia}} + \recentry{}{\optField{is\-Impo\-sed\-Ti\-me\-Fun\-ction}{in}} +\end{record} -The value of \param{masterElement} specifies the element number to which the hanging node is attached. -The node can be attached to any arbitrary coordinate within the master element. -The element must support the necessary interpolation classes. -The same interpolation for unknowns and geometry is assumed. +The order of particular records is optional, boundary condition number is determined by \componentNum\ parameter. +The numbering should start from one and should end at n, where n is the number of records. +Time function value (given by \param{loadTimeFunction} parameter) is a multiplier, using which +each component (value of loading or value of boundary condition) +describes its time variation. +The optional parameter \param{valType} allows to determine the +physical meaning of bc value, which is sometimes required. Supported +values are (1 - temperature, 2 - force/traction, +3 - pressure, 4 - humudity, 5 - velocity, 6 - displacement). +Another optional parameter \param{dofs} is used to determine which dofs the boundary condition should act +upon. It is not relevant for all BCs.. -The no (or -1) value for \param{masterElement} is supplied, then the node will locate the element closest to its coordinate. -If no (or zero) value for \param{masterRegion} is supplied, then all regions will be searched, -otherwise only the elements in cross section with number \param{masterRegion}. -If \param{masterElement} is directly supplied \param{masterRegion} is unused. +The nonzero value of \param{isImposedTimeFunction} time function +indicates that given boundary condition is active, zero value +indicates not active boundary condition in given time (the bc does not +exist). By default, the boundary condition applies at any time. -\item Slave node +Currently, EntType keyword can be one from +\begin{itemize} +\item Dirichlet boundary condition + +\noindent \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{SlaveNode}}{\field{coords}{ra}} - \recentry{}{\field{dofType}{in}} - \recentry{}{\field{masterDofMan}{ia}} - \recentry{}{\field{weights}{ra}} + \recentry{\entKeywordInst{BoundaryCondition}}{\field{prescribedvalue}{rn}} + \recentry{}{\optField{d}{rn}} \end{record} -Works identical to hanging node, but the weights (\param{weights}) are not computed from any element, -but given explicitly, as well as the connected dof managers (\param{masterDMan}). +Represents boundary condition. +Prescribed value is specified using \param{prescribedvalue} parameter. +The physical meaning of value is fully determined by corresponding DOF. +Optionally, the prescribed value can be specified using \param{d} +parameter. It is introduced for compatibility reasons. If +\param{prescribedvalue} is specified, then \param{d} is ignored. -\item Element side +\item Prescribed gradient boundary condition (Dirichlet type) \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{ElementSide}}{} + \recentry{\entKeywordInst{PrescribedGradient}}{\field{gradient}{rm}} + \recentry{}{\optField{cCoords}{ra}} \end{record} -Represents an abstraction for element side, which holds some unknowns. - -\item PFEMParticle \label{pfemparticles} -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{PFEMParticle}}{\field{coords}{ra}} -\end{record} -Represent the particle used in PFEM analysis. +Prescribes $ v_i = d_{ij}(x_j-\bar{x}_j) $ or $ s = d_{1j}(x_j - \bar{x}_j) $ +where $ v_i $ are primary unknowns, $x_j$ is the coordinate of the node, $\bar x$ is \param{cCoords} and $d$ is \param{gradient}. +The parameter \param{cCoords} defaults to zero. +This is typical boundary condition in multiscale analysis where $ d = \partial_x s$ +would a macroscopic gradient at the integration point, i.e. this is a boundary condition for prolongation. +It is also convenient to use when one wants to test a arbitrary specimen for shear. -\item InteractionPFEMParticle \label{interactionparticle} +\item Mixed prescribed gradient / pressure boundary condition (Active type) \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{InteractionPFEMParticle}}{\field{coords}{ra}} - \recentry{}{\field{bc}{ia}} - \recentry{}{\field{coupledNode}{in}} + \recentry{\entKeywordInst{MixedGradientPressure*}}{\field{devGradient}{ra}} + \recentry{}{\field{pressure}{rn}} + \recentry{}{\optField{cCoord}{ra}} \end{record} -Represent a special particle used in the PFEM-part of the FluidStructureProblem. The particle is -attached to \param{coupledNode} from the structural counter part. InteractionBoundaryCondition~\ref{interactionbc} must be prescribed under \param{bc} to access the velocities from solid nodes. -\end{itemize} +All boundary conditions of ensures that the deviatoric gradient and pressure is at least weakly fullfilled on the prescribed domain. They are used for computational homogenization of incompressible flow or elasticity problems. -\subsection{Element records} -\label{_ElementsRecords} -These records specify a description of particular elements. The -general format is following: +\item Mixed prescribed gradient / pressure boundary condition (Weakly periodic type) -\noindent -\begin{record} - \recentry{\entKeyword{ElementType}}{\componentNum} - \recentry{}{\field{mat}{in} \field{crossSect}{in} \field{nodes}{ia}} - \recentry{}{\optField{bodyLoads}{ia} \optField{boundaryLoads}{ia}} - \recentry{}{\optField{activityltf}{in} \optField{lcs}{ra}} - \recentry{}{\PoptField{partitions}{ia} \PoptFieldnotype{remote}} +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{MixedGradientPressureWeaklyPeriodic}}{\field{order}{rn}} \end{record} -The order of element records is optional, the element number is determined by \componentNum\ parameter. -The numbering of individual elements is arbitrary, it could be even non-continuous. In this context, one could think of element number as a label that is assigned to individual elements and by which the element is referenced. -\Pmode{In parallel mode, the label represents a global id across all partitions.} +Prescribes a periodic constant (unknown) stress tensor along the specified boundaries. For \param{order} set to 1, one obtains the same results as the Neumann boundary condition. + -Element -material is described by parameter \param{mat}, which contains corresponding -material record number. Element cross -section is determined by cross section with \param{crossSect} -record number. Element dof managers (nodes, sides, etc.) defining element geometry are specified using -\param{nodes} array. +\item Mixed prescribed gradient / pressure boundary condition (Neumann type) -Body load acting on element is specified using \param{bodyLoads} array. Components -of this array are corresponding load record numbers. The loads should -have the proper type (body load type), otherwise error will be generated. +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{MixedGradientPressureNeumann}}{} +\end{record} -Boundary load acting on element boundary is specified using -\param{boundaryLoads} array. The format of this array is -\begin{displaymath} -2\cdot size \; lnum(1)~id(1)~\dots~lnum(size)~id(size), -\end{displaymath} -where $size$ is total number of loadings applied to element, -$lnum(i)$ is the applied load number, and $id(i)$ -is the corresponding entity number, to which the load is applied (for example -a side or a surface number). The entity numbering is element dependent and -is described in element specific sections. The applied loads must be -of proper type (boundary load type), otherwise error is generated. +Prescribes a constant (unknown) deviatoric stress tensor along the specified boundaries. +Additional unknowns appears, $\tens{\sigma}_\dev$, which is handled by the boundary condition itself (no control from the input file). +The input devGradient is weakly fulfilled (homogenized over the elementsides). As with the the Dirichlet type, the volumetric gradient is free. +This is useful in multiscale computations of RVE's that experience incompressible behavior, typically fluid problems. In that case, the element sides should cover the entire RVE boundary. +It is also convenient to use when one wants to test a arbitrary specimen for shear, with a free volumetric part (in which case the pressure is set to zero). +Symmetry is not assumed, so rigid body rotations are removed, but translations need to be prescribed separately. -The support for element insertion and removal during the analysis is provided. One can specify optional time function (identified by its id using \param{activityltf} parameter). The nonzero value of this time function indicates, whether the element is active (nonzero value, the default) or inactive (zero value) at particulat solution step. Tested for structural and transport elements. This feature allows considering temperature evolution of layered casting of concrete, where certain layers needs to be inactive before they are cast. See a corresponding example in oofem -tests how to enforce hydrating material model, boundary conditions and element activity acting concurrently. +\item Mixed prescribed gradient / pressure boundary condition (Dirichlet type) -Orientation of local coordinates can be specified using \param{lcs} array. This array contains six numbers, -where the first three numbers represent a directional vector of local -x-axis, and the next three numbers represent a directional vector of local -y-axis. The local z-axis is determined using the vector product. The \param{lcs} array on the element is particularly useful for modeling of orthotropic materials which follow the element orientation. On a beam or truss element, the \param{lcs} array has no effect and the 1D element orientation is aligned with the global $xx$ component. +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{MixedGradientPressureDirichlet}}{} +\end{record} -\Pmode{ -The \param{remote} forces the element to be remote element. Remote -element does not contribute to local partition governing equation. -They are introduced in order to implement band of elements involved -in computation of nonlocal variables (see fig. \ref{nodecut-nlm} illustrating -this approach for node-cut partitioning). They role is to provide -local mirror of corresponding remote partition element integration point values which undergo -nonlocal averaging on local partition. -%This mirroring will lead to -%minimized communication pattern when exchanging remote element data, -%because values are transferred only once, instead of fine grain -%communication when each local element possibly requests its remote -%data over network. -If not used, element is assumed to be local partition element. -When \param{remote} is used, the \param{partitions} parameter should -contain remote partition number, where -corresponding element is local (this array should have size equal to one). -} +Prescribes $ v_i = d_{\dev,ij}(x_j-\bar{x}_j) + d_\vol(x_i-\bar{x}_i)$, and a pressure $p$. +where $ v_i $ are primary unknowns, $x_j$ is the coordinate of the node, $\bar x$ is \param{cCoords} and $d_\dev$ is \param{devGradient}. +The parameter \param{cCoords} defaults to zero. +An additional unknown appears, $d_\vol$, which is handled by the boundary condition itself (no control from the input file). +This unknown is in a way related to the applied pressure. +This is useful in multiscale computations of RVE's that experience incompressible behavior, typically fluid problems. +It is also convenient to use when one wants to test a arbitrary specimen for shear, with a free volumetric part (in which case the pressure is set to zero). -Available material models, their outline and -corresponding parameters are described in separate \textbf{Element Library Manual.} +\item Nodal fluxes (loads) -\subsection{Set records} -\label{_SetRecords} +\noindent +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{NodalLoad}}{\field{components}{ra}} \recentry{}{\optField{cstype}{in}} +\end{record} -Sets specify regions of the geometry as a combination of volumes, surfaces, edges, and nodes. -The main usage of sets are to connect regions of elements to a given cross section or apply a boundary condition, though sets can be used for many other things as well. +Concentrated nodal load. The components of nodal load vector +are given by \param{components} parameter. The size of this vector +corresponds to a total number of nodal DOFs, and i-th value +corresponds to i-th DOF in associated dof manager. The load can be defined in global coordinate system (\param{cstype} = +0) or in entity - specific local coordinate system +(\param{cstype} = 1, default). +\item \mbox{} +\noindent \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{Set}}{\componentNum} - \recentry{}{\optField{elements}{ia} \optField{elementranges}{rl} \optional{allElements}} - \recentry{}{\optField{nodes}{ia} \optField{noderanges}{rl} \optional{allNodes}} - \recentry{}{\optField{elementboundaries}{ia} \optField{elementedges}{ia}} + \recentry{\entKeywordInst{PrescribedTractionPressureBC}}{} \end{record} -Volumes (elements) and nodes can be specified using either a list, \param{elements}, \param{nodes}, or with a range list \param{elementranges}, \param{noderanges}. -Edges \param{elementedges}, and surfaces \param{elementboundaries}, are specified in a interleaved list, every other number specifying the element, and edge/surface number (the total length of the list being twice the number of surfaces/edges). -The internal numbering of edges/surfaces is available in the \textbf{Element Library Manual}. +Represents pressure boundary condition (of Dirichlet type) due to +prescribed tractions. +In CBS algorithm formulation the prescribed traction +boundary condition leads indirectly to pressure boundary condition in +corresponding nodes. This boundary condition implements this pressure +bc. The value of bc is determined from applied tractions, that should be specified on element edges/surfaces using +suitable boundary loads. -Note that edge loads (singular loads given in ``newton per length'' (or equivalent), should be applied to \param{elementedges}, surface loads ``newton per area'' on \param{elementboundaries}, and bulk loads ``newton per volume'' on \param{elements}. +\item Linear constraint boundary condition -Example 1: A deadweight (gravity) load would be applied to the \param{elements} in a set, while a distributed line load would be applied to the midline ``edge'' of the beam element, thus should be applied to a \param{elementedges} set. In the latter case, the midline of the beam is defined as the first (and only) ``edge'' of the beam. +\noindent +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{LinearConstraintBC}}{\field{weights}{ra}} + \recentry{}{\optField{weightsLtf}{ia}} + \recentry{}{\field{dofmans}{in}} \recentry{}{\field{dofs}{in}} + \recentry{}{\field{rhs}{rn}} \recentry{}{\optField{rhsLtf}{in}} + \recentry{}{\field{lhstype}{ia}} \recentry{}{\field{rhsType}{ia}} +\end{record} -Example 2: Axisymmetric structural element analysis: A deadweight load would be applied to \param{elements} in a set. A external pressure would be defined as a surface load an be applied to the \param{elementboundaries} in a set. The element integrates the load (analytically) around the axis, so the load would still count as a surface load. +This boundary condition implements a linear constraint in the form $\sum_i w_ir_i = c$, +where $r_i$ are unknowns related to DOFs determined by \param{dofmans} and \param{dofs}, the weights are determined by \param{weights} and \param{weightsLtf}. The constant is determined by \param{rhs} and \param{rhsLtf} parameters. This boundary condition is introduced as additional stationary condition using Lagrange multiplier, which is an additional degree of freedom introduced by this boundary condition. +The individual DOFs are determined using dof manager numbers (\param{dofmans} array) and corresponding DOF indices (\param{dofs}). The weights corresponding to participating DOFs are specified using \param{weights} array. The weights are multiplied by value returned by load time function, associated to individual weight using optional \param{weightsLtf} array. By default, all weights are set to 1. The constant $c$ is determined by \param{rhs} parameter and it is multiplied by the value of load time function, specified using \param{rhsLtf} parameter, or by 1 by default. The characteristic component, to which this boundary condition contributes must be identified using \param{lhstype} and \param{rhsType} parameters, values of which are corresponding to CharType enum. The left hand side contribution is assembled into terms identified by \param{lhstype}. The rhs contribution is assembled into the term identified by \param{rhsType} parameter. Note, that multiple values are allowed, this allows to select all variants of stifness matrix, for example. Note, that the size of \param{dofmans}, \param{dofs}, \param{weights}, \param{weightsLtf} arrays should be equal. -\subsection{Cross section records} -\label{_CrossSectionRecords} -These records specify a cross section model descriptions. The general format is -following: +\item InteractionBoundaryCondition \label{interactionbc} +\noindent \begin{record}[0.9\textwidth] - \recentry{\entKeyword{CrossSectType}}{\componentNum} + \recentry{\entKeywordInst{InteractionBoundaryCondition}}{} \end{record} -The order of particular cross section records is optional, cross section model number is determined by \componentNum\ parameter. -The numbering should start from one and should end at n, where n is the number of records. +Is a special boundary condition prescribed on InteractionPFEMParticles~\ref{interactionparticle} in the PFEM part of the FluidStructureProblem. This sort of particles is regarded as it would have prescribed velocities, but the values change dynamically, as the solid part deforms. The velocities are obtained from coupled structural nodes. -The crossSectType keyword can be one from following possibilities +\end{itemize} +\paragraph{Body loads} \begin{itemize} -\item -Integral cross section with constant properties\\ +\item Volume flux (load) + +\noindent \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{SimpleCS}}{\optField{thick}{rn} \optField{width}{rn} \optField{area}{rn}} - \recentry{}{\optField{iy}{rn} \optField{iz}{rn} \optField{ik}{rn}} - \recentry{}{\optField{shearareay}{rn} \optField{shearareaz}{rn} \field{beamshearcoeff}{rn}} + \recentry{\entKeywordInst{DeadWeight}}{\field{components}{ra}} +\end{record}\\ +Represents dead weight loading applied on element volume (for +structural elements). For transport problems, it represents the +internal source, i.e. the rate of (heat) generated per unit volume. +The magnitude of load for specific i-th DOF is computed as product of material density, +corresponding volume and i-th member of \param{components} array. +\item Structural temperature load + +\noindent +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{StructTemperatureLoad}~}{\field{components}{ra}} \end{record} -Represents integral type of cross section model. In current -implementation, such cross section is described using cross section -thick (\param{thickVal}) and width (\param{widthVal}). For some -problems (for example 3d), the corresponding volume and cross section dimensions are -determined using element geometry, and then you can omit some (or all) parameters (refer to documentation of individual elements for required cross section properties). Parameter \param{area} allows to set cross section area, parameters \param{iz}, \param{iz}, and \param{ik} represent -inertia moment along y and z axis and torsion inertia moment. Parameter \param{beamshearcoeff} allows to set shear correction factor, or equivalent -shear areas (\param{shearareay} and \param{shearareaz} parameters) can be provided. -These cross section properties are assumed to be defined in local coordinate system of element.\\ -\item -Integral cross section with variable properties\\ +Represents temperature loading imposed to some elements. The members of +\param{components} array represent the change of temperature (or change +of temperature gradient) corresponding to +specific element strain components. See element library manual for details. + +\item Structural eigenstrain load + +\noindent \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{VariableCS}}{\optField{thick}{expr} \optField{width}{expr} \optField{area}{expr}} - \recentry{}{\optField{iy}{expr} \optField{iz}{expr} \optField{ik}{expr}} - \recentry{}{\optField{shearareay}{expr} \optField{shearareaz}{expr} } + \recentry{\entKeywordInst{StructEigenstrainLoad}~}{\field{components}{ra}} \end{record} -Represents integral type of cross section model, where individual cross section parameters can be expressed as an arbitrary function of global coordinates x,y,z. Similar to SimpleCS, for some problems (for example 3d), the corresponding volume and cross section dimensions are -determined using element geometry, then you can omit many (or some) parameters (refer to documentation of individual elements for required cross section properties). -Parameter \param{area} allows to set cross section area, parameters \param{iz}, \param{iz}, and \param{ik} represent -inertia moment along y and z axis and torsion inertia moment. Parameters (\param{shearareay} and \param{shearareaz} determine shear area, which is required by beam and plate elements. All cross section properties are assumed to be defined in local coordinate system of element.\\ +Prescribes eigenstrain (or stress-free strain) to a structural element. The array of \param{components} is defined in the global coordinate system. The number of components corresponds to a material mode, e.g. plane stress has three components and 3D six. Periodic boundary conditions can be imposed using eigenstrains and master-slave nodes. Consider decomposition of strain into average and fluctuating part +\begin{equation} +\tens{\strain}(\vect{x}) = \langle \tens{\strain} \rangle + \tens{\strain}^*(\vect{x}) +\end{equation} +where $\langle \tens{\strain} \rangle$ can be imposed as eigenstrain over the domain and the solution gives the fluctuating part $\tens{\strain}^*(\vect{x})$. Master-slave nodes have to interconnect opposing boundary nodes of a unit cell. + + +\end{itemize} +\paragraph{Boundary loads} +\begin{itemize} +\item Constant edge fluxes (load) -\item -Layered cross section \\ \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{LayeredCS}}{\field{nLayers}{in}} - \recentry{}{\field{LayerMaterials}{ia}} - \recentry{}{\field{Thicks}{ra} \field{Widths}{ra}} - \recentry{}{\field{mid\-Surf}{rn}} + \recentry{\entKeywordInst{ConstantEdgeLoad}}{} + \recentry{}{\field{loadType}{in}} + \recentry{}{\field{components}{ra}} + \recentry{}{\optField{dofexcludemask}{ia}} + \recentry{}{\optField{csType}{in}} + \recentry{}{\optField{properties}{dc}} + \recentry{}{\optField{propertytf}{dc}} \end{record} -Represents the layered cross section model, based on -geometrical hypothesis, that cross sections remain planar after -deformation. Number of layers is -determined by \param{nLayers} parameter. Materials for each -layer are specified by \param{LayerMaterials} array. For each layer is -necessary to input -geometrical characteristic, thick - using \param{Thicks} array, and -width - using -\param{Widths} array. Position of mid surface is determined by its -distance from -bottom of cross section using \param{mid\-Surf} parameter (normal and -momentum forces are then computed with regard to it's position). -Elements using this cross section model must implement layered cross -section extension. For information see element library manual. -\item -Fibered cross section\\ +\item Constant surface fluxes (load) + \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{FiberedCS}}{\field{nfibers}{in} \field{fibermaterials}{ia}} - \recentry{}{\field{thicks}{ra} \field{widths}{ra} \field{thick}{rn} \field{width}{rn}} - \recentry{}{\field{fiberycentrecoords}{ra} \field{fiberzcentrecoords}{ra}} + \recentry{\entKeywordInst{ConstantSurfaceLoad}}{} + \recentry{}{\field{loadType}{in}} + \recentry{}{\field{components}{ra}} + \recentry{}{\optField{dofexcludemask}{ia}} + \recentry{}{\optField{csType}{in}} + \recentry{}{\optField{properties}{dc}} + \recentry{}{\optField{propertytf}{dc}} +\end{record} + +Represent constant edge/surface loads or boundary conditions. +Parameter \param{loadType} distinguishes the type of boundary condition. Supported values are specified in bctype.h: +\begin{itemize} +\item \param{loadType} = 2 prescribed flux input (Neumann boundary condition), +\item \param{loadType} = 3 uniform distributed load or the convection (Newton) BC. Parameter \param{components} contains the +environmental values (temperature of the environment) corresponding to +element unknowns, and \param{properties} dictionary should contain +value of transfer (convection) coefficient (assumed to be a constant) under the key 'a', +\item \param{loadType} = 7 specifies radiative boundary condition (Stefan-Boltzmann). It requires to specify emmisivity $\varepsilon\in\langle 0,1\rangle$, the \param{components} array contains the environmental values (temperature of the environment). Default units are Celsius. Optional parameter \param{temperOffset} = 0 can be used to calculate in Kelvin. +\end{itemize} + +If the boundary condition corresponds to distributed force load, the \param{components} array contains components of distributed load corresponding to element unknowns. +The load is specified for all DOFs of object to which is associated. +For some types of boundary conditions the zero value of load does not mean that the load is not applied (Newton's type of bc, for example). +Then some mask, which allows to exclude specific dofs is necessary. +The \param{dofexcludemask} parameter is introduced to alow this. +It should have the same size as \param{components} array, and by +default is filled with zeroes. If some value of dofExcludeMask is set +to nonzero, then the corresponding componentArray +is set to zero and load is not applied for this DOF. +If the boundary condition corresponds to prescribed flux input, then +the \param{components} array contains the components of prescribed +input flux corresponding to element unknowns. + +The properties can vary in time. Each property can have associated time function which determines its time variation. The time functions are set up using optional \param{propertytf} dictionary, containing for selected properties the corresponding time function number. The time function must be registered under the same key as in \param{properties} dictionary. The property value is then computed by product of property value (determined by \param{properties}) and corresponding time function evaluated at given time. If no time function provided for particula property, a unit constant function is assumed. + +The load can be defined in global coordinate system (\param{csType} = +0, default) or in entity - specific local coordinate system +(\param{csType} = 1). +\item Linear edge flux (load) + +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{LinearEdgeLoad}}{} + \recentry{}{\field{loadType}{in}} + \recentry{}{\field{components}{ra}} + \recentry{}{\optField{dofexcludemask}{ia}} + \recentry{}{\optField{csType}{in}} \end{record} -Cross section represented as a set of rectangular fibers. It is based on -geometrical hypothesis, that cross sections remain planar after -deformation (3d generalization of layered approach for beams). -Paramater \param{nfibers} determines the number of fibers that together form the overall cross section. -The model requires to specify a material model corresponding to particular fiber using \param{fibermaterials} array. This array should contain for each fibre corresponding material model number (the material model specified on element level has no meaning in this particular case). -\textbf{The geometry of cross section is determined from fiber dimensions and fiber positions, all input in local coordinate system of the beam (yz plane).} The thick and width of each fiber are determined using \param{thicks} and \param{widths} arrays. The overall thick and width are specified using parameters \param{thick} and \param{width}. Positions of particular fibers are specified by providing coordinates of center of each fiber using \param{fiberycentrecoords} array for y-coordinates and \param{fiberzcentrecoords} array for z-coordinates. -%%\item \entKeywordInst{HeatCS} \field{thick}{rn} -%%\field{width}{rn}\\ -%%Represents cross section abstraction for heat transfer problems. -%%The input parameters are: thick - determined using \param{thick} parameter -%%and width - determined using \param{width} parameter of cross section. -\item -Warping cross section \\ +Represents linear edge load. The meanings of parameters \param{csType} and \param{loadType} are the same as for +\entKeywordInst{ConstantEdgeLoad}. +In \param{components} array are stored load components for corresponding unknowns at the +beginning of edge, followed by values valid for end of edge. +The load can be defined in global coordinate system (\param{csType} = 0, default) or in entity - specific local coordinate system +(\param{csType} = 1). +\item InteractionLoad + \begin{record}[0.9\textwidth] -\recentry{\entKeywordInst{WarpingCS}}{\field{WarpingNode}{in}} + \recentry{\entKeywordInst{InteractionLoad}}{\field{ndofs}{in}} + \recentry{}{\field{loadType}{in}} + \recentry{}{\field{Components}{ra}} + \recentry{}{\optField{csType}{in}} + \recentry{}{\field{coupledparticles}{ia}} \end{record} -Represents the cross section for Free warping analysis, see section \ref{FreeWarping}. The \param{WarpingNode} parametr defines the number of external node with prescribed boundary condition which corresponds to the relative twist of warping cross section. + +Represents a fluid pressure induced load in the solid part of the FluidStructureProblem. +The meanings of parameters \param{ndofs}, +\param{csType}, and \param{loadType} are the same as for +\entKeywordInst{LinearEdgeLoad}. In \param{Components} +array are stored load components for corresponding unknowns at the +beginning of edge (\param{ndofs} values), followed by values valid for +end of edge (\param{ndofs} values). The load should be defined in global +coordinate system (\param{csType} = 0) as it acts in normal direction of the edge. +Array \param{coupledparticles} assign PFEMParticles from the fluid part of the problem +providing fluid pressure. \end{itemize} -\subsection{Material type records} -\label{_MaterialTypeRecords} -These records specify a material model description. The general format is + +\section{Initial conditions} +\label{_InitialConditions} +These records specify description of initial conditions. The general format is following: \noindent \begin{record} - \recentry{\entKeyword{MaterialType}}{\componentNum\ \field{d}{rn}} + \recentry{\entKeywordInst{InitialCondition}}{\componentNum} + \recentry{}{\field{conditions}{dc}} \end{record} - -The order of particular material records is optional, the material number is determined by \componentNum\ parameter. +The order of particular records is optional, load, boundary or initial condition number is determined by \componentNum\ parameter. The numbering should start from one and should end at n, where n is the number of records. -Material density is compulsory parameter and it's value is given by -\param{d} parameter. - -Available material models, their outline and -corresponding parameters are described in separate \textbf{Material Library Manual}. - -\subsection{Nonlocal barrier records} -\label{_NonlocalBarrierRecords} -Nonlocal material models of integral type are based on replacement of -certain suitable local quantity in local constitutive law by their -nonlocal counterparts, that are obtained as weighted average over -some characteristic volume. The weighted average is computed as a sum -of a remote value multiplied by weight function value. The weight -function typically depend on a distance between remote and receiver -points and decreases with increasing distance. In some cases, it is -necessary to disregard mutual interaction between some points (for -example if they are on the opposite sides of a thin notch, which -prevents the nonlocal interactions to take place). The barriers are -the way how to introduce these constrains. The barrier represent a -curve (in 2D) or surface (in 3D). When the line connecting receiver and -remote point intersects a barrier, the barriers is activated and the -corresponding interaction is not taken into account. - -Currently, the supported barrier types are following: -\begin{itemize} -\item - Polyline barrier +Initial parameters are listed in \param{conditions} dictionary using keys followed by their initial values. +Now 'v' key represents velocity and 'a' key represents acceleration. -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{polylinebarrier}}{\componentNum\ \field{vertexnodes}{ia}} - \recentry{}{\optField{xcoordindx}{in} \optField{ycoordindx}{in}} -\end{record} -This represents a polyline barrier for 2D problems. Barrier is a -polyline, defined as a sequence of nodes representing vertices. -The vertices are specified using parameter \param{vertexnodes} array, -which contains the node numbers. The optional parameters -\param{xcoordindx} and \param{ycoordindx} allow to select the plane -(xy, yz, or xz), where the barrier is defined. The \param{xcoordindx} is the -first coordinate index, \param{ycoordindx} is the second. The default values -are 1 for \param{xcoordindx} and 2 for \param{ycoordindx}, representing barrier in xy plane. -\item Symmetry barrier -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{symmetrybarrier}}{\componentNum\ \field{origin}{ra}} - \recentry{}{\field{normals}{ra} \field{activemask}{ia}} -\end{record} -Implementation of symmetry barier, that allows to specify up to three planes (orthogonal ones) of symmetry. -This barrier allows to model the symmetry of the averaged field on the boundary without -the need of modeling the other part of structure across the plane of symmetry. -It is based on modifying the integration weights of source points to take into account -the symmetry. -The potential symmetry planes are determined by specifying orthogonal right-handed coordinate system, -where axes represent the normals of corresponding symmetry planes. -Parameter \param{origin} determines the origin of the coordinate system, the \param{normals} array -contains three components of x-axis direction vector, -followed by three components of y-axis direction vector (expressed in global coordinate system). -The z-axis is determined from the orthogonality conditions. -Parameter \param{activemask} allows to specify active symmetry planes; i-th nonzero value activates the symmetry barrier for plane -with normal determined by corresponding coordinate axis (x=1, y=2, z=3). -\end{itemize} -\subsection{Load and boundary conditions} -\label{_LoadBoundaryInitialConditions} -These records specify description of boundary conditions. The general format is +\section{Time functions records} +\label{_TimeFunctionsRecords} +These records specify description of time functions, which generally describe +time variation of components during solution. The general format is following: \noindent \begin{record} - \recentry{\entKeyword{EntType}}{\componentNum} - \recentry{}{\field{loadTimeFunction}{in}} - \recentry{}{\optField{valType}{in} \optField{dofs}{ia}} - \recentry{}{\optField{is\-Impo\-sed\-Ti\-me\-Fun\-ction}{in}} + \recentry{\entKeyword{TimeFunctType}}{\componentNum} + \recentry{}{\optField{initialValue}{rn}} \end{record} -The order of particular records is optional, boundary condition number is determined by \componentNum\ parameter. -The numbering should start from one and should end at n, where n is the number of records. -Time function value (given by \param{loadTimeFunction} parameter) is a multiplier, using which -each component (value of loading or value of boundary condition) -describes its time variation. -The optional parameter \param{valType} allows to determine the -physical meaning of bc value, which is sometimes required. Supported -values are (1 - temperature, 2 - force/traction, -3 - pressure, 4 - humudity, 5 - velocity, 6 - displacement). -Another optional parameter \param{dofs} is used to determine which dofs the boundary condition should act -upon. It is not relevant for all BCs.. - -The nonzero value of \param{isImposedTimeFunction} time function -indicates that given boundary condition is active, zero value -indicates not active boundary condition in given time (the bc does not -exist). By default, the boundary condition applies at any time. +The order of these records is optional, time function number is determined by \componentNum\ parameter. +The \param{initialValue} parameter allows to control the way, how increment of receiver is evaluated for the first solution step. +This first solution step increment is evaluated as the difference of value of receiver at this first step and given initial value (which is by default set to zero). +The increments of receiver in subsequent steps are computed as a difference between receiver evaluated at given solution step and in previous step. +The numbering should start from one and should end at n, where n is the number of records. -Currently, EntType keyword can be one from +Currently, TimeFunctType keyword can be one from \begin{itemize} -\item Dirichlet boundary condition +\item Constant function \noindent \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{BoundaryCondition}}{\field{prescribedvalue}{rn}} - \recentry{}{\optField{d}{rn}} + \recentry{\entKeywordInst{ConstantFunction}}{\field{f(t)}{rn}} \end{record} -Represents boundary condition. -Prescribed value is specified using \param{prescribedvalue} parameter. -The physical meaning of value is fully determined by corresponding DOF. -Optionally, the prescribed value can be specified using \param{d} -parameter. It is introduced for compatibility reasons. If -\param{prescribedvalue} is specified, then \param{d} is ignored. +Represents the constant time function, with value \param{f(t)}. -\item Prescribed gradient boundary condition (Dirichlet type) +\item Peak function \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{PrescribedGradient}}{\field{gradient}{rm}} - \recentry{}{\optField{cCoords}{ra}} + \recentry{\entKeywordInst{PeakFunction}}{\field{t}{rn}} + \recentry{}{\field{f(t)}{rn}} \end{record} -Prescribes $ v_i = d_{ij}(x_j-\bar{x}_j) $ or $ s = d_{1j}(x_j - \bar{x}_j) $ -where $ v_i $ are primary unknowns, $x_j$ is the coordinate of the node, $\bar x$ is \param{cCoords} and $d$ is \param{gradient}. -The parameter \param{cCoords} defaults to zero. -This is typical boundary condition in multiscale analysis where $ d = \partial_x s$ -would a macroscopic gradient at the integration point, i.e. this is a boundary condition for prolongation. -It is also convenient to use when one wants to test a arbitrary specimen for shear. +Represents peak time function. If time is equal to \param{t} +value, then the value of time function is given by \param{f(t)} value, +otherwise zero value is returned. -\item Mixed prescribed gradient / pressure boundary condition (Active type) +\item Piecewise function \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{MixedGradientPressure*}}{\field{devGradient}{ra}} - \recentry{}{\field{pressure}{rn}} - \recentry{}{\optField{cCoord}{ra}} + \recentry{\entKeywordInst{PiecewiseLinFunction}}{[\field{nPoints}{in} {\field{t}{ra} \field{f(t)}{ra}}] [ \field{datafile}{"string"}]} \end{record} -All boundary conditions of ensures that the deviatoric gradient and pressure is at least weakly fullfilled on the prescribed domain. They are used for computational homogenization of incompressible flow or elasticity problems. - -\item Mixed prescribed gradient / pressure boundary condition (Weakly periodic type) - -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{MixedGradientPressureWeaklyPeriodic}}{\field{order}{rn}} -\end{record} +Represents the piecewise time function. The particular time values in +\param{t} array should be sorted according to time scale. Corresponding time +function values are in \param{f(t)} array. Value for time, which +is not present in \param{t} is computed using liner interpolation scheme. +Number of time-value pairs is in \param{nPoints} parameter. -Prescribes a periodic constant (unknown) stress tensor along the specified boundaries. For \param{order} set to 1, one obtains the same results as the Neumann boundary condition. +The second alternative allows reading input data from an external ASCII file. A hash commented line (\#) is +skipped during reading. File name should be eclosed with " ". -\item Mixed prescribed gradient / pressure boundary condition (Neumann type) +\item Heaviside-like time function \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{MixedGradientPressureNeumann}}{} + \recentry{\entKeywordInst{HeavisideLTF}}{\field{origin}{rn}} + \recentry{}{\field{value}{rn}} \end{record} -Prescribes a constant (unknown) deviatoric stress tensor along the specified boundaries. -Additional unknowns appears, $\tens{\sigma}_\dev$, which is handled by the boundary condition itself (no control from the input file). -The input devGradient is weakly fulfilled (homogenized over the elementsides). As with the the Dirichlet type, the volumetric gradient is free. -This is useful in multiscale computations of RVE's that experience incompressible behavior, typically fluid problems. In that case, the element sides should cover the entire RVE boundary. -It is also convenient to use when one wants to test a arbitrary specimen for shear, with a free volumetric part (in which case the pressure is set to zero). -Symmetry is not assumed, so rigid body rotations are removed, but translations need to be prescribed separately. - -\item Mixed prescribed gradient / pressure boundary condition (Dirichlet type) +Up to time, given by +parameter \param{origin}, the value of time function is zero. If time +greater than \param{origin} parameter, the value is +equal to parameter \param{value} value. +\item User defined \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{MixedGradientPressureDirichlet}}{} + \recentry{\entKeywordInst{UsrDefLTF}}{\field{f(t)}{expr}} + \recentry{}{\optField{dfdt(t)}{expr}} + \recentry{}{\optField{d2fdt2(t)}{expr}} \end{record} -Prescribes $ v_i = d_{\dev,ij}(x_j-\bar{x}_j) + d_\vol(x_i-\bar{x}_i)$, and a pressure $p$. -where $ v_i $ are primary unknowns, $x_j$ is the coordinate of the node, $\bar x$ is \param{cCoords} and $d_\dev$ is \param{devGradient}. -The parameter \param{cCoords} defaults to zero. -An additional unknown appears, $d_\vol$, which is handled by the boundary condition itself (no control from the input file). -This unknown is in a way related to the applied pressure. -This is useful in multiscale computations of RVE's that experience incompressible behavior, typically fluid problems. -It is also convenient to use when one wants to test a arbitrary specimen for shear, with a free volumetric part (in which case the pressure is set to zero). - +Represents user defined time function. +The expressions can depend on ``t'' parameter, for which actual time will be substituted and +expression evaluated. The function is defined using \param{f(t)} parameter, and optionally, its first and second time derivatives using \param{dfdt(t)} and \param{d2fdt2(t)} parameters. +The first and second derivatives may be required, this depend on type of analysis. +Very general, but relatively slow. +\end{itemize} -\item Nodal fluxes (loads) +\section{Xfem manager record and associated records} +\label{_XFEMManagerRecords} +This record specifies the number of enrichment items and simulation options +common for all enrichment items. Functions used for enrichment (e.g. Heaviside, +abs or branch functions) are not specified here, they are specified for each +enrichment item separately. The same holds for the geometrical representation of +each enrichment item (e.g. a polygon line or a circle). Currently, OOFEM +supports XFEM simulations of cracks and material interfaces in 2D. The input +format for the XFEM manager is:\\ +\begin{record} + \recentry{\entKeywordInst{XfemManager}}{\field{numberofenrichmentitems}{in}} + \recentry{}{\field{numberofgppertri}{in}} + \recentry{}{\field{debugvtk}{in}} + \recentry{}{\field{vtkexport}{in}} + \recentry{}{\field{exportfields}{in}} +\end{record} +where \param{numberofenrichmentitems} represents number of enrichment items, +\param{numberofgppertri} denotes the number of Gauss points in each subtriangle +of a cut element (default 12) and \param{debugvtk} controls if additional debug +vtk files should be written (1 activates the option, 0 is default). +The specification of an enrichment item may consist of several lines, see e.g. +the test \textit{sm/xFemCrackValBranch.in}. First, the enrichment item type is +specified together with some optional parameters according to\\ \noindent -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{NodalLoad}}{\field{components}{ra}} \recentry{}{\optField{cstype}{in}} +\begin{record} + \recentry{\entKeyword{EntType}}{\componentNum} + \recentry{}{\field{enrichmentfront}{in}} + \recentry{}{\field{propagationlaw}{in}} \end{record} +where \param{enrichmentfront} specifies an enrichment front (we may for example +employ branch functions at a crack tip and Heaviside enrichment along the rest +of the crack, hence the ``front'' of the enrichment is treated separately) and +\param{propagationlaw} specifies a rule for crack propagation (this feature is +still highly experimental though). Specification of an \param{enrichmentfront} +and a \param{propagationlaw} is optional. -Concentrated nodal load. The components of nodal load vector -are given by \param{components} parameter. The size of this vector -corresponds to a total number of nodal DOFs, and i-th value -corresponds to i-th DOF in associated dof manager. The load can be defined in global coordinate system (\param{cstype} = -0) or in entity - specific local coordinate system -(\param{cstype} = 1, default). -\item \mbox{} - +The next line specifies the enrichment function to be used:\\ \noindent -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{PrescribedTractionPressureBC}}{} +\begin{record} + \recentry{\entKeyword{EntType}}{\componentNum} \end{record} -Represents pressure boundary condition (of Dirichlet type) due to -prescribed tractions. -In CBS algorithm formulation the prescribed traction -boundary condition leads indirectly to pressure boundary condition in -corresponding nodes. This boundary condition implements this pressure -bc. The value of bc is determined from applied tractions, that should be specified on element edges/surfaces using -suitable boundary loads. +This is followed by a line specifying the geometric description (e.g. a polygon +line or a circle) according to\\ +\noindent +\begin{record} + \recentry{\entKeyword{EntType}}{\componentNum \ extra attributes} +\end{record} +where the number and type of extra attributes to specify will vary depending on the +geometry chosen, e.g. center and radius for a circle or a number of points for a +polygon line. -\item Linear constraint boundary condition +If an enrichment front was specified previously, the type and properties of the +enrichment front are specified on the next line according to\\ +\noindent +\begin{record} + \recentry{\entKeyword{EntType}}{\componentNum \ extra attributes} +\end{record} +If a propagation law was specified previously, it's type and properties are also +specified on a separate line according to\\ \noindent -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{LinearConstraintBC}}{\field{weights}{ra}} - \recentry{}{\optField{weightsLtf}{ia}} - \recentry{}{\field{dofmans}{in}} \recentry{}{\field{dofs}{in}} - \recentry{}{\field{rhs}{rn}} \recentry{}{\optField{rhsLtf}{in}} - \recentry{}{\field{lhstype}{ia}} \recentry{}{\field{rhsType}{ia}} +\begin{record} + \recentry{\entKeyword{EntType}}{\componentNum \ extra attributes} \end{record} -This boundary condition implements a linear constraint in the form $\sum_i w_ir_i = c$, -where $r_i$ are unknowns related to DOFs determined by \param{dofmans} and \param{dofs}, the weights are determined by \param{weights} and \param{weightsLtf}. The constant is determined by \param{rhs} and \param{rhsLtf} parameters. This boundary condition is introduced as additional stationary condition using Lagrange multiplier, which is an additional degree of freedom introduced by this boundary condition. -The individual DOFs are determined using dof manager numbers (\param{dofmans} array) and corresponding DOF indices (\param{dofs}). The weights corresponding to participating DOFs are specified using \param{weights} array. The weights are multiplied by value returned by load time function, associated to individual weight using optional \param{weightsLtf} array. By default, all weights are set to 1. The constant $c$ is determined by \param{rhs} parameter and it is multiplied by the value of load time function, specified using \param{rhsLtf} parameter, or by 1 by default. The characteristic component, to which this boundary condition contributes must be identified using \param{lhstype} and \param{rhsType} parameters, values of which are corresponding to CharType enum. The left hand side contribution is assembled into terms identified by \param{lhstype}. The rhs contribution is assembled into the term identified by \param{rhsType} parameter. Note, that multiple values are allowed, this allows to select all variants of stifness matrix, for example. Note, that the size of \param{dofmans}, \param{dofs}, \param{weights}, \param{weightsLtf} arrays should be equal. +\chapter{Appendix} +\section{Sparse linear solver parameters} +\label{sparselinsolver} +The sparselinsolverparams field has the following general syntax:\\ +\begin{record} + \recentry{\hspace{20mm}}{\optField{lstype$^M$}{in}} + \recentry{}{\optField{smtype}{in}} + \recentry{}{\field{solverParams$^M$}{string}} +\end{record} +where parameter \param{lstype} allows to select the solver for the linear system of +equations. Currently supported values are 0 (default) for a direct solver +(ST\_Direct), 1 for an Iterative Method Library (IML) solver (ST\_IML), +2 for a Spooles direct solver, 3 for Petsc +library family of solvers, and 4 for a DirectSparseSolver (ST\_DSS). +Parameter \param{smtype} allows to select the sparse matrix storage +scheme. The scheme should be compatible with the solver type. +Currently supported values (marked as ``id'') are summarized in table +(\ref{linsolvstoragecompattable}). The 0 value is default and selects +the symmetric skyline (SMT\_Skyline). Possible storage formats +include unsymmetric skyline (SMT\_SkylineU), +compressed column (SMT\_CompCol), dynamically growing compressed +column (SMT\_DynCompCol), symmetric compressed column +(SMT\_SymCompCol), spooles library storage format (SMT\_SpoolesMtrx), +PETSc library matrix representation (SMT\_PetscMtrx, a sparse +serial/parallel matrix in AIJ format), and DSS compatible matrix +representations (SMT\_DSS\_*). +The allowed \param{lstype} and \param{smtype} combinations are +summarized in the table (\ref{linsolvstoragecompattable}), together +with solver parameters related to specific solver. -\item InteractionBoundaryCondition \label{interactionbc} +\begin{table}[ht] +\begin{center} +%%\scalebox{0.50}{ +\begin{tabular}{|l|c|c|c|c|c|c|c|c|} +\hline +Storage format & id & \multicolumn{5}{c|}{Sparse solver, \param{lstype}} \\ +\hline +& \param{smtype} & \tiny{Direct (0)} &\tiny{IML (1)} &\tiny{Spooles (2)}& \tiny{Petsc (3)}& \tiny{DSS (4)}& \tiny{MKLPardiso (6)}& \tiny{SuperLU\_MT (7)}\\ +& & & & & & & \tiny{Pardiso.org(8)}& \\ -\noindent -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{InteractionBoundaryCondition}}{} -\end{record} +\hline +\small{SMT\_Skyline} & 0&+&+& & & & &\\ +\small{SMT\_SkylineU} & 1&+&+& & & & & \\ +\small{SMT\_CompCol} & 2& &+& & & &+&+\\ +\small{SMT\_DynCompCol} & 3& &+& & & & & \\ +\small{SMT\_SymCompCol} & 4& &+& & & & & \\ +\small{SMT\_DynCompRow} & 5& &+& & & & & \\ +\small{SMT\_SpoolesMtrx} & 6& & &+& & & & \\ +\small{SMT\_PetscMtrx } & 7& & & &+& & & \\ +\small{SMT\_DSS\_sym\_LDL} & 8& & & & &+ & &\\ +\small{SMT\_DSS\_sym\_LL} & 9& & & & &+ & &\\ +\small{SMT\_DSS\_unsym\_LU}&10& & & & &+ & &\\ +\hline +\end{tabular} +%%} +\caption{Solver and storage scheme compatibility.} +\label{linsolvstoragecompattable} +\end{center} +\end{table} -Is a special boundary condition prescribed on InteractionPFEMParticles~\ref{interactionparticle} in the PFEM part of the FluidStructureProblem. This sort of particles is regarded as it would have prescribed velocities, but the values change dynamically, as the solid part deforms. The velocities are obtained from coupled structural nodes. +The solver parameters in \param{solverParams} depend on the solver +type and are summarized in table (\ref{sparsesolverparams}). -\end{itemize} -\paragraph{Body loads} -\begin{itemize} -\item Volume flux (load) +\begin{table}[ht] +\begin{center} +\begin{tabular}{|l|l|l|} +\hline +Solver type & id & Solver parameters/notes \\ +\hline +ST\_Direct &0&\\ +ST\_IML &1& \optField{stype}{in} \field{lstol}{rn} \field{lsiter}{in}\field{lsprecond}{in}\\ + & & \optField{precondattributes}{string}\\ + & & Included in OOFEM, requires to compile with USE\_IML\\ +ST\_Spooles &2& \optField{msglvl}{in} \optField{msgfile}{s}\\ + & & http://www.netlib.org/linalg/spooles/spooles.2.2.html\\ +ST\_Petsc &3& See Petsc manual, for details\footnotemark\\ +ST\_DSS &4& Sparse direct solver, included in OOFEM\\ + & & Requires to compile with USE\_DSS\\ +ST\_MKLPardiso&6&Requires Intel MKL Pardiso \\ +ST\_SuperLU\_MT&7&SuperLU for shared memory machines\\ + & &http://crd-legacy.lbl.gov/~xiaoye/SuperLU/\\ +ST\_PardisoProjectOrg&8&Requires Pardiso solver(http://www.pardiso-project.org/)\\ +\hline +\end{tabular} +\caption{Solver parameters.} +\label{sparsesolverparams} +\end{center} +\end{table} +\footnotetext[2]{User can set several run-time options, e.g., + \mbox{-ksp\_type}~$[$cg, gmres, bicg, bcgs$]$ + \mbox{-pc\_type}~$[$jacobi, bjacobi,none,ilu,...$]$ + \mbox{-ksp\_monitor} \mbox{-ksp\_rtol}~$<$rtol$>$ \mbox{-ksp\_view} \mbox{-ksp\_converged\_reason}. + These options will override those that are default (PETSC KSPSetFromOptions() routine is called after any other customization + routines).} +The \param{stype} allows to select particular iterative solver from IML library, currently supported values are 0 (default) for Conjugate-Gradient solver, 1 for GMRES solver. Parameter \param{lstol} represents the maximum value of residual after the +final iteration and the \param{lsiter} is maximum number of iteration for iterative solver. +The \param{precondattributes} parameters contains the optional +preconditioner parameters. +The \param{lsprecond} parameter determines the type of preconditioner to be +used. The possible values of \param{lsprecond} together with supported +storage schemes and their descriptions are summarized in table +(\ref{precondtable}). -\noindent -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{DeadWeight}}{\field{components}{ra}} -\end{record} -Represents dead weight loading applied on element volume (for -structural elements). For transport problems, it represents the -internal source, i.e. the rate of (heat) generated per unit volume. -The magnitude of load for specific i-th DOF is computed as product of material density, -corresponding volume and i-th member of \param{components} array. -\item Structural temperature load +\begin{table}[ht] +\begin{center} +\begin{tabular}{|l|l|l|l|} +\hline +Precond type & id & Compatible storage & Description and parameters \\ +\hline\hline +IML\_VoidPrec &0& all & No preconditioning\\ +\hline +IML\_DiagPrec &1& all & Diagonal preconditioning\\ +\hline +IML\_ILUPrec &2& SMT\_CompCol & Incomplete LU Decomposition\\ + & & SMT\_DynCompCol&with no fill up\\ +\hline +IML\_ILUPrec &3& SMT\_DynCompRow & Incomplete LU (ILUT) with\\ + & & & fillup. \\ + & & & The \param{precondattributes} are:\\ + & & & \optField{droptol}{rn} \optField{partfill}{in}.\\ + & & & \param{droptol} dropping tolerance\\ + & & & \param{partfill} level of fill-up\\ +\hline +IML\_ICPrec &4& SMT\_SymCompCol&Incomplete Cholesky\\ + & & SMT\_CompCol &with no fill up\\ +\hline +\end{tabular} +\caption{Preconditioning summary.} +\label{precondtable} +\end{center} +\end{table} -\noindent -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{StructTemperatureLoad}~}{\field{components}{ra}} +\section{Eigen value solvers} +\label{eigensolverssection} +The eigensolverparams field has the following general syntax:\\ +\begin{record} + \recentry{\hspace{20mm}}{\optField{stype$^M$}{in}} + \recentry{}{\optField{smtype}{in}} + \recentry{}{\field{solverParams$^M$}{string}} \end{record} +where parameter \param{stype} allows to select solver type. Parameter \param{smtype} allows to select sparse matrix storage +scheme. The scheme should be compatible with solver type. Currently supported values of \param{stype} are summarized in table~\ref{eigenvaluesolverparamtable}. -Represents temperature loading imposed to some elements. The members of -\param{components} array represent the change of temperature (or change -of temperature gradient) corresponding to -specific element strain components. See element library manual for details. +\begin{table}[ht] +\begin{center} +%%\scalebox{0.50}{ +\begin{tabular}{|l|l|l|} +\hline +Solver type & stype id & solver parameters \\ +Subspace Iteration & 0 (default) & \\ +Inverse Iteration& 1 & \\ +SLEPc solver& 2 & requires ``smtype 7''\\ +&& see also SLEPc manual \\ +\hline +\end{tabular} +\caption{Eigen Solver parameters.} +\label{eigenvaluesolverparamtable} +\end{center} +\end{table} -\item Structural eigenstrain load + +\section{\Pmode{Dynamic load balancing parameters}} +\label{dynamicloadbalancing} +There are in general two basic factors causing load imbalance between individual subdomains: (i) one comming from application nature, such as switching from linear to nonlinear response in certain regions or local adaptive refinment, and (ii) external factors, caused by resourse realocation, typical for nondedicated cluster environments, where indivudual processors are shared by different applications and users, leading to time variation in allocated processing power. The load balance recovery is achieved by repartitioning of the problem domain and transferring the work (represented typically by finite elements) from one subdomain to another. +This section describes the structure and syntax of parameters related to dynamic load balancing. +The corresponding part of analysis record has the following general syntax:\\ \noindent -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{StructEigenstrainLoad}~}{\field{components}{ra}} +\begin{record} + \recentry{\hspace{20mm}}{\optField{lbflag$^M$}{in}} + \recentry{}{\optField{forcelb1}{in}} + \recentry{}{\optField{wtp}{ia}} + \recentry{}{\optField{lbstep}{in}} + \recentry{}{\optField{relwct}{rn}} + \recentry{}{\optField{abswct}{rn}} + \recentry{}{\optField{minwct}{rn}} \end{record} -Prescribes eigenstrain (or stress-free strain) to a structural element. The array of \param{components} is defined in the global coordinate system. The number of components corresponds to a material mode, e.g. plane stress has three components and 3D six. Periodic boundary conditions can be imposed using eigenstrains and master-slave nodes. Consider decomposition of strain into average and fluctuating part -\begin{equation} -\tens{\strain}(\vect{x}) = \langle \tens{\strain} \rangle + \tens{\strain}^*(\vect{x}) -\end{equation} -where $\langle \tens{\strain} \rangle$ can be imposed as eigenstrain over the domain and the solution gives the fluctuating part $\tens{\strain}^*(\vect{x})$. Master-slave nodes have to interconnect opposing boundary nodes of a unit cell. +where the parameters have following meaning: +\begin{itemize} +\item \param{lbflag}, when set to nonzero value activates the dynamic load balancing. Default value is zero. +\item \param{forcelb1} forces the load rebalancing after the first solution step, when set to nonzero value. +\item \param{wtp} allows to activate optional load balancing plugins. At present, the only supported value is 1, that activates nonlocal plugin, necessary for nonlocal averaging to work properly when dynamic load balancing is active. +\item \param{lbstep} rebalancing, if needed, is performed only every lbstep solution step. +Default value is 1 (recover balance after every step, if necessary). +\item \param{relwcr} sets relative wall-clock imbalance treshold. When achieved relative imbalance between wall clock solution time of individual processors is greater than provided treshold, the rebalancing procedure will be activated. +\item \param{abswct} sets absolute wall-clock imbalance treshold. When achieved absolute imbalance between wall clock solution time of individual processors is greater than provided treshold, the rebalancing procedure will be activated. +\item \param{minwct} minimum absolute imbalance to perform relative imbalance check using \param{relwcr} parameter, otherwise only absolute check is done. Default value is 0. +\end{itemize} +At present, the load balancing support requires ParMETIS module to be configured and compiled. + + +% +\section{Error estimators and indicators} +\label{errorestimators} +The currently supported values of \param{eetype} are in table +\ref{eetypestable}. +\begin{itemize} +\item +EET\_SEI - Represents scalar error indicator. +It indicates element error based on the value of some suitable scalar +value (for example damage level, plastic strain level) obtained from the +element integration points and corresponding material model. +\item +EET\_ZZEE - The implementation of Zienkiewicz Zhu Error +Estimator. It requires the special element algorithms, which may not +be available for all element types. +Please note, that in the actual version, the error on the element level is evaluated using default integration rule. For example, in case of ZZ error estimator, the error (L2 or energy norm) is evaluated from the difference of computed and ``recovered'' stresses, which are approximated using the same interpolation functions as displacements). Therefore, in many cases, the default integration rule order is not sufficient and higher integration must be used on elements (consult element library manual and related NIP parameter). +\item +EET\_CZZSI - The implementation of combined criteria: Zienkiewicz Zhu Error Estimator for elastic regime and +scalar error indicator in non-linear regime. \end{itemize} -\paragraph{Boundary loads} -\begin{itemize} -\item Constant edge fluxes (load) +\begin{table}[ht] +\begin{center} +\begin{tabular}{|l|l|} +\hline +Error estimator/indicator & \param{eetype}\\ +\hline +EET\_SEI & 0 \\ +EET\_ZZEE& 1 \\ +EET\_CZZSI& 2\\ +\hline +\end{tabular} +\caption{Supported error estimators and indicators.} +\label{eetypestable} +\end{center} +\end{table} + +The sets of parameters (\param{errorestimatorparams} field) used to +configure each error estimator are different +\begin{itemize} +\item +EET\_SEI\\ \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{ConstantEdgeLoad}}{} - \recentry{}{\field{loadType}{in}} - \recentry{}{\field{components}{ra}} - \recentry{}{\optField{dofexcludemask}{ia}} - \recentry{}{\optField{csType}{in}} - \recentry{}{\optField{properties}{dc}} - \recentry{}{\optField{propertytf}{dc}} + \recentry{\hspace{2cm}}{\optField{regionskipmap}{ia}} + \recentry{}{\field{vartype}{in}} + \recentry{}{\field{minlim}{rn} \field{maxlim}{rn}} + \recentry{}{\field{mindens}{rn} \field{maxdens}{rn} \field{defdens}{rn}} + \recentry{}{\optField{remeshingdensityratio}{rn}} \end{record} -\item Constant surface fluxes (load) - +\begin{itemize} +\item \param{regionskipmap} parameter allows to skip some regions. The +error is not evaluated in these regions and default mesh density is +used. The size of this array should be equal to number of regions and +nonzero entry indicates region to skip. +\item \param{vartype} parameter determines the type of internal +variable to be used as error indicator. Currently supported value is +1, representing damage based indicator. +\item If the indicator value is in range given by parameters (\param{minlim}, + \param{maxlim}) then the proposed mesh density is linearly +interpolated within range given by parameters (\param{mindens}, \param{maxdens}). If +indicator value is less than value of \param{minlim} parameter then +value of \param{defdens} parameter is used as +required density, if it is larger than \param{maxlim} then +\param{maxdens} is used as required density. +\item +\param{remeshingdensityratio} parameter determines the allowed ratio +between proposed density and actual density. +The remeshing is forced, whenever the actual ratio is smaller than +this value. Default value is equal to 0.80. +\end{itemize} +\item +EET\_ZZEE\\ \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{ConstantSurfaceLoad}}{} - \recentry{}{\field{loadType}{in}} - \recentry{}{\field{components}{ra}} - \recentry{}{\optField{dofexcludemask}{ia}} - \recentry{}{\optField{csType}{in}} - \recentry{}{\optField{properties}{dc}} - \recentry{}{\optField{propertytf}{dc}} + \recentry{\hspace{2cm}}{\optField{regionskipmap}{ia}} + \recentry{}{\field{normtype}{in}} + \recentry{}{\field{requirederror}{rn}} + \recentry{}{\field{minelemsize}{rn}} \end{record} -Represent constant edge/surface loads or boundary conditions. -Parameter \param{loadType} distinguishes the type of boundary condition. Supported values are specified in bctype.h: \begin{itemize} -\item \param{loadType} = 2 prescribed flux input (Neumann boundary condition), -\item \param{loadType} = 3 uniform distributed load or the convection (Newton) BC. Parameter \param{components} contains the -environmental values (temperature of the environment) corresponding to -element unknowns, and \param{properties} dictionary should contain -value of transfer (convection) coefficient (assumed to be a constant) under the key 'a', -\item \param{loadType} = 7 specifies radiative boundary condition (Stefan-Boltzmann). It requires to specify emmisivity $\varepsilon\in\langle 0,1\rangle$, the \param{components} array contains the environmental values (temperature of the environment). Default units are Celsius. Optional parameter \param{temperOffset} = 0 can be used to calculate in Kelvin. +\item \param{regionskipmap} parameter allows to skip some regions. The +error is not evaluated in these regions and default mesh density is +used. The size of this array should be equal to number of regions and +nonzero entry indicates region to skip. +\item \param{normtype} Allows select the type of norm used in +evaluation of error. Default value is to use L2 norm (equal to 0), +value equal to 1 uses the energy norm. +\item \param{requirederror} parameter determines the required error to +obtain (in percents/100). +\item{minelemsize} parameter allows to set minimum limit on element size. +\end{itemize} +\item +EET\_CZZSI - combination of parameters for EET\_SEI and EET\_ZZEE; the +in elastic regions are driven using EET\_SEI, the elastic are driven +by EET\_ZZEE. \end{itemize} -If the boundary condition corresponds to distributed force load, the \param{components} array contains components of distributed load corresponding to element unknowns. -The load is specified for all DOFs of object to which is associated. -For some types of boundary conditions the zero value of load does not mean that the load is not applied (Newton's type of bc, for example). -Then some mask, which allows to exclude specific dofs is necessary. -The \param{dofexcludemask} parameter is introduced to alow this. -It should have the same size as \param{components} array, and by -default is filled with zeroes. If some value of dofExcludeMask is set -to nonzero, then the corresponding componentArray -is set to zero and load is not applied for this DOF. -If the boundary condition corresponds to prescribed flux input, then -the \param{components} array contains the components of prescribed -input flux corresponding to element unknowns. -The properties can vary in time. Each property can have associated time function which determines its time variation. The time functions are set up using optional \param{propertytf} dictionary, containing for selected properties the corresponding time function number. The time function must be registered under the same key as in \param{properties} dictionary. The property value is then computed by product of property value (determined by \param{properties}) and corresponding time function evaluated at given time. If no time function provided for particula property, a unit constant function is assumed. +\section{Material interfaces} +\label{materialinterfaces} +The material interfaces are used to represent and track the position of +various interfaces on fixed grids. Typical examples include free surface, +evolving interface between two materials, etc. +Available representations include: -The load can be defined in global coordinate system (\param{csType} = -0, default) or in entity - specific local coordinate system -(\param{csType} = 1). -\item Linear edge flux (load) +\begin{tabular}{|l|l|l|} +\hline +MI & miflag & Compatibility \\ +\hline +LEPlic & 0 & 2D triangular \\ +LevelSet & 1 & 2D triangular \\ +\hline +\end{tabular} +\begin{itemize} +\item LEPlic- representation based on Volume-Of-Fluid approach; the initial distribution of VOF fractions should be specified for each element (see element manual)\\ + \begin{record}[0.9\textwidth] + \recentry{}{\optField{refvol}{rn}} + \end{record} +\begin{itemize} +\item +parameter \param{refvol} allows to set initial volume of reference fluid, then the reference volume is computed in each step and printed, so the accuracy and mass conservation can be monitored. +\end{itemize} +\item +LevelSet- level set based representation\\ \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{LinearEdgeLoad}}{} - \recentry{}{\field{loadType}{in}} - \recentry{}{\field{components}{ra}} - \recentry{}{\optField{dofexcludemask}{ia}} - \recentry{}{\optField{csType}{in}} + \recentry{}{\mbox{[\field{levelset}{ra} OR \field{refmatpolyx}{ra} \field{refmatpolyy}{ra}]}} + \recentry{}{\optField{lsra}{in} \optField{rdt}{rn} \optField{rerr}{rn}} \end{record} +\begin{itemize} +\item \param{levelset} allows to specify the initial level set values for all nodes directly. The size should be equal to total number of nodes within the domain. +\item Parameters \param{refmatpolyx} and \param{refmatpolyy} allow to initialize level set by specifying interface geometry as 2d polygon. Then polygon describes the initial zero level set, and level set values are then defined as signed distance from this polygon. Positive values are on the left side when walking along polygon. The parameter \param{refmatpolyx} specifies the x-coordinates of polygon vertices, parameter \param{refmatpolyy} y-corrdinates. Please note, that level set must be initialized, either using \param{levelset} parameter or using \param{refmatpolyx} and \param{refmatpolyy}. +\item Parameter \param{lsra} allows to select level set reinitialization algorithm. Currently supported values are 0 (no re-initialization), 1 (re-initializes the level set representation by solving $d_{\tau} = S(\phi)(1-\vert\grad d\vert)$ to steady state, default), 2 (uses fast marching method to build signed distance level set representation). +\item Parameters \param{rdt} \param{rerr} are used to control reinitialization algorithm for \param{lsra} = 0. \param{rdt} allows to change time step of integration algorithm and parameter \param{rerr} allows to change default error limit used to detect steady state. +\end{itemize} +\end{itemize} -Represents linear edge load. The meanings of parameters \param{csType} and \param{loadType} are the same as for -\entKeywordInst{ConstantEdgeLoad}. -In \param{components} array are stored load components for corresponding unknowns at the -beginning of edge, followed by values valid for end of edge. -The load can be defined in global coordinate system (\param{csType} = 0, default) or in entity - specific local coordinate system -(\param{csType} = 1). -\item InteractionLoad - -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{InteractionLoad}}{\field{ndofs}{in}} - \recentry{}{\field{loadType}{in}} - \recentry{}{\field{Components}{ra}} - \recentry{}{\optField{csType}{in}} - \recentry{}{\field{coupledparticles}{ia}} +\section{Mesh generator interfaces} +\label{meshpackages} +The mesh generator interface is responsible to provide a link to +specific mesh generator. The supported values of \param{meshpackage} +parameter are +\begin{itemize} +\item +MPT\_T3D: \param{meshpackage} = 0. T3d mesh interface. Default. Supports both 1d, 2d +(triangles) and 3d (tetrahedras) meshes. Reliable. +\item +MPT\_TARGE2: \param{meshpackage} = 1. Interface to Targe2 2D +mesh generator. +\item +MPT\_SUBDIVISION: \param{meshpackage}=3. Built-in subdivision algorithm. Supports triangular 2D and tetrahedral 3D meshes. Can operate in parallel mode. +\end{itemize} +% +\section{Initialization modules} +\label{InitModulesSec} +Initialization modules allow to initialize the state variables using data +previously computed by external software. The number of initialization module records is specified in +analysis record using \param{ninitmodules} parameter (see the initial part of section \ref{_AnalysisRecord}). The general format +is the following:\\ +\begin{record} + \recentry{\entKeyword{EntType}}{\field{initfile}{string}} \end{record} +The file name following the keyword ``initfile'' specifies +the path to the file that contains the initialization data +and should be given without quotes. -Represents a fluid pressure induced load in the solid part of the FluidStructureProblem. -The meanings of parameters \param{ndofs}, -\param{csType}, and \param{loadType} are the same as for -\entKeywordInst{LinearEdgeLoad}. In \param{Components} -array are stored load components for corresponding unknowns at the -beginning of edge (\param{ndofs} values), followed by values valid for -end of edge (\param{ndofs} values). The load should be defined in global -coordinate system (\param{csType} = 0) as it acts in normal direction of the edge. -Array \param{coupledparticles} assign PFEMParticles from the fluid part of the problem -providing fluid pressure. - -\end{itemize} +Currently, the only supported initialization module is +\begin{itemize} +\item Gauss point initialization module +\begin{record}[0.9\textwidth] + \recentry{GPInitModule}{\field{initfile}{string}} \end{record} +\begin{itemize} +\item +Each Gauss point is represented by one line in the initialization file. +\item +The Gauss points should be given in a specific order, based on the element number and the Gauss point number, in agreement with the mesh specified in later sections. +\item +Each line referring to a Gauss point should contain the following data: -\subsection{Initial conditions} -\label{_InitialConditions} -These records specify description of initial conditions. The general format is -following: +\begin{record} + \recentry{}{\field{elnum}{in} \field{gpnum}{in} \field{coords}{ra} \field{ng}{in}} + \recentry{}{\field{var\_1\_id}{in} \field{values\_1}{ra}} + \recentry{}{ ...} + \recentry{}{\field{var\_ng\_id}{in} \field{values\_ng}{ra}} +\end{record} + \item \param{elnum} is the element number + \item \param{gpnum} is the Gauss point number + \item \param{coords} are the coordinates of the Gauss point + \item \param{ng} is the number of groups of variables that will follow + \item \param{var\_1\_id} is the identification number of variable group number 1 (according to the definitions in internalstatetype.h) + \item \param{values\_1} are the values of variables in group number 1 + \item \param{var\_ng\_id} is the identification number of variable group number ng + \item \param{values\_ng} are the values of variables in group number ng +\item Example:\\ \mbox{``37 4 3 0.02 0.04 0.05 3 52 1 0.23 62 1 0.049 1 6 0 -2.08e+07 0 0 0 0''} means that Gauss point number 4 of element number 37 has coordinates $x=0.02$, $y=0.04$ and $z=0.05$ and the initial values are specified for 3 groups of variables;\\ +the first group (variable ID 52) is of type IST\_DamageScalar (see internalstatetype.h) and contains 1 variable (since it is a scalar) with value 0.23;\\ + the second group (ID 62) is of type IST\_CumPlasticStrain +and contains 1 variable with value 0.049;\\ + the third group is of type IST\_StressTensor +and contains 6 variables (stress components $\sigma_x$, $\sigma_y$, etc.) with values +0, -2.08e+07, 0, 0, 0, 0 +\end{itemize} +\end{itemize} -\noindent +\section{Export modules} +\label{ExportModulesSec} +Export modules allow to export computed data into external software for +post-processing. The number of export module records is specified in +analysis record using \param{nmodules} parameter (see the initial part of section \ref{_AnalysisRecord}). The general format +is the following:\\ \begin{record} - \recentry{\entKeywordInst{InitialCondition}}{\componentNum} - \recentry{}{\field{conditions}{dc}} + \recentry{\entKeyword{EntType}}{[\fieldnotype{tstep\_all}]} + \recentry{}{\optField{tstep\_step}{in}} + \recentry{}{\optField{tsteps\_out}{rl}} + \recentry{}{\optField{subtsteps\_out}{in}} + \recentry{}{[\fieldnotype{domain\_all}]} + \recentry{}{\optField{domain\_mask}{in}} \end{record} -The order of particular records is optional, load, boundary or initial condition number is determined by \componentNum\ parameter. -The numbering should start from one and should end at n, where n is the number of records. -Initial parameters are listed in \param{conditions} dictionary using keys followed by their initial values. -Now 'v' key represents velocity and 'a' key represents acceleration. - +To select all solution steps, in which output will be performed, use +\param{tstep\_all}. To select each \param{tstep\_step}-nth step, use +\param{tstep\_step} parameter. In order to select only specific +solution steps, the \param{tsteps\_out} list can be specified, +supplying solution step number list in which output will be done. +To select output for all domain of the problem the \param{domain\_all} +keyword can be used. To select only specific domains, +\param{domain\_mask} array can be used, where the values of the array +specify the domain numbers to be exported. +If the parameter \param{subtsteps\_out} = 1, it turns on the export of intermediate results, +for example during the substepping or individual equilibrium iterations. This option requires support from the solver. -\subsection{Time functions records} -\label{_TimeFunctionsRecords} -These records specify description of time functions, which generally describe -time variation of components during solution. The general format is -following: +Currently, the supported export modules are following +\begin{itemize} +\item VTK export, \textbf{DEPRECATED - Use VTKXML} -\noindent -\begin{record} - \recentry{\entKeyword{TimeFunctType}}{\componentNum} - \recentry{}{\optField{initialValue}{rn}} +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{vtk}}{\optField{vars}{ia}} + \recentry{}{\optField{primvars}{ia}} + \recentry{}{\optField{cellvars}{ia}} + \recentry{}{\optField{stype}{in}} + \recentry{}{\optField{regionstoskip}{ia}} \end{record} -The order of these records is optional, time function number is determined by \componentNum\ parameter. -The \param{initialValue} parameter allows to control the way, how increment of receiver is evaluated for the first solution step. -This first solution step increment is evaluated as the difference of value of receiver at this first step and given initial value (which is by default set to zero). -The increments of receiver in subsequent steps are computed as a difference between receiver evaluated at given solution step and in previous step. -The numbering should start from one and should end at n, where n is the number of records. +\begin{record}[0.9\textwidth] + \recentry{\entKeywordInst{vtkxml}}{\optField{vars}{ia}} + \recentry{}{\optField{primvars}{ia}} + \recentry{}{\optField{cellvars}{ia}} + \recentry{}{\optField{ipvars}{ia}} + \recentry{}{\optField{stype}{in}} + \recentry{}{\optField{regionsets}{ia}} + \recentry{}{\optField{timeScale}{rn}} +\end{record} -Currently, TimeFunctType keyword can be one from \begin{itemize} -\item Constant function +\item The vtk module is obsolete, use vtkxml instead. Vtkxml allows to export results recovered on region by region basis and has more features. -\noindent -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{ConstantFunction}}{\field{f(t)}{rn}} -\end{record} +\item The array \param{vars} contains identifiers for those internal +variables which are to be exported. These variables will be smoothed and transfered to nodes. The id values are defined by +InternalStateType enumeration, which is defined in include file +``src/oofemlib/internal\-statetype.h''. -Represents the constant time function, with value \param{f(t)}. +\item The array \param{primvars} +contains identifiers of primary variables to be exported. +The possible values correspond to the values of enumerated type +UnknownType, which is again defined in ``src/oofemlib/unknown\-type.h''. +Please note, that the values corresponding to enumerated type values +start from zero, if not specified directly and that not all values are +supported by particular material model or analysis type. -\item Peak function +\item The array \param{cellvars} contains identifiers of constant variables defined +on an element (cell), e.g. a material number. Identifier numbers are specified in +``src/oofemlib/internalstatetype.h''. -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{PeakFunction}}{\field{t}{rn}} - \recentry{}{\field{f(t)}{rn}} -\end{record} +\item The array \param{ipvars} contains identifiers for those internal +variables which are to be exported. These variables will be directly exported (no smoothing) as point dataset, where each point corresponds to individual integration point. A separate vtu file for these raw, point data will be created. +The id values are defined by +InternalStateType enumeration, which is defined in include file +``src/oofemlib/internal\-statetype.h''. -Represents peak time function. If time is equal to \param{t} -value, then the value of time function is given by \param{f(t)} value, -otherwise zero value is returned. -\item Piecewise function +\item The parameter \param{stype} allows to select smoothing procedure for +internal variables, which is used to compute nodal values from values +in integration points. The supported values are $0$ for simple nodal averageing (generally supported only by triangular and tetrahedral elements), $1$ for Zienkiewicz Zhu recovery (default), and $2$ for Superconvergent Patch Recovery (SPR, based on least square fitting). -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{PiecewiseLinFunction}}{[\field{nPoints}{in} {\field{t}{ra} \field{f(t)}{ra}}] [ \field{datafile}{"string"}]} -\end{record} +\item The export is done on region basis, on each region, the nodal recovery is performed independently and results are exported in a separate piece. This allows to take into account for discntinuities, or to export variables defined only by particular material model. The region volumes are defined using sets containing individual elements. By default the one region is created, containing all element in the problem domain. The optional parameter \param{regionsets} allows to use user-defined. The individual values refer to numbers (ids) of domain sets. Note, that regions are determined solely using elements. -Represents the piecewise time function. The particular time values in -\param{t} array should be sorted according to time scale. Corresponding time -function values are in \param{f(t)} array. Value for time, which -is not present in \param{t} is computed using liner interpolation scheme. -Number of time-value pairs is in \param{nPoints} parameter. +{\footnotesize vtkxml tstep\_all cellvars 1 46 vars 1 1 primvars 1 1 stype 2 regionsets 2 1 2} -The second alternative allows reading input data from an external ASCII file. A hash commented line (\#) is -skipped during reading. File name should be eclosed with " ". +\item \param{timeScale} scales time in output. In transport problem, basic units are seconds. Setting timeScale = 2.777777e-4 (=1/3600.) converts all time data in vtkXML from seconds to hours. + +\end{itemize} +By default vtk and vtkxml modules perform recovery over the whole domain. The VTKXML module can operate in region-by-region mode (see \param{nvr} and \param{vrmap} parameters). In this case, the smoothing is performed only over particular virtual region, where only elements in this virtual region participate. -\item Heaviside-like time function +\item Homogenization of IP quantities in the global coordinate system (such as stress, strain, damage, heat flow). Corresponding IP quantities are summed and averaged over the volume. It is possible to select region sets from which the averaging occurs. The averaging works for all domains with an extension to trusses. A truss is considered as a volume element with oriented stress and strain components along the truss axis. The transformation to global components occurs before averaging. \begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{HeavisideLTF}}{\field{origin}{rn}} - \recentry{}{\field{value}{rn}} + \recentry{\entKeywordInst{hom}}{} + \recentry{}{\field{ists}{ia}} + \recentry{}{\optField{scale}{rn}} + \recentry{}{\optField{regionSets}{ia}} + \recentry{}{\optFieldnotype{strain\_energy}} \end{record} -Up to time, given by -parameter \param{origin}, the value of time function is zero. If time -greater than \param{origin} parameter, the value is -equal to parameter \param{value} value. -\item User defined +\begin{itemize} -\begin{record}[0.9\textwidth] - \recentry{\entKeywordInst{UsrDefLTF}}{\field{f(t)}{expr}} - \recentry{}{\optField{dfdt(t)}{expr}} - \recentry{}{\optField{d2fdt2(t)}{expr}} -\end{record} +\item An integer array \param{ists} specifies internal state types for export which are defined in internalstatetype.h file. -Represents user defined time function. -The expressions can depend on ``t'' parameter, for which actual time will be substituted and -expression evaluated. The function is defined using \param{f(t)} parameter, and optionally, its first and second time derivatives using \param{dfdt(t)} and \param{d2fdt2(t)} parameters. -The first and second derivatives may be required, this depend on type of analysis. +\item The parameter \param{scale} multiplies all averaged IP quantities. \param{scale}=1 by default. + +\item An integer array \param{regionSets} specifies region sets for averaging. All domain is averaged by default. + +\item \param{strain\_energy} calculates strain energy over selected elements (defined by sets) by +\begin{equation} +W^*=\int_V \int \sigma \mathrm{d} (\varepsilon-\varepsilon_{eig}) \mathrm{d} V +\end{equation} +where $\sigma$ is the stress tensor, $\varepsilon$ stands for the strain tensor and $\varepsilon_{eig}$ is eigenstrain tensor (originates from temperature load or prescribed eigenstrain). Strain energy increment and total strain energy is reported in each step. The integration uses mid-point rule for stress and yields exact results for linear elastic materials. -Very general, but relatively slow. \end{itemize} -\subsection{Xfem manager record and associated records} -\label{_XFEMManagerRecords} -This record specifies the number of enrichment items and simulation options -common for all enrichment items. Functions used for enrichment (e.g. Heaviside, -abs or branch functions) are not specified here, they are specified for each -enrichment item separately. The same holds for the geometrical representation of -each enrichment item (e.g. a polygon line or a circle). Currently, OOFEM -supports XFEM simulations of cracks and material interfaces in 2D. The input -format for the XFEM manager is:\\ -\begin{record} - \recentry{\entKeywordInst{XfemManager}}{\field{numberofenrichmentitems}{in}} - \recentry{}{\field{numberofgppertri}{in}} - \recentry{}{\field{debugvtk}{in}} - \recentry{}{\field{vtkexport}{in}} - \recentry{}{\field{exportfields}{in}} -\end{record} -where \param{numberofenrichmentitems} represents number of enrichment items, -\param{numberofgppertri} denotes the number of Gauss points in each subtriangle -of a cut element (default 12) and \param{debugvtk} controls if additional debug -vtk files should be written (1 activates the option, 0 is default). +\item Gauss point export is useful if one needs to plot a certain variable +(such as damage) as a function of a spatial coordinate using tools like +gnuplot. It generates files with data organized in columns, each row +representing one Gauss point. In this way, one can plot e.g.\ the damage +distribution along a one-dimensional bar. -The specification of an enrichment item may consist of several lines, see e.g. -the test \textit{sm/xFemCrackValBranch.in}. First, the enrichment item type is -specified together with some optional parameters according to\\ -\noindent -\begin{record} - \recentry{\entKeyword{EntType}}{\componentNum} - \recentry{}{\field{enrichmentfront}{in}} - \recentry{}{\field{propagationlaw}{in}} +\begin{record}[0.9\textwidth] + \recentry{gpexportmodule}{\optField{vars}{ia}} + \recentry{}{\optField{ncoords}{in}} \end{record} -where \param{enrichmentfront} specifies an enrichment front (we may for example -employ branch functions at a crack tip and Heaviside enrichment along the rest -of the crack, hence the ``front'' of the enrichment is treated separately) and -\param{propagationlaw} specifies a rule for crack propagation (this feature is -still highly experimental though). Specification of an \param{enrichmentfront} -and a \param{propagationlaw} is optional. -The next line specifies the enrichment function to be used:\\ -\noindent -\begin{record} - \recentry{\entKeyword{EntType}}{\componentNum} -\end{record} +\begin{itemize} +\item The array \param{vars} contains identifiers for those internal +variables which are to be exported. The id values are defined by +InternalStateType enumeration, which is defined in include file +``src/oofemlib/internal\-statetype.h''. +\item Parameter \param{ncoords} specifies the number of spatial coordinates to be exported at each Gauss point. Depending on the spatial dimension of the +domain, the points can have one, two or three coordinates. If \param{ncoords} +is set to -1, only those coordinates that are actually used are exported. + If \param{ncoords} is set to 0, no coordinates are exported. +If \param{ncoords} +is set to a positive integer, exactly \param{ncoords} coordinates are exported. +If \param{ncoords} exceeds the actual number of coordinates, the actual +coordinates are supplemented by zeros. For instance, if we deal with a 2D +problem, the actual number of coordinates is 2. For \param{ncoords}=3, +the two actual coordinates followed by 0 will be exported. +For \param{ncoords}=1, only the first coordinate will be exported. +\end{itemize} +The Gauss point export module creates a file with extension ``gp'' +after each step for which the output is performed. This file contains +a header with lines starting by the symbol \#, followed by the actual data +section. +Each data line corresponds to one Gauss point and contains the following +data: +\begin{enumerate} +\item element number, + \item material number, + \item Gauss point number, + \item contributing volume around Gauss point, +\item Gauss point global coordinates (written as a real array of length \param{ncoords}), +\item internal variables according to the specification in \param{vars} (each written as a real array of the corresponding length). +\end{enumerate} +Example:\\ +``GPExportModule 1 tstep\_step 100 domain\_all ncoords 2 vars 5 4 13 31 64 65'' +\\ +means that the *.gp file will be written after each 100 steps and will contain +for each of the Gauss points in the entire domain its 2 coordinates and also internal +variables of type 4, 13, 31, 64 and 65, which are the strain tensor, damage tensor, maximum equivalent strain level, stress work density and dissipated work density. Of course, the material model must be able to deliver such variables. +The size of the strain tensor depends on the spatial dimension, and the size +of the damage tensor depends on the spatial dimension and type of model +(e.g., for a simple isotropic damage model it will have just 1 component +while for an anisotropic damage model it may have more). The other variables +in this example are scalars, but they will be written as arrays of length 1, +so the actual value will always be preceded by ``1'' as the length of the array. Since certain internal variables have the meaning of densities (per unit volume +or area, again depending on the spatial dimension), it is useful to have +access to the contributing volume of the Gauss point. The product of this +contributing volume and the density gives an additive contribution to the +total value of the corresponding variable. This can be exploited e.g.\ to +evaluate the total dissipated energy over the entire domain. +\end{itemize} -This is followed by a line specifying the geometric description (e.g. a polygon -line or a circle) according to\\ -\noindent -\begin{record} - \recentry{\entKeyword{EntType}}{\componentNum \ extra attributes} -\end{record} -where the number and type of extra attributes to specify will vary depending on the -geometry chosen, e.g. center and radius for a circle or a number of points for a -polygon line. -If an enrichment front was specified previously, the type and properties of the -enrichment front are specified on the next line according to\\ -\noindent -\begin{record} - \recentry{\entKeyword{EntType}}{\componentNum \ extra attributes} -\end{record} -If a propagation law was specified previously, it's type and properties are also -specified on a separate line according to\\ -\noindent -\begin{record} - \recentry{\entKeyword{EntType}}{\componentNum \ extra attributes} -\end{record} \clearpage -\section{Examples} -\subsection {Beam structure} +\chapter{Examples} +\section {Beam structure} This example for a simple beam structure gives basic overview of the input file (found under tests/sm/beam2d\_1.in). Structure geometry and its constitutive and geometrical properties are shown in Fig. (\ref{ex01}). The linear static analysis is required, the influence of shear is neglected. @@ -3172,7 +3185,7 @@ \section{Examples} Set 7 elements 2 1 2 \end{verbatim}} -\subsection {Plane stress example} +\section {Plane stress example} \begin{figure}[htb] \begin{htmlonly} \centerline{\includegraphics[width=0.7\textwidth]{ex02}} @@ -3367,13 +3380,8 @@ \subsection{Element-cut example} ConstantFunction 1 f(t) 1.0 \end{verbatim} -\addcontentsline{toc}{section}{References} -\begin{thebibliography}{9} -\bibitem{Codina01} R. Codina: Pressure Stability in Fractional Step Finite Element Methods for Incompressible Flows. {\em Journal of Computational Physics} 170(1): 112 -- 140, 2001. -\bibitem{Idelsohn04} S. R. Idelsohn, E. O\~nate, E. and F. Del Pin. -\newblock The particle finite element method: a powerful tool to solve incompressible flows with free-surfaces and breaking waves. -\newblock {\em International Journal for Numerical Methods in Engineering}, 61: 964--989, 2004. -\end{thebibliography} +%\addcontentsline{toc}{section}{References} +%\begin{thebibliography}{9} \section{Figures} %\subsection {Node cut mode} diff --git a/doc/theorymanual/ackno.tex b/doc/theorymanual/ackno.tex new file mode 100644 index 000000000..4d8185fee --- /dev/null +++ b/doc/theorymanual/ackno.tex @@ -0,0 +1,3 @@ +\section*{Acknowledgments} +This work was supported by the Grant Agency of the Czech Republic - +Project No.: 103/97/P106. diff --git a/doc/theorymanual/basicequations.tex b/doc/theorymanual/basicequations.tex new file mode 100644 index 000000000..7c96c4a31 --- /dev/null +++ b/doc/theorymanual/basicequations.tex @@ -0,0 +1,222 @@ +% Basic equations +\section{Linear elasticity} +\subsection{Linear kinematics} +Let us consider a deformable body as a collection of points, where position of each point is denoted as $\x\in\Omega$. In a deformed configuration the position of each point is identified by its position vector $\xd(x) = \mbf{\phi}(\x)$. The displacement vector is then defined as: +\begin{equation} + \label{eq:displacementvector} + \xd(\x) = \x + \du(\x) +\end{equation} + +Let us now examine the position in a local neighborhood of a point. The deformed position of such neighbor point with coordinates $\x+d\x$ (where d\x is infinitisemally small vector) is +$$\xd(\x+d\x) = \x+d\x+\du(\x+d\x) = \xd + d\xd$$, +where $d\xd$ is the mapping of vector $d\x$ onto deformed configuration, see Fig.~\ref{fig:deformedconfiguration}. +\begin{figure} + \begin{center} + \includegraphics[width=0.5\textwidth]{figs/deformedconfiguration.png} + \end{center} + \label{fig:deformedconfiguration} + \caption{Deformed configuration} +\end{figure} +Taking into account the definition of displacement vector ~\ref{eq:displacementvector} and using Taylor formula we get +\begin{equation} + d\xd = \x+d\x+\du(\x+d\x)-\xd = d\x-\du(\x)+\du(\x+d\x) \approx [\mbf{I}+\grad\du(\x)]d\x +\end{equation} +where $\grad\du(\x)$ is the displacement gradient tensor (in small strain theory we assume $\vert\vert\grad\du(\x)\vert\vert \ll 1$). +The displacement gradient tensor can be decomposed into symetric and antisymmetric parts +$$ +\grad\du = \mbf{\eps}+\mbf{\omega}={1\over 2}(\grad\du+\grad\du^T)+{1\over 2}(\grad\du-\grad\du^T) = \grad^s\mbf{u}+\grad^a\mbf{u} +$$ + +The antisymmetric part corresponds to infinitesimal rotation. The symmeric part of displacement gradient tensor is therefore the measure of infinitesimal deformation +$$ +d\xd = \mbf{\eps} d\x +$$ +\subsection{Equlibrium equations} +Stress is defined as the force across a "small" boundary per unit area of that boundary, for all orientations of the boundary. In the most general case, called triaxial stress, the stress is nonzero across every surface element. Cauchy observed that the stress vector $\mbf{t}$ across a surface is a linear function of the surface's normal vector $\mbf{n}$: +$$ +\mbf{t}(x)=\mbf{\sigma}(x)\mbf{n}(x) +$$ +where $\mbf{\sigma}(x)$ is called the (Cauchy) stress tensor, completely describing the stress state at any point. +\begin{figure} + \begin{center} + \includegraphics[width=0.5\textwidth]{figs/tractionstressrelation.png} + \end{center} + \label{fig:tractionstressrelation} + \caption{Balance between tractions and stresses in 2D} +\end{figure} + +The components of the Cauchy stress tensor at every point in a material satisfy the equilibrium equations (Cauchy’s equlibrium equations). From the conservation of angular momentum follows the symmetry of the stress tensor. Therefore, the stress state of the medium at any point and instant can be specified by only six independent parameters, rather than nine. These may be written +$$ +\left[ + \begin{array}{ccc} + \sigma_{xx} & \tau_{xy} & \tau_{xz}\\ + \tau_{xy} & \sigma_{yy} & \tau_{yz}\\ + \tau_{zx} & \tau_{zy} & \sigma_{zz} + \end{array} +\right] +$$ +where the elements $\sigma_{xx}, \sigma_{yy}, \sigma_{zz}$ are called the normal stresses (relative to the chosen coordinate system), and $\tau_{yz}, \tau_{xz}, \tau_{xy}$ the shear stresses. + +In a static equlibrium, the Cauchy stress components in every material point satisfy the equilibrium equations, see~ref{fig:stressbalance} +\begin{equation} + \sigma_{ji, j} + F_i = 0 +\end{equation} +where we use summation convention over repated indices and $F_i$ are the components of the body force. In a compact tensorial notation we can write the above equation as +\begin{equation} + \grad\cdot\sigma + F_i = 0 + \label{eq:staticequlibrium3d} +\end{equation} + +\begin{figure} + \begin{center} + \includegraphics[width=0.5\textwidth]{figs/stressbalance2d.png} + \end{center} + \label{fig:stressbalance} + \caption{Stress balance in 2D} +\end{figure} + +\subsection{Constitutive equations} +In this section we present the constituve relations (i.e. relations between stress and strain tensors) for the case of hyperelasticity, which could be defined in terms of strain energy density $W(\mbf{\eps})$, which allows to evaluate stress components as partial derivatives: +$$ +\sigma_{ij}=\pard{W}{\eps_{ij}} +$$ +For example, the Hooke's law is defined using following strain energy potential +$$ +W(\eps) = \del{1}{2}\eps_{ij}\mbf{C}_{ijkl}\eps_{kl} +$$ +where $\mbf{C}$ is forth order elasticity tensor. The equality of mixed derivatives $(\dpd{W}{\eps_{ij}\eps_{kl}} = \dpd{W}{\eps{kl}\eps{ij}})$ and symmetry of stress and strain tensors $\pard{\sigma{ij}}{\eps_{kl}} = C_{ijkl}=C_{jikl}=C_{ijlk}$ imply that there is in general maximum 21 independ components of the elasticity tensor. +In the simplest case, the elasticity tensor for isotropic linear elastic material can be described by only two parameters: either Lame\'s parameters ($\lambda, \mu$) or more usual parametrs being Young's modulus $E$ and Poisson's ratio $\nu$: +$$ +C_{ijkl}=\lambda\delta_{ij}\delta_{kl}+2\mu {1\over 2}[\delta_{ik}\delta_{jl}+ + \delta_{il}\delta_{jk}] \equiv \mbf{C}=\lambda\mbf{1}\otimes\mbf{I}+2\mu\mbf{I} +$$ + +\subsection{Voight notation} + +The Voigt notation is hrequantly used to take advantage of the symmetry of the stress tensor to express the stress tensor as a six-dimensional vector of the following form: +$$ +\tilde{\mbf{\sigma}}= +\left[ + \sigma_{x}, \sigma_y, \sigma_z, \tau_{yz}, \tau_{xz}, \tau_{xy} + \right]^T \equiv +\left[ + \sigma_{xx}, \sigma_{yy}, \sigma_{zz}, \tau_{yz}, \tau_{xz}, \tau_{xy} + \right]^T +$$ + +The strain tensor, similar in nature to the stress tensor (both symmetric second-order tensors) can be written in Voight notation as +$$ +\tilde{\mbf{\eps }}= +\left[ + \eps_{x}, \eps_y, \eps_z, \gamma_{yz}, \gamma_{xz}, \gamma_{xy} + \right]^T \equiv +\left[ + \eps_{xx}, \eps_{yy}, \eps_{zz}, 2\eps_{yz}, 2\eps_{xz}, 2\eps_{xy} + \right]^T +$$ + +The benefit of using different representations for stress and strain is the scalar invariance +$$ +\mbf{\sigma}\cdot\mbf{\eps}=\sigma_{ij}\eps_{ij}=\tilde{\sigma} \tilde{\eps} +$$ +Similarly, a three-dimensional symmetric fourth-order tensor can be reduced to a [6,6] matrix. + + +\subsection {Boundary value problem in small strain elasticity} +\subsubsection{Strong form} + +Starting from the equilibrium equations~ref{eq:staticequlibrium3d}, into which we can substitute the constituve equations and strain-displacement relation we obtain the equlibrium equation expressed in terms of displacements: +$$ +\pard{}{x_j}\left({C_{ijkl} {1\over 2}(\pard{u_k}{x_l}+\pard{u_l}{x_k})}\right) + F_i = 0 +$$ +This system of three partial differnetial equations can be solved, provided that appropriate boundary conditions are given. In summary, the strong form is the following:\\ +\begin{center} +\fbox{ + \begin{minipage}{8cm} + Find $\mbf{u}\in R^n$, such that\\[4mm] + $\pard{}{x_j}\left({C_{ijkl} {1\over 2}(\pard{u_k}{x_l}+\pard{u_l}{x_k})}\right) + F_i = 0 \in \Omega\,$\\[2mm] + $\mbf{u}=\mbf{\bar{u}} \in \Gamma_u$\\[2mm] + $\mbf{t}^n_i = C_{ijkl}{1\over 2}(\pard{u_k}{x_l}+\pard{u_l}{x_k})\,n_j = \bar t_i \,\in \Gamma_t$ + \end{minipage} +} +\end{center} + +\subsubsection{Weak form} + + By following the method of weighted residuals, we multiply the governing differential equations~\ref{eq:staticequlibrium3d} in residual form by a sutable test functions $\delta\mbf{u}$, satisfying the homogeneous boundary conditions on $\Gamma_u$ + $$ + \int_\Omega \delta\mbf{u} \cdot \left( + \grad\cdot\mbf{\sigma} + F \right)\ d\Omega = \mbf{0} + $$ + By applying the Green's formula, we arrive at + $$ + \int_\Omega\grad\delta\mbf{u}\cdot\mbf{\sigma}\ d\Omega = + \int_\Omega\delta\mbf{u}\cdot\mbf{F}\ d\Omega + \int_\Gamma\delta\mbf{u}\cdot\mbf{\sigma}\mbf{n}\ d\Gamma + $$ + Then we can substitute for the stresses and tractions and taking into account the symmetry of stress tensor ($\sigma=C\mbf{\eps})$ + \begin{equation} + \int_\Omega\grad^s\delta\mbf{u}\cdot\mbf{C}\mbf{\eps}\ d\Omega = + \int_\Omega\delta\mbf{u}\cdot\mbf{F}\ d\Omega + \int_\Gamma\delta\mbf{u}\cdot\mbf{t}\ d\Gamma + \label{weakform3d} + \end{equation} + Or, equaivalently using Voight's notation + \begin{equation} + \int_\Omega\delta\tilde{\eps}^T\tilde{\mbf{D}}\tilde{\mbf{\eps}}\ d\Omega = + \int_\Omega\delta\mbf{u}^T\mbf{F}\ d\Omega + \int_\Gamma\delta\mbf{u}^T\mbf{t}\ d\Gamma + \label{eq:weakformvoight} + \end{equation} + + Note: this is equaivalent to the principle of virtual displacements. For hyperelastic material, the weak form is identical to the principle of minimum potential energy. + + +\subsection{Finite element discretization} +Let us consider discretization of the problem domain $\Omega$ into set of nonoverlapping subdomains $\Omega_e$, called elements. +Next we will consider the approximation of the unknown displacement field, defined on individual subdomains. Note that the approximation is not arbitrary: +\begin{itemize} + \item The weak form kontains only first derivatives of the unknown and test functions, thus only $C^0$ continuity is required. +\end{itemize} +The element approxiamtion of the arbitrary function $f$ has the form +$$ +f = \sum N_j(\mbf{x})r_j = \mbf{N}\mbf{r} +$$ +where $N_j$ are so called shape or approximation functions and $r_j$ are nodal values. +Note that for the approximation functions to be interpolatory, the shape functions have to satisfy Kronecker-delta property, i.e., $N_j(\mbf{x}_i)=\delta_{ij}$, where $\mbf{x}_i$ is the position vector of the i-th node. Also, the shape functions have to satisfy the condition $\sum N_i=1$, which follows from the requirement to approximate the constant function. +The required continuity of element approximations have to be satisfied. This is typically achieved by enforcing the continuity at the nodal points. +In our case, the approximation of displacements and test functions is +\begin{eqnarray} + \mbf{u}^e&=&\mbf{N}^e(\mbf{x})\mbf{r}^e\\ + \delta\mbf{u}^t&=&\mbf{N}^e(\mbf{x})\delta\mbf{r}^e +\end{eqnarray} + +We will use the weak form~\ref{weakform3d}, which using Voight's notation has the form +$$ + \int_\Omega\grad^s\delta\mbf{u}\cdot\mbf{C}\mbf{\eps}\ d\Omega = + \int_\Omega\delta\mbf{u}\cdot\mbf{F}\ d\Omega + \int_\Gamma\delta\mbf{u}\cdot\mbf{t}\ d\Gamma +$$ + + We will need also the derivatives of the displacement and test functions + \begin{eqnarray} + \tilde{\eps}^e = = \mbf{B}^e(\mbf{x})\mbf{r}^e\\ + \delta\tilde{\eps}^e&=&\mbf{B}^e(\mbf{x})\delta\mbf{r}^e +\end{eqnarray} +where $B^e$ matrix contains the first partial derivatives of the shape functions. +By substiituting into the weak form~\ref{eq:weakformvoight} we obtain +\begin{equation} + \sum_e \delta\mbf{r}^{e,T} + \left[ + \underbrace{\int_{\Omega^e} \mbf{B}^{e,T}\tilde{\mbf{D}}^e\mbf{B}^e\mbf{r}^e\ d\Omega}_{\mbf{K}^e}\mbf{r}^e-\underbrace{\int_{\Omega}\mbf{N}^{e,T}\mbf{F}\ d\Omega}_{\mbf{f}^e_\Omega} - \underbrace{\int_{\Gamma_t}\mbf{N}^{e,T}\bar{\mbf{t}}\ d\Gamma}_{\mbf{f}^e_\Gamma} + \right] = \mbf{0} +\end{equation} + +After introducing a mappig between element displacement vectors $\mbf{r}^e$, nodal vectors of test function values $\delta\mbf{r}$ and their global counterparts $\hat{\mbf{r}}, \delta\hat{\mbf{r}}$ one can obtain +\begin{equation} + \delta\hat{\mbf{r}}^{T} + \left[ + \hat{\mbf{K}}\hat{\mbf{r}}-\hat{\mbf{f}}_\Omega - \hat{\mbf{f}}_{\Gamma} + \right] = \mbf{0} +\end{equation} +By taking into account that the test fuctions are arbitrary (i.e. $\delta\hat{\mbf{r}}\ne\mbf{0}$), one finnaly obtains the following set of linear algebraic equations for unknonwn nodal displacements $\hat{\mbf{r}}$: +\begin{equation} + \hat{\mbf{K}}\hat{\mbf{r}}=\hat{\mbf{f}}_\Omega + \hat{\mbf{f}}_{\Gamma} +\end{equation} + diff --git a/doc/theorymanual/constitutiveequations.tex b/doc/theorymanual/constitutiveequations.tex new file mode 100644 index 000000000..c261cd5b6 --- /dev/null +++ b/doc/theorymanual/constitutiveequations.tex @@ -0,0 +1,402 @@ +The purpose of this chapter is to present the theoretical backgroung +of some handy general purpose theories and algorithms, that are provided in oofem in the +form of general material base classes. They can significantly +facilitate the implementation of particular material models that are +based on such concepts. Typical example can be a general purpose +plasticity class, that implements general stress return and stifness +matrix evaluation algorithms, based on provided methods for computing +yield functions and corresponding derivatives. Particular +models are simply derived from the base classes, inheriting +common algorithms. + + +\section{Isotropic damage model} +\label{IsoDamMod} + In this section, the formulation of an isotropic damage model will be + described. To cover the various models based on isotropic damage concept, + a base class IsotropicDamageMaterial is defined first, + declaring the necessary services and providing the implementation of + them, which are general. The derived classes then only implement a particular + damage-evolution law. + + The isotropic damage models are based on the simplifying assumption + that the stiffness degradation is isotropic, i.e., stiffness moduli + corresponding to different directions decrease proportionally and + independently of direction of loading. Consequently, the damaged + stiffness matrix is expressed as + $$ +\mbf{D} = (1-\omega)\mbf{D}_e, + $$ + where $\mbf{D}_e$ is elastic stiffness matrix of the undamaged + material and $\omega$ is the damage parameter. Initially, $\omega$ is + set to zero, representing the virgin undamaged material, and the response is + linear-elastic. As the material undergoes the deformation, the + initiation and propagation of microdefects decreases the stiffness, + which is represented by the growth of the damage parameter $\omega$. + For $\omega = 1$, the stiffness completely disappears. + + In the present context, the $\mbf{D}$ matrix represents the secant + stiffness that relates the total strain to the total stress + $$ + \mbf{\sigma}=\mbf{D}\mbf{\varepsilon} = (1-\omega)\mbf{D}_e\mbf{\varepsilon}. + $$ + Similarly to the theory of plasticity, a loading function $f$ is + introduced. In the damage theory, it is natural to work in the strain + space and therefore the loading function is depending on the strain + and on an additional parameter $\kappa$, describing the evolution of + the damage. Physically, $\kappa$ is a scalar measure of the + largest strain level ever reached. The loading function usually has + the form + $$ + f(\mbf{\varepsilon}, \kappa) = \tilde\varepsilon(\mbf{\varepsilon}) - \kappa, + $$ + where $\tilde\varepsilon$ is the equivalent strain, i.e., the scalar + measure of the strain level. + Damage can grow only if current state reaches the boundary of elastic + domain ($f=0$). This is expressed by the following loading/unloading + conditions + $$ + f \le 0,\;\;\dot\kappa \ge0,\;\;\dot\kappa f = 0. + $$ + It remains to link the variable $\kappa$ to the damage parameter + $\omega$. As both $\kappa$ and $\omega$ grow monotonically, it is + convenient to postulate an explicit evolution law + $$ + \omega = g(\kappa). + $$ + The important advantage of this explicit formulation is that the + stress corresponding to the given strain can be evaluated directly, + without the need to solve the nonlinear system of equations. + For the given strain, the corresponding stress is computed simply by + evaluating the current equivalent strain, updating the maximum + previously reached equivalent strain value $\kappa$ and the damage + parameter and reducing the effective stress according to $\mbf{\sigma} + = (1-\omega)\mbf{D}_e \mbf{\varepsilon}$. + + This general framework for computing stresses and + stiffness matrix is common for all material models of this type. + Therefore, it is natural to introduce + the base class for all isotropic-based damage models which provides the general + implementation for the stress and stiffness matrix evaluation + algorithms. The particular models then only provide their equivalent + strain and damage evolution law definitions. + The base class only declares the virtual services for computing equivalent + strain and corresponding damage. The implementation of common services + uses these virtual functions, but they are only declared at + IsotropicDamageMaterial class level and have to be + implemented by the derived classes. + + Together with the material model, the corresponding status has to be + defined, containing all necessary history variables. + For the isotropic-based damage models, the only history variable is + the value of the largest strain level ever reached ($\kappa$). + In addition, the corresponding damage level $\omega$ will be stored. + This is not necessary because damage can be always computed from + corresponding $\kappa$. + The IsotropicDamageMaterialStatus class is derived from + StructuralMaterialStatus class. The base class represents the + base material status class for all structural statuses. At + StructuralMaterialStatus level, the attributes common to all + ``structural analysis'' material models - the strain and + stress vectors (both the temporary and non-temporary) are introduced. The + corresponding services for accessing, setting, initializing, and + updating these attributes are provided. + Therefore, only the $\kappa$ and $\omega$ parameters are introduced + (both the temporary and non-temporary). The corresponding services for + manipulating these attributes are added and services for context + initialization, update, and store/restore operations are overloaded, to + handle the history parameters properly. + + + +\section{Multisurface plasticity driver - MPlasticMaterial class} + +In this section, a general multisurface plasticity theory with +hardening/softening is reviewed. The presented algorithms are +implemented in MPlasticMaterial class. + + + +\subsection{Plasticity overview} +Let $\mbf{\sigma},\e, {\rm and}\ \ep$ be the stress, total strain, and plastic strain vectors, respectively. +It is assumed that the total strain is decomposed into reversible elastic and irreversible plastic parts +\begin{equation} + \e = \e^e + \ep +\end{equation} +The elastic response is characterized in terms of elastic constitutive matrix $\mbf{D}$ as +\begin{equation} +\label{el1} +\mbf{\sigma}=\mbf{D}\e^e = \mbf{D}(\mbf{\varepsilon}-\ep) +\end{equation} +As long as the stress remains inside the elastic domain, the deformation process is purely elastic and the plastic strain does not change. +It is assumed that the elastic domain, denoted as $IE$ is bounded by a composite yield surface. It is defined as +\begin{equation} +IE=\{(\mbf{\sigma},\mbf{\kappa})|f_i(\mbf{\sigma},\mbf{\kappa})<0, \rm{for\ all\ }i\in\{1,\cdots,m\}\} +\end{equation} +where $f_i(\mbf{\sigma},\mbf{\kappa})$ are $m\ge1$ yield functions intersecting in a possibly non-smooth fashion. The +vector $\mbf{\kappa}$ contains internal variables controlling the evolution of yield surfaces (amount of hardening or softening). +The evolution of plastic strain $\ep$ is expressed in Koiter's form. Assuming the non-associated plasticity, this reads +\begin{equation} +\label{epe} +\epd=\sum^{m}_{i=1} \lambda^i \partial_{\mbf{\sigma}}g_i(\mbf{\sigma},\mbf{\kappa}) +\end{equation} +where $g_i$ are plastic potential functions. The $\lambda^i$ are referred as plastic consistency parameters, which satisfy the following Kuhn-Tucker conditions +\begin{equation} +\label{ktc} +\lambda^i\ge0,\;f_i\le0,\;{\rm and}\ \lambda^i f_i=0 +\end{equation} +These conditions imply that in the elastic regime the yield function must remain negative and the rate of the plastic multiplier is zero (plastic strain remains constant) while in the plastic regime the yield function must be equal to zero (stress remains on the surface) and the rate of the plastic multiplier is positive. +The evolution of vector of internal hardening/softening variables $\mbf{\kappa}$ is expressed in terms of a general +hardening/softening law of the form +\begin{equation} +\dot{\mbf{\kappa}} = \dot{\mbf{\kappa}}(\sig, \mbf{\lambda}) +\end{equation} +where $\mbf{\lambda}$ is the vector of plastic consistency parameters $\lambda_i$. + + + +\subsection{Closest-point return algorithm} +Let us assume, that at time $t_n$ the total and plastic strain vectors and internal variables are known +$$ +\{\mbf{\varepsilon}_n, \mbf{\varepsilon}^p_n, \mbf{\kappa}_n\}\ {\rm given\ at}\ t_n +$$ +By applying an implicit backward Euler difference scheme to the evolution equations (\ref{el1} and \ref{epe}) +and making use of the initial conditions the following discrete non-linear system is obtained +\begin{eqnarray} +\e_{n+1}&=&\e_n+\Delta\e\\ +\label{del} +\sig_{n+1}&=&\mbf{D}(\e_{n+1}-\ep_{n+1})\\ +\label{dep} +\ep_{n+1}&=&\ep_{n}+\sum\lambda^i\partial_{\sig} g_i(\sig_{n+1}, \mbf{\kappa}_{n+1}) +\end{eqnarray} +In addition, the discrete counterpart of the Kuhn-Tucker conditions becomes +\begin{eqnarray} +\label{dktc} +f_i(\sig_{n+1}, \mbf{\kappa}_{n+1}) &=& 0\\ +\lambda^i_{n+1} &\ge& 0\\ +\lambda^i_{n+1} f_i(\sig_{n+1}, \mbf{\kappa}_{n+1})&=& 0 +\end{eqnarray} +In the standard displacement-based finite element analysis, the strain evolution is determined by the displacement increments computed on the structural level. The basic task on the level of a material point is to evaluate the stress evolution generated by strain history. +According to this, the strain driven algorithm is assumed, i.e. that the total strain $\e_{n+1}$ is given. +Then, the Kuhn-Tucker conditions determine whether a constraint is active. The set of active constraints is denoted as $J_{act}$ and is defined as +\begin{equation} +J_{act}=\{\beta\in\{1,\cdots,m\}|f_\beta=0\ \&\ \dot{f}_\beta=0\} +\end{equation} +Let's start with the definition of the residual of plastic flow +\begin{equation} +\label{rpf} +\mbf{R}_{n+1}=-\ep_{n+1}+\ep_{n}+\sum_{j\in J_{act}}\lambda^j_{n+1}\partial_\sigma g_{n+1} +\end{equation} +By noting that total strain $\e_{n+1}$ is fixed during the increment we can express the plastic strain increment using (\ref{el1}) as +\begin{equation} +\Delta\ep_{n+1} = -\mbf{D}\Delta\sig_{n+1} +\end{equation} +The linearization of the plastic flow residual (\ref{rpf}) yields\footnote{For brevity, the simplified notation is introduced: $f=f(\sig,\mbf{\kappa}),\ g=g(\sig,\ \mbf{\kappa}),\ \mbf{\kappa}=\mbf{\kappa}(\sig,\lambda)$, and subscript $n+1$ is omitted.} +\begin{eqnarray} +\nonumber +&&\mbf{R}+\mbf{D}^{-1}\Delta\sig+\sum\lambda\partial_{\sigma\sigma}g\Delta\sig+\\ +&&+\sum\lambda\partial_{\sigma\kappa}g\cdot(\partial_\sigma\kappa\Delta\sig+\partial_\lambda\kappa\Delta\lambda)+\sum\Delta\lambda\partial_{\sigma}g =0 +\end{eqnarray} +From the previous equation, the stress increment $\Delta\sig$ can be expressed as +\begin{equation} +\label{dsig} +\Delta\sig=-\mbf{H}^{-1}\left(\mbf{R}+\sum\Delta\lambda\partial_{\sigma}g+\sum\lambda\partial_{\sigma\kappa}g\partial_{\lambda}\kappa\Delta\lambda\right) +\end{equation} +where $\mbf{H}$ is algorithmic moduli defined as +\begin{equation} +\mbf{H}=\left[\mbf{D}^{-1}+\sum\lambda\partial_{\sigma\sigma}g+\sum\lambda\partial_{\sigma\kappa}g\partial_{\sigma}\kappa\right] +\end{equation} +Differentiation of active discrete consistency conditions (\ref{dktc}) yields +\begin{equation} +\label{ddyc} +\mbf{f}+\partial_{\sigma}\mbf{f}\Delta\sig+\partial_{\kappa}\mbf{f} (\partial_\sigma\kappa\Delta\sig+\partial_\lambda\kappa\Delta\lambda) =0 +\end{equation} +Finally, by combining equations (\ref{dsig}) and (\ref{ddyc}), one can obtain expression for incremental vector of consistency parameters $\Delta\mbf{\lambda}$ +\begin{equation} +\left[\mbf{V}^T\mbf{H}^{-1}\mbf{U}-\partial_{\kappa}\mbf{f}\partial_{\lambda}\mbf{\kappa}\right]\Delta\mbf{\lambda}=\mbf{f}-\mbf{V}^T\mbf{H}^{-1}\mbf{R} +\end{equation} +where the matrices $\mbf{U}$ and $\mbf{V}$ are defined as +\begin{eqnarray} +\mbf{U} &=& \left[\partial_{\sigma}\mbf{g}+\sum\lambda\partial_{\sigma\kappa}g\partial_{\lambda}\kappa\right]\\ +\mbf{V} &=& \left[\partial_{\sigma}\mbf{f}+\partial_{\kappa}\mbf{f}\partial_{\sigma}\kappa\right] +\end{eqnarray} + +Before presenting the final return mapping algorithm, the algorithm for determination of the active constrains should be discussed. A yield surface $f_{i,n+1}$ is active if $\lambda^i_{n+1} > 0$. A systematic enforcement of the discrete Kuhn-Tucker condition (\ref{dktc}), which relies on the solution of return mapping algorithm, then serves as the basis for determining the active constraints. The starting point in enforcing (\ref{dktc}) is to define the trial set +\begin{equation} + J^{trial}_{act}=\{j\in\{1,\cdots,m\}|f^{trial}_{j,n+1} > 0\} +\end{equation} +where $J_{act}\subseteq J_{act}^{trial}$. Two different procedures can be adopted to determine the final set $J_{act}$. The conceptual procedure is as follows +\begin{itemize} + \item + Solve the closest point projection with $J_{act}=J_{act}^{trial}$ to obtain final stresses, along with $\lambda^i_{n+1},\ i\in J_{act}^{trial}$. +\item +Check the sign of $\lambda^i_{n+1}$. If $\lambda^i_{n+1} <0$, for some $i\in J_{act}^{trial}$, drop the $i-$th constrain from the active set and goto first point. Otherwise exit. +\end{itemize} + +In the procedure 2, the working set $J_{act}^{trial}$ is allowed to change within the iteration process, as follows +\begin{itemize} +\item +Let $J_{act}^{(k)}$ be the working set at the k-th iteration. Compute increments $\Delta\lambda^{i,(k)}_{n+1},\ i\in J_{act}^{(k)}$. +\item +Update and check the signs of $\Delta\lambda^{i,(k)}_{n+1}$. If $\Delta\lambda^{i,(k)}_{n+1} < 0$, drop the i-th constrain from the active set $J_{act}^{(k)}$ and restart the iteration. Otherwise continue with next iteration. +\end{itemize} +If the consistency parameters $\Delta\lambda^{i}$ can be shown to increase monotonically within the return mapping algorithm, the the latter procedure is preferred since it leads to more efficient computer implementation. + +The overall algorithm is convergent, first order accurate and unconditionally stable. +The general algorithm is summarized in Tab.~\ref{closespointalgo}. + +\begin{table} +\label{closespointalgo} +{\small +\begin{enumerate} +\item + Elastic predictor + + \begin{enumerate} + \item + Compute Elastic predictor (assume frozen plastic flow)\\ + $\sig^{trial}_{n+1} = \mbf{D}\left(\e_{n+1}-\ep_{n}\right)$\\ + $f^{trial}_{i,n+1}=f_i(\sig^{trial}_{n+1},\kap_{n}),\ \rm{for}\ i\in\{1,\cdots,m\}$ + \item + Check for plastic processes + IF $f^{trial}_{i,n+1}\le 0$ for all $i\in\{1,\cdots,m\}$ THEN: + \begin{itemize} +\item[] + Trial state is the final state, EXIT. + \end{itemize} + ELSE: + \begin{itemize} + \item[] +$J^{(0)}_{act}=\{i\in\{1,\cdots,m\}|f^{trial}_{i,n+1} > 0\}$ + \item[] +$\e^{p(0)}_{n+1}=\ep_n,\ \kap^{(0)}_{n+1}=\kap_n,\ \lambda^{i(0)}_{n+1}=0$ + \end{itemize} + ENDIF +\end{enumerate} + +\item + Plastic Corrector + \begin{enumerate} + \item[(c)] + Evaluate plastic strain residual + \begin{itemize} + \item[] +$\sig^{(k)}_{n+1} = \mbf{D}\left(\e_{n+1}-\e^{p(k)}_{n+1}\right)$ + \item[] +$\mbf{R}^{(k)}_{n+1}=-\e^{p(k)}_{n+1}+\ep_n+\sum\lambda^{i(k)}_{n+1}\partial_{\sigma}g_i$ + \end{itemize} + \item[(d)] + Check convergence + \begin{itemize} + \item[] +$f^{(k)}_{i,n+1}=f_i(\sig^{(k)}_{n+1},\kap^{(k)}_{n+1})$ + \item[] +if $f^{(k)}_{i,n+1} < TOL$, for all $i\in J^{(k)}_{act}$ and $\Vert\mbf{R}^{(k)}_{n+1}\Vert`. diff --git a/doc/theorymanual2/general.rst b/doc/theorymanual2/general.rst new file mode 100644 index 000000000..6ed71b825 --- /dev/null +++ b/doc/theorymanual2/general.rst @@ -0,0 +1,2 @@ +General documentation +##################### \ No newline at end of file diff --git a/doc/theorymanual2/index.rst b/doc/theorymanual2/index.rst new file mode 100644 index 000000000..bec0c3213 --- /dev/null +++ b/doc/theorymanual2/index.rst @@ -0,0 +1,28 @@ +.. OOFEM Theory manual documentation master file, created by + sphinx-quickstart on Tue Nov 19 09:32:57 2019. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to OOFEM Theory manual! +=============================================== + +.. toctree:: + :maxdepth: 2 + :caption: Table of Contents + + introduction + general + problems + elements + materials + +* :download:`How to contribute ` + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/theorymanual2/introduction.rst b/doc/theorymanual2/introduction.rst new file mode 100644 index 000000000..2a19952b9 --- /dev/null +++ b/doc/theorymanual2/introduction.rst @@ -0,0 +1,4 @@ +Introduction +############ + +* :download:`How to contribute ` \ No newline at end of file diff --git a/doc/theorymanual2/make.bat b/doc/theorymanual2/make.bat new file mode 100644 index 000000000..2119f5109 --- /dev/null +++ b/doc/theorymanual2/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/doc/theorymanual2/materials.rst b/doc/theorymanual2/materials.rst new file mode 100644 index 000000000..b2627ead5 --- /dev/null +++ b/doc/theorymanual2/materials.rst @@ -0,0 +1,2 @@ +Material models documentation +############################# \ No newline at end of file diff --git a/doc/theorymanual2/problems.rst b/doc/theorymanual2/problems.rst new file mode 100644 index 000000000..946564bca --- /dev/null +++ b/doc/theorymanual2/problems.rst @@ -0,0 +1,3 @@ +Engineering Models documentation +################################ +* :download:`Linear Elasticity `. \ No newline at end of file diff --git a/doc/theorymanual2/templates/include.tex b/doc/theorymanual2/templates/include.tex new file mode 100644 index 000000000..526e40c55 --- /dev/null +++ b/doc/theorymanual2/templates/include.tex @@ -0,0 +1,89 @@ +\newcommand{\mbf}[1]{\mbox{\boldmath$#1$}} +\font\mbff=cmbsy10\def\mbfx#1{\hbox{\mbff#1}}%\let\mbf\Mbff +\newcommand{\del}[2]{\mbox{$\displaystyle\frac{#1}{#2}$}} +\newcommand{\pard}[2]{\del{\partial \,{#1}}{\partial \,{#2}}} +\newcommand{\ppd}[2]{\del{\partial \,{#1}}{\partial \,{#2}}} +\newcommand{\dpd}[2]{\del{\partial ^{2}\,{#1}}{\partial \,{#2}^{2}}} +\newcommand{\tpd}[2]{\del{\partial ^{3}\,{#1}}{\partial \,{#2}^{3}}} +\newcommand{\cpd}[2]{\del{\partial ^{4}\,{#1}}{\partial \,{#2}^{4}}} +%\newcommand{\spd}[1]{\del{\partial ^{3}\,{#1}}{\partial \,x\,\partial \,t^{2}}} +%\newcommand{\scpd}[1]{\del{\partial ^{4}\,{#1}}{\partial \,x^{2}\,\partial +%\,t^{2}}} +\newcommand{\der}[2]{\del{d \,{#1}}{d \,{#2}}} +\newcommand{\dd}[2]{\del{d ^2\,{#1}}{d \,{#2}^2}} +\newcommand{\td}[2]{\del{d ^3\,{#1}}{d \,{#2}^3}} +\newcommand{\cd}[2]{\del{d ^4\,{#1}}{d \,{#2}^4}} +\newcommand{\MKP}{{MKP$\;\;$}} +\newcommand{\inl}[2]{\mbox{$\displaystyle\int_{#1}^{#2}$}} +\newcommand{\sul}[2]{\mbox{$\displaystyle\sum_{#1}^{#2}\,$}} +\newcommand{\limit}[1]{\mbox{$\displaystyle\lim_{#1}$}} +\newcommand{\vp}{\varphi} +\newcommand{\e}{\mbf{\varepsilon}} +\newcommand{\ep}[0]{\mbf{\varepsilon}^p} +\newcommand{\epd}[0]{\dot{\mbf{\varepsilon}}^p} +\newcommand{\sig}{\mbf{\sigma}} +\newcommand{\sigs}{\sigma}%scalar +\newcommand{\kap}{\mbf{\kappa}} + +\newcommand{\vsigrate}{\dot {\mbf{\sigma}}} +\newcommand{\sigrate}{\dot {\sigma}} +\newcommand{\taurate}{\dot {\tau}} +\newcommand{\erate} {\dot {\mbf{e}}} + +\newcommand{\rest}[1]{\Re\left( {#1} \right)} +\newcommand{\refeq}[1]{Eq.~(\ref{#1})} +\newcommand{\reffig}[1]{Fig.~(\ref{#1})} +\newcommand{\refeqs}[2]{Eqs.~(\ref{#1}), (\ref{#2})} +\newcommand{\refeqsr}[2]{\mbox{Eqs.~(\ref{#1})-(\ref{#2})}} + +\newcommand{\C}{$^{\circ}\mathrm{C}$} +\newcommand{\ymu}{y_{\mu}} +\newcommand{\y}[1]{y_{#1}} +\newcommand{\ymui}[1]{y_{\mu_{#1}}} +\newcommand{\tdymu}{{\dot y}_{\mu}} +\newcommand{\ttdymu}{{\ddot y}_{\mu}} +\newcommand{\timeder}[1]{\dot {#1}} +\newcommand{\dprime}{\prime\prime} + +\newcommand{\beq}{\begin{equation}} +\newcommand{\eeq}{\end{equation}} +\newcommand{\bea}{\begin{eqnarray}} +\newcommand{\eea}{\end{eqnarray}} +\newcommand{\vsi}{\mbf{\sigma}} +\newcommand{\vep}{\mbf{\varepsilon}} +\newcommand{\eps}{\varepsilon} +\newcommand{\mD}{\mbf{D}} +\newcommand{\vxi}{\mbf{\xi}} +\newcommand{\vx}{\mbf{x}} +\newcommand{\dxi}{\;\mbox{d}\mbf{\xi}} +\newcommand{\vf}{\mbf{f}} +\newcommand{\vg}{\mbf{g}} +\newcommand{\veps}{\mbf{\varepsilon}} +\newcommand{\mB}{\mbf{B}} +\newcommand{\vsig}{\mbf{\sigma}} +\newcommand{\vd}{\mbf{d}} +\newcommand{\mK}{\mbf{K}} +\newcommand{\macbra}[1]{\langle{#1}\rangle} +\newcommand{\vbs}{\mbf{b}^{\sigma}} +\newcommand{\vbe}{\mbf{b}^{\eta}} +\newcommand{\vbeT}{\mbf{b}^{\eta T}} + +\newcommand{\ud}{\mathrm{d}} +\newcommand{\grad}{\nabla} +%position vectors +\newcommand{\x}{\mbf{x}} +\newcommand{\xd}{\mbf{x}^\varphi} +%displacement +\newcommand{\du}{\mbf{u}} +\newcommand{\bestresultcolor}{blue} +\newcommand{\bestresult}[1]{\textcolor{\bestresultcolor}{\bf{#1}}} +\newcommand{\ignore}[1]{} + + + + + +\newcommand{\oofem}{\htmladdnormallink{OOFEM}{http://www.oofem.org}\ } +\newcommand{\oofemlnk}[1]{\htmladdnormallink{#1}{http://www.oofem.org}\ } +\newcommand{\bp}{\htmladdnormallink{Bo\v{r}ek Patz\'{a}k}{http://mech.fsv.cvut.cz/~bp/bp.html}} + diff --git a/doc/theorymanual2/templates/template.rst b/doc/theorymanual2/templates/template.rst new file mode 100644 index 000000000..670d180dd --- /dev/null +++ b/doc/theorymanual2/templates/template.rst @@ -0,0 +1,8 @@ + +================================= +This is a template +================================= +Hi. I am a small blind text. For as long as I can remember. It was not easy to understand what it means to be a blind text: it makes no sense. Really no sense. You are inconclusively inserted and turned around - and often not even read. But am I therefore worse text than others? Alright, I'll never be on the bestseller lists. But other texts do not do that either. And that's why it does not bother me to be very blind. And if you still read these lines, then I've done something as a small blind text of what all the right and important texts usually only dream. + + +Author: A. Author, Date: 10/2020 \ No newline at end of file diff --git a/doc/theorymanual2/templates/template.tex b/doc/theorymanual2/templates/template.tex new file mode 100644 index 000000000..21cbac072 --- /dev/null +++ b/doc/theorymanual2/templates/template.tex @@ -0,0 +1,46 @@ +\usepackage{fancyhdr, blindtext} +\usepackage{lastpage} + +\pagestyle{fancyplain} + +\fancyhead{} +\fancyfoot{} +\fancyhead[L]{\bf \mytitle} +\fancyhead[R]{\large OOFEM.ORG} +\fancyfoot[L]{Responsible: \myauthor} +\fancyfoot[R]{Date: \mydate\ Page:\ \thepage/\pageref{LastPage} } +\renewcommand{\headrulewidth}{0.4pt} +\renewcommand{\footrulewidth}{0.4pt} +\setlength\headheight{14pt} + +\fancypagestyle{titlestyle}{% + \fancyhead[L]{} + \fancyhead[R]{\large OOFEM.ORG} + \lfoot{Responsible:~\myauthor} + \renewcommand{\headrulewidth}{0.4pt} + \renewcommand{\footrulewidth}{0.4pt} +} + +%Redefine chapter by adding special first chapter page page-style +%\makeatletter +% \let\stdchapter\chapter +% \renewcommand*\chapter{% +% \@ifstar{\starchapter}{\@dblarg\nostarchapter}} +% \newcommand*\starchapter[1]{\stdchapter*{#1}\thispagestyle{chapterstyle}} +% \def\nostarchapter[#1]#2{\stdchapter[{#1}]{#2}\thispagestyle{chapterstyle}} +%\makeatother + +\renewcommand{\maketitle}[1]{ + %\begin{titlepage} + %{ + \thispagestyle{titlestyle} + \vspace*{15em} + \noindent{\Huge \mytitle}\\ + \noindent\rule{\textwidth}{0.4pt}\\[2em] + {\bf Summary}\\[0.5em] + #1 + \newpage + %} + %\end{titlepage} +} + diff --git a/doc/usermanual/Makefile b/doc/usermanual/Makefile new file mode 100644 index 000000000..7bdc70a1a --- /dev/null +++ b/doc/usermanual/Makefile @@ -0,0 +1,29 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build +RCP = scp + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +www-install: +ifdef INSTALLDIR + cd _build; $(RCP) -r html $(INSTALLDIR)/resources/doc/usermanual + cd _build; $(RCP) -r latex/oofemusermanual.pdf $(INSTALLDIR)/resources/doc/usermanual +else + echo "INSTALLDIR not defined" +endif + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/usermanual/conf.py b/doc/usermanual/conf.py new file mode 100644 index 000000000..10f319902 --- /dev/null +++ b/doc/usermanual/conf.py @@ -0,0 +1,55 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- 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 sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'OOFEM User Manual' +copyright = '2019, OOFEM team' +author = 'OOFEM team' + +# The full version, including alpha/beta/rc tags +release = '2.5' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# 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 = ['_build', 'Thumbs.db', '.DS_Store'] + + +# -- 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 = 'classic' + +# 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', 'figs'] \ No newline at end of file diff --git a/doc/usermanual/figs/Installation_win_VisualC.png b/doc/usermanual/figs/Installation_win_VisualC.png new file mode 100644 index 000000000..626ca1315 Binary files /dev/null and b/doc/usermanual/figs/Installation_win_VisualC.png differ diff --git a/doc/usermanual/figs/Installation_win_VisualC2.png b/doc/usermanual/figs/Installation_win_VisualC2.png new file mode 100644 index 000000000..ac6e95592 Binary files /dev/null and b/doc/usermanual/figs/Installation_win_VisualC2.png differ diff --git a/doc/usermanual/figs/Installation_win_cmake.png b/doc/usermanual/figs/Installation_win_cmake.png new file mode 100644 index 000000000..ffa90ef5c Binary files /dev/null and b/doc/usermanual/figs/Installation_win_cmake.png differ diff --git a/doc/usermanual/figs/concrete_3point.png b/doc/usermanual/figs/concrete_3point.png new file mode 100644 index 000000000..fc263e959 Binary files /dev/null and b/doc/usermanual/figs/concrete_3point.png differ diff --git a/doc/usermanual/figs/input_beam_example.png b/doc/usermanual/figs/input_beam_example.png new file mode 100644 index 000000000..e8e49dea5 Binary files /dev/null and b/doc/usermanual/figs/input_beam_example.png differ diff --git a/doc/usermanual/gettingstarted.rst b/doc/usermanual/gettingstarted.rst new file mode 100644 index 000000000..f0487eeba --- /dev/null +++ b/doc/usermanual/gettingstarted.rst @@ -0,0 +1,55 @@ +Getting started +=============== + +To get OOFEM installed on your system, please follow :ref:`installation` instructions first. + +OOFEM is console application, it should be executed from command line with arguments specifying the path to input file. When no arguments are privided, the help is printed on output. + +.. code-block:: bash + + $ ./oofem + + Options: + + -v prints oofem version + -f (string) input file name + -r (int) restarts analysis from given step + -ar (int) restarts adaptive analysis from given step + -l (int) sets treshold for log messages (Errors=0, Warnings=1, + Relevant=2, Info=3, Debug=4) + -rn turns on renumbering + -qo (string) redirects the standard output stream to given file + -qe (string) redirects the standard error stream to given file + -c creates context file for each solution step + + Copyright (C) 1994-2017 Borek Patzak + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +The problem to be solved is fully described in input file. The structure of input is explained in :ref:`understanding_input` sectiona and fully documented in `OOFEM Input manual `_. + +To run oofem with specific input, use ``-f`` option followed by a system path to input file. For illustration, we demonstrate the execution using `beam2d_1.in `_ test which is a part of OOFEM test suite and is located in ``tests/sm`` directory. + +.. code-block:: bash + + $ ./oofem -f /home/user/oofem.git/tests/sm/beam2d_1.in + ____________________________________________________ + OOFEM - Finite Element Solver + Copyright (C) 1994-2017 Borek Patzak + ____________________________________________________ + Computing initial guess + + StaticStructural :: solveYourselfAt - Solving step 1, metastep 1, (neq = 15) + + ... + + ANALYSIS FINISHED + + Real time consumed: 000h:00m:00s + User time consumed: 000h:00m:00s + Total 0 error(s) and 0 warning(s) reported + +By default, the text output file with results is created (as specified in input file). In this case, the ``beam2d_1.out`` file is created in the current working directory. + + + diff --git a/doc/usermanual/index.rst b/doc/usermanual/index.rst new file mode 100644 index 000000000..75d2acedf --- /dev/null +++ b/doc/usermanual/index.rst @@ -0,0 +1,29 @@ +.. OOFEM User manual documentation master file, created by + sphinx-quickstart on Tue Nov 19 09:32:57 2019. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to OOFEM User Manual +=============================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + introduction + installation + gettingstarted + understandinginput + understandingoutput + postprocessing + + + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/doc/usermanual/installation.rst b/doc/usermanual/installation.rst new file mode 100644 index 000000000..646b28ddb --- /dev/null +++ b/doc/usermanual/installation.rst @@ -0,0 +1,108 @@ +.. _installation: + +Installation +============ + +Installation options +--------------------- +* Official stable releases (http://www.oofem.org/en/download) + * Usually 12M release cycle + * Binary packages for Windows (AMD64 version only) and Linux (x86_64 version, Debian package) + * Source package (requires compilation) + +• Development version + * Manual installation from OOFEM GitHub repository (https://github.com/oofem/oofem.git) + +Binary package installation - Windows +------------------------------------- +* Extract downloaded zip archive (oofem_2.5_AMD64.zip) into any directory +* The extraction should create oofem_2.5_AMD64 directory +* Modify PATH variable to include oofem_2.5_AMD64/lib dir + + .. code-block:: bat + + set PATH=C:\Users\user\Documents\oofem_2.5_AMD64\lib;%PATH% + +* Test run + + .. code-block:: bat + + C:\Users\user\Documents\oofem_2.5_AMD64\bin\oofem -v + OOFEM version 2.5 (AMD64-Windows, fm;tm;sm;IML++) of Dec 30 2017 on JAJA + Copyright (C) 1994-2017 Borek Patzak + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + +Binary installation – Unix/Linux +-------------------------------- +You can either choose generic Linux binary or Debian package. + +Linux – binary +^^^^^^^^^^^^^^ +* Extract downloaded zip archive (oofem_2.5_x86.tar.gz) + .. code-block:: bash + + tr xzvf oofem_2.5_x86.tar.gz + +* This creates oofem_2.5_x86_64/bin and oofem_2.5_x86_64/bin directories +* Define where to find libraries + .. code-block:: bash + + $ export LDD_LIBRARY_PATH=../lib:$LDD_LIBRARY_PATH + +* Run oofem + .. code-block:: bash + + $ cd bin; ./oofem –v + +Linux – Debian package +^^^^^^^^^^^^^^^^^^^^^^ +.. code-block:: bash + + $ sudo apt install oofem_2.5_x86_64.deb + +Installation from source +------------------------ +Requirements + +* C++ compiler (g++, Visual Studio, MinGW, ...) +* CMake build tools (https://cmake.org/) +* Controls software compilation process by using platform independent configuration and generate native makefiles or projects +* To generate platform makefile or project configuration, use ``cmake`` (or any user friendly based GUI, such as ccmake or cmake-gui) + +Instalation from source - Linux +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In the following, we assume the sources are in /home/user/oofem.src and build directory in /home/user/oofem.build + +.. code-block:: bash + + $ cd /home/user/oofem.build + $ ccmake /home/user/oofem.src + $ make + +Installation from source - Windows +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Requirements: + +* C++ compiler (Visual Studio, MinGW) +* CMake build tools (https://cmake.org/) + +Procedure: + +* Clone oofem git repository +* Use cmake to generate VS solution + .. image:: figs/Installation_win_cmake.png + :scale: 10 % + :alt: screenshot of cmake gui + :align: right + + * Select compiler + * Set source directory + * Set build directory + * Generate project/solution +* Use compiler to build project targets (oofem and RUN_TESTS) + .. image:: figs/Installation_win_VisualC2.png + :scale: 10% + .. image:: figs/Installation_win_VisualC.png + :scale: 10% diff --git a/doc/usermanual/introduction.rst b/doc/usermanual/introduction.rst new file mode 100644 index 000000000..40d7c0ab3 --- /dev/null +++ b/doc/usermanual/introduction.rst @@ -0,0 +1,42 @@ +Introduction +============ + +OOFEM is a general purpose, object-oriented Finite Element code for solving mechanical. transport and fluid mechanics problems, primarily focused on academic/research use. It has been continuously developed since 1997. At present it consist of more than 230 thousands lines of source C++ code. It has acive development team and large user base around the world. The code has been successfully applied to solution of several industrial problems. + +OOFEM is trying to be one of the best FEM solvers. To make this a reality, we focus on this and do not try to provide extensive pre and post processing capabilities. Here we rely on third party external tools. + +OOFEM as a FEM solver solves the problems described by a set of partial differential equations. On input it expects the discretized domain and corresponding problem parameters, initial and boundary conditions. On output, it provides the primary unknown fields as well as other secondary fields of interest. The results can be exported in many ways to facilitate post-processing. + +OOFEM is free software, distributed under GNU LGPL license. + + + +General Features +---------------- +* Structural, heat & mass transfer, and CFD modules +* Support for parallel processing on shared and massively parallel machines, computer clusters, Dynamic load balancing +* Direct & iterative solvers (IML, Spooles, PETSc, SuperLU, Pardisso) +* Full restart capability, support for adaptive and staggered analyses +* Postprocessing: X-Windows post-processing, export to VTK +* Python bindings allowing to script oofem and implement new components in Python + + +Documentation +--------------------- +The extensive documentation is available on `OOFEM web pages `_: + +* Input manual, available in [`html `_] and [`PDF `_]. +* Element Library Manual, available in [`html `_] and [`PDF `_] +* Material Model Library Manual, available in [`html `_] and [`PDF `_] + +* Programmer's manual, available in [`html `_] and [`PDF `_]. +* The [`Reference manual `_] +* Python bindings documentation , available in [`html `_] and [`PDF `_] + + +OOFEM Ecosystem +--------------------- + +* `OOFEM forum `_ is the best place to ask questions and get support from developpers and user community. +* `OOFEM wiki `_ contains many useful resources, gallery of results and tutorials. +* `OOFEM gitHub repository `_. \ No newline at end of file diff --git a/doc/usermanual/make.bat b/doc/usermanual/make.bat new file mode 100644 index 000000000..2119f5109 --- /dev/null +++ b/doc/usermanual/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/doc/usermanual/postprocessing.rst b/doc/usermanual/postprocessing.rst new file mode 100644 index 000000000..a56e47add --- /dev/null +++ b/doc/usermanual/postprocessing.rst @@ -0,0 +1,41 @@ +.. _postprocessing: + +Postprocessing +============== + +By default, oofem produces output in the form of readable text file, called output file. +At the same time, oofem can produce output in other formats, that are more suitable for postprocessing in third-party tools. This is done by configuring one or more export modules in the input file. +In this short tutorial, we will cover vtk postprocessing. + +Configuring vtk export +---------------------- +VTK is a widely used format for storing simulation results. The vtk files can be opened in many visualization tools. +The export of results in vtk format can be done using ``vtkxml`` export module. +The number of export modules is defined in analysis record using ``nmodules`` keyword. The records for export modules should immediately follow analysis record. +The detailed syntax of ``vtkxml`` record is described in oofem input manual. +As an example, consider an example of 3-point bending test input file (located in `tests/benchmark/sm/concrete_3point.in `_) which we modify to add vtk export: + +:: + + concrete_3point.out + Test: 3-point bending, triangular elements, 1 loaded point + StaticStructural nsteps 4 solverType "calm" stepLength 0.025 rtolf 1e-4 Psi 0.0 MaxIter 200 reqIterations 80 HPC 2 1 2 stiffmode 1 nmodules 1 + vtkxml tstep_all dofman_all element_all primvars 1 1 vars 2 1 4 + ... + +The export has been requested for all solution steps ``tstep_all``, all dof managers (nodes) ``dofman_all`` and all elements ``element_all``. The primary variables exported consists of displacement vector: ``primvars 1 1``, where ``primvars`` is the keyword for primary variable export, what follows is an array of primary variables IDs (defined in `src/oofemlib/unknowntype.h `_), first number determines the array size. +The export of secondary (internal) variables consists of strain and stress tensors (``vars 2 1 4``, where internal variable codes are defined in `src/oofemlib/internalstatetype.h `_). + +After running the modified, extended input the solver will produce for each solution step ``vtu`` file. + +Postprocessing in paraview +-------------------------- +In this example, we will use Paraview (Open-source, multi-platform data analysis and visualization application, `www.paraview.org `_). +After installation of this tool, simply launch paraview and open one or all vtu files produced. + +.. image:: figs/concrete_3point.png + :width: 400 + :alt: Screenshot of paraview visualization + + + diff --git a/doc/usermanual/understandinginput.rst b/doc/usermanual/understandinginput.rst new file mode 100644 index 000000000..8dc3003ff --- /dev/null +++ b/doc/usermanual/understandinginput.rst @@ -0,0 +1,184 @@ +.. _understanding_input: + +Understanding input file +========================= + +The OOFEM input file fully describes the problem under consideration. Input file is a text file with specific structure, outlined below and fully documented in `OOFEM Input manual `_. + +The input file can be prepared manually by any text editor or generated by special purpose code, preprocessor or converter. + +Input file consists of several sections + +* Ordering of sections is compulsory +* Each section can consist of one or more records ( corresponding to lines) +* Each record starts with a keyword followed by compulsory or optional parameters +* Input file can contain comments (lines beginning with ‘#’ character) +* Long Input records (lines) can be splitted using continuation character at the end of each line ‘\\’ +* Content is not case sensitive + +An Example +^^^^^^^^^^ +Consider the linear elastic analysis of beam structure, as illustrated on + +.. image:: figs/input_beam_example.png + +The full input file `beam2d_1.in `_ listing is following: + +.. code-block:: + + beam2d_1.out + Simple Beam Structure - linear analysis + #only momentum influence to the displacements is taken into account + #beamShearCoeff is artificially enlarged. + StaticStructural nsteps 3 nmodules 0 + domain 2dBeam + OutputManager tstep_all dofman_all element_all + ndofman 6 nelem 5 ncrosssect 1 nmat 1 nbc 6 nic 0 nltf 3 nset 7 + node 1 coords 3 0. 0. 0. + node 2 coords 3 2.4 0. 0. + node 3 coords 3 3.8 0. 0. + node 4 coords 3 5.8 0. 1.5 + node 5 coords 3 7.8 0. 3.0 + node 6 coords 3 2.4 0. 3.0 + Beam2d 1 nodes 2 1 2 + Beam2d 2 nodes 2 2 3 DofsToCondense 1 6 + Beam2d 3 nodes 2 3 4 DofsToCondense 1 3 + Beam2d 4 nodes 2 4 5 + Beam2d 5 nodes 2 6 2 DofsToCondense 1 6 + SimpleCS 1 area 1.e8 Iy 0.0039366 beamShearCoeff 1.e18 thick 0.54 material 1 set 1 + IsoLE 1 d 1. E 30.e6 n 0.2 tAlpha 1.2e-5 + BoundaryCondition 1 loadTimeFunction 1 dofs 1 3 values 1 0.0 set 4 + BoundaryCondition 2 loadTimeFunction 1 dofs 1 5 values 1 0.0 set 5 + BoundaryCondition 3 loadTimeFunction 2 dofs 3 1 3 5 values 3 0.0 0.0 -0.006e-3 set 6 + ConstantEdgeLoad 4 loadTimeFunction 1 Components 3 0.0 10.0 0.0 loadType 3 set 3 + NodalLoad 5 loadTimeFunction 1 dofs 3 1 3 5 Components 3 -18.0 24.0 0.0 set 2 + StructTemperatureLoad 6 loadTimeFunction 3 Components 2 30.0 -20.0 set 7 + PeakFunction 1 t 1.0 f(t) 1. + PeakFunction 2 t 2.0 f(t) 1. + PeakFunction 3 t 3.0 f(t) 1. + Set 1 elementranges {(1 5)} + Set 2 nodes 1 4 + Set 3 elementedges 2 1 1 + Set 4 nodes 2 1 5 + Set 5 nodes 1 3 + Set 6 nodes 1 6 + Set 7 elements 2 1 2 + +The details explained +""""""""""""""""""""" + +The input file starts with ``output file record`` represented by a line containing the path to output file + +.. code-block:: + + beam2d_1.out + +Next, the ``job description record`` follows represented by a line with free text describing the problem + +.. code-block:: + + Simple Beam Structure - linear analysis + +Next record, called ``analysis record`` determines the problem to be solved. In our case we solve linear elastic problem represented by ``StaticStructural`` keyword. The analysis keyword has compulsory parameter ``nsteps`` determining in this case the number of time steps representing load cases in our example. + +.. code-block:: + + StaticStructural nsteps 3 + +Next, the domain type is described. At present version, the domain type is no longer relevant, but it is maintained for compatibility reasons. So we declare our domain type as 2dbeam. Note that oofem allows to combine different element types with different degrees of freedom per node. + +.. code-block:: + + domain 2dBeam + +The next record determines what the default output should contain. In our case, we require output for all time steps and all elements + +.. code-block:: + + OutputManager tstep_all dofman_all element_all + +The ``components size record`` determines the number of nodes, elements, cross-section and material models and other components describing the discretization and problem. + +.. code-block:: + + ndofman 6 nelem 5 ncrosssect 1 nmat 1 nbc 6 nic 0 nltf 3 nset 7 + +Here the ``ndofman`` determines the number of dof managers (nodes), the ``nelem`` determines the number of elements, ``ncrosssect`` determines the number of cross section models (oofem decouples the geometrical model of cross section from matterial model). The number of material models used is determined by ``nmat`` keyword. Number of boundary and initial conditions is determined by ``nbc`` and ``nic`` keywords, respectively. Number of functions, determining time variation or activity of certain component, is described using ``nltf`` keyword. Finally, number of sets, which are used to group entities into groups to assign for example material or boundary conditions, is determined by ``nset`` keyword. + +Next, the nodal records follow. The number of nodes has been determined in the ``components size record`` and so the input contains in our case 6 records (lines) for individual nodes. The nodal records start with ``node`` keyword followed by its label, which is later used to refer to specific node. Labels should be unique integer numbers. A number of optional or compulsory parameters follows. Compulsory parameters determine the nodal coordinates, for example. + +.. code-block:: + + node 1 coords 3 0. 0. 0. + node 2 coords 3 2.4 0. 0. + node 3 coords 3 3.8 0. 0. + node 4 coords 3 5.8 0. 1.5 + node 5 coords 3 7.8 0. 3.0 + node 6 coords 3 2.4 0. 3.0 + +Next, the element records follow. The number of elements has been specified in ``components size record`` and so the input contains in our case 5 records (lines) for individual elements. The element type is determined by element keyword at the beginning of each record. In our case, we use ``beam2d`` element type (Available element types are documented in `OOFEM Element manual `_. + +The element type keyword is followed by a compuslory parameters (determining the element nodes, for example) and optional parameters (in our case determining which element degrees of freedom to condense out to represent hinge type of connection). + +.. code-block:: + + Beam2d 1 nodes 2 1 2 + Beam2d 2 nodes 2 2 3 DofsToCondense 1 6 + Beam2d 3 nodes 2 3 4 DofsToCondense 1 3 + Beam2d 4 nodes 2 4 5 + Beam2d 5 nodes 2 6 2 DofsToCondense 1 6 + +After element records, the records describing cross-section models follow. In our example, the cross section consists of single cross section (same dimensions) made of single material, so we use integral cross section model, represented by ``SimpleCS`` keyword, which is followed by cross section model label (unique integer number) followed by parameters describing cross section dimensions and associated material model (``material`` keyword). The cross section model is associated to all elements in given set (``set keyword). + +.. code-block:: + + SimpleCS 1 area 1.e8 Iy 0.0039366 beamShearCoeff 1.e18 thick 0.54 material 1 set 1 + +Similar to cross section models, we follow with material models. IN our example we have a single linear isotropic material model, represented by ``isole`` keyword. This keyword is followed by a material model label (unique integer number) followed by a number of parameters determining material model parameters. + +.. code-block:: + + IsoLE 1 d 1. E 30.e6 n 0.2 tAlpha 1.2e-5 + +Next, we proceed with boundary conditions. In our example, we have 6 boundary conditions in total. The first one is Dirichlet type boundary condition, corresponding to fixed vertical displacement (prescribed is one nodal DOF corresponding to vertical displacement in z-direction: ``dofs 1 3``) enforced at nodes 1 and 5 (specified using ``set 4``) + +.. code-block:: + + BoundaryCondition 1 loadTimeFunction 1 dofs 1 3 values 1 0.0 set 4 + +The second boundary condition is fixed rotation in node 3. Yes, in node 3 we need to fix rotation, as both connected elements (2 and 3) have independent, condensed rotations, so that there is no rotation stiffness in node 3 and thus the nodal rotation has to be fixed. + +.. code-block:: + + BoundaryCondition 2 loadTimeFunction 1 dofs 1 5 values 1 0.0 set 5 + +The third boundary condition is used to enforce the clamped displacements and prescribed rotation at node 6. + +.. code-block:: + + BoundaryCondition 3 loadTimeFunction 2 dofs 3 1 3 5 values 3 0.0 0.0 -0.006e-3 set 6 + +The remaining three boundary condition represent applied constant edge load on element 1, concentrated loading at node 4, and temperature loading on element 1. + +.. code-block:: + + ConstantEdgeLoad 4 loadTimeFunction 1 Components 3 0.0 10.0 0.0 loadType 3 set 3 + NodalLoad 5 loadTimeFunction 1 dofs 3 1 3 5 Components 3 -18.0 24.0 0.0 set 2 + StructTemperatureLoad 6 loadTimeFunction 3 Components 2 30.0 -20.0 set 7 + +What follows is ``function section`` defining the functions. They are attributes of several components (boundary conditions, for example) and define, how the things evolve in time or space. In this example, the functions are only functions of time, determining the time evolution of boundary condition values. +The example is divided into three load cases, in the first load case only force loading is taken into account, so all force loads (labels 4 and 5) have the first function associated (using ``loadTimeFunction`` keyword) which is nonzero in the first time increment and zero otherwise. Similarly, the prescribed rotation is applied exclusively in second loading step and temperature loading in the third. + +The input is finally concluded with defining the sets, that are used to define group of nodes, elements, element edges, etc, on which the boundary conditions or cross sections are applied. + +.. code-block:: + + Set 1 elementranges {(1 5)} + Set 2 nodes 1 4 + Set 3 elementedges 2 1 1 + Set 4 nodes 2 1 5 + Set 5 nodes 1 3 + Set 6 nodes 1 6 + Set 7 elements 2 1 2 + +For more information about the input file structure, please follow `OOFEM Input manual `_. \ No newline at end of file diff --git a/doc/usermanual/understandingoutput.rst b/doc/usermanual/understandingoutput.rst new file mode 100644 index 000000000..9993411d3 --- /dev/null +++ b/doc/usermanual/understandingoutput.rst @@ -0,0 +1,146 @@ +.. _understanding_output: + +Understanding output file +========================= + +By default, oofem produces output in the form of readable text file, called output file. +Its content can be controlled to some extend in ``OutputManager`` record of input file. One can filter output for selected solution steps, and specific sets of nodes and elements, for example. + +An Example +^^^^^^^^^^ +Consider the same linear elastic analysis of beam structure, as in previous section. +We first run the solver with the example + +.. code-block:: bash + + $ ./oofem -f /home/user/oofem.git/tests/sm/beam2d_1.in + +Upon the successful execution, the text output file containing simulation results is created (the name of output file is specified in input file). In our case, the ``beam2d_1.out`` file is created in the current working directory. +The output file can be inspected by any text editor. + +Header section +-------------- +Every output file starts with Header containing information on solver version, job name and +starting date and time of the analysis + +:: + + ############################################################## www.oofem.org ### + #### #### ###### ###### # # + # # # # # # ## ## + # # # # ##### ##### # ## # + # # # # # # # # + # # # # # # # # OOFEM ver. 2.6 + #### #### # ###### # # Copyright (C) 1994-2020 Borek Patzak + ################################################################################ + + + Starting analysis on: Wed Jun 9 09:32:17 2021 + + Homework www sm40 no. 1 + +Solution step section(s) +------------------------ +The output file continues with output for each solution step of the analysis. +This consists of simple header indicating the solution step time + +:: + + ============================================================== + Output for time 1.00000000e+00 + ============================================================== + +The output for solution step consists of output of problem domain(s) + +:: + + Output for domain 1 + +consisting of output for all nodes and elements. We start with nodal output. +The output for each node starts with ``Node`` keyword, followed by node label and number (in parenthesis). +This is followed by indented block containing the output for every degree of freedom of the node. +DOF meaning is identified by a integer code after ``dof`` keyword. The codes are defined by DofIDItem enum. +For example, the mechanical unknowns have following codes: ``1`` for displacement in x direction, ``2`` for displacement in y direction, ``3`` for displacement in z direction, ``4`` for rotation around x axis, ``5`` for rotation around y axis and ``6`` for rotation around z axis (see src/oofemlib/dofiditem.h for full definition). +Our 2D beam structure is in xz plane, so the relevant DOFs are displacement in x, displacement in z and rotation around y, corresponding to DOF codes 1,3,5. +The ``d`` code dof output means that actual value is printed, for some analyses, also velocities and accelerations of the corresponding unknown can be printed. + +:: + + DofManager output: + ------------------ + Node 1 ( 1): + dof 1 d -1.37172495e-03 + dof 3 d 0.00000000e+00 + dof 5 d -2.38787802e-05 + Node 2 ( 2): + dof 1 d -1.37172495e-03 + dof 3 d 2.03123137e-14 + dof 5 d -1.01549259e-06 + Node 3 ( 3): + dof 1 d -1.37172495e-03 + dof 3 d 4.20823351e-05 + dof 5 d 0.00000000e+00 + Node 4 ( 4): + dof 1 d -1.75286359e-03 + dof 3 d 5.50267187e-04 + dof 5 d 1.05205838e-05 + Node 5 ( 5): + dof 1 d -1.34016320e-03 + dof 3 d 0.00000000e+00 + dof 5 d 4.07440098e-04 + Node 6 ( 6): + dof 1 d 0.00000000e+00 + dof 3 d 0.00000000e+00 + dof 5 d -0.00000000e+00 + +The nodal output is followed by element output. The actual format depends on particular +element, but generally internal variables at each integration point are +reported. In case of beam element, the local displacements and end forces are printed as well. + +:: + + Element output: + --------------- + beam element 1 ( 1) : + local displacements -1.3717e-03 0.0000e+00 -2.3879e-05 -1.3717e-03 2.0312e-14 -1.0155e-06 + local end forces 0.0000e+00 -8.9375e+00 0.0000e+00 0.0000e+00 -1.5062e+01 -7.3499e+00 + GP 1.1 : strains 0.0000e+00 0.0000e+00 0.0000e+00 3.6323e-05 0.0000e+00 0.0000e+00 -2.4500e-33 0.0000e+00 + stresses 0.0000e+00 0.0000e+00 0.0000e+00 4.2897e+00 0.0000e+00 0.0000e+00 -3.0625e+00 0.0000e+00 + GP 1.2 : strains 0.0000e+00 0.0000e+00 0.0000e+00 2.0106e-05 0.0000e+00 0.0000e+00 -2.4500e-33 0.0000e+00 + stresses 0.0000e+00 0.0000e+00 0.0000e+00 2.3745e+00 0.0000e+00 0.0000e+00 -3.0625e+00 0.0000e+00 + GP 1.3 : strains 0.0000e+00 0.0000e+00 0.0000e+00 -1.0531e-06 0.0000e+00 0.0000e+00 -2.4500e-33 0.0000e+00 + stresses 0.0000e+00 0.0000e+00 0.0000e+00 -1.2437e-01 0.0000e+00 0.0000e+00 -3.0625e+00 0.0000e+00 + GP 1.4 : strains 0.0000e+00 0.0000e+00 0.0000e+00 -1.7270e-05 0.0000e+00 0.0000e+00 -2.4500e-33 0.0000e+00 + stresses 0.0000e+00 0.0000e+00 0.0000e+00 -2.0396e+00 0.0000e+00 0.0000e+00 -3.0625e+00 0.0000e+00 + ... + +For structural analyses the reaction table is reported: + +:: + + R E A C T I O N S O U T P U T: + _______________________________ + + Node 1 iDof 3 reaction -8.9375e+00 [bc-id: 1] + Node 3 iDof 5 reaction 0.0000e+00 [bc-id: 2] + Node 5 iDof 3 reaction -1.8750e+01 [bc-id: 1] + Node 6 iDof 1 reaction 1.8000e+01 [bc-id: 3] + Node 6 iDof 3 reaction -2.0312e+01 [bc-id: 3] + Node 6 iDof 5 reaction -5.3999e+01 [bc-id: 3] + +Finally, the solution time for every time step is reported. + +:: + + User time consumed by solution step 1: 0.004 [s] + +The output is then repeated for each solution step of the problem. +Finally, the accumulated total solution time is reported. + +:: + + Finishing analysis on: Wed Jun 9 09:32:17 2021 + + Real time consumed: 000h:00m:00s + User time consumed: 000h:00m:00s + diff --git a/extern/pybind11 b/extern/pybind11 new file mode 160000 index 000000000..ffa346860 --- /dev/null +++ b/extern/pybind11 @@ -0,0 +1 @@ +Subproject commit ffa346860b306c9bbfb341aed9c14c067751feb8 diff --git a/src/dss/DSSAfx.h b/src/dss/DSSAfx.h index 511c870cd..df15e188b 100644 --- a/src/dss/DSSAfx.h +++ b/src/dss/DSSAfx.h @@ -52,10 +52,7 @@ #include #include #include - -#ifndef min - #define min(a, b) ( ( a ) < ( b ) ? ( a ) : ( b ) ) -#endif +#include #define DSS_NAMESPASE_BEGIN #define DSS_NAMESPASE_END diff --git a/src/dss/SparseConectivityMtx.cpp b/src/dss/SparseConectivityMtx.cpp index ea57e0185..43a7bddc7 100644 --- a/src/dss/SparseConectivityMtx.cpp +++ b/src/dss/SparseConectivityMtx.cpp @@ -822,7 +822,7 @@ long MD_Qqraph :: ApproximateMinumumDegree(long i, IntArrayList &Lp) } } - long d = min(n - this->no_elements, degrees [ i ] + Lpc); + long d = std::min(n - this->no_elements, degrees [ i ] + Lpc); long Les = 0; //foreach(long e in E[i]) if (amd_w[e]<0) Les += L[e].Length; else Les += amd_w[e]; @@ -835,7 +835,7 @@ long MD_Qqraph :: ApproximateMinumumDegree(long i, IntArrayList &Lp) } } - d = min(d, Aic + Lpc + Les); + d = std::min(d, Aic + Lpc + Les); if ( MinDegB > d && IsFree(i) ) { MinDegB = d; @@ -1233,7 +1233,7 @@ IntArrayList *MD_Qqraph :: GenerateMD(bool approximate_degree, IntArrayList *fix } } else { while ( no_elements < n ) { - long MinimDeg = min(MinDegB, MinDegA); + long MinimDeg = std::min(MinDegB, MinDegA); MinDegB = n; MinDegC = n; diff --git a/src/dss/dssmatrix.C b/src/dss/dssmatrix.C index 41e9e5558..7e9252172 100644 --- a/src/dss/dssmatrix.C +++ b/src/dss/dssmatrix.C @@ -42,7 +42,6 @@ #include "sparsemtrxtype.h" #include "classfactory.h" #include "activebc.h" -#include "DSSolver.h" #include @@ -52,29 +51,13 @@ REGISTER_SparseMtrx( DSSMatrixLDL, SMT_DSS_sym_LDL); REGISTER_SparseMtrx( DSSMatrixLL, SMT_DSS_sym_LL); REGISTER_SparseMtrx( DSSMatrixLU, SMT_DSS_unsym_LU); -DSSMatrix :: DSSMatrix(dssType _t) : SparseMtrx(), _dss(new DSSolver()) -{ - eDSSolverType _st = eDSSFactorizationLDLT; - _type = _t; - if ( _t == sym_LDL ) { - _st = eDSSFactorizationLDLT; - } else if ( _t == sym_LL ) { - _st = eDSSFactorizationLLT; - } else if ( _t == unsym_LU ) { - _st = eDSSFactorizationLU; - } else { - OOFEM_ERROR("unknown dssType"); - } - _dss->Initialize(0, _st); - isFactorized = false; -} - - -DSSMatrix :: DSSMatrix(dssType _t, int n) : SparseMtrx(n, n), _dss(new DSSolver()) +DSSMatrix :: DSSMatrix(dssType _t, int n) : SparseMtrx(n, n), + _dss(std::make_unique()), + isFactorized(false), + _type(_t) { eDSSolverType _st = eDSSFactorizationLDLT; - _type = _t; if ( _t == sym_LDL ) { _st = eDSSFactorizationLDLT; } else if ( _t == sym_LL ) { @@ -86,12 +69,8 @@ DSSMatrix :: DSSMatrix(dssType _t, int n) : SparseMtrx(n, n), _dss(new DSSolver( } _dss->Initialize(0, _st); - isFactorized = false; } -DSSMatrix :: ~DSSMatrix() -{ -} /*****************************/ /* Copy constructor */ @@ -102,33 +81,25 @@ DSSMatrix :: DSSMatrix(const DSSMatrix &S) : SparseMtrx(S.nRows, S.nColumns) OOFEM_ERROR("not implemented"); } -SparseMtrx *DSSMatrix :: GiveCopy() const -{ - OOFEM_ERROR("not implemented"); - return NULL; -} void DSSMatrix :: times(const FloatArray &x, FloatArray &answer) const { - // Note: not really eficient. The sparse matrix is assembled directly into its block structure, - // which is efficient for factorization, but unfortunately not efficient for implementing the multiplication, - // as the blocks have to be identified (see implementation of ElementAt method) when traversing rows - // Also note, that this method will yield correct results only before factorization, after that the blocks - // contain factorized matrix. - - int i, j, dim; - - dim = this->_sm->neq; - - answer.resize(dim); - answer.zero(); - - for (i = 1; i <= dim; i++) { - for (j = 1; j <= dim; j++) - { - answer.at(i) += _dss->ElementAt(i - 1, j - 1) * x.at(j); - } - } + // Note: not really eficient. The sparse matrix is assembled directly into its block structure, + // which is efficient for factorization, but unfortunately not efficient for implementing the multiplication, + // as the blocks have to be identified (see implementation of ElementAt method) when traversing rows + // Also note, that this method will yield correct results only before factorization, after that the blocks + // contain factorized matrix. + + int dim = this->_sm->neq; + + answer.resize(dim); + answer.zero(); + + for ( int i = 1; i <= dim; i++) { + for ( int j = 1; j <= dim; j++) { + answer.at(i) += _dss->ElementAt(i - 1, j - 1) * x.at(j); + } + } } void DSSMatrix :: times(double x) @@ -143,9 +114,7 @@ int DSSMatrix :: buildInternalStructure(EngngModel *eModel, int di, const Unknow int neq = eModel->giveNumberOfDomainEquations(di, s); unsigned long indx; // allocation map - std :: vector< std :: set< int > >columns(neq); - - unsigned long nz_ = 0; + std :: vector< IntArray > columns(neq); for ( auto &elem : domain->giveElements() ) { elem->giveLocationArray(loc, s); @@ -154,20 +123,18 @@ int DSSMatrix :: buildInternalStructure(EngngModel *eModel, int di, const Unknow if ( ii > 0 ) { for ( int jj : loc ) { if ( jj > 0 ) { - columns [ jj - 1 ].insert(ii - 1); + columns [ jj - 1 ].insertSortedOnce(ii - 1); } } } } } - // loop over active boundary conditions - std::vector r_locs; - std::vector c_locs; - for ( auto &gbc : domain->giveBcs() ) { ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() ); - if ( bc != NULL ) { + if ( bc ) { + std::vector r_locs; + std::vector c_locs; bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s); for (std::size_t k = 0; k < r_locs.size(); k++) { IntArray &krloc = r_locs[k]; @@ -176,7 +143,7 @@ int DSSMatrix :: buildInternalStructure(EngngModel *eModel, int di, const Unknow if ( ii > 0 ) { for ( int jj : kcloc ) { if ( jj > 0 ) { - columns [ jj - 1 ].insert(ii - 1); + columns [ jj - 1 ].insertSortedOnce(ii - 1); } } } @@ -184,9 +151,10 @@ int DSSMatrix :: buildInternalStructure(EngngModel *eModel, int di, const Unknow } } } - + + unsigned long nz_ = 0; for ( int i = 0; i < neq; i++ ) { - nz_ += columns [ i ].size(); + nz_ += columns [ i ].giveSize(); } rowind_.reset( new unsigned long [ nz_ ]); @@ -309,9 +277,9 @@ int DSSMatrix :: buildInternalStructure(EngngModel *eModel, int di, const Unknow if ( dof->isPrimaryDof() ) { _neq = dof->giveEquationNumber(s); if ( _neq > 0 ) { - mcn [ _c++ ] = _neq - 1; + mcn [ _c++ ] = _neq - 1; } else { - mcn [ _c++ ] = -1; // no corresponding row in sparse mtrx structure + mcn [ _c++ ] = -1; // no corresponding row in sparse mtrx structure } } } @@ -321,7 +289,7 @@ int DSSMatrix :: buildInternalStructure(EngngModel *eModel, int di, const Unknow } } } - + if ( _succ ) { _dss->SetMatrixPattern(_sm.get(), bsize); _dss->LoadMCN(ndofmans+ndofmansbc+nInternalElementDofMans, bsize, mcn); @@ -346,24 +314,20 @@ int DSSMatrix :: buildInternalStructure(EngngModel *eModel, int di, const Unknow int DSSMatrix :: assemble(const IntArray &loc, const FloatMatrix &mat) { - int i, j, ii, jj, dim; + int dim = mat.giveNumberOfRows(); - # ifdef DEBUG - dim = mat.giveNumberOfRows(); +# ifdef DEBUG if ( dim != loc.giveSize() ) { OOFEM_ERROR("dimension of 'k' and 'loc' mismatch"); } - # endif - dim = mat.giveNumberOfRows(); - if ( _type == unsym_LU ) { - for ( j = 1; j <= dim; j++ ) { - jj = loc.at(j); + for ( int j = 1; j <= dim; j++ ) { + int jj = loc.at(j); if ( jj ) { - for ( i = 1; i <= dim; i++ ) { - ii = loc.at(i); + for ( int i = 1; i <= dim; i++ ) { + int ii = loc.at(i); if ( ii ) { _dss->ElementAt(ii - 1, jj - 1) += mat.at(i, j); } @@ -371,11 +335,11 @@ int DSSMatrix :: assemble(const IntArray &loc, const FloatMatrix &mat) } } } else { // symmetric pattern - for ( j = 1; j <= dim; j++ ) { - jj = loc.at(j); + for ( int j = 1; j <= dim; j++ ) { + int jj = loc.at(j); if ( jj ) { - for ( i = 1; i <= dim; i++ ) { - ii = loc.at(i); + for ( int i = 1; i <= dim; i++ ) { + int ii = loc.at(i); if ( ii ) { if ( jj > ii ) { continue; @@ -388,7 +352,6 @@ int DSSMatrix :: assemble(const IntArray &loc, const FloatMatrix &mat) } } - // increment version this->version++; return 1; @@ -396,12 +359,8 @@ int DSSMatrix :: assemble(const IntArray &loc, const FloatMatrix &mat) int DSSMatrix :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) { - int dim1, dim2; - - // this->checkSizeTowards(rloc, cloc); - - dim1 = mat.giveNumberOfRows(); - dim2 = mat.giveNumberOfColumns(); + int dim1 = mat.giveNumberOfRows(); + int dim2 = mat.giveNumberOfColumns(); if ( _type == unsym_LU ) { for ( int i = 1; i <= dim1; i++ ) { int ii = rloc.at(i); @@ -428,7 +387,6 @@ int DSSMatrix :: assemble(const IntArray &rloc, const IntArray &cloc, const Floa } } - // increment version this->version++; return 1; @@ -438,7 +396,6 @@ void DSSMatrix :: zero() { _dss->LoadZeros(); - // increment version this->version++; isFactorized = false; } @@ -466,7 +423,6 @@ void DSSMatrix :: solve(FloatArray &b, FloatArray &x) double &DSSMatrix :: at(int i, int j) { - // increment version this->version++; return _dss->ElementAt(i - 1, j - 1); } @@ -484,7 +440,6 @@ double DSSMatrix :: operator() (int i, int j) const double &DSSMatrix :: operator() (int i, int j) { - // increment version this->version++; return _dss->ElementAt(i, j); } diff --git a/src/dss/dssmatrix.h b/src/dss/dssmatrix.h index cd1990c1a..6fc6a19e1 100644 --- a/src/dss/dssmatrix.h +++ b/src/dss/dssmatrix.h @@ -38,10 +38,12 @@ #include "sparsemtrx.h" #include "intarray.h" #include "floatarray.h" +#include "DSSolver.h" +#include "SparseMatrixF.h" #include -#include +#define _IFT_DSSMatrix_Name "dss" /* DSS module lives in global namespace, not in oofem namespace */ class DSSolver; @@ -87,35 +89,27 @@ class OOFEM_EXPORT DSSMatrix : public SparseMtrx * @param n Size of row and columns of square matrix * @see buildInternalStructure */ - DSSMatrix(dssType t, int n); - /** - * Constructor. Before any operation an internal profile must be built. - * @param t Storage type - * @see buildInternalStructure - */ - DSSMatrix(dssType t); + DSSMatrix(dssType t, int n=0); /// Copy constructor DSSMatrix(const DSSMatrix &S); /// Destructor - virtual ~DSSMatrix(); - - // Overloaded methods - virtual SparseMtrx *GiveCopy() const; - virtual void times(const FloatArray &x, FloatArray &answer) const; - virtual void times(double x); - virtual int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme & s); - virtual int assemble(const IntArray &loc, const FloatMatrix &mat); - virtual int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat); - virtual bool canBeFactorized() const { return true; } - virtual SparseMtrx *factorized(); - virtual void solve(FloatArray &b, FloatArray &x); - virtual void zero(); - virtual double &at(int i, int j); - virtual double at(int i, int j) const; - virtual SparseMtrxType giveType() const { return SMT_SymCompCol; } - virtual bool isAsymmetric() const { return false; } - - virtual const char *giveClassName() const { return "DSSMatrix"; } + virtual ~DSSMatrix() {} + + void times(const FloatArray &x, FloatArray &answer) const override; + void times(double x) override; + int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme & s) override; + int assemble(const IntArray &loc, const FloatMatrix &mat) override; + int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) override; + bool canBeFactorized() const override { return true; } + SparseMtrx *factorized() override; + void solve(FloatArray &b, FloatArray &x); + void zero() override; + double &at(int i, int j) override; + double at(int i, int j) const override; + SparseMtrxType giveType() const override { return SMT_SymCompCol; } + bool isAsymmetric() const override { return false; } + + const char *giveClassName() const override { return "DSSMatrix"; } }; class DSSMatrixLDL : public DSSMatrix diff --git a/src/dss/dsssolver.C b/src/dss/dsssolver.C index 3584677e8..a3348d75f 100644 --- a/src/dss/dsssolver.C +++ b/src/dss/dsssolver.C @@ -34,7 +34,6 @@ #include "dsssolver.h" #include "classfactory.h" - #include "dssmatrix.h" #include "timer.h" diff --git a/src/dss/dsssolver.h b/src/dss/dsssolver.h index e306e8d8e..1c8265b49 100644 --- a/src/dss/dsssolver.h +++ b/src/dss/dsssolver.h @@ -35,9 +35,12 @@ #ifndef dsssolver_h #define dsssolver_h +#include "oofemcfg.h" #include "sparselinsystemnm.h" #include "sparsemtrx.h" +#define _IFT_DSSSolver_Name "dss" + namespace oofem { class Domain; class EngngModel; @@ -62,20 +65,11 @@ class OOFEM_EXPORT DSSSolver : public SparseLinearSystemNM /// Destructor. virtual ~DSSSolver(); - /** - * Solves the given linear system by @f$L\cdot D\cdot L^{\mathrm{T}}@f$ factorization. - * Implementation rely on factorization support provided by mapped sparse matrix. - * It calls Lhs->factorized()->backSubstitutionWith(*solutionArray). Sets solved flag to 1 if o.k. - * @param A Coefficient matrix. - * @param b Right hand side. - * @param x Solution array. - * @return NM_Status value. - */ - virtual NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x); + NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x) override; - virtual const char *giveClassName() const { return "DSSSolver"; } - virtual LinSystSolverType giveLinSystSolverType() const { return ST_DSS; } - virtual SparseMtrxType giveRecommendedMatrix(bool symmetric) const { return symmetric ? SMT_DSS_sym_LDL : SMT_DSS_unsym_LU; } ///@todo Check + const char *giveClassName() const override { return "DSSSolver"; } + LinSystSolverType giveLinSystSolverType() const override { return ST_DSS; } + SparseMtrxType giveRecommendedMatrix(bool symmetric) const override { return symmetric ? SMT_DSS_sym_LDL : SMT_DSS_unsym_LU; } ///@todo Check }; } // end namespace oofem diff --git a/src/fm/CMakeLists.txt b/src/fm/CMakeLists.txt index c2695e240..41b665157 100644 --- a/src/fm/CMakeLists.txt +++ b/src/fm/CMakeLists.txt @@ -30,21 +30,18 @@ set (fm_element set (fm_material fluidcrosssection.C - newtonianfluid.C - fe2fluidmaterial.C - nonlinearfluidmaterial.C + Materials/newtonianfluid.C + Materials/fe2fluidmaterial.C + Materials/nonlinearfluidmaterial.C + Materials/fluiddynamicmaterial.C + Materials/twofluidmaterial.C + Materials/binghamfluid2.C ) set (fm_loads tractionpressurebc.C ) -set (fm_status - fluiddynamicmaterial.C - twofluidmaterial.C - binghamfluid2.C - ) - set (fm_interface leplic.C ) @@ -77,7 +74,6 @@ set (fm ${fm_emodel} ${fm_element} ${fm_material} - ${fm_status} ${fm_loads} ${fm_interface} ${fm_levelset} diff --git a/src/fm/Materials/binghamfluid2.C b/src/fm/Materials/binghamfluid2.C new file mode 100644 index 000000000..ec025fc4f --- /dev/null +++ b/src/fm/Materials/binghamfluid2.C @@ -0,0 +1,415 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "fm/Materials/binghamfluid2.h" +#include "fm/Materials/fluiddynamicmaterial.h" +#include "domain.h" +#include "floatmatrix.h" +#include "gausspoint.h" +#include "engngm.h" +#include "mathfem.h" +#include "datastream.h" +#include "contextioerr.h" +#include "dynamicinputrecord.h" +#include "classfactory.h" + +#include + +namespace oofem { +#define BINGHAM_ALT 1 +#define BINGHAM_MIN_SHEAR_RATE 1.e-10 + +REGISTER_Material(BinghamFluidMaterial2); +///@todo Remove the alternative ID. Just stick to "binghamfluid". +// static bool __dummy_BinghamFluidMaterial2_alt __attribute__((unused)) = GiveClassFactory().registerMaterial("binghamfluid2", matCreator< BinghamFluidMaterial2 > ); +REGISTER_Material_Alt(BinghamFluidMaterial2, binghamfluid2); + +BinghamFluidMaterial2 :: BinghamFluidMaterial2(int n, Domain *d) : FluidDynamicMaterial(n, d) +{ } + + +void +BinghamFluidMaterial2 :: initializeFrom(InputRecord &ir) +{ + FluidDynamicMaterial :: initializeFrom(ir); + // we use rather object's member data than to store data into slow + // key-val dictionary with lot of memory allocations + IR_GIVE_FIELD(ir, mu_0, _IFT_BinghamFluidMaterial2_mu0); + IR_GIVE_FIELD(ir, tau_0, _IFT_BinghamFluidMaterial2_tau0); + mu_inf = 1.e6; + IR_GIVE_OPTIONAL_FIELD(ir, mu_inf, _IFT_BinghamFluidMaterial2_muinf); + stressGrowthRate = BINGHAM_DEFAULT_STRESS_GROWTH_RATE; + IR_GIVE_OPTIONAL_FIELD(ir, stressGrowthRate, _IFT_BinghamFluidMaterial2_stressGrowthRate); + tau_c = tau_0 * mu_inf / ( mu_inf - mu_0 ); + //tau_c = tau_0; +} + + +void +BinghamFluidMaterial2 :: giveInputRecord(DynamicInputRecord &input) +{ + FluidDynamicMaterial :: giveInputRecord(input); + input.setField(this->mu_0, _IFT_BinghamFluidMaterial2_mu0); + input.setField(this->tau_0, _IFT_BinghamFluidMaterial2_tau0); + input.setField(this->mu_inf, _IFT_BinghamFluidMaterial2_muinf); + input.setField(this->stressGrowthRate, _IFT_BinghamFluidMaterial2_stressGrowthRate); +} + +double +BinghamFluidMaterial2 :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const +{ + BinghamFluidMaterial2Status *status = static_cast< BinghamFluidMaterial2Status * >( this->giveStatus(gp) ); + //double temp_tau=status->giveTempDevStressMagnitude(); + //double temp_gamma=status->giveTempDevStrainMagnitude(); + //determine actual viscosity + //return this->computeActualViscosity(temp_tau, temp_gamma); +#ifdef BINGHAM_ALT + double gamma = status->giveTempDevStrainMagnitude(); //status->giveTempDevStrainMagnitude(); + return computeActualViscosity(tau_0, gamma); + + #if 0 + const FloatArray &epsd = status->giveTempDeviatoricStrainVector(); //status->giveTempDeviatoricStrainVector(); + double gamma2 = gamma * gamma; + double dmudg, dgde1, dgde2, dgde3, mu; + if ( gamma < BINGHAM_MIN_SHEAR_RATE ) { + dmudg = dgde1 = dgde2 = dgde3 = 0.0; + mu = computeActualViscosity(tau_0, gamma); + } else { + dmudg = ( -1.0 ) * tau_0 * ( 1.0 - exp(-this->stressGrowthRate * gamma) ) / gamma2 + + tau_0 *this->stressGrowthRate *exp(-this->stressGrowthRate *gamma) / gamma; + mu = mu_0 + tau_0 * ( 1. - exp(-this->stressGrowthRate * gamma) ) / gamma; + + dgde1 = 2.0 * fabs( epsd.at(1) ) / gamma; + dgde2 = 2.0 * fabs( epsd.at(2) ) / gamma; + dgde3 = 1.0 * fabs( epsd.at(3) ) / gamma; + } + + return min( min( ( epsd.at(1) * dmudg * dgde1 + mu ), ( epsd.at(2) * dmudg * dgde2 + mu ) ), + ( epsd.at(3) * dmudg * dgde3 + mu ) ); + + #endif + +#else + if ( temp_tau < tau_c ) { + return mu_inf; + } else { + return mu_0; + } + +#endif +} + + +double +BinghamFluidMaterial2 :: give(int aProperty, GaussPoint *gp) const +{ + if ( aProperty == Viscosity ) { + return mu_0; + } else if ( aProperty == YieldStress ) { + return tau_0; + } else { + return FluidDynamicMaterial :: give(aProperty, gp); + } +} + + +MaterialStatus * +BinghamFluidMaterial2 :: CreateStatus(GaussPoint *gp) const +{ + return new BinghamFluidMaterial2Status(gp); +} + + +FloatArrayF<6> +BinghamFluidMaterial2 :: computeDeviatoricStress3D(const FloatArrayF<6> &eps, GaussPoint *gp, TimeStep *tStep) const +{ + BinghamFluidMaterial2Status *status = static_cast< BinghamFluidMaterial2Status * >( this->giveStatus(gp) ); + + // determine actual viscosity + auto epsd = this->computeDeviatoricStrain(eps); + // determine shear strain magnitude + double gamma = this->computeDevStrainMagnitude(epsd); + +#ifdef BINGHAM_ALT + double nu = computeActualViscosity(tau_0, gamma); + auto stress = this->computeDeviatoricStress(epsd, nu); + double tau = this->computeDevStressMagnitude(stress); + + //printf ("nu %e gamma %e\n", nu, gamma); +#else + // compute trial state + auto stress = this->computeDeviatoricStress(epsd, this->mu_inf); + // check if state allowed + double tau = this->computeDevStressMagnitude(stress); + if ( tau > this->tau_c ) { + double nu = this->computeActualViscosity(tau, gamma); + auto stress = this->computeDeviatoricStress(stress, epsd, nu); + tau = this->computeDevStressMagnitude(stress); + } + +#endif + // update status + status->letTempDeviatoricStrainVectorBe(epsd); + status->letDeviatoricStressVectorBe(stress); + status->letTempDevStrainMagnitudeBe(gamma); + status->letTempDevStressMagnitudeBe(tau); + + return stress; +} + +FloatMatrixF<6,6> +BinghamFluidMaterial2 :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + BinghamFluidMaterial2Status *status = static_cast< BinghamFluidMaterial2Status * >( this->giveStatus(gp) ); + const auto &epsd = status->giveTempDeviatoricStrainVector(); + double gamma = status->giveTempDevStrainMagnitude(); + + FloatMatrixF<6,6> d; + double mu; + if ( gamma < BINGHAM_MIN_SHEAR_RATE ) { + mu = computeActualViscosity(tau_0, gamma); + } else { + double dmudg = - tau_0 * ( 1.0 - exp(-this->stressGrowthRate * gamma) ) / (gamma * gamma) + + tau_0 * this->stressGrowthRate * exp(-this->stressGrowthRate * gamma) / gamma; + mu = mu_0 + tau_0 * ( 1. - exp(-this->stressGrowthRate * gamma) ) / gamma; + + FloatArrayF<6> dgde = { + 2.0 * epsd.at(1) / gamma, + 2.0 * epsd.at(2) / gamma, + 2.0 * epsd.at(3) / gamma, + 1.0 * epsd.at(4) / gamma, + 1.0 * epsd.at(5) / gamma, + 1.0 * epsd.at(6) / gamma, + }; + + for ( int i = 1; i <= 6; i++ ) { + d.at(1, i) = std::abs( 2.0 * epsd.at(1) * dmudg * dgde.at(i) ); + d.at(2, i) = std::abs( 2.0 * epsd.at(2) * dmudg * dgde.at(i) ); + d.at(3, i) = std::abs( 2.0 * epsd.at(3) * dmudg * dgde.at(i) ); + d.at(4, i) = std::abs( epsd.at(4) * dmudg * dgde.at(i) ); + d.at(5, i) = std::abs( epsd.at(5) * dmudg * dgde.at(i) ); + d.at(6, i) = std::abs( epsd.at(6) * dmudg * dgde.at(i) ); + } + } + + d.at(1, 1) += 2.0 * mu; + d.at(2, 2) += 2.0 * mu; + d.at(3, 3) += 2.0 * mu; + d.at(4, 4) += mu; + d.at(5, 5) += mu; + d.at(6, 6) += mu; + return d; +} + + +int +BinghamFluidMaterial2 :: checkConsistency() +{ + if ( domain->giveEngngModel()->giveEquationScalingFlag() ) { + double scale = domain->giveEngngModel()->giveVariableScale(VST_Density); + propertyDictionary.at('d') /= scale; + + scale = domain->giveEngngModel()->giveVariableScale(VST_Viscosity); + this->mu_0 /= scale; + this->tau_0 /= scale; + } + + return 1; +} + +double +BinghamFluidMaterial2 :: computeActualViscosity(double tau, double shearRate) const +{ +#ifdef BINGHAM_ALT + if ( tau_0 > 0.0 ) { + shearRate = max(shearRate, BINGHAM_MIN_SHEAR_RATE); + return ( mu_0 + tau_0 * ( 1. - exp(-this->stressGrowthRate * shearRate) ) / shearRate ); + } else { + // newtonian flow + return mu_0; + } + +#else + if ( tau <= tau_c ) { + return this->mu_inf; + } else { + return mu_0 + ( tau_0 / shearRate ); + } + +#endif +} + + +double +BinghamFluidMaterial2 :: computeDevStrainMagnitude(const FloatArrayF<6> &epsd) +{ + double val = 2.0 * ( epsd[0] * epsd[0] + epsd[1] * epsd[1] + epsd[2] * epsd[2] ) + + epsd[3] * epsd[3] + epsd[4] * epsd[4] + epsd[5] * epsd[5]; + return sqrt(val); +} + +double +BinghamFluidMaterial2 :: computeDevStressMagnitude(const FloatArrayF<6> &sigd) +{ + double val = 0.5 * ( sigd[0] * sigd[0] + sigd[1] * sigd[1] + sigd[2] * sigd[2] + + 2.0 * (sigd[3] * sigd[3] + sigd[4] * sigd[4] + sigd[5] * sigd[5]) ); + return sqrt(val); +} + +FloatArrayF<6> +BinghamFluidMaterial2 :: computeDeviatoricStrain(const FloatArrayF<6> &eps) +{ + //double ekk=(eps.at(1)+eps.at(2)+eps.at(3))/3.0; + double ekk = 0.0; + return { + eps[0] - ekk, + eps[1] - ekk, + eps[2] - ekk, + eps[3], + eps[4], + eps[5] + }; +} + + +FloatArrayF<6> +BinghamFluidMaterial2 :: computeDeviatoricStress(const FloatArrayF<6> &deps, double nu) +{ + return { + 2.0 * nu * ( deps[0] ), + 2.0 * nu * ( deps[1] ), + 2.0 * nu * ( deps[2] ), + deps[3] * nu, + deps[4] * nu, + deps[5] * nu + }; +} + + +BinghamFluidMaterial2Status :: BinghamFluidMaterial2Status(GaussPoint *g) : + FluidDynamicMaterialStatus(g) +{} + +void +BinghamFluidMaterial2Status :: printOutputAt(FILE *File, TimeStep *tStep) const +{ + fprintf(File, " strains "); + for ( double e: deviatoricStrainRateVector ) { + fprintf( File, " %.4e", e ); + } + + fprintf(File, "\n deviatoric stresses"); + for ( double e: deviatoricStressVector ) { + fprintf( File, " %.4e", e ); + } + + fprintf(File, "\n status { gamma %e, tau %e }", devStrainMagnitude, devStressMagnitude); + + fprintf(File, "\n"); +} + +void +BinghamFluidMaterial2Status :: updateYourself(TimeStep *tStep) +{ + FluidDynamicMaterialStatus :: updateYourself(tStep); + + devStrainMagnitude = temp_devStrainMagnitude; + devStressMagnitude = temp_devStressMagnitude; + deviatoricStrainRateVector = temp_deviatoricStrainVector; +} + + +void +BinghamFluidMaterial2Status :: initTempStatus() +{ + FluidDynamicMaterialStatus :: initTempStatus(); + + temp_devStrainMagnitude = devStrainMagnitude; + temp_devStressMagnitude = devStressMagnitude; + temp_deviatoricStrainVector = deviatoricStrainRateVector; +} + + +void +BinghamFluidMaterial2Status :: saveContext(DataStream &stream, ContextMode mode) +{ + FluidDynamicMaterialStatus :: saveContext(stream, mode); + + if ( !stream.write(devStrainMagnitude) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(devStressMagnitude) ) { + THROW_CIOERR(CIO_IOERR); + } +} + + +void +BinghamFluidMaterial2Status :: restoreContext(DataStream &stream, ContextMode mode) +{ + FluidDynamicMaterialStatus :: restoreContext(stream, mode); + + if ( !stream.read(devStrainMagnitude) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(devStressMagnitude) ) { + THROW_CIOERR(CIO_IOERR); + } +} + + +#if 0 +void +BinghamFluidMaterial2 :: __debug(GaussPoint *gp, TimeStep *tStep) +{ + BinghamFluidMaterial2Status *status = static_cast< BinghamFluidMaterial2Status * >( this->giveStatus(gp) ); + const FloatArray &epsd = status->giveTempDeviatoricStrainVector(); + const FloatArray &sigd = status->giveTempDeviatoricStrainVector() + for ( int i = 1; i <= nincr; i++ ) { + eps.add(eps_i); + computeDeviatoricStressVector(tau, gp, eps, tStep); + giveDeviatoricStiffnessMatrix(d, TangentStiffness, gp, tStep); + tau_t.beProductOf(d, eps_i); + tau_t.add(tau_p); + //tau.printYourself(); + //tau_t.printYourself(); + //d.printYourself(); + printf( "%e %e %e %e %e %e %e %e %e\n", eps.at(1), eps.at(2), eps.at(3), tau.at(1), tau.at(2), tau.at(3), tau_t.at(1), tau_t.at(2), tau_t.at(3) ); + tau_p = tau_t; + } +} +#endif +} // end namespace oofem diff --git a/src/fm/binghamfluid2.h b/src/fm/Materials/binghamfluid2.h similarity index 58% rename from src/fm/binghamfluid2.h rename to src/fm/Materials/binghamfluid2.h index 3440b442d..be24df881 100644 --- a/src/fm/binghamfluid2.h +++ b/src/fm/Materials/binghamfluid2.h @@ -35,7 +35,7 @@ #ifndef binghamfluid2_h #define binghamfluid2_h -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "floatarray.h" #include "floatmatrix.h" #include "matconst.h" @@ -51,7 +51,6 @@ //@} namespace oofem { -class GaussPoint; #define BINGHAM_DEFAULT_STRESS_GROWTH_RATE 400.0 @@ -62,25 +61,23 @@ class BinghamFluidMaterial2Status : public FluidDynamicMaterialStatus { protected: /// Magnitude of deviatoric strains - double devStrainMagnitude, temp_devStrainMagnitude; + double devStrainMagnitude = 0., temp_devStrainMagnitude = 0.; /// Magnitude of deviatoric stresses - double devStressMagnitude, temp_devStressMagnitude; + double devStressMagnitude = 0., temp_devStressMagnitude = 0.; /// Deviatoric stresses and strains (reduced form). - FloatArray temp_deviatoricStrainVector; + FloatArrayF<6> temp_deviatoricStrainVector; public: /// Constructor - creates new BinghamFluidMaterial2Status with number n, belonging to domain d and IntegrationPoint g. - BinghamFluidMaterial2Status(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~BinghamFluidMaterial2Status() { } + BinghamFluidMaterial2Status(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; double giveTempDevStressMagnitude() const { return temp_devStressMagnitude; } double giveTempDevStrainMagnitude() const { return temp_devStrainMagnitude; } @@ -90,14 +87,13 @@ class BinghamFluidMaterial2Status : public FluidDynamicMaterialStatus void letTempDevStrainMagnitudeBe(double _val) { temp_devStrainMagnitude = _val; } void letTempDevStressMagnitudeBe(double _val) { temp_devStressMagnitude = _val; } - const FloatArray &giveTempDeviatoricStrainVector() { return temp_deviatoricStrainVector; } - void letTempDeviatoricStrainVectorBe(FloatArray v) { temp_deviatoricStrainVector = std :: move(v); } + const FloatArrayF<6> &giveTempDeviatoricStrainVector() const { return temp_deviatoricStrainVector; } + void letTempDeviatoricStrainVectorBe(const FloatArrayF<6> &v) { temp_deviatoricStrainVector = v; } - virtual const char *giveClassName() const { return "BinghamFluidMaterialStatus"; } + const char *giveClassName() const override { return "BinghamFluidMaterialStatus"; } }; - /** * Constitutive model of Bingham fluid for concentrated suspensions and pastes. * This is the simplest two-constant model, with yield stress and viscosity as parameters. @@ -106,13 +102,13 @@ class BinghamFluidMaterial2 : public FluidDynamicMaterial { protected: /// Viscosity. - double mu_0; + double mu_0 = 0.; /// Yield stress. - double tau_0; - double tau_c; - double mu_inf; - // Stress growth rate - parameter controlling the shape of regularized model. - double stressGrowthRate; + double tau_0 = 0.; + double tau_c = 0.; + double mu_inf = 1.e6; + /// Stress growth rate - parameter controlling the shape of regularized model. + double stressGrowthRate = BINGHAM_DEFAULT_STRESS_GROWTH_RATE; public: /** @@ -121,32 +117,30 @@ class BinghamFluidMaterial2 : public FluidDynamicMaterial * @param d Domain to which new material will belong. */ BinghamFluidMaterial2(int n, Domain * d); - /// Destructor. - virtual ~BinghamFluidMaterial2() { } - virtual void computeDeviatoricStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep); + FloatArrayF<6> computeDeviatoricStress3D(const FloatArrayF<6> &eps, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode, GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> computeTangent3D(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep); - virtual double give(int aProperty, GaussPoint *gp); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveClassName() const { return "BinghamFluidMaterial2"; } - virtual const char *giveInputRecordName() const { return _IFT_BinghamFluidMaterial2_Name; } - virtual int checkConsistency(); - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const override; + double give(int aProperty, GaussPoint *gp) const override; + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveClassName() const override { return "BinghamFluidMaterial2"; } + const char *giveInputRecordName() const override { return _IFT_BinghamFluidMaterial2_Name; } + int checkConsistency() override; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: - double computeActualViscosity(double Tau, double shearRate); - double computeDevStrainMagnitude(MaterialMode mmode, const FloatArray &epsd); - double computeDevStressMagnitude(MaterialMode mmode, const FloatArray &sigd); - void computeDeviatoricStrain(FloatArray &answer, const FloatArray &eps, MaterialMode mmode); - void computeDeviatoricStress(FloatArray &answer, const FloatArray &deps, - double _nu, MaterialMode mmode); + double computeActualViscosity(double tau, double shearRate) const; + static double computeDevStrainMagnitude(const FloatArrayF<6> &epsd); + static double computeDevStressMagnitude(const FloatArrayF<6> &sigd); + static FloatArrayF<6> computeDeviatoricStrain(const FloatArrayF<6> &eps); + static FloatArrayF<6> computeDeviatoricStress(const FloatArrayF<6> &deps, double nu); +#if 0 void __debug(GaussPoint *gp, TimeStep *tStep); +#endif }; } // end namespace oofem #endif // binghamfluid2_h diff --git a/src/fm/fe2fluidmaterial.C b/src/fm/Materials/fe2fluidmaterial.C similarity index 53% rename from src/fm/fe2fluidmaterial.C rename to src/fm/Materials/fe2fluidmaterial.C index 83e079aff..06f0b398f 100644 --- a/src/fm/fe2fluidmaterial.C +++ b/src/fm/Materials/fe2fluidmaterial.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "fe2fluidmaterial.h" +#include "fm/Materials/fe2fluidmaterial.h" #include "stokesflow.h" #include "oofemtxtdatareader.h" #include "domain.h" @@ -61,23 +61,18 @@ void FE2FluidMaterialStatus :: setTimeStep(TimeStep *tStep) rveTStep->setTimeIncrement( tStep->giveTimeIncrement() ); } -void FE2FluidMaterial :: computeDeviatoricStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep) +FloatArrayF<6> FE2FluidMaterial :: computeDeviatoricStress3D(const FloatArrayF<6> &eps, GaussPoint *gp, TimeStep *tStep) const { - double r_vol; - this->computeDeviatoricStressVector(answer, r_vol, gp, eps, 0.0, tStep); - if ( gp->giveMaterialMode() == _2dFlow ) { - r_vol += eps.at(1) + eps.at(2); - } else { - r_vol += eps.at(1) + eps.at(2) + eps.at(3); - } - + auto val = this->computeDeviatoricStress3D(eps, 0.0, gp, tStep); + double r_vol = val.second + eps.at(1) + eps.at(2) + eps.at(3); if ( r_vol > 1e-9 ) { OOFEM_ERROR("RVE seems to be compressible;" " extended macro-formulation which doesn't assume incompressibility is required"); } + return val.first; } -void FE2FluidMaterial :: computeDeviatoricStressVector(FloatArray &stress_dev, double &r_vol, GaussPoint *gp, const FloatArray &eps, double pressure, TimeStep *tStep) +std::pair, double> FE2FluidMaterial :: computeDeviatoricStress3D(const FloatArrayF<6> &eps, double pressure, GaussPoint *gp, TimeStep *tStep) const { FE2FluidMaterialStatus *ms = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) ); @@ -91,6 +86,8 @@ void FE2FluidMaterial :: computeDeviatoricStressVector(FloatArray &stress_dev, d // Solve subscale problem ms->giveRVE()->solveYourselfAt(ms->giveRVE()->giveCurrentStep()); + FloatArray stress_dev; + double r_vol; bc->computeFields(stress_dev, r_vol, tStep); ms->letDeviatoricStressVectorBe(stress_dev); @@ -99,157 +96,158 @@ void FE2FluidMaterial :: computeDeviatoricStressVector(FloatArray &stress_dev, d ms->markOldTangents(); // Mark this so that tangents are reevaluated if they are needed. // One could also just compute them here, but you don't actually need them if the problem has converged, so this method saves on that iteration. // Computing the tangents are often *more* expensive than computeFields, so this is well worth the time it saves - // All the tangents are computed in one go, because they are almost always all needed, and doing so saves time. + return {stress_dev, r_vol}; } -void FE2FluidMaterial :: giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<6,6> FE2FluidMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { FE2FluidMaterialStatus *ms = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) ); ms->computeTangents(tStep); - if ( mode == TangentStiffness ) { - answer = ms->giveDeviatoricTangent(); - } else { + if ( mode != TangentStiffness ) { OOFEM_ERROR("Mode not implemented"); } + FloatMatrixF<6,6> x = ms->giveDeviatoricTangent(); + return x; //ms->giveDeviatoricTangent(); } -void FE2FluidMaterial :: giveStiffnessMatrices(FloatMatrix &dsdd, FloatArray &dsdp, FloatArray &dedd, double &dedp, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FluidDynamicMaterial::Tangents<6> +FE2FluidMaterial :: computeTangents3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { + //FloatMatrix &dsdd, FloatArray &dsdp, FloatArray &dedd, double &dedp, FE2FluidMaterialStatus *ms = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) ); ms->computeTangents(tStep); - if ( mode == TangentStiffness ) { - dsdd = ms->giveDeviatoricTangent(); - dsdp = ms->giveDeviatoricPressureTangent(); - dedd = ms->giveVolumetricDeviatoricTangent(); - dedp = ms->giveVolumetricPressureTangent(); + if ( mode != TangentStiffness ) { + OOFEM_ERROR("Mode not implemented"); + } #if 0 - // Numerical ATS for debugging - FloatMatrix numericalATS(6, 6); - FloatArray dsig; - FloatArray tempStrain(6); - - tempStrain.zero(); - FloatArray sig, strain, sigPert; - double epspvol; - computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, 0., tStep); - double h = 0.001; // Linear problem, size of this doesn't matter. - for ( int k = 1; k <= 6; ++k ) { - strain = tempStrain; - strain.at(k) += h; - double tmp = strain.at(1) + strain.at(2) + strain.at(3); - strain.at(1) -= tmp/3.0; - strain.at(2) -= tmp/3.0; - strain.at(3) -= tmp/3.0; - strain.printYourself(); - computeDeviatoricStressVector(sigPert, epspvol, gp, strain, 0., tStep); - sigPert.printYourself(); - dsig.beDifferenceOf(sigPert, sig); - numericalATS.setColumn(dsig, k); - } - numericalATS.times(1. / h); - - printf("Analytical deviatoric tangent = "); - dsdd.printYourself(); - printf("Numerical deviatoric tangent = "); - numericalATS.printYourself(); - numericalATS.subtract(dsdd); - double norm = numericalATS.computeFrobeniusNorm(); - if ( norm > dsdd.computeFrobeniusNorm() * DEBUG_ERR && norm > 0.0 ) { - OOFEM_ERROR("Error in deviatoric tangent"); - } + // Numerical ATS for debugging + FloatMatrix numericalATS(6, 6); + FloatArray dsig; + FloatArray tempStrain(6); + + tempStrain.zero(); + FloatArray sig, strain, sigPert; + double epspvol; + computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, 0., tStep); + double h = 0.001; // Linear problem, size of this doesn't matter. + for ( int k = 1; k <= 6; ++k ) { + strain = tempStrain; + strain.at(k) += h; + double tmp = strain.at(1) + strain.at(2) + strain.at(3); + strain.at(1) -= tmp/3.0; + strain.at(2) -= tmp/3.0; + strain.at(3) -= tmp/3.0; + strain.printYourself(); + computeDeviatoricStressVector(sigPert, epspvol, gp, strain, 0., tStep); + sigPert.printYourself(); + dsig.beDifferenceOf(sigPert, sig); + numericalATS.setColumn(dsig, k); + } + numericalATS.times(1. / h); + + printf("Analytical deviatoric tangent = "); + dsdd.printYourself(); + printf("Numerical deviatoric tangent = "); + numericalATS.printYourself(); + numericalATS.subtract(dsdd); + double norm = numericalATS.computeFrobeniusNorm(); + if ( norm > dsdd.computeFrobeniusNorm() * DEBUG_ERR && norm > 0.0 ) { + OOFEM_ERROR("Error in deviatoric tangent"); + } #endif #if 0 - // Numerical ATS for debugging - FloatArray strain(3); - strain.zero(); - FloatArray sig, sigh; - double epspvol, pressure = 0.0; - double h = 1.00; // Linear problem, size of this doesn't matter. - computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep); - computeDeviatoricStressVector(sigh, epspvol, gp, strain, pressure + h, tStep); - - FloatArray dsigh; - dsigh.beDifferenceOf(sigh, sig); - dsigh.times(1 / h); - - printf("Analytical deviatoric pressure tangent = "); - dsdp.printYourself(); - printf("Numerical deviatoric pressure tangent = "); - dsigh.printYourself(); - dsigh.subtract(dsdp); - double norm = dsigh.computeNorm(); - if ( norm > dsdp.computeNorm() * DEBUG_ERR && norm > 0.0 ) { - OOFEM_ERROR("Error in deviatoric pressure tangent"); - } + // Numerical ATS for debugging + FloatArray strain(3); + strain.zero(); + FloatArray sig, sigh; + double epspvol, pressure = 0.0; + double h = 1.00; // Linear problem, size of this doesn't matter. + computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep); + computeDeviatoricStressVector(sigh, epspvol, gp, strain, pressure + h, tStep); + + FloatArray dsigh; + dsigh.beDifferenceOf(sigh, sig); + dsigh.times(1 / h); + + printf("Analytical deviatoric pressure tangent = "); + dsdp.printYourself(); + printf("Numerical deviatoric pressure tangent = "); + dsigh.printYourself(); + dsigh.subtract(dsdp); + double norm = dsigh.computeNorm(); + if ( norm > dsdp.computeNorm() * DEBUG_ERR && norm > 0.0 ) { + OOFEM_ERROR("Error in deviatoric pressure tangent"); + } #endif #if 0 - // Numerical ATS for debugging - FloatArray tempStrain(3); - tempStrain.zero(); - FloatArray sig, strain; - double epspvol, epspvol11, epspvol22, epspvol12, pressure = 0.0; - double h = 1.0; // Linear problem, size of this doesn't matter. - - computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, pressure, tStep); - strain = tempStrain; - strain.at(1) += h; - computeDeviatoricStressVector(sig, epspvol11, gp, strain, pressure, tStep); - strain = tempStrain; - strain.at(2) += h; - computeDeviatoricStressVector(sig, epspvol22, gp, strain, pressure, tStep); - strain = tempStrain; - strain.at(3) += h; - computeDeviatoricStressVector(sig, epspvol12, gp, strain, pressure, tStep); - - FloatArray dvol(3); - dvol.at(1) = ( epspvol11 - epspvol ) / h; - dvol.at(2) = ( epspvol22 - epspvol ) / h; - dvol.at(3) = ( epspvol12 - epspvol ) / h; - dvol.at(1) += 1.0; - dvol.at(2) += 1.0; - - printf("Analytical volumetric deviatoric tangent = "); - dedd.printYourself(); - printf("Numerical volumetric deviatoric tangent = "); - dvol.printYourself(); - dvol.subtract(dedd); - double norm = dvol.computeNorm(); - if ( norm > dedd.computeNorm() * DEBUG_ERR && norm > 0.0 ) { - OOFEM_ERROR("Error in volumetric deviatoric tangent"); - } + // Numerical ATS for debugging + FloatArray tempStrain(3); + tempStrain.zero(); + FloatArray sig, strain; + double epspvol, epspvol11, epspvol22, epspvol12, pressure = 0.0; + double h = 1.0; // Linear problem, size of this doesn't matter. + + computeDeviatoricStressVector(sig, epspvol, gp, tempStrain, pressure, tStep); + strain = tempStrain; + strain.at(1) += h; + computeDeviatoricStressVector(sig, epspvol11, gp, strain, pressure, tStep); + strain = tempStrain; + strain.at(2) += h; + computeDeviatoricStressVector(sig, epspvol22, gp, strain, pressure, tStep); + strain = tempStrain; + strain.at(3) += h; + computeDeviatoricStressVector(sig, epspvol12, gp, strain, pressure, tStep); + + FloatArray dvol(3); + dvol.at(1) = ( epspvol11 - epspvol ) / h; + dvol.at(2) = ( epspvol22 - epspvol ) / h; + dvol.at(3) = ( epspvol12 - epspvol ) / h; + dvol.at(1) += 1.0; + dvol.at(2) += 1.0; + + printf("Analytical volumetric deviatoric tangent = "); + dedd.printYourself(); + printf("Numerical volumetric deviatoric tangent = "); + dvol.printYourself(); + dvol.subtract(dedd); + double norm = dvol.computeNorm(); + if ( norm > dedd.computeNorm() * DEBUG_ERR && norm > 0.0 ) { + OOFEM_ERROR("Error in volumetric deviatoric tangent"); + } #endif #if 0 - // Numerical ATS for debugging - FloatArray strain(3); - strain.zero(); - FloatArray sig; - double epspvol, epspvolh, pressure = 0.0; - double h = 1.0; // Linear problem, size of this doesn't matter. + // Numerical ATS for debugging + FloatArray strain(3); + strain.zero(); + FloatArray sig; + double epspvol, epspvolh, pressure = 0.0; + double h = 1.0; // Linear problem, size of this doesn't matter. - computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep); - computeDeviatoricStressVector(sig, epspvolh, gp, strain, pressure + h, tStep); + computeDeviatoricStressVector(sig, epspvol, gp, strain, pressure, tStep); + computeDeviatoricStressVector(sig, epspvolh, gp, strain, pressure + h, tStep); - double dvol = -( epspvolh - epspvol ) / h; + double dvol = -( epspvolh - epspvol ) / h; - printf("Analytical volumetric pressure tangent = %e\n", dedp); - printf("Numerical volumetric pressure tangent = %e\n", dvol); + printf("Analytical volumetric pressure tangent = %e\n", dedp); + printf("Numerical volumetric pressure tangent = %e\n", dvol); - double norm = fabs(dvol - dedp); - if ( norm > fabs(dedp) * DEBUG_ERR && norm > 0.0 ) { - OOFEM_ERROR("Error in volumetric pressure tangent"); - } -#endif - } else { - OOFEM_ERROR("Mode not implemented"); + double norm = fabs(dvol - dedp); + if ( norm > fabs(dedp) * DEBUG_ERR && norm > 0.0 ) { + OOFEM_ERROR("Error in volumetric pressure tangent"); } +#endif + return { + ms->giveDeviatoricTangent(), + ms->giveDeviatoricPressureTangent(), + ms->giveVolumetricDeviatoricTangent(), + ms->giveVolumetricPressureTangent(), + }; } -IRResultType FE2FluidMaterial :: initializeFrom(InputRecord *ir) +void FE2FluidMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; + FluidDynamicMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->inputfile, _IFT_FE2FluidMaterial_fileName); - return FluidDynamicMaterial :: initializeFrom(ir); } void FE2FluidMaterial :: giveInputRecord(DynamicInputRecord &input) @@ -301,7 +299,11 @@ int FE2FluidMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, Internal MaterialStatus *FE2FluidMaterial :: CreateStatus(GaussPoint *gp) const { - return new FE2FluidMaterialStatus(n++, this->giveDomain(), gp, this->inputfile); + int rank = -1; + if ( this->domain->giveEngngModel()->isParallel() && this->domain->giveEngngModel()->giveNumberOfProcesses() > 1 ) { + rank = this->domain->giveEngngModel()->giveRank(); + } + return new FE2FluidMaterialStatus(n++, rank, gp, this->inputfile); } int FE2FluidMaterial :: checkConsistency() @@ -309,42 +311,32 @@ int FE2FluidMaterial :: checkConsistency() return true; } -FE2FluidMaterialStatus :: FE2FluidMaterialStatus(int n, Domain *d, GaussPoint *gp, const std :: string &inputfile) : - FluidDynamicMaterialStatus(n, d, gp) +FE2FluidMaterialStatus :: FE2FluidMaterialStatus(int n, int rank, GaussPoint *gp, const std :: string &inputfile) : + FluidDynamicMaterialStatus(gp), + voffraction(0.0), + oldTangents(true) { - //this->strainVector.resize(size); - //this->strainVector.zero(); - //this->tempStrainVector = this->strainVector; - this->voffraction = 0.0; - this->oldTangents = true; - - if ( !this->createRVE(n, gp, inputfile) ) { + if ( !this->createRVE(n, rank ,gp, inputfile) ) { OOFEM_ERROR("Couldn't create RVE"); } } -FE2FluidMaterialStatus :: ~FE2FluidMaterialStatus() -{ -} - // Uses an input file for now, should eventually create the RVE itself. -bool FE2FluidMaterialStatus :: createRVE(int n, GaussPoint *gp, const std :: string &inputfile) +bool FE2FluidMaterialStatus :: createRVE(int n, int rank, GaussPoint *gp, const std :: string &inputfile) { OOFEMTXTDataReader dr( inputfile.c_str() ); - EngngModel *em = InstanciateProblem(& dr, _processor, 0); // Everything but nrsolver is updated. + this->rve = InstanciateProblem(dr, _processor, 0); // Everything but nrsolver is updated. dr.finish(); - em->setProblemScale(microScale); - em->checkProblemConsistency(); - em->initMetaStepAttributes( em->giveMetaStep(1) ); - em->giveNextStep(); // Makes sure there is a timestep (which we will modify before solving a step) - em->init(); - - this->rve.reset( em ); + this->rve->setProblemScale(microScale); + this->rve->checkProblemConsistency(); + this->rve->initMetaStepAttributes( this->rve->giveMetaStep(1) ); + this->rve->giveNextStep(); // Makes sure there is a timestep (which we will modify before solving a step) + this->rve->init(); std :: ostringstream name; name << this->rve->giveOutputBaseFileName() << "-gp" << n; - if ( this->domain->giveEngngModel()->isParallel() && this->domain->giveEngngModel()->giveNumberOfProcesses() > 1 ) { - name << "." << this->domain->giveEngngModel()->giveRank(); + if ( rank >= 0 ) { + name << "." << rank; } this->rve->letOutputBaseFileNameBe( name.str() ); @@ -357,7 +349,7 @@ bool FE2FluidMaterialStatus :: createRVE(int n, GaussPoint *gp, const std :: str return true; } -void FE2FluidMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +void FE2FluidMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { FluidDynamicMaterialStatus :: printOutputAt(file, tStep); } @@ -378,25 +370,17 @@ void FE2FluidMaterialStatus :: initTempStatus() FluidDynamicMaterialStatus :: initTempStatus(); } -contextIOResultType FE2FluidMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void FE2FluidMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = FluidDynamicMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return this->rve->saveContext(stream, mode); + FluidDynamicMaterialStatus :: saveContext(stream, mode); + this->rve->saveContext(stream, mode); } -contextIOResultType FE2FluidMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void FE2FluidMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = FluidDynamicMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + FluidDynamicMaterialStatus :: restoreContext(stream, mode); this->markOldTangents(); - - return this->rve->restoreContext(&stream, mode, obj); + this->rve->restoreContext(stream, mode); } void FE2FluidMaterialStatus :: markOldTangents() { this->oldTangents = true; } @@ -418,11 +402,11 @@ void FE2FluidMaterialStatus :: computeTangents(TimeStep *tStep) this->oldTangents = false; } -double FE2FluidMaterial :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) +double FE2FluidMaterial :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const { FE2FluidMaterialStatus *status = static_cast< FE2FluidMaterialStatus * >( this->giveStatus(gp) ); status->computeTangents(tStep); - const FloatMatrix &t = status->giveDeviatoricTangent(); + const auto &t = status->giveDeviatoricTangent(); // Project against the normalized I_dev double v; if ( gp->giveMaterialMode() == _3dFlow ) { diff --git a/src/fm/fe2fluidmaterial.h b/src/fm/Materials/fe2fluidmaterial.h similarity index 68% rename from src/fm/fe2fluidmaterial.h rename to src/fm/Materials/fe2fluidmaterial.h index 9f97ec2c0..016c20a23 100644 --- a/src/fm/fe2fluidmaterial.h +++ b/src/fm/Materials/fe2fluidmaterial.h @@ -35,7 +35,7 @@ #ifndef fe2sinteringmaterial_h #define fe2sinteringmaterial_h -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "matstatus.h" #include "mixedgradientpressurebc.h" #include "floatmatrix.h" @@ -77,13 +77,11 @@ class FE2FluidMaterialStatus : public FluidDynamicMaterialStatus /** * Creates new material status. * @param n Material status number. - * @param d Domain that status belongs to. + * @param rank Parallel rank (ignored if negative). * @param gp Gauss point that the status belongs to. * @param inputfile The input file describing the micro problem. */ - FE2FluidMaterialStatus(int n, Domain * d, GaussPoint * gp, const std :: string & inputfile); - /// Destructor - virtual ~FE2FluidMaterialStatus(); + FE2FluidMaterialStatus(int n, int rank, GaussPoint * gp, const std :: string & inputfile); EngngModel *giveRVE() { return this->rve.get(); } MixedGradientPressureBC *giveBC() { return this->bc; } @@ -94,7 +92,7 @@ class FE2FluidMaterialStatus : public FluidDynamicMaterialStatus double giveVOFFraction() { return this->voffraction; } /// Creates/Initiates the RVE problem. - bool createRVE(int n, GaussPoint *gp, const std :: string &inputfile); + bool createRVE(int n, int rank, GaussPoint *gp, const std :: string &inputfile); /// Copies time step data to RVE. void setTimeStep(TimeStep *tStep); @@ -107,15 +105,15 @@ class FE2FluidMaterialStatus : public FluidDynamicMaterialStatus double givePressure() { return this->pressure; } void letPressureBe(double val) { this->pressure = val; } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual const char *giveClassName() const { return "FE2FluidMaterialStatus"; } + const char *giveClassName() const override { return "FE2FluidMaterialStatus"; } }; @@ -142,29 +140,26 @@ class FE2FluidMaterial : public FluidDynamicMaterial * @param d Domain to which new material will belong. */ FE2FluidMaterial(int n, Domain * d) : FluidDynamicMaterial(n, d) { } - /// Destructor. - virtual ~FE2FluidMaterial() { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual int checkConsistency(); + int checkConsistency() override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual void computeDeviatoricStressVector(FloatArray &stress_dev, double &r_vol, GaussPoint *gp, const FloatArray &eps, double pressure, TimeStep *tStep); - virtual void computeDeviatoricStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep); + std::pair, double> computeDeviatoricStress3D(const FloatArrayF<6> &eps, double pressure, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<6> computeDeviatoricStress3D(const FloatArrayF<6> &eps, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveStiffnessMatrices(FloatMatrix &dsdd, FloatArray &dsdp, FloatArray &dedd, double &dedp, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<6,6> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + Tangents<6> computeTangents3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep); + double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual const char *giveClassName() const { return "FE2FluidMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_FE2FluidMaterial_Name; } + const char *giveClassName() const override { return "FE2FluidMaterial"; } + const char *giveInputRecordName() const override { return _IFT_FE2FluidMaterial_Name; } }; } // end namespace oofem #endif // rvesinteringmaterial_h diff --git a/src/fm/Materials/fluiddynamicmaterial.C b/src/fm/Materials/fluiddynamicmaterial.C new file mode 100644 index 000000000..592e5f473 --- /dev/null +++ b/src/fm/Materials/fluiddynamicmaterial.C @@ -0,0 +1,187 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "fm/Materials/fluiddynamicmaterial.h" +#include "gausspoint.h" +#include "floatarray.h" +#include "contextioerr.h" + +namespace oofem { + +std::pair, double> +FluidDynamicMaterial :: computeDeviatoricStress3D(const FloatArrayF<6> &eps, double pressure, GaussPoint *gp, TimeStep *tStep) const +{ + double epsp_vol = -( eps[0] + eps[1] + eps[2] ); + auto stress_dev = this->computeDeviatoricStress3D(eps, gp, tStep); + return {stress_dev, epsp_vol}; +} + + +std::pair, double> +FluidDynamicMaterial :: computeDeviatoricStress2D(const FloatArrayF<3> &eps, double pressure, GaussPoint *gp, TimeStep *tStep) const +{ + //auto [stress, epsv] = this->computeDeviatoricStress3D(assemble<6>(eps, {0, 1, 5}), pressure, gp, tStep); + auto val = this->computeDeviatoricStress3D(assemble<6>(eps, {0, 1, 5}), pressure, gp, tStep); + auto stress3 = val.first; + auto epsv = val.second; + return {stress3[{0, 1, 5}], epsv}; +} + + +FloatArrayF<3> +FluidDynamicMaterial :: computeDeviatoricStress2D(const FloatArrayF<3> &eps, GaussPoint *gp, TimeStep *tStep) const +{ + auto stress3 = this->computeDeviatoricStress3D(assemble<6>(eps, {0, 1, 5}), gp, tStep); + return stress3[{0, 1, 5}]; +} + + +FloatArrayF<4> +FluidDynamicMaterial :: computeDeviatoricStressAxi(const FloatArrayF<4> &eps, GaussPoint *gp, TimeStep *tStep) const +{ + auto stress3 = this->computeDeviatoricStress3D(assemble<6>(eps, {0, 1, 2, 5}), gp, tStep); + return stress3[{0, 1, 2, 5}]; +} + + +FloatMatrixF<3,3> +FluidDynamicMaterial :: computeTangent2D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto dsdd3 = this->computeTangent3D(mode, gp, tStep); + return dsdd3({0, 1, 5}, {0, 1, 5}); +} + + +FloatMatrixF<4,4> +FluidDynamicMaterial :: computeTangentAxi(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto dsdd3 = this->computeTangent3D(mode, gp, tStep); + return dsdd3({0, 1, 2, 5}, {0, 1, 2, 5}); +} + + +FluidDynamicMaterial::Tangents<6> +FluidDynamicMaterial :: computeTangents3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + return { + this->computeTangent3D(mode, gp, tStep), + zeros<6>(), + zeros<6>(), + 0. + }; +} + + +FluidDynamicMaterial::Tangents<3> +FluidDynamicMaterial :: computeTangents2D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto t = this->computeTangents3D(mode, gp, tStep); + + auto dsdd = t.dsdd({0, 1, 5}, {0, 1, 5}); + auto dsdp = t.dsdp[{0, 1, 5}]; + auto dedd = t.dedd[{0, 1, 5}]; + return {dsdd, dsdp, dedd, t.dedp}; +} + + +FluidDynamicMaterialStatus :: FluidDynamicMaterialStatus(GaussPoint *g) : + MaterialStatus(g) +{ } + +void +FluidDynamicMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const +{ + fprintf(file, "\n deviatoric stresses"); + for ( double e: deviatoricStressVector ) { + fprintf(file, " %.4e", e ); + } + + fprintf(file, "\n"); +} + +int +FluidDynamicMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +{ + auto status = static_cast< FluidDynamicMaterialStatus * >( this->giveStatus(gp) ); + if ( type == IST_DeviatoricStress ) { + answer = status->giveDeviatoricStressVector(); + return 1; + } else if ( type == IST_DeviatoricStrain ) { + answer = status->giveDeviatoricStrainRateVector(); + return 1; + } else if ( type == IST_Viscosity ) { + answer.resize(1); + answer.at(1) = this->giveEffectiveViscosity(gp, tStep); + return 1; + } else if ( type == IST_Density ) { + answer.resize(1); + answer.at(1) = this->give('d', gp); + return 1; + } else { + return Material :: giveIPValue(answer, gp, type, tStep); + } +} + + +void +FluidDynamicMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) +{ + MaterialStatus :: saveContext(stream, mode); + + contextIOResultType iores; + if ( ( iores = deviatoricStressVector.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = deviatoricStrainRateVector.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } +} + + +void +FluidDynamicMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) +{ + MaterialStatus :: restoreContext(stream, mode); + + contextIOResultType iores; + if ( ( iores = deviatoricStressVector.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = deviatoricStrainRateVector.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } +} +} // end namespace oofem diff --git a/src/fm/fluiddynamicmaterial.h b/src/fm/Materials/fluiddynamicmaterial.h similarity index 60% rename from src/fm/fluiddynamicmaterial.h rename to src/fm/Materials/fluiddynamicmaterial.h index 1ec5b298c..293010a57 100644 --- a/src/fm/fluiddynamicmaterial.h +++ b/src/fm/Materials/fluiddynamicmaterial.h @@ -38,7 +38,8 @@ #include "material.h" #include "matstatus.h" #include "floatarray.h" - +#include "floatarrayf.h" +#include "floatmatrixf.h" namespace oofem { /** @@ -56,32 +57,31 @@ class FluidDynamicMaterialStatus : public MaterialStatus { protected: /// Stress vector in reduced form. - FloatArray deviatoricStressVector; + FloatArrayF<6> deviatoricStressVector; /// Strain vector in reduced form. - FloatArray deviatoricStrainRateVector; + FloatArrayF<6> deviatoricStrainRateVector; public: /// Constructor - creates new TransportMaterialStatus with number n, belonging to domain d and integration point g. - FluidDynamicMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor. - virtual ~FluidDynamicMaterialStatus() { } + FluidDynamicMaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual void initTempStatus(); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; /** * Gives the deviatoric stress. */ - const FloatArray &giveDeviatoricStressVector() { return deviatoricStressVector; } - const FloatArray &giveDeviatoricStrainRateVector() { return deviatoricStrainRateVector; } + const FloatArrayF<6> &giveDeviatoricStressVector() const { return deviatoricStressVector; } + const FloatArrayF<6> &giveDeviatoricStrainRateVector() const { return deviatoricStrainRateVector; } /** * Sets the deviatoric stress. */ - void letDeviatoricStressVectorBe(FloatArray v) { deviatoricStressVector = std :: move(v); } - void letDeviatoricStrainRateVectorBe(FloatArray v) { deviatoricStrainRateVector = std :: move(v); } + void letDeviatoricStressVectorBe(const FloatArrayF<6> &v) { deviatoricStressVector = v; } + void letDeviatoricStrainRateVectorBe(const FloatArrayF<6> &v) { deviatoricStrainRateVector = v; } + + const char *giveClassName() const override { return "FluidDynamicMaterialStatus"; } }; @@ -92,26 +92,33 @@ class FluidDynamicMaterialStatus : public MaterialStatus class FluidDynamicMaterial : public Material { public: + template struct Tangents { + FloatMatrixF dsdd; + FloatArrayF dsdp; + FloatArrayF dedd; + double dedp; + }; + /** * Constructor. Creates material with given number, belonging to given domain. * @param n Material number. * @param d Domain to which new material will belong. */ FluidDynamicMaterial(int n, Domain * d) : Material(n, d) { } - /// Destructor. - virtual ~FluidDynamicMaterial() { } /** * Computes the deviatoric stress vector and volumetric strain rate from given deviatoric strain and pressure. * Defaults to incompressible function. - * @param stress_dev Deviatoric stress. - * @param epsp_vol Volumetric strain-rate (minus the volumetric part of the eps argument). * @param gp Integration point. * @param eps Strain-rate. * @param pressure Pressure. * @param tStep Time step. + * @return Deviatoric stress and volumetric strain-rate (minus the volumetric part of the eps argument). */ - virtual void computeDeviatoricStressVector(FloatArray &stress_dev, double &epsp_vol, GaussPoint *gp, const FloatArray &eps, double pressure, TimeStep *tStep); + virtual std::pair, double> computeDeviatoricStress3D(const FloatArrayF<6> &eps, double pressure, + GaussPoint *gp, TimeStep *tStep) const; + virtual std::pair, double> computeDeviatoricStress2D(const FloatArrayF<3> &eps, double pressure, + GaussPoint *gp, TimeStep *tStep) const; /** * Computes the deviatoric stress vector from given strain. * @param answer Deviatoric stress. @@ -119,8 +126,9 @@ class FluidDynamicMaterial : public Material * @param eps Strain-rate. * @param tStep Time step. */ - virtual void computeDeviatoricStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep) = 0; - + virtual FloatArrayF<6> computeDeviatoricStress3D(const FloatArrayF<6> &eps, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF<3> computeDeviatoricStress2D(const FloatArrayF<3> &eps, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatArrayF<4> computeDeviatoricStressAxi(const FloatArrayF<4> &eps, GaussPoint *gp, TimeStep *tStep) const; /** * Computes the deviatoric stiffness; @f$ \frac{\partial\sigma_{\mathrm{dev}}}{\partial \epsilon_{\mathrm{dev}}}@f$. @@ -129,19 +137,22 @@ class FluidDynamicMaterial : public Material * @param gp Integration point. * @param tStep Time step. */ - virtual void giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + virtual FloatMatrixF<6,6> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatMatrixF<3,3> computeTangent2D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatMatrixF<4,4> computeTangentAxi(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; + /** * Computes the 4 tangents of the compressible material response in 3D. - * @param dsdd @f$ \frac{\partial\sigma_{\mathrm{dev}}}{\partial \epsilon_{\mathrm{dev}}}@f$. - * @param dsdp @f$ \frac{\partial\sigma_{\mathrm{dev}}}{\partial p}@f$ - * @param dedd @f$ \frac{\partial\epsilon_{\mathrm{vol}}}{\partial\epsilon_{\mathrm{dev}}}@f$ - * @param dedp @f$ \frac{\partial\epsilon_{\mathrm{vol}}}{\partial p}@f$ + * - dsdd @f$ \frac{\partial\sigma_{\mathrm{dev}}}{\partial \epsilon_{\mathrm{dev}}}@f$. + * - dsdp @f$ \frac{\partial\sigma_{\mathrm{dev}}}{\partial p}@f$ + * - dedd @f$ \frac{\partial\epsilon_{\mathrm{vol}}}{\partial\epsilon_{\mathrm{dev}}}@f$ + * - dedp @f$ \frac{\partial\epsilon_{\mathrm{vol}}}{\partial p}@f$ * @param mode Mode of result. * @param gp Integration point. * @param tStep Time step. */ - virtual void giveStiffnessMatrices(FloatMatrix &dsdd, FloatArray &dsdp, FloatArray &dedd, double &dedp, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + virtual Tangents<6> computeTangents3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; + virtual Tangents<3> computeTangents2D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; /** * Gives the effective viscosity for the given integration point. @@ -149,17 +160,9 @@ class FluidDynamicMaterial : public Material * @param tStep Time step. * @return The effective viscosity in the point. */ - virtual double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) = 0; - - /** - * Updates internal state of material according to new state vector. - * @param vec New state vector. - * @param gp Integration point. - * @param tStep Solution step. - */ - virtual void updateInternalState(const FloatArray &vec, GaussPoint *gp, TimeStep *tStep); + virtual double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const = 0; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; }; } // end namespace oofem #endif // fluiddynamicmaterial_h diff --git a/src/fm/Materials/newtonianfluid.C b/src/fm/Materials/newtonianfluid.C new file mode 100644 index 000000000..3345d6f44 --- /dev/null +++ b/src/fm/Materials/newtonianfluid.C @@ -0,0 +1,132 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "fm/Materials/newtonianfluid.h" +#include "domain.h" +#include "floatmatrix.h" +#include "gausspoint.h" +#include "engngm.h" +#include "dynamicinputrecord.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(NewtonianFluidMaterial); + +void +NewtonianFluidMaterial :: initializeFrom(InputRecord &ir) +{ + FluidDynamicMaterial :: initializeFrom(ir); + IR_GIVE_FIELD(ir, viscosity, _IFT_NewtonianFluidMaterial_mu); + +} + + +void +NewtonianFluidMaterial :: giveInputRecord(DynamicInputRecord &input) +{ + FluidDynamicMaterial :: giveInputRecord(input); + input.setField(this->viscosity, _IFT_NewtonianFluidMaterial_mu); +} + + +double +NewtonianFluidMaterial :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const +{ + return this->viscosity; +} + + +double +NewtonianFluidMaterial :: give(int aProperty, GaussPoint *gp) const +{ + if ( aProperty == Viscosity ) { + return viscosity; + } else if ( aProperty == YieldStress ) { + return 0.0; + } else { + return FluidDynamicMaterial :: give(aProperty, gp); + } +} + + +MaterialStatus * +NewtonianFluidMaterial :: CreateStatus(GaussPoint *gp) const +{ + return new FluidDynamicMaterialStatus(gp); +} + + +FloatArrayF<6> +NewtonianFluidMaterial :: computeDeviatoricStress3D(const FloatArrayF<6> &eps, GaussPoint *gp, TimeStep *tStep) const +{ + double ekk = eps.at(1) + eps.at(2) + eps.at(3); + + FloatArrayF<6> stress = { + 2.0 * viscosity * ( eps.at(1) - ekk / 3.0 ), + 2.0 * viscosity * ( eps.at(2) - ekk / 3.0 ), + 2.0 * viscosity * ( eps.at(3) - ekk / 3.0 ), + eps.at(4) * viscosity, + eps.at(5) * viscosity, + eps.at(6) * viscosity + }; + + static_cast< FluidDynamicMaterialStatus * >( this->giveStatus(gp) )->letDeviatoricStressVectorBe(stress); + static_cast< FluidDynamicMaterialStatus * >( this->giveStatus(gp) )->letDeviatoricStrainRateVectorBe(eps); + + return stress; +} + +FloatMatrixF<6,6> +NewtonianFluidMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + return 2 * viscosity * I_dev6; +} + + +int +NewtonianFluidMaterial :: checkConsistency() +{ + ///@todo Fix this, checkConsistency shouldn't be a replacement for "post-initialization" but should be completely optional. + if ( domain->giveEngngModel()->giveEquationScalingFlag() ) { + double scale; + scale = domain->giveEngngModel()->giveVariableScale(VST_Density); + propertyDictionary.at('d') /= scale; + + scale = domain->giveEngngModel()->giveVariableScale(VST_Viscosity); + this->viscosity /= scale; + } + + return 1; +} +} // end namespace oofem diff --git a/src/fm/newtonianfluid.h b/src/fm/Materials/newtonianfluid.h similarity index 71% rename from src/fm/newtonianfluid.h rename to src/fm/Materials/newtonianfluid.h index 24d0314fc..dde8d70e1 100644 --- a/src/fm/newtonianfluid.h +++ b/src/fm/Materials/newtonianfluid.h @@ -35,7 +35,7 @@ #ifndef newtonianfluid_h #define newtonianfluid_h -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "floatarray.h" #include "floatmatrix.h" #include "matconst.h" @@ -65,21 +65,19 @@ class NewtonianFluidMaterial : public FluidDynamicMaterial * @param d Domain to which new material will belong. */ NewtonianFluidMaterial(int n, Domain * d) : FluidDynamicMaterial(n, d) { } - /// Destructor. - virtual ~NewtonianFluidMaterial() { } - virtual double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep); + double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const override; - virtual void computeDeviatoricStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep); - virtual void giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode, GaussPoint *gp, TimeStep *tStep); + FloatArrayF<6> computeDeviatoricStress3D(const FloatArrayF<6> &eps, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<6,6> computeTangent3D(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual double give(int aProperty, GaussPoint *gp); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveClassName() const { return "NewtonianFluidMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_NewtonianFluidMaterial_Name; } - virtual int checkConsistency(); - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + double give(int aProperty, GaussPoint *gp) const override; + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveClassName() const override { return "NewtonianFluidMaterial"; } + const char *giveInputRecordName() const override { return _IFT_NewtonianFluidMaterial_Name; } + int checkConsistency() override; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; }; } // end namespace oofem #endif // newtonianfluid_h diff --git a/src/fm/nonlinearfluidmaterial.C b/src/fm/Materials/nonlinearfluidmaterial.C similarity index 56% rename from src/fm/nonlinearfluidmaterial.C rename to src/fm/Materials/nonlinearfluidmaterial.C index 47f04b9c4..546abc52e 100644 --- a/src/fm/nonlinearfluidmaterial.C +++ b/src/fm/Materials/nonlinearfluidmaterial.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "fluiddynamicmaterial.h" -#include "nonlinearfluidmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" +#include "fm/Materials/nonlinearfluidmaterial.h" #include "domain.h" #include "floatmatrix.h" #include "gausspoint.h" @@ -49,16 +49,13 @@ namespace oofem { REGISTER_Material(NonlinearFluidMaterial); -IRResultType -NonlinearFluidMaterial :: initializeFrom(InputRecord *ir) +void +NonlinearFluidMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - + FluidDynamicMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, viscosity, _IFT_NonlinearFluidMaterial_mu); IR_GIVE_FIELD(ir, alpha, _IFT_NonlinearFluidMaterial_alpha); IR_GIVE_FIELD(ir, c, _IFT_NonlinearFluidMaterial_C); - - return FluidDynamicMaterial :: initializeFrom(ir); } @@ -73,14 +70,14 @@ NonlinearFluidMaterial :: giveInputRecord(DynamicInputRecord &input) double -NonlinearFluidMaterial :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) +NonlinearFluidMaterial :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const { return this->viscosity; } double -NonlinearFluidMaterial :: give(int aProperty, GaussPoint *gp) +NonlinearFluidMaterial :: give(int aProperty, GaussPoint *gp) const { if ( aProperty == Viscosity ) { return viscosity; @@ -93,89 +90,62 @@ NonlinearFluidMaterial :: give(int aProperty, GaussPoint *gp) MaterialStatus * NonlinearFluidMaterial :: CreateStatus(GaussPoint *gp) const { - return new NonlinearFluidMaterialStatus(1, this->giveDomain(), gp); + return new NonlinearFluidMaterialStatus(gp); } -void -NonlinearFluidMaterial :: computeDeviatoricStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep) +FloatArrayF<6> +NonlinearFluidMaterial :: computeDeviatoricStress3D(const FloatArrayF<6> &eps, GaussPoint *gp, TimeStep *tStep) const { NonlinearFluidMaterialStatus *status = static_cast< NonlinearFluidMaterialStatus * >( this->giveStatus(gp) ); - double normeps2; - - answer = eps; - if ( eps.giveSize() == 3 ) { - normeps2 = eps.at(1) * eps.at(1) + eps.at(2) * eps.at(2) + 0.5 * ( eps.at(3) * eps.at(3) ); - answer.at(3) *= 0.5; - } else if ( eps.giveSize() == 4 ) { - normeps2 = eps.at(1) * eps.at(1) + eps.at(2) * eps.at(2) + eps.at(3) * eps.at(3) + 0.5 * ( eps.at(4) * eps.at(4) ); - answer.at(4) *= 0.5; - } else { - normeps2 = eps.at(1) * eps.at(1) + eps.at(2) * eps.at(2) + eps.at(3) * eps.at(3) + 0.5 * ( eps.at(4) * eps.at(4) + eps.at(5) * eps.at(5) + eps.at(6) * eps.at(6) ); - answer.at(4) *= 0.5; - answer.at(5) *= 0.5; - answer.at(6) *= 0.5; - } + ///@todo This doesn't look like a strain norm? + double normeps2 = eps[0] * eps[0] + eps[1] * eps[1] + eps[2] * eps[2] + 0.5 * ( eps[3] * eps[3] + eps[4] * eps[4] + eps[5] * eps[5] ); - answer.times( 2.0 * viscosity * ( 1.0 + c * pow(normeps2, alpha * 0.5) ) ); + auto answer = eps; + answer[3] *= 0.5; + answer[4] *= 0.5; + answer[5] *= 0.5; + answer *= 2.0 * viscosity * ( 1.0 + c * pow(normeps2, alpha * 0.5) ); status->letTempDeviatoricStressVectorBe(answer); status->letTempDeviatoricStrainVectorBe(eps); status->letTempStrainNorm2Be(normeps2); + return answer; } -void -NonlinearFluidMaterial :: giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF<6,6> +NonlinearFluidMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - FloatArray eps; - double normeps2; - NonlinearFluidMaterialStatus *status = static_cast< NonlinearFluidMaterialStatus * >( this->giveStatus(gp) ); - eps = status->giveTempDeviatoricStrainVector(); - normeps2 = status->giveTempStrainNorm2(); + double normeps2 = status->giveTempStrainNorm2(); - answer.resize( eps.giveSize(), eps.giveSize() ); - answer.zero(); - for ( int i = 1; i <= answer.giveNumberOfRows(); i++ ) { - answer.at(i, i) = 1.; - } - if ( eps.giveSize() == 3 ) { - answer.at(3, 3) *= 0.5; - } else if ( eps.giveSize() == 4 ) { - answer.at(4, 4) *= 0.5; - } else { - answer.at(4, 4) *= 0.5; - answer.at(5, 5) *= 0.5; - answer.at(6, 6) *= 0.5; - } + auto answer = eye<6>(); + answer.at(4, 4) *= 0.5; + answer.at(5, 5) *= 0.5; + answer.at(6, 6) *= 0.5; if ( normeps2 != 0 ) { - FloatMatrix op; - if ( eps.giveSize() == 3 ) { - eps.at(3) *= 0.5; - } else if ( eps.giveSize() == 4 ) { - eps.at(4) *= 0.5; - } else { - eps.at(4) *= 0.5; - eps.at(5) *= 0.5; - eps.at(6) *= 0.5; - } - op.beDyadicProductOf(eps, eps); - answer.times( 2 * viscosity * ( 1 + c * pow(normeps2, alpha * 0.5) ) ); - answer.add(2 * viscosity * c * alpha * pow(normeps2, alpha * 0.5 - 1), op); + auto eps = status->giveTempDeviatoricStrainVector(); + + eps.at(4) *= 0.5; + eps.at(5) *= 0.5; + eps.at(6) *= 0.5; + + auto op = dyad(eps, eps); + answer *= 2 * viscosity * ( 1 + c * pow(normeps2, alpha * 0.5) ); + answer += (2 * viscosity * c * alpha * pow(normeps2, alpha * 0.5 - 1)) * op; } else { - answer.times(2 * viscosity); + answer *= 2 * viscosity; } + return answer; } int NonlinearFluidMaterial :: checkConsistency() { if ( domain->giveEngngModel()->giveEquationScalingFlag() ) { - double scale; - scale = domain->giveEngngModel()->giveVariableScale(VST_Density); + double scale = domain->giveEngngModel()->giveVariableScale(VST_Density); propertyDictionary.at('d') /= scale; scale = domain->giveEngngModel()->giveVariableScale(VST_Viscosity); @@ -185,11 +155,8 @@ NonlinearFluidMaterial :: checkConsistency() return 1; } -NonlinearFluidMaterialStatus :: NonlinearFluidMaterialStatus(int n, Domain *d, GaussPoint *g) : - FluidDynamicMaterialStatus(n, d, g), - temp_deviatoricStressVector(), - temp_deviatoricStrainVector(), - temp_norm2(0) +NonlinearFluidMaterialStatus :: NonlinearFluidMaterialStatus(GaussPoint *g) : + FluidDynamicMaterialStatus(g) { } void diff --git a/src/fm/nonlinearfluidmaterial.h b/src/fm/Materials/nonlinearfluidmaterial.h similarity index 63% rename from src/fm/nonlinearfluidmaterial.h rename to src/fm/Materials/nonlinearfluidmaterial.h index 86f3076be..12ad1e46f 100644 --- a/src/fm/nonlinearfluidmaterial.h +++ b/src/fm/Materials/nonlinearfluidmaterial.h @@ -35,7 +35,7 @@ #ifndef nonlinearfluidmaterial_h #define nonlinearfluidmaterial_h -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "floatarray.h" #include "floatmatrix.h" #include "matconst.h" @@ -60,27 +60,25 @@ class GaussPoint; class NonlinearFluidMaterialStatus : public FluidDynamicMaterialStatus { protected: - FloatArray temp_deviatoricStressVector; - FloatArray temp_deviatoricStrainVector; - double temp_norm2; + FloatArrayF<6> temp_deviatoricStressVector; + FloatArrayF<6> temp_deviatoricStrainVector; + double temp_norm2 = 0.; public: - NonlinearFluidMaterialStatus(int n, Domain * d, GaussPoint * g); + NonlinearFluidMaterialStatus(GaussPoint * g); - virtual ~NonlinearFluidMaterialStatus() { } + void initTempStatus() override; - virtual void initTempStatus(); + void updateYourself(TimeStep *tStep) override; - virtual void updateYourself(TimeStep *); - - const FloatArray &giveTempDeviatoricStressVector() { return temp_deviatoricStressVector; } - const FloatArray &giveTempDeviatoricStrainVector() { return temp_deviatoricStrainVector; } + const FloatArrayF<6> &giveTempDeviatoricStressVector() { return temp_deviatoricStressVector; } + const FloatArrayF<6> &giveTempDeviatoricStrainVector() { return temp_deviatoricStrainVector; } double giveTempStrainNorm2() { return temp_norm2; } - void letTempDeviatoricStressVectorBe(FloatArray v) { temp_deviatoricStressVector = std :: move(v); } - void letTempDeviatoricStrainVectorBe(FloatArray v) { temp_deviatoricStrainVector = std :: move(v); } + void letTempDeviatoricStressVectorBe(const FloatArrayF<6> &v) { temp_deviatoricStressVector = v; } + void letTempDeviatoricStrainVectorBe(const FloatArrayF<6> &v) { temp_deviatoricStrainVector = v; } void letTempStrainNorm2Be(double v) { temp_norm2 = v; } - virtual const char *giveClassName() const { return "NonlinearFluidMaterialStatus"; } + const char *giveClassName() const override { return "NonlinearFluidMaterialStatus"; } }; /** @@ -105,25 +103,22 @@ class NonlinearFluidMaterial : public FluidDynamicMaterial public: NonlinearFluidMaterial(int n, Domain * d) : FluidDynamicMaterial(n, d) { } - virtual ~NonlinearFluidMaterial() { } - - virtual void computeDeviatoricStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep); + FloatArrayF<6> computeDeviatoricStress3D(const FloatArrayF<6> &eps, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode, GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> computeTangent3D(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep); - virtual double give(int aProperty, GaussPoint *); + double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const override; + double give(int aProperty, GaussPoint *) const override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual const char *giveClassName() const { return "NewtonianFluidMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_NonlinearFluidMaterial_Name; } + const char *giveClassName() const override { return "NewtonianFluidMaterial"; } + const char *giveInputRecordName() const override { return _IFT_NonlinearFluidMaterial_Name; } - virtual int checkConsistency(); + int checkConsistency() override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; }; } // end namespace oofem #endif // nonlinearfluidmaterial_h diff --git a/src/fm/twofluidmaterial.C b/src/fm/Materials/twofluidmaterial.C similarity index 61% rename from src/fm/twofluidmaterial.C rename to src/fm/Materials/twofluidmaterial.C index dedbf4a0c..b349d4e68 100644 --- a/src/fm/twofluidmaterial.C +++ b/src/fm/Materials/twofluidmaterial.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "twofluidmaterial.h" +#include "fm/Materials/twofluidmaterial.h" #include "domain.h" #include "floatmatrix.h" #include "gausspoint.h" @@ -40,6 +40,7 @@ #include "materialinterface.h" #include "dynamicinputrecord.h" #include "classfactory.h" +#include "gausspoint.h" namespace oofem { REGISTER_Material(TwoFluidMaterial); @@ -52,18 +53,13 @@ TwoFluidMaterial :: checkConsistency() } -IRResultType -TwoFluidMaterial :: initializeFrom(InputRecord *ir) +void +TwoFluidMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, this->slaveMaterial, _IFT_TwoFluidMaterial_mat); if ( this->slaveMaterial.giveSize() != 2 ) { - OOFEM_WARNING("mat array should have two values"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_TwoFluidMaterial_mat, "mat array should have two values"); } - - return IRRT_OK; } @@ -76,7 +72,7 @@ TwoFluidMaterial :: giveInputRecord(DynamicInputRecord &input) double -TwoFluidMaterial :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) +TwoFluidMaterial :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const { TwoFluidMaterialStatus *status = static_cast< TwoFluidMaterialStatus * >( this->giveStatus(gp) ); double vof = this->giveTempVOF(gp); @@ -86,7 +82,7 @@ TwoFluidMaterial :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) double -TwoFluidMaterial :: give(int aProperty, GaussPoint *gp) +TwoFluidMaterial :: give(int aProperty, GaussPoint *gp) const { TwoFluidMaterialStatus *status = static_cast< TwoFluidMaterialStatus * >( this->giveStatus(gp) ); double vof = this->giveTempVOF(gp); @@ -111,51 +107,46 @@ TwoFluidMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStat MaterialStatus * TwoFluidMaterial :: CreateStatus(GaussPoint *gp) const { - return new TwoFluidMaterialStatus(1, this->giveDomain(), gp, this->slaveMaterial); + return new TwoFluidMaterialStatus(gp, {this->giveMaterial(0), this->giveMaterial(1)}); } FluidDynamicMaterial * TwoFluidMaterial :: giveMaterial(int i) const { - return static_cast< FluidDynamicMaterial * >( domain->giveMaterial( slaveMaterial(i) ) ); + return static_cast< FluidDynamicMaterial * >( domain->giveMaterial( slaveMaterial[i] ) ); } -void -TwoFluidMaterial :: computeDeviatoricStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep) +FloatArrayF<6> +TwoFluidMaterial :: computeDeviatoricStress3D(const FloatArrayF<6> &eps, GaussPoint *gp, TimeStep *tStep) const { double vof = this->giveTempVOF(gp); - FloatArray v0, v1; TwoFluidMaterialStatus *status = static_cast< TwoFluidMaterialStatus * >( this->giveStatus(gp) ); - this->giveMaterial(0)->computeDeviatoricStressVector(v0, status->giveSlaveGaussPoint0(), eps, tStep); - this->giveMaterial(1)->computeDeviatoricStressVector(v1, status->giveSlaveGaussPoint1(), eps, tStep); + auto v0 = this->giveMaterial(0)->computeDeviatoricStress3D(eps, status->giveSlaveGaussPoint0(), tStep); + auto v1 = this->giveMaterial(1)->computeDeviatoricStress3D(eps, status->giveSlaveGaussPoint1(), tStep); - answer.clear(); - answer.add(1.0 - vof, v0); - answer.add(vof, v1); + auto stress = (1.0 - vof) * v0 + vof * v1; status->letDeviatoricStrainRateVectorBe(eps); - status->letDeviatoricStressVectorBe(answer); + status->letDeviatoricStressVectorBe(stress); + + return stress; } -void -TwoFluidMaterial :: giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF<6,6> +TwoFluidMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix a0, a1; double vof = this->giveTempVOF(gp); TwoFluidMaterialStatus *status = static_cast< TwoFluidMaterialStatus * >( this->giveStatus(gp) ); - this->giveMaterial(0)->giveDeviatoricStiffnessMatrix(a0, mode, status->giveSlaveGaussPoint0(), tStep); - this->giveMaterial(1)->giveDeviatoricStiffnessMatrix(a1, mode, status->giveSlaveGaussPoint1(), tStep); + auto a0 = this->giveMaterial(0)->computeTangent3D(mode, status->giveSlaveGaussPoint0(), tStep); + auto a1 = this->giveMaterial(1)->computeTangent3D(mode, status->giveSlaveGaussPoint1(), tStep); - answer.clear(); - answer.add(1.0 - vof, a0); - answer.add(vof, a1); + return (1.0 - vof) * a0 + vof * a1; } double -TwoFluidMaterial :: giveTempVOF(GaussPoint *gp) +TwoFluidMaterial :: giveTempVOF(GaussPoint *gp) const { FloatArray vof(2); MaterialInterface *mi = domain->giveEngngModel()->giveMaterialInterface( domain->giveNumber() ); @@ -175,21 +166,18 @@ TwoFluidMaterial :: giveTempVOF(GaussPoint *gp) -TwoFluidMaterialStatus :: TwoFluidMaterialStatus(int n, Domain *d, GaussPoint *gp, const IntArray &slaveMaterial) : - FluidDynamicMaterialStatus(n, d, gp), - slaveGp0( new GaussPoint(NULL, 0, FloatArray(), 0., gp->giveMaterialMode()) ), - slaveGp1( new GaussPoint(NULL, 0, FloatArray(), 0., gp->giveMaterialMode()) ) +TwoFluidMaterialStatus :: TwoFluidMaterialStatus(GaussPoint *gp, const std::array &slaveMaterial) : + FluidDynamicMaterialStatus(gp), + slaveGps{{{nullptr, 0, 0., gp->giveMaterialMode()}, {nullptr, 0, 0., gp->giveMaterialMode()}}} { - this->slaveGp0->setMaterialStatus( domain->giveMaterial( slaveMaterial(0) )->CreateStatus(this->slaveGp0.get()), this->giveNumber() ); - this->slaveGp1->setMaterialStatus( domain->giveMaterial( slaveMaterial(1) )->CreateStatus(this->slaveGp0.get()), this->giveNumber() ); + for ( int i = 0; i < 2; ++i ) slaveGps[i].setMaterialStatus( slaveMaterial[i]->CreateStatus( &slaveGps[i] ) ); } void -TwoFluidMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +TwoFluidMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { - this->giveSlaveGaussPoint0()->giveMaterialStatus()->printOutputAt(file, tStep); - this->giveSlaveGaussPoint1()->giveMaterialStatus()->printOutputAt(file, tStep); + for ( auto &gp : slaveGps ) gp.giveMaterialStatus()->printOutputAt(file, tStep); } @@ -197,8 +185,7 @@ void TwoFluidMaterialStatus :: updateYourself(TimeStep *tStep) { FluidDynamicMaterialStatus :: updateYourself(tStep); - this->giveSlaveGaussPoint0()->giveMaterialStatus()->updateYourself(tStep); - this->giveSlaveGaussPoint1()->giveMaterialStatus()->updateYourself(tStep); + for ( auto &gp : slaveGps ) gp.giveMaterialStatus()->updateYourself(tStep); } @@ -206,25 +193,20 @@ void TwoFluidMaterialStatus :: initTempStatus() { FluidDynamicMaterialStatus :: initTempStatus(); - static_cast< MaterialStatus * >( this->giveSlaveGaussPoint0()->giveMaterialStatus() )->initTempStatus(); - static_cast< MaterialStatus * >( this->giveSlaveGaussPoint1()->giveMaterialStatus() )->initTempStatus(); + for ( auto &gp : slaveGps ) static_cast< MaterialStatus * >( gp.giveMaterialStatus() )->initTempStatus(); } -contextIOResultType -TwoFluidMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +TwoFluidMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - this->giveSlaveGaussPoint0()->giveMaterialStatus()->saveContext(stream, mode, obj); - this->giveSlaveGaussPoint1()->giveMaterialStatus()->saveContext(stream, mode, obj); - return CIO_OK; + for ( auto &gp : slaveGps ) gp.giveMaterialStatus()->saveContext(stream, mode); } -contextIOResultType -TwoFluidMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +TwoFluidMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - this->giveSlaveGaussPoint0()->giveMaterialStatus()->restoreContext(stream, mode, obj); - this->giveSlaveGaussPoint1()->giveMaterialStatus()->restoreContext(stream, mode, obj); - return CIO_OK; + for ( auto &gp : slaveGps ) gp.giveMaterialStatus()->restoreContext(stream, mode); } } // end namespace oofem diff --git a/src/fm/twofluidmaterial.h b/src/fm/Materials/twofluidmaterial.h similarity index 56% rename from src/fm/twofluidmaterial.h rename to src/fm/Materials/twofluidmaterial.h index 6e88e2c39..9083c0277 100644 --- a/src/fm/twofluidmaterial.h +++ b/src/fm/Materials/twofluidmaterial.h @@ -35,11 +35,13 @@ #ifndef twofluidmaterial_h #define twofluidmaterial_h -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "intarray.h" #include "matstatus.h" +#include "gausspoint.h" #include +#include ///@name Input fields for TwoFluidMaterial //@{ @@ -48,7 +50,6 @@ //@} namespace oofem { -class GaussPoint; /** * Material coupling the behavior of two particular materials based on @@ -66,52 +67,49 @@ class TwoFluidMaterial : public FluidDynamicMaterial * @param d Domain to which new material will belong. */ TwoFluidMaterial(int n, Domain * d) : FluidDynamicMaterial(n, d) { } - /// Destructor. - virtual ~TwoFluidMaterial() { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void computeDeviatoricStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep); - virtual void giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + FloatArrayF<6> computeDeviatoricStress3D(const FloatArrayF<6> &answer, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<6,6> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep); - virtual double give(int aProperty, GaussPoint *gp); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual const char *giveClassName() const { return "TwoFluidMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_TwoFluidMaterial_Name; } - virtual int checkConsistency(); - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + double giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) const override; + double give(int aProperty, GaussPoint *gp) const override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + const char *giveClassName() const override { return "TwoFluidMaterial"; } + const char *giveInputRecordName() const override { return _IFT_TwoFluidMaterial_Name; } + int checkConsistency() override; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: FluidDynamicMaterial *giveMaterial(int i) const; - double giveTempVOF(GaussPoint *gp); + double giveTempVOF(GaussPoint *gp) const; }; class TwoFluidMaterialStatus : public FluidDynamicMaterialStatus { protected: - std :: unique_ptr< GaussPoint >slaveGp0; - std :: unique_ptr< GaussPoint >slaveGp1; + std::array slaveGps; + ///@todo This should technically suffice; + //std::array, 2> slaveStatus; public: /// Constructor - TwoFluidMaterialStatus(int n, Domain * d, GaussPoint * g, const IntArray & slaveMaterial); - /// Destructor - virtual ~TwoFluidMaterialStatus() { } + TwoFluidMaterialStatus(GaussPoint * g, const std::array &slaveMaterial); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual const char *giveClassName() const { return "TwoFluidMaterialStatus"; } + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + const char *giveClassName() const override { return "TwoFluidMaterialStatus"; } - GaussPoint *giveSlaveGaussPoint0() { return this->slaveGp0.get(); } - GaussPoint *giveSlaveGaussPoint1() { return this->slaveGp1.get(); } + GaussPoint *giveSlaveGaussPoint0() { return &this->slaveGps[0]; } + GaussPoint *giveSlaveGaussPoint1() { return &this->slaveGps[1]; } }; } // end namespace oofem #endif // twofluidmaterial_h diff --git a/src/fm/binghamfluid2.C b/src/fm/binghamfluid2.C deleted file mode 100644 index 58205f96f..000000000 --- a/src/fm/binghamfluid2.C +++ /dev/null @@ -1,683 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "binghamfluid2.h" -#include "fluiddynamicmaterial.h" -#include "domain.h" -#include "floatmatrix.h" -#include "gausspoint.h" -#include "engngm.h" -#include "mathfem.h" -#include "datastream.h" -#include "contextioerr.h" -#include "dynamicinputrecord.h" -#include "classfactory.h" - -#include - -namespace oofem { -#define BINGHAM_ALT 1 -#define BINGHAM_MIN_SHEAR_RATE 1.e-10 - -REGISTER_Material(BinghamFluidMaterial2); -///@todo Remove the alternative ID. Just stick to "binghamfluid". -static bool __dummy_BinghamFluidMaterial2_alt __attribute__((unused)) = GiveClassFactory().registerMaterial("binghamfluid2", matCreator< BinghamFluidMaterial2 > ); - -BinghamFluidMaterial2 :: BinghamFluidMaterial2(int n, Domain *d) : FluidDynamicMaterial(n, d), - mu_0(0.), - tau_0(0.), - tau_c(0.), - mu_inf(1.e6), - stressGrowthRate(BINGHAM_DEFAULT_STRESS_GROWTH_RATE) -{ } - - -IRResultType -BinghamFluidMaterial2 :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - // we use rather object's member data than to store data into slow - // key-val dictionary with lot of memory allocations - IR_GIVE_FIELD(ir, mu_0, _IFT_BinghamFluidMaterial2_mu0); - IR_GIVE_FIELD(ir, tau_0, _IFT_BinghamFluidMaterial2_tau0); - mu_inf = 1.e6; - IR_GIVE_OPTIONAL_FIELD(ir, mu_inf, _IFT_BinghamFluidMaterial2_muinf); - stressGrowthRate = BINGHAM_DEFAULT_STRESS_GROWTH_RATE; - IR_GIVE_OPTIONAL_FIELD(ir, stressGrowthRate, _IFT_BinghamFluidMaterial2_stressGrowthRate); - tau_c = tau_0 * mu_inf / ( mu_inf - mu_0 ); - //tau_c = tau_0; - return FluidDynamicMaterial :: initializeFrom(ir); -} - - -void -BinghamFluidMaterial2 :: giveInputRecord(DynamicInputRecord &input) -{ - FluidDynamicMaterial :: giveInputRecord(input); - input.setField(this->mu_0, _IFT_BinghamFluidMaterial2_mu0); - input.setField(this->tau_0, _IFT_BinghamFluidMaterial2_tau0); - input.setField(this->mu_inf, _IFT_BinghamFluidMaterial2_muinf); - input.setField(this->stressGrowthRate, _IFT_BinghamFluidMaterial2_stressGrowthRate); -} - -double -BinghamFluidMaterial2 :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) -{ - BinghamFluidMaterial2Status *status = static_cast< BinghamFluidMaterial2Status * >( this->giveStatus(gp) ); - //double temp_tau=status->giveTempDevStressMagnitude(); - //double temp_gamma=status->giveTempDevStrainMagnitude(); - //determine actual viscosity - //return this->computeActualViscosity(temp_tau, temp_gamma); -#ifdef BINGHAM_ALT - double gamma = status->giveTempDevStrainMagnitude(); //status->giveTempDevStrainMagnitude(); - return computeActualViscosity(tau_0, gamma); - - #if 0 - const FloatArray &epsd = status->giveTempDeviatoricStrainVector(); //status->giveTempDeviatoricStrainVector(); - double gamma2 = gamma * gamma; - double dmudg, dgde1, dgde2, dgde3, mu; - if ( gamma < BINGHAM_MIN_SHEAR_RATE ) { - dmudg = dgde1 = dgde2 = dgde3 = 0.0; - mu = computeActualViscosity(tau_0, gamma); - } else { - dmudg = ( -1.0 ) * tau_0 * ( 1.0 - exp(-this->stressGrowthRate * gamma) ) / gamma2 + - tau_0 *this->stressGrowthRate *exp(-this->stressGrowthRate *gamma) / gamma; - mu = mu_0 + tau_0 * ( 1. - exp(-this->stressGrowthRate * gamma) ) / gamma; - - dgde1 = 2.0 * fabs( epsd.at(1) ) / gamma; - dgde2 = 2.0 * fabs( epsd.at(2) ) / gamma; - dgde3 = 1.0 * fabs( epsd.at(3) ) / gamma; - } - - return min( min( ( epsd.at(1) * dmudg * dgde1 + mu ), ( epsd.at(2) * dmudg * dgde2 + mu ) ), - ( epsd.at(3) * dmudg * dgde3 + mu ) ); - - #endif - -#else - if ( temp_tau < tau_c ) { - return mu_inf; - } else { - return mu_0; - } - -#endif -} - - -double -BinghamFluidMaterial2 :: give(int aProperty, GaussPoint *gp) -{ - if ( aProperty == Viscosity ) { - return mu_0; - } else if ( aProperty == YieldStress ) { - return tau_0; - } else { - return FluidDynamicMaterial :: give(aProperty, gp); - } -} - - -MaterialStatus * -BinghamFluidMaterial2 :: CreateStatus(GaussPoint *gp) const -{ - return new BinghamFluidMaterial2Status(1, this->giveDomain(), gp); -} - - -void -BinghamFluidMaterial2 :: computeDeviatoricStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep) -{ - int size = eps.giveSize(); - answer.resize(size); - BinghamFluidMaterial2Status *status = static_cast< BinghamFluidMaterial2Status * >( this->giveStatus(gp) ); - MaterialMode mmode = gp->giveMaterialMode(); - FloatArray epsd; - double gamma, tau, _nu; - - // determine actual viscosity - this->computeDeviatoricStrain(epsd, eps, mmode); - // determine shear strain magnitude - gamma = this->computeDevStrainMagnitude(mmode, epsd); - -#ifdef BINGHAM_ALT - _nu = computeActualViscosity(tau_0, gamma); - this->computeDeviatoricStress(answer, epsd, _nu, mmode); - tau = this->computeDevStressMagnitude(mmode, answer); - - //printf ("_nu %e gamma %e\n", _nu, gamma); -#else - // compute trial state - this->computeDeviatoricStress(answer, epsd, this->mu_inf, mmode); - // check if state allowed - tau = this->computeDevStressMagnitude(mmode, answer); - if ( tau > this->tau_c ) { - _nu = this->computeActualViscosity(tau, gamma); - this->computeDeviatoricStress(answer, epsd, _nu, mmode); - tau = this->computeDevStressMagnitude(mmode, answer); - } - -#endif - // update status - status->letTempDeviatoricStrainVectorBe(epsd); - status->letDeviatoricStressVectorBe(answer); - status->letTempDevStrainMagnitudeBe(gamma); - status->letTempDevStressMagnitudeBe(tau); -} - -void -BinghamFluidMaterial2 :: giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) -{ - BinghamFluidMaterial2Status *status = static_cast< BinghamFluidMaterial2Status * >( this->giveStatus(gp) ); - MaterialMode mmode = gp->giveMaterialMode(); - const FloatArray &epsd = status->giveTempDeviatoricStrainVector(); //status->giveTempDeviatoricStrainVector(); - ///@note This variable was actually never used: - //double tau = status->giveTempDevStressMagnitude(); - double gamma = status->giveTempDevStrainMagnitude(); //status->giveTempDevStrainMagnitude(); - // determine actual viscosity - double gamma2 = gamma * gamma; - - if ( mmode == _2dFlow ) { - answer.resize(3, 3); - answer.zero(); - - double dgde1, dgde2, dgde3; - double dmudg, mu; - -#if 0 - double _nu = computeActualViscosity(tau_0, gamma); - - answer.at(1, 1) = answer.at(2, 2) = 2.0 * _nu; - answer.at(3, 3) = _nu; - - //answer.at(1,1) = answer.at(2,2) = answer.at(3,3) = 2.0*_nu; - //answer.at(4,4) = _nu; - return; -#endif - - if ( ( mode == ElasticStiffness ) || ( mode == SecantStiffness ) ) { - double _nu = computeActualViscosity(tau_0, gamma); - answer.at(1, 1) = answer.at(2, 2) = 2.0 * _nu; - answer.at(3, 3) = _nu; - return; - } else { // tangent stiffness - if ( gamma < BINGHAM_MIN_SHEAR_RATE ) { - dmudg = dgde1 = dgde2 = dgde3 = 0.0; - mu = computeActualViscosity(tau_0, gamma); - } else { - dmudg = ( -1.0 ) * tau_0 * ( 1.0 - exp(-this->stressGrowthRate * gamma) ) / gamma2 + - tau_0 *this->stressGrowthRate *exp(-this->stressGrowthRate *gamma) / gamma; - mu = mu_0 + tau_0 * ( 1. - exp(-this->stressGrowthRate * gamma) ) / gamma; - -#if 1 - //dgde1 = 2.0 * fabs( epsd.at(1) ) / gamma; - //dgde2 = 2.0 * fabs( epsd.at(2) ) / gamma; - //dgde3 = 1.0 * fabs( epsd.at(3) ) / gamma; - dgde1 = 0.5 * fabs( epsd.at(1) ) / gamma; - dgde2 = 0.5 * fabs( epsd.at(2) ) / gamma; - dgde3 = 1.0 * fabs( epsd.at(3) ) / gamma; -#else - //dgde1 = 2.0 * epsd.at(1) / gamma; - //dgde2 = 2.0 * epsd.at(2) / gamma; - //dgde3 = 1.0 * epsd.at(3) / gamma; -#endif - } - - answer.at(1, 1) = 2.0 * epsd.at(1) * dmudg * dgde1 + 2.0 * mu; - answer.at(1, 2) = 2.0 * epsd.at(1) * dmudg * dgde2; - answer.at(1, 3) = 2.0 * epsd.at(1) * dmudg * dgde3; - - answer.at(2, 1) = 2.0 * epsd.at(2) * dmudg * dgde1; - answer.at(2, 2) = 2.0 * epsd.at(2) * dmudg * dgde2 + 2.0 * mu; - answer.at(2, 3) = 2.0 * epsd.at(2) * dmudg * dgde3; - - answer.at(3, 1) = epsd.at(3) * dmudg * dgde1; - answer.at(3, 2) = epsd.at(3) * dmudg * dgde2; - answer.at(3, 3) = epsd.at(3) * dmudg * dgde3 + mu; - - return; - } - } else if ( mmode == _2dAxiFlow ) { - answer.resize(4, 4); - answer.zero(); - - - double dgde1, dgde2, dgde3, dgde4; - double dmudg, mu; - - if ( 0 ) { - double _nu = computeActualViscosity(tau_0, gamma); - - answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = 2.0 * _nu; - answer.at(4, 4) = _nu; - - //answer.at(1,1) = answer.at(2,2) = answer.at(3,3) = 2.0*_nu; - //answer.at(4,4) = _nu; - return; - } - - if ( ( mode == ElasticStiffness ) || ( mode == SecantStiffness ) ) { - double _nu = computeActualViscosity(tau_0, gamma); - answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = 2.0 * _nu; - answer.at(4, 4) = _nu; - return; - } else { // tangent stiffness - if ( gamma < BINGHAM_MIN_SHEAR_RATE ) { - dmudg = dgde1 = dgde2 = dgde3 = dgde4 = 0.0; - mu = computeActualViscosity(tau_0, gamma); - } else { - dmudg = ( -1.0 ) * tau_0 * ( 1.0 - exp(-this->stressGrowthRate * gamma) ) / gamma2 + - tau_0 *this->stressGrowthRate *exp(-this->stressGrowthRate *gamma) / gamma; - mu = mu_0 + tau_0 * ( 1. - exp(-this->stressGrowthRate * gamma) ) / gamma; - -#if 1 - dgde1 = 2.0 * fabs( epsd.at(1) ) / gamma; - dgde2 = 2.0 * fabs( epsd.at(2) ) / gamma; - dgde3 = 2.0 * fabs( epsd.at(3) ) / gamma; - dgde4 = 1.0 * fabs( epsd.at(4) ) / gamma; -#else - dgde1 = 2.0 * epsd.at(1) / gamma; - dgde2 = 2.0 * epsd.at(2) / gamma; - dgde3 = 2.0 * epsd.at(3) / gamma; - dgde4 = 1.0 * epsd.at(4) / gamma; -#endif - } - - answer.at(1, 1) = 2.0 * epsd.at(1) * dmudg * dgde1 + 2.0 * mu; - answer.at(1, 2) = 2.0 * epsd.at(1) * dmudg * dgde2; - answer.at(1, 3) = 2.0 * epsd.at(1) * dmudg * dgde3; - answer.at(1, 4) = 2.0 * epsd.at(1) * dmudg * dgde4; - - answer.at(2, 1) = 2.0 * epsd.at(2) * dmudg * dgde1; - answer.at(2, 2) = 2.0 * epsd.at(2) * dmudg * dgde2 + 2.0 * mu; - answer.at(2, 3) = 2.0 * epsd.at(2) * dmudg * dgde3; - answer.at(2, 4) = 2.0 * epsd.at(2) * dmudg * dgde4; - - answer.at(3, 1) = 2.0 * epsd.at(3) * dmudg * dgde1; - answer.at(3, 2) = 2.0 * epsd.at(3) * dmudg * dgde2; - answer.at(3, 3) = 2.0 * epsd.at(3) * dmudg * dgde3 + 2.0 * mu; - answer.at(3, 4) = 2.0 * epsd.at(3) * dmudg * dgde4; - - - answer.at(4, 1) = epsd.at(4) * dmudg * dgde1; - answer.at(4, 2) = epsd.at(4) * dmudg * dgde2; - answer.at(4, 3) = epsd.at(4) * dmudg * dgde3; - answer.at(4, 4) = epsd.at(4) * dmudg * dgde4 + mu; - - return; - } - } else if ( gp->giveMaterialMode() == _3dFlow ) { - answer.resize(6, 6); - answer.zero(); - - FloatArray dgde(6); - double dmudg, mu; - - if ( gamma < BINGHAM_MIN_SHEAR_RATE ) { - dmudg = 0.0; - dgde.zero(); - mu = computeActualViscosity(tau_0, gamma); - } else { - dmudg = ( -1.0 ) * tau_0 * ( 1.0 - exp(-this->stressGrowthRate * gamma) ) / gamma2 + - tau_0 *this->stressGrowthRate *exp(-this->stressGrowthRate *gamma) / gamma; - mu = mu_0 + tau_0 * ( 1. - exp(-this->stressGrowthRate * gamma) ) / gamma; - - dgde.at(1) = 2.0 * epsd.at(1) / gamma; - dgde.at(2) = 2.0 * epsd.at(2) / gamma; - dgde.at(3) = 2.0 * epsd.at(3) / gamma; - dgde.at(4) = 1.0 * epsd.at(4) / gamma; - dgde.at(5) = 1.0 * epsd.at(5) / gamma; - dgde.at(6) = 1.0 * epsd.at(6) / gamma; - } - - for ( int i = 1; i <= 6; i++ ) { - answer.at(1, i) = fabs( 2.0 * epsd.at(1) * dmudg * dgde.at(i) ); - answer.at(2, i) = fabs( 2.0 * epsd.at(2) * dmudg * dgde.at(i) ); - answer.at(3, i) = fabs( 2.0 * epsd.at(3) * dmudg * dgde.at(i) ); - answer.at(4, i) = fabs( epsd.at(4) * dmudg * dgde.at(i) ); - answer.at(5, i) = fabs( epsd.at(5) * dmudg * dgde.at(i) ); - answer.at(6, i) = fabs( epsd.at(6) * dmudg * dgde.at(i) ); - } - - answer.at(1, 1) += 2.0 * mu; - answer.at(2, 2) += 2.0 * mu; - answer.at(3, 3) += 2.0 * mu; - answer.at(4, 4) += mu; - answer.at(5, 5) += mu; - answer.at(6, 6) += mu; - - return; - } else { - OOFEM_ERROR("unsupportted material mode"); - } -} - - -int -BinghamFluidMaterial2 :: checkConsistency() -{ - if ( domain->giveEngngModel()->giveEquationScalingFlag() ) { - double scale; - scale = domain->giveEngngModel()->giveVariableScale(VST_Density); - propertyDictionary.at('d') /= scale; - - scale = domain->giveEngngModel()->giveVariableScale(VST_Viscosity); - this->mu_0 /= scale; - this->tau_0 /= scale; - } - - return 1; -} - -double -BinghamFluidMaterial2 :: computeActualViscosity(double Tau, double shearRate) -{ -#ifdef BINGHAM_ALT - if ( tau_0 > 0.0 ) { - shearRate = max(shearRate, BINGHAM_MIN_SHEAR_RATE); - return ( mu_0 + tau_0 * ( 1. - exp(-this->stressGrowthRate * shearRate) ) / shearRate ); - } else { - // newtonian flow - return mu_0; - } - -#else - if ( Tau <= tau_c ) { - return this->mu_inf; - } else { - return mu_0 + ( tau_0 / shearRate ); - } - -#endif -} - - -double -BinghamFluidMaterial2 :: computeDevStrainMagnitude(MaterialMode mmode, const FloatArray &epsd) -{ - double _val = 0.0; - if ( mmode == _2dFlow ) { - // _val = 2.0 * ( epsd.at(1) * epsd.at(1) + epsd.at(2) * epsd.at(2) ) + epsd.at(3) * epsd.at(3); - _val = 0.5 * ( epsd.at(1) * epsd.at(1) + epsd.at(2) * epsd.at(2) ) + epsd.at(3) * epsd.at(3); - } else if ( mmode == _2dAxiFlow ) { - _val = 2.0 * ( epsd.at(1) * epsd.at(1) + epsd.at(2) * epsd.at(2) + - epsd.at(3) * epsd.at(3) ) + epsd.at(4) * epsd.at(4); - } else if ( mmode == _3dFlow ) { - _val = 2.0 * ( epsd.at(1) * epsd.at(1) + epsd.at(2) * epsd.at(2) + epsd.at(3) * epsd.at(3) ) - + epsd.at(4) * epsd.at(4) + epsd.at(5) * epsd.at(5) + epsd.at(6) * epsd.at(6); - } else { - OOFEM_ERROR("unsupported material mode"); - } - - return sqrt(_val); -} - -double -BinghamFluidMaterial2 :: computeDevStressMagnitude(MaterialMode mmode, const FloatArray &sigd) -{ - double _val = 0.0; - if ( mmode == _2dFlow ) { - _val = 0.5 * ( sigd.at(1) * sigd.at(1) + sigd.at(2) * sigd.at(2) + 2.0 * sigd.at(3) * sigd.at(3) ); - } else if ( mmode == _2dAxiFlow ) { - _val = 0.5 * ( sigd.at(1) * sigd.at(1) + - sigd.at(2) * sigd.at(2) + - sigd.at(3) * sigd.at(3) + - 2.0 * sigd.at(4) * sigd.at(4) ); - } else if ( mmode == _3dFlow ) { - _val = 0.5 * ( sigd.at(1) * sigd.at(1) + sigd.at(2) * sigd.at(2) + sigd.at(3) * sigd.at(3) + - 2.0 * sigd.at(4) * sigd.at(4) + 2.0 * sigd.at(5) * sigd.at(5) + 2.0 * sigd.at(6) * sigd.at(6) ); - } else { - OOFEM_ERROR("unsupported material mode"); - } - - return sqrt(_val); -} - -void -BinghamFluidMaterial2 :: computeDeviatoricStrain(FloatArray &answer, const FloatArray &eps, MaterialMode mmode) -{ - if ( mmode == _2dFlow ) { - //double ekk=(eps.at(1)+eps.at(2))/3.0; - double ekk = 0.0; - - answer = { - eps.at(1) - ekk, - eps.at(2) - ekk, - eps.at(3) - }; - } else if ( mmode == _2dAxiFlow ) { - //double ekk=(eps.at(1)+eps.at(2)+eps.at(3))/3.0; - double ekk = 0.0; - - answer = { - eps.at(1) - ekk, - eps.at(2) - ekk, - eps.at(3) - ekk, - eps.at(4) - }; - } else if ( mmode == _3dFlow ) { - //double ekk=(eps.at(1)+eps.at(2)+eps.at(3))/3.0; - double ekk = 0.0; - - answer = { - eps.at(1) - ekk, - eps.at(2) - ekk, - eps.at(3) - ekk, - eps.at(4), - eps.at(5), - eps.at(6) - }; - } else { - OOFEM_ERROR("unsupported material mode"); - } -} - - -void -BinghamFluidMaterial2 :: computeDeviatoricStress(FloatArray &answer, const FloatArray &deps, - double _nu, MaterialMode mmode) -{ - if ( mmode == _2dFlow ) { - answer = { - 2.0 * _nu * ( deps.at(1) ), - 2.0 * _nu * ( deps.at(2) ), - deps.at(3) * _nu - }; - } else if ( mmode == _2dAxiFlow ) { - answer = { - answer.at(1) = 2.0 * _nu * ( deps.at(1) ), - answer.at(2) = 2.0 * _nu * ( deps.at(2) ), - answer.at(3) = 2.0 * _nu * ( deps.at(3) ), - answer.at(4) = deps.at(4) * _nu, - }; - } else if ( mmode == _3dFlow ) { - answer = { - 2.0 * _nu * ( deps.at(1) ), - 2.0 * _nu * ( deps.at(2) ), - 2.0 * _nu * ( deps.at(3) ), - deps.at(4) * _nu, - deps.at(5) * _nu, - deps.at(6) * _nu - }; - } else { - OOFEM_ERROR("unsupported material mode"); - } -} - - -BinghamFluidMaterial2Status :: BinghamFluidMaterial2Status(int n, Domain *d, GaussPoint *g) : - FluidDynamicMaterialStatus(n, d, g) -{ - MaterialMode mmode = gp->giveMaterialMode(); - int _size = 0; - - devStrainMagnitude = temp_devStrainMagnitude = 0.0; - devStressMagnitude = temp_devStressMagnitude = 0.0; - - if ( mmode == _2dFlow ) { - _size = 3; - } else if ( mmode == _2dAxiFlow ) { - _size = 4; - } else if ( mmode == _3dFlow ) { - _size = 6; - } else { - OOFEM_ERROR("unsupported material mode"); - } - - deviatoricStrainRateVector.resize(_size); - deviatoricStrainRateVector.zero(); - deviatoricStressVector.resize(_size); - deviatoricStressVector.zero(); - temp_deviatoricStrainVector = deviatoricStrainRateVector; -} - -void -BinghamFluidMaterial2Status :: printOutputAt(FILE *File, TimeStep *tStep) -// Prints the strains and stresses on the data file. -{ - fprintf(File, " strains "); - for ( double e: deviatoricStrainRateVector ) { - fprintf( File, " %.4e", e ); - } - - fprintf(File, "\n deviatoric stresses"); - for ( double e: deviatoricStressVector ) { - fprintf( File, " %.4e", e ); - } - - fprintf(File, "\n status { gamma %e, tau %e }", devStrainMagnitude, devStressMagnitude); - - fprintf(File, "\n"); -} - -void -BinghamFluidMaterial2Status :: updateYourself(TimeStep *tStep) -// Performs end-of-step updates. -{ - FluidDynamicMaterialStatus :: updateYourself(tStep); - - devStrainMagnitude = temp_devStrainMagnitude; - devStressMagnitude = temp_devStressMagnitude; - deviatoricStrainRateVector = temp_deviatoricStrainVector; -} - - -void -BinghamFluidMaterial2Status :: initTempStatus() -// -// initialize record at the begining of new load step -// -{ - FluidDynamicMaterialStatus :: initTempStatus(); - - temp_devStrainMagnitude = devStrainMagnitude; - temp_devStressMagnitude = devStressMagnitude; - temp_deviatoricStrainVector = deviatoricStrainRateVector; -} - - -contextIOResultType -BinghamFluidMaterial2Status :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full ms context (saves state variables, that completely describe -// current state) -// saving the data in dictionary is left to material (yield crit. level). -{ - contextIOResultType iores; - - if ( ( iores = FluidDynamicMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( !stream.write(devStrainMagnitude) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.write(devStressMagnitude) ) { - THROW_CIOERR(CIO_IOERR); - } - - return CIO_OK; -} - - -contextIOResultType -BinghamFluidMaterial2Status :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full material context (saves state variables, that completely describe -// current state) -// -{ - contextIOResultType iores; - - if ( ( iores = FluidDynamicMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( !stream.read(devStrainMagnitude) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.read(devStressMagnitude) ) { - THROW_CIOERR(CIO_IOERR); - } - - return CIO_OK; -} - - -#if 0 -void -BinghamFluidMaterial2 :: __debug(GaussPoint *gp, TimeStep *tStep) -{ - BinghamFluidMaterial2Status *status = static_cast< BinghamFluidMaterial2Status * >( this->giveStatus(gp) ); - const FloatArray &epsd = status->giveTempDeviatoricStrainVector(); - const FloatArray &sigd = status->giveTempDeviatoricStrainVector() - for ( int i = 1; i <= nincr; i++ ) { - eps.add(eps_i); - computeDeviatoricStressVector(tau, gp, eps, tStep); - giveDeviatoricStiffnessMatrix(d, TangentStiffness, gp, tStep); - tau_t.beProductOf(d, eps_i); - tau_t.add(tau_p); - //tau.printYourself(); - //tau_t.printYourself(); - //d.printYourself(); - printf( "%e %e %e %e %e %e %e %e %e\n", eps.at(1), eps.at(2), eps.at(3), tau.at(1), tau.at(2), tau.at(3), tau_t.at(1), tau_t.at(2), tau_t.at(3) ); - tau_p = tau_t; - } -} -#endif -} // end namespace oofem diff --git a/src/fm/cbs.C b/src/fm/cbs.C index dee78bd6e..a7fdc06ac 100644 --- a/src/fm/cbs.C +++ b/src/fm/cbs.C @@ -73,7 +73,6 @@ void IntermediateConvectionDiffusionAssembler :: vectorFromElement(FloatArray &v void PrescribedVelocityRhsAssembler :: vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const { static_cast< CBSElement & >( element ).computePrescribedTermsI(vec, tStep); - } void DensityPrescribedTractionPressureAssembler :: vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const @@ -92,7 +91,6 @@ void DensityRhsAssembler :: vectorFromElement(FloatArray &vec, Element &element, void CorrectionRhsAssembler :: vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const { static_cast< CBSElement & >( element ).computeCorrectionRhs(vec, tStep); - } void PressureLhsAssembler :: matrixFromElement(FloatMatrix &answer, Element &element, TimeStep *tStep) const @@ -108,15 +106,14 @@ void PressureLhsAssembler :: locationFromElement(IntArray& loc, Element& element CBS :: CBS(int i, EngngModel* _master) : FluidModel ( i, _master ), - PressureField ( this, 1, FT_Pressure, 1 ), - VelocityField ( this, 1, FT_Velocity, 1 ), - vnum ( false ), vnumPrescribed ( true ), pnum ( false ), pnumPrescribed ( true ) + pressureField ( this, 1, FT_Pressure, 1 ), + velocityField ( this, 1, FT_Velocity, 1 ), + initFlag(1), consistentMassFlag(1), + vnum ( false ), vnumPrescribed ( true ), pnum ( false ), pnumPrescribed ( true ), + equationScalingFlag(false), + lscale(1.0), uscale(1.0), dscale(1.0), Re(1.0) { - initFlag = 1; ndomains = 1; - consistentMassFlag = 0; - equationScalingFlag = false; - lscale = uscale = dscale = 1.0; } CBS :: ~CBS() @@ -126,7 +123,7 @@ CBS :: ~CBS() NumericalMethod *CBS :: giveNumericalMethod(MetaStep *mStep) { if ( !nMethod ) { - nMethod.reset( classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this) ); + nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); if ( !nMethod ) { OOFEM_ERROR("linear solver creation failed for lstype %d", solverType); } @@ -134,11 +131,10 @@ NumericalMethod *CBS :: giveNumericalMethod(MetaStep *mStep) return nMethod.get(); } -IRResultType -CBS :: initializeFrom(InputRecord *ir) +void +CBS :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - + EngngModel :: initializeFrom(ir); int val = 0; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_lstype); solverType = ( LinSystSolverType ) val; @@ -175,36 +171,25 @@ CBS :: initializeFrom(InputRecord *ir) val = 0; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_CBS_miflag); if ( val ) { - this->materialInterface.reset( new LEPlic( 1, this->giveDomain(1) ) ); + this->materialInterface = std::make_unique( 1, this->giveDomain(1) ); // export velocity field FieldManager *fm = this->giveContext()->giveFieldManager(); IntArray mask = {V_u, V_v, V_w}; - //std::shared_ptr _velocityField = make_shared(FT_Velocity, &this->VelocityField, mask); - std :: shared_ptr< Field > _velocityField( new MaskedPrimaryField ( FT_Velocity, &this->VelocityField, mask ) ); + std::shared_ptr _velocityField = std::make_shared(FT_Velocity, &this->velocityField, mask); fm->registerField(_velocityField, FT_Velocity); } // - - return EngngModel :: initializeFrom(ir); } double CBS :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) -// returns unknown quantity like displacement, velocity of dof { -#ifdef DEBUG - if ( dof->__giveEquationNumber() == 0 ) { - OOFEM_ERROR("invalid equation number"); - } - -#endif - if ( dof->giveDofID() == P_f ) { // pressures - return PressureField.giveUnknownValue(dof, mode, tStep); + return pressureField.giveUnknownValue(dof, mode, tStep); } else { // velocities - return VelocityField.giveUnknownValue(dof, mode, tStep); + return velocityField.giveUnknownValue(dof, mode, tStep); } } @@ -238,16 +223,15 @@ CBS :: giveTractionPressure(Dof *dof) TimeStep * CBS :: giveSolutionStepWhenIcApply(bool force) { - if ( master && (!force)) { - return master->giveSolutionStepWhenIcApply(); - } else { - if ( !stepWhenIcApply ) { - stepWhenIcApply.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, - 0.0, deltaT, 0) ); - } + if ( master && (!force)) { + return master->giveSolutionStepWhenIcApply(); + } else { + if ( !stepWhenIcApply ) { + stepWhenIcApply = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 0, 0.0, deltaT, 0); + } - return stepWhenIcApply.get(); - } + return stepWhenIcApply.get(); + } } TimeStep * @@ -256,7 +240,7 @@ CBS :: giveNextStep() double dt = deltaT; if ( !currentStep ) { // first step -> generate initial step - currentStep.reset( new TimeStep( *giveSolutionStepWhenIcApply() ) ); + currentStep = std::make_unique( *giveSolutionStepWhenIcApply() ); } previousStep = std :: move(currentStep); @@ -271,7 +255,7 @@ CBS :: giveNextStep() dt = max(dt, minDeltaT); dt /= this->giveVariableScale(VST_Time); - currentStep.reset( new TimeStep(*previousStep, dt) ); + currentStep = std::make_unique(*previousStep, dt); OOFEM_LOG_INFO( "SolutionStep %d : t = %e, dt = %e\n", currentStep->giveNumber(), currentStep->giveTargetTime() * this->giveVariableScale(VST_Time), dt * this->giveVariableScale(VST_Time) ); @@ -287,8 +271,6 @@ CBS :: solveYourselfAt(TimeStep *tStep) int presneq_prescribed = this->giveNumberOfDomainEquations(1, pnumPrescribed); double deltaT = tStep->giveTimeIncrement(); - FloatArray rhs(momneq); - if ( initFlag ) { deltaAuxVelocity.resize(momneq); @@ -299,7 +281,7 @@ CBS :: solveYourselfAt(TimeStep *tStep) pnumPrescribed, this->giveDomain(1) ); - lhs.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + lhs = classFactory.createSparseMtrx(sparseMtrxType); if ( !lhs ) { OOFEM_ERROR("sparse matrix creation failed"); } @@ -311,7 +293,7 @@ CBS :: solveYourselfAt(TimeStep *tStep) lhs->times(deltaT * theta1 * theta2); if ( consistentMassFlag ) { - mss.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + mss = classFactory.createSparseMtrx(sparseMtrxType); if ( !mss ) { OOFEM_ERROR("sparse matrix creation failed"); } @@ -360,17 +342,23 @@ CBS :: solveYourselfAt(TimeStep *tStep) this->applyIC(stepWhenIcApply); } - VelocityField.advanceSolution(tStep); - PressureField.advanceSolution(tStep); - FloatArray *velocityVector = VelocityField.giveSolutionVector(tStep); - FloatArray *prevVelocityVector = VelocityField.giveSolutionVector( tStep->givePreviousStep() ); - FloatArray *pressureVector = PressureField.giveSolutionVector(tStep); - FloatArray *prevPressureVector = PressureField.giveSolutionVector( tStep->givePreviousStep() ); + velocityField.advanceSolution(tStep); + pressureField.advanceSolution(tStep); + //this->velocityField.applyBoundaryCondition(tStep); + //this->pressureField.applyBoundaryCondition(tStep); - velocityVector->resize(momneq); - pressureVector->resize(presneq); + FloatArray velocityVector; + FloatArray pressureVector; + FloatArray prevVelocityVector; + FloatArray prevPressureVector; + + this->velocityField.initialize(VM_Total, tStep->givePreviousStep(), prevVelocityVector, this->vnum ); + this->pressureField.initialize(VM_Total, tStep->givePreviousStep(), prevPressureVector, this->pnum ); + this->velocityField.update(VM_Total, tStep, prevVelocityVector, this->vnum ); + this->pressureField.update(VM_Total, tStep, prevPressureVector, this->pnum ); /* STEP 1 - calculates auxiliary velocities*/ + FloatArray rhs(momneq); rhs.zero(); // Depends on old v: this->assembleVectorFromElements( rhs, tStep, IntermediateConvectionDiffusionAssembler(), VM_Total, vnum, this->giveDomain(1) ); @@ -398,36 +386,38 @@ CBS :: solveYourselfAt(TimeStep *tStep) } // DensityRhsVelocityTerms needs this: Current velocity without correction; - * velocityVector = * prevVelocityVector; - velocityVector->add(this->theta1, deltaAuxVelocity); + velocityVector = prevVelocityVector; + velocityVector.add(this->theta1, deltaAuxVelocity); + this->velocityField.update(VM_Total, tStep, velocityVector, this->vnum ); // Depends on old V + deltaAuxV * theta1 and p: rhs.resize(presneq); rhs.zero(); - this->assembleVectorFromElements( rhs, tStep, DensityRhsAssembler(), VM_Total, - pnum, this->giveDomain(1) ); + this->assembleVectorFromElements( rhs, tStep, DensityRhsAssembler(), VM_Total, pnum, this->giveDomain(1) ); this->giveNumericalMethod( this->giveCurrentMetaStep() ); - nMethod->solve(*lhs, rhs, *pressureVector); - pressureVector->times(this->theta2); - pressureVector->add(* prevPressureVector); + nMethod->solve(*lhs, rhs, pressureVector); + pressureVector.times(this->theta2); + pressureVector.add(prevPressureVector); + this->pressureField.update(VM_Total, tStep, pressureVector, this->pnum ); /* STEP 3 - velocity correction step */ rhs.resize(momneq); rhs.zero(); // Depends on p: - this->assembleVectorFromElements( rhs, tStep, CorrectionRhsAssembler(), VM_Total, - vnum, this->giveDomain(1) ); + this->assembleVectorFromElements( rhs, tStep, CorrectionRhsAssembler(), VM_Total, vnum, this->giveDomain(1) ); if ( consistentMassFlag ) { rhs.times(deltaT); //this->assembleVectorFromElements(rhs, tStep, PrescribedRhsAssembler(), VM_Incremental, vnum, this->giveDomain(1)); - nMethod->solve(*mss, rhs, *velocityVector); - velocityVector->add(deltaAuxVelocity); - velocityVector->add(* prevVelocityVector); + nMethod->solve(*mss, rhs, velocityVector); + velocityVector.add(deltaAuxVelocity); + velocityVector.add(prevVelocityVector); } else { for ( int i = 1; i <= momneq; i++ ) { - velocityVector->at(i) = prevVelocityVector->at(i) + deltaAuxVelocity.at(i) + deltaT *rhs.at(i) / mm.at(i); + velocityVector.at(i) = prevVelocityVector.at(i) + deltaAuxVelocity.at(i) + deltaT *rhs.at(i) / mm.at(i); } } + this->velocityField.update(VM_Total, tStep, velocityVector, this->vnum ); + this->updateInternalState(tStep); // update solution state counter tStep->incrementStateCounter(); @@ -449,10 +439,16 @@ CBS :: solveYourselfAt(TimeStep *tStep) } +int +CBS :: giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) +{ + return tStep->giveNumber() % 2; +} + + void CBS :: updateYourself(TimeStep *tStep) { - this->updateInternalState(tStep); EngngModel :: updateYourself(tStep); // if ( materialInterface ) { @@ -468,12 +464,6 @@ void CBS :: updateInternalState(TimeStep *tStep) { for ( auto &domain: domainList ) { - if ( requiresUnknownsDictionaryUpdate() ) { - for ( auto &dman : domain->giveDofManagers() ) { - this->updateDofUnknownsDictionary(dman.get(), tStep); - } - } - for ( auto &elem : domain->giveElements() ) { elem->updateInternalState(tStep); } @@ -481,76 +471,27 @@ CBS :: updateInternalState(TimeStep *tStep) } -contextIOResultType +void CBS :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = EngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = PressureField.saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = VelocityField.saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + EngngModel :: saveContext(stream, mode); + contextIOResultType iores; if ( ( iores = prescribedTractionPressure.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -CBS :: restoreContext(DataStream *stream, ContextMode mode, void *obj) -// -// restore state variable - displacement vector -// +void +CBS :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - int closeFlag = 0; - int istep, iversion; - FILE *file = NULL; + EngngModel :: restoreContext(stream, mode); - this->resolveCorrespondingStepNumber(istep, iversion, obj); - - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - - if ( ( iores = EngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = PressureField.restoreContext(*stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = VelocityField.restoreContext(*stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = prescribedTractionPressure.restoreYourself(*stream) ) != CIO_OK ) { + contextIOResultType iores; + if ( ( iores = prescribedTractionPressure.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } // ensure consistent records - - return CIO_OK; } @@ -617,7 +558,7 @@ CBS :: printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep) double pscale = ( dscale * uscale * uscale ); DofIDItem type = iDof->giveDofID(); - if ( ( type == V_u ) || ( type == V_v ) || ( type == V_w ) ) { + if ( type == V_u || type == V_v || type == V_w ) { iDof->printSingleOutputAt(stream, tStep, 'd', VM_Total, uscale); } else if ( type == P_f ) { iDof->printSingleOutputAt(stream, tStep, 'd', VM_Total, pscale); @@ -630,47 +571,14 @@ CBS :: printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep) void CBS :: applyIC(TimeStep *stepWhenIcApply) { - Domain *domain = this->giveDomain(1); - int mbneq = this->giveNumberOfDomainEquations(1, vnum); - int pdneq = this->giveNumberOfDomainEquations(1, pnum); - FloatArray *velocityVector, *pressureVector; - #ifdef VERBOSE OOFEM_LOG_INFO("Applying initial conditions\n"); #endif - - VelocityField.advanceSolution(stepWhenIcApply); - velocityVector = VelocityField.giveSolutionVector(stepWhenIcApply); - velocityVector->resize(mbneq); - velocityVector->zero(); - - PressureField.advanceSolution(stepWhenIcApply); - pressureVector = PressureField.giveSolutionVector(stepWhenIcApply); - pressureVector->resize(pdneq); - pressureVector->zero(); - - for ( auto &node : domain->giveDofManagers() ) { - for ( Dof *iDof: *node ) { - // ask for initial values obtained from - // bc (boundary conditions) and ic (initial conditions) - if ( !iDof->isPrimaryDof() ) { - continue; - } - - int jj = iDof->__giveEquationNumber(); - if ( jj ) { - DofIDItem type = iDof->giveDofID(); - if ( ( type == V_u ) || ( type == V_v ) || ( type == V_w ) ) { - velocityVector->at(jj) = iDof->giveUnknown(VM_Total, stepWhenIcApply); - } else { - pressureVector->at(jj) = iDof->giveUnknown(VM_Total, stepWhenIcApply); - } - } - } - } + velocityField.applyDefaultInitialCondition(); + pressureField.applyDefaultInitialCondition(); // update element state according to given ic - for ( auto &elem : domain->giveElements() ) { + for ( auto &elem : this->giveDomain(1)->giveElements() ) { CBSElement *element = static_cast< CBSElement * >( elem.get() ); element->updateInternalState(stepWhenIcApply); element->updateYourself(stepWhenIcApply); @@ -681,7 +589,7 @@ CBS :: applyIC(TimeStep *stepWhenIcApply) int CBS :: giveNewEquationNumber(int domain, DofIDItem id) { - if ( ( id == V_u ) || ( id == V_v ) || ( id == V_w ) ) { + if ( id == V_u || id == V_v || id == V_w ) { return this->vnum.askNewEquationNumber(); } else if ( id == P_f ) { return this->pnum.askNewEquationNumber(); @@ -696,7 +604,7 @@ CBS :: giveNewEquationNumber(int domain, DofIDItem id) int CBS :: giveNewPrescribedEquationNumber(int domain, DofIDItem id) { - if ( ( id == V_u ) || ( id == V_v ) || ( id == V_w ) ) { + if ( id == V_u || id == V_v || id == V_w ) { return this->vnumPrescribed.askNewEquationNumber(); } else if ( id == P_f ) { return this->pnumPrescribed.askNewEquationNumber(); diff --git a/src/fm/cbs.h b/src/fm/cbs.h index 026b27f6a..0eaacc504 100644 --- a/src/fm/cbs.h +++ b/src/fm/cbs.h @@ -38,7 +38,7 @@ #include "fluidmodel.h" #include "sparselinsystemnm.h" #include "sparsemtrx.h" -#include "primaryfield.h" +#include "dofdistributedprimaryfield.h" // #include "materialinterface.h" // @@ -66,50 +66,50 @@ namespace oofem { class NumberOfNodalPrescribedTractionPressureAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; /// Implementation for assembling external forces vectors in standard monolithic FE-problems class IntermediateConvectionDiffusionAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; /// Implementation for assembling external forces vectors in standard monolithic FE-problems class PrescribedVelocityRhsAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; /// Implementation for assembling external forces vectors in standard monolithic FE-problems class DensityPrescribedTractionPressureAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; /// Implementation for assembling external forces vectors in standard monolithic FE-problems class DensityRhsAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; /// Implementation for assembling external forces vectors in standard monolithic FE-problems class CorrectionRhsAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; /// Callback class for assembling CBS pressure matrices class PressureLhsAssembler : public MatrixAssembler { public: - virtual void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const; - virtual void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const; + void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const override; + void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const override; }; @@ -125,8 +125,8 @@ class VelocityEquationNumbering : public UnknownNumberingScheme public: VelocityEquationNumbering(bool prescribed) : UnknownNumberingScheme(), prescribed(prescribed), numEqs(0) { } - virtual bool isDefault() const { return !prescribed; } - virtual int giveDofEquationNumber(Dof *dof) const { + bool isDefault() const override { return !prescribed; } + int giveDofEquationNumber(Dof *dof) const override { DofIDItem id = dof->giveDofID(); if ( id == V_u || id == V_v || id == V_w ) { return prescribed ? dof->__givePrescribedEquationNumber() : dof->__giveEquationNumber(); @@ -134,7 +134,7 @@ class VelocityEquationNumbering : public UnknownNumberingScheme return 0; } - virtual int giveRequiredNumberOfDomainEquation() const { return numEqs; } + int giveRequiredNumberOfDomainEquation() const override { return numEqs; } int askNewEquationNumber() { return ++numEqs; } }; @@ -151,8 +151,8 @@ class PressureEquationNumbering : public UnknownNumberingScheme public: PressureEquationNumbering(bool prescribed) : UnknownNumberingScheme(), prescribed(prescribed), numEqs(0) { } - virtual bool isDefault() const { return !prescribed; } - virtual int giveDofEquationNumber(Dof *dof) const { + bool isDefault() const override { return !prescribed; } + int giveDofEquationNumber(Dof *dof) const override { DofIDItem id = dof->giveDofID(); if ( id == P_f ) { return prescribed ? dof->__givePrescribedEquationNumber() : dof->__giveEquationNumber(); @@ -160,7 +160,7 @@ class PressureEquationNumbering : public UnknownNumberingScheme return 0; } - virtual int giveRequiredNumberOfDomainEquation() const { return numEqs; } + int giveRequiredNumberOfDomainEquation() const override { return numEqs; } int askNewEquationNumber() { return ++numEqs; } }; @@ -179,9 +179,9 @@ class CBS : public FluidModel std :: unique_ptr< SparseMtrx > lhs; /// Pressure field. - PrimaryField PressureField; + DofDistributedPrimaryField pressureField; /// Velocity field. - PrimaryField VelocityField; + DofDistributedPrimaryField velocityField; FloatArray deltaAuxVelocity; FloatArray prescribedTractionPressure; FloatArray nodalPrescribedTractionPressureConnectivity; @@ -223,49 +223,48 @@ class CBS : public FluidModel CBS(int i, EngngModel * _master = NULL); virtual ~CBS(); - virtual void solveYourselfAt(TimeStep *tStep); + void solveYourselfAt(TimeStep *tStep) override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof); - virtual double giveReynoldsNumber(); + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override; + double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof) override; + bool newDofHandling() override { return true; } + double giveReynoldsNumber() override; double giveTheta1(); double giveTheta2(); double giveTractionPressure(Dof *dof); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void updateDomainLinks(); + void updateDomainLinks() override; - virtual TimeStep *giveNextStep(); - virtual TimeStep *giveSolutionStepWhenIcApply(bool force = false); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + TimeStep *giveNextStep() override; + TimeStep *giveSolutionStepWhenIcApply(bool force = false) override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual int checkConsistency(); + int checkConsistency() override; // identification - virtual const char *giveClassName() const { return "CBS"; } - virtual const char *giveInputRecordName() const { return _IFT_CBS_Name; } - virtual fMode giveFormulation() { return TL; } + const char *giveClassName() const override { return "CBS"; } + const char *giveInputRecordName() const { return _IFT_CBS_Name; } + fMode giveFormulation() override { return TL; } - virtual void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep); + void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep) override; - virtual int giveNumberOfDomainEquations(int, const UnknownNumberingScheme &num); + int giveNumberOfDomainEquations(int, const UnknownNumberingScheme &num) override; - virtual int giveNewEquationNumber(int domain, DofIDItem); - virtual int giveNewPrescribedEquationNumber(int domain, DofIDItem); + int giveNewEquationNumber(int domain, DofIDItem) override; + int giveNewPrescribedEquationNumber(int domain, DofIDItem) override; - virtual bool giveEquationScalingFlag() { return equationScalingFlag; } - virtual double giveVariableScale(VarScaleType varId); + bool giveEquationScalingFlag() override { return equationScalingFlag; } + double giveVariableScale(VarScaleType varId) override; protected: /** - * Updates nodal values - * (calls also this->updateDofUnknownsDictionary for updating dofs unknowns dictionaries - * if model supports changes of static system). The element internal state update is also forced using - * updateInternalState service. + * Updates the IP values for the new solution velocities */ void updateInternalState(TimeStep *tStep); void applyIC(TimeStep *tStep); diff --git a/src/fm/cbselement.C b/src/fm/cbselement.C index 0c6b76950..3c66cb1ea 100644 --- a/src/fm/cbselement.C +++ b/src/fm/cbselement.C @@ -51,20 +51,14 @@ CBSElement :: CBSElement(int n, Domain *aDomain) : { } -CBSElement :: ~CBSElement() -{ } - -IRResultType -CBSElement :: initializeFrom(InputRecord *ir) +void +CBSElement :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - + FMElement :: initializeFrom(ir); IR_GIVE_OPTIONAL_FIELD(ir, boundarySides, _IFT_CBSElement_bsides); if ( !boundarySides.isEmpty() ) { IR_GIVE_FIELD(ir, boundaryCodes, _IFT_CBSElement_bcodes); } - - return FMElement :: initializeFrom(ir); } @@ -156,7 +150,7 @@ CBSElement :: updateInternalState(TimeStep *tStep) // force updating strains & stresses for ( auto &iRule: integrationRulesArray ) { - for ( GaussPoint *gp: *iRule ) { + for ( auto &gp: *iRule ) { computeDeviatoricStress(stress, gp, tStep); } } diff --git a/src/fm/cbselement.h b/src/fm/cbselement.h index 9d3a02d47..674f0c24f 100644 --- a/src/fm/cbselement.h +++ b/src/fm/cbselement.h @@ -63,13 +63,12 @@ class CBSElement : public FMElement public: CBSElement(int n, Domain * aDomain); - virtual ~CBSElement(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep); - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep); + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) override; + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override; /** Calculates consistent mass matrix. */ virtual void computeConsistentMassMtrx(FloatMatrix &answer, TimeStep *tStep) = 0; @@ -99,12 +98,12 @@ class CBSElement : public FMElement virtual double computeCriticalTimeStep(TimeStep *tStep) = 0; // time step termination - virtual void updateInternalState(TimeStep *tStep); - virtual int checkConsistency(); + void updateInternalState(TimeStep *tStep) override; + int checkConsistency() override; #ifdef __OOFEG int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *tStep); + int node, TimeStep *tStep) override; #endif protected: diff --git a/src/fm/fastmarchingmethod.C b/src/fm/fastmarchingmethod.C index 0ba0ce8fa..13360bb09 100644 --- a/src/fm/fastmarchingmethod.C +++ b/src/fm/fastmarchingmethod.C @@ -135,7 +135,7 @@ FastMarchingMethod :: updateTrialValue(FloatArray &dmanValues, int id, double F) int ai, bi, ci, h, nroot, _ind = 0; double at, bt, ht, a, b, u, cos_fi, sin_fi, _a, _b, _c, r1, r2, r3, t = 0.0, _h; bool reg_upd_flag; - FloatArray *ac, *bc, *cc, cb, ca; + FloatArray cb, ca; ConnectivityTable *ct = domain->giveConnectivityTable(); @@ -169,18 +169,18 @@ FastMarchingMethod :: updateTrialValue(FloatArray &dmanValues, int id, double F) } // get nodal coordinates - ac = domain->giveNode(ai)->giveCoordinates(); - bc = domain->giveNode(bi)->giveCoordinates(); - cc = domain->giveNode(ci)->giveCoordinates(); + const auto &ac = domain->giveNode(ai)->giveCoordinates(); + const auto &bc = domain->giveNode(bi)->giveCoordinates(); + const auto &cc = domain->giveNode(ci)->giveCoordinates(); // a = distance of BC - a = cc->distance(bc); + a = distance(cc, bc); // b = distance of AC - b = cc->distance(ac); + b = distance(cc, ac); // compute fi angle - cb.beDifferenceOf(* bc, * cc); + cb.beDifferenceOf(bc, cc); cb.normalize(); - ca.beDifferenceOf(* ac, * cc); + ca.beDifferenceOf(ac, cc); ca.normalize(); cos_fi = cb.dotProduct(ca); sin_fi = sqrt(1.0 - cos_fi * cos_fi); diff --git a/src/fm/fastmarchingmethod.h b/src/fm/fastmarchingmethod.h index bf19cb32b..a95ad2040 100644 --- a/src/fm/fastmarchingmethod.h +++ b/src/fm/fastmarchingmethod.h @@ -101,7 +101,6 @@ class FastMarchingMethod FastMarchingMethod(Domain * d) : dmanTrialQueue( FMM_DofmanRecordDelegate_greater(& this->dmanValuesPtr) ) { domain = d; } - ~FastMarchingMethod() { } /** * Solution of problem. diff --git a/src/fm/fluidcrosssection.C b/src/fm/fluidcrosssection.C index 75298d433..13b098489 100644 --- a/src/fm/fluidcrosssection.C +++ b/src/fm/fluidcrosssection.C @@ -33,7 +33,7 @@ */ #include "fluidcrosssection.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "dynamicinputrecord.h" #include "domain.h" #include "classfactory.h" @@ -43,17 +43,12 @@ REGISTER_CrossSection(FluidCrossSection); FluidCrossSection :: FluidCrossSection(int n, Domain *d) : CrossSection(n, d), matNumber(0) { } -FluidCrossSection :: ~FluidCrossSection() { } - -IRResultType -FluidCrossSection :: initializeFrom(InputRecord *ir) +void +FluidCrossSection :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - + CrossSection :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->matNumber, _IFT_FluidCrossSection_material); - - return CrossSection :: initializeFrom(ir); } @@ -89,7 +84,7 @@ FluidCrossSection :: giveIPValue(FloatArray &answer, GaussPoint *ip, InternalSta bool -FluidCrossSection :: isCharacteristicMtrxSymmetric(MatResponseMode rMode) +FluidCrossSection :: isCharacteristicMtrxSymmetric(MatResponseMode rMode) const { return this->domain->giveMaterial(this->matNumber)->isCharacteristicMtrxSymmetric(rMode); } @@ -102,7 +97,7 @@ FluidCrossSection :: giveFluidMaterial() } Material* -FluidCrossSection :: giveMaterial(IntegrationPoint *ip) +FluidCrossSection :: giveMaterial(IntegrationPoint *ip) const { if ( this->matNumber ) { return this->giveDomain()->giveMaterial( this->matNumber ); diff --git a/src/fm/fluidcrosssection.h b/src/fm/fluidcrosssection.h index af3694f09..e9083e8b3 100644 --- a/src/fm/fluidcrosssection.h +++ b/src/fm/fluidcrosssection.h @@ -60,27 +60,25 @@ class OOFEM_EXPORT FluidCrossSection : public CrossSection * @param d Domain for cross section. */ FluidCrossSection(int n, Domain * d); - /// Destructor. - virtual ~FluidCrossSection(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual int checkConsistency(); + int checkConsistency() override; - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode); - virtual int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep); + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override; + int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep) override; virtual double giveDensity(GaussPoint *gp); FluidDynamicMaterial *giveFluidMaterial(); - Material *giveMaterial(IntegrationPoint *ip); + Material *giveMaterial(IntegrationPoint *ip) const override; - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp); - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp); - virtual int estimatePackSize(DataStream &buff, GaussPoint *gp); + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) override; + int estimatePackSize(DataStream &buff, GaussPoint *gp) override; - virtual const char *giveClassName() const { return "FluidCrossSection"; } - virtual const char *giveInputRecordName() const { return _IFT_FluidCrossSection_Name; } + const char *giveClassName() const override { return "FluidCrossSection"; } + const char *giveInputRecordName() const override { return _IFT_FluidCrossSection_Name; } }; } // end namespace oofem #endif // fluidcrosssection_h diff --git a/src/fm/fluiddynamicmaterial.C b/src/fm/fluiddynamicmaterial.C deleted file mode 100644 index 0164d1a2a..000000000 --- a/src/fm/fluiddynamicmaterial.C +++ /dev/null @@ -1,210 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "fluiddynamicmaterial.h" -#include "gausspoint.h" -#include "floatarray.h" -#include "contextioerr.h" - -namespace oofem { -void -FluidDynamicMaterial :: updateInternalState(const FloatArray &vec, GaussPoint *gp, TimeStep *tStep) -{ } - - -void -FluidDynamicMaterial :: computeDeviatoricStressVector(FloatArray &stress_dev, double &epsp_vol, GaussPoint *gp, const FloatArray &eps, double pressure, TimeStep *tStep) -{ - if ( gp->giveMaterialMode() == _2dFlow ) { - epsp_vol = -( eps.at(1) + eps.at(2) ); - } else { - epsp_vol = -( eps.at(1) + eps.at(2) + eps.at(3) ); - } - - this->computeDeviatoricStressVector(stress_dev, gp, eps, tStep); -} - -void -FluidDynamicMaterial :: giveStiffnessMatrices(FloatMatrix &dsdd, FloatArray &dsdp, FloatArray &dedd, double &dedp, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - this->giveDeviatoricStiffnessMatrix(dsdd, mode, gp, tStep); - int size = dsdd.giveNumberOfRows(); - dsdp.resize(size); - dsdp.zero(); - dedd.resize(size); - dedd.zero(); - dedp = 0; -} - - -FluidDynamicMaterialStatus :: FluidDynamicMaterialStatus(int n, Domain *d, GaussPoint *g) : - MaterialStatus(n, d, g), deviatoricStressVector(), deviatoricStrainRateVector() -{ } - -void -FluidDynamicMaterialStatus :: printOutputAt(FILE *File, TimeStep *tStep) -// Prints the strains and stresses on the data file. -{ - fprintf(File, "\n deviatoric stresses"); - for ( double e: deviatoricStressVector ) { - fprintf( File, " %.4e", e ); - } - - fprintf(File, "\n"); -} - -void -FluidDynamicMaterialStatus :: initTempStatus() -{ - MaterialStatus :: initTempStatus(); -} - - -int -FluidDynamicMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) -{ - FluidDynamicMaterialStatus *status = static_cast< FluidDynamicMaterialStatus * >( this->giveStatus(gp) ); - if ( type == IST_DeviatoricStress ) { - MaterialMode mmode = gp->giveMaterialMode(); - const FloatArray &vec = status->giveDeviatoricStressVector(); - if ( mmode == _2dFlow ) { - answer.resize(6); - answer.at(1) = vec.at(1); - answer.at(2) = vec.at(2); - answer.at(3) = -( vec.at(1) + vec.at(2) ); ///@todo Verify that this is correct for for all models. - answer.at(4) = 0.; - answer.at(5) = 0.; - answer.at(6) = vec.at(3); - return 1; - } else if ( mmode == _2dAxiFlow ) { - answer.resize(6); - answer.at(1) = vec.at(1); - answer.at(2) = vec.at(2); - answer.at(3) = vec.at(3); - answer.at(4) = 0; - answer.at(5) = 0; - answer.at(6) = vec.at(6); - return 1; - } else if ( mmode == _3dFlow ) { - answer = vec; - return 1; - } else { - OOFEM_ERROR("material mode not supported"); - return 0; - } - - } else if ( type == IST_DeviatoricStrain ) { - MaterialMode mmode = gp->giveMaterialMode(); - const FloatArray &vec = status->giveDeviatoricStrainRateVector(); - if ( mmode == _2dFlow ) { - answer.resize(6); - answer.at(1) = vec.at(1); - answer.at(2) = vec.at(2); - answer.at(3) = 0.; - answer.at(4) = vec.at(3); - answer.at(5) = 0.; - answer.at(6) = 0.; - answer.copySubVector(vec, 1); - return 1; - } else if ( mmode == _2dAxiFlow ) { - answer.resize(6); - answer.at(1) = vec.at(1); - answer.at(2) = vec.at(2); - answer.at(3) = vec.at(3); - answer.at(4) = 0; - answer.at(5) = 0; - answer.at(6) = vec.at(6); - return 1; - } else if ( mmode == _3dFlow ) { - answer = vec; - return 1; - } else { - OOFEM_ERROR("material mode not supported"); - return 0; - } - - } else if ( type == IST_Viscosity ) { - answer.resize(1); - answer.at(1) = this->giveEffectiveViscosity(gp, tStep); - return 1; - } else if ( type == IST_Density ) { - answer.resize(1); - answer.at(1) = this->give('d', gp); - return 1; - } else { - return Material :: giveIPValue(answer, gp, type, tStep); - } -} - - -contextIOResultType -FluidDynamicMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -{ - contextIOResultType iores; - if ( ( iores = MaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = deviatoricStressVector.storeYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = deviatoricStrainRateVector.storeYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; -} - - -contextIOResultType -FluidDynamicMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -{ - contextIOResultType iores; - if ( ( iores = MaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = deviatoricStressVector.restoreYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = deviatoricStrainRateVector.restoreYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; -} -} // end namespace oofem diff --git a/src/fm/fluidmaterialevaluator.C b/src/fm/fluidmaterialevaluator.C index c07117cf2..70dc61ad2 100644 --- a/src/fm/fluidmaterialevaluator.C +++ b/src/fm/fluidmaterialevaluator.C @@ -37,7 +37,7 @@ #include "timestep.h" #include "domain.h" #include "gausspoint.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "function.h" #include "classfactory.h" @@ -51,13 +51,9 @@ FluidMaterialEvaluator :: FluidMaterialEvaluator(int i, EngngModel *_master) : E this->ndomains = 1; } -FluidMaterialEvaluator :: ~FluidMaterialEvaluator() -{ } -IRResultType FluidMaterialEvaluator :: initializeFrom(InputRecord *ir) +void FluidMaterialEvaluator :: initializeFrom(InputRecord &ir) { - IRResultType result; - this->deltaT = 1.0; IR_GIVE_OPTIONAL_FIELD(ir, this->deltaT, _IFT_FluidMaterialEvaluator_deltat); IR_GIVE_FIELD(ir, this->numberOfSteps, _IFT_FluidMaterialEvaluator_numberOfTimeSteps); @@ -78,8 +74,6 @@ IRResultType FluidMaterialEvaluator :: initializeFrom(InputRecord *ir) eControl.followedBy(i); } } - - return IRRT_OK; } @@ -105,8 +99,7 @@ void FluidMaterialEvaluator :: solveYourself() gps.clear(); gps.reserve(d->giveNumberOfMaterialModels()); for ( int i = 1; i <= d->giveNumberOfMaterialModels(); i++ ) { - std :: unique_ptr< GaussPoint > gp(new GaussPoint(nullptr, i, FloatArray(), 1, mode)); - gps.emplace_back( std :: move(gp)); + gps.emplace_back( std::make_unique(nullptr, i, FloatArray(), 1, mode) ); // Initialize the strain vector; FluidDynamicMaterial *mat = static_cast< FluidDynamicMaterial * >( d->giveMaterial(i) ); FluidDynamicMaterialStatus *status = static_cast< FluidDynamicMaterialStatus * >( mat->giveStatus( &*gps[i-1] ) ); @@ -123,14 +116,9 @@ void FluidMaterialEvaluator :: solveYourself() // Note, strain == strain-rate (kept as strain for brevity) int maxiter = 100; // User input? double tolerance = 1.e-6; // Needs to be normalized somehow, or user input - double strainVol, pressure, strainVolC = 0.; - FloatArray stressDevC, deltaStrain, strainDev, stressDev, res; - stressDevC.resize( sControl.giveSize() ); - res.resize( sControl.giveSize() ); - - FloatMatrix tangent, reducedTangent; - FloatArray dsdp, dedd; - double dedp; + double strainVolC = 0.; + FloatArray stressDevC( sControl.giveSize() ), res( sControl.giveSize() ); + for ( int istep = 1; istep <= this->numberOfSteps; ++istep ) { this->timer.startTimer(EngngModelTimer :: EMTT_SolutionStepTimer); for ( int imat = 1; imat <= d->giveNumberOfMaterialModels(); ++imat ) { @@ -138,8 +126,8 @@ void FluidMaterialEvaluator :: solveYourself() FluidDynamicMaterial *mat = static_cast< FluidDynamicMaterial * >( d->giveMaterial(imat) ); FluidDynamicMaterialStatus *status = static_cast< FluidDynamicMaterialStatus * >( mat->giveStatus(gp) ); - strainDev = status->giveDeviatoricStrainRateVector(); - pressure = 0.; ///@todo We should ask the material model for this initial guess. + auto strainDev = status->giveDeviatoricStrainRateVector(); + double pressure = 0.; ///@todo We should ask the material model for this initial guess. // Update the controlled parts for ( int j = 1; j <= eControl.giveSize(); ++j ) { int p = eControl.at(j); @@ -158,7 +146,21 @@ void FluidMaterialEvaluator :: solveYourself() } for ( int iter = 1; iter < maxiter; iter++ ) { - mat->computeDeviatoricStressVector(stressDev, strainVol, gp, strainDev, pressure, tStep); + FloatMatrix tangent, reducedTangent; + FloatArray dsdp, dedd; + double dedp; + double strainVol; + FloatArray stressDev; + if ( ndim == 3 ) { + auto val = mat->computeDeviatoricStress3D(strainDev, pressure, gp, tStep); + stressDev = val.first; + strainVol = val.second; + } else { + auto val = mat->computeDeviatoricStress2D({strainDev[0], strainDev[1], strainDev[5]}, pressure, gp, tStep); + stressDev = val.first; + strainVol = val.second; + } + for ( int j = 1; j <= sControl.giveSize(); ++j ) { res.at(j) = stressDevC.at(j) - stressDev.at( sControl.at(j) ); } @@ -167,12 +169,23 @@ void FluidMaterialEvaluator :: solveYourself() resVol = strainVolC - strainVol; } - OOFEM_LOG_RELEVANT( "Time step: %d, Material %d, Iteration: %d, Residual = %e, Resvol = %e\n", istep, imat, iter, res.computeNorm(), resVol ); - if ( res.computeNorm() <= tolerance && resVol <= tolerance ) { ///@todo More flexible control of convergence needed. Something relative? + OOFEM_LOG_RELEVANT( "Time step: %d, Material %d, Iteration: %d, Residual = %e, Resvol = %e\n", istep, imat, iter, norm(res), resVol ); + if ( norm(res) <= tolerance && resVol <= tolerance ) { ///@todo More flexible control of convergence needed. Something relative? break; } - - mat->giveStiffnessMatrices(tangent, dsdp, dedd, dedp, TangentStiffness, gp, tStep); + if ( ndim == 3 ) { + auto t = mat->computeTangents3D(TangentStiffness, gp, tStep); + tangent = t.dsdd; + dsdp = t.dsdp; + dedd = t.dedd; + dedp = t.dedp; + } else { + auto t = mat->computeTangents2D(TangentStiffness, gp, tStep); + tangent = t.dsdd; + dsdp = t.dsdp; + dedd = t.dedd; + dedp = t.dedp; + } if ( res.giveSize() > 0 ) { // Add mean part to make it invertible double norm = tangent.computeFrobeniusNorm(); @@ -186,6 +199,7 @@ void FluidMaterialEvaluator :: solveYourself() reducedTangent.beSubMatrixOf(tangent, sControl, sControl); // Update stress-controlled part of the strain + FloatArray deltaStrain; reducedTangent.solveForRhs(res, deltaStrain); for ( int j = 1; j <= sControl.giveSize(); ++j ) { strainDev.at( sControl.at(j) ) += deltaStrain.at(j); @@ -255,11 +269,11 @@ TimeStep *FluidMaterialEvaluator :: giveNextStep() { if ( !currentStep ) { // first step -> generate initial step - //currentStep.reset( new TimeStep(*giveSolutionStepWhenIcApply()) ); - currentStep.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., this->deltaT, 0) ); + //currentStep = std::make_unique(*giveSolutionStepWhenIcApply()); + currentStep = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., this->deltaT, 0); } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(*previousStep, this->deltaT) ); + currentStep = std::make_unique(*previousStep, this->deltaT); return currentStep.get(); diff --git a/src/fm/fluidmaterialevaluator.h b/src/fm/fluidmaterialevaluator.h index 978ec38b1..b2fce24f0 100644 --- a/src/fm/fluidmaterialevaluator.h +++ b/src/fm/fluidmaterialevaluator.h @@ -69,13 +69,13 @@ class GaussPoint; class FluidMaterialEvaluator : public EngngModel { protected: - double deltaT; ///< Time increment. + double deltaT = 1.; ///< Time increment. - int ndim; /// Number of spatial dimensions. + int ndim = 3; /// Number of spatial dimensions. IntArray cmpntFunctions; /// Time functions controlling each component of the deviatoric part of the stress. - int volFunction; /// Time function controlling the volumetric/pressure part + int volFunction = 0; /// Time function controlling the volumetric/pressure part IntArray sControl, eControl; - bool pressureControl; + bool pressureControl = false; IntArray vars; @@ -84,19 +84,18 @@ class FluidMaterialEvaluator : public EngngModel std :: ofstream outfile; public: - FluidMaterialEvaluator(int i, EngngModel * _master = NULL); - virtual ~FluidMaterialEvaluator(); + FluidMaterialEvaluator(int i, EngngModel * _master = nullptr); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void solveYourself(); + void solveYourself() override; - virtual int checkConsistency(); - virtual void doStepOutput(TimeStep *tStep); - virtual TimeStep *giveNextStep(); + int checkConsistency() override; + void doStepOutput(TimeStep *tStep) override; + TimeStep *giveNextStep() override; - virtual const char *giveClassName() const { return "FluidMaterialEvaluator"; } - virtual const char *giveInputRecordName() const { return _IFT_FluidMaterialEvaluator_Name; } + const char *giveClassName() const override { return "FluidMaterialEvaluator"; } + const char *giveInputRecordName() const { return _IFT_FluidMaterialEvaluator_Name; } }; } // end namespace oofem diff --git a/src/fm/fluidmodel.h b/src/fm/fluidmodel.h index 89a699663..20f38ac37 100644 --- a/src/fm/fluidmodel.h +++ b/src/fm/fluidmodel.h @@ -48,8 +48,8 @@ class FluidModel : public EngngModel public: FluidModel(int i, EngngModel * master) : EngngModel(i, master) { } - virtual int forceEquationNumbering(int id); - virtual int forceEquationNumbering() { return EngngModel :: forceEquationNumbering(); } + int forceEquationNumbering(int id) override; + int forceEquationNumbering() override { return EngngModel :: forceEquationNumbering(); } virtual double giveReynoldsNumber() = 0; }; diff --git a/src/fm/fmelement.C b/src/fm/fmelement.C index ef24d1aad..c634e7b56 100644 --- a/src/fm/fmelement.C +++ b/src/fm/fmelement.C @@ -40,10 +40,6 @@ FMElement :: FMElement(int n, Domain *aDomain) : { } -FMElement :: ~FMElement() -{ } - - void FMElement :: computeVectorOfVelocities(ValueModeType mode, TimeStep *tStep, FloatArray &velocities) { @@ -57,4 +53,23 @@ FMElement :: computeVectorOfPressures(ValueModeType mode, TimeStep *tStep, Float this->computeVectorOf({P_f}, mode, tStep, pressures); } + +FloatArray +FMElement :: computeVectorOfVelocities(ValueModeType mode, TimeStep *tStep) +{ + FloatArray ans; + this->computeVectorOf({V_u, V_v, V_w}, mode, tStep, ans); + return ans; +} + + +FloatArray +FMElement :: computeVectorOfPressures(ValueModeType mode, TimeStep *tStep) +{ + FloatArray ans; + this->computeVectorOf({P_f}, mode, tStep, ans); + return ans; +} + + } // end namespace oofem diff --git a/src/fm/fmelement.h b/src/fm/fmelement.h index 55a47bc1c..6c36e9fc8 100644 --- a/src/fm/fmelement.h +++ b/src/fm/fmelement.h @@ -55,7 +55,6 @@ class FMElement : public Element { public: FMElement(int n, Domain * aDomain); - virtual ~FMElement(); /** * Updates the stabilization coefficients used for CBS and SUPG algorithms. @@ -63,8 +62,11 @@ class FMElement : public Element */ virtual void updateStabilizationCoeffs(TimeStep *tStep) { } - virtual void computeVectorOfVelocities(ValueModeType mode, TimeStep *tStep, FloatArray &velocities); - virtual void computeVectorOfPressures(ValueModeType mode, TimeStep *tStep, FloatArray &pressures); + void computeVectorOfVelocities(ValueModeType mode, TimeStep *tStep, FloatArray &velocities); + void computeVectorOfPressures(ValueModeType mode, TimeStep *tStep, FloatArray &pressures); + + FloatArray computeVectorOfVelocities(ValueModeType mode, TimeStep *tStep); + FloatArray computeVectorOfPressures(ValueModeType mode, TimeStep *tStep); }; } // end namespace oofem #endif // fmelement_h diff --git a/src/fm/hexa21stokes.C b/src/fm/hexa21stokes.C index a375754dc..031ff6345 100644 --- a/src/fm/hexa21stokes.C +++ b/src/fm/hexa21stokes.C @@ -44,7 +44,7 @@ #include "bodyload.h" #include "boundaryload.h" #include "mathfem.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fei3dhexalin.h" #include "fei3dhexatriquad.h" #include "fluidcrosssection.h" @@ -78,14 +78,11 @@ Hexa21Stokes :: Hexa21Stokes(int n, Domain *aDomain) : FMElement(n, aDomain), Sp this->numberOfGaussPoints = 27; } -Hexa21Stokes :: ~Hexa21Stokes() -{ } - void Hexa21Stokes :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } @@ -139,7 +136,7 @@ void Hexa21Stokes :: computeInternalForcesVector(FloatArray &answer, TimeStep *t FloatArray momentum, conservation; B.zero(); - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); double detJ = fabs( this->interpolation_quad.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) ); @@ -154,7 +151,9 @@ void Hexa21Stokes :: computeInternalForcesVector(FloatArray &answer, TimeStep *t epsp.beProductOf(B, a_velocity); pressure = Nh.dotProduct(a_pressure); - mat->computeDeviatoricStressVector(devStress, r_vol, gp, epsp, pressure, tStep); + auto val = mat->computeDeviatoricStress3D(epsp, pressure, gp, tStep); + devStress = val.first; + r_vol = val.second; momentum.plusProduct(B, devStress, dV); momentum.add(-pressure * dV, dN_V); @@ -209,7 +208,7 @@ void Hexa21Stokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharT load->computeComponentArrayAt(gVector, tStep, VM_Total); temparray.zero(); if ( gVector.giveSize() ) { - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp); @@ -247,7 +246,7 @@ void Hexa21Stokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharT f.zero(); iRule.SetUpPointsOnTriangle(numberOfSurfaceIPs, _Unknown); - for ( GaussPoint *gp: iRule ) { + for ( auto &gp: iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->interpolation_quad.surfaceEvalN( N, iSurf, lcoords, FEIElementGeometryWrapper(this) ); @@ -280,49 +279,39 @@ void Hexa21Stokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharT void Hexa21Stokes :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) { FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); - FloatMatrix B(6, 81), EdB, K, G, Dp, DvT, C, Ed, dN; - FloatArray dN_V(81), Nlin, Ep, Cd, tmpA, tmpB; - double Cp; + FloatMatrixF<81,81> K; + FloatMatrixF<81,8> G, Dp; + FloatMatrixF<8,81> DvT; + FloatMatrixF<8,8> C; - B.zero(); + for ( auto &gp: *integrationRulesArray [ 0 ] ) { + const auto &lcoords = gp->giveNaturalCoordinates(); - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { - // Compute Gauss point and determinant at current element - const FloatArray &lcoords = gp->giveNaturalCoordinates(); + auto Nlin = this->interpolation_lin.evalN( lcoords ); + auto detj_dn = this->interpolation_quad.evaldNdx( lcoords, FEIElementGeometryWrapper(this) ); + auto dN = detj_dn.second; + auto detJ = detj_dn.first; + auto dA = std::abs(detJ) * gp->giveWeight(); - double detJ = fabs( this->interpolation_quad.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) ); - double dV = detJ * gp->giveWeight(); - this->interpolation_lin.evalN( Nlin, lcoords, FEIElementGeometryWrapper(this) ); - - for ( int j = 0, k = 0; j < dN.giveNumberOfRows(); j++, k += 3 ) { - dN_V(k + 0) = B(0, k + 0) = B(5, k + 1) = B(4, k + 2) = dN(j, 0); - dN_V(k + 1) = B(1, k + 1) = B(5, k + 0) = B(3, k + 2) = dN(j, 1); - dN_V(k + 2) = B(2, k + 2) = B(4, k + 0) = B(3, k + 1) = dN(j, 2); - } + auto dN_V = flatten(dN); + auto B = Bmatrix_3d(dN); // Computing the internal forces should have been done first. // dsigma_dev/deps_dev dsigma_dev/dp deps_vol/deps_dev deps_vol/dp - mat->giveStiffnessMatrices(Ed, Ep, Cd, Cp, mode, gp, tStep); - - EdB.beProductOf(Ed, B); - K.plusProductSymmUpper(B, EdB, dV); - G.plusDyadUnsym(dN_V, Nlin, -dV); - C.plusDyadSymmUpper(Nlin, Cp * dV); - - tmpA.beTProductOf(B, Ep); - Dp.plusDyadUnsym(tmpA, Nlin, dV); - - tmpB.beTProductOf(B, Cd); - DvT.plusDyadUnsym(Nlin, tmpB, dV); + //auto [Ed, Ep, Cd, Cp] = mat->computeTangents2D(mode, gp, tStep); + auto tangents = mat->computeTangents3D(mode, gp, tStep); + + K.plusProductSymmUpper(B, dot(tangents.dsdd, B), dA); + G.plusDyadUnsym(dN_V, Nlin, -dA); + Dp.plusDyadUnsym(Tdot(B, tangents.dsdp), Nlin, dA); + DvT.plusDyadUnsym(Nlin, Tdot(B, tangents.dedd), dA); + C.plusDyadSymmUpper(Nlin, tangents.dedp * dA); } K.symmetrized(); C.symmetrized(); - FloatMatrix GTDvT, GDp; - GTDvT.beTranspositionOf(G); - GTDvT.add(DvT); - GDp = G; - GDp.add(Dp); + auto GTDvT = transpose(G) + DvT; + auto GDp = G + Dp; answer.resize(89, 89); answer.zero(); @@ -399,15 +388,13 @@ void Hexa21Stokes :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answ answer.at(1) = this->giveNode(node)->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep); } else if ( node <= 20 ) { // Edge nodes // Edges are numbered consistently with edge nodes, so node number - 8 = edge number - IntArray eNodes; - this->interpolation_quad.computeLocalEdgeMapping(eNodes, node - 8); + const auto &eNodes = this->interpolation_quad.computeLocalEdgeMapping(node - 8); answer.at(1) = 0.5 * ( this->giveNode( eNodes.at(1) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) + this->giveNode( eNodes.at(2) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) ); } else if ( node <= 26 ) { // Face nodes // Faces are numbered consistently with edge nodes, so node number - 12 = face number - IntArray fNodes; - this->interpolation_quad.computeLocalSurfaceMapping(fNodes, node - 20); + const auto &fNodes = this->interpolation_quad.computeLocalSurfaceMapping(node - 20); answer.at(1) = 0.25 * ( this->giveNode( fNodes.at(1) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) + this->giveNode( fNodes.at(2) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) + diff --git a/src/fm/hexa21stokes.h b/src/fm/hexa21stokes.h index 8642ef7db..2790097db 100644 --- a/src/fm/hexa21stokes.h +++ b/src/fm/hexa21stokes.h @@ -69,37 +69,36 @@ public SpatialLocalizerInterface public: Hexa21Stokes(int n, Domain * d); - virtual ~Hexa21Stokes(); - virtual void computeGaussPoints(); - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep); + void computeGaussPoints() override; + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override; + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) override; void computeInternalForcesVector(FloatArray &answer, TimeStep *tStep); void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); void computeExternalForcesVector(FloatArray &answer, TimeStep *tStep); - virtual void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true); + void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; + void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true) override; - virtual const char *giveClassName() const { return "Hexa21Stokes"; } - virtual const char *giveInputRecordName() const { return _IFT_Hexa21Stokes_Name; } - virtual MaterialMode giveMaterialMode() { return _3dFlow; } + const char *giveClassName() const override { return "Hexa21Stokes"; } + const char *giveInputRecordName() const override { return _IFT_Hexa21Stokes_Name; } + MaterialMode giveMaterialMode() override { return _3dFlow; } - virtual int computeNumberOfDofs(); + int computeNumberOfDofs() override; - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual void computeField(ValueModeType u, TimeStep *tStep, const FloatArray &coords, FloatArray &answer); + void computeField(ValueModeType u, TimeStep *tStep, const FloatArray &coords, FloatArray &answer) override; // Nodal averaging interface: - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; }; } // end namespace oofem #endif // hexa21stokes_h diff --git a/src/fm/leplic.C b/src/fm/leplic.C index a1e3bd1f4..758a07255 100644 --- a/src/fm/leplic.C +++ b/src/fm/leplic.C @@ -82,12 +82,11 @@ LEPlicElementInterface :: isBoundary() } -contextIOResultType -LEPlicElementInterface :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +LEPlicElementInterface :: saveContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - // write a raw data if ( !stream.write(vof) ) { THROW_CIOERR(CIO_IOERR); } @@ -99,16 +98,13 @@ LEPlicElementInterface :: saveContext(DataStream &stream, ContextMode mode, void if ( ( iores = normal.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -LEPlicElementInterface :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +LEPlicElementInterface :: restoreContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - // read raw data if ( !stream.read(vof) ) { THROW_CIOERR(CIO_IOERR); } @@ -124,13 +120,10 @@ LEPlicElementInterface :: restoreContext(DataStream &stream, ContextMode mode, v } temp_normal = normal; - return CIO_OK; } - - void LEPlic :: updatePosition(TimeStep *tStep) { @@ -159,13 +152,11 @@ void LEPlic :: doLagrangianPhase(TimeStep *tStep) { //Maps element nodes along trajectories using basic Runge-Kutta method (midpoint rule) - int i, ci, ndofman = domain->giveNumberOfDofManagers(); + int ci, ndofman = domain->giveNumberOfDofManagers(); int nsd = 2; double dt = tStep->giveTimeIncrement(); - DofManager *dman; - Node *inode; IntArray velocityMask; - FloatArray x, x2(nsd), v_t, v_tn1; + FloatArray x2(nsd), v_t, v_tn1; FloatMatrix t; #if 1 EngngModel *emodel = domain->giveEngngModel(); @@ -177,16 +168,16 @@ LEPlic :: doLagrangianPhase(TimeStep *tStep) updated_YCoords.resize(ndofman); - for ( i = 1; i <= ndofman; i++ ) { - dman = domain->giveDofManager(i); - inode = dynamic_cast< Node * >(dman); + for ( int i = 1; i <= ndofman; i++ ) { + DofManager *dman = domain->giveDofManager(i); + Node *inode = dynamic_cast< Node * >(dman); // skip dofmanagers with no position information if ( !inode ) { continue; } // get node coordinates - x = * ( inode->giveCoordinates() ); + const auto &x = inode->giveCoordinates(); // get velocity field v(tn, x(tn)) for dof manager #if 1 @@ -203,9 +194,8 @@ LEPlic :: doLagrangianPhase(TimeStep *tStep) // compute interpolated velocity field at x2 [ v(tn+1, x(tn)+0.5*dt*v(tn,x(tn))) = v(tn+1, x2) ] - FieldPtr vfield; - vfield = emodel->giveContext()->giveFieldManager()->giveField(FT_Velocity); - if ( vfield == NULL ) { + FieldPtr vfield = emodel->giveContext()->giveFieldManager()->giveField(FT_Velocity); + if ( !vfield ) { OOFEM_ERROR("Velocity field not available"); } @@ -219,7 +209,7 @@ LEPlic :: doLagrangianPhase(TimeStep *tStep) // compute final updated position for ( ci = 1; ci <= nsd; ci++ ) { - x2.at(ci) = x.at(ci) + dt *v_tn1.at(ci); + x2.at(ci) = x.at(ci) + dt * v_tn1.at(ci); } #else @@ -494,7 +484,7 @@ LEPlic :: doCellDLS(FloatArray &fvgrad, int ie, bool coord_upd, bool vof_temp_fl } ineghbrInterface->giveElementCenter(this, xk, coord_upd); - wk = xk.distance(xi); + wk = distance(xk, xi); dx = ( xk.at(1) - xi.at(1) ) / wk; dy = ( xk.at(2) - xi.at(2) ) / wk; lhs.at(1, 1) += dx * dx; @@ -641,14 +631,11 @@ LEPlic :: findCellLineConstant(double &p, FloatArray &fvgrad, int ie, bool coord } } -IRResultType -LEPlic :: initializeFrom(InputRecord *ir) +void +LEPlic :: initializeFrom(InputRecord &ir) { - IRResultType result; - orig_reference_fluid_volume = 0.0; IR_GIVE_OPTIONAL_FIELD(ir, orig_reference_fluid_volume, _IFT_LEPLIC_refVol); - return IRRT_OK; } diff --git a/src/fm/leplic.h b/src/fm/leplic.h index 393d0a65c..6767a5b92 100644 --- a/src/fm/leplic.h +++ b/src/fm/leplic.h @@ -130,18 +130,14 @@ class LEPlicElementInterface : public Interface * Only non-temp internal history variables are stored. * @param stream stream where to write data * @param mode determines amount of info required in stream (state, definition,...) - * @param obj pointer to integration point, which invokes this method - * @return contextIOResultType. */ - contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode); /** * Restores context of receiver from given stream. * @param stream stream where to read data * @param mode determines amount of info required in stream (state, definition,...) - * @param obj pointer to integration point, which invokes this method - * @return contextIOResultType. */ - contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void restoreContext(DataStream &stream, ContextMode mode); }; /** @@ -170,12 +166,12 @@ class LEPlic : public MaterialInterface orig_reference_fluid_volume = 0.0; } - virtual void updatePosition(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep) { } - virtual void giveMaterialMixtureAt(FloatArray &answer, FloatArray &position); - virtual void giveElementMaterialMixture(FloatArray &answer, int ielem); - virtual double giveNodalScalarRepresentation(int); - virtual double computeCriticalTimeStep(TimeStep *tStep); + void updatePosition(TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override { } + void giveMaterialMixtureAt(FloatArray &answer, FloatArray &position) override; + void giveElementMaterialMixture(FloatArray &answer, int ielem) override; + double giveNodalScalarRepresentation(int) override; + double computeCriticalTimeStep(TimeStep *tStep) override; /** * Returns updated nodal positions. @@ -189,11 +185,11 @@ class LEPlic : public MaterialInterface double giveUpdatedXCoordinate(int num) { return updated_XCoords.at(num); } double giveUpdatedYCoordinate(int num) { return updated_YCoords.at(num); } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; // identification - virtual const char *giveClassName() const { return "LEPlic"; } + const char *giveClassName() const override { return "LEPlic"; } protected: void doLagrangianPhase(TimeStep *tStep); diff --git a/src/fm/levelsetpcs.C b/src/fm/levelsetpcs.C index 11eb4fabc..79318b381 100644 --- a/src/fm/levelsetpcs.C +++ b/src/fm/levelsetpcs.C @@ -71,11 +71,9 @@ LevelSetPCS :: initialize() } -IRResultType -LevelSetPCS :: initializeFrom(InputRecord *ir) +void +LevelSetPCS :: initializeFrom(InputRecord &ir) { - IRResultType result; - IR_GIVE_OPTIONAL_FIELD(ir, previousLevelSetValues, _IFT_LevelSetPCS_levelSetValues); if ( !previousLevelSetValues.giveSize() ) { FloatArray refmatpoly_x, refmatpoly_y; @@ -116,8 +114,6 @@ LevelSetPCS :: initializeFrom(InputRecord *ir) nsd = 2; IR_GIVE_OPTIONAL_FIELD(ir, nsd, _IFT_LevelSetPCS_nsd); - - return IRRT_OK; } @@ -620,8 +616,8 @@ LevelSetPCS :: FMMReinitialization(FloatArray &dmanValues) } -contextIOResultType -LevelSetPCS :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +LevelSetPCS :: saveContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; @@ -632,13 +628,11 @@ LevelSetPCS :: saveContext(DataStream &stream, ContextMode mode, void *obj) if ( ( iores = levelSetValues.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -LevelSetPCS :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +LevelSetPCS :: restoreContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; @@ -654,7 +648,5 @@ LevelSetPCS :: restoreContext(DataStream &stream, ContextMode mode, void *obj) #ifdef LevelSetPCS_CACHE_ELEMENT_VOF elemVofLevelSetVersion = 0; #endif - - return CIO_OK; } } // end namespace oofem diff --git a/src/fm/levelsetpcs.h b/src/fm/levelsetpcs.h index 51a835d6d..020a42b24 100644 --- a/src/fm/levelsetpcs.h +++ b/src/fm/levelsetpcs.h @@ -152,26 +152,26 @@ class LevelSetPCS : public MaterialInterface levelSetVersion = 0; } - virtual void initialize(); - virtual void updatePosition(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep) { previousLevelSetValues = levelSetValues; } - virtual double computeCriticalTimeStep(TimeStep *tStep); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void reinitialization(TimeStep *tStep); - - virtual void giveMaterialMixtureAt(FloatArray &answer, FloatArray &position); - virtual void giveElementMaterialMixture(FloatArray &answer, int ielem); - virtual double giveNodalScalarRepresentation(int i) { return levelSetValues.at(i); } + void initialize() override; + void updatePosition(TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override { previousLevelSetValues = levelSetValues; } + double computeCriticalTimeStep(TimeStep *tStep) override; + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void reinitialization(TimeStep *tStep); + + void giveMaterialMixtureAt(FloatArray &answer, FloatArray &position) override; + void giveElementMaterialMixture(FloatArray &answer, int ielem) override; + double giveNodalScalarRepresentation(int i) override { return levelSetValues.at(i); } /// Returns level set value in specific node double giveLevelSetDofManValue(int i) { return levelSetValues.at(i); } // identification - virtual const char *giveClassName() const { return "LevelSetPCS"; } + const char *giveClassName() const override { return "LevelSetPCS"; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; protected: void pcs_stage1(FloatArray &ls, FloatArray &fs, FloatArray &w, TimeStep *tStep, PCSEqType t); diff --git a/src/fm/line2boundaryelement.C b/src/fm/line2boundaryelement.C index 715a8fbfe..ace473631 100644 --- a/src/fm/line2boundaryelement.C +++ b/src/fm/line2boundaryelement.C @@ -51,9 +51,6 @@ Line2BoundaryElement :: Line2BoundaryElement(int n, Domain *aDomain) : FMElement integrationRulesArray.resize( 0 ); } -Line2BoundaryElement :: ~Line2BoundaryElement() -{ } - FEInterpolation *Line2BoundaryElement :: giveInterpolation() const { return & this->fei; diff --git a/src/fm/line2boundaryelement.h b/src/fm/line2boundaryelement.h index 6acb3015a..dc7c91dc5 100644 --- a/src/fm/line2boundaryelement.h +++ b/src/fm/line2boundaryelement.h @@ -63,24 +63,22 @@ public SpatialLocalizerInterface * @param d Pointer to the domain to which element belongs. */ Line2BoundaryElement(int n, Domain * d); - /// Destructor. - virtual ~Line2BoundaryElement(); - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) { answer.clear(); } - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) { answer.clear(); } + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override { answer.clear(); } + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) override { answer.clear(); } - virtual void giveDofManDofIDMask(int i, IntArray &nodeDofIDMask) const; + void giveDofManDofIDMask(int i, IntArray &nodeDofIDMask) const override; - virtual FEInterpolation *giveInterpolation() const; - virtual int computeNumberOfDofs() { return 6; } + FEInterpolation *giveInterpolation() const override; + int computeNumberOfDofs() override { return 6; } - virtual const char *giveClassName() const { return "Line2BoundaryElement"; } - virtual const char *giveInputRecordName() const { return _IFT_Line2BoundaryElement_Name; } + const char *giveClassName() const override { return "Line2BoundaryElement"; } + const char *giveInputRecordName() const override { return _IFT_Line2BoundaryElement_Name; } // Interfaces - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer); + void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) override; }; } diff --git a/src/fm/newtonianfluid.C b/src/fm/newtonianfluid.C deleted file mode 100644 index 70673dd4a..000000000 --- a/src/fm/newtonianfluid.C +++ /dev/null @@ -1,204 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "newtonianfluid.h" -#include "domain.h" -#include "floatmatrix.h" -#include "gausspoint.h" -#include "engngm.h" -#include "dynamicinputrecord.h" -#include "classfactory.h" - -namespace oofem { -REGISTER_Material(NewtonianFluidMaterial); - -IRResultType -NewtonianFluidMaterial :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - IR_GIVE_FIELD(ir, viscosity, _IFT_NewtonianFluidMaterial_mu); - - return FluidDynamicMaterial :: initializeFrom(ir); -} - - -void -NewtonianFluidMaterial :: giveInputRecord(DynamicInputRecord &input) -{ - FluidDynamicMaterial :: giveInputRecord(input); - input.setField(this->viscosity, _IFT_NewtonianFluidMaterial_mu); -} - - -double -NewtonianFluidMaterial :: giveEffectiveViscosity(GaussPoint *gp, TimeStep *tStep) -{ - return this->viscosity; -} - - -double -NewtonianFluidMaterial :: give(int aProperty, GaussPoint *gp) -{ - if ( aProperty == Viscosity ) { - return viscosity; - } else if ( aProperty == YieldStress ) { - return 0.0; - } else { - return FluidDynamicMaterial :: give(aProperty, gp); - } -} - - -MaterialStatus * -NewtonianFluidMaterial :: CreateStatus(GaussPoint *gp) const -{ - return new FluidDynamicMaterialStatus(1, this->giveDomain(), gp); -} - - -void -NewtonianFluidMaterial :: computeDeviatoricStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &eps, TimeStep *tStep) -{ - int size = eps.giveSize(); - answer.resize(size); - - if ( gp->giveMaterialMode() == _2dFlow ) { - double ekk = eps.at(1) + eps.at(2); - - answer = { - 2.0 * viscosity * ( eps.at(1) - ekk / 3.0 ), - 2.0 * viscosity * ( eps.at(2) - ekk / 3.0 ), - eps.at(3) * viscosity - }; - } else if ( gp->giveMaterialMode() == _2dAxiFlow ) { -#if 1 - double ekk = eps.at(1) + eps.at(2) + eps.at(3); - - answer = { - 2.0 * viscosity * ( eps.at(1) - ekk / 3.0 ), - 2.0 * viscosity * ( eps.at(2) - ekk / 3.0 ), - 2.0 * viscosity * ( eps.at(3) - ekk / 3.0 ), - eps.at(4) * viscosity - }; -#else - answer = { - 2.0 * viscosity * ( eps.at(1) ), - 2.0 * viscosity * ( eps.at(2) ), - 2.0 * viscosity * ( eps.at(3) ), - eps.at(4) * viscosity - }; -#endif - } else if ( gp->giveMaterialMode() == _3dFlow ) { - double ekk = eps.at(1) + eps.at(2) + eps.at(3); - - answer = { - 2.0 * viscosity * ( eps.at(1) - ekk / 3.0 ), - 2.0 * viscosity * ( eps.at(2) - ekk / 3.0 ), - 2.0 * viscosity * ( eps.at(3) - ekk / 3.0 ), - eps.at(4) * viscosity, - eps.at(5) * viscosity, - eps.at(6) * viscosity - }; - } else { - OOFEM_ERROR("unsupported material mode"); - } - - - static_cast< FluidDynamicMaterialStatus * >( this->giveStatus(gp) )->letDeviatoricStressVectorBe(answer); - static_cast< FluidDynamicMaterialStatus * >( this->giveStatus(gp) )->letDeviatoricStrainRateVectorBe(eps); -} - -void -NewtonianFluidMaterial :: giveDeviatoricStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) -{ - if ( ( gp->giveMaterialMode() == _2dFlow ) ) { - answer.resize(3, 3); - answer.zero(); - - answer.at(1, 1) = answer.at(2, 2) = 2.0 * viscosity * ( 2. / 3. ); - answer.at(1, 2) = answer.at(2, 1) = -2.0 * viscosity * ( 1. / 3. ); - answer.at(3, 3) = viscosity; - } else if ( gp->giveMaterialMode() == _2dAxiFlow ) { -#if 1 - answer.resize(4, 4); - answer.zero(); - - answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = 2.0 * viscosity * ( 2. / 3. ); - answer.at(1, 2) = answer.at(1, 3) = -2.0 * viscosity * ( 1. / 3. ); - answer.at(2, 1) = answer.at(2, 3) = -2.0 * viscosity * ( 1. / 3. ); - answer.at(3, 1) = answer.at(3, 2) = -2.0 * viscosity * ( 1. / 3. ); - - answer.at(4, 4) = viscosity; -#else - answer.resize(4, 4); - answer.zero(); - - answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = 2.0 * viscosity; - answer.at(4, 4) = viscosity; -#endif - } else if ( gp->giveMaterialMode() == _3dFlow ) { - answer.resize(6, 6); - answer.zero(); - - answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = 2.0 * viscosity * ( 2. / 3. ); - answer.at(1, 2) = answer.at(1, 3) = -2.0 * viscosity * ( 1. / 3. ); - answer.at(2, 1) = answer.at(2, 3) = -2.0 * viscosity * ( 1. / 3. ); - answer.at(3, 1) = answer.at(3, 2) = -2.0 * viscosity * ( 1. / 3. ); - - answer.at(4, 4) = answer.at(5, 5) = answer.at(6, 6) = viscosity; - } else { - OOFEM_ERROR("unsupportted material mode"); - } -} - - -int -NewtonianFluidMaterial :: checkConsistency() -{ - ///@todo Fix this, checkConsistency shouldn't be a replacement for "post-initialization" but should be completely optional. - if ( domain->giveEngngModel()->giveEquationScalingFlag() ) { - double scale; - scale = domain->giveEngngModel()->giveVariableScale(VST_Density); - propertyDictionary.at('d') /= scale; - - scale = domain->giveEngngModel()->giveVariableScale(VST_Viscosity); - this->viscosity /= scale; - } - - return 1; -} -} // end namespace oofem diff --git a/src/fm/pfem/delaunaytriangle.C b/src/fm/pfem/delaunaytriangle.C index 8616b2e9d..77a492b5f 100644 --- a/src/fm/pfem/delaunaytriangle.C +++ b/src/fm/pfem/delaunaytriangle.C @@ -36,6 +36,7 @@ #include "dofmanager.h" #include "math.h" #include "octreelocalizert.h" +#include "octreelocalizertutil.h" #include "mathfem.h" namespace oofem { @@ -137,7 +138,7 @@ DelaunayTriangle :: giveEdgeLength(int nodeA, int nodeB) DofManager *dmanA = domain->giveDofManager( giveNode(nodeA) ); DofManager *dmanB = domain->giveDofManager( giveNode(nodeB) ); - return dmanA->giveCoordinates()->distance( dmanB->giveCoordinates() ); + return distance(*dmanA->giveCoordinates(), *dmanB->giveCoordinates()); } } // end namespace oofem diff --git a/src/fm/pfem/delaunaytriangulator.C b/src/fm/pfem/delaunaytriangulator.C index d1ddd66ab..17a955449 100644 --- a/src/fm/pfem/delaunaytriangulator.C +++ b/src/fm/pfem/delaunaytriangulator.C @@ -60,39 +60,33 @@ DelaunayTriangulator :: DelaunayTriangulator(Domain *d, double setAlpha) : DelaunayTriangulator :: ~DelaunayTriangulator() { - // clean up triangle list - for ( genIT = generalTriangleList.begin(); genIT != generalTriangleList.end(); ) { - delete( * genIT ); - genIT = generalTriangleList.erase(genIT); + for ( auto tri : generalTriangleList ) { + delete tri; } - for ( elIT = edgeList.begin(); elIT != edgeList.end(); ++elIT ) { - delete( * elIT ); + for ( auto edge : edgeList ) { + delete edge; } } -void DelaunayTriangulator :: addUniqueEdgeToPolygon(Edge2D *edge, std :: list< Edge2D > &polygon) +void DelaunayTriangulator :: addUniqueEdgeToPolygon(Edge2D edge, std :: list< Edge2D > &polygon) { - std :: list< Edge2D > :: iterator pos; - int addingMask = 1; - - if ( !polygon.empty() ) { - for ( pos = polygon.begin(); pos != polygon.end(); ) { - if ( ( * pos ) == * edge ) { - pos = polygon.erase(pos); - delete edge; - addingMask = 0; - break; - } else { - ++pos; - } + int do_add = 1; + + for ( auto pos = polygon.begin(); pos != polygon.end(); ) { + if ( ( * pos ) == edge ) { + pos = polygon.erase(pos); + do_add = 0; + break; + } else { + ++pos; } } - if ( addingMask ) { - polygon.push_back(* edge); + if ( do_add ) { + polygon.push_back(edge); } } @@ -142,7 +136,6 @@ void DelaunayTriangulator :: writeMesh() { int num = 1; int nelem = generalTriangleList.size(); - Element *elem; IntArray dmans(3); DofManager *dman; DofIDItem type; @@ -160,10 +153,10 @@ void DelaunayTriangulator :: writeMesh() domain->resizeElements(nelem); //from domain.C - for ( genIT = generalTriangleList.begin(); genIT != generalTriangleList.end(); genIT++ ) { - elem = new TR1_2D_PFEM(num, domain, ( * genIT )->giveNode(1), ( * genIT )->giveNode(2), ( * genIT )->giveNode(3), mat, cs); + for ( auto gen : generalTriangleList ) { + auto elem = std::make_unique(num, domain, gen->giveNode(1), gen->giveNode(2), gen->giveNode(3), mat, cs); - domain->setElement(num, elem); + domain->setElement(num, std::move(elem)); num++; } @@ -177,10 +170,10 @@ void DelaunayTriangulator :: writeMesh() } // and then prescribe zero pressure on the free surface - for ( elIT = alphaShapeEdgeList.begin(); elIT != alphaShapeEdgeList.end(); elIT++ ) { + for ( auto el : alphaShapeEdgeList ) { bool oneIsFree = false; hasNoBcOnItself = true; - dman = domain->giveDofManager( ( * elIT )->giveFirstNodeNumber() ); + dman = domain->giveDofManager( el->giveFirstNodeNumber() ); for ( Dof *dof: *dman ) { type = dof->giveDofID(); if ( ( type == V_u ) || ( type == V_v ) || ( type == V_w ) ) { @@ -196,7 +189,7 @@ void DelaunayTriangulator :: writeMesh() dynamic_cast< PFEMParticle * >( dman )->setOnAlphaShape(); hasNoBcOnItself = true; - dman = domain->giveDofManager( ( * elIT )->giveSecondNodeNumber() ); + dman = domain->giveDofManager( el->giveSecondNodeNumber() ); for ( Dof *dof: *dman ) { type = dof->giveDofID(); if ( ( type == V_u ) || ( type == V_v ) || ( type == V_w ) ) { @@ -212,10 +205,10 @@ void DelaunayTriangulator :: writeMesh() dynamic_cast< PFEMParticle * >( dman )->setOnAlphaShape(); if ( oneIsFree ) { - Dof *dofOnNode1 = domain->giveDofManager( ( * elIT )->giveFirstNodeNumber() )->giveDofWithID(P_f); + Dof *dofOnNode1 = domain->giveDofManager( el->giveFirstNodeNumber() )->giveDofWithID(P_f); dofOnNode1->setBcId(pressureBC); - Dof *dofOnNode2 = domain->giveDofManager( ( * elIT )->giveSecondNodeNumber() )->giveDofWithID(P_f); + Dof *dofOnNode2 = domain->giveDofManager( el->giveSecondNodeNumber() )->giveDofWithID(P_f); dofOnNode2->setBcId(pressureBC); } } @@ -228,28 +221,28 @@ void DelaunayTriangulator :: computeAlphaComplex() bool alphaLengthInitialized = false; double minimalLength = 1.e6; - for ( genIT = generalTriangleList.begin(); genIT != generalTriangleList.end(); genIT++ ) { + for ( auto &gen : generalTriangleList ) { if ( alphaLengthInitialized ) { - minimalLength = min( ( * genIT )->giveShortestEdgeLength(), minimalLength ); + minimalLength = min( gen->giveShortestEdgeLength(), minimalLength ); } else { - minimalLength = ( * genIT )->giveShortestEdgeLength(); + minimalLength = gen->giveShortestEdgeLength(); alphaLengthInitialized = true; } - int par1 = ( * genIT )->giveNode(1); - int par2 = ( * genIT )->giveNode(2); - int par3 = ( * genIT )->giveNode(3); - double ccRadius = ( * genIT )->giveCircumRadius(); + int par1 = gen->giveNode(1); + int par2 = gen->giveNode(2); + int par3 = gen->giveNode(3); + double ccRadius = gen->giveCircumRadius(); AlphaEdge2D *containedEdge; - AlphaEdge2D *edge1 = new AlphaEdge2D( par1, par2, ( * genIT )->giveEdgeLength(1, 2) ); + AlphaEdge2D *edge1 = new AlphaEdge2D( par1, par2, gen->giveEdgeLength(1, 2) ); - containedEdge = giveBackEdgeIfAlreadyContainedInList(edge1); + containedEdge = giveBackEdgeIfAlreadyContainedInList(*edge1); if ( containedEdge ) { delete edge1; - containedEdge->setSharing( 2, ( * genIT ) ); + containedEdge->setSharing( 2, gen ); double outAlph = containedEdge->giveOuterAlphaBound(); if ( ccRadius < outAlph ) { containedEdge->setOuterAlphaBound(ccRadius); @@ -268,17 +261,17 @@ void DelaunayTriangulator :: computeAlphaComplex() edge1->setInnerAlphaBound(ccRadius); edge1->setHullFlag(true); - edge1->setSharing( 1, ( * genIT ) ); + edge1->setSharing( 1, gen ); edgeList.push_back(edge1); } - AlphaEdge2D *edge2 = new AlphaEdge2D( par2, par3, ( * genIT )->giveEdgeLength(2, 3) ); + AlphaEdge2D *edge2 = new AlphaEdge2D( par2, par3, gen->giveEdgeLength(2, 3) ); - containedEdge = giveBackEdgeIfAlreadyContainedInList(edge2); + containedEdge = giveBackEdgeIfAlreadyContainedInList(*edge2); if ( containedEdge ) { delete edge2; - containedEdge->setSharing( 2, ( * genIT ) ); + containedEdge->setSharing( 2, gen ); double outAlph = containedEdge->giveOuterAlphaBound(); if ( ccRadius < outAlph ) { @@ -298,17 +291,17 @@ void DelaunayTriangulator :: computeAlphaComplex() edge2->setInnerAlphaBound(ccRadius); edge2->setHullFlag(true); - edge2->setSharing( 1, ( * genIT ) ); + edge2->setSharing( 1, gen ); edgeList.push_back(edge2); } - AlphaEdge2D *edge3 = new AlphaEdge2D( par3, par1, ( * genIT )->giveEdgeLength(3, 1) ); + AlphaEdge2D *edge3 = new AlphaEdge2D( par3, par1, gen->giveEdgeLength(3, 1) ); - containedEdge = giveBackEdgeIfAlreadyContainedInList(edge3); + containedEdge = giveBackEdgeIfAlreadyContainedInList(*edge3); if ( containedEdge ) { delete edge3; - containedEdge->setSharing( 2, ( * genIT ) ); + containedEdge->setSharing( 2, gen ); double outAlph = containedEdge->giveOuterAlphaBound(); if ( ccRadius < outAlph ) { @@ -328,7 +321,7 @@ void DelaunayTriangulator :: computeAlphaComplex() edge3->setInnerAlphaBound(ccRadius); edge3->setHullFlag(true); - edge3->setSharing( 1, ( * genIT ) ); + edge3->setSharing( 1, gen ); edgeList.push_back(edge3); } } @@ -338,56 +331,50 @@ void DelaunayTriangulator :: computeAlphaComplex() //gives back pointer from edgeList ////////////////////////////////////////////////////////////////////////// -AlphaEdge2D *DelaunayTriangulator :: giveBackEdgeIfAlreadyContainedInList(AlphaEdge2D *alphaEdge) +AlphaEdge2D *DelaunayTriangulator :: giveBackEdgeIfAlreadyContainedInList(AlphaEdge2D &alphaEdge) { - AlphaEdge2D *foundEdge = NULL; - - if ( !edgeList.empty() ) { - for ( elIT = edgeList.begin(); elIT != edgeList.end(); ++elIT ) { - if ( ( * * elIT ) == ( * alphaEdge ) ) { - foundEdge = * elIT; - edgeList.erase(elIT); - break; - } + for ( auto elIT = edgeList.begin(); elIT != edgeList.end(); ++elIT ) { + if ( ( * * elIT ) == alphaEdge ) { + AlphaEdge2D *foundEdge = * elIT; + edgeList.erase(elIT); + return foundEdge; } } - return foundEdge; + return nullptr; } ////////////////////////////////////////////////////////////////////////// void DelaunayTriangulator :: giveAlphaShape() { - double outBound, innBound; - - for ( elIT = edgeList.begin(); elIT != edgeList.end(); elIT++ ) { + for ( auto el : edgeList ) { // Option 2 : setting bounds vor computed Alpha - //double alpha = max(min(alphaValue * (*elIT)->giveLength(), maxAlpha), minAlpha); + //double alpha = max(min(alphaValue * el->giveLength(), maxAlpha), minAlpha); double alpha = alphaValue; - outBound = ( * elIT )->giveOuterAlphaBound(); + double outBound = el->giveOuterAlphaBound(); //innerBound = infinity - if ( ( * elIT )->giveHullFlag() ) { + if ( el->giveHullFlag() ) { if ( alpha > outBound ) { - alphaShapeEdgeList.push_back(* elIT); + alphaShapeEdgeList.push_back(el); } else { //invalidating element - ( * elIT )->giveShared(1)->setValidFlag(false); + el->giveShared(1)->setValidFlag(false); } } else { - innBound = ( * elIT )->giveInnerAlphaBound(); + double innBound = el->giveInnerAlphaBound(); if ( alpha > outBound && alpha < innBound ) { - alphaShapeEdgeList.push_back(* elIT); - if ( ( * elIT )->giveShared(1)->giveCircumRadius() > alpha ) { - ( * elIT )->giveShared(1)->setValidFlag(false); + alphaShapeEdgeList.push_back(el); + if ( el->giveShared(1)->giveCircumRadius() > alpha ) { + el->giveShared(1)->setValidFlag(false); } else { - ( * elIT )->giveShared(2)->setValidFlag(false); + el->giveShared(2)->setValidFlag(false); } } if ( alpha < outBound ) { for ( int i = 1; i <= 2; i++ ) { - ( * elIT )->giveShared(i)->setValidFlag(false); + el->giveShared(i)->setValidFlag(false); } } } @@ -409,30 +396,21 @@ DelaunayTriangulator :: initializeTimers() void DelaunayTriangulator :: findNonDelaunayTriangles(int insertedNode, InsertTriangleBasedOnCircumcircle &tInsert, std :: list< Edge2D > &polygon) { - DofManager *dman = domain->giveDofManager(insertedNode); - FloatArray *nodeCoords = ( ( ( Node * ) dman )->giveCoordinates() ); + DofManager *node = domain->giveNode(insertedNode); + const auto &nodeCoords = *node->giveCoordinates(); ElementCircumCirclesContainingNode findElements(nodeCoords, domain); - std :: list< DelaunayTriangle * >nonDelaunayTriangles; - std :: list< DelaunayTriangle * > :: iterator triangleIT; + std :: list< DelaunayTriangle * > nonDelaunayTriangles; this->searchingTimer.resumeTimer(); triangleOctree.proceedDataOnFilterAndRemoveFromOctree(nonDelaunayTriangles, findElements, tInsert, searchingTimer); this->searchingTimer.pauseTimer(); this->polygonTimer.resumeTimer(); - for ( triangleIT = nonDelaunayTriangles.begin(); triangleIT != nonDelaunayTriangles.end(); ++triangleIT ) { - DelaunayTriangle *triangle; - triangle = * triangleIT; - Edge2D *edge1 = new Edge2D( triangle->giveNode(1), triangle->giveNode(2) ); - addUniqueEdgeToPolygon(edge1, polygon); - - Edge2D *edge2 = new Edge2D( triangle->giveNode(2), triangle->giveNode(3) ); - addUniqueEdgeToPolygon(edge2, polygon); - - Edge2D *edge3 = new Edge2D( triangle->giveNode(3), triangle->giveNode(1) ); - addUniqueEdgeToPolygon(edge3, polygon); - + for ( auto triangle : nonDelaunayTriangles ) { + addUniqueEdgeToPolygon({triangle->giveNode(1), triangle->giveNode(2)}, polygon); + addUniqueEdgeToPolygon({triangle->giveNode(2), triangle->giveNode(3)}, polygon); + addUniqueEdgeToPolygon({triangle->giveNode(3), triangle->giveNode(1)}, polygon); triangle->setValidFlag(false); } @@ -442,8 +420,7 @@ DelaunayTriangulator :: findNonDelaunayTriangles(int insertedNode, InsertTriangl void DelaunayTriangulator :: meshPolygon(int insertedNode, InsertTriangleBasedOnCircumcircle &tInsert, std :: list< Edge2D > &polygon) { - std :: list< Edge2D > :: iterator polygonIT; - for ( polygonIT = polygon.begin(); polygonIT != polygon.end(); polygonIT++ ) { + for ( auto polygonIT = polygon.begin(); polygonIT != polygon.end(); polygonIT++ ) { DelaunayTriangle *newTriangle = new DelaunayTriangle(domain, ( * polygonIT ).giveFirstNodeNumber(), ( * polygonIT ).giveSecondNodeNumber(), insertedNode); this->creativeTimer.resumeTimer(); @@ -480,7 +457,7 @@ DelaunayTriangulator :: giveTimeReport() void DelaunayTriangulator :: cleanUpTriangleList() { - for ( genIT = generalTriangleList.begin(); genIT != generalTriangleList.end(); ) { + for ( auto genIT = generalTriangleList.begin(); genIT != generalTriangleList.end(); ) { int node1 = ( * genIT )->giveNode(1); int node2 = ( * genIT )->giveNode(2); int node3 = ( * genIT )->giveNode(3); @@ -507,7 +484,7 @@ void DelaunayTriangulator :: buildInitialBBXMesh(InsertTriangleBasedOnCircumcirc FloatArray coords; - Node *bottomLeftNode = new Node(nnode + 1, domain); + auto bottomLeftNode = std::make_unique(nnode + 1, domain); BBX.giveOrigin(coords); double diff = BBX.giveSize(); for ( int ci = 1; ci <= 2; ci++ ) { @@ -516,23 +493,23 @@ void DelaunayTriangulator :: buildInitialBBXMesh(InsertTriangleBasedOnCircumcirc bottomLeftNode->setCoordinates(coords); - Node *bottomRightNode = new Node(nnode + 2, domain); + auto bottomRightNode = std::make_unique(nnode + 2, domain); coords.at(1) += BBX.giveSize() + 2.0 * diff; bottomRightNode->setCoordinates(coords); - Node *topRightNode = new Node(nnode + 3, domain); + auto topRightNode = std::make_unique(nnode + 3, domain); coords.at(2) += BBX.giveSize() + 2.0 * diff; topRightNode->setCoordinates(coords); - Node *topLeftNode = new Node(nnode + 4, domain); + auto topLeftNode = std::make_unique(nnode + 4, domain); coords.at(1) -= BBX.giveSize() + 2.0 * diff; topLeftNode->setCoordinates(coords); domain->resizeDofManagers(nnode + 4); - domain->setDofManager(nnode + 1, bottomLeftNode); - domain->setDofManager(nnode + 2, bottomRightNode); - domain->setDofManager(nnode + 3, topRightNode); - domain->setDofManager(nnode + 4, topLeftNode); + domain->setDofManager(nnode + 1, std::move(bottomLeftNode)); + domain->setDofManager(nnode + 2, std::move(bottomRightNode)); + domain->setDofManager(nnode + 3, std::move(topRightNode)); + domain->setDofManager(nnode + 4, std::move(topLeftNode)); DelaunayTriangle *firstTriangle = new DelaunayTriangle(domain, nnode + 1, nnode + 2, nnode + 3); generalTriangleList.push_back(firstTriangle); @@ -540,7 +517,6 @@ void DelaunayTriangulator :: buildInitialBBXMesh(InsertTriangleBasedOnCircumcirc DelaunayTriangle *secondTriangle = new DelaunayTriangle(domain, nnode + 3, nnode + 4, nnode + 1); generalTriangleList.push_back(secondTriangle); - triangleOctree.insertMemberIntoOctree(firstTriangle, tInsert); triangleOctree.insertMemberIntoOctree(secondTriangle, tInsert); } @@ -548,52 +524,49 @@ void DelaunayTriangulator :: buildInitialBBXMesh(InsertTriangleBasedOnCircumcirc void DelaunayTriangulator:: computeBBXBasedOnNodeData(BoundingBox &BBX) { - int i, j, init = 1, nnode = this->domain->giveNumberOfDofManagers(); - double rootSize, resolutionLimit; - FloatArray minc(3), maxc(3), * coords; - DofManager *dman; - - // first determine domain extends (bounding box), and check for degenerated domain type - for ( i = 1; i <= nnode; i++ ) { - dman = domain->giveDofManager(i); - coords = static_cast< Node * >( dman )->giveCoordinates(); - if ( init ) { - init = 0; - for ( j = 1; j <= coords->giveSize(); j++ ) { - minc.at(j) = maxc.at(j) = coords->at(j); - } - } else { - for ( j = 1; j <= coords->giveSize(); j++ ) { - if ( coords->at(j) < minc.at(j) ) { - minc.at(j) = coords->at(j); - } - - if ( coords->at(j) > maxc.at(j) ) { - maxc.at(j) = coords->at(j); - } - } + int init = 1, nnode = this->domain->giveNumberOfDofManagers(); + FloatArray minc(3), maxc(3); + + // first determine domain extends (bounding box), and check for degenerated domain type + for ( int i = 1; i <= nnode; i++ ) { + auto node = domain->giveNode(i); + const auto &coords = node->giveCoordinates(); + if ( init ) { + init = 0; + for ( int j = 1; j <= coords->giveSize(); j++ ) { + minc.at(j) = maxc.at(j) = coords->at(j); + } + } else { + for ( int j = 1; j <= coords->giveSize(); j++ ) { + if ( coords->at(j) < minc.at(j) ) { + minc.at(j) = coords->at(j); + } + if ( coords->at(j) > maxc.at(j) ) { + maxc.at(j) = coords->at(j); + } + } + } + } // end loop over nodes + + BBX.setOrigin(minc); + + // determine root size + double rootSize = 0.0; + for ( int i = 1; i <= 3; i++ ) { + rootSize = 1.000001 * max( rootSize, maxc.at(i) - minc.at(i) ); } - } // end loop over nodes - - BBX.setOrigin(minc); - - // determine root size - rootSize = 0.0; - for ( i = 1; i <= 3; i++ ) { - rootSize = 1.000001 * max( rootSize, maxc.at(i) - minc.at(i) ); - } - - BBX.setSize(rootSize); - - // check for degenerated domain - resolutionLimit = min(1.e-3, rootSize / 1.e6); - for ( i = 1; i <= 3; i++ ) { - if ( ( maxc.at(i) - minc.at(i) ) > resolutionLimit ) { - BBX.setMask(i, 1); - } else { - BBX.setMask(i, 0); + + BBX.setSize(rootSize); + + // check for degenerated domain + double resolutionLimit = min(1.e-3, rootSize / 1.e6); + for ( int i = 1; i <= 3; i++ ) { + if ( ( maxc.at(i) - minc.at(i) ) > resolutionLimit ) { + BBX.setMask(i, 1); + } else { + BBX.setMask(i, 0); + } } - } } diff --git a/src/fm/pfem/delaunaytriangulator.h b/src/fm/pfem/delaunaytriangulator.h index 4b7b617f5..0583c5762 100644 --- a/src/fm/pfem/delaunaytriangulator.h +++ b/src/fm/pfem/delaunaytriangulator.h @@ -46,6 +46,7 @@ #include "contextioresulttype.h" #include "timer.h" #include "octreelocalizert.h" +#include "octreelocalizertutil.h" #include "intarray.h" #include "edge2d.h" @@ -85,14 +86,12 @@ class DelaunayTriangulator Timer creativeTimer; /// Contains all triangles (even not valid) std :: list< DelaunayTriangle * >generalTriangleList; - std :: list< DelaunayTriangle * > :: iterator genIT; /// Contains resulting alpha-shape in form of a list std :: list< AlphaEdge2D * >alphaShapeEdgeList; /// contains all edges of the triangulation std :: list< AlphaEdge2D * >edgeList; - std :: list< AlphaEdge2D * > :: iterator elIT; /// Octree with Delaunay triangles allowing fast search OctreeSpatialLocalizerT< DelaunayTriangle * >triangleOctree; @@ -108,7 +107,7 @@ class DelaunayTriangulator private: /// Edge is added to the polygon only if it's not contained. Otherwise both are removed (edge shared by two non-Delaunay triangles). - void addUniqueEdgeToPolygon(Edge2D *edge, std :: list< Edge2D > &polygon); + void addUniqueEdgeToPolygon(Edge2D edge, std :: list< Edge2D > &polygon); /// Identifies the bounding box of pfemparticles and creates initial triangulation consisting of 2 triangles conecting bounding box nodes void buildInitialBBXMesh(InsertTriangleBasedOnCircumcircle &tInsert); @@ -121,7 +120,7 @@ class DelaunayTriangulator /** * Fills the edgeList with unique alphaEdges. If an edge is already contained a pointer to it is returned and inserted edge is removed. */ - AlphaEdge2D *giveBackEdgeIfAlreadyContainedInList(AlphaEdge2D *alphaEdge); + AlphaEdge2D *giveBackEdgeIfAlreadyContainedInList(AlphaEdge2D &alphaEdge); /// Iterates through the edgeList container and compares alpha-value with alphaEdge bounds. Alpha shape is stored in the alphaShapeEdgeList void giveAlphaShape(); diff --git a/src/fm/pfem/fluidstructureproblem.C b/src/fm/pfem/fluidstructureproblem.C index 043a9ee0a..778dd4ae2 100644 --- a/src/fm/pfem/fluidstructureproblem.C +++ b/src/fm/pfem/fluidstructureproblem.C @@ -46,8 +46,8 @@ #include "pfem.h" #include "interactionpfemparticle.h" -#include "../../sm/EngineeringModels/diidynamic.h" -#include "../../sm/EngineeringModels/nlineardynamic.h" +#include "sm/EngineeringModels/diidynamic.h" +#include "sm/EngineeringModels/nlineardynamic.h" #include @@ -70,15 +70,10 @@ FluidStructureProblem :: ~FluidStructureProblem() {} -IRResultType -FluidStructureProblem :: initializeFrom(InputRecord *ir) +void +FluidStructureProblem :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StaggeredProblem :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StaggeredProblem :: initializeFrom(ir); maxiter = 50; IR_GIVE_OPTIONAL_FIELD(ir, maxiter, _IFT_FluidStructureProblem_maxiter); @@ -88,8 +83,6 @@ FluidStructureProblem :: initializeFrom(InputRecord *ir) rtolp = 1.e-3; IR_GIVE_OPTIONAL_FIELD(ir, rtolp, _IFT_FluidStructureProblem_rtolp); - - return IRRT_OK; } void diff --git a/src/fm/pfem/fluidstructureproblem.h b/src/fm/pfem/fluidstructureproblem.h index 46f017953..0045357e8 100644 --- a/src/fm/pfem/fluidstructureproblem.h +++ b/src/fm/pfem/fluidstructureproblem.h @@ -81,25 +81,24 @@ class OOFEM_EXPORT FluidStructureProblem : public StaggeredProblem void setUDContextOutputMode(int cStep); void setProblemMode(problemMode pmode); - virtual void solveYourselfAt(TimeStep *tStep); - virtual void initializeYourself(TimeStep *tStep); - virtual int initializeAdaptive(int stepNumber) { return 0; } + void solveYourselfAt(TimeStep *tStep) override; + void initializeYourself(TimeStep *tStep) override; + int initializeAdaptive(int stepNumber) override { return 0; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; void printYourself(); - virtual void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *atTime) { } + void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *atTime) override { } - virtual void preInitializeNextStep(); + void preInitializeNextStep() override; // identification - virtual const char *giveClassName() const { return "FluidStructureProblem"; } - virtual const char *giveInputRecordName() const { return _IFT_FluidStructureProblem_Name; } - virtual int isIncremental() { return 0; } - virtual int useNonlocalStiffnessOption() { return 0; } - - virtual fMode giveFormulation() { return UNKNOWN; } + const char *giveClassName() const override { return "FluidStructureProblem"; } + const char *giveInputRecordName() const override { return _IFT_FluidStructureProblem_Name; } + int isIncremental() { return 0; } + int useNonlocalStiffnessOption() override { return 0; } + fMode giveFormulation() override { return UNKNOWN; } /// Returns list of model number that this model is coupled with. Used for staggered approach. void giveCoupledModels(IntArray &answer) { answer = coupledModels; } @@ -108,15 +107,10 @@ class OOFEM_EXPORT FluidStructureProblem : public StaggeredProblem /** * Shows the sparse structure of required matrix, type == 1 stiffness. */ - virtual void showSparseMtrxStructure(int type, oofegGraphicContext &context, TimeStep *atTime) { } + void showSparseMtrxStructure(int type, oofegGraphicContext &context, TimeStep *atTime) override { } #endif - virtual int giveNumberOfSlaveProblems() { return ( int ) inputStreamNames.size(); } - - virtual int giveNumberOfFirstStep() { if ( master ) { return master->giveNumberOfFirstStep(); } else { return 1; } } - virtual int giveNumberOfTimeStepWhenIcApply() { - if ( master ) { return master->giveNumberOfTimeStepWhenIcApply(); } else { return 0; } - } + int giveNumberOfSlaveProblems() override { return ( int ) inputStreamNames.size(); } int giveIterationNumber() { return iterationNumber; } }; diff --git a/src/fm/pfem/interactionload.C b/src/fm/pfem/interactionload.C index 20a19a72c..ed86ae9d6 100644 --- a/src/fm/pfem/interactionload.C +++ b/src/fm/pfem/interactionload.C @@ -45,15 +45,12 @@ namespace oofem { REGISTER_BoundaryCondition(InteractionLoad); -IRResultType -InteractionLoad :: initializeFrom(InputRecord *ir) +void +InteractionLoad :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + LinearEdgeLoad :: initializeFrom(ir); IR_GIVE_FIELD(ir, coupledParticles, _IFT_InteractionLoad_CoupledParticles); - - - return LinearEdgeLoad :: initializeFrom(ir); } diff --git a/src/fm/pfem/interactionload.h b/src/fm/pfem/interactionload.h index 05f02712e..66724aef8 100644 --- a/src/fm/pfem/interactionload.h +++ b/src/fm/pfem/interactionload.h @@ -68,19 +68,19 @@ class OOFEM_EXPORT InteractionLoad : public LinearEdgeLoad public: InteractionLoad(int i, Domain *d) : LinearEdgeLoad(i, d), coupledParticles(2) { } - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; - virtual int giveApproxOrder() { return 1; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual bcGeomType giveBCGeoType() const { return EdgeLoadBGT; } - virtual FormulationType giveFormulationType() { return formulation; } + int giveApproxOrder() override { return 1; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + bcGeomType giveBCGeoType() const override { return EdgeLoadBGT; } + FormulationType giveFormulationType() override { return formulation; } - virtual const char *giveClassName() const { return "InteractionLoad"; } - virtual const char *giveInputRecordName() const { return _IFT_InteractionLoad_Name; } + const char *giveClassName() const override { return "InteractionLoad"; } + const char *giveInputRecordName() const override { return _IFT_InteractionLoad_Name; } protected: - virtual void computeNArray(FloatArray &answer, const FloatArray &coords) const; + void computeNArray(FloatArray &answer, const FloatArray &coords) const override; }; } // end namespace oofem #endif // interactionload_h diff --git a/src/fm/pfem/interactionpfemparticle.C b/src/fm/pfem/interactionpfemparticle.C index ced46dc71..d0de20fd1 100644 --- a/src/fm/pfem/interactionpfemparticle.C +++ b/src/fm/pfem/interactionpfemparticle.C @@ -38,7 +38,7 @@ #include "classfactory.h" #include "floatmatrix.h" #include "fluidstructureproblem.h" -#include "../../sm/EngineeringModels/structengngmodel.h" +#include "sm/EngineeringModels/structengngmodel.h" #include "domain.h" #include "dof.h" #include "mathfem.h" @@ -56,16 +56,12 @@ InteractionPFEMParticle :: InteractionPFEMParticle(int n, Domain *aDomain) : PFE /** * Gets from the source line from the data file all the data of the receiver. */ -IRResultType -InteractionPFEMParticle :: initializeFrom(InputRecord *ir) +void +InteractionPFEMParticle :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = PFEMParticle :: initializeFrom(ir); + PFEMParticle :: initializeFrom(ir); IR_GIVE_OPTIONAL_FIELD(ir, coupledNode, _IFT_InteractionPFEMParticle_CoupledNode); - - return (result != IRRT_OK) ? result : IRRT_OK; } /** @@ -130,7 +126,7 @@ InteractionPFEMParticle::giveCoupledVelocities(FloatArray &answer, TimeStep *ste } void -InteractionPFEMParticle :: printOutputAt(FILE *stream, TimeStep *stepN) +InteractionPFEMParticle :: printOutputAt(FILE *stream, TimeStep *stepN) const { PFEMParticle :: printOutputAt(stream, stepN); } diff --git a/src/fm/pfem/interactionpfemparticle.h b/src/fm/pfem/interactionpfemparticle.h index cefdaca67..dc41e25ac 100644 --- a/src/fm/pfem/interactionpfemparticle.h +++ b/src/fm/pfem/interactionpfemparticle.h @@ -70,25 +70,25 @@ class OOFEM_EXPORT InteractionPFEMParticle : public PFEMParticle /** * Destructor. */ - ~InteractionPFEMParticle(void) { } + virtual ~InteractionPFEMParticle(void) { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int checkConsistency(); + void initializeFrom(InputRecord &ir) override; + int checkConsistency() override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual void givePrescribedUnknownVector(FloatArray &answer, const IntArray &dofMask, - ValueModeType mode, TimeStep *stepN); + void givePrescribedUnknownVector(FloatArray &answer, const IntArray &dofMask, + ValueModeType mode, TimeStep *stepN) override; void giveCoupledVelocities(FloatArray &answer, TimeStep *stepN); - virtual void printOutputAt(FILE *stream, TimeStep *stepN); + void printOutputAt(FILE *stream, TimeStep *stepN) const override; - virtual const char *giveClassName() const { return "InteractionPFEMParticle"; } - virtual const char *giveInputRecordName() const { return _IFT_InteractionPFEMParticle_Name; } + const char *giveClassName() const override { return "InteractionPFEMParticle"; } + const char *giveInputRecordName() const override { return _IFT_InteractionPFEMParticle_Name; } #ifdef __OOFEG - virtual void drawScalar(oofegGraphicContext &gc); + void drawScalar(oofegGraphicContext &gc) override; #endif private: diff --git a/src/fm/pfem/octreelocalizertutil.h b/src/fm/pfem/octreelocalizertutil.h new file mode 100644 index 000000000..1c1485ec3 --- /dev/null +++ b/src/fm/pfem/octreelocalizertutil.h @@ -0,0 +1,319 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// **************************************************** +// *** UTILITY CLASSES FOR OCTREE SPATIAL LOCALIZER *** +// **************************************************** + +#ifndef octreelocalizertutil_h +#define octreelocalizertutil_h + +#include "spatiallocalizer.h" +#include "octreelocalizer.h" +#include "octreelocalizert.h" +#include "delaunaytriangle.h" +#include "dofmanager.h" +#include "node.h" +#include "element.h" +#include "mathfem.h" +#include "timer.h" + +#include +#include + +namespace oofem { +class Domain; +class Element; +class TimeStep; +class DofManager; +class IntArray; + +/** + * Functor for storing nodes in the octree + * + * @author David Krybus + */ +class InsertNode : public SL_Insertion_Functor< int > +{ +protected: + Domain *domain; + +public: + /// Constuctor + InsertNode(Domain *d) : + domain(d) + { } + /// Destructor + ~InsertNode() { } + + /** + * Evaluates the position of a node + * @param nodeNr Number of the node in the domain + * @param cell Octant cell to be tested + * @returns true if the node is contained in the cell, false otherwise + */ + bool evaluate(int &nodeNr, OctantRecT< int > *cell) override + { + FloatArray coords(3); + for ( int i = 1; i <= 3; i++ ) { + coords.at(i) = this->domain->giveNode(nodeNr)->giveCoordinate(i); + } + + if ( cell->containsPoint(coords) ) { + return true; + } else { + return false; + } + }; + + void registerInsertion(int &nodeNr, LocalInsertionData< int >LIdata) override { } + + std :: list< LocalInsertionData< int > > *giveInsertionList(int &nodeNr) override + { + return nullptr; + } +}; + +/** + * Functor for storing triangles in the octree according to theirs circumscribed circles + * + * @author David Krybus + */ +class InsertTriangleBasedOnCircumcircle : public SL_Insertion_Functor< DelaunayTriangle * > +{ +protected: + Domain *domain; + +public: + /// Constructor + InsertTriangleBasedOnCircumcircle(Domain *d) : + domain(d) + { } + /// Destructor + ~InsertTriangleBasedOnCircumcircle() { } + + /** + * Evaluates the position of a triangle + * @param DTptr Delaunay triangle + * @param cell Octant cell to be tested + * @returns true if the cirumscribed circle of the circle lies inside or contains a part of the cell, false otherwise + */ + bool evaluate(DelaunayTriangle * &DTptr, OctantRecT< DelaunayTriangle * > *cell) override + { + double radius = DTptr->giveCircumRadius(); + FloatArray centerCoords(3); + centerCoords.at(1) = DTptr->giveXCenterCoordinate(); + centerCoords.at(2) = DTptr->giveYCenterCoordinate(); + centerCoords.at(3) = 0.0; + + if ( cell->testBoundingSphere(centerCoords, radius) == SphereOutsideCell ) { + return false; + } else { + return true; + } + } + void registerInsertion(DelaunayTriangle * &TEptr, LocalInsertionData< DelaunayTriangle * >LIdata) override + { + ( TEptr->giveListOfCellsAndPosition() )->push_back(LIdata); + } + std :: list< LocalInsertionData< DelaunayTriangle * > > *giveInsertionList(DelaunayTriangle * &DTptr) override + { + return DTptr->giveListOfCellsAndPosition(); + } +}; + +/** + * Functor for closest node search + * + * @author David Krybus + */ +class ClosestNode : public SL_Evaluation_Functor< int > +{ +protected: + FloatArray startingPosition; + Domain *domain; + int CNindex; + double distanceToClosestNode; + bool initFlag; + + std :: list< int >closestNodeIndices; + +public: + /** + * Constructor + * @param pos Starting position of the search + * @param d Domain containing nodes + */ + ClosestNode(const FloatArray &pos, Domain *d) : + startingPosition(pos), + domain(d), + initFlag(false) + { } + /// Destructor + ~ClosestNode() { } + + /** + * Gives the starting position of the search + * @param position startingPosition + */ + void giveStartingPosition(FloatArray &position) override + { + position = startingPosition; + } + + /** + * Evaluates a node. The closest nodes are stored in a container, if their distance to starting position is the same. + * Is the distance smaller than previous one, the container is emptied and new node is added. + * @param nodeNr Number of the node in the domain list + * @returns true after evaluation is processed. + */ + bool evaluate(int &nodeNr) override + { + if ( initFlag ) { + double dist = distance(startingPosition, *this->domain->giveNode(nodeNr)->giveCoordinates()); + + if ( ( dist - distanceToClosestNode ) <= dist * 0.001 ) { + if ( ( dist - distanceToClosestNode ) >= -0.001 * dist ) { + closestNodeIndices.push_back(nodeNr); + } else { + closestNodeIndices.clear(); + closestNodeIndices.push_back(nodeNr); + distanceToClosestNode = dist; + } + } + } else { + closestNodeIndices.push_back(nodeNr); + distanceToClosestNode = distance(startingPosition, *this->domain->giveNode( * ( closestNodeIndices.begin() ) )->giveCoordinates()); + initFlag = true; + } + + return true; + } + + /** + * Gives the closest nodes + * @param answer List containing numbers of the closest nodes + */ + void giveResult(std :: list< int > &answer) override { + answer = closestNodeIndices; + } + + bool isBBXStage1Defined(BoundingBox &BBXStage1) override + { + return false; + } + + bool isBBXStage2Defined(BoundingBox &BBXStage2) override + { + if ( initFlag ) { + BBXStage2.setOrigin(startingPosition); + BBXStage2.setSize(distanceToClosestNode); + return true; + } else { + return false; + } + } +}; + + +/** + * Functor for finding triangles whose circumscribed circles contains given node + * + * @author David Krybus + */ +class ElementCircumCirclesContainingNode : public SL_Evaluation_Functor< DelaunayTriangle * > +{ +protected: + FloatArray startingPosition; + Domain *domain; + std :: list< DelaunayTriangle * >result; + +public: + /** + * Constructor + * @param pos Starting position of the search + * @param d Domain containing nodes the triangles are defined by + */ + ElementCircumCirclesContainingNode(FloatArray pos, Domain *d) : + startingPosition(std::move(pos)), + domain(d) + { } + ~ElementCircumCirclesContainingNode() { } + + /** + * Evaluates a triangle upon its circumscribed cricle. + * @param DTptr Delaunay triangle. nodeNr Number of the node in the domain list + * @returns true if the circumscribed circle of the Delaunay triangle contains the point, false otherwise + */ + bool evaluate(DelaunayTriangle * &DTptr) override + { + double radius = DTptr->giveCircumRadius(); + FloatArray centerCoords(3); + centerCoords.at(1) = DTptr->giveXCenterCoordinate(); + centerCoords.at(2) = DTptr->giveYCenterCoordinate(); + centerCoords.at(3) = 0.0; + + if ( distance(startingPosition, centerCoords) < radius ) { + result.push_back(DTptr); + return true; + } else { + return false; + } + } + + /** + * Gives the starting position of the search + * @param position startingPosition + */ + void giveStartingPosition(FloatArray &answer) override + { + answer = startingPosition; + } + + /** + * Gives the triangles containing the node + * @param answer List containing Delaunay triangles + */ + void giveResult(std :: list< DelaunayTriangle * > &answer) override + { + answer = result; + } + + // neither stage1, nor stage 2 are defined + bool isBBXStage1Defined(BoundingBox &BBXStage1) override { return false; } + bool isBBXStage2Defined(BoundingBox &BBXStage2) override { return false; } +}; + +} // end namespace oofem +#endif // octreelocalizertutil_h diff --git a/src/fm/pfem/pfem.C b/src/fm/pfem/pfem.C index 1dcb210bf..0ab65677a 100644 --- a/src/fm/pfem/pfem.C +++ b/src/fm/pfem/pfem.C @@ -54,6 +54,7 @@ #include "load.h" #include "pfemparticle.h" #include "octreelocalizert.h" //changed from "octreelocalizer.h" +#include "octreelocalizertutil.h" #include "spatiallocalizer.h" #include "classfactory.h" #include "mathfem.h" @@ -211,11 +212,9 @@ PFEM :: forceEquationNumbering(int id) -IRResultType -PFEM :: initializeFrom(InputRecord *ir) +void +PFEM :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - EngngModel :: initializeFrom(ir); int val = 0; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_lstype); @@ -253,8 +252,6 @@ PFEM :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, associatedMaterial, _IFT_PFEM_associatedMaterial); IR_GIVE_FIELD(ir, associatedCrossSection, _IFT_PFEM_associatedCrossSection); IR_GIVE_FIELD(ir, associatedPressureBC, _IFT_PFEM_pressureBC); - - return IRRT_OK; } @@ -294,7 +291,7 @@ TimeStep * PFEM :: giveSolutionStepWhenIcApply() { if ( !stepWhenIcApply ) { - stepWhenIcApply.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, 0.0, deltaT, 0) ); + stepWhenIcApply = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 0, 0.0, deltaT, 0); } return stepWhenIcApply.get(); @@ -349,7 +346,7 @@ PFEM :: giveNextStep() if ( !currentStep ) { // first step -> generate initial step - currentStep.reset( new TimeStep( * giveSolutionStepWhenIcApply() ) ); + currentStep = std::make_unique( * giveSolutionStepWhenIcApply() ); } else { istep = currentStep->giveNumber() + 1; counter = currentStep->giveSolutionStateCounter() + 1; @@ -377,7 +374,7 @@ PFEM :: giveNextStep() totalTime = previousStep->giveTargetTime() + ndt; - currentStep.reset( new TimeStep(istep, this, 1, totalTime, ndt, counter) ); + currentStep = std::make_unique(istep, this, 1, totalTime, ndt, counter); // time and dt variables are set eq to 0 for staics - has no meaning OOFEM_LOG_INFO( "SolutionStep %d : t = %e, dt = %e\n", istep, totalTime * this->giveVariableScale(VST_Time), ndt * this->giveVariableScale(VST_Time) ); @@ -706,69 +703,22 @@ PFEM :: updateDofUnknownsDictionaryVelocities(DofManager *inode, TimeStep *tStep // NOT ACTIVE -contextIOResultType +void PFEM :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = EngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = PressureField.saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = VelocityField.saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + EngngModel :: saveContext(stream, mode); + PressureField.saveContext(stream, mode); + VelocityField.saveContext(stream, mode); } // NOT ACTIVE -contextIOResultType -PFEM :: restoreContext(DataStream *stream, ContextMode mode, void *obj) -// -// restore state variable - displacement vector -// +void +PFEM :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - int closeFlag = 0; - int istep, iversion; - FILE *file = NULL; - - this->resolveCorrespondingStepNumber(istep, iversion, obj); - - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - - if ( ( iores = EngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = PressureField.restoreContext(* stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = VelocityField.restoreContext(* stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } - - return CIO_OK; + EngngModel :: restoreContext(stream, mode); + PressureField.restoreContext(stream, mode); + VelocityField.restoreContext(stream, mode); } @@ -941,9 +891,9 @@ PFEM :: deactivateTooCloseParticles() PFEMParticle *particle2 = dynamic_cast< PFEMParticle * >( element->giveNode(2) ); PFEMParticle *particle3 = dynamic_cast< PFEMParticle * >( element->giveNode(3) ); - double l12 = particle1->giveCoordinates()->distance( particle2->giveCoordinates() ); - double l23 = particle2->giveCoordinates()->distance( particle3->giveCoordinates() ); - double l31 = particle3->giveCoordinates()->distance( particle1->giveCoordinates() ); + double l12 = distance( *particle1->giveCoordinates(), *particle2->giveCoordinates() ); + double l23 = distance( *particle2->giveCoordinates(), *particle3->giveCoordinates() ); + double l31 = distance( *particle3->giveCoordinates(), *particle1->giveCoordinates() ); double maxLength = max( l12, max(l23, l31) ); double minLength = min( l12, min(l23, l31) ); diff --git a/src/fm/pfem/pfem.h b/src/fm/pfem/pfem.h index f7064151a..93eba9ecc 100644 --- a/src/fm/pfem/pfem.h +++ b/src/fm/pfem/pfem.h @@ -70,7 +70,7 @@ namespace oofem { class PFEMPressureRhsAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; /** @@ -84,8 +84,8 @@ class PFEMCorrectionRhsAssembler : public VectorAssembler public: PFEMCorrectionRhsAssembler(double deltaT) : VectorAssembler(), deltaT(deltaT) {} - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; - virtual void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; + void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const override; }; /** @@ -93,8 +93,8 @@ class PFEMCorrectionRhsAssembler : public VectorAssembler */ class PFEMLaplaceVelocityAssembler : public VectorAssembler { - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; - virtual void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; + void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const override; }; /** @@ -102,8 +102,8 @@ class PFEMLaplaceVelocityAssembler : public VectorAssembler */ class PFEMMassVelocityAssembler : public VectorAssembler { - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; - virtual void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; + void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const override; }; /** @@ -112,8 +112,8 @@ class PFEMMassVelocityAssembler : public VectorAssembler class PFEMPressureLaplacianAssembler : public MatrixAssembler { public: - virtual void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const; - virtual void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const; + void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const override; + void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const override; }; /** @@ -184,7 +184,7 @@ class PFEM : public EngngModel VelocityNumberingScheme prescribedVns; public: - PFEM(int i, EngngModel *_master = NULL) : + PFEM(int i, EngngModel *_master = nullptr) : EngngModel(i, _master) , avLhs() , pLhs() @@ -206,43 +206,43 @@ class PFEM : public EngngModel } ~PFEM() { } - void solveYourselfAt(TimeStep *); + void solveYourselfAt(TimeStep *) override; /** * Updates nodal values * (calls also this->updateDofUnknownsDictionary for updating dofs unknowns dictionaries * if model supports changes of static system). The element internal state update is also forced using * updateInternalState service.giv */ - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof); + double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) override; - contextIOResultType saveContext(DataStream &stream, ContextMode mode); - contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - TimeStep *giveNextStep(); - TimeStep *giveSolutionStepWhenIcApply(); - NumericalMethod *giveNumericalMethod(MetaStep *); + TimeStep *giveNextStep() override; + TimeStep *giveSolutionStepWhenIcApply() override; + NumericalMethod *giveNumericalMethod(MetaStep *) override; /** Removes all elements and call DelaunayTriangulator to build up new mesh with new recognized boundary. * Non-meshed particles are set free and move according Newton laws of motion */ - virtual void preInitializeNextStep(); + void preInitializeNextStep() override; //equation numbering using PressureNumberingScheme - virtual int forceEquationNumbering(int id); + int forceEquationNumbering(int id) override; - virtual int requiresUnknownsDictionaryUpdate() { return true; } + int requiresUnknownsDictionaryUpdate() override { return true; } /// Initialization from given input record - IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; // consistency check - virtual int checkConsistency(); // returns nonzero if o.k. + int checkConsistency() override; // returns nonzero if o.k. // identification - const char *giveClassName() const { return "PFEM"; } - fMode giveFormulation() { return AL; } + const char *giveClassName() const override { return "PFEM"; } + fMode giveFormulation() override { return AL; } // fMode giveFormulation() { return TL; } /** DOF printing routine. Called by DofManagers to print Dof specific part. @@ -252,15 +252,15 @@ class PFEM : public EngngModel * @param iDof dof to be processed * @param atTime solution step */ - virtual void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *atTime); + void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *atTime) override; - virtual int giveNumberOfDomainEquations(int, const UnknownNumberingScheme &num); + int giveNumberOfDomainEquations(int, const UnknownNumberingScheme &num) override; - virtual int giveNewEquationNumber(int domain, DofIDItem); - virtual int giveNewPrescribedEquationNumber(int domain, DofIDItem); + int giveNewEquationNumber(int domain, DofIDItem) override; + int giveNewPrescribedEquationNumber(int domain, DofIDItem) override; - virtual int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *stepN); // { return ( int ) mode; } - virtual void updateDofUnknownsDictionary(DofManager *inode, TimeStep *tStep); + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *stepN) override; // { return ( int ) mode; } + void updateDofUnknownsDictionary(DofManager *inode, TimeStep *tStep) override; /// Writes pressures into the dof unknown dictionaries void updateDofUnknownsDictionaryPressure(DofManager *inode, TimeStep *tStep); diff --git a/src/fm/pfem/pfemelement.C b/src/fm/pfem/pfemelement.C index b61de91bf..fe3e526b7 100644 --- a/src/fm/pfem/pfemelement.C +++ b/src/fm/pfem/pfemelement.C @@ -57,24 +57,18 @@ namespace oofem { PFEMElement :: PFEMElement(int n, Domain *aDomain) : FMElement(n, aDomain) - // Constructor. Creates an element with number n, belonging to aDomain. { } PFEMElement :: ~PFEMElement() -// Destructor. { } -IRResultType -PFEMElement :: initializeFrom(InputRecord *ir) +void +PFEMElement :: initializeFrom(InputRecord &ir) { - //const char *__proc = "initializeFrom"; // Required by IR_GIVE_FIELD macro - //IRResultType result; // Required by IR_GIVE_FIELD macro - FMElement :: initializeFrom(ir); this->computeGaussPoints(); - return IRRT_OK; } @@ -216,7 +210,7 @@ PFEMElement :: updateInternalState(TimeStep *stepN) } void -PFEMElement :: printOutputAt(FILE *file, TimeStep *tStep) +PFEMElement :: printOutputAt(FILE *file, TimeStep *tStep) const // Performs end-of-step operations. { #ifdef __PARALLEL_MODE diff --git a/src/fm/pfem/pfemelement.h b/src/fm/pfem/pfemelement.h index 1b38a06e4..9c9348946 100644 --- a/src/fm/pfem/pfemelement.h +++ b/src/fm/pfem/pfemelement.h @@ -69,14 +69,14 @@ class PFEMElement : public FMElement /// Constructor PFEMElement(int, Domain *); /// Destructor - ~PFEMElement(); + virtual ~PFEMElement(); ///Initializes receiver acording to object description stored in input record. - IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; // characteristic matrix - void giveCharacteristicMatrix(FloatMatrix & answer, CharType, TimeStep *); - void giveCharacteristicVector(FloatArray & answer, CharType, ValueModeType, TimeStep *); + void giveCharacteristicMatrix(FloatMatrix & answer, CharType, TimeStep *) override; + void giveCharacteristicVector(FloatArray & answer, CharType, ValueModeType, TimeStep *) override; /** Calculates diagonal mass matrix as vector*/ virtual void computeDiagonalMassMtrx(FloatArray &answer, TimeStep *) = 0; @@ -85,20 +85,19 @@ class PFEMElement : public FMElement /// Calculates critical time step virtual double computeCriticalTimeStep(TimeStep *tStep) = 0; - virtual void updateInternalState(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual int checkConsistency(); + void updateInternalState(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) override; + int checkConsistency() override; /// Returns the interpolation for velocity virtual FEInterpolation *giveVelocityInterpolation() = 0; /// Returns the interpolation for the pressure virtual FEInterpolation *givePressureInterpolation() = 0; - void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); - + computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; // definition - virtual const char *giveClassName() const { return "PFEMElement"; } + const char *giveClassName() const override { return "PFEMElement"; } /// Returns mask of velocity Dofs virtual const IntArray &giveVelocityDofMask() const = 0; diff --git a/src/fm/pfem/pfemelement2d.C b/src/fm/pfem/pfemelement2d.C index 77a26e8fb..99e99bdeb 100644 --- a/src/fm/pfem/pfemelement2d.C +++ b/src/fm/pfem/pfemelement2d.C @@ -67,10 +67,10 @@ PFEMElement2d :: ~PFEMElement2d() { } -IRResultType -PFEMElement2d :: initializeFrom(InputRecord *ir) +void +PFEMElement2d :: initializeFrom(InputRecord &ir) { - return this->PFEMElement :: initializeFrom(ir); + PFEMElement :: initializeFrom(ir); } int diff --git a/src/fm/pfem/pfemelement2d.h b/src/fm/pfem/pfemelement2d.h index 89ffd9050..592b0c89f 100644 --- a/src/fm/pfem/pfemelement2d.h +++ b/src/fm/pfem/pfemelement2d.h @@ -73,20 +73,20 @@ class PFEMElement2d : public PFEMElement /// Constructor PFEMElement2d(int n, Domain *d); /// Destructor - ~PFEMElement2d(); + virtual ~PFEMElement2d(); - virtual double computeCriticalTimeStep(TimeStep *tStep) = 0; + double computeCriticalTimeStep(TimeStep *tStep) override = 0; - virtual const char *giveClassName() const { return "PFEMElement2d"; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_1; } + const char *giveClassName() const override { return "PFEMElement2d"; } + Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_1; } - virtual void giveElementDofIDMask(IntArray &answer) const = 0; - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const = 0; - virtual int computeNumberOfDofs() = 0; - IRResultType initializeFrom(InputRecord *ir); - virtual int checkConsistency(); + void giveElementDofIDMask(IntArray &answer) const override = 0; + void giveDofManDofIDMask(int inode, IntArray &answer) const override = 0; + int computeNumberOfDofs() override = 0; + void initializeFrom(InputRecord &ir) override; + int checkConsistency() override; - virtual Interface *giveInterface(InterfaceType) = 0; + Interface *giveInterface(InterfaceType) override = 0; virtual Element *giveElement() { return this; } @@ -100,21 +100,21 @@ class PFEMElement2d : public PFEMElement //virtual void drawDeformedGeometry(oofegGraphicContext&, UnknownType) {} #endif - virtual FEInterpolation *giveVelocityInterpolation() = 0; - virtual FEInterpolation *givePressureInterpolation() = 0; + FEInterpolation *giveVelocityInterpolation() override = 0; + FEInterpolation *givePressureInterpolation() override = 0; protected: - virtual void computeGaussPoints() = 0; - virtual void computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) = 0; - virtual void computeDeviatoricStressDivergence(FloatArray &answer, TimeStep *tStep) = 0; + void computeGaussPoints() override = 0; + void computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override = 0; + void computeDeviatoricStressDivergence(FloatArray &answer, TimeStep *tStep) override = 0; - virtual void computeBMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); //K - virtual void computePressureLaplacianMatrix(FloatMatrix &answer, TimeStep *tStep); //L - virtual void computeDivergenceMatrix(FloatMatrix &answerx, TimeStep *tStep); //D - virtual void computeGradientMatrix(FloatMatrix &answer, TimeStep *tStep); //G + void computeBMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) override; //K + void computePressureLaplacianMatrix(FloatMatrix &answer, TimeStep *tStep) override; //L + void computeDivergenceMatrix(FloatMatrix &answerx, TimeStep *tStep) override; //D + void computeGradientMatrix(FloatMatrix &answer, TimeStep *tStep) override; //G - void computePrescribedRhsVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode); + void computePrescribedRhsVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode) override; /// Calculates the shape function matrix on an edge void computeEdgeNMatrixAt(FloatMatrix &answer, int iedge, GaussPoint *gp); diff --git a/src/fm/pfem/pfemparticle.C b/src/fm/pfem/pfemparticle.C index b35b81fb4..bf2423eab 100644 --- a/src/fm/pfem/pfemparticle.C +++ b/src/fm/pfem/pfemparticle.C @@ -53,10 +53,10 @@ REGISTER_DofManager(PFEMParticle); /** * Gets from the source line from the data file all the data of the receiver. */ -IRResultType -PFEMParticle :: initializeFrom(InputRecord *ir) +void +PFEMParticle :: initializeFrom(InputRecord &ir) { - return Node :: initializeFrom(ir); + Node :: initializeFrom(ir); } /** diff --git a/src/fm/pfem/pfemparticle.h b/src/fm/pfem/pfemparticle.h index 6ba7c98e6..31a7b0ffe 100644 --- a/src/fm/pfem/pfemparticle.h +++ b/src/fm/pfem/pfemparticle.h @@ -73,12 +73,12 @@ class PFEMParticle : public Node /** * Destructor. */ - ~PFEMParticle(void) { } + virtual ~PFEMParticle(void) { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int checkConsistency(); + void initializeFrom(InputRecord &ir) override; + int checkConsistency() override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; /// Returns the free-propery flag virtual bool isFree() { return freeFlag; } @@ -95,13 +95,13 @@ class PFEMParticle : public Node /// Sets the activeFlag to false virtual void deactivate() { activeFlag = false; } - virtual void printOutputAt(FILE *stream, TimeStep *stepN); + void printOutputAt(FILE *stream, TimeStep *stepN) override; - virtual const char *giveClassName() const { return "PFEMParticle"; } - virtual const char *giveInputRecordName() const { return _IFT_PFEMParticle_Name; } + const char *giveClassName() const override { return "PFEMParticle"; } + const char *giveInputRecordName() const override { return _IFT_PFEMParticle_Name; } #ifdef __OOFEG - virtual void drawScalar(oofegGraphicContext &gc); + void drawScalar(oofegGraphicContext &gc) override; #endif }; } // end namespace oofem diff --git a/src/fm/pfem/tr1_2d_pfem.C b/src/fm/pfem/tr1_2d_pfem.C index 36136e59b..142378607 100644 --- a/src/fm/pfem/tr1_2d_pfem.C +++ b/src/fm/pfem/tr1_2d_pfem.C @@ -116,13 +116,12 @@ TR1_2D_PFEM :: giveElementDofIDMask(IntArray &answer) const } -IRResultType -TR1_2D_PFEM :: initializeFrom(InputRecord *ir) +void +TR1_2D_PFEM :: initializeFrom(InputRecord &ir) { - IRResultType ret = this->PFEMElement :: initializeFrom(ir); + PFEMElement :: initializeFrom(ir); this->computeGaussPoints(); - return ret; } void @@ -131,7 +130,7 @@ TR1_2D_PFEM :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); integrationRulesArray [ 0 ]->setUpIntegrationPoints(_Triangle, 3, _2dFlow); } } @@ -405,28 +404,15 @@ TR1_2D_PFEM :: computeCriticalTimeStep(TimeStep *tStep) } -contextIOResultType TR1_2D_PFEM :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void TR1_2D_PFEM :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = PFEMElement2d :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + PFEMElement2d :: saveContext(stream, mode); } -contextIOResultType TR1_2D_PFEM :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void TR1_2D_PFEM :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = PFEMElement2d :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - - return CIO_OK; + PFEMElement2d :: restoreContext(stream, mode); } diff --git a/src/fm/pfem/tr1_2d_pfem.h b/src/fm/pfem/tr1_2d_pfem.h index 60b0e3f75..3b77755fb 100644 --- a/src/fm/pfem/tr1_2d_pfem.h +++ b/src/fm/pfem/tr1_2d_pfem.h @@ -97,67 +97,67 @@ class TR1_2D_PFEM : public PFEMElement2d */ TR1_2D_PFEM(int n, Domain *aDomain, int particle1, int particle2, int particle3, int mat, int cs); /// Destructor - ~TR1_2D_PFEM(); + virtual ~TR1_2D_PFEM(); - virtual void computeDiagonalMassMtrx(FloatArray &answer, TimeStep *tStep); - virtual void computeDiagonalMassMtrx(FloatMatrix &answer, TimeStep *tStep); + void computeDiagonalMassMtrx(FloatArray &answer, TimeStep *tStep) override; + void computeDiagonalMassMtrx(FloatMatrix &answer, TimeStep *tStep) override; - virtual double computeCriticalTimeStep(TimeStep *tStep); + double computeCriticalTimeStep(TimeStep *tStep) override; - virtual const char *giveClassName() const { return "TR1_2D_PFEM"; } - virtual const char *giveInputRecordName() const { return _IFT_TR1_2D_PFEM_Name; } + const char *giveClassName() const override { return "TR1_2D_PFEM"; } + const char *giveInputRecordName() const override { return _IFT_TR1_2D_PFEM_Name; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_1; } + Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_1; } - virtual void giveElementDofIDMask(IntArray &answer) const; + void giveElementDofIDMask(IntArray &answer) const override; - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual int computeNumberOfDofs(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int checkConsistency(); + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + int computeNumberOfDofs() override; + void initializeFrom(InputRecord &ir) override; + int checkConsistency() override; - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual Element *giveElement() { return this; } + Element *giveElement() override { return this; } #ifdef __OOFEG - virtual int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *atTime); + int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, + int node, TimeStep *atTime) override; // Graphics output - //virtual void drawYourself(oofegGraphicContext&); - virtual void drawRawGeometry(oofegGraphicContext &); - virtual void drawScalar(oofegGraphicContext &context); - //virtual void drawDeformedGeometry(oofegGraphicContext&, UnknownType) {} + //void drawYourself(oofegGraphicContext&) override; + void drawRawGeometry(oofegGraphicContext &) override; + void drawScalar(oofegGraphicContext &context) override; + //void drawDeformedGeometry(oofegGraphicContext&, UnknownType) override {} #endif - virtual FEInterpolation *giveVelocityInterpolation() { return & velocityInterpolation; } - virtual FEInterpolation *givePressureInterpolation() { return & pressureInterpolation; } + FEInterpolation *giveVelocityInterpolation() override { return & velocityInterpolation; } + FEInterpolation *givePressureInterpolation() override { return & pressureInterpolation; } - virtual FEInterpolation *giveInterpolation() const { return & velocityInterpolation; } - virtual FEInterpolation *giveInterpolation(DofIDItem id) const { return id == P_f ? & pressureInterpolation : & velocityInterpolation; } + FEInterpolation *giveInterpolation() const override { return & velocityInterpolation; } + FEInterpolation *giveInterpolation(DofIDItem id) const override { return id == P_f ? & pressureInterpolation : & velocityInterpolation; } - virtual const IntArray &giveVelocityDofMask() const + const IntArray &giveVelocityDofMask() const override { return this->velocityDofMask; } - virtual const IntArray &givePressureDofMask() const + const IntArray &givePressureDofMask() const override { return this->pressureDofMask; } protected: - virtual void computeGaussPoints(); - virtual void computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeGaussPoints() override; + void computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; - virtual void computeDeviatoricStressDivergence(FloatArray &answer, TimeStep *tStep); + void computeDeviatoricStressDivergence(FloatArray &answer, TimeStep *tStep) override; - virtual void computeBodyLoadVectorAt(FloatArray &answer, BodyLoad *load, TimeStep *tStep, ValueModeType mode); - virtual void computeEdgeBCSubVectorAt(FloatArray &answer, Load *load, int iEdge, TimeStep *tStep); + void computeBodyLoadVectorAt(FloatArray &answer, BodyLoad *load, TimeStep *tStep, ValueModeType mode) override; + void computeEdgeBCSubVectorAt(FloatArray &answer, Load *load, int iEdge, TimeStep *tStep) override; }; } // end namespace oofem #endif // tr1_2d_pfem_h diff --git a/src/fm/quad10_2d_supg.C b/src/fm/quad10_2d_supg.C index 2d7a909b2..99ce4a353 100644 --- a/src/fm/quad10_2d_supg.C +++ b/src/fm/quad10_2d_supg.C @@ -39,7 +39,7 @@ #include "material.h" #include "gausspoint.h" #include "gaussintegrationrule.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fluidcrosssection.h" #include "floatmatrix.h" #include "floatarray.h" @@ -70,9 +70,6 @@ Quad10_2D_SUPG :: Quad10_2D_SUPG(int n, Domain *aDomain) : numberOfDofMans = 4; } -Quad10_2D_SUPG :: ~Quad10_2D_SUPG() -{ } - FEInterpolation * Quad10_2D_SUPG :: giveInterpolation() const { @@ -117,12 +114,12 @@ Quad10_2D_SUPG :: giveInternalDofManDofIDMask(int i, IntArray &answer) const } -IRResultType -Quad10_2D_SUPG :: initializeFrom(InputRecord *ir) +void +Quad10_2D_SUPG :: initializeFrom(InputRecord &ir) { this->pressureNode.initializeFrom(ir); - return SUPGElement2 :: initializeFrom(ir); + SUPGElement2 :: initializeFrom(ir); } @@ -142,26 +139,40 @@ Quad10_2D_SUPG :: computeGaussPoints() integrationRulesArray.resize(3); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 4, this); //seven point Gauss integration - integrationRulesArray [ 1 ].reset( new GaussIntegrationRule(2, this, 1, 3) ); + integrationRulesArray [ 1 ] = std::make_unique(2, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 1 ], 4, this); - integrationRulesArray [ 2 ].reset( new GaussIntegrationRule(3, this, 1, 3) ); + integrationRulesArray [ 2 ] = std::make_unique(3, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 3 ], 4, this); } } +void +Quad10_2D_SUPG :: computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStress2D(eps, gp, tStep); +} + + +void +Quad10_2D_SUPG :: computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeTangent2D(mode, gp, tStep); +} + + void Quad10_2D_SUPG :: computeNuMatrix(FloatMatrix &answer, GaussPoint *gp) { FloatArray n; this->velocityInterpolation.evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.beNMatrixOf(n, 2); - } +} void @@ -558,37 +569,18 @@ Quad10_2D_SUPG :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateT } -contextIOResultType -Quad10_2D_SUPG :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full element context (saves state variables, that completely describe -// current state) -// +void +Quad10_2D_SUPG :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = SUPGElement :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + SUPGElement :: saveContext(stream, mode); } -contextIOResultType Quad10_2D_SUPG :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full element context (saves state variables, that completely describe -// current state) -// +void +Quad10_2D_SUPG :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = SUPGElement :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + SUPGElement :: restoreContext(stream, mode); } diff --git a/src/fm/quad10_2d_supg.h b/src/fm/quad10_2d_supg.h index b1871cce3..32612633e 100644 --- a/src/fm/quad10_2d_supg.h +++ b/src/fm/quad10_2d_supg.h @@ -63,37 +63,36 @@ class Quad10_2D_SUPG : public SUPGElement2, public LevelSetPCSElementInterface, public: Quad10_2D_SUPG(int n, Domain * d); - virtual ~Quad10_2D_SUPG(); - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; // definition - virtual const char *giveClassName() const { return "Quad1_2D_SUPG"; } - virtual const char *giveInputRecordName() const { return _IFT_Quad10_2D_SUPG_Name; } - virtual MaterialMode giveMaterialMode() { return _2dFlow; } + const char *giveClassName() const override { return "Quad1_2D_SUPG"; } + const char *giveInputRecordName() const override { return _IFT_Quad10_2D_SUPG_Name; } + MaterialMode giveMaterialMode() override { return _2dFlow; } - virtual void giveInternalDofManDofIDMask(int i, IntArray &answer) const; - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual int computeNumberOfDofs(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void updateYourself(TimeStep *tStep); - virtual int checkConsistency(); + void giveInternalDofManDofIDMask(int i, IntArray &answer) const override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + int computeNumberOfDofs() override; + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void updateYourself(TimeStep *tStep) override; + int checkConsistency() override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual double LS_PCS_computeF(LevelSetPCS *ls, TimeStep *tStep); - virtual void LS_PCS_computedN(FloatMatrix &answer); - virtual double LS_PCS_computeVolume() { return 0.0; } - virtual double LS_PCS_computeS(LevelSetPCS *ls, TimeStep *tStep); - virtual void LS_PCS_computeVOFFractions(FloatArray &answer, FloatArray &fi); + double LS_PCS_computeF(LevelSetPCS *ls, TimeStep *tStep) override; + void LS_PCS_computedN(FloatMatrix &answer) override; + double LS_PCS_computeVolume() override { return 0.0; } + double LS_PCS_computeS(LevelSetPCS *ls, TimeStep *tStep) override; + void LS_PCS_computeVOFFractions(FloatArray &answer, FloatArray &fi) override; - virtual Interface *giveInterface(InterfaceType t); + Interface *giveInterface(InterfaceType t) override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; /// @name Helping functions for computing VOFFractions. //@{ @@ -112,48 +111,50 @@ class Quad10_2D_SUPG : public SUPGElement2, public LevelSetPCSElementInterface, void computeQuadraticFunct(FloatArray &answer, FloatArray line); //@} - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; #ifdef __OOFEG int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *tStep); + int node, TimeStep *tStep) override; // Graphics output - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - //virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) {} + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override {} #endif - virtual double computeCriticalTimeStep(TimeStep *tStep); + double computeCriticalTimeStep(TimeStep *tStep) override; // three terms for computing their norms due to computing t_supg - virtual void computeAdvectionTerm(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionDeltaTerm(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassDeltaTerm(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLSICTerm(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionEpsilonTerm(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassEpsilonTerm(FloatMatrix &answer, TimeStep *tStep); + void computeAdvectionTerm(FloatMatrix &answer, TimeStep *tStep); + void computeAdvectionDeltaTerm(FloatMatrix &answer, TimeStep *tStep); + void computeMassDeltaTerm(FloatMatrix &answer, TimeStep *tStep); + void computeLSICTerm(FloatMatrix &answer, TimeStep *tStep); + void computeAdvectionEpsilonTerm(FloatMatrix &answer, TimeStep *tStep); + void computeMassEpsilonTerm(FloatMatrix &answer, TimeStep *tStep); - //virtual int giveNumberOfDofs() { return 1; } - virtual int giveNumberOfInternalDofManagers() const { return 1; } - virtual DofManager *giveInternalDofManager(int i) const; + //int giveNumberOfDofs() override { return 1; } + int giveNumberOfInternalDofManagers() const override { return 1; } + DofManager *giveInternalDofManager(int i) const override; protected: - virtual void giveLocalVelocityDofMap(IntArray &map); - virtual void giveLocalPressureDofMap(IntArray &map); - - virtual void computeGaussPoints(); - virtual void computeNuMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeUDotGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - virtual void computeBMatrix(FloatMatrix &anwer, GaussPoint *gp); - virtual void computeDivUMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeNpMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeGradPMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeDivTauMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - virtual void computeGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - virtual int giveNumberOfSpatialDimensions(); - virtual double computeVolumeAround(GaussPoint *gp); - - virtual void updateStabilizationCoeffs(TimeStep *tStep); + void giveLocalVelocityDofMap(IntArray &map) override; + void giveLocalPressureDofMap(IntArray &map) override; + + void computeGaussPoints() override; + void computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) override; + void computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void computeNuMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeUDotGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) override; + void computeBMatrix(FloatMatrix &anwer, GaussPoint *gp) override; + void computeDivUMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeNpMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeGradPMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeDivTauMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) override; + void computeGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) override; + int giveNumberOfSpatialDimensions() override; + double computeVolumeAround(GaussPoint *gp) override; + + void updateStabilizationCoeffs(TimeStep *tStep) override; }; } // end namespace oofem #endif // quad10_supg_h diff --git a/src/fm/stokesflow.C b/src/fm/stokesflow.C index b2a8310ea..2b9b222c3 100644 --- a/src/fm/stokesflow.C +++ b/src/fm/stokesflow.C @@ -55,13 +55,13 @@ StokesFlow :: StokesFlow(int i, EngngModel *_master) : FluidModel(i, _master) this->ndomains = 1; } -StokesFlow :: ~StokesFlow() -{ -} -IRResultType StokesFlow :: initializeFrom(InputRecord *ir) +StokesFlow :: ~StokesFlow() { } + + +void StokesFlow :: initializeFrom(InputRecord &ir) { - IRResultType result; + FluidModel :: initializeFrom(ir); int val; val = ( int ) SMT_PetscMtrx; @@ -75,15 +75,13 @@ IRResultType StokesFlow :: initializeFrom(InputRecord *ir) this->deltaT = 1.0; IR_GIVE_OPTIONAL_FIELD(ir, deltaT, _IFT_StokesFlow_deltat); - this->velocityPressureField.reset( new DofDistributedPrimaryField(this, 1, FT_VelocityPressure, 1) ); - this->stiffnessMatrix.reset( NULL ); - this->meshqualityee.reset( NULL ); + this->velocityPressureField = std::make_unique(this, 1, FT_VelocityPressure, 1); + this->stiffnessMatrix = nullptr; + this->meshqualityee = nullptr; this->ts = TS_OK; this->maxdef = 25; ///@todo Deal with this parameter (set to some reasonable value by default now) - - return FluidModel :: initializeFrom(ir); } @@ -95,7 +93,7 @@ void StokesFlow :: solveYourselfAt(TimeStep *tStep) if ( d->giveNumberOfElements() == 0 && d->giveTopology() ) { d->giveTopology()->replaceFEMesh(); - this->meshqualityee.reset( new MeshQualityErrorEstimator( 1, d ) ); + this->meshqualityee = std::make_unique( 1, d ); } if ( d->giveTopology() && this->meshqualityee ) { @@ -115,15 +113,12 @@ void StokesFlow :: solveYourselfAt(TimeStep *tStep) int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); - // Move solution space to current time step velocityPressureField->advanceSolution(tStep); - - // Point pointer SolutionVector to current solution in velocityPressureField velocityPressureField->initialize(VM_Total, tStep, solutionVector, EModelDefaultEquationNumbering() ); // Create "stiffness matrix" if ( !this->stiffnessMatrix ) { - this->stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + this->stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( !this->stiffnessMatrix ) { OOFEM_ERROR("Couldn't create requested sparse matrix of type %d", sparseMtrxType); } @@ -150,26 +145,26 @@ void StokesFlow :: solveYourselfAt(TimeStep *tStep) #if 1 double loadLevel; int currentIterations; - this->updateComponent( tStep, InternalRhs, d ); + this->updateInternalRHS( this->internalForces, tStep, d, &this->eNorm ); NM_Status status = this->nMethod->solve(*this->stiffnessMatrix, externalForces, NULL, solutionVector, incrementOfSolution, this->internalForces, - this->eNorm, loadLevel, // Only relevant for incrementalBCLoadVector? SparseNonLinearSystemNM :: rlm_total, currentIterations, tStep); #else - this->updateComponent( tStep, InternalRhs, d ); - this->updateComponent( tStep, NonLinearLhs, d ); + this->updateInternalRHS( this->internalForces, tStep, d, nullptr ); + this->updateMatrix( this->stiffnessMatrix, tStep, d ); this->internalForces.negated(); this->internalForces.add(externalForces); NM_Status status = this->nMethod->giveLinearSolver()->solve(this->stiffnessMatrix.get(), & ( this->internalForces ), & solutionVector); - this->updateComponent( tStep, NonLinearLhs, d ); + this->updateSolution(solutionVector); + this->updateInternalRHS( this->internalForces, tStep, d, nullptr ); #endif if ( !( status & NM_Success ) ) { @@ -202,17 +197,45 @@ void StokesFlow :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain * } } +void StokesFlow :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) +{ + this->velocityPressureField->update(VM_Total, tStep, solutionVector, EModelDefaultEquationNumbering()); + // update element stabilization + for ( auto &elem : d->giveElements() ) { + static_cast< FMElement * >( elem.get() )->updateStabilizationCoeffs(tStep); + } +} + + +void StokesFlow :: updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) +{ + answer.zero(); + this->assembleVector(answer, tStep, InternalForceAssembler(), VM_Total, + EModelDefaultEquationNumbering(), d, eNorm); + this->updateSharedDofManagers(answer, EModelDefaultEquationNumbering(), InternalForcesExchangeTag); +} + + +void StokesFlow :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) +{ + mat.zero(); + this->assemble(mat, tStep, TangentAssembler(TangentStiffness), + EModelDefaultEquationNumbering(), d); +} + + void StokesFlow :: updateYourself(TimeStep *tStep) { this->updateInternalState(tStep); FluidModel :: updateYourself(tStep); } + int StokesFlow :: forceEquationNumbering(int id) { int neq = FluidModel :: forceEquationNumbering(id); this->equationNumberingCompleted = false; - this->stiffnessMatrix.reset( NULL ); + this->stiffnessMatrix = nullptr; return neq; } @@ -271,7 +294,7 @@ void StokesFlow :: doStepOutput(TimeStep *tStep) NumericalMethod *StokesFlow :: giveNumericalMethod(MetaStep *mStep) { if ( !this->nMethod ) { - this->nMethod.reset( new NRSolver(this->giveDomain(1), this) ); + this->nMethod = std::make_unique(this->giveDomain(1), this); } return this->nMethod.get(); } @@ -280,11 +303,11 @@ TimeStep *StokesFlow :: giveNextStep() { if ( !currentStep ) { // first step -> generate initial step - //currentStep.reset( new TimeStep(*giveSolutionStepWhenIcApply()) ); - currentStep.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., this->deltaT, 0) ); + //currentStep = std::make_unique(*giveSolutionStepWhenIcApply()); + currentStep = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., this->deltaT, 0); } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(*previousStep, this->deltaT) ); + currentStep = std::make_unique(*previousStep, this->deltaT); return currentStep.get(); } diff --git a/src/fm/stokesflow.h b/src/fm/stokesflow.h index 754c96c70..6e0cd3c3a 100644 --- a/src/fm/stokesflow.h +++ b/src/fm/stokesflow.h @@ -64,7 +64,7 @@ class StokesFlow : public FluidModel { protected: /// Time increment read from input record. - double deltaT; + double deltaT = 1.; /// Primary unknowns. std :: unique_ptr< PrimaryField > velocityPressureField; /// Sparse matrix type. @@ -72,14 +72,14 @@ class StokesFlow : public FluidModel /// Numerical method. std :: unique_ptr< SparseNonLinearSystemNM > nMethod; /// Linear solver type. - LinSystSolverType solverType; + LinSystSolverType solverType = ST_Direct; /// Element norm for nonlinear analysis (squared) FloatArray eNorm; /// Used for determining if a new mesh must be created. std :: unique_ptr< MeshQualityErrorEstimator > meshqualityee; /// Maximum deformation allowed - double maxdef; + double maxdef = 1.; std :: unique_ptr< SparseMtrx > stiffnessMatrix; FloatArray solutionVector; @@ -89,35 +89,39 @@ class StokesFlow : public FluidModel TopologyState ts; public: - StokesFlow(int i, EngngModel * _master = NULL); - virtual ~StokesFlow(); + StokesFlow(int i, EngngModel * _master = nullptr); + ~StokesFlow(); - virtual void solveYourselfAt(TimeStep *tStep); + void solveYourselfAt(TimeStep *tStep) override; /** * Updates everything for the problem. * Updates the internal state for the elements. * Also calls updateNodalPositions. */ - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *domain, Dof *dof); + double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *domain, Dof *dof) override; + bool newDofHandling() override { return true; } - virtual double giveReynoldsNumber(); + double giveReynoldsNumber() override; - virtual int forceEquationNumbering(int id); + int forceEquationNumbering(int id) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual int checkConsistency(); - virtual void doStepOutput(TimeStep *tStep); + int checkConsistency() override; + void doStepOutput(TimeStep *tStep) override; void updateInternalState(TimeStep *tStep); - virtual void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); - virtual TimeStep *giveNextStep(); - - virtual const char *giveClassName() const { return "StokesFlow"; } - virtual const char *giveInputRecordName() const { return _IFT_StokesFlow_Name; } + void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) override; + void updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) override; + void updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) override; + void updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; + TimeStep *giveNextStep() override; + + const char *giveClassName() const override { return "StokesFlow"; } + const char *giveInputRecordName() const { return _IFT_StokesFlow_Name; } }; } // end namespace oofem diff --git a/src/fm/stokesflowvelocityhomogenization.C b/src/fm/stokesflowvelocityhomogenization.C index b620e1d0c..ffe50e58e 100644 --- a/src/fm/stokesflowvelocityhomogenization.C +++ b/src/fm/stokesflowvelocityhomogenization.C @@ -48,21 +48,16 @@ StokesFlowVelocityHomogenization :: StokesFlowVelocityHomogenization(int i, Engn { } -StokesFlowVelocityHomogenization :: ~StokesFlowVelocityHomogenization() -{ } - double StokesFlowVelocityHomogenization :: giveAreaOfRVE() { - FloatArray min, max; - - min = * this->giveDomain(1)->giveDofManager(1)->giveCoordinates(); - max = * this->giveDomain(1)->giveDofManager(1)->giveCoordinates(); + auto min = this->giveDomain(1)->giveDofManager(1)->giveCoordinates(); + auto max = this->giveDomain(1)->giveDofManager(1)->giveCoordinates(); for ( auto &node : this->giveDomain(1)->giveDofManagers() ) { - min.beMinOf( min, * node->giveCoordinates() ); - max.beMaxOf( max, * node->giveCoordinates() ); + min.beMinOf( min, node->giveCoordinates() ); + max.beMaxOf( max, node->giveCoordinates() ); } max.subtract(min); diff --git a/src/fm/stokesflowvelocityhomogenization.h b/src/fm/stokesflowvelocityhomogenization.h index ac6ec4bae..074135e51 100644 --- a/src/fm/stokesflowvelocityhomogenization.h +++ b/src/fm/stokesflowvelocityhomogenization.h @@ -47,22 +47,18 @@ namespace oofem { /** * Class for using the stokes flow class as an rve/constitutive model. - * * @author Carl Sandström - * */ class StokesFlowVelocityHomogenization : public StokesFlow { public: - StokesFlowVelocityHomogenization(int i, EngngModel * _master = NULL); - virtual ~StokesFlowVelocityHomogenization(); + StokesFlowVelocityHomogenization(int i, EngngModel * _master = nullptr); /** Compute area of domain (includes holes)*/ double giveAreaOfRVE(); - virtual const char *giveClassName() const { return "StokesFlowVelocityHomogenization"; } - virtual const char *giveInputRecordName() const { return _IFT_StokesFlowVelocityHomogenization_Name; } - + const char *giveClassName() const override { return "StokesFlowVelocityHomogenization"; } + const char *giveInputRecordName() const { return _IFT_StokesFlowVelocityHomogenization_Name; } void computeTangent(FloatMatrix &answer, TimeStep *tStep); /** Computes the mean velocity and pressure gradient */ diff --git a/src/fm/supg.C b/src/fm/supg.C index 30ceeb6ee..565807b86 100644 --- a/src/fm/supg.C +++ b/src/fm/supg.C @@ -209,23 +209,14 @@ void SUPGTangentAssembler :: matrixFromElement(FloatMatrix &answer, Element &el, SUPG :: SUPG(int i, EngngModel * _master) : FluidModel(i, _master), accelerationVector() { - initFlag = 1; ndomains = 1; - consistentMassFlag = 0; - equationScalingFlag = false; - lscale = uscale = dscale = 1.0; -} - - -SUPG :: ~SUPG() -{ } NumericalMethod *SUPG :: giveNumericalMethod(MetaStep *mStep) { if ( !this->nMethod ) { - this->nMethod.reset( classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this) ); + this->nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); if ( !this->nMethod ) { OOFEM_ERROR("linear solver creation failed for lstype %d", solverType); } @@ -233,22 +224,17 @@ NumericalMethod *SUPG :: giveNumericalMethod(MetaStep *mStep) return this->nMethod.get(); } -IRResultType -SUPG :: initializeFrom(InputRecord *ir) +void +SUPG :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = FluidModel :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + FluidModel :: initializeFrom(ir); IR_GIVE_FIELD(ir, rtolv, _IFT_SUPG_rtolv); atolv = 1.e-15; IR_GIVE_OPTIONAL_FIELD(ir, atolv, _IFT_SUPG_atolv); - stopmaxiter = ir->hasField(_IFT_SUPG_stopmaxiter); + stopmaxiter = ir.hasField(_IFT_SUPG_stopmaxiter); maxiter = 200; IR_GIVE_OPTIONAL_FIELD(ir, maxiter, _IFT_SUPG_maxiter); @@ -285,33 +271,30 @@ SUPG :: initializeFrom(InputRecord *ir) } if ( requiresUnknownsDictionaryUpdate() ) { - VelocityPressureField.reset( new DofDistributedPrimaryField(this, 1, FT_VelocityPressure, 1) ); + VelocityPressureField = std::make_unique(this, 1, FT_VelocityPressure, 1); } else { - VelocityPressureField.reset( new PrimaryField(this, 1, FT_VelocityPressure, 1) ); + VelocityPressureField = std::make_unique(this, 1, FT_VelocityPressure, 1); } val = 0; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_SUPG_miflag); if ( val == 1 ) { - this->materialInterface.reset( new LEPlic( 1, this->giveDomain(1) ) ); + this->materialInterface = std::make_unique( 1, this->giveDomain(1) ); this->materialInterface->initializeFrom(ir); // export velocity field FieldManager *fm = this->giveContext()->giveFieldManager(); - IntArray mask; - mask = {V_u, V_v, V_w}; + IntArray mask = {V_u, V_v, V_w}; - std :: shared_ptr< Field > _velocityField( new MaskedPrimaryField ( FT_Velocity, this->VelocityPressureField.get(), mask ) ); + std :: shared_ptr< Field > _velocityField = std::make_shared( FT_Velocity, this->VelocityPressureField.get(), mask ); fm->registerField(_velocityField, FT_Velocity); //fsflag = 0; //IR_GIVE_OPTIONAL_FIELD (ir, fsflag, _IFT_SUPG_fsflag, "fsflag"); } else if ( val == 2 ) { // positive coefficient scheme level set alg - this->materialInterface.reset( new LevelSetPCS( 1, this->giveDomain(1) ) ); + this->materialInterface = std::make_unique( 1, this->giveDomain(1) ); this->materialInterface->initializeFrom(ir); } - - return IRRT_OK; } @@ -382,6 +365,37 @@ SUPG :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) } } +void SUPG :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) +{ + this->VelocityPressureField->update(VM_Total, tStep, solutionVector, EModelDefaultEquationNumbering()); + // update element stabilization + for ( auto &elem : d->giveElements() ) { + static_cast< FMElement * >( elem.get() )->updateStabilizationCoeffs(tStep); + } +} + + +void SUPG :: updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) +{ + answer.zero(); + this->assembleVector(answer, tStep, SUPGInternalForceAssembler(lscale, dscale, uscale), VM_Total, + EModelDefaultEquationNumbering(), d, eNorm); + this->updateSharedDofManagers(answer, EModelDefaultEquationNumbering(), InternalForcesExchangeTag); +} + + +void SUPG :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) +{ + mat.zero(); + //if ( 1 ) { //if ((nite > 5)) // && (rnorm < 1.e4)) + this->assemble( mat, tStep, SUPGTangentAssembler(TangentStiffness, lscale, dscale, uscale, alpha), + EModelDefaultEquationNumbering(), d ); + // } else { + // this->assemble( lhs, tStep, SUPGTangentAssembler(SecantStiffness), + // EModelDefaultEquationNumbering(), d ); + // } +} + double SUPG :: giveReynoldsNumber() @@ -403,8 +417,7 @@ SUPG :: giveSolutionStepWhenIcApply(bool force) if ( !stepWhenIcApply ) { double dt = deltaT / this->giveVariableScale(VST_Time); - stepWhenIcApply.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, - 0.0, dt, 0) ); + stepWhenIcApply = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 0, 0.0, dt, 0); } return stepWhenIcApply.get(); @@ -420,7 +433,7 @@ SUPG :: giveNextStep() if ( !currentStep ) { // first step -> generate initial step - currentStep.reset( new TimeStep( *giveSolutionStepWhenIcApply() ) ); + currentStep = std::make_unique( *giveSolutionStepWhenIcApply() ); } previousStep = std :: move(currentStep); @@ -441,7 +454,7 @@ SUPG :: giveNextStep() // dt *= 0.6; dt /= this->giveVariableScale(VST_Time); - currentStep.reset( new TimeStep(*previousStep, dt) ); + currentStep = std::make_unique(*previousStep, dt); OOFEM_LOG_INFO( "SolutionStep %d : t = %e, dt = %e\n", currentStep->giveNumber(), currentStep->giveTargetTime() * this->giveVariableScale(VST_Time), dt * this->giveVariableScale(VST_Time) ); @@ -483,7 +496,7 @@ SUPG :: solveYourselfAt(TimeStep *tStep) incrementalSolutionVector.resize(neq); - lhs.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + lhs = classFactory.createSparseMtrx(sparseMtrxType); if ( !lhs ) { OOFEM_ERROR("sparse matrix creation failed"); } @@ -560,7 +573,7 @@ SUPG :: solveYourselfAt(TimeStep *tStep) this->initMetaStepAttributes( this->giveCurrentMetaStep() ); double loadLevel; int currentIterations; - this->updateComponent( tStep, InternalRhs, this->giveDomain(1) ); + this->updateInternalRHS( this->internalForces, tStep, this->giveDomain(1), &this->eNorm ); NM_Status status = this->nMethod->solve(*this->lhs, externalForces, NULL, @@ -619,27 +632,27 @@ SUPG :: solveYourselfAt(TimeStep *tStep) #if 1 nMethod->solve(*lhs, rhs, incrementalSolutionVector); #else + { + auto lhs_copy = lhs->clone(); - SparseMtrx *__lhs = lhs->GiveCopy(); + nMethod->solve(*lhs, rhs, incrementalSolutionVector); - nMethod->solve(*lhs, rhs, incrementalSolutionVector); + // check solver + FloatArray __rhs(neq); + double __absErr = 0., __relErr = 0.; + lhs_copy->times(incrementalSolutionVector, __rhs); + for ( int i = 1; i <= neq; i++ ) { + if ( fabs( __rhs.at(i) - rhs.at(i) ) > __absErr ) { + __absErr = fabs( __rhs.at(i) - rhs.at(i) ); + } - // check solver - FloatArray __rhs(neq); - double __absErr = 0., __relErr = 0.; - __lhs->times(incrementalSolutionVector, __rhs); - for ( int i = 1; i <= neq; i++ ) { - if ( fabs( __rhs.at(i) - rhs.at(i) ) > __absErr ) { - __absErr = fabs( __rhs.at(i) - rhs.at(i) ); + if ( fabs( ( __rhs.at(i) - rhs.at(i) ) / rhs.at(i) ) > __relErr ) { + __relErr = fabs( ( __rhs.at(i) - rhs.at(i) ) / rhs.at(i) ); + } } - if ( fabs( ( __rhs.at(i) - rhs.at(i) ) / rhs.at(i) ) > __relErr ) { - __relErr = fabs( ( __rhs.at(i) - rhs.at(i) ) / rhs.at(i) ); - } + OOFEM_LOG_INFO("SUPG: solver check: absoluteError %e, relativeError %e\n", __absErr, __relErr); } - - OOFEM_LOG_INFO("SUPG: solver check: absoluteError %e, relativeError %e\n", __absErr, __relErr); - delete(__lhs); #endif @@ -804,77 +817,39 @@ SUPG :: updateInternalState(TimeStep *tStep) } -contextIOResultType +void SUPG :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = EngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + EngngModel :: saveContext(stream, mode); - if ( ( iores = VelocityPressureField->saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + VelocityPressureField->saveContext(stream); + contextIOResultType iores; if ( ( iores = accelerationVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } if ( materialInterface ) { - if ( ( iores = materialInterface->saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + materialInterface->saveContext(stream, mode); } - - return CIO_OK; } -contextIOResultType -SUPG :: restoreContext(DataStream *stream, ContextMode mode, void *obj) +void +SUPG :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - int closeFlag = 0; - int istep, iversion; - FILE *file = NULL; + EngngModel :: restoreContext(stream, mode); - this->resolveCorrespondingStepNumber(istep, iversion, obj); + VelocityPressureField->restoreContext(stream); - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - - if ( ( iores = EngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = VelocityPressureField->restoreContext(*stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = accelerationVector.restoreYourself(*stream) ) != CIO_OK ) { + contextIOResultType iores; + if ( ( iores = accelerationVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } if ( materialInterface ) { - if ( ( iores = materialInterface->restoreContext(*stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + materialInterface->restoreContext(stream, mode); } - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } // ensure consistent records - - return CIO_OK; } diff --git a/src/fm/supg.h b/src/fm/supg.h index fa3a894b3..a46d28d2e 100644 --- a/src/fm/supg.h +++ b/src/fm/supg.h @@ -78,7 +78,7 @@ class SUPGInternalForceAssembler : public VectorAssembler public: SUPGInternalForceAssembler(double l, double d, double u); - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; /** @@ -94,7 +94,7 @@ class SUPGTangentAssembler : public MatrixAssembler public: SUPGTangentAssembler(MatResponseMode m, double l, double d, double u, double a); - virtual void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const; + void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const override; }; /** @@ -120,28 +120,28 @@ class SUPG : public FluidModel FloatArray eNorm; ///@todo Use ScalarFunction here! - double deltaT; - int deltaTF; + double deltaT = 1.; + int deltaTF = 0; /// Convergence tolerance. - double atolv, rtolv; + double atolv = 1., rtolv = 1.; /// Max number of iterations. - int maxiter; + int maxiter = 0; /** * Flag if set to true (default), then when max number of iteration reached, computation stops * otherwise computation continues with next step. */ - bool stopmaxiter; + bool stopmaxiter = true; /// Integration constant. - double alpha; + double alpha = 0.; - int initFlag; - int consistentMassFlag; + int initFlag = 1; + int consistentMassFlag = 0; - bool equationScalingFlag; + bool equationScalingFlag = false; // length, velocity, and density scales - double lscale, uscale, dscale; + double lscale = 1., uscale = 1., dscale = 1.; /// Reynolds number. - double Re; + double Re = 0.; // material interface representation for multicomponent flows std :: unique_ptr< MaterialInterface > materialInterface; @@ -151,46 +151,47 @@ class SUPG : public FluidModel // int fsflag; public: - SUPG(int i, EngngModel * _master = NULL); - virtual ~SUPG(); + SUPG(int i, EngngModel * _master = nullptr); - virtual void solveYourselfAt(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); + void solveYourselfAt(TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override; - virtual double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof); - virtual void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d); - virtual double giveReynoldsNumber(); + double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) override; + void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) override; + void updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) override; + void updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) override; + void updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) override; + double giveReynoldsNumber() override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void updateDomainLinks(); + void updateDomainLinks() override; - virtual TimeStep *giveNextStep(); - virtual TimeStep *giveSolutionStepWhenIcApply(bool force = false); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + TimeStep *giveNextStep() override; + TimeStep *giveSolutionStepWhenIcApply(bool force = false) override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual int checkConsistency(); + int checkConsistency() override; // identification - virtual const char *giveClassName() const { return "SUPG"; } - virtual const char *giveInputRecordName() const { return _IFT_SUPG_Name; } - - virtual fMode giveFormulation() { return TL; } + const char *giveClassName() const override { return "SUPG"; } + const char *giveInputRecordName() const { return _IFT_SUPG_Name; } - virtual void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep); + fMode giveFormulation() override { return TL; } - virtual int requiresUnknownsDictionaryUpdate() { return renumberFlag; } + void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep) override; - virtual bool giveEquationScalingFlag() { return equationScalingFlag; } - virtual double giveVariableScale(VarScaleType varId); + int requiresUnknownsDictionaryUpdate() override { return renumberFlag; } - virtual void updateDofUnknownsDictionary(DofManager *dman, TimeStep *tStep); - virtual int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep); + bool giveEquationScalingFlag() override { return equationScalingFlag; } + double giveVariableScale(VarScaleType varId) override; - virtual MaterialInterface *giveMaterialInterface(int n) { return materialInterface.get(); } + void updateDofUnknownsDictionary(DofManager *dman, TimeStep *tStep) override; + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override; + MaterialInterface *giveMaterialInterface(int n) override { return materialInterface.get(); } protected: void updateInternalState(TimeStep *tStep); diff --git a/src/fm/supgelement.C b/src/fm/supgelement.C index de8f328be..9e5cfa9f3 100644 --- a/src/fm/supgelement.C +++ b/src/fm/supgelement.C @@ -39,7 +39,7 @@ #include "intarray.h" #include "floatarray.h" #include "floatmatrix.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fluidcrosssection.h" #include "dynamicinputrecord.h" #include "engngm.h" @@ -53,26 +53,18 @@ namespace oofem { SUPGElement :: SUPGElement(int n, Domain *aDomain) : - FMElement(n, aDomain), t_supg(0), t_pspg(0), t_lsic(0) + FMElement(n, aDomain) { } -SUPGElement :: ~SUPGElement() -// Destructor. -{ } - -IRResultType -SUPGElement :: initializeFrom(InputRecord *ir) +void +SUPGElement :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - + FMElement :: initializeFrom(ir); IR_GIVE_OPTIONAL_FIELD(ir, boundarySides, _IFT_SUPGElement_bsides); if ( !boundarySides.isEmpty() ) { IR_GIVE_FIELD(ir, boundaryCodes, _IFT_SUPGElement_bcodes); } - - return FMElement :: initializeFrom(ir); } @@ -223,22 +215,6 @@ SUPGElement :: giveCharacteristicVector(FloatArray &answer, CharType mtrx, Value } - - - -void -SUPGElement :: computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) -{ - FloatArray eps; - - // compute deviatoric strain - this->computeDeviatoricStrain(eps, gp, tStep); - // call material to compute stress - static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStressVector(answer, gp, eps, tStep); -} - - - void SUPGElement :: computeBCLhsTerm_MB(FloatMatrix &answer, TimeStep *tStep) { @@ -350,12 +326,13 @@ SUPGElement :: checkConsistency() void SUPGElement :: updateInternalState(TimeStep *tStep) { - FloatArray stress; + FloatArray stress, eps; // force updating strains & stresses for ( auto &iRule: integrationRulesArray ) { - for ( GaussPoint *gp: *iRule ) { - computeDeviatoricStress(stress, gp, tStep); + for ( auto &gp: *iRule ) { + computeDeviatoricStrain(eps, gp, tStep); + computeDeviatoricStress(stress, eps, gp, tStep); } } } diff --git a/src/fm/supgelement.h b/src/fm/supgelement.h index 7cb88c0ac..9bcfbdd53 100644 --- a/src/fm/supgelement.h +++ b/src/fm/supgelement.h @@ -67,18 +67,17 @@ class SUPGElement : public FMElement * Stabilization coefficients, updated for each solution step * in updateStabilizationCoeffs() */ - double t_supg, t_pspg, t_lsic; + double t_supg = 0., t_pspg = 0., t_lsic = 0.; public: SUPGElement(int n, Domain * aDomain); - virtual ~SUPGElement(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep); - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void updateStabilizationCoeffs(TimeStep *tStep) { } + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) override; + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override; + void updateStabilizationCoeffs(TimeStep *tStep) override { } virtual void updateElementForNewInterfacePosition(TimeStep *tStep) { } /** @@ -197,12 +196,12 @@ class SUPGElement : public FMElement virtual double computeCriticalTimeStep(TimeStep *tStep) = 0; // time step termination - virtual void updateInternalState(TimeStep *tStep); - virtual int checkConsistency(); + void updateInternalState(TimeStep *tStep) override; + int checkConsistency() override; #ifdef __OOFEG int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *tStep); + int node, TimeStep *tStep) override; #endif virtual void giveLocalVelocityDofMap(IntArray &map) { } @@ -210,7 +209,8 @@ class SUPGElement : public FMElement protected: virtual void computeDeviatoricStrain(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) = 0; - virtual void computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + virtual void computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) = 0; + virtual void computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; }; } // end namespace oofem #endif // supgelement_h diff --git a/src/fm/supgelement2.C b/src/fm/supgelement2.C index 4958e5a04..3cbf9a256 100644 --- a/src/fm/supgelement2.C +++ b/src/fm/supgelement2.C @@ -40,7 +40,7 @@ #include "floatarray.h" #include "floatmatrix.h" #include "fluidmodel.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fluidcrosssection.h" #include "integrationrule.h" #include "node.h" @@ -54,20 +54,13 @@ namespace oofem { SUPGElement2 :: SUPGElement2(int n, Domain *aDomain) : SUPGElement(n, aDomain) - // Constructor. Creates an element with number n, belonging to aDomain. { } -SUPGElement2 :: ~SUPGElement2() -// Destructor. -{ } - -IRResultType -SUPGElement2 :: initializeFrom(InputRecord *ir) +void +SUPGElement2 :: initializeFrom(InputRecord &ir) { - //IRResultType result; // Required by IR_GIVE_FIELD macro - - return SUPGElement :: initializeFrom(ir); + SUPGElement :: initializeFrom(ir); } @@ -208,12 +201,13 @@ SUPGElement2 :: checkConsistency() void SUPGElement2 :: updateInternalState(TimeStep *tStep) { - FloatArray stress; + FloatArray stress, eps; // force updating strains & stresses for ( auto &iRule: integrationRulesArray ) { - for ( GaussPoint *gp: *iRule ) { - computeDeviatoricStress(stress, gp, tStep); + for ( auto &gp: *iRule ) { + computeDeviatoricStrain(eps, gp, tStep); + computeDeviatoricStress(stress, eps, gp, tStep); } } } @@ -341,7 +335,6 @@ SUPGElement2 :: computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) answer.clear(); - FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); this->computeVectorOfVelocities(VM_Total, tStep, u); int rule = 1; @@ -351,7 +344,7 @@ SUPGElement2 :: computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) this->computeDivTauMatrix(dDB, gp, tStep); this->computeUDotGradUMatrix( un_gu, gp, tStep->givePreviousStep() ); eps.beProductOf(b, u); - mat->computeDeviatoricStressVector(stress, gp, eps, tStep); + this->computeDeviatoricStress(stress, eps, gp, tStep); dDB_u.beProductOf(dDB, u); /* consistent part */ answer.plusProduct(b, stress, dV / Re); @@ -369,13 +362,11 @@ SUPGElement2 :: computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatRespon answer.clear(); - FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); - int rule = 1; for ( GaussPoint *gp: *this->integrationRulesArray [ rule ] ) { double dV = this->computeVolumeAround(gp); this->computeBMatrix(_b, gp); - mat->giveDeviatoricStiffnessMatrix(_d, mode, gp, tStep); + this->computeTangent(_d, mode, gp, tStep); this->computeDivTauMatrix(dDB, gp, tStep); this->computeUDotGradUMatrix( un_gu, gp, tStep->givePreviousStep() ); @@ -789,14 +780,4 @@ SUPGElement2 :: computeDeviatoricStrain(FloatArray &answer, GaussPoint *gp, Time answer.beProductOf(b, u); } -void -SUPGElement2 :: computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) -{ - FloatArray eps; - - // compute deviatoric strain - this->computeDeviatoricStrain(eps, gp, tStep); - // call material to compute stress - static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStressVector(answer, gp, eps, tStep); -} } // end namespace oofem diff --git a/src/fm/supgelement2.h b/src/fm/supgelement2.h index 64eff2a4e..bef9d5d13 100644 --- a/src/fm/supgelement2.h +++ b/src/fm/supgelement2.h @@ -58,48 +58,46 @@ class SUPGElement2 : public SUPGElement { public: SUPGElement2(int n, Domain * aDomain); - virtual ~SUPGElement2(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; // characteristic matrix - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType, TimeStep *tStep); - virtual void giveCharacteristicVector(FloatArray &answer, CharType, ValueModeType, TimeStep *tStep); - virtual void updateElementForNewInterfacePosition(TimeStep *tStep) { } + void giveCharacteristicMatrix(FloatMatrix &answer, CharType, TimeStep *tStep) override; + void giveCharacteristicVector(FloatArray &answer, CharType, ValueModeType, TimeStep *tStep) override; + void updateElementForNewInterfacePosition(TimeStep *tStep) override { } - virtual void computeAccelerationTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeAdvectionDerivativeTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); - virtual void computePressureTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLSICStabilizationTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLinearAdvectionTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionTerm_MC(FloatArray &answer, TimeStep *tStep); - virtual void computeAdvectionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionTerm_MC(FloatArray &answer, TimeStep *tStep); - virtual void computeAccelerationTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computePressureTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeBCRhsTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeBCRhsTerm_MC(FloatArray &answer, TimeStep *tStep); - virtual void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); + void computeAccelerationTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeAdvectionTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeAdvectionDerivativeTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) override; + void computePressureTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeLSICStabilizationTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeLinearAdvectionTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeAdvectionTerm_MC(FloatArray &answer, TimeStep *tStep) override; + void computeAdvectionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionTerm_MC(FloatArray &answer, TimeStep *tStep) override; + void computeAccelerationTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computePressureTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeBCRhsTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeBCRhsTerm_MC(FloatArray &answer, TimeStep *tStep) override; + void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; - virtual double computeCriticalTimeStep(TimeStep *tStep) = 0; + double computeCriticalTimeStep(TimeStep *tStep) override = 0; // time step termination - virtual void updateInternalState(TimeStep *tStep); - virtual int checkConsistency(); + void updateInternalState(TimeStep *tStep) override; + int checkConsistency() override; #ifdef __OOFEG int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *tStep); + int node, TimeStep *tStep) override; #endif protected: - virtual void computeDeviatoricStrain(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); - virtual void computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeDeviatoricStrain(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; virtual void computeNuMatrix(FloatMatrix &answer, GaussPoint *gp) = 0; virtual void computeUDotGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) = 0; virtual void computeBMatrix(FloatMatrix &anwer, GaussPoint *gp) = 0; diff --git a/src/fm/tet1_3d_supg.C b/src/fm/tet1_3d_supg.C index 684f27b34..6d0abd6dc 100644 --- a/src/fm/tet1_3d_supg.C +++ b/src/fm/tet1_3d_supg.C @@ -39,7 +39,7 @@ #include "material.h" #include "gausspoint.h" #include "gaussintegrationrule.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fluidcrosssection.h" #include "floatmatrix.h" #include "floatarray.h" @@ -62,15 +62,10 @@ FEI3dTetLin Tet1_3D_SUPG :: interpolation; Tet1_3D_SUPG :: Tet1_3D_SUPG(int n, Domain *aDomain) : SUPGElement2(n, aDomain) - // Constructor. { numberOfDofMans = 4; } -Tet1_3D_SUPG :: ~Tet1_3D_SUPG() -// Destructor -{ } - int Tet1_3D_SUPG :: computeNumberOfDofs() { @@ -90,13 +85,13 @@ Tet1_3D_SUPG :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(3); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); - integrationRulesArray [ 1 ].reset( new GaussIntegrationRule(2, this, 1, 3) ); + integrationRulesArray [ 1 ] = std::make_unique(2, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 1 ], 4, this); - integrationRulesArray [ 2 ].reset( new GaussIntegrationRule(3, this, 1, 3) ); + integrationRulesArray [ 2 ] = std::make_unique(3, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 2 ], 4, this); } } @@ -364,14 +359,14 @@ Tet1_3D_SUPG :: computeCriticalTimeStep(TimeStep *tStep) jnode = this->giveNode(j); knode = this->giveNode(k); lnode = this->giveNode(l); - t1.beDifferenceOf(*inode->giveCoordinates(), *jnode->giveCoordinates()); + t1.beDifferenceOf(inode->giveCoordinates(), jnode->giveCoordinates()); - t2.beDifferenceOf(*knode->giveCoordinates(), *jnode->giveCoordinates()); + t2.beDifferenceOf(knode->giveCoordinates(), jnode->giveCoordinates()); n.beVectorProductOf(t1, t2); n.normalize(); - n3.beDifferenceOf(*lnode->giveCoordinates(), *jnode->giveCoordinates()); + n3.beDifferenceOf(lnode->giveCoordinates(), jnode->giveCoordinates()); ln = min( ln, sqrt( fabs( n.dotProduct(n3) ) ) ); } @@ -399,6 +394,20 @@ Tet1_3D_SUPG :: computeVolumeAround(GaussPoint *gp) } +void +Tet1_3D_SUPG :: computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStress3D(eps, gp, tStep); +} + + +void +Tet1_3D_SUPG :: computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeTangent3D(mode, gp, tStep); +} + + double Tet1_3D_SUPG :: LS_PCS_computeF(LevelSetPCS *ls, TimeStep *tStep) { diff --git a/src/fm/tet1_3d_supg.h b/src/fm/tet1_3d_supg.h index d281e87c1..d1da2295e 100644 --- a/src/fm/tet1_3d_supg.h +++ b/src/fm/tet1_3d_supg.h @@ -54,43 +54,44 @@ class Tet1_3D_SUPG : public SUPGElement2, public LevelSetPCSElementInterface public: Tet1_3D_SUPG(int n, Domain * d); - virtual ~Tet1_3D_SUPG(); // definition - virtual const char *giveClassName() const { return "Tet1_3D_SUPG"; } - virtual const char *giveInputRecordName() const { return _IFT_Tet1_3D_SUPG_Name; } - virtual MaterialMode giveMaterialMode() { return _3dFlow; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual int computeNumberOfDofs(); + const char *giveClassName() const override { return "Tet1_3D_SUPG"; } + const char *giveInputRecordName() const override { return _IFT_Tet1_3D_SUPG_Name; } + MaterialMode giveMaterialMode() override { return _3dFlow; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + int computeNumberOfDofs() override; - virtual Interface *giveInterface(InterfaceType t); + Interface *giveInterface(InterfaceType t) override; - virtual double computeCriticalTimeStep(TimeStep *tStep); - virtual double computeVolumeAround(GaussPoint *gp); + double computeCriticalTimeStep(TimeStep *tStep) override; + double computeVolumeAround(GaussPoint *gp) override; - virtual void updateStabilizationCoeffs(TimeStep *tStep); + void updateStabilizationCoeffs(TimeStep *tStep) override; - virtual double LS_PCS_computeF(LevelSetPCS *, TimeStep *); - virtual void LS_PCS_computedN(FloatMatrix &answer); - virtual double LS_PCS_computeVolume(); - virtual double LS_PCS_computeS(LevelSetPCS *, TimeStep *); - virtual void LS_PCS_computeVOFFractions(FloatArray &answer, FloatArray &fi); + double LS_PCS_computeF(LevelSetPCS *, TimeStep *tStep) override; + void LS_PCS_computedN(FloatMatrix &answer) override; + double LS_PCS_computeVolume() override; + double LS_PCS_computeS(LevelSetPCS *, TimeStep *tStep) override; + void LS_PCS_computeVOFFractions(FloatArray &answer, FloatArray &fi) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; #endif protected: - virtual void computeGaussPoints(); - virtual void computeNuMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeUDotGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - virtual void computeBMatrix(FloatMatrix &anwer, GaussPoint *gp); - virtual void computeDivUMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeNpMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeGradPMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeDivTauMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - virtual void computeGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - virtual int giveNumberOfSpatialDimensions(); + void computeGaussPoints() override; + void computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) override; + void computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void computeNuMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeUDotGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) override; + void computeBMatrix(FloatMatrix &anwer, GaussPoint *gp) override; + void computeDivUMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeNpMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeGradPMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeDivTauMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) override; + void computeGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) override; + int giveNumberOfSpatialDimensions() override; }; } // end namespace oofem #endif // tet1_3d_supg_h diff --git a/src/fm/tet1bubblestokes.C b/src/fm/tet1bubblestokes.C index a141420a6..5531e4b9d 100644 --- a/src/fm/tet1bubblestokes.C +++ b/src/fm/tet1bubblestokes.C @@ -42,7 +42,7 @@ #include "bodyload.h" #include "boundaryload.h" #include "mathfem.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fei3dtetlin.h" #include "masterdof.h" #include "fluidcrosssection.h" @@ -68,21 +68,17 @@ Tet1BubbleStokes :: Tet1BubbleStokes(int n, Domain *aDomain) : FMElement(n, aDom this->numberOfDofMans = 4; this->numberOfGaussPoints = 24; - this->bubble.reset( new ElementDofManager(1, aDomain, this) ); + this->bubble = std::make_unique(1, aDomain, this); this->bubble->appendDof( new MasterDof(this->bubble.get(), V_u) ); this->bubble->appendDof( new MasterDof(this->bubble.get(), V_v) ); this->bubble->appendDof( new MasterDof(this->bubble.get(), V_w) ); } -Tet1BubbleStokes :: ~Tet1BubbleStokes() -{ -} - void Tet1BubbleStokes :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], this->numberOfGaussPoints, this); } } @@ -105,7 +101,7 @@ void Tet1BubbleStokes :: giveInternalDofManDofIDMask(int i, IntArray &answer) co double Tet1BubbleStokes :: computeVolumeAround(GaussPoint *gp) { double detJ = fabs( this->interp.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - return detJ *gp->giveWeight(); + return detJ * gp->giveWeight(); } void Tet1BubbleStokes :: giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, @@ -135,42 +131,44 @@ void Tet1BubbleStokes :: giveCharacteristicMatrix(FloatMatrix &answer, void Tet1BubbleStokes :: computeInternalForcesVector(FloatArray &answer, TimeStep *tStep) { FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); - FloatArray a_pressure, a_velocity, devStress, epsp, N, dNv(15); - double r_vol, pressure; - FloatMatrix dN, B(6, 15); - B.zero(); - this->computeVectorOfVelocities(VM_Total, tStep, a_velocity); - this->computeVectorOfPressures(VM_Total, tStep, a_pressure); + FloatArrayF<15> a_velocity = this->computeVectorOfVelocities(VM_Total, tStep); + FloatArrayF<4> a_pressure = this->computeVectorOfPressures(VM_Total, tStep); - FloatArray momentum, conservation; + FloatArrayF<15> momentum; + FloatArrayF<4> conservation; - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { - const FloatArray &lcoords = gp->giveNaturalCoordinates(); + for ( auto &gp: *integrationRulesArray [ 0 ] ) { + const auto &lcoords = gp->giveNaturalCoordinates(); - double detJ = fabs( this->interp.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) ); - this->interp.evalN( N, lcoords, FEIElementGeometryWrapper(this) ); - double dV = detJ * gp->giveWeight(); + auto N = this->interp.evalN( lcoords ); + auto detj_dn = this->interp.evaldNdx( FEIElementGeometryWrapper(this) ); + auto dN = detj_dn.second; + auto detJ = detj_dn.first; + auto dV = std::abs(detJ) * gp->giveWeight(); - for ( int j = 0, k = 0; j < dN.giveNumberOfRows(); j++, k += 3 ) { - dNv(k + 0) = B(0, k + 0) = B(5, k + 1) = B(4, k + 2) = dN(j, 0); - dNv(k + 1) = B(1, k + 1) = B(5, k + 0) = B(3, k + 2) = dN(j, 1); - dNv(k + 2) = B(2, k + 2) = B(4, k + 0) = B(3, k + 1) = dN(j, 2); + FloatArrayF<15> dN_V; + FloatMatrixF<6,15> B; + for ( std::size_t j = 0, k = 0; j < dN.rows(); j++, k += 3 ) { + dN_V[k + 0] = B(0, k + 0) = B(5, k + 1) = B(4, k + 2) = dN(0, j); + dN_V[k + 1] = B(1, k + 1) = B(5, k + 0) = B(3, k + 2) = dN(1, j); + dN_V[k + 2] = B(2, k + 2) = B(4, k + 0) = B(3, k + 1) = dN(2, j); } // Bubble contribution; - dNv(12) = B(0, 12) = B(5, 13) = B(4, 14) = dN(0, 0) * N(1) * N(2) * N(3) + N(0) * dN(1, 0) * N(2) * N(3) + N(0) * N(1) * dN(2, 0) * N(3) + N(0) * N(1) * N(2) * dN(3, 0); - dNv(13) = B(1, 13) = B(5, 12) = B(3, 14) = dN(0, 1) * N(1) * N(2) * N(3) + N(0) * dN(1, 1) * N(2) * N(3) + N(0) * N(1) * dN(2, 1) * N(3) + N(0) * N(1) * N(2) * dN(3, 1); - dNv(14) = B(2, 14) = B(4, 12) = B(3, 13) = dN(0, 2) * N(1) * N(2) * N(3) + N(0) * dN(1, 2) * N(2) * N(3) + N(0) * N(1) * dN(2, 2) * N(3) + N(0) * N(1) * N(2) * dN(3, 2); + dN_V[12] = B(0, 12) = B(5, 13) = B(4, 14) = dN(0, 0) * N[1] * N[2] * N[3] + N[0] * dN(1, 0) * N[2] * N[3] + N[0] * N[1] * dN(2, 0) * N[3] + N[0] * N[1] * N[2] * dN(3, 0); + dN_V[13] = B(1, 13) = B(5, 12) = B(3, 14) = dN(0, 1) * N[1] * N[2] * N[3] + N[0] * dN(1, 1) * N[2] * N[3] + N[0] * N[1] * dN(2, 1) * N[3] + N[0] * N[1] * N[2] * dN(3, 1); + dN_V[14] = B(2, 14) = B(4, 12) = B(3, 13) = dN(0, 2) * N[1] * N[2] * N[3] + N[0] * dN(1, 2) * N[2] * N[3] + N[0] * N[1] * dN(2, 2) * N[3] + N[0] * N[1] * N[2] * dN(3, 2); - pressure = N.dotProduct(a_pressure); - epsp.beProductOf(B, a_velocity); + auto pressure = dot(N, a_pressure); + auto epsp = dot(B, a_velocity); - mat->computeDeviatoricStressVector(devStress, r_vol, gp, epsp, pressure, tStep); + auto s_r = mat->computeDeviatoricStress3D(epsp, pressure, gp, tStep); + auto devStress = s_r.first; + auto r_vol = s_r.second; - momentum.plusProduct(B, devStress, dV); - momentum.add(-pressure * dV, dNv); - conservation.add(r_vol * dV, N); + momentum += Tdot(B, devStress * dV) + dN_V * (-pressure * dV); + conservation += N * (r_vol * dV); } answer.resize(19); @@ -231,7 +229,7 @@ void Tet1BubbleStokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, C load->computeComponentArrayAt(gVector, tStep, VM_Total); temparray.zero(); if ( gVector.giveSize() ) { - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp); @@ -273,7 +271,7 @@ void Tet1BubbleStokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, C f.zero(); iRule.SetUpPointsOnTriangle(numberOfIPs, _Unknown); - for ( GaussPoint *gp: iRule ) { + for ( auto &gp: iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->interp.surfaceEvalN( N, iSurf, lcoords, FEIElementGeometryWrapper(this) ); @@ -310,54 +308,49 @@ void Tet1BubbleStokes :: computeStiffnessMatrix(FloatMatrix &answer, MatResponse { // Note: Working with the components; [K, G+Dp; G^T+Dv^T, C] . [v,p] FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); - FloatMatrix B(6, 15), EdB, K, G, Dp, DvT, C, Ed, dN; - FloatArray dNv(15), N, Ep, Cd, tmpA, tmpB; - double Cp; - - B.zero(); + FloatMatrixF<15,15> K; + FloatMatrixF<15,4> G, Dp; + FloatMatrixF<4,15> DvT; + FloatMatrixF<4,4> C; - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { // Compute Gauss point and determinant at current element - const FloatArray &lcoords = gp->giveNaturalCoordinates(); - - double detJ = fabs( this->interp.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) ); - double dV = detJ * gp->giveWeight(); - this->interp.evalN( N, lcoords, FEIElementGeometryWrapper(this) ); - - for ( int j = 0, k = 0; j < 4; j++, k += 3 ) { - dNv(k + 0) = B(0, k + 0) = B(5, k + 1) = B(4, k + 2) = dN(j, 0); - dNv(k + 1) = B(1, k + 1) = B(5, k + 0) = B(3, k + 2) = dN(j, 1); - dNv(k + 2) = B(2, k + 2) = B(4, k + 0) = B(3, k + 1) = dN(j, 2); + const auto &lcoords = gp->giveNaturalCoordinates(); + + auto N = this->interp.evalN( lcoords ); + auto detj_dn = this->interp.evaldNdx( FEIElementGeometryWrapper(this) ); + auto dN = detj_dn.second; + auto detJ = detj_dn.first; + auto dA = std::abs(detJ) * gp->giveWeight(); + + FloatArrayF<15> dN_V; + FloatMatrixF<6,15> B; + for ( std::size_t j = 0, k = 0; j < dN.rows(); j++, k += 3 ) { + dN_V[k + 0] = B(0, k + 0) = B(5, k + 1) = B(4, k + 2) = dN(0, j); + dN_V[k + 1] = B(1, k + 1) = B(5, k + 0) = B(3, k + 2) = dN(1, j); + dN_V[k + 2] = B(2, k + 2) = B(4, k + 0) = B(3, k + 1) = dN(2, j); } // Bubble contribution; - dNv(12) = B(0, 12) = B(5, 13) = B(4, 14) = dN(0, 0) * N(1) * N(2) * N(3) + N(0) * dN(1, 0) * N(2) * N(3) + N(0) * N(1) * dN(2, 0) * N(3) + N(0) * N(1) * N(2) * dN(3, 0); - dNv(13) = B(1, 13) = B(5, 12) = B(3, 14) = dN(0, 1) * N(1) * N(2) * N(3) + N(0) * dN(1, 1) * N(2) * N(3) + N(0) * N(1) * dN(2, 1) * N(3) + N(0) * N(1) * N(2) * dN(3, 1); - dNv(14) = B(2, 14) = B(4, 12) = B(3, 13) = dN(0, 2) * N(1) * N(2) * N(3) + N(0) * dN(1, 2) * N(2) * N(3) + N(0) * N(1) * dN(2, 2) * N(3) + N(0) * N(1) * N(2) * dN(3, 2); + dN_V[12] = B(0, 12) = B(5, 13) = B(4, 14) = dN(0, 0) * N[1] * N[2] * N[3] + N[0] * dN(1, 0) * N[2] * N[3] + N[0] * N[1] * dN(2, 0) * N[3] + N[0] * N[1] * N[2] * dN(3, 0); + dN_V[13] = B(1, 13) = B(5, 12) = B(3, 14) = dN(0, 1) * N[1] * N[2] * N[3] + N[0] * dN(1, 1) * N[2] * N[3] + N[0] * N[1] * dN(2, 1) * N[3] + N[0] * N[1] * N[2] * dN(3, 1); + dN_V[14] = B(2, 14) = B(4, 12) = B(3, 13) = dN(0, 2) * N[1] * N[2] * N[3] + N[0] * dN(1, 2) * N[2] * N[3] + N[0] * N[1] * dN(2, 2) * N[3] + N[0] * N[1] * N[2] * dN(3, 2); // Computing the internal forces should have been done first. // dsigma_dev/deps_dev dsigma_dev/dp deps_vol/deps_dev deps_vol/dp - mat->giveStiffnessMatrices(Ed, Ep, Cd, Cp, mode, gp, tStep); - - EdB.beProductOf(Ed, B); - K.plusProductSymmUpper(B, EdB, dV); - G.plusDyadUnsym(dNv, N, -dV); - C.plusDyadSymmUpper(N, Cp * dV); - - tmpA.beTProductOf(B, Ep); - Dp.plusDyadUnsym(tmpA, N, dV); + auto tangents = mat->computeTangents3D(mode, gp, tStep); - tmpB.beTProductOf(B, Cd); - DvT.plusDyadUnsym(N, tmpB, dV); + K.plusProductSymmUpper(B, dot(tangents.dsdd, B), dA); + G.plusDyadUnsym(dN_V, N, -dA); + Dp.plusDyadUnsym(Tdot(B, tangents.dsdp), N, dA); + DvT.plusDyadUnsym(N, Tdot(B, tangents.dedd), dA); + C.plusDyadSymmUpper(N, tangents.dedp * dA); } K.symmetrized(); C.symmetrized(); - FloatMatrix GTDvT, GDp; - GTDvT.beTranspositionOf(G); - GTDvT.add(DvT); - GDp = G; - GDp.add(Dp); + auto GTDvT = transpose(G) + DvT; + auto GDp = G + Dp; answer.resize(19, 19); answer.zero(); diff --git a/src/fm/tet1bubblestokes.h b/src/fm/tet1bubblestokes.h index 064822baa..317566ec0 100644 --- a/src/fm/tet1bubblestokes.h +++ b/src/fm/tet1bubblestokes.h @@ -77,42 +77,41 @@ public SpatialLocalizerInterface public: Tet1BubbleStokes(int n, Domain * d); - virtual ~Tet1BubbleStokes(); - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual void computeGaussPoints(); + void computeGaussPoints() override; - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep); + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override; + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) override; void computeInternalForcesVector(FloatArray &answer, TimeStep *tStep); void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); void computeExternalForcesVector(FloatArray &answer, TimeStep *tStep); - virtual void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true); + void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; + void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true) override; - virtual const char *giveClassName() const { return "Tet1BubbleStokes"; } - virtual const char *giveInputRecordName() const { return _IFT_Tet1BubbleStokes_Name; } - virtual MaterialMode giveMaterialMode() { return _3dFlow; } + const char *giveClassName() const override { return "Tet1BubbleStokes"; } + const char *giveInputRecordName() const override { return _IFT_Tet1BubbleStokes_Name; } + MaterialMode giveMaterialMode() override { return _3dFlow; } - virtual int computeNumberOfDofs(); + int computeNumberOfDofs() override; - virtual int giveNumberOfInternalDofManagers() const { return 1; } - virtual DofManager *giveInternalDofManager(int i) const { return bubble.get(); } - virtual void giveInternalDofManDofIDMask(int i, IntArray &answer) const; + int giveNumberOfInternalDofManagers() const override { return 1; } + DofManager *giveInternalDofManager(int i) const override { return bubble.get(); } + void giveInternalDofManDofIDMask(int i, IntArray &answer) const override; - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual void computeField(ValueModeType u, TimeStep *tStep, const FloatArray &coords, FloatArray &answer); + void computeField(ValueModeType u, TimeStep *tStep, const FloatArray &coords, FloatArray &answer) override; }; } // end namespace oofem #endif // tet1bubblestokes_h diff --git a/src/fm/tet21stokes.C b/src/fm/tet21stokes.C index 54d8cfd22..c9ed1813c 100644 --- a/src/fm/tet21stokes.C +++ b/src/fm/tet21stokes.C @@ -44,7 +44,7 @@ #include "bodyload.h" #include "boundaryload.h" #include "mathfem.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fei3dtetlin.h" #include "fei3dtetquad.h" #include "fluidcrosssection.h" @@ -74,14 +74,11 @@ Tet21Stokes :: Tet21Stokes(int n, Domain *aDomain) : FMElement(n, aDomain), Spat this->numberOfGaussPoints = 5; } -Tet21Stokes :: ~Tet21Stokes() -{ } - void Tet21Stokes :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], this->numberOfGaussPoints, this); } } @@ -135,7 +132,7 @@ void Tet21Stokes :: computeInternalForcesVector(FloatArray &answer, TimeStep *tS FloatArray momentum, conservation; B.zero(); - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); double detJ = fabs( this->interpolation_quad.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) ); @@ -150,7 +147,9 @@ void Tet21Stokes :: computeInternalForcesVector(FloatArray &answer, TimeStep *tS epsp.beProductOf(B, a_velocity); pressure = Nh.dotProduct(a_pressure); - mat->computeDeviatoricStressVector(devStress, r_vol, gp, epsp, pressure, tStep); + auto val = mat->computeDeviatoricStress3D(epsp, pressure, gp, tStep); + devStress = val.first; + r_vol = val.second; momentum.plusProduct(B, devStress, dV); momentum.add(-pressure * dV, dN_V); @@ -211,7 +210,7 @@ void Tet21Stokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharTy load->computeComponentArrayAt(gVector, tStep, VM_Total); temparray.zero(); if ( gVector.giveSize() ) { - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp); @@ -252,7 +251,7 @@ void Tet21Stokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharTy f.zero(); iRule.SetUpPointsOnTriangle(numberOfSurfaceIPs, _Unknown); - for ( GaussPoint *gp: iRule ) { + for ( auto &gp: iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->interpolation_quad.surfaceEvalN( N, iSurf, lcoords, FEIElementGeometryWrapper(this) ); @@ -283,49 +282,39 @@ void Tet21Stokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharTy void Tet21Stokes :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) { FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); - FloatMatrix B(6, 30), EdB, K, G, Dp, DvT, C, Ed, dN; - FloatArray dN_V(30), Nlin, Ep, Cd, tmpA, tmpB; - double Cp; + FloatMatrixF<30,30> K; + FloatMatrixF<30,4> G, Dp; + FloatMatrixF<4,30> DvT; + FloatMatrixF<4,4> C; - B.zero(); + for ( auto &gp: *this->integrationRulesArray [ 0 ] ) { + const auto &lcoords = gp->giveNaturalCoordinates(); - for ( GaussPoint *gp: *this->integrationRulesArray [ 0 ] ) { - // Compute Gauss point and determinant at current element - const FloatArray &lcoords = gp->giveNaturalCoordinates(); + auto Nlin = this->interpolation_lin.evalN( lcoords ); + auto detj_dn = this->interpolation_quad.evaldNdx( lcoords, FEIElementGeometryWrapper(this) ); + auto dN = detj_dn.second; + auto detJ = detj_dn.first; + auto dA = std::abs(detJ) * gp->giveWeight(); - double detJ = fabs( this->interpolation_quad.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) ); - double dV = detJ * gp->giveWeight(); - this->interpolation_lin.evalN( Nlin, lcoords, FEIElementGeometryWrapper(this) ); - - for ( int j = 0, k = 0; j < dN.giveNumberOfRows(); j++, k += 3 ) { - dN_V(k + 0) = B(0, k + 0) = B(3, k + 1) = B(4, k + 2) = dN(j, 0); - dN_V(k + 1) = B(1, k + 1) = B(3, k + 0) = B(5, k + 2) = dN(j, 1); - dN_V(k + 2) = B(2, k + 2) = B(4, k + 0) = B(5, k + 1) = dN(j, 2); - } + auto dN_V = flatten(dN); + auto B = Bmatrix_3d(dN); // Computing the internal forces should have been done first. // dsigma_dev/deps_dev dsigma_dev/dp deps_vol/deps_dev deps_vol/dp - mat->giveStiffnessMatrices(Ed, Ep, Cd, Cp, mode, gp, tStep); - - EdB.beProductOf(Ed, B); - K.plusProductSymmUpper(B, EdB, dV); - G.plusDyadUnsym(dN_V, Nlin, -dV); - C.plusDyadSymmUpper(Nlin, Cp * dV); - - tmpA.beTProductOf(B, Ep); - Dp.plusDyadUnsym(tmpA, Nlin, dV); - - tmpB.beTProductOf(B, Cd); - DvT.plusDyadUnsym(Nlin, tmpB, dV); + //auto [Ed, Ep, Cd, Cp] = mat->computeTangents2D(mode, gp, tStep); + auto tangents = mat->computeTangents3D(mode, gp, tStep); + + K.plusProductSymmUpper(B, dot(tangents.dsdd, B), dA); + G.plusDyadUnsym(dN_V, Nlin, -dA); + Dp.plusDyadUnsym(Tdot(B, tangents.dsdp), Nlin, dA); + DvT.plusDyadUnsym(Nlin, Tdot(B, tangents.dedd), dA); + C.plusDyadSymmUpper(Nlin, tangents.dedp * dA); } K.symmetrized(); C.symmetrized(); - FloatMatrix GTDvT, GDp; - GTDvT.beTranspositionOf(G); - GTDvT.add(DvT); - GDp = G; - GDp.add(Dp); + auto GTDvT = transpose(G) + DvT; + auto GDp = G + Dp; answer.resize(34, 34); answer.zero(); @@ -333,10 +322,6 @@ void Tet21Stokes :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode answer.assemble(GDp, this->momentum_ordering, this->conservation_ordering); answer.assemble(GTDvT, this->conservation_ordering, this->momentum_ordering); answer.assemble(C, this->conservation_ordering); - // K.printYourself(); - // GDp.printYourself(); - // GTDvT.printYourself(); - // C.printYourself(); } FEInterpolation *Tet21Stokes :: giveInterpolation() const @@ -403,8 +388,7 @@ void Tet21Stokes :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answe if ( node <= 4 ) { answer.at(1) = this->giveNode(node)->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep); } else { - IntArray eNodes; - this->interpolation_quad.computeLocalEdgeMapping(eNodes, node - 4); + const auto &eNodes = this->interpolation_quad.computeLocalEdgeMapping(node - 4); answer.at(1) = 0.5 * ( this->giveNode( eNodes.at(1) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) + this->giveNode( eNodes.at(2) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) ); diff --git a/src/fm/tet21stokes.h b/src/fm/tet21stokes.h index f85159b4f..c9f9de811 100644 --- a/src/fm/tet21stokes.h +++ b/src/fm/tet21stokes.h @@ -71,27 +71,26 @@ public EIPrimaryUnknownMapperInterface public: Tet21Stokes(int n, Domain * d); - virtual ~Tet21Stokes(); - virtual void computeGaussPoints(); - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep); + void computeGaussPoints() override; + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override; + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) override; void computeInternalForcesVector(FloatArray &answer, TimeStep *tStep); void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); void computeExternalForcesVector(FloatArray &answer, TimeStep *tStep); - virtual void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true); + void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; + void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true) override; - virtual const char *giveClassName() const { return "Tet21Stokes"; } - virtual const char *giveInputRecordName() const { return _IFT_Tet21Stokes_Name; } - virtual MaterialMode giveMaterialMode() { return _3dFlow; } + const char *giveClassName() const override { return "Tet21Stokes"; } + const char *giveInputRecordName() const override { return _IFT_Tet21Stokes_Name; } + MaterialMode giveMaterialMode() override { return _3dFlow; } - virtual int computeNumberOfDofs(); + int computeNumberOfDofs() override; - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; /** * Gives the dof ID mask for the element. @@ -99,18 +98,18 @@ public EIPrimaryUnknownMapperInterface * @param inode Node to check. * @param answer List of dof IDs. */ - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; // Element interpolation interface: - virtual void EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(ValueModeType u, - TimeStep *tStep, const FloatArray &coords, FloatArray &answer); + void EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(ValueModeType u, + TimeStep *tStep, const FloatArray &coords, FloatArray &answer) override; // Nodal averaging interface: - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; }; } // end namespace oofem #endif // tet21stokes_h diff --git a/src/fm/tr1_2d_cbs.C b/src/fm/tr1_2d_cbs.C index b2820d9d0..64f305763 100644 --- a/src/fm/tr1_2d_cbs.C +++ b/src/fm/tr1_2d_cbs.C @@ -45,7 +45,7 @@ #include "domain.h" #include "mathfem.h" #include "engngm.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fluidcrosssection.h" #include "load.h" #include "timestep.h" @@ -76,12 +76,9 @@ TR1_2D_CBS :: TR1_2D_CBS(int n, Domain *aDomain) : , LEPlicElementInterface() // { - // Constructor. numberOfDofMans = 3; } -TR1_2D_CBS :: ~TR1_2D_CBS() -{ } FEInterpolation * TR1_2D_CBS :: giveInterpolation() const { return & interp; } @@ -99,12 +96,12 @@ TR1_2D_CBS :: giveDofManDofIDMask(int inode, IntArray &answer) const } -IRResultType -TR1_2D_CBS :: initializeFrom(InputRecord *ir) +void +TR1_2D_CBS :: initializeFrom(InputRecord &ir) { - // - IRResultType result; // Required by IR_GIVE_FIELD macro + CBSElement :: initializeFrom(ir); + // this->vof = 0.0; IR_GIVE_OPTIONAL_FIELD(ir, vof, _IFT_Tr1CBS_pvof); if ( vof > 0.0 ) { @@ -117,8 +114,6 @@ TR1_2D_CBS :: initializeFrom(InputRecord *ir) } // - - return CBSElement :: initializeFrom(ir); } @@ -140,7 +135,7 @@ TR1_2D_CBS :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } } @@ -148,13 +143,13 @@ TR1_2D_CBS :: computeGaussPoints() void TR1_2D_CBS :: computeConsistentMassMtrx(FloatMatrix &answer, TimeStep *tStep) { - answer.resize(9, 9); - answer.zero(); double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity( integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); double ar6 = rho * area / 6.0; double ar12 = rho * area / 12.0; + answer.resize(9, 9); + answer.zero(); answer.at(1, 1) = answer.at(2, 2) = ar6; answer.at(4, 4) = answer.at(5, 5) = ar6; answer.at(7, 7) = answer.at(8, 8) = ar6; @@ -172,11 +167,10 @@ TR1_2D_CBS :: computeConsistentMassMtrx(FloatMatrix &answer, TimeStep *tStep) void TR1_2D_CBS :: computeDiagonalMassMtrx(FloatArray &answer, TimeStep *tStep) { - answer.resize(9); - answer.zero(); - double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity( integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); double mm = rho * this->area / 3.0; + answer.resize(9); + answer.zero(); for ( int i = 0; i < 3; i++ ) { answer.at(i * 3 + 1) = mm; answer.at(i * 3 + 2) = mm; @@ -196,8 +190,6 @@ TR1_2D_CBS :: computeConvectionTermsI(FloatArray &answer, TimeStep *tStep) //double rho =static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp); double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity( integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); int nLoads; - bcGeomType ltype; - Load *load; FloatArray gVector; FloatArray u; @@ -251,9 +243,9 @@ TR1_2D_CBS :: computeConvectionTermsI(FloatArray &answer, TimeStep *tStep) // body load (gravity effects) nLoads = this->giveBodyLoadArray()->giveSize(); for ( int i = 1; i <= nLoads; i++ ) { - load = domain->giveLoad( bodyLoadArray.at(i) ); - ltype = load->giveBCGeoType(); - if ( ( ltype == BodyLoadBGT ) && ( load->giveBCValType() == ForceLoadBVT ) ) { + auto load = domain->giveLoad( bodyLoadArray.at(i) ); + auto ltype = load->giveBCGeoType(); + if ( ltype == BodyLoadBGT && load->giveBCValType() == ForceLoadBVT ) { load->computeComponentArrayAt(gVector, tStep, VM_Total); if ( gVector.giveSize() ) { answer.at(1) -= dt * 0.5 * ar3 * ( b [ 0 ] * usum + c [ 0 ] * vsum ) * gVector.at(1); @@ -276,7 +268,7 @@ TR1_2D_CBS :: computeDiffusionTermsI(FloatArray &answer, TimeStep *tStep) FloatArray stress; double Re = static_cast< FluidModel * >( domain->giveEngngModel() )->giveReynoldsNumber(); GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); - double coeff, rho = static_cast< FluidCrossSection* >(this->giveCrossSection())->giveDensity( gp ); + double rho = static_cast< FluidCrossSection* >(this->giveCrossSection())->giveDensity( gp ); FloatArray gVector; double ar3 = area / 3.0; @@ -287,12 +279,12 @@ TR1_2D_CBS :: computeDiffusionTermsI(FloatArray &answer, TimeStep *tStep) answer.resize(9); answer.zero(); for ( int i = 0; i < 3; i++ ) { - answer.at(i * 3 + 1) = -area * ( stress.at(1) * b [ i ] + stress.at(3) * c [ i ] ); - answer.at(i * 3 + 2) = -area * ( stress.at(3) * b [ i ] + stress.at(2) * c [ i ] ); + answer.at(i * 3 + 1) = -area * ( stress.at(1) * b [ i ] + stress.at(6) * c [ i ] ); + answer.at(i * 3 + 2) = -area * ( stress.at(6) * b [ i ] + stress.at(2) * c [ i ] ); } // add boundary termms - coeff = ar3 * rho; + double coeff = ar3 * rho; // body load (gravity effects) int nLoads = this->giveBodyLoadArray()->giveSize(); for ( int i = 1; i <= nLoads; i++ ) { @@ -313,8 +305,6 @@ TR1_2D_CBS :: computeDiffusionTermsI(FloatArray &answer, TimeStep *tStep) // terms now computed even for boundary nodes that have prescribed velocities! (but they will not be localized) // loop over sides - int n1, n2; - double tx, ty, l, nx, ny; nLoads = boundarySides.giveSize(); for ( int j = 1; j <= nLoads; j++ ) { int code = boundaryCodes.at(j); @@ -324,22 +314,21 @@ TR1_2D_CBS :: computeDiffusionTermsI(FloatArray &answer, TimeStep *tStep) //_error("computeDiffusionTermsI: traction bc not supported"); FloatArray t, coords(1); - BoundaryLoad *load; // integrate tractions - n1 = boundarySides.at(j); - n2 = ( n1 == 3 ? 1 : n1 + 1 ); + int n1 = boundarySides.at(j); + int n2 = ( n1 == 3 ? 1 : n1 + 1 ); - tx = giveNode(n2)->giveCoordinate(1) - giveNode(n1)->giveCoordinate(1); - ty = giveNode(n2)->giveCoordinate(2) - giveNode(n1)->giveCoordinate(2); - l = sqrt(tx * tx + ty * ty); - nx = ty / l; - ny = -tx / l; + double tx = giveNode(n2)->giveCoordinate(1) - giveNode(n1)->giveCoordinate(1); + double ty = giveNode(n2)->giveCoordinate(2) - giveNode(n1)->giveCoordinate(2); + double l = sqrt(tx * tx + ty * ty); + double nx = ty / l; + double ny = -tx / l; // loop over boundary load array int numLoads = this->giveBoundaryLoadArray()->giveSize() / 2; for ( int i = 1; i <= numLoads; i++ ) { int n = boundaryLoadArray.at(1 + ( i - 1 ) * 2); - load = dynamic_cast< BoundaryLoad * >( domain->giveLoad(n) ); + auto load = dynamic_cast< BoundaryLoad * >( domain->giveLoad(n) ); if ( load ) { load->computeValueAt(t, tStep, coords, VM_Total); @@ -365,11 +354,11 @@ TR1_2D_CBS :: computeDiffusionTermsI(FloatArray &answer, TimeStep *tStep) * nx = ty/l; ny = -tx/l; * * // normal displacement precribed - * answer.at((n1-1)*3+1)+=l*0.5*(stress.at(1)*nx + stress.at(3)*ny); - * answer.at((n1-1)*3+2)+=l*0.5*(stress.at(3)*nx + stress.at(2)*ny); + * answer.at((n1-1)*3+1)+=l*0.5*(stress.at(1)*nx + stress.at(6)*ny); + * answer.at((n1-1)*3+2)+=l*0.5*(stress.at(6)*nx + stress.at(2)*ny); * - * answer.at((n2-1)*3+1)+=l*0.5*(stress.at(1)*nx + stress.at(3)*ny); - * answer.at((n2-1)*3+2)+=l*0.5*(stress.at(3)*nx + stress.at(2)*ny); + * answer.at((n2-1)*3+1)+=l*0.5*(stress.at(1)*nx + stress.at(6)*ny); + * answer.at((n2-1)*3+2)+=l*0.5*(stress.at(6)*nx + stress.at(2)*ny); * //} */ } @@ -420,24 +409,20 @@ TR1_2D_CBS :: computeDensityRhsVelocityTerms(FloatArray &answer, TimeStep *tStep /* account for normal prescribed velocity on boundary*/ /* on the rest of the boundary the tractions or pressure is prescribed -> to be implemented later */ - int n1, n2; - double tx, ty, l, nx, ny, un1, un2; - // loop over sides - int code; for ( int j = 1; j <= boundarySides.giveSize(); j++ ) { - code = boundaryCodes.at(j); + int code = boundaryCodes.at(j); if ( ( code & FMElement_PrescribedPressureBC ) ) { continue; } else if ( ( code & FMElement_PrescribedUnBC ) ) { this->computeVectorOfPrescribed({V_u, V_v}, VM_Total, tStep, u); - n1 = boundarySides.at(j); - n2 = ( n1 == 3 ? 1 : n1 + 1 ); + int n1 = boundarySides.at(j); + int n2 = ( n1 == 3 ? 1 : n1 + 1 ); //if (giveNode(n1)->isBoundary() && giveNode(n2)->isBoundary()) { - + double tx, ty, l, nx, ny, un1, un2; tx = giveNode(n2)->giveCoordinate(1) - giveNode(n1)->giveCoordinate(1); ty = giveNode(n2)->giveCoordinate(2) - giveNode(n1)->giveCoordinate(2); l = sqrt(tx * tx + ty * ty); @@ -478,20 +463,16 @@ TR1_2D_CBS :: computePrescribedTractionPressure(FloatArray &answer, TimeStep *tS answer.zero(); // loop over sides - int n1, n2, code, sid; - double tx, ty, l, nx, ny, pcoeff; - //IntArray nodecounter (3); for ( int j = 1; j <= boundarySides.giveSize(); j++ ) { - code = boundaryCodes.at(j); - sid = boundarySides.at(j); + int code = boundaryCodes.at(j); + int sid = boundarySides.at(j); if ( ( code & FMElement_PrescribedTractionBC ) ) { FloatArray t, coords(1); - int nLoads, n, id; - BoundaryLoad *load; // integrate tractions - n1 = sid; - n2 = ( n1 == 3 ? 1 : n1 + 1 ); + int n1 = sid; + int n2 = ( n1 == 3 ? 1 : n1 + 1 ); + double tx, ty, l, nx, ny, pcoeff; tx = giveNode(n2)->giveCoordinate(1) - giveNode(n1)->giveCoordinate(1); ty = giveNode(n2)->giveCoordinate(2) - giveNode(n1)->giveCoordinate(2); l = sqrt(tx * tx + ty * ty); @@ -501,7 +482,7 @@ TR1_2D_CBS :: computePrescribedTractionPressure(FloatArray &answer, TimeStep *tS //nodecounter.at(n1)++; //nodecounter.at(n2)++; - pcoeff = stress.at(1) * nx * nx + stress.at(2) * ny * ny + 2.0 * stress.at(3) * nx * ny; + pcoeff = stress.at(1) * nx * nx + stress.at(2) * ny * ny + 2.0 * stress.at(6) * nx * ny; answer.at(n1 * 3) += pcoeff; answer.at(n2 * 3) += pcoeff; @@ -509,15 +490,15 @@ TR1_2D_CBS :: computePrescribedTractionPressure(FloatArray &answer, TimeStep *tS // then zero traction is assumed !!! // loop over boundary load array - nLoads = this->giveBoundaryLoadArray()->giveSize() / 2; + int nLoads = this->giveBoundaryLoadArray()->giveSize() / 2; for ( int i = 1; i <= nLoads; i++ ) { - n = boundaryLoadArray.at(1 + ( i - 1 ) * 2); - id = boundaryLoadArray.at(i * 2); + int n = boundaryLoadArray.at(1 + ( i - 1 ) * 2); + int id = boundaryLoadArray.at(i * 2); if ( id != sid ) { continue; } - load = dynamic_cast< BoundaryLoad * >( domain->giveLoad(n) ); + BoundaryLoad *load = dynamic_cast< BoundaryLoad * >( domain->giveLoad(n) ); if ( load ) { load->computeValueAt(t, tStep, coords, VM_Total); @@ -546,13 +527,11 @@ TR1_2D_CBS :: computeNumberOfNodalPrescribedTractionPressureContributions(FloatA answer.zero(); // loop over sides - int n1, n2, code; - IntArray nodecounter(3); for ( int j = 1; j <= boundarySides.giveSize(); j++ ) { - code = boundaryCodes.at(j); + int code = boundaryCodes.at(j); if ( ( code & FMElement_PrescribedTractionBC ) ) { - n1 = boundarySides.at(j); - n2 = ( n1 == 3 ? 1 : n1 + 1 ); + int n1 = boundarySides.at(j); + int n2 = ( n1 == 3 ? 1 : n1 + 1 ); answer.at(n1 * 3)++; answer.at(n2 * 3)++; } @@ -607,7 +586,7 @@ TR1_2D_CBS :: computeCorrectionRhs(FloatArray &answer, TimeStep *tStep) { //Evaluates the RHS of velocity correction step FloatArray p, u; - double pn1, ar3; + double ar3; double usum, vsum, coeff; @@ -615,7 +594,7 @@ TR1_2D_CBS :: computeCorrectionRhs(FloatArray &answer, TimeStep *tStep) double dpdx = 0.0, dpdy = 0.0; for ( int i = 0; i < 3; i++ ) { - pn1 = p.at(i + 1); + double pn1 = p.at(i + 1); dpdx += b [ i ] * pn1; dpdy += c [ i ] * pn1; } @@ -632,7 +611,7 @@ TR1_2D_CBS :: computeCorrectionRhs(FloatArray &answer, TimeStep *tStep) this->computeVectorOfVelocities(VM_Total, tStep->givePreviousStep(), u); dpdx = 0.0, dpdy = 0.0; for ( int i = 0; i < 3; i++ ) { - pn1 = p.at(i + 1); + double pn1 = p.at(i + 1); dpdx += b [ i ] * pn1; dpdy += c [ i ] * pn1; } @@ -670,7 +649,7 @@ TR1_2D_CBS :: giveInterface(InterfaceType interface) } // - return NULL; + return nullptr; } @@ -678,25 +657,25 @@ void TR1_2D_CBS :: computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { /* one should call material driver instead */ - FloatArray u, eps(3); - + FloatArray u; this->computeVectorOfVelocities(VM_Total, tStep, u); - eps.at(1) = ( b [ 0 ] * u.at(1) + b [ 1 ] * u.at(3) + b [ 2 ] * u.at(5) ); - eps.at(2) = ( c [ 0 ] * u.at(2) + c [ 1 ] * u.at(4) + c [ 2 ] * u.at(6) ); - eps.at(3) = ( b [ 0 ] * u.at(2) + b [ 1 ] * u.at(4) + b [ 2 ] * u.at(6) + c [ 0 ] * u.at(1) + c [ 1 ] * u.at(3) + c [ 2 ] * u.at(5) ); - static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStressVector(answer, gp, eps, tStep); + FloatArrayF<3> eps = { + b [ 0 ] * u.at(1) + b [ 1 ] * u.at(3) + b [ 2 ] * u.at(5), + c [ 0 ] * u.at(2) + c [ 1 ] * u.at(4) + c [ 2 ] * u.at(6), + b [ 0 ] * u.at(2) + b [ 1 ] * u.at(4) + b [ 2 ] * u.at(6) + c [ 0 ] * u.at(1) + c [ 1 ] * u.at(3) + c [ 2 ] * u.at(5), + }; + answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStress2D(eps, gp, tStep); } int TR1_2D_CBS :: checkConsistency() { - Node *node1, *node2, *node3; double x1, x2, x3, y1, y2, y3; - node1 = giveNode(1); - node2 = giveNode(2); - node3 = giveNode(3); + auto node1 = giveNode(1); + auto node2 = giveNode(2); + auto node3 = giveNode(3); // init geometry data x1 = node1->giveCoordinate(1); @@ -723,7 +702,6 @@ double TR1_2D_CBS :: computeCriticalTimeStep(TimeStep *tStep) { FloatArray u; - double dt1, dt2, dt; double Re = static_cast< FluidModel * >( domain->giveEngngModel() )->giveReynoldsNumber(); this->computeVectorOfVelocities(VM_Total, tStep, u); @@ -740,9 +718,10 @@ TR1_2D_CBS :: computeCriticalTimeStep(TimeStep *tStep) double ln = min( l1, min(l2, l3) ); // viscous limit - dt2 = 0.5 * ln * ln * Re; + double dt; + double dt2 = 0.5 * ln * ln * Re; if ( veln != 0.0 ) { - dt1 = ln / veln; + double dt1 = ln / veln; dt = dt1 * dt2 / ( dt1 + dt2 ); } else { dt = dt2; @@ -770,7 +749,6 @@ void TR1_2D_CBS :: formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface, const FloatArray &normal, const double p, bool updFlag) { - double x, y; Vertex v; matvolpoly.clear(); @@ -779,6 +757,7 @@ TR1_2D_CBS :: formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface, return; } else if ( this->vof >= ( 1 - TRSUPG_ZERO_VOF ) ) { for ( int i = 1; i <= 3; i++ ) { + double x, y; if ( updFlag ) { x = matInterface->giveUpdatedXCoordinate( this->giveNode(i)->giveNumber() ); y = matInterface->giveUpdatedYCoordinate( this->giveNode(i)->giveNumber() ); @@ -927,12 +906,12 @@ TR1_2D_CBS :: truncateMatVolume(const Polygon &matvolpoly, double &volume) void TR1_2D_CBS :: formMyVolumePoly(Polygon &me, LEPlic *matInterface, bool updFlag) { - double x, y; Vertex v; me.clear(); for ( int i = 1; i <= 3; i++ ) { + double x, y; if ( updFlag ) { x = matInterface->giveUpdatedXCoordinate( this->giveNode(i)->giveNumber() ); y = matInterface->giveUpdatedYCoordinate( this->giveNode(i)->giveNumber() ); @@ -950,8 +929,8 @@ TR1_2D_CBS :: formMyVolumePoly(Polygon &me, LEPlic *matInterface, bool updFlag) double TR1_2D_CBS :: computeMyVolume(LEPlic *matInterface, bool updFlag) { - double x1, x2, x3, y1, y2, y3; if ( updFlag ) { + double x1, x2, x3, y1, y2, y3; x1 = matInterface->giveUpdatedXCoordinate( this->giveNode(1)->giveNumber() ); x2 = matInterface->giveUpdatedXCoordinate( this->giveNode(2)->giveNumber() ); x3 = matInterface->giveUpdatedXCoordinate( this->giveNode(3)->giveNumber() ); @@ -1122,51 +1101,21 @@ TR1_2D_CBS :: printOutputAt(FILE *file, TimeStep *tStep) -contextIOResultType TR1_2D_CBS :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full element context (saves state variables, that completely describe -// current state) -// +void TR1_2D_CBS :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = CBSElement :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - + CBSElement :: saveContext(stream, mode); // - if ( ( iores = LEPlicElementInterface :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - + LEPlicElementInterface :: saveContext(stream, mode); // - - return CIO_OK; } - -contextIOResultType TR1_2D_CBS :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full element context (saves state variables, that completely describe -// current state) -// +void TR1_2D_CBS :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = CBSElement :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - + CBSElement :: restoreContext(stream, mode); // - if ( ( iores = LEPlicElementInterface :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - + LEPlicElementInterface :: restoreContext(stream, mode); // - - - return CIO_OK; } diff --git a/src/fm/tr1_2d_cbs.h b/src/fm/tr1_2d_cbs.h index d55a29d6d..efa5302d4 100644 --- a/src/fm/tr1_2d_cbs.h +++ b/src/fm/tr1_2d_cbs.h @@ -78,85 +78,84 @@ public ZZNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterfac //double a[3]; double b [ 3 ]; double c [ 3 ]; - double area; + double area = 0.; public: TR1_2D_CBS(int n, Domain * aDomain); - virtual ~TR1_2D_CBS(); - - virtual FEInterpolation *giveInterpolation() const; - - virtual void computeConsistentMassMtrx(FloatMatrix &answer, TimeStep *); - virtual void computeDiagonalMassMtrx(FloatArray &answer, TimeStep *); - virtual void computeConvectionTermsI(FloatArray &answer, TimeStep *); - virtual void computeDiffusionTermsI(FloatArray &answer, TimeStep *); - virtual void computeDensityRhsVelocityTerms(FloatArray &answer, TimeStep *tStep); - virtual void computeDensityRhsPressureTerms(FloatArray &answer, TimeStep *tStep); - virtual void computePrescribedTractionPressure(FloatArray &answer, TimeStep *tStep); - virtual void computeNumberOfNodalPrescribedTractionPressureContributions(FloatArray &answer, TimeStep *tStep); - virtual void computePressureLhs(FloatMatrix &answer, TimeStep *tStep); - virtual void computeCorrectionRhs(FloatArray &answer, TimeStep *tStep); - virtual double computeCriticalTimeStep(TimeStep *tStep); + + FEInterpolation *giveInterpolation() const override; + + void computeConsistentMassMtrx(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiagonalMassMtrx(FloatArray &answer, TimeStep *tStep) override; + void computeConvectionTermsI(FloatArray &answer, TimeStep *tStep) override; + void computeDiffusionTermsI(FloatArray &answer, TimeStep *tStep) override; + void computeDensityRhsVelocityTerms(FloatArray &answer, TimeStep *tStep) override; + void computeDensityRhsPressureTerms(FloatArray &answer, TimeStep *tStep) override; + void computePrescribedTractionPressure(FloatArray &answer, TimeStep *tStep) override; + void computeNumberOfNodalPrescribedTractionPressureContributions(FloatArray &answer, TimeStep *tStep) override; + void computePressureLhs(FloatMatrix &answer, TimeStep *tStep) override; + void computeCorrectionRhs(FloatArray &answer, TimeStep *tStep) override; + double computeCriticalTimeStep(TimeStep *tStep) override; // definition - virtual const char *giveClassName() const { return "TR1_2D_CBS"; } - virtual const char *giveInputRecordName() const { return _IFT_TR1_2D_CBS_Name; } - virtual MaterialMode giveMaterialMode() { return _2dFlow; } - - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual int computeNumberOfDofs(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void updateYourself(TimeStep *tStep); + const char *giveClassName() const override { return "TR1_2D_CBS"; } + const char *giveInputRecordName() const override { return _IFT_TR1_2D_CBS_Name; } + MaterialMode giveMaterialMode() override { return _2dFlow; } + + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + int computeNumberOfDofs() override; + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void updateYourself(TimeStep *tStep) override; /// Used to check consistency and initialize some element geometry data (area,b,c) - virtual int checkConsistency(); + int checkConsistency() override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; - virtual int EIPrimaryFieldI_evaluateFieldVectorAt(FloatArray &answer, PrimaryField &pf, - const FloatArray &coords, IntArray &dofId, ValueModeType mode, - TimeStep *tStep); + int EIPrimaryFieldI_evaluateFieldVectorAt(FloatArray &answer, PrimaryField &pf, + const FloatArray &coords, IntArray &dofId, ValueModeType mode, + TimeStep *tStep) override; // - virtual double computeLEPLICVolumeFraction(const FloatArray &n, const double p, LEPlic *matInterface, bool updFlag); - virtual void formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface, - const FloatArray &normal, const double p, bool updFlag); - virtual void formVolumeInterfacePoly(Polygon &matvolpoly, LEPlic *matInterface, - const FloatArray &normal, const double p, bool updFlag); - virtual double truncateMatVolume(const Polygon &matvolpoly, double &volume); - virtual void giveElementCenter(LEPlic *mat_interface, FloatArray ¢er, bool upd); - virtual void formMyVolumePoly(Polygon &myPoly, LEPlic *mat_interface, bool updFlag); - virtual Element *giveElement() { return this; } - virtual double computeMyVolume(LEPlic *matInterface, bool updFlag); - virtual double computeCriticalLEPlicTimeStep(TimeStep *tStep) { return 1.e6; } + double computeLEPLICVolumeFraction(const FloatArray &n, const double p, LEPlic *matInterface, bool updFlag) override; + void formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface, + const FloatArray &normal, const double p, bool updFlag) override; + void formVolumeInterfacePoly(Polygon &matvolpoly, LEPlic *matInterface, + const FloatArray &normal, const double p, bool updFlag) override; + double truncateMatVolume(const Polygon &matvolpoly, double &volume) override; + void giveElementCenter(LEPlic *mat_interface, FloatArray ¢er, bool upd) override; + void formMyVolumePoly(Polygon &myPoly, LEPlic *mat_interface, bool updFlag) override; + Element *giveElement() override { return this; } + double computeMyVolume(LEPlic *matInterface, bool updFlag) override; + double computeCriticalLEPlicTimeStep(TimeStep *tStep) override { return 1.e6; } // - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) override; #ifdef __OOFEG int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *tStep); + int node, TimeStep *tStep) override; // Graphics output - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - //virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) {} + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override {} #endif protected: - virtual void computeGaussPoints(); - virtual void computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeGaussPoints() override; + void computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; }; } // end namespace oofem #endif // tr1_2d_cbs_h diff --git a/src/fm/tr1_2d_supg.C b/src/fm/tr1_2d_supg.C index 6b5e9402c..a48e8468e 100644 --- a/src/fm/tr1_2d_supg.C +++ b/src/fm/tr1_2d_supg.C @@ -45,7 +45,7 @@ #include "domain.h" #include "mathfem.h" #include "engngm.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fluidcrosssection.h" #include "load.h" #include "timestep.h" @@ -76,9 +76,6 @@ TR1_2D_SUPG :: TR1_2D_SUPG(int n, Domain *aDomain) : numberOfDofMans = 3; } -TR1_2D_SUPG :: ~TR1_2D_SUPG() -{ } - int TR1_2D_SUPG :: computeNumberOfDofs() { @@ -94,10 +91,10 @@ TR1_2D_SUPG :: giveDofManDofIDMask(int inode, IntArray &answer) const FEInterpolation * TR1_2D_SUPG :: giveInterpolation() const { return & interp; } -IRResultType -TR1_2D_SUPG :: initializeFrom(InputRecord *ir) +void +TR1_2D_SUPG :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + SUPGElement :: initializeFrom(ir); this->vof = 0.0; IR_GIVE_OPTIONAL_FIELD(ir, vof, _IFT_Tr1SUPG_pvof); @@ -110,12 +107,8 @@ TR1_2D_SUPG :: initializeFrom(InputRecord *ir) this->temp_vof = this->vof; } - result = SUPGElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + this->initGeometry(); - return IRRT_OK; } @@ -137,7 +130,7 @@ TR1_2D_SUPG :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } } @@ -322,19 +315,18 @@ TR1_2D_SUPG :: computeAdvectionDerivativeTerm_MB(FloatMatrix &answer, TimeStep * void TR1_2D_SUPG :: computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) { - answer.resize(6); - answer.zero(); - FloatArray u, eps(3), stress; double Re = static_cast< FluidModel * >( domain->giveEngngModel() )->giveReynoldsNumber(); + FloatArray u; this->computeVectorOfVelocities(VM_Total, tStep, u); - eps.at(1) = ( b [ 0 ] * u.at(1) + b [ 1 ] * u.at(3) + b [ 2 ] * u.at(5) ); - eps.at(2) = ( c [ 0 ] * u.at(2) + c [ 1 ] * u.at(4) + c [ 2 ] * u.at(6) ); - eps.at(3) = ( b [ 0 ] * u.at(2) + b [ 1 ] * u.at(4) + b [ 2 ] * u.at(6) + c [ 0 ] * u.at(1) + c [ 1 ] * u.at(3) + c [ 2 ] * u.at(5) ); - static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStressVector( - stress, integrationRulesArray [ 0 ]->getIntegrationPoint(0), eps, tStep); - stress.times(1. / Re); + FloatArrayF<3> eps = { + b [ 0 ] * u.at(1) + b [ 1 ] * u.at(3) + b [ 2 ] * u.at(5), + c [ 0 ] * u.at(2) + c [ 1 ] * u.at(4) + c [ 2 ] * u.at(6), + b [ 0 ] * u.at(2) + b [ 1 ] * u.at(4) + b [ 2 ] * u.at(6) + c [ 0 ] * u.at(1) + c [ 1 ] * u.at(3) + c [ 2 ] * u.at(5), + }; + auto stress = (1. / Re) * static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStress2D( + eps, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); // \int dNu/dxj \Tau_ij answer.resize(6); @@ -372,8 +364,8 @@ TR1_2D_SUPG :: computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatRespons _b.at(3, 5) = c [ 2 ]; _b.at(3, 6) = b [ 2 ]; - static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->giveDeviatoricStiffnessMatrix( - _d, mode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + _d = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeTangent2D( + mode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); _db.beProductOf(_d, _b); answer.resize(6, 6); answer.zero(); @@ -1986,46 +1978,17 @@ TR1_2D_SUPG :: printOutputAt(FILE *file, TimeStep *tStep) } - -contextIOResultType TR1_2D_SUPG :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full element context (saves state variables, that completely describe -// current state) -// +void TR1_2D_SUPG :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = SUPGElement :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = LEPlicElementInterface :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + SUPGElement :: saveContext(stream, mode); + LEPlicElementInterface :: saveContext(stream, mode); } - -contextIOResultType TR1_2D_SUPG :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full element context (saves state variables, that completely describe -// current state) -// +void TR1_2D_SUPG :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = SUPGElement :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = LEPlicElementInterface :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - - return CIO_OK; + SUPGElement :: restoreContext(stream, mode); + LEPlicElementInterface :: restoreContext(stream, mode); } @@ -2119,12 +2082,12 @@ TR1_2D_SUPG :: LS_PCS_computeS(LevelSetPCS *ls, TimeStep *tStep) int prev_node = ( si > 1 ) ? si - 1 : 3; int next_node = ( si < 3 ) ? si + 1 : 1; - //double l = this->giveNode(si)->giveCoordinates()->distance(this->giveNode(next_node)->giveCoordinates()); + //double l = distance( *this->giveNode(si)->giveCoordinates(), *this->giveNode(next_node)->giveCoordinates() ); double t = fi.at(si) / ( fi.at(si) - fi.at(next_node) ); x2 = x1 + t * ( this->giveNode(next_node)->giveCoordinate(1) - x1 ); y2 = y1 + t * ( this->giveNode(next_node)->giveCoordinate(2) - y1 ); - //l = this->giveNode(si)->giveCoordinates()->distance(this->giveNode(prev_node)->giveCoordinates()); + //l = distance( this->giveNode(si)->giveCoordinates(), *this->giveNode(prev_node)->giveCoordinates() ); t = fi.at(si) / ( fi.at(si) - fi.at(prev_node) ); x3 = x1 + t * ( this->giveNode(prev_node)->giveCoordinate(1) - x1 ); y3 = y1 + t * ( this->giveNode(prev_node)->giveCoordinate(2) - y1 ); @@ -2263,6 +2226,19 @@ TR1_2D_SUPG :: giveLocalPressureDofMap(IntArray &map) } +void +TR1_2D_SUPG :: computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStress2D(eps, gp, tStep); +} + +void +TR1_2D_SUPG :: computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeTangent2D(mode, gp, tStep); +} + + #ifdef __OOFEG int TR1_2D_SUPG :: giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, diff --git a/src/fm/tr1_2d_supg.h b/src/fm/tr1_2d_supg.h index 694710d11..9b29b8577 100644 --- a/src/fm/tr1_2d_supg.h +++ b/src/fm/tr1_2d_supg.h @@ -76,118 +76,119 @@ public LEPlicElementInterface, public LevelSetPCSElementInterface //double a[3]; double b [ 3 ]; double c [ 3 ]; - double area; + double area = 0.; public: TR1_2D_SUPG(int n, Domain * d); - virtual ~TR1_2D_SUPG(); - - virtual FEInterpolation *giveInterpolation() const; - - virtual void computeAccelerationTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeAdvectionDerivativeTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); - virtual void computePressureTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLSICStabilizationTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLinearAdvectionTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionTerm_MC(FloatArray &answer, TimeStep *tStep); - virtual void computeAdvectionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) { + + FEInterpolation *giveInterpolation() const override; + + void computeAccelerationTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeAdvectionTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeAdvectionDerivativeTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) override; + void computePressureTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeLSICStabilizationTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeLinearAdvectionTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeAdvectionTerm_MC(FloatArray &answer, TimeStep *tStep) override; + void computeAdvectionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) override { answer.resize(3, 6); answer.zero(); } - virtual void computeDiffusionTerm_MC(FloatArray &answer, TimeStep *tStep) { + void computeDiffusionTerm_MC(FloatArray &answer, TimeStep *tStep) override { answer.resize(3); answer.zero(); } - virtual void computeAccelerationTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computePressureTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeBCRhsTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeBCRhsTerm_MC(FloatArray &answer, TimeStep *tStep); - virtual void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); + void computeAccelerationTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computePressureTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeBCRhsTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeBCRhsTerm_MC(FloatArray &answer, TimeStep *tStep) override; + void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; - virtual void computeSlipWithFrictionBCTerm_MB(FloatMatrix &answer, Load *load, int side, TimeStep *tStep); - virtual void computePenetrationWithResistanceBCTerm_MB(FloatMatrix &answer, Load *load, int side, TimeStep *tStep); - virtual void computeOutFlowBCTerm_MB(FloatMatrix &answer, int side, TimeStep *tStep); + void computeSlipWithFrictionBCTerm_MB(FloatMatrix &answer, Load *load, int side, TimeStep *tStep) override; + void computePenetrationWithResistanceBCTerm_MB(FloatMatrix &answer, Load *load, int side, TimeStep *tStep) override; + void computeOutFlowBCTerm_MB(FloatMatrix &answer, int side, TimeStep *tStep) override; - virtual void computeHomogenizedReinforceTerm_MB(FloatMatrix &answer, Load *load, TimeStep *tStep); - virtual void computeHomogenizedReinforceTerm_MC(FloatMatrix &answer, Load *load, TimeStep *tStep); + void computeHomogenizedReinforceTerm_MB(FloatMatrix &answer, Load *load, TimeStep *tStep) override; + void computeHomogenizedReinforceTerm_MC(FloatMatrix &answer, Load *load, TimeStep *tStep) override; - virtual void updateStabilizationCoeffs(TimeStep *tStep); - virtual double computeCriticalTimeStep(TimeStep *tStep); + void updateStabilizationCoeffs(TimeStep *tStep) override; + double computeCriticalTimeStep(TimeStep *tStep) override; // definition - virtual const char *giveClassName() const { return "TR1_2D_SUPG"; } - virtual const char *giveInputRecordName() const { return _IFT_TR1_2D_SUPG_Name; } - virtual MaterialMode giveMaterialMode() { return _2dFlow; } - - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual int computeNumberOfDofs(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void updateYourself(TimeStep *tStep); + const char *giveClassName() const override { return "TR1_2D_SUPG"; } + const char *giveInputRecordName() const override { return _IFT_TR1_2D_SUPG_Name; } + MaterialMode giveMaterialMode() override { return _2dFlow; } + + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + int computeNumberOfDofs() override; + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void updateYourself(TimeStep *tStep) override; /// Used to check consistency and initialize some element geometry data (area,b,c). - virtual int checkConsistency(); - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - - virtual Interface *giveInterface(InterfaceType); - - virtual int EIPrimaryFieldI_evaluateFieldVectorAt(FloatArray &answer, PrimaryField &pf, - const FloatArray &coords, IntArray &dofId, ValueModeType mode, - TimeStep *tStep); - - virtual double computeLEPLICVolumeFraction(const FloatArray &n, const double p, LEPlic *matInterface, bool updFlag); - virtual void formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface, - const FloatArray &normal, const double p, bool updFlag); - virtual void formVolumeInterfacePoly(Polygon &matvolpoly, LEPlic *matInterface, - const FloatArray &normal, const double p, bool updFlag); - virtual double truncateMatVolume(const Polygon &matvolpoly, double &volume); - virtual void giveElementCenter(LEPlic *mat_interface, FloatArray ¢er, bool updFlag); - virtual void formMyVolumePoly(Polygon &myPoly, LEPlic *mat_interface, bool updFlag); - virtual Element *giveElement() { return this; } - virtual double computeMyVolume(LEPlic *matInterface, bool updFlag); - virtual double computeVolumeAround(GaussPoint *gp); - virtual double computeCriticalLEPlicTimeStep(TimeStep *tStep); - - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); - - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); - - virtual double LS_PCS_computeF(LevelSetPCS *ls, TimeStep *tStep); - virtual void LS_PCS_computedN(FloatMatrix &answer); - virtual double LS_PCS_computeVolume() { return area; } - virtual double LS_PCS_computeS(LevelSetPCS *ls, TimeStep *tStep); - virtual void LS_PCS_computeVOFFractions(FloatArray &answer, FloatArray &fi); - - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int checkConsistency() override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + + Interface *giveInterface(InterfaceType) override; + + int EIPrimaryFieldI_evaluateFieldVectorAt(FloatArray &answer, PrimaryField &pf, + const FloatArray &coords, IntArray &dofId, ValueModeType mode, + TimeStep *tStep) override; + + double computeLEPLICVolumeFraction(const FloatArray &n, const double p, LEPlic *matInterface, bool updFlag) override; + void formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface, + const FloatArray &normal, const double p, bool updFlag) override; + void formVolumeInterfacePoly(Polygon &matvolpoly, LEPlic *matInterface, + const FloatArray &normal, const double p, bool updFlag) override; + double truncateMatVolume(const Polygon &matvolpoly, double &volume) override; + void giveElementCenter(LEPlic *mat_interface, FloatArray ¢er, bool updFlag) override; + void formMyVolumePoly(Polygon &myPoly, LEPlic *mat_interface, bool updFlag) override; + Element *giveElement() override { return this; } + double computeMyVolume(LEPlic *matInterface, bool updFlag) override; + double computeVolumeAround(GaussPoint *gp) override; + double computeCriticalLEPlicTimeStep(TimeStep *tStep) override; + + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; + + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; + + double LS_PCS_computeF(LevelSetPCS *ls, TimeStep *tStep) override; + void LS_PCS_computedN(FloatMatrix &answer) override; + double LS_PCS_computeVolume() override { return area; } + double LS_PCS_computeS(LevelSetPCS *ls, TimeStep *tStep) override; + void LS_PCS_computeVOFFractions(FloatArray &answer, FloatArray &fi) override; + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; #ifdef __OOFEG int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *tStep); + int node, TimeStep *tStep) override; // Graphics output - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - //virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) {} + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override {} #endif - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; protected: - virtual void giveLocalVelocityDofMap(IntArray &map); - virtual void giveLocalPressureDofMap(IntArray &map); + void giveLocalVelocityDofMap(IntArray &map) override; + void giveLocalPressureDofMap(IntArray &map) override; void computeNMtrx(FloatArray &answer, GaussPoint *gp); - virtual void computeGaussPoints(); + void computeGaussPoints() override; - virtual void computeDeviatoricStrain(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeDeviatoricStrain(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; + void computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) override; + void computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; virtual void initGeometry(); }; } // end namespace oofem diff --git a/src/fm/tr1_2d_supg2.C b/src/fm/tr1_2d_supg2.C index 16e3eebdc..2509ba60c 100644 --- a/src/fm/tr1_2d_supg2.C +++ b/src/fm/tr1_2d_supg2.C @@ -44,7 +44,7 @@ #include "domain.h" #include "mathfem.h" #include "engngm.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fluidcrosssection.h" #include "load.h" #include "timestep.h" @@ -75,10 +75,6 @@ TR1_2D_SUPG2 :: TR1_2D_SUPG2(int n, Domain *aDomain) : numberOfDofMans = 3; } -TR1_2D_SUPG2 :: ~TR1_2D_SUPG2() -{ -} - void TR1_2D_SUPG2 :: computeNVector(FloatArray &answer, GaussPoint *gp) @@ -99,16 +95,10 @@ TR1_2D_SUPG2 :: giveDofManDofIDMask(int inode, IntArray &answer) const answer = {V_u, V_v, P_f}; } -IRResultType -TR1_2D_SUPG2 :: initializeFrom(InputRecord *ir) +void +TR1_2D_SUPG2 :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = SUPGElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - + SUPGElement :: initializeFrom(ir); this->vof = 0.0; IR_GIVE_OPTIONAL_FIELD(ir, vof, _IFT_Tr1SUPG_pvof); @@ -125,8 +115,6 @@ TR1_2D_SUPG2 :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, mat [ 0 ], _IFT_Tr1SUPG2_mat0); IR_GIVE_OPTIONAL_FIELD(ir, mat [ 1 ], _IFT_Tr1SUPG2_mat1); this->material = this->mat [ 0 ]; - - return IRRT_OK; } @@ -160,11 +148,11 @@ TR1_2D_SUPG2 :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(2); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3, true) ); - integrationRulesArray [ 1 ].reset( new GaussIntegrationRule(2, this, 1, 3, true) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3, true); + integrationRulesArray [ 1 ] = std::make_unique(2, this, 1, 3, true); } if ( !defaultIRule ) { - defaultIRule.reset( new GaussIntegrationRule(1, this, 1, 3, true) ); + defaultIRule = std::make_unique(1, this, 1, 3, true); this->giveCrossSection()->setupIntegrationPoints(* defaultIRule, 1, this); } } @@ -450,7 +438,7 @@ TR1_2D_SUPG2 :: computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) answer.resize(6); answer.zero(); FloatArray u, eps(3), stress; - double dV, Re = static_cast< FluidModel * >( domain->giveEngngModel() )->giveReynoldsNumber(); + double Re = static_cast< FluidModel * >( domain->giveEngngModel() )->giveReynoldsNumber(); //double dudx,dudy,dvdx,dvdy; this->computeVectorOfVelocities(VM_Total, tStep, u); @@ -469,11 +457,10 @@ TR1_2D_SUPG2 :: computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) for ( int ifluid = 0; ifluid < 2; ifluid++ ) { FluidDynamicMaterial *mat = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(ifluid) ); - for ( GaussPoint *gp: *integrationRulesArray [ ifluid ] ) { - dV = this->computeVolumeAroundID(gp, id [ ifluid ], vcoords [ ifluid ]); + for ( auto &gp: *integrationRulesArray [ ifluid ] ) { + double dV = this->computeVolumeAroundID(gp, id [ ifluid ], vcoords [ ifluid ]); - mat->computeDeviatoricStressVector(stress, gp, eps, tStep); - stress.times(1. / Re); + stress = (1. / Re) * mat->computeDeviatoricStress2D(eps, gp, tStep); // \int dNu/dxj \Tau_ij for ( int i = 0; i < 3; i++ ) { @@ -510,7 +497,6 @@ TR1_2D_SUPG2 :: computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) void TR1_2D_SUPG2 :: computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) { - double dV; //double dudx, dudy, dvdx, dvdy; answer.resize(6, 6); answer.zero(); @@ -554,11 +540,10 @@ TR1_2D_SUPG2 :: computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatRespon for ( int ifluid = 0; ifluid < 2; ifluid++ ) { FluidDynamicMaterial *mat = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(ifluid) ); - for ( GaussPoint *gp: *integrationRulesArray [ ifluid ] ) { - dV = this->computeVolumeAroundID(gp, id [ ifluid ], vcoords [ ifluid ]); + for ( auto &gp: *integrationRulesArray [ ifluid ] ) { + double dV = this->computeVolumeAroundID(gp, id [ ifluid ], vcoords [ ifluid ]); - - mat->giveDeviatoricStiffnessMatrix(_d, mode, gp, tStep); + _d = mat->computeTangent2D(mode, gp, tStep); _db.beProductOf(_d, _b); answer.plusProductSymmUpper(_b, _db, dV); //answer.plusProductSymmUpper (_bs,_db,dV*t_supg); @@ -1195,25 +1180,27 @@ TR1_2D_SUPG2 :: giveInterface(InterfaceType interface) return static_cast< LEPlicElementInterface * >(this); } - return NULL; + return nullptr; } void -TR1_2D_SUPG2 :: computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +TR1_2D_SUPG2 :: computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) { /* one computes here average deviatoric stress, based on rule of mixture (this is used only for postprocessing) */ - FloatArray eps, s0, s1; - answer.resize(3); + auto s0 = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(0) )->computeDeviatoricStress2D(eps, gp, tStep); + auto s1 = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(1) )->computeDeviatoricStress2D(eps, gp, tStep); - this->computeDeviatoricStrain(eps, gp, tStep); + answer = temp_vof * s0 + ( 1. - temp_vof ) * s1; +} - static_cast< FluidDynamicMaterial * >( this->_giveMaterial(0) )->computeDeviatoricStressVector(s0, gp, eps, tStep); - static_cast< FluidDynamicMaterial * >( this->_giveMaterial(1) )->computeDeviatoricStressVector(s1, gp, eps, tStep); +void +TR1_2D_SUPG2 :: computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + auto t0 = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(0) )->computeTangent2D(mode, gp, tStep); + auto t1 = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(1) )->computeTangent2D(mode, gp, tStep); - for ( int i = 1; i <= 3; i++ ) { - answer.at(i) = ( temp_vof ) * s0.at(i) + ( 1. - temp_vof ) * s1.at(i); - } + answer = temp_vof * t0 + (1. - temp_vof) * t1; } @@ -1864,50 +1851,20 @@ TR1_2D_SUPG2 :: printOutputAt(FILE *file, TimeStep *tStep) } -contextIOResultType TR1_2D_SUPG2 :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full element context (saves state variables, that completely describe -// current state) -// +void TR1_2D_SUPG2 :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = SUPGElement :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = LEPlicElementInterface :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + SUPGElement :: saveContext(stream, mode); + LEPlicElementInterface :: saveContext(stream, mode); } - -contextIOResultType TR1_2D_SUPG2 :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full element context (saves state variables, that completely describe -// current state) -// +void TR1_2D_SUPG2 :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = SUPGElement :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = LEPlicElementInterface :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - - return CIO_OK; + SUPGElement :: restoreContext(stream, mode); + LEPlicElementInterface :: restoreContext(stream, mode); } - - #ifdef __OOFEG int TR1_2D_SUPG2 :: giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, diff --git a/src/fm/tr1_2d_supg2.h b/src/fm/tr1_2d_supg2.h index 53d980eec..a1fe6e368 100644 --- a/src/fm/tr1_2d_supg2.h +++ b/src/fm/tr1_2d_supg2.h @@ -86,97 +86,97 @@ class TR1_2D_SUPG2 : public TR1_2D_SUPG public: TR1_2D_SUPG2(int n, Domain * d); - virtual ~TR1_2D_SUPG2(); - - virtual void computeAccelerationTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeAdvectionDerivativeTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); - virtual void computePressureTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLSICStabilizationTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLinearAdvectionTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionTerm_MC(FloatArray &answer, TimeStep *tStep); - virtual void computeAdvectionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) { + + void computeAccelerationTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeAdvectionTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeAdvectionDerivativeTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) override; + void computePressureTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeLSICStabilizationTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeLinearAdvectionTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeAdvectionTerm_MC(FloatArray &answer, TimeStep *tStep) override; + void computeAdvectionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) override { answer.resize(3, 6); answer.zero(); } - virtual void computeDiffusionTerm_MC(FloatArray &answer, TimeStep *tStep) { + void computeDiffusionTerm_MC(FloatArray &answer, TimeStep *tStep) override { answer.resize(3); answer.zero(); } - virtual void computeAccelerationTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computePressureTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeBCRhsTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeBCRhsTerm_MC(FloatArray &answer, TimeStep *tStep); + void computeAccelerationTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computePressureTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeBCRhsTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeBCRhsTerm_MC(FloatArray &answer, TimeStep *tStep) override; - virtual void updateStabilizationCoeffs(TimeStep *tStep); - virtual void updateElementForNewInterfacePosition(TimeStep *tStep) { this->updateIntegrationRules(); } - virtual double computeCriticalTimeStep(TimeStep *tStep); + void updateStabilizationCoeffs(TimeStep *tStep) override; + void updateElementForNewInterfacePosition(TimeStep *tStep) override { this->updateIntegrationRules(); } + double computeCriticalTimeStep(TimeStep *tStep) override; // definition - virtual const char *giveClassName() const { return "TR1_2D_SUPG2"; } - virtual const char *giveInputRecordName() const { return _IFT_TR1_2D_SUPG2_Name; } + const char *giveClassName() const override { return "TR1_2D_SUPG2"; } + const char *giveInputRecordName() const override { return _IFT_TR1_2D_SUPG2_Name; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual int computeNumberOfDofs(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void updateYourself(TimeStep *tStep); + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + int computeNumberOfDofs() override; + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; - virtual int EIPrimaryFieldI_evaluateFieldVectorAt(FloatArray &answer, PrimaryField &pf, - const FloatArray &coords, IntArray &dofId, ValueModeType mode, - TimeStep *tStep); + int EIPrimaryFieldI_evaluateFieldVectorAt(FloatArray &answer, PrimaryField &pf, + const FloatArray &coords, IntArray &dofId, ValueModeType mode, + TimeStep *tStep) override; - virtual double computeLEPLICVolumeFraction(const FloatArray &n, const double p, LEPlic *matInterface, bool updFlag); - virtual void formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface, - const FloatArray &normal, const double p, bool updFlag); - virtual void formVolumeInterfacePoly(Polygon &matvolpoly, LEPlic *matInterface, - const FloatArray &normal, const double p, bool updFlag); - virtual double truncateMatVolume(const Polygon &matvolpoly, double &volume); - virtual void giveElementCenter(LEPlic *mat_interface, FloatArray ¢er, bool updFlag); - virtual void formMyVolumePoly(Polygon &myPoly, LEPlic *mat_interface, bool updFlag); - virtual Element *giveElement() { return this; } - virtual double computeMyVolume(LEPlic *matInterface, bool updFlag); + double computeLEPLICVolumeFraction(const FloatArray &n, const double p, LEPlic *matInterface, bool updFlag) override; + void formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface, + const FloatArray &normal, const double p, bool updFlag) override; + void formVolumeInterfacePoly(Polygon &matvolpoly, LEPlic *matInterface, + const FloatArray &normal, const double p, bool updFlag) override; + double truncateMatVolume(const Polygon &matvolpoly, double &volume) override; + void giveElementCenter(LEPlic *mat_interface, FloatArray ¢er, bool updFlag) override; + void formMyVolumePoly(Polygon &myPoly, LEPlic *mat_interface, bool updFlag) override; + Element *giveElement() override { return this; } + double computeMyVolume(LEPlic *matInterface, bool updFlag) override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual int giveDefaultIntegrationRule() const { return 0; } - virtual IntegrationRule *giveDefaultIntegrationRulePtr() { return defaultIRule.get(); } + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + int giveDefaultIntegrationRule() const override { return 0; } + IntegrationRule *giveDefaultIntegrationRulePtr() override { return defaultIRule.get(); } #ifdef __OOFEG int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *tStep); + int node, TimeStep *tStep) override; // Graphics output - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - //virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) {} + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override {} #endif - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; protected: - virtual void computeGaussPoints(); - virtual void postInitialize(); - virtual void computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *); + void computeGaussPoints() override; + void postInitialize() override; + void computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) override; + void computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; void computeNVector(FloatArray &answer, GaussPoint *gp); - virtual void updateVolumePolygons(Polygon &referenceFluidPoly, Polygon &secondFluidPoly, int &rfPoints, int &sfPoints, - const FloatArray &normal, const double p, bool updFlag); + void updateVolumePolygons(Polygon &referenceFluidPoly, Polygon &secondFluidPoly, int &rfPoints, int &sfPoints, + const FloatArray &normal, const double p, bool updFlag); double computeVolumeAroundID(GaussPoint *gp, integrationDomain id, const std::vector< FloatArray > &idpoly); void updateIntegrationRules(); Material *_giveMaterial(int indx) { return domain->giveMaterial(mat [ indx ]); } diff --git a/src/fm/tr1_2d_supg2_axi.C b/src/fm/tr1_2d_supg2_axi.C index 7f964c4ef..b153ce148 100644 --- a/src/fm/tr1_2d_supg2_axi.C +++ b/src/fm/tr1_2d_supg2_axi.C @@ -44,7 +44,7 @@ #include "domain.h" #include "mathfem.h" #include "engngm.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fluidcrosssection.h" #include "load.h" #include "timestep.h" @@ -70,20 +70,15 @@ REGISTER_Element(TR1_2D_SUPG2_AXI); TR1_2D_SUPG2_AXI :: TR1_2D_SUPG2_AXI(int n, Domain *aDomain) : TR1_2D_SUPG(n, aDomain) - // Constructor. { numberOfDofMans = 3; } -TR1_2D_SUPG2_AXI :: ~TR1_2D_SUPG2_AXI() -// Destructor -{ } - -IRResultType -TR1_2D_SUPG2_AXI :: initializeFrom(InputRecord *ir) +void +TR1_2D_SUPG2_AXI :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + SUPGElement :: initializeFrom(ir); this->vof = 0.0; IR_GIVE_OPTIONAL_FIELD(ir, vof, _IFT_Tr1SUPG_pvof); @@ -101,12 +96,7 @@ TR1_2D_SUPG2_AXI :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, mat [ 1 ], _IFT_Tr1SUPG2_mat1); this->material = this->mat [ 0 ]; - result = SUPGElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } this->initGeometry(); - return IRRT_OK; } @@ -130,8 +120,8 @@ TR1_2D_SUPG2_AXI :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 2 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3, true) ); - integrationRulesArray [ 1 ].reset( new GaussIntegrationRule(2, this, 1, 3, true) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3, true); + integrationRulesArray [ 1 ] = std::make_unique(2, this, 1, 3, true); } } @@ -300,26 +290,25 @@ TR1_2D_SUPG2_AXI :: computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) this->computeVectorOfVelocities(VM_Total, tStep, u); FloatArray n; - double _u, _v, _r; this->computeVectorOfVelocities(VM_Total, tStep->givePreviousStep(), un); FloatMatrix _b(4, 6); for ( int ifluid = 0; ifluid < 2; ifluid++ ) { FluidDynamicMaterial *mat = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(ifluid) ); - for ( GaussPoint *gp: *integrationRulesArray [ ifluid ] ) { + for ( auto &gp: *integrationRulesArray [ ifluid ] ) { double dV = this->computeVolumeAroundID(gp, id [ ifluid ], vcoords [ ifluid ]); this->computeBMtrx(_b, gp); eps.beProductOf(_b, u); - mat->computeDeviatoricStressVector(stress, gp, eps, tStep); + stress = mat->computeDeviatoricStressAxi(eps, gp, tStep); answer.plusProduct(_b, stress, dV / Re); #if 1 // stabilization term k_delta - _r = this->computeRadiusAt(gp); computeNVector(n, gp); - _u = n.at(1) * un.at(1) + n.at(2) * un.at(3) + n.at(3) * un.at(5); - _v = n.at(1) * un.at(2) + n.at(2) * un.at(4) + n.at(3) * un.at(6); + double _r = this->computeRadiusAt(gp); + double _u = n.at(1) * un.at(1) + n.at(2) * un.at(3) + n.at(3) * un.at(5); + double _v = n.at(1) * un.at(2) + n.at(2) * un.at(4) + n.at(3) * un.at(6); for ( int i = 1; i <= 3; i++ ) { answer.at(2 * i - 1) -= t_supg * ( _u * b [ i - 1 ] + _v * c [ i - 1 ] ) * ( stress.at(1) / _r ) * dV / Re; @@ -342,32 +331,31 @@ TR1_2D_SUPG2_AXI :: computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatRe //FloatArray un; double Re = static_cast< FluidModel * >( domain->giveEngngModel() )->giveReynoldsNumber(); FloatArray un, u, n, eps, stress; - double _u, _v, _r; this->computeVectorOfVelocities(VM_Total, tStep->givePreviousStep(), un); this->computeVectorOfVelocities(VM_Total, tStep, u); for ( int ifluid = 0; ifluid < 2; ifluid++ ) { FluidDynamicMaterial *mat = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(ifluid) ); - for ( GaussPoint *gp: *integrationRulesArray [ ifluid ] ) { + for ( auto gp: *integrationRulesArray [ ifluid ] ) { double dV = this->computeVolumeAroundID(gp, id [ ifluid ], vcoords [ ifluid ]); this->computeBMtrx(_b, gp); - mat->giveDeviatoricStiffnessMatrix(_d, mode, gp, tStep); + _d = mat->computeTangentAxi(mode, gp, tStep); _db.beProductOf(_d, _b); answer.plusProductUnsym(_b, _db, dV); //answer.plusProductSymmUpper (_bs,_db,dV*t_supg); // } #if 1 - _r = this->computeRadiusAt(gp); computeNVector(n, gp); eps.beProductOf(_b, u); - mat->computeDeviatoricStressVector(stress, gp, eps, tStep); + stress = mat->computeDeviatoricStressAxi(eps, gp, tStep); //_mu = mat->giveCharacteristicValue(MRM_Viscosity, gp, tStep); - _u = n.at(1) * un.at(1) + n.at(2) * un.at(3) + n.at(3) * un.at(5); - _v = n.at(1) * un.at(2) + n.at(2) * un.at(4) + n.at(3) * un.at(6); + double _r = this->computeRadiusAt(gp); + double _u = n.at(1) * un.at(1) + n.at(2) * un.at(3) + n.at(3) * un.at(5); + double _v = n.at(1) * un.at(2) + n.at(2) * un.at(4) + n.at(3) * un.at(6); for ( int i = 1; i <= 3; i++ ) { for ( int j = 1; j <= 6; j++ ) { @@ -567,8 +555,7 @@ void TR1_2D_SUPG2_AXI :: computeDiffusionTerm_MC(FloatArray &answer, TimeStep *t double _r = this->computeRadiusAt(gp); this->computeBMtrx(_b, gp); eps.beProductOf(_b, u); - mat->computeDeviatoricStressVector(stress, gp, eps, tStep); - stress.times(1. / Re); + stress = (1. / Re) * mat->computeDeviatoricStressAxi(eps, gp, tStep); for ( int i = 1; i <= 3; i++ ) { answer.at(i) -= t_pspg * ( b [ i - 1 ] * stress.at(1) + c [ i - 1 ] * stress.at(4) ) * dV / rho / _r; } @@ -592,12 +579,12 @@ void TR1_2D_SUPG2_AXI :: computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, //this -> computeVectorOfVelocities(VM_Total,tStep, u) ; for ( int ifluid = 0; ifluid < 2; ifluid++ ) { FluidDynamicMaterial *mat = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(ifluid) ); - for ( GaussPoint *gp: *integrationRulesArray [ ifluid ] ) { + for ( auto &gp: *integrationRulesArray [ ifluid ] ) { double dV = this->computeVolumeAroundID(gp, id [ ifluid ], vcoords [ ifluid ]); double rho = mat->give('d', gp); double _r = this->computeRadiusAt(gp); this->computeBMtrx(_b, gp); - mat->giveDeviatoricStiffnessMatrix(_d, TangentStiffness, gp, tStep); + _d = mat->computeTangentAxi(TangentStiffness, gp, tStep); _db.beProductOf(_d, _b); //eps.beProductOf (_b, u); //mat->computeDeviatoricStressVector (stress,gp,eps,tStep); @@ -1072,24 +1059,23 @@ TR1_2D_SUPG2_AXI :: computeCriticalTimeStep(TimeStep *tStep) void -TR1_2D_SUPG2_AXI :: computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +TR1_2D_SUPG2_AXI :: computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) { /* one computes here average deviatoric stress, based on rule of mixture (this is used only for postprocessing) */ - FloatArray u, eps, s0, s1; - FloatMatrix _b; - answer.resize(3); + auto s0 = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(0) )->computeDeviatoricStressAxi(eps, gp, tStep); + auto s1 = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(1) )->computeDeviatoricStressAxi(eps, gp, tStep); + answer = temp_vof * s0 + ( 1. - temp_vof ) * s1; +} - this->computeVectorOfVelocities(VM_Total, tStep, u); - this->computeBMtrx(_b, gp); - eps.beProductOf(_b, u); - static_cast< FluidDynamicMaterial * >( this->_giveMaterial(0) )->computeDeviatoricStressVector(s0, gp, eps, tStep); - static_cast< FluidDynamicMaterial * >( this->_giveMaterial(1) )->computeDeviatoricStressVector(s1, gp, eps, tStep); +void +TR1_2D_SUPG2_AXI :: computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + auto t0 = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(0) )->computeTangentAxi(mode, gp, tStep); + auto t1 = static_cast< FluidDynamicMaterial * >( this->_giveMaterial(1) )->computeTangentAxi(mode, gp, tStep); - for ( int i = 1; i <= 3; i++ ) { - answer.at(i) = ( temp_vof ) * s0.at(i) + ( 1. - temp_vof ) * s1.at(i); - } + answer = temp_vof * t0 + ( 1. - temp_vof ) * t1; } diff --git a/src/fm/tr1_2d_supg2_axi.h b/src/fm/tr1_2d_supg2_axi.h index 46ca038c3..f38f8c32f 100644 --- a/src/fm/tr1_2d_supg2_axi.h +++ b/src/fm/tr1_2d_supg2_axi.h @@ -69,50 +69,50 @@ class TR1_2D_SUPG2_AXI : public TR1_2D_SUPG public: TR1_2D_SUPG2_AXI(int n, Domain * d); - virtual ~TR1_2D_SUPG2_AXI(); - virtual void computeAccelerationTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeAdvectionDerivativeTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); - virtual void computePressureTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLSICStabilizationTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLinearAdvectionTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionTerm_MC(FloatArray &answer, TimeStep *tStep); - virtual void computeAdvectionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionTerm_MC(FloatArray &answer, TimeStep *tStep); - virtual void computeAccelerationTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computePressureTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeBCRhsTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeBCRhsTerm_MC(FloatArray &answer, TimeStep *tStep); + void computeAccelerationTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeAdvectionTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeAdvectionDerivativeTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) override; + void computePressureTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeLSICStabilizationTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeLinearAdvectionTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeAdvectionTerm_MC(FloatArray &answer, TimeStep *tStep) override; + void computeAdvectionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionTerm_MC(FloatArray &answer, TimeStep *tStep) override; + void computeAccelerationTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computePressureTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeBCRhsTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeBCRhsTerm_MC(FloatArray &answer, TimeStep *tStep) override; - virtual void updateStabilizationCoeffs(TimeStep *tStep); - virtual void updateElementForNewInterfacePosition(TimeStep *tStep) { this->updateIntegrationRules(); } - virtual double computeCriticalTimeStep(TimeStep *tStep); + void updateStabilizationCoeffs(TimeStep *tStep) override; + void updateElementForNewInterfacePosition(TimeStep *tStep) override { this->updateIntegrationRules(); } + double computeCriticalTimeStep(TimeStep *tStep) override; // definition - virtual const char *giveClassName() const { return "TR1_2D_SUPG2_AXI"; } - virtual const char *giveInputRecordName() const { return _IFT_TR1_2D_SUPG2_AXI_Name; } - virtual MaterialMode giveMaterialMode() { return _2dAxiFlow; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + const char *giveClassName() const override { return "TR1_2D_SUPG2_AXI"; } + const char *giveInputRecordName() const override { return _IFT_TR1_2D_SUPG2_AXI_Name; } + MaterialMode giveMaterialMode() override { return _2dAxiFlow; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; #ifdef __OOFEG int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *tStep); + int node, TimeStep *tStep) override; // Graphics output - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; //virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) {} #endif protected: - virtual void computeGaussPoints(); - virtual void computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *); + void computeGaussPoints() override; + void computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) override; + void computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; void updateVolumePolygons(Polygon &referenceFluidPoly, Polygon &secondFluidPoly, int &rfPoints, int &sfPoints, const FloatArray &normal, const double p, bool updFlag); double computeVolumeAroundID(GaussPoint *gp, integrationDomain id, const std::vector< FloatArray > &idpoly); @@ -122,24 +122,24 @@ class TR1_2D_SUPG2_AXI : public TR1_2D_SUPG void updateIntegrationRules(); Material *_giveMaterial(int indx) { return domain->giveMaterial(mat [ indx ]); } - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; - virtual double computeLEPLICVolumeFraction(const FloatArray &n, const double p, LEPlic *matInterface, bool updFlag); - virtual void formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface, - const FloatArray &normal, const double p, bool updFlag); - virtual void formVolumeInterfacePoly(Polygon &matvolpoly, LEPlic *matInterface, - const FloatArray &normal, const double p, bool updFlag); - virtual double truncateMatVolume(const Polygon &matvolpoly, double &volume); - virtual void giveElementCenter(LEPlic *mat_interface, FloatArray ¢er, bool updFlag); - virtual void formMyVolumePoly(Polygon &myPoly, LEPlic *mat_interface, bool updFlag); - virtual Element *giveElement() { return this; } - virtual double computeMyVolume(LEPlic *matInterface, bool updFlag); + double computeLEPLICVolumeFraction(const FloatArray &n, const double p, LEPlic *matInterface, bool updFlag) override; + void formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface, + const FloatArray &normal, const double p, bool updFlag) override; + void formVolumeInterfacePoly(Polygon &matvolpoly, LEPlic *matInterface, + const FloatArray &normal, const double p, bool updFlag) override; + double truncateMatVolume(const Polygon &matvolpoly, double &volume) override; + void giveElementCenter(LEPlic *mat_interface, FloatArray ¢er, bool updFlag) override; + void formMyVolumePoly(Polygon &myPoly, LEPlic *mat_interface, bool updFlag) override; + Element *giveElement() override { return this; } + double computeMyVolume(LEPlic *matInterface, bool updFlag) override; }; } // end namespace oofem #endif // tr1_2d_supg2_axi_h diff --git a/src/fm/tr1_2d_supg_axi.C b/src/fm/tr1_2d_supg_axi.C index 547525cfd..a8aa288b7 100644 --- a/src/fm/tr1_2d_supg_axi.C +++ b/src/fm/tr1_2d_supg_axi.C @@ -47,7 +47,7 @@ #include "timestep.h" #include "bodyload.h" #include "boundaryload.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fluidcrosssection.h" #include "crosssection.h" #include "classfactory.h" @@ -61,12 +61,8 @@ namespace oofem { REGISTER_Element(TR1_2D_SUPG_AXI); TR1_2D_SUPG_AXI :: TR1_2D_SUPG_AXI(int n, Domain *aDomain) : TR1_2D_SUPG(n, aDomain) - // Constructor. { } -TR1_2D_SUPG_AXI :: ~TR1_2D_SUPG_AXI() -// Destructor -{ } void TR1_2D_SUPG_AXI :: computeGaussPoints() @@ -74,7 +70,7 @@ TR1_2D_SUPG_AXI :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 7, this); } } @@ -230,11 +226,11 @@ TR1_2D_SUPG_AXI :: computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) this->computeVectorOfVelocities(VM_Total, tStep->givePreviousStep(), un); // end k_delta declaration - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { double dV = this->computeVolumeAround(gp); this->computeBMtrx(_b, gp); eps.beProductOf(_b, u); - mat->computeDeviatoricStressVector(stress, gp, eps, tStep); + stress = mat->computeDeviatoricStressAxi(eps, gp, tStep); answer.plusProduct(_b, stress, dV / Re); #if 1 @@ -273,7 +269,7 @@ TR1_2D_SUPG_AXI :: computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatRes for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { double dV = this->computeVolumeAround(gp); this->computeBMtrx(_b, gp); - mat->giveDeviatoricStiffnessMatrix(_d, mode, gp, tStep); + _d = mat->computeTangentAxi(mode, gp, tStep); _db.beProductOf(_d, _b); answer.plusProductUnsym(_b, _db, dV); //answer.plusProductSymmUpper (_bs,_db,dV*t_supg); @@ -283,7 +279,7 @@ TR1_2D_SUPG_AXI :: computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatRes _r = this->computeRadiusAt(gp); this->computeNVector(n, gp); eps.beProductOf(_b, u); - mat->computeDeviatoricStressVector(stress, gp, eps, tStep); + stress = mat->computeDeviatoricStressAxi(eps, gp, tStep); //_mu = mat->giveCharacteristicValue(MRM_Viscosity, gp, tStep); _u = n.at(1) * un.at(1) + n.at(2) * un.at(3) + n.at(3) * un.at(5); @@ -462,21 +458,20 @@ void TR1_2D_SUPG_AXI :: computeDiffusionTerm_MC(FloatArray &answer, TimeStep *tS #if 1 double Re = static_cast< FluidModel * >( domain->giveEngngModel() )->giveReynoldsNumber(); - FloatArray eps, stress, u; + FloatArray eps, u; FloatMatrix _b; FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); // stabilization term K_eps this->computeVectorOfVelocities(VM_Total, tStep, u); - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { double dV = this->computeVolumeAround(gp); double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp); double _r = this->computeRadiusAt(gp); this->computeBMtrx(_b, gp); eps.beProductOf(_b, u); - mat->computeDeviatoricStressVector(stress, gp, eps, tStep); - stress.times(1. / Re); + auto stress = (1. / Re) * mat->computeDeviatoricStressAxi(eps, gp, tStep); for ( int i = 1; i <= 3; i++ ) { answer.at(i) -= t_pspg * ( b [ i - 1 ] * stress.at(1) + c [ i - 1 ] * stress.at(4) ) * dV / rho / _r; } @@ -498,12 +493,12 @@ void TR1_2D_SUPG_AXI :: computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, T // stabilization term K_eps //this -> computeVectorOfVelocities(VM_Total,tStep, u) ; - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { double dV = this->computeVolumeAround(gp); double rho = mat->give('d', gp); double _r = this->computeRadiusAt(gp); this->computeBMtrx(_b, gp); - mat->giveDeviatoricStiffnessMatrix(_d, TangentStiffness, gp, tStep); + _d = mat->computeTangentAxi(TangentStiffness, gp, tStep); _db.beProductOf(_d, _b); //eps.beProductOf (_b, u); //mat->computeDeviatoricStressVector (stress,gp,eps,tStep); @@ -573,17 +568,20 @@ TR1_2D_SUPG_AXI :: computeDeviatoricStrain(FloatArray &answer, GaussPoint *gp, T answer.beProductOf(_b, u); } + void -TR1_2D_SUPG_AXI :: computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +TR1_2D_SUPG_AXI :: computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) { - /* one should call material driver instead */ - FloatArray eps; - - this->computeDeviatoricStrain(eps, gp, tStep); - static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStressVector(answer, gp, eps, tStep); + answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStressAxi(eps, gp, tStep); } +void +TR1_2D_SUPG_AXI :: computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeTangentAxi(mode, gp, tStep); +} + void TR1_2D_SUPG_AXI :: computeBCRhsTerm_MB(FloatArray &answer, TimeStep *tStep) diff --git a/src/fm/tr1_2d_supg_axi.h b/src/fm/tr1_2d_supg_axi.h index 30d7b2880..dfb434230 100644 --- a/src/fm/tr1_2d_supg_axi.h +++ b/src/fm/tr1_2d_supg_axi.h @@ -57,47 +57,47 @@ class TR1_2D_SUPG_AXI : public TR1_2D_SUPG public: TR1_2D_SUPG_AXI(int n, Domain * d); - virtual ~TR1_2D_SUPG_AXI(); - virtual void computeAccelerationTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeAdvectionDerivativeTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); - virtual void computePressureTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLSICStabilizationTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLinearAdvectionTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionTerm_MC(FloatArray &answer, TimeStep *tStep); - virtual void computeAdvectionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computeDiffusionTerm_MC(FloatArray &answer, TimeStep *tStep); - virtual void computeAccelerationTerm_MC(FloatMatrix &answer, TimeStep *tStep); - virtual void computePressureTerm_MC(FloatMatrix &answer, TimeStep *tStep); + void computeAccelerationTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeAdvectionTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeAdvectionDerivativeTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeDiffusionDerivativeTerm_MB(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) override; + void computePressureTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeLSICStabilizationTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeLinearAdvectionTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeAdvectionTerm_MC(FloatArray &answer, TimeStep *tStep) override; + void computeAdvectionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionDerivativeTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computeDiffusionTerm_MC(FloatArray &answer, TimeStep *tStep) override; + void computeAccelerationTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; + void computePressureTerm_MC(FloatMatrix &answer, TimeStep *tStep) override; - virtual void updateStabilizationCoeffs(TimeStep *tStep); - virtual void computeBCRhsTerm_MB(FloatArray &answer, TimeStep *tStep); - virtual void computeBCRhsTerm_MC(FloatArray &answer, TimeStep *tStep); - virtual void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); + void updateStabilizationCoeffs(TimeStep *tStep) override; + void computeBCRhsTerm_MB(FloatArray &answer, TimeStep *tStep) override; + void computeBCRhsTerm_MC(FloatArray &answer, TimeStep *tStep) override; + void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; - virtual void computeSlipWithFrictionBCTerm_MB(FloatMatrix &answer, Load *load, int side, TimeStep *tStep); - virtual void computePenetrationWithResistanceBCTerm_MB(FloatMatrix &answer, Load *load, int side, TimeStep *tStep); - virtual void computeOutFlowBCTerm_MB(FloatMatrix &answer, int side, TimeStep *tStep); - virtual void computeBCLhsTerm_MB(FloatMatrix &answer, TimeStep *tStep); - virtual void computeBCLhsPressureTerm_MB(FloatMatrix &answer, TimeStep *tStep); + void computeSlipWithFrictionBCTerm_MB(FloatMatrix &answer, Load *load, int side, TimeStep *tStep) override; + void computePenetrationWithResistanceBCTerm_MB(FloatMatrix &answer, Load *load, int side, TimeStep *tStep) override; + void computeOutFlowBCTerm_MB(FloatMatrix &answer, int side, TimeStep *tStep) override; + void computeBCLhsTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; + void computeBCLhsPressureTerm_MB(FloatMatrix &answer, TimeStep *tStep) override; - virtual double computeVolumeAround(GaussPoint *gp); - virtual void LS_PCS_computeVOFFractions(FloatArray &answer, FloatArray &fi); + double computeVolumeAround(GaussPoint *gp) override; + void LS_PCS_computeVOFFractions(FloatArray &answer, FloatArray &fi) override; // definition - virtual const char *giveClassName() const { return "TR1_2D_SUPG_AXI"; } - virtual const char *giveInputRecordName() const { return _IFT_TR1_2D_SUPG_AXI_Name; } - virtual MaterialMode giveMaterialMode() { return _2dAxiFlow; } + const char *giveClassName() const override { return "TR1_2D_SUPG_AXI"; } + const char *giveInputRecordName() const override { return _IFT_TR1_2D_SUPG_AXI_Name; } + MaterialMode giveMaterialMode() override { return _2dAxiFlow; } protected: - virtual void computeGaussPoints(); - virtual void computeDeviatoricStrain(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); - virtual void computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); - virtual void initGeometry(); + void computeGaussPoints() override; + void computeDeviatoricStrain(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; + void computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) override; + void computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void initGeometry() override; virtual double computeRadiusAt(GaussPoint *gp); virtual void computeBMtrx(FloatMatrix &answer, GaussPoint *gp); void computeNVector(FloatArray &answer, GaussPoint *gp); diff --git a/src/fm/tr1bubblestokes.C b/src/fm/tr1bubblestokes.C index b70bf1346..81f1c855a 100644 --- a/src/fm/tr1bubblestokes.C +++ b/src/fm/tr1bubblestokes.C @@ -43,7 +43,7 @@ #include "bodyload.h" #include "boundaryload.h" #include "mathfem.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fei2dtrlin.h" #include "masterdof.h" #include "fluidcrosssection.h" @@ -68,20 +68,16 @@ Tr1BubbleStokes :: Tr1BubbleStokes(int n, Domain *aDomain) : FMElement(n, aDomai this->numberOfDofMans = 3; this->numberOfGaussPoints = 7; - this->bubble.reset( new ElementDofManager(1, aDomain, this) ); + this->bubble = std::make_unique(1, aDomain, this); this->bubble->appendDof( new MasterDof(this->bubble.get(), V_u) ); this->bubble->appendDof( new MasterDof(this->bubble.get(), V_v) ); } -Tr1BubbleStokes :: ~Tr1BubbleStokes() -{ -} - void Tr1BubbleStokes :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], this->numberOfGaussPoints, this); } } @@ -144,40 +140,42 @@ void Tr1BubbleStokes :: giveCharacteristicMatrix(FloatMatrix &answer, void Tr1BubbleStokes :: computeInternalForcesVector(FloatArray &answer, TimeStep *tStep) { FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); - FloatArray a_pressure, a_velocity, devStress, epsp, N, dNv(8); - double r_vol, pressure; - FloatMatrix dN, B(3, 8); - B.zero(); - this->computeVectorOfVelocities(VM_Total, tStep, a_velocity); - this->computeVectorOfPressures(VM_Total, tStep, a_pressure); + FloatArrayF<8> a_velocity = this->computeVectorOfVelocities(VM_Total, tStep); + FloatArrayF<3> a_pressure = this->computeVectorOfPressures(VM_Total, tStep); - FloatArray momentum, conservation; + FloatArrayF<8> momentum; + FloatArrayF<3> conservation; - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { - const FloatArray &lcoords = gp->giveNaturalCoordinates(); + for ( auto &gp: *integrationRulesArray [ 0 ] ) { + const auto &lcoords = gp->giveNaturalCoordinates(); - double detJ = fabs( this->interp.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) ); - this->interp.evalN( N, lcoords, FEIElementGeometryWrapper(this) ); - double dA = detJ * gp->giveWeight(); + auto N = this->interp.evalN( lcoords ); + auto val = this->interp.evaldNdx( FEIElementGeometryWrapper(this) ); + auto detJ = val.first; + auto dN = val.second; + auto dA = std::abs(detJ) * gp->giveWeight(); + FloatArrayF<8> dNv; + FloatMatrixF<3,8> B; for ( int j = 0, k = 0; j < 3; j++, k += 2 ) { - dNv(k) = B(0, k) = B(2, k + 1) = dN(j, 0); - dNv(k + 1) = B(1, k + 1) = B(2, k) = dN(j, 1); + dNv[k] = B(0, k) = B(2, k + 1) = dN(0, j); + dNv[k + 1] = B(1, k + 1) = B(2, k) = dN(1, j); } // Bubble contribution; - dNv(6) = B(0, 6) = B(2, 7) = 27. * ( dN(0, 0) * N(1) * N(2) + N(0) * dN(1, 0) * N(2) + N(0) * N(1) * dN(2, 0) ); - dNv(7) = B(1, 7) = B(2, 6) = 27. * ( dN(0, 1) * N(1) * N(2) + N(0) * dN(1, 1) * N(2) + N(0) * N(1) * dN(2, 1) ); + dNv[6] = B(0, 6) = B(2, 7) = 27. * ( dN(0, 0) * N[1] * N[2] + N[0] * dN(1, 0) * N[2] + N[0] * N[1] * dN(2, 0) ); + dNv[7] = B(1, 7) = B(2, 6) = 27. * ( dN(0, 1) * N[1] * N[2] + N[0] * dN(1, 1) * N[2] + N[0] * N[1] * dN(2, 1) ); - pressure = N.dotProduct(a_pressure); - epsp.beProductOf(B, a_velocity); + auto pressure = dot(N, a_pressure); + auto epsp = dot(B, a_velocity); - mat->computeDeviatoricStressVector(devStress, r_vol, gp, epsp, pressure, tStep); + auto s_r = mat->computeDeviatoricStress2D(epsp, pressure, gp, tStep); + auto devStress = s_r.first; + auto r_vol = s_r.second; - momentum.plusProduct(B, devStress, dA); - momentum.add(-pressure * dA, dNv); - conservation.add(r_vol * dA, N); + momentum += Tdot(B, devStress * dA) + dNv * (-pressure * dA); + conservation += N * (r_vol * dA); } answer.resize(11); @@ -188,20 +186,16 @@ void Tr1BubbleStokes :: computeInternalForcesVector(FloatArray &answer, TimeStep void Tr1BubbleStokes :: computeExternalForcesVector(FloatArray &answer, TimeStep *tStep) { - int load_number, load_id; - Load *load; - BodyLoad *bLoad; - bcGeomType ltype; FloatArray vec; int nLoads = this->boundaryLoadArray.giveSize() / 2; answer.resize(11); answer.zero(); for ( int i = 1; i <= nLoads; i++ ) { // For each Neumann boundary condition - load_number = this->boundaryLoadArray.at(2 * i - 1); - load_id = this->boundaryLoadArray.at(2 * i); - load = this->domain->giveLoad(load_number); - ltype = load->giveBCGeoType(); + int load_number = this->boundaryLoadArray.at(2 * i - 1); + int load_id = this->boundaryLoadArray.at(2 * i); + Load *load = this->domain->giveLoad(load_number); + bcGeomType ltype = load->giveBCGeoType(); if ( ltype == EdgeLoadBGT ) { this->computeBoundarySurfaceLoadVector(vec, static_cast< BoundaryLoad * >(load), load_id, ExternalForcesVector, VM_Total, tStep); @@ -211,13 +205,14 @@ void Tr1BubbleStokes :: computeExternalForcesVector(FloatArray &answer, TimeStep nLoads = this->giveBodyLoadArray()->giveSize(); for ( int i = 1; i <= nLoads; i++ ) { - load = domain->giveLoad( bodyLoadArray.at(i) ); - if ((bLoad = dynamic_cast(load))) { - ltype = load->giveBCGeoType(); - if ( ltype == BodyLoadBGT && load->giveBCValType() == ForceLoadBVT ) { - this->computeLoadVector(vec, bLoad, ExternalForcesVector, VM_Total, tStep); - answer.add(vec); - } + Load *load = domain->giveLoad( bodyLoadArray.at(i) ); + BodyLoad *bLoad; + if ((bLoad = dynamic_cast(load))) { + bcGeomType ltype = load->giveBCGeoType(); + if ( ltype == BodyLoadBGT && load->giveBCValType() == ForceLoadBVT ) { + this->computeLoadVector(vec, bLoad, ExternalForcesVector, VM_Total, tStep); + answer.add(vec); + } } } } @@ -235,7 +230,7 @@ void Tr1BubbleStokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, Ch load->computeComponentArrayAt(gVector, tStep, VM_Total); temparray.zero(); if ( gVector.giveSize() ) { - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp); @@ -275,7 +270,7 @@ void Tr1BubbleStokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, Ch f.zero(); iRule.SetUpPointsOnLine(numberOfEdgeIPs, _Unknown); - for ( GaussPoint *gp: iRule ) { + for ( auto &gp: iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->interp.edgeEvalN( N, iEdge, lcoords, FEIElementGeometryWrapper(this) ); @@ -309,51 +304,48 @@ void Tr1BubbleStokes :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseM { // Note: Working with the components; [K, G+Dp; G^T+Dv^T, C] . [v,p] FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); - FloatMatrix B(3, 8), EdB, K, G, Dp, DvT, C, Ed, dN; - FloatArray dNv(8), N, Ep, Cd, tmpA, tmpB; - double Cp; - B.zero(); + FloatMatrixF<8,8> K; + FloatMatrixF<8,3> G, Dp; + FloatMatrixF<3,8> DvT; + FloatMatrixF<3,3> C; - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { // Compute Gauss point and determinant at current element - const FloatArray &lcoords = gp->giveNaturalCoordinates(); + const auto &lcoords = gp->giveNaturalCoordinates(); - double detJ = fabs( this->interp.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) ); - double dA = detJ * gp->giveWeight(); - this->interp.evalN( N, lcoords, FEIElementGeometryWrapper(this) ); + auto N = this->interp.evalN( lcoords ); + auto detj_dn = this->interp.evaldNdx( FEIElementGeometryWrapper(this) ); + auto dN = detj_dn.second; + auto detJ = detj_dn.first; + auto dA = std::abs(detJ) * gp->giveWeight(); + + FloatArrayF<8> dN_V; + FloatMatrixF<3,8> B; for ( int j = 0, k = 0; j < 3; j++, k += 2 ) { - dNv(k) = B(0, k) = B(2, k + 1) = dN(j, 0); - dNv(k + 1) = B(1, k + 1) = B(2, k) = dN(j, 1); + dN_V[k] = B(0, k) = B(2, k + 1) = dN(0, j); + dN_V[k + 1] = B(1, k + 1) = B(2, k) = dN(1, j); } // Bubble contribution; - dNv(6) = B(0, 6) = B(2, 7) = 27. * ( dN(0, 0) * N(1) * N(2) + N(0) * dN(1, 0) * N(2) + N(0) * N(1) * dN(2, 0) ); - dNv(7) = B(1, 7) = B(2, 6) = 27. * ( dN(0, 1) * N(1) * N(2) + N(0) * dN(1, 1) * N(2) + N(0) * N(1) * dN(2, 1) ); + dN_V[6] = B(0, 6) = B(2, 7) = 27. * ( dN(0, 0) * N[1] * N[2] + N[0] * dN(1, 0) * N[2] + N[0] * N[1] * dN(2, 0) ); + dN_V[7] = B(1, 7) = B(2, 6) = 27. * ( dN(0, 1) * N[1] * N[2] + N[0] * dN(1, 1) * N[2] + N[0] * N[1] * dN(2, 1) ); // Computing the internal forces should have been done first. // dsigma_dev/deps_dev dsigma_dev/dp deps_vol/deps_dev deps_vol/dp - mat->giveStiffnessMatrices(Ed, Ep, Cd, Cp, mode, gp, tStep); - - EdB.beProductOf(Ed, B); - K.plusProductSymmUpper(B, EdB, dA); - G.plusDyadUnsym(dNv, N, -dA); - C.plusDyadSymmUpper(N, Cp * dA); - - tmpA.beTProductOf(B, Ep); - Dp.plusDyadUnsym(tmpA, N, dA); - - tmpB.beTProductOf(B, Cd); - DvT.plusDyadUnsym(N, tmpB, dA); + //auto [Ed, Ep, Cd, Cp] = mat->computeTangents2D(mode, gp, tStep); + auto tangents = mat->computeTangents2D(mode, gp, tStep); + + K.plusProductSymmUpper(B, dot(tangents.dsdd, B), dA); + G.plusDyadUnsym(dN_V, N, -dA); + Dp.plusDyadUnsym(Tdot(B, tangents.dsdp), N, dA); + DvT.plusDyadUnsym(N, Tdot(B, tangents.dedd), dA); + C.plusDyadSymmUpper(N, tangents.dedp * dA); } K.symmetrized(); C.symmetrized(); - - FloatMatrix GTDvT, GDp; - GTDvT.beTranspositionOf(G); - GTDvT.add(DvT); - GDp = G; - GDp.add(Dp); + auto GTDvT = transpose(G) + DvT; + auto GDp = G + Dp; answer.resize(11, 11); answer.zero(); diff --git a/src/fm/tr1bubblestokes.h b/src/fm/tr1bubblestokes.h index 157b6b2e3..3109a7f10 100644 --- a/src/fm/tr1bubblestokes.h +++ b/src/fm/tr1bubblestokes.h @@ -73,42 +73,41 @@ public SpatialLocalizerInterface public: Tr1BubbleStokes(int n, Domain * d); - virtual ~Tr1BubbleStokes(); - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual void computeGaussPoints(); + void computeGaussPoints() override; - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep); + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override; + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) override; void computeInternalForcesVector(FloatArray &answer, TimeStep *tStep); void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); void computeExternalForcesVector(FloatArray &answer, TimeStep *tStep); - virtual void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true); + void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; + void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true) override; - virtual const char *giveClassName() const { return "Tr1BubbleStokes"; } - virtual const char *giveInputRecordName() const { return _IFT_Tr1BubbleStokes_Name; } - virtual MaterialMode giveMaterialMode() { return _2dFlow; } + const char *giveClassName() const override { return "Tr1BubbleStokes"; } + const char *giveInputRecordName() const override { return _IFT_Tr1BubbleStokes_Name; } + MaterialMode giveMaterialMode() override { return _2dFlow; } - virtual int computeNumberOfDofs(); + int computeNumberOfDofs() override; - virtual int giveNumberOfInternalDofManagers() const; - virtual DofManager *giveInternalDofManager(int i) const; - virtual void giveInternalDofManDofIDMask(int i, IntArray &answer) const; + int giveNumberOfInternalDofManagers() const override; + DofManager *giveInternalDofManager(int i) const override; + void giveInternalDofManDofIDMask(int i, IntArray &answer) const override; - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual void computeField(ValueModeType u, TimeStep *tStep, const FloatArray &coords, FloatArray &answer); + void computeField(ValueModeType u, TimeStep *tStep, const FloatArray &coords, FloatArray &answer) override; }; } // end namespace oofem #endif // tr1bubblestokes_h diff --git a/src/fm/tr21_2d_supg.C b/src/fm/tr21_2d_supg.C index d59cf0f61..5d73ab35e 100644 --- a/src/fm/tr21_2d_supg.C +++ b/src/fm/tr21_2d_supg.C @@ -43,7 +43,7 @@ #include "floatarray.h" #include "intarray.h" #include "mathfem.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fluidcrosssection.h" #include "timestep.h" #include "contextioerr.h" @@ -65,15 +65,10 @@ FEI2dTrLin TR21_2D_SUPG :: pressureInterpolation(1, 2); TR21_2D_SUPG :: TR21_2D_SUPG(int n, Domain *aDomain) : SUPGElement2(n, aDomain), ZZNodalRecoveryModelInterface(this) - // Constructor. { numberOfDofMans = 6; } -TR21_2D_SUPG :: ~TR21_2D_SUPG() -// Destructor -{ } - FEInterpolation * TR21_2D_SUPG :: giveInterpolation() const { @@ -113,23 +108,37 @@ TR21_2D_SUPG :: computeGaussPoints() if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(3); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 3, this); //seven point Gauss integration - integrationRulesArray [ 1 ].reset( new GaussIntegrationRule(2, this, 1, 3) ); + integrationRulesArray [ 1 ] = std::make_unique(2, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 1 ], 7, this); - integrationRulesArray [ 2 ].reset( new GaussIntegrationRule(3, this, 1, 3) ); + integrationRulesArray [ 2 ] = std::make_unique(3, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 2 ], 13, this); - //integrationRulesArray [ 3 ] = new GaussIntegrationRule(4, this, 1, 3); + //integrationRulesArray [ 3 ] = std::make_unique(4, this, 1, 3); //this->giveCrossSection()->setupIntegrationPoints( *integrationRulesArray[3], 27, this ); } } +void +TR21_2D_SUPG :: computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStress2D(eps, gp, tStep); +} + + +void +TR21_2D_SUPG :: computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeTangent2D(mode, gp, tStep); +} + + void TR21_2D_SUPG :: computeNuMatrix(FloatMatrix &answer, GaussPoint *gp) { @@ -236,16 +245,14 @@ TR21_2D_SUPG :: computeGradPMatrix(FloatMatrix &answer, GaussPoint *gp) void TR21_2D_SUPG :: computeDivTauMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) { - FloatMatrix D, d2n; - - answer.resize(2, 12); - answer.zero(); - + FloatMatrix d2n; this->velocityInterpolation.evald2Ndx2( d2n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->giveDeviatoricStiffnessMatrix(D, TangentStiffness, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + auto D = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeTangent2D(TangentStiffness, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + answer.resize(2, 12); + answer.zero(); for ( int i = 1; i <= 6; i++ ) { answer.at(1, 2 * i - 1) = D.at(1, 1) * d2n.at(i, 1) + D.at(1, 3) * d2n.at(i, 3) + D.at(3, 1) * d2n.at(i, 3) + D.at(3, 3) * d2n.at(i, 2); answer.at(1, 2 * i) = D.at(1, 2) * d2n.at(i, 3) + D.at(1, 3) * d2n.at(i, 1) + D.at(3, 2) * d2n.at(i, 2) + D.at(3, 3) * d2n.at(i, 3); @@ -1056,11 +1063,10 @@ TR21_2D_SUPG :: computeIntersection(int iedge, FloatArray &intcoords, FloatArray { FloatArray Coeff(3), helplcoords(3); double fi1, fi2, fi3, r1, r11, r12; - IntArray edge(3); intcoords.resize(2); intcoords.zero(); - this->velocityInterpolation.computeLocalEdgeMapping(edge, iedge); + const auto &edge = this->velocityInterpolation.computeLocalEdgeMapping(iedge); fi1 = fi.at( edge.at(1) ); fi2 = fi.at( edge.at(2) ); fi3 = fi.at( edge.at(3) ); @@ -1187,9 +1193,7 @@ void TR21_2D_SUPG :: computeCoordsOfEdge(FloatArray &answer, int iedge) { - IntArray edge; - - velocityInterpolation.computeLocalEdgeMapping(edge, iedge); + const auto &edge = velocityInterpolation.computeLocalEdgeMapping(iedge); answer.at(1) = this->giveNode( edge.at(1) )->giveCoordinate(1); answer.at(2) = this->giveNode( edge.at(1) )->giveCoordinate(2); @@ -1343,36 +1347,14 @@ TR21_2D_SUPG :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateTyp return SUPGElement2 :: giveIPValue(answer, gp, type, tStep); } -contextIOResultType TR21_2D_SUPG :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full element context (saves state variables, that completely describe -// current state) -// +void TR21_2D_SUPG :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = SUPGElement :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + SUPGElement :: saveContext(stream, mode); } - - -contextIOResultType TR21_2D_SUPG :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full element context (saves state variables, that completely describe -// current state) -// +void TR21_2D_SUPG :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = SUPGElement :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + SUPGElement :: restoreContext(stream, mode); } diff --git a/src/fm/tr21_2d_supg.h b/src/fm/tr21_2d_supg.h index 38b3bb39a..52ba848a8 100644 --- a/src/fm/tr21_2d_supg.h +++ b/src/fm/tr21_2d_supg.h @@ -50,7 +50,7 @@ class FEI2dTrQuad; class FEI2dTrLin; /** - * Class representing 2d triangular element with quadratic velocity + * Class representing 2d triangular element with quadratic velocity * and linear pressure approximation for solving incompressible fluid problems * with SUPG solver. */ @@ -62,35 +62,34 @@ class TR21_2D_SUPG : public SUPGElement2, public LevelSetPCSElementInterface, pu public: TR21_2D_SUPG(int n, Domain * aDomain); - virtual ~TR21_2D_SUPG(); - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; // definition - virtual const char *giveClassName() const { return "TR21_2D_SUPG"; } - virtual const char *giveInputRecordName() const { return _IFT_TR21_2D_SUPG_Name; } - virtual MaterialMode giveMaterialMode() { return _2dFlow; } + const char *giveClassName() const override { return "TR21_2D_SUPG"; } + const char *giveInputRecordName() const override { return _IFT_TR21_2D_SUPG_Name; } + MaterialMode giveMaterialMode() override { return _2dFlow; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual int computeNumberOfDofs(); - virtual void updateYourself(TimeStep *tStep); + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + int computeNumberOfDofs() override; + void updateYourself(TimeStep *tStep) override; /// Used to check consistency and initialize some element geometry data (area,b,c). - virtual int checkConsistency(); + int checkConsistency() override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual double LS_PCS_computeF(LevelSetPCS *ls, TimeStep *tStep); - virtual void LS_PCS_computedN(FloatMatrix &answer); - virtual double LS_PCS_computeVolume(); - virtual void LS_PCS_computeVolume(double &answer, const FloatArray **coordinates); - virtual double LS_PCS_computeS(LevelSetPCS *ls, TimeStep *tStep); - virtual void LS_PCS_computeVOFFractions(FloatArray &answer, FloatArray &fi); + double LS_PCS_computeF(LevelSetPCS *ls, TimeStep *tStep) override; + void LS_PCS_computedN(FloatMatrix &answer) override; + double LS_PCS_computeVolume() override; + void LS_PCS_computeVolume(double &answer, const FloatArray **coordinates); + double LS_PCS_computeS(LevelSetPCS *ls, TimeStep *tStep) override; + void LS_PCS_computeVOFFractions(FloatArray &answer, FloatArray &fi) override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; /// @name Helping functions for computing VOFFractions. //@{ @@ -103,45 +102,47 @@ class TR21_2D_SUPG : public SUPGElement2, public LevelSetPCSElementInterface, pu void computeQuadraticFunct(FloatArray &answer, FloatArray line); //@{ - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; #ifdef __OOFEG int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *tStep); + int node, TimeStep *tStep) override; // Graphics output - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - //virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) {} + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override {} #endif - virtual double computeCriticalTimeStep(TimeStep *tStep); + double computeCriticalTimeStep(TimeStep *tStep) override; // three terms for computing their norms due to computing t_supg - virtual void computeAdvectionTerm(FloatMatrix &answer, TimeStep *tStep); - virtual void computeAdvectionDeltaTerm(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassDeltaTerm(FloatMatrix &answer, TimeStep *tStep); - virtual void computeLSICTerm(FloatMatrix &answer, TimeStep *tStep); + void computeAdvectionTerm(FloatMatrix &answer, TimeStep *tStep); + void computeAdvectionDeltaTerm(FloatMatrix &answer, TimeStep *tStep); + void computeMassDeltaTerm(FloatMatrix &answer, TimeStep *tStep); + void computeLSICTerm(FloatMatrix &answer, TimeStep *tStep); - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; protected: - virtual void giveLocalVelocityDofMap(IntArray &map); - virtual void giveLocalPressureDofMap(IntArray &map); - - virtual void computeGaussPoints(); - virtual void computeNuMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeUDotGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - virtual void computeBMatrix(FloatMatrix &anwer, GaussPoint *gp); - virtual void computeDivUMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeNpMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeGradPMatrix(FloatMatrix &answer, GaussPoint *gp); - virtual void computeDivTauMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - virtual void computeGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - virtual int giveNumberOfSpatialDimensions(); - virtual double computeVolumeAround(GaussPoint *gp); - virtual void initGeometry(); - - virtual void updateStabilizationCoeffs(TimeStep *tStep); + void giveLocalVelocityDofMap(IntArray &map) override; + void giveLocalPressureDofMap(IntArray &map) override; + + void computeGaussPoints() override; + void computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep) override; + void computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void computeNuMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeUDotGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) override; + void computeBMatrix(FloatMatrix &anwer, GaussPoint *gp) override; + void computeDivUMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeNpMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeGradPMatrix(FloatMatrix &answer, GaussPoint *gp) override; + void computeDivTauMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) override; + void computeGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) override; + int giveNumberOfSpatialDimensions() override; + double computeVolumeAround(GaussPoint *gp) override; + void initGeometry(); + + void updateStabilizationCoeffs(TimeStep *tStep) override; }; } // end namespace oofem #endif // tr21_2d_supg_h diff --git a/src/fm/tr21stokes.C b/src/fm/tr21stokes.C index 27b79ec58..5ef38e509 100644 --- a/src/fm/tr21stokes.C +++ b/src/fm/tr21stokes.C @@ -43,7 +43,7 @@ #include "bodyload.h" #include "boundaryload.h" #include "mathfem.h" -#include "fluiddynamicmaterial.h" +#include "fm/Materials/fluiddynamicmaterial.h" #include "fei2dtrlin.h" #include "fei2dtrquad.h" #include "fluidcrosssection.h" @@ -76,14 +76,11 @@ Tr21Stokes :: Tr21Stokes(int n, Domain *aDomain) : FMElement(n, aDomain), ZZNoda } } -Tr21Stokes :: ~Tr21Stokes() -{ } - void Tr21Stokes :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], this->numberOfGaussPoints, this); } } @@ -135,36 +132,34 @@ void Tr21Stokes :: giveCharacteristicMatrix(FloatMatrix &answer, void Tr21Stokes :: computeInternalForcesVector(FloatArray &answer, TimeStep *tStep) { FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); - FloatArray a_pressure, a_velocity, devStress, epsp, Nh, dNv(12); - double r_vol, pressure; - FloatMatrix dN, B(3, 12); - B.zero(); - this->computeVectorOfVelocities(VM_Total, tStep, a_velocity); - this->computeVectorOfPressures(VM_Total, tStep, a_pressure); + FloatArrayF<12> a_velocity = this->computeVectorOfVelocities(VM_Total, tStep); + FloatArrayF<3> a_pressure = this->computeVectorOfPressures(VM_Total, tStep); - FloatArray momentum, conservation; + FloatArrayF<12> momentum; + FloatArrayF<3> conservation; - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { - const FloatArray &lcoords = gp->giveNaturalCoordinates(); + for ( auto &gp: *integrationRulesArray [ 0 ] ) { + const auto &lcoords = gp->giveNaturalCoordinates(); - double detJ = fabs( this->interpolation_quad.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) ); - this->interpolation_lin.evalN( Nh, lcoords, FEIElementGeometryWrapper(this) ); - double dA = detJ * gp->giveWeight(); + auto Nh = this->interpolation_lin.evalN( lcoords ); + auto val = this->interpolation_quad.evaldNdx( lcoords, FEIElementGeometryWrapper(this) ); + auto detJ = val.first; + auto dN = val.second; + auto dA = std::abs(detJ) * gp->giveWeight(); - for ( int j = 0, k = 0; j < dN.giveNumberOfRows(); j++, k += 2 ) { - dNv(k) = B(0, k) = B(2, k + 1) = dN(j, 0); - dNv(k + 1) = B(1, k + 1) = B(2, k) = dN(j, 1); - } + auto dNv = flatten(dN); + auto B = Bmatrix_2d(dN); - pressure = Nh.dotProduct(a_pressure); - epsp.beProductOf(B, a_velocity); + auto pressure = dot(Nh, a_pressure); + auto epsp = dot(B, a_velocity); - mat->computeDeviatoricStressVector(devStress, r_vol, gp, epsp, pressure, tStep); + auto s_r = mat->computeDeviatoricStress2D(epsp, pressure, gp, tStep); + auto devStress = s_r.first; + auto r_vol = s_r.second; - momentum.plusProduct(B, devStress, dA); - momentum.add(-pressure * dA, dNv); - conservation.add(r_vol * dA, Nh); + momentum += Tdot(B, devStress * dA) + dNv * (-pressure * dA); + conservation += Nh * (r_vol * dA); } answer.resize(15); @@ -192,16 +187,16 @@ void Tr21Stokes :: computeExternalForcesVector(FloatArray &answer, TimeStep *tSt } } - BodyLoad *bload; nLoads = this->giveBodyLoadArray()->giveSize(); for ( int i = 1; i <= nLoads; i++ ) { Load *load = domain->giveLoad( bodyLoadArray.at(i) ); - if ((bload = dynamic_cast(load))) { - bcGeomType ltype = load->giveBCGeoType(); - if ( ltype == BodyLoadBGT && load->giveBCValType() == ForceLoadBVT ) { - this->computeLoadVector(vec, bload, ExternalForcesVector, VM_Total, tStep); - answer.add(vec); - } + BodyLoad *bload; + if ((bload = dynamic_cast(load))) { + bcGeomType ltype = load->giveBCGeoType(); + if ( ltype == BodyLoadBGT && load->giveBCValType() == ForceLoadBVT ) { + this->computeLoadVector(vec, bload, ExternalForcesVector, VM_Total, tStep); + answer.add(vec); + } } } } @@ -219,7 +214,7 @@ void Tr21Stokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharTyp load->computeComponentArrayAt(gVector, tStep, VM_Total); temparray.zero(); if ( gVector.giveSize() ) { - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: *integrationRulesArray [ 0 ] ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); double rho = mat->give('d', gp); @@ -256,7 +251,7 @@ void Tr21Stokes :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharTyp f.zero(); iRule.SetUpPointsOnLine(numberOfEdgeIPs, _Unknown); - for ( GaussPoint *gp: iRule ) { + for ( auto &gp: iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->interpolation_quad.edgeEvalN( N, boundary, lcoords, FEIElementGeometryWrapper(this) ); @@ -290,48 +285,39 @@ void Tr21Stokes :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode m { // Note: Working with the components; [K, G+Dp; G^T+Dv^T, C] . [v,p] FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); - FloatMatrix B(3, 12), EdB, K, G, Dp, DvT, C, Ed, dN; - FloatArray dN_V(12), Nlin, Ep, Cd, tmpA, tmpB; - double Cp; + FloatMatrixF<12,12> K; + FloatMatrixF<12,3> G, Dp; + FloatMatrixF<3,12> DvT; + FloatMatrixF<3,3> C; - B.zero(); + for ( auto &gp: *integrationRulesArray [ 0 ] ) { + const auto &lcoords = gp->giveNaturalCoordinates(); - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { - // Compute Gauss point and determinant at current element - const FloatArray &lcoords = gp->giveNaturalCoordinates(); + auto Nlin = this->interpolation_lin.evalN( lcoords ); + auto detj_dn = this->interpolation_quad.evaldNdx( lcoords, FEIElementGeometryWrapper(this) ); + auto dN = detj_dn.second; + auto detJ = detj_dn.first; + auto dA = std::abs(detJ) * gp->giveWeight(); - this->interpolation_lin.evalN( Nlin, lcoords, FEIElementGeometryWrapper(this) ); - double detJ = fabs( this->interpolation_quad.evaldNdx( dN, lcoords, FEIElementGeometryWrapper(this) ) ); - double dA = detJ * gp->giveWeight(); - - for ( int j = 0, k = 0; j < 6; j++, k += 2 ) { - dN_V(k) = B(0, k) = B(2, k + 1) = dN(j, 0); - dN_V(k + 1) = B(1, k + 1) = B(2, k) = dN(j, 1); - } + auto dN_V = flatten(dN); + auto B = Bmatrix_2d(dN); // Computing the internal forces should have been done first. // dsigma_dev/deps_dev dsigma_dev/dp deps_vol/deps_dev deps_vol/dp - mat->giveStiffnessMatrices(Ed, Ep, Cd, Cp, mode, gp, tStep); + //auto [Ed, Ep, Cd, Cp] = mat->computeTangents2D(mode, gp, tStep); + auto tangents = mat->computeTangents2D(mode, gp, tStep); - EdB.beProductOf(Ed, B); - K.plusProductSymmUpper(B, EdB, dA); + K.plusProductSymmUpper(B, dot(tangents.dsdd, B), dA); G.plusDyadUnsym(dN_V, Nlin, -dA); - C.plusDyadSymmUpper(Nlin, Cp * dA); - - tmpA.beTProductOf(B, Ep); - Dp.plusDyadUnsym(tmpA, Nlin, dA); - - tmpB.beTProductOf(B, Cd); - DvT.plusDyadUnsym(Nlin, tmpB, dA); + Dp.plusDyadUnsym(Tdot(B, tangents.dsdp), Nlin, dA); + DvT.plusDyadUnsym(Nlin, Tdot(B, tangents.dedd), dA); + C.plusDyadSymmUpper(Nlin, tangents.dedp * dA); } K.symmetrized(); C.symmetrized(); - FloatMatrix GTDvT, GDp; - GTDvT.beTranspositionOf(G); - GTDvT.add(DvT); - GDp = G; - GDp.add(Dp); + auto GTDvT = transpose(G) + DvT; + auto GDp = G + Dp; answer.resize(15, 15); answer.zero(); diff --git a/src/fm/tr21stokes.h b/src/fm/tr21stokes.h index 68e9d2412..6f7c17f8d 100644 --- a/src/fm/tr21stokes.h +++ b/src/fm/tr21stokes.h @@ -71,30 +71,29 @@ public SpatialLocalizerInterface public: Tr21Stokes(int n, Domain * d); - virtual ~Tr21Stokes(); - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual void computeGaussPoints(); + void computeGaussPoints() override; - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep); + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override; + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) override; void computeInternalForcesVector(FloatArray &answer, TimeStep *tStep); void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); void computeExternalForcesVector(FloatArray &answer, TimeStep *tStep); - virtual void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true); + void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; + void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true) override; - virtual const char *giveClassName() const { return "Tr21Stokes"; } - virtual const char *giveInputRecordName() const { return _IFT_Tr21Stokes_Name; } - virtual MaterialMode giveMaterialMode() { return _2dFlow; } + const char *giveClassName() const override { return "Tr21Stokes"; } + const char *giveInputRecordName() const override { return _IFT_Tr21Stokes_Name; } + MaterialMode giveMaterialMode() override { return _2dFlow; } - virtual int computeNumberOfDofs(); + int computeNumberOfDofs() override; - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; /** * Gives the dof ID mask for the element. @@ -102,16 +101,15 @@ public SpatialLocalizerInterface * @param inode Node to check. * @param answer List of dof IDs. */ - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual void computeField(ValueModeType u, TimeStep *tStep, const FloatArray &coords, FloatArray &answer); + void computeField(ValueModeType u, TimeStep *tStep, const FloatArray &coords, FloatArray &answer) override; - // Nodal averaging interface: - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; }; } // end namespace oofem #endif // tr21stokes_h diff --git a/src/fm/tractionpressurebc.h b/src/fm/tractionpressurebc.h index cffe895d4..8195a34bc 100644 --- a/src/fm/tractionpressurebc.h +++ b/src/fm/tractionpressurebc.h @@ -53,14 +53,12 @@ class TractionPressureBC : public BoundaryCondition * @param d Domain to which new object will belongs. */ TractionPressureBC(int i, Domain * d) : BoundaryCondition(i, d) { } - /// Destructor. - virtual ~TractionPressureBC() { } - virtual double give(Dof *dof, ValueModeType mode, double time); + double give(Dof *dof, ValueModeType mode, double time) override; - virtual void scale(double s) { } - virtual const char *giveClassName() const { return "TractionPressureBC"; } - virtual const char *giveInputRecordName() const { return _IFT_TractionPressureBC_Name; } + void scale(double s) override { } + const char *giveClassName() const override { return "TractionPressureBC"; } + const char *giveInputRecordName() const override { return _IFT_TractionPressureBC_Name; } }; } // end namespace oofem #endif // tractionpressurebc_h diff --git a/src/main/benchmark.C b/src/main/benchmark.C new file mode 100644 index 000000000..d87f35416 --- /dev/null +++ b/src/main/benchmark.C @@ -0,0 +1,516 @@ +#include + +#include "fei2dtrlin.h" +#include "fei2dtrquad.h" + +#include "fei2dquadlin.h" +#include "fei2dquadquad.h" +#include "fei2dquadbiquad.h" + +#include "fei3dhexalin.h" +#include "fei3dhexaquad.h" + +#include "floatarrayf.h" +#include "floatmatrixf.h" +#include "sm/Materials/structuralmaterial.h" + +using namespace oofem; + +#if 1 +static void PrincipalValuesDyn(benchmark::State& state) { + FloatArray s = {1., 4., 6., 5., 3., 2.}; + FloatArray v(3); + for (auto _ : state) { + StructuralMaterial::computePrincipalValues(v, s, principal_stress); + benchmark::DoNotOptimize(s); + benchmark::DoNotOptimize(v); + } +} +BENCHMARK(PrincipalValuesDyn); + + +static void PrincipalValuesFix(benchmark::State& state) { + FloatArrayF<6> s = {1., 4., 6., 5., 3., 2.}; + for (auto _ : state) { + auto v = StructuralMaterial::computePrincipalValues(from_voigt_stress(s)); + benchmark::DoNotOptimize(s); + benchmark::DoNotOptimize(v); + } +} +BENCHMARK(PrincipalValuesFix); + + +static void EigDyn(benchmark::State& state) { +#if 0 + FloatMatrix D = { + {1., 2., 3., 0., 0., 0.}, + {2., -4., 5., 0., 1., 10.}, + {3., 5., 6., 4., 0., 0.}, + {0., 0., 4., 10., 0., 0.}, + {0., 1., 0., 0., 20., 0.}, + {0., 10., 0., 0., 0., 10.}, + }; +#elif 0 + FloatMatrix D = { + {1, 3}, + {3, 5}, + }; +#else + FloatMatrix D = { + {1, 2, 3}, + {2, 4, 5}, + {3, 5, 6}, + }; +#endif + FloatArray e(3); + FloatMatrix v(3,3); + for (auto _ : state) { + D.jaco_(e, v, 10); + benchmark::DoNotOptimize(e); + benchmark::DoNotOptimize(v); + } +} +BENCHMARK(EigDyn); + + +static void EigFix(benchmark::State& state) { +#if 0 + FloatMatrixF<6,6> D = { + 1., 2., 3., 0., 0., 0., + 2., -4., 5., 0., 1., 10., + 3., 5., 6., 4., 0., 0., + 0., 0., 4., 10., 0., 0., + 0., 1., 0., 0., 20., 0., + 0., 10., 0., 0., 0., 10., + }; +#elif 0 + FloatMatrixF<2,2> D = { + 1., 3., + 3., 5., + }; +#else + FloatMatrixF<3,3> D = { + 1., 2., 3., + 2., 4., 5., + 3., 5., 6., + }; +#endif + for (auto _ : state) { + auto tmp = eig(D, 10); + benchmark::DoNotOptimize(tmp); + benchmark::DoNotOptimize(D); + } +} +BENCHMARK(EigFix); + + +static void SolDyn(benchmark::State& state) { +#if 1 + FloatMatrix D = { + {1, 2, 3, 7}, + {2, -4, 5, 0}, + {3, 5, 6, 9}, + {7, 0, 9, 10}, + }; + FloatArray x = {1., -2., 3., -4.}; +#elif 0 + FloatMatrix D = { + {1, 3}, + {3, 5}, + }; +#else + FloatMatrix D = { + {1, 2, 3}, + {2, -4, 5}, + {3, 5, 6}, + }; + FloatArray x = {1., -2., 3.}; +#endif + FloatArray s; + FloatMatrix D2; + for (auto _ : state) { + D2 = D; + D2.solveForRhs(x, s); + benchmark::DoNotOptimize(s); + benchmark::DoNotOptimize(D2); + benchmark::DoNotOptimize(D); + } +} +BENCHMARK(SolDyn); + + +static void SolFix(benchmark::State& state) { +#if 1 + FloatMatrixF<4,4> D = { + 1., 2., 3., 7., + 2., -4., 5., 0., + 3., 5., 6., 9., + 7., 0., 9., 10., + }; + FloatArrayF<4> x = {1., -2., 3., -4.}; +#elif 0 + FloatMatrixF<2,2> D = { + 1., 3., + 3., 5., + }; +#else + FloatMatrixF<3,3> D = { + 1., 2., 3., + 2., -4., 5., + 3., 5., 6., + }; + FloatArrayF<3> x = {1., -2., 3.}; +#endif + for (auto _ : state) { + auto tmp = solve(D, x); + //auto tmp = dot(inv(D), x); + benchmark::DoNotOptimize(tmp); + benchmark::DoNotOptimize(D); + benchmark::DoNotOptimize(x); + } +} +BENCHMARK(SolFix); + + +static void InvDyn(benchmark::State& state) { +#if 1 + FloatMatrix D = { + {1, 2, 3, 7}, + {2, -4, 5, 0}, + {3, 5, 6, 9}, + {7, 0, 9, 10}, + }; +#elif 0 + FloatMatrix D = { + {1, 3}, + {3, 5}, + }; +#else + FloatMatrix D = { + {1, 2, 3}, + {2, -4, 5}, + {3, 5, 6}, + }; +#endif + FloatMatrix v(3,3); + for (auto _ : state) { + v.beInverseOf(D); + benchmark::DoNotOptimize(v); + } +} +BENCHMARK(InvDyn); + + +static void InvFix(benchmark::State& state) { +#if 1 + FloatMatrixF<4,4> D = { + 1., 2., 3., 7., + 2., -4., 5., 0., + 3., 5., 6., 9., + 7., 0., 9., 10., + }; +#elif 0 + FloatMatrixF<2,2> D = { + 1., 3., + 3., 5., + }; +#else + FloatMatrixF<3,3> D = { + 1., 2., 3., + 2., -4., 5., + 3., 5., 6., + }; +#endif + for (auto _ : state) { + auto tmp = inv(D); + benchmark::DoNotOptimize(tmp); + benchmark::DoNotOptimize(D); + } +} +BENCHMARK(InvFix); + + + +static void CopyD(benchmark::State& state) { + FloatMatrix D(3,3); + double E = 210; + double nu = 0.3; + double G = (E / ( 2.0 * ( 1. + nu ) )); + //double K = E / ( 3.0 * ( 1. - 2. * nu ) ); + double ee = E / ( 1. - nu * nu ); + FloatMatrixF<3,3> tangent = { + ee, nu*ee, 0., + nu*ee, ee, 0., + 0., 0., G + }; + + for (auto _ : state) { + auto xxx = tangent; + benchmark::DoNotOptimize(xxx); + } +} +BENCHMARK(CopyD); + +static void ComputeD(benchmark::State& state) { + //FloatMatrix D(3,3); + double E = 210; + double nu = 0.3; + double G = (E / ( 2.0 * ( 1. + nu ) )); + for (auto _ : state) { + double e = E; + double ee = e / ( 1. - nu * nu ); + double shear = G; + FloatMatrixF<3,3> D; + D.at(1, 1) = ee; + D.at(1, 2) = nu * ee; + D.at(2, 1) = nu * ee; + D.at(2, 2) = ee; + D.at(3, 3) = shear; + benchmark::DoNotOptimize(D); + } +} +BENCHMARK(ComputeD); +#endif + +#if 0 +const std::vector> nodes_6 = { + FloatArrayF<3>{0.,0.,0.},FloatArrayF<3>{2.,0.,0.},FloatArrayF<3>{0.,1.,0.}, + FloatArrayF<3>{1.,0.,0.},FloatArrayF<3>{1.,0.6,0.},FloatArrayF<3>{0.,0.5,0.}, +}; + +const std::vector> nodes_8 = { + FloatArrayF<3>{-1.,-1., 1.},FloatArrayF<3>{-1.,1., 1.},FloatArrayF<3>{1.,1., 1.},FloatArrayF<3>{1.,-1., 1.}, + FloatArrayF<3>{-1.,-1.,-1.},FloatArrayF<3>{-1.,1.,-1.},FloatArrayF<3>{1.,1.,-1.},FloatArrayF<3>{1.,-1.,-1.}, +}; + +const std::vector> nodes_20 = { + FloatArrayF<3>{-1.,-1., 1.},FloatArrayF<3>{-1.,1., 1.},FloatArrayF<3>{1.,1., 1.},FloatArrayF<3>{1.,-1., 1.}, + FloatArrayF<3>{-1.,-1.,-1.},FloatArrayF<3>{-1.,1.,-1.},FloatArrayF<3>{1.,1.,-1.},FloatArrayF<3>{1.,-1.,-1.}, + FloatArrayF<3>{-1., 0., 1.},FloatArrayF<3>{ 0.,1., 1.},FloatArrayF<3>{1.,0., 1.},FloatArrayF<3>{0.,-1., 1.}, + FloatArrayF<3>{-1., 0.,-1.},FloatArrayF<3>{ 0.,1.,-1.},FloatArrayF<3>{1.,0.,-1.},FloatArrayF<3>{0.,-1.,-1.}, + FloatArrayF<3>{-1.,-1., 0.},FloatArrayF<3>{-1.,1., 0.},FloatArrayF<3>{1.,1., 0.},FloatArrayF<3>{1.,-1., 0.} +}; +#else +const std::vector nodes_6 = { + FloatArray{0.,0.,0.},FloatArray{2.,0.,0.},FloatArray{0.,1.,0.}, + FloatArray{1.,0.,0.},FloatArray{1.,0.6,0.},FloatArray{0.,0.5,0.}, +}; + +const std::vector nodes_4 = { + FloatArray{0.,0.2,0.}, FloatArray{1.2,0.,0.}, + FloatArray{1.1,1.1,0.}, FloatArray{0.,1.,0.}, +}; + +const std::vector nodes_8 = { + FloatArray{-1.,-1., 1.},FloatArray{-1.,1., 1.},FloatArray{1.,1., 1.},FloatArray{1.,-1., 1.}, + FloatArray{-1.,-1.,-1.},FloatArray{-1.,1.,-1.},FloatArray{1.,1.,-1.},FloatArray{1.,-1.,-1.}, +}; + +const std::vector nodes_20 = { + FloatArray{-1.,-1., 1.},FloatArray{-1.,1., 1.},FloatArray{1.,1., 1.},FloatArray{1.,-1., 1.}, + FloatArray{-1.,-1.,-1.},FloatArray{-1.,1.,-1.},FloatArray{1.,1.,-1.},FloatArray{1.,-1.,-1.}, + FloatArray{-1., 0., 1.},FloatArray{ 0.,1., 1.},FloatArray{1.,0., 1.},FloatArray{0.,-1., 1.}, + FloatArray{-1., 0.,-1.},FloatArray{ 0.,1.,-1.},FloatArray{1.,0.,-1.},FloatArray{0.,-1.,-1.}, + FloatArray{-1.,-1., 0.},FloatArray{-1.,1., 0.},FloatArray{1.,1., 0.},FloatArray{1.,-1., 0.} +}; +#endif + +const FEIVertexListGeometryWrapper tri_6 = nodes_6; +const FEIVertexListGeometryWrapper quad_4 = nodes_4; +const FEIVertexListGeometryWrapper cube_8 = nodes_8; +const FEIVertexListGeometryWrapper cube_20 = nodes_20; +const FEIVoidCellGeometry void_cell; + + +static void QuadLinN(benchmark::State& state) { + FEI2dQuadLin interp(1,2); + FloatArray lcoords = {0.2, 0.4}; + FloatArray x(4); + for (auto _ : state) { + interp.evalN(x, lcoords, void_cell); + benchmark::DoNotOptimize(x); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(QuadLinN); + +static void QuadLinNFixed(benchmark::State& state) { + FEI2dQuadLin interp(1,2); + FloatArrayF<2> lcoords = {0.2, 0.4}; + for (auto _ : state) { + auto x = interp.evalN(lcoords); + benchmark::DoNotOptimize(x); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(QuadLinNFixed); + + +static void QuadLinB(benchmark::State& state) { + FEI2dQuadLin interp(1,2); + FloatArray lcoords = {0.2, 0.4}; + FloatMatrix x(4,2); + for (auto _ : state) { + interp.evaldNdx(x, lcoords, quad_4); + benchmark::DoNotOptimize(x); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(QuadLinB); + +static void QuadLinBFixed(benchmark::State& state) { + FEI2dQuadLin interp(1,2); + FloatArrayF<2> lcoords = {0.2, 0.4}; + for (auto _ : state) { + auto x = interp.evaldNdx(lcoords, quad_4); + benchmark::DoNotOptimize(x); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(QuadLinBFixed); + + + +static void HexLinN(benchmark::State& state) { + FEI3dHexaLin interp; + FloatArray lcoords = {0.2, 0.4, 0.3}; + FloatArray N(8); + for (auto _ : state) { + interp.evalN(N, lcoords, void_cell); + benchmark::DoNotOptimize(N); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(HexLinN); + +static void HexLinNFixed(benchmark::State& state) { + FEI3dHexaLin interp; + FloatArrayF<3> lcoords = {0.2, 0.4, 0.3}; + for (auto _ : state) { + auto x = interp.evalN(lcoords); + benchmark::DoNotOptimize(x); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(HexLinNFixed); + +static void HexaLinB(benchmark::State& state) { + FEI3dHexaLin interp; + FloatArray lcoords = {0.2, 0.4, 0.3}; + for (auto _ : state) { + FloatMatrix B; + interp.evaldNdx(B, lcoords, cube_8); + benchmark::DoNotOptimize(B); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(HexaLinB); + +static void HexaLinBFixed(benchmark::State& state) { + FEI3dHexaLin interp; + FloatArrayF<3> lcoords = {0.2, 0.4, 0.3}; + for (auto _ : state) { + auto x = interp.evaldNdx(lcoords, cube_8); + benchmark::DoNotOptimize(x); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(HexaLinBFixed); + + +static void HexQuadB(benchmark::State& state) { + FEI3dHexaQuad interp; + FloatArray lcoords = {0.2, 0.4, 0.3}; + for (auto _ : state) { + FloatMatrix B; + interp.evaldNdx(B, lcoords, cube_20); + benchmark::DoNotOptimize(B); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(HexQuadB); + +static void HexQuadBFixed(benchmark::State& state) { + FEI3dHexaQuad interp; + FloatArrayF<3> lcoords = {0.2, 0.4, 0.3}; + for (auto _ : state) { + auto x = interp.evaldNdx(lcoords, cube_20); + benchmark::DoNotOptimize(x); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(HexQuadBFixed); + + +static void HexQuadN(benchmark::State& state) { + FEI3dHexaQuad interp; + FloatArray lcoords = {0.2, 0.4, 0.3}; + FloatArray N(20); + for (auto _ : state) { + interp.evalN(N, lcoords, void_cell); + benchmark::DoNotOptimize(N); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(HexQuadN); + +static void HexQuadNFixed(benchmark::State& state) { + FEI3dHexaQuad interp; + FloatArrayF<3> lcoords = {0.2, 0.4, 0.3}; + for (auto _ : state) { + auto N = interp.evalN(lcoords); + benchmark::DoNotOptimize(N); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(HexQuadNFixed); + + +static void TriQuadN(benchmark::State& state) { + FEI2dTrQuad interp(1,2); + FloatArray lcoords = {0.2, 0.4}; + for (auto _ : state) { + FloatArray N; + interp.evalN(N, lcoords, void_cell); + benchmark::DoNotOptimize(N); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(TriQuadN); + +static void TriQuadNFixed(benchmark::State& state) { + FEI2dTrQuad interp(1,2); + FloatArrayF<2> lcoords = {0.2, 0.4}; + for (auto _ : state) { + auto x = interp.evalN(lcoords); + benchmark::DoNotOptimize(x); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(TriQuadNFixed); + +static void TriQuadB(benchmark::State& state) { + FEI2dTrQuad interp(1,2); + FloatArray lcoords = {0.2, 0.4}; + for (auto _ : state) { + FloatMatrix B; + interp.evaldNdx(B, lcoords, tri_6); + benchmark::DoNotOptimize(B); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(TriQuadB); + +static void TriQuadBFixed(benchmark::State& state) { + FEI2dTrQuad interp(1,2); + FloatArrayF<2> lcoords = {0.2, 0.4}; + for (auto _ : state) { + auto x = interp.evaldNdx(lcoords, tri_6); + benchmark::DoNotOptimize(x); + benchmark::DoNotOptimize(lcoords); + } +} +BENCHMARK(TriQuadBFixed); + + +BENCHMARK_MAIN(); diff --git a/src/main/main.C b/src/main/main.C index f608b79e5..6f6d303a9 100644 --- a/src/main/main.C +++ b/src/main/main.C @@ -35,7 +35,7 @@ // MAIN // Solves finite element problems. // -#ifdef __PYTHON_MODULE +#ifdef _PYTHON_EXTENSION #include #endif @@ -43,6 +43,7 @@ #include "oofemcfg.h" #include "oofemtxtdatareader.h" +#include "datastream.h" #include "util.h" #include "error.h" #include "logger.h" @@ -82,14 +83,8 @@ using namespace oofem; -void freeStoreError() -// This function is called whenever operator "new" is unable to allocate memory. -{ - OOFEM_FATAL("free store exhausted"); -} - // debug -void oofem_debug(EngngModel *emodel); +void oofem_debug(EngngModel &emodel); void oofem_print_help(); void oofem_print_version(); @@ -98,13 +93,42 @@ void oofem_print_epilog(); // Finalize PETSc, SLEPc and MPI void oofem_finalize_modules(); +#define LOG_ERR_HEADER "_______________________________________________________" +#define LOG_ERR_TAIL "_______________________________________________________\a\n" + + +// Handler for uncaught exceptions +void exception_handler() { + try { + auto eptr = std::current_exception(); + if (eptr) { + std::rethrow_exception(eptr); + } + } catch (const RuntimeException& e) { + + fprintf(stderr, "%s\nOOFEM Error exception: %s\n%s", LOG_ERR_HEADER, e.what(), LOG_ERR_TAIL); + #ifdef __GNUC__ + print_stacktrace(); + #endif + oofem_logger.incrementErrorCounter(); + oofem_logger.printStatistics(); + + } catch(const std::exception& e) { + fprintf(stderr, "Caught exception: %s\n", e.what()); +#ifdef __GNUC__ + print_stacktrace(); +#endif + exit(1); + } +} + + int main(int argc, char *argv[]) { -#ifndef _MSC_VER - std :: set_new_handler(freeStoreError); // prevents memory overflow -#endif + // Stack trace on uncaught exceptions; + std::set_terminate( exception_handler ); - int adaptiveRestartFlag = 0, restartStep; + int adaptiveRestartFlag = 0, restartStep = 0; bool parallelFlag = false, renumberFlag = false, debugFlag = false, contextFlag = false, restartFlag = false, inputFileFlag = false, outputFileFlag = false, errOutputFileFlag = false; std :: stringstream inputFileName, outputFileName, errOutputFileName; @@ -238,7 +262,7 @@ int main(int argc, char *argv[]) SlepcInitialize(& modulesArgc, & modulesArgv, PETSC_NULL, PETSC_NULL); #endif -#ifdef __PYTHON_MODULE +#ifdef _PYTHON_EXTENSION Py_Initialize(); // Adding . to the system path allows us to run Python functions stored in the working directory. PyRun_SimpleString("import sys"); @@ -262,8 +286,8 @@ int main(int argc, char *argv[]) // print header to redirected output OOFEM_LOG_FORCED(PRG_HEADER_SM); - OOFEMTXTDataReader dr( inputFileName.str ( ).c_str() ); - EngngModel *problem = :: InstanciateProblem(& dr, _processor, contextFlag, NULL, parallelFlag); + OOFEMTXTDataReader dr( inputFileName.str() ); + auto problem = :: InstanciateProblem(dr, _processor, contextFlag, NULL, parallelFlag); dr.finish(); if ( !problem ) { OOFEM_LOG_ERROR("Couldn't instanciate problem, exiting"); @@ -279,11 +303,12 @@ int main(int argc, char *argv[]) if ( restartFlag ) { try { - //FileDataStream stream(this->giveContextFileName(restartStep, 0), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - int restartStepInfo [ 2 ] = {restartStep, 0}; - problem->restoreContext(NULL, CM_State | CM_Definition, ( void * ) restartStepInfo); - } catch(ContextIOERR & c) { + FileDataStream stream(problem->giveContextFileName(restartStep, 0), false); + problem->restoreContext(stream, CM_State | CM_Definition); + } catch ( const FileDataStream::CantOpen & e ) { + printf("%s", e.what()); + exit(1); + } catch ( ContextIOERR & c ) { c.print(); exit(1); } @@ -295,14 +320,14 @@ int main(int argc, char *argv[]) } if ( debugFlag ) { - oofem_debug(problem); + oofem_debug(*problem); } try { problem->solveYourself(); } catch(OOFEM_Terminate & c) { - delete problem; + problem = nullptr; oofem_finalize_modules(); @@ -316,7 +341,7 @@ int main(int argc, char *argv[]) } #endif oofem_logger.printStatistics(); - delete problem; + problem = nullptr; oofem_finalize_modules(); @@ -371,21 +396,27 @@ void oofem_finalize_modules() MPI_Finalize(); #endif -#ifdef __PYTHON_MODULE +#ifdef _PYTHON_EXTENSION Py_Finalize(); #endif } //#include "loadbalancer.h" //#include "xfem/iga.h" - -void oofem_debug(EngngModel *emodel) +#include "floatmatrix.h" +#include "domain.h" +#include "element.h" +void oofem_debug(EngngModel &emodel) { + FloatMatrix k; + emodel.giveDomain(1)->giveElement(1)->giveCharacteristicMatrix(k, ConductivityMatrix, NULL); + emodel.giveDomain(1)->giveElement(1)->giveCharacteristicMatrix(k, CapacityMatrix, NULL); + //FloatMatrix k; - //((BsplinePlaneStressElement*)emodel->giveDomain(1)->giveElement(1))->giveCharacteristicMatrix(k, StiffnessMatrix, NULL); + //((BsplinePlaneStressElement*)emodel.giveDomain(1)->giveElement(1))->giveCharacteristicMatrix(k, StiffnessMatrix, NULL); #ifdef __PARALLEL_MODE - //LoadBalancer* lb = emodel->giveDomain(1)->giveLoadBalancer(); + //LoadBalancer* lb = emodel.giveDomain(1)->giveLoadBalancer(); //lb->calculateLoadTransfer(); //lb->migrateLoad(); //exit(1); diff --git a/src/main/oofeg.C b/src/main/oofeg.C index cb2ead64a..4a3139323 100644 --- a/src/main/oofeg.C +++ b/src/main/oofeg.C @@ -40,7 +40,7 @@ #include "timestep.h" #include "error.h" #include "oofeggraphiccontext.h" - +#include "datastream.h" #include "connectivitytable.h" #include "mathfem.h" @@ -123,7 +123,7 @@ static XtActionsRec oofeg_remap_return[] = { static int oofeg_box_setup = 0; static int oofeg_axes = 1; -EngngModel *problem; +std::unique_ptr problem; @@ -362,9 +362,10 @@ main(int argc, char *argv[]) std :: string jobName = temp.substr(k); std :: string viewTitle = "OOFEG (" + jobName + ")"; - problem = InstanciateProblem(& dr, _postProcessor, 0, NULL, parallelFlag); + problem = InstanciateProblem(dr, _postProcessor, 0, NULL, parallelFlag); dr.finish(); problem->checkProblemConsistency(); + problem->init(); #ifdef OOFEG_DEVEL mask = ESI_GRAPHIC_EDITOR_MASK; @@ -387,7 +388,7 @@ main(int argc, char *argv[]) const_cast< char * >(OOFEG_DEFAULTDRAW_COLOR), 500, 400); EVSetRenderMode(myview, WIRE_RENDERING); EMAttachView(age_model, myview); - gc [ 0 ].init(problem); // init all gcs + gc [ 0 ].init(problem.get()); // init all gcs // AugmentCommandTable(); @@ -888,7 +889,7 @@ void ESICustomize(Widget parent_pane) oofeg_add_palette("< Filters >", parent_pane, & filters_palette); oofeg_add_palette("< Material Region Filter >", filters_palette, & matregfilter_palette); for ( int id = 1; id <= problem->giveNumberOfDomains(); id++ ) { - nmat = problem->giveDomain(id)->giveNumberOfMaterialModels(); + nmat = problem->giveDomain(id)->giveNumberOfRegions(); for ( i = 1; i <= nmat; i++ ) { sprintf(ltname, "region %2d.%2d", id, i); @@ -953,15 +954,13 @@ void OOFEGSimpleCmd(char *buf) pstep = gc [ 0 ].getActiveStep(); istep = atoi(remain); try { - //FileDataStream stream(this->giveContextFileName(istep, iversion), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State | CM_Definition); + FileDataStream stream(problem->giveContextFileName(istep, iversion), false); + problem->restoreContext(stream, CM_State | CM_Definition); } catch(ContextIOERR & m) { m.print(); try { - //FileDataStream stream(this->giveContextFileName(pstep, iversion), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State | CM_Definition); + FileDataStream stream(problem->giveContextFileName(pstep, iversion), false); + problem->restoreContext(stream, CM_State | CM_Definition); } catch(ContextIOERR & m2) { m2.print(); exit(1); @@ -974,20 +973,9 @@ void OOFEGSimpleCmd(char *buf) //problem ->forceEquationNumbering(); } else if ( !strncmp(cmd, "active_eigen_value", 18) ) { - istep = atoi(remain); - gc [ 0 ].setActiveStep(istep); - int stepinfo [ 2 ]; - stepinfo [ 0 ] = istep; - stepinfo [ 1 ] = iversion; - try { - //FileDataStream stream(this->giveContextFileName(istep, iversion), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State | CM_Definition, ( void * ) stepinfo); - } catch(ContextIOERR & m) { - m.print(); - exit(1); - } - gc [ 0 ].setActiveEigVal(istep); + double ieig = atoi(remain); + problem->setActiveVector(ieig); + gc [ 0 ].setActiveEigVal(ieig); } else if ( !strncmp(cmd, "set_def_scale", 13) ) { gc [ 0 ].setDefScale( strtod(remain, NULL) ); if ( strtod(remain, NULL) < 0 ) { @@ -1132,63 +1120,48 @@ int updateDefPlotFlag() void nextStep(Widget wid, XtPointer cl, XtPointer cd) { - int istep, prevStep, stepStep, prevStepVersion, istepVersion; - int stepInfo [ 2 ]; - - stepStep = problem->giveContextOutputStep(); + int stepStep = problem->giveContextOutputStep(); if ( stepStep == 0 ) { stepStep = 1; } if ( gc [ 0 ].getActiveStep() != -1 ) { - prevStep = gc [ 0 ].getActiveStep(); - prevStepVersion = gc [ 0 ].getActiveStepVersion(); + int prevStep = gc [ 0 ].getActiveStep(); + int prevStepVersion = gc [ 0 ].getActiveStepVersion(); // first try next version for the same step - if ( problem->testContextFile(prevStep, prevStepVersion + 1) ) { - istepVersion = prevStepVersion + 1; - stepInfo [ 0 ] = prevStep; - stepInfo [ 1 ] = istepVersion; - printf("OOFEG: restoring context file %d.%d\n", stepInfo [ 0 ], stepInfo [ 1 ]); + int istepVersion = prevStepVersion + 1; + try { + FileDataStream stream(problem->giveContextFileName(prevStep, istepVersion), false); + printf("OOFEG: restoring context file %d.%d\n", prevStep, istepVersion); try { - //FileDataStream stream(this->giveContextFileName(prevStep, istepVersion), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State| CM_Definition, ( void * ) stepInfo); + problem->restoreContext(stream, CM_State | CM_Definition); } catch(ContextIOERR & m) { m.print(); istepVersion = 0; - stepInfo [ 0 ] = prevStep; - stepInfo [ 1 ] = 0; try { - //FileDataStream stream(this->giveContextFileName(prevStep, 0), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State | CM_Definition, ( void * ) stepInfo); - } catch(ContextIOERR & m2) { + FileDataStream stream(problem->giveContextFileName(prevStep, 0), false); + problem->restoreContext(stream, CM_State | CM_Definition); + } catch ( ContextIOERR & m2 ) { m2.print(); exit(1); } } gc [ 0 ].setActiveStep(prevStep); gc [ 0 ].setActiveStepVersion(istepVersion); - } else { + } catch ( const FileDataStream::CantOpen &e ) { // no next version exist => next step with version 0 - istep = prevStep + stepStep; - stepInfo [ 0 ] = istep; - stepInfo [ 1 ] = 0; + int istep = prevStep + stepStep; //printf ("NextStep: prevStep %d, nstep %d, stepStep %d\n", prevStep, istep, stepStep); try { - //FileDataStream stream(this->giveContextFileName(prevStep + stepStep, 0);, false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State| CM_Definition, ( void * ) stepInfo); + FileDataStream stream(problem->giveContextFileName(prevStep + stepStep, 0), false); + problem->restoreContext(stream, CM_State | CM_Definition); } catch(ContextIOERR & m) { m.print(); - stepInfo [ 0 ] = prevStep; - stepInfo [ 1 ] = 0; try { - //FileDataStream stream(this->giveContextFileName(prevStep, 0), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State| CM_Definition, ( void * ) stepInfo); + FileDataStream stream(problem->giveContextFileName(prevStep, 0), false); + problem->restoreContext(stream, CM_State | CM_Definition); } catch(ContextIOERR & m2) { m2.print(); exit(1); @@ -1199,14 +1172,11 @@ void nextStep(Widget wid, XtPointer cl, XtPointer cd) gc [ 0 ].setActiveStepVersion(0); } } else { - istep = problem->giveNumberOfFirstStep() + stepStep - 1; + int istep = problem->giveNumberOfFirstStep() + stepStep - 1; gc [ 0 ].setActiveStep(istep); - stepInfo [ 0 ] = istep; - stepInfo [ 1 ] = 0; try { - //FileDataStream stream(this->giveContextFileName(istep, 0), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State| CM_Definition, ( void * ) stepInfo); + FileDataStream stream(problem->giveContextFileName(istep, 0), false); + problem->restoreContext(stream, CM_State | CM_Definition); } catch(ContextIOERR & m) { m.print(); exit(1); @@ -1219,7 +1189,6 @@ void nextStep(Widget wid, XtPointer cl, XtPointer cd) void previousStep(Widget wid, XtPointer cl, XtPointer cd) { int istep, prevStep, stepStep = problem->giveContextOutputStep(); - int stepInfo [ 2 ]; if ( stepStep == 0 ) { stepStep = 1; } @@ -1228,20 +1197,14 @@ void previousStep(Widget wid, XtPointer cl, XtPointer cd) prevStep = gc [ 0 ].getActiveStep(); istep = prevStep - stepStep; if ( istep >= 0 ) { - stepInfo [ 0 ] = istep; - stepInfo [ 1 ] = 0; try { - //FileDataStream stream(this->giveContextFileName(istep, 0), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State | CM_Definition, ( void * ) stepInfo); + FileDataStream stream(problem->giveContextFileName(istep, 0), false); + problem->restoreContext(stream, CM_State | CM_Definition); } catch(ContextIOERR & m) { m.print(); - stepInfo [ 0 ] = prevStep; - stepInfo [ 1 ] = 0; try { - //FileDataStream stream(this->giveContextFileName(prevStep, 0), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State | CM_Definition, ( void * ) stepInfo); + FileDataStream stream(problem->giveContextFileName(prevStep, 0), false); + problem->restoreContext(stream, CM_State | CM_Definition); } catch(ContextIOERR & m2) { m2.print(); exit(1); @@ -1255,12 +1218,9 @@ void previousStep(Widget wid, XtPointer cl, XtPointer cd) istep = 1; gc [ 0 ].setActiveStep(istep); gc [ 0 ].setActiveStepVersion(0); - stepInfo [ 0 ] = istep; - stepInfo [ 1 ] = 0; try { - //FileDataStream stream(this->giveContextFileName(istep, 0), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State | CM_Definition, ( void * ) stepInfo); + FileDataStream stream(problem->giveContextFileName(istep, 0), false); + problem->restoreContext(stream, CM_State | CM_Definition); } catch(ContextIOERR & m) { m.print(); exit(1); @@ -2196,7 +2156,6 @@ pass_setanimate_command(Widget w, XtPointer ptr, XtPointer call_data) Arg al [ 2 ]; char *s; int estep, sstep; - int stepinfo [ 2 ]; int istep, iversion = 0; ac = 0; @@ -2225,12 +2184,9 @@ pass_setanimate_command(Widget w, XtPointer ptr, XtPointer call_data) } for ( istep = sstep; istep <= estep; istep++ ) { - stepinfo [ 0 ] = istep; - stepinfo [ 1 ] = iversion; try { - //FileDataStream stream(this->giveContextFileName(istep, iversion), false); - //problem->restoreContext(stream, CM_State | CM_Definition); - problem->restoreContext(NULL, CM_State | CM_Definition, ( void * ) stepinfo); + FileDataStream stream(problem->giveContextFileName(istep, iversion), false); + problem->restoreContext(stream, CM_State | CM_Definition); } catch(ContextIOERR & m) { m.print(); return; @@ -2808,7 +2764,7 @@ void debug_run(Widget w, XtPointer ptr, XtPointer call_data) gc [ 0 ].setActiveStep(0); problem->solveYourself(); } catch(OOFEM_Terminate & c) { - delete problem; + problem = nullptr; #ifdef __PETSC_MODULE PetscFinalize(); #endif diff --git a/src/mpm/CMakeLists.txt b/src/mpm/CMakeLists.txt new file mode 100644 index 000000000..cbf4a1d29 --- /dev/null +++ b/src/mpm/CMakeLists.txt @@ -0,0 +1,18 @@ +set (mpm_element + termlibrary.C + prototype.C + up.C + ) +set (mpm_problems + mpmproblem.C + ) + +set (mpm + ${mpm_element} + ${mpm_problems} + ) + +add_library (mpm + ${LIB_TYPE} + ${mpm} + ) diff --git a/src/mpm/mpm.h b/src/mpm/mpm.h new file mode 100644 index 000000000..398213edb --- /dev/null +++ b/src/mpm/mpm.h @@ -0,0 +1,236 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef mpm_h +#define mpm_h + +/** + * Multiphysics module + * Classes: + * - ElementBase(Element) defining geometry + * - Variable class representing unknown field (or test feld) in a weak psolution. The variable has its interpolation, type (scalar, vector), size. + When test field, it keeps reference to its primary (unknown) variable. The history parameter dermines how many time steps to remember. + * - Term class represnting a term to evaluate on element. Paramaters element(geometry), variables + * - Element - responsible for defining and performing integration (of terms), assembly of term contributions. + */ + +#include "element.h" +#include "dofmanager.h" +#include "gausspoint.h" +#include "feinterpol.h" +#include "intarray.h" +#include "classfactory.h" + + +namespace oofem { + +class MPElement; + +/* + * Note: someone should be able to return for given cell and variable vector of unknowns. + * this depends on interpolation (constant, linear, etc), cell type and variable (defined the physical meaning of unknown(s)) + * Interpolation should identify (or even introduce) cell nodes needed (quadratic element, linear interpolation), variable should assign to these nodes DOFs. + * interpolation.getCellNodes(cell) + */ + +/** + * @brief Class representing unknown field (or test feld) in a weak psolution. + * The variable has its interpolation, type (scalar, vector), size. + * When test (dual) field, it keeps reference to its primary (unknown) variable. + * @todo The history parameter dermines how many time steps to remember. + */ +class Variable { + public: + enum VariableType { + scalar, + vector + }; + + enum VariableQuantity { + Displacement, + Temperature, + Pressure + }; + + const FEInterpolation& interpolation; + Variable* dualVar; //? or just bool? + VariableType type; + VariableQuantity q; + int size; + IntArray dofIDs; + + Variable (const FEInterpolation& i, Variable::VariableQuantity q, Variable::VariableType t, int size, Variable* dual = NULL, std :: initializer_list< int > dofIDs={}) : + interpolation(i), + dualVar(dual), + q(q), + dofIDs(dofIDs) { + this->type = t; + this->size = size; + } + + /// Returns DodIF mask in node; need generalization (which dofMan) + const IntArray& getDofManDofIDs () const {return this->dofIDs;} +}; + + +/** + * @brief Class representing a weak form expression to be evaluated (integrated). + */ +class Term { + public: + const Variable& field; + const Variable& testField; + + public: + Term (const Variable &testField, const Variable& unknownField) : field(unknownField), testField(testField) {} + + // evaluate term contribution to weak form on given cell at given point + virtual void evaluate_dw (FloatMatrix& , MPElement& cell, GaussPoint* gp, TimeStep* tStep) const =0; + // evaluate contribution (all vars known) on given cell + virtual void evaluate_c (FloatArray&, MPElement& cell, GaussPoint* gp, TimeStep* tStep) const =0; + virtual void getDimensions_dw(Element& cell) const =0; + virtual void initializeCell(Element& cell) const =0; +}; + + +/** +* Element code sample: +* term=Poison(Variable(interpolation, Temperature, 1), Variable(Interpolation, Temperature,1)); +* this-> Assemble(integrationRule, term, destination); // where to integrate (volume, surface,edge?) +* +*/ + +/** + * @brief Base class for elements based on mp (multi-physics) concept + * + */ +class MPElement : public Element { + public: + + MPElement (int n, Domain * aDomain) : + Element(n, aDomain) + {} + + void initialize () { + // loop over variables and allocate nodal dofs (for unknownFields) + } + + void integrateTerm_dw (FloatMatrix& answer, const Term& term, IntegrationRule* iRule, TimeStep* tstep) { + // need for integration domain and rule. + // who should determine integration domain? Element or term? Term is just integrand, not integral + // so integral type (surface, volume, etc) defined by element --- + FloatMatrix dw; + for ( GaussPoint *igp : * iRule ) { + term.evaluate_dw(dw, *this, igp, tstep); + dw.times(this->computeVolumeAround(igp)); + answer.add(dw); + } + } + + void integrateTerm_c (FloatArray& answer, const Term& term, IntegrationRule* iRule, TimeStep* tstep) { + // need for integration domain and rule. + // who should determine integration domain? Element or term? Term is just integrand, not integral + // so integral type (surface, volume, etc) defined by element --- + FloatArray dw; + for ( GaussPoint *igp : * iRule ) { + term.evaluate_c(dw, *this, igp, tstep); + dw.times(this->computeVolumeAround(igp)); + answer.add(dw); + } + } + + /// @brief returns local code number on element to assemble variable/term contribution + /// @param answer + /// @param v + void getLocalCodeNumbers (IntArray& answer, const Variable& v) const { + getLocalCodeNumbers(answer, v.q); + } + + /** + * Returns local code numbers corresponding to specific variable identified by variablequantity. + * This essentialy allows to assemble partial element contributions separately. + * It is assumed, that partial element contributions are obtained using standard + * getCharacteristicMatrix and getCharacteristicVector methods. + * @param answer code numbers corrresponding to given variable + * @param q variable type + */ + virtual void getLocalCodeNumbers (IntArray& answer, const Variable::VariableQuantity q ) const = 0; + + /// @brief Assembles the partial element contribution into local element matrix + /// @param answer + /// @param contrib + /// @param t + void assembleTermContribution (FloatMatrix& answer, FloatMatrix& contrib, const Term& t) { + IntArray uloc, tloc; + this->getLocalCodeNumbers(uloc, t.field); + this->getLocalCodeNumbers(tloc, t.testField); + answer.assemble(contrib, tloc, uloc); + } + + void assembleTermContributionT (FloatMatrix& answer, FloatMatrix& contrib, const Term& t) { + IntArray uloc, tloc; + this->getLocalCodeNumbers(uloc, t.field); + this->getLocalCodeNumbers(tloc, t.testField); + answer.assembleT(contrib, tloc, uloc); + } + + void assembleTermContribution (FloatArray& answer, FloatArray& contrib, const Term& t) { + IntArray loc; + this->getLocalCodeNumbers(loc, t.testField); + answer.assemble(contrib, loc); + } + + /** + * @brief Returns vector of nodal unknows for given Variable + * + * @param answer + * @param field + * @param tstep + */ + void getUnknownVector(FloatArray& answer, const Variable& field, ValueModeType mode, TimeStep* tstep) { + FloatArray uloc; + IntArray nodes, dofs; + field.interpolation.giveCellDofMans(nodes, this); + for (int i : nodes) { + dofs=field.getDofManDofIDs(); + this->giveDofManager(i)->giveUnknownVector(uloc, dofs, mode, tstep); + answer.append(uloc); + } + } +}; + + + + +} // end namespace oofem +#endif // mpm_h \ No newline at end of file diff --git a/src/mpm/mpmproblem.C b/src/mpm/mpmproblem.C new file mode 100644 index 000000000..52b467506 --- /dev/null +++ b/src/mpm/mpmproblem.C @@ -0,0 +1,616 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mpmproblem.h" +#include "timestep.h" +#include "element.h" +#include "dofmanager.h" +#include "dof.h" +#include "dictionary.h" +#include "verbose.h" +#include "classfactory.h" +#include "mathfem.h" +#include "assemblercallback.h" +#include "unknownnumberingscheme.h" +#include "dofdistributedprimaryfield.h" +#include "primaryfield.h" +#include "mpm.h" + +namespace oofem { +REGISTER_EngngModel(MPMProblem); + +MPMLhsAssembler :: MPMLhsAssembler(double alpha, double deltaT) : + MatrixAssembler(), alpha(alpha), deltaT(deltaT) +{} + + +void MPMLhsAssembler :: matrixFromElement(FloatMatrix &answer, Element &el, TimeStep *tStep) const +{ + FloatMatrix contrib; + IntArray locu, locp; + MPElement *e = dynamic_cast(&el); + int ndofs = e->giveNumberOfDofs(); + answer.resize(ndofs, ndofs); + answer.zero(); + + e->getLocalCodeNumbers (locu, Variable::VariableQuantity::Displacement); + e->getLocalCodeNumbers (locp, Variable::VariableQuantity::Pressure); + + e->giveCharacteristicMatrix(contrib, MomentumBalance_StiffnessMatrix, tStep); + contrib.times(this->alpha); + answer.assemble(contrib, locu, locu); + e->giveCharacteristicMatrix(contrib, MomentumBalance_PressureCouplingMatrix, tStep); + contrib.times((-1.0)*this->alpha); + answer.assemble(contrib, locu, locp); + + e->giveCharacteristicMatrix(contrib, MassBalance_PermeabilityMatrix, tStep); + contrib.times((-1.0)*this->alpha*this->alpha*this->deltaT); + answer.assemble(contrib, locp, locp); + e->giveCharacteristicMatrix(contrib, MassBalance_CompresibilityMatrix, tStep); + contrib.times((-1.0)*this->alpha); + answer.assemble(contrib, locp, locp); + e->giveCharacteristicMatrix(contrib, MassBalance_StressCouplingMatrix, tStep); + contrib.times((-1.0)*this->alpha); + answer.assemble(contrib, locp, locu); +} + +void MPMRhsAssembler :: vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const +{ + vec.clear(); + FloatArray contrib; + IntArray locu, locp; + MPElement *e = dynamic_cast(&element); + e->getLocalCodeNumbers (locu, Variable::VariableQuantity::Displacement); + e->getLocalCodeNumbers (locp, Variable::VariableQuantity::Pressure); + + //e->giveCharacteristicVector(contrib, MomentumBalance_Rhs, mode, tStep); + vec.assemble(contrib, locu); + //e->giveCharacteristicVector(contrib, MassBalance_Rhs, mode, tStep); + contrib.times((-1.0)*this->alpha*this->deltaT); + vec.assemble(contrib, locp); +} +void MPMResidualAssembler :: vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const +{ + FloatArray contrib; + IntArray locu, locp; + MPElement *e = dynamic_cast(&element); + int ndofs = e->giveNumberOfDofs(); + vec.resize(ndofs); + vec.zero(); + + e->getLocalCodeNumbers (locu, Variable::VariableQuantity::Displacement); + e->getLocalCodeNumbers (locp, Variable::VariableQuantity::Pressure); + + e->giveCharacteristicVector(contrib, MomentumBalance_StressResidual, mode, tStep); + vec.assemble(contrib, locu); + e->giveCharacteristicVector(contrib, MomentumBalance_PressureResidual, mode, tStep); + contrib.times((-1.0)); + vec.assemble(contrib, locu); + + e->giveCharacteristicVector(contrib, MassBalance_StressRateResidual, mode, tStep); + contrib.times(-1.0*alpha*deltaT); + vec.assemble(contrib, locp); + e->giveCharacteristicVector(contrib, MassBalance_PressureResidual, mode, tStep); + contrib.times(-1.0*alpha*deltaT); + vec.assemble(contrib, locp); + e->giveCharacteristicVector(contrib, MassBalance_PressureRateResidual, mode, tStep); + contrib.times(-1.0*alpha*deltaT); + vec.assemble(contrib, locp); + + vec.negated(); +} + +MPMProblem :: MPMProblem(int i, EngngModel *_master = nullptr) : EngngModel(i, _master) +{ + ndomains = 1; +} + +void +MPMProblem :: initializeFrom(InputRecord &ir) +{ + EngngModel :: initializeFrom(ir); + + if ( ir.hasField(_IFT_MPMProblem_initt) ) { + IR_GIVE_FIELD(ir, initT, _IFT_MPMProblem_initt); + } + + if ( ir.hasField(_IFT_MPMProblem_deltat) ) { + IR_GIVE_FIELD(ir, deltaT, _IFT_MPMProblem_deltat); + } else if ( ir.hasField(_IFT_MPMProblem_deltatfunction) ) { + IR_GIVE_FIELD(ir, dtFunction, _IFT_MPMProblem_deltatfunction); + } else if ( ir.hasField(_IFT_MPMProblem_prescribedtimes) ) { + IR_GIVE_FIELD(ir, discreteTimes, _IFT_MPMProblem_prescribedtimes); + } else { + throw ValueInputException(ir, "none", "Time step not defined"); + } + + IR_GIVE_FIELD(ir, alpha, _IFT_MPMProblem_alpha); + + + int val = 30; + IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_MPMProblem_nsmax); + nsmax = val; + + IR_GIVE_FIELD(ir, rtol, _IFT_MPMProblem_rtol); + + NR_Mode = nrsolverModifiedNRM; + MANRMSteps = 0; + IR_GIVE_OPTIONAL_FIELD(ir, MANRMSteps, _IFT_MPMProblem_manrmsteps); + if ( MANRMSteps > 0 ) { + NR_Mode = nrsolverAccelNRM; + } else { + NR_Mode = nrsolverModifiedNRM; + } + NR_Mode = nrsolverFullNRM; // bp + + //secure equation renumbering, otherwise keep efficient algorithms + if ( ir.hasField(_IFT_MPMProblem_changingproblemsize) ) { + changingProblemSize = true; + UnknownsField = std::make_unique(this, 1, FT_TransportProblemUnknowns, 1); + } else { + UnknownsField = std::make_unique(this, 1, FT_TransportProblemUnknowns, 1); + } +} + +TimeStep * +MPMProblem :: giveNextStep() +{ + int istep = this->giveNumberOfFirstStep(); + double totalTime = this->initT; + double intrinsicTime; + StateCounterType counter = 1; + + if ( currentStep ) { + istep = currentStep->giveNumber() + 1; + totalTime = currentStep->giveTargetTime() + giveDeltaT(istep); + counter = currentStep->giveSolutionStateCounter() + 1; + } else { + // first step -> generate initial step + currentStep = std::make_unique( *giveSolutionStepWhenIcApply() ); + } + + previousStep = std :: move(currentStep); + currentStep = std::make_unique(istep, this, 1, totalTime, this->giveDeltaT ( istep ), counter); + //set intrinsic time to time of integration + intrinsicTime = previousStep->giveTargetTime() + this->alpha*(currentStep->giveTargetTime()-previousStep->giveTargetTime()); + currentStep->setIntrinsicTime(intrinsicTime); + return currentStep.get(); +} + + +void MPMProblem :: solveYourselfAt(TimeStep *tStep) +{ + // creates system of governing eq's and solves them at given time step + // first assemble problem at current time step + + // Right hand side + FloatArray rhs; + double solutionErr, incrementErr; + int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); + +#ifdef VERBOSE + OOFEM_LOG_RELEVANT( "Solving [step number %8d, time %15e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); +#endif + //Delete lhs matrix and create a new one. This is necessary due to growing/decreasing number of equations. + if ( tStep->isTheFirstStep() || this->changingProblemSize ) { + + jacobianMatrix = classFactory.createSparseMtrx(sparseMtrxType); + if ( !jacobianMatrix ) { + OOFEM_ERROR("sparse matrix creation failed"); + } + + jacobianMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); +#ifdef VERBOSE + OOFEM_LOG_INFO("Assembling LHS matrix\n"); +#endif + } + //create previous solution from IC or from previous tStep + if ( tStep->isTheFirstStep() ) { + if ( !stepWhenIcApply ) { + stepWhenIcApply = std::make_unique( *tStep->givePreviousStep() ); + } + this->applyIC(stepWhenIcApply.get()); //insert solution to hash=1(previous), if changes in equation numbering + } + + //Predictor + FloatArray *solutionVector; + UnknownsField->advanceSolution(tStep); + solutionVector = UnknownsField->giveSolutionVector(tStep); + + //Initialize and give solutionVector from previous solution + if ( changingProblemSize ) { + if ( !tStep->isTheFirstStep() ) { + //copy recent solution to previous position, copy from hash=0 to hash=1(previous) + copyUnknownsInDictionary( VM_Total, tStep, tStep->givePreviousStep() ); + } + + UnknownsField->initialize( VM_Total, tStep->givePreviousStep(), *solutionVector, EModelDefaultEquationNumbering() ); + } else { + //copy previous solution vector to actual + *solutionVector = *UnknownsField->giveSolutionVector( tStep->givePreviousStep() ); + } + + this->updateInternalState(tStep); //insert to hash=0(current), if changes in equation numbering + + FloatArray solutionVectorIncrement(neq); + int nite = 0; + + OOFEM_LOG_INFO("Time Iter ResidNorm IncrNorm\n__________________________________________________________\n"); + + + do { + nite++; + + // Corrector +#ifdef VERBOSE + // printf("\nAssembling conductivity and capacity matrices"); +#endif + + if ( ( nite == 1 ) || ( NR_Mode == nrsolverFullNRM ) || ( ( NR_Mode == nrsolverAccelNRM ) && ( nite % MANRMSteps == 0 ) ) ) { + jacobianMatrix->zero(); + MPMLhsAssembler jacobianAssembler(this->alpha, tStep->giveTimeIncrement()); + //Assembling left hand side + this->assemble( *jacobianMatrix, tStep, jacobianAssembler, + EModelDefaultEquationNumbering(), this->giveDomain(1) ); + } + + rhs.resize(neq); + rhs.zero(); + //edge or surface load on element + //add internal source vector on elements + //this->assembleVectorFromElements( rhs, tStep, TransportExternalForceAssembler(), VM_Total, + // EModelDefaultEquationNumbering(), this->giveDomain(1) ); + //add nodal load + + this->assembleVectorFromDofManagers( rhs, tStep, ExternalForceAssembler(), VM_Total, + EModelDefaultEquationNumbering(), this->giveDomain(1) ); + this->assembleVectorFromBC (rhs, tStep, ExternalForceAssembler(), VM_Total, + EModelDefaultEquationNumbering(), this->giveDomain(1) ); + // subtract the rhs part depending on previous solution + this->assembleVectorFromElements( rhs, tStep, MPMResidualAssembler(this->alpha, tStep->giveTimeIncrement()), VM_Total, + EModelDefaultEquationNumbering(), this->giveDomain(1) ); + // set-up numerical model + this->giveNumericalMethod( this->giveCurrentMetaStep() ); + + // call numerical model to solve arised problem +#ifdef VERBOSE + //OOFEM_LOG_INFO("Solving ...\n"); +#endif + + // compute norm of residuals from balance equations + solutionErr = rhs.computeNorm(); + + linSolver->solve(*jacobianMatrix, rhs, solutionVectorIncrement); + + solutionVector->add(solutionVectorIncrement); + this->updateInternalState(tStep); //insert to hash=0(current), if changes in equation numbering + // compute error in the solutionvector increment + incrementErr = solutionVectorIncrement.computeNorm(); + + // update solution state counter + //TauStep.incrementStateCounter(); + tStep->incrementStateCounter(); + + OOFEM_LOG_INFO("%-15e %-10d %-15e %-15e\n", tStep->giveTargetTime(), nite, solutionErr, incrementErr); + + currentIterations = nite; + + if ( nite >= nsmax ) { + OOFEM_ERROR("convergence not reached after %d iterations", nsmax); + } + } while ( ( fabs(solutionErr) > rtol ) || ( fabs(incrementErr) > rtol ) ); +} + + +double MPMProblem :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) +// returns unknown quantity like displacement, velocity of equation +// This function translates this request to numerical method language +{ + if ( this->requiresUnknownsDictionaryUpdate() ) { + if ( mode == VM_Incremental ) { //get difference between current and previous time variable + return dof->giveUnknowns()->at(0) - dof->giveUnknowns()->at(1); + } else if ( mode == VM_TotalIntrinsic ) { // intrinsic value only for current step + return this->alpha * dof->giveUnknowns()->at(0) + (1.-this->alpha) * dof->giveUnknowns()->at(1); + } + int hash = this->giveUnknownDictHashIndx(mode, tStep); + if ( dof->giveUnknowns()->includes(hash) ) { + return dof->giveUnknowns()->at(hash); + } else { + OOFEM_ERROR("Dof unknowns dictionary does not contain unknown of value mode (%s)", __ValueModeTypeToString(mode) ); + } + } + + double t = tStep->giveTargetTime(); + TimeStep *previousStep = this->givePreviousStep(), *currentStep = this->giveCurrentStep(); + + if ( dof->__giveEquationNumber() == 0 ) { + OOFEM_ERROR("invalid equation number on DoF %d", dof->giveDofID() ); + } + + if ( ( t >= previousStep->giveTargetTime() ) && ( t <= currentStep->giveTargetTime() ) ) { + ///@todo Shouldn't it be enough to just run this? + //UnknownsField->giveUnknownValue(dof, mode, currentStep); + double rtdt = UnknownsField->giveUnknownValue(dof, VM_Total, currentStep); + double rt = UnknownsField->giveUnknownValue(dof, VM_Total, previousStep); + double psi = ( t - previousStep->giveTargetTime() ) / currentStep->giveTimeIncrement(); + if ( mode == VM_Velocity ) { + return ( rtdt - rt ) / currentStep->giveTimeIncrement(); + } else if ( mode == VM_TotalIntrinsic ) { + // only supported for current step + return this->alpha * rtdt + ( 1. - this->alpha ) * rt; + } else if ( mode == VM_Total ) { + return psi * rtdt + ( 1. - psi ) * rt; + } else if ( mode == VM_Incremental ) { + if ( previousStep->isIcApply() ) { + return 0; + } else { + return ( rtdt - rt ); + } + } else { + OOFEM_ERROR("Unknown mode %s is undefined for this problem", __ValueModeTypeToString(mode) ); + } + } else { + OOFEM_ERROR("time value %f not within bounds %f and %f", t, previousStep->giveTargetTime(), currentStep->giveTargetTime() ); + } + + return 0.; // to make compiler happy; +} + + +void +MPMProblem :: applyIC(TimeStep *stepWhenIcApply) +{ + Domain *domain = this->giveDomain(1); + int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); + FloatArray *solutionVector; + double val; + +#ifdef VERBOSE + OOFEM_LOG_INFO("Applying initial conditions\n"); +#endif + + UnknownsField->advanceSolution(stepWhenIcApply); + solutionVector = UnknownsField->giveSolutionVector(stepWhenIcApply); + solutionVector->resize(neq); + solutionVector->zero(); + + for ( auto &node : domain->giveDofManagers() ) { + + for ( Dof *dof: *node ) { + // ask for initial values obtained from + // bc (boundary conditions) and ic (initial conditions) + if ( !dof->isPrimaryDof() ) { + continue; + } + + int jj = dof->__giveEquationNumber(); + if ( jj ) { + val = dof->giveUnknown(VM_Total, stepWhenIcApply); + solutionVector->at(jj) = val; + //update in dictionary, if the problem is growing/decreasing + if ( this->changingProblemSize ) { + dof->updateUnknownsDictionary(stepWhenIcApply, VM_Total, val); + } + } + } + } + + // update element state according to given ic + for ( auto &elem : domain->giveElements() ) { + Element *element = elem.get() ; + element->updateInternalState(stepWhenIcApply); + element->updateYourself(stepWhenIcApply); + } +} + +void +MPMProblem :: createPreviousSolutionInDofUnknownsDictionary(TimeStep *tStep) +{ + //Copy the last known temperature to be a previous solution + for ( auto &domain: domainList ) { + if ( requiresUnknownsDictionaryUpdate() ) { + for ( auto &node : domain->giveDofManagers() ) { + for ( Dof *dof: *node ) { + double val = dof->giveUnknown(VM_Total, tStep); //get number on hash=0(current) + dof->updateUnknownsDictionary(tStep->givePreviousStep(), VM_Total, val); + } + } + } + } +} + + +void +MPMProblem :: updateYourself(TimeStep *tStep) +{ + //this->updateInternalState(tStep); + //Set intrinsic time for a staggered problem here. This is important for materials such as hydratingconcretemat, who keep history of intrinsic times. + for ( auto &domain: domainList ) { + if ( requiresUnknownsDictionaryUpdate() ) { + //update temperature vector + UnknownsField->update( VM_Total, tStep, * ( this->UnknownsField->giveSolutionVector(tStep) ), EModelDefaultEquationNumbering() ); + //update Rhs vector + //UnknownsField->update(VM_RhsTotal, tStep, bcRhs, EModelDefaultEquationNumbering()); + } + + if ( internalVarUpdateStamp != tStep->giveSolutionStateCounter() ) { + for ( auto &elem : domain->giveElements() ) { + elem->updateInternalState(tStep); + } + + internalVarUpdateStamp = tStep->giveSolutionStateCounter(); + } + } + EngngModel :: updateYourself(tStep); +} + + +int +MPMProblem :: giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) +{ + if ( mode == VM_Total ) { //Nodal temperature + if ( tStep->giveNumber() == this->giveCurrentStep()->giveNumber() ) { //current time + return 0; + } else if ( tStep->giveNumber() == this->giveCurrentStep()->giveNumber() - 1 ) { //previous time + return 1; + } else { + OOFEM_ERROR("No history available at TimeStep %d = %f, called from TimeStep %d = %f", tStep->giveNumber(), tStep->giveTargetTime(), this->giveCurrentStep()->giveNumber(), this->giveCurrentStep()->giveTargetTime() ); + } + } else { + OOFEM_ERROR("ValueModeType %s undefined", __ValueModeTypeToString(mode)); + } + + return 0; +} + +void +MPMProblem :: updateDofUnknownsDictionary(DofManager *inode, TimeStep *tStep) +{ + // update DoF unknowns dictionary. Store the last and previous temperature only, see giveUnknownDictHashIndx + for ( Dof *dof: *inode ) { + int eqNum = dof->__giveEquationNumber(); + double val; + if ( dof->hasBc(tStep) ) { // boundary condition + val = dof->giveBcValue(VM_Total, tStep); + } else { + FloatArray *vect = this->UnknownsField->giveSolutionVector(tStep); + val = vect->at(eqNum); + } + + //update temperature, which is present in every node + dof->updateUnknownsDictionary(tStep, VM_Total, val); + } +} + + +void +MPMProblem :: updateInternalState(TimeStep *tStep) +{ + for ( auto &domain: domainList ) { + if ( requiresUnknownsDictionaryUpdate() ) { + for ( auto &dman : domain->giveDofManagers() ) { + //update dictionary entry or add a new pair if the position is missing + this->updateDofUnknownsDictionary(dman.get(), tStep); + } + } + + for ( auto &elem : domain->giveElements() ) { + elem->updateInternalState(tStep); + } + } +} + +double +MPMProblem :: giveDeltaT(int n) +{ + if ( giveDtFunction() ) { + return giveDtFunction()->evaluateAtTime(n); + } + + if ( discreteTimes.giveSize() > 0 ) { + return this->giveDiscreteTime(n) - this->giveDiscreteTime(n - 1); + } + + return deltaT; +} + + +void +MPMProblem :: copyUnknownsInDictionary(ValueModeType mode, TimeStep *fromTime, TimeStep *toTime) +{ + Domain *domain = this->giveDomain(1); + + for ( auto &node : domain->giveDofManagers() ) { + for ( Dof *dof: *node ) { + double val = dof->giveUnknown(mode, fromTime); + dof->updateUnknownsDictionary(toTime, mode, val); + } + } +} + +Function * +MPMProblem :: giveDtFunction() +// Returns the load-time function of the receiver. +{ + if ( !dtFunction ) { + return NULL; + } + + return giveDomain(1)->giveFunction(dtFunction); +} + +double +MPMProblem :: giveDiscreteTime(int iStep) +{ + if ( ( iStep > 0 ) && ( iStep <= discreteTimes.giveSize() ) ) { + return ( discreteTimes.at(iStep) ); + } + + if ( ( iStep == 0 ) && ( iStep <= discreteTimes.giveSize() ) ) { + return ( initT ); + } + + OOFEM_ERROR("invalid iStep"); + return 0.0; +} + +TimeStep * +MPMProblem :: giveSolutionStepWhenIcApply(bool force) +{ + if ( master && (!force)) { + return master->giveSolutionStepWhenIcApply(); + } else { + if ( !stepWhenIcApply ) { + stepWhenIcApply = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 0, this->initT - giveDeltaT( giveNumberOfFirstStep() ), giveDeltaT( giveNumberOfFirstStep() ), 0); + } + + return stepWhenIcApply.get(); + } +} + +NumericalMethod *MPMProblem :: giveNumericalMethod(MetaStep *mStep) +// only one has reason for LinearStatic +// - SolutionOfLinearEquations +{ + if ( !linSolver ) { + linSolver = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); + if ( !linSolver ) { + OOFEM_ERROR("linear solver creation failed for lstype %d", solverType); + } + } + return linSolver.get(); +} + + +} // end namespace oofem diff --git a/src/mpm/mpmproblem.h b/src/mpm/mpmproblem.h new file mode 100644 index 000000000..5afc06411 --- /dev/null +++ b/src/mpm/mpmproblem.h @@ -0,0 +1,201 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef mpmproblem_h +#define mpmproblem_h + +#include "engngm.h" +#include "sparselinsystemnm.h" +#include "sparsenonlinsystemnm.h" +#include "sparsemtrx.h" +#include "primaryfield.h" +#include "function.h" + +///@name Input fields for mpmproblem +//@{ +#define _IFT_MPMProblem_Name "mpmproblem" +#define _IFT_MPMProblem_nsmax "nsmax" +#define _IFT_MPMProblem_rtol "rtol" +#define _IFT_MPMProblem_manrmsteps "manrmsteps" +#define _IFT_MPMProblem_initt "initt" +#define _IFT_MPMProblem_deltat "deltat" +#define _IFT_MPMProblem_deltatfunction "deltatfunction" +#define _IFT_MPMProblem_prescribedtimes "prescribedtimes" +#define _IFT_MPMProblem_alpha "alpha" +#define _IFT_MPMProblem_changingproblemsize "changingproblemsize" + + +//@} + +namespace oofem { + +/** + * Callback class for assembling mid point effective tangents. + * @todo Need to parametrize individual contributing terms, ther locations and multilication factors. + */ +class MPMLhsAssembler : public MatrixAssembler +{ +protected: + double alpha; + double deltaT; + +public: + MPMLhsAssembler(double alpha, double deltaT); + void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const override; +}; + +/** + * Callback class for assembling rhs external forces + */ +class MPMRhsAssembler : public VectorAssembler +{ +protected: + double alpha; + double deltaT; +public: + MPMRhsAssembler(double alpha, double deltaT) : VectorAssembler(), alpha(alpha), deltaT(deltaT) {} + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; +}; + +/** + * Callback class for assembling residuals + */ +class MPMResidualAssembler : public VectorAssembler +{ + protected: + double alpha; + double deltaT; +public: + MPMResidualAssembler(double alpha, double deltaT) : VectorAssembler(), alpha(alpha), deltaT(deltaT) {} + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; +}; + + +/** + * This class represents generic nonlinear multi-physics problem. The problem can be growing/decreasing, signalized by flag "changingproblemsize" + * in the problem description. The solution is stored in UnknownsField, which can obtain/ project solution from/to DOFs (nodes). If the problem + * keeps the same equation numbers, solution is taken from UnknownsField without any projection, which is more efficient. See the matlibmanual + * for solution strategy of balance equations and the solution algorithm. + * + * @todo Documentation errors (there is no "UnknownsField" used here). + */ +class MPMProblem : public EngngModel +{ +protected: + enum nlttp_ModeType { nrsolverModifiedNRM, nrsolverFullNRM, nrsolverAccelNRM }; + + SparseMtrxType sparseMtrxType = SMT_Skyline; + /// This field stores solution vector. For fixed size of problem, the PrimaryField is used, for growing/decreasing size, DofDistributedPrimaryField applies. + std :: unique_ptr< PrimaryField > UnknownsField; + + std :: unique_ptr< SparseMtrx > jacobianMatrix; + FloatArray internalForces; + FloatArray eNorm; + + /// Numerical method used to solve the problem + std::unique_ptr nMethod; + LinSystSolverType solverType = ST_Direct; ///@todo Remove this and use nonlinear methods. + std :: unique_ptr< SparseLinearSystemNM > linSolver; ///@todo Remove this and use nonlinear methods. + + bool keepTangent = false; + + double rtol = 0.; + int nsmax = 0; + nlttp_ModeType NR_Mode = nrsolverModifiedNRM; + int MANRMSteps = 0; + int currentIterations = 0; + + /// Initial time from which the computation runs. Default is zero. + double initT = 0.; + /// Length of time step. + double deltaT = 0.; + double alpha = 0.; + /// Associated time function for time step increment. + int dtFunction = 0; + /// Specified times where the problem is solved + FloatArray discreteTimes; + /// Determines if there are change in the problem size (no application/removal of Dirichlet boundary conditions). + bool changingProblemSize = false; + /** + * Contains last time stamp of internal variable update. + * This update is made via various services + * (like those for computing real internal forces or updating the internal state). + */ + StateCounterType internalVarUpdateStamp; + +public: + MPMProblem(int i, EngngModel * _master); + + TimeStep* giveNextStep() override; + void solveYourselfAt(TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override; + double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) override; + + void initializeFrom(InputRecord &ir) override; + + // identification + const char *giveInputRecordName() const { return _IFT_MPMProblem_Name; } + const char *giveClassName() const override { return "MPMProblem"; } + fMode giveFormulation() override { return nonLinFormulation; } + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override; + void updateDofUnknownsDictionary(DofManager *dman, TimeStep *tStep) override; + + int giveCurrentNumberOfIterations() override { return currentIterations; } + TimeStep *giveSolutionStepWhenIcApply(bool force = false) override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; + + +protected: + void updateInternalState(TimeStep *tStep) ; + void applyIC(TimeStep *tStep) ; + void createPreviousSolutionInDofUnknownsDictionary(TimeStep *tStep); + /** + * Returns the time step length for given step number n, initial step is number 0. + */ + double giveDeltaT(int n); + /** + * Copy unknowns in DOF's from previous to current position. + * @param mode What the unknown describes (increment, total value etc.). + * @param fromTime From which time step to obtain value. + * @param toTime To which time to copy. + */ + virtual void copyUnknownsInDictionary(ValueModeType mode, TimeStep *fromTime, TimeStep *toTime); + Function * giveDtFunction(); + /** + * Returns time for time step number n (array discreteTimes must be specified) + */ + double giveDiscreteTime(int n); +}; +} // end namespace oofem +#endif // mpmproblem_h diff --git a/src/mpm/prototype.C b/src/mpm/prototype.C new file mode 100644 index 000000000..7c0442483 --- /dev/null +++ b/src/mpm/prototype.C @@ -0,0 +1,139 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "mpm.h" +#include "element.h" +#include "gausspoint.h" +#include "feinterpol.h" +#include "intarray.h" +#include "classfactory.h" + +// for demo +#include "fei2dtrlin.h" +#include "gaussintegrationrule.h" + + +namespace oofem { + + +class PoissonTerm : public Term { + protected: + double c; + public: + PoissonTerm (const Variable& unknownField, const Variable &testField, double c) : Term(unknownField, testField) { + this->c = c; + } + + void grad(FloatMatrix& answer, const Variable &v, const FEInterpolation& interpol, const Element& cell, const FloatArray& coords) const { + interpol.evaldNdx(answer, coords, FEIElementGeometryWrapper(&cell)); + } + + + void evaluate_dw (FloatMatrix& answer, MPElement& e, GaussPoint* gp, TimeStep *tstep) const override { + const FEInterpolation & si = field.interpolation; + const FEInterpolation &ti = testField.interpolation; + FloatMatrix bs, bt; + this->grad(bs, this->field,si,e,gp->giveNaturalCoordinates()); + this->grad(bt, this->testField,ti,e,gp->giveNaturalCoordinates()); + + FloatMatrix gc, c(2,2); + c.at(1,1) = this->c; + c.at(2,2) = this->c; + + gc.beProductOf(bs, c); + answer.beProductTOf(gc, bt); + } + + void evaluate_c (FloatArray&, MPElement& cell, GaussPoint*gp, TimeStep* tstep) const override {} + void getDimensions_dw(Element& cell) const override {} + void initializeCell(Element& cell) const override {} +}; + + + +#define _IFT_PoissonElement_Name "pe" + + +class PoissonElement : public MPElement { + protected: + FEI2dTrLin interpol; + Variable t; + Variable dt; + PoissonTerm p; + GaussIntegrationRule ir; + public: + PoissonElement(int n, Domain* d): + MPElement(n,d), + interpol(1,2), + t(interpol, Variable::VariableQuantity::Temperature, Variable::VariableType::scalar, 3), + dt(interpol, Variable::VariableQuantity::Temperature, Variable::VariableType::scalar, 3, &t), + p(t,dt,1.0), + ir(1, this) + { + numberOfDofMans = 3; + numberOfGaussPoints = 1; + ir.SetUpPointsOnTriangle(numberOfGaussPoints, _2dHeat); + } + + // Note: performance can be probably improved once it will be possible + // to directly assemble multiple term contributions to the system matrix. + // template metaprogramming? + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) override { + if (type == ConductivityMatrix) { + FloatMatrix term; + answer.resize(3,3); + this->integrateTerm_dw (term, this->p, &this->ir, tStep) ; + this->assembleTermContribution(answer, term, this->p); + answer.printYourself("Conductivity"); + + } + } + void getLocalCodeNumbers (IntArray& answer, const Variable::VariableQuantity q) const override { + answer.enumerate(this->giveNumberOfDofManagers()); + } + + const char *giveInputRecordName() const override {return "pe";} + + double computeVolumeAround(GaussPoint *gp) override { + double determinant = fabs( this->interpol.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double weight = gp->giveWeight(); + return determinant * weight ; + } +}; + +REGISTER_Element(PoissonElement) + + +} // end namespace oofem \ No newline at end of file diff --git a/src/mpm/termlibrary.C b/src/mpm/termlibrary.C new file mode 100644 index 000000000..4488f115c --- /dev/null +++ b/src/mpm/termlibrary.C @@ -0,0 +1,275 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mpm.h" +#include "termlibrary.h" +#include "element.h" +#include "material.h" + +namespace oofem { + +BTSigTerm::BTSigTerm (const Variable& unknownField, const Variable &testField) : Term(unknownField, testField) {} + + +void BTSigTerm::evaluate_dw (FloatMatrix& answer, MPElement& e, GaussPoint* gp, TimeStep* tstep) const { + FloatMatrix D, B, DB; + e.giveMaterial()->giveCharacteristicMatrix(D, StiffnessMatrix, gp, tstep); + this->grad(B, this->field, this->field.interpolation, e, gp->giveNaturalCoordinates()); + DB.beProductOf(D, B); + //answer.plusProductSymmUpper(B, DB, 1.0); + answer.beTProductOf(B,DB); +} + +void BTSigTerm::evaluate_c (FloatArray& answer, MPElement& cell, GaussPoint* gp, TimeStep* tstep) const { + FloatArray u, eps, sig; + FloatMatrix B; + cell.getUnknownVector(u, this->field, VM_TotalIntrinsic, tstep); + this->grad(B, this->field, this->field.interpolation, cell, gp->giveNaturalCoordinates()); + eps.beProductOf(B, u); + cell.giveMaterial()->giveCharacteristicVector(sig, eps, InternalForcesVector, gp, tstep); + answer.beTProductOf(B, sig); +} + +void BTSigTerm::getDimensions_dw(Element& cell) const { + //int nnodes = interpol.giveNumberOfNodes(); + //int ndofs = v.size; + //return nnodes*ndofs; +} +void BTSigTerm::initializeCell(Element& cell) const {} + +void BTSigTerm::grad(FloatMatrix& answer, const Variable &v, const FEInterpolation& interpol, const Element& cell, const FloatArray& coords) const { + FloatMatrix dndx; + int nnodes = interpol.giveNumberOfNodes(); + int ndofs = v.size; + // evaluate matrix of derivatives, the member at i,j position contains value of dNi/dxj + interpol.evaldNdx(dndx, coords, FEIElementGeometryWrapper(&cell)); + + + // 3D mode only now + answer.resize(6, nnodes*ndofs); + for (int i = 0; i< nnodes; i++) { + answer(0, i*ndofs+0) = dndx(i, 0); + answer(1, i*ndofs+1) = dndx(i, 1); + answer(2, i*ndofs+2) = dndx(i, 2); + + answer(3, i*ndofs+1) = dndx(i, 2); + answer(3, i*ndofs+2) = dndx(i, 1); + + answer(4, i*ndofs+0) = dndx(i, 2); + answer(4, i*ndofs+2) = dndx(i, 0); + + answer(5, i*ndofs+0) = dndx(i, 1); + answer(5, i*ndofs+1) = dndx(i, 0); + } +} + +//wTgNTfTerm class (H) + + +gNTfTerm::gNTfTerm (const Variable& unknownField, const Variable &testField) : Term(unknownField, testField) {} + + +void gNTfTerm::evaluate_dw (FloatMatrix& answer, MPElement& e, GaussPoint* gp, TimeStep* tstep) const { + FloatMatrix D, B, DB; + e.giveMaterial()->giveCharacteristicMatrix(D, PermeabilityMatrix, gp, tstep); // update + this->grad(B, this->field, this->field.interpolation, e, gp->giveNaturalCoordinates()); + DB.beProductOf(D, B); + answer.beTProductOf(B, DB); +} + +void gNTfTerm::evaluate_c (FloatArray& answer, MPElement& cell, GaussPoint* gp, TimeStep* tstep) const { + FloatArray p, gradp, fp; + FloatMatrix B; + cell.getUnknownVector(p, this->field, VM_TotalIntrinsic, tstep); + this->grad(B, this->field, this->field.interpolation, cell, gp->giveNaturalCoordinates()); + gradp.beProductOf(B, p); + cell.giveMaterial()->giveCharacteristicVector(fp, gradp, FluidMassBalancePressureContribution, gp, tstep); // update + answer.beTProductOf(B, fp); +} + +void gNTfTerm::getDimensions_dw(Element& cell) const { + //int nnodes = interpol.giveNumberOfNodes(); + //int ndofs = v.size; + //return nnodes*ndofs; +} +void gNTfTerm::initializeCell(Element& cell) const {} + +void gNTfTerm::grad(FloatMatrix& answer, const Variable &v, const FEInterpolation& interpol, const Element& cell, const FloatArray& coords) const { + FloatMatrix at; + // evaluate matrix of derivatives, the member at i,j position contains value of dNi/dxj + interpol.evaldNdx(at, coords, FEIElementGeometryWrapper(&cell)); + answer.beTranspositionOf(at); +} + +// BTamN Term (Qp) + +BTamNTerm::BTamNTerm (const Variable& unknownField, const Variable &testField) : Term(unknownField, testField) {} + +void BTamNTerm::evaluate_dw (FloatMatrix& answer, MPElement& e, GaussPoint* gp, TimeStep* tstep) const { + FloatMatrix B, mn; + FloatArray m({1,1,1,0,0,0}), Np; + this->field.interpolation.evalN(Np, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(&e)); + m.times(e.giveMaterial()->giveCharacteristicValue(BiotConstant, gp, tstep)); + mn.beDyadicProductOf(m, Np); + this->grad(B, this->testField, this->testField.interpolation, e, gp->giveNaturalCoordinates()); + answer.beTProductOf(B, mn); +} + +void BTamNTerm::evaluate_c (FloatArray& answer, MPElement& cell, GaussPoint* gp, TimeStep* tstep) const { + FloatArray p; + FloatMatrix Q; + cell.getUnknownVector(p, this->field, VM_TotalIntrinsic, tstep); + this->evaluate_dw (Q, cell,gp, tstep); + answer.beProductOf(Q,p); +} + +void BTamNTerm::getDimensions_dw(Element& cell) const { + //int nnodes = interpol.giveNumberOfNodes(); + //int ndofs = v.size; + //return nnodes*ndofs; +} +void BTamNTerm::initializeCell(Element& cell) const {} + +void BTamNTerm::grad(FloatMatrix& answer, const Variable &v, const FEInterpolation& interpol, const Element& cell, const FloatArray& coords) const { + FloatMatrix dndx; + int nnodes = interpol.giveNumberOfNodes(); + int ndofs = v.size; + // evaluate matrix of derivatives, the member at i,j position contains value of dNi/dxj + interpol.evaldNdx(dndx, coords, FEIElementGeometryWrapper(&cell)); + + + // 3D mode only now + answer.resize(6, nnodes*ndofs); + for (int i = 0; i< nnodes; i++) { + answer(0, i*ndofs+0) = dndx(i, 0); + answer(1, i*ndofs+1) = dndx(i, 1); + answer(2, i*ndofs+2) = dndx(i, 2); + + answer(3, i*ndofs+1) = dndx(i, 2); + answer(3, i*ndofs+2) = dndx(i, 1); + + answer(4, i*ndofs+0) = dndx(i, 2); + answer(4, i*ndofs+2) = dndx(i, 0); + + answer(5, i*ndofs+0) = dndx(i, 1); + answer(5, i*ndofs+1) = dndx(i, 0); + } +} + +// NTamTBTerm Term (Q^T du/dt) + +NTamTBTerm::NTamTBTerm (const Variable& unknownField, const Variable &testField) : Term(unknownField, testField) {} + +void NTamTBTerm::evaluate_dw (FloatMatrix& answer, MPElement& e, GaussPoint* gp, TimeStep* tstep) const { + FloatMatrix B, mb; + FloatArray m({1,1,1,0,0,0}), Np; + this->testField.interpolation.evalN(Np, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(&e)); + m.times(e.giveMaterial()->giveCharacteristicValue(BiotConstant, gp, tstep)); + this->grad(B, this->field, this->field.interpolation, e, gp->giveNaturalCoordinates()); + mb.beTProductOf(m, B); + FloatMatrix Npm(Np); + answer.beProductOf(Npm, mb); +} + +void NTamTBTerm::evaluate_c (FloatArray& answer, MPElement& cell, GaussPoint* gp, TimeStep* tstep) const { + FloatArray ut; + FloatMatrix Q; + cell.getUnknownVector(ut, this->field, VM_Velocity ,tstep); + this->evaluate_dw (Q, cell,gp, tstep); + answer.beProductOf(Q,ut); +} + +void NTamTBTerm::getDimensions_dw(Element& cell) const { + //int nnodes = interpol.giveNumberOfNodes(); + //int ndofs = v.size; + //return nnodes*ndofs; +} +void NTamTBTerm::initializeCell(Element& cell) const {} + +void NTamTBTerm::grad(FloatMatrix& answer, const Variable &v, const FEInterpolation& interpol, const Element& cell, const FloatArray& coords) const { + FloatMatrix dndx; + int nnodes = interpol.giveNumberOfNodes(); + int ndofs = v.size; + // evaluate matrix of derivatives, the member at i,j position contains value of dNi/dxj + interpol.evaldNdx(dndx, coords, FEIElementGeometryWrapper(&cell)); + + + // 3D mode only now + answer.resize(6, nnodes*ndofs); + for (int i = 0; i< nnodes; i++) { + answer(0, i*ndofs+0) = dndx(i, 0); + answer(1, i*ndofs+1) = dndx(i, 1); + answer(2, i*ndofs+2) = dndx(i, 2); + + answer(3, i*ndofs+1) = dndx(i, 2); + answer(3, i*ndofs+2) = dndx(i, 1); + + answer(4, i*ndofs+0) = dndx(i, 2); + answer(4, i*ndofs+2) = dndx(i, 0); + + answer(5, i*ndofs+0) = dndx(i, 1); + answer(5, i*ndofs+1) = dndx(i, 0); + } +} + + +// NTcN Term (S(dp/dt)) + +NTcN::NTcN (const Variable& unknownField, const Variable &testField) : Term(unknownField, testField) {} + +void NTcN::evaluate_dw (FloatMatrix& answer, MPElement& e, GaussPoint* gp, TimeStep* tstep) const { + FloatArray Np; + this->field.interpolation.evalN(Np, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(&e)); + answer.beDyadicProductOf(Np, Np); + answer.times(e.giveMaterial()->giveCharacteristicValue(CompressibilityCoefficient, gp, tstep)); +} + +void NTcN::evaluate_c (FloatArray& answer, MPElement& cell, GaussPoint* gp, TimeStep* tstep) const { + FloatArray p; + FloatMatrix S; + cell.getUnknownVector(p, this->field, VM_Velocity, tstep); + this->evaluate_dw (S, cell,gp, tstep); + answer.beProductOf(S,p); +} + +void NTcN::getDimensions_dw(Element& cell) const { + //int nnodes = interpol.giveNumberOfNodes(); + //int ndofs = v.size; + //return nnodes*ndofs; +} +void NTcN::initializeCell(Element& cell) const {} + + + +} // end namespace oofem diff --git a/src/mpm/termlibrary.h b/src/mpm/termlibrary.h new file mode 100644 index 000000000..7094626e9 --- /dev/null +++ b/src/mpm/termlibrary.h @@ -0,0 +1,233 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef termlibrary_h +#define termlibrary_h + +#include "mpm.h" + +namespace oofem { +/** + * @brief A Linear momentum balance equation term ($B^T\sigma(u)$) + * + */ +class BTSigTerm : public Term { + protected: + public: + BTSigTerm (const Variable& unknownField, const Variable &testField) ; + + /** + * @brief Evaluates the linearization of $B^T\sigma(u)$, i.e. $B^TDBu$ + * + * @param answer + * @param e + * @param coords + */ + void evaluate_dw (FloatMatrix& answer, MPElement& e, GaussPoint* gp, TimeStep* tstep) const override; + /** + * @brief Evaluates Internal forces vector, i.e. $b^T\sigma(u)$ + * + * @param cell + * @param coords + */ + void evaluate_c (FloatArray&, MPElement& cell, GaussPoint* gp, TimeStep* tstep) const override; + void getDimensions_dw(Element& cell) const override; + void initializeCell(Element& cell) const override; + + protected: + /** + * @brief Evaluates B matrix; i.e. $LN$ where $L$ is operator matrix and $N$ is interpolation matrix of unknowns + * + * @param answer B matrix + * @param v + * @param interpol + * @param cell + * @param coords + */ + void grad(FloatMatrix& answer, const Variable &v, const FEInterpolation& interpol, const Element& cell, const FloatArray& coords) const ; + +}; + +/** + * @brief A continuity equation term ($Hp=(\grad N_p)^T f(p)$, where $f=\bf{k}/\mu \grad p$. + */ +class gNTfTerm : public Term { + protected: + public: + gNTfTerm (const Variable& unknownField, const Variable &testField) ; + + /** + * @brief Evaluates $\bf{H}$ matrix, the linearization of $w^T(\grad N)^T f(p)$, i.e. $(\grad N)^T \bf{k}/\mu \grad p = \bf{H}$ + * + * @param answer + * @param e + * @param coords + */ + void evaluate_dw (FloatMatrix& answer, MPElement& e, GaussPoint* gp, TimeStep* tstep) const override; + /** + * @brief Evaluates Internal forces vector, i.e. $w^T(\grad N)^T f(p)$ + * + * @param cell + * @param coords + */ + void evaluate_c (FloatArray&, MPElement& cell, GaussPoint* gp, TimeStep* tstep) const override; + void getDimensions_dw(Element& cell) const override; + void initializeCell(Element& cell) const override; + + protected: + /** + * @brief Evaluates B matrix; i.e. $\grad N$ where $N$ is interpolation matrix of unknown (p) + * + * @param answer B matrix + * @param v + * @param interpol + * @param cell + * @param coords + */ + void grad(FloatMatrix& answer, const Variable &v, const FEInterpolation& interpol, const Element& cell, const FloatArray& coords) const ; + +}; + +/** + * @brief A continuity equation term $Qp=(B)^T \alpha\bf{m}N_p$. + */ +class BTamNTerm : public Term { + protected: + public: + BTamNTerm (const Variable& unknownField, const Variable &testField) ; + + /** + * @brief Evaluates the linearization of receiver, i.e. the LHS term + * + * @param answer + * @param e + * @param coords + */ + void evaluate_dw (FloatMatrix& answer, MPElement& e, GaussPoint* gp, TimeStep* tstep) const override; + /** + * @brief Evaluates Internal forces vector, i.e. $w^T(\grad N)^T f(p)$ + * + * @param cell + * @param coords + */ + void evaluate_c (FloatArray&, MPElement& cell, GaussPoint* gp, TimeStep* tstep) const override; + void getDimensions_dw(Element& cell) const override; + void initializeCell(Element& cell) const override; + + protected: + /** + * @brief Evaluates B matrix; i.e. $\grad N$ where $N$ is interpolation matrix of unknown (p) + * + * @param answer B matrix + * @param v + * @param interpol + * @param cell + * @param coords + */ + void grad(FloatMatrix& answer, const Variable &v, const FEInterpolation& interpol, const Element& cell, const FloatArray& coords) const ; + +}; + +/** + * @brief A continuity equation term $Q^T(du\over dt)=(N)^T \alpha\bf{m}^TB du\over dt$. + */ +class NTamTBTerm : public Term { + protected: + public: + NTamTBTerm (const Variable& unknownField, const Variable &testField) ; + + /** + * @brief Evaluates the linearization of receiver, i.e. the LHS term + * + * @param answer + * @param e + * @param coords + */ + void evaluate_dw (FloatMatrix& answer, MPElement& e, GaussPoint* gp, TimeStep* tstep) const override; + /** + * @brief Evaluates Internal forces vector, i.e. $w^T(\grad N)^T f(p)$ + * + * @param cell + * @param coords + */ + void evaluate_c (FloatArray&, MPElement& cell, GaussPoint* gp, TimeStep* tstep) const override; + void getDimensions_dw(Element& cell) const override; + void initializeCell(Element& cell) const override; + + protected: + /** + * @brief Evaluates B matrix; i.e. $\grad N$ where $N$ is interpolation matrix of unknown (p) + * + * @param answer B matrix + * @param v + * @param interpol + * @param cell + * @param coords + */ + void grad(FloatMatrix& answer, const Variable &v, const FEInterpolation& interpol, const Element& cell, const FloatArray& coords) const ; + +}; + + +/** + * @brief A continuity equation compressibility matrix $S=(N_p)^T c\ N_p$, where $c=({\alpha-n}\over{K_s}+{n}\over{K_w})$. + */ +class NTcN : public Term { + protected: + public: + NTcN (const Variable& unknownField, const Variable &testField) ; + + /** + * @brief Evaluates the linearization of term (the lhs contribution) + * + * @param answer + * @param e + * @param coords + */ + void evaluate_dw (FloatMatrix& answer, MPElement& e, GaussPoint* gp, TimeStep* tstep) const override; + /** + * @brief Evaluates Internal forces vector, i.e. $w^T(\grad N)^T f(p)$ + * + * @param cell + * @param coords + */ + void evaluate_c (FloatArray&, MPElement& cell, GaussPoint* gp, TimeStep* tstep) const override; + void getDimensions_dw(Element& cell) const override; + void initializeCell(Element& cell) const override; + +}; + + + +} // end namespace oofem +#endif // termlibrary_h \ No newline at end of file diff --git a/src/mpm/up.C b/src/mpm/up.C new file mode 100644 index 000000000..607474fd2 --- /dev/null +++ b/src/mpm/up.C @@ -0,0 +1,441 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "mpm.h" +#include "termlibrary.h" +#include "element.h" +#include "gausspoint.h" +#include "feinterpol.h" +#include "intarray.h" +#include "classfactory.h" +#include "gaussintegrationrule.h" + +#include "fei3dtetlin.h" +#include "fei3dtetquad.h" +#include "fei3dhexalin.h" +#include "mathfem.h" + +#include "material.h" +#include "matstatus.h" + +namespace oofem { + + +/** + * @brief Base class for (3D) UP elements + * + */ +class UPElement : public MPElement { + + public: + UPElement(int n, Domain* d): + MPElement(n,d) { } + + // Note: performance can be probably improved once it will be possible + // to directly assemble multiple term contributions to the system matrix. + // template metaprogramming? + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) override { + IntegrationRule* ir = this->giveDefaultIntegrationRulePtr(); + + if (type == MomentumBalance_StiffnessMatrix) { + int udofs = this->giveNumberOfUDofs(); + answer.resize(udofs,udofs); + answer.zero(); + this->integrateTerm_dw (answer, BTSigTerm(getU(),getU()), ir, tStep) ; + } else if (type == MomentumBalance_PressureCouplingMatrix) { + answer.resize(this->giveNumberOfUDofs(),this->giveNumberOfPDofs()); + answer.zero(); + this->integrateTerm_dw (answer, BTamNTerm(getU(),getP()), ir, tStep) ; + } else if (type == MassBalance_PermeabilityMatrix) { + int pdofs = this->giveNumberOfPDofs(); + answer.resize(pdofs,pdofs); + answer.zero(); + this->integrateTerm_dw (answer, gNTfTerm(getP(), getP()), ir, tStep) ; + } else if (type == MassBalance_CompresibilityMatrix) { + int pdofs = this->giveNumberOfPDofs(); + answer.resize(pdofs,pdofs); + answer.zero(); + this->integrateTerm_dw (answer, NTcN(getP(), getP()), ir, tStep) ; + } else if (type == MassBalance_StressCouplingMatrix) { + answer.resize(this->giveNumberOfPDofs(),this->giveNumberOfUDofs()); + answer.zero(); + this->integrateTerm_dw (answer, NTamTBTerm(getP(), getU()), ir, tStep) ; + } else { + OOFEM_ERROR("Unknown characteristic matrix type"); + } + } + + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override { + IntegrationRule* ir = this->giveDefaultIntegrationRulePtr(); + if (type == MomentumBalance_StressResidual) { + answer.resize(this->giveNumberOfUDofs()); + answer.zero(); + this->integrateTerm_c (answer, BTSigTerm(getU(),getU()), ir, tStep) ; + } else if (type == MomentumBalance_PressureResidual) { + answer.resize(this->giveNumberOfUDofs()); + answer.zero(); + this->integrateTerm_c(answer, BTamNTerm(getU(),getP()), ir, tStep) ; + } else if (type == MassBalance_StressRateResidual) { + answer.resize(this->giveNumberOfPDofs()); + answer.zero(); + this->integrateTerm_c (answer, NTamTBTerm(getP(), getU()), ir, tStep) ; + } else if (type == MassBalance_PressureResidual) { + answer.resize(this->giveNumberOfPDofs()); + answer.zero(); + this->integrateTerm_c (answer, gNTfTerm(getP(), getP()), ir, tStep) ; + } else if (type == MassBalance_PressureRateResidual) { + answer.resize(this->giveNumberOfPDofs()); + answer.zero(); + this->integrateTerm_c (answer, NTcN(getP(), getP()), ir, tStep) ; + } else { + OOFEM_ERROR("Unknown characteristic vector type"); + } + } + + //virtual void getLocalCodeNumbers (IntArray& answer, const Variable::VariableQuantity q ) const = 0; + //virtual void giveDofManDofIDMask(int inode, IntArray &answer) const =0; + private: + virtual int giveNumberOfUDofs() const = 0; + virtual int giveNumberOfPDofs() const = 0; + virtual const Variable& getU() const = 0; + virtual const Variable& getP() const = 0; +}; + +/** + * @brief 3D Tetrahedra element with quadratic interpolation for displacements, linear interpolation for pressure + * + */ +class UPTetra21 : public UPElement { + protected: + //FEI3dTetLin pInterpol; + //FEI3dTetQuad uInterpol; + const static FEInterpolation & pInterpol; + const static FEInterpolation & uInterpol; + const static Variable& p; + const static Variable& u; + + GaussIntegrationRule ir; + + public: + UPTetra21(int n, Domain* d): + UPElement(n,d), + ir(1, this) + { + numberOfDofMans = 10; + numberOfGaussPoints = 4; + ir.SetUpPointsOnTetrahedra(numberOfGaussPoints, _Unknown); + } + + void getLocalCodeNumbers (IntArray& answer, const Variable::VariableQuantity q ) const override { + /* dof ordering: u1 v1 w1 p1 u2 v2 w2 p2 u3 v3 w3 p3 u4 v4 w4 u5 v5 w5 u6 v6 w6*/ + if (q == Variable::VariableQuantity::Displacement) { + answer={1,2,3, 5,6,7, 9,10,11, 13,14,15, 17,18,19, 20,21,22, 23,24,25, 26,27,28, 29,30,31, 32,33,34 }; + } else if (q == Variable::VariableQuantity::Pressure) { + answer = {4, 8, 12, 16}; + } + } + + void giveDofManDofIDMask(int inode, IntArray &answer) const override { + if (inode >0 && inode <5) { + answer = {1,2,3,11}; + } else { + answer= {1,2,3}; + } + } + int giveNumberOfDofs() override { return 34; } + const char *giveInputRecordName() const override {return "uptetra21";} + + double computeVolumeAround(GaussPoint *gp) override { + double determinant = fabs( this->pInterpol.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double weight = gp->giveWeight(); + return determinant * weight ; + } + IntegrationRule *giveDefaultIntegrationRulePtr() override { + return &ir; + } + Element_Geometry_Type giveGeometryType() const override { + return EGT_tetra_2; + } + private: + virtual int giveNumberOfUDofs() const override {return 30;} + virtual int giveNumberOfPDofs() const override {return 4;} + virtual const Variable& getU() const override {return u;} + virtual const Variable& getP() const override {return p;} + void computeGaussPoints() override { + if ( integrationRulesArray.size() == 0 ) { + integrationRulesArray.resize( 1 ); + integrationRulesArray [ 0 ] = std::make_unique(1, this); + integrationRulesArray [ 0 ]->SetUpPointsOnTetrahedra(numberOfGaussPoints, _Unknown); + } + } +}; + +const FEInterpolation & UPTetra21::uInterpol = FEI3dTetQuad(); +const FEInterpolation & UPTetra21::pInterpol = FEI3dTetLin(); +const Variable& UPTetra21::p = Variable(UPTetra21::pInterpol, Variable::VariableQuantity::Pressure, Variable::VariableType::scalar, 3, NULL, {11}); +const Variable& UPTetra21::u = Variable(UPTetra21::uInterpol, Variable::VariableQuantity::Displacement, Variable::VariableType::vector, 3, NULL, {1,2,3}); + +#define _IFT_UPTetra21_Name "uptetra21" +REGISTER_Element(UPTetra21) + +/** + * @brief 3D Equal order linear Brick UP Element + * + */ +class UPBrick11 : public UPElement { + protected: + //FEI3dTetLin pInterpol; + //FEI3dTetQuad uInterpol; + const static FEInterpolation & pInterpol; + const static FEInterpolation & uInterpol; + const static Variable& p; + const static Variable& u; + + GaussIntegrationRule ir; + + public: + UPBrick11(int n, Domain* d): + UPElement(n,d), + ir(1, this) + { + numberOfDofMans = 8; + numberOfGaussPoints = 4; + ir.SetUpPointsOnCube(numberOfGaussPoints, _Unknown); + } + + void getLocalCodeNumbers (IntArray& answer, const Variable::VariableQuantity q ) const override { + /* dof ordering: u1 v1 w1 p1 u2 v2 w2 p2 u3 v3 w3 p3 u4 v4 w4 u5 v5 w5 u6 v6 w6*/ + if (q == Variable::VariableQuantity::Displacement) { + answer={1,2,3, 5,6,7, 9,10,11, 13,14,15, 17,18,19, 21,22,23, 25,26,27, 29,30,31 }; + } else if (q == Variable::VariableQuantity::Pressure) { + answer = {4, 8, 12, 16, 20, 24, 28, 32}; + } + } + + void giveDofManDofIDMask(int inode, IntArray &answer) const override { + answer = {1,2,3,11}; + } + int giveNumberOfDofs() override { return 32; } + const char *giveInputRecordName() const override {return "upbrick11";} + + double computeVolumeAround(GaussPoint *gp) override { + double determinant = fabs( this->pInterpol.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double weight = gp->giveWeight(); + return determinant * weight ; + } + IntegrationRule *giveDefaultIntegrationRulePtr() override { + return &ir; + } + Element_Geometry_Type giveGeometryType() const override { + return EGT_hexa_1; + } + private: + virtual int giveNumberOfUDofs() const override {return 24;} + virtual int giveNumberOfPDofs() const override {return 8;} + virtual const Variable& getU() const override {return u;} + virtual const Variable& getP() const override {return p;} + void computeGaussPoints() override { + if ( integrationRulesArray.size() == 0 ) { + integrationRulesArray.resize( 1 ); + integrationRulesArray [ 0 ] = std::make_unique(1, this); + integrationRulesArray [ 0 ]->SetUpPointsOnTetrahedra(numberOfGaussPoints, _Unknown); + } + } +}; + +const FEInterpolation & UPBrick11::uInterpol = FEI3dHexaLin(); +const FEInterpolation & UPBrick11::pInterpol = FEI3dHexaLin(); +const Variable& UPBrick11::p = Variable(UPBrick11::pInterpol, Variable::VariableQuantity::Pressure, Variable::VariableType::scalar, 3, NULL, {11}); +const Variable& UPBrick11::u = Variable(UPBrick11::uInterpol, Variable::VariableQuantity::Displacement, Variable::VariableType::vector, 3, NULL, {1,2,3}); + +#define _IFT_UPBrick11_Name "upbrick11" +REGISTER_Element(UPBrick11) + + + +#define _IFT_UPSimpleMaterial_Name "upm" +#define _IFT_UPSimpleMaterial_E "e" +#define _IFT_UPSimpleMaterial_nu "nu" +#define _IFT_UPSimpleMaterial_k "k" +#define _IFT_UPSimpleMaterial_alpha "alpha" +#define _IFT_UPSimpleMaterial_c "c" + +class UPMaterialStatus : public MaterialStatus +{ +protected: + /// Equilibrated strain vector in reduced form + FloatArray strainVector; + /// Equilibrated stress vector in reduced form + FloatArray stressVector; + /// Temporary stress vector in reduced form (increments are used mainly in nonlinear analysis) + FloatArray tempStressVector; + /// Temporary strain vector in reduced form (to find balanced state) + FloatArray tempStrainVector; +public: + /// Constructor. Creates new StructuralMaterialStatus with IntegrationPoint g. + UPMaterialStatus (GaussPoint * g) : MaterialStatus(g), strainVector(), stressVector(), + tempStressVector(), tempStrainVector() + {} + +/// Returns the const pointer to receiver's strain vector. + const FloatArray &giveStrainVector() const { return strainVector; } + /// Returns the const pointer to receiver's stress vector. + const FloatArray &giveStressVector() const { return stressVector; } + /// Returns the const pointer to receiver's temporary strain vector. + const FloatArray &giveTempStrainVector() const { return tempStrainVector; } + /// Returns the const pointer to receiver's temporary stress vector. + const FloatArray &giveTempStressVector() const { return tempStressVector; } + /// Assigns tempStressVector to given vector v. + void letTempStressVectorBe(const FloatArray &v) { tempStressVector = v; } + /// Assigns tempStrainVector to given vector v + void letTempStrainVectorBe(const FloatArray &v) { tempStrainVector = v; } + + void printOutputAt(FILE *file, TimeStep *tStep) const override { + MaterialStatus :: printOutputAt(file, tStep); + fprintf(file, " strains "); + for ( auto &var : strainVector ) { + fprintf( file, " %+.4e", var ); + } + + fprintf(file, "\n stresses"); + for ( auto &var : stressVector ) { + fprintf( file, " %+.4e", var ); + } + fprintf(file, "\n"); + } + + void initTempStatus() override { + MaterialStatus :: initTempStatus(); + tempStressVector = stressVector; + tempStrainVector = strainVector; + } + void updateYourself(TimeStep *tStep) override { + MaterialStatus :: updateYourself(tStep); + stressVector = tempStressVector; + strainVector = tempStrainVector; + } + const char *giveClassName() const override {return "UPMaterialStatus";} + +}; + +class UPSimpleMaterial : public Material { + protected: + double e, nu; // elastic isotropic constants + double k; // isotropic permeability + double alpha; // Biot constant = 1-K_t/K_s (Kt bulk moduli of the porous medium, Ks bulk moduli of solid phase) + double c; // 1/Q, where Q is combined compressibility of the fluid and solid phases (1/Q=n/Kt+(b-n)/Ks, where n is porosity) + public: + UPSimpleMaterial (int n, Domain* d) : Material (n,d) {e=1.0; nu=0.15; k=1.0; alpha=1.0; c=0.1;} + + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, GaussPoint* gp, TimeStep *tStep) override { + if (type == StiffnessMatrix) { + double ee; + + ee = e / ( ( 1. + nu ) * ( 1. - 2. * nu ) ); + answer.resize(6, 6); + answer.zero(); + + answer.at(1, 1) = 1. - nu; + answer.at(1, 2) = nu; + answer.at(1, 3) = nu; + answer.at(2, 1) = nu; + answer.at(2, 2) = 1. - nu; + answer.at(2, 3) = nu; + answer.at(3, 1) = nu; + answer.at(3, 2) = nu; + answer.at(3, 3) = 1. - nu; + + answer.at(4, 4) = ( 1. - 2. * nu ) * 0.5; + answer.at(5, 5) = ( 1. - 2. * nu ) * 0.5; + answer.at(6, 6) = ( 1. - 2. * nu ) * 0.5; + + answer.times(ee); + } else if (type == PermeabilityMatrix) { + answer.resize(3,3); + answer.beUnitMatrix(); + answer.times(this->k); + } + } + + void giveCharacteristicVector(FloatArray &answer, FloatArray& flux, CharType type, GaussPoint* gp, TimeStep *tStep) override { + if (type == InternalForcesVector) { + FloatMatrix d; + UPMaterialStatus *status = static_cast< UPMaterialStatus * >( this->giveStatus(gp) ); + + this->giveCharacteristicMatrix(d, StiffnessMatrix, gp, tStep); + answer.beProductOf(d, flux); + // update gp status + status->letTempStrainVectorBe(flux); + status->letTempStressVectorBe(answer); + + }else if (type == FluidMassBalancePressureContribution) { + FloatMatrix k; + this->giveCharacteristicMatrix(k, PermeabilityMatrix, gp, tStep); + answer.beProductOf(k, flux); + } + } + + + double giveCharacteristicValue(CharType type, GaussPoint* gp, TimeStep *tStep) override { + if (type == BiotConstant) { + return alpha; + } else if (type == CompressibilityCoefficient) { + return c; + } else { + return 0.0; + } + }; + + void initializeFrom(InputRecord &ir) override { + Material :: initializeFrom(ir); + + IR_GIVE_OPTIONAL_FIELD(ir, e, _IFT_UPSimpleMaterial_E); + IR_GIVE_OPTIONAL_FIELD(ir, nu, _IFT_UPSimpleMaterial_nu); + IR_GIVE_OPTIONAL_FIELD(ir, k, _IFT_UPSimpleMaterial_k); + IR_GIVE_OPTIONAL_FIELD(ir, alpha, _IFT_UPSimpleMaterial_alpha); + IR_GIVE_OPTIONAL_FIELD(ir, c, _IFT_UPSimpleMaterial_c); + + }; + // void giveInputRecord(DynamicInputRecord &input) override {}; + void giveInputRecord(DynamicInputRecord &input) override {}; + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new UPMaterialStatus(gp); } + + const char *giveClassName() const override {return "UPSimpleMaterial";} + const char *giveInputRecordName() const override {return _IFT_UPSimpleMaterial_Name;} + +}; +REGISTER_Material(UPSimpleMaterial) + +} // end namespace oofem diff --git a/src/oofemcfg.h.in b/src/oofemcfg.h.in index 0f49267f3..7b097a57f 100644 --- a/src/oofemcfg.h.in +++ b/src/oofemcfg.h.in @@ -4,36 +4,33 @@ #define PRG_HEADER_SM "\ ____________________________________________________\n\ - OOFEM - Finite Element Solver\n\ + ____ ____ __________ ___ \n\ + / __ \\/ __ \\/ __/ __/ |/ /___ _______ _\n\ +/ /_/ / /_/ / _// _// /|_/ // _ \\/ __/ _ `/\n\ +\\____/\\____/_/ /___/_/ /_(_)___/_/ \\_, / \n\ + /___/ \n\ @oofem_COPYRIGHT@\n\ ____________________________________________________\n" #define PRG_HEADER "\ ############################################################## www.oofem.org ###\n\ - #### #### ###### ###### # #\n\ - # # # # # # ## ##\n\ - # # # # ##### ##### # ## #\n\ - # # # # # # # #\n\ - # # # # # # # # OOFEM ver. @oofem_VERSION_MAJOR@.@oofem_VERSION_MINOR@\n\ - #### #### # ###### # # @oofem_COPYRIGHT@\n\ + ____ ____ __________ ___\n\ + / __ \\/ __ \\/ __/ __/ |/ /___ _______ _\n\ +/ /_/ / /_/ / _// _// /|_/ // _ \\/ __/ _ `/\n\ +\\____/\\____/_/ /___/_/ /_(_)___/_/ \\_, / OOFEM ver. @oofem_VERSION_MAJOR@.@oofem_VERSION_MINOR@\n\ + /___/ @oofem_COPYRIGHT@\n\ ################################################################################\n\n" - + #define HOST_TYPE "@HOST_TYPE@" #define HOST_NAME "@HOST_NAME@" #define MODULE_LIST "@MODULE_LIST@" /* Headers */ -/* Define if unistd.h defined */ -#cmakedefine HAVE_UNISTD_H 1 - /* Define if execinfo.h defined */ #cmakedefine HAVE_EXECINFO_H 1 /* Symbols */ -/* Define if access is defined */ -#cmakedefine HAVE_ACCESS 1 - /* Define if cbrt is defined */ #cmakedefine HAVE_CBRT 1 diff --git a/src/oofemlib/CMakeLists.txt b/src/oofemlib/CMakeLists.txt index 54e10ad7d..9a47054a2 100644 --- a/src/oofemlib/CMakeLists.txt +++ b/src/oofemlib/CMakeLists.txt @@ -38,6 +38,8 @@ set (core_unsorted # symcompcol.C compcol.C unstructuredgridfield.C + # + loadbalancer.C ) #oofegutils @@ -108,7 +110,8 @@ if (USE_PETSC) list (APPEND core_nm petscsolver.C petscsparsemtrx.C) endif () -if (USE_INTEL_MKL_PARDISO) +if (USE_INTEL_MKL_PARDISO OR USE_ONEAPI) + message (STATUS " MKL Solver is enabled for compilation") list (APPEND core_nm mklpardisosolver.C) endif () @@ -124,6 +127,7 @@ set (core_fields intvarfield.C maskedprimaryfield.C dofdistributedprimaryfield.C + eigenvectorprimaryfield.C uniformgridfield.C ) @@ -143,21 +147,24 @@ set (core_ltf set (core_cs crosssection.C emptycs.C + dummycrosssection.C ) set (core_td - particletopologydescription.C ) set (core_dofman dofmanager.C node.C slavenode.C + generalslavenode.C hangingnode.C qcnode.C rigidarmnode.C elementinternaldofman.C elementside.C + latticedirichletcouplingnode.C + latticeneumanncouplingnode.C ) set (core_material @@ -172,12 +179,23 @@ set (core_export outputexportmodule.C errorcheckingexportmodule.C vtkexportmodule.C + vtkbaseexportmodule.C vtkxmlexportmodule.C + vtkmemoryexportmodule.C + vtkxmlperiodicexportmodule.C + vtkxmllatticeexportmodule.C + vtkpfemexportmodule.C + vtkxfemexportmodule.C homexportmodule.C matlabexportmodule.C gpexportmodule.C ) +set (core_monitors + monitormanager.C + monitor.C + ) + set (core_iga iga/iga.C iga/feibspline.C @@ -194,6 +212,7 @@ set (core_arrays set (core_engng engngm.C staggeredproblem.C + dummyengngm.C ) set (core_element @@ -219,6 +238,7 @@ set (core_fei fei2dquadbiquad.C fei3dlinelin.C fei3dtrlin.C + fei3dquadlin.C fei3dtrquad.C fei3dtetlin.C fei3dtetquad.C @@ -264,7 +284,6 @@ set (core_parallel domaintransactionmanager.C parallelordering.C dyncombuff.C - loadbalancer.C wallclockloadbalancermonitor.C nonlocalmatwtp.C ) @@ -300,11 +319,17 @@ set (core_bc linearconstraintbc.C ) -if (USE_PYTHON) +if (USE_PYTHON_EXTENSION) list (APPEND core_bc userdefdirichletbc.C) list (APPEND core_unsorted pythonexpression.C) endif () +if (USE_PYBIND_BINDINGS) + list (APPEND core_unsorted pythonfield.C) +endif () + + + set (core_mapping mmaclosestiptransfer.C mmashapefunctprojection.C @@ -331,6 +356,7 @@ set (core ${core_dofman} ${core_material} ${core_export} + ${core_monitors} ${core_ltf} ${core_cs} ${core_arrays} diff --git a/src/oofemlib/activebc.h b/src/oofemlib/activebc.h index e276638f0..338e2a842 100644 --- a/src/oofemlib/activebc.h +++ b/src/oofemlib/activebc.h @@ -72,18 +72,15 @@ class OOFEM_EXPORT ActiveBoundaryCondition : public GeneralBoundaryCondition /// Destructor. virtual ~ActiveBoundaryCondition() { } - IRResultType initializeFrom(InputRecord *ir) + void initializeFrom(InputRecord &ir) override { GeneralBoundaryCondition :: initializeFrom(ir); - IRResultType result; IntArray tempA, tempB, tempC; IR_GIVE_OPTIONAL_FIELD(ir, tempB, _IFT_ActiveBoundaryCondition_elementSides); for ( int i = 0; i < tempB.giveSize() / 2; ++i ) { - this->addElementSide( tempB(i * 2), tempB(i * 2 + 1) ); + this->addElementSide( tempB[i * 2], tempB[i * 2 + 1] ); } - - return IRRT_OK; } /// @name Methods supporting classical input files. @@ -105,9 +102,10 @@ class OOFEM_EXPORT ActiveBoundaryCondition : public GeneralBoundaryCondition * @param r_s Row numbering scheme. * @param c_s Column numbering scheme. * @param scale Scaling factor. + * @param omp_lock optional OMP lock to ensure correct update of answer */ virtual void assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0) { } + CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0, void* lock=nullptr) { } /** * Assembles B.C. contributions to specified vector. @@ -117,11 +115,12 @@ class OOFEM_EXPORT ActiveBoundaryCondition : public GeneralBoundaryCondition * @param mode Mode of value. * @param s Numbering scheme. * @param eNorms Norms for each dofid. + * @param omp_lock optional OMP lock to ensure correct update of answer * @return Equivalent of the sum of the element norm (squared) of assembled vector. */ virtual void assembleVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorms = NULL) { } + const UnknownNumberingScheme &s, FloatArray *eNorms=nullptr, void*lock=nullptr) { } /** * Gives a list of location arrays that will be assembled. @@ -183,7 +182,7 @@ class OOFEM_EXPORT ActiveBoundaryCondition : public GeneralBoundaryCondition virtual Dof *giveMasterDof(ActiveDof *dof, int mdof) { OOFEM_ERROR("Not supported by bc."); - return NULL; + return nullptr; } virtual void computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs) { diff --git a/src/oofemlib/activedof.C b/src/oofemlib/activedof.C index c15697f7e..d85cbd4e7 100644 --- a/src/oofemlib/activedof.C +++ b/src/oofemlib/activedof.C @@ -256,22 +256,19 @@ double ActiveDof :: giveBcValue(ValueModeType mode, TimeStep *tStep) // Not sure of initial conditions yet. -bool ActiveDof :: hasIc(TimeStep *tStep) { return false; } bool ActiveDof :: hasIcOn(ValueModeType type) { return false; } bool ActiveDof :: hasIc() { return false; } int ActiveDof :: giveIcId() { return 0; } InitialCondition *ActiveDof :: giveIc() { return NULL; } -contextIOResultType ActiveDof :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void ActiveDof :: saveContext(DataStream &stream, ContextMode mode) { // Nothing here since the boundary condition deals with all the values. - return CIO_OK; } -contextIOResultType ActiveDof :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void ActiveDof :: restoreContext(DataStream &stream, ContextMode mode) { - return CIO_OK; } inline Dof *ActiveDof :: giveMasterDof(int i) diff --git a/src/oofemlib/activedof.h b/src/oofemlib/activedof.h index 81285e3d4..e5b2ad184 100644 --- a/src/oofemlib/activedof.h +++ b/src/oofemlib/activedof.h @@ -66,41 +66,40 @@ class OOFEM_EXPORT ActiveDof : public Dof /// Destructor. virtual ~ActiveDof() { } - virtual void initialize(int cntOfMstrDfMngr, const IntArray &masterNodes, const IntArray *mstrDofID, const FloatArray &mstrContribution); - virtual int giveNumberOfPrimaryMasterDofs(); - virtual bool isPrimaryDof(); + void initialize(int cntOfMstrDfMngr, const IntArray &masterNodes, const IntArray *mstrDofID, const FloatArray &mstrContribution); + int giveNumberOfPrimaryMasterDofs() override; + bool isPrimaryDof() override; int giveNumberOfMasterDofs(); - virtual void giveMasterDofManArray(IntArray &answer); - virtual void giveUnknowns(FloatArray &masterUnknowns, ValueModeType mode, TimeStep *tStep); - virtual void giveUnknowns(FloatArray &masterUnknowns, PrimaryField &field, ValueModeType mode, TimeStep *tStep); - virtual void computeDofTransformation(FloatArray &primaryMasterContribs); - virtual void giveEquationNumbers(IntArray &masterEqNumbers, const UnknownNumberingScheme &s); - virtual void giveDofIDs(IntArray &masterDofIDs); + void giveMasterDofManArray(IntArray &answer) override; + void giveUnknowns(FloatArray &masterUnknowns, ValueModeType mode, TimeStep *tStep) override; + void giveUnknowns(FloatArray &masterUnknowns, PrimaryField &field, ValueModeType mode, TimeStep *tStep) override; + void computeDofTransformation(FloatArray &primaryMasterContribs) override; + void giveEquationNumbers(IntArray &masterEqNumbers, const UnknownNumberingScheme &s) override; + void giveDofIDs(IntArray &masterDofIDs) override; - virtual double giveUnknown(ValueModeType mode, TimeStep *tStep); - virtual double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep); + double giveUnknown(ValueModeType mode, TimeStep *tStep) override; + double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual dofType giveDofType() { return DT_active; } - virtual const char *giveClassName() const { return "ActiveDof"; } + dofType giveDofType() override { return DT_active; } + const char *giveClassName() const override { return "ActiveDof"; } - virtual void updateLocalNumbering(EntityRenumberingFunctor &f); + void updateLocalNumbering(EntityRenumberingFunctor &f) override; - virtual int __giveEquationNumber() const; - virtual int __givePrescribedEquationNumber(); - virtual int askNewEquationNumber(TimeStep *tStep); - virtual bool hasBc(TimeStep *tStep); - virtual int giveBcId(); - virtual void setBcId(int bcId); - virtual double giveBcValue(ValueModeType mode, TimeStep *tStep); + int __giveEquationNumber() const override; + int __givePrescribedEquationNumber() override; + int askNewEquationNumber(TimeStep *tStep) override; + bool hasBc(TimeStep *tStep) override; + int giveBcId() override; + void setBcId(int bcId) override; + double giveBcValue(ValueModeType mode, TimeStep *tStep) override; - virtual bool hasIc(TimeStep *tStep); - virtual bool hasIcOn(ValueModeType type); - virtual InitialCondition *giveIc(); - virtual bool hasIc(); - virtual int giveIcId(); + bool hasIcOn(ValueModeType type) override; + InitialCondition *giveIc() override; + bool hasIc() override; + int giveIcId() override; ActiveBoundaryCondition *giveActiveBoundaryCondition(); diff --git a/src/oofemlib/alist.h b/src/oofemlib/alist.h deleted file mode 100644 index 0de34be6a..000000000 --- a/src/oofemlib/alist.h +++ /dev/null @@ -1,362 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef alist_h -#define alist_h - -#include "error.h" - -#include - - -namespace oofem { -/** - * Class implementing generic list (or more precisely array). - * It maintains the array of generic pointers to objects of type T using 1-based numbering. - * - * This class maintains only the links (pointers) to particular objects, objects themselves are not contained within - * this array. They have to be created outside (in memory, usually on heap) and then their pointers can be added to - * array. This is sometimes called non-intrusive approach. When destructor is called, the linked objects - * are deleted. To prevent the deletion, objects should be unlinked before deconstructor is called. - * - * The links to particular objects in array are stored in pointer array, therefore the access to particular - * component is very efficient. On the other hand, the resizing of array is relative time expensive (the whole - * existing pointer table must be transferred) and is recommended to set size of the array to the final size. - */ -template< class T > class AList -{ -protected: - /// Array or list size (number of components to store). - int size; - /// Real allocated size (may be larger than size, to prevent often reallocation). - int allocatedSize; - /// List size allocation increment. - int sizeIncrement; - /// Array of pointers to particular components. - T **values; - -public: - /** - * Creates list of size s. - * @param s Initial size. - * @param sizeIncrement Increases array in blocks of this size when necessary. - */ - AList(int s = 0, int sizeIncrement = 0); - /// Destructor - ~AList(); - - /** - * @param i Index of object. - * @return Object at given index. - */ - inline T *at(int i) const; - /** - * Expands the receiver from its current size to newSize, in order to accommodate new entries. - * @param newSize Size that receiver must fit. - */ - void growTo(int newSize); - /** - * Resize the receiver from its current size to newSize, in order to accommodate new entries. - * If existing size is larger than new size, existing elements at postions exceeding newSize - * will be deleted. - * @param newSize Size that receiver must fit. - */ - void resize(int newSize); - /** - * Checks if receiver includes object as given position. - * @param i Index of object. - * @return true if object is non-null at i-th entry, otherwise false. - */ - bool includes(int i) const; - /// @return Size of array. - int giveSize() const { return size; } - /// @return True if receiver is empty, otherwise false. - int isEmpty() const { return ( size == 0 ); } - /// @return True if receiver is not empty, otherwise false. - int isNotEmpty() const { return ( size != 0 ); } - /// Prints the receiver on screen. - void printYourself() const; - /** - * Stores anObject at position i. - * Enlarges the receiver if too small and deletes the old value if it exists. - * @param i Index to put object - * @param anObject Object to put as position i. - */ - void put(int i, T *anObject); - /** - * Clears receiver. - * Objects are deleted if depending on the delete flag. - * @param deleteObjectFlag Shows if objects should be deleted. - */ - void clear(bool deleteObjectFlag = true); - /// Deletes the object at i-th position. - void remove(int i); - /** - * Unlinks the object a i-th position. - * The object is returned, and its entry is - * unlinked, so there will be no further reference to this object. Does not delete - * the object, its pointer is returned. - * @param i Index where to unlink. - * @return Object at index i. - */ - T *unlink(int i); -}; - -template< class T >AList< T > :: AList(int s, int sizeIncrement) -// Constructor : creates a list of size s. -{ - int i; - T **p; - - allocatedSize = size = s; - if ( size ) { - values = new T * [ size ]; - p = values; - i = size; - while ( i-- ) { - * p++ = NULL; - } - } // initialize 'values' - else { - values = NULL; - } - - this->sizeIncrement = sizeIncrement; -} - - -template< class T > AList< T > :: ~AList() -{ - this->clear(true); -} - -template< class T > void -AList< T > :: clear(bool deleteObjectFlag) -{ - int i = size; - - if ( size ) { - if ( deleteObjectFlag ) { - while ( i-- ) { - delete(values [ i ]); - } - } - - delete[] values; - } - - allocatedSize = size = 0; - values = NULL; -} - -template< class T > void -AList< T > :: growTo(int newSize) -// Expands the receiver from its current size to newSize, in order to accommodate new entries. -{ - int i; - T **newValues, **p1, **p2; - - - if ( newSize < size ) { -#ifdef DEBUG - OOFEM_ERROR("new list size (%d) not larger than current size (%d)", newSize, size); -#endif - // delete entities in indexes in the range (newSize, size) - i = size; - if ( size ) { - while ( ( --i ) >= newSize ) { - delete(values [ i ]); - values [ i ] = NULL; - } - } - } else if ( newSize > allocatedSize ) { - this->allocatedSize = newSize + this->sizeIncrement; - newValues = new T * [ this->allocatedSize ]; - p1 = values; - p2 = newValues; - for ( i = 0; i < size; i++ ) { - * p2++ = * p1++; - } - - for ( i = size; i < this->allocatedSize; i++ ) { - * p2++ = NULL; - } - - if ( values ) { - delete[] values; - } - - values = newValues; - this->allocatedSize = newSize + this->sizeIncrement; - } - - size = newSize; -} - -template< class T > void -AList< T > :: resize(int newSize) -// Expands the receiver from its current size to newSize, in order to accommodate new entries. -{ - int i; - T **newValues, **p1, **p2; - - - if ( newSize < size ) { - // delete entities in indexes in the range (newSize, size) - i = size; - if ( size ) { - while ( ( --i ) >= newSize ) { - delete(values [ i ]); - values [ i ] = NULL; - } - } - } else if ( newSize > allocatedSize ) { - this->allocatedSize = newSize + this->sizeIncrement; - newValues = new T * [ this->allocatedSize ]; - p1 = values; - p2 = newValues; - for ( i = 0; i < size; i++ ) { - * p2++ = * p1++; - } - - for ( i = size; i < this->allocatedSize; i++ ) { - * p2++ = NULL; - } - - if ( values ) { - // delete [size] values ; - delete[] values; - } - - values = newValues; - this->allocatedSize = newSize + this->sizeIncrement; - } - - size = newSize; -} - -template< class T > T * -AList< T > :: at(int i) const -{ -#ifdef DEBUG - if ( i <= 0 ) { - OOFEM_ERROR("Asking for negative or zero indices (%d)", i); - } -#endif - return values [ i - 1 ]; -} - -template< class T > bool -AList< T > :: includes(int i) const -// Returns True if the receiver has a non-null i-th entry, else returns -// False. -{ -#ifdef DEBUG - if ( i <= 0 ) { - OOFEM_ERROR("Asking for negative or zero indices (%d)", i); - } -#endif - if ( i > size ) { - return false; - } else { - return ( values [ i - 1 ] != NULL ); - } -} - -template< class T > void -AList< T > :: printYourself() const -// Prints the receiver on screen. -{ - printf("List of components of size %d\n", size); - for ( int i = 1; i <= size; i++ ) { - printf("%d : %p\n", i, values [ i - 1 ]); - } -} - -template< class T > void AList< T > :: put(int i, T *anObject) -// Stores anObject at position i. Enlarge the receiver if too small. -{ -#ifdef DEBUG - if ( i <= 0 ) { - OOFEM_ERROR("Trying to write to zero or negative indices (%d)", i); - } -#endif - if ( size < i ) { - this->growTo(i); - } - - // delete old value - if ( values [ i - 1 ] ) { - delete values [ i - 1 ]; - } - - values [ i - 1 ] = anObject; -} - -template< class T > void AList< T > :: remove(int i) -{ -#ifdef DEBUG - if ( i < 0 ) { - OOFEM_ERROR("Trying to remove at zero or negative indices (%d)", i); - } -#endif - - if ( size < i ) { - return; - } - - if ( values [ i - 1 ] ) { - delete values [ i - 1 ]; - values [ i - 1 ] = NULL; - } -} - - -template< class T > T *AList< T > :: unlink(int i) -{ -#ifdef DEBUG - if ( i <= 0 ) { - OOFEM_ERROR("Trying to unlink at zero or negative indices (%d)", i); - } -#endif - if ( size < i ) { - return NULL; - } - - T *answer = values [ i - 1 ]; - values [ i - 1 ] = NULL; - return answer; -} -} // end namespace oofem -#endif // alist_h diff --git a/src/oofemlib/assemblercallback.C b/src/oofemlib/assemblercallback.C index 054561342..15c320de1 100644 --- a/src/oofemlib/assemblercallback.C +++ b/src/oofemlib/assemblercallback.C @@ -55,7 +55,7 @@ void VectorAssembler :: vectorFromEdgeLoad(FloatArray& vec, Element& element, Ed void VectorAssembler :: vectorFromNodeLoad(FloatArray& vec, DofManager& dman, NodalLoad* load, TimeStep* tStep, ValueModeType mode) const { vec.clear(); } -void VectorAssembler :: assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) const { } +void VectorAssembler :: assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms, void* lock) const { } void VectorAssembler :: locationFromElement(IntArray& loc, Element& element, const UnknownNumberingScheme& s, IntArray* dofIds) const { @@ -75,7 +75,7 @@ void MatrixAssembler :: matrixFromSurfaceLoad(FloatMatrix& mat, Element& element void MatrixAssembler :: matrixFromEdgeLoad(FloatMatrix& mat, Element& element, EdgeLoad* load, int edge, TimeStep* tStep) const { mat.clear(); } -void MatrixAssembler :: assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c) const {} +void MatrixAssembler :: assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c, void *lock) const {} void MatrixAssembler :: locationFromElement(IntArray& loc, Element& element, const UnknownNumberingScheme& s, IntArray* dofIds) const { @@ -91,29 +91,31 @@ void MatrixAssembler :: locationFromElementNodes(IntArray& loc, Element& element void MatrixProductAssembler :: vectorFromElement(FloatArray& vec, Element& element, TimeStep* tStep, ValueModeType mode) const { FloatMatrix mat; + FloatArray r; this->mAssem.matrixFromElement(mat, element, tStep); - vec.beProductOf(mat, this->vec); + element.computeVectorOf(mode, tStep, r); + vec.beProductOf(mat, r); } void MatrixProductAssembler :: vectorFromLoad(FloatArray& vec, Element& element, BodyLoad* load, TimeStep* tStep, ValueModeType mode) const { FloatMatrix mat; this->mAssem.matrixFromLoad(mat, element, load, tStep); - vec.beProductOf(mat, this->vec); + //vec.beProductOf(mat, this->vec); } void MatrixProductAssembler :: vectorFromSurfaceLoad(FloatArray& vec, Element& element, SurfaceLoad* load, int boundary, TimeStep* tStep, ValueModeType mode) const { FloatMatrix mat; this->mAssem.matrixFromSurfaceLoad(mat, element, load, boundary, tStep); - vec.beProductOf(mat, this->vec); + //vec.beProductOf(mat, this->vec); } void MatrixProductAssembler :: vectorFromEdgeLoad(FloatArray& vec, Element& element, EdgeLoad* load, int edge, TimeStep* tStep, ValueModeType mode) const { FloatMatrix mat; this->mAssem.matrixFromEdgeLoad(mat, element, load, edge, tStep); // ?????? - vec.beProductOf(mat, this->vec); + //vec.beProductOf(mat, this->vec); } @@ -141,9 +143,9 @@ void InternalForceAssembler :: vectorFromEdgeLoad(FloatArray& vec, Element& elem //element.computeInternalForcesFromEdgeLoad(vec, load, edge, tStep); } -void InternalForceAssembler :: assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) const +void InternalForceAssembler :: assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms, void* lock) const { - bc.assembleVector(answer, tStep, InternalForcesVector, mode, s, eNorms); + bc.assembleVector(answer, tStep, InternalForcesVector, mode, s, eNorms, lock); //bc.assembleInternalForces(answer, tStep, s, eNorms); } @@ -156,6 +158,7 @@ void ExternalForceAssembler :: vectorFromElement(FloatArray& vec, Element& eleme void ExternalForceAssembler :: vectorFromLoad(FloatArray& vec, Element& element, BodyLoad* load, TimeStep* tStep, ValueModeType mode) const { + vec.clear(); if ( ! load->reference ) element.computeLoadVector(vec, load, ExternalForcesVector, mode, tStep); //element.computeExternalForcesFromLoad(vec, load, tStep); @@ -163,6 +166,7 @@ void ExternalForceAssembler :: vectorFromLoad(FloatArray& vec, Element& element, void ExternalForceAssembler :: vectorFromSurfaceLoad(FloatArray& vec, Element& element, SurfaceLoad* load, int boundary, TimeStep* tStep, ValueModeType mode) const { + vec.clear(); if ( ! load->reference ) element.computeBoundarySurfaceLoadVector(vec, load, boundary, ExternalForcesVector, mode, tStep); //element.computeExternalForcesFromSurfaceLoad(vec, load, boundary, tStep); @@ -170,6 +174,7 @@ void ExternalForceAssembler :: vectorFromSurfaceLoad(FloatArray& vec, Element& e void ExternalForceAssembler :: vectorFromEdgeLoad(FloatArray& vec, Element& element, EdgeLoad* load, int edge, TimeStep* tStep, ValueModeType mode) const { + vec.clear(); if ( ! load->reference ) element.computeBoundaryEdgeLoadVector(vec, load, edge, ExternalForcesVector, mode, tStep); //element.computeExternalForcesFromEdgeLoad(vec, load, edge, tStep); @@ -177,20 +182,22 @@ void ExternalForceAssembler :: vectorFromEdgeLoad(FloatArray& vec, Element& elem void ExternalForceAssembler :: vectorFromNodeLoad(FloatArray& vec, DofManager& dman, NodalLoad* load, TimeStep* tStep, ValueModeType mode) const { + vec.clear(); if ( ! load->reference ) dman.computeLoadVector(vec, load, ExternalForcesVector, tStep, mode); //dman.computeExternalForcesFromLoad(vec, load, tStep); } -void ExternalForceAssembler :: assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) const +void ExternalForceAssembler :: assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms, void* lock) const { - bc.assembleVector(answer, tStep, ExternalForcesVector, mode, s, eNorms); + bc.assembleVector(answer, tStep, ExternalForcesVector, mode, s, eNorms, lock); //bc.assembleExternalForces(answer, tStep, s, eNorms); } void ReferenceForceAssembler :: vectorFromLoad(FloatArray& vec, Element& element, BodyLoad* load, TimeStep* tStep, ValueModeType mode) const { + vec.clear(); if ( load->reference ) element.computeLoadVector(vec, load, ExternalForcesVector, mode, tStep); //element.computeExternalForcesFromLoad(vec, load, tStep); @@ -199,6 +206,7 @@ void ReferenceForceAssembler :: vectorFromLoad(FloatArray& vec, Element& element void ReferenceForceAssembler :: vectorFromSurfaceLoad(FloatArray& vec, Element& element, SurfaceLoad* load, int boundary, TimeStep* tStep, ValueModeType mode) const { + vec.clear(); if ( load->reference ) element.computeBoundarySurfaceLoadVector(vec, load, boundary, ExternalForcesVector, mode, tStep); //element.computeExternalForcesFromBoundaryLoad(vec, load, boundary, tStep); @@ -206,6 +214,7 @@ void ReferenceForceAssembler :: vectorFromSurfaceLoad(FloatArray& vec, Element& void ReferenceForceAssembler :: vectorFromEdgeLoad(FloatArray& vec, Element& element, EdgeLoad* load, int edge, TimeStep* tStep, ValueModeType mode) const { + vec.clear(); if ( load->reference ) element.computeBoundaryEdgeLoadVector(vec, load, edge, ExternalForcesVector, mode, tStep); //element.computeExternalForcesFromEdgeLoad(vec, load, edge, tStep); @@ -213,6 +222,7 @@ void ReferenceForceAssembler :: vectorFromEdgeLoad(FloatArray& vec, Element& ele void ReferenceForceAssembler :: vectorFromNodeLoad(FloatArray& vec, DofManager& dman, NodalLoad* load, TimeStep* tStep, ValueModeType mode) const { + vec.clear(); if ( load->reference ) dman.computeLoadVector(vec, load, ExternalForcesVector, tStep, mode); //dman.computeExternalForcesFromLoad(vec, load, tStep); @@ -262,9 +272,9 @@ void TangentAssembler :: matrixFromEdgeLoad(FloatMatrix& mat, Element& element, element.computeTangentFromEdgeLoad(mat, load, edge, this->rmode, tStep); } -void TangentAssembler :: assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c) const +void TangentAssembler :: assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c, void *lock) const { - bc.assemble(k, tStep, TangentStiffnessMatrix, s_r, s_c); + bc.assemble(k, tStep, TangentStiffnessMatrix, s_r, s_c, 1.0, lock); } @@ -315,14 +325,14 @@ void EffectiveTangentAssembler :: matrixFromSurfaceLoad(FloatMatrix& mat, Elemen void EffectiveTangentAssembler :: matrixFromEdgeLoad(FloatMatrix& mat, Element& element, EdgeLoad* load, int edge, TimeStep* tStep) const { mat.clear(); - //element.computeTangentFromEdgeLoad(mat, load, edge, this->rmode, tStep); - //mat.times(this->k); + element.computeTangentFromEdgeLoad(mat, load, edge, this->rmode, tStep); + mat.times(this->k); } -void EffectiveTangentAssembler :: assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c) const +void EffectiveTangentAssembler :: assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c, void* lock) const { // TODO: Crucial part to add: We have to support a scaling factor for this method to support effective tangents. - bc.assemble(k, tStep, TangentStiffnessMatrix, s_r, s_c, this->k); + bc.assemble(k, tStep, TangentStiffnessMatrix, s_r, s_c, this->k, lock); } diff --git a/src/oofemlib/assemblercallback.h b/src/oofemlib/assemblercallback.h index 695a85de9..7140be24f 100644 --- a/src/oofemlib/assemblercallback.h +++ b/src/oofemlib/assemblercallback.h @@ -35,6 +35,7 @@ #ifndef assemblercallback_h #define assemblercallback_h +#include "oofem_export.h" #include "valuemodetype.h" ///@todo We shouldn't have this for assembling vectors or matrices(!) / Mikael #include "matresponsemode.h" #include "chartype.h" @@ -60,7 +61,7 @@ class ActiveBoundaryCondition; * Default implementations are that no contributions are considered (empty vectors on output). * @author Mikael Öhman */ -class VectorAssembler +class OOFEM_EXPORT VectorAssembler { public: virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; @@ -68,7 +69,7 @@ class VectorAssembler virtual void vectorFromSurfaceLoad(FloatArray &vec, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep, ValueModeType mode) const; virtual void vectorFromEdgeLoad(FloatArray &vec, Element &element, EdgeLoad *load, int edge, TimeStep *tStep, ValueModeType mode) const; virtual void vectorFromNodeLoad(FloatArray &vec, DofManager &dman, NodalLoad *load, TimeStep *tStep, ValueModeType mode) const; - virtual void assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) const; + virtual void assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms, void* lock=nullptr) const; /// Default implementation takes all the DOF IDs virtual void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const; @@ -80,14 +81,14 @@ class VectorAssembler * Callback class for assembling specific types of matrices * @author Mikael Öhman */ -class MatrixAssembler +class OOFEM_EXPORT MatrixAssembler { public: virtual void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const; virtual void matrixFromLoad(FloatMatrix &mat, Element &element, BodyLoad *load, TimeStep *tStep) const; virtual void matrixFromSurfaceLoad(FloatMatrix &mat, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep) const; virtual void matrixFromEdgeLoad(FloatMatrix &mat, Element &element, EdgeLoad *load, int edge, TimeStep *tStep) const; - virtual void assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c) const; + virtual void assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c, void* lock=nullptr) const; virtual void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const; virtual void locationFromElementNodes(IntArray &loc, Element &element, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIds = nullptr) const; @@ -98,62 +99,62 @@ class MatrixAssembler * Implementation for assembling internal forces vectors in standard monolithic, nonlinear FE-problems * @author Mikael Öhman */ -class InternalForceAssembler : public VectorAssembler +class OOFEM_EXPORT InternalForceAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromLoad(FloatArray &vec, Element &element, BodyLoad *load, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromSurfaceLoad(FloatArray &vec, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromEdgeLoad(FloatArray &vec, Element &element, EdgeLoad *load, int edge, TimeStep *tStep, ValueModeType mode) const; - virtual void assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromLoad(FloatArray &vec, Element &element, BodyLoad *load, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromSurfaceLoad(FloatArray &vec, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromEdgeLoad(FloatArray &vec, Element &element, EdgeLoad *load, int edge, TimeStep *tStep, ValueModeType mode) const override; + void assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms, void* lock=nullptr) const override; }; /** * Implementation for assembling external forces vectors in standard monolithic FE-problems * @author Mikael Öhman */ -class ExternalForceAssembler : public VectorAssembler +class OOFEM_EXPORT ExternalForceAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; ///@todo Temporary: Remove when switch to sets is complete - virtual void vectorFromLoad(FloatArray &vec, Element &element, BodyLoad *load, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromSurfaceLoad(FloatArray &vec, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromEdgeLoad(FloatArray &vec, Element &element, EdgeLoad *load, int edge, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromNodeLoad(FloatArray &vec, DofManager &dman, NodalLoad *load, TimeStep *tStep, ValueModeType mode) const; - virtual void assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; ///@todo Temporary: Remove when switch to sets is complete + void vectorFromLoad(FloatArray &vec, Element &element, BodyLoad *load, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromSurfaceLoad(FloatArray &vec, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromEdgeLoad(FloatArray &vec, Element &element, EdgeLoad *load, int edge, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromNodeLoad(FloatArray &vec, DofManager &dman, NodalLoad *load, TimeStep *tStep, ValueModeType mode) const override; + void assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep* tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms, void*lock=nullptr) const override; }; /** * Implementation for assembling reference (external) forces vectors * @author Mikael Öhman */ -class ReferenceForceAssembler : public VectorAssembler +class OOFEM_EXPORT ReferenceForceAssembler : public VectorAssembler { public: - virtual void vectorFromLoad(FloatArray &vec, Element &element, BodyLoad *load, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromSurfaceLoad(FloatArray &vec, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromEdgeLoad(FloatArray &vec, Element &element, EdgeLoad *load, int edge, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromNodeLoad(FloatArray &vec, DofManager &dman, NodalLoad *load, TimeStep *tStep, ValueModeType mode) const; + void vectorFromLoad(FloatArray &vec, Element &element, BodyLoad *load, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromSurfaceLoad(FloatArray &vec, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromEdgeLoad(FloatArray &vec, Element &element, EdgeLoad *load, int edge, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromNodeLoad(FloatArray &vec, DofManager &dman, NodalLoad *load, TimeStep *tStep, ValueModeType mode) const override; }; /** * Implementation for assembling lumped mass matrix (diagonal components) in vector form. * @author Mikael Öhman */ -class LumpedMassVectorAssembler : public VectorAssembler +class OOFEM_EXPORT LumpedMassVectorAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; /** * Implementation for assembling the intertia forces vector (i.e. C * dT/dt or M * a) * @author Mikael Öhman */ -class InertiaForceAssembler : public VectorAssembler +class OOFEM_EXPORT InertiaForceAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; @@ -162,19 +163,18 @@ class InertiaForceAssembler : public VectorAssembler * This is useful for computing; f = K * u for extrapolated forces, without constructing the K-matrix. * @author Mikael Öhman */ -class MatrixProductAssembler : public VectorAssembler +class OOFEM_EXPORT MatrixProductAssembler : public VectorAssembler { protected: - MatrixAssembler mAssem; - const FloatArray &vec; + const MatrixAssembler &mAssem; public: - MatrixProductAssembler(MatrixAssembler m, const FloatArray &vec): VectorAssembler(), mAssem(m), vec(vec) {} + MatrixProductAssembler(const MatrixAssembler &m): VectorAssembler(), mAssem(m) {} - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromLoad(FloatArray &vec, Element &element, BodyLoad *load, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromSurfaceLoad(FloatArray &vec, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep, ValueModeType mode) const; - virtual void vectorFromEdgeLoad(FloatArray &vec, Element &element, EdgeLoad *load, int edge, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromLoad(FloatArray &vec, Element &element, BodyLoad *load, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromSurfaceLoad(FloatArray &vec, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep, ValueModeType mode) const override; + void vectorFromEdgeLoad(FloatArray &vec, Element &element, EdgeLoad *load, int edge, TimeStep *tStep, ValueModeType mode) const override; }; @@ -182,20 +182,20 @@ class MatrixProductAssembler : public VectorAssembler * Implementation for assembling tangent matrices in standard monolithic FE-problems * @author Mikael Öhman */ -class TangentAssembler : public MatrixAssembler +class OOFEM_EXPORT TangentAssembler : public MatrixAssembler { protected: ///@todo This is more general than just material responses; we should make a "TangentType" MatResponseMode rmode; - + public: TangentAssembler(MatResponseMode m = TangentStiffness): MatrixAssembler(), rmode(m) {} - virtual void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const; - virtual void matrixFromLoad(FloatMatrix &mat, Element &element, BodyLoad *load, TimeStep *tStep) const; - virtual void matrixFromSurfaceLoad(FloatMatrix &mat, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep) const; - virtual void matrixFromEdgeLoad(FloatMatrix &mat, Element &element, EdgeLoad *load, int edge, TimeStep *tStep) const; - virtual void assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c) const; + void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const override; + void matrixFromLoad(FloatMatrix &mat, Element &element, BodyLoad *load, TimeStep *tStep) const override; + void matrixFromSurfaceLoad(FloatMatrix &mat, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep) const override; + void matrixFromEdgeLoad(FloatMatrix &mat, Element &element, EdgeLoad *load, int edge, TimeStep *tStep) const override; + void assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c, void*lock=nullptr) const override; }; @@ -203,10 +203,10 @@ class TangentAssembler : public MatrixAssembler * Implementation for assembling the consistent mass matrix * @author Mikael Öhman */ -class MassMatrixAssembler : public MatrixAssembler +class OOFEM_EXPORT MassMatrixAssembler : public MatrixAssembler { public: - virtual void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const; + void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const override; }; @@ -214,7 +214,7 @@ class MassMatrixAssembler : public MatrixAssembler * Callback class for assembling effective tangents composed of stiffness and mass matrix. * @author Mikael Öhman */ -class EffectiveTangentAssembler : public MatrixAssembler +class OOFEM_EXPORT EffectiveTangentAssembler : public MatrixAssembler { protected: MatResponseMode rmode; @@ -223,11 +223,11 @@ class EffectiveTangentAssembler : public MatrixAssembler public: EffectiveTangentAssembler(MatResponseMode mode, bool lumped, double k, double m); - virtual void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const; - virtual void matrixFromLoad(FloatMatrix &mat, Element &element, BodyLoad *load, TimeStep *tStep) const; - virtual void matrixFromSurfaceLoad(FloatMatrix &mat, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep) const; - virtual void matrixFromEdgeLoad(FloatMatrix &mat, Element &element, EdgeLoad *load, int edge, TimeStep *tStep) const; - virtual void assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c) const; + void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const override; + void matrixFromLoad(FloatMatrix &mat, Element &element, BodyLoad *load, TimeStep *tStep) const override; + void matrixFromSurfaceLoad(FloatMatrix &mat, Element &element, SurfaceLoad *load, int boundary, TimeStep *tStep) const override; + void matrixFromEdgeLoad(FloatMatrix &mat, Element &element, EdgeLoad *load, int edge, TimeStep *tStep) const override; + void assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep* tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c, void *lock=nullptr) const override; }; } diff --git a/src/oofemlib/bodyload.h b/src/oofemlib/bodyload.h index e03678445..37fd7f384 100644 --- a/src/oofemlib/bodyload.h +++ b/src/oofemlib/bodyload.h @@ -60,7 +60,7 @@ class OOFEM_EXPORT BodyLoad : public Load * Returns receiver's load geometry type. * @return BodyLoadBGT. */ - virtual bcGeomType giveBCGeoType() const { return BodyLoadBGT; } + bcGeomType giveBCGeoType() const override { return BodyLoadBGT; } }; } // end namespace oofem #endif // bodyload_h diff --git a/src/oofemlib/boundarycondition.C b/src/oofemlib/boundarycondition.C index b74e701e3..2ac228873 100644 --- a/src/oofemlib/boundarycondition.C +++ b/src/oofemlib/boundarycondition.C @@ -76,21 +76,16 @@ double BoundaryCondition :: give(Dof *dof, ValueModeType mode, double time) } -IRResultType -BoundaryCondition :: initializeFrom(InputRecord *ir) +void +BoundaryCondition :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = GeneralBoundaryCondition :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + GeneralBoundaryCondition :: initializeFrom(ir); - if ( ir->hasField(_IFT_BoundaryCondition_values) ) { + if ( ir.hasField(_IFT_BoundaryCondition_values) ) { IR_GIVE_FIELD(ir, values, _IFT_BoundaryCondition_values); } else { double prescribedValue; - if ( ir->hasField(_IFT_BoundaryCondition_PrescribedValue) ) { + if ( ir.hasField(_IFT_BoundaryCondition_PrescribedValue) ) { IR_GIVE_FIELD(ir, prescribedValue, _IFT_BoundaryCondition_PrescribedValue); } else { IR_GIVE_FIELD(ir, prescribedValue, _IFT_BoundaryCondition_PrescribedValue_d); @@ -104,8 +99,6 @@ BoundaryCondition :: initializeFrom(InputRecord *ir) values.zero(); values.add(prescribedValue); } - - return IRRT_OK; } @@ -132,38 +125,30 @@ BoundaryCondition :: scale(double s) } -contextIOResultType -BoundaryCondition :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +BoundaryCondition :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = GeneralBoundaryCondition :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + GeneralBoundaryCondition :: saveContext(stream, mode); if ( mode & CM_Definition ) { - if ( (iores = values.storeYourself(stream) ) != CIO_OK ) { + contextIOResultType iores; + if ( (iores = values.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(CIO_IOERR); } } - - return CIO_OK; } -contextIOResultType -BoundaryCondition :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +BoundaryCondition :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = GeneralBoundaryCondition :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + GeneralBoundaryCondition :: restoreContext(stream, mode); if ( mode & CM_Definition ) { - if ( (iores = values.restoreYourself(stream) ) != CIO_OK ) { + contextIOResultType iores; + if ( (iores = values.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(CIO_IOERR); } } - - return CIO_OK; } } // end namespace oofem diff --git a/src/oofemlib/boundarycondition.h b/src/oofemlib/boundarycondition.h index 0bed27015..7fd2ef7b1 100644 --- a/src/oofemlib/boundarycondition.h +++ b/src/oofemlib/boundarycondition.h @@ -118,16 +118,15 @@ class OOFEM_EXPORT BoundaryCondition : public GeneralBoundaryCondition void setPrescribedValue(double s); // Overloaded methods: - virtual bcType giveType() const { return DirichletBT; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void scale(double s); - virtual const char *giveClassName() const { return "BoundaryCondition"; } - virtual const char *giveInputRecordName() const { return _IFT_BoundaryCondition_Name; } - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + bcType giveType() const override { return DirichletBT; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void scale(double s) override; + const char *giveClassName() const override { return "BoundaryCondition"; } + const char *giveInputRecordName() const override { return _IFT_BoundaryCondition_Name; } + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; } // end namespace oofem #endif // boudary_h diff --git a/src/oofemlib/boundaryload.C b/src/oofemlib/boundaryload.C index 3c855879d..b5918bf8e 100644 --- a/src/oofemlib/boundaryload.C +++ b/src/oofemlib/boundaryload.C @@ -39,6 +39,8 @@ #include "dynamicinputrecord.h" #include "valuemodetype.h" #include "domain.h" +#include "datastream.h" +#include "contextioerr.h" namespace oofem { @@ -88,15 +90,10 @@ BoundaryLoad :: computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatA } -IRResultType -BoundaryLoad :: initializeFrom(InputRecord *ir) +void +BoundaryLoad :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = Load :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + Load :: initializeFrom(ir); int dummy; IR_GIVE_OPTIONAL_FIELD(ir, dummy, "ndofs"); @@ -116,8 +113,6 @@ BoundaryLoad :: initializeFrom(InputRecord *ir) temperOffset = 273.15; IR_GIVE_OPTIONAL_FIELD(ir, temperOffset, _IFT_BoundaryLoad_temperOffset); - - return IRRT_OK; } @@ -166,5 +161,52 @@ BoundaryLoad :: giveTemperOffset(void) return this->temperOffset; } +void +BoundaryLoad :: saveContext(DataStream &stream, ContextMode mode) +{ + Load :: saveContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( !stream.write(lType) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(coordSystemType) ) { + THROW_CIOERR(CIO_IOERR); + } + propertyDictionary.saveContext(stream); + propertyTimeFunctDictionary.saveContext(stream); + + if ( !stream.write(temperOffset) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +void +BoundaryLoad :: restoreContext(DataStream &stream, ContextMode mode) +{ + Load :: restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + int _val; + if ( !stream.read(_val) ) { + THROW_CIOERR(CIO_IOERR); + } + lType = (bcType) _val; + + if ( !stream.read(_val) ) { + THROW_CIOERR(CIO_IOERR); + } + coordSystemType = (CoordSystType) _val; + + propertyDictionary.restoreContext(stream); + propertyTimeFunctDictionary.restoreContext(stream); + + if ( !stream.read(temperOffset) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} } // end namespace oofem diff --git a/src/oofemlib/boundaryload.h b/src/oofemlib/boundaryload.h index 1c60df3a6..17da2518e 100644 --- a/src/oofemlib/boundaryload.h +++ b/src/oofemlib/boundaryload.h @@ -142,20 +142,20 @@ class OOFEM_EXPORT BoundaryLoad : public Load */ BoundaryLoad(int i, Domain * d); - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; /** * @return Approximation order of load geometry. */ - virtual int giveApproxOrder() = 0; + int giveApproxOrder() override = 0; - virtual CoordSystType giveCoordSystMode() { return coordSystemType; } + CoordSystType giveCoordSystMode() override { return coordSystemType; } /** * Initializes receiver according to object description stored in input record. * Reads number of dofs into nDofs attribute (i.e. the number of dofs, which are on loaded entity), * its loadType into loadType attribute and coordinate system type into csType attribute. */ - IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; /** * Returns receiver load type. It distinguish particular boundary conditions according to * their "physical" meaning (like StructuralTemperatureLoadLT, StructuralLoadLT). @@ -163,9 +163,9 @@ class OOFEM_EXPORT BoundaryLoad : public Load * specified on input by user. * See cltypes.h file for details. */ - virtual bcType giveType() const { return lType; } + bcType giveType() const override { return lType; } virtual double giveProperty(int aProperty, TimeStep *tStep, const std :: map< std :: string, FunctionArgument > &valDict); - virtual double giveProperty(int aProperty, TimeStep *tStep); + double giveProperty(int aProperty, TimeStep *tStep) override; /// Return temperature offset virtual double giveTemperOffset(void); /// Expression to multiply all properties @@ -186,7 +186,10 @@ class OOFEM_EXPORT BoundaryLoad : public Load * @param tStep Time step. * @param mode Determines response mode. */ - virtual void computeComponentArrayAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode); + void computeComponentArrayAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -226,9 +229,5 @@ class OOFEM_EXPORT SurfaceLoad: public BoundaryLoad SurfaceLoad(int i, Domain * d) : BoundaryLoad (i, d) {} }; - - - - } // end namespace oofem #endif // boundaryload_h diff --git a/src/oofemlib/calculatorfunction.C b/src/oofemlib/calculatorfunction.C index 13b9fe965..7fee1f100 100644 --- a/src/oofemlib/calculatorfunction.C +++ b/src/oofemlib/calculatorfunction.C @@ -45,16 +45,14 @@ REGISTER_Function(CalculatorFunction); CalculatorFunction :: CalculatorFunction(int n, Domain *d) : Function(n, d) { } -IRResultType -CalculatorFunction :: initializeFrom(InputRecord *ir) +void +CalculatorFunction :: initializeFrom(InputRecord &ir) { - IRResultType result; + Function :: initializeFrom(ir); IR_GIVE_FIELD(ir, fExpression, _IFT_CalculatorFunction_f); IR_GIVE_OPTIONAL_FIELD(ir, dfdtExpression, _IFT_CalculatorFunction_dfdt); IR_GIVE_OPTIONAL_FIELD(ir, d2fdt2Expression, _IFT_CalculatorFunction_d2fdt2); - - return Function :: initializeFrom(ir); } @@ -69,7 +67,7 @@ CalculatorFunction :: giveInputRecord(DynamicInputRecord &input) void -CalculatorFunction :: evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict) +CalculatorFunction :: evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp, double param) { Parser myParser; int err; diff --git a/src/oofemlib/calculatorfunction.h b/src/oofemlib/calculatorfunction.h index 1ec68297d..b23a71f55 100644 --- a/src/oofemlib/calculatorfunction.h +++ b/src/oofemlib/calculatorfunction.h @@ -79,16 +79,16 @@ class OOFEM_EXPORT CalculatorFunction : public Function * - dfdt(t) (optional) * - d2fdt2(t) (optional) */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &ir); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &ir) override; - virtual void evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict); - virtual double evaluateAtTime(double t); - virtual double evaluateVelocityAtTime(double t); - virtual double evaluateAccelerationAtTime(double t); + void evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp=nullptr, double param=0.) override; + double evaluateAtTime(double t) override; + double evaluateVelocityAtTime(double t) override; + double evaluateAccelerationAtTime(double t) override; - virtual const char *giveClassName() const { return "CalculatorFunction"; } - virtual const char *giveInputRecordName() const { return _IFT_CalculatorFunction_Name; } + const char *giveClassName() const override { return "CalculatorFunction"; } + const char *giveInputRecordName() const override { return _IFT_CalculatorFunction_Name; } }; } // end namespace oofem #endif // calculatorfunction_h diff --git a/src/oofemlib/calmls.C b/src/oofemlib/calmls.C index 9c3f1f21c..e5f54d1d5 100644 --- a/src/oofemlib/calmls.C +++ b/src/oofemlib/calmls.C @@ -58,7 +58,7 @@ namespace oofem { REGISTER_SparseNonLinearSystemNM(CylindricalALM) CylindricalALM :: CylindricalALM(Domain *d, EngngModel *m) : - SparseNonLinearSystemNM(d, m), calm_HPCWeights(), calm_HPCIndirectDofMask(), calm_HPCDmanDofSrcArray(), ccDofGroups() + SparseNonLinearSystemNM(d, m), calm_HPCWeights(), calm_HPCIndirectDofMask(), calm_HPCDmanDofSrcArray(), ccDofGroups(), old_dX() { nsmax = 60; // default maximum number of sweeps allowed numberOfRequiredIterations = 3; @@ -101,8 +101,7 @@ CylindricalALM :: CylindricalALM(Domain *d, EngngModel *m) : CylindricalALM :: ~CylindricalALM() -{ -} +{} NM_Status @@ -197,9 +196,9 @@ restart: // This is useful e.g. to trigger localization in a homogeneous material under uniform stress without // the need to introduce material imperfections. The problem itself remains symmetric but the iterative // solution is brought to a nonsymmetric state and it gets a chance to converge to a nonsymmetric solution. - // Parameters of the perturbation technique are specified by the user and by default no perturbation is done. + // Parameters of the perturbation technique are specified by the user and by default no perturbation is done. // Milan Jirasek - SparseNonLinearSystemNM :: applyPerturbation(&deltaXt); + SparseNonLinearSystemNM :: applyPerturbation(& deltaXt); if ( calm_Control == calm_hpc_off ) { XX = parallel_context->localNorm(deltaXt); @@ -218,7 +217,7 @@ restart: // In case of paralllel analysis: FloatArray collected_XXRR; - parallel_context->accumulate({_XX, _RR}, collected_XXRR); + parallel_context->accumulate({ _XX, _RR }, collected_XXRR); _XX = collected_XXRR(0); _RR = collected_XXRR(1); @@ -236,11 +235,18 @@ restart: p = parallel_context->accumulate(p); } - XR = parallel_context->localDotProduct(deltaXt, R); - /* XR is unscaled Bergan's param of current stiffness XR = deltaXt^T k deltaXt - * this is used to test whether k has negative or positive slope */ - Lambda = ReachedLambda; + if(rootselectiontype == RST_Cos) { + /* XR is unscaled Bergan's param of current stiffness XR = deltaXt^T k deltaXt + * this is used to test whether k has negative or positive slope */ + XR = parallel_context->localDotProduct(deltaXt, R); + } else { + if(old_dX.giveSize()) { + XR = parallel_context->localDotProduct(deltaXt, old_dX); + } else { + XR = parallel_context->localDotProduct(deltaXt, R); + } + } DeltaLambda = deltaLambda = sgn(XR) * deltaL / p; Lambda += DeltaLambda; // @@ -470,7 +476,7 @@ restart: status = NM_Success; solved = 1; ReachedLambda = Lambda; - + old_dX = dX; return status; } @@ -518,7 +524,7 @@ CylindricalALM :: checkConvergence(const FloatArray &R, const FloatArray *R0, co } // loop over individual dofs - for ( Dof *_idofptr: *dman ) { + for ( Dof *_idofptr : *dman ) { // loop over dof groups for ( int _dg = 1; _dg <= _ng; _dg++ ) { // test if dof ID is in active set @@ -551,7 +557,7 @@ CylindricalALM :: checkConvergence(const FloatArray &R, const FloatArray *R0, co // loop over element internal Dofs for ( int _idofman = 1; _idofman <= elem->giveNumberOfInternalDofManagers(); _idofman++ ) { // loop over individual dofs - for ( Dof *_idofptr: *elem->giveInternalDofManager(_idofman) ) { + for ( Dof *_idofptr : *elem->giveInternalDofManager(_idofman) ) { // loop over dof groups for ( int _dg = 1; _dg <= _ng; _dg++ ) { // test if dof ID is in active set @@ -607,7 +613,7 @@ CylindricalALM :: checkConvergence(const FloatArray &R, const FloatArray *R0, co } if ( ( fabs( dg_forceErr.at(_dg) ) > rtolf.at(_dg) * CALM_MAX_REL_ERROR_BOUND ) || - ( fabs( dg_dispErr.at(_dg) ) > rtold.at(_dg) * CALM_MAX_REL_ERROR_BOUND ) ) { + ( fabs( dg_dispErr.at(_dg) ) > rtold.at(_dg) * CALM_MAX_REL_ERROR_BOUND ) || std :: isnan( dg_forceErr.at(_dg) ) || std :: isnan( dg_dispErr.at(_dg) ) ) { errorOutOfRange = true; } @@ -655,7 +661,7 @@ CylindricalALM :: checkConvergence(const FloatArray &R, const FloatArray *R0, co } if ( ( fabs(forceErr) > rtolf.at(1) * CALM_MAX_REL_ERROR_BOUND ) || - ( fabs(dispErr) > rtold.at(1) * CALM_MAX_REL_ERROR_BOUND ) ) { + ( fabs(dispErr) > rtold.at(1) * CALM_MAX_REL_ERROR_BOUND ) || ( std :: isnan(forceErr) ) || ( std :: isnan(dispErr) ) ) { errorOutOfRange = true; } @@ -671,10 +677,10 @@ CylindricalALM :: checkConvergence(const FloatArray &R, const FloatArray *R0, co -IRResultType -CylindricalALM :: initializeFrom(InputRecord *ir) +void +CylindricalALM :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + SparseNonLinearSystemNM :: initializeFrom(ir); double oldPsi = Psi; // default from constructor double initialStepLength, forcedInitialStepLength; @@ -725,8 +731,9 @@ CylindricalALM :: initializeFrom(InputRecord *ir) numberOfRequiredIterations = 1000; } - IR_GIVE_OPTIONAL_FIELD(ir, minIterations, _IFT_CylindricalALM_miniterations); - if ( result == IRRT_OK ) { + try { + IR_GIVE_OPTIONAL_FIELD(ir, minIterations, _IFT_CylindricalALM_miniterations); + } catch ( InputException & ) { if ( minIterations > 3 && minIterations < 1000 ) { numberOfRequiredIterations = minIterations; } @@ -834,7 +841,7 @@ CylindricalALM :: initializeFrom(InputRecord *ir) if ( nccdg >= 1 ) { IntArray _val; - char name [ 12 ]; + char name [ 16 ]; // create an empty set __DofIDSet _set; // resize dof group vector @@ -876,10 +883,17 @@ CylindricalALM :: initializeFrom(InputRecord *ir) } this->giveLinearSolver()->initializeFrom(ir); - - SparseNonLinearSystemNM :: initializeFrom(ir); - - return IRRT_OK; + + rootselectiontype = RST_Cos; + if ( ( calm_Control == calm_hpc_off ) || ( calm_Control == calm_hpc_on ) ) { + int rst = 0; + IR_GIVE_OPTIONAL_FIELD(ir, rst, _IFT_CylindricalALM_rootselectiontype); + if(rst == 0) { + rootselectiontype = RST_Cos; + } else if(rst == 1) { + rootselectiontype = RST_Dot; + } + } } @@ -941,27 +955,21 @@ void CylindricalALM :: convertHPCMap() } -contextIOResultType -CylindricalALM :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +CylindricalALM :: saveContext(DataStream &stream, ContextMode mode) { - // write current deltaL if ( !stream.write(deltaL) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -CylindricalALM :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +CylindricalALM :: restoreContext(DataStream &stream, ContextMode mode) { - // read last deltaL if ( !stream.read(deltaL) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } @@ -974,7 +982,7 @@ CylindricalALM :: giveLinearSolver() } } - linSolver.reset( classFactory.createSparseLinSolver(solverType, domain, engngModel) ); + linSolver = classFactory.createSparseLinSolver(solverType, domain, engngModel); if ( !linSolver ) { OOFEM_ERROR("linear solver creation failed for lstype %d", solverType); } @@ -1008,12 +1016,12 @@ CylindricalALM :: computeDeltaLambda(double &deltaLambda, const FloatArray &dX, a1 = eta * eta * XX + Psi * Psi * RR; a2 = RR * Psi * Psi * DeltaLambda0 * 2.0 - + 2.0 * eta * XXt - + 2.0 * eta * eta * X_Xt; + + 2.0 * eta * XXt + + 2.0 * eta * eta * X_Xt; a3 = dXdX - + 2.0 * eta * dXX_ - + eta * eta * X_X_ - + DeltaLambda0 * DeltaLambda0 * RR * Psi * Psi - deltaL * deltaL; + + 2.0 * eta * dXX_ + + eta * eta * X_X_ + + DeltaLambda0 * DeltaLambda0 * RR * Psi * Psi - deltaL * deltaL; } else if ( calm_Control == calm_hpc_on ) { double _rr = 0.; double _RR = 0.; @@ -1031,7 +1039,7 @@ CylindricalALM :: computeDeltaLambda(double &deltaLambda, const FloatArray &dX, } FloatArray col_; - parallel_context->accumulate({_rr, _RR, _a2, _a3}, col_); + parallel_context->accumulate({ _rr, _RR, _a2, _a3 }, col_); a1 = eta * eta * col_(0) + Psi *Psi *col_(1); a2 = col_(1) * Psi * Psi * DeltaLambda0 * 2.0; a2 += 2.0 * col_(2); @@ -1042,7 +1050,10 @@ CylindricalALM :: computeDeltaLambda(double &deltaLambda, const FloatArray &dX, // solution of quadratic eqn. double discr = a2 * a2 - 4.0 * a1 * a3; if ( discr < 0.0 ) { - OOFEM_ERROR("discriminant is negative, solution failed"); + OOFEM_WARNING("discriminant is negative, restarting the step"); + deltaLambda = 0; + return 0; + //OOFEM_ERROR("discriminant is negative, solution failed"); } discr = sqrt(discr); @@ -1071,18 +1082,38 @@ CylindricalALM :: computeDeltaLambda(double &deltaLambda, const FloatArray &dX, // In case of parallel simulations (equiv to no-op on seq sim): FloatArray cola; - parallel_context->accumulate({a4, a5}, cola); + parallel_context->accumulate({ a4, a5 }, cola); a4 = cola(0); a5 = cola(1); } - - double cos1 = ( a4 + a5 * lam1 ) / deltaL / deltaL; - double cos2 = ( a4 + a5 * lam2 ) / deltaL / deltaL; - if ( cos1 > cos2 ) { + if(rootselectiontype == RST_Cos) { + double cos1 = ( a4 + a5 * lam1 ) / deltaL / deltaL; + double cos2 = ( a4 + a5 * lam2 ) / deltaL / deltaL; + if ( cos1 > cos2 ) { deltaLambda = lam1; - } else { + } else { deltaLambda = lam2; - } + } + } else { + double XX = parallel_context->localNorm(deltaXt); + XX *= XX; + double XXt = parallel_context->localDotProduct(dX, deltaXt); + double dXdX = parallel_context->localNorm(dX); + dXdX *= dXdX; + double dXX_ = parallel_context->localDotProduct(dX, deltaX_); + double X_X_ = parallel_context->localNorm(deltaX_); + X_X_ *= X_X_; + + double c1 = (dXdX + dXX_ + lam1 * XXt) + (Psi * Psi * ((DeltaLambda0 + deltaLambda) * (DeltaLambda0 + deltaLambda) + (DeltaLambda0 + deltaLambda) * lam1)) ; + double c2 = (dXdX + dXX_ + lam2 * XXt) + (Psi * Psi * ((DeltaLambda0 + deltaLambda) * (DeltaLambda0 + deltaLambda) + (DeltaLambda0 + deltaLambda) * lam2)); + + if ( c1 > c2 ) { + deltaLambda = lam1; + } else { + deltaLambda = lam2; + } + + } //printf ("eta=%e, lam1=%e, lam2=%e", eta, lam1, lam2); } else if ( calm_Control == calml_hpc ) { @@ -1099,7 +1130,7 @@ CylindricalALM :: computeDeltaLambda(double &deltaLambda, const FloatArray &dX, // In case of parallel simulations (equiv to no-op on seq sim): FloatArray colv; - parallel_context->accumulate({nom, denom}, colv); + parallel_context->accumulate({ nom, denom }, colv); nom = colv(0); denom = colv(1); diff --git a/src/oofemlib/calmls.h b/src/oofemlib/calmls.h index efe6c0193..c77989fee 100644 --- a/src/oofemlib/calmls.h +++ b/src/oofemlib/calmls.h @@ -71,6 +71,7 @@ #define _IFT_CylindricalALM_rtolv "rtolv" #define _IFT_CylindricalALM_rtolf "rtolf" #define _IFT_CylindricalALM_rtold "rtold" +#define _IFT_CylindricalALM_rootselectiontype "rootselectiontype" //@} @@ -209,37 +210,52 @@ class OOFEM_EXPORT CylindricalALM : public SparseNonLinearSystemNM /// Parallel context for computing norms, dot products and such. ParallelContext *parallel_context; + /** Type characterizing how the roots of the quadratic equation + * for the arc-length parameter are selected + * 0 -- cosinus based criterion + * 1 -- dot product based criterion + */ + enum RootSelectionType { + RST_Cos=0, + RST_Dot=1, + }; + + /// Root selection type + RootSelectionType rootselectiontype; + /// previous increment of dX, needed by root selection type 1 + FloatArray old_dX; + public: CylindricalALM(Domain * d, EngngModel * m); virtual ~CylindricalALM(); // Overloaded methods: - virtual NM_Status solve(SparseMtrx &K, FloatArray &R, FloatArray *R0, - FloatArray &X, FloatArray &dX, FloatArray &F, - const FloatArray &internalForcesEBENorm, double &ReachedLambda, referenceLoadInputModeType rlm, - int &nite, TimeStep *); - virtual double giveCurrentStepLength() { return deltaL; } - virtual void setStepLength(double s) { deltaL = s; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual bool referenceLoad() const { return true; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual void setDomain(Domain *d) { + NM_Status solve(SparseMtrx &K, FloatArray &R, FloatArray *R0, + FloatArray &X, FloatArray &dX, FloatArray &F, + const FloatArray &internalForcesEBENorm, double &ReachedLambda, referenceLoadInputModeType rlm, + int &nite, TimeStep *) override; + double giveCurrentStepLength() override { return deltaL; } + void setStepLength(double s) override { deltaL = s; } + void initializeFrom(InputRecord &ir) override; + bool referenceLoad() const override { return true; } + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + void setDomain(Domain *d) override { this->domain = d; if ( linSolver ) { linSolver->setDomain(d); } } - virtual void reinitialize() { + void reinitialize() override { calm_hpc_init = 1; if ( linSolver ) { linSolver->reinitialize(); } } - virtual const char *giveClassName() const { return "CylindricalALM"; } - virtual const char *giveInputRecordName() const { return _IFT_CylindricalALM_Name; } + const char *giveClassName() const override { return "CylindricalALM"; } + const char *giveInputRecordName() const { return _IFT_CylindricalALM_Name; } - virtual SparseLinearSystemNM *giveLinearSolver(); + SparseLinearSystemNM *giveLinearSolver() override; protected: void convertHPCMap(); diff --git a/src/oofemlib/chartype.h b/src/oofemlib/chartype.h index 82c1751d3..2cba36f1a 100644 --- a/src/oofemlib/chartype.h +++ b/src/oofemlib/chartype.h @@ -60,6 +60,7 @@ namespace oofem { ENUM_ITEM_WITH_VALUE(ConductivityMatrix, 9) \ ENUM_ITEM_WITH_VALUE(CapacityMatrix, 10) \ ENUM_ITEM_WITH_VALUE(InitialStressMatrix, 11) \ + ENUM_ITEM_WITH_VALUE(LumpedInitialStressMatrix, 12) \ /* characteristic vectors */ \ ENUM_ITEM_WITH_VALUE(ExternalForcesVector, 150) \ ENUM_ITEM_WITH_VALUE(InternalForcesVector, 151) \ @@ -81,7 +82,23 @@ namespace oofem { ENUM_ITEM_WITH_VALUE(LaplacePressureVector, 211) \ ENUM_ITEM_WITH_VALUE(LaplaceVelocityVector, 212) \ ENUM_ITEM_WITH_VALUE(DivergenceAuxVelocityVector, 213) \ - ENUM_ITEM_WITH_VALUE(DivergenceVelocityVector, 214) + ENUM_ITEM_WITH_VALUE(DivergenceVelocityVector, 214) \ + /* MPM */ \ + ENUM_ITEM_WITH_VALUE(PermeabilityMatrix, 250) \ + ENUM_ITEM_WITH_VALUE(FluidMassBalancePressureContribution, 251) \ + ENUM_ITEM_WITH_VALUE(BiotConstant, 252) \ + ENUM_ITEM_WITH_VALUE(CompressibilityCoefficient, 253) \ + ENUM_ITEM_WITH_VALUE(MomentumBalance_StiffnessMatrix, 254) \ + ENUM_ITEM_WITH_VALUE(MomentumBalance_PressureCouplingMatrix, 255) \ + ENUM_ITEM_WITH_VALUE(MassBalance_PermeabilityMatrix, 256) \ + ENUM_ITEM_WITH_VALUE(MassBalance_CompresibilityMatrix, 257) \ + ENUM_ITEM_WITH_VALUE(MassBalance_StressCouplingMatrix, 258) \ + ENUM_ITEM_WITH_VALUE(MomentumBalance_StressResidual, 259) \ + ENUM_ITEM_WITH_VALUE(MomentumBalance_PressureResidual, 260) \ + ENUM_ITEM_WITH_VALUE(MassBalance_StressRateResidual, 261) \ + ENUM_ITEM_WITH_VALUE(MassBalance_PressureResidual, 262) \ + ENUM_ITEM_WITH_VALUE(MassBalance_PressureRateResidual, 263) + enum CharType { diff --git a/src/oofemlib/classfactory.C b/src/oofemlib/classfactory.C index 4e5994d85..ab1f4fe95 100644 --- a/src/oofemlib/classfactory.C +++ b/src/oofemlib/classfactory.C @@ -35,48 +35,50 @@ #include "classfactory.h" #include +#include #include +// unique_ptrs need the base +#include "engngm.h" #include "masterdof.h" #include "slavedof.h" #include "simpleslavedof.h" #include "activedof.h" +#include "sparsemtrx.h" +#include "sparsegeneigenvalsystemnm.h" +#include "sparsenonlinsystemnm.h" +#include "sparselinsystemnm.h" +#include "mesherinterface.h" +#include "errorestimator.h" +#include "materialmappingalgorithm.h" +#include "function.h" +#include "material.h" +#include "crosssection.h" +#include "nonlocalbarrier.h" +#include "exportmodule.h" +#include "initmodule.h" +#include "loadbalancer.h" + #include "gaussintegrationrule.h" #include "lobattoir.h" #include "initialcondition.h" -#include "subspaceit.h" -#include "inverseit.h" -#ifdef __SLEPC_MODULE - #include "slepcsolver.h" -#endif +// Experimental stuff +#include "xfem/nucleationcriterion.h" +#include "xfem/xfemmanager.h" +#include "xfem/enrichmentfunction.h" +#include "xfem/enrichmentitem.h" +#include "xfem/propagationlaw.h" +#include "xfem/enrichmentfunction.h" +#include "xfem/enrichmentitem.h" +#include "topologydescription.h" +#include "geometry.h" +#include "fracturemanager.h" +#include "contact/contactmanager.h" +#include "contact/contactdefinition.h" -#include "nodalaveragingrecoverymodel.h" -#include "zznodalrecoverymodel.h" -#include "sprnodalrecoverymodel.h" - -// mesher interfaces -#include "t3dinterface.h" -#include "targe2interface.h" -#include "subdivision.h" -#include "freeminterface.h" - -#include "mmaclosestiptransfer.h" -#include "mmaleastsquareprojection.h" -#include "mmashapefunctprojection.h" -#include "mmacontainingelementprojection.h" ///@todo This doesn't seem to be included? It is broken? - -// Helper macro for creating objects -#define CF_CREATE(list, ...) \ - auto creator = list.find(conv2lower(name));\ - return creator != list.end() ? creator->second(__VA_ARGS__) : nullptr; - -// Helper macro for storing objects -#define CF_STORE(list) \ - list[ conv2lower(name) ] = creator;\ - return true; namespace oofem { ClassFactory &GiveClassFactory() @@ -89,12 +91,46 @@ ClassFactory &classFactory = GiveClassFactory(); std :: string conv2lower(std :: string input) { - for ( std :: size_t i = 0; i < input.size(); i++ ) { - input [ i ] = (char)std :: tolower(input [ i ]); - } + std::transform(input.begin(), input.end(), input.begin(), ::tolower); return input; } +// Non-string names (should be changed eventually): +template< typename C, typename T, typename V, typename ... As> C *cf_create2(const T &list, V name, As ... args) +{ + auto creator = list.find(name); + return creator != list.end() ? creator->second(args...) : nullptr; +} + +// Helper for storing creators +template< typename T, typename V, typename C> bool cf_store2(T &list, V name, C &creator) +{ + list[ name ] = creator; + return true; +} + +// Non string names (should be replaced with eventually) +template< typename C, typename T, typename V, typename ... As> std::unique_ptr cf_create4(const T &list, V name, As ... args) +{ + auto creator = list.find(name); + return creator != list.end() ? creator->second(args...) : nullptr; +} + +// Helper for creating objects +template< typename C, typename T, typename ... As> std::unique_ptr cf_create(const T &list, const char *name, As ... args) +{ + auto creator = list.find(conv2lower(name)); + return creator != list.end() ? creator->second(args...) : nullptr; +} + +// Helper for storing creators +template< typename T, typename C> bool cf_store(T &list, const char *name, C &creator) +{ + list[ conv2lower(name) ] = creator; + return true; +} + + ClassFactory :: ClassFactory() { // Fixed list for DOF types. No new components can register for these since these are part of the internal structure in OOFEM. @@ -104,395 +140,378 @@ ClassFactory :: ClassFactory() dofList [ DT_active ] = dofCreator< ActiveDof >; } -SparseMtrx *ClassFactory :: createSparseMtrx(SparseMtrxType name) +std::unique_ptr ClassFactory :: createSparseMtrx(SparseMtrxType name) { - //CF_CREATE(sparseMtrxList) - return ( sparseMtrxList.count(name) == 1 ) ? sparseMtrxList [ name ]() : NULL; + return cf_create4(sparseMtrxList, name); } -bool ClassFactory :: registerSparseMtrx( SparseMtrxType name, SparseMtrx * ( *creator )( ) ) +bool ClassFactory :: registerSparseMtrx( SparseMtrxType name, std::unique_ptr ( *creator )( ) ) { - //CF_STORE(sparseMtrxList); - sparseMtrxList[ name ] = creator; - return true; + return cf_store2(sparseMtrxList, name, creator); } Dof *ClassFactory :: createDof(dofType name, DofIDItem dofid, DofManager *dman) { - //CF_CREATE(dofList, dofid, dman) - return ( dofList.count(name) == 1 ) ? dofList [ name ](dofid, dman) : NULL; + return cf_create2(dofList, name, dofid, dman); } -SparseLinearSystemNM *ClassFactory :: createSparseLinSolver(LinSystSolverType name, Domain *domain, EngngModel *emodel) +std::unique_ptr ClassFactory :: createSparseLinSolver(LinSystSolverType name, Domain *domain, EngngModel *emodel) { - //CF_CREATE(sparseLinSolList, domain, emodel) - return ( sparseLinSolList.count(name) == 1 ) ? sparseLinSolList [ name ](domain, emodel) : NULL; + return cf_create4(sparseLinSolList, name, domain, emodel); } -bool ClassFactory :: registerSparseLinSolver( LinSystSolverType name, SparseLinearSystemNM * ( *creator )( Domain *, EngngModel * ) ) +bool ClassFactory :: registerSparseLinSolver( LinSystSolverType name, std::unique_ptr ( *creator )( Domain *, EngngModel * ) ) { - //CF_STORE(sparseLinSolList) - sparseLinSolList[ name ] = creator; - return true; + return cf_store2(sparseLinSolList, name, creator); } -ErrorEstimator *ClassFactory :: createErrorEstimator(ErrorEstimatorType name, int number, Domain *domain) +std::unique_ptr ClassFactory :: createErrorEstimator(ErrorEstimatorType name, int number, Domain *domain) { - //CF_CREATE(errEstList, number, domain) - return ( errEstList.count(name) == 1 ) ? errEstList [ name ](number, domain) : NULL; + return cf_create4(errEstList, name, number, domain); } -bool ClassFactory :: registerErrorEstimator( ErrorEstimatorType name, ErrorEstimator * ( *creator )( int, Domain * ) ) +bool ClassFactory :: registerErrorEstimator( ErrorEstimatorType name, std::unique_ptr ( *creator )( int, Domain * ) ) { - //CF_STORE(errEstList) - errEstList[ name ] = creator; - return true; + return cf_store2(errEstList, name, creator); } -InitialCondition *ClassFactory :: createInitialCondition(const char *name, int number, Domain *domain) +std::unique_ptr ClassFactory :: createInitialCondition(const char *name, int number, Domain *domain) { if ( conv2lower(name).compare("initialcondition") == 0 ) { - return new InitialCondition(number, domain); + return std::make_unique(number, domain); } - return NULL; + return nullptr; } -NodalRecoveryModel *ClassFactory :: createNodalRecoveryModel(NodalRecoveryModel :: NodalRecoveryModelType type, Domain *domain) +bool ClassFactory :: registerNodalRecoveryModel( NodalRecoveryModel :: NodalRecoveryModelType name, std::unique_ptr ( *creator )(Domain *) ) { - //CF_CREATE(nodalRecoveryModelList, domain) - if ( type == NodalRecoveryModel :: NRM_NodalAveraging ) { - return new NodalAveragingRecoveryModel(domain); - } else if ( type == NodalRecoveryModel :: NRM_ZienkiewiczZhu ) { - return new ZZNodalRecoveryModel(domain); - } else if ( type == NodalRecoveryModel :: NRM_SPR ) { - return new SPRNodalRecoveryModel(domain); - } - return NULL; + return cf_store2(nodalRecoveryModelList, name, creator); +} + +std::unique_ptr ClassFactory :: createNodalRecoveryModel(NodalRecoveryModel :: NodalRecoveryModelType name, Domain *domain) +{ + return cf_create4(nodalRecoveryModelList, name, domain); } -Element *ClassFactory :: createElement(const char *name, int number, Domain *domain) +std::unique_ptr ClassFactory :: createElement(const char *name, int number, Domain *domain) { - CF_CREATE(elemList, number, domain) + return cf_create(elemList, name,number, domain); } -bool ClassFactory :: registerElement( const char *name, Element * ( *creator )( int, Domain * ) ) +bool ClassFactory :: registerElement( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ) { - CF_STORE(elemList) + return cf_store(elemList, name, creator); } -DofManager *ClassFactory :: createDofManager(const char *name, int number, Domain *domain) +std::unique_ptr ClassFactory :: createDofManager(const char *name, int number, Domain *domain) { - CF_CREATE(dofmanList, number, domain) + return cf_create(dofmanList, name, number, domain); } -bool ClassFactory :: registerDofManager( const char *name, DofManager * ( *creator )( int, Domain * ) ) +bool ClassFactory :: registerDofManager( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ) { - CF_STORE(dofmanList) + return cf_store(dofmanList, name, creator); } -GeneralBoundaryCondition *ClassFactory :: createBoundaryCondition(const char *name, int number, Domain *domain) +std::unique_ptr ClassFactory :: createBoundaryCondition(const char *name, int number, Domain *domain) { - CF_CREATE(bcList, number, domain) + return cf_create(bcList, name, number, domain); } -bool ClassFactory :: registerBoundaryCondition( const char *name, GeneralBoundaryCondition * ( *creator )( int, Domain * ) ) +bool ClassFactory :: registerBoundaryCondition( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ) { - CF_STORE(bcList) + return cf_store(bcList, name, creator); } -CrossSection *ClassFactory :: createCrossSection(const char *name, int number, Domain *domain) +std::unique_ptr ClassFactory :: createCrossSection(const char *name, int number, Domain *domain) { - CF_CREATE(csList, number, domain) + return cf_create(csList, name, number, domain); } -bool ClassFactory :: registerCrossSection( const char *name, CrossSection * ( *creator )( int, Domain * ) ) +bool ClassFactory :: registerCrossSection( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ) { - CF_STORE(csList) + return cf_store(csList, name, creator); } -Material *ClassFactory :: createMaterial(const char *name, int number, Domain *domain) +std::unique_ptr ClassFactory :: createMaterial(const char *name, int number, Domain *domain) { - CF_CREATE(matList, number, domain) + return cf_create(matList, name, number, domain); } -bool ClassFactory :: registerMaterial( const char *name, Material * ( *creator )( int, Domain * ) ) +bool ClassFactory :: registerMaterial( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ) { - CF_STORE(matList) + return cf_store(matList, name, creator); } -EngngModel *ClassFactory :: createEngngModel(const char *name, int number, EngngModel *master) +std::unique_ptr ClassFactory :: createEngngModel(const char *name, int number, EngngModel *master) { - CF_CREATE(engngList, number, master) + return cf_create(engngList, name, number, master); } -bool ClassFactory :: registerEngngModel( const char *name, EngngModel * ( *creator )( int, EngngModel * ) ) +bool ClassFactory :: registerEngngModel( const char *name, std::unique_ptr ( *creator )( int, EngngModel * ) ) { - CF_STORE(engngList) + return cf_store(engngList, name, creator); } -Function *ClassFactory :: createFunction(const char *name, int number, Domain *domain) +std::unique_ptr ClassFactory :: createFunction(const char *name, int number, Domain *domain) { - CF_CREATE(funcList, number, domain) + return cf_create(funcList, name, number, domain); } -bool ClassFactory :: registerFunction( const char *name, Function * ( *creator )( int, Domain * ) ) +bool ClassFactory :: registerFunction( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ) { - CF_STORE(funcList) + return cf_store(funcList, name, creator); } -NonlocalBarrier *ClassFactory :: createNonlocalBarrier(const char *name, int number, Domain *domain) +std::unique_ptr ClassFactory :: createNonlocalBarrier(const char *name, int number, Domain *domain) { - CF_CREATE(nlbList, number, domain) + return cf_create(nlbList, name, number, domain); } -bool ClassFactory :: registerNonlocalBarrier( const char *name, NonlocalBarrier * ( *creator )( int, Domain * ) ) +bool ClassFactory :: registerNonlocalBarrier( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ) { - CF_STORE(nlbList) + return cf_store(nlbList, name, creator); } -ExportModule *ClassFactory :: createExportModule(const char *name, int number, EngngModel *emodel) +std::unique_ptr ClassFactory :: createExportModule(const char *name, int number, EngngModel *emodel) { - CF_CREATE(exportList, number, emodel) + return cf_create(exportList, name, number, emodel); } -bool ClassFactory :: registerExportModule( const char *name, ExportModule * ( *creator )( int, EngngModel * ) ) +bool ClassFactory :: registerExportModule( const char *name, std::unique_ptr ( *creator )( int, EngngModel * ) ) { - CF_STORE(exportList) + return cf_store(exportList, name, creator); } -SparseNonLinearSystemNM *ClassFactory :: createNonLinearSolver(const char *name, Domain *domain, EngngModel *emodel) +std::unique_ptr ClassFactory :: createMonitor(const char *name, int number) { - CF_CREATE(nonlinList, domain, emodel) + return cf_create(monitorList, name, number); } -bool ClassFactory :: registerSparseNonLinearSystemNM( const char *name, SparseNonLinearSystemNM * ( *creator )( Domain *, EngngModel * ) ) +bool ClassFactory :: registerMonitor( const char *name, std::unique_ptr ( *creator )( int ) ) { - CF_STORE(nonlinList) + return cf_store(monitorList, name, creator); } -InitModule *ClassFactory :: createInitModule(const char *name, int number, EngngModel *emodel) +std::unique_ptrClassFactory :: createNonLinearSolver(const char *name, Domain *domain, EngngModel *emodel) { - CF_CREATE(initList, number, emodel) + return cf_create(nonlinList, name, domain, emodel); } -bool ClassFactory :: registerInitModule( const char *name, InitModule * ( *creator )( int, EngngModel * ) ) +bool ClassFactory :: registerSparseNonLinearSystemNM(const char *name, std::unique_ptr ( *creator )( Domain *, EngngModel * ) ) { - CF_STORE(initList) + return cf_store(nonlinList, name, creator); } -TopologyDescription *ClassFactory :: createTopology(const char *name, Domain *domain) +std::unique_ptr ClassFactory :: createInitModule(const char *name, int number, EngngModel *emodel) { - CF_CREATE(topologyList, domain) + return cf_create(initList, name, number, emodel); } -bool ClassFactory :: registerTopologyDescription( const char *name, TopologyDescription * ( *creator )( Domain * ) ) +bool ClassFactory :: registerInitModule(const char *name, std::unique_ptr ( *creator )( int, EngngModel * ) ) { - CF_STORE(topologyList) + return cf_store(initList, name, creator); +} + +std::unique_ptr ClassFactory :: createTopology(const char *name, Domain *domain) +{ + return cf_create(topologyList, name, domain); +} + +bool ClassFactory :: registerTopologyDescription(const char *name, std::unique_ptr ( *creator )( Domain * ) ) +{ + return cf_store(topologyList, name, creator); } // XFEM: -EnrichmentItem *ClassFactory :: createEnrichmentItem(const char *name, int number, XfemManager *xm, Domain *domain) +std::unique_ptr ClassFactory :: createEnrichmentItem(const char *name, int number, XfemManager *xm, Domain *domain) { - CF_CREATE(enrichItemList, number, xm, domain) + return cf_create(enrichItemList, name, number, xm, domain); } -bool ClassFactory :: registerEnrichmentItem( const char *name, EnrichmentItem * ( *creator )( int, XfemManager *, Domain * ) ) +bool ClassFactory :: registerEnrichmentItem(const char *name, std::unique_ptr ( *creator )( int, XfemManager *, Domain * ) ) { - CF_STORE(enrichItemList) + return cf_store(enrichItemList, name, creator); } -NucleationCriterion *ClassFactory :: createNucleationCriterion(const char *name, Domain *domain) +std::unique_ptr ClassFactory :: createNucleationCriterion(const char *name, Domain *domain) { - CF_CREATE(nucleationCritList, domain) + return cf_create(nucleationCritList, name, domain); } -bool ClassFactory :: registerNucleationCriterion( const char *name, NucleationCriterion * ( *creator )( Domain * ) ) +bool ClassFactory :: registerNucleationCriterion(const char *name, std::unique_ptr ( *creator )( Domain * ) ) { - CF_STORE(nucleationCritList) + return cf_store(nucleationCritList, name, creator); } -EnrichmentFunction *ClassFactory :: createEnrichmentFunction(const char *name, int number, Domain *domain) +std::unique_ptr ClassFactory :: createEnrichmentFunction(const char *name, int number, Domain *domain) { - CF_CREATE(enrichFuncList, number, domain) + return cf_create(enrichFuncList, name, number, domain); } -bool ClassFactory :: registerEnrichmentFunction( const char *name, EnrichmentFunction * ( *creator )( int, Domain * ) ) +bool ClassFactory :: registerEnrichmentFunction(const char *name, std::unique_ptr ( *creator )( int, Domain * ) ) { - CF_STORE(enrichFuncList) + return cf_store(enrichFuncList, name, creator); } -EnrichmentDomain *ClassFactory :: createEnrichmentDomain(const char *name) +#if 0 +std::unique_ptr ClassFactory :: createEnrichmentDomain(const char *name) { - CF_CREATE(enrichmentDomainList) + return cf_create(enrichmentDomainList, name); } -bool ClassFactory :: registerEnrichmentDomain( const char *name, EnrichmentDomain * ( *creator )( ) ) +bool ClassFactory :: registerEnrichmentDomain(const char *name, std::unique_ptr ( *creator )( ) ) { - CF_STORE(enrichmentDomainList) + return cf_store(enrichmentDomainList, name, creator); } +#endif -EnrichmentFront *ClassFactory :: createEnrichmentFront(const char *name) +std::unique_ptr ClassFactory :: createEnrichmentFront(const char *name) { - CF_CREATE(enrichmentFrontList) + return cf_create(enrichmentFrontList, name); } -bool ClassFactory :: registerEnrichmentFront( const char *name, EnrichmentFront * ( *creator )( ) ) +bool ClassFactory :: registerEnrichmentFront(const char *name, std::unique_ptr ( *creator )( ) ) { - CF_STORE(enrichmentFrontList) + return cf_store(enrichmentFrontList, name, creator); } -PropagationLaw *ClassFactory :: createPropagationLaw(const char *name) +std::unique_ptr ClassFactory :: createPropagationLaw(const char *name) { - CF_CREATE(propagationLawList) + return cf_create(propagationLawList, name); } -bool ClassFactory :: registerPropagationLaw( const char *name, PropagationLaw * ( *creator )( ) ) +bool ClassFactory :: registerPropagationLaw( const char *name, std::unique_ptr ( *creator )( ) ) { - CF_STORE(propagationLawList) + return cf_store(propagationLawList, name, creator); } -BasicGeometry *ClassFactory :: createGeometry(const char *name) +std::unique_ptr ClassFactory :: createGeometry(const char *name) { - CF_CREATE(geometryList) + return cf_create(geometryList, name); } -bool ClassFactory :: registerGeometry( const char *name, BasicGeometry * ( *creator )( ) ) +bool ClassFactory :: registerGeometry(const char *name, std::unique_ptr ( *creator )( ) ) { - CF_STORE(geometryList) + return cf_store(geometryList, name, creator); } -XfemManager *ClassFactory :: createXfemManager(const char *name, Domain *domain) +std::unique_ptr ClassFactory :: createXfemManager(const char *name, Domain *domain) { - CF_CREATE(xManList, domain) + return cf_create(xManList, name, domain); } -bool ClassFactory :: registerXfemManager( const char *name, XfemManager * ( *creator )( Domain * ) ) +bool ClassFactory :: registerXfemManager(const char *name, std::unique_ptr ( *creator )( Domain * ) ) { - CF_STORE(xManList) + return cf_store(xManList, name, creator); } // Failure module: -FailureCriteria *ClassFactory :: createFailureCriteria(const char *name, int number, FractureManager *fracManager) +std::unique_ptr ClassFactory :: createFailureCriteria(const char *name, int number, FractureManager *fracManager) { - CF_CREATE(failureCriteriaList, number, fracManager) + return cf_create(failureCriteriaList, name, number, fracManager); } -bool ClassFactory :: registerFailureCriteria( const char *name, FailureCriteria * ( *creator )( int, FractureManager * ) ) +bool ClassFactory :: registerFailureCriteria( const char *name, std::unique_ptr ( *creator )( int, FractureManager * ) ) { - CF_STORE(failureCriteriaList) + return cf_store(failureCriteriaList, name, creator); } -FailureCriteriaStatus *ClassFactory :: createFailureCriteriaStatus(const char *name, int number, FailureCriteria *fc) +std::unique_ptr ClassFactory :: createFailureCriteriaStatus(const char *name, int number, FailureCriteria *fc) { - CF_CREATE(failureCriteriaStatusList, number, fc) + return cf_create(failureCriteriaStatusList, name, number, fc); } -bool ClassFactory :: registerFailureCriteriaStatus( const char *name, FailureCriteriaStatus * ( *creator )( int, FailureCriteria * ) ) +bool ClassFactory :: registerFailureCriteriaStatus(const char *name, std::unique_ptr ( *creator )( int, FailureCriteria * ) ) { - CF_STORE(failureCriteriaStatusList) + return cf_store(failureCriteriaStatusList, name, creator); } -ContactManager *ClassFactory :: createContactManager(const char *name, Domain *domain) +std::unique_ptr ClassFactory :: createContactManager(const char *name, Domain *domain) { - CF_CREATE(contactManList, domain) + return cf_create(contactManList, name, domain); } -bool ClassFactory :: registerContactManager( const char *name, ContactManager * ( *creator )( Domain * ) ) +bool ClassFactory :: registerContactManager(const char *name, std::unique_ptr ( *creator )( Domain * ) ) { - CF_STORE(contactManList) + return cf_store(contactManList, name, creator); } -ContactDefinition *ClassFactory :: createContactDefinition(const char *name, ContactManager *cMan) +std::unique_ptr ClassFactory :: createContactDefinition(const char *name, ContactManager *cMan) { - CF_CREATE(contactDefList, cMan) + return cf_create(contactDefList, name, cMan); } -bool ClassFactory :: registerContactDefinition( const char *name, ContactDefinition * ( *creator )( ContactManager * ) ) +bool ClassFactory :: registerContactDefinition( const char *name, std::unique_ptr ( *creator )( ContactManager * ) ) { - CF_STORE(contactDefList) + return cf_store(contactDefList, name, creator); } +std::unique_ptr ClassFactory :: createGeneralizedEigenValueSolver(GenEigvalSolverType name, Domain *domain, EngngModel *emodel) +{ + return cf_create4(generalizedEigenValueSolverList, name, domain, emodel); +} - -SparseGeneralEigenValueSystemNM *ClassFactory :: createGeneralizedEigenValueSolver(GenEigvalSolverType st, Domain *domain, EngngModel *emodel) +bool ClassFactory :: registerGeneralizedEigenValueSolver( GenEigvalSolverType name, std::unique_ptr ( *creator )(Domain *, EngngModel *) ) { - //CF_CREATE(mesherInterfaceList, domain) - if ( st == GES_SubspaceIt ) { - return new SubspaceIteration(domain, emodel); - } else if ( st == GES_InverseIt ) { - return new InverseIteration(domain, emodel); - } -#ifdef __SLEPC_MODULE - else if ( st == GES_SLEPc ) { - return new SLEPcSolver(domain, emodel); - } -#endif - return NULL; + return cf_store2(generalizedEigenValueSolverList, name, creator); } -IntegrationRule *ClassFactory :: createIRule(IntegrationRuleType type, int number, Element *e) +std::unique_ptr ClassFactory :: createIRule(IntegrationRuleType type, int number, Element *e) { if ( type == IRT_Gauss ) { - return new GaussIntegrationRule(number, e); + return std::make_unique(number, e); } else if ( type == IRT_Lobatto ) { - return new LobattoIntegrationRule(number, e); + return std::make_unique(number, e); } - return NULL; + return nullptr; } -MaterialMappingAlgorithm *ClassFactory :: createMaterialMappingAlgorithm(MaterialMappingAlgorithmType type) +bool ClassFactory :: registerMaterialMappingAlgorithm( MaterialMappingAlgorithmType name, std::unique_ptr ( *creator )( ) ) { - //CF_CREATE(materialMappingList) - if ( type == MMA_ClosestPoint ) { - return new MMAClosestIPTransfer(); - } else if ( type == MMA_LeastSquareProjection ) { - return new MMALeastSquareProjection(); - } else if ( type == MMA_ShapeFunctionProjection ) { - return new MMAShapeFunctProjection(); - } - return NULL; + return cf_store2(materialMappingList, name, creator); } -MesherInterface *ClassFactory :: createMesherInterface(MeshPackageType type, Domain *domain) +std::unique_ptr ClassFactory :: createMaterialMappingAlgorithm(MaterialMappingAlgorithmType name) { - //CF_CREATE(mesherInterfaceList, domain) - if ( type == MPT_T3D ) { - return new T3DInterface(domain); - } else if ( type == MPT_TARGE2 ) { - return new Targe2Interface(domain); - } else if ( type == MPT_FREEM ) { - return new FreemInterface(domain); - } else if ( type == MPT_SUBDIVISION ) { - return new Subdivision(domain); - } - return NULL; + return cf_create4(materialMappingList, name); +} + +bool ClassFactory :: registerMesherInterface( MeshPackageType name, std::unique_ptr ( *creator )( Domain * ) ) +{ + return cf_store2(mesherInterfaceList, name, creator); +} + +std::unique_ptr ClassFactory :: createMesherInterface(MeshPackageType name, Domain *domain) +{ + return cf_create4(mesherInterfaceList, name, domain); } -LoadBalancerMonitor *ClassFactory :: createLoadBalancerMonitor(const char *name, EngngModel *emodel) +std::unique_ptr ClassFactory :: createLoadBalancerMonitor(const char *name, EngngModel *emodel) { - CF_CREATE(loadMonitorList, emodel) + return cf_create(loadMonitorList, name, emodel); } -bool ClassFactory :: registerLoadBalancerMonitor( const char *name, LoadBalancerMonitor * ( *creator )( EngngModel * ) ) +bool ClassFactory :: registerLoadBalancerMonitor(const char *name, std::unique_ptr ( *creator )( EngngModel * ) ) { - CF_STORE(loadMonitorList) + return cf_store(loadMonitorList, name, creator); } -LoadBalancer *ClassFactory :: createLoadBalancer(const char *name, Domain *domain) +std::unique_ptr ClassFactory :: createLoadBalancer(const char *name, Domain *domain) { - CF_CREATE(loadBalancerList, domain) + return cf_create(loadBalancerList, name, domain); } -bool ClassFactory :: registerLoadBalancer( const char *name, LoadBalancer * ( *creator )( Domain * ) ) +bool ClassFactory :: registerLoadBalancer(const char *name, std::unique_ptr ( *creator )( Domain * ) ) { - CF_STORE(loadBalancerList) + return cf_store(loadBalancerList, name, creator); } } // End namespace oofem diff --git a/src/oofemlib/classfactory.h b/src/oofemlib/classfactory.h index bbbb5315b..684b994b9 100644 --- a/src/oofemlib/classfactory.h +++ b/src/oofemlib/classfactory.h @@ -51,6 +51,7 @@ #include #include #include +#include namespace oofem { class Domain; @@ -66,6 +67,7 @@ class ExportModule; class SparseNonLinearSystemNM; class InitModule; class TopologyDescription; +class Monitor; class Dof; class SparseMtrx; @@ -98,82 +100,71 @@ class FailureCriteria; class ContactManager; class ContactDefinition; -// Templates to wrap constructors into functions -template< typename T > Element *elemCreator(int n, Domain *d) { return new T(n, d); } -template< typename T > DofManager *dofmanCreator(int n, Domain *d) { return new T(n, d); } -template< typename T > GeneralBoundaryCondition *bcCreator(int n, Domain *d) { return new T(n, d); } -template< typename T > CrossSection *csCreator(int n, Domain *d) { return new T(n, d); } -template< typename T > Material *matCreator(int n, Domain *d) { return new T(n, d); } -template< typename T > EngngModel *engngCreator(int n, EngngModel *m) { return ( new T(n, m) ); } -template< typename T > Function *funcCreator(int n, Domain *d) { return new T(n, d); } -template< typename T > NonlocalBarrier *nlbCreator(int n, Domain *d) { return new T(n, d); } -template< typename T > ExportModule *exportCreator(int n, EngngModel *e) { return ( new T(n, e) ); } -template< typename T > SparseNonLinearSystemNM *nonlinCreator(Domain *d, EngngModel *m) { return ( new T(d, m) ); } -template< typename T > InitModule *initCreator(int n, EngngModel *e) { return ( new T(n, e) ); } -template< typename T > TopologyDescription *topologyCreator(Domain *d) { return new T(d); } - -template< typename T > Dof *dofCreator(DofIDItem dofid, DofManager *dman) { return new T(dman, dofid); } -template< typename T > SparseMtrx *sparseMtrxCreator() { return new T(); } -template< typename T > SparseLinearSystemNM *sparseLinSolCreator(Domain *d, EngngModel *m) { return new T(d, m); } -template< typename T > ErrorEstimator *errEstCreator(int n, Domain *d) { return new T(n, d); } +#ifdef _GNUC +#define OOFEM_ATTR_UNUSED __attribute__((unused)) +#else +#define OOFEM_ATTR_UNUSED +#endif -template< typename T > LoadBalancer *loadBalancerCreator(Domain *d) { return new T(d); } -template< typename T > LoadBalancerMonitor *loadMonitorCreator(EngngModel *e) { return new T(e); } - -// XFEM stuff -template< typename T > XfemManager *xManCreator(Domain *d) { return new T(d); } -template< typename T > EnrichmentItem *enrichItemCreator(int n, XfemManager *x, Domain *d) { return new T(n, x, d); } -template< typename T > NucleationCriterion *nucleationCritCreator(Domain *d) { return new T(d); } -template< typename T > EnrichmentFunction *enrichFuncCreator(int n, Domain *d) { return new T(n, d); } -template< typename T > EnrichmentDomain *enrichmentDomainCreator() { return new T(); } -template< typename T > BasicGeometry *geometryCreator() { return new T(); } -template< typename T > EnrichmentFront *enrichFrontCreator() { return new T(); } -template< typename T > PropagationLaw *propagationLawCreator() { return new T(); } +// Templates to wrap constructors into functions +// Wraps any ctor into -template< typename T > FailureCriteria *failureCriteriaCreator(int n, FractureManager *x) { return new T(n, x); } -template< typename T > FailureCriteriaStatus *failureCriteriaCreator(int n, FailureCriteria *x) { return new T(n, x); } +/** + * Wrapper for ctors, creates a function that returns a unique_ptr to the object. + * The base class (B) template argument must be specified explicitly, becuase we can't "downcast" the function pointer. + * E.g. + * CTOR + * CTOR + */ +template< typename B, typename T, typename... V > std::unique_ptr CTOR(V... x) { return std::make_unique(x...); } -template< typename T > ContactManager *contactManCreator(Domain *d) { return new T(d); } -template< typename T > ContactDefinition *contactDefCreator(ContactManager *cMan) { return new T(cMan); } +template< typename T > Dof *dofCreator(DofIDItem dofid, DofManager *dman) { return new T(dman, dofid); } ///@name Macros for registering new components. Unique dummy variables must be created as a result (design flaw in C++). //@{ -#define REGISTER_Element(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerElement(_IFT_ ## class ## _Name, elemCreator< class > ); -#define REGISTER_DofManager(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerDofManager(_IFT_ ## class ## _Name, dofmanCreator< class > ); -#define REGISTER_BoundaryCondition(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerBoundaryCondition(_IFT_ ## class ## _Name, bcCreator< class > ); -#define REGISTER_CrossSection(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerCrossSection(_IFT_ ## class ## _Name, csCreator< class > ); -#define REGISTER_Material(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerMaterial(_IFT_ ## class ## _Name, matCreator< class > ); -#define REGISTER_EngngModel(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerEngngModel(_IFT_ ## class ## _Name, engngCreator< class > ); -#define REGISTER_Function(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerFunction(_IFT_ ## class ## _Name, funcCreator< class > ); -#define REGISTER_NonlocalBarrier(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerNonlocalBarrier(_IFT_ ## class ## _Name, nlbCreator< class > ); -#define REGISTER_ExportModule(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerExportModule(_IFT_ ## class ## _Name, exportCreator< class > ); -#define REGISTER_SparseNonLinearSystemNM(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerSparseNonLinearSystemNM(_IFT_ ## class ## _Name, nonlinCreator< class > ); -#define REGISTER_InitModule(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerInitModule(_IFT_ ## class ## _Name, initCreator< class > ); -#define REGISTER_TopologyDescription(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerTopologyDescription(_IFT_ ## class ## _Name, topologyCreator< class > ); -#define REGISTER_LoadBalancerMonitor(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerLoadBalancerMonitor(_IFT_ ## class ## _Name, loadMonitorCreator< class > ); -#define REGISTER_LoadBalancer(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerLoadBalancer(_IFT_ ## class ## _Name, loadBalancerCreator< class > ); +#define REGISTER_Element(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerElement(_IFT_ ## class ## _Name, CTOR< Element, class, int, Domain* > ); +#define REGISTER_DofManager(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerDofManager(_IFT_ ## class ## _Name, CTOR< DofManager, class, int, Domain* > ); +#define REGISTER_BoundaryCondition(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerBoundaryCondition(_IFT_ ## class ## _Name, CTOR< GeneralBoundaryCondition, class, int, Domain* > ); +#define REGISTER_CrossSection(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerCrossSection(_IFT_ ## class ## _Name, CTOR< CrossSection, class, int, Domain* > ); +#define REGISTER_Material(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerMaterial(_IFT_ ## class ## _Name, CTOR< Material, class, int, Domain* > ); +#define REGISTER_Material_Alt(class, altname) static bool __dummy_ ## class ## altname OOFEM_ATTR_UNUSED = GiveClassFactory().registerMaterial(#altname, CTOR< Material, class, int, Domain* > ); +#define REGISTER_EngngModel(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerEngngModel(_IFT_ ## class ## _Name, CTOR< EngngModel, class, int, EngngModel* > ); +#define REGISTER_Function(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerFunction(_IFT_ ## class ## _Name, CTOR< Function, class, int, Domain* > ); +#define REGISTER_NonlocalBarrier(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerNonlocalBarrier(_IFT_ ## class ## _Name, CTOR< NonlocalBarrier, class, int, Domain* > ); +#define REGISTER_ExportModule(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerExportModule(_IFT_ ## class ## _Name, CTOR< ExportModule, class, int, EngngModel* > ); +#define REGISTER_SparseNonLinearSystemNM(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerSparseNonLinearSystemNM(_IFT_ ## class ## _Name, CTOR< SparseNonLinearSystemNM, class, Domain*, EngngModel* > ); +#define REGISTER_InitModule(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerInitModule(_IFT_ ## class ## _Name, CTOR< InitModule, class, int, EngngModel* > ); +#define REGISTER_TopologyDescription(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerTopologyDescription(_IFT_ ## class ## _Name, CTOR< TopologyDescription, class, Domain* > ); +#define REGISTER_LoadBalancerMonitor(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerLoadBalancerMonitor(_IFT_ ## class ## _Name, CTOR< LoadBalancerMonitor, class, EngngModel* > ); +#define REGISTER_LoadBalancer(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerLoadBalancer(_IFT_ ## class ## _Name, CTOR< LoadBalancer, class, EngngModel* > ); +#define REGISTER_Monitor(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerMonitor(_IFT_ ## class ## _Name, CTOR< Monitor, class, int > ); // These should be converted to use strings. -#define REGISTER_SparseMtrx(class, type) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerSparseMtrx(type, sparseMtrxCreator< class > ); -#define REGISTER_SparseLinSolver(class, type) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerSparseLinSolver(type, sparseLinSolCreator< class > ); -#define REGISTER_ErrorEstimator(class, type) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerErrorEstimator(type, errEstCreator< class > ); - -#define REGISTER_XfemManager(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerXfemManager(_IFT_ ## class ## _Name, xManCreator< class > ); -#define REGISTER_EnrichmentItem(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerEnrichmentItem(_IFT_ ## class ## _Name, enrichItemCreator< class > ); -#define REGISTER_NucleationCriterion(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerNucleationCriterion(_IFT_ ## class ## _Name, nucleationCritCreator< class > ); -#define REGISTER_EnrichmentFunction(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerEnrichmentFunction(_IFT_ ## class ## _Name, enrichFuncCreator< class > ); -#define REGISTER_EnrichmentDomain(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerEnrichmentDomain(_IFT_ ## class ## _Name, enrichmentDomainCreator< class > ); -#define REGISTER_Geometry(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerGeometry(_IFT_ ## class ## _Name, geometryCreator< class > ); -#define REGISTER_EnrichmentFront(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerEnrichmentFront(_IFT_ ## class ## _Name, enrichFrontCreator< class > ); -#define REGISTER_PropagationLaw(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerPropagationLaw(_IFT_ ## class ## _Name, propagationLawCreator< class > ); - -#define REGISTER_FailureCriteria(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerFailureCriteria(_IFT_ ## class ## _Name, failureCriteriaCreator< class > ); -#define REGISTER_FailureCriteriaStatus(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerFailureCriteriaStatus(_IFT_ ## class ## _Name, failureCriteriaCreator< class > ); - -#define REGISTER_ContactManager(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerContactManager(_IFT_ ## class ## _Name, contactManCreator< class > ); -#define REGISTER_ContactDefinition(class) static bool __dummy_ ## class __attribute__((unused)) = GiveClassFactory().registerContactDefinition(_IFT_ ## class ## _Name, contactDefCreator< class > ); -#define REGISTER_Quasicontinuum(class) static bool __dummy_ ## class = GiveClassFactory().registerQuasicontinuum(_IFT_ ## class ## _Name, QuasicontinuumCreator< class > ); +#define REGISTER_SparseMtrx(class, type) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerSparseMtrx(type, CTOR< SparseMtrx, class > ); +#define REGISTER_SparseLinSolver(class, type) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerSparseLinSolver(type, CTOR< SparseLinearSystemNM, class, Domain*, EngngModel* > ); +#define REGISTER_ErrorEstimator(class, type) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerErrorEstimator(type, CTOR< ErrorEstimator, class, int, Domain* > ); +#define REGISTER_NodalRecoveryModel(class, type) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerNodalRecoveryModel(type, CTOR< NodalRecoveryModel, class, Domain* > ); +#define REGISTER_GeneralizedEigenValueSolver(class, type) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerGeneralizedEigenValueSolver(type, CTOR< SparseGeneralEigenValueSystemNM, class, Domain*, EngngModel* > ); +#define REGISTER_Mesher(class, type) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerMesherInterface(type, CTOR< MesherInterface, class, Domain* > ); +#define REGISTER_MaterialMappingAlgorithm(class, type) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerMaterialMappingAlgorithm(type, CTOR< MaterialMappingAlgorithm, class > ); + +#define REGISTER_XfemManager(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerXfemManager(_IFT_ ## class ## _Name, CTOR< XfemManager, class, Domain* > ); +#define REGISTER_EnrichmentItem(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerEnrichmentItem(_IFT_ ## class ## _Name, CTOR< EnrichmentItem, class, int, XfemManager*, Domain* > ); +#define REGISTER_NucleationCriterion(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerNucleationCriterion(_IFT_ ## class ## _Name, CTOR< NucleationCriterion, class, Domain* > ); +#define REGISTER_EnrichmentFunction(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerEnrichmentFunction(_IFT_ ## class ## _Name, CTOR< EnrichmentFunction, class, int, Domain* > ); +//#define REGISTER_EnrichmentDomain(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerEnrichmentDomain(_IFT_ ## class ## _Name, CTOR< EnrichmentDomain, class > ); +#define REGISTER_EnrichmentFront(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerEnrichmentFront(_IFT_ ## class ## _Name, CTOR< EnrichmentFront, class > ); +#define REGISTER_PropagationLaw(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerPropagationLaw(_IFT_ ## class ## _Name, CTOR< PropagationLaw, class > ); +#define REGISTER_Geometry(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerGeometry(_IFT_ ## class ## _Name, CTOR< BasicGeometry, class > ); + +#define REGISTER_FailureCriteria(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerFailureCriteria(_IFT_ ## class ## _Name, CTOR< FailureCriteria, class, int, FractureManager* > ); +#define REGISTER_FailureCriteriaStatus(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerFailureCriteriaStatus(_IFT_ ## class ## _Name, CTOR< FailureCriteriaStatus, class, FailureCriteria* > ); + +#define REGISTER_ContactManager(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerContactManager(_IFT_ ## class ## _Name, CTOR< ContactManager, class, Domain* > ); +#define REGISTER_ContactDefinition(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerContactDefinition(_IFT_ ## class ## _Name, CTOR< ContactDefinition, class, ContactManager* > ); +///@todo What is this? Doesn't seem needed / Mikael +#define REGISTER_Quasicontinuum(class) static bool __dummy_ ## class OOFEM_ATTR_UNUSED = GiveClassFactory().registerQuasicontinuum(_IFT_ ## class ## _Name, < QuasiContinuum, class, ????? > ); //@} /** @@ -188,70 +179,80 @@ class OOFEM_EXPORT ClassFactory { private: /// Associative container containing element creators with element name as key. - std :: map < std :: string, Element * ( * )(int, Domain *) > elemList; + std :: map < std :: string, std::unique_ptr ( * )(int, Domain *) > elemList; /// Associative container containing dofmanager creators with dofmanager name as key. - std :: map < std :: string, DofManager * ( * )(int, Domain *) > dofmanList; + std :: map < std :: string, std::unique_ptr ( * )(int, Domain *) > dofmanList; /// Associative container containing boundary condition creators with bc name as key. - std :: map < std :: string, GeneralBoundaryCondition * ( * )(int, Domain *) > bcList; + std :: map < std :: string, std::unique_ptr ( * )(int, Domain *) > bcList; /// Associative container containing cross section creators with cross section name as key. - std :: map < std :: string, CrossSection * ( * )(int, Domain *) > csList; + std :: map < std :: string, std::unique_ptr ( * )(int, Domain *) > csList; /// Associative container containing material creators with material name as key. - std :: map < std :: string, Material * ( * )(int, Domain *) > matList; + std :: map < std :: string, std::unique_ptr ( * )(int, Domain *) > matList; /// Associative container containing engng model creators with engng model name as key. - std :: map < std :: string, EngngModel * ( * )(int, EngngModel *) > engngList; + std :: map < std :: string, std::unique_ptr ( * )(int, EngngModel *) > engngList; /// Associative container containing load time function creators with function name as key. - std :: map < std :: string, Function * ( * )(int, Domain *) > funcList; + std :: map < std :: string, std::unique_ptr ( * )(int, Domain *) > funcList; /// Associative container containing nonlocal barriers creators with barrier name as key. - std :: map < std :: string, NonlocalBarrier * ( * )(int, Domain *) > nlbList; + std :: map < std :: string, std::unique_ptr ( * )(int, Domain *) > nlbList; /// Associative container containing export module creators. - std :: map < std :: string, ExportModule * ( * )(int, EngngModel *) > exportList; + std :: map < std :: string, std::unique_ptr ( * )(int, EngngModel *) > exportList; + /// Associative container containing monitor creators. + std :: map < std :: string, std::unique_ptr ( * )(int) > monitorList; /// Associative container containing nonlinear solver creators. - std :: map < std :: string, SparseNonLinearSystemNM * ( * )(Domain *, EngngModel *) > nonlinList; + std :: map < std :: string, std::unique_ptr ( * )(Domain *, EngngModel *) > nonlinList; /// Associative container containing init module creators. - std :: map < std :: string, InitModule * ( * )(int, EngngModel *) > initList; + std :: map < std :: string, std::unique_ptr ( * )(int, EngngModel *) > initList; /// Associative container containing topology description creators. - std :: map < std :: string, TopologyDescription * ( * )(Domain *) > topologyList; + std :: map < std :: string, std::unique_ptr ( * )(Domain *) > topologyList; // Internal structures (accessed by hard-coded enum values) /// Associative container containing load balancer creators. - std :: map < std :: string, LoadBalancer * ( * )(Domain *) > loadBalancerList; + std :: map < std :: string, std::unique_ptr ( * )(Domain *) > loadBalancerList; /// Associative container containing load balancer monitor creators. - std :: map < std :: string, LoadBalancerMonitor * ( * )(EngngModel *) > loadMonitorList; + std :: map < std :: string, std::unique_ptr ( * )(EngngModel *) > loadMonitorList; /// Associative container containing sparse matrix creators. - std :: map < SparseMtrxType, SparseMtrx * ( * )() > sparseMtrxList; + std :: map < SparseMtrxType, std::unique_ptr ( * )() > sparseMtrxList; /// Associative container containing dof creators. std :: map < dofType, Dof * ( * )(DofIDItem, DofManager *) > dofList; /// Associative container containing error estimator creators. - std :: map < ErrorEstimatorType, ErrorEstimator * ( * )(int, Domain *) > errEstList; + std :: map < ErrorEstimatorType, std::unique_ptr ( * )(int, Domain *) > errEstList; /// Associative container containing sparse linear solver creators - std :: map < LinSystSolverType, SparseLinearSystemNM * ( * )(Domain *, EngngModel *) > sparseLinSolList; + std :: map < LinSystSolverType, std::unique_ptr ( * )(Domain *, EngngModel *) > sparseLinSolList; + /// Associative container containing nodal recovery model creators + std :: map < NodalRecoveryModel :: NodalRecoveryModelType, std::unique_ptr ( * )(Domain *) > nodalRecoveryModelList; + /// Associative container containing sparse generalized eigenvalue creators + std :: map < GenEigvalSolverType, std::unique_ptr ( * )(Domain *, EngngModel *) > generalizedEigenValueSolverList; + /// Associative container containing material mapping algorithm creators + std :: map < MaterialMappingAlgorithmType, std::unique_ptr ( * )() > materialMappingList; + /// Associative container containing mesher interface creators + std :: map < MeshPackageType, std::unique_ptr ( * )(Domain *) > mesherInterfaceList; // XFEM: /// Associative container containing enrichment item creators - std :: map < std :: string, EnrichmentItem * ( * )(int, XfemManager *, Domain *) > enrichItemList; + std :: map < std :: string, std::unique_ptr ( * )(int, XfemManager *, Domain *) > enrichItemList; /// Associative container containing nucleation criterion creators - std :: map < std :: string, NucleationCriterion * ( * )(Domain *) > nucleationCritList; + std :: map < std :: string, std::unique_ptr ( * )(Domain *) > nucleationCritList; /// Associative container containing enrichment function creators - std :: map < std :: string, EnrichmentFunction * ( * )(int, Domain *) > enrichFuncList; + std :: map < std :: string, std::unique_ptr ( * )(int, Domain *) > enrichFuncList; /// Associative container containing geometry creators - std :: map < std :: string, BasicGeometry * ( * )() > geometryList; + std :: map < std :: string, std::unique_ptr ( * )() > geometryList; /// Associative container containing enrichment-domain creators - std :: map < std :: string, EnrichmentDomain * ( * )() > enrichmentDomainList; + std :: map < std :: string, std::unique_ptr ( * )() > enrichmentDomainList; /// Associative container containing enrichment front creators - std :: map < std :: string, EnrichmentFront * ( * )() > enrichmentFrontList; + std :: map < std :: string, std::unique_ptr ( * )() > enrichmentFrontList; /// Associative container containing propagation law creators - std :: map < std :: string, PropagationLaw * ( * )() > propagationLawList; + std :: map < std :: string, std::unique_ptr ( * )() > propagationLawList; /// Associative container containing XfemManager creators - std :: map < std :: string, XfemManager * ( * )(Domain *) > xManList; + std :: map < std :: string, std::unique_ptr ( * )(Domain *) > xManList; /// Associative container containing failure criteria creators - std :: map < std :: string, FailureCriteria * ( * )(int, FractureManager *) > failureCriteriaList; - std :: map < std :: string, FailureCriteriaStatus * ( * )(int, FailureCriteria *) > failureCriteriaStatusList; + std :: map < std :: string, std::unique_ptr ( * )(int, FractureManager *) > failureCriteriaList; + std :: map < std :: string, std::unique_ptr ( * )(int, FailureCriteria *) > failureCriteriaStatusList; /// Associative container containing ContactManager creators - std :: map < std :: string, ContactManager * ( * )(Domain *) > contactManList; - std :: map < std :: string, ContactDefinition * ( * )(ContactManager *) > contactDefList; - + std :: map < std :: string, std::unique_ptr ( * )(Domain *) > contactManList; + std :: map < std :: string, std::unique_ptr ( * )(ContactManager *) > contactDefList; + public: /// Creates empty factory ClassFactory(); @@ -263,12 +264,12 @@ class OOFEM_EXPORT ClassFactory * @param domain Domain assigned to new element. * @return Newly allocated object of requested type, null if keyword not supported. */ - Element *createElement(const char *name, int num, Domain *domain); + std::unique_ptr createElement(const char *name, int num, Domain *domain); /** * Registers a new element in the class factory. * @param name Keyword string. */ - bool registerElement( const char *name, Element * ( *creator )( int, Domain * ) ); + bool registerElement( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ); /** * Creates new instance of Dof manager corresponding to given keyword. * @param name Keyword string determining the type of new instance. @@ -276,12 +277,12 @@ class OOFEM_EXPORT ClassFactory * @param domain Domain assigned to new instance. * @return Newly allocated object of requested type, null if keyword not supported. */ - DofManager *createDofManager(const char *name, int num, Domain *domain); + std::unique_ptr createDofManager(const char *name, int num, Domain *domain); /** * Registers a new dof manager in the class factory. * @param name Keyword string. */ - bool registerDofManager( const char *name, DofManager * ( *creator )( int, Domain * ) ); + bool registerDofManager( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ); /** * Creates new instance of boundary condition corresponding to given keyword. * @param name Keyword string determining the type of new instance. @@ -289,12 +290,12 @@ class OOFEM_EXPORT ClassFactory * @param domain Domain assigned to new object. * @return Newly allocated object of requested type, null if keyword not supported. */ - GeneralBoundaryCondition *createBoundaryCondition(const char *name, int num, Domain *domain); + std::unique_ptr createBoundaryCondition(const char *name, int num, Domain *domain); /** * Registers a new boundary condition in the class factory. * @param name Keyword string. */ - bool registerBoundaryCondition( const char *name, GeneralBoundaryCondition * ( *creator )( int, Domain * ) ); + bool registerBoundaryCondition( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ); /** * Creates new instance of cross section corresponding to given keyword. * @param name Keyword string determining the type of new instance. @@ -302,12 +303,12 @@ class OOFEM_EXPORT ClassFactory * @param domain Domain assigned to new object. * @return Newly allocated object of requested type, null if keyword not supported. */ - CrossSection *createCrossSection(const char *name, int num, Domain *domain); + std::unique_ptr createCrossSection(const char *name, int num, Domain *domain); /** * Registers a new cross section in the class factory. * @param name Keyword string. */ - bool registerCrossSection( const char *name, CrossSection * ( *creator )( int, Domain * ) ); + bool registerCrossSection( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ); /** * Creates new instance of material corresponding to given keyword. * @param name Keyword string determining the type of new instance. @@ -315,12 +316,12 @@ class OOFEM_EXPORT ClassFactory * @param domain Domain assigned to new material. * @return Newly allocated object of requested type, null if keyword not supported. */ - Material *createMaterial(const char *name, int num, Domain *domain); + std::unique_ptr createMaterial(const char *name, int num, Domain *domain); /** * Registers a new material in the class factory. * @param name Keyword string. */ - bool registerMaterial( const char *name, Material * ( *creator )( int, Domain * ) ); + bool registerMaterial( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ); /** * Creates new instance of engng model corresponding to given keyword. * @param name Keyword string determining the type of new instance. @@ -328,12 +329,12 @@ class OOFEM_EXPORT ClassFactory * @param master Master engineering model (used for multiscale modeling). * @return Newly allocated object of requested type, null if keyword not supported. */ - EngngModel *createEngngModel(const char *name, int num, EngngModel *master); + std::unique_ptr createEngngModel(const char *name, int num, EngngModel *master); /** * Registers a new engineering model in the class factory. * @param name Keyword string. */ - bool registerEngngModel( const char *name, EngngModel * ( *creator )( int, EngngModel * ) ); + bool registerEngngModel( const char *name, std::unique_ptr ( *creator )( int, EngngModel * ) ); /** * Creates new instance of load time function corresponding to given keyword. * @param name Keyword string determining the type of new instance. @@ -341,12 +342,12 @@ class OOFEM_EXPORT ClassFactory * @param domain Domain assigned to new object. * @return Newly allocated object of requested type, null if keyword not supported. */ - Function *createFunction(const char *name, int num, Domain *domain); + std::unique_ptr createFunction(const char *name, int num, Domain *domain); /** * Registers a new load time function in the class factory. * @param name Keyword string. */ - bool registerFunction( const char *name, Function * ( *creator )( int, Domain * ) ); + bool registerFunction( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ); /** * Creates new instance of nonlocal barrier corresponding to given keyword. * @param name Keyword string determining the type of new instance. @@ -354,12 +355,12 @@ class OOFEM_EXPORT ClassFactory * @param domain Domain assigned to new object. * @return Newly allocated object of requested type, null if keyword not supported. */ - NonlocalBarrier *createNonlocalBarrier(const char *name, int num, Domain *domain); + std::unique_ptr createNonlocalBarrier(const char *name, int num, Domain *domain); /** * Registers a new nonlocal barrier in the class factory. * @param name Keyword string. */ - bool registerNonlocalBarrier( const char *name, NonlocalBarrier * ( *creator )( int, Domain * ) ); + bool registerNonlocalBarrier( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ); /** * Creates new instance of export module corresponding to given keyword. * @param name Keyword string determining the type of new instance. @@ -367,12 +368,25 @@ class OOFEM_EXPORT ClassFactory * @param emodel Engineering model that object belongs to. * @return Newly allocated object of requested type, null if keyword not supported. */ - ExportModule *createExportModule(const char *name, int num, EngngModel *emodel); + std::unique_ptr createExportModule(const char *name, int num, EngngModel *emodel); /** * Registers a new export module in the class factory. * @param name Keyword string. */ - bool registerExportModule( const char *name, ExportModule * ( *creator )( int, EngngModel * ) ); + bool registerExportModule( const char *name, std::unique_ptr ( *creator )( int, EngngModel * ) ); + /** + * Creates new instance of monitor corresponding to given keyword. + * @param name Keyword string determining the type of new instance. + * @param num Monitor number. + * @return Newly allocated object of requested type, null if keyword not supported. + */ + std::unique_ptr createMonitor(const char *name, int num); + /** + * Registers a new monitor in the class factory. + * @param name Keyword string. + */ + bool registerMonitor( const char *name, std::unique_ptr ( *creator )( int ) ); + /** * Creates new instance of nonlinear solver corresponding to given keyword. * @param name Keyword string determining the type of new instance. @@ -380,12 +394,12 @@ class OOFEM_EXPORT ClassFactory * @param emodel Engineering model that object belongs to. * @return Newly allocated object of requested type, null if keyword not supported. */ - SparseNonLinearSystemNM *createNonLinearSolver(const char *name, Domain *domain, EngngModel *emodel); + std::unique_ptr createNonLinearSolver(const char *name, Domain *domain, EngngModel *emodel); /** * Registers a new nonlinear solver in the class factory. * @param name Keyword string. */ - bool registerSparseNonLinearSystemNM( const char *name, SparseNonLinearSystemNM * ( *creator )( Domain *, EngngModel * ) ); + bool registerSparseNonLinearSystemNM( const char *name, std::unique_ptr ( *creator )( Domain *, EngngModel * ) ); /** * Creates new instance of init module corresponding to given keyword. * @param name Keyword string determining the type of new instance. @@ -393,12 +407,12 @@ class OOFEM_EXPORT ClassFactory * @param emodel Engineering model that object belongs to. * @return Newly allocated object of requested type, null if keyword not supported. */ - InitModule *createInitModule(const char *name, int num, EngngModel *emodel); + std::unique_ptr createInitModule(const char *name, int num, EngngModel *emodel); /** * Registers a new init module in the class factory. * @param name Keyword string. */ - bool registerInitModule( const char *name, InitModule * ( *creator )( int, EngngModel * ) ); + bool registerInitModule( const char *name, std::unique_ptr ( *creator )( int, EngngModel * ) ); /** * Creates new instance of Initial Condition corresponding to given type. * @param name Keyword string determining the type of new instance. @@ -406,31 +420,31 @@ class OOFEM_EXPORT ClassFactory * @param d Domain assigned to new object. * @return Newly allocated object of requested type, null if keyword not supported. */ - InitialCondition *createInitialCondition(const char *name, int num, Domain *d); + std::unique_ptr createInitialCondition(const char *name, int num, Domain *d); /** * Creates new instance of topology description corresponding to given keyword. * @param name Keyword string determining the type of new instance. * @param domain Domain assigned to new object. * @return Newly allocated object of requested type, null if keyword not supported. */ - TopologyDescription *createTopology(const char *name, Domain *domain); + std::unique_ptr createTopology(const char *name, Domain *domain); /** * Registers a new topology description in the class factory. * @param name Keyword string. */ - bool registerTopologyDescription( const char *name, TopologyDescription * ( *creator )( Domain * ) ); + bool registerTopologyDescription( const char *name, std::unique_ptr ( *creator )( Domain * ) ); /** * Creates new instance of sparse matrix corresponding to given keyword. * @param type SparseMtrxType id determining the type of new instance. * @return Newly allocated object of requested type, null if keyword not supported. */ - SparseMtrx *createSparseMtrx(SparseMtrxType type); + std::unique_ptr createSparseMtrx(SparseMtrxType type); /** * Registers a sparse matrix type. * @param type SparseMtrxType id determining the type of new instance. */ - bool registerSparseMtrx( SparseMtrxType type, SparseMtrx * ( *creator )() ); + bool registerSparseMtrx( SparseMtrxType type, std::unique_ptr ( *creator )(void) ); /** * Creates new instance of DOF corresponding to given keyword. * @param type ID determining the type of new instance. @@ -447,12 +461,12 @@ class OOFEM_EXPORT ClassFactory * @param m EngngModel assigned to new object. * @return Newly allocated object of requested type, null if keyword not supported. */ - SparseLinearSystemNM *createSparseLinSolver(LinSystSolverType st, Domain *d, EngngModel *m); + std::unique_ptr createSparseLinSolver(LinSystSolverType st, Domain *d, EngngModel *m); /** * Registers a sparse linear system solver. * @param type LinSystSolverType id determining the type of new instance. */ - bool registerSparseLinSolver( LinSystSolverType type, SparseLinearSystemNM * ( *creator )(Domain *, EngngModel *) ); + bool registerSparseLinSolver( LinSystSolverType type, std::unique_ptr ( *creator )(Domain *, EngngModel *) ); /** * Creates new instance of ErrorEstimator corresponding * to given type. @@ -461,78 +475,90 @@ class OOFEM_EXPORT ClassFactory * @param d Domain assigned to new object. * @return Newly allocated object of requested type, null if keyword not supported. */ - ErrorEstimator *createErrorEstimator(ErrorEstimatorType type, int num, Domain *d); + std::unique_ptr createErrorEstimator(ErrorEstimatorType type, int num, Domain *d); /** * Registers a new error estimator. * @param type ErrorEstimatorType id determining the type of new instance. */ - bool registerErrorEstimator( ErrorEstimatorType type, ErrorEstimator * ( *creator )(int, Domain *) ); + bool registerErrorEstimator( ErrorEstimatorType type, std::unique_ptr ( *creator )(int, Domain *) ); + /** + * Registers a new nodal recovery model. + * @param name Indentifier. + */ + bool registerNodalRecoveryModel( NodalRecoveryModel :: NodalRecoveryModelType name, std::unique_ptr ( *creator )(Domain *) ); /** * Creates new instance of nodal recovery model corresponding to given type. * @param type ID determining the type of new instance. * @param d Domain assigned to new object. * @return Newly allocated object of requested type, null if keyword not supported. */ - NodalRecoveryModel *createNodalRecoveryModel(NodalRecoveryModel :: NodalRecoveryModelType type, Domain *d); + std::unique_ptr createNodalRecoveryModel(NodalRecoveryModel :: NodalRecoveryModelType type, Domain *d); // XFEM: - EnrichmentItem *createEnrichmentItem(const char *name, int num, XfemManager *xm, Domain *domain); - bool registerEnrichmentItem( const char *name, EnrichmentItem * ( *creator )( int, XfemManager *, Domain * ) ); + std::unique_ptr createEnrichmentItem(const char *name, int num, XfemManager *xm, Domain *domain); + bool registerEnrichmentItem( const char *name, std::unique_ptr ( *creator )( int, XfemManager *, Domain * ) ); - NucleationCriterion *createNucleationCriterion(const char *name, Domain *domain); - bool registerNucleationCriterion( const char *name, NucleationCriterion * ( *creator )( Domain * ) ); + std::unique_ptr createNucleationCriterion(const char *name, Domain *domain); + bool registerNucleationCriterion( const char *name, std::unique_ptr ( *creator )( Domain * ) ); - EnrichmentFunction *createEnrichmentFunction(const char *name, int num, Domain *domain); - bool registerEnrichmentFunction( const char *name, EnrichmentFunction * ( *creator )( int, Domain * ) ); + std::unique_ptr createEnrichmentFunction(const char *name, int num, Domain *domain); + bool registerEnrichmentFunction( const char *name, std::unique_ptr ( *creator )( int, Domain * ) ); - EnrichmentDomain *createEnrichmentDomain(const char *name); - bool registerEnrichmentDomain( const char *name, EnrichmentDomain * ( *creator )( ) ); +#if 0 + std::unique_ptr createEnrichmentDomain(const char *name); + bool registerEnrichmentDomain( const char *name, std::unique_ptr ( *creator )( ) ); +#endif - EnrichmentFront *createEnrichmentFront(const char *name); - bool registerEnrichmentFront( const char *name, EnrichmentFront * ( *creator )( ) ); + std::unique_ptr createEnrichmentFront(const char *name); + bool registerEnrichmentFront( const char *name, std::unique_ptr ( *creator )( ) ); - PropagationLaw *createPropagationLaw(const char *name); - bool registerPropagationLaw( const char *name, PropagationLaw * ( *creator )( ) ); + std::unique_ptr createPropagationLaw(const char *name); + bool registerPropagationLaw( const char *name, std::unique_ptr ( *creator )( ) ); - BasicGeometry *createGeometry(const char *name); - bool registerGeometry( const char *name, BasicGeometry * ( *creator )( ) ); + std::unique_ptr createGeometry(const char *name); + bool registerGeometry( const char *name, std::unique_ptr ( *creator )( ) ); - XfemManager *createXfemManager(const char *name, Domain *domain); - bool registerXfemManager( const char *name, XfemManager * ( *creator )( Domain * ) ); + std::unique_ptr createXfemManager(const char *name, Domain *domain); + bool registerXfemManager( const char *name, std::unique_ptr ( *creator )( Domain * ) ); - ContactManager *createContactManager(const char *name, Domain *domain); - bool registerContactManager( const char *name, ContactManager * ( *creator )( Domain * ) ); + std::unique_ptr createContactManager(const char *name, Domain *domain); + bool registerContactManager( const char *name, std::unique_ptr ( *creator )( Domain * ) ); - ContactDefinition *createContactDefinition(const char *name, ContactManager *cMan); - bool registerContactDefinition( const char *name, ContactDefinition * ( *creator )( ContactManager * ) ); - + std::unique_ptr createContactDefinition(const char *name, ContactManager *cMan); + bool registerContactDefinition( const char *name, std::unique_ptr ( *creator )( ContactManager * ) ); // Failure module (in development!) - FailureCriteria *createFailureCriteria(const char *name, int num, FractureManager *fracManager); - bool registerFailureCriteria( const char *name, FailureCriteria * ( *creator )( int, FractureManager * ) ); + std::unique_ptr createFailureCriteria(const char *name, int num, FractureManager *fracManager); + bool registerFailureCriteria( const char *name, std::unique_ptr ( *creator )( int, FractureManager * ) ); + + std::unique_ptr createFailureCriteriaStatus(const char *name, int num, FailureCriteria *critManager); + bool registerFailureCriteriaStatus( const char *name, std::unique_ptr ( *creator )( int, FailureCriteria * ) ); + + std::unique_ptr createGeneralizedEigenValueSolver(GenEigvalSolverType name, Domain *d, EngngModel *m); + bool registerGeneralizedEigenValueSolver( GenEigvalSolverType name, std::unique_ptr ( *creator )(Domain *, EngngModel *) ); + + std::unique_ptr createIRule(IntegrationRuleType name, int number, Element *e); - FailureCriteriaStatus *createFailureCriteriaStatus(const char *name, int num, FailureCriteria *critManager); - bool registerFailureCriteriaStatus( const char *name, FailureCriteriaStatus * ( *creator )( int, FailureCriteria * ) ); + std::unique_ptr createMaterialMappingAlgorithm(MaterialMappingAlgorithmType name); + bool registerMaterialMappingAlgorithm( MaterialMappingAlgorithmType name, std::unique_ptr ( *creator )( ) ); + std::unique_ptr createMesherInterface(MeshPackageType name, Domain *d); + bool registerMesherInterface( MeshPackageType name, std::unique_ptr ( *creator )( Domain * ) ); - SparseGeneralEigenValueSystemNM *createGeneralizedEigenValueSolver(GenEigvalSolverType st, Domain *d, EngngModel *m); - IntegrationRule *createIRule(IntegrationRuleType type, int number, Element *e); - MaterialMappingAlgorithm *createMaterialMappingAlgorithm(MaterialMappingAlgorithmType type); - MesherInterface *createMesherInterface(MeshPackageType type, Domain *d); + std::unique_ptr createLoadBalancerMonitor(const char *name, EngngModel *e); + bool registerLoadBalancerMonitor( const char *name, std::unique_ptr ( *creator )( EngngModel * ) ); - LoadBalancerMonitor *createLoadBalancerMonitor(const char *name, EngngModel *e); - bool registerLoadBalancerMonitor( const char *name, LoadBalancerMonitor * ( *creator )( EngngModel * ) ); - LoadBalancer *createLoadBalancer(const char *name, Domain *d); - bool registerLoadBalancer( const char *name, LoadBalancer * ( *creator )( Domain * ) ); + std::unique_ptr createLoadBalancer(const char *name, Domain *d); + bool registerLoadBalancer( const char *name, std::unique_ptr ( *creator )( Domain * ) ); }; -extern ClassFactory &classFactory; +extern OOFEM_EXPORT ClassFactory &classFactory; /** * This function must be used by all code that run at link time to ensure that the classFactory is constructed first. * See "static initialization order fiasco" for explanation. */ -ClassFactory &GiveClassFactory(); +OOFEM_EXPORT ClassFactory &GiveClassFactory(); } // end namespace oofem #endif // clasfactort_h diff --git a/src/oofemlib/cltypes.C b/src/oofemlib/cltypes.C index 6f8ed2e86..bb400f473 100644 --- a/src/oofemlib/cltypes.C +++ b/src/oofemlib/cltypes.C @@ -64,7 +64,7 @@ char cltypesGiveUnknownTypeModeKey(ValueModeType mode) case VM_Velocity: return 'v'; case VM_Acceleration: return 'a'; - + case VM_TotalIntrinsic: return 'i'; default: OOFEM_ERROR("unsupported ValueModeType"); @@ -82,12 +82,15 @@ InternalStateValueType giveInternalStateValueType(InternalStateType type) case IST_DeviatoricStrain: case IST_PlasticStrainTensor: case IST_ThermalStrainTensor: + case IST_ElasticStrainTensor: case IST_CylindricalStrainTensor: case IST_CreepStrainTensor: case IST_ShellStrainTensor: case IST_CurvatureTensor: case IST_CurvatureTensorTemp: case IST_EigenStrainTensor: + case IST_CrackStrainTensor: + return ISVT_TENSOR_S3E; case IST_StressTensor: @@ -118,7 +121,12 @@ InternalStateValueType giveInternalStateValueType(InternalStateType type) case IST_DeformationGradientTensor: case IST_FirstPKStressTensor: + case IST_MacroSlipGradient: + case IST_ReinfMembraneStress: //case IST_MaterialOrientation: + case IST_LatticeStrain: + case IST_LatticeStress: + case IST_PlasticLatticeStrain: return ISVT_TENSOR_G; case IST_BeamForceMomentTensor: @@ -142,9 +150,10 @@ InternalStateValueType giveInternalStateValueType(InternalStateType type) case IST_HumidityFlow: case IST_CrackDirs: case IST_CrackStatuses: + case IST_CrackStatusesTemp: case IST_CrackVector: case IST_2ndCrackVector: - case IST_3rdCrackVector: + case IST_3rdCrackVector: case IST_InterfaceFirstPKTraction: case IST_InterfaceTraction: case IST_InterfaceJump: @@ -152,6 +161,8 @@ InternalStateValueType giveInternalStateValueType(InternalStateType type) case IST_PrincStressVector1: case IST_PrincStressVector2: case IST_PrincStressVector3: + case IST_MacroSlipVector: + case IST_TransferStress: return ISVT_VECTOR; case IST_MaxEquivalentStrainLevel: @@ -199,12 +210,17 @@ InternalStateValueType giveInternalStateValueType(InternalStateType type) case IST_CrossSectionNumber: case IST_CrackWidth: case IST_2ndCrackWidth: - case IST_3rdCrackWidth: + case IST_3rdCrackWidth: case IST_TensileStrength: case IST_ResidualTensileStrength: case IST_CrackIndex: case IST_FiberStressNL: - case IST_FiberStressLocal: + case IST_FiberStressLocal: + case IST_CrackSlip: + case IST_EquivalentTime: + case IST_MoistureContent: + case IST_IncrementCreepModulus: + case IST_InternalSource: return ISVT_SCALAR; default: @@ -235,44 +251,44 @@ int giveInternalStateTypeSize(InternalStateValueType valType) InternalStateValueType giveInternalStateValueType(UnknownType type) { - if ( type == DisplacementVector || type == EigenVector || type == VelocityVector || type == DirectorField ) { + if ( type == DisplacementVector || type == EigenVector || type == VelocityVector || type == DirectorField || type == MacroSlipVector || type == ResidualForce ) { return ISVT_VECTOR; } else if ( type == FluxVector || type == PressureVector || type == Temperature || type == Humidity || type == DeplanationFunction ) { return ISVT_SCALAR; } else { - OOFEM_ERROR( "unsupported UnknownType %s", __UnknownTypeToString(type) ); + OOFEM_ERROR("unsupported UnknownType %s", __UnknownTypeToString(type) ); return ISVT_SCALAR; // To make compiler happy. } } -ContextIOERR :: ContextIOERR(contextIOResultType e, const char *file, int line) +ContextIOERR::ContextIOERR(contextIOResultType e, const char *file, int line) : + error(e), + msg(nullptr), + file(file), + line(line) { - error = e; - this->file = file; - this->line = line; - this->msg = NULL; + this->full_message = "ContextIOERR " + std::to_string(error) + " at line " + std::to_string(line) + " in file \"" + file + "\""; } -ContextIOERR :: ContextIOERR(contextIOResultType e, const char *msg, const char *file, int line) +ContextIOERR::ContextIOERR(contextIOResultType e, const char *msg, const char *file, int line) : + error(e), + msg(msg), + file(file), + line(line) { - error = e; - this->file = file; - this->line = line; - this->msg = msg; + this->full_message = "ContextIOERR " + std::to_string(error) + " at line " + std::to_string(line) + " in file \"" + file + "\":" + this->msg; } -ContextIOERR :: ~ContextIOERR() { } - void -ContextIOERR :: print() +ContextIOERR::print() { if ( msg ) { - oofem_logger.writeELogMsg(Logger :: LOG_LEVEL_ERROR, NULL, file, line, + oofem_logger.writeELogMsg(Logger::LOG_LEVEL_ERROR, NULL, file, line, "ContextIOERR encountered, error code: %d\n%s", error, msg); } else { - oofem_logger.writeELogMsg(Logger :: LOG_LEVEL_ERROR, NULL, file, line, + oofem_logger.writeELogMsg(Logger::LOG_LEVEL_ERROR, NULL, file, line, "ContextIOERR encountered, error code: %d", error); } OOFEM_EXIT(1); @@ -326,9 +342,9 @@ const char *__MatResponseModeToString(MatResponseMode _value) { TO_STRING_BODY(MatResponseMode_DEF) } -std :: string __DofIDItemToString(DofIDItem _value) { +std::string __DofIDItemToString(DofIDItem _value) { if ( _value >= MaxDofID ) { - char tmp [ 1024 ]; + char tmp[ 1024 ]; sprintf(tmp, "X_%d", _value - MaxDofID + 1); return tmp; } diff --git a/src/oofemlib/combuff.h b/src/oofemlib/combuff.h index e4fd7fd6c..70e6406de 100644 --- a/src/oofemlib/combuff.h +++ b/src/oofemlib/combuff.h @@ -210,13 +210,9 @@ class OOFEM_EXPORT CommunicationBuffer: public DataStream protected: MPI_Comm communicator; public: - CommunicationBuffer(MPI_Comm comm, int size, bool dynamic = 0) { - communicator = comm; - } + CommunicationBuffer(MPI_Comm comm, int size, bool dynamic = 0) : communicator(comm) { } /// Constructor. Creates empty buffer, using given communicator for packing - CommunicationBuffer(MPI_Comm comm, bool dynamic = 0) { - communicator = comm; - } + CommunicationBuffer(MPI_Comm comm, bool dynamic = 0) : communicator(comm) { } /// Destructor. virtual ~CommunicationBuffer() { } @@ -240,16 +236,16 @@ class OOFEM_EXPORT CommunicationBuffer: public DataStream virtual void initForUnpacking() = 0; using DataStream::read; - virtual int read(bool &data); + int read(bool &data) override; using DataStream::write; - virtual int write(bool data); - - virtual int givePackSizeOfInt(int count); - virtual int givePackSizeOfDouble(int count); - virtual int givePackSizeOfChar(int count); - virtual int givePackSizeOfBool(int count); - virtual int givePackSizeOfLong(int count); + int write(bool data) override; + + int givePackSizeOfInt(int count) override; + int givePackSizeOfDouble(int count) override; + int givePackSizeOfChar(int count) override; + int givePackSizeOfBool(int count) override; + int givePackSizeOfLong(int count) override; /**@name Services for buffer sending/receiving */ //@{ @@ -298,9 +294,6 @@ class OOFEM_EXPORT CommunicationBuffer: public DataStream }; - - - class OOFEM_EXPORT StaticCommunicationBuffer : public CommunicationBuffer, public MPIBuffer { public: @@ -311,47 +304,47 @@ class OOFEM_EXPORT StaticCommunicationBuffer : public CommunicationBuffer, publi /// Destructor. virtual ~StaticCommunicationBuffer() { } - virtual int resize(int newSize) { return MPIBuffer :: resize(newSize); } + int resize(int newSize) override { return MPIBuffer :: resize(newSize); } - virtual void init() { return MPIBuffer :: init(); } - virtual void initForPacking() { this->init(); } - virtual void initForUnpacking() { this->init(); } + void init() override { return MPIBuffer :: init(); } + void initForPacking() override { this->init(); } + void initForUnpacking() override { this->init(); } using CommunicationBuffer::write; - virtual int write(const int *src, int n) + int write(const int *src, int n) override { return MPIBuffer :: packArray(this->communicator, src, n, MPI_INT); } - virtual int write(const long *src, int n) + int write(const long *src, int n) override { return MPIBuffer :: packArray(this->communicator, src, n, MPI_LONG); } - virtual int write(const unsigned long *src, int n) + int write(const unsigned long *src, int n) override { return MPIBuffer :: packArray(this->communicator, src, n, MPI_UNSIGNED_LONG); } - virtual int write(const double *src, int n) + int write(const double *src, int n) override { return MPIBuffer :: packArray(this->communicator, src, n, MPI_DOUBLE); } - virtual int write(const char *src, int n) + int write(const char *src, int n) override { return MPIBuffer :: packArray(this->communicator, src, n, MPI_CHAR); } using CommunicationBuffer::read; - virtual int read(int *dest, int n) + int read(int *dest, int n) override { return MPIBuffer :: unpackArray(this->communicator, dest, n, MPI_INT); } - virtual int read(long *dest, int n) + int read(long *dest, int n) override { return MPIBuffer :: unpackArray(this->communicator, dest, n, MPI_LONG); } - virtual int read(unsigned long *dest, int n) + int read(unsigned long *dest, int n) override { return MPIBuffer :: unpackArray(this->communicator, dest, n, MPI_UNSIGNED_LONG); } - virtual int read(double *dest, int n) + int read(double *dest, int n) override { return MPIBuffer :: unpackArray(this->communicator, dest, n, MPI_DOUBLE); } - virtual int read(char *dest, int n) + int read(char *dest, int n) override { return MPIBuffer :: unpackArray(this->communicator, dest, n, MPI_CHAR); } - virtual int iSend(int dest, int tag) { return MPIBuffer :: iSend(this->communicator, dest, tag); } + int iSend(int dest, int tag) override { return MPIBuffer :: iSend(this->communicator, dest, tag); } - virtual int iRecv(int source, int tag, int count = 0) { return MPIBuffer :: iRecv(this->communicator, source, tag, count); } + int iRecv(int source, int tag, int count = 0) override { return MPIBuffer :: iRecv(this->communicator, source, tag, count); } - virtual int testCompletion() { return MPIBuffer :: testCompletion(); } + int testCompletion() override { return MPIBuffer :: testCompletion(); } int testCompletion(int &source, int &tag) { return MPIBuffer :: testCompletion(source, tag); } - virtual int waitCompletion() { return MPIBuffer :: waitCompletion(); } + int waitCompletion() override { return MPIBuffer :: waitCompletion(); } - virtual int bcast(int root) { return MPIBuffer :: bcast(this->communicator, root); } + int bcast(int root) override { return MPIBuffer :: bcast(this->communicator, root); } }; } // end namespace oofem diff --git a/src/oofemlib/communicator.C b/src/oofemlib/communicator.C index 3ad0713f6..8783c3a65 100644 --- a/src/oofemlib/communicator.C +++ b/src/oofemlib/communicator.C @@ -44,68 +44,31 @@ namespace oofem { CommunicatorBuff :: CommunicatorBuff(int s, CommBuffType t) { - this->size = s; - - if ( size ) { - processCommBuffs = new ProcessCommunicatorBuff * [ size ]; - for ( int i = 0; i < size; i++ ) { - processCommBuffs [ i ] = new ProcessCommunicatorBuff(t); - } - } else { - processCommBuffs = NULL; + this->processCommBuffs.reserve(s); + for ( int i = 0; i < s; ++i ) { + this->processCommBuffs.emplace_back(t); } } -CommunicatorBuff :: ~CommunicatorBuff() -{ - for ( int i = 0; i < size; i++ ) { - if ( processCommBuffs [ i ] ) { - delete(processCommBuffs [ i ]); - } - } - - if ( processCommBuffs ) { - delete[] processCommBuffs; - } -} -Communicator :: Communicator(EngngModel *emodel, CommunicatorBuff *b, int rank, int size, CommunicatorMode m) +Communicator :: Communicator(EngngModel *emodel, CommunicatorBuff *b, int rank, int size, CommunicatorMode m) : + rank(rank), + engngModel(emodel), + mode(m) { - this->engngModel = emodel; - this->rank = rank; - this->size = size; - this->mode = m; - - if ( size ) { - processComms = new ProcessCommunicator * [ size ]; - for ( int i = 0; i < size; i++ ) { - processComms [ i ] = - new ProcessCommunicator(b->giveProcessCommunicatorBuff ( i ), i, mode); - } - } else { - processComms = NULL; + processComms.reserve(size); + for ( int i = 0; i < size; i++ ) { + processComms.emplace_back(b->giveProcessCommunicatorBuff ( i ), i, mode); } } -Communicator :: ~Communicator() -{ - int i = size; - - if ( size ) { - while ( i-- ) { - delete(processComms [ i ]); - } - - delete[] processComms; - } -} int Communicator :: initExchange(int tag) { int result = 1; - for ( int i = 0; i < size; i++ ) { - result &= this->giveProcessCommunicator(i)->initExchange(tag); + for ( auto &pc : processComms ) { + result &= pc.initExchange(tag); } return result; @@ -115,8 +78,8 @@ int Communicator :: finishExchange() { int result = 1; - for ( int i = 0; i < size; i++ ) { - result &= this->giveProcessCommunicator(i)->finishExchange(); + for ( auto &pc : processComms ) { + result &= pc.finishExchange(); } return result; @@ -128,8 +91,8 @@ int Communicator :: initSend(int tag) { int result = 1; - for ( int i = 0; i < size; i++ ) { - result &= this->giveProcessCommunicator(i)->initSend(tag); + for ( auto &pc : processComms ) { + result &= pc.initSend(tag); } return result; @@ -139,8 +102,8 @@ int Communicator :: initReceive(int tag) { int result = 1; - for ( int i = 0; i < size; i++ ) { - result &= this->giveProcessCommunicator(i)->initReceive(tag); + for ( auto &pc : processComms) { + result &= pc.initReceive(tag); } return result; @@ -149,8 +112,8 @@ Communicator :: initReceive(int tag) void Communicator :: clearBuffers() { - for ( int i = 0; i < size; i++ ) { - this->giveProcessCommunicator(i)->clearBuffers(); + for ( auto &pc : processComms ) { + pc.clearBuffers(); } } diff --git a/src/oofemlib/communicator.h b/src/oofemlib/communicator.h index f7ef9e08d..25643a2d2 100644 --- a/src/oofemlib/communicator.h +++ b/src/oofemlib/communicator.h @@ -60,14 +60,11 @@ class EngngModel; class OOFEM_EXPORT CommunicatorBuff { protected: - /// Number of processes. - int size; /// Array of process communicators. - ProcessCommunicatorBuff **processCommBuffs; + std::vector processCommBuffs; public: CommunicatorBuff(int s, CommBuffType t = CBT_static); - ~CommunicatorBuff(); /** * Returns i-th process communicator buff. The process comm buffs are numbered from rank 0. @@ -76,11 +73,7 @@ class OOFEM_EXPORT CommunicatorBuff */ ProcessCommunicatorBuff * giveProcessCommunicatorBuff(int i) { - if ( i < size ) { - return processCommBuffs [ i ]; - } else { - return NULL; - } + return &this->processCommBuffs[i]; } }; @@ -107,10 +100,8 @@ class OOFEM_EXPORT Communicator protected: /// Rank of process. int rank; - /// Number of processes. - int size; /// Array of process communicators. - ProcessCommunicator **processComms; + std::vector processComms; /// Engineering model. EngngModel *engngModel; /// Mode. @@ -128,7 +119,7 @@ class OOFEM_EXPORT Communicator */ Communicator(EngngModel * emodel, CommunicatorBuff * buff, int rank, int size, CommunicatorMode mode = CommMode_Static); /// Destructor - virtual ~Communicator(); + virtual ~Communicator() {} /** * Returns i-th problem communicator. The problems are numbered from rank 0. @@ -137,11 +128,7 @@ class OOFEM_EXPORT Communicator */ ProcessCommunicator * giveProcessCommunicator(int i) { - if ( i < size ) { - return processComms [ i ]; - } else { - return NULL; - } + return &this->processComms[i]; } /** @@ -222,37 +209,33 @@ class OOFEM_EXPORT Communicator template< class T > int Communicator :: packAllData( T *ptr, int ( T :: *packFunc )( ProcessCommunicator & ) ) { - int i = size, result = 1; + int result = 1; - if ( size ) { - for ( i = 0; i < size; i++ ) { - result &= giveProcessCommunicator(i)->packData(ptr, packFunc); - } + for ( auto &pc : processComms ) { + result &= pc.packData(ptr, packFunc); } return result; } -/* - * template int - * Communicator :: packAllData (T* ptr, FloatArray* src, int (T::*packFunc) (FloatArray*, ProcessCommunicator&)) - * { - * int i = size, result = 1; - * - * if (size) - * for (i=0; i< size; i++) result &= giveProcessCommunicator(i)->packData (ptr, src, packFunc); - * return result; - * } - */ +#if 0 +template int +Communicator :: packAllData (T* ptr, FloatArray* src, int (T::*packFunc) (FloatArray*, ProcessCommunicator&)) +{ + int result = 1; + + for ( auto &pc : processComms ) result &= pc.packData (ptr, src, packFunc); + return result; +} +#endif + template< class T, class P > int Communicator :: packAllData( T *ptr, P *src, int ( T :: *packFunc )( P *, ProcessCommunicator & ) ) { - int i = size, result = 1; + int result = 1; - if ( size ) { - for ( i = 0; i < size; i++ ) { - result &= giveProcessCommunicator(i)->packData(ptr, src, packFunc); - } + for ( auto &pc : this->processComms ) { + result &= pc.packData(ptr, src, packFunc); } return result; @@ -261,15 +244,14 @@ Communicator :: packAllData( T *ptr, P *src, int ( T :: *packFunc )( P *, Proces template< class T > int Communicator :: unpackAllData( T *ptr, int ( T :: *unpackFunc )( ProcessCommunicator & ) ) { - int i, received, num_recv = 0, result = 1; + int num_recv = 0, result = 1, size = processComms.size(); IntArray recvFlag(size); //MPI_Status status; - for ( i = 0; i < size; i++ ) { + for ( int i = 0; i < size; i++ ) { // receive if receive map is not empty or mode is dynamic - if ( ( giveProcessCommunicator(i)->giveToRecvMap()->giveSize() ) || - ( this->mode == CommMode_Dynamic ) ) { - recvFlag.at(i + 1) = 1; + if ( processComms[i].giveToRecvMap().giveSize() || this->mode == CommMode_Dynamic ) { + recvFlag[i] = 1; num_recv++; } } @@ -277,19 +259,19 @@ Communicator :: unpackAllData( T *ptr, int ( T :: *unpackFunc )( ProcessCommunic while ( num_recv-- ) { // wait for any completion while ( 1 ) { - received = 0; - for ( i = 0; i < size; i++ ) { - if ( recvFlag.at(i + 1) ) { - //if (giveProcessCommunicator(i)->giveRecvBuff()->testCompletion()) { - if ( giveProcessCommunicator(i)->receiveCompleted() ) { + bool received = false; + for ( int i = 0; i < size; i++ ) { + if ( recvFlag[i] ) { + //if ( processComms[i].giveRecvBuff()->testCompletion() ) { + if ( processComms[i].receiveCompleted() ) { #ifdef __VERBOSE_PARALLEL OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Received data from partition %3d\n", rank, "Communicator :: unpackAllData", i); #endif - recvFlag.at(i + 1) = 0; - result &= giveProcessCommunicator(i)->unpackData(ptr, unpackFunc); - received = 1; + recvFlag[i] = 0; + result &= processComms[i].unpackData(ptr, unpackFunc); + received = true; break; } } @@ -315,76 +297,72 @@ Communicator :: unpackAllData( T *ptr, int ( T :: *unpackFunc )( ProcessCommunic } -/* - * template int - * Communicator :: unpackAllData (T* ptr, FloatArray* dest, int (T::*unpackFunc) (FloatArray*, ProcessCommunicator&)) - * { - * int i, received, num_recv = 0, result = 1; - * IntArray recvFlag (size); - * //MPI_Status status; - * - * for (i=0; igiveToRecvMap()->giveSize()) || - * (this->mode == CommMode_Dynamic)) { - * recvFlag.at(i+1) = 1; - * num_recv ++; - * } - * } - * - * while (num_recv--) { - * - * // wait for any completion - * while (1) { - * received = 0; - * for (i=0; igiveRecvBuff()->testCompletion()) { - * if (giveProcessCommunicator(i)->receiveCompleted()) { - * - * - ****#ifdef __VERBOSE_PARALLEL - * OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Received data from partition %3d\n", - * rank,"Communicator :: unpackAllData", i); - ****#endif - * - * recvFlag.at(i+1) = 0; - * result &= giveProcessCommunicator(i)->unpackData (ptr, dest, unpackFunc); - * received = 1; - * break; - * } - * } - * } - * if (received) break; - * } - * } - * - ****#ifdef __VERBOSE_PARALLEL - * VERBOSEPARALLEL_PRINT("Communicator :: unpackAllData", "Synchronize barrier started",rank) - ****#endif - * - * MPI_Barrier (MPI_COMM_WORLD); - * - ****#ifdef __VERBOSE_PARALLEL - * VERBOSEPARALLEL_PRINT("Communicator :: unpackAllData", "Synchronize barrier finished",rank) - ****#endif - * - * return result; - * } - */ +#if 0 +template int +Communicator :: unpackAllData (T* ptr, FloatArray* dest, int (T::*unpackFunc) (FloatArray*, ProcessCommunicator&)) +{ + int num_recv = 0, result = 1, size = processComms.size(); + IntArray recvFlag(size); + //MPI_Status status; + + for ( int i = 0; i < size; i++) { + // receive if receive map is not empty or mode is dynamic + if ( processComms[i].giveToRecvMap()->giveSize() || this->mode == CommMode_Dynamic) { + recvFlag[i] = 1; + num_recv ++; + } + } + + while (num_recv--) { + // wait for any completion + while (1) { + bool received = false; + for ( int i = 0; i < size; i++ ) { + if ( recvFlag[i] ) { + //if ( processComms[i].giveRecvBuff()->testCompletion() ) { + if ( processComms[i].receiveCompleted() ) { + +#ifdef __VERBOSE_PARALLEL + OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Received data from partition %3d\n", + rank,"Communicator :: unpackAllData", i); +#endif + + recvFlag[i] = 0; + result &= processComms[i].unpackData (ptr, dest, unpackFunc); + received = true; + break; + } + } + } + if (received) break; + } + } + +#ifdef __VERBOSE_PARALLEL + VERBOSEPARALLEL_PRINT("Communicator :: unpackAllData", "Synchronize barrier started",rank) +#endif + + MPI_Barrier (MPI_COMM_WORLD); + +#ifdef __VERBOSE_PARALLEL + VERBOSEPARALLEL_PRINT("Communicator :: unpackAllData", "Synchronize barrier finished",rank) +#endif + + return result; +} +#endif template< class T, class P > int Communicator :: unpackAllData( T *ptr, P *dest, int ( T :: *unpackFunc )( P *, ProcessCommunicator & ) ) { - int i, received, num_recv = 0, result = 1; + int num_recv = 0, result = 1, size = processComms.size(); IntArray recvFlag(size); //MPI_Status status; - for ( i = 0; i < size; i++ ) { + for ( int i = 0; i < size; i++ ) { // receive if receive map is not empty or mode is dynamic - if ( ( giveProcessCommunicator(i)->giveToRecvMap()->giveSize() ) || - ( this->mode == CommMode_Dynamic ) ) { - recvFlag.at(i + 1) = 1; + if ( processComms[i].giveToRecvMap().giveSize() || this->mode == CommMode_Dynamic ) { + recvFlag[i] = 1; num_recv++; } } @@ -392,19 +370,19 @@ Communicator :: unpackAllData( T *ptr, P *dest, int ( T :: *unpackFunc )( P *, P while ( num_recv-- ) { // wait for any completion while ( 1 ) { - received = 0; - for ( i = 0; i < size; i++ ) { - if ( recvFlag.at(i + 1) ) { - //if (giveProcessCommunicator(i)->giveRecvBuff()->testCompletion()) { - if ( giveProcessCommunicator(i)->receiveCompleted() ) { + bool received = false; + for ( int i = 0; i < size; i++ ) { + if ( recvFlag[i] ) { + //if ( processComms[i].giveRecvBuff()->testCompletion() ) { + if ( processComms[i].receiveCompleted() ) { #ifdef __VERBOSE_PARALLEL OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Received data from partition %3d\n", rank, "Communicator :: unpackAllData", i); #endif - recvFlag.at(i + 1) = 0; - result &= giveProcessCommunicator(i)->unpackData(ptr, dest, unpackFunc); - received = 1; + recvFlag[i] = 0; + result &= processComms[i].unpackData(ptr, dest, unpackFunc); + received = true; break; } } diff --git a/src/oofemlib/compcol.C b/src/oofemlib/compcol.C index 49b9292b7..0ebe00790 100644 --- a/src/oofemlib/compcol.C +++ b/src/oofemlib/compcol.C @@ -32,8 +32,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -// Class CompCol - // inspired by /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* ******** *** SparseLib++ */ @@ -83,105 +81,102 @@ namespace oofem { REGISTER_SparseMtrx(CompCol, SMT_CompCol); -CompCol :: CompCol(void) : SparseMtrx(), val_(0), rowind_(0), colptr_(0), base_(0), nz_(0) -{ - dim_ [ 0 ] = 0; - dim_ [ 1 ] = 0; -} - - -CompCol :: CompCol(int n) : SparseMtrx(n, n), val_(0), rowind_(0), colptr_(n), base_(0), nz_(0) -{ - dim_ [ 0 ] = n; - dim_ [ 1 ] = n; -} +CompCol :: CompCol(int n) : SparseMtrx(n, n), + val(0), + rowind(0), + colptr(n), + base(0), + nz(0) +{} -/*****************************/ -/* Copy constructor */ -/*****************************/ CompCol :: CompCol(const CompCol &S) : SparseMtrx(S.nRows, S.nColumns), - val_(S.val_), rowind_(S.rowind_), colptr_(S.colptr_), - base_(S.base_), nz_(S.nz_) -{ - dim_ [ 0 ] = S.dim_ [ 0 ]; - dim_ [ 1 ] = S.dim_ [ 1 ]; - nRows = S.nRows; - nColumns = S.nColumns; -} + val(S.val), + rowind(S.rowind), + colptr(S.colptr), + base(S.base), + nz(S.nz) +{} - -/***************************/ -/* Assignment operator... */ -/***************************/ - CompCol &CompCol :: operator = ( const CompCol & C ) { - dim_ [ 0 ] = C.dim_ [ 0 ]; - dim_ [ 1 ] = C.dim_ [ 1 ]; nRows = C.nRows; nColumns = C.nColumns; - base_ = C.base_; - nz_ = C.nz_; - val_ = C.val_; - rowind_ = C.rowind_; - colptr_ = C.colptr_; + base = C.base; + nz = C.nz; + val = C.val; + rowind = C.rowind; + colptr = C.colptr; this->version = C.version; return * this; } - -SparseMtrx *CompCol :: GiveCopy() const +std::unique_ptr CompCol :: clone() const { - CompCol *result = new CompCol(*this); - return result; + return std::make_unique(*this); } void CompCol :: times(const FloatArray &x, FloatArray &answer) const { - int M = dim_ [ 0 ]; - int N = dim_ [ 1 ]; - - // Check for compatible dimensions: - if ( x.giveSize() != N ) { + if ( x.giveSize() != this->giveNumberOfColumns() ) { OOFEM_ERROR("incompatible dimensions"); } - answer.resize(M); + answer.resize(this->giveNumberOfRows()); + answer.zero(); + + for ( int j = 0; j < this->giveNumberOfColumns(); j++ ) { + double rhs = x[j]; + for ( int t = colptr[j]; t < colptr[j + 1]; t++ ) { + answer[ rowind[t] ] += val[t] * rhs; + } + } +} + + +void CompCol :: timesT(const FloatArray &x, FloatArray &answer) const +{ + if ( x.giveSize() != this->giveNumberOfRows() ) { + OOFEM_ERROR("Error in CompCol -- incompatible dimensions"); + } + + answer.resize(this->giveNumberOfColumns()); answer.zero(); - for ( int j = 0; j < N; j++ ) { - double rhs = x(j); - for ( int t = colptr_(j); t < colptr_(j + 1); t++ ) { - answer( rowind_(t) ) += val_(t) * rhs; + for ( int i = 0; i < this->giveNumberOfColumns(); i++ ) { + double r = 0.0; + for ( int t = colptr[i]; t < colptr[i + 1]; t++ ) { + r += val[t] * x[ rowind[t] ]; } + + answer[i] = r; } } + void CompCol :: times(double x) { - val_.times(x); + val.times(x); - // increment version this->version++; } + int CompCol :: buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s) { IntArray loc; Domain *domain = eModel->giveDomain(di); int neq = eModel->giveNumberOfDomainEquations(di, s); - int indx; // allocation map std :: vector< std :: set< int > > columns(neq); - this->nz_ = 0; + this->nz = 0; for ( auto &elem : domain->giveElements() ) { elem->giveLocationArray(loc, s); @@ -223,31 +218,30 @@ int CompCol :: buildInternalStructure(EngngModel *eModel, int di, const UnknownN } for ( int i = 0; i < neq; i++ ) { - this->nz_ += columns [ i ].size(); + this->nz += columns [ i ].size(); } - rowind_.resize(nz_); - colptr_.resize(neq + 1); - indx = 0; + rowind.resize(nz); + colptr.resize(neq + 1); + int indx = 0; for ( int j = 0; j < neq; j++ ) { // column loop - colptr_(j) = indx; - for ( int row: columns [ j ] ) { // row loop - rowind_(indx++) = row; + colptr[j] = indx; + for ( int row: columns [ j ] ) { // row loop + rowind[indx++] = row; } } - colptr_(neq) = indx; + colptr[neq] = indx; // allocate value array - val_.resize(nz_); - val_.zero(); + val.resize(nz); + val.zero(); - OOFEM_LOG_DEBUG("CompCol info: neq is %d, nwk is %d\n", neq, nz_); + OOFEM_LOG_DEBUG("CompCol info: neq is %d, nwk is %d\n", neq, nz); - dim_ [ 0 ] = dim_ [ 1 ] = nColumns = nRows = neq; + nColumns = nRows = neq; - // increment version this->version++; return true; @@ -267,7 +261,7 @@ int CompCol :: assemble(const IntArray &loc, const FloatMatrix &mat) for ( int j = 0; j < dim; j++ ) { int jj = loc[j]; if ( jj ) { - int cstart = colptr_[jj - 1]; + int cstart = colptr[jj - 1]; int t = cstart; int last_ii = this->nRows + 1; // Ensures that t is set correctly the first time. for ( int i = 0; i < dim; i++ ) { @@ -278,13 +272,13 @@ int CompCol :: assemble(const IntArray &loc, const FloatMatrix &mat) t = cstart; else if ( ii > last_ii ) t++; - for ( ; rowind_[t] < ii - 1; t++ ) { + for ( ; rowind[t] < ii - 1; t++ ) { # ifdef DEBUG - if ( t >= colptr_[jj] ) + if ( t >= colptr[jj] ) OOFEM_ERROR("Couldn't find row %d in the sparse structure", ii); # endif } - val_[t] += mat(i, j); + val[t] += mat(i, j); last_ii = ii; } } @@ -307,7 +301,7 @@ int CompCol :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatM for ( int j = 0; j < dim2; j++ ) { int jj = cloc[j]; if ( jj ) { - int cstart = colptr_[jj - 1]; + int cstart = colptr[jj - 1]; int t = cstart; int last_ii = this->nRows + 1; // Ensures that t is set correctly the first time. for ( int i = 0; i < dim1; i++ ) { @@ -318,20 +312,19 @@ int CompCol :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatM t = cstart; else if ( ii > last_ii ) t++; - for ( ; rowind_[t] < ii - 1; t++ ) { + for ( ; rowind[t] < ii - 1; t++ ) { # ifdef DEBUG - if ( t >= colptr_[jj] ) + if ( t >= colptr[jj] ) OOFEM_ERROR("Couldn't find row %d in the sparse structure", ii); # endif } - val_[t] += mat(i, j); + val[t] += mat(i, j); last_ii = ii; } } } } - // increment version this->version++; return 1; @@ -339,9 +332,8 @@ int CompCol :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatM void CompCol :: zero() { - val_.zero(); + val.zero(); - // increment version this->version++; } @@ -352,93 +344,66 @@ void CompCol :: toFloatMatrix(FloatMatrix &answer) const void CompCol :: printYourself() const { } -/*********************/ -/* Array access */ -/*********************/ double &CompCol :: at(int i, int j) { - // increment version this->version++; - for ( int t = colptr_(j - 1); t < colptr_(j); t++ ) { - if ( rowind_(t) == i - 1 ) { - return val_(t); + for ( int t = colptr[j - 1]; t < colptr[j]; t++ ) { + if ( rowind[t] == i - 1 ) { + return val[t]; } } OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j); - return val_(0); // return to suppress compiler warning message + return val[0]; // return to suppress compiler warning message } double CompCol :: at(int i, int j) const { - for ( int t = colptr_(j - 1); t < colptr_(j); t++ ) { - if ( rowind_(t) == i - 1 ) { - return val_(t); + for ( int t = colptr[j - 1]; t < colptr[j]; t++ ) { + if ( rowind[t] == i - 1 ) { + return val[t]; } } - if ( i <= dim_ [ 0 ] && j <= dim_ [ 1 ] ) { + if ( i <= this->giveNumberOfRows() && j <= this->giveNumberOfColumns() ) { return 0.0; } else { OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j); - return ( 0 ); // return to suppress compiler warning message } + return 0.; // return to suppress compiler warning message } double CompCol :: operator() (int i, int j) const { - for ( int t = colptr_(j); t < colptr_(j + 1); t++ ) { - if ( rowind_(t) == i ) { - return val_(t); + for ( int t = colptr[j]; t < colptr[j + 1]; t++ ) { + if ( rowind[t] == i ) { + return val[t]; } } - if ( i < dim_ [ 0 ] && j < dim_ [ 1 ] ) { + if ( i < this->giveNumberOfRows() && j < this->giveNumberOfColumns() ) { return 0.0; } else { OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j); - return ( 0 ); // return to suppress compiler warning message } + return 0.; // return to suppress compiler warning message } double &CompCol :: operator() (int i, int j) { - // increment version this->version++; - for ( int t = colptr_(j); t < colptr_(j + 1); t++ ) { - if ( rowind_(t) == i ) { - return val_(t); + for ( int t = colptr[j]; t < colptr[j + 1]; t++ ) { + if ( rowind[t] == i ) { + return val[t]; } } OOFEM_ERROR("Array element (%d,%d) not in sparse structure -- cannot assign", i, j); - return val_(0); // return to suppress compiler warning message + return val[0]; // return to suppress compiler warning message } -void CompCol :: timesT(const FloatArray &x, FloatArray &answer) const -{ - int M = dim_ [ 0 ]; - int N = dim_ [ 1 ]; - - // Check for compatible dimensions: - if ( x.giveSize() != M ) { - OOFEM_ERROR("Error in CompCol -- incompatible dimensions"); - } - - answer.resize(N); - answer.zero(); - - for ( int i = 0; i < N; i++ ) { - double r = 0.0; - for ( int t = colptr_(i); t < colptr_(i + 1); t++ ) { - r += val_(t) * x( rowind_(t) ); - } - - answer(i) = r; - } -} } // end namespace oofem diff --git a/src/oofemlib/compcol.h b/src/oofemlib/compcol.h index 298502560..effbb89f2 100644 --- a/src/oofemlib/compcol.h +++ b/src/oofemlib/compcol.h @@ -75,31 +75,28 @@ #include "sparsemtrx.h" #include "intarray.h" +#define _IFT_CompCol_Name "csc" + namespace oofem { -/* +/** * Implementation of sparse matrix stored in compressed column storage. */ class OOFEM_EXPORT CompCol : public SparseMtrx { protected: - FloatArray val_; // data values (nz_ elements) - IntArray rowind_; // row_ind (nz_ elements) - IntArray colptr_; // col_ptr (dim_[1]+1 elements) + FloatArray val; // data values (nz_ elements) + IntArray rowind; // row_ind (nz_ elements) + IntArray colptr; // col_ptr (dim_[1]+1 elements) - int base_; // index base: offset of first element - int nz_; // number of nonzeros - int dim_ [ 2 ]; // number of rows, cols + int base; // index base: offset of first element + int nz; // number of nonzeros public: /** Constructor. Before any operation an internal profile must be built. * @see buildInternalStructure */ - CompCol(int n); - /** Constructor. Before any operation an internal profile must be built. - * @see buildInternalStructure - */ - CompCol(); + CompCol(int n=0); /// Copy constructor CompCol(const CompCol & S); /// Assignment operator @@ -108,49 +105,36 @@ class OOFEM_EXPORT CompCol : public SparseMtrx virtual ~CompCol() { } // Overloaded methods: - SparseMtrx *GiveCopy() const; - virtual void times(const FloatArray &x, FloatArray &answer) const; - virtual void timesT(const FloatArray &x, FloatArray &answer) const; - virtual void times(double x); - virtual int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &s); - virtual int assemble(const IntArray &loc, const FloatMatrix &mat); - virtual int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat); - virtual bool canBeFactorized() const { return false; } - virtual void zero(); - virtual double &at(int i, int j); - virtual double at(int i, int j) const; - virtual void toFloatMatrix(FloatMatrix &answer) const; - virtual void printYourself() const; - virtual const char* giveClassName() const { return "CompCol"; } - virtual SparseMtrxType giveType() const { return SMT_CompCol; } - virtual bool isAsymmetric() const { return true; } + std::unique_ptr clone() const override; + void times(const FloatArray &x, FloatArray &answer) const override; + void timesT(const FloatArray &x, FloatArray &answer) const override; + void times(double x) override; + int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &s) override; + int assemble(const IntArray &loc, const FloatMatrix &mat) override; + int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) override; + bool canBeFactorized() const override { return false; } + void zero() override; + double &at(int i, int j) override; + double at(int i, int j) const override; + void toFloatMatrix(FloatMatrix &answer) const override; + void printYourself() const override; + const char* giveClassName() const override { return "CompCol"; } + SparseMtrxType giveType() const override { return SMT_CompCol; } + bool isAsymmetric() const override { return true; } // Breaks encapsulation, but access is needed for PARDISO and SuperLU solvers; - FloatArray &giveValues() { return val_; } - IntArray &giveRowIndex() { return rowind_; } - IntArray &giveColPtr() { return colptr_; } + FloatArray &giveValues() { return val; } + IntArray &giveRowIndex() { return rowind; } + IntArray &giveColPtr() { return colptr; } // Methods needed by SuperLU interface - const int giveNumberOfNonzeros() {return nz_;} - - const double &val(int i) const { return val_(i); } - const int &row_ind(int i) const { return rowind_(i); } - const int &col_ptr(int i) const { return colptr_(i); } - int dim(int i) const { return dim_ [ i ]; } + const int giveNumberOfNonzeros() {return nz;} -protected: - /*******************************/ - /* Access and info functions */ - /*******************************/ - - double &val(int i) { return val_(i); } - int &row_ind(int i) { return rowind_(i); } - int &col_ptr(int i) { return colptr_(i); } - - int size(int i) const { return dim_ [ i ]; } - int NumNonzeros() const { return nz_; } - int base() const { return base_; } + const double &values(int i) const { return val[i]; } + const int &row_ind(int i) const { return rowind[i]; } + const int &col_ptr(int i) const { return colptr[i]; } +protected: /***********************************/ /* General access function (slow) */ /***********************************/ diff --git a/src/oofemlib/connectivitytable.C b/src/oofemlib/connectivitytable.C index aa96ab210..23ad80b73 100644 --- a/src/oofemlib/connectivitytable.C +++ b/src/oofemlib/connectivitytable.C @@ -40,6 +40,13 @@ namespace oofem { + ConnectivityTable::ConnectivityTable(Domain * d) : domain(d), nodalConnectivity(), nodalConnectivityFlag(0) +{ + #ifdef _OPENMP + omp_init_lock(&initLock); +#endif +} + void ConnectivityTable :: reset() { @@ -59,7 +66,13 @@ ConnectivityTable :: instanciateConnectivityTable() if ( nodalConnectivityFlag ) { return; // already initialized } - +#ifdef _OPENMP + omp_set_lock(&initLock); // if not initialized yet; one thread can proceed with init; others have to wait until init completed + if ( this->nodalConnectivityFlag ) { + omp_unset_lock(&initLock); + return; + } +#endif // OOFEM_LOG_INFO("ConnectivityTable: initializing\n"); for ( auto &elem : domain->giveElements() ) { @@ -73,7 +86,7 @@ ConnectivityTable :: instanciateConnectivityTable() // allocate Nodal connectivity table for domain nodalConnectivity.resize(ndofMan); for ( int i = 0; i < ndofMan; i++ ) { - nodalConnectivity[i].resize( dofManConnectivity(i) ); + nodalConnectivity[i].resize( dofManConnectivity[i] ); } // build Nodal connectivity table for domain @@ -89,6 +102,11 @@ ConnectivityTable :: instanciateConnectivityTable() } nodalConnectivityFlag = 1; + + #ifdef _OPENMP + omp_unset_lock(&initLock); +#endif + } const IntArray * diff --git a/src/oofemlib/connectivitytable.h b/src/oofemlib/connectivitytable.h index 0265edff5..b50b8a2e2 100644 --- a/src/oofemlib/connectivitytable.h +++ b/src/oofemlib/connectivitytable.h @@ -39,6 +39,10 @@ #include +#ifdef _OPENMP +#include +#endif + namespace oofem { class IntArray; class Domain; @@ -62,12 +66,14 @@ class OOFEM_EXPORT ConnectivityTable std::vector< IntArray > nodalConnectivity; /// Flag indicating assembled connectivity table for domain. int nodalConnectivityFlag; - +#ifdef _OPENMP + omp_lock_t initLock; +#endif public: /** * Constructor. Creates new Connectivity table belonging to given domain. */ - ConnectivityTable(Domain * d) : domain(d), nodalConnectivity(), nodalConnectivityFlag(0) { } + ConnectivityTable(Domain * d) ; /// Destructor ~ConnectivityTable() { } /// reset receiver to an initial state (will force table update, when needed next time) diff --git a/src/oofemlib/constantedgeload.C b/src/oofemlib/constantedgeload.C index 82e6225ac..e4679c4df 100644 --- a/src/oofemlib/constantedgeload.C +++ b/src/oofemlib/constantedgeload.C @@ -41,10 +41,10 @@ namespace oofem { REGISTER_BoundaryCondition(ConstantEdgeLoad); -IRResultType -ConstantEdgeLoad :: initializeFrom(InputRecord *ir) +void +ConstantEdgeLoad :: initializeFrom(InputRecord &ir) { - return BoundaryLoad :: initializeFrom(ir); + BoundaryLoad :: initializeFrom(ir); } void diff --git a/src/oofemlib/constantedgeload.h b/src/oofemlib/constantedgeload.h index b564ae2ea..e4aeacdbd 100644 --- a/src/oofemlib/constantedgeload.h +++ b/src/oofemlib/constantedgeload.h @@ -64,16 +64,16 @@ class OOFEM_EXPORT ConstantEdgeLoad : public EdgeLoad public: ConstantEdgeLoad(int i, Domain * d) : EdgeLoad(i, d) { } - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); - virtual int giveApproxOrder() { return 0; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual bcGeomType giveBCGeoType() const { return EdgeLoadBGT; } + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; + int giveApproxOrder() override { return 0; } + void initializeFrom(InputRecord &ir) override; + bcGeomType giveBCGeoType() const override { return EdgeLoadBGT; } - virtual const char *giveClassName() const { return "ConstantEdgeLoad"; } - virtual const char *giveInputRecordName() const { return _IFT_ConstantEdgeLoad_Name; } + const char *giveClassName() const override { return "ConstantEdgeLoad"; } + const char *giveInputRecordName() const override { return _IFT_ConstantEdgeLoad_Name; } private: - virtual void computeNArray(FloatArray &answer, const FloatArray &coords) const { answer.clear(); } + void computeNArray(FloatArray &answer, const FloatArray &coords) const override { answer.clear(); } }; } // end namespace oofem #endif // constantedgeload_h diff --git a/src/oofemlib/constantfunction.C b/src/oofemlib/constantfunction.C index b19938715..07216daf8 100644 --- a/src/oofemlib/constantfunction.C +++ b/src/oofemlib/constantfunction.C @@ -35,18 +35,18 @@ #include "constantfunction.h" #include "dynamicinputrecord.h" #include "classfactory.h" +#include "datastream.h" +#include "contextioerr.h" namespace oofem { REGISTER_Function(ConstantFunction); -IRResultType -ConstantFunction :: initializeFrom(InputRecord *ir) +void +ConstantFunction :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Function :: initializeFrom(ir); IR_GIVE_FIELD(ir, value, _IFT_ConstantFunction_f); - - return Function :: initializeFrom(ir); } @@ -56,4 +56,30 @@ ConstantFunction :: giveInputRecord(DynamicInputRecord &input) Function :: giveInputRecord(input); input.setField(this->value, _IFT_ConstantFunction_f); } + +void +ConstantFunction :: saveContext(DataStream &stream, ContextMode mode) +{ + Function :: saveContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( !stream.write(value) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +void +ConstantFunction :: restoreContext(DataStream &stream, ContextMode mode) +{ + Function :: restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( !stream.read(value) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + } // end namespace oofem diff --git a/src/oofemlib/constantfunction.h b/src/oofemlib/constantfunction.h index b8f348623..c87d342ca 100644 --- a/src/oofemlib/constantfunction.h +++ b/src/oofemlib/constantfunction.h @@ -65,16 +65,18 @@ class OOFEM_EXPORT ConstantFunction : public Function /// @return Value of receiver. double giveValue() { return value; } - virtual void evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp=NULL, double param=0.) { answer = FloatArray{this->giveValue()}; } - virtual double evaluateAtTime(double t) { return this->giveValue(); } - virtual double evaluateVelocityAtTime(double t) { return 0.; } - virtual double evaluateAccelerationAtTime(double t) { return 0.; } + void evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp=nullptr, double param=0.) override { answer = FloatArray{this->giveValue()}; } + double evaluateAtTime(double t) override { return this->giveValue(); } + double evaluateVelocityAtTime(double t) override { return 0.; } + double evaluateAccelerationAtTime(double t) override { return 0.; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual const char *giveClassName() const { return "ConstantFunction"; } - virtual const char *giveInputRecordName() const { return _IFT_ConstantFunction_Name; } + const char *giveClassName() const override { return "ConstantFunction"; } + const char *giveInputRecordName() const override { return _IFT_ConstantFunction_Name; } + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; } // end namespace oofem #endif // constantfunction_h diff --git a/src/oofemlib/constantsurfaceload.C b/src/oofemlib/constantsurfaceload.C index f50d96a08..5312333ff 100644 --- a/src/oofemlib/constantsurfaceload.C +++ b/src/oofemlib/constantsurfaceload.C @@ -47,14 +47,12 @@ ConstantSurfaceLoad :: ConstantSurfaceLoad(int i, Domain *d) : SurfaceLoad(i, d) this->loadOffset = 0.0; } -IRResultType -ConstantSurfaceLoad :: initializeFrom(InputRecord *ir) +void +ConstantSurfaceLoad :: initializeFrom(InputRecord &ir) { SurfaceLoad :: initializeFrom(ir); - IRResultType result; // Required by IR_GIVE_FIELD macro IR_GIVE_OPTIONAL_FIELD(ir, this->loadOffset, _IFT_ConstantSurfaceLoad_LoadOffset); - return IRRT_OK; } void diff --git a/src/oofemlib/constantsurfaceload.h b/src/oofemlib/constantsurfaceload.h index 4a0684d43..ba20a48c8 100644 --- a/src/oofemlib/constantsurfaceload.h +++ b/src/oofemlib/constantsurfaceload.h @@ -71,8 +71,8 @@ class OOFEM_EXPORT ConstantSurfaceLoad : public SurfaceLoad ConstantSurfaceLoad(int i, Domain * d); // Overloaded methods: - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); - virtual int giveApproxOrder() { return 0; } + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; + int giveApproxOrder() override { return 0; } /** * Sets a new load vector. @@ -80,16 +80,16 @@ class OOFEM_EXPORT ConstantSurfaceLoad : public SurfaceLoad */ void updateLoad(const FloatArray &newValue) { componentArray = newValue; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual bcGeomType giveBCGeoType() const { return SurfaceLoadBGT; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + bcGeomType giveBCGeoType() const override { return SurfaceLoadBGT; } - virtual const char *giveClassName() const { return "ConstantSurfaceLoad"; } - virtual const char *giveInputRecordName() const { return _IFT_ConstantSurfaceLoad_Name; } + const char *giveClassName() const override { return "ConstantSurfaceLoad"; } + const char *giveInputRecordName() const override { return _IFT_ConstantSurfaceLoad_Name; } double giveLoadOffset() { return this->loadOffset; } private: - virtual void computeNArray(FloatArray &answer, const FloatArray &coords) const { answer.clear(); } + void computeNArray(FloatArray &answer, const FloatArray &coords) const override { answer.clear(); } double loadOffset; // xi-coord offset of load. xi=-1 -> bottom, xi=0 -> midsurface (default), xi=1 -> top surface }; } // end namespace oofem diff --git a/src/oofemlib/contact/contactdefinition.C b/src/oofemlib/contact/contactdefinition.C index ecac53f52..876b8ff2b 100644 --- a/src/oofemlib/contact/contactdefinition.C +++ b/src/oofemlib/contact/contactdefinition.C @@ -59,9 +59,9 @@ ContactDefinition :: ~ContactDefinition() int -ContactDefinition :: instanciateYourself(DataReader *dr) +ContactDefinition :: instanciateYourself(DataReader &dr) { - for ( ContactElement *cEl : this->masterElementList ) { + for ( auto cEl : this->masterElementList ) { cEl->instanciateYourself(dr); cEl->setupIntegrationPoints(); } diff --git a/src/oofemlib/contact/contactdefinition.h b/src/oofemlib/contact/contactdefinition.h index 3dbfa3ca4..ecf48b09f 100644 --- a/src/oofemlib/contact/contactdefinition.h +++ b/src/oofemlib/contact/contactdefinition.h @@ -82,9 +82,9 @@ class OOFEM_EXPORT ContactDefinition virtual void createContactDofs(); - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + virtual void initializeFrom(InputRecord &ir) { } - virtual int instanciateYourself(DataReader *dr); + virtual int instanciateYourself(DataReader &dr); virtual const char *giveClassName() const { return "ContactDefinition"; } //virtual const char *giveInputRecordName() const { return _IFT_ContactDefinition_Name; } ContactManager *giveContactManager() { return this->cMan; } diff --git a/src/oofemlib/contact/contactelement.C b/src/oofemlib/contact/contactelement.C index d35461c01..e4efc33be 100644 --- a/src/oofemlib/contact/contactelement.C +++ b/src/oofemlib/contact/contactelement.C @@ -65,7 +65,7 @@ Node2NodeContact :: Node2NodeContact(DofManager *master, DofManager *slave) : Co }; int -Node2NodeContact :: instanciateYourself(DataReader *dr) +Node2NodeContact :: instanciateYourself(DataReader &dr) { // compute normal as direction vector from master node to slave node FloatArray xs, xm, normal; diff --git a/src/oofemlib/contact/contactelement.h b/src/oofemlib/contact/contactelement.h index e7229e6f2..ce7a5343b 100644 --- a/src/oofemlib/contact/contactelement.h +++ b/src/oofemlib/contact/contactelement.h @@ -75,40 +75,34 @@ class IntegrationRule; class OOFEM_EXPORT ContactElement { private: - //ContactDefinition *cDef; - - std :: vector< ContactElement *> slaveObjectList; // remove? - + //std::unique_ptr cDef; + std :: vector< std::unique_ptr > slaveObjectList; // remove? + IntArray dofIdArray; - - protected: bool inContact; public: - IntegrationRule *integrationRule; + std::unique_ptr integrationRule; /// Constructor. ContactElement(); /// Destructor. virtual ~ContactElement(){}; virtual void setupIntegrationPoints(){}; - - - ContactElement *giveSlave(const int num) { return slaveObjectList[num-1]; } + + ContactElement *giveSlave(const int num) { return slaveObjectList[num-1].get(); } int giveNumberOfSlaves() { return (int)slaveObjectList.size(); } - virtual int instanciateYourself(DataReader *dr){ return 1; } + virtual int instanciateYourself(DataReader &dr){ return 1; } //virtual const char *giveClassName() const { return "ContactDefinition"; } bool isInContact() { return inContact; } virtual void giveDofManagersToAppendTo(IntArray &answer) { answer.clear(); } - - + virtual void computeContactForces(FloatArray &answer, TimeStep *tStep, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms) = 0; - + virtual void computeContactTangent(FloatMatrix &answer, TimeStep *tStep) = 0; - - + virtual void giveLocationArray(IntArray &answer, const UnknownNumberingScheme &s) = 0; // set the dof id array if the contact element has its own dofs (Lagrange multipliers) virtual void setDofIdArray(IntArray &array){ this->dofIdArray = array; } @@ -137,7 +131,7 @@ class OOFEM_EXPORT Node2NodeContact : public ContactElement Node2NodeContact(DofManager *master, DofManager *slave); /// Destructor. virtual ~Node2NodeContact(){}; - virtual int instanciateYourself(DataReader *dr); + virtual int instanciateYourself(DataReader &dr); virtual void setupIntegrationPoints(); virtual void computeGap(FloatArray &answer, TimeStep *tStep); @@ -178,7 +172,7 @@ class OOFEM_EXPORT Node2NodeContactL : public Node2NodeContact Node2NodeContactL(DofManager *master, DofManager *slave); /// Destructor. virtual ~Node2NodeContactL(){}; - //virtual int instanciateYourself(DataReader *dr); + //virtual int instanciateYourself(DataReader &dr); virtual void giveDofManagersToAppendTo(IntArray &answer); virtual void computeContactTractionAt(GaussPoint *gp, FloatArray &t, FloatArray &gap, TimeStep *tStep); diff --git a/src/oofemlib/contact/contactmanager.C b/src/oofemlib/contact/contactmanager.C index 69d66d185..574a3f2a8 100644 --- a/src/oofemlib/contact/contactmanager.C +++ b/src/oofemlib/contact/contactmanager.C @@ -52,41 +52,34 @@ ContactManager :: ~ContactManager() } -IRResultType -ContactManager :: initializeFrom(InputRecord *ir) +void +ContactManager :: initializeFrom(InputRecord &ir) { - - IRResultType result; // Required by IR_GIVE_FIELD macro - this->numberOfContactDefinitions = 0; IR_GIVE_FIELD(ir, this->numberOfContactDefinitions, _IFT_ContactManager_NumberOfContactDefinitions); - this->contactDefinitionList.resize(this->numberOfContactDefinitions); #if 0 for ( int i = 1; i <= numberOfContactDefinitions; i++ ) { std::string name; - result = ir->giveRecordKeywordField(name); + ir.giveRecordKeywordField(name); this->contactDefinitionList[i-1] = new ContactDefinition(this); this->contactDefinitionList[i-1] = classFactory.createContactDefinition( name.c_str(), this ); } #endif - - return IRRT_OK; } int -ContactManager :: instanciateYourself(DataReader *dr) +ContactManager :: instanciateYourself(DataReader &dr) { - IRResultType result = IRRT_OK; // Required by IR_GIVE_FIELD macro std :: string name; // Create and instantiate contact definitions for ( int i = 1; i <= this->giveNumberOfContactDefinitions(); i++ ) { - InputRecord *ir = dr->giveInputRecord(DataReader :: IR_contactDefRec, i); - result = ir->giveRecordKeywordField(name); - this->contactDefinitionList[i-1].reset( classFactory.createContactDefinition( name.c_str(), this ) ); + auto &ir = dr.giveInputRecord(DataReader :: IR_contactDefRec, i); + ir.giveRecordKeywordField(name); + this->contactDefinitionList[i-1] = classFactory.createContactDefinition( name.c_str(), this ); if ( this->contactDefinitionList[i-1] ) { this->contactDefinitionList[i-1]->initializeFrom(ir); this->contactDefinitionList[i-1]->instanciateYourself(dr); @@ -95,7 +88,7 @@ ContactManager :: instanciateYourself(DataReader *dr) } } - return result; + return 1; } diff --git a/src/oofemlib/contact/contactmanager.h b/src/oofemlib/contact/contactmanager.h index ec5e021b9..a996b22c5 100644 --- a/src/oofemlib/contact/contactmanager.h +++ b/src/oofemlib/contact/contactmanager.h @@ -83,9 +83,9 @@ class OOFEM_EXPORT ContactManager void createContactDofs(); /// Initializes receiver according to object description stored in input record. - virtual IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); - virtual int instanciateYourself(DataReader *dr); + virtual int instanciateYourself(DataReader &dr); virtual const char *giveClassName() const { return "ContactManager"; } Domain *giveDomain() { return this->domain; } diff --git a/src/oofemlib/contextioerr.h b/src/oofemlib/contextioerr.h index e7a1bd379..0dffb4cd1 100644 --- a/src/oofemlib/contextioerr.h +++ b/src/oofemlib/contextioerr.h @@ -35,6 +35,8 @@ #ifndef contextioerr_h #define contextioerr_h +#include + #include "oofemcfg.h" #include "contextioresulttype.h" @@ -43,18 +45,18 @@ namespace oofem { * Context IO exception class * @todo Document more. */ -class OOFEM_EXPORT ContextIOERR +class OOFEM_EXPORT ContextIOERR : public std::exception { contextIOResultType error; const char *msg, *file; int line; + std::string full_message; public: - ContextIOERR(contextIOResultType e, const char *file, int line); ContextIOERR(contextIOResultType e, const char *msg, const char *file, int line); - ~ContextIOERR(); + const char* what() const noexcept override { return this->full_message.c_str(); } void print(); }; diff --git a/src/oofemlib/crosssectextension.h b/src/oofemlib/crosssectextension.h index 52bcff85e..8802aed49 100644 --- a/src/oofemlib/crosssectextension.h +++ b/src/oofemlib/crosssectextension.h @@ -41,6 +41,7 @@ enum CrossSectExtension { CS_StructuralCapability, ///< Structural capability. CS_StructuralInterfaceCapability, ///< Structural interface capability. CS_HeatCapability, ///< Heat capability. + CS_LatticeStructuralCapability, ///< Structural lattice capability. }; } // end namespace oofem #endif // crosssectextension_h diff --git a/src/oofemlib/crosssection.C b/src/oofemlib/crosssection.C index 605b007a4..faa7015ff 100644 --- a/src/oofemlib/crosssection.C +++ b/src/oofemlib/crosssection.C @@ -38,6 +38,7 @@ #include "gausspoint.h" #include "material.h" #include "contextioerr.h" +#include "datastream.h" #include "gaussintegrationrule.h" namespace oofem { @@ -63,19 +64,12 @@ CrossSection :: setupIntegrationPoints(IntegrationRule &irule, int npointsXY, in return irule.setUpIntegrationPoints( element->giveIntegrationDomain(), npointsXY, npointsZ, element->giveMaterialMode() ); } -IRResultType -CrossSection :: initializeFrom(InputRecord *ir) -// -// instanciates receiver from input record -// +void +CrossSection :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - // Read set number the cross section is applied to this->setNumber = 0; IR_GIVE_OPTIONAL_FIELD(ir, this->setNumber, _IFT_CrossSection_SetNumber); - - return IRRT_OK; } void @@ -106,39 +100,19 @@ CrossSection :: printYourself() } -contextIOResultType +void CrossSection :: saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -// -// saves full material context (saves state variables, that completely describe -// current state) -// { - contextIOResultType iores; Material *mat = this->giveMaterial(gp); - - if ( ( iores = mat->saveIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + mat->saveIPContext(stream, mode, gp); } -contextIOResultType +void CrossSection :: restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -// -// restores full material context (saves state variables, that completely describe -// current state) -// { - contextIOResultType iores; Material *mat = this->giveMaterial(gp); - - if ( ( iores = mat->restoreIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + mat->restoreIPContext(stream, mode, gp); } bool @@ -148,7 +122,7 @@ CrossSection :: hasProperty(CrossSectionProperty aProperty) } double -CrossSection :: give(CrossSectionProperty aProperty, GaussPoint *gp) +CrossSection :: give(CrossSectionProperty aProperty, GaussPoint *gp) const // Returns the value of the property aProperty of the receiver. { if ( propertyDictionary.includes(aProperty) ) { @@ -161,7 +135,7 @@ CrossSection :: give(CrossSectionProperty aProperty, GaussPoint *gp) } double -CrossSection :: give(CrossSectionProperty aProperty, const FloatArray &coords, Element *elem, bool local) +CrossSection :: give(CrossSectionProperty aProperty, const FloatArray &coords, Element *elem, bool local) const // Returns the value of the property aProperty of the receiver. { if ( propertyDictionary.includes(aProperty) ) { @@ -180,4 +154,32 @@ CrossSection :: predictRelativeComputationalCost(GaussPoint *gp) return this->giveRelativeSelfComputationalCost() * this->giveMaterial(gp)->predictRelativeComputationalCost(gp); } + +void CrossSection :: saveContext(DataStream &stream, ContextMode mode) +{ + FEMComponent :: saveContext(stream, mode); + + if ( ( mode & CM_Definition ) ) { + propertyDictionary.saveContext (stream) ; + + if ( !stream.write(setNumber) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +void CrossSection :: restoreContext(DataStream &stream, ContextMode mode) +{ + FEMComponent :: restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + propertyDictionary.restoreContext(stream); + + if ( !stream.read(setNumber) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + } // end namespace oofem diff --git a/src/oofemlib/crosssection.h b/src/oofemlib/crosssection.h index 4aeffca34..cafdbbce2 100644 --- a/src/oofemlib/crosssection.h +++ b/src/oofemlib/crosssection.h @@ -62,7 +62,7 @@ enum CrossSectionProperty { CS_Area, ///< Area CS_InertiaMomentY, ///< Moment of inertia around y-axis CS_InertiaMomentZ, ///< Moment of inertia around z-axis - CS_TorsionMomentX, ///< Moment of inertia around x-axis + CS_TorsionConstantX, ///< Saint-Venant torsional constant (J) CS_ShearAreaY, ///< Shear area in y direction CS_ShearAreaZ, ///< Shear area in z direction CS_DrillingStiffness, ///< Penalty stiffness for drilling DOFs. @@ -140,7 +140,7 @@ class OOFEM_EXPORT CrossSection : public FEMComponent * @param gp Integration point * @return Property value. */ - virtual double give(CrossSectionProperty a, GaussPoint *gp); + virtual double give(CrossSectionProperty a, GaussPoint *gp) const; /** * Returns the value of cross section property at given point (belonging to given element). * the point coordinates can be specified using its local element coordinates or @@ -152,7 +152,7 @@ class OOFEM_EXPORT CrossSection : public FEMComponent * @param gp Integration point * @return Property value. */ - virtual double give(CrossSectionProperty a, const FloatArray &coords, Element *elem, bool local = true); + virtual double give(CrossSectionProperty a, const FloatArray &coords, Element *elem, bool local = true) const; /** * Returns the value of cross section property. @@ -160,7 +160,7 @@ class OOFEM_EXPORT CrossSection : public FEMComponent * @param gp Integration point. * @return Property value. */ - virtual double give(int aProperty, GaussPoint *gp) { return 0.0; } + virtual double give(int aProperty, GaussPoint *gp) const { return 0.0; } /** * Check for symmetry of stiffness matrix. @@ -169,8 +169,9 @@ class OOFEM_EXPORT CrossSection : public FEMComponent * @param rMode Response mode of material. * @return True if stiffness matrix of receiver is symmetric. */ - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } - virtual void printYourself(); + virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const { return false; } + + void printYourself() override; /** * Sets up integration rule for the given element. @@ -263,33 +264,34 @@ class OOFEM_EXPORT CrossSection : public FEMComponent */ virtual double predictRelativeRedistributionCost(GaussPoint *gp) { return 1.0; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; /** * Returns the material associated with the GP. * Default implementation uses gp->giveMaterial() for backwards compatibility, but it should be overloaded in each specialized cross-section. */ - virtual Material *giveMaterial(IntegrationPoint *ip) = 0; + virtual Material *giveMaterial(IntegrationPoint *ip) const = 0; /** * Stores integration point state to output stream. * @param stream Output stream. * @param mode Determines amount of info required in stream (state, definition, ...). * @param gp integration point. - * @return contextIOResultType. * @exception throws an ContextIOERR exception if error encountered. */ - virtual contextIOResultType saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); + virtual void saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); /** * Reads integration point state to output stream. * @param stream Output stream. * @param mode Determines amount of info required in stream (state, definition, ...). * @param gp integration point. - * @return contextIOResultType. * @exception throws an ContextIOERR exception if error encountered. */ - virtual contextIOResultType restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); + virtual void restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; } // end namespace oofem #endif // crosssection_h diff --git a/src/oofemlib/datareader.h b/src/oofemlib/datareader.h index 761a78bd6..b435f3712 100644 --- a/src/oofemlib/datareader.h +++ b/src/oofemlib/datareader.h @@ -75,7 +75,7 @@ class OOFEM_EXPORT DataReader * @param irType Determines type of record to be returned. * @param recordId Determines the record number corresponding to component number. */ - virtual InputRecord *giveInputRecord(InputRecordType irType, int recordId) = 0; + virtual InputRecord &giveInputRecord(InputRecordType irType, int recordId) = 0; /** * Peak in advance into the record list. @@ -88,15 +88,12 @@ class OOFEM_EXPORT DataReader */ virtual void finish() = 0; + /// Gives the reference file name (e.g. file name) + virtual std :: string giveReferenceName() const = 0; /// Gives the output file name std :: string giveOutputFileName() { return this->outputFileName; } /// Gives the problem description std :: string giveDescription() { return this->description; } - - /// Prints the name (shortened) of data source. - virtual const char *giveDataSourceName() const = 0; - /// Prints the error message. - void report_error(const char *_class, const char *proc, const char *kwd, IRResultType result, const char *file, int line); }; } // end namespace oofem #endif // datareader_h diff --git a/src/oofemlib/datastream.C b/src/oofemlib/datastream.C index 3c307e610..6e2d07620 100644 --- a/src/oofemlib/datastream.C +++ b/src/oofemlib/datastream.C @@ -63,14 +63,13 @@ int DataStream :: write(const std :: string &data) } FileDataStream :: FileDataStream(std::string filename, bool write): - stream(NULL), - filename(std::move(filename)), - close(true) + stream(nullptr), + filename(std::move(filename)) { + //stream.open(filename, (write ? std::ios::out : std::ios:in) | std::ios::binary ); this->stream = fopen(this->filename.c_str(), write ? "wb" : "rb" ); - if ( this->stream == NULL ) { - //throw some exception here - OOFEM_ERROR("nope"); + if ( !this->stream ) { + throw CantOpen(this->filename); } } @@ -82,6 +81,8 @@ FileDataStream :: ~FileDataStream() int FileDataStream :: read(int *data, int count) { return ( (int)fread(data, sizeof( int ), count, stream) == count ); + //this->stream.read(reinterpret_cast< char* >(data), sizeof(int)*count); + //return this->stream.good(); } int FileDataStream :: read(unsigned long *data, int count) diff --git a/src/oofemlib/datastream.h b/src/oofemlib/datastream.h index e6259ce79..28d9ab205 100644 --- a/src/oofemlib/datastream.h +++ b/src/oofemlib/datastream.h @@ -39,6 +39,8 @@ #include #include +#include +#include namespace oofem { /** @@ -133,39 +135,45 @@ class OOFEM_EXPORT DataStream */ class OOFEM_EXPORT FileDataStream : public DataStream { +public: + class CantOpen : public std::runtime_error + { + public: + std::string filename; + CantOpen(std::string file): std::runtime_error("can't open file"), filename(std::move(file)) {} + }; + private: /// FILE pointer of associated stream FILE *stream; /// Filename std :: string filename; - bool close; public: /// Constructor, takes associated stream pointer as parameter - FileDataStream(FILE * s): stream(s), close(false) { } FileDataStream(std :: string filename, bool write); /// Destructor (will not close stream!) virtual ~FileDataStream(); - virtual int read(int *data, int count); - virtual int read(unsigned long *data, int count); - virtual int read(long *data, int count); - virtual int read(double *data, int count); - virtual int read(char *data, int count); - virtual int read(bool &data); + int read(int *data, int count) override; + int read(unsigned long *data, int count) override; + int read(long *data, int count) override; + int read(double *data, int count) override; + int read(char *data, int count) override; + int read(bool &data) override; - virtual int write(const int *data, int count); - virtual int write(const unsigned long *data, int count); - virtual int write(const long *data, int count); - virtual int write(const double *data, int count); - virtual int write(const char *data, int count); - virtual int write(bool data); + int write(const int *data, int count) override; + int write(const unsigned long *data, int count) override; + int write(const long *data, int count) override; + int write(const double *data, int count) override; + int write(const char *data, int count) override; + int write(bool data) override; - virtual int givePackSizeOfInt(int count); - virtual int givePackSizeOfDouble(int count); - virtual int givePackSizeOfChar(int count); - virtual int givePackSizeOfBool(int count); - virtual int givePackSizeOfLong(int count); + int givePackSizeOfInt(int count) override; + int givePackSizeOfDouble(int count) override; + int givePackSizeOfChar(int count) override; + int givePackSizeOfBool(int count) override; + int givePackSizeOfLong(int count) override; }; } // end namespace oofem diff --git a/src/oofemlib/deadweight.h b/src/oofemlib/deadweight.h index 6739bfe81..d9eb4509a 100644 --- a/src/oofemlib/deadweight.h +++ b/src/oofemlib/deadweight.h @@ -62,15 +62,15 @@ class OOFEM_EXPORT DeadWeight : public BodyLoad * @param coords Global coordinates, which are used to evaluate components values. * @param mode Determines response mode- */ - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; - virtual bcValType giveBCValType() const { return ForceLoadBVT; } - virtual bcGeomType giveBCGeoType() const { return BodyLoadBGT; } + bcValType giveBCValType() const override { return ForceLoadBVT; } + bcGeomType giveBCGeoType() const override { return BodyLoadBGT; } void setDeadWeighComponents(FloatArray newComponents); - virtual const char *giveClassName() const { return "DeadWeight"; } - virtual const char *giveInputRecordName() const { return _IFT_DeadWeight_Name; } + const char *giveClassName() const override { return "DeadWeight"; } + const char *giveInputRecordName() const override { return _IFT_DeadWeight_Name; } }; } // end namespace oofem #endif // deadweight_h diff --git a/src/oofemlib/dictionary.C b/src/oofemlib/dictionary.C index 7ec2bdf72..8a4e21c96 100644 --- a/src/oofemlib/dictionary.C +++ b/src/oofemlib/dictionary.C @@ -66,10 +66,8 @@ Dictionary :: clear() int Dictionary :: giveSize() { - Pair *next; int size = 0; - - next = first; + Pair *next = first; while ( next ) { size++; next = next->giveNext(); @@ -81,7 +79,6 @@ Dictionary :: giveSize() Pair *Dictionary :: add(int k, double v) // Adds the pair (k,v) to the receiver. Returns this new pair. { - Pair *newPair; # ifdef DEBUG if ( this->includes(k) ) { @@ -90,7 +87,7 @@ Pair *Dictionary :: add(int k, double v) # endif - newPair = new Pair(k, v); + Pair *newPair = new Pair(k, v); if ( last ) { last->append(newPair); } else { // empty dictionary @@ -107,9 +104,7 @@ double &Dictionary :: at(int aKey) // Returns the value of the pair which key is aKey. If such pair does // not exist, creates it and assign value 0. { - Pair *next, *newPair; - - next = first; + Pair *next = first; while ( next ) { if ( next->giveKey() == aKey ) { return next->giveValue(); @@ -118,18 +113,31 @@ double &Dictionary :: at(int aKey) next = next->giveNext(); } - newPair = this->add(aKey, 0); // pair does not exist yet + Pair *newPair = this->add(aKey, 0); // pair does not exist yet return newPair->giveValue(); } -bool Dictionary :: includes(int aKey) +double Dictionary :: at(int aKey) const +{ + Pair *next = first; + while ( next ) { + if ( next->giveKey() == aKey ) { + return next->giveValue(); + } + + next = next->giveNext(); + } + OOFEM_ERROR("Requested key missing from dictionary"); + return 0.; +} + + +bool Dictionary :: includes(int aKey) const // Returns True if the receiver contains a pair which key is aKey, else // returns False. { - Pair *next; - - next = first; + Pair *next = first; while ( next ) { if ( next->giveKey() == aKey ) { return true; @@ -172,11 +180,7 @@ Dictionary :: formatAsString(std :: string &str) } -contextIOResultType Dictionary :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full node context (saves state variables, that completely describe -// current state) -// +void Dictionary :: saveContext(DataStream &stream) { int nitems = 0; int key; @@ -209,17 +213,10 @@ contextIOResultType Dictionary :: saveContext(DataStream &stream, ContextMode mo next = next->giveNext(); } - - // return result back - return CIO_OK; } -contextIOResultType Dictionary :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full node context (saves state variables, that completely describe -// current state) -// +void Dictionary :: restoreContext(DataStream &stream) { int size; int key; @@ -245,8 +242,6 @@ contextIOResultType Dictionary :: restoreContext(DataStream &stream, ContextMode this->at(key) = value; } - - return CIO_OK; } diff --git a/src/oofemlib/dictionary.h b/src/oofemlib/dictionary.h index 819d296ac..87e222283 100644 --- a/src/oofemlib/dictionary.h +++ b/src/oofemlib/dictionary.h @@ -85,12 +85,13 @@ class OOFEM_EXPORT Dictionary * @return Reference to value of pair with given key */ double &at(int aKey); + double at(int aKey) const; /** * Checks if dictionary includes given key * @param aKey Dictionary key. * @return True if receiver contains pair with given key, otherwise false. */ - bool includes(int aKey); + bool includes(int aKey) const; /// Prints the receiver on screen. void printYourself(); /// Formats itself as string. @@ -100,16 +101,14 @@ class OOFEM_EXPORT Dictionary /** * Saves the receiver contends (state) to given stream. - * @return contextIOResultType value. * @exception throws an ContextIOERR exception if error encountered */ - contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream); /** * Restores the receiver contents (state) from given stream. - * @return contextIOResultType value. * @exception throws an ContextIOERR exception if error encountered */ - contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void restoreContext(DataStream &stream); friend std :: ostream &operator << ( std :: ostream & out, const Dictionary & r ); }; diff --git a/src/oofemlib/dof.C b/src/oofemlib/dof.C index 3438b54f8..50549770c 100644 --- a/src/oofemlib/dof.C +++ b/src/oofemlib/dof.C @@ -78,7 +78,7 @@ void Dof :: printSingleOutputAt(FILE *File, TimeStep *tStep, char ch, ValueModeT // 'd') of the receiver, at tStep. { double x = scale * this->giveUnknown(mode, tStep); - fprintf(File, " dof %d %c % .8e\n", dofID, ch, x); + fprintf(File, " dof %-3d %c % .8e\n", dofID, ch, x); } void Dof :: printSingleOutputWithAdditionAt(FILE *File, TimeStep *tStep, char ch, ValueModeType mode, double addend) @@ -86,7 +86,7 @@ void Dof :: printSingleOutputWithAdditionAt(FILE *File, TimeStep *tStep, char ch // 'd') of the receiver, at tStep. { double x = addend + this->giveUnknown(mode, tStep); - fprintf(File, " dof %d %c % .8e\n", dofID, ch, x); + fprintf(File, " dof %-3d %c % .8e\n", dofID, ch, x); } void Dof :: printMultipleOutputAt(FILE *File, TimeStep *tStep, char *ch, @@ -132,20 +132,18 @@ Dof :: giveBcValue(ValueModeType mode, TimeStep *tStep) } } -contextIOResultType -Dof :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +Dof :: saveContext(DataStream &stream, ContextMode mode) { int _val = dofID; if ( !stream.write(_val) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -Dof :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +Dof :: restoreContext(DataStream &stream, ContextMode mode) { // restore dofid int _val; @@ -154,8 +152,6 @@ Dof :: restoreContext(DataStream &stream, ContextMode mode, void *obj) } dofID = ( DofIDItem ) _val; - - return CIO_OK; } void diff --git a/src/oofemlib/dof.h b/src/oofemlib/dof.h index b0f3987cb..58f1dd2f0 100644 --- a/src/oofemlib/dof.h +++ b/src/oofemlib/dof.h @@ -375,9 +375,9 @@ class OOFEM_EXPORT Dof /// Returns string for prepending output (used by error reporting macros). std :: string errorInfo(const char *func) const; /// Stores receiver state to output stream. - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); + virtual void saveContext(DataStream &stream, ContextMode mode); /// Restores the receiver state previously written in stream. - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + virtual void restoreContext(DataStream &stream, ContextMode mode); /// Overwrites the boundary condition id (0-inactive BC), intended for specific purposes such as coupling of bc's in multiscale simulations virtual void setBcId(int bcId) { } /// Overwrites the initial condition id (0-inactive IC) diff --git a/src/oofemlib/dofdistributedprimaryfield.C b/src/oofemlib/dofdistributedprimaryfield.C index fbffc46a3..555955ad4 100644 --- a/src/oofemlib/dofdistributedprimaryfield.C +++ b/src/oofemlib/dofdistributedprimaryfield.C @@ -48,8 +48,9 @@ namespace oofem { DofDistributedPrimaryField :: DofDistributedPrimaryField(EngngModel *a, int idomain, - FieldType ft, int nHist) : - PrimaryField(a, idomain, ft, nHist) + FieldType ft, int nHist, double alpha) : + PrimaryField(a, idomain, ft, nHist), + alpha(alpha) { } DofDistributedPrimaryField :: ~DofDistributedPrimaryField() @@ -65,6 +66,8 @@ DofDistributedPrimaryField :: giveUnknownValue(Dof *dof, ValueModeType mode, Tim double val0 = dof->giveUnknownsDictionaryValue(tStep->givePreviousStep(), VM_Total); if ( mode == VM_Velocity ) { return (val1 - val0) / tStep->giveTimeIncrement(); + } else if ( mode == VM_Intermediate || mode == VM_TotalIntrinsic ) { + return this->alpha * val1 + (1-this->alpha) * val0; } else if ( mode == VM_Incremental ) { return val1 - val0; } else { @@ -76,13 +79,6 @@ DofDistributedPrimaryField :: giveUnknownValue(Dof *dof, ValueModeType mode, Tim return 0.; } -FloatArray * -DofDistributedPrimaryField :: giveSolutionVector(TimeStep *tStep) -{ - //OOFEM_ERROR("This function should not be called. initialize and update should be used instead"); - return PrimaryField :: giveSolutionVector(tStep); -} - void DofDistributedPrimaryField :: initialize(ValueModeType mode, TimeStep *tStep, FloatArray &answer, const UnknownNumberingScheme &s) { @@ -129,51 +125,37 @@ DofDistributedPrimaryField :: initialize(ValueModeType mode, TimeStep *tStep, Fl } } -// project solutionVector to DoF unknowns dictionary + void DofDistributedPrimaryField :: update(ValueModeType mode, TimeStep *tStep, const FloatArray &vectorToStore, const UnknownNumberingScheme &s) { Domain *d = emodel->giveDomain(domainIndx); - for ( auto &node : d->giveDofManagers() ) { - for ( Dof *dof: *node ) { + auto set_values = [&mode, &tStep, &vectorToStore, &s](DofManager &dman) { + for ( Dof *dof: dman ) { if ( !dof->isPrimaryDof() ) continue; int eqNum = dof->giveEquationNumber(s); if ( eqNum > 0 ) { - dof->updateUnknownsDictionary(tStep, mode, vectorToStore.at(eqNum)); - } - ///@todo This should not be here / Mikael - if ( mode == VM_Total ) { - if ( dof->hasBc(tStep) ) { - dof->updateUnknownsDictionary(tStep, mode, dof->giveBcValue(VM_Total, tStep)); - } + dof->updateUnknownsDictionary(tStep, VM_Total, vectorToStore.at(eqNum)); } } + }; + + for ( auto &node : d->giveDofManagers() ) { + set_values(*node); } for ( auto &elem : d->giveElements() ) { int ndman = elem->giveNumberOfInternalDofManagers(); for ( int i = 1; i <= ndman; i++ ) { - for ( auto &dof : *elem->giveInternalDofManager(i) ) { - if ( !dof->isPrimaryDof() ) continue; - int eqNum = dof->giveEquationNumber(s); - if ( eqNum > 0 ) { - dof->updateUnknownsDictionary(tStep, mode, vectorToStore.at(eqNum)); - } - } + set_values(*elem->giveInternalDofManager(i)); } } for ( auto &bc : d->giveBcs() ) { int ndman = bc->giveNumberOfInternalDofManagers(); for ( int i = 1; i <= ndman; i++ ) { - for ( auto &dof : *bc->giveInternalDofManager(i) ) { - if ( !dof->isPrimaryDof() ) continue; - int eqNum = dof->giveEquationNumber(s); - if ( eqNum > 0 ) { - dof->updateUnknownsDictionary(tStep, mode, vectorToStore.at(eqNum)); - } - } + set_values(*bc->giveInternalDofManager(i)); } } } @@ -339,8 +321,6 @@ DofDistributedPrimaryField :: setInitialGuess(DofManager &dman, TimeStep *tStep, void DofDistributedPrimaryField :: advanceSolution(TimeStep *tStep) { - PrimaryField :: advanceSolution(tStep); -#if 0 // Copy over the old dictionary values to the new step as the initial guess: Domain *d = emodel->giveDomain(1); TimeStep *prev = tStep->givePreviousStep(); @@ -360,27 +340,13 @@ DofDistributedPrimaryField :: advanceSolution(TimeStep *tStep) for ( auto &bc : d->giveBcs() ) { int ndman = bc->giveNumberOfInternalDofManagers(); for ( int i = 1; i <= ndman; i++ ) { - if ( abc->giveInternalDofManager(i)->isNull() ) continue; + if ( bc->giveInternalDofManager(i)->isNull() ) continue; this->setInitialGuess(*bc->giveInternalDofManager(i), tStep, prev); } } // Apply dirichlet b.c.s - //this->applyBoundaryCondition(tStep); -#endif + this->applyBoundaryCondition(tStep); } - -contextIOResultType -DofDistributedPrimaryField :: saveContext(DataStream &stream, ContextMode mode) -{ - // all the job is done by dofs alone - return CIO_OK; -} - -contextIOResultType -DofDistributedPrimaryField :: restoreContext(DataStream &stream, ContextMode mode) -{ - return CIO_OK; -} } // end namespace oofem diff --git a/src/oofemlib/dofdistributedprimaryfield.h b/src/oofemlib/dofdistributedprimaryfield.h index bfd09ce9f..3f550ea0c 100644 --- a/src/oofemlib/dofdistributedprimaryfield.h +++ b/src/oofemlib/dofdistributedprimaryfield.h @@ -40,14 +40,24 @@ namespace oofem { /** * Class representing field of primary variables, which are typically allocated on nodes. - * The field is determined by DOF values stored in DOF repositories (unknown dictionary). - * These repositories are maintained and updated by engineering models since the algorithms are very specific to each model. - * The class can return several variables stored in DOF. The purpose of this class is to provide - * a shell that allows to access these repositories using field services. - * The class contains also a solution vector for temporal storage of unknowns. The vector needs to be projected back to DOFs. + * + * The class also handles the basic time integration, making it suitable for quasistatic problems. + * VM_Total is @$ x = x_n @$ + * VM_Intermediate is @$ x = \alpha x_n + (1-\alpha)x_{n-1} @$ + * VM_Incremental is @$ \delta x = x_n - x_{n-1} @$ + * VM_Velocity @$ \dot x = (x_n - x_{n-1}) / \delta t @$ + * Accelerations are not considered. + * + * Note that the physical unit(s) of x stems from the dof type. E.g. a viscous flow problem may have x be the velocity, + * and VM_Velocity is thus a fluid acceleration. + * + * Problem domains that require other types of time integration should overload this class. */ class OOFEM_EXPORT DofDistributedPrimaryField : public PrimaryField { +private: + double alpha; + public: /** * Constructor. Creates a field of given type associated to given domain. @@ -57,29 +67,33 @@ class OOFEM_EXPORT DofDistributedPrimaryField : public PrimaryField * @param a Engineering model which field belongs to. * @param idomain Index of domain for field. * @param ft Type of stored field. - * @param nHist Number of old time steps to store. + * @param nHist Number of old time steps to store (minimum 1). + * @param alpha Parameter for computing the interpolated intermediate value. */ - DofDistributedPrimaryField(EngngModel * a, int idomain, FieldType ft, int nHist); + DofDistributedPrimaryField(EngngModel * a, int idomain, FieldType ft, int nHist=2, double alpha=1.0); virtual ~DofDistributedPrimaryField(); - virtual void initialize(ValueModeType mode, TimeStep *tStep, FloatArray &answer, const UnknownNumberingScheme &s); + void initialize(ValueModeType mode, TimeStep *tStep, FloatArray &answer, const UnknownNumberingScheme &s) override; - virtual double giveUnknownValue(Dof *dof, ValueModeType mode, TimeStep *tStep); + double giveUnknownValue(Dof *dof, ValueModeType mode, TimeStep *tStep) override; - virtual void update(ValueModeType mode, TimeStep *tStep, const FloatArray &vectorToStore, const UnknownNumberingScheme &s); + void update(ValueModeType mode, TimeStep *tStep, const FloatArray &vectorToStore, const UnknownNumberingScheme &s) override; - virtual void applyDefaultInitialCondition(); + void applyDefaultInitialCondition() override; void applyInitialCondition(InitialCondition &ic); - virtual void applyBoundaryCondition(TimeStep *tStep); - virtual void applyBoundaryCondition(BoundaryCondition &bc, TimeStep *tStep); - virtual FloatArray *giveSolutionVector(TimeStep *tStep); + void applyBoundaryCondition(TimeStep *tStep) override; + void applyBoundaryCondition(BoundaryCondition &bc, TimeStep *tStep); + + FloatArray *giveSolutionVector(TimeStep *tStep) override { OOFEM_ERROR("DEPRECATED"); return nullptr; } void setInitialGuess(DofManager &dman, TimeStep *tStep, TimeStep *prev); - virtual void advanceSolution(TimeStep *tStep); + void advanceSolution(TimeStep *tStep) override; + + - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode); + void saveContext(DataStream &stream) override { } + void restoreContext(DataStream &stream) override { } }; } // end namespace oofem #endif // dofdistributedprimaryfield_h diff --git a/src/oofemlib/dofiditem.h b/src/oofemlib/dofiditem.h index a93892590..858eef490 100644 --- a/src/oofemlib/dofiditem.h +++ b/src/oofemlib/dofiditem.h @@ -10,7 +10,7 @@ * * OOFEM : Object Oriented Finite Element Code * - * Copyright (C) 1993 - 2013 Borek Patzak + * Copyright (C) 1993 - 2019 Borek Patzak * * * @@ -76,7 +76,33 @@ namespace oofem { ENUM_ITEM_WITH_VALUE(Trac_u, 28) /* Independent traction field in x-direction*/ \ ENUM_ITEM_WITH_VALUE(Trac_v, 29) /* Independent traction field in y-direction*/ \ ENUM_ITEM_WITH_VALUE(Trac_w, 30) /* Independent traction field in z-direction*/ \ - + \ + ENUM_ITEM_WITH_VALUE(E_xx, 31) /* Macroscopic strain component xx*/ \ + ENUM_ITEM_WITH_VALUE(E_yy, 32) /* Macroscopic strain component yy*/ \ + ENUM_ITEM_WITH_VALUE(E_zz, 33) /* Macroscopic strain component zz*/ \ + ENUM_ITEM_WITH_VALUE(E_yz, 34) /* Macroscopic strain component yz*/ \ + ENUM_ITEM_WITH_VALUE(E_zy, 35) /* Macroscopic strain component zy*/ \ + ENUM_ITEM_WITH_VALUE(E_xz, 36) /* Macroscopic strain component xz*/ \ + ENUM_ITEM_WITH_VALUE(E_zx, 37) /* Macroscopic strain component zx*/ \ + ENUM_ITEM_WITH_VALUE(E_xy, 38) /* Macroscopic strain component xy*/ \ + ENUM_ITEM_WITH_VALUE(E_yx, 39) /* Macroscopic strain component yx*/ \ + \ + ENUM_ITEM_WITH_VALUE(G_yz, 40) /* Macroscopic shear strain component xy (E_yz+E_zy)*/ \ + ENUM_ITEM_WITH_VALUE(G_xz, 41) /* Macroscopic shear strain component xz (E_xz+E_zx)*/ \ + ENUM_ITEM_WITH_VALUE(G_xy, 42) /* Macroscopic shear strain component xz (E_xz+E_zx)*/ \ +\ + ENUM_ITEM_WITH_VALUE(K_xx, 43) /* Macroscopic curvature component xx*/ \ + ENUM_ITEM_WITH_VALUE(K_yy, 44) /* Macroscopic curvature component yy*/ \ + ENUM_ITEM_WITH_VALUE(K_zz, 45) /* Macroscopic curvature component zz*/ \ + ENUM_ITEM_WITH_VALUE(K_yz, 46) /* Macroscopic curvature component yz*/ \ + ENUM_ITEM_WITH_VALUE(K_zy, 47) /* Macroscopic curvature component zy*/ \ + ENUM_ITEM_WITH_VALUE(K_zx, 48) /* Macroscopic curvature component zx*/ \ + ENUM_ITEM_WITH_VALUE(K_xy, 49) /* Macroscopic curvature component xy*/ \ + ENUM_ITEM_WITH_VALUE(K_yx, 50) /* Macroscopic curvature component yx*/ \ +\ + ENUM_ITEM_WITH_VALUE(S_u, 51) /* Macroscopic reinforcement slip field in x-direction */ \ + ENUM_ITEM_WITH_VALUE(S_v, 52) /* Macroscopic reinforcement slip field in y-direction */ \ + ENUM_ITEM_WITH_VALUE(S_w, 53) /* Macroscopic reinforcement slip field in z-direction */ \ /** * Type representing particular dof type. Values of this type describe the physical meaning of * available DOFs. diff --git a/src/oofemlib/dofmanager.C b/src/oofemlib/dofmanager.C index 9680bccfc..218c97e27 100644 --- a/src/oofemlib/dofmanager.C +++ b/src/oofemlib/dofmanager.C @@ -322,11 +322,9 @@ int DofManager :: giveNumberOfPrimaryMasterDofs(const IntArray &dofIDArray) cons } -IRResultType -DofManager :: initializeFrom(InputRecord *ir) +void +DofManager :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - delete dofidmask; dofidmask = NULL; delete dofTypemap; @@ -348,7 +346,7 @@ DofManager :: initializeFrom(InputRecord *ir) int dummy; IR_GIVE_OPTIONAL_FIELD(ir, dummy, "ndofs"); - if ( ir->hasField(_IFT_DofManager_dofidmask) ) { + if ( ir.hasField(_IFT_DofManager_dofidmask) ) { IR_GIVE_FIELD(ir, dofIDArry, _IFT_DofManager_dofidmask); this->dofidmask = new IntArray(dofIDArry); } else { @@ -370,7 +368,7 @@ DofManager :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, dofTypeMask, _IFT_DofManager_doftypemask); // read boundary flag - if ( ir->hasField(_IFT_DofManager_boundaryflag) ) { + if ( ir.hasField(_IFT_DofManager_boundaryflag) ) { isBoundaryFlag = true; } @@ -378,11 +376,11 @@ DofManager :: initializeFrom(InputRecord *ir) partitions.clear(); IR_GIVE_OPTIONAL_FIELD(ir, partitions, _IFT_DofManager_partitions); - if ( ir->hasField(_IFT_DofManager_sharedflag) ) { + if ( ir.hasField(_IFT_DofManager_sharedflag) ) { parallel_mode = DofManager_shared; - } else if ( ir->hasField(_IFT_DofManager_remoteflag) ) { + } else if ( ir.hasField(_IFT_DofManager_remoteflag) ) { parallel_mode = DofManager_remote; - } else if ( ir->hasField(_IFT_DofManager_nullflag) ) { + } else if ( ir.hasField(_IFT_DofManager_nullflag) ) { parallel_mode = DofManager_null; } else { parallel_mode = DofManager_local; @@ -450,8 +448,6 @@ DofManager :: initializeFrom(InputRecord *ir) } } } - - return IRRT_OK; } @@ -540,24 +536,16 @@ void DofManager :: updateYourself(TimeStep *tStep) } -contextIOResultType DofManager :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full node context (saves state variables, that completely describe -// current state) -// +void DofManager :: saveContext(DataStream &stream, ContextMode mode) { - int _val; - contextIOResultType iores; - - if ( ( iores = FEMComponent :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + FEMComponent :: saveContext(stream, mode); if ( mode & CM_Definition ) { if ( !stream.write(this->giveNumberOfDofs()) ) { THROW_CIOERR(CIO_IOERR); } + int _val; for ( auto &dof : *this ) { _val = dof->giveDofType(); if ( !stream.write(_val) ) { @@ -567,11 +555,10 @@ contextIOResultType DofManager :: saveContext(DataStream &stream, ContextMode mo if ( !stream.write(_val) ) { THROW_CIOERR(CIO_IOERR); } - if ( ( iores = dof->saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + dof->saveContext(stream, mode); } + contextIOResultType iores; if ( ( iores = loadArray.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -598,27 +585,17 @@ contextIOResultType DofManager :: saveContext(DataStream &stream, ContextMode mo } } else { for ( auto &dof : *this ) { - if ( ( iores = dof->saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + dof->saveContext(stream, mode); } } - - return CIO_OK; } -contextIOResultType DofManager :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full node context (saves state variables, that completely describe -// current state) -// +void DofManager :: restoreContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - if ( ( iores = FEMComponent :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + FEMComponent :: restoreContext(stream, mode); if ( mode & CM_Definition ) { int _numberOfDofs; @@ -639,9 +616,7 @@ contextIOResultType DofManager :: restoreContext(DataStream &stream, ContextMode THROW_CIOERR(CIO_IOERR); } Dof *dof = classFactory.createDof( ( dofType ) dtype, (DofIDItem)dofid, this ); - if ( ( iores = dof->restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + dof->restoreContext(stream, mode); this->appendDof(dof); } @@ -672,13 +647,9 @@ contextIOResultType DofManager :: restoreContext(DataStream &stream, ContextMode } } else { for ( auto &dof : this->dofArray ) { - if ( ( iores = dof->restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + dof->restoreContext(stream, mode); } } - - return CIO_OK; } diff --git a/src/oofemlib/dofmanager.h b/src/oofemlib/dofmanager.h index 92384b5e4..f7cfdd7b5 100644 --- a/src/oofemlib/dofmanager.h +++ b/src/oofemlib/dofmanager.h @@ -40,6 +40,7 @@ #include "femcmpnn.h" #include "intarray.h" +#include "floatarray.h" #include "valuemodetype.h" #include "doftype.h" #include "dofiditem.h" @@ -113,6 +114,9 @@ enum dofManagerParallelMode { class OOFEM_EXPORT DofManager : public FEMComponent { protected: + /// Array storing nodal coordinates. + FloatArray coordinates; + /// Array of DOFs. std::vector< Dof * > dofArray; /// List of applied loads. @@ -375,13 +379,22 @@ class OOFEM_EXPORT DofManager : public FEMComponent /**@name Position query functions */ //@{ - virtual bool hasCoordinates() { return false; } /// @return The i-th coordinate. - virtual double giveCoordinate(int i) { return 0.0; } + double giveCoordinate(int i) const { + if ( i > this->coordinates.giveSize() ) { + return 0.; + } + return this->coordinates.at(i); + } /// @return Pointer to node coordinate array. - virtual FloatArray *giveCoordinates() { return NULL; } + const FloatArray &giveCoordinates() const { return this->coordinates; } //@} + /// Set coordinates + void setCoordinates(const FloatArray &coords) { + this->coordinates = coords; + } + /**@name Functions necessary for dof creation. All optional. */ //@{ /** @@ -414,7 +427,7 @@ class OOFEM_EXPORT DofManager : public FEMComponent std :: map< int, int > *giveIcMap() { return dofICmap; } //@} - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; /** * Updates receiver after equilibrium in time step has been reached. * @param tStep Active time step. @@ -440,12 +453,12 @@ class OOFEM_EXPORT DofManager : public FEMComponent */ virtual bool giveMasterDofMans(IntArray &masters); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void printYourself(); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void printYourself() override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; /// Returns true if dof of given type is allowed to be associated to receiver virtual bool isDofTypeCompatible(dofType type) const { return false; } @@ -460,7 +473,7 @@ class OOFEM_EXPORT DofManager : public FEMComponent * these relations to reflect updated numbering. The renumbering function is passed, which is supposed * to return an updated number of specified entity type based on old number. */ - virtual void updateLocalNumbering(EntityRenumberingFunctor &f); + void updateLocalNumbering(EntityRenumberingFunctor &f) override; /**@name Advanced functions */ //@{ diff --git a/src/oofemlib/dofmanvalfield.C b/src/oofemlib/dofmanvalfield.C index 8edd90f7d..3b43d0636 100644 --- a/src/oofemlib/dofmanvalfield.C +++ b/src/oofemlib/dofmanvalfield.C @@ -36,72 +36,138 @@ #include "domain.h" #include "spatiallocalizer.h" #include "element.h" +#include "crosssection.h" #include "timestep.h" +#include "util.h" +#include "classfactory.h" #include "dofmanager.h" #include "feinterpol.h" +#include "problemmode.h" +#include "nodalrecoverymodel.h" +#include "vtkbaseexportmodule.h" +#include "octreelocalizer.h" + namespace oofem { -DofManValueField :: DofManValueField(FieldType ft, Domain *d) : Field(ft), dmanvallist() +DofManValueField::DofManValueField(FieldType ft, Domain *d) : Field(ft), dmanvallist() { int ndofman = d->giveNumberOfDofManagers(); this->domain = d; this->dmanvallist.resize(ndofman); } +DofManValueField::DofManValueField(FieldType ft, int nNodes, int nElements, const std::string engngModel = "transienttransport", const std::string domainDofsDefaults = "heattransfer") : Field(ft), dmanvallist() +{ + //ft FieldType::FT_Unknown + this->eModel = classFactory.createEngngModel(engngModel.c_str(), 1, NULL); + if ( !this->eModel ) { + OOFEM_ERROR("Couldn't create EngngModel\n"); + } + eModel->Instanciate_init();//create one domain + this->domain = eModel->giveDomain(1); + this->domain->resolveDomainDofsDefaults(domainDofsDefaults.c_str() ); + this->domain->dofManagerList.clear(); + this->domain->dofManagerList.resize(nNodes); + dmanvallist.resize(nNodes); + this->domain->elementList.clear(); + this->domain->elementList.resize(nElements); + this->crossSect = classFactory.createCrossSection("emptycs", 1, this->domain);//create one dummy cross-section + this->domain->crossSectionList.clear(); + this->domain->crossSectionList.resize(1); + this->domain->crossSectionList[0] = std::move(this->crossSect); + std::unique_ptr< SpatialLocalizer > spatialLocalizer; + spatialLocalizer = std::make_unique(this->domain); + spatialLocalizer->init(); + this->domain->setSpatialLocalizer(std::move(spatialLocalizer)); +} + + +void DofManValueField::addNode(int i, const FloatArray &coords) { + std::unique_ptr< DofManager >dman(classFactory.createDofManager("node", i, eModel->giveDomain(1) ) ); + if ( !dman ) { + OOFEM_ERROR("Couldn't create node %d\n", i); + } + dman->setCoordinates(coords); + dman->setGlobalNumber(i); + this->domain->dofManagerList [ i - 1 ] = std::move(dman); +} + + +void +DofManValueField::addElement(int i, const char *name, const IntArray &nodes) { + std::unique_ptr< Element >elem(classFactory.createElement(name, i, this->domain) ); + if ( !elem ) { + OOFEM_ERROR("Couldn't create element %d: %s\n", i, name); + } + + elem->setDofManagers(nodes); + elem->setGlobalNumber(i); + elem->setCrossSection(1); + this->domain->elementList [ i - 1 ] = std::move(elem); +} + + int -DofManValueField :: evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) +DofManValueField::evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) { int result = 0; // assume ok FloatArray lc, n; - + answer.resize(0); + // request element containing target point Element *elem = this->domain->giveSpatialLocalizer()->giveElementContainingPoint(coords); if ( elem ) { // ok element containing target point found FEInterpolation *interp = elem->giveInterpolation(); if ( interp ) { // map target point to element local coordinates - if ( interp->global2local( lc, coords, FEIElementGeometryWrapper(elem) ) ) { + if ( interp->global2local(lc, coords, FEIElementGeometryWrapper(elem) ) ) { // evaluate interpolation functions at target point - interp->evalN( n, lc, FEIElementGeometryWrapper(elem) ); + interp->evalN(n, lc, FEIElementGeometryWrapper(elem) ); // loop over element nodes for ( int i = 1; i <= n.giveSize(); i++ ) { // multiply nodal value by value of corresponding shape function and add this to answer - answer.add( n.at(i), this->dmanvallist[elem->giveDofManagerNumber(i)-1] ); + answer.add(n.at(i), this->dmanvallist [ elem->giveDofManagerNumber(i) - 1 ]); } } else { // mapping from global to local coordinates failed + OOFEM_ERROR("Error in mapping from global to local coordinates\n"); result = 1; // failed } } else { // element without interpolation + OOFEM_ERROR("Error in element without interpolation\n"); result = 1; // failed } } else { // no element containing given point found + OOFEM_ERROR("Point out of defined elements\n"); result = 1; // failed } return result; } + int -DofManValueField :: evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) +DofManValueField::evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) { - answer = this->dmanvallist[dman->giveNumber()-1]; + answer = this->dmanvallist [ dman->giveNumber() - 1 ]; return 1; } void -DofManValueField :: setDofManValue(int dofMan, FloatArray value) +DofManValueField::setDofManValue(int dofMan, FloatArray value) { - this->dmanvallist[dofMan-1] = std :: move(value); + this->dmanvallist [ dofMan - 1 ] = std::move(value); } -contextIOResultType -DofManValueField :: saveContext(DataStream &stream, ContextMode mode) +const FloatArray &DofManValueField::getNodeCoordinates(int i) { - return CIO_OK; + return this->domain->dofManagerList [ i - 1 ]->giveCoordinates(); } -contextIOResultType -DofManValueField :: restoreContext(DataStream &stream, ContextMode mode) -{ - return CIO_OK; -} + +void +DofManValueField::saveContext(DataStream &stream) +{} + +void +DofManValueField::restoreContext(DataStream &stream) +{} } // end namespace oofem diff --git a/src/oofemlib/dofmanvalfield.h b/src/oofemlib/dofmanvalfield.h index 7872360b9..2cff9a502 100644 --- a/src/oofemlib/dofmanvalfield.h +++ b/src/oofemlib/dofmanvalfield.h @@ -36,9 +36,24 @@ #define dofmanvalfield_h #include "field.h" - +#include "elementgeometrytype.h" +#include "error.h" +#include "engngm.h" +#include "domain.h" #include +#include "internalstatetype.h" +#include "intarray.h" +#include "materialmappingalgorithm.h" +#include "mmashapefunctprojection.h" +#include "cltypes.h" + +#ifdef _PYBIND_BINDINGS + #include + #include //Conversion for lists + namespace py = pybind11; +#endif + namespace oofem { class Domain; @@ -46,7 +61,9 @@ class Domain; * Class representing field defined by nodal values associated to given domain. * Field represent the spatial distribution of certain variable. * The implementation allows to set individual dofMan values; - * However, in the current implementation doe not allow to specify values for different time steps. + * However, in the current implementation does not allow to specify values for different time steps. + * It is also possible to create a separate, virtual domain by adding particular + * nodes and elements with nodal values. */ class OOFEM_EXPORT DofManValueField : public Field { @@ -55,23 +72,37 @@ class OOFEM_EXPORT DofManValueField : public Field Domain *domain; /// Array of dofman values std::vector< FloatArray >dmanvallist; + /// Pointer to engineering model + std::unique_ptr< EngngModel >eModel; + /// Pointer to single cross-section; + std::unique_ptr< CrossSection >crossSect; public: /** * Constructor. Creates an empty field of given type associated to given domain. */ - DofManValueField(FieldType b, Domain * d); + DofManValueField(FieldType ft, Domain *d); + + /** + * Constructor. Creates a virtual empty domain which needs to be populated + * by nodes, elements and nodal values. + */ + + DofManValueField(FieldType ft, int nNodes, int nElements, const std::string engngModel, const std::string domainDofsDefaults); + virtual ~DofManValueField() { } + /** - * Evaluates the field at given point. - * @param coords Coordinates of the point of interest - * @param answer Field evaluated at coordinate. - * @param tStep Time step to evaluate for. - * @param mode Mode of value (total, velocity,...). - * @return Zero if ok, otherwise nonzero. + * Add node to the domain */ - virtual int evaluateAt(FloatArray &answer, const FloatArray &coords, - ValueModeType mode, TimeStep *tStep); + void addNode(int i, const FloatArray &coords); + + /** + * Add element to the domain + */ + void addElement(int i, const char *name, const IntArray &nodes); + + int evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) override; /** * Evaluates the field at given DofManager. This potentially can be resolved quickly, as @@ -84,39 +115,27 @@ class OOFEM_EXPORT DofManValueField : public Field * @param[out] answer Evaluated field for dman. * @param dman Reference to dof manager. * @param mode Mode of value (total, velocity,...). - * @param tStep Time step to evaluate for. + * @param tStep TimInternalStateType valID, IntArray regions, TimeStep *tStepe step to evaluate for. * @return Zero if ok, nonzero Error code (0-ok, 1-failed) */ - virtual int evaluateAt(FloatArray &answer, DofManager *dman, - ValueModeType mode, TimeStep *tStep); + int evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) override; /** - * Stores receiver state to output stream. - * Writes the FEMComponent class-id in order to allow test whether correct data are then restored. - * @param stream Output stream. - * @param mode Determines amount of info in stream (state, definition,...). - * @return contextIOResultType. - * @exception Throws an ContextIOERR exception if error encountered. - */ - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - /** - * Restores the receiver state previously written in stream. - * Reads the FEMComponent class-id in order to allow test consistency. - * @param stream Input stream. - * @param mode Determines amount of info in stream (state, definition,...). - * @return contextIOResultType. - * @exception Throws an ContextIOERR exception if error encountered. + * Sets the value associated to given dofManager */ - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode); - + void setDofManValue(int dofMan, FloatArray value); /** - * Sets the value associated to given dofManager + * Obtain coordinates of a node */ - void setDofManValue(int dofMan, FloatArray value); + const FloatArray &getNodeCoordinates(int i); + + void saveContext(DataStream &stream) override; + void restoreContext(DataStream &stream) override; - /// @return Class name of the receiver. - virtual const char *giveClassName() const { return "DofManValueField"; } + const char *giveClassName() const override { + return "DofManValueField"; + } }; } // end namespace oofem #endif // dofmanvalfield_h diff --git a/src/oofemlib/domain.C b/src/oofemlib/domain.C index f28244587..18eac9a80 100644 --- a/src/oofemlib/domain.C +++ b/src/oofemlib/domain.C @@ -51,7 +51,6 @@ #include "connectivitytable.h" #include "outputmanager.h" #include "octreelocalizer.h" -#include "datareader.h" #include "nodalrecoverymodel.h" #include "nonlocalbarrier.h" #include "classfactory.h" @@ -61,9 +60,8 @@ #include "errorestimator.h" #include "range.h" #include "fracturemanager.h" -#include "dynamicinputrecord.h" -#include "dynamicdatareader.h" #include "datareader.h" +#include "oofemtxtdatareader.h" #include "initmodulemanager.h" #include "exportmodulemanager.h" #include "xfem/enrichmentitem.h" @@ -97,9 +95,7 @@ Domain :: Domain(int n, int serNum, EngngModel *e) : defaultNodeDofIDArry(), // Constructor. Creates a new domain. { if ( !e->giveSuppressOutput() ) { - outputManager = std::unique_ptr (new OutputManager(this) ); - } else { - outputManager = NULL; + outputManager = std::make_unique(this); } this->engineeringModel = e; @@ -127,8 +123,8 @@ Domain :: clear() // Clear receiver { elementList.clear(); - mElementPlaceInArray.clear(); - mDofManPlaceInArray.clear(); + elementGlobal2LocalMap.clear(); + dofmanGlobal2LocalMap.clear(); dofManagerList.clear(); materialList.clear(); bcList.clear(); @@ -137,23 +133,23 @@ Domain :: clear() crossSectionList.clear(); nonlocalBarrierList.clear(); setList.clear(); - xfemManager.reset(NULL); - contactManager.reset(NULL); + xfemManager = nullptr; + contactManager = nullptr; if ( connectivityTable ) { connectivityTable->reset(); } - spatialLocalizer.reset(NULL); + spatialLocalizer = nullptr; if ( smoother ) { smoother->clear(); } ///@todo bp: how to clear/reset topology data? - topology.reset(NULL); + topology = nullptr; #ifdef __PARALLEL_MODE - transactionManager.reset(NULL); + transactionManager = nullptr; #endif } @@ -184,9 +180,9 @@ Domain :: giveGlobalElement(int n) int Domain :: giveElementPlaceInArray(int iGlobalElNum) const { - auto res = mElementPlaceInArray.find(iGlobalElNum); + auto res = elementGlobal2LocalMap.find(iGlobalElNum); - if ( res != mElementPlaceInArray.end() ) { + if ( res != elementGlobal2LocalMap.end() ) { return res->second; } else { OOFEM_ERROR("returning -1 for iGlobalElNum: %d.", iGlobalElNum ); @@ -197,9 +193,9 @@ Domain :: giveElementPlaceInArray(int iGlobalElNum) const int Domain :: giveDofManPlaceInArray(int iGlobalDofManNum) const { - auto res = mDofManPlaceInArray.find(iGlobalDofManNum); + auto res = dofmanGlobal2LocalMap.find(iGlobalDofManNum); - if ( res != mDofManPlaceInArray.end() ) { + if ( res != dofmanGlobal2LocalMap.end() ) { return res->second; } else { OOFEM_ERROR("returning -1 for iGlobalDofManNum: %d.", iGlobalDofManNum ); @@ -210,9 +206,9 @@ Domain :: giveDofManPlaceInArray(int iGlobalDofManNum) const const IntArray & Domain :: giveElementsWithMaterialNum(int iMaterialNum) const { - auto res = mMapMaterialNum2El.find(iMaterialNum); + auto res = materialNum2ElMap.find(iMaterialNum); - if ( res != mMapMaterialNum2El.end() ) { + if ( res != materialNum2ElMap.end() ) { return res->second; } else { OOFEM_ERROR("Material not found.") @@ -453,42 +449,49 @@ void Domain :: resizeInitialConditions(int _newSize) { icList.resize(_newSize); void Domain :: resizeFunctions(int _newSize) { functionList.resize(_newSize); } void Domain :: resizeSets(int _newSize) { setList.resize(_newSize); } -void Domain :: setDofManager(int i, DofManager *obj) { dofManagerList[i-1].reset(obj); mDofManPlaceInArray[obj->giveGlobalNumber()] = i;} -void Domain :: setElement(int i, Element *obj) { elementList[i-1].reset(obj); mElementPlaceInArray[obj->giveGlobalNumber()] = i;} -void Domain :: setCrossSection(int i, CrossSection *obj) { crossSectionList[i-1].reset(obj); } -void Domain :: setMaterial(int i, Material *obj) { materialList[i-1].reset(obj); } -void Domain :: setNonlocalBarrier(int i, NonlocalBarrier *obj) { nonlocalBarrierList[i-1].reset(obj); } -void Domain :: setBoundaryCondition(int i, GeneralBoundaryCondition *obj) { bcList[i-1].reset(obj); } -void Domain :: setInitialCondition(int i, InitialCondition *obj) { icList[i-1].reset(obj); } -void Domain :: setFunction(int i, Function *obj) { functionList[i-1].reset(obj); } -void Domain :: setSet(int i, Set *obj) { setList[i-1].reset(obj); } -void Domain :: setXfemManager(XfemManager *ipXfemManager) { xfemManager.reset(ipXfemManager); } +void Domain :: py_setDofManager(int i, DofManager *obj) { dofManagerList[i-1].reset(obj); dofmanGlobal2LocalMap[obj->giveGlobalNumber()] = i;} +void Domain :: py_setElement(int i, Element *obj) { elementList[i-1].reset(obj); elementGlobal2LocalMap[obj->giveGlobalNumber()] = i;} +void Domain :: py_setCrossSection(int i, CrossSection *obj) { crossSectionList[i-1].reset(obj); } +void Domain :: py_setMaterial(int i, Material *obj) { materialList[i-1].reset(obj); } +void Domain :: py_setNonlocalBarrier(int i, NonlocalBarrier *obj) { nonlocalBarrierList[i-1].reset(obj); } +void Domain :: py_setBoundaryCondition(int i, GeneralBoundaryCondition *obj) { bcList[i-1].reset(obj); } +void Domain :: py_setInitialCondition(int i, InitialCondition *obj) { icList[i-1].reset(obj); } +void Domain :: py_setFunction(int i, Function *obj) { functionList[i-1].reset(obj); } +void Domain :: py_setSet(int i, Set *obj) { setList[i-1].reset(obj); } + +void Domain :: setDofManager(int i, std::unique_ptr obj) { dofmanGlobal2LocalMap[obj->giveGlobalNumber()] = i; dofManagerList[i-1] = std::move(obj); } +void Domain :: setElement(int i, std::unique_ptr obj) { materialNum2ElMap[obj->giveGlobalNumber()] = i; elementList[i-1] = std::move(obj); } +void Domain :: setCrossSection(int i, std::unique_ptr obj) { crossSectionList[i-1] = std::move(obj); } +void Domain :: setMaterial(int i, std::unique_ptr obj) { materialList[i-1] = std::move(obj); } +void Domain :: setNonlocalBarrier(int i, std::unique_ptr obj) { nonlocalBarrierList[i-1] = std::move(obj); } +void Domain :: setBoundaryCondition(int i, std::unique_ptr obj) { bcList[i-1] = std::move(obj); } +void Domain :: setInitialCondition(int i, std::unique_ptr obj) { icList[i-1] = std::move(obj); } +void Domain :: setFunction(int i, std::unique_ptr obj) { functionList[i-1] = std::move(obj); } +void Domain :: setSet(int i, std::unique_ptr obj) { setList[i-1] = std::move(obj); } +void Domain :: setXfemManager(std::unique_ptr obj) { xfemManager = std::move(obj); } void Domain :: clearBoundaryConditions() { bcList.clear(); } void Domain :: clearElements() { elementList.clear(); } int -Domain :: instanciateYourself(DataReader *dr) +Domain :: instanciateYourself(DataReader &dr) // Creates all objects mentioned in the data file. { - IRResultType result; // Required by IR_GIVE_FIELD macro - int num; std :: string name, topologytype; int nnode, nelem, nmat, nload, nic, nloadtimefunc, ncrossSections, nbarrier = 0, nset = 0; bool nxfemman = false; bool ncontactman = false; bool nfracman = false; - //XfemManager *xMan; - // mapping from label to local numbers for dofmans and elements - std :: map< int, int >dofManLabelMap, elemLabelMap; // read type of Domain to be solved - InputRecord *ir = dr->giveInputRecord(DataReader :: IR_domainRec, 1); - IR_GIVE_FIELD(ir, name, _IFT_Domain_type); // This is inconsistent, "domain" isn't exactly a field, but the actual record keyword. + { + auto &ir = dr.giveInputRecord(DataReader :: IR_domainRec, 1); + IR_GIVE_FIELD(ir, name, _IFT_Domain_type); // This is inconsistent, "domain" isn't exactly a field, but the actual record keyword. - mDomainType = name; + mDomainType = name; - ir->finish(); + ir.finish(); + } # ifdef VERBOSE VERBOSE_PRINT0("Instanciating domain ", this->number); @@ -497,34 +500,37 @@ Domain :: instanciateYourself(DataReader *dr) resolveDomainDofsDefaults( name.c_str() ); // read output manager record - std :: string tmp; - ir = dr->giveInputRecord(DataReader :: IR_outManRec, 1); - ir->giveRecordKeywordField(tmp); + { + std :: string tmp; + auto &ir = dr.giveInputRecord(DataReader :: IR_outManRec, 1); + ir.giveRecordKeywordField(tmp); - if(!giveEngngModel()->giveSuppressOutput()) { - outputManager->initializeFrom(ir); + if ( !giveEngngModel()->giveSuppressOutput() ) { + outputManager->initializeFrom(ir); + } + ir.finish(); } - ir->finish(); - // read domain description - ir = dr->giveInputRecord(DataReader :: IR_domainCompRec, 1); - IR_GIVE_FIELD(ir, nnode, _IFT_Domain_ndofman); - IR_GIVE_FIELD(ir, nelem, _IFT_Domain_nelem); - IR_GIVE_FIELD(ir, ncrossSections, _IFT_Domain_ncrosssect); - IR_GIVE_FIELD(ir, nmat, _IFT_Domain_nmat); - IR_GIVE_FIELD(ir, nload, _IFT_Domain_nbc); - IR_GIVE_FIELD(ir, nic, _IFT_Domain_nic); - IR_GIVE_FIELD(ir, nloadtimefunc, _IFT_Domain_nfunct); - IR_GIVE_OPTIONAL_FIELD(ir, nset, _IFT_Domain_nset); - IR_GIVE_OPTIONAL_FIELD(ir, nxfemman, _IFT_Domain_nxfemman); - IR_GIVE_OPTIONAL_FIELD(ir, ncontactman, _IFT_Domain_ncontactman); - IR_GIVE_OPTIONAL_FIELD(ir, topologytype, _IFT_Domain_topology); - this->nsd = -1; ///@todo Change this to default 0 when the domaintype record has been removed. - IR_GIVE_OPTIONAL_FIELD(ir, this->nsd, _IFT_Domain_numberOfSpatialDimensions); - this->axisymm = ir->hasField(_IFT_Domain_axisymmetric); - IR_GIVE_OPTIONAL_FIELD(ir, nfracman, _IFT_Domain_nfracman); - IR_GIVE_OPTIONAL_FIELD(ir, nbarrier, _IFT_Domain_nbarrier); + { + auto &ir = dr.giveInputRecord(DataReader :: IR_domainCompRec, 1); + IR_GIVE_FIELD(ir, nnode, _IFT_Domain_ndofman); + IR_GIVE_FIELD(ir, nelem, _IFT_Domain_nelem); + IR_GIVE_FIELD(ir, ncrossSections, _IFT_Domain_ncrosssect); + IR_GIVE_FIELD(ir, nmat, _IFT_Domain_nmat); + IR_GIVE_FIELD(ir, nload, _IFT_Domain_nbc); + IR_GIVE_FIELD(ir, nic, _IFT_Domain_nic); + IR_GIVE_FIELD(ir, nloadtimefunc, _IFT_Domain_nfunct); + IR_GIVE_OPTIONAL_FIELD(ir, nset, _IFT_Domain_nset); + IR_GIVE_OPTIONAL_FIELD(ir, nxfemman, _IFT_Domain_nxfemman); + IR_GIVE_OPTIONAL_FIELD(ir, ncontactman, _IFT_Domain_ncontactman); + IR_GIVE_OPTIONAL_FIELD(ir, topologytype, _IFT_Domain_topology); + this->nsd = -1; ///@todo Change this to default 0 when the domaintype record has been removed. + IR_GIVE_OPTIONAL_FIELD(ir, this->nsd, _IFT_Domain_numberOfSpatialDimensions); + this->axisymm = ir.hasField(_IFT_Domain_axisymmetric); + IR_GIVE_OPTIONAL_FIELD(ir, nfracman, _IFT_Domain_nfracman); + IR_GIVE_OPTIONAL_FIELD(ir, nbarrier, _IFT_Domain_nbarrier); + } ///@todo Eventually remove this backwards compatibility: //_HeatTransferMode _HeatMass1Mode // Are these deprecated? @@ -544,7 +550,7 @@ Domain :: instanciateYourself(DataReader *dr) dofManagerList.clear(); dofManagerList.resize(nnode); for ( int i = 1; i <= nnode; i++ ) { - ir = dr->giveInputRecord(DataReader :: IR_dofmanRec, i); + auto &ir = dr.giveInputRecord(DataReader :: IR_dofmanRec, i); // read type of dofManager IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); @@ -556,17 +562,10 @@ Domain :: instanciateYourself(DataReader *dr) } dman->initializeFrom(ir); - if ( dofManLabelMap.find(num) == dofManLabelMap.end() ) { - // label does not exist yet - dofManLabelMap [ num ] = i; - } else { - OOFEM_ERROR("iDofmanager entry already exist (label=%d)", num); - } - dman->setGlobalNumber(num); // set label dofManagerList[i - 1] = std :: move(dman); - ir->finish(); + ir.finish(); } # ifdef VERBOSE @@ -579,7 +578,7 @@ Domain :: instanciateYourself(DataReader *dr) elementList.clear(); elementList.resize(nelem); for ( int i = 1; i <= nelem; i++ ) { - ir = dr->giveInputRecord(DataReader :: IR_elemRec, i); + auto &ir = dr.giveInputRecord(DataReader :: IR_elemRec, i); // read type of element IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); @@ -589,32 +588,24 @@ Domain :: instanciateYourself(DataReader *dr) } elem->initializeFrom(ir); - - if ( elemLabelMap.find(num) == elemLabelMap.end() ) { - // label does not exist yet - elemLabelMap [ num ] = i; - } else { - OOFEM_ERROR("Element entry already exist (label=%d)", num); - } - elem->setGlobalNumber(num); elementList[i - 1] = std :: move(elem); - ir->finish(); + ir.finish(); } BuildElementPlaceInArrayMap(); // Support sets defined directly after the elements (special hack for backwards compatibility). setList.clear(); - if ( dr->peakNext("set") ) { + if ( dr.peakNext("set") ) { setList.resize(nset); for ( int i = 1; i <= nset; i++ ) { - ir = dr->giveInputRecord(DataReader :: IR_setRec, i); + auto &ir = dr.giveInputRecord(DataReader :: IR_setRec, i); // read type of set IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); // Only one set for now (i don't see any need to ever introduce any other version) - std :: unique_ptr< Set > set(new Set(num, this)); //classFactory.createSet(name.c_str(), num, this) + std::unique_ptr< Set > set = std::make_unique(num, this); //classFactory.createSet(name.c_str(), num, this) if ( !set ) { OOFEM_ERROR("Couldn't create set: %s", name.c_str()); } @@ -632,7 +623,7 @@ Domain :: instanciateYourself(DataReader *dr) OOFEM_ERROR("Set entry already exist (num=%d)", num); } - ir->finish(); + ir.finish(); } } @@ -644,7 +635,7 @@ Domain :: instanciateYourself(DataReader *dr) crossSectionList.clear(); crossSectionList.resize(ncrossSections); for ( int i = 1; i <= ncrossSections; i++ ) { - ir = dr->giveInputRecord(DataReader :: IR_crosssectRec, i); + auto &ir = dr.giveInputRecord(DataReader :: IR_crosssectRec, i); IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); std :: unique_ptr< CrossSection >crossSection( classFactory.createCrossSection(name.c_str(), num, this) ); @@ -665,7 +656,7 @@ Domain :: instanciateYourself(DataReader *dr) OOFEM_ERROR("crossSection entry already exist (num=%d)", num); } - ir->finish(); + ir.finish(); } # ifdef VERBOSE @@ -676,7 +667,7 @@ Domain :: instanciateYourself(DataReader *dr) materialList.clear(); materialList.resize(nmat); for ( int i = 1; i <= nmat; i++ ) { - ir = dr->giveInputRecord(DataReader :: IR_matRec, i); + auto &ir = dr.giveInputRecord(DataReader :: IR_matRec, i); // read type of material IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); @@ -698,7 +689,7 @@ Domain :: instanciateYourself(DataReader *dr) OOFEM_ERROR("material entry already exist (num=%d)", num); } - ir->finish(); + ir.finish(); } # ifdef VERBOSE @@ -709,7 +700,7 @@ Domain :: instanciateYourself(DataReader *dr) nonlocalBarrierList.clear(); nonlocalBarrierList.resize(nbarrier); for ( int i = 1; i <= nbarrier; i++ ) { - ir = dr->giveInputRecord(DataReader :: IR_nlocBarRec, i); + auto &ir = dr.giveInputRecord(DataReader :: IR_nlocBarRec, i); // read type of load IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); @@ -731,7 +722,7 @@ Domain :: instanciateYourself(DataReader *dr) OOFEM_ERROR("barrier entry already exist (num=%d)", num); } - ir->finish(); + ir.finish(); } # ifdef VERBOSE @@ -744,7 +735,7 @@ Domain :: instanciateYourself(DataReader *dr) bcList.clear(); bcList.resize(nload); for ( int i = 1; i <= nload; i++ ) { - ir = dr->giveInputRecord(DataReader :: IR_bcRec, i); + auto &ir = dr.giveInputRecord(DataReader :: IR_bcRec, i); // read type of bc IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); @@ -766,7 +757,7 @@ Domain :: instanciateYourself(DataReader *dr) OOFEM_ERROR("boundary condition entry already exist (num=%d)", num); } - ir->finish(); + ir.finish(); } # ifdef VERBOSE @@ -777,7 +768,7 @@ Domain :: instanciateYourself(DataReader *dr) icList.clear(); icList.resize(nic); for ( int i = 1; i <= nic; i++ ) { - ir = dr->giveInputRecord(DataReader :: IR_icRec, i); + auto &ir = dr.giveInputRecord(DataReader :: IR_icRec, i); // read type of load IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); @@ -799,7 +790,7 @@ Domain :: instanciateYourself(DataReader *dr) OOFEM_ERROR("initial condition entry already exist (num=%d)", num); } - ir->finish(); + ir.finish(); } # ifdef VERBOSE @@ -811,7 +802,7 @@ Domain :: instanciateYourself(DataReader *dr) functionList.clear(); functionList.resize(nloadtimefunc); for ( int i = 1; i <= nloadtimefunc; i++ ) { - ir = dr->giveInputRecord(DataReader :: IR_funcRec, i); + auto &ir = dr.giveInputRecord(DataReader :: IR_funcRec, i); // read type of func IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); @@ -833,7 +824,7 @@ Domain :: instanciateYourself(DataReader *dr) OOFEM_ERROR("Function entry already exist (num=%d)", num); } - ir->finish(); + ir.finish(); } # ifdef VERBOSE @@ -844,11 +835,11 @@ Domain :: instanciateYourself(DataReader *dr) if ( setList.size() == 0 ) { setList.resize(nset); for ( int i = 1; i <= nset; i++ ) { - ir = dr->giveInputRecord(DataReader :: IR_setRec, i); + auto &ir = dr.giveInputRecord(DataReader :: IR_setRec, i); // read type of set IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); // Only one set for now (i don't see any need to ever introduce any other version) - std :: unique_ptr< Set > set(new Set(num, this)); //classFactory.createSet(name.c_str(), num, this) + std :: unique_ptr< Set > set = std::make_unique(num, this); //classFactory.createSet(name.c_str(), num, this) if ( !set ) { OOFEM_ERROR("Couldn't create set: %s", name.c_str()); } @@ -866,7 +857,7 @@ Domain :: instanciateYourself(DataReader *dr) OOFEM_ERROR("Set entry already exist (num=%d)", num); } - ir->finish(); + ir.finish(); } } @@ -877,10 +868,10 @@ Domain :: instanciateYourself(DataReader *dr) # endif if ( nxfemman ) { - ir = dr->giveInputRecord(DataReader :: IR_xfemManRec, 1); + auto &ir = dr.giveInputRecord(DataReader :: IR_xfemManRec, 1); IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); - xfemManager.reset( classFactory.createXfemManager(name.c_str(), this) ); + xfemManager = classFactory.createXfemManager(name.c_str(), this); if ( !xfemManager ) { OOFEM_ERROR("Couldn't create xfemmanager: %s", name.c_str()); } @@ -895,10 +886,10 @@ Domain :: instanciateYourself(DataReader *dr) if ( ncontactman ) { // don't read any input yet - ir = dr->giveInputRecord(DataReader :: IR_contactManRec, 1); + auto &ir = dr.giveInputRecord(DataReader :: IR_contactManRec, 1); IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); - contactManager.reset( classFactory.createContactManager(name.c_str(), this) ); + contactManager = classFactory.createContactManager(name.c_str(), this); if ( !contactManager ) { OOFEM_ERROR("Couldn't create contact manager: %s", name.c_str()); } @@ -915,7 +906,7 @@ Domain :: instanciateYourself(DataReader *dr) this->topology = NULL; if ( topologytype.length() > 0 ) { - this->topology.reset( classFactory.createTopology(topologytype.c_str(), this) ); + this->topology = classFactory.createTopology(topologytype.c_str(), this); if ( !this->topology ) { OOFEM_ERROR("Couldn't create topology of type '%s'", topologytype.c_str()); } @@ -928,8 +919,8 @@ Domain :: instanciateYourself(DataReader *dr) if ( nfracman ) { - ir = dr->giveInputRecord(DataReader :: IR_fracManRec, 1); - fracManager.reset( new FractureManager(this) ); + auto &ir = dr.giveInputRecord(DataReader :: IR_fracManRec, 1); + fracManager = std::make_unique(this); fracManager->initializeFrom(ir); fracManager->instanciateYourself(dr); # ifdef VERBOSE @@ -938,7 +929,7 @@ Domain :: instanciateYourself(DataReader *dr) } // change internal component references from labels to assigned local numbers - MapBasedEntityRenumberingFunctor labelToLocNumFunctor(dofManLabelMap, elemLabelMap); + MapBasedEntityRenumberingFunctor labelToLocNumFunctor(dofmanGlobal2LocalMap, elementGlobal2LocalMap); for ( auto &dman: this->dofManagerList ) { dman->updateLocalNumbering(labelToLocNumFunctor); } @@ -974,6 +965,17 @@ Domain :: postInitialize() } } + { + spatialLocalizer = std::make_unique(this); + spatialLocalizer->init(); + connectivityTable = std::make_unique(this); + OOFEM_LOG_INFO("Spatial localizer init done\n"); + } + + if ( this->hasXfemManager() ) { + this->giveXfemManager()->postInitialize(); + } + // Dofs must be created before dof managers due their post-initialization: this->createDofs(); @@ -981,9 +983,6 @@ Domain :: postInitialize() dman->postInitialize(); } - if ( this->hasXfemManager() ) { - //this->giveXfemManager()->postInitialize(); - } for ( auto &el: elementList ) { el->postInitialize(); @@ -992,6 +991,8 @@ Domain :: postInitialize() for ( auto &bc: bcList ) { bc->postInitialize(); } + + } @@ -1175,7 +1176,8 @@ Domain :: giveConnectivityTable() // { if ( !connectivityTable ) { - connectivityTable.reset( new ConnectivityTable(this) ); + //connectivityTable = std::make_unique(this); + OOFEM_LOG_ERROR("Connectivity table init error"); } return connectivityTable.get(); @@ -1188,13 +1190,17 @@ Domain :: giveSpatialLocalizer() // return connectivity Table - if no defined - creates new one // { - // if (spatialLocalizer == NULL) spatialLocalizer = new DummySpatialLocalizer(1, this); - if ( !spatialLocalizer ) { - spatialLocalizer.reset( new OctreeSpatialLocalizer(this) ); +// if (spatialLocalizer == NULL) spatialLocalizer = new DummySpatialLocalizer(1, this); + if ( spatialLocalizer ) { + return spatialLocalizer.get(); + } else { + OOFEM_LOG_ERROR("Spatial localizer init failure"); + return nullptr; } +} - spatialLocalizer->init(); - return spatialLocalizer.get(); +void Domain :: setSpatialLocalizer(std::unique_ptr sl){ + spatialLocalizer = std::move(sl); } @@ -1323,20 +1329,18 @@ Domain :: createDofs() OOFEM_ERROR("Incompatible dof type (%d) in node %d", dtype, i); } - - // Finally create the new DOF: //printf("Creating: node %d, id = %d, dofType = %d, bc = %d, ic = %d\n", i, id, dtype, bcid, icid); - if (!dman->hasDofID((DofIDItem)id)) { - - Dof *dof = classFactory.createDof(dtype, (DofIDItem)id, dman); - dof->setBcId(bcid); // Note: slave dofs and such will simple ignore this. - dof->setIcId(icid); - // Slave dofs obtain their weights post-initialization, simple slave dofs must have their master node specified. - if ( dtype == DT_simpleSlave ) { - static_cast< SimpleSlaveDof * >(dof)->setMasterDofManagerNum( ( * dman->giveMasterMap() ) [ id ] ); - } - dman->appendDof(dof); + if ( !dman->hasDofID((DofIDItem)id) ) { + + Dof *dof = classFactory.createDof(dtype, (DofIDItem)id, dman); + dof->setBcId(bcid); // Note: slave dofs and such will simple ignore this. + dof->setIcId(icid); + // Slave dofs obtain their weights post-initialization, simple slave dofs must have their master node specified. + if ( dtype == DT_simpleSlave ) { + static_cast< SimpleSlaveDof * >(dof)->setMasterDofManagerNum( ( * dman->giveMasterMap() ) [ id ] ); + } + dman->appendDof(dof); } } } @@ -1345,11 +1349,10 @@ Domain :: createDofs() if ( this->hasXfemManager() ) { xfemManager->createEnrichedDofs(); } - + if ( this->hasContactManager() ) { contactManager->createContactDofs(); } - } @@ -1451,191 +1454,134 @@ Domain :: giveTopology() } +template< typename T > +void save_components(T &list, DataStream &stream, ContextMode mode) +{ + if ( !stream.write((int)list.size()) ) { + THROW_CIOERR(CIO_IOERR); + } + for ( const auto &object: list ) { + if ( ( mode & CM_Definition ) != 0 ) { + if ( stream.write( std :: string( object->giveInputRecordName() ) ) == 0 ) { + THROW_CIOERR(CIO_IOERR); + } + } + object->saveContext(stream, mode); + } +} + + +template< typename T, typename C > +void restore_components(T &list, DataStream &stream, ContextMode mode, const C &creator) +{ + int size = 0; + if ( !stream.read(size) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( mode & CM_Definition ) { + list.clear(); + list.resize(size); + } + for ( int i = 1; i <= size; i++ ) { + if ( mode & CM_Definition ) { + std :: string name; + if ( !stream.read(name) ) { + THROW_CIOERR(CIO_IOERR); + } + list[i-1] = creator(name, i); + } + list[i-1]->restoreContext(stream, mode); + } +} + -#define SAVE_COMPONENTS(list) \ - { \ - for ( const auto &object: list ) { \ - if ( ( mode & CM_Definition ) != 0 ) { \ - if ( stream.write( std :: string( object->giveInputRecordName() ) ) == 0 ) { \ - THROW_CIOERR(CIO_IOERR); \ - } \ - } \ - if ( ( iores = object->saveContext(stream, mode) ) != CIO_OK ) { \ - THROW_CIOERR(iores); \ - } \ - } \ - } - -#define RESTORE_COMPONENTS(size, list, creator) \ - { \ - if ( mode & CM_Definition ) { \ - list.resize(size); \ - } \ - for ( int i = 1; i <= size; i++ ) { \ - if ( mode & CM_Definition ) { \ - std :: string name; \ - if ( !stream.read(name) ) { \ - THROW_CIOERR(CIO_IOERR); \ - } \ - auto *object = creator(name.c_str(), i, this); \ - if ( !object ) { \ - THROW_CIOERR(CIO_BADVERSION); \ - } \ - list[i-1].reset(object); \ - } \ - if ( ( iores = list[i-1]->restoreContext(stream, mode) ) != CIO_OK ) { \ - THROW_CIOERR(iores); \ - } \ - } \ - } - -#define DOMAIN_NCOMP 8 - -contextIOResultType +void Domain :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - int serNum; - ErrorEstimator *ee; - - // save domain serial number - serNum = this->giveSerialNumber(); - if ( !stream.write(serNum) ) { + if ( !stream.write(this->giveSerialNumber()) ) { THROW_CIOERR(CIO_IOERR); } if ( ( mode & CM_Definition ) ) { - long ncomp [ DOMAIN_NCOMP ]; - ncomp [ 0 ] = this->giveNumberOfDofManagers(); - ncomp [ 1 ] = this->giveNumberOfElements(); - ncomp [ 2 ] = this->giveNumberOfMaterialModels(); - ncomp [ 3 ] = this->giveNumberOfCrossSectionModels(); - ncomp [ 4 ] = this->giveNumberOfBoundaryConditions(); - ncomp [ 5 ] = this->giveNumberOfInitialConditions(); - ncomp [ 6 ] = this->giveNumberOfFunctions(); - ncomp [ 7 ] = this->giveNumberOfNonlocalBarriers(); - - // store number of components - if ( !stream.write(ncomp, DOMAIN_NCOMP) ) { - THROW_CIOERR(CIO_IOERR); - } - - // Have to store materials (and possible other things first) before restoring integration points and such). - SAVE_COMPONENTS(this->materialList); - SAVE_COMPONENTS(this->crossSectionList); - SAVE_COMPONENTS(this->icList); - SAVE_COMPONENTS(this->functionList); - SAVE_COMPONENTS(this->nonlocalBarrierList); + save_components(this->setList, stream, mode); + save_components(this->materialList, stream, mode); + save_components(this->crossSectionList, stream, mode); + save_components(this->icList, stream, mode); + save_components(this->functionList, stream, mode); + save_components(this->nonlocalBarrierList, stream, mode); } - // save dof managers - SAVE_COMPONENTS(this->dofManagerList); - // elements and corresponding integration points - SAVE_COMPONENTS(this->elementList); - // boundary conditions - SAVE_COMPONENTS(this->bcList); + save_components(this->dofManagerList, stream, mode); + save_components(this->elementList, stream, mode); + save_components(this->bcList, stream, mode); - // store error estimator data - ee = this->giveErrorEstimator(); + auto ee = this->giveErrorEstimator(); if ( ee ) { - if ( ( iores = ee->saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + ee->saveContext(stream, mode); } - - return CIO_OK; } -contextIOResultType +void Domain :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - int serNum; - bool domainUpdated; - ErrorEstimator *ee; - long ncomp [ DOMAIN_NCOMP ]; - - int nnodes, nelem, nmat, ncs, nbc, nic, nfunc, nnlb; - - - domainUpdated = false; - serNum = this->giveSerialNumber(); + bool domainUpdated = false; + int serNum = this->giveSerialNumber(); // restore domain serial number if ( !stream.read(this->serialNumber) ) { THROW_CIOERR(CIO_IOERR); } if ( ( mode & CM_Definition ) ) { - // read number of components - if ( !stream.read(ncomp, DOMAIN_NCOMP) ) { - THROW_CIOERR(CIO_IOERR); - } - - nnodes = ncomp [ 0 ]; - nelem = ncomp [ 1 ]; - nmat = ncomp [ 2 ]; - ncs = ncomp [ 3 ]; - nbc = ncomp [ 4 ]; - nic = ncomp [ 5 ]; - nfunc = ncomp [ 6 ]; - nnlb = ncomp [ 7 ]; - - // clear receiver data - dofManagerList.clear(); - elementList.clear(); - mElementPlaceInArray.clear(); - mDofManPlaceInArray.clear(); - materialList.clear(); - bcList.clear(); - icList.clear(); - functionList.clear(); - nonlocalBarrierList.clear(); - setList.clear(); + // clear cached data: + elementGlobal2LocalMap.clear(); + dofmanGlobal2LocalMap.clear(); + ///@todo Saving and restoring xfemmanagers. - xfemManager.reset(NULL); - //this->clear(); - - RESTORE_COMPONENTS(nmat, this->materialList, classFactory.createMaterial); - RESTORE_COMPONENTS(ncs, this->crossSectionList, classFactory.createCrossSection); - RESTORE_COMPONENTS(nic, this->icList, classFactory.createInitialCondition); - RESTORE_COMPONENTS(nfunc, this->functionList, classFactory.createFunction); - RESTORE_COMPONENTS(nnlb, this->nonlocalBarrierList, classFactory.createNonlocalBarrier); + xfemManager = nullptr; + + restore_components(this->setList, stream, mode, + [this] (std::string &x, int i) { return std::make_unique(i, this); }); + restore_components(this->materialList, stream, mode, + [this] (std::string &x, int i) { return classFactory.createMaterial(x.c_str(), i, this); }); + restore_components(this->crossSectionList, stream, mode, + [this] (std::string &x, int i) { return classFactory.createCrossSection(x.c_str(), i, this); }); + restore_components(this->icList, stream, mode, + [this] (std::string &x, int i) { return classFactory.createInitialCondition(x.c_str(), i, this); }); + restore_components(this->functionList, stream, mode, + [this] (std::string &x, int i) { return classFactory.createFunction(x.c_str(), i, this); }); + restore_components(this->nonlocalBarrierList, stream, mode, + [this] (std::string &x, int i) { return classFactory.createNonlocalBarrier(x.c_str(), i, this); }); domainUpdated = true; } else { if ( serNum != this->giveSerialNumber() ) { // read corresponding domain OOFEM_LOG_INFO("restoring domain %d.%d\n", this->number, this->giveSerialNumber()); - DataReader *domainDr = this->engineeringModel->GiveDomainDataReader(1, this->giveSerialNumber(), contextMode_read); + OOFEMTXTDataReader domainDr(this->engineeringModel->giveDomainFileName(1, this->giveSerialNumber())); this->clear(); if ( !this->instanciateYourself(domainDr) ) { OOFEM_ERROR("domain Instanciation failed"); } - delete domainDr; domainUpdated = true; } - - nnodes = this->giveNumberOfDofManagers(); - nelem = this->giveNumberOfElements(); - nbc = this->giveNumberOfBoundaryConditions(); } - RESTORE_COMPONENTS(nnodes, this->dofManagerList, classFactory.createDofManager); - RESTORE_COMPONENTS(nelem, this->elementList, classFactory.createElement); - RESTORE_COMPONENTS(nbc, this->bcList, classFactory.createBoundaryCondition); + restore_components(this->dofManagerList, stream, mode, + [this] (std::string &x, int i) { return classFactory.createDofManager(x.c_str(), i, this); }); + restore_components(this->elementList, stream, mode, + [this] (std::string &x, int i) { return classFactory.createElement(x.c_str(), i, this); }); + restore_components(this->bcList, stream, mode, + [this] (std::string &x, int i) { return classFactory.createBoundaryCondition(x.c_str(), i, this); }); - // restore error estimator data - ee = this->giveErrorEstimator(); + auto ee = this->giveErrorEstimator(); if ( ee ) { if ( domainUpdated ) { ee->setDomain(this); } - if ( ( iores = ee->restoreContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + ee->restoreContext(stream, mode); } if ( domainUpdated ) { @@ -1643,20 +1589,15 @@ Domain :: restoreContext(DataStream &stream, ContextMode mode) this->smoother->clear(); } } - - return CIO_OK; } - - - #ifdef __PARALLEL_MODE DomainTransactionManager * Domain :: giveTransactionManager() { if ( !transactionManager ) { - transactionManager.reset( new DomainTransactionManager(this) ); + transactionManager = std::make_unique(this); if ( !transactionManager ) { OOFEM_ERROR("allocation failed"); } @@ -1823,7 +1764,7 @@ Domain :: renumberDofManData(DomainTransactionManager *tm) SpecificEntityRenumberingFunctor< Domain > domainLToLFunctor(this, &Domain :: LB_giveUpdatedLocalNumber); - for ( auto &map: dmanMap ) { + for ( auto &map : dmanMap ) { if ( tm->dofmanTransactions.find(map.first) != tm->dofmanTransactions.end() ) { // received dof manager -> we map global numbers to new local number map.second->updateLocalNumbering(domainGToLFunctor); // g_to_l @@ -1841,7 +1782,7 @@ Domain :: renumberElementData(DomainTransactionManager *tm) SpecificEntityRenumberingFunctor< Domain > domainGToLFunctor(this, &Domain :: LB_giveUpdatedGlobalNumber); SpecificEntityRenumberingFunctor< Domain > domainLToLFunctor(this, &Domain :: LB_giveUpdatedLocalNumber); - for ( auto &map: elementMap ) { + for ( auto &map : elementMap ) { if ( tm->elementTransactions.find(map.first) != tm->elementTransactions.end() ) { // received dof manager -> we map global numbers to new local number map.second->updateLocalNumbering(domainGToLFunctor); // g_to_l @@ -1877,7 +1818,7 @@ int Domain :: LB_giveUpdatedLocalNumber(int num, EntityRenumberingScheme scheme) { if ( scheme == ERS_DofManager ) { - DofManager *dm = this->giveDofManager(num); + auto dm = this->giveDofManager(num); if ( dm ) { return dm->giveNumber(); } else { @@ -1895,7 +1836,7 @@ int Domain :: LB_giveUpdatedGlobalNumber(int num, EntityRenumberingScheme scheme) { if ( scheme == ERS_DofManager ) { - DofManager *dm = dmanMap [ num ]; + auto dm = dmanMap [ num ]; if ( dm ) { return dm->giveNumber(); } else { @@ -1933,44 +1874,54 @@ Domain :: elementGlobal2Local(int _globnum) } } - - #endif void Domain :: BuildElementPlaceInArrayMap() { - mElementPlaceInArray.clear(); + elementGlobal2LocalMap.clear(); int nelem = giveNumberOfElements(); for ( int i = 1; i <= nelem; i++ ) { Element *elem = this->giveElement(i); - mElementPlaceInArray[ elem->giveGlobalNumber() ] = i; + int globnum = elem->giveGlobalNumber(); + if ( elementGlobal2LocalMap.find(globnum) == elementGlobal2LocalMap.end() ) { + // label does not exist yet + elementGlobal2LocalMap [ globnum ] = i; + } else { + OOFEM_ERROR("Element with same global number already exist (label=%d)", globnum); + } } } void Domain :: BuildDofManPlaceInArrayMap() { - mDofManPlaceInArray.clear(); + dofmanGlobal2LocalMap.clear(); int ndman = giveNumberOfDofManagers(); for ( int i = 1; i <= ndman; i++ ) { DofManager *dMan = this->giveDofManager(i); - mDofManPlaceInArray[ dMan->giveGlobalNumber() ] = i; + int globnum = dMan->giveGlobalNumber(); + if ( dofmanGlobal2LocalMap.find(globnum) == dofmanGlobal2LocalMap.end() ) { + // label does not exist yet + dofmanGlobal2LocalMap [ globnum ] = i; + } else { + OOFEM_ERROR("DofManagaer with same global number already exist (label=%d)", globnum); + } } } void Domain :: BuildMaterialToElementMap() { - mMapMaterialNum2El.clear(); + materialNum2ElMap.clear(); int nelem = giveNumberOfElements(); for ( int i = 1; i <= nelem; i++ ) { Element *elem = this->giveElement(i); int matNum = elem->giveMaterialNumber(); - mMapMaterialNum2El[ matNum ].followedBy(i); + materialNum2ElMap[ matNum ].followedBy(i); } } diff --git a/src/oofemlib/domain.h b/src/oofemlib/domain.h index 4efc80d83..0950d8307 100644 --- a/src/oofemlib/domain.h +++ b/src/oofemlib/domain.h @@ -114,15 +114,16 @@ class ContactManager; */ class OOFEM_EXPORT Domain { -private: + public: /// Element list. std :: vector< std :: unique_ptr< Element > > elementList; /// Dof manager list. std :: vector< std :: unique_ptr< DofManager > > dofManagerList; + /// Cross section list. + std :: vector< std :: unique_ptr< CrossSection > > crossSectionList; +private: /// Material list. std :: vector< std :: unique_ptr< Material > > materialList; - /// Cross section list. - std :: vector< std :: unique_ptr< CrossSection > > crossSectionList; /// Boundary condition list. std :: vector< std :: unique_ptr< GeneralBoundaryCondition > > bcList; /// Initial condition list. @@ -198,22 +199,23 @@ class OOFEM_EXPORT Domain BCTracker bcTracker; /** - * Map from an element's global number to its place + * Map from an element's global number (label) to its place * in the element array. Added by ES 140326. */ - std::unordered_map< int, int > mElementPlaceInArray; + // elementGlobal2LocalMap + std::unordered_map< int, int > elementGlobal2LocalMap; /** - * Map from a dofmans's global number to its place + * Map from a dofmans's global number (label) to its place * in the dofman array. */ - std::unordered_map< int, int > mDofManPlaceInArray; + std::unordered_map< int, int > dofmanGlobal2LocalMap; /** * Map from material number to elements that have the * given material number. Added by ES 140718. */ - std::unordered_map< int, IntArray> mMapMaterialNum2El; + std::unordered_map< int, IntArray> materialNum2ElMap; /// Topology description std :: unique_ptr< TopologyDescription > topology; @@ -416,7 +418,7 @@ class OOFEM_EXPORT Domain * @return Nonzero if o.k. * @see FemComponent::initializeFrom */ - int instanciateYourself(DataReader *dr); + int instanciateYourself(DataReader &dr); /** * Performs post-initialization for all the domain contents (which is called after initializeFrom). * Currently, it only calls Element::postInitialize. @@ -476,27 +478,40 @@ class OOFEM_EXPORT Domain /// Resizes the internal data structure to accommodate space for _newSize sets. void resizeSets(int _newSize); + ///@note Needed for some of the boost-python bindings. NOTE: This takes ownership of the pointers, so it's actually completely unsafe. + //@{ + void py_setDofManager(int i, DofManager *obj); + void py_setElement(int i, Element *obj); + void py_setCrossSection(int i, CrossSection *obj); + void py_setMaterial(int i, Material *obj); + void py_setNonlocalBarrier(int i, NonlocalBarrier *obj); + void py_setBoundaryCondition(int i, GeneralBoundaryCondition *obj); + void py_setInitialCondition(int i, InitialCondition *obj); + void py_setFunction(int i, Function *obj); + void py_setSet(int i, Set *obj); + ///@} + /// Sets i-th component. The component will be further managed and maintained by domain object. - void setDofManager(int i, DofManager *obj); + void setDofManager(int i, std::unique_ptr obj); /// Sets i-th component. The component will be further managed and maintained by domain object. - void setElement(int i, Element *obj); + void setElement(int i, std::unique_ptr obj); /// Sets i-th component. The component will be further managed and maintained by domain object. - void setCrossSection(int i, CrossSection *obj); + void setCrossSection(int i, std::unique_ptr obj); /// Sets i-th component. The component will be further managed and maintained by domain object. - void setMaterial(int i, Material *obj); + void setMaterial(int i, std::unique_ptr obj); /// Sets i-th component. The component will be further managed and maintained by domain object. - void setNonlocalBarrier(int i, NonlocalBarrier *obj); + void setNonlocalBarrier(int i, std::unique_ptr obj); /// Sets i-th component. The component will be further managed and maintained by domain object. - void setBoundaryCondition(int i, GeneralBoundaryCondition *obj); + void setBoundaryCondition(int i, std::unique_ptr obj); /// Sets i-th component. The component will be further managed and maintained by domain object. - void setInitialCondition(int i, InitialCondition *obj); + void setInitialCondition(int i, std::unique_ptr obj); /// Sets i-th component. The component will be further managed and maintained by domain object. - void setFunction(int i, Function *obj); + void setFunction(int i, std::unique_ptr obj); /// Sets i-th component. The component will be further managed and maintained by domain object. - void setSet(int i, Set *obj); + void setSet(int i, std::unique_ptr obj); /// Temporary function, sets xfemManager. - void setXfemManager(XfemManager *ipXfemManager); + void setXfemManager(std::unique_ptr ipXfemManager); XfemManager *giveXfemManager(); bool hasXfemManager(); @@ -533,10 +548,9 @@ class OOFEM_EXPORT Domain * @param stream Context stream. If NULL then new file descriptor will be opened and closed * at the end else the stream given as parameter will be used and not closed at the end. * @param mode Determines amount of info in stream. - * @return contextIOResultType. * @exception ContextIOERR If error encountered. */ - contextIOResultType saveContext(DataStream &stream, ContextMode mode); + void saveContext(DataStream &stream, ContextMode mode); /** * Restores the domain state from output stream. Restores recursively the state of all * managed objects, like DofManagers and Elements. @@ -547,10 +561,9 @@ class OOFEM_EXPORT Domain * context. * @param stream Context file. * @param mode Determines amount of info in stream. - * @return contextIOResultType. * @exception ContextIOERR exception if error encountered. */ - contextIOResultType restoreContext(DataStream &stream, ContextMode mode); + void restoreContext(DataStream &stream, ContextMode mode); /** * Returns default DofID array which defines physical meaning of particular DOFs. * of nodal dofs. Default values are determined using current domain type. @@ -609,6 +622,11 @@ class OOFEM_EXPORT Domain * Returns receiver's associated spatial localizer. */ SpatialLocalizer *giveSpatialLocalizer(); + + /** + * Set spatial localizer + */ + void setSpatialLocalizer(std::unique_ptr sl); /** * Returns domain output manager. */ @@ -692,9 +710,9 @@ class OOFEM_EXPORT Domain /// sets the value of nonlocalUpdateStateCounter void setNonlocalUpdateStateCounter(StateCounterType val) { this->nonlocalUpdateStateCounter = val; } -private: void resolveDomainDofsDefaults(const char *); +private: /// Returns string for prepending output (used by error reporting macros). std :: string errorInfo(const char *func) const; diff --git a/src/oofemlib/dummycrosssection.C b/src/oofemlib/dummycrosssection.C new file mode 100644 index 000000000..2920e09af --- /dev/null +++ b/src/oofemlib/dummycrosssection.C @@ -0,0 +1,95 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "dummycrosssection.h" +#include "dynamicinputrecord.h" +#include "material.h" +#include "gaussintegrationrule.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_CrossSection(DummyCrossSection); + +DummyCrossSection :: DummyCrossSection(int n, Domain* d) : CrossSection(n, d) +{ +} + +void +DummyCrossSection :: initializeFrom(InputRecord &ir) +{ + CrossSection :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, this->matNumber, _IFT_DummyCrossSection_material); +} + + +void +DummyCrossSection :: giveInputRecord(DynamicInputRecord &input) +{ + CrossSection :: giveInputRecord(input); + + input.setField(this->matNumber, _IFT_DummyCrossSection_material); +} + + +bool +DummyCrossSection :: isCharacteristicMtrxSymmetric(MatResponseMode rMode) const +{ + return this->domain->giveMaterial(this->matNumber)->isCharacteristicMtrxSymmetric(rMode); +} + +Material * +DummyCrossSection :: giveMaterial(IntegrationPoint *ip) const +{ + return this->domain->giveMaterial(this->matNumber); +} +int +DummyCrossSection :: packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) +{ + return this->domain->giveMaterial(this->matNumber)->packUnknowns(buff, tStep, gp); +} + +int +DummyCrossSection :: unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) +{ + return this->domain->giveMaterial(this->matNumber)->unpackAndUpdateUnknowns(buff, tStep, gp); +} + +int +DummyCrossSection :: estimatePackSize(DataStream &buff, GaussPoint *gp) +{ + return this->domain->giveMaterial(this->matNumber)->estimatePackSize(buff, gp); +} +} // end namespace oofem diff --git a/src/sm/Materials/hyperelasticmaterial.h b/src/oofemlib/dummycrosssection.h similarity index 52% rename from src/sm/Materials/hyperelasticmaterial.h rename to src/oofemlib/dummycrosssection.h index c129b43e4..1314e799a 100644 --- a/src/sm/Materials/hyperelasticmaterial.h +++ b/src/oofemlib/dummycrosssection.h @@ -32,47 +32,48 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef hyperelasticmaterial_h -#define hyperelasticmaterial_h +#ifndef dummycrosssection_h +#define dummycrosssection_h -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "crosssection.h" +#include "materialmode.h" +#include "matresponsemode.h" +#include "material.h" +#include "internalstatetype.h" +#include "internalstatevaluetype.h" +#include "dictionary.h" +#include "crosssectextension.h" +#include "gausspoint.h" -///@name Input fields for HyperElasticMaterial +///@name Input fields for CrossSection //@{ -#define _IFT_HyperElasticMaterial_Name "hyperelmat" -#define _IFT_HyperElasticMaterial_k "k" -#define _IFT_HyperElasticMaterial_g "g" +#define _IFT_DummyCrossSection_Name "dummycs" +#define _IFT_DummyCrossSection_material "mat" //@} namespace oofem { + /** - * Saint Venant–Kirchhoff model defined by shear and bulk modulus. - * @todo Should we even have this? Isn't this identical to the isotropic linear elastic model? / Mikael + * Class representing dummy cross section, that forwards all requests to material model. + * */ -class HyperElasticMaterial : public StructuralMaterial +class OOFEM_EXPORT DummyCrossSection : public CrossSection { protected: - double K; ///< Bulk modulus. - double G; ///< Shear modulus. - + int matNumber = 0; public: - HyperElasticMaterial(int n, Domain * d); - - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep); - - - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + DummyCrossSection(int n, Domain *d); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override; + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int estimatePackSize(DataStream &buff, GaussPoint *ip) override; + Material *giveMaterial(IntegrationPoint *ip) const override; + const char *giveClassName() const override { return "DummyCrossSection"; } + const char *giveInputRecordName() const override { return _IFT_DummyCrossSection_Name; } - virtual const char *giveInputRecordName() const { return _IFT_HyperElasticMaterial_Name; } - virtual const char *giveClassName() const { return "HyperElasticMaterial"; } }; } // end namespace oofem -#endif +#endif // dummycrosssection_h diff --git a/src/oofemlib/dummyengngm.C b/src/oofemlib/dummyengngm.C new file mode 100644 index 000000000..653301e1e --- /dev/null +++ b/src/oofemlib/dummyengngm.C @@ -0,0 +1,78 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Milan ????????????????? +//#include "gpinitmodule.h" +// Milan ????????????????? + +#include "dummyengngm.h" +#include "timestep.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_EngngModel(DummyEngngModel); + +DummyEngngModel :: DummyEngngModel(int i, EngngModel *_master) : EngngModel (i, _master) +{ + ndomains = 1; +} + +void +DummyEngngModel :: initializeFrom(InputRecord &ir) +{ + this->numberOfSteps = 1; + this->nMetaSteps = 0; + this->suppressOutput = true; + +} + +TimeStep *DummyEngngModel :: giveNextStep() +{ + if ( !currentStep ) { + // first step -> generate initial step + //currentStep = std::make_unique(*giveSolutionStepWhenIcApply()); + currentStep = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., 1., 0); + } + previousStep = std :: move(currentStep); + currentStep = std::make_unique(*previousStep, 1.); + + return currentStep.get(); +} + +void DummyEngngModel :: solveYourselfAt(TimeStep *tStep) +{ + +} +} // end namespace oofem diff --git a/src/oofemlib/dummyengngm.h b/src/oofemlib/dummyengngm.h new file mode 100644 index 000000000..d8cfc6348 --- /dev/null +++ b/src/oofemlib/dummyengngm.h @@ -0,0 +1,72 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef dummyengngm_h +#define dummyengngm_h + +#include "engngm.h" +#include "inputrecord.h" + + + +#define _IFT_DummyEngngModel_Name "Dummy" + +namespace oofem { + + + +/** + * Dummy Engneering model. Does not solve any problem, but invokes the configured export modules. + * Usefull for exporting model geometry without solving the problem. + */ +class OOFEM_EXPORT DummyEngngModel : public EngngModel +{ +public: + + /** + * Constructor. Creates Engng model with number i. + */ + DummyEngngModel(int i, EngngModel * _master = NULL); + virtual ~DummyEngngModel() {} + + void solveYourselfAt(TimeStep *tStep) override; + void initializeFrom(InputRecord &ir) override; + TimeStep * giveNextStep() override; + const char *giveClassName() const override { return "DummyEngngModel"; } + + +}; + +} // end namespace oofem +#endif // engngm_h diff --git a/src/oofemlib/dummylocalizer.C b/src/oofemlib/dummylocalizer.C index 30b7ef34f..59368aff1 100644 --- a/src/oofemlib/dummylocalizer.C +++ b/src/oofemlib/dummylocalizer.C @@ -160,16 +160,16 @@ GaussPoint * DummySpatialLocalizer :: giveClosestIP(const FloatArray &coords, int region, bool iCohesiveZoneGP) { double minDist = 0.0; - GaussPoint *answer = NULL; + GaussPoint *answer = nullptr; FloatArray jGpCoords; for ( auto &elem : this->giveDomain()->giveElements() ) { if ( ( region < 0 ) || ( region == elem->giveRegionNumber() ) ) { - for ( GaussPoint *jGp: *elem->giveDefaultIntegrationRulePtr() ) { + for ( auto &jGp: *elem->giveDefaultIntegrationRulePtr() ) { if ( elem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) { - double distance = coords.distance(jGpCoords); - if ( answer == NULL || distance < minDist ) { - minDist = distance; + double dist = distance(coords, jGpCoords); + if ( answer == nullptr || dist < minDist ) { + minDist = dist; answer = jGp; } } @@ -190,9 +190,9 @@ DummySpatialLocalizer :: giveAllElementsWithIpWithinBox(elementContainerType &el nelem = this->giveDomain()->giveNumberOfElements(); for ( int i = 1; i <= nelem; i++ ) { Element *ielem = this->giveDomain()->giveElement(i); - for ( GaussPoint *jGp: *ielem->giveDefaultIntegrationRulePtr() ) { + for ( auto &jGp: *ielem->giveDefaultIntegrationRulePtr() ) { if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) { - double currDist = coords.distance(jGpCoords); + double currDist = distance(coords, jGpCoords); if ( currDist <= radius ) { elemSet.insertSortedOnce(i); } @@ -209,8 +209,8 @@ DummySpatialLocalizer :: giveAllNodesWithinBox(nodeContainerType &nodeSet, const for ( int i = 1; i <= nnode; i++ ) { DofManager *idofman = this->giveDomain()->giveDofManager(i); Node *inode = dynamic_cast< Node * >(idofman); - if ( inode != NULL ) { - if ( coords.distance( inode->giveCoordinates() ) <= radius ) { + if ( inode ) { + if ( distance(coords, inode->giveCoordinates()) <= radius ) { nodeSet.push_back(i); } } @@ -221,19 +221,19 @@ DummySpatialLocalizer :: giveAllNodesWithinBox(nodeContainerType &nodeSet, const Node * DummySpatialLocalizer :: giveNodeClosestToPoint(const FloatArray &coords, double maxDist) { - Node *closest = NULL; + Node *closest = nullptr; double maxdist = 0.; for ( auto &dman : this->giveDomain()->giveDofManagers() ) { Node *node = dynamic_cast< Node* >( dman.get() ); if ( node ) { - double dist = coords.distance( node->giveCoordinates() ); - if ( closest == NULL || dist < maxdist ) { + double dist = distance(coords, node->giveCoordinates()); + if ( closest == nullptr || dist < maxdist ) { closest = node; maxdist = dist; } } } - return maxdist > maxDist ? closest : NULL; + return maxdist > maxDist ? closest : nullptr; } } // end namespace oofem diff --git a/src/oofemlib/dummylocalizer.h b/src/oofemlib/dummylocalizer.h index 7e227f032..7506257e2 100644 --- a/src/oofemlib/dummylocalizer.h +++ b/src/oofemlib/dummylocalizer.h @@ -60,16 +60,16 @@ class OOFEM_EXPORT DummySpatialLocalizer : public SpatialLocalizer /// Destructor virtual ~DummySpatialLocalizer() { } - virtual int init(bool force = false); + int init(bool force = false) override; - virtual Element *giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList = NULL); - virtual Element *giveElementClosestToPoint(FloatArray &lcoords, FloatArray &closest, const FloatArray &coords, int region = 0); - virtual GaussPoint *giveClosestIP(const FloatArray &coords, int region, bool iCohesiveZoneGP = false); - virtual void giveAllElementsWithIpWithinBox(elementContainerType &elemSet, const FloatArray &coords, const double radius); - virtual void giveAllNodesWithinBox(nodeContainerType &nodeList, const FloatArray &coords, const double radius); - virtual Node *giveNodeClosestToPoint(const FloatArray &coords, double maxDist); + Element *giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList = nullptr) override; + Element *giveElementClosestToPoint(FloatArray &lcoords, FloatArray &closest, const FloatArray &coords, int region = 0) override; + GaussPoint *giveClosestIP(const FloatArray &coords, int region, bool iCohesiveZoneGP = false) override; + void giveAllElementsWithIpWithinBox(elementContainerType &elemSet, const FloatArray &coords, const double radius) override; + void giveAllNodesWithinBox(nodeContainerType &nodeList, const FloatArray &coords, const double radius) override; + Node *giveNodeClosestToPoint(const FloatArray &coords, double maxDist) override; - virtual const char *giveClassName() const { return "DummySpatialLocalizer"; } + const char *giveClassName() const override { return "DummySpatialLocalizer"; } }; } // end namespace oofem #endif // dummylocalizer_h diff --git a/src/oofemlib/dummymaterial.h b/src/oofemlib/dummymaterial.h index acc61de6c..75f8c1683 100644 --- a/src/oofemlib/dummymaterial.h +++ b/src/oofemlib/dummymaterial.h @@ -52,11 +52,12 @@ class OOFEM_EXPORT DummyMaterial : public Material { public: DummyMaterial(int n, Domain * d) : Material(n, d) { } - virtual int hasMaterialModeCapability(MaterialMode mode) { return 0; } - virtual const char *giveClassName() const { return "DummyMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_DummyMaterial_Name; } - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + bool hasMaterialModeCapability(MaterialMode mode) const override { return false; } + + const char *giveClassName() const override { return "DummyMaterial"; } + const char *giveInputRecordName() const override { return _IFT_DummyMaterial_Name; } + void initializeFrom(InputRecord &ir) override { } }; } // end namespace oofem #endif // material_h diff --git a/src/oofemlib/dynamicdatareader.C b/src/oofemlib/dynamicdatareader.C index ba1dfff05..2e4070050 100644 --- a/src/oofemlib/dynamicdatareader.C +++ b/src/oofemlib/dynamicdatareader.C @@ -36,10 +36,11 @@ #include "inputrecord.h" #include "error.h" +#include #include namespace oofem { -DynamicDataReader :: DynamicDataReader() : DataReader() +DynamicDataReader :: DynamicDataReader(std :: string name) : DataReader(), name(std :: move(name)) { this->it = recordList.end(); } @@ -49,13 +50,14 @@ DynamicDataReader :: ~DynamicDataReader() } void -DynamicDataReader :: insertInputRecord(InputRecordType type, InputRecord *record) +DynamicDataReader :: insertInputRecord(InputRecordType type, std::unique_ptr record) { // Should care about the record type, but its a hassle. - this->recordList.emplace_back(record); + this->recordList.push_back(std::move(record)); + this->it = recordList.end(); } -InputRecord * +InputRecord & DynamicDataReader :: giveInputRecord(InputRecordType typeId, int recordId) { // Ignores recordId in favor of having a dynamic list (just incremental access). typeId could be supported, but its a hassle. @@ -65,7 +67,7 @@ DynamicDataReader :: giveInputRecord(InputRecordType typeId, int recordId) } else { ++this->it; } - return this->it->get(); + return **(this->it); } bool diff --git a/src/oofemlib/dynamicdatareader.h b/src/oofemlib/dynamicdatareader.h index 5e22922d7..6ac403e94 100644 --- a/src/oofemlib/dynamicdatareader.h +++ b/src/oofemlib/dynamicdatareader.h @@ -36,7 +36,7 @@ #define dynamicdatareader_h #include "datareader.h" -#include +#include #include namespace oofem { @@ -53,14 +53,15 @@ class InputRecord; class OOFEM_EXPORT DynamicDataReader : public DataReader { protected: + std :: string name; /// Keeps track of the current position in the list - std :: list< std :: unique_ptr< InputRecord > > :: iterator it; + std :: vector< std :: unique_ptr< InputRecord > > :: iterator it; /// All record types will be appended to this list, no split in terms of InputRecordType is implemented yet. - std :: list< std :: unique_ptr< InputRecord > >recordList; + std :: vector< std :: unique_ptr< InputRecord > >recordList; public: /// Constructor. - DynamicDataReader(); + DynamicDataReader(std :: string name); virtual ~DynamicDataReader(); DynamicDataReader(const DynamicDataReader& src) = delete; @@ -72,7 +73,7 @@ class OOFEM_EXPORT DynamicDataReader : public DataReader * @param type Currently ignored, but left here for consistency with giveInputRecord * @param record New record to be added at the end. New input records have to be added in the same order as the text input files do it. */ - void insertInputRecord(InputRecordType type, InputRecord *record); + void insertInputRecord(InputRecordType type, std::unique_ptr record); /** * Sets the output file name. Used for writing input files. @@ -83,10 +84,10 @@ class OOFEM_EXPORT DynamicDataReader : public DataReader */ void setDescription(const std :: string &description) { this->description = description; } - virtual InputRecord *giveInputRecord(InputRecordType, int recordId); - virtual bool peakNext(const std :: string &keyword); - virtual void finish(); - virtual const char *giveDataSourceName() const { return ""; } + InputRecord &giveInputRecord(InputRecordType, int recordId) override; + bool peakNext(const std :: string &keyword) override; + void finish() override; + std :: string giveReferenceName() const override { return name; } /** * Writes all input records to file. diff --git a/src/oofemlib/dynamicinputrecord.C b/src/oofemlib/dynamicinputrecord.C index a14e6caaf..dfd2c59f8 100644 --- a/src/oofemlib/dynamicinputrecord.C +++ b/src/oofemlib/dynamicinputrecord.C @@ -46,16 +46,16 @@ #include namespace oofem { -DynamicInputRecord *CreateNodeIR(int i, InputFieldType nodeType, FloatArray coord) +std::unique_ptr CreateNodeIR(int i, InputFieldType nodeType, FloatArray coord) { - DynamicInputRecord *result = new DynamicInputRecord(nodeType, i); + auto result = std::make_unique(nodeType, i); result->setField(std :: move(coord), _IFT_Node_coords); return result; } -DynamicInputRecord *CreateElementIR(int i, InputFieldType elementType, IntArray nodes, int cs) +std::unique_ptr CreateElementIR(int i, InputFieldType elementType, IntArray nodes, int cs) { - DynamicInputRecord *result = new DynamicInputRecord(elementType, i); + auto result = std::make_unique(elementType, i); result->setField(std :: move(nodes), _IFT_Element_nodes); if ( cs != 0 ) { result->setField(cs, _IFT_Element_crosssect); @@ -64,8 +64,8 @@ DynamicInputRecord *CreateElementIR(int i, InputFieldType elementType, IntArray } -DynamicInputRecord :: DynamicInputRecord(std :: string keyword, int value) : InputRecord(), - recordKeyword(keyword), ///@todo std::move here +DynamicInputRecord :: DynamicInputRecord(std :: string keyword, int value) : + recordKeyword(std::move(keyword)), recordNumber(value), emptyRecord(), intRecord(), @@ -80,7 +80,7 @@ DynamicInputRecord :: DynamicInputRecord(std :: string keyword, int value) : Inp rangeRecord() { } -DynamicInputRecord :: DynamicInputRecord(FEMComponent &femc) : InputRecord(), +DynamicInputRecord :: DynamicInputRecord(FEMComponent &femc) : recordKeyword(), recordNumber(0), emptyRecord(), @@ -98,7 +98,7 @@ DynamicInputRecord :: DynamicInputRecord(FEMComponent &femc) : InputRecord(), femc.giveInputRecord(* this); } -DynamicInputRecord :: DynamicInputRecord(const DynamicInputRecord &src) : InputRecord(src), +DynamicInputRecord :: DynamicInputRecord(const DynamicInputRecord &src) : recordKeyword(src.recordKeyword), recordNumber(src.recordNumber), emptyRecord(src.emptyRecord), @@ -141,127 +141,114 @@ void DynamicInputRecord :: finish(bool wrn) ///@todo Implement warning about unread entries } -IRResultType DynamicInputRecord :: giveRecordKeywordField(std :: string &answer, int &value) +void DynamicInputRecord :: giveRecordKeywordField(std :: string &answer, int &value) { answer = this->recordKeyword; value = this->recordNumber; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveRecordKeywordField(std :: string &answer) +void DynamicInputRecord :: giveRecordKeywordField(std :: string &answer) { answer = this->recordKeyword; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveField(int &answer, InputFieldType id) +void DynamicInputRecord :: giveField(int &answer, InputFieldType id) { std :: map< std :: string, int > :: iterator it = this->intRecord.find(id); if ( it == this->intRecord.end() ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, recordNumber); } answer = it->second; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveField(double &answer, InputFieldType id) +void DynamicInputRecord :: giveField(double &answer, InputFieldType id) { std :: map< std :: string, double > :: iterator it = this->doubleRecord.find(id); if ( it == this->doubleRecord.end() ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, recordNumber); } answer = it->second; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveField(bool &answer, InputFieldType id) +void DynamicInputRecord :: giveField(bool &answer, InputFieldType id) { std :: map< std :: string, bool > :: iterator it = this->boolRecord.find(id); if ( it == this->boolRecord.end() ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, recordNumber); } answer = it->second; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveField(std :: string &answer, InputFieldType id) +void DynamicInputRecord :: giveField(std :: string &answer, InputFieldType id) { std :: map< std :: string, std :: string > :: iterator it = this->stringRecord.find(id); if ( it == this->stringRecord.end() ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, recordNumber); } answer = it->second; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveField(FloatArray &answer, InputFieldType id) +void DynamicInputRecord :: giveField(FloatArray &answer, InputFieldType id) { std :: map< std :: string, FloatArray > :: iterator it = this->floatArrayRecord.find(id); if ( it == this->floatArrayRecord.end() ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, recordNumber); } answer = it->second; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveField(IntArray &answer, InputFieldType id) +void DynamicInputRecord :: giveField(IntArray &answer, InputFieldType id) { std :: map< std :: string, IntArray > :: iterator it = this->intArrayRecord.find(id); if ( it == this->intArrayRecord.end() ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, recordNumber); } answer = it->second; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveField(FloatMatrix &answer, InputFieldType id) +void DynamicInputRecord :: giveField(FloatMatrix &answer, InputFieldType id) { std :: map< std :: string, FloatMatrix > :: iterator it = this->matrixRecord.find(id); if ( it == this->matrixRecord.end() ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, recordNumber); } answer = it->second; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveField(std :: vector< std :: string > &answer, InputFieldType id) +void DynamicInputRecord :: giveField(std :: vector< std :: string > &answer, InputFieldType id) { std :: map< std :: string, std :: vector< std :: string > > :: iterator it = this->stringListRecord.find(id); if ( it == this->stringListRecord.end() ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, recordNumber); } answer = it->second; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveField(Dictionary &answer, InputFieldType id) +void DynamicInputRecord :: giveField(Dictionary &answer, InputFieldType id) { std :: map< std :: string, Dictionary > :: iterator it = this->dictionaryRecord.find(id); if ( it == this->dictionaryRecord.end() ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, recordNumber); } answer = it->second; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveField(std :: list< Range > &answer, InputFieldType id) +void DynamicInputRecord :: giveField(std :: list< Range > &answer, InputFieldType id) { std :: map< std :: string, std :: list< Range > > :: iterator it = this->rangeRecord.find(id); if ( it == this->rangeRecord.end() ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, recordNumber); } answer = it->second; - return IRRT_OK; } -IRResultType DynamicInputRecord :: giveField(ScalarFunction &answer, InputFieldType id) +void DynamicInputRecord :: giveField(ScalarFunction &answer, InputFieldType id) { std :: map< std :: string, ScalarFunction > :: iterator it = this->scalarFunctionRecord.find(id); if ( it == this->scalarFunctionRecord.end() ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, recordNumber); } answer = it->second; - return IRRT_OK; } bool DynamicInputRecord :: hasField(InputFieldType id) @@ -372,15 +359,6 @@ void DynamicInputRecord :: unsetField(InputFieldType id) this->scalarFunctionRecord.erase(id); } -void -DynamicInputRecord :: report_error(const char *_class, const char *proc, InputFieldType id, - IRResultType result, const char *file, int line) -{ - oofem_logger.writeELogMsg(Logger :: LOG_LEVEL_ERROR, NULL, file, line, - "Input error: \"%s\", field keyword \"%s\"\n%s::%s", - strerror(result), id, _class, proc); - OOFEM_EXIT(1); ///@todo We should never directly exit when dealing with user input. -} // Helpful macro since we have so many separate records #define forRecord(name) \ diff --git a/src/oofemlib/dynamicinputrecord.h b/src/oofemlib/dynamicinputrecord.h index 8e114189c..3adea04c9 100644 --- a/src/oofemlib/dynamicinputrecord.h +++ b/src/oofemlib/dynamicinputrecord.h @@ -45,10 +45,10 @@ class FEMComponent; class DynamicInputRecord; /// Helper function for creating a dynamic input record for a node -OOFEM_EXPORT DynamicInputRecord *CreateNodeIR(int i, InputFieldType nodeType, FloatArray coord); +OOFEM_EXPORT std::unique_ptr CreateNodeIR(int i, InputFieldType nodeType, FloatArray coord); /// Helper function for creating elements (with optional cross-section number). -OOFEM_EXPORT DynamicInputRecord *CreateElementIR(int i, InputFieldType elementType, IntArray nodes, int cs = 0); +OOFEM_EXPORT std::unique_ptr CreateElementIR(int i, InputFieldType elementType, IntArray nodes, int cs = 0); /** * Class representing the a dynamic Input Record. @@ -62,7 +62,6 @@ class OOFEM_EXPORT DynamicInputRecord : public InputRecord std :: string recordKeyword; int recordNumber; - // Record representation. std :: set< std :: string >emptyRecord; ///< Fields without values std :: map< std :: string, int >intRecord; std :: map< std :: string, double >doubleRecord; @@ -88,27 +87,28 @@ class OOFEM_EXPORT DynamicInputRecord : public InputRecord /// Assignment operator. DynamicInputRecord &operator = ( const DynamicInputRecord & ); - virtual InputRecord *GiveCopy() { return new DynamicInputRecord(*this); } - virtual void finish(bool wrn = true); + std::unique_ptr clone() const override { return std::make_unique(*this); } + void finish(bool wrn = true) override; - virtual std :: string giveRecordAsString() const; + std :: string giveRecordAsString() const override; - virtual IRResultType giveRecordKeywordField(std :: string &answer, int &value); - virtual IRResultType giveRecordKeywordField(std :: string &answer); - virtual IRResultType giveField(int &answer, InputFieldType id); - virtual IRResultType giveField(double &answer, InputFieldType id); - virtual IRResultType giveField(bool &answer, InputFieldType id); - virtual IRResultType giveField(std :: string &answer, InputFieldType id); - virtual IRResultType giveField(FloatArray &answer, InputFieldType id); - virtual IRResultType giveField(IntArray &answer, InputFieldType id); - virtual IRResultType giveField(FloatMatrix &answer, InputFieldType id); - virtual IRResultType giveField(std :: vector< std :: string > &answer, InputFieldType id); - virtual IRResultType giveField(Dictionary &answer, InputFieldType id); - virtual IRResultType giveField(std :: list< Range > &answer, InputFieldType id); - virtual IRResultType giveField(ScalarFunction &function, InputFieldType id); + void giveRecordKeywordField(std :: string &answer, int &value) override; + void giveRecordKeywordField(std :: string &answer) override; + void giveField(int &answer, InputFieldType id) override; + void giveField(double &answer, InputFieldType id) override; + void giveField(bool &answer, InputFieldType id) override; + void giveField(std :: string &answer, InputFieldType id) override; + void giveField(FloatArray &answer, InputFieldType id) override; + void giveField(IntArray &answer, InputFieldType id) override; + void giveField(FloatMatrix &answer, InputFieldType id) override; + void giveField(std :: vector< std :: string > &answer, InputFieldType id) override; + void giveField(Dictionary &answer, InputFieldType id) override; + void giveField(std :: list< Range > &answer, InputFieldType id) override; + void giveField(ScalarFunction &function, InputFieldType id) override; + + bool hasField(InputFieldType id) override; + void printYourself() override; - virtual bool hasField(InputFieldType id); - virtual void printYourself(); // Setters, unique for the dynamic input record void setRecordKeywordField(std :: string keyword, int number); void setRecordKeywordNumber(int number); @@ -127,9 +127,6 @@ class OOFEM_EXPORT DynamicInputRecord : public InputRecord void setField(InputFieldType id); /// Removes given field from record. void unsetField(InputFieldType id); - - virtual void report_error(const char *_class, const char *proc, InputFieldType id, - IRResultType result, const char *file, int line); }; } // end namespace oofem #endif // dynamicinputrecord_h diff --git a/src/oofemlib/dynamicrelaxationsolver.C b/src/oofemlib/dynamicrelaxationsolver.C index d08996117..9575c66c2 100644 --- a/src/oofemlib/dynamicrelaxationsolver.C +++ b/src/oofemlib/dynamicrelaxationsolver.C @@ -42,6 +42,7 @@ #include "element.h" #include "unknownnumberingscheme.h" #include "mathfem.h" +#include "assemblercallback.h" namespace oofem { @@ -55,10 +56,10 @@ DynamicRelaxationSolver :: DynamicRelaxationSolver(Domain *d, EngngModel *m) : N } -IRResultType -DynamicRelaxationSolver :: initializeFrom(InputRecord *ir) +void +DynamicRelaxationSolver :: initializeFrom(InputRecord &ir) { - return NRSolver :: initializeFrom(ir); + NRSolver :: initializeFrom(ir); } diff --git a/src/oofemlib/dynamicrelaxationsolver.h b/src/oofemlib/dynamicrelaxationsolver.h index e29798f3e..60017172c 100644 --- a/src/oofemlib/dynamicrelaxationsolver.h +++ b/src/oofemlib/dynamicrelaxationsolver.h @@ -65,15 +65,15 @@ class OOFEM_EXPORT DynamicRelaxationSolver : public NRSolver DynamicRelaxationSolver(Domain * d, EngngModel * m); virtual ~DynamicRelaxationSolver() {} - virtual NM_Status solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, - FloatArray &X, FloatArray &dX, FloatArray &F, - const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm, - int &nite, TimeStep *); + NM_Status solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, + FloatArray &X, FloatArray &dX, FloatArray &F, + const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm, + int &nite, TimeStep *) override; - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual const char *giveClassName() const { return "DynamicRelaxationSolver"; } - virtual const char *giveInputRecordName() const { return _IFT_DynamicRelaxationSolver_Name; } + void initializeFrom(InputRecord &ir) override; + + const char *giveClassName() const override { return "DynamicRelaxationSolver"; } + const char *giveInputRecordName() const override { return _IFT_DynamicRelaxationSolver_Name; } }; } // end namespace oofem #endif // dynamicrelaxationsolver_h diff --git a/src/oofemlib/dyncombuff.h b/src/oofemlib/dyncombuff.h index 69cbd1c32..52717bb68 100644 --- a/src/oofemlib/dyncombuff.h +++ b/src/oofemlib/dyncombuff.h @@ -89,7 +89,7 @@ class OOFEM_EXPORT CommunicationPacket : public MPIBuffer * @param communicator Communicator request handle. * @return Sends MIP_Succes if ok. */ - int iSend(MPI_Comm communicator, int dest, int tag); + int iSend(MPI_Comm communicator, int dest, int tag) override; /** * Starts standard mode, nonblocking receive. The buffer must be large enough to receive all data. * @param source Rank of source. @@ -99,7 +99,7 @@ class OOFEM_EXPORT CommunicationPacket : public MPIBuffer * @param communicator Communicator request handle. * @return MIP_Succes if ok. */ - int iRecv(MPI_Comm communicator, int source, int tag, int count = 0); + int iRecv(MPI_Comm communicator, int source, int tag, int count = 0) override; /** * Tests if the operation identified by this->request is complete. * In such case, true is returned and @@ -116,7 +116,7 @@ class OOFEM_EXPORT CommunicationPacket : public MPIBuffer * then the object is deallocated by the call to MPI_WAIT and the request handle is set to MPI_REQUEST_NULL. * @return True if request is successful. */ - virtual int waitCompletion(); + int waitCompletion() override; #endif //@} @@ -181,40 +181,40 @@ class OOFEM_EXPORT DynamicCommunicationBuffer : public CommunicationBuffer /// Destructor. virtual ~DynamicCommunicationBuffer(); - virtual int resize(int newSize) { return 1; } - virtual void init(); + int resize(int newSize) override { return 1; } + void init() override; /// Initialize for packing. - virtual void initForPacking(); + void initForPacking() override; /// Initialize for Unpacking (data already received). - virtual void initForUnpacking(); + void initForUnpacking() override; - virtual int write(const int *src, int n) + int write(const int *src, int n) override { return __write(src, n, MPI_INT); } - virtual int write(const long *src, int n) + int write(const long *src, int n) override { return __write(src, n, MPI_LONG); } - virtual int write(const unsigned long *src, int n) + int write(const unsigned long *src, int n) override { return __write(src, n, MPI_UNSIGNED_LONG); } - virtual int write(const double *src, int n) + int write(const double *src, int n) override { return __write(src, n, MPI_DOUBLE); } - virtual int write(const char *src, int n) + int write(const char *src, int n) override { return __write(src, n, MPI_CHAR); } - virtual int read(int *dest, int n) + int read(int *dest, int n) override { return __read(dest, n, MPI_INT); } - virtual int read(long *dest, int n) + int read(long *dest, int n) override { return __read(dest, n, MPI_LONG); } - virtual int read(unsigned long *dest, int n) + int read(unsigned long *dest, int n) override { return __read(dest, n, MPI_UNSIGNED_LONG); } - virtual int read(double *dest, int n) + int read(double *dest, int n) override { return __read(dest, n, MPI_DOUBLE); } - virtual int read(char *dest, int n) + int read(char *dest, int n) override { return __read(dest, n, MPI_CHAR); } - virtual int iSend(int dest, int tag); - virtual int iRecv(int source, int tag, int count = 0); - virtual int bcast(int root); + int iSend(int dest, int tag) override; + int iRecv(int source, int tag, int count = 0) override; + int bcast(int root) override; /** * Tests if the operation identified by this->request is complete. @@ -223,7 +223,7 @@ class OOFEM_EXPORT DynamicCommunicationBuffer : public CommunicationBuffer * is set to MPI_REQUEST_NULL. Otherwise call returns flag=false. * @return True if operation complete, false otherwise. */ - int testCompletion(); + int testCompletion() override; /** * Waits until a completion of a nonblocking communication. The completion of a send operation indicates that the sender is * now free to update the locations in the send buffer, the completion of a receive operation indicates that the @@ -232,7 +232,7 @@ class OOFEM_EXPORT DynamicCommunicationBuffer : public CommunicationBuffer * then the object is deallocated by the call to MPI_WAIT and the request handle is set to MPI_REQUEST_NULL. * @return True if request is successful. */ - virtual int waitCompletion(); + int waitCompletion() override; static void printInfo() { packetPool.printInfo(); } diff --git a/src/oofemlib/eigenvectorprimaryfield.C b/src/oofemlib/eigenvectorprimaryfield.C new file mode 100644 index 000000000..1f27f2fb8 --- /dev/null +++ b/src/oofemlib/eigenvectorprimaryfield.C @@ -0,0 +1,122 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "eigenvectorprimaryfield.h" +#include "timestep.h" +#include "domain.h" +#include "dofmanager.h" +#include "dof.h" +#include "floatarray.h" +#include "floatmatrix.h" +#include "engngm.h" +#include "set.h" +#include "boundarycondition.h" +#include "initialcondition.h" +#include "element.h" +#include "activebc.h" + + +namespace oofem { +EigenVectorPrimaryField :: EigenVectorPrimaryField(EngngModel *a, int idomain, FieldType ft, int nHist): + DofDistributedPrimaryField(a, idomain, ft, nHist) +{ } + + +EigenVectorPrimaryField :: ~EigenVectorPrimaryField() +{ } + + +double +EigenVectorPrimaryField :: giveUnknownValue(Dof *dof, ValueModeType mode, TimeStep *tStep) +{ + if ( mode != VM_Total ) OOFEM_ERROR("Only VM_Total is applicable to eigen vector fields"); + return dof->giveUnknownsDictionaryValue(tStep, mode); +} + + +void +EigenVectorPrimaryField :: updateAll(const FloatMatrix &eigenVectors, const UnknownNumberingScheme &s) +{ + Domain *d = emodel->giveDomain(domainIndx); + + for (int i = 1; i <= eigenVectors.giveNumberOfColumns(); ++i ) { + TimeStep step(i, nullptr, 0, 1.0, 0.0, 0); + this->applyBoundaryCondition(&step); + } + + auto set_values = [&eigenVectors, &s](DofManager &dman) { + for ( Dof *dof: dman ) { + if ( !dof->isPrimaryDof() ) continue; + int eqNum = dof->giveEquationNumber(s); + if ( eqNum > 0 ) { + for (int i = 1; i <= eigenVectors.giveNumberOfColumns(); ++i ) { + // updateUnknownsDict should be changed to let the field have direct input rather than calling such a method. + // Until then, we "fake" a time step, relying on the fact that only the time-step number matters here. + TimeStep step(i, nullptr, 0, 1.0, 0.0, 0); + dof->updateUnknownsDictionary(&step, VM_Total, eigenVectors.at(eqNum, i)); + } + } + } + }; + + for ( auto &node : d->giveDofManagers() ) { + set_values(*node); + } + + for ( auto &elem : d->giveElements() ) { + int ndman = elem->giveNumberOfInternalDofManagers(); + for ( int i = 1; i <= ndman; i++ ) { + set_values(*elem->giveInternalDofManager(i)); + } + } + + for ( auto &bc : d->giveBcs() ) { + int ndman = bc->giveNumberOfInternalDofManagers(); + for ( int i = 1; i <= ndman; i++ ) { + set_values(*bc->giveInternalDofManager(i)); + } + } +} + + +void +EigenVectorPrimaryField :: applyDefaultInitialCondition() +{ } + + +void +EigenVectorPrimaryField :: advanceSolution(TimeStep *tStep) +{ } + +} // end namespace oofem diff --git a/src/oofemlib/eigenvectorprimaryfield.h b/src/oofemlib/eigenvectorprimaryfield.h new file mode 100644 index 000000000..ea540b400 --- /dev/null +++ b/src/oofemlib/eigenvectorprimaryfield.h @@ -0,0 +1,72 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef eigenvectorprimaryfield_h +#define eigenvectorprimaryfield_h + +#include "dofdistributedprimaryfield.h" + +namespace oofem { +/** + * Class representing the mode shapes of eigen vectors. + * The values are stored as VM_Total only. + * Active vector is determined by the time step number. + */ +class OOFEM_EXPORT EigenVectorPrimaryField : public DofDistributedPrimaryField +{ +public: + /** + * Constructor. Creates a field of given type associated to given domain. + * @param a Engineering model which field belongs to. + * @param idomain Index of domain for field. + * @param ft Type of stored field. + * @param nHist Number of old time steps to store (minimum 1), i.e. the number of eigen vectors. + */ + EigenVectorPrimaryField(EngngModel * a, int idomain, FieldType ft, int nHist); + virtual ~EigenVectorPrimaryField(); + + double giveUnknownValue(Dof *dof, ValueModeType mode, TimeStep *tStep) override; + + /** + * Stores all the eigenvectors in one call. + * @param eigenVectors Matrix with all eigen vectors (stored as columns) + * @param s Equation numbering for the rows of the vectors. + */ + void updateAll(const FloatMatrix &eigenVectors, const UnknownNumberingScheme &s); + + void applyDefaultInitialCondition() override; + void advanceSolution(TimeStep *tStep) override; +}; +} // end namespace oofem +#endif // eigenvectorprimaryfield_h diff --git a/src/oofemlib/element.C b/src/oofemlib/element.C index bc2bf239c..70dd50efd 100644 --- a/src/oofemlib/element.C +++ b/src/oofemlib/element.C @@ -634,11 +634,9 @@ Element :: giveCharacteristicValue(CharType mtrx, TimeStep *tStep) } -IRResultType -Element :: initializeFrom(InputRecord *ir) +void +Element :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - # ifdef VERBOSE // VERBOSE_PRINT1("Instanciating element ",number); # endif @@ -660,7 +658,7 @@ Element :: initializeFrom(InputRecord *ir) elemLocalCS.clear(); - if ( ir->hasField(_IFT_Element_lcs) ) { //local coordinate system + if ( ir.hasField(_IFT_Element_lcs) ) { //local coordinate system double n1 = 0.0, n2 = 0.0; FloatArray triplets; IR_GIVE_OPTIONAL_FIELD(ir, triplets, _IFT_Element_lcs); @@ -687,7 +685,7 @@ Element :: initializeFrom(InputRecord *ir) partitions.clear(); IR_GIVE_OPTIONAL_FIELD(ir, partitions, _IFT_Element_partitions); - if ( ir->hasField(_IFT_Element_remote) ) { + if ( ir.hasField(_IFT_Element_remote) ) { parallel_mode = Element_remote; } else { parallel_mode = Element_local; @@ -697,8 +695,6 @@ Element :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, activityTimeFunction, _IFT_Element_activityTimeFunction); IR_GIVE_OPTIONAL_FIELD(ir, numberOfGaussPoints, _IFT_Element_nip); - - return IRRT_OK; } @@ -766,11 +762,11 @@ Element :: printOutputAt(FILE *file, TimeStep *tStep) } if (this->isActivated(tStep) ) { - for ( auto &iRule: integrationRulesArray ) { - iRule->printOutputAt(file, tStep); - } + for ( auto &iRule: integrationRulesArray ) { + iRule->printOutputAt(file, tStep); + } } else { - fprintf(file, "is not active in current time step\n"); + fprintf(file, "is not active in current time step\n"); } } @@ -788,58 +784,46 @@ Element :: updateYourself(TimeStep *tStep) } } - + bool Element :: isActivated(TimeStep *tStep) { if ( activityTimeFunction ) { - if ( tStep ) { - return ( domain->giveFunction(activityTimeFunction)->evaluateAtTime( tStep->giveIntrinsicTime() ) > 1.e-3 ); - } else { - return false; - } + if ( tStep ) { + return ( domain->giveFunction(activityTimeFunction)->evaluateAtTime( tStep->giveIntrinsicTime() ) > 1.e-3 ); + } else { + return false; + } } else { - return true; + return true; } } - bool Element :: isCast(TimeStep *tStep) { + // this approach used to work when material was assigned to element + // if ( tStep->giveIntrinsicTime() >= this->giveMaterial()->giveCastingTime() ) + if ( tStep ) { - // this approach used to work when material was assigned to element - // if ( tStep->giveIntrinsicTime() >= this->giveMaterial()->giveCastingTime() ) + double castingTime; + double tNow = tStep->giveIntrinsicTime(); - - if ( tStep ) { + for ( auto &iRule : integrationRulesArray ) { + for ( auto &gp: *iRule ) { + castingTime = this->giveCrossSection()->giveMaterial(gp)->giveCastingTime(); - double castingTime; - double tNow = tStep->giveIntrinsicTime(); - - if ( integrationRulesArray.size() > 0 ) { - - for ( int i = 0; i < (int)integrationRulesArray.size(); i++ ) { - IntegrationRule *iRule; - iRule = integrationRulesArray [ i ].get(); - - for ( GaussPoint *gp: *iRule ) { - castingTime = this->giveCrossSection()->giveMaterial(gp)->giveCastingTime(); - - if (tNow < castingTime ) { - return false; - } + if ( tNow < castingTime ) { + return false; + } + } } - } + return true; + + } else { + return false; } - - return true; - - } else { - return false; - } - } void @@ -855,44 +839,37 @@ Element :: initForNewStep() } - -void -Element::giveBoundaryEdgeNodes (IntArray& bNodes, int boundary) +IntArray +Element::giveBoundaryEdgeNodes(int boundary) const { - this->giveInterpolation()->boundaryEdgeGiveNodes(bNodes, boundary); + return this->giveInterpolation()->boundaryEdgeGiveNodes(boundary); } -void -Element::giveBoundarySurfaceNodes (IntArray& bNodes, int boundary) +IntArray +Element::giveBoundarySurfaceNodes(int boundary) const { - this->giveInterpolation()->boundarySurfaceGiveNodes(bNodes, boundary); + return this->giveInterpolation()->boundarySurfaceGiveNodes(boundary); } -IntegrationRule* -Element::giveBoundaryEdgeIntegrationRule (int order, int boundary) +std::unique_ptr +Element::giveBoundaryEdgeIntegrationRule(int order, int boundary) { - return this->giveInterpolation()->giveBoundaryEdgeIntegrationRule(order, boundary); + return this->giveInterpolation()->giveBoundaryEdgeIntegrationRule(order, boundary); } -IntegrationRule* -Element::giveBoundarySurfaceIntegrationRule (int order, int boundary) +std::unique_ptr +Element::giveBoundarySurfaceIntegrationRule(int order, int boundary) { - return this->giveInterpolation()->giveBoundarySurfaceIntegrationRule(order, boundary); + return this->giveInterpolation()->giveBoundarySurfaceIntegrationRule(order, boundary); } - -contextIOResultType Element :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// saves full element context (saves state variables, that completely describe current state) +void Element :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - int _val; - - if ( ( iores = FEMComponent :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + FEMComponent :: saveContext(stream, mode); if ( ( mode & CM_Definition ) ) { + contextIOResultType iores; if ( !stream.write(numberOfDofMans) ) { THROW_CIOERR(CIO_IOERR); } @@ -936,7 +913,7 @@ contextIOResultType Element :: saveContext(DataStream &stream, ContextMode mode, } for ( auto &iRule: integrationRulesArray ) { - _val = iRule->giveIntegrationRuleType(); + int _val = iRule->giveIntegrationRuleType(); if ( !stream.write(_val) ) { THROW_CIOERR(CIO_IOERR); } @@ -958,24 +935,17 @@ contextIOResultType Element :: saveContext(DataStream &stream, ContextMode mode, } for ( auto &iRule: integrationRulesArray ) { - if ( ( iores = iRule->saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + iRule->saveContext(stream, mode); } - - return CIO_OK; } -contextIOResultType Element :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// restores full element context (saves state variables, that completely describe current state) +void Element :: restoreContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; int _nrules; - if ( ( iores = FEMComponent :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + FEMComponent :: restoreContext(stream, mode); if ( mode & CM_Definition ) { if ( !stream.read(numberOfDofMans) ) { @@ -1019,12 +989,12 @@ contextIOResultType Element :: restoreContext(DataStream &stream, ContextMode mo // AND ALLOCATE NEW ONE integrationRulesArray.resize( _nrules ); for ( int i = 0; i < _nrules; i++ ) { - integrationRulesArray [ i ].reset( classFactory.createIRule( ( IntegrationRuleType ) dtypes(i), i + 1, this ) ); + integrationRulesArray [ i ] = classFactory.createIRule( ( IntegrationRuleType ) dtypes[i], i + 1, this ); } } else { for ( int i = 0; i < _nrules; i++ ) { - if ( integrationRulesArray [ i ]->giveIntegrationRuleType() != dtypes(i) ) { - integrationRulesArray [ i ].reset( classFactory.createIRule( ( IntegrationRuleType ) dtypes(i), i + 1, this ) ); + if ( integrationRulesArray [ i ]->giveIntegrationRuleType() != dtypes[i] ) { + integrationRulesArray [ i ] = classFactory.createIRule( ( IntegrationRuleType ) dtypes[i], i + 1, this ); } } } @@ -1046,12 +1016,8 @@ contextIOResultType Element :: restoreContext(DataStream &stream, ContextMode mo for ( auto &iRule: integrationRulesArray ) { - if ( ( iores = iRule->restoreContext(stream, mode, this) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + iRule->restoreContext(stream, mode); } - - return CIO_OK; } @@ -1063,7 +1029,7 @@ Element :: computeVolumeAreaOrLength() double answer = 0.; IntegrationRule *iRule = this->giveDefaultIntegrationRulePtr(); if ( iRule ) { - for ( GaussPoint *gp: *iRule ) { + for ( auto &gp: *iRule ) { answer += this->computeVolumeAround(gp); } @@ -1146,16 +1112,15 @@ Element :: giveLengthInDir(const FloatArray &normalToCrackPlane) // (exploited by the crack band approach) // { - FloatArray *coords; - double maxDis, minDis, dis; + double maxDis, minDis; int nnode = giveNumberOfNodes(); - coords = this->giveNode(1)->giveCoordinates(); - minDis = maxDis = normalToCrackPlane.dotProduct( * coords, coords->giveSize() ); + const auto &coords = this->giveNode(1)->giveCoordinates(); + minDis = maxDis = normalToCrackPlane.dotProduct( coords, coords.giveSize() ); for ( int i = 2; i <= nnode; i++ ) { - coords = this->giveNode(i)->giveCoordinates(); - dis = normalToCrackPlane.dotProduct( * coords, coords->giveSize() ); + const auto &coords = this->giveNode(i)->giveCoordinates(); + double dis = normalToCrackPlane.dotProduct( coords, coords.giveSize() ); if ( dis > maxDis ) { maxDis = dis; } else if ( dis < minDis ) { diff --git a/src/oofemlib/element.h b/src/oofemlib/element.h index e31bb5573..15be34319 100644 --- a/src/oofemlib/element.h +++ b/src/oofemlib/element.h @@ -556,31 +556,29 @@ class OOFEM_EXPORT Element : public FEMComponent * @param bNodes list of boundary edge nodes * @param boundary edge id */ - virtual void giveBoundaryEdgeNodes (IntArray& bNodes, int boundary); + virtual IntArray giveBoundaryEdgeNodes(int boundary) const; /** * Returns list of receiver boundary nodes for given surface * @param bNodes list of boundary surface nodes * @param boundary surface id */ - virtual void giveBoundarySurfaceNodes (IntArray& bNodes, int boundary); + virtual IntArray giveBoundarySurfaceNodes(int boundary) const; /** * Returns boundary edge integration rule * @param order approximation order to integrate * @param boundary boundary edge id - * @note some elements may increase the order (like axusymmetric elements) + * @note some elements may increase the order (like axisymmetric elements) */ - virtual IntegrationRule* giveBoundaryEdgeIntegrationRule (int order, int boundary); + virtual std::unique_ptr giveBoundaryEdgeIntegrationRule(int order, int boundary); /** * Returns boundary surface integration rule * @param order approximation order to integrate * @param boundary boundary surface id - * @note some elements may increase the order (like axusymmetric elements) + * @note some elements may increase the order (like axisymmetric elements) */ - virtual IntegrationRule* giveBoundarySurfaceIntegrationRule (int order, int boundary); + virtual std::unique_ptr giveBoundarySurfaceIntegrationRule(int order, int boundary); - - // data management /** * Translates local to global indices for dof managers. @@ -640,6 +638,20 @@ class OOFEM_EXPORT Element : public FEMComponent int giveMaterialNumber() const {return material;} /// @return Reference to the associated crossSection of element. CrossSection *giveCrossSection(); + + + /** + * Gets the activity time function number. + */ + int getActivityTimeFunctionNumber(){ return this->activityTimeFunction; } + + + /** + * Sets the activity time function of receiver. + * @param funcIndx Index of new time function. + */ + void setActivityTimeFunctionNumber(int funcIndx){ this->activityTimeFunction = funcIndx; } + /** * Sets the material of receiver. * @param matIndx Index of new material. @@ -654,6 +666,8 @@ class OOFEM_EXPORT Element : public FEMComponent /// @return Number of dofmanagers of receiver. virtual int giveNumberOfDofManagers() const { return numberOfDofMans; } + /// Sets number of element dof managers + void setNumberOfDofManagers(int i) {this->numberOfDofMans = i;} /** * Returns number of nodes of receiver. * Default implementation returns number of dofmanagers of element @@ -760,7 +774,7 @@ class OOFEM_EXPORT Element : public FEMComponent * this is invoked after all domain components are instanciated. * @return Zero value if check fail, otherwise nonzero. */ - virtual int checkConsistency() { return 1; } + int checkConsistency() override { return 1; } /** * @return True, if receiver is activated for given solution step, otherwise false. @@ -986,7 +1000,7 @@ class OOFEM_EXPORT Element : public FEMComponent * to return an updated number of specified entity type based on old number. * @param f Decides the renumbering. */ - virtual void updateLocalNumbering(EntityRenumberingFunctor &f); + void updateLocalNumbering(EntityRenumberingFunctor &f) override; /// Integration point evaluator, loops over receiver IP's and calls given function (passed as f parameter) on them. The IP is parameter to function f. template< class T > void ipEvaluator( T *src, void ( T :: *f )( GaussPoint *gp ) ); @@ -1139,14 +1153,18 @@ class OOFEM_EXPORT Element : public FEMComponent IntArray *giveBoundaryLoadArray(); // Overloaded methods: - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual const char *giveClassName() const { return "Element"; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + const char *giveClassName() const override { return "Element"; } -protected: + void printOutputAt(FILE *file, TimeStep *tStep) override; + + virtual const IntArray giveLocation() {IntArray answer(0); return answer;} + virtual void recalculateCoordinates(int nodeNumber, FloatArray &coords){;} + + protected: /** * Initializes the array of integration rules member variable. * Element can have multiple integration rules for different tasks. diff --git a/src/oofemlib/elementinternaldofman.C b/src/oofemlib/elementinternaldofman.C index 580262166..42ca56e0a 100644 --- a/src/oofemlib/elementinternaldofman.C +++ b/src/oofemlib/elementinternaldofman.C @@ -49,14 +49,14 @@ ElementDofManager :: ~ElementDofManager() { } -IRResultType ElementDofManager :: initializeFrom(InputRecord *ir) +void ElementDofManager :: initializeFrom(InputRecord &ir) // Gets from the source line from the data file all the data of the receiver. { # ifdef VERBOSE // VERBOSE_PRINT1("Instanciating node ",number) # endif - return DofManager :: initializeFrom(ir); + DofManager :: initializeFrom(ir); } diff --git a/src/oofemlib/elementinternaldofman.h b/src/oofemlib/elementinternaldofman.h index f57386a04..d763fb1c0 100644 --- a/src/oofemlib/elementinternaldofman.h +++ b/src/oofemlib/elementinternaldofman.h @@ -67,12 +67,12 @@ class OOFEM_EXPORT ElementDofManager : public DofManager /// Destructor. virtual ~ElementDofManager(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void printYourself(); - virtual const char *giveClassName() const { return "ElementDofManager"; } - virtual const char *giveInputRecordName() const { return ""; } // Note: Can't be created in input files. + void initializeFrom(InputRecord &ir) override; + void printYourself() override; + const char *giveClassName() const override { return "ElementDofManager"; } + const char *giveInputRecordName() const override { return ""; } // Note: Can't be created in input files. - virtual bool isDofTypeCompatible(dofType type) const { return ( type == DT_master || type == DT_simpleSlave ); } + bool isDofTypeCompatible(dofType type) const override { return ( type == DT_master || type == DT_simpleSlave ); } }; } // end namespace oofem #endif // elementdofman_h diff --git a/src/oofemlib/elementside.C b/src/oofemlib/elementside.C index a271cdf31..aabcdf13f 100644 --- a/src/oofemlib/elementside.C +++ b/src/oofemlib/elementside.C @@ -51,14 +51,14 @@ ElementSide :: ~ElementSide() { } -IRResultType ElementSide :: initializeFrom(InputRecord *ir) +void ElementSide :: initializeFrom(InputRecord &ir) // Gets from the source line from the data file all the data of the receiver. { # ifdef VERBOSE // VERBOSE_PRINT1("Instanciating node ",number) # endif - return DofManager :: initializeFrom(ir); + DofManager :: initializeFrom(ir); } diff --git a/src/oofemlib/elementside.h b/src/oofemlib/elementside.h index 2510e0b39..d15054b5a 100644 --- a/src/oofemlib/elementside.h +++ b/src/oofemlib/elementside.h @@ -69,11 +69,10 @@ class OOFEM_EXPORT ElementSide : public DofManager /// Destructor. virtual ~ElementSide(); - // miscellaneous - virtual const char *giveClassName() const { return "ElementSide"; } - virtual const char *giveInputRecordName() const { return _IFT_ElementSide_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void printYourself(); + const char *giveClassName() const override { return "ElementSide"; } + const char *giveInputRecordName() const override { return _IFT_ElementSide_Name; } + void initializeFrom(InputRecord &ir) override; + void printYourself() override; /** * Computes receiver transformation matrix from global cs. to dofManager specific @@ -89,8 +88,8 @@ class OOFEM_EXPORT ElementSide : public DofManager * assembled. If dofIDArry is NULL, then all receiver dofs are assumed. */ virtual void computeTransformation(FloatMatrix &answer, const IntArray *dofIDArry); - virtual bool requiresTransformation() { return false; } - virtual bool isDofTypeCompatible(dofType type) const { return ( type == DT_master || type == DT_simpleSlave ); } + bool requiresTransformation() override { return false; } + bool isDofTypeCompatible(dofType type) const override { return ( type == DT_master || type == DT_simpleSlave ); } }; } // end namespace oofem #endif // elementside_h diff --git a/src/oofemlib/eleminterpunknownmapper.C b/src/oofemlib/eleminterpunknownmapper.C index 7f754b81c..ec5934b41 100644 --- a/src/oofemlib/eleminterpunknownmapper.C +++ b/src/oofemlib/eleminterpunknownmapper.C @@ -84,7 +84,7 @@ EIPrimaryUnknownMapper :: mapAndUpdate(FloatArray &answer, ValueModeType mode, #endif ///@todo Shouldn't we pass a primary field or something to this function? - if ( this->evaluateAt(unknownValues, dofidMask, mode, oldd, * node->giveCoordinates(), reglist, tStep) ) { + if ( this->evaluateAt(unknownValues, dofidMask, mode, oldd, node->giveCoordinates(), reglist, tStep) ) { ///@todo This doesn't respect local coordinate systems in nodes. Supporting that would require major reworking. for ( int ii = 1; ii <= dofidMask.giveSize(); ii++ ) { // exclude slaves; they are determined from masters @@ -109,7 +109,7 @@ EIPrimaryUnknownMapper :: mapAndUpdate(FloatArray &answer, ValueModeType mode, int EIPrimaryUnknownMapper :: evaluateAt(FloatArray &answer, IntArray &dofMask, ValueModeType mode, - Domain *oldd, FloatArray &coords, IntArray ®List, TimeStep *tStep) + Domain *oldd, const FloatArray &coords, IntArray ®List, TimeStep *tStep) { Element *oelem; SpatialLocalizer *sl = oldd->giveSpatialLocalizer(); @@ -120,11 +120,11 @@ EIPrimaryUnknownMapper :: evaluateAt(FloatArray &answer, IntArray &dofMask, Valu } else { // Take the minimum of any region double mindist = 0.0, distance; - oelem = NULL; + oelem = nullptr; for ( int i = 1; i <= regList.giveSize(); ++i ) { Element *tmpelem = sl->giveElementClosestToPoint( lcoords, closest, coords, regList.at(i) ); - if ( tmpelem != NULL ) { - distance = closest.distance_square(coords); + if ( tmpelem ) { + distance = distance_square(closest, coords); if ( distance < mindist || i == 1 ) { mindist = distance; oelem = tmpelem; diff --git a/src/oofemlib/eleminterpunknownmapper.h b/src/oofemlib/eleminterpunknownmapper.h index 536e736b6..32506d3a3 100644 --- a/src/oofemlib/eleminterpunknownmapper.h +++ b/src/oofemlib/eleminterpunknownmapper.h @@ -55,10 +55,10 @@ class OOFEM_EXPORT EIPrimaryUnknownMapper : public PrimaryUnknownMapper /// Destructor virtual ~EIPrimaryUnknownMapper() { } - virtual int mapAndUpdate(FloatArray &answer, ValueModeType mode, - Domain *oldd, Domain *newd, TimeStep *tStep); - virtual int evaluateAt(FloatArray &answer, IntArray &dofMask, ValueModeType mode, - Domain *oldd, FloatArray &coords, IntArray ®List, TimeStep *tStep); + int mapAndUpdate(FloatArray &answer, ValueModeType mode, + Domain *oldd, Domain *newd, TimeStep *tStep) override; + int evaluateAt(FloatArray &answer, IntArray &dofMask, ValueModeType mode, + Domain *oldd, const FloatArray &coords, IntArray ®List, TimeStep *tStep) override; }; } // end namespace oofem #endif // eleminterpunknownmapper_h diff --git a/src/oofemlib/emptycs.C b/src/oofemlib/emptycs.C index 4b8bd17f2..3586b2a3e 100644 --- a/src/oofemlib/emptycs.C +++ b/src/oofemlib/emptycs.C @@ -40,11 +40,9 @@ REGISTER_CrossSection(EmptyCS); EmptyCS :: EmptyCS(int n, Domain *d) : CrossSection(n, d) { } -EmptyCS :: ~EmptyCS() { } - -Material* EmptyCS::giveMaterial(IntegrationPoint* ip) +Material* EmptyCS::giveMaterial(IntegrationPoint* ip) const { - return NULL; + return nullptr; } } // end namespace oofem diff --git a/src/oofemlib/emptycs.h b/src/oofemlib/emptycs.h index b671d0244..d5667e539 100644 --- a/src/oofemlib/emptycs.h +++ b/src/oofemlib/emptycs.h @@ -52,16 +52,14 @@ class OOFEM_EXPORT EmptyCS : public CrossSection * @param d Domain for cross section. */ EmptyCS(int n, Domain * d); - /// Destructor. - virtual ~EmptyCS(); - virtual Material *giveMaterial(IntegrationPoint *ip); - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) { return 1; } - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) { return 1; } - virtual int estimatePackSize(DataStream &buff, GaussPoint *ip) { return 0; } + Material *giveMaterial(IntegrationPoint *ip) const override; + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override { return 1; } + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override { return 1; } + int estimatePackSize(DataStream &buff, GaussPoint *ip) override { return 0; } - virtual const char *giveClassName() const { return "EmptyCS"; } - virtual const char *giveInputRecordName() const { return _IFT_EmptyCS_Name; } + const char *giveClassName() const override { return "EmptyCS"; } + const char *giveInputRecordName() const override { return _IFT_EmptyCS_Name; } }; } // end namespace oofem #endif // emptycs_h diff --git a/src/oofemlib/engngm.C b/src/oofemlib/engngm.C index c2a63e680..7ab851717 100644 --- a/src/oofemlib/engngm.C +++ b/src/oofemlib/engngm.C @@ -70,6 +70,7 @@ #include "unknownnumberingscheme.h" #include "contact/contactmanager.h" + #ifdef __PARALLEL_MODE #include "problemcomm.h" #include "processcomm.h" @@ -79,25 +80,22 @@ #include #include #include -// include unistd.h; needed for access -#ifdef HAVE_UNISTD_H - #include -#elif _MSC_VER - #include +#ifdef _OPENMP + #include #endif - #ifdef __OOFEG #include "oofeggraphiccontext.h" #endif - namespace oofem { -EngngModel :: EngngModel(int i, EngngModel *_master) : domainNeqs(), domainPrescribedNeqs() +EngngModel :: EngngModel(int i, EngngModel *_master) : domainNeqs(), domainPrescribedNeqs(), + exportModuleManager(this), + initModuleManager(this), + monitorManager(this) { suppressOutput = false; number = i; - defaultErrEstimator = NULL; numberOfSteps = 0; numberOfEquations = 0; numberOfPrescribedEquations = 0; @@ -117,8 +115,6 @@ EngngModel :: EngngModel(int i, EngngModel *_master) : domainNeqs(), domainPresc pMode = _processor; // for giveContextFile() pScale = macroScale; - exportModuleManager = new ExportModuleManager(this); - initModuleManager = new InitModuleManager(this); master = _master; // master mode by default // create context if in master mode; otherwise request context from master if ( master ) { @@ -148,10 +144,6 @@ EngngModel :: EngngModel(int i, EngngModel *_master) : domainNeqs(), domainPresc EngngModel :: ~EngngModel() { - delete exportModuleManager; - - delete initModuleManager; - // master deletes the context if ( master == NULL ) { delete context; @@ -162,14 +154,7 @@ EngngModel :: ~EngngModel() fclose(outputStream); } - delete defaultErrEstimator; - #ifdef __PARALLEL_MODE - if ( loadBalancingFlag ) { - delete lb; - delete lbm; - } - delete communicator; delete nonlocCommunicator; delete commBuff; @@ -197,20 +182,16 @@ EngngModel :: Instanciate_init() domainList.clear(); domainList.reserve(ndomains); for ( int i = 1; i <= ndomains; i++ ) { - domainList.emplace_back(new Domain(i, 0, this)); + domainList.push_back(std::make_unique(i, 0, this)); } this->initParallelContexts(); } -int EngngModel :: instanciateYourself(DataReader *dr, InputRecord *ir, const char *dataOutputFileName, const char *desc) -// simple input - only number of steps variable is read +int EngngModel :: instanciateYourself(DataReader &dr, InputRecord &ir, const char *dataOutputFileName, const char *desc) { - OOFEMTXTDataReader *txtReader = dynamic_cast< OOFEMTXTDataReader* > (dr); - if ( txtReader != NULL ) { - referenceFileName = std :: string(txtReader->giveDataSourceName()); - } + referenceFileName = dr.giveReferenceName(); bool inputReaderFinish = true; @@ -229,50 +210,55 @@ int EngngModel :: instanciateYourself(DataReader *dr, InputRecord *ir, const cha this->startTime = time(NULL); # ifdef VERBOSE - OOFEM_LOG_DEBUG( "Reading all data from input file %s\n", dr->giveDataSourceName() ); + OOFEM_LOG_DEBUG( "Reading all data from \"%s\"\n", referenceFileName.c_str() ); # endif simulationDescription = std::string(desc); - // instanciate receiver - this->initializeFrom(ir); - exportModuleManager->initializeFrom(ir); - initModuleManager->initializeFrom(ir); + try { + // instanciate receiver + this->initializeFrom(ir); + exportModuleManager.initializeFrom(ir); + initModuleManager.initializeFrom(ir); + monitorManager.initializeFrom(ir); - if ( this->nMetaSteps == 0 ) { - inputReaderFinish = false; - this->instanciateDefaultMetaStep(ir); - } else { - this->instanciateMetaSteps(dr); - } + if ( this->nMetaSteps == 0 ) { + inputReaderFinish = false; + this->instanciateDefaultMetaStep(ir); + } else { + this->instanciateMetaSteps(dr); + } - // instanciate initialization module manager - initModuleManager->instanciateYourself(dr, ir); - // instanciate export module manager - exportModuleManager->instanciateYourself(dr, ir); - this->instanciateDomains(dr); + // instanciate initialization module manager + initModuleManager.instanciateYourself(dr, ir); + // instanciate export module manager + exportModuleManager.instanciateYourself(dr, ir); + // instanciate monitor manager + monitorManager.instanciateYourself(dr, ir); + this->instanciateDomains(dr); - exportModuleManager->initialize(); + exportModuleManager.initialize(); - // Milan ?????????????????? - //GPImportModule* gim = new GPImportModule(this); - //gim -> getInput(); - // Milan ?????????????????? + // Milan ?????????????????? + //GPImportModule* gim = new GPImportModule(this); + //gim -> getInput(); + // Milan ?????????????????? - // check emodel input record if no default metastep, since all has been read - if ( inputReaderFinish ) { - ir->finish(); + // check emodel input record if no default metastep, since all has been read + if ( inputReaderFinish ) { + ir.finish(); + } + } catch ( InputException &e ) { + OOFEM_ERROR("Error initializing from user input: %s\n", e.what()); } return 1; } -IRResultType -EngngModel :: initializeFrom(InputRecord *ir) +void +EngngModel :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, numberOfSteps, _IFT_EngngModel_nsteps); if ( numberOfSteps <= 0 ) { OOFEM_ERROR("nsteps not specified, bad format"); @@ -316,10 +302,10 @@ EngngModel :: initializeFrom(InputRecord *ir) #endif - suppressOutput = ir->hasField(_IFT_EngngModel_suppressOutput); + suppressOutput = ir.hasField(_IFT_EngngModel_suppressOutput); - if(suppressOutput) { -// printf("Suppressing output.\n"); + if ( suppressOutput ) { + //printf("Suppressing output.\n"); } else { @@ -337,13 +323,11 @@ EngngModel :: initializeFrom(InputRecord *ir) } #endif } - - return IRRT_OK; } int -EngngModel :: instanciateDomains(DataReader *dr) +EngngModel :: instanciateDomains(DataReader &dr) { int result = 1; // read problem domains @@ -356,12 +340,9 @@ EngngModel :: instanciateDomains(DataReader *dr) } - int -EngngModel :: instanciateMetaSteps(DataReader *dr) +EngngModel :: instanciateMetaSteps(DataReader &dr) { - int result = 1; - // create meta steps metaStepList.clear(); metaStepList.reserve(nMetaSteps); @@ -372,18 +353,17 @@ EngngModel :: instanciateMetaSteps(DataReader *dr) // read problem domains for ( int i = 1; i <= this->nMetaSteps; i++ ) { - InputRecord *ir = dr->giveInputRecord(DataReader :: IR_mstepRec, i); - result &= metaStepList[i-1].initializeFrom(ir); + auto &ir = dr.giveInputRecord(DataReader :: IR_mstepRec, i); + metaStepList[i-1].initializeFrom(ir); } - this->numberOfSteps = metaStepList.size(); - return result; + return 1; } int -EngngModel :: instanciateDefaultMetaStep(InputRecord *ir) +EngngModel :: instanciateDefaultMetaStep(InputRecord &ir) { if ( numberOfSteps == 0 ) { OOFEM_ERROR("nsteps cannot be zero"); @@ -393,7 +373,7 @@ EngngModel :: instanciateDefaultMetaStep(InputRecord *ir) this->nMetaSteps = 1; metaStepList.clear(); //MetaStep *mstep = new MetaStep(1, this, numberOfSteps, *ir); - metaStepList.emplace_back(1, this, numberOfSteps, *ir); + metaStepList.emplace_back(1, this, numberOfSteps, ir); return 1; } @@ -522,12 +502,11 @@ EngngModel :: solveYourself() } for ( int imstep = smstep; imstep <= nMetaSteps; imstep++, sjstep = 1 ) { //loop over meta steps - MetaStep *activeMStep = this->giveMetaStep(imstep); + auto activeMStep = this->giveMetaStep(imstep); // update state according to new meta step this->initMetaStepAttributes(activeMStep); - int nTimeSteps = activeMStep->giveNumberOfSteps(); - for ( int jstep = sjstep; jstep <= nTimeSteps; jstep++ ) { //loop over time steps + for ( int jstep = sjstep; jstep <= activeMStep->giveNumberOfSteps(); jstep++ ) { //loop over time steps this->timer.startTimer(EngngModelTimer :: EMTT_SolutionStepTimer); this->timer.initTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); @@ -570,7 +549,6 @@ EngngModel :: solveYourself() TimeStep* EngngModel :: generateNextStep() { - /* code */ int smstep = 1, sjstep = 1; if ( this->currentStep ) { smstep = this->currentStep->giveMetaStepNumber(); @@ -595,14 +573,14 @@ EngngModel :: initMetaStepAttributes(MetaStep *mStep) // update attributes this->updateAttributes(mStep); // virtual function // finish data acquiring - mStep->giveAttributesRecord()->finish(); + mStep->giveAttributesRecord().finish(); } void EngngModel :: updateAttributes(MetaStep *mStep) { MetaStep *mStep1 = this->giveMetaStep( mStep->giveNumber() ); //this line ensures correct input file in staggered problem - InputRecord *ir = mStep1->giveAttributesRecord(); + auto &ir = mStep1->giveAttributesRecord(); if ( this->giveNumericalMethod(mStep1) ) { this->giveNumericalMethod(mStep1)->initializeFrom(ir); @@ -668,11 +646,14 @@ EngngModel :: updateYourself(TimeStep *tStep) void EngngModel :: terminate(TimeStep *tStep) { - if(!suppressOutput) { - this->doStepOutput(tStep); - fflush( this->giveOutputStream() ); + if ( !suppressOutput ) { + this->doStepOutput(tStep); + fflush( this->giveOutputStream() ); + } else { + exportModuleManager.doOutput(tStep); } - + monitorManager.update(tStep, Monitor::MonitorEvent::TimeStepTermination); + this->saveStepContext(tStep, CM_State | CM_Definition); } @@ -686,7 +667,7 @@ EngngModel :: doStepOutput(TimeStep *tStep) } // export using export manager - exportModuleManager->doOutput(tStep); + exportModuleManager.doOutput(tStep); } void @@ -726,6 +707,79 @@ EngngModel :: printOutputAt(FILE *file, TimeStep *tStep) } } + +void +EngngModel :: printOutputAt(FILE *file, TimeStep *tStep, const IntArray &nodeSets, const IntArray &elementSets) +{ + for ( auto &domain: domainList ) { + int dnum = domain->giveNumber(); + fprintf( file, "Output for domain %3d\n", dnum ); + int nset = nodeSets.giveSize() < dnum ? 0 : nodeSets.at(dnum); + int eset = elementSets.giveSize() < dnum ? 0 : elementSets.at(dnum); + + this->outputNodes(file, *domain, tStep, nset); + this->outputElements(file, *domain, tStep, eset); + ///@todo Add general support for reaction forces +#if 0 + this->outputReactionForces(file, *domain, tStep, nset); +#endif + } +} + + +void +EngngModel :: outputNodes(FILE *file, Domain &domain, TimeStep *tStep, int setNum) +{ + fprintf(file, "\n\nNode output:\n------------------\n"); + + if ( setNum == 0 ) { // No set specified, export all + for ( auto &dman : domain.giveDofManagers() ) { + if ( dman->giveParallelMode() == DofManager_null ) { + continue; + } + dman->printOutputAt(file, tStep); + } + } else { + auto &nodes = domain.giveSet(setNum)->giveNodeList(); + + for ( int inode : nodes ) { + auto dman = domain.giveDofManager(inode); + if ( dman->giveParallelMode() == DofManager_null ) { + continue; + } + dman->printOutputAt(file, tStep); + } + } + fprintf(file, "\n\n"); +} + + +void +EngngModel :: outputElements(FILE *file, Domain &domain, TimeStep *tStep, int setNum) +{ + fprintf(file, "\n\nElement output:\n---------------\n"); + + if ( setNum == 0 ) { + for ( auto &elem : domain.giveElements() ) { + if ( elem->giveParallelMode() == Element_remote ) { + continue; + } + elem->printOutputAt(file, tStep); + } + } else { + auto &elements = domain.giveSet(setNum)->giveElementList(); + for ( int ielem : elements ) { + auto element = domain.giveElement(ielem); + if ( element->giveParallelMode() == Element_remote ) { + continue; + } + element->printOutputAt(file, tStep); + } + } + fprintf(file, "\n\n"); +} + + void EngngModel :: printYourself() { printf("\nEngineeringModel: instance %s\n", this->giveClassName() ); @@ -740,20 +794,21 @@ void EngngModel :: printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep) void EngngModel :: assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma, const UnknownNumberingScheme &s, Domain *domain) -// -// assembles matrix -// { IntArray loc; FloatMatrix mat, R; +#ifdef _OPENMP + omp_lock_t writelock; + omp_init_lock(&writelock); +#endif this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); int nelem = domain->giveNumberOfElements(); #ifdef _OPENMP - #pragma omp parallel for shared(answer) private(mat, R, loc) +#pragma omp parallel for shared(answer) private(mat, R, loc) #endif for ( int ielem = 1; ielem <= nelem; ielem++ ) { - Element *element = domain->giveElement(ielem); + auto element = domain->giveElement(ielem); // skip remote elements (these are used as mirrors of remote elements on other domains // when nonlocal constitutive models are used. They introduction is necessary to // allow local averaging on domains without fine grain communication between domains). @@ -779,15 +834,25 @@ void EngngModel :: assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAss } } - int nbc = domain->giveNumberOfBoundaryConditions(); - for ( int i = 1; i <= nbc; ++i ) { - GeneralBoundaryCondition *bc = domain->giveBc(i); - ActiveBoundaryCondition *abc; - Load *load; - - if ( ( abc = dynamic_cast< ActiveBoundaryCondition * >(bc) ) ) { +#ifdef _OPENMP +#pragma omp parallel for shared(answer) private(mat, R, loc) +#endif + //for ( auto &bc : domain->giveBcs() ) { //problems with OPENMP + for (size_t i = 0; i < domain->giveBcs().size(); i++) { + auto &bc = domain->giveBcs()[i]; + auto abc = dynamic_cast< ActiveBoundaryCondition * >(bc.get()); + if ( abc ) { + /// @note: Some active bcs still make changes even when they are not applied + /// We should probably reconsider this approach, so that they e.g. just prescribe their lagrange mult. instead. +#ifdef _OPENMP + ma.assembleFromActiveBC(answer, *abc, tStep, s, s, &writelock); +#else ma.assembleFromActiveBC(answer, *abc, tStep, s, s); - } else if ( bc->giveSetNumber() && ( load = dynamic_cast< Load * >(bc) ) && bc->isImposed(tStep) ) { +#endif + } else if ( bc->giveSetNumber() ) { + if ( !bc->isImposed(tStep) ) continue; + auto load = dynamic_cast< Load * >(bc.get()); + if ( !load ) continue; // Now we assemble the corresponding load type for the respective components in the set: IntArray loc, bNodes; FloatMatrix mat, R; @@ -798,8 +863,8 @@ void EngngModel :: assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAss if ( ( bodyLoad = dynamic_cast< BodyLoad * >(load) ) ) { // Body load: const IntArray &elements = set->giveElementList(); - for ( int ielem = 1; ielem <= elements.giveSize(); ++ielem ) { - Element *element = domain->giveElement( elements.at(ielem) ); + for ( auto ielem : elements ) { + auto element = domain->giveElement( ielem ); mat.clear(); ma.matrixFromLoad(mat, *element, bodyLoad, tStep); @@ -809,43 +874,62 @@ void EngngModel :: assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAss } ma.locationFromElement(loc, *element, s); +#ifdef _OPENMP + omp_set_lock(&writelock); +#endif answer.assemble(loc, mat); +#ifdef _OPENMP + omp_unset_lock(&writelock); +#endif } } - } else if ( ( sLoad = dynamic_cast< SurfaceLoad * >(load) ) ) { // Surface load: - const IntArray &boundaries = set->giveBoundaryList(); - for ( int ibnd = 1; ibnd <= boundaries.giveSize() / 2; ++ibnd ) { - Element *element = domain->giveElement( boundaries.at(ibnd * 2 - 1) ); - int boundary = boundaries.at(ibnd * 2); + } else if ( ( sLoad = dynamic_cast< SurfaceLoad * >(load) ) ) { + const auto &surfaces = set->giveBoundaryList(); + for ( int ibnd = 1; ibnd <= surfaces.giveSize() / 2; ++ibnd ) { + auto element = domain->giveElement( surfaces.at(ibnd * 2 - 1) ); + int boundary = surfaces.at(ibnd * 2); mat.clear(); ma.matrixFromSurfaceLoad(mat, *element, sLoad, boundary, tStep); if ( mat.isNotEmpty() ) { - element->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + bNodes = element->giveInterpolation()->boundaryGiveNodes(boundary); if ( element->computeDofTransformationMatrix(R, bNodes, false) ) { mat.rotatedWith(R); } ma.locationFromElementNodes(loc, *element, bNodes, s); + +#ifdef _OPENMP + omp_set_lock(&writelock); +#endif answer.assemble(loc, mat); +#ifdef _OPENMP + omp_unset_lock(&writelock); +#endif } } - } else if ( ( eLoad = dynamic_cast< EdgeLoad * >(load) ) ) { // Edge load: - const IntArray &edgeBoundaries = set->giveEdgeList(); - for ( int ibnd = 1; ibnd <= edgeBoundaries.giveSize() / 2; ++ibnd ) { - Element *element = domain->giveElement( edgeBoundaries.at(ibnd * 2 - 1) ); - int boundary = edgeBoundaries.at(ibnd * 2); + } else if ( ( eLoad = dynamic_cast< EdgeLoad * >(load) ) ) { + const auto &edges = set->giveEdgeList(); + for ( int ibnd = 1; ibnd <= edges.giveSize() / 2; ++ibnd ) { + auto element = domain->giveElement( edges.at(ibnd * 2 - 1) ); + int boundary = edges.at(ibnd * 2); mat.clear(); ma.matrixFromEdgeLoad(mat, *element, eLoad, boundary, tStep); if ( mat.isNotEmpty() ) { - element->giveInterpolation()->boundaryEdgeGiveNodes(bNodes, boundary); + bNodes = element->giveInterpolation()->boundaryEdgeGiveNodes(boundary); if ( element->computeDofTransformationMatrix(R, bNodes, false) ) { mat.rotatedWith(R); } ma.locationFromElementNodes(loc, *element, bNodes, s); +#ifdef _OPENMP + omp_set_lock(&writelock); +#endif answer.assemble(loc, mat); +#ifdef _OPENMP + omp_unset_lock(&writelock); +#endif } } } @@ -853,7 +937,7 @@ void EngngModel :: assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAss } if ( domain->hasContactManager() ) { - OOFEM_ERROR("Contant problems temporarily deactivated"); + OOFEM_ERROR("Contact problems temporarily deactivated"); //domain->giveContactManager()->assembleTangentFromContacts(answer, tStep, type, s, s); } @@ -871,11 +955,15 @@ void EngngModel :: assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAss { IntArray r_loc, c_loc, dofids(0); FloatMatrix mat, R; +#ifdef _OPENMP + omp_lock_t writelock; + omp_init_lock(&writelock); +#endif this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); int nelem = domain->giveNumberOfElements(); #ifdef _OPENMP - #pragma omp parallel for shared(answer) private(mat, R, r_loc, c_loc) +#pragma omp parallel for shared(answer) private(mat, R, r_loc, c_loc) #endif for ( int ielem = 1; ielem <= nelem; ielem++ ) { Element *element = domain->giveElement(ielem); @@ -903,11 +991,19 @@ void EngngModel :: assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAss } } - int nbc = domain->giveNumberOfBoundaryConditions(); - for ( int i = 1; i <= nbc; ++i ) { - ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( domain->giveBc(i) ); +#ifdef _OPENMP +#pragma omp parallel for shared(answer) private(mat, R, r_loc, c_loc) +#endif + //for ( auto &gbc : domain->giveBcs() ) { //problems with OPENMP + for (size_t i = 0; i < domain->giveBcs().size(); i++) { + auto &gbc = domain->giveBcs()[i]; + ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() ); if ( bc != NULL ) { +#ifdef _OPENMP + ma.assembleFromActiveBC(answer, *bc, tStep, rs, cs, &writelock); +#else ma.assembleFromActiveBC(answer, *bc, tStep, rs, cs); +#endif } } @@ -966,7 +1062,7 @@ void EngngModel :: assembleVectorFromDofManagers(FloatArray &answer, TimeStep *t this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); // Note! For normal master dofs, loc is unique to each node, but there can be slave dofs, so we must keep it shared, unfortunately. #ifdef _OPENMP - #pragma omp parallel for shared(answer, eNorms) private(R, charVec, loc, dofids) +#pragma omp parallel for shared(answer, eNorms) private(R, charVec, loc, dofids) #endif for ( int i = 1; i <= nnode; i++ ) { DofManager *node = domain->giveDofManager(i); @@ -1013,18 +1109,29 @@ void EngngModel :: assembleVectorFromBC(FloatArray &answer, TimeStep *tStep, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms) { int nbc = domain->giveNumberOfBoundaryConditions(); +#ifdef _OPENMP + omp_lock_t writelock; + omp_init_lock(&writelock); +#endif this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); +#ifdef _OPENMP +#pragma omp parallel for shared(answer, eNorms) +#endif for ( int i = 1; i <= nbc; ++i ) { GeneralBoundaryCondition *bc = domain->giveBc(i); ActiveBoundaryCondition *abc; Load *load; if ( ( abc = dynamic_cast< ActiveBoundaryCondition * >(bc) ) ) { +#ifdef _OPENMP + va.assembleFromActiveBC(answer, *abc, tStep, mode, s, eNorms, &writelock); +#else va.assembleFromActiveBC(answer, *abc, tStep, mode, s, eNorms); +#endif } else if ( bc->giveSetNumber() && ( load = dynamic_cast< Load * >(bc) ) && bc->isImposed(tStep) ) { // Now we assemble the corresponding load type fo the respective components in the set: - IntArray dofids, loc, bNodes; + IntArray dofids, loc; FloatArray charVec; FloatMatrix R; BodyLoad *bodyLoad; @@ -1048,11 +1155,16 @@ void EngngModel :: assembleVectorFromBC(FloatArray &answer, TimeStep *tStep, } va.locationFromElement(loc, *element, s, & dofids); +#ifdef _OPENMP + omp_set_lock(&writelock); +#endif answer.assemble(charVec, loc); - if ( eNorms ) { eNorms->assembleSquared(charVec, dofids); } +#ifdef _OPENMP + omp_unset_lock(&writelock); +#endif } } } @@ -1068,17 +1180,23 @@ void EngngModel :: assembleVectorFromBC(FloatArray &answer, TimeStep *tStep, if ( charVec.isNotEmpty() ) { //element->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); - element->giveBoundarySurfaceNodes(bNodes, boundary); + auto bNodes = element->giveBoundarySurfaceNodes(boundary); if ( element->computeDofTransformationMatrix(R, bNodes, false) ) { charVec.rotatedWith(R, 't'); } va.locationFromElementNodes(loc, *element, bNodes, s, & dofids); +#ifdef _OPENMP + omp_set_lock(&writelock); +#endif answer.assemble(charVec, loc); if ( eNorms ) { eNorms->assembleSquared(charVec, dofids); } +#ifdef _OPENMP + omp_unset_lock(&writelock); +#endif } } } @@ -1093,17 +1211,23 @@ void EngngModel :: assembleVectorFromBC(FloatArray &answer, TimeStep *tStep, if ( charVec.isNotEmpty() ) { //element->giveInterpolation()->boundaryEdgeGiveNodes(bNodes, boundary); - element->giveBoundaryEdgeNodes(bNodes, boundary); + auto bNodes = element->giveBoundaryEdgeNodes(boundary); if ( element->computeDofTransformationMatrix(R, bNodes, false) ) { charVec.rotatedWith(R, 't'); } va.locationFromElementNodes(loc, *element, bNodes, s, & dofids); +#ifdef _OPENMP + omp_set_lock(&writelock); +#endif answer.assemble(charVec, loc); if ( eNorms ) { eNorms->assembleSquared(charVec, dofids); } +#ifdef _OPENMP + omp_unset_lock(&writelock); +#endif } } } @@ -1120,11 +1244,17 @@ void EngngModel :: assembleVectorFromBC(FloatArray &answer, TimeStep *tStep, } node->giveLocationArray(nLoad->giveDofIDs(), loc, s); +#ifdef _OPENMP + omp_set_lock(&writelock); +#endif answer.assemble(charVec, loc); if ( eNorms ) { eNorms->assembleSquared(charVec, dofids); } +#ifdef _OPENMP + omp_unset_lock(&writelock); +#endif } } } @@ -1147,7 +1277,7 @@ void EngngModel :: assembleVectorFromElements(FloatArray &answer, TimeStep *tSte FloatMatrix R; FloatArray charVec; int nelem = domain->giveNumberOfElements(); - + bool assembleFlag = false; ///@todo Checking the chartype is not since there could be some other chartype in the future. We need to try and deal with chartype in a better way. /// For now, this is the best we can do. @@ -1159,10 +1289,11 @@ void EngngModel :: assembleVectorFromElements(FloatArray &answer, TimeStep *tSte this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); ///@todo Consider using private answer variables and sum them up at the end, but it just might be slower then a shared variable. #ifdef _OPENMP - #pragma omp parallel for shared(answer, eNorms) private(R, charVec, loc, dofids) +#pragma omp parallel for shared(answer, eNorms) private(R, charVec, loc, dofids) #endif for ( int i = 1; i <= nelem; i++ ) { - Element *element = domain->giveElement(i); + + Element *element = domain->giveElement(i); // skip remote elements (these are used as mirrors of remote elements on other domains // when nonlocal constitutive models are used. They introduction is necessary to @@ -1175,16 +1306,15 @@ void EngngModel :: assembleVectorFromElements(FloatArray &answer, TimeStep *tSte continue; } - va.vectorFromElement(charVec, *element, tStep, mode); + if ( charVec.isNotEmpty() ) { if ( element->giveRotationMatrix(R) ) { charVec.rotatedWith(R, 't'); } va.locationFromElement(loc, *element, s, & dofids); - #ifdef _OPENMP - #pragma omp critical +#pragma omp critical #endif { answer.assemble(charVec, loc); @@ -1193,7 +1323,24 @@ void EngngModel :: assembleVectorFromElements(FloatArray &answer, TimeStep *tSte } } } + } + +#ifdef _OPENMP +#pragma omp parallel for shared(answer, eNorms) private(R, charVec, loc, dofids) +#endif + for ( int i = 1; i <= nelem; i++ ) { + Element *element = domain->giveElement(i); + + // skip remote elements (these are used as mirrors of remote elements on other domains + // when nonlocal constitutive models are used. They introduction is necessary to + // allow local averaging on domains without fine grain communication between domains). + if ( element->giveParallelMode() == Element_remote ) { + continue; + } + if ( !element->isActivated(tStep) || !this->isElementActivated(element) ) { + continue; + } // obtain form element its body, surface, edge, and point loads const IntArray& list = element->giveBodyLoadList(); @@ -1210,67 +1357,92 @@ void EngngModel :: assembleVectorFromElements(FloatArray &answer, TimeStep *tSte } va.locationFromElement(loc, *element, s, & dofids); - answer.assemble(charVec, loc); - - if ( eNorms ) { - eNorms->assembleSquared(charVec, dofids); +#ifdef _OPENMP +#pragma omp critical +#endif + { + answer.assemble(charVec, loc); + if ( eNorms ) { + eNorms->assembleSquared(charVec, dofids); + } } } } } // loop over body load list } // if (!(list = element->giveBodyLoadList()).isEmpty()) + } + +#ifdef _OPENMP +#pragma omp parallel for shared(answer, eNorms) private(R, charVec, loc, dofids, assembleFlag) +#endif + for ( int i = 1; i <= nelem; i++ ) { + Element *element = domain->giveElement(i); + + // skip remote elements (these are used as mirrors of remote elements on other domains + // when nonlocal constitutive models are used. They introduction is necessary to + // allow local averaging on domains without fine grain communication between domains). + if ( element->giveParallelMode() == Element_remote ) { + continue; + } + + if ( !element->isActivated(tStep) || !this->isElementActivated(element) ) { + continue; + } // obtain from element its boundaryloads (surface+edge) const IntArray& list2 = element->giveBoundaryLoadList(); - IntArray bNodes; - if (!list2.isEmpty()) { - for (int j=1; j<=list2.giveSize()/2; j++) { // loop over boundary loads + + for (int j=1; j<=list2.giveSize()/2; j++) { // loop over boundary loads int iload = list2.at(j * 2 - 1) ; int boundary = list2.at(j * 2); SurfaceLoad *sLoad; EdgeLoad *eLoad; + assembleFlag = false; + IntArray bNodes; + if ((eLoad = dynamic_cast< EdgeLoad * >(domain->giveLoad(iload)))) { - charVec.clear(); - va.vectorFromEdgeLoad(charVec, *element, eLoad, boundary, tStep, mode); - - if ( charVec.isNotEmpty() ) { - //element->giveInterpolation()->boundaryEdgeGiveNodes(bNodes, boundary); - element->giveBoundaryEdgeNodes(bNodes, boundary); - if ( element->computeDofTransformationMatrix(R, bNodes, false) ) { - charVec.rotatedWith(R, 't'); - } - - va.locationFromElementNodes(loc, *element, bNodes, s, & dofids); - answer.assemble(charVec, loc); - - if ( eNorms ) { - eNorms->assembleSquared(charVec, dofids); + charVec.clear(); + va.vectorFromEdgeLoad(charVec, *element, eLoad, boundary, tStep, mode); + + if ( charVec.isNotEmpty() ) { + //element->giveInterpolation()->boundaryEdgeGiveNodes(bNodes, boundary); + bNodes = element->giveBoundaryEdgeNodes(boundary); + if ( element->computeDofTransformationMatrix(R, bNodes, false) ) { + charVec.rotatedWith(R, 't'); + } + assembleFlag = true; } - } } else if ((sLoad = dynamic_cast< SurfaceLoad * >(domain->giveLoad(iload)))) { - charVec.clear(); - va.vectorFromSurfaceLoad(charVec, *element, sLoad, boundary, tStep, mode); - - if ( charVec.isNotEmpty() ) { - //element->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); - element->giveBoundarySurfaceNodes(bNodes, boundary); - if ( element->computeDofTransformationMatrix(R, bNodes, false) ) { - charVec.rotatedWith(R, 't'); - } - - va.locationFromElementNodes(loc, *element, bNodes, s, & dofids); - answer.assemble(charVec, loc); - - if ( eNorms ) { - eNorms->assembleSquared(charVec, dofids); + charVec.clear(); + va.vectorFromSurfaceLoad(charVec, *element, sLoad, boundary, tStep, mode); + + if ( charVec.isNotEmpty() ) { + //element->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + bNodes = element->giveBoundarySurfaceNodes(boundary); + if ( element->computeDofTransformationMatrix(R, bNodes, false) ) { + charVec.rotatedWith(R, 't'); + } + assembleFlag = true; } - } } else { - OOFEM_ERROR ("Unsupported element boundary load type"); + OOFEM_ERROR ("Unsupported element boundary load type"); } - } - } // end loop over lement boundary loads + + if ( assembleFlag ) { + // assemble the contribution + va.locationFromElementNodes(loc, *element, bNodes, s, & dofids); +#ifdef _OPENMP +#pragma omp critical +#endif + { + answer.assemble(charVec, loc); + if ( eNorms ) { + eNorms->assembleSquared(charVec, dofids); + } + } + } // end loop over lement boundary loads + } } // end loop over elements @@ -1293,7 +1465,7 @@ EngngModel :: assembleExtrapolatedForces(FloatArray &answer, TimeStep *tStep, Ch this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); #ifdef _OPENMP - #pragma omp parallel for shared(answer) private(R, charMatrix, charVec, loc, delta_u) +//#pragma omp parallel for shared(answer) private(R, charMatrix, charVec, loc, delta_u) #endif for ( int i = 1; i <= nelems; i++ ) { Element *element = domain->giveElement(i); @@ -1309,11 +1481,12 @@ EngngModel :: assembleExtrapolatedForces(FloatArray &answer, TimeStep *tStep, Ch continue; } - element->giveLocationArray(loc, dn); + element->giveLocationArray(loc, dn); // Take the tangent from the previous step ///@todo This is not perfect. It is probably no good for viscoelastic materials, and possibly other scenarios that are rate dependent ///(tangent will be computed for the previous step, with whatever deltaT it had) + element->giveCharacteristicMatrix(charMatrix, type, tStep); if ( charMatrix.isNotEmpty() ) { ///@note Temporary work-around for active b.c. used in multiscale (it can't support VM_Incremental easily). @@ -1341,7 +1514,7 @@ EngngModel :: assembleExtrapolatedForces(FloatArray &answer, TimeStep *tStep, Ch ///@todo Deal with element deactivation and reactivation properly. #ifdef _OPENMP - #pragma omp critical +#pragma omp critical #endif { answer.assemble(charVec, loc); @@ -1349,6 +1522,7 @@ EngngModel :: assembleExtrapolatedForces(FloatArray &answer, TimeStep *tStep, Ch } } + this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); } @@ -1369,7 +1543,7 @@ EngngModel :: assemblePrescribedExtrapolatedForces(FloatArray &answer, TimeStep this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); #ifdef _OPENMP - #pragma omp parallel for shared(answer) private(R, charMatrix, charVec, loc, delta_u) +//#pragma omp parallel for shared(answer) private(R, charMatrix, charVec, loc, delta_u) #endif for ( int i = 1; i <= nelems; i++ ) { Element *element = domain->giveElement(i); @@ -1423,15 +1597,32 @@ EngngModel :: assembleVectorFromContacts(FloatArray &answer, TimeStep *tStep, Ch void EngngModel :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) -// -// updates some component, which is used by numerical method -// to newly reached state -// { OOFEM_ERROR("Unknown Type of component."); } +void +EngngModel :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) +{ + OOFEM_ERROR("updateSolution is not implemented."); +} + + +void +EngngModel :: updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorms) +{ + OOFEM_ERROR("updateInternalRHS is not implemented."); +} + + +void +EngngModel :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) +{ + OOFEM_ERROR("updateMatrix is not implemented."); +} + + void EngngModel :: initStepIncrements() // @@ -1461,10 +1652,10 @@ void EngngModel :: updateDomainLinks() { this->giveExportModuleManager()->initialize(); -}; +} -contextIOResultType EngngModel :: saveContext(DataStream &stream, ContextMode mode) +void EngngModel :: saveContext(DataStream &stream, ContextMode mode) // // this procedure is used mainly for two reasons: // @@ -1485,10 +1676,12 @@ contextIOResultType EngngModel :: saveContext(DataStream &stream, ContextMode mo { contextIOResultType iores; - if ( ( iores = giveCurrentStep()->saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); + if ( !stream.write(giveCurrentStep()->giveNumber()) ) { + THROW_CIOERR(CIO_IOERR); } + giveCurrentStep()->saveContext(stream); + if ( !stream.write(numberOfEquations) ) { THROW_CIOERR(CIO_IOERR); } @@ -1516,16 +1709,12 @@ contextIOResultType EngngModel :: saveContext(DataStream &stream, ContextMode mo // store nMethod NumericalMethod *nmethod = this->giveNumericalMethod( this->giveMetaStep( giveCurrentStep()->giveMetaStepNumber() ) ); if ( nmethod ) { - if ( ( iores = nmethod->saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + nmethod->saveContext(stream, mode); } - - return CIO_OK; } -contextIOResultType EngngModel :: restoreContext(DataStream *stream, ContextMode mode, void *obj) +void EngngModel :: restoreContext(DataStream &stream, ContextMode mode) // // this procedure is used mainly for two reasons: // @@ -1544,34 +1733,20 @@ contextIOResultType EngngModel :: restoreContext(DataStream *stream, ContextMode // This version loads only Element and Material properties. // // This function is inverse to the saveContext() member function -// -// WARNING obj is cast into int pointer to time step for which to seek Context. -// { contextIOResultType iores; - int closeFlag = 0, istep, iversion; - FILE *file = NULL; - this->resolveCorrespondingStepNumber(istep, iversion, obj); - OOFEM_LOG_RELEVANT("Restoring context for time step %d.%d\n", istep, iversion); - - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; + // restore solution step + int istep; + if ( !stream.read(istep) ) { + THROW_CIOERR(CIO_IOERR); } - // restore solution step if ( !currentStep ) { - currentStep.reset( new TimeStep(istep, this, 0, 0., 0., 0) ); + currentStep = std::make_unique(istep, this, 0, 0., 0., 0); } - if ( ( iores = currentStep->restoreContext(*stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + currentStep->restoreContext(stream); // this->updateAttributes (currentStep); @@ -1582,80 +1757,45 @@ contextIOResultType EngngModel :: restoreContext(DataStream *stream, ContextMode } } - previousStep.reset( new TimeStep(istep - 1, this, pmstep, currentStep->giveTargetTime ( ) - currentStep->giveTimeIncrement(), - currentStep->giveTimeIncrement(), currentStep->giveSolutionStateCounter() - 1) ); + previousStep = std::make_unique(istep - 1, this, pmstep, currentStep->giveTargetTime ( ) - currentStep->giveTimeIncrement(), + currentStep->giveTimeIncrement(), currentStep->giveSolutionStateCounter() - 1); // restore numberOfEquations and domainNeqs array - if ( !stream->read(numberOfEquations) ) { + if ( !stream.read(numberOfEquations) ) { THROW_CIOERR(CIO_IOERR); } - if ( ( iores = domainNeqs.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = domainNeqs.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } // restore numberOfPrescribedEquations and domainNeqs array - if ( !stream->read(numberOfPrescribedEquations) ) { + if ( !stream.read(numberOfPrescribedEquations) ) { THROW_CIOERR(CIO_IOERR); } - if ( ( iores = domainPrescribedNeqs.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = domainPrescribedNeqs.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } // restore renumber flag - if ( !stream->read(renumberFlag) ) { + if ( !stream.read(renumberFlag) ) { THROW_CIOERR(CIO_IOERR); } for ( auto &domain: domainList ) { - domain->restoreContext(*stream, mode); + domain->restoreContext(stream, mode); } // restore nMethod NumericalMethod *nmethod = this->giveNumericalMethod( this->giveCurrentMetaStep() ); if ( nmethod ) { - if ( ( iores = nmethod->restoreContext(*stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + nmethod->restoreContext(stream, mode); } this->updateDomainLinks(); this->updateAttributes( this->giveCurrentMetaStep() ); this->initStepIncrements(); - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } // ensure consistent records - - return CIO_OK; -} - - -void -EngngModel :: resolveCorrespondingStepNumber(int &istep, int &iversion, void *obj) -{ - // - // returns corresponding step number - // - if ( obj == NULL ) { - istep = 1; - iversion = 0; - return; - } - - istep = * ( int * ) obj; - iversion = * ( ( ( int * ) obj ) + 1 ); - - if ( istep > this->giveNumberOfSteps() ) { - istep = this->giveNumberOfSteps(); - } - - if ( istep <= 0 ) { - istep = 1; - } } @@ -1666,31 +1806,8 @@ EngngModel :: giveCurrentMetaStep() } -int -EngngModel :: giveContextFile(FILE **contextFile, int tStepNumber, int stepVersion, ContextFileMode cmode, int errLevel) -{ - std :: string fname = giveContextFileName(tStepNumber, stepVersion); - - if ( cmode == contextMode_read ) { - * contextFile = fopen(fname.c_str(), "rb"); // open for reading - } else { - * contextFile = fopen(fname.c_str(), "wb"); // open for writing, - } - - // rewind (*contextFile); // seek the beginning - // // overwrite if exist - // else *contextFile = fopen(fname,"r+"); // open for reading and writing - - if ( ( * contextFile == NULL ) && errLevel > 0 ) { - OOFEM_ERROR("can't open %s", fname.c_str()); - } - - return 1; -} - - std ::string -EngngModel :: giveContextFileName(int tStepNumber, int stepVersion) +EngngModel :: giveContextFileName(int tStepNumber, int stepVersion) const { std :: string fname = this->coreOutputFileName; char fext [ 100 ]; @@ -1699,43 +1816,13 @@ EngngModel :: giveContextFileName(int tStepNumber, int stepVersion) } -bool -EngngModel :: testContextFile(int tStepNumber, int stepVersion) -{ - std :: string fname = giveContextFileName(tStepNumber, stepVersion); - -#ifdef HAVE_ACCESS - return access(fname.c_str(), R_OK) == 0; - -#elif _MSC_VER - return _access(fname.c_str(), 4) == 0; - -#else - return true; - -#endif -} - -DataReader * -EngngModel :: GiveDomainDataReader(int domainNum, int domainSerNum, ContextFileMode cmode) -// -// -// returns domain i/o file -// returns nonzero on success -// +std :: string +EngngModel :: giveDomainFileName(int domainNum, int domainSerNum) const { std :: string fname = this->coreOutputFileName; char fext [ 100 ]; sprintf(fext, ".domain.%d.%d.din", domainNum, domainSerNum); - fname += fext; - - DataReader *dr; - - if ( ( dr = new OOFEMTXTDataReader( fname ) ) == NULL ) { - OOFEM_ERROR("Creation of DataReader failed"); - } - - return dr; + return fname + fext; } std :: string @@ -1869,7 +1956,7 @@ EngngModel :: terminateAnalysis() OOFEM_LOG_FORCED("\n\nANALYSIS FINISHED\n\n\n"); OOFEM_LOG_FORCED("Real time consumed: %03dh:%02dm:%02ds\n", rhrs, rmin, rsec); OOFEM_LOG_FORCED("User time consumed: %03dh:%02dm:%02ds\n", uhrs, umin, usec); - exportModuleManager->terminate(); + exportModuleManager.terminate(); } int @@ -1914,7 +2001,7 @@ EngngModel :: postInitialize() void EngngModel :: init() { - initModuleManager->doInit(); + initModuleManager.doInit(); } @@ -2129,13 +2216,13 @@ int EngngModel :: packRemoteElementData(ProcessCommunicator &processComm) { int result = 1; - IntArray const *toSendMap = processComm.giveToSendMap(); - CommunicationBuffer *send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); + const IntArray &toSendMap = processComm.giveToSendMap(); + CommunicationBuffer &send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); Domain *domain = this->giveDomain(1); - for ( int i = 1; i <= toSendMap->giveSize(); i++ ) { - result &= domain->giveElement( toSendMap->at(i) )->packUnknowns( * send_buff, this->giveCurrentStep() ); + for ( int ielem : toSendMap ) { + result &= domain->giveElement( ielem )->packUnknowns( send_buff, this->giveCurrentStep() ); } return result; @@ -2146,15 +2233,15 @@ int EngngModel :: unpackRemoteElementData(ProcessCommunicator &processComm) { int result = 1; - IntArray const *toRecvMap = processComm.giveToRecvMap(); - CommunicationBuffer *recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); + const IntArray &toRecvMap = processComm.giveToRecvMap(); + CommunicationBuffer &recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); Domain *domain = this->giveDomain(1); - for ( int i = 1; i <= toRecvMap->giveSize(); i++ ) { - Element *element = domain->giveElement( toRecvMap->at(i) ); + for ( int ielem : toRecvMap ) { + Element *element = domain->giveElement( ielem ); if ( element->giveParallelMode() == Element_remote ) { - result &= element->unpackAndUpdateUnknowns( * recv_buff, this->giveCurrentStep() ); + result &= element->unpackAndUpdateUnknowns( recv_buff, this->giveCurrentStep() ); } else { OOFEM_ERROR("element is not remote"); } @@ -2171,14 +2258,14 @@ EngngModel :: packDofManagers(ArrayWithNumbering *srcData, ProcessCommunicator & const UnknownNumberingScheme &s = * srcData->numbering; int result = 1; Domain *domain = this->giveDomain(1); - IntArray const *toSendMap = processComm.giveToSendMap(); + const IntArray &toSendMap = processComm.giveToSendMap(); ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); ///@todo Shouldn't hardcode domain number 1 ///@todo Must fix: Internal dofmanagers in xfem and bc - for ( int i = 1; i <= toSendMap->giveSize(); i++ ) { - DofManager *dman = domain->giveDofManager( toSendMap->at(i) ); - for ( Dof *jdof: *dman ) { + for ( int inode : toSendMap ) { + DofManager *dman = domain->giveDofManager( inode ); + for ( auto &jdof: *dman ) { if ( jdof->isPrimaryDof() ) { int eqNum = jdof->giveEquationNumber(s); if ( eqNum ) { @@ -2199,16 +2286,16 @@ EngngModel :: unpackDofManagers(ArrayWithNumbering *destData, ProcessCommunicato const UnknownNumberingScheme &s = * destData->numbering; int result = 1; Domain *domain = this->giveDomain(1); - IntArray const *toRecvMap = processComm.giveToRecvMap(); + const IntArray &toRecvMap = processComm.giveToRecvMap(); ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); double value; ///@todo Shouldn't hardcode domain number 1 ///@todo Must fix: Internal dofmanagers in bc - for ( int i = 1; i <= toRecvMap->giveSize(); i++ ) { - DofManager *dman = domain->giveDofManager( toRecvMap->at(i) ); + for ( int inode : toRecvMap ) { + DofManager *dman = domain->giveDofManager( inode ); dofManagerParallelMode dofmanmode = dman->giveParallelMode(); - for ( Dof *jdof: *dman ) { + for ( auto &jdof: *dman ) { int eqNum = jdof->giveEquationNumber(s); if ( jdof->isPrimaryDof() && eqNum ) { result &= pcbuff->read(value); diff --git a/src/oofemlib/engngm.h b/src/oofemlib/engngm.h index a56d37220..997b72789 100644 --- a/src/oofemlib/engngm.h +++ b/src/oofemlib/engngm.h @@ -55,6 +55,9 @@ #include "contextioresulttype.h" #include "metastep.h" #include "parallelcontext.h" +#include "exportmodulemanager.h" +#include "initmodulemanager.h" +#include "monitormanager.h" #ifdef __PARALLEL_MODE #include "parallel.h" @@ -247,9 +250,11 @@ class OOFEM_EXPORT EngngModel int contextOutputStep; /// Export module manager. - ExportModuleManager *exportModuleManager; + ExportModuleManager exportModuleManager; /// Initialization module manager. - InitModuleManager *initModuleManager; + InitModuleManager initModuleManager; + /// Monitor manager. + MonitorManager monitorManager; /// Domain mode. problemMode pMode; @@ -270,7 +275,7 @@ class OOFEM_EXPORT EngngModel /// Type of non linear formulation (total or updated formulation). enum fMode nonLinFormulation; /// Error estimator. Useful for adaptivity, or simply printing errors output. - ErrorEstimator *defaultErrEstimator; + std::unique_ptr defaultErrEstimator; /// Domain rank in a group of collaborating processes (0..groupSize-1). int rank; @@ -289,8 +294,8 @@ class OOFEM_EXPORT EngngModel /**@name Load balancing attributes */ //@{ /// Load Balancer. - LoadBalancer *lb; - LoadBalancerMonitor *lbm; + std::unique_ptr lb; + std::unique_ptr lbm; /// If set to true, load balancing is active. bool loadBalancingFlag; /// Debug flag forcing load balancing after first step. @@ -346,9 +351,9 @@ class OOFEM_EXPORT EngngModel bool giveSuppressOutput() const { return suppressOutput; } /** Service for accessing ErrorEstimator corresponding to particular domain */ - virtual ErrorEstimator *giveDomainErrorEstimator(int n) { return defaultErrEstimator; } + virtual ErrorEstimator *giveDomainErrorEstimator(int n) { return defaultErrEstimator.get(); } /** Returns material interface representation for given domain */ - virtual MaterialInterface *giveMaterialInterface(int n) { return NULL; } + virtual MaterialInterface *giveMaterialInterface(int n) { return nullptr; } void setNumberOfEquations(int id, int neq) { numberOfEquations = neq; domainNeqs.at(id) = neq; @@ -520,7 +525,8 @@ class OOFEM_EXPORT EngngModel /// Only relevant for eigen value analysis. Otherwise returns zero. virtual double giveEigenValue(int eigNum) { return 0.0; } - + /// Only relevant for eigen value analysis. Otherwise does noting. + virtual void setActiveVector(int i) { } /** * Exchanges necessary remote DofManagers data. * @todo The name and description of this function is misleading, the function really just accumulates the total values for shared "equations". @@ -603,7 +609,7 @@ class OOFEM_EXPORT EngngModel * Prints header, opens the outFileName, instanciate itself the receiver using * using virtual initializeFrom service and instanciates all problem domains. */ - virtual int instanciateYourself(DataReader *dr, InputRecord *ir, const char *outFileName, const char *desc); + virtual int instanciateYourself(DataReader &dr, InputRecord &ir, const char *outFileName, const char *desc); /** * Initialization of the receiver state (opening the default output stream, empty domain creation, * initialization of parallel context, etc) @@ -616,13 +622,13 @@ class OOFEM_EXPORT EngngModel * InitString can be imagined as data record in component database * belonging to receiver. Receiver may use value-name extracting functions * to extract particular field from record.*/ - virtual IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); /// Instanciate problem domains by calling their instanciateYourself() service - int instanciateDomains(DataReader *dr); + int instanciateDomains(DataReader &dr); /// Instanciate problem meta steps by calling their instanciateYourself() service - int instanciateMetaSteps(DataReader *dr); + int instanciateMetaSteps(DataReader &dr); /// Instanciate default metastep, if nmsteps is zero - virtual int instanciateDefaultMetaStep(InputRecord *ir); + virtual int instanciateDefaultMetaStep(InputRecord &ir); /** * Update receiver attributes according to step metaStep attributes. @@ -647,10 +653,9 @@ class OOFEM_EXPORT EngngModel * integration points (and material statuses) are stored. * @param stream Context stream. * @param mode Determines amount of info in stream. - * @return contextIOResultType. * @exception ContextIOERR If error encountered. */ - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); + virtual void saveContext(DataStream &stream, ContextMode mode); /** * Restores the state of model from output stream. Restores not only the receiver state, * but also same function is invoked for all DofManagers and Elements in associated @@ -663,12 +668,9 @@ class OOFEM_EXPORT EngngModel * context. * @param stream Context file. * @param mode Determines amount of info in stream. - * @param obj Void pointer to an int array containing two values:time step number and - * version of a context file to be restored. - * @return contextIOResultType. * @exception ContextIOERR exception if error encountered. */ - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + virtual void restoreContext(DataStream &stream, ContextMode mode); /** * Updates domain links after the domains of receiver have changed. Used mainly after * restoring context - the domains may change and this service is then used @@ -676,7 +678,6 @@ class OOFEM_EXPORT EngngModel * like error estimators, solvers, etc, having domains as attributes. */ virtual void updateDomainLinks(); - void resolveCorrespondingStepNumber(int &, int &, void *obj); /// Returns current meta step. MetaStep *giveCurrentMetaStep(); /** Returns current time step. @@ -755,9 +756,9 @@ class OOFEM_EXPORT EngngModel /// Returns the time step number, when initial conditions should apply. int giveNumberOfTimeStepWhenIcApply() { return 0; } /// Returns reference to receiver's numerical method. - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep) { return NULL; } + virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep) { return nullptr; } /// Returns receiver's export module manager. - ExportModuleManager *giveExportModuleManager() { return exportModuleManager; } + ExportModuleManager *giveExportModuleManager() { return &exportModuleManager; } /// Returns reference to receiver timer (EngngModelTimer). EngngModelTimer *giveTimer() { return & timer; } @@ -777,43 +778,46 @@ class OOFEM_EXPORT EngngModel * can be numbered separately. */ virtual int giveNewPrescribedEquationNumber(int domain, DofIDItem) { return ++domainPrescribedNeqs.at(domain); } - /** - * Assigns context file-descriptor for given step number to stream. - * Returns nonzero on success. - * @param contextFile Assigned file descriptor. - * @param tStepNumber Solution step number to store/restore. - * @param stepVersion Version of step. - * @param cmode Determines the i/o mode of context file. - * @param errLevel Determines the amount of warning messages if errors are encountered, level 0 no warnings reported. - */ - int giveContextFile(FILE **contextFile, int tStepNumber, int stepVersion, - ContextFileMode cmode, int errLevel = 1); /** * Returns the filename for the context file for the given step and version * @param tStepNumber Solution step number to store/restore. * @param stepVersion Version of step. */ - std :: string giveContextFileName(int tStepNumber, int stepVersion); - /** Returns true if context file for given step and version is available */ - bool testContextFile(int tStepNumber, int stepVersion); + std :: string giveContextFileName(int tStepNumber, int stepVersion) const; /** - * Creates new DataReader for given domain. - * Returns nonzero on success. + * Returns the filename for the given domain (used by adaptivity and restore) * @param domainNum Domain number. * @param domainSerNum Domain serial number. - * @param cmode Determines the i/o mode of context file. */ - DataReader *GiveDomainDataReader(int domainNum, int domainSerNum, ContextFileMode cmode); + std :: string giveDomainFileName(int domainNum, int domainSerNum) const; + virtual void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d); /** - * Updates components mapped to numerical method if necessary during solution process. - * Some numerical methods may require updating - * mapped components during solution process (e.g., updating of tangent stiffness - * when using updated Newton-Raphson method). + * Updates the solution (guess) according to the new values. + * Callback for nonlinear solvers (e.g. Newton-Raphson), and are called before new internal forces are computed. + * @param solutionVector New solution. * @param tStep Time when component is updated. - * @param cmpn Numerical component to update. * @param d Domain. */ - virtual void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d); + virtual void updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d); + /** + * Updates the solution (guess) according to the new values. + * Callback for nonlinear solvers (e.g. Newton-Raphson). + * @param solutionVector New solution. + * @param tStep Time when component is updated. + * @param d Domain. + * @param eNorm Optional per-element norm (for normalization). + */ + virtual void updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm); + /** + * Updates the solution (guess) according to the new values. + * Callback for nonlinear solvers (e.g. Newton-Raphson). + * @note For performance, the matrix should keep it's non-zero structure between calls, + * so the caller should make sure *not* to clear the matrix object before called. + * @param solutionVector New solution. + * @param tStep Time when component is updated. + * @param d Domain. + */ + virtual void updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d); /** * Initializes solution of new time step. Default implementation * resets all internal history variables (in integration points of elements) @@ -882,7 +886,13 @@ class OOFEM_EXPORT EngngModel * actual one to avoid storage of complete history. */ virtual int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) { return 0; } - + /** + * Temporary method for allowing code to seamlessly convert from the old to new way of handling DOF values. + * (the new way expects the field to store all values, regardless of if they are computed, from BC, or IC.) + * This is used by MasterDof + * @todo When all models have converted to using a field, this should be removed. + */ + virtual bool newDofHandling() { return false; } /** * Returns the parallel context corresponding to given domain (n) and unknown type * Default implementation returns i-th context from parallelContextList. @@ -1031,7 +1041,23 @@ class OOFEM_EXPORT EngngModel * (gaussPoint::printOutputAt). */ virtual void printOutputAt(FILE *file, TimeStep *tStep); - + virtual void printOutputAt(FILE *file, TimeStep *tStep, const IntArray &nodeSets, const IntArray &elementSets); + /** + * Outputs all nodes in the given set. + * @param file Output stream. + * @param domain Domain. + * @param tStep Time step. + * @param setNum Set number. If zero, outputs all elements. + */ + void outputNodes(FILE *file, Domain &domain, TimeStep *tStep, int setNum); + /** + * Outputs all elements in the given set. + * @param file Output stream. + * @param domain Domain. + * @param tStep Time step. + * @param setNum Set number. If zero, outputs all elements. + */ + void outputElements(FILE *file, Domain &domain, TimeStep *tStep, int setNum); // input / output /// Prints state of receiver. Useful for debugging. @@ -1119,7 +1145,6 @@ class OOFEM_EXPORT EngngModel virtual bool isElementActivated( int elemNum ) { return true; } virtual bool isElementActivated( Element *e ) { return true; } - #ifdef __OOFEG virtual void drawYourself(oofegGraphicContext &gc); @@ -1131,6 +1156,11 @@ class OOFEM_EXPORT EngngModel virtual void showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep) { } #endif +#ifdef _PYBIND_BINDINGS + void setNumberOfDomains(const int& i) {this->ndomains=i;} + const int& getNumberOfDomains() const {return this->ndomains;} +#endif + /// Returns string for prepending output (used by error reporting macros). std :: string errorInfo(const char *func) const; }; diff --git a/src/oofemlib/entityrenumberingscheme.h b/src/oofemlib/entityrenumberingscheme.h index bd2d66dc0..c78b608c8 100644 --- a/src/oofemlib/entityrenumberingscheme.h +++ b/src/oofemlib/entityrenumberingscheme.h @@ -36,6 +36,7 @@ #define entityrenumberingscheme_h #include +#include #include "oofemcfg.h" #include "error.h" @@ -98,23 +99,24 @@ template< class TClass > class SpecificEntityRenumberingFunctor : public EntityR class OOFEM_EXPORT MapBasedEntityRenumberingFunctor : public EntityRenumberingFunctor { private: - std :: map< int, int > &dofmanMap, &elemMap; + std :: unordered_map< int, int > &dofmanMap, &elemMap; public: - MapBasedEntityRenumberingFunctor(std :: map< int, int > & _dofmanMap, std :: map< int, int > & _elemMap) : + MapBasedEntityRenumberingFunctor(std :: unordered_map< int, int > & _dofmanMap, std :: unordered_map< int, int > & _elemMap) : dofmanMap(_dofmanMap), elemMap(_elemMap) { } - virtual int operator() (int n, EntityRenumberingScheme ers) + int operator() (int n, EntityRenumberingScheme ers) override { - std :: map< int, int > :: const_iterator it; if ( ers == ERS_DofManager ) { - if ( ( it = dofmanMap.find(n) ) != dofmanMap.end() ) { - return it->second; + auto pos = dofmanMap.find(n); + if (pos != dofmanMap.end()) { + return pos->second; } } else if ( ers == ERS_Element ) { - if ( ( it = elemMap.find(n) ) != elemMap.end() ) { - return it->second; + auto pos = elemMap.find(n); + if ( pos != elemMap.end() ) { + return pos->second; } } else { OOFEM_ERROR("unsupported EntityRenumberingScheme"); @@ -124,7 +126,7 @@ class OOFEM_EXPORT MapBasedEntityRenumberingFunctor : public EntityRenumberingFu return 0; } - virtual int call(int n, EntityRenumberingScheme ers) + int call(int n, EntityRenumberingScheme ers) override { return this->operator() (n, ers); }; }; } // end namespace oofem diff --git a/src/oofemlib/error.C b/src/oofemlib/error.C index 64485ab64..936818456 100644 --- a/src/oofemlib/error.C +++ b/src/oofemlib/error.C @@ -35,12 +35,35 @@ #include "error.h" #include +#include + + namespace oofem { + + std::string errorInfo(const char *func) { return std :: string(func); } +RuntimeException::RuntimeException(const char * _func, const char * _file, int _line, const char *format, ...) +{ + char stream [500]; + va_list args; + va_start(args, format); + vsprintf(stream, format, args); + va_end(args); + msg = stream; + + sprintf(stream, "\nIn %s (%s:%d)", _func, _file, _line); + msg += stream; +} + +const char* RuntimeException::what() const noexcept +{ + return msg.c_str(); +} + } // end namespace oofem diff --git a/src/oofemlib/error.h b/src/oofemlib/error.h index a9b409f04..8c580dd25 100644 --- a/src/oofemlib/error.h +++ b/src/oofemlib/error.h @@ -44,6 +44,8 @@ #include #include #include +#include + namespace oofem { /** Cause oofem program termination by calling exit. */ @@ -52,13 +54,24 @@ namespace oofem { fprintf(stderr, "oofem exit code %d\n", code); \ exit(code); + +class RuntimeException : public std::exception +{ +public: + std::string msg; + + RuntimeException(const char* _func, const char* _file, int _line, const char *format, ...); + const char* what() const noexcept override; +}; + + /** * Macros for printing errors. * This macro can be used only within classes that implement errorInfo function. */ //@{ -#define OOFEM_FATAL(...) { oofem_logger.writeELogMsg(Logger :: LOG_LEVEL_FATAL, errorInfo(__func__).c_str(), __FILE__, __LINE__, __VA_ARGS__); OOFEM_EXIT(1); } -#define OOFEM_ERROR(...) { oofem_logger.writeELogMsg(Logger :: LOG_LEVEL_ERROR, errorInfo(__func__).c_str(), __FILE__, __LINE__, __VA_ARGS__); OOFEM_EXIT(1); } +#define OOFEM_FATAL(...) { throw RuntimeException(__func__, __FILE__, __LINE__, __VA_ARGS__);} +#define OOFEM_ERROR(...) { throw RuntimeException(__func__, __FILE__, __LINE__, __VA_ARGS__);} #define OOFEM_WARNING(...) oofem_logger.writeELogMsg(Logger :: LOG_LEVEL_WARNING, errorInfo(__func__).c_str(), __FILE__, __LINE__, __VA_ARGS__) #define OOFEM_SERROR(...) { oofem_logger.writeELogMsg(Logger :: LOG_LEVEL_ERROR, __func__, __FILE__, __LINE__, __VA_ARGS__); OOFEM_EXIT(1); } #define OOFEM_SWARNING(...) oofem_logger.writeELogMsg(Logger :: LOG_LEVEL_WARNING, __func__, __FILE__, __LINE__, __VA_ARGS__) diff --git a/src/oofemlib/errorcheckingexportmodule.C b/src/oofemlib/errorcheckingexportmodule.C index 006a8aa85..3141436cc 100644 --- a/src/oofemlib/errorcheckingexportmodule.C +++ b/src/oofemlib/errorcheckingexportmodule.C @@ -45,12 +45,11 @@ #include "classfactory.h" #include "dof.h" #include "oofemtxtinputrecord.h" -#include "irresulttype.h" #include "mathfem.h" #ifdef __SM_MODULE - #include "../sm/EngineeringModels/structengngmodel.h" - #include "../sm/Elements/Beams/beam2d.h" - #include "../sm/Elements/Beams/beam3d.h" + #include "sm/EngineeringModels/structengngmodel.h" + #include "sm/Elements/Beams/beam2d.h" + #include "sm/Elements/Beams/beam3d.h" #endif namespace oofem { @@ -68,7 +67,6 @@ NodeErrorCheckingRule :: NodeErrorCheckingRule(const std :: string &line, double ErrorCheckingRule(tol) { /* - IRResultType result; char unknown; std :: string kwd; OOFEMTXTInputRecord rec (0, line), *ptr = &rec; @@ -111,7 +109,7 @@ bool NodeErrorCheckingRule :: check(Domain *domain, TimeStep *tStep) { // Rule doesn't apply yet. - if ( (tStep->giveNumber() != tstep ) || (tStep->giveVersion() != tsubstep) ) { + if ( tStep->giveNumber() != tstep || tStep->giveVersion() != tsubstep ) { return true; } @@ -170,7 +168,7 @@ bool ElementErrorCheckingRule :: check(Domain *domain, TimeStep *tStep) { // Rule doesn't apply yet. - if ( (tStep->giveNumber() != tstep ) || (tStep->giveVersion() != tsubstep) ) { + if ( tStep->giveNumber() != tstep || tStep->giveVersion() != tsubstep ) { return true; } @@ -231,7 +229,7 @@ bool BeamElementErrorCheckingRule :: check(Domain *domain, TimeStep *tStep) { // Rule doesn't apply yet. - if ( (tStep->giveNumber() != tstep ) || (tStep->giveVersion() != tsubstep) ) { + if ( tStep->giveNumber() != tstep || tStep->giveVersion() != tsubstep ) { return true; } @@ -246,18 +244,23 @@ BeamElementErrorCheckingRule :: check(Domain *domain, TimeStep *tStep) } } if ( element->giveParallelMode() != Element_local ) { - return true; + return true; } if (ist == BET_localEndDisplacement) { - element->computeVectorOf(VM_Total, tStep, val); + element->computeVectorOf(VM_Total, tStep, val); } else if (ist == BET_localEndForces) { - if(Beam2d* b = dynamic_cast(element)) b->giveEndForcesVector(val, tStep); - else if(Beam3d* b = dynamic_cast(element)) b->giveEndForcesVector(val, tStep); - else { +#ifdef __SM_MODULE + if(Beam2d* b = dynamic_cast(element)) b->giveEndForcesVector(val, tStep); + else if(Beam3d* b = dynamic_cast(element)) b->giveEndForcesVector(val, tStep); + else { + OOFEM_WARNING("Element %d has no beam interface.", number); + return false; + } +#else OOFEM_WARNING("Element %d has no beam interface.", number); return false; - } +#endif } if ( component > val.giveSize() || component < 1 ) { @@ -299,7 +302,7 @@ bool ReactionErrorCheckingRule :: check(Domain *domain, TimeStep *tStep) { // Rule doesn't apply yet. - if ( (tStep->giveNumber() != tstep ) || (tStep->giveVersion() != tsubstep) ) { + if ( tStep->giveNumber() != tstep || tStep->giveVersion() != tsubstep ) { return true; } @@ -414,21 +417,19 @@ EigenValueErrorCheckingRule :: check(Domain *domain, TimeStep *tStep) ErrorCheckingExportModule :: ErrorCheckingExportModule(int n, EngngModel *e) : ExportModule(n, e) { - allPassed = true; - writeChecks = false; } -IRResultType -ErrorCheckingExportModule :: initializeFrom(InputRecord *ir) +void +ErrorCheckingExportModule :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + ExportModule :: initializeFrom(ir); allPassed = true; this->errorCheckingRules.clear(); filename = std::string(""); - if ( ir->hasField(_IFT_ErrorCheckingExportModule_filename) ) { + if ( ir.hasField(_IFT_ErrorCheckingExportModule_filename) ) { IR_GIVE_FIELD(ir, this->filename, _IFT_ErrorCheckingExportModule_filename); } else { @@ -438,13 +439,12 @@ ErrorCheckingExportModule :: initializeFrom(InputRecord *ir) // Reads all the rules; std :: ifstream inputStream(this->filename); if ( !inputStream ) { - OOFEM_WARNING("Couldn't open file '%s'\n", this->filename.c_str()); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_ErrorCheckingExportModule_filename, "Couldn't open file"); } double tol = 0.; if ( this->scanToErrorChecks(inputStream, tol) ) { for (;;) { - std :: unique_ptr< ErrorCheckingRule > rule(this->giveErrorCheck(inputStream, tol)); + std :: unique_ptr< ErrorCheckingRule > rule = this->giveErrorCheck(inputStream, tol); if ( !rule ) { break; } @@ -453,7 +453,7 @@ ErrorCheckingExportModule :: initializeFrom(InputRecord *ir) } this->writeIST.clear(); - writeChecks = ir->hasField(_IFT_ErrorCheckingExportModule_writeIST); + writeChecks = ir.hasField(_IFT_ErrorCheckingExportModule_writeIST); if ( writeChecks ) { IR_GIVE_FIELD(ir, this->writeIST, _IFT_ErrorCheckingExportModule_writeIST); } @@ -461,8 +461,6 @@ ErrorCheckingExportModule :: initializeFrom(InputRecord *ir) if ( errorCheckingRules.size() == 0 && !writeChecks ) { OOFEM_WARNING("No rules found (possibly wrong file or syntax)."); } - - return ExportModule :: initializeFrom(ir); } void @@ -558,7 +556,7 @@ ErrorCheckingExportModule :: scanToErrorChecks(std :: ifstream &stream, double & return false; } -ErrorCheckingRule * +std::unique_ptr ErrorCheckingExportModule :: giveErrorCheck(std :: ifstream &stream, double errorTolerance) { std :: string line; @@ -572,24 +570,23 @@ ErrorCheckingExportModule :: giveErrorCheck(std :: ifstream &stream, double erro break; } } - } if ( line.compare(0, 5, "#NODE") == 0 ) { - return new NodeErrorCheckingRule(line, errorTolerance); + return std::make_unique(line, errorTolerance); } else if ( line.compare(0, 8, "#ELEMENT") == 0 ) { - return new ElementErrorCheckingRule(line, errorTolerance); + return std::make_unique(line, errorTolerance); } else if ( line.compare(0, 13, "#BEAM_ELEMENT") == 0 ) { - return new BeamElementErrorCheckingRule(line, errorTolerance); + return std::make_unique(line, errorTolerance); } else if ( line.compare(0, 9, "#REACTION") == 0 ) { - return new ReactionErrorCheckingRule(line, errorTolerance); + return std::make_unique(line, errorTolerance); } else if ( line.compare(0, 10, "#LOADLEVEL") == 0 ) { - return new LoadLevelErrorCheckingRule(line, errorTolerance); + return std::make_unique(line, errorTolerance); } else if ( line.compare(0, 7, "#EIGVAL") == 0 ) { - return new EigenValueErrorCheckingRule(line, errorTolerance); + return std::make_unique(line, errorTolerance); } else { OOFEM_ERROR("Unsupported rule '%s'", line.c_str()); - return NULL; + return nullptr; } } diff --git a/src/oofemlib/errorcheckingexportmodule.h b/src/oofemlib/errorcheckingexportmodule.h index dd8db52c1..d7aec6d8f 100644 --- a/src/oofemlib/errorcheckingexportmodule.h +++ b/src/oofemlib/errorcheckingexportmodule.h @@ -62,14 +62,15 @@ class DofManager; class OOFEM_EXPORT ErrorCheckingRule { protected: - int tstep; - int tsubstep; - int number; - double tolerance; - double value; + int tstep = 0; + int tsubstep = 0; + int number = 0; + double tolerance = 0.; + double value = 0.; public: - ErrorCheckingRule(double tol) : tolerance(tol) {tsubstep=0;} + ErrorCheckingRule(double tol) : tolerance(tol) { } + virtual ~ErrorCheckingRule() = default; /// Checks if the rule is correct. virtual bool check(Domain *domain, TimeStep *tStep) = 0; @@ -82,46 +83,47 @@ class OOFEM_EXPORT ErrorCheckingRule class OOFEM_EXPORT NodeErrorCheckingRule : public ErrorCheckingRule { protected: - int dofid; - ValueModeType mode; + int dofid = 0; + ValueModeType mode = VM_Unknown; public: NodeErrorCheckingRule(const std :: string &line, double tol); - virtual bool check(Domain *domain, TimeStep *tStep); - virtual const char *giveClassName() const {return "NodeErrorCheckingRule";} + bool check(Domain *domain, TimeStep *tStep) override; + const char *giveClassName() const override { return "NodeErrorCheckingRule"; } }; /// Checks an element value class OOFEM_EXPORT ElementErrorCheckingRule : public ErrorCheckingRule { protected: - int irule; - int gpnum; - InternalStateType ist; - int component; + int irule = 0; + int gpnum = 0; + InternalStateType ist = IST_Undefined; + int component = 0; public: ElementErrorCheckingRule(const std :: string &line, double tol); - virtual bool check(Domain *domain, TimeStep *tStep); - virtual const char *giveClassName() const {return "ElementErrorCheckingRule";} + bool check(Domain *domain, TimeStep *tStep) override; + const char *giveClassName() const override { return "ElementErrorCheckingRule"; } }; /// Checks a beam element value (in terms of end forces and and-displacements) class OOFEM_EXPORT BeamElementErrorCheckingRule : public ErrorCheckingRule { public: - enum BeamElementValueType{ - BET_localEndDisplacement, - BET_localEndForces - } ; + enum BeamElementValueType{ + BET_localEndDisplacement, + BET_localEndForces + }; + protected: - BeamElementValueType ist; - int component; + BeamElementValueType ist = BET_localEndDisplacement; + int component = 0; public: BeamElementErrorCheckingRule(const std :: string &line, double tol); - virtual bool check(Domain *domain, TimeStep *tStep); - virtual const char *giveClassName() const {return "BeamElementErrorCheckingRule";} + bool check(Domain *domain, TimeStep *tStep) override; + const char *giveClassName() const override { return "BeamElementErrorCheckingRule"; } }; @@ -129,12 +131,12 @@ class OOFEM_EXPORT BeamElementErrorCheckingRule : public ErrorCheckingRule class OOFEM_EXPORT ReactionErrorCheckingRule : public ErrorCheckingRule { protected: - int dofid; + int dofid = 0; public: ReactionErrorCheckingRule(const std :: string &line, double tol); - virtual bool check(Domain *domain, TimeStep *tStep); - virtual const char *giveClassName() const {return "ReactionErrorCheckingRule";} + bool check(Domain *domain, TimeStep *tStep) override; + const char *giveClassName() const override { return "ReactionErrorCheckingRule"; } }; /// Checks a reaction force value @@ -142,8 +144,8 @@ class OOFEM_EXPORT LoadLevelErrorCheckingRule : public ErrorCheckingRule { public: LoadLevelErrorCheckingRule(const std :: string &line, double tol); - virtual bool check(Domain *domain, TimeStep *tStep); - virtual const char *giveClassName() const {return "LoadLevelErrorCheckingRule";} + bool check(Domain *domain, TimeStep *tStep) override; + const char *giveClassName() const override { return "LoadLevelErrorCheckingRule"; } }; /// Checks eigen value @@ -151,8 +153,8 @@ class OOFEM_EXPORT EigenValueErrorCheckingRule : public ErrorCheckingRule { public: EigenValueErrorCheckingRule(const std :: string &line, double tol); - virtual bool check(Domain *domain, TimeStep *tStep); - virtual const char *giveClassName() const {return "EigenValueErrorCheckingRule";} + bool check(Domain *domain, TimeStep *tStep) override; + const char *giveClassName() const override { return "EigenValueErrorCheckingRule"; } }; @@ -167,26 +169,25 @@ class OOFEM_EXPORT ErrorCheckingExportModule : public ExportModule protected: std :: string filename; std :: vector< std :: unique_ptr< ErrorCheckingRule > > errorCheckingRules; - bool allPassed; - bool writeChecks; + bool allPassed = true; + bool writeChecks = false; IntArray writeIST; bool scanToErrorChecks(std :: ifstream &stream, double &errorTolerance); - ErrorCheckingRule *giveErrorCheck(std :: ifstream &stream, double errorTolerance); + std::unique_ptr giveErrorCheck(std :: ifstream &stream, double errorTolerance); void writeCheck(Domain *domain, TimeStep *tStep); public: ErrorCheckingExportModule(int n, EngngModel * e); - virtual ~ErrorCheckingExportModule() {} ErrorCheckingExportModule(const ErrorCheckingExportModule &) = delete; ErrorCheckingExportModule &operator=(const ErrorCheckingExportModule &) = delete; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void doOutput(TimeStep *tStep, bool forcedOutput = false); + void initializeFrom(InputRecord &ir) override; + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; - virtual const char *giveClassName() const { return "ErrorCheckingExportModule"; } - virtual const char *giveInputRecordName() const { return _IFT_ErrorCheckingExportModule_Name; } + const char *giveClassName() const override { return "ErrorCheckingExportModule"; } + const char *giveInputRecordName() const { return _IFT_ErrorCheckingExportModule_Name; } }; } // end namespace oofem #endif // errorcheckingexportmodule_h_ diff --git a/src/oofemlib/errorestimator.C b/src/oofemlib/errorestimator.C index baf9f7316..c87b9c5d7 100644 --- a/src/oofemlib/errorestimator.C +++ b/src/oofemlib/errorestimator.C @@ -56,19 +56,15 @@ ErrorEstimator :: setDomain(Domain *d) -IRResultType -ErrorEstimator :: initializeFrom(InputRecord *ir) +void +ErrorEstimator :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - regionSkipMap.clear(); IR_GIVE_OPTIONAL_FIELD(ir, regionSkipMap, _IFT_ErrorEstimator_regionskipmap); this->IStype = IST_StressTensor; int val = ( int ) this->IStype; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_ErrorEstimator_IStype); this->IStype = ( InternalStateType ) val; - - return IRRT_OK; } void ErrorEstimator :: reinitialize() diff --git a/src/oofemlib/errorestimator.h b/src/oofemlib/errorestimator.h index 222881238..ee22a093e 100644 --- a/src/oofemlib/errorestimator.h +++ b/src/oofemlib/errorestimator.h @@ -100,7 +100,7 @@ class OOFEM_EXPORT ErrorEstimator : public FEMComponent /// Destructor virtual ~ErrorEstimator(); /// Sets Domain; should also re-initialize attributes if necessary. - void setDomain(Domain *d); + void setDomain(Domain *d) override; /** * Returns the element error. The estimateError service should be called before. * @param type Error type. @@ -151,9 +151,7 @@ class OOFEM_EXPORT ErrorEstimator : public FEMComponent bool skipRegion(int reg); virtual void reinitialize(); - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual const char *giveInputRecordName() const { return NULL; } + void initializeFrom(InputRecord &ir) override; }; } // end namespace oofem #endif // errorestimator_h diff --git a/src/oofemlib/exportmodule.C b/src/oofemlib/exportmodule.C index 3d3dbe3de..68d2f6c7f 100644 --- a/src/oofemlib/exportmodule.C +++ b/src/oofemlib/exportmodule.C @@ -47,6 +47,7 @@ ExportModule :: ExportModule(int n, EngngModel *e) : tsteps_out(), domainMask(), emodel = e; regionSets.resize(0); timeScale = 1.; + pythonExport = false; } @@ -54,12 +55,10 @@ ExportModule :: ~ExportModule() { } -IRResultType -ExportModule :: initializeFrom(InputRecord *ir) +void +ExportModule :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - tstep_all_out_flag = ir->hasField(_IFT_ExportModule_tstepall); + tstep_all_out_flag = ir.hasField(_IFT_ExportModule_tstepall); tstep_step_out = 0; IR_GIVE_OPTIONAL_FIELD(ir, tstep_step_out, _IFT_ExportModule_tstepstep); @@ -69,7 +68,9 @@ ExportModule :: initializeFrom(InputRecord *ir) tstep_substeps_out_flag = 0; IR_GIVE_OPTIONAL_FIELD(ir, tstep_substeps_out_flag, _IFT_ExportModule_subtstepsout); - domain_all_flag = ir->hasField(_IFT_ExportModule_domainall); + IR_GIVE_OPTIONAL_FIELD(ir, pythonExport, _IFT_ExportModule_pythonexport); + + domain_all_flag = ir.hasField(_IFT_ExportModule_domainall); if ( !domain_all_flag ) { domainMask.clear(); @@ -79,8 +80,6 @@ ExportModule :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, regionSets, _IFT_ExportModule_regionsets); // Macro IR_GIVE_OPTIONAL_FIELD(ir, timeScale, _IFT_ExportModule_timescale); // Macro - - return IRRT_OK; } void ExportModule :: initialize(){ diff --git a/src/oofemlib/exportmodule.h b/src/oofemlib/exportmodule.h index 5c1f8644d..4f449ce1b 100644 --- a/src/oofemlib/exportmodule.h +++ b/src/oofemlib/exportmodule.h @@ -53,6 +53,7 @@ #define _IFT_ExportModule_domainmask "domain_mask" #define _IFT_ExportModule_regionsets "regionsets" #define _IFT_ExportModule_timescale "timescale" +#define _IFT_ExportModule_pythonexport "pythonexport" //@} namespace oofem { @@ -108,6 +109,10 @@ class OOFEM_EXPORT ExportModule /// Returns element set Set *giveRegionSet(int i); + + ///Output is carried out as a python list instead of writing files + bool pythonExport; + public: @@ -116,7 +121,7 @@ class OOFEM_EXPORT ExportModule /// Destructor virtual ~ExportModule(); /// Initializes receiver according to object description stored in input record. - virtual IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); /** * Writes the output. Abstract service. * @param tStep Time step. diff --git a/src/oofemlib/exportmodulemanager.C b/src/oofemlib/exportmodulemanager.C index 7d7ed6e0f..6aaa8b5fe 100644 --- a/src/oofemlib/exportmodulemanager.C +++ b/src/oofemlib/exportmodulemanager.C @@ -44,17 +44,14 @@ ExportModuleManager :: ExportModuleManager(EngngModel *emodel) : ModuleManager< ExportModuleManager :: ~ExportModuleManager() { } -IRResultType -ExportModuleManager :: initializeFrom(InputRecord *ir) +void +ExportModuleManager :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - this->numberOfModules = 0; IR_GIVE_OPTIONAL_FIELD(ir, numberOfModules, _IFT_ModuleManager_nmodules); - return IRRT_OK; } -ExportModule *ExportModuleManager :: CreateModule(const char *name, int n, EngngModel *emodel) +std::unique_ptr ExportModuleManager :: CreateModule(const char *name, int n, EngngModel *emodel) { return classFactory.createExportModule(name, n, emodel); } diff --git a/src/oofemlib/exportmodulemanager.h b/src/oofemlib/exportmodulemanager.h index 74fa1c044..828aae590 100644 --- a/src/oofemlib/exportmodulemanager.h +++ b/src/oofemlib/exportmodulemanager.h @@ -51,8 +51,8 @@ class OOFEM_EXPORT ExportModuleManager : public ModuleManager< ExportModule > ExportModuleManager(EngngModel * emodel); virtual ~ExportModuleManager(); - virtual IRResultType initializeFrom(InputRecord *ir); - ExportModule *CreateModule(const char *name, int num, EngngModel *emodel); + void initializeFrom(InputRecord &ir) override; + std::unique_ptr CreateModule(const char *name, int num, EngngModel *emodel) override; /** * Writes the output. Loops over all modules and calls corresponding doOutput module service. @@ -68,7 +68,7 @@ class OOFEM_EXPORT ExportModuleManager : public ModuleManager< ExportModule > * Terminates the receiver, the corresponding terminate module services are called. */ void terminate(); - virtual const char *giveClassName() const { return "ExportModuleManager"; } + const char *giveClassName() const override { return "ExportModuleManager"; } }; } // end namespace oofem #endif // exportmodulemanager_h diff --git a/src/oofemlib/fei1dhermite.C b/src/oofemlib/fei1dhermite.C index 4a485ca7b..3b36cf13e 100644 --- a/src/oofemlib/fei1dhermite.C +++ b/src/oofemlib/fei1dhermite.C @@ -36,10 +36,13 @@ #include "mathfem.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" namespace oofem { + void -FEI1dHermite :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dHermite :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); double l = this->giveLength(cellgeo); @@ -53,8 +56,22 @@ FEI1dHermite :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICe answer.at(4) = -0.125 * l * ( 1.0 + ksi ) * ( 1.0 + ksi ) * ( 1.0 - ksi ); } +std::pair> +FEI1dHermite :: evaldNdx(double ksi, const FEICellGeometry &cellgeo) const +{ + double l = this->giveLength(cellgeo); + double l_inv = 1.0 / l; + FloatMatrixF<1,4> ans = { + 1.5 * ( -1.0 + ksi * ksi ) * l_inv, + 0.25 * ( ksi - 1.0 ) * ( 1.0 + 3.0 * ksi ), + -1.5 * ( -1.0 + ksi * ksi ) * l_inv, + 0.25 * ( ksi - 1.0 ) * ( 1.0 + 3.0 * ksi ) + }; + return {0.5 * l, ans}; +} + double -FEI1dHermite :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dHermite :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double l = this->giveLength(cellgeo); double l_inv = 1.0 / l; @@ -71,9 +88,23 @@ FEI1dHermite :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const F return 0.5 * l; } +FloatMatrixF<1,4> +FEI1dHermite :: evald2Ndx2(double ksi, const FEICellGeometry &cellgeo) const +{ + double l_inv = 1.0 / this->giveLength(cellgeo); + + return { + l_inv * 6.0 * ksi * l_inv, + l_inv * ( 3.0 * ksi - 1.0 ), + -l_inv * 6.0 * ksi * l_inv, + l_inv * ( 3.0 * ksi + 1.0 ) + }; +} + void -FEI1dHermite :: evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dHermite :: evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { + //answer = evald2Ndx2(lcoords[0]); double l_inv = 1.0 / this->giveLength(cellgeo); double ksi = lcoords.at(1); answer.resize(1, 4); @@ -86,32 +117,31 @@ FEI1dHermite :: evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const } void -FEI1dHermite :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dHermite :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; - answer.resize(1); - this->evalN(n, lcoords, cellgeo); - answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates(1)->at(cindx) + - n.at(2) * cellgeo.giveVertexCoordinates(2)->at(cindx) + n.at(3) * cellgeo.giveVertexCoordinates(3)->at(cindx) ); + + answer.resize(1); + answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates(1).at(cindx) + + n.at(2) * cellgeo.giveVertexCoordinates(2).at(cindx) + + n.at(3) * cellgeo.giveVertexCoordinates(3).at(cindx); } int -FEI1dHermite :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) +FEI1dHermite :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) const { - double ksi, x1, x2; - answer.resize(1); + double x1 = cellgeo.giveVertexCoordinates(1).at(cindx); + double x2 = cellgeo.giveVertexCoordinates(2).at(cindx); - x1 = cellgeo.giveVertexCoordinates(1)->at(cindx); - x2 = cellgeo.giveVertexCoordinates(2)->at(cindx); - - ksi = ( 2.0 * coords.at(1) - ( x1 + x2 ) ) / ( x2 - x1 ); + double ksi = ( 2.0 * coords.at(1) - ( x1 + x2 ) ) / ( x2 - x1 ); + answer.resize(1); answer.at(1) = clamp(ksi, -1., 1.); return fabs(ksi) <= 1.0; } double -FEI1dHermite :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dHermite :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // This isn't really relevant, interpolation of geometry will be just linear double l = this->giveLength(cellgeo); @@ -121,6 +151,6 @@ FEI1dHermite :: giveTransformationJacobian(const FloatArray &lcoords, const FEIC double FEI1dHermite :: giveLength(const FEICellGeometry &cellgeo) const { - return fabs( cellgeo.giveVertexCoordinates(2)->at(cindx) - cellgeo.giveVertexCoordinates(1)->at(cindx) ); + return fabs( cellgeo.giveVertexCoordinates(2).at(cindx) - cellgeo.giveVertexCoordinates(1).at(cindx) ); } } // end namespace oofem diff --git a/src/oofemlib/fei1dhermite.h b/src/oofemlib/fei1dhermite.h index 2be332dda..5b35f7d14 100644 --- a/src/oofemlib/fei1dhermite.h +++ b/src/oofemlib/fei1dhermite.h @@ -48,23 +48,24 @@ class OOFEM_EXPORT FEI1dHermite : public FEInterpolation1d int cindx; public: - FEI1dHermite(int coordIndx) : FEInterpolation1d(2) { - cindx = coordIndx; - } + FEI1dHermite(int coordIndx) : FEInterpolation1d(2), cindx(coordIndx) { } - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } - virtual double giveLength(const FEICellGeometry &cellgeo) const; + double giveLength(const FEICellGeometry &cellgeo) const override; - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); + std::pair> evaldNdx(double ksi, const FEICellGeometry &cellgeo) const; + FloatMatrixF<1,4> evald2Ndx2(double ksi, const FEICellGeometry &cellgeo) const; - virtual int giveNumberOfNodes() const { return 2; } + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + + int giveNumberOfNodes() const override { return 2; } }; } // end namespace oofem #endif diff --git a/src/oofemlib/fei1dlin.C b/src/oofemlib/fei1dlin.C index 9f26b130e..69e4088e1 100644 --- a/src/oofemlib/fei1dlin.C +++ b/src/oofemlib/fei1dlin.C @@ -36,16 +36,24 @@ #include "mathfem.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" namespace oofem { double FEI1dLin :: giveLength(const FEICellGeometry &cellgeo) const { - return fabs( cellgeo.giveVertexCoordinates(2)->at(cindx) - cellgeo.giveVertexCoordinates(1)->at(cindx) ); + return fabs( cellgeo.giveVertexCoordinates(2).at(cindx) - cellgeo.giveVertexCoordinates(1).at(cindx) ); +} + +FloatArrayF<2> +FEI1dLin :: evalN(double ksi) +{ + return {( 1. - ksi ) * 0.5, ( 1. + ksi ) * 0.5}; } void -FEI1dLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); answer.resize(2); @@ -54,10 +62,17 @@ FEI1dLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGe answer.at(2) = ( 1. + ksi ) * 0.5; } +std::pair> +FEI1dLin :: evaldNdx(const FEICellGeometry &cellgeo) const +{ + double l = cellgeo.giveVertexCoordinates(2).at(cindx) - cellgeo.giveVertexCoordinates(1).at(cindx); + return {0.5 * l, {-1.0 / l, 1.0 / l}}; +} + double -FEI1dLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double l = cellgeo.giveVertexCoordinates(2)->at(cindx) - cellgeo.giveVertexCoordinates(1)->at(cindx); + double l = cellgeo.giveVertexCoordinates(2).at(cindx) - cellgeo.giveVertexCoordinates(1).at(cindx); answer.resize(2, 1); answer.at(1, 1) = -1.0 / l; @@ -66,52 +81,49 @@ FEI1dLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICe } void -FEI1dLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; answer.resize(1); this->evalN(n, lcoords, cellgeo); - answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates(1)->at(cindx) + - n.at(2) * cellgeo.giveVertexCoordinates(2)->at(cindx) ); + answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates(1).at(cindx) + + n.at(2) * cellgeo.giveVertexCoordinates(2).at(cindx); } int -FEI1dLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) +FEI1dLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) const { - double ksi, x1, x2; + double x1 = cellgeo.giveVertexCoordinates(1).at(cindx); + double x2 = cellgeo.giveVertexCoordinates(2).at(cindx); + double ksi = ( 2.0 * coords.at(1) - ( x1 + x2 ) ) / ( x2 - x1 ); answer.resize(1); - - x1 = cellgeo.giveVertexCoordinates(1)->at(cindx); - x2 = cellgeo.giveVertexCoordinates(2)->at(cindx); - - ksi = ( 2.0 * coords.at(1) - ( x1 + x2 ) ) / ( x2 - x1 ); answer.at(1) = clamp(ksi, -1., 1.); return fabs(ksi) <= 1.0; } double -FEI1dLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - return 0.5 * ( cellgeo.giveVertexCoordinates(2)->at(cindx) - cellgeo.giveVertexCoordinates(1)->at(cindx) ); + return 0.5 * ( cellgeo.giveVertexCoordinates(2).at(cindx) - cellgeo.giveVertexCoordinates(1).at(cindx) ); } -void FEI1dLin :: boundaryEdgeGiveNodes(IntArray &answer, int boundary) +IntArray FEI1dLin :: boundaryEdgeGiveNodes(int boundary) const { - answer = {1, 2}; + return {1, 2}; } -void FEI1dLin :: boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI1dLin :: boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - this->evalN(answer, lcoords, cellgeo); + this->evalN(answer, lcoords, cellgeo); } -double FEI1dLin :: boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI1dLin :: boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->giveTransformationJacobian(lcoords, cellgeo); } -void FEI1dLin :: boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI1dLin :: boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->local2global(answer, lcoords, cellgeo); } diff --git a/src/oofemlib/fei1dlin.h b/src/oofemlib/fei1dlin.h index 740fc167d..8f10b5b62 100644 --- a/src/oofemlib/fei1dlin.h +++ b/src/oofemlib/fei1dlin.h @@ -44,38 +44,34 @@ namespace oofem { class OOFEM_EXPORT FEI1dLin : public FEInterpolation1d { protected: - int cindx; + int cindx = 0; public: - FEI1dLin(int coordIndx) : FEInterpolation1d(1) { - cindx = coordIndx; - } + FEI1dLin(int coordIndx) : FEInterpolation1d(1), cindx(coordIndx) { } - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Point; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _UnknownIntegrationDomain; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _UnknownIntegrationDomain; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Point; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _UnknownIntegrationDomain; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _UnknownIntegrationDomain; } + double giveLength(const FEICellGeometry &cellgeo) const override; - - virtual double giveLength(const FEICellGeometry &cellgeo) const; + static FloatArrayF<2> evalN(double ksi); + std::pair> evaldNdx(const FEICellGeometry &cellgeo) const; - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; - virtual int giveNumberOfNodes() const { return 2; } + int giveNumberOfNodes() const override { return 2; } - virtual void boundaryEdgeGiveNodes(IntArray &answer, int boundary); - virtual void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - - - + IntArray boundaryEdgeGiveNodes(int boundary) const override; + void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; }; } // end namespace oofem #endif // fei1dlin_h diff --git a/src/oofemlib/fei1dquad.C b/src/oofemlib/fei1dquad.C index c6d853c91..52c1c30ae 100644 --- a/src/oofemlib/fei1dquad.C +++ b/src/oofemlib/fei1dquad.C @@ -36,11 +36,23 @@ #include "mathfem.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" namespace oofem { + +FloatArrayF<3> +FEI1dQuad :: evalN(double ksi) +{ + return {ksi * ( ksi - 1. ) * 0.5, ksi * ( 1. + ksi ) * 0.5, ( 1. - ksi * ksi )}; +} + void -FEI1dQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + answer = evalN(lcoords[0]); +#else double ksi = lcoords.at(1); answer.resize(3); answer.zero(); @@ -48,10 +60,29 @@ FEI1dQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellG answer.at(1) = ksi * ( ksi - 1. ) * 0.5; answer.at(2) = ksi * ( 1. + ksi ) * 0.5; answer.at(3) = ( 1. - ksi * ksi ); +#endif } +std::pair> +FEI1dQuad :: evaldNdx(double ksi, const FEICellGeometry &cellgeo) const +{ + double x1 = cellgeo.giveVertexCoordinates(1).at(cindx); + double x2 = cellgeo.giveVertexCoordinates(2).at(cindx); + double x3 = cellgeo.giveVertexCoordinates(3).at(cindx); + + double J = 1. / 2. * ( 2 * ksi - 1 ) * x1 + 1. / 2. * ( 2 * ksi + 1 ) * x2 - 2. * ksi * x3; + + FloatMatrixF<1, 3> ans = { + ( -1. / 2. + ksi ) / J, + ( 1. / 2. + ksi ) / J, + -2. * ksi / J, + }; + return {J, ans}; +} + + double -FEI1dQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double J = this->giveTransformationJacobian(lcoords, cellgeo); double ksi = lcoords.at(1); @@ -65,29 +96,27 @@ FEI1dQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEIC } void -FEI1dQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; answer.resize(1); this->evalN(n, lcoords, cellgeo); - answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates(1)->at(cindx) + - n.at(2) * cellgeo.giveVertexCoordinates(2)->at(cindx) + n.at(3) * cellgeo.giveVertexCoordinates(3)->at(cindx) ); + answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates(1).at(cindx) + + n.at(2) * cellgeo.giveVertexCoordinates(2).at(cindx) + + n.at(3) * cellgeo.giveVertexCoordinates(3).at(cindx); } int -FEI1dQuad :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) +FEI1dQuad :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) const { - double x1, x2, x3; - double a, b, c; - - x1 = cellgeo.giveVertexCoordinates(1)->at(cindx); - x2 = cellgeo.giveVertexCoordinates(2)->at(cindx); - x3 = cellgeo.giveVertexCoordinates(3)->at(cindx); + double x1 = cellgeo.giveVertexCoordinates(1).at(cindx); + double x2 = cellgeo.giveVertexCoordinates(2).at(cindx); + double x3 = cellgeo.giveVertexCoordinates(3).at(cindx); - a = 0.5 * ( x1 + x2 ) - x3; - b = 0.5 * ( x2 - x1 ); - c = x3 - coords.at(1); + double a = 0.5 * ( x1 + x2 ) - x3; + double b = 0.5 * ( x2 - x1 ); + double c = x3 - coords.at(1); answer.resize(1); if ( fabs(a) < 1.e-6 ) { @@ -115,42 +144,40 @@ FEI1dQuad :: global2local(FloatArray &answer, const FloatArray &coords, const FE } double -FEI1dQuad :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI1dQuad :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double x1, x2, x3, J, ksi; - - x1 = cellgeo.giveVertexCoordinates(1)->at(cindx); - x2 = cellgeo.giveVertexCoordinates(2)->at(cindx); - x3 = cellgeo.giveVertexCoordinates(3)->at(cindx); - ksi = lcoords.at(1); + double x1 = cellgeo.giveVertexCoordinates(1).at(cindx); + double x2 = cellgeo.giveVertexCoordinates(2).at(cindx); + double x3 = cellgeo.giveVertexCoordinates(3).at(cindx); + double ksi = lcoords.at(1); - J = 1. / 2. * ( 2 * ksi - 1 ) * x1 + 1. / 2. * ( 2 * ksi + 1 ) * x2 - 2. * ksi * x3; + double J = 1. / 2. * ( 2 * ksi - 1 ) * x1 + 1. / 2. * ( 2 * ksi + 1 ) * x2 - 2. * ksi * x3; return J; } double FEI1dQuad :: giveLength(const FEICellGeometry &cellgeo) const { - return fabs( cellgeo.giveVertexCoordinates(2)->at(cindx) - cellgeo.giveVertexCoordinates(1)->at(cindx) ); + return fabs( cellgeo.giveVertexCoordinates(2).at(cindx) - cellgeo.giveVertexCoordinates(1).at(cindx) ); } -void FEI1dQuad :: boundaryEdgeGiveNodes(IntArray &answer, int boundary) +IntArray FEI1dQuad :: boundaryEdgeGiveNodes(int boundary) const { - answer={1, 2, 3}; + return {1, 2, 3}; } -void FEI1dQuad :: boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI1dQuad :: boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - this->evalN(answer, lcoords, cellgeo); + this->evalN(answer, lcoords, cellgeo); } -double FEI1dQuad :: boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI1dQuad :: boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->giveTransformationJacobian(lcoords, cellgeo); } -void FEI1dQuad :: boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI1dQuad :: boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->local2global(answer, lcoords, cellgeo); } diff --git a/src/oofemlib/fei1dquad.h b/src/oofemlib/fei1dquad.h index f183831ac..b6b3e51f3 100644 --- a/src/oofemlib/fei1dquad.h +++ b/src/oofemlib/fei1dquad.h @@ -47,33 +47,31 @@ class OOFEM_EXPORT FEI1dQuad : public FEInterpolation1d int cindx; public: - FEI1dQuad(int coordIndx) : FEInterpolation1d(2) { - cindx = coordIndx; - } + FEI1dQuad(int coordIndx) : FEInterpolation1d(2), cindx(coordIndx) { } - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_2; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + Element_Geometry_Type giveGeometryType() const override { return EGT_line_2; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Point; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _UnknownIntegrationDomain; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _UnknownIntegrationDomain; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Point; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _UnknownIntegrationDomain; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _UnknownIntegrationDomain; } + double giveLength(const FEICellGeometry &cellgeo) const override; - - virtual double giveLength(const FEICellGeometry &cellgeo) const; + static FloatArrayF<3> evalN(double ksi); + std::pair> evaldNdx(double ksi, const FEICellGeometry &cellgeo) const; - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; - virtual int giveNumberOfNodes() const { return 3; } - - virtual void boundaryEdgeGiveNodes(IntArray &answer, int boundary); - virtual void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + int giveNumberOfNodes() const override { return 3; } + IntArray boundaryEdgeGiveNodes(int boundary) const override; + void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; }; } // end namespace oofem #endif diff --git a/src/oofemlib/fei2dlinehermite.C b/src/oofemlib/fei2dlinehermite.C index 8315d61ed..4accfcca1 100644 --- a/src/oofemlib/fei2dlinehermite.C +++ b/src/oofemlib/fei2dlinehermite.C @@ -40,13 +40,12 @@ namespace oofem { double FEI2dLineHermite :: giveLength(const FEICellGeometry &cellgeo) const { - double x2_x1, y2_y1; - x2_x1 = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); - y2_y1 = cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind); + double x2_x1 = cellgeo.giveVertexCoordinates(2).at(xind) - cellgeo.giveVertexCoordinates(1).at(xind); + double y2_y1 = cellgeo.giveVertexCoordinates(2).at(yind) - cellgeo.giveVertexCoordinates(1).at(yind); return sqrt(x2_x1 * x2_x1 + y2_y1 * y2_y1); } -void FEI2dLineHermite :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dLineHermite :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); double l = this->giveLength(cellgeo); @@ -60,43 +59,40 @@ void FEI2dLineHermite :: evalN(FloatArray &answer, const FloatArray &lcoords, co answer.at(4) = -0.125 * l * ( 1.0 + ksi ) * ( 1.0 + ksi ) * ( 1.0 - ksi ); } -double FEI2dLineHermite :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dLineHermite :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // This is dNds projected on the direction if the linear edge. If any other interpolation is used for geometry, this can't be used anymore. FloatArray dNds; this->edgeEvaldNds(dNds, 1, lcoords, cellgeo); // Tangent line to project on FloatArray vec(2); - vec.at(1) = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); - vec.at(2) = cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind); + vec.at(1) = cellgeo.giveVertexCoordinates(2).at(xind) - cellgeo.giveVertexCoordinates(1).at(xind); + vec.at(2) = cellgeo.giveVertexCoordinates(2).at(yind) - cellgeo.giveVertexCoordinates(1).at(yind); double detJ = vec.normalize() * 0.5; answer.beDyadicProductOf(dNds, vec); return detJ; } -void FEI2dLineHermite :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dLineHermite :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; this->evalN(n, lcoords, cellgeo); answer.resize( max(xind, yind) ); answer.zero(); - answer.at(xind) = ( n.at(1) * cellgeo.giveVertexCoordinates(1)->at(xind) + - n.at(2) * cellgeo.giveVertexCoordinates(2)->at(xind) ); - answer.at(yind) = ( n.at(1) * cellgeo.giveVertexCoordinates(1)->at(yind) + - n.at(2) * cellgeo.giveVertexCoordinates(2)->at(yind) ); + answer.at(xind) = n.at(1) * cellgeo.giveVertexCoordinates(1).at(xind) + + n.at(2) * cellgeo.giveVertexCoordinates(2).at(xind); + answer.at(yind) = n.at(1) * cellgeo.giveVertexCoordinates(1).at(yind) + + n.at(2) * cellgeo.giveVertexCoordinates(2).at(yind); } -int FEI2dLineHermite :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) +int FEI2dLineHermite :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const { - double xi; - double x2_x1, y2_y1; - - x2_x1 = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); - y2_y1 = cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind); + double x2_x1 = cellgeo.giveVertexCoordinates(2).at(xind) - cellgeo.giveVertexCoordinates(1).at(xind); + double y2_y1 = cellgeo.giveVertexCoordinates(2).at(yind) - cellgeo.giveVertexCoordinates(1).at(yind); // Projection of the global coordinate gives the value interpolated in [0,1]. - xi = ( x2_x1 * gcoords(0) + y2_y1 * gcoords(1) ) / ( sqrt(x2_x1 * x2_x1 + y2_y1 * y2_y1) ); + double xi = ( x2_x1 * gcoords(0) + y2_y1 * gcoords(1) ) / ( sqrt(x2_x1 * x2_x1 + y2_y1 * y2_y1) ); // Map to [-1,1] domain. xi = xi * 2.0 - 1.0; @@ -105,54 +101,50 @@ int FEI2dLineHermite :: global2local(FloatArray &answer, const FloatArray &gcoor return false; } -void FEI2dLineHermite :: edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dLineHermite :: edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double l_inv = this->giveLength(cellgeo); double ksi = lcoords.at(1); answer.resize(4); - answer.zero(); - answer.at(1) = 1.5 * ( ksi * ksi - 1.0 ) * l_inv; answer.at(2) = 0.25 * ( ksi - 1.0 ) * ( 3.0 * ksi + 1.0 ); answer.at(3) = -1.5 * ( ksi * ksi - 1.0 ) * l_inv; answer.at(4) = 0.25 * ( ksi + 1.0 ) * ( 3.0 * ksi - 1.0 ); } -void FEI2dLineHermite :: edgeEvald2Nds2(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dLineHermite :: edgeEvald2Nds2(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double l_inv = this->giveLength(cellgeo); double ksi = lcoords.at(1); answer.resize(4); - answer.zero(); - answer.at(1) = l_inv * 6.0 * ksi * l_inv; answer.at(2) = l_inv * ( 3.0 * ksi - 1.0 ); answer.at(3) = -l_inv * 6.0 * ksi * l_inv; answer.at(4) = l_inv * ( 3.0 * ksi + 1.0 ); } -double FEI2dLineHermite :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dLineHermite :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { normal.resize(2); - normal.at(1) = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); - normal.at(2) = -( cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind) ); + normal.at(1) = cellgeo.giveVertexCoordinates(2).at(yind) - cellgeo.giveVertexCoordinates(1).at(yind); + normal.at(2) = -( cellgeo.giveVertexCoordinates(2).at(xind) - cellgeo.giveVertexCoordinates(1).at(xind) ); return normal.normalize() * 0.5; } -double FEI2dLineHermite :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dLineHermite :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double x2_x1, y2_y1; - x2_x1 = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); - y2_y1 = cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind); + x2_x1 = cellgeo.giveVertexCoordinates(2).at(xind) - cellgeo.giveVertexCoordinates(1).at(xind); + y2_y1 = cellgeo.giveVertexCoordinates(2).at(yind) - cellgeo.giveVertexCoordinates(1).at(yind); return sqrt(x2_x1 * x2_x1 + y2_y1 * y2_y1) * 0.5; } -IntegrationRule *FEI2dLineHermite :: giveIntegrationRule(int order) +std::unique_ptr FEI2dLineHermite :: giveIntegrationRule(int order) const { OOFEM_ERROR("Not supported."); - return NULL; + return nullptr; } } // end namespace oofem diff --git a/src/oofemlib/fei2dlinehermite.h b/src/oofemlib/fei2dlinehermite.h index cd9bf8040..4ac121f0a 100644 --- a/src/oofemlib/fei2dlinehermite.h +++ b/src/oofemlib/fei2dlinehermite.h @@ -49,41 +49,37 @@ class OOFEM_EXPORT FEI2dLineHermite : public FEInterpolation2d public: FEI2dLineHermite(int ind1, int ind2) : FEInterpolation2d(1, ind1, ind2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Point; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _UnknownIntegrationDomain; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _UnknownIntegrationDomain; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Point; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _UnknownIntegrationDomain; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _UnknownIntegrationDomain; } - virtual double giveArea(const FEICellGeometry &cellgeo) const { return 0.0; } - virtual double giveLength(const FEICellGeometry &cellgeo) const; + double giveArea(const FEICellGeometry &cellgeo) const override { return 0.0; } + double giveLength(const FEICellGeometry &cellgeo) const; - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo); + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const override; // "Bulk" - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveArea(const FEICellGeometry &cellgeo) { return 0.0; } + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; // Edge (same as bulk for this type, so they are all ignored) (perhaps do it the other way around?). - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) { } - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { } - virtual double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvald2Nds2(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); + IntArray computeLocalEdgeMapping(int iedge) const override { return {}; } + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { } + double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvald2Nds2(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const ; - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) { } + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { } - virtual int giveNumberOfNodes() const { return 2; } + int giveNumberOfNodes() const override { return 2; } - virtual IntegrationRule *giveIntegrationRule(int order); + std::unique_ptr giveIntegrationRule(int order) const override; }; } // end namespace oofem #endif // fei2dlinehermite_h diff --git a/src/oofemlib/fei2dlinelin.C b/src/oofemlib/fei2dlinelin.C index 2e79ff22d..7e65e6141 100644 --- a/src/oofemlib/fei2dlinelin.C +++ b/src/oofemlib/fei2dlinelin.C @@ -36,10 +36,17 @@ #include "mathfem.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatarrayf.h" #include "gaussintegrationrule.h" namespace oofem { -void FEI2dLineLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) + +FloatArrayF<2> FEI2dLineLin :: evalN(double xi) +{ + return {( 1. - xi ) * 0.5, ( 1. + xi ) * 0.5}; +} + +void FEI2dLineLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double xi = lcoords(0); answer.resize(2); @@ -47,42 +54,41 @@ void FEI2dLineLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const answer.at(2) = ( 1. + xi ) * 0.5; } -double FEI2dLineLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dLineLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // Not meaningful to return anything. answer.clear(); return 0.; } -void FEI2dLineLin :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dLineLin :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(2, 1); answer(0, 0) = -0.5; answer(1, 0) = 0.5; } -void FEI2dLineLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dLineLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; this->evalN(n, lcoords, cellgeo); answer.resize( max(xind, yind) ); answer.zero(); - answer.at(xind) = ( n(0) * cellgeo.giveVertexCoordinates(1)->at(xind) + - n(1) * cellgeo.giveVertexCoordinates(2)->at(xind) ); - answer.at(yind) = ( n(0) * cellgeo.giveVertexCoordinates(1)->at(yind) + - n(1) * cellgeo.giveVertexCoordinates(2)->at(yind) ); + answer.at(xind) = n(0) * cellgeo.giveVertexCoordinates(1).at(xind) + + n(1) * cellgeo.giveVertexCoordinates(2).at(xind); + answer.at(yind) = n(0) * cellgeo.giveVertexCoordinates(1).at(yind) + + n(1) * cellgeo.giveVertexCoordinates(2).at(yind); } -int FEI2dLineLin :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) +int FEI2dLineLin :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const { - double xi; - double x2_x1, y2_y1; - - x2_x1 = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); - y2_y1 = cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind); + double x2_x1 = cellgeo.giveVertexCoordinates(2).at(xind) - cellgeo.giveVertexCoordinates(1).at(xind); + double y2_y1 = cellgeo.giveVertexCoordinates(2).at(yind) - cellgeo.giveVertexCoordinates(1).at(yind); // Projection of the global coordinate gives the value interpolated in [0,1]. - xi = ( x2_x1 * gcoords(0) + y2_y1 * gcoords(1) ) / ( sqrt(x2_x1 * x2_x1 + y2_y1 * y2_y1) ); + double dx = gcoords(0) - cellgeo.giveVertexCoordinates(1).at(xind); + double dy = gcoords(1) - cellgeo.giveVertexCoordinates(1).at(yind); + double xi = (x2_x1) ? ( sqrt( dx*dx*(1 + (y2_y1 / x2_x1)*(y2_y1 / x2_x1) )) ) / ( sqrt(x2_x1 * x2_x1 + y2_y1 * y2_y1) ) : sqrt(dy*dy) / ( sqrt(x2_x1 * x2_x1 + y2_y1 * y2_y1) ); // Map to [-1,1] domain. xi = xi * 2 - 1; @@ -92,87 +98,82 @@ int FEI2dLineLin :: global2local(FloatArray &answer, const FloatArray &gcoords, } void FEI2dLineLin :: edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double xi = lcoords(0); answer.resize(2); answer(0) = -0.5 * xi; answer(1) = 0.5 * xi; - double es1 = answer(0) * cellgeo.giveVertexCoordinates(1)->at(xind) + - answer(1) * cellgeo.giveVertexCoordinates(2)->at(xind); - double es2 = answer(0) * cellgeo.giveVertexCoordinates(1)->at(yind) + - answer(1) * cellgeo.giveVertexCoordinates(2)->at(yind); + double es1 = answer(0) * cellgeo.giveVertexCoordinates(1).at(xind) + + answer(1) * cellgeo.giveVertexCoordinates(2).at(xind); + double es2 = answer(0) * cellgeo.giveVertexCoordinates(1).at(yind) + + answer(1) * cellgeo.giveVertexCoordinates(2).at(yind); double J = sqrt(es1 * es1 + es2 * es2); answer.times(1 / J); //return J; } -double FEI2dLineLin :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dLineLin :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { normal.resize(2); - normal.at(1) = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); - normal.at(2) = -( cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind) ); + normal.at(1) = cellgeo.giveVertexCoordinates(2).at(yind) - cellgeo.giveVertexCoordinates(1).at(yind); + normal.at(2) = -( cellgeo.giveVertexCoordinates(2).at(xind) - cellgeo.giveVertexCoordinates(1).at(xind) ); return normal.normalize() * 0.5; } -double FEI2dLineLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dLineLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double x2_x1, y2_y1; - x2_x1 = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); - y2_y1 = cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind); + double x2_x1 = cellgeo.giveVertexCoordinates(2).at(xind) - cellgeo.giveVertexCoordinates(1).at(xind); + double y2_y1 = cellgeo.giveVertexCoordinates(2).at(yind) - cellgeo.giveVertexCoordinates(1).at(yind); return sqrt(x2_x1 * x2_x1 + y2_y1 * y2_y1) / 2.0; } -void FEI2dLineLin :: boundaryEdgeGiveNodes(IntArray &answer, int boundary) +IntArray FEI2dLineLin :: boundaryEdgeGiveNodes(int boundary) const { - answer = {1, 2}; + return {1, 2}; } -void FEI2dLineLin :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray FEI2dLineLin :: computeLocalEdgeMapping(int iedge) const { if ( iedge != 1 ) { OOFEM_ERROR("wrong egde number (%d)", iedge); } - edgeNodes = {1, 2}; + return {1, 2}; } -void FEI2dLineLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dLineLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->evalN(answer, lcoords, cellgeo); } -double FEI2dLineLin :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) +double FEI2dLineLin :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const { - double x2_x1, y2_y1; - x2_x1 = cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); - y2_y1 = cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind); + double x2_x1 = cellgeo.giveVertexCoordinates(2).at(xind) - cellgeo.giveVertexCoordinates(1).at(xind); + double y2_y1 = cellgeo.giveVertexCoordinates(2).at(yind) - cellgeo.giveVertexCoordinates(1).at(yind); return sqrt(x2_x1 * x2_x1 + y2_y1 * y2_y1); } -double FEI2dLineLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) +double FEI2dLineLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const { - const FloatArray *node; - double x1, x2, y1, y2; - - node = cellgeo.giveVertexCoordinates(1); - x1 = node->at(xind); - y1 = node->at(yind); + const auto &node1 = cellgeo.giveVertexCoordinates(1); + double x1 = node1.at(xind); + double y1 = node1.at(yind); - node = cellgeo.giveVertexCoordinates(2); - x2 = node->at(xind); - y2 = node->at(yind); + const auto &node2 = cellgeo.giveVertexCoordinates(2); + double x2 = node2.at(xind); + double y2 = node2.at(yind); return x2 * y1 - x1 * y2; } -IntegrationRule *FEI2dLineLin :: giveIntegrationRule(int order) +std::unique_ptr FEI2dLineLin :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Line, order + 0); iRule->SetUpPointsOnLine(points, _Unknown); - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei2dlinelin.h b/src/oofemlib/fei2dlinelin.h index 5c82e0dd0..40ebab04b 100644 --- a/src/oofemlib/fei2dlinelin.h +++ b/src/oofemlib/fei2dlinelin.h @@ -48,45 +48,42 @@ class OOFEM_EXPORT FEI2dLineLin : public FEInterpolation2d public: FEI2dLineLin(int ind1, int ind2) : FEInterpolation2d(1, ind1, ind2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Point; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _UnknownIntegrationDomain; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Point; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _UnknownIntegrationDomain; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } - + double giveArea(const FEICellGeometry &cellgeo) const override { return 0.0; } - virtual double giveArea(const FEICellGeometry &cellgeo) const { return 0.0; } + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const override; - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo); - - virtual int giveNumberOfEdges() const {return 1;} + int giveNumberOfEdges() const override { return 1; } // "Bulk" - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveArea(const FEICellGeometry &cellgeo) { return 0.0; } + static FloatArrayF<2> evalN(double xi); + + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; // Edge (same as bulk for this type, so they are all ignored) (perhaps do it the other way around?). - virtual void boundaryEdgeGiveNodes(IntArray &answer, int boundary); - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) { } - virtual double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo); + IntArray boundaryEdgeGiveNodes(int boundary) const override; + IntArray computeLocalEdgeMapping(int iedge) const override; + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { } + double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const override; - virtual int giveNumberOfNodes() const { return 2; } + int giveNumberOfNodes() const override { return 2; } - virtual IntegrationRule *giveIntegrationRule(int order); + std::unique_ptr giveIntegrationRule(int order) const override; protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; }; } // end namespace oofem #endif // fei2dlinelin_h diff --git a/src/oofemlib/fei2dlinequad.C b/src/oofemlib/fei2dlinequad.C index 73123b261..79e44633f 100644 --- a/src/oofemlib/fei2dlinequad.C +++ b/src/oofemlib/fei2dlinequad.C @@ -39,7 +39,7 @@ #include "gaussintegrationrule.h" namespace oofem { -void FEI2dLineQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dLineQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double xi = lcoords(0); answer.resize(3); @@ -48,7 +48,7 @@ void FEI2dLineQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const answer(2) = 1.0 - xi * xi; } -double FEI2dLineQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dLineQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // Not meaningful to return anything. answer.clear(); @@ -56,7 +56,7 @@ double FEI2dLineQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, } void -FEI2dLineQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dLineQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double xi = lcoords(0); answer.resize(3, 1); @@ -65,30 +65,30 @@ FEI2dLineQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const answer.at(3, 1) = -2.0 * xi; } -void FEI2dLineQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dLineQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; this->evalN(n, lcoords, cellgeo); answer.resize(2); - answer.at(1) = ( n(0) * cellgeo.giveVertexCoordinates(1)->at(xind) + - n(1) * cellgeo.giveVertexCoordinates(2)->at(xind) + - n(2) * cellgeo.giveVertexCoordinates(3)->at(xind) ); - answer.at(2) = ( n(0) * cellgeo.giveVertexCoordinates(1)->at(yind) + - n(1) * cellgeo.giveVertexCoordinates(2)->at(yind) + - n(2) * cellgeo.giveVertexCoordinates(3)->at(yind) ); + answer.at(1) = n(0) * cellgeo.giveVertexCoordinates(1).at(xind) + + n(1) * cellgeo.giveVertexCoordinates(2).at(xind) + + n(2) * cellgeo.giveVertexCoordinates(3).at(xind); + answer.at(2) = n(0) * cellgeo.giveVertexCoordinates(1).at(yind) + + n(1) * cellgeo.giveVertexCoordinates(2).at(yind) + + n(2) * cellgeo.giveVertexCoordinates(3).at(yind); } -int FEI2dLineQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) +int FEI2dLineQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const { double x1_x2, y1_y2, px_x3, py_y3, x3_x2_x1, y3_y2_y1; double b0, b1, b2, b3; - x1_x2 = cellgeo.giveVertexCoordinates(1)->at(xind) - cellgeo.giveVertexCoordinates(2)->at(xind); - y1_y2 = cellgeo.giveVertexCoordinates(1)->at(yind) - cellgeo.giveVertexCoordinates(2)->at(yind); - px_x3 = gcoords.at(1) - cellgeo.giveVertexCoordinates(3)->at(xind); - py_y3 = gcoords.at(2) - cellgeo.giveVertexCoordinates(3)->at(yind); - x3_x2_x1 = 2 * cellgeo.giveVertexCoordinates(3)->at(xind) - cellgeo.giveVertexCoordinates(2)->at(xind) - cellgeo.giveVertexCoordinates(1)->at(xind); - y3_y2_y1 = 2 * cellgeo.giveVertexCoordinates(3)->at(yind) - cellgeo.giveVertexCoordinates(2)->at(yind) - cellgeo.giveVertexCoordinates(1)->at(yind); + x1_x2 = cellgeo.giveVertexCoordinates(1).at(xind) - cellgeo.giveVertexCoordinates(2).at(xind); + y1_y2 = cellgeo.giveVertexCoordinates(1).at(yind) - cellgeo.giveVertexCoordinates(2).at(yind); + px_x3 = gcoords.at(1) - cellgeo.giveVertexCoordinates(3).at(xind); + py_y3 = gcoords.at(2) - cellgeo.giveVertexCoordinates(3).at(yind); + x3_x2_x1 = 2 * cellgeo.giveVertexCoordinates(3).at(xind) - cellgeo.giveVertexCoordinates(2).at(xind) - cellgeo.giveVertexCoordinates(1).at(xind); + y3_y2_y1 = 2 * cellgeo.giveVertexCoordinates(3).at(yind) - cellgeo.giveVertexCoordinates(2).at(yind) - cellgeo.giveVertexCoordinates(1).at(yind); b0 = 0.50 * ( x1_x2 * px_x3 + y1_y2 * py_y3 ); b1 = 0.25 * ( x1_x2 * x1_x2 + y1_y2 * y1_y2 ) + x3_x2_x1 * px_x3 + y3_y2_y1 * py_y3; @@ -115,14 +115,14 @@ int FEI2dLineQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, } } - double min_distance2 = 0.0, min_xi = 0, distance2; + double min_distance2 = 0.0, min_xi = 0; FloatArray f(2); answer.resize(1); for ( int i = 0; i < points; i++ ) { answer(0) = p [ i ]; this->local2global(f, answer, cellgeo); - distance2 = f.distance_square(gcoords); + double distance2 = distance_square(f, gcoords); if ( i == 0 || distance2 < min_distance2 ) { min_distance2 = distance2; min_xi = answer(0); @@ -134,18 +134,18 @@ int FEI2dLineQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, return false; // It will never land exactly on the geometry. } -void FEI2dLineQuad :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray FEI2dLineQuad :: computeLocalEdgeMapping(int iedge) const { - edgeNodes = { 1, 2, 3}; + return {1, 2, 3}; } -void FEI2dLineQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dLineQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->evalN(answer, lcoords, cellgeo); } void FEI2dLineQuad :: edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double xi = lcoords(0); answer.resize(3); @@ -153,21 +153,22 @@ void FEI2dLineQuad :: edgeEvaldNds(FloatArray &answer, int iedge, answer(1) = 0.5 + xi; answer(2) = -2.0 * xi; - double es1 = answer(0) * cellgeo.giveVertexCoordinates(1)->at(xind) + - answer(1) * cellgeo.giveVertexCoordinates(2)->at(xind) + - answer(2) * cellgeo.giveVertexCoordinates(3)->at(xind); + double es1 = answer(0) * cellgeo.giveVertexCoordinates(1).at(xind) + + answer(1) * cellgeo.giveVertexCoordinates(2).at(xind) + + answer(2) * cellgeo.giveVertexCoordinates(3).at(xind); - double es2 = answer(0) * cellgeo.giveVertexCoordinates(1)->at(yind) + - answer(1) * cellgeo.giveVertexCoordinates(2)->at(yind) + - answer(2) * cellgeo.giveVertexCoordinates(3)->at(yind); + double es2 = answer(0) * cellgeo.giveVertexCoordinates(1).at(yind) + + answer(1) * cellgeo.giveVertexCoordinates(2).at(yind) + + answer(2) * cellgeo.giveVertexCoordinates(3).at(yind); double J = sqrt(es1 * es1 + es2 * es2); answer.times(1 / J); //return J; } -double FEI2dLineQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dLineQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); double xi = lcoords(0); double dN1dxi = -0.5 + xi; double dN2dxi = 0.5 + xi; @@ -175,53 +176,53 @@ double FEI2dLineQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const Floa normal.resize(2); - normal.at(1) = -dN1dxi *cellgeo.giveVertexCoordinates(1)->at(yind) + - - dN2dxi *cellgeo.giveVertexCoordinates(2)->at(yind) + - - dN3dxi *cellgeo.giveVertexCoordinates(3)->at(yind); + normal.at(1) = dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind) + + dN2dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind) + + dN3dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(yind); - normal.at(2) = dN1dxi * cellgeo.giveVertexCoordinates(1)->at(xind) + - dN2dxi *cellgeo.giveVertexCoordinates(2)->at(xind) + - dN3dxi *cellgeo.giveVertexCoordinates(3)->at(xind); + normal.at(2) = - dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) + + - dN2dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind) + + - dN3dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(xind); return normal.normalize(); } void FEI2dLineQuad :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->local2global(answer, lcoords, cellgeo); } -double FEI2dLineQuad :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dLineQuad :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double xi = lcoords(0); double a1 = -0.5 + xi; double a2 = 0.5 + xi; double a3 = -2.0 * xi; - double es1 = a1 * cellgeo.giveVertexCoordinates(1)->at(xind) + - a2 *cellgeo.giveVertexCoordinates(2)->at(xind) + - a3 *cellgeo.giveVertexCoordinates(3)->at(xind); - double es2 = a1 * cellgeo.giveVertexCoordinates(1)->at(yind) + - a2 *cellgeo.giveVertexCoordinates(2)->at(yind) + - a3 *cellgeo.giveVertexCoordinates(3)->at(yind); + double es1 = a1 * cellgeo.giveVertexCoordinates(1).at(xind) + + a2 * cellgeo.giveVertexCoordinates(2).at(xind) + + a3 * cellgeo.giveVertexCoordinates(3).at(xind); + double es2 = a1 * cellgeo.giveVertexCoordinates(1).at(yind) + + a2 * cellgeo.giveVertexCoordinates(2).at(yind) + + a3 * cellgeo.giveVertexCoordinates(3).at(yind); return sqrt(es1 * es1 + es2 * es2); } -void FEI2dLineQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dLineQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double xi = lcoords(0); double dN1dxi = -0.5 + xi; double dN2dxi = 0.5 + xi; double dN3dxi = -2.0 * xi; - double es1 = dN1dxi * cellgeo.giveVertexCoordinates(1)->at(xind) + - dN2dxi *cellgeo.giveVertexCoordinates(2)->at(xind) + - dN3dxi *cellgeo.giveVertexCoordinates(3)->at(xind); - double es2 = dN1dxi * cellgeo.giveVertexCoordinates(1)->at(yind) + - dN2dxi *cellgeo.giveVertexCoordinates(2)->at(yind) + - dN3dxi *cellgeo.giveVertexCoordinates(3)->at(yind); + double es1 = dN1dxi * cellgeo.giveVertexCoordinates(1).at(xind) + + dN2dxi * cellgeo.giveVertexCoordinates(2).at(xind) + + dN3dxi * cellgeo.giveVertexCoordinates(3).at(xind); + double es2 = dN1dxi * cellgeo.giveVertexCoordinates(1).at(yind) + + dN2dxi * cellgeo.giveVertexCoordinates(2).at(yind) + + dN3dxi * cellgeo.giveVertexCoordinates(3).at(yind); double J = sqrt(es1 * es1 + es2 * es2); @@ -233,37 +234,34 @@ void FEI2dLineQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const Fl jacobianMatrix(1, 1) = es1 / J; } -double FEI2dLineQuad :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) +double FEI2dLineQuad :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("Not implemented"); return 0.0; } -double FEI2dLineQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) +double FEI2dLineQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const { - const FloatArray *node; - double x1, x2, x3, y1, y2, y3; + const auto &node1 = cellgeo.giveVertexCoordinates(1); + double x1 = node1.at(xind); + double y1 = node1.at(yind); - node = cellgeo.giveVertexCoordinates(1); - x1 = node->at(xind); - y1 = node->at(yind); + const auto &node2 = cellgeo.giveVertexCoordinates(2); + double x2 = node2.at(xind); + double y2 = node2.at(yind); - node = cellgeo.giveVertexCoordinates(2); - x2 = node->at(xind); - y2 = node->at(yind); - - node = cellgeo.giveVertexCoordinates(3); - x3 = node->at(xind); - y3 = node->at(yind); + const auto &node3 = cellgeo.giveVertexCoordinates(3); + double x3 = node3.at(xind); + double y3 = node3.at(yind); return ( x1 * y2 - x2 * y1 + 4 * ( x3 * ( y1 - y2 ) + y3 * ( x2 - x1 ) ) ) / 3.0; } -IntegrationRule *FEI2dLineQuad :: giveIntegrationRule(int order) +std::unique_ptr FEI2dLineQuad :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Line, order + 1); iRule->SetUpPointsOnLine(points, _Unknown); - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei2dlinequad.h b/src/oofemlib/fei2dlinequad.h index 689dcb6d5..ac93ea8ca 100644 --- a/src/oofemlib/fei2dlinequad.h +++ b/src/oofemlib/fei2dlinequad.h @@ -48,45 +48,40 @@ class OOFEM_EXPORT FEI2dLineQuad : public FEInterpolation2d public: FEI2dLineQuad(int ind1, int ind2) : FEInterpolation2d(2, ind1, ind2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_2; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Line; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Square; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + Element_Geometry_Type giveGeometryType() const override { return EGT_line_2; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Line; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Square; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } + double giveArea(const FEICellGeometry &cellgeo) const override { return 0.0; } - + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const override; - virtual double giveArea(const FEICellGeometry &cellgeo) const { return 0.0; } - - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo); - - virtual int giveNumberOfEdges() const {return 1;} + int giveNumberOfEdges() const override { return 1; } // "Bulk" - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveArea(const FEICellGeometry &cellgeo) { return 0.0; } + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; // Edge (same as bulk for this type, so they are all ignored) (perhaps do it the other way around?). - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo); + IntArray computeLocalEdgeMapping(int iedge) const override; + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const override; - virtual int giveNumberOfNodes() const { return 3; } + int giveNumberOfNodes() const override { return 3; } - virtual IntegrationRule *giveIntegrationRule(int order); + std::unique_ptr giveIntegrationRule(int order) const override; protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); - void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; }; } // end namespace oofem #endif // fei2dlinequad_h diff --git a/src/oofemlib/fei2dquadbiquad.C b/src/oofemlib/fei2dquadbiquad.C index e711c5a7f..f3f2e8e7e 100644 --- a/src/oofemlib/fei2dquadbiquad.C +++ b/src/oofemlib/fei2dquadbiquad.C @@ -35,23 +35,44 @@ #include "fei2dquadbiquad.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "gaussintegrationrule.h" namespace oofem { + +FloatArrayF<9> +FEI2dQuadBiQuad :: evalN(const FloatArrayF<2> &lcoords) +{ + double u = lcoords[0]; + double v = lcoords[1]; + + std::array a = {0.5 * ( u - 1.0 ) * u, 1.0 - u * u, 0.5 * ( u + 1.0 ) * u}; + std::array b = {0.5 * ( v - 1.0 ) * v, 1.0 - v * v, 0.5 * ( v + 1.0 ) * v}; + + return { + a [ 0 ] * b [ 0 ], + a [ 2 ] * b [ 0 ], + a [ 2 ] * b [ 2 ], + a [ 0 ] * b [ 2 ], + a [ 1 ] * b [ 0 ], + a [ 2 ] * b [ 1 ], + a [ 1 ] * b [ 2 ], + a [ 0 ] * b [ 1 ], + a [ 1 ] * b [ 1 ], + }; +} + void -FEI2dQuadBiQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadBiQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double u, v; u = lcoords.at(1); v = lcoords.at(2); - double a[] = { - 0.5 * ( u - 1.0 ) * u, 1.0 - u * u, 0.5 * ( u + 1.0 ) * u - }; - double b[] = { - 0.5 * ( v - 1.0 ) * v, 1.0 - v * v, 0.5 * ( v + 1.0 ) * v - }; + std::array a = {0.5 * ( u - 1.0 ) * u, 1.0 - u * u, 0.5 * ( u + 1.0 ) * u}; + std::array b = {0.5 * ( v - 1.0 ) * v, 1.0 - v * v, 0.5 * ( v + 1.0 ) * v}; answer.resize(9); answer.at(1) = a [ 0 ] * b [ 0 ]; @@ -68,8 +89,43 @@ FEI2dQuadBiQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FE } +FloatMatrixF<2,9> +FEI2dQuadBiQuad :: evaldNdxi(const FloatArrayF<2> &lc) +{ + double u = lc[0]; + double v = lc[1]; + + std::array a = {0.5 * ( u - 1.0 ) * u, 1.0 - u * u, 0.5 * ( u + 1.0 ) * u}; + std::array b = {0.5 * ( v - 1.0 ) * v, 1.0 - v * v, 0.5 * ( v + 1.0 ) * v}; + + std::array da = {u - 0.5, -2.0 * u, u + 0.5}; + std::array db = {v - 0.5, -2.0 * v, v + 0.5}; + + return { + da [ 0 ] * b [ 0 ], + a [ 0 ] * db [ 0 ], + da [ 2 ] * b [ 0 ], + a [ 2 ] * db [ 0 ], + da [ 2 ] * b [ 2 ], + a [ 2 ] * db [ 2 ], + da [ 0 ] * b [ 2 ], + a [ 0 ] * db [ 2 ], + da [ 1 ] * b [ 0 ], + a [ 1 ] * db [ 0 ], + da [ 2 ] * b [ 1 ], + a [ 2 ] * db [ 1 ], + da [ 1 ] * b [ 2 ], + a [ 1 ] * db [ 2 ], + da [ 0 ] * b [ 1 ], + a [ 0 ] * db [ 1 ], + da [ 1 ] * b [ 1 ], + a [ 1 ] * db [ 1 ], + }; +} + + void -FEI2dQuadBiQuad :: giveDerivatives(FloatMatrix &dN, const FloatArray &lc) +FEI2dQuadBiQuad :: evaldNdxi(FloatMatrix &dN, const FloatArray &lc, const FEICellGeometry &cellgeo) const { double u = lc.at(1); double v = lc.at(2); @@ -112,11 +168,32 @@ FEI2dQuadBiQuad :: giveDerivatives(FloatMatrix &dN, const FloatArray &lc) } -IntegrationRule *FEI2dQuadBiQuad :: giveIntegrationRule(int order) +std::pair> +FEI2dQuadBiQuad :: evaldNdx(const FloatArrayF<2> &lcoords, const FEICellGeometry &cellgeo) const +{ + auto dn = evaldNdxi(lcoords); + FloatMatrixF<2,2> jacT; + for ( std::size_t i = 1; i <= dn.cols(); i++ ) { + const auto &c = cellgeo.giveVertexCoordinates(i); + double x = c.at(xind); + double y = c.at(yind); + + ///@todo check transpose + jacT(0, 0) += dn.at(1, i) * x; + jacT(0, 1) += dn.at(1, i) * y; + jacT(1, 0) += dn.at(2, i) * x; + jacT(1, 1) += dn.at(2, i) * y; + } + + return {det(jacT), dot(inv(jacT), dn)}; +} + + +std::unique_ptr FEI2dQuadBiQuad :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order + 6); iRule->SetUpPointsOnSquare(points, _Unknown); - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei2dquadbiquad.h b/src/oofemlib/fei2dquadbiquad.h index 22eb010e3..2ae09f65b 100644 --- a/src/oofemlib/fei2dquadbiquad.h +++ b/src/oofemlib/fei2dquadbiquad.h @@ -59,14 +59,14 @@ class OOFEM_EXPORT FEI2dQuadBiQuad : public FEI2dQuadQuad public: FEI2dQuadBiQuad(int ind1, int ind2) : FEI2dQuadQuad(ind1, ind2) { } - // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int giveNumberOfNodes() const { return 9; } - - virtual IntegrationRule *giveIntegrationRule(int order); + static FloatArrayF<9> evalN(const FloatArrayF<2> &lcoords); + static FloatMatrixF<2,9> evaldNdxi(const FloatArrayF<2> &lcoords); + std::pair> evaldNdx(const FloatArrayF<2> &lcoords, const FEICellGeometry &cellgeo) const; -protected: - virtual void giveDerivatives(FloatMatrix &answer, const FloatArray &lcoords); + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int giveNumberOfNodes() const override { return 9; } + std::unique_ptr giveIntegrationRule(int order) const override; }; } // end namespace oofem #endif // fei2dquadbiquad_h diff --git a/src/oofemlib/fei2dquadconst.C b/src/oofemlib/fei2dquadconst.C index abbcdf3c6..071e9a6e5 100644 --- a/src/oofemlib/fei2dquadconst.C +++ b/src/oofemlib/fei2dquadconst.C @@ -37,17 +37,18 @@ #include "floatmatrix.h" #include "floatarray.h" #include "gaussintegrationrule.h" +#include namespace oofem { void -FEI2dQuadConst :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadConst :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(1); answer.at(1) = 1.; } double -FEI2dQuadConst :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadConst :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(1, 2); answer.at(1, 1) = 0.; @@ -56,18 +57,18 @@ FEI2dQuadConst :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const } void -FEI2dQuadConst :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadConst :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(2); - answer.at(1) = 0.25 * ( cellgeo.giveVertexCoordinates(1)->at(xind) + - cellgeo.giveVertexCoordinates(2)->at(xind) + - cellgeo.giveVertexCoordinates(3)->at(xind) + - cellgeo.giveVertexCoordinates(4)->at(xind) ); - answer.at(2) = 0.25 * ( cellgeo.giveVertexCoordinates(1)->at(yind) + - cellgeo.giveVertexCoordinates(2)->at(yind) + - cellgeo.giveVertexCoordinates(3)->at(yind) + - cellgeo.giveVertexCoordinates(4)->at(yind) ); + answer.at(1) = 0.25 * ( cellgeo.giveVertexCoordinates(1).at(xind) + + cellgeo.giveVertexCoordinates(2).at(xind) + + cellgeo.giveVertexCoordinates(3).at(xind) + + cellgeo.giveVertexCoordinates(4).at(xind) ); + answer.at(2) = 0.25 * ( cellgeo.giveVertexCoordinates(1).at(yind) + + cellgeo.giveVertexCoordinates(2).at(yind) + + cellgeo.giveVertexCoordinates(3).at(yind) + + cellgeo.giveVertexCoordinates(4).at(yind) ); } @@ -88,13 +89,13 @@ bool FEI2dQuadConst :: inside(const FloatArray &lcoords) const void -FEI2dQuadConst :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadConst :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer = FloatArray{1.}; } -double FEI2dQuadConst :: edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dQuadConst :: edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("not implemented"); return 0.; @@ -102,61 +103,50 @@ double FEI2dQuadConst :: edgeEvalNormal(FloatArray &answer, int iedge, const Flo void FEI2dQuadConst :: edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("not implemented"); } void FEI2dQuadConst :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("not implemented"); } -void -FEI2dQuadConst :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI2dQuadConst :: computeLocalEdgeMapping(int iedge) const { - int aNode = 0, bNode = 0; - edgeNodes.resize(2); - if ( iedge == 1 ) { // edge between nodes 1 2 - aNode = 1; - bNode = 2; + return {1, 2}; } else if ( iedge == 2 ) { // edge between nodes 2 3 - aNode = 2; - bNode = 3; + return {2, 3}; } else if ( iedge == 3 ) { // edge between nodes 2 3 - aNode = 3; - bNode = 1; + return {3, 1}; } else { - OOFEM_ERROR("wrong egde number (%d)", iedge); + throw std::range_error("invalid egde number"); + return {}; } - - edgeNodes.at(1) = aNode; - edgeNodes.at(2) = bNode; } double -FEI2dQuadConst :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) +FEI2dQuadConst :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const { - double dx, dy; - int nodeA, nodeB; - - nodeA = edgeNodes.at(1); - nodeB = edgeNodes.at(2); + int nodeA = edgeNodes.at(1); + int nodeB = edgeNodes.at(2); - dx = cellgeo.giveVertexCoordinates(nodeB)->at(xind) - cellgeo.giveVertexCoordinates(nodeA)->at(xind); - dy = cellgeo.giveVertexCoordinates(nodeB)->at(yind) - cellgeo.giveVertexCoordinates(nodeA)->at(yind); + double dx = cellgeo.giveVertexCoordinates(nodeB).at(xind) - cellgeo.giveVertexCoordinates(nodeA).at(xind); + double dy = cellgeo.giveVertexCoordinates(nodeB).at(yind) - cellgeo.giveVertexCoordinates(nodeA).at(yind); return sqrt(dx * dx + dy * dy); } -IntegrationRule * -FEI2dQuadConst :: giveIntegrationRule(int order) +std::unique_ptr +FEI2dQuadConst :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order + 0); iRule->SetUpPointsOnSquare(points, _Unknown); - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei2dquadconst.h b/src/oofemlib/fei2dquadconst.h index 7e4404327..027b18b55 100644 --- a/src/oofemlib/fei2dquadconst.h +++ b/src/oofemlib/fei2dquadconst.h @@ -46,31 +46,29 @@ class OOFEM_EXPORT FEI2dQuadConst : public FEInterpolation2d public: FEI2dQuadConst(int ind1, int ind2) : FEInterpolation2d(0, ind1, ind2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Square; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_quad_1; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Line; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Square; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Square; } + Element_Geometry_Type giveGeometryType() const override { return EGT_quad_1; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Line; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Square; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; - virtual bool inside(const FloatArray &lcoords) const; + bool inside(const FloatArray &lcoords) const override; // Edge - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); + IntArray computeLocalEdgeMapping(int iedge) const override; + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; - virtual IntegrationRule *giveIntegrationRule(int order); + std::unique_ptr giveIntegrationRule(int order) const override; - virtual int giveNumberOfNodes() const { return 4; } + int giveNumberOfNodes() const override { return 4; } protected: /** @@ -78,7 +76,7 @@ class OOFEM_EXPORT FEI2dQuadConst : public FEInterpolation2d * @param edgeNodes Node indices of edge. * @param cellgeo Cell geometry. */ - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; }; } // end namespace oofem #endif // fei2dquadlin_h diff --git a/src/oofemlib/fei2dquadlin.C b/src/oofemlib/fei2dquadlin.C index 2644088cc..b8ec51189 100644 --- a/src/oofemlib/fei2dquadlin.C +++ b/src/oofemlib/fei2dquadlin.C @@ -36,34 +36,34 @@ #include "mathfem.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" #include "gaussintegrationrule.h" namespace oofem { double FEI2dQuadLin :: giveArea(const FEICellGeometry &cellgeo) const { - const FloatArray *node1 = cellgeo.giveVertexCoordinates(1); - const FloatArray *node2 = cellgeo.giveVertexCoordinates(2); - const FloatArray *node3 = cellgeo.giveVertexCoordinates(3); - const FloatArray *node4 = cellgeo.giveVertexCoordinates(4); + const auto &node1 = cellgeo.giveVertexCoordinates(1); + const auto &node2 = cellgeo.giveVertexCoordinates(2); + const auto &node3 = cellgeo.giveVertexCoordinates(3); + const auto &node4 = cellgeo.giveVertexCoordinates(4); - double x13 = node1->at(xind) - node3->at(xind); - double y13 = node1->at(yind) - node3->at(yind); - double x24 = node2->at(xind) - node4->at(xind); - double y24 = node2->at(yind) - node4->at(yind); + double x13 = node1.at(xind) - node3.at(xind); + double y13 = node1.at(yind) - node3.at(yind); + double x24 = node2.at(xind) - node4.at(xind); + double y24 = node2.at(yind) - node4.at(yind); return fabs( 0.5 * ( x13 * y24 - x24 * y13 ) ); } -void -FEI2dQuadLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FloatArrayF<4> +FEI2dQuadLin :: evalN(const FloatArrayF<2> &lcoords) { - double ksi, eta; - - ksi = lcoords.at(1); - eta = lcoords.at(2); + double ksi = lcoords[0]; + double eta = lcoords[1]; - answer = { + return { ( 1. + ksi ) * ( 1. + eta ) * 0.25, ( 1. - ksi ) * ( 1. + eta ) * 0.25, ( 1. - ksi ) * ( 1. - eta ) * 0.25, @@ -71,29 +71,40 @@ FEI2dQuadLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICe }; } -double -FEI2dQuadLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void +FEI2dQuadLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FloatMatrix jacobianMatrix(2, 2), inv, dn; + answer = evalN({lcoords[0], lcoords[1]}); +} - this->evaldNdxi(dn, lcoords, cellgeo); - for ( int i = 1; i <= dn.giveNumberOfRows(); i++ ) { - double x = cellgeo.giveVertexCoordinates(i)->at(xind); - double y = cellgeo.giveVertexCoordinates(i)->at(yind); +std::pair> +FEI2dQuadLin :: evaldNdx(const FloatArrayF<2> &lcoords, const FEICellGeometry &cellgeo) const +{ + auto dndu = this->evaldNdxi(lcoords); - jacobianMatrix.at(1, 1) += dn.at(i, 1) * x; - jacobianMatrix.at(1, 2) += dn.at(i, 1) * y; - jacobianMatrix.at(2, 1) += dn.at(i, 2) * x; - jacobianMatrix.at(2, 2) += dn.at(i, 2) * y; + FloatMatrixF<2,2> jacT; + for ( std::size_t i = 0; i < dndu.cols(); i++ ) { + double x = cellgeo.giveVertexCoordinates(i+1).at(xind); + double y = cellgeo.giveVertexCoordinates(i+1).at(yind); + + jacT(0, 0) += dndu(0, i) * x; + jacT(0, 1) += dndu(0, i) * y; + jacT(1, 0) += dndu(1, i) * x; + jacT(1, 1) += dndu(1, i) * y; } - inv.beInverseOf(jacobianMatrix); + return {det(jacT), dot(inv(jacT), dndu)}; +} - answer.beProductTOf(dn, inv); - return jacobianMatrix.giveDeterminant(); +double +FEI2dQuadLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + auto tmp = evaldNdx(lcoords, cellgeo); + answer = transpose(tmp.second); + return tmp.first; } void -FEI2dQuadLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); double eta = lcoords.at(2); @@ -103,21 +114,21 @@ FEI2dQuadLin :: local2global(FloatArray &answer, const FloatArray &lcoords, cons double n3 = ( 1. - ksi ) * ( 1. - eta ) * 0.25; double n4 = ( 1. + ksi ) * ( 1. - eta ) * 0.25; - const FloatArray* const p1 = cellgeo.giveVertexCoordinates(1); - const FloatArray* const p2 = cellgeo.giveVertexCoordinates(2); - const FloatArray* const p3 = cellgeo.giveVertexCoordinates(3); - const FloatArray* const p4 = cellgeo.giveVertexCoordinates(4); + const auto &p1 = cellgeo.giveVertexCoordinates(1); + const auto &p2 = cellgeo.giveVertexCoordinates(2); + const auto &p3 = cellgeo.giveVertexCoordinates(3); + const auto &p4 = cellgeo.giveVertexCoordinates(4); - answer = {n1 * p1->at(xind) + n2 * p2->at(xind) + - n3 * p3->at(xind) + n4 * p4->at(xind), - n1 * p1->at(yind) + n2 * p2->at(yind) + - n3 * p3->at(yind) + n4 * p4->at(yind)} ; + answer = {n1 * p1.at(xind) + n2 * p2.at(xind) + + n3 * p3.at(xind) + n4 * p4.at(xind), + n1 * p1.at(yind) + n2 * p2.at(yind) + + n3 * p3.at(yind) + n4 * p4.at(yind)} ; } #define POINT_TOL 1.e-6 int -FEI2dQuadLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) +FEI2dQuadLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) const { double x1, x2, x3, x4, y1, y2, y3, y4, a1, a2, a3, a4, b1, b2, b3, b4; double a, b, c, ksi1, ksi2, ksi3, eta1 = 0.0, eta2 = 0.0, denom; @@ -125,15 +136,15 @@ FEI2dQuadLin :: global2local(FloatArray &answer, const FloatArray &coords, const answer.resize(2); - x1 = cellgeo.giveVertexCoordinates(1)->at(xind); - x2 = cellgeo.giveVertexCoordinates(2)->at(xind); - x3 = cellgeo.giveVertexCoordinates(3)->at(xind); - x4 = cellgeo.giveVertexCoordinates(4)->at(xind); + x1 = cellgeo.giveVertexCoordinates(1).at(xind); + x2 = cellgeo.giveVertexCoordinates(2).at(xind); + x3 = cellgeo.giveVertexCoordinates(3).at(xind); + x4 = cellgeo.giveVertexCoordinates(4).at(xind); - y1 = cellgeo.giveVertexCoordinates(1)->at(yind); - y2 = cellgeo.giveVertexCoordinates(2)->at(yind); - y3 = cellgeo.giveVertexCoordinates(3)->at(yind); - y4 = cellgeo.giveVertexCoordinates(4)->at(yind); + y1 = cellgeo.giveVertexCoordinates(1).at(yind); + y2 = cellgeo.giveVertexCoordinates(2).at(yind); + y3 = cellgeo.giveVertexCoordinates(3).at(yind); + y4 = cellgeo.giveVertexCoordinates(4).at(yind); a1 = x1 + x2 + x3 + x4; a2 = x1 - x2 - x3 + x4; @@ -242,34 +253,31 @@ FEI2dQuadLin :: global2local(FloatArray &answer, const FloatArray &coords, const } void -FEI2dQuadLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); answer = { ( 1. - ksi ) * 0.5, ( 1. + ksi ) * 0.5 }; } double -FEI2dQuadLin :: edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadLin :: edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - int nodeA, nodeB; - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); - nodeA = edgeNodes.at(1); - nodeB = edgeNodes.at(2); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); + int nodeA = edgeNodes.at(1); + int nodeB = edgeNodes.at(2); answer = { - cellgeo.giveVertexCoordinates(nodeA)->at(yind) - cellgeo.giveVertexCoordinates(nodeB)->at(yind), - cellgeo.giveVertexCoordinates(nodeB)->at(xind) - cellgeo.giveVertexCoordinates(nodeA)->at(xind) + cellgeo.giveVertexCoordinates(nodeB).at(yind) - cellgeo.giveVertexCoordinates(nodeA).at(yind), + cellgeo.giveVertexCoordinates(nodeA).at(xind) - cellgeo.giveVertexCoordinates(nodeB).at(xind) }; return answer.normalize() * 0.5; } void FEI2dQuadLin :: edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); double l = this->edgeComputeLength(edgeNodes, cellgeo); answer = { -1.0 / l, 1.0 / l }; @@ -277,64 +285,51 @@ FEI2dQuadLin :: edgeEvaldNds(FloatArray &answer, int iedge, void FEI2dQuadLin :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; FloatArray n; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); this->edgeEvalN(n, iedge, lcoords, cellgeo); answer.resize(2); - answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) ); - answer.at(2) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) ); + answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind); + answer.at(2) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind); } -void -FEI2dQuadLin :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI2dQuadLin :: computeLocalEdgeMapping(int iedge) const { - int aNode = 0, bNode = 0; - edgeNodes.resize(2); - if ( iedge == 1 ) { // edge between nodes 1 2 - aNode = 1; - bNode = 2; + return {1, 2}; } else if ( iedge == 2 ) { // edge between nodes 2 3 - aNode = 2; - bNode = 3; + return {2, 3}; } else if ( iedge == 3 ) { // edge between nodes 3 4 - aNode = 3; - bNode = 4; + return {3, 4}; } else if ( iedge == 4 ) { // edge between nodes 4 1 - aNode = 4; - bNode = 1; + return {4, 1}; } else { - OOFEM_ERROR("wrong egde number (%d)", iedge); + throw std::range_error("invalid edge number"); + return {}; } - - edgeNodes.at(1) = aNode; - edgeNodes.at(2) = bNode; } double -FEI2dQuadLin :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) +FEI2dQuadLin :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const { - double dx, dy; - int nodeA, nodeB; - - nodeA = edgeNodes.at(1); - nodeB = edgeNodes.at(2); + int nodeA = edgeNodes.at(1); + int nodeB = edgeNodes.at(2); - dx = cellgeo.giveVertexCoordinates(nodeB)->at(xind) - cellgeo.giveVertexCoordinates(nodeA)->at(xind); - dy = cellgeo.giveVertexCoordinates(nodeB)->at(yind) - cellgeo.giveVertexCoordinates(nodeA)->at(yind); + double dx = cellgeo.giveVertexCoordinates(nodeB).at(xind) - cellgeo.giveVertexCoordinates(nodeA).at(xind); + double dy = cellgeo.giveVertexCoordinates(nodeB).at(yind) - cellgeo.giveVertexCoordinates(nodeA).at(yind); return sqrt(dx * dx + dy * dy); } bool FEI2dQuadLin :: inside(const FloatArray &lcoords) const { - const double point_tol = 1.0e-3; + const double point_tol = 1.0e-3; bool inside = true; for ( int i = 1; i <= 2; i++ ) { if ( lcoords.at(i) < ( -1. - point_tol ) ) { @@ -347,100 +342,96 @@ bool FEI2dQuadLin :: inside(const FloatArray &lcoords) const return inside; } -void FEI2dQuadLin :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FloatMatrixF<2,4> FEI2dQuadLin :: evaldNdxi(const FloatArrayF<2> &lcoords) { const double &ksi = lcoords[0]; const double &eta = lcoords[1]; - answer.resize(4, 2); - + FloatMatrixF<2,4> answer; // dn/dxi answer.at(1, 1) = 0.25 * ( 1. + eta ); - answer.at(2, 1) = -0.25 * ( 1. + eta ); - answer.at(3, 1) = -0.25 * ( 1. - eta ); - answer.at(4, 1) = 0.25 * ( 1. - eta ); + answer.at(1, 2) = -0.25 * ( 1. + eta ); + answer.at(1, 3) = -0.25 * ( 1. - eta ); + answer.at(1, 4) = 0.25 * ( 1. - eta ); // dn/deta - answer.at(1, 2) = 0.25 * ( 1. + ksi ); + answer.at(2, 1) = 0.25 * ( 1. + ksi ); answer.at(2, 2) = 0.25 * ( 1. - ksi ); - answer.at(3, 2) = -0.25 * ( 1. - ksi ); - answer.at(4, 2) = -0.25 * ( 1. + ksi ); + answer.at(2, 3) = -0.25 * ( 1. - ksi ); + answer.at(2, 4) = -0.25 * ( 1. + ksi ); + return answer; } -double FEI2dQuadLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) +void FEI2dQuadLin :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray eNodes; - const FloatArray *node; - double x1, x2, y1, y2; + answer = transpose(evaldNdxi({lcoords[0], lcoords[1]})); +} - this->computeLocalEdgeMapping(eNodes, iEdge); +double FEI2dQuadLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const +{ + const auto &eNodes = this->computeLocalEdgeMapping(iEdge); - node = cellgeo.giveVertexCoordinates( eNodes.at(1) ); - x1 = node->at(xind); - y1 = node->at(yind); + const auto &node1 = cellgeo.giveVertexCoordinates( eNodes.at(1) ); + double x1 = node1.at(xind); + double y1 = node1.at(yind); - node = cellgeo.giveVertexCoordinates( eNodes.at(2) ); - x2 = node->at(xind); - y2 = node->at(yind); + const auto &node2 = cellgeo.giveVertexCoordinates( eNodes.at(2) ); + double x2 = node2.at(xind); + double y2 = node2.at(yind); return -( x2 * y1 - x1 * y2 ); } -IntegrationRule * -FEI2dQuadLin :: giveIntegrationRule(int order) +std::unique_ptr +FEI2dQuadLin :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order + 2); iRule->SetUpPointsOnSquare(points, _Unknown); - return iRule; + return std::move(iRule); } /* * FEI2dQuadlinAxi element */ - double -FEI2dQuadLinAxi :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadLinAxi :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FloatArray N; - this->evalN( N, lcoords, cellgeo); + FloatArray N; + this->evalN( N, lcoords, cellgeo); - double r = 0.0; - for ( int i = 1; i <= 4; i++ ) { - double x = cellgeo.giveVertexCoordinates(i)->at(1); - r += x * N.at(i); - } + double r = 0.0; + for ( int i = 1; i <= 4; i++ ) { + double x = cellgeo.giveVertexCoordinates(i).at(1); + r += x * N.at(i); + } - return r * FEI2dQuadLin::giveTransformationJacobian(lcoords, cellgeo); + return r * FEI2dQuadLin::giveTransformationJacobian(lcoords, cellgeo); } double FEI2dQuadLinAxi::edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - FloatArray n; - this->computeLocalEdgeMapping(edgeNodes, iedge); - this->edgeEvalN(n, iedge, lcoords, cellgeo); - - double r = n.at(1)*cellgeo.giveVertexCoordinates(edgeNodes.at(1))->at(1) + n.at(2)*cellgeo.giveVertexCoordinates(edgeNodes.at(2))->at(1); - return r * FEI2dQuadLin::edgeGiveTransformationJacobian(iedge, lcoords, cellgeo); + FloatArray n; + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); + this->edgeEvalN(n, iedge, lcoords, cellgeo); + double r = n.at(1)*cellgeo.giveVertexCoordinates(edgeNodes.at(1)).at(1) + n.at(2)*cellgeo.giveVertexCoordinates(edgeNodes.at(2)).at(1); + return r * FEI2dQuadLin::edgeGiveTransformationJacobian(iedge, lcoords, cellgeo); } - + double -FEI2dQuadLinAxi::boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadLinAxi::boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); + return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); } double -FEI2dQuadLinAxi::boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadLinAxi::boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); + return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); } - - } // end namespace oofem diff --git a/src/oofemlib/fei2dquadlin.h b/src/oofemlib/fei2dquadlin.h index 4fea6f9eb..4be485a28 100644 --- a/src/oofemlib/fei2dquadlin.h +++ b/src/oofemlib/fei2dquadlin.h @@ -47,41 +47,41 @@ class OOFEM_EXPORT FEI2dQuadLin : public FEInterpolation2d public: FEI2dQuadLin(int ind1, int ind2) : FEInterpolation2d(1, ind1, ind2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Square; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_quad_1; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Line; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Square; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Square; } + Element_Geometry_Type giveGeometryType() const override { return EGT_quad_1; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Line; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Square; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } - virtual double giveArea(const FEICellGeometry &cellgeo) const; + double giveArea(const FEICellGeometry &cellgeo) const override; // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int giveNumberOfNodes() const { return 4; } + static FloatArrayF<4> evalN(const FloatArrayF<2> &lcoords) ; + static FloatMatrixF<2,4> evaldNdxi(const FloatArrayF<2> &lcoords); + std::pair> evaldNdx(const FloatArrayF<2> &lcoords, const FEICellGeometry &cellgeo) const; - virtual bool inside(const FloatArray &lcoords) const; + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int giveNumberOfNodes() const override { return 4; } - // Edge - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); - virtual int giveNumberOfEdges() const { return 4; } - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo); - - virtual IntegrationRule *giveIntegrationRule(int order); + bool inside(const FloatArray &lcoords) const override; + // Edge + IntArray computeLocalEdgeMapping(int iedge) const override; + int giveNumberOfEdges() const override { return 4; } + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const override; - virtual void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + std::unique_ptr giveIntegrationRule(int order) const override; protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; }; /** @@ -92,16 +92,12 @@ class OOFEM_EXPORT FEI2dQuadLinAxi : public FEI2dQuadLin { public: FEI2dQuadLinAxi(int ind1, int ind2) : FEI2dQuadLin(ind1, ind2) { } - - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - -}; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; +}; - } // end namespace oofem #endif // fei2dquadlin_h diff --git a/src/oofemlib/fei2dquadquad.C b/src/oofemlib/fei2dquadquad.C index ad2be7f3c..74c28a85b 100644 --- a/src/oofemlib/fei2dquadquad.C +++ b/src/oofemlib/fei2dquadquad.C @@ -36,6 +36,8 @@ #include "mathfem.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "gaussintegrationrule.h" namespace oofem { @@ -45,34 +47,34 @@ FEI2dQuadQuad :: giveArea(const FEICellGeometry &cellgeo) const double x1, x2, x3, x4, y1, y2, y3, y4; double x85, x56, x67, x78, y85, y56, y67, y78; - const FloatArray *node1 = cellgeo.giveVertexCoordinates(1); - const FloatArray *node2 = cellgeo.giveVertexCoordinates(2); - const FloatArray *node3 = cellgeo.giveVertexCoordinates(3); - const FloatArray *node4 = cellgeo.giveVertexCoordinates(4); - const FloatArray *node5 = cellgeo.giveVertexCoordinates(5); - const FloatArray *node6 = cellgeo.giveVertexCoordinates(6); - const FloatArray *node7 = cellgeo.giveVertexCoordinates(7); - const FloatArray *node8 = cellgeo.giveVertexCoordinates(8); - - x1 = node1->at(xind); - x2 = node2->at(xind); - x3 = node3->at(xind); - x4 = node4->at(xind); - - y1 = node1->at(yind); - y2 = node2->at(yind); - y3 = node3->at(yind); - y4 = node4->at(yind); - - x85 = node8->at(xind) - node5->at(xind); - x56 = node5->at(xind) - node6->at(xind); - x67 = node6->at(xind) - node7->at(xind); - x78 = node7->at(xind) - node8->at(xind); - - y85 = node8->at(yind) - node5->at(yind); - y56 = node5->at(yind) - node6->at(yind); - y67 = node6->at(yind) - node7->at(yind); - y78 = node7->at(yind) - node8->at(yind); + const auto &node1 = cellgeo.giveVertexCoordinates(1); + const auto &node2 = cellgeo.giveVertexCoordinates(2); + const auto &node3 = cellgeo.giveVertexCoordinates(3); + const auto &node4 = cellgeo.giveVertexCoordinates(4); + const auto &node5 = cellgeo.giveVertexCoordinates(5); + const auto &node6 = cellgeo.giveVertexCoordinates(6); + const auto &node7 = cellgeo.giveVertexCoordinates(7); + const auto &node8 = cellgeo.giveVertexCoordinates(8); + + x1 = node1.at(xind); + x2 = node2.at(xind); + x3 = node3.at(xind); + x4 = node4.at(xind); + + y1 = node1.at(yind); + y2 = node2.at(yind); + y3 = node3.at(yind); + y4 = node4.at(yind); + + x85 = node8.at(xind) - node5.at(xind); + x56 = node5.at(xind) - node6.at(xind); + x67 = node6.at(xind) - node7.at(xind); + x78 = node7.at(xind) - node8.at(xind); + + y85 = node8.at(yind) - node5.at(yind); + y56 = node5.at(yind) - node6.at(yind); + y67 = node6.at(yind) - node7.at(yind); + y78 = node7.at(yind) - node8.at(yind); double p1 = ( x2 - x4 ) * ( y1 - y3 ) - ( x1 - x3 ) * ( y2 - y4 ); double p2 = y1 * x85 + y2 * x56 + y3 * x67 + y4 * x78 - x1 * y85 - x2 * y56 - x3 * y67 - x4 * y78; @@ -80,13 +82,30 @@ FEI2dQuadQuad :: giveArea(const FEICellGeometry &cellgeo) const return fabs(p1 + p2 * 4.0) / 6.; // Expression derived with mathematica, but not verified in any computations } -void -FEI2dQuadQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) + +FloatArrayF<8> +FEI2dQuadQuad :: evalN(const FloatArrayF<2> &lcoords) { - double ksi, eta; + double ksi = lcoords[0]; + double eta = lcoords[1]; + return { + ( 1. + ksi ) * ( 1. + eta ) * 0.25 * ( ksi + eta - 1. ), + ( 1. - ksi ) * ( 1. + eta ) * 0.25 * ( -ksi + eta - 1. ), + ( 1. - ksi ) * ( 1. - eta ) * 0.25 * ( -ksi - eta - 1. ), + ( 1. + ksi ) * ( 1. - eta ) * 0.25 * ( ksi - eta - 1. ), + 0.5 * ( 1. - ksi * ksi ) * ( 1. + eta ), + 0.5 * ( 1. - ksi ) * ( 1. - eta * eta ), + 0.5 * ( 1. - ksi * ksi ) * ( 1. - eta ), + 0.5 * ( 1. + ksi ) * ( 1. - eta * eta ) + }; +} - ksi = lcoords.at(1); - eta = lcoords.at(2); + +void +FEI2dQuadQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + double ksi = lcoords.at(1); + double eta = lcoords.at(2); answer = { ( 1. + ksi ) * ( 1. + eta ) * 0.25 * ( ksi + eta - 1. ), @@ -100,15 +119,100 @@ FEI2dQuadQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEIC }; } + +FloatMatrixF<2,8> +FEI2dQuadQuad :: evaldNdxi(const FloatArrayF<2> &lcoords) +{ + double ksi = lcoords.at(1); + double eta = lcoords.at(2); + + return { + 0.25 * ( 1. + eta ) * ( 2.0 * ksi + eta ), // 1 + 0.25 * ( 1. + ksi ) * ( 2.0 * eta + ksi ), + -0.25 * ( 1. + eta ) * ( -2.0 * ksi + eta ), // 2 + 0.25 * ( 1. - ksi ) * ( 2.0 * eta - ksi ), + -0.25 * ( 1. - eta ) * ( -2.0 * ksi - eta ), // 3 + -0.25 * ( 1. - ksi ) * ( -2.0 * eta - ksi ), + 0.25 * ( 1. - eta ) * ( 2.0 * ksi - eta ), // 4 + -0.25 * ( 1. + ksi ) * ( -2.0 * eta + ksi ), + -ksi * ( 1. + eta ), // 5 + 0.5 * ( 1. - ksi * ksi ), + -0.5 * ( 1. - eta * eta ), // 6 + -eta * ( 1. - ksi ), + -ksi * ( 1. - eta ), // 7 + -0.5 * ( 1. - ksi * ksi ), + 0.5 * ( 1. - eta * eta ), // 83 + -eta * ( 1. + ksi ) + }; +} + + +void FEI2dQuadQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ +#if 0 + answer = dNdxi(lcoords); +#else + double ksi = lcoords.at(1); + double eta = lcoords.at(2); + answer.resize(8, 2); + + // dn/dxi + answer.at(1, 1) = 0.25 * ( 1. + eta ) * ( 2.0 * ksi + eta ); + answer.at(2, 1) = -0.25 * ( 1. + eta ) * ( -2.0 * ksi + eta ); + answer.at(3, 1) = -0.25 * ( 1. - eta ) * ( -2.0 * ksi - eta ); + answer.at(4, 1) = 0.25 * ( 1. - eta ) * ( 2.0 * ksi - eta ); + answer.at(5, 1) = -ksi * ( 1. + eta ); + answer.at(6, 1) = -0.5 * ( 1. - eta * eta ); + answer.at(7, 1) = -ksi * ( 1. - eta ); + answer.at(8, 1) = 0.5 * ( 1. - eta * eta ); + + answer.at(1, 2) = 0.25 * ( 1. + ksi ) * ( 2.0 * eta + ksi ); + answer.at(2, 2) = 0.25 * ( 1. - ksi ) * ( 2.0 * eta - ksi ); + answer.at(3, 2) = -0.25 * ( 1. - ksi ) * ( -2.0 * eta - ksi ); + answer.at(4, 2) = -0.25 * ( 1. + ksi ) * ( -2.0 * eta + ksi ); + answer.at(5, 2) = 0.5 * ( 1. - ksi * ksi ); + answer.at(6, 2) = -eta * ( 1. - ksi ); + answer.at(7, 2) = -0.5 * ( 1. - ksi * ksi ); + answer.at(8, 2) = -eta * ( 1. + ksi ); +#endif +} + + +std::pair> +FEI2dQuadQuad :: evaldNdx(const FloatArrayF<2> &lcoords, const FEICellGeometry &cellgeo) const +{ + auto dn = evaldNdxi(lcoords); + FloatMatrixF<2,2> jacT; + for ( std::size_t i = 1; i <= dn.cols(); i++ ) { + const auto &c = cellgeo.giveVertexCoordinates(i); + double x = c.at(xind); + double y = c.at(yind); + + ///@todo check transpose + jacT(0, 0) += dn.at(1, i) * x; + jacT(0, 1) += dn.at(1, i) * y; + jacT(1, 0) += dn.at(2, i) * x; + jacT(1, 1) += dn.at(2, i) * y; + } + + return {det(jacT), dot(inv(jacT), dn)}; +} + + double -FEI2dQuadQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + auto tmp = evaldNdx(lcoords, cellgeo); + answer = tmp.second; + return tmp.first; +#else FloatMatrix jacobianMatrix(2, 2), inv, dn; this->evaldNdxi(dn, lcoords, cellgeo); for ( int i = 1; i <= dn.giveNumberOfRows(); i++ ) { - double x = cellgeo.giveVertexCoordinates(i)->at(xind); - double y = cellgeo.giveVertexCoordinates(i)->at(yind); + double x = cellgeo.giveVertexCoordinates(i).at(xind); + double y = cellgeo.giveVertexCoordinates(i).at(yind); jacobianMatrix.at(1, 1) += dn.at(i, 1) * x; jacobianMatrix.at(1, 2) += dn.at(i, 1) * y; @@ -119,10 +223,11 @@ FEI2dQuadQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const answer.beProductTOf(dn, inv); return jacobianMatrix.giveDeterminant(); +#endif } void -FEI2dQuadQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; @@ -131,16 +236,16 @@ FEI2dQuadQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, co answer.resize(2); answer.zero(); for ( int i = 1; i <= n.giveSize(); i++ ) { - answer.at(1) += n.at(i) * cellgeo.giveVertexCoordinates(i)->at(xind); - answer.at(2) += n.at(i) * cellgeo.giveVertexCoordinates(i)->at(yind); + answer.at(1) += n.at(i) * cellgeo.giveVertexCoordinates(i).at(xind); + answer.at(2) += n.at(i) * cellgeo.giveVertexCoordinates(i).at(yind); } } double FEI2dQuadQuad :: giveCharacteristicLength(const FEICellGeometry &cellgeo) const { - const FloatArray *n1 = cellgeo.giveVertexCoordinates(1); - const FloatArray *n2 = cellgeo.giveVertexCoordinates(3); - return n1->distance(n2); + const auto &n1 = cellgeo.giveVertexCoordinates(1); + const auto &n2 = cellgeo.giveVertexCoordinates(3); + return distance(n1, n2); } bool FEI2dQuadQuad :: inside(const FloatArray &lcoords) const @@ -160,19 +265,19 @@ bool FEI2dQuadQuad :: inside(const FloatArray &lcoords) const void -FEI2dQuadQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // 1-------3-------2 - double n3, ksi = lcoords.at(1); - n3 = 1. - ksi * ksi; + double ksi = lcoords.at(1); + double n3 = 1. - ksi * ksi; answer = { ( 1. - ksi - n3 ) * 0.5, ( 1. + ksi - n3 ) * 0.5, n3 }; } void FEI2dQuadQuad :: edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); answer = { ksi - 0.5, ksi + 0.5, ksi * 2.0 }; @@ -180,58 +285,42 @@ FEI2dQuadQuad :: edgeEvaldNds(FloatArray &answer, int iedge, void FEI2dQuadQuad :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; FloatArray n; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); this->edgeEvalN(n, iedge, lcoords, cellgeo); answer.resize(2); - answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) + - n.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(xind) ); - answer.at(2) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) + - n.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(yind) ); + answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind) + + n.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(xind); + answer.at(2) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind) + + n.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(yind); } -void -FEI2dQuadQuad :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI2dQuadQuad :: computeLocalEdgeMapping(int iedge) const { - int aNode = 0, bNode = 0, cNode = 0; - edgeNodes.resize(3); - if ( iedge == 1 ) { // edge between nodes 1 2 - aNode = 1; - bNode = 2; - cNode = 5; + return {1, 2, 5}; } else if ( iedge == 2 ) { // edge between nodes 2 3 - aNode = 2; - bNode = 3; - cNode = 6; + return {2, 3, 6}; } else if ( iedge == 3 ) { // edge between nodes 2 3 - aNode = 3; - bNode = 4; - cNode = 7; + return {3, 4, 7}; } else if ( iedge == 4 ) { // edge between nodes 3 4 - aNode = 4; - bNode = 1; - cNode = 8; + return {4, 1, 8}; } else { - OOFEM_ERROR("wrong edge number (%d)", iedge); + throw std::range_error("invalid edge number"); + return {}; } - - edgeNodes.at(1) = aNode; - edgeNodes.at(2) = bNode; - edgeNodes.at(3) = cNode; } -double FEI2dQuadQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dQuadQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); double xi = lcoords(0); double dN1dxi = -0.5 + xi; double dN2dxi = 0.5 + xi; @@ -239,129 +328,92 @@ double FEI2dQuadQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const Floa normal.resize(2); - normal.at(1) = dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind) + - dN2dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) + - dN3dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(yind); + normal.at(1) = dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind) + + dN2dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind) + + dN3dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(yind); - normal.at(2) = -dN1dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) + - - dN2dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) + - - dN3dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(xind); + normal.at(2) = - dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) + + - dN2dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind) + + - dN3dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(xind); return normal.normalize(); } -void FEI2dQuadQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) -{ - double ksi, eta; - ksi = lcoords.at(1); - eta = lcoords.at(2); - answer.resize(8, 2); - - // dn/dxi - answer.at(1, 1) = 0.25 * ( 1. + eta ) * ( 2.0 * ksi + eta ); - answer.at(2, 1) = -0.25 * ( 1. + eta ) * ( -2.0 * ksi + eta ); - answer.at(3, 1) = -0.25 * ( 1. - eta ) * ( -2.0 * ksi - eta ); - answer.at(4, 1) = 0.25 * ( 1. - eta ) * ( 2.0 * ksi - eta ); - answer.at(5, 1) = -ksi * ( 1. + eta ); - answer.at(6, 1) = -0.5 * ( 1. - eta * eta ); - answer.at(7, 1) = -ksi * ( 1. - eta ); - answer.at(8, 1) = 0.5 * ( 1. - eta * eta ); - - answer.at(1, 2) = 0.25 * ( 1. + ksi ) * ( 2.0 * eta + ksi ); - answer.at(2, 2) = 0.25 * ( 1. - ksi ) * ( 2.0 * eta - ksi ); - answer.at(3, 2) = -0.25 * ( 1. - ksi ) * ( -2.0 * eta - ksi ); - answer.at(4, 2) = -0.25 * ( 1. + ksi ) * ( -2.0 * eta + ksi ); - answer.at(5, 2) = 0.5 * ( 1. - ksi * ksi ); - answer.at(6, 2) = -eta * ( 1. - ksi ); - answer.at(7, 2) = -0.5 * ( 1. - ksi * ksi ); - answer.at(8, 2) = -eta * ( 1. + ksi ); -} - - double -FEI2dQuadQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) +FEI2dQuadQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const { - IntArray eNodes; - const FloatArray *node; - double x1, x2, x3, y1, y2, y3; - - this->computeLocalEdgeMapping(eNodes, iEdge); + auto eNodes = this->computeLocalEdgeMapping(iEdge); - node = cellgeo.giveVertexCoordinates( eNodes.at(1) ); - x1 = node->at(xind); - y1 = node->at(yind); + const FloatArray &node1 = cellgeo.giveVertexCoordinates( eNodes.at(1) ); + double x1 = node1.at(xind); + double y1 = node1.at(yind); - node = cellgeo.giveVertexCoordinates( eNodes.at(2) ); - x2 = node->at(xind); - y2 = node->at(yind); + const FloatArray &node2 = cellgeo.giveVertexCoordinates( eNodes.at(2) ); + double x2 = node2.at(xind); + double y2 = node2.at(yind); - node = cellgeo.giveVertexCoordinates( eNodes.at(3) ); - x3 = node->at(xind); - y3 = node->at(yind); + const FloatArray &node3 = cellgeo.giveVertexCoordinates( eNodes.at(3) ); + double x3 = node3.at(xind); + double y3 = node3.at(yind); return -( x1 * y2 - x2 * y1 + 4 * ( x3 * ( y1 - y2 ) + y3 * ( x2 - x1 ) ) ) / 3.0; } -IntegrationRule * -FEI2dQuadQuad :: giveIntegrationRule(int order) +std::unique_ptr +FEI2dQuadQuad :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order + 4); iRule->SetUpPointsOnSquare(points, _Unknown); - return iRule; + return std::move(iRule); } /* * FEI2dQuadQuadAxi element */ - double -FEI2dQuadQuadAxi :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadQuadAxi :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FloatArray N; - this->evalN( N, lcoords, cellgeo); + FloatArray N; + this->evalN( N, lcoords, cellgeo); - double r = 0.0; - for ( int i = 1; i <= 8; i++ ) { - double x = cellgeo.giveVertexCoordinates(i)->at(1); - r += x * N.at(i); - } + double r = 0.0; + for ( int i = 1; i <= 8; i++ ) { + double x = cellgeo.giveVertexCoordinates(i).at(1); + r += x * N.at(i); + } - return r * FEI2dQuadQuad::giveTransformationJacobian(lcoords, cellgeo); + return r * FEI2dQuadQuad::giveTransformationJacobian(lcoords, cellgeo); } double FEI2dQuadQuadAxi::edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - FloatArray n; - this->computeLocalEdgeMapping(edgeNodes, iedge); - this->edgeEvalN(n, iedge, lcoords, cellgeo); - - double r = n.at(1)*cellgeo.giveVertexCoordinates(edgeNodes.at(1))->at(1) + - n.at(2)*cellgeo.giveVertexCoordinates(edgeNodes.at(2))->at(1) + - n.at(3)*cellgeo.giveVertexCoordinates(edgeNodes.at(3))->at(1); - return r * FEI2dQuadQuad::edgeGiveTransformationJacobian(iedge, lcoords, cellgeo); + FloatArray n; + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); + this->edgeEvalN(n, iedge, lcoords, cellgeo); + + double r = n.at(1)*cellgeo.giveVertexCoordinates(edgeNodes.at(1)).at(1) + + n.at(2)*cellgeo.giveVertexCoordinates(edgeNodes.at(2)).at(1) + + n.at(3)*cellgeo.giveVertexCoordinates(edgeNodes.at(3)).at(1); + return r * FEI2dQuadQuad::edgeGiveTransformationJacobian(iedge, lcoords, cellgeo); } - + double -FEI2dQuadQuadAxi::boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadQuadAxi::boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); + return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); } double -FEI2dQuadQuadAxi::boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dQuadQuadAxi::boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); + return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); } - - - } // end namespace oofem diff --git a/src/oofemlib/fei2dquadquad.h b/src/oofemlib/fei2dquadquad.h index 66cd0195c..2b071cdb3 100644 --- a/src/oofemlib/fei2dquadquad.h +++ b/src/oofemlib/fei2dquadquad.h @@ -54,45 +54,41 @@ class OOFEM_EXPORT FEI2dQuadQuad : public FEInterpolation2d public: FEI2dQuadQuad(int ind1, int ind2) : FEInterpolation2d(2, ind1, ind2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Square; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_quad_2; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Line; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Square; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Square; } + Element_Geometry_Type giveGeometryType() const override { return EGT_quad_2; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Line; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Square; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } - virtual double giveArea(const FEICellGeometry &cellgeo) const; + double giveArea(const FEICellGeometry &cellgeo) const override; // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int giveNumberOfNodes() const { return 8; } - /** - * Returns a characteristic length of the geometry, typically a diagonal or edge length. - * @param cellgeo underlying cell geometry - * @return distance from node 1 to 3 - */ - virtual double giveCharacteristicLength(const FEICellGeometry &cellgeo) const; + static FloatArrayF<8> evalN(const FloatArrayF<2> &lcoords) ; + static FloatMatrixF<2,8> evaldNdxi(const FloatArrayF<2> &lcoords) ; + std::pair> evaldNdx(const FloatArrayF<2> &lcoords, const FEICellGeometry &cellgeo) const; - virtual bool inside(const FloatArray &lcoords) const; + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int giveNumberOfNodes() const override { return 8; } - // Edge - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo); + double giveCharacteristicLength(const FEICellGeometry &cellgeo) const override; - virtual IntegrationRule *giveIntegrationRule(int order); + bool inside(const FloatArray &lcoords) const override; - virtual void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + // Edge + IntArray computeLocalEdgeMapping(int iedge) const override; + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const override; + + std::unique_ptr giveIntegrationRule(int order) const override; }; - /** * Class representing a 2d isoparametric quadratic interpolation based on natural coordinates * for quadrilateral elements in axisymmetric setting. @@ -100,17 +96,13 @@ class OOFEM_EXPORT FEI2dQuadQuad : public FEInterpolation2d class OOFEM_EXPORT FEI2dQuadQuadAxi : public FEI2dQuadQuad { public: - FEI2dQuadQuadAxi(int ind1, int ind2) : FEI2dQuadQuad(ind1, ind2) { } - - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - -}; - + FEI2dQuadQuadAxi(int ind1, int ind2) : FEI2dQuadQuad(ind1, ind2) { } + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; +}; } // end namespace oofem #endif // fei2dquadquad_h diff --git a/src/oofemlib/fei2dtrconst.C b/src/oofemlib/fei2dtrconst.C index b1e40d0d6..93ab32392 100644 --- a/src/oofemlib/fei2dtrconst.C +++ b/src/oofemlib/fei2dtrconst.C @@ -39,13 +39,13 @@ namespace oofem { void -FEI2dTrConst :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrConst :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer = FloatArray{1.}; } double -FEI2dTrConst :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrConst :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(1, 2); answer.zero(); @@ -54,13 +54,11 @@ FEI2dTrConst :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const F } void -FEI2dTrConst :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrConst :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double l1, l2, l3; - - l1 = lcoords.at(1); - l2 = lcoords.at(2); - l3 = 1.0 - l1 - l2; + double l1 = lcoords.at(1); + double l2 = lcoords.at(2); + double l3 = 1.0 - l1 - l2; answer.resize(2); answer.at(1) = ( l1 * cellgeo.giveVertexCoordinates(1)->at(xind) + @@ -74,19 +72,17 @@ FEI2dTrConst :: local2global(FloatArray &answer, const FloatArray &lcoords, cons #define POINT_TOL 1.e-3 int -FEI2dTrConst :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) +FEI2dTrConst :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) const { - double detJ, x1, x2, x3, y1, y2, y3; - - x1 = cellgeo.giveVertexCoordinates(1)->at(xind); - x2 = cellgeo.giveVertexCoordinates(2)->at(xind); - x3 = cellgeo.giveVertexCoordinates(3)->at(xind); + double x1 = cellgeo.giveVertexCoordinates(1)->at(xind); + double x2 = cellgeo.giveVertexCoordinates(2)->at(xind); + double x3 = cellgeo.giveVertexCoordinates(3)->at(xind); - y1 = cellgeo.giveVertexCoordinates(1)->at(yind); - y2 = cellgeo.giveVertexCoordinates(2)->at(yind); - y3 = cellgeo.giveVertexCoordinates(3)->at(yind); + double y1 = cellgeo.giveVertexCoordinates(1)->at(yind); + double y2 = cellgeo.giveVertexCoordinates(2)->at(yind); + double y3 = cellgeo.giveVertexCoordinates(3)->at(yind); - detJ = ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 ); + double detJ = ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 ); answer.resize(3); answer.at(1) = ( ( x2 * y3 - x3 * y2 ) + ( y2 - y3 ) * coords.at(xind) + ( x3 - x2 ) * coords.at(yind) ) / detJ; @@ -111,31 +107,29 @@ FEI2dTrConst :: global2local(FloatArray &answer, const FloatArray &coords, const double -FEI2dTrConst :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrConst :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double x1, x2, x3, y1, y2, y3; + double x1 = cellgeo.giveVertexCoordinates(1)->at(xind); + double x2 = cellgeo.giveVertexCoordinates(2)->at(xind); + double x3 = cellgeo.giveVertexCoordinates(3)->at(xind); - x1 = cellgeo.giveVertexCoordinates(1)->at(xind); - x2 = cellgeo.giveVertexCoordinates(2)->at(xind); - x3 = cellgeo.giveVertexCoordinates(3)->at(xind); - - y1 = cellgeo.giveVertexCoordinates(1)->at(yind); - y2 = cellgeo.giveVertexCoordinates(2)->at(yind); - y3 = cellgeo.giveVertexCoordinates(3)->at(yind); + double y1 = cellgeo.giveVertexCoordinates(1)->at(yind); + double y2 = cellgeo.giveVertexCoordinates(2)->at(yind); + double y3 = cellgeo.giveVertexCoordinates(3)->at(yind); return x1 * ( y2 - y3 ) + x2 * ( -y1 + y3 ) + x3 * ( y1 - y2 ); } void -FEI2dTrConst :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrConst :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(1); answer.at(1) = 1.; } double -FEI2dTrConst :: edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrConst :: edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("Not applicable to constant interpolation"); return 0.; @@ -143,18 +137,17 @@ FEI2dTrConst :: edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray & void FEI2dTrConst :: edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer = { 0., 0. }; } void FEI2dTrConst :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; FloatArray n = { ( 1 - lcoords(0) ) * 0.5, ( 1 + lcoords(0) ) * 0.5 }; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); answer.resize(2); answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) + @@ -163,49 +156,38 @@ FEI2dTrConst :: edgeLocal2global(FloatArray &answer, int iedge, n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) ); } -void -FEI2dTrConst :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI2dTrConst :: computeLocalEdgeMapping(int iedge) const { - int aNode = 0, bNode = 0; - edgeNodes.resize(2); - if ( iedge == 1 ) { // edge between nodes 1 2 - aNode = 1; - bNode = 2; + return {1, 2}; } else if ( iedge == 2 ) { // edge between nodes 2 3 - aNode = 2; - bNode = 3; + return {2, 3}; } else if ( iedge == 3 ) { // edge between nodes 2 3 - aNode = 3; - bNode = 1; + return {3, 1}; } else { - OOFEM_ERROR("wrong egde number (%d)", iedge); + throw std::range_error("invalid edge number"); + return {}; } - - edgeNodes.at(1) = aNode; - edgeNodes.at(2) = bNode; } double -FEI2dTrConst :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) +FEI2dTrConst :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) const { - double dx, dy; - int nodeA, nodeB; - - nodeA = edgeNodes.at(1); - nodeB = edgeNodes.at(2); + auto nodeA = edgeNodes.at(1); + auto nodeB = edgeNodes.at(2); - dx = cellgeo.giveVertexCoordinates(nodeB)->at(xind) - cellgeo.giveVertexCoordinates(nodeA)->at(xind); - dy = cellgeo.giveVertexCoordinates(nodeB)->at(yind) - cellgeo.giveVertexCoordinates(nodeA)->at(yind); + double dx = cellgeo.giveVertexCoordinates(nodeB)->at(xind) - cellgeo.giveVertexCoordinates(nodeA)->at(xind); + double dy = cellgeo.giveVertexCoordinates(nodeB)->at(yind) - cellgeo.giveVertexCoordinates(nodeA)->at(yind); return sqrt(dx * dx + dy * dy); } -IntegrationRule * -FEI2dTrConst :: giveIntegrationRule(int order) +std::unique_ptr +FEI2dTrConst :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, order + 0); iRule->SetUpPointsOnTriangle(points, _Unknown); - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei2dtrconst.h b/src/oofemlib/fei2dtrconst.h index 2270c4cd5..81c3be926 100644 --- a/src/oofemlib/fei2dtrconst.h +++ b/src/oofemlib/fei2dtrconst.h @@ -44,36 +44,31 @@ namespace oofem { class OOFEM_EXPORT FEI2dTrConst : public FEInterpolation2d { public: - FEI2dTrConst(int ind1, int ind2) : FEInterpolation2d(0) { - xind = ind1; - yind = ind2; - } + FEI2dTrConst(int ind1, int ind2) : FEInterpolation2d(0, ind1, ind2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_1; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } + Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_1; } // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; // Edge - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); + IntArray computeLocalEdgeMapping(int iedge) const override; + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; - virtual IntegrationRule *giveIntegrationRule(int order); + std::unique_ptr giveIntegrationRule(int order) const override; - virtual int giveNumberOfNodes() const { return 3; } + int giveNumberOfNodes() const override { return 3; } protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; }; } // end namespace oofem #endif // fei2dtrlin_h diff --git a/src/oofemlib/fei2dtrlin.C b/src/oofemlib/fei2dtrlin.C index b57d1d290..3526bfec6 100644 --- a/src/oofemlib/fei2dtrlin.C +++ b/src/oofemlib/fei2dtrlin.C @@ -36,11 +36,20 @@ #include "mathfem.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "gaussintegrationrule.h" namespace oofem { + +FloatArrayF<3> +FEI2dTrLin :: evalN(const FloatArrayF<2> &lcoords) +{ + return {lcoords[0], lcoords[1], 1. - lcoords[0] - lcoords[1]}; +} + void -FEI2dTrLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer = { lcoords.at(1), @@ -49,18 +58,39 @@ FEI2dTrLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICell }; } +std::pair> +FEI2dTrLin :: evaldNdx(const FEICellGeometry &cellgeo) const +{ + double x1 = cellgeo.giveVertexCoordinates(1).at(xind); + double x2 = cellgeo.giveVertexCoordinates(2).at(xind); + double x3 = cellgeo.giveVertexCoordinates(3).at(xind); + double y1 = cellgeo.giveVertexCoordinates(1).at(yind); + double y2 = cellgeo.giveVertexCoordinates(2).at(yind); + double y3 = cellgeo.giveVertexCoordinates(3).at(yind); + double detJ = x1 * ( y2 - y3 ) + x2 * ( y3 - y1 ) + x3 * ( y1 - y2 ); + + FloatMatrixF<2,3> ans = { + y2 - y3, x3 - x2, + y3 - y1, x1 - x3, + y1 - y2, x2 - x1, + }; + + return {detJ, ans * (1./detJ)}; +} + + double -FEI2dTrLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double x1, x2, x3, y1, y2, y3, detJ; - x1 = cellgeo.giveVertexCoordinates(1)->at(xind); - x2 = cellgeo.giveVertexCoordinates(2)->at(xind); - x3 = cellgeo.giveVertexCoordinates(3)->at(xind); + x1 = cellgeo.giveVertexCoordinates(1).at(xind); + x2 = cellgeo.giveVertexCoordinates(2).at(xind); + x3 = cellgeo.giveVertexCoordinates(3).at(xind); - y1 = cellgeo.giveVertexCoordinates(1)->at(yind); - y2 = cellgeo.giveVertexCoordinates(2)->at(yind); - y3 = cellgeo.giveVertexCoordinates(3)->at(yind); + y1 = cellgeo.giveVertexCoordinates(1).at(yind); + y2 = cellgeo.giveVertexCoordinates(2).at(yind); + y3 = cellgeo.giveVertexCoordinates(3).at(yind); detJ = x1 * ( y2 - y3 ) + x2 * ( -y1 + y3 ) + x3 * ( y1 - y2 ); @@ -78,41 +108,36 @@ FEI2dTrLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEI } void -FEI2dTrLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double l1, l2, l3; - - l1 = lcoords.at(1); - l2 = lcoords.at(2); - l3 = 1.0 - l1 - l2; + double l1 = lcoords.at(1); + double l2 = lcoords.at(2); + double l3 = 1.0 - l1 - l2; - //answer.resize(2); answer.resize(3); answer.zero(); - answer.at(1) = ( l1 * cellgeo.giveVertexCoordinates(1)->at(xind) + - l2 * cellgeo.giveVertexCoordinates(2)->at(xind) + - l3 * cellgeo.giveVertexCoordinates(3)->at(xind) ); - answer.at(2) = ( l1 * cellgeo.giveVertexCoordinates(1)->at(yind) + - l2 * cellgeo.giveVertexCoordinates(2)->at(yind) + - l3 * cellgeo.giveVertexCoordinates(3)->at(yind) ); + answer.at(1) = l1 * cellgeo.giveVertexCoordinates(1).at(xind) + + l2 * cellgeo.giveVertexCoordinates(2).at(xind) + + l3 * cellgeo.giveVertexCoordinates(3).at(xind); + answer.at(2) = l1 * cellgeo.giveVertexCoordinates(1).at(yind) + + l2 * cellgeo.giveVertexCoordinates(2).at(yind) + + l3 * cellgeo.giveVertexCoordinates(3).at(yind); } #define POINT_TOL 1.e-3 int -FEI2dTrLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) +FEI2dTrLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) const { - double detJ, x1, x2, x3, y1, y2, y3; + double x1 = cellgeo.giveVertexCoordinates(1).at(xind); + double x2 = cellgeo.giveVertexCoordinates(2).at(xind); + double x3 = cellgeo.giveVertexCoordinates(3).at(xind); - x1 = cellgeo.giveVertexCoordinates(1)->at(xind); - x2 = cellgeo.giveVertexCoordinates(2)->at(xind); - x3 = cellgeo.giveVertexCoordinates(3)->at(xind); + double y1 = cellgeo.giveVertexCoordinates(1).at(yind); + double y2 = cellgeo.giveVertexCoordinates(2).at(yind); + double y3 = cellgeo.giveVertexCoordinates(3).at(yind); - y1 = cellgeo.giveVertexCoordinates(1)->at(yind); - y2 = cellgeo.giveVertexCoordinates(2)->at(yind); - y3 = cellgeo.giveVertexCoordinates(3)->at(yind); - - detJ = x1 * ( y2 - y3 ) + x2 * ( -y1 + y3 ) + x3 * ( y1 - y2 ); + double detJ = x1 * ( y2 - y3 ) + x2 * ( -y1 + y3 ) + x3 * ( y1 - y2 ); answer.resize(3); answer.at(1) = ( ( x2 * y3 - x3 * y2 ) + ( y2 - y3 ) * coords.at(xind) + ( x3 - x2 ) * coords.at(yind) ) / detJ; @@ -144,17 +169,15 @@ FEI2dTrLin :: global2local(FloatArray &answer, const FloatArray &coords, const F double -FEI2dTrLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double x1, x2, x3, y1, y2, y3; - - x1 = cellgeo.giveVertexCoordinates(1)->at(xind); - x2 = cellgeo.giveVertexCoordinates(2)->at(xind); - x3 = cellgeo.giveVertexCoordinates(3)->at(xind); + double x1 = cellgeo.giveVertexCoordinates(1).at(xind); + double x2 = cellgeo.giveVertexCoordinates(2).at(xind); + double x3 = cellgeo.giveVertexCoordinates(3).at(xind); - y1 = cellgeo.giveVertexCoordinates(1)->at(yind); - y2 = cellgeo.giveVertexCoordinates(2)->at(yind); - y3 = cellgeo.giveVertexCoordinates(3)->at(yind); + double y1 = cellgeo.giveVertexCoordinates(1).at(yind); + double y2 = cellgeo.giveVertexCoordinates(2).at(yind); + double y3 = cellgeo.giveVertexCoordinates(3).at(yind); return ( x1 * ( y2 - y3 ) + x2 * ( -y1 + y3 ) + x3 * ( y1 - y2 ) ); } @@ -181,7 +204,7 @@ bool FEI2dTrLin :: inside(const FloatArray &lcoords) const } void -FEI2dTrLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); answer = { ( 1. - ksi ) * 0.5, ( 1. + ksi ) * 0.5 }; @@ -189,176 +212,147 @@ FEI2dTrLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords void FEI2dTrLin :: edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); double l = this->edgeComputeLength(edgeNodes, cellgeo); answer = { -1.0 / l, 1.0 / l }; } -double FEI2dTrLin :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dTrLin :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); normal = { - cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) - cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind), - cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) - cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) + cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind) - cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind), + cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) - cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind) }; return normal.normalize() * 0.5; } void FEI2dTrLin :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; FloatArray n; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); this->edgeEvalN(n, iedge, lcoords, cellgeo); answer.resize(2); - answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) ); - answer.at(2) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) ); + answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind) ); + answer.at(2) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind) ); } -void -FEI2dTrLin :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI2dTrLin :: computeLocalEdgeMapping(int iedge) const { - int aNode = 0, bNode = 0; - edgeNodes.resize(2); - if ( iedge == 1 ) { // edge between nodes 1 2 - aNode = 1; - bNode = 2; + return {1, 2}; } else if ( iedge == 2 ) { // edge between nodes 2 3 - aNode = 2; - bNode = 3; + return {2, 3}; } else if ( iedge == 3 ) { // edge between nodes 2 3 - aNode = 3; - bNode = 1; + return {3, 1}; } else { - OOFEM_ERROR("wrong egde number (%d)", iedge); + throw std::range_error("invalid edge number"); + return {}; } - - edgeNodes.at(1) = aNode; - edgeNodes.at(2) = bNode; } double -FEI2dTrLin :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) +FEI2dTrLin :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const { - double dx, dy; - int nodeA, nodeB; - - nodeA = edgeNodes.at(1); - nodeB = edgeNodes.at(2); + int nodeA = edgeNodes.at(1); + int nodeB = edgeNodes.at(2); - dx = cellgeo.giveVertexCoordinates(nodeB)->at(xind) - cellgeo.giveVertexCoordinates(nodeA)->at(xind); - dy = cellgeo.giveVertexCoordinates(nodeB)->at(yind) - cellgeo.giveVertexCoordinates(nodeA)->at(yind); + double dx = cellgeo.giveVertexCoordinates(nodeB).at(xind) - cellgeo.giveVertexCoordinates(nodeA).at(xind); + double dy = cellgeo.giveVertexCoordinates(nodeB).at(yind) - cellgeo.giveVertexCoordinates(nodeA).at(yind); return sqrt(dx * dx + dy * dy); } double FEI2dTrLin :: giveArea(const FEICellGeometry &cellgeo) const { - const FloatArray *p; - double x1, x2, x3, y1, y2, y3; - - p = cellgeo.giveVertexCoordinates(1); - x1 = p->at(1); - y1 = p->at(2); - p = cellgeo.giveVertexCoordinates(2); - x2 = p->at(1); - y2 = p->at(2); - p = cellgeo.giveVertexCoordinates(3); - x3 = p->at(1); - y3 = p->at(2); + const auto &p1 = cellgeo.giveVertexCoordinates(1); + double x1 = p1.at(xind); + double y1 = p1.at(yind); + const auto &p2 = cellgeo.giveVertexCoordinates(2); + double x2 = p2.at(xind); + double y2 = p2.at(yind); + const auto &p3 = cellgeo.giveVertexCoordinates(3); + double x3 = p3.at(xind); + double y3 = p3.at(yind); return fabs( 0.5 * ( x1 * ( y2 - y3 ) + x2 * ( -y1 + y3 ) + x3 * ( y1 - y2 ) ) ); } double -FEI2dTrLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) +FEI2dTrLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const { - IntArray eNodes; - const FloatArray *node; - double x1, x2, y1, y2; + const auto &eNodes = this->computeLocalEdgeMapping(iEdge); - this->computeLocalEdgeMapping(eNodes, iEdge); + const auto &node1 = cellgeo.giveVertexCoordinates( eNodes.at(1) ); + double x1 = node1.at(xind); + double y1 = node1.at(yind); - node = cellgeo.giveVertexCoordinates( eNodes.at(1) ); - x1 = node->at(xind); - y1 = node->at(yind); - - node = cellgeo.giveVertexCoordinates( eNodes.at(2) ); - x2 = node->at(xind); - y2 = node->at(yind); + const auto &node2 = cellgeo.giveVertexCoordinates( eNodes.at(2) ); + double x2 = node2.at(xind); + double y2 = node2.at(yind); return -( x2 * y1 - x1 * y2 ); } -IntegrationRule * -FEI2dTrLin :: giveIntegrationRule(int order) +std::unique_ptr +FEI2dTrLin :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, order + 0); iRule->SetUpPointsOnTriangle(points, _Unknown); - return iRule; + return std::move(iRule); } - - - - // FEI2dTrLinAxi element - double -FEI2dTrLinAxi :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrLinAxi :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FloatArray N; - this->evalN( N, lcoords, cellgeo); + FloatArray N; + this->evalN( N, lcoords, cellgeo); - double r = 0.0; - for ( int i = 1; i <= 3; i++ ) { - double x = cellgeo.giveVertexCoordinates(i)->at(1); - r += x * N.at(i); - } + double r = 0.0; + for ( int i = 1; i <= 3; i++ ) { + double x = cellgeo.giveVertexCoordinates(i).at(1); + r += x * N.at(i); + } - return r * FEI2dTrLin::giveTransformationJacobian(lcoords, cellgeo); + return r * FEI2dTrLin::giveTransformationJacobian(lcoords, cellgeo); } double FEI2dTrLinAxi::edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - FloatArray n; - this->computeLocalEdgeMapping(edgeNodes, iedge); - this->edgeEvalN(n, iedge, lcoords, cellgeo); + FloatArray n; + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); + this->edgeEvalN(n, iedge, lcoords, cellgeo); - double r = n.at(1)*cellgeo.giveVertexCoordinates(edgeNodes.at(1))->at(1) + n.at(2)*cellgeo.giveVertexCoordinates(edgeNodes.at(2))->at(1); - return r * FEI2dTrLin::edgeGiveTransformationJacobian(iedge, lcoords, cellgeo); + double r = n.at(1)*cellgeo.giveVertexCoordinates(edgeNodes.at(1)).at(1) + n.at(2)*cellgeo.giveVertexCoordinates(edgeNodes.at(2)).at(1); + return r * FEI2dTrLin::edgeGiveTransformationJacobian(iedge, lcoords, cellgeo); } - + double -FEI2dTrLinAxi::boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrLinAxi::boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); + return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); } double -FEI2dTrLinAxi::boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrLinAxi::boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); + return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); } - - } // end namespace oofem diff --git a/src/oofemlib/fei2dtrlin.h b/src/oofemlib/fei2dtrlin.h index 458893a19..3d37f71e8 100644 --- a/src/oofemlib/fei2dtrlin.h +++ b/src/oofemlib/fei2dtrlin.h @@ -46,40 +46,40 @@ class OOFEM_EXPORT FEI2dTrLin : public FEInterpolation2d public: FEI2dTrLin(int ind1, int ind2) : FEInterpolation2d(1, ind1, ind2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Line; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Triangle; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Line; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Triangle; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } - - virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_1; } + Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_1; } // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveArea(const FEICellGeometry &cellgeo) const; - virtual int giveNumberOfNodes() const { return 3; } + static FloatArrayF<3> evalN(const FloatArrayF<2> &lcoords) ; + std::pair> evaldNdx(const FEICellGeometry &cellgeo) const; + + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveArea(const FEICellGeometry &cellgeo) const override; + int giveNumberOfNodes() const override { return 3; } - virtual bool inside(const FloatArray &lcoords) const; + bool inside(const FloatArray &lcoords) const override; // Edge - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); - virtual int giveNumberOfEdges() const { return 3; } - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo); + IntArray computeLocalEdgeMapping(int iedge) const override; + int giveNumberOfEdges() const override { return 3; } + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const override; - virtual IntegrationRule *giveIntegrationRule(int order); + std::unique_ptr giveIntegrationRule(int order) const override; protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; }; /** @@ -89,17 +89,14 @@ class OOFEM_EXPORT FEI2dTrLin : public FEInterpolation2d class OOFEM_EXPORT FEI2dTrLinAxi : public FEI2dTrLin { public: - FEI2dTrLinAxi(int ind1, int ind2) : FEI2dTrLin(ind1, ind2) { } - - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - -}; + FEI2dTrLinAxi(int ind1, int ind2) : FEI2dTrLin(ind1, ind2) { } + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; +}; } // end namespace oofem #endif // fei2dtrlin_h diff --git a/src/oofemlib/fei2dtrquad.C b/src/oofemlib/fei2dtrquad.C index ee3a8ea06..3eb6ebe8f 100644 --- a/src/oofemlib/fei2dtrquad.C +++ b/src/oofemlib/fei2dtrquad.C @@ -36,12 +36,35 @@ #include "mathfem.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "gaussintegrationrule.h" namespace oofem { + +FloatArrayF<6> +FEI2dTrQuad :: evalN(const FloatArrayF<2> &lcoords) +{ + double l1 = lcoords[0]; + double l2 = lcoords[1]; + double l3 = 1. - l1 - l2; + + return { + ( 2. * l1 - 1. ) * l1, + ( 2. * l2 - 1. ) * l2, + ( 2. * l3 - 1. ) * l3, + 4. * l1 * l2, + 4. * l2 * l3, + 4. * l3 * l1 + }; +} + void -FEI2dTrQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + answer = evalN(lcoords); +#else double l1 = lcoords.at(1); double l2 = lcoords.at(2); double l3 = 1. - l1 - l2; @@ -54,17 +77,69 @@ FEI2dTrQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICel 4. * l2 * l3, 4. * l3 * l1 }; +#endif } + +FloatMatrixF<2,6> +FEI2dTrQuad :: evaldNdxi(const FloatArrayF<2> &lcoords) +{ + double l1 = lcoords[0]; + double l2 = lcoords[1]; + double l3 = 1.0 - l1 - l2; + + return { + 4.0 * l1 - 1.0, // col0 + 0.0, + 0.0, // col1 + 4.0 * l2 - 1.0, + -1.0 * ( 4.0 * l3 - 1.0 ), // col2 + -1.0 * ( 4.0 * l3 - 1.0 ), + 4.0 * l2, // col3 + 4.0 * l1, + -4.0 * l2, // col4 + 4.0 * l3 - 4.0 * l2, + 4.0 * l3 - 4.0 * l1, // col5 + -4.0 * l1, + }; +} + + +std::pair> +FEI2dTrQuad :: evaldNdx(const FloatArrayF<2> &lcoords, const FEICellGeometry &cellgeo) const +{ + auto dn = evaldNdxi(lcoords); + FloatMatrixF<2,2> jacT; + for ( std::size_t i = 1; i <= dn.cols(); i++ ) { + const auto &c = cellgeo.giveVertexCoordinates(i); + double x = c.at(xind); + double y = c.at(yind); + + ///@todo check transpose + jacT(0, 0) += dn.at(1, i) * x; + jacT(0, 1) += dn.at(1, i) * y; + jacT(1, 0) += dn.at(2, i) * x; + jacT(1, 1) += dn.at(2, i) * y; + } + + return {det(jacT), dot(inv(jacT), dn)}; +} + + double -FEI2dTrQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + auto tmp = evaldNdx(lcoords, cellgeo); + answer = tmp.second; + return tmp.first; +#else FloatMatrix jacobianMatrix(2, 2), inv, dn; this->evaldNdxi(dn, lcoords, cellgeo); for ( int i = 1; i <= dn.giveNumberOfRows(); i++ ) { - double x = cellgeo.giveVertexCoordinates(i)->at(xind); - double y = cellgeo.giveVertexCoordinates(i)->at(yind); + double x = cellgeo.giveVertexCoordinates(i).at(xind); + double y = cellgeo.giveVertexCoordinates(i).at(yind); jacobianMatrix.at(1, 1) += dn.at(i, 1) * x; jacobianMatrix.at(1, 2) += dn.at(i, 1) * y; @@ -75,31 +150,29 @@ FEI2dTrQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FE answer.beProductTOf(dn, inv); return jacobianMatrix.giveDeterminant(); +#endif } void -FEI2dTrQuad :: evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrQuad :: evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double x1, x2, x3, y1, y2, y3, y23, x32, y31, x13, area; - - answer.resize(6, 3); + double x1 = cellgeo.giveVertexCoordinates(1).at(xind); + double x2 = cellgeo.giveVertexCoordinates(2).at(xind); + double x3 = cellgeo.giveVertexCoordinates(3).at(xind); - x1 = cellgeo.giveVertexCoordinates(1)->at(xind); - x2 = cellgeo.giveVertexCoordinates(2)->at(xind); - x3 = cellgeo.giveVertexCoordinates(3)->at(xind); + double y1 = cellgeo.giveVertexCoordinates(1).at(yind); + double y2 = cellgeo.giveVertexCoordinates(2).at(yind); + double y3 = cellgeo.giveVertexCoordinates(3).at(yind); - y1 = cellgeo.giveVertexCoordinates(1)->at(yind); - y2 = cellgeo.giveVertexCoordinates(2)->at(yind); - y3 = cellgeo.giveVertexCoordinates(3)->at(yind); + double area = 0.5 * ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 ); - area = 0.5 * ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 ); + double y23 = ( y2 - y3 ) / ( 2. * area ); + double x32 = ( x3 - x2 ) / ( 2. * area ); - y23 = ( y2 - y3 ) / ( 2. * area ); - x32 = ( x3 - x2 ) / ( 2. * area ); - - y31 = ( y3 - y1 ) / ( 2. * area ); - x13 = ( x1 - x3 ) / ( 2. * area ); + double y31 = ( y3 - y1 ) / ( 2. * area ); + double x13 = ( x1 - x3 ) / ( 2. * area ); + answer.resize(6, 3); answer.at(1, 1) = 4 * y23 * y23; answer.at(1, 2) = 4 * x32 * x32; answer.at(1, 3) = 4 * y23 * x32; @@ -128,7 +201,7 @@ FEI2dTrQuad :: evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const void -FEI2dTrQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; this->evalN(n, lcoords, cellgeo); @@ -136,24 +209,24 @@ FEI2dTrQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const answer.resize(2); answer.zero(); for ( int i = 1; i <= 6; i++ ) { - answer.at(1) += n.at(i) * cellgeo.giveVertexCoordinates(i)->at(xind); - answer.at(2) += n.at(i) * cellgeo.giveVertexCoordinates(i)->at(yind); + answer.at(1) += n.at(i) * cellgeo.giveVertexCoordinates(i).at(xind); + answer.at(2) += n.at(i) * cellgeo.giveVertexCoordinates(i).at(yind); } } void -FEI2dTrQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI2dTrQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double n3, ksi = lcoords.at(1); - n3 = 1. - ksi * ksi; + double ksi = lcoords.at(1); + double n3 = 1. - ksi * ksi; answer = { ( 1. - ksi - n3 ) * 0.5, ( 1. + ksi - n3 ) * 0.5, n3 }; } void FEI2dTrQuad :: edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // I think it at least should return both dNds and J. Both are almost always needed. // In fact, dxdxi is also needed sometimes (surface tension) @@ -167,12 +240,12 @@ FEI2dTrQuad :: edgeEvaldNds(FloatArray &answer, int iedge, dNdxi.at(2) = xi + 0.5; dNdxi.at(3) = -2 * xi; - dxdxi.at(1) = dNdxi.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) + - dNdxi.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) + - dNdxi.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(xind); - dxdxi.at(2) = dNdxi.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind) + - dNdxi.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) + - dNdxi.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(yind); + dxdxi.at(1) = dNdxi.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) + + dNdxi.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind) + + dNdxi.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(xind); + dxdxi.at(2) = dNdxi.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind) + + dNdxi.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind) + + dNdxi.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(yind); double J = dxdxi.computeNorm(); answer = dNdxi; @@ -189,10 +262,9 @@ FEI2dTrQuad :: edgeEvaldNds(FloatArray &answer, int iedge, }; } -double FEI2dTrQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI2dTrQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); double xi = lcoords(0); double dN1dxi = -0.5 + xi; double dN2dxi = 0.5 + xi; @@ -200,71 +272,57 @@ double FEI2dTrQuad :: edgeEvalNormal(FloatArray &normal, int iedge, const FloatA normal.resize(2); - normal.at(1) = dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind) + - dN2dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) + - dN3dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(yind); + normal.at(1) = dN1dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind) + + dN2dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind) + + dN3dxi * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(yind); - normal.at(2) = -dN1dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) + - - dN2dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) + - - dN3dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(xind); + normal.at(2) = - dN1dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) + + - dN2dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind) + + - dN3dxi *cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(xind); return normal.normalize(); } void FEI2dTrQuad :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; FloatArray n; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); this->edgeEvalN(n, iedge, lcoords, cellgeo); answer.resize(2); - answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(xind) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(xind) + - n.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(xind) ); - answer.at(2) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(yind) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(yind) + - n.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) )->at(yind) ); + answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(xind) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(xind) + + n.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(xind); + answer.at(2) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(yind) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(yind) + + n.at(3) * cellgeo.giveVertexCoordinates( edgeNodes.at(3) ).at(yind); } -void -FEI2dTrQuad :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI2dTrQuad :: computeLocalEdgeMapping(int iedge) const { - int aNode = 0, bNode = 0, cNode = 0; - edgeNodes.resize(3); - if ( iedge == 1 ) { // edge between nodes 1 2 - aNode = 1; - bNode = 2; - cNode = 4; + return {1, 2, 4}; } else if ( iedge == 2 ) { // edge between nodes 2 3 - aNode = 2; - bNode = 3; - cNode = 5; + return {2, 3, 5}; } else if ( iedge == 3 ) { // edge between nodes 2 3 - aNode = 3; - bNode = 1; - cNode = 6; + return {3, 1, 6}; } else { - OOFEM_ERROR("wrong egde number (%d)", iedge); + throw std::range_error("invalid edge number"); + return {}; } - - edgeNodes.at(1) = aNode; - edgeNodes.at(2) = bNode; - edgeNodes.at(3) = cNode; } -void FEI2dTrQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI2dTrQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double l1, l2, l3; - l1 = lcoords.at(1); - l2 = lcoords.at(2); - l3 = 1.0 - l1 - l2; + double l1 = lcoords.at(1); + double l2 = lcoords.at(2); + double l3 = 1.0 - l1 - l2; answer.resize(6, 2); @@ -287,27 +345,24 @@ void FEI2dTrQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, co double FEI2dTrQuad :: giveArea(const FEICellGeometry &cellgeo) const { - const FloatArray *p; - double x1, x2, x3, x4, x5, x6, y1, y2, y3, y4, y5, y6; - - p = cellgeo.giveVertexCoordinates(1); - x1 = p->at(1); - y1 = p->at(2); - p = cellgeo.giveVertexCoordinates(2); - x2 = p->at(1); - y2 = p->at(2); - p = cellgeo.giveVertexCoordinates(3); - x3 = p->at(1); - y3 = p->at(2); - p = cellgeo.giveVertexCoordinates(4); - x4 = p->at(1); - y4 = p->at(2); - p = cellgeo.giveVertexCoordinates(5); - x5 = p->at(1); - y5 = p->at(2); - p = cellgeo.giveVertexCoordinates(6); - x6 = p->at(1); - y6 = p->at(2); + const auto &p1 = cellgeo.giveVertexCoordinates(1); + double x1 = p1.at(xind); + double y1 = p1.at(yind); + const auto &p2 = cellgeo.giveVertexCoordinates(2); + double x2 = p2.at(xind); + double y2 = p2.at(yind); + const auto &p3 = cellgeo.giveVertexCoordinates(3); + double x3 = p3.at(xind); + double y3 = p3.at(yind); + const auto &p4 = cellgeo.giveVertexCoordinates(4); + double x4 = p4.at(xind); + double y4 = p4.at(yind); + const auto &p5 = cellgeo.giveVertexCoordinates(5); + double x5 = p5.at(xind); + double y5 = p5.at(yind); + const auto &p6 = cellgeo.giveVertexCoordinates(6); + double x6 = p6.at(xind); + double y6 = p6.at(yind); return fabs( ( 4 * ( -( x4 * y1 ) + x6 * y1 + x4 * y2 - x5 * y2 + x5 * y3 - x6 * y3 ) + x2 * ( y1 - y3 - 4 * y4 + 4 * y5 ) + x1 * ( -y2 + y3 + 4 * y4 - 4 * y6 ) + x3 * ( -y1 + y2 - 4 * y5 + 4 * y6 ) ) / 6 ); @@ -315,7 +370,7 @@ FEI2dTrQuad :: giveArea(const FEICellGeometry &cellgeo) const bool FEI2dTrQuad :: inside(const FloatArray &lcoords) const { - const double point_tol = 1.0e-3; + const double point_tol = 1.0e-3; bool inside = true; for ( int i = 1; i <= 2; i++ ) { if ( lcoords.at(i) < - point_tol ) { @@ -335,35 +390,31 @@ bool FEI2dTrQuad :: inside(const FloatArray &lcoords) const } double -FEI2dTrQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) +FEI2dTrQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const { - IntArray eNodes; - const FloatArray *node; - double x1, x2, x3, y1, y2, y3; - - this->computeLocalEdgeMapping(eNodes, iEdge); + const auto &eNodes = this->computeLocalEdgeMapping(iEdge); - node = cellgeo.giveVertexCoordinates( eNodes.at(1) ); - x1 = node->at(xind); - y1 = node->at(yind); + const auto &node1 = cellgeo.giveVertexCoordinates( eNodes.at(1) ); + double x1 = node1.at(xind); + double y1 = node1.at(yind); - node = cellgeo.giveVertexCoordinates( eNodes.at(2) ); - x2 = node->at(xind); - y2 = node->at(yind); + const auto &node2 = cellgeo.giveVertexCoordinates( eNodes.at(2) ); + double x2 = node2.at(xind); + double y2 = node2.at(yind); - node = cellgeo.giveVertexCoordinates( eNodes.at(3) ); - x3 = node->at(xind); - y3 = node->at(yind); + const auto &node3 = cellgeo.giveVertexCoordinates( eNodes.at(3) ); + double x3 = node3.at(xind); + double y3 = node3.at(yind); return -( x1 * y2 - x2 * y1 + 4 * ( x3 * ( y1 - y2 ) + y3 * ( x2 - x1 ) ) ) / 3.0; } -IntegrationRule * -FEI2dTrQuad :: giveIntegrationRule(int order) +std::unique_ptr +FEI2dTrQuad :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, order + 2); iRule->SetUpPointsOnTriangle(points, _Unknown); - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei2dtrquad.h b/src/oofemlib/fei2dtrquad.h index fe9c7c8ae..6eb4775d5 100644 --- a/src/oofemlib/fei2dtrquad.h +++ b/src/oofemlib/fei2dtrquad.h @@ -46,38 +46,38 @@ class OOFEM_EXPORT FEI2dTrQuad : public FEInterpolation2d public: FEI2dTrQuad(int ind1, int ind2) : FEInterpolation2d(2, ind1, ind2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_2; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Line; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Triangle; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } - - + integrationDomain giveIntegrationDomain() const override { return _Triangle; } + Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_2; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Line; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Triangle; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveArea(const FEICellGeometry &cellgeo) const; - virtual int giveNumberOfNodes() const { return 6; } + static FloatArrayF<6> evalN(const FloatArrayF<2> &lcoords); + static FloatMatrixF<2,6> evaldNdxi(const FloatArrayF<2> &lcoords); + std::pair> evaldNdx(const FloatArrayF<2> &lcoords, const FEICellGeometry &cellgeo) const; + + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveArea(const FEICellGeometry &cellgeo) const override; + int giveNumberOfNodes() const override { return 6; } - virtual bool inside(const FloatArray &lcoords) const; + bool inside(const FloatArray &lcoords) const override; // Edge - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); - virtual int giveNumberOfEdges() const { return 3; } - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo); + IntArray computeLocalEdgeMapping(int iedge) const override; + int giveNumberOfEdges() const override { return 3; } + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeEvalNormal(FloatArray &normal, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const override; - virtual IntegrationRule *giveIntegrationRule(int order); + std::unique_ptr giveIntegrationRule(int order) const override; - virtual void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; protected: double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); diff --git a/src/oofemlib/fei3dhexalin.C b/src/oofemlib/fei3dhexalin.C index dd461d711..4030fe263 100644 --- a/src/oofemlib/fei3dhexalin.C +++ b/src/oofemlib/fei3dhexalin.C @@ -37,61 +37,189 @@ #include "floatmatrix.h" #include "floatarray.h" #include "gaussintegrationrule.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" namespace oofem { + +FloatArrayF<8> +FEI3dHexaLin :: evalN(const FloatArrayF<3> &lcoords) +{ + ///auto [x, y, z] = lcoords; // structured bindings C++17 would be nice. + double x = lcoords[0]; + double y = lcoords[1]; + double z = lcoords[2]; + + return { + 0.125 * ( 1. - x ) * ( 1. - y ) * ( 1. + z ), + 0.125 * ( 1. - x ) * ( 1. + y ) * ( 1. + z ), + 0.125 * ( 1. + x ) * ( 1. + y ) * ( 1. + z ), + 0.125 * ( 1. + x ) * ( 1. - y ) * ( 1. + z ), + 0.125 * ( 1. - x ) * ( 1. - y ) * ( 1. - z ), + 0.125 * ( 1. - x ) * ( 1. + y ) * ( 1. - z ), + 0.125 * ( 1. + x ) * ( 1. + y ) * ( 1. - z ), + 0.125 * ( 1. + x ) * ( 1. - y ) * ( 1. - z ) + }; +} + + void -FEI3dHexaLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ +#if 0 + answer = evalN(lcoords); +#else + double x = lcoords[0]; + double y = lcoords[1]; + double z = lcoords[2]; + + answer = { + 0.125 * ( 1. - x ) * ( 1. - y ) * ( 1. + z ), + 0.125 * ( 1. - x ) * ( 1. + y ) * ( 1. + z ), + 0.125 * ( 1. + x ) * ( 1. + y ) * ( 1. + z ), + 0.125 * ( 1. + x ) * ( 1. - y ) * ( 1. + z ), + 0.125 * ( 1. - x ) * ( 1. - y ) * ( 1. - z ), + 0.125 * ( 1. - x ) * ( 1. + y ) * ( 1. - z ), + 0.125 * ( 1. + x ) * ( 1. + y ) * ( 1. - z ), + 0.125 * ( 1. + x ) * ( 1. - y ) * ( 1. - z ) + }; +#endif +} + + +FloatMatrixF<3,8> +FEI3dHexaLin :: evaldNdxi(const FloatArrayF<3> &lcoords) { - double x, y, z; - answer.resize(8); - - x = lcoords.at(1); - y = lcoords.at(2); - z = lcoords.at(3); - - answer.at(1) = 0.125 * ( 1. - x ) * ( 1. - y ) * ( 1. + z ); - answer.at(2) = 0.125 * ( 1. - x ) * ( 1. + y ) * ( 1. + z ); - answer.at(3) = 0.125 * ( 1. + x ) * ( 1. + y ) * ( 1. + z ); - answer.at(4) = 0.125 * ( 1. + x ) * ( 1. - y ) * ( 1. + z ); - answer.at(5) = 0.125 * ( 1. - x ) * ( 1. - y ) * ( 1. - z ); - answer.at(6) = 0.125 * ( 1. - x ) * ( 1. + y ) * ( 1. - z ); - answer.at(7) = 0.125 * ( 1. + x ) * ( 1. + y ) * ( 1. - z ); - answer.at(8) = 0.125 * ( 1. + x ) * ( 1. - y ) * ( 1. - z ); + //auto [u, v, w] = lcoords; + double u = lcoords.at(1); + double v = lcoords.at(2); + double w = lcoords.at(3); + + return { + -0.125 * ( 1. - v ) * ( 1. + w ), + -0.125 * ( 1. - u ) * ( 1. + w ), + 0.125 * ( 1. - u ) * ( 1. - v ), + -0.125 * ( 1. + v ) * ( 1. + w ), + 0.125 * ( 1. - u ) * ( 1. + w ), + 0.125 * ( 1. - u ) * ( 1. + v ), + 0.125 * ( 1. + v ) * ( 1. + w ), + 0.125 * ( 1. + u ) * ( 1. + w ), + 0.125 * ( 1. + u ) * ( 1. + v ), + 0.125 * ( 1. - v ) * ( 1. + w ), + -0.125 * ( 1. + u ) * ( 1. + w ), + 0.125 * ( 1. + u ) * ( 1. - v ), + -0.125 * ( 1. - v ) * ( 1. - w ), + -0.125 * ( 1. - u ) * ( 1. - w ), + -0.125 * ( 1. - u ) * ( 1. - v ), + -0.125 * ( 1. + v ) * ( 1. - w ), + 0.125 * ( 1. - u ) * ( 1. - w ), + -0.125 * ( 1. - u ) * ( 1. + v ), + 0.125 * ( 1. + v ) * ( 1. - w ), + 0.125 * ( 1. + u ) * ( 1. - w ), + -0.125 * ( 1. + u ) * ( 1. + v ), + 0.125 * ( 1. - v ) * ( 1. - w ), + -0.125 * ( 1. + u ) * ( 1. - w ), + -0.125 * ( 1. + u ) * ( 1. - v ), + }; } +void +FEI3dHexaLin :: evaldNdxi(FloatMatrix &dN, const FloatArray &lcoords, const FEICellGeometry &) const +{ +#if 0 + dN = evaldNdxi(lcoords); +#else + double u, v, w; + u = lcoords.at(1); + v = lcoords.at(2); + w = lcoords.at(3); + + dN.resize(8, 3); + + dN.at(1, 1) = -0.125 * ( 1. - v ) * ( 1. + w ); + dN.at(2, 1) = -0.125 * ( 1. + v ) * ( 1. + w ); + dN.at(3, 1) = 0.125 * ( 1. + v ) * ( 1. + w ); + dN.at(4, 1) = 0.125 * ( 1. - v ) * ( 1. + w ); + dN.at(5, 1) = -0.125 * ( 1. - v ) * ( 1. - w ); + dN.at(6, 1) = -0.125 * ( 1. + v ) * ( 1. - w ); + dN.at(7, 1) = 0.125 * ( 1. + v ) * ( 1. - w ); + dN.at(8, 1) = 0.125 * ( 1. - v ) * ( 1. - w ); + + dN.at(1, 2) = -0.125 * ( 1. - u ) * ( 1. + w ); + dN.at(2, 2) = 0.125 * ( 1. - u ) * ( 1. + w ); + dN.at(3, 2) = 0.125 * ( 1. + u ) * ( 1. + w ); + dN.at(4, 2) = -0.125 * ( 1. + u ) * ( 1. + w ); + dN.at(5, 2) = -0.125 * ( 1. - u ) * ( 1. - w ); + dN.at(6, 2) = 0.125 * ( 1. - u ) * ( 1. - w ); + dN.at(7, 2) = 0.125 * ( 1. + u ) * ( 1. - w ); + dN.at(8, 2) = -0.125 * ( 1. + u ) * ( 1. - w ); + + dN.at(1, 3) = 0.125 * ( 1. - u ) * ( 1. - v ); + dN.at(2, 3) = 0.125 * ( 1. - u ) * ( 1. + v ); + dN.at(3, 3) = 0.125 * ( 1. + u ) * ( 1. + v ); + dN.at(4, 3) = 0.125 * ( 1. + u ) * ( 1. - v ); + dN.at(5, 3) = -0.125 * ( 1. - u ) * ( 1. - v ); + dN.at(6, 3) = -0.125 * ( 1. - u ) * ( 1. + v ); + dN.at(7, 3) = -0.125 * ( 1. + u ) * ( 1. + v ); + dN.at(8, 3) = -0.125 * ( 1. + u ) * ( 1. - v ); +#endif +} + + +std::pair> +FEI3dHexaLin :: evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo) +{ + auto dNduvw = evaldNdxi(lcoords); + FloatMatrixF<3,8> coords; + for ( int i = 0; i < 8; i++ ) { + ///@todo cellgeo should give a FloatArrayF<3>, this will add a "costly" construction now: + coords.setColumn(cellgeo.giveVertexCoordinates(i+1), i); + } + auto jacT = dotT(dNduvw, coords); + return {det(jacT), dot(inv(jacT), dNduvw)}; +} + + double -FEI3dHexaLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + auto tmp = evaldNdx(lcoords, cellgeo); + //auto [det, dndx] = evaldNdx(lcoords, cellgeo); + answer = tmp.second; + return tmp.first; +#else FloatMatrix jacobianMatrix, inv, dNduvw, coords; - this->giveLocalDerivative(dNduvw, lcoords); + this->evaldNdxi(dNduvw, lcoords, cellgeo); coords.resize(3, 8); for ( int i = 1; i <= 8; i++ ) { - coords.setColumn(* cellgeo.giveVertexCoordinates(i), i); + coords.setColumn(cellgeo.giveVertexCoordinates(i), i); } jacobianMatrix.beProductOf(coords, dNduvw); inv.beInverseOf(jacobianMatrix); answer.beProductOf(dNduvw, inv); return jacobianMatrix.giveDeterminant(); +#endif } void -FEI3dHexaLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; this->evalN(n, lcoords, cellgeo); answer.clear(); for ( int i = 1; i <= 8; i++ ) { - answer.add( n.at(i), * cellgeo.giveVertexCoordinates(i) ); + answer.add( n.at(i), cellgeo.giveVertexCoordinates(i) ); } } #define POINT_TOL 1.e-3 int -FEI3dHexaLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) const { double x1, x2, x3, x4, x5, x6, x7, x8, a1, a2, a3, a4, a5, a6, a7, a8; double y1, y2, y3, y4, y5, y6, y7, y8, b1, b2, b3, b4, b5, b6, b7, b8; @@ -101,32 +229,32 @@ FEI3dHexaLin :: global2local(FloatArray &answer, const FloatArray &coords, const FloatArray r(3), delta; int nite = 0; - x1 = cellgeo.giveVertexCoordinates(1)->at(1); - x2 = cellgeo.giveVertexCoordinates(2)->at(1); - x3 = cellgeo.giveVertexCoordinates(3)->at(1); - x4 = cellgeo.giveVertexCoordinates(4)->at(1); - x5 = cellgeo.giveVertexCoordinates(5)->at(1); - x6 = cellgeo.giveVertexCoordinates(6)->at(1); - x7 = cellgeo.giveVertexCoordinates(7)->at(1); - x8 = cellgeo.giveVertexCoordinates(8)->at(1); - - y1 = cellgeo.giveVertexCoordinates(1)->at(2); - y2 = cellgeo.giveVertexCoordinates(2)->at(2); - y3 = cellgeo.giveVertexCoordinates(3)->at(2); - y4 = cellgeo.giveVertexCoordinates(4)->at(2); - y5 = cellgeo.giveVertexCoordinates(5)->at(2); - y6 = cellgeo.giveVertexCoordinates(6)->at(2); - y7 = cellgeo.giveVertexCoordinates(7)->at(2); - y8 = cellgeo.giveVertexCoordinates(8)->at(2); - - z1 = cellgeo.giveVertexCoordinates(1)->at(3); - z2 = cellgeo.giveVertexCoordinates(2)->at(3); - z3 = cellgeo.giveVertexCoordinates(3)->at(3); - z4 = cellgeo.giveVertexCoordinates(4)->at(3); - z5 = cellgeo.giveVertexCoordinates(5)->at(3); - z6 = cellgeo.giveVertexCoordinates(6)->at(3); - z7 = cellgeo.giveVertexCoordinates(7)->at(3); - z8 = cellgeo.giveVertexCoordinates(8)->at(3); + x1 = cellgeo.giveVertexCoordinates(1).at(1); + x2 = cellgeo.giveVertexCoordinates(2).at(1); + x3 = cellgeo.giveVertexCoordinates(3).at(1); + x4 = cellgeo.giveVertexCoordinates(4).at(1); + x5 = cellgeo.giveVertexCoordinates(5).at(1); + x6 = cellgeo.giveVertexCoordinates(6).at(1); + x7 = cellgeo.giveVertexCoordinates(7).at(1); + x8 = cellgeo.giveVertexCoordinates(8).at(1); + + y1 = cellgeo.giveVertexCoordinates(1).at(2); + y2 = cellgeo.giveVertexCoordinates(2).at(2); + y3 = cellgeo.giveVertexCoordinates(3).at(2); + y4 = cellgeo.giveVertexCoordinates(4).at(2); + y5 = cellgeo.giveVertexCoordinates(5).at(2); + y6 = cellgeo.giveVertexCoordinates(6).at(2); + y7 = cellgeo.giveVertexCoordinates(7).at(2); + y8 = cellgeo.giveVertexCoordinates(8).at(2); + + z1 = cellgeo.giveVertexCoordinates(1).at(3); + z2 = cellgeo.giveVertexCoordinates(2).at(3); + z3 = cellgeo.giveVertexCoordinates(3).at(3); + z4 = cellgeo.giveVertexCoordinates(4).at(3); + z5 = cellgeo.giveVertexCoordinates(5).at(3); + z6 = cellgeo.giveVertexCoordinates(6).at(3); + z7 = cellgeo.giveVertexCoordinates(7).at(3); + z8 = cellgeo.giveVertexCoordinates(8).at(3); xp = coords.at(1); yp = coords.at(2); @@ -219,7 +347,7 @@ FEI3dHexaLin :: global2local(FloatArray &answer, const FloatArray &coords, const } void -FEI3dHexaLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); answer.resize(2); @@ -230,12 +358,10 @@ FEI3dHexaLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoor void FEI3dHexaLin :: edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double l; - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); - l = this->edgeComputeLength(edgeNodes, cellgeo); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); + double l = this->edgeComputeLength(edgeNodes, cellgeo); answer.resize(2, 1); answer.at(1, 1) = -1.0 / l; @@ -244,7 +370,7 @@ FEI3dHexaLin :: edgeEvaldNdx(FloatMatrix &answer, int iedge, void -FEI3dHexaLin :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(2); answer(0) = -0.5; @@ -254,95 +380,76 @@ FEI3dHexaLin :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &l void FEI3dHexaLin :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; FloatArray n; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); this->edgeEvalN(n, iedge, lcoords, cellgeo); answer.resize(3); - answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(1) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(1) ); - answer.at(2) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(2) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(2) ); - answer.at(3) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(3) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(3) ); + answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(1) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(1); + answer.at(2) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(2) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(2); + answer.at(3) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(3) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(3); } double -FEI3dHexaLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); return 0.5 * this->edgeComputeLength(edgeNodes, cellgeo); } -void -FEI3dHexaLin :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI3dHexaLin :: computeLocalEdgeMapping(int iedge) const { - int aNode = 0, bNode = 0; - if ( iedge == 1 ) { // edge between nodes 1 2 - aNode = 1; - bNode = 2; + return {1, 2}; } else if ( iedge == 2 ) { // edge between nodes 2 3 - aNode = 2; - bNode = 3; + return {2, 3}; } else if ( iedge == 3 ) { // edge between nodes 3 4 - aNode = 3; - bNode = 4; + return {3, 4}; } else if ( iedge == 4 ) { // edge between nodes 4 1 - aNode = 4; - bNode = 1; + return {4, 1}; } else if ( iedge == 5 ) { // edge between nodes 1 5 - aNode = 1; - bNode = 5; + return {1, 5}; } else if ( iedge == 6 ) { // edge between nodes 2 6 - aNode = 2; - bNode = 6; + return {2, 6}; } else if ( iedge == 7 ) { // edge between nodes 3 7 - aNode = 3; - bNode = 7; + return {3, 7}; } else if ( iedge == 8 ) { // edge between nodes 4 8 - aNode = 4; - bNode = 8; + return {4, 8}; } else if ( iedge == 9 ) { // edge between nodes 5 6 - aNode = 5; - bNode = 6; + return {5, 6}; } else if ( iedge == 10 ) { // edge between nodes 6 7 - aNode = 6; - bNode = 7; + return {6, 7}; } else if ( iedge == 11 ) { // edge between nodes 7 8 - aNode = 7; - bNode = 8; + return {7, 8}; } else if ( iedge == 12 ) { // edge between nodes 8 5 - aNode = 8; - bNode = 5; + return {8, 5}; } else { - OOFEM_ERROR("wrong egde number (%d)", iedge); + throw std::range_error("invalid edge number"); + return {}; } - - edgeNodes = {aNode, bNode}; } double -FEI3dHexaLin :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const { - return cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->distance( cellgeo.giveVertexCoordinates( edgeNodes.at(1) ) ); + return distance(cellgeo.giveVertexCoordinates( edgeNodes.at(2) ), cellgeo.giveVertexCoordinates( edgeNodes.at(1) )); } void -FEI3dHexaLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double ksi, eta; - answer.resize(4); - - ksi = lcoords.at(1); - eta = lcoords.at(2); + double ksi = lcoords.at(1); + double eta = lcoords.at(2); + answer.resize(4); answer.at(1) = ( 1. + ksi ) * ( 1. + eta ) * 0.25; answer.at(2) = ( 1. - ksi ) * ( 1. + eta ) * 0.25; answer.at(3) = ( 1. - ksi ) * ( 1. - eta ) * 0.25; @@ -350,11 +457,10 @@ FEI3dHexaLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lc } void -FEI3dHexaLin :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // Note, this must be in correct order, not just the correct nodes, therefore we must use snodes; - IntArray snodes; - this->computeLocalSurfaceMapping(snodes, isurf); + const auto &snodes = this->computeLocalSurfaceMapping(isurf); FloatArray lcoords_hex; @@ -406,34 +512,30 @@ FEI3dHexaLin :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray void FEI3dHexaLin :: surfaceLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray nodes; FloatArray n; - this->computeLocalSurfaceMapping(nodes, iedge); + const auto &nodes = this->computeLocalSurfaceMapping(iedge); this->surfaceEvalN(n, iedge, lcoords, cellgeo); answer.resize(3); - answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates( nodes.at(1) )->at(1) + n.at(2) * cellgeo.giveVertexCoordinates( nodes.at(2) )->at(1) + - n.at(3) * cellgeo.giveVertexCoordinates( nodes.at(3) )->at(1) + n.at(4) * cellgeo.giveVertexCoordinates( nodes.at(4) )->at(1); - answer.at(2) = n.at(1) * cellgeo.giveVertexCoordinates( nodes.at(1) )->at(2) + n.at(2) * cellgeo.giveVertexCoordinates( nodes.at(2) )->at(2) + - n.at(3) * cellgeo.giveVertexCoordinates( nodes.at(3) )->at(2) + n.at(4) * cellgeo.giveVertexCoordinates( nodes.at(4) )->at(2); - answer.at(3) = n.at(1) * cellgeo.giveVertexCoordinates( nodes.at(1) )->at(3) + n.at(2) * cellgeo.giveVertexCoordinates( nodes.at(2) )->at(3) + - n.at(3) * cellgeo.giveVertexCoordinates( nodes.at(3) )->at(3) + n.at(4) * cellgeo.giveVertexCoordinates( nodes.at(4) )->at(3); + answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates( nodes.at(1) ).at(1) + n.at(2) * cellgeo.giveVertexCoordinates( nodes.at(2) ).at(1) + + n.at(3) * cellgeo.giveVertexCoordinates( nodes.at(3) ).at(1) + n.at(4) * cellgeo.giveVertexCoordinates( nodes.at(4) ).at(1); + answer.at(2) = n.at(1) * cellgeo.giveVertexCoordinates( nodes.at(1) ).at(2) + n.at(2) * cellgeo.giveVertexCoordinates( nodes.at(2) ).at(2) + + n.at(3) * cellgeo.giveVertexCoordinates( nodes.at(3) ).at(2) + n.at(4) * cellgeo.giveVertexCoordinates( nodes.at(4) ).at(2); + answer.at(3) = n.at(1) * cellgeo.giveVertexCoordinates( nodes.at(1) ).at(3) + n.at(2) * cellgeo.giveVertexCoordinates( nodes.at(2) ).at(3) + + n.at(3) * cellgeo.giveVertexCoordinates( nodes.at(3) ).at(3) + n.at(4) * cellgeo.giveVertexCoordinates( nodes.at(4) ).at(3); } double -FEI3dHexaLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray a, b, dNdksi(4), dNdeta(4); - double ksi, eta; - IntArray snodes; - - this->computeLocalSurfaceMapping(snodes, isurf); + const auto &snodes = this->computeLocalSurfaceMapping(isurf); - ksi = lcoords.at(1); - eta = lcoords.at(2); + double ksi = lcoords.at(1); + double eta = lcoords.at(2); // No need to divide by 1/4, we'll normalize anyway; dNdksi.at(1) = ( 1. + eta ); @@ -447,8 +549,8 @@ FEI3dHexaLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArra dNdeta.at(4) = -( 1. + ksi ); for ( int i = 1; i <= 4; ++i ) { - a.add( dNdksi.at(i), * cellgeo.giveVertexCoordinates( snodes.at(i) ) ); - b.add( dNdeta.at(i), * cellgeo.giveVertexCoordinates( snodes.at(i) ) ); + a.add( dNdksi.at(i), cellgeo.giveVertexCoordinates( snodes.at(i) ) ); + b.add( dNdeta.at(i), cellgeo.giveVertexCoordinates( snodes.at(i) ) ); } answer.beVectorProductOf(a, b); @@ -457,116 +559,78 @@ FEI3dHexaLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArra double FEI3dHexaLin :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + const FEICellGeometry &cellgeo) const { FloatArray normal; return this->surfaceEvalNormal(normal, isurf, lcoords, cellgeo); } -void -FEI3dHexaLin :: computeLocalSurfaceMapping(IntArray &surfNodes, int isurf) +IntArray +FEI3dHexaLin :: computeLocalSurfaceMapping(int isurf) const { if ( isurf == 1 ) { // surface 1 - nodes 1 4 3 2 - surfNodes = {1, 4, 3, 2}; + return {1, 4, 3, 2}; } else if ( isurf == 2 ) { // surface 2 - nodes 5 6 7 8 - surfNodes = {5, 6, 7, 8}; + return {5, 6, 7, 8}; } else if ( isurf == 3 ) { // surface 3 - nodes 1 2 6 5 - surfNodes = {1, 2, 6, 5}; + return {1, 2, 6, 5}; } else if ( isurf == 4 ) { // surface 4 - nodes 2 3 7 6 - surfNodes = {2, 3, 7, 6}; + return {2, 3, 7, 6}; } else if ( isurf == 5 ) { // surface 5 - nodes 3 4 8 7 - surfNodes = {3, 4, 8, 7}; + return {3, 4, 8, 7}; } else if ( isurf == 6 ) { // surface 6 - nodes 4 1 5 8 - surfNodes = {4, 1, 5, 8}; + return {4, 1, 5, 8}; } else { - OOFEM_ERROR("wrong surface number (%d)", isurf); + throw std::runtime_error("invalid surface number"); } } void -FEI3dHexaLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const // Returns the jacobian matrix J (x,y,z)/(ksi,eta,dzeta) of the receiver. { FloatMatrix dNduvw, coords; - this->giveLocalDerivative(dNduvw, lcoords); + this->evaldNdxi(dNduvw, lcoords, cellgeo); coords.resize(3, 8); for ( int i = 1; i <= 8; i++ ) { - coords.setColumn(* cellgeo.giveVertexCoordinates(i), i); + coords.setColumn(cellgeo.giveVertexCoordinates(i), i); } jacobianMatrix.beProductOf(coords, dNduvw); } -void -FEI3dHexaLin :: giveLocalDerivative(FloatMatrix &dN, const FloatArray &lcoords) -{ - double u, v, w; - u = lcoords.at(1); - v = lcoords.at(2); - w = lcoords.at(3); - - dN.resize(8, 3); - - dN.at(1, 1) = -0.125 * ( 1. - v ) * ( 1. + w ); - dN.at(2, 1) = -0.125 * ( 1. + v ) * ( 1. + w ); - dN.at(3, 1) = 0.125 * ( 1. + v ) * ( 1. + w ); - dN.at(4, 1) = 0.125 * ( 1. - v ) * ( 1. + w ); - dN.at(5, 1) = -0.125 * ( 1. - v ) * ( 1. - w ); - dN.at(6, 1) = -0.125 * ( 1. + v ) * ( 1. - w ); - dN.at(7, 1) = 0.125 * ( 1. + v ) * ( 1. - w ); - dN.at(8, 1) = 0.125 * ( 1. - v ) * ( 1. - w ); - - dN.at(1, 2) = -0.125 * ( 1. - u ) * ( 1. + w ); - dN.at(2, 2) = 0.125 * ( 1. - u ) * ( 1. + w ); - dN.at(3, 2) = 0.125 * ( 1. + u ) * ( 1. + w ); - dN.at(4, 2) = -0.125 * ( 1. + u ) * ( 1. + w ); - dN.at(5, 2) = -0.125 * ( 1. - u ) * ( 1. - w ); - dN.at(6, 2) = 0.125 * ( 1. - u ) * ( 1. - w ); - dN.at(7, 2) = 0.125 * ( 1. + u ) * ( 1. - w ); - dN.at(8, 2) = -0.125 * ( 1. + u ) * ( 1. - w ); - - dN.at(1, 3) = 0.125 * ( 1. - u ) * ( 1. - v ); - dN.at(2, 3) = 0.125 * ( 1. - u ) * ( 1. + v ); - dN.at(3, 3) = 0.125 * ( 1. + u ) * ( 1. + v ); - dN.at(4, 3) = 0.125 * ( 1. + u ) * ( 1. - v ); - dN.at(5, 3) = -0.125 * ( 1. - u ) * ( 1. - v ); - dN.at(6, 3) = -0.125 * ( 1. - u ) * ( 1. + v ); - dN.at(7, 3) = -0.125 * ( 1. + u ) * ( 1. + v ); - dN.at(8, 3) = -0.125 * ( 1. + u ) * ( 1. - v ); -} double -FEI3dHexaLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) +FEI3dHexaLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const { - IntArray fNodes; - this->computeLocalSurfaceMapping(fNodes, iEdge); + const auto &fNodes = this->computeLocalSurfaceMapping(iEdge); - const FloatArray &c1 = * cellgeo.giveVertexCoordinates( fNodes.at(1) ); - const FloatArray &c2 = * cellgeo.giveVertexCoordinates( fNodes.at(2) ); - const FloatArray &c3 = * cellgeo.giveVertexCoordinates( fNodes.at(3) ); - const FloatArray &c4 = * cellgeo.giveVertexCoordinates( fNodes.at(4) ); + const auto &c1 = cellgeo.giveVertexCoordinates( fNodes.at(1) ); + const auto &c2 = cellgeo.giveVertexCoordinates( fNodes.at(2) ); + const auto &c3 = cellgeo.giveVertexCoordinates( fNodes.at(3) ); + const auto &c4 = cellgeo.giveVertexCoordinates( fNodes.at(4) ); return ( - c4(2) * ( c1(1) * ( -c2(0) - c3(0) ) + c2(1) * ( c1(0) - c3(0) ) + c3(1) * ( c1(0) + c2(0) ) ) + - c3(2) * ( c1(1) * ( -c2(0) + c4(0) ) + c2(1) * ( c1(0) + c4(0) ) + c4(1) * ( -c1(0) - c2(0) ) ) + - c2(2) * ( c1(1) * ( c3(0) + c4(0) ) + c3(1) * ( -c1(0) - c4(0) ) + c4(1) * ( -c1(0) + c3(0) ) ) + - c1(2) * ( c2(1) * ( -c3(0) - c4(0) ) + c3(1) * ( c2(0) - c4(0) ) + c4(1) * ( c2(0) + c3(0) ) ) ) * 0.25; + c4(2) * ( c1(1) * ( -c2(0) - c3(0) ) + c2(1) * ( c1(0) - c3(0) ) + c3(1) * ( c1(0) + c2(0) ) ) + + c3(2) * ( c1(1) * ( -c2(0) + c4(0) ) + c2(1) * ( c1(0) + c4(0) ) + c4(1) * ( -c1(0) - c2(0) ) ) + + c2(2) * ( c1(1) * ( c3(0) + c4(0) ) + c3(1) * ( -c1(0) - c4(0) ) + c4(1) * ( -c1(0) + c3(0) ) ) + + c1(2) * ( c2(1) * ( -c3(0) - c4(0) ) + c3(1) * ( c2(0) - c4(0) ) + c4(1) * ( c2(0) + c3(0) ) ) ) * 0.25; } -IntegrationRule * -FEI3dHexaLin :: giveIntegrationRule(int order) +std::unique_ptr +FEI3dHexaLin :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Cube, order + 6); iRule->SetUpPointsOnCube(points, _Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule * -FEI3dHexaLin :: giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr +FEI3dHexaLin :: giveBoundaryIntegrationRule(int order, int boundary) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order + 2); iRule->SetUpPointsOnSquare(points, _Unknown); - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei3dhexalin.h b/src/oofemlib/fei3dhexalin.h index 3faf875af..f632d349b 100644 --- a/src/oofemlib/fei3dhexalin.h +++ b/src/oofemlib/fei3dhexalin.h @@ -38,6 +38,7 @@ #include "feinterpol3d.h" namespace oofem { + /** * Class representing implementation of linear hexahedra interpolation class. */ @@ -46,47 +47,50 @@ class OOFEM_EXPORT FEI3dHexaLin : public FEInterpolation3d public: FEI3dHexaLin() : FEInterpolation3d(1) { } - virtual integrationDomain giveIntegrationDomain() const { return _Cube; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_hexa_1; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Square; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Square; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Cube; } + Element_Geometry_Type giveGeometryType() const override { return EGT_hexa_1; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Square; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Square; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int giveNumberOfNodes() const { return 8; } - + static FloatArrayF<8> evalN(const FloatArrayF<3> &lcoords); + static std::pair> evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo); + static FloatMatrixF<3,8> evaldNdxi(const FloatArrayF<3> &lcoords); + + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &dN, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int giveNumberOfNodes() const override { return 8; } + void giveCellDofMans(IntArray& nodes, Element* elem) const override {nodes={1,2,3,4,5,6,7,8};} + + // Edge - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalEdgeMapping(int iedge) const override; // Surface - virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void computeLocalSurfaceMapping(IntArray &edgeNodes, int iedge); + void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalSurfaceMapping(int iedge) const override; - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo); + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const override; - virtual IntegrationRule *giveIntegrationRule(int order); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary); + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); - void giveLocalDerivative(FloatMatrix &dN, const FloatArray &lcoords); + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; }; } // end namespace oofem #endif // fei3dhexalin_h diff --git a/src/oofemlib/fei3dhexaquad.C b/src/oofemlib/fei3dhexaquad.C index bdde7fb0d..af84f8814 100644 --- a/src/oofemlib/fei3dhexaquad.C +++ b/src/oofemlib/fei3dhexaquad.C @@ -36,12 +36,50 @@ #include "intarray.h" #include "floatarray.h" #include "floatmatrix.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "gaussintegrationrule.h" namespace oofem { + +FloatArrayF<20> +FEI3dHexaQuad :: evalN(const FloatArrayF<3> &lcoords) +{ + //auto [u, v, w] = lcoords; + double u = lcoords[0]; + double v = lcoords[1]; + double w = lcoords[2]; + return { + 0.125 * ( 1.0 - u ) * ( 1.0 - v ) * ( 1.0 + w ) * ( -u - v + w - 2.0 ), + 0.125 * ( 1.0 - u ) * ( 1.0 + v ) * ( 1.0 + w ) * ( -u + v + w - 2.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 + v ) * ( 1.0 + w ) * ( u + v + w - 2.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 - v ) * ( 1.0 + w ) * ( u - v + w - 2.0 ), + 0.125 * ( 1.0 - u ) * ( 1.0 - v ) * ( 1.0 - w ) * ( -u - v - w - 2.0 ), + 0.125 * ( 1.0 - u ) * ( 1.0 + v ) * ( 1.0 - w ) * ( -u + v - w - 2.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 + v ) * ( 1.0 - w ) * ( u + v - w - 2.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 - v ) * ( 1.0 - w ) * ( u - v - w - 2.0 ), + 0.25 * ( 1.0 - v * v ) * ( 1.0 - u ) * ( 1.0 + w ), + 0.25 * ( 1.0 - u * u ) * ( 1.0 + v ) * ( 1.0 + w ), + 0.25 * ( 1.0 - v * v ) * ( 1.0 + u ) * ( 1.0 + w ), + 0.25 * ( 1.0 - u * u ) * ( 1.0 - v ) * ( 1.0 + w ), + 0.25 * ( 1.0 - v * v ) * ( 1.0 - u ) * ( 1.0 - w ), + 0.25 * ( 1.0 - u * u ) * ( 1.0 + v ) * ( 1.0 - w ), + 0.25 * ( 1.0 - v * v ) * ( 1.0 + u ) * ( 1.0 - w ), + 0.25 * ( 1.0 - u * u ) * ( 1.0 - v ) * ( 1.0 - w ), + 0.25 * ( 1.0 - u ) * ( 1.0 - v ) * ( 1.0 - w * w ), + 0.25 * ( 1.0 - u ) * ( 1.0 + v ) * ( 1.0 - w * w ), + 0.25 * ( 1.0 + u ) * ( 1.0 + v ) * ( 1.0 - w * w ), + 0.25 * ( 1.0 + u ) * ( 1.0 - v ) * ( 1.0 - w * w ) + }; +} + + void -FEI3dHexaQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + answer = evalN(lcoords); +#else double u, v, w; answer.resize(20); @@ -72,49 +110,223 @@ FEI3dHexaQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEIC answer.at(18) = 0.25 * ( 1.0 - u ) * ( 1.0 + v ) * ( 1.0 - w * w ); answer.at(19) = 0.25 * ( 1.0 + u ) * ( 1.0 + v ) * ( 1.0 - w * w ); answer.at(20) = 0.25 * ( 1.0 + u ) * ( 1.0 - v ) * ( 1.0 - w * w ); +#endif +} + + +FloatMatrixF<3,20> +FEI3dHexaQuad :: evaldNdxi(const FloatArrayF<3> &lcoords) +{ + //auto [u, v, w] = lcoords; + double u = lcoords[0]; + double v = lcoords[1]; + double w = lcoords[2]; + + return { + 0.125 * ( 1.0 - v ) * ( 1.0 + w ) * ( 2.0 * u + v - w + 1.0 ), + 0.125 * ( 1.0 - u ) * ( 1.0 + w ) * ( 2.0 * v + u - w + 1.0 ), + 0.125 * ( 1.0 - u ) * ( 1.0 - v ) * ( 2.0 * w - u - v - 1.0 ), + 0.125 * ( 1.0 + v ) * ( 1.0 + w ) * ( 2.0 * u - v - w + 1.0 ), + 0.125 * ( 1.0 - u ) * ( 1.0 + w ) * ( 2.0 * v - u + w - 1.0 ), + 0.125 * ( 1.0 - u ) * ( 1.0 + v ) * ( 2.0 * w - u + v - 1.0 ), + 0.125 * ( 1.0 + v ) * ( 1.0 + w ) * ( 2.0 * u + v + w - 1.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 + w ) * ( 2.0 * v + u + w - 1.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 + v ) * ( 2.0 * w + u + v - 1.0 ), + 0.125 * ( 1.0 - v ) * ( 1.0 + w ) * ( 2.0 * u - v + w - 1.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 + w ) * ( 2.0 * v - u - w + 1.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 - v ) * ( 2.0 * w + u - v - 1.0 ), + 0.125 * ( 1.0 - v ) * ( 1.0 - w ) * ( 2.0 * u + v + w + 1.0 ), + 0.125 * ( 1.0 - u ) * ( 1.0 - w ) * ( 2.0 * v + u + w + 1.0 ), + 0.125 * ( 1.0 - u ) * ( 1.0 - v ) * ( 2.0 * w + u + v + 1.0 ), + 0.125 * ( 1.0 + v ) * ( 1.0 - w ) * ( 2.0 * u - v + w + 1.0 ), + 0.125 * ( 1.0 - u ) * ( 1.0 - w ) * ( 2.0 * v - u - w - 1.0 ), + 0.125 * ( 1.0 - u ) * ( 1.0 + v ) * ( 2.0 * w + u - v + 1.0 ), + 0.125 * ( 1.0 + v ) * ( 1.0 - w ) * ( 2.0 * u + v - w - 1.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 - w ) * ( 2.0 * v + u - w - 1.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 + v ) * ( 2.0 * w - u - v + 1.0 ), + 0.125 * ( 1.0 - v ) * ( 1.0 - w ) * ( 2.0 * u - v - w - 1.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 - w ) * ( 2.0 * v - u + w + 1.0 ), + 0.125 * ( 1.0 + u ) * ( 1.0 - v ) * ( 2.0 * w - u + v + 1.0 ), + -0.25 * ( 1.0 - v * v ) * ( 1.0 + w ), + -0.50 * v * ( 1.0 - u ) * ( 1.0 + w ), + 0.25 * ( 1.0 - v * v ) * ( 1.0 - u ), + -0.50 * u * ( 1.0 + v ) * ( 1.0 + w ), + 0.25 * ( 1.0 - u * u ) * ( 1.0 + w ), + 0.25 * ( 1.0 - u * u ) * ( 1.0 + v ), + -0.50 * v * ( 1.0 + u ) * ( 1.0 + w ), + 0.25 * ( 1.0 - v * v ) * ( 1.0 + w ), + 0.25 * ( 1.0 - v * v ) * ( 1.0 + u ), + -0.50 * u * ( 1.0 - v ) * ( 1.0 + w ), + -0.25 * ( 1.0 - u * u ) * ( 1.0 + w ), + 0.25 * ( 1.0 - u * u ) * ( 1.0 - v ), + -0.25 * ( 1.0 - v * v ) * ( 1.0 - w ), + -0.50 * v * ( 1.0 - u ) * ( 1.0 - w ), + -0.25 * ( 1.0 - v * v ) * ( 1.0 - u ), + -0.50 * u * ( 1.0 + v ) * ( 1.0 - w ), + 0.25 * ( 1.0 - u * u ) * ( 1.0 - w ), + -0.25 * ( 1.0 - u * u ) * ( 1.0 + v ), + 0.25 * ( 1.0 - v * v ) * ( 1.0 - w ), + -0.50 * v * ( 1.0 + u ) * ( 1.0 - w ), + -0.25 * ( 1.0 - v * v ) * ( 1.0 + u ), + -0.50 * u * ( 1.0 - v ) * ( 1.0 - w ), + -0.25 * ( 1.0 - u * u ) * ( 1.0 - w ), + -0.25 * ( 1.0 - u * u ) * ( 1.0 - v ), + -0.25 * ( 1.0 - v ) * ( 1.0 - w * w ), + -0.25 * ( 1.0 - u ) * ( 1.0 - w * w ), + -0.50 * ( 1.0 - u ) * ( 1.0 - v ) * w, + -0.25 * ( 1.0 + v ) * ( 1.0 - w * w ), + 0.25 * ( 1.0 - u ) * ( 1.0 - w * w ), + -0.50 * ( 1.0 - u ) * ( 1.0 + v ) * w, + 0.25 * ( 1.0 + v ) * ( 1.0 - w * w ), + 0.25 * ( 1.0 + u ) * ( 1.0 - w * w ), + -0.50 * ( 1.0 + u ) * ( 1.0 + v ) * w, + 0.25 * ( 1.0 - v ) * ( 1.0 - w * w ), + -0.25 * ( 1.0 + u ) * ( 1.0 - w * w ), + -0.50 * ( 1.0 + u ) * ( 1.0 - v ) * w, + }; +} + + +void +FEI3dHexaQuad :: evaldNdxi(FloatMatrix &dN, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ +#if 0 + dN = evaldNdxi(lcoords); +#else + double u, v, w; + u = lcoords.at(1); + v = lcoords.at(2); + w = lcoords.at(3); + + dN.resize(20, 3); + + dN.at(1, 1) = 0.125 * ( 1.0 - v ) * ( 1.0 + w ) * ( 2.0 * u + v - w + 1.0 ); + dN.at(2, 1) = 0.125 * ( 1.0 + v ) * ( 1.0 + w ) * ( 2.0 * u - v - w + 1.0 ); + dN.at(3, 1) = 0.125 * ( 1.0 + v ) * ( 1.0 + w ) * ( 2.0 * u + v + w - 1.0 ); + dN.at(4, 1) = 0.125 * ( 1.0 - v ) * ( 1.0 + w ) * ( 2.0 * u - v + w - 1.0 ); + dN.at(5, 1) = 0.125 * ( 1.0 - v ) * ( 1.0 - w ) * ( 2.0 * u + v + w + 1.0 ); + dN.at(6, 1) = 0.125 * ( 1.0 + v ) * ( 1.0 - w ) * ( 2.0 * u - v + w + 1.0 ); + dN.at(7, 1) = 0.125 * ( 1.0 + v ) * ( 1.0 - w ) * ( 2.0 * u + v - w - 1.0 ); + dN.at(8, 1) = 0.125 * ( 1.0 - v ) * ( 1.0 - w ) * ( 2.0 * u - v - w - 1.0 ); + dN.at(9, 1) = -0.25 * ( 1.0 - v * v ) * ( 1.0 + w ); + dN.at(10, 1) = -0.5 * u * ( 1.0 + v ) * ( 1.0 + w ); + dN.at(11, 1) = 0.25 * ( 1.0 - v * v ) * ( 1.0 + w ); + dN.at(12, 1) = -0.5 * u * ( 1.0 - v ) * ( 1.0 + w ); + dN.at(13, 1) = -0.25 * ( 1.0 - v * v ) * ( 1.0 - w ); + dN.at(14, 1) = -0.5 * u * ( 1.0 + v ) * ( 1.0 - w ); + dN.at(15, 1) = 0.25 * ( 1.0 - v * v ) * ( 1.0 - w ); + dN.at(16, 1) = -0.5 * u * ( 1.0 - v ) * ( 1.0 - w ); + dN.at(17, 1) = -0.25 * ( 1.0 - v ) * ( 1.0 - w * w ); + dN.at(18, 1) = -0.25 * ( 1.0 + v ) * ( 1.0 - w * w ); + dN.at(19, 1) = 0.25 * ( 1.0 + v ) * ( 1.0 - w * w ); + dN.at(20, 1) = 0.25 * ( 1.0 - v ) * ( 1.0 - w * w ); + + dN.at(1, 2) = 0.125 * ( 1.0 - u ) * ( 1.0 + w ) * ( 2.0 * v + u - w + 1.0 ); + dN.at(2, 2) = 0.125 * ( 1.0 - u ) * ( 1.0 + w ) * ( 2.0 * v - u + w - 1.0 ); + dN.at(3, 2) = 0.125 * ( 1.0 + u ) * ( 1.0 + w ) * ( 2.0 * v + u + w - 1.0 ); + dN.at(4, 2) = 0.125 * ( 1.0 + u ) * ( 1.0 + w ) * ( 2.0 * v - u - w + 1.0 ); + dN.at(5, 2) = 0.125 * ( 1.0 - u ) * ( 1.0 - w ) * ( 2.0 * v + u + w + 1.0 ); + dN.at(6, 2) = 0.125 * ( 1.0 - u ) * ( 1.0 - w ) * ( 2.0 * v - u - w - 1.0 ); + dN.at(7, 2) = 0.125 * ( 1.0 + u ) * ( 1.0 - w ) * ( 2.0 * v + u - w - 1.0 ); + dN.at(8, 2) = 0.125 * ( 1.0 + u ) * ( 1.0 - w ) * ( 2.0 * v - u + w + 1.0 ); + dN.at(9, 2) = -0.5 * v * ( 1.0 - u ) * ( 1.0 + w ); + dN.at(10, 2) = 0.25 * ( 1.0 - u * u ) * ( 1.0 + w ); + dN.at(11, 2) = -0.5 * v * ( 1.0 + u ) * ( 1.0 + w ); + dN.at(12, 2) = -0.25 * ( 1.0 - u * u ) * ( 1.0 + w ); + dN.at(13, 2) = -0.5 * v * ( 1.0 - u ) * ( 1.0 - w ); + dN.at(14, 2) = 0.25 * ( 1.0 - u * u ) * ( 1.0 - w ); + dN.at(15, 2) = -0.5 * v * ( 1.0 + u ) * ( 1.0 - w ); + dN.at(16, 2) = -0.25 * ( 1.0 - u * u ) * ( 1.0 - w ); + dN.at(17, 2) = -0.25 * ( 1.0 - u ) * ( 1.0 - w * w ); + dN.at(18, 2) = 0.25 * ( 1.0 - u ) * ( 1.0 - w * w ); + dN.at(19, 2) = 0.25 * ( 1.0 + u ) * ( 1.0 - w * w ); + dN.at(20, 2) = -0.25 * ( 1.0 + u ) * ( 1.0 - w * w ); + + dN.at(1, 3) = 0.125 * ( 1.0 - u ) * ( 1.0 - v ) * ( 2.0 * w - u - v - 1.0 ); + dN.at(2, 3) = 0.125 * ( 1.0 - u ) * ( 1.0 + v ) * ( 2.0 * w - u + v - 1.0 ); + dN.at(3, 3) = 0.125 * ( 1.0 + u ) * ( 1.0 + v ) * ( 2.0 * w + u + v - 1.0 ); + dN.at(4, 3) = 0.125 * ( 1.0 + u ) * ( 1.0 - v ) * ( 2.0 * w + u - v - 1.0 ); + dN.at(5, 3) = 0.125 * ( 1.0 - u ) * ( 1.0 - v ) * ( 2.0 * w + u + v + 1.0 ); + dN.at(6, 3) = 0.125 * ( 1.0 - u ) * ( 1.0 + v ) * ( 2.0 * w + u - v + 1.0 ); + dN.at(7, 3) = 0.125 * ( 1.0 + u ) * ( 1.0 + v ) * ( 2.0 * w - u - v + 1.0 ); + dN.at(8, 3) = 0.125 * ( 1.0 + u ) * ( 1.0 - v ) * ( 2.0 * w - u + v + 1.0 ); + dN.at(9, 3) = 0.25 * ( 1.0 - v * v ) * ( 1.0 - u ); + dN.at(10, 3) = 0.25 * ( 1.0 - u * u ) * ( 1.0 + v ); + dN.at(11, 3) = 0.25 * ( 1.0 - v * v ) * ( 1.0 + u ); + dN.at(12, 3) = 0.25 * ( 1.0 - u * u ) * ( 1.0 - v ); + dN.at(13, 3) = -0.25 * ( 1.0 - v * v ) * ( 1.0 - u ); + dN.at(14, 3) = -0.25 * ( 1.0 - u * u ) * ( 1.0 + v ); + dN.at(15, 3) = -0.25 * ( 1.0 - v * v ) * ( 1.0 + u ); + dN.at(16, 3) = -0.25 * ( 1.0 - u * u ) * ( 1.0 - v ); + dN.at(17, 3) = -0.5 * ( 1.0 - u ) * ( 1.0 - v ) * w; + dN.at(18, 3) = -0.5 * ( 1.0 - u ) * ( 1.0 + v ) * w; + dN.at(19, 3) = -0.5 * ( 1.0 + u ) * ( 1.0 + v ) * w; + dN.at(20, 3) = -0.5 * ( 1.0 + u ) * ( 1.0 - v ) * w; +#endif +} + + +std::pair> +FEI3dHexaQuad :: evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo) +{ + auto dNduvw = evaldNdxi(lcoords); + FloatMatrixF<3,20> coords; + for ( int i = 0; i < 20; i++ ) { + ///@todo cellgeo should give a FloatArrayF<3>, this will add a "costly" construction now: + coords.setColumn(cellgeo.giveVertexCoordinates(i+1), i); + } + auto jacT = dotT(dNduvw, coords); + return {det(jacT), dot(inv(jacT), dNduvw)}; } + double -FEI3dHexaQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + auto tmp = evaldNdx(lcoords, cellgeo); + answer = tmp.second; + return tmp.first; +#else FloatMatrix jacobianMatrix, inv, dNduvw, coords; - this->giveLocalDerivative(dNduvw, lcoords); + this->evaldNdxi(dNduvw, lcoords, cellgeo); coords.resize( 3, dNduvw.giveNumberOfRows() ); for ( int i = 1; i <= dNduvw.giveNumberOfRows(); i++ ) { - coords.setColumn(* cellgeo.giveVertexCoordinates(i), i); + coords.setColumn(cellgeo.giveVertexCoordinates(i), i); } jacobianMatrix.beProductOf(coords, dNduvw); inv.beInverseOf(jacobianMatrix); answer.beProductOf(dNduvw, inv); return jacobianMatrix.giveDeterminant(); +#endif } void -FEI3dHexaQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; this->evalN(n, lcoords, cellgeo); answer.clear(); for ( int i = 1; i <= n.giveSize(); i++ ) { - answer.add( n.at(i), * cellgeo.giveVertexCoordinates(i) ); + answer.add( n.at(i), cellgeo.giveVertexCoordinates(i) ); } } double FEI3dHexaQuad :: giveCharacteristicLength(const FEICellGeometry &cellgeo) const { - const FloatArray *n1 = cellgeo.giveVertexCoordinates(1); - const FloatArray *n2 = cellgeo.giveVertexCoordinates(7); + const auto &n1 = cellgeo.giveVertexCoordinates(1); + const auto &n2 = cellgeo.giveVertexCoordinates(7); ///@todo Change this so that it is not dependent on node order. - return n1->distance(n2); + return distance(n1, n2); } #define POINT_TOL 1.e-3 int -FEI3dHexaQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) +FEI3dHexaQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const { FloatArray res, delta, guess; FloatMatrix jac; @@ -167,7 +379,7 @@ FEI3dHexaQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, con return inside; } -void FEI3dHexaQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI3dHexaQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double u = lcoords.at(1); answer.resize(3); @@ -176,85 +388,80 @@ void FEI3dHexaQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray answer.at(3) = 1. - u * u; } -void FEI3dHexaQuad :: edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI3dHexaQuad :: edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray eNodes; double u = lcoords.at(1); - this->computeLocalEdgeMapping(eNodes, iedge); + const auto &eNodes = this->computeLocalEdgeMapping(iedge); answer.clear(); - answer.add( 0.5 * ( u - 1. ) * u, * cellgeo.giveVertexCoordinates( eNodes.at(1) ) ); - answer.add( 0.5 * ( u - 1. ) * u, * cellgeo.giveVertexCoordinates( eNodes.at(2) ) ); - answer.add( 1. - u * u, * cellgeo.giveVertexCoordinates( eNodes.at(3) ) ); + answer.add( 0.5 * ( u - 1. ) * u, cellgeo.giveVertexCoordinates( eNodes.at(1) ) ); + answer.add( 0.5 * ( u - 1. ) * u, cellgeo.giveVertexCoordinates( eNodes.at(2) ) ); + answer.add( 1. - u * u, cellgeo.giveVertexCoordinates( eNodes.at(3) ) ); } -void FEI3dHexaQuad :: edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI3dHexaQuad :: edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { ///@todo I think the "x" in dNdx implies global cs. It should be - IntArray eNodes; FloatArray dNdu; double u = lcoords.at(1); - this->computeLocalEdgeMapping(eNodes, iedge); - dNdu.add( u - 0.5, * cellgeo.giveVertexCoordinates( eNodes.at(1) ) ); - dNdu.add( u + 0.5, * cellgeo.giveVertexCoordinates( eNodes.at(2) ) ); - dNdu.add( -2. * u, * cellgeo.giveVertexCoordinates( eNodes.at(3) ) ); + const auto &eNodes = this->computeLocalEdgeMapping(iedge); + dNdu.add( u - 0.5, cellgeo.giveVertexCoordinates( eNodes.at(1) ) ); + dNdu.add( u + 0.5, cellgeo.giveVertexCoordinates( eNodes.at(2) ) ); + dNdu.add( -2. * u, cellgeo.giveVertexCoordinates( eNodes.at(3) ) ); // Why matrix output? answer.resize(3, 1); answer.setColumn(dNdu, 1); } -double FEI3dHexaQuad :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI3dHexaQuad :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray eNodes; FloatArray dNdu; double u = lcoords.at(1); - this->computeLocalEdgeMapping(eNodes, iedge); - dNdu.add( u - 0.5, * cellgeo.giveVertexCoordinates( eNodes.at(1) ) ); - dNdu.add( u + 0.5, * cellgeo.giveVertexCoordinates( eNodes.at(2) ) ); - dNdu.add( -2. * u, * cellgeo.giveVertexCoordinates( eNodes.at(3) ) ); + const auto &eNodes = this->computeLocalEdgeMapping(iedge); + dNdu.add( u - 0.5, cellgeo.giveVertexCoordinates( eNodes.at(1) ) ); + dNdu.add( u + 0.5, cellgeo.giveVertexCoordinates( eNodes.at(2) ) ); + dNdu.add( -2. * u, cellgeo.giveVertexCoordinates( eNodes.at(3) ) ); return dNdu.computeNorm(); } -void -FEI3dHexaQuad :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI3dHexaQuad :: computeLocalEdgeMapping(int iedge) const { if ( iedge == 1 ) { - edgeNodes = { 1, 2, 9}; + return { 1, 2, 9}; } else if ( iedge == 2 ) { - edgeNodes = { 2, 3, 10}; + return { 2, 3, 10}; } else if ( iedge == 3 ) { - edgeNodes = { 3, 4, 11}; + return { 3, 4, 11}; } else if ( iedge == 4 ) { - edgeNodes = { 4, 1, 12}; + return { 4, 1, 12}; } else if ( iedge == 5 ) { - edgeNodes = { 5, 6, 13}; + return { 5, 6, 13}; } else if ( iedge == 6 ) { - edgeNodes = { 6, 7, 14}; + return { 6, 7, 14}; } else if ( iedge == 7 ) { - edgeNodes = { 7, 8, 15}; + return { 7, 8, 15}; } else if ( iedge == 8 ) { - edgeNodes = { 8, 5, 16}; + return { 8, 5, 16}; } else if ( iedge == 9 ) { - edgeNodes = { 1, 5, 17}; + return { 1, 5, 17}; } else if ( iedge == 10 ) { - edgeNodes = { 2, 6, 18}; + return { 2, 6, 18}; } else if ( iedge == 11 ) { - edgeNodes = { 3, 7, 19}; + return { 3, 7, 19}; } else if ( iedge == 12 ) { - edgeNodes = { 4, 8, 20}; + return { 4, 8, 20}; } else { - OOFEM_ERROR("wrong edge number (%d)", iedge); + throw std::range_error("invalid edge number"); } } void -FEI3dHexaQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double ksi, eta; - answer.resize(8); - - ksi = lcoords.at(1); - eta = lcoords.at(2); + double ksi = lcoords.at(1); + double eta = lcoords.at(2); + answer.resize(8); answer.at(1) = ( 1. + ksi ) * ( 1. + eta ) * 0.25 * ( ksi + eta - 1. ); answer.at(2) = ( 1. - ksi ) * ( 1. + eta ) * 0.25 * ( -ksi + eta - 1. ); answer.at(3) = ( 1. - ksi ) * ( 1. - eta ) * 0.25 * ( -ksi - eta - 1. ); @@ -266,11 +473,10 @@ FEI3dHexaQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &l } void -FEI3dHexaQuad :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaQuad :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // Note, this must be in correct order, not just the correct nodes, therefore we must use snodes; - IntArray snodes; - this->computeLocalSurfaceMapping(snodes, isurf); + const auto &snodes = this->computeLocalSurfaceMapping(isurf); FloatArray lcoords_hex; @@ -322,16 +528,14 @@ FEI3dHexaQuad :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArra double -FEI3dHexaQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray a, b, dNdksi(8), dNdeta(8); - double ksi, eta; - IntArray snodes; - this->computeLocalSurfaceMapping(snodes, isurf); + const auto &snodes = this->computeLocalSurfaceMapping(isurf); - ksi = lcoords.at(1); - eta = lcoords.at(2); + double ksi = lcoords.at(1); + double eta = lcoords.at(2); dNdksi.at(1) = 0.25 * ( 1. + eta ) * ( 2.0 * ksi + eta ); dNdksi.at(2) = -0.25 * ( 1. + eta ) * ( -2.0 * ksi + eta ); @@ -352,8 +556,8 @@ FEI3dHexaQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArr dNdeta.at(8) = -eta * ( 1. + ksi ); for ( int i = 1; i <= 8; ++i ) { - a.add( dNdksi.at(i), * cellgeo.giveVertexCoordinates( snodes.at(i) ) ); - b.add( dNdeta.at(i), * cellgeo.giveVertexCoordinates( snodes.at(i) ) ); + a.add( dNdksi.at(i), cellgeo.giveVertexCoordinates( snodes.at(i) ) ); + b.add( dNdeta.at(i), cellgeo.giveVertexCoordinates( snodes.at(i) ) ); } answer.beVectorProductOf(a, b); @@ -362,52 +566,49 @@ FEI3dHexaQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArr void FEI3dHexaQuad :: surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray nodes; FloatArray n; - this->computeLocalSurfaceMapping(nodes, isurf); + const auto &nodes = this->computeLocalSurfaceMapping(isurf); this->surfaceEvalN(n, isurf, lcoords, cellgeo); answer.clear(); for ( int i = 1; i <= n.giveSize(); ++i ) { - answer.add( n.at(i), * cellgeo.giveVertexCoordinates( nodes.at(i) ) ); + answer.add( n.at(i), cellgeo.giveVertexCoordinates( nodes.at(i) ) ); } } double FEI3dHexaQuad :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + const FEICellGeometry &cellgeo) const { FloatArray normal; return this->surfaceEvalNormal(normal, isurf, lcoords, cellgeo); } -void -FEI3dHexaQuad :: computeLocalSurfaceMapping(IntArray &nodes, int isurf) +IntArray +FEI3dHexaQuad :: computeLocalSurfaceMapping(int isurf) const { - nodes.resize(8); - // the actual numbering has a positive normal pointing outwards from the element - (LSpace compatible) if ( isurf == 1 ) { - nodes = { 3, 2, 1, 4, 10, 9, 12, 11}; + return { 3, 2, 1, 4, 10, 9, 12, 11}; } else if ( isurf == 2 ) { - nodes = { 7, 8, 5, 6, 15, 16, 13, 14}; + return { 7, 8, 5, 6, 15, 16, 13, 14}; } else if ( isurf == 3 ) { - nodes = { 2, 6, 5, 1, 18, 13, 17, 9}; + return { 2, 6, 5, 1, 18, 13, 17, 9}; } else if ( isurf == 4 ) { - nodes = { 3, 7, 6, 2, 19, 14, 18, 10}; + return { 3, 7, 6, 2, 19, 14, 18, 10}; } else if ( isurf == 5 ) { - nodes = { 3, 4, 8, 7, 11, 20, 15, 19}; + return { 3, 4, 8, 7, 11, 20, 15, 19}; } else if ( isurf == 6 ) { - nodes = { 4, 1, 5, 8, 12, 17, 16, 20}; + return { 4, 1, 5, 8, 12, 17, 16, 20}; } else { - OOFEM_ERROR("wrong surface number (%d)", isurf); + throw std::range_error("invalid surface number"); } #if 0 @@ -475,108 +676,32 @@ FEI3dHexaQuad :: computeLocalSurfaceMapping(IntArray &nodes, int isurf) void -FEI3dHexaQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const // Returns the jacobian matrix J (x,y,z)/(ksi,eta,dzeta) of the receiver. { FloatMatrix dNduvw, coords; - this->giveLocalDerivative(dNduvw, lcoords); + this->evaldNdxi(dNduvw, lcoords, cellgeo); coords.resize( 3, dNduvw.giveNumberOfRows() ); for ( int i = 1; i <= dNduvw.giveNumberOfRows(); i++ ) { - coords.setColumn(* cellgeo.giveVertexCoordinates(i), i); + coords.setColumn(cellgeo.giveVertexCoordinates(i), i); } jacobianMatrix.beProductOf(coords, dNduvw); } -void -FEI3dHexaQuad :: giveLocalDerivative(FloatMatrix &dN, const FloatArray &lcoords) -{ - double u, v, w; - u = lcoords.at(1); - v = lcoords.at(2); - w = lcoords.at(3); - - dN.resize(20, 3); - - dN.at(1, 1) = 0.125 * ( 1.0 - v ) * ( 1.0 + w ) * ( 2.0 * u + v - w + 1.0 ); - dN.at(2, 1) = 0.125 * ( 1.0 + v ) * ( 1.0 + w ) * ( 2.0 * u - v - w + 1.0 ); - dN.at(3, 1) = 0.125 * ( 1.0 + v ) * ( 1.0 + w ) * ( 2.0 * u + v + w - 1.0 ); - dN.at(4, 1) = 0.125 * ( 1.0 - v ) * ( 1.0 + w ) * ( 2.0 * u - v + w - 1.0 ); - dN.at(5, 1) = 0.125 * ( 1.0 - v ) * ( 1.0 - w ) * ( 2.0 * u + v + w + 1.0 ); - dN.at(6, 1) = 0.125 * ( 1.0 + v ) * ( 1.0 - w ) * ( 2.0 * u - v + w + 1.0 ); - dN.at(7, 1) = 0.125 * ( 1.0 + v ) * ( 1.0 - w ) * ( 2.0 * u + v - w - 1.0 ); - dN.at(8, 1) = 0.125 * ( 1.0 - v ) * ( 1.0 - w ) * ( 2.0 * u - v - w - 1.0 ); - dN.at(9, 1) = -0.25 * ( 1.0 - v * v ) * ( 1.0 + w ); - dN.at(10, 1) = -0.5 * u * ( 1.0 + v ) * ( 1.0 + w ); - dN.at(11, 1) = 0.25 * ( 1.0 - v * v ) * ( 1.0 + w ); - dN.at(12, 1) = -0.5 * u * ( 1.0 - v ) * ( 1.0 + w ); - dN.at(13, 1) = -0.25 * ( 1.0 - v * v ) * ( 1.0 - w ); - dN.at(14, 1) = -0.5 * u * ( 1.0 + v ) * ( 1.0 - w ); - dN.at(15, 1) = 0.25 * ( 1.0 - v * v ) * ( 1.0 - w ); - dN.at(16, 1) = -0.5 * u * ( 1.0 - v ) * ( 1.0 - w ); - dN.at(17, 1) = -0.25 * ( 1.0 - v ) * ( 1.0 - w * w ); - dN.at(18, 1) = -0.25 * ( 1.0 + v ) * ( 1.0 - w * w ); - dN.at(19, 1) = 0.25 * ( 1.0 + v ) * ( 1.0 - w * w ); - dN.at(20, 1) = 0.25 * ( 1.0 - v ) * ( 1.0 - w * w ); - - dN.at(1, 2) = 0.125 * ( 1.0 - u ) * ( 1.0 + w ) * ( 2.0 * v + u - w + 1.0 ); - dN.at(2, 2) = 0.125 * ( 1.0 - u ) * ( 1.0 + w ) * ( 2.0 * v - u + w - 1.0 ); - dN.at(3, 2) = 0.125 * ( 1.0 + u ) * ( 1.0 + w ) * ( 2.0 * v + u + w - 1.0 ); - dN.at(4, 2) = 0.125 * ( 1.0 + u ) * ( 1.0 + w ) * ( 2.0 * v - u - w + 1.0 ); - dN.at(5, 2) = 0.125 * ( 1.0 - u ) * ( 1.0 - w ) * ( 2.0 * v + u + w + 1.0 ); - dN.at(6, 2) = 0.125 * ( 1.0 - u ) * ( 1.0 - w ) * ( 2.0 * v - u - w - 1.0 ); - dN.at(7, 2) = 0.125 * ( 1.0 + u ) * ( 1.0 - w ) * ( 2.0 * v + u - w - 1.0 ); - dN.at(8, 2) = 0.125 * ( 1.0 + u ) * ( 1.0 - w ) * ( 2.0 * v - u + w + 1.0 ); - dN.at(9, 2) = -0.5 * v * ( 1.0 - u ) * ( 1.0 + w ); - dN.at(10, 2) = 0.25 * ( 1.0 - u * u ) * ( 1.0 + w ); - dN.at(11, 2) = -0.5 * v * ( 1.0 + u ) * ( 1.0 + w ); - dN.at(12, 2) = -0.25 * ( 1.0 - u * u ) * ( 1.0 + w ); - dN.at(13, 2) = -0.5 * v * ( 1.0 - u ) * ( 1.0 - w ); - dN.at(14, 2) = 0.25 * ( 1.0 - u * u ) * ( 1.0 - w ); - dN.at(15, 2) = -0.5 * v * ( 1.0 + u ) * ( 1.0 - w ); - dN.at(16, 2) = -0.25 * ( 1.0 - u * u ) * ( 1.0 - w ); - dN.at(17, 2) = -0.25 * ( 1.0 - u ) * ( 1.0 - w * w ); - dN.at(18, 2) = 0.25 * ( 1.0 - u ) * ( 1.0 - w * w ); - dN.at(19, 2) = 0.25 * ( 1.0 + u ) * ( 1.0 - w * w ); - dN.at(20, 2) = -0.25 * ( 1.0 + u ) * ( 1.0 - w * w ); - - dN.at(1, 3) = 0.125 * ( 1.0 - u ) * ( 1.0 - v ) * ( 2.0 * w - u - v - 1.0 ); - dN.at(2, 3) = 0.125 * ( 1.0 - u ) * ( 1.0 + v ) * ( 2.0 * w - u + v - 1.0 ); - dN.at(3, 3) = 0.125 * ( 1.0 + u ) * ( 1.0 + v ) * ( 2.0 * w + u + v - 1.0 ); - dN.at(4, 3) = 0.125 * ( 1.0 + u ) * ( 1.0 - v ) * ( 2.0 * w + u - v - 1.0 ); - dN.at(5, 3) = 0.125 * ( 1.0 - u ) * ( 1.0 - v ) * ( 2.0 * w + u + v + 1.0 ); - dN.at(6, 3) = 0.125 * ( 1.0 - u ) * ( 1.0 + v ) * ( 2.0 * w + u - v + 1.0 ); - dN.at(7, 3) = 0.125 * ( 1.0 + u ) * ( 1.0 + v ) * ( 2.0 * w - u - v + 1.0 ); - dN.at(8, 3) = 0.125 * ( 1.0 + u ) * ( 1.0 - v ) * ( 2.0 * w - u + v + 1.0 ); - dN.at(9, 3) = 0.25 * ( 1.0 - v * v ) * ( 1.0 - u ); - dN.at(10, 3) = 0.25 * ( 1.0 - u * u ) * ( 1.0 + v ); - dN.at(11, 3) = 0.25 * ( 1.0 - v * v ) * ( 1.0 + u ); - dN.at(12, 3) = 0.25 * ( 1.0 - u * u ) * ( 1.0 - v ); - dN.at(13, 3) = -0.25 * ( 1.0 - v * v ) * ( 1.0 - u ); - dN.at(14, 3) = -0.25 * ( 1.0 - u * u ) * ( 1.0 + v ); - dN.at(15, 3) = -0.25 * ( 1.0 - v * v ) * ( 1.0 + u ); - dN.at(16, 3) = -0.25 * ( 1.0 - u * u ) * ( 1.0 - v ); - dN.at(17, 3) = -0.5 * ( 1.0 - u ) * ( 1.0 - v ) * w; - dN.at(18, 3) = -0.5 * ( 1.0 - u ) * ( 1.0 + v ) * w; - dN.at(19, 3) = -0.5 * ( 1.0 + u ) * ( 1.0 + v ) * w; - dN.at(20, 3) = -0.5 * ( 1.0 + u ) * ( 1.0 - v ) * w; -} - - double -FEI3dHexaQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) +FEI3dHexaQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const { - IntArray fNodes; - this->computeLocalSurfaceMapping(fNodes, iEdge); - - const FloatArray &c1 = * cellgeo.giveVertexCoordinates( fNodes.at(1) ); - const FloatArray &c2 = * cellgeo.giveVertexCoordinates( fNodes.at(2) ); - const FloatArray &c3 = * cellgeo.giveVertexCoordinates( fNodes.at(3) ); - const FloatArray &c4 = * cellgeo.giveVertexCoordinates( fNodes.at(4) ); - const FloatArray &c5 = * cellgeo.giveVertexCoordinates( fNodes.at(5) ); - const FloatArray &c6 = * cellgeo.giveVertexCoordinates( fNodes.at(6) ); - const FloatArray &c7 = * cellgeo.giveVertexCoordinates( fNodes.at(7) ); - const FloatArray &c8 = * cellgeo.giveVertexCoordinates( fNodes.at(8) ); + const auto &fNodes = this->computeLocalSurfaceMapping(iEdge); + + const auto &c1 = cellgeo.giveVertexCoordinates( fNodes.at(1) ); + const auto &c2 = cellgeo.giveVertexCoordinates( fNodes.at(2) ); + const auto &c3 = cellgeo.giveVertexCoordinates( fNodes.at(3) ); + const auto &c4 = cellgeo.giveVertexCoordinates( fNodes.at(4) ); + const auto &c5 = cellgeo.giveVertexCoordinates( fNodes.at(5) ); + const auto &c6 = cellgeo.giveVertexCoordinates( fNodes.at(6) ); + const auto &c7 = cellgeo.giveVertexCoordinates( fNodes.at(7) ); + const auto &c8 = cellgeo.giveVertexCoordinates( fNodes.at(8) ); // Generated with Mathematica (rather unwieldy expression, tried to simplify it as good as possible, but it could probably be better) return ( @@ -640,21 +765,21 @@ FEI3dHexaQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) } -IntegrationRule * -FEI3dHexaQuad :: giveIntegrationRule(int order) +std::unique_ptr +FEI3dHexaQuad :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Cube, order + 9); iRule->SetUpPointsOnCube(points, _Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule * -FEI3dHexaQuad :: giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr +FEI3dHexaQuad :: giveBoundaryIntegrationRule(int order, int boundary) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order + 4); iRule->SetUpPointsOnSquare(points, _Unknown); - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei3dhexaquad.h b/src/oofemlib/fei3dhexaquad.h index aeae8ba26..38c9cac84 100644 --- a/src/oofemlib/fei3dhexaquad.h +++ b/src/oofemlib/fei3dhexaquad.h @@ -72,49 +72,46 @@ class OOFEM_EXPORT FEI3dHexaQuad : public FEInterpolation3d public: FEI3dHexaQuad() : FEInterpolation3d(2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Cube; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_hexa_2; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Square; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Square; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Cube; } + Element_Geometry_Type giveGeometryType() const override { return EGT_hexa_2; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Square; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Square; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } - - - virtual double giveCharacteristicLength(const FEICellGeometry &cellgeo) const; + double giveCharacteristicLength(const FEICellGeometry &cellgeo) const; // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int giveNumberOfNodes() const { return 20; } - + static FloatArrayF<20> evalN(const FloatArrayF<3> &lcoords); + static std::pair> evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo); + static FloatMatrixF<3,20> evaldNdxi(const FloatArrayF<3> &lcoords); + + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int giveNumberOfNodes() const override { return 20; } + // Edge - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalEdgeMapping(int iedge) const override; // Surface - virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void computeLocalSurfaceMapping(IntArray &nodes, int iSurf); - virtual double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo); - - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalSurfaceMapping(int iSurf) const override; + double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const override; - virtual IntegrationRule *giveIntegrationRule(int order); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary); + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; -protected: - virtual void giveLocalDerivative(FloatMatrix &dN, const FloatArray &lcoords); + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; }; } // end namespace oofem #endif diff --git a/src/oofemlib/fei3dhexatriquad.C b/src/oofemlib/fei3dhexatriquad.C index a7776d6e4..916b0a408 100644 --- a/src/oofemlib/fei3dhexatriquad.C +++ b/src/oofemlib/fei3dhexatriquad.C @@ -35,13 +35,62 @@ #include "fei3dhexatriquad.h" #include "intarray.h" #include "floatarray.h" +#include "floatarrayf.h" #include "floatmatrix.h" +#include "floatmatrixf.h" #include "gaussintegrationrule.h" namespace oofem { + +FloatArrayF<27> +FEI3dHexaTriQuad :: evalN(const FloatArrayF<3> &lcoords) +{ + //auto [u, v, w] = lcoords; + double u = lcoords[0]; + double v = lcoords[1]; + double w = lcoords[2]; + + std::array a = {0.5 * ( u - 1.0 ) * u, 0.5 * ( u + 1.0 ) * u, 1.0 - u * u}; + std::array b = {0.5 * ( v - 1.0 ) * v, 0.5 * ( v + 1.0 ) * v, 1.0 - v * v}; + std::array c = {0.5 * ( w - 1.0 ) * w, 0.5 * ( w + 1.0 ) * w, 1.0 - w * w}; + + return { + a [ 0 ] * b [ 0 ] * c [ 1 ], + a [ 0 ] * b [ 1 ] * c [ 1 ], + a [ 1 ] * b [ 1 ] * c [ 1 ], + a [ 1 ] * b [ 0 ] * c [ 1 ], + a [ 0 ] * b [ 0 ] * c [ 0 ], + a [ 0 ] * b [ 1 ] * c [ 0 ], + a [ 1 ] * b [ 1 ] * c [ 0 ], + a [ 1 ] * b [ 0 ] * c [ 0 ], + a [ 0 ] * b [ 2 ] * c [ 1 ], + a [ 2 ] * b [ 1 ] * c [ 1 ], + a [ 1 ] * b [ 2 ] * c [ 1 ], + a [ 2 ] * b [ 0 ] * c [ 1 ], + a [ 0 ] * b [ 2 ] * c [ 0 ], + a [ 2 ] * b [ 1 ] * c [ 0 ], + a [ 1 ] * b [ 2 ] * c [ 0 ], + a [ 2 ] * b [ 0 ] * c [ 0 ], + a [ 0 ] * b [ 0 ] * c [ 2 ], + a [ 0 ] * b [ 1 ] * c [ 2 ], + a [ 1 ] * b [ 1 ] * c [ 2 ], + a [ 1 ] * b [ 0 ] * c [ 2 ], + a [ 2 ] * b [ 2 ] * c [ 1 ], + a [ 0 ] * b [ 2 ] * c [ 2 ], + a [ 2 ] * b [ 2 ] * c [ 0 ], + a [ 2 ] * b [ 1 ] * c [ 2 ], + a [ 1 ] * b [ 2 ] * c [ 2 ], + a [ 2 ] * b [ 0 ] * c [ 2 ], + a [ 2 ] * b [ 2 ] * c [ 2 ] + }; +} + void -FEI3dHexaTriQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaTriQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + answer = evalN(lcoords); +#else double u = lcoords.at(1); double v = lcoords.at(2); double w = lcoords.at(3); @@ -93,11 +142,12 @@ FEI3dHexaTriQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const F answer.at(23) = a [ 0 ] * b [ 2 ] * c [ 2 ]; answer.at(25) = a [ 1 ] * b [ 2 ] * c [ 2 ]; answer.at(27) = a [ 2 ] * b [ 2 ] * c [ 2 ]; +#endif } void -FEI3dHexaTriQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaTriQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double u = lcoords.at(1); double v = lcoords.at(2); @@ -126,9 +176,8 @@ FEI3dHexaTriQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray double -FEI3dHexaTriQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dHexaTriQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray snodes; FloatArray e1, e2, dNdu(9), dNdv(9); double u = lcoords.at(1); @@ -173,10 +222,10 @@ FEI3dHexaTriQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const Float dNdv.at(6) = a [ 1 ] * db [ 2 ]; dNdv.at(9) = a [ 2 ] * db [ 2 ]; - this->computeLocalSurfaceMapping(snodes, isurf); + const auto &snodes = this->computeLocalSurfaceMapping(isurf); for ( int i = 1; i <= 9; ++i ) { - e1.add( dNdu.at(i), * cellgeo.giveVertexCoordinates( snodes.at(i) ) ); - e2.add( dNdv.at(i), * cellgeo.giveVertexCoordinates( snodes.at(i) ) ); + e1.add( dNdu.at(i), cellgeo.giveVertexCoordinates( snodes.at(i) ) ); + e2.add( dNdv.at(i), cellgeo.giveVertexCoordinates( snodes.at(i) ) ); } answer.beVectorProductOf(e1, e2); @@ -184,30 +233,81 @@ FEI3dHexaTriQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const Float } -void -FEI3dHexaTriQuad :: computeLocalSurfaceMapping(IntArray &nodes, int isurf) +IntArray +FEI3dHexaTriQuad :: computeLocalSurfaceMapping(int isurf) const { if ( isurf == 1 ) { - nodes = { 2, 1, 4, 3, 9, 12, 11, 10, 21}; + return { 2, 1, 4, 3, 9, 12, 11, 10, 21}; } else if ( isurf == 2 ) { - nodes = { 5, 6, 7, 8, 13, 14, 15, 16, 22}; + return { 5, 6, 7, 8, 13, 14, 15, 16, 22}; } else if ( isurf == 3 ) { - nodes = { 1, 2, 6, 5, 9, 18, 13, 17, 23}; + return { 1, 2, 6, 5, 9, 18, 13, 17, 23}; } else if ( isurf == 4 ) { - nodes = { 2, 3, 7, 6, 10, 19, 14, 18, 24}; + return { 2, 3, 7, 6, 10, 19, 14, 18, 24}; } else if ( isurf == 5 ) { - nodes = { 3, 4, 8, 7, 11, 20, 15, 19, 25}; + return { 3, 4, 8, 7, 11, 20, 15, 19, 25}; } else if ( isurf == 6 ) { - nodes = { 4, 1, 5, 8, 12, 17, 16, 20, 26}; + return { 4, 1, 5, 8, 12, 17, 16, 20, 26}; } else { - OOFEM_ERROR("wrong surface number (%d)", isurf); + throw std::range_error("invalid surface number"); } } +FloatMatrixF<3,27> +FEI3dHexaTriQuad :: evaldNdxi(const FloatArrayF<3> &lcoords) +{ + //auto [u, v, w] = lcoords; + double u = lcoords[0]; + double v = lcoords[1]; + double w = lcoords[2]; + + std::array a = {0.5 * ( u - 1.0 ) * u, 0.5 * ( u + 1.0 ) * u, 1.0 - u * u}; + std::array b = {0.5 * ( v - 1.0 ) * v, 0.5 * ( v + 1.0 ) * v, 1.0 - v * v}; + std::array c = {0.5 * ( w - 1.0 ) * w, 0.5 * ( w + 1.0 ) * w, 1.0 - w * w}; + + std::array da = {-0.5 + u, 0.5 + u, -2.0 * u}; + std::array db = {-0.5 + v, 0.5 + v, -2.0 * v}; + std::array dc = {-0.5 + w, 0.5 + w, -2.0 * w}; + + return { + da [ 0 ] * b [ 0 ] * c [ 1 ], a [ 0 ] * db [ 0 ] * c [ 1 ], a [ 0 ] * b [ 0 ] * dc [ 1 ], + da [ 0 ] * b [ 1 ] * c [ 1 ], a [ 0 ] * db [ 1 ] * c [ 1 ], a [ 0 ] * b [ 1 ] * dc [ 1 ], + da [ 1 ] * b [ 1 ] * c [ 1 ], a [ 1 ] * db [ 1 ] * c [ 1 ], a [ 1 ] * b [ 1 ] * dc [ 1 ], + da [ 1 ] * b [ 0 ] * c [ 1 ], a [ 1 ] * db [ 0 ] * c [ 1 ], a [ 1 ] * b [ 0 ] * dc [ 1 ], + da [ 0 ] * b [ 0 ] * c [ 0 ], a [ 0 ] * db [ 0 ] * c [ 0 ], a [ 0 ] * b [ 0 ] * dc [ 0 ], + da [ 0 ] * b [ 1 ] * c [ 0 ], a [ 0 ] * db [ 1 ] * c [ 0 ], a [ 0 ] * b [ 1 ] * dc [ 0 ], + da [ 1 ] * b [ 1 ] * c [ 0 ], a [ 1 ] * db [ 1 ] * c [ 0 ], a [ 1 ] * b [ 1 ] * dc [ 0 ], + da [ 1 ] * b [ 0 ] * c [ 0 ], a [ 1 ] * db [ 0 ] * c [ 0 ], a [ 1 ] * b [ 0 ] * dc [ 0 ], + da [ 0 ] * b [ 2 ] * c [ 1 ], a [ 0 ] * db [ 2 ] * c [ 1 ], a [ 0 ] * b [ 2 ] * dc [ 1 ], + da [ 2 ] * b [ 1 ] * c [ 1 ], a [ 2 ] * db [ 1 ] * c [ 1 ], a [ 2 ] * b [ 1 ] * dc [ 1 ], + da [ 1 ] * b [ 2 ] * c [ 1 ], a [ 1 ] * db [ 2 ] * c [ 1 ], a [ 1 ] * b [ 2 ] * dc [ 1 ], + da [ 2 ] * b [ 0 ] * c [ 1 ], a [ 2 ] * db [ 0 ] * c [ 1 ], a [ 2 ] * b [ 0 ] * dc [ 1 ], + da [ 0 ] * b [ 2 ] * c [ 0 ], a [ 0 ] * db [ 2 ] * c [ 0 ], a [ 0 ] * b [ 2 ] * dc [ 0 ], + da [ 2 ] * b [ 1 ] * c [ 0 ], a [ 2 ] * db [ 1 ] * c [ 0 ], a [ 2 ] * b [ 1 ] * dc [ 0 ], + da [ 1 ] * b [ 2 ] * c [ 0 ], a [ 1 ] * db [ 2 ] * c [ 0 ], a [ 1 ] * b [ 2 ] * dc [ 0 ], + da [ 2 ] * b [ 0 ] * c [ 0 ], a [ 2 ] * db [ 0 ] * c [ 0 ], a [ 2 ] * b [ 0 ] * dc [ 0 ], + da [ 0 ] * b [ 0 ] * c [ 2 ], a [ 0 ] * db [ 0 ] * c [ 2 ], a [ 0 ] * b [ 0 ] * dc [ 2 ], + da [ 0 ] * b [ 1 ] * c [ 2 ], a [ 0 ] * db [ 1 ] * c [ 2 ], a [ 0 ] * b [ 1 ] * dc [ 2 ], + da [ 1 ] * b [ 1 ] * c [ 2 ], a [ 1 ] * db [ 1 ] * c [ 2 ], a [ 1 ] * b [ 1 ] * dc [ 2 ], + da [ 1 ] * b [ 0 ] * c [ 2 ], a [ 1 ] * db [ 0 ] * c [ 2 ], a [ 1 ] * b [ 0 ] * dc [ 2 ], + da [ 2 ] * b [ 2 ] * c [ 1 ], a [ 2 ] * db [ 2 ] * c [ 1 ], a [ 2 ] * b [ 2 ] * dc [ 1 ], + da [ 2 ] * b [ 2 ] * c [ 0 ], a [ 2 ] * db [ 2 ] * c [ 0 ], a [ 2 ] * b [ 2 ] * dc [ 0 ], + da [ 0 ] * b [ 2 ] * c [ 2 ], a [ 0 ] * db [ 2 ] * c [ 2 ], a [ 0 ] * b [ 2 ] * dc [ 2 ], + da [ 2 ] * b [ 1 ] * c [ 2 ], a [ 2 ] * db [ 1 ] * c [ 2 ], a [ 2 ] * b [ 1 ] * dc [ 2 ], + da [ 1 ] * b [ 2 ] * c [ 2 ], a [ 1 ] * db [ 2 ] * c [ 2 ], a [ 1 ] * b [ 2 ] * dc [ 2 ], + da [ 2 ] * b [ 0 ] * c [ 2 ], a [ 2 ] * db [ 0 ] * c [ 2 ], a [ 2 ] * b [ 0 ] * dc [ 2 ], + da [ 2 ] * b [ 2 ] * c [ 2 ], a [ 2 ] * db [ 2 ] * c [ 2 ], a [ 2 ] * b [ 2 ] * dc [ 2 ], + }; +} + + void -FEI3dHexaTriQuad :: giveLocalDerivative(FloatMatrix &dN, const FloatArray &lcoords) +FEI3dHexaTriQuad :: evaldNdxi(FloatMatrix &dN, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + dN = evaldNdxi(lcoords); +#else double u, v, w; u = lcoords.at(1); v = lcoords.at(2); @@ -347,24 +447,45 @@ FEI3dHexaTriQuad :: giveLocalDerivative(FloatMatrix &dN, const FloatArray &lcoor dN.at(23, 3) = a [ 0 ] * b [ 2 ] * dc [ 2 ]; dN.at(25, 3) = a [ 1 ] * b [ 2 ] * dc [ 2 ]; dN.at(27, 3) = a [ 2 ] * b [ 2 ] * dc [ 2 ]; +#endif } +std::pair> +FEI3dHexaTriQuad :: evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo) +{ + auto dNduvw = evaldNdxi(lcoords); + FloatMatrixF<3,27> coords; + for ( int i = 0; i < 27; i++ ) { + ///@todo cellgeo should give a FloatArrayF<3>, this will add a "costly" construction now: + coords.setColumn(cellgeo.giveVertexCoordinates(i+1), i); + } + auto jacT = dotT(dNduvw, coords); + return {det(jacT), dot(inv(jacT), dNduvw)}; +} + +double +FEI3dHexaTriQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + auto tmp = evaldNdx(lcoords, cellgeo); + answer = transpose(tmp.second); + return tmp.first; +} + double -FEI3dHexaTriQuad :: evalNXIntegral(int iSurf, const FEICellGeometry &cellgeo) +FEI3dHexaTriQuad :: evalNXIntegral(int iSurf, const FEICellGeometry &cellgeo) const { - IntArray fNodes; - this->computeLocalSurfaceMapping(fNodes, iSurf); - - const FloatArray &c1 = * cellgeo.giveVertexCoordinates( fNodes.at(1) ); - const FloatArray &c2 = * cellgeo.giveVertexCoordinates( fNodes.at(2) ); - const FloatArray &c3 = * cellgeo.giveVertexCoordinates( fNodes.at(3) ); - const FloatArray &c4 = * cellgeo.giveVertexCoordinates( fNodes.at(4) ); - const FloatArray &c5 = * cellgeo.giveVertexCoordinates( fNodes.at(5) ); - const FloatArray &c6 = * cellgeo.giveVertexCoordinates( fNodes.at(6) ); - const FloatArray &c7 = * cellgeo.giveVertexCoordinates( fNodes.at(7) ); - const FloatArray &c8 = * cellgeo.giveVertexCoordinates( fNodes.at(8) ); - const FloatArray &c9 = * cellgeo.giveVertexCoordinates( fNodes.at(9) ); + const auto &fNodes = this->computeLocalSurfaceMapping(iSurf); + + const auto &c1 = cellgeo.giveVertexCoordinates( fNodes.at(1) ); + const auto &c2 = cellgeo.giveVertexCoordinates( fNodes.at(2) ); + const auto &c3 = cellgeo.giveVertexCoordinates( fNodes.at(3) ); + const auto &c4 = cellgeo.giveVertexCoordinates( fNodes.at(4) ); + const auto &c5 = cellgeo.giveVertexCoordinates( fNodes.at(5) ); + const auto &c6 = cellgeo.giveVertexCoordinates( fNodes.at(6) ); + const auto &c7 = cellgeo.giveVertexCoordinates( fNodes.at(7) ); + const auto &c8 = cellgeo.giveVertexCoordinates( fNodes.at(8) ); + const auto &c9 = cellgeo.giveVertexCoordinates( fNodes.at(9) ); // Generated with Mathematica (rather unwieldy expression, tried to simplify it as good as possible, but it could probably be better) return ( @@ -460,23 +581,23 @@ FEI3dHexaTriQuad :: evalNXIntegral(int iSurf, const FEICellGeometry &cellgeo) ) / 300.0; } -IntegrationRule * -FEI3dHexaTriQuad :: giveIntegrationRule(int order) +std::unique_ptr +FEI3dHexaTriQuad :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); ///@todo Verify: Is +15 correct for dealing with "detJ"? If it is, perhaps we shouldn't go for exact integration since it is likely overkill. int points = iRule->getRequiredNumberOfIntegrationPoints(_Cube, order + 15); iRule->SetUpPointsOnCube(points, _Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule * -FEI3dHexaTriQuad :: giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr +FEI3dHexaTriQuad :: giveBoundaryIntegrationRule(int order, int boundary) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); ///@todo Verify: Is +6 correct for dealing with "detJ" on this surface? int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order + 6); iRule->SetUpPointsOnSquare(points, _Unknown); - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei3dhexatriquad.h b/src/oofemlib/fei3dhexatriquad.h index 83938beb7..f428f6349 100644 --- a/src/oofemlib/fei3dhexatriquad.h +++ b/src/oofemlib/fei3dhexatriquad.h @@ -47,28 +47,31 @@ class OOFEM_EXPORT FEI3dHexaTriQuad : public FEI3dHexaQuad public: FEI3dHexaTriQuad() : FEI3dHexaQuad() { } - virtual integrationDomain giveIntegrationDomain() const { return _Cube; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_hexa_27; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Square; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Square; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Cube; } + Element_Geometry_Type giveGeometryType() const override { return EGT_hexa_27; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Square; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Square; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int giveNumberOfNodes() const { return 27; } - - // Surface - virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - //virtual void surfaceEvaldNdx(FloatMatrix&answer, int isurf, const FloatArray& lcoords, const FEICellGeometry& cellgeo); - virtual void computeLocalSurfaceMapping(IntArray &nodes, int iSurf); - virtual double evalNXIntegral(int iSurf, const FEICellGeometry &cellgeo); + static FloatArrayF<27> evalN(const FloatArrayF<3> &lcoords); + static std::pair> evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo); + static FloatMatrixF<3,27> evaldNdxi(const FloatArrayF<3> &lcoords); + + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int giveNumberOfNodes() const override { return 27; } - virtual IntegrationRule *giveIntegrationRule(int order); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary); + // Surface + void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + //void surfaceEvaldNdx(FloatMatrix&answer, int isurf, const FloatArray& lcoords, const FEICellGeometry& cellgeo) override; + IntArray computeLocalSurfaceMapping(int iSurf) const override; + double evalNXIntegral(int iSurf, const FEICellGeometry &cellgeo) const override; -protected: - virtual void giveLocalDerivative(FloatMatrix &dN, const FloatArray &lcoords); + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; }; } // end namespace oofem #endif diff --git a/src/oofemlib/fei3dlinelin.C b/src/oofemlib/fei3dlinelin.C index 0d1d4555f..98e854ce2 100644 --- a/src/oofemlib/fei3dlinelin.C +++ b/src/oofemlib/fei3dlinelin.C @@ -42,11 +42,11 @@ namespace oofem { double FEI3dLineLin :: giveLength(const FEICellGeometry &cellgeo) const { - return cellgeo.giveVertexCoordinates(2)->distance( * cellgeo.giveVertexCoordinates(1) ); + return distance(cellgeo.giveVertexCoordinates(2), cellgeo.giveVertexCoordinates(1)); } void -FEI3dLineLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dLineLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); answer.resize(2); @@ -56,11 +56,11 @@ FEI3dLineLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICe } double -FEI3dLineLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dLineLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { ///@todo Not clear what this function should return. Just dNds would make sense if the caller defines a local coordinate system. FloatArray vec; - vec.beDifferenceOf( * cellgeo.giveVertexCoordinates(2), * cellgeo.giveVertexCoordinates(1) ); + vec.beDifferenceOf( cellgeo.giveVertexCoordinates(2), cellgeo.giveVertexCoordinates(1) ); double detJ = vec.computeSquaredNorm() * 0.5; double l2_inv = 0.5 / detJ; @@ -77,28 +77,28 @@ FEI3dLineLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const F } void -FEI3dLineLin :: evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dLineLin :: evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(2, 3); ///@todo Check this part answer.zero(); } void -FEI3dLineLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dLineLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); - answer.beScaled( ( 1. - ksi ) * 0.5, * cellgeo.giveVertexCoordinates(1) ); - answer.add( ( 1. + ksi ) * 0.5, * cellgeo.giveVertexCoordinates(2) ); + answer.beScaled( ( 1. - ksi ) * 0.5, cellgeo.giveVertexCoordinates(1) ); + answer.add( ( 1. + ksi ) * 0.5, cellgeo.giveVertexCoordinates(2) ); } int -FEI3dLineLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) +FEI3dLineLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) const { FloatArray vec, x; - vec.beDifferenceOf( * cellgeo.giveVertexCoordinates(2), * cellgeo.giveVertexCoordinates(1) ); - x.beDifferenceOf( coords, * cellgeo.giveVertexCoordinates(1) ); + vec.beDifferenceOf( cellgeo.giveVertexCoordinates(2), cellgeo.giveVertexCoordinates(1) ); + x.beDifferenceOf( coords, cellgeo.giveVertexCoordinates(1) ); double l2 = vec.computeSquaredNorm(); double xvec = x.dotProduct(vec); @@ -109,21 +109,21 @@ FEI3dLineLin :: global2local(FloatArray &answer, const FloatArray &coords, const double -FEI3dLineLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dLineLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return 0.5 * this->giveLength(cellgeo); } void -FEI3dLineLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dLineLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->evalN(answer, lcoords, cellgeo); } void FEI3dLineLin :: edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double l_inv = 1.0 / this->giveLength(cellgeo); @@ -134,36 +134,36 @@ FEI3dLineLin :: edgeEvaldNdx(FloatMatrix &answer, int iedge, void FEI3dLineLin :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->local2global(answer, lcoords, cellgeo); } double -FEI3dLineLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dLineLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->giveTransformationJacobian(lcoords, cellgeo); } -void -FEI3dLineLin :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI3dLineLin :: computeLocalEdgeMapping(int iedge) const { if ( iedge != 1 ) { OOFEM_ERROR("wrong edge number (%d)", iedge); } - edgeNodes = {1, 2}; + return {1, 2}; } void -FEI3dLineLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dLineLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("no surfaces available"); } double -FEI3dLineLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dLineLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("no surfaces available"); return 0.0; @@ -171,28 +171,29 @@ FEI3dLineLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArra void FEI3dLineLin :: surfaceLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("no surfaces available"); } double FEI3dLineLin :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + const FEICellGeometry &cellgeo) const { OOFEM_ERROR("no surfaces available"); return 0.0; } -void -FEI3dLineLin :: computeLocalSurfaceMapping(IntArray &surfNodes, int isurf) +IntArray +FEI3dLineLin :: computeLocalSurfaceMapping(int isurf) const { OOFEM_ERROR("no surfaces available"); + return {}; } void -FEI3dLineLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dLineLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const // Returns the jacobian matrix J (x,y,z)/(ksi,eta,dzeta) of the receiver. { ///@todo Not sure about this matrix @@ -200,20 +201,20 @@ FEI3dLineLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArr jacobianMatrix.at(1, 1) = 1.0; } -IntegrationRule * -FEI3dLineLin :: giveIntegrationRule(int order) +std::unique_ptr +FEI3dLineLin :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Line, order + 0); iRule->SetUpPointsOnLine(points, _Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule * -FEI3dLineLin :: giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr +FEI3dLineLin :: giveBoundaryIntegrationRule(int order, int boundary) const { ///@todo Not sure about this. OOFEM_ERROR("Not supported"); - return NULL; + return nullptr; } } // end namespace oofem diff --git a/src/oofemlib/fei3dlinelin.h b/src/oofemlib/fei3dlinelin.h index 26c1cad49..86bb74fe5 100644 --- a/src/oofemlib/fei3dlinelin.h +++ b/src/oofemlib/fei3dlinelin.h @@ -46,41 +46,40 @@ class OOFEM_EXPORT FEI3dLineLin : public FEInterpolation3d public: FEI3dLineLin() : FEInterpolation3d(1) { } - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Point; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _UnknownIntegrationDomain; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _UnknownIntegrationDomain; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Point; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _UnknownIntegrationDomain; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _UnknownIntegrationDomain; } - - virtual double giveVolume(const FEICellGeometry &cellgeo) const { return 0.0; } - virtual double giveLength(const FEICellGeometry &cellgeo) const; + double giveVolume(const FEICellGeometry &cellgeo) const override { return 0.; } + double giveLength(const FEICellGeometry &cellgeo) const; - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const override; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalEdgeMapping(int iedge) const override; - virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void computeLocalSurfaceMapping(IntArray &surfNodes, int isurf); + void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalSurfaceMapping(int isurf) const override; - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; - virtual int giveNumberOfNodes() const { return 2; } + int giveNumberOfNodes() const override { return 2; } - virtual IntegrationRule *giveIntegrationRule(int order); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary); + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; }; } // end namespace oofem #endif // fei3dlinelin_h diff --git a/src/oofemlib/fei3dquadlin.C b/src/oofemlib/fei3dquadlin.C new file mode 100644 index 000000000..df8c05176 --- /dev/null +++ b/src/oofemlib/fei3dquadlin.C @@ -0,0 +1,313 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "fei3dquadlin.h" + +#include "mathfem.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "gaussintegrationrule.h" +#include + +namespace oofem { +void +FEI3dQuadLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + this->surfaceEvalN(answer, 1, lcoords, cellgeo); +} + +double +FEI3dQuadLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + OOFEM_ERROR("FEI3dQuadLin :: evaldNdx - Not supported"); + return 0.; +} + + +void +FEI3dQuadLin :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + this->surfaceEvaldNdxi(answer, lcoords); +} + + +void +FEI3dQuadLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + FloatArray n; + this->evalN(n, lcoords, cellgeo); + answer.resize(0); + for ( int i = 1; i <= 4; ++i ) { + answer.add( n.at(i), cellgeo.giveVertexCoordinates(i) ); + } +} + +#define POINT_TOL 1.e-3 +int +FEI3dQuadLin :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const +{ + OOFEM_ERROR("FEI3dQuadLin :: global2local - Not supported"); + return -1; + +} + + +void +FEI3dQuadLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + OOFEM_ERROR("FEI3dQuadLin :: giveJacobianMatrixAt - Not supported"); +} + + +void +FEI3dQuadLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + double xi = lcoords.at(1); + answer.resize(2); + answer.at(1) = ( 1. - xi ) * 0.5; + answer.at(2) = ( 1. + xi ) * 0.5; +} + + + +void +FEI3dQuadLin :: edgeEvaldNdx(FloatMatrix &answer, int iedge, + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + OOFEM_ERROR("FEI3dQuadLin :: edgeEvaldNdx - Not supported"); +} + +void +FEI3dQuadLin :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + answer.resize(2); + answer(0) = -0.5; + answer(1) = 0.5; +} + +void +FEI3dQuadLin :: edgeLocal2global(FloatArray &answer, int iedge, + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + FloatArray N; + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); + this->edgeEvalN(N, iedge, lcoords, cellgeo); + + answer.resize(0); + for ( int i = 0; i < N.giveSize(); ++i ) { + answer.add( N[i], cellgeo.giveVertexCoordinates( edgeNodes[i] ) ); + } +} + + +double +FEI3dQuadLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); + ///@todo Implement this + OOFEM_ERROR("FEI3dQuadLin :: edgeGiveTransformationJacobian - Not supported"); + return -1; +} + + +IntArray +FEI3dQuadLin :: computeLocalEdgeMapping(int iedge) const +{ + if ( iedge == 1 ) { // edge between nodes 1 2 + return { 1, 2 }; + } else if ( iedge == 2 ) { // edge between nodes 2 3 + return { 2, 3 }; + } else if ( iedge == 3 ) { // edge between nodes 3 4 + return { 3, 4 }; + } else if ( iedge == 4 ) { // edge between nodes 4 1 + return { 4, 1 }; + } else { + throw std::range_error("invalid edge number"); + return {}; + } +} + +double +FEI3dQuadLin :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const +{ + ///@todo Implement this + OOFEM_ERROR("FEI3dQuadLin :: edgeComputeLength - Not supported"); + return -1; +} + +void +FEI3dQuadLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + double ksi = lcoords[0]; + double eta = lcoords[1]; + + answer.resize(4); + answer.at(1) = ( 1. + ksi ) * ( 1. + eta ) * 0.25; + answer.at(2) = ( 1. - ksi ) * ( 1. + eta ) * 0.25; + answer.at(3) = ( 1. - ksi ) * ( 1. - eta ) * 0.25; + answer.at(4) = ( 1. + ksi ) * ( 1. - eta ) * 0.25; +} + +void +FEI3dQuadLin :: surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) const +{ + const double ksi = lcoords[0]; + const double eta = lcoords[1]; + + answer.resize(4,2); + // dn/dxi + answer.at(1, 1) = 0.25 * ( 1. + eta ); + answer.at(2, 1) = -0.25 * ( 1. + eta ); + answer.at(3, 1) = -0.25 * ( 1. - eta ); + answer.at(4, 1) = 0.25 * ( 1. - eta ); + + // dn/deta + answer.at(1, 2) = 0.25 * ( 1. + ksi ); + answer.at(2, 2) = 0.25 * ( 1. - ksi ); + answer.at(3, 2) = -0.25 * ( 1. - ksi ); + answer.at(4, 2) = -0.25 * ( 1. + ksi ); +} + + + +void +FEI3dQuadLin :: surfaceLocal2global(FloatArray &answer, int isurf, + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + //Note: This gives the coordinate in the reference system + FloatArray N; + this->surfaceEvalN(N, isurf, lcoords, cellgeo); + + answer.resize(0); + for ( int i = 1; i <= N.giveSize(); ++i ) { + answer.add( N.at(i), cellgeo.giveVertexCoordinates(i) ); + } +} + +void +FEI3dQuadLin :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + ///@todo Implement this + OOFEM_ERROR("FEI3dQuadLin :: surfaceEvaldNdx - Not supported"); +} + +void +FEI3dQuadLin :: surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + // Note: These are not normalized. Returns the two tangent vectors to the surface. + FloatMatrix dNdxi; + this->surfaceEvaldNdxi(dNdxi, lcoords); + + G1.resize(0); + G2.resize(0); + for ( int i = 0; i < 4; ++i ) { + G1.add( dNdxi(i, 1), cellgeo.giveVertexCoordinates(i) ); + G2.add( dNdxi(i, 2), cellgeo.giveVertexCoordinates(i) ); + } +} + +double +FEI3dQuadLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + FloatArray G1, G2; // local curvilinear base vectors + this->surfaceEvalBaseVectorsAt(G1, G2, lcoords, cellgeo); + answer.beVectorProductOf(G1, G2); + double J = answer.computeNorm(); + answer.times(1 / J); + return J; +} + +void +FEI3dQuadLin :: surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + // Jacobian matrix consists of the three curvilinear base vectors. The third is taken as the normal to the surface. + // Note! The base vectors are not normalized except the third (normal) + FloatArray G1, G2, G3; + this->surfaceEvalBaseVectorsAt(G1, G2, lcoords, cellgeo); + G3.beVectorProductOf(G1, G2); + + jacobianMatrix.resize(3, 3); + jacobianMatrix.at(1, 1) = G1.at(1); + jacobianMatrix.at(1, 2) = G2.at(1); + jacobianMatrix.at(1, 3) = G3.at(1); + jacobianMatrix.at(2, 1) = G1.at(2); + jacobianMatrix.at(2, 2) = G2.at(2); + jacobianMatrix.at(2, 3) = G3.at(2); + jacobianMatrix.at(3, 1) = G1.at(3); + jacobianMatrix.at(3, 2) = G2.at(3); + jacobianMatrix.at(3, 3) = G3.at(3); +} + +double +FEI3dQuadLin :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const +{ + OOFEM_ERROR("FEI3dQuadLin :: surfaceGiveTransformationJacobian - Not supported yet"); + return 0; +} + +IntArray +FEI3dQuadLin :: computeLocalSurfaceMapping(int isurf) const +{ + //surfNodes.setValues(3, 1, 2, 3); + return computeLocalEdgeMapping(isurf); + +} + +std::unique_ptr +FEI3dQuadLin :: giveIntegrationRule(int order) const +{ + auto iRule = std::make_unique(1, nullptr); + int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order); + iRule->SetUpPointsOnSquare(points, _Unknown); + return std::move(iRule); +} + +std::unique_ptr +FEI3dQuadLin :: giveBoundaryIntegrationRule(int order, int boundary) const +{ + ///@todo Not sure about what defines boundaries on these elements. + OOFEM_ERROR("FEI3dQuadLin :: giveBoundaryIntegrationRule - Not supported"); + return nullptr; +} + + +double +FEI3dQuadLin :: giveArea(const FEICellGeometry &cellgeo) const +{ + ///@todo Not sure about what defines boundaries on these elements. + OOFEM_ERROR("FEI3dQuadLin :: giveArea - Not supported"); + return 0.; + +} +} // end namespace oofem diff --git a/src/oofemlib/fei3dquadlin.h b/src/oofemlib/fei3dquadlin.h new file mode 100644 index 000000000..035524892 --- /dev/null +++ b/src/oofemlib/fei3dquadlin.h @@ -0,0 +1,98 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef fei3dquadlin_h +#define fei3dquadlin_h + +#include "feinterpol3d.h" + +namespace oofem { +/** + * First order (linear) quad interpolation in 3D space (4 nodes). + * @todo This class is entirely unchecked. + */ +class OOFEM_EXPORT FEI3dQuadLin : public FEInterpolation3d +{ +public: + FEI3dQuadLin() : FEInterpolation3d(2) { } + + integrationDomain giveIntegrationDomain() const override { return _Square; } + Element_Geometry_Type giveGeometryType() const override { return EGT_quad_1_interface; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Line; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Square; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } + + // Bulk + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + + // Edge + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalEdgeMapping(int iedge) const override; + + int giveNumberOfEdges() const override { return 4; } + + // Surface + void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) const ; + + double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalSurfaceMapping(int iedge) const override; + void surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const ; + void surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const ; + + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; + double giveArea(const FEICellGeometry &cellgeo) const; + + int giveNumberOfNodes() const override { return 4; } + +protected: + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; + double computeVolume(const FEICellGeometry &cellgeo) const ; + +}; +} // end namespace oofem +#endif // fei3dquadlin_h diff --git a/src/oofemlib/fei3dtetlin.C b/src/oofemlib/fei3dtetlin.C index b2775f91b..f79f8c9d3 100644 --- a/src/oofemlib/fei3dtetlin.C +++ b/src/oofemlib/fei3dtetlin.C @@ -36,40 +36,107 @@ #include "mathfem.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "gaussintegrationrule.h" namespace oofem { + +FloatArrayF<4> +FEI3dTetLin :: evalN(const FloatArrayF<3> &lcoords) +{ + return { + lcoords[0], + lcoords[1], + lcoords[2], + 1.0 - lcoords[0] - lcoords[1] - lcoords[2] + }; +} + void -FEI3dTetLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + answer = evalN(lcoords); +#else answer.resize(4); answer.at(1) = lcoords.at(1); answer.at(2) = lcoords.at(2); answer.at(3) = lcoords.at(3); answer.at(4) = 1. - lcoords.at(1) - lcoords.at(2) - lcoords.at(3); +#endif +} + +std::pair> +FEI3dTetLin :: evaldNdx(const FEICellGeometry &cellgeo) +{ + //auto [x1, y1, z1] = cellgeo.giveVertexCoordinates(1); + //auto [x2, y2, z2] = cellgeo.giveVertexCoordinates(2); + //auto [x3, y3, z3] = cellgeo.giveVertexCoordinates(3); + //auto [x4, y4, z4] = cellgeo.giveVertexCoordinates(4); + + double x1 = cellgeo.giveVertexCoordinates(1).at(1); + double x2 = cellgeo.giveVertexCoordinates(2).at(1); + double x3 = cellgeo.giveVertexCoordinates(3).at(1); + double x4 = cellgeo.giveVertexCoordinates(4).at(1); + + double y1 = cellgeo.giveVertexCoordinates(1).at(2); + double y2 = cellgeo.giveVertexCoordinates(2).at(2); + double y3 = cellgeo.giveVertexCoordinates(3).at(2); + double y4 = cellgeo.giveVertexCoordinates(4).at(2); + + double z1 = cellgeo.giveVertexCoordinates(1).at(3); + double z2 = cellgeo.giveVertexCoordinates(2).at(3); + double z3 = cellgeo.giveVertexCoordinates(3).at(3); + double z4 = cellgeo.giveVertexCoordinates(4).at(3); + + double detJ = ( ( x4 - x1 ) * ( y2 - y1 ) * ( z3 - z1 ) - ( x4 - x1 ) * ( y3 - y1 ) * ( z2 - z1 ) + + ( x3 - x1 ) * ( y4 - y1 ) * ( z2 - z1 ) - ( x2 - x1 ) * ( y4 - y1 ) * ( z3 - z1 ) + + ( x2 - x1 ) * ( y3 - y1 ) * ( z4 - z1 ) - ( x3 - x1 ) * ( y2 - y1 ) * ( z4 - z1 ) ); + + FloatMatrixF<3,4> ans = { + -( ( y3 - y2 ) * ( z4 - z2 ) - ( y4 - y2 ) * ( z3 - z2 ) ), + -( ( x4 - x2 ) * ( z3 - z2 ) - ( x3 - x2 ) * ( z4 - z2 ) ), + -( ( x3 - x2 ) * ( y4 - y2 ) - ( x4 - x2 ) * ( y3 - y2 ) ), + ( y4 - y3 ) * ( z1 - z3 ) - ( y1 - y3 ) * ( z4 - z3 ), + ( x1 - x3 ) * ( z4 - z3 ) - ( x4 - x3 ) * ( z1 - z3 ), + ( x4 - x3 ) * ( y1 - y3 ) - ( x1 - x3 ) * ( y4 - y3 ), + -( ( y1 - y4 ) * ( z2 - z4 ) - ( y2 - y4 ) * ( z1 - z4 ) ), + -( ( x2 - x4 ) * ( z1 - z4 ) - ( x1 - x4 ) * ( z2 - z4 ) ), + -( ( x1 - x4 ) * ( y2 - y4 ) - ( x2 - x4 ) * ( y1 - y4 ) ), + ( y2 - y1 ) * ( z3 - z1 ) - ( y3 - y1 ) * ( z2 - z1 ), + ( x3 - x1 ) * ( z2 - z1 ) - ( x2 - x1 ) * ( z3 - z1 ), + ( x2 - x1 ) * ( y3 - y1 ) - ( x3 - x1 ) * ( y2 - y1 ), + }; + return {detJ, ans * (1. / detJ)}; } double -FEI3dTetLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + auto tmp = evaldNdx(lcoords, cellgeo); + answer = tmp.second; + return tmp.first; +#else double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4, detJ; answer.resize(4, 3); - x1 = cellgeo.giveVertexCoordinates(1)->at(1); - x2 = cellgeo.giveVertexCoordinates(2)->at(1); - x3 = cellgeo.giveVertexCoordinates(3)->at(1); - x4 = cellgeo.giveVertexCoordinates(4)->at(1); + x1 = cellgeo.giveVertexCoordinates(1).at(1); + x2 = cellgeo.giveVertexCoordinates(2).at(1); + x3 = cellgeo.giveVertexCoordinates(3).at(1); + x4 = cellgeo.giveVertexCoordinates(4).at(1); - y1 = cellgeo.giveVertexCoordinates(1)->at(2); - y2 = cellgeo.giveVertexCoordinates(2)->at(2); - y3 = cellgeo.giveVertexCoordinates(3)->at(2); - y4 = cellgeo.giveVertexCoordinates(4)->at(2); + y1 = cellgeo.giveVertexCoordinates(1).at(2); + y2 = cellgeo.giveVertexCoordinates(2).at(2); + y3 = cellgeo.giveVertexCoordinates(3).at(2); + y4 = cellgeo.giveVertexCoordinates(4).at(2); - z1 = cellgeo.giveVertexCoordinates(1)->at(3); - z2 = cellgeo.giveVertexCoordinates(2)->at(3); - z3 = cellgeo.giveVertexCoordinates(3)->at(3); - z4 = cellgeo.giveVertexCoordinates(4)->at(3); + z1 = cellgeo.giveVertexCoordinates(1).at(3); + z2 = cellgeo.giveVertexCoordinates(2).at(3); + z3 = cellgeo.giveVertexCoordinates(3).at(3); + z4 = cellgeo.giveVertexCoordinates(4).at(3); detJ = ( ( x4 - x1 ) * ( y2 - y1 ) * ( z3 - z1 ) - ( x4 - x1 ) * ( y3 - y1 ) * ( z2 - z1 ) + ( x3 - x1 ) * ( y4 - y1 ) * ( z2 - z1 ) - ( x2 - x1 ) * ( y4 - y1 ) * ( z3 - z1 ) + @@ -97,42 +164,43 @@ FEI3dTetLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FE answer.times(1. / detJ); return detJ; +#endif } void -FEI3dTetLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; this->evalN(n, lcoords, cellgeo); answer.clear(); for ( int i = 1; i <= 4; i++ ) { - answer.add( n.at(i), * cellgeo.giveVertexCoordinates(i) ); + answer.add( n.at(i), cellgeo.giveVertexCoordinates(i) ); } } #define POINT_TOL 1.e-3 int -FEI3dTetLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) +FEI3dTetLin :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) const { double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4, xp, yp, zp, volume; answer.resize(4); - x1 = cellgeo.giveVertexCoordinates(1)->at(1); - x2 = cellgeo.giveVertexCoordinates(2)->at(1); - x3 = cellgeo.giveVertexCoordinates(3)->at(1); - x4 = cellgeo.giveVertexCoordinates(4)->at(1); + x1 = cellgeo.giveVertexCoordinates(1).at(1); + x2 = cellgeo.giveVertexCoordinates(2).at(1); + x3 = cellgeo.giveVertexCoordinates(3).at(1); + x4 = cellgeo.giveVertexCoordinates(4).at(1); - y1 = cellgeo.giveVertexCoordinates(1)->at(2); - y2 = cellgeo.giveVertexCoordinates(2)->at(2); - y3 = cellgeo.giveVertexCoordinates(3)->at(2); - y4 = cellgeo.giveVertexCoordinates(4)->at(2); + y1 = cellgeo.giveVertexCoordinates(1).at(2); + y2 = cellgeo.giveVertexCoordinates(2).at(2); + y3 = cellgeo.giveVertexCoordinates(3).at(2); + y4 = cellgeo.giveVertexCoordinates(4).at(2); - z1 = cellgeo.giveVertexCoordinates(1)->at(3); - z2 = cellgeo.giveVertexCoordinates(2)->at(3); - z3 = cellgeo.giveVertexCoordinates(3)->at(3); - z4 = cellgeo.giveVertexCoordinates(4)->at(3); + z1 = cellgeo.giveVertexCoordinates(1).at(3); + z2 = cellgeo.giveVertexCoordinates(2).at(3); + z3 = cellgeo.giveVertexCoordinates(3).at(3); + z4 = cellgeo.giveVertexCoordinates(4).at(3); xp = coords.at(1); yp = coords.at(2); @@ -175,24 +243,24 @@ FEI3dTetLin :: global2local(FloatArray &answer, const FloatArray &coords, const double -FEI3dTetLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double detJ, x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4; - x1 = cellgeo.giveVertexCoordinates(1)->at(1); - x2 = cellgeo.giveVertexCoordinates(2)->at(1); - x3 = cellgeo.giveVertexCoordinates(3)->at(1); - x4 = cellgeo.giveVertexCoordinates(4)->at(1); + x1 = cellgeo.giveVertexCoordinates(1).at(1); + x2 = cellgeo.giveVertexCoordinates(2).at(1); + x3 = cellgeo.giveVertexCoordinates(3).at(1); + x4 = cellgeo.giveVertexCoordinates(4).at(1); - y1 = cellgeo.giveVertexCoordinates(1)->at(2); - y2 = cellgeo.giveVertexCoordinates(2)->at(2); - y3 = cellgeo.giveVertexCoordinates(3)->at(2); - y4 = cellgeo.giveVertexCoordinates(4)->at(2); + y1 = cellgeo.giveVertexCoordinates(1).at(2); + y2 = cellgeo.giveVertexCoordinates(2).at(2); + y3 = cellgeo.giveVertexCoordinates(3).at(2); + y4 = cellgeo.giveVertexCoordinates(4).at(2); - z1 = cellgeo.giveVertexCoordinates(1)->at(3); - z2 = cellgeo.giveVertexCoordinates(2)->at(3); - z3 = cellgeo.giveVertexCoordinates(3)->at(3); - z4 = cellgeo.giveVertexCoordinates(4)->at(3); + z1 = cellgeo.giveVertexCoordinates(1).at(3); + z2 = cellgeo.giveVertexCoordinates(2).at(3); + z3 = cellgeo.giveVertexCoordinates(3).at(3); + z4 = cellgeo.giveVertexCoordinates(4).at(3); detJ = ( ( x4 - x1 ) * ( y2 - y1 ) * ( z3 - z1 ) - ( x4 - x1 ) * ( y3 - y1 ) * ( z2 - z1 ) + ( x3 - x1 ) * ( y4 - y1 ) * ( z2 - z1 ) - ( x2 - x1 ) * ( y4 - y1 ) * ( z3 - z1 ) + @@ -203,7 +271,7 @@ FEI3dTetLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICe void -FEI3dTetLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); answer.resize(2); @@ -214,20 +282,18 @@ FEI3dTetLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoord void FEI3dTetLin :: edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double coeff, l, x1, x2, y1, y2, z1, z2; - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); - l = this->edgeComputeLength(edgeNodes, cellgeo); - coeff = 1.0 / l / l; - - x1 = cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(1); - y1 = cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(2); - z1 = cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(3); - x2 = cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(1); - y2 = cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(2); - z2 = cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(3); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); + double l = this->edgeComputeLength(edgeNodes, cellgeo); + double coeff = 1.0 / l / l; + + double x1 = cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(1); + double y1 = cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(2); + double z1 = cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(3); + double x2 = cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(1); + double y2 = cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(2); + double z2 = cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(3); answer.resize(2, 3); answer.at(1, 1) = ( x1 - x2 ) * coeff; @@ -241,72 +307,59 @@ FEI3dTetLin :: edgeEvaldNdx(FloatMatrix &answer, int iedge, void FEI3dTetLin :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; FloatArray n; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); this->edgeEvalN(n, iedge, lcoords, cellgeo); answer.resize(3); - answer.at(1) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(1) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(1) ); - answer.at(2) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(2) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(2) ); - answer.at(3) = ( n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) )->at(3) + - n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->at(3) ); + answer.at(1) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(1) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(1); + answer.at(2) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(2) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(2); + answer.at(3) = n.at(1) * cellgeo.giveVertexCoordinates( edgeNodes.at(1) ).at(3) + + n.at(2) * cellgeo.giveVertexCoordinates( edgeNodes.at(2) ).at(3); } double -FEI3dTetLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); return 0.5 * this->edgeComputeLength(edgeNodes, cellgeo); } -void -FEI3dTetLin :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI3dTetLin :: computeLocalEdgeMapping(int iedge) const { - int aNode = 0, bNode = 0; - edgeNodes.resize(2); - if ( iedge == 1 ) { // edge between nodes 1 2 - aNode = 1; - bNode = 2; + return {1, 2}; } else if ( iedge == 2 ) { // edge between nodes 2 3 - aNode = 2; - bNode = 3; + return {2, 3}; } else if ( iedge == 3 ) { // edge between nodes 3 1 - aNode = 3; - bNode = 1; + return {3, 1}; } else if ( iedge == 4 ) { // edge between nodes 1 4 - aNode = 1; - bNode = 4; + return {1, 4}; } else if ( iedge == 5 ) { // edge between nodes 2 4 - aNode = 2; - bNode = 4; + return {2, 4}; } else if ( iedge == 6 ) { // edge between nodes 3 4 - aNode = 3; - bNode = 4; + return {3, 4}; } else { - OOFEM_ERROR("wrong egde number (%d)", iedge); + throw std::range_error("invalid edge number"); + return {}; } - - edgeNodes.at(1) = ( aNode ); - edgeNodes.at(2) = ( bNode ); } double -FEI3dTetLin :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) +FEI3dTetLin :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const { - return cellgeo.giveVertexCoordinates( edgeNodes.at(2) )->distance( cellgeo.giveVertexCoordinates( edgeNodes.at(1) ) ); + return distance(cellgeo.giveVertexCoordinates( edgeNodes.at(2) ), cellgeo.giveVertexCoordinates( edgeNodes.at(1) )); } void -FEI3dTetLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(3); @@ -317,35 +370,31 @@ FEI3dTetLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lco void FEI3dTetLin :: surfaceLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double l1, l2, l3; + const auto &nodes = computeLocalSurfaceMapping(iedge); + + double l1 = lcoords.at(1); + double l2 = lcoords.at(2); + double l3 = 1.0 - l1 - l2; + answer.resize(3); - IntArray nodes(3); - - computeLocalSurfaceMapping(nodes, iedge); - - l1 = lcoords.at(1); - l2 = lcoords.at(2); - l3 = 1.0 - l1 - l2; - - answer.at(1) = ( l1 * cellgeo.giveVertexCoordinates( nodes.at(1) )->at(1) + - l2 * cellgeo.giveVertexCoordinates( nodes.at(2) )->at(1) + - l3 * cellgeo.giveVertexCoordinates( nodes.at(3) )->at(1) ); - answer.at(2) = ( l1 * cellgeo.giveVertexCoordinates( nodes.at(1) )->at(2) + - l2 * cellgeo.giveVertexCoordinates( nodes.at(2) )->at(2) + - l3 * cellgeo.giveVertexCoordinates( nodes.at(3) )->at(2) ); - answer.at(3) = ( l1 * cellgeo.giveVertexCoordinates( nodes.at(1) )->at(3) + - l2 * cellgeo.giveVertexCoordinates( nodes.at(2) )->at(3) + - l3 * cellgeo.giveVertexCoordinates( nodes.at(3) )->at(3) ); + answer.at(1) = l1 * cellgeo.giveVertexCoordinates( nodes.at(1) ).at(1) + + l2 * cellgeo.giveVertexCoordinates( nodes.at(2) ).at(1) + + l3 * cellgeo.giveVertexCoordinates( nodes.at(3) ).at(1); + answer.at(2) = l1 * cellgeo.giveVertexCoordinates( nodes.at(1) ).at(2) + + l2 * cellgeo.giveVertexCoordinates( nodes.at(2) ).at(2) + + l3 * cellgeo.giveVertexCoordinates( nodes.at(3) ).at(2); + answer.at(3) = l1 * cellgeo.giveVertexCoordinates( nodes.at(1) ).at(3) + + l2 * cellgeo.giveVertexCoordinates( nodes.at(2) ).at(3) + + l3 * cellgeo.giveVertexCoordinates( nodes.at(3) ).at(3); } void -FEI3dTetLin :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetLin :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // Note, this must be in correct order, not just the correct nodes, therefore we must use snodes; - IntArray snodes; - this->computeLocalSurfaceMapping(snodes, isurf); + const auto &snodes = this->computeLocalSurfaceMapping(isurf); FloatArray lcoords_tet(4); lcoords_tet.at(snodes.at(1)) = lcoords.at(1); @@ -363,14 +412,13 @@ FEI3dTetLin :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray } double -FEI3dTetLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FloatArray a, b; - IntArray snodes(3); - this->computeLocalSurfaceMapping(snodes, isurf); + const auto &snodes = this->computeLocalSurfaceMapping(isurf); - a.beDifferenceOf( * cellgeo.giveVertexCoordinates( snodes.at(2) ), * cellgeo.giveVertexCoordinates( snodes.at(1) ) ); - b.beDifferenceOf( * cellgeo.giveVertexCoordinates( snodes.at(3) ), * cellgeo.giveVertexCoordinates( snodes.at(1) ) ); + FloatArray a, b; + a.beDifferenceOf( cellgeo.giveVertexCoordinates( snodes.at(2) ), cellgeo.giveVertexCoordinates( snodes.at(1) ) ); + b.beDifferenceOf( cellgeo.giveVertexCoordinates( snodes.at(3) ), cellgeo.giveVertexCoordinates( snodes.at(1) ) ); answer.beVectorProductOf(a, b); return answer.normalize(); @@ -378,17 +426,16 @@ FEI3dTetLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray double FEI3dTetLin :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + const FEICellGeometry &cellgeo) const { FloatArray c; return this->surfaceEvalNormal(c, isurf, lcoords, cellgeo); } -void -FEI3dTetLin :: computeLocalSurfaceMapping(IntArray &surfNodes, int isurf) +IntArray +FEI3dTetLin :: computeLocalSurfaceMapping(int isurf) const { int aNode = 0, bNode = 0, cNode = 0; - surfNodes.resize(3); if ( isurf == 1 ) { // surface 1 - nodes 1 3 2 aNode = 1; @@ -410,41 +457,38 @@ FEI3dTetLin :: computeLocalSurfaceMapping(IntArray &surfNodes, int isurf) OOFEM_ERROR("wrong surface number (%d)", isurf); } - surfNodes.at(1) = ( aNode ); - surfNodes.at(2) = ( bNode ); - surfNodes.at(3) = ( cNode ); + return {aNode, bNode, cNode}; } double -FEI3dTetLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) +FEI3dTetLin :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const { - IntArray fNodes; - this->computeLocalSurfaceMapping(fNodes, iEdge); + auto fNodes = this->computeLocalSurfaceMapping(iEdge); - const FloatArray &c1 = * cellgeo.giveVertexCoordinates( fNodes.at(1) ); - const FloatArray &c2 = * cellgeo.giveVertexCoordinates( fNodes.at(2) ); - const FloatArray &c3 = * cellgeo.giveVertexCoordinates( fNodes.at(3) ); + const FloatArray &c1 = cellgeo.giveVertexCoordinates( fNodes.at(1) ); + const FloatArray &c2 = cellgeo.giveVertexCoordinates( fNodes.at(2) ); + const FloatArray &c3 = cellgeo.giveVertexCoordinates( fNodes.at(3) ); return ( ( c2.at(1) * c3.at(2) - c3.at(1) * c2.at(2) ) * c1.at(3) + ( c3.at(1) * c1.at(2) - c1.at(1) * c3.at(2) ) * c2.at(3) + ( c1.at(1) * c2.at(2) - c2.at(1) * c1.at(2) ) * c3.at(3) ) * 0.5; } -IntegrationRule * -FEI3dTetLin :: giveIntegrationRule(int order) +std::unique_ptr +FEI3dTetLin :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Tetrahedra, order + 0); iRule->SetUpPointsOnTetrahedra(points, _Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule * -FEI3dTetLin :: giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr +FEI3dTetLin :: giveBoundaryIntegrationRule(int order, int boundary) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, order + 0); iRule->SetUpPointsOnTriangle(points, _Unknown); - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei3dtetlin.h b/src/oofemlib/fei3dtetlin.h index 0acd95c0c..b85d8b0d6 100644 --- a/src/oofemlib/fei3dtetlin.h +++ b/src/oofemlib/fei3dtetlin.h @@ -46,48 +46,45 @@ class OOFEM_EXPORT FEI3dTetLin : public FEInterpolation3d public: FEI3dTetLin() : FEInterpolation3d(1) { } - virtual integrationDomain giveIntegrationDomain() const { return _Tetrahedra; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_tetra_1; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Triangle; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Triangle; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Tetrahedra; } + Element_Geometry_Type giveGeometryType() const override { return EGT_tetra_1; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Triangle; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Triangle; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int giveNumberOfNodes() const { return 4; } + static FloatArrayF<4> evalN(const FloatArrayF<3> &lcoords); + static std::pair> evaldNdx(const FEICellGeometry &cellgeo); + + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int giveNumberOfNodes() const override { return 4; } + void giveCellDofMans(IntArray& nodes, Element* elem) const override {nodes={1,2,3,4};} // Edge - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalEdgeMapping(int iedge) const override; // Surface - virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceEvaldNdx(FloatMatrix &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceEvalNormal(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalSurfaceMapping(IntArray &edgeNodes, int iedge); - virtual double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo); + void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalSurfaceMapping(int iedge) const override; + double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const override; - virtual IntegrationRule *giveIntegrationRule(int order); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary); + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; }; } // end namespace oofem #endif // fei3dtetlin_h diff --git a/src/oofemlib/fei3dtetquad.C b/src/oofemlib/fei3dtetquad.C index ff163912a..53df56d89 100644 --- a/src/oofemlib/fei3dtetquad.C +++ b/src/oofemlib/fei3dtetquad.C @@ -36,6 +36,8 @@ #include "mathfem.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "gaussintegrationrule.h" namespace oofem { @@ -48,25 +50,25 @@ FEI3dTetQuad :: giveVolume(const FEICellGeometry &cellgeo) const double y1, y2, y3, y4; //, y5, y6, y7, y8, y9, y10; double z1, z2, z3, z4; //, z5, z6, z7, z8, z9, z10; - x1 = cellgeo.giveVertexCoordinates(1)->at(1); - y1 = cellgeo.giveVertexCoordinates(1)->at(2); - z1 = cellgeo.giveVertexCoordinates(1)->at(3); - x2 = cellgeo.giveVertexCoordinates(2)->at(1); - y2 = cellgeo.giveVertexCoordinates(2)->at(2); - z2 = cellgeo.giveVertexCoordinates(2)->at(3); - x3 = cellgeo.giveVertexCoordinates(3)->at(1); - y3 = cellgeo.giveVertexCoordinates(3)->at(2); - z3 = cellgeo.giveVertexCoordinates(3)->at(3); - x4 = cellgeo.giveVertexCoordinates(4)->at(1); - y4 = cellgeo.giveVertexCoordinates(4)->at(2); - z4 = cellgeo.giveVertexCoordinates(4)->at(3); + x1 = cellgeo.giveVertexCoordinates(1).at(1); + y1 = cellgeo.giveVertexCoordinates(1).at(2); + z1 = cellgeo.giveVertexCoordinates(1).at(3); + x2 = cellgeo.giveVertexCoordinates(2).at(1); + y2 = cellgeo.giveVertexCoordinates(2).at(2); + z2 = cellgeo.giveVertexCoordinates(2).at(3); + x3 = cellgeo.giveVertexCoordinates(3).at(1); + y3 = cellgeo.giveVertexCoordinates(3).at(2); + z3 = cellgeo.giveVertexCoordinates(3).at(3); + x4 = cellgeo.giveVertexCoordinates(4).at(1); + y4 = cellgeo.giveVertexCoordinates(4).at(2); + z4 = cellgeo.giveVertexCoordinates(4).at(3); #if 0 - x5=cellgeo.giveVertexCoordinates(5)->at(1); y5=cellgeo.giveVertexCoordinates(5)->at(2); z5=cellgeo.giveVertexCoordinates(5)->at(3); - x6=cellgeo.giveVertexCoordinates(6)->at(1); y6=cellgeo.giveVertexCoordinates(6)->at(2); z6=cellgeo.giveVertexCoordinates(6)->at(3); - x7=cellgeo.giveVertexCoordinates(7)->at(1); y7=cellgeo.giveVertexCoordinates(7)->at(2); z7=cellgeo.giveVertexCoordinates(7)->at(3); - x8=cellgeo.giveVertexCoordinates(8)->at(1); y8=cellgeo.giveVertexCoordinates(8)->at(2); z8=cellgeo.giveVertexCoordinates(8)->at(3); - x9=cellgeo.giveVertexCoordinates(9)->at(1); y9=cellgeo.giveVertexCoordinates(9)->at(2); z9=cellgeo.giveVertexCoordinates(9)->at(3); - x10=cellgeo.giveVertexCoordinates(10)->at(1); y10=cellgeo.giveVertexCoordinates(10)->at(2); z10=cellgeo.giveVertexCoordinates(10)->at(3); + x5=cellgeo.giveVertexCoordinates(5).at(1); y5=cellgeo.giveVertexCoordinates(5).at(2); z5=cellgeo.giveVertexCoordinates(5).at(3); + x6=cellgeo.giveVertexCoordinates(6).at(1); y6=cellgeo.giveVertexCoordinates(6).at(2); z6=cellgeo.giveVertexCoordinates(6).at(3); + x7=cellgeo.giveVertexCoordinates(7).at(1); y7=cellgeo.giveVertexCoordinates(7).at(2); z7=cellgeo.giveVertexCoordinates(7).at(3); + x8=cellgeo.giveVertexCoordinates(8).at(1); y8=cellgeo.giveVertexCoordinates(8).at(2); z8=cellgeo.giveVertexCoordinates(8).at(3); + x9=cellgeo.giveVertexCoordinates(9).at(1); y9=cellgeo.giveVertexCoordinates(9).at(2); z9=cellgeo.giveVertexCoordinates(9).at(3); + x10=cellgeo.giveVertexCoordinates(10).at(1); y10=cellgeo.giveVertexCoordinates(10).at(2); z10=cellgeo.giveVertexCoordinates(10).at(3); double area = x1*y3*z2 - x1*y2*z3 + x2*y1*z3 - x2*y3*z1 - x3*y1*z2 + x3*y2*z1 + x1*y2*z4 - x1*y4*z2 - x2*y1*z4 + x2*y4*z1 + x4*y1*z2 - x4*y2*z1 - x1*y3*z4 + x1*y4*z3 + x3*y1*z4 - x3*y4*z1 - x4*y1*z3 + x4*y3*z1 - 2*x1*y2*z6 + 2*x1*y3*z5 - 2*x1*y5*z3 + 2*x1*y6*z2 + 2*x2*y1*z6 + x2*y3*z4 - x2*y4*z3 - 2*x2*y6*z1 - 2*x3*y1*z5 - x3*y2*z4 @@ -121,50 +123,141 @@ FEI3dTetQuad :: giveVolume(const FEICellGeometry &cellgeo) const return area; } +FloatArrayF<10> +FEI3dTetQuad :: evalN(const FloatArrayF<3> &lcoords) +{ + //auto [x1,x2,x3] = lcoords; + double x1 = lcoords[0]; + double x2 = lcoords[1]; + double x3 = lcoords[2]; + double x4 = 1.0 - x1 - x2 - x3; + + return { + x1 * ( 2 * x1 - 1 ), + x2 * ( 2 * x2 - 1 ), + x3 * ( 2 * x3 - 1 ), + x4 * ( 2 * x4 - 1 ), + 4 * x1 * x2, + 4 * x2 * x3, + 4 * x3 * x1, + 4 * x1 * x4, + 4 * x2 * x4, + 4 * x3 * x4 + }; +} + void -FEI3dTetQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double x1 = lcoords(0); - double x2 = lcoords(1); - double x3 = lcoords(2); +#if 0 + answer = evalN(lcoords); +#else + double x1 = lcoords[0]; + double x2 = lcoords[1]; + double x3 = lcoords[2]; double x4 = 1.0 - x1 - x2 - x3; answer.resize(10); - answer(0) = x1 * ( 2 * x1 - 1 ); - answer(1) = x2 * ( 2 * x2 - 1 ); - answer(2) = x3 * ( 2 * x3 - 1 ); - answer(3) = x4 * ( 2 * x4 - 1 ); - - answer(4) = 4 * x1 * x2; - answer(5) = 4 * x2 * x3; - answer(6) = 4 * x3 * x1; - answer(7) = 4 * x1 * x4; - answer(8) = 4 * x2 * x4; - answer(9) = 4 * x3 * x4; + answer[0] = x1 * ( 2 * x1 - 1 ); + answer[1] = x2 * ( 2 * x2 - 1 ); + answer[2] = x3 * ( 2 * x3 - 1 ); + answer[3] = x4 * ( 2 * x4 - 1 ); + + answer[4] = 4 * x1 * x2; + answer[5] = 4 * x2 * x3; + answer[6] = 4 * x3 * x1; + answer[7] = 4 * x1 * x4; + answer[8] = 4 * x2 * x4; + answer[9] = 4 * x3 * x4; +#endif +} + +std::pair> +FEI3dTetQuad :: evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo) +{ + auto dNduvw = evaldNdxi(lcoords); + FloatMatrixF<3,10> coords; + for ( int i = 0; i < 10; i++ ) { + ///@todo cellgeo should give a FloatArrayF<3>, this will add a "costly" construction now: + coords.setColumn(cellgeo.giveVertexCoordinates(i+1), i); + } + auto jacT = dotT(dNduvw, coords); + return {det(jacT), dot(inv(jacT), dNduvw)}; } double -FEI3dTetQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { +#if 0 + auto tmp = evaldNdx(lcoords, cellgeo); + answer = tmp.second; + return tmp.first; +#else FloatMatrix jacobianMatrix, inv, dNduvw, coords; this->evaldNdxi(dNduvw, lcoords, cellgeo); coords.resize( 3, dNduvw.giveNumberOfRows() ); for ( int i = 1; i <= dNduvw.giveNumberOfRows(); i++ ) { - coords.setColumn(* cellgeo.giveVertexCoordinates(i), i); + coords.setColumn(cellgeo.giveVertexCoordinates(i), i); } jacobianMatrix.beProductOf(coords, dNduvw); inv.beInverseOf(jacobianMatrix); answer.beProductOf(dNduvw, inv); return jacobianMatrix.giveDeterminant(); +#endif +} + +FloatMatrixF<3,10> +FEI3dTetQuad :: evaldNdxi(const FloatArrayF<3> &lcoords) +{ + double x1 = lcoords[0]; + double x2 = lcoords[1]; + double x3 = lcoords[2]; + double x4 = 1.0 - x1 - x2 - x3; + + return { + 4. * x1 - 1, // 1 + 0., + 0., + 0., // 2 + 4. * x2 - 1, + 0., + 0., // 3 + 0., + 4. * x3 - 1, + -4. * x4 + 1, // 4 + -4. * x4 + 1, + -4. * x4 + 1, + 4. * x2, // 5 + 4. * x1, + 0., + 0., // 6 + 4. * x3, + 4. * x2, + 4. * x3, // 7 + 0., + 4. * x1, + 4. * ( x4 - x1 ), // 8 + -4. * x1, + -4. * x1, + -4. * x2, // 9 + 4. * ( x4 - x2 ), + -4. * x2, + -4. * x3, // 10 + -4. * x3, + 4. * ( x4 - x3 ) + }; } void -FEI3dTetQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords , const FEICellGeometry &cellgeo) +FEI3dTetQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords , const FEICellGeometry &cellgeo) const { - double x1 = lcoords(0); - double x2 = lcoords(1); - double x3 = lcoords(2); +#if 0 + answer = evaldNdxi(lcoords); +#else + double x1 = lcoords[0]; + double x2 = lcoords[1]; + double x3 = lcoords[2]; double x4 = 1.0 - x1 - x2 - x3; answer.resize(10, 3); @@ -204,24 +297,25 @@ FEI3dTetQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords , const answer(7, 2) = -4 * x1; answer(8, 2) = -4 * x2; answer(9, 2) = 4 * ( x4 - x3 ); +#endif } void -FEI3dTetQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray N; this->evalN(N, lcoords, cellgeo); answer.clear(); for ( int i = 1; i <= N.giveSize(); i++ ) { - answer.add( N.at(i), * cellgeo.giveVertexCoordinates(i) ); + answer.add( N.at(i), cellgeo.giveVertexCoordinates(i) ); } } #define POINT_TOL 1e-6 int -FEI3dTetQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) +FEI3dTetQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const { FloatArray res, delta, guess, lcoords_guess; FloatMatrix jac; @@ -260,23 +354,23 @@ FEI3dTetQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, cons } answer.resize(4); - answer(0) = lcoords_guess(0); - answer(1) = lcoords_guess(1); - answer(2) = lcoords_guess(2); + answer[0] = lcoords_guess[0]; + answer[1] = lcoords_guess[1]; + answer[2] = lcoords_guess[2]; bool inside = true; for ( int i = 0; i < 3; i++ ) { - if ( answer(i) < ( 0. - POINT_TOL ) ) { - answer(i) = 0.; + if ( answer[i] < ( 0. - POINT_TOL ) ) { + answer[i] = 0.; inside = false; - } else if ( answer(i) > ( 1. + POINT_TOL ) ) { - answer(i) = 1.; + } else if ( answer[i] > ( 1. + POINT_TOL ) ) { + answer[i] = 1.; inside = false; } } - answer(3) = 1.0 - answer(0) - answer(1) - answer(2); // Do this afterwards, since it might get clamped. - if ( answer(3) < 0. - POINT_TOL ) { + answer[3] = 1.0 - answer[0] - answer[1] - answer[2]; // Do this afterwards, since it might get clamped. + if ( answer[3] < 0. - POINT_TOL ) { return false; } return inside; @@ -286,106 +380,90 @@ FEI3dTetQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, cons double FEI3dTetQuad :: giveCharacteristicLength(const FEICellGeometry &cellgeo) const { - return cellgeo.giveVertexCoordinates(1)->distance( cellgeo.giveVertexCoordinates(2) ); + return distance(cellgeo.giveVertexCoordinates(1), cellgeo.giveVertexCoordinates(2)); } void -FEI3dTetQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatMatrix dNduvw, coords; this->evaldNdxi(dNduvw, lcoords, cellgeo); coords.resize( 3, dNduvw.giveNumberOfRows() ); for ( int i = 1; i <= dNduvw.giveNumberOfRows(); i++ ) { - coords.setColumn(* cellgeo.giveVertexCoordinates(i), i); + coords.setColumn(cellgeo.giveVertexCoordinates(i), i); } jacobianMatrix.beProductOf(coords, dNduvw); } void -FEI3dTetQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double xi = lcoords.at(1); + double xi = lcoords[0]; answer.resize(3); - answer(0) = 0.5 * ( xi - 1.0 ) * xi; - answer(1) = 0.5 * ( xi + 1.0 ) * xi; - answer(2) = 1.0 - xi * xi; + answer[0] = 0.5 * ( xi - 1.0 ) * xi; + answer[1] = 0.5 * ( xi + 1.0 ) * xi; + answer[2] = 1.0 - xi * xi; } void FEI3dTetQuad :: edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); ///@todo Implement this OOFEM_ERROR("Not supported"); } void FEI3dTetQuad :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; FloatArray N; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); this->edgeEvalN(N, iedge, lcoords, cellgeo); answer.clear(); for ( int i = 0; i < N.giveSize(); ++i ) { - answer.add( N(i), * cellgeo.giveVertexCoordinates( edgeNodes(i) ) ); + answer.add( N[i], cellgeo.giveVertexCoordinates( edgeNodes[i] ) ); } } double -FEI3dTetQuad :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetQuad :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); ///@todo Implement this OOFEM_ERROR("Not supported"); return -1; } -void -FEI3dTetQuad :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI3dTetQuad :: computeLocalEdgeMapping(int iedge) const { - edgeNodes.resize(3); - if ( iedge == 1 ) { // edge between nodes 1 2 - edgeNodes(0) = 1; - edgeNodes(1) = 2; - edgeNodes(2) = 5; + return {1, 2, 5}; } else if ( iedge == 2 ) { // edge between nodes 2 3 - edgeNodes(0) = 2; - edgeNodes(1) = 3; - edgeNodes(2) = 6; + return {2, 3, 6}; } else if ( iedge == 3 ) { // edge between nodes 3 1 - edgeNodes(0) = 3; - edgeNodes(1) = 1; - edgeNodes(2) = 7; + return {3, 1, 7}; } else if ( iedge == 4 ) { // edge between nodes 1 4 - edgeNodes(0) = 1; - edgeNodes(1) = 4; - edgeNodes(2) = 8; + return {1, 4, 8}; } else if ( iedge == 5 ) { // edge between nodes 2 4 - edgeNodes(0) = 2; - edgeNodes(1) = 4; - edgeNodes(2) = 9; + return {2, 4, 9}; } else if ( iedge == 6 ) { // edge between nodes 3 4 - edgeNodes(0) = 3; - edgeNodes(1) = 4; - edgeNodes(2) = 10; + return {3, 4, 10}; } else { - OOFEM_ERROR("wrong edge number (%d)", iedge); + throw std::range_error("invalid edge number"); + return {}; } } double -FEI3dTetQuad :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) +FEI3dTetQuad :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const { ///@todo Implement this OOFEM_ERROR("Not supported"); @@ -393,10 +471,10 @@ FEI3dTetQuad :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &ce } void -FEI3dTetQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - double l1 = lcoords.at(1); - double l2 = lcoords.at(2); + double l1 = lcoords[0]; + double l2 = lcoords[1]; double l3 = 1. - l1 - l2; answer.resize(6); @@ -411,24 +489,22 @@ FEI3dTetQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lc void FEI3dTetQuad :: surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray nodes; FloatArray N; - this->computeLocalSurfaceMapping(nodes, isurf); + const auto &nodes = this->computeLocalSurfaceMapping(isurf); this->surfaceEvalN(N, isurf, lcoords, cellgeo); answer.clear(); for ( int i = 0; i < N.giveSize(); ++i ) { - answer.add( N(i), * cellgeo.giveVertexCoordinates( nodes(i) ) ); + answer.add( N[i], cellgeo.giveVertexCoordinates( nodes[i] ) ); } } void -FEI3dTetQuad :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetQuad :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray snodes; - this->computeLocalSurfaceMapping(snodes, isurf); + const auto &snodes = this->computeLocalSurfaceMapping(isurf); FloatArray lcoords_tet(4); lcoords_tet.at(snodes.at(1)) = lcoords.at(1); @@ -446,11 +522,10 @@ FEI3dTetQuad :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray } double -FEI3dTetQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTetQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray snodes(3); FloatArray a, b; - this->computeLocalSurfaceMapping(snodes, isurf); + const auto &snodes = this->computeLocalSurfaceMapping(isurf); double l1, l2, l3; l1 = lcoords.at(1); @@ -459,23 +534,23 @@ FEI3dTetQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArra FloatArray dNdxi(6), dNdeta(6); - dNdxi(0) = 4.0 * l1 - 1.0; - dNdxi(1) = 0.0; - dNdxi(2) = -1.0 * ( 4.0 * l3 - 1.0 ); - dNdxi(3) = 4.0 * l2; - dNdxi(4) = -4.0 * l2; - dNdxi(5) = 4.0 * l3 - 4.0 * l1; + dNdxi[0] = 4.0 * l1 - 1.0; + dNdxi[1] = 0.0; + dNdxi[2] = -1.0 * ( 4.0 * l3 - 1.0 ); + dNdxi[3] = 4.0 * l2; + dNdxi[4] = -4.0 * l2; + dNdxi[5] = 4.0 * l3 - 4.0 * l1; - dNdeta(0) = 0.0; - dNdeta(1) = 4.0 * l2 - 1.0; - dNdeta(2) = -1.0 * ( 4.0 * l3 - 1.0 ); - dNdeta(3) = 4.0 * l1; - dNdeta(4) = 4.0 * l3 - 4.0 * l2; - dNdeta(5) = -4.0 * l1; + dNdeta[0] = 0.0; + dNdeta[1] = 4.0 * l2 - 1.0; + dNdeta[2] = -1.0 * ( 4.0 * l3 - 1.0 ); + dNdeta[3] = 4.0 * l1; + dNdeta[4] = 4.0 * l3 - 4.0 * l2; + dNdeta[5] = -4.0 * l1; for ( int i = 0; i < 6; ++i ) { - a.add( dNdxi(i), * cellgeo.giveVertexCoordinates( snodes(i) ) ); - b.add( dNdeta(i), * cellgeo.giveVertexCoordinates( snodes(i) ) ); + a.add( dNdxi[i], cellgeo.giveVertexCoordinates( snodes[i] ) ); + b.add( dNdeta[i], cellgeo.giveVertexCoordinates( snodes[i] ) ); } answer.beVectorProductOf(a, b); return answer.normalize(); @@ -483,17 +558,16 @@ FEI3dTetQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArra double FEI3dTetQuad :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + const FEICellGeometry &cellgeo) const { FloatArray normal; return this->surfaceEvalNormal(normal, isurf, lcoords, cellgeo); } -void -FEI3dTetQuad :: computeLocalSurfaceMapping(IntArray &surfNodes, int isurf) +IntArray +FEI3dTetQuad :: computeLocalSurfaceMapping(int isurf) const { int aNode = 0, bNode = 0, cNode = 0, dNode = 0, eNode = 0, fNode = 0; - surfNodes.resize(6); if ( isurf == 1 ) { aNode = 1; @@ -527,76 +601,77 @@ FEI3dTetQuad :: computeLocalSurfaceMapping(IntArray &surfNodes, int isurf) OOFEM_ERROR("wrong surface number (%d)", isurf); } - surfNodes.at(1) = aNode; - surfNodes.at(2) = bNode; - surfNodes.at(3) = cNode; - surfNodes.at(4) = dNode; - surfNodes.at(5) = eNode; - surfNodes.at(6) = fNode; + return { + aNode, + bNode, + cNode, + dNode, + eNode, + fNode, + }; } -double FEI3dTetQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) +double FEI3dTetQuad :: evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const { - IntArray fNodes; - this->computeLocalSurfaceMapping(fNodes, iEdge); + const auto &fNodes = this->computeLocalSurfaceMapping(iEdge); - const FloatArray &c1 = * cellgeo.giveVertexCoordinates( fNodes.at(1) ); - const FloatArray &c2 = * cellgeo.giveVertexCoordinates( fNodes.at(2) ); - const FloatArray &c3 = * cellgeo.giveVertexCoordinates( fNodes.at(3) ); - const FloatArray &c4 = * cellgeo.giveVertexCoordinates( fNodes.at(4) ); - const FloatArray &c5 = * cellgeo.giveVertexCoordinates( fNodes.at(5) ); - const FloatArray &c6 = * cellgeo.giveVertexCoordinates( fNodes.at(6) ); + const auto &c1 = cellgeo.giveVertexCoordinates( fNodes.at(1) ); + const auto &c2 = cellgeo.giveVertexCoordinates( fNodes.at(2) ); + const auto &c3 = cellgeo.giveVertexCoordinates( fNodes.at(3) ); + const auto &c4 = cellgeo.giveVertexCoordinates( fNodes.at(4) ); + const auto &c5 = cellgeo.giveVertexCoordinates( fNodes.at(5) ); + const auto &c6 = cellgeo.giveVertexCoordinates( fNodes.at(6) ); // Expression derived in Mathematica: return ( - c1(2) * ( c2(1) * ( -2 * c3(0) - 3 * c4(0) + 5 * c5(0) + 5 * c6(0) ) + - c3(1) * ( 2 * c2(0) - 5 * c4(0) - 5 * c5(0) + 3 * c6(0) ) + - c4(1) * ( 3 * c2(0) + 5 * c3(0) - 4 * c5(0) - 24 * c6(0) ) + - c5(1) * ( -5 * c2(0) + 5 * c3(0) + 4 * c4(0) - 4 * c6(0) ) + - c6(1) * ( -5 * c2(0) - 3 * c3(0) + 24 * c4(0) + 4 * c5(0) ) ) + - c2(2) * ( c1(1) * ( 2 * c3(0) + 3 * c4(0) - 5 * c5(0) - 5 * c6(0) ) + - c3(1) * ( -2 * c1(0) + 5 * c4(0) - 3 * c5(0) + 5 * c6(0) ) + - c4(1) * ( -3 * c1(0) - 5 * c3(0) + 24 * c5(0) + 4 * c6(0) ) + - c5(1) * ( 5 * c1(0) + 3 * c3(0) - 24 * c4(0) - 4 * c6(0) ) + - c6(1) * ( 5 * c1(0) - 5 * c3(0) - 4 * c4(0) + 4 * c5(0) ) ) + - c3(2) * ( c1(1) * ( -2 * c2(0) + 5 * c4(0) + 5 * c5(0) - 3 * c6(0) ) + - c2(1) * ( 2 * c1(0) - 5 * c4(0) + 3 * c5(0) - 5 * c6(0) ) + - c4(1) * ( -5 * c1(0) + 5 * c2(0) - 4 * c5(0) + 4 * c6(0) ) + - c5(1) * ( -5 * c1(0) - 3 * c2(0) + 4 * c4(0) + 24 * c6(0) ) + - c6(1) * ( 3 * c1(0) + 5 * c2(0) - 4 * c4(0) - 24 * c5(0) ) ) + - c4(2) * ( c1(1) * ( -3 * c2(0) - 5 * c3(0) + 4 * c5(0) + 24 * c6(0) ) + - c2(1) * ( 3 * c1(0) + 5 * c3(0) - 24 * c5(0) - 4 * c6(0) ) + - c3(1) * ( 5 * c1(0) - 5 * c2(0) + 4 * c5(0) - 4 * c6(0) ) + - c5(1) * ( -4 * c1(0) + 24 * c2(0) - 4 * c3(0) - 16 * c6(0) ) + - c6(1) * ( -24 * c1(0) + 4 * c2(0) + 4 * c3(0) + 16 * c5(0) ) ) + - c5(2) * ( c1(1) * ( 5 * c2(0) - 5 * c3(0) - 4 * c4(0) + 4 * c6(0) ) + - c2(1) * ( -5 * c1(0) - 3 * c3(0) + 24 * c4(0) + 4 * c6(0) ) + - c3(1) * ( 5 * c1(0) + 3 * c2(0) - 4 * c4(0) - 24 * c6(0) ) + - c4(1) * ( 4 * c1(0) - 24 * c2(0) + 4 * c3(0) + 16 * c6(0) ) + - c6(1) * ( -4 * c1(0) - 4 * c2(0) + 24 * c3(0) - 16 * c4(0) ) ) + - c6(2) * ( c1(1) * ( 5 * c2(0) + 3 * c3(0) - 24 * c4(0) - 4 * c5(0) ) + - c2(1) * ( -5 * c1(0) + 5 * c3(0) + 4 * c4(0) - 4 * c5(0) ) + - c3(1) * ( -3 * c1(0) - 5 * c2(0) + 4 * c4(0) + 24 * c5(0) ) + - c4(1) * ( 24 * c1(0) - 4 * c2(0) - 4 * c3(0) - 16 * c5(0) ) + - c5(1) * ( 4 * c1(0) + 4 * c2(0) - 24 * c3(0) + 16 * c4(0) ) ) + c1[2] * ( c2[1] * ( -2 * c3[0] - 3 * c4[0] + 5 * c5[0] + 5 * c6[0] ) + + c3[1] * ( 2 * c2[0] - 5 * c4[0] - 5 * c5[0] + 3 * c6[0] ) + + c4[1] * ( 3 * c2[0] + 5 * c3[0] - 4 * c5[0] - 24 * c6[0] ) + + c5[1] * ( -5 * c2[0] + 5 * c3[0] + 4 * c4[0] - 4 * c6[0] ) + + c6[1] * ( -5 * c2[0] - 3 * c3[0] + 24 * c4[0] + 4 * c5[0] ) ) + + c2[2] * ( c1[1] * ( 2 * c3[0] + 3 * c4[0] - 5 * c5[0] - 5 * c6[0] ) + + c3[1] * ( -2 * c1[0] + 5 * c4[0] - 3 * c5[0] + 5 * c6[0] ) + + c4[1] * ( -3 * c1[0] - 5 * c3[0] + 24 * c5[0] + 4 * c6[0] ) + + c5[1] * ( 5 * c1[0] + 3 * c3[0] - 24 * c4[0] - 4 * c6[0] ) + + c6[1] * ( 5 * c1[0] - 5 * c3[0] - 4 * c4[0] + 4 * c5[0] ) ) + + c3[2] * ( c1[1] * ( -2 * c2[0] + 5 * c4[0] + 5 * c5[0] - 3 * c6[0] ) + + c2[1] * ( 2 * c1[0] - 5 * c4[0] + 3 * c5[0] - 5 * c6[0] ) + + c4[1] * ( -5 * c1[0] + 5 * c2[0] - 4 * c5[0] + 4 * c6[0] ) + + c5[1] * ( -5 * c1[0] - 3 * c2[0] + 4 * c4[0] + 24 * c6[0] ) + + c6[1] * ( 3 * c1[0] + 5 * c2[0] - 4 * c4[0] - 24 * c5[0] ) ) + + c4[2] * ( c1[1] * ( -3 * c2[0] - 5 * c3[0] + 4 * c5[0] + 24 * c6[0] ) + + c2[1] * ( 3 * c1[0] + 5 * c3[0] - 24 * c5[0] - 4 * c6[0] ) + + c3[1] * ( 5 * c1[0] - 5 * c2[0] + 4 * c5[0] - 4 * c6[0] ) + + c5[1] * ( -4 * c1[0] + 24 * c2[0] - 4 * c3[0] - 16 * c6[0] ) + + c6[1] * ( -24 * c1[0] + 4 * c2[0] + 4 * c3[0] + 16 * c5[0] ) ) + + c5[2] * ( c1[1] * ( 5 * c2[0] - 5 * c3[0] - 4 * c4[0] + 4 * c6[0] ) + + c2[1] * ( -5 * c1[0] - 3 * c3[0] + 24 * c4[0] + 4 * c6[0] ) + + c3[1] * ( 5 * c1[0] + 3 * c2[0] - 4 * c4[0] - 24 * c6[0] ) + + c4[1] * ( 4 * c1[0] - 24 * c2[0] + 4 * c3[0] + 16 * c6[0] ) + + c6[1] * ( -4 * c1[0] - 4 * c2[0] + 24 * c3[0] - 16 * c4[0] ) ) + + c6[2] * ( c1[1] * ( 5 * c2[0] + 3 * c3[0] - 24 * c4[0] - 4 * c5[0] ) + + c2[1] * ( -5 * c1[0] + 5 * c3[0] + 4 * c4[0] - 4 * c5[0] ) + + c3[1] * ( -3 * c1[0] - 5 * c2[0] + 4 * c4[0] + 24 * c5[0] ) + + c4[1] * ( 24 * c1[0] - 4 * c2[0] - 4 * c3[0] - 16 * c5[0] ) + + c5[1] * ( 4 * c1[0] + 4 * c2[0] - 24 * c3[0] + 16 * c4[0] ) ) ) / 30.; } -IntegrationRule * -FEI3dTetQuad :: giveIntegrationRule(int order) +std::unique_ptr +FEI3dTetQuad :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Tetrahedra, order + 3); iRule->SetUpPointsOnTetrahedra(points, _Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule * -FEI3dTetQuad :: giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr +FEI3dTetQuad :: giveBoundaryIntegrationRule(int order, int boundary) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, order + 2); iRule->SetUpPointsOnTriangle(points, _Unknown); - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei3dtetquad.h b/src/oofemlib/fei3dtetquad.h index 74aa6226b..d3355f3fd 100644 --- a/src/oofemlib/fei3dtetquad.h +++ b/src/oofemlib/fei3dtetquad.h @@ -48,62 +48,56 @@ class OOFEM_EXPORT FEI3dTetQuad : public FEInterpolation3d public: FEI3dTetQuad() : FEInterpolation3d(2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Tetrahedra; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_tetra_2; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Triangle; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Triangle; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Tetrahedra; } + Element_Geometry_Type giveGeometryType() const override { return EGT_tetra_2; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Triangle; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Triangle; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } - virtual double giveVolume(const FEICellGeometry &cellgeo) const; + double giveVolume(const FEICellGeometry &cellgeo) const override; // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - - virtual void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + static FloatArrayF<10> evalN(const FloatArrayF<3> &lcoords); + static std::pair> evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo); + static FloatMatrixF<3,10> evaldNdxi(const FloatArrayF<3> &lcoords); + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int giveNumberOfNodes() const override { return 10; } + void giveCellDofMans(IntArray& nodes, Element* elem) const override {nodes={1,2,3,4,5,6,7,8,9,10};} /** * Returns a characteristic length of the geometry, typically a diagonal or edge length. * @param cellgeo Underlying cell geometry. * @return Square root of area. */ - virtual double giveCharacteristicLength(const FEICellGeometry &cellgeo) const; + double giveCharacteristicLength(const FEICellGeometry &cellgeo) const; // Edge - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalEdgeMapping(int iedge) const override; // Surface - virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceEvaldNdx(FloatMatrix &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceEvalNormal(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalSurfaceMapping(IntArray &edgeNodes, int iedge); - virtual double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo); + void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalSurfaceMapping(int iedge) const override; + double evalNXIntegral(int iEdge, const FEICellGeometry &cellgeo) const override; - virtual IntegrationRule *giveIntegrationRule(int order); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary); - virtual int giveNumberOfNodes() const { return 10; } + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); - - double computeVolume(const FEICellGeometry &cellgeo); - - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; + double computeVolume(const FEICellGeometry &cellgeo) const ; }; } // end namespace oofem #endif // fei3dtetquad_h diff --git a/src/oofemlib/fei3dtrlin.C b/src/oofemlib/fei3dtrlin.C index bb38fd3cf..f71f076b2 100644 --- a/src/oofemlib/fei3dtrlin.C +++ b/src/oofemlib/fei3dtrlin.C @@ -38,16 +38,17 @@ #include "floatmatrix.h" #include "floatarray.h" #include "gaussintegrationrule.h" +#include namespace oofem { void -FEI3dTrLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->surfaceEvalN(answer, 1, lcoords, cellgeo); } double -FEI3dTrLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("FEI3dTrLin :: evaldNdx - Not supported"); return 0.; @@ -55,14 +56,14 @@ FEI3dTrLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEI void -FEI3dTrLin :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->surfaceEvaldNdxi(answer, lcoords); } void -FEI3dTrLin :: giveDerivativeXi(FloatArray &n, const FloatArray &lc) +FEI3dTrLin :: giveDerivativeXi(FloatArray &n, const FloatArray &lc) const { n.resize(3); n.at(1) = 1.0;; @@ -71,7 +72,7 @@ FEI3dTrLin :: giveDerivativeXi(FloatArray &n, const FloatArray &lc) } void -FEI3dTrLin :: giveDerivativeEta(FloatArray &n, const FloatArray &lc) +FEI3dTrLin :: giveDerivativeEta(FloatArray &n, const FloatArray &lc) const { n.resize(3); n.at(1) = 0.0;; @@ -81,19 +82,19 @@ FEI3dTrLin :: giveDerivativeEta(FloatArray &n, const FloatArray &lc) void -FEI3dTrLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; this->evalN(n, lcoords, cellgeo); answer.resize(0); for ( int i = 1; i <= 3; ++i ) { - answer.add( n.at(i), * cellgeo.giveVertexCoordinates(i) ); + answer.add( n.at(i), cellgeo.giveVertexCoordinates(i) ); } } #define POINT_TOL 1.e-3 int -FEI3dTrLin :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("FEI3dTrLin :: global2local - Not supported"); return -1; @@ -102,14 +103,14 @@ FEI3dTrLin :: global2local(FloatArray &answer, const FloatArray &gcoords, const void -FEI3dTrLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("FEI3dTrLin :: giveJacobianMatrixAt - Not supported"); } void -FEI3dTrLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double xi = lcoords.at(1); answer.resize(2); @@ -121,13 +122,13 @@ FEI3dTrLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords void FEI3dTrLin :: edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("FEI3dTrLin :: edgeEvaldNdx - Not supported"); } void -FEI3dTrLin :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(2); answer(0) = -0.5; @@ -136,52 +137,46 @@ FEI3dTrLin :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lco void FEI3dTrLin :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; FloatArray N; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); this->edgeEvalN(N, iedge, lcoords, cellgeo); answer.resize(0); for ( int i = 0; i < N.giveSize(); ++i ) { - answer.add( N(i), * cellgeo.giveVertexCoordinates( edgeNodes(i) ) ); + answer.add( N[i], cellgeo.giveVertexCoordinates( edgeNodes[i] ) ); } } double -FEI3dTrLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); ///@todo Implement this OOFEM_ERROR("FEI3dTrLin :: edgeGiveTransformationJacobian - Not supported"); return -1; } -void -FEI3dTrLin :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI3dTrLin :: computeLocalEdgeMapping(int iedge) const { - if ( iedge == 1 ) { // edge between nodes 1 2 - edgeNodes = { 1, 2 }; - + return { 1, 2 }; } else if ( iedge == 2 ) { // edge between nodes 2 3 - edgeNodes = { 2, 3 }; - + return { 2, 3 }; } else if ( iedge == 3 ) { // edge between nodes 2 3 - edgeNodes = { 3, 1 }; - + return { 3, 1 }; } else { - OOFEM_ERROR("Wrong edge number (%d)", iedge); + throw std::range_error("invalid edge number"); + return {}; } - } double -FEI3dTrLin :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) +FEI3dTrLin :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const { ///@todo Implement this OOFEM_ERROR("FEI3dTrLin :: edgeComputeLength - Not supported"); @@ -189,7 +184,7 @@ FEI3dTrLin :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cell } void -FEI3dTrLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(3); answer.at(1) = lcoords.at(1); @@ -198,7 +193,7 @@ FEI3dTrLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoo } void -FEI3dTrLin :: surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) +FEI3dTrLin :: surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) const { // Returns matrix with derivatives wrt local coordinates answer.resize(3, 2); @@ -216,27 +211,27 @@ FEI3dTrLin :: surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) void FEI3dTrLin :: surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { //Note: This gives the coordinate in the reference system FloatArray N; this->surfaceEvalN(N, isurf, lcoords, cellgeo); answer.resize(0); - for ( int i = 0; i < N.giveSize(); ++i ) { - answer.add( N(i), * cellgeo.giveVertexCoordinates(i) ); + for ( int i = 1; i <= N.giveSize(); ++i ) { + answer.add( N.at(i), cellgeo.giveVertexCoordinates(i) ); } } void -FEI3dTrLin :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { ///@todo Implement this OOFEM_ERROR("FEI3dTrLin :: surfaceEvaldNdx - Not supported"); } void -FEI3dTrLin :: surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // Note: These are not normalized. Returns the two tangent vectors to the surface. FloatMatrix dNdxi; @@ -245,13 +240,13 @@ FEI3dTrLin :: surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const Flo G1.resize(0); G2.resize(0); for ( int i = 0; i < 3; ++i ) { - G1.add( dNdxi(i, 1), * cellgeo.giveVertexCoordinates(i) ); - G2.add( dNdxi(i, 2), * cellgeo.giveVertexCoordinates(i) ); + G1.add( dNdxi(i, 1), cellgeo.giveVertexCoordinates(i) ); + G2.add( dNdxi(i, 2), cellgeo.giveVertexCoordinates(i) ); } } double -FEI3dTrLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray G1, G2; // local curvilinear base vectors this->surfaceEvalBaseVectorsAt(G1, G2, lcoords, cellgeo); @@ -262,7 +257,7 @@ FEI3dTrLin :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray } void -FEI3dTrLin :: surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // Jacobian matrix consists of the three curvilinear base vectors. The third is taken as the normal to the surface. // Note! The base vectors are not normalized except the third (normal) @@ -283,35 +278,35 @@ FEI3dTrLin :: surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const Flo } double -FEI3dTrLin :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrLin :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("FEI3dTrLin :: surfaceGiveTransformationJacobian - Not supported yet"); return 0; } -void -FEI3dTrLin :: computeLocalSurfaceMapping(IntArray &surfNodes, int isurf) +IntArray +FEI3dTrLin :: computeLocalSurfaceMapping(int isurf) const { //surfNodes.setValues(3, 1, 2, 3); - computeLocalEdgeMapping(surfNodes, isurf); + return computeLocalEdgeMapping(isurf); } -IntegrationRule * -FEI3dTrLin :: giveIntegrationRule(int order) +std::unique_ptr +FEI3dTrLin :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, order); iRule->SetUpPointsOnTriangle(points, _Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule * -FEI3dTrLin :: giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr +FEI3dTrLin :: giveBoundaryIntegrationRule(int order, int boundary) const { ///@todo Not sure about what defines boundaries on these elements. 2 surfaces + 3 edges? Ask Jim about this. OOFEM_ERROR("FEI3dTrLin :: giveBoundaryIntegrationRule - Not supported"); - return NULL; + return nullptr; } @@ -319,9 +314,8 @@ double FEI3dTrLin :: giveArea(const FEICellGeometry &cellgeo) const { // A = 0.5 * |AB x AC| - FloatArray AB, AC; - AB = *cellgeo.giveVertexCoordinates(2) - *cellgeo.giveVertexCoordinates(1); - AC = *cellgeo.giveVertexCoordinates(3) - *cellgeo.giveVertexCoordinates(1); + FloatArray AB = cellgeo.giveVertexCoordinates(2) - cellgeo.giveVertexCoordinates(1); + FloatArray AC = cellgeo.giveVertexCoordinates(3) - cellgeo.giveVertexCoordinates(1); FloatArray temp; temp.beVectorProductOf(AB, AC); return 0.5 * temp.computeNorm(); diff --git a/src/oofemlib/fei3dtrlin.h b/src/oofemlib/fei3dtrlin.h index 99229b2f0..d7cc77827 100644 --- a/src/oofemlib/fei3dtrlin.h +++ b/src/oofemlib/fei3dtrlin.h @@ -48,62 +48,55 @@ class OOFEM_EXPORT FEI3dTrLin : public FEInterpolation3d public: FEI3dTrLin() : FEInterpolation3d(2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_1; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } + Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_1; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Line; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Triangle; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Line; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Triangle; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } - - // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; - void giveDerivativeXi(FloatArray &n, const FloatArray &lcoords); - void giveDerivativeEta(FloatArray &n, const FloatArray &lcoords); - virtual void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - void surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords); + void giveDerivativeXi(FloatArray &n, const FloatArray &lcoords) const ; + void giveDerivativeEta(FloatArray &n, const FloatArray &lcoords) const ; // Edge - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalEdgeMapping(int iedge) const override; - virtual int giveNumberOfEdges() const { return 3; } + int giveNumberOfEdges() const override { return 3; } // Surface - virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceEvaldNdx(FloatMatrix &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - - virtual double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void computeLocalSurfaceMapping(IntArray &edgeNodes, int iedge); - void surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - - virtual IntegrationRule *giveIntegrationRule(int order); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary); + void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) const ; + + double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalSurfaceMapping(int iedge) const override; + void surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const ; + void surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const ; + + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; double giveArea(const FEICellGeometry &cellgeo) const; - virtual int giveNumberOfNodes() const { return 3; } + int giveNumberOfNodes() const override { return 3; } protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); - - double computeVolume(const FEICellGeometry &cellgeo); + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; + double computeVolume(const FEICellGeometry &cellgeo) const ; - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); }; } // end namespace oofem #endif // fei3dtetquad_h diff --git a/src/oofemlib/fei3dtrquad.C b/src/oofemlib/fei3dtrquad.C index 07313911d..ce5097832 100644 --- a/src/oofemlib/fei3dtrquad.C +++ b/src/oofemlib/fei3dtrquad.C @@ -37,16 +37,17 @@ #include "floatmatrix.h" #include "floatarray.h" #include "gaussintegrationrule.h" +#include namespace oofem { void -FEI3dTrQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->surfaceEvalN(answer, 1, lcoords, cellgeo); } double -FEI3dTrQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("FEI3dTrQuad :: evaldNdx - Not supported"); return 0.; @@ -54,14 +55,14 @@ FEI3dTrQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FE void -FEI3dTrQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->surfaceEvaldNdxi(answer, lcoords); } void -FEI3dTrQuad :: giveDerivativeXi(FloatArray &n, const FloatArray &lc) +FEI3dTrQuad :: giveDerivativeXi(FloatArray &n, const FloatArray &lc) const { double l1, l2, l3; @@ -80,7 +81,7 @@ FEI3dTrQuad :: giveDerivativeXi(FloatArray &n, const FloatArray &lc) } void -FEI3dTrQuad :: giveDerivativeEta(FloatArray &n, const FloatArray &lc) +FEI3dTrQuad :: giveDerivativeEta(FloatArray &n, const FloatArray &lc) const { double l1, l2, l3; @@ -100,7 +101,7 @@ FEI3dTrQuad :: giveDerivativeEta(FloatArray &n, const FloatArray &lc) void -FEI3dTrQuad :: giveLocalNodeCoords(FloatMatrix &answer) +FEI3dTrQuad :: giveLocalNodeCoords(FloatMatrix &answer) const { answer.resize(3,6); @@ -123,19 +124,19 @@ FEI3dTrQuad :: giveLocalNodeCoords(FloatMatrix &answer) void -FEI3dTrQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; this->evalN(n, lcoords, cellgeo); answer.clear(); for ( int i = 1; i <= 6; ++i ) { - answer.add( n.at(i), * cellgeo.giveVertexCoordinates(i) ); + answer.add( n.at(i), cellgeo.giveVertexCoordinates(i) ); } } #define POINT_TOL 1.e-3 int -FEI3dTrQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const { //OOFEM_ERROR("FEI3dTrQuad :: global2local - Not supported"); //return -1; @@ -143,21 +144,18 @@ FEI3dTrQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const ///@todo this is for linear triangle int xind = 1; int yind = 2; - - - double detJ, x1, x2, x3, y1, y2, y3; - answer.resize(3); - x1 = cellgeo.giveVertexCoordinates(1)->at(xind); - x2 = cellgeo.giveVertexCoordinates(2)->at(xind); - x3 = cellgeo.giveVertexCoordinates(3)->at(xind); + double x1 = cellgeo.giveVertexCoordinates(1).at(xind); + double x2 = cellgeo.giveVertexCoordinates(2).at(xind); + double x3 = cellgeo.giveVertexCoordinates(3).at(xind); - y1 = cellgeo.giveVertexCoordinates(1)->at(yind); - y2 = cellgeo.giveVertexCoordinates(2)->at(yind); - y3 = cellgeo.giveVertexCoordinates(3)->at(yind); + double y1 = cellgeo.giveVertexCoordinates(1).at(yind); + double y2 = cellgeo.giveVertexCoordinates(2).at(yind); + double y3 = cellgeo.giveVertexCoordinates(3).at(yind); - detJ = x1*(y2 - y3) + x2*(-y1 + y3) + x3*(y1 - y2); + double detJ = x1*(y2 - y3) + x2*(-y1 + y3) + x3*(y1 - y2); + answer.resize(3); answer.at(1) = ( ( x2 * y3 - x3 * y2 ) + ( y2 - y3 ) * gcoords.at(xind) + ( x3 - x2 ) * gcoords.at(yind) ) / detJ; answer.at(2) = ( ( x3 * y1 - x1 * y3 ) + ( y3 - y1 ) * gcoords.at(xind) + ( x1 - x3 ) * gcoords.at(yind) ) / detJ; answer.at(3) = 1. - answer.at(1) - answer.at(2); @@ -173,107 +171,93 @@ FEI3dTrQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const inside = false; } } - + return inside; } void -FEI3dTrQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("Not supported"); } void -FEI3dTrQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double xi = lcoords.at(1); answer.resize(3); - answer(0) = 0.5 * ( xi - 1.0 ) * xi; - answer(1) = 0.5 * ( xi + 1.0 ) * xi; - answer(2) = 1.0 - xi * xi; + answer[0] = 0.5 * ( xi - 1.0 ) * xi; + answer[1] = 0.5 * ( xi + 1.0 ) * xi; + answer[2] = 1.0 - xi * xi; } void FEI3dTrQuad :: edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("Not supported"); } void -FEI3dTrQuad :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double xi = lcoords.at(1); answer.resize(3); - answer(0) = xi - 0.5; - answer(1) = xi + 0.5; - answer(2) = -2 * xi; + answer[0] = xi - 0.5; + answer[1] = xi + 0.5; + answer[2] = -2 * xi; } void FEI3dTrQuad :: edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray edgeNodes; FloatArray N; - this->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->computeLocalEdgeMapping(iedge); this->edgeEvalN(N, iedge, lcoords, cellgeo); answer.clear(); for ( int i = 0; i < N.giveSize(); ++i ) { - answer.add( N(i), * cellgeo.giveVertexCoordinates( edgeNodes(i) ) ); + answer.add( N[i], cellgeo.giveVertexCoordinates( edgeNodes[i] ) ); } } double -FEI3dTrQuad :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray eNodes; FloatArray dNdu; double u = lcoords.at(1); - this->computeLocalEdgeMapping(eNodes, iedge); - dNdu.add( u - 0.5, * cellgeo.giveVertexCoordinates( eNodes.at(1) ) ); - dNdu.add( u + 0.5, * cellgeo.giveVertexCoordinates( eNodes.at(2) ) ); - dNdu.add( -2. * u, * cellgeo.giveVertexCoordinates( eNodes.at(3) ) ); + const auto &eNodes = this->computeLocalEdgeMapping(iedge); + dNdu.add( u - 0.5, cellgeo.giveVertexCoordinates( eNodes.at(1) ) ); + dNdu.add( u + 0.5, cellgeo.giveVertexCoordinates( eNodes.at(2) ) ); + dNdu.add( -2. * u, cellgeo.giveVertexCoordinates( eNodes.at(3) ) ); return dNdu.computeNorm(); } -void -FEI3dTrQuad :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI3dTrQuad :: computeLocalEdgeMapping(int iedge) const { - int aNode = 0, bNode = 0, cNode = 0; - edgeNodes.resize(3); - if ( iedge == 1 ) { // edge between nodes 1 2 - aNode = 1; - bNode = 2; - cNode = 4; + return {1, 2, 4}; } else if ( iedge == 2 ) { // edge between nodes 2 3 - aNode = 2; - bNode = 3; - cNode = 5; + return {2, 3, 5}; } else if ( iedge == 3 ) { // edge between nodes 2 3 - aNode = 3; - bNode = 1; - cNode = 6; + return {3, 1, 6}; } else { - OOFEM_ERROR("Wrong edge number (%d)", iedge); + throw std::range_error("invalid edge number"); + return {}; } - - edgeNodes.at(1) = aNode; - edgeNodes.at(2) = bNode; - edgeNodes.at(3) = cNode; } double -FEI3dTrQuad :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const { ///@todo Implement this OOFEM_ERROR("Not supported"); @@ -281,7 +265,7 @@ FEI3dTrQuad :: edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cel } void -FEI3dTrQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double l1 = lcoords.at(1); double l2 = lcoords.at(2); @@ -298,7 +282,7 @@ FEI3dTrQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lco } void -FEI3dTrQuad :: surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) +FEI3dTrQuad :: surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) const { // Returns matrix with derivatives wrt local coordinates answer.resize(6, 2); @@ -316,27 +300,27 @@ FEI3dTrQuad :: surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) void FEI3dTrQuad :: surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { //Note: This gives the coordinate in the reference system FloatArray N; this->surfaceEvalN(N, isurf, lcoords, cellgeo); answer.clear(); - for ( int i = 0; i < N.giveSize(); ++i ) { - answer.add( N(i), * cellgeo.giveVertexCoordinates(i) ); + for ( int i = 1; i <= N.giveSize(); ++i ) { + answer.add( N.at(i), cellgeo.giveVertexCoordinates(i) ); } } void -FEI3dTrQuad :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { ///@todo Implement this OOFEM_ERROR("Not supported"); } void -FEI3dTrQuad :: surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // Note: These are not normalized. Returns the two tangent vectors to the surface. FloatMatrix dNdxi; @@ -345,13 +329,13 @@ FEI3dTrQuad :: surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const Fl G1.clear(); G2.clear(); for ( int i = 0; i < 6; ++i ) { - G1.add( dNdxi(i, 1), * cellgeo.giveVertexCoordinates(i) ); - G2.add( dNdxi(i, 2), * cellgeo.giveVertexCoordinates(i) ); + G1.add( dNdxi(i, 1), cellgeo.giveVertexCoordinates(i) ); + G2.add( dNdxi(i, 2), cellgeo.giveVertexCoordinates(i) ); } } double -FEI3dTrQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray G1, G2; // local curvilinear base vectors this->surfaceEvalBaseVectorsAt(G1, G2, lcoords, cellgeo); @@ -362,7 +346,7 @@ FEI3dTrQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray } void -FEI3dTrQuad :: surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // Jacobian matrix consists of the three curvilinear base vectors. The third is taken as the normal to the surface. // Note! The base vectors are not normalized except the third (normal) @@ -383,37 +367,37 @@ FEI3dTrQuad :: surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const Fl } double -FEI3dTrQuad :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dTrQuad :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("Not supported yet"); return 0; } -void -FEI3dTrQuad :: computeLocalSurfaceMapping(IntArray &surfNodes, int isurf) +IntArray +FEI3dTrQuad :: computeLocalSurfaceMapping(int isurf) const { //surfNodes.setValues(6, 1, 2, 3, 4, 5, 6); //surfNodes = {1, 2, 3, 4, 5, 6}; ///@todo - fix wrt xfem - computeLocalEdgeMapping(surfNodes, isurf); + return computeLocalEdgeMapping(isurf); } -IntegrationRule * -FEI3dTrQuad :: giveIntegrationRule(int order) +std::unique_ptr +FEI3dTrQuad :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, order); iRule->SetUpPointsOnTriangle(points, _Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule * -FEI3dTrQuad :: giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr +FEI3dTrQuad :: giveBoundaryIntegrationRule(int order, int boundary) const { ///@todo Not sure about what defines boundaries on these elements. 2 surfaces + 3 edges? Ask Jim about this. OOFEM_ERROR("FEI3dTrQuad :: giveBoundaryIntegrationRule - Not supported"); - return NULL; + return nullptr; } @@ -421,27 +405,24 @@ double FEI3dTrQuad :: giveArea(const FEICellGeometry &cellgeo) const { ///@todo this only correct for a planar triangle in the xy-plane - const FloatArray *p; - double x1, x2, x3, x4, x5, x6, y1, y2, y3, y4, y5, y6; - - p = cellgeo.giveVertexCoordinates(1); - x1 = p->at(1); - y1 = p->at(2); - p = cellgeo.giveVertexCoordinates(2); - x2 = p->at(1); - y2 = p->at(2); - p = cellgeo.giveVertexCoordinates(3); - x3 = p->at(1); - y3 = p->at(2); - p = cellgeo.giveVertexCoordinates(4); - x4 = p->at(1); - y4 = p->at(2); - p = cellgeo.giveVertexCoordinates(5); - x5 = p->at(1); - y5 = p->at(2); - p = cellgeo.giveVertexCoordinates(6); - x6 = p->at(1); - y6 = p->at(2); + const auto &p1 = cellgeo.giveVertexCoordinates(1); + double x1 = p1.at(1); + double y1 = p1.at(2); + const auto &p2 = cellgeo.giveVertexCoordinates(2); + double x2 = p2.at(1); + double y2 = p2.at(2); + const auto &p3 = cellgeo.giveVertexCoordinates(3); + double x3 = p3.at(1); + double y3 = p3.at(2); + const auto &p4 = cellgeo.giveVertexCoordinates(4); + double x4 = p4.at(1); + double y4 = p4.at(2); + const auto &p5 = cellgeo.giveVertexCoordinates(5); + double x5 = p5.at(1); + double y5 = p5.at(2); + const auto &p6 = cellgeo.giveVertexCoordinates(6); + double x6 = p6.at(1); + double y6 = p6.at(2); return (4*(-(x4*y1) + x6*y1 + x4*y2 - x5*y2 + x5*y3 - x6*y3) + x2*(y1 - y3 - 4*y4 + 4*y5) + x1*(-y2 + y3 + 4*y4 - 4*y6) + x3*(-y1 + y2 - 4*y5 + 4*y6))/6; diff --git a/src/oofemlib/fei3dtrquad.h b/src/oofemlib/fei3dtrquad.h index 5e1058455..fca64ada0 100644 --- a/src/oofemlib/fei3dtrquad.h +++ b/src/oofemlib/fei3dtrquad.h @@ -49,65 +49,57 @@ class OOFEM_EXPORT FEI3dTrQuad : public FEInterpolation3d public: FEI3dTrQuad() : FEInterpolation3d(2) { } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_2; } - - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { return _Triangle; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return _Triangle; } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } + Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_2; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { return _Triangle; } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return _Triangle; } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; // new methods - void giveDerivativeXi(FloatArray &n, const FloatArray &lcoords); - void giveDerivativeEta(FloatArray &n, const FloatArray &lcoords); - virtual void giveLocalNodeCoords(FloatMatrix &answer); - virtual void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - void surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords); + void giveDerivativeXi(FloatArray &n, const FloatArray &lcoords) const; + void giveDerivativeEta(FloatArray &n, const FloatArray &lcoords) const ; + void giveLocalNodeCoords(FloatMatrix &answer) const override; + void surfaceEvaldNdxi(FloatMatrix &answer, const FloatArray &lcoords) const ; // Edge - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - void edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalEdgeMapping(int iedge) const override; - virtual int giveNumberOfEdges() const { return 3; } + int giveNumberOfEdges() const override { return 3; } // Surface - virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceEvaldNdx(FloatMatrix &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - - virtual double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void computeLocalSurfaceMapping(IntArray &edgeNodes, int iedge); - void surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - - virtual IntegrationRule *giveIntegrationRule(int order); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary); + void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalSurfaceMapping(int iedge) const override; + void surfaceEvalBaseVectorsAt(FloatArray &G1, FloatArray &G2, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const ; + void surfaceGiveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const ; + + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; double giveArea(const FEICellGeometry &cellgeo) const; - virtual int giveNumberOfNodes() const { return 6; } + int giveNumberOfNodes() const override { return 6; } protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); - - double computeVolume(const FEICellGeometry &cellgeo); + double edgeComputeLength(const IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; + double computeVolume(const FEICellGeometry &cellgeo) const; - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); }; } // end namespace oofem #endif // fei3dtetquad_h diff --git a/src/oofemlib/fei3dwedgelin.C b/src/oofemlib/fei3dwedgelin.C index eccc27d79..7da14427b 100644 --- a/src/oofemlib/fei3dwedgelin.C +++ b/src/oofemlib/fei3dwedgelin.C @@ -35,12 +35,33 @@ #include "fei3dwedgelin.h" #include "floatarray.h" #include "floatmatrix.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "intarray.h" #include "gaussintegrationrule.h" namespace oofem { + +FloatArrayF<6> +FEI3dWedgeLin :: evalN(const FloatArrayF<3> &lcoords) +{ + double u = lcoords[0]; + double v = lcoords[1]; + double w = lcoords[2]; + double x = 1. - u - v; + return { + 0.5 * ( 1. - w ) * x, + 0.5 * ( 1. - w ) * u, + 0.5 * ( 1. - w ) * v, + 0.5 * ( 1. + w ) * x, + 0.5 * ( 1. + w ) * u, + 0.5 * ( 1. + w ) * v, + }; +} + + void -FEI3dWedgeLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double u, v, w; answer.resize(6); @@ -58,15 +79,91 @@ FEI3dWedgeLin :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEIC } +FloatMatrixF<3,6> +FEI3dWedgeLin :: evaldNdxi(const FloatArrayF<3> &lcoords) +{ + double u = lcoords.at(1); + double v = lcoords.at(2); + double w = lcoords.at(3); + double x = 1. - u - v; + + return { + -0.5 * ( 1. - w ), + -0.5 * ( 1. - w ), + -0.5 * x, + 0.5 * ( 1. - w ), + 0., + -0.5 * u, + 0., + 0.5 * ( 1. - w ), + -0.5 * v, + -0.5 * ( 1. + w ), + -0.5 * ( 1. + w ), + 0.5 * x, + 0.5 * ( 1. + w ), + 0., + 0.5 * u, + 0., + 0.5 * ( 1. + w ), + 0.5 * v, + }; +} + + +void +FEI3dWedgeLin :: evaldNdxi(FloatMatrix &dN, const FloatArray &lcoords, const FEICellGeometry &) const +{ + double u = lcoords.at(1); + double v = lcoords.at(2); + double w = lcoords.at(3); + + dN.resize(6, 3); + + dN.at(1, 1) = -0.5 * ( 1. - w ); + dN.at(2, 1) = 0.5 * ( 1. - w ); + dN.at(3, 1) = 0.; + dN.at(4, 1) = -0.5 * ( 1. + w ); + dN.at(5, 1) = 0.5 * ( 1. + w ); + dN.at(6, 1) = 0.; + + dN.at(1, 2) = -0.5 * ( 1. - w ); + dN.at(2, 2) = 0.; + dN.at(3, 2) = 0.5 * ( 1. - w ); + dN.at(4, 2) = -0.5 * ( 1. + w ); + dN.at(5, 2) = 0.; + dN.at(6, 2) = 0.5 * ( 1. + w ); + + dN.at(1, 3) = -0.5 * ( 1. - u - v ); + dN.at(2, 3) = -0.5 * u; + dN.at(3, 3) = -0.5 * v; + dN.at(4, 3) = 0.5 * ( 1. - u - v ); + dN.at(5, 3) = 0.5 * u; + dN.at(6, 3) = 0.5 * v; +} + + +std::pair> +FEI3dWedgeLin :: evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo) +{ + auto dNduvw = evaldNdxi(lcoords); + FloatMatrixF<3,6> coords; + for ( int i = 0; i < 6; i++ ) { + coords.setColumn(cellgeo.giveVertexCoordinates(i+1), i); + } + auto jacT = dotT(dNduvw, coords); + return {det(jacT), dot(inv(jacT), dNduvw)}; +} + + double -FEI3dWedgeLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatMatrix jacobianMatrix, inv, dNduvw, coords; - this->giveLocalDerivative(dNduvw, lcoords); + this->evaldNdxi(dNduvw, lcoords, cellgeo); coords.resize(3, 6); for ( int i = 1; i <= 6; i++ ) { - coords.setColumn(* cellgeo.giveVertexCoordinates(i), i); + coords.setColumn(cellgeo.giveVertexCoordinates(i), i); } jacobianMatrix.beProductOf(coords, dNduvw); inv.beInverseOf(jacobianMatrix); @@ -77,7 +174,7 @@ FEI3dWedgeLin :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const void -FEI3dWedgeLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeLin :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; @@ -85,23 +182,23 @@ FEI3dWedgeLin :: local2global(FloatArray &answer, const FloatArray &lcoords, con answer.clear(); for ( int i = 1; i <= 6; i++ ) { - answer.add( n.at(i), * cellgeo.giveVertexCoordinates(i) ); + answer.add( n.at(i), cellgeo.giveVertexCoordinates(i) ); } } double FEI3dWedgeLin :: giveCharacteristicLength(const FEICellGeometry &cellgeo) const { - const FloatArray *n1 = cellgeo.giveVertexCoordinates(1); - const FloatArray *n2 = cellgeo.giveVertexCoordinates(6); + const auto &n1 = cellgeo.giveVertexCoordinates(1); + const auto &n2 = cellgeo.giveVertexCoordinates(6); ///@todo Change this so that it is not dependent on node order. - return n1->distance(n2); + return distance(n1, n2); } #define POINT_TOL 1.e-3 int -FEI3dWedgeLin :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeLin :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const { FloatArray res, delta, guess; FloatMatrix jac; @@ -156,64 +253,31 @@ FEI3dWedgeLin :: global2local(FloatArray &answer, const FloatArray &gcoords, con double -FEI3dWedgeLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeLin :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatMatrix jacobianMatrix; this->giveJacobianMatrixAt(jacobianMatrix, lcoords, cellgeo); - return jacobianMatrix.giveDeterminant() / 2.; ///@todo Should this really be a factor 1/2 here? + return jacobianMatrix.giveDeterminant(); } void -FEI3dWedgeLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeLin :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const // Returns the jacobian matrix J (x,y,z)/(ksi,eta,dzeta) of the receiver. { FloatMatrix dNduvw, coords; - this->giveLocalDerivative(dNduvw, lcoords); + this->evaldNdxi(dNduvw, lcoords, cellgeo); coords.resize(3, 6); for ( int i = 1; i <= 6; i++ ) { - coords.setColumn(* cellgeo.giveVertexCoordinates(i), i); + coords.setColumn(cellgeo.giveVertexCoordinates(i), i); } jacobianMatrix.beProductOf(coords, dNduvw); } void -FEI3dWedgeLin :: giveLocalDerivative(FloatMatrix &dN, const FloatArray &lcoords) -{ - double u, v, w; - u = lcoords.at(1); - v = lcoords.at(2); - w = lcoords.at(3); - - dN.resize(6, 3); - - dN.at(1, 1) = -0.5 * ( 1. - w ); - dN.at(2, 1) = 0.5 * ( 1. - w ); - dN.at(3, 1) = 0.; - dN.at(4, 1) = -0.5 * ( 1. + w ); - dN.at(5, 1) = 0.5 * ( 1. + w ); - dN.at(6, 1) = 0.; - - dN.at(1, 2) = -0.5 * ( 1. - w ); - dN.at(2, 2) = 0.; - dN.at(3, 2) = 0.5 * ( 1. - w ); - dN.at(4, 2) = -0.5 * ( 1. + w ); - dN.at(5, 2) = 0.; - dN.at(6, 2) = 0.5 * ( 1. + w ); - - dN.at(1, 3) = -0.5 * ( 1. - u - v ); - dN.at(2, 3) = -0.5 * u; - dN.at(3, 3) = -0.5 * v; - dN.at(4, 3) = 0.5 * ( 1. - u - v ); - dN.at(5, 3) = 0.5 * u; - dN.at(6, 3) = 0.5 * v; -} - - -void -FEI3dWedgeLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); answer.resize(2); @@ -223,57 +287,57 @@ FEI3dWedgeLin :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoo void -FEI3dWedgeLin :: edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeLin :: edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("not implemented"); } void -FEI3dWedgeLin :: edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeLin :: edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray nodes; FloatArray n; - this->computeLocalEdgeMapping(nodes, iedge); + const auto &nodes = this->computeLocalEdgeMapping(iedge); this->edgeEvalN(n, iedge, lcoords, cellgeo); answer.clear(); for ( int i = 1; i <= n.giveSize(); ++i ) { - answer.add( n.at(i), * cellgeo.giveVertexCoordinates( nodes.at(i) ) ); + answer.add( n.at(i), cellgeo.giveVertexCoordinates( nodes.at(i) ) ); } } -void -FEI3dWedgeLin :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI3dWedgeLin :: computeLocalEdgeMapping(int iedge) const { if ( iedge == 1 ) { - edgeNodes = {1, 2}; + return {1, 2}; } else if ( iedge == 2 ) { - edgeNodes = {2, 3}; + return {2, 3}; } else if ( iedge == 3 ) { - edgeNodes = {3, 1}; + return {3, 1}; } else if ( iedge == 4 ) { - edgeNodes = {4, 5}; + return {4, 5}; } else if ( iedge == 5 ) { - edgeNodes = {5, 6}; + return {5, 6}; } else if ( iedge == 6 ) { - edgeNodes = {6, 4}; + return {6, 4}; } else if ( iedge == 7 ) { - edgeNodes = {1, 4}; + return {1, 4}; } else if ( iedge == 8 ) { - edgeNodes = {2, 5}; + return {2, 5}; } else if ( iedge == 9 ) { - edgeNodes = {3, 6}; + return {3, 6}; } else { - OOFEM_ERROR("Edge %d doesn't exist.\n", iedge); + throw std::range_error("invalid edge number"); + return {}; } } double -FEI3dWedgeLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("not implemented"); return 0.0; @@ -281,7 +345,7 @@ FEI3dWedgeLin :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lco void -FEI3dWedgeLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); double eta = lcoords.at(2); @@ -303,67 +367,67 @@ FEI3dWedgeLin :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &l void FEI3dWedgeLin :: surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray nodes; FloatArray n; - this->computeLocalSurfaceMapping(nodes, isurf); + const auto &nodes = this->computeLocalSurfaceMapping(isurf); this->surfaceEvalN(n, isurf, lcoords, cellgeo); answer.clear(); for ( int i = 1; i <= n.giveSize(); ++i ) { - answer.add( n.at(i), * cellgeo.giveVertexCoordinates( nodes.at(i) ) ); + answer.add( n.at(i), cellgeo.giveVertexCoordinates( nodes.at(i) ) ); } } -void -FEI3dWedgeLin :: computeLocalSurfaceMapping(IntArray &nodes, int isurf) +IntArray +FEI3dWedgeLin :: computeLocalSurfaceMapping(int isurf) const { if ( isurf == 1 ) { - nodes = {1, 2, 3}; + return {1, 2, 3}; } else if ( isurf == 2 ) { - nodes = {4, 5, 6}; + return {4, 5, 6}; } else if ( isurf == 3 ) { - nodes = {1, 2, 5, 4}; + return {1, 2, 5, 4}; } else if ( isurf == 4 ) { - nodes = {2, 3, 6, 5}; + return {2, 3, 6, 5}; } else if ( isurf == 5 ) { - nodes = {3, 1, 4, 6}; + return {3, 1, 4, 6}; } else { - OOFEM_ERROR("Surface %d doesn't exist.\n", isurf); + throw std::range_error("invalid surface number"); + return {}; } } double FEI3dWedgeLin :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + const FEICellGeometry &cellgeo) const { OOFEM_ERROR("not implemented"); return 0; } -IntegrationRule * -FEI3dWedgeLin :: giveIntegrationRule(int order) +std::unique_ptr +FEI3dWedgeLin :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); ///@todo This function below isn't supported for wedges. We must decide how we should do this. //int points = iRule->getRequiredNumberOfIntegrationPoints(_Wedge, order); OOFEM_WARNING("Warning.. ignoring 'order' argument: FIXME"); int pointsZeta = 1; int pointsTriangle = 1; iRule->SetUpPointsOnWedge(pointsTriangle, pointsZeta, _Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule * -FEI3dWedgeLin :: giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr +FEI3dWedgeLin :: giveBoundaryIntegrationRule(int order, int boundary) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); if ( boundary <= 2 ) { int points = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, order + 0); iRule->SetUpPointsOnTriangle(points, _Unknown); @@ -371,6 +435,6 @@ FEI3dWedgeLin :: giveBoundaryIntegrationRule(int order, int boundary) int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order + 2); iRule->SetUpPointsOnSquare(points, _Unknown); } - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei3dwedgelin.h b/src/oofemlib/fei3dwedgelin.h index 399fd7a75..3cebce3f2 100644 --- a/src/oofemlib/fei3dwedgelin.h +++ b/src/oofemlib/fei3dwedgelin.h @@ -47,60 +47,56 @@ namespace oofem { */ class OOFEM_EXPORT FEI3dWedgeLin : public FEInterpolation3d { -protected: - public: FEI3dWedgeLin() : FEInterpolation3d(1) { } - virtual integrationDomain giveIntegrationDomain() const { return _Wedge; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_wedge_1; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { - if (ib <= 2) return _Triangle; - else return _Square; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return this->giveBoundaryIntegrationDomain(isurf); } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } - - + integrationDomain giveIntegrationDomain() const override { return _Wedge; } + Element_Geometry_Type giveGeometryType() const override { return EGT_wedge_1; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override + { + if (ib <= 2) return _Triangle; + else return _Square; + } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return this->giveBoundaryIntegrationDomain(isurf); } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } // Bulk - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveCharacteristicLength(const FEICellGeometry &cellgeo) const; + static FloatArrayF<6> evalN(const FloatArrayF<3> &lcoords); + static std::pair> evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo); + static FloatMatrixF<3,6> evaldNdxi(const FloatArrayF<3> &lcoords); + + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix & answer, const FloatArray & lcoords, const FEICellGeometry & cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double giveCharacteristicLength(const FEICellGeometry &cellgeo) const; // Edge - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalEdgeMapping(int iedge) const override; // Surface - virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - //virtual void surfaceEvaldNdx (FloatMatrix&answer, int iedge, - // const FloatArray& lcoords, const FEICellGeometry& cellgeo); - virtual void surfaceLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalSurfaceMapping(IntArray &nodes, int iSurf); + void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + //void surfaceEvaldNdx (FloatMatrix&answer, int iedge, const FloatArray& lcoords, const FEICellGeometry& cellgeo) override; + void surfaceLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalSurfaceMapping(int iSurf) const override; - virtual IntegrationRule *giveIntegrationRule(int order); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary); - virtual IntegrationRule *giveSurfaceIntegrationRule(int order, int isurf) - { return giveBoundaryIntegrationRule(order, isurf); } + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; + std::unique_ptr giveSurfaceIntegrationRule(int order, int isurf) const + { return giveBoundaryIntegrationRule(order, isurf); } - virtual int giveNumberOfNodes() const { return 6; } + int giveNumberOfNodes() const override { return 6; } protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); - void giveLocalDerivative(FloatMatrix &dN, const FloatArray &lcoords); + double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; }; } // end namespace oofem #endif diff --git a/src/oofemlib/fei3dwedgequad.C b/src/oofemlib/fei3dwedgequad.C index 025af2b22..b708b3684 100644 --- a/src/oofemlib/fei3dwedgequad.C +++ b/src/oofemlib/fei3dwedgequad.C @@ -35,12 +35,40 @@ #include "fei3dwedgequad.h" #include "floatarray.h" #include "floatmatrix.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "intarray.h" #include "gaussintegrationrule.h" namespace oofem { + +FloatArrayF<15> +FEI3dWedgeQuad :: evalN(const FloatArrayF<3> &lcoords) +{ + double x = lcoords[0]; + double y = lcoords[1]; + double z = lcoords[2]; + return { + 0.5 * ( ( 1. - x - y ) * ( 2. * ( 1. - x - y ) - 1. ) * ( 1. - z ) - ( 1. - x - y ) * ( 1. - z * z ) ), + 0.5 * ( x * ( 2. * x - 1. ) * ( 1. - z ) - x * ( 1. - z * z ) ), + 0.5 * ( y * ( 2. * y - 1. ) * ( 1. - z ) - y * ( 1. - z * z ) ), + 0.5 * ( ( 1. - x - y ) * ( 2. * ( 1. - x - y ) - 1. ) * ( 1. + z ) - ( 1. - x - y ) * ( 1. - z * z ) ), + 0.5 * ( x * ( 2. * x - 1. ) * ( 1. + z ) - x * ( 1. - z * z ) ), + 0.5 * ( y * ( 2. * y - 1. ) * ( 1. + z ) - y * ( 1. - z * z ) ), + 2. * ( 1. - x - y ) * x * ( 1. - z ), + 2. * x * y * ( 1. - z ), + 2. * y * ( 1. - x - y ) * ( 1. - z ), + 2. * x * ( 1. - x - y ) * ( 1. + z ), + 2. * x * y * ( 1. + z ), + 2. * y * ( 1. - x - y ) * ( 1. + z ), + ( 1. - x - y ) * ( 1. - z * z ), + x * ( 1. - z * z ), + y * ( 1. - z * z ), + }; +} + void -FEI3dWedgeQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double x, y, z; answer.resize(15); @@ -66,14 +94,123 @@ FEI3dWedgeQuad :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEI answer.at(15) = y * ( 1. - z * z ); } + +FloatMatrixF<3,15> +FEI3dWedgeQuad :: evaldNdxi(const FloatArrayF<3> &lcoords) +{ + double x = lcoords[0]; + double y = lcoords[1]; + double z = lcoords[2]; + + return { + 1. / 2. - ( z - 1. ) * ( x + y - 1. ) - z * z / 2. - ( ( z - 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2., // 1 + 1. / 2. - ( z - 1. ) * ( x + y - 1. ) - z * z / 2. - ( ( z - 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2., + -z * ( x + y - 1. ) - ( ( 2. * x + 2. * y - 1. ) * ( x + y - 1. ) ) / 2., + z * z / 2. - x * ( z - 1. ) - ( ( 2. * x - 1. ) * ( z - 1. ) ) / 2. - 1 / 2., // 2 + 0., + x * z - ( x * ( 2. * x - 1. ) ) / 2., + 0., // 3 + z * z / 2. - y * ( z - 1. ) - ( ( 2. * y - 1. ) * ( z - 1. ) ) / 2. - 1. / 2., + y * z - ( y * ( 2 * y - 1. ) ) / 2., + ( ( z + 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2. + ( z + 1. ) * ( x + y - 1. ) - z * z / 2. + 1. / 2., // 4 + ( ( z + 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2. + ( z + 1. ) * ( x + y - 1. ) - z * z / 2. + 1. / 2., + ( ( 2. * x + 2. * y - 1. ) * ( x + y - 1. ) ) / 2. - z * ( x + y - 1. ), + ( ( 2. * x - 1. ) * ( z + 1. ) ) / 2. + x * ( z + 1. ) + z * z / 2. - 1. / 2., 0., ( x * ( 2. * x - 1. ) ) / 2. + x * z, // 5 + 0., ( ( 2. * y - 1. ) * ( z + 1. ) ) / 2. + y * ( z + 1. ) + z * z / 2. - 1. / 2., ( y * ( 2. * y - 1. ) ) / 2. + y * z, // 6 + ( z - 1. ) * ( 2. * x + 2. * y - 2. ) + 2. * x * ( z - 1. ), 2. * x * ( z - 1. ), x * ( 2. * x + 2. * y - 2. ), // 7 + -2. * y * ( z - 1. ), -2. * x * ( z - 1. ), -2. * x * y, // 8 + 2. * y * ( z - 1. ), 2. * ( z - 1. ) * ( x + y - 1. ) + 2. * y * ( z - 1. ), 2. * y * ( x + y - 1. ), // 9 + -2. * ( z + 1. ) * ( x + y - 1. ) - 2. * x * ( z + 1. ), -2. * x * ( z + 1. ), -2. * x * ( x + y - 1. ), // 10 + 2. * y * ( z + 1. ), 2. * x * ( z + 1. ), 2. * x * y, // 11 + -2. * y * ( z + 1. ), -2. * ( z + 1. ) * ( x + y - 1. ) - 2. * y * ( z + 1. ), -2. * y * ( x + y - 1. ), // 12 + z * z - 1., z * z - 1., 2. * z * ( x + y - 1. ), // 13 + 1. - z * z, 0., -2. * x * z, // 14 + 0., 1. - z * z, -2. * y * z, // 15 + }; +} + + +void +FEI3dWedgeQuad :: evaldNdxi(FloatMatrix &dN, const FloatArray &lcoords, const FEICellGeometry &) const +{ + double x, y, z; + x = lcoords.at(1); + y = lcoords.at(2); + z = lcoords.at(3); + + dN.resize(15, 3); + + dN.at(1, 1) = 1. / 2. - ( z - 1. ) * ( x + y - 1. ) - z * z / 2. - ( ( z - 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2.; + dN.at(2, 1) = z * z / 2. - x * ( z - 1. ) - ( ( 2. * x - 1. ) * ( z - 1. ) ) / 2. - 1 / 2.; + dN.at(3, 1) = 0.; + dN.at(4, 1) = ( ( z + 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2. + ( z + 1. ) * ( x + y - 1. ) - z * z / 2. + 1. / 2.; + dN.at(5, 1) = ( ( 2. * x - 1. ) * ( z + 1. ) ) / 2. + x * ( z + 1. ) + z * z / 2. - 1. / 2.; + dN.at(6, 1) = 0.; + dN.at(7, 1) = ( z - 1. ) * ( 2. * x + 2. * y - 2. ) + 2. * x * ( z - 1. ); + dN.at(8, 1) = -2. * y * ( z - 1. ); + dN.at(9, 1) = 2. * y * ( z - 1. ); + dN.at(10, 1) = -2. * ( z + 1. ) * ( x + y - 1. ) - 2. * x * ( z + 1. ); + dN.at(11, 1) = 2. * y * ( z + 1. ); + dN.at(12, 1) = -2. * y * ( z + 1. ); + dN.at(13, 1) = z * z - 1.; + dN.at(14, 1) = 1. - z * z; + dN.at(15, 1) = 0.; + + dN.at(1, 2) = 1. / 2. - ( z - 1. ) * ( x + y - 1. ) - z * z / 2. - ( ( z - 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2.; + dN.at(2, 2) = 0.; + dN.at(3, 2) = z * z / 2. - y * ( z - 1. ) - ( ( 2. * y - 1. ) * ( z - 1. ) ) / 2. - 1. / 2.; + dN.at(4, 2) = ( ( z + 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2. + ( z + 1. ) * ( x + y - 1. ) - z * z / 2. + 1. / 2.; + dN.at(5, 2) = 0.; + dN.at(6, 2) = ( ( 2. * y - 1. ) * ( z + 1. ) ) / 2. + y * ( z + 1. ) + z * z / 2. - 1. / 2.; + dN.at(7, 2) = 2. * x * ( z - 1. ); + dN.at(8, 2) = -2. * x * ( z - 1. ); + dN.at(9, 2) = 2. * ( z - 1. ) * ( x + y - 1. ) + 2. * y * ( z - 1. ); + dN.at(10, 2) = -2. * x * ( z + 1. ); + dN.at(11, 2) = 2. * x * ( z + 1. ); + dN.at(12, 2) = -2. * ( z + 1. ) * ( x + y - 1. ) - 2. * y * ( z + 1. ); + dN.at(13, 2) = z * z - 1.; + dN.at(14, 2) = 0.; + dN.at(15, 2) = 1. - z * z; + + dN.at(1, 3) = -z * ( x + y - 1. ) - ( ( 2. * x + 2. * y - 1. ) * ( x + y - 1. ) ) / 2.; + dN.at(2, 3) = x * z - ( x * ( 2. * x - 1. ) ) / 2.; + dN.at(3, 3) = y * z - ( y * ( 2 * y - 1. ) ) / 2.; + dN.at(4, 3) = ( ( 2. * x + 2. * y - 1. ) * ( x + y - 1. ) ) / 2. - z * ( x + y - 1. ); + dN.at(5, 3) = ( x * ( 2. * x - 1. ) ) / 2. + x * z; + dN.at(6, 3) = ( y * ( 2. * y - 1. ) ) / 2. + y * z; + dN.at(7, 3) = x * ( 2. * x + 2. * y - 2. ); + dN.at(8, 3) = -2. * x * y; + dN.at(9, 3) = 2. * y * ( x + y - 1. ); + dN.at(10, 3) = -2. * x * ( x + y - 1. ); + dN.at(11, 3) = 2. * x * y; + dN.at(12, 3) = -2. * y * ( x + y - 1. ); + dN.at(13, 3) = 2. * z * ( x + y - 1. ); + dN.at(14, 3) = -2. * x * z; + dN.at(15, 3) = -2. * y * z; +} + + +std::pair> +FEI3dWedgeQuad :: evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo) +{ + auto dNduvw = evaldNdxi(lcoords); + FloatMatrixF<3,15> coords; + for ( int i = 0; i < 15; i++ ) { + coords.setColumn(cellgeo.giveVertexCoordinates(i+1), i); + } + auto jacT = dotT(dNduvw, coords); + return {det(jacT), dot(inv(jacT), dNduvw)}; +} + + double -FEI3dWedgeQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatMatrix jacobianMatrix, inv, dNduvw, coords; - this->giveLocalDerivative(dNduvw, lcoords); + this->evaldNdxi(dNduvw, lcoords, cellgeo); coords.resize(3, 15); for ( int i = 1; i <= 15; i++ ) { - coords.setColumn(* cellgeo.giveVertexCoordinates(i), i); + coords.setColumn(cellgeo.giveVertexCoordinates(i), i); } jacobianMatrix.beProductOf(coords, dNduvw); inv.beInverseOf(jacobianMatrix); @@ -84,7 +221,7 @@ FEI3dWedgeQuad :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const void -FEI3dWedgeQuad :: giveLocalNodeCoords(FloatMatrix &answer) +FEI3dWedgeQuad :: giveLocalNodeCoords(FloatMatrix &answer) const { answer.resize(3,15); @@ -108,7 +245,7 @@ FEI3dWedgeQuad :: giveLocalNodeCoords(FloatMatrix &answer) void -FEI3dWedgeQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray n; this->evalN(n, lcoords, cellgeo); @@ -116,108 +253,103 @@ FEI3dWedgeQuad :: local2global(FloatArray &answer, const FloatArray &lcoords, co answer.resize(3); answer.zero(); for ( int i = 1; i <= 15; i++ ) { - answer.at(1) += n.at(i) * cellgeo.giveVertexCoordinates(i)->at(1); - answer.at(2) += n.at(i) * cellgeo.giveVertexCoordinates(i)->at(2); - answer.at(3) += n.at(i) * cellgeo.giveVertexCoordinates(i)->at(3); + answer.at(1) += n.at(i) * cellgeo.giveVertexCoordinates(i).at(1); + answer.at(2) += n.at(i) * cellgeo.giveVertexCoordinates(i).at(2); + answer.at(3) += n.at(i) * cellgeo.giveVertexCoordinates(i).at(3); } } +#define POINT_TOL 1.e-3 int -FEI3dWedgeQuad :: global2local(FloatArray &answer, const FloatArray &coords, const FEICellGeometry &cellgeo) +FEI3dWedgeQuad :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const { - OOFEM_ERROR("not implemented"); - return 1; + FloatArray res, delta, guess; + FloatMatrix jac; + double convergence_limit, error = 0.0; + + // find a suitable convergence limit + convergence_limit = 1e-6 * this->giveCharacteristicLength(cellgeo); + + // setup initial guess + answer.resize( gcoords.giveSize() ); + answer.zero(); + + // apply Newton-Raphson to solve the problem + for ( int nite = 0; nite < 40; nite++ ) { + // compute the residual + this->local2global(guess, answer, cellgeo); + res.beDifferenceOf(gcoords, guess); + + // check for convergence + error = res.computeNorm(); + if ( error < convergence_limit ) { + break; + } + + // compute the corrections + this->giveJacobianMatrixAt(jac, answer, cellgeo); + jac.solveForRhs(res, delta); + + // update guess + answer.add(delta); + } + if ( error > convergence_limit ) { // Imperfect, could give false negatives. + //OOFEM_ERROR("no convergence after 10 iterations"); + answer.zero(); + return false; + } + + // check limits for each local coordinate [-1,1] for quadrilaterals. (different for other elements, typically [0,1]). + bool inside = true; + for ( int i = 1; i <= answer.giveSize(); i++ ) { + if ( answer.at(i) < ( -1. - POINT_TOL ) ) { + answer.at(i) = -1.; + inside = false; + } else if ( answer.at(i) > ( 1. + POINT_TOL ) ) { + answer.at(i) = 1.; + inside = false; + } + } + + return inside; +} + +double FEI3dWedgeQuad :: giveCharacteristicLength(const FEICellGeometry &cellgeo) const +{ + const auto &n1 = cellgeo.giveVertexCoordinates(1); + const auto &n2 = cellgeo.giveVertexCoordinates(4); + ///@todo Change this so that it is not dependent on node order. + return distance(n1, n2); } + double -FEI3dWedgeQuad :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeQuad :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatMatrix jacobianMatrix; this->giveJacobianMatrixAt(jacobianMatrix, lcoords, cellgeo); - return jacobianMatrix.giveDeterminant() / 2.; ///@todo Should this really be a factor 1/2 here? + return jacobianMatrix.giveDeterminant(); } void -FEI3dWedgeQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeQuad :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const // Returns the jacobian matrix J (x,y,z)/(ksi,eta,dzeta) of the receiver. { FloatMatrix dNduvw, coords; - this->giveLocalDerivative(dNduvw, lcoords); + this->evaldNdxi(dNduvw, lcoords, cellgeo); coords.resize(3, 15); for ( int i = 1; i <= 15; i++ ) { - coords.setColumn(* cellgeo.giveVertexCoordinates(i), i); + coords.setColumn(cellgeo.giveVertexCoordinates(i), i); } jacobianMatrix.beProductOf(coords, dNduvw); } -void -FEI3dWedgeQuad :: giveLocalDerivative(FloatMatrix &dN, const FloatArray &lcoords) -{ - double x, y, z; - x = lcoords.at(1); - y = lcoords.at(2); - z = lcoords.at(3); - - dN.resize(15, 3); - - dN.at(1, 1) = 1. / 2. - ( z - 1. ) * ( x + y - 1. ) - z * z / 2. - ( ( z - 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2.; - dN.at(2, 1) = z * z / 2. - x * ( z - 1. ) - ( ( 2. * x - 1. ) * ( z - 1. ) ) / 2. - 1 / 2.; - dN.at(3, 1) = 0.; - dN.at(4, 1) = ( ( z + 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2. + ( z + 1. ) * ( x + y - 1. ) - z * z / 2. + 1. / 2.; - dN.at(5, 1) = ( ( 2. * x - 1. ) * ( z + 1. ) ) / 2. + x * ( z + 1. ) + z * z / 2. - 1. / 2.; - dN.at(6, 1) = 0.; - dN.at(7, 1) = ( z - 1. ) * ( 2. * x + 2. * y - 2. ) + 2. * x * ( z - 1. ); - dN.at(8, 1) = -2. * y * ( z - 1. ); - dN.at(9, 1) = 2. * y * ( z - 1. ); - dN.at(10, 1) = -2. * ( z + 1. ) * ( x + y - 1. ) - 2. * x * ( z + 1. ); - dN.at(11, 1) = 2. * y * ( z + 1. ); - dN.at(12, 1) = -2. * y * ( z + 1. ); - dN.at(13, 1) = z * z - 1.; - dN.at(14, 1) = 1. - z * z; - dN.at(15, 1) = 0.; - - - dN.at(1, 2) = 1. / 2. - ( z - 1. ) * ( x + y - 1. ) - z * z / 2. - ( ( z - 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2.; - dN.at(2, 2) = 0.; - dN.at(3, 2) = z * z / 2. - y * ( z - 1. ) - ( ( 2. * y - 1. ) * ( z - 1. ) ) / 2. - 1. / 2.; - dN.at(4, 2) = ( ( z + 1. ) * ( 2. * x + 2. * y - 1. ) ) / 2. + ( z + 1. ) * ( x + y - 1. ) - z * z / 2. + 1. / 2.; - dN.at(5, 2) = 0.; - dN.at(6, 2) = ( ( 2. * y - 1. ) * ( z + 1. ) ) / 2. + y * ( z + 1. ) + z * z / 2. - 1. / 2.; - dN.at(7, 2) = 2. * x * ( z - 1. ); - dN.at(8, 2) = -2. * x * ( z - 1. ); - dN.at(9, 2) = 2. * ( z - 1. ) * ( x + y - 1. ) + 2. * y * ( z - 1. ); - dN.at(10, 2) = -2. * x * ( z + 1. ); - dN.at(11, 2) = 2. * x * ( z + 1. ); - dN.at(12, 2) = -2. * ( z + 1. ) * ( x + y - 1. ) - 2. * y * ( z + 1. ); - dN.at(13, 2) = z * z - 1.; - dN.at(14, 2) = 0.; - dN.at(15, 2) = 1. - z * z; - - - dN.at(1, 3) = -z * ( x + y - 1. ) - ( ( 2. * x + 2. * y - 1. ) * ( x + y - 1. ) ) / 2.; - dN.at(2, 3) = x * z - ( x * ( 2. * x - 1. ) ) / 2.; - dN.at(3, 3) = y * z - ( y * ( 2 * y - 1. ) ) / 2.; - dN.at(4, 3) = ( ( 2. * x + 2. * y - 1. ) * ( x + y - 1. ) ) / 2. - z * ( x + y - 1. ); - dN.at(5, 3) = ( x * ( 2. * x - 1. ) ) / 2. + x * z; - dN.at(6, 3) = ( y * ( 2. * y - 1. ) ) / 2. + y * z; - dN.at(7, 3) = x * ( 2. * x + 2. * y - 2. ); - dN.at(8, 3) = -2. * x * y; - dN.at(9, 3) = 2. * y * ( x + y - 1. ); - dN.at(10, 3) = -2. * x * ( x + y - 1. ); - dN.at(11, 3) = 2. * x * y; - dN.at(12, 3) = -2. * y * ( x + y - 1. ); - dN.at(13, 3) = 2. * z * ( x + y - 1. ); - dN.at(14, 3) = -2. * x * z; - dN.at(15, 3) = -2. * y * z; -} - - -void FEI3dWedgeQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI3dWedgeQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { double ksi = lcoords.at(1); answer.resize(3); @@ -227,55 +359,55 @@ void FEI3dWedgeQuad :: edgeEvalN(FloatArray &answer, int iedge, const FloatArray } -void FEI3dWedgeQuad :: edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI3dWedgeQuad :: edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("not implemented"); } -void FEI3dWedgeQuad :: edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEI3dWedgeQuad :: edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray nodes; FloatArray n; - this->computeLocalEdgeMapping(nodes, iedge); + const auto &nodes = this->computeLocalEdgeMapping(iedge); this->edgeEvalN(n, iedge, lcoords, cellgeo); answer.clear(); for ( int i = 1; i <= n.giveSize(); ++i ) { - answer.add( n.at(i), * cellgeo.giveVertexCoordinates( nodes.at(i) ) ); + answer.add( n.at(i), cellgeo.giveVertexCoordinates( nodes.at(i) ) ); } } -void -FEI3dWedgeQuad :: computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) +IntArray +FEI3dWedgeQuad :: computeLocalEdgeMapping(int iedge) const { if ( iedge == 1 ) { - edgeNodes = {1, 2, 7}; + return {1, 2, 7}; } else if ( iedge == 2 ) { - edgeNodes = {2, 3, 8}; + return {2, 3, 8}; } else if ( iedge == 3 ) { - edgeNodes = {3, 1, 9}; + return {3, 1, 9}; } else if ( iedge == 4 ) { - edgeNodes = {4, 5, 10}; + return {4, 5, 10}; } else if ( iedge == 5 ) { - edgeNodes = {5, 6, 11}; + return {5, 6, 11}; } else if ( iedge == 6 ) { - edgeNodes = {6, 4, 12}; + return {6, 4, 12}; } else if ( iedge == 7 ) { - edgeNodes = {1, 4, 13}; + return {1, 4, 13}; } else if ( iedge == 8 ) { - edgeNodes = {2, 5, 14}; + return {2, 5, 14}; } else if ( iedge == 9 ) { - edgeNodes = {3, 6, 15}; + return {3, 6, 15}; } else { - OOFEM_ERROR("Edge %d doesn't exist.\n", iedge); + throw std::range_error("invalid edge number"); + return {}; } } -double FEI3dWedgeQuad :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEI3dWedgeQuad :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("not implemented"); return 0.0; @@ -283,7 +415,7 @@ double FEI3dWedgeQuad :: edgeGiveTransformationJacobian(int iedge, const FloatAr void -FEI3dWedgeQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { if ( isurf <= 2 ) { double l1, l2, l3; @@ -317,47 +449,46 @@ FEI3dWedgeQuad :: surfaceEvalN(FloatArray &answer, int isurf, const FloatArray & void FEI3dWedgeQuad :: surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - IntArray nodes; FloatArray n; - this->computeLocalSurfaceMapping(nodes, isurf); + const auto &nodes = this->computeLocalSurfaceMapping(isurf); this->surfaceEvalN(n, isurf, lcoords, cellgeo); answer.clear(); for ( int i = 1; i <= n.giveSize(); ++i ) { - answer.add( n.at(i), * cellgeo.giveVertexCoordinates( nodes.at(i) ) ); + answer.add( n.at(i), cellgeo.giveVertexCoordinates( nodes.at(i) ) ); } } -void -FEI3dWedgeQuad :: computeLocalSurfaceMapping(IntArray &nodes, int isurf) +IntArray +FEI3dWedgeQuad :: computeLocalSurfaceMapping(int isurf) const { if ( isurf == 1 ) { - nodes = {1, 2, 3, 7, 8, 9}; + return {1, 2, 3, 7, 8, 9}; } else if ( isurf == 2 ) { - nodes = {4, 5, 6, 10, 11, 12}; + return {4, 5, 6, 10, 11, 12}; } else if ( isurf == 3 ) { - nodes = {1, 2, 5, 4, 7, 14, 10, 13}; + return {1, 2, 5, 4, 7, 14, 10, 13}; } else if ( isurf == 4 ) { - nodes = {2, 3, 6, 5, 8, 15, 11, 14}; + return {2, 3, 6, 5, 8, 15, 11, 14}; } else if ( isurf == 5 ) { - nodes = {3, 1, 4, 6, 9, 13, 12, 15}; + return {3, 1, 4, 6, 9, 13, 12, 15}; } else { OOFEM_ERROR("Surface %d doesn't exist.\n", isurf); + return {}; } } double -FEI3dWedgeQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray a, b, dNdksi, dNdeta; - IntArray snodes; - this->computeLocalSurfaceMapping(snodes, isurf); + const auto &snodes = this->computeLocalSurfaceMapping(isurf); if ( snodes.giveSize() == 6 ) { double l1, l2, l3; @@ -407,8 +538,8 @@ FEI3dWedgeQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatAr } for ( int i = 1; i <= snodes.giveSize(); ++i ) { - a.add( dNdksi.at(i), * cellgeo.giveVertexCoordinates( snodes.at(i) ) ); - b.add( dNdeta.at(i), * cellgeo.giveVertexCoordinates( snodes.at(i) ) ); + a.add( dNdksi.at(i), cellgeo.giveVertexCoordinates( snodes.at(i) ) ); + b.add( dNdeta.at(i), cellgeo.giveVertexCoordinates( snodes.at(i) ) ); } answer.beVectorProductOf(a, b); @@ -417,30 +548,30 @@ FEI3dWedgeQuad :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatAr double -FEI3dWedgeQuad :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEI3dWedgeQuad :: surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray normal; return this->surfaceEvalNormal(normal, isurf, lcoords, cellgeo); } -IntegrationRule * -FEI3dWedgeQuad :: giveIntegrationRule(int order) +std::unique_ptr +FEI3dWedgeQuad :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); ///@todo This function below isn't supported. We must decide on how to deal with wedges. //int points = iRule->getRequiredNumberOfIntegrationPoints(_Wedge, order); OOFEM_WARNING("Warning.. ignoring 'order' argument: FIXME"); int pointsZeta = 1; int pointsTriangle = 1; iRule->SetUpPointsOnWedge(pointsTriangle, pointsZeta, _Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule * -FEI3dWedgeQuad :: giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr +FEI3dWedgeQuad :: giveBoundaryIntegrationRule(int order, int boundary) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); if ( boundary <= 2 ) { int points = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, order + 2); iRule->SetUpPointsOnTriangle(points, _Unknown); @@ -449,6 +580,6 @@ FEI3dWedgeQuad :: giveBoundaryIntegrationRule(int order, int boundary) int points = iRule->getRequiredNumberOfIntegrationPoints(_Square, order + 2); iRule->SetUpPointsOnSquare(points, _Unknown); } - return iRule; + return std::move(iRule); } } // end namespace oofem diff --git a/src/oofemlib/fei3dwedgequad.h b/src/oofemlib/fei3dwedgequad.h index 00b7669a4..295358e4f 100644 --- a/src/oofemlib/fei3dwedgequad.h +++ b/src/oofemlib/fei3dwedgequad.h @@ -52,52 +52,54 @@ class OOFEM_EXPORT FEI3dWedgeQuad : public FEInterpolation3d public: FEI3dWedgeQuad() : FEInterpolation3d(1) { } - virtual integrationDomain giveIntegrationDomain() const { return _Wedge; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_wedge_2; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { - if (ib <= 2) return _Triangle; - else return _Square; } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { return this->giveBoundaryIntegrationDomain(isurf); } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { return _Line; } + integrationDomain giveIntegrationDomain() const override { return _Wedge; } + Element_Geometry_Type giveGeometryType() const override { return EGT_wedge_2; } + integrationDomain giveBoundaryIntegrationDomain(int ib) const override + { + if (ib <= 2) return _Triangle; + else return _Square; + } + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { return this->giveBoundaryIntegrationDomain(isurf); } + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { return _Line; } - - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); + static FloatArrayF<15> evalN(const FloatArrayF<3> &lcoords); + static std::pair> evaldNdx(const FloatArrayF<3> &lcoords, const FEICellGeometry &cellgeo); + static FloatMatrixF<3,15> evaldNdxi(const FloatArrayF<3> &lcoords); + + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void evaldNdxi(FloatMatrix & answer, const FloatArray & lcoords, const FEICellGeometry & cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const override; + double giveCharacteristicLength(const FEICellGeometry &cellgeo) const; + double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; // Edge - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void giveLocalNodeCoords(FloatMatrix &answer); - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge); + void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void giveLocalNodeCoords(FloatMatrix &answer) const override; + void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalEdgeMapping(int iedge) const override; // Surface - virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void surfaceLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void computeLocalSurfaceMapping(IntArray &nodes, int iSurf); + void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void surfaceLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray computeLocalSurfaceMapping(int iSurf) const override; - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; - virtual IntegrationRule *giveIntegrationRule(int order); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary); - virtual IntegrationRule *giveSurfaceIntegrationRule(int order, int isurf) - { return giveBoundaryIntegrationRule(order, isurf); } + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; + std::unique_ptr giveSurfaceIntegrationRule(int order, int isurf) const + { return giveBoundaryIntegrationRule(order, isurf); } - virtual int giveNumberOfNodes() const { return 15; } + int giveNumberOfNodes() const override { return 15; } protected: - double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo); - void giveLocalDerivative(FloatMatrix &dN, const FloatArray &lcoords); + double edgeComputeLength(IntArray &edgeNodes, const FEICellGeometry &cellgeo) const; }; } // end namespace oofem #endif diff --git a/src/oofemlib/feinterpol.C b/src/oofemlib/feinterpol.C index 2eaf2cb8f..37647db68 100644 --- a/src/oofemlib/feinterpol.C +++ b/src/oofemlib/feinterpol.C @@ -40,7 +40,7 @@ namespace oofem { int FEIElementGeometryWrapper :: giveNumberOfVertices() const { return elem->giveNumberOfNodes(); } double -FEInterpolation :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEInterpolation :: giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatMatrix jacobianMatrix; this->giveJacobianMatrixAt(jacobianMatrix, lcoords, cellgeo); @@ -48,50 +48,48 @@ FEInterpolation :: giveTransformationJacobian(const FloatArray &lcoords, const F } -IntegrationRule* -FEInterpolation:: giveIntegrationRule(int order) +std::unique_ptr +FEInterpolation:: giveIntegrationRule(int order) const { - integrationDomain id = this->giveIntegrationDomain(); - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + integrationDomain id = this->giveIntegrationDomain(); + auto iRule = std::make_unique(1, nullptr); - int points = iRule->getRequiredNumberOfIntegrationPoints(id, order + this->order); - iRule->SetUpPointsOnLine(points, _Unknown); - return iRule; + int points = iRule->getRequiredNumberOfIntegrationPoints(id, order + this->order); + iRule->SetUpPointsOnLine(points, _Unknown); + return std::move(iRule); } -IntegrationRule* -FEInterpolation::giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr +FEInterpolation::giveBoundaryIntegrationRule(int order, int boundary) const { - integrationDomain id = this->giveBoundaryIntegrationDomain(boundary); - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + integrationDomain id = this->giveBoundaryIntegrationDomain(boundary); + auto iRule = std::make_unique(1, nullptr); - int points = iRule->getRequiredNumberOfIntegrationPoints(id, order + this->order); - iRule->setUpIntegrationPoints(id, points, _Unknown); - return iRule; + int points = iRule->getRequiredNumberOfIntegrationPoints(id, order + this->order); + iRule->setUpIntegrationPoints(id, points, _Unknown); + return std::move(iRule); } -IntegrationRule* -FEInterpolation::giveBoundaryEdgeIntegrationRule(int order, int boundary) +std::unique_ptr +FEInterpolation::giveBoundaryEdgeIntegrationRule(int order, int boundary) const { - integrationDomain id = this->giveBoundaryEdgeIntegrationDomain(boundary); - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + integrationDomain id = this->giveBoundaryEdgeIntegrationDomain(boundary); + auto iRule = std::make_unique(1, nullptr); - int points = iRule->getRequiredNumberOfIntegrationPoints(id, order + this->order); - iRule->setUpIntegrationPoints(id, points, _Unknown); - return iRule; + int points = iRule->getRequiredNumberOfIntegrationPoints(id, order + this->order); + iRule->setUpIntegrationPoints(id, points, _Unknown); + return std::move(iRule); } -IntegrationRule* -FEInterpolation::giveBoundarySurfaceIntegrationRule(int order, int boundary) +std::unique_ptr +FEInterpolation::giveBoundarySurfaceIntegrationRule(int order, int boundary) const { - integrationDomain id = this->giveBoundarySurfaceIntegrationDomain(boundary); - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + integrationDomain id = this->giveBoundarySurfaceIntegrationDomain(boundary); + auto iRule = std::make_unique(1, nullptr); - int points = iRule->getRequiredNumberOfIntegrationPoints(id, order + this->order); - iRule->setUpIntegrationPoints(id, points, _Unknown); - return iRule; -} - - + int points = iRule->getRequiredNumberOfIntegrationPoints(id, order + this->order); + iRule->setUpIntegrationPoints(id, points, _Unknown); + return std::move(iRule); +} } // end namespace oofem diff --git a/src/oofemlib/feinterpol.h b/src/oofemlib/feinterpol.h index 065b5a8d4..537c4c663 100644 --- a/src/oofemlib/feinterpol.h +++ b/src/oofemlib/feinterpol.h @@ -52,6 +52,9 @@ class FloatMatrix; class IntArray; class IntegrationRule; +template class FloatArrayF; +template class FloatMatrixF; + /** * Class representing a general abstraction for cell geometry. * The motivation for this class is that the interpolation classes require to pass underlying cell geometry. @@ -65,7 +68,7 @@ class OOFEM_EXPORT FEICellGeometry FEICellGeometry() { } virtual ~FEICellGeometry() { } virtual int giveNumberOfVertices() const = 0; - virtual const FloatArray *giveVertexCoordinates(int i) const = 0; + virtual const FloatArray &giveVertexCoordinates(int i) const = 0; }; @@ -75,16 +78,19 @@ class OOFEM_EXPORT FEICellGeometry */ class OOFEM_EXPORT FEIVoidCellGeometry : public FEICellGeometry { + FloatArray tmp; public: FEIVoidCellGeometry() : FEICellGeometry() { } virtual ~FEIVoidCellGeometry() { } - int giveNumberOfVertices() const { + int giveNumberOfVertices() const override + { OOFEM_ERROR("no reference geometry"); return 0; } - const FloatArray *giveVertexCoordinates(int i) const { + const FloatArray &giveVertexCoordinates(int i) const override + { OOFEM_ERROR("no reference geometry"); - return NULL; + return tmp; } std :: string errorInfo(const char *func) const { return func; } ///@todo Class name? }; @@ -97,14 +103,13 @@ class OOFEM_EXPORT FEIElementGeometryWrapper : public FEICellGeometry protected: const Element *elem; public: - FEIElementGeometryWrapper(const Element * elem) : FEICellGeometry() { - this->elem = elem; - } + FEIElementGeometryWrapper(const Element * elem) : + FEICellGeometry(), elem(elem) { } virtual ~FEIElementGeometryWrapper() { } - int giveNumberOfVertices() const; - inline const FloatArray *giveVertexCoordinates(int i) const + int giveNumberOfVertices() const override; + const FloatArray &giveVertexCoordinates(int i) const override { - return &(elem->giveNode(i)->giveNodeCoordinates()); + return elem->giveNode(i)->giveCoordinates(); } }; @@ -121,8 +126,8 @@ class OOFEM_EXPORT FEIVertexListGeometryWrapper : public FEICellGeometry FEIVertexListGeometryWrapper(const std::vector< FloatArray > &coords) : FEICellGeometry(), coords(coords) { } virtual ~FEIVertexListGeometryWrapper() { } - int giveNumberOfVertices() const { return (int)this->coords.size(); } - const FloatArray *giveVertexCoordinates(int i) const { return &this->coords [ i - 1 ]; } + int giveNumberOfVertices() const override { return (int)this->coords.size(); } + const FloatArray &giveVertexCoordinates(int i) const override { return this->coords [ i - 1 ]; } }; /** @@ -132,16 +137,13 @@ class OOFEM_EXPORT FEIVertexListGeometryWrapper : public FEICellGeometry class OOFEM_EXPORT FEInterpolation { protected: - int order; + int order = 0; public: - FEInterpolation(int o) { - order = o; - } - virtual ~FEInterpolation() { } + FEInterpolation(int o) : order(o) { } + virtual ~FEInterpolation() = default; /// Initializes receiver according to object description stored in input record. - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } - + virtual void initializeFrom(InputRecord &ir) { } /* @name basic interpolation services */ //@{ @@ -156,14 +158,23 @@ class OOFEM_EXPORT FEInterpolation /** * Returns the interpolation order. */ - int giveInterpolationOrder() { return order; } + int giveInterpolationOrder() const { return order; } + /** + * Returns local element node numbers defining the approximation. Typically this corresponds to all element nodes. + * But for elements with mixed interpolation, we need to select subset of nodes + * (quadratic triangle with linear interpolation). This method can query element geometry type (from given element) + * and compile the nodal set. + * @brief Returns all element nodes (including on edges and surfaces) defining the approximation + * @note Required by mpm module + */ + virtual void giveCellDofMans(IntArray& nodes, Element* elem) const {} /** * Evaluates the array of interpolation functions (shape functions) at given point. * @param answer Contains resulting array of evaluated interpolation functions. * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the matrix of derivatives of interpolation functions (shape functions) at given point. * These derivatives are in global coordinate system (where the nodal coordinates are defined) @@ -172,7 +183,7 @@ class OOFEM_EXPORT FEInterpolation * @param cellgeo Underlying cell geometry. * @return Determinant of the Jacobian. */ - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the matrix of second derivatives of interpolation functions (shape functions) at given point. * These derivatives are in global coordinate system (where the nodal coordinates are defined) @@ -180,7 +191,8 @@ class OOFEM_EXPORT FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { + virtual void evald2Ndx2(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const + { OOFEM_ERROR("not implemented"); } /** @@ -190,13 +202,15 @@ class OOFEM_EXPORT FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { + virtual void evaldNdxi(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const + { OOFEM_ERROR("not implemented"); } /** * Returns a matrix containing the local coordinates for each node corresponding to the interpolation */ - virtual void giveLocalNodeCoords(FloatMatrix &answer) { + virtual void giveLocalNodeCoords(FloatMatrix &answer) const + { OOFEM_ERROR("FEInterpolation::giveLocalNodeCoords: not implemented"); } /** @@ -205,7 +219,7 @@ class OOFEM_EXPORT FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates local coordinates from given global ones. * If local coordinates cannot be found (generate elements, or point far outside geometry, @@ -215,21 +229,21 @@ class OOFEM_EXPORT FEInterpolation * @param cellgeo Underlying cell geometry. * @return Nonzero is returned if point is within the element geometry, zero otherwise. */ - virtual int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) = 0; + virtual int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the determinant of the transformation. * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. * @return Determinant of the transformation. */ - virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo); + virtual double giveTransformationJacobian(const FloatArray &lcoords, const FEICellGeometry &cellgeo) const; /** * Gives the jacobian matrix at the local coordinates. * @param jacobianMatrix The requested matrix. * @param lcoords Local coordinates. * @param cellgeo Element geometry. */ - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) + virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("Not overloaded."); } /** @@ -237,10 +251,9 @@ class OOFEM_EXPORT FEInterpolation * The required polynomial order for the determinant of the jacobian is added automatically. * @param order Polynomial order of integrand (should NOT including determinant of jacobian). */ - virtual IntegrationRule *giveIntegrationRule(int order); + virtual std::unique_ptr giveIntegrationRule(int order) const; //@} - /** @name Edge boundary functions. * Provide interpolation services for boundary edges (entity of dimension 1) */ @@ -255,7 +268,7 @@ class OOFEM_EXPORT FEInterpolation * @param cellgeo Underlying cell geometry. * @todo */ - virtual void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo)=0; + virtual void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the determinant of the transformation Jacobian on the requested boundary. * Boundaries are defined as the corner nodes for 1D geometries, edges for 2D geometries and surfaces for 3D geometries. @@ -264,7 +277,7 @@ class OOFEM_EXPORT FEInterpolation * @param cellgeo Underlying cell geometry. * @return The determinant of the boundary transformation Jacobian. */ - virtual double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo)=0; + virtual double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Maps the local boundary coordinates to global. * Boundaries are defined as the corner nodes for 1D geometries, edges for 2D geometries and surfaces for 3D geometries. @@ -273,7 +286,7 @@ class OOFEM_EXPORT FEInterpolation * @param lcoords The local coordinates (on the boundary local coordinate system). * @param cellgeo Underlying cell geometry. */ - virtual void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo)=0; + virtual void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /// Returns boundary integration domain virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int boundary) const = 0; /** @@ -282,13 +295,13 @@ class OOFEM_EXPORT FEInterpolation * @param order Polynomial order of the integrand (should NOT including determinant of jacobian). * @param boundary Boundary number. */ - virtual IntegrationRule *giveBoundaryEdgeIntegrationRule(int order, int boundary); + virtual std::unique_ptr giveBoundaryEdgeIntegrationRule(int order, int boundary) const ; /** * Gives the boundary nodes for requested boundary number. * @param answer Array to be filled with the boundary nodes. * @param boundary Boundary number. */ - virtual void boundaryEdgeGiveNodes(IntArray &answer, int boundary)=0; + virtual IntArray boundaryEdgeGiveNodes(int boundary) const = 0; //@} /**@name Surface interpolation services @@ -302,7 +315,7 @@ class OOFEM_EXPORT FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the matrix of derivatives of edge interpolation functions (shape functions) at given point. * These derivatives are in global coordinate system (where the nodal coordinates are defined). @@ -311,8 +324,7 @@ class OOFEM_EXPORT FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void boundarySurfaceEvaldNdx(FloatMatrix &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo)=0; + virtual void boundarySurfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the normal out of the surface at given point. * @param answer Contains resulting normal vector. @@ -321,8 +333,7 @@ class OOFEM_EXPORT FEInterpolation * @param cellgeo Underlying cell geometry. * @return Surface mapping jacobian. */ - virtual double boundarySurfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo)=0; + virtual double boundarySurfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates edge global coordinates from given local ones. @@ -332,8 +343,7 @@ class OOFEM_EXPORT FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void boundarySurfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo)=0; + virtual void boundarySurfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0; /** * Evaluates the edge jacobian of transformation between local and global coordinates. * @param isurf Determines the surface number. @@ -341,8 +351,7 @@ class OOFEM_EXPORT FEInterpolation * @param cellgeo Underlying cell geometry. * @return Determinant of the transformation. */ - virtual double boundarySurfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo)=0; + virtual double boundarySurfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /// Returns boundary integration domain virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int boundary) const = 0; /** @@ -351,14 +360,13 @@ class OOFEM_EXPORT FEInterpolation * @param order Polynomial order of the integrand (should NOT including determinant of jacobian). * @param boundary Boundary number. */ - virtual IntegrationRule *giveBoundarySurfaceIntegrationRule(int order, int boundary); + virtual std::unique_ptr giveBoundarySurfaceIntegrationRule(int order, int boundary) const ; /** * Gives the boundary nodes for requested boundary number. * @param answer Array to be filled with the boundary nodes. * @param boundary Boundary number. */ - virtual void boundarySurfaceGiveNodes(IntArray &answer, int boundary)=0; - + virtual IntArray boundarySurfaceGiveNodes(int boundary) const = 0; //@} /** @name General boundary interpolation functions. @@ -373,7 +381,7 @@ class OOFEM_EXPORT FEInterpolation * @param answer Array to be filled with the boundary nodes. * @param boundary Boundary number. */ - virtual void boundaryGiveNodes(IntArray &answer, int boundary) = 0; + virtual IntArray boundaryGiveNodes(int boundary) const = 0; /** * Evaluates the basis functions on the requested boundary. * Only basis functions that are nonzero anywhere on the boundary are given. Ordering can be obtained from giveBoundaryNodes. @@ -383,7 +391,7 @@ class OOFEM_EXPORT FEInterpolation * @param lcoords The local coordinates (on the boundary local coordinate system). * @param cellgeo Underlying cell geometry. */ - virtual void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the normal on the requested boundary. * @param answer The evaluated normal. @@ -392,7 +400,7 @@ class OOFEM_EXPORT FEInterpolation * @param cellgeo Underlying cell geometry. * @return The boundary transformation Jacobian. */ - virtual double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the determinant of the transformation Jacobian on the requested boundary. * Boundaries are defined as the corner nodes for 1D geometries, edges for 2D geometries and surfaces for 3D geometries. @@ -401,7 +409,7 @@ class OOFEM_EXPORT FEInterpolation * @param cellgeo Underlying cell geometry. * @return The determinant of the boundary transformation Jacobian. */ - virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Maps the local boundary coordinates to global. * Boundaries are defined as the corner nodes for 1D geometries, edges for 2D geometries and surfaces for 3D geometries. @@ -410,14 +418,15 @@ class OOFEM_EXPORT FEInterpolation * @param lcoords The local coordinates (on the boundary local coordinate system). * @param cellgeo Underlying cell geometry. */ - virtual void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Computes the integral @f$ \int_S n \cdot x \mathrm{d}s @f$. * @param boundary Boundary number. * @param cellgeo Underlying cell geometry. * @return Evaluated integral. */ - virtual double evalNXIntegral(int boundary, const FEICellGeometry &cellgeo) { + virtual double evalNXIntegral(int boundary, const FEICellGeometry &cellgeo) const + { OOFEM_ERROR("Not implemented"); return 0.; } @@ -429,8 +438,7 @@ class OOFEM_EXPORT FEInterpolation * @param order Polynomial order of the integrand (should NOT including determinant of jacobian). * @param boundary Boundary number. */ - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary) ; - + virtual std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const; //@} /**@name Methods to support interpolation defined on patch by patch basis. */ @@ -441,52 +449,50 @@ class OOFEM_EXPORT FEInterpolation * @return Nonzero if mask is provided, zero otherwise meaning that all * basis functions are generally nonzero. */ - virtual int giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask) { return 0; } + virtual int giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask) const { return 0; } /** * Returns the number of nonzero basis functions at individual knot span, - * @return Zero in case of all basis functions generally nonzero, answer otherwise. + * @return Zero in case of all basis functions generaedgeEvaldNdslly nonzero, answer otherwise. */ - virtual int giveNumberOfKnotSpanBasisFunctions(const IntArray &knotSpan) { return 0; } + virtual int giveNumberOfKnotSpanBasisFunctions(const IntArray &knotSpan) const { return 0; } /** * Returns true, if receiver is formulated on sub-patch basis. */ - virtual bool hasSubPatchFormulation() { return false; } + virtual bool hasSubPatchFormulation() const { return false; } /** * Returns the subdivision of patch parametric space */ - virtual const double *const *giveKnotVector() { - return NULL; - } + virtual const FloatArray *giveKnotVector() const { return nullptr; } /** * Returns the number of knot spans of the receiver. */ - virtual int giveNumberOfKnotSpans(int dim) { return 0; } + virtual int giveNumberOfKnotSpans(int dim) const { return 0; } /** * Returns the knot values of the receiver. */ - virtual const FloatArray *giveKnotValues(int dim) { return NULL; } + virtual const FloatArray *giveKnotValues(int dim) const { return nullptr; } /** * Returns the knot multiplicity of the receiver. */ - virtual const IntArray *giveKnotMultiplicity(int dim) { return NULL; } + virtual const IntArray *giveKnotMultiplicity(int dim) const { return nullptr; } /** * Returns number of spatial dimensions. */ - virtual int giveNsd() = 0; + virtual int giveNsd() const = 0; /** * Returns number of edges. */ virtual int giveNumberOfEdges() const - { OOFEM_ERROR("FEInterpolation :: giveNumberOfEdges : Not overloaded."); return -1;} + { OOFEM_ERROR("FEInterpolation :: giveNumberOfEdges : Not overloaded."); return -1; } //@} /** * Returns the number of geometric nodes of the receiver. */ virtual int giveNumberOfNodes() const - { OOFEM_ERROR("giveNumberOfNodes: Not overloaded."); return -1;} + { OOFEM_ERROR("giveNumberOfNodes: Not overloaded."); return -1; } //@} - + std :: string errorInfo(const char *func) const { return func; } ///@todo Class name? }; } // end namespace oofem diff --git a/src/oofemlib/feinterpol1d.C b/src/oofemlib/feinterpol1d.C index 150b1259d..cc3a949cb 100644 --- a/src/oofemlib/feinterpol1d.C +++ b/src/oofemlib/feinterpol1d.C @@ -35,53 +35,54 @@ #include "feinterpol1d.h" #include "floatarray.h" #include "gaussintegrationrule.h" +#include namespace oofem { -void FEInterpolation1d :: boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation1d :: boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { answer.resize(1); answer.at(1) = 1.; } -void FEInterpolation1d :: boundaryGiveNodes(IntArray &answer, int boundary) +IntArray FEInterpolation1d :: boundaryGiveNodes(int boundary) const { - OOFEM_ERROR("Not implemented"); + throw std::runtime_error("Not implemented"); } -double FEInterpolation1d :: boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEInterpolation1d :: boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("Not implemented"); return 1.; } -double FEInterpolation1d :: boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEInterpolation1d :: boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return 1.; } -void FEInterpolation1d :: boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation1d :: boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - answer = * cellgeo.giveVertexCoordinates(boundary); + answer = cellgeo.giveVertexCoordinates(boundary); } -IntegrationRule *FEInterpolation1d :: giveIntegrationRule(int order) +std::unique_ptr FEInterpolation1d :: giveIntegrationRule(int order) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Line, order + this->order); iRule->SetUpPointsOnLine(points, _Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule *FEInterpolation1d :: giveBoundaryIntegrationRule(int order, int boundary) +std::unique_ptr FEInterpolation1d :: giveBoundaryIntegrationRule(int order, int boundary) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); iRule->SetUpPoint(_Unknown); - return iRule; + return std::move(iRule); } -IntegrationRule *FEInterpolation1d :: giveBoundaryEdgeIntegrationRule(int order, int boundary) +std::unique_ptr FEInterpolation1d :: giveBoundaryEdgeIntegrationRule(int order, int boundary) const { return this->giveIntegrationRule(order); } diff --git a/src/oofemlib/feinterpol1d.h b/src/oofemlib/feinterpol1d.h index b2bd99435..50d0e030b 100644 --- a/src/oofemlib/feinterpol1d.h +++ b/src/oofemlib/feinterpol1d.h @@ -36,6 +36,7 @@ #define feinterpol1d_h #include "feinterpol.h" +#include namespace oofem { /** @@ -45,38 +46,32 @@ class OOFEM_EXPORT FEInterpolation1d : public FEInterpolation { public: FEInterpolation1d(int o) : FEInterpolation(o) { } - virtual int giveNsd() { return 1; } + int giveNsd() const override { return 1; } - //virtual FloatArray giveParametricCenter() const { return {0.}; } + //FloatArray giveParametricCenter() const override { return {0.}; } - virtual void boundaryGiveNodes(IntArray &answer, int boundary); - virtual void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + IntArray boundaryGiveNodes(int boundary) const override; + void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; /**@name Surface interpolation services */ //@{ - virtual void boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) {OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual void boundarySurfaceEvaldNdx(FloatMatrix &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + void boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual double boundarySurfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + void boundarySurfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual void boundarySurfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + double boundarySurfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual double boundarySurfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + void boundarySurfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual void boundarySurfaceGiveNodes(IntArray &answer, int boundary) + double boundarySurfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } - + IntArray boundarySurfaceGiveNodes(int boundary) const override + { throw std::runtime_error("Functions not supported for this interpolator."); } //@} - - /** * Computes the exact length. * @param cellgeo Cell geometry for the element. @@ -88,9 +83,9 @@ class OOFEM_EXPORT FEInterpolation1d : public FEInterpolation return 0; } - virtual IntegrationRule *giveIntegrationRule(int order); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary); - virtual IntegrationRule *giveBoundaryEdgeIntegrationRule(int order, int boundary); + std::unique_ptr giveIntegrationRule(int order) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override; + std::unique_ptr giveBoundaryEdgeIntegrationRule(int order, int boundary) const override; }; } // end namespace oofem #endif // feinterpol1d_h diff --git a/src/oofemlib/feinterpol2d.C b/src/oofemlib/feinterpol2d.C index eca85c85d..35f0fa61a 100644 --- a/src/oofemlib/feinterpol2d.C +++ b/src/oofemlib/feinterpol2d.C @@ -37,22 +37,22 @@ #include "gaussintegrationrule.h" namespace oofem { -void FEInterpolation2d :: boundaryEdgeGiveNodes(IntArray &answer, int boundary) +IntArray FEInterpolation2d :: boundaryEdgeGiveNodes(int boundary) const { - this->computeLocalEdgeMapping(answer, boundary); + return this->computeLocalEdgeMapping(boundary); } -void FEInterpolation2d :: boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation2d :: boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - this->edgeEvalN(answer, boundary, lcoords, cellgeo); + this->edgeEvalN(answer, boundary, lcoords, cellgeo); } -double FEInterpolation2d :: boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEInterpolation2d :: boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); } -void FEInterpolation2d :: boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation2d :: boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->edgeLocal2global(answer, boundary, lcoords, cellgeo); } @@ -65,7 +65,7 @@ double FEInterpolation2d :: giveArea(const FEICellGeometry &cellgeo) const #define POINT_TOL 1.e-3 -int FEInterpolation2d :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) +int FEInterpolation2d :: global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const { FloatArray res, delta, guess, lcoords_guess; FloatMatrix jac; @@ -109,10 +109,9 @@ int FEInterpolation2d :: global2local(FloatArray &answer, const FloatArray &gcoo } void -FEInterpolation2d :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +FEInterpolation2d :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const // Returns the jacobian matrix J (x,y)/(ksi,eta) of the receiver. { - double x, y; FloatMatrix dn; jacobianMatrix.resize(2, 2); @@ -121,8 +120,8 @@ FEInterpolation2d :: giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const Flo this->evaldNdxi(dn, lcoords, cellgeo ); for ( int i = 1; i <= dn.giveNumberOfRows(); i++ ) { - x = cellgeo.giveVertexCoordinates(i)->at(xind); - y = cellgeo.giveVertexCoordinates(i)->at(yind); + double x = cellgeo.giveVertexCoordinates(i).at(xind); + double y = cellgeo.giveVertexCoordinates(i).at(yind); jacobianMatrix.at(1, 1) += dn.at(i, 1) * x; jacobianMatrix.at(2, 1) += dn.at(i, 1) * y; @@ -136,85 +135,84 @@ bool FEInterpolation2d ::inside(const FloatArray &lcoords) const OOFEM_ERROR("Not implemented.") } -void FEInterpolation2d :: boundaryGiveNodes(IntArray &answer, int boundary) +IntArray FEInterpolation2d :: boundaryGiveNodes(int boundary) const { - this->computeLocalEdgeMapping(answer, boundary); + return this->computeLocalEdgeMapping(boundary); } -void FEInterpolation2d :: boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation2d :: boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->edgeEvalN(answer, boundary, lcoords, cellgeo); } -double FEInterpolation2d :: boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEInterpolation2d :: boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->edgeEvalNormal(answer, boundary, lcoords, cellgeo); } -double FEInterpolation2d :: boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEInterpolation2d :: boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); } -void FEInterpolation2d :: boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation2d :: boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->edgeLocal2global(answer, boundary, lcoords, cellgeo); } -void FEInterpolation2d :: computeEdgeMapping(IntArray &edgeNodes, IntArray &elemNodes, int iedge) +IntArray FEInterpolation2d :: computeEdgeMapping(const IntArray &elemNodes, int iedge) const { - IntArray ln; - this->computeLocalEdgeMapping(ln, iedge); + const auto& ln = this->computeLocalEdgeMapping(iedge); int size = ln.giveSize(); - edgeNodes.resize(size); + IntArray edgeNodes(size); for ( int i = 1; i <= size; i++ ) { edgeNodes.at(i) = elemNodes.at( ln.at(i) ); } + return edgeNodes; } -double FEInterpolation2d :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEInterpolation2d :: edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { FloatArray normal; return this->edgeEvalNormal(normal, iedge, lcoords, cellgeo); } -void FEInterpolation2d::boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation2d::boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->evalN(answer, lcoords, cellgeo); } void FEInterpolation2d::boundarySurfaceEvaldNdx(FloatMatrix &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->evaldNdx(answer, lcoords, cellgeo); } double FEInterpolation2d::boundarySurfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + const FEICellGeometry &cellgeo) const { - answer = {0,0,1}; - return this->giveTransformationJacobian(lcoords, cellgeo); + answer = {0, 0, 1}; + return this->giveTransformationJacobian(lcoords, cellgeo); } void FEInterpolation2d::boundarySurfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - this->local2global(answer, lcoords, cellgeo); + this->local2global(answer, lcoords, cellgeo); } double FEInterpolation2d::boundarySurfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + const FEICellGeometry &cellgeo) const { return this->giveTransformationJacobian(lcoords, cellgeo); } -void FEInterpolation2d::boundarySurfaceGiveNodes(IntArray &answer, int boundary) +IntArray FEInterpolation2d::boundarySurfaceGiveNodes(int boundary) const { - int nnode = this->giveNumberOfNodes(); - answer.resize(nnode); - for (int i =1; i<=nnode; i++) { - answer.at(i)=i; - } + int nnode = this->giveNumberOfNodes(); + IntArray answer(nnode); + answer.enumerate(nnode); + return answer; } diff --git a/src/oofemlib/feinterpol2d.h b/src/oofemlib/feinterpol2d.h index 86f820c96..bc4ae27a7 100644 --- a/src/oofemlib/feinterpol2d.h +++ b/src/oofemlib/feinterpol2d.h @@ -50,7 +50,7 @@ class OOFEM_EXPORT FEInterpolation2d : public FEInterpolation public: FEInterpolation2d(int o, int ind1, int ind2) : FEInterpolation(o), xind(ind1), yind(ind2) { } - virtual int giveNsd() { return 2; } + int giveNsd() const override { return 2; } /** * Computes the exact area. @@ -64,15 +64,15 @@ class OOFEM_EXPORT FEInterpolation2d : public FEInterpolation * @param cellgeo Underlying cell geometry. * @return Square root of area. */ - virtual double giveCharacteristicLength(const FEICellGeometry &cellgeo) const {return sqrt( this->giveArea(cellgeo) );} + virtual double giveCharacteristicLength (const FEICellGeometry &cellgeo) const {return sqrt( this->giveArea(cellgeo) );} /** * Default implementation using Newton's method to find the local coordinates. * Can be overloaded if desired. */ - virtual int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo); + int global2local(FloatArray &answer, const FloatArray &gcoords, const FEICellGeometry &cellgeo) const override; - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; virtual bool inside(const FloatArray &lcoords) const; @@ -81,38 +81,32 @@ class OOFEM_EXPORT FEInterpolation2d : public FEInterpolation than the interpolation represents */ //@{ - virtual void boundaryEdgeGiveNodes(IntArray &answer, int boundary); - virtual void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - - virtual void boundaryGiveNodes(IntArray &answer, int boundary); - virtual void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - + IntArray boundaryEdgeGiveNodes(int boundary) const override; + void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + + IntArray boundaryGiveNodes(int boundary) const override; + void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; //@} - /**@name Surface interpolation services */ //@{ - virtual void boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void boundarySurfaceEvaldNdx(FloatMatrix &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundarySurfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); - virtual void boundarySurfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) ; - virtual double boundarySurfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) ; - virtual void boundarySurfaceGiveNodes(IntArray &answer, int boundary); + void boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void boundarySurfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundarySurfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void boundarySurfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundarySurfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + IntArray boundarySurfaceGiveNodes(int boundary) const override; //@} /**@name Edge interpolation services. */ //@{ - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) = 0; - void computeEdgeMapping(IntArray &edgeNodes, IntArray &elemNodes, int iedge); + virtual IntArray computeLocalEdgeMapping(int iedge) const = 0; + IntArray computeEdgeMapping(const IntArray &elemNodes, int iedge) const; /** * Evaluates the array of edge interpolation functions (shape functions) at given point. * @param answer Contains resulting array of evaluated interpolation functions. @@ -120,7 +114,7 @@ class OOFEM_EXPORT FEInterpolation2d : public FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the normal on the given edge. * @param answer Contains the evaluated normal. @@ -128,7 +122,7 @@ class OOFEM_EXPORT FEInterpolation2d : public FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual double edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual double edgeEvalNormal(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the matrix of derivatives of edge interpolation functions (shape functions) at given point. * These derivatives are in global coordinate system (where the nodal coordinates are defined). @@ -137,9 +131,7 @@ class OOFEM_EXPORT FEInterpolation2d : public FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void edgeEvaldNds(FloatArray &answer, int iedge, - const FloatArray &lcoords, - const FEICellGeometry &cellgeo) = 0; + virtual void edgeEvaldNds(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates edge global coordinates from given local ones. * These derivatives are in global coordinate system (where the nodal coordinates are defined). @@ -148,8 +140,7 @@ class OOFEM_EXPORT FEInterpolation2d : public FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the edge Jacobian of transformation between local and global coordinates. * @param iedge Determines edge number. @@ -157,8 +148,7 @@ class OOFEM_EXPORT FEInterpolation2d : public FEInterpolation * @param cellgeo Underlying cell geometry. * @return Determinant of the mapping on the given edge. */ - virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); + virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const ; //@} }; diff --git a/src/oofemlib/feinterpol3d.C b/src/oofemlib/feinterpol3d.C index b5e18483b..b22f2037c 100644 --- a/src/oofemlib/feinterpol3d.C +++ b/src/oofemlib/feinterpol3d.C @@ -43,102 +43,100 @@ double FEInterpolation3d :: giveVolume(const FEICellGeometry &cellgeo) const return 0; } -void FEInterpolation3d :: boundaryEdgeGiveNodes(IntArray &answer, int boundary) +IntArray FEInterpolation3d :: boundaryEdgeGiveNodes(int boundary) const { - this->computeLocalEdgeMapping(answer, boundary); + return this->computeLocalEdgeMapping(boundary); } -void FEInterpolation3d :: boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation3d :: boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->edgeEvalN(answer, boundary, lcoords, cellgeo); } -double FEInterpolation3d :: boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEInterpolation3d :: boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->edgeGiveTransformationJacobian(boundary, lcoords, cellgeo); } -void FEInterpolation3d :: boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation3d :: boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->edgeLocal2global(answer, boundary, lcoords, cellgeo); } -void FEInterpolation3d :: boundaryGiveNodes(IntArray &answer, int boundary) +IntArray FEInterpolation3d :: boundaryGiveNodes(int boundary) const { - this->computeLocalSurfaceMapping(answer, boundary); + return this->computeLocalSurfaceMapping(boundary); } -void FEInterpolation3d :: boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation3d :: boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { this->surfaceEvalN(answer, boundary, lcoords, cellgeo); } -double FEInterpolation3d :: boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEInterpolation3d :: boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->surfaceEvalNormal(answer, boundary, lcoords, cellgeo); } -double FEInterpolation3d :: boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEInterpolation3d :: boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->surfaceGiveTransformationJacobian(boundary, lcoords, cellgeo); } -void FEInterpolation3d :: boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation3d :: boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { return this->surfaceLocal2global(answer, boundary, lcoords, cellgeo); } -void FEInterpolation3d :: computeEdgeMapping(IntArray &edgeNodes, IntArray &elemNodes, int iedge) +IntArray FEInterpolation3d :: computeEdgeMapping(const IntArray &elemNodes, int iedge) const { - int size; - IntArray ln; - this->computeLocalEdgeMapping(ln, iedge); - size = ln.giveSize(); - edgeNodes.resize(size); + const auto &ln = this->computeLocalEdgeMapping(iedge); + int size = ln.giveSize(); + IntArray edgeNodes(size); for ( int i = 1; i <= size; i++ ) { edgeNodes.at(i) = elemNodes.at( ln.at(i) ); } + return edgeNodes; } -void FEInterpolation3d :: computeSurfaceMapping(IntArray &surfNodes, IntArray &elemNodes, int isurf) +IntArray FEInterpolation3d :: computeSurfaceMapping(const IntArray &elemNodes, int isurf) const { - int size; - IntArray ln; - this->computeLocalSurfaceMapping(ln, isurf); - size = ln.giveSize(); - surfNodes.resize(size); + const auto &ln = this->computeLocalSurfaceMapping(isurf); + int size = ln.giveSize(); + IntArray surfNodes(size); for ( int i = 1; i <= size; i++ ) { surfNodes.at(i) = elemNodes.at( ln.at(i) ); } + return surfNodes; } -IntegrationRule *FEInterpolation3d :: giveBoundaryEdgeIntegrationRule(int order, int boundary) +std::unique_ptr FEInterpolation3d :: giveBoundaryEdgeIntegrationRule(int order, int boundary) const { - IntegrationRule *iRule = new GaussIntegrationRule(1, NULL); + auto iRule = std::make_unique(1, nullptr); int points = iRule->getRequiredNumberOfIntegrationPoints(_Line, order + this->order); iRule->SetUpPointsOnLine(points, _Unknown); return iRule; } -void FEInterpolation3d :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation3d :: edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("Not implemented"); } -void FEInterpolation3d :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void FEInterpolation3d :: surfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("Not implemented"); } -double FEInterpolation3d :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double FEInterpolation3d :: surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { OOFEM_ERROR("Not implemented"); return -1.0; } -void FEInterpolation3d::boundarySurfaceGiveNodes(IntArray &answer, int boundary) +IntArray FEInterpolation3d::boundarySurfaceGiveNodes(int boundary) const { - this->computeLocalSurfaceMapping(answer, boundary); + return this->computeLocalSurfaceMapping(boundary); } } // end namespace oofem diff --git a/src/oofemlib/feinterpol3d.h b/src/oofemlib/feinterpol3d.h index a1b71fc72..01cbc988e 100644 --- a/src/oofemlib/feinterpol3d.h +++ b/src/oofemlib/feinterpol3d.h @@ -45,7 +45,7 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation { public: FEInterpolation3d(int o) : FEInterpolation(o) { } - virtual int giveNsd() { return 3; } + int giveNsd() const override { return 3; } /** * Computes the exact volume. @@ -54,32 +54,27 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation */ virtual double giveVolume(const FEICellGeometry &cellgeo) const; - virtual void boundaryEdgeGiveNodes(IntArray &answer, int boundary); - virtual void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + IntArray boundaryEdgeGiveNodes(int boundary) const override; + void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override + { this->surfaceEvalN(answer, isurf, lcoords, cellgeo); } + void boundarySurfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override + { this->surfaceEvaldNdx(answer, isurf, lcoords, cellgeo); } + double boundarySurfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override + { return surfaceEvalNormal(answer, isurf, lcoords, cellgeo); } + void boundarySurfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override + { this->surfaceLocal2global(answer, isurf, lcoords, cellgeo); } + double boundarySurfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override + { return this->surfaceGiveTransformationJacobian(isurf, lcoords, cellgeo); } - virtual void boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) {this->surfaceEvalN(answer, isurf, lcoords, cellgeo);} - virtual void boundarySurfaceEvaldNdx(FloatMatrix &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) - {this->surfaceEvaldNdx(answer, isurf, lcoords, cellgeo);} - virtual double boundarySurfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) - {return surfaceEvalNormal(answer, isurf, lcoords, cellgeo);} - virtual void boundarySurfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) - {this->surfaceLocal2global(answer, isurf, lcoords, cellgeo);} - virtual double boundarySurfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) - {return this->surfaceGiveTransformationJacobian(isurf, lcoords, cellgeo);} - - - virtual void boundaryGiveNodes(IntArray &answer, int boundary); - virtual void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + IntArray boundaryGiveNodes(int boundary) const override; + void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; /**@name Edge interpolation services */ //@{ @@ -90,7 +85,7 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void edgeEvalN(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the matrix of derivatives of edge interpolation functions (shape functions) at given point. * These derivatives are in global coordinate system (where the nodal coordinates are defined) @@ -99,8 +94,7 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void edgeEvaldNdx(FloatMatrix &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void edgeEvaldNdx(FloatMatrix &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the matrix of derivatives of edge interpolation functions (shape functions) at given point. * These derivatives are in local (parent) coordinate system @@ -109,8 +103,7 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void edgeEvaldNdxi(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); + virtual void edgeEvaldNdxi(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const ; /** * Evaluates edge global coordinates from given local ones. * These derivatives are in global coordinate system (where the nodal coordinates are defined). @@ -119,8 +112,7 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void edgeLocal2global(FloatArray &answer, int iedge, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void edgeLocal2global(FloatArray &answer, int iedge, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the edge jacobian of transformation between local and global coordinates. * @param iedge Determines edge number. @@ -128,12 +120,10 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation * @param cellgeo Underlying cell geometry. * @return Determinant of the transformation. */ - virtual double edgeGiveTransformationJacobian(int iedge, - const FloatArray &lcoords, - const FEICellGeometry &cellgeo) = 0; + virtual double edgeGiveTransformationJacobian(int iedge, const FloatArray &lcoords,const FEICellGeometry &cellgeo) const = 0; - virtual void computeLocalEdgeMapping(IntArray &edgeNodes, int iedge) = 0; - void computeEdgeMapping(IntArray &edgeNodes, IntArray &elemNodes, int iedge); + virtual IntArray computeLocalEdgeMapping(int iedge) const = 0; + IntArray computeEdgeMapping(const IntArray &elemNodes, int iedge) const; //@} /**@name Surface interpolation services */ @@ -145,7 +135,7 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void surfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the matrix of derivatives of edge interpolation functions (shape functions) at given point. * These derivatives are in global coordinate system (where the nodal coordinates are defined). @@ -154,8 +144,7 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void surfaceEvaldNdx(FloatMatrix &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo); + virtual void surfaceEvaldNdx(FloatMatrix &answer, int isurf,const FloatArray &lcoords, const FEICellGeometry &cellgeo) const ; /** * Evaluates the normal out of the surface at given point. * @param answer Contains resulting normal vector. @@ -164,8 +153,7 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation * @param cellgeo Underlying cell geometry. * @return Surface mapping jacobian. */ - virtual double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo); + virtual double surfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const ; /** * Evaluates edge global coordinates from given local ones. @@ -175,8 +163,7 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation * @param lcoords Array containing (local) coordinates. * @param cellgeo Underlying cell geometry. */ - virtual void surfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) = 0; + virtual void surfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; /** * Evaluates the edge jacobian of transformation between local and global coordinates. * @param isurf Determines the surface number. @@ -184,20 +171,19 @@ class OOFEM_EXPORT FEInterpolation3d : public FEInterpolation * @param cellgeo Underlying cell geometry. * @return Determinant of the transformation. */ - virtual double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) = 0; + virtual double surfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const = 0; - virtual void computeLocalSurfaceMapping(IntArray &surfNodes, int isurf) = 0; - void computeSurfaceMapping(IntArray &surfNodes, IntArray &elemNodes, int isurf); + virtual IntArray computeLocalSurfaceMapping(int isurf) const = 0; + IntArray computeSurfaceMapping(const IntArray &elemNodes, int isurf) const; //@} - virtual IntegrationRule *giveBoundaryEdgeIntegrationRule(int order, int boundary); - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary) - { - OOFEM_ERROR("Not overloaded"); - return NULL; + std::unique_ptr giveBoundaryEdgeIntegrationRule(int order, int boundary) const override; + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override + { + OOFEM_ERROR("Not overloaded"); + return nullptr; }; - virtual void boundarySurfaceGiveNodes(IntArray &answer, int boundary); + IntArray boundarySurfaceGiveNodes(int boundary) const override; }; } // end namespace oofem #endif // feinterpol3d_h diff --git a/src/oofemlib/femcmpnn.C b/src/oofemlib/femcmpnn.C index 03ad12496..d4b1e3829 100644 --- a/src/oofemlib/femcmpnn.C +++ b/src/oofemlib/femcmpnn.C @@ -47,29 +47,25 @@ namespace oofem { -contextIOResultType -FEMComponent :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +FEMComponent :: saveContext(DataStream &stream, ContextMode mode) { if ( mode & CM_Definition ) { if ( !stream.write(number) ) { THROW_CIOERR(CIO_IOERR); } } - - return CIO_OK; } -contextIOResultType -FEMComponent :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +FEMComponent :: restoreContext(DataStream &stream, ContextMode mode) { if ( mode & CM_Definition ) { if ( !stream.read(number) ) { THROW_CIOERR(CIO_IOERR); } } - - return CIO_OK; } @@ -86,9 +82,8 @@ FEMComponent :: errorInfo(const char *func) const return std :: string(this->giveClassName()) + "::" + func + ", number: " + std::to_string(this->giveNumber()); } -IRResultType FEMComponent :: initializeFrom(InputRecord* ir) +void FEMComponent :: initializeFrom(InputRecord &ir) { - return IRRT_OK; } int FEMComponent :: checkConsistency() diff --git a/src/oofemlib/femcmpnn.h b/src/oofemlib/femcmpnn.h index 69de47bcb..48e4d5d28 100644 --- a/src/oofemlib/femcmpnn.h +++ b/src/oofemlib/femcmpnn.h @@ -45,7 +45,6 @@ #include "oofemcfg.h" #include "interfacetype.h" -#include "irresulttype.h" #include "contextioresulttype.h" #include "contextmode.h" @@ -90,7 +89,7 @@ class OOFEM_EXPORT FEMComponent */ FEMComponent(int n, Domain * d) : number(n), domain(d) { } /// Virtual destructor. - virtual ~FEMComponent() { } + virtual ~FEMComponent() = default; /// @return Class name of the receiver. virtual const char *giveClassName() const = 0; @@ -127,9 +126,8 @@ class OOFEM_EXPORT FEMComponent * @see IR_GIVE_FIELD * @see IR_GIVE_OPTIONAL_FIELD * @param ir Input record to initialize from. - * @return IRResultType */ - virtual IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); /** * Setups the input record string of receiver. * @param input Dynamic input record to be filled by receiver. @@ -139,21 +137,17 @@ class OOFEM_EXPORT FEMComponent * Stores receiver state to output stream. * @param stream Output stream. * @param mode Determines amount of info required in stream (state, definition, ...). - * @param obj Special parameter, used only to send particular integration point to material class version of this method. - * @return contextIOResultType. * @exception throws an ContextIOERR exception if error encountered. */ - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); + virtual void saveContext(DataStream &stream, ContextMode mode); /** * Restores the receiver state previously written in stream. * @see saveContext * @param stream Input stream. * @param mode Determines amount of info available in stream (state, definition, ...). - * @param obj Special parameter for sending extra information. - * @return contextIOResultType. * @exception throws an ContextIOERR exception if error encountered. */ - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + virtual void restoreContext(DataStream &stream, ContextMode mode); /** * Allows programmer to test some internal data, before computation begins. * For example, one may use this function, to ensure that element has material with @@ -176,7 +170,7 @@ class OOFEM_EXPORT FEMComponent * @see InterfaceType * @return Requested interface if implemented, otherwise NULL. */ - virtual Interface *giveInterface(InterfaceType t) { return NULL; } + virtual Interface *giveInterface(InterfaceType t) { return nullptr; } /// Returns string for prepending output (used by error reporting macros). std :: string errorInfo(const char *func) const; diff --git a/src/oofemlib/field.h b/src/oofemlib/field.h index 6295367bb..e36067ae1 100644 --- a/src/oofemlib/field.h +++ b/src/oofemlib/field.h @@ -118,25 +118,22 @@ class OOFEM_EXPORT Field /// Returns the type of receiver FieldType giveType() { return type; } + + /// Sets the type of receiver + void setType(FieldType b) { type=b; } /** * Stores receiver state to output stream. - * Writes the FEMComponent class-id in order to allow test whether correct data are then restored. * @param stream Output stream. - * @param mode Determines amount of info in stream (state, definition,...). - * @return contextIOResultType. * @exception Throws an ContextIOERR exception if error encountered. */ - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode) = 0; + virtual void saveContext(DataStream &stream) = 0; /** * Restores the receiver state previously written in stream. - * Reads the FEMComponent class-id in order to allow test consistency. * @param stream Input stream. - * @param mode Determines amount of info in stream (state, definition,...). - * @return contextIOResultType. * @exception Throws an ContextIOERR exception if error encountered. */ - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode) = 0; + virtual void restoreContext(DataStream &stream) = 0; /// Returns string for prepending output (used by error reporting macros). diff --git a/src/oofemlib/floatarray.C b/src/oofemlib/floatarray.C index 33ac963ae..0dc125d9e 100644 --- a/src/oofemlib/floatarray.C +++ b/src/oofemlib/floatarray.C @@ -80,67 +80,6 @@ bool FloatArray :: isFinite() const return true; } -#ifdef DEBUG -double & -FloatArray :: operator() (int i) -{ - if ( i >= this->giveSize() ) { - OOFEM_ERROR("array error on index : %d >= %d", i, this->giveSize()); - } - return values [ i ]; -} - -const double & -FloatArray :: operator() (int i) const -{ - if ( i >= this->giveSize() ) { - OOFEM_ERROR("array error on index : %d >= %d", i, this->giveSize()); - } - return values [ i ]; -} -double & -FloatArray :: operator[] (int i) -{ - if ( i >= this->giveSize() ) { - OOFEM_ERROR("array error on index : %d >= %d", i, this->giveSize()); - } - return values [ i ]; -} - -const double & -FloatArray :: operator[] (int i) const -{ - if ( i >= this->giveSize() ) { - OOFEM_ERROR("array error on index : %d >= %d", i, this->giveSize()); - } - return values [ i ]; -} - -double &FloatArray :: at(int i) -{ - this->checkBounds(i); - return values [ i - 1 ]; -} - -double FloatArray :: at(int i) const -{ - this->checkBounds(i); - return values [ i - 1 ]; -} - -#endif -void FloatArray :: checkBounds(int i) const -// Checks that the receiver's size is not smaller than 'i'. -{ - if ( i <= 0 ) { - OOFEM_ERROR("array error on index : %d <= 0", i); - } - - if ( i > this->giveSize() ) { - OOFEM_ERROR("array error on index : %d > %d", i, this->giveSize()); - } -} - void FloatArray :: beScaled(double s, const FloatArray &b) @@ -167,7 +106,7 @@ void FloatArray :: add(const FloatArray &b) return; } -# ifdef DEBUG +# ifndef NDEBUG if ( this->giveSize() != b.giveSize() ) { OOFEM_ERROR("dimension mismatch in a[%d]->add(b[%d])", this->giveSize(), b.giveSize()); } @@ -204,7 +143,7 @@ void FloatArray :: add(double factor, const FloatArray &b) return; } -# ifdef DEBUG +# ifndef NDEBUG if ( this->giveSize() != b.giveSize() ) { OOFEM_ERROR("dimension mismatch in a[%d]->add(b[%d])", this->giveSize(), b.giveSize()); } @@ -233,7 +172,7 @@ void FloatArray :: plusProduct(const FloatMatrix &b, const FloatArray &s, double this->values.assign( nColumns, 0. ); } -# ifdef DEBUG +# ifndef NDEBUG if ( this->giveSize() != b.giveNumberOfColumns() ) { OOFEM_ERROR( "dimension mismatch in a[%d] and b[%d, *]", this->giveSize(), b.giveNumberOfColumns() ); } @@ -272,7 +211,7 @@ void FloatArray :: subtract(const FloatArray &src) return; } -# ifdef DEBUG +# ifndef NDEBUG if ( this->giveSize() != src.giveSize() ) { OOFEM_ERROR("dimension mismatch in a[%d]->add(b[%d])", this->giveSize(), src.giveSize()); } @@ -297,7 +236,7 @@ void FloatArray :: beMaxOf(const FloatArray &a, const FloatArray &b) return; } -# ifdef DEBUG +# ifndef NDEBUG if ( n != b.giveSize() ) { OOFEM_ERROR("dimension mismatch in beMaxOf(a[%d],b[%d])", n, b.giveSize()); } @@ -324,7 +263,7 @@ void FloatArray :: beMinOf(const FloatArray &a, const FloatArray &b) return; } -# ifdef DEBUG +# ifndef NDEBUG if ( n != b.giveSize() ) { OOFEM_ERROR("dimension mismatch in beMinOf(a[%d],b[%d])", n, b.giveSize()); } @@ -340,7 +279,7 @@ void FloatArray :: beMinOf(const FloatArray &a, const FloatArray &b) void FloatArray :: beDifferenceOf(const FloatArray &a, const FloatArray &b) { -#ifdef DEBUG +#ifndef NDEBUG if ( a.giveSize() != b.giveSize() ) { OOFEM_ERROR("size mismatch (%d : %d)", a.giveSize(), b.giveSize()); } @@ -363,7 +302,7 @@ void FloatArray :: beDifferenceOf(const FloatArray &a, const FloatArray &b) void FloatArray :: beDifferenceOf(const FloatArray &a, const FloatArray &b, int n) { -#ifdef DEBUG +#ifndef NDEBUG if ( a.giveSize() < n || b.giveSize() < n ) { OOFEM_ERROR("wrong size ", a.giveSize(), b.giveSize()); } @@ -382,7 +321,7 @@ void FloatArray :: beSubArrayOf(const FloatArray &src, const IntArray &indx) // this->at(i) = src.at(indx->at(i)) // { -#ifdef DEBUG +#ifndef NDEBUG if ( indx.maximum() > src.giveSize() || indx.minimum() < 1 ) { OOFEM_ERROR("index points outside of source"); } @@ -414,7 +353,7 @@ void FloatArray :: addSubVector(const FloatArray &src, int si) void FloatArray :: beVectorProductOf(const FloatArray &v1, const FloatArray &v2) { -# if DEBUG +# ifndef NDEBUG // check proper bounds if ( ( v1.giveSize() != 3 ) || ( v2.giveSize() != 3 ) ) { OOFEM_ERROR("size mismatch, size is not equal to 3"); @@ -462,7 +401,7 @@ int FloatArray :: giveIndexMaxElem() double FloatArray :: dotProduct(const FloatArray &x) const { -# ifdef DEBUG +# ifndef NDEBUG if ( this->giveSize() != x.giveSize() ) { OOFEM_ERROR("dimension mismatch in a[%d]->dotProduct(b[%d])", this->giveSize(), x.giveSize()); } @@ -475,7 +414,7 @@ double FloatArray :: dotProduct(const FloatArray &x) const double FloatArray :: dotProduct(const FloatArray &x, int size) const { -# ifdef DEBUG +# ifndef NDEBUG if ( size > this->giveSize() || size > x.giveSize() ) { OOFEM_ERROR("dimension mismatch in a[%d]->dotProduct(b[%d])", this->giveSize(), x.giveSize()); } @@ -540,7 +479,7 @@ double FloatArray :: distance_square(const FloatArray &from) const double dist = 0.; int s = min(this->giveSize(), from.giveSize()); for ( int i = 1; i <= s; ++i ) { - double dx = this->at(i) - from.at(i); ///@todo This isn't a distance to "from"?! + double dx = this->at(i) - from.at(i); dist += dx * dx; } @@ -553,7 +492,7 @@ void FloatArray :: assemble(const FloatArray &fe, const IntArray &loc) // element) to the receiver, using loc as location array. { int n = fe.giveSize(); -# ifdef DEBUG +# ifndef NDEBUG if ( n != loc.giveSize() ) { OOFEM_ERROR("dimensions of 'fe' (%d) and 'loc' (%d) mismatch", fe.giveSize(), loc.giveSize() ); } @@ -574,7 +513,7 @@ void FloatArray :: assembleSquared(const FloatArray &fe, const IntArray &loc) // element) to the receiver, using loc as location array. { int n = fe.giveSize(); -# ifdef DEBUG +# ifndef NDEBUG if ( n != loc.giveSize() ) { OOFEM_ERROR("dimensions of 'fe' (%d) and 'loc' (%d) mismatch", fe.giveSize(), loc.giveSize() ); } @@ -614,7 +553,7 @@ void FloatArray :: reserve(int s) void FloatArray :: resizeWithValues(int n, int allocChunk) { -#ifdef DEBUG +#ifndef NDEBUG if ( allocChunk < 0 ) { OOFEM_FATAL("allocChunk must be non-negative; %d", allocChunk); } @@ -681,7 +620,7 @@ void FloatArray :: beProductOf(const FloatMatrix &aMatrix, const FloatArray &anA FAST_RESIZE(nRows); -# ifdef DEBUG +# ifndef NDEBUG if ( aMatrix.giveNumberOfColumns() != anArray.giveSize() ) { OOFEM_ERROR("dimension mismatch (%d, %d) . (%d)", aMatrix.giveNumberOfRows(), aMatrix.giveNumberOfColumns(), anArray.giveSize()); @@ -711,7 +650,7 @@ void FloatArray :: beTProductOf(const FloatMatrix &aMatrix, const FloatArray &an int nRows = aMatrix.giveNumberOfRows(); int nColumns = aMatrix.giveNumberOfColumns(); -# ifdef DEBUG +# ifndef NDEBUG if ( aMatrix.giveNumberOfRows() != anArray.giveSize() ) { OOFEM_ERROR( "dimension mismatch, matrix rows = %d, array size = %d", aMatrix.giveNumberOfRows(), anArray.giveSize() ); } @@ -982,17 +921,53 @@ double dot(const FloatArray &x, const FloatArray &y) return x.dotProduct(y); } +double distance(const FloatArray &x, const FloatArray &y) +{ + return x.distance(y); +} + +double distance_square(const FloatArray &x, const FloatArray &y) +{ + return x.distance_square(y); +} + double norm(const FloatArray &x) { return x.computeNorm(); } +double norm_square(const FloatArray &x) +{ + return x.computeSquaredNorm(); +} + +bool isfinite(const FloatArray &x) +{ + return x.isFinite(); +} + +bool iszero(const FloatArray &x) +{ + return x.containsOnlyZeroes(); +} + +double sum(const FloatArray & x) +{ + return x.sum(); +} + +double product(const FloatArray & x) +{ + return x.product(); +} + + // End of IML compat void FloatArray :: beVectorForm(const FloatMatrix &aMatrix) { // Rewrites the matrix on vector form, order: 11, 22, 33, 23, 13, 12, 32, 31, 21 -# ifdef DEBUG +# ifndef NDEBUG if ( aMatrix.giveNumberOfColumns() != 3 || aMatrix.giveNumberOfColumns() != 3 ) { OOFEM_ERROR("matrix dimension is not 3x3"); } @@ -1015,7 +990,7 @@ void FloatArray :: beSymVectorFormOfStrain(const FloatMatrix &aMatrix) { // Revrites a symmetric strain matrix on reduced vector form, order: 11, 22, 33, 23, 13, 12 // shear components are multiplied with a factor 2 -# ifdef DEBUG +# ifndef NDEBUG if ( aMatrix.giveNumberOfColumns() != 3 || aMatrix.giveNumberOfColumns() != 3 ) { OOFEM_ERROR("matrix dimension is not 3x3"); } @@ -1035,7 +1010,7 @@ void FloatArray :: beSymVectorFormOfStrain(const FloatMatrix &aMatrix) void FloatArray :: beSymVectorForm(const FloatMatrix &aMatrix) { // Revrites the matrix on vector form (symmetrized matrix used), order: 11, 22, 33, 23, 13, 12 -# ifdef DEBUG +# ifndef NDEBUG if ( aMatrix.giveNumberOfColumns() != 3 || aMatrix.giveNumberOfColumns() != 3 ) { OOFEM_ERROR("matrix dimension is not 3x3"); } @@ -1088,7 +1063,7 @@ std :: ostream &operator << ( std :: ostream & out, const FloatArray & x ) //void FloatArray :: beReducedVectorFormOfStrain(const FloatMatrix &aMatrix) //{ // // Revrites the matrix on vector form (symmetrized matrix used), order: 11, 22, 33, 23, 13, 12 -//# ifdef DEBUG +//# ifndef NDEBUG // if ( aMatrix.giveNumberOfColumns() !=3 || aMatrix.giveNumberOfColumns() !=3) { // OOFEM_ERROR("matrix dimension is not 3x3"); // } diff --git a/src/oofemlib/floatarray.h b/src/oofemlib/floatarray.h index b9cc80bdd..90ff11a43 100644 --- a/src/oofemlib/floatarray.h +++ b/src/oofemlib/floatarray.h @@ -38,6 +38,7 @@ #include "oofemcfg.h" #include "contextioresulttype.h" #include "contextmode.h" +#include "error.h" #include #include @@ -47,6 +48,7 @@ namespace oofem { class IntArray; class FloatMatrix; class DataStream; +template class FloatArrayF; /** * Class representing vector of real numbers. This array can grow or shrink to @@ -104,8 +106,14 @@ class OOFEM_EXPORT FloatArray FloatArray(FloatArray &&src) : values(std::move(src.values)) { } /// Initializer list constructor. inline FloatArray(std :: initializer_list< double >list) : values(list) { } + /// Wrapper to direct assignment from iterator pairs + template< class InputIt > + FloatArray( InputIt first, InputIt last ) : values(first, last) { } + /// Wrapper to direct assignment from iterator pairs + template< std::size_t N > + inline FloatArray( const FloatArrayF &src ) : values(src.begin(), src.end()) { } /// Destructor. - virtual ~FloatArray() {}; + virtual ~FloatArray() {} /// Assignment operator FloatArray &operator = (const FloatArray &src) { values = src.values; return *this; } @@ -113,9 +121,12 @@ class OOFEM_EXPORT FloatArray FloatArray &operator = (FloatArray &&src) { values = std::move(src.values); return *this; } /// Assignment operator. inline FloatArray &operator = (std :: initializer_list< double >list) { values = list; return *this; } + /// Assign from fixed size array + template< std::size_t N > + inline FloatArray &operator = (const FloatArrayF &src) { values.assign(src.begin(), src.end()); return *this; } /// Add one element - void push_back(const double &iVal) {values.push_back(iVal);} + void push_back(double iVal) { values.push_back(iVal); } /// Returns true if no element is NAN or infinite bool isFinite() const; @@ -125,56 +136,69 @@ class OOFEM_EXPORT FloatArray * position of the receiver. Provides 1-based indexing access. * @param i Position of coefficient in array. */ -#ifdef DEBUG - double &at(int i); -#else - inline double &at(int i) { return values [ i - 1 ]; } + inline double &at(int i) + { +#ifndef NDEBUG + this->checkBounds( i ); #endif + return values [ i - 1 ]; + } /** * Coefficient access function. Returns l-value of coefficient at given * position of the receiver. Provides 1-based indexing access. * @param i Position of coefficient in array. */ -#ifdef DEBUG - double at(int i) const; -#else - inline double at(int i) const { return values [ i - 1 ]; } + inline double at(int i) const + { +#ifndef NDEBUG + this->checkBounds( i ); #endif + return values [ i - 1 ]; + } /** * Coefficient access function. Returns value of coefficient at given * position of the receiver. Provides 0-based indexing access. * @param i Position of coefficient in array. */ -#ifdef DEBUG - double &operator() (int i); - double &operator[] (int i); -#else - inline double &operator() (int i) { - return values [ i ]; - }; - inline double &operator[] (int i) { - return values [ i ]; - }; + inline double &operator() (int i) { return this->operator[](i); } + inline double &operator[] (int i) + { +#ifndef NDEBUG + if ( i >= this->giveSize() ) { + OOFEM_ERROR( "array error on index : %d >= %d", i, this->giveSize() ); + } #endif + return values [ i ]; + } /** * Coefficient access function. Returns value of coefficient at given * position of the receiver. Provides 0-based indexing access. * @param i Position of coefficient in array. */ -#ifdef DEBUG - const double &operator() (int i) const; - const double &operator[] (int i) const; -#else - inline const double &operator() (int i) const { return values [ i ]; } - inline const double &operator[] (int i) const { return values [ i ]; } + inline const double &operator() (int i) const { return this->operator[](i); } + inline const double &operator[] (int i) const { +#ifndef NDEBUG + if ( i >= this->giveSize() ) { + OOFEM_ERROR( "array error on index : %d >= %d", i, this->giveSize() ); + } #endif - /** Checks size of receiver towards requested bounds. + return values [ i ]; + } + /** + * Checks size of receiver towards requested bounds. * Current implementation will call exit(1), if dimension * mismatch found. * @param i Required size of receiver. */ - void checkBounds(int i) const; + void checkBounds(int i) const + { + if ( i <= 0 ) { + OOFEM_ERROR("array error on index : %d <= 0", i); + } else if ( i > this->giveSize() ) { + OOFEM_ERROR("array error on index : %d > %d", i, this->giveSize()); + } + } /** * Checks size of receiver towards values stored in loc array. * Expands the receiver if loc points to coefficients beyond the size of receiver. @@ -514,7 +538,7 @@ class OOFEM_EXPORT FloatArray FloatArray &operator = ( const double & ); //@} -#ifdef BOOST_PYTHON +#ifdef _BOOSTPYTHON_BINDINGS void __setitem__(int i, double val) { this->values[i] = val; } double __getitem__(int i) { return this->values[i]; } void beCopyOf(const FloatArray &src) { this->operator = ( src ); } @@ -526,16 +550,23 @@ const FloatArray ZeroVector = {0.0,0.0,0.0}; ///@name IML compatibility //@{ /// Vector multiplication by scalar -FloatArray &operator *= ( FloatArray & x, const double & a ); -FloatArray operator *( const double & a, const FloatArray & x ); -FloatArray operator *( const FloatArray & x, const double & a ); -FloatArray operator + ( const FloatArray & x, const FloatArray & y ); -FloatArray operator - ( const FloatArray & x, const FloatArray & y ); -FloatArray &operator += ( FloatArray & x, const FloatArray & y ); -FloatArray &operator -= ( FloatArray & x, const FloatArray & y ); - -double norm(const FloatArray &x); -double dot(const FloatArray &x, const FloatArray &y); +OOFEM_EXPORT FloatArray &operator *= ( FloatArray & x, const double & a ); +OOFEM_EXPORT FloatArray operator *( const double & a, const FloatArray & x ); +OOFEM_EXPORT FloatArray operator *( const FloatArray & x, const double & a ); +OOFEM_EXPORT FloatArray operator + ( const FloatArray & x, const FloatArray & y ); +OOFEM_EXPORT FloatArray operator - ( const FloatArray & x, const FloatArray & y ); +OOFEM_EXPORT FloatArray &operator += ( FloatArray & x, const FloatArray & y ); +OOFEM_EXPORT FloatArray &operator -= ( FloatArray & x, const FloatArray & y ); + +OOFEM_EXPORT double norm(const FloatArray &x); +OOFEM_EXPORT double norm_square(const FloatArray &x); +OOFEM_EXPORT double dot(const FloatArray &x, const FloatArray &y); +OOFEM_EXPORT double distance(const FloatArray &x, const FloatArray &y); +OOFEM_EXPORT double distance_square(const FloatArray &x, const FloatArray &y); +OOFEM_EXPORT bool isfinite(const FloatArray &x); +OOFEM_EXPORT bool iszero(const FloatArray &x); +OOFEM_EXPORT double sum(const FloatArray & x); +OOFEM_EXPORT double product(const FloatArray & x); //@} } // end namespace oofem #endif // floatarray_h diff --git a/src/oofemlib/floatarrayf.h b/src/oofemlib/floatarrayf.h new file mode 100644 index 000000000..a08e5c82c --- /dev/null +++ b/src/oofemlib/floatarrayf.h @@ -0,0 +1,531 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef floatarrayf_h +#define floatarrayf_h + +#include "oofemcfg.h" +#include "contextioresulttype.h" +#include "contextmode.h" +#include "datastream.h" +#include "error.h" +#include "floatarray.h" + +#include +#include +#include +#include +#include + +namespace oofem { + +/** + * Class representing vector of real numbers with compile time fixed size. + * @author Mikael Öhman + */ +template +class OOFEM_EXPORT FloatArrayF +{ +protected: + /// Stored values. + std::array< double, N > values; + +public: + /// @name Iterator for for-each loops: + //@{ + auto begin() { return this->values.begin(); } + auto end() { return this->values.end(); } + auto begin() const { return this->values.begin(); } + auto end() const { return this->values.end(); } + //@} + + /// Copy ctor + FloatArrayF(const FloatArrayF &x) : values{x.values} { } + /// Ctor from dynamic array (size must match) + FloatArrayF(const FloatArray &x) + { +#ifndef NDEBUG + if ( x.giveSize() != N ) { + OOFEM_ERROR("Can't convert dynamic float array of size %d to fixed size %d\n", x.giveSize(), N); + } +#endif + std::copy_n(x.begin(), N, values.begin()); + } + /// Direct value ctor + template> + FloatArrayF(V... x) : values{x...} { } + /// Empty Ctor (zeroes) + FloatArrayF() : values{} { } + + /// Assignment operator + void operator = (const FloatArrayF &src) { values = src.values; } + + /** + * Coefficient access function. Returns value of coefficient at given + * position of the receiver. Provides 1-based indexing access. + * @param i Position of coefficient in array. + */ + inline double &at(int i) + { +#ifndef NDEBUG + return values.at( i - 1 ); +#else + return values [ i - 1 ]; +#endif + } + /** + * Coefficient access function. Returns l-value of coefficient at given + * position of the receiver. Provides 1-based indexing access. + * @param i Position of coefficient in array. + */ + inline double at(int i) const + { +#ifndef NDEBUG + return values.at( i - 1 ); +#else + return values [ i - 1 ]; +#endif + } + + /** + * Coefficient access function. Returns value of coefficient at given + * position of the receiver. Provides 0-based indexing access. + * @param i Position of coefficient in array. + */ + inline double &operator[] (int i) + { +#ifndef NDEBUG + return values.at( i ); +#else + return values [ i ]; +#endif + } + /** + * Coefficient access function. Returns value of coefficient at given + * position of the receiver. Provides 0-based indexing access. + * @param i Position of coefficient in array. + */ + inline const double &operator[] (int i) const { +#ifndef NDEBUG + return values.at( i ); +#else + return values [ i ]; +#endif + } + + /** + * Multi-indexing to select sub-vectors, + * @param c Position of coefficient in array. + */ + template + inline FloatArrayF operator[] (int const (&c)[M]) const + { + FloatArrayF x; + for ( std::size_t i = 0; i < M; ++i ) { + x[i] = values[ c[i] ]; + } + return x; + } + + /// Assign x into self. + template + inline void assign(const FloatArrayF &x, int const (&c)[M] ) + { + for ( std::size_t i = 0; i < M; ++i ) { + (*this)[c[i]] = x[i]; + } + } + + /// Assemble x into self. + template + inline void assemble(const FloatArrayF &x, int const (&c)[M] ) + { + for ( std::size_t i = 0; i < M; ++i ) { + (*this)[c[i]] += x[i]; + } + } + + /// Returns the size of receiver. + int size() const { return N; } + /// Returns the size of receiver. + int giveSize() const { return N; } + /** + * Print receiver on stdout with custom name. + * @param name Display name of reciever. + */ + void printYourself(const std::string &name="FloatArrayF") const + { + printf("%s (%d): \n", name.c_str(), this->size()); + for ( double x: *this ) { + printf( "%10.3e ", x ); + } + printf("\n"); + } + /** + * Gives the pointer to the raw data, breaking encapsulation. + * @return Pointer to values of array + */ + const double *givePointer() const { return values.data(); } + double *givePointer() { return values.data(); } + + contextIOResultType storeYourself(DataStream &stream) const + { + if ( !stream.write(this->givePointer(), this->size()) ) { + return CIO_IOERR; + } + return CIO_OK; + } + + contextIOResultType restoreYourself(DataStream &stream) + { + if ( !stream.read(this->givePointer(), this->size()) ) { + return CIO_IOERR; + } + return CIO_OK; + } + + int givePackSize(DataStream &buff) const + { + return buff.givePackSizeOfDouble(this->size()); + } + + //friend class FloatMatrixF; +}; + + +/// Assemble components into zero matrix. +template +inline FloatArrayF assemble(const FloatArrayF &x, int const (&c)[M] ) +{ + FloatArrayF out; + for ( std::size_t i = 0; i < M; ++i ) { + out[c[i]] = x[i]; + } + return out; +} + + +/// Print to stream +template +std::ostream & operator << ( std::ostream & out, const FloatArrayF & x ) +{ + out << x.size(); + for ( double xi : x ) { + out << " " << xi; + } + return out; +} + +/// Simple math operations +template +FloatArrayF operator * ( double a, const FloatArrayF & x ) +{ + FloatArrayF out; + for ( std::size_t i = 0; i < N; ++i ) { + out[i] = x[i] * a; + } + return out; +} + +template +FloatArrayF operator * ( const FloatArrayF & x, double a ) +{ + return a*x; +} + +/// Element-wise multiplication +template +FloatArrayF mult ( const FloatArrayF & x, const FloatArrayF & y ) +{ + FloatArrayF out; + for ( std::size_t i = 0; i < N; ++i ) { + out[i] = x[i] * y[i]; + } + return out; +} + + +template +FloatArrayF operator / ( const FloatArrayF & x, double a ) +{ + FloatArrayF out; + for ( std::size_t i = 0; i < N; ++i ) { + out[i] = x[i] / a; + } + return out; +} + +template +FloatArrayF operator ^ ( const FloatArrayF & x, double a) +{ + FloatArrayF out; + for ( std::size_t i = 0; i < N; ++i ) { + out[i] = std::pow(x[i], a); + } + return out; +} + +template +FloatArrayF operator + ( const FloatArrayF & x, const FloatArrayF & y ) +{ + FloatArrayF out; + for ( std::size_t i = 0; i < N; ++i ) { + out[i] = x[i] + y[i]; + } + return out; +} + +template +FloatArrayF operator - ( const FloatArrayF & x, const FloatArrayF & y ) +{ + FloatArrayF out; + for ( std::size_t i = 0; i < N; ++i ) { + out[i] = x[i] - y[i]; + } + return out; +} + +template +FloatArrayF operator - ( const FloatArrayF & x ) +{ + FloatArrayF out; + for ( std::size_t i = 0; i < N; ++i ) { + out[i] = - x[i]; + } + return out; +} + +template +FloatArrayF &operator += ( FloatArrayF & x, const FloatArrayF & y ) +{ + for ( std::size_t i = 0; i < N; ++i ) { + x[i] += y[i]; + } + return x; +} + +template +FloatArrayF &operator -= ( FloatArrayF & x, const FloatArrayF & y ) +{ + for ( std::size_t i = 0; i < N; ++i ) { + x[i] -= y[i]; + } + return x; +} + +template +FloatArrayF &operator *= ( FloatArrayF & x, double a ) +{ + for ( auto &v : x ) { + v *= a; + } + return x; +} + +template +FloatArrayF &operator /= ( FloatArrayF & x, double a ) +{ + for ( auto &v : x ) { + v /= a; + } + return x; +} + +template +FloatArrayF operator ^= ( FloatArrayF & x, double a) +{ + for ( auto &v : x ) { + v = std::pow(v, a); + } +} + + +/// Returns true if all coefficients of the receiver are 0, else false. +template +bool iszero(const FloatArrayF &x) +{ + for ( auto &v : x ) { + if ( v != 0. ) { + return false; + } + } + return true; +} + +/// Returns true if all coefficients of the receiver are finite, else false. +template +bool isfinite( const FloatArrayF &x ) +{ + for ( auto &val : x ) { + if ( !std::isfinite(val) ) { + return false; + } + } + return true; +} + +/// Computes the L2 norm of x +template +double norm_squared( const FloatArrayF & x ) +{ + double ans = 0.; + for ( auto &val : x ) { + ans += val * val; + } + return ans; +} + +/// Computes the L2 norm of x +template +double norm( const FloatArrayF & x ) +{ + return std::sqrt(norm_squared(x)); +} + +/// Normalizes vector (L2 norm) +template +FloatArrayF normalize( const FloatArrayF & x ) +{ + return x / norm(x); +} + +/// Computes the sum of x +template +double sum( const FloatArrayF & x ) +{ + return std::accumulate(x.begin(), x.end(), 0.); +} + +/// Computes the product of x +template +double product( const FloatArrayF & x ) +{ + return std::accumulate(x.begin(), x.end(), 1.0, [](double a, double b) { return a*b; }); +} + +/// Computes the norm(a-b)^2 +template +FloatArrayF distance_squared(const FloatArrayF &a, const FloatArrayF &b) +{ + return norm_squared(a-b); +} + +/// Computes the norm(a-b) +template +FloatArrayF distance(const FloatArrayF &a, const FloatArrayF &b) +{ + return norm(a-b); +} + +/// Computes @$ x \cross y @$ +inline FloatArrayF<3> cross( const FloatArrayF<3> & x, const FloatArrayF<3> & y ) +{ + return { + x[1] * y[2] - x[2] * y[1], + x[2] * y[0] - x[0] * y[2], + x[0] * y[1] - x[1] * y[0], + }; +} + +/// Computes @$ x_i y_i @$ +template +double dot( const FloatArrayF & x, const FloatArrayF & y ) +{ + double ans = 0.; + for ( std::size_t i = 0; i < N; ++i ) { + ans += x[i] * y[i]; + } + return ans; +} + +/** + * Swaps the fourth and sixth index in the array. This is to reorder the indices + * from OOFEM's order to Abaqus' and vice versa. + */ +inline void swap_46(FloatArrayF<6> &t) +{ + std::swap( t[3], t[5] ); +} + +inline void swap_46(FloatArrayF<9> &t) +{ + // OOFEM: 11, 22, 33, 23, 13, 12, 32, 31, 21 + // UMAT: 11, 22, 33, 12, 13, 23, 32, 21, 31 + std::swap( t[3], t[5] ); + std::swap( t[7], t[8] ); +} + +template +FloatArrayF max(const FloatArrayF &a, const FloatArrayF &b) +{ + FloatArrayF out; + for (std::size_t i = 0; i < N; ++i) { + out[i] = std::max(a[i], b[i]); + } + return out; +} + +template +FloatArrayF min(const FloatArrayF &a, const FloatArrayF &b) +{ + FloatArrayF out; + for (std::size_t i = 0; i < N; ++i) { + out[i] = std::min(a[i], b[i]); + } + return out; +} + +/// I expressed in Voigt form +const FloatArrayF<6> I6 {1., 1., 1., 0., 0., 0.}; + +/// Convert stress to strain Voigt form +inline FloatArrayF<6> to_voigt_strain(const FloatArrayF<6> &s) +{ + return {s[0], s[1], s[2], 0.5*s[3], 0.5*s[4], 0.5*s[5]}; +} + +/// Convert strain to stress Voigt form +inline FloatArrayF<6> to_voigt_stress(const FloatArrayF<6> &e) +{ + return {e[0], e[1], e[2], 2*e[3], 2*e[4], 2*e[5]}; +} + +/// For more readable code +template +FloatArrayF zeros() { + return FloatArrayF(); +} + +} // end namespace oofem +#endif // floatarrayf_h diff --git a/src/oofemlib/floatmatrix.C b/src/oofemlib/floatmatrix.C index 4ec2ee29e..8c75b6934 100644 --- a/src/oofemlib/floatmatrix.C +++ b/src/oofemlib/floatmatrix.C @@ -31,11 +31,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* - * The original idea for this class comes from - * Dubois-Pelerin, Y.: "Object-Oriented Finite Elements: Programming concepts and Implementation", - * PhD Thesis, EPFL, Lausanne, 1992. - */ #include "floatmatrix.h" #include "floatarray.h" @@ -63,7 +58,7 @@ } \ } -#ifdef BOOST_PYTHON +#ifdef _BOOSTPYTHON_BINDINGS #include #include #endif @@ -217,42 +212,11 @@ bool FloatMatrix :: isFinite() const return true; } -#ifdef DEBUG -double &FloatMatrix :: at(int i, int j) -// Returns the coefficient (i,j) of the receiver. Safer but slower than -// the inline version of method 'at'. -{ - this->checkBounds(i, j); - return values [ ( j - 1 ) * nRows + i - 1 ]; -} - -double FloatMatrix :: at(int i, int j) const -// Returns the coefficient (i,j) of the receiver. Safer but slower than -// the inline version of method 'at'. -{ - this->checkBounds(i, j); - return values [ ( j - 1 ) * nRows + i - 1 ]; -} - -double &FloatMatrix :: operator() (int i, int j) -{ - this->checkBounds(i + 1, j + 1); - return values [ j * nRows + i ]; -} - -double FloatMatrix :: operator() (int i, int j) const -{ - this->checkBounds(i + 1, j + 1); - return values [ j * nRows + i ]; -} -#endif - - void FloatMatrix :: assemble(const FloatMatrix &src, const IntArray &loc) { int ii, jj, size = src.giveNumberOfRows(); -#ifdef DEBUG +#ifndef NDEBUG if ( size != loc.giveSize() ) { OOFEM_ERROR("dimensions of 'src' and 'loc' mismatch"); } @@ -280,7 +244,7 @@ void FloatMatrix :: assemble(const FloatMatrix &src, const IntArray &rowind, con int nr = src.giveNumberOfRows(); int nc = src.giveNumberOfColumns(); -#ifdef DEBUG +#ifndef NDEBUG if ( nr != rowind.giveSize() ) { OOFEM_ERROR("row dimensions of 'src' and 'rowind' mismatch"); } @@ -301,6 +265,33 @@ void FloatMatrix :: assemble(const FloatMatrix &src, const IntArray &rowind, con } } +void FloatMatrix :: assembleT(const FloatMatrix &src, const IntArray &rowind, const IntArray &colind) +{ + int ii, jj; + int nr = src.giveNumberOfRows(); + int nc = src.giveNumberOfColumns(); + +#ifndef NDEBUG + if ( nr != rowind.giveSize() ) { + OOFEM_ERROR("row dimensions of 'src' and 'rowind' mismatch"); + } + + if ( nc != colind.giveSize() ) { + OOFEM_ERROR("column dimensions of 'src' and 'colind' mismatch"); + } +#endif + + for ( int i = 1; i <= nr; i++ ) { + if ( ( ii = rowind.at(i) ) ) { + for ( int j = 1; j <= nc; j++ ) { + if ( ( jj = colind.at(j) ) ) { + this->at(jj, ii) += src.at(i, j); + } + } + } + } +} + void FloatMatrix :: assemble(const FloatMatrix &src, const int *rowind, const int *colind) { @@ -337,9 +328,9 @@ void FloatMatrix :: beTranspositionOf(const FloatMatrix &src) void FloatMatrix :: beProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix) // Receiver = aMatrix * bMatrix { -# ifdef DEBUG +# ifndef NDEBUG if ( aMatrix.nColumns != bMatrix.nRows ) { - OOFEM_ERROR("error in product A*B : dimensions do not match"); + OOFEM_ERROR("error in product A*B : dimensions do not match, A(*,%d), B(%d,*)", aMatrix.nColumns, bMatrix.nRows); } # endif RESIZE(aMatrix.nRows, bMatrix.nColumns); @@ -367,7 +358,7 @@ void FloatMatrix :: beProductOf(const FloatMatrix &aMatrix, const FloatMatrix &b void FloatMatrix :: beTProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix) // Receiver = aMatrix^T * bMatrix { -# ifdef DEBUG +# ifndef NDEBUG if ( aMatrix.nRows != bMatrix.nRows ) { OOFEM_ERROR("error in product A*B : dimensions do not match"); } @@ -397,7 +388,7 @@ void FloatMatrix :: beTProductOf(const FloatMatrix &aMatrix, const FloatMatrix & void FloatMatrix :: beProductTOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix) // Receiver = aMatrix * bMatrix^T { -# ifdef DEBUG +# ifndef NDEBUG if ( aMatrix.nColumns != bMatrix.nColumns ) { OOFEM_ERROR("error in product A*B : dimensions do not match"); } @@ -427,7 +418,7 @@ void FloatMatrix :: beProductTOf(const FloatMatrix &aMatrix, const FloatMatrix & void FloatMatrix :: addProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix) // Receiver = aMatrix * bMatrix { -# ifdef DEBUG +# ifndef NDEBUG if ( aMatrix.nColumns != bMatrix.nRows ) { OOFEM_ERROR("error in product A*B : dimensions do not match"); } @@ -459,7 +450,7 @@ void FloatMatrix :: addProductOf(const FloatMatrix &aMatrix, const FloatMatrix & void FloatMatrix :: addTProductOf(const FloatMatrix &aMatrix, const FloatMatrix &bMatrix) // Receiver += aMatrix^T * bMatrix { -# ifdef DEBUG +# ifndef NDEBUG if ( aMatrix.nRows != bMatrix.nRows ) { OOFEM_ERROR("error in product A*B : dimensions do not match"); } @@ -560,7 +551,7 @@ void FloatMatrix :: setSubMatrix(const FloatMatrix &src, int sr, int sc) sc--; int srcRows = src.giveNumberOfRows(), srcCols = src.giveNumberOfColumns(); -#ifdef DEBUG +#ifndef NDEBUG int nr = sr + srcRows; int nc = sc + srcCols; @@ -585,7 +576,7 @@ void FloatMatrix :: setTSubMatrix(const FloatMatrix &src, int sr, int sc) sc--; int srcRows = src.giveNumberOfRows(), srcCols = src.giveNumberOfColumns(); -#ifdef DEBUG +#ifndef NDEBUG int nr = sr + srcCols; int nc = sc + srcRows; @@ -648,7 +639,7 @@ void FloatMatrix :: addSubVectorCol(const FloatArray &src, int sr, int sc) void FloatMatrix :: setColumn(const FloatArray &src, int c) { int nr = src.giveSize(); -#ifdef DEBUG +#ifndef NDEBUG if ( this->giveNumberOfRows() != nr || c < 1 || c > this->giveNumberOfColumns() ) { OOFEM_ERROR("Size mismatch"); } @@ -662,7 +653,7 @@ void FloatMatrix :: setColumn(const FloatArray &src, int c) void FloatMatrix :: copyColumn(FloatArray &dest, int c) const { int nr = this->giveNumberOfRows(); -#ifdef DEBUG +#ifndef NDEBUG if ( c < 1 || c > this->giveNumberOfColumns() ) { OOFEM_ERROR("Column outside range (%d)", c); } @@ -832,12 +823,12 @@ void FloatMatrix :: plusDyadUnsym(const FloatArray &a, const FloatArray &b, doub } -void FloatMatrix :: beInverseOf(const FloatMatrix &src) +bool FloatMatrix :: beInverseOf(const FloatMatrix &src) // Receiver becomes inverse of given parameter src. If necessary, size is adjusted. { double det; -# ifdef DEBUG +# ifndef NDEBUG if ( !src.isSquare() ) { OOFEM_ERROR("cannot inverse a %d by %d matrix", src.nRows, src.nColumns); } @@ -846,40 +837,41 @@ void FloatMatrix :: beInverseOf(const FloatMatrix &src) RESIZE(src.nRows, src.nColumns); if ( nRows == 1 ) { - this->at(1, 1) = 1. / src.at(1, 1); - return; + if (fabs(src.at(1,1)) > 1.e-30) { + this->at(1, 1) = 1. / src.at(1, 1); + return true; + } else { + return false; + } } else if ( nRows == 2 ) { det = src.at(1, 1) * src.at(2, 2) - src.at(1, 2) * src.at(2, 1); - this->at(1, 1) = src.at(2, 2) / det; - this->at(2, 1) = -src.at(2, 1) / det; - this->at(1, 2) = -src.at(1, 2) / det; - this->at(2, 2) = src.at(1, 1) / det; - return; + if (fabs(det)>1.e-30) { + this->at(1, 1) = src.at(2, 2) / det; + this->at(2, 1) = -src.at(2, 1) / det; + this->at(1, 2) = -src.at(1, 2) / det; + this->at(2, 2) = src.at(1, 1) / det; + return true; + } else { + return false; + } } else if ( nRows == 3 ) { det = src.at(1, 1) * src.at(2, 2) * src.at(3, 3) + src.at(1, 2) * src.at(2, 3) * src.at(3, 1) + src.at(1, 3) * src.at(2, 1) * src.at(3, 2) - src.at(1, 3) * src.at(2, 2) * src.at(3, 1) - src.at(2, 3) * src.at(3, 2) * src.at(1, 1) - src.at(3, 3) * src.at(1, 2) * src.at(2, 1); - - this->at(1, 1) = ( src.at(2, 2) * src.at(3, 3) - src.at(2, 3) * src.at(3, 2) ) / det; - this->at(2, 1) = ( src.at(2, 3) * src.at(3, 1) - src.at(2, 1) * src.at(3, 3) ) / det; - this->at(3, 1) = ( src.at(2, 1) * src.at(3, 2) - src.at(2, 2) * src.at(3, 1) ) / det; - this->at(1, 2) = ( src.at(1, 3) * src.at(3, 2) - src.at(1, 2) * src.at(3, 3) ) / det; - this->at(2, 2) = ( src.at(1, 1) * src.at(3, 3) - src.at(1, 3) * src.at(3, 1) ) / det; - this->at(3, 2) = ( src.at(1, 2) * src.at(3, 1) - src.at(1, 1) * src.at(3, 2) ) / det; - this->at(1, 3) = ( src.at(1, 2) * src.at(2, 3) - src.at(1, 3) * src.at(2, 2) ) / det; - this->at(2, 3) = ( src.at(1, 3) * src.at(2, 1) - src.at(1, 1) * src.at(2, 3) ) / det; - this->at(3, 3) = ( src.at(1, 1) * src.at(2, 2) - src.at(1, 2) * src.at(2, 1) ) / det; - - //p[0]= (values[4]*values[8]-values[7]*values[5])/det ; - //p[1]= (values[7]*values[2]-values[1]*values[8])/det ; - //p[2]= (values[1]*values[5]-values[4]*values[2])/det ; - //p[3]= (values[6]*values[5]-values[3]*values[8])/det ; - //p[4]= (values[0]*values[8]-values[6]*values[2])/det ; - //p[5]= (values[3]*values[2]-values[0]*values[5])/det ; - //p[6]= (values[3]*values[7]-values[6]*values[4])/det ; - //p[7]= (values[6]*values[1]-values[0]*values[7])/det ; - //p[8]= (values[0]*values[4]-values[3]*values[1])/det ; - return; + if (fabs(det)>1.e-30) { + this->at(1, 1) = ( src.at(2, 2) * src.at(3, 3) - src.at(2, 3) * src.at(3, 2) ) / det; + this->at(2, 1) = ( src.at(2, 3) * src.at(3, 1) - src.at(2, 1) * src.at(3, 3) ) / det; + this->at(3, 1) = ( src.at(2, 1) * src.at(3, 2) - src.at(2, 2) * src.at(3, 1) ) / det; + this->at(1, 2) = ( src.at(1, 3) * src.at(3, 2) - src.at(1, 2) * src.at(3, 3) ) / det; + this->at(2, 2) = ( src.at(1, 1) * src.at(3, 3) - src.at(1, 3) * src.at(3, 1) ) / det; + this->at(3, 2) = ( src.at(1, 2) * src.at(3, 1) - src.at(1, 1) * src.at(3, 2) ) / det; + this->at(1, 3) = ( src.at(1, 2) * src.at(2, 3) - src.at(1, 3) * src.at(2, 2) ) / det; + this->at(2, 3) = ( src.at(1, 3) * src.at(2, 1) - src.at(1, 1) * src.at(2, 3) ) / det; + this->at(3, 3) = ( src.at(1, 1) * src.at(2, 2) - src.at(1, 2) * src.at(2, 1) ) / det; + return true; + } else { + return false; + } } else { #ifdef __LAPACK_MODULE int n = this->nRows; @@ -890,7 +882,8 @@ void FloatMatrix :: beInverseOf(const FloatMatrix &src) // LU-factorization dgetrf_(& n, & n, this->givePointer(), & n, ipiv.givePointer(), & info); if ( info != 0 ) { - OOFEM_ERROR("dgetrf error %d", info); + OOFEM_WARNING("dgetrf error %d", info); + return false; } // Inverse @@ -898,7 +891,8 @@ void FloatMatrix :: beInverseOf(const FloatMatrix &src) FloatArray work(lwork); dgetri_(& this->nRows, this->givePointer(), & this->nRows, ipiv.givePointer(), work.givePointer(), & lwork, & info); if ( info > 0 ) { - OOFEM_ERROR("Singular at %d", info); + OOFEM_WARNING("Singular at %d", info); + return false; } else if ( info < 0 ) { OOFEM_ERROR("Error on input %d", info); } @@ -916,8 +910,9 @@ void FloatMatrix :: beInverseOf(const FloatMatrix &src) // lower triangle elimination by columns for ( int i = 1; i < nRows; i++ ) { piv = tmp.at(i, i); - if ( fabs(piv) < 1.e-24 ) { - OOFEM_ERROR("pivot (%d,%d) to close to small (< 1.e-24)", i, i); + if ( fabs(piv) < 1.e-30 ) { + OOFEM_WARNING("pivot (%d,%d) to close to small (< 1.e-20)", i, i); + return false; } for ( int j = i + 1; j <= nRows; j++ ) { @@ -954,6 +949,7 @@ void FloatMatrix :: beInverseOf(const FloatMatrix &src) this->at(i, j) /= tmp.at(i, i); } } + return true; #endif } } @@ -967,7 +963,7 @@ void FloatMatrix :: beSubMatrixOf(const FloatMatrix &src, * input parameters */ { -#ifdef DEBUG +#ifndef NDEBUG if ( ( topRow < 1 ) || ( bottomRow < 1 ) || ( topCol < 1 ) || ( bottomCol < 1 ) ) { OOFEM_ERROR("subindexes size mismatch"); } @@ -1002,7 +998,7 @@ FloatMatrix :: beSubMatrixOf(const FloatMatrix &src, const IntArray &indxRow, co * this(i,j) = src( indxRow(i), indxCol(j) ) */ { -# ifdef DEBUG +# ifndef NDEBUG if ( indxRow.maximum() > src.giveNumberOfRows() || indxCol.maximum() > src.giveNumberOfColumns() || indxRow.minimum() < 1 || indxCol.minimum() < 1 ) { OOFEM_ERROR("index exceeds source dimensions"); @@ -1032,7 +1028,7 @@ void FloatMatrix :: add(const FloatMatrix &aMatrix) this->operator = ( aMatrix ); return; } -# ifdef DEBUG +# ifndef NDEBUG if ( ( aMatrix.nRows != nRows || aMatrix.nColumns != nColumns ) && aMatrix.isNotEmpty() ) { OOFEM_ERROR("dimensions mismatch : (r1,c1)+(r2,c2) : (%d,%d)+(%d,%d)", nRows, nColumns, aMatrix.nRows, aMatrix.nColumns); } @@ -1064,7 +1060,7 @@ void FloatMatrix :: add(double s, const FloatMatrix &aMatrix) this->times(s); return; } -# ifdef DEBUG +# ifndef NDEBUG if ( ( aMatrix.nRows != nRows || aMatrix.nColumns != nColumns ) && aMatrix.isNotEmpty() ) { OOFEM_ERROR("dimensions mismatch : (r1,c1)+(r2,c2) : (%d,%d)+(%d,%d)", nRows, nColumns, aMatrix.nRows, aMatrix.nColumns); } @@ -1090,7 +1086,7 @@ void FloatMatrix :: subtract(const FloatMatrix &aMatrix) this->negated(); return; } -# ifdef DEBUG +# ifndef NDEBUG if ( ( aMatrix.nRows != nRows || aMatrix.nColumns != nColumns ) && aMatrix.isNotEmpty() ) { OOFEM_ERROR("dimensions mismatch : (r1,c1)-(r2,c2) : (%d,%d)-(%d,%d)", nRows, nColumns, aMatrix.nRows, aMatrix.nColumns); } @@ -1112,7 +1108,7 @@ void FloatMatrix :: subtract(const FloatMatrix &aMatrix) bool FloatMatrix :: solveForRhs(const FloatArray &b, FloatArray &answer, bool transpose) // solves equation b = this * x { -# ifdef DEBUG +# ifndef NDEBUG if ( !this->isSquare() ) { OOFEM_ERROR("cannot solve a %d by %d matrix", nRows, nColumns); } @@ -1201,14 +1197,14 @@ bool FloatMatrix :: solveForRhs(const FloatArray &b, FloatArray &answer, bool tr } -void FloatMatrix :: solveForRhs(const FloatMatrix &b, FloatMatrix &answer, bool transpose) +bool FloatMatrix :: solveForRhs(const FloatMatrix &b, FloatMatrix &answer, bool transpose) // solves equation b = this * x // returns x. this and b are kept untouched // // gaussian elimination - slow but safe // { -# ifdef DEBUG +# ifndef NDEBUG if ( !this->isSquare() ) { OOFEM_ERROR("cannot solve a %d by %d matrix", nRows, nColumns); } @@ -1227,7 +1223,7 @@ void FloatMatrix :: solveForRhs(const FloatMatrix &b, FloatMatrix &answer, bool dgetrs_(transpose ? "t" : "n", & this->nRows, & answer.nColumns, this->givePointer(), & this->nRows, ipiv.givePointer(), answer.givePointer(), & this->nRows, & info); } if ( info != 0 ) { - OOFEM_ERROR("error %d", info); + return false; //OOFEM_ERROR("error %d", info); } #else int pivRow, nPs; @@ -1256,7 +1252,7 @@ void FloatMatrix :: solveForRhs(const FloatMatrix &b, FloatMatrix &answer, bool } if ( fabs(piv) < 1.e-20 ) { - OOFEM_ERROR("pivot too small, cannot solve %d by %d matrix", nRows, nColumns); + return false; //OOFEM_ERROR("pivot too small, cannot solve %d by %d matrix", nRows, nColumns); } // exchange rows @@ -1274,10 +1270,6 @@ void FloatMatrix :: solveForRhs(const FloatMatrix &b, FloatMatrix &answer, bool } } - if ( fabs(piv) < 1.e-20 ) { - OOFEM_ERROR("cannot solve, zero pivot encountered"); - } - for ( int j = i + 1; j <= nRows; j++ ) { linkomb = mtrx->at(j, i) / mtrx->at(i, i); for ( int k = i; k <= nRows; k++ ) { @@ -1301,6 +1293,7 @@ void FloatMatrix :: solveForRhs(const FloatMatrix &b, FloatMatrix &answer, bool answer.at(i, k) = ( answer.at(i, k) - help ) / mtrx->at(i, i); } } + return true; #endif } @@ -1331,7 +1324,7 @@ void FloatMatrix :: zero() void FloatMatrix :: beUnitMatrix() { -#ifdef DEBUG +#ifndef NDEBUG if ( !this->isSquare() ) { OOFEM_ERROR("cannot make unit matrix of %d by %d matrix", nRows, nColumns); } @@ -1408,7 +1401,7 @@ void FloatMatrix :: hardResize(int rows, int columns) double FloatMatrix :: giveDeterminant() const // Returns the determinant of the receiver. { -# ifdef DEBUG +# ifndef NDEBUG if ( !this->isSquare() ) { OOFEM_ERROR("cannot compute the determinant of a non-square %d by %d matrix", nRows, nColumns); } @@ -1442,7 +1435,7 @@ void FloatMatrix :: beDiagonal(const FloatArray &diag) double FloatMatrix :: giveTrace() const { -# ifdef DEBUG +# ifndef NDEBUG if ( !this->isSquare() ) { OOFEM_ERROR("cannot compute the trace of a non-square %d by %d matrix", nRows, nColumns); } @@ -1576,7 +1569,7 @@ void FloatMatrix :: rotatedWith(const FloatMatrix &r, char mode) void FloatMatrix :: symmetrized() // Initializes the lower half of the receiver to the upper half. { -# ifdef DEBUG +# ifndef NDEBUG if ( nRows != nColumns ) { OOFEM_ERROR("cannot symmetrize a non-square matrix"); } @@ -1659,7 +1652,7 @@ void FloatMatrix :: beMatrixForm(const FloatArray &aArray) // Revrites the vector on matrix form (symmetrized matrix used if size is 6), // order: 11, 22, 33, 23, 13, 12 // order: 11, 22, 33, 23, 13, 12, 32, 31, 21 -# ifdef DEBUG +# ifndef NDEBUG if ( aArray.giveSize() != 6 && aArray.giveSize() != 9 ) { OOFEM_ERROR("matrix dimension is not 3x3"); } @@ -1691,7 +1684,7 @@ void FloatMatrix :: beMatrixForm(const FloatArray &aArray) void FloatMatrix :: changeComponentOrder() { // Changes index order between abaqus <-> OOFEM -//# ifdef DEBUG +//# ifndef NDEBUG // if ( nRows != 6 || nColumns != 6 ) { // OOFEM_ERROR("matrix dimension is not 6x6"); // } @@ -1736,7 +1729,7 @@ void FloatMatrix :: changeComponentOrder() double FloatMatrix :: computeReciprocalCondition(char p) const { -# ifdef DEBUG +# ifndef NDEBUG if ( !this->isSquare() ) { OOFEM_ERROR("receiver must be square (is %d by %d)", this->nRows, this->nColumns); } @@ -1774,7 +1767,7 @@ double FloatMatrix :: computeReciprocalCondition(char p) const void FloatMatrix :: beMatrixFormOfStress(const FloatArray &aArray) { // Revrites the matrix on vector form (symmetrized matrix used), order: 11, 22, 33, 23, 13, 12 -# ifdef DEBUG +# ifndef NDEBUG if ( aArray.giveSize() != 6 && aArray.giveSize() != 9 ) { OOFEM_ERROR("matrix dimension is not 3x3"); } @@ -1926,21 +1919,19 @@ bool FloatMatrix :: jaco_(FloatArray &eval, FloatMatrix &v, int nf) /* Local variables */ - double ssum, aa, co, si, tt, tol, sum, aij, aji; - int ite, i, j, k, ih; int neq = this->giveNumberOfRows(); double c_b2 = .10; //double c_b27 = .01; /* Function Body */ -#ifdef DEBUG +#ifndef NDEBUG if ( !isSquare() ) { OOFEM_ERROR("Not square matrix"); } // check for symmetry - for ( i = 1; i <= neq; i++ ) { - for ( j = i + 1; j <= neq; j++ ) { + for ( int i = 1; i <= neq; i++ ) { + for ( int j = i + 1; j <= neq; j++ ) { //if ( this->at(i, j) != this->at(j, i) ) { if ( fabs( this->at(i, j) - this->at(j, i) ) > 1.0e-6 ) { OOFEM_ERROR("Not Symmetric matrix"); @@ -1953,14 +1944,14 @@ bool FloatMatrix :: jaco_(FloatArray &eval, FloatMatrix &v, int nf) eval.resize(neq); v.resize(neq, neq); - for ( i = 1; i <= neq; i++ ) { + for ( int i = 1; i <= neq; i++ ) { eval.at(i) = this->at(i, i); } - tol = pow(c_b2, nf); - sum = 0.0; - for ( i = 1; i <= neq; ++i ) { - for ( j = 1; j <= neq; ++j ) { + double tol = pow(c_b2, nf); + double sum = 0.0; + for ( int i = 1; i <= neq; ++i ) { + for ( int j = 1; j <= neq; ++j ) { sum += fabs( this->at(i, j) ); v.at(i, j) = 0.0; } @@ -1974,18 +1965,19 @@ bool FloatMatrix :: jaco_(FloatArray &eval, FloatMatrix &v, int nf) /* ---- REDUCE MATRIX TO DIAGONAL ---------------- */ - ite = 0; + int ite = 0; + double ssum; do { ssum = 0.0; - for ( j = 2; j <= neq; ++j ) { - ih = j - 1; - for ( i = 1; i <= ih; ++i ) { + for ( int j = 2; j <= neq; ++j ) { + int ih = j - 1; + for ( int i = 1; i <= ih; ++i ) { if ( ( fabs( this->at(i, j) ) / sum ) > tol ) { ssum += fabs( this->at(i, j) ); /* ---- CALCULATE ROTATION ANGLE ----------------- */ - aa = atan2( this->at(i, j) * 2.0, eval.at(i) - eval.at(j) ) / 2.0; - si = sin(aa); - co = cos(aa); + double aa = atan2( this->at(i, j) * 2.0, eval.at(i) - eval.at(j) ) / 2.0; + double si = sin(aa); + double co = cos(aa); /* * // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V" * for (k = 1; k <= neq; ++k) { @@ -2009,27 +2001,27 @@ bool FloatMatrix :: jaco_(FloatArray &eval, FloatMatrix &v, int nf) * } */ // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V" - for ( k = 1; k < i; ++k ) { - tt = this->at(k, i); - this->at(k, i) = co * tt + si *this->at(k, j); - this->at(k, j) = -si * tt + co *this->at(k, j); + for ( int k = 1; k < i; ++k ) { + double tt = this->at(k, i); + this->at(k, i) = co * tt + si * this->at(k, j); + this->at(k, j) = -si * tt + co * this->at(k, j); tt = v.at(k, i); v.at(k, i) = co * tt + si *v.at(k, j); v.at(k, j) = -si * tt + co *v.at(k, j); } // diagonal term (i,i) - tt = eval.at(i); - eval.at(i) = co * tt + si *this->at(i, j); - aij = -si * tt + co *this->at(i, j); + double tt = eval.at(i); + eval.at(i) = co * tt + si * this->at(i, j); + double aij = -si * tt + co *this->at(i, j); tt = v.at(i, i); v.at(i, i) = co * tt + si *v.at(i, j); v.at(i, j) = -si * tt + co *v.at(i, j); - for ( k = i + 1; k < j; ++k ) { - tt = this->at(i, k); - this->at(i, k) = co * tt + si *this->at(k, j); - this->at(k, j) = -si * tt + co *this->at(k, j); + for ( int k = i + 1; k < j; ++k ) { + double tt = this->at(i, k); + this->at(i, k) = co * tt + si * this->at(k, j); + this->at(k, j) = -si * tt + co * this->at(k, j); tt = v.at(k, i); v.at(k, i) = co * tt + si *v.at(k, j); v.at(k, j) = -si * tt + co *v.at(k, j); @@ -2037,15 +2029,15 @@ bool FloatMatrix :: jaco_(FloatArray &eval, FloatMatrix &v, int nf) // diagonal term (j,j) tt = this->at(i, j); - aji = co * tt + si *eval.at(j); + double aji = co * tt + si *eval.at(j); eval.at(j) = -si * tt + co *eval.at(j); tt = v.at(j, i); v.at(j, i) = co * tt + si *v.at(j, j); v.at(j, j) = -si * tt + co *v.at(j, j); // - for ( k = j + 1; k <= neq; ++k ) { - tt = this->at(i, k); + for ( int k = j + 1; k <= neq; ++k ) { + double tt = this->at(i, k); this->at(i, k) = co * tt + si *this->at(j, k); this->at(j, k) = -si * tt + co *this->at(j, k); tt = v.at(k, i); @@ -2071,8 +2063,8 @@ bool FloatMatrix :: jaco_(FloatArray &eval, FloatMatrix &v, int nf) } while ( fabs(ssum) / sum > tol ); // restore original matrix - for ( i = 1; i <= neq; i++ ) { - for ( j = i; j <= neq; j++ ) { + for ( int i = 1; i <= neq; i++ ) { + for ( int j = i; j <= neq; j++ ) { this->at(i, j) = this->at(j, i); } } @@ -2081,7 +2073,7 @@ bool FloatMatrix :: jaco_(FloatArray &eval, FloatMatrix &v, int nf) } /* jaco_ */ -#ifdef BOOST_PYTHON +#ifdef _BOOSTPYTHON_BINDINGS void FloatMatrix :: __setitem__(boost :: python :: api :: object t, double val) { @@ -2107,4 +2099,18 @@ std :: ostream &operator << ( std :: ostream & out, const FloatMatrix & x ) out << "}"; return out; } + +FloatMatrix &operator *= ( FloatMatrix & x, const double & a ) {x.times(a); return x;} +FloatMatrix operator *( const FloatMatrix & a, const FloatMatrix & b ) {FloatMatrix ans; ans.beProductOf (a,b); return ans;} +FloatArray operator *( const FloatMatrix & a, const FloatArray & b ) {FloatArray ans; ans.beProductOf (a,b); return ans;} +FloatMatrix operator +( const FloatMatrix & a, const FloatMatrix & b ) {FloatMatrix ans(a); ans.add(b); return ans;} +FloatMatrix operator -( const FloatMatrix & a, const FloatMatrix & b ) {FloatMatrix ans(a); ans.subtract(b); return ans;} +FloatMatrix &operator += ( FloatMatrix & a, const FloatMatrix & b ) {a.add(b); return a;} +FloatMatrix &operator -= ( FloatMatrix & a, const FloatMatrix & b ) {a.subtract(b); return a;} + + + + + + } // end namespace oofem diff --git a/src/oofemlib/floatmatrix.h b/src/oofemlib/floatmatrix.h index 45c87695f..d1faa1558 100644 --- a/src/oofemlib/floatmatrix.h +++ b/src/oofemlib/floatmatrix.h @@ -32,12 +32,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* - * The original idea for this class comes from - * Dubois-Pelerin, Y.: "Object-Oriented Finite Elements: Programming concepts and Implementation", - * PhD Thesis, EPFL, Lausanne, 1992. - */ - #ifndef flotmtrx_h #define flotmtrx_h @@ -49,8 +43,9 @@ #include #include #include +#include -#ifdef BOOST_PYTHON +#ifdef _BOOSTPYTHON_BINDINGS namespace boost { namespace python { namespace api { @@ -62,6 +57,8 @@ class object; namespace oofem { class FloatArray; +template class FloatArrayF; +template class FloatMatrixF; class IntArray; class DataStream; @@ -102,6 +99,14 @@ class OOFEM_EXPORT FloatMatrix std :: vector< double >values; public: + /// @name Iterator for for-each loops (columns-wise order): + //@{ + std::vector< double > :: iterator begin() { return this->values.begin(); } + std::vector< double > :: iterator end() { return this->values.end(); } + std::vector< double > :: const_iterator begin() const { return this->values.begin(); } + std::vector< double > :: const_iterator end() const { return this->values.end(); } + //@} + /** * Creates matrix of given size. * @param n Number of rows. @@ -125,6 +130,9 @@ class OOFEM_EXPORT FloatMatrix FloatMatrix(FloatMatrix && mat) : nRows(mat.nRows), nColumns(mat.nColumns), values( std :: move(mat.values) ) {} /// Initializer list constructor. FloatMatrix(std :: initializer_list< std :: initializer_list< double > >mat); + /// Initializer list constructor. + template + FloatMatrix(const FloatMatrixF &src) : nRows(N), nColumns(M), values(src.begin(), src.end()) { } /// Assignment operator. FloatMatrix &operator=(std :: initializer_list< std :: initializer_list< double > >mat); /// Assignment operator. @@ -142,8 +150,14 @@ class OOFEM_EXPORT FloatMatrix values = std :: move(mat.values); return * this; } - /// Destructor. - ~FloatMatrix() {} + /// Assignment operator, adjusts size of the receiver if necessary. + template + FloatMatrix &operator=(const FloatMatrixF &mat) { + nRows = N; + nColumns = M; + values.assign(mat.begin(), mat.end()); + return * this; + } /** * Checks size of receiver towards requested bounds. @@ -170,22 +184,26 @@ class OOFEM_EXPORT FloatMatrix * @param i Row position of coefficient. * @param j Column position of coefficient. */ -#ifdef DEBUG - double at(int i, int j) const; -#else - inline double at(int i, int j) const { return values [ ( j - 1 ) * nRows + i - 1 ]; } + inline double at(int i, int j) const + { +#ifndef NDEBUG + this->checkBounds(i, j); #endif + return values [ ( j - 1 ) * nRows + i - 1 ]; + } /** * Coefficient access function. Returns value of coefficient at given * position of the receiver. Implements 1-based indexing. * @param i Row position of coefficient. * @param j Column position of coefficient. */ -#ifdef DEBUG - double &at(int i, int j); -#else - inline double &at(int i, int j) { return values [ ( j - 1 ) * nRows + i - 1 ]; } + inline double &at(int i, int j) + { +#ifndef NDEBUG + this->checkBounds(i, j); #endif + return values [ ( j - 1 ) * nRows + i - 1 ]; + } /** * Coefficient access function. Returns l-value of coefficient at given @@ -193,21 +211,25 @@ class OOFEM_EXPORT FloatMatrix * @param i Row position of coefficient. * @param j Column position of coefficient. */ -#ifdef DEBUG - double &operator()(int i, int j); -#else - inline double &operator()(int i, int j) { return values [ j * nRows + i ]; } + inline double &operator()(int i, int j) + { +#ifndef NDEBUG + this->checkBounds(i + 1, j + 1); #endif + return values [ j * nRows + i ]; + } /** * Coefficient access function. Implements 0-based indexing. * @param i Row position of coefficient. * @param j Column position of coefficient. */ -#ifdef DEBUG - double operator()(int i, int j) const; -#else - inline double operator()(int i, int j) const { return values [ j * nRows + i ]; } -#endif + inline double operator()(int i, int j) const + { +#ifndef NDEBUG + this->checkBounds(i + 1, j + 1); +#endif + return values [ j * nRows + i ]; + } /** * Assembles the contribution using localization array into receiver. The receiver must * have dimensions large enough to localize contribution. @@ -223,6 +245,14 @@ class OOFEM_EXPORT FloatMatrix * @param colind Column localization indices. */ void assemble(const FloatMatrix &src, const IntArray &rowind, const IntArray &colind); + /** + * Assembles the transposed contribution using localization array into receiver. The receiver must + * have dimensions large enough to localize contribution. + * @param src Source to be assembled. + * @param rowind Row localization indices. + * @param colind Column localization indices. + */ + void assembleT(const FloatMatrix &src, const IntArray &rowind, const IntArray &colind); /** * Assembles the contribution using localization array into receiver. The receiver must * have dimensions large enough to localize contribution. @@ -398,8 +428,9 @@ class OOFEM_EXPORT FloatMatrix /** * Modifies receiver to become inverse of given parameter. Size of receiver will be adjusted. * @param src Matrix to be inverted. + * @return False if K is singular, otherwise true. */ - void beInverseOf(const FloatMatrix &src); + bool beInverseOf(const FloatMatrix &src); /** * Solves the system of linear equations @f$ K\cdot a = b @f$ . Uses Gaussian elimination with pivoting directly on receiver. * @param b RHS of linear system. @@ -414,7 +445,7 @@ class OOFEM_EXPORT FloatMatrix * @param answer Solution of linear equations, each column corresponding to columns in B. * @param transpose Solves for the transpose of K. */ - void solveForRhs(const FloatMatrix &B, FloatMatrix &answer, bool transpose = false); + bool solveForRhs(const FloatMatrix &B, FloatMatrix &answer, bool transpose = false); /** * Adds to the receiver the product @f$ a^{\mathrm{T}}\cdot b \mathrm{d}V @f$. If the receiver has zero size, it is expanded. * Assumes that receiver and product @f$ a^{\mathrm{T}}\cdot b \mathrm{d}V @f$ are symmetric matrices. Computes only the @@ -582,11 +613,27 @@ class OOFEM_EXPORT FloatMatrix friend std :: ostream &operator<<(std :: ostream &out, const FloatMatrix &r); -#ifdef BOOST_PYTHON +#ifdef _BOOSTPYTHON_BINDINGS void __setitem__(boost :: python :: api :: object t, double val); double __getitem__(boost :: python :: api :: object t); void beCopyOf(const FloatMatrix &src) { this->operator=(src); } #endif -}; + + +}; // class FloatMatrix + +//@name operators +//@{ +/// Vector multiplication by scalar +OOFEM_EXPORT FloatMatrix &operator *= ( FloatMatrix & x, const double & a ); +OOFEM_EXPORT FloatMatrix operator *( const FloatMatrix & a, const FloatMatrix & b ) ; +OOFEM_EXPORT FloatArray operator *( const FloatMatrix & a, const FloatArray & b ) ; +OOFEM_EXPORT FloatMatrix operator +( const FloatMatrix & a, const FloatMatrix & b ) ; +OOFEM_EXPORT FloatMatrix operator -( const FloatMatrix & a, const FloatMatrix & b ) ; +OOFEM_EXPORT FloatMatrix &operator += ( FloatMatrix & a, const FloatMatrix & b ) ; +OOFEM_EXPORT FloatMatrix &operator -= ( FloatMatrix & a, const FloatMatrix & b ) ; + +//@} + } // end namespace oofem #endif // flotmtrx_h diff --git a/src/oofemlib/floatmatrixf.h b/src/oofemlib/floatmatrixf.h new file mode 100644 index 000000000..c0248f182 --- /dev/null +++ b/src/oofemlib/floatmatrixf.h @@ -0,0 +1,1501 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#ifndef floatmatrixf_h +#define floatmatrixf_h + +#include "oofemcfg.h" +#include "contextioresulttype.h" +#include "contextmode.h" +#include "floatmatrix.h" +#include "floatarrayf.h" + +#include +#include +#include +#include +#include + +namespace oofem { + +/** + * Implementation of matrix containing floating point numbers. + * @author Mikael Öhman + */ +template +class OOFEM_EXPORT FloatMatrixF +{ +protected: + /// Values of matrix stored column wise. + std::array< double, N*M > values; + +public: + /// @name Iterator for for-each loops: + //@{ + auto begin() { return this->values.begin(); } + auto end() { return this->values.end(); } + auto begin() const { return this->values.begin(); } + auto end() const { return this->values.end(); } + //@} + + /** + * Constructor (values are specified column-wise) + * @note The syntax {{x,y,z},{...}} can be achieved by nested initializer_list, but + */ + template< typename... V, class = typename std::enable_if_t > + FloatMatrixF(V... x) noexcept : values{x...} { } + /** + * Empty ctor, initializes to zero. + */ + FloatMatrixF() noexcept : values{} { } + /// Copy constructor. + FloatMatrixF(const FloatMatrixF &mat) noexcept : values(mat.values) {} + /// FloatMatrix conversion constructor. + FloatMatrixF(const FloatMatrix &mat) + { +#ifndef NDEBUG + if ( mat.giveNumberOfRows() != N || mat.giveNumberOfColumns() != M ) { + throw std::out_of_range("Can't convert dynamic float matrix of size " + + std::to_string(mat.giveNumberOfRows()) + "x" + std::to_string(mat.giveNumberOfRows()) + + " to fixed size " + std::to_string(N) + "x" + std::to_string(M)); + } +#endif + std::copy_n(mat.begin(), N*M, values.begin()); + } + FloatMatrixF(FloatArrayF const (&x)[M]) noexcept + { + for (std::size_t i = 0; i < N; ++i) { + for (std::size_t j = 0; j < M; ++j) { + (*this)(i,j) = x[j][i]; + } + } + } + + /// Assignment operator + FloatMatrixF &operator=(const FloatMatrixF &mat) + { + values = mat.values; + return * this; + } + + /** + * Checks size of receiver towards requested bounds. + * @param i Required number of rows. + * @param j Required number of columns. + */ + void checkBounds(std::size_t i, std::size_t j) const + { + if ( i <= 0 ) { + throw std::out_of_range("matrix error on rows : " + std::to_string(i) + " <= 0"); + } else if ( j <= 0 ) { + throw std::out_of_range("matrix error on rows : " + std::to_string(j) + " <= 0"); + } else if ( i > N ) { + throw std::out_of_range("matrix error on rows : " + std::to_string(i) + " < " + std::to_string(N)); + } else if ( j > M ) { + throw std::out_of_range("matrix error on rows : " + std::to_string(j) + " < " + std::to_string(M)); + } + } + + /// Returns number of rows of receiver. + std::size_t rows() const { return N; } + /// Returns number of columns of receiver. + std::size_t cols() const { return M; } + + /** + * Coefficient access function. Returns value of coefficient at given + * position of the receiver. Implements 1-based indexing. + * @param i Row position of coefficient. + * @param j Column position of coefficient. + */ + double at(int i, int j) const + { +#ifndef NDEBUG + this->checkBounds(i, j); +#endif + return values [ ( j - 1 ) * N + i - 1 ]; + } + /** + * Coefficient access function. Returns value of coefficient at given + * position of the receiver. Implements 1-based indexing. + * @param i Row position of coefficient. + * @param j Column position of coefficient. + */ + inline double &at(int i, int j) + { +#ifndef NDEBUG + this->checkBounds(i, j); +#endif + return values [ ( j - 1 ) * N + i - 1 ]; + } + + /** + * Direct value access (column major). Implements 0-based indexing. + * @param i Position in data. + */ + double &operator[](int i) + { + return values[ i ]; + } + /** + * Direct value access (column major). Implements 0-based indexing. + * @param i Position in data. + */ + double operator[](int i) const + { + return values[ i ]; + } + + /** + * Coefficient access function. Returns l-value of coefficient at given + * position of the receiver. Implements 0-based indexing. + * @param i Row position of coefficient. + * @param j Column position of coefficient. + */ + double &operator()(int i, int j) + { +#ifndef NDEBUG + this->checkBounds(i + 1, j + 1); +#endif + return values [ j * N + i ]; + } + /** + * Coefficient access function. Implements 0-based indexing. + * @param i Row position of coefficient. + * @param j Column position of coefficient. + */ + double operator()(int i, int j) const + { +#ifndef NDEBUG + this->checkBounds(i + 1, j + 1); +#endif + return values [ j * N + i ]; + } + + /** + * Extract sub matrix (can also reorder the matrix). Implements 0-based indexing. + * @param r Rows to extract. + * @param c Columns to extract. + */ + template + FloatMatrixF operator()(int const (&r)[R], int const (&c)[C]) const + { + FloatMatrixF x; + for ( std::size_t i = 0; i < R; ++i ) { + for ( std::size_t j = 0; j < C; ++j ) { + x(i, j) = (*this)(r[i], c[j]); + } + } + return x; + } + + /// Assemble x into self. + template + inline void assemble(const FloatMatrixF &x, int const (&r)[R], int const (&c)[C] ) + { + for ( std::size_t i = 0; i < R; ++i ) { + for ( std::size_t j = 0; j < C; ++j ) { + (*this)(r[i], c[j]) += x(i, j); + } + } + } + + + /** + * Sets the values of the matrix in specified column. If matrix size is zero, the size is adjusted. + * @param src Array to set at column c. + * @param c Column to set. + */ + void setColumn(const FloatArrayF &src, int c) + { + for ( std::size_t i = 0; i < N; i++ ) { + (*this)(i, c) = src[i]; + } + } + + /** + * Sets the values of the matrix in specified column. If matrix size is zero, the size is adjusted. + * @param src Array to set at column c. + * @param c Column to set. + */ + FloatArrayF column(int j) const + { + FloatArrayF c; + for ( std::size_t i = 0; i < N; i++ ) { + c[i] = (*this)(i, j); + } + return c; + } + + /** + * Extract column from matrix + */ + template> + FloatArrayF column() const + { + FloatArrayF c; + for ( std::size_t i = 0; i < N; i++ ) { + c[i] = (*this)(i, C); + } + return c; + } + + /** + * Extract row from matrix + */ + template> + FloatArrayF row() const + { + FloatArrayF r; + for ( std::size_t j = 0; j < M; j++ ) { + r[j] = (*this)(R, j); + } + return r; + } + + /** + * Adds to the receiver the product @f$ a^{\mathrm{T}}\cdot b \mathrm{d}V @f$. If the receiver has zero size, it is expanded. + * Assumes that receiver and product @f$ a^{\mathrm{T}}\cdot b \mathrm{d}V @f$ are symmetric matrices. Computes only the + * upper half of receiver. + * @param a Matrix a in equation. + * @param b Matrix b in equation. + * @param dV Scaling factor. + */ + template + void plusProductSymmUpper(const FloatMatrixF &a, const FloatMatrixF &b, double dV) + { + ///@todo Larger matrices needs optimized BLAS. + for ( std::size_t i = 0; i < N; ++i ) { + for ( std::size_t j = i; j < M; ++j ) { + double summ = 0.; + for ( std::size_t k = 0; k < P; ++k ) { + summ += a(k, i) * b(k, j); + } + (*this)(i, j) += summ * dV; + } + } + } + /** + * Adds to the receiver the dyadic product @f$ a \otimes a \mathrm{d}V @f$. + * Computes only the upper half of receiver. + * @param a Array a in equation. + * @param dV Scaling factor. + */ + void plusDyadSymmUpper(const FloatArrayF &a, double dV) + { + ///@todo This method should only exist if we have N == M, how do I enforce this? + for ( std::size_t i = 0; i < N; ++i ) { + for ( std::size_t j = i; j < N; ++j ) { + (*this)(i, j) += a[i] * a[j] * dV; + } + } + } + /** + * Adds to the receiver the product @f$a^{\mathrm{T}} \cdot b \mathrm{d}V@f$. + * @param a Matrix a in equation. + * @param b Matrix b in equation. + * @param dV Scaling factor. + */ + template + void plusProductUnsym(const FloatMatrixF &a, const FloatMatrixF &b, double dV) + { + ///@todo Larger matrices needs optimized BLAS. + for ( std::size_t i = 0; i < N; ++i ) { + for ( std::size_t j = 0; j < M; ++j ) { + double summ = 0.; + for ( std::size_t k = 0; k < P; ++k ) { + summ += a(k, i) * b(k, j); + } + (*this)(i, j) += summ * dV; + } + } + } + /** + * Adds to the receiver the product @f$a \otimes b \mathrm{d}V@f$. + * @param a Array a in equation. + * @param b Array b in equation. + * @param dV Scaling factor. + */ + void plusDyadUnsym(const FloatArray &a, const FloatArray &b, double dV) + { + ///@todo This method should only exist if we have N == M, how do I enforce this? + for ( std::size_t i = 0; i < N; ++i ) { + for ( std::size_t j = 0; j < M; ++j ) { + (*this)(i, j) += a[i] * b[j] * dV; + } + } + } + /** + * Initializes the lower half of the receiver according to the upper half. + */ + void symmetrized() + { + for ( std::size_t i = 2; i <= this->rows(); i++ ) { + for ( std::size_t j = 1; j < i; j++ ) { + this->at(i, j) = this->at(j, i); + } + } + } + + /// Prints matrix to stdout. Useful for debugging. + void printYourself(const std::string &name="FloatMatrixF") const + { + printf("%s (%zu x %zu): \n", name.c_str(), N, M); + if ( this->rows() <= 250 && this->cols() <= 250 ) { + for ( std::size_t i = 0; i < this->rows(); ++i ) { + for ( std::size_t j = 0; j < this->cols() && j < 100; ++j ) { + printf( "%10.3e ", (*this)(i, j) ); + } + printf("\n"); + } + } else { + for ( std::size_t i = 0; i < this->rows() && i < 20; ++i ) { + for ( std::size_t j = 0; j < this->cols() && j < 10; ++j ) { + printf( "%10.3e ", (*this)(i, j) ); + } + if ( this->cols() > 10 ) printf(" ..."); + printf("\n"); + } + if ( this->cols() > 20 ) printf(" ...\n"); + } + } + + /** + * Exposes the internal values of the matrix. Should typically not be used outside of matrix classes. + * @return Pointer to the values of the matrix. + */ + const double *givePointer() const { return values.data(); } + double *givePointer() { return values.data(); } + + contextIOResultType storeYourself(DataStream &stream) const + { + if ( !stream.write(values.data(), N*M) ) { + return CIO_IOERR; + } + return CIO_OK; + } + + contextIOResultType restoreYourself(DataStream &stream) + { + if ( !stream.read(values.data(), N*M) ) { + return CIO_IOERR; + } + return CIO_OK; + } + + int givePackSize(DataStream &buff) const + { + return buff.givePackSizeOfDouble(N*M); + } +}; + + +/// Assemble components into zero matrix. +template +inline FloatMatrixF assemble(const FloatMatrixF &x, int const (&r)[R], int const (&c)[C] ) +{ + FloatMatrixF out; + for ( std::size_t i = 0; i < R; ++i ) { + for ( std::size_t j = 0; j < C; ++j ) { + out(r[i], c[j]) = x(i, j); + } + } + return out; +} + + +template +std::ostream & operator << ( std::ostream & out, const FloatMatrixF & x ) +{ + out << N << " " << M << " {"; + for ( std::size_t i = 0; i < N; ++i ) { + for ( std::size_t j = 0; j < M; ++j ) { + out << " " << x(i, j); + } + out << ";"; + } + out << "}"; + return out; +} + +template +FloatMatrixF operator * ( double a, const FloatMatrixF & x ) +{ + FloatMatrixF out; + for ( std::size_t i = 0; i < N*M; ++i ) { + out[i] = x[i] * a; + } + return out; +} + +template +FloatMatrixF operator * ( const FloatMatrixF & x, double a ) +{ + return a*x; +} + +template +FloatMatrixF operator / ( const FloatMatrixF & x, double a ) +{ + FloatMatrixF out; + for ( std::size_t i = 0; i < N*M; ++i ) { + out[i] = x[i] / a; + } + return out; +} + +template +FloatMatrixF operator + ( const FloatMatrixF & x, const FloatMatrixF & y ) +{ + FloatMatrixF out; + for ( std::size_t i = 0; i < N*M; ++i ) { + out[i] = x[i] + y[i]; + } + return out; +} + +template +FloatMatrixF operator - ( const FloatMatrixF & x, const FloatMatrixF & y ) +{ + FloatMatrixF out; + for ( std::size_t i = 0; i < N*M; ++i ) { + out[i] = x[i] - y[i]; + } + return out; +} + +template +FloatMatrixF &operator += ( FloatMatrixF & x, const FloatMatrixF & y ) +{ + for ( std::size_t i = 0; i < N*M; ++i ) { + x[i] += y[i]; + } + return x; +} + +template +FloatMatrixF &operator -= ( FloatMatrixF & x, const FloatMatrixF & y ) +{ + for ( std::size_t i = 0; i < N*M; ++i ) { + x[i] -= y[i]; + } + return x; +} + +template +FloatMatrixF &operator *= ( FloatMatrixF & x, double a ) +{ + for ( std::size_t i = 0; i < N*M; ++i ) { + x[i] *= a; + } + return x; +} + +/// Returns true if no element is not finite (NAN or infinite) +template +bool isfinite(const FloatMatrixF &mat) +{ + for ( auto &val : mat ) { + if ( !std::isfinite(val) ) { + return false; + } + } + return true; +} + +/** + * Constructs the N matrix + * @param n Vector with components which will appear in respective diagonal. + */ +template +FloatMatrixF Nmatrix(const FloatArrayF &n) +{ + FloatMatrixF out; + for ( std::size_t i = 0; i < N; ++i ) { + for ( std::size_t j = 0; j < NSD; ++j ) { + out( j, i * NSD + j ) = n[j]; + } + } + return out; +} + +/** + * Constructs a local coordinary system for the given normal. + * @param normal Normal (normalized). + */ +inline FloatMatrixF<2,2> local_cs(const FloatArrayF<2> &normal) +{ + return { + normal[0], normal[1], + normal[1], -normal[0] + }; +} + +inline FloatMatrixF<3,3> local_cs(const FloatArrayF<3> &normal) +{ + // Create a permutated vector of n, *always* length 1 and significantly different from n. + FloatArrayF<3> tangent = {normal[1], -normal[2], normal[0]}; + + // Construct orthogonal vector + double npn = dot(tangent, normal); + tangent += -npn * normal; + tangent /= norm(tangent); + auto bigent = cross(tangent, normal); + + FloatMatrixF<3,3> out; + //out.setColumn(normal, 0); + //out.setColumn(bigent, 1); + //out.setColumn(tangent, 2); + out(0, 0) = normal[0]; + out(0, 1) = normal[1]; + out(0, 2) = normal[2]; + + out(1, 0) = bigent[0]; + out(1, 1) = bigent[1]; + out(1, 2) = bigent[2]; + + out(2, 0) = tangent[0]; + out(2, 1) = tangent[1]; + out(2, 2) = tangent[2]; + return out; +} + +/// Constructs transposed matrix +template +FloatMatrixF transpose(const FloatMatrixF &mat) +{ + FloatMatrixF out; + for ( std::size_t i = 0; i < N; ++i ) { + for ( std::size_t j = 0; j < M; ++j ) { + out(j, i) = mat(i, j); + } + } + return out; +} + +/// Computes @f$ a \cdot b @f$. +template +FloatMatrixF dot(const FloatMatrixF &a, const FloatMatrixF &b) +{ + FloatMatrixF out; + ///@todo BLAS for larger matrix sizes (maybe) + for ( std::size_t i = 0; i < N; i++ ) { + for ( std::size_t j = 0; j < P; j++ ) { + double coeff = 0.; + for ( std::size_t k = 0; k < M; k++ ) { + coeff += a(i, k) * b(k, j); + } + out(i, j) = coeff; + } + } + return out; +} + +/// Computes @f$ a \cdot b^{\mathrm{T}} @f$. +template +FloatMatrixF dotT(const FloatMatrixF &a, const FloatMatrixF &b) +{ + FloatMatrixF out; + ///@todo BLAS for larger matrix sizes (maybe) + for ( std::size_t i = 0; i < N; i++ ) { + for ( std::size_t j = 0; j < P; j++ ) { + double coeff = 0.; + for ( std::size_t k = 0; k < M; k++ ) { + coeff += a(i, k) * b(j, k); + } + out(i, j) = coeff; + } + } + return out; +} + +/// Computes @f$ a^{\mathrm{T}} \cdot b @f$. +template +FloatMatrixF Tdot(const FloatMatrixF &a, const FloatMatrixF &b) +{ + FloatMatrixF out; + ///@todo BLAS for larger matrix sizes (maybe) + for ( std::size_t i = 0; i < N; i++ ) { + for ( std::size_t j = 0; j < P; j++ ) { + double coeff = 0.; + for ( std::size_t k = 0; k < M; k++ ) { + coeff += a(k, i) * b(k, j); + } + out(i, j) = coeff; + } + } + return out; +} + +/// Computes @$ m_ij x_j = m \cdot x @$ +template +FloatArrayF dot(const FloatMatrixF &m, const FloatArrayF &x) +{ + FloatArrayF out; + for ( std::size_t i = 0; i < N; i++ ) { + double sum = 0.; + for ( std::size_t j = 0; j < M; j++ ) { + sum += m(i, j) * x[j]; + } + out[i] = sum; + } + return out; +} + +/// Computes @$ x_j m_ji = x \cdot m = m^{\mathrm{T}} \cdot x @$ +template +FloatArrayF dot(const FloatArrayF &x, const FloatMatrixF &m) +{ + FloatArrayF out; + for ( std::size_t i = 0; i < N; i++ ) { + double sum = 0.; + for ( std::size_t j = 0; j < M; j++ ) { + sum += x[j] * m(j, i); + } + out[i] = sum; + } + return out; +} + +/// Computes @$ x_j m_ji = x \cdot m = m^{\mathrm{T}} \cdot x @$ +template +FloatArrayF Tdot(const FloatMatrixF &m, const FloatArrayF &x) +{ + return dot(x, m); +} + +/// Computes the dyadic product @f$ m_{ij} = a_i b_j @f$. +template +FloatMatrixF dyad(const FloatArrayF &a, const FloatArrayF &b) +{ + FloatMatrixF out; + for ( std::size_t i = 0; i < N; ++i ) { + for ( std::size_t j = 0; j < M; ++j ) { + out(i, j) = a[i] * b[j]; + } + } + return out; +} + +/// Computes @f$ a = r^{\mathrm{T}} \cdot a \cdot r @f$ +template +FloatMatrixF rotate(FloatMatrixF &a, const FloatMatrixF &r) +{ + return dot(dotT(r, a), r); +} + +/// Computes @f$ a = r \cdot a \cdot r^{\mathrm{T}} @f$ +template +FloatMatrixF unrotate(FloatMatrixF &a, const FloatMatrixF &r) +{ + return dotT(dot(r, a), r); +} + +/** + * Returns a copy of the given matrix column, + */ +template +FloatArrayF column(const FloatMatrixF &mat, std::size_t col) +{ + FloatArrayF ans; + for ( std::size_t row = 0; row < N; ++row ) { + ans[row] = mat(row, col); + } + return ans; +} + +/** + * Symmetrizes and stores a matrix in Voigt form: + * x_11, x_22, x_33, x_23, x_13, x_12, x_32, x_31, x_21 + */ +inline FloatMatrixF<3,3> from_voigt_form(const FloatArrayF<9> &v) +{ + return { + v[0], v[8], v[7], + v[5], v[1], v[6], + v[4], v[3], v[2] + }; // note: column major order +} + +/** + * Symmetrizes and stores a matrix in Voigt form: + * x_11, x_22, x_33, x_23, x_13, x_12, x_32, x_31, x_21 + */ +inline FloatArrayF<9> to_voigt_form(const FloatMatrixF<3,3> &t) +{ + return { + t(0, 0), + t(1, 1), + t(2, 2), + t(1, 2), + t(0, 2), + t(0, 1), + t(2, 1), + t(2, 0), + t(1, 0) + }; +} + +/** + * Symmetrizes and stores a matrix in stress Voigt form: + * s_11, s_22, s_33, s_23, s_13, s_12 + */ +inline FloatMatrixF<3,3> from_voigt_stress(const FloatArrayF<6> &v) +{ + return { + v[0], v[5], v[4], + v[5], v[1], v[3], + v[4], v[3], v[2] + }; // note: column-major order +} + +/** + * Symmetrizes and stores a matrix in stress Voigt form: + * s_11, s_22, s_33, s_23, s_13, s_12 + */ +inline FloatArrayF<6> to_voigt_stress(const FloatMatrixF<3,3> &t) +{ + return { + t(0, 0), + t(1, 1), + t(2, 2), + 0.5 * ( t(1, 2) + t(2, 1) ), + 0.5 * ( t(0, 2) + t(2, 0) ), + 0.5 * ( t(0, 1) + t(1, 0) ) + }; +} + +/** + * Converts Voigt vector to matrix form: + * e_11, e_22, e_33, v_23, v_13, v_12 + */ +inline FloatMatrixF<3,3> from_voigt_strain(const FloatArrayF<6> &v) +{ + return { + v[0], 0.5*v[5], 0.5*v[4], + 0.5*v[5], v[1], 0.5*v[3], + 0.5*v[4], 0.5*v[3], v[2] + }; // note: column-major order +} + +/** + * Symmetrizes and stores a matrix in strain Voigt form: + * e_11, e_22, e_33, v_23, v_13, v_12 + */ +inline FloatArrayF<6> to_voigt_strain(const FloatMatrixF<3,3> &t) +{ + return { + t(0, 0), + t(1, 1), + t(2, 2), + ( t(1, 2) + t(2, 1) ), + ( t(0, 2) + t(2, 0) ), + ( t(0, 1) + t(1, 0) ) + }; +} + +/** + * Constructs diagonal matrix from vector. + */ +template +FloatMatrixF diag(const FloatArrayF &v) +{ + FloatMatrixF out; + for ( std::size_t i = 0; i < N; ++i ) { + out(i, i) = v[i]; + } + return out; +} + + +/** + * Extract diagonal from matrix. + */ +template +FloatArrayF diag(const FloatMatrixF &m) +{ + FloatArrayF out; + for ( std::size_t i = 0; i < N; ++i ) { + out[i] = m(i, i); + } + return out; +} + +/** + * Constructs diagonal matrix from vector. + */ +template +FloatArrayF flatten(const FloatMatrixF &m) +{ + FloatArrayF out; + for (std::size_t i = 0; i < N*M; ++i) { + out[i] = m[i]; + } + return out; +} + +/** + * Swaps the fourth and sixth index in the array. This is to reorder the indices + * from OOFEM's order to Abaqus' and vice versa. + */ +#if 0 +void swap_46(FloatMatrixF<6,6> &t) +{ + std::swap( t(3, 0), t(5, 0) ); + std::swap( t(3, 1), t(5, 1) ); + std::swap( t(3, 2), t(5, 2) ); + std::swap( t(0, 3), t(0, 5) ); + std::swap( t(1, 3), t(1, 5) ); + std::swap( t(2, 3), t(2, 5) ); + std::swap( t(3, 3), t(5, 5) ); + std::swap( t(4, 3), t(4, 5) ); + std::swap( t(5, 3), t(3, 5) ); + std::swap( t(3, 4), t(5, 4) ); +} + +void swap_46(FloatMatrixF<9,9> &t) +{ + // OOFEM: 11, 22, 33, 23, 13, 12, 32, 31, 21 + // UMAT: 11, 22, 33, 12, 13, 23, 32, 21, 31 + + std::array abq2oo = {0, 1, 2, 5, 4, 3, 6, 8, 7}; + + FloatMatrixF<9,9> tmp; + for ( std::size_t i = 0; i < 9; i++ ) { + for ( std::size_t j = 0; j < 9; j++ ) { + tmp(i, j) = t(abq2oo[ i ], abq2oo[ j ]); + } + } + + t = tmp; +} +#endif + +/// Constructs a zero matrix (this is the default behavior when constructing a matrix, this is just for nicer syntax) +template +FloatMatrixF zero() +{ + return FloatMatrixF(); +} + +/// Constructs an identity matrix +template +FloatMatrixF eye() +{ + FloatMatrixF out; + for ( std::size_t i = 0; i < N; ++i ) { + out(i, i) = 1.; + } + return out; +} + +/// I_dev matrix in Voigt (stress) form +const FloatMatrixF<6,6> I_dev6 = { + 2./3., -1./3., -1/3., 0., 0., 0., + -1./3., 2./3., -1/3., 0., 0., 0., + -1./3., -1./3., 2/3., 0., 0., 0., + 0., 0., 0., 0.5, 0., 0., + 0., 0., 0., 0., 0.5, 0., + 0., 0., 0., 0., 0., 0.5, +}; + +/// I(x)I expressed in Voigt form +const FloatMatrixF<6,6> I6_I6 = { + 1., 1., 1., 0., 0., 0., + 1., 1., 1., 0., 0., 0., + 1., 1., 1., 0., 0., 0., + 0., 0., 0., 0., 0., 0., + 0., 0., 0., 0., 0., 0., + 0., 0., 0., 0., 0., 0., +}; + + +/** + * Constructs "N" matrix + * N_1 0 0 N_2 ... + * 0 N_1 0 0 ... + * 0 0 N_1 0 ... + */ +template +FloatMatrixF Nmatrix(const FloatArrayF &n) +{ + FloatMatrixF out; + for ( std::size_t i = 0; i < N; ++i ) { + for ( std::size_t j = 0; j < NSD; ++j ) { + out( j, i * NSD + j ) = n[j]; + } + } + return out; +} + +/// Constructs the B matrix for 3D momentum balance problems. +template +FloatMatrixF<6, N*3> Bmatrix_3d(const FloatMatrixF<3,N> &dN) +{ + FloatMatrixF<6, N*3> B; + for ( std::size_t j = 0, k = 0; j < dN.rows(); j++, k += 3 ) { + B(0, k + 0) = B(3, k + 1) = B(4, k + 2) = dN(0, j); + B(1, k + 1) = B(3, k + 0) = B(5, k + 2) = dN(1, j); + B(2, k + 2) = B(4, k + 0) = B(5, k + 1) = dN(2, j); + } + return B; +} + +/// Constructs the B matrix for plane stress momentum balance problems. +template +FloatMatrixF<3,N*2> Bmatrix_2d(const FloatMatrixF<2,N> &dN) +{ + FloatMatrixF<3,N*2> B; + for ( std::size_t j = 0, k = 0; j < N; j++, k += 2 ) { + B(0, k + 0) = B(2, k + 1) = dN(0, j); + B(1, k + 1) = B(2, k + 0) = dN(1, j); + } + return B; +} + +///@todo Move these more costly operations to a seperate header? +///@{ + +/** + * Computes the trace of the matrix. + */ +template +double trace(const FloatMatrixF &mat) +{ + double s = 0.; + for ( std::size_t i = 0; i < N; ++i ) { + s += mat(i, i); + } + return s; +} + +/** + * Computes the Frobenius norm of the receiver. + * The Frobenius norm is defined as the square root of the sum of the absolute squares of its elements. + * @return Frobenius norm. + */ +template +double frobeniusNorm(const FloatMatrixF &mat) +{ + double n = 0.; + for ( std::size_t i = 0; i < N*N; ++i ) { + n += mat[i] * mat[i]; + } + return std::sqrt( n ); + //return std::sqrt( std::inner_product(mat.values.begin(), mat.values.end(), mat.values.begin(), 0.) ); +} + +/** + * Computes the operator norm of the receiver. + * @param p Norm type, 1 norm, else 2 norm. + * @return Norm. + */ +template +double norm(const FloatMatrixF &mat, int p=1) +{ + if ( p == 1 ) { + double max_col = 0.; + for ( std::size_t j = 0; j < N; j++ ) { + double col_sum = 0.; + for ( std::size_t i = 0; i < N; i++ ) { + col_sum += fabs( mat(i, j) ); + } + if ( col_sum > max_col ) { + max_col = col_sum; + } + } + return max_col; + } else if ( p == 2 ) { + auto e = eig(transpose(mat) * mat, 1); + return sqrt(e.first(0)); + } +} + +/** + * Computes the reciprocal conditioning of the receiver. From 0 to 1, where 0 is singular and 1 best. + * The receiver must be square. + * Works identically as MATLAB/Octaves rcond(). + * @param p Norm type, 1 norm, else 2 norm. + * @return Conditioning of receiver. + */ +template +double rcond(const FloatMatrixF &mat, int p=1) +{ + ///@todo Do we need lapack here? + double anorm = norm(mat, p); + if ( det(mat) <= 1e-6 * anorm ) { + return 0.; + } + return 1. / ( norm(inv(mat)) * anorm, p ); +} + +/// Computes the determinant +inline double det(const FloatMatrixF<2,2> &mat) +{ + return mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0); +} + +/// Computes the determinant +inline double det(const FloatMatrixF<3,3> &mat) +{ + return mat(0, 0) * mat(1, 1) * mat(2, 2) + mat(0, 1) * mat(1, 2) * mat(2, 0) + + mat(0, 2) * mat(1, 0) * mat(2, 1) - mat(0, 2) * mat(1, 1) * mat(2, 0) - + mat(1, 2) * mat(2, 1) * mat(0, 0) - mat(2, 2) * mat(0, 1) * mat(1, 0); +} + +/// Computes the inverse +template +FloatMatrixF inv(const FloatMatrixF &mat, double zeropiv=1e-24) +{ + // gaussian elimination - slow but safe + auto tmp = mat; + // initialize answer to be unity matrix; + auto out = eye(); + // lower triangle elimination by columns + for ( std::size_t i = 1; i < N; i++ ) { + double piv = tmp.at(i, i); + if ( std::abs(piv) <= zeropiv ) { + OOFEM_ERROR("pivot (%d,%d) to close to small", i, i); + } + for ( std::size_t j = i + 1; j <= N; j++ ) { + double linkomb = tmp.at(j, i) / tmp.at(i, i); + for ( std::size_t k = i; k <= N; k++ ) { + tmp.at(j, k) -= tmp.at(i, k) * linkomb; + } + for ( std::size_t k = 1; k <= N; k++ ) { + out.at(j, k) -= out.at(i, k) * linkomb; + } + } + } + // upper triangle elimination by columns + for ( std::size_t i = N; i > 1; i-- ) { + double piv = tmp.at(i, i); + for ( std::size_t j = i - 1; j > 0; j-- ) { + double linkomb = tmp.at(j, i) / piv; + for ( std::size_t k = i; k > 0; k-- ) { + tmp.at(j, k) -= tmp.at(i, k) * linkomb; + } + for ( std::size_t k = N; k > 0; k-- ) { + out.at(j, k) -= out.at(i, k) * linkomb; + } + } + } + // diagonal scaling + for ( std::size_t i = 1; i <= N; i++ ) { + for ( std::size_t j = 1; j <= N; j++ ) { + out.at(i, j) /= tmp.at(i, i); + } + } + return out; +} + +/// Computes the inverse +template<> +inline FloatMatrixF<2,2> inv(const FloatMatrixF<2,2> &mat, double /*zeropiv*/) +{ + FloatMatrixF<2,2> out; + double d = det(mat); + out(0, 0) = mat(1, 1) / d; + out(1, 0) = -mat(1, 0) / d; + out(0, 1) = -mat(0, 1) / d; + out(1, 1) = mat(0, 0) / d; + return out; +} + +/// Computes the inverse +template<> +inline FloatMatrixF<3,3> inv(const FloatMatrixF<3,3> &mat, double /*zeropiv*/) +{ + FloatMatrixF<3,3> out; + double d = det(mat); + out(0, 0) = ( mat(1, 1) * mat(2, 2) - mat(1, 2) * mat(2, 1) ) / d; + out(1, 0) = ( mat(1, 2) * mat(2, 0) - mat(1, 0) * mat(2, 2) ) / d; + out(2, 0) = ( mat(1, 0) * mat(2, 1) - mat(1, 1) * mat(2, 0) ) / d; + out(0, 1) = ( mat(0, 2) * mat(2, 1) - mat(0, 1) * mat(2, 2) ) / d; + out(1, 1) = ( mat(0, 0) * mat(2, 2) - mat(0, 2) * mat(2, 0) ) / d; + out(2, 1) = ( mat(0, 1) * mat(2, 0) - mat(0, 0) * mat(2, 1) ) / d; + out(0, 2) = ( mat(0, 1) * mat(1, 2) - mat(0, 2) * mat(1, 1) ) / d; + out(1, 2) = ( mat(0, 2) * mat(1, 0) - mat(0, 0) * mat(1, 2) ) / d; + out(2, 2) = ( mat(0, 0) * mat(1, 1) - mat(0, 1) * mat(1, 0) ) / d; + return out; +} + +/** + * Computes (real) eigenvalues and eigenvectors of receiver (must be symmetric) + * @param mat Matrix. + * @param nf Number of significant figures. + * @return Pair of eigenvalues and vectors.. + */ +template +std::pair, FloatMatrixF> eig(const FloatMatrixF &mat, int nf=9) +{ + FloatArrayF eval = diag(mat); + FloatMatrixF v = eye(); + + double sum = 0.0; + for ( std::size_t i = 0; i < N; ++i ) { + for ( std::size_t j = 0; j < N; ++j ) { + sum += fabs( mat(i, j) ); + } + } + + if ( sum <= 0.0 ) { + return {zeros(), eye()}; + } + + auto m = mat; + /* ---- REDUCE MATRIX TO DIAGONAL ---------------- */ + double c_b2 = .10; + double tol = pow(c_b2, nf); + int ite = 0; + double ssum; + do { + ssum = 0.0; + for ( std::size_t j = 1; j < N; ++j ) { + for ( std::size_t i = 0; i < j; ++i ) { + if ( ( fabs( m(i, j) ) / sum ) > tol ) { + ssum += fabs( m(i, j) ); + /* ---- CALCULATE ROTATION ANGLE ----------------- */ + double aa = atan2( m(i, j) * 2.0, eval[i] - eval[j] ) / 2.0; + double si = sin(aa); + double co = cos(aa); + /* + * // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V" + * for (k = 0; k < neq; ++k) { + * tt = m(k, i); + * m(k, i) = co * tt + si * m(k, j); + * m(k, j) = -si * tt + co * m(k, j); + * tt = v(k, i); + * v(k, i) = co * tt + si * v(k, j); + * // L500: + * v(k, j) = -si * tt + co * v(k, j); + * } + * // ---- MODIFY DIAGONAL TERMS -------------------- + * m(i, i) = co * m(i, i) + si * m(j, i); + * m(j, j) = -si * m(i, j) + co * m(j, j); + * m(i, j) = 0.0; + * // ---- MAKE "A" MATRIX SYMMETRICAL -------------- + * for (k = 1; k <= neq; ++k) { + * m(i, k) = m(k, i); + * m(j, k) = m(k, j); + * // L600: + * } + */ + // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V" + for ( std::size_t k = 0; k < i; ++k ) { + double tt2 = m(k, i); + m(k, i) = co * tt2 + si * m(k, j); + m(k, j) = -si * tt2 + co * m(k, j); + tt2 = v(k, i); + v(k, i) = co * tt2 + si * v(k, j); + v(k, j) = -si * tt2 + co * v(k, j); + } + + // diagonal term (i,i) + double tt = eval[i]; + eval[i] = co * tt + si * m(i, j); + double aij = -si * tt + co * m(i, j); + tt = v(i, i); + v(i, i) = co * tt + si * v(i, j); + v(i, j) = -si * tt + co * v(i, j); + + for ( std::size_t k = i + 1; k < j; ++k ) { + double tt2 = m(i, k); + m(i, k) = co * tt2 + si * m(k, j); + m(k, j) = -si * tt2 + co * m(k, j); + tt2 = v(k, i); + v(k, i) = co * tt2 + si * v(k, j); + v(k, j) = -si * tt2 + co * v(k, j); + } + + // diagonal term (j,j) + tt = m(i, j); + double aji = co * tt + si * eval[j]; + eval[j] = -si * tt + co * eval[j]; + + tt = v(j, i); + v(j, i) = co * tt + si * v(j, j); + v(j, j) = -si * tt + co * v(j, j); + // + for ( std::size_t k = j + 1; k < N; ++k ) { + double tt2 = m(i, k); + m(i, k) = co * tt2 + si * m(j, k); + m(j, k) = -si * tt2 + co * m(j, k); + tt2 = v(k, i); + v(k, i) = co * tt2 + si * v(k, j); + v(k, j) = -si * tt2 + co * v(k, j); + } + + // ---- MODIFY DIAGONAL TERMS -------------------- + eval[i] = co * eval[i] + si * aji; + eval[j] = -si * aij + co * eval[j]; + m(i, j) = 0.0; + } else { + /* ---- A(I,J) MADE ZERO BY ROTATION ------------- */ + } + } + } + /* ---- CHECK FOR CONVERGENCE -------------------- */ + if ( ++ite > 50 ) { + throw std::runtime_error("eig computation failed"); + } + } while ( fabs(ssum) / sum > tol ); + return {eval, v}; +} + + +/** + * Computes (real) eigenvalues and eigenvectors of receiver (must be symmetric) using inverse iterations. + * @param mat Matrix. + * @return Pair of eigenvalues and vectors.. + */ +template +std::pair, FloatMatrixF> eig_inverse(const FloatMatrixF &mat) +{ + int nitem = 100; + double rtol = 1e-12; + + FloatArrayF w; + std::array, N> x; + for ( std::size_t i = 0; i < N; ++i ) { + w[i] += 1.; + x[i][i] = 1.; + } + auto invmat = inv(mat); + + for ( int it = 0; it < nitem; it++ ) { + auto z = x; + // solve matrix equation K.X = M.X + for ( std::size_t i = 0; i < N; ++i ) { + x[i] = dot(invmat, z[i]); + } + + // evaluation of Rayleigh quotients + auto old_w = w; + for ( std::size_t i = 0; i < N; i++ ) { + w[i] = dot(z[i], x[i]) / dot(x[i], x[i]); + } + + orthogonalize(x); + + // check convergence + if ( norm2(old_w - w) <= norm2(w) * rtol ) { + break; + } + } + + return {w, x}; +} + + +template +void orthogonalize(std::array, N> &x) +{ + for ( std::size_t j = 0; j < N; j++ ) { + auto t = x[j]; + for ( std::size_t ii = 0; ii < j; ii++ ) { + x[j] -= dot(x[ii], t) * x[ii]; + } + x[j] *= 1.0 / norm(x[j]); + } +} + + +#if 0 +template<> +inline std::pair, FloatMatrixF<2,2>> eig(const FloatMatrixF<2,2> &mat, int nf) +{ + double b = - (mat(0,0) + mat(1,1))/2.; + double c = mat(0,0) * mat(1,1) - mat(0,1) * mat(1,0); + FloatArrayF<2> vals = { + -b + std::sqrt(b*b - c), + -b - std::sqrt(b*b - c) + }; + FloatMatrixF<2,2> vecs; + OOFEM_ERROR("TODO"); // is this even worth specializing? I don't think we ever use it for 2x2. Typically just 3x3, 6x6, 9x9 + return {vals, vecs}; +} +#endif + +/** + * Solves the system of linear equations @f$ K\cdot a = b @f$ . + * Uses Gaussian elimination with pivoting directly on receiver. + * @param b RHS of linear system. + * @return Solution of linear equations. + */ +template +std::pair> solve_check(FloatMatrixF mtrx, const FloatArrayF &b, double zeropiv = 1e-20) +{ + auto answer = b; + // initialize answer to be unity matrix; + // lower triangle elimination by columns + for ( std::size_t i = 0; i < N - 1; i++ ) { + // find the suitable row and pivot + double piv = fabs( mtrx(i, i) ); + std::size_t pivRow = i; + for ( std::size_t j = i + 1; j < N; j++ ) { + if ( fabs( mtrx(j, i) ) > piv ) { + pivRow = j; + piv = fabs( mtrx(j, i) ); + } + } + + if ( piv <= zeropiv ) { + return {false, zeros()}; + } + + // exchange rows + if ( pivRow != i ) { + for ( std::size_t j = i; j < N; j++ ) { + double help = mtrx(i, j); + mtrx(i, j) = mtrx(pivRow, j); + mtrx(pivRow, j) = help; + } + double help = answer[i]; + answer[i] = answer[pivRow]; + answer[pivRow] = help; + } + + for ( std::size_t j = i + 1; j < N; j++ ) { + double linkomb = mtrx(j, i) / mtrx(i, i); + for ( std::size_t k = i; k < N; k++ ) { + mtrx(j, k) -= mtrx(i, k) * linkomb; + } + + answer[j] -= answer[i] * linkomb; + } + } + + // back substitution + for ( int i = N - 1; i >= 0; i-- ) { + double help = 0.; + for ( std::size_t j = i + 1; j < N; j++ ) { + help += mtrx(i, j) * answer[j]; + } + + answer[i] = ( answer[i] - help ) / mtrx(i, i); + } + return {true, answer}; +} + + +/** + * Solves the system of linear equations @f$ K\cdot a = b @f$ . + * Uses Gaussian elimination with pivoting directly on receiver. + * @param b RHS of linear system. + * @return Solution of linear equations. + */ +template +FloatArrayF solve(FloatMatrixF mtrx, const FloatArrayF &b, double zeropiv=1e-20) +{ + auto tmp = solve_check(mtrx, b, zeropiv); + if ( tmp.first ) { + return tmp.second; + } else { + throw std::runtime_error("Singular pivot encountered"); + } +} + +/** + * Solves the system of linear equations @f$ K\cdot A = B @f$ . + * Uses Gaussian elimination with pivoting directly on receiver. + * @param B RHS of linear system. + * @return Solution of linear equations, each column corresponding to columns in B. + */ +template +FloatMatrixF solve(FloatMatrixF mtrx, const FloatMatrixF &B, double zeropiv=1e-20) +{ + auto answer = B; + // initialize answer to be unity matrix; + // lower triangle elimination by columns + for ( std::size_t i = 0; i < N - 1; i++ ) { + // find the suitable row and pivot + double piv = fabs( mtrx(i, i) ); + std::size_t pivRow = i; + for ( std::size_t j = i + 1; j < N; j++ ) { + if ( fabs( mtrx(j, i) ) > piv ) { + pivRow = j; + piv = fabs( mtrx(j, i) ); + } + } + + if ( fabs(piv) < zeropiv ) { + throw std::runtime_error("pivot too small, matrix problem could not be solved"); + } + + // exchange rows + if ( pivRow != i ) { + for ( std::size_t j = i; j < N; j++ ) { + double help = mtrx(i, j); + mtrx(i, j) = mtrx(pivRow, j); + mtrx(pivRow, j) = help; + } + + for ( std::size_t j = 0; j < M; j++ ) { + double help = answer(i, j); + answer(i, j) = answer(pivRow, j); + answer(pivRow, j) = help; + } + } + + for ( std::size_t j = i + 1; j < N; j++ ) { + double linkomb = mtrx(j, i) / mtrx(i, i); + for ( std::size_t k = i; k < N; k++ ) { + mtrx(j, k) -= mtrx(i, k) * linkomb; + } + + for ( std::size_t k = 0; k < M; k++ ) { + answer(j, k) -= answer(i, k) * linkomb; + } + } + } + + // back substitution + for ( std::size_t i = N - 1; i >= 0; i-- ) { + for ( std::size_t k = 0; k < M; k++ ) { + double help = 0.; + for ( std::size_t j = i + 1; j < N; j++ ) { + help += mtrx(i, j) * answer(j, k); + } + + answer(i, k) = ( answer(i, k) - help ) / mtrx(i, i); + } + } + return answer; +} +///@} + +} // end namespace oofem +#endif // floatmatrixf_h diff --git a/src/oofemlib/fracturemanager.C b/src/oofemlib/fracturemanager.C index ff49636f8..007e2dc73 100644 --- a/src/oofemlib/fracturemanager.C +++ b/src/oofemlib/fracturemanager.C @@ -66,39 +66,27 @@ FractureManager :: clear() { } -IRResultType FractureManager :: initializeFrom(InputRecord *ir) +void FractureManager :: initializeFrom(InputRecord &ir) { // Read number of failure criterias to evaluate - IRResultType result; // Required by IR_GIVE_FIELD macro - int numCriterias; IR_GIVE_FIELD(ir, numCriterias, _IFT_FracManager_numcriterias); this->criteriaList.resize(numCriterias); bool verbose = false; IR_GIVE_OPTIONAL_FIELD(ir, verbose, _IFT_FracManager_verbose); - -#define VERBOSE - - - return IRRT_OK; } -int FractureManager :: instanciateYourself(DataReader *dr) +int FractureManager :: instanciateYourself(DataReader &dr) { - IRResultType result; // Required by IR_GIVE_FIELD macro std :: string name; // Create and initialize all failure criterias for ( int i = 1; i <= ( int ) this->criteriaList.size(); i++ ) { - InputRecord *mir = dr->giveInputRecord(DataReader :: IR_failCritRec, i); - result = mir->giveRecordKeywordField(name); - - if ( result != IRRT_OK ) { ///@todo Make so that this can't fail. - IR_IOERR("", mir, result); - } + auto &mir = dr.giveInputRecord(DataReader :: IR_failCritRec, i); + mir.giveRecordKeywordField(name); - FailureCriteria *failCriteria = classFactory.createFailureCriteria(name.c_str(), i, this); + auto failCriteria = classFactory.createFailureCriteria(name.c_str(), i, this); if ( !failCriteria ) { OOFEM_ERROR( "unknown failure criteria (%s)", name.c_str() ); return 0; @@ -111,7 +99,7 @@ int FractureManager :: instanciateYourself(DataReader *dr) failCriteria->list.resize(numEl); for ( int j = 1; j <= numEl; j++ ) { Element *el = domain->giveElement(j); - FailureCriteriaStatus *fcs = failCriteria->CreateStatus(el, failCriteria); + FailureCriteriaStatus *fcs = failCriteria->CreateStatus(el); failCriteria->list.at(j - 1) = fcs; } } else if ( failCriteria->giveType() == IPLocal ) { @@ -122,7 +110,7 @@ int FractureManager :: instanciateYourself(DataReader *dr) OOFEM_ERROR("Unknown failure criteria"); } - this->criteriaList.at(i - 1) = failCriteria; + this->criteriaList.at(i - 1) = std::move(failCriteria); } return 1; @@ -148,7 +136,7 @@ FractureManager :: evaluateFailureCriterias(TimeStep *tStep) #ifdef VERBOSE printf("\n Evaluating failure criteria %i \n", i); #endif - FailureCriteria *failCrit = this->criteriaList.at(i - 1); + auto &failCrit = this->criteriaList.at(i - 1); if ( failCrit->giveType() == ELLocal ) { for ( int j = 1; j <= ( int ) failCrit->list.size(); j++ ) { #ifdef VERBOSE @@ -185,7 +173,7 @@ FractureManager :: updateXFEM(TimeStep *tStep) #ifdef VERBOSE printf("based on failure criteria %i \n", i); #endif - FailureCriteria *failCrit = this->criteriaList.at(i - 1); + auto &failCrit = this->criteriaList.at(i - 1); for ( int j = 1; j <= ( int ) failCrit->list.size(); j++ ) { // each criteria (often each element) #ifdef VERBOSE @@ -250,24 +238,17 @@ DamagedNeighborLayered :: evaluateFailureCriteria(FailureCriteriaStatus *fcStatu -IRResultType FailureCriteria :: initializeFrom(InputRecord *ir) +void FailureCriteria :: initializeFrom(InputRecord &ir) { - //IRResultType result; // Required by IR_GIVE_FIELD macro - - return IRRT_OK; } -IRResultType DamagedNeighborLayered :: initializeFrom(InputRecord *ir) +void DamagedNeighborLayered :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - // Read damage threshold value IR_GIVE_FIELD(ir, this->DamageThreshold, _IFT_DamagedNeighborLayered_DamageThreshold); this->setType(ELLocal); - - return IRRT_OK; } #endif @@ -277,10 +258,7 @@ IRResultType DamagedNeighborLayered :: initializeFrom(InputRecord *ir) //=================================================== // Failure Criteria Status //=================================================== -IRResultType FailureCriteriaStatus :: initializeFrom(InputRecord *ir) +void FailureCriteriaStatus :: initializeFrom(InputRecord &ir) { - //IRResultType result; // Required by IR_GIVE_FIELD macro - - return IRRT_OK; } } // end namespace oofem diff --git a/src/oofemlib/fracturemanager.h b/src/oofemlib/fracturemanager.h index d40839f81..db3314e17 100644 --- a/src/oofemlib/fracturemanager.h +++ b/src/oofemlib/fracturemanager.h @@ -85,7 +85,6 @@ class FailureCriteriaStatus { // abstract class from all the different failure criterias should be derived private: - //FractureManager *fMan; FailureCriteria *failCrit; // pointer to the corresponding failure criteria // FailureCriteriaType type; // local, nonlocal @@ -93,8 +92,6 @@ class FailureCriteriaStatus // bool failedFlag; // is the criteria fulfilled? int number; - - public: FailureCriteriaStatus(int number, FailureCriteria * failCrit) { @@ -116,22 +113,17 @@ class FailureCriteriaStatus FloatArray thresholds; std :: vector< bool >failedFlags; - //FailureCriteriaType giveType() { return this->giveFailureCriteria().giveType(); } FailureCriteria *giveFailureCriteria() { return this->failCrit; } - bool hasFailed(int i) { return failedFlags.at(i - 1); } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int instanciateYourself(DataReader *dr) { return 1; } + virtual void initializeFrom(InputRecord &ir); + virtual int instanciateYourself(DataReader &dr) { return 1; } virtual const char *giveClassName() const { return "FailureCriteriaStatus"; } }; - - - class FailureCriteria { private: @@ -153,20 +145,17 @@ class FailureCriteria FractureManager *giveFractureManager() { return this->fMan; } void setType(FailureCriteriaType type) { this->type = type; } - virtual IRResultType initializeFrom(InputRecord *ir); - int instanciateYourself(DataReader *dr); + virtual void initializeFrom(InputRecord &ir); + int instanciateYourself(DataReader &dr); virtual const char *giveClassName() const { return "FailureCriteria"; } - - virtual FailureCriteriaStatus *CreateStatus(Element *el, FailureCriteria *failCrit) const = 0; + virtual FailureCriteriaStatus *CreateStatus(Element *el) = 0; virtual bool computeFailureCriteriaQuantities(FailureCriteriaStatus *fcStatus, TimeStep *tStep); virtual bool evaluateFCQuantities(Element *el, TimeStep *tStep) { return false; } // defaults to no implementation virtual bool evaluateFailureCriteria(FailureCriteriaStatus *fcStatus) = 0; }; - - class DamagedNeighborLayeredStatus : public FailureCriteriaStatus { public: @@ -186,27 +175,25 @@ class DamagedNeighborLayered : public FailureCriteria DamagedNeighborLayered(int number, FractureManager * fracMan) : FailureCriteria(number, fracMan) { } - virtual bool evaluateFailureCriteria(FailureCriteriaStatus *fcStatus); - virtual const char *giveClassName() const { return "DamagedNeighborLayered"; } - virtual const char *giveInputRecordName() const { return _IFT_DamagedNeighborLayered_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + bool evaluateFailureCriteria(FailureCriteriaStatus *fcStatus) override; + const char *giveClassName() const override { return "DamagedNeighborLayered"; } + const char *giveInputRecordName() const { return _IFT_DamagedNeighborLayered_Name; } + void initializeFrom(InputRecord &ir) override; - virtual FailureCriteriaStatus *CreateStatus(Element *el, FailureCriteria *failCrit) const - { return new DamagedNeighborLayeredStatus(el, failCrit); } + FailureCriteriaStatus * CreateStatus(Element *el) override + { return new DamagedNeighborLayeredStatus(el, this); } }; - class FailureModuleElementInterface : public Interface { public: FailureModuleElementInterface() : Interface() { } - virtual const char *giveClassName() const { return "FailureModuleElementInterface"; } + const char *giveClassName() const override { return "FailureModuleElementInterface"; } virtual void computeFailureCriteriaQuantities(FailureCriteriaStatus *fc, TimeStep *tStep) { } }; - /** * This class manages the fracture mechanics part * @@ -234,18 +221,14 @@ class FractureManager void updateXFEM(TimeStep *tStep); void updateXFEM(FailureCriteriaStatus *fc, TimeStep *tStep); - - - IRResultType initializeFrom(InputRecord *ir); - int instanciateYourself(DataReader *dr); + void initializeFrom(InputRecord &ir); + int instanciateYourself(DataReader &dr); const char *giveClassName() const { return "FractureManager"; } const char *giveInputRecordName() const { return "FractureManager"; } void clear(); Domain *giveDomain() { return this->domain; } - - - std :: vector< FailureCriteria * >criteriaList; + std::vector> criteriaList; //std :: vector< CrackManager* > crackManagers; // Keep track of all cracks - each crack may have several fronts/tips //std :: vector< PropagationLawManager* > propagationLawManagers; }; diff --git a/src/oofemlib/freeminterface.C b/src/oofemlib/freeminterface.C index 4f0e9e782..562738627 100644 --- a/src/oofemlib/freeminterface.C +++ b/src/oofemlib/freeminterface.C @@ -40,10 +40,13 @@ #include "connectivitytable.h" #include "mathfem.h" #include "remeshingcrit.h" +#include "classfactory.h" #include namespace oofem { +REGISTER_Mesher(FreemInterface, MPT_FREEM); + MesherInterface :: returnCode FreemInterface :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, Domain **dNew) { @@ -107,17 +110,10 @@ FreemInterface :: createInput(Domain *d, TimeStep *tStep) void FreemInterface :: smoothNodalDensities(Domain *d, FloatArray &nodalDensities, TimeStep *tStep) { - int neighbour, candidate, found, jelemNodes; - int nnodes = d->giveNumberOfDofManagers(); - double dist; - const IntArray *candidateConnectivity; - FloatArray *neighbourCoords; - Element *jelem; - Node *candNode; - std :: list< int >queue; - + std :: list< int > queue; // loop over nodes + int nnodes = d->giveNumberOfDofManagers(); for ( int i = 1; i <= nnodes; i++ ) { if ( !dynamic_cast< Node * >( d->giveDofManager(i) ) ) { continue; @@ -128,24 +124,24 @@ FreemInterface :: smoothNodalDensities(Domain *d, FloatArray &nodalDensities, T while ( !queue.empty() ) { // extract candidate - candidate = * ( queue.begin() ); + int candidate = * ( queue.begin() ); queue.erase( queue.begin() ); - candNode = static_cast< Node * >( d->giveDofManager(candidate) ); + Node *candNode = static_cast< Node * >( d->giveDofManager(candidate) ); // find candidate neighbours - candidateConnectivity = d->giveConnectivityTable()->giveDofManConnectivityArray(candidate); + const IntArray *candidateConnectivity = d->giveConnectivityTable()->giveDofManConnectivityArray(candidate); for ( int j = 1; j <= candidateConnectivity->giveSize(); j++ ) { - jelem = d->giveElement( candidateConnectivity->at(j) ); - jelemNodes = jelem->giveNumberOfNodes(); + Element *jelem = d->giveElement( candidateConnectivity->at(j) ); + int jelemNodes = jelem->giveNumberOfNodes(); for ( int k = 1; k <= jelemNodes; k++ ) { - neighbour = jelem->giveNode(k)->giveNumber(); + int neighbour = jelem->giveNode(k)->giveNumber(); if ( neighbour == candidate ) { continue; } // neighbour found, check if smoothing necessary - neighbourCoords = jelem->giveNode(k)->giveCoordinates(); - dist = candNode->giveCoordinates()->distance(neighbourCoords); + const auto &neighbourCoords = jelem->giveNode(k)->giveCoordinates(); + double dist = distance(candNode->giveCoordinates(), neighbourCoords); // overshoot criteria if ( ( ( nodalDensities.at(neighbour) / nodalDensities.at(candidate) ) > 1.3 ) && ( nodalDensities.at(neighbour) > 1.0 * dist ) ) { @@ -153,10 +149,10 @@ FreemInterface :: smoothNodalDensities(Domain *d, FloatArray &nodalDensities, T nodalDensities.at(neighbour) = max( 1.0 * dist, nodalDensities.at(candidate) ); // printf ("o"); // put candidate into queue if not yet added present - found = 0; + bool found = false; for ( int q: queue ) { if ( q == neighbour ) { - found = 1; + found = true; break; } } @@ -171,10 +167,10 @@ FreemInterface :: smoothNodalDensities(Domain *d, FloatArray &nodalDensities, T nodalDensities.at(neighbour) = nodalDensities.at(candidate) + 2.2 * dist; //printf ("g"); // put candidate into queue if not yet added present - found = 0; + bool found = false; for ( int q: queue ) { if ( q == neighbour ) { - found = 1; + found = true; break; } } diff --git a/src/oofemlib/freeminterface.h b/src/oofemlib/freeminterface.h index 95d0c1420..e90ca5519 100644 --- a/src/oofemlib/freeminterface.h +++ b/src/oofemlib/freeminterface.h @@ -38,6 +38,8 @@ #include "mesherinterface.h" #include "floatarray.h" +#define _IFT_FreemInterface_Name "freem" + namespace oofem { class TimeStep; @@ -56,7 +58,7 @@ class OOFEM_EXPORT FreemInterface : public MesherInterface /// Destructor virtual ~FreemInterface() { } - virtual returnCode createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, Domain **dNew); + returnCode createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, Domain **dNew) override; protected: /// Creates the mesher input, containing the required mesh density information. diff --git a/src/oofemlib/function.C b/src/oofemlib/function.C index ead460b2f..8e17a1c43 100644 --- a/src/oofemlib/function.C +++ b/src/oofemlib/function.C @@ -37,6 +37,8 @@ #include "error.h" #include "domain.h" #include "gausspoint.h" +#include "datastream.h" +#include "contextioerr.h" namespace oofem { Function :: Function(int n, Domain *d) : @@ -116,4 +118,29 @@ Function :: evaluate(const std :: map< std :: string, FunctionArgument > &valDic return ans[0]; } +void +Function :: saveContext(DataStream &stream, ContextMode mode) +{ + FEMComponent :: saveContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( !stream.write(parameterType) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +void +Function :: restoreContext(DataStream &stream, ContextMode mode) +{ + FEMComponent :: restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( !stream.read(parameterType) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + } // end namespace oofem diff --git a/src/oofemlib/function.h b/src/oofemlib/function.h index 07245066e..ea3bfe794 100644 --- a/src/oofemlib/function.h +++ b/src/oofemlib/function.h @@ -114,7 +114,7 @@ class OOFEM_EXPORT Function : public FEMComponent * @param valDict Map with inputs. * @param answer Function value. */ - virtual void evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp=NULL, double param=0.); + virtual void evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp=nullptr, double param=0.); /** * Returns the (scalar) value of the function for given input. * @param valDict Map with inputs. @@ -142,6 +142,8 @@ class OOFEM_EXPORT Function : public FEMComponent virtual double evaluateAccelerationAtTime(double t) = 0; double giveFunctionParameter(int paramID); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; } // end namespace oofem #endif // function_h diff --git a/src/oofemlib/gaussintegrationrule.C b/src/oofemlib/gaussintegrationrule.C index 14e1ef6fe..2fd475ef4 100644 --- a/src/oofemlib/gaussintegrationrule.C +++ b/src/oofemlib/gaussintegrationrule.C @@ -1437,6 +1437,10 @@ GaussIntegrationRule :: giveLineCoordsAndWeights(int nPoints, FloatArray &coords // Create arrays of coordinates and weights for Gauss Integration Points of a line with 'nPoints' integrationpoints { switch ( nPoints ) { + case 0: + coords_xi = FloatArray{}; + weights = FloatArray{}; + break; case 1: coords_xi = FloatArray{0.0}; weights = FloatArray{2.0}; diff --git a/src/oofemlib/gaussintegrationrule.h b/src/oofemlib/gaussintegrationrule.h index 7bff8d6e7..c3df21c07 100644 --- a/src/oofemlib/gaussintegrationrule.h +++ b/src/oofemlib/gaussintegrationrule.h @@ -37,6 +37,8 @@ #include "integrationrule.h" +#define _IFT_GaussIntegrationRule_Name "gauss" + namespace oofem { class Element; @@ -70,24 +72,23 @@ class OOFEM_EXPORT GaussIntegrationRule : public IntegrationRule /// Destructor virtual ~GaussIntegrationRule(); - virtual const char *giveClassName() const { return "GaussIntegrationRule"; } - virtual IntegrationRuleType giveIntegrationRuleType() const { return IRT_Gauss; } - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } - - virtual int getRequiredNumberOfIntegrationPoints(integrationDomain dType, int approxOrder); + const char *giveClassName() const override { return "GaussIntegrationRule"; } + IntegrationRuleType giveIntegrationRuleType() const override { return IRT_Gauss; } + void initializeFrom(InputRecord &ir) override { } + int getRequiredNumberOfIntegrationPoints(integrationDomain dType, int approxOrder) override; - virtual int SetUpPointsOnLine(int nPoints, MaterialMode mode); - virtual int SetUpPointsOnTriangle(int nPoints, MaterialMode mode); - virtual int SetUpPointsOnSquare(int nPoints, MaterialMode mode); - virtual int SetUpPointsOn3dDegShell(int nPointsXY, int nPointsZ, MaterialMode mode); - virtual int SetUpPointsOn3dDegShellLayers(int nPointsXY, int nPointsZ, MaterialMode mode, const FloatArray &layerThickness); - virtual int SetUpPointsOnCubeLayers(int nPoints1, int nPoints2, int nPointsDepth, MaterialMode mode, const FloatArray &layerThickness); - virtual int SetUpPointsOnCube(int nPoints, MaterialMode mode); - virtual int SetUpPointsOnTetrahedra(int nPoints, MaterialMode mode); - virtual int SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, MaterialMode mode); - virtual int SetUpPointsOnWedgeLayers(int nPointsTri, int nPointsDepth, MaterialMode mode, const FloatArray &layerThickness); - virtual int SetUpPointsOn2DEmbeddedLine(int nPoints, MaterialMode mode, const FloatArray &coord0, const FloatArray &coord1); + int SetUpPointsOnLine(int nPoints, MaterialMode mode) override; + int SetUpPointsOnTriangle(int nPoints, MaterialMode mode) override; + int SetUpPointsOnSquare(int nPoints, MaterialMode mode) override; + int SetUpPointsOn3dDegShell(int nPointsXY, int nPointsZ, MaterialMode mode) override; + int SetUpPointsOn3dDegShellLayers(int nPointsXY, int nPointsZ, MaterialMode mode, const FloatArray &layerThickness) override; + int SetUpPointsOnCubeLayers(int nPoints1, int nPoints2, int nPointsDepth, MaterialMode mode, const FloatArray &layerThickness) override; + int SetUpPointsOnCube(int nPoints, MaterialMode mode) override; + int SetUpPointsOnTetrahedra(int nPoints, MaterialMode mode) override; + int SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, MaterialMode mode) override; + int SetUpPointsOnWedgeLayers(int nPointsTri, int nPointsDepth, MaterialMode mode, const FloatArray &layerThickness) override; + int SetUpPointsOn2DEmbeddedLine(int nPoints, MaterialMode mode, const FloatArray &coord0, const FloatArray &coord1) override; static void giveTetCoordsAndWeights(int nPoints, FloatArray &coords_xi1, FloatArray &coords_xi2, FloatArray &coords_xi3, FloatArray &weights); static void giveTriCoordsAndWeights(int nPoints, FloatArray &coords_xi1, FloatArray &coords_xi2, FloatArray &weights); diff --git a/src/oofemlib/gausspoint.C b/src/oofemlib/gausspoint.C index ff3292ff1..6392e7e52 100644 --- a/src/oofemlib/gausspoint.C +++ b/src/oofemlib/gausspoint.C @@ -47,9 +47,6 @@ GaussPoint :: GaussPoint(IntegrationRule *ir, int n, FloatArray iNaturalCoord, d weight(w), materialMode(mode) { - subPatchCoordinates = NULL; - globalCoordinates = NULL; - materialStatus = NULL; } GaussPoint :: GaussPoint(IntegrationRule * ir, int n, double w, MaterialMode mode) : @@ -58,47 +55,34 @@ GaussPoint :: GaussPoint(IntegrationRule * ir, int n, double w, MaterialMode mod weight(w), materialMode(mode) { - subPatchCoordinates = NULL; - globalCoordinates = NULL; - materialStatus = NULL; } -GaussPoint :: ~GaussPoint() +GaussPoint::~GaussPoint() { for ( GaussPoint *gp: gaussPoints ) { delete gp; } - - delete subPatchCoordinates; - delete globalCoordinates; - delete materialStatus; } -void GaussPoint :: printOutputAt(FILE *File, TimeStep *tStep) -// Prints the strains and stresses on the data file. + void GaussPoint :: printOutputAt(FILE *file, TimeStep *tStep, const char* indent) { - int iruleNumber = 0; - - if ( irule ) { - iruleNumber = irule->giveNumber(); - } + int iruleNumber = irule ? irule->giveNumber() : 0; - fprintf(File, " GP %2d.%-2d :", iruleNumber, number); + fprintf(file, "%s GP %2d.%-2d :", indent, iruleNumber, number); - // invoke printOutputAt method for all managed statuses IntegrationPointStatus *status = this->giveMaterialStatus(); if ( status ) { - status->printOutputAt(File, tStep); + status->printOutputAt(file, tStep); } if ( gaussPoints.size() != 0 ) { // layered material - fprintf(File, "Layers report \n{\n"); - for ( GaussPoint *gp: gaussPoints ) { - gp->printOutputAt(File, tStep); + fprintf(file, "\tLayers report {\n"); + for ( auto &gp: gaussPoints ) { + gp->printOutputAt(file, tStep, "\t\t"); } - fprintf(File, "} end layers report\n"); + fprintf(file, "\t} end layers report\n"); } } @@ -111,7 +95,7 @@ GaussPoint *GaussPoint :: giveSlaveGaussPoint(int index) // { if ( gaussPoints.size() == 0 ) { - return NULL; + return nullptr; } if ( ( index < 0 ) || ( index >= (int)gaussPoints.size() ) ) { @@ -121,16 +105,17 @@ GaussPoint *GaussPoint :: giveSlaveGaussPoint(int index) return gaussPoints [ index ]; } -bool GaussPoint :: hasSlaveGaussPoint() { +bool GaussPoint :: hasSlaveGaussPoint() +{ if ( this->gaussPoints.size() != 0 ) {// layered material return true; } return false; } -size_t GaussPoint :: findFirstIndexOfSlaveGaussPoint(GaussPoint *gp) { - std::vector< GaussPoint * >::iterator it; - it = find( gaussPoints.begin(), gaussPoints.end(), gp ); +size_t GaussPoint :: findFirstIndexOfSlaveGaussPoint(GaussPoint *gp) +{ + auto it = find( gaussPoints.begin(), gaussPoints.end(), gp ); if ( it != gaussPoints.end() ) { return it - gaussPoints.begin(); } else { @@ -139,58 +124,15 @@ size_t GaussPoint :: findFirstIndexOfSlaveGaussPoint(GaussPoint *gp) { } void GaussPoint :: updateYourself(TimeStep *tStep) -// Performs end-of-step updates. { IntegrationPointStatus *status = this->giveMaterialStatus(); if ( status ) { status->updateYourself(tStep); } - for ( GaussPoint *gp: gaussPoints ) { + for ( auto &gp: gaussPoints ) { gp->updateYourself(tStep); } } - - -/* - * contextIOResultType - * GaussPoint :: saveContext (FILE* stream, void *obj) - * // - * // saves full gp context (saves state variables, that completely describe - * // current state) - * // does not saves the slave - records - * // this task is done at the layeredCrossSection level - * { - * - * contextIOResultType iores; - * - * if ((iores = this->giveMaterial()->saveContext(stream,(void*) this)) != CIO_OK) THROW_CIOERR(iores); - * // if (matStatusDict->saveContext(stream,obj) != 1) - * // error ("saveContext io error encountered"); - * - * return CIO_OK; - * - * } - * - * - * contextIOResultType - * GaussPoint :: restoreContext (FILE* stream, void *obj) - * // - * // restores full material context (saves state variables, that completely describe - * // current state) - * // does not restores the slave - records - * // this task is done at the layeredCrossSection level - * // - * { - * - * contextIOResultType iores; - * if ((iores = this->giveMaterial()->restoreContext(stream,(void*) this)) != CIO_OK) THROW_CIOERR(iores); - * //if (matStatusDict->restoreContext(stream,obj) != 1) - * // error ("restoreContext io error encountered"); - * - * return CIO_OK; - * - * } - */ } // end namespace oofem diff --git a/src/oofemlib/gausspoint.h b/src/oofemlib/gausspoint.h index 8a280ebd3..63bb5c3e1 100644 --- a/src/oofemlib/gausspoint.h +++ b/src/oofemlib/gausspoint.h @@ -100,9 +100,9 @@ class OOFEM_EXPORT GaussPoint /// Natural Element Coordinates of receiver. FloatArray naturalCoordinates; /// Optional local sub-patch (sub-patches form element volume) coordinates of the receiver. - FloatArray *subPatchCoordinates; + std::unique_ptr subPatchCoordinates; /// Optional global (Cartesian) coordinates - FloatArray *globalCoordinates; + std::unique_ptr globalCoordinates; /// Integration weight. double weight; /// Material mode of receiver. @@ -111,9 +111,9 @@ class OOFEM_EXPORT GaussPoint protected: // layer and fibered material support /// List of slave integration points. - std::vector< GaussPoint * >gaussPoints; + std::vector< GaussPoint * > gaussPoints; /// Status of e.g. material in point - IntegrationPointStatus *materialStatus; + std::unique_ptr materialStatus; public: /** @@ -125,23 +125,21 @@ class OOFEM_EXPORT GaussPoint * @param w Integration weight. * @param mode Material mode. */ - GaussPoint(IntegrationRule * ir, int n, FloatArray iNaturalCoord, double w, MaterialMode mode); + GaussPoint(IntegrationRule *ir, int n, FloatArray iNaturalCoord, double w, MaterialMode mode); - GaussPoint(IntegrationRule * ir, int n, double w, MaterialMode mode); + GaussPoint(IntegrationRule *ir, int n, double w, MaterialMode mode); - /// Destructor - virtual ~GaussPoint(); + ~GaussPoint(); /// Returns i-th natural element coordinate of receiver double giveNaturalCoordinate(int i) const { return naturalCoordinates.at(i); } /// Returns coordinate array of receiver. - const FloatArray &giveNaturalCoordinates() { return naturalCoordinates; } - void setNaturalCoordinates(const FloatArray &c) { - naturalCoordinates = c; - } + const FloatArray &giveNaturalCoordinates() const { return naturalCoordinates; } + void setNaturalCoordinates(const FloatArray &c) { naturalCoordinates = c; } /// Returns local sub-patch coordinates of the receiver - const FloatArray &giveSubPatchCoordinates() { + const FloatArray &giveSubPatchCoordinates() const + { if ( subPatchCoordinates ) { return *subPatchCoordinates; } else { @@ -153,32 +151,32 @@ class OOFEM_EXPORT GaussPoint if ( subPatchCoordinates ) { * subPatchCoordinates = c; } else { - subPatchCoordinates = new FloatArray(c); + subPatchCoordinates = std::make_unique(c); } } - inline const FloatArray &giveGlobalCoordinates() { - if( globalCoordinates ) { + inline const FloatArray &giveGlobalCoordinates() + { + if ( globalCoordinates ) { return *globalCoordinates; - } - else { - globalCoordinates = new FloatArray(); + } else { + globalCoordinates = std::make_unique(); this->giveElement()->computeGlobalCoordinates(*globalCoordinates, naturalCoordinates); return *globalCoordinates; } } - void setGlobalCoordinates(const FloatArray &iCoord) { - if( globalCoordinates ) { + void setGlobalCoordinates(const FloatArray &iCoord) + { + if ( globalCoordinates ) { *globalCoordinates = iCoord; - } - else { - globalCoordinates = new FloatArray(iCoord); + } else { + globalCoordinates = std::make_unique(iCoord); } } /// Returns integration weight of receiver. - virtual double giveWeight() { return weight; } + double giveWeight() { return weight; } void setWeight(double w) { weight = w; } /// Returns number of receiver. int giveNumber() { return number; } @@ -202,19 +200,9 @@ class OOFEM_EXPORT GaussPoint /** * Returns reference to associated material status (NULL if not defined). */ - IntegrationPointStatus *giveMaterialStatus() { return this->materialStatus; } - - /** - * Sets Material status managed by receiver. - * @param ptr Pointer to new status of receiver. - * @return Pointer to new status. - * @deprecated should be removed since only one mat stat is saved in the integration point - */ - IntegrationPointStatus *setMaterialStatus(IntegrationPointStatus *ptr, int n) - { - return this->setMaterialStatus(ptr); - } - + IntegrationPointStatus *giveMaterialStatus() { return this->materialStatus.get(); } + const IntegrationPointStatus *giveMaterialStatus() const { return this->materialStatus.get(); } + /** * Sets Material status managed by receiver. * @param ptr Pointer to new status of receiver. @@ -222,10 +210,10 @@ class OOFEM_EXPORT GaussPoint */ IntegrationPointStatus *setMaterialStatus(IntegrationPointStatus *ptr) { - if ( this->materialStatus != NULL ) { + if ( this->materialStatus ) { OOFEM_ERROR("status already exist"); } - this->materialStatus = ptr; + this->materialStatus.reset(ptr); return ptr; } /** @@ -234,7 +222,8 @@ class OOFEM_EXPORT GaussPoint * @return Slave gp. */ GaussPoint *giveSlaveGaussPoint(int index); - + std::vector< GaussPoint * > &giveSlaveGaussPoints() {return this->gaussPoints;} + /** * True if gauss point has slave points. Otherwise false. */ @@ -248,53 +237,20 @@ class OOFEM_EXPORT GaussPoint * associated status is called. The same function is also invoked for all available * slaves of receiver. */ - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep, const char* indent=""); /** * Updates internal state of receiver after finishing time step. * Material::updateYourself (receiver, tStep) function is called to * update material status. Same function is also invoked for * all receiver's slaves. */ - virtual void updateYourself(TimeStep *tStep); - - // store & restore context functions - /* - * Stores receiver state to output stream, including associated material status. - * Warning: Slaves are not saved, they must be saved by corresponding - * cross section or material model, which creates these slaves. - * This is because they may have special weights and coordinates, - * and these are not saved into context file, because they remain the same - * during whole solution (only variables which vary are stored into context). - * Note: does not invoke FEMComponents saveContext, since this writes only - * class id header, but typically due to large number of IPs, - * this is avoided. - * @exception throws an ContextIOERR exception if error encountered. - */ - //contextIOResultType saveContext (FILE* stream, void *obj = NULL); - /* - * Restores receiver state to output stream, including associated material status. - * Warning: Slaves are not restored, they must be restored by corresponding - * cross section or material model, which creates these slaves. - * This is because they may have special weights and coordinates, - * and these are not saved into context file, because they remain the same - * during whole solution (only variables which vary are stored into context). - * Note: does not invoke FEMComponents restoreContext, since this writes only - * class id header, but typically due to large number of IPs, - * this is avoided. - * @exception throws an ContextIOERR exception if error encountered. - */ - //contextIOResultType restoreContext(FILE* stream, void *obj = NULL); + void updateYourself(TimeStep *tStep); /// Returns class name of the receiver. - virtual const char *giveClassName() const { return "GaussPoint"; } - /// Initializes receiver according to object description stored in input record. - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + const char *giveClassName() const { return "GaussPoint"; } friend class LayeredCrossSection; - friend class MicroplaneMaterial; friend class FiberedCrossSection; - //friend class Material; - //friend class LayeredMaterial; }; typedef GaussPoint IntegrationPoint; diff --git a/src/oofemlib/generalboundarycondition.C b/src/oofemlib/generalboundarycondition.C index 04754030f..39d5dc960 100644 --- a/src/oofemlib/generalboundarycondition.C +++ b/src/oofemlib/generalboundarycondition.C @@ -62,15 +62,12 @@ Function *GeneralBoundaryCondition :: giveTimeFunction() } -IRResultType -GeneralBoundaryCondition :: initializeFrom(InputRecord *ir) +void +GeneralBoundaryCondition :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, timeFunction, _IFT_GeneralBoundaryCondition_timeFunct); if ( timeFunction <= 0 ) { - OOFEM_WARNING("bad TimeFunction id"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_GeneralBoundaryCondition_timeFunct, "Must be over 0"); } int val = 0; @@ -85,8 +82,6 @@ GeneralBoundaryCondition :: initializeFrom(InputRecord *ir) set = 0; IR_GIVE_OPTIONAL_FIELD(ir, set, _IFT_GeneralBoundaryCondition_set); - - return IRRT_OK; } bool GeneralBoundaryCondition :: isImposed(TimeStep *tStep) @@ -127,28 +122,56 @@ GeneralBoundaryCondition :: giveInputRecord(DynamicInputRecord &input) } } -contextIOResultType -GeneralBoundaryCondition :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +GeneralBoundaryCondition :: saveContext(DataStream &stream, ContextMode mode) { + FEMComponent :: saveContext(stream, mode); + if ( mode & CM_Definition ) { if ( !stream.write(timeFunction) ) { THROW_CIOERR(CIO_IOERR); } + if ( !stream.write(valType) ) { + THROW_CIOERR(CIO_IOERR); + } + contextIOResultType iores; + if ( ( iores = dofs.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + if ( !stream.write(isImposedTimeFunction) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(set) ) { + THROW_CIOERR(CIO_IOERR); + } } - - return CIO_OK; } -contextIOResultType -GeneralBoundaryCondition :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +GeneralBoundaryCondition :: restoreContext(DataStream &stream, ContextMode mode) { + FEMComponent :: restoreContext(stream, mode); + if ( mode & CM_Definition ) { if ( !stream.read(timeFunction) ) { THROW_CIOERR(CIO_IOERR); } + int _val; + if ( !stream.read(_val) ) { + THROW_CIOERR(CIO_IOERR); + } + contextIOResultType iores; + valType = (bcValType) _val; + if ( ( iores = dofs.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + if ( !stream.read(isImposedTimeFunction) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(set) ) { + THROW_CIOERR(CIO_IOERR); + } } - - return CIO_OK; } } // end namespace oofem diff --git a/src/oofemlib/generalboundarycondition.h b/src/oofemlib/generalboundarycondition.h index fe2c48b39..a92ebcb6c 100644 --- a/src/oofemlib/generalboundarycondition.h +++ b/src/oofemlib/generalboundarycondition.h @@ -113,7 +113,7 @@ class OOFEM_EXPORT GeneralBoundaryCondition : public FEMComponent /// Gives the number of internal dof managers. virtual int giveNumberOfInternalDofManagers() { return 0; } /// Gives an internal dof manager from receiver. - virtual DofManager *giveInternalDofManager(int i) { return NULL; } + virtual DofManager *giveInternalDofManager(int i) { return nullptr; } /** @@ -121,6 +121,18 @@ class OOFEM_EXPORT GeneralBoundaryCondition : public FEMComponent */ Function *giveTimeFunction(); + /** + * Gets the activity time function number. + */ + int getIsImposedTimeFunctionNumber(){ return this->isImposedTimeFunction; } + + + /** + * Sets the activity time function of receiver. + * @param funcIndx Index of new time function. + */ + void setIsImposedTimeFunctionNumber(int funcIndx){ this->isImposedTimeFunction = funcIndx; } + /** * Returns receiver load type. It distinguish particular boundary conditions according to * their "physical" meaning (like StructuralTemperatureLoadLT, StructuralLoadLT). @@ -162,11 +174,11 @@ class OOFEM_EXPORT GeneralBoundaryCondition : public FEMComponent virtual void postInitialize() { } // Overloaded methods: - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; } // end namespace oofem #endif // generalbc_h diff --git a/src/oofemlib/generalslavenode.C b/src/oofemlib/generalslavenode.C new file mode 100644 index 000000000..0a61d24c5 --- /dev/null +++ b/src/oofemlib/generalslavenode.C @@ -0,0 +1,122 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2022 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "generalslavenode.h" +#include "slavedof.h" +#include "floatarray.h" +#include "intarray.h" +#include "entityrenumberingscheme.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_DofManager(GeneralSlaveNode); + +void GeneralSlaveNode::initializeFrom(InputRecord &ir) +{ + IntArray dofTypeMask; + dofTypeMask.clear(); + IR_GIVE_FIELD(ir, dofTypeMask, _IFT_DofManager_doftypemask); + // + Node::initializeFrom(ir); + // + int size = 0; + for ( int i = 1; i <= dofTypeMask.giveSize(); i++ ) { + if ( dofTypeMask.at(i) != 0 ) { + size++; + } + } + + IntArray masterList; + FloatArray masterWeights; + masterSizes = 0; + if ( size > 0 ) { + IR_GIVE_FIELD(ir, masterSizes, _IFT_GeneralSlaveNode_masterSizes); + if ( masterSizes.giveSize() != size ) { + OOFEM_ERROR("OOFEM ERROR: masterSizes size does not correspond to doftype size"); + } + + IR_GIVE_FIELD(ir, masterList, _IFT_GeneralSlaveNode_masterList); + IR_GIVE_FIELD(ir, masterWeights, _IFT_GeneralSlaveNode_masterWeights); + } + + int index = 0; + for ( int j = 1; j <= masterSizes.giveSize(); j++ ) { + IntArray dof_masterList( masterSizes.at(j) ); + IntArray dof_dofsList( masterSizes.at(j) ); + FloatArray dof_weightsList( masterSizes.at(j) ); + + for ( int i = 1; i <= masterSizes.at(j); i++ ) { + index++; + dof_masterList.at(i) = masterList.at(2 * index - 1); + dof_dofsList.at(i) = masterList.at(2 * index); + dof_weightsList.at(i) = masterWeights.at(index); + } + dofs_masterList.push_back(dof_masterList); + dofs_dofsList.push_back(dof_dofsList); + dofs_weightsList.push_back(dof_weightsList); + } +} + + +void +GeneralSlaveNode::postInitialize() +{ + Node::postInitialize(); + + // initialize slave dofs (inside check of consistency of receiver and master dof) + int i = 0; + for ( Dof *dof: * this ) { + SlaveDof *sdof = dynamic_cast< SlaveDof * >( dof ); + if ( sdof ) { + IntArray masterDofManagers = dofs_masterList [ i ]; + IntArray masterDofIDArray = dofs_dofsList [ i ]; + FloatArray masterWeights = dofs_weightsList [ i ]; + sdof->initialize(masterDofManagers, masterDofIDArray, masterWeights); + i++; + } + } +} + + + +void GeneralSlaveNode::updateLocalNumbering(EntityRenumberingFunctor &f) +{ + for ( int j = 0; j < masterSizes.giveSize(); j++ ) { + for ( int i = 1; i <= dofs_masterList [ j ].giveSize(); i++ ) { + dofs_masterList [ j ].at(i) = f(dofs_masterList [ j ].at(i), ERS_DofManager); + } + } + DofManager::updateLocalNumbering(f); +} +} // end namespace oofem diff --git a/src/oofemlib/generalslavenode.h b/src/oofemlib/generalslavenode.h new file mode 100644 index 000000000..eb3831aed --- /dev/null +++ b/src/oofemlib/generalslavenode.h @@ -0,0 +1,93 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2022 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef generalslavenode_h +#define generalslavenode_h + +#include "node.h" +#include +///@name Input fields for SlaveNode +//@{ +#define _IFT_GeneralSlaveNode_Name "generalslavenode" +#define _IFT_GeneralSlaveNode_masterSizes "mastersizes" +#define _IFT_GeneralSlaveNode_masterWeights "masterweights" +#define _IFT_GeneralSlaveNode_masterList "masterlist" +//@} + +namespace oofem { +/** + * Class implementing slave node connected to other nodes (masters) using predetermined weights. + * The node can not have its own boundary or initial conditions, + * they are determined completely from master dof conditions except for dofs of master type. + * This approach is more general than SlaveNode because it enables individual slave node's dofs + * to depend on different masters with different sizes + * The GeneralSlaveNode is suitable, e.g., for setting periodic boundary conditions + * @author Martin Horák + */ +class OOFEM_EXPORT GeneralSlaveNode : public Node +{ +protected: + + /// Master nodes for all dofs. + std::vector< IntArray >dofs_masterList; + std::vector< IntArray >dofs_dofsList; + std::vector< FloatArray >dofs_weightsList; + + IntArray masterSizes; + +public: + /** + * Constructor. Creates a general slave node with number n, belonging to aDomain. + * @param n Node number in domain aDomain. + * @param aDomain Domain to which node belongs. + */ + GeneralSlaveNode(int n, Domain *aDomain) : Node(n, aDomain) {} + /// Destructor. + virtual ~GeneralSlaveNode(void) {} + + void initializeFrom(InputRecord &ir) override; + virtual void postInitialize() override; + virtual bool isDofTypeCompatible(dofType type) const override { + return ( type == DT_master || type == DT_slave ); + } + virtual void updateLocalNumbering(EntityRenumberingFunctor &f) override; + virtual const char *giveClassName() const override { + return "GeneralSlaveNode"; + } + virtual const char *giveInputRecordName() const override { + return _IFT_GeneralSlaveNode_Name; + } +}; +} // end namespace oofem +#endif // generalslavenode_h diff --git a/src/oofemlib/geometry.C b/src/oofemlib/geometry.C index c80e0d0c5..704c8f72a 100644 --- a/src/oofemlib/geometry.C +++ b/src/oofemlib/geometry.C @@ -66,22 +66,20 @@ BasicGeometry :: ~BasicGeometry() void BasicGeometry :: removeDuplicatePoints(const double &iTolSquare) { - if(mVertices.size() > 1) { - for(size_t i = mVertices.size()-1; i > 0; i--) { - - if( mVertices[i].distance_square(mVertices[i-1]) < iTolSquare ) { + if ( mVertices.size() > 1 ) { + for ( size_t i = mVertices.size()-1; i > 0; i--) { + if ( distance_square(mVertices[i], mVertices[i-1]) < iTolSquare ) { mVertices.erase( mVertices.begin()+i ); } - } } } void BasicGeometry :: translate(const FloatArray &iTrans) { - for(size_t i = 0; i < mVertices.size(); i++) { - mVertices[i].add(iTrans); - } + for ( size_t i = 0; i < mVertices.size(); i++ ) { + mVertices[i].add(iTrans); + } } @@ -118,25 +116,25 @@ double BasicGeometry :: computeLineDistance(const FloatArray &iP1, const FloatAr bool lockXi = false, lockEta = false; - for(size_t iter = 0; iter < maxIter; iter++) { + for ( size_t iter = 0; iter < maxIter; iter++ ) { - if(xi < 0.0) { + if ( xi < 0.0 ) { xi = 0.0; lockXi = true; } - if(xi > 1.0) { + if ( xi > 1.0 ) { xi = 1.0; lockXi = true; } - if(eta < 0.0) { + if ( eta < 0.0 ) { eta = 0.0; lockEta = true; } - if(eta > 1.0) { + if ( eta > 1.0 ) { eta = 1.0; lockEta = true; } @@ -144,18 +142,18 @@ double BasicGeometry :: computeLineDistance(const FloatArray &iP1, const FloatAr FloatArray R = { d.dotProduct(u) + c1*xi, -d.dotProduct(v) + c2*eta}; - if(lockXi) { + if ( lockXi ) { R[0] = 0.0; } - if(lockEta) { + if ( lockEta ) { R[1] = 0.0; } const double res = R.computeNorm(); // printf("iter: %lu res: %e\n", iter, res); - if(res < absTol && iter >= minIter) { + if ( res < absTol && iter >= minIter ) { // printf("xi: %e eta: %e\n", xi, eta); break; } @@ -166,12 +164,12 @@ double BasicGeometry :: computeLineDistance(const FloatArray &iP1, const FloatAr K(1,1) = -v.dotProduct(v)-c2; - if(lockXi) { + if ( lockXi ) { K(0,0) = -1.0; K(0,1) = K(1,0) = 0.0; } - if(lockEta) { + if ( lockEta ) { K(0,1) = K(1,0) = 0.0; K(1,1) = -1.0; } @@ -190,19 +188,19 @@ double BasicGeometry :: computeLineDistance(const FloatArray &iP1, const FloatAr d.add(-eta, v); } - if(xi < 0.0) { + if ( xi < 0.0 ) { xi = 0.0; } - if(xi > 1.0) { + if ( xi > 1.0 ) { xi = 1.0; } - if(eta < 0.0) { + if ( eta < 0.0 ) { eta = 0.0; } - if(eta > 1.0) { + if ( eta > 1.0 ) { eta = 1.0; } @@ -228,16 +226,16 @@ Line :: Line(const FloatArray &iPointA, const FloatArray &iPointB) : BasicGeomet mVertices.push_back(iPointB); } -double Line :: computeDistanceTo(const FloatArray *point) +double Line :: computeDistanceTo(const FloatArray &point) { // TODO: Is this function correct?! /ES - const FloatArray &pointA = mVertices [ 0 ]; - const FloatArray &pointB = mVertices [ 1 ]; + const auto &pointA = mVertices [ 0 ]; + const auto &pointB = mVertices [ 1 ]; double a = pointA.at(2) - pointB.at(2); double b = pointB.at(1) - pointA.at(1); double c = pointA.at(1) * pointB.at(2) - pointB.at(1) * pointA.at(2); - double l = pointA.distance(pointB); - return ( a * point->at(1) + b * point->at(2) + c ) / l; + double l = distance(pointA, pointB); + return ( a * point.at(1) + b * point.at(2) + c ) / l; } void Line :: computeProjection(FloatArray &answer) @@ -245,12 +243,12 @@ void Line :: computeProjection(FloatArray &answer) answer.beDifferenceOf(mVertices [ 1 ], mVertices [ 0 ]); } -double Line :: computeTangentialDistanceToEnd(FloatArray *point) +double Line :: computeTangentialDistanceToEnd(const FloatArray &point) { FloatArray projection; this->computeProjection(projection); FloatArray tmp; - tmp.beDifferenceOf(* point, mVertices [ 1 ]); + tmp.beDifferenceOf(point, mVertices [ 1 ]); return tmp.dotProduct(projection) / projection.computeNorm(); } @@ -274,15 +272,14 @@ int Line :: computeNumberOfIntersectionPoints(Element *element) const int numEdges = element->giveInterpolation()->giveNumberOfEdges(); for ( int edgeIndex = 1; edgeIndex <= numEdges; edgeIndex++ ) { - IntArray bNodes; - element->giveInterpolation()->boundaryGiveNodes(bNodes, edgeIndex); + auto bNodes = element->giveInterpolation()->boundaryGiveNodes(edgeIndex); const int nsLoc = bNodes.at(1); const int neLoc = bNodes.at( bNodes.giveSize() ); - FloatArray xS = *(element->giveNode(nsLoc)->giveCoordinates() ); + FloatArray xS = element->giveNode(nsLoc)->giveCoordinates(); xS.resizeWithValues(2); - FloatArray xE = *(element->giveNode(neLoc)->giveCoordinates() ); + FloatArray xE = element->giveNode(neLoc)->giveCoordinates(); xE.resizeWithValues(2); const double dist = BasicGeometry :: computeLineDistance(xS, xE, mVertices[0], mVertices[1]); @@ -357,14 +354,11 @@ void Line :: transformIntoPolar(FloatArray *point, FloatArray &answer) answer.at(2) = atan2( xp.at(2), xp.at(1) ); } -IRResultType Line :: initializeFrom(InputRecord *ir) +void Line :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - mVertices.resize(2); IR_GIVE_FIELD(ir, mVertices [ 0 ], _IFT_Line_start); IR_GIVE_FIELD(ir, mVertices [ 1 ], _IFT_Line_end); - return IRRT_OK; } bool Line :: isPointInside(FloatArray *point) @@ -398,7 +392,7 @@ bool Line :: isOutside(BasicGeometry *bg) { // equivalent to up int count = 0; for ( int i = 1; i <= bg->giveNrVertices(); i++ ) { - if ( this->computeDistanceTo( & ( bg->giveVertex(i) ) ) > 0.1 ) { + if ( this->computeDistanceTo( bg->giveVertex(i) ) > 0.1 ) { count++; } } @@ -422,16 +416,16 @@ double Triangle :: getArea() double Triangle :: getRadiusOfCircumCircle() { - return 0.25 * mVertices [ 0 ].distance(mVertices [ 1 ]) * - mVertices [ 1 ].distance(mVertices [ 2 ]) * - mVertices [ 0 ].distance(mVertices [ 2 ]) / this->getArea(); + return 0.25 * distance(mVertices [ 0 ], mVertices [ 1 ]) * + distance(mVertices [ 1 ], mVertices [ 2 ]) * + distance(mVertices [ 0 ], mVertices [ 2 ]) / this->getArea(); } void Triangle :: computeBarycentrCoor(FloatArray &answer) const { - double c = mVertices [ 0 ].distance(mVertices [ 1 ]); - double a = mVertices [ 1 ].distance(mVertices [ 2 ]); - double b = mVertices [ 0 ].distance(mVertices [ 2 ]); + double c = distance(mVertices [ 0 ], mVertices [ 1 ]); + double a = distance(mVertices [ 1 ], mVertices [ 2 ]); + double b = distance(mVertices [ 0 ], mVertices [ 2 ]); // just to avoid multiple multiplication double aPow = a * a; @@ -609,7 +603,7 @@ bool Triangle :: pointIsInTriangle(const FloatArray &iP) const FloatArray p1pProj; - p1pProj.beDifferenceOf(pProj, mVertices [ 0 ]); + p1pProj.beDifferenceOf(pProj, mVertices [ 0 ], mVertices[0].giveSize()); if ( p1pProj.dotProduct(a1) < 0.0 ) { return false; } @@ -617,13 +611,13 @@ bool Triangle :: pointIsInTriangle(const FloatArray &iP) const FloatArray p2pProj; - p2pProj.beDifferenceOf(pProj, mVertices [ 1 ]); + p2pProj.beDifferenceOf(pProj, mVertices [ 1 ], mVertices[1].giveSize()); if ( p2pProj.dotProduct(a2) < 0.0 ) { return false; } FloatArray p3pProj; - p3pProj.beDifferenceOf(pProj, mVertices [ 2 ]); + p3pProj.beDifferenceOf(pProj, mVertices [ 2 ], mVertices[2].giveSize()); if ( p3pProj.dotProduct(a3) < 0.0 ) { return false; } @@ -665,7 +659,7 @@ Circle :: Circle(FloatArray ¢er, double radius) : void Circle :: computeNormalSignDist(double &oDist, const FloatArray &iPoint) const { - oDist = mVertices [ 0 ].distance(iPoint) - radius; + oDist = distance(mVertices [ 0 ], iPoint) - radius; } void Circle :: giveGlobalCoordinates(FloatArray &oGlobalCoord, const double &iArcPos) const @@ -676,23 +670,20 @@ void Circle :: giveGlobalCoordinates(FloatArray &oGlobalCoord, const double &iAr oGlobalCoord = { mVertices[0][0] + radius*cos(angle), mVertices[0][1] + radius*sin(angle) }; } -IRResultType Circle :: initializeFrom(InputRecord *ir) +void Circle :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - mVertices.resize(1); IR_GIVE_FIELD(ir, mVertices [ 0 ], _IFT_Circle_center); IR_GIVE_FIELD(ir, radius, _IFT_Circle_radius); - return IRRT_OK; } bool Circle :: intersects(Element *element) { int count = 0; for ( int i = 1; i <= element->giveNumberOfDofManagers(); i++ ) { - FloatArray *nodeCoor = element->giveDofManager(i)->giveCoordinates(); + const auto &nodeCoor = element->giveDofManager(i)->giveCoordinates(); // distance from the node to the center of the circle - double dist = nodeCoor->distance(mVertices [ 0 ]); + double dist = distance(nodeCoor, mVertices [ 0 ]); if ( dist > this->radius ) { count++; } @@ -708,9 +699,9 @@ bool Circle :: intersects(Element *element) bool -Circle :: isInside(FloatArray &point) +Circle :: isInside(const FloatArray &point) { - double dist = this->giveVertex(1).distance(point); + double dist = distance(this->giveVertex(1), point); if ( dist < this->radius ) { return true; } @@ -721,7 +712,7 @@ Circle :: isInside(FloatArray &point) bool Circle :: isInside(Element *element) { // condition should maybe be that all nodes should be inside for ( int i = 1; i <= element->giveNumberOfDofManagers(); i++ ) { - FloatArray nodeCoord = * element->giveDofManager(i)->giveCoordinates(); + const auto &nodeCoord = element->giveDofManager(i)->giveCoordinates(); if ( isInside(nodeCoord) ) { return true; } @@ -738,13 +729,10 @@ void Circle :: computeIntersectionPoints(Element *element, std :: vector< FloatA for ( int i = 1; i <= element->giveNumberOfBoundarySides(); i++ ) { std :: vector< FloatArray >oneLineIntersects; ///@todo Move semantics or something would be useful here to avoid multiple copies. - FloatArray a = * element->giveDofManager ( i )->giveCoordinates(); - FloatArray b; - if ( i != element->giveNumberOfBoundarySides() ) { - b = * element->giveDofManager ( i + 1 )->giveCoordinates(); - } else { - b = * element->giveDofManager ( 1 )->giveCoordinates(); - } + const auto &a = element->giveDofManager ( i )->giveCoordinates(); + const auto &b = ( i != element->giveNumberOfBoundarySides() ) ? + element->giveDofManager ( i + 1 )->giveCoordinates() : + element->giveDofManager ( 1 )->giveCoordinates(); Line l(a, b); computeIntersectionPoints(& l, oneLineIntersects); @@ -824,7 +812,7 @@ bool Circle :: isOutside(BasicGeometry *bg) { int count = 0; for ( int i = 1; i <= bg->giveNrVertices(); i++ ) { - if ( 0.9999 * bg->giveVertex(i).distance(mVertices [ 0 ]) > this->radius ) { + if ( 0.9999 * distance(bg->giveVertex(i), mVertices [ 0 ]) > this->radius ) { count++; } } @@ -894,17 +882,17 @@ void PolygonLine :: computeNormalSignDist(double &oDist, const FloatArray &iPoin if ( s > l ) { // X is closest to P2 - dist2 = point.distance_square(crackP2); + dist2 = distance_square(point, crackP2); } else { double xi = s / l; - FloatArray q = ( 1.0 - xi ) * crackP1 + xi * crackP2; - dist2 = point.distance_square(q); + auto q = ( 1.0 - xi ) * crackP1 + xi * crackP2; + dist2 = distance_square(point, q); } } else { // If the points P1 and P2 coincide, // we can compute the distance to any // of these points. - dist2 = point.distance_square(crackP1); + dist2 = distance_square(point, crackP1); } } else if ( segId == numSeg ) { // Vector from start P1 to point X @@ -920,17 +908,17 @@ void PolygonLine :: computeNormalSignDist(double &oDist, const FloatArray &iPoin if ( s < 0.0 ) { // X is closest to P1 - dist2 = point.distance_square(crackP1); + dist2 = distance_square(point, crackP1); } else { double xi = s / l; - FloatArray q = ( 1.0 - xi ) * crackP1 + xi * crackP2; - dist2 = point.distance_square(q); + auto q = ( 1.0 - xi ) * crackP1 + xi * crackP2; + dist2 = distance_square(point, q); } } else { // If the points P1 and P2 coincide, // we can compute the distance to any // of these points. - dist2 = point.distance_square(crackP1); + dist2 = distance_square(point, crackP1); } } else { double arcPos = -1.0, dummy; @@ -953,35 +941,35 @@ void PolygonLine :: computeNormalSignDist(double &oDist, const FloatArray &iPoin void PolygonLine :: computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinArcDist) const { - FloatArray point = iPoint; - point.resizeWithValues(2); + FloatArray point = iPoint; + point.resizeWithValues(2); const int numSeg = this->giveNrVertices() - 1; double xi = 0.0, xiUnbounded = 0.0; - if(numSeg == 0) { - FloatArray crackP1 = giveVertex ( 1 ); - oDist = crackP1.distance(iPoint); - oMinArcDist = 0.0; - return; + if ( numSeg == 0 ) { + FloatArray crackP1 = giveVertex ( 1 ); + oDist = distance(crackP1, iPoint); + oMinArcDist = 0.0; + return; } - if(numSeg == 1) { - FloatArray crackP1 = giveVertex ( 1 ); - crackP1.resizeWithValues(2); - FloatArray crackP2 = giveVertex ( 2 ); - crackP2.resizeWithValues(2); + if ( numSeg == 1 ) { + FloatArray crackP1 = giveVertex ( 1 ); + crackP1.resizeWithValues(2); + FloatArray crackP2 = giveVertex ( 2 ); + crackP2.resizeWithValues(2); point.distance(crackP1, crackP2, xi, xiUnbounded); if( xiUnbounded < 0.0 ) { - oDist = xiUnbounded*crackP1.distance(crackP2); + oDist = xiUnbounded * distance(crackP1, crackP2); oMinArcDist = 0.0; return; } if( xiUnbounded > 1.0 ) { - oDist = -(xiUnbounded-1.0)*crackP1.distance(crackP2); + oDist = -(xiUnbounded-1.0) * distance(crackP1, crackP2); oMinArcDist = 1.0; return; } @@ -1007,11 +995,11 @@ void PolygonLine :: computeTangentialSignDist(double &oDist, const FloatArray &i if( xiUnbounded < 0.0 ) { isBeforeStart = true; - distBeforeStart = xiUnbounded*crackP1_start.distance(crackP2_start); + distBeforeStart = xiUnbounded * distance(crackP1_start, crackP2_start); } - double arcPosPassed = crackP1_start.distance(crackP2_start); - double distToStart = xi*crackP1_start.distance(crackP2_start); + double arcPosPassed = distance(crackP1_start, crackP2_start); + double distToStart = xi * distance(crackP1_start, crackP2_start); double minGeomDist = distSeg_start; @@ -1021,9 +1009,9 @@ void PolygonLine :: computeTangentialSignDist(double &oDist, const FloatArray &i /////////////////////////////////////////////////////////////////// // Check interior segments for ( int segId = 2; segId <= numSeg-1; segId++ ) { - FloatArray crackP1 = giveVertex ( segId ); - crackP1.resizeWithValues(2); - FloatArray crackP2 = giveVertex ( segId+1 ); + FloatArray crackP1 = giveVertex ( segId ); + crackP1.resizeWithValues(2); + FloatArray crackP2 = giveVertex ( segId+1 ); crackP2.resizeWithValues(2); const double distSeg = point.distance(crackP1, crackP2, xi, xiUnbounded); @@ -1031,10 +1019,10 @@ void PolygonLine :: computeTangentialSignDist(double &oDist, const FloatArray &i if(distSeg < minGeomDist) { isBeforeStart = false; minGeomDist = distSeg; - distToStart = arcPosPassed + xi*crackP1.distance(crackP2); + distToStart = arcPosPassed + xi * distance(crackP1, crackP2); } - arcPosPassed += crackP1.distance(crackP2); + arcPosPassed += distance(crackP1, crackP2); } @@ -1048,21 +1036,21 @@ void PolygonLine :: computeTangentialSignDist(double &oDist, const FloatArray &i crackP2_end.resizeWithValues(2); const double distSeg_end = point.distance(crackP1_end, crackP2_end, xi, xiUnbounded); - if(numSeg > 1) { + if ( numSeg > 1 ) { if( xiUnbounded > 1.0 ) { - arcPosPassed += xiUnbounded*crackP1_end.distance(crackP2_end); + arcPosPassed += xiUnbounded * distance(crackP1_end, crackP2_end); } else { - arcPosPassed += xi*crackP1_end.distance(crackP2_end); + arcPosPassed += xi * distance(crackP1_end, crackP2_end); } } - if(distSeg_end < minGeomDist) { + if ( distSeg_end < minGeomDist ) { isBeforeStart = false; if( xiUnbounded > 1.0 ) { isAfterEnd = true; - distAfterEnd = -(xiUnbounded-1.0)*crackP1_end.distance(crackP2_end); + distAfterEnd = -(xiUnbounded-1.0) * distance(crackP1_end, crackP2_end); } distToStart = arcPosPassed; @@ -1071,13 +1059,13 @@ void PolygonLine :: computeTangentialSignDist(double &oDist, const FloatArray &i /////////////////////////////////////////////////////////////////// // Return result - if(isBeforeStart) { + if ( isBeforeStart ) { oDist = distBeforeStart; oMinArcDist = 0.0; return; } - if(isAfterEnd) { + if ( isAfterEnd ) { oDist = distAfterEnd; oMinArcDist = 1.0; return; @@ -1094,20 +1082,20 @@ void PolygonLine :: computeLocalCoordinates(FloatArray &oLocCoord, const FloatAr double PolygonLine :: computeLength() const { - if( mVertices.size() == 0 ) { - return 0.0; - } + if ( mVertices.size() == 0 ) { + return 0.0; + } double L = 0.0; size_t numSeg = mVertices.size() - 1; - if(numSeg == 0) { - return 0.0; + if ( numSeg == 0 ) { + return 0.0; } for ( size_t i = 0; i < numSeg; i++ ) { - L += mVertices [ i ].distance(mVertices [ i + 1 ]); + L += distance(mVertices [ i ], mVertices [ i + 1 ]); } return L; @@ -1126,10 +1114,10 @@ void PolygonLine :: giveSubPolygon(std :: vector< FloatArray > &oPoints, const d } for ( size_t i = 0; i < numSeg; i++ ) { - xSegEnd += mVertices [ i ].distance(mVertices [ i + 1 ]); + xSegEnd += distance(mVertices [ i ], mVertices [ i + 1 ]); xiSegStart = xSegStart / L; - xiSegEnd = xSegEnd / L; + xiSegEnd = xSegEnd / L; if ( iXiStart > xiSegStart-xiTol && iXiStart < xiSegEnd+xiTol ) { // Start point is within the segment @@ -1172,10 +1160,10 @@ void PolygonLine :: giveGlobalCoordinates(FloatArray &oGlobalCoord, const double } for ( size_t i = 0; i < numSeg; i++ ) { - xSegEnd += mVertices [ i ].distance(mVertices [ i + 1 ]); + xSegEnd += distance(mVertices [ i ], mVertices [ i + 1 ]); xiSegStart = xSegStart / L; - xiSegEnd = xSegEnd / L; + xiSegEnd = xSegEnd / L; if ( iArcPos > xiSegStart-xiTol && iArcPos < xiSegEnd+xiTol ) { // Point is within the segment @@ -1199,10 +1187,10 @@ void PolygonLine :: giveNormal(FloatArray &oNormal, const double &iArcPosition) const double xiTol = 1.0e-9; for ( size_t i = 0; i < numSeg; i++ ) { - xSegEnd += mVertices [ i ].distance(mVertices [ i + 1 ]); + xSegEnd += distance(mVertices [ i ], mVertices [ i + 1 ]); - xiSegStart = xSegStart / L; - xiSegEnd = xSegEnd / L; + xiSegStart = xSegStart / L; + xiSegEnd = xSegEnd / L; if ( iArcPosition > xiSegStart-xiTol && iArcPosition < xiSegEnd+xiTol ) { // The given point is within the segment @@ -1234,10 +1222,10 @@ void PolygonLine :: giveTangent(FloatArray &oTangent, const double &iArcPosition const double xiTol = 1.0e-9; for ( size_t i = 0; i < numSeg; i++ ) { - xSegEnd += mVertices [ i ].distance(mVertices [ i + 1 ]); + xSegEnd += distance(mVertices [ i ], mVertices [ i + 1 ]); - xiSegStart = xSegStart / L; - xiSegEnd = xSegEnd / L; + xiSegStart = xSegStart / L; + xiSegEnd = xSegEnd / L; if ( iArcPosition > xiSegStart-xiTol && iArcPosition < xiSegEnd+xiTol ) { // The given point is within the segment @@ -1257,11 +1245,8 @@ void PolygonLine :: giveTangent(FloatArray &oTangent, const double &iArcPosition OOFEM_ERROR("Arc position not found.") } -IRResultType PolygonLine :: initializeFrom(InputRecord *ir) +void PolygonLine :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - FloatArray points; IR_GIVE_FIELD(ir, points, _IFT_PolygonLine_points); @@ -1271,13 +1256,10 @@ IRResultType PolygonLine :: initializeFrom(InputRecord *ir) mVertices.push_back({points.at(2 * ( i - 1 ) + 1), points.at( 2 * ( i ) )}); } - #ifdef __BOOST_MODULE // Precompute bounding box to speed up calculation of intersection points. calcBoundingBox(LC, UC); #endif - - return IRRT_OK; } void PolygonLine :: giveInputRecord(DynamicInputRecord &input) @@ -1396,7 +1378,7 @@ bool PolygonLine :: isInside(Element *element) } bool -PolygonLine :: isInside(FloatArray &point) +PolygonLine :: isInside(const FloatArray &point) { return false; } @@ -1430,18 +1412,14 @@ void PolygonLine :: computeIntersectionPoints(Element *element, std :: vector< F for ( int i = 1; i <= element->giveNumberOfBoundarySides(); i++ ) { std :: vector< FloatArray > oneLineIntersects; ///@todo Move semantics or something would be useful here to avoid multiple copies. - FloatArray xStart = * element->giveDofManager ( i )->giveCoordinates(); - FloatArray xEnd; - if ( i != element->giveNumberOfBoundarySides() ) { - xEnd = * element->giveDofManager ( i + 1 )->giveCoordinates(); - } else { - xEnd = * element->giveDofManager ( 1 )->giveCoordinates(); - } - + const auto &xStart = element->giveDofManager ( i )->giveCoordinates(); + const auto &xEnd = ( i != element->giveNumberOfBoundarySides() ) ? + element->giveDofManager ( i + 1 )->giveCoordinates() : + element->giveDofManager ( 1 )->giveCoordinates(); computeIntersectionPoints(xStart, xEnd, oneLineIntersects); - for ( FloatArray &interSect: oneLineIntersects ) { + for ( auto &interSect: oneLineIntersects ) { // Check that the intersection point has not already been identified. // This may happen if the crack intersects the element exactly at a node, // so that intersection is detected for both element edges in that node. @@ -1451,12 +1429,9 @@ void PolygonLine :: computeIntersectionPoints(Element *element, std :: vector< F bool alreadyFound = false; - FloatArray pNew = interSect; + for ( auto &pInterSect: oIntersectionPoints ) { - for ( FloatArray &pInterSect: oIntersectionPoints ) { - FloatArray pOld = pInterSect; - - if ( pOld.distance(pNew) < distTol ) { + if ( distance(pInterSect, interSect) < distTol ) { alreadyFound = true; break; } @@ -1482,13 +1457,10 @@ void PolygonLine :: computeIntersectionPoints(Element *element, std :: vector< F for ( int i = 1; i <= element->giveNumberOfBoundarySides(); i++ ) { std :: vector< FloatArray >oneLineIntersects; ///@todo Move semantics or something would be useful here to avoid multiple copies. - FloatArray a = * element->giveDofManager ( i )->giveCoordinates(); - FloatArray b; - if ( i != element->giveNumberOfBoundarySides() ) { - b = * element->giveDofManager ( i + 1 )->giveCoordinates(); - } else { - b = * element->giveDofManager ( 1 )->giveCoordinates(); - } + const auto &a = * element->giveDofManager ( i )->giveCoordinates(); + const auto &b = ( i != element->giveNumberOfBoundarySides() ) ? + * element->giveDofManager ( i + 1 )->giveCoordinates() : + * element->giveDofManager ( 1 )->giveCoordinates(); Line l(a, b); @@ -1617,8 +1589,8 @@ void PolygonLine :: computeIntersectionPoints(const FloatArray &iXStart, const F FloatArray dxi; dxi.beProductOf(KInv, res); - xi1 -= dxi(0); - xi2 -= dxi(1); + xi1 -= dxi[0]; + xi2 -= dxi[1]; } // printf("xi1: %e xi2: %e\n", xi1, xi2); @@ -1791,7 +1763,7 @@ void PolygonLine :: giveBoundingSphere(FloatArray &oCenter, double &oRadius) oCenter.times( 1.0 / double( nVert ) ); for ( int i = 1; i <= nVert; i++ ) { - oRadius = std :: max( oRadius, oCenter.distance( giveVertex(i) ) ); + oRadius = std :: max( oRadius, distance(oCenter, giveVertex(i) ) ); } } @@ -1808,9 +1780,8 @@ void PolygonLine :: cropPolygon(const double &iArcPosStart, const double &iArcPo } -IRResultType PointSwarm :: initializeFrom(InputRecord *ir) +void PointSwarm :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro IntArray idList; IR_GIVE_FIELD(ir, idList, _IFT_PointSwarm_nodeID); // Macro @@ -1818,6 +1789,5 @@ IRResultType PointSwarm :: initializeFrom(InputRecord *ir) for ( int i = 1; i <= idList.giveSize(); i++ ) { this->idList.push_back( idList.at(i) ); } - return IRRT_OK; } } // end namespace oofem diff --git a/src/oofemlib/geometry.h b/src/oofemlib/geometry.h index 0caaa35e7..42c42f522 100644 --- a/src/oofemlib/geometry.h +++ b/src/oofemlib/geometry.h @@ -96,7 +96,7 @@ class OOFEM_EXPORT BasicGeometry //: public Geometry virtual BasicGeometry *Clone() = 0; /// Computes normal signed distance between this object and a point. - virtual double computeDistanceTo(const FloatArray *point) { return 0; } + virtual double computeDistanceTo(const FloatArray &point) { return 0; } // For debugging @@ -135,7 +135,7 @@ class OOFEM_EXPORT BasicGeometry //: public Geometry void translate(const FloatArray &iTrans); /// Initializes the Geometry from the InputRecord. - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + virtual void initializeFrom(InputRecord &ir) { } virtual void giveInputRecord(DynamicInputRecord &input) { OOFEM_ERROR("not implemented"); } /// Gives class name. virtual const char *giveClassName() const { return NULL; } @@ -144,26 +144,22 @@ class OOFEM_EXPORT BasicGeometry //: public Geometry int giveNrVertices() const { return (int)mVertices.size(); } virtual bool isOutside(BasicGeometry *bg) { return false; } virtual bool isInside(Element *el) { return false; } - virtual bool isInside(FloatArray &point) { return false; } + virtual bool isInside(const FloatArray &point) { return false; } virtual void printYourself() { } /** * Stores the state of receiver to output stream. * @param stream Context stream. * @param mode Determines amount of info in stream. - * @param obj Special parameter, used to pass optional parameters. - * @return contextIOResultType. * @exception ContextIOERR If error encountered. */ - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL) { return CIO_OK; } + virtual void saveContext(DataStream &stream, ContextMode mode) { } /** * Restores the state of receiver from output stream. * @param stream Context file. * @param mode Determines amount of info in stream. - * @param obj Special parameter for sending extra information. - * @return contextIOResultType. * @exception ContextIOERR exception if error encountered. */ - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL) { return CIO_OK; } + virtual void restoreContext(DataStream &stream, ContextMode mode) { } #ifdef __OOFEG virtual void draw(oofegGraphicContext &gc) { } @@ -193,29 +189,29 @@ class OOFEM_EXPORT Line : public BasicGeometry virtual ~Line() { } Line(const FloatArray &iPointA, const FloatArray &iPointB); - virtual BasicGeometry *Clone() { return new Line(*this); } + BasicGeometry *Clone() override { return new Line(*this); } - virtual double computeDistanceTo(const FloatArray *point); + double computeDistanceTo(const FloatArray &point) override; /// Computes tangential distance to a point - virtual void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const { OOFEM_ERROR("not implemented"); } + void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const override { OOFEM_ERROR("not implemented"); } - double computeTangentialDistanceToEnd(FloatArray *point); + double computeTangentialDistanceToEnd(const FloatArray &point); - virtual void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const; + void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const override; void computeProjection(FloatArray &answer); - virtual int computeNumberOfIntersectionPoints(Element *element); - virtual void computeIntersectionPoints(Element *element, std :: vector< FloatArray > &oIntersectionPoints); + int computeNumberOfIntersectionPoints(Element *element) override; + void computeIntersectionPoints(Element *element, std :: vector< FloatArray > &oIntersectionPoints) override; double computeInclinationAngle(); void computeTransformationMatrix(FloatMatrix &answer); void transformIntoPolar(FloatArray *point, FloatArray &answer); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; bool isPointInside(FloatArray *point); - virtual bool intersects(Element *element); - virtual bool isOutside(BasicGeometry *bg); + bool intersects(Element *element) override; + bool isOutside(BasicGeometry *bg) override; - double giveLength() const {return mVertices[0].distance( mVertices[1] );} + double giveLength() const { return distance( mVertices[0], mVertices[1] ); } }; class OOFEM_EXPORT Triangle : public BasicGeometry @@ -224,17 +220,19 @@ class OOFEM_EXPORT Triangle : public BasicGeometry Triangle(const FloatArray & iP1, const FloatArray & iP2, const FloatArray & iP3); virtual ~Triangle() { } - virtual BasicGeometry *Clone() { return new Triangle(*this); } + BasicGeometry *Clone() override { return new Triangle(*this); } - virtual void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const { OOFEM_ERROR("not implemented"); } - virtual void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const { OOFEM_ERROR("not implemented"); } + void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const override + { OOFEM_ERROR("not implemented"); } + void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const override + { OOFEM_ERROR("not implemented"); } double getArea(); void computeBarycentrCoor(FloatArray &answer) const; double getRadiusOfCircumCircle(); void computeCenterOfCircumCircle(FloatArray &answer) const; - virtual void printYourself(); - virtual int computeNumberOfIntersectionPoints(Element *element) { return 0; } + void printYourself() override; + int computeNumberOfIntersectionPoints(Element *element) override { return 0; } bool isOrientedAnticlockwise(); void changeToAnticlockwise(); @@ -261,33 +259,33 @@ class OOFEM_EXPORT Circle : public BasicGeometry virtual ~Circle() { } Circle(FloatArray ¢er, double radius); - virtual BasicGeometry *Clone() { return new Circle(*this); } + BasicGeometry *Clone() override { return new Circle(*this); } - virtual void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const; + void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const override; // Irrelevant for a closed interface: we can always consider ourselves to be "inside" a closed interface in // tangential direction. Therefore, we may return any positive number. - virtual void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const { oDist = mTangSignDist; } + void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const override + { oDist = mTangSignDist; } - virtual void giveGlobalCoordinates(FloatArray &oGlobalCoord, const double &iArcPos) const; + void giveGlobalCoordinates(FloatArray &oGlobalCoord, const double &iArcPos) const override; - virtual void giveTangent(FloatArray &oTangent, const double &iArcPosition) const { } + void giveTangent(FloatArray &oTangent, const double &iArcPosition) const override { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "Circle"; } - virtual bool intersects(Element *element); - virtual void computeIntersectionPoints(Element *element, std :: vector< FloatArray > &oIntersectionPoints); - virtual void computeIntersectionPoints(Line *l, std :: vector< FloatArray > &oIntersectionPoints); - virtual int computeNumberOfIntersectionPoints(Element *element); - virtual bool isOutside(BasicGeometry *bg); - virtual bool isInside(Element *element); - virtual bool isInside(FloatArray &point); - virtual void printYourself(); + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "Circle"; } + bool intersects(Element *element) override; + void computeIntersectionPoints(Element *element, std :: vector< FloatArray > &oIntersectionPoints) override; + void computeIntersectionPoints(Line *l, std :: vector< FloatArray > &oIntersectionPoints); + int computeNumberOfIntersectionPoints(Element *element) override; + bool isOutside(BasicGeometry *bg) override; + bool isInside(Element *element) override; + bool isInside(const FloatArray &point) override; + void printYourself() override; double giveRadius() const {return radius;} - virtual void giveBoundingSphere(FloatArray &oCenter, double &oRadius); - + void giveBoundingSphere(FloatArray &oCenter, double &oRadius) override; }; class OOFEM_EXPORT PolygonLine : public BasicGeometry @@ -297,56 +295,56 @@ class OOFEM_EXPORT PolygonLine : public BasicGeometry PolygonLine(); virtual ~PolygonLine() { } - virtual BasicGeometry *Clone() { return new PolygonLine(*this); } + BasicGeometry *Clone() override { return new PolygonLine(*this); } - virtual void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const; - virtual void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const; + void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const override; + void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const override; /// Computes arc length coordinate in the range [0,1] - virtual void computeLocalCoordinates(FloatArray &oLocCoord, const FloatArray &iPoint) const; + void computeLocalCoordinates(FloatArray &oLocCoord, const FloatArray &iPoint) const override; double computeLength() const; - virtual void giveSubPolygon(std :: vector< FloatArray > &oPoints, const double &iXiStart, const double &iXiEnd) const; - virtual void giveGlobalCoordinates(FloatArray &oGlobalCoord, const double &iArcPos) const; + void giveSubPolygon(std :: vector< FloatArray > &oPoints, const double &iXiStart, const double &iXiEnd) const override; + void giveGlobalCoordinates(FloatArray &oGlobalCoord, const double &iArcPos) const override; void giveNormal(FloatArray &oNormal, const double &iArcPosition) const; - virtual void giveTangent(FloatArray &oTangent, const double &iArcPosition) const; + void giveTangent(FloatArray &oTangent, const double &iArcPosition) const override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveClassName() const { return "PolygonLine"; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveClassName() const override { return "PolygonLine"; } #ifdef __BOOST_MODULE - virtual bool boundingBoxIntersects(Element *element); + bool boundingBoxIntersects(Element *element); #endif - virtual bool intersects(Element *element); - virtual void computeIntersectionPoints(Element *element, std :: vector< FloatArray > &oIntersectionPoints); - virtual void computeIntersectionPoints(Line *l, std :: vector< FloatArray > &oIntersectionPoints); + bool intersects(Element *element) override; + void computeIntersectionPoints(Element *element, std :: vector< FloatArray > &oIntersectionPoints) override; + void computeIntersectionPoints(Line *l, std :: vector< FloatArray > &oIntersectionPoints); void computeIntersectionPoints(const PolygonLine &iPolygonLine, std :: vector< FloatArray > &oIntersectionPoints) const; void computeIntersectionPoints(const FloatArray &iXStart, const FloatArray &iXEnd, std :: vector< FloatArray > &oIntersectionPoints) const; - virtual int computeNumberOfIntersectionPoints(Element *element); - virtual bool isOutside(BasicGeometry *bg); - virtual bool isInside(Element *element); - virtual bool isInside(FloatArray &point); + int computeNumberOfIntersectionPoints(Element *element) override; + bool isOutside(BasicGeometry *bg) override; + bool isInside(Element *element) override; + bool isInside(const FloatArray &point) override; #ifdef __BOOST_MODULE virtual void calcBoundingBox(bPoint2 &oLC, bPoint2 &oUC); #endif - virtual void printYourself(); + void printYourself() override; // For debugging - virtual void printVTK(int iTStepIndex, int iLineIndex); + void printVTK(int iTStepIndex, int iLineIndex) override; #ifdef __BOOST_MODULE // Upper and lower corner bPoint2 LC, UC; #endif - virtual bool giveTips(TipInfo &oStartTipInfo, TipInfo &oEndTipInfo) const; + bool giveTips(TipInfo &oStartTipInfo, TipInfo &oEndTipInfo) const override; - virtual void giveBoundingSphere(FloatArray &oCenter, double &oRadius); + void giveBoundingSphere(FloatArray &oCenter, double &oRadius) override; /** * Keep only a part of the underlying geometry, @@ -366,21 +364,25 @@ class OOFEM_EXPORT PointSwarm : public BasicGeometry virtual ~PointSwarm() { } PointSwarm(std :: list< int >pointsID); - virtual BasicGeometry *Clone() { return new PointSwarm(*this); } + BasicGeometry *Clone() override { return new PointSwarm(*this); } - virtual void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const { OOFEM_ERROR("not implemented"); } - virtual void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const { OOFEM_ERROR("not implemented"); } + void computeNormalSignDist(double &oDist, const FloatArray &iPoint) const override + { OOFEM_ERROR("not implemented"); } + void computeTangentialSignDist(double &oDist, const FloatArray &iPoint, double &oMinDistArcPos) const override + { OOFEM_ERROR("not implemented"); } /// Computes the normal distance to the surface not to the center. - // virtual double computeDistanceTo(FloatArray *point); - virtual IRResultType initializeFrom(InputRecord *ir); - // virtual const char *giveClassName() const { return "Circle"; } - // virtual bool intersects(Element *element); - // virtual void computeIntersectionPoints(Element *element, std :: vector< FloatArray > *intersecPoints); - // virtual void computeIntersectionPoints(Line *l, std :: vector< FloatArray > *intersecPoints); - // virtual bool isOutside(BasicGeometry *bg); - // virtual bool isInside(Element *element); - // virtual bool isInside(FloatArray &point); + void initializeFrom(InputRecord &ir) override; +#if 0 + double computeDistanceTo(FloatArray &point) override; + const char *giveClassName() const override { return "Circle"; } + bool intersects(Element *element) override; + void computeIntersectionPoints(Element *element, std :: vector< FloatArray > *intersecPoints) override; + void computeIntersectionPoints(Line *l, std :: vector< FloatArray > *intersecPoints) override; + bool isOutside(BasicGeometry *bg) override; + bool isInside(Element *element) override; + bool isInside(const FloatArray &point) override; +#endif }; } // end namespace oofem #endif // geometry_h diff --git a/src/oofemlib/gjacobi.h b/src/oofemlib/gjacobi.h index d8a63513f..18f17f378 100644 --- a/src/oofemlib/gjacobi.h +++ b/src/oofemlib/gjacobi.h @@ -68,9 +68,9 @@ class OOFEM_EXPORT GJacobi : public NumericalMethod * @param w Eigenvalue(s). * @return Status. */ - virtual NM_Status solve(FloatMatrix &K, FloatMatrix &M, FloatArray &w, FloatMatrix &x); + NM_Status solve(FloatMatrix &K, FloatMatrix &M, FloatArray &w, FloatMatrix &x); - virtual const char *giveClassName() const { return "GeneralizedJacobiSolver"; } + const char *giveClassName() const { return "GeneralizedJacobiSolver"; } std :: string errorInfo(const char *func) { return std :: string(this->giveClassName()) + func; } }; } // end namespace oofem diff --git a/src/oofemlib/gpexportmodule.C b/src/oofemlib/gpexportmodule.C index 538893999..b56db20de 100644 --- a/src/oofemlib/gpexportmodule.C +++ b/src/oofemlib/gpexportmodule.C @@ -54,14 +54,12 @@ GPExportModule :: ~GPExportModule() { } -IRResultType -GPExportModule :: initializeFrom(InputRecord *ir) +void +GPExportModule :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - + ExportModule :: initializeFrom(ir); IR_GIVE_FIELD(ir, vartypes, _IFT_GPExportModule_vartypes); IR_GIVE_OPTIONAL_FIELD(ir, ncoords, _IFT_GPExportModule_ncoords); - return ExportModule :: initializeFrom(ir); } @@ -88,73 +86,80 @@ GPExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) } fprintf(stream, "\n %%# for interpretation see internalstatetype.h\n"); - + + elements.resize(0); + for ( int ireg = 1; ireg <= this->giveNumberOfRegions(); ireg++ ) { + elements.followedBy(this->giveRegionSet(ireg)->giveElementList()); + } + // loop over elements for ( auto &elem : d->giveElements() ) { - //iRule = elem->giveDefaultIntegrationRulePtr(); - //int numIntRules = elem->giveNumberOfIntegrationRules(); - for ( int i = 0; i < elem->giveNumberOfIntegrationRules(); i++ ) { - IntegrationRule *iRule = elem->giveIntegrationRule(i); - - // loop over Gauss points - for ( GaussPoint *gp: *iRule ) { - // export: - // 1) element number - // 2) material number ///@todo deprecated returns -1 - // 3) Integration rule number - // 4) Gauss point number - // 5) contributing volume around Gauss point - weight = elem->computeVolumeAround(gp); - fprintf(stream, "%d %d %d %d %.6e ", elem->giveNumber(), -1, i + 1, gp->giveNumber(), weight); - - // export Gauss point coordinates - if ( ncoords ) { // no coordinates exported if ncoords==0 - elem->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); - int nc = gcoords.giveSize(); - if ( ncoords >= 0 ) { - fprintf(stream, "%d ", ncoords); - } else { - fprintf(stream, "%d ", nc); - } - - if ( ncoords > 0 && ncoords < nc ) { - nc = ncoords; - } - - for ( auto &c : gcoords ) { - fprintf( stream, "%.6e ", c ); + if ( elements.contains(elem -> giveNumber()) ){ + + //iRule = elem->giveDefaultIntegrationRulePtr(); + //int numIntRules = elem->giveNumberOfIntegrationRules(); + for ( int i = 0; i < elem->giveNumberOfIntegrationRules(); i++ ) { + IntegrationRule *iRule = elem->giveIntegrationRule(i); + + // loop over Gauss points + for ( GaussPoint *gp: *iRule ) { + // export: + // 1) element number + // 2) material number ///@todo deprecated returns -1 + // 3) Integration rule number + // 4) Gauss point number + // 5) contributing volume around Gauss point + weight = elem->computeVolumeAround(gp); + fprintf(stream, "%d %d %d %d %.6e ", elem->giveNumber(), -1, i + 1, gp->giveNumber(), weight); + + // export Gauss point coordinates + if ( ncoords ) { // no coordinates exported if ncoords==0 + elem->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); + int nc = gcoords.giveSize(); + if ( ncoords >= 0 ) { + fprintf(stream, "%d ", ncoords); + } else { + fprintf(stream, "%d ", nc); + } + + if ( ncoords > 0 && ncoords < nc ) { + nc = ncoords; + } + + for ( auto &c : gcoords ) { + fprintf( stream, "%.6e ", c ); + } + + for ( int ic = nc + 1; ic <= ncoords; ic++ ) { + fprintf(stream, "%g ", 0.0); + } } - for ( int ic = nc + 1; ic <= ncoords; ic++ ) { - fprintf(stream, "%g ", 0.0); + // export internal variables + for ( auto vartype : vartypes ) { + elem->giveIPValue(intvar, gp, ( InternalStateType )vartype, tStep); + fprintf(stream, "%d ", intvar.giveSize()); + for ( auto &val : intvar ) { + fprintf( stream, "%.6e ", val ); + } } - } - // export internal variables - for ( auto vartype : vartypes ) { - elem->giveIPValue(intvar, gp, ( InternalStateType )vartype, tStep); - fprintf(stream, "%d ", intvar.giveSize()); - for ( auto &val : intvar ) { - fprintf( stream, "%.6e ", val ); - } + fprintf(stream, "\n"); } - - fprintf(stream, "\n"); } - } -#if 0 - // for CST elements write also nodal coordinates - // (non-standard part, used only exceptionally) - int nnode = elem->giveNumberOfNodes(); - if ( nnode == 3 ) { - for ( int inod = 1; inod <= 3; inod++ ) { - fprintf( stream, "%f %f ", elem->giveNode(inod)->giveCoordinate(1), elem->giveNode(inod)->giveCoordinate(2) ); + #if 0 + // for CST elements write also nodal coordinates + // (non-standard part, used only exceptionally) + int nnode = elem->giveNumberOfNodes(); + if ( nnode == 3 ) { + for ( int inod = 1; inod <= 3; inod++ ) { + fprintf( stream, "%f %f ", elem->giveNode(inod)->giveCoordinate(1), elem->giveNode(inod)->giveCoordinate(2) ); + } } - } #endif + } } - fclose(stream); } diff --git a/src/oofemlib/gpexportmodule.h b/src/oofemlib/gpexportmodule.h index cb46e7493..2ae5da3d6 100644 --- a/src/oofemlib/gpexportmodule.h +++ b/src/oofemlib/gpexportmodule.h @@ -61,6 +61,8 @@ class OOFEM_EXPORT GPExportModule : public ExportModule IntArray vartypes; /// Number of coordinates to be exported (at each Gauss point) int ncoords; + /// List of elements + IntArray elements; public: /// Constructor. Creates empty Output Manager. By default all components are selected. @@ -68,12 +70,12 @@ class OOFEM_EXPORT GPExportModule : public ExportModule /// Destructor virtual ~GPExportModule(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void doOutput(TimeStep *tStep, bool forcedOutput = false); - virtual void initialize(); - virtual void terminate(); - virtual const char *giveClassName() const { return "GPExportModule"; } - virtual const char *giveInputRecordName() const { return _IFT_GPExportModule_Name; } + void initializeFrom(InputRecord &ir) override; + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; + void initialize() override; + void terminate() override; + const char *giveClassName() const override { return "GPExportModule"; } + const char *giveInputRecordName() const { return _IFT_GPExportModule_Name; } protected: /// Returns the output stream for given solution step diff --git a/src/oofemlib/grid.C b/src/oofemlib/grid.C index 4ad0a4711..0e13acd1d 100644 --- a/src/oofemlib/grid.C +++ b/src/oofemlib/grid.C @@ -5,8 +5,6 @@ #include namespace oofem { -#define MIN(a, b) ( ( a ) > ( b ) ? ( b ) : ( a ) ) -#define MAX(a, b) ( ( a ) > ( b ) ? ( a ) : ( b ) ) // NB: When using matrix indices (i,j), they run from 1 to (m,n). // When using 1-dim array index 'ind', it runs from 0 to (m*n-1). @@ -43,13 +41,12 @@ int jcalcOffsets[] = { }; -Grid :: Grid(int N, int M) +Grid :: Grid(int N, int M) : + n(N), m(M), + T(m, n), + F(m, n) { - n = N; - m = M; solutionAvailable = false; - T = new FloatMatrix(m, n); - F = new FloatMatrix(m, n); // (calloc sets all bits of the allocated memory to zero, so the initial values are "false") Frozen = ( bool * ) calloc( m * n, sizeof( bool ) ); @@ -58,8 +55,6 @@ Grid :: Grid(int N, int M) Grid :: ~Grid() { - delete T; - delete F; if ( Frozen ) { free(Frozen); } @@ -135,53 +130,53 @@ Grid :: setZeroValues(FloatMatrix *gridCoords) int CPInd = ij2ind(i, j, m); // Calculate time-distance of nearest grid node and freeze the value - double Fij = F->at(i, j); - T->at(i, j) = sqrt( ( i - CPy ) * ( i - CPy ) + ( j - CPx ) * ( j - CPx ) ) / Fij; + double Fij = F.at(i, j); + T.at(i, j) = sqrt( ( i - CPy ) * ( i - CPy ) + ( j - CPx ) * ( j - CPx ) ) / Fij; Frozen [ CPInd ] = true; // For four direct neighbors or all eight neighbours of the nearest grid node, do the same // (depending on parameter initDiag) - int nInd, ni, nj; - double time; if ( initDiag <= 0. ) { // initialize direct neighbors only for ( int neigh = 0; neigh < 4; neigh++ ) { - ni = i + iOffsets [ neigh ]; - nj = j + jOffsets [ neigh ]; + int ni = i + iOffsets [ neigh ]; + int nj = j + jOffsets [ neigh ]; if ( isInDomain(ni, nj, m, n) ) { - nInd = ij2ind(ni, nj, m); + int nInd = ij2ind(ni, nj, m); + double time; if ( centDiff > 0 ) { // use the average speed - time = sqrt( ( ni - CPy ) * ( ni - CPy ) + ( nj - CPx ) * ( nj - CPx ) ) / ( 0.5 * ( Fij + F->at(ni, nj) ) ); + time = sqrt( ( ni - CPy ) * ( ni - CPy ) + ( nj - CPx ) * ( nj - CPx ) ) / ( 0.5 * ( Fij + F.at(ni, nj) ) ); } else { // use the speed at the arrival point - time = sqrt( ( ni - CPy ) * ( ni - CPy ) + ( nj - CPx ) * ( nj - CPx ) ) / F->at(ni, nj); + time = sqrt( ( ni - CPy ) * ( ni - CPy ) + ( nj - CPx ) * ( nj - CPx ) ) / F.at(ni, nj); } if ( Frozen [ nInd ] ) { - T->at(ni, nj) = MIN( time, T->at(ni, nj) ); + T.at(ni, nj) = std::min( time, T.at(ni, nj) ); } else { - T->at(ni, nj) = time; + T.at(ni, nj) = time; Frozen [ nInd ] = true; } } } } else { // initialize all neighbors for ( int neigh = 0; neigh < 8; neigh++ ) { - ni = i + iOffsets_full [ neigh ]; - nj = j + jOffsets_full [ neigh ]; + int ni = i + iOffsets_full [ neigh ]; + int nj = j + jOffsets_full [ neigh ]; if ( isInDomain(ni, nj, m, n) ) { - nInd = ij2ind(ni, nj, m); + int nInd = ij2ind(ni, nj, m); + double time; if ( centDiff > 0 ) { // use the average speed - time = sqrt( ( ni - CPy ) * ( ni - CPy ) + ( nj - CPx ) * ( nj - CPx ) ) / ( 0.5 * ( Fij + F->at(ni, nj) ) ); + time = sqrt( ( ni - CPy ) * ( ni - CPy ) + ( nj - CPx ) * ( nj - CPx ) ) / ( 0.5 * ( Fij + F.at(ni, nj) ) ); } else { // use the speed at the arrival point - time = sqrt( ( ni - CPy ) * ( ni - CPy ) + ( nj - CPx ) * ( nj - CPx ) ) / F->at(ni, nj); + time = sqrt( ( ni - CPy ) * ( ni - CPy ) + ( nj - CPx ) * ( nj - CPx ) ) / F.at(ni, nj); } // for diagonal neighbors, use initDiag as a scaling factor if ( is_diag [ neigh ] ) { time *= initDiag; } if ( Frozen [ nInd ] ) { - T->at(ni, nj) = MIN( time, T->at(ni, nj) ); + T.at(ni, nj) = std::min( time, T.at(ni, nj) ); } else { - T->at(ni, nj) = time; + T.at(ni, nj) = time; Frozen [ nInd ] = true; } } @@ -195,7 +190,7 @@ Grid :: setZeroValues(FloatMatrix *gridCoords) void Grid :: setSolutionValueAt(int i, int j, double value) { - T->at(i, j) = value; + T.at(i, j) = value; // after each external change, the solution becomes invalid solutionAvailable = false; } @@ -209,7 +204,7 @@ Grid :: giveSolutionValueAt(int i, int j) // TBD: one should check eFlag and send an error message if it is > 0 solutionAvailable = true; } - return T->at(i, j); + return T.at(i, j); } void @@ -218,7 +213,7 @@ Grid :: printSolutionAsData() for ( int j = 1; j <= n; j++ ) { printf("\n"); for ( int i = 1; i <= m; i++ ) { - printf( "%d %d %g\n", j, i, T->at(i, j) ); + printf( "%d %d %g\n", j, i, T.at(i, j) ); } } } @@ -227,9 +222,6 @@ Grid :: printSolutionAsData() void Grid :: fastMarch(int &eFlag) { - double time; - int i, j, ni, nj, nInd; - int tmpFlag = 0; eFlag = 0; // Create the initial narrow band @@ -240,17 +232,18 @@ Grid :: fastMarch(int &eFlag) // Loop over all grid points (not efficient, but done only once) for ( int ind = 0; ind < ( m * n ); ind++ ) { if ( Frozen [ ind ] ) { - i = ind2i(ind, m); - j = ind2j(ind, m); + int i = ind2i(ind, m); + int j = ind2j(ind, m); for ( int neigh = 0; neigh < 4; neigh++ ) { - ni = i + iOffsets [ neigh ]; - nj = j + jOffsets [ neigh ]; - nInd = ij2ind(ni, nj, m); + int ni = i + iOffsets [ neigh ]; + int nj = j + jOffsets [ neigh ]; + int nInd = ij2ind(ni, nj, m); if ( isInDomain(ni, nj, m, n) && !Frozen [ nInd ] ) { if ( !narrowBand->isInHeap(nInd) ) { - time = calcTime(ni, nj, F->at(ni, nj), order, tmpFlag); + int tmpFlag = 0; + double time = calcTime(ni, nj, F.at(ni, nj), order, tmpFlag); narrowBand->insert(time, nInd); if ( tmpFlag > eFlag ) { eFlag = tmpFlag; @@ -265,23 +258,24 @@ Grid :: fastMarch(int &eFlag) int CPInd; while ( narrowBand->nElems() > 0 ) { // Get minimal time-distance and index of this narrow-band element - time = narrowBand->getSmallest(& CPInd); - i = ind2i(CPInd, m); - j = ind2j(CPInd, m); + double time = narrowBand->getSmallest(& CPInd); + int i = ind2i(CPInd, m); + int j = ind2j(CPInd, m); // Freeze and set time Frozen [ CPInd ] = true; - T->at(i, j) = time; + T.at(i, j) = time; // For all neighbours for ( int neigh = 0; neigh < 4; neigh++ ) { - ni = i + iOffsets [ neigh ]; - nj = j + jOffsets [ neigh ]; - nInd = ij2ind(ni, nj, m); + int ni = i + iOffsets [ neigh ]; + int nj = j + jOffsets [ neigh ]; + int nInd = ij2ind(ni, nj, m); // If valid for consideration if ( isInDomain(ni, nj, m, n) && !Frozen [ nInd ] ) { - time = calcTime(ni, nj, F->at(ni, nj), order, tmpFlag); + int tmpFlag; + double time = calcTime(ni, nj, F.at(ni, nj), order, tmpFlag); // If T(ni,nj) has not been previously calculated if ( !narrowBand->isInHeap(nInd) ) { narrowBand->insert(time, nInd); @@ -300,7 +294,8 @@ Grid :: fastMarch(int &eFlag) // Time-dist calculation (for a grid with unit spacing) double -Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { +Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) +{ // Get infinity. // NB: Is this good practice? As in the matlab code, using Inf as // a flag simplifies the code, so that's why I use this. Maybe this @@ -320,19 +315,16 @@ Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { // time calculated double time; - // Indices of neighbouring nodes - int ni, nj, nInd; - // Variables used in the final formula double xmin1 = 0., xmin2, ymin1 = 0., ymin2; // Get values at surrounding nodes (at those that are frozen) for ( int iter = 0; iter < 8; iter++ ) { - ni = i + icalcOffsets [ iter ]; - nj = j + jcalcOffsets [ iter ]; - nInd = ij2ind(ni, nj, m); + int ni = i + icalcOffsets [ iter ]; + int nj = j + jcalcOffsets [ iter ]; + int nInd = ij2ind(ni, nj, m); if ( isInDomain(ni, nj, m, n) && Frozen [ nInd ] ) { - CrossVals [ iter ] = T->at(ni, nj); + CrossVals [ iter ] = T.at(ni, nj); } else { CrossVals [ iter ] = Inf; } @@ -342,7 +334,7 @@ Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { if ( ( CrossVals [ 1 ] == Inf ) && ( CrossVals [ 2 ] == Inf ) && ( CrossVals [ 5 ] == Inf ) && ( CrossVals [ 6 ] == Inf ) ) { eFlag = 0; - time = Inf; + double time = Inf; return time; } @@ -357,11 +349,12 @@ Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { case 1: // Contribution of y-direction if ( !( ( CrossVals [ 1 ] == Inf ) && ( CrossVals [ 2 ] == Inf ) ) ) { - ymin1 = MIN(CrossVals [ 1 ], CrossVals [ 2 ]); + ymin1 = std::min(CrossVals [ 1 ], CrossVals [ 2 ]); a += 1.; b -= 2. * ymin1; c += ymin1 * ymin1; //mj + int ni, nj; if ( CrossVals [ 1 ] < CrossVals [ 2 ] ) { ni = i + icalcOffsets [ 1 ]; nj = j + jcalcOffsets [ 1 ]; @@ -369,17 +362,18 @@ Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { ni = i + icalcOffsets [ 2 ]; nj = j + jcalcOffsets [ 2 ]; } - Fy = F->at(ni, nj); + Fy = F.at(ni, nj); //end mj } // Contribution of x-direction if ( !( ( CrossVals [ 5 ] == Inf ) && ( CrossVals [ 6 ] == Inf ) ) ) { - xmin1 = MIN(CrossVals [ 5 ], CrossVals [ 6 ]); + xmin1 = std::min(CrossVals [ 5 ], CrossVals [ 6 ]); a += 1.; b -= 2. * xmin1; c += xmin1 * xmin1; //mj + int ni, nj; if ( CrossVals [ 5 ] < CrossVals [ 6 ] ) { ni = i + icalcOffsets [ 5 ]; nj = j + jcalcOffsets [ 5 ]; @@ -387,7 +381,7 @@ Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { ni = i + icalcOffsets [ 6 ]; nj = j + jcalcOffsets [ 6 ]; } - Fx = F->at(ni, nj); + Fx = F.at(ni, nj); //end mj } break; @@ -400,9 +394,9 @@ Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { if ( CrossVals [ 1 ] < CrossVals [ 2 ] ) { ymin1 = CrossVals [ 1 ]; //mj - ni = i + icalcOffsets [ 1 ]; - nj = j + jcalcOffsets [ 1 ]; - Fy = F->at(ni, nj); + int ni = i + icalcOffsets [ 1 ]; + int nj = j + jcalcOffsets [ 1 ]; + Fy = F.at(ni, nj); //end mj if ( CrossVals [ 0 ] <= CrossVals [ 1 ] ) { //second-order formula can be applied ymin2 = CrossVals [ 0 ]; @@ -417,9 +411,9 @@ Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { } else { ymin1 = CrossVals [ 2 ]; //mj - ni = i + icalcOffsets [ 2 ]; - nj = j + jcalcOffsets [ 2 ]; - Fy = F->at(ni, nj); + int ni = i + icalcOffsets [ 2 ]; + int nj = j + jcalcOffsets [ 2 ]; + Fy = F.at(ni, nj); //end mj if ( CrossVals [ 3 ] <= CrossVals [ 2 ] ) { //second-order formula can be applied ymin2 = CrossVals [ 3 ]; @@ -438,9 +432,9 @@ Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { if ( CrossVals [ 5 ] < CrossVals [ 6 ] ) { xmin1 = CrossVals [ 5 ]; //mj - ni = i + icalcOffsets [ 5 ]; - nj = j + jcalcOffsets [ 5 ]; - Fx = F->at(ni, nj); + int ni = i + icalcOffsets [ 5 ]; + int nj = j + jcalcOffsets [ 5 ]; + Fx = F.at(ni, nj); //end mj if ( CrossVals [ 4 ] <= CrossVals [ 5 ] ) { //second-order formula can be applied xmin2 = CrossVals [ 4 ]; @@ -455,9 +449,9 @@ Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { } else { xmin1 = CrossVals [ 6 ]; //mj - ni = i + icalcOffsets [ 6 ]; - nj = j + jcalcOffsets [ 6 ]; - Fx = F->at(ni, nj); + int ni = i + icalcOffsets [ 6 ]; + int nj = j + jcalcOffsets [ 6 ]; + Fx = F.at(ni, nj); //end mj if ( CrossVals [ 7 ] <= CrossVals [ 6 ] ) { //second-order formula can be applied xmin2 = CrossVals [ 7 ]; @@ -496,7 +490,7 @@ Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { if ( ( d < 0.0 ) && ( ord == 2 ) ) { // if second-order method did not work, try first-order formula time = calcTime(i, j, Fij, 1, tmpFlag); - eFlag = MAX(1, tmpFlag); + eFlag = std::max(1, tmpFlag); } else if ( ( d < 0.0 ) && ( ord == 1 ) ) { if ( ( CrossVals [ 1 ] == Inf ) && ( CrossVals [ 2 ] == Inf ) ) { ymin1 = Inf; @@ -506,7 +500,7 @@ Grid :: calcTime(int i, int j, double Fij, int ord, int &eFlag) { } eFlag = 2; - time = MIN(xmin1, ymin1) + 1.0 / Fij; + time = std::min(xmin1, ymin1) + 1.0 / Fij; } else { eFlag = 0; time = ( -b + sqrt(d) ) / ( 2.0 * a ); diff --git a/src/oofemlib/grid.h b/src/oofemlib/grid.h index 5573836f5..c0229a360 100644 --- a/src/oofemlib/grid.h +++ b/src/oofemlib/grid.h @@ -50,8 +50,8 @@ class Grid /// Method setting the values of the prescribed field (e.g., front velocities) //void setPrescribedField(double *PF); - void setPrescribedFieldValue(int i, int j, double val) { F->at(i, j) = val; } - FloatMatrix *givePrescribedField() { return F; } + void setPrescribedFieldValue(int i, int j, double val) { F.at(i, j) = val; } + FloatMatrix &givePrescribedField() { return F; } /// Methods setting the values of the unknown field at selected points (e.g., zero times) void setZeroValues(FloatMatrix *gridCoords); @@ -75,10 +75,10 @@ class Grid bool solutionAvailable; /// Matrix storing the values of the unknown (computed) field (e.g., arrival times) - FloatMatrix *T; + FloatMatrix T; /// Matrix storing the values of the prescribed field (e.g., front velocities) - FloatMatrix *F; + FloatMatrix F; /// Array storing indicators of frozen points (at which the solution is already known) bool *Frozen; diff --git a/src/oofemlib/hangingnode.C b/src/oofemlib/hangingnode.C index 7aa4f30f0..4b0062780 100644 --- a/src/oofemlib/hangingnode.C +++ b/src/oofemlib/hangingnode.C @@ -51,20 +51,22 @@ HangingNode :: HangingNode(int n, Domain *aDomain) : Node(n, aDomain) #endif } -IRResultType HangingNode :: initializeFrom(InputRecord *ir) +void HangingNode :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - + Node :: initializeFrom(ir); this->masterElement = -1; IR_GIVE_OPTIONAL_FIELD(ir, this->masterElement, _IFT_HangingNode_masterElement); this->masterRegion = 0; IR_GIVE_OPTIONAL_FIELD(ir, this->masterRegion, _IFT_HangingNode_masterRegion); - return Node :: initializeFrom(ir); } int HangingNode :: checkConsistency() { - Element *e = this->domain->giveElement(this->masterElement); + if (this->masterElement !=-1){ + return true; + } + + Element *e = this->domain->giveGlobalElement(this->masterElement); int result = Node :: checkConsistency(); #if 0 @@ -115,7 +117,10 @@ void HangingNode :: postInitialize() OOFEM_ERROR("Couldn't find closest element (automatically)."); } this->masterElement = e->giveNumber(); - } else if ( !( e = this->giveDomain()->giveElement(this->masterElement) ) ) { + # ifdef DEBUG + OOFEM_LOG_INFO("Found element %d for hanging node %d\n", e->giveGlobalNumber(), this->giveNumber() ); + #endif + } else if ( !( e = this->giveDomain()->giveGlobalElement(this->masterElement) ) ) { OOFEM_ERROR("Requested element %d doesn't exist.", this->masterElement); } if ( !( fei = e->giveInterpolation() ) ) { diff --git a/src/oofemlib/hangingnode.h b/src/oofemlib/hangingnode.h index d5c1f6e48..2121c1ad9 100644 --- a/src/oofemlib/hangingnode.h +++ b/src/oofemlib/hangingnode.h @@ -83,13 +83,13 @@ class OOFEM_EXPORT HangingNode : public Node /// Destructor. virtual ~HangingNode(void) { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void postInitialize(); - virtual int checkConsistency(); - virtual bool isDofTypeCompatible(dofType type) const { return ( type == DT_master || type == DT_slave ); } + void initializeFrom(InputRecord &ir) override; + void postInitialize() override; + int checkConsistency() override; + bool isDofTypeCompatible(dofType type) const override { return ( type == DT_master || type == DT_slave ); } - virtual const char *giveClassName() const { return "HangingNode"; } - virtual const char *giveInputRecordName() const { return _IFT_HangingNode_Name; } + const char *giveClassName() const override { return "HangingNode"; } + const char *giveInputRecordName() const override { return _IFT_HangingNode_Name; } }; } // end namespace oofem #endif // hangingnode_h diff --git a/src/oofemlib/heavisidetimefunction.C b/src/oofemlib/heavisidetimefunction.C index 133032d48..8ed099206 100644 --- a/src/oofemlib/heavisidetimefunction.C +++ b/src/oofemlib/heavisidetimefunction.C @@ -51,15 +51,13 @@ HeavisideTimeFunction :: evaluateAtTime(double time) } -IRResultType -HeavisideTimeFunction :: initializeFrom(InputRecord *ir) +void +HeavisideTimeFunction :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Function :: initializeFrom(ir); IR_GIVE_FIELD(ir, origin, _IFT_HeavisideTimeFunction_origin); IR_GIVE_FIELD(ir, value, _IFT_HeavisideTimeFunction_value); - - return Function :: initializeFrom(ir); } diff --git a/src/oofemlib/heavisidetimefunction.h b/src/oofemlib/heavisidetimefunction.h index 81d429594..6506d9ce3 100644 --- a/src/oofemlib/heavisidetimefunction.h +++ b/src/oofemlib/heavisidetimefunction.h @@ -68,14 +68,14 @@ class OOFEM_EXPORT HeavisideTimeFunction : public Function } virtual ~HeavisideTimeFunction() { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveClassName() const { return "HeavisideTimeFunction"; } - virtual const char *giveInputRecordName() const { return _IFT_HeavisideTimeFunction_Name; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveClassName() const override { return "HeavisideTimeFunction"; } + const char *giveInputRecordName() const override { return _IFT_HeavisideTimeFunction_Name; } - virtual double evaluateAtTime(double); - virtual double evaluateVelocityAtTime(double t) { return 0.; } - virtual double evaluateAccelerationAtTime(double t) { return 0.; } + double evaluateAtTime(double) override; + double evaluateVelocityAtTime(double t) override { return 0.; } + double evaluateAccelerationAtTime(double t) override { return 0.; } }; } // end namespace oofem #endif // heavisidetimefunction_h diff --git a/src/oofemlib/homexportmodule.C b/src/oofemlib/homexportmodule.C index d962513fe..ab59d4892 100644 --- a/src/oofemlib/homexportmodule.C +++ b/src/oofemlib/homexportmodule.C @@ -39,6 +39,10 @@ #include "engngm.h" #include "material.h" #include "classfactory.h" +#include "crosssection.h" +#include "tm/EngineeringModels/transienttransportproblem.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Materials/structuralmaterial.h" namespace oofem { REGISTER_ExportModule(HOMExportModule) @@ -47,16 +51,21 @@ HOMExportModule :: HOMExportModule(int n, EngngModel *e) : ExportModule(n, e) { HOMExportModule :: ~HOMExportModule() { } -IRResultType -HOMExportModule :: initializeFrom(InputRecord *ir) +void +HOMExportModule :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, this->ists, _IFT_HOMExportModule_ISTs); + ExportModule :: initializeFrom(ir); + + IR_GIVE_OPTIONAL_FIELD(ir, this->ists, _IFT_HOMExportModule_ISTs); + this->reactions = 0; + IR_GIVE_OPTIONAL_FIELD(ir, this->reactions, _IFT_HOMExportModule_reactions); this->scale = 1.; IR_GIVE_OPTIONAL_FIELD(ir, this->scale, _IFT_HOMExportModule_scale); - //this->matnum.clear(); - //IR_GIVE_OPTIONAL_FIELD(ir, this->matnum, _IFT_HOMExportModule_matnum); - return ExportModule :: initializeFrom(ir); + this->strainEnergy = ir.hasField(_IFT_HOMExportModule_strain_energy); + this->strainEnergySumStressDep = 0; + + lastStress.resize(0); + lastStrainStressDep.resize(0); } void @@ -65,63 +74,152 @@ HOMExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) if ( !( testTimeStepOutput(tStep) || forcedOutput ) ) { return; } - - bool volExported = false; - fprintf(this->stream, "%.3e ", tStep->giveTargetTime()*this->timeScale); - IntArray elements; + bool outputVol = false; + double volTot; + FloatArray answer; + this->stream << std::scientific << tStep->giveTargetTime()*this->timeScale << " "; + //assemble list of eligible elements. Elements can be present more times in a list but averaging goes just once over each element. elements.resize(0); for ( int ireg = 1; ireg <= this->giveNumberOfRegions(); ireg++ ) { elements.followedBy(this->giveRegionSet(ireg)->giveElementList()); } //elements.printYourself(); + + if (!ists.isEmpty()) { + for ( int ist: ists ) { + average(answer, volTot, ist, false, tStep); + + if(!outputVol){ + this->stream << std::scientific << volTot << " "; + outputVol = true; + } + + if(answer.giveSize() == 0) { //value not defined + this->stream << "-"; + } else if (answer.giveSize() == 1) { + this->stream << answer.at(1); + } else { + this->stream << answer.giveSize() << " "; + for ( auto s: answer ) { + this->stream << std::scientific << s << " "; + } + } + this->stream << " "; + } + } + if (reactions) { + ///@todo need reaction forces from engngm model, not separately from sm/tm modules as it is implemented now + /* + TransientTransportProblem *TTP = dynamic_cast< TransientTransportProblem * >(emodel); + FieldPtr fld = TTP->giveField(FT_HumidityConcentration, tStep); + */ + + } + + + if(strainEnergy){ + average(answer, volTot, IST_Undefined, true, tStep); + strainEnergySumStressDep += answer.at(1); + this->stream << answer.at(1) << " " << strainEnergySumStressDep; + } + + this->stream << "\n" << std::flush; +} + - for ( int ist: ists ) { - FloatArray ipState, avgState; - double VolTot = 0.; - Domain *d = emodel->giveDomain(1); - for ( auto &elem : d->giveElements() ) { - //printf("%d ", elem -> giveNumber()); - if ( elements.contains(elem -> giveNumber()) ){ - for ( GaussPoint *gp: *elem->giveDefaultIntegrationRulePtr() ) { - double dV = elem->computeVolumeAround(gp); - VolTot += dV; +void +HOMExportModule :: average(FloatArray &answer, double &volTot, int ist, bool strainEn, TimeStep *tStep) +{ + FloatArray ipState, tmp; + answer.resize(0); + volTot = 0.; + double dStrainEnergyStressDep=0; + int num = 0; + Domain *d = emodel->giveDomain(1); + for ( auto &elem : d->giveElements() ) { + //printf("%d ", elem -> giveNumber()); + if ( elements.contains(elem -> giveNumber()) ){ + for ( GaussPoint *gp: *elem->giveDefaultIntegrationRulePtr() ) { + double dV = elem->computeVolumeAround(gp); + volTot += dV; + + if(strainEn){ + FloatArray stress, lastStressIP, strain, strainRed, tmp, strainStressDep, lastStrainStressDepIP, avSig, dEpsStressDep; + elem->giveGlobalIPValue(stress, gp, IST_StressTensor, tStep); //returns in giveFullSymVectorForm + elem->giveGlobalIPValue(strain, gp, IST_StrainTensor, tStep); + + //Get stress-dependent strain, need FullSymVectorForm of (eps-eps_eig) + StructuralMaterial :: giveReducedSymVectorForm(strainRed, strain, gp->giveMaterialMode()); + dynamic_cast< StructuralMaterial * >(elem->giveCrossSection()->giveMaterial(gp))->giveStressDependentPartOfStrainVector(tmp, gp, strainRed, tStep, VM_Total); + StructuralMaterial :: giveFullSymVectorForm(strainStressDep, tmp, gp->giveMaterialMode()); + + if(int(lastStress.size()) <= num){ + lastStressIP.resize(stress.giveSize()); + lastStressIP.zero(); + lastStrainStressDepIP.resize(stress.giveSize()); + lastStrainStressDepIP.zero(); + } else { + lastStressIP = lastStress[num]; + lastStrainStressDepIP = lastStrainStressDep[num]; + } + + + avSig = 0.5*lastStressIP + 0.5*stress; + dEpsStressDep.beDifferenceOf(strainStressDep, lastStrainStressDepIP); + + dStrainEnergyStressDep += dV*avSig.dotProduct(dEpsStressDep); + + //memorize current values for the next step + if(int(lastStress.size()) <= num){ + lastStress.push_back(stress); + lastStrainStressDep.push_back(strainStressDep); + } else { + lastStress[num] = stress; + lastStrainStressDep[num] = strainStressDep; + } + num++; + } else { elem->giveGlobalIPValue(ipState, gp, (InternalStateType)ist, tStep); - avgState.add(dV, ipState); + answer.add(dV, ipState); } + } } + } - if ( !volExported ) { - fprintf(this->stream, "%.3e ", VolTot); - volExported = true; - } - avgState.times( 1. / VolTot * this->scale ); - fprintf(this->stream, "%d ", avgState.giveSize()); - for ( auto s: avgState ) { - fprintf(this->stream, "%e ", s); - } - fprintf(this->stream, " "); + if(strainEn){ + answer.resize(1); + answer.at(1) = dStrainEnergyStressDep ; + return; + } else { + answer.times( 1. / volTot * this->scale ); + return; } - fprintf(this->stream, "\n" ); - fflush(this->stream); } + void HOMExportModule :: initialize() { - std :: string fileName = emodel->giveOutputBaseFileName() + ".hom"; - if ( ( this->stream = fopen(fileName.c_str(), "w") ) == NULL ) { - OOFEM_ERROR( "failed to open file %s", fileName.c_str() ); + char numStr[32]; + sprintf(numStr, "%02d", this->number); + std::string fileName = emodel->giveOutputBaseFileName() + "." + numStr + ".hom"; + stream = std::ofstream(fileName); + if ( !stream.good() ) { + OOFEM_ERROR("failed to open file %s", fileName.c_str() ); } - - fprintf(this->stream, "#Time Volume "); + + this->stream << "#Time Volume "; for ( int var: this->ists ) { - fprintf(this->stream, "%s ", __InternalStateTypeToString( ( InternalStateType ) var) ); + this->stream << __InternalStateTypeToString( ( InternalStateType ) var) << " "; } - fprintf(this->stream, "\n" ); - fflush(this->stream); - + + if(this->strainEnergy){ + this->stream << "StrainEnergyIncrStressDep StrainEnergySumStressDep "; + } + + this->stream << "\n" << std::flush; initializeElementSet(); @@ -131,6 +229,9 @@ HOMExportModule :: initialize() void HOMExportModule :: terminate() { - fclose(this->stream); + + if (this->stream){ + this->stream.close(); + } } } // end namespace oofem diff --git a/src/oofemlib/homexportmodule.h b/src/oofemlib/homexportmodule.h index bcfbfbd2b..b68d0cc09 100644 --- a/src/oofemlib/homexportmodule.h +++ b/src/oofemlib/homexportmodule.h @@ -37,15 +37,19 @@ #include "exportmodule.h" #include "floatarray.h" +#include +#include ///@name Input fields for Homogenization export module //@{ #define _IFT_HOMExportModule_Name "hom" #define _IFT_HOMExportModule_ISTs "ists" /// List of internal state types used for output +#define _IFT_HOMExportModule_reactions "reactions" /// Whether to export reactions #define _IFT_HOMExportModule_scale "scale" ///[optional] Scales the output variables -//#define _IFT_HOMExportModule_matnum "matnum" ///[optional] If specified, only these materials are used +#define _IFT_HOMExportModule_strain_energy "strain_energy" ///[optional] Strain energy through the integration over strain energy densities in integration points //@} +using namespace std; namespace oofem { /** * Represents HOM (Homogenization) export module. It averages internal variables over the whole domain @@ -61,23 +65,35 @@ class OOFEM_EXPORT HOMExportModule : public ExportModule /// Scale of all homogenized values. double scale; /// Stream for file. - FILE *stream; - /// Material numbers over which averaging is performed. - replaced by 'regionsets' - //IntArray matnum; + std::ofstream stream; /// Internal states to export IntArray ists; + /// List of elements + IntArray elements; + /// Last averaged stress + std::vector< FloatArray > lastStress; + /// Last averaged stress-dependent strain + std::vector< FloatArray > lastStrainStressDep; + /// Reactions to export + bool reactions; + /// Allow calculation of strain energy, evaluated from mid-point rule (exact for linear elastic problems with zero initial stress/strain field). Allows only non-growing domains. + bool strainEnergy; + // Sum of strain energy (total) and stress-dependent strain energy + double strainEnergySumStressDep; public: /// Constructor. Creates empty Output Manager. HOMExportModule(int n, EngngModel * e); /// Destructor. virtual ~HOMExportModule(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void doOutput(TimeStep *tStep, bool forcedOutput = false); - virtual void initialize(); - virtual void terminate(); - virtual const char *giveClassName() const { return "HOMExportModule"; } - virtual const char *giveInputRecordName() const { return _IFT_HOMExportModule_Name; } + void initializeFrom(InputRecord &ir) override; + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; + //returns averaged property + void average(FloatArray &answer, double &volTot, int ist, bool subtractStressDepStrain, TimeStep *tStep); + void initialize() override; + void terminate() override; + const char *giveClassName() const override { return "HOMExportModule"; } + const char *giveInputRecordName() const { return _IFT_HOMExportModule_Name; } }; } // end namespace oofem diff --git a/src/oofemlib/homogenize.C b/src/oofemlib/homogenize.C index 3e6c1c76e..e89a6002f 100644 --- a/src/oofemlib/homogenize.C +++ b/src/oofemlib/homogenize.C @@ -44,14 +44,13 @@ void Homogenize :: voigt(FloatMatrix &PhaseMatrix) { double k, mu; double volTot = 0.; - int r; int NumPhases = PhaseMatrix.giveNumberOfRows(); checkVolFraction(PhaseMatrix); k_hmg = 0.; mu_hmg = 0.; - for ( r = 0; r < NumPhases; r++ ) { + for ( int r = 0; r < NumPhases; r++ ) { ENuToKMu(PhaseMatrix(r, 1), PhaseMatrix(r, 2), k, mu); k_hmg += k * PhaseMatrix(r, 0); mu_hmg += mu * PhaseMatrix(r, 0); @@ -66,14 +65,13 @@ void Homogenize :: voigt(FloatMatrix &PhaseMatrix) void Homogenize :: reuss(FloatMatrix &PhaseMatrix) { double k, mu; - int r; int NumPhases = PhaseMatrix.giveNumberOfRows(); checkVolFraction(PhaseMatrix); k_hmg = 0.; mu_hmg = 0.; - for ( r = 0; r < NumPhases; r++ ) { + for ( int r = 0; r < NumPhases; r++ ) { ENuToKMu(PhaseMatrix(r, 1), PhaseMatrix(r, 2), k, mu); k_hmg += PhaseMatrix(r, 0) / k; mu_hmg += PhaseMatrix(r, 0) / mu; @@ -94,7 +92,7 @@ void Homogenize :: reuss(FloatMatrix &PhaseMatrix) */ void Homogenize :: hashinShtrikmanWalpole(FloatMatrix &PhaseMatrix) { - int phase = 0, i, r; + int phase = 0; int counter = 0; int numRows = PhaseMatrix.giveNumberOfRows(); double k, k_min, mu, mu_phase = 0., muMin, muMax; @@ -107,9 +105,9 @@ void Homogenize :: hashinShtrikmanWalpole(FloatMatrix &PhaseMatrix) checkVolFraction(PhaseMatrix1); //Sort phases in ascending order of bulk moduli - for ( i = 0; i < numRows; i++ ) { + for ( int i = 0; i < numRows; i++ ) { k_min = 1.e+40; - for ( r = 0; r < numRows; r++ ) { + for ( int r = 0; r < numRows; r++ ) { if ( PhaseMatrix1(r, 0) > 0. + 1.e-40 ) { ENuToKMu(PhaseMatrix1(r, 1), PhaseMatrix1(r, 2), k, mu); if ( k < k_min ) { @@ -132,7 +130,7 @@ void Homogenize :: hashinShtrikmanWalpole(FloatMatrix &PhaseMatrix) //Find phase numbers for maximum and minimum shear moduli muMin = 1.e+40; muMax = 0.; - for ( i = 0; i < numRows; i++ ) { + for ( int i = 0; i < numRows; i++ ) { if ( SortedPhaseMatrix(i, 2) > muMax ) { muMax = SortedPhaseMatrix(i, 2); } @@ -145,7 +143,7 @@ void Homogenize :: hashinShtrikmanWalpole(FloatMatrix &PhaseMatrix) // find bounds for bulk moduli k_hmg = 0; //lower bound k_hmg_2 = 0; //upper bound - for ( i = 0; i < numRows; i++ ) { + for ( int i = 0; i < numRows; i++ ) { k_hmg += SortedPhaseMatrix(i, 0) / ( SortedPhaseMatrix(i, 1) + 4. / 3. * muMin ); k_hmg_2 += SortedPhaseMatrix(i, 0) / ( SortedPhaseMatrix(i, 1) + 4. / 3. * muMax ); } @@ -182,7 +180,6 @@ void Homogenize :: moriTanaka(FloatMatrix &PhaseMatrix, int refRow) double k_S_denom = 0., mu_S_denom = 0.; double alpha_m, beta_m; int numRows = PhaseMatrix.giveNumberOfRows(); - int r; FloatArray k_S(numRows), mu_S(numRows); checkVolFraction(PhaseMatrix); @@ -198,7 +195,7 @@ void Homogenize :: moriTanaka(FloatMatrix &PhaseMatrix, int refRow) beta_m = 6. * ( k_m + 2. * mu_m ) / ( 5. * ( 3. * k_m + 4. * mu_m ) ); //cycle through all phases, including the matrix phase - for ( r = 0; r < numRows; r++ ) { + for ( int r = 0; r < numRows; r++ ) { f_r = PhaseMatrix(r, 0); E_r = PhaseMatrix(r, 1); nu_r = PhaseMatrix(r, 2); @@ -223,7 +220,7 @@ void Homogenize :: moriTanaka(FloatMatrix &PhaseMatrix, int refRow) kMuToENu(k_hmg, mu_hmg, E_hmg, nu_hmg); //calculate denominator of strain concentration tensor (in terms of k_S and mu_S) and final values - for ( r = 0; r < numRows; r++ ) { + for ( int r = 0; r < numRows; r++ ) { f_r = PhaseMatrix(r, 0); E_r = PhaseMatrix(r, 1); nu_r = PhaseMatrix(r, 2); @@ -232,7 +229,7 @@ void Homogenize :: moriTanaka(FloatMatrix &PhaseMatrix, int refRow) mu_S_denom += f_r * 1. / ( 1. + beta_m * ( mu_r / mu_m - 1. ) ); } - for ( r = 0; r < numRows; r++ ) { + for ( int r = 0; r < numRows; r++ ) { E_r = PhaseMatrix(r, 1); nu_r = PhaseMatrix(r, 2); ENuToKMu(E_r, nu_r, k_r, mu_r); @@ -343,7 +340,6 @@ void Homogenize :: selfConsistent(FloatMatrix &PhaseMatrix) void Homogenize :: herveZaoui(FloatMatrix &PhaseMatrix) { - int i, j, phi; int NumPhases = PhaseMatrix.giveNumberOfRows() + 1; //need to extend for an equivalent homogeneous medium FloatMatrix PhaseMatrix1( NumPhases, PhaseMatrix.giveNumberOfColumns() ); checkVolFraction(PhaseMatrix); @@ -365,19 +361,19 @@ void Homogenize :: herveZaoui(FloatMatrix &PhaseMatrix) OOFEM_ERROR("Number of considered phases must be at least 3 (including hom. medium)"); } - F(NumPhases - 1) = lambda_0 / 3.; + F[NumPhases - 1] = lambda_0 / 3.; //radii of spheres, assume 1 as the maximal radius temp1 = 0.; - for ( i = 0; i < NumPhases - 1; i++ ) { + for ( int i = 0; i < NumPhases - 1; i++ ) { temp1 += PhaseMatrix1(i, 0); - r(i) = 1. * cbrt(temp1); - //printf( "r(%d)=%f\n", i, r(i) ); + r[i] = 1. * cbrt(temp1); + //printf( "r(%d)=%f\n", i, r[i] ); } - for ( i = 0; i < NumPhases; i++ ) { - ENuToKMu( PhaseMatrix1(i, 1), PhaseMatrix1(i, 2), k(i), mu(i) ); - //printf("k(%d)=%f mu(%d)=%f\n", i, k(i), i, mu(i)); + for ( int i = 0; i < NumPhases; i++ ) { + ENuToKMu( PhaseMatrix1(i, 1), PhaseMatrix1(i, 2), k[i], mu[i] ); + //printf("k(%d)=%f mu(%d)=%f\n", i, k[i], i, mu[i]); } //create unit matrix for the first multiplication @@ -385,42 +381,42 @@ void Homogenize :: herveZaoui(FloatMatrix &PhaseMatrix) Nhelp(1, 1) = 1.; //calculate Q - for ( phi = 0; phi <= NumPhases - 2; phi++ ) { + for ( int phi = 0; phi <= NumPhases - 2; phi++ ) { //calculate inverse of J_{phi+1} - fillJ(J, r(phi), mu, k, phi + 1); + fillJ(J, r[phi], mu, k, phi + 1); Jinv.beInverseOf(J); //calculate J_{phi} - fillJ(J, r(phi), mu, k, phi); + fillJ(J, r[phi], mu, k, phi); //calculate N^{phi}=J_{phi+1}^{-1}*J_{phi} N.beProductOf(Jinv, J); //calculate a part of Q^{phi} Q.beProductOf(N, Nhelp); //store part of matrix Q in vector Q11 and Q21 - Q11(phi) = Q(0, 0); - Q21(phi) = Q(1, 0); + Q11[phi] = Q(0, 0); + Q21[phi] = Q(1, 0); //copy Q to Nhelp and use in the next cycle Nhelp = Q; } - //calculate V (contains vector components F,G), F(0) and G(0) make no sense - for ( phi = 1; phi <= NumPhases - 1; phi++ ) { - F(phi) = F(NumPhases - 1) * Q11(phi - 1) / Q11(NumPhases - 2); - G(phi) = F(NumPhases - 1) * Q21(phi - 1) / Q11(NumPhases - 2); - //printf("F(%d)=%f G(%d)=%f\n", phi, F(phi), phi, G(phi)); + //calculate V (contains vector components F,G), F[0] and G[0] make no sense + for ( int phi = 1; phi <= NumPhases - 1; phi++ ) { + F[phi] = F[NumPhases - 1] * Q11[phi - 1] / Q11[NumPhases - 2]; + G[phi] = F[NumPhases - 1] * Q21[phi - 1] / Q11[NumPhases - 2]; + //printf("F(%d)=%f G(%d)=%f\n", phi, F[phi], phi, G[phi]); } //check displacement and stress continuity, phi is the more distant phase - /* - * for ( int phi = 1; phi <= NumPhases - 1; phi++ ) { - * printf("r=%f displ(in)=%f displ(out)=%f\n", r(phi-1), F(phi-1)*r(phi-1)+G(phi-1)/(r(phi-1)*r(phi-1)), F(phi)*r(phi-1)+G(phi)/(r(phi-1)*r(phi-1))); - * printf("r=%f stress(in)=%f stress(out)=%f\n", r(phi-1), 3.*k(phi-1)*F(phi-1)-4.*mu(phi-1)*G(phi-1)/(r(phi-1)*r(phi-1)*r(phi-1)), 3.*k(phi)*F(phi)-4.*mu(phi)*G(phi)/(r(phi-1)*r(phi-1)*r(phi-1))); - * } - */ +#if 0 + for ( int phi = 1; phi <= NumPhases - 1; phi++ ) { + printf("r=%f displ(in)=%f displ(out)=%f\n", r[phi-1], F[phi-1]*r[phi-1]+G[phi-1]/(r[phi-1]*r[phi-1]), F[phi]*r[phi-1]+G[phi]/(r[phi-1]*r[phi-1])); + printf("r=%f stress(in)=%f stress(out)=%f\n", r[phi-1], 3.*k[phi-1]*F[phi-1]-4.*mu[phi-1]*G[phi-1]/(r[phi-1]*r[phi-1]*r[phi-1]), 3.*k[phi]*F[phi]-4.*mu[phi]*G[phi]/(r[phi-1]*r[phi-1]*r[phi-1])); + } +#endif /*replace n+1 layer with equivalent homogeneous media calculate homogenized k * checked with Mori-Tanaka method for two phases, bulk modulus is exact */ - k_hmg = ( 3. * k(NumPhases - 2) * pow(r(NumPhases - 2), 3.) * Q11(NumPhases - 3) - 4. * mu(NumPhases - 2) * Q21(NumPhases - 3) ) / ( 3. * ( pow(r(NumPhases - 2), 3.) * Q11(NumPhases - 3) + Q21(NumPhases - 3) ) ); + k_hmg = ( 3. * k[NumPhases - 2] * pow(r[NumPhases - 2], 3.) * Q11[NumPhases - 3] - 4. * mu[NumPhases - 2] * Q21[NumPhases - 3] ) / ( 3. * ( pow(r[NumPhases - 2], 3.) * Q11[NumPhases - 3] + Q21[NumPhases - 3] ) ); //printf("Homogenized k=%f\n", k_hmg); @@ -435,65 +431,64 @@ void Homogenize :: herveZaoui(FloatMatrix &PhaseMatrix) double gamma = 10.; //no effect for homogenziation A.zero(); - A(NumPhases - 1) = gamma; + A[NumPhases - 1] = gamma; //create unit matrix for the first multiplication Mhelp.zero(); Mhelp.beUnitMatrix(); //calculate P - for ( phi = 0; phi < NumPhases - 1; phi++ ) { + for ( int phi = 0; phi < NumPhases - 1; phi++ ) { //calculate inverse of L_{phi+1} - fillL(L, r(phi), mu, k, phi + 1); + fillL(L, r[phi], mu, k, phi + 1); //printf("%f", L(0,1)); Linv.beInverseOf(L); //calculate L_{phi} - fillL(L, r(phi), mu, k, phi); + fillL(L, r[phi], mu, k, phi); //calulate M^{phi}=L_{phi+1}^{-1}*L_{phi} M.beProductOf(Linv, L); - /*test routine directly for M - * this part calculate inverse of M directly - * M=M_test so the L, Linv and M assembly are OK - * - * double ak, bk, ck, dk, ek, fk, alphak, nuk, nukp1, koef; - * - * nuk=PhaseMatrix1(phi,2); - * nukp1=PhaseMatrix1(phi+1,2); - * - * ak=mu(phi)/mu(phi+1)*(7.+5.*nuk)*(7.-10.*nukp1)-(7.-10*nuk)*(7.+5.*nukp1); - * bk=4.*(7.-10.*nuk)+mu(phi)/mu(phi+1)*(7.+5.*nuk); - * ck=(7.-5.*nukp1)+2.*mu(phi)/mu(phi+1)*(4.-5.*nukp1); - * dk=(7.+5.*nukp1)+4.*mu(phi)/mu(phi+1)*(7.-10.*nukp1); - * ek=2*(4.-5.*nuk)+mu(phi)/mu(phi+1)*(7.-5.*nuk); - * fk=(4.-5.*nuk)*(7.-5.*nukp1)-mu(phi)/mu(phi+1)*(4.-5.*nukp1)*(7.-5.*nuk); - * alphak=mu(phi)/mu(phi+1)-1.; - * koef=1./(5.*(1-nukp1)); - * - * M_test(0,0)=koef*ck/3.; - * M_test(0,1)=koef*pow(r(phi),2)*(3*bk-7*ck)/(5.*(1.-2*nuk)); - * M_test(0,2)=koef*(-12.)*alphak/pow(r(phi),5); - * M_test(0,3)=koef*4.*(fk-27.*alphak)/(15.*(1.-2*nuk)*pow(r(phi),3)); - * - * M_test(1,0)=koef*0.; - * M_test(1,1)=koef*(1.-2*nukp1)*bk/(7.*(1.-2.*nuk)); - * M_test(1,2)=koef*(-20.)*(1.-2.*nukp1)*alphak/(7*pow(r(phi),7)); - * M_test(1,3)=koef*(-12.)*alphak*(1.-2.*nukp1)/(7.*(1.-2.*nuk)*(pow(r(phi),5))); - * - * M_test(2,0)=koef*pow(r(phi),5)*alphak/2.; - * M_test(2,1)=koef*(-pow(r(phi),7))*(2*ak+147*alphak)/(70.*(1.-2.*nuk)); - * M_test(2,2)=koef*dk/7.; - * M_test(2,3)=koef*pow(r(phi),2)*(105*(1.-nukp1)+12.*alphak*(7.-10.*nukp1)-7.*ek)/(35.*(1.-2*nuk)); - * - * M_test(3,0)=koef*(-5.)/6.*(1.-2*nukp1)*alphak*pow(r(phi),3); - * M_test(3,1)=koef*7.*(1.-2*nukp1)*alphak*pow(r(phi),5)/(2.*(1.-2.*nuk)); - * M_test(3,2)=koef*0.; - * M_test(3,3)=koef*ek*(1.-2.*nukp1)/(3.*(1.-2*nuk)); - * - * for(int ii=0;ii<4;ii++) - * for(int jj=0;jj<4;jj++) - * M(ii,jj)=M_test(ii,jj); - */ +#if 0 + // test routine directly for M + this part calculate inverse of M directly + M=M_test so the L, Linv and M assembly are OK + + double ak, bk, ck, dk, ek, fk, alphak, nuk, nukp1, koef; + + nuk=PhaseMatrix1(phi,2); + nukp1=PhaseMatrix1(phi+1,2); + + ak=mu[phi]/mu[phi+1]*(7.+5.*nuk)*(7.-10.*nukp1)-(7.-10*nuk)*(7.+5.*nukp1); + bk=4.*(7.-10.*nuk)+mu[phi]/mu[phi+1]*(7.+5.*nuk); + ck=(7.-5.*nukp1)+2.*mu[phi]/mu[phi+1]*(4.-5.*nukp1); + dk=(7.+5.*nukp1)+4.*mu[phi]/mu[phi+1]*(7.-10.*nukp1); + ek=2*(4.-5.*nuk)+mu[phi]/mu[phi+1]*(7.-5.*nuk); + fk=(4.-5.*nuk)*(7.-5.*nukp1)-mu[phi]/mu[phi+1]*(4.-5.*nukp1)*(7.-5.*nuk); + alphak=mu[phi]/mu[phi+1]-1.; + koef=1./(5.*(1-nukp1)); + + M_test(0,0)=koef*ck/3.; + M_test(0,1)=koef*pow(r[phi],2)*(3*bk-7*ck)/(5.*(1.-2*nuk)); + M_test(0,2)=koef*(-12.)*alphak/pow(r[phi],5); + M_test(0,3)=koef*4.*(fk-27.*alphak)/(15.*(1.-2*nuk)*pow(r[phi],3)); + + M_test(1,0)=koef*0.; + M_test(1,1)=koef*(1.-2*nukp1)*bk/(7.*(1.-2.*nuk)); + M_test(1,2)=koef*(-20.)*(1.-2.*nukp1)*alphak/(7*pow(r[phi],7)); + M_test(1,3)=koef*(-12.)*alphak*(1.-2.*nukp1)/(7.*(1.-2.*nuk)*(pow(r[phi],5))); + + M_test(2,0)=koef*pow(r[phi],5)*alphak/2.; + M_test(2,1)=koef*(-pow(r[phi],7))*(2*ak+147*alphak)/(70.*(1.-2.*nuk)); + M_test(2,2)=koef*dk/7.; + M_test(2,3)=koef*pow(r[phi],2)*(105*(1.-nukp1)+12.*alphak*(7.-10.*nukp1)-7.*ek)/(35.*(1.-2*nuk)); + + M_test(3,0)=koef*(-5.)/6.*(1.-2*nukp1)*alphak*pow(r[phi],3); + M_test(3,1)=koef*7.*(1.-2*nukp1)*alphak*pow(r[phi],5)/(2.*(1.-2.*nuk)); + M_test(3,2)=koef*0.; + M_test(3,3)=koef*ek*(1.-2.*nukp1)/(3.*(1.-2*nuk)); + + M = M_test; +#endif P_arr [ phi ].resize(4, 4); P_arr [ phi ].beProductOf(M, Mhelp); Mhelp = P_arr [ phi ]; @@ -503,68 +498,68 @@ void Homogenize :: herveZaoui(FloatMatrix &PhaseMatrix) //calculate vector W (contains scalar components A,B,C,D for each step) - P_v(0) = P_arr [ NumPhases - 2 ](1, 1); //matrix stored column wise (P11, P21, P31....), P_22 - P_v(1) = -P_arr [ NumPhases - 2 ](1, 0); // P_21 - P_v(2) = P_v(3) = 0.; + P_v[0] = P_arr [ NumPhases - 2 ](1, 1); //matrix stored column wise (P11, P21, P31....), P_22 + P_v[1] = -P_arr [ NumPhases - 2 ](1, 0); // P_21 + P_v[2] = P_v[3] = 0.; - for ( phi = 1; phi <= NumPhases - 1; phi++ ) { + for ( int phi = 1; phi <= NumPhases - 1; phi++ ) { Phelp.beProductOf(P_arr [ phi - 1 ], P_v); - Phelp.times( A(NumPhases - 1) / sqrt(2.) / ( P_arr [ NumPhases - 2 ](0, 0) * P_arr [ NumPhases - 2 ](1, 1) - P_arr [ NumPhases - 2 ](0, 1) * P_arr [ NumPhases - 2 ](1, 0) ) ); - A(phi) = Phelp(0); - B(phi) = Phelp(1); - C(phi) = Phelp(2); - D(phi) = Phelp(3); - //printf("A(%d]=%f B(%d)=%f C(%d)=%f D(%d)=%f\n", phi, A(phi), phi, B(phi), phi, C(phi), phi, D(phi)); + Phelp.times( A[NumPhases - 1] / sqrt(2.) / ( P_arr [ NumPhases - 2 ](0, 0) * P_arr [ NumPhases - 2 ](1, 1) - P_arr [ NumPhases - 2 ](0, 1) * P_arr [ NumPhases - 2 ](1, 0) ) ); + A[phi] = Phelp[0]; + B[phi] = Phelp[1]; + C[phi] = Phelp[2]; + D[phi] = Phelp[3]; + //printf("A(%d]=%f B(%d)=%f C(%d)=%f D(%d)=%f\n", phi, A[phi], phi, B[phi], phi, C[phi], phi, D[phi]); } //check displacement and stress continuity, phi is the less distant phase //this cycle for for checking purposes only - for ( phi = 0; phi <= NumPhases - 2; phi++ ) { + for ( int phi = 0; phi <= NumPhases - 2; phi++ ) { //phase closer to the center - fillL(L, r(phi), mu, k, phi); - Phelp(0) = A(phi); - Phelp(1) = B(phi); - Phelp(2) = C(phi); - Phelp(3) = D(phi); + fillL(L, r[phi], mu, k, phi); + Phelp[0] = A[phi]; + Phelp[1] = B[phi]; + Phelp[2] = C[phi]; + Phelp[3] = D[phi]; P_v.beProductOf(L, Phelp); - //printf("(in) n=%d r=%f ur=%f uphi=%f srp=%f srf=%f\n",phi, r(phi), P_v(0),P_v(1), P_v(2), P_v(3)); + //printf("(in) n=%d r=%f ur=%f uphi=%f srp=%f srf=%f\n",phi, r[phi], P_v[0],P_v[1], P_v[2], P_v[3]); - fillL(L, r(phi), mu, k, phi + 1); - Phelp(0) = A(phi + 1); - Phelp(1) = B(phi + 1); - Phelp(2) = C(phi + 1); - Phelp(3) = D(phi + 1); + fillL(L, r[phi], mu, k, phi + 1); + Phelp[0] = A[phi + 1]; + Phelp[1] = B[phi + 1]; + Phelp[2] = C[phi + 1]; + Phelp[3] = D[phi + 1]; P_v.beProductOf(L, Phelp); - //printf("(out) n=%d r=%f ur=%f uphi=%f srp=%f srf=%f\n", phi,r(phi), P_v(0),P_v(1), P_v(2), P_v(3)); + //printf("(out) n=%d r=%f ur=%f uphi=%f srp=%f srf=%f\n", phi,r[phi], P_v[0],P_v[1], P_v[2], P_v[3]); } // replace n+1 layer with equivalent homogeneous media, calculate homogenized mu - for ( i = 0; i <= 3; i++ ) { //alpha, rows in Z - for ( j = 0; j <= 3; j++ ) { //beta, columns in Z + for ( int i = 0; i <= 3; i++ ) { //alpha, rows in Z + for ( int j = 0; j <= 3; j++ ) { //beta, columns in Z Z(i, j) = P_arr [ NumPhases - 3 ](i, 0) * P_arr [ NumPhases - 3 ](j, 1) - P_arr [ NumPhases - 3 ](j, 0) * P_arr [ NumPhases - 3 ](i, 1); // printf("Z=%f ", Z(i,j)); } } - nu_n = ( 3. * k(NumPhases - 2) - 2. * mu(NumPhases - 2) ) / ( 6. * k(NumPhases - 2) + 2. * mu(NumPhases - 2) ); + nu_n = ( 3. * k[NumPhases - 2] - 2. * mu[NumPhases - 2] ) / ( 6. * k[NumPhases - 2] + 2. * mu[NumPhases - 2] ); - a = 4. * pow(r(NumPhases - 2), 10.) * ( 1. - 2. * nu_n ) * ( 7. - 10. * nu_n ) * Z(0, 1) + - 20. * pow(r(NumPhases - 2), 7.) * ( 7. - 12. * nu_n + 8. * nu_n * nu_n ) * Z(3, 1) + - 12. * pow(r(NumPhases - 2), 5.) * ( 1. - 2. * nu_n ) * ( Z(0, 3) - 7. * Z(1, 2) ) + - 20. * pow(r(NumPhases - 2), 3.) * ( 1. - 2. * nu_n ) * ( 1. - 2. * nu_n ) * Z(0, 2) + - 16. * ( 4. - 5. * nu_n ) * ( 1. - 2. * nu_n ) * Z(3, 2); + a = 4. * pow(r[NumPhases - 2], 10.) * ( 1. - 2. * nu_n ) * ( 7. - 10. * nu_n ) * Z(0, 1) + + 20. * pow(r[NumPhases - 2], 7.) * ( 7. - 12. * nu_n + 8. * nu_n * nu_n ) * Z(3, 1) + + 12. * pow(r[NumPhases - 2], 5.) * ( 1. - 2. * nu_n ) * ( Z(0, 3) - 7. * Z(1, 2) ) + + 20. * pow(r[NumPhases - 2], 3.) * ( 1. - 2. * nu_n ) * ( 1. - 2. * nu_n ) * Z(0, 2) + + 16. * ( 4. - 5. * nu_n ) * ( 1. - 2. * nu_n ) * Z(3, 2); - b = 3. * pow(r(NumPhases - 2), 10.) * ( 1. - 2. * nu_n ) * ( 15. * nu_n - 7. ) * Z(0, 1) + - 60. * pow(r(NumPhases - 2), 7.) * ( nu_n - 3. ) * nu_n * Z(3, 1) - - 24. * pow(r(NumPhases - 2), 5.) * ( 1. - 2. * nu_n ) * ( Z(0, 3) - 7. * Z(1, 2) ) - - 40. * pow(r(NumPhases - 2), 3.) * ( 1. - 2. * nu_n ) * ( 1. - 2. * nu_n ) * Z(0, 2) - - 8. * ( 1. - 5. * nu_n ) * ( 1. - 2. * nu_n ) * Z(3, 2); + b = 3. * pow(r[NumPhases - 2], 10.) * ( 1. - 2. * nu_n ) * ( 15. * nu_n - 7. ) * Z(0, 1) + + 60. * pow(r[NumPhases - 2], 7.) * ( nu_n - 3. ) * nu_n * Z(3, 1) - + 24. * pow(r[NumPhases - 2], 5.) * ( 1. - 2. * nu_n ) * ( Z(0, 3) - 7. * Z(1, 2) ) - + 40. * pow(r[NumPhases - 2], 3.) * ( 1. - 2. * nu_n ) * ( 1. - 2. * nu_n ) * Z(0, 2) - + 8. * ( 1. - 5. * nu_n ) * ( 1. - 2. * nu_n ) * Z(3, 2); - c = -pow(r(NumPhases - 2), 10.) * ( 1. - 2. * nu_n ) * ( 7. + 5 * nu_n ) * Z(0, 1) + - 10. * pow(r(NumPhases - 2), 7.) * ( 7. - nu_n * nu_n ) * Z(3, 1) + - 12. * pow(r(NumPhases - 2), 5.) * ( 1. - 2. * nu_n ) * ( Z(0, 3) - 7. * Z(1, 2) ) + - 20. * pow(r(NumPhases - 2), 3.) * ( 1. - 2. * nu_n ) * ( 1. - 2. * nu_n ) * Z(0, 2) - - 8. * ( 7. - 5. * nu_n ) * ( 1. - 2. * nu_n ) * Z(3, 2); + c = -pow(r[NumPhases - 2], 10.) * ( 1. - 2. * nu_n ) * ( 7. + 5 * nu_n ) * Z(0, 1) + + 10. * pow(r[NumPhases - 2], 7.) * ( 7. - nu_n * nu_n ) * Z(3, 1) + + 12. * pow(r[NumPhases - 2], 5.) * ( 1. - 2. * nu_n ) * ( Z(0, 3) - 7. * Z(1, 2) ) + + 20. * pow(r[NumPhases - 2], 3.) * ( 1. - 2. * nu_n ) * ( 1. - 2. * nu_n ) * Z(0, 2) - + 8. * ( 7. - 5. * nu_n ) * ( 1. - 2. * nu_n ) * Z(3, 2); //solve quadratic equation, report higher number sqr = b * b - 4. * a * c; @@ -577,7 +572,7 @@ void Homogenize :: herveZaoui(FloatMatrix &PhaseMatrix) } //usually this higher value is reported - mu_hmg = mu(NumPhases - 2) * ( -b + pow(sqr, 0.5) ) / ( 2. * a ); + mu_hmg = mu[NumPhases - 2] * ( -b + pow(sqr, 0.5) ) / ( 2. * a ); //uncomment if lower value of mu should be used, only when positive //mu_hmg=mu(NumPhases-2)*(-b+pow(sqr, 0.5))/(2.*a); @@ -701,7 +696,8 @@ void Homogenize :: kMuToENu(const double k, const double mu, double &E, double & } //Auxiliary function for Hashin-Shtrikman-Walpole shear bounds -double Homogenize :: zeta(double k, double mu) { +double Homogenize :: zeta(double k, double mu) +{ return mu / 6. * ( 9. * k + 8. * mu ) / ( k + 2. * mu ); } @@ -709,10 +705,9 @@ double Homogenize :: zeta(double k, double mu) { double Homogenize :: gamma(FloatMatrix &SortedPhaseMatrix, double zeta) { double gamma = 0; - int r; int NumPhases = SortedPhaseMatrix.giveNumberOfRows(); - for ( r = 0; r < NumPhases; r++ ) { + for ( int r = 0; r < NumPhases; r++ ) { gamma += SortedPhaseMatrix(r, 0) / ( SortedPhaseMatrix(r, 2) + zeta ); } @@ -725,8 +720,7 @@ void Homogenize :: checkVolFraction(FloatMatrix &PhaseMatrix) { double volTot = 0.; int NumPhases = PhaseMatrix.giveNumberOfRows(); - int r; - for ( r = 0; r < NumPhases; r++ ) { + for ( int r = 0; r < NumPhases; r++ ) { volTot += PhaseMatrix(r, 0); } @@ -740,15 +734,15 @@ void Homogenize :: fillJ(FloatMatrix &J, double r, const FloatArray &mu, const F { J(0, 0) = r; J(0, 1) = 1. / ( pow(r, 2.) ); - J(1, 0) = 3 * k(phase); - J(1, 1) = -4. * mu(phase) / ( pow(r, 3.) ); + J(1, 0) = 3 * k[phase]; + J(1, 1) = -4. * mu[phase] / ( pow(r, 3.) ); } //help function for filling the L matrix void Homogenize :: fillL(FloatMatrix &L, double r, const FloatArray &mu, const FloatArray &k, int phase) { - double mu_l = mu(phase); - double k_l = k(phase); + double mu_l = mu[phase]; + double k_l = k[phase]; double nu_l = ( 3. * k_l - 2. * mu_l ) / ( 6. * k_l + 2. * mu_l ); //OK L(0, 0) = r; diff --git a/src/oofemlib/iga/feibspline.C b/src/oofemlib/iga/feibspline.C index b5a2e6282..80f1f35a8 100644 --- a/src/oofemlib/iga/feibspline.C +++ b/src/oofemlib/iga/feibspline.C @@ -39,30 +39,11 @@ #include "mathfem.h" namespace oofem { -BSplineInterpolation :: ~BSplineInterpolation() -{ - delete [] degree; - delete [] numberOfControlPoints; - delete [] numberOfKnotSpans; - - for ( int i = 0; i < nsd; i++ ) { - delete [] knotVector [ i ]; - } - - delete [] knotValues; - delete [] knotMultiplicity; - delete [] knotVector; -} - -IRResultType -BSplineInterpolation :: initializeFrom(InputRecord *ir) +void +BSplineInterpolation :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IntArray degree_tmp; - double *knotVec, knotVal; - int sum, pos, size; InputFieldType IFT_knotVector [ 3 ] = { _IFT_BSplineInterpolation_knotVectorU, @@ -76,17 +57,9 @@ BSplineInterpolation :: initializeFrom(InputRecord *ir) _IFT_BSplineInterpolation_knotMultiplicityW }; - knotValues = new FloatArray [ nsd ]; - knotMultiplicity = new IntArray [ nsd ]; - degree = new int [ nsd ]; - knotVector = new double * [ nsd ]; - numberOfKnotSpans = new int [ nsd ]; - numberOfControlPoints = new int [ nsd ]; - IR_GIVE_FIELD(ir, degree_tmp, _IFT_BSplineInterpolation_degree); if ( degree_tmp.giveSize() != nsd ) { - OOFEM_WARNING("degree size mismatch"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_BSplineInterpolation_degree, "degree size mismatch"); } for ( int i = 0; i < nsd; i++ ) { @@ -95,18 +68,16 @@ BSplineInterpolation :: initializeFrom(InputRecord *ir) for ( int n = 0; n < nsd; n++ ) { IR_GIVE_FIELD(ir, knotValues [ n ], IFT_knotVector [ n ]); - size = knotValues [ n ].giveSize(); + int size = knotValues [ n ].giveSize(); if ( size < 2 ) { - OOFEM_WARNING("invalid size of knot vector %s", IFT_knotVector [ n ]); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, IFT_knotVector [ n ], "invalid size of knot vector"); } // check for monotonicity of knot vector without multiplicity - knotVal = knotValues [ n ].at(1); + double knotVal = knotValues [ n ].at(1); for ( int i = 1; i < size; i++ ) { if ( knotValues [ n ].at(i + 1) <= knotVal ) { - OOFEM_WARNING("knot vector %s is not monotonic", IFT_knotVector [ n ]); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, IFT_knotVector [ n ], "knot vector is not monotonic"); } knotVal = knotValues [ n ].at(i + 1); @@ -115,7 +86,7 @@ BSplineInterpolation :: initializeFrom(InputRecord *ir) // transform knot vector to interval <0;1> double span = knotVal - knotValues [ n ].at(1); for ( int i = 1; i <= size; i++ ) { - knotValues [ n ].at(i) = knotValues [ n ].at(i) / span; + knotValues [ n ].at(i) /= span; } IR_GIVE_OPTIONAL_FIELD(ir, knotMultiplicity [ n ], IFT_knotMultiplicity [ n ]); @@ -128,16 +99,13 @@ BSplineInterpolation :: initializeFrom(InputRecord *ir) } } else { if ( knotMultiplicity [ n ].giveSize() != size ) { - OOFEM_WARNING("knot multiplicity %s size mismatch", IFT_knotMultiplicity [ n ]); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, IFT_knotMultiplicity [ n ], "knot multiplicity size mismatch"); } // check for multiplicity range (skip the first and last one) for ( int i = 1; i < size - 1; i++ ) { if ( knotMultiplicity [ n ].at(i + 1) < 1 || knotMultiplicity [ n ].at(i + 1) > degree [ n ] ) { - OOFEM_WARNING("knot multiplicity %s out of range - value %d", - IFT_knotMultiplicity [ n ], knotMultiplicity [ n ].at(i + 1) ); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, IFT_knotMultiplicity [ n ], "knot multiplicity out of range"); } } @@ -155,67 +123,63 @@ BSplineInterpolation :: initializeFrom(InputRecord *ir) knotMultiplicity [ n ].at(1) = knotMultiplicity [ n ].at(size) = degree [ n ] + 1; // sum the size of knot vector with multiplicity values - sum = 0; + int sum = 0; for ( int i = 0; i < size; i++ ) { - sum += knotMultiplicity [ n ].at(i + 1); + sum += knotMultiplicity [ n ][i]; } - knotVec = knotVector [ n ] = new double [ sum ]; + knotVector [ n ].resize( sum ); // fill knot vector including multiplicity values - pos = 0; + int pos = 0; for ( int i = 0; i < size; i++ ) { for ( int j = 0; j < knotMultiplicity [ n ].at(i + 1); j++ ) { - knotVec [ pos++ ] = knotValues [ n ].at(i + 1); + knotVector [ n ] [ pos++ ] = knotValues [ n ].at(i + 1); } } numberOfKnotSpans [ n ] = size - 1; numberOfControlPoints [ n ] = sum - degree [ n ] - 1; } - - return IRRT_OK; } -void BSplineInterpolation :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void BSplineInterpolation :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); IntArray span(nsd); - int c = 1, count; + int c = 1; std :: vector< FloatArray > N(nsd); - - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } for ( int i = 0; i < nsd; i++ ) { - this->basisFuns(N [ i ], span(i), lcoords(i), degree [ i ], knotVector [ i ]); + this->basisFuns(N [ i ], span[i], lcoords[i], degree [ i ], knotVector [ i ]); } - count = giveNumberOfKnotSpanBasisFunctions(span); - answer.resize(count); + answer.resize(giveNumberOfKnotSpanBasisFunctions(span)); if ( nsd == 1 ) { for ( int k = 0; k <= degree [ 0 ]; k++ ) { - answer.at(c++) = N [ 0 ](k); + answer.at(c++) = N [ 0 ][k]; } } else if ( nsd == 2 ) { for ( int l = 0; l <= degree [ 1 ]; l++ ) { for ( int k = 0; k <= degree [ 0 ]; k++ ) { - answer.at(c++) = N [ 0 ](k) * N [ 1 ](l); + answer.at(c++) = N [ 0 ][k] * N [ 1 ][l]; } } } else if ( nsd == 3 ) { for ( int m = 0; m <= degree [ 2 ]; m++ ) { for ( int l = 0; l <= degree [ 1 ]; l++ ) { for ( int k = 0; k <= degree [ 0 ]; k++ ) { - answer.at(c++) = N [ 0 ](k) * N [ 1 ](l) * N [ 2 ](m); + answer.at(c++) = N [ 0 ][k] * N [ 1 ][l] * N [ 2 ][m]; } } } @@ -225,40 +189,36 @@ void BSplineInterpolation :: evalN(FloatArray &answer, const FloatArray &lcoords } -double BSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double BSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; - const FloatArray *vertexCoordsPtr; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); FloatMatrix jacobian(nsd, nsd); IntArray span(nsd); double Jacob = 0.; - int count, cnt, ind, indx, uind, vind, tind; std :: vector< FloatMatrix > ders(nsd); - - - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } for ( int i = 0; i < nsd; i++ ) { - this->dersBasisFuns(1, lcoords(i), span(i), degree [ i ], knotVector [ i ], ders [ i ]); + this->dersBasisFuns(1, lcoords[i], span[i], degree [ i ], knotVector [ i ], ders [ i ]); } - count = giveNumberOfKnotSpanBasisFunctions(span); + int count = giveNumberOfKnotSpanBasisFunctions(span); answer.resize(count, nsd); jacobian.zero(); if ( nsd == 1 ) { - uind = span(0) - degree [ 0 ]; - ind = uind + 1; + int uind = span[0] - degree [ 0 ]; + int ind = uind + 1; for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - jacobian(0, 0) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1); // dx/du=sum(dNu/du*x) + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + jacobian(0, 0) += ders [ 0 ](1, k) * vertexCoords[0]; // dx/du=sum(dNu/du*x) } Jacob = jacobian.giveDeterminant(); @@ -267,7 +227,7 @@ double BSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &l OOFEM_ERROR("evaldNdx - zero Jacobian"); } - cnt = 0; + int cnt = 0; for ( int k = 0; k <= degree [ 0 ]; k++ ) { answer(cnt, 0) = ders [ 0 ](1, k) / Jacob; // dN/dx=dN/du / dx/du cnt++; @@ -275,29 +235,29 @@ double BSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &l } else if ( nsd == 2 ) { FloatArray tmp1(nsd), tmp2(nsd); - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - ind = vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int ind = vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp1.zero(); tmp2.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); - tmp1(0) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1); // sum(dNu/du*x) - tmp1(1) += ders [ 0 ](1, k) * vertexCoordsPtr->at(2); // sum(dNu/du*y) + tmp1[0] += ders [ 0 ](1, k) * vertexCoords[0]; // sum(dNu/du*x) + tmp1[1] += ders [ 0 ](1, k) * vertexCoords[1]; // sum(dNu/du*y) - tmp2(0) += ders [ 0 ](0, k) * vertexCoordsPtr->at(1); // sum(Nu*x) - tmp2(1) += ders [ 0 ](0, k) * vertexCoordsPtr->at(2); // sum(Nu*y) + tmp2[0] += ders [ 0 ](0, k) * vertexCoords[0]; // sum(Nu*x) + tmp2[1] += ders [ 0 ](0, k) * vertexCoords[1]; // sum(Nu*y) } ind += numberOfControlPoints [ 0 ]; - jacobian(0, 0) += ders [ 1 ](0, l) * tmp1(0); // dx/du=sum(Nv*sum(dNu/du*x)) - jacobian(0, 1) += ders [ 1 ](0, l) * tmp1(1); // dy/du=sum(Nv*sum(dNu/du*y)) + jacobian(0, 0) += ders [ 1 ](0, l) * tmp1[0]; // dx/du=sum(Nv*sum(dNu/du*x)) + jacobian(0, 1) += ders [ 1 ](0, l) * tmp1[1]; // dy/du=sum(Nv*sum(dNu/du*y)) - jacobian(1, 0) += ders [ 1 ](1, l) * tmp2(0); // dx/dv=sum(dNv/dv*sum(Nu*x)) - jacobian(1, 1) += ders [ 1 ](1, l) * tmp2(1); // dy/dv=sum(dNv/dv*sum(Nu*y)) + jacobian(1, 0) += ders [ 1 ](1, l) * tmp2[0]; // dx/dv=sum(dNv/dv*sum(Nu*x)) + jacobian(1, 1) += ders [ 1 ](1, l) * tmp2[1]; // dy/dv=sum(dNv/dv*sum(Nu*y)) } Jacob = jacobian.giveDeterminant(); @@ -306,13 +266,13 @@ double BSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &l OOFEM_ERROR("evaldNdx - zero Jacobian"); } - cnt = 0; + int cnt = 0; for ( int l = 0; l <= degree [ 1 ]; l++ ) { for ( int k = 0; k <= degree [ 0 ]; k++ ) { - tmp1(0) = ders [ 0 ](1, k) * ders [ 1 ](0, l); // dN/du=dNu/du*Nv - tmp1(1) = ders [ 0 ](0, k) * ders [ 1 ](1, l); // dN/dv=Nu*dNv/dv - answer(cnt, 0) = ( +jacobian(1, 1) * tmp1(0) - jacobian(0, 1) * tmp1(1) ) / Jacob; // dN/dx - answer(cnt, 1) = ( -jacobian(1, 0) * tmp1(0) + jacobian(0, 0) * tmp1(1) ) / Jacob; // dN/dy + tmp1[0] = ders [ 0 ](1, k) * ders [ 1 ](0, l); // dN/du=dNu/du*Nv + tmp1[1] = ders [ 0 ](0, k) * ders [ 1 ](1, l); // dN/dv=Nu*dNv/dv + answer(cnt, 0) = ( +jacobian(1, 1) * tmp1[0] - jacobian(0, 1) * tmp1[1] ) / Jacob; // dN/dx + answer(cnt, 1) = ( -jacobian(1, 0) * tmp1[0] + jacobian(0, 0) * tmp1[1] ) / Jacob; // dN/dy cnt++; } } @@ -320,58 +280,58 @@ double BSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &l FloatArray tmp1(nsd), tmp2(nsd); FloatArray temp1(nsd), temp2(nsd), temp3(nsd); - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - tind = span(2) - degree [ 2 ]; - ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int tind = span[2] - degree [ 2 ]; + int ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int m = 0; m <= degree [ 2 ]; m++ ) { temp1.zero(); temp2.zero(); temp3.zero(); - indx = ind; + int indx = ind; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp1.zero(); tmp2.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); - tmp1(0) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1); // sum(dNu/du*x) - tmp1(1) += ders [ 0 ](1, k) * vertexCoordsPtr->at(2); // sum(dNu/du*y) - tmp1(2) += ders [ 0 ](1, k) * vertexCoordsPtr->at(3); // sum(dNu/du*z) + tmp1[0] += ders [ 0 ](1, k) * vertexCoords[0]; // sum(dNu/du*x) + tmp1[1] += ders [ 0 ](1, k) * vertexCoords[1]; // sum(dNu/du*y) + tmp1[2] += ders [ 0 ](1, k) * vertexCoords[2]; // sum(dNu/du*z) - tmp2(0) += ders [ 0 ](0, k) * vertexCoordsPtr->at(1); // sum(Nu*x) - tmp2(1) += ders [ 0 ](0, k) * vertexCoordsPtr->at(2); // sum(Nu*y) - tmp2(2) += ders [ 0 ](0, k) * vertexCoordsPtr->at(3); // sum(Nu*y) + tmp2[0] += ders [ 0 ](0, k) * vertexCoords[0]; // sum(Nu*x) + tmp2[1] += ders [ 0 ](0, k) * vertexCoords[1]; // sum(Nu*y) + tmp2[2] += ders [ 0 ](0, k) * vertexCoords[2]; // sum(Nu*y) } ind += numberOfControlPoints [ 0 ]; - temp1(0) += ders [ 1 ](0, l) * tmp1(0); // sum(Nv*sum(dNu/du*x)) - temp1(1) += ders [ 1 ](0, l) * tmp1(1); // sum(Nv*sum(dNu/du*y)) - temp1(2) += ders [ 1 ](0, l) * tmp1(2); // sum(Nv*sum(dNu/du*z)) + temp1[0] += ders [ 1 ](0, l) * tmp1[0]; // sum(Nv*sum(dNu/du*x)) + temp1[1] += ders [ 1 ](0, l) * tmp1[1]; // sum(Nv*sum(dNu/du*y)) + temp1[2] += ders [ 1 ](0, l) * tmp1[2]; // sum(Nv*sum(dNu/du*z)) - temp2(0) += ders [ 1 ](1, l) * tmp2(0); // sum(dNv/dv*sum(Nu*x)) - temp2(1) += ders [ 1 ](1, l) * tmp2(1); // sum(dNv/dv*sum(Nu*y)) - temp2(2) += ders [ 1 ](1, l) * tmp2(1); // sum(dNv/dv*sum(Nu*z)) + temp2[0] += ders [ 1 ](1, l) * tmp2[0]; // sum(dNv/dv*sum(Nu*x)) + temp2[1] += ders [ 1 ](1, l) * tmp2[1]; // sum(dNv/dv*sum(Nu*y)) + temp2[2] += ders [ 1 ](1, l) * tmp2[1]; // sum(dNv/dv*sum(Nu*z)) - temp3(0) += ders [ 1 ](0, l) * tmp2(0); // sum(Nv*sum(Nu*x)) - temp3(1) += ders [ 1 ](0, l) * tmp2(1); // sum(Nv*sum(Nu*y)) - temp3(2) += ders [ 1 ](0, l) * tmp2(1); // sum(Nv*sum(Nu*z)) + temp3[0] += ders [ 1 ](0, l) * tmp2[0]; // sum(Nv*sum(Nu*x)) + temp3[1] += ders [ 1 ](0, l) * tmp2[1]; // sum(Nv*sum(Nu*y)) + temp3[2] += ders [ 1 ](0, l) * tmp2[1]; // sum(Nv*sum(Nu*z)) } ind = indx + numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ]; - jacobian(0, 0) += ders [ 2 ](0, m) * temp1(0); // dx/du=sum(Nt*sum(Nv*sum(dNu/du*x))) - jacobian(0, 1) += ders [ 2 ](0, m) * temp1(1); // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y))) - jacobian(0, 2) += ders [ 2 ](0, m) * temp1(2); // dz/du=sum(Nt*sum(Nv*sum(dNu/du*z))) + jacobian(0, 0) += ders [ 2 ](0, m) * temp1[0]; // dx/du=sum(Nt*sum(Nv*sum(dNu/du*x))) + jacobian(0, 1) += ders [ 2 ](0, m) * temp1[1]; // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y))) + jacobian(0, 2) += ders [ 2 ](0, m) * temp1[2]; // dz/du=sum(Nt*sum(Nv*sum(dNu/du*z))) - jacobian(1, 0) += ders [ 2 ](0, m) * temp2(0); // dx/dv=sum(Nt*sum(dNv/dv*sum(Nu*x))) - jacobian(1, 1) += ders [ 2 ](0, m) * temp2(1); // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y))) - jacobian(1, 2) += ders [ 2 ](0, m) * temp2(2); // dz/dv=sum(Nt*sum(dNv/dv*sum(Nu*z))) + jacobian(1, 0) += ders [ 2 ](0, m) * temp2[0]; // dx/dv=sum(Nt*sum(dNv/dv*sum(Nu*x))) + jacobian(1, 1) += ders [ 2 ](0, m) * temp2[1]; // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y))) + jacobian(1, 2) += ders [ 2 ](0, m) * temp2[2]; // dz/dv=sum(Nt*sum(dNv/dv*sum(Nu*z))) - jacobian(2, 0) += ders [ 2 ](1, m) * temp3(0); // dx/dt=sum(dNt/dt*sum(Nv*sum(Nu*x))) - jacobian(2, 1) += ders [ 2 ](1, m) * temp3(1); // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y))) - jacobian(2, 2) += ders [ 2 ](1, m) * temp3(2); // dz/dt=sum(dNt/dt*sum(Nv*sum(Nu*z))) + jacobian(2, 0) += ders [ 2 ](1, m) * temp3[0]; // dx/dt=sum(dNt/dt*sum(Nv*sum(Nu*x))) + jacobian(2, 1) += ders [ 2 ](1, m) * temp3[1]; // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y))) + jacobian(2, 2) += ders [ 2 ](1, m) * temp3[2]; // dz/dt=sum(dNt/dt*sum(Nv*sum(Nu*z))) } Jacob = jacobian.giveDeterminant(); @@ -380,22 +340,22 @@ double BSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &l OOFEM_ERROR("evaldNdx - zero Jacobian"); } - cnt = 0; + int cnt = 0; for ( int m = 0; m <= degree [ 2 ]; m++ ) { for ( int l = 0; l <= degree [ 1 ]; l++ ) { for ( int k = 0; k <= degree [ 0 ]; k++ ) { - tmp1(0) = ders [ 0 ](1, k) * ders [ 1 ](0, l) * ders [ 2 ](0, m); // dN/du=dNu/du*Nv*Nt - tmp1(1) = ders [ 0 ](0, k) * ders [ 1 ](1, l) * ders [ 2 ](0, m); // dN/dv=Nu*dNv/dv*Nt - tmp1(2) = ders [ 0 ](0, k) * ders [ 1 ](0, l) * ders [ 2 ](1, m); // dN/dt=Nu*Nv*dNt/dt - answer(cnt, 0) = ( ( jacobian(1, 1) * jacobian(2, 2) - jacobian(1, 2) * jacobian(2, 1) ) * tmp1(0) + - ( jacobian(0, 2) * jacobian(2, 1) - jacobian(0, 1) * jacobian(2, 2) ) * tmp1(1) + - ( jacobian(0, 1) * jacobian(1, 2) - jacobian(0, 2) * jacobian(1, 1) ) * tmp1(2) ) / Jacob; // dN/dx - answer(cnt, 1) = ( ( jacobian(1, 2) * jacobian(2, 0) - jacobian(1, 0) * jacobian(2, 2) ) * tmp1(0) + - ( jacobian(0, 0) * jacobian(2, 2) - jacobian(0, 2) * jacobian(2, 0) ) * tmp1(1) + - ( jacobian(0, 2) * jacobian(1, 0) - jacobian(0, 0) * jacobian(1, 2) ) * tmp1(2) ) / Jacob; // dN/dy - answer(cnt, 2) = ( ( jacobian(1, 0) * jacobian(2, 1) - jacobian(1, 1) * jacobian(2, 0) ) * tmp1(0) + - ( jacobian(0, 1) * jacobian(2, 0) - jacobian(0, 0) * jacobian(2, 1) ) * tmp1(1) + - ( jacobian(0, 0) * jacobian(1, 1) - jacobian(0, 1) * jacobian(1, 0) ) * tmp1(2) ) / Jacob; // dN/dz + tmp1[0] = ders [ 0 ](1, k) * ders [ 1 ](0, l) * ders [ 2 ](0, m); // dN/du=dNu/du*Nv*Nt + tmp1[1] = ders [ 0 ](0, k) * ders [ 1 ](1, l) * ders [ 2 ](0, m); // dN/dv=Nu*dNv/dv*Nt + tmp1[2] = ders [ 0 ](0, k) * ders [ 1 ](0, l) * ders [ 2 ](1, m); // dN/dt=Nu*Nv*dNt/dt + answer(cnt, 0) = ( ( jacobian(1, 1) * jacobian(2, 2) - jacobian(1, 2) * jacobian(2, 1) ) * tmp1[0] + + ( jacobian(0, 2) * jacobian(2, 1) - jacobian(0, 1) * jacobian(2, 2) ) * tmp1[1] + + ( jacobian(0, 1) * jacobian(1, 2) - jacobian(0, 2) * jacobian(1, 1) ) * tmp1[2] ) / Jacob; // dN/dx + answer(cnt, 1) = ( ( jacobian(1, 2) * jacobian(2, 0) - jacobian(1, 0) * jacobian(2, 2) ) * tmp1[0] + + ( jacobian(0, 0) * jacobian(2, 2) - jacobian(0, 2) * jacobian(2, 0) ) * tmp1[1] + + ( jacobian(0, 2) * jacobian(1, 0) - jacobian(0, 0) * jacobian(1, 2) ) * tmp1[2] ) / Jacob; // dN/dy + answer(cnt, 2) = ( ( jacobian(1, 0) * jacobian(2, 1) - jacobian(1, 1) * jacobian(2, 0) ) * tmp1[0] + + ( jacobian(0, 1) * jacobian(2, 0) - jacobian(0, 0) * jacobian(2, 1) ) * tmp1[1] + + ( jacobian(0, 0) * jacobian(1, 1) - jacobian(0, 1) * jacobian(1, 0) ) * tmp1[2] ) / Jacob; // dN/dz cnt++; } } @@ -408,83 +368,81 @@ double BSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &l } -void BSplineInterpolation :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void BSplineInterpolation :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { /* Based on SurfacePoint A3.5 implementation*/ - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; - const FloatArray *vertexCoordsPtr; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); IntArray span(nsd); - int ind, indx, uind, vind, tind; std :: vector< FloatArray > N(nsd); - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } for ( int i = 0; i < nsd; i++ ) { - this->basisFuns(N [ i ], span(i), lcoords(i), degree [ i ], knotVector [ i ]); + this->basisFuns(N [ i ], span[i], lcoords[i], degree [ i ], knotVector [ i ]); } answer.resize(nsd); answer.zero(); if ( nsd == 1 ) { - uind = span(0) - degree [ 0 ]; - ind = uind + 1; + int uind = span[0] - degree [ 0 ]; + int ind = uind + 1; for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - answer(0) += N [ 0 ](k) * vertexCoordsPtr->at(1); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + answer[0] += N [ 0 ][k] * vertexCoords[0]; } } else if ( nsd == 2 ) { FloatArray tmp(nsd); - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - ind = vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int ind = vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); - tmp(0) += N [ 0 ](k) * vertexCoordsPtr->at(1); - tmp(1) += N [ 0 ](k) * vertexCoordsPtr->at(2); + tmp[0] += N [ 0 ][k] * vertexCoords[0]; + tmp[1] += N [ 0 ][k] * vertexCoords[1]; } ind += numberOfControlPoints [ 0 ]; - answer(0) += N [ 1 ](l) * tmp(0); - answer(1) += N [ 1 ](l) * tmp(1); + answer[0] += N [ 1 ][l] * tmp[0]; + answer[1] += N [ 1 ][l] * tmp[1]; } } else if ( nsd == 3 ) { FloatArray tmp(nsd), temp(nsd); - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - tind = span(2) - degree [ 2 ]; - ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int tind = span[2] - degree [ 2 ]; + int ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int m = 0; m <= degree [ 2 ]; m++ ) { temp.zero(); - indx = ind; + int indx = ind; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - tmp.add(N [ 0 ](k), *vertexCoordsPtr); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + tmp.add(N [ 0 ][k], vertexCoords); } ind += numberOfControlPoints [ 0 ]; - temp.add(N [ 1 ](l), tmp); + temp.add(N [ 1 ][l], tmp); } ind = indx + numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ]; - answer.add(N [ 2 ](m), temp); + answer.add(N [ 2 ][m], temp); } } else { OOFEM_ERROR("local2global not implemented for nsd = %d", nsd); @@ -492,84 +450,82 @@ void BSplineInterpolation :: local2global(FloatArray &answer, const FloatArray & } -void BSplineInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void BSplineInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; - const FloatArray *vertexCoordsPtr; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); IntArray span(nsd); - int indx, ind, uind, vind, tind; std :: vector< FloatMatrix > ders(nsd); jacobian.resize(nsd, nsd); - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } for ( int i = 0; i < nsd; i++ ) { - this->dersBasisFuns(1, lcoords(i), span(i), degree [ i ], knotVector [ i ], ders [ i ]); + this->dersBasisFuns(1, lcoords[i], span[i], degree [ i ], knotVector [ i ], ders [ i ]); } jacobian.zero(); if ( nsd == 1 ) { - uind = span(0) - degree [ 0 ]; - ind = uind + 1; + int uind = span[0] - degree [ 0 ]; + int ind = uind + 1; for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - jacobian(0, 0) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1); // dx/du=sum(dNu/du*x) + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + jacobian(0, 0) += ders [ 0 ](1, k) * vertexCoords[0]; // dx/du=sum(dNu/du*x) } } else if ( nsd == 2 ) { FloatArray tmp1(nsd), tmp2(nsd); - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - ind = vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int ind = vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp1.zero(); tmp2.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); - tmp1(0) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1); // sum(dNu/du*x) - tmp1(1) += ders [ 0 ](1, k) * vertexCoordsPtr->at(2); // sum(dNu/du*y) + tmp1[0] += ders [ 0 ](1, k) * vertexCoords[0]; // sum(dNu/du*x) + tmp1[1] += ders [ 0 ](1, k) * vertexCoords[1]; // sum(dNu/du*y) - tmp2(0) += ders [ 0 ](0, k) * vertexCoordsPtr->at(1); // sum(Nu*x) - tmp2(1) += ders [ 0 ](0, k) * vertexCoordsPtr->at(2); // sum(Nu*y) + tmp2[0] += ders [ 0 ](0, k) * vertexCoords[0]; // sum(Nu*x) + tmp2[1] += ders [ 0 ](0, k) * vertexCoords[1]; // sum(Nu*y) } ind += numberOfControlPoints [ 0 ]; - jacobian(0, 0) += ders [ 1 ](0, l) * tmp1(0); // dx/du=sum(Nv*sum(dNu/du*x)) - jacobian(0, 1) += ders [ 1 ](0, l) * tmp1(1); // dy/du=sum(Nv*sum(dNu/du*y)) + jacobian(0, 0) += ders [ 1 ](0, l) * tmp1[0]; // dx/du=sum(Nv*sum(dNu/du*x)) + jacobian(0, 1) += ders [ 1 ](0, l) * tmp1[1]; // dy/du=sum(Nv*sum(dNu/du*y)) - jacobian(1, 0) += ders [ 1 ](1, l) * tmp2(0); // dx/dv=sum(dNv/dv*sum(Nu*x)) - jacobian(1, 1) += ders [ 1 ](1, l) * tmp2(1); // dy/dv=sum(dNv/dv*sum(Nu*y)) + jacobian(1, 0) += ders [ 1 ](1, l) * tmp2[0]; // dx/dv=sum(dNv/dv*sum(Nu*x)) + jacobian(1, 1) += ders [ 1 ](1, l) * tmp2[1]; // dy/dv=sum(dNv/dv*sum(Nu*y)) } } else if ( nsd == 3 ) { FloatArray tmp1(nsd), tmp2(nsd); FloatArray temp1(nsd), temp2(nsd), temp3(nsd); - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - tind = span(2) - degree [ 2 ]; - ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int tind = span[2] - degree [ 2 ]; + int ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int m = 0; m <= degree [ 2 ]; m++ ) { temp1.zero(); temp2.zero(); temp3.zero(); - indx = ind; + int indx = ind; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp1.zero(); tmp2.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); - tmp1.add(ders [ 0 ](1, k), *vertexCoordsPtr); // sum(dNu/du*x) - tmp2.add(ders [ 0 ](0, k), *vertexCoordsPtr); // sum(Nu*x) + tmp1.add(ders [ 0 ](1, k), vertexCoords); // sum(dNu/du*x) + tmp2.add(ders [ 0 ](0, k), vertexCoords); // sum(Nu*x) } ind += numberOfControlPoints [ 0 ]; @@ -581,17 +537,17 @@ void BSplineInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const F ind = indx + numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ]; - jacobian(0, 0) += ders [ 2 ](0, m) * temp1(0); // dx/du=sum(Nt*sum(Nv*sum(dNu/du*x))) - jacobian(0, 1) += ders [ 2 ](0, m) * temp1(1); // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y))) - jacobian(0, 2) += ders [ 2 ](0, m) * temp1(2); // dz/du=sum(Nt*sum(Nv*sum(dNu/du*z))) + jacobian(0, 0) += ders [ 2 ](0, m) * temp1[0]; // dx/du=sum(Nt*sum(Nv*sum(dNu/du*x))) + jacobian(0, 1) += ders [ 2 ](0, m) * temp1[1]; // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y))) + jacobian(0, 2) += ders [ 2 ](0, m) * temp1[2]; // dz/du=sum(Nt*sum(Nv*sum(dNu/du*z))) - jacobian(1, 0) += ders [ 2 ](0, m) * temp2(0); // dx/dv=sum(Nt*sum(dNv/dv*sum(Nu*x))) - jacobian(1, 1) += ders [ 2 ](0, m) * temp2(1); // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y))) - jacobian(1, 2) += ders [ 2 ](0, m) * temp2(2); // dz/dv=sum(Nt*sum(dNv/dv*sum(Nu*z))) + jacobian(1, 0) += ders [ 2 ](0, m) * temp2[0]; // dx/dv=sum(Nt*sum(dNv/dv*sum(Nu*x))) + jacobian(1, 1) += ders [ 2 ](0, m) * temp2[1]; // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y))) + jacobian(1, 2) += ders [ 2 ](0, m) * temp2[2]; // dz/dv=sum(Nt*sum(dNv/dv*sum(Nu*z))) - jacobian(2, 0) += ders [ 2 ](1, m) * temp3(0); // dx/dt=sum(dNt/dt*sum(Nv*sum(Nu*x))) - jacobian(2, 1) += ders [ 2 ](1, m) * temp3(1); // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y))) - jacobian(2, 2) += ders [ 2 ](1, m) * temp3(2); // dz/dt=sum(dNt/dt*sum(Nv*sum(Nu*z))) + jacobian(2, 0) += ders [ 2 ](1, m) * temp3[0]; // dx/dt=sum(dNt/dt*sum(Nv*sum(Nu*x))) + jacobian(2, 1) += ders [ 2 ](1, m) * temp3[1]; // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y))) + jacobian(2, 2) += ders [ 2 ](1, m) * temp3[2]; // dz/dt=sum(dNt/dt*sum(Nv*sum(Nu*z))) } } else { OOFEM_ERROR("giveTransformationJacobian not implemented for nsd = %d", nsd); @@ -599,33 +555,32 @@ void BSplineInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const F } -int BSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask) +int BSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask) const { - int size, c = 1, iindx, jindx, kindx; - - size = giveNumberOfKnotSpanBasisFunctions(knotSpan); + int c = 1; + int size = giveNumberOfKnotSpanBasisFunctions(knotSpan); mask.resize(size); if ( nsd == 1 ) { for ( int i = 0; i <= degree [ 0 ]; i++ ) { - iindx = ( i + knotSpan(0) - degree [ 0 ] ); + int iindx = ( i + knotSpan[0] - degree [ 0 ] ); mask.at(c++) = iindx + 1; } } else if ( nsd == 2 ) { for ( int j = 0; j <= degree [ 1 ]; j++ ) { - jindx = ( j + knotSpan(1) - degree [ 1 ] ); + int jindx = ( j + knotSpan[1] - degree [ 1 ] ); for ( int i = 0; i <= degree [ 0 ]; i++ ) { - iindx = ( i + knotSpan(0) - degree [ 0 ] ); + int iindx = ( i + knotSpan[0] - degree [ 0 ] ); mask.at(c++) = jindx * numberOfControlPoints [ 0 ] + iindx + 1; } } } else if ( nsd == 3 ) { for ( int k = 0; k <= degree [ 2 ]; k++ ) { - kindx = ( k + knotSpan(2) - degree [ 2 ] ); + int kindx = ( k + knotSpan[2] - degree [ 2 ] ); for ( int j = 0; j <= degree [ 1 ]; j++ ) { - jindx = ( j + knotSpan(1) - degree [ 1 ] ); + int jindx = ( j + knotSpan[1] - degree [ 1 ] ); for ( int i = 0; i <= degree [ 0 ]; i++ ) { - iindx = ( i + knotSpan(0) - degree [ 0 ] ); + int iindx = ( i + knotSpan[0] - degree [ 0 ] ); mask.at(c++) = kindx * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + jindx * numberOfControlPoints [ 0 ] + iindx + 1; } } @@ -638,7 +593,7 @@ int BSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &knotSpan, // for pure Bspline the number of nonzero basis functions is the same for each knot span -int BSplineInterpolation :: giveNumberOfKnotSpanBasisFunctions(const IntArray &knotSpan) +int BSplineInterpolation :: giveNumberOfKnotSpanBasisFunctions(const IntArray &knotSpan) const { int answer = 1; // there are always degree+1 nonzero basis functions on each knot span @@ -657,28 +612,27 @@ int BSplineInterpolation :: giveNumberOfKnotSpanBasisFunctions(const IntArray &k // it is also redundant to pass the span which can be calculated // but we want to profit from knowing the span a priori -void BSplineInterpolation :: basisFuns(FloatArray &N, int span, double u, int p, const double *U) +void BSplineInterpolation :: basisFuns(FloatArray &N, int span, double u, int p, const FloatArray &U) const { // // Based on Algorithm A2.2 (p. 70) // FloatArray right(p + 1); FloatArray left(p + 1); - double saved, temp; N.resize(p + 1); - N(0) = 1.0; + N[0] = 1.0; for ( int j = 1; j <= p; j++ ) { - left(j) = u - U [ span + 1 - j ]; - right(j) = U [ span + j ] - u; - saved = 0.0; + left[j] = u - U [ span + 1 - j ]; + right[j] = U [ span + j ] - u; + double saved = 0.0; for ( int r = 0; r < j; r++ ) { - temp = N(r) / ( right(r + 1) + left(j - r) ); - N(r) = saved + right(r + 1) * temp; + double temp = N[r] / ( right(r + 1) + left(j - r) ); + N[r] = saved + right(r + 1) * temp; saved = left(j - r) * temp; } - N(j) = saved; + N[j] = saved; } } @@ -689,7 +643,7 @@ void BSplineInterpolation :: basisFuns(FloatArray &N, int span, double u, int p, // it is also redundant to pass the span which can be calculated // but we want to profit from knowing the span a priori -void BSplineInterpolation :: dersBasisFuns(int n, double u, int span, int p, double *const U, FloatMatrix &ders) +void BSplineInterpolation :: dersBasisFuns(int n, double u, int span, int p, const FloatArray &U, FloatMatrix &ders) const { // // Based on Algorithm A2.3 (p. 72) @@ -697,20 +651,19 @@ void BSplineInterpolation :: dersBasisFuns(int n, double u, int span, int p, dou FloatArray left(p + 1); FloatArray right(p + 1); FloatMatrix ndu(p + 1, p + 1); - double saved, temp; ders.resize(n + 1, p + 1); ndu(0, 0) = 1.0; for ( int j = 1; j <= p; j++ ) { - left(j) = u - U [ span + 1 - j ]; - right(j) = U [ span + j ] - u; - saved = 0.0; + left[j] = u - U [ span + 1 - j ]; + right[j] = U [ span + j ] - u; + double saved = 0.0; for ( int r = 0; r < j; r++ ) { // Lower triangle ndu(j, r) = right(r + 1) + left(j - r); - temp = ndu(r, j - 1) / ndu(j, r); + double temp = ndu(r, j - 1) / ndu(j, r); // Upper triangle ndu(r, j) = saved + right(r + 1) * temp; saved = left(j - r) * temp; @@ -789,7 +742,7 @@ void BSplineInterpolation :: dersBasisFuns(int n, double u, int span, int p, dou // jaky ma vyznam const = ve funkci se objekt nesmi zmenit -int BSplineInterpolation :: findSpan(int n, int p, double u, const double *U) const +int BSplineInterpolation :: findSpan(int n, int p, double u, const FloatArray &U) const { if ( u == U [ n + 1 ] ) { return n; diff --git a/src/oofemlib/iga/feibspline.h b/src/oofemlib/iga/feibspline.h index eddbb8674..d801c0214 100644 --- a/src/oofemlib/iga/feibspline.h +++ b/src/oofemlib/iga/feibspline.h @@ -37,6 +37,7 @@ #include "feinterpol.h" #include "floatarray.h" +#include ///@name Input fields for BSplineInterpolation //@{ @@ -63,28 +64,27 @@ class OOFEM_EXPORT BSplineInterpolation : public FEInterpolation /// Number of spatial directions. int nsd; /// Degree in each direction. - int *degree; // eg. 2 + std::array degree; // eg. 2 /// Knot values [nsd] - FloatArray *knotValues; // eg. 0 1 2 3 4 5 + std::array knotValues; // eg. 0 1 2 3 4 5 /// Knot multiplicity [nsd] - IntArray *knotMultiplicity; // eg. 3 1 1 1 2 3 + std::array knotMultiplicity; // eg. 3 1 1 1 2 3 /// numberOfControlPoints[nsd] /** * For TSpline this is filled by values corresponding to case when there are no T-junctions * (i.e. TSpline = BSpline) */ - int *numberOfControlPoints; + std::array numberOfControlPoints; /// Knot vectors [nsd][knot_vector_size] - double **knotVector; // eg. 0 0 0 1 2 3 4 4 5 5 5 + std::array knotVector; // eg. 0 0 0 1 2 3 4 4 5 5 5 /// Nonzero spans in each directions [nsd] - int *numberOfKnotSpans; // eg. 5 (0-1,1-2,2-3,3-4,4-5) + std::array numberOfKnotSpans; // eg. 5 (0-1,1-2,2-3,3-4,4-5) public: - BSplineInterpolation(int nsd) : FEInterpolation(0) { - this->nsd = nsd; - } - virtual ~BSplineInterpolation(); + BSplineInterpolation(int nsd) : FEInterpolation(0), + nsd(nsd) + {} - virtual integrationDomain giveIntegrationDomain() const { + integrationDomain giveIntegrationDomain() const override { if ( nsd == 3 ) { return _Cube; } else if ( nsd == 2 ) { @@ -95,9 +95,9 @@ class OOFEM_EXPORT BSplineInterpolation : public FEInterpolation return _UnknownIntegrationDomain; } } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_unknown; } + Element_Geometry_Type giveGeometryType() const override { return EGT_unknown; } - virtual integrationDomain giveBoundaryIntegrationDomain(int ib) const { + integrationDomain giveBoundaryIntegrationDomain(int ib) const override { if ( nsd == 3 ) { return _Square; } else if ( nsd == 2 ) { @@ -108,7 +108,7 @@ class OOFEM_EXPORT BSplineInterpolation : public FEInterpolation return _UnknownIntegrationDomain; } } - virtual integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const { + integrationDomain giveBoundarySurfaceIntegrationDomain(int isurf) const override { if ( nsd == 3 ) { return _Square; } else if ( nsd == 2 ) { @@ -117,7 +117,7 @@ class OOFEM_EXPORT BSplineInterpolation : public FEInterpolation return _UnknownIntegrationDomain; } } - virtual integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const { + integrationDomain giveBoundaryEdgeIntegrationDomain(int iedge) const override { if ( nsd >= 2 ) { return _Line; } else { @@ -125,89 +125,75 @@ class OOFEM_EXPORT BSplineInterpolation : public FEInterpolation } } + int giveNsd() const override { return nsd; } + void initializeFrom(InputRecord &ir) override; - - virtual int giveNsd() { return nsd; } - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual void boundaryEdgeGiveNodes(IntArray &answer, int boundary) - { OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) + IntArray boundaryEdgeGiveNodes(int boundary) const override + { OOFEM_ERROR("Functions not supported for this interpolator."); return {}; } + void boundaryEdgeEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) - { OOFEM_ERROR("Functions not supported for this interpolator."); - return 0.; } - virtual void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) + double boundaryEdgeGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override + { OOFEM_ERROR("Functions not supported for this interpolator."); return 0.; } + void boundaryEdgeLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } /**@name Surface interpolation services */ //@{ - virtual void boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) {OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual void boundarySurfaceEvaldNdx(FloatMatrix &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + void boundarySurfaceEvalN(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual double boundarySurfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + void boundarySurfaceEvaldNdx(FloatMatrix &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual void boundarySurfaceLocal2global(FloatArray &answer, int isurf, - const FloatArray &lcoords, const FEICellGeometry &cellgeo) + double boundarySurfaceEvalNormal(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual double boundarySurfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, - const FEICellGeometry &cellgeo) + void boundarySurfaceLocal2global(FloatArray &answer, int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } - virtual void boundarySurfaceGiveNodes(IntArray &answer, int boundary) + double boundarySurfaceGiveTransformationJacobian(int isurf, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Functions not supported for this interpolator."); } - + IntArray boundarySurfaceGiveNodes(int boundary) const override + { OOFEM_ERROR("Functions not supported for this interpolator."); return {}; } //@} - - - virtual void boundaryGiveNodes(IntArray &answer, int boundary) - { OOFEM_ERROR("Not implemented"); } - virtual void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) + IntArray boundaryGiveNodes(int boundary) const override + { OOFEM_ERROR("Not implemented"); return {}; } + void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Not implemented"); } - virtual double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) - { OOFEM_ERROR("Not implemented"); - return 0.; } - virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) - { OOFEM_ERROR("boundaryGiveTransformationJacobian - Not implemented"); - return 0.; } - virtual void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) + double boundaryEvalNormal(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override + { OOFEM_ERROR("Not implemented"); return 0.; } + double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override + { OOFEM_ERROR("boundaryGiveTransformationJacobian - Not implemented"); return 0.; } + void boundaryLocal2Global(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("boundaryLocal2Global - Not implemented"); } - virtual int giveNumberOfKnotSpans(int dim) { return numberOfKnotSpans [ dim - 1 ]; } - virtual int giveNumberOfControlPoints(int dim) { return numberOfControlPoints [ dim - 1 ]; } - virtual const double *const *giveKnotVector() { - return this->knotVector; + int giveNumberOfKnotSpans(int dim) const override { return numberOfKnotSpans [ dim - 1 ]; } + virtual int giveNumberOfControlPoints(int dim) const { return numberOfControlPoints [ dim - 1 ]; } + const FloatArray *giveKnotVector() const override { + return this->knotVector.data(); } - virtual const IntArray *giveKnotMultiplicity(int dim) { return & this->knotMultiplicity [ dim - 1 ]; } - virtual const FloatArray *giveKnotValues(int dim) { return & this->knotValues [ dim - 1 ]; } - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { + const IntArray *giveKnotMultiplicity(int dim) const override { return & this->knotMultiplicity [ dim - 1 ]; } + const FloatArray *giveKnotValues(int dim) const override { return & this->knotValues [ dim - 1 ]; } + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Not yet implemented."); return 0; } - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask); - virtual int giveNumberOfKnotSpanBasisFunctions(const IntArray &knotSpan); + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask) const override; + int giveNumberOfKnotSpanBasisFunctions(const IntArray &knotSpan) const override; - virtual const char *giveClassName() const { return "BSplineInterpolation"; } - virtual bool hasSubPatchFormulation() { return true; } + const char *giveClassName() const { return "BSplineInterpolation"; } + bool hasSubPatchFormulation() const override { return true; } - virtual IntegrationRule *giveIntegrationRule(int order) - { OOFEM_ERROR("Not supported."); - return NULL; } - virtual IntegrationRule *giveBoundaryIntegrationRule(int order, int boundary) - { OOFEM_ERROR("Not supported."); - return NULL; } - virtual IntegrationRule *giveBoundaryEdgeIntegrationRule(int order, int boundary) - { OOFEM_ERROR("Not supported."); - return NULL; } + std::unique_ptr giveIntegrationRule(int order) const override + { OOFEM_ERROR("Not supported."); return nullptr; } + std::unique_ptr giveBoundaryIntegrationRule(int order, int boundary) const override + { OOFEM_ERROR("Not supported."); return nullptr; } + std::unique_ptr giveBoundaryEdgeIntegrationRule(int order, int boundary) const override + { OOFEM_ERROR("Not supported."); return nullptr; } protected: /** @@ -219,7 +205,7 @@ class OOFEM_EXPORT BSplineInterpolation : public FEInterpolation * @param N Computed p+1 nonvanishing functions (N_{span-p,p}-N_{span,p}) * @warning Parameter u and span must be in a valid range. */ - void basisFuns(FloatArray &N, int span, double u, int p, const double *U); + void basisFuns(FloatArray &N, int span, double u, int p, const FloatArray &U) const; /** * Computes nonzero basis functions and their derivatives at u. * @@ -241,7 +227,7 @@ class OOFEM_EXPORT BSplineInterpolation : public FEInterpolation * * @warning Parameters n, u and span must be in a valid range. */ - void dersBasisFuns(int n, double u, int span, int p, double *const U, FloatMatrix &ders); + void dersBasisFuns(int n, double u, int span, int p, const FloatArray &U, FloatMatrix &ders) const; /** * Determines the knot span index (Algorithm A2.1 from the NURBS book) * @@ -256,11 +242,11 @@ class OOFEM_EXPORT BSplineInterpolation : public FEInterpolation * @return Span index at u (zero based). * @warning Parameter u must be in a valid range. */ - int findSpan(int n, int p, double u, const double *U) const; + int findSpan(int n, int p, double u, const FloatArray &U) const; /** * Returns the range of nonzero basis functions for given knot span and given degree. */ - void giveNonzeroBasisFuncInterval(int span, int deg, int &s, int &e) { + void giveNonzeroBasisFuncInterval(int span, int deg, int &s, int &e) const { s = span - deg; e = span; } diff --git a/src/oofemlib/iga/feinurbs.C b/src/oofemlib/iga/feinurbs.C index 3f209a323..a1b10a2aa 100644 --- a/src/oofemlib/iga/feinurbs.C +++ b/src/oofemlib/iga/feinurbs.C @@ -41,62 +41,67 @@ namespace oofem { // optimized version of A4.4 for d=1 #define OPTIMIZED_VERSION_A4dot4 +void +NURBSInterpolation :: initializeFrom(InputRecord &ir) +{ + BSplineInterpolation :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, weights, _IFT_NURBSInterpolation_weights); +} -NURBSInterpolation :: ~NURBSInterpolation() { } - - -void NURBSInterpolation :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) + +void NURBSInterpolation :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); IntArray span(nsd); double sum = 0.0, val; - int count, c = 1, ind, indx, uind, vind, tind; + int count, c = 1; std :: vector< FloatArray >N; - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } for ( int i = 0; i < nsd; i++ ) { - this->basisFuns(N [ i ], span(i), lcoords(i), degree [ i ], knotVector [ i ]); + this->basisFuns(N [ i ], span[i], lcoords[i], degree [ i ], knotVector [ i ]); } count = giveNumberOfKnotSpanBasisFunctions(span); answer.resize(count); if ( nsd == 1 ) { - uind = span(0) - degree [ 0 ]; - ind = uind + 1; + int uind = span[0] - degree [ 0 ]; + int ind = uind + 1; for ( int k = 0; k <= degree [ 0 ]; k++ ) { - answer.at(c++) = val = N [ 0 ](k) * cellgeo.giveVertexCoordinates(ind + k)->at(2); // Nu*w + answer.at(c++) = val = N [ 0 ][k] * weights.at(ind + k); // Nu*w sum += val; } } else if ( nsd == 2 ) { - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - ind = vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int ind = vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int l = 0; l <= degree [ 1 ]; l++ ) { for ( int k = 0; k <= degree [ 0 ]; k++ ) { - answer.at(c++) = val = N [ 0 ](k) * N [ 1 ](l) * cellgeo.giveVertexCoordinates(ind + k)->at(3); // Nu*Nv*w + answer.at(c++) = val = N [ 0 ][k] * N [ 1 ][l] * weights.at(ind + k); // Nu*Nv*w sum += val; } ind += numberOfControlPoints [ 0 ]; } } else if ( nsd == 3 ) { - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - tind = span(2) - degree [ 2 ]; - ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int tind = span[2] - degree [ 2 ]; + int ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int m = 0; m <= degree [ 2 ]; m++ ) { - indx = ind; + int indx = ind; for ( int l = 0; l <= degree [ 1 ]; l++ ) { for ( int k = 0; k <= degree [ 0 ]; k++ ) { - answer.at(c++) = val = N [ 0 ](k) * N [ 1 ](l) * N [ 2 ](m) * cellgeo.giveVertexCoordinates(ind + k)->at(4); // Nu*Nv*Nt*w + answer.at(c++) = val = N [ 0 ][k] * N [ 1 ][l] * N [ 2 ][m] * weights.at(ind + k); // Nu*Nv*Nt*w sum += val; } @@ -109,33 +114,30 @@ void NURBSInterpolation :: evalN(FloatArray &answer, const FloatArray &lcoords, OOFEM_ERROR("not implemented for nsd = %d", nsd); } - while ( count ) { - answer.at(count--) /= sum; - } + answer.times(1./sum); } -double NURBSInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double NURBSInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; - const FloatArray *vertexCoordsPtr; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); FloatMatrix jacobian(nsd, nsd); IntArray span(nsd); - double Jacob = 0., product, w, weight; - int count, cnt, ind, indx, uind, vind, tind; + double Jacob = 0.; + int count; std :: vector< FloatArray > N(nsd); std :: vector< FloatMatrix > ders(nsd); - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } for ( int i = 0; i < nsd; i++ ) { - this->dersBasisFuns(1, lcoords(i), span(i), degree [ i ], knotVector [ i ], ders [ i ]); + this->dersBasisFuns(1, lcoords[i], span[i], degree [ i ], knotVector [ i ], ders [ i ]); } count = giveNumberOfKnotSpanBasisFunctions(span); @@ -171,41 +173,41 @@ double NURBSInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lco // calculation of jacobian matrix according to A4.4 // calculate values and derivatives of nonrational Bspline surface with weights at first (Aders, wders) - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - ind = vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int ind = vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp1.zero(); tmp2.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - w = vertexCoordsPtr->at(3); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + double w = this->weights.at(ind + k); - tmp1(0) += ders [ 0 ](0, k) * vertexCoordsPtr->at(1) * w; // sum(Nu*x*w) - tmp1(1) += ders [ 0 ](0, k) * vertexCoordsPtr->at(2) * w; // sum(Nu*y*w) - tmp1(2) += ders [ 0 ](0, k) * w; // sum(Nu*w) + tmp1[0] += ders [ 0 ](0, k) * vertexCoords[0] * w; // sum(Nu*x*w) + tmp1[1] += ders [ 0 ](0, k) * vertexCoords[1] * w; // sum(Nu*y*w) + tmp1[2] += ders [ 0 ](0, k) * w; // sum(Nu*w) - tmp2(0) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1) * w; // sum(dNu/du*x*w) - tmp2(1) += ders [ 0 ](1, k) * vertexCoordsPtr->at(2) * w; // sum(dNu/du*y*w) - tmp2(2) += ders [ 0 ](1, k) * w; // sum(dNu/du*w) + tmp2[0] += ders [ 0 ](1, k) * vertexCoords[0] * w; // sum(dNu/du*x*w) + tmp2[1] += ders [ 0 ](1, k) * vertexCoords[1] * w; // sum(dNu/du*y*w) + tmp2[2] += ders [ 0 ](1, k) * w; // sum(dNu/du*w) } ind += numberOfControlPoints [ 0 ]; - Aders [ 0 ](0, 0) += ders [ 1 ](0, l) * tmp1(0); // xw=sum(Nv*sum(Nu*x*w)) - Aders [ 1 ](0, 0) += ders [ 1 ](0, l) * tmp1(1); // yw=sum(Nv*sum(Nu*y*w)) - wders(0, 0) += ders [ 1 ](0, l) * tmp1(2); // w=sum(Nv*sum(Nu*w)) + Aders [ 0 ](0, 0) += ders [ 1 ](0, l) * tmp1[0]; // xw=sum(Nv*sum(Nu*x*w)) + Aders [ 1 ](0, 0) += ders [ 1 ](0, l) * tmp1[1]; // yw=sum(Nv*sum(Nu*y*w)) + wders(0, 0) += ders [ 1 ](0, l) * tmp1[2]; // w=sum(Nv*sum(Nu*w)) - Aders [ 0 ](0, 1) += ders [ 1 ](1, l) * tmp1(0); // dxw/dv=sum(dNv/dv*sum(Nu*x*w)) - Aders [ 1 ](0, 1) += ders [ 1 ](1, l) * tmp1(1); // dyw/dv=sum(dNv/dv*sum(Nu*y*w)) - wders(0, 1) += ders [ 1 ](1, l) * tmp1(2); // dw/dv=sum(dNv/dv*sum(Nu*w)) + Aders [ 0 ](0, 1) += ders [ 1 ](1, l) * tmp1[0]; // dxw/dv=sum(dNv/dv*sum(Nu*x*w)) + Aders [ 1 ](0, 1) += ders [ 1 ](1, l) * tmp1[1]; // dyw/dv=sum(dNv/dv*sum(Nu*y*w)) + wders(0, 1) += ders [ 1 ](1, l) * tmp1[2]; // dw/dv=sum(dNv/dv*sum(Nu*w)) - Aders [ 0 ](1, 0) += ders [ 1 ](0, l) * tmp2(0); // dxw/du=sum(Nv*sum(dNu/du*x*w)) - Aders [ 1 ](1, 0) += ders [ 1 ](0, l) * tmp2(1); // dyw/du=sum(Nv*sum(dNu/du*y*w)) - wders(1, 0) += ders [ 1 ](0, l) * tmp2(2); // dw/du=sum(Nv*sum(dNu/du*w)) + Aders [ 0 ](1, 0) += ders [ 1 ](0, l) * tmp2[0]; // dxw/du=sum(Nv*sum(dNu/du*x*w)) + Aders [ 1 ](1, 0) += ders [ 1 ](0, l) * tmp2[1]; // dyw/du=sum(Nv*sum(dNu/du*y*w)) + wders(1, 0) += ders [ 1 ](0, l) * tmp2[2]; // dw/du=sum(Nv*sum(dNu/du*w)) } - weight = wders(0, 0); + double weight = wders(0, 0); #ifndef OPTIMIZED_VERSION_A4dot4 const int d = 1; @@ -213,28 +215,28 @@ double NURBSInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lco // since all entries in Pascal triangle up to d=1 are 1, binomial coefficients are ignored for ( int k = 0; k <= d; k++ ) { for ( int l = 0; l <= d - k; l++ ) { - tmp1(0) = Aders [ 0 ](k, l); - tmp1(1) = Aders [ 1 ](k, l); + tmp1[0] = Aders [ 0 ](k, l); + tmp1[1] = Aders [ 1 ](k, l); for ( j = 1; j <= l; j++ ) { - tmp1(0) -= wders(0, j) * Sders [ 0 ](k, l - j); // *Bin(l,j) - tmp1(1) -= wders(0, j) * Sders [ 1 ](k, l - j); // *Bin(l,j) + tmp1[0] -= wders(0, j) * Sders [ 0 ](k, l - j); // *Bin(l,j) + tmp1[1] -= wders(0, j) * Sders [ 1 ](k, l - j); // *Bin(l,j) } for ( int i = 1; i <= k; i++ ) { - tmp1(0) -= wders(i, 0) * Sders [ 0 ](k - i, l); // *Bin(k,i) - tmp1(1) -= wders(i, 0) * Sders [ 1 ](k - i, l); // *Bin(k,i) + tmp1[0] -= wders(i, 0) * Sders [ 0 ](k - i, l); // *Bin(k,i) + tmp1[1] -= wders(i, 0) * Sders [ 1 ](k - i, l); // *Bin(k,i) tmp2.zero(); for ( int j = 1; j <= l; j++ ) { - tmp2(0) += wders(i, j) * Sders [ 0 ](k - i, l - j); // *Bin(l,j) - tmp2(1) += wders(i, j) * Sders [ 1 ](k - i, l - j); // *Bin(l,j) + tmp2[0] += wders(i, j) * Sders [ 0 ](k - i, l - j); // *Bin(l,j) + tmp2[1] += wders(i, j) * Sders [ 1 ](k - i, l - j); // *Bin(l,j) } - tmp1(0) -= tmp2(0); // *Bin(k,i) - tmp1(1) -= tmp2(1); // *Bin(k,i) + tmp1[0] -= tmp2[0]; // *Bin(k,i) + tmp1[1] -= tmp2[1]; // *Bin(k,i) } - Sders [ 0 ](k, l) = tmp1(0) / weight; - Sders [ 1 ](k, l) = tmp1(1) / weight; + Sders [ 0 ](k, l) = tmp1[0] / weight; + Sders [ 1 ](k, l) = tmp1[1] / weight; } } @@ -263,32 +265,32 @@ double NURBSInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lco */ // k=0 l=0 loop - tmp1(0) = Aders [ 0 ](0, 0) / weight; - tmp1(1) = Aders [ 1 ](0, 0) / weight; + tmp1[0] = Aders [ 0 ](0, 0) / weight; + tmp1[1] = Aders [ 1 ](0, 0) / weight; // k=1 l=0 loop - jacobian(0, 0) = ( Aders [ 0 ](1, 0) - wders(1, 0) * tmp1(0) ) / weight; // dx/du - jacobian(0, 1) = ( Aders [ 1 ](1, 0) - wders(1, 0) * tmp1(1) ) / weight; // dy/du + jacobian(0, 0) = ( Aders [ 0 ](1, 0) - wders(1, 0) * tmp1[0] ) / weight; // dx/du + jacobian(0, 1) = ( Aders [ 1 ](1, 0) - wders(1, 0) * tmp1[1] ) / weight; // dy/du // k=0 l=1 loop - jacobian(1, 0) = ( Aders [ 0 ](0, 1) - wders(0, 1) * tmp1(0) ) / weight; // dx/dv - jacobian(1, 1) = ( Aders [ 1 ](0, 1) - wders(0, 1) * tmp1(1) ) / weight; // dy/dv + jacobian(1, 0) = ( Aders [ 0 ](0, 1) - wders(0, 1) * tmp1[0] ) / weight; // dx/dv + jacobian(1, 1) = ( Aders [ 1 ](0, 1) - wders(0, 1) * tmp1[1] ) / weight; // dy/dv #endif Jacob = jacobian.giveDeterminant(); //calculation of derivatives of NURBS basis functions with respect to local parameters is not covered by NURBS book - product = Jacob * weight * weight; - cnt = 0; + double product = Jacob * weight * weight; + int cnt = 0; ind = vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int l = 0; l <= degree [ 1 ]; l++ ) { for ( int k = 0; k <= degree [ 0 ]; k++ ) { - w = cellgeo.giveVertexCoordinates(ind + k)->at(3); + double w = weights.at(ind + k); // dNu/du*Nv*w*sum(Nv*Nu*w) - Nu*Nv*w*sum(dNu/du*Nv*w) - tmp1(0) = ders [ 0 ](1, k) * ders [ 1 ](0, l) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * w * wders(1, 0); + tmp1[0] = ders [ 0 ](1, k) * ders [ 1 ](0, l) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * w * wders(1, 0); // Nu*dNv/dv*w*sum(Nv*Nu*w) - Nu*Nv*w*sum(Nu*dNv/dv*w) - tmp1(1) = ders [ 0 ](0, k) * ders [ 1 ](1, l) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * w * wders(0, 1); + tmp1[1] = ders [ 0 ](0, k) * ders [ 1 ](1, l) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * w * wders(0, 1); - answer(cnt, 0) = ( +jacobian(1, 1) * tmp1(0) - jacobian(0, 1) * tmp1(1) ) / product; - answer(cnt, 1) = ( -jacobian(1, 0) * tmp1(0) + jacobian(0, 0) * tmp1(1) ) / product; + answer(cnt, 0) = ( +jacobian(1, 1) * tmp1[0] - jacobian(0, 1) * tmp1[1] ) / product; + answer(cnt, 1) = ( -jacobian(1, 0) * tmp1[0] + jacobian(0, 0) * tmp1[1] ) / product; cnt++; } @@ -312,100 +314,100 @@ double NURBSInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lco if ( nsd == 1 ) { // calculate values and derivatives of nonrational Bspline curve with weights at first (Aders, wders) - uind = span(0) - degree [ 0 ]; - ind = uind + 1; + int uind = span[0] - degree [ 0 ]; + int ind = uind + 1; for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - w = vertexCoordsPtr->at(2); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + double w = this->weights.at(ind + k); - Aders [ 0 ](0) += ders [ 0 ](0, k) * vertexCoordsPtr->at(1) * w; // xw=sum(Nu*x*w) - wders(0) += ders [ 0 ](0, k) * w; // w=sum(Nu*w) + Aders [ 0 ][0] += ders [ 0 ](0, k) * vertexCoords[0] * w; // xw=sum(Nu*x*w) + wders[0] += ders [ 0 ](0, k) * w; // w=sum(Nu*w) - Aders [ 0 ](1) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1) * w; // dxw/du=sum(dNu/du*x*w) - wders(1) += ders [ 0 ](1, k) * w; // dw/du=sum(dNu/du*w) + Aders [ 0 ][1] += ders [ 0 ](1, k) * vertexCoords[0] * w; // dxw/du=sum(dNu/du*x*w) + wders[1] += ders [ 0 ](1, k) * w; // dw/du=sum(dNu/du*w) } - weight = wders(0); + double weight = wders[0]; // calculation of jacobian matrix according to Eq 4.7 - jacobian(0, 0) = ( Aders [ 0 ](1) - wders(1) * Aders [ 0 ](0) / weight ) / weight; // dx/du + jacobian(0, 0) = ( Aders [ 0 ][1] - wders[1] * Aders [ 0 ][0] / weight ) / weight; // dx/du Jacob = jacobian.giveDeterminant(); //calculation of derivatives of NURBS basis functions with respect to local parameters is not covered by NURBS book - product = Jacob * weight * weight; - cnt = 0; + double product = Jacob * weight * weight; + int cnt = 0; ind = uind + 1; for ( int k = 0; k <= degree [ 0 ]; k++ ) { - w = cellgeo.giveVertexCoordinates(ind + k)->at(2); + double w = this->weights.at(ind + k); // [dNu/du*w*sum(Nu*w) - Nu*w*sum(dNu/du*w)] / [J*sum(Nu*w)^2] - answer(cnt, 0) = ders [ 0 ](1, k) * w * weight - ders [ 0 ](0, k) * w * wders(1) / product; + answer(cnt, 0) = ders [ 0 ](1, k) * w * weight - ders [ 0 ](0, k) * w * wders[1] / product; cnt++; } } else if ( nsd == 2 ) { FloatArray tmp1(nsd + 1), tmp2(nsd + 1); // allow for weight // calculate values and derivatives of nonrational Bspline surface with weights at first (Aders, wders) - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - ind = vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int ind = vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp1.zero(); tmp2.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - w = vertexCoordsPtr->at(3); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + double w = this->weights.at(ind + k); - tmp1(0) += ders [ 0 ](0, k) * vertexCoordsPtr->at(1) * w; // sum(Nu*x*w) - tmp1(1) += ders [ 0 ](0, k) * vertexCoordsPtr->at(2) * w; // sum(Nu*y*w) - tmp1(2) += ders [ 0 ](0, k) * w; // sum(Nu*w) + tmp1[0] += ders [ 0 ](0, k) * vertexCoords[0] * w; // sum(Nu*x*w) + tmp1[1] += ders [ 0 ](0, k) * vertexCoords[1] * w; // sum(Nu*y*w) + tmp1[2] += ders [ 0 ](0, k) * w; // sum(Nu*w) - tmp2(0) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1) * w; // sum(dNu/du*x*w) - tmp2(1) += ders [ 0 ](1, k) * vertexCoordsPtr->at(2) * w; // sum(dNu/du*y*w) - tmp2(2) += ders [ 0 ](1, k) * w; // sum(dNu/du*w) + tmp2[0] += ders [ 0 ](1, k) * vertexCoords[0] * w; // sum(dNu/du*x*w) + tmp2[1] += ders [ 0 ](1, k) * vertexCoords[1] * w; // sum(dNu/du*y*w) + tmp2[2] += ders [ 0 ](1, k) * w; // sum(dNu/du*w) } ind += numberOfControlPoints [ 0 ]; - Aders [ 0 ](0) += ders [ 1 ](0, l) * tmp1(0); // xw=sum(Nv*sum(Nu*x*w) - Aders [ 1 ](0) += ders [ 1 ](0, l) * tmp1(1); // yw=sum(Nv*sum(Nu*y*w) - wders(0) += ders [ 1 ](0, l) * tmp1(2); // w=sum(Nv*sum(Nu*w) + Aders [ 0 ][0] += ders [ 1 ](0, l) * tmp1[0]; // xw=sum(Nv*sum(Nu*x*w) + Aders [ 1 ][0] += ders [ 1 ](0, l) * tmp1[1]; // yw=sum(Nv*sum(Nu*y*w) + wders[0] += ders [ 1 ](0, l) * tmp1[2]; // w=sum(Nv*sum(Nu*w) - Aders [ 0 ](1) += ders [ 1 ](0, l) * tmp2(0); // dxw/du=sum(Nv*sum(dNu/du*x*w) - Aders [ 1 ](1) += ders [ 1 ](0, l) * tmp2(1); // dyw/du=sum(Nv*sum(dNu/du*y*w) - wders(1) += ders [ 1 ](0, l) * tmp2(2); // dw/du=sum(Nv*sum(dNu/du*w) + Aders [ 0 ][1] += ders [ 1 ](0, l) * tmp2[0]; // dxw/du=sum(Nv*sum(dNu/du*x*w) + Aders [ 1 ][1] += ders [ 1 ](0, l) * tmp2[1]; // dyw/du=sum(Nv*sum(dNu/du*y*w) + wders[1] += ders [ 1 ](0, l) * tmp2[2]; // dw/du=sum(Nv*sum(dNu/du*w) - Aders [ 0 ](2) += ders [ 1 ](1, l) * tmp1(0); // dxw/dv=sum(dNv/dv*sum(Nu*x*w) - Aders [ 1 ](2) += ders [ 1 ](1, l) * tmp1(1); // dyw/dv=sum(dNv/dv*sum(Nu*y*w) - wders(2) += ders [ 1 ](1, l) * tmp1(2); // dw/dv=sum(dNv/dv*sum(Nu*w) + Aders [ 0 ][2] += ders [ 1 ](1, l) * tmp1[0]; // dxw/dv=sum(dNv/dv*sum(Nu*x*w) + Aders [ 1 ][2] += ders [ 1 ](1, l) * tmp1[1]; // dyw/dv=sum(dNv/dv*sum(Nu*y*w) + wders[2] += ders [ 1 ](1, l) * tmp1[2]; // dw/dv=sum(dNv/dv*sum(Nu*w) } - weight = wders(0); + double weight = wders[0]; // calculation of jacobian matrix according to Eq 4.19 - tmp1(0) = Aders [ 0 ](0) / weight; - tmp1(1) = Aders [ 1 ](0) / weight; - jacobian(0, 0) = ( Aders [ 0 ](1) - wders(1) * tmp1(0) ) / weight; // dx/du - jacobian(0, 1) = ( Aders [ 1 ](1) - wders(1) * tmp1(1) ) / weight; // dy/du - jacobian(1, 0) = ( Aders [ 0 ](2) - wders(2) * tmp1(0) ) / weight; // dx/dv - jacobian(1, 1) = ( Aders [ 1 ](2) - wders(2) * tmp1(1) ) / weight; // dy/dv + tmp1[0] = Aders [ 0 ][0] / weight; + tmp1[1] = Aders [ 1 ][0] / weight; + jacobian(0, 0) = ( Aders [ 0 ][1] - wders[1] * tmp1[0] ) / weight; // dx/du + jacobian(0, 1) = ( Aders [ 1 ][1] - wders[1] * tmp1[1] ) / weight; // dy/du + jacobian(1, 0) = ( Aders [ 0 ][2] - wders[2] * tmp1[0] ) / weight; // dx/dv + jacobian(1, 1) = ( Aders [ 1 ][2] - wders[2] * tmp1[1] ) / weight; // dy/dv Jacob = jacobian.giveDeterminant(); //calculation of derivatives of NURBS basis functions with respect to local parameters is not covered by NURBS book - product = Jacob * weight * weight; - cnt = 0; + double product = Jacob * weight * weight; + int cnt = 0; ind = vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int l = 0; l <= degree [ 1 ]; l++ ) { for ( int k = 0; k <= degree [ 0 ]; k++ ) { - w = cellgeo.giveVertexCoordinates(ind + k)->at(3); + double w = this->weights.at(ind + k); // dNu/du*Nv*w*sum(Nu*Nv*w) - Nu*Nv*w*sum(dNu/du*Nv*w) - tmp1(0) = ders [ 0 ](1, k) * ders [ 1 ](0, l) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * w * wders(1); + tmp1[0] = ders [ 0 ](1, k) * ders [ 1 ](0, l) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * w * wders[1]; // Nu*dNv/dv*w*sum(Nu*Nv*w) - Nu*Nv*w*sum(Nu*dNv/dv*w) - tmp1(1) = ders [ 0 ](0, k) * ders [ 1 ](1, l) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * w * wders(2); + tmp1[1] = ders [ 0 ](0, k) * ders [ 1 ](1, l) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * w * wders[2]; - answer(cnt, 0) = ( +jacobian(1, 1) * tmp1(0) - jacobian(0, 1) * tmp1(1) ) / product; - answer(cnt, 1) = ( -jacobian(1, 0) * tmp1(0) + jacobian(0, 0) * tmp1(1) ) / product; + answer(cnt, 0) = ( +jacobian(1, 1) * tmp1[0] - jacobian(0, 1) * tmp1[1] ) / product; + answer(cnt, 1) = ( -jacobian(1, 0) * tmp1[0] + jacobian(0, 0) * tmp1[1] ) / product; cnt++; } @@ -416,117 +418,117 @@ double NURBSInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lco FloatArray temp1(nsd + 1), temp2(nsd + 1), temp3(nsd + 1); // allow for weight // calculate values and derivatives of nonrational Bspline solid with weights at first (Aders, wders) - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - tind = span(2) - degree [ 2 ]; - ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int tind = span[2] - degree [ 2 ]; + int ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int m = 0; m <= degree [ 2 ]; m++ ) { temp1.zero(); temp2.zero(); temp3.zero(); - indx = ind; + int indx = ind; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp1.zero(); tmp2.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - w = vertexCoordsPtr->at(4); - - tmp1(0) += ders [ 0 ](0, k) * vertexCoordsPtr->at(1) * w; // sum(Nu*x*w) - tmp1(1) += ders [ 0 ](0, k) * vertexCoordsPtr->at(2) * w; // sum(Nu*y*w) - tmp1(2) += ders [ 0 ](0, k) * vertexCoordsPtr->at(3) * w; // sum(Nu*z*w) - tmp1(3) += ders [ 0 ](0, k) * w; // sum(Nu*w) - - tmp2(0) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1) * w; // sum(dNu/du*x*w) - tmp2(1) += ders [ 0 ](1, k) * vertexCoordsPtr->at(2) * w; // sum(dNu/du*y*w) - tmp2(2) += ders [ 0 ](1, k) * vertexCoordsPtr->at(3) * w; // sum(dNu/du*z*w) - tmp2(3) += ders [ 0 ](1, k) * w; // sum(dNu/du*w) + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + double w = this->weights.at(ind + k); + + tmp1[0] += ders [ 0 ](0, k) * vertexCoords[0] * w; // sum(Nu*x*w) + tmp1[1] += ders [ 0 ](0, k) * vertexCoords[1] * w; // sum(Nu*y*w) + tmp1[2] += ders [ 0 ](0, k) * vertexCoords[2] * w; // sum(Nu*z*w) + tmp1[3] += ders [ 0 ](0, k) * w; // sum(Nu*w) + + tmp2[0] += ders [ 0 ](1, k) * vertexCoords[0] * w; // sum(dNu/du*x*w) + tmp2[1] += ders [ 0 ](1, k) * vertexCoords[1] * w; // sum(dNu/du*y*w) + tmp2[2] += ders [ 0 ](1, k) * vertexCoords[2] * w; // sum(dNu/du*z*w) + tmp2[3] += ders [ 0 ](1, k) * w; // sum(dNu/du*w) } ind += numberOfControlPoints [ 0 ]; - temp1(0) += ders [ 1 ](0, l) * tmp1(0); // sum(Nv*sum(Nu*x*w)) - temp1(1) += ders [ 1 ](0, l) * tmp1(1); // sum(Nv*sum(Nu*y*w)) - temp1(2) += ders [ 1 ](0, l) * tmp1(2); // sum(Nv*sum(Nu*z*w)) - temp1(3) += ders [ 1 ](0, l) * tmp1(3); // sum(Nv*sum(Nu*w)) + temp1[0] += ders [ 1 ](0, l) * tmp1[0]; // sum(Nv*sum(Nu*x*w)) + temp1[1] += ders [ 1 ](0, l) * tmp1[1]; // sum(Nv*sum(Nu*y*w)) + temp1[2] += ders [ 1 ](0, l) * tmp1[2]; // sum(Nv*sum(Nu*z*w)) + temp1[3] += ders [ 1 ](0, l) * tmp1[3]; // sum(Nv*sum(Nu*w)) - temp2(0) += ders [ 1 ](0, l) * tmp2(0); // sum(Nv*sum(dNu/du*x*w)) - temp2(1) += ders [ 1 ](0, l) * tmp2(1); // sum(Nv*sum(dNu/du*y*w)) - temp2(2) += ders [ 1 ](0, l) * tmp2(2); // sum(Nv*sum(dNu/du*z*w)) - temp2(3) += ders [ 1 ](0, l) * tmp2(3); // sum(Nv*sum(dNu/du*w)) + temp2[0] += ders [ 1 ](0, l) * tmp2[0]; // sum(Nv*sum(dNu/du*x*w)) + temp2[1] += ders [ 1 ](0, l) * tmp2[1]; // sum(Nv*sum(dNu/du*y*w)) + temp2[2] += ders [ 1 ](0, l) * tmp2[2]; // sum(Nv*sum(dNu/du*z*w)) + temp2[3] += ders [ 1 ](0, l) * tmp2[3]; // sum(Nv*sum(dNu/du*w)) - temp3(0) += ders [ 1 ](1, l) * tmp1(0); // sum(dNv/dv*sum(Nu*x*w)) - temp3(1) += ders [ 1 ](1, l) * tmp1(1); // sum(dNv/dv*sum(Nu*y*w)) - temp3(2) += ders [ 1 ](1, l) * tmp1(2); // sum(dNv/dv*sum(Nu*z*w)) - temp3(3) += ders [ 1 ](1, l) * tmp1(3); // sum(dNv/dv*sum(Nu*w)) + temp3[0] += ders [ 1 ](1, l) * tmp1[0]; // sum(dNv/dv*sum(Nu*x*w)) + temp3[1] += ders [ 1 ](1, l) * tmp1[1]; // sum(dNv/dv*sum(Nu*y*w)) + temp3[2] += ders [ 1 ](1, l) * tmp1[2]; // sum(dNv/dv*sum(Nu*z*w)) + temp3[3] += ders [ 1 ](1, l) * tmp1[3]; // sum(dNv/dv*sum(Nu*w)) } ind = indx + numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ]; - Aders [ 0 ](0) += ders [ 2 ](0, m) * temp1(0); // x=sum(Nt*sum(Nv*sum(Nu*x*w))) - Aders [ 1 ](0) += ders [ 2 ](0, m) * temp1(1); // y=sum(Nt*sum(Nv*sum(Nu*y*w))) - Aders [ 2 ](0) += ders [ 2 ](0, m) * temp1(2); // y=sum(Nt*sum(Nv*sum(Nu*y*w))) - wders(0) += ders [ 2 ](0, m) * temp1(3); // w=sum(Nt*sum(Nv*sum(Nu*w))) - - Aders [ 0 ](1) += ders [ 2 ](0, m) * temp2(0); // dx/du=sum(Nt*sum(Nv*sum(dNu/du*x*w))) - Aders [ 1 ](1) += ders [ 2 ](0, m) * temp2(1); // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y*w))) - Aders [ 2 ](1) += ders [ 2 ](0, m) * temp2(2); // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y*w))) - wders(1) += ders [ 2 ](0, m) * temp2(3); // dw/du=sum(Nt*sum(Nv*sum(dNu/du*w))) - - Aders [ 0 ](2) += ders [ 2 ](0, m) * temp3(0); // dx/dv=sum(Nt*sum(dNv/dv*sum(Nu*x*w))) - Aders [ 1 ](2) += ders [ 2 ](0, m) * temp3(1); // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y*w))) - Aders [ 2 ](2) += ders [ 2 ](0, m) * temp3(2); // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y*w))) - wders(2) += ders [ 2 ](0, m) * temp3(3); // dw/dv=sum(Nt*sum(dNv/dv*sum(Nu*w))) - - Aders [ 0 ](3) += ders [ 2 ](1, m) * temp1(0); // dx/dt=sum(dNt/dt*sum(Nv*sum(Nu*x*w))) - Aders [ 1 ](3) += ders [ 2 ](1, m) * temp1(1); // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y*w))) - Aders [ 2 ](3) += ders [ 2 ](1, m) * temp1(2); // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y*w))) - wders(3) += ders [ 2 ](1, m) * temp1(3); // dw/dt=sum(dNt/dt*sum(Nv*sum(Nu*w))) + Aders [ 0 ][0] += ders [ 2 ](0, m) * temp1[0]; // x=sum(Nt*sum(Nv*sum(Nu*x*w))) + Aders [ 1 ][0] += ders [ 2 ](0, m) * temp1[1]; // y=sum(Nt*sum(Nv*sum(Nu*y*w))) + Aders [ 2 ][0] += ders [ 2 ](0, m) * temp1[2]; // y=sum(Nt*sum(Nv*sum(Nu*y*w))) + wders[0] += ders [ 2 ](0, m) * temp1[3]; // w=sum(Nt*sum(Nv*sum(Nu*w))) + + Aders [ 0 ][1] += ders [ 2 ](0, m) * temp2[0]; // dx/du=sum(Nt*sum(Nv*sum(dNu/du*x*w))) + Aders [ 1 ][1] += ders [ 2 ](0, m) * temp2[1]; // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y*w))) + Aders [ 2 ][1] += ders [ 2 ](0, m) * temp2[2]; // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y*w))) + wders[1] += ders [ 2 ](0, m) * temp2[3]; // dw/du=sum(Nt*sum(Nv*sum(dNu/du*w))) + + Aders [ 0 ][2] += ders [ 2 ](0, m) * temp3[0]; // dx/dv=sum(Nt*sum(dNv/dv*sum(Nu*x*w))) + Aders [ 1 ][2] += ders [ 2 ](0, m) * temp3[1]; // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y*w))) + Aders [ 2 ][2] += ders [ 2 ](0, m) * temp3[2]; // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y*w))) + wders[2] += ders [ 2 ](0, m) * temp3[3]; // dw/dv=sum(Nt*sum(dNv/dv*sum(Nu*w))) + + Aders [ 0 ][3] += ders [ 2 ](1, m) * temp1[0]; // dx/dt=sum(dNt/dt*sum(Nv*sum(Nu*x*w))) + Aders [ 1 ][3] += ders [ 2 ](1, m) * temp1[1]; // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y*w))) + Aders [ 2 ][3] += ders [ 2 ](1, m) * temp1[2]; // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y*w))) + wders[3] += ders [ 2 ](1, m) * temp1[3]; // dw/dt=sum(dNt/dt*sum(Nv*sum(Nu*w))) } - weight = wders(0); + double weight = wders[0]; // calculation of jacobian matrix - tmp1(0) = Aders [ 0 ](0) / weight; - tmp1(1) = Aders [ 1 ](0) / weight; - tmp1(2) = Aders [ 2 ](0) / weight; - jacobian(0, 0) = ( Aders [ 0 ](1) - wders(1) * tmp1(0) ) / weight; // dx/du - jacobian(0, 1) = ( Aders [ 1 ](1) - wders(1) * tmp1(1) ) / weight; // dy/du - jacobian(0, 2) = ( Aders [ 2 ](1) - wders(1) * tmp1(2) ) / weight; // dz/du - jacobian(1, 0) = ( Aders [ 0 ](2) - wders(2) * tmp1(0) ) / weight; // dx/dv - jacobian(1, 1) = ( Aders [ 1 ](2) - wders(2) * tmp1(1) ) / weight; // dy/dv - jacobian(1, 2) = ( Aders [ 2 ](2) - wders(2) * tmp1(2) ) / weight; // dz/dv - jacobian(2, 0) = ( Aders [ 0 ](3) - wders(3) * tmp1(0) ) / weight; // dx/dt - jacobian(2, 1) = ( Aders [ 1 ](3) - wders(3) * tmp1(1) ) / weight; // dy/dt - jacobian(2, 2) = ( Aders [ 2 ](3) - wders(3) * tmp1(2) ) / weight; // dz/dt + tmp1[0] = Aders [ 0 ][0] / weight; + tmp1[1] = Aders [ 1 ][0] / weight; + tmp1[2] = Aders [ 2 ][0] / weight; + jacobian(0, 0) = ( Aders [ 0 ][1] - wders[1] * tmp1[0] ) / weight; // dx/du + jacobian(0, 1) = ( Aders [ 1 ][1] - wders[1] * tmp1[1] ) / weight; // dy/du + jacobian(0, 2) = ( Aders [ 2 ][1] - wders[1] * tmp1[2] ) / weight; // dz/du + jacobian(1, 0) = ( Aders [ 0 ][2] - wders[2] * tmp1[0] ) / weight; // dx/dv + jacobian(1, 1) = ( Aders [ 1 ][2] - wders[2] * tmp1[1] ) / weight; // dy/dv + jacobian(1, 2) = ( Aders [ 2 ][2] - wders[2] * tmp1[2] ) / weight; // dz/dv + jacobian(2, 0) = ( Aders [ 0 ][3] - wders[3] * tmp1[0] ) / weight; // dx/dt + jacobian(2, 1) = ( Aders [ 1 ][3] - wders[3] * tmp1[1] ) / weight; // dy/dt + jacobian(2, 2) = ( Aders [ 2 ][3] - wders[3] * tmp1[2] ) / weight; // dz/dt Jacob = jacobian.giveDeterminant(); //calculation of derivatives of NURBS basis functions with respect to local parameters is not covered by NURBS book - product = Jacob * weight * weight; - cnt = 0; + double product = Jacob * weight * weight; + int cnt = 0; ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int m = 0; m <= degree [ 2 ]; m++ ) { - indx = ind; + int indx = ind; for ( int l = 0; l <= degree [ 1 ]; l++ ) { for ( int k = 0; k <= degree [ 0 ]; k++ ) { - w = cellgeo.giveVertexCoordinates(ind + k)->at(4); + double w = this->weights.at(ind + k); // dNu/du*Nv*Nt*w*sum(Nu*Nv*Nt*w) - Nu*Nv*Nt*w*sum(dNu/du*Nv*Nt*w) - tmp1(0) = ders [ 0 ](1, k) * ders [ 1 ](0, l) * ders [ 2 ](0, m) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * ders [ 2 ](0, m) * w * wders(1); + tmp1[0] = ders [ 0 ](1, k) * ders [ 1 ](0, l) * ders [ 2 ](0, m) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * ders [ 2 ](0, m) * w * wders[1]; // Nu*dNv/dv*Nt*w*sum(Nu*Nv*Nt*w) - Nu*Nv*Nt*w*sum(Nu*dNv/dv*Nt*w) - tmp1(1) = ders [ 0 ](0, k) * ders [ 1 ](1, l) * ders [ 2 ](0, m) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * ders [ 2 ](0, m) * w * wders(2); + tmp1[1] = ders [ 0 ](0, k) * ders [ 1 ](1, l) * ders [ 2 ](0, m) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * ders [ 2 ](0, m) * w * wders[2]; // Nu*Nv*dNt/dt*w*sum(Nu*Nv*Nt*w) - Nu*Nv*Nt*w*sum(Nu*Nv*dNt/dt*w) - tmp1(2) = ders [ 0 ](0, k) * ders [ 1 ](0, l) * ders [ 2 ](1, m) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * ders [ 2 ](0, m) * w * wders(3); - - answer(cnt, 0) = ( ( jacobian(1, 1) * jacobian(2, 2) - jacobian(1, 2) * jacobian(2, 1) ) * tmp1(0) + - ( jacobian(0, 2) * jacobian(2, 1) - jacobian(0, 1) * jacobian(2, 2) ) * tmp1(1) + - ( jacobian(0, 1) * jacobian(1, 2) - jacobian(0, 2) * jacobian(1, 1) ) * tmp1(2) ) / product; // dN/dx - answer(cnt, 1) = ( ( jacobian(1, 2) * jacobian(2, 0) - jacobian(1, 0) * jacobian(2, 2) ) * tmp1(0) + - ( jacobian(0, 0) * jacobian(2, 2) - jacobian(0, 2) * jacobian(2, 0) ) * tmp1(1) + - ( jacobian(0, 2) * jacobian(1, 0) - jacobian(0, 0) * jacobian(1, 2) ) * tmp1(2) ) / product; // dN/dy - answer(cnt, 2) = ( ( jacobian(1, 0) * jacobian(2, 1) - jacobian(1, 1) * jacobian(2, 0) ) * tmp1(0) + - ( jacobian(0, 1) * jacobian(2, 0) - jacobian(0, 0) * jacobian(2, 1) ) * tmp1(1) + - ( jacobian(0, 0) * jacobian(1, 1) - jacobian(0, 1) * jacobian(1, 0) ) * tmp1(2) ) / product; // dN/dz + tmp1[2] = ders [ 0 ](0, k) * ders [ 1 ](0, l) * ders [ 2 ](1, m) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, l) * ders [ 2 ](0, m) * w * wders[3]; + + answer(cnt, 0) = ( ( jacobian(1, 1) * jacobian(2, 2) - jacobian(1, 2) * jacobian(2, 1) ) * tmp1[0] + + ( jacobian(0, 2) * jacobian(2, 1) - jacobian(0, 1) * jacobian(2, 2) ) * tmp1[1] + + ( jacobian(0, 1) * jacobian(1, 2) - jacobian(0, 2) * jacobian(1, 1) ) * tmp1[2] ) / product; // dN/dx + answer(cnt, 1) = ( ( jacobian(1, 2) * jacobian(2, 0) - jacobian(1, 0) * jacobian(2, 2) ) * tmp1[0] + + ( jacobian(0, 0) * jacobian(2, 2) - jacobian(0, 2) * jacobian(2, 0) ) * tmp1[1] + + ( jacobian(0, 2) * jacobian(1, 0) - jacobian(0, 0) * jacobian(1, 2) ) * tmp1[2] ) / product; // dN/dy + answer(cnt, 2) = ( ( jacobian(1, 0) * jacobian(2, 1) - jacobian(1, 1) * jacobian(2, 0) ) * tmp1[0] + + ( jacobian(0, 1) * jacobian(2, 0) - jacobian(0, 0) * jacobian(2, 1) ) * tmp1[1] + + ( jacobian(0, 0) * jacobian(1, 1) - jacobian(0, 1) * jacobian(1, 0) ) * tmp1[2] ) / product; // dN/dz cnt++; } @@ -545,96 +547,94 @@ double NURBSInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lco } -void NURBSInterpolation :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void NURBSInterpolation :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { /* Based on SurfacePoint A4.3 implementation*/ - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; - const FloatArray *vertexCoordsPtr; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); IntArray span(nsd); - double w, weight = 0.0; - int ind, indx, uind, vind, tind; + double weight = 0.0; std :: vector< FloatArray > N(nsd); - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } for ( int i = 0; i < nsd; i++ ) { - this->basisFuns(N [ i ], span(i), lcoords(i), degree [ i ], knotVector [ i ]); + this->basisFuns(N [ i ], span[i], lcoords[i], degree [ i ], knotVector [ i ]); } answer.resize(nsd); answer.zero(); if ( nsd == 1 ) { - uind = span(0) - degree [ 0 ]; - ind = uind + 1; + int uind = span[0] - degree [ 0 ]; + int ind = uind + 1; for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - w = vertexCoordsPtr->at(2); - answer(0) += N [ 0 ](k) * vertexCoordsPtr->at(1) * w; // xw=sum(Nu*x*w) - weight += N [ 0 ](k) * w; // w=sum(Nu*w) + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + double w = this->weights.at(ind + k); + answer[0] += N [ 0 ][k] * vertexCoords[0] * w; // xw=sum(Nu*x*w) + weight += N [ 0 ][k] * w; // w=sum(Nu*w) } } else if ( nsd == 2 ) { FloatArray tmp(nsd + 1); // allow for weight - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - ind = vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int ind = vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - w = vertexCoordsPtr->at(3); - tmp(0) += N [ 0 ](k) * vertexCoordsPtr->at(1) * w; // sum(Nu*x*w) - tmp(1) += N [ 0 ](k) * vertexCoordsPtr->at(2) * w; // sum(Nu*y*w) - tmp(2) += N [ 0 ](k) * w; // sum(Nu*w) + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + double w = this->weights.at(ind + k); + tmp[0] += N [ 0 ][k] * vertexCoords[0] * w; // sum(Nu*x*w) + tmp[1] += N [ 0 ][k] * vertexCoords[1] * w; // sum(Nu*y*w) + tmp[2] += N [ 0 ][k] * w; // sum(Nu*w) } ind += numberOfControlPoints [ 0 ]; - answer(0) += N [ 1 ](l) * tmp(0); // xw=sum(Nv*Nu*x*w) - answer(1) += N [ 1 ](l) * tmp(1); // yw=sum(Nv*Nu*y*w) - weight += N [ 1 ](l) * tmp(2); // w=sum(Nv*Nu*w) + answer[0] += N [ 1 ][l] * tmp[0]; // xw=sum(Nv*Nu*x*w) + answer[1] += N [ 1 ][l] * tmp[1]; // yw=sum(Nv*Nu*y*w) + weight += N [ 1 ][l] * tmp[2]; // w=sum(Nv*Nu*w) } } else if ( nsd == 3 ) { FloatArray tmp(nsd + 1), temp(nsd + 1); // allow for weight - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - tind = span(2) - degree [ 2 ]; - ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int tind = span[2] - degree [ 2 ]; + int ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int m = 0; m <= degree [ 2 ]; m++ ) { temp.zero(); - indx = ind; + int indx = ind; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - w = vertexCoordsPtr->at(4); - tmp(0) += N [ 0 ](k) * vertexCoordsPtr->at(1) * w; // sum(Nu*x*w) - tmp(1) += N [ 0 ](k) * vertexCoordsPtr->at(2) * w; // sum(Nu*y*w) - tmp(2) += N [ 0 ](k) * vertexCoordsPtr->at(3) * w; // sum(Nu*z*w) - tmp(3) += N [ 0 ](k) * w; // sum(Nu*w) + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + double w = this->weights.at(ind + k); + tmp[0] += N [ 0 ][k] * vertexCoords[0] * w; // sum(Nu*x*w) + tmp[1] += N [ 0 ][k] * vertexCoords[1] * w; // sum(Nu*y*w) + tmp[2] += N [ 0 ][k] * vertexCoords[2] * w; // sum(Nu*z*w) + tmp[3] += N [ 0 ][k] * w; // sum(Nu*w) } ind += numberOfControlPoints [ 0 ]; - temp(0) += N [ 1 ](l) * tmp(0); // sum(Nv*Nu*x*w) - temp(1) += N [ 1 ](l) * tmp(1); // sum(Nv*Nu*y*w) - temp(2) += N [ 1 ](l) * tmp(2); // sum(Nv*Nu*z*w) - temp(3) += N [ 1 ](l) * tmp(3); // sum(Nv*Nu*w) + temp[0] += N [ 1 ][l] * tmp[0]; // sum(Nv*Nu*x*w) + temp[1] += N [ 1 ][l] * tmp[1]; // sum(Nv*Nu*y*w) + temp[2] += N [ 1 ][l] * tmp[2]; // sum(Nv*Nu*z*w) + temp[3] += N [ 1 ][l] * tmp[3]; // sum(Nv*Nu*w) } ind = indx + numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ]; - answer(0) += N [ 2 ](m) * temp(0); // xw=sum(Nv*Nu*Nt*x*w) - answer(1) += N [ 2 ](m) * temp(1); // yw=sum(Nv*Nu*Nt*y*w) - answer(2) += N [ 2 ](m) * temp(2); // zw=sum(Nv*Nu*Nt*z*w) - weight += N [ 2 ](m) * temp(3); // w=sum(Nv*Nu*Nt*w) + answer[0] += N [ 2 ][m] * temp[0]; // xw=sum(Nv*Nu*Nt*x*w) + answer[1] += N [ 2 ][m] * temp[1]; // yw=sum(Nv*Nu*Nt*y*w) + answer[2] += N [ 2 ][m] * temp[2]; // zw=sum(Nv*Nu*Nt*z*w) + weight += N [ 2 ][m] * temp[3]; // w=sum(Nv*Nu*Nt*w) } } else { OOFEM_ERROR("lnot implemented for nsd = %d", nsd); @@ -644,29 +644,26 @@ void NURBSInterpolation :: local2global(FloatArray &answer, const FloatArray &lc } -void NURBSInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void NURBSInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // // Based on Algorithm A4.4 (p. 137) for d=1 // - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; - const FloatArray *vertexCoordsPtr; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); IntArray span(nsd); - double w, weight; - int ind, indx, uind, vind, tind; std :: vector< FloatMatrix > ders(nsd); jacobian.resize(nsd, nsd); - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } for ( int i = 0; i < nsd; i++ ) { - this->dersBasisFuns(1, lcoords(i), span(i), degree [ i ], knotVector [ i ], ders [ i ]); + this->dersBasisFuns(1, lcoords[i], span[i], degree [ i ], knotVector [ i ], ders [ i ]); } #if 0 // code according NURBS book (too general allowing higher derivatives) @@ -699,41 +696,41 @@ void NURBSInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const Flo // calculation of jacobian matrix according to A4.4 // calculate values and derivatives of nonrational Bspline surface with weights at first (Aders, wders) - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - ind = vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int ind = vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp1.zero(); tmp2.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - w = vertexCoordsPtr->at(3); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + double w = this->weights.at(ind + k); - tmp1(0) += ders [ 0 ](0, k) * vertexCoordsPtr->at(1) * w; // sum(Nu*x*w) - tmp1(1) += ders [ 0 ](0, k) * vertexCoordsPtr->at(2) * w; // sum(Nu*y*w) - tmp1(2) += ders [ 0 ](0, k) * w; // sum(Nu*w) + tmp1[0] += ders [ 0 ](0, k) * vertexCoords[0] * w; // sum(Nu*x*w) + tmp1[1] += ders [ 0 ](0, k) * vertexCoords[1] * w; // sum(Nu*y*w) + tmp1[2] += ders [ 0 ](0, k) * w; // sum(Nu*w) - tmp2(0) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1) * w; // sum(dNu/du*x*w) - tmp2(1) += ders [ 0 ](1, k) * vertexCoordsPtr->at(2) * w; // sum(dNu/du*y*w) - tmp2(2) += ders [ 0 ](1, k) * w; // sum(dNu/du*w) + tmp2[0] += ders [ 0 ](1, k) * vertexCoords[0] * w; // sum(dNu/du*x*w) + tmp2[1] += ders [ 0 ](1, k) * vertexCoords[1] * w; // sum(dNu/du*y*w) + tmp2[2] += ders [ 0 ](1, k) * w; // sum(dNu/du*w) } ind += numberOfControlPoints [ 0 ]; - Aders [ 0 ](0, 0) += ders [ 1 ](0, l) * tmp1(0); // xw=sum(Nv*sum(Nu*x*w)) - Aders [ 1 ](0, 0) += ders [ 1 ](0, l) * tmp1(1); // yw=sum(Nv*sum(Nu*y*w)) - wders(0, 0) += ders [ 1 ](0, l) * tmp1(2); // w=sum(Nv*sum(Nu*w)) + Aders [ 0 ](0, 0) += ders [ 1 ](0, l) * tmp1[0]; // xw=sum(Nv*sum(Nu*x*w)) + Aders [ 1 ](0, 0) += ders [ 1 ](0, l) * tmp1[1]; // yw=sum(Nv*sum(Nu*y*w)) + wders(0, 0) += ders [ 1 ](0, l) * tmp1[2]; // w=sum(Nv*sum(Nu*w)) - Aders [ 0 ](0, 1) += ders [ 1 ](1, l) * tmp1(0); // dxw/dv=sum(dNv/dv*sum(Nu*x*w)) - Aders [ 1 ](0, 1) += ders [ 1 ](1, l) * tmp1(1); // dyw/dv=sum(dNv/dv*sum(Nu*y*w)) - wders(0, 1) += ders [ 1 ](1, l) * tmp1(2); // dw/dv=sum(dNv/dv*sum(Nu*w)) + Aders [ 0 ](0, 1) += ders [ 1 ](1, l) * tmp1[0]; // dxw/dv=sum(dNv/dv*sum(Nu*x*w)) + Aders [ 1 ](0, 1) += ders [ 1 ](1, l) * tmp1[1]; // dyw/dv=sum(dNv/dv*sum(Nu*y*w)) + wders(0, 1) += ders [ 1 ](1, l) * tmp1[2]; // dw/dv=sum(dNv/dv*sum(Nu*w)) - Aders [ 0 ](1, 0) += ders [ 1 ](0, l) * tmp2(0); // dxw/du=sum(Nv*sum(dNu/du*x*w)) - Aders [ 1 ](1, 0) += ders [ 1 ](0, l) * tmp2(1); // dyw/du=sum(Nv*sum(dNu/du*y*w)) - wders(1, 0) += ders [ 1 ](0, l) * tmp2(2); // dw/du=sum(Nv*sum(dNu/du*w)) + Aders [ 0 ](1, 0) += ders [ 1 ](0, l) * tmp2[0]; // dxw/du=sum(Nv*sum(dNu/du*x*w)) + Aders [ 1 ](1, 0) += ders [ 1 ](0, l) * tmp2[1]; // dyw/du=sum(Nv*sum(dNu/du*y*w)) + wders(1, 0) += ders [ 1 ](0, l) * tmp2[2]; // dw/du=sum(Nv*sum(dNu/du*w)) } - weight = wders(0, 0); + double weight = wders(0, 0); #ifndef OPTIMIZED_VERSION_A4dot4 const int d = 1; @@ -741,28 +738,28 @@ void NURBSInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const Flo // since all entries in Pascal triangle up to d=1 are 1, binomial coefficients are ignored for ( int k = 0; k <= d; k++ ) { for ( int l = 0; l <= d - k; l++ ) { - tmp1(0) = Aders [ 0 ](k, l); - tmp1(1) = Aders [ 1 ](k, l); + tmp1[0] = Aders [ 0 ](k, l); + tmp1[1] = Aders [ 1 ](k, l); for ( j = 1; j <= l; j++ ) { - tmp1(0) -= wders(0, j) * Sders [ 0 ](k, l - j); // *Bin(l,j) - tmp1(1) -= wders(0, j) * Sders [ 1 ](k, l - j); // *Bin(l,j) + tmp1[0] -= wders(0, j) * Sders [ 0 ](k, l - j); // *Bin(l,j) + tmp1[1] -= wders(0, j) * Sders [ 1 ](k, l - j); // *Bin(l,j) } for ( int i = 1; i <= k; i++ ) { - tmp1(0) -= wders(i, 0) * Sders [ 0 ](k - i, l); // *Bin(k,i) - tmp1(1) -= wders(i, 0) * Sders [ 1 ](k - i, l); // *Bin(k,i) + tmp1[0] -= wders(i, 0) * Sders [ 0 ](k - i, l); // *Bin(k,i) + tmp1[1] -= wders(i, 0) * Sders [ 1 ](k - i, l); // *Bin(k,i) tmp2.zero(); for ( int j = 1; j <= l; j++ ) { - tmp2(0) += wders(i, j) * Sders [ 0 ](k - i, l - j); // *Bin(l,j) - tmp2(1) += wders(i, j) * Sders [ 1 ](k - i, l - j); // *Bin(l,j) + tmp2[0] += wders(i, j) * Sders [ 0 ](k - i, l - j); // *Bin(l,j) + tmp2[1] += wders(i, j) * Sders [ 1 ](k - i, l - j); // *Bin(l,j) } - tmp1(0) -= tmp2(0); // *Bin(k,i) - tmp1(1) -= tmp2(1); // *Bin(k,i) + tmp1[0] -= tmp2[0]; // *Bin(k,i) + tmp1[1] -= tmp2[1]; // *Bin(k,i) } - Sders [ 0 ](k, l) = tmp1(0) / weight; - Sders [ 1 ](k, l) = tmp1(1) / weight; + Sders [ 0 ](k, l) = tmp1[0] / weight; + Sders [ 1 ](k, l) = tmp1[1] / weight; } } @@ -791,14 +788,14 @@ void NURBSInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const Flo */ // k=0 l=0 loop - tmp1(0) = Aders [ 0 ](0, 0) / weight; - tmp1(1) = Aders [ 1 ](0, 0) / weight; + tmp1[0] = Aders [ 0 ](0, 0) / weight; + tmp1[1] = Aders [ 1 ](0, 0) / weight; // k=1 l=0 loop - jacobian(0, 0) = ( Aders [ 0 ](1, 0) - wders(1, 0) * tmp1(0) ) / weight; // dx/du - jacobian(0, 1) = ( Aders [ 1 ](1, 0) - wders(1, 0) * tmp1(1) ) / weight; // dy/du + jacobian(0, 0) = ( Aders [ 0 ](1, 0) - wders(1, 0) * tmp1[0] ) / weight; // dx/du + jacobian(0, 1) = ( Aders [ 1 ](1, 0) - wders(1, 0) * tmp1[1] ) / weight; // dy/du // k=0 l=1 loop - jacobian(1, 0) = ( Aders [ 0 ](0, 1) - wders(0, 1) * tmp1(0) ) / weight; // dx/dv - jacobian(1, 1) = ( Aders [ 1 ](0, 1) - wders(0, 1) * tmp1(1) ) / weight; // dy/dv + jacobian(1, 0) = ( Aders [ 0 ](0, 1) - wders(0, 1) * tmp1[0] ) / weight; // dx/dv + jacobian(1, 1) = ( Aders [ 1 ](0, 1) - wders(0, 1) * tmp1[1] ) / weight; // dy/dv #endif } else { OOFEM_ERROR("not implemented for nsd = %d", nsd); @@ -818,158 +815,158 @@ void NURBSInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const Flo if ( nsd == 1 ) { // calculate values and derivatives of nonrational Bspline curve with weights at first (Aders, wders) - uind = span(0) - degree [ 0 ]; - ind = uind + 1; + int uind = span[0] - degree [ 0 ]; + int ind = uind + 1; for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - w = vertexCoordsPtr->at(2); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + double w = this->weights.at(ind + k); - Aders [ 0 ](0) += ders [ 0 ](0, k) * vertexCoordsPtr->at(1) * w; // xw=sum(Nu*x*w) - wders(0) += ders [ 0 ](0, k) * w; // w=sum(Nu*w) + Aders [ 0 ][0] += ders [ 0 ](0, k) * vertexCoords[0] * w; // xw=sum(Nu*x*w) + wders[0] += ders [ 0 ](0, k) * w; // w=sum(Nu*w) - Aders [ 0 ](1) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1) * w; // dxw/du=sum(dNu/du*x*w) - wders(1) += ders [ 0 ](1, k) * w; // dw/du=sum(dNu/du*w) + Aders [ 0 ][1] += ders [ 0 ](1, k) * vertexCoords[0] * w; // dxw/du=sum(dNu/du*x*w) + wders[1] += ders [ 0 ](1, k) * w; // dw/du=sum(dNu/du*w) } - weight = wders(0); + double weight = wders[0]; // calculation of jacobian matrix according to Eq 4.7 - jacobian(0, 0) = ( Aders [ 0 ](1) - wders(1) * Aders [ 0 ](0) / weight ) / weight; // dx/du + jacobian(0, 0) = ( Aders [ 0 ][1] - wders[1] * Aders [ 0 ][0] / weight ) / weight; // dx/du } else if ( nsd == 2 ) { FloatArray tmp1(nsd + 1), tmp2(nsd + 1); // allow for weight // calculate values and derivatives of nonrational Bspline surface with weights at first (Aders, wders) - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - ind = vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int ind = vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp1.zero(); tmp2.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - w = vertexCoordsPtr->at(3); + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + double w = this->weights.at(ind + k); - tmp1(0) += ders [ 0 ](0, k) * vertexCoordsPtr->at(1) * w; // sum(Nu*x*w) - tmp1(1) += ders [ 0 ](0, k) * vertexCoordsPtr->at(2) * w; // sum(Nu*y*w) - tmp1(2) += ders [ 0 ](0, k) * w; // sum(Nu*w) + tmp1[0] += ders [ 0 ](0, k) * vertexCoords[0] * w; // sum(Nu*x*w) + tmp1[1] += ders [ 0 ](0, k) * vertexCoords[1] * w; // sum(Nu*y*w) + tmp1[2] += ders [ 0 ](0, k) * w; // sum(Nu*w) - tmp2(0) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1) * w; // sum(dNu/du*x*w) - tmp2(1) += ders [ 0 ](1, k) * vertexCoordsPtr->at(2) * w; // sum(dNu/du*y*w) - tmp2(2) += ders [ 0 ](1, k) * w; // sum(dNu/du*w) + tmp2[0] += ders [ 0 ](1, k) * vertexCoords[0] * w; // sum(dNu/du*x*w) + tmp2[1] += ders [ 0 ](1, k) * vertexCoords[1] * w; // sum(dNu/du*y*w) + tmp2[2] += ders [ 0 ](1, k) * w; // sum(dNu/du*w) } ind += numberOfControlPoints [ 0 ]; - Aders [ 0 ](0) += ders [ 1 ](0, l) * tmp1(0); // xw=sum(Nv*sum(Nu*x*w) - Aders [ 1 ](0) += ders [ 1 ](0, l) * tmp1(1); // yw=sum(Nv*sum(Nu*y*w) - wders(0) += ders [ 1 ](0, l) * tmp1(2); // w=sum(Nv*sum(Nu*w) + Aders [ 0 ][0] += ders [ 1 ](0, l) * tmp1[0]; // xw=sum(Nv*sum(Nu*x*w) + Aders [ 1 ][0] += ders [ 1 ](0, l) * tmp1[1]; // yw=sum(Nv*sum(Nu*y*w) + wders[0] += ders [ 1 ](0, l) * tmp1[2]; // w=sum(Nv*sum(Nu*w) - Aders [ 0 ](1) += ders [ 1 ](0, l) * tmp2(0); // dxw/du=sum(Nv*sum(dNu/du*x*w) - Aders [ 1 ](1) += ders [ 1 ](0, l) * tmp2(1); // dyw/du=sum(Nv*sum(dNu/du*y*w) - wders(1) += ders [ 1 ](0, l) * tmp2(2); // dw/du=sum(Nv*sum(dNu/du*w) + Aders [ 0 ][1] += ders [ 1 ](0, l) * tmp2[0]; // dxw/du=sum(Nv*sum(dNu/du*x*w) + Aders [ 1 ][1] += ders [ 1 ](0, l) * tmp2[1]; // dyw/du=sum(Nv*sum(dNu/du*y*w) + wders[1] += ders [ 1 ](0, l) * tmp2[2]; // dw/du=sum(Nv*sum(dNu/du*w) - Aders [ 0 ](2) += ders [ 1 ](1, l) * tmp1(0); // dxw/dv=sum(dNv/dv*sum(Nu*x*w) - Aders [ 1 ](2) += ders [ 1 ](1, l) * tmp1(1); // dyw/dv=sum(dNv/dv*sum(Nu*y*w) - wders(2) += ders [ 1 ](1, l) * tmp1(2); // dw/dv=sum(dNv/dv*sum(Nu*w) + Aders [ 0 ][2] += ders [ 1 ](1, l) * tmp1[0]; // dxw/dv=sum(dNv/dv*sum(Nu*x*w) + Aders [ 1 ][2] += ders [ 1 ](1, l) * tmp1[1]; // dyw/dv=sum(dNv/dv*sum(Nu*y*w) + wders[2] += ders [ 1 ](1, l) * tmp1[2]; // dw/dv=sum(dNv/dv*sum(Nu*w) } - weight = wders(0); + double weight = wders[0]; // calculation of jacobian matrix according to Eq 4.19 - tmp1(0) = Aders [ 0 ](0) / weight; - tmp1(1) = Aders [ 1 ](0) / weight; - jacobian(0, 0) = ( Aders [ 0 ](1) - wders(1) * tmp1(0) ) / weight; // dx/du - jacobian(0, 1) = ( Aders [ 1 ](1) - wders(1) * tmp1(1) ) / weight; // dy/du - jacobian(1, 0) = ( Aders [ 0 ](2) - wders(2) * tmp1(0) ) / weight; // dx/dv - jacobian(1, 1) = ( Aders [ 1 ](2) - wders(2) * tmp1(1) ) / weight; // dy/dv + tmp1[0] = Aders [ 0 ][0] / weight; + tmp1[1] = Aders [ 1 ][0] / weight; + jacobian(0, 0) = ( Aders [ 0 ][1] - wders[1] * tmp1[0] ) / weight; // dx/du + jacobian(0, 1) = ( Aders [ 1 ][1] - wders[1] * tmp1[1] ) / weight; // dy/du + jacobian(1, 0) = ( Aders [ 0 ][2] - wders[2] * tmp1[0] ) / weight; // dx/dv + jacobian(1, 1) = ( Aders [ 1 ][2] - wders[2] * tmp1[1] ) / weight; // dy/dv } else if ( nsd == 3 ) { FloatArray tmp1(nsd + 1), tmp2(nsd + 1); // allow for weight FloatArray temp1(nsd + 1), temp2(nsd + 1), temp3(nsd + 1); // allow for weight // calculate values and derivatives of nonrational Bspline solid with weights at first (Aders, wders) - uind = span(0) - degree [ 0 ]; - vind = span(1) - degree [ 1 ]; - tind = span(2) - degree [ 2 ]; - ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; + int uind = span[0] - degree [ 0 ]; + int vind = span[1] - degree [ 1 ]; + int tind = span[2] - degree [ 2 ]; + int ind = tind * numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ] + vind * numberOfControlPoints [ 0 ] + uind + 1; for ( int m = 0; m <= degree [ 2 ]; m++ ) { temp1.zero(); temp2.zero(); temp3.zero(); - indx = ind; + int indx = ind; for ( int l = 0; l <= degree [ 1 ]; l++ ) { tmp1.zero(); tmp2.zero(); for ( int k = 0; k <= degree [ 0 ]; k++ ) { - vertexCoordsPtr = cellgeo.giveVertexCoordinates(ind + k); - w = vertexCoordsPtr->at(4); - - tmp1(0) += ders [ 0 ](0, k) * vertexCoordsPtr->at(1) * w; // sum(Nu*x*w) - tmp1(1) += ders [ 0 ](0, k) * vertexCoordsPtr->at(2) * w; // sum(Nu*y*w) - tmp1(2) += ders [ 0 ](0, k) * vertexCoordsPtr->at(3) * w; // sum(Nu*z*w) - tmp1(3) += ders [ 0 ](0, k) * w; // sum(Nu*w) - - tmp2(0) += ders [ 0 ](1, k) * vertexCoordsPtr->at(1) * w; // sum(dNu/du*x*w) - tmp2(1) += ders [ 0 ](1, k) * vertexCoordsPtr->at(2) * w; // sum(dNu/du*y*w) - tmp2(2) += ders [ 0 ](1, k) * vertexCoordsPtr->at(3) * w; // sum(dNu/du*z*w) - tmp2(3) += ders [ 0 ](1, k) * w; // sum(dNu/du*w) + const auto &vertexCoords = cellgeo.giveVertexCoordinates(ind + k); + double w = this->weights.at(ind + k); + + tmp1[0] += ders [ 0 ](0, k) * vertexCoords[0] * w; // sum(Nu*x*w) + tmp1[1] += ders [ 0 ](0, k) * vertexCoords[1] * w; // sum(Nu*y*w) + tmp1[2] += ders [ 0 ](0, k) * vertexCoords[2] * w; // sum(Nu*z*w) + tmp1[3] += ders [ 0 ](0, k) * w; // sum(Nu*w) + + tmp2[0] += ders [ 0 ](1, k) * vertexCoords[0] * w; // sum(dNu/du*x*w) + tmp2[1] += ders [ 0 ](1, k) * vertexCoords[1] * w; // sum(dNu/du*y*w) + tmp2[2] += ders [ 0 ](1, k) * vertexCoords[2] * w; // sum(dNu/du*z*w) + tmp2[3] += ders [ 0 ](1, k) * w; // sum(dNu/du*w) } ind += numberOfControlPoints [ 0 ]; - temp1(0) += ders [ 1 ](0, l) * tmp1(0); // sum(Nv*sum(Nu*x*w)) - temp1(1) += ders [ 1 ](0, l) * tmp1(1); // sum(Nv*sum(Nu*y*w)) - temp1(2) += ders [ 1 ](0, l) * tmp1(2); // sum(Nv*sum(Nu*z*w)) - temp1(3) += ders [ 1 ](0, l) * tmp1(3); // sum(Nv*sum(Nu*w)) + temp1[0] += ders [ 1 ](0, l) * tmp1[0]; // sum(Nv*sum(Nu*x*w)) + temp1[1] += ders [ 1 ](0, l) * tmp1[1]; // sum(Nv*sum(Nu*y*w)) + temp1[2] += ders [ 1 ](0, l) * tmp1[2]; // sum(Nv*sum(Nu*z*w)) + temp1[3] += ders [ 1 ](0, l) * tmp1[3]; // sum(Nv*sum(Nu*w)) - temp2(0) += ders [ 1 ](0, l) * tmp2(0); // sum(Nv*sum(dNu/du*x*w)) - temp2(1) += ders [ 1 ](0, l) * tmp2(1); // sum(Nv*sum(dNu/du*y*w)) - temp2(2) += ders [ 1 ](0, l) * tmp2(2); // sum(Nv*sum(dNu/du*z*w)) - temp2(3) += ders [ 1 ](0, l) * tmp2(3); // sum(Nv*sum(dNu/du*w)) + temp2[0] += ders [ 1 ](0, l) * tmp2[0]; // sum(Nv*sum(dNu/du*x*w)) + temp2[1] += ders [ 1 ](0, l) * tmp2[1]; // sum(Nv*sum(dNu/du*y*w)) + temp2[2] += ders [ 1 ](0, l) * tmp2[2]; // sum(Nv*sum(dNu/du*z*w)) + temp2[3] += ders [ 1 ](0, l) * tmp2[3]; // sum(Nv*sum(dNu/du*w)) - temp3(0) += ders [ 1 ](1, l) * tmp1(0); // sum(dNv/dv*sum(Nu*x*w)) - temp3(1) += ders [ 1 ](1, l) * tmp1(1); // sum(dNv/dv*sum(Nu*y*w)) - temp3(2) += ders [ 1 ](1, l) * tmp1(2); // sum(dNv/dv*sum(Nu*z*w)) - temp3(3) += ders [ 1 ](1, l) * tmp1(3); // sum(dNv/dv*sum(Nu*w)) + temp3[0] += ders [ 1 ](1, l) * tmp1[0]; // sum(dNv/dv*sum(Nu*x*w)) + temp3[1] += ders [ 1 ](1, l) * tmp1[1]; // sum(dNv/dv*sum(Nu*y*w)) + temp3[2] += ders [ 1 ](1, l) * tmp1[2]; // sum(dNv/dv*sum(Nu*z*w)) + temp3[3] += ders [ 1 ](1, l) * tmp1[3]; // sum(dNv/dv*sum(Nu*w)) } ind = indx + numberOfControlPoints [ 0 ] * numberOfControlPoints [ 1 ]; - Aders [ 0 ](0) += ders [ 2 ](0, m) * temp1(0); // x=sum(Nt*sum(Nv*sum(Nu*x*w))) - Aders [ 1 ](0) += ders [ 2 ](0, m) * temp1(1); // y=sum(Nt*sum(Nv*sum(Nu*y*w))) - Aders [ 2 ](0) += ders [ 2 ](0, m) * temp1(2); // y=sum(Nt*sum(Nv*sum(Nu*y*w))) - wders(0) += ders [ 2 ](0, m) * temp1(3); // w=sum(Nt*sum(Nv*sum(Nu*w))) - - Aders [ 0 ](1) += ders [ 2 ](0, m) * temp2(0); // dx/du=sum(Nt*sum(Nv*sum(dNu/du*x*w))) - Aders [ 1 ](1) += ders [ 2 ](0, m) * temp2(1); // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y*w))) - Aders [ 2 ](1) += ders [ 2 ](0, m) * temp2(2); // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y*w))) - wders(1) += ders [ 2 ](0, m) * temp2(3); // dw/du=sum(Nt*sum(Nv*sum(dNu/du*w))) - - Aders [ 0 ](2) += ders [ 2 ](0, m) * temp3(0); // dx/dv=sum(Nt*sum(dNv/dv*sum(Nu*x*w))) - Aders [ 1 ](2) += ders [ 2 ](0, m) * temp3(1); // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y*w))) - Aders [ 2 ](2) += ders [ 2 ](0, m) * temp3(2); // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y*w))) - wders(2) += ders [ 2 ](0, m) * temp3(3); // dw/dv=sum(Nt*sum(dNv/dv*sum(Nu*w))) - - Aders [ 0 ](3) += ders [ 2 ](1, m) * temp1(0); // dx/dt=sum(dNt/dt*sum(Nv*sum(Nu*x*w))) - Aders [ 1 ](3) += ders [ 2 ](1, m) * temp1(1); // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y*w))) - Aders [ 2 ](3) += ders [ 2 ](1, m) * temp1(2); // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y*w))) - wders(3) += ders [ 2 ](1, m) * temp1(3); // dw/dt=sum(dNt/dt*sum(Nv*sum(Nu*w))) + Aders [ 0 ][0] += ders [ 2 ](0, m) * temp1[0]; // x=sum(Nt*sum(Nv*sum(Nu*x*w))) + Aders [ 1 ][0] += ders [ 2 ](0, m) * temp1[1]; // y=sum(Nt*sum(Nv*sum(Nu*y*w))) + Aders [ 2 ][0] += ders [ 2 ](0, m) * temp1[2]; // y=sum(Nt*sum(Nv*sum(Nu*y*w))) + wders[0] += ders [ 2 ](0, m) * temp1[3]; // w=sum(Nt*sum(Nv*sum(Nu*w))) + + Aders [ 0 ][1] += ders [ 2 ](0, m) * temp2[0]; // dx/du=sum(Nt*sum(Nv*sum(dNu/du*x*w))) + Aders [ 1 ][1] += ders [ 2 ](0, m) * temp2[1]; // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y*w))) + Aders [ 2 ][1] += ders [ 2 ](0, m) * temp2[2]; // dy/du=sum(Nt*sum(Nv*sum(dNu/du*y*w))) + wders[1] += ders [ 2 ](0, m) * temp2[3]; // dw/du=sum(Nt*sum(Nv*sum(dNu/du*w))) + + Aders [ 0 ][2] += ders [ 2 ](0, m) * temp3[0]; // dx/dv=sum(Nt*sum(dNv/dv*sum(Nu*x*w))) + Aders [ 1 ][2] += ders [ 2 ](0, m) * temp3[1]; // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y*w))) + Aders [ 2 ][2] += ders [ 2 ](0, m) * temp3[2]; // dy/dv=sum(Nt*sum(dNv/dv*sum(Nu*y*w))) + wders[2] += ders [ 2 ](0, m) * temp3[3]; // dw/dv=sum(Nt*sum(dNv/dv*sum(Nu*w))) + + Aders [ 0 ][3] += ders [ 2 ](1, m) * temp1[0]; // dx/dt=sum(dNt/dt*sum(Nv*sum(Nu*x*w))) + Aders [ 1 ][3] += ders [ 2 ](1, m) * temp1[1]; // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y*w))) + Aders [ 2 ][3] += ders [ 2 ](1, m) * temp1[2]; // dy/dt=sum(dNt/dt*sum(Nv*sum(Nu*y*w))) + wders[3] += ders [ 2 ](1, m) * temp1[3]; // dw/dt=sum(dNt/dt*sum(Nv*sum(Nu*w))) } - weight = wders(0); + double weight = wders[0]; // calculation of jacobian matrix - tmp1(0) = Aders [ 0 ](0) / weight; - tmp1(1) = Aders [ 1 ](0) / weight; - tmp1(2) = Aders [ 2 ](0) / weight; - jacobian(0, 0) = ( Aders [ 0 ](1) - wders(1) * tmp1(0) ) / weight; // dx/du - jacobian(0, 1) = ( Aders [ 1 ](1) - wders(1) * tmp1(1) ) / weight; // dy/du - jacobian(0, 2) = ( Aders [ 2 ](1) - wders(1) * tmp1(2) ) / weight; // dz/du - jacobian(1, 0) = ( Aders [ 0 ](2) - wders(2) * tmp1(0) ) / weight; // dx/dv - jacobian(1, 1) = ( Aders [ 1 ](2) - wders(2) * tmp1(1) ) / weight; // dy/dv - jacobian(1, 2) = ( Aders [ 2 ](2) - wders(2) * tmp1(2) ) / weight; // dz/dv - jacobian(2, 0) = ( Aders [ 0 ](3) - wders(3) * tmp1(0) ) / weight; // dx/dt - jacobian(2, 1) = ( Aders [ 1 ](3) - wders(3) * tmp1(1) ) / weight; // dy/dt - jacobian(2, 2) = ( Aders [ 2 ](3) - wders(3) * tmp1(2) ) / weight; // dz/dt + tmp1[0] = Aders [ 0 ][0] / weight; + tmp1[1] = Aders [ 1 ][0] / weight; + tmp1[2] = Aders [ 2 ][0] / weight; + jacobian(0, 0) = ( Aders [ 0 ][1] - wders[1] * tmp1[0] ) / weight; // dx/du + jacobian(0, 1) = ( Aders [ 1 ][1] - wders[1] * tmp1[1] ) / weight; // dy/du + jacobian(0, 2) = ( Aders [ 2 ][1] - wders[1] * tmp1[2] ) / weight; // dz/du + jacobian(1, 0) = ( Aders [ 0 ][2] - wders[2] * tmp1[0] ) / weight; // dx/dv + jacobian(1, 1) = ( Aders [ 1 ][2] - wders[2] * tmp1[1] ) / weight; // dy/dv + jacobian(1, 2) = ( Aders [ 2 ][2] - wders[2] * tmp1[2] ) / weight; // dz/dv + jacobian(2, 0) = ( Aders [ 0 ][3] - wders[3] * tmp1[0] ) / weight; // dx/dt + jacobian(2, 1) = ( Aders [ 1 ][3] - wders[3] * tmp1[1] ) / weight; // dy/dt + jacobian(2, 2) = ( Aders [ 2 ][3] - wders[3] * tmp1[2] ) / weight; // dz/dt } else { OOFEM_ERROR("not implemented for nsd = %d", nsd); } diff --git a/src/oofemlib/iga/feinurbs.h b/src/oofemlib/iga/feinurbs.h index 0ebdd924a..ca9fa1daf 100644 --- a/src/oofemlib/iga/feinurbs.h +++ b/src/oofemlib/iga/feinurbs.h @@ -40,26 +40,35 @@ #include "floatmatrix.h" #include "mathfem.h" +///@name Input fields for NURBSInterpolation +//@{ +#define _IFT_NURBSInterpolation_weights "weights" +//@} + namespace oofem { /** * Interpolation class for NURBS. */ class OOFEM_EXPORT NURBSInterpolation : public BSplineInterpolation { +protected: + FloatArray weights; + public: NURBSInterpolation(int nsd) : BSplineInterpolation(nsd) { } - virtual ~NURBSInterpolation(); - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { + void initializeFrom(InputRecord &ir) override; + + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Not yet implemented."); return 0; } - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; - virtual const char *giveClassName() const { return "NURBSInterpolation"; } + const char *giveClassName() const { return "NURBSInterpolation"; } }; } // end namespace oofem #endif // feinurbs_h diff --git a/src/oofemlib/iga/feitspline.C b/src/oofemlib/iga/feitspline.C index 013ef9f88..e51dd96ad 100644 --- a/src/oofemlib/iga/feitspline.C +++ b/src/oofemlib/iga/feitspline.C @@ -43,31 +43,11 @@ namespace oofem { #define OPTIMIZED_VERSION_A4dot4 -TSplineInterpolation :: ~TSplineInterpolation() +void TSplineInterpolation :: initializeFrom(InputRecord &ir) { - for ( int i = 0; i <= numberOfControlPoints [ 0 ]; i++ ) { - for ( int j = 0; j < nsd; j++ ) { - delete [] localIndexKnotVector [ i ] [ j ]; - } - - delete [] localIndexKnotVector [ i ]; - } - - delete [] localIndexKnotVector; - - delete [] openLocalKnotVector; -} - - -IRResultType TSplineInterpolation :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - BSplineInterpolation :: initializeFrom(ir); IntArray localIndexKnotVector_tmp; - int *indexKnotVec, indexKnotVal; - int pos, p; InputFieldType IFT_localIndexKnotVector [ 3 ] = { _IFT_TSplineInterpolation_localIndexKnotVectorU, @@ -81,37 +61,32 @@ IRResultType TSplineInterpolation :: initializeFrom(InputRecord *ir) } } - openLocalKnotVector = new double [ 3 * max_deg + 2 ]; + //openLocalKnotVector.resize( 3 * max_deg + 2 ); - localIndexKnotVector = new int ** [ totalNumberOfControlPoints ]; - for ( int i = 0; i < totalNumberOfControlPoints; i++ ) { - localIndexKnotVector [ i ] = new int * [ nsd ]; - } + localIndexKnotVector.resize( totalNumberOfControlPoints ); for ( int n = 0; n < nsd; n++ ) { localIndexKnotVector_tmp.clear(); IR_GIVE_FIELD(ir, localIndexKnotVector_tmp, IFT_localIndexKnotVector [ n ]); if ( localIndexKnotVector_tmp.giveSize() != totalNumberOfControlPoints * ( degree [ n ] + 2 ) ) { - OOFEM_WARNING("invalid size of knot vector %s", IFT_localIndexKnotVector [ n ]); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, IFT_localIndexKnotVector [ n ], "invalid size of knot vector"); } - pos = 0; + int pos = 0; for ( int i = 0; i < totalNumberOfControlPoints; i++ ) { - indexKnotVec = localIndexKnotVector [ i ] [ n ] = new int [ degree [ n ] + 2 ]; + auto &indexKnotVec = localIndexKnotVector [ i ] [ n ]; + indexKnotVec.resize( degree [ 2 ] + 2 ); - p = 0; + int p = 0; for ( int j = 0; j < degree [ n ] + 2; j++ ) { - indexKnotVec [ p++ ] = localIndexKnotVector_tmp(pos++); + indexKnotVec [ p++ ] = localIndexKnotVector_tmp[pos++]; } // check for monotonicity of local index knot vector with multiplicity - indexKnotVal = indexKnotVec [ 0 ]; + int indexKnotVal = indexKnotVec [ 0 ]; for ( int j = 1; j < degree [ n ] + 2; j++ ) { if ( indexKnotVal > indexKnotVec [ j ] ) { - OOFEM_WARNING("local index knot vector %s of control point %d is not monotonic", - IFT_localIndexKnotVector [ n ], i + 1); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, IFT_localIndexKnotVector [ n ], "local index knot vector is not monotonic"); } /* this is only for the case when TSpline = NURBS @@ -124,27 +99,23 @@ IRResultType TSplineInterpolation :: initializeFrom(InputRecord *ir) // check for nondegeneracy of local index knot vector if ( indexKnotVal == indexKnotVec [ 0 ] ) { - OOFEM_WARNING("local index knot vector %s of control point %d is degenerated", - IFT_localIndexKnotVector [ n ], i + 1); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, IFT_localIndexKnotVector [ n ], "local index knot vector is degenerated"); } // check for range of local index knot vector if ( indexKnotVec [ 0 ] <= 0 || indexKnotVal > knotValues [ n ].giveSize() ) { - OOFEM_WARNING("local index knot vector %s of control point %d out of range", - IFT_localIndexKnotVector [ n ], i + 1); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, IFT_localIndexKnotVector [ n ], "local index knot vector out of range"); } } } - return IRRT_OK; + IR_GIVE_FIELD(ir, this->weights, _IFT_TSplineInterpolation_weights); } -void TSplineInterpolation :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void TSplineInterpolation :: evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); FloatArray N(nsd); IntArray span(nsd); IntArray mask; @@ -155,11 +126,11 @@ void TSplineInterpolation :: evalN(FloatArray &answer, const FloatArray &lcoords OOFEM_ERROR("implemented for nsd = %d", nsd); } - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } @@ -171,29 +142,26 @@ void TSplineInterpolation :: evalN(FloatArray &answer, const FloatArray &lcoords if ( nsd == 2 ) { for ( int k = 0; k < count; k++ ) { for ( int i = 0; i < nsd; i++ ) { - N(i) = this->basisFunction(lcoords(i), degree [ i ], * giveKnotValues(i + 1), localIndexKnotVector [ mask(k) - 1 ] [ i ]); + N[i] = this->basisFunction(lcoords[i], degree [ i ], * giveKnotValues(i + 1), localIndexKnotVector [ mask[k] - 1 ] [ i ]); } - answer(k) = val = N(0) * N(1) * cellgeo.giveVertexCoordinates( mask(k) )->at(3); // Nu*Nv*w + answer[k] = val = N[0] * N[1] * this->weights.at( mask[k] ); // Nu*Nv*w sum += val; } } - while ( count ) { - answer.at(count--) /= sum; - } + answer.times(1./sum); } -double TSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +double TSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; - const FloatArray *vertexCoordsPtr; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); FloatMatrix jacobian(nsd, nsd); FloatArray temp(nsd); IntArray span(nsd); IntArray mask; - double Jacob = 0., product, w, xw, yw, weight; + double Jacob = 0.; int count; std :: vector< FloatArray > tmp_ders(nsd); std :: vector< FloatMatrix > ders(nsd); @@ -208,11 +176,11 @@ double TSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &l OOFEM_ERROR("not implemented for nsd = %d", nsd); } - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } @@ -244,35 +212,36 @@ double TSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &l for ( int k = 0; k < count; k++ ) { for ( int i = 0; i < nsd; i++ ) { // it would be simpler if I could pass k-th column of ders[i] directly to dersBasisFunction HUHU array - this->dersBasisFunction(1, lcoords(i), degree [ i ], * giveKnotValues(i + 1), localIndexKnotVector [ mask(k) - 1 ] [ i ], tmp_ders [ i ]); - ders [ i ](0, k) = tmp_ders [ i ](0); - ders [ i ](1, k) = tmp_ders [ i ](1); + this->dersBasisFunction(1, lcoords[i], degree [ i ], * giveKnotValues(i + 1), localIndexKnotVector [ mask[k] - 1 ] [ i ], tmp_ders [ i ]); + ders [ i ](0, k) = tmp_ders [ i ][0]; + ders [ i ](1, k) = tmp_ders [ i ][1]; } // calculation of jacobian matrix in similar fashion as A4.4 // calculate values and derivatives of nonrational Bspline surface with weights at first (Aders, wders) - vertexCoordsPtr = cellgeo.giveVertexCoordinates( mask(k) ); - w = vertexCoordsPtr->at(3); - xw = vertexCoordsPtr->at(1) * w; - yw = vertexCoordsPtr->at(2) * w; + const auto &vertexCoords = cellgeo.giveVertexCoordinates( mask[k] ); + double w = this->weights.at( mask[k] ); + double xw = vertexCoords[0] * w; + double yw = vertexCoords[1] * w; + double product; - product = tmp_ders [ 0 ](0) * tmp_ders [ 1 ](0); // Nu*Nv + product = tmp_ders [ 0 ][0] * tmp_ders [ 1 ][0]; // Nu*Nv Aders [ 0 ](0, 0) += product * xw; // x=sum Nu*Nv*x*w Aders [ 1 ](0, 0) += product * yw; // x=sum Nu*Nv*y*w wders(0, 0) += product * w; // w=sum Nu*Nv*w - product = tmp_ders [ 0 ](1) * tmp_ders [ 1 ](0); // dNu/du*Nv + product = tmp_ders [ 0 ][1] * tmp_ders [ 1 ][0]; // dNu/du*Nv Aders [ 0 ](1, 0) += product * xw; // dx/du=sum dNu/du*Nv*x*w Aders [ 1 ](1, 0) += product * yw; // dy/du=sum dNu/du*Nv*y*w wders(1, 0) += product * w; // dw/du=sum dNu/du*Nv*w - product = tmp_ders [ 0 ](0) * tmp_ders [ 1 ](1); // Nu*dNv/dv + product = tmp_ders [ 0 ][0] * tmp_ders [ 1 ][1]; // Nu*dNv/dv Aders [ 0 ](0, 1) += product * xw; // dx/dv=sum Nu*dNv/dv*x*w Aders [ 1 ](0, 1) += product * yw; // dy/dv=sum Nu*dNv/dv*y*w wders(0, 1) += product * w; // dw/dv=sum Nu*dNv/dv*w } - weight = wders(0, 0); + double weight = wders(0, 0); // optimized version of A4.4 for d=1, binomial coefficients ignored /* @@ -289,27 +258,27 @@ double TSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &l * jacobian(1,1) = Sders[1](0,1); // dy/dv */ - temp(0) = Aders [ 0 ](0, 0) / weight; - temp(1) = Aders [ 1 ](0, 0) / weight; - jacobian(1, 0) = ( Aders [ 0 ](0, 1) - wders(0, 1) * temp(0) ) / weight; // dx/dv - jacobian(1, 1) = ( Aders [ 1 ](0, 1) - wders(0, 1) * temp(1) ) / weight; // dy/dv - jacobian(0, 0) = ( Aders [ 0 ](1, 0) - wders(1, 0) * temp(0) ) / weight; // dx/du - jacobian(0, 1) = ( Aders [ 1 ](1, 0) - wders(1, 0) * temp(1) ) / weight; // dy/du + temp[0] = Aders [ 0 ](0, 0) / weight; + temp[1] = Aders [ 1 ](0, 0) / weight; + jacobian(1, 0) = ( Aders [ 0 ](0, 1) - wders(0, 1) * temp[0] ) / weight; // dx/dv + jacobian(1, 1) = ( Aders [ 1 ](0, 1) - wders(0, 1) * temp[1] ) / weight; // dy/dv + jacobian(0, 0) = ( Aders [ 0 ](1, 0) - wders(1, 0) * temp[0] ) / weight; // dx/du + jacobian(0, 1) = ( Aders [ 1 ](1, 0) - wders(1, 0) * temp[1] ) / weight; // dy/du Jacob = jacobian.giveDeterminant(); //calculation of derivatives of TSpline basis functions with respect to local parameters - product = Jacob * weight * weight; + double product = Jacob * weight * weight; for ( int k = 0; k < count; k++ ) { - w = cellgeo.giveVertexCoordinates( mask(k) )->at(3); + double w = this->weights.at( mask[k] ); // dNu/du*Nv*w*sum(Nv*Nu*w) - Nu*Nv*w*sum(dNu/du*Nv*w) - temp(0) = ders [ 0 ](1, k) * ders [ 1 ](0, k) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, k) * w * wders(1, 0); + temp[0] = ders [ 0 ](1, k) * ders [ 1 ](0, k) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, k) * w * wders(1, 0); // Nu*dNv/dv*w*sum(Nv*Nu*w) - Nu*Nv*w*sum(Nu*dNv/dv*w) - temp(1) = ders [ 0 ](0, k) * ders [ 1 ](1, k) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, k) * w * wders(0, 1); + temp[1] = ders [ 0 ](0, k) * ders [ 1 ](1, k) * w * weight - ders [ 0 ](0, k) * ders [ 1 ](0, k) * w * wders(0, 1); - answer(k, 0) = ( jacobian(1, 1) * temp(0) - jacobian(0, 1) * temp(1) ) / product; - answer(k, 1) = ( -jacobian(1, 0) * temp(0) + jacobian(0, 0) * temp(1) ) / product; + answer(k, 0) = ( jacobian(1, 1) * temp[0] - jacobian(0, 1) * temp[1] ) / product; + answer(k, 1) = ( -jacobian(1, 0) * temp[0] + jacobian(0, 0) * temp[1] ) / product; } } @@ -317,26 +286,25 @@ double TSplineInterpolation :: evaldNdx(FloatMatrix &answer, const FloatArray &l } -void TSplineInterpolation :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void TSplineInterpolation :: local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { /* Based on SurfacePoint A4.3 implementation*/ - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; - const FloatArray *vertexCoordsPtr; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); FloatArray N(nsd); IntArray span(nsd); IntArray mask; - double w, xw, yw, product, weight = 0.0; + double weight = 0.0; int count; if ( nsd != 2 ) { OOFEM_ERROR("not implemented for nsd = %d", nsd); } - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } @@ -350,17 +318,17 @@ void TSplineInterpolation :: local2global(FloatArray &answer, const FloatArray & if ( nsd == 2 ) { for ( int k = 0; k < count; k++ ) { for ( int i = 0; i < nsd; i++ ) { - N(i) = this->basisFunction(lcoords(i), degree [ i ], * giveKnotValues(i + 1), localIndexKnotVector [ mask(k) - 1 ] [ i ]); + N[i] = this->basisFunction(lcoords[i], degree [ i ], * giveKnotValues(i + 1), localIndexKnotVector [ mask[k] - 1 ] [ i ]); } - vertexCoordsPtr = cellgeo.giveVertexCoordinates( mask(k) ); - w = vertexCoordsPtr->at(3); - xw = vertexCoordsPtr->at(1) * w; - yw = vertexCoordsPtr->at(2) * w; + const auto &vertexCoords = cellgeo.giveVertexCoordinates( mask[k] ); + double w = this->weights.at( mask[k] ); + double xw = vertexCoords[0] * w; + double yw = vertexCoords[1] * w; - product = N(0) * N(1); // Nu*Nv - answer(0) += product * xw; // x=sum Nu*Nv*x*w - answer(1) += product * yw; // y=sum Nu*Nv*y*w + double product = N[0] * N[1]; // Nu*Nv + answer[0] += product * xw; // x=sum Nu*Nv*x*w + answer[1] += product * yw; // y=sum Nu*Nv*y*w weight += product * w; // w=sum Nu*Nv*w } } @@ -369,17 +337,15 @@ void TSplineInterpolation :: local2global(FloatArray &answer, const FloatArray & } -void TSplineInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const FloatArray &lcoords, const FEICellGeometry &cellgeo) +void TSplineInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const { // // Based on Algorithm A4.4 (p. 137) for d=1 // - FEIIGAElementGeometryWrapper *gw = ( FEIIGAElementGeometryWrapper * ) & cellgeo; - const FloatArray *vertexCoordsPtr; + const FEIIGAElementGeometryWrapper &gw = static_cast< const FEIIGAElementGeometryWrapper& >(cellgeo); FloatArray temp(nsd); IntArray span(nsd); IntArray mask; - double w, xw, yw, product, weight; int count; std :: vector< FloatArray > ders(nsd); jacobian.resize(nsd, nsd); @@ -394,11 +360,11 @@ void TSplineInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const F OOFEM_ERROR("not implemented for nsd = %d", nsd); } - if ( gw->knotSpan ) { - span = * gw->knotSpan; + if ( gw.knotSpan ) { + span = * gw.knotSpan; } else { for ( int i = 0; i < nsd; i++ ) { - span(i) = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords(i), knotVector [ i ]); + span[i] = this->findSpan(numberOfControlPoints [ i ], degree [ i ], lcoords[i], knotVector [ i ]); } } @@ -424,33 +390,34 @@ void TSplineInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const F for ( int k = 0; k < count; k++ ) { for ( int i = 0; i < nsd; i++ ) { - this->dersBasisFunction(1, lcoords(i), degree [ i ], * giveKnotValues(i + 1), localIndexKnotVector [ mask(k) - 1 ] [ i ], ders [ i ]); + this->dersBasisFunction(1, lcoords[i], degree [ i ], * giveKnotValues(i + 1), localIndexKnotVector [ mask[k] - 1 ] [ i ], ders [ i ]); } // calculation of jacobian matrix in similar fashion as A4.4 // calculate values and derivatives of nonrational Bspline surface with weights at first (Aders, wders) - vertexCoordsPtr = cellgeo.giveVertexCoordinates( mask(k) ); - w = vertexCoordsPtr->at(3); - xw = vertexCoordsPtr->at(1) * w; - yw = vertexCoordsPtr->at(2) * w; + const auto &vertexCoords = cellgeo.giveVertexCoordinates( mask[k] ); + double w = this->weights.at( mask[k] ); + double xw = vertexCoords[0] * w; + double yw = vertexCoords[1] * w; + double product; - product = ders [ 0 ](0) * ders [ 1 ](0); // Nu*Nv + product = ders [ 0 ][0] * ders [ 1 ][0]; // Nu*Nv Aders [ 0 ](0, 0) += product * xw; // x=sum Nu*Nv*x*w Aders [ 1 ](0, 0) += product * yw; // x=sum Nu*Nv*y*w wders(0, 0) += product * w; // w=sum Nu*Nv*w - product = ders [ 0 ](1) * ders [ 1 ](0); // dNu/du*Nv + product = ders [ 0 ][1] * ders [ 1 ][0]; // dNu/du*Nv Aders [ 0 ](1, 0) += product * xw; // dx/du=sum dNu/du*Nv*x*w Aders [ 1 ](1, 0) += product * yw; // dy/du=sum dNu/du*Nv*y*w wders(1, 0) += product * w; // dw/du=sum dNu/du*Nv*w - product = ders [ 0 ](0) * ders [ 1 ](1); // Nu*dNv/dv + product = ders [ 0 ][0] * ders [ 1 ][1]; // Nu*dNv/dv Aders [ 0 ](0, 1) += product * xw; // dx/dv=sum Nu*dNv/dv*x*w Aders [ 1 ](0, 1) += product * yw; // dy/dv=sum Nu*dNv/dv*y*w wders(0, 1) += product * w; // dw/dv=sum Nu*dNv/dv*w } - weight = wders(0, 0); + double weight = wders(0, 0); // optimized version of A4.4 for d=1, binomial coefficients ignored #if 0 @@ -467,12 +434,12 @@ void TSplineInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const F jacobian(1,1) = Sders[1](0,1); // dy/dv #endif - temp(0) = Aders [ 0 ](0, 0) / weight; - temp(1) = Aders [ 1 ](0, 0) / weight; - jacobian(1, 0) = ( Aders [ 0 ](0, 1) - wders(0, 1) * temp(0) ) / weight; // dx/dv - jacobian(1, 1) = ( Aders [ 1 ](0, 1) - wders(0, 1) * temp(1) ) / weight; // dy/dv - jacobian(0, 0) = ( Aders [ 0 ](1, 0) - wders(1, 0) * temp(0) ) / weight; // dx/du - jacobian(0, 1) = ( Aders [ 1 ](1, 0) - wders(1, 0) * temp(1) ) / weight; // dy/du + temp[0] = Aders [ 0 ](0, 0) / weight; + temp[1] = Aders [ 1 ](0, 0) / weight; + jacobian(1, 0) = ( Aders [ 0 ](0, 1) - wders(0, 1) * temp[0] ) / weight; // dx/dv + jacobian(1, 1) = ( Aders [ 1 ](0, 1) - wders(0, 1) * temp[1] ) / weight; // dy/dv + jacobian(0, 0) = ( Aders [ 0 ](1, 0) - wders(1, 0) * temp[0] ) / weight; // dx/du + jacobian(0, 1) = ( Aders [ 1 ](1, 0) - wders(1, 0) * temp[1] ) / weight; // dy/du } } @@ -482,7 +449,7 @@ void TSplineInterpolation :: giveJacobianMatrixAt(FloatMatrix &jacobian, const F // this implementation relies on the fact that IGAIntegrationElements are those subsets // of T-mesh cells on which there are fully (this means not only partially) nonzero relevant basis functions -int TSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask) +int TSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask) const { FloatArray knotStart(nsd), knotEnd(nsd); @@ -496,8 +463,8 @@ int TSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &knotSpan, // get starting and ending knots for ( int j = 0; j < nsd; j++ ) { - knotStart(j) = knotVector [ j ] [ knotSpan(j) ]; - knotEnd(j) = knotVector [ j ] [ knotSpan(j) + 1 ]; + knotStart[j] = knotVector [ j ] [ knotSpan[j] ]; + knotEnd[j] = knotVector [ j ] [ knotSpan[j] + 1 ]; } // for each control point check @@ -505,8 +472,8 @@ int TSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &knotSpan, // whether local knot vector overlaps the given knot span int nonzero = 1; for ( int j = 0; j < nsd; j++ ) { - if ( ( knotEnd(j) <= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ 0 ]) ) || - ( knotStart(j) >= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ degree [ j ] + 1 ]) ) ) { + if ( ( knotEnd[j] <= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ 0 ]) ) || + ( knotStart[j] >= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ degree [ j ] + 1 ]) ) ) { nonzero = 0; break; } @@ -527,15 +494,15 @@ int TSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &knotSpan, // this implementation relies on the fact that IGAIntegrationElements are those subsets // of T-mesh cells on which there are fully (this means not only partially) nonzero relevant basis functions -int TSplineInterpolation :: giveNumberOfKnotSpanBasisFunctions(const IntArray &knotSpan) +int TSplineInterpolation :: giveNumberOfKnotSpanBasisFunctions(const IntArray &knotSpan) const { int answer = 0; FloatArray knotStart(nsd), knotEnd(nsd); // get starting and ending knots for ( int j = 0; j < nsd; j++ ) { - knotStart(j) = knotVector [ j ] [ knotSpan(j) ]; - knotEnd(j) = knotVector [ j ] [ knotSpan(j) + 1 ]; + knotStart[j] = knotVector [ j ] [ knotSpan[j] ]; + knotEnd[j] = knotVector [ j ] [ knotSpan[j] + 1 ]; } // for each control point check @@ -543,8 +510,8 @@ int TSplineInterpolation :: giveNumberOfKnotSpanBasisFunctions(const IntArray &k answer++; // whether local knot vector overlaps the given knot span for ( int j = 0; j < nsd; j++ ) { - if ( ( knotEnd(j) <= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ 0 ]) ) || - ( knotStart(j) >= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ degree [ j ] + 1 ]) ) ) { + if ( ( knotEnd[j] <= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ 0 ]) ) || + ( knotStart[j] >= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ degree [ j ] + 1 ]) ) ) { answer--; break; } @@ -561,7 +528,7 @@ int TSplineInterpolation :: giveNumberOfKnotSpanBasisFunctions(const IntArray &k // starKnotSpan and endKnotSpan are equal; // some of the basis function may not cover the whole knot span interval !!! -int TSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &startKnotSpan, const IntArray &endKnotSpan, IntArray &mask) +int TSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &startKnotSpan, const IntArray &endKnotSpan, IntArray &mask) const { int nonzero; FloatArray knotStart(nsd), knotEnd(nsd); @@ -576,8 +543,8 @@ int TSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &startKnotS // get starting and ending knots for ( int j = 0; j < nsd; j++ ) { - knotStart(j) = knotVector [ j ] [ startKnotSpan(j) ]; - knotEnd(j) = knotVector [ j ] [ endKnotSpan(j) + 1 ]; + knotStart[j] = knotVector [ j ] [ startKnotSpan[j] ]; + knotEnd[j] = knotVector [ j ] [ endKnotSpan[j] + 1 ]; } // for each control point check @@ -585,8 +552,8 @@ int TSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &startKnotS // whether local knot vector overlaps at least partially the knot span interval nonzero = 1; for ( int j = 0; j < nsd; j++ ) { - if ( ( knotEnd(j) <= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ 0 ]) ) || - ( knotStart(j) >= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ degree [ j ] + 1 ]) ) ) { + if ( ( knotEnd[j] <= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ 0 ]) ) || + ( knotStart[j] >= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ degree [ j ] + 1 ]) ) ) { nonzero = 0; break; } @@ -606,15 +573,15 @@ int TSplineInterpolation :: giveKnotSpanBasisFuncMask(const IntArray &startKnotS // starKnotSpan and endKnotSpan are equal // some of the basis function may not cover the whole knot span interval !!! -int TSplineInterpolation :: giveNumberOfKnotSpanBasisFunctions(const IntArray &startKnotSpan, const IntArray &endKnotSpan) +int TSplineInterpolation :: giveNumberOfKnotSpanBasisFunctions(const IntArray &startKnotSpan, const IntArray &endKnotSpan) const { int answer = 0; FloatArray knotStart(nsd), knotEnd(nsd); // get starting and ending knots for ( int j = 0; j < nsd; j++ ) { - knotStart(j) = knotVector [ j ] [ startKnotSpan(j) ]; - knotEnd(j) = knotVector [ j ] [ endKnotSpan(j) + 1 ]; + knotStart[j] = knotVector [ j ] [ startKnotSpan[j] ]; + knotEnd[j] = knotVector [ j ] [ endKnotSpan[j] + 1 ]; } // for each control point check @@ -622,8 +589,8 @@ int TSplineInterpolation :: giveNumberOfKnotSpanBasisFunctions(const IntArray &s answer++; // whether local knot vector overlaps at least partially the knot span interval for ( int j = 0; j < nsd; j++ ) { - if ( ( knotEnd(j) <= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ 0 ]) ) || - ( knotStart(j) >= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ degree [ j ] + 1 ]) ) ) { + if ( ( knotEnd[j] <= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ 0 ]) ) || + ( knotStart[j] >= knotValues [ j ].at(localIndexKnotVector [ i ] [ j ] [ degree [ j ] + 1 ]) ) ) { answer--; break; } @@ -637,12 +604,12 @@ int TSplineInterpolation :: giveNumberOfKnotSpanBasisFunctions(const IntArray &s // call corresponding BSpline methods for open local knot vector -double TSplineInterpolation :: basisFunction(double u, int p, const FloatArray &U, const int *I) +double TSplineInterpolation :: basisFunction(double u, int p, const FloatArray &U, const IntArray &I) const { int span, prepend, append; - FloatArray N; + FloatArray N, openLocalKnotVector; - createLocalKnotVector(p, U, I, & prepend, & append); + createLocalKnotVector(openLocalKnotVector, p, U, I, prepend, append); span = BSplineInterpolation :: findSpan(prepend + append, p, u, openLocalKnotVector); BSplineInterpolation :: basisFuns(N, span, u, p, openLocalKnotVector); @@ -654,12 +621,13 @@ double TSplineInterpolation :: basisFunction(double u, int p, const FloatArray & // call corresponding BSpline methods for open local knot vector -void TSplineInterpolation :: dersBasisFunction(int n, double u, int p, const FloatArray &U, const int *I, FloatArray &ders) +void TSplineInterpolation :: dersBasisFunction(int n, double u, int p, const FloatArray &U, const IntArray &I, FloatArray &ders) const { int span, prepend, append; + FloatArray openLocalKnotVector; FloatMatrix Ders; - createLocalKnotVector(p, U, I, & prepend, & append); + createLocalKnotVector(openLocalKnotVector, p, U, I, prepend, append); span = BSplineInterpolation :: findSpan(prepend + append, p, u, openLocalKnotVector); BSplineInterpolation :: dersBasisFuns(n, u, span, p, openLocalKnotVector, Ders); @@ -667,16 +635,23 @@ void TSplineInterpolation :: dersBasisFunction(int n, double u, int p, const Flo // this corresponds to index p-span, however prepended knotspans must be considered ders.resize(n + 1); for ( int i = 0; i <= n; i++ ) { - ders(i) = Ders(i, p - span + prepend); + ders[i] = Ders(i, p - span + prepend); } } -void TSplineInterpolation :: createLocalKnotVector(int p, const FloatArray &U, const int *I, int *prepend, int *append) +void TSplineInterpolation :: createLocalKnotVector(FloatArray &openLocalKnotVector, int p, const FloatArray &U, const IntArray &I, int &prepend, int &append) const { int j = 0, index_first = I [ 0 ], index_last = I [ p + 1 ], mult_first = 1, mult_last = 1; double first = U.at(index_first), last = U.at(index_last); - + int max_deg = 0; + for ( int i = 0; i < nsd; i++ ) { + if ( degree [ i ] > max_deg ) { + max_deg = degree [ i ]; + } + } + openLocalKnotVector.resize( 3 * max_deg + 2 ); + for ( int i = 1; i < p + 1; i++ ) { if ( I [ i ] != index_first ) { break; @@ -693,11 +668,11 @@ void TSplineInterpolation :: createLocalKnotVector(int p, const FloatArray &U, c mult_last++; } - * prepend = p + 1 - mult_first; - * append = p + 1 - mult_last; + prepend = p + 1 - mult_first; + append = p + 1 - mult_last; // prepend first knot (once more) - for ( int i = 0; i <= * prepend; i++ ) { + for ( int i = 0; i <= prepend; i++ ) { openLocalKnotVector [ j++ ] = first; } @@ -707,7 +682,7 @@ void TSplineInterpolation :: createLocalKnotVector(int p, const FloatArray &U, c } // append last knot (once more) - for ( int i = 0; i <= * append; i++ ) { + for ( int i = 0; i <= append; i++ ) { openLocalKnotVector [ j++ ] = last; } } diff --git a/src/oofemlib/iga/feitspline.h b/src/oofemlib/iga/feitspline.h index 3210a18e7..2435795a5 100644 --- a/src/oofemlib/iga/feitspline.h +++ b/src/oofemlib/iga/feitspline.h @@ -49,6 +49,7 @@ ///@name Input fields for TSplineInterpolation //@{ +#define _IFT_TSplineInterpolation_weights "weights" #define _IFT_TSplineInterpolation_localIndexKnotVectorU "localindexknotvectoru" #define _IFT_TSplineInterpolation_localIndexKnotVectorV "localindexknotvectorv" #define _IFT_TSplineInterpolation_localIndexKnotVectorW "localindexknotvectorw" @@ -62,29 +63,29 @@ class OOFEM_EXPORT TSplineInterpolation : public BSplineInterpolation { protected: /// Local index knot vector of the dimensions [totalNumberOfControlPoints][nsd][degree+2]. - int ***localIndexKnotVector; - int totalNumberOfControlPoints; + std::vector< std::array > localIndexKnotVector; + int totalNumberOfControlPoints = 0; + FloatArray weights; /** * Temporary open local knot vector to enable use of BSpline algorithms (common for all directions) [3*max_degree+2]. */ - double *openLocalKnotVector; + //FloatArray openLocalKnotVector; public: TSplineInterpolation(int nsd) : BSplineInterpolation(nsd) { } - virtual ~TSplineInterpolation(); - IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; void setNumberOfControlPoints(int num) { this->totalNumberOfControlPoints = num; } - virtual void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo); - virtual int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) { + void evalN(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + double evaldNdx(FloatMatrix &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + void local2global(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; + int global2local(FloatArray &answer, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override { OOFEM_ERROR("Not yet implemented, contact lazy dr for implementation"); return 0; } - virtual void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo); + void giveJacobianMatrixAt(FloatMatrix &jacobianMatrix, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const override; - virtual int giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask); - virtual int giveNumberOfKnotSpanBasisFunctions(const IntArray &knotSpan); + int giveKnotSpanBasisFuncMask(const IntArray &knotSpan, IntArray &mask) const override; + int giveNumberOfKnotSpanBasisFunctions(const IntArray &knotSpan) const override; const char *giveClassName() const { return "TSplineInterpolation"; } @@ -98,7 +99,7 @@ class OOFEM_EXPORT TSplineInterpolation : public BSplineInterpolation * @return N Computed middle basis function. * @warning Parameter u must be in a valid range. */ - double basisFunction(double u, int p, const FloatArray &U, const int *I); + double basisFunction(double u, int p, const FloatArray &U, const IntArray &I) const; /** * Computes the middle basis function and it derivatives on local knot vector at u. * The result is stored in the ders vector @@ -116,7 +117,7 @@ class OOFEM_EXPORT TSplineInterpolation : public BSplineInterpolation * * @warning Parameters n and u must be in a valid range. */ - void dersBasisFunction(int n, double u, int p, const FloatArray &U, const int *I, FloatArray &ders); + void dersBasisFunction(int n, double u, int p, const FloatArray &U, const IntArray &I, FloatArray &ders) const; /** * Creates local open knot vector. * This is generally done extracting knot values from global knot vector using the local index knot vector @@ -128,13 +129,13 @@ class OOFEM_EXPORT TSplineInterpolation : public BSplineInterpolation * @param prepend Number of prepended entries * @param append Number of appended entries */ - void createLocalKnotVector(int p, const FloatArray &U, const int *I, int *prepend, int *append); + void createLocalKnotVector(FloatArray& answer, int p, const FloatArray &U, const IntArray &I, int &prepend, int &append) const; /** * Returns indices (zero based) of nonzero basis functions for given knot span interval. */ - int giveKnotSpanBasisFuncMask(const IntArray &startKnotSpan, const IntArray &endKnotSpan, IntArray &mask); + int giveKnotSpanBasisFuncMask(const IntArray &startKnotSpan, const IntArray &endKnotSpan, IntArray &mask) const; /** Returns the number of nonzero basis functions at given knot span interval. */ - int giveNumberOfKnotSpanBasisFunctions(const IntArray &startKnotSpan, const IntArray &endKnotSpan); + int giveNumberOfKnotSpanBasisFunctions(const IntArray &startKnotSpan, const IntArray &endKnotSpan) const; }; // end of TSplineInterpolation class definition } // end namespace oofem #endif //feitspline_h diff --git a/src/oofemlib/iga/iga.C b/src/oofemlib/iga/iga.C index 636cebd90..bd6399d2b 100644 --- a/src/oofemlib/iga/iga.C +++ b/src/oofemlib/iga/iga.C @@ -43,33 +43,27 @@ #ifdef __OOFEG #include "oofeggraphiccontext.h" #include "oofegutils.h" - #include "../sm/Elements/structuralelementevaluator.h" + #include "sm/Elements/structuralelementevaluator.h" #endif namespace oofem { -IRResultType IGAElement :: initializeFrom(InputRecord *ir) +void IGAElement :: initializeFrom(InputRecord &ir) { - int indx = 0, nsd; + int indx = 0; numberOfGaussPoints = 1; - double du, dv, dw; - FloatArray newgpcoords; - IntArray knotSpan; #ifdef __PARALLEL_MODE int numberOfKnotSpans = 0; #endif - IRResultType result = Element :: initializeFrom(ir); // read nodes , material, cross section - if ( result != IRRT_OK ) { - return result; - } + Element :: initializeFrom(ir); // read nodes , material, cross section // set number of dofmanagers this->numberOfDofMans = dofManArray.giveSize(); this->giveInterpolation()->initializeFrom(ir); // read geometry // generate individual IntegrationElements; one for each nonzero knot span - nsd = this->giveNsd(); + int nsd = this->giveNsd(); if ( nsd == 1 ) { //HUHU } else if ( nsd == 2 ) { @@ -83,27 +77,27 @@ IRResultType IGAElement :: initializeFrom(InputRecord *ir) const FloatArray *knotValuesU = this->giveInterpolation()->giveKnotValues(1); const FloatArray *knotValuesV = this->giveInterpolation()->giveKnotValues(2); - newgpcoords.resize(2); - knotSpan.resize(2); + FloatArray newgpcoords(2); + IntArray knotSpan(2); int numberOfIntegrationRules = numberOfKnotSpansU * numberOfKnotSpansV; integrationRulesArray.resize( numberOfIntegrationRules ); knotSpan.at(2) = -1; for ( int vi = 1; vi <= numberOfKnotSpansV; vi++ ) { - dv = knotValuesV->at(vi + 1) - knotValuesV->at(vi); + double dv = knotValuesV->at(vi + 1) - knotValuesV->at(vi); knotSpan.at(2) += knotMultiplicityV->at(vi); knotSpan.at(1) = -1; for ( int ui = 1; ui <= numberOfKnotSpansU; ui++ ) { - du = knotValuesU->at(ui + 1) - knotValuesU->at(ui); + double du = knotValuesU->at(ui + 1) - knotValuesU->at(ui); knotSpan.at(1) += knotMultiplicityU->at(ui); - integrationRulesArray [ indx ].reset( new IGAIntegrationElement(indx, this, knotSpan) ); + integrationRulesArray [ indx ] = std::make_unique(indx, this, knotSpan); integrationRulesArray [ indx ]->SetUpPointsOnSquare(numberOfGaussPoints, _PlaneStress); // HUHU _PlaneStress, rectangle // remap local subelement gp coordinates into knot span coordinates and update integration weight - for ( GaussPoint *gp: *integrationRulesArray [ indx ] ) { + for ( auto &gp: *integrationRulesArray [ indx ] ) { const FloatArray &gpcoords = gp->giveNaturalCoordinates(); newgpcoords.at(1) = knotValuesU->at(ui) + du * ( gpcoords.at(1) / 2.0 + 0.5 ); @@ -129,32 +123,32 @@ IRResultType IGAElement :: initializeFrom(InputRecord *ir) const FloatArray *knotValuesV = this->giveInterpolation()->giveKnotValues(2); const FloatArray *knotValuesW = this->giveInterpolation()->giveKnotValues(3); - newgpcoords.resize(3); - knotSpan.resize(3); + FloatArray newgpcoords(3); + IntArray knotSpan(3); int numberOfIntegrationRules = numberOfKnotSpansU * numberOfKnotSpansV * numberOfKnotSpansW; integrationRulesArray.resize( numberOfIntegrationRules ); knotSpan.at(3) = -1; for ( int wi = 1; wi <= numberOfKnotSpansW; wi++ ) { - dw = knotValuesW->at(wi + 1) - knotValuesW->at(wi); + double dw = knotValuesW->at(wi + 1) - knotValuesW->at(wi); knotSpan.at(3) += knotMultiplicityW->at(wi); knotSpan.at(2) = -1; for ( int vi = 1; vi <= numberOfKnotSpansV; vi++ ) { - dv = knotValuesV->at(vi + 1) - knotValuesV->at(vi); + double dv = knotValuesV->at(vi + 1) - knotValuesV->at(vi); knotSpan.at(2) += knotMultiplicityV->at(vi); knotSpan.at(1) = -1; for ( int ui = 1; ui <= numberOfKnotSpansU; ui++ ) { - du = knotValuesU->at(ui + 1) - knotValuesU->at(ui); + double du = knotValuesU->at(ui + 1) - knotValuesU->at(ui); knotSpan.at(1) += knotMultiplicityU->at(ui); - integrationRulesArray [ indx ].reset( new IGAIntegrationElement(indx, this, knotSpan) ); + integrationRulesArray [ indx ] = std::make_unique(indx, this, knotSpan); integrationRulesArray [ indx ]->SetUpPointsOnCube(numberOfGaussPoints, _3dMat); // remap local subelement gp coordinates into knot span coordinates and update integration weight - for ( GaussPoint *gp: *integrationRulesArray [ indx ] ) { + for ( auto &gp: *integrationRulesArray [ indx ] ) { const FloatArray &gpcoords = gp->giveNaturalCoordinates(); newgpcoords.at(1) = knotValuesU->at(ui) + du * ( gpcoords.at(1) / 2.0 + 0.5 ); @@ -169,10 +163,9 @@ IRResultType IGAElement :: initializeFrom(InputRecord *ir) } } } else { - OOFEM_WARNING("unsupported number of spatial dimensions (nsd = %d)", nsd); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, "Domain", "unsupported number of spatial dimensions"); } - + #ifdef __PARALLEL_MODE // read optional knot span parallel mode this->knotSpanParallelMode.resize(numberOfKnotSpans); @@ -182,9 +175,6 @@ IRResultType IGAElement :: initializeFrom(InputRecord *ir) } IR_GIVE_OPTIONAL_FIELD(ir, knotSpanParallelMode, _IFT_IGAElement_KnotSpanParallelMode); #endif - - - return IRRT_OK; } @@ -209,31 +199,23 @@ IGAElement :: giveKnotSpanParallelMode(int knotSpanIndex) const // integration elements are setup in the same way as for IGAElement for now HUHU -IRResultType IGATSplineElement :: initializeFrom(InputRecord *ir) +void IGATSplineElement :: initializeFrom(InputRecord &ir) { TSplineInterpolation *interpol = static_cast< TSplineInterpolation * >( this->giveInterpolation() ); - int indx = 0, ui, vi, nsd, numberOfGaussPoints = 1; - double du, dv; - FloatArray newgpcoords; - IntArray knotSpan; + int indx = 0, numberOfGaussPoints = 1; + + Element :: initializeFrom(ir); // read nodes , material, cross section - IRResultType result = Element :: initializeFrom(ir); // read nodes , material, cross section - if ( result != IRRT_OK ) { - return result; - } // set number of dofmanagers this->numberOfDofMans = dofManArray.giveSize(); // set number of control points before initialization HUHU HAHA interpol->setNumberOfControlPoints(this->numberOfDofMans); - result = this->giveInterpolation()->initializeFrom(ir); // read geometry - if ( result != IRRT_OK ) { - return result; - } + this->giveInterpolation()->initializeFrom(ir); // read geometry // generate individual IntegrationElements; one for each nonzero knot span - nsd = giveNsd(); + int nsd = giveNsd(); if ( nsd == 2 ) { int numberOfKnotSpansU = this->giveInterpolation()->giveNumberOfKnotSpans(1); int numberOfKnotSpansV = this->giveInterpolation()->giveNumberOfKnotSpans(2); @@ -242,28 +224,28 @@ IRResultType IGATSplineElement :: initializeFrom(InputRecord *ir) const FloatArray *knotValuesU = this->giveInterpolation()->giveKnotValues(1); const FloatArray *knotValuesV = this->giveInterpolation()->giveKnotValues(2); - newgpcoords.resize(2); - knotSpan.resize(2); + FloatArray newgpcoords(2); + IntArray knotSpan(2); int numberOfIntegrationRules = numberOfKnotSpansU * numberOfKnotSpansV; integrationRulesArray.resize( numberOfIntegrationRules ); knotSpan.at(2) = -1; - for ( vi = 1; vi <= numberOfKnotSpansV; vi++ ) { - dv = knotValuesV->at(vi + 1) - knotValuesV->at(vi); + for ( int vi = 1; vi <= numberOfKnotSpansV; vi++ ) { + double dv = knotValuesV->at(vi + 1) - knotValuesV->at(vi); knotSpan.at(2) += knotMultiplicityV->at(vi); knotSpan.at(1) = -1; - for ( ui = 1; ui <= numberOfKnotSpansU; ui++ ) { - du = knotValuesU->at(ui + 1) - knotValuesU->at(ui); + for ( int ui = 1; ui <= numberOfKnotSpansU; ui++ ) { + double du = knotValuesU->at(ui + 1) - knotValuesU->at(ui); knotSpan.at(1) += knotMultiplicityU->at(ui); - integrationRulesArray [ indx ].reset( new IGAIntegrationElement(indx, this, knotSpan) ); + integrationRulesArray [ indx ] = std::make_unique(indx, this, knotSpan); integrationRulesArray [ indx ]->SetUpPointsOnSquare(numberOfGaussPoints, _PlaneStress); // HUHU _PlaneStress, rectangle // remap local subelement gp coordinates into knot span coordinates and update integration weight - for ( GaussPoint *gp: *integrationRulesArray [ indx ] ) { - const FloatArray &gpcoords = gp->giveNaturalCoordinates(); + for ( auto &gp: *integrationRulesArray [ indx ] ) { + const auto &gpcoords = gp->giveNaturalCoordinates(); newgpcoords.at(1) = knotValuesU->at(ui) + du * ( gpcoords.at(1) / 2.0 + 0.5 ); newgpcoords.at(2) = knotValuesV->at(vi) + dv * ( gpcoords.at(2) / 2.0 + 0.5 ); @@ -275,11 +257,8 @@ IRResultType IGATSplineElement :: initializeFrom(InputRecord *ir) } } } else { - OOFEM_WARNING("unsupported number of spatial dimensions (nsd = %d)", nsd); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, "Domain", "unsupported number of spatial dimensions"); } - - return IRRT_OK; } @@ -298,9 +277,8 @@ IRResultType IGATSplineElement :: initializeFrom(InputRecord *ir) void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { WCRec p [ 8 ]; - GraphicObj *go; FEInterpolation *interp = this->giveInterpolation(); - int i, j, k, m, nseg; + int nseg; #ifdef DRAW_MESH WCRec pp [ 2 ]; @@ -325,36 +303,34 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) nseq = 4; #endif - const double *const *knotVector = interp->giveKnotVector(); - const IntArray *span; + const FloatArray *knotVector = interp->giveKnotVector(); int nsd = this->giveNsd(); if ( nsd == 1 ) { FloatArray c [ 2 ], cg [ 2 ]; - double du; - for ( j = 0; j < 2; j++ ) { + for ( int j = 0; j < 2; j++ ) { c [ j ].resize(1); cg [ j ].resize(1); } // loop over individual integration rules (i.e., knot spans) for ( auto &iRule: integrationRulesArray ) { - span = iRule->giveKnotSpan(); + const IntArray *span = iRule->giveKnotSpan(); // divide span locally to get finer geometry rep. - du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; - for ( i = 1; i <= nseg; i++ ) { + double du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; + for ( int i = 1; i <= nseg; i++ ) { c [ 0 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * ( i - 1 ); c [ 1 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * i; - for ( k = 0; k < 2; k++ ) { + for ( int k = 0; k < 2; k++ ) { interp->local2global( cg [ k ], c [ k ], FEIIGAElementGeometryWrapper( this, iRule->giveKnotSpan() ) ); p [ k ].x = ( FPNum ) cg [ k ].at(1); p [ k ].y = 0.; p [ k ].z = 0.; } - go = CreateLine3D(p); + auto go = CreateLine3D(p); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -362,21 +338,20 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } // end loop over knot spans (irules) } else if ( nsd == 2 ) { FloatArray c [ 4 ], cg [ 4 ]; - double du, dv; - for ( j = 0; j < 4; j++ ) { + for ( int j = 0; j < 4; j++ ) { c [ j ].resize(2); cg [ j ].resize(2); } // loop over individual integration rules (i.e., knot spans) for ( auto &iRule: integrationRulesArray ) { - span = iRule->giveKnotSpan(); + const IntArray *span = iRule->giveKnotSpan(); // divide span locally to get finer geometry rep. - du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; - dv = ( knotVector [ 1 ] [ span->at(2) + 1 ] - knotVector [ 1 ] [ span->at(2) ] ) / nseg; - for ( i = 1; i <= nseg; i++ ) { - for ( j = 1; j <= nseg; j++ ) { + double du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; + double dv = ( knotVector [ 1 ] [ span->at(2) + 1 ] - knotVector [ 1 ] [ span->at(2) ] ) / nseg; + for ( int i = 1; i <= nseg; i++ ) { + for ( int j = 1; j <= nseg; j++ ) { c [ 0 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * ( i - 1 ); c [ 0 ].at(2) = knotVector [ 1 ] [ span->at(2) ] + dv * ( j - 1 ); c [ 1 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * i; @@ -386,7 +361,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) c [ 3 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * ( i - 1 ); c [ 3 ].at(2) = knotVector [ 1 ] [ span->at(2) ] + dv * j; - for ( k = 0; k < 4; k++ ) { + for ( int k = 0; k < 4; k++ ) { interp->local2global( cg [ k ], c [ k ], FEIIGAElementGeometryWrapper( this, iRule->giveKnotSpan() ) ); p [ k ].x = ( FPNum ) cg [ k ].at(1); p [ k ].y = ( FPNum ) cg [ k ].at(2); @@ -403,7 +378,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) pp [ 1 ].y = p [ 3 ].y; pp [ 1 ].z = p [ 3 ].z; - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -418,7 +393,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) pp [ 1 ].y = p [ 1 ].y; pp [ 1 ].z = p [ 1 ].z; - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -433,7 +408,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) pp [ 1 ].y = p [ 2 ].y; pp [ 1 ].z = p [ 2 ].z; - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -448,14 +423,14 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) pp [ 1 ].y = p [ 3 ].y; pp [ 1 ].z = p [ 3 ].z; - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); } #else - go = CreateQuad3D(p); + auto go = CreateQuad3D(p); EGWithMaskChangeAttributes(WIDTH_MASK | FILL_MASK | COLOR_MASK | EDGE_COLOR_MASK | EDGE_FLAG_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -465,23 +440,22 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } // end loop over knot spans (irules) } else if ( nsd == 3 ) { FloatArray c [ 8 ], cg [ 8 ]; - double du, dv, dt; - for ( j = 0; j < 8; j++ ) { + for ( int j = 0; j < 8; j++ ) { c [ j ].resize(3); cg [ j ].resize(3); } // loop over individual integration rules (i.e., knot spans) for ( auto &iRule: integrationRulesArray ) { - span = iRule->giveKnotSpan(); + const IntArray *span = iRule->giveKnotSpan(); // divide span locally to get finer geometry rep. - du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; - dv = ( knotVector [ 1 ] [ span->at(2) + 1 ] - knotVector [ 1 ] [ span->at(2) ] ) / nseg; - dt = ( knotVector [ 2 ] [ span->at(3) + 1 ] - knotVector [ 2 ] [ span->at(3) ] ) / nseg; - for ( i = 1; i <= nseg; i++ ) { - for ( j = 1; j <= nseg; j++ ) { - for ( k = 1; k <= nseg; k++ ) { + double du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; + double dv = ( knotVector [ 1 ] [ span->at(2) + 1 ] - knotVector [ 1 ] [ span->at(2) ] ) / nseg; + double dt = ( knotVector [ 2 ] [ span->at(3) + 1 ] - knotVector [ 2 ] [ span->at(3) ] ) / nseg; + for ( int i = 1; i <= nseg; i++ ) { + for ( int j = 1; j <= nseg; j++ ) { + for ( int k = 1; k <= nseg; k++ ) { c [ 0 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * ( i - 1 ); c [ 0 ].at(2) = knotVector [ 1 ] [ span->at(2) ] + dv * ( j - 1 ); c [ 0 ].at(3) = knotVector [ 2 ] [ span->at(3) ] + dt * ( k - 1 ); @@ -507,7 +481,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) c [ 7 ].at(2) = knotVector [ 1 ] [ span->at(2) ] + dv * j; c [ 7 ].at(3) = knotVector [ 2 ] [ span->at(3) ] + dt * k; - for ( m = 0; m < 8; m++ ) { + for ( int m = 0; m < 8; m++ ) { interp->local2global( cg [ m ], c [ m ], FEIIGAElementGeometryWrapper( this, iRule->giveKnotSpan() ) ); p [ m ].x = ( FPNum ) cg [ m ].at(1); p [ m ].y = ( FPNum ) cg [ m ].at(2); @@ -540,7 +514,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { if ( zz < 2.0001 || rr < 1.001 * 1.001 || yy < 0.0001 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -548,7 +522,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -580,7 +554,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { if ( zz < 2.0001 || rr < 1.001 * 1.001 || yy < 0.0001 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -588,7 +562,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -620,7 +594,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { if ( zz < 2.0001 || rr < 1.001 * 1.001 || yy < 0.0001 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -628,7 +602,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -660,7 +634,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { if ( zz < 2.0001 || rr < 1.001 * 1.001 || yy < 0.0001 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -668,7 +642,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -699,14 +673,14 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) r = rr + zz * zz; if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -738,7 +712,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { if ( yy < 1.5 || zz < 2.0001 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -746,7 +720,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -777,14 +751,14 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) r = rr + zz * zz; if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -816,7 +790,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { if ( yy < 1.5 || zz < 2.0001 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -824,7 +798,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -855,14 +829,14 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) r = rr + zz * zz; if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -893,14 +867,14 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) r = rr + zz * zz; if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -932,7 +906,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { if ( yy < 0.0001 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -940,7 +914,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -972,7 +946,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) if ( zz < 2.0001 /* || xx < 0.0001 */ || yy < 0.0001 || rr < 1.001 * 1.001 || r < 25.0 || r > 5.98 * 5.98 ) { if ( yy < 2.0001 ) { - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -980,7 +954,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } #endif #else - go = CreateLine3D(pp); + auto go = CreateLine3D(pp); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -988,7 +962,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } #else - go = CreateHexahedron(p); + auto go = CreateHexahedron(p); EGWithMaskChangeAttributes(WIDTH_MASK | FILL_MASK | COLOR_MASK | EDGE_COLOR_MASK | EDGE_FLAG_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) this); EMAddGraphicsToModel(ESIModel(), go); @@ -1006,8 +980,7 @@ void IGAElement :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, oofegGraphicContext &gc, TimeStep *tStep, UnknownType) { WCRec p [ 8 ]; - GraphicObj *go; - int i, j, k, m, n, nseg; + int nseg; FloatArray u; FloatMatrix N; FloatArray ur, d; @@ -1035,17 +1008,16 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, nseg = 4; #endif - const double *const *knotVector = interp->giveKnotVector(); - const IntArray *span; + const FloatArray *knotVector = interp->giveKnotVector(); int nsd = interp->giveNsd(); se->computeVectorOf(VM_Total, tStep, u); if ( nsd == 1 ) { FloatArray c [ 2 ], cg [ 2 ]; - double du; - for ( j = 0; j < 2; j++ ) { + + for ( int j = 0; j < 2; j++ ) { c [ j ].resize(1); cg [ j ].resize(1); } @@ -1053,14 +1025,14 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, // loop over individual integration rules (i.e., knot spans) for ( int ir = 0; ir < elem->giveNumberOfIntegrationRules(); ir++ ) { IntegrationRule *iRule = elem->giveIntegrationRule(ir); - span = iRule->giveKnotSpan(); + const IntArray *span = iRule->giveKnotSpan(); // divide span locally to get finer geometry rep. - du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; - for ( i = 1; i <= nseg; i++ ) { + double du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; + for ( int i = 1; i <= nseg; i++ ) { c [ 0 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * ( i - 1 ); c [ 1 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * i; - for ( k = 0; k < 2; k++ ) { + for ( int k = 0; k < 2; k++ ) { // create a dummy ip's GaussPoint gp(iRule, 999, c [ k ], 1.0, _PlaneStress); @@ -1070,7 +1042,7 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, // get local code numbers corresponding to ir se->giveIntegrationElementLocalCodeNumbers(lc, elem, gp.giveIntegrationRule()); ur.resize( N.giveNumberOfColumns() ); - for ( n = 1; n <= lc.giveSize(); n++ ) { + for ( int n = 1; n <= lc.giveSize(); n++ ) { ur.at(n) = u.at( lc.at(n) ); } @@ -1083,7 +1055,7 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, p [ k ].z = 0.; } - go = CreateLine3D(p); + auto go = CreateLine3D(p); EGWithMaskChangeAttributes(WIDTH_MASK | STYLE_MASK | COLOR_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) elem); EMAddGraphicsToModel(ESIModel(), go); @@ -1091,9 +1063,8 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, } // end loop over knot spans (irules) } else if ( nsd == 2 ) { FloatArray c [ 4 ], cg [ 4 ]; - double du, dv; - for ( j = 0; j < 4; j++ ) { + for ( int j = 0; j < 4; j++ ) { c [ j ].resize(2); cg [ j ].resize(2); } @@ -1101,12 +1072,12 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, // loop over individual integration rules (i.e., knot spans) for ( int ir = 0; ir < elem->giveNumberOfIntegrationRules(); ir++ ) { IntegrationRule *iRule = elem->giveIntegrationRule(ir); - span = iRule->giveKnotSpan(); + const IntArray *span = iRule->giveKnotSpan(); // divide span locally to get finer geometry rep. - du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; - dv = ( knotVector [ 1 ] [ span->at(2) + 1 ] - knotVector [ 1 ] [ span->at(2) ] ) / nseg; - for ( i = 1; i <= nseg; i++ ) { - for ( j = 1; j <= nseg; j++ ) { + double du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; + double dv = ( knotVector [ 1 ] [ span->at(2) + 1 ] - knotVector [ 1 ] [ span->at(2) ] ) / nseg; + for ( int i = 1; i <= nseg; i++ ) { + for ( int j = 1; j <= nseg; j++ ) { c [ 0 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * ( i - 1 ); c [ 0 ].at(2) = knotVector [ 1 ] [ span->at(2) ] + dv * ( j - 1 ); c [ 1 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * i; @@ -1116,7 +1087,7 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, c [ 3 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * ( i - 1 ); c [ 3 ].at(2) = knotVector [ 1 ] [ span->at(2) ] + dv * j; - for ( k = 0; k < 4; k++ ) { + for ( int k = 0; k < 4; k++ ) { // create a dummy ip's GaussPoint gp(iRule, 999, c [ k ], 1.0, _PlaneStress); @@ -1126,7 +1097,7 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, // get local code numbers corresponding to ir se->giveIntegrationElementLocalCodeNumbers(lc, elem, gp.giveIntegrationRule()); ur.resize( N.giveNumberOfColumns() ); - for ( n = 1; n <= lc.giveSize(); n++ ) { + for ( int n = 1; n <= lc.giveSize(); n++ ) { ur.at(n) = u.at( lc.at(n) ); } @@ -1139,7 +1110,7 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, p [ k ].z = 0.; } - go = CreateQuad3D(p); + auto go = CreateQuad3D(p); EGWithMaskChangeAttributes(WIDTH_MASK | FILL_MASK | COLOR_MASK | EDGE_COLOR_MASK | EDGE_FLAG_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) elem); EMAddGraphicsToModel(ESIModel(), go); @@ -1148,9 +1119,8 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, } // end loop over knot spans (irules) } else if ( nsd == 3 ) { FloatArray c [ 8 ], cg [ 8 ]; - double du, dv, dt; - for ( j = 0; j < 8; j++ ) { + for ( int j = 0; j < 8; j++ ) { c [ j ].resize(3); cg [ j ].resize(3); } @@ -1158,14 +1128,14 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, // loop over individual integration rules (i.e., knot spans) for ( int ir = 0; ir < elem->giveNumberOfIntegrationRules(); ir++ ) { IntegrationRule *iRule = elem->giveIntegrationRule(ir); - span = iRule->giveKnotSpan(); + const IntArray *span = iRule->giveKnotSpan(); // divide span locally to get finer geometry rep. - du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; - dv = ( knotVector [ 1 ] [ span->at(2) + 1 ] - knotVector [ 1 ] [ span->at(2) ] ) / nseg; - dt = ( knotVector [ 2 ] [ span->at(3) + 1 ] - knotVector [ 2 ] [ span->at(3) ] ) / nseg; - for ( i = 1; i <= nseg; i++ ) { - for ( j = 1; j <= nseg; j++ ) { - for ( k = 1; k <= nseg; k++ ) { + double du = ( knotVector [ 0 ] [ span->at(1) + 1 ] - knotVector [ 0 ] [ span->at(1) ] ) / nseg; + double dv = ( knotVector [ 1 ] [ span->at(2) + 1 ] - knotVector [ 1 ] [ span->at(2) ] ) / nseg; + double dt = ( knotVector [ 2 ] [ span->at(3) + 1 ] - knotVector [ 2 ] [ span->at(3) ] ) / nseg; + for ( int i = 1; i <= nseg; i++ ) { + for ( int j = 1; j <= nseg; j++ ) { + for ( int k = 1; k <= nseg; k++ ) { c [ 0 ].at(1) = knotVector [ 0 ] [ span->at(1) ] + du * ( i - 1 ); c [ 0 ].at(2) = knotVector [ 1 ] [ span->at(2) ] + dv * ( j - 1 ); c [ 0 ].at(3) = knotVector [ 2 ] [ span->at(3) ] + dt * ( k - 1 ); @@ -1191,7 +1161,7 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, c [ 7 ].at(2) = knotVector [ 1 ] [ span->at(2) ] + dv * j; c [ 7 ].at(3) = knotVector [ 2 ] [ span->at(3) ] + dt * k; - for ( m = 0; m < 8; m++ ) { + for ( int m = 0; m < 8; m++ ) { // create a dummy ip's GaussPoint gp(iRule, 999, c [ m ], 1.0, _3dMat); @@ -1201,7 +1171,7 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, // get local code numbers corresponding to ir se->giveIntegrationElementLocalCodeNumbers(lc, elem, gp.giveIntegrationRule()); ur.resize( N.giveNumberOfColumns() ); - for ( n = 1; n <= lc.giveSize(); n++ ) { + for ( int n = 1; n <= lc.giveSize(); n++ ) { ur.at(n) = u.at( lc.at(n) ); } @@ -1214,7 +1184,7 @@ void drawIGAPatchDeformedGeometry(Element *elem, StructuralElementEvaluator *se, p [ m ].z = ( FPNum ) ( cg [ m ].at(3) + d.at(3) * defScale ); } - go = CreateHexahedron(p); + auto go = CreateHexahedron(p); EGWithMaskChangeAttributes(WIDTH_MASK | FILL_MASK | COLOR_MASK | EDGE_COLOR_MASK | EDGE_FLAG_MASK | LAYER_MASK, go); EGAttachObject(go, ( EObjectP ) elem); EMAddGraphicsToModel(ESIModel(), go); diff --git a/src/oofemlib/iga/iga.h b/src/oofemlib/iga/iga.h index 8e310d955..97420d1e4 100644 --- a/src/oofemlib/iga/iga.h +++ b/src/oofemlib/iga/iga.h @@ -60,17 +60,10 @@ class OOFEM_EXPORT FEIIGAElementGeometryWrapper : public FEICellGeometry const IntArray *knotSpan; Element *elem; public: - FEIIGAElementGeometryWrapper(Element * _elem, const IntArray * _knotSpan) : FEICellGeometry() { - this->elem = _elem; - this->knotSpan = _knotSpan; - } - FEIIGAElementGeometryWrapper(Element * _elem) : FEICellGeometry() { - this->elem = _elem; - this->knotSpan = NULL; - } + FEIIGAElementGeometryWrapper(Element *elem, const IntArray *knotSpan=nullptr) : FEICellGeometry(), knotSpan(knotSpan), elem(elem) { } - int giveNumberOfVertices() const { return elem->giveNumberOfNodes(); } - const FloatArray *giveVertexCoordinates(int i) const { return elem->giveNode(i)->giveCoordinates(); } + int giveNumberOfVertices() const override { return elem->giveNumberOfNodes(); } + const FloatArray &giveVertexCoordinates(int i) const override { return elem->giveNode(i)->giveCoordinates(); } }; @@ -82,11 +75,11 @@ class OOFEM_EXPORT IGAIntegrationElement : public GaussIntegrationRule protected: IntArray knotSpan; // knot_span(nsd) public: - IGAIntegrationElement(int _n, Element * _e, IntArray & _knotSpan) : - GaussIntegrationRule(_n, _e, 0, 0, false), - knotSpan(_knotSpan) { } - const IntArray *giveKnotSpan() { return & this->knotSpan; } - void setKnotSpan1(IntArray &src) { this->knotSpan = src; } + IGAIntegrationElement(int _n, Element *e, IntArray knotSpan) : + GaussIntegrationRule(_n, e, 0, 0, false), + knotSpan(std::move(knotSpan)) { } + const IntArray *giveKnotSpan() override { return & this->knotSpan; } + void setKnotSpan1(const IntArray &src) { this->knotSpan = src; } }; @@ -96,20 +89,19 @@ class OOFEM_EXPORT IGAIntegrationElement : public GaussIntegrationRule class OOFEM_EXPORT IGAElement : public Element { protected: - // FEInterpolation interpolation; #ifdef __PARALLEL_MODE IntArray knotSpanParallelMode; #endif public: IGAElement(int n, Domain * aDomain) : Element(n, aDomain) { } - IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; #ifdef __PARALLEL_MODE - elementParallelMode giveKnotSpanParallelMode(int) const; + elementParallelMode giveKnotSpanParallelMode(int) const override; #endif #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; #endif protected: @@ -124,10 +116,7 @@ class OOFEM_EXPORT IGATSplineElement : public IGAElement { public: IGATSplineElement(int n, Domain * aDomain) : IGAElement(n, aDomain) { } - IRResultType initializeFrom(InputRecord *ir); - -protected: - virtual int giveNsd() = 0; + void initializeFrom(InputRecord &ir) override; }; } // end namespace oofem #endif //iga_h diff --git a/src/oofemlib/iml/diagpre.C b/src/oofemlib/iml/diagpre.C index f9c4f31f9..99e74555f 100644 --- a/src/oofemlib/iml/diagpre.C +++ b/src/oofemlib/iml/diagpre.C @@ -33,7 +33,7 @@ namespace oofem { DiagPreconditioner :: DiagPreconditioner(const SparseMtrx &C, InputRecord &attributes) : Preconditioner(C, attributes), - diag_( C.giveNumberOfRows() ) + diag( C.giveNumberOfRows() ) { } @@ -42,17 +42,17 @@ DiagPreconditioner :: init(const SparseMtrx &C) { int n = C.giveNumberOfRows(); - diag_.resize( n ); - diag_.zero(); + diag.resize( n ); + diag.zero(); /* Find the diagonal elements */ for ( int i = 1; i <= n; i++ ) { - double diag = C.at(i, i); - if ( diag == 0 ) { + double d = C.at(i, i); + if ( d == 0 ) { OOFEM_ERROR("failed, zero diagonal detected in equation %d", i); } - diag_(i - 1) = 1. / diag; + diag.at(i) = 1. / d; } } @@ -62,7 +62,7 @@ DiagPreconditioner :: solve(const FloatArray &x, FloatArray &y) const { y.resize( x.giveSize() ); for ( int i = 0; i < x.giveSize(); i++ ) { - y(i) = x(i) * diag(i); + y[i] = x[i] * diag[i]; } } @@ -73,7 +73,7 @@ DiagPreconditioner :: trans_solve(const FloatArray &x, FloatArray &y) const y.resize( x.giveSize() ); for ( int i = 0; i < x.giveSize(); i++ ) { - y(i) = x(i) * diag(i); + y[i] = x[i] * diag[i]; } } } // end namespace oofem diff --git a/src/oofemlib/iml/diagpre.h b/src/oofemlib/iml/diagpre.h index d9de18b48..fa73fabe9 100644 --- a/src/oofemlib/iml/diagpre.h +++ b/src/oofemlib/iml/diagpre.h @@ -42,7 +42,7 @@ namespace oofem { class OOFEM_EXPORT DiagPreconditioner : public Preconditioner { private: - FloatArray diag_; + FloatArray diag; public: /// Constructor. Initializes the the receiver (constructs the precontioning matrix M) of given matrix. @@ -52,15 +52,12 @@ class OOFEM_EXPORT DiagPreconditioner : public Preconditioner /// Destructor virtual ~DiagPreconditioner(void) { } - virtual void init(const SparseMtrx &a); + void init(const SparseMtrx &a) override; - void solve(const FloatArray &rhs, FloatArray &solution) const; - void trans_solve(const FloatArray &rhs, FloatArray &solution) const; + void solve(const FloatArray &rhs, FloatArray &solution) const override; + void trans_solve(const FloatArray &rhs, FloatArray &solution) const override; - virtual const char *giveClassName() const { return "DiagPre"; } - - const double &diag(int i) const { return diag_(i); } - double &diag(int i) { return diag_(i); } + const char *giveClassName() const override { return "DiagPre"; } }; } // end namespace oofem #endif // diagpre_h diff --git a/src/oofemlib/iml/dyncompcol.C b/src/oofemlib/iml/dyncompcol.C index 5c4ac0a45..c4ecc31b2 100644 --- a/src/oofemlib/iml/dyncompcol.C +++ b/src/oofemlib/iml/dyncompcol.C @@ -47,169 +47,26 @@ namespace oofem { REGISTER_SparseMtrx(DynCompCol, SMT_DynCompCol); -DynCompCol :: DynCompCol(void) : SparseMtrx(), base_(0) -{ -#ifndef DynCompCol_USE_STL_SETS - columns_ = NULL; - rowind_ = NULL; -#else - columns = NULL; -#endif -} +DynCompCol :: DynCompCol(int n) : SparseMtrx(n, n), + base(0) +{} -DynCompCol :: DynCompCol(int n) : SparseMtrx(n, n), base_(0) -{ -#ifndef DynCompCol_USE_STL_SETS - columns_ = NULL; - rowind_ = NULL; -#else - columns = NULL; -#endif - nRows = nColumns = n; -} - - -/*****************************/ -/* Copy constructor */ -/*****************************/ - -DynCompCol :: DynCompCol(const DynCompCol &S) : SparseMtrx(S.nRows, S.nColumns), base_(S.base_) +DynCompCol :: DynCompCol(const DynCompCol &S) : SparseMtrx(S.nRows, S.nColumns), + columns(S.columns), + rowind(S.rowind), + base(S.base) { -#ifndef DynCompCol_USE_STL_SETS - int i; - if ( S.columns_ ) { - this->columns_ = new FloatArray * [ S.nColumns ]; - for ( i = 0; i < S.nColumns; i++ ) { - this->columns_ [ i ] = new FloatArray(*S.columns_ [ i ]); - } - } else { - this->columns_ = NULL; - } - - if ( S.rowind_ ) { - this->rowind_ = new IntArray * [ S.nColumns ]; - for ( i = 0; i < S.nColumns; i++ ) { - this->rowind_ [ i ] = new IntArray(*S.rowind_ [ i ]); - } - } else { - this->rowind_ = NULL; - } - -#else - int i; - if ( S.columns ) { - this->columns = new std :: map< int, double > * [ S.nColumns ]; - for ( i = 0; i < S.nColumns; i++ ) { - this->columns [ i ] = new std :: map< int, double >(*S.columns [ i ]); - } - } else { - this->columns = NULL; - } - -#endif - - this->nRows = S.nRows; - this->nColumns = S.nColumns; this->version = S.version; } -// Destructor -DynCompCol :: ~DynCompCol() -{ -#ifndef DynCompCol_USE_STL_SETS - int i; - - if ( this->columns_ ) { - for ( i = 0; i < nColumns; i++ ) { - delete this->columns_ [ i ]; - } - - delete this->columns_; - } - - if ( this->rowind_ ) { - for ( i = 0; i < nColumns; i++ ) { - delete this->rowind_ [ i ]; - } - - delete this->rowind_; - } - -#else - int i; - - if ( this->columns ) { - for ( i = 0; i < nColumns; i++ ) { - delete this->columns [ i ]; - } - - delete this->columns; - } - -#endif -} - - - -/***************************/ -/* Assignment operator... */ -/***************************/ - DynCompCol &DynCompCol :: operator = ( const DynCompCol & C ) { - base_ = C.base_; - -#ifndef DynCompCol_USE_STL_SETS - int i; - - if ( this->columns_ ) { - for ( i = 0; i < nColumns; i++ ) { - delete this->columns_ [ i ]; - } - - delete this->columns_; - } - - if ( C.columns_ ) { - this->columns_ = new FloatArray * [ C.nColumns ]; - for ( i = 0; i < C.nColumns; i++ ) { - this->columns_ [ i ] = new FloatArray(*C.columns_ [ i ]); - } - } else { - this->columns_ = NULL; - } - - - if ( this->rowind_ ) { - for ( i = 0; i < nColumns; i++ ) { - delete this->rowind_ [ i ]; - } - - delete this->rowind_; - } - - if ( C.rowind_ ) { - this->rowind_ = new IntArray * [ C.nColumns ]; - for ( i = 0; i < C.nColumns; i++ ) { - this->rowind_ [ i ] = new IntArray(*C.rowind_ [ i ]); - } - } else { - this->rowind_ = NULL; - } - -#else - int i; - - if ( this->columns ) { - for ( i = 0; i < nColumns; i++ ) { - this->columns [ i ] = C.columns [ i ]; - } - } - -#endif + columns = C.columns; + rowind = C.rowind; + base = C.base; nRows = C.nRows; nColumns = C.nColumns; @@ -218,15 +75,13 @@ DynCompCol &DynCompCol :: operator = ( const DynCompCol & C ) return * this; } -SparseMtrx *DynCompCol :: GiveCopy() const +std::unique_ptr DynCompCol :: clone() const { - DynCompCol *result = new DynCompCol(*this); - return result; + return std::make_unique(*this); } void DynCompCol :: times(const FloatArray &x, FloatArray &answer) const { - // Check for compatible dimensions: if ( x.giveSize() != nColumns ) { OOFEM_ERROR("incompatible dimensions"); } @@ -234,47 +89,20 @@ void DynCompCol :: times(const FloatArray &x, FloatArray &answer) const answer.resize(nRows); answer.zero(); -#ifndef DynCompCol_USE_STL_SETS - int j, t; - double rhs; - - for ( j = 0; j < nColumns; j++ ) { - rhs = x(j); - for ( t = 1; t <= columns_ [ j ]->giveSize(); t++ ) { - answer( rowind_ [ j ]->at(t) ) += columns_ [ j ]->at(t) * rhs; - } - } - -#else - double rhs; - for ( int j = 0; j < nColumns; j++ ) { - rhs = x(j); - for ( auto &val: columns [ j ] ) { - answer(val.first) += val.second * rhs; + double rhs = x[j]; + for ( int t = 1; t <= columns[ j ].giveSize(); t++ ) { + answer[ rowind[ j ].at(t) ] += columns[ j ].at(t) * rhs; } } - -#endif } void DynCompCol :: times(double x) { -#ifndef DynCompCol_USE_STL_SETS - for ( int j = 0; j < nColumns; j++ ) { - columns_ [ j ]->times(x); - } - -#else - for ( int j = 0; j < nColumns; j++ ) { - for ( auto &val: columns [ j ] ) { - val.second *= x; - } + for ( auto &column : columns ) { + column.times(x); } -#endif - - // increment version this->version++; } @@ -282,38 +110,14 @@ int DynCompCol :: buildInternalStructure(EngngModel *eModel, int di, const Unkno { int neq = eModel->giveNumberOfDomainEquations(di, s); -#ifndef DynCompCol_USE_STL_SETS IntArray loc; Domain *domain = eModel->giveDomain(di); nColumns = nRows = neq; - if ( rowind_ ) { - for ( int i = 0; i < nColumns; i++ ) { - delete this->rowind_ [ i ]; - } - - delete this->rowind_; - } - - rowind_ = ( IntArray ** ) new IntArray * [ neq ]; - for ( int j = 0; j < neq; j++ ) { - rowind_ [ j ] = new IntArray(); - } - - // allocate value array - if ( columns_ ) { - for ( int i = 0; i < nColumns; i++ ) { - delete this->columns_ [ i ]; - } - - delete this->columns_; - } - - columns_ = ( FloatArray ** ) new FloatArray * [ neq ]; - for ( int j = 0; j < neq; j++ ) { - columns_ [ j ] = new FloatArray(); - } + rowind.clear(); + columns.clear(); + this->growTo(neq); for ( auto &elem : domain->giveElements() ) { elem->giveLocationArray(loc, s); @@ -335,7 +139,7 @@ int DynCompCol :: buildInternalStructure(EngngModel *eModel, int di, const Unkno for ( auto &gbc : domain->giveBcs() ) { ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() ); - if ( bc != NULL ) { + if ( bc ) { bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s); for ( std :: size_t k = 0; k < r_locs.size(); k++ ) { IntArray &krloc = r_locs [ k ]; @@ -355,21 +159,11 @@ int DynCompCol :: buildInternalStructure(EngngModel *eModel, int di, const Unkno int nz_ = 0; for ( int j = 0; j < neq; j++ ) { - nz_ += this->rowind_ [ j ]->giveSize(); + nz_ += this->rowind[ j ].giveSize(); } OOFEM_LOG_DEBUG("DynCompCol info: neq is %d, nelem is %d\n", neq, nz_); -#else - nColumns = nRows = neq; - columns.resize( neq ); - for ( auto &col: columns ) { - col.clear(); - } - -#endif - - // increment version this->version++; return true; @@ -378,23 +172,19 @@ int DynCompCol :: buildInternalStructure(EngngModel *eModel, int di, const Unkno int DynCompCol :: assemble(const IntArray &loc, const FloatMatrix &mat) { - int i, j, ii, jj, dim; + int dim = mat.giveNumberOfRows(); # ifdef DEBUG - dim = mat.giveNumberOfRows(); if ( dim != loc.giveSize() ) { OOFEM_ERROR("dimension of 'k' and 'loc' mismatch"); } - # endif - dim = mat.giveNumberOfRows(); - - for ( j = 1; j <= dim; j++ ) { - jj = loc.at(j); + for ( int j = 1; j <= dim; j++ ) { + int jj = loc.at(j); if ( jj ) { - for ( i = 1; i <= dim; i++ ) { - ii = loc.at(i); + for ( int i = 1; i <= dim; i++ ) { + int ii = loc.at(i); if ( ii ) { this->at(ii, jj) += mat.at(i, j); } @@ -402,7 +192,6 @@ int DynCompCol :: assemble(const IntArray &loc, const FloatMatrix &mat) } } - // increment version this->version++; return 1; @@ -410,365 +199,210 @@ int DynCompCol :: assemble(const IntArray &loc, const FloatMatrix &mat) int DynCompCol :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) { -#ifndef DynCompCol_USE_STL_SETS - /* - * /// slow and safe - * int i,j,ii,jj,dim1,dim2 ; - * - * this->checkSizeTowards(rloc, cloc); - * - * dim1 = mat.giveNumberOfRows() ; - * dim2 = mat.giveNumberOfColumns() ; - * for (i=1 ; i<= dim1; i++) { - * ii = rloc.at(i); - * if (ii) for (j=1 ; j<= dim2; j++) { - * jj = cloc.at(j); - * if (jj) this->at(ii,jj) += mat.at(i,j); - * } - * } - * return 1; - */ - - /// optimized low-end implementation - IntArray rowsToAdd( rloc.giveSize() ); - int i, ii, ii1, j, jj, jj1, rowindx; - int rsize = rloc.giveSize(); - int csize = cloc.giveSize(); - - /* - * // adjust the size of receiver - * int maxid=0; - * for (i=0; igrowTo (maxid); - */ - - for ( i = 0; i < csize; i++ ) { - if ( ( ii = cloc(i) ) ) { - ii1 = ii - 1; - for ( j = 0; j < rsize; j++ ) { - if ( ( jj = rloc(j) ) ) { - jj1 = jj - 1; - - /* - * rowindx = 0; - * for (int t=columns_[ii1]->giveSize(); t > 0; t--) - * if (rowind_[ii1]->at(t) == (jj1)) {rowindx = t; break;} - */ - - // rowindx = this->giveRowIndx (ii1, jj1); - // if (rowindx == 0) { - /* - * int oldsize = rowind_[ii1]->giveSize(); - * rowind_[ii1]->resizeWithValues(oldsize+1, DynCompCol_CHUNK); - * columns_[ii1]->resizeWithValues(oldsize+1, DynCompCol_CHUNK); - * rowindx = oldsize+1; - * rowind_[ii1]->at(oldsize+1) = jj1; - */ - // rowindx = this->insertRowInColumn (ii1, jj1); - // } - - rowindx = this->insertRowInColumn(ii1, jj1); - //if (rowind_[j-1]->at(t) == (i-1)) return columns_[j-1]->at(t); - columns_ [ ii1 ]->at(rowindx) += mat(j, i); - } +#if 0 + // slow and safe + this->checkSizeTowards(rloc, cloc); + int dim1 = mat.giveNumberOfRows(); + int dim2 = mat.giveNumberOfColumns(); + for (int i = 1 ; i <= dim1; i++) { + int ii = rloc.at(i); + if (ii) + for (j=1 ; j<= dim2; j++) { + int jj = cloc.at(j); + if (jj) this->at(ii,jj) += mat.at(i,j); } - } - } + } + return 1; +#endif -#else - int i, ii, ii1, j, jj, jj1; + // optimized low-end implementation + IntArray rowsToAdd( rloc.giveSize() ); int rsize = rloc.giveSize(); int csize = cloc.giveSize(); - for ( i = 0; i < csize; i++ ) { - if ( ( ii = cloc(i) ) ) { - ii1 = ii - 1; - for ( j = 0; j < rsize; j++ ) { - if ( ( jj = rloc(j) ) ) { - jj1 = jj - 1; - this->columns [ ii1 ] [ jj1 ] += mat(j, i); +#if 0 + // adjust the size of receiver + int maxid = 0; + for (int i = 0; i < rsize; i++) maxid = max(maxid, rloc[i]); + for (int i = 0; i < csize; i++) maxid = max(maxid, cloc[i]); + this->growTo(maxid); +#endif + + for ( int i = 0; i < csize; i++ ) { + int ii = cloc[i]; + if ( ii ) { + int ii1 = ii - 1; + for ( int j = 0; j < rsize; j++ ) { + int jj = rloc[j]; + if ( jj ) { + int jj1 = jj - 1; + + int rowindx = this->insertRowInColumn(ii1, jj1); + columns[ ii1 ].at(rowindx) += mat(j, i); } } } } -#endif - // increment version this->version++; return 1; } + void DynCompCol :: zero() { -#ifndef DynCompCol_USE_STL_SETS - for ( int j = 0; j < nColumns; j++ ) { - columns_ [ j ]->zero(); + for ( auto &column : columns ) { + column.zero(); } -#else - for ( auto &col: columns ) { - for ( auto &val: col ) { - val.second = 0.; - } - } - -#endif - // increment version this->version++; } + void DynCompCol :: printStatistics() const { - int j, nz_ = 0; -#ifndef DynCompCol_USE_STL_SETS - for ( j = 0; j < nColumns; j++ ) { - nz_ += rowind_ [ j ]->giveSize(); + int nz_ = 0; + for ( auto &row : rowind ) { + nz_ += row.giveSize(); } -#else - for ( j = 0; j < nColumns; j++ ) { - nz_ += columns [ j ].size(); -#endif OOFEM_LOG_DEBUG("DynCompCol info: neq is %d, nelem is %d\n", nColumns, nz_); } -/*********************/ -/* Array access */ -/*********************/ - double &DynCompCol :: at(int i, int j) { - // increment version this->version++; -#ifndef DynCompCol_USE_STL_SETS - /* - * for (int t=1; t<=columns_[j-1]->giveSize(); t++) - * if (rowind_[j-1]->at(t) == (i-1)) return columns_[j-1]->at(t); - * printf ("DynCompCol::operator(): Array accessing exception -- out of bounds.\n"); - * exit(1); - * return columns_[0]->at(1); // return to suppress compiler warning message - */ - int rowIndx; - if ( ( rowIndx = this->giveRowIndx(j - 1, i - 1) ) ) { - return columns_ [ j - 1 ]->at(rowIndx); + + int rowIndx = this->giveRowIndx(j - 1, i - 1); + if ( rowIndx ) { + return columns[ j - 1 ].at(rowIndx); } OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j); - return columns_ [ 0 ]->at(1); // return to suppress compiler warning message - -#else - return this->columns [ j - 1 ] [ i - 1 ]; - -#endif + return columns[ 0 ].at(1); // return to suppress compiler warning message } double DynCompCol :: at(int i, int j) const { -#ifndef DynCompCol_USE_STL_SETS - /* - * for (int t=1; t<=columns_[j-1]->giveSize(); t++) - * if (rowind_[j-1]->at(t) == (i-1)) return columns_[j-1]->at(t); - * if (i <= nRows && j <= nColumns) return 0.0; - * else - * { - * printf ("DynCompCol::operator(): Array accessing exception -- out of bounds.\n"); - * exit(1); - * return (0); // return to suppress compiler warning message - * } - */ - int rowIndx; - if ( ( rowIndx = this->giveRowIndx(j - 1, i - 1) ) ) { - return columns_ [ j - 1 ]->at(rowIndx); + int rowIndx = this->giveRowIndx(j - 1, i - 1); + if ( rowIndx ) { + return columns[ j - 1 ].at(rowIndx); } if ( i <= nRows && j <= nColumns ) { return 0.0; } else { OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j); - return columns_ [ 0 ]->at(1); // return to suppress compiler warning message + return columns[ 0 ].at(1); // return to suppress compiler warning message } - -#else - auto pos = this->columns [ j - 1 ].find(i - 1); - if ( pos != this->columns [ j - 1 ].end() ) { - return pos->second; - } else { - OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j); - return 0.0; - } - -#endif } double DynCompCol :: operator() (int i, int j) const { -#ifndef DynCompCol_USE_STL_SETS - /* - * for (int t=1; t<=columns_[j]->giveSize(); t++) - * if (rowind_[j]->at(t) == i) return columns_[j]->at(t); - * if (i < nRows && j < nColumns) return 0.0; - * else - * { - * printf ("DynCompCol::operator(): Array accessing exception -- out of bounds.\n"); - * exit(1); - * return (0); // return to suppress compiler warning message - * } - */ int rowIndx; if ( ( rowIndx = this->giveRowIndx(j, i) ) ) { - return columns_ [ j ]->at(rowIndx); + return columns[ j ].at(rowIndx); } if ( i < nRows && j < nColumns ) { return 0.0; } else { OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j); - return columns_ [ 0 ]->at(1); // return to suppress compiler warning message + return columns[ 0 ].at(1); // return to suppress compiler warning message } - -#else - auto pos = this->columns [ j ].find(i); - if ( pos != this->columns [ j ].end() ) { - return pos->second; - } else { - OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j); - return 0.0; - } - -#endif } double &DynCompCol :: operator() (int i, int j) { - // increment version this->version++; -#ifndef DynCompCol_USE_STL_SETS - /* - * for (int t=1; t<=columns_[j]->giveSize(); t++) - * if (rowind_[j]->at(t) == i) return columns_[j]->at(t); - * - * printf ("DynCompCol::set: Array element (%d,%d) not in sparse structure -- cannot assign.\n",i,j); - * exit(1); - * return columns_[j]->at(1); // return to suppress compiler warning message - */ - int rowIndx; - if ( ( rowIndx = this->giveRowIndx(j, i) ) ) { - return columns_ [ j ]->at(rowIndx); + int rowIndx = this->giveRowIndx(j, i); + if ( rowIndx ) { + return columns[ j ].at(rowIndx); } OOFEM_ERROR("Array element (%d,%d) not in sparse structure -- cannot assign", i, j); - return columns_ [ 0 ]->at(1); // return to suppress compiler warning message - -#else - return this->columns [ j ] [ i ]; - -#endif + return columns[ 0 ].at(1); // return to suppress compiler warning message } void DynCompCol :: timesT(const FloatArray &x, FloatArray &answer) const { - // Check for compatible dimensions: if ( x.giveSize() != nRows ) { OOFEM_ERROR("Error in CompCol -- incompatible dimensions"); } answer.resize(nColumns); answer.zero(); -#ifndef DynCompCol_USE_STL_SETS - int i, t; - double r; - - for ( i = 0; i < nColumns; i++ ) { - r = 0.0; - for ( t = 1; t <= columns_ [ i ]->giveSize(); t++ ) { - r += columns_ [ i ]->at(t) * x( rowind_ [ i ]->at(t) ); - } - - answer(i) = r; - } - -#else - double r; for ( int i = 0; i < nColumns; i++ ) { double r = 0.0; - for ( auto &val: columns [ i ] ) { - r += val.second * x(val.first); + for ( int t = 1; t <= columns[ i ].giveSize(); t++ ) { + r += columns[ i ].at(t) * x[ rowind[ i ].at(t) ]; } - answer(i) = r; + answer[i] = r; } - -#endif } - void DynCompCol :: checkSizeTowards(IntArray &loc) { - int i, maxid = 0; + int maxid = 0; int size = loc.giveSize(); // adjust the size of receiver - for ( i = 0; i < size; i++ ) { - maxid = max( maxid, loc(i) ); + for ( int i = 0; i < size; i++ ) { + maxid = max( maxid, loc[i] ); } this->growTo(maxid); -#ifndef DynCompCol_USE_STL_SETS - int ii, j, jj; - - for ( i = 0; i < size; i++ ) { - if ( ( ii = loc(i) ) ) { - for ( j = 0; j < size; j++ ) { - if ( ( jj = loc(j) ) ) { + for ( int i = 0; i < size; i++ ) { + int ii = loc[i]; + if ( ii ) { + for ( int j = 0; j < size; j++ ) { + int jj = loc[j]; + if ( jj ) { this->insertRowInColumn(ii - 1, jj - 1); } } } } - -#endif } void DynCompCol :: checkSizeTowards(const IntArray &rloc, const IntArray &cloc) { - int i, maxid = 0; + int maxid = 0; int rsize = rloc.giveSize(); int csize = cloc.giveSize(); // adjust the size of receiver - for ( i = 0; i < rsize; i++ ) { - maxid = max( maxid, rloc(i) ); + for ( int i = 0; i < rsize; i++ ) { + maxid = max( maxid, rloc[i] ); } - for ( i = 0; i < csize; i++ ) { - maxid = max( maxid, cloc(i) ); + for ( int i = 0; i < csize; i++ ) { + maxid = max( maxid, cloc[i] ); } this->growTo(maxid); -#ifndef DynCompCol_USE_STL_SETS IntArray rowsToAdd( rloc.giveSize() ); - int ii, j, jj; - for ( i = 0; i < csize; i++ ) { - if ( ( ii = cloc(i) ) ) { - for ( j = 0; j < rsize; j++ ) { - if ( ( jj = rloc(j) ) ) { + for ( int i = 0; i < csize; i++ ) { + int ii = cloc[i]; + if ( ii ) { + for ( int j = 0; j < rsize; j++ ) { + int jj = rloc[j]; + if ( jj ) { insertRowInColumn(ii - 1, jj - 1); } } } } - -#endif } @@ -776,35 +410,17 @@ void DynCompCol :: checkSizeTowards(const IntArray &rloc, const IntArray &cloc) void DynCompCol :: growTo(int ns) { if ( ns > nColumns ) { -#ifndef DynCompCol_USE_STL_SETS - FloatArray **newcolumns_ = new FloatArray * [ ns ]; - IntArray **newrowind_ = new IntArray * [ ns ]; - - // copy existing columns - for ( int i = 0; i < nColumns; i++ ) { - newcolumns_ [ i ] = columns_ [ i ]; - newrowind_ [ i ] = rowind_ [ i ]; - } - - delete columns_; - delete rowind_; - - columns_ = newcolumns_; - rowind_ = newrowind_; -#else columns.resize(ns); -#endif - + rowind.resize(ns); nColumns = nRows = ns; } } -#ifndef DynCompCol_USE_STL_SETS int DynCompCol :: giveRowIndx(int col, int row) const { // fast row indx search, based on assumption, that row indices are sorted - int left = 1, right = this->rowind_ [ col ]->giveSize(); + int left = 1, right = this->rowind[ col ].giveSize(); int middle = ( left + right ) / 2; int middleVal; @@ -812,11 +428,11 @@ int DynCompCol :: giveRowIndx(int col, int row) const return 0; } - if ( this->rowind_ [ col ]->at(right) == row ) { + if ( this->rowind[ col ].at(right) == row ) { return right; } - while ( !( ( ( middleVal = this->rowind_ [ col ]->at(middle) ) == row ) || ( middle == left ) ) ) { + while ( !( ( ( middleVal = this->rowind[ col ].at(middle) ) == row ) || ( middle == left ) ) ) { if ( row > middleVal ) { left = middle; } else { @@ -834,29 +450,28 @@ int DynCompCol :: giveRowIndx(int col, int row) const } - int DynCompCol :: insertRowInColumn(int col, int row) { // insert row into column, preserving order of row indexes. - int i, oldsize = this->rowind_ [ col ]->giveSize(); + int oldsize = this->rowind[ col ].giveSize(); int left = 1, right = oldsize; int middle = ( left + right ) / 2; int middleVal; if ( oldsize == 0 ) { - rowind_ [ col ]->resizeWithValues(1, DynCompCol_CHUNK); - columns_ [ col ]->resizeWithValues(1, DynCompCol_CHUNK); - columns_ [ col ]->at(1) = 0.0; - rowind_ [ col ]->at(1) = row; + rowind[ col ].resizeWithValues(1, DynCompCol_CHUNK); + columns[ col ].resizeWithValues(1, DynCompCol_CHUNK); + columns[ col ].at(1) = 0.0; + rowind[ col ].at(1) = row; return 1; } - if ( this->rowind_ [ col ]->at(right) == row ) { + if ( this->rowind[ col ].at(right) == row ) { return right; } - while ( !( ( ( middleVal = this->rowind_ [ col ]->at(middle) ) == row ) || ( middle == left ) ) ) { + while ( !( ( ( middleVal = this->rowind[ col ].at(middle) ) == row ) || ( middle == left ) ) ) { if ( row > middleVal ) { left = middle; } else { @@ -871,25 +486,24 @@ DynCompCol :: insertRowInColumn(int col, int row) } // we have to insert new row entry - if ( row > this->rowind_ [ col ]->at(oldsize) ) { + if ( row > this->rowind[ col ].at(oldsize) ) { right = oldsize + 1; - } else if ( row < this->rowind_ [ col ]->at(1) ) { + } else if ( row < this->rowind[ col ].at(1) ) { right = 1; } // insert row at middle+1 position - rowind_ [ col ]->resizeWithValues(oldsize + 1, DynCompCol_CHUNK); - columns_ [ col ]->resizeWithValues(oldsize + 1, DynCompCol_CHUNK); + rowind[ col ].resizeWithValues(oldsize + 1, DynCompCol_CHUNK); + columns[ col ].resizeWithValues(oldsize + 1, DynCompCol_CHUNK); - for ( i = oldsize; i >= right; i-- ) { - rowind_ [ col ]->at(i + 1) = rowind_ [ col ]->at(i); - columns_ [ col ]->at(i + 1) = columns_ [ col ]->at(i); + for ( int i = oldsize; i >= right; i-- ) { + rowind[ col ].at(i + 1) = rowind[ col ].at(i); + columns[ col ].at(i + 1) = columns[ col ].at(i); } - columns_ [ col ]->at(right) = 0.0; - rowind_ [ col ]->at(right) = row; + columns[ col ].at(right) = 0.0; + rowind[ col ].at(right) = row; return right; } -#endif } // end namespace oofem diff --git a/src/oofemlib/iml/dyncompcol.h b/src/oofemlib/iml/dyncompcol.h index 8aa73b704..b1c9368f7 100644 --- a/src/oofemlib/iml/dyncompcol.h +++ b/src/oofemlib/iml/dyncompcol.h @@ -43,16 +43,13 @@ #include "sparsemtrx.h" #include "intarray.h" +#define _IFT_DynCompCol_Name "dcsc" + namespace oofem { // alloc chunk for columns #define DynCompCol_CHUNK 8 // turns on the stl set container, used to store column data, usually slower -//#define DynCompCol_USE_STL_SETS - -#ifdef DynCompCol_USE_STL_SETS - #include -#endif /** * Implementation of sparse matrix stored in compressed column storage. * Designed to allow simple dynamic runtime grow of receiver. @@ -60,61 +57,47 @@ namespace oofem { class OOFEM_EXPORT DynCompCol : public SparseMtrx { protected: + std::vector columns; // data values per column + std::vector rowind; // row_ind per column -#ifndef DynCompCol_USE_STL_SETS - FloatArray * * columns_; // data values per column - IntArray **rowind_; // row_ind per column -#else - std :: vector< std :: map< int, double > > columns; -#endif - - int base_; // index base: offset of first element + int base; // index base: offset of first element public: /** Constructor. Before any operation an internal profile must be built. * @see builInternalStructure */ - DynCompCol(int n); - /** Constructor. Before any operation an internal profile must be built. - * @see builInternalStructure - */ - DynCompCol(); + DynCompCol(int n=0); /// Copy constructor DynCompCol(const DynCompCol & S); /// Assignment operator DynCompCol &operator = ( const DynCompCol & C ); /// Destructor - virtual ~DynCompCol(); + virtual ~DynCompCol() {} // Overloaded methods: - SparseMtrx *GiveCopy() const; - virtual void times(const FloatArray &x, FloatArray &answer) const; - virtual void timesT(const FloatArray &x, FloatArray &answer) const; - virtual void times(double x); - virtual int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &); - virtual int assemble(const IntArray &loc, const FloatMatrix &mat); - virtual int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat); - virtual bool canBeFactorized() const { return false; } - virtual void zero(); - virtual const char* giveClassName() const { return "DynCompCol"; } - virtual SparseMtrxType giveType() const { return SMT_DynCompCol; } - virtual bool isAsymmetric() const { return true; } - virtual double &at(int i, int j); - virtual double at(int i, int j) const; - virtual void printStatistics() const; + std::unique_ptr clone() const override; + void times(const FloatArray &x, FloatArray &answer) const override; + void timesT(const FloatArray &x, FloatArray &answer) const override; + void times(double x) override; + int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &) override; + int assemble(const IntArray &loc, const FloatMatrix &mat) override; + int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) override; + bool canBeFactorized() const override { return false; } + void zero() override; + const char* giveClassName() const override { return "DynCompCol"; } + SparseMtrxType giveType() const override { return SMT_DynCompCol; } + bool isAsymmetric() const override { return true; } + double &at(int i, int j) override; + double at(int i, int j) const override; + void printStatistics() const override; /*******************************/ /* Access and info functions */ /*******************************/ -#ifndef DynCompCol_USE_STL_SETS /// Returns row index for i-th column - const IntArray *row_ind(int i) const { return rowind_ [ i ]; } - /// Returns column values - const FloatArray *column(int i) const { return columns_ [ i ]; } -#else + const IntArray &row_ind(int i) const { return rowind[ i ]; } /// Returns column values - std :: map< int, double > *column(int i) const { return columns [ i ]; } -#endif + const FloatArray &column(int i) const { return columns[ i ]; } protected: @@ -126,12 +109,10 @@ class OOFEM_EXPORT DynCompCol : public SparseMtrx /// Implements 0-based access double &operator() (int i, int j); -#ifndef DynCompCol_USE_STL_SETS /// Returns the row index of given row at given column, else returns zero. int giveRowIndx(int col, int row) const; /// Insert row entry into column, preserving order of row indexes, returns the index of new row. int insertRowInColumn(int col, int row); -#endif void checkSizeTowards(IntArray &); void checkSizeTowards(const IntArray &rloc, const IntArray &cloc); diff --git a/src/oofemlib/iml/dyncomprow.C b/src/oofemlib/iml/dyncomprow.C index 6497ed6e3..ecfc3962c 100644 --- a/src/oofemlib/iml/dyncomprow.C +++ b/src/oofemlib/iml/dyncomprow.C @@ -31,9 +31,6 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -// Class DynCompRow - -// inspired by SL++ #include "dyncomprow.h" #include "floatarray.h" @@ -53,121 +50,28 @@ namespace oofem { REGISTER_SparseMtrx(DynCompRow, SMT_DynCompRow); -DynCompRow :: DynCompRow(void) : SparseMtrx(), base_(0) -{ - rows_ = NULL; - colind_ = NULL; -} +DynCompRow :: DynCompRow(int n) : SparseMtrx(n, n), + base(0) +{} -DynCompRow :: DynCompRow(int n) : SparseMtrx(n, n), base_(0) -{ - rows_ = NULL; - colind_ = NULL; - nRows = nColumns = n; -} - - -/*****************************/ -/* Copy constructor */ -/*****************************/ - -DynCompRow :: DynCompRow(const DynCompRow &S) : SparseMtrx(S.nRows, S.nColumns), base_(S.base_) +DynCompRow :: DynCompRow(const DynCompRow &S) : SparseMtrx(S.nRows, S.nColumns), + rows(S.rows), + colind(S.colind), + diag(S.diag), + base(S.base) { - int i; - if ( S.rows_ ) { - this->rows_ = new FloatArray * [ S.nRows ]; - for ( i = 0; i < S.nRows; i++ ) { - this->rows_ [ i ] = new FloatArray(*S.rows_ [ i ]); - } - } else { - this->rows_ = NULL; - } - - if ( S.colind_ ) { - this->colind_ = new IntArray * [ S.nRows ]; - for ( i = 0; i < S.nRows; i++ ) { - this->colind_ [ i ] = new IntArray(*S.colind_ [ i ]); - } - } else { - this->colind_ = NULL; - } - - this->nRows = S.nRows; - this->nColumns = S.nColumns; this->version = S.version; } -// Destructor -DynCompRow :: ~DynCompRow() -{ - int i; - - if ( this->rows_ ) { - for ( i = 0; i < nRows; i++ ) { - delete this->rows_ [ i ]; - } - - delete this->rows_; - } - - if ( this->colind_ ) { - for ( i = 0; i < nRows; i++ ) { - delete this->colind_ [ i ]; - } - - delete this->colind_; - } -} - - - -/***************************/ -/* Assignment operator... */ -/***************************/ - DynCompRow &DynCompRow :: operator = ( const DynCompRow & C ) { - base_ = C.base_; - - int i; - - if ( this->rows_ ) { - for ( i = 0; i < nRows; i++ ) { - delete this->rows_ [ i ]; - } - - delete this->rows_; - } - - if ( C.rows_ ) { - this->rows_ = new FloatArray * [ C.nRows ]; - for ( i = 0; i < C.nRows; i++ ) { - this->rows_ [ i ] = new FloatArray(*C.rows_ [ i ]); - } - } else { - this->rows_ = NULL; - } - - - if ( this->colind_ ) { - for ( i = 0; i < nRows; i++ ) { - delete this->colind_ [ i ]; - } - - delete this->colind_; - } - - if ( C.colind_ ) { - this->colind_ = new IntArray * [ C.nRows ]; - for ( i = 0; i < C.nRows; i++ ) { - this->colind_ [ i ] = new IntArray(*C.colind_ [ i ]); - } - } else { - this->colind_ = NULL; - } + rows = C.rows; + colind = C.colind; + diag = C.diag; + base = C.base; nRows = C.nRows; nColumns = C.nColumns; @@ -175,16 +79,14 @@ DynCompRow &DynCompRow :: operator = ( const DynCompRow & C ) return * this; } -SparseMtrx *DynCompRow :: GiveCopy() const +std::unique_ptr DynCompRow :: clone() const { - DynCompRow *result = new DynCompRow(*this); - return result; + return std::make_unique(*this); } void DynCompRow :: times(const FloatArray &x, FloatArray &answer) const { - // Check for compatible dimensions: if ( x.giveSize() != nColumns ) { OOFEM_ERROR("Error in CompRow -- incompatible dimensions"); } @@ -192,13 +94,10 @@ void DynCompRow :: times(const FloatArray &x, FloatArray &answer) const answer.resize(nRows); answer.zero(); - int j, t; - double r; - - for ( j = 0; j < nRows; j++ ) { - r = 0.0; - for ( t = 1; t <= rows_ [ j ]->giveSize(); t++ ) { - r += rows_ [ j ]->at(t) * x( colind_ [ j ]->at(t) ); + for ( int j = 0; j < nRows; j++ ) { + double r = 0.0; + for ( int t = 1; t <= rows [ j ].giveSize(); t++ ) { + r += rows [ j ].at(t) * x[ colind [ j ].at(t) ]; } answer(j) = r; @@ -207,11 +106,10 @@ void DynCompRow :: times(const FloatArray &x, FloatArray &answer) const void DynCompRow :: times(double x) { - for ( int j = 0; j < nRows; j++ ) { - rows_ [ j ]->times(x); + for ( auto &row : rows ) { + row.times(x); } - // increment version this->version++; } @@ -221,48 +119,23 @@ int DynCompRow :: buildInternalStructure(EngngModel *eModel, int di, const Unkno IntArray loc; Domain *domain = eModel->giveDomain(di); - int i, ii, j, jj; #ifdef TIME_REPORT Timer timer; timer.startTimer(); #endif - nColumns = nRows = neq; - - if ( colind_ ) { - for ( i = 0; i < nRows; i++ ) { - delete this->colind_ [ i ]; - } - - delete this->colind_; - } - - colind_ = ( IntArray ** ) new IntArray * [ neq ]; - for ( j = 0; j < neq; j++ ) { - colind_ [ j ] = new IntArray(); - } - - // allocate value array - if ( rows_ ) { - for ( i = 0; i < nRows; i++ ) { - delete this->rows_ [ i ]; - } - - delete this->rows_; - } - - rows_ = ( FloatArray ** ) new FloatArray * [ neq ]; - for ( j = 0; j < neq; j++ ) { - rows_ [ j ] = new FloatArray(); - } + this->colind.clear(); + this->rows.clear(); + this->growTo(neq); for ( auto &elem : domain->giveElements() ) { elem->giveLocationArray(loc, s); - - for ( i = 1; i <= loc.giveSize(); i++ ) { // row indx + for ( int i = 1; i <= loc.giveSize(); i++ ) { // row indx + int ii; if ( ( ii = loc.at(i) ) ) { - for ( j = 1; j <= loc.giveSize(); j++ ) { // col indx + for ( int j = 1; j <= loc.giveSize(); j++ ) { // col indx + int jj; if ( ( jj = loc.at(j) ) ) { this->insertColInRow(ii - 1, jj - 1); } @@ -272,21 +145,21 @@ int DynCompRow :: buildInternalStructure(EngngModel *eModel, int di, const Unkno } - // loop over active boundary conditions - //int nbc = domain->giveNumberOfBoundaryConditions(); std :: vector< IntArray >r_locs; std :: vector< IntArray >c_locs; for ( auto &gbc : domain->giveBcs() ) { ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() ); - if ( bc != NULL ) { + if ( bc ) { bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s); for ( std :: size_t k = 0; k < r_locs.size(); k++ ) { IntArray &krloc = r_locs [ k ]; IntArray &kcloc = c_locs [ k ]; for ( int i = 1; i <= krloc.giveSize(); i++ ) { + int ii; if ( ( ii = krloc.at(i) ) ) { for ( int j = 1; j <= kcloc.giveSize(); j++ ) { + int jj; if ( ( jj = kcloc.at(j) ) ) { this->insertColInRow(ii - 1, jj - 1); } @@ -297,17 +170,13 @@ int DynCompRow :: buildInternalStructure(EngngModel *eModel, int di, const Unkno } } - - - int nz_ = 0; - for ( j = 0; j < neq; j++ ) { - nz_ += this->colind_ [ j ]->giveSize(); + for ( auto &col : this->colind ) { + nz_ += col.giveSize(); } OOFEM_LOG_DEBUG("DynCompRow info: neq is %d, nelem is %d\n", neq, nz_); - // increment version this->version++; #ifdef TIME_REPORT timer.stopTimer(); @@ -320,23 +189,19 @@ int DynCompRow :: buildInternalStructure(EngngModel *eModel, int di, const Unkno int DynCompRow :: assemble(const IntArray &loc, const FloatMatrix &mat) { - int i, j, ii, jj, dim; + int dim = mat.giveNumberOfRows(); # ifdef DEBUG - dim = mat.giveNumberOfRows(); if ( dim != loc.giveSize() ) { OOFEM_ERROR("dimension of 'k' and 'loc' mismatch"); } - # endif - dim = mat.giveNumberOfRows(); - - for ( j = 1; j <= dim; j++ ) { - jj = loc.at(j); + for ( int j = 1; j <= dim; j++ ) { + int jj = loc.at(j); if ( jj ) { - for ( i = 1; i <= dim; i++ ) { - ii = loc.at(i); + for ( int i = 1; i <= dim; i++ ) { + int ii = loc.at(i); if ( ii ) { this->at(ii, jj) += mat.at(i, j); } @@ -344,7 +209,6 @@ int DynCompRow :: assemble(const IntArray &loc, const FloatMatrix &mat) } } - // increment version this->version++; return 1; } @@ -353,68 +217,61 @@ int DynCompRow :: assemble(const IntArray &rloc, const IntArray &cloc, const Flo { // optimized low-end implementation IntArray colsToAdd( rloc.giveSize() ); - int i, ii, ii1, j, jj, jj1, colindx; int rsize = rloc.giveSize(); int csize = cloc.giveSize(); - for ( i = 0; i < rsize; i++ ) { - if ( ( ii = rloc(i) ) ) { - ii1 = ii - 1; - for ( j = 0; j < csize; j++ ) { - if ( ( jj = cloc(j) ) ) { - jj1 = jj - 1; - - colindx = this->insertColInRow(ii1, jj1); - //if (rowind_[j-1]->at(t) == (i-1)) return columns_[j-1]->at(t); - rows_ [ ii1 ]->at(colindx) += mat(i, j); + for ( int i = 0; i < rsize; i++ ) { + int ii; + if ( ( ii = rloc[i] ) ) { + int ii1 = ii - 1; + for ( int j = 0; j < csize; j++ ) { + int jj; + if ( ( jj = cloc[j] ) ) { + int jj1 = jj - 1; + + int colindx = this->insertColInRow(ii1, jj1); + rows [ ii1 ].at(colindx) += mat(i, j); } } } } - // increment version this->version++; return 1; } void DynCompRow :: zero() { - for ( int j = 0; j < nRows; j++ ) { - rows_ [ j ]->zero(); + for ( auto &row: rows ) { + row.zero(); } - // increment version this->version++; } void DynCompRow :: printStatistics() const { - int nz_ = 0; - for ( int j = 0; j < nRows; j++ ) { - nz_ += rows_ [ j ]->giveSize(); + int nz = 0; + for ( auto &row : rows ) { + nz += row.giveSize(); } - printf("\nDynCompRow info: neq is %d, nelem is %d\n", nRows, nz_); + printf("\nDynCompRow info: neq is %d, nelem is %d\n", nRows, nz); } -/*********************/ -/* Array access */ -/*********************/ - double &DynCompRow :: at(int i, int j) { int colIndx; - // increment version this->version++; if ( ( colIndx = this->giveColIndx(i - 1, j - 1) ) ) { - return rows_ [ i - 1 ]->at(colIndx); + return rows [ i - 1 ].at(colIndx); } OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j); - return rows_ [ 0 ]->at(1); // return to suppress compiler warning message + return rows [ 0 ].at(1); // return to suppress compiler warning message } @@ -422,14 +279,14 @@ double DynCompRow :: at(int i, int j) const { int colIndx; if ( ( colIndx = this->giveColIndx(i - 1, j - 1) ) ) { - return rows_ [ i - 1 ]->at(colIndx); + return rows [ i - 1 ].at(colIndx); } if ( i <= nRows && j <= nColumns ) { return 0.0; } else { OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j); - return rows_ [ 0 ]->at(1); // return to suppress compiler warning message + return rows [ 0 ].at(1); // return to suppress compiler warning message } } @@ -437,14 +294,14 @@ double DynCompRow :: operator() (int i, int j) const { int colIndx; if ( ( colIndx = this->giveColIndx(i, j) ) ) { - return rows_ [ i ]->at(colIndx); + return rows [ i ].at(colIndx); } if ( i < nRows && j < nColumns ) { return 0.0; } else { OOFEM_ERROR("Array accessing exception -- (%d,%d) out of bounds", i, j); - return rows_ [ 0 ]->at(1); // return to suppress compiler warning message + return rows [ 0 ].at(1); // return to suppress compiler warning message } } @@ -456,11 +313,11 @@ double &DynCompRow :: operator() (int i, int j) this->version++; if ( ( colIndx = this->giveColIndx(i, j) ) ) { - return rows_ [ i ]->at(colIndx); + return rows [ i ].at(colIndx); } OOFEM_ERROR("Array element (%d,%d) not in sparse structure -- cannot assign", i, j); - return rows_ [ 0 ]->at(1); // return to suppress compiler warning message + return rows [ 0 ].at(1); // return to suppress compiler warning message } void DynCompRow :: timesT(const FloatArray &x, FloatArray &answer) const @@ -473,13 +330,10 @@ void DynCompRow :: timesT(const FloatArray &x, FloatArray &answer) const answer.resize(nColumns); answer.zero(); - int i, t; - double r; - - for ( i = 0; i < nColumns; i++ ) { - r = x(i); - for ( t = 1; t <= rows_ [ i ]->giveSize(); t++ ) { - answer( colind_ [ i ]->at(t) ) += rows_ [ i ]->at(t) * r; + for ( int i = 0; i < nColumns; i++ ) { + double r = x[i]; + for ( int t = 1; t <= rows [ i ].giveSize(); t++ ) { + answer[ colind [ i ].at(t) ] += rows [ i ].at(t) * r; } } } @@ -488,21 +342,21 @@ void DynCompRow :: timesT(const FloatArray &x, FloatArray &answer) const void DynCompRow :: checkSizeTowards(IntArray &loc) { - int i, maxid = 0; + int maxid = 0; int size = loc.giveSize(); // adjust the size of receiver - for ( i = 0; i < size; i++ ) { - maxid = max( maxid, loc(i) ); + for ( int i = 0; i < size; i++ ) { + maxid = max( maxid, loc[i] ); } this->growTo(maxid); - int ii, j, jj; - - for ( i = 0; i < size; i++ ) { - if ( ( ii = loc(i) ) ) { - for ( j = 0; j < size; j++ ) { - if ( ( jj = loc(j) ) ) { + for ( int i = 0; i < size; i++ ) { + int ii; + if ( ( ii = loc[i] ) ) { + for ( int j = 0; j < size; j++ ) { + int jj; + if ( ( jj = loc[j] ) ) { this->insertColInRow(ii - 1, jj - 1); } } @@ -513,27 +367,27 @@ void DynCompRow :: checkSizeTowards(IntArray &loc) void DynCompRow :: checkSizeTowards(const IntArray &rloc, const IntArray &cloc) { - int i, maxid = 0; + int maxid = 0; int rsize = rloc.giveSize(); int csize = cloc.giveSize(); // adjust the size of receiver - for ( i = 0; i < rsize; i++ ) { - maxid = max( maxid, rloc(i) ); + for ( int i = 0; i < rsize; i++ ) { + maxid = max( maxid, rloc[i] ); } - for ( i = 0; i < csize; i++ ) { - maxid = max( maxid, cloc(i) ); + for ( int i = 0; i < csize; i++ ) { + maxid = max( maxid, cloc[i] ); } this->growTo(maxid); - int ii, j, jj; - - for ( i = 0; i < rsize; i++ ) { - if ( ( ii = rloc(i) ) ) { - for ( j = 0; j < csize; j++ ) { - if ( ( jj = cloc(j) ) ) { + for ( int i = 0; i < rsize; i++ ) { + int ii; + if ( ( ii = rloc[i] ) ) { + for ( int j = 0; j < csize; j++ ) { + int jj; + if ( ( jj = cloc[j] ) ) { this->insertColInRow(ii - 1, jj - 1); } } @@ -542,25 +396,11 @@ void DynCompRow :: checkSizeTowards(const IntArray &rloc, const IntArray &cloc) } - void DynCompRow :: growTo(int ns) { if ( ns > nRows ) { - FloatArray **newrows_ = new FloatArray * [ ns ]; - IntArray **newcolind_ = new IntArray * [ ns ]; - - // copy existing columns - for ( int i = 0; i < nRows; i++ ) { - newrows_ [ i ] = rows_ [ i ]; - newcolind_ [ i ] = colind_ [ i ]; - } - - delete rows_; - delete colind_; - - rows_ = newrows_; - colind_ = newcolind_; - + this->rows.resize(ns); + this->colind.resize(ns); nColumns = nRows = ns; } } @@ -569,7 +409,7 @@ void DynCompRow :: growTo(int ns) int DynCompRow :: giveColIndx(int row, int col) const { // fast col indx search, based on assumption, that col indices are sorted - int left = 1, right = this->colind_ [ row ]->giveSize(); + int left = 1, right = this->colind [ row ].giveSize(); int middle = ( left + right ) / 2; int middleVal; @@ -577,11 +417,11 @@ int DynCompRow :: giveColIndx(int row, int col) const return 0; } - if ( this->colind_ [ row ]->at(right) == col ) { + if ( this->colind [ row ].at(right) == col ) { return right; } - while ( !( ( ( middleVal = this->colind_ [ row ]->at(middle) ) == col ) || ( middle == left ) ) ) { + while ( !( ( ( middleVal = this->colind [ row ].at(middle) ) == col ) || ( middle == left ) ) ) { if ( col > middleVal ) { left = middle; } else { @@ -599,29 +439,28 @@ int DynCompRow :: giveColIndx(int row, int col) const } - int DynCompRow :: insertColInRow(int row, int col) { // insert col entry into row, preserving order of col indexes. - int i, oldsize = this->colind_ [ row ]->giveSize(); + int oldsize = this->colind [ row ].giveSize(); int left = 1, right = oldsize; int middle = ( left + right ) / 2; int middleVal; if ( oldsize == 0 ) { - colind_ [ row ]->resizeWithValues(1, DynCompRow_CHUNK); - rows_ [ row ]->resizeWithValues(1, DynCompRow_CHUNK); - rows_ [ row ]->at(1) = 0.0; - colind_ [ row ]->at(1) = col; + colind [ row ].resizeWithValues(1, DynCompRow_CHUNK); + rows [ row ].resizeWithValues(1, DynCompRow_CHUNK); + rows [ row ].at(1) = 0.0; + colind [ row ].at(1) = col; return 1; } - if ( this->colind_ [ row ]->at(right) == col ) { + if ( this->colind [ row ].at(right) == col ) { return right; } - while ( !( ( ( middleVal = this->colind_ [ row ]->at(middle) ) == col ) || ( middle == left ) ) ) { + while ( !( ( ( middleVal = this->colind [ row ].at(middle) ) == col ) || ( middle == left ) ) ) { if ( col > middleVal ) { left = middle; } else { @@ -636,87 +475,27 @@ DynCompRow :: insertColInRow(int row, int col) } // we have to insert new row entry - if ( col > this->colind_ [ row ]->at(oldsize) ) { + if ( col > this->colind [ row ].at(oldsize) ) { right = oldsize + 1; - } else if ( col < this->colind_ [ row ]->at(1) ) { + } else if ( col < this->colind [ row ].at(1) ) { right = 1; } // insert col at middle+1 position - colind_ [ row ]->resizeWithValues(oldsize + 1, DynCompRow_CHUNK); - rows_ [ row ]->resizeWithValues(oldsize + 1, DynCompRow_CHUNK); + colind [ row ].resizeWithValues(oldsize + 1, DynCompRow_CHUNK); + rows [ row ].resizeWithValues(oldsize + 1, DynCompRow_CHUNK); - for ( i = oldsize; i >= right; i-- ) { - colind_ [ row ]->at(i + 1) = colind_ [ row ]->at(i); - rows_ [ row ]->at(i + 1) = rows_ [ row ]->at(i); + for ( int i = oldsize; i >= right; i-- ) { + colind [ row ].at(i + 1) = colind [ row ].at(i); + rows [ row ].at(i + 1) = rows [ row ].at(i); } - rows_ [ row ]->at(right) = 0.0; - colind_ [ row ]->at(right) = col; + rows [ row ].at(right) = 0.0; + colind [ row ].at(right) = col; return right; } - - - -/* reference ILU(0) version - * void - * DynCompRow::ILUPYourself () - * { - * int i, j, k, kk, krow, colk; - * double multiplier; - * - * IntArray iw (nColumns); - * diag_rowptr_.resize(nRows); - * - **#ifndef DynCompRow_USE_STL_SETS - * for (i = 0; i < nRows; i++) // row loop - * if ((diag_rowptr_(i) = giveColIndx (i, i)) == 0) { // giveColIndx returns 1-based indexing - * printf ("DynCompRow:: Zero diagonal member\n"); - * exit(1); - * } - * - **#else - * std::map::iterator pos; - * for (i = 0; i < nRows; i++) {// row loop - * pos = this->rows[i]->find(i); - * if (pos != this->rows[i-1]->end()) - * diag_rowptr_(i) = *pos->first; - * else { - * printf ("DynCompRow:: Zero diagonal member\n"); - * exit(1); - * } - * } - **#endif - * - * // FACTOR MATRIX // - **#ifndef DynCompRow_USE_STL_SETS - * - * for (i=1; i< nRows; i++) { // loop over rows - * for (k=0; k < (diag_rowptr_(i)-1); k++) { // loop 1,...,i-1 for (i,k) \in NZ(A) - * // initialize k-th row indexes - * krow = colind_[i]->at(k+1); - * for (kk=1; kk<= rows_[krow]->giveSize(); kk++) - * iw(colind_[krow]->at(kk)) = kk; - * multiplier = (rows_[i]->at(k+1) /= rows_[krow]->at(diag_rowptr_(krow))); - * for (j=k+1; j < rows_[i]->giveSize(); j++) { // loop over k+1,...,n for (i,j) \in NZ(A) - * colk = iw (colind_[i]->at(j+1)); // column position of a(i,j) at row k - * if (colk) rows_[i]->at(j+1) -= multiplier * rows_[krow]->at(colk); // aij=aij-aik*akj - * } - * // Refresh all iw enries to zero - * for (kk=1; kk<= rows_[krow]->giveSize(); kk++) - * iw(colind_[krow]->at(kk)) = 0; - * } - * } - * - **#else - * NOT IMPLEMENTED NOW - **#endif - * } - */ - - //#define ILU_0 //#define ILU_DROP_TOL 1.e-8 #define ILU_ROW_CHUNK 10 @@ -725,64 +504,59 @@ DynCompRow :: insertColInRow(int row, int col) void DynCompRow :: ILUPYourself(int part_fill, double drop_tol) { - int i, ii, j, jcol, k, kk, krow, ck; - int end, curr; - double multiplier, inorm, val; - IntArray irw(nColumns), iw; FloatArray w; - diag_rowptr_.resize(nRows); + diag.resize(nRows); #ifdef TIME_REPORT Timer timer; timer.startTimer(); #endif - for ( i = 0; i < nRows; i++ ) { // row loop - if ( ( diag_rowptr_(i) = giveColIndx(i, i) ) == 0 ) { // giveColIndx returns 1-based indexing + for ( int i = 0; i < nRows; i++ ) { // row loop + if ( ( diag[i] = giveColIndx(i, i) ) == 0 ) { // giveColIndx returns 1-based indexing OOFEM_ERROR("zero value on diagonal"); } } /* FACTOR MATRIX */ - for ( i = 1; i < nRows; i++ ) { // loop over rows - inorm = 0.0; - for ( ii = 1; ii <= rows_ [ i ]->giveSize(); ii++ ) { - val = rows_ [ i ]->at(ii); + for ( int i = 1; i < nRows; i++ ) { // loop over rows + double inorm = 0.0; + for ( int ii = 1; ii <= rows [ i ].giveSize(); ii++ ) { + double val = rows [ i ].at(ii); inorm += val * val; } inorm = sqrt(inorm); - w.resizeWithValues(rows_ [ i ]->giveSize(), ILU_ROW_CHUNK); - iw.resizeWithValues(rows_ [ i ]->giveSize(), ILU_ROW_CHUNK); - for ( kk = 1; kk <= rows_ [ i ]->giveSize(); kk++ ) { - irw( colind_ [ i ]->at(kk) ) = kk; - iw(kk - 1) = colind_ [ i ]->at(kk); - w(kk - 1) = rows_ [ i ]->at(kk); + w.resizeWithValues(rows [ i ].giveSize(), ILU_ROW_CHUNK); + iw.resizeWithValues(rows [ i ].giveSize(), ILU_ROW_CHUNK); + for ( int kk = 1; kk <= rows [ i ].giveSize(); kk++ ) { + irw[ colind [ i ].at(kk) ] = kk; + iw[kk - 1] = colind [ i ].at(kk); + w[kk - 1] = rows [ i ].at(kk); } - //for (k=0; k < (diag_rowptr_(i)-1); k++) { // loop 1,...,i-1 for (i,k) \in NZ(A) - k = 0; + //for (k=0; k < (diag(i)-1); k++) { // loop 1,...,i-1 for (i,k) \in NZ(A) + int k = 0; while ( iw.at(k + 1) < i ) { // initialize k-th row indexes - krow = iw.at(k + 1); - //multiplier = (rows_[i]->at(k+1) /= rows_[krow]->at(diag_rowptr_(krow))); - multiplier = ( w.at(k + 1) /= rows_ [ krow ]->at( diag_rowptr_(krow) ) ); - + int krow = iw.at(k + 1); + //multiplier = (rows[i].at(k+1) /= rows[krow].at(diag(krow))); + double multiplier = ( w.at(k + 1) /= rows [ krow ].at( diag[krow] ) ); #ifndef ILU_0 // first dropping rule for aik if ( fabs(multiplier) >= drop_tol * inorm ) #endif { // first drop rule - for ( j = 0; j < colind_ [ krow ]->giveSize(); j++ ) { - jcol = colind_ [ krow ]->at(j + 1); + for ( int j = 0; j < colind [ krow ].giveSize(); j++ ) { + int jcol = colind [ krow ].at(j + 1); if ( jcol > krow ) { - if ( irw(jcol) ) { - //rows_[i]->at(irw(jcol)) -= multiplier*rows_[krow]->at(j+1); - w.at( irw(jcol) ) -= multiplier * rows_ [ krow ]->at(j + 1); + if ( irw[jcol] ) { + //rows[i].at(irw(jcol)) -= multiplier*rows[krow].at(j+1); + w.at( irw[jcol] ) -= multiplier * rows [ krow ].at(j + 1); } else { #ifndef ILU_0 // insert new entry @@ -791,19 +565,19 @@ DynCompRow :: ILUPYourself(int part_fill, double drop_tol) iw.resizeWithValues(newsize, ILU_ROW_CHUNK); iw.at(newsize) = jcol; - w.at(newsize) = -multiplier * rows_ [ krow ]->at(j + 1); - irw(jcol) = newsize; + w.at(newsize) = -multiplier * rows [ krow ].at(j + 1); + irw[jcol] = newsize; #endif /* * ipos = insertColInRow (i,jcol) ; - * for (kk=ipos+1; kk<= rows_[i]->giveSize(); kk++) - * irw(colind_[i]->at(kk))++; + * for (kk=ipos+1; kk<= rows[i].giveSize(); kk++) + * irw(colind[i].at(kk))++; * * ipos = insertColInRow (i,jcol) ; - * rows_[i]->at(ipos) = -multiplier*rows_[krow]->at(j+1); + * rows[i].at(ipos) = -multiplier*rows[krow].at(j+1); * irw(jcol) = ipos; - * if (jcol < i) diag_rowptr_(i)++; + * if (jcol < i) diag(i)++; */ } } @@ -811,29 +585,29 @@ DynCompRow :: ILUPYourself(int part_fill, double drop_tol) } // scan iw to find closest index to krow - ck = nColumns + 1; - for ( kk = 0; kk < iw.giveSize(); kk++ ) { - if ( ( ( iw(kk) - krow ) > 0 ) && ( ( iw(kk) - krow ) < ( ck - krow ) ) ) { - ck = iw(kk); + int ck = nColumns + 1; + for ( int kk = 0; kk < iw.giveSize(); kk++ ) { + if ( ( ( iw[kk] - krow ) > 0 ) && ( ( iw[kk] - krow ) < ( ck - krow ) ) ) { + ck = iw[kk]; } } - k = irw(ck) - 1; + k = irw[ck] - 1; } #ifndef ILU_0 - end = iw.giveSize(); - curr = 1; + int end = iw.giveSize(); + int curr = 1; // second drop rule while ( curr <= end ) { if ( ( fabs( w.at(curr) ) < drop_tol * inorm ) && ( iw.at(curr) != i ) ) { // remove entry w.at(curr) = w.at(end); - irw( iw.at(curr) ) = 0; + irw[ iw.at(curr) ] = 0; iw.at(curr) = iw.at(end); if ( curr != end ) { - irw( iw.at(curr) ) = curr; + irw[ iw.at(curr) ] = curr; } end--; @@ -851,8 +625,8 @@ DynCompRow :: ILUPYourself(int part_fill, double drop_tol) // select only the p-largest w values this->qsortRow(iw, irw, w, 0, iw.giveSize() - 1); // - int lsizeLimit = diag_rowptr_(i) - 1; - int usizeLimit = rows_ [ i ]->giveSize() - lsizeLimit; + int lsizeLimit = diag[i] - 1; + int usizeLimit = rows [ i ].giveSize() - lsizeLimit; lsizeLimit += part_fill; usizeLimit += part_fill; @@ -860,16 +634,16 @@ DynCompRow :: ILUPYourself(int part_fill, double drop_tol) int lnums = 0; int unums = 0; count = 0; - for ( kk = 1; kk <= iw.giveSize(); kk++ ) { + for ( int kk = 1; kk <= iw.giveSize(); kk++ ) { if ( iw.at(kk) < i ) { // lpart if ( ++lnums > lsizeLimit ) { - irw( iw.at(kk) ) = 0; + irw[ iw.at(kk) ] = 0; } else { count++; } } else if ( iw.at(kk) > i ) { // upart if ( ++unums > usizeLimit ) { - irw( iw.at(kk) ) = 0; + irw[ iw.at(kk) ] = 0; } else { count++; } @@ -881,20 +655,20 @@ DynCompRow :: ILUPYourself(int part_fill, double drop_tol) #else int count = iw.giveSize(); #endif - rows_ [ i ]->resize(count); - colind_ [ i ]->resize(count); + rows [ i ].resize(count); + colind [ i ].resize(count); int icount = 1; - int kki, indx, idist, previndx = -1; + int indx, idist, previndx = -1; int kkend = iw.giveSize(); - for ( kk = 1; kk <= count; kk++ ) { + for ( int kk = 1; kk <= count; kk++ ) { idist = nColumns + 2; indx = 0; - for ( kki = 1; kki <= kkend; kki++ ) { - if ( ( irw( iw.at(kki) ) != 0 ) && ( iw.at(kki) > previndx ) && ( ( iw.at(kki) - previndx ) < idist ) ) { - idist = ( iw.at(kki) - previndx ); + for ( int kki = 1; kki <= kkend; kki++ ) { + if ( ( irw[ iw.at(kki) ] != 0 ) && ( iw.at(kki) > previndx ) && ( ( iw.at(kki) - previndx ) < idist ) ) { + idist = iw.at(kki) - previndx; indx = kki; } } @@ -904,52 +678,52 @@ DynCompRow :: ILUPYourself(int part_fill, double drop_tol) } previndx = iw.at(indx); - rows_ [ i ]->at(icount) = w.at(indx); - colind_ [ i ]->at(icount) = iw.at(indx); - if ( colind_ [ i ]->at(icount) == i ) { - diag_rowptr_(i) = icount; + rows [ i ].at(icount) = w.at(indx); + colind [ i ].at(icount) = iw.at(indx); + if ( colind [ i ].at(icount) == i ) { + diag[i] = icount; } icount++; - // exclude the indx entry from search by moving it to the end of list - irw( iw.at(indx) ) = 0; + irw[ iw.at(indx) ] = 0; iw.at(indx) = iw.at(kkend); w.at(indx) = w.at(kkend); - if ( irw( iw.at(indx) ) != 0 ) { - irw( iw.at(indx) ) = indx; + if ( irw[ iw.at(indx) ] != 0 ) { + irw[ iw.at(indx) ] = indx; } kkend--; // exclude the indx entry from search by moving it to the end of list - //swap = irw(iw.at(indx)); irw(iw.at(indx)) = irw(iw.at(kkend)); irw(iw.at(kkend)) = swap; - //swap = iw.at(indx); iw.at(indx) = iw.at(kkend); iw.at(kkend) = swap; - //dswap= w.at(indx); w.at(indx) = w.at(kkend); w.at(kkend) = dswap; - - //kkend--; +#if 0 + std::swap(irw[iw.at(indx)], irw[iw.at(kkend)]); + std::swap(iw.at(indx), iw.at(kkend)); + std::swap(w.at(indx), w.at(kkend)); + kkend--; +#endif } - /* - * int icount = 1; - * for (kk=1; kk<= nColumns; kk++) { - * if ( irw.at(kk) > 0 ) { - * rows_[i]->at(icount) = w.at(abs(irw(kk-1))); - * colind_[i]->at(icount) = iw.at(abs(irw(kk-1))); - * if (colind_[i]->at(icount) == i) diag_rowptr_(i) = icount; - * icount++; - * } - * } - */ +#if 0 + int icount = 1; + for (kk=1; kk<= nColumns; kk++) { + if ( irw.at(kk) > 0 ) { + rows[i].at(icount) = w.at(abs(irw[kk-1])); + colind[i].at(icount) = iw.at(abs(irw[kk-1])); + if (colind[i].at(icount) == i) diag[i] = icount; + icount++; + } + } +#endif if ( ( icount - count ) != 1 ) { OOFEM_ERROR("%d - row errorr (%d,%d)\n", i, icount, count); } //Refresh all iw enries to zero - for ( kk = 1; kk <= iw.giveSize(); kk++ ) { - irw( iw.at(kk) ) = 0; + for ( int kk = 1; kk <= iw.giveSize(); kk++ ) { + irw[ iw.at(kk) ] = 0; } //irw.zero(); @@ -960,7 +734,6 @@ DynCompRow :: ILUPYourself(int part_fill, double drop_tol) OOFEM_LOG_DEBUG( "\nILUT(%d,%e): user time consumed by factorization: %.2fs\n", part_fill, drop_tol, timer.getUtime() ); #endif - // increment version this->version++; } @@ -970,36 +743,29 @@ void DynCompRow :: ILUPsolve(const FloatArray &x, FloatArray &y) const { int M = x.giveSize(); - double r; FloatArray work(M); - int i, t; - - y.resize(M); - - work.zero(); // solve Lw=x - for ( i = 0; i < M; i++ ) { - r = x(i); - for ( t = 0; t < ( diag_rowptr_(i) - 1 ); t++ ) { - r -= rows_ [ i ]->at(t + 1) * work( colind_ [ i ]->at(t + 1) ); + for ( int i = 0; i < M; i++ ) { + double r = x[i]; + for ( int t = 0; t < ( diag[i] - 1 ); t++ ) { + r -= rows [ i ].at(t + 1) * work( colind [ i ].at(t + 1) ); } - work(i) = r; + work[i] = r; } + y.resize(M); y.zero(); // solve Uy=w - for ( i = M - 1; i >= 0; i-- ) { - r = work(i); - for ( t = diag_rowptr_(i); t < rows_ [ i ]->giveSize(); t++ ) { - r -= rows_ [ i ]->at(t + 1) * y( colind_ [ i ]->at(t + 1) ); + for ( int i = M - 1; i >= 0; i-- ) { + double r = work[i]; + for ( int t = diag[i]; t < rows [ i ].giveSize(); t++ ) { + r -= rows [ i ].at(t + 1) * y( colind [ i ].at(t + 1) ); } - y(i) = r / rows_ [ i ]->at( diag_rowptr_(i) ); + y[i] = r / rows [ i ].at( diag[i] ); } - - //return y; } @@ -1009,65 +775,26 @@ DynCompRow :: ILUPtrans_solve(const FloatArray &x, FloatArray &y) const int M = x.giveSize(); FloatArray work(M); - int i, t; - y.resize(M); - //work.zero(); + // solve for U^Tw = x - for ( i = 0; i < M; i++ ) { - work(i) = ( x(i) + work(i) ) / rows_ [ i ]->at( diag_rowptr_(i) ); - for ( t = diag_rowptr_(i); t < rows_ [ i ]->giveSize(); t++ ) { - work( colind_ [ i ]->at(t + 1) ) -= rows_ [ i ]->at(t + 1) * work(i); + for ( int i = 0; i < M; i++ ) { + work[i] = ( x[i] + work[i] ) / rows [ i ].at( diag[i] ); + for ( int t = diag[i]; t < rows [ i ].giveSize(); t++ ) { + work( colind [ i ].at(t + 1) ) -= rows [ i ].at(t + 1) * work[i]; } } // solve for L^T y = w - for ( i = M - 1; i >= 0; i-- ) { - y(i) = work(i); - for ( t = 1; t < diag_rowptr_(i); t++ ) { - work( colind_ [ i ]->at(t) ) -= rows_ [ i ]->at(t) * y(i); + for ( int i = M - 1; i >= 0; i-- ) { + y[i] = work[i]; + for ( int t = 1; t < diag[i]; t++ ) { + work( colind [ i ].at(t) ) -= rows [ i ].at(t) * y[i]; } } - - //return y; } -/* - * void - * DynCompRow::qsortRow (IntArray& ind, IntArray& ir, FloatArray& val, int l, int r) - * { - * if (r<=l) return; - * int i = qsortRowPartition (ind, ir, val, l, r); - * qsortRow (ind, ir, val, l, i-1); - * qsortRow (ind, ir, val, i+1, r); - * } - * - * - * int - * DynCompRow::qsortRowPartition (IntArray& ind, IntArray& ir, FloatArray& val, int l, int r) - * { - * int i=l-1, j=r; - * double v = fabs(val(r)); - * int swap; - * double dswap; - * - * for (;;) { - * while (( fabs(val(++i)) > v )); - * while (( v > fabs(val(--j)))) if (j==l) break; - * if (i >= j) break; - * swap = ir(ind(i)); ir(ind(i)) = ir(ind(j)); ir(ind(j)) = swap; - * swap = ind(i); ind(i) = ind(j); ind(j) = swap; - * dswap= val(i); val(i) = val(j); val(j) = dswap; - * } - * swap = ir(ind(i)); ir(ind(i)) = ir(ind(r)); ir(ind(r)) = swap; - * swap = ind(i); ind(i) = ind(r); ind(r) = swap; - * dswap= val(i); val(i) = val(r); val(r) = dswap; - * - * return i; - * } - */ - void DynCompRow :: qsortRow(IntArray &ind, IntArray &ir, FloatArray &val, int l, int r) { @@ -1085,9 +812,7 @@ int DynCompRow :: qsortRowPartition(IntArray &ind, IntArray &ir, FloatArray &val, int l, int r) { int i = l - 1, j = r; - double v = fabs( val(r) ); - int swap; - double dswap; + double v = fabs( val[r] ); for ( ; ; ) { while ( ( fabs( val(++i) ) > v ) ) { @@ -1104,26 +829,14 @@ DynCompRow :: qsortRowPartition(IntArray &ind, IntArray &ir, FloatArray &val, in break; } - swap = ir( ind(i) ); - ir( ind(i) ) = ir( ind(j) ); - ir( ind(j) ) = swap; - swap = ind(i); - ind(i) = ind(j); - ind(j) = swap; - dswap = val(i); - val(i) = val(j); - val(j) = dswap; + std::swap(ir[ ind[i] ], ir[ ind[j] ]); + std::swap(ind[i], ind[j]); + std::swap(val[i], val[j]); } - swap = ir( ind(i) ); - ir( ind(i) ) = ir( ind(r) ); - ir( ind(r) ) = swap; - swap = ind(i); - ind(i) = ind(r); - ind(r) = swap; - dswap = val(i); - val(i) = val(r); - val(r) = dswap; + std::swap(ir[ ind[i] ], ir[ ind[r] ]); + std::swap(ind[i], ind[r]); + std::swap(val[i], val[r]); return i; } diff --git a/src/oofemlib/iml/dyncomprow.h b/src/oofemlib/iml/dyncomprow.h index 8f5f1f933..1758a5f73 100644 --- a/src/oofemlib/iml/dyncomprow.h +++ b/src/oofemlib/iml/dyncomprow.h @@ -43,6 +43,8 @@ #include "sparsemtrx.h" #include "intarray.h" +#define _IFT_DynCompRow_Name "dcsr" + namespace oofem { // alloc chunk for columns #define DynCompRow_CHUNK 8 @@ -55,45 +57,43 @@ namespace oofem { class OOFEM_EXPORT DynCompRow : public SparseMtrx { protected: + /// data values per column + std::vector rows; + /// row_ind per column + std::vector colind; + /// pointers to the diagonal elements; needed only for ILU + IntArray diag; - FloatArray **rows_; // data values per column - IntArray **colind_; // row_ind per column - IntArray diag_rowptr_; // pointers to the diagonal elements; needed only for ILU - - int base_; // index base: offset of first element + /// index base: offset of first element + int base; public: /** Constructor. Before any operation an internal profile must be built. * @see builInternalStructure */ - DynCompRow(int n); - /** Constructor. Before any operation an internal profile must be built. - * @see builInternalStructure - */ - DynCompRow(); + DynCompRow(int n=0); /// Copy constructor DynCompRow(const DynCompRow & S); /// Assignment operator DynCompRow &operator = ( const DynCompRow & C ); /// Destructor - virtual ~DynCompRow(); - - // Overloaded methods: - SparseMtrx *GiveCopy() const; - virtual void times(const FloatArray &x, FloatArray &answer) const; - virtual void timesT(const FloatArray &x, FloatArray &answer) const; - virtual void times(double x); - virtual int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &); - virtual int assemble(const IntArray &loc, const FloatMatrix &mat); - virtual int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat); - virtual bool canBeFactorized() const { return false; } - virtual void zero(); - virtual const char* giveClassName() const { return "DynCompRow"; } - virtual SparseMtrxType giveType() const { return SMT_DynCompRow; } - virtual bool isAsymmetric() const { return true; } - virtual void printStatistics() const; - virtual double &at(int i, int j); - virtual double at(int i, int j) const; + virtual ~DynCompRow() {} + + std::unique_ptr clone() const override; + void times(const FloatArray &x, FloatArray &answer) const override; + void timesT(const FloatArray &x, FloatArray &answer) const override; + void times(double x) override; + int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &) override; + int assemble(const IntArray &loc, const FloatMatrix &mat) override; + int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) override; + bool canBeFactorized() const override { return false; } + void zero() override; + const char* giveClassName() const override { return "DynCompRow"; } + SparseMtrxType giveType() const override { return SMT_DynCompRow; } + bool isAsymmetric() const override { return true; } + void printStatistics() const override; + double &at(int i, int j) override; + double at(int i, int j) const override; /** * Performs LU factorization on yourself; modifies receiver @@ -107,9 +107,9 @@ class OOFEM_EXPORT DynCompRow : public SparseMtrx /* Access and info functions */ /*******************************/ /// Returns col index for i-th row - const IntArray *col_ind(int i) const { return colind_ [ i ]; } + const IntArray &col_ind(int i) const { return colind[ i ]; } /// Returns row values - const FloatArray *row(int i) const { return rows_ [ i ]; } + const FloatArray &row(int i) const { return rows[ i ]; } protected: diff --git a/src/oofemlib/iml/icprecond.C b/src/oofemlib/iml/icprecond.C index 1974edb91..94a8f00ef 100644 --- a/src/oofemlib/iml/icprecond.C +++ b/src/oofemlib/iml/icprecond.C @@ -39,68 +39,62 @@ CompCol_ICPreconditioner :: CompCol_ICPreconditioner(const SparseMtrx &A, InputR Preconditioner(A, attributes) { } -IRResultType -CompCol_ICPreconditioner :: initializeFrom(InputRecord *ir) + +void +CompCol_ICPreconditioner :: initializeFrom(InputRecord &ir) { - return Preconditioner :: initializeFrom(ir); + Preconditioner :: initializeFrom(ir); } + void CompCol_ICPreconditioner :: init(const SparseMtrx &A) { if ( dynamic_cast< const SymCompCol * >(&A) ) { - this->initialize( * ( ( SymCompCol * ) & A ) ); + this->initialize( static_cast< const SymCompCol & >(A) ); } else if ( dynamic_cast< const CompCol * >(&A) ) { - this->initialize( * ( ( CompCol * ) & A ) ); + this->initialize( static_cast< const CompCol & >(A) ); } else { OOFEM_ERROR("unsupported sparse matrix type"); } } - - void CompCol_ICPreconditioner :: initialize(const CompCol &A) { - dim_ [ 0 ] = A.dim(0); - dim_ [ 1 ] = A.dim(1); + dim [ 0 ] = A.giveNumberOfRows(); + dim [ 1 ] = A.giveNumberOfColumns(); - pntr_.resize(A.dim(1) + 1); + pntr.resize(dim [ 1 ] + 1); - - int i, j, k; - - nz_ = 0; - for ( k = 0; k < dim_ [ 1 ]; k++ ) { - for ( j = A.col_ptr(k); j < A.col_ptr(k + 1); j++ ) { + nz = 0; + for ( int k = 0; k < dim [ 1 ]; k++ ) { + for ( int j = A.col_ptr(k); j < A.col_ptr(k + 1); j++ ) { if ( A.row_ind(j) >= k ) { - nz_++; + nz++; } } } - val_.resize(nz_); - indx_.resize(nz_); + val.resize(nz); + indx.resize(nz); // Copy just triangular part - pntr_(0) = 0; - for ( k = 0; k < dim_ [ 1 ]; k++ ) { - pntr_(k + 1) = pntr_(k); - for ( j = A.col_ptr(k); j < A.col_ptr(k + 1); j++ ) { + pntr[0] = 0; + for ( int k = 0; k < dim [ 1 ]; k++ ) { + pntr[k + 1] = pntr[k]; + for ( int j = A.col_ptr(k); j < A.col_ptr(k + 1); j++ ) { if ( A.row_ind(j) >= k ) { - i = pntr_(k + 1)++; - val_(i) = A.val(j); - indx_(i) = A.row_ind(j); + int i = pntr[k + 1]++; + val[i] = A.values(j); + indx[i] = A.row_ind(j); } } } - // for (i = 0; i < dim_[1]; i++) - // qsortRow(indx_, val_, pntr_(i), pntr_(i+1) -1); - - for ( i = 0; i < dim_ [ 1 ]; i++ ) { - if ( indx_( pntr_(i) ) != i ) { + for ( int i = 0; i < dim [ 1 ]; i++ ) { + if ( indx[ pntr[i] ] != i ) { OOFEM_ERROR("diagonal not found!"); } } @@ -128,62 +122,60 @@ CompCol_ICPreconditioner :: trans_solve(const FloatArray &x, FloatArray &y) cons void CompCol_ICPreconditioner :: ICFactor() { - int d, g, h, i, j, k, n = pntr_.giveSize() - 1; - double z; - - for ( k = 0; k < n - 1; k++ ) { - d = pntr_(k); - z = val_(d) = sqrt( val_(d) ); - - for ( i = d + 1; i < pntr_(k + 1); i++ ) { - val_(i) /= z; + int n = pntr.giveSize() - 1; + + for ( int k = 0; k < n - 1; k++ ) { + int d = pntr[k]; + double z = val[d] = sqrt( val[d] ); + + for ( int i = d + 1; i < pntr[k + 1]; i++ ) { + val[i] /= z; } - for ( i = d + 1; i < pntr_(k + 1); i++ ) { - z = val_(i); - h = indx_(i); - g = i; + for ( int i = d + 1; i < pntr[k + 1]; i++ ) { + double z = val[i]; + int h = indx[i]; + int g = i; - for ( j = pntr_(h); j < pntr_(h + 1); j++ ) { - for ( ; g < pntr_(k + 1) && indx_(g + 1) <= indx_(j); g++ ) { - if ( indx_(g) == indx_(j) ) { - val_(j) -= z * val_(g); + for ( int j = pntr[h]; j < pntr[h + 1]; j++ ) { + for ( ; g < pntr[k + 1] && indx[g + 1] <= indx[j]; g++ ) { + if ( indx[g] == indx[j] ) { + val[j] -= z * val[g]; } } } } } - d = pntr_(n - 1); - val_(d) = sqrt( val_(d) ); + int d = pntr[n - 1]; + val[d] = sqrt( val[d] ); } void CompCol_ICPreconditioner :: ICSolve(FloatArray &dest) const { - int i, t, M = dest.giveSize(); + int M = dest.giveSize(); FloatArray work(M); - double val; // lower diag - work.zero(); // solve Uw=x - for ( i = 0; i < M; i++ ) { - work(i) = val = ( dest(i) + work(i) ) / val_( pntr_(i) ); - for ( t = pntr_(i) + 1; t < pntr_(i + 1); t++ ) { - work( indx_(t) ) -= val_(t) * val; + for ( int i = 0; i < M; i++ ) { + double temp; + work[i] = temp = ( dest[i] + work[i] ) / val[ pntr[i] ]; + for ( int t = pntr[i] + 1; t < pntr[i + 1]; t++ ) { + work[ indx[t] ] -= val[t] * temp; } } dest.zero(); // solve U^Ty=w - for ( i = M - 1; i >= 0; i-- ) { - for ( t = pntr_(i) + 1; t < pntr_(i + 1); t++ ) { - dest(i) -= val_(t) * dest( indx_(t) ); + for ( int i = M - 1; i >= 0; i-- ) { + for ( int t = pntr[i] + 1; t < pntr[i + 1]; t++ ) { + dest[i] -= val[t] * dest( indx[t] ); } - dest(i) = ( work(i) + dest(i) ) / val_( pntr_(i) ); + dest[i] = ( work[i] + dest[i] ) / val[ pntr[i] ]; } } @@ -205,16 +197,14 @@ int CompCol_ICPreconditioner :: qsortRowPartition(IntArray &src, FloatArray &val, int l, int r) { int i = l - 1, j = r; - int v = src(r); - int swap; - double dswap; + int v = src[r]; for ( ; ; ) { - while ( ( src(++i) < v ) ) { + while ( ( src[++i] < v ) ) { ; } - while ( ( v < src(--j) ) ) { + while ( ( v < src[--j] ) ) { if ( j == l ) { break; } @@ -224,20 +214,12 @@ CompCol_ICPreconditioner :: qsortRowPartition(IntArray &src, FloatArray &val, in break; } - swap = src(i); - src(i) = src(j); - src(j) = swap; - dswap = val(i); - val(i) = val(j); - val(j) = dswap; + std::swap(src[i], src[j]); + std::swap(val[i], val[j]); } - swap = src(i); - src(i) = src(r); - src(r) = swap; - dswap = val(i); - val(i) = val(r); - val(r) = dswap; + std::swap(src[i], src[r]); + std::swap(val[i], val[r]); return i; } diff --git a/src/oofemlib/iml/icprecond.h b/src/oofemlib/iml/icprecond.h index 87ae1ae83..69b11eb41 100644 --- a/src/oofemlib/iml/icprecond.h +++ b/src/oofemlib/iml/icprecond.h @@ -44,11 +44,11 @@ namespace oofem { class OOFEM_EXPORT CompCol_ICPreconditioner : public Preconditioner { private: - FloatArray val_; - IntArray pntr_; - IntArray indx_; - int nz_; - int dim_ [ 2 ]; + FloatArray val; + IntArray pntr; + IntArray indx; + int nz; + int dim [ 2 ]; public: /// Constructor. Initializes the the receiver (constructs the precontioning matrix M) of given matrix. @@ -58,15 +58,15 @@ class OOFEM_EXPORT CompCol_ICPreconditioner : public Preconditioner /// Destructor. virtual ~CompCol_ICPreconditioner(void) { } - virtual void init(const SparseMtrx &a); + void init(const SparseMtrx &a) override; void initialize(const CompCol &A); - void solve(const FloatArray &rhs, FloatArray &solution) const; - void trans_solve(const FloatArray &rhs, FloatArray &solution) const; + void solve(const FloatArray &rhs, FloatArray &solution) const override; + void trans_solve(const FloatArray &rhs, FloatArray &solution) const override; - virtual const char *giveClassName() const { return "ICP"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "ICP"; } + void initializeFrom(InputRecord &ir) override; protected: void qsortRow(IntArray &, FloatArray &, int l, int r); diff --git a/src/oofemlib/iml/ilucomprowprecond.C b/src/oofemlib/iml/ilucomprowprecond.C index a3bf3e74b..439a60e31 100644 --- a/src/oofemlib/iml/ilucomprowprecond.C +++ b/src/oofemlib/iml/ilucomprowprecond.C @@ -41,18 +41,15 @@ CompRow_ILUPreconditioner :: CompRow_ILUPreconditioner(const SparseMtrx &A, InputRecord &attributes) : Preconditioner(A, attributes) { } -IRResultType -CompRow_ILUPreconditioner :: initializeFrom(InputRecord *ir) +void +CompRow_ILUPreconditioner :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - + Preconditioner :: initializeFrom(ir); this->drop_tol = 1.e-8; IR_GIVE_OPTIONAL_FIELD(ir, this->drop_tol, _IFT_CompRow_ILUPrecond_droptol); part_fill = 5; IR_GIVE_OPTIONAL_FIELD(ir, part_fill, _IFT_CompRow_ILUPrecond_partfill); - - return Preconditioner :: initializeFrom(ir); } @@ -60,13 +57,14 @@ void CompRow_ILUPreconditioner :: init(const SparseMtrx &A) { if ( dynamic_cast< const DynCompRow *>(& A) ) { - this->A = ( * ( ( DynCompRow * ) & A ) ); - ( this->A ).ILUPYourself(part_fill, drop_tol); + this->A = static_cast< const DynCompRow &>(A); + this->A.ILUPYourself(part_fill, drop_tol); } else { OOFEM_ERROR("unsupported sparse matrix type"); } } + void CompRow_ILUPreconditioner :: solve(const FloatArray &x, FloatArray &y) const { diff --git a/src/oofemlib/iml/ilucomprowprecond.h b/src/oofemlib/iml/ilucomprowprecond.h index 2d3be3f8d..a67b18d68 100644 --- a/src/oofemlib/iml/ilucomprowprecond.h +++ b/src/oofemlib/iml/ilucomprowprecond.h @@ -68,25 +68,16 @@ class OOFEM_EXPORT CompRow_ILUPreconditioner : public Preconditioner /// Destructor virtual ~CompRow_ILUPreconditioner(void) { } - /** - * Initializes the receiver (constructs the precontioning matrix M) of given matrix. - * @param a Sparse matrix to be preconditioned - */ - virtual void init(const SparseMtrx &a); + void init(const SparseMtrx &a) override; //void initialize (const CompCol &A); void initialize(const DynCompRow &A); - /// Solves the linear system - virtual void solve(const FloatArray &x, FloatArray &y) const; - /// Solves transposed system - virtual void trans_solve(const FloatArray &x, FloatArray &y) const; - - /// returns the preconditioner name - virtual const char *giveClassName() const { return "ILUT"; } - /// Initializes receiver from given record. Empty implementation. - virtual IRResultType initializeFrom(InputRecord *ir); + void solve(const FloatArray &x, FloatArray &y) const override; + void trans_solve(const FloatArray &x, FloatArray &y) const override; + const char *giveClassName() const override { return "ILUT"; } + void initializeFrom(InputRecord &ir) override; protected: void qsortCol(IntArray &, FloatArray &, int l, int r); diff --git a/src/oofemlib/iml/iluprecond.C b/src/oofemlib/iml/iluprecond.C index 7bc597453..5dbfe8a75 100644 --- a/src/oofemlib/iml/iluprecond.C +++ b/src/oofemlib/iml/iluprecond.C @@ -38,19 +38,15 @@ #include "timer.h" #endif -#ifdef DynCompCol_USE_STL_SETS - #include -#endif - namespace oofem { CompCol_ILUPreconditioner :: CompCol_ILUPreconditioner(const SparseMtrx &A, InputRecord &attributes) : Preconditioner(A, attributes) { } -IRResultType -CompCol_ILUPreconditioner :: initializeFrom(InputRecord *ir) +void +CompCol_ILUPreconditioner :: initializeFrom(InputRecord &ir) { - return Preconditioner :: initializeFrom(ir); + Preconditioner :: initializeFrom(ir); } @@ -63,9 +59,9 @@ CompCol_ILUPreconditioner :: init(const SparseMtrx &A) #endif if ( dynamic_cast< const CompCol * >(&A) ) { - this->initialize( * ( ( CompCol * ) & A ) ); + this->initialize( static_cast< const CompCol & >(A) ); } else if ( dynamic_cast< const DynCompCol * >(&A) ) { - this->initialize( * ( ( DynCompCol * ) & A ) ); + this->initialize( static_cast< const DynCompCol & >(A) ); } else { OOFEM_ERROR("unsupported sparse matrix type"); } @@ -80,92 +76,90 @@ CompCol_ILUPreconditioner :: init(const SparseMtrx &A) void CompCol_ILUPreconditioner :: initialize(const CompCol &A) { - int i, j, k, pn, qn, rn; - double multiplier; + int pn, qn, rn; // Copy - dim_ [ 0 ] = A.giveNumberOfRows(); - dim_ [ 1 ] = A.giveNumberOfColumns(); + dim [ 0 ] = A.giveNumberOfRows(); + dim [ 1 ] = A.giveNumberOfColumns(); - l_colptr_.resize(A.dim(1) + 1); - u_colptr_.resize(A.dim(1) + 1); + l_colptr.resize(dim [ 1 ] + 1); + u_colptr.resize(dim [ 1 ] + 1); - l_nz_ = 0; - u_nz_ = 0; + l_nz = 0; + u_nz = 0; // Get size of l and u - for ( i = 0; i < dim_ [ 1 ]; i++ ) { - for ( j = A.col_ptr(i); j < A.col_ptr(i + 1); j++ ) { + for ( int i = 0; i < dim [ 1 ]; i++ ) { + for ( int j = A.col_ptr(i); j < A.col_ptr(i + 1); j++ ) { if ( A.row_ind(j) > i ) { - l_nz_++; + l_nz++; } else { - u_nz_++; + u_nz++; } } } - l_val_.resize(l_nz_); - u_val_.resize(u_nz_); - l_rowind_.resize(l_nz_); - u_rowind_.resize(u_nz_); + l_val.resize(l_nz); + u_val.resize(u_nz); + l_rowind.resize(l_nz); + u_rowind.resize(u_nz); - l_colptr_(0) = u_colptr_(0) = 0; + l_colptr[0] = u_colptr[0] = 0; // Split up A into l and u - for ( i = 0; i < dim_ [ 1 ]; i++ ) { - l_colptr_(i + 1) = l_colptr_(i); - u_colptr_(i + 1) = u_colptr_(i); + for ( int i = 0; i < dim [ 1 ]; i++ ) { + l_colptr[i + 1] = l_colptr[i]; + u_colptr[i + 1] = u_colptr[i]; - for ( j = A.col_ptr(i); j < A.col_ptr(i + 1); j++ ) { + for ( int j = A.col_ptr(i); j < A.col_ptr(i + 1); j++ ) { if ( A.row_ind(j) > i ) { - k = l_colptr_(i + 1)++; - l_val_(k) = A.val(j); - l_rowind_(k) = A.row_ind(j); + int k = l_colptr[i + 1]++; + l_val[k] = A.values(j); + l_rowind[k] = A.row_ind(j); } else if ( A.row_ind(j) <= i ) { - k = u_colptr_(i + 1)++; - u_val_(k) = A.val(j); - u_rowind_(k) = A.row_ind(j); + int k = u_colptr[i + 1]++; + u_val[k] = A.values(j); + u_rowind[k] = A.row_ind(j); } } } /* sort entries to assure entries stored with increasing row index */ /* - * for (i = 0; i < dim_[1]; i++) { - * QSort(l_rowind_, l_val_, l_colptr_[i], l_colptr_[i+1] - l_colptr_[i]); - * QSort(u_rowind_, u_val_, u_colptr_[i], u_colptr_[i+1] - u_colptr_[i]); + * for (i = 0; i < dim[1]; i++) { + * QSort(l_rowind_, l_val_, l_colptr[i], l_colptr[i+1] - l_colptr[i]); + * QSort(u_rowind_, u_val_, u_colptr[i], u_colptr[i+1] - u_colptr[i]); * } */ // Factor matrix - for ( i = 0; i < dim_ [ 0 ] - 1; i++ ) { - multiplier = u_val_(u_colptr_(i + 1) - 1); + for ( int i = 0; i < dim [ 0 ] - 1; i++ ) { + double multiplier = u_val[u_colptr[i + 1] - 1]; - for ( j = l_colptr_(i); j < l_colptr_(i + 1); j++ ) { - l_val_(j) /= multiplier; + for ( int j = l_colptr[i]; j < l_colptr[i + 1]; j++ ) { + l_val[j] /= multiplier; } - for ( j = u_colptr_(i + 1); j < u_colptr_(i + 2) - 1; j++ ) { - multiplier = u_val_(j); + for ( int j = u_colptr[i + 1]; j < u_colptr[i + 2] - 1; j++ ) { + multiplier = u_val[j]; qn = j + 1; - rn = l_colptr_(i + 1); - for ( pn = l_colptr_( u_rowind_(j) ); - pn < l_colptr_(u_rowind_(j) + 1) && l_rowind_(pn) <= i + 1; pn++ ) { - while ( qn < u_colptr_(i + 2) && u_rowind_(qn) < l_rowind_(pn) ) { + rn = l_colptr[i + 1]; + for ( pn = l_colptr[ u_rowind[j] ]; pn < l_colptr[u_rowind[j] + 1] && l_rowind[pn] <= i + 1; pn++ ) { + while ( qn < u_colptr[i + 2] && u_rowind[qn] < l_rowind[pn] ) { qn++; } - if ( qn < u_colptr_(i + 2) && l_rowind_(pn) == u_rowind_(qn) ) { - u_val_(qn) -= multiplier * l_val_(pn); + if ( qn < u_colptr[i + 2] && l_rowind[pn] == u_rowind[qn] ) { + u_val[qn] -= multiplier * l_val[pn]; } } - for ( ; pn < l_colptr_(u_rowind_(j) + 1); pn++ ) { - while ( rn < l_colptr_(i + 2) && l_rowind_(rn) < l_rowind_(pn) ) { + for ( ; pn < l_colptr[u_rowind[j] + 1]; pn++ ) { + while ( rn < l_colptr[i + 2] && l_rowind[rn] < l_rowind[pn] ) { rn++; } - if ( rn < l_colptr_(i + 2) && l_rowind_(pn) == l_rowind_(rn) ) { - l_val_(rn) -= multiplier * l_val_(pn); + if ( rn < l_colptr[i + 2] && l_rowind[pn] == l_rowind[rn] ) { + l_val[rn] -= multiplier * l_val[pn]; } } } @@ -176,131 +170,90 @@ CompCol_ILUPreconditioner :: initialize(const CompCol &A) void CompCol_ILUPreconditioner :: initialize(const DynCompCol &A) { - int i, j, k, pn, qn, rn; - double multiplier; + int pn, qn, rn; // Copy - dim_ [ 0 ] = A.giveNumberOfRows(); - dim_ [ 1 ] = A.giveNumberOfColumns(); + dim [ 0 ] = A.giveNumberOfRows(); + dim [ 1 ] = A.giveNumberOfColumns(); - l_colptr_.resize(A.giveNumberOfColumns() + 1); - u_colptr_.resize(A.giveNumberOfColumns() + 1); + l_colptr.resize(A.giveNumberOfColumns() + 1); + u_colptr.resize(A.giveNumberOfColumns() + 1); - l_nz_ = 0; - u_nz_ = 0; + l_nz = 0; + u_nz = 0; -#ifndef DynCompCol_USE_STL_SETS // Get size of l and u - for ( i = 0; i < dim_ [ 1 ]; i++ ) { - for ( j = 0; j < A.row_ind(i)->giveSize(); j++ ) { - if ( A.row_ind(i)->at(j + 1) > i ) { - l_nz_++; + for ( int i = 0; i < dim [ 1 ]; i++ ) { + for ( int j = 0; j < A.row_ind(i).giveSize(); j++ ) { + if ( A.row_ind(i).at(j + 1) > i ) { + l_nz++; } else { - u_nz_++; + u_nz++; } } } - l_val_.resize(l_nz_); - u_val_.resize(u_nz_); - l_rowind_.resize(l_nz_); - u_rowind_.resize(u_nz_); + l_val.resize(l_nz); + u_val.resize(u_nz); + l_rowind.resize(l_nz); + u_rowind.resize(u_nz); - l_colptr_(0) = u_colptr_(0) = 0; + l_colptr[0] = u_colptr[0] = 0; // Split up A into l and u - for ( i = 0; i < dim_ [ 1 ]; i++ ) { - l_colptr_(i + 1) = l_colptr_(i); - u_colptr_(i + 1) = u_colptr_(i); - - for ( j = 0; j < A.row_ind(i)->giveSize(); j++ ) { - if ( A.row_ind(i)->at(j + 1) > i ) { - k = l_colptr_(i + 1)++; - l_val_(k) = A.column(i)->at(j + 1); - l_rowind_(k) = A.row_ind(i)->at(j + 1); - } else if ( A.row_ind(i)->at(j + 1) <= i ) { - k = u_colptr_(i + 1)++; - u_val_(k) = A.column(i)->at(j + 1); - u_rowind_(k) = A.row_ind(i)->at(j + 1); - } - } - } - -#else - // Get size of l and u - for ( i = 0; i < dim_ [ 1 ]; i++ ) { - for ( auto &val: A.column(i) ) { - if ( val.first > i ) { - l_nz_++; - } else { - u_nz_++; + for ( int i = 0; i < dim [ 1 ]; i++ ) { + l_colptr[i + 1] = l_colptr[i]; + u_colptr[i + 1] = u_colptr[i]; + + for ( int j = 0; j < A.row_ind(i).giveSize(); j++ ) { + if ( A.row_ind(i).at(j + 1) > i ) { + int k = l_colptr[i + 1]++; + l_val[k] = A.column(i).at(j + 1); + l_rowind[k] = A.row_ind(i).at(j + 1); + } else if ( A.row_ind(i).at(j + 1) <= i ) { + int k = u_colptr[i + 1]++; + u_val[k] = A.column(i).at(j + 1); + u_rowind[k] = A.row_ind(i).at(j + 1); } } } - l_val_.resize(l_nz_); - u_val_.resize(u_nz_); - l_rowind_.resize(l_nz_); - u_rowind_.resize(u_nz_); - - l_colptr_(0) = u_colptr_(0) = 0; - - // Split up A into l and u - for ( i = 0; i < dim_ [ 1 ]; i++ ) { - l_colptr_(i + 1) = l_colptr_(i); - u_colptr_(i + 1) = u_colptr_(i); - - for ( auto &val: A.column(i) ) { - if ( val.first > i ) { - k = l_colptr_(i + 1)++; - l_val_(k) = val.second; - l_rowind_(k) = val.first; - } else if ( val.first <= i ) { - k = u_colptr_(i + 1)++; - u_val_(k) = val.second; - u_rowind_(k) = val.first; - } - } - } - -#endif /* sort entries to assure entries stored with increasing row index */ - for ( i = 0; i < dim_ [ 1 ]; i++ ) { - qsortRow(l_rowind_, l_val_, l_colptr_(i), l_colptr_(i + 1) - 1); - qsortRow(u_rowind_, u_val_, u_colptr_(i), u_colptr_(i + 1) - 1); + for ( int i = 0; i < dim [ 1 ]; i++ ) { + qsortRow(l_rowind, l_val, l_colptr[i], l_colptr[i + 1] - 1); + qsortRow(u_rowind, u_val, u_colptr[i], u_colptr[i + 1] - 1); } // Factor matrix - for ( i = 0; i < dim_ [ 0 ] - 1; i++ ) { - multiplier = u_val_(u_colptr_(i + 1) - 1); + for ( int i = 0; i < dim [ 0 ] - 1; i++ ) { + double multiplier = u_val[u_colptr[i + 1] - 1]; - for ( j = l_colptr_(i); j < l_colptr_(i + 1); j++ ) { - l_val_(j) /= multiplier; + for ( int j = l_colptr[i]; j < l_colptr[i + 1]; j++ ) { + l_val[j] /= multiplier; } - for ( j = u_colptr_(i + 1); j < u_colptr_(i + 2) - 1; j++ ) { - multiplier = u_val_(j); + for ( int j = u_colptr[i + 1]; j < u_colptr[i + 2] - 1; j++ ) { + multiplier = u_val[j]; qn = j + 1; - rn = l_colptr_(i + 1); - for ( pn = l_colptr_( u_rowind_(j) ); - pn < l_colptr_(u_rowind_(j) + 1) && l_rowind_(pn) <= i + 1; pn++ ) { - while ( qn < u_colptr_(i + 2) && u_rowind_(qn) < l_rowind_(pn) ) { + rn = l_colptr[i + 1]; + for ( pn = l_colptr[ u_rowind[j] ]; pn < l_colptr[u_rowind[j] + 1] && l_rowind[pn] <= i + 1; pn++ ) { + while ( qn < u_colptr[i + 2] && u_rowind[qn] < l_rowind[pn] ) { qn++; } - if ( qn < u_colptr_(i + 2) && l_rowind_(pn) == u_rowind_(qn) ) { - u_val_(qn) -= multiplier * l_val_(pn); + if ( qn < u_colptr[i + 2] && l_rowind[pn] == u_rowind[qn] ) { + u_val[qn] -= multiplier * l_val[pn]; } } - for ( ; pn < l_colptr_(u_rowind_(j) + 1); pn++ ) { - while ( rn < l_colptr_(i + 2) && l_rowind_(rn) < l_rowind_(pn) ) { + for ( ; pn < l_colptr[u_rowind[j] + 1]; pn++ ) { + while ( rn < l_colptr[i + 2] && l_rowind[rn] < l_rowind[pn] ) { rn++; } - if ( rn < l_colptr_(i + 2) && l_rowind_(pn) == l_rowind_(rn) ) { - l_val_(rn) -= multiplier * l_val_(pn); + if ( rn < l_colptr[i + 2] && l_rowind[pn] == l_rowind[rn] ) { + l_val[rn] -= multiplier * l_val[pn]; } } } @@ -314,28 +267,24 @@ CompCol_ILUPreconditioner :: solve(const FloatArray &x, FloatArray &y) const int M = x.giveSize(); FloatArray work(M); - int i, t; - y.resize(M); - work.zero(); + // solve Lw=x - for ( i = 0; i < M; i++ ) { - work(i) = x(i) + work(i); - for ( t = l_colptr_(i); t < l_colptr_(i + 1); t++ ) { - work( l_rowind_(t) ) -= l_val_(t) * work(i); + for ( int i = 0; i < M; i++ ) { + work[i] += x[i]; + for ( int t = l_colptr[i]; t < l_colptr[i + 1]; t++ ) { + work[ l_rowind[t] ] -= l_val[t] * work[i]; } } y.zero(); // solve Uy=w - for ( i = M - 1; i >= 0; i-- ) { - y(i) = ( work(i) ) / u_val_(u_colptr_(i + 1) - 1); - for ( t = u_colptr_(i); t < u_colptr_(i + 1) - 1; t++ ) { - work( u_rowind_(t) ) -= u_val_(t) * y(i); + for ( int i = M - 1; i >= 0; i-- ) { + y[i] = ( work[i] ) / u_val[u_colptr[i + 1] - 1]; + for ( int t = u_colptr[i]; t < u_colptr[i + 1] - 1; t++ ) { + work[ u_rowind[t] ] -= u_val[t] * y[i]; } } - - //return y; } @@ -345,33 +294,28 @@ CompCol_ILUPreconditioner :: trans_solve(const FloatArray &x, FloatArray &y) con int M = x.giveSize(); FloatArray work(M); - int i, t; - double val; - y.resize(M); - //work.zero(); + // solve for U^Tw = x - for ( i = 0; i < M; i++ ) { - val = 0.0; - for ( t = u_colptr_(i); t < u_colptr_(i + 1) - 1; t++ ) { - val += u_val_(t) * x( u_rowind_(t) ); + for ( int i = 0; i < M; i++ ) { + double val = 0.0; + for ( int t = u_colptr[i]; t < u_colptr[i + 1] - 1; t++ ) { + val += u_val[t] * x[ u_rowind[t] ]; } - work(i) = ( x(i) - val ) / u_val_(u_colptr_(i + 1) - 1); + work[i] = ( x[i] - val ) / u_val[u_colptr[i + 1] - 1]; } // solve for L^T y = w - for ( i = M - 1; i >= 0; i-- ) { - val = 0.0; - for ( t = l_colptr_(i); t < l_colptr_(i + 1); t++ ) { - val += l_val_(t) * work( l_rowind_(t) ); + for ( int i = M - 1; i >= 0; i-- ) { + double val = 0.0; + for ( int t = l_colptr[i]; t < l_colptr[i + 1]; t++ ) { + val += l_val[t] * work( l_rowind[t] ); } - y.at(i) = work(i) - val; + y[i] = work[i] - val; } - - //return y; } @@ -392,16 +336,14 @@ int CompCol_ILUPreconditioner :: qsortRowPartition(IntArray &src, FloatArray &val, int l, int r) { int i = l - 1, j = r; - int v = src(r); - int swap; - double dswap; + int v = src[r]; for ( ; ; ) { - while ( ( src(++i) < v ) ) { + while ( ( src[++i] < v ) ) { ; } - while ( ( v < src(--j) ) ) { + while ( ( v < src[--j] ) ) { if ( j == l ) { break; } @@ -411,20 +353,12 @@ CompCol_ILUPreconditioner :: qsortRowPartition(IntArray &src, FloatArray &val, i break; } - swap = src(i); - src(i) = src(j); - src(j) = swap; - dswap = val(i); - val(i) = val(j); - val(j) = dswap; + std::swap(src[i], src[j]); + std::swap(val[i], val[j]); } - swap = src(i); - src(i) = src(r); - src(r) = swap; - dswap = val(i); - val(i) = val(r); - val(r) = dswap; + std::swap(src[i], src[r]); + std::swap(val[i], val[r]); return i; } diff --git a/src/oofemlib/iml/iluprecond.h b/src/oofemlib/iml/iluprecond.h index 820032d6b..67ceff7af 100644 --- a/src/oofemlib/iml/iluprecond.h +++ b/src/oofemlib/iml/iluprecond.h @@ -45,17 +45,17 @@ namespace oofem { class OOFEM_EXPORT CompCol_ILUPreconditioner : public Preconditioner { private: - FloatArray l_val_; - IntArray l_colptr_; - IntArray l_rowind_; - int l_nz_; + FloatArray l_val; + IntArray l_colptr; + IntArray l_rowind; + int l_nz; - FloatArray u_val_; - IntArray u_colptr_; - IntArray u_rowind_; - int u_nz_; + FloatArray u_val; + IntArray u_colptr; + IntArray u_rowind; + int u_nz; - int dim_ [ 2 ]; + int dim [ 2 ]; public: /// Constructor. Initializes the the receiver (constructs the precontioning matrix M) of given matrix. @@ -65,16 +65,16 @@ class OOFEM_EXPORT CompCol_ILUPreconditioner : public Preconditioner /// Destructor virtual ~CompCol_ILUPreconditioner(void) { } - virtual void init(const SparseMtrx &); + void init(const SparseMtrx &) override; void initialize(const CompCol &A); void initialize(const DynCompCol &A); - void solve(const FloatArray &x, FloatArray &y) const; - void trans_solve(const FloatArray &x, FloatArray &y) const; + void solve(const FloatArray &x, FloatArray &y) const override; + void trans_solve(const FloatArray &x, FloatArray &y) const override; - virtual const char *giveClassName() const { return "ILU"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "ILU"; } + void initializeFrom(InputRecord &ir) override; protected: void qsortRow(IntArray &, FloatArray &, int l, int r); diff --git a/src/oofemlib/iml/imlsolver.C b/src/oofemlib/iml/imlsolver.C index 3e897a700..b8909c6ef 100644 --- a/src/oofemlib/iml/imlsolver.C +++ b/src/oofemlib/iml/imlsolver.C @@ -55,29 +55,18 @@ namespace oofem { REGISTER_SparseLinSolver(IMLSolver, ST_IML) -IMLSolver :: IMLSolver(Domain *d, EngngModel *m) : SparseLinearSystemNM(d, m) -{ - Lhs = NULL; - M = NULL; - solverType = IML_ST_CG; - precondType = IML_VoidPrec; - precondInit = true; -} - +IMLSolver :: IMLSolver(Domain *d, EngngModel *m) : SparseLinearSystemNM(d, m), + lhs(nullptr), + solverType(IML_ST_CG), + precondType(IML_VoidPrec), + precondInit(true) +{} -IMLSolver :: ~IMLSolver() -{ - delete M; -} -IRResultType -IMLSolver :: initializeFrom(InputRecord *ir) +void +IMLSolver :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - int val; - - val = 0; + int val = 0; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_IMLSolver_stype); solverType = ( IMLSolverType ) val; @@ -91,18 +80,17 @@ IMLSolver :: initializeFrom(InputRecord *ir) // create preconditioner if ( precondType == IML_DiagPrec ) { - M = new DiagPreconditioner(); + M = std::make_unique(); } else if ( precondType == IML_VoidPrec ) { - M = new VoidPreconditioner(); + M = std::make_unique(); } else if ( precondType == IML_ILU_CompRowPrec ) { - M = new CompRow_ILUPreconditioner(); + M = std::make_unique(); } else if ( precondType == IML_ILU_CompColPrec ) { - M = new CompCol_ILUPreconditioner(); + M = std::make_unique(); } else if ( precondType == IML_ICPrec ) { - M = new CompCol_ICPreconditioner(); + M = std::make_unique(); } else { - OOFEM_WARNING("unknown preconditioner type"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IMLSolver_lsprecond, "unknown preconditioner type"); } // initialize precond attributes @@ -119,17 +107,16 @@ IMLSolver :: solve(SparseMtrx &A, FloatArray &b, FloatArray &x) OOFEM_ERROR("size mismatch"); } - // check preconditioner if ( M ) { - if ( ( precondInit ) || ( Lhs != &A ) || ( this->lhsVersion != A.giveVersion() ) ) { + if ( precondInit || lhs != &A || this->lhsVersion != A.giveVersion() ) { M->init(A); } } else { OOFEM_ERROR("preconditioner creation error"); } - Lhs = &A; + lhs = &A; this->lhsVersion = A.giveVersion(); #ifdef TIME_REPORT @@ -137,17 +124,15 @@ IMLSolver :: solve(SparseMtrx &A, FloatArray &b, FloatArray &x) timer.startTimer(); #endif - + int mi = this->maxite; + double t = this->tol; if ( solverType == IML_ST_CG ) { - int mi = this->maxite; - double t = this->tol; - result = CG(* Lhs, x, b, * M, mi, t); + result = CG(* lhs, x, b, * M, mi, t); OOFEM_LOG_INFO("CG(%s): flag=%d, nite %d, achieved tol. %g\n", M->giveClassName(), result, mi, t); } else if ( solverType == IML_ST_GMRES ) { - int mi = this->maxite, restart = 100; - double t = this->tol; + int restart = 100; FloatMatrix H(restart + 1, restart); // storage for upper Hesenberg - result = GMRES(* Lhs, x, b, * M, H, restart, mi, t); + result = GMRES(* lhs, x, b, * M, H, restart, mi, t); OOFEM_LOG_INFO("GMRES(%s): flag=%d, nite %d, achieved tol. %g\n", M->giveClassName(), result, mi, t); } else { OOFEM_ERROR("unknown lsover type"); @@ -158,8 +143,6 @@ IMLSolver :: solve(SparseMtrx &A, FloatArray &b, FloatArray &x) OOFEM_LOG_INFO( "IMLSolver info: user time consumed by solution: %.2fs\n", timer.getUtime() ); #endif - - //solved = 1; return NM_Success; } } // end namespace oofem diff --git a/src/oofemlib/iml/imlsolver.h b/src/oofemlib/iml/imlsolver.h index fecba77d9..7b426938d 100644 --- a/src/oofemlib/iml/imlsolver.h +++ b/src/oofemlib/iml/imlsolver.h @@ -40,8 +40,11 @@ #include "floatarray.h" #include "precond.h" +#include + ///@name Input fields for IMLSolver //@{ +#define _IFT_IMLSolver_Name "iml" #define _IFT_IMLSolver_stype "stype" #define _IFT_IMLSolver_lstol "lstol" #define _IFT_IMLSolver_lsiter "lsiter" @@ -66,11 +69,11 @@ class OOFEM_EXPORT IMLSolver : public SparseLinearSystemNM enum IMLPrecondType { IML_VoidPrec, IML_DiagPrec, IML_ILU_CompColPrec, IML_ILU_CompRowPrec, IML_ICPrec }; /// Last mapped Lhs matrix - SparseMtrx *Lhs; + SparseMtrx *lhs; /// Last mapped matrix version SparseMtrx :: SparseMtrxVersionType lhsVersion; /// Preconditioner. - Preconditioner *M; + std::unique_ptr M; /// IML Solver type. IMLSolverType solverType; /// IML Preconditioner type. @@ -85,26 +88,18 @@ class OOFEM_EXPORT IMLSolver : public SparseLinearSystemNM /// Max number of iterations. int maxite; - public: /// Constructor. Creates new instance of LDLTFactorization, with number i, belonging to domain d and Engngmodel m. IMLSolver(Domain * d, EngngModel * m); /// Destructor - virtual ~IMLSolver(); + virtual ~IMLSolver() {} - /** - * Solves the given linear system iteratively by method described by IMLSolverType. - * @param A Coefficient matrix. - * @param b Right hand side. - * @param x Solution array. - * @return Status value. - */ - virtual NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x); + NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "IMLSolver"; } - virtual LinSystSolverType giveLinSystSolverType() const { return ST_IML; } - virtual SparseMtrxType giveRecommendedMatrix(bool symmetric) const { return symmetric ? SMT_SymCompCol : SMT_CompCol; } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "IMLSolver"; } + LinSystSolverType giveLinSystSolverType() const override { return ST_IML; } + SparseMtrxType giveRecommendedMatrix(bool symmetric) const override { return symmetric ? SMT_SymCompCol : SMT_CompCol; } }; } // end namespace oofem #endif // imlsolver_h diff --git a/src/oofemlib/iml/precond.C b/src/oofemlib/iml/precond.C index 608ca4a6d..f01ab4b18 100644 --- a/src/oofemlib/iml/precond.C +++ b/src/oofemlib/iml/precond.C @@ -37,7 +37,7 @@ namespace oofem { Preconditioner :: Preconditioner(const SparseMtrx &a, InputRecord &attributes) { - this->initializeFrom(& attributes); + this->initializeFrom(attributes); this->init(a); }; } // end namespace oofem diff --git a/src/oofemlib/iml/precond.h b/src/oofemlib/iml/precond.h index 5847820b2..b42b6ae09 100644 --- a/src/oofemlib/iml/precond.h +++ b/src/oofemlib/iml/precond.h @@ -112,7 +112,7 @@ class OOFEM_EXPORT Preconditioner /// Returns the preconditioner name. virtual const char *giveClassName() const { return "Preconditioner"; } /// Initializes receiver from given record. Empty implementation. - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + virtual void initializeFrom(InputRecord &ir) { } }; } // end namespace oofem #endif // precond_h diff --git a/src/oofemlib/iml/voidprecond.h b/src/oofemlib/iml/voidprecond.h index f2fee7d7c..fb1dd289b 100644 --- a/src/oofemlib/iml/voidprecond.h +++ b/src/oofemlib/iml/voidprecond.h @@ -45,8 +45,6 @@ namespace oofem { */ class OOFEM_EXPORT VoidPreconditioner : public Preconditioner { -private: - public: /// Constructor. Creates the empty preconditioner. VoidPreconditioner(const SparseMtrx & a, InputRecord & attributes); @@ -55,11 +53,11 @@ class OOFEM_EXPORT VoidPreconditioner : public Preconditioner /// Destructor virtual ~VoidPreconditioner(void) { } - void init(const SparseMtrx &a) { } - void solve(const FloatArray &rhs, FloatArray &solution) const { solution = rhs; } - void trans_solve(const FloatArray &rhs, FloatArray &solution) const { solution = rhs; } + void init(const SparseMtrx &a) override { } + void solve(const FloatArray &rhs, FloatArray &solution) const override { solution = rhs; } + void trans_solve(const FloatArray &rhs, FloatArray &solution) const override { solution = rhs; } - virtual const char *giveClassName() const { return "VoidPreconditioner"; } + const char *giveClassName() const override { return "VoidPreconditioner"; } }; } // end namespace oofem #endif // voidprecond_h diff --git a/src/oofemlib/initialcondition.C b/src/oofemlib/initialcondition.C index a89542088..6ca3ab374 100644 --- a/src/oofemlib/initialcondition.C +++ b/src/oofemlib/initialcondition.C @@ -74,13 +74,11 @@ void InitialCondition :: printYourself() } -IRResultType -InitialCondition :: initializeFrom(InputRecord *ir) +void +InitialCondition :: initializeFrom(InputRecord &ir) // Sets up the dictionary where the receiver stores the conditions it // imposes. { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, initialValueDictionary, _IFT_InitialCondition_conditions); int val = 0; @@ -92,8 +90,6 @@ InitialCondition :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, this->set, _IFT_InitialCondition_set); this->dofIDs.clear(); IR_GIVE_OPTIONAL_FIELD(ir, this->dofIDs, _IFT_InitialCondition_dofs); - - return IRRT_OK; } diff --git a/src/oofemlib/initialcondition.h b/src/oofemlib/initialcondition.h index eadbf0343..effec5df1 100644 --- a/src/oofemlib/initialcondition.h +++ b/src/oofemlib/initialcondition.h @@ -142,11 +142,11 @@ class OOFEM_EXPORT InitialCondition : public FEMComponent */ const IntArray &giveDofIDs() { return dofIDs; } - // Overloaded methods: - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void printYourself(); - virtual const char *giveClassName() const { return "InitialCondition"; } - virtual const char *giveInputRecordName() const { return _IFT_InitialCondition_Name; } + void printYourself() override; + + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "InitialCondition"; } + const char *giveInputRecordName() const override { return _IFT_InitialCondition_Name; } }; } // end namespace oofem #endif // initial_h diff --git a/src/oofemlib/initmodule.C b/src/oofemlib/initmodule.C index f2cd88033..26bd0e3e4 100644 --- a/src/oofemlib/initmodule.C +++ b/src/oofemlib/initmodule.C @@ -47,17 +47,13 @@ InitModule :: ~InitModule() { } -IRResultType -InitModule :: initializeFrom(InputRecord *ir) +void +InitModule :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - std :: string initFileName; IR_GIVE_FIELD(ir, initFileName, _IFT_InitModule_initfilename); if ( ( initStream = fopen(initFileName.c_str(), "r") ) == NULL ) { OOFEM_ERROR("failed to open file %s", initFileName.c_str()); } - - return IRRT_OK; } } // end namespace oofem diff --git a/src/oofemlib/initmodule.h b/src/oofemlib/initmodule.h index 8b2d3eb46..d1a03c845 100644 --- a/src/oofemlib/initmodule.h +++ b/src/oofemlib/initmodule.h @@ -74,7 +74,7 @@ class OOFEM_EXPORT InitModule /// Destructor virtual ~InitModule(); /// Initializes receiver according to object description stored in input record. - virtual IRResultType initializeFrom(InputRecord *ir) = 0; + virtual void initializeFrom(InputRecord &ir) = 0; /// Reads the input. Abstract service. virtual void doInit() = 0; /// Returns class name of the receiver. diff --git a/src/oofemlib/initmodulemanager.C b/src/oofemlib/initmodulemanager.C index dc5af8806..6ee7c62e7 100644 --- a/src/oofemlib/initmodulemanager.C +++ b/src/oofemlib/initmodulemanager.C @@ -43,17 +43,14 @@ InitModuleManager :: InitModuleManager(EngngModel *emodel) : ModuleManager< Init InitModuleManager :: ~InitModuleManager() { } -IRResultType -InitModuleManager :: initializeFrom(InputRecord *ir) +void +InitModuleManager :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - this->numberOfModules = 0; IR_GIVE_OPTIONAL_FIELD(ir, numberOfModules, "ninitmodules"); ///@todo This is named differently from _IFT_ModuleManager_nmodules . Should we change or keep it? - return IRRT_OK; } -InitModule *InitModuleManager :: CreateModule(const char *name, int n, EngngModel *emodel) +std::unique_ptr InitModuleManager :: CreateModule(const char *name, int n, EngngModel *emodel) { return classFactory.createInitModule(name, n, emodel); } diff --git a/src/oofemlib/initmodulemanager.h b/src/oofemlib/initmodulemanager.h index 96fc83e8c..16ca0bbbe 100644 --- a/src/oofemlib/initmodulemanager.h +++ b/src/oofemlib/initmodulemanager.h @@ -52,7 +52,7 @@ class OOFEM_EXPORT InitModuleManager : public ModuleManager< InitModule > InitModuleManager(EngngModel * emodel); virtual ~InitModuleManager(); - InitModule *CreateModule(const char *name, int n, EngngModel *emodel); + std::unique_ptr CreateModule(const char *name, int n, EngngModel *emodel) override; /** * Performs the initialization of individual modules. @@ -60,9 +60,9 @@ class OOFEM_EXPORT InitModuleManager : public ModuleManager< InitModule > */ void doInit(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveClassName() const { return "InitModuleManager"; } + const char *giveClassName() const override { return "InitModuleManager"; } }; } // end namespace oofem #endif // initmodulemanager_h diff --git a/src/oofemlib/inputrecord.C b/src/oofemlib/inputrecord.C index 90a205a56..a3f15b667 100644 --- a/src/oofemlib/inputrecord.C +++ b/src/oofemlib/inputrecord.C @@ -35,149 +35,162 @@ #include "inputrecord.h" namespace oofem { -InputRecord :: InputRecord() { } -InputRecord :: InputRecord(const InputRecord &src) { } - -InputRecord & -InputRecord :: operator = ( const InputRecord & src ) -{ - return * this; -} - -const char * -InputRecord :: strerror(IRResultType rt) -{ - switch ( rt ) { - case IRRT_NOTFOUND: - return "Missing Keyword"; // string literal is statically allocated, return safe - - case IRRT_BAD_FORMAT: - return "Bad format"; - - default: - return "Unknown error"; - } -} - -IRResultType +void InputRecord :: giveOptionalField(int &answer, InputFieldType id) { - IRResultType r = this->giveField(answer, id); - if ( r == IRRT_NOTFOUND ) { - return IRRT_OK; - } else { - return r; + if ( this->hasField(id) ) { + try { + this->giveField(answer, id); + } catch ( MissingKeywordInputException & ) { } } } -IRResultType +void InputRecord :: giveOptionalField(double &answer, InputFieldType id) { - IRResultType r = this->giveField(answer, id); - if ( r == IRRT_NOTFOUND ) { - return IRRT_OK; - } else { - return r; + if ( this->hasField(id) ) { + try { + this->giveField(answer, id); + } catch ( MissingKeywordInputException & ) { } } } -IRResultType +void InputRecord :: giveOptionalField(bool &answer, InputFieldType id) { - IRResultType r = this->giveField(answer, id); - if ( r == IRRT_NOTFOUND ) { - return IRRT_OK; - } else { - return r; + if ( this->hasField(id) ) { + try { + this->giveField(answer, id); + } catch ( MissingKeywordInputException & ) { } } } -IRResultType +void InputRecord :: giveOptionalField(std :: string &answer, InputFieldType id) { - IRResultType r = this->giveField(answer, id); - if ( r == IRRT_NOTFOUND ) { - return IRRT_OK; - } else { - return r; + if ( this->hasField(id) ) { + try { + this->giveField(answer, id); + } catch ( MissingKeywordInputException & ) { } } } -IRResultType +void InputRecord :: giveOptionalField(FloatArray &answer, InputFieldType id) { - IRResultType r = this->giveField(answer, id); - if ( r == IRRT_NOTFOUND ) { - return IRRT_OK; - } else { - return r; + if ( this->hasField(id) ) { + try { + this->giveField(answer, id); + } catch ( MissingKeywordInputException & ) { } } } -IRResultType +void InputRecord :: giveOptionalField(IntArray &answer, InputFieldType id) { - IRResultType r = this->giveField(answer, id); - if ( r == IRRT_NOTFOUND ) { - return IRRT_OK; - } else { - return r; + if ( this->hasField(id) ) { + try { + this->giveField(answer, id); + } catch ( MissingKeywordInputException & ) { } } } -IRResultType +void InputRecord :: giveOptionalField(FloatMatrix &answer, InputFieldType id) { - IRResultType r = this->giveField(answer, id); - if ( r == IRRT_NOTFOUND ) { - return IRRT_OK; - } else { - return r; + if ( this->hasField(id) ) { + try { + this->giveField(answer, id); + } catch ( MissingKeywordInputException & ) { } } } -IRResultType +void InputRecord :: giveOptionalField(std :: vector< std :: string > &answer, InputFieldType id) { - IRResultType r = this->giveField(answer, id); - if ( r == IRRT_NOTFOUND ) { - return IRRT_OK; - } else { - return r; + if ( this->hasField(id) ) { + try { + this->giveField(answer, id); + } catch ( MissingKeywordInputException & ) { } } } -IRResultType +void InputRecord :: giveOptionalField(Dictionary &answer, InputFieldType id) { - IRResultType r = this->giveField(answer, id); - if ( r == IRRT_NOTFOUND ) { - return IRRT_OK; - } else { - return r; + if ( this->hasField(id) ) { + try { + this->giveField(answer, id); + } catch ( MissingKeywordInputException & ) { } } } -IRResultType +void InputRecord :: giveOptionalField(std :: list< Range > &answer, InputFieldType id) { - IRResultType r = this->giveField(answer, id); - if ( r == IRRT_NOTFOUND ) { - return IRRT_OK; - } else { - return r; + if ( this->hasField(id) ) { + try { + this->giveField(answer, id); + } catch ( MissingKeywordInputException & ) { } } } -IRResultType +void InputRecord :: giveOptionalField(ScalarFunction &answer, InputFieldType id) { - IRResultType r = this->giveField(answer, id); - if ( r == IRRT_NOTFOUND ) { - return IRRT_OK; - } else { - return r; + if ( this->hasField(id) ) { + try { + this->giveField(answer, id); + } catch ( MissingKeywordInputException & ) { } } } + + +InputException::InputException(const InputRecord& ir, std::string keyword, int number) : + record(ir.giveRecordAsString()), keyword(std::move(keyword)), number(number) +{ } + + +MissingKeywordInputException::MissingKeywordInputException(const InputRecord& ir, std::string kw, int n) : + InputException(ir, std::move(kw), n) +{ + msg = "Missing keyword \"" + keyword + "\" on input " + std::to_string(number) + \ + "\nRecord: \"" + record + "\""; +} + + +BadFormatInputException::BadFormatInputException(const InputRecord& ir, std::string kw, int n) : + InputException(ir, std::move(kw), n) +{ + msg = "Bad format for keyword \"" + keyword + "\" on input " + std::to_string(number) + \ + "\nRecord: \"" + record + "\""; +} + + +ValueInputException::ValueInputException(const InputRecord& ir, std::string kw, const std::string &reason) : + InputException(ir, std::move(kw), -1) +{ + msg = "Value input error for keyword \"" + keyword + "\"" + \ + "\nReason: \"" + reason + "\"\n" + \ + "\nRecord: \"" + record + "\""; +} + + +const char* MissingKeywordInputException::what() const noexcept +{ + return msg.c_str(); +} + + +const char* BadFormatInputException::what() const noexcept +{ + return msg.c_str(); +} + +const char* ValueInputException::what() const noexcept +{ + return msg.c_str(); +} + } // end namespace oofem diff --git a/src/oofemlib/inputrecord.h b/src/oofemlib/inputrecord.h index 02c637c15..98a730f79 100644 --- a/src/oofemlib/inputrecord.h +++ b/src/oofemlib/inputrecord.h @@ -38,10 +38,11 @@ #include #include #include +#include +#include #include "logger.h" // for missing __func__ in MSC #include "oofemcfg.h" -#include "irresulttype.h" namespace oofem { class IntArray; @@ -54,20 +55,13 @@ class ScalarFunction; /// Identifier of fields in input records. typedef const char *InputFieldType; -/** - * Macro simplifying the error reporting. - */ -#define IR_IOERR(__keyword, __ir, __result) \ - __ir->report_error(this->giveClassName(), __func__, __keyword, __result, __FILE__, __LINE__); - /** * Macro facilitating the use of input record reading methods. * uses the given input record (__ir parameter) and reads the compulsory * field identified by __kwd and stores the result into __value parameter. * Includes also the error reporting. */ -#define IR_GIVE_FIELD(__ir, __value, __id) result = __ir->giveField(__value, __id); \ - if ( result != IRRT_OK ) { IR_IOERR(__id, __ir, result); } +#define IR_GIVE_FIELD(__ir, __value, __id) __ir.giveField(__value, __id); /** * Macro facilitating the use of input record reading methods. @@ -75,8 +69,7 @@ typedef const char *InputFieldType; * field identified by __kwd and stores the result into __value parameter. * Includes also the error reporting. */ -#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id) result = __ir->giveOptionalField(__value, __id); \ - if ( result != IRRT_OK ) { IR_IOERR(__id, __ir, result); } +#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id) __ir.giveOptionalField(__value, __id); /** * Macro facilitating the use of input record reading methods. @@ -84,8 +77,7 @@ typedef const char *InputFieldType; * and its number (__value param). Includes also the error reporting. */ #define IR_GIVE_RECORD_KEYWORD_FIELD(__ir, __name, __value) \ - result = __ir->giveRecordKeywordField(__name, __value); \ - if ( result != IRRT_OK ) { IR_IOERR("RecordIDField", __ir, result); } + __ir.giveRecordKeywordField(__name, __value); @@ -101,17 +93,11 @@ typedef const char *InputFieldType; class OOFEM_EXPORT InputRecord { public: - /// Constructor. Creates an empty input record. - InputRecord(); - /// Copy constructor - InputRecord(const InputRecord &); /// Destructor - virtual ~InputRecord() { } - /// Assignment operator. - InputRecord &operator = ( const InputRecord & ); + virtual ~InputRecord() = default; /** Creates a newly allocated copy of the receiver */ - virtual InputRecord *GiveCopy() = 0; + virtual std::unique_ptr clone() const = 0; /// Returns string representation of record in OOFEMs text format. virtual std :: string giveRecordAsString() const = 0; @@ -119,83 +105,120 @@ class OOFEM_EXPORT InputRecord /**@name Compulsory field extraction methods * Reads the field value identified by keyword * @param answer contains result - * @param idString field keyword - * @return IRResultType + * @param id field keyword */ //@{ /// Reads the record id field (type of record) and its corresponding number. - virtual IRResultType giveRecordKeywordField(std :: string &answer, int &value) = 0; + virtual void giveRecordKeywordField(std :: string &answer, int &value) = 0; /// Reads the record id field (type of record). - virtual IRResultType giveRecordKeywordField(std :: string &answer) = 0; + virtual void giveRecordKeywordField(std :: string &answer) = 0; /// Reads the integer field value. - virtual IRResultType giveField(int &answer, InputFieldType id) = 0; + virtual void giveField(int &answer, InputFieldType id) = 0; /// Reads the double field value. - virtual IRResultType giveField(double &answer, InputFieldType id) = 0; + virtual void giveField(double &answer, InputFieldType id) = 0; /// Reads the bool field value. - virtual IRResultType giveField(bool &answer, InputFieldType id) = 0; + virtual void giveField(bool &answer, InputFieldType id) = 0; /// Reads the string field value. - virtual IRResultType giveField(std :: string &answer, InputFieldType id) = 0; + virtual void giveField(std :: string &answer, InputFieldType id) = 0; /// Reads the FloatArray field value. - virtual IRResultType giveField(FloatArray &answer, InputFieldType id) = 0; + virtual void giveField(FloatArray &answer, InputFieldType id) = 0; /// Reads the IntArray field value. - virtual IRResultType giveField(IntArray &answer, InputFieldType id) = 0; + virtual void giveField(IntArray &answer, InputFieldType id) = 0; /// Reads the FloatMatrix field value. - virtual IRResultType giveField(FloatMatrix &answer, InputFieldType id) = 0; + virtual void giveField(FloatMatrix &answer, InputFieldType id) = 0; /// Reads the vector of strings. - virtual IRResultType giveField(std :: vector< std :: string > &answer, InputFieldType id) = 0; + virtual void giveField(std :: vector< std :: string > &answer, InputFieldType id) = 0; /// Reads the Dictionary field value. - virtual IRResultType giveField(Dictionary &answer, InputFieldType id) = 0; + virtual void giveField(Dictionary &answer, InputFieldType id) = 0; /// Reads the std::list field value. - virtual IRResultType giveField(std :: list< Range > &answer, InputFieldType id) = 0; + virtual void giveField(std :: list< Range > &answer, InputFieldType id) = 0; /// Reads the ScalarFunction field value. - virtual IRResultType giveField(ScalarFunction &function, InputFieldType id) = 0; + virtual void giveField(ScalarFunction &function, InputFieldType id) = 0; //@} /**@name Optional field extraction methods * Reads the field value identified by keyword * @param answer contains result - * @param idString field keyword - * @return IRResultType + * @param id field keyword */ //@{ /// Reads the integer field value. - IRResultType giveOptionalField(int &answer, InputFieldType id); + void giveOptionalField(int &answer, InputFieldType id); /// Reads the double field value. - IRResultType giveOptionalField(double &answer, InputFieldType id); + void giveOptionalField(double &answer, InputFieldType id); /// Reads the bool field value. - IRResultType giveOptionalField(bool &answer, InputFieldType id); + void giveOptionalField(bool &answer, InputFieldType id); /// Reads the string field value. - IRResultType giveOptionalField(std :: string &answer, InputFieldType id); + void giveOptionalField(std :: string &answer, InputFieldType id); /// Reads the FloatArray field value. - IRResultType giveOptionalField(FloatArray &answer, InputFieldType id); + void giveOptionalField(FloatArray &answer, InputFieldType id); /// Reads the IntArray field value. - IRResultType giveOptionalField(IntArray &answer, InputFieldType id); + void giveOptionalField(IntArray &answer, InputFieldType id); /// Reads the FloatMatrix field value. - IRResultType giveOptionalField(FloatMatrix &answer, InputFieldType id); + void giveOptionalField(FloatMatrix &answer, InputFieldType id); /// Reads the vector of strings. - IRResultType giveOptionalField(std :: vector< std :: string > &answer, InputFieldType id); + void giveOptionalField(std :: vector< std :: string > &answer, InputFieldType id); /// Reads the Dictionary field value. - IRResultType giveOptionalField(Dictionary &answer, InputFieldType id); + void giveOptionalField(Dictionary &answer, InputFieldType id); /// Reads the std::list field value. - IRResultType giveOptionalField(std :: list< Range > &answer, InputFieldType id); + void giveOptionalField(std :: list< Range > &answer, InputFieldType id); /// Reads the ScalarFunction field value. - IRResultType giveOptionalField(ScalarFunction &function, InputFieldType id); + void giveOptionalField(ScalarFunction &function, InputFieldType id); //@} /// Returns true if record contains field identified by idString keyword. virtual bool hasField(InputFieldType id) = 0; - /// Returns error string corresponding to given value of IRResultType type. - const char *strerror(IRResultType); /// Print input record. virtual void printYourself() = 0; - /// Prints the error message. - virtual void report_error(const char *_class, const char *proc, InputFieldType id, - IRResultType result, const char *file, int line) = 0; - /// Terminates the current record session and if the flag is true, warning is printed for unscanned tokens. virtual void finish(bool wrn = true) = 0; }; + + +class InputException : public std::exception +{ +public: + std::string record; + std::string keyword; + int number; + InputException(const InputRecord &ir, std::string keyword, int number); +}; + + +class MissingKeywordInputException : public InputException +{ +protected: + std::string msg; + +public: + MissingKeywordInputException(const InputRecord &ir, std::string keyword, int number); + const char* what() const noexcept override; +}; + + +class BadFormatInputException : public InputException +{ +protected: + std::string msg; + +public: + BadFormatInputException(const InputRecord &ir, std::string keyword, int number); + const char* what() const noexcept override; +}; + + +class ValueInputException : public InputException +{ +protected: + std::string msg; + +public: + ValueInputException(const InputRecord &ir, std::string keyword, const std::string &reason); + const char* what() const noexcept override; +}; + + } // end namespace oofem #endif // inputrecord_h diff --git a/src/oofemlib/intarray.C b/src/oofemlib/intarray.C index 52f188b61..246dd4ae3 100644 --- a/src/oofemlib/intarray.C +++ b/src/oofemlib/intarray.C @@ -61,57 +61,6 @@ void IntArray :: add(int value) } -#ifdef DEBUG -int &IntArray :: at(int i) -{ - this->checkBounds(i); - return values [ i - 1 ]; -} - -int IntArray :: at(int i) const -{ - this->checkBounds(i); - return values [ i - 1 ]; -} - -int &IntArray :: operator()(int i) -{ - this->checkBounds(i); - return values [ i ]; -} - -const int &IntArray :: operator()(int i) const -{ - this->checkBounds(i); - return values [ i ]; -} - -int &IntArray :: operator[](int i) -{ - this->checkBounds(i); - return values [ i ]; -} - -const int &IntArray :: operator[](int i) const -{ - this->checkBounds(i); - return values [ i ]; -} - -void IntArray :: checkBounds(int i) const -// Checks that the receiver includes an index i. -{ - if ( i < 0 ) { - OOFEM_ERROR("array error on index : %d < 0", i); - } - - if ( i > this->giveSize() ) { - OOFEM_ERROR("array error on index : %d > %d", i, this->giveSize()); - } -} -#endif - - void IntArray :: resizeWithValues(int n, int allocChunk) { if ( allocChunk > 0 && (int)this->values.capacity() < n ) { @@ -162,7 +111,7 @@ void IntArray :: followedBy(int b, int allocChunk) void IntArray :: erase(int _pos) { -#ifdef DEBUG +#ifndef NDEBUG this->checkBounds(_pos); #endif values.erase(values.begin() + _pos - 1); @@ -183,7 +132,7 @@ bool IntArray :: containsOnlyZeroes() const int IntArray :: minimum() const { -#ifdef DEBUG +#ifndef NDEBUG if ( this->isEmpty() ) { OOFEM_ERROR("Empty array."); } @@ -194,7 +143,7 @@ int IntArray :: minimum() const int IntArray :: maximum() const { -#ifdef DEBUG +#ifndef NDEBUG if ( this->isEmpty() ) { OOFEM_ERROR("Empty array."); } @@ -257,8 +206,8 @@ void IntArray :: printYourself(const std::string name) const bool IntArray :: isFinite() const { - for(int val : values) { - if(!std::isfinite(val)) { + for ( int val : values ) { + if( !std::isfinite((double)val) ) { return false; } } diff --git a/src/oofemlib/intarray.h b/src/oofemlib/intarray.h index 96bb6d0bf..126041156 100644 --- a/src/oofemlib/intarray.h +++ b/src/oofemlib/intarray.h @@ -38,6 +38,7 @@ #include "oofemcfg.h" #include "contextioresulttype.h" #include "contextmode.h" +#include "error.h" #include #include @@ -97,66 +98,70 @@ class OOFEM_EXPORT IntArray * @param i Position of coefficient in array. * @return Value at position. */ -#ifdef DEBUG - int &at(int i); -#else - inline int &at(int i) { return values [ i - 1 ]; } + inline int &at(int i) + { +#ifndef NDEBUG + this->checkBounds(i); #endif + return values[ i - 1 ]; + } /** * Coefficient access function. Returns value of coefficient at given * position of the receiver. * @param i position of coefficient in array. * @return Value at position. */ -#ifdef DEBUG - int at(int i) const; -#else - inline int at(int i) const { return values [ i - 1 ]; } + inline int at(int i) const + { +#ifndef NDEBUG + this->checkBounds(i); #endif + return values[ i - 1 ]; + } /** * Coefficient access function. Returns value of coefficient at given * position of the receiver. Provides 0-based indexing access. * @param i Position of coefficient in array. * @return Value at position. */ -#ifdef DEBUG - int &operator() (int i); -#else - inline int &operator() (int i) { return values [ i ]; } + inline int &operator() (int i) { return this->operator[](i); } + inline int &operator[] (int i) + { +#ifndef NDEBUG + this->checkBounds(i + 1); #endif + return values[ i ]; + } /** * Coefficient access function. Returns value of coefficient at given * position of the receiver. Provides 0-based indexing access. * @param i position of coefficient in array. * @return Value at position. */ -#ifdef DEBUG - const int &operator() (int i) const; -#else - inline const int &operator() (int i) const { return values [ i ]; } -#endif - -#ifdef DEBUG - int &operator[] ( int i ); -#else - inline int &operator[] ( int i ) { return values [ i ]; } -#endif - -#ifdef DEBUG - const int &operator[] ( int i ) const; -#else - inline const int &operator[] ( int i ) const { return values [ i ]; } + inline const int &operator() (int i) const { return this->operator[](i); } + inline const int &operator[] (int i) const + { +#ifndef NDEBUG + this->checkBounds(i + 1); #endif + return values[ i ]; + } -#ifdef DEBUG /** * Checks size of receiver towards requested bounds. * Current implementation will call exit(1) if dimension * mismatch found. * @param i Required size of receiver */ - void checkBounds(int i) const; -#endif + void checkBounds(int i) const + { + if ( i <= 0 ) { + OOFEM_ERROR("array error on index : %d <= 0", i); + } else if ( i > this->giveSize() ) { + OOFEM_ERROR("array error on index : %d > %d", i, this->giveSize()); + } + } + /** * Checks size of receiver towards requested bounds. * If dimension mismatch, size is adjusted accordingly and memory is copied over. @@ -353,7 +358,7 @@ class OOFEM_EXPORT IntArray friend std :: ostream &operator << ( std :: ostream & out, const IntArray & x ); -#ifdef BOOST_PYTHON +#ifdef _BOOSTPYTHON_BINDINGS void __setitem__(int i, int val) { this->at(i + 1) = val; } int __getitem__(int i) { return this->at(i + 1); } void beCopyOf(const IntArray &src) { this->operator = ( src ); } @@ -362,7 +367,8 @@ class OOFEM_EXPORT IntArray template< class operation > int -quickSortPartition(IntArray &arry, int l, int r, operation op) { +quickSortPartition(IntArray &arry, int l, int r, operation op) +{ int i = l - 1, j = r; int v = arry.at(r); int swap; @@ -395,7 +401,8 @@ quickSortPartition(IntArray &arry, int l, int r, operation op) { -template< class operation > void quickSort(IntArray &arry, int l, int r, operation op) { +template< class operation > void quickSort(IntArray &arry, int l, int r, operation op) +{ if ( r <= l ) { return; } diff --git a/src/oofemlib/intarrayf.h b/src/oofemlib/intarrayf.h new file mode 100644 index 000000000..97e420ae6 --- /dev/null +++ b/src/oofemlib/intarrayf.h @@ -0,0 +1,417 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef intarray_h +#define intarray_h + +#include "oofemcfg.h" +#include "contextioresulttype.h" +#include "contextmode.h" +#include "error.h" + +#include +#include +#include +#include + +namespace oofem { +class DataStream; + +/** + */ +template< class T > +class OOFEM_EXPORT IntArrayF +{ +private: + /// Stored values. + T values; + +public: + /// @name Iterator for for-each loops: + //@{ + T :: iterator begin() { return this->values.begin(); } + T :: iterator end() { return this->values.end(); } + T :: const_iterator begin() const { return this->values.begin(); } + T :: const_iterator end() const { return this->values.end(); } + //@} + + /// Constructor for sized array. Data is zeroed. + IntArray(int n = 0) : values(n) { } + /// Copy constructor. Creates the array from another array. + IntArray(const IntArray &src) : values(src.values) { } + /// Move constructor. Creates the array from another array. + IntArray(IntArray &&src) : values(std::move(src.values)) { } + /// Initializer list constructor. + inline IntArray(std :: initializer_list< int >list) : values(list) { } + /// Destructor. + ~IntArray() = default; + + /// Assignment operator + IntArray &operator = (const IntArray &src) { values = src.values; return *this; } + /// Move operator + IntArray &operator = (IntArray &&src) { values = std::move(src.values); return *this; } + /// Assignment operator. + inline IntArray &operator = (std :: initializer_list< int >list) { values = list; return *this; } + + /** + * Coefficient access function. Returns l-value of coefficient at given + * position of the receiver. + * @param i Position of coefficient in array. + * @return Value at position. + */ + inline int &at(int i) + { +#ifndef NDEBUG + this->checkBounds(i); +#endif + return values[ i - 1 ]; + } + /** + * Coefficient access function. Returns value of coefficient at given + * position of the receiver. + * @param i position of coefficient in array. + * @return Value at position. + */ + inline int at(int i) const + { +#ifndef NDEBUG + this->checkBounds(i); +#endif + return values[ i - 1 ]; + } + /** + * Coefficient access function. Returns value of coefficient at given + * position of the receiver. Provides 0-based indexing access. + * @param i Position of coefficient in array. + * @return Value at position. + */ + inline int &operator() (int i) { return this->operator[](i); } + inline int &operator[] (int i) + { +#ifndef NDEBUG + this->checkBounds(i + 1); +#endif + return values[ i ]; + } + /** + * Coefficient access function. Returns value of coefficient at given + * position of the receiver. Provides 0-based indexing access. + * @param i position of coefficient in array. + * @return Value at position. + */ + inline const int &operator() (int i) const { return this->operator[](i); } + inline const int &operator[] (int i) const + { +#ifndef NDEBUG + this->checkBounds(i + 1); +#endif + return values[ i ]; + } + + /** + * Checks size of receiver towards requested bounds. + * Current implementation will call exit(1) if dimension + * mismatch found. + * @param i Required size of receiver + */ + void checkBounds(int i) const + { + if ( i <= 0 ) { + OOFEM_ERROR("array error on index : %d <= 0", i); + } else if ( i > this->giveSize() ) { + OOFEM_ERROR("array error on index : %d > %d", i, this->giveSize()); + } + } + + /** + * Checks size of receiver towards requested bounds. + * If dimension mismatch, size is adjusted accordingly and memory is copied over. + * @param n New size of array. + * @param allocChunk If reallocation needed, an additional space for allocChunk values will be allocated + * to prevent excessive reallocation. + */ + void resizeWithValues(int n, int allocChunk = 0); + /** + * Checks size of receiver towards requested bounds. + * Data is always zeroed. + * @param n New size of array. + */ + void resize(int n); + /** + * Clears the array (zero size). + */ + void clear() { this->values.clear(); } + /** + * Preallocates receiver to given futureSize if larger then allocatedSize. + * @param futureSize Size to be allocated. + */ + void preallocate(int futureSize); + /** + * Resizes receiver and enumerates from 1 to the maximum value given. + * @param maxVal to enumerate to. + */ + void enumerate(int maxVal); + /** + * Appends array b at the end of receiver. + * @param b Array to be appended at the end of receiver + * @param allocChunk If reallocation needed, an additional space for allocChunk values will be allocated + * to prevent excessive reallocation. + */ + void followedBy(const IntArray &b, int allocChunk = 0); + /** + * Appends given Number at the end of receiver. + * @param b value to be appended. + * @param allocChunk If reallocation needed, an additional space for allocChunk values will be allocated + * to prevent excessive reallocation. + */ + void followedBy(int b, int allocChunk = 0); + /// @return Size of receiver. + int giveSize() const { return (int)values.size(); } + /** + * Checks if receiver is empty (i.e., zero sized). + * @return True is size is zero. + */ + bool isEmpty() const { return values.size() == 0; } + /** + * Checks if receiver is all zero. + * @return True is receiver contains only zeroes. + */ + bool containsOnlyZeroes() const; + /** + * Finds the first occurrence of given value, assuming that the receiver is sorted. + * @return Index (1-based), if not present, 0 is returned. + */ + int findSorted(int value) const; + /** + * Finds the minimum component in the array. + * @return Minimum of array or prints error is array is empty. + */ + int minimum() const; + /** + * Finds the maximum component in the array. + * @return Maximum of array or prints error is array is empty. + */ + int maximum() const; + /** + * Finds all indices where the input array is nonzero + * @param logical Array of logical values (0 = false, nonzero = true) to have index extracted. + */ + void findNonzeros(const IntArray &logical); + /** + * Checks if sorted receiver contains a given value. + * @return True if receiver contains given value. + */ + bool containsSorted(int value) const { return ( findSorted(value) > 0 ); } + + /** + * Inserts given value into a receiver, which is assumed to be sorted. + * The size of receiver is changed accordingly. + * @param value value to insert. + * @param allocChunk If reallocation needed, an additional space for allocChunk values will be allocated. + */ + void insertSorted(int value, int allocChunk = 0); + /** + * Inserts given value into a receiver, which is assumed to be sorted. + * The value is inserted only if it does not exist. + * The size of receiver is changed accordingly. + * @param value Value to insert. + * @param allocChunk If reallocation needed, an additional space for allocChunk values will be allocated. + * @return True if value is inserted, false if value is already in array. + */ + bool insertSortedOnce(int value, int allocChunk = 0); + /** + * Erase the element of given value. + * If the value is found receiver will shrink accordingly, + * while preserving a sorted state. + * @param value Value to erase. + */ + void eraseSorted(int value); + /** + * Extracts common values in receiver and iarray. + * Assumes that receiver as well as iarray are sorted. + * The size of array common is changed accordingly. + * @param iarray Array to search for values common with receiver. + * @param common Array of common values. + * @param allocChunk If reallocation needed, an additional space for allocChunk values will be allocated. + * @return Number of common values. + */ + int findCommonValuesSorted(const IntArray &iarray, IntArray &common, int allocChunk = 0) const; + + /** + * Finds index of first occurrence of given value in array. + * @param value Scanned value. + * @return Index of first value in array, otherwise zero. + */ + int findFirstIndexOf(int value) const; + /** + * @return True if receiver contains given value. + */ + bool contains(int value) const { return ( findFirstIndexOf(value) > 0 ); } + /** + * Insert once (does not make any assumption about receiver state or ordering, quite + * inefficient). More efficient version insertSortedOnce exist. + * @param p Value to insert. + */ + void insertOnce(int p); + /** + * Sorts array. + */ + void sort(); + /** + * Erase the element at given position (1-based index) + * Receiver will shrink accordingly, the values at positions (pos+1,...,size) + * will be moved to positions (pos,...,size-1) + * @param pos Position to erase. + */ + void erase(int pos); + /** + * Adds given scalar to all values of receiver + * @param val Value to add. + */ + void add(int val); + + /// Sets all component to zero. + void zero(); + + /// Prints receiver on stdout. + void printYourself() const; + + /// Abbreviation for printYourself(). + void pY() const; + + /** + * Prints receiver on stdout with custom name. + * @param name Display name of reciever. + */ + void printYourself(const std::string name) const; + + /** + * Print receiver to file + * @param filename Name of recieving file. + * @param showDimensions Determins if dimesions should be included in output + */ + void printYourselfToFile(const std::string filename, const bool showDimensions=true) const; + + /// Returns true if no element is NAN or infinite + bool isFinite() const; + + /** + * Breaks encapsulation. Avoid using this unless absolutely necessary. + * @return Internal pointer to stored values. + */ + inline const int *givePointer() const { return values.data(); } + inline int *givePointer() { return values.data(); } + + /** + * Stores array to output stream. + */ + contextIOResultType storeYourself(DataStream &stream) const; + /** + * Restores array from image on stream. + */ + contextIOResultType restoreYourself(DataStream &stream); + /** + * Returns how much space is needed to pack receivers message. + * @param buff Buffer used for packing. + */ + int givePackSize(DataStream &buff) const; + + + friend std :: ostream &operator << ( std :: ostream & out, const IntArray & x ); + +#ifdef _BOOSTPYTHON_BINDINGS + void __setitem__(int i, int val) { this->at(i + 1) = val; } + int __getitem__(int i) { return this->at(i + 1); } + void beCopyOf(const IntArray &src) { this->operator = ( src ); } +#endif +}; + + +template< class operation > int +quickSortPartition(IntArray &arry, int l, int r, operation op) +{ + int i = l - 1, j = r; + int v = arry.at(r); + int swap; + + for ( ; ; ) { + while ( ( op(arry.at(++i), v) ) < 0 ) { + ; + } + + while ( ( op( v, arry.at(--j) ) ) < 0 ) { + if ( j == l ) { + break; + } + } + + if ( i >= j ) { + break; + } + + swap = arry.at(i); + arry.at(i) = arry.at(j); + arry.at(j) = swap; + } + + swap = arry.at(i); + arry.at(i) = arry.at(r); + arry.at(r) = swap; + return i; +} + + + +template< class operation > void quickSort(IntArray &arry, int l, int r, operation op) +{ + if ( r <= l ) { + return; + } + + int i = quickSortPartition(arry, l, r, op); + quickSort(arry, l, i - 1, op); + quickSort(arry, i + 1, r, op); +} + + +/** + * Sorts the receiver using quicksort algorithm. + * @param op Function object, required to have member function int class::operator() (int, int), + * must return a negative value if first argument is less than the second, + * zero if the arguments are equal, and a positive number otherwise. + * @param arry Array to sort. + */ +template< class operation > void sort(IntArray &arry, operation op) { quickSort(arry, 1, arry.giveSize(), op); } +} // end namespace oofem +#endif // intarray_h diff --git a/src/oofemlib/integrationpointstatus.h b/src/oofemlib/integrationpointstatus.h index c03133075..29706968f 100644 --- a/src/oofemlib/integrationpointstatus.h +++ b/src/oofemlib/integrationpointstatus.h @@ -35,10 +35,15 @@ #ifndef integrationpointstatus_h #define integrationpointstatus_h -#include "femcmpnn.h" +#include "interface.h" +#include "interfacetype.h" +#include "contextioresulttype.h" +#include "contextmode.h" namespace oofem { class GaussPoint; +class TimeStep; +class DataStream; /** * Abstract base class representing a integration status. @@ -50,7 +55,7 @@ class GaussPoint; * Any object that stores its status in integration point is responsible for its creation, * initialization, and serialization. */ -class OOFEM_EXPORT IntegrationPointStatus : public FEMComponent +class OOFEM_EXPORT IntegrationPointStatus { protected: /// Associated integration point. @@ -59,15 +64,13 @@ class OOFEM_EXPORT IntegrationPointStatus : public FEMComponent public: /** * Constructor. - * @param n receiver's number - * @param d domain to which new status belongs * @param g associated integration point */ - IntegrationPointStatus(int n, Domain * d, GaussPoint * g) : FEMComponent(n, d), gp(g) { } + IntegrationPointStatus(GaussPoint * g) : gp(g) { } /// Destructor. - virtual ~IntegrationPointStatus() { } + virtual ~IntegrationPointStatus() = default; /// Print receiver's output to given stream. - virtual void printOutputAt(FILE *file, TimeStep *tStep) { } + virtual void printOutputAt(FILE *file, TimeStep *tStep) const { } /** * Update equilibrium history variables according to temp-variables. * Invoked, after new equilibrium state has been reached. @@ -82,10 +85,25 @@ class OOFEM_EXPORT IntegrationPointStatus : public FEMComponent * by another simulation (e.g. of the manufacturing process). */ virtual void setStatusVariable(int varID, double value) { } + /** + * Stores receiver state to output stream. + * @param stream Output stream. + * @param mode Determines amount of info required in stream (state, definition, ...). + * @exception throws an ContextIOERR exception if error encountered. + */ + virtual void saveContext(DataStream &stream, ContextMode mode) { } + /** + * Restores the receiver state previously written in stream. + * @see saveContext + * @param stream Input stream. + * @param mode Determines amount of info available in stream (state, definition, ...). + * @exception throws an ContextIOERR exception if error encountered. + */ + virtual void restoreContext(DataStream &stream, ContextMode mode) { } + + virtual Interface *giveInterface(InterfaceType t) { return nullptr; } - virtual const char *giveInputRecordName() const { return NULL; } - virtual const char *giveClassName() const { return "IntegrationPointStatus"; } - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + virtual const char *giveClassName() const = 0; //{ return "IntegrationPointStatus"; } }; } // end namespace oofem #endif // integrationpointstatus_h diff --git a/src/oofemlib/integrationrule.C b/src/oofemlib/integrationrule.C index be55b844c..30d92906d 100644 --- a/src/oofemlib/integrationrule.C +++ b/src/oofemlib/integrationrule.C @@ -95,9 +95,9 @@ GaussPoint * IntegrationRule :: findIntegrationPointClosestTo(const FloatArray &lcoord) { double mindist = -1.; - GaussPoint *minGp = NULL; + GaussPoint *minGp = nullptr; for ( GaussPoint *gp: *this ) { - double dist = lcoord.distance_square(gp->giveNaturalCoordinates()); + double dist = distance_square(lcoord, gp->giveNaturalCoordinates()); if ( dist <= mindist || mindist < 0. ) { mindist = dist; minGp = gp; @@ -111,7 +111,7 @@ void IntegrationRule :: printOutputAt(FILE *file, TimeStep *tStep) // Performs end-of-step operations. { - for ( GaussPoint *gp: *this ) { + for ( auto &gp: *this ) { gp->printOutputAt(file, tStep); } } @@ -120,20 +120,15 @@ void IntegrationRule :: updateYourself(TimeStep *tStep) { // Updates the receiver at end of step. - for ( GaussPoint *gp: *this ) { + for ( auto &gp: *this ) { gp->updateYourself(tStep); } } -contextIOResultType -IntegrationRule :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +IntegrationRule :: saveContext(DataStream &stream, ContextMode mode) { - // - // saves full context (saves state variables, that completely describe - // current state) - // - contextIOResultType iores; int isdyn = isDynamic; @@ -161,7 +156,7 @@ IntegrationRule :: saveContext(DataStream &stream, ContextMode mode, void *obj) } } - for ( GaussPoint *gp: *this ) { + for ( auto &gp: *this ) { if ( mode & CM_Definition ) { // write gp weight, coordinates, element number, and material mode double dval = gp->giveWeight(); @@ -182,22 +177,13 @@ IntegrationRule :: saveContext(DataStream &stream, ContextMode mode, void *obj) } // write gp data - if ( ( iores = gp->giveCrossSection()->saveIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + gp->giveCrossSection()->saveIPContext(stream, mode, gp); } - - return CIO_OK; } -contextIOResultType -IntegrationRule :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +IntegrationRule :: restoreContext(DataStream &stream, ContextMode mode) { - // - // restores full element context (saves state variables, that completely describe - // current state) - // - contextIOResultType iores; int size; @@ -227,12 +213,12 @@ IntegrationRule :: restoreContext(DataStream &stream, ContextMode mode, void *ob } this->clear(); - + this->gaussPoints.resize(size); } int i = 1; - for ( GaussPoint *&gp: *this ) { + for ( auto &gp: *this ) { if ( mode & CM_Definition ) { // read weight double w; @@ -263,12 +249,8 @@ IntegrationRule :: restoreContext(DataStream &stream, ContextMode mode, void *ob } // read gp data - if ( ( iores = gp->giveCrossSection()->restoreIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + gp->giveCrossSection()->restoreIPContext(stream, mode, gp); } - - return CIO_OK; } diff --git a/src/oofemlib/integrationrule.h b/src/oofemlib/integrationrule.h index b40d260ec..a6b8702cc 100644 --- a/src/oofemlib/integrationrule.h +++ b/src/oofemlib/integrationrule.h @@ -221,10 +221,9 @@ class OOFEM_EXPORT IntegrationRule * to write class id info for each integration rule. * @param stream Output stream. * @param mode Determines amount of info required in stream (state, definition, ...). - * @param obj Special parameter. * @exception ContextIOERR If error encountered. */ - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj); + virtual void saveContext(DataStream &stream, ContextMode mode); /** * Restores receiver's context to stream. * Calls restoreContext service for all receiver's integration points. @@ -232,10 +231,9 @@ class OOFEM_EXPORT IntegrationRule * to write class id info for each integration rule. * @param stream Input stream. * @param mode Determines amount of info available in stream (state, definition, ...). - * @param obj Should be a pointer to invoking element, ie., to which the receiver will belong to. * @exception ContextIOERR If error encountered. */ - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj); + virtual void restoreContext(DataStream &stream, ContextMode mode); /** * Clears the receiver, ie deallocates all integration points */ @@ -248,7 +246,7 @@ class OOFEM_EXPORT IntegrationRule /// Error printing helper. std :: string errorInfo(const char *func) const { return std :: string(giveClassName()) + func; } virtual IntegrationRuleType giveIntegrationRuleType() const { return IRT_None; } - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + virtual void initializeFrom(InputRecord &ir) { } /** * Trivial implementation, only creates a single point. diff --git a/src/oofemlib/interfacetype.h b/src/oofemlib/interfacetype.h index c56089cd7..03d9356ca 100644 --- a/src/oofemlib/interfacetype.h +++ b/src/oofemlib/interfacetype.h @@ -60,8 +60,8 @@ enum InterfaceType { EIPrimaryFieldInterfaceType, NonlocalMaterialStatusExtensionInterfaceType, - GradDpMaterialExtensionInterfaceType, - GradDpMaterialStatusExtensionInterfaceType, + GradientDamageMaterialExtensionInterfaceType, + GradientDamageMaterialStatusExtensionInterfaceType, NonlocalMaterialExtensionInterfaceType, NonlocalMaterialStiffnessInterfaceType, @@ -81,7 +81,9 @@ enum InterfaceType { Beam3dSubsoilElementInterfaceType, Beam3dSubsoilMaterialInterfaceType, - QCMaterialExtensionInterfaceType + QCMaterialExtensionInterfaceType, + + MixedPressureMaterialExtensionInterfaceType }; } // end namespace oofem #endif // interfacetype_h diff --git a/src/oofemlib/internalstatetype.h b/src/oofemlib/internalstatetype.h index 142755838..70d909198 100644 --- a/src/oofemlib/internalstatetype.h +++ b/src/oofemlib/internalstatetype.h @@ -108,7 +108,7 @@ namespace oofem { ENUM_ITEM_WITH_VALUE(IST_HumidityFlow, 58) \ ENUM_ITEM_WITH_VALUE(IST_CrackStatuses, 59) \ ENUM_ITEM_WITH_VALUE(IST_CrackedFlag, 60) \ - ENUM_ITEM_WITH_VALUE(IST_CrackDirs, 61) \ + ENUM_ITEM_WITH_VALUE(IST_CrackDirs, 61) \ ENUM_ITEM_WITH_VALUE(IST_CumPlasticStrain, 62) \ ENUM_ITEM_WITH_VALUE(IST_CumPlasticStrain_2, 63) \ ENUM_ITEM_WITH_VALUE(IST_StressWorkDensity, 64) \ @@ -150,7 +150,7 @@ namespace oofem { ENUM_ITEM_WITH_VALUE(IST_InterfaceFirstPKTraction, 100) \ ENUM_ITEM_WITH_VALUE(IST_StressTensor_Reduced, 101) \ ENUM_ITEM_WITH_VALUE(IST_StrainTensor_Reduced, 102) \ - ENUM_ITEM_WITH_VALUE(IST_CrossSectionNumber, 103 ) \ + ENUM_ITEM_WITH_VALUE(IST_CrossSectionNumber, 103) \ ENUM_ITEM_WITH_VALUE(IST_ShellStrainTensor, 104) \ ENUM_ITEM_WITH_VALUE(IST_AbaqusStateVector, 105) \ ENUM_ITEM_WITH_VALUE(IST_AutogenousShrinkageTensor, 106) \ @@ -178,8 +178,28 @@ namespace oofem { ENUM_ITEM_WITH_VALUE(IST_MomentTensor, 128) \ ENUM_ITEM_WITH_VALUE(IST_MomentTensorTemp, 129) \ ENUM_ITEM_WITH_VALUE(IST_YieldStrength, 130) \ - ENUM_ITEM_WITH_VALUE(IST_MoistureContent, 131) - + ENUM_ITEM_WITH_VALUE(IST_ElasticStrainTensor, 131) \ + ENUM_ITEM_WITH_VALUE(IST_MoistureContent, 132) \ + ENUM_ITEM_WITH_VALUE(IST_CrackStatusesTemp, 133) \ + ENUM_ITEM_WITH_VALUE(IST_CrackSlip, 134) \ + ENUM_ITEM_WITH_VALUE(IST_EquivalentTime, 135) \ + ENUM_ITEM_WITH_VALUE(IST_IncrementCreepModulus, 136) \ + ENUM_ITEM_WITH_VALUE(IST_NormalStress, 137) \ + ENUM_ITEM_WITH_VALUE(IST_LatticeStrain, 138) \ + ENUM_ITEM_WITH_VALUE(IST_LatticeStress, 139) \ + ENUM_ITEM_WITH_VALUE(IST_PlasticLatticeStrain, 140) \ + ENUM_ITEM_WITH_VALUE(IST_InternalSource, 141) \ + ENUM_ITEM_WITH_VALUE(IST_MacroSlipVector, 142) \ + ENUM_ITEM_WITH_VALUE(IST_TransferStress, 143) \ + ENUM_ITEM_WITH_VALUE(IST_MacroSlipGradient, 144) \ + ENUM_ITEM_WITH_VALUE(IST_ReinfMembraneStress, 145)\ + ENUM_ITEM_WITH_VALUE(IST_TensionDissWork, 146) \ + ENUM_ITEM_WITH_VALUE(IST_TensionDeltaDissWork, 147) \ + ENUM_ITEM_WITH_VALUE(IST_ShearDissWork, 148) \ + ENUM_ITEM_WITH_VALUE(IST_ShearDeltaDissWork, 149) \ + ENUM_ITEM_WITH_VALUE(IST_CompressionDissWork, 150) \ + ENUM_ITEM_WITH_VALUE(IST_CompressionDeltaDissWork, 151) + /** * Type representing the physical meaning of element or constitutive model internal variable. * Values of this type are used, when these internal variables are requested. diff --git a/src/oofemlib/interpolatingfunction.C b/src/oofemlib/interpolatingfunction.C index bc7e545fb..b00c0338a 100644 --- a/src/oofemlib/interpolatingfunction.C +++ b/src/oofemlib/interpolatingfunction.C @@ -53,14 +53,17 @@ InterpolatingFuction :: ~InterpolatingFuction() void InterpolatingFuction :: evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp, double param) { + double randomVariable = 0.; + auto it = valDict.find("x"); if ( it == valDict.end() ) { OOFEM_ERROR("Coordinate needed for evaluating function"); } const FloatArray &globalCoordinates = it->second.val1; + + if(this->dimension == 2){//2D Case // Map the corresponding random value from the field int countXDown = 0, countXUp = 0, countYDown = 0, countYUp = 0; - double randomVariable = 0.; //Determine x count double helpX = 0., helpY = 0.; int i = 0, exitFlag = 0; @@ -123,9 +126,120 @@ InterpolatingFuction :: evaluate(FloatArray &answer, const std :: map< std :: st ( 1. - helpX ) * helpY * field(3 * ( countXDown * numberReal(1) + countYUp ) + 2); } } + } + else if(this->dimension == 3){//3D case + // Map the corresponding random value from the field + int countXDown = 0, countXUp = 0, countYDown = 0, countYUp = 0, countZDown = 0, countZUp = 0; + //Determine x count + double helpX = 0., helpY = 0., helpZ = 0.; + int i = 0, exitFlag = 0; - if ( randomVariable <= 0. ) { - randomVariable = 1.e-8; + //Check if gp lies in random field + double randomXStart = field.at(1); + double randomXEnd = field(4 * ( numberReal.at(1)*numberReal.at(2)*numberReal.at(3) - 1 )); + double randomYStart = field.at(2); + double randomYEnd = field(4 * ( numberReal.at(1)*numberReal.at(2)*numberReal.at(3) - 1 ) + 1); + double randomZStart = field.at(3); + double randomZEnd = field(4 * ( numberReal.at(1)*numberReal.at(2)*numberReal.at(3) - 1 ) + 2); + + double fieldX0Y0Z0, fieldX1Y0Z0, fieldX0Y1Z0, fieldX0Y0Z1, fieldX1Y1Z0, fieldX1Y1Z1, fieldX0Y1Z1, fieldX1Y0Z1; + double field00, field01, field10, field11; + double field0,field1; + + if ( !( globalCoordinates.at(1) >= randomXStart && globalCoordinates.at(1) <= randomXEnd && + globalCoordinates.at(2) >= randomYStart && globalCoordinates.at(2) <= randomYEnd && + globalCoordinates.at(3) >= randomZStart && globalCoordinates.at(3) <= randomZEnd ) ) { + randomVariable = 1; + printf("Warning: External field too small\n"); + } else { + //Determine the corner points of the square over which we are going to interpolate + //Determine xCount + while ( exitFlag == 0 ) { + if ( field.at( 4 * i * numberReal.at(2)*numberReal.at(3) +1) > globalCoordinates.at(1) ) { + if ( i == 0 ) { //Check soundness + OOFEM_ERROR("error in externalfieldgenerator.C: i is zero"); + } else if ( i > numberReal.at(1) ) { + OOFEM_ERROR("error in externalfieldgenerator.C: i is greater than realNumber1"); + } + + exitFlag = 1; + countXDown = i - 1; + countXUp = i; + helpX = ( globalCoordinates.at(1) - field.at( 4 * countXDown * numberReal.at(2) * numberReal.at(3)+1 ) ) + / ( field.at( 4 * countXUp * numberReal.at(2) * numberReal.at(3)+1 ) - field.at( 4 * countXDown * numberReal.at(2) * numberReal.at(3) +1) ); + } + + i++; + } + + //Determine y count + i = 0, exitFlag = 0; + while ( exitFlag == 0 ) { + if ( field.at(4 *i*numberReal.at(3) + 2) > globalCoordinates.at(2) ) { + if ( i == 0 ) { + OOFEM_ERROR("error in externalfieldgenerator.C: i is zero"); + } else if ( i > numberReal.at(2) ) {//Not sure that this is a problem + OOFEM_ERROR("error in externalfieldgenerator.C: i is greater than realNumber2"); + } + + exitFlag = 1; + countYDown = i - 1; + countYUp = i; + helpY = ( globalCoordinates.at(2) - field.at(4 * countYDown*numberReal.at(3) + 2) ) + / ( field.at(4 * countYUp*numberReal.at(3) + 2) - field.at(4 * countYDown*numberReal.at(3) + 2) ); + } + + i++; + } + + + //Determine z count + i = 0, exitFlag = 0; + while ( exitFlag == 0 ) { + if ( field.at(4 * i + 3) > globalCoordinates.at(3) ) { + if ( i == 0 ) { + OOFEM_ERROR("error in externalfieldgenerator.C: i is zero"); + } else if ( i > numberReal.at(3) ) { + OOFEM_ERROR("error in externalfieldgenerator.C: i is equal to realNumber"); + } + + exitFlag = 1; + countZDown = i - 1; + countZUp = i; + helpZ = ( globalCoordinates.at(3) - field.at(4 * countZDown + 3) ) + / ( field.at(4 * countZUp + 3) - field.at(4 * countZDown + 3) ); + } + + i++; + } + + + //Do the interpolation in 3D. + if ( randomVariable == 0. ) { + + fieldX0Y0Z0 = field.at(4 * ( countXDown * numberReal.at(2)*numberReal.at(3) + countYDown*numberReal.at(3) + countZDown ) + 4); + fieldX1Y0Z0 = field.at(4 * ( countXUp * numberReal.at(2)*numberReal.at(3) + countYDown*numberReal.at(3) + countZDown ) + 4); + fieldX0Y1Z0 = field.at(4 * ( countXDown * numberReal.at(2)*numberReal.at(3) + countYUp*numberReal.at(3) + countZDown ) + 4); + fieldX0Y0Z1 = field.at(4 * ( countXDown * numberReal.at(2)*numberReal.at(3) + countYDown*numberReal.at(3) + countZUp ) + 4); + fieldX1Y1Z0 = field.at(4 * ( countXUp * numberReal.at(2)*numberReal.at(3) + countYUp*numberReal.at(3) + countZDown ) + 4); + fieldX1Y1Z1 = field.at(4 * ( countXUp * numberReal.at(2)*numberReal.at(3) + countYUp*numberReal.at(3) + countZUp ) + 4); + fieldX0Y1Z1 = field.at(4 * ( countXDown * numberReal.at(2)*numberReal.at(3) + countYUp*numberReal.at(3) + countZUp ) + 4); + fieldX1Y0Z1 = field.at(4 * ( countXUp * numberReal.at(2)*numberReal.at(3) + countYDown*numberReal.at(3) + countZUp ) + 4); + + field00 = fieldX0Y0Z0 * (1. - helpX) + fieldX1Y0Z0 * helpX; + field10 = fieldX0Y1Z0 * (1. - helpX) + fieldX1Y1Z0 * helpX; + field01 = fieldX0Y0Z1 * (1. - helpX) + fieldX1Y0Z1 * helpX; + field11 = fieldX0Y1Z1 * (1. - helpX) + fieldX1Y1Z1 * helpX; + + field0 = field00 * (1.-helpY) + field10*helpY; + field1 = field01 * (1.-helpY) + field11*helpY; + + randomVariable = field0*(1. - helpZ) + field1*helpZ; + } + } + } + else{ + OOFEM_ERROR("Unknown dimension. Must be 2 or 3."); } answer = FloatArray{randomVariable}; @@ -140,34 +254,47 @@ InterpolatingFuction :: evaluateAtTime(double t) -IRResultType -InterpolatingFuction :: initializeFrom(InputRecord *ir) +void +InterpolatingFuction :: initializeFrom(InputRecord &ir) { std :: string name; - IRResultType result; // Required by IR_GIVE_FIELD macro + + this->dimension = 2; + IR_GIVE_OPTIONAL_FIELD(ir, dimension, _IFT_InterpolatingFuction_dim); IR_GIVE_FIELD(ir, name, _IFT_InterpolatingFuction_filename); std :: ifstream inputField( name.c_str() ); if ( !inputField.is_open() ) { - OOFEM_WARNING("Unable to open file %s", name.c_str()); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_InterpolatingFuction_filename, "Unable to open file: " + name); } - double deltaX, deltaY; - numberReal.resize(2); - numberReal.zero(); - inputField >> numberReal(0) >> numberReal(1) >> deltaX >> deltaY; + if(this->dimension == 2){//2D field + double deltaX, deltaY; + numberReal.resize(2); + numberReal.zero(); + inputField >> numberReal(0) >> numberReal(1) >> deltaX >> deltaY; + field.resize( 3 * numberReal(0) * numberReal(1) ); + field.zero(); - field.resize( 3 * numberReal(0) * numberReal(1) ); - field.zero(); - - //Read in coordinates and field values - for ( int i = 0; i < numberReal(0) * numberReal(1); i++ ) { + //Read in coordinates and field values + for ( int i = 0; i < numberReal(0) * numberReal(1); i++ ) { inputField >> field(3 * i) >> field(3 * i + 1) >> field(3 * i + 2); + } } + else{//3D field + double deltaX, deltaY, deltaZ; + numberReal.resize(3); + numberReal.zero(); + inputField >> numberReal(0) >> numberReal(1) >> numberReal(2) >> deltaX >> deltaY >> deltaZ; + field.resize( 4 * numberReal.at(1) * numberReal.at(2) * numberReal.at(3) ); + field.zero(); - return IRRT_OK; + //Read in coordinates and field values + for ( int i = 0; i < numberReal.at(1) * numberReal.at(2) * numberReal.at(3) ; i++ ) { + inputField >> field.at(4 * i+1) >> field.at(4 * i + 2) >> field.at(4 * i + 3) >> field.at(4 * i + 4); + } + } } } // end namespace oofem diff --git a/src/oofemlib/interpolatingfunction.h b/src/oofemlib/interpolatingfunction.h index 1ee3968f4..f1a1b2711 100644 --- a/src/oofemlib/interpolatingfunction.h +++ b/src/oofemlib/interpolatingfunction.h @@ -41,6 +41,7 @@ //@{ #define _IFT_InterpolatingFuction_Name "interpolatingfunction" #define _IFT_InterpolatingFuction_filename "name" +#define _IFT_InterpolatingFuction_dim "dim" //@} namespace oofem { @@ -53,6 +54,7 @@ class OOFEM_EXPORT InterpolatingFuction : public Function protected: FloatArray field; IntArray numberReal; + int dimension; public: /// Constructor @@ -60,14 +62,14 @@ class OOFEM_EXPORT InterpolatingFuction : public Function /// Destructor virtual ~InterpolatingFuction(); - virtual void evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp=NULL, double param=0.); - virtual double evaluateAtTime(double t); - virtual double evaluateVelocityAtTime(double t) { return 0.; } - virtual double evaluateAccelerationAtTime(double t) { return 0.; } + void evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp=nullptr, double param=0.) override; + double evaluateAtTime(double t) override; + double evaluateVelocityAtTime(double t) override { return 0.; } + double evaluateAccelerationAtTime(double t) override { return 0.; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "InterpolatingFuction"; } - virtual const char *giveInputRecordName() const { return _IFT_InterpolatingFuction_Name; } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "InterpolatingFuction"; } + const char *giveInputRecordName() const override { return _IFT_InterpolatingFuction_Name; } }; } // end namespace oofem diff --git a/src/oofemlib/intvarfield.C b/src/oofemlib/intvarfield.C index 438f72e5c..e8a27d5aa 100644 --- a/src/oofemlib/intvarfield.C +++ b/src/oofemlib/intvarfield.C @@ -39,24 +39,16 @@ namespace oofem { InternalVariableField :: InternalVariableField(InternalStateType ist, FieldType ft, MaterialMappingAlgorithmType mma_type, Domain *d) : - Field(ft) -{ - this->type = ist; - this->mma = classFactory.createMaterialMappingAlgorithm(mma_type); - this->domain = d; -} - -InternalVariableField :: ~InternalVariableField() -{ - if ( mma ) { - delete mma; - } -} + Field(ft), + mma(classFactory.createMaterialMappingAlgorithm(mma_type)), + type(ist), + domain(d) +{} int InternalVariableField :: evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) { - IntArray types(1); + IntArray types; types.at(1) = this->type; /// Use MaterialMappingAlgorithm classes to do the job Set eset(0, domain); @@ -70,22 +62,14 @@ InternalVariableField :: evaluateAt(FloatArray &answer, const FloatArray &coords int InternalVariableField :: evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) { - if ( dman->hasCoordinates() ) { - return this->evaluateAt(answer, * ( dman->giveCoordinates() ), mode, tStep); - } else { - return 1; // failed -> dman without coordinates - } + return this->evaluateAt(answer, dman->giveCoordinates(), mode, tStep); } -contextIOResultType -InternalVariableField :: saveContext(DataStream &stream, ContextMode mode) -{ - return CIO_OK; -} +void +InternalVariableField :: saveContext(DataStream &stream) +{} -contextIOResultType -InternalVariableField :: restoreContext(DataStream &stream, ContextMode mode) -{ - return CIO_OK; -} +void +InternalVariableField :: restoreContext(DataStream &stream) +{} } // end namespace oofem diff --git a/src/oofemlib/intvarfield.h b/src/oofemlib/intvarfield.h index edcb83d42..ba52b7013 100644 --- a/src/oofemlib/intvarfield.h +++ b/src/oofemlib/intvarfield.h @@ -38,6 +38,7 @@ #include "field.h" #include "materialmappingalgorithmtype.h" #include "internalstatetype.h" +#include "materialmappingalgorithm.h" namespace oofem { class Domain; @@ -57,7 +58,7 @@ class OOFEM_EXPORT InternalVariableField : public Field { protected: /// Material mapping algorithm used. - MaterialMappingAlgorithm *mma; + std::unique_ptr mma; /// InternalStateType. InternalStateType type; /// Source domain. @@ -72,14 +73,14 @@ class OOFEM_EXPORT InternalVariableField : public Field * @param d Domain which field belongs to. */ InternalVariableField(InternalStateType ist, FieldType b, MaterialMappingAlgorithmType mma_type, Domain * d); - virtual ~InternalVariableField(); + virtual ~InternalVariableField() {} - virtual int evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep); - virtual int evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep); + int evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) override; + int evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode); - virtual const char *giveClassName() const { return "InternalVariableField"; } + void saveContext(DataStream &stream) override; + void restoreContext(DataStream &stream) override; + const char *giveClassName() const override { return "InternalVariableField"; } }; } // end namespace oofem #endif // intvarfield_h diff --git a/src/oofemlib/inverseit.C b/src/oofemlib/inverseit.C index cdbd9749f..9033de232 100644 --- a/src/oofemlib/inverseit.C +++ b/src/oofemlib/inverseit.C @@ -41,25 +41,25 @@ #include "classfactory.h" namespace oofem { +REGISTER_GeneralizedEigenValueSolver(InverseIteration, GES_InverseIt); + InverseIteration :: InverseIteration(Domain *d, EngngModel *m) : - SparseGeneralEigenValueSystemNM(d, m) + SparseGeneralEigenValueSystemNM(d, m), + nitem(100) { - nitem = 100; // max number of iterations } -InverseIteration :: ~InverseIteration() { } - NM_Status -InverseIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, FloatMatrix &_r, double rtol, int nroot) +InverseIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &eigv, FloatMatrix &r, double rtol, int nroot) { if ( a.giveNumberOfColumns() != b.giveNumberOfColumns() ) { OOFEM_ERROR("matrices size mismatch"); } - SparseLinearSystemNM *solver = GiveClassFactory().createSparseLinSolver(ST_Direct, domain, engngModel); - + auto solver = GiveClassFactory().createSparseLinSolver(ST_Direct, domain, engngModel); + int nn = a.giveNumberOfColumns(); int nc = min(2 * nroot, nroot + 8); nc = min(nc, nn); @@ -158,11 +158,11 @@ InverseIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, Float order.enumerate(w.giveSize()); std :: sort(order.begin(), order.end(), [&w](int a, int b) { return w.at(a) < w.at(b); }); - _eigv.resize(nroot); - _r.resize(nn, nroot); + eigv.resize(nroot); + r.resize(nn, nroot); for ( int i = 1; i <= nroot; i++ ) { - _eigv.at(i) = w.at(order.at(i)); - _r.setColumn(x[order.at(i) - 1], i); + eigv.at(i) = w.at(order.at(i)); + r.setColumn(x[order.at(i) - 1], i); } if ( it < nitem ) { diff --git a/src/oofemlib/inverseit.h b/src/oofemlib/inverseit.h index b3d5dcf46..41451ff8d 100644 --- a/src/oofemlib/inverseit.h +++ b/src/oofemlib/inverseit.h @@ -32,17 +32,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -// ************************************************** -// *** CLASS GENERALIZED INVERSE ITERATION SOLVER *** -// ************************************************** - - #ifndef inverseit_h #define inverseit_h #include "sparsegeneigenvalsystemnm.h" #include "floatarray.h" +#define _IFT_InverseIteration_Name "inverseit" + namespace oofem { class Domain; class EngngModel; @@ -84,14 +81,15 @@ class EngngModel; class OOFEM_EXPORT InverseIteration : public SparseGeneralEigenValueSystemNM { private: + /// Max number of iterations int nitem; public: InverseIteration(Domain * d, EngngModel * m); - virtual ~InverseIteration(); + virtual ~InverseIteration() {} - virtual NM_Status solve(SparseMtrx &A, SparseMtrx &B, FloatArray &x, FloatMatrix &v, double rtol, int nroot); - virtual const char *giveClassName() const { return "InverseIteration"; } + NM_Status solve(SparseMtrx &A, SparseMtrx &B, FloatArray &x, FloatMatrix &v, double rtol, int nroot) override; + const char *giveClassName() const override { return "InverseIteration"; } }; } // end namespace oofem #endif // inverseit_h diff --git a/src/oofemlib/latticedirichletcouplingnode.C b/src/oofemlib/latticedirichletcouplingnode.C new file mode 100644 index 000000000..d7fa54ccb --- /dev/null +++ b/src/oofemlib/latticedirichletcouplingnode.C @@ -0,0 +1,237 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticedirichletcouplingnode.h" +#include "dof.h" +#include "slavedof.h" +#include "simpleslavedof.h" +#include "nodalload.h" +#include "timestep.h" + +#include "floatarray.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "verbose.h" +#include "datastream.h" +#include "contextioerr.h" +#include "staggeredproblem.h" + +#ifdef __SM_MODULE + #include "../sm/Elements/LatticeElements/latticestructuralelement.h" +#endif + +#include +#include +#include "classfactory.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { + + REGISTER_DofManager(LatticeDirichletCouplingNode); + +LatticeDirichletCouplingNode :: LatticeDirichletCouplingNode(int n, Domain *aDomain) : + Node(n, aDomain) +{} + +LatticeDirichletCouplingNode :: ~LatticeDirichletCouplingNode() +// Destructor. +{} + +void +LatticeDirichletCouplingNode :: initializeFrom(InputRecord &ir) +// Gets from the source line from the data file all the data of the receiver. +{ + FloatArray triplets; + + Node :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, couplingElements, _IFT_LatticeDirichletCouplingNode_couplingelements); + +} + +void LatticeDirichletCouplingNode :: printYourself() +// Prints the receiver on screen. +{ + int i; + double x, y; + + x = this->giveCoordinate(1); + y = this->giveCoordinate(2); + printf("LatticeDirichletCouplingNode %d coord : x %f y %f\n", number, x, y); + for ( i = 0; i < this->giveNumberOfDofs(); i++ ) { + if ( dofArray [ i ] ) { + dofArray [ i ]->printYourself(); + } else { + printf("dof %d is nil \n", i + 1); + } + } + + loadArray.printYourself(); + printf("\n"); +} + +void +LatticeDirichletCouplingNode :: giveUnknownVector(FloatArray &answer, const IntArray &dofIDArry, ValueModeType mode, TimeStep *tStep, bool padding) +//giveUnknownVector(FloatArray &answer, const IntArray &dofMask, ValueModeType mode, TimeStep *stepN) +{ + + int size; + IntArray dofArray; + + answer.resize( size = dofIDArry.giveSize() ); + + for ( int i = 1; i <= size; i++ ) { + auto pos = this->findDofWithDofId( ( DofIDItem ) dofIDArry.at(i) ); +#ifdef DEBUG + if ( pos == this->end() ) { + OOFEM_ERROR("Couldn't find dof with Dof ID %d", dofIDArry.at(i)); + } +#endif + answer.at(i) = (*pos)->giveUnknown(mode, tStep); + activedirichletbc = computeUnknownCouplingContribution(tStep); + answer.at(i) += activedirichletbc; + + } + + // Transform to global c.s. + FloatMatrix L2G; + if ( this->computeL2GTransformation(L2G, dofIDArry) ) { + answer.rotatedWith(L2G, 'n'); + } + + + // if ( !hasSlaveDofs ) { + // int j, size; + // IntArray dofArray; + // this->activedirichletbc = 0; + // answer.resize( size = dofMask.giveSize() ); + // this->giveDofArray(dofMask, dofArray); + + // for ( j = 1; j <= size; j++ ) { + // answer.at(j) = this->giveDof( dofArray.at(j) )->giveUnknown(mode, stepN); + + // activedirichletbc = computeUnknownCouplingContribution(stepN); + + // answer.at(j) += activedirichletbc; + // } + // } else { + // int i, k, indx; + // IntArray dofArray; + // FloatArray mstrUnknwns; + + // this->giveDofArray(dofMask, dofArray); + // answer.resize( giveNumberOfPrimaryMasterDofs(dofArray) ); + + // for ( k = 1, i = 1; i <= dofArray.giveSize(); i++ ) { + // indx = dofArray.at(i); + // if ( !this->giveDof(indx)->isPrimaryDof() ) { // slave DOF + // this->giveDof(indx)->giveUnknowns(mstrUnknwns, mode, stepN); + // answer.copySubVector(mstrUnknwns, k); + // k += mstrUnknwns.giveSize(); + // } else { + // answer.at(k++) = this->giveDof(indx)->giveUnknown(mode, stepN); + // } + // } + // } +} + +double +LatticeDirichletCouplingNode :: computeUnknownCouplingContribution(TimeStep *stepN) { + double distance = 0.; + double result = 0.; + + int nCouplingElements = couplingElements.giveSize(); + + FloatArray couplingGpCoords; + double normalStress; + + double nominator = 0; + double denominator = 0; + +#ifdef __SM_MODULE + IntArray coupledModels; + if ( domain->giveEngngModel()->giveMasterEngngModel() ) { + ( static_cast< StaggeredProblem * >( domain->giveEngngModel()->giveMasterEngngModel() ) )->giveCoupledModels(coupledModels); + if ( coupledModels.at(1) != 0 && !(stepN->giveNumber()<=domain->giveEngngModel()->giveNumberOfFirstStep()) ) { + LatticeStructuralElement *coupledElement; + for ( int i = 1; i <= nCouplingElements; i++ ) { + couplingGpCoords.zero(); + coupledElement = static_cast< LatticeStructuralElement * >( domain->giveEngngModel()->giveMasterEngngModel()->giveSlaveProblem( coupledModels.at(1) )->giveDomain(1)->giveElement( couplingElements.at(i) ) ); + + coupledElement->giveGpCoordinates(couplingGpCoords); + if(coupledElement->hasBeenUpdated() == 1){ + normalStress = coupledElement->giveOldNormalStress(); + } + else{ + normalStress = coupledElement->giveNormalStress(); + } + + if(normalStress > 0.){ + normalStress = 0.; + } + + distance = sqrt( pow(couplingGpCoords.at(1) - coordinates.at(1), 2.) + pow(couplingGpCoords.at(2) - coordinates.at(2), 2.) ); + + nominator = nominator + distance * normalStress; + denominator = denominator + distance; + } + + result = nominator / denominator; + } + +#endif +} + +return result; +} + +void LatticeDirichletCouplingNode :: printOutputAt(FILE *stream, TimeStep *stepN) +{ + int i; + +#if defined( __PARALLEL_MODE ) || defined( __ENABLE_COMPONENT_LABELS ) + fprintf( stream, "%-8s%8d (%8d):\n", this->giveClassName(), this->giveLabel(), this->giveNumber() ); +#else + fprintf( stream, "%-8s%8d:\n", this->giveClassName(), this->giveGlobalNumber() ); +#endif + + for ( i = 1; i <= this->giveNumberOfDofs(); i++ ) { + fprintf(stream, " dof %d f % .16e\n", this->giveGlobalNumber(), activedirichletbc); + } +} + +} // end namespace oofem diff --git a/src/oofemlib/latticedirichletcouplingnode.h b/src/oofemlib/latticedirichletcouplingnode.h new file mode 100644 index 000000000..4cc66172d --- /dev/null +++ b/src/oofemlib/latticedirichletcouplingnode.h @@ -0,0 +1,96 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticedirichletcouplingnode_h +#define latticedirichletcouplingnode_h + +#include "node.h" +#include "domain.h" +#include "floatarray.h" + + +///@name Input fields for LatticeCouplingNode +//@{ +#define _IFT_LatticeDirichletCouplingNode_Name "latticedirichletcouplingnode" +#define _IFT_LatticeDirichletCouplingNode_couplingelements "couplingelements" +//@} + +namespace oofem { +class Node; +class Dof; +class NodalLoad; +class TimeStep; +class FloatArray; +class IntArray; + +/** + * Class implementing lattice coupling node + * This DOF manager is based on the standard node but allows to read + * in associated DOFs and elements which are used to calculated coupling forces + */ + +class LatticeDirichletCouplingNode : public Node +{ +protected: + /// Array storing nodal coordinates. + IntArray couplingElements; //IntArray used here cause the element numbers are all whole numbers (integers) instead of using a float array . + int couplingType; + double activedirichletbc; + +public: + + LatticeDirichletCouplingNode(int n, Domain *aDomain); // constructor + + ~LatticeDirichletCouplingNode(); // destructor + + const char *giveClassName() const override { return "LatticeDirichletCouplingNode"; } + void initializeFrom(InputRecord &ir) override; + + IntArray *giveCouplingNodes(); + + IntArray *giveCouplingElements(); + + virtual void giveUnknownVector(FloatArray &answer, const IntArray &dofMask, ValueModeType mode, TimeStep *stepN, bool padding = false); + + double giveUnknown(ValueModeType mode, TimeStep *stepN); + + double computeUnknownCouplingContribution(TimeStep *stepN); + + void printOutputAt(FILE *stream, TimeStep *stepN) override; + + void printYourself() override; +}; +} // end namespace oofem + +#endif // latticedirichletcouplingnode_h diff --git a/src/oofemlib/latticeneumanncouplingnode.C b/src/oofemlib/latticeneumanncouplingnode.C new file mode 100644 index 000000000..998acfd94 --- /dev/null +++ b/src/oofemlib/latticeneumanncouplingnode.C @@ -0,0 +1,167 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticeneumanncouplingnode.h" +#include "dof.h" +#include "slavedof.h" +#include "simpleslavedof.h" +#include "nodalload.h" +#include "timestep.h" + +#include "floatarray.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "verbose.h" +#include "datastream.h" +#include "contextioerr.h" +#include "staggeredproblem.h" + +#ifdef __SM_MODULE + #include "../sm/Elements/LatticeElements/latticestructuralelement.h" +#endif + +#include +#include +#include "classfactory.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { +REGISTER_DofManager(LatticeNeumannCouplingNode); + +LatticeNeumannCouplingNode :: LatticeNeumannCouplingNode(int n, Domain *aDomain) : + Node(n, aDomain), directionVector(), couplingNodes() +{} + +LatticeNeumannCouplingNode :: ~LatticeNeumannCouplingNode() +// Destructor. +{} + +void +LatticeNeumannCouplingNode :: initializeFrom(InputRecord &ir) +// Gets from the source line from the data file all the data of the receiver. +{ + FloatArray triplets; + + Node :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, directionVector, _IFT_LatticeNeumannCouplingNode_direction); + IR_GIVE_FIELD(ir, couplingNodes, _IFT_LatticeNeumannCouplingNode_couplingnodes); +} + + +void +LatticeNeumannCouplingNode :: computeLoadVectorAt(FloatArray &answer, TimeStep *stepN, ValueModeType mode) +// Computes the vector of the nodal loads of the receiver. +{ + FloatArray contribution; + + if ( this->giveLoadArray()->isEmpty() ) { + answer.resize(0); + } else { + answer.resize(0); + int nLoads = loadArray.giveSize(); // the node may be subjected + for ( int i = 1; i <= nLoads; i++ ) { // to more than one load + int n = loadArray.at(i); + Load *loadN = domain->giveLoad(n); + computeLoadVector(contribution, loadN, ExternalForcesVector, stepN, mode); + answer.add(contribution); + } + } + + computeLoadCouplingContribution(contribution, stepN); + answer.add(contribution); +} + +void LatticeNeumannCouplingNode :: printYourself() +// Prints the receiver on screen. +{ + int i; + double x, y; + + x = this->giveCoordinate(1); + y = this->giveCoordinate(2); + printf("LatticeNeumannCouplingNode %d coord : x %f y %f\n", number, x, y); + for ( i = 0; i < this->giveNumberOfDofs(); i++ ) { + if ( dofArray [ i ] ) { + dofArray [ i ]->printYourself(); + } else { + printf("dof %d is nil \n", i + 1); + } + } + + loadArray.printYourself(); + printf("\n"); +} + +void +LatticeNeumannCouplingNode :: computeLoadCouplingContribution(FloatArray &answer, TimeStep *stepN) { + int nCouplingNodes = couplingNodes.giveSize(); + + FloatArray contribution; + answer.resize(this->directionVector.giveSize() ); + + IntArray coupledModels; + double waterPressureNew = 0., waterPressureOld = 0.; + + if ( domain->giveEngngModel()->giveMasterEngngModel() ) { + ( static_cast< StaggeredProblem * >( domain->giveEngngModel()->giveMasterEngngModel() ) )->giveCoupledModels(coupledModels); + if ( coupledModels.at(2) != 0 && !( stepN->giveNumber() <= domain->giveEngngModel()->giveNumberOfFirstStep() ) ) { + for ( int k = 0; k < nCouplingNodes; k++ ) { + Node *coupledNode = domain->giveEngngModel()->giveMasterEngngModel()->giveSlaveProblem(coupledModels.at(2) )->giveDomain(1)->giveNode(couplingNodes(k) ); + const auto &couplingCoords = coupledNode->giveCoordinates(); + TimeStep *previousStep = domain->giveEngngModel()->giveMasterEngngModel()->givePreviousStep(); + + waterPressureNew = coupledNode->giveDofWithID(P_f)->giveUnknown(VM_Total, stepN); + if ( !stepN->givePreviousStep()->isTheFirstStep() ) { + waterPressureOld = coupledNode->giveDofWithID(P_f)->giveUnknown(VM_Total, previousStep); + } else { + waterPressureOld = 0.; + } + + double waterPressure = waterPressureNew - waterPressureOld; + double dist = distance(couplingCoords, coordinates); + double factor = waterPressure * dist; + contribution = this->directionVector; + contribution.times(factor); + answer.add(contribution); + } + } + } + + return; +} +} diff --git a/src/oofemlib/latticeneumanncouplingnode.h b/src/oofemlib/latticeneumanncouplingnode.h new file mode 100644 index 000000000..215e58543 --- /dev/null +++ b/src/oofemlib/latticeneumanncouplingnode.h @@ -0,0 +1,90 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticeneumanncouplingnode_h +#define latticeneumanncouplingnode_h + +#include "node.h" +#include "domain.h" +#include "floatarray.h" + + +///@name Input fields for LatticeCouplingNode +//@{ +#define _IFT_LatticeNeumannCouplingNode_Name "latticeneumanncouplingnode" +#define _IFT_LatticeNeumannCouplingNode_direction "direction" +#define _IFT_LatticeNeumannCouplingNode_couplingnodes "couplingnodes" +//@} + +namespace oofem { +class Node; +class Dof; +class NodalLoad; +class TimeStep; +class FloatArray; +class IntArray; + +/** + * Class implementing lattice coupling node + * This DOF manager is based on the standard node but allows to read + * in associated DOFs and elements which are used to calculated coupling forces + */ + +class LatticeNeumannCouplingNode : public Node +{ +protected: + /// Array storing nodal coordinates. + FloatArray directionVector; + IntArray couplingNodes; + +public: + + LatticeNeumannCouplingNode(int n, Domain *aDomain); // constructor + + ~LatticeNeumannCouplingNode(); // destructor + + virtual void computeLoadVectorAt(FloatArray &answer, TimeStep *stepN, ValueModeType mode); + + const char *giveClassName() const override { return "LatticeNeumannCouplingNode"; } + void initializeFrom(InputRecord &ir) override; + + IntArray *giveCouplingNodes(); + + void computeLoadCouplingContribution(FloatArray &answer, TimeStep *stepN); + + void printYourself() override; +}; +} // end namespace oofem + +#endif // latticecouplingnode_h diff --git a/src/oofemlib/ldltfact.h b/src/oofemlib/ldltfact.h index 33ba11553..5bfba5e9a 100644 --- a/src/oofemlib/ldltfact.h +++ b/src/oofemlib/ldltfact.h @@ -32,12 +32,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -// ****************************************** -// *** CLASS LDL^T Factorization *** -// ****************************************** - - #ifndef ldltfact_h #define ldltfact_h @@ -45,6 +39,8 @@ #include "sparsemtrx.h" #include "floatarray.h" +#define _IFT_LDLTFactorization_Name "direct" + namespace oofem { class Domain; class EngngModel; @@ -57,8 +53,6 @@ class FloatMatrix; */ class OOFEM_EXPORT LDLTFactorization : public SparseLinearSystemNM { -private: - public: /// Constructor - creates new instance of LDLTFactorization, with number i, belonging to domain d and Engngmodel m. LDLTFactorization(Domain * d, EngngModel * m); @@ -74,11 +68,11 @@ class OOFEM_EXPORT LDLTFactorization : public SparseLinearSystemNM * @param x solution array * @return NM_Status value */ - virtual NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x); + NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x) override; - virtual const char *giveClassName() const { return "LDLTFactorization"; } - virtual LinSystSolverType giveLinSystSolverType() const { return ST_Direct; } - virtual SparseMtrxType giveRecommendedMatrix(bool symmetric) const { return symmetric ? SMT_Skyline : SMT_SkylineU; } + const char *giveClassName() const override { return "LDLTFactorization"; } + LinSystSolverType giveLinSystSolverType() const override { return ST_Direct; } + SparseMtrxType giveRecommendedMatrix(bool symmetric) const override { return symmetric ? SMT_Skyline : SMT_SkylineU; } }; } // end namespace oofem #endif // ldltfact_h diff --git a/src/oofemlib/linearconstraintbc.C b/src/oofemlib/linearconstraintbc.C index fa58390a2..b97786b15 100644 --- a/src/oofemlib/linearconstraintbc.C +++ b/src/oofemlib/linearconstraintbc.C @@ -45,6 +45,10 @@ #include "node.h" #include "domain.h" +#ifdef _OPENMP +#include +#endif + namespace oofem { REGISTER_BoundaryCondition(LinearConstraintBC); @@ -64,9 +68,9 @@ LinearConstraintBC :: ~LinearConstraintBC() } -IRResultType LinearConstraintBC :: initializeFrom(InputRecord *ir) +void LinearConstraintBC :: initializeFrom(InputRecord &ir) { - IRResultType result; + ActiveBoundaryCondition :: initializeFrom(ir); rhsTf = 0; IR_GIVE_FIELD(ir, weights, _IFT_LinearConstraintBC_weights); @@ -74,16 +78,13 @@ IRResultType LinearConstraintBC :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, dofmans, _IFT_LinearConstraintBC_dofmans); IR_GIVE_FIELD(ir, dofs, _IFT_LinearConstraintBC_dofs); if ( weights.giveSize() != dofmans.giveSize() ) { - OOFEM_WARNING("Size mismatch, weights %d and dofmans %d", weights.giveSize(), dofmans.giveSize()); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_LinearConstraintBC_weights, "Size mismatch weights and dofmans"); } IR_GIVE_OPTIONAL_FIELD(ir, weightsTf, _IFT_LinearConstraintBC_weightsfuncs); IR_GIVE_OPTIONAL_FIELD(ir, rhsTf, _IFT_LinearConstraintBC_rhsfuncs); IR_GIVE_FIELD(ir, lhsType, _IFT_LinearConstraintBC_lhstype); IR_GIVE_FIELD(ir, rhsType, _IFT_LinearConstraintBC_rhstype); - - return ActiveBoundaryCondition :: initializeFrom(ir); } @@ -104,7 +105,8 @@ void LinearConstraintBC :: giveLocArray(const UnknownNumberingScheme &r_s, IntA void LinearConstraintBC :: assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, const UnknownNumberingScheme &r_s, - const UnknownNumberingScheme &c_s, double scale) + const UnknownNumberingScheme &c_s, double scale, + void*lock) { int size = this->weights.giveSize(); IntArray lambdaeq(1); @@ -127,22 +129,35 @@ void LinearConstraintBC :: assemble(SparseMtrx &answer, TimeStep *tStep, contribt.times(scale); contribt.beTranspositionOf(contrib); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(lambdaeq, locr, contribt); answer.assemble(locr, lambdaeq, contrib); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } else { // the bc is not imposed at specific time step, however in order to make the equation system regular // we initialize the allocated equation to the following form 1*labmda = 0, forcing lagrange multiplier // of inactive condition to be zero. FloatMatrix help(1, 1); help.at(1, 1) = 1.0; +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(lambdaeq, lambdaeq, help); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } void LinearConstraintBC :: assembleVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorms) + const UnknownNumberingScheme &s, + FloatArray *eNorms, + void* lock) { IntArray loc, lambdaeq(1); FloatArray vec(1); @@ -166,10 +181,22 @@ void LinearConstraintBC :: assembleVector(FloatArray &answer, TimeStep *tStep, } idof = this->domain->giveDofManager( this->dofmans.at(_i) )->giveDofWithID( this->dofs.at(_i) ); if ( s.giveDofEquationNumber(idof) ) { +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.at( s.giveDofEquationNumber(idof) ) += mdof->giveUnknown(mode, tStep) * this->weights.at(_i) * factor; +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } if ( s.giveDofEquationNumber( mdof ) ) { +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.at( s.giveDofEquationNumber( mdof ) ) += idof->giveUnknown(mode, tStep) * this->weights.at(_i) * factor; +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } } else if ( type == ExternalForcesVector ) { @@ -180,7 +207,13 @@ void LinearConstraintBC :: assembleVector(FloatArray &answer, TimeStep *tStep, } this->giveLocArray( s, loc, lambdaeq.at(1) ); vec.at(1) = rhs * factor; +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(vec, lambdaeq); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } @@ -203,11 +236,11 @@ void LinearConstraintBC :: giveLocationArrays(std :: vector< IntArray > &rows, s } -contextIOResultType -LinearConstraintBC :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +LinearConstraintBC :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; if ( mode & CM_Definition ) { + contextIOResultType iores; if ( ( iores = weights.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -234,19 +267,15 @@ LinearConstraintBC :: saveContext(DataStream &stream, ContextMode mode, void *ob } } - if ( ( iores = md->saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + md->saveContext(stream, mode); } -contextIOResultType -LinearConstraintBC :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +LinearConstraintBC :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; if ( mode & CM_Definition ) { + contextIOResultType iores; if ( ( iores = weights.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -273,10 +302,6 @@ LinearConstraintBC :: restoreContext(DataStream &stream, ContextMode mode, void } } - if ( ( iores = md->restoreContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + md->restoreContext(stream, mode); } } //end of oofem namespace diff --git a/src/oofemlib/linearconstraintbc.h b/src/oofemlib/linearconstraintbc.h index 979683556..65973f5ae 100644 --- a/src/oofemlib/linearconstraintbc.h +++ b/src/oofemlib/linearconstraintbc.h @@ -93,27 +93,28 @@ class OOFEM_EXPORT LinearConstraintBC : public ActiveBoundaryCondition /// Destructor. virtual ~LinearConstraintBC(); - IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveInputRecordName() const { return _IFT_LinearConstraintBC_Name; } - virtual void assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0); - virtual void assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorms = NULL); - - virtual void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, - CharType type, const UnknownNumberingScheme &r_s, - const UnknownNumberingScheme &c_s); - - /// Gives the number of internal dof managers. - virtual int giveNumberOfInternalDofManagers() { return 1; } - /// Gives an internal dof manager from receiver. - virtual DofManager *giveInternalDofManager(int i) { return this->md.get(); } - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - - virtual const char *giveClassName() const { return "LinearConstraintBC"; } + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_LinearConstraintBC_Name; } + void assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, double scale = 1.0, + void* lock=nullptr) override; + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorms=nullptr, + void*lock=nullptr) override; + + void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, + CharType type, const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s) override; + + int giveNumberOfInternalDofManagers() override { return 1; } + DofManager *giveInternalDofManager(int i) override { return this->md.get(); } + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + + const char *giveClassName() const override { return "LinearConstraintBC"; } protected: void giveLocArray(const UnknownNumberingScheme &r_s, IntArray &locr, int &lambdaeq); diff --git a/src/oofemlib/linearedgeload.C b/src/oofemlib/linearedgeload.C index ee4b7852e..1994a96c6 100644 --- a/src/oofemlib/linearedgeload.C +++ b/src/oofemlib/linearedgeload.C @@ -41,10 +41,10 @@ namespace oofem { REGISTER_BoundaryCondition(LinearEdgeLoad); -IRResultType -LinearEdgeLoad :: initializeFrom(InputRecord *ir) +void +LinearEdgeLoad :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + BoundaryLoad :: initializeFrom(ir); int fType = 0; IR_GIVE_OPTIONAL_FIELD(ir, fType, _IFT_LinearEdgeLoad_formulation); @@ -54,14 +54,11 @@ LinearEdgeLoad :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, startCoords, _IFT_LinearEdgeLoad_startcoord); IR_GIVE_FIELD(ir, endCoords, _IFT_LinearEdgeLoad_endcoord); if ( startCoords.isEmpty() || endCoords.isEmpty() ) { - OOFEM_WARNING("coordinates not specified"); - return IRRT_NOTFOUND; + throw ValueInputException(ir, "sc/ec", "coordinates not specified"); } } else { this->formulation = FT_Entity; } - - return BoundaryLoad :: initializeFrom(ir); } @@ -83,9 +80,8 @@ LinearEdgeLoad :: computeNArray(FloatArray &answer, const FloatArray &coords) co double ksi; if ( formulation == FT_Global ) { - int i; - double length = endCoords.distance(startCoords); - double dl = coords.distance(startCoords); + double length = distance(endCoords, startCoords); + double dl = distance(coords, startCoords); double eta = dl / length; ksi = ( dl - 0.5 * length ) / ( 0.5 * length ); FloatArray dir = endCoords; @@ -98,7 +94,7 @@ LinearEdgeLoad :: computeNArray(FloatArray &answer, const FloatArray &coords) co answer.zero(); } - for ( i = 1; i <= dir.giveSize(); i++ ) { + for ( int i = 1; i <= dir.giveSize(); i++ ) { if ( fabs( startCoords.at(i) + dir.at(i) * eta - coords.at(i) ) > 1.e-6 ) { OOFEM_WARNING("point out of receiver, skipped", 1); answer.resize(2); @@ -109,14 +105,9 @@ LinearEdgeLoad :: computeNArray(FloatArray &answer, const FloatArray &coords) co ksi = coords.at(1); } - double n1, n2; - - n1 = ( 1. - ksi ) * 0.5; - n2 = ( 1. + ksi ) * 0.5; - answer.resize(2); - answer.at(1) = n1; - answer.at(2) = n2; + answer.at(1) = ( 1. - ksi ) * 0.5; + answer.at(2) = ( 1. + ksi ) * 0.5; } } // end namespace oofem diff --git a/src/oofemlib/linearedgeload.h b/src/oofemlib/linearedgeload.h index 35a0ebbee..446f7630a 100644 --- a/src/oofemlib/linearedgeload.h +++ b/src/oofemlib/linearedgeload.h @@ -74,18 +74,19 @@ class OOFEM_EXPORT LinearEdgeLoad : public EdgeLoad public: LinearEdgeLoad(int i, Domain * d) : EdgeLoad(i, d) { } + virtual ~LinearEdgeLoad() { } - virtual int giveApproxOrder() { return 1; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual bcGeomType giveBCGeoType() const { return EdgeLoadBGT; } - virtual FormulationType giveFormulationType() { return formulation; } + int giveApproxOrder() override { return 1; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + bcGeomType giveBCGeoType() const override { return EdgeLoadBGT; } + FormulationType giveFormulationType() override { return formulation; } - virtual const char *giveClassName() const { return "LinearEdgeLoad"; } - virtual const char *giveInputRecordName() const { return _IFT_LinearEdgeLoad_Name; } + const char *giveClassName() const override { return "LinearEdgeLoad"; } + const char *giveInputRecordName() const override { return _IFT_LinearEdgeLoad_Name; } protected: - virtual void computeNArray(FloatArray &answer, const FloatArray &coords) const; + void computeNArray(FloatArray &answer, const FloatArray &coords) const override; }; } // end namespace oofem #endif // linearedgeload_h diff --git a/src/oofemlib/linesearch.C b/src/oofemlib/linesearch.C index dad64ad83..9048e52e4 100644 --- a/src/oofemlib/linesearch.C +++ b/src/oofemlib/linesearch.C @@ -243,11 +243,9 @@ LineSearchNM :: search(int istep, FloatArray &prod, FloatArray &eta, double amp, } } -IRResultType -LineSearchNM :: initializeFrom(InputRecord *ir) +void +LineSearchNM :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - /* default values set in constructor * ls_tolerance = 0.80; * amplifFactor = 2.5; @@ -282,7 +280,5 @@ LineSearchNM :: initializeFrom(InputRecord *ir) //printf ("\nLineSearchNM::initializeFrom: tol=%e, ampl=%e, maxEta=%e\n", // ls_tolerance, amplifFactor,maxEta); - - return IRRT_OK; } } // end namespace oofem diff --git a/src/oofemlib/linesearch.h b/src/oofemlib/linesearch.h index 8f0567d4d..e5e15a8f1 100644 --- a/src/oofemlib/linesearch.h +++ b/src/oofemlib/linesearch.h @@ -88,11 +88,11 @@ class OOFEM_EXPORT LineSearchNM : public NumericalMethod * @param status Linesearch status * @param tStep Time step. */ - virtual NM_Status solve(FloatArray &r, FloatArray &dr, FloatArray &F, FloatArray &R, FloatArray *R0, - IntArray &eqnmask, double lambda, double &etaValue, LS_status &status, TimeStep *tStep); + NM_Status solve(FloatArray &r, FloatArray &dr, FloatArray &F, FloatArray &R, FloatArray *R0, + IntArray &eqnmask, double lambda, double &etaValue, LS_status &status, TimeStep *tStep); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "LineSearchNM"; } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const { return "LineSearchNM"; } protected: void search(int istep, FloatArray &prod, FloatArray &eta, double amp, double maxeta, double mineta, int &status); diff --git a/src/oofemlib/load.C b/src/oofemlib/load.C index 4a9324528..4b3212432 100644 --- a/src/oofemlib/load.C +++ b/src/oofemlib/load.C @@ -37,6 +37,8 @@ #include "timestep.h" #include "function.h" #include "dynamicinputrecord.h" +#include "datastream.h" +#include "contextioerr.h" namespace oofem { Load :: Load(int i, Domain *aDomain) : @@ -94,14 +96,10 @@ Load :: computeComponentArrayAt(FloatArray &answer, TimeStep *tStep, ValueModeTy } -IRResultType -Load :: initializeFrom(InputRecord *ir) +void +Load :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - -# ifdef VERBOSE - // VERBOSE_PRINT1 ("Instanciating load ",number) -# endif + GeneralBoundaryCondition :: initializeFrom(ir); IR_GIVE_FIELD(ir, componentArray, _IFT_Load_components); @@ -110,8 +108,7 @@ Load :: initializeFrom(InputRecord *ir) dofExcludeMask.zero(); IR_GIVE_OPTIONAL_FIELD(ir, dofExcludeMask, _IFT_Load_dofexcludemask); if ( dofExcludeMask.giveSize() != size ) { - OOFEM_WARNING("dofExcludeMask and componentArray size mismatch"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Load_dofexcludemask, "dofExcludeMask and componentArray size mismatch"); } else { for ( int i = 1; i <= size; i++ ) { if ( dofExcludeMask.at(i) ) { @@ -120,9 +117,7 @@ Load :: initializeFrom(InputRecord *ir) } } - this->reference = ir->hasField(_IFT_Load_reference); - - return GeneralBoundaryCondition :: initializeFrom(ir); + this->reference = ir.hasField(_IFT_Load_reference); } @@ -157,4 +152,45 @@ Load :: scale(double s) this->reference = false; } + +void +Load :: saveContext(DataStream &stream, ContextMode mode) +{ + GeneralBoundaryCondition :: saveContext(stream, mode); + + if ( mode & CM_Definition ) { + contextIOResultType iores; + if ( ( iores = componentArray.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + if ( ( iores = dofExcludeMask.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + if ( !stream.write(reference) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +void +Load :: restoreContext(DataStream &stream, ContextMode mode) +{ + GeneralBoundaryCondition :: restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + contextIOResultType iores; + if ( ( iores = componentArray.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + if ( ( iores = dofExcludeMask.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + if ( !stream.read(reference) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + } // end namespace oofem diff --git a/src/oofemlib/load.h b/src/oofemlib/load.h index 9cf255b97..c22327d83 100644 --- a/src/oofemlib/load.h +++ b/src/oofemlib/load.h @@ -143,7 +143,7 @@ class OOFEM_EXPORT Load : public GeneralBoundaryCondition */ int isDofExcluded(int index); - virtual void scale(double s); + void scale(double s) override; /** * Returns receiver's coordinate system. @@ -168,14 +168,17 @@ class OOFEM_EXPORT Load : public GeneralBoundaryCondition return 0; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; /** * @return Pointer to receiver component array, where component values of boundary condition are stored. */ const FloatArray &giveComponentArray() const; - void setComponentArray(FloatArray &arry) { componentArray = arry; } + void setComponentArray(FloatArray &arry) { componentArray = std::move(arry); } + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; } // end namespace oofem #endif // load_h diff --git a/src/oofemlib/loadbalancer.C b/src/oofemlib/loadbalancer.C index 47923050f..5483739f9 100644 --- a/src/oofemlib/loadbalancer.C +++ b/src/oofemlib/loadbalancer.C @@ -44,33 +44,46 @@ #include "floatarray.h" #include "intarray.h" +#ifdef __PARALLEL_MODE #include "processcomm.h" #include "datastream.h" #include "communicator.h" #include "domaintransactionmanager.h" #include "nonlocalmatwtp.h" +#endif namespace oofem { //#define __VERBOSE_PARALLEL //#define LoadBalancer_debug_print +#ifndef __PARALLEL_MODE + LoadBalancer :: LoadBalancer(Domain *d) : wtpList() { domain = d; } +void LoadBalancer::migrateLoad(Domain *d) {} +void LoadBalancer::printStatistics() const {} +void LoadBalancer::initializeFrom(InputRecord &ir) { } +void LoadBalancerMonitor::initializeFrom(InputRecord &ir) { } + +#else -IRResultType -LoadBalancer :: initializeFrom(InputRecord *ir) + +LoadBalancer :: LoadBalancer(Domain *d) : wtpList() { - IRResultType result; // Required by IR_GIVE_FIELD macro + domain = d; +} + +void +LoadBalancer :: initializeFrom(InputRecord &ir) +{ IntArray wtp; IR_GIVE_OPTIONAL_FIELD(ir, wtp, _IFT_LoadBalancer_wtp); this->initializeWtp(wtp); - - return IRRT_OK; } void @@ -84,7 +97,7 @@ LoadBalancer :: initializeWtp(IntArray &wtp) for ( int iwtp: wtp ) { std :: unique_ptr< WorkTransferPlugin > plugin; if ( iwtp == 1 ) { - plugin.reset( new NonlocalMaterialWTP(this) ); + plugin = std::make_unique(this); } else { OOFEM_ERROR("Unknown work transfer plugin type"); } @@ -343,7 +356,7 @@ LoadBalancer :: unpackMigratingData(Domain *d, ProcessCommunicator &pc) * } */ _newentry = true; - dofman = classFactory.createDofManager(_type.c_str(), 0, d); + dofman = classFactory.createDofManager(_type.c_str(), 0, d).release(); ///@todo Unsafe! Find a better way to preserve ownership. dofman->setGlobalNumber(_globnum); // unpack dofman state (this is the local dofman, not available on remote) @@ -373,8 +386,7 @@ LoadBalancer :: unpackMigratingData(Domain *d, ProcessCommunicator &pc) * } */ _newentry = true; - dofman = classFactory.createDofManager(_type.c_str(), 0, d); - + dofman = classFactory.createDofManager(_type.c_str(), 0, d).release(); ///@todo Unsafe! Find a better way to preserve ownership. dofman->setGlobalNumber(_globnum); // unpack dofman state (this is the local dofman, not available on remote) @@ -408,7 +420,7 @@ LoadBalancer :: unpackMigratingData(Domain *d, ProcessCommunicator &pc) break; } - elem = classFactory.createElement(_type.c_str(), 0, d); + elem = classFactory.createElement(_type.c_str(), 0, d).release(); ///@todo Unsafe! Find a better way to preserve ownership. elem->restoreContext(*pcbuff, CM_Definition | CM_State); elem->initForNewStep(); dtm->addElementTransaction(DomainTransactionManager :: DTT_ADD, elem->giveGlobalNumber(), elem); @@ -532,10 +544,9 @@ LoadBalancer :: printStatistics() const } -IRResultType -LoadBalancerMonitor :: initializeFrom(InputRecord *ir) +void +LoadBalancerMonitor :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro int nproc = emodel->giveNumberOfProcesses(); int nodeWeightMode = 0; @@ -560,29 +571,7 @@ LoadBalancerMonitor :: initializeFrom(InputRecord *ir) OOFEM_ERROR("unsupported node weight type, using default value"); staticNodeWeightFlag = false; } - - return IRRT_OK; } - -/* - * void - * LoadBalancer::migrateLoad () {} - * - * IRResultType - * LoadBalancer::initializeFrom (InputRecord* ir) { - * - * return IRRT_OK; - * } - * - * IRResultType - * LoadBalancerMonitor::initializeFrom (InputRecord* ir) {return IRRT_OK;} - */ - - - -LoadBalancer :: WorkTransferPlugin :: WorkTransferPlugin(LoadBalancer *_lb) { - lb = _lb; -} -LoadBalancer :: WorkTransferPlugin :: ~WorkTransferPlugin() { } +#endif // end __PARALLEL_MODE } // end namespace oofem diff --git a/src/oofemlib/loadbalancer.h b/src/oofemlib/loadbalancer.h index e3e5338da..c19f52506 100644 --- a/src/oofemlib/loadbalancer.h +++ b/src/oofemlib/loadbalancer.h @@ -78,7 +78,7 @@ class OOFEM_EXPORT LoadBalancerMonitor virtual ~LoadBalancerMonitor() { } /// Initializes receiver according to object description stored in input record. - virtual IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); /**@name Load evaluation and imbalance detection methods*/ //@{ @@ -125,6 +125,9 @@ class OOFEM_EXPORT LoadBalancer LoadBalancer(Domain * d); virtual ~LoadBalancer() { } +#ifdef _MSC_VER + LoadBalancer(LoadBalancer&& src) {domain = src.domain;} +#endif @@ -154,7 +157,7 @@ class OOFEM_EXPORT LoadBalancer //@} ///Initializes receiver according to object description stored in input record. - virtual IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); /// Returns reference to its domain. Domain *giveDomain() { return domain; } @@ -178,8 +181,8 @@ class OOFEM_EXPORT LoadBalancer protected: LoadBalancer *lb; public: - WorkTransferPlugin(LoadBalancer * _lb); - virtual ~WorkTransferPlugin(); + WorkTransferPlugin(LoadBalancer * _lb) {lb = _lb;} + virtual ~WorkTransferPlugin() {} /** * initializes receiver; should be called before any work transfer. diff --git a/src/oofemlib/lobattoir.h b/src/oofemlib/lobattoir.h index dfacd900f..966b4e4e7 100644 --- a/src/oofemlib/lobattoir.h +++ b/src/oofemlib/lobattoir.h @@ -37,6 +37,8 @@ #include "integrationrule.h" +#define _IFT_LobattoIntegrationRule_Name "lobatto" + namespace oofem { /** * Class representing Lobatto-quadrature integration rule. @@ -59,19 +61,19 @@ class OOFEM_EXPORT LobattoIntegrationRule : public IntegrationRule /// Destructor virtual ~LobattoIntegrationRule(); - virtual const char *giveClassName() const { return "LobattoIntegrationRule"; } - virtual IntegrationRuleType giveIntegrationRuleType() const { return IRT_Lobatto; } - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + const char *giveClassName() const override { return "LobattoIntegrationRule"; } + IntegrationRuleType giveIntegrationRuleType() const override { return IRT_Lobatto; } + void initializeFrom(InputRecord &ir) override { } - virtual int getRequiredNumberOfIntegrationPoints(integrationDomain dType, int approxOrder); + int getRequiredNumberOfIntegrationPoints(integrationDomain dType, int approxOrder) override; //@todo These 3 integration rules have not been verified but the code is identical // to that in GaussIntegrationRule, only the point coords and weights differ /JB - virtual int SetUpPointsOnLine(int nPoints, MaterialMode mode); - virtual int SetUpPointsOnSquare(int nPoints, MaterialMode mode); - virtual int SetUpPointsOnCube(int nPoints, MaterialMode mode); + int SetUpPointsOnLine(int nPoints, MaterialMode mode) override; + int SetUpPointsOnSquare(int nPoints, MaterialMode mode) override; + int SetUpPointsOnCube(int nPoints, MaterialMode mode) override; static void giveLineCoordsAndWeights(int nPoints, FloatArray &coords_xi, FloatArray &weights); - virtual int SetUpPointsOnTriangle(int nPoints, MaterialMode mode); + int SetUpPointsOnTriangle(int nPoints, MaterialMode mode) override; }; } // end namespace oofem #endif // lobattoir_h diff --git a/src/oofemlib/localgaussianrandomfunction.C b/src/oofemlib/localgaussianrandomfunction.C index f4bbdaf8e..a5b5b77d1 100644 --- a/src/oofemlib/localgaussianrandomfunction.C +++ b/src/oofemlib/localgaussianrandomfunction.C @@ -73,11 +73,9 @@ LocalGaussianRandomFunction :: evaluateAccelerationAtTime(double t) return 0.; } -IRResultType -LocalGaussianRandomFunction :: initializeFrom(InputRecord *ir) +void +LocalGaussianRandomFunction :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, mean, _IFT_LocalGaussianRandomFunction_mean); IR_GIVE_FIELD(ir, variance, _IFT_LocalGaussianRandomFunction_variance); randomInteger = ( long ) ( -time(NULL) ); @@ -86,8 +84,6 @@ LocalGaussianRandomFunction :: initializeFrom(InputRecord *ir) if ( seed ) { randomInteger = seed; } - - return IRRT_OK; } #define IA 16807 diff --git a/src/oofemlib/localgaussianrandomfunction.h b/src/oofemlib/localgaussianrandomfunction.h index dffe4f116..76422effb 100644 --- a/src/oofemlib/localgaussianrandomfunction.h +++ b/src/oofemlib/localgaussianrandomfunction.h @@ -64,14 +64,14 @@ class OOFEM_EXPORT LocalGaussianRandomFunction : public Function /// Destructor virtual ~LocalGaussianRandomFunction(); - virtual void evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp=NULL, double param=0.); - virtual double evaluateAtTime(double t); - virtual double evaluateVelocityAtTime(double t); - virtual double evaluateAccelerationAtTime(double t); + void evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp=nullptr, double param=0.) override; + double evaluateAtTime(double t) override; + double evaluateVelocityAtTime(double t) override; + double evaluateAccelerationAtTime(double t) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "LocalGaussianRandomFunction"; } - virtual const char *giveInputRecordName() const { return _IFT_LocalGaussianRandomFunction_Name; } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "LocalGaussianRandomFunction"; } + const char *giveInputRecordName() const override { return _IFT_LocalGaussianRandomFunction_Name; } protected: /** diff --git a/src/oofemlib/logger.C b/src/oofemlib/logger.C index b39c287fa..8cf45e608 100644 --- a/src/oofemlib/logger.C +++ b/src/oofemlib/logger.C @@ -34,6 +34,7 @@ #include "logger.h" #include "error.h" +#include "util.h" #include #ifdef __PARALLEL_MODE @@ -41,93 +42,6 @@ #endif -#if defined ( __GNUC__ ) && defined ( HAVE_EXECINFO_H ) - #include - #include - #include - #include -// Taken from https://idlebox.net/2008/0901-stacktrace-demangled/ which indicated free usage. -/** Print a demangled stack backtrace of the caller function to FILE* out. */ -static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63) -{ - int addrlen = 0; - fprintf(out, "stack trace:\n"); - - // storage array for stack trace address data - void *addrlist [ max_frames + 1 ]; - - // retrieve current stack addresses - addrlen = backtrace( addrlist, sizeof( addrlist ) / sizeof( void * ) ); - if ( addrlen == 0 ) { - fprintf(out, " \n"); - return; - } - - // resolve addresses into strings containing "filename(function+address)", - // this array must be free()-ed - char **symbollist; - symbollist = backtrace_symbols(addrlist, addrlen); - // allocate string which will be filled with the demangled function name - size_t funcnamesize = 256; - char *funcname = ( char * ) malloc(funcnamesize); - - // iterate over the returned symbol lines. skip the first, it is the - // address of this function. - for ( int i = 2; i < addrlen; i++ ) { - char *begin_name = 0, *begin_offset = 0, *end_offset = 0; - - // find parentheses and +address offset surrounding the mangled name: - // ./module(function+0x15c) [0x8048a6d] - for ( char *p = symbollist [ i ]; * p; ++p ) { - if ( * p == '(' ) { - begin_name = p; - } else if ( * p == '+' ) { - begin_offset = p; - } else if ( * p == ')' && begin_offset ) { - end_offset = p; - break; - } - } - - if ( begin_name && begin_offset && end_offset && - begin_name < begin_offset ) { - * begin_name++ = '\0'; - * begin_offset++ = '\0'; - * end_offset = '\0'; - - // mangled name is now in [begin_name, begin_offset) and caller - // offset in [begin_offset, end_offset). now apply - // __cxa_demangle(): - - int status; - char *ret = abi :: __cxa_demangle(begin_name, - funcname, & funcnamesize, & status); - if ( status == 0 ) { - funcname = ret; // use possibly realloc()-ed string - fprintf(out, " %s : %s+%s\n", - symbollist [ i ], funcname, begin_offset); - } else { - // demangling failed. Output function name as a C function with - // no arguments. - fprintf(out, " %s : %s()+%s\n", - symbollist [ i ], begin_name, begin_offset); - } - } else { - // couldn't parse the line? print the whole line. - fprintf(out, " %s\n", symbollist [ i ]); - } - } - - free(funcname); - free(symbollist); -} -#else -static inline void print_stacktrace(FILE *out = stderr, unsigned int max_frames = 63) -{ - fprintf(out, "No backtrace available\n"); -} -#endif - namespace oofem { #define LOG_ERR_HEADER "_______________________________________________________" #define LOG_ERR_TAIL "_______________________________________________________\a\n" @@ -277,22 +191,31 @@ Logger :: writeELogMsg(logLevelType level, const char *_func, const char *_file, if ( level <= this->logLevel ) { if ( _file ) { - fprintf(stream, "%s\n%s: (%s:%d)\n", LOG_ERR_HEADER, giveLevelName(level), _file, _line); + fprintf(stream, "%s\n%s:", LOG_ERR_HEADER, giveLevelName(level)); } else { - fprintf(stream, "%s\n%s:\n", LOG_ERR_HEADER, giveLevelName(level) ); - } - if ( _func ) { - fprintf(stream, "In %s:\n", _func ); + fprintf(stream, "%s\n%s:", LOG_ERR_HEADER, giveLevelName(level)); } va_start(args, format); vfprintf(stream, format, args); va_end(args); + fprintf(stream, "\n"); + + if ( _func ) { + fprintf(stream, "In %s ", _func ); + } + + if ( _file ) { + fprintf(stream, "(%s:%d)", _file, _line); + } + fprintf(stream, "\n%s", LOG_ERR_TAIL); } if ( level == LOG_LEVEL_FATAL || level == LOG_LEVEL_ERROR ) { +#ifndef CEMPY print_stacktrace(this->errStream, 10); +#endif } } diff --git a/src/oofemlib/logger.h b/src/oofemlib/logger.h index fe67fd504..8c648cef1 100644 --- a/src/oofemlib/logger.h +++ b/src/oofemlib/logger.h @@ -36,6 +36,7 @@ #define logger_h #include "oofemcfg.h" +//#include "util.h" #include #include @@ -105,6 +106,8 @@ class OOFEM_EXPORT Logger void setLogLevel(logLevelType level) { logLevel = level; } /// Sets log level to given one. Only log messages with level less or equal given threshold will be printed. void setLogLevel(int level); + /// Increment error count by one + void incrementErrorCounter() {numberOfErr++;} /// Prints number of errors and warning logged. void printStatistics(); diff --git a/src/oofemlib/maskedprimaryfield.h b/src/oofemlib/maskedprimaryfield.h index d25d8ac10..4af0919c5 100644 --- a/src/oofemlib/maskedprimaryfield.h +++ b/src/oofemlib/maskedprimaryfield.h @@ -57,20 +57,20 @@ class OOFEM_EXPORT MaskedPrimaryField : public Field protected: PrimaryField *master; IntArray mask; + public: - MaskedPrimaryField(FieldType b, PrimaryField * m, IntArray dofIdMask) : Field(b), mask(std::move(dofIdMask)) { - master = m; - } + MaskedPrimaryField(FieldType b, PrimaryField * m, IntArray dofIdMask) : Field(b), + master(m), + mask(std::move(dofIdMask)) + { } - virtual int evaluateAt(FloatArray &answer, const FloatArray &coords, - ValueModeType mode, TimeStep *tStep); - virtual int evaluateAt(FloatArray &answer, DofManager *dman, - ValueModeType mode, TimeStep *tStep); + int evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) override; + int evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) override; - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode) { return CIO_OK; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode) { return CIO_OK; } + void restoreContext(DataStream &stream) override { } + void saveContext(DataStream &stream) override { } - virtual const char *giveClassName() const { return "MaskedPrimaryField"; } + const char *giveClassName() const override { return "MaskedPrimaryField"; } }; } // end namespace oofem #endif // maskedprimaryfield_h diff --git a/src/oofemlib/masterdof.C b/src/oofemlib/masterdof.C index 149b726e4..bd44140d4 100644 --- a/src/oofemlib/masterdof.C +++ b/src/oofemlib/masterdof.C @@ -149,40 +149,41 @@ double MasterDof :: giveUnknown(ValueModeType mode, TimeStep *tStep) if ( dofManager->giveParallelMode() == DofManager_null ) { return 0.0; } -#if 1 - // first try if IC apply - if ( tStep->giveNumber() == dofManager->giveDomain()->giveEngngModel()->giveNumberOfTimeStepWhenIcApply() ) { // step when Ic apply - if ( this->hasIcOn(mode) ) { - return this->giveIc()->give(mode); - } else if ( this->hasBc(tStep) ) { - return this->giveBcValue(mode, tStep); - } else { - return 0.; + + if ( (! dofManager->giveDomain()->giveEngngModel()->newDofHandling() ) && (mode!=VM_Residual)) { + // first try if IC apply + if ( tStep->giveNumber() == dofManager->giveDomain()->giveEngngModel()->giveNumberOfTimeStepWhenIcApply() ) { // step when Ic apply + if ( this->hasIcOn(mode) ) { + return this->giveIc()->give(mode); + } else if ( this->hasBc(tStep) ) { + return this->giveBcValue(mode, tStep); + } else { + return 0.; + } } - } - // if ( dofManager->giveDomain()->giveEngngModel()->requiresUnknownsDictionaryUpdate() ) { - // if this feature is active, engng model must ensure - // valid data in unknowns dictionary - // the e-model must ensure that bc and ic values are correctly set in unknowns dictionaries - // they could not be obtained from bc (which are typically incremental) - // directly since dictionaries keep the history. - - // return ( dofManager->giveDomain()->giveEngngModel()-> - // giveUnknownComponent(mode, tStep, dofManager->giveDomain(), this) ); - - // int hash = dofManager->giveDomain()->giveEngngModel()->giveUnknownDictHashIndx(mode, tStep); - // if ( unknowns->includes(hash) ) { - // return unknowns->at(hash); - // } else { - // OOFEM_ERROR(Dof unknowns dictionary does not contain unknown of value mode (%s)", __ValueModeTypeToString(mode)); - // } - // } - - if ( !dofManager->giveDomain()->giveEngngModel()->requiresUnknownsDictionaryUpdate() && this->hasBc(tStep) ) { - return this->giveBcValue(mode, tStep); + // if ( dofManager->giveDomain()->giveEngngModel()->requiresUnknownsDictionaryUpdate() ) { + // if this feature is active, engng model must ensure + // valid data in unknowns dictionary + // the e-model must ensure that bc and ic values are correctly set in unknowns dictionaries + // they could not be obtained from bc (which are typically incremental) + // directly since dictionaries keep the history. + + // return ( dofManager->giveDomain()->giveEngngModel()-> + // giveUnknownComponent(mode, tStep, dofManager->giveDomain(), this) ); + + // int hash = dofManager->giveDomain()->giveEngngModel()->giveUnknownDictHashIndx(mode, tStep); + // if ( unknowns->includes(hash) ) { + // return unknowns->at(hash); + // } else { + // OOFEM_ERROR(Dof unknowns dictionary does not contain unknown of value mode (%s)", __ValueModeTypeToString(mode)); + // } + // } + + if ( !dofManager->giveDomain()->giveEngngModel()->requiresUnknownsDictionaryUpdate() && this->hasBc(tStep) ) { + return this->giveBcValue(mode, tStep); + } } -#endif return ( dofManager->giveDomain()->giveEngngModel()-> giveUnknownComponent(mode, tStep, dofManager->giveDomain(), this) ); } @@ -295,17 +296,9 @@ void MasterDof :: printYourself() } -contextIOResultType MasterDof :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full node context (saves state variables, that completely describe -// current state) -// +void MasterDof :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = Dof :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + Dof :: saveContext(stream, mode); if ( mode & CM_Definition ) { if ( !stream.write(bc) ) { @@ -323,26 +316,14 @@ contextIOResultType MasterDof :: saveContext(DataStream &stream, ContextMode mod } if ( ( mode & CM_UnknownDictState ) || ( dofManager->giveDomain()->giveEngngModel()->requiresUnknownsDictionaryUpdate() ) ) { - if ( ( iores = unknowns.saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + unknowns.saveContext(stream); } - - return CIO_OK; } -contextIOResultType MasterDof :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full node context (saves state variables, that completely describe -// current state) -// +void MasterDof :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = Dof :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + Dof :: restoreContext(stream, mode); if ( mode & CM_Definition ) { if ( !stream.read(bc) ) { @@ -361,11 +342,7 @@ contextIOResultType MasterDof :: restoreContext(DataStream &stream, ContextMode } if ( ( mode & CM_UnknownDictState ) || ( dofManager->giveDomain()->giveEngngModel()->requiresUnknownsDictionaryUpdate() ) ) { - if ( ( iores = unknowns.restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + unknowns.restoreContext(stream); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/oofemlib/masterdof.h b/src/oofemlib/masterdof.h index 9540e4682..85cbc233b 100644 --- a/src/oofemlib/masterdof.h +++ b/src/oofemlib/masterdof.h @@ -117,46 +117,46 @@ class OOFEM_EXPORT MasterDof : public Dof /// Destructor. virtual ~MasterDof(); - virtual dofType giveDofType() { return DT_master; } - virtual const char *giveClassName() const { return "MasterDof"; } + dofType giveDofType() override { return DT_master; } + const char *giveClassName() const override { return "MasterDof"; } - virtual int __giveEquationNumber() const; + int __giveEquationNumber() const override; - virtual int __givePrescribedEquationNumber(); + int __givePrescribedEquationNumber() override; - virtual int askNewEquationNumber(TimeStep *tStep); + int askNewEquationNumber(TimeStep *tStep) override; - virtual double giveUnknown(ValueModeType mode, TimeStep *tStep); - virtual double giveUnknown(PrimaryField &field, ValueModeType, TimeStep *tStep); + double giveUnknown(ValueModeType mode, TimeStep *tStep) override; + double giveUnknown(PrimaryField &field, ValueModeType, TimeStep *tStep) override; - virtual bool hasBc(TimeStep *tStep); - virtual bool hasIc(); - virtual bool hasIcOn(ValueModeType); + bool hasBc(TimeStep *tStep) override; + bool hasIc() override; + bool hasIcOn(ValueModeType) override; - virtual bool isPrimaryDof() { return true; } + bool isPrimaryDof() override { return true; } - virtual int giveBcId(); - virtual int giveIcId(); + int giveBcId() override; + int giveIcId() override; - virtual void printYourself(); - virtual void updateYourself(TimeStep *tStep); + void printYourself() override; + void updateYourself(TimeStep *tStep) override; - virtual void updateUnknownsDictionary(TimeStep *tStep, ValueModeType mode, double dofValue); + void updateUnknownsDictionary(TimeStep *tStep, ValueModeType mode, double dofValue) override; - virtual double giveUnknownsDictionaryValue(TimeStep *tStep, ValueModeType mode); + double giveUnknownsDictionaryValue(TimeStep *tStep, ValueModeType mode) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void setBcId(int bcId) { this->bc = bcId; } - virtual void setIcId(int icId) { this->ic = icId; } - virtual void setEquationNumber(int newEquationNumber) { this->equationNumber = newEquationNumber; } - virtual Dictionary *giveUnknowns() { return &this->unknowns; } - virtual int giveEqn() { return equationNumber; } + void setBcId(int bcId) override { this->bc = bcId; } + void setIcId(int icId) override { this->ic = icId; } + void setEquationNumber(int newEquationNumber) override { this->equationNumber = newEquationNumber; } + Dictionary *giveUnknowns() override { return &this->unknowns; } + int giveEqn() override { return equationNumber; } protected: - BoundaryCondition *giveBc(); - InitialCondition *giveIc(); + BoundaryCondition *giveBc() override; + InitialCondition *giveIc() override; }; } // end namespace oofem #endif // masterdof_h diff --git a/src/oofemlib/matconst.h b/src/oofemlib/matconst.h index ad1aca0c9..65090c8e9 100644 --- a/src/oofemlib/matconst.h +++ b/src/oofemlib/matconst.h @@ -95,5 +95,9 @@ namespace oofem { #define AVERAGING_TYPE 901 #define exponent_ID 902 #define rf_ID 903 + +/* lattice parameters */ +#define eNormal_ID 1101 + } // end namespace oofem #endif // matconst_h diff --git a/src/oofemlib/material.C b/src/oofemlib/material.C index d5db9f684..e1dcf4342 100644 --- a/src/oofemlib/material.C +++ b/src/oofemlib/material.C @@ -39,17 +39,15 @@ #include "mathfem.h" #include "dynamicinputrecord.h" #include "contextioerr.h" +#include "datastream.h" namespace oofem { Material :: Material(int n, Domain *d) : FEMComponent(n, d), propertyDictionary(), castingTime(-1.) { } -Material :: ~Material() -{} - double -Material :: give(int aProperty, GaussPoint *gp) +Material :: give(int aProperty, GaussPoint *gp) const // Returns the value of the property aProperty (e.g. the Young's modulus // 'E') of the receiver. // tStep allows time dependent behavior to be taken into account @@ -65,9 +63,15 @@ Material :: give(int aProperty, GaussPoint *gp) return value; } +double +Material :: giveCharacteristicValue(CharType type, GaussPoint* gp, TimeStep *tStep) +{ + OOFEM_ERROR( "Characteristic value %s(%d) on element %d and GP %d not defined", __CharTypeToString(type), type, gp->giveElement()->giveNumber(), gp->giveNumber() ); + return 0.0; +} bool -Material :: hasProperty(int aProperty, GaussPoint *gp) +Material :: hasProperty(int aProperty, GaussPoint *gp) const // Returns true if the aProperty is defined on a material { return propertyDictionary.includes(aProperty); @@ -85,11 +89,9 @@ Material :: modifyProperty(int aProperty, double value, GaussPoint *gp) } -IRResultType -Material :: initializeFrom(InputRecord *ir) +void +Material :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - double value; # ifdef VERBOSE @@ -101,8 +103,9 @@ Material :: initializeFrom(InputRecord *ir) this->castingTime = -1.e10; IR_GIVE_OPTIONAL_FIELD(ir, castingTime, _IFT_Material_castingtime); - - return IRRT_OK; + + this->preCastingTimeMat = 0; + IR_GIVE_OPTIONAL_FIELD(ir, preCastingTimeMat, _IFT_Material_preCastingTimeMat); } @@ -115,26 +118,19 @@ Material :: giveInputRecord(DynamicInputRecord &input) } -int -Material :: hasMaterialModeCapability(MaterialMode mode) +bool +Material :: hasMaterialModeCapability(MaterialMode mode) const // // returns whether receiver supports given mode // { - return 0; + return false; } -int -Material :: hasCastingTimeSupport() -// -// returns whether receiver fully supports casting time -// +bool +Material :: hasCastingTimeSupport() const { - if ( this->castingTime > 0. ) { - return 0; // casting time is user-defined. By default the casting time is not supported. - } else { - return 1; // do not check anything - casting time has not been user-defined - } + return this->castingTime <= 0.; } @@ -169,64 +165,30 @@ Material :: printYourself() // store & restore context - material info in gp not saved now! // -contextIOResultType +void Material :: saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -// -// saves full material status (saves state variables, that completely describe -// current state) stored in gp->matstatusDict with key = this->giveNumber() -// storing of corresponding context if it is defined for current material in -// gp status dictionary should be performed here by overloading this function. -// (such code should invoke also corresponding function for yield conditions, -// submaterials and so on) -// - -// { - contextIOResultType iores; - - if ( gp == NULL ) { + if ( gp == nullptr ) { THROW_CIOERR(CIO_BADOBJ); } - // write raw data - we save status there for this MaterialStatus *status = this->giveStatus(gp); - if ( status ) { - if ( ( iores = status->saveContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + status->saveContext(stream, mode); } - - return CIO_OK; } -contextIOResultType +void Material :: restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -// -// restores full material status (saves state variables, that completely describe -// current state) stored in gp->matstatusDict with key = this->giveNumber() -// restoring of corresponding context if it is defined for current material in -// gp status dictionary should be performed here by overloading this function. -// (such code should invoke also corresponding function for yield conditions, -// submaterials and so on) -// - -// { - contextIOResultType iores; - if ( gp == NULL ) { + if ( gp == nullptr ) { THROW_CIOERR(CIO_BADOBJ); } - // read raw data - context - MaterialStatus *status = this->giveStatus(gp); + MaterialStatus *status = this->giveStatus(gp); if ( status ) { - if ( ( iores = status->restoreContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + status->restoreContext(stream, mode); } - - return CIO_OK; } @@ -247,15 +209,15 @@ Material :: giveStatus(GaussPoint *gp) const */ { MaterialStatus *status = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); - if ( status == NULL ) { + if ( status == nullptr ) { // create a new one status = this->CreateStatus(gp); // if newly created status is null // dont include it. specific instance // does not have status. - if ( status != NULL ) { - gp->setMaterialStatus( status, this->giveNumber() ); + if ( status ) { + gp->setMaterialStatus( status ); } } @@ -264,7 +226,7 @@ Material :: giveStatus(GaussPoint *gp) const void -Material :: initTempStatus(GaussPoint *gp) +Material :: initTempStatus(GaussPoint *gp) const // // Initialize MatStatus (respective it's temporary variables at the begining // of integrating incremental constitutive relations) to correct values @@ -282,4 +244,33 @@ Material :: initMaterial(Element *element) { return 0; } + + +void Material :: saveContext(DataStream &stream, ContextMode mode) +{ + FEMComponent :: saveContext(stream, mode); + + if ( ( mode & CM_Definition ) ) { + propertyDictionary.saveContext(stream); + + if ( !stream.write(castingTime) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +void Material :: restoreContext(DataStream &stream, ContextMode mode) +{ + FEMComponent :: restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + propertyDictionary.restoreContext(stream); + + if ( !stream.read(castingTime) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + } // end namespace oofem diff --git a/src/oofemlib/material.h b/src/oofemlib/material.h index b50c435cb..389dc8261 100644 --- a/src/oofemlib/material.h +++ b/src/oofemlib/material.h @@ -45,11 +45,13 @@ #include "internalstatevaluetype.h" #include "matresponsemode.h" #include "dictionary.h" +#include "chartype.h" ///@name Input fields for Material //@{ #define _IFT_Material_density "d" #define _IFT_Material_castingtime "castingtime" +#define _IFT_Material_preCastingTimeMat "precastingtimemat" //@} namespace oofem { @@ -111,6 +113,10 @@ class OOFEM_EXPORT Material : public FEMComponent * material model */ double castingTime; + + /// Material existing before casting time - optional parameter, zero by default + int preCastingTimeMat; + public: /** @@ -120,13 +126,28 @@ class OOFEM_EXPORT Material : public FEMComponent */ Material(int n, Domain *d); /// Destructor. - virtual ~Material(); + virtual ~Material() = default; /** * Returns true if stiffness matrix of receiver is symmetric * Default implementation returns true. */ - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return true; } + virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const { return true; } + /** + * @brief Returns characteristic matrix of the receiver + * + */ + virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, GaussPoint* gp, TimeStep *tStep) {} + /** + * @brief Returns characteristic vector of the receiver + * + */ + virtual void giveCharacteristicVector(FloatArray &answer, FloatArray& flux, CharType type, GaussPoint* gp, TimeStep *tStep) {} + /** + * @brief Returns characteristic value of the receiver + * + */ + virtual double giveCharacteristicValue(CharType type, GaussPoint* gp, TimeStep *tStep); /** * Returns the value of material property 'aProperty'. Property must be identified * by unique int id. Integration point also passed to allow for materials with spatially @@ -135,14 +156,14 @@ class OOFEM_EXPORT Material : public FEMComponent * @param gp Integration point, * @return Property value. */ - virtual double give(int aProperty, GaussPoint *gp); + virtual double give(int aProperty, GaussPoint *gp) const; /** * Returns true if 'aProperty' exists on material. * @param aProperty ID of property requested. * @param gp Integration point. * @return True if 'aProperty' exists. */ - virtual bool hasProperty(int aProperty, GaussPoint *gp); + virtual bool hasProperty(int aProperty, GaussPoint *gp) const; /** * Modify 'aProperty', which already exists on material. Intended for evolving material properties. * @param aProperty ID of a property requested. @@ -153,39 +174,32 @@ class OOFEM_EXPORT Material : public FEMComponent /** * @return Casting time of the receiver. */ - double giveCastingTime() { return this->castingTime; } + double giveCastingTime() const { return this->castingTime; } /** * @param tStep Time step to check activity for. * @return True if material is activated for given solution step. */ - virtual bool isActivated(TimeStep *tStep) { + virtual bool isActivated(TimeStep *tStep) const { if ( tStep ) { - return ( tStep->giveIntrinsicTime() >= this->castingTime ); + return ( tStep->giveTargetTime() >= this->castingTime ); } else { return true; } } // identification and auxiliary functions - /** - * Returns nonzero if receiver is non linear - */ - virtual int hasNonLinearBehaviour() { return 0; } - /** * Tests if material supports material mode. * @param mode Required material mode. * @return Nonzero if supported, zero otherwise. */ - virtual int hasMaterialModeCapability(MaterialMode mode); - + virtual bool hasMaterialModeCapability(MaterialMode mode) const; /** * Tests if material supports casting time * @return Nonzero if supported, zero otherwise. */ - virtual int hasCastingTimeSupport(); - + virtual bool hasCastingTimeSupport() const; ///@name Access functions for internal states. Usually overloaded by new material models. //@{ @@ -210,28 +224,26 @@ class OOFEM_EXPORT Material : public FEMComponent virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); //@} - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void printYourself(); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void printYourself() override; /** * Stores integration point state to output stream. * @param stream Output stream. * @param mode Determines amount of info required in stream (state, definition, ...). * @param gp integration point. - * @return contextIOResultType. * @exception throws an ContextIOERR exception if error encountered. */ - virtual contextIOResultType saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); + virtual void saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); /** * Reads integration point state to output stream. * @param stream Output stream. * @param mode Determines amount of info required in stream (state, definition, ...). * @param gp integration point. - * @return contextIOResultType. * @exception throws an ContextIOERR exception if error encountered. */ - virtual contextIOResultType restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); + virtual void restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); /** * Allows programmer to test some internal data, before computation begins. @@ -240,9 +252,14 @@ class OOFEM_EXPORT Material : public FEMComponent * mesh components are instanciated. * @return Nonzero if receiver is consistent. */ - virtual int checkConsistency(); - - + int checkConsistency() override; + /** + * Restores consistency of the status, i.e., computes or corrects + * the values of certain status variables such that the state is admissible. + * For instance, if the initial values of some internal variables + * are read from a file, other internal variables are adjusted accordingly. + */ + virtual void restoreConsistency(GaussPoint *gp) { } /** * Optional function to call specific procedures when initializing a material. * For example, multiscale simulations need to create master and slave material statuses on specific integration points before the computation. @@ -307,14 +324,13 @@ class OOFEM_EXPORT Material : public FEMComponent */ virtual double predictRelativeRedistributionCost(GaussPoint *gp) { return 1.0; } - /** * Creates new copy of associated status and inserts it into given integration point. * @param gp Integration point where newly created status will be stored. * @return Reference to new status. */ virtual MaterialStatus *CreateStatus(GaussPoint *gp) const - { return NULL; } + { return nullptr; } /** * Initializes temporary variables stored in integration point status @@ -325,7 +341,23 @@ class OOFEM_EXPORT Material : public FEMComponent * Default implementation simply extracts status from integration point and * calls its initTempStatus method. */ - virtual void initTempStatus(GaussPoint *gp); + virtual void initTempStatus(GaussPoint *gp) const; + + /** + * Stores receiver state to output stream. + * @param stream Output stream. + * @param mode Determines amount of info required in stream (state, definition, ...). + * @exception throws an ContextIOERR exception if error encountered. + */ + void saveContext(DataStream &stream, ContextMode mode) override; + /** + * Restores the receiver state previously written in stream. + * @see saveContext + * @param stream Input stream. + * @param mode Determines amount of info available in stream (state, definition, ...). + * @exception throws an ContextIOERR exception if error encountered. + */ + void restoreContext(DataStream &stream, ContextMode mode) override; }; } // end namespace oofem #endif // material_h diff --git a/src/oofemlib/materialinterface.h b/src/oofemlib/materialinterface.h index c101c841c..828825133 100644 --- a/src/oofemlib/materialinterface.h +++ b/src/oofemlib/materialinterface.h @@ -56,7 +56,7 @@ class OOFEM_EXPORT MaterialInterface : public FEMComponent */ MaterialInterface(int n, Domain * d) : FEMComponent(n, d) { } - virtual const char *giveInputRecordName() const { return NULL; } + const char *giveInputRecordName() const override { return nullptr; } /** * Initializes receiver diff --git a/src/oofemlib/materialmappingalgorithm.h b/src/oofemlib/materialmappingalgorithm.h index 38f482ca1..63404d58f 100644 --- a/src/oofemlib/materialmappingalgorithm.h +++ b/src/oofemlib/materialmappingalgorithm.h @@ -150,7 +150,7 @@ class OOFEM_EXPORT MaterialMappingAlgorithm */ virtual int mapStatus(MaterialStatus &oStatus) const = 0; - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + virtual void initializeFrom(InputRecord &ir) { } /** * Setups the input record of receiver. * @param input Input record to be filled. diff --git a/src/oofemlib/materialmode.h b/src/oofemlib/materialmode.h index 3203296bc..8f2332c77 100644 --- a/src/oofemlib/materialmode.h +++ b/src/oofemlib/materialmode.h @@ -53,6 +53,7 @@ namespace oofem { ENUM_ITEM(_2dBeam) \ ENUM_ITEM(_3dBeam) \ ENUM_ITEM(_3dShell) \ + ENUM_ITEM(_3dShellRot) \ ENUM_ITEM(_3dDegeneratedShell) \ ENUM_ITEM(_3dBeamSubSoil) /* Subsoil model for beams */ \ \ @@ -66,18 +67,19 @@ namespace oofem { ENUM_ITEM(_2dInterface) \ ENUM_ITEM(_1dInterface) \ \ - ENUM_ITEM(_1dHeat) /* 1d heat */ \ + ENUM_ITEM(_1dHeat) /* 1d heat or 1d mass*/ \ ENUM_ITEM(_1dHeMo) /* 1d heat and mass (one component) transfer */ \ - ENUM_ITEM(_2dHeat) /* 2d heat */ \ + ENUM_ITEM(_2dHeat) /* 2d heat or 2d mass */ \ ENUM_ITEM(_2dHeMo) /* 2d heat and mass (one component) transfer */ \ - ENUM_ITEM(_3dHeat) /* 3d heat */ \ + ENUM_ITEM(_3dHeat) /* 3d heat or 3d mass */ \ ENUM_ITEM(_3dHeMo) /* 3d heat and mass (one component) transfer */ \ \ ENUM_ITEM(_2dFlow) \ ENUM_ITEM(_2dAxiFlow) \ ENUM_ITEM(_3dFlow) \ \ - ENUM_ITEM(_2dLattice) \ + ENUM_ITEM(_1dLattice) \ + ENUM_ITEM(_2dLattice) \ ENUM_ITEM(_3dLattice) \ ENUM_ITEM(_2dMTLattice) \ ENUM_ITEM(_3dMTLattice) \ diff --git a/src/oofemlib/mathfem.C b/src/oofemlib/mathfem.C index bfc9e398e..83a964635 100644 --- a/src/oofemlib/mathfem.C +++ b/src/oofemlib/mathfem.C @@ -236,6 +236,7 @@ void cubic3r(double a, double b, double c, double d, double *r1, double *r2, dou * r1 = -2.0 *p *cos(phi / 3.0) - a / 3.0; * r2 = -2.0 *p *cos( ( phi + 2.0 *M_PI ) / 3.0 ) - a / 3.0; + * r2 = -2.0 *p *cos( ( phi + 2.0 *M_PI ) / 3.0 ) - a / 3.0; * r3 = -2.0 *p *cos( ( phi - 2.0 *M_PI ) / 3.0 ) - a / 3.0; * num = 3; /* } else { diff --git a/src/oofemlib/matlabexportmodule.C b/src/oofemlib/matlabexportmodule.C index 33d456368..cd4b36cb0 100644 --- a/src/oofemlib/matlabexportmodule.C +++ b/src/oofemlib/matlabexportmodule.C @@ -54,14 +54,18 @@ #include "feinterpol.h" #ifdef __FM_MODULE -#include "../fm/tr21stokes.h" -#include "../fm/tet21stokes.h" -#include "../fm/stokesflow.h" +#include "fm/tr21stokes.h" +#include "fm/tet21stokes.h" +#include "fm/stokesflow.h" #endif #ifdef __SM_MODULE -#include "../sm/Elements/nlstructuralelement.h" -#include "../sm/EngineeringModels/structengngmodel.h" +#include "sm/Elements/nlstructuralelement.h" +#include "sm/EngineeringModels/structengngmodel.h" +#include "sm/prescribeddispslipbcdirichletrc.h" +#include "sm/prescribeddispslipbcneumannrc.h" +#include "sm/prescribeddispslipmultiple.h" +#include "sm/transversereinfconstraint.h" #endif @@ -91,26 +95,24 @@ MatlabExportModule :: ~MatlabExportModule() { } -IRResultType -MatlabExportModule :: initializeFrom(InputRecord *ir) +void +MatlabExportModule :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - ExportModule :: initializeFrom(ir); - exportMesh = ir->hasField(_IFT_MatlabExportModule_mesh); + exportMesh = ir.hasField(_IFT_MatlabExportModule_mesh); - exportData = ir->hasField(_IFT_MatlabExportModule_data); + exportData = ir.hasField(_IFT_MatlabExportModule_data); if ( exportData ) { IR_GIVE_OPTIONAL_FIELD(ir, this->dataNodeSet, _IFT_MatlabExportModule_DataNodeSet); } - exportArea = ir->hasField(_IFT_MatlabExportModule_area); - exportSpecials = ir->hasField(_IFT_MatlabExportModule_specials); - exportHomogenizeIST = ir->hasField(_IFT_MatlabExportModule_homogenizeInternalVars); + exportArea = ir.hasField(_IFT_MatlabExportModule_area); + exportSpecials = ir.hasField(_IFT_MatlabExportModule_specials); + exportHomogenizeIST = ir.hasField(_IFT_MatlabExportModule_homogenizeInternalVars); - exportReactionForces = ir->hasField(_IFT_MatlabExportModule_ReactionForces); + exportReactionForces = ir.hasField(_IFT_MatlabExportModule_ReactionForces); reactionForcesDofManList.resize(0); if ( exportReactionForces ) { IR_GIVE_OPTIONAL_FIELD(ir, reactionForcesDofManList, _IFT_MatlabExportModule_DofManList); @@ -118,7 +120,7 @@ MatlabExportModule :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, this->reactionForcesNodeSet, _IFT_MatlabExportModule_ReactionForcesNodeSet); } - exportIntegrationPointFields = ir->hasField(_IFT_MatlabExportModule_IntegrationPoints); + exportIntegrationPointFields = ir.hasField(_IFT_MatlabExportModule_IntegrationPoints); elList.resize(0); IR_GIVE_OPTIONAL_FIELD(ir, internalVarsToExport, _IFT_MatlabExportModule_internalVarsToExport); if ( exportIntegrationPointFields ) { @@ -127,9 +129,8 @@ MatlabExportModule :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, IPFieldsElSet, _IFT_MatlabExportModule_IPFieldsElSet); } - noscaling = ir->hasField(_IFT_MatlabExportModule_noScaledHomogenization); + noscaling = ir.hasField(_IFT_MatlabExportModule_noScaledHomogenization); - return ExportModule :: initializeFrom(ir); } @@ -453,7 +454,7 @@ MatlabExportModule :: doOutputSpecials(TimeStep *tStep, FILE *FID) */ // Output weak periodic boundary conditions - unsigned int wpbccount = 1, sbsfcount = 1, mcount = 1; + unsigned int wpbccount = 1, sbsfcount = 1, mcount = 1, pdsdcount=1, pdsncount=1, pdsmcount=1, trccount=1; for ( auto &gbc : domain->giveBcs() ) { WeakPeriodicBoundaryCondition *wpbc = dynamic_cast< WeakPeriodicBoundaryCondition * >( gbc.get() ); @@ -490,6 +491,86 @@ MatlabExportModule :: doOutputSpecials(TimeStep *tStep, FILE *FID) fprintf(FID, "];\n"); mcount++; } + PrescribedDispSlipBCDirichletRC *pdsd = dynamic_cast( gbc.get() ); + if (pdsd) { + FloatArray stress, bStress, rStress; + pdsd->computeStress(stress, tStep); + pdsd->computeTransferStress(bStress, tStep); + pdsd->computeReinfStress(rStress, tStep); + fprintf(FID, "\tspecials.prescribeddispslipbcdirichletrc{%u}.stress=[", pdsdcount); + for ( auto i : stress ) { + fprintf(FID, "%e\t", i); + } + fprintf(FID, "];\n"); + fprintf(FID, "\tspecials.prescribeddispslipbcdirichletrc{%u}.transferstress=[", pdsdcount); + for ( auto i : bStress ) { + fprintf(FID, "%e\t", i); + } + fprintf(FID, "];\n"); + fprintf(FID, "\tspecials.prescribeddispslipbcdirichletrc{%u}.reinfstress=[", pdsdcount); + for ( auto i : rStress ) { + fprintf(FID, "%e\t", i); + } + fprintf(FID, "];\n"); + pdsdcount++; + } + PrescribedDispSlipBCNeumannRC *pdsn = dynamic_cast( gbc.get() ); + if (pdsn) { + FloatArray stress, bStress, rStress; + pdsn->computeStress(stress, tStep); + pdsn->computeTransferStress(bStress, tStep); + pdsn->computeReinfStress(rStress, tStep); + fprintf(FID, "\tspecials.prescribeddispslipbcneumannrc{%u}.stress=[", pdsncount); + for ( auto i : stress ) { + fprintf(FID, "%e\t", i); + } + fprintf(FID, "];\n"); + fprintf(FID, "\tspecials.prescribeddispslipbcneumannrc{%u}.transferstress=[", pdsncount); + for ( auto i : bStress ) { + fprintf(FID, "%e\t", i); + } + fprintf(FID, "];\n"); + fprintf(FID, "\tspecials.prescribeddispslipbcneumannrc{%u}.reinfstress=[", pdsncount); + for ( auto i : rStress ) { + fprintf(FID, "%e\t", i); + } + fprintf(FID, "];\n"); + pdsncount++; + } + PrescribedDispSlipMultiple *pdsm = dynamic_cast( gbc.get() ); + if (pdsm) { + FloatArray stress, bStress, rStress; + pdsm->computeStress(stress, tStep); + pdsm->computeTransferStress(bStress, tStep); + pdsm->computeReinfStress(rStress, tStep); + fprintf(FID, "\tspecials.prescribeddispslipmultiple{%u}.stress=[", pdsncount); + for ( auto i : stress ) { + fprintf(FID, "%e\t", i); + } + fprintf(FID, "];\n"); + fprintf(FID, "\tspecials.prescribeddispslipmultiple{%u}.transferstress=[", pdsncount); + for ( auto i : bStress ) { + fprintf(FID, "%e\t", i); + } + fprintf(FID, "];\n"); + fprintf(FID, "\tspecials.prescribeddispslipmultiple{%u}.reinfstress=[", pdsncount); + for ( auto i : rStress ) { + fprintf(FID, "%e\t", i); + } + fprintf(FID, "];\n"); + pdsmcount++; + } + TransverseReinfConstraint *trc = dynamic_cast ( gbc.get() ); + if (trc) { + FloatArray lambda; + trc->computeField(lambda, tStep); + fprintf(FID, "\tspecials.transversereinfconstraint{%u}.stress=[", trccount); + for ( auto i : lambda ) { + fprintf(FID, "%e\t", i); + } + fprintf(FID, "];\n"); + trccount++; + } } } @@ -583,6 +664,12 @@ MatlabExportModule :: doOutputReactionForces(TimeStep *tStep, FILE *FID) } fprintf(FID, "];\n"); } + + // Output the current load level (useful for CALM solver) + double loadLevel = domain->giveEngngModel()->giveLoadLevel(); + fprintf( FID, "\tReactionForces.LoadLevel = [" ); + fprintf( FID, "%.9e", loadLevel); + fprintf( FID, "];\n" ); } @@ -653,6 +740,10 @@ MatlabExportModule :: doOutputIntegrationPointFields(TimeStep *tStep, FILE *F } fprintf( FID, "]; \n" ); + //export volume around Gauss point + fprintf( FID, "\tIntegrationPointFields.Elements{%i}.integrationRule{%i}.ip{%i}.volume = %e; \n ", + ielem, i, ip->giveNumber(), el->computeVolumeAround(ip)); + // export internal variables fprintf( FID, "\tIntegrationPointFields.Elements{%i}.integrationRule{%i}.ip{%i}.valArray = cell(%i,1); \n", ielem, i, ip->giveNumber(), numVars); @@ -747,60 +838,51 @@ MatlabExportModule :: giveOutputStream(TimeStep *tStep) } void -MatlabExportModule :: doOutputHomogenizeDofIDs(TimeStep *tStep, FILE *FID) +MatlabExportModule :: doOutputHomogenizeDofIDs(TimeStep *tStep, FILE *FID) { - - std :: vector HomQuantities; - double Vol = 0.0; + std :: vector HomQuantities; + double vol = 0.0; // Initialize vector of arrays constaining homogenized quantities HomQuantities.resize(internalVarsToExport.giveSize()); - for (int j=0; jelList.giveSize(); for (int i = 1; i<=nelem; i++) { Element *e = this->emodel->giveDomain(1)->giveElement(elList.at(i)); FEInterpolation *Interpolation = e->giveInterpolation(); - Vol = Vol + e->computeVolumeAreaOrLength(); + vol += e->computeVolumeAreaOrLength(); - for ( GaussPoint *gp: *e->giveDefaultIntegrationRulePtr() ) { + for ( auto &gp: *e->giveDefaultIntegrationRulePtr() ) { for (int j=0; jgiveIPValue(elementValues, gp, (InternalStateType) internalVarsToExport(j), tStep); + e->giveIPValue(elementValues, gp, (InternalStateType) internalVarsToExport[j], tStep); double detJ=fabs(Interpolation->giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(e))); elementValues.times(gp->giveWeight()*detJ); - if (HomQuantities.at(j)->giveSize() == 0) { - HomQuantities.at(j)->resize(elementValues.giveSize()); - HomQuantities.at(j)->zero(); + if (HomQuantities[j].giveSize() == 0) { + HomQuantities[j].resize(elementValues.giveSize()); }; - HomQuantities.at(j)->add(elementValues); + HomQuantities[j].add(elementValues); } } } - - if (noscaling) Vol=1.0; + if (noscaling) vol = 1.0; for ( std :: size_t i = 0; i < HomQuantities.size(); i ++) { - FloatArray *thisIS; - thisIS = HomQuantities.at(i); - thisIS->times(1.0/Vol); - fprintf(FID, "\tspecials.%s = [", __InternalStateTypeToString ( InternalStateType (internalVarsToExport(i)) ) ); - - for (int j = 0; jgiveSize(); j++) { - fprintf(FID, "%e", thisIS->at(j+1)); - if (j!=(thisIS->giveSize()-1) ) { + FloatArray &thisIS = HomQuantities[i]; + thisIS.times(1.0/vol); + fprintf(FID, "\tspecials.%s = [", __InternalStateTypeToString ( (InternalStateType) internalVarsToExport[i] ) ); + + for (int j = 0; j()) +{} int MaterialStatusMapperInterface :: MSMI_map(const GaussPoint &iGP, const Domain &iOldDom, Set &sourceSet, const TimeStep &iTStep, MaterialStatus &oStatus) { diff --git a/src/oofemlib/matstatmapperint.h b/src/oofemlib/matstatmapperint.h index 8101c8571..e45354aef 100644 --- a/src/oofemlib/matstatmapperint.h +++ b/src/oofemlib/matstatmapperint.h @@ -35,19 +35,19 @@ #ifndef MATSTATMAPPERINT_H_ #define MATSTATMAPPERINT_H_ +#include "materialmappingalgorithm.h" + +#include + namespace oofem { class MaterialStatus; class StructuralInterfaceMaterialStatus; -class MaterialMappingAlgorithm; class GaussPoint; class Domain; class TimeStep; class Set; /** - * matstatmapperint.h - * - * MaterialStatusMapperInterface: * An interface class for MaterialStatus. The purpose is to allow * mapping of state variables (Gauss point variables) in a * generic way. This is useful when the mesh changes, e.g. due to @@ -65,11 +65,14 @@ class Set; * @author Erik Svenning * Created on: Nov 6, 2013 */ -class MaterialStatusMapperInterface +class OOFEM_EXPORT MaterialStatusMapperInterface { +protected: + std::unique_ptr< MaterialMappingAlgorithm > mpMaterialMapper; + public: MaterialStatusMapperInterface(); - virtual ~MaterialStatusMapperInterface(); + virtual ~MaterialStatusMapperInterface() {} virtual void copyStateVariables(const MaterialStatus &iStatus) = 0; virtual void addStateVariables(const MaterialStatus &iStatus) = 0; @@ -98,9 +101,6 @@ class MaterialStatusMapperInterface * Finishes the mapping for given time step. Used to perform cleanup. */ virtual int MSMI_finish(const TimeStep &iTStep); - -protected: - MaterialMappingAlgorithm *mpMaterialMapper; }; } /* namespace oofem */ #endif /* MATSTATMAPPERINT_H_ */ diff --git a/src/oofemlib/matstatus.h b/src/oofemlib/matstatus.h index 4b993ff43..e72846f36 100644 --- a/src/oofemlib/matstatus.h +++ b/src/oofemlib/matstatus.h @@ -86,15 +86,11 @@ class OOFEM_EXPORT MaterialStatus : public IntegrationPointStatus public: /** * Constructor. - * @param n Receiver's number. - * @param d Domain to which new status belongs. * @param g Associated integration point. */ - MaterialStatus(int n, Domain * d, GaussPoint * g) : IntegrationPointStatus(n, d, g) { } - /// Destructor. - virtual ~MaterialStatus() { } + MaterialStatus(GaussPoint * g) : IntegrationPointStatus(g) { } /// Print receiver's output to given stream. - virtual void printOutputAt(FILE *file, TimeStep *tStep) { } + void printOutputAt(FILE *file, TimeStep *tStep) const override { } /** * Initializes the temporary internal variables, describing the current state according to @@ -105,7 +101,7 @@ class OOFEM_EXPORT MaterialStatus : public IntegrationPointStatus * Update equilibrium history variables according to temp-variables. * Invoked, after new equilibrium state has been reached. */ - virtual void updateYourself(TimeStep *) { } + void updateYourself(TimeStep *) override { } /** * Returns the value of material model property stored in receiving status. * This is typically used when random variation of some material property is considered, @@ -119,25 +115,6 @@ class OOFEM_EXPORT MaterialStatus : public IntegrationPointStatus * in this case the individual values are to be stored in status (they are no longer material constants) */ virtual void setMaterialProperty(int propID, double value) { } - - /** - * Allows to set the value of a specific variable, identified by varID. - * The meaning of varID is defined in each specific implementation - * of the method depending on the material model. - * This method can be used to set the initial values of internal - * variables, stresses, etc., which have been previously determined - * by another simulation (e.g. of the manufacturing process). - */ - virtual void setStatusVariable(int varID, double value) { } - /** - * Restores consistency of the status, i.e., computes or corrects - * the values of certain status variables such that the state is admissible. - * For instance, if the initial values of some internal variables - * are read from a file, other internal variables are adjusted accordingly. - */ - virtual void restoreConsistency() { } - - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } }; } // end namespace oofem #endif // matstatus_h diff --git a/src/oofemlib/mesherinterface.h b/src/oofemlib/mesherinterface.h index 403cc21db..7f42e2e01 100644 --- a/src/oofemlib/mesherinterface.h +++ b/src/oofemlib/mesherinterface.h @@ -77,7 +77,7 @@ class OOFEM_EXPORT MesherInterface * belonging to receiver. Receiver may use value-name extracting functions * to extract particular field from record. */ - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + virtual void initializeFrom(InputRecord &ir) { } }; } // end namespace oofem #endif // mesherinterface_h diff --git a/src/oofemlib/meshqualityerrorestimator.C b/src/oofemlib/meshqualityerrorestimator.C index b8e0325ce..2657e1dbd 100644 --- a/src/oofemlib/meshqualityerrorestimator.C +++ b/src/oofemlib/meshqualityerrorestimator.C @@ -71,14 +71,12 @@ double MeshQualityErrorEstimator :: computeTriangleRadiusError(Element *elem) { // Outside/inside circle radius fraction based for quality measurement. // Zero for a perfect triangle, - double a, b, c; - FloatArray *c1, *c2, *c3; - c1 = elem->giveNode(1)->giveCoordinates(); - c2 = elem->giveNode(2)->giveCoordinates(); - c3 = elem->giveNode(3)->giveCoordinates(); - a = c1->distance(* c2); - b = c1->distance(* c3); - c = c2->distance(* c3); + const auto &c1 = elem->giveNode(1)->giveCoordinates(); + const auto &c2 = elem->giveNode(2)->giveCoordinates(); + const auto &c3 = elem->giveNode(3)->giveCoordinates(); + double a = distance(c1, c2); + double b = distance(c1, c3); + double c = distance(c2, c3); return a * b * c / ( ( b + c - a ) * ( a + c - b ) * ( a + b - c ) ) - 1.0; // Reciprocal error would be; // (b+c-a)*(a+c-b)*(a+b-c)/(a*b*c - (b+c-a)*(a+c-b)*(a+b-c)); @@ -90,7 +88,7 @@ double MeshQualityErrorEstimator :: computeJacobianError(FEInterpolation &fei, I double min_rcond = 1.0, rcond; FloatMatrix jac; - for ( GaussPoint *gp: ir ) { + for ( auto &gp: ir ) { fei.giveJacobianMatrixAt( jac, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(elem) ); rcond = jac.computeReciprocalCondition() * sgn( jac.giveDeterminant() ); // Signed rcond. as inverted mappings are particularly bad. if ( rcond < min_rcond ) { @@ -102,9 +100,9 @@ double MeshQualityErrorEstimator :: computeJacobianError(FEInterpolation &fei, I double MeshQualityErrorEstimator :: giveValue(EE_ValueType type, TimeStep *tStep) { - double error = 0.0, temp; + double error = 0.0; for ( auto &elem : this->domain->giveElements() ) { - temp = this->giveElementError(unknownET, elem.get(), tStep); + double temp = this->giveElementError(unknownET, elem.get(), tStep); if ( temp > error ) { error = temp; } @@ -117,8 +115,8 @@ int MeshQualityErrorEstimator :: estimateError(EE_ErrorMode mode, TimeStep *tSte return true; } -IRResultType MeshQualityErrorEstimator :: initializeFrom(InputRecord *ir) +void MeshQualityErrorEstimator :: initializeFrom(InputRecord &ir) { - return ErrorEstimator :: initializeFrom(ir); + ErrorEstimator :: initializeFrom(ir); } } // end namespace oofem diff --git a/src/oofemlib/meshqualityerrorestimator.h b/src/oofemlib/meshqualityerrorestimator.h index 17f65e5a9..803bd2f52 100644 --- a/src/oofemlib/meshqualityerrorestimator.h +++ b/src/oofemlib/meshqualityerrorestimator.h @@ -38,6 +38,8 @@ #include "errorestimator.h" #include "errorestimatortype.h" +#define _IFT_MeshQualityErrorEstimator_Name "meshquality" + namespace oofem { class Domain; class Element; @@ -79,18 +81,19 @@ class OOFEM_EXPORT MeshQualityErrorEstimator : public ErrorEstimator /// Destructor virtual ~MeshQualityErrorEstimator() { } - virtual double giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep); + double giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep) override; /// Gives the max error from any element in the domain. - virtual double giveValue(EE_ValueType type, TimeStep *tStep); + double giveValue(EE_ValueType type, TimeStep *tStep) override; /// Empty implementation. - virtual int estimateError(EE_ErrorMode mode, TimeStep *tStep); + int estimateError(EE_ErrorMode mode, TimeStep *tStep) override; - virtual RemeshingCriteria *giveRemeshingCrit() { return NULL; } + RemeshingCriteria *giveRemeshingCrit() override { return nullptr; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "MeshQualityErrorEstimator"; } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "MeshQualityErrorEstimator"; } + const char *giveInputRecordName() const override { return _IFT_MeshQualityErrorEstimator_Name; } }; } // end namespace oofem #endif // meshqualityerrorestimator_h diff --git a/src/oofemlib/metastep.C b/src/oofemlib/metastep.C index a280d7351..2e24e27bc 100644 --- a/src/oofemlib/metastep.C +++ b/src/oofemlib/metastep.C @@ -35,39 +35,26 @@ #include "metastep.h" namespace oofem { -MetaStep :: MetaStep(int n, EngngModel *e) -{ - this->number = n; - this->eModel = e; - this->numberOfSteps = 0; - this->attributes = NULL; -} +MetaStep :: MetaStep(int n, EngngModel *e) : + eModel(e), + numberOfSteps(0), + number(n) +{} -MetaStep :: MetaStep(int n, EngngModel *e, int nsteps, InputRecord &attrib) -{ - this->number = n; - this->eModel = e; - this->numberOfSteps = nsteps; - this->attributes = attrib.GiveCopy(); -} +MetaStep :: MetaStep(int n, EngngModel *e, int nsteps, InputRecord &attrib) : + eModel(e), + numberOfSteps(nsteps), + attributes(attrib.clone()), + number(n) +{} -MetaStep :: ~MetaStep() -{ - delete attributes; -} - -IRResultType -MetaStep :: initializeFrom(InputRecord *ir) +void +MetaStep :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, numberOfSteps, _IFT_MetaStep_nsteps); - delete attributes; - this->attributes = ir->GiveCopy(); - - return IRRT_OK; + this->attributes = ir.clone(); } int @@ -87,11 +74,6 @@ MetaStep :: setNumberOfSteps(int newNumberOfSteps) int MetaStep :: isStepValid(int solStepNumber) { - if ( ( solStepNumber >= sindex ) && - ( solStepNumber < ( sindex + numberOfSteps ) ) ) { - return 1; - } - - return 0; + return solStepNumber >= sindex && solStepNumber < ( sindex + numberOfSteps ); } } // end namespace oofem diff --git a/src/oofemlib/metastep.h b/src/oofemlib/metastep.h index ac05ee8d6..f72b90721 100644 --- a/src/oofemlib/metastep.h +++ b/src/oofemlib/metastep.h @@ -38,6 +38,8 @@ #include "oofemcfg.h" #include "inputrecord.h" +#include + ///@name Input fields for meta step //@{ #define _IFT_MetaStep_Name "metastep" @@ -69,7 +71,7 @@ class OOFEM_EXPORT MetaStep /// Intrinsic time increment. double deltaT; /// Engineering model attributes. - InputRecord *attributes; + std::unique_ptr attributes; /// Start solution step number for which receiver is responsible. int sindex; /// Receiver number. @@ -82,8 +84,7 @@ class OOFEM_EXPORT MetaStep */ MetaStep(int n, EngngModel * e); MetaStep(int n, EngngModel * e, int nsteps, InputRecord & attrib); - /// Destructor. - ~MetaStep(); + MetaStep(MetaStep &&ms) = default; /// Returns receiver's number. int giveNumber() { return number; } @@ -92,11 +93,11 @@ class OOFEM_EXPORT MetaStep /// Returns time increment. double giveTimeIncrement() { return this->deltaT; } /// Returns e-model attributes. - InputRecord *giveAttributesRecord() { return this->attributes; } + InputRecord &giveAttributesRecord() { return *this->attributes; } /** * Instanciates the receiver from input record. */ - IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir); /// Sets the receiver bounds according to given solution step number, returns end index. int setStepBounds(int startStepNumber); /// Sets the number of steps within the metastep. diff --git a/src/oofemlib/mixedgradientpressurebc.C b/src/oofemlib/mixedgradientpressurebc.C index 8fdaf57b4..fd0c136d9 100644 --- a/src/oofemlib/mixedgradientpressurebc.C +++ b/src/oofemlib/mixedgradientpressurebc.C @@ -58,9 +58,9 @@ double MixedGradientPressureBC :: domainSize() } -IRResultType MixedGradientPressureBC :: initializeFrom(InputRecord *ir) +void MixedGradientPressureBC :: initializeFrom(InputRecord &ir) { - IRResultType result; + GeneralBoundaryCondition :: initializeFrom(ir); FloatArray devGradient; double pressure; @@ -70,7 +70,5 @@ IRResultType MixedGradientPressureBC :: initializeFrom(InputRecord *ir) this->setPrescribedDeviatoricGradientFromVoigt(devGradient); this->setPrescribedPressure(pressure); - - return GeneralBoundaryCondition :: initializeFrom(ir); } } // end namespace oofem diff --git a/src/oofemlib/mixedgradientpressurebc.h b/src/oofemlib/mixedgradientpressurebc.h index 09b321431..a517db0da 100644 --- a/src/oofemlib/mixedgradientpressurebc.h +++ b/src/oofemlib/mixedgradientpressurebc.h @@ -69,7 +69,7 @@ class OOFEM_EXPORT MixedGradientPressureBC : public ActiveBoundaryCondition virtual ~MixedGradientPressureBC() { } /// Not relevant for this boundary condition. - virtual bcType giveType() const { return UnknownBT; } + bcType giveType() const override { return UnknownBT; } /** * Initializes receiver according to object description stored in input record. @@ -80,7 +80,7 @@ class OOFEM_EXPORT MixedGradientPressureBC : public ActiveBoundaryCondition * The prescribed tensor's columns must be equal to the size of the center coordinates. * The size of the center coordinates must be equal to the size of the coordinates in the applied nodes. */ - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; /** * Computes the size (including pores) by surface integral over the domain diff --git a/src/oofemlib/mixedgradientpressuredirichlet.C b/src/oofemlib/mixedgradientpressuredirichlet.C index 65a3c1c46..af25387d7 100644 --- a/src/oofemlib/mixedgradientpressuredirichlet.C +++ b/src/oofemlib/mixedgradientpressuredirichlet.C @@ -53,6 +53,10 @@ #include "unknownnumberingscheme.h" #include "assemblercallback.h" +#ifdef _OPENMP +#include +#endif + namespace oofem { REGISTER_BoundaryCondition(MixedGradientPressureDirichlet); @@ -132,10 +136,10 @@ Dof *MixedGradientPressureDirichlet :: giveMasterDof(ActiveDof *dof, int mdof) void MixedGradientPressureDirichlet :: computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs) { DofIDItem id = dof->giveDofID(); - FloatArray *coords = dof->giveDofManager()->giveCoordinates(); + const auto &coords = dof->giveDofManager()->giveCoordinates(); FloatArray dx; - dx.beDifferenceOf(* coords, this->centerCoord); + dx.beDifferenceOf(coords, this->centerCoord); int nsd = dx.giveSize(); // Number of spatial dimensions @@ -185,14 +189,10 @@ void MixedGradientPressureDirichlet :: computeDofTransformation(ActiveDof *dof, double MixedGradientPressureDirichlet :: giveUnknown(double vol, const FloatArray &dev, ValueModeType mode, TimeStep *tStep, ActiveDof *dof) { DofIDItem id = dof->giveDofID(); - FloatArray *coords = dof->giveDofManager()->giveCoordinates(); - - if ( coords == NULL || coords->giveSize() != this->centerCoord.giveSize() ) { - OOFEM_ERROR("Size of coordinate system different from center coordinate (%d) in b.c.", this->centerCoord.giveSize() ); - } + const auto &coords = dof->giveDofManager()->giveCoordinates(); FloatArray dx; - dx.beDifferenceOf(* coords, this->centerCoord); + dx.beDifferenceOf(coords, this->centerCoord); int nsd = dx.giveSize(); // Number of spatial dimensions @@ -397,7 +397,10 @@ void MixedGradientPressureDirichlet :: setPrescribedDeviatoricGradientFromVoigt( void MixedGradientPressureDirichlet :: assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, + FloatArray *eNorms, + void* lock) { if ( type != ExternalForcesVector ) { return; @@ -407,10 +410,16 @@ void MixedGradientPressureDirichlet :: assembleVector(FloatArray &answer, TimeSt int vol_loc = vol->giveEquationNumber(s); if ( vol_loc ) { double rve_size = this->domainSize(); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.at(vol_loc) -= rve_size * pressure; // Note the negative sign (pressure as opposed to mean stress) if ( eNorms ) { eNorms->at( vol->giveDofID() ) = rve_size * pressure * rve_size * pressure; } +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } @@ -443,15 +452,13 @@ bool MixedGradientPressureDirichlet :: isDevDof(Dof *dof) } -IRResultType MixedGradientPressureDirichlet :: initializeFrom(InputRecord *ir) +void MixedGradientPressureDirichlet :: initializeFrom(InputRecord &ir) { - IRResultType result; + MixedGradientPressureBC :: initializeFrom(ir); this->centerCoord.resize( domain->giveNumberOfSpatialDimensions() ); this->centerCoord.zero(); IR_GIVE_OPTIONAL_FIELD(ir, this->centerCoord, _IFT_MixedGradientPressure_centerCoords) - - return MixedGradientPressureBC :: initializeFrom(ir); } diff --git a/src/oofemlib/mixedgradientpressuredirichlet.h b/src/oofemlib/mixedgradientpressuredirichlet.h index 90f9420c8..444ab454a 100644 --- a/src/oofemlib/mixedgradientpressuredirichlet.h +++ b/src/oofemlib/mixedgradientpressuredirichlet.h @@ -107,11 +107,11 @@ class OOFEM_EXPORT MixedGradientPressureDirichlet : public MixedGradientPressure * This boundary condition stores its own DOF managers, one for @f$ d_{\mathrm{dev},ij} @f$ in which the DOFs are prescribed * and one for @f$ d_{\mathrm{vol}} @f$ for single free volumetric strain rate. */ - virtual int giveNumberOfInternalDofManagers(); + int giveNumberOfInternalDofManagers() override; /** * Returns the volumetric DOF manager for i == 1, and the deviatoric manager for i == 2. */ - virtual DofManager *giveInternalDofManager(int i); + DofManager *giveInternalDofManager(int i) override; /** * Initializes receiver according to object description stored in input record. @@ -123,19 +123,19 @@ class OOFEM_EXPORT MixedGradientPressureDirichlet : public MixedGradientPressure * The prescribed tensor's columns must be equal to the size of the center coordinates. * The size of the center coordinates must be equal to the size of the coordinates in the applied nodes. */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void scale(double s) { + void scale(double s) override { devGradient.times(s); pressure *= s; } - virtual void computeFields(FloatArray &stressDev, double &vol, TimeStep *tStep); - virtual void computeTangents(FloatMatrix &Ed, FloatArray &Ep, FloatArray &Cd, double &Cp, TimeStep *tStep); + void computeFields(FloatArray &stressDev, double &vol, TimeStep *tStep) override; + void computeTangents(FloatMatrix &Ed, FloatArray &Ep, FloatArray &Cd, double &Cp, TimeStep *tStep) override; - virtual void setPrescribedPressure(double p) { pressure = p; } - virtual void setPrescribedDeviatoricGradientFromVoigt(const FloatArray &ddev); + void setPrescribedPressure(double p) override { pressure = p; } + void setPrescribedDeviatoricGradientFromVoigt(const FloatArray &ddev) override; /** * Set the center coordinate. @@ -143,31 +143,32 @@ class OOFEM_EXPORT MixedGradientPressureDirichlet : public MixedGradientPressure */ virtual void setCenterCoordinate(const FloatArray &x) { centerCoord = x; } /// Returns the center coordinate - virtual FloatArray &giveCenterCoordinate() { return centerCoord; } + FloatArray &giveCenterCoordinate() { return centerCoord; } - virtual void assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorms = NULL); + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorms=nullptr, + void* lock=nullptr) override; - virtual bool requiresActiveDofs() { return true; } - virtual bool isPrimaryDof(ActiveDof *dof); + bool requiresActiveDofs() override { return true; } + bool isPrimaryDof(ActiveDof *dof) override; - virtual double giveBcValue(Dof *dof, ValueModeType mode, TimeStep *tStep); - virtual bool hasBc(Dof *dof, TimeStep *tStep); + double giveBcValue(Dof *dof, ValueModeType mode, TimeStep *tStep) override; + bool hasBc(Dof *dof, TimeStep *tStep) override; /// Returns true is DOF represents one of the deviatoric parts. bool isDevDof(Dof *dof); - virtual int giveNumberOfMasterDofs(ActiveDof *dof); - virtual Dof *giveMasterDof(ActiveDof *dof, int mdof); - virtual void computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs); + int giveNumberOfMasterDofs(ActiveDof *dof) override; + Dof *giveMasterDof(ActiveDof *dof, int mdof) override; + void computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs) override; double giveUnknown(double vol, const FloatArray &dev, ValueModeType mode, TimeStep *tStep, ActiveDof *dof); - virtual double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof); - virtual double giveUnknown(ValueModeType mode, TimeStep *tStep, ActiveDof *dof); + double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof) override; + double giveUnknown(ValueModeType mode, TimeStep *tStep, ActiveDof *dof) override; - virtual const char *giveClassName() const { return "MixedGradientPressureDirichlet"; } - virtual const char *giveInputRecordName() const { return _IFT_MixedGradientPressureDirichlet_Name; } + const char *giveClassName() const override { return "MixedGradientPressureDirichlet"; } + const char *giveInputRecordName() const override { return _IFT_MixedGradientPressureDirichlet_Name; } }; } // end namespace oofem diff --git a/src/oofemlib/mixedgradientpressureneumann.C b/src/oofemlib/mixedgradientpressureneumann.C index c46959065..bd81b90ca 100644 --- a/src/oofemlib/mixedgradientpressureneumann.C +++ b/src/oofemlib/mixedgradientpressureneumann.C @@ -56,11 +56,15 @@ #include "feinterpol.h" #include "unknownnumberingscheme.h" +#ifdef _OPENMP +#include +#endif + namespace oofem { REGISTER_BoundaryCondition(MixedGradientPressureNeumann); MixedGradientPressureNeumann :: MixedGradientPressureNeumann(int n, Domain *d) : MixedGradientPressureBC(n, d), - sigmaDev(new Node(-1, d)) // Node number lacks meaning here. + sigmaDev(std::make_unique(-1, d)) // Node number lacks meaning here. { ///@todo Rethink this. Should be created as part of createDofs() int nsd = d->giveNumberOfSpatialDimensions(); @@ -242,7 +246,6 @@ void MixedGradientPressureNeumann :: giveLocationArrays(std :: vector< IntArray return; } - IntArray bNodes; IntArray loc_r, loc_c, sigma_loc_r, sigma_loc_c; // Fetch the columns/rows for the stress contributions; @@ -259,7 +262,7 @@ void MixedGradientPressureNeumann :: giveLocationArrays(std :: vector< IntArray Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc_r, bNodes, this->dofs, r_s); e->giveBoundaryLocationArray(loc_c, bNodes, this->dofs, c_s); // For most uses, loc_r == loc_c, and sigma_loc_r == sigma_loc_c. @@ -395,14 +398,16 @@ void MixedGradientPressureNeumann :: integrateDevTangent(FloatMatrix &answer, El void MixedGradientPressureNeumann :: assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, + FloatArray *eNorms, + void* lock) { Set *set = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = set->giveBoundaryList(); IntArray loc, sigma_loc; // For the velocities and stress respectively IntArray masterDofIDs; - IntArray bNodes; this->sigmaDev->giveLocationArray(dev_id, sigma_loc, s); if ( type == ExternalForcesVector ) { @@ -410,7 +415,13 @@ void MixedGradientPressureNeumann :: assembleVector(FloatArray &answer, TimeStep double rve_size = this->domainSize(); FloatArray devLoad; devLoad.beScaled(-rve_size, this->devGradient); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(devLoad, sigma_loc); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif // The second contribution is on the momentumbalance equation; - int delta_v . n dA * p FloatArray fe; @@ -418,14 +429,20 @@ void MixedGradientPressureNeumann :: assembleVector(FloatArray &answer, TimeStep Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc, bNodes, this->dofs, s, & masterDofIDs); this->integrateVolTangent(fe, e, boundary); fe.times(-this->pressure); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(fe, loc); if ( eNorms ) { eNorms->assembleSquared(fe, masterDofIDs); } +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } else if ( type == InternalForcesVector ) { FloatMatrix Ke; @@ -442,7 +459,7 @@ void MixedGradientPressureNeumann :: assembleVector(FloatArray &answer, TimeStep int boundary = boundaries.at(pos * 2); // Fetch the element information; - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc, bNodes, this->dofs, s, & masterDofIDs); e->computeBoundaryVectorOf(bNodes, this->dofs, mode, tStep, e_v); this->integrateDevTangent(Ke, e, boundary); @@ -454,24 +471,31 @@ void MixedGradientPressureNeumann :: assembleVector(FloatArray &answer, TimeStep fe_v.negated(); fe_s.negated(); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(fe_s, loc); // Contributions to delta_v equations answer.assemble(fe_v, sigma_loc); // Contribution to delta_s_i equations if ( eNorms ) { eNorms->assembleSquared(fe_s, masterDofIDs); eNorms->assembleSquared(fe_v, dev_id); } +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } } void MixedGradientPressureNeumann :: assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale) + CharType type, const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, double scale, + void* lock) { if ( type == TangentStiffnessMatrix || type == SecantStiffnessMatrix || type == ElasticStiffnessMatrix ) { FloatMatrix Ke, KeT; IntArray loc_r, loc_c, sigma_loc_r, sigma_loc_c; - IntArray bNodes; Set *set = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = set->giveBoundaryList(); @@ -484,15 +508,21 @@ void MixedGradientPressureNeumann :: assemble(SparseMtrx &answer, TimeStep *tSte int boundary = boundaries.at(pos * 2); // Fetch the element information; - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc_r, bNodes, this->dofs, r_s); e->giveBoundaryLocationArray(loc_c, bNodes, this->dofs, c_s); this->integrateDevTangent(Ke, e, boundary); Ke.negated(); Ke.times(scale); KeT.beTranspositionOf(Ke); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(sigma_loc_r, loc_c, Ke); // Contribution to delta_s_i equations answer.assemble(loc_r, sigma_loc_c, KeT); // Contributions to delta_v equations +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } } @@ -520,14 +550,13 @@ void MixedGradientPressureNeumann :: computeFields(FloatArray &sigmaDev, double } // Postprocessing; vol = int v . n dA - IntArray bNodes; FloatArray unknowns, fe; vol = 0.; for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->computeBoundaryVectorOf(bNodes, this->dofs, VM_Total, tStep, unknowns); this->integrateVolTangent(fe, e, boundary); vol += fe.dotProduct(unknowns); @@ -548,7 +577,6 @@ void MixedGradientPressureNeumann :: computeTangents(FloatMatrix &Ed, FloatArray SparseMtrxType stype = solver->giveRecommendedMatrix(true); EModelDefaultEquationNumbering fnum; Set *set = this->giveDomain()->giveSet(this->set); - IntArray bNodes; const IntArray &boundaries = set->giveBoundaryList(); double rve_size = this->domainSize(); @@ -588,7 +616,7 @@ void MixedGradientPressureNeumann :: computeTangents(FloatMatrix &Ed, FloatArray Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc, bNodes, this->dofs, fnum); this->integrateVolTangent(fe, e, boundary); fe.times(-1.0); // here d_p = 1.0 @@ -620,7 +648,7 @@ void MixedGradientPressureNeumann :: computeTangents(FloatMatrix &Ed, FloatArray this->integrateVolTangent(fe, e, boundary); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc, bNodes, this->dofs, fnum); // Using "loc" to pick out the relevant contributions. This won't work at all if there are local coordinate systems in these nodes @@ -657,9 +685,9 @@ void MixedGradientPressureNeumann :: computeTangents(FloatMatrix &Ed, FloatArray } -IRResultType MixedGradientPressureNeumann :: initializeFrom(InputRecord *ir) +void MixedGradientPressureNeumann :: initializeFrom(InputRecord &ir) { - return MixedGradientPressureBC :: initializeFrom(ir); + MixedGradientPressureBC :: initializeFrom(ir); } diff --git a/src/oofemlib/mixedgradientpressureneumann.h b/src/oofemlib/mixedgradientpressureneumann.h index b538eba87..fb07fb7c6 100644 --- a/src/oofemlib/mixedgradientpressureneumann.h +++ b/src/oofemlib/mixedgradientpressureneumann.h @@ -123,14 +123,14 @@ class OOFEM_EXPORT MixedGradientPressureNeumann : public MixedGradientPressureBC * This boundary condition stores its own DOF managers, one for @f$ d_{\mathrm{dev},ij} @f$ in which the DOFs are prescribed * and one for @f$ d_{\mathrm{vol}} @f$ for single free volumetric strain rate. */ - virtual int giveNumberOfInternalDofManagers(); + int giveNumberOfInternalDofManagers() override; /** * Returns the volumetric DOF manager for i == 1, and the deviatoric manager for i == 2. */ - virtual DofManager *giveInternalDofManager(int i); + DofManager *giveInternalDofManager(int i) override; /// Not relevant for this boundary condition. - virtual bcType giveType() const { return UnknownBT; } + bcType giveType() const override { return UnknownBT; } /** * Initializes receiver according to object description stored in input record. @@ -139,29 +139,31 @@ class OOFEM_EXPORT MixedGradientPressureNeumann : public MixedGradientPressureBC * - pressure p (required) * The gradient should be in Voigt notation (only the deviatoric part will be used) */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void scale(double s); + void scale(double s) override; - virtual void computeFields(FloatArray &sigmaDev, double &vol, TimeStep *tStep); - virtual void computeTangents(FloatMatrix &Ed, FloatArray &Ep, FloatArray &Cd, double &Cp, TimeStep *tStep); + void computeFields(FloatArray &sigmaDev, double &vol, TimeStep *tStep) override; + void computeTangents(FloatMatrix &Ed, FloatArray &Ep, FloatArray &Cd, double &Cp, TimeStep *tStep) override; - virtual void setPrescribedPressure(double p) { pressure = p; } - virtual void setPrescribedDeviatoricGradientFromVoigt(const FloatArray &ddev); + void setPrescribedPressure(double p) override { pressure = p; } + void setPrescribedDeviatoricGradientFromVoigt(const FloatArray &ddev) override; - virtual void assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm = NULL); + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorm=nullptr, + void*lock=nullptr) override; - virtual void assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0); + void assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, + double scale = 1.0, void*lock=nullptr) override; - virtual void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, - const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s); + void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) override; - virtual const char *giveClassName() const { return "MixedGradientPressureNeumann"; } - virtual const char *giveInputRecordName() const { return _IFT_MixedGradientPressureNeumann_Name; } + const char *giveClassName() const override { return "MixedGradientPressureNeumann"; } + const char *giveInputRecordName() const override { return _IFT_MixedGradientPressureNeumann_Name; } protected: /// Helper function that integrates the deviatoric tangent contribution from a single element boundary. diff --git a/src/oofemlib/mixedgradientpressureweakperiodic.C b/src/oofemlib/mixedgradientpressureweakperiodic.C index e4258a429..46240b67a 100644 --- a/src/oofemlib/mixedgradientpressureweakperiodic.C +++ b/src/oofemlib/mixedgradientpressureweakperiodic.C @@ -56,6 +56,10 @@ #include "feinterpol.h" #include "unknownnumberingscheme.h" +#ifdef _OPENMP +#include +#endif + namespace oofem { REGISTER_BoundaryCondition(MixedGradientPressureWeakPeriodic); @@ -90,10 +94,9 @@ DofManager *MixedGradientPressureWeakPeriodic :: giveInternalDofManager(int i) } -IRResultType MixedGradientPressureWeakPeriodic :: initializeFrom(InputRecord *ir) +void MixedGradientPressureWeakPeriodic :: initializeFrom(InputRecord &ir) { - IRResultType result; - + MixedGradientPressureBC :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->order, _IFT_MixedGradientPressureWeakPeriodic_order); if ( this->order < 0 ) { @@ -111,8 +114,6 @@ IRResultType MixedGradientPressureWeakPeriodic :: initializeFrom(InputRecord *ir // then the linear terms, [x,0,0], [0,x,0] ... and so on this->tractionsdman->appendDof( new MasterDof( tractionsdman.get(), ( DofIDItem ) dofid ) ); } - - return MixedGradientPressureBC :: initializeFrom(ir); } @@ -169,7 +170,6 @@ void MixedGradientPressureWeakPeriodic :: giveLocationArrays(std :: vector< IntA this->voldman->giveLocationArray(v_id, e_loc_c, c_s); Set *set = this->giveDomain()->giveSet(this->set); - IntArray bNodes; const IntArray &boundaries = set->giveBoundaryList(); rows.resize(boundaries.giveSize() + 2); @@ -179,7 +179,7 @@ void MixedGradientPressureWeakPeriodic :: giveLocationArrays(std :: vector< IntA Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc_r, bNodes, this->dofs, r_s); e->giveBoundaryLocationArray(loc_c, bNodes, this->dofs, c_s); // For most uses, *loc_r == *loc_c @@ -340,7 +340,10 @@ void MixedGradientPressureWeakPeriodic :: integrateTractionDev(FloatArray &answe void MixedGradientPressureWeakPeriodic :: assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms) + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, + FloatArray *eNorms, + void*lock) { Set *set = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = set->giveBoundaryList(); @@ -355,10 +358,16 @@ void MixedGradientPressureWeakPeriodic :: assembleVector(FloatArray &answer, Tim double rve_size = this->domainSize(); if ( e_loc.at(1) ) { +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.at( e_loc.at(1) ) -= rve_size * pressure; // Note the negative sign (pressure as opposed to mean stress) if ( eNorms ) { eNorms->at( v_id.at(1) ) += rve_size * pressure * rve_size * pressure; } +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } // The second contribution is on the momentumbalance equation; int t . [[ d_dev . x ]] dA = int t . [[ d_dev . x ]] dA @@ -369,11 +378,16 @@ void MixedGradientPressureWeakPeriodic :: assembleVector(FloatArray &answer, Tim this->integrateTractionDev(fe, e, boundary, this->devGradient); fe.negated(); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(fe, t_loc); if ( eNorms ) { eNorms->assembleSquared(fe, velocityDofIDs); } +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } else if ( type == InternalForcesVector ) { FloatMatrix Ke_v, Ke_e; @@ -392,7 +406,7 @@ void MixedGradientPressureWeakPeriodic :: assembleVector(FloatArray &answer, Tim int boundary = boundaries.at(pos * 2); // Fetch the element information; - el->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = el->giveInterpolation()->boundaryGiveNodes(boundary); el->giveBoundaryLocationArray(v_loc, bNodes, this->dofs, s, & velocityDofIDs); el->computeBoundaryVectorOf(bNodes, this->dofs, mode, tStep, v); @@ -408,7 +422,9 @@ void MixedGradientPressureWeakPeriodic :: assembleVector(FloatArray &answer, Tim fe_t2.beProductOf(Ke_e, e); fe_t.add(fe_t2); fe_e.beTProductOf(Ke_e, t); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(fe_v, v_loc); // Contributions to delta_v equations answer.assemble(fe_t, t_loc); // Contribution to delta_t equations answer.assemble(fe_e, e_loc); // Contribution to delta_e equations @@ -417,18 +433,22 @@ void MixedGradientPressureWeakPeriodic :: assembleVector(FloatArray &answer, Tim eNorms->assembleSquared(fe_t, t_id); eNorms->assembleSquared(fe_e, v_id); } +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } } void MixedGradientPressureWeakPeriodic :: assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale) + CharType type, const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, double scale, + void*lock) { if ( type == TangentStiffnessMatrix || type == SecantStiffnessMatrix || type == ElasticStiffnessMatrix ) { FloatMatrix Ke_v, Ke_vT, Ke_e, Ke_eT; IntArray v_loc_r, v_loc_c, t_loc_r, t_loc_c, e_loc_r, e_loc_c; - IntArray bNodes; Set *set = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = set->giveBoundaryList(); @@ -444,7 +464,7 @@ void MixedGradientPressureWeakPeriodic :: assemble(SparseMtrx &answer, TimeStep int boundary = boundaries.at(pos * 2); // Fetch the element information; - el->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = el->giveInterpolation()->boundaryGiveNodes(boundary); el->giveBoundaryLocationArray(v_loc_r, bNodes, this->dofs, r_s); el->giveBoundaryLocationArray(v_loc_c, bNodes, this->dofs, c_s); @@ -456,11 +476,17 @@ void MixedGradientPressureWeakPeriodic :: assemble(SparseMtrx &answer, TimeStep Ke_vT.beTranspositionOf(Ke_v); Ke_eT.beTranspositionOf(Ke_e); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(t_loc_r, v_loc_c, Ke_v); answer.assemble(v_loc_r, t_loc_c, Ke_vT); answer.assemble(t_loc_r, e_loc_c, Ke_e); answer.assemble(e_loc_r, t_loc_c, Ke_eT); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } } diff --git a/src/oofemlib/mixedgradientpressureweakperiodic.h b/src/oofemlib/mixedgradientpressureweakperiodic.h index 50c1c128f..780d87b52 100644 --- a/src/oofemlib/mixedgradientpressureweakperiodic.h +++ b/src/oofemlib/mixedgradientpressureweakperiodic.h @@ -101,14 +101,14 @@ class OOFEM_EXPORT MixedGradientPressureWeakPeriodic : public MixedGradientPress * Returns the number of internal DOF managers (=2). * This boundary condition stores its own DOF managers, one for tractions and one for @f$ d_{\mathrm{vol}} @f$ which is a single DOF for the volumetric gradient. */ - virtual int giveNumberOfInternalDofManagers(); + int giveNumberOfInternalDofManagers() override; /** * Returns the volumetric DOF manager for i == 1, and the deviatoric manager for i == 2. */ - virtual DofManager *giveInternalDofManager(int i); + DofManager *giveInternalDofManager(int i) override; /// Not relevant for this boundary condition. - virtual bcType giveType() const { return UnknownBT; } + bcType giveType() const override { return UnknownBT; } /** * Initializes receiver according to object description stored in input record. @@ -117,30 +117,33 @@ class OOFEM_EXPORT MixedGradientPressureWeakPeriodic : public MixedGradientPress * - pressure p (required) * The gradient should be in Voigt notation (only the deviatoric part will be used) */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void scale(double s); + void scale(double s) override; - virtual void computeFields(FloatArray &sigmaDev, double &vol, TimeStep *tStep); + void computeFields(FloatArray &sigmaDev, double &vol, TimeStep *tStep) override; void computeStress(FloatArray &sigmaDev, FloatArray &tractions, double rve_size); - virtual void computeTangents(FloatMatrix &Ed, FloatArray &Ep, FloatArray &Cd, double &Cp, TimeStep *tStep); + void computeTangents(FloatMatrix &Ed, FloatArray &Ep, FloatArray &Cd, double &Cp, TimeStep *tStep) override; - virtual void setPrescribedPressure(double p) { pressure = p; } - virtual void setPrescribedDeviatoricGradientFromVoigt(const FloatArray &ddev); + void setPrescribedPressure(double p) override { pressure = p; } + void setPrescribedDeviatoricGradientFromVoigt(const FloatArray &ddev) override; - virtual void assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm = NULL); + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorm=nullptr, + void*lock=nullptr) override; - virtual void assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0); + void assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, double scale = 1.0, + void* lock=nullptr) override; - virtual void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, - const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s); + void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) override; - virtual const char *giveClassName() const { return "MixedGradientPressureWeakPeriodic"; } - virtual const char *giveInputRecordName() const { return _IFT_MixedGradientPressureWeakPeriodic_Name; } + const char *giveClassName() const override { return "MixedGradientPressureWeakPeriodic"; } + const char *giveInputRecordName() const override { return _IFT_MixedGradientPressureWeakPeriodic_Name; } protected: void integrateTractionVelocityTangent(FloatMatrix &answer, Element *el, int boundary); diff --git a/src/oofemlib/mklpardisosolver.h b/src/oofemlib/mklpardisosolver.h index 40c909875..faa5e4c6c 100644 --- a/src/oofemlib/mklpardisosolver.h +++ b/src/oofemlib/mklpardisosolver.h @@ -37,6 +37,8 @@ #include "sparselinsystemnm.h" +#define _IFT_MKLPardisoSolver_Name "mklpardiso" + namespace oofem { /** @@ -55,14 +57,13 @@ class OOFEM_EXPORT MKLPardisoSolver : public SparseLinearSystemNM * @param m Engineering model which solver belongs to. */ MKLPardisoSolver(Domain * d, EngngModel * m); - virtual ~MKLPardisoSolver(); - virtual NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x); + NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x) override; - virtual const char *giveClassName() const { return "MKLPardisoSolver"; } - virtual LinSystSolverType giveLinSystSolverType() const { return ST_MKLPardiso; } - virtual SparseMtrxType giveRecommendedMatrix(bool symmetric) const { return SMT_CompCol; } + const char *giveClassName() const override { return "MKLPardisoSolver"; } + LinSystSolverType giveLinSystSolverType() const override { return ST_MKLPardiso; } + SparseMtrxType giveRecommendedMatrix(bool symmetric) const override { return SMT_CompCol; } }; } // end namespace oofem #endif // mklpardisosolver_h diff --git a/src/oofemlib/mmaclosestiptransfer.C b/src/oofemlib/mmaclosestiptransfer.C index ee37b9050..70c9fdb11 100644 --- a/src/oofemlib/mmaclosestiptransfer.C +++ b/src/oofemlib/mmaclosestiptransfer.C @@ -38,9 +38,12 @@ #include "material.h" #include "gausspoint.h" #include "matstatmapperint.h" +#include "classfactory.h" #include "xfem/xfemelementinterface.h" namespace oofem { +REGISTER_MaterialMappingAlgorithm(MMAClosestIPTransfer, MMA_ClosestPoint); + MMAClosestIPTransfer :: MMAClosestIPTransfer() : MaterialMappingAlgorithm() { } diff --git a/src/oofemlib/mmaclosestiptransfer.h b/src/oofemlib/mmaclosestiptransfer.h index b2c7a74f0..4f299f1ba 100644 --- a/src/oofemlib/mmaclosestiptransfer.h +++ b/src/oofemlib/mmaclosestiptransfer.h @@ -37,6 +37,8 @@ #include "materialmappingalgorithm.h" +#define _IFT_MMAClosestIPTransfer_Name "closest" + namespace oofem { class Domain; class Element; @@ -55,16 +57,17 @@ class OOFEM_EXPORT MMAClosestIPTransfer : public MaterialMappingAlgorithm public: /// Constructor MMAClosestIPTransfer(); + virtual ~MMAClosestIPTransfer() {} - virtual void __init(Domain *dold, IntArray &type, const FloatArray &coords, Set &sourceElemSet, TimeStep *tStep, bool iCohesiveZoneGP = false); + void __init(Domain *dold, IntArray &type, const FloatArray &coords, Set &sourceElemSet, TimeStep *tStep, bool iCohesiveZoneGP = false) override; - virtual void finish(TimeStep *tStep) { } + void finish(TimeStep *tStep) override { } - virtual int __mapVariable(FloatArray &answer, const FloatArray &coords, InternalStateType type, TimeStep *tStep); + int __mapVariable(FloatArray &answer, const FloatArray &coords, InternalStateType type, TimeStep *tStep) override; - virtual int mapStatus(MaterialStatus &oStatus) const; + int mapStatus(MaterialStatus &oStatus) const override; - virtual const char *giveClassName() const { return "MMAClosestIPTransfer"; } + const char *giveClassName() const override { return "MMAClosestIPTransfer"; } }; } // end namespace oofem #endif // mmaclosestiptransfer_h diff --git a/src/oofemlib/mmacontainingelementprojection.C b/src/oofemlib/mmacontainingelementprojection.C index f3b7b683b..de43cddd0 100644 --- a/src/oofemlib/mmacontainingelementprojection.C +++ b/src/oofemlib/mmacontainingelementprojection.C @@ -49,16 +49,16 @@ MMAContainingElementProjection :: __init(Domain *dold, IntArray &type, const Flo { SpatialLocalizer *sl = dold->giveSpatialLocalizer(); FloatArray jGpCoords; - double distance, minDist = 1.e6; + double minDist = 1.e6; Element *srcElem; if ( ( srcElem = sl->giveElementContainingPoint(coords, elemSet) ) ) { - this->source = NULL; - for ( GaussPoint *jGp: *srcElem->giveDefaultIntegrationRulePtr() ) { + this->source = nullptr; + for ( auto &jGp: *srcElem->giveDefaultIntegrationRulePtr() ) { if ( srcElem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) { - distance = coords.distance(jGpCoords); - if ( distance < minDist ) { - minDist = distance; + double dist = distance(coords, jGpCoords); + if ( dist < minDist ) { + minDist = dist; this->source = jGp; } } diff --git a/src/oofemlib/mmacontainingelementprojection.h b/src/oofemlib/mmacontainingelementprojection.h index bae2fddd4..9c48c3dec 100644 --- a/src/oofemlib/mmacontainingelementprojection.h +++ b/src/oofemlib/mmacontainingelementprojection.h @@ -56,15 +56,15 @@ class OOFEM_EXPORT MMAContainingElementProjection : public MaterialMappingAlgori /// Constructor MMAContainingElementProjection(); - virtual void __init(Domain *dold, IntArray &type, const FloatArray &coords, Set &sourceElemSet, TimeStep *tStep, bool iCohesiveZoneGP = false); + void __init(Domain *dold, IntArray &type, const FloatArray &coords, Set &sourceElemSet, TimeStep *tStep, bool iCohesiveZoneGP = false) override; - virtual void finish(TimeStep *tStep) { } + void finish(TimeStep *tStep) override { } - virtual int __mapVariable(FloatArray &answer, const FloatArray &coords, InternalStateType type, TimeStep *tStep); + int __mapVariable(FloatArray &answer, const FloatArray &coords, InternalStateType type, TimeStep *tStep) override; - virtual int mapStatus(MaterialStatus &oStatus) const; + int mapStatus(MaterialStatus &oStatus) const override; - virtual const char *giveClassName() const { return "MMAContainingElementProjection"; } + const char *giveClassName() const override { return "MMAContainingElementProjection"; } }; } // end namespace oofem #endif // mmacontainingelementprojection_h diff --git a/src/oofemlib/mmaleastsquareprojection.C b/src/oofemlib/mmaleastsquareprojection.C index 546044242..5e0343369 100644 --- a/src/oofemlib/mmaleastsquareprojection.C +++ b/src/oofemlib/mmaleastsquareprojection.C @@ -41,8 +41,11 @@ #include "integrationrule.h" #include "connectivitytable.h" #include "dynamicinputrecord.h" +#include "classfactory.h" namespace oofem { +REGISTER_MaterialMappingAlgorithm(MMALeastSquareProjection, MMA_LeastSquareProjection); + MMALeastSquareProjection :: MMALeastSquareProjection() : MaterialMappingAlgorithm() { this->stateFilter = 0; @@ -177,20 +180,20 @@ MMALeastSquareProjection :: __init(Domain *dold, IntArray &type, const FloatArra for ( int ielem = 1; ielem <= patchList.giveSize(); ielem++ ) { element = patchDomain->giveElement( patchList.at(ielem) ); iRule = element->giveDefaultIntegrationRulePtr(); - for ( GaussPoint *srcgp: *iRule ) { + for ( auto &srcgp: *iRule ) { if ( element->computeGlobalCoordinates( srcgpcoords, * ( srcgp->giveNaturalCoordinates() ) ) ) { element->giveIPValue(dam, srcgp, IST_PrincipalDamageTensor, tStep); if ( this->stateFilter ) { // consider only points with same state if ( ( ( state == 1 ) && ( norm(dam) > 1.e-3 ) ) || ( ( ( state == 0 ) && norm(dam) < 1.e-3 ) ) ) { npoints++; - dist.at(npoints) = coords.distance(srcgpcoords); + dist.at(npoints) = distance(coords, srcgpcoords); gpList [ npoints - 1 ] = srcgp; } } else { // take all points into account npoints++; - dist.at(npoints) = coords.distance(srcgpcoords); + dist.at(npoints) = distance(coords, srcgpcoords); gpList [ npoints - 1 ] = srcgp; } } else { @@ -406,18 +409,14 @@ MMALeastSquareProjection :: giveNumberOfUnknownPolynomialCoefficients(MMALeastSq } -IRResultType -MMALeastSquareProjection :: initializeFrom(InputRecord *ir) +void +MMALeastSquareProjection :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - this->stateFilter = 0; IR_GIVE_OPTIONAL_FIELD(ir, this->stateFilter, _IFT_MMALeastSquareProjection_statefilter); this->regionFilter = 0; IR_GIVE_OPTIONAL_FIELD(ir, this->regionFilter, _IFT_MMALeastSquareProjection_regionfilter); - - return IRRT_OK; } diff --git a/src/oofemlib/mmaleastsquareprojection.h b/src/oofemlib/mmaleastsquareprojection.h index eb7fdc740..fd7caab25 100644 --- a/src/oofemlib/mmaleastsquareprojection.h +++ b/src/oofemlib/mmaleastsquareprojection.h @@ -42,6 +42,7 @@ ///@name Input fields for MMALeastSquareProjection //@{ +#define _IFT_MMALeastSquareProjection_Name "leastsquare" #define _IFT_MMALeastSquareProjection_statefilter "mmalsp_statefilter" #define _IFT_MMALeastSquareProjection_regionfilter "mmalsp_regionfilter" //@} @@ -93,18 +94,19 @@ class OOFEM_EXPORT MMALeastSquareProjection : public MaterialMappingAlgorithm /// Destructor virtual ~MMALeastSquareProjection(); - virtual void __init(Domain *dold, IntArray &type, const FloatArray &coords, Set &sourceElemSet, TimeStep *tStep, bool iCohesiveZoneGP = false); + void __init(Domain *dold, IntArray &type, const FloatArray &coords, Set &sourceElemSet, TimeStep *tStep, bool iCohesiveZoneGP = false) override; - virtual void finish(TimeStep *tStep); + void finish(TimeStep *tStep) override; - virtual int __mapVariable(FloatArray &answer, const FloatArray &coords, InternalStateType type, TimeStep *tStep); + int __mapVariable(FloatArray &answer, const FloatArray &coords, InternalStateType type, TimeStep *tStep) override; - virtual int mapStatus(MaterialStatus &oStatus) const; + int mapStatus(MaterialStatus &oStatus) const override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual const char *giveClassName() const { return "MMALeastSquareProjectionPatchType"; } + const char *giveClassName() const override { return "MMALeastSquareProjectionPatchType"; } + const char *giveInputRecordName() const { return _IFT_MMALeastSquareProjection_Name; } protected: void computePolynomialTerms(FloatArray &P, const FloatArray &coords, MMALeastSquareProjectionPatchType type); diff --git a/src/oofemlib/mmashapefunctprojection.C b/src/oofemlib/mmashapefunctprojection.C index d40a19bc2..d85690933 100644 --- a/src/oofemlib/mmashapefunctprojection.C +++ b/src/oofemlib/mmashapefunctprojection.C @@ -41,10 +41,13 @@ #include "timestep.h" #include "feinterpol.h" #include "nodalaveragingrecoverymodel.h" +#include "classfactory.h" #include namespace oofem { +REGISTER_MaterialMappingAlgorithm(MMAShapeFunctProjection, MMA_ShapeFunctionProjection); + MMAShapeFunctProjection :: MMAShapeFunctProjection() : MaterialMappingAlgorithm() { stateCounter = 0; @@ -136,7 +139,7 @@ MMAShapeFunctProjection :: __mapVariable(FloatArray &answer, const FloatArray &c if ( indx ) { container.reserve(nnodes); for ( int inode = 1; inode <= nnodes; inode++ ) { - this->smootherList.at(indx)->giveNodalVector( nvec, elem->giveDofManager(inode)->giveNumber() ); + this->smootherList.at(indx-1)->giveNodalVector( nvec, elem->giveDofManager(inode)->giveNumber() ); container.emplace_back(*nvec); } diff --git a/src/oofemlib/mmashapefunctprojection.h b/src/oofemlib/mmashapefunctprojection.h index fafcfaddc..b386fa8c1 100644 --- a/src/oofemlib/mmashapefunctprojection.h +++ b/src/oofemlib/mmashapefunctprojection.h @@ -42,6 +42,8 @@ #include #include +#define _IFT_MMAShapeFunctProjection_Name "shapefun" + namespace oofem { class Domain; class Element; @@ -88,19 +90,19 @@ class OOFEM_EXPORT MMAShapeFunctProjection : public MaterialMappingAlgorithm MMAShapeFunctProjection(const MMAShapeFunctProjection &) = delete; MMAShapeFunctProjection &operator=(const MMAShapeFunctProjection &) = delete; - virtual void __init(Domain *dold, IntArray &type, const FloatArray &coords, Set &sourceElemSet, TimeStep *tStep, bool iCohesiveZoneGP = false); + void __init(Domain *dold, IntArray &type, const FloatArray &coords, Set &sourceElemSet, TimeStep *tStep, bool iCohesiveZoneGP = false) override; - virtual void finish(TimeStep *tStep); + void finish(TimeStep *tStep) override; - virtual int mapVariable(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int mapVariable(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual int __mapVariable(FloatArray &answer, const FloatArray &coords, InternalStateType type, TimeStep *tStep); + int __mapVariable(FloatArray &answer, const FloatArray &coords, InternalStateType type, TimeStep *tStep) override; - virtual int mapStatus(MaterialStatus &oStatus) const; + int mapStatus(MaterialStatus &oStatus) const override; void interpolateIntVarAt(FloatArray &answer, Element *elem, const FloatArray &lcoords, std :: vector< FloatArray > &list, InternalStateType type, TimeStep *tStep) const; - virtual const char *giveClassName() const { return "MMAShapeFunctProjectionInterface"; } + const char *giveClassName() const override { return "MMAShapeFunctProjectionInterface"; } }; } // end namespace oofem #endif // mmashapefunctprojection_h diff --git a/src/oofemlib/modulemanager.h b/src/oofemlib/modulemanager.h index 9e776cb5b..0d6f6e3e4 100644 --- a/src/oofemlib/modulemanager.h +++ b/src/oofemlib/modulemanager.h @@ -37,6 +37,8 @@ #include "datareader.h" #include "error.h" +#include "exportmodule.h" + #include #include @@ -58,7 +60,7 @@ class OOFEM_EXPORT ModuleManager { protected: /// Module list. - std :: vector< std :: unique_ptr< M > > moduleList; + std::vector< std::unique_ptr< M > > moduleList; /// Number of modules. int numberOfModules; /// Associated Engineering model. @@ -79,7 +81,7 @@ class OOFEM_EXPORT ModuleManager * @param n Number associated with module. * @param emodel Engineering model which receiver belongs to. */ - virtual M *CreateModule(const char *name, int n, EngngModel *emodel) = 0; + virtual std::unique_ptr CreateModule(const char *name, int n, EngngModel *emodel) = 0; /** * * Reads receiver description from input stream and creates corresponding modules components accordingly. @@ -91,29 +93,25 @@ class OOFEM_EXPORT ModuleManager * @param ir Record for receiver. * @return Nonzero if o.k. */ - virtual int instanciateYourself(DataReader *dr, InputRecord *ir) + virtual int instanciateYourself(DataReader &dr, InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - std :: string name; // read modules moduleList.reserve(numberOfModules); for ( int i = 0; i < numberOfModules; i++ ) { - InputRecord *mir = dr->giveInputRecord(DataReader :: IR_expModuleRec, i + 1); - result = mir->giveRecordKeywordField(name); - if ( result != IRRT_OK ) { - IR_IOERR("", mir, result); - } + auto &mir = dr.giveInputRecord(DataReader :: IR_expModuleRec, i + 1); + mir.giveRecordKeywordField(name); // read type of module - std :: unique_ptr< M > module( this->CreateModule(name.c_str(), i, emodel) ); + std :: unique_ptr< M > module = this->CreateModule(name.c_str(), i, emodel); if ( !module ) { OOFEM_ERROR("unknown module (%s)", name.c_str()); } module->initializeFrom(mir); - moduleList.push_back(std :: move(module)); + registerModule(module); +// moduleList.push_back(std :: move(module)); } # ifdef VERBOSE @@ -122,11 +120,21 @@ class OOFEM_EXPORT ModuleManager return 1; } + /** + * Stores a module in moduleList. Useful when + * adding modules externally, e.g. from Python + */ + + virtual void registerModule (std::unique_ptr< M > &module){ + moduleList.push_back(std::move(module)); + } + + /** * Instanciates the receiver from input record. Called from instanciateYourself to initialize yourself * from corresponding record. Should be called before instanciateYourself. */ - virtual IRResultType initializeFrom(InputRecord *ir) = 0; + virtual void initializeFrom(InputRecord &ir) = 0; /// Returns class name of the receiver. virtual const char *giveClassName() const = 0; @@ -148,5 +156,8 @@ class OOFEM_EXPORT ModuleManager int giveNumberOfModules() const { return (int)moduleList.size(); } }; + +template class OOFEM_EXPORT ModuleManager; + } // end namespace oofem #endif // modulemanager_h diff --git a/src/sm/Materials/latticematstatus.C b/src/oofemlib/monitor.C similarity index 80% rename from src/sm/Materials/latticematstatus.C rename to src/oofemlib/monitor.C index fa53d93be..4522ddae0 100644 --- a/src/sm/Materials/latticematstatus.C +++ b/src/oofemlib/monitor.C @@ -32,9 +32,18 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "latticematstatus.h" +#include "monitor.h" +#include "classfactory.h" +#include "logger.h" namespace oofem { -LatticeMaterialStatus :: LatticeMaterialStatus(int n, Domain *d, GaussPoint *g) : StructuralMaterialStatus(n, d, g) -{ } -} // end namespace oofem + +REGISTER_Monitor( DummyMonitor ) + +void DummyMonitor::initializeFrom(InputRecord &ir) +{} +void DummyMonitor::update(EngngModel* eModel, TimeStep *tStep, MonitorEvent event) +{ + OOFEM_LOG_FORCED ("DummyMonitor: received event %d\n", event); +} +} // end namespace oofem \ No newline at end of file diff --git a/src/oofemlib/monitor.h b/src/oofemlib/monitor.h new file mode 100644 index 000000000..b695b5bbb --- /dev/null +++ b/src/oofemlib/monitor.h @@ -0,0 +1,97 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef monitor_h +#define monitor_h + +#include "oofemcfg.h" + +namespace oofem { +class EngngModel; +class TimeStep; +class InputRecord; + +///@name Input fields for Monitor +//@{ +#define _IFT_DummyMonitor_Name "dummymonitor" + + +/** + * Class representing monitor, an abstract class inplementing solution monitor. + * Monitors are managed by MonitorManager and are invoked at user controlled events, such as solution step termoination. + * Derived classes can perform specific actions (updating model, plotting proogress, etc) + */ +class OOFEM_EXPORT Monitor +{ +protected: + int number; +public: + enum MonitorEvent { + TimeStepTermination + }; +public: + Monitor(int n) { + this->number = n; + } + virtual ~Monitor() {} + + /// Initializes receiver according to object description stored in input record. + virtual void initializeFrom(InputRecord &ir) = 0; + /** + * updates the monitor state. This can also mean updating received eModel state. + * @param eModel instance of EngngModel + * @param tStep time step + * @param event event type + */ + virtual void update(EngngModel* eModel, TimeStep *tStep, MonitorEvent event) = 0; + + /// Returns class name of the receiver. + virtual const char *giveClassName() const = 0; + +}; + +/** Dummy monitor */ +class OOFEM_EXPORT DummyMonitor : public Monitor +{ + public: + DummyMonitor (int n) : Monitor (n) {} + + /// Initializes receiver according to object description stored in input record. + void initializeFrom(InputRecord &ir) override; + void update(EngngModel* eModel, TimeStep *tStep, MonitorEvent event) override; + virtual const char *giveClassName() const override {return "DummuMonitor"; } +}; + +} // end namespace oofem +#endif // monitor_h diff --git a/src/sm/Elements/latticestructuralelement.C b/src/oofemlib/monitormanager.C similarity index 67% rename from src/sm/Elements/latticestructuralelement.C rename to src/oofemlib/monitormanager.C index 32f018f27..239e39f70 100644 --- a/src/sm/Elements/latticestructuralelement.C +++ b/src/oofemlib/monitormanager.C @@ -32,18 +32,36 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/latticestructuralelement.h" +#include "monitormanager.h" +#include "modulemanager.h" +#include "monitor.h" +#include "classfactory.h" namespace oofem { -LatticeStructuralElement :: LatticeStructuralElement(int n, Domain *aDomain) : StructuralElement(n, aDomain) +MonitorManager :: MonitorManager(EngngModel *emodel) : ModuleManager< Monitor >(emodel) { } -LatticeStructuralElement :: ~LatticeStructuralElement() +MonitorManager :: ~MonitorManager() { } -IRResultType -LatticeStructuralElement :: initializeFrom(InputRecord *ir) +void +MonitorManager :: initializeFrom(InputRecord &ir) { - return StructuralElement :: initializeFrom(ir); + this->numberOfModules = 0; + IR_GIVE_OPTIONAL_FIELD(ir, numberOfModules, "nmonitors"); } + +std::unique_ptr MonitorManager :: CreateModule(const char *name, int n, EngngModel *emodel) +{ + return classFactory.createMonitor(name, n); +} + +void +MonitorManager :: update(TimeStep *tStep, Monitor::MonitorEvent event) +{ + for ( auto &module: moduleList ) { + module->update(this->emodel, tStep, event); + } +} + } // end namespace oofem diff --git a/src/oofemlib/monitormanager.h b/src/oofemlib/monitormanager.h new file mode 100644 index 000000000..71c2453ed --- /dev/null +++ b/src/oofemlib/monitormanager.h @@ -0,0 +1,76 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef monitormanager_h +#define monitormanager_h + +#include "modulemanager.h" +#include "monitor.h" + +namespace oofem { +class EngngModel; + +/** + * Class representing and implementing MonitorManager. It is attribute of EngngModel. + * It manages individual monitors, which perform monitor - specific output operations. + * Monitors can be called at user specific events, such as time step termination, etc. + * The event type is preopagated to each monitor. + */ +class OOFEM_EXPORT MonitorManager : public ModuleManager< Monitor > +{ +public: + MonitorManager(EngngModel * emodel); + virtual ~MonitorManager(); + + void initializeFrom(InputRecord &ir) override; + std::unique_ptr CreateModule(const char *name, int num, EngngModel *emodel) override; + + /** + * Writes the output. Loops over all modules and calls corresponding doOutput module service. + * @param tStep Time step. + * @param substepFlag is set to true, only the modules with substepFlag set to true will be processed. + */ + void update(TimeStep *tStep, Monitor::MonitorEvent event); + /** + * Initializes output manager. The corresponding initialize module services are called. + */ + //void initialize(); + /** + * Terminates the receiver, the corresponding terminate module services are called. + */ + //void terminate(); + const char *giveClassName() const override { return "MonitorManager"; } +}; +} // end namespace oofem +#endif // monitormanager_h diff --git a/src/oofemlib/neumannmomentload.C b/src/oofemlib/neumannmomentload.C index 704d48722..c560b7c41 100644 --- a/src/oofemlib/neumannmomentload.C +++ b/src/oofemlib/neumannmomentload.C @@ -48,21 +48,17 @@ namespace oofem { REGISTER_BoundaryCondition(NeumannMomentLoad); -IRResultType -NeumannMomentLoad :: initializeFrom(InputRecord *ir) +void +NeumannMomentLoad :: initializeFrom(InputRecord &ir) { BoundaryLoad :: initializeFrom(ir); - IRResultType result; - IR_GIVE_FIELD(ir, g, _IFT_NeumannMomentLoad_Gradient); p = 0.; IR_GIVE_OPTIONAL_FIELD(ir, p, _IFT_NeumannMomentLoad_Constant); IR_GIVE_FIELD(ir, cset, _IFT_NeumannMomentLoad_CenterSet); xbar.resize(0); - - return result; } void @@ -74,34 +70,29 @@ NeumannMomentLoad :: computeXbar() celements = this->giveDomain()->giveSet(cset)->giveElementList(); - double V=0.0; + double V = 0.0; for ( auto elementID : celements ) { Element *thisElement = this->giveDomain()->giveElement(elementID); FEInterpolation *i = thisElement->giveInterpolation(); - IntegrationRule *iRule = i->giveIntegrationRule(3); + auto iRule = i->giveIntegrationRule(3); - for ( GaussPoint * gp: * iRule ) { - FloatArray coord; + FloatArray coord; + for ( auto &gp: *iRule ) { FloatArray lcoords = gp->giveNaturalCoordinates(); double detJ = i->giveTransformationJacobian(lcoords, FEIElementGeometryWrapper(thisElement)); i->local2global(coord, lcoords, FEIElementGeometryWrapper(thisElement)); coord.times(gp->giveWeight()*fabs(detJ)); - V=V+gp->giveWeight()*fabs(detJ); + V += gp->giveWeight()*fabs(detJ); xbar.add(coord); } - - delete iRule; - } - xbar.times(1.0/V); - } void diff --git a/src/oofemlib/neumannmomentload.h b/src/oofemlib/neumannmomentload.h index bafbdb4d1..b1665328f 100644 --- a/src/oofemlib/neumannmomentload.h +++ b/src/oofemlib/neumannmomentload.h @@ -71,28 +71,28 @@ class OOFEM_EXPORT NeumannMomentLoad : public SurfaceLoad void computeNormal(FloatArray &answer, Element *e, int side); public: NeumannMomentLoad(int i, Domain * d) : SurfaceLoad(i, d) { } + virtual ~NeumannMomentLoad() {} - // Overloaded methods: - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); - virtual int giveApproxOrder() { return 0; } + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; + int giveApproxOrder() override { return 0; } - FormulationType giveFormulationType() { return FT_Global; } + FormulationType giveFormulationType() override { return FT_Global; } - virtual void computeValueAtBoundary(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode, Element *e, int boundary); + void computeValueAtBoundary(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode, Element *e, int boundary); /** * Sets a new load vector. * @param newValue New load. */ void updateLoad(const FloatArray &newValue) { componentArray = newValue; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual bcGeomType giveBCGeoType() const { return SurfaceLoadBGT; } + void initializeFrom(InputRecord &ir) override; + bcGeomType giveBCGeoType() const override { return SurfaceLoadBGT; } - virtual const char *giveClassName() const { return "NeumannMomentLoad"; } - virtual const char *giveInputRecordName() const { return _IFT_NeumannMomentLoad_Name; } + const char *giveClassName() const override { return "NeumannMomentLoad"; } + const char *giveInputRecordName() const override { return _IFT_NeumannMomentLoad_Name; } private: - virtual void computeNArray(FloatArray &answer, const FloatArray &coords) const { answer.clear(); } + void computeNArray(FloatArray &answer, const FloatArray &coords) const override { answer.clear(); } }; } // end namespace oofem diff --git a/src/oofemlib/nodalaveragingrecoverymodel.C b/src/oofemlib/nodalaveragingrecoverymodel.C index 7aade1306..bf5631fff 100644 --- a/src/oofemlib/nodalaveragingrecoverymodel.C +++ b/src/oofemlib/nodalaveragingrecoverymodel.C @@ -37,6 +37,7 @@ #include "element.h" #include "dofmanager.h" #include "engngm.h" +#include "classfactory.h" #ifdef __PARALLEL_MODE #include "problemcomm.h" @@ -45,6 +46,8 @@ #endif namespace oofem { +REGISTER_NodalRecoveryModel(NodalAveragingRecoveryModel, NodalRecoveryModel :: NRM_NodalAveraging); + NodalAveragingRecoveryModel :: NodalAveragingRecoveryModel(Domain *d) : NodalRecoveryModel(d) { } @@ -189,15 +192,14 @@ NodalAveragingRecoveryModel :: exchangeDofManValues(FloatArray &lhs, IntArray &r int NodalAveragingRecoveryModel :: packSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm) { - int result = 1, size; + int result = 1; ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); - IntArray const *toSendMap = processComm.giveToSendMap(); + const IntArray &toSendMap = processComm.giveToSendMap(); - size = toSendMap->giveSize(); - for ( int i = 1; i <= size; i++ ) { + for ( int inode : toSendMap ) { // toSendMap contains all shared dofmans with remote partition // one has to check, if particular shared node value is available for given region - int indx = s->regionNodalNumbers->at( toSendMap->at(i) ); + int indx = s->regionNodalNumbers->at( inode ); if ( indx ) { // pack "1" to indicate that for given shared node this is a valid contribution result &= pcbuff->write(1); @@ -219,14 +221,12 @@ int NodalAveragingRecoveryModel :: unpackSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm) { int result = 1; - int size, flag, intValue; - IntArray const *toRecvMap = processComm.giveToRecvMap(); + int flag, intValue; + const IntArray &toRecvMap = processComm.giveToRecvMap(); ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); - double value; - size = toRecvMap->giveSize(); - for ( int i = 1; i <= size; i++ ) { - int indx = s->regionNodalNumbers->at( toRecvMap->at(i) ); + for ( int inode : toRecvMap ) { + int indx = s->regionNodalNumbers->at( inode ); // toRecvMap contains all shared dofmans with remote partition // one has to check, if particular shared node received contribution is available for given region result &= pcbuff->read(flag); @@ -240,6 +240,7 @@ NodalAveragingRecoveryModel :: unpackSharedDofManData(parallelStruct *s, Process int eq = ( indx - 1 ) * s->regionValSize; for ( int j = 1; j <= s->regionValSize; j++ ) { + double value; result &= pcbuff->read(value); if ( indx ) { s->lhs->at(eq + j) += value; diff --git a/src/oofemlib/nodalaveragingrecoverymodel.h b/src/oofemlib/nodalaveragingrecoverymodel.h index 1810f805e..f2ea5e310 100644 --- a/src/oofemlib/nodalaveragingrecoverymodel.h +++ b/src/oofemlib/nodalaveragingrecoverymodel.h @@ -38,6 +38,8 @@ #include "nodalrecoverymodel.h" #include "interface.h" +#define _IFT_NodalAveragingRecoveryModel_Name "nodalaverage" + namespace oofem { class GaussPoint; class ProcessCommunicator; @@ -67,18 +69,18 @@ class OOFEM_EXPORT NodalAveragingRecoveryModel : public NodalRecoveryModel /// Constructor. NodalAveragingRecoveryModel(Domain * d); /// Destructor. - ~NodalAveragingRecoveryModel(); + virtual ~NodalAveragingRecoveryModel(); - int recoverValues(Set elementSet, InternalStateType type, TimeStep *tStep); + int recoverValues(Set elementSet, InternalStateType type, TimeStep *tStep) override; - virtual const char *giveClassName() const { return "NodalAveragingRecoveryModel"; } + const char *giveClassName() const override { return "NodalAveragingRecoveryModel"; } private: #ifdef __PARALLEL_MODE void initCommMaps(); void exchangeDofManValues(FloatArray &lhs, IntArray &, IntArray &, int); - int packSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm); - int unpackSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm); + int packSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm); + int unpackSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm); #endif }; diff --git a/src/oofemlib/nodalload.C b/src/oofemlib/nodalload.C index 2ecd4f5e7..a6b02b710 100644 --- a/src/oofemlib/nodalload.C +++ b/src/oofemlib/nodalload.C @@ -34,21 +34,20 @@ #include "nodalload.h" #include "classfactory.h" +#include "datastream.h" #include "dynamicinputrecord.h" +#include "contextioerr.h" namespace oofem { REGISTER_BoundaryCondition(NodalLoad); -IRResultType -NodalLoad :: initializeFrom(InputRecord *ir) +void +NodalLoad :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - + Load :: initializeFrom(ir); int value = 1; IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_NodalLoad_cstype); coordSystemType = ( CoordSystType ) value; - - return Load :: initializeFrom(ir); } @@ -57,4 +56,34 @@ void NodalLoad :: giveInputRecord(DynamicInputRecord &input) Load :: giveInputRecord(input); input.setField(this->coordSystemType, _IFT_NodalLoad_cstype); } + + +void +NodalLoad :: saveContext(DataStream &stream, ContextMode mode) +{ + Load :: saveContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( !stream.write(coordSystemType) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +void +NodalLoad :: restoreContext(DataStream &stream, ContextMode mode) +{ + Load :: restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + int _val; + if ( !stream.read(_val) ) { + THROW_CIOERR(CIO_IOERR); + } + coordSystemType = (CoordSystType) _val; + } +} + + } // end namespace oofem diff --git a/src/oofemlib/nodalload.h b/src/oofemlib/nodalload.h index 133d993a6..634e9e6f6 100644 --- a/src/oofemlib/nodalload.h +++ b/src/oofemlib/nodalload.h @@ -82,15 +82,18 @@ class OOFEM_EXPORT NodalLoad : public Load */ NodalLoad(int n, Domain * d) : Load(n, d) { } - virtual const char *giveInputRecordName() const { return _IFT_NodalLoad_Name; } - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) + const char *giveInputRecordName() const override { return _IFT_NodalLoad_Name; } + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override { computeComponentArrayAt(answer, tStep, mode); } - virtual CoordSystType giveCoordSystMode() { return coordSystemType; } + CoordSystType giveCoordSystMode() override { return coordSystemType; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveClassName() const { return "NodalLoad"; } - virtual bcGeomType giveBCGeoType() const { return NodalLoadBGT; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveClassName() const override { return "NodalLoad"; } + bcGeomType giveBCGeoType() const override { return NodalLoadBGT; } + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; } // end namespace oofem #endif // nodalload_h diff --git a/src/oofemlib/node.C b/src/oofemlib/node.C index 6207b39f7..705523aed 100644 --- a/src/oofemlib/node.C +++ b/src/oofemlib/node.C @@ -66,45 +66,20 @@ namespace oofem { REGISTER_DofManager(Node); Node :: Node(int n, Domain *aDomain) : - DofManager(n, aDomain), coordinates() -{ - localCoordinateSystem = NULL; -} - - -Node :: ~Node() -{ - delete localCoordinateSystem; -} - - -double -Node :: giveCoordinate(int i) -// Returns the i-th coordinate of the receiver. -{ - if ( i > coordinates.giveSize() ) { - return 0.; - } - - return coordinates.at(i); -} + DofManager(n, aDomain) +{ } -IRResultType Node :: initializeFrom(InputRecord *ir) +void Node :: initializeFrom(InputRecord &ir) // Gets from the source line from the data file all the data of the receiver. { - IRResultType result; // Required by IR_GIVE_FIELD macro - int size; # ifdef VERBOSE // VERBOSE_PRINT1("Instanciating node ",number) # endif - result = DofManager :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + DofManager :: initializeFrom(ir); IR_GIVE_FIELD(ir, coordinates, _IFT_Node_coords); @@ -118,7 +93,7 @@ IRResultType Node :: initializeFrom(InputRecord *ir) // Read if available local coordinate system in this node - if ( ir->hasField(_IFT_Node_lcs) ) { + if ( ir.hasField(_IFT_Node_lcs) ) { FloatArray triplets; IR_GIVE_FIELD(ir, triplets, _IFT_Node_lcs); size = triplets.giveSize(); @@ -127,7 +102,7 @@ IRResultType Node :: initializeFrom(InputRecord *ir) } double n1 = 0.0, n2 = 0.0; - localCoordinateSystem = new FloatMatrix(3, 3); + localCoordinateSystem = std::make_unique(3, 3); for ( int j = 1; j <= 3; j++ ) { localCoordinateSystem->at(1, j) = triplets.at(j); @@ -158,8 +133,6 @@ IRResultType Node :: initializeFrom(InputRecord *ir) localCoordinateSystem->at(1, 1) * localCoordinateSystem->at(2, 2) - localCoordinateSystem->at(1, 2) * localCoordinateSystem->at(2, 1); } - - return IRRT_OK; } void Node :: giveInputRecord(DynamicInputRecord &input) @@ -168,7 +141,7 @@ void Node :: giveInputRecord(DynamicInputRecord &input) input.setField(coordinates, _IFT_Node_coords); - if ( localCoordinateSystem != NULL ) { + if ( localCoordinateSystem ) { input.setField(* localCoordinateSystem, _IFT_Node_lcs); } } @@ -430,7 +403,7 @@ Node :: computeL2GTransformation(FloatMatrix &answer, const IntArray &dofIDArry) // DofIDItem id; - if ( localCoordinateSystem == NULL ) { + if ( !localCoordinateSystem ) { answer.clear(); return false; } else { @@ -561,21 +534,14 @@ Node :: computeL2GTransformation(FloatMatrix &answer, const IntArray &dofIDArry) } -contextIOResultType -Node :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full node context (saves state variables, that completely describe -// current state) -// +void +Node :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = DofManager :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + DofManager :: saveContext(stream, mode); if ( mode & CM_Definition ) { int _haslcs = hasLocalCS(); + contextIOResultType iores; if ( ( iores = coordinates.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -590,26 +556,17 @@ Node :: saveContext(DataStream &stream, ContextMode mode, void *obj) } } } - - return CIO_OK; } -contextIOResultType -Node :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full node context (saves state variables, that completely describe -// current state) -// +void +Node :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = DofManager :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + DofManager :: restoreContext(stream, mode); if ( mode & CM_Definition ) { int _haslcs; + contextIOResultType iores; if ( ( iores = coordinates.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -619,19 +576,14 @@ Node :: restoreContext(DataStream &stream, ContextMode mode, void *obj) } if ( _haslcs ) { - if ( localCoordinateSystem == NULL ) { - localCoordinateSystem = new FloatMatrix(); - } - + localCoordinateSystem = std::make_unique(); if ( ( iores = localCoordinateSystem->restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } } else { - localCoordinateSystem = NULL; + localCoordinateSystem = nullptr; } } - - return CIO_OK; } diff --git a/src/oofemlib/node.h b/src/oofemlib/node.h index d56b7ece5..35c5c6019 100644 --- a/src/oofemlib/node.h +++ b/src/oofemlib/node.h @@ -43,6 +43,9 @@ #include "dofmanager.h" #include "floatarray.h" +#include "floatmatrix.h" + +#include ///@name Input fields for Node //@{ @@ -87,37 +90,21 @@ class IntArray; class OOFEM_EXPORT Node : public DofManager { protected: - /// Array storing nodal coordinates. - FloatArray coordinates; /** * Triplet defining the local coordinate system in node. * Value at position (i,j) represents angle between e'(i) and e(j), * where e' is base vector of local coordinate system and e is * base vector of global c.s. */ - FloatMatrix *localCoordinateSystem; - + std::unique_ptr localCoordinateSystem; public: - /** * Constructor. Creates a node belonging to domain. * @param n Node number in domain aDomain. * @param aDomain Domain to which node belongs. */ Node(int n, Domain * aDomain); - /// Destructor. - virtual ~Node(); - - virtual bool hasCoordinates() { return true; } - virtual double giveCoordinate(int i); - virtual FloatArray *giveCoordinates() { return & coordinates; } - - /** - * As giveCoordinates, but non-virtual and therefore faster - * (because it can be inlined). /ES - */ - inline const FloatArray &giveNodeCoordinates() const {return coordinates;} /** * Sets node coordinates to given array. @@ -147,7 +134,7 @@ class OOFEM_EXPORT Node : public DofManager // local coordinate system /// Returns nonzero if node has prescribed local coordinate system. - bool hasLocalCS() { return ( localCoordinateSystem != NULL ); } + bool hasLocalCS() { return ( localCoordinateSystem != nullptr ); } /** Returns pointer to local coordinate triplet in node. * If not defined, returns NULL. * @return Triplet defining the local coordinate system in node. @@ -155,13 +142,13 @@ class OOFEM_EXPORT Node : public DofManager * where e' is base vector of local coordinate system and e is * base vector of global c.s. */ - FloatMatrix *giveLocalCoordinateTriplet() { return localCoordinateSystem; } + FloatMatrix *giveLocalCoordinateTriplet() { return localCoordinateSystem.get(); } /** Returns true, if the local coordinate systems of receiver and given node are the same */ bool hasSameLCS(Node *remote); - virtual bool computeL2GTransformation(FloatMatrix &answer, const IntArray &dofIDArry); - virtual bool requiresTransformation() { return ( this->hasLocalCS() || hasSlaveDofs ); } - virtual void computeLoadVector(FloatArray &answer, Load *load, CharType type, TimeStep *tStep, ValueModeType mode); + bool computeL2GTransformation(FloatMatrix &answer, const IntArray &dofIDArry) override; + bool requiresTransformation() override { return ( this->hasLocalCS() || hasSlaveDofs ); } + void computeLoadVector(FloatArray &answer, Load *load, CharType type, TimeStep *tStep, ValueModeType mode) override; /** * Updates receiver at end of time step (i.e. after equilibrium has been reached). @@ -170,24 +157,23 @@ class OOFEM_EXPORT Node : public DofManager * @param tStep Time step for which to update. * @see EngngModel::giveFormulation */ - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; // miscellaneous - virtual const char *giveClassName() const { return "Node"; } - virtual const char *giveInputRecordName() const { return _IFT_Node_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void printYourself(); - virtual int checkConsistency(); - virtual bool isDofTypeCompatible(dofType type) const { return ( type == DT_master || type == DT_simpleSlave || type == DT_active ); } - virtual int giveQcNodeType() {return 0;}; - - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + const char *giveClassName() const override { return "Node"; } + const char *giveInputRecordName() const override { return _IFT_Node_Name; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void printYourself() override; + int checkConsistency() override; + bool isDofTypeCompatible(dofType type) const override { return ( type == DT_master || type == DT_simpleSlave || type == DT_active ); } + virtual int giveQcNodeType() { return 0; } + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; #ifdef __OOFEG - virtual void drawYourself(oofegGraphicContext &gc, TimeStep *tStep); + void drawYourself(oofegGraphicContext &gc, TimeStep *tStep) override; #endif }; } // end namespace oofem diff --git a/src/oofemlib/nonlocalbarrier.h b/src/oofemlib/nonlocalbarrier.h index 04eb57da4..bef2f9d6c 100644 --- a/src/oofemlib/nonlocalbarrier.h +++ b/src/oofemlib/nonlocalbarrier.h @@ -74,14 +74,15 @@ class OOFEM_EXPORT NonlocalBarrier : public FEMComponent /** * Abstract method modifying the integration weight between master (c1) and source (c2) point. + * @param cl Characteristic length of nonlocal model. * @param c1 Coordinates of master point. * @param c2 Coordinates of source point. * @param weight Original integration weight; on output modified weight. * @param[out] shieldFlag Set to true if shielding is activated. * @param nei The element with the non local material extension. */ - virtual void applyConstraint(const FloatArray &c1, const FloatArray &c2, double &weight, - bool &shieldFlag, NonlocalMaterialExtensionInterface *nei) = 0; + virtual void applyConstraint(const double cl, const FloatArray &c1, const FloatArray &c2, double &weight, + bool &shieldFlag, const NonlocalMaterialExtensionInterface &nei) = 0; /** * Abstract method calculating the minimum distance of the Gauss Point diff --git a/src/oofemlib/nonlocalmaterialext.C b/src/oofemlib/nonlocalmaterialext.C index ec692a15c..e9901cfee 100644 --- a/src/oofemlib/nonlocalmaterialext.C +++ b/src/oofemlib/nonlocalmaterialext.C @@ -48,7 +48,9 @@ #ifdef __PARALLEL_MODE #include "parallel.h" #endif - +#ifdef _OPENMP +#include +#endif #include namespace oofem { @@ -57,6 +59,9 @@ namespace oofem { // If not defined (default) only integration points with nonzero weight are included. // #define NMEI_USE_ALL_ELEMENTS_IN_SUPPORT +#ifdef _OPENMP + omp_lock_t NonlocalMaterialExtensionInterface::updateDomainBeforeNonlocAverageLock; +#endif // constructor NonlocalMaterialExtensionInterface :: NonlocalMaterialExtensionInterface(Domain *d) : Interface() @@ -88,21 +93,30 @@ NonlocalMaterialExtensionInterface :: NonlocalMaterialExtensionInterface(Domain averType = 0; gridSize = 0; - grid = NULL; - minDist2 = NULL; initDiag = 0.; order = 1; centDiff = 2; + +#ifdef _OPENMP + omp_init_lock(&NonlocalMaterialExtensionInterface::updateDomainBeforeNonlocAverageLock); +#endif } void -NonlocalMaterialExtensionInterface :: updateDomainBeforeNonlocAverage(TimeStep *tStep) +NonlocalMaterialExtensionInterface :: updateDomainBeforeNonlocAverage(TimeStep *tStep) const { - Domain *d = this->giveDomain(); + Domain *d = this->domain; if ( d->giveNonlocalUpdateStateCounter() == tStep->giveSolutionStateCounter() ) { return; // already updated } + #ifdef _OPENMP + omp_set_lock(&NonlocalMaterialExtensionInterface::updateDomainBeforeNonlocAverageLock); // if not initialized yet; one thread can proceed with init; others have to wait until init completed + if ( d->giveNonlocalUpdateStateCounter() == tStep->giveSolutionStateCounter() ) { + omp_unset_lock(&NonlocalMaterialExtensionInterface::updateDomainBeforeNonlocAverageLock); + return; // already updated + } +#endif OOFEM_LOG_DEBUG("Updating Before NonlocAverage\n"); for ( auto &elem : d->giveElements() ) { @@ -111,12 +125,16 @@ NonlocalMaterialExtensionInterface :: updateDomainBeforeNonlocAverage(TimeStep * // mark last update counter to prevent multiple updates d->setNonlocalUpdateStateCounter( tStep->giveSolutionStateCounter() ); +#ifdef _OPENMP + omp_unset_lock(&NonlocalMaterialExtensionInterface::updateDomainBeforeNonlocAverageLock); +#endif } void -NonlocalMaterialExtensionInterface :: buildNonlocalPointTable(GaussPoint *gp) +NonlocalMaterialExtensionInterface :: buildNonlocalPointTable(GaussPoint *gp) const { double elemVolume, integrationVolume = 0.; + double cl=this->cl, suprad; // bp: local to be thread safe NonlocalMaterialStatusExtensionInterface *statusExt = static_cast< NonlocalMaterialStatusExtensionInterface * >( gp->giveMaterialStatus()-> @@ -144,9 +162,11 @@ NonlocalMaterialExtensionInterface :: buildNonlocalPointTable(GaussPoint *gp) // If nonlocal variation is set to the distance-based approach, a new nonlocal radius // is calculated as a function of the distance from the Gauss point to the nonlocal boundaries if ( nlvar == NLVT_DistanceBasedLinear || nlvar == NLVT_DistanceBasedExponential ) { - // cl=cl0; - cl = giveDistanceBasedInteractionRadius(gpCoords); - suprad = evaluateSupportRadius(); + // cl=cl0; + cl = giveDistanceBasedInteractionRadius(gpCoords); + suprad = evaluateSupportRadius(cl); + } else { + suprad = this->suprad; } // If the mesh represents a periodic cell, nonlocal interaction is considered not only for the real neighbors @@ -165,20 +185,20 @@ NonlocalMaterialExtensionInterface :: buildNonlocalPointTable(GaussPoint *gp) // ask domain spatial localizer for list of elements with IP within this zone #ifdef NMEI_USE_ALL_ELEMENTS_IN_SUPPORT - this->giveDomain()->giveSpatialLocalizer()->giveAllElementsWithNodesWithinBox(elemSet, shiftedGpCoords, suprad); + this->domain->giveSpatialLocalizer()->giveAllElementsWithNodesWithinBox(elemSet, shiftedGpCoords, suprad); // insert element containing given gp elemSet.insert( gp->giveElement()->giveNumber() ); #else - this->giveDomain()->giveSpatialLocalizer()->giveAllElementsWithIpWithinBox_EvenIfEmpty(elemSet, shiftedGpCoords, suprad); + this->domain->giveSpatialLocalizer()->giveAllElementsWithIpWithinBox_EvenIfEmpty(elemSet, shiftedGpCoords, suprad); #endif // initialize iList iList->reserve(elemSet.giveSize()); for ( auto elindx : elemSet ) { - Element *ielem = this->giveDomain()->giveElement(elindx); + Element *ielem = this->domain->giveElement(elindx); if ( regionMap.at( ielem->giveRegionNumber() ) == 0 ) { for ( auto &jGp : *ielem->giveDefaultIntegrationRulePtr() ) { if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) { - double weight = this->computeWeightFunction(shiftedGpCoords, jGpCoords); + double weight = this->computeWeightFunction(cl, shiftedGpCoords, jGpCoords); //manipulate weights for a special averaging of strain (OFF by default) this->manipulateWeight(weight, gp, jGp); @@ -209,10 +229,11 @@ NonlocalMaterialExtensionInterface :: buildNonlocalPointTable(GaussPoint *gp) } void -NonlocalMaterialExtensionInterface :: rebuildNonlocalPointTable(GaussPoint *gp, IntArray *contributingElems) + NonlocalMaterialExtensionInterface :: rebuildNonlocalPointTable(GaussPoint *gp, IntArray *contributingElems) const { double weight, elemVolume, integrationVolume = 0.; - + double cl = this->cl; + NonlocalMaterialStatusExtensionInterface *statusExt = static_cast< NonlocalMaterialStatusExtensionInterface * >( gp->giveMaterialStatus()-> giveInterface(NonlocalMaterialStatusExtensionInterfaceType) ); @@ -226,7 +247,7 @@ NonlocalMaterialExtensionInterface :: rebuildNonlocalPointTable(GaussPoint *gp, if ( contributingElems == NULL ) { // no element table provided, use standard method - this->buildNonlocalPointTable(gp); + this->buildNonlocalPointTable(gp); } else { FloatArray gpCoords, jGpCoords; int _size = contributingElems->giveSize(); @@ -239,17 +260,16 @@ NonlocalMaterialExtensionInterface :: rebuildNonlocalPointTable(GaussPoint *gp, if ( nlvar == NLVT_DistanceBasedLinear || nlvar == NLVT_DistanceBasedExponential ) { cl = cl0; cl = giveDistanceBasedInteractionRadius(gpCoords); - suprad = evaluateSupportRadius(); } // initialize iList iList->reserve(_size); for ( int _e = 1; _e <= _size; _e++ ) { - Element *ielem = this->giveDomain()->giveElement( contributingElems->at(_e) ); + Element *ielem = const_cast(this)->giveDomain()->giveElement( contributingElems->at(_e) ); if ( regionMap.at( ielem->giveRegionNumber() ) == 0 ) { for ( auto &jGp : *ielem->giveDefaultIntegrationRulePtr() ) { if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) { - weight = this->computeWeightFunction(gpCoords, jGpCoords); + weight = this->computeWeightFunction(cl, gpCoords, jGpCoords); //manipulate weights for a special averaging of strain (OFF by default) this->manipulateWeight(weight, gp, jGp); @@ -291,10 +311,15 @@ NonlocalMaterialExtensionInterface :: rebuildNonlocalPointTable(GaussPoint *gp, // This is the method used by eikonal nonlocal models to adjust the nonlocal interaction // depending on the evolution of some internal variables such as damage void -NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunctionAround(GaussPoint *gp) + NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunctionAround(GaussPoint *gp) const { Element *elem = gp->giveElement(); FloatArray coords; + // Grid on which the eikonal equation will be solved (used by eikonal nonlocal models) + Grid grid(2 *gridSize + 1, 2 *gridSize + 1); + // Auxiliary matrix to store minimum distances of grid points from Gauss points + FloatMatrix minDist2(2 *gridSize + 1, 2 *gridSize + 1); + elem->computeGlobalCoordinates( coords, gp->giveNaturalCoordinates() ); int dim = coords.giveSize(); if ( dim == 1 ) { @@ -309,7 +334,7 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunctionAround(GaussPo #endif // Compute the "speed" at each grid node, depending on damage or a similar variable (note that "speed" will be deleted by grid) - FloatMatrix *speed = grid->givePrescribedField(); + FloatMatrix &speed = grid.givePrescribedField(); // This is a simple initialization that leads to standard Euclidean distance /* * for (i=1; i<=2*gridSize+1; i++) @@ -341,8 +366,8 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunctionAround(GaussPo if ( ipos == 1 ) { for ( int i = 1; i <= 2 * gridSize + 1; i++ ) { for ( int j = 1; j <= 2 * gridSize + 1; j++ ) { - minDist2->at(i, j) = dist2FromGridNode(xngp, yngp, j, i); - speed->at(i, j) = damgp; + minDist2.at(i, j) = dist2FromGridNode(xngp, yngp, j, i); + speed.at(i, j) = damgp; } } // For the other neighbors, check whether distance is smaller and update damage @@ -350,9 +375,9 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunctionAround(GaussPo for ( int i = 1; i <= 2 * gridSize + 1; i++ ) { for ( int j = 1; j <= 2 * gridSize + 1; j++ ) { double dist2 = dist2FromGridNode(xngp, yngp, j, i); - if ( dist2 < minDist2->at(i, j) ) { - minDist2->at(i, j) = dist2; - speed->at(i, j) = damgp; + if ( dist2 < minDist2.at(i, j) ) { + minDist2.at(i, j) = dist2; + speed.at(i, j) = damgp; } } } @@ -362,20 +387,20 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunctionAround(GaussPo // Transform damage to speed for ( int i = 1; i <= 2 * gridSize + 1; i++ ) { for ( int j = 1; j <= 2 * gridSize + 1; j++ ) { - speed->at(i, j) = 1. / computeDistanceModifier( speed->at(i, j) ); + speed.at(i, j) = 1. / computeDistanceModifier( cl, speed.at(i, j) ); } } // Initialize grid for distance evaluation - grid->unFreeze(); + grid.unFreeze(); // Set the details of the method that should be used by the grid - grid->setMethod(order, initDiag, centDiff); + grid.setMethod(order, initDiag, centDiff); // Set zero distance at the grid center FloatMatrix center(1, 2); center.at(1, 1) = center.at(1, 2) = ( double ) gridSize + 1; - grid->setZeroValues(& center); + grid.setZeroValues(& center); // The fast marching method will be invoked implicitly, by asking for the solution @@ -400,7 +425,7 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunctionAround(GaussPo } // Get solution value from the nearest grid point - double distance = ( suprad / gridSize ) * grid->giveSolutionValueAt(i, j); + double distance = ( suprad / gridSize ) * grid.giveSolutionValueAt(i, j); if ( distance < 0. ) { printf("Warning\n"); } @@ -411,7 +436,7 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunctionAround(GaussPo static_cast< NonlocalMaterialStatusExtensionInterface * >( lip.nearGp->giveMaterialStatus()-> giveInterface(NonlocalMaterialStatusExtensionInterfaceType) ); double volumeAround = statusExt->giveVolumeAround(); - double w = computeWeightFunction(distance) * volumeAround; + double w = computeWeightFunction(cl, distance) * volumeAround; lip.weight = w; wsum += w; } @@ -425,7 +450,7 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunctionAround(GaussPo // Simple algorithm, limited to 1D, can be used for comparison void -NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunction_1D_Around(GaussPoint *gp) +NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunction_1D_Around(GaussPoint *gp) const { auto *list = this->giveIPIntegrationList(gp); std :: vector< localIntegrationRecord > :: iterator postarget; @@ -442,17 +467,16 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunction_1D_Around(Gau elem->computeGlobalCoordinates( coords, gp->giveNaturalCoordinates() ); double xtarget = coords.at(1); - double w, wsum = 0., x, xprev, damage, damageprev = 0.; - Element *nearElem; + double wsum = 0., xprev, damageprev = 0.; // process the list from the target to the end double distance = 0.; // distance modified by damage xprev = xtarget; for ( auto pos = postarget; pos != list->end(); ++pos ) { - nearElem = ( pos->nearGp )->giveElement(); + Element *nearElem = ( pos->nearGp )->giveElement(); nearElem->computeGlobalCoordinates( coords, pos->nearGp->giveNaturalCoordinates() ); - x = coords.at(1); - damage = this->giveNonlocalMetricModifierAt(pos->nearGp); + double x = coords.at(1); + double damage = this->giveNonlocalMetricModifierAt(pos->nearGp); /* * nonlocStatus = static_cast< IDNLMaterialStatus * >( this->giveStatus(pos->nearGp) ); * damage = nonlocStatus->giveTempDamage(); @@ -466,7 +490,7 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunction_1D_Around(Gau //( x - xprev ) * 0.5 * ( computeDistanceModifier(damage) + computeDistanceModifier(damageprev) ); } - w = computeWeightFunction(distance) * nearElem->computeVolumeAround(pos->nearGp); + double w = computeWeightFunction(cl, distance) * nearElem->computeVolumeAround(pos->nearGp); pos->weight = w; wsum += w; xprev = x; @@ -476,10 +500,10 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunction_1D_Around(Gau // process the list from the target to the beginning distance = 0.; for ( auto pos = postarget; pos != list->begin(); --pos ) { - nearElem = ( pos->nearGp )->giveElement(); + Element *nearElem = ( pos->nearGp )->giveElement(); nearElem->computeGlobalCoordinates( coords, pos->nearGp->giveNaturalCoordinates() ); - x = coords.at(1); - damage = this->giveNonlocalMetricModifierAt(pos->nearGp); + double x = coords.at(1); + double damage = this->giveNonlocalMetricModifierAt(pos->nearGp); /* * nonlocStatus = static_cast< IDNLMaterialStatus * >( this->giveStatus(pos->nearGp) ); * damage = nonlocStatus->giveTempDamage(); @@ -491,7 +515,7 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunction_1D_Around(Gau if ( pos != postarget ) { distance += computeModifiedLength(xprev - x, damage, damageprev); //distance += ( xprev - x ) * 0.5 * ( computeDistanceModifier(damage) + computeDistanceModifier(damageprev) ); - w = computeWeightFunction(distance) * nearElem->computeVolumeAround(pos->nearGp); + double w = computeWeightFunction(cl, distance) * nearElem->computeVolumeAround(pos->nearGp); pos->weight = w; wsum += w; } @@ -503,10 +527,10 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunction_1D_Around(Gau // the beginning must be treated separately auto pos = list->begin(); if ( pos != postarget ) { - nearElem = ( pos->nearGp )->giveElement(); + Element *nearElem = ( pos->nearGp )->giveElement(); nearElem->computeGlobalCoordinates( coords, pos->nearGp->giveNaturalCoordinates() ); - x = coords.at(1); - damage = this->giveNonlocalMetricModifierAt(pos->nearGp); + double x = coords.at(1); + double damage = this->giveNonlocalMetricModifierAt(pos->nearGp); /* * nonlocStatus = static_cast< IDNLMaterialStatus * >( this->giveStatus(pos->nearGp) ); * damage = nonlocStatus->giveTempDamage(); @@ -517,7 +541,7 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunction_1D_Around(Gau distance += computeModifiedLength(xprev - x, damage, damageprev); //distance += ( xprev - x ) * 0.5 * ( computeDistanceModifier(damage) + computeDistanceModifier(damageprev) ); - w = computeWeightFunction(distance) * nearElem->computeVolumeAround(pos->nearGp); + double w = computeWeightFunction(cl, distance) * nearElem->computeVolumeAround(pos->nearGp); pos->weight = w; wsum += w; } @@ -530,18 +554,18 @@ NonlocalMaterialExtensionInterface :: modifyNonlocalWeightFunction_1D_Around(Gau } double -NonlocalMaterialExtensionInterface :: computeModifiedLength(double length, double dam1, double dam2) +NonlocalMaterialExtensionInterface :: computeModifiedLength(double length, double dam1, double dam2) const { if ( averType == 6 ) { // different (improved) integration scheme - return length * 2. / ( 1. / computeDistanceModifier(dam1) + 1. / computeDistanceModifier(dam2) ); + return length * 2. / ( 1. / computeDistanceModifier(cl, dam1) + 1. / computeDistanceModifier(cl, dam2) ); } else { // standard integration scheme //printf("%g %g %g %g %g %g\n",dam1,dam2,computeDistanceModifier(dam1),computeDistanceModifier(dam2),length,length * 0.5 * ( computeDistanceModifier(dam1) + computeDistanceModifier(dam2) )); - return length * 0.5 * ( computeDistanceModifier(dam1) + computeDistanceModifier(dam2) ); + return length * 0.5 * ( computeDistanceModifier(cl, dam1) + computeDistanceModifier(cl, dam2) ); } } double -NonlocalMaterialExtensionInterface :: computeDistanceModifier(double damage) +NonlocalMaterialExtensionInterface :: computeDistanceModifier(double cl, double damage) const { switch ( averType ) { case 2: return 1. / ( Rf / cl + ( 1. - Rf / cl ) * pow(1. - damage, exponent) ); @@ -563,7 +587,7 @@ NonlocalMaterialExtensionInterface :: computeDistanceModifier(double damage) } std :: vector< localIntegrationRecord > * -NonlocalMaterialExtensionInterface :: giveIPIntegrationList(GaussPoint *gp) +NonlocalMaterialExtensionInterface :: giveIPIntegrationList(GaussPoint *gp) const { NonlocalMaterialStatusExtensionInterface *statusExt = static_cast< NonlocalMaterialStatusExtensionInterface * >( gp->giveMaterialStatus()-> @@ -574,17 +598,16 @@ NonlocalMaterialExtensionInterface :: giveIPIntegrationList(GaussPoint *gp) } if ( statusExt->giveIntegrationDomainList()->empty() ) { - this->buildNonlocalPointTable(gp); + this->buildNonlocalPointTable(gp); } return statusExt->giveIntegrationDomainList(); } void -NonlocalMaterialExtensionInterface :: endIPNonlocalAverage(GaussPoint *gp) +NonlocalMaterialExtensionInterface :: endIPNonlocalAverage(GaussPoint *gp) const { - NonlocalMaterialStatusExtensionInterface *statusExt = - static_cast< NonlocalMaterialStatusExtensionInterface * >( gp->giveMaterialStatus()-> + auto statusExt = static_cast< NonlocalMaterialStatusExtensionInterface * >( gp->giveMaterialStatus()-> giveInterface(NonlocalMaterialStatusExtensionInterfaceType) ); if ( !statusExt ) { @@ -597,7 +620,7 @@ NonlocalMaterialExtensionInterface :: endIPNonlocalAverage(GaussPoint *gp) } double -NonlocalMaterialExtensionInterface :: computeWeightFunction(double distance) +NonlocalMaterialExtensionInterface :: computeWeightFunction(double cl, double distance) const { if ( weightFun == WFT_UniformOverElement ) { // uniform function over one element return 1.; @@ -607,8 +630,8 @@ NonlocalMaterialExtensionInterface :: computeWeightFunction(double distance) return 0.; } - double aux = distance / this->cl; - double iwf = giveIntegralOfWeightFunction( this->domain->giveNumberOfSpatialDimensions() ); + double aux = distance / cl; + double iwf = giveIntegralOfWeightFunction( cl, this->domain->giveNumberOfSpatialDimensions() ); switch ( weightFun ) { case WFT_Bell: // Bell shaped function (quartic spline) @@ -629,16 +652,16 @@ NonlocalMaterialExtensionInterface :: computeWeightFunction(double distance) * OOFEM_ERROR("this type of weight function can be used for a 1D problem only"); * } */ - iwf = giveIntegralOfWeightFunction(2); // indeed + iwf = giveIntegralOfWeightFunction(cl, 2); // indeed double x = distance; double y = 0.; double r = sqrt(x * x + y * y); - double sum = exp(-r / this->cl); - double h = this->cl / 10.; // 10 could later be replaced by an optional parameter + double sum = exp(-r / cl); + double h = cl / 10.; // 10 could later be replaced by an optional parameter do { y += h; r = sqrt(x * x + y * y); - sum += 2. * exp(-r / this->cl); + sum += 2. * exp(-r / cl); } while ( r <= suprad ); //printf("%14g %14g\n",distance,sum * h / iwf); return sum * h / iwf; @@ -654,13 +677,13 @@ NonlocalMaterialExtensionInterface :: computeWeightFunction(double distance) } double -NonlocalMaterialExtensionInterface :: computeWeightFunction(const FloatArray &src, const FloatArray &coord) + NonlocalMaterialExtensionInterface :: computeWeightFunction(const double cl, const FloatArray &src, const FloatArray &coord) const { - return computeWeightFunction( src.distance(coord) ); + return computeWeightFunction( cl, distance(src, coord) ); } double -NonlocalMaterialExtensionInterface :: giveIntegralOfWeightFunction(const int spatial_dimension) +NonlocalMaterialExtensionInterface :: giveIntegralOfWeightFunction(double cl, const int spatial_dimension) const { const double pi = M_PI; switch ( weightFun ) { @@ -716,12 +739,12 @@ NonlocalMaterialExtensionInterface :: giveIntegralOfWeightFunction(const int spa double NonlocalMaterialExtensionInterface :: maxValueOfWeightFunction() { - double iwf = giveIntegralOfWeightFunction( this->domain->giveNumberOfSpatialDimensions() ); + double iwf = giveIntegralOfWeightFunction( cl, this->domain->giveNumberOfSpatialDimensions() ); return 1. / iwf; } double -NonlocalMaterialExtensionInterface :: evaluateSupportRadius() +NonlocalMaterialExtensionInterface :: evaluateSupportRadius(double cl) const { switch ( weightFun ) { case WFT_Bell: return cl; @@ -739,12 +762,10 @@ NonlocalMaterialExtensionInterface :: evaluateSupportRadius() } -IRResultType -NonlocalMaterialExtensionInterface :: initializeFrom(InputRecord *ir) +void +NonlocalMaterialExtensionInterface :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - if ( ir->hasField(_IFT_NonlocalMaterialExtensionInterface_regionmap) ) { + if ( ir.hasField(_IFT_NonlocalMaterialExtensionInterface_regionmap) ) { IR_GIVE_FIELD(ir, regionMap, _IFT_NonlocalMaterialExtensionInterface_regionmap); if ( regionMap.giveSize() != this->giveDomain()->giveNumberOfRegions() ) { OOFEM_ERROR("regionMap size mismatch"); @@ -782,7 +803,7 @@ NonlocalMaterialExtensionInterface :: initializeFrom(InputRecord *ir) } // evaluate the support radius based on type of weight function and characteristic length - suprad = evaluateSupportRadius(); + suprad = evaluateSupportRadius(cl); // read the optional parameter for overnonlocal formulation mm = 1.; @@ -841,8 +862,6 @@ NonlocalMaterialExtensionInterface :: initializeFrom(InputRecord *ir) if ( averType >= 2 && averType <= 6 ) { // eikonal models gridSize = 10; // default value IR_GIVE_OPTIONAL_FIELD(ir, gridSize, _IFT_NonlocalMaterialExtensionInterface_gridsize); - grid = new Grid(2 *gridSize + 1, 2 *gridSize + 1); - minDist2 = new FloatMatrix(2 *gridSize + 1, 2 *gridSize + 1); order = 1; // default value IR_GIVE_OPTIONAL_FIELD(ir, order, _IFT_NonlocalMaterialExtensionInterface_order); initDiag = 0.; // default value @@ -850,8 +869,6 @@ NonlocalMaterialExtensionInterface :: initializeFrom(InputRecord *ir) centDiff = 2; // default value IR_GIVE_OPTIONAL_FIELD(ir, centDiff, _IFT_NonlocalMaterialExtensionInterface_centdiff); } - - return IRRT_OK; } @@ -905,13 +922,13 @@ void NonlocalMaterialExtensionInterface :: giveInputRecord(DynamicInputRecord &i */ void -NonlocalMaterialExtensionInterface :: applyBarrierConstraints(const FloatArray &gpCoords, const FloatArray &jGpCoords, double &weight) +NonlocalMaterialExtensionInterface :: applyBarrierConstraints(const FloatArray &gpCoords, const FloatArray &jGpCoords, double &weight) const { int ib, nbarrier = domain->giveNumberOfNonlocalBarriers(); bool shieldFlag = false; for ( ib = 1; ib <= nbarrier; ib++ ) { - domain->giveNonlocalBarrier(ib)->applyConstraint(gpCoords, jGpCoords, weight, shieldFlag, this); + domain->giveNonlocalBarrier(ib)->applyConstraint(cl, gpCoords, jGpCoords, weight, shieldFlag, *this); if ( shieldFlag ) { weight = 0.0; return; @@ -920,7 +937,7 @@ NonlocalMaterialExtensionInterface :: applyBarrierConstraints(const FloatArray & } void -NonlocalMaterialExtensionInterface :: manipulateWeight(double &weight, GaussPoint *gp, GaussPoint *jGp) +NonlocalMaterialExtensionInterface :: manipulateWeight(double &weight, GaussPoint *gp, GaussPoint *jGp) const { Element *ielem = jGp->giveElement(); IntegrationRule *iRule = ielem->giveDefaultIntegrationRulePtr(); @@ -934,7 +951,7 @@ NonlocalMaterialExtensionInterface :: manipulateWeight(double &weight, GaussPoin double -NonlocalMaterialExtensionInterface :: giveDistanceBasedInteractionRadius(const FloatArray &gpCoords) +NonlocalMaterialExtensionInterface :: giveDistanceBasedInteractionRadius(const FloatArray &gpCoords) const { double distance = 1.e10; // Initially distance from the boundary is set to the maximum value double temp; diff --git a/src/oofemlib/nonlocalmaterialext.h b/src/oofemlib/nonlocalmaterialext.h index abb75f3f4..db203c174 100644 --- a/src/oofemlib/nonlocalmaterialext.h +++ b/src/oofemlib/nonlocalmaterialext.h @@ -40,9 +40,13 @@ #include "intarray.h" #include "grid.h" #include "mathfem.h" +#include "dynamicinputrecord.h" #include - +#include +#ifdef _OPENMP +#include +#endif ///@name Input fields for NonlocalMaterialExtensionInterface //@{ #define _IFT_NonlocalMaterialExtensionInterface_regionmap "regionmap" @@ -80,6 +84,15 @@ struct localIntegrationRecord { double weight; }; + enum WeightFunctionType { + WFT_Unknown, + WFT_Bell, + WFT_Gauss, + WFT_Green, + WFT_Uniform, + WFT_UniformOverElement, + WFT_Green_21 }; + /** * Abstract base class for all nonlocal constitutive model statuses. Introduces the list of * localIntegrationRecords stored in each integration point, where references to all influencing @@ -169,36 +182,31 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * * StateCounterType lastUpdatedStateCounter; */ - Domain *domain; + Domain *domain = nullptr; /// Map indicating regions to skip (region - cross section model). IntArray regionMap; /// Flag indicating whether to keep nonlocal interaction tables of integration points cached. - bool permanentNonlocTableFlag; - /// Type characterizing the nonlocal weight function. - enum WeightFunctionType { WFT_Unknown, WFT_Bell, WFT_Gauss, WFT_Green, WFT_Uniform, WFT_UniformOverElement, WFT_Green_21 }; + bool permanentNonlocTableFlag = false; /// Parameter specifying the type of nonlocal weight function. WeightFunctionType weightFun; /// Grid on which the eikonal equation will be solved (used by eikonal nonlocal models) - int gridSize; - Grid *grid; - /// Auxiliary matrix to store minimum distances of grid points from Gauss points - FloatMatrix *minDist2; + int gridSize = 0; /// Optional parameters setting details of the fast marching method - double initDiag; - int order; - int centDiff; + double initDiag = 0.; + int order = 0; + int centDiff = 0; /** * Characteristic length of the nonlocal model * (its interpretation depends on the type of weight function). */ - double cl; + mutable double cl = 0.; /// Support radius. - double suprad; + mutable double suprad = 0.; /// For "undernonlocal" or "overnonlocal" formulation. - double mm; + double mm = 0.; /// Type characterizing the scaling approach. enum ScalingType { ST_Unknown, ST_Standard, ST_Noscaling, ST_Borino }; @@ -216,7 +224,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * Is different to cl when a Stress-based or a Distance-based * nonlocal variation is applied */ - double cl0; + double cl0 = 0.; /// Type characterizing the Nonlocal variation enum NlVariationType { NLVT_Standard, NLVT_DistanceBasedLinear, NLVT_StressBased, NLVT_DistanceBasedExponential }; ///Parameter specifying the type of nonlocal variation. @@ -226,7 +234,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * gives its minimum allowed value. It is used when a Stress-based * or a Distance-based nonlocal variation is applied */ - double beta; + double beta = 0.; /** * Parameter used when Distance-based nonlocal variation is applied * When it is multiplied with the interaction radius cl gives the maxinmum @@ -234,7 +242,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * from the boundary is larger than this value the interaction radius cl is set * to cl0 */ - double zeta; + double zeta = 0.; /** * Parameter specifying the periodic shift in x-direction. Typically it is zero. @@ -243,17 +251,21 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * but also if the source point shifted by -px or +px satisfies this condition. * This is useful if the mesh represents a periodic cell. */ - double px; + double px = 0.; // Parameters used by models with evolving characteristic length. /// Final value of interaction radius, for a model with evolving characteristic length. - double Rf; + double Rf = 0.; /// Parameter used as an exponent by models with evolving characteristic length. - double exponent; + double exponent = 0.; /// Parameter specifying how the weight function should be adjusted due to damage. - int averType; + int averType = 0; +#ifdef _OPENMP + public: + static omp_lock_t updateDomainBeforeNonlocAverageLock; +#endif public: /** * Constructor. Creates material with given number, belonging to given domain. @@ -261,7 +273,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface */ NonlocalMaterialExtensionInterface(Domain *d); /// Destructor. - virtual ~NonlocalMaterialExtensionInterface() { delete grid; delete minDist2; } + virtual ~NonlocalMaterialExtensionInterface() { } /** @@ -279,7 +291,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * last modification time mark is kept. * @see Element::updateBeforeNonlocalAverage */ - void updateDomainBeforeNonlocAverage(TimeStep *tStep); + void updateDomainBeforeNonlocAverage(TimeStep *tStep) const; /** * Builds list of integration points which take part in nonlocal average in given integration point. @@ -289,7 +301,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * influencing integration points would be wasting of space and should be cleared after averaging has * been finished in integration point. The endIPNonlocalAverage method will ensure this. */ - void buildNonlocalPointTable(GaussPoint *gp); + void buildNonlocalPointTable(GaussPoint *gp) const; /** * Rebuild list of integration points which take part @@ -298,33 +310,33 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * a complete list of elements contributing to receiver. If equal to NULL * existing list is cleared and buildNonlocalPointTable service is invoked. */ - void rebuildNonlocalPointTable(GaussPoint *gp, IntArray *contributingElems); + void rebuildNonlocalPointTable(GaussPoint *gp, IntArray *contributingElems) const; /** * Recompute the nonlocal interaction weights based on the current solution (e.g., on the damage field). * This method is used e.g. by eikonal nonlocal damage models. */ - void modifyNonlocalWeightFunctionAround(GaussPoint *gp); - void modifyNonlocalWeightFunction_1D_Around(GaussPoint *gp); + void modifyNonlocalWeightFunctionAround(GaussPoint *gp) const; + void modifyNonlocalWeightFunction_1D_Around(GaussPoint *gp) const; /** * Provide the current value of the variable that affects nonlocal interaction (e.g., of damage) * This method is used e.g. by eikonal nonlocal damage models. */ - virtual double giveNonlocalMetricModifierAt(GaussPoint *gp) { return 1.; } + virtual double giveNonlocalMetricModifierAt(GaussPoint *gp) const { return 1.; } /** * Compute the factor that specifies how the interaction length should be modified, * based on the current solution (e.g., on the damage field). * This method is used e.g. by eikonal nonlocal damage models. */ - double computeDistanceModifier(double damage); + double computeDistanceModifier(double cl, double damage) const; /** * Compute the modified interaction length based on the current solution (e.g., on the damage field). * This method is used e.g. by eikonal nonlocal damage models. */ - double computeModifiedLength(double length, double dam1, double dam2); + double computeModifiedLength(double length, double dam1, double dam2) const; /** * Returns integration list corresponding to given integration point. @@ -333,7 +345,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * receiver's associated integration point. * Rebuilds the IP list by calling buildNonlocalPointTable if not available. */ - std :: vector< localIntegrationRecord > *giveIPIntegrationList(GaussPoint *gp); + std :: vector< localIntegrationRecord > *giveIPIntegrationList(GaussPoint *gp) const; /** * Evaluates the basic nonlocal weight function for a given distance @@ -342,7 +354,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * @param distance Distance between interacting points. * @return Value of weight function. */ - virtual double computeWeightFunction(double distance); + virtual double computeWeightFunction(const double cl, const double distance) const; /** * Evaluates the basic nonlocal weight function for two points @@ -352,13 +364,13 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * @param coord Coordinates of receiver point. * @return Value of weight function. */ - virtual double computeWeightFunction(const FloatArray &src, const FloatArray &coord); + virtual double computeWeightFunction(const double cl, const FloatArray &src, const FloatArray &coord) const; /** * Provides the integral of the weight function * over the contributing volume in 1, 2 or 3D. */ - double giveIntegralOfWeightFunction(const int spatial_dimension); + double giveIntegralOfWeightFunction(double cl, const int spatial_dimension) const; /// Determines the maximum value of the nonlocal weight function. @@ -368,7 +380,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * Determines the number of material regions of domain. * In the current implementation the region is associated with cross section model. */ - int giveNumberOfRegions(); + int giveNumberOfRegions() const; /* * Returns the region id of given element * @param element pointer to element which region id is requested. @@ -379,17 +391,17 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * Determines, whether receiver has bounded weighting function (limited support). * @return True if weighting function bounded, zero otherwise. */ - virtual int hasBoundedSupport() { return 1; } + virtual int hasBoundedSupport() const { return 1; } /** * Determines the width (radius) of limited support of weighting function. * i.e., the distance at which the interaction weight becomes zero. */ - virtual double evaluateSupportRadius(); + virtual double evaluateSupportRadius(double cl) const; /// Returns reference to domain. Domain *giveDomain() { return this->domain; } - IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir); /** * Stores receiver in an input record * @param input Input record to be filled in. @@ -408,7 +420,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * This can save significant memory, since nonlocal tables are not stored, but every time computed when needed, * but on the other hand computational time may significantly grow. */ - void endIPNonlocalAverage(GaussPoint *gp); + void endIPNonlocalAverage(GaussPoint *gp) const; protected: /* @@ -421,7 +433,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface */ //bool isBarrierActivated (const FloatArray& c1, const FloatArray& c2) const; - void applyBarrierConstraints(const FloatArray &gpCoords, const FloatArray &jGpCoords, double &weight); + void applyBarrierConstraints(const FloatArray &gpCoords, const FloatArray &jGpCoords, double &weight) const; /** * Manipulates weight on integration point in the element. @@ -431,7 +443,7 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * @param gp Pointer to the GP owing the PointTable. * @param jGp Pointer to GP in the PointTable. */ - void manipulateWeight(double &weight, GaussPoint *gp, GaussPoint *jGp); + void manipulateWeight(double &weight, GaussPoint *gp, GaussPoint *jGp) const; /** * Provides the distance based interaction radius @@ -441,11 +453,11 @@ class OOFEM_EXPORT NonlocalMaterialExtensionInterface : public Interface * @param gpCoords The Gauss points' coordinates, whose interaction radius is calculated based on the distance-based averaging approach. * @return New interaction radius based on the Distance of the Gauss Point from Nonlocal Boundaries. */ - double giveDistanceBasedInteractionRadius(const FloatArray &gpCoords); + double giveDistanceBasedInteractionRadius(const FloatArray &gpCoords) const; - int mapToGridPoint(double x, double x0) { return 1 + gridSize + ( int ) ceil(gridSize * ( x - x0 ) / suprad - 0.5); } - double mapToGridCoord(double x, double x0) { return 1. + gridSize + gridSize * ( x - x0 ) / suprad; } - double dist2FromGridNode(double x, double y, int j, int i) { return ( ( x - j ) * ( x - j ) + ( y - i ) * ( y - i ) ); } + int mapToGridPoint(double x, double x0) const { return 1 + gridSize + ( int ) ceil(gridSize * ( x - x0 ) / suprad - 0.5); } + double mapToGridCoord(double x, double x0) const { return 1. + gridSize + gridSize * ( x - x0 ) / suprad; } + double dist2FromGridNode(double x, double y, int j, int i) const { return ( ( x - j ) * ( x - j ) + ( y - i ) * ( y - i ) ); } }; } // end namespace oofem #endif // nonlocalmaterialext_h diff --git a/src/oofemlib/nonlocalmatwtp.C b/src/oofemlib/nonlocalmatwtp.C index 8c92e8742..3c108bc93 100644 --- a/src/oofemlib/nonlocalmatwtp.C +++ b/src/oofemlib/nonlocalmatwtp.C @@ -420,7 +420,6 @@ int NonlocalMaterialWTP :: unpackRemoteElements(Domain *d, ProcessCommunicator & int myrank = d->giveEngngModel()->giveRank(); int iproc = pc.giveRank(); std :: string _type; - DofManager *dofman; IntArray _partitions; if ( iproc == myrank ) { @@ -436,22 +435,20 @@ int NonlocalMaterialWTP :: unpackRemoteElements(Domain *d, ProcessCommunicator & if ( _type.size() == 0 ) { break; } - dofman = classFactory.createDofManager(_type.c_str(), 0, d); + auto dofman = classFactory.createDofManager(_type.c_str(), 0, d); dofman->restoreContext(*pcbuff, CM_Definition | CM_State | CM_UnknownDictState); dofman->setParallelMode(DofManager_null); if ( d->dofmanGlobal2Local( dofman->giveGlobalNumber() ) ) { // record already exist - delete dofman; } else { d->giveTransactionManager()->addDofManTransaction(DomainTransactionManager :: DTT_ADD, dofman->giveGlobalNumber(), - dofman); + dofman.release()); ///@todo Can be do safer than just releasing? } } while ( 1 ); // unpack element data - Element *elem; _partitions.resize(1); _partitions.at(1) = iproc; do { @@ -460,7 +457,7 @@ int NonlocalMaterialWTP :: unpackRemoteElements(Domain *d, ProcessCommunicator & break; } - elem = classFactory.createElement(_type.c_str(), 0, d); + auto elem = classFactory.createElement(_type.c_str(), 0, d).release(); ///@todo Can be do safer than just releasing? elem->restoreContext(*pcbuff, CM_Definition | CM_State); elem->setParallelMode(Element_remote); elem->setPartitionList(_partitions); diff --git a/src/oofemlib/nonlocalmatwtp.h b/src/oofemlib/nonlocalmatwtp.h index b19e25cb9..0b13a5fdc 100644 --- a/src/oofemlib/nonlocalmatwtp.h +++ b/src/oofemlib/nonlocalmatwtp.h @@ -76,7 +76,7 @@ class OOFEM_EXPORT NonlocalMaterialWTP : public LoadBalancer :: WorkTransferPlug * Current implementation assembles for each local element the list * of contributing global element numbers. This is extracted from IP nonlocal tables; */ - void init(Domain *d); + void init(Domain *d) override; /** * Migrates necessary local elements to remote processors, where they * become remote elements needed to efficiently handle nonlocal dependencies. @@ -87,12 +87,12 @@ class OOFEM_EXPORT NonlocalMaterialWTP : public LoadBalancer :: WorkTransferPlug * - build domain nonlocal element dependency list. Then exclude local elements - what remains are unsatisfied remote dependencies that have to be broadcasted and received from partitions owning relevant elements * - transfer of local elements and nodes to remote partitions (remote elements and null dofmans) */ - void migrate(); + void migrate() override; /** * Called after all wtps migrated their data. Intended to update local data structure. * Current implementations rebuilds the nonlocal integration point tables. */ - void update(); + void update() override; protected: void giveElementNonlocalDepArry(IntArray &answer, Domain *d, int num); diff --git a/src/oofemlib/nrsolver.C b/src/oofemlib/nrsolver.C index 31fe89121..acd722d86 100644 --- a/src/oofemlib/nrsolver.C +++ b/src/oofemlib/nrsolver.C @@ -81,8 +81,8 @@ NRSolver :: NRSolver(Domain *d, EngngModel *m) : prescribedEqsInitFlag = false; prescribedDisplacementTF = 0; lsFlag = 0; // no line-search - - constrainedNRFlag = false; + + constrainedNRFlag = false; this->forceErrVecOld.resize(0); this->forceErrVec.resize(0); constrainedNRalpha = 0.5; // default @@ -95,14 +95,13 @@ NRSolver :: NRSolver(Domain *d, EngngModel *m) : NRSolver :: ~NRSolver() -{ -} +{} -IRResultType -NRSolver :: initializeFrom(InputRecord *ir) +void +NRSolver :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + SparseNonLinearSystemNM :: initializeFrom(ir); // Choosing a big "enough" number. (Alternative: Force input of maxinter) nsmax = ( int ) 1e8; @@ -129,14 +128,16 @@ NRSolver :: initializeFrom(InputRecord *ir) int _val = 0; IR_GIVE_OPTIONAL_FIELD(ir, _val, _IFT_NRSolver_lstype); solverType = ( LinSystSolverType ) _val; - this->giveLinearSolver()->initializeFrom(ir); // make sure that linear solver is initialized from ir as well + this->giveLinearSolver()->initializeFrom(ir); // make sure that linear solver is initialized from it as well // read relative error tolerances of the solver // if rtolv provided set to this tolerance both rtolf and rtold rtolf.resize(1); rtolf.at(1) = 1.e-3; // Default value. rtold.resize(1); - rtold = FloatArray{0.0}; // Default off (0.0 or negative values mean that residual is ignored) + rtold = FloatArray { + 0.0 + }; // Default off (0.0 or negative values mean that residual is ignored) IR_GIVE_OPTIONAL_FIELD(ir, rtolf.at(1), _IFT_NRSolver_rtolv); IR_GIVE_OPTIONAL_FIELD(ir, rtold.at(1), _IFT_NRSolver_rtolv); @@ -175,7 +176,9 @@ NRSolver :: initializeFrom(InputRecord *ir) mCalcStiffBeforeRes = false; } - + solutionDependentExternalForcesFlag = ir.hasField(_IFT_NRSolver_solutionDependentExternalForces); + + this->constrainedNRminiter = 0; IR_GIVE_OPTIONAL_FIELD(ir, this->constrainedNRminiter, _IFT_NRSolver_constrainedNRminiter); this->constrainedNRFlag = this->constrainedNRminiter != 0; @@ -184,17 +187,16 @@ NRSolver :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, this->maxIncAllowed, _IFT_NRSolver_maxinc); dg_forceScale.clear(); - if ( ir->hasField(_IFT_NRSolver_forceScale) ) { + if ( ir.hasField(_IFT_NRSolver_forceScale) ) { IntArray dofs; FloatArray forces; IR_GIVE_FIELD(ir, forces, _IFT_NRSolver_forceScale); IR_GIVE_FIELD(ir, dofs, _IFT_NRSolver_forceScaleDofs); for ( int i = 0; i < dofs.giveSize(); ++i ) { - dg_forceScale[dofs[i]] = forces[i]; + dg_forceScale [ dofs [ i ] ] = forces [ i ]; } } - return SparseNonLinearSystemNM :: initializeFrom(ir); } @@ -263,8 +265,8 @@ NRSolver :: solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, for ( nite = 0; ; ++nite ) { // Compute the residual engngModel->updateComponent(tStep, InternalRhs, domain); - rhs.beDifferenceOf(RT, F); - + rhs.beDifferenceOf(RT, F); + if ( this->prescribedDofsFlag ) { this->applyConstraintsToLoadIncrement(nite, k, rhs, rlm, tStep); } @@ -296,10 +298,9 @@ NRSolver :: solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, R.zero(); ddX = rhs; } else { - -// if ( engngModel->giveProblemScale() == macroScale ) { -// k.writeToFile("k.txt"); -// } + // if ( engngModel->giveProblemScale() == macroScale ) { + // k.writeToFile("k.txt"); + // } linSolver->solve(k, rhs, ddX); } @@ -326,16 +327,16 @@ NRSolver :: solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, double maxInc = 0.0; for ( double inc : ddX ) { - if(fabs(inc) > maxInc) { + if ( fabs(inc) > maxInc ) { maxInc = fabs(inc); } } - if(maxInc > maxIncAllowed) { + if ( maxInc > maxIncAllowed ) { if ( engngModel->giveProblemScale() == macroScale ) { - printf("Restricting increment. maxInc: %e\n", maxInc); + printf("Restricting increment. maxInc: %e\n", maxInc); } - ddX.times(maxIncAllowed/maxInc); + ddX.times(maxIncAllowed / maxInc); } ///////////////////////////////////////// @@ -343,6 +344,17 @@ NRSolver :: solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, X.add(ddX); dX.add(ddX); + + if ( solutionDependentExternalForcesFlag ) { + engngModel->updateComponent(tStep, ExternalRhs, domain); + RT = R; + if ( R0 ) { + RT.add(* R0); + } + } + + + tStep->incrementStateCounter(); // update solution state counter tStep->incrementSubStepNumber(); @@ -392,12 +404,10 @@ NRSolver :: giveLinearSolver() if ( linSolver ) { if ( linSolver->giveLinSystSolverType() == solverType ) { return linSolver.get(); - } else { - linSolver.reset(NULL); } } - linSolver.reset( classFactory.createSparseLinSolver(solverType, domain, engngModel) ); + linSolver = classFactory.createSparseLinSolver(solverType, domain, engngModel); if ( !linSolver ) { OOFEM_ERROR("linear solver creation failed for lstype %d", solverType); } @@ -410,7 +420,7 @@ LineSearchNM * NRSolver :: giveLineSearchSolver() { if ( !linesearchSolver ) { - linesearchSolver.reset( new LineSearchNM(domain, engngModel) ); + linesearchSolver = std :: make_unique< LineSearchNM >(domain, engngModel); } return linesearchSolver.get(); @@ -458,7 +468,7 @@ NRSolver :: applyConstraintsToStiffness(SparseMtrx &k) } #ifdef __PETSC_MODULE - PetscSparseMtrx *lhs = dynamic_cast< PetscSparseMtrx * >(&k); + PetscSparseMtrx *lhs = dynamic_cast< PetscSparseMtrx * >(& k); if ( lhs ) { Vec diag; PetscScalar *ptr; @@ -503,7 +513,7 @@ NRSolver :: applyConstraintsToLoadIncrement(int nite, const SparseMtrx &k, Float //factor -= engngModel->giveDomain(1)->giveFunction(prescribedDisplacementTF)-> // at(tStep->givePreviousStep()->giveTime()) ; factor -= engngModel->giveDomain(1)->giveFunction(prescribedDisplacementTF)-> - evaluateAtTime( tStep->giveTargetTime() - tStep->giveTimeIncrement() ); + evaluateAtTime( tStep->giveTargetTime() - tStep->giveTimeIncrement() ); } if ( nite == 0 ) { @@ -523,7 +533,7 @@ NRSolver :: applyConstraintsToLoadIncrement(int nite, const SparseMtrx &k, Float #endif #else #ifdef __PETSC_MODULE - const PetscSparseMtrx *lhs = dynamic_cast< const PetscSparseMtrx * >(&k); + const PetscSparseMtrx *lhs = dynamic_cast< const PetscSparseMtrx * >(& k); if ( lhs ) { Vec diag; PetscScalar *ptr; @@ -600,7 +610,7 @@ NRSolver :: checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, Fl answer = true; errorOutOfRange = false; - // Store the errors associated with the dof groups + // Store the errors associated with the dof groups if ( this->constrainedNRFlag ) { this->forceErrVecOld = this->forceErrVec; // copy the old values this->forceErrVec.resize( internalForcesEBENorm.giveSize() ); @@ -623,12 +633,12 @@ NRSolver :: checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, Fl dg_totalDisp.zero(); // loop over dof managers for ( auto &dofman : domain->giveDofManagers() ) { - if ( !parallel_context->isLocal(dofman.get()) ) { + if ( !parallel_context->isLocal( dofman.get() ) ) { continue; } // loop over individual dofs - for ( Dof *dof: *dofman ) { + for ( Dof *dof : *dofman ) { if ( !dof->isPrimaryDof() ) { continue; } @@ -656,7 +666,7 @@ NRSolver :: checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, Fl for ( int idofman = 1; idofman <= elem->giveNumberOfInternalDofManagers(); idofman++ ) { DofManager *dofman = elem->giveInternalDofManager(idofman); // loop over individual dofs - for ( Dof *dof: *dofman ) { + for ( Dof *dof : *dofman ) { if ( !dof->isPrimaryDof() ) { continue; } @@ -682,7 +692,7 @@ NRSolver :: checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, Fl for ( int idofman = 1; idofman <= bc->giveNumberOfInternalDofManagers(); idofman++ ) { DofManager *dofman = bc->giveInternalDofManager(idofman); // loop over individual dofs - for ( Dof *dof: *dofman ) { + for ( Dof *dof : *dofman ) { if ( !dof->isPrimaryDof() ) { continue; } @@ -723,16 +733,15 @@ NRSolver :: checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, Fl //bool zeroNorm = false; // loop over dof groups and check convergence individually for ( int dg = 1; dg <= nccdg; dg++ ) { - bool zeroFNorm = false, zeroDNorm = false; // Skips the ones which aren't used in this problem (the residual will be zero for these anyway, but it is annoying to print them all) if ( !idsInUse.at(dg) ) { continue; } - numPrintouts++; + numPrintouts++; - if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts) { + if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts ) { OOFEM_LOG_INFO( " %s:", __DofIDItemToString( ( DofIDItem ) dg ).c_str() ); } @@ -740,7 +749,7 @@ NRSolver :: checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, Fl // compute a relative error norm if ( dg_forceScale.find(dg) != dg_forceScale.end() ) { forceErr = sqrt( dg_forceErr.at(dg) / ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) + - idsInUse.at(dg)*dg_forceScale[dg]*dg_forceScale[dg] ) ); + idsInUse.at(dg) * dg_forceScale [ dg ] * dg_forceScale [ dg ] ) ); } else if ( ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) ) >= nrsolver_ERROR_NORM_SMALL_NUM ) { forceErr = sqrt( dg_forceErr.at(dg) / ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) ) ); } else { @@ -756,8 +765,13 @@ NRSolver :: checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, Fl if ( forceErr > rtolf.at(1) ) { answer = false; } + if ( (forceErr > 0.0) && (nite == 0)) { + // if forceError > 0 and first iteration we report no convergence to actually + // apply the loading + answer = false; + } - if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts) { + if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts ) { OOFEM_LOG_INFO(zeroFNorm ? " *%.3e" : " %.3e", forceErr); } @@ -784,7 +798,7 @@ NRSolver :: checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, Fl answer = false; } - if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts) { + if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts ) { OOFEM_LOG_INFO(zeroDNorm ? " *%.3e" : " %.3e", dispErr); } } @@ -802,7 +816,7 @@ NRSolver :: checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, Fl if ( engngModel->giveProblemScale() == macroScale ) { OOFEM_LOG_INFO("NRSolver: %-15d", nite); } else { -// OOFEM_LOG_INFO(" NRSolver: %-15d", nite); + // OOFEM_LOG_INFO(" NRSolver: %-15d", nite); } diff --git a/src/oofemlib/nrsolver.h b/src/oofemlib/nrsolver.h index 0c8ba79f0..3d38a0206 100644 --- a/src/oofemlib/nrsolver.h +++ b/src/oofemlib/nrsolver.h @@ -69,6 +69,7 @@ #define _IFT_NRSolver_maxinc "maxinc" #define _IFT_NRSolver_forceScale "forcescale" #define _IFT_NRSolver_forceScaleDofs "forcescaledofs" +#define _IFT_NRSolver_solutionDependentExternalForces "soldepextforces" //@} namespace oofem { @@ -104,7 +105,7 @@ class OOFEM_EXPORT NRSolver : public SparseNonLinearSystemNM int MANRMSteps; /// linear system solver - std :: unique_ptr< SparseLinearSystemNM > linSolver; + std :: unique_ptr< SparseLinearSystemNM >linSolver; /// linear system solver ID LinSystSolverType solverType; /// sparse matrix version, used to control constrains application to stiffness @@ -134,7 +135,7 @@ class OOFEM_EXPORT NRSolver : public SparseNonLinearSystemNM /// Flag indicating whether to use line-search bool lsFlag; /// Line search solver - std :: unique_ptr< LineSearchNM > linesearchSolver; + std :: unique_ptr< LineSearchNM >linesearchSolver; /// Flag indicating if the stiffness should be evaluated before the residual in the first iteration. bool mCalcStiffBeforeRes; /// Flag indicating whether to use constrained Newton @@ -153,26 +154,31 @@ class OOFEM_EXPORT NRSolver : public SparseNonLinearSystemNM FloatArray forceErrVec; FloatArray forceErrVecOld; + /// Solution dependent external forces - updating then each NR iteration + bool solutionDependentExternalForcesFlag; + + + /// Optional user supplied scale of forces used in convergence check. - std :: map dg_forceScale; + std :: map< int, double >dg_forceScale; double maxIncAllowed; public: - NRSolver(Domain * d, EngngModel * m); + NRSolver(Domain *d, EngngModel *m); virtual ~NRSolver(); // Overloaded methods: - virtual NM_Status solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, - FloatArray &X, FloatArray &dX, FloatArray &F, - const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm, - int &nite, TimeStep *); - virtual void printState(FILE *outputStream); - - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "NRSolver"; } + NM_Status solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, + FloatArray &X, FloatArray &dX, FloatArray &F, + const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm, + int &nite, TimeStep *) override; + void printState(FILE *outputStream) override; + + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "NRSolver"; } virtual const char *giveInputRecordName() const { return _IFT_NRSolver_Name; } - virtual void setDomain(Domain *d) { + void setDomain(Domain *d) override { this->domain = d; if ( linSolver ) { linSolver->setDomain(d); @@ -181,13 +187,13 @@ class OOFEM_EXPORT NRSolver : public SparseNonLinearSystemNM linesearchSolver->setDomain(d); } } - virtual void reinitialize() { + void reinitialize() override { if ( linSolver ) { linSolver->reinitialize(); } } - virtual SparseLinearSystemNM *giveLinearSolver(); + SparseLinearSystemNM *giveLinearSolver() override; protected: /// Constructs and returns a line search solver. diff --git a/src/oofemlib/numericalcmpn.h b/src/oofemlib/numericalcmpn.h index bf46f511f..1130eaf31 100644 --- a/src/oofemlib/numericalcmpn.h +++ b/src/oofemlib/numericalcmpn.h @@ -46,6 +46,7 @@ namespace oofem { enum NumericalCmpn { InternalRhs, NonLinearLhs, + ExternalRhs, }; } // end namespace oofem #endif // numericalcmpn_h diff --git a/src/oofemlib/nummet.h b/src/oofemlib/nummet.h index d1e1ec00b..93e28c9a4 100644 --- a/src/oofemlib/nummet.h +++ b/src/oofemlib/nummet.h @@ -98,7 +98,7 @@ class OOFEM_EXPORT NumericalMethod /// @return Engineering model receiver is connected to. EngngModel *giveEngngModel() { return engngModel; } - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + virtual void initializeFrom(InputRecord &ir) { } /** * Reinitializes the receiver. This is used, when topology of problem has changed @@ -113,8 +113,8 @@ class OOFEM_EXPORT NumericalMethod virtual void setDomain(Domain *d) { domain = d; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL) { return CIO_OK; } - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL) { return CIO_OK; } + virtual void saveContext(DataStream &stream, ContextMode mode) { } + virtual void restoreContext(DataStream &stream, ContextMode mode) { } }; } // end namespace oofem #endif // nummet_h diff --git a/src/oofemlib/octreelocalizer.C b/src/oofemlib/octreelocalizer.C index 214aa08c8..522e41fbd 100644 --- a/src/oofemlib/octreelocalizer.C +++ b/src/oofemlib/octreelocalizer.C @@ -48,36 +48,12 @@ #include namespace oofem { -OctantRec :: OctantRec(OctreeSpatialLocalizer *loc, OctantRec *parent, FloatArray &origin, double halfWidth) : - localizer(loc), +OctantRec :: OctantRec(OctantRec *parent, FloatArray origin, double halfWidth) : parent(parent), - origin(origin), + origin(std::move(origin)), halfWidth(halfWidth) { this->depth = parent ? parent->giveCellDepth() + 1 : 0; - - for ( int i = 0; i <= 1; i++ ) { - for ( int j = 0; j <= 1; j++ ) { - for ( int k = 0; k <= 1; k++ ) { - this->child [ i ] [ j ] [ k ] = NULL; - } - } - } -} - -OctantRec :: ~OctantRec() -{ - // destructor - delete all receivers children recursively - // delete children first, then itself - for ( int i = 0; i <= 1; i++ ) { - for ( int j = 0; j <= 1; j++ ) { - for ( int k = 0; k <= 1; k++ ) { - if ( this->child [ i ] [ j ] [ k ] ) { - delete this->child [ i ] [ j ] [ k ]; - } - } - } - } } std :: list< int > & @@ -106,30 +82,31 @@ OctantRec * OctantRec :: giveChild(int xi, int yi, int zi) { if ( ( xi >= 0 ) && ( xi < 2 ) && ( yi >= 0 ) && ( yi < 2 ) && ( zi >= 0 ) && ( zi < 2 ) ) { - return this->child [ xi ] [ yi ] [ zi ]; + return this->child [ xi ] [ yi ] [ zi ].get(); + ///@todo We could inline the entire block if we do: std::unique_ptr child; + //return &(*child) [ xi ] [ yi ] [ zi ]; } else { OOFEM_ERROR("invalid child index (%d,%d,%d)", xi, yi, zi); } - return NULL; + return nullptr; } OctantRec :: ChildStatus -OctantRec :: giveChildContainingPoint(OctantRec **child, const FloatArray &coords) +OctantRec :: giveChildContainingPoint(OctantRec *&child, const FloatArray &coords, const IntArray &mask) { - IntArray ind(3); - if ( this->isTerminalOctant() ) { - * child = NULL; + child = nullptr; return CS_NoChild; } - for ( int i = 1; i <= coords.giveSize(); ++i ) { - ind.at(i) = localizer->giveOctreeMaskValue(i) && coords.at(i) > this->origin.at(i); + IntArray ind(3); + for ( int i = 0; i < coords.giveSize(); ++i ) { + ind[i] = mask[i] && coords[i] > this->origin[i]; } - * child = this->child [ ind.at(1) ] [ ind.at(2) ] [ ind.at(3) ]; + child = this->child [ ind[0] ] [ ind[1] ] [ ind[2] ].get(); return CS_ChildFound; } @@ -139,28 +116,24 @@ OctantRec :: isTerminalOctant() { // This implementation is relying on fact, that child [0][0][0] // is created even for all degenerated trees - if ( this->child [ 0 ] [ 0 ] [ 0 ] ) { - return false; - } - - return true; + return ! this->child [ 0 ] [ 0 ] [ 0 ]; } void -OctantRec :: divideLocally(int level, const IntArray &octantMask) +OctantRec :: divideLocally(int level, const IntArray &mask) { if ( this->isTerminalOctant() ) { // create corresponding child octants - FloatArray childOrigin(3); - - for ( int i = 0; i <= octantMask.at(1); i++ ) { - for ( int j = 0; j <= octantMask.at(2); j++ ) { - for ( int k = 0; k <= octantMask.at(3); k++ ) { - childOrigin.at(1) = this->origin.at(1) + ( i - 0.5 ) * this->halfWidth * octantMask.at(1); - childOrigin.at(2) = this->origin.at(2) + ( j - 0.5 ) * this->halfWidth * octantMask.at(2); - childOrigin.at(3) = this->origin.at(3) + ( k - 0.5 ) * this->halfWidth * octantMask.at(3); - this->child [ i ] [ j ] [ k ] = new OctantRec(localizer, this, childOrigin, this->halfWidth * 0.5); + for ( int i = 0; i <= mask.at(1); i++ ) { + for ( int j = 0; j <= mask.at(2); j++ ) { + for ( int k = 0; k <= mask.at(3); k++ ) { + FloatArray childOrigin = { + this->origin.at(1) + ( i - 0.5 ) * this->halfWidth * mask.at(1), + this->origin.at(2) + ( j - 0.5 ) * this->halfWidth * mask.at(2), + this->origin.at(3) + ( k - 0.5 ) * this->halfWidth * mask.at(3) + }; + this->child [ i ] [ j ] [ k ] = std::make_unique(this, std::move(childOrigin), this->halfWidth * 0.5); } } } @@ -169,11 +142,11 @@ OctantRec :: divideLocally(int level, const IntArray &octantMask) int newLevel = level - 1; if ( newLevel > 0 ) { // propagate message to children recursively with level param decreased - for ( int i = 0; i <= octantMask.at(1); i++ ) { - for ( int j = 0; j <= octantMask.at(2); j++ ) { - for ( int k = 0; k <= octantMask.at(3); k++ ) { + for ( int i = 0; i <= mask.at(1); i++ ) { + for ( int j = 0; j <= mask.at(2); j++ ) { + for ( int k = 0; k <= mask.at(3); k++ ) { if ( this->child [ i ] [ j ] [ k ] ) { - this->child [ i ] [ j ] [ k ]->divideLocally(newLevel, octantMask); + this->child [ i ] [ j ] [ k ]->divideLocally(newLevel, mask); } } } @@ -183,19 +156,16 @@ OctantRec :: divideLocally(int level, const IntArray &octantMask) OctantRec :: BoundingBoxStatus -OctantRec :: testBoundingBox(const FloatArray &coords, double radius) +OctantRec :: testBoundingBox(const FloatArray &coords, double radius, const IntArray &mask) { - int size = coords.giveSize(); - double bb0, bb1; - double oct0, oct1; bool bbInside = true; - for ( int i = 1; i <= size; i++ ) { - if ( localizer->giveOctreeMaskValue(i) ) { - bb0 = coords.at(i) - radius; - bb1 = coords.at(i) + radius; - oct0 = this->origin.at(i) - this->halfWidth; - oct1 = this->origin.at(i) + this->halfWidth; + for ( int i = 1; i <= coords.giveSize(); i++ ) { + if ( mask.at(i) ) { + double bb0 = coords.at(i) - radius; + double bb1 = coords.at(i) + radius; + double oct0 = this->origin.at(i) - this->halfWidth; + double oct1 = this->origin.at(i) + this->halfWidth; if ( oct1 < bb0 || oct0 > bb1 ) { // Then its definitely outside, no need to go on return BBS_OutsideCell; @@ -235,30 +205,27 @@ void OctantRec :: printYourself() } - - -OctreeSpatialLocalizer :: OctreeSpatialLocalizer(Domain* d) : SpatialLocalizer(d), octreeMask(3) -{ - rootCell = NULL; - elementIPListsInitialized = false; - elementListsInitialized.clear(); -} - - -OctreeSpatialLocalizer :: ~OctreeSpatialLocalizer() +OctreeSpatialLocalizer :: OctreeSpatialLocalizer(Domain* d) : SpatialLocalizer(d), + octreeMask(3), + elementIPListsInitialized(false) { - delete rootCell; + this->initialized = false; + this->rootCell=nullptr; +#ifdef _OPENMP + omp_init_lock(&ElementIPDataStructureLock); + omp_init_lock(&buildOctreeDataStructureLock); + omp_init_lock(&initLock); +#endif } OctantRec * -OctreeSpatialLocalizer :: findTerminalContaining(OctantRec *startCell, const FloatArray &coords) +OctreeSpatialLocalizer :: findTerminalContaining(OctantRec &startCell, const FloatArray &coords) { - OctantRec :: ChildStatus result; - OctantRec *currCell = startCell; + OctantRec *currCell = &startCell; // found terminal octant containing node while ( !currCell->isTerminalOctant() ) { - result = currCell->giveChildContainingPoint(& currCell, coords); + auto result = currCell->giveChildContainingPoint(currCell, coords, octreeMask); if ( result == OctantRec :: CS_NoChild ) { OOFEM_ERROR("internal error - octree inconsistency"); } @@ -273,14 +240,19 @@ OctreeSpatialLocalizer :: buildOctreeDataStructure() // OOFEM_LOG_INFO("Initializing Octree structure\n"); int init = 1, nnode = this->domain->giveNumberOfDofManagers(); double rootSize, resolutionLimit; - FloatArray minc(3), maxc(3), * coords; - DofManager *dman; - Node *node; + FloatArray minc(3), maxc(3); // test if tree already built if ( rootCell ) { return true; } +#ifdef _OPENMP + omp_set_lock(&buildOctreeDataStructureLock); // if not initialized yet; one thread can proceed with init; others have to wait until init completed + if ( rootCell ) { + omp_unset_lock(&buildOctreeDataStructureLock); + return true; + } +#endif this->elementListsInitialized.resize(this->domain->giveNumberOfRegions() + 1); this->elementListsInitialized.zero(); @@ -292,23 +264,22 @@ OctreeSpatialLocalizer :: buildOctreeDataStructure() // first determine domain extends (bounding box), and check for degenerated domain type for ( int i = 1; i <= nnode; i++ ) { - dman = domain->giveDofManager(i); - node = dynamic_cast< Node * >(dman); + Node *node = domain->giveNode(i); if ( node ) { - coords = node->giveCoordinates(); + const auto &coords = node->giveCoordinates(); if ( init ) { init = 0; - for ( int j = 1; j <= coords->giveSize(); j++ ) { - minc.at(j) = maxc.at(j) = coords->at(j); + for ( int j = 1; j <= coords.giveSize(); j++ ) { + minc.at(j) = maxc.at(j) = coords.at(j); } } else { - for ( int j = 1; j <= coords->giveSize(); j++ ) { - if ( coords->at(j) < minc.at(j) ) { - minc.at(j) = coords->at(j); + for ( int j = 1; j <= coords.giveSize(); j++ ) { + if ( coords.at(j) < minc.at(j) ) { + minc.at(j) = coords.at(j); } - if ( coords->at(j) > maxc.at(j) ) { - maxc.at(j) = coords->at(j); + if ( coords.at(j) > maxc.at(j) ) { + maxc.at(j) = coords.at(j); } } } @@ -318,7 +289,7 @@ OctreeSpatialLocalizer :: buildOctreeDataStructure() // determine root size rootSize = 0.0; for ( int i = 1; i <= 3; i++ ) { - rootSize = 1.000001 * max( rootSize, maxc.at(i) - minc.at(i) ); + rootSize = max( rootSize, 1.000001 * (maxc.at(i) - minc.at(i)) ); } // check for degenerated domain @@ -335,7 +306,7 @@ OctreeSpatialLocalizer :: buildOctreeDataStructure() FloatArray center = minc; center.add(maxc); center.times(0.5); - this->rootCell = new OctantRec(this, NULL, center, rootSize * 0.5); + this->rootCell = std::make_unique(nullptr, center, rootSize * 0.5); // Build octree tree if ( nnode > OCTREE_MAX_NODES_LIMIT ) { @@ -344,21 +315,21 @@ OctreeSpatialLocalizer :: buildOctreeDataStructure() // insert domain nodes into tree for ( int i = 1; i <= nnode; i++ ) { - dman = domain->giveDofManager(i); - node = dynamic_cast< Node * >(dman); + Node *node = domain->giveNode(i); if ( node ) { - coords = node->giveCoordinates(); - this->insertNodeIntoOctree(this->rootCell, i, * coords); + const auto &coords = node->giveCoordinates(); + this->insertNodeIntoOctree(*this->rootCell, i, coords); } } timer.stopTimer(); // compute max. tree depth - int treeDepth = 0; - this->giveMaxTreeDepthFrom(this->rootCell, treeDepth); + int treeDepth = this->giveMaxTreeDepthFrom(*this->rootCell); OOFEM_LOG_DEBUG( "Octree init [depth %d in %.2fs]\n", treeDepth, timer.getUtime() ); - +#ifdef _OPENMP + omp_unset_lock(&buildOctreeDataStructureLock); +#endif return true; } @@ -370,11 +341,16 @@ OctreeSpatialLocalizer :: initElementIPDataStructure() // int nelems = this->domain->giveNumberOfElements(); FloatArray jGpCoords; - if ( this->elementIPListsInitialized ) { return; } - +#ifdef _OPENMP + omp_set_lock(&ElementIPDataStructureLock); // if not initialized yet; one thread can proceed with init; others have to wait until init completed + if ( this->elementIPListsInitialized ) { + omp_unset_lock(&ElementIPDataStructureLock); + return; + } +#endif // insert IP records into tree (the tree topology is determined by nodes) for ( int i = 1; i <= nelems; i++ ) { // only default IP are taken into account @@ -382,7 +358,7 @@ OctreeSpatialLocalizer :: initElementIPDataStructure() if ( ielem->giveNumberOfIntegrationRules() > 0 ) { for ( GaussPoint *jGp: *ielem->giveDefaultIntegrationRulePtr() ) { if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) { - this->insertIPElementIntoOctree(this->rootCell, i, jGpCoords); + this->insertIPElementIntoOctree(*this->rootCell, i, jGpCoords); } else { OOFEM_ERROR("computeGlobalCoordinates failed"); } @@ -392,8 +368,8 @@ OctreeSpatialLocalizer :: initElementIPDataStructure() // but the element should be present in octree data structure // this is needed by some services (giveElementContainingPoint, for example) for ( int j = 1; j <= ielem->giveNumberOfNodes(); j++ ) { - FloatArray *nc = ielem->giveNode(j)->giveCoordinates(); - this->insertIPElementIntoOctree(this->rootCell, i, * nc); + const auto &nc = ielem->giveNode(j)->giveCoordinates(); + this->insertIPElementIntoOctree(*this->rootCell, i, nc); } } @@ -411,15 +387,18 @@ OctreeSpatialLocalizer :: initElementIPDataStructure() //this->insertElementsUsingNodalConnectivitiesIntoOctree (this->rootCell); this->elementIPListsInitialized = true; +#ifdef _OPENMP + omp_unset_lock(&ElementIPDataStructureLock); +#endif + } void -OctreeSpatialLocalizer :: insertIPElementIntoOctree(OctantRec *rootCell, int elemNum, const FloatArray &coords) +OctreeSpatialLocalizer :: insertIPElementIntoOctree(OctantRec &rootCell, int elemNum, const FloatArray &coords) { - OctantRec *currCell; // found terminal octant containing IP - currCell = this->findTerminalContaining(rootCell, coords); + OctantRec *currCell = this->findTerminalContaining(rootCell, coords); currCell->addElementIP(elemNum); } @@ -430,7 +409,7 @@ OctreeSpatialLocalizer :: initElementDataStructure(int region) FloatArray b0, b1; this->init(); - if ( this->elementListsInitialized.giveSize() >= region + 1 && this->elementListsInitialized(region) ) { + if ( this->elementListsInitialized.giveSize() >= region + 1 && this->elementListsInitialized[region] ) { return; } @@ -440,16 +419,16 @@ OctreeSpatialLocalizer :: initElementDataStructure(int region) SpatialLocalizerInterface *interface = static_cast< SpatialLocalizerInterface * >( ielem->giveInterface(SpatialLocalizerInterfaceType) ); if ( interface ) { interface->SpatialLocalizerI_giveBBox(b0, b1); - this->insertElementIntoOctree(this->rootCell, region, i, b0, b1); + this->insertElementIntoOctree(*this->rootCell, region, i, b0, b1); } } } - this->elementListsInitialized(region) = true; + this->elementListsInitialized[region] = true; } void -OctreeSpatialLocalizer :: insertElementIntoOctree(OctantRec *rootCell, int region, int elemNum, const FloatArray &b0, const FloatArray &b1) +OctreeSpatialLocalizer :: insertElementIntoOctree(OctantRec &rootCell, int region, int elemNum, const FloatArray &b0, const FloatArray &b1) { // Compare the bounding box corners to the center to determine which region is overlaps // Checks: b0 <= center, b1 >= center for each entry. @@ -457,7 +436,7 @@ OctreeSpatialLocalizer :: insertElementIntoOctree(OctantRec *rootCell, int regio IntArray bbc [ 2 ] = { IntArray(3), IntArray(3) }; - FloatArray origin = rootCell->giveOrigin(); + FloatArray origin = rootCell.giveOrigin(); for ( int i = 1; i <= b0.giveSize(); i++ ) { if ( this->octreeMask.at(i) ) { bbc [ 0 ].at(i) = b0.at(i) <= origin.at(i); @@ -470,8 +449,8 @@ OctreeSpatialLocalizer :: insertElementIntoOctree(OctantRec *rootCell, int regio bbc [ 0 ].at(i) = bbc [ 1 ].at(i) = true; } // Check terminal or recurse - if ( rootCell->isTerminalOctant() ) { - rootCell->addElement(region, elemNum); + if ( rootCell.isTerminalOctant() ) { + rootCell.addElement(region, elemNum); } else { // The for loops below check if the bounding box overlaps the region before or after the cell center // e.g. when i = 0, then we check for the children that have x-coordinate <= than root center @@ -480,8 +459,8 @@ OctreeSpatialLocalizer :: insertElementIntoOctree(OctantRec *rootCell, int regio for ( int j = 0; j <= octreeMask.at(2); j++ ) { if ( bbc [ j ].at(2) ) { for ( int k = 0; k <= octreeMask.at(3); k++ ) { - if ( bbc [ k ].at(3) && rootCell->giveChild(i, j, k) ) { - this->insertElementIntoOctree(rootCell->giveChild(i, j, k), region, elemNum, b0, b1); + if ( bbc [ k ].at(3) && rootCell.giveChild(i, j, k) ) { + this->insertElementIntoOctree(*rootCell.giveChild(i, j, k), region, elemNum, b0, b1); } } } @@ -493,15 +472,15 @@ OctreeSpatialLocalizer :: insertElementIntoOctree(OctantRec *rootCell, int regio void -OctreeSpatialLocalizer :: insertElementsUsingNodalConnectivitiesIntoOctree(OctantRec *currCell) +OctreeSpatialLocalizer :: insertElementsUsingNodalConnectivitiesIntoOctree(OctantRec &currCell) { - if ( currCell->isTerminalOctant() ) { - for ( int inod: currCell->giveNodeList() ) { + if ( currCell.isTerminalOctant() ) { + for ( int inod: currCell.giveNodeList() ) { // loop over cell nodes and ask connectivity table for shared elements const IntArray *dofmanConnectivity = domain->giveConnectivityTable()->giveDofManConnectivityArray(inod); if ( dofmanConnectivity ) { for ( int d: *dofmanConnectivity ) { - currCell->addElementIP( d ); + currCell.addElementIP( d ); } } } @@ -509,8 +488,9 @@ OctreeSpatialLocalizer :: insertElementsUsingNodalConnectivitiesIntoOctree(Octan for ( int i = 0; i <= octreeMask.at(1); i++ ) { for ( int j = 0; j <= octreeMask.at(2); j++ ) { for ( int k = 0; k <= octreeMask.at(3); k++ ) { - if ( currCell->giveChild(i, j, k) ) { - this->insertElementsUsingNodalConnectivitiesIntoOctree( currCell->giveChild(i, j, k) ); + auto child = currCell.giveChild(i, j, k); + if ( child ) { + this->insertElementsUsingNodalConnectivitiesIntoOctree(*child); } } } @@ -520,29 +500,25 @@ OctreeSpatialLocalizer :: insertElementsUsingNodalConnectivitiesIntoOctree(Octan void -OctreeSpatialLocalizer :: insertNodeIntoOctree(OctantRec *rootCell, int nodeNum, const FloatArray &coords) +OctreeSpatialLocalizer :: insertNodeIntoOctree(OctantRec &rootCell, int nodeNum, const FloatArray &coords) { - int nCellItems, cellDepth; - OctantRec :: ChildStatus result; - OctantRec *currCell; - // found terminal octant containing node - currCell = this->findTerminalContaining(rootCell, coords); + OctantRec *currCell = this->findTerminalContaining(rootCell, coords); // request cell node list nodeContainerType &cellNodeList = currCell->giveNodeList(); - nCellItems = cellNodeList.size(); - cellDepth = currCell->giveCellDepth(); + int nCellItems = cellNodeList.size(); + int cellDepth = currCell->giveCellDepth(); // check for refinement criteria // should also include max refinement level criteria // - if ( ( nCellItems > OCTREE_MAX_NODES_LIMIT ) && ( cellDepth <= OCTREE_MAX_DEPTH ) ) { + if ( nCellItems > OCTREE_MAX_NODES_LIMIT && cellDepth <= OCTREE_MAX_DEPTH ) { // refine tree one level currCell->divideLocally(1, this->octreeMask); // propagate all nodes already assigned to currCell to children for ( int inod: cellNodeList ) { Node *node = domain->giveNode(inod); - FloatArray *nodeCoords = node->giveCoordinates(); - this->insertNodeIntoOctree(currCell, inod, * nodeCoords); + const auto &nodeCoords = node->giveCoordinates(); + this->insertNodeIntoOctree(*currCell, inod, nodeCoords); } // remove node list at relative root cell @@ -558,11 +534,11 @@ OctreeSpatialLocalizer :: insertNodeIntoOctree(OctantRec *rootCell, int nodeNum, // Please note, that the next insertion in particular cell cause the refinement. // find child containing new node - result = currCell->giveChildContainingPoint(& currCell, coords); + auto result = currCell->giveChildContainingPoint(currCell, coords, this->octreeMask); if ( result != OctantRec :: CS_ChildFound ) { OOFEM_ERROR("internal error - octree inconsistency"); } - this->insertNodeIntoOctree(currCell, nodeNum, coords); + this->insertNodeIntoOctree(*currCell, nodeNum, coords); } else { currCell->addNode(nodeNum); } @@ -572,17 +548,16 @@ OctreeSpatialLocalizer :: insertNodeIntoOctree(OctantRec *rootCell, int nodeNum, Element * OctreeSpatialLocalizer :: giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList) { - OctantRec *currCell, *childCell = NULL; + OctantRec *currCell, *childCell = nullptr; this->init(); this->initElementIPDataStructure(); // found terminal octant containing point - currCell = this->findTerminalContaining(rootCell, coords); + currCell = this->findTerminalContaining(*rootCell, coords); - while ( currCell != NULL ) { - // loop over all elements in currCell, skip search on child cell already scanned - Element *answer = this->giveElementContainingPoint(currCell, coords, childCell, regionList); + while ( currCell ) { + Element *answer = this->giveElementContainingPoint(*currCell, coords, childCell, regionList); if ( answer ) { return answer; } @@ -594,23 +569,23 @@ OctreeSpatialLocalizer :: giveElementContainingPoint(const FloatArray &coords, c } // there isn't any element containing point. - return NULL; + return nullptr; } Element * OctreeSpatialLocalizer :: giveElementContainingPoint(const FloatArray &coords, const Set &eset) { - OctantRec *currCell, *childCell = NULL; + OctantRec *currCell, *childCell = nullptr; this->init(); this->initElementIPDataStructure(); // found terminal octant containing point - currCell = this->findTerminalContaining(rootCell, coords); + currCell = this->findTerminalContaining(*rootCell, coords); - while ( currCell != NULL ) { + while ( currCell ) { // loop over all elements in currCell, skip search on child cell already scanned - Element *answer = this->giveElementContainingPoint(currCell, coords, childCell, & eset); + Element *answer = this->giveElementContainingPoint(*currCell, coords, childCell, & eset); if ( answer ) { return answer; } @@ -622,23 +597,20 @@ OctreeSpatialLocalizer :: giveElementContainingPoint(const FloatArray &coords, c } // there isn't any element containing point. - return NULL; + return nullptr; } Element * -OctreeSpatialLocalizer :: giveElementContainingPoint(OctantRec *cell, const FloatArray &coords, +OctreeSpatialLocalizer :: giveElementContainingPoint(OctantRec &cell, const FloatArray &coords, OctantRec *scannedChild, const IntArray *regionList) { - elementContainerType &elementList = cell->giveIPElementList(); - // recursive implementation - if ( cell->isTerminalOctant() && ( !elementList.isEmpty() ) ) { + if ( cell.isTerminalOctant() ) { - for ( int iel: elementList ) { + for ( int iel: cell.giveIPElementList() ) { Element *ielemptr = this->giveDomain()->giveElement(iel); - /* HUHU CHEATING */ if ( ielemptr->giveParallelMode() == Element_remote ) { continue; } @@ -659,19 +631,19 @@ OctreeSpatialLocalizer :: giveElementContainingPoint(OctantRec *cell, const Floa } } - return NULL; + return nullptr; } else { - Element *answer; // receiver is not terminal octant -> call same service on childs for ( int i = 0; i <= octreeMask.at(1); i++ ) { for ( int j = 0; j <= octreeMask.at(2); j++ ) { for ( int k = 0; k <= octreeMask.at(3); k++ ) { - if ( cell->giveChild(i, j, k) ) { - if ( scannedChild == cell->giveChild(i, j, k) ) { + auto child = cell.giveChild(i, j, k); + if ( child ) { + if ( scannedChild == child ) { continue; } - answer = this->giveElementContainingPoint(cell->giveChild(i, j, k), coords, NULL, regionList); + Element *answer = this->giveElementContainingPoint(*child, coords, nullptr, regionList); if ( answer ) { return answer; } @@ -681,22 +653,19 @@ OctreeSpatialLocalizer :: giveElementContainingPoint(OctantRec *cell, const Floa } } - return NULL; + return nullptr; } Element * -OctreeSpatialLocalizer :: giveElementContainingPoint(OctantRec *cell, const FloatArray &coords, +OctreeSpatialLocalizer :: giveElementContainingPoint(OctantRec &cell, const FloatArray &coords, OctantRec *scannedChild, const Set *eset) { - elementContainerType &elementList = cell->giveIPElementList(); - // recursive implementation - if ( cell->isTerminalOctant() && ( !elementList.isEmpty() ) ) { + if ( cell.isTerminalOctant() ) { - for ( int iel: elementList ) { + for ( int iel: cell.giveIPElementList() ) { Element *ielemptr = this->giveDomain()->giveElement(iel); - /* HUHU CHEATING */ if ( ielemptr->giveParallelMode() == Element_remote ) { continue; } @@ -717,18 +686,19 @@ OctreeSpatialLocalizer :: giveElementContainingPoint(OctantRec *cell, const Floa } } - return NULL; + return nullptr; } else { // receiver is not terminal octant -> call same service on childs for ( int i = 0; i <= octreeMask.at(1); i++ ) { for ( int j = 0; j <= octreeMask.at(2); j++ ) { for ( int k = 0; k <= octreeMask.at(3); k++ ) { - if ( cell->giveChild(i, j, k) ) { - if ( scannedChild == cell->giveChild(i, j, k) ) { + auto child = cell.giveChild(i, j, k); + if ( child ) { + if ( scannedChild == child ) { continue; } - Element *answer = this->giveElementContainingPoint(cell->giveChild(i, j, k), coords, NULL, eset); + Element *answer = this->giveElementContainingPoint(*child, coords, nullptr, eset); if ( answer ) { return answer; } @@ -738,7 +708,7 @@ OctreeSpatialLocalizer :: giveElementContainingPoint(OctantRec *cell, const Floa } } - return NULL; + return nullptr; } @@ -746,29 +716,28 @@ Element * OctreeSpatialLocalizer :: giveElementClosestToPoint(FloatArray &lcoords, FloatArray &closest, const FloatArray &gcoords, int region) { - Element *answer = NULL; + Element *answer = nullptr; std :: list< OctantRec * >cellList; OctantRec *currCell; double radius, prevRadius; - FloatArray c = this->rootCell->giveOrigin(); + const FloatArray &c = this->rootCell->giveOrigin(); this->initElementDataStructure(region); // Maximum distance given coordinate and furthest terminal cell ( center_distance + width/2*sqrt(3) ) - double minDist = c.distance(gcoords) + this->rootCell->giveWidth() * 0.87; - + double minDist = distance(c, gcoords) + this->rootCell->giveWidth() * 0.87; // found terminal octant containing point - currCell = this->findTerminalContaining(rootCell, gcoords); + currCell = this->findTerminalContaining(*rootCell, gcoords); // Look in center, then expand. - this->giveElementClosestToPointWithinOctant(currCell, gcoords, minDist, lcoords, closest, answer, region); + this->giveElementClosestToPointWithinOctant(*currCell, gcoords, minDist, lcoords, closest, answer, region); prevRadius = 0.; radius = currCell->giveWidth(); while ( radius < minDist ) { - this->giveListOfTerminalCellsInBoundingBox(cellList, gcoords, radius, prevRadius, this->rootCell); + this->giveListOfTerminalCellsInBoundingBox(cellList, gcoords, radius, prevRadius, *this->rootCell); for ( OctantRec *icell: cellList ) { - this->giveElementClosestToPointWithinOctant(icell, gcoords, minDist, lcoords, closest, answer, region); + this->giveElementClosestToPointWithinOctant(*icell, gcoords, minDist, lcoords, closest, answer, region); } prevRadius = radius; radius *= 2.; // Keep expanding the scope until the radius is larger than the entire root cell, then give up (because we have checked every possible cell) @@ -778,36 +747,33 @@ OctreeSpatialLocalizer :: giveElementClosestToPoint(FloatArray &lcoords, FloatAr void -OctreeSpatialLocalizer :: giveElementClosestToPointWithinOctant(OctantRec *currCell, const FloatArray &gcoords, +OctreeSpatialLocalizer :: giveElementClosestToPointWithinOctant(OctantRec &currCell, const FloatArray &gcoords, double &minDist, FloatArray &lcoords, FloatArray &closest, Element * &answer, int region) { - double currDist; FloatArray currLcoords; FloatArray currClosest; - std :: list &elementList = currCell->giveElementList(region); - if ( !elementList.empty() ) { - for ( int iel: elementList ) { - Element *ielemptr = this->giveDomain()->giveElement(iel); + auto &elementList = currCell.giveElementList(region); + for ( int iel: elementList ) { + Element *ielemptr = this->giveDomain()->giveElement(iel); - if ( ielemptr->giveParallelMode() == Element_remote ) { - continue; - } + if ( ielemptr->giveParallelMode() == Element_remote ) { + continue; + } - SpatialLocalizerInterface *interface = static_cast< SpatialLocalizerInterface * >( ielemptr->giveInterface(SpatialLocalizerInterfaceType) ); - if ( region > 0 && ielemptr->giveRegionNumber() != region ) { - continue; - } - currDist = interface->SpatialLocalizerI_giveClosestPoint(currLcoords, currClosest, gcoords); - if ( currDist < minDist ) { - lcoords = currLcoords; - closest = currClosest; - answer = ielemptr; - minDist = currDist; - } + SpatialLocalizerInterface *interface = static_cast< SpatialLocalizerInterface * >( ielemptr->giveInterface(SpatialLocalizerInterfaceType) ); + if ( region > 0 && ielemptr->giveRegionNumber() != region ) { + continue; } - if ( minDist == 0.0 ) { - return; + double currDist = interface->SpatialLocalizerI_giveClosestPoint(currLcoords, currClosest, gcoords); + if ( currDist < minDist ) { + lcoords = currLcoords; + closest = currClosest; + answer = ielemptr; + minDist = currDist; + if ( minDist == 0.0 ) { + return; + } } } } @@ -816,10 +782,7 @@ OctreeSpatialLocalizer :: giveElementClosestToPointWithinOctant(OctantRec *currC GaussPoint * OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, int region, bool iCohesiveZoneGP) { - double minDist; - OctantRec *currCell; - GaussPoint *nearestGp = NULL; - OctantRec :: BoundingBoxStatus BBStatus; + GaussPoint *nearestGp = nullptr; FloatArray jGpCoords; this->init(); @@ -827,34 +790,32 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, int region, bo // list of already tested elements // elementContainerType visitedElems; - minDist = 1.1 * rootCell->giveWidth(); + double minDist = 1.1 * rootCell->giveWidth(); // found terminal octant containing point - currCell = this->findTerminalContaining(rootCell, coords); - elementContainerType &elementList = currCell->giveIPElementList(); + OctantRec *currCell = this->findTerminalContaining(*rootCell, coords); + auto &elementList = currCell->giveIPElementList(); // find nearest ip in this terminal cell for ( int iel: elementList ) { Element *ielem = domain->giveElement(iel); - /* HUHU CHEATING */ if ( ielem->giveParallelMode() == Element_remote ) { continue; } - //igp = ipContainer[i].giveGp(); - if ( ( region > 0 ) && ( region != ielem->giveRegionNumber() ) ) { + if ( region > 0 && region != ielem->giveRegionNumber() ) { continue; } if ( !iCohesiveZoneGP ) { // test if element already visited // if (!visitedElems.insert(*pos).second) continue; - for ( GaussPoint *jGp: *ielem->giveDefaultIntegrationRulePtr() ) { + for ( auto &jGp: *ielem->giveDefaultIntegrationRulePtr() ) { if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) { // compute distance - double dist = coords.distance(jGpCoords); + double dist = distance(coords, jGpCoords); if ( dist < minDist ) { - minDist = dist; + minDist = dist; nearestGp = jGp; } } else { @@ -866,18 +827,18 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, int region, bo // Check for cohesive zone Gauss points XfemElementInterface *xFemEl = dynamic_cast< XfemElementInterface * >(ielem); - if ( xFemEl != NULL ) { + if ( xFemEl ) { size_t numCZRules = xFemEl->mpCZIntegrationRules.size(); for ( size_t czRuleIndex = 0; czRuleIndex < numCZRules; czRuleIndex++ ) { std :: unique_ptr< IntegrationRule > &iRule = xFemEl->mpCZIntegrationRules [ czRuleIndex ]; if ( iRule ) { - for ( GaussPoint *jGp: *iRule ) { + for ( auto &jGp: *iRule ) { if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) { // compute distance - double dist = coords.distance(jGpCoords); + double dist = distance(coords, jGpCoords); //printf("czRuleIndex: %d j: %d dist: %e\n", czRuleIndex, j, dist); if ( dist < minDist ) { - minDist = dist; + minDist = dist; nearestGp = jGp; } } else { @@ -885,43 +846,42 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, int region, bo } } } else { - OOFEM_ERROR("iRule == NULL"); + OOFEM_ERROR("iRule is null"); } } } - //////////////////////////////// } } FloatArray bborigin = coords; // all cell element ip's scanned // construct bounding box and test its position within currCell - BBStatus = currCell->testBoundingBox(bborigin, minDist); + auto BBStatus = currCell->testBoundingBox(bborigin, minDist, this->octreeMask); if ( BBStatus == OctantRec :: BBS_InsideCell ) { return nearestGp; } else if ( BBStatus == OctantRec :: BBS_ContainsCell ) { std :: list< OctantRec * >cellList; // found terminal octant containing point - OctantRec *startCell = this->findTerminalContaining(rootCell, coords); + OctantRec *startCell = this->findTerminalContaining(*rootCell, coords); // go up, until cell containing bbox is found - if ( startCell != rootCell ) { - while ( startCell->testBoundingBox(coords, minDist) != OctantRec :: BBS_InsideCell ) { + if ( startCell != rootCell.get() ) { + while ( startCell->testBoundingBox(coords, minDist, this->octreeMask) != OctantRec :: BBS_InsideCell ) { startCell = startCell->giveParent(); - if ( startCell == rootCell ) { + if ( startCell == rootCell.get() ) { break; } } } - this->giveListOfTerminalCellsInBoundingBox(cellList, bborigin, minDist, 0, startCell); + this->giveListOfTerminalCellsInBoundingBox(cellList, bborigin, minDist, 0, *startCell); for ( OctantRec *icell: cellList ) { if ( currCell == icell ) { continue; } - this->giveClosestIPWithinOctant( icell, coords, region, minDist, & nearestGp, iCohesiveZoneGP ); + this->giveClosestIPWithinOctant(*icell, coords, region, minDist, nearestGp, iCohesiveZoneGP); } return nearestGp; @@ -931,7 +891,7 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, int region, bo OctantRec *startCell = this->findTerminalContaining(rootCell, coords); // go up, until cell containing bbox is found if ( startCell != rootCell ) { - while ( startCell->testBoundingBox(coords, minDist) != OctantRec :: BBS_InsideCell ) { + while ( startCell->testBoundingBox(coords, minDist, this->octreeMask) != OctantRec :: BBS_InsideCell ) { startCell = startCell->giveParent(); if ( startCell == rootCell ) { break; @@ -958,10 +918,10 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, int region, bo //igp = ipContainer[i].giveGp(); if ( region == ielem->giveRegionNumber() ) { iRule = ielem->giveDefaultIntegrationRulePtr(); - for ( GaussPoint *jGp: *iRule ) { + for ( auto &jGp: *iRule ) { if ( ielem->computeGlobalCoordinates( jGpCoords, * ( jGp->giveCoordinates() ) ) ) { // compute distance - double dist = coords.distance(jGpCoords); + double dist = distance(coords, jGpCoords); if ( dist < minDist ) { minDist = dist; nearestGp = jGp; @@ -975,31 +935,27 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, int region, bo } #endif } else { - printf("coords: "); - coords.printYourself(); + coords.printYourself("coords"); OOFEM_ERROR("octree inconsistency found"); } - return NULL; + return nullptr; } void -OctreeSpatialLocalizer :: giveClosestIPWithinOctant(OctantRec *currentCell, //elementContainerType& visitedElems, +OctreeSpatialLocalizer :: giveClosestIPWithinOctant(OctantRec ¤tCell, //elementContainerType& visitedElems, const FloatArray &coords, - int region, double &dist, GaussPoint **answer, bool iCohesiveZoneGP) + int region, double &dist, GaussPoint *&answer, bool iCohesiveZoneGP) { - if ( currentCell->isTerminalOctant() ) { - double currDist; + if ( currentCell.isTerminalOctant() ) { FloatArray jGpCoords; // loop over cell elements and check if they meet the criteria - elementContainerType &elementList = currentCell->giveIPElementList(); - for ( int iel: elementList ) { + for ( int iel: currentCell.giveIPElementList() ) { // ask for element Element *ielem = domain->giveElement(iel); - /* HUHU CHEATING */ if ( ielem->giveParallelMode() == Element_remote ) { continue; } @@ -1012,13 +968,13 @@ OctreeSpatialLocalizer :: giveClosestIPWithinOctant(OctantRec *currentCell, //el // test if element already visited // if (!visitedElems.insert(*pos).second) continue; // is one of his ip's within given bbox -> inset it into elemSet - for ( GaussPoint *gp: *ielem->giveDefaultIntegrationRulePtr() ) { + for ( auto &gp: *ielem->giveDefaultIntegrationRulePtr() ) { if ( ielem->computeGlobalCoordinates( jGpCoords, gp->giveNaturalCoordinates() ) ) { - currDist = coords.distance(jGpCoords); + double currDist = distance(coords, jGpCoords); // multiple insertion are handled by STL set implementation if ( currDist <= dist ) { dist = currDist; - * answer = gp; + answer = gp; } } else { OOFEM_ERROR("computeGlobalCoordinates failed"); @@ -1029,18 +985,18 @@ OctreeSpatialLocalizer :: giveClosestIPWithinOctant(OctantRec *currentCell, //el // Check for cohesive zone Gauss points XfemElementInterface *xFemEl = dynamic_cast< XfemElementInterface * >(ielem); - if ( xFemEl != NULL ) { + if ( xFemEl ) { size_t numCZRules = xFemEl->mpCZIntegrationRules.size(); for ( size_t czRuleIndex = 0; czRuleIndex < numCZRules; czRuleIndex++ ) { std :: unique_ptr< IntegrationRule > &iRule = xFemEl->mpCZIntegrationRules [ czRuleIndex ]; if ( iRule ) { - for ( GaussPoint *gp: *iRule ) { + for ( auto &gp: *iRule ) { if ( ielem->computeGlobalCoordinates( jGpCoords, gp->giveNaturalCoordinates() ) ) { - currDist = coords.distance(jGpCoords); + double currDist = distance(coords, jGpCoords); // multiple insertion are handled by STL set implementation if ( currDist <= dist ) { dist = currDist; - * answer = gp; + answer = gp; } } else { OOFEM_ERROR("computeGlobalCoordinates failed"); @@ -1049,24 +1005,19 @@ OctreeSpatialLocalizer :: giveClosestIPWithinOctant(OctantRec *currentCell, //el } } } - ////////////////////////////////////////////////////////// } } - - return; } else { - OctantRec :: BoundingBoxStatus BBStatus; - for ( int i = 0; i <= octreeMask.at(1); i++ ) { for ( int j = 0; j <= octreeMask.at(2); j++ ) { for ( int k = 0; k <= octreeMask.at(3); k++ ) { - if ( currentCell->giveChild(i, j, k) ) { + if ( currentCell.giveChild(i, j, k) ) { // test if box hits the cell - BBStatus = currentCell->giveChild(i, j, k)->testBoundingBox(coords, dist); - if ( ( BBStatus == OctantRec :: BBS_InsideCell ) || ( BBStatus == OctantRec :: BBS_ContainsCell ) ) { + auto BBStatus = currentCell.giveChild(i, j, k)->testBoundingBox(coords, dist, this->octreeMask); + if ( BBStatus == OctantRec :: BBS_InsideCell || BBStatus == OctantRec :: BBS_ContainsCell ) { // if yes call this method for such cell - //this->giveClosestIPWithinOctant (currentCell->giveChild(i,j,k), visitedElems, coords, region, dist, answer); - this->giveClosestIPWithinOctant(currentCell->giveChild(i, j, k), coords, region, dist, answer, iCohesiveZoneGP); + //this->giveClosestIPWithinOctant(*currentCell.giveChild(i,j,k), visitedElems, coords, region, dist, answer); + this->giveClosestIPWithinOctant(*currentCell.giveChild(i, j, k), coords, region, dist, answer, iCohesiveZoneGP); } } } @@ -1079,10 +1030,7 @@ OctreeSpatialLocalizer :: giveClosestIPWithinOctant(OctantRec *currentCell, //el GaussPoint * OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, Set &elementSet, bool iCohesiveZoneGP) { - double minDist; - OctantRec *currCell; - GaussPoint *nearestGp = NULL; - OctantRec :: BoundingBoxStatus BBStatus; + GaussPoint *nearestGp = nullptr; FloatArray jGpCoords; this->init(); @@ -1090,15 +1038,13 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, Set &elementSe // list of already tested elements // elementContainerType visitedElems; - minDist = 1.1 * rootCell->giveWidth(); + double minDist = 1.1 * rootCell->giveWidth(); // found terminal octant containing point - currCell = this->findTerminalContaining(rootCell, coords); - elementContainerType &elementList = currCell->giveIPElementList(); + OctantRec *currCell = this->findTerminalContaining(*rootCell, coords); // find nearest ip in this terminal cell - for ( int iel: elementList) { + for ( int iel: currCell->giveIPElementList()) { Element *ielem = domain->giveElement(iel); - /* HUHU CHEATING */ if ( ielem->giveParallelMode() == Element_remote ) { continue; } @@ -1111,10 +1057,10 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, Set &elementSe if ( !iCohesiveZoneGP ) { // test if element already visited // if (!visitedElems.insert(ielem).second) continue; - for ( GaussPoint *jGp: *ielem->giveDefaultIntegrationRulePtr() ) { + for ( auto &jGp: *ielem->giveDefaultIntegrationRulePtr() ) { if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) { // compute distance - double dist = coords.distance(jGpCoords); + double dist = distance(coords, jGpCoords); if ( dist < minDist ) { minDist = dist; nearestGp = jGp; @@ -1128,15 +1074,15 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, Set &elementSe // Check for cohesive zone Gauss points XfemElementInterface *xFemEl = dynamic_cast< XfemElementInterface * >(ielem); - if ( xFemEl != NULL ) { + if ( xFemEl ) { size_t numCZRules = xFemEl->mpCZIntegrationRules.size(); for ( size_t czRuleIndex = 0; czRuleIndex < numCZRules; czRuleIndex++ ) { std :: unique_ptr< IntegrationRule > &iRule = xFemEl->mpCZIntegrationRules [ czRuleIndex ]; if ( iRule ) { - for ( GaussPoint *jGp: *iRule ) { + for ( auto &jGp: *iRule ) { if ( ielem->computeGlobalCoordinates( jGpCoords, jGp->giveNaturalCoordinates() ) ) { // compute distance - double dist = coords.distance(jGpCoords); + double dist = distance(coords, jGpCoords); //printf("czRuleIndex: %d j: %d dist: %e\n", czRuleIndex, j, dist); if ( dist < minDist ) { minDist = dist; @@ -1147,43 +1093,42 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, Set &elementSe } } } else { - OOFEM_ERROR("iRule == NULL"); + OOFEM_ERROR("iRule is null"); } } } - //////////////////////////////// } } FloatArray bborigin = coords; // all cell element ip's scanned // construct bounding box and test its position within currCell - BBStatus = currCell->testBoundingBox(bborigin, minDist); + auto BBStatus = currCell->testBoundingBox(bborigin, minDist, this->octreeMask); if ( BBStatus == OctantRec :: BBS_InsideCell ) { return nearestGp; } else if ( BBStatus == OctantRec :: BBS_ContainsCell ) { std :: list< OctantRec * >cellList; // found terminal octant containing point - OctantRec *startCell = this->findTerminalContaining(rootCell, coords); + OctantRec *startCell = this->findTerminalContaining(*rootCell, coords); // go up, until cell containing bbox is found - if ( startCell != rootCell ) { - while ( startCell->testBoundingBox(coords, minDist) != OctantRec :: BBS_InsideCell ) { + if ( startCell != rootCell.get() ) { + while ( startCell->testBoundingBox(coords, minDist, this->octreeMask) != OctantRec :: BBS_InsideCell ) { startCell = startCell->giveParent(); - if ( startCell == rootCell ) { + if ( startCell == rootCell.get() ) { break; } } } - this->giveListOfTerminalCellsInBoundingBox(cellList, bborigin, minDist, 0, startCell); + this->giveListOfTerminalCellsInBoundingBox(cellList, bborigin, minDist, 0, *startCell); for ( OctantRec *icell: cellList ) { if ( currCell == icell ) { continue; } - this->giveClosestIPWithinOctant( icell, coords, elementSet, minDist, & nearestGp, iCohesiveZoneGP ); + this->giveClosestIPWithinOctant(*icell, coords, elementSet, minDist, nearestGp, iCohesiveZoneGP ); } return nearestGp; @@ -1193,7 +1138,7 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, Set &elementSe OctantRec *startCell = this->findTerminalContaining(rootCell, coords); // go up, until cell containing bbox is found if ( startCell != rootCell ) { - while ( startCell->testBoundingBox(coords, minDist) != OctantRec :: BBS_InsideCell ) { + while ( startCell->testBoundingBox(coords, minDist, this->octreeMask) != OctantRec :: BBS_InsideCell ) { startCell = startCell->giveParent(); if ( startCell == rootCell ) { break; @@ -1201,7 +1146,7 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, Set &elementSe } } // loop over all child (if any) and found all nodes meeting the criteria - // this->giveClosestIPWithinOctant (startCell, visitedElems, coords, region, minDist, &nearestGp); + // this->giveClosestIPWithinOctant(startCell, visitedElems, coords, region, minDist, &nearestGp); this->giveClosestIPWithinOctant(startCell, coords, region, minDist, & nearestGp); return nearestGp; @@ -1219,10 +1164,10 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, Set &elementSe Element *ielem = domain->giveElement(iel); //igp = ipContainer[i].giveGp(); if ( region == ielem->giveRegionNumber() ) { - for ( GaussPoint *jGp: *ielem->giveDefaultIntegrationRulePtr() ) { + for ( auto &jGp: *ielem->giveDefaultIntegrationRulePtr() ) { if ( ielem->computeGlobalCoordinates( jGpCoords, * ( jGp->giveCoordinates() ) ) ) { // compute distance - double dist = coords.distance(jGpCoords); + double dist = distance(coords, jGpCoords); if ( dist < minDist ) { minDist = dist; nearestGp = jGp; @@ -1241,26 +1186,24 @@ OctreeSpatialLocalizer :: giveClosestIP(const FloatArray &coords, Set &elementSe OOFEM_ERROR("octree inconsistency found"); } - return NULL; + return nullptr; } void -OctreeSpatialLocalizer :: giveClosestIPWithinOctant(OctantRec *currentCell, //elementContainerType& visitedElems, +OctreeSpatialLocalizer :: giveClosestIPWithinOctant(OctantRec ¤tCell, //elementContainerType& visitedElems, const FloatArray &coords, - Set &elementSet, double &dist, GaussPoint **answer, bool iCohesiveZoneGP) + Set &elementSet, double &dist, GaussPoint *&answer, bool iCohesiveZoneGP) { - if ( currentCell->isTerminalOctant() ) { + if ( currentCell.isTerminalOctant() ) { double currDist; FloatArray jGpCoords; // loop over cell elements and check if they meet the criteria - elementContainerType &elementList = currentCell->giveIPElementList(); - for ( int iel: elementList ) { + for ( int iel: currentCell.giveIPElementList() ) { // ask for element Element *ielem = domain->giveElement(iel); - /* HUHU CHEATING */ if ( ielem->giveParallelMode() == Element_remote ) { continue; } @@ -1273,13 +1216,13 @@ OctreeSpatialLocalizer :: giveClosestIPWithinOctant(OctantRec *currentCell, //el // test if element already visited // if (!visitedElems.insert(iel).second) continue; // is one of his ip's within given bbox -> inset it into elemSet - for ( GaussPoint *gp: *ielem->giveDefaultIntegrationRulePtr() ) { + for ( auto &gp: *ielem->giveDefaultIntegrationRulePtr() ) { if ( ielem->computeGlobalCoordinates( jGpCoords, gp->giveNaturalCoordinates() ) ) { - currDist = coords.distance(jGpCoords); + currDist = distance(coords, jGpCoords); // multiple insertion are handled by STL set implementation if ( currDist <= dist ) { dist = currDist; - * answer = gp; + answer = gp; } } else { OOFEM_ERROR("computeGlobalCoordinates failed"); @@ -1290,18 +1233,18 @@ OctreeSpatialLocalizer :: giveClosestIPWithinOctant(OctantRec *currentCell, //el // Check for cohesive zone Gauss points XfemElementInterface *xFemEl = dynamic_cast< XfemElementInterface * >(ielem); - if ( xFemEl != NULL ) { + if ( xFemEl ) { size_t numCZRules = xFemEl->mpCZIntegrationRules.size(); for ( size_t czRuleIndex = 0; czRuleIndex < numCZRules; czRuleIndex++ ) { std :: unique_ptr< IntegrationRule > &iRule = xFemEl->mpCZIntegrationRules [ czRuleIndex ]; if ( iRule ) { - for ( GaussPoint *gp: *iRule ) { + for ( auto &gp: *iRule ) { if ( ielem->computeGlobalCoordinates( jGpCoords, gp->giveNaturalCoordinates() ) ) { - currDist = coords.distance(jGpCoords); + currDist = distance(coords, jGpCoords); // multiple insertion are handled by STL set implementation if ( currDist <= dist ) { dist = currDist; - * answer = gp; + answer = gp; } } else { OOFEM_ERROR("computeGlobalCoordinates failed"); @@ -1310,24 +1253,19 @@ OctreeSpatialLocalizer :: giveClosestIPWithinOctant(OctantRec *currentCell, //el } } } - ////////////////////////////////////////////////////////// } } - - return; } else { - OctantRec :: BoundingBoxStatus BBStatus; - for ( int i = 0; i <= octreeMask.at(1); i++ ) { for ( int j = 0; j <= octreeMask.at(2); j++ ) { for ( int k = 0; k <= octreeMask.at(3); k++ ) { - if ( currentCell->giveChild(i, j, k) ) { + if ( currentCell.giveChild(i, j, k) ) { // test if box hits the cell - BBStatus = currentCell->giveChild(i, j, k)->testBoundingBox(coords, dist); - if ( ( BBStatus == OctantRec :: BBS_InsideCell ) || ( BBStatus == OctantRec :: BBS_ContainsCell ) ) { + auto BBStatus = currentCell.giveChild(i, j, k)->testBoundingBox(coords, dist, this->octreeMask); + if ( BBStatus == OctantRec :: BBS_InsideCell || BBStatus == OctantRec :: BBS_ContainsCell ) { // if yes call this method for such cell //this->giveClosestIPWithinOctant (currentCell->giveChild(i,j,k), visitedElems, coords, region, dist, answer); - this->giveClosestIPWithinOctant(currentCell->giveChild(i, j, k), coords, elementSet, dist, answer, iCohesiveZoneGP); + this->giveClosestIPWithinOctant(*currentCell.giveChild(i, j, k), coords, elementSet, dist, answer, iCohesiveZoneGP); } } } @@ -1344,19 +1282,19 @@ OctreeSpatialLocalizer :: giveAllElementsWithIpWithinBox_EvenIfEmpty(elementCont this->init(); this->initElementIPDataStructure(); // found terminal octant containing point - OctantRec *currCell = this->findTerminalContaining(rootCell, coords); + OctantRec *currCell = this->findTerminalContaining(*rootCell, coords); // go up, until cell containing bbox is found - if ( currCell != rootCell ) { - while ( currCell->testBoundingBox(coords, radius) != OctantRec :: BBS_InsideCell ) { + if ( currCell != rootCell.get() ) { + while ( currCell->testBoundingBox(coords, radius, this->octreeMask) != OctantRec :: BBS_InsideCell ) { currCell = currCell->giveParent(); - if ( currCell == rootCell ) { + if ( currCell == rootCell.get() ) { break; } } } // loop over all child (if any) and found all nodes meeting the criteria - this->giveElementsWithIPWithinBox(elemSet, currCell, coords, radius, iCohesiveZoneGP); + this->giveElementsWithIPWithinBox(elemSet, *currCell, coords, radius, iCohesiveZoneGP); } @@ -1372,16 +1310,15 @@ OctreeSpatialLocalizer :: giveAllElementsWithIpWithinBox(elementContainerType &e void -OctreeSpatialLocalizer :: giveElementsWithIPWithinBox(elementContainerType &elemSet, OctantRec *currentCell, +OctreeSpatialLocalizer :: giveElementsWithIPWithinBox(elementContainerType &elemSet, OctantRec ¤tCell, const FloatArray &coords, const double radius, bool iCohesiveZoneGP) { - if ( currentCell->isTerminalOctant() ) { + if ( currentCell.isTerminalOctant() ) { double currDist; FloatArray jGpCoords; // loop over cell elements and check if they meet the criteria - elementContainerType &elementList = currentCell->giveIPElementList(); - for ( int iel: elementList ) { + for ( int iel: currentCell.giveIPElementList() ) { // test if element is already present if ( elemSet.findSorted(iel) ) { continue; @@ -1395,7 +1332,7 @@ OctreeSpatialLocalizer :: giveElementsWithIPWithinBox(elementContainerType &elem // is one of his ip's within given bbox -> inset it into elemSet for ( auto &gp: *ielem->giveDefaultIntegrationRulePtr() ) { if ( ielem->computeGlobalCoordinates( jGpCoords, gp->giveNaturalCoordinates() ) ) { - currDist = coords.distance(jGpCoords); + currDist = distance(coords, jGpCoords); // multiple insertion are handled by STL set implementation if ( currDist <= radius ) { elemSet.insertSortedOnce(iel); @@ -1410,14 +1347,14 @@ OctreeSpatialLocalizer :: giveElementsWithIPWithinBox(elementContainerType &elem XfemElementInterface *xFemEl = dynamic_cast< XfemElementInterface * >(ielem); - if ( xFemEl != NULL ) { + if ( xFemEl ) { size_t numCZRules = xFemEl->mpCZIntegrationRules.size(); for ( size_t czRuleIndex = 0; czRuleIndex < numCZRules; czRuleIndex++ ) { std :: unique_ptr< IntegrationRule > &iRule = xFemEl->mpCZIntegrationRules [ czRuleIndex ]; if ( iRule ) { for ( auto &gp: *iRule ) { if ( ielem->computeGlobalCoordinates( jGpCoords, gp->giveNaturalCoordinates() ) ) { - currDist = coords.distance(jGpCoords); + currDist = distance(coords, jGpCoords); // multiple insertion are handled by STL set implementation if ( currDist <= radius ) { elemSet.insertSortedOnce(iel); @@ -1431,22 +1368,19 @@ OctreeSpatialLocalizer :: giveElementsWithIPWithinBox(elementContainerType &elem } } } - /////////////////////////////////////////////////// } } } else { - OctantRec :: BoundingBoxStatus BBStatus; - - for ( int i = 0; i <= octreeMask.at(1); i++ ) { for ( int j = 0; j <= octreeMask.at(2); j++ ) { for ( int k = 0; k <= octreeMask.at(3); k++ ) { - if ( currentCell->giveChild(i, j, k) ) { + auto child = currentCell.giveChild(i, j, k); + if ( child ) { // test if box hits the cell - BBStatus = currentCell->giveChild(i, j, k)->testBoundingBox(coords, radius); - if ( ( BBStatus == OctantRec :: BBS_InsideCell ) || ( BBStatus == OctantRec :: BBS_ContainsCell ) ) { + auto BBStatus = child->testBoundingBox(coords, radius, this->octreeMask); + if ( BBStatus == OctantRec :: BBS_InsideCell || BBStatus == OctantRec :: BBS_ContainsCell ) { // if yes call this method for such cell - this->giveElementsWithIPWithinBox(elemSet, currentCell->giveChild(i, j, k), coords, radius, iCohesiveZoneGP); + this->giveElementsWithIPWithinBox(elemSet, *child, coords, radius, iCohesiveZoneGP); } } } @@ -1461,44 +1395,42 @@ OctreeSpatialLocalizer :: giveAllNodesWithinBox(nodeContainerType &nodeSet, cons { this->init(); // found terminal octant containing point - OctantRec *currCell = this->findTerminalContaining(rootCell, coords); + OctantRec *currCell = this->findTerminalContaining(*rootCell, coords); // go up, until cell containing bbox is found - if ( currCell != rootCell ) { - while ( currCell->testBoundingBox(coords, radius) != OctantRec :: BBS_InsideCell ) { + if ( currCell != rootCell.get() ) { + while ( currCell->testBoundingBox(coords, radius, this->octreeMask) != OctantRec :: BBS_InsideCell ) { currCell = currCell->giveParent(); - if ( currCell == rootCell ) { + if ( currCell == rootCell.get() ) { break; } } } // loop over all child (if any) and found all nodes meeting the criteria - this->giveNodesWithinBox(nodeSet, currCell, coords, radius); + this->giveNodesWithinBox(nodeSet, *currCell, coords, radius); } Node * OctreeSpatialLocalizer :: giveNodeClosestToPoint(const FloatArray &gcoords, double maxDist) { - Node *answer = NULL; - std :: list< OctantRec * >cellList; - OctantRec *currCell; - double radius, prevRadius; + Node *answer = nullptr; + std :: list< OctantRec * > cellList; // Maximum distance given coordinate and furthest terminal cell ( center_distance + width/2*sqrt(3) ) double minDist = maxDist; // found terminal octant containing point - currCell = this->findTerminalContaining(rootCell, gcoords); + OctantRec *currCell = this->findTerminalContaining(*rootCell, gcoords); // Look in center, then expand. - this->giveNodeClosestToPointWithinOctant(currCell, gcoords, minDist, answer); - prevRadius = 0.; - radius = min(currCell->giveWidth(), minDist); + this->giveNodeClosestToPointWithinOctant(*currCell, gcoords, minDist, answer); + double prevRadius = 0.; + double radius = min(currCell->giveWidth(), minDist); do { - this->giveListOfTerminalCellsInBoundingBox(cellList, gcoords, radius, prevRadius, this->rootCell); + this->giveListOfTerminalCellsInBoundingBox(cellList, gcoords, radius, prevRadius, *this->rootCell); for ( OctantRec *cell: cellList ) { - this->giveNodeClosestToPointWithinOctant(cell, gcoords, minDist, answer); + this->giveNodeClosestToPointWithinOctant(*cell, gcoords, minDist, answer); } prevRadius = radius; radius *= 2.; // Keep expanding the scope until the radius is larger than the entire root cell, then give up (because we have checked every possible cell) @@ -1508,14 +1440,14 @@ OctreeSpatialLocalizer :: giveNodeClosestToPoint(const FloatArray &gcoords, doub void -OctreeSpatialLocalizer :: giveNodeClosestToPointWithinOctant(OctantRec *currCell, const FloatArray &gcoords, +OctreeSpatialLocalizer :: giveNodeClosestToPointWithinOctant(OctantRec &currCell, const FloatArray &gcoords, double &minDist, Node * &answer) { double minDist2 = minDist*minDist; - for ( auto &inod : currCell->giveNodeList() ) { + for ( auto &inod : currCell.giveNodeList() ) { Node *node = domain->giveNode(inod); - double currDist2 = gcoords.distance_square(*node->giveCoordinates()); + double currDist2 = distance_square(gcoords, node->giveCoordinates()); if ( currDist2 < minDist2 ) { answer = node; @@ -1527,36 +1459,33 @@ OctreeSpatialLocalizer :: giveNodeClosestToPointWithinOctant(OctantRec *currCell void -OctreeSpatialLocalizer :: giveNodesWithinBox(nodeContainerType &nodeList, OctantRec *currentCell, +OctreeSpatialLocalizer :: giveNodesWithinBox(nodeContainerType &nodeList, OctantRec ¤tCell, const FloatArray &coords, const double radius) { - nodeContainerType &cellNodes = currentCell->giveNodeList(); - - if ( currentCell->isTerminalOctant() ) { - FloatArray *nodeCoords; + if ( currentCell.isTerminalOctant() ) { + nodeContainerType &cellNodes = currentCell.giveNodeList(); if ( !cellNodes.empty() ) { for ( int inod: cellNodes ) { // loop over cell nodes and check if they meet the criteria - nodeCoords = domain->giveNode(inod)->giveCoordinates(); + const auto &nodeCoords = domain->giveNode(inod)->giveCoordinates(); // is node within bbox - if ( nodeCoords->distance(coords) <= radius ) { + if ( distance(nodeCoords, coords) <= radius ) { // if yes, append them into set nodeList.push_back(inod); } } } } else { - OctantRec :: BoundingBoxStatus BBStatus; - for ( int i = 0; i <= octreeMask.at(1); i++ ) { for ( int j = 0; j <= octreeMask.at(2); j++ ) { for ( int k = 0; k <= octreeMask.at(3); k++ ) { - if ( currentCell->giveChild(i, j, k) ) { + auto child = currentCell.giveChild(i, j, k); + if ( child ) { // test if box hits the cell - BBStatus = currentCell->giveChild(i, j, k)->testBoundingBox(coords, radius); - if ( ( BBStatus == OctantRec :: BBS_InsideCell ) || ( BBStatus == OctantRec :: BBS_ContainsCell ) ) { + auto BBStatus = child->testBoundingBox(coords, radius, this->octreeMask); + if ( BBStatus == OctantRec :: BBS_InsideCell || BBStatus == OctantRec :: BBS_ContainsCell ) { // if yes call this method for such cell - this->giveNodesWithinBox(nodeList, currentCell->giveChild(i, j, k), coords, radius); + this->giveNodesWithinBox(nodeList, *child, coords, radius); } } } @@ -1566,42 +1495,41 @@ OctreeSpatialLocalizer :: giveNodesWithinBox(nodeContainerType &nodeList, Octant } -void -OctreeSpatialLocalizer :: giveMaxTreeDepthFrom(OctantRec *root, int &maxDepth) +int +OctreeSpatialLocalizer :: giveMaxTreeDepthFrom(OctantRec &root) { - int depth = root->giveCellDepth(); - maxDepth = max(maxDepth, depth); - + int maxDepth = 0; for ( int i = 0; i <= octreeMask.at(1); i++ ) { for ( int j = 0; j <= octreeMask.at(2); j++ ) { for ( int k = 0; k <= octreeMask.at(3); k++ ) { - if ( root->giveChild(i, j, k) ) { - this->giveMaxTreeDepthFrom(root->giveChild(i, j, k), maxDepth); + auto child = root.giveChild(i, j, k); + if ( child ) { + maxDepth = std::max(maxDepth, this->giveMaxTreeDepthFrom(*child)); } } } } + return maxDepth + 1; } void OctreeSpatialLocalizer :: giveListOfTerminalCellsInBoundingBox(std :: list< OctantRec * > &cellList, const FloatArray &coords, - double radius, double innerRadius, OctantRec *currentCell) + double radius, double innerRadius, OctantRec ¤tCell) { - OctantRec :: BoundingBoxStatus BBStatus; - - BBStatus = currentCell->testBoundingBox(coords, radius); + auto BBStatus = currentCell.testBoundingBox(coords, radius, this->octreeMask); if ( BBStatus != OctantRec :: BBS_OutsideCell ) { - if ( currentCell->isTerminalOctant() ) { - //if ( currentCell->testBoundingBox(coords, innerRadius) == OctantRec :: BBS_OutsideCell ) { - cellList.push_back(currentCell); + if ( currentCell.isTerminalOctant() ) { + //if ( currentCell.testBoundingBox(coords, innerRadius, this->octreeMask) == OctantRec :: BBS_OutsideCell ) { + cellList.push_back(¤tCell); //} } else { for ( int i = 0; i <= octreeMask.at(1); i++ ) { for ( int j = 0; j <= octreeMask.at(2); j++ ) { for ( int k = 0; k <= octreeMask.at(3); k++ ) { - if ( currentCell->giveChild(i, j, k) ) { - this->giveListOfTerminalCellsInBoundingBox( cellList, coords, radius, innerRadius, currentCell->giveChild(i, j, k) ); + auto child = currentCell.giveChild(i, j, k); + if ( child ) { + this->giveListOfTerminalCellsInBoundingBox( cellList, coords, radius, innerRadius, *child ); } } } @@ -1615,18 +1543,46 @@ int OctreeSpatialLocalizer :: init(bool force) { if ( force ) { - if ( rootCell ) { - delete rootCell; + int ans; + initialized = false; +#ifdef _OPENMP + omp_set_lock(&initLock); // if not initialized yet; one thread can proceed with init; others have to wait until init completed + if ( initialized) { + omp_unset_lock(&initLock); + return 0; } - rootCell = NULL; +#endif + rootCell = nullptr; elementIPListsInitialized = false; elementListsInitialized.zero(); - } - - if ( !rootCell ) { - return this->buildOctreeDataStructure(); + ans = this->buildOctreeDataStructure(); + //this->initElementIPDataStructure(); + this->initialized=true; +#ifdef _OPENMP + omp_unset_lock(&initLock); +#endif + return ans; } else { + if ( !this->initialized) { + int ans; +#ifdef _OPENMP + omp_set_lock(&initLock); // if not initialized yet; one thread can proceed with init; others have to wait until init completed + if ( initialized) { + omp_unset_lock(&initLock); + return 0; + } +#endif + OOFEM_LOG_INFO("OctreeLocalizer: init\n"); + ans = this->buildOctreeDataStructure(); + //this->initElementIPDataStructure(); + this->initialized = true; +#ifdef _OPENMP + omp_unset_lock(&initLock); +#endif + return ans; + } else { return 0; + } } } } // end namespace oofem diff --git a/src/oofemlib/octreelocalizer.h b/src/oofemlib/octreelocalizer.h index a027db383..1a75381a2 100644 --- a/src/oofemlib/octreelocalizer.h +++ b/src/oofemlib/octreelocalizer.h @@ -43,6 +43,11 @@ #include #include #include +#include + +#ifdef _OPENMP +#include +#endif namespace oofem { class Domain; @@ -64,12 +69,11 @@ class OctreeSpatialLocalizer; class OOFEM_NO_EXPORT OctantRec { protected: - /// Link to octree class. - OctreeSpatialLocalizer *localizer; /// Link to parent cell record. OctantRec *parent; /// Link to octant children. - OctantRec *child [ 2 ] [ 2 ] [ 2 ]; + std::unique_ptr child [ 2 ] [ 2 ] [ 2 ]; + //std::unique_ptr child2; /// Octant origin coordinates (lower corner) FloatArray origin; /// Octant size. @@ -84,14 +88,15 @@ class OOFEM_NO_EXPORT OctantRec /// Element list of all elements close to the cell. std :: vector< std :: list< int > >elementList; + public: enum BoundingBoxStatus { BBS_OutsideCell, BBS_InsideCell, BBS_ContainsCell }; enum ChildStatus { CS_ChildFound, CS_NoChild }; /// Constructor. - OctantRec(OctreeSpatialLocalizer * loc, OctantRec * parent, FloatArray & origin, double halfWidth); + OctantRec(OctantRec * parent, FloatArray origin, double halfWidth); /// Destructor. - ~OctantRec(); + ~OctantRec() {} /// @return Reference to parent; NULL if root. OctantRec *giveParent() { return this->parent; } @@ -120,9 +125,10 @@ class OOFEM_NO_EXPORT OctantRec * child is set to NULL. * @param child * @param coords Coordinate which child should contain. + * @param mask Mask for which dimensions are in used (size 3, 0 or 1 values) * @return Child status. */ - ChildStatus giveChildContainingPoint(OctantRec **child, const FloatArray &coords); + ChildStatus giveChildContainingPoint(OctantRec *&child, const FloatArray &coords, const IntArray &mask); /// @return True if octant is terminal (no children). bool isTerminalOctant(); /// @return Reference to node List. @@ -142,9 +148,10 @@ class OOFEM_NO_EXPORT OctantRec * Test if receiver within bounding box (sphere). * @param coords Center of sphere. * @param radius Radius of sphere. + * @param mask Mask for which dimensions are in used (size 3, 0 or 1 values) * @return BoundingBoxStatus status. */ - BoundingBoxStatus testBoundingBox(const FloatArray &coords, double radius); + BoundingBoxStatus testBoundingBox(const FloatArray &coords, double radius, const IntArray &mask); /** * Adds given element to cell list of elements having IP within this cell. * @param elementNum Element number to add. @@ -186,18 +193,23 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer { protected: /// Root cell of octree. - OctantRec *rootCell; + std::unique_ptr rootCell; /// Octree degenerate mask. IntArray octreeMask; /// Flag indicating elementIP tables are initialized. bool elementIPListsInitialized; IntArray elementListsInitialized; - + bool initialized; +#ifdef _OPENMP + omp_lock_t initLock; + omp_lock_t buildOctreeDataStructureLock; + omp_lock_t ElementIPDataStructureLock; +#endif public: /// Constructor OctreeSpatialLocalizer(Domain * d); /// Destructor - deletes the octree tree - virtual ~OctreeSpatialLocalizer(); + virtual ~OctreeSpatialLocalizer() {} /** * Returns the octreeMask value given by the index @@ -210,21 +222,24 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * Initialize receiver data structure if not done previously. * Current implementation calls and returns the buildOctreeDataStructure service response. */ - virtual int init(bool force = false); + int init(bool force = false) override; + + Element *giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList = nullptr) override; + Element *giveElementContainingPoint(const FloatArray &coords, const Set &eset) override; + Element *giveElementClosestToPoint(FloatArray &lcoords, FloatArray &closest, const FloatArray &gcoords, int region) override; + + GaussPoint *giveClosestIP(const FloatArray &coords, int region, bool iCohesiveZoneGP = false) override; + GaussPoint *giveClosestIP(const FloatArray &coords, Set &elemSet, bool iCohesiveZoneGP = false) override; + + void giveAllElementsWithIpWithinBox_EvenIfEmpty(elementContainerType &elemSet, const FloatArray &coords, const double radius) override { giveAllElementsWithIpWithinBox_EvenIfEmpty(elemSet, coords, radius, false); } + void giveAllElementsWithIpWithinBox(elementContainerType &elemSet, const FloatArray &coords, const double radius) override { giveAllElementsWithIpWithinBox(elemSet, coords, radius, false); } + void giveAllElementsWithIpWithinBox_EvenIfEmpty(elementContainerType &elemSet, const FloatArray &coords, const double radius, bool iCohesiveZoneGP); + void giveAllElementsWithIpWithinBox(elementContainerType &elemSet, const FloatArray &coords, const double radius, bool iCohesiveZoneGP); - virtual Element *giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList = NULL); - virtual Element *giveElementContainingPoint(const FloatArray &coords, const Set &eset); - virtual Element *giveElementClosestToPoint(FloatArray &lcoords, FloatArray &closest, const FloatArray &gcoords, int region); - virtual GaussPoint *giveClosestIP(const FloatArray &coords, int region, bool iCohesiveZoneGP = false); - virtual GaussPoint *giveClosestIP(const FloatArray &coords, Set &elemSet, bool iCohesiveZoneGP = false); - virtual void giveAllElementsWithIpWithinBox_EvenIfEmpty(elementContainerType &elemSet, const FloatArray &coords, const double radius) { giveAllElementsWithIpWithinBox_EvenIfEmpty(elemSet, coords, radius, false); } - virtual void giveAllElementsWithIpWithinBox(elementContainerType &elemSet, const FloatArray &coords, const double radius) { giveAllElementsWithIpWithinBox(elemSet, coords, radius, false); } - virtual void giveAllElementsWithIpWithinBox_EvenIfEmpty(elementContainerType &elemSet, const FloatArray &coords, const double radius, bool iCohesiveZoneGP); - virtual void giveAllElementsWithIpWithinBox(elementContainerType &elemSet, const FloatArray &coords, const double radius, bool iCohesiveZoneGP); - virtual void giveAllNodesWithinBox(nodeContainerType &nodeList, const FloatArray &coords, const double radius); - virtual Node * giveNodeClosestToPoint(const FloatArray &coords, double maxDist); + void giveAllNodesWithinBox(nodeContainerType &nodeList, const FloatArray &coords, const double radius) override; + Node * giveNodeClosestToPoint(const FloatArray &coords, double maxDist) override; - virtual const char *giveClassName() const { return "OctreeSpatialLocalizer"; } + const char *giveClassName() const override { return "OctreeSpatialLocalizer"; } protected: /** @@ -250,7 +265,7 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param coords Coordinates of point of interest. * @return Pointer to terminal octant, NULL if point outside startingCell. */ - OctantRec *findTerminalContaining(OctantRec *startCell, const FloatArray &coords); + OctantRec *findTerminalContaining(OctantRec &startCell, const FloatArray &coords); /** * Inserts the given node (identified by its number and position) to the octree structure. * The tree is traversed until terminal octant containing given position is found and node is then inserted @@ -260,7 +275,7 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param nodeNum Node number. * @param coords Corresponding node coordinates. */ - void insertNodeIntoOctree(OctantRec *rootCell, int nodeNum, const FloatArray &coords); + void insertNodeIntoOctree(OctantRec &rootCell, int nodeNum, const FloatArray &coords); /** * Inserts the given integration point (or more precisely the element owning it) to the octree data structure. * The tree is traversed until terminal octant containing given position (ip coordinates) is found @@ -269,7 +284,7 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param elemNum Element number. * @param coords Global IP coordinates. */ - void insertIPElementIntoOctree(OctantRec *rootCell, int elemNum, const FloatArray &coords); + void insertIPElementIntoOctree(OctantRec &rootCell, int elemNum, const FloatArray &coords); /** * Inserts an element with the given bounding box. * @param rootCell Starting cell for insertion. @@ -278,7 +293,7 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param b0 Lower bounding box. * @param b1 Upper bounding box. */ - void insertElementIntoOctree(OctantRec *rootCell, int region, int elemNum, const FloatArray &b0, const FloatArray &b1); + void insertElementIntoOctree(OctantRec &rootCell, int region, int elemNum, const FloatArray &b0, const FloatArray &b1); /** * Initializes the element lists in octree data structure. * This implementation requires that the list of nodes in terminate cells exists @@ -287,7 +302,7 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * this leads to more complete element list in terminal cell. * @param rootCell Starting cell for octree transversal. */ - void insertElementsUsingNodalConnectivitiesIntoOctree(OctantRec *rootCell); + void insertElementsUsingNodalConnectivitiesIntoOctree(OctantRec &rootCell); /** * Returns container (set) of elements having integration point within given box and given root cell. * @param elemSet answer containing the list of elements meeting the criteria. @@ -295,7 +310,7 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param coords Center of box of interest. * @param radius Radius of bounding sphere. */ - void giveElementsWithIPWithinBox(elementContainerType &elemSet, OctantRec *currentCell, + void giveElementsWithIPWithinBox(elementContainerType &elemSet, OctantRec ¤tCell, const FloatArray &coords, const double radius, bool iCohesiveZoneGP = false); /** * Returns container (list) of nodes within given box and given root cell. @@ -304,7 +319,7 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param coords Center of box of interest. * @param radius Radius of bounding sphere. */ - void giveNodesWithinBox(nodeContainerType &nodeList, OctantRec *currentCell, + void giveNodesWithinBox(nodeContainerType &nodeList, OctantRec ¤tCell, const FloatArray &coords, const double radius); /** @@ -315,9 +330,9 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param dist Threshold distance, only update answer param, if distance is smaller, distance is updated too. * @param answer Pointer to IP, which has the smallest distance "distance" from given point. */ - void giveClosestIPWithinOctant(OctantRec *currentCell, //elementContainerType& visitedElems, + void giveClosestIPWithinOctant(OctantRec ¤tCell, //elementContainerType& visitedElems, const FloatArray &coords, - int region, double &dist, GaussPoint **answer, bool iCohesiveZoneGP); + int region, double &dist, GaussPoint *&answer, bool iCohesiveZoneGP); /** * Returns closest IP to given point contained within given octree cell. * @param currentCell Starting cell to search, all children will be searched too @@ -326,9 +341,9 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param dist Threshold distance, only update answer param, if distance is smaller, distance is updated too. * @param answer Pointer to IP, which has the smallest distance "distance" from given point. */ - void giveClosestIPWithinOctant(OctantRec *currentCell, //elementContainerType& visitedElems, + void giveClosestIPWithinOctant(OctantRec ¤tCell, //elementContainerType& visitedElems, const FloatArray &coords, - Set &elemSet, double &dist, GaussPoint **answer, bool iCohesiveZoneGP); + Set &elemSet, double &dist, GaussPoint *&answer, bool iCohesiveZoneGP); /** * Returns the element containing given point. * The search is done only for given cell and its children, skipping the given child from search @@ -338,8 +353,8 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param regionList Only elements within given regions are considered, if NULL all regions are considered. * @note regions depreceted, use sets insteed */ - Element *giveElementContainingPoint(OctantRec *cell, const FloatArray &coords, - OctantRec *scannedChild = NULL, const IntArray *regionList = NULL); + Element *giveElementContainingPoint(OctantRec &cell, const FloatArray &coords, + OctantRec *scannedChild = nullptr, const IntArray *regionList = nullptr); /** * Returns the element containing given point. * The search is done only for given cell and its children, skipping the given child from search @@ -348,8 +363,8 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param scannedChild Child pointer to exclude from search. * @param elset Only elements in gibven set are considered, if NULL all regions are considered. */ - Element *giveElementContainingPoint(OctantRec *cell, const FloatArray &coords, - OctantRec *scannedChild = NULL, const Set *elset = NULL); + Element *giveElementContainingPoint(OctantRec &cell, const FloatArray &coords, + OctantRec *scannedChild = nullptr, const Set *elset = nullptr); /** * Returns the element closest to the given point within the cell. * @param currCell Terminal cell to look in. @@ -360,7 +375,7 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param answer Requested element. * @param region Region to consider. */ - void giveElementClosestToPointWithinOctant(OctantRec *currCell, const FloatArray &gcoords, + void giveElementClosestToPointWithinOctant(OctantRec &currCell, const FloatArray &gcoords, double &minDist, FloatArray &lcoords, FloatArray &closest, Element * &answer, int region); /** * Returns the node closest to the given point within the cell. @@ -369,16 +384,16 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param[in,out] minDist Distance from the center of returned element. * @param answer Requested node. */ - void giveNodeClosestToPointWithinOctant(OctantRec* cell, const FloatArray &gcoords, double &minDist, Node * &answer); + void giveNodeClosestToPointWithinOctant(OctantRec &cell, const FloatArray &gcoords, double &minDist, Node * &answer); /** * Determines the max tree depth computed for given tree cell and its children. * To obtain total tree depth, root cell should be supplied. * The tree depth is always measured from the root cell. * Before call, maxDepth should be set to zero. * @param root Root of tree. - * @param maxDepth The maximum depth in the tree. + * @return The maximum depth in the tree from the given root */ - void giveMaxTreeDepthFrom(OctantRec *root, int &maxDepth); + int giveMaxTreeDepthFrom(OctantRec &root); /** * Builds the list of terminal cells contained within given box (coords, radius), starting from given currentCell. * @param cellList List of terminal cell pointers contained by bounding box. @@ -388,7 +403,7 @@ class OOFEM_EXPORT OctreeSpatialLocalizer : public SpatialLocalizer * @param currentCell Starting cell. */ void giveListOfTerminalCellsInBoundingBox(std :: list< OctantRec * > &cellList, const FloatArray &coords, - const double radius, double innerRadius, OctantRec *currentCell); + const double radius, double innerRadius, OctantRec ¤tCell); }; } // end namespace oofem #endif // octreelocalizer_h diff --git a/src/fm/pfem/octreelocalizert.h b/src/oofemlib/octreelocalizert.h similarity index 80% rename from src/fm/pfem/octreelocalizert.h rename to src/oofemlib/octreelocalizert.h index 166e95cb7..41b2aec29 100644 --- a/src/fm/pfem/octreelocalizert.h +++ b/src/oofemlib/octreelocalizert.h @@ -35,14 +35,14 @@ // ************************************** // *** CLASS OCTREE SPATIAL LOCALIZER *** // ************************************** -// general Octree localizer - using template +// +// Generic templated Octree localizer #ifndef octreelocalizert_h #define octreelocalizert_h #include "spatiallocalizer.h" #include "octreelocalizer.h" -#include "delaunaytriangle.h" #include "dofmanager.h" #include "node.h" #include "element.h" @@ -129,19 +129,19 @@ class BoundingBox } bool contains(const FloatArray& coords) const { - for ( int i = 1; i <= coords.giveSize(); i++ ) { - if ( spatialMask.at(i) ) { - if ( coords.at(i) < this->origin.at(i) ) { - return 0; - } - - if ( coords.at(i) > ( this->origin.at(i) + this->size ) ) { - return 0; - } - } - } - - return 1; + for ( int i = 1; i <= coords.giveSize(); i++ ) { + if ( spatialMask.at(i) ) { + if ( coords.at(i) < this->origin.at(i) ) { + return 0; + } + + if ( coords.at(i) > ( this->origin.at(i) + this->size ) ) { + return 0; + } + } + } + + return 1; } }; @@ -522,100 +522,6 @@ template< class T >class SL_Insertion_Functor }; -/** - * Functor for storing nodes in the octree - * - * @author David Krybus - */ -class InsertNode : public SL_Insertion_Functor< int > -{ -protected: - Domain *domain; - -public: - /// Constuctor - InsertNode(Domain *d) { - domain = d; - } - /// Destructor - ~InsertNode() { } - - /** - * Evaluates the position of a node - * @param nodeNr Number of the node in the domain - * @param cell Octant cell to be tested - * @returns true if the node is contained in the cell, false otherwise - */ - bool evaluate(int &nodeNr, OctantRecT< int > *cell) - { - FloatArray coords(3); - for ( int i = 1; i <= 3; i++ ) { - coords.at(i) = this->domain->giveNode(nodeNr)->giveCoordinate(i); - } - - if ( cell->containsPoint(coords) ) { - return true; - } else { - return false; - } - }; - - void registerInsertion(int &nodeNr, LocalInsertionData< int >LIdata) { } - - std :: list< LocalInsertionData< int > > *giveInsertionList(int &nodeNr) - { - return NULL; - } -}; - -/** - * Functor for storing triangles in the octree according to theirs circumscribed circles - * - * @author David Krybus - */ -class InsertTriangleBasedOnCircumcircle : public SL_Insertion_Functor< DelaunayTriangle * > -{ -protected: - Domain *domain; - -public: - /// Constructor - InsertTriangleBasedOnCircumcircle(Domain *d) { - domain = d; - } - /// Destructor - ~InsertTriangleBasedOnCircumcircle() { } - - /** - * Evaluates the position of a triangle - * @param DTptr Delaunay triangle - * @param cell Octant cell to be tested - * @returns true if the cirumscribed circle of the circle lies inside or contains a part of the cell, false otherwise - */ - bool evaluate(DelaunayTriangle * &DTptr, OctantRecT< DelaunayTriangle * > *cell) - { - double radius = DTptr->giveCircumRadius(); - FloatArray centerCoords(3); - centerCoords.at(1) = DTptr->giveXCenterCoordinate(); - centerCoords.at(2) = DTptr->giveYCenterCoordinate(); - centerCoords.at(3) = 0.0; - - if ( cell->testBoundingSphere(centerCoords, radius) == SphereOutsideCell ) { - return false; - } else { - return true; - } - } - void registerInsertion(DelaunayTriangle * &TEptr, LocalInsertionData< DelaunayTriangle * >LIdata) - { - ( TEptr->giveListOfCellsAndPosition() )->push_back(LIdata); - } - std :: list< LocalInsertionData< DelaunayTriangle * > > *giveInsertionList(DelaunayTriangle * &DTptr) - { - return DTptr->giveListOfCellsAndPosition(); - } -}; - /** * Functor base class for evaluating search tasks on the octree according given condition * @@ -642,169 +548,6 @@ template< class T >class SL_Evaluation_Functor }; -/** - * Functor for closest node search - * - * @author David Krybus - */ -class ClosestNode : public SL_Evaluation_Functor< int > -{ -protected: - FloatArray *startingPosition; - Domain *domain; - int CNindex; - double distanceToClosestNode; - bool initFlag; - - std :: list< int >closestNodeIndices; - -public: - /** - * Constructor - * @param pos Starting position of the search - * @param d Domain containing nodes - */ - ClosestNode(FloatArray *pos, Domain *d) { - initFlag = false; - startingPosition = pos; - domain = d; - } - /// Destructor - ~ClosestNode() { } - - /** - * Gives the starting position of the search - * @param position startingPosition - */ - void giveStartingPosition(FloatArray &position) - { - position = * startingPosition; - } - - /** - * Evaluates a node. The closest nodes are stored in a container, if their distance to starting position is the same. - * Is the distance smaller than previous one, the container is emptied and new node is added. - * @param nodeNr Number of the node in the domain list - * @returns true after evaluation is processed. - */ - bool evaluate(int &nodeNr) - { - if ( initFlag ) { - double distance = startingPosition->distance( this->domain->giveNode(nodeNr)->giveCoordinates() ); - - if ( ( distance - distanceToClosestNode ) <= distance * 0.001 ) { - if ( ( distance - distanceToClosestNode ) >= -0.001 * distance ) { - closestNodeIndices.push_back(nodeNr); - } else { - closestNodeIndices.clear(); - closestNodeIndices.push_back(nodeNr); - distanceToClosestNode = distance; - } - } - } else { - closestNodeIndices.push_back(nodeNr); - distanceToClosestNode = startingPosition->distance( this->domain->giveNode( * ( closestNodeIndices.begin() ) )->giveCoordinates() ); - initFlag = true; - } - - return true; - } - - /** - * Gives the closest nodes - * @param answer List containing numbers of the closest nodes - */ - void giveResult(std :: list< int > &answer) { - answer = closestNodeIndices; - } - - bool isBBXStage1Defined(BoundingBox &BBXStage1) - { - return false; - } - - bool isBBXStage2Defined(BoundingBox &BBXStage2) - { - if ( initFlag ) { - BBXStage2.setOrigin(* startingPosition); - BBXStage2.setSize(distanceToClosestNode); - return true; - } else { - return false; - } - } -}; - - -/** - * Functor for finding triangles whose circumscribed circles contains given node - * - * @author David Krybus - */ -class ElementCircumCirclesContainingNode : public SL_Evaluation_Functor< DelaunayTriangle * > -{ -protected: - FloatArray *startingPosition; - Domain *domain; - std :: list< DelaunayTriangle * >result; - -public: - /** - * Constructor - * @param pos Starting position of the search - * @param d Domain containing nodes the triangles are defined by - */ - ElementCircumCirclesContainingNode(FloatArray *pos, Domain *d) - { - startingPosition = pos; - domain = d; - } - ~ElementCircumCirclesContainingNode() { } - - /** - * Evaluates a triangle upon its circumscribed cricle. - * @param DTptr Delaunay triangle. nodeNr Number of the node in the domain list - * @returns true if the circumscribed circle of the Delaunay triangle contains the point, false otherwise - */ - bool evaluate(DelaunayTriangle * &DTptr) - { - double radius = DTptr->giveCircumRadius(); - FloatArray centerCoords(3); - centerCoords.at(1) = DTptr->giveXCenterCoordinate(); - centerCoords.at(2) = DTptr->giveYCenterCoordinate(); - centerCoords.at(3) = 0.0; - - if ( ( startingPosition->distance(centerCoords) ) < radius ) { - result.push_back(DTptr); - return true; - } else { - return false; - } - } - - /** - * Gives the starting position of the search - * @param position startingPosition - */ - void giveStartingPosition(FloatArray &answer) - { - answer = * startingPosition; - } - - /** - * Gives the triangles containing the node - * @param answer List containing Delaunay triangles - */ - void giveResult(std :: list< DelaunayTriangle * > &answer) - { - answer = result; - } - - // neither stage1, nor stage 2 are defined - bool isBBXStage1Defined(BoundingBox &BBXStage1) { return false; } - bool isBBXStage2Defined(BoundingBox &BBXStage2) { return false; } -}; - /** * Templated octree spatial localizer * diff --git a/src/oofemlib/oofeggraphiccontext.C b/src/oofemlib/oofeggraphiccontext.C index 960c1f899..333cb7ecf 100644 --- a/src/oofemlib/oofeggraphiccontext.C +++ b/src/oofemlib/oofeggraphiccontext.C @@ -122,7 +122,7 @@ oofegGraphicContext :: init(EngngModel *d) nmat = 0; for ( int id = 1; id <= d->giveNumberOfDomains(); id++ ) { - nmat = max( nmat, d->giveDomain(id)->giveNumberOfMaterialModels() ); + nmat = max( nmat, d->giveDomain(id)->giveNumberOfRegions() ); } // ft = ColorCreateFringeTable(); @@ -160,7 +160,7 @@ oofegGraphicContext :: GR_giveColorFromUserColorTable(EPixel *table, int tableSi int oofegGraphicContext :: testElementGraphicActivity(Element *e) { - int matFilterState = ( this->getMaterialModelFilterState( e->giveMaterial()->giveNumber() ) ); + int matFilterState = ( this->getMaterialModelFilterState( e->giveRegionNumber() ) ); int elemFiltState = 0; if ( element_filter.empty() ) { return matFilterState; diff --git a/src/oofemlib/oofeggraphiccontext.h b/src/oofemlib/oofeggraphiccontext.h index f6bb659c7..7b79c5cec 100644 --- a/src/oofemlib/oofeggraphiccontext.h +++ b/src/oofemlib/oofeggraphiccontext.h @@ -36,21 +36,29 @@ #ifndef oofeggraphiccontext_h #define oofeggraphiccontext_h +#pragma once + #include "oofemcfg.h" #include "intarray.h" #include "internalstatemode.h" #include "internalstatetype.h" +#include "floatmatrix.h" +#include "timer.h" +#include "outputmanager.h" +#include "floatarrayf.h" +#include #include // // for c++ compiler to be successful on some c files // + +#include + extern "C" { - #define new __new - #define class __class - #define inline __inline + /* #define min __min #define max __max #define sgn __sgn @@ -58,12 +66,9 @@ extern "C" { #define Status __Status #define Request __Request #define Complex __Complex - - #include - - #undef new - #undef class - #undef inline + */ + #include + /* #undef min #undef max #undef sgn @@ -73,6 +78,7 @@ extern "C" { #undef PI #undef Complex #undef None + */ }; diff --git a/src/oofemlib/oofemtxtdatareader.C b/src/oofemlib/oofemtxtdatareader.C index 07dd210e7..42ecca902 100644 --- a/src/oofemlib/oofemtxtdatareader.C +++ b/src/oofemlib/oofemtxtdatareader.C @@ -94,13 +94,13 @@ OOFEMTXTDataReader :: ~OOFEMTXTDataReader() { } -InputRecord * +InputRecord & OOFEMTXTDataReader :: giveInputRecord(InputRecordType typeId, int recordId) { if ( this->it == this->recordList.end() ) { OOFEM_ERROR("Out of input records, file contents must be missing"); } - return &(*this->it++); + return *this->it++; } bool @@ -124,8 +124,6 @@ OOFEMTXTDataReader :: finish() bool OOFEMTXTDataReader :: giveLineFromInput(std :: ifstream &stream, int &lineNum, std :: string &line) { - // reads one line from inputStream - // if " detected, start/stop changing to lower case characters bool flag = false; //0-tolower, 1-remain with capitals bool read = this->giveRawLineFromInput(stream, lineNum, line); @@ -148,9 +146,6 @@ OOFEMTXTDataReader :: giveLineFromInput(std :: ifstream &stream, int &lineNum, s bool OOFEMTXTDataReader :: giveRawLineFromInput(std :: ifstream &stream, int &lineNum, std :: string &line) { - // - // reads one line from inputStream - for private use only. - // do { lineNum++; std :: getline(stream, line); diff --git a/src/oofemlib/oofemtxtdatareader.h b/src/oofemlib/oofemtxtdatareader.h index b0e310299..834f3ebb2 100644 --- a/src/oofemlib/oofemtxtdatareader.h +++ b/src/oofemlib/oofemtxtdatareader.h @@ -64,13 +64,18 @@ class OOFEM_EXPORT OOFEMTXTDataReader : public DataReader OOFEMTXTDataReader(const OOFEMTXTDataReader & x); virtual ~OOFEMTXTDataReader(); - virtual InputRecord *giveInputRecord(InputRecordType, int recordId); - virtual bool peakNext(const std :: string &keyword); - virtual void finish(); - virtual const char *giveDataSourceName() const { return dataSourceName.c_str(); } + InputRecord &giveInputRecord(InputRecordType, int recordId) override; + bool peakNext(const std :: string &keyword) override; + void finish() override; + std :: string giveReferenceName() const override { return dataSourceName; } protected: + /** + * Reads one line from inputStream + * Parts within quotations have case preserved. + */ bool giveLineFromInput(std :: ifstream &stream, int &lineNum, std :: string &line); + /// Reads one line from stream. bool giveRawLineFromInput(std :: ifstream &stream, int &lineNum, std :: string &line); }; } // end namespace oofem diff --git a/src/oofemlib/oofemtxtinputrecord.C b/src/oofemlib/oofemtxtinputrecord.C index f53c7433a..e17f7cb29 100644 --- a/src/oofemlib/oofemtxtinputrecord.C +++ b/src/oofemlib/oofemtxtinputrecord.C @@ -48,10 +48,10 @@ #include namespace oofem { -OOFEMTXTInputRecord :: OOFEMTXTInputRecord() : InputRecord(), tokenizer(), record() +OOFEMTXTInputRecord :: OOFEMTXTInputRecord() : tokenizer(), record() { } -OOFEMTXTInputRecord :: OOFEMTXTInputRecord(const OOFEMTXTInputRecord &src) : InputRecord(src), tokenizer(), +OOFEMTXTInputRecord :: OOFEMTXTInputRecord(const OOFEMTXTInputRecord &src) : tokenizer(), record(src.record), lineNumber(src.lineNumber) { tokenizer.tokenizeLine( this->record ); @@ -62,7 +62,7 @@ OOFEMTXTInputRecord :: OOFEMTXTInputRecord(const OOFEMTXTInputRecord &src) : Inp } } -OOFEMTXTInputRecord :: OOFEMTXTInputRecord(int linenumber, std :: string source) : InputRecord(), tokenizer(), +OOFEMTXTInputRecord :: OOFEMTXTInputRecord(int linenumber, std :: string source) : tokenizer(), record(std :: move(source)), lineNumber(linenumber) { tokenizer.tokenizeLine( this->record ); @@ -99,100 +99,93 @@ OOFEMTXTInputRecord :: setRecordString(std :: string newRec) } } -IRResultType +void OOFEMTXTInputRecord :: giveRecordKeywordField(std :: string &answer, int &value) { if ( tokenizer.giveNumberOfTokens() > 0 ) { answer = std :: string( tokenizer.giveToken(1) ); setReadFlag(1); auto ptr = scanInteger(tokenizer.giveToken(2), value); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, "RecordID", lineNumber); } setReadFlag(2); - - return IRRT_OK; } else { - return IRRT_BAD_FORMAT; + throw BadFormatInputException(*this, "RecordID", lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveRecordKeywordField(std :: string &answer) { if ( tokenizer.giveNumberOfTokens() > 0 ) { answer = std :: string( tokenizer.giveToken(1) ); setReadFlag(1); - - return IRRT_OK; } else { - return IRRT_BAD_FORMAT; + throw BadFormatInputException(*this, "RecordID", lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveField(int &answer, InputFieldType id) { int indx = this->giveKeywordIndx(id); if ( indx ) { auto ptr = scanInteger(tokenizer.giveToken(indx + 1), answer); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } setReadFlag(indx); setReadFlag(indx + 1); - return IRRT_OK; } else { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveField(double &answer, InputFieldType id) { int indx = this->giveKeywordIndx(id); if ( indx ) { auto ptr = scanDouble(tokenizer.giveToken(indx + 1), answer); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } setReadFlag(indx); setReadFlag(indx + 1); - return IRRT_OK; } else { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveField(bool &answer, InputFieldType id) { - int val; int indx = this->giveKeywordIndx(id); if ( indx ) { + int val; auto ptr = scanInteger(tokenizer.giveToken(indx + 1), val); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } setReadFlag(indx); setReadFlag(indx + 1); answer = val != 0; - return IRRT_OK; } else { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveField(std :: string &answer, InputFieldType id) { int indx = 0; if ( id ) { if ( ( indx = this->giveKeywordIndx(id) ) == 0 ) { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } setReadFlag(indx); @@ -205,118 +198,115 @@ OOFEMTXTInputRecord :: giveField(std :: string &answer, InputFieldType id) if ( _token ) { answer = std :: string( tokenizer.giveToken(indx) ); setReadFlag(indx); - return IRRT_OK; } else { answer = ""; - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveField(IntArray &answer, InputFieldType id) { - int value, size; int indx = this->giveKeywordIndx(id); if ( indx ) { + int size; setReadFlag(indx); auto ptr = scanInteger(tokenizer.giveToken(++indx), size); - if ( ptr == NULL || *ptr != 0) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0) { + throw BadFormatInputException(*this, id, lineNumber); } answer.resize(size); setReadFlag(indx); for ( int i = 1; i <= size; i++ ) { + int value; ptr = scanInteger(tokenizer.giveToken(indx + i), value); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } answer.at(i) = value; setReadFlag(indx + i); } - return IRRT_OK; } else { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveField(FloatArray &answer, InputFieldType id) { - double value; - int size; int indx = this->giveKeywordIndx(id); if ( indx ) { + int size; setReadFlag(indx); auto ptr = scanInteger(tokenizer.giveToken(++indx), size); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } answer.resize(size); setReadFlag(indx); for ( int i = 1; i <= size; i++ ) { + double value; auto ptr = scanDouble(tokenizer.giveToken(indx + i), value); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } answer.at(i) = value; setReadFlag(indx + i); } - return IRRT_OK; } else { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveField(FloatMatrix &answer, InputFieldType id) { - int nrows, ncols; int indx = this->giveKeywordIndx(id); if ( indx ) { + int nrows, ncols; setReadFlag(indx); auto ptr = scanInteger(tokenizer.giveToken(++indx), nrows); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } setReadFlag(indx); ptr = scanInteger(tokenizer.giveToken(++indx), ncols); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } setReadFlag(indx); if ( readMatrix(tokenizer.giveToken(++indx), nrows, ncols, answer) == 0 ) { - return IRRT_BAD_FORMAT; + throw BadFormatInputException(*this, id, lineNumber); } setReadFlag(indx); - return IRRT_OK; } else { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveField(std :: vector< std :: string > &answer, InputFieldType id) { - int size; int indx = this->giveKeywordIndx(id); if ( indx ) { + int size; setReadFlag(indx); auto ptr = scanInteger(tokenizer.giveToken(++indx), size); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } answer.reserve(size); setReadFlag(indx); @@ -325,60 +315,55 @@ OOFEMTXTInputRecord :: giveField(std :: vector< std :: string > &answer, InputFi setReadFlag(indx + i); } - return IRRT_OK; } else { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveField(Dictionary &answer, InputFieldType id) { - double value; - int size; - char key; int indx = this->giveKeywordIndx(id); if ( indx ) { setReadFlag(indx); + int size; auto ptr = scanInteger(tokenizer.giveToken(++indx), size); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } setReadFlag(indx); answer.clear(); for ( int i = 1; i <= size; i++ ) { - key = ( tokenizer.giveToken(++indx) ) [ 0 ]; + char key = ( tokenizer.giveToken(++indx) ) [ 0 ]; + double value; setReadFlag(indx); auto ptr = scanDouble(tokenizer.giveToken(++indx), value); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } setReadFlag(indx); answer.add(key, value); } - - return IRRT_OK; } else { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveField(std :: list< Range > &list, InputFieldType id) { - int li, hi; - const char *rec; int indx = this->giveKeywordIndx(id); if ( indx ) { + int li, hi; setReadFlag(indx); - rec = tokenizer.giveToken(++indx); + const char *rec = tokenizer.giveToken(++indx); if ( * rec != '{' ) { OOFEM_WARNING("missing left '{'"); list.clear(); - return IRRT_BAD_FORMAT; + throw BadFormatInputException(*this, id, lineNumber); } setReadFlag(indx); @@ -398,16 +383,14 @@ OOFEMTXTInputRecord :: giveField(std :: list< Range > &list, InputFieldType id) if ( * rec != '}' ) { OOFEM_WARNING("missing end '}'"); list.clear(); - return IRRT_BAD_FORMAT; + throw BadFormatInputException(*this, id, lineNumber); } - - return IRRT_OK; } else { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } } -IRResultType +void OOFEMTXTInputRecord :: giveField(ScalarFunction &answer, InputFieldType id) { const char *rec; @@ -420,8 +403,8 @@ OOFEMTXTInputRecord :: giveField(ScalarFunction &answer, InputFieldType id) // reference to function int refVal; auto ptr = scanInteger(rec + 1, refVal); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } setReadFlag(indx); answer.setReference(refVal); @@ -437,17 +420,15 @@ OOFEMTXTInputRecord :: giveField(ScalarFunction &answer, InputFieldType id) } else { double val; auto ptr = scanDouble(tokenizer.giveToken(indx), val); - if ( ptr == NULL || *ptr != 0 ) { - return IRRT_BAD_FORMAT; + if ( ptr == nullptr || *ptr != 0 ) { + throw BadFormatInputException(*this, id, lineNumber); } setReadFlag(indx); answer.setValue(val); } - - return IRRT_OK; } else { - return IRRT_NOTFOUND; + throw MissingKeywordInputException(*this, id, lineNumber); } } @@ -477,9 +458,9 @@ OOFEMTXTInputRecord :: scanInteger(const char *source, int &value) // char *endptr; - if ( source == NULL ) { + if ( source == nullptr ) { value = 0; - return NULL; + return nullptr; } value = strtol(source, & endptr, 10); @@ -494,9 +475,9 @@ OOFEMTXTInputRecord :: scanDouble(const char *source, double &value) // char *endptr; - if ( source == NULL ) { + if ( source == nullptr ) { value = 0; - return NULL; + return nullptr; } value = strtod(source, & endptr); @@ -663,14 +644,4 @@ OOFEMTXTInputRecord :: readMatrix(const char *helpSource, int r, int c, FloatMat } - -void -OOFEMTXTInputRecord :: report_error(const char *_class, const char *proc, InputFieldType id, - IRResultType result, const char *file, int line) -{ - oofem_logger.writeELogMsg(Logger :: LOG_LEVEL_ERROR, NULL, file, line, - "Input error on line %d: \"%s\", field keyword \"%s\"\nIn function %s::%s\nRecord:\"%s\"", - lineNumber, strerror(result), id, _class, proc, this->giveRecordAsString().c_str()); - OOFEM_EXIT(1); ///@todo We should never directly exit when dealing with user input. -} } // end namespace oofem diff --git a/src/oofemlib/oofemtxtinputrecord.h b/src/oofemlib/oofemtxtinputrecord.h index 483512e36..cbaf9b1dd 100644 --- a/src/oofemlib/oofemtxtinputrecord.h +++ b/src/oofemlib/oofemtxtinputrecord.h @@ -69,41 +69,37 @@ class OOFEM_EXPORT OOFEMTXTInputRecord : public InputRecord OOFEMTXTInputRecord(int linenumber, std :: string source); /// Copy constructor. OOFEMTXTInputRecord(const OOFEMTXTInputRecord &); - /// Destructor. - virtual ~OOFEMTXTInputRecord() { } /// Assignment operator. OOFEMTXTInputRecord &operator = ( const OOFEMTXTInputRecord & ); - virtual InputRecord *GiveCopy() { return new OOFEMTXTInputRecord(*this); } + std::unique_ptr clone() const override { return std::make_unique(*this); } public: /// Sets the record string. void setRecordString(std :: string newStr); /// Returns record string. - virtual std :: string giveRecordAsString() const { return this->record; } + std :: string giveRecordAsString() const override { return this->record; } - void finish(bool wrn = true); + void finish(bool wrn = true) override; public: - virtual IRResultType giveRecordKeywordField(std :: string &answer, int &value); - virtual IRResultType giveRecordKeywordField(std :: string &answer); - virtual IRResultType giveField(int &answer, InputFieldType id); - virtual IRResultType giveField(double &answer, InputFieldType id); - virtual IRResultType giveField(bool &answer, InputFieldType id); - virtual IRResultType giveField(std :: string &answer, InputFieldType id); - virtual IRResultType giveField(FloatArray &answer, InputFieldType id); - virtual IRResultType giveField(IntArray &answer, InputFieldType id); - virtual IRResultType giveField(FloatMatrix &answer, InputFieldType id); - virtual IRResultType giveField(std :: vector< std :: string > &answer, InputFieldType id); - virtual IRResultType giveField(Dictionary &answer, InputFieldType id); - virtual IRResultType giveField(std :: list< Range > &answer, InputFieldType id); - virtual IRResultType giveField(ScalarFunction &answer, InputFieldType id); + void giveRecordKeywordField(std :: string &answer, int &value) override; + void giveRecordKeywordField(std :: string &answer) override; + void giveField(int &answer, InputFieldType id) override; + void giveField(double &answer, InputFieldType id) override; + void giveField(bool &answer, InputFieldType id) override; + void giveField(std :: string &answer, InputFieldType id) override; + void giveField(FloatArray &answer, InputFieldType id) override; + void giveField(IntArray &answer, InputFieldType id) override; + void giveField(FloatMatrix &answer, InputFieldType id) override; + void giveField(std :: vector< std :: string > &answer, InputFieldType id) override; + void giveField(Dictionary &answer, InputFieldType id) override; + void giveField(std :: list< Range > &answer, InputFieldType id) override; + void giveField(ScalarFunction &answer, InputFieldType id) override; - virtual bool hasField(InputFieldType id); - virtual void printYourself(); + bool hasField(InputFieldType id) override; + void printYourself() override; - virtual void report_error(const char *_class, const char *proc, InputFieldType id, - IRResultType result, const char *file, int line); void setLineNumber(int lineNumber) { this->lineNumber = lineNumber; } protected: diff --git a/src/oofemlib/outputexportmodule.C b/src/oofemlib/outputexportmodule.C index d953ec428..cf4ac46f5 100644 --- a/src/oofemlib/outputexportmodule.C +++ b/src/oofemlib/outputexportmodule.C @@ -50,25 +50,21 @@ OutputExportModule :: OutputExportModule(int n, EngngModel *e) : ExportModule(n, { } -IRResultType -OutputExportModule :: initializeFrom(InputRecord *ir) +void +OutputExportModule :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - nodeSets.clear(); IR_GIVE_OPTIONAL_FIELD(ir, nodeSets, _IFT_OutputExportModule_nodeSets); elementSets.clear(); IR_GIVE_OPTIONAL_FIELD(ir, elementSets, _IFT_OutputExportModule_elementSets); - result = ExportModule :: initializeFrom(ir); + ExportModule :: initializeFrom(ir); auto *file = giveOutputStream(); fprintf(file, "%s", PRG_HEADER); fprintf(file, "\nStarting analysis on: %s\n", ctime(& emodel->giveStartTime()) ); fprintf(file, "%s\n", emodel->giveDescription().c_str()); - - return result; } FILE * @@ -89,33 +85,14 @@ OutputExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) return; } - if ( domainMask.containsOnlyZeroes() && domainMask.giveSize() > 0 ) { - return; - } - FILE *file = this->giveOutputStream(); fprintf(file, "\n=============================================================="); fprintf(file, "\nOutput for time %.8e ", tStep->giveTargetTime() * emodel->giveVariableScale(VST_Time) ); fprintf(file, "\n==============================================================\n"); -#if 0 - for ( int idomain = 1; idomain <= emodel->giveNumberOfDomains(); idomain++ ) { - if ( domainMask.giveSize() > 0 && domainMask.at(idomain) == 0 ) { - continue; - } - fprintf(file, "Output for domain %3d\n", idomain ); - - Domain *domain = emodel->giveDomain(idomain); - this->doDofManOutput(file, domain, tStep); - this->doElementOutput(file, domain, tStep); - ///@todo This module should handle printing reaction forces, we need more information from the domain/engineering model though. - //emodel->printReactionForces(tStep, idomain); - } -#else - ///@todo Should we even support the domain mask? I'd say, just let the emodel decide this. - //emodel->printOutputAt(file, tStep, domainMask); - emodel->printOutputAt(file, tStep); -#endif + + emodel->printOutputAt(file, tStep, nodeSets, elementSets); + fprintf(file, "\nUser time consumed by solution step %d: %.3f [s]\n\n", tStep->giveNumber(), emodel->giveSolutionStepTime()); } @@ -133,68 +110,4 @@ OutputExportModule :: terminate() fprintf(out, "User time consumed: %03dh:%02dm:%02ds\n\n\n", uhrs, umin, usec); } -void -OutputExportModule :: doDofManOutput(FILE *file, Domain *domain, TimeStep *tStep) -{ - fprintf(file, "\n\nDofManager output:\n------------------\n"); - - int setNum = nodeSets.isEmpty() ? 0 : nodeSets.at(domain->giveNumber()) ; - - if ( nodeSets.isEmpty() ) { - for ( auto &dman : domain->giveDofManagers() ) { - if ( dman->giveParallelMode() == DofManager_null ) { - continue; - } - - dman->printOutputAt(file, tStep); - } - } else { - Set *set = domain->giveSet(setNum); - const IntArray &nodes = set->giveNodeList(); - - for ( int inode : nodes ) { - DofManager *dman = domain->giveDofManager(inode); - - if ( dman->giveParallelMode() == DofManager_null ) { - continue; - } - - dman->printOutputAt(file, tStep); - } - } - - fprintf(file, "\n\n"); -} - -void -OutputExportModule :: doElementOutput(FILE *file, Domain *domain, TimeStep *tStep) -{ - fprintf(file, "\n\nElement output:\n---------------\n"); - - int setNum = elementSets.isEmpty() ? 0 : elementSets.at(domain->giveNumber()) ; - - if ( setNum == 0 ) { - for ( auto &elem : domain->giveElements() ) { - if ( elem->giveParallelMode() == Element_remote ) { - continue; - } - - elem->printOutputAt(file, tStep); - } - } else { - Set *set = domain->giveSet(setNum); - for ( int ielem : set->giveElementList() ) { - Element *element = domain->giveElement(ielem); - - if ( element->giveParallelMode() == Element_remote ) { - continue; - } - - element->printOutputAt(file, tStep); - } - } - - fprintf(file, "\n\n"); -} - } // end namespace oofem diff --git a/src/oofemlib/outputexportmodule.h b/src/oofemlib/outputexportmodule.h index c5232cd4d..23d158a92 100644 --- a/src/oofemlib/outputexportmodule.h +++ b/src/oofemlib/outputexportmodule.h @@ -42,7 +42,7 @@ ///@name Input fields for OutputExportModule //@{ #define _IFT_OutputExportModule_Name "output" -#define _IFT_OutputExportModule_nodeSets "dofman_sets" +#define _IFT_OutputExportModule_nodeSets "node_sets" #define _IFT_OutputExportModule_elementSets "element_sets" //@} @@ -53,10 +53,9 @@ class DofManager; /** * Standard output for OOFEM. Most available data is written in plain text. - * - * Adapted from OutputManager. + * Implementation simply relies on EngngModel::printOutputAt * - * @author Mikael Öhman (and others) + * @author Mikael Öhman */ class OOFEM_EXPORT OutputExportModule : public ExportModule { @@ -69,39 +68,18 @@ class OOFEM_EXPORT OutputExportModule : public ExportModule /// Set which contains elements which should be exported IntArray elementSets; - /** - * Does the dofmanager output. - * All selected dofmanagers are requested for doing their output using printOutputAt service. - */ - void doDofManOutput(FILE *file, Domain *domain, TimeStep *tStep); - /** - * Does the element output. - * All selected elements are requested for doing their output using printOutputAt service. - */ - void doElementOutput(FILE *file, Domain *domain, TimeStep *tStep); - - /** - * Tests if given dof manager is required to do its output for given time step. - * @return nonzero if output required. - */ - int testDofManOutput(DofManager *dman); - /** - * Tests if given element is required to do its output for given time step. - * @return nonzero if output required. - */ - int testElementOutput(Element *element); - public: OutputExportModule(int n, EngngModel * e); virtual ~OutputExportModule() {} - virtual IRResultType initializeFrom(InputRecord *ir); + + void initializeFrom(InputRecord &ir) override; FILE *giveOutputStream(); - virtual void doOutput(TimeStep *tStep, bool forcedOutput = false); - virtual void terminate(); + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; + void terminate() override; - virtual const char *giveClassName() const { return "OutputExportModule"; } - virtual const char *giveInputRecordName() const { return _IFT_OutputExportModule_Name; } + const char *giveClassName() const override { return "OutputExportModule"; } + const char *giveInputRecordName() const { return _IFT_OutputExportModule_Name; } }; } // end namespace oofem #endif // outputexportmodule_h_ diff --git a/src/oofemlib/outputmanager.C b/src/oofemlib/outputmanager.C index 578bf211c..713b919b8 100644 --- a/src/oofemlib/outputmanager.C +++ b/src/oofemlib/outputmanager.C @@ -48,17 +48,15 @@ OutputManager :: OutputManager(Domain *d) : dofman_out(), dofman_except(), eleme dofman_all_out_flag = element_all_out_flag = 0; } -IRResultType -OutputManager :: initializeFrom(InputRecord *ir) +void +OutputManager :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - tstep_all_out_flag = ir->hasField(_IFT_OutputManager_tstepall); + tstep_all_out_flag = ir.hasField(_IFT_OutputManager_tstepall); tstep_step_out = 0; IR_GIVE_OPTIONAL_FIELD(ir, tstep_step_out, _IFT_OutputManager_tstepstep); - dofman_all_out_flag = ir->hasField(_IFT_OutputManager_dofmanall); - element_all_out_flag = ir->hasField(_IFT_OutputManager_elementall); + dofman_all_out_flag = ir.hasField(_IFT_OutputManager_dofmanall); + element_all_out_flag = ir.hasField(_IFT_OutputManager_elementall); tsteps_out.clear(); IR_GIVE_OPTIONAL_FIELD(ir, tsteps_out, _IFT_OutputManager_tstepsout); @@ -70,8 +68,6 @@ OutputManager :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, element_out, _IFT_OutputManager_elementoutput); element_except.clear(); IR_GIVE_OPTIONAL_FIELD(ir, element_except, _IFT_OutputManager_elementexcept); - - return IRRT_OK; } void diff --git a/src/oofemlib/outputmanager.h b/src/oofemlib/outputmanager.h index 96f216142..66ad597cd 100644 --- a/src/oofemlib/outputmanager.h +++ b/src/oofemlib/outputmanager.h @@ -109,7 +109,7 @@ class OOFEM_EXPORT OutputManager /// Creates empty Output Manager. By default all components are selected. OutputManager(Domain * d); /// Initializes receiver according to object description stored in input record. - IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir); /** * Does the dofmanager output. diff --git a/src/oofemlib/parallelcontext.C b/src/oofemlib/parallelcontext.C index 3abb170c3..cf7851739 100644 --- a/src/oofemlib/parallelcontext.C +++ b/src/oofemlib/parallelcontext.C @@ -188,7 +188,7 @@ ParallelContext :: accumulate(const FloatArray &local, FloatArray &global) int size = local.giveSize(); global.resize(size); ///@todo Why aren't we using the C++ MPI functions? - MPI_Allreduce( const_cast(local.givePointer()), global.givePointer(), size, MPI_DOUBLE, MPI_SUM, this->emodel->giveParallelComm() ); + MPI_Allreduce( local.givePointer(), global.givePointer(), size, MPI_DOUBLE, MPI_SUM, this->emodel->giveParallelComm() ); } else { #endif global = local; diff --git a/src/oofemlib/parallelordering.C b/src/oofemlib/parallelordering.C index ba75c349c..5b6c6c98c 100644 --- a/src/oofemlib/parallelordering.C +++ b/src/oofemlib/parallelordering.C @@ -120,7 +120,7 @@ Natural2GlobalOrdering :: init(EngngModel *emodel, int di, const UnknownNumberin } // end shared dman #endif if ( isLocal(dman) ) { - for ( Dof *dof: *dman ) { + for ( auto &dof: *dman ) { if ( dof->isPrimaryDof() ) { if ( dof->giveEquationNumber(n) ) { l_neqs++; @@ -219,7 +219,7 @@ Natural2GlobalOrdering :: init(EngngModel *emodel, int di, const UnknownNumberin //} else if (dman->giveParallelMode() == DofManager_local) { } else { - for ( Dof *dof: *dman ) { + for ( auto &dof: *dman ) { if ( dof->isPrimaryDof() ) { int eq = dof->giveEquationNumber(n); diff --git a/src/oofemlib/parallelordering.h b/src/oofemlib/parallelordering.h index b79f6588a..cdf50f0a0 100644 --- a/src/oofemlib/parallelordering.h +++ b/src/oofemlib/parallelordering.h @@ -112,16 +112,16 @@ class OOFEM_EXPORT Natural2GlobalOrdering : public ParallelOrdering Natural2GlobalOrdering(); virtual ~Natural2GlobalOrdering() { } - virtual void init(EngngModel *, int di, const UnknownNumberingScheme &n); + void init(EngngModel *, int di, const UnknownNumberingScheme &n) override; - virtual int giveNewEq(int leq); - virtual int giveOldEq(int eq); + int giveNewEq(int leq) override; + int giveOldEq(int eq) override; - virtual void map2New(IntArray &answer, const IntArray &src, int baseOffset = 0); - virtual void map2Old(IntArray &answer, const IntArray &src, int baseOffset = 0); + void map2New(IntArray &answer, const IntArray &src, int baseOffset = 0) override; + void map2Old(IntArray &answer, const IntArray &src, int baseOffset = 0) override; - int giveNumberOfLocalEqs() { return l_neqs; } - int giveNumberOfGlobalEqs() { return g_neqs; } + int giveNumberOfLocalEqs() override { return l_neqs; } + int giveNumberOfGlobalEqs() override { return g_neqs; } IntArray *giveN2Gmap() { return & locGlobMap; } }; @@ -140,13 +140,13 @@ class OOFEM_EXPORT Natural2LocalOrdering : public ParallelOrdering Natural2LocalOrdering(); virtual ~Natural2LocalOrdering() { } - virtual void init(EngngModel *, int di, const UnknownNumberingScheme &n); + void init(EngngModel *, int di, const UnknownNumberingScheme &n) override; - virtual int giveNewEq(int leq); - virtual int giveOldEq(int eq); + int giveNewEq(int leq) override; + int giveOldEq(int eq) override; - virtual void map2New(IntArray &answer, const IntArray &src, int baseOffset = 0); - virtual void map2Old(IntArray &answer, const IntArray &src, int baseOffset = 0); + void map2New(IntArray &answer, const IntArray &src, int baseOffset = 0) override; + void map2Old(IntArray &answer, const IntArray &src, int baseOffset = 0) override; IntArray *giveN2Lmap() { return & n2l; } }; diff --git a/src/oofemlib/pardisoprojectorgsolver.h b/src/oofemlib/pardisoprojectorgsolver.h index 8ec3a8bd8..740debb27 100644 --- a/src/oofemlib/pardisoprojectorgsolver.h +++ b/src/oofemlib/pardisoprojectorgsolver.h @@ -46,6 +46,8 @@ extern "C" void pardiso_chkvec(int *, int *, double *, int *); extern "C" void pardiso_printstats(int *, int *, double *, int *, int *, int *, double *, int *); +#define _IFT_PardisoProjectOrgSolver_Name "pardiso" + namespace oofem { /** * Implements the solution of linear system of equation in the form @f$ A\cdot x=b @f$ using solvers @@ -65,11 +67,11 @@ class OOFEM_EXPORT PardisoProjectOrgSolver : public SparseLinearSystemNM virtual ~PardisoProjectOrgSolver(); - virtual NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x); + NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x) override; - virtual const char *giveClassName() const { return "PardisoProjectOrgSolver"; } - virtual LinSystSolverType giveLinSystSolverType() const { return ST_PardisoProjectOrg; } - virtual SparseMtrxType giveRecommendedMatrix(bool symmetric) const { return SMT_CompCol; } + const char *giveClassName() const override { return "PardisoProjectOrgSolver"; } + LinSystSolverType giveLinSystSolverType() const override { return ST_PardisoProjectOrg; } + SparseMtrxType giveRecommendedMatrix(bool symmetric) const override { return SMT_CompCol; } }; } // end namespace oofem #endif // pardisoprojectorgsolver_h diff --git a/src/oofemlib/parmetisloadbalancer.h b/src/oofemlib/parmetisloadbalancer.h index 4fd4fddda..d688a7a6b 100644 --- a/src/oofemlib/parmetisloadbalancer.h +++ b/src/oofemlib/parmetisloadbalancer.h @@ -74,12 +74,12 @@ class OOFEM_EXPORT ParmetisLoadBalancer : public LoadBalancer ParmetisLoadBalancer(Domain * d); virtual ~ParmetisLoadBalancer(); - virtual void calculateLoadTransfer(); + void calculateLoadTransfer() override; #if 1 - virtual DofManMode giveDofManState(int idofman); - virtual IntArray *giveDofManPartitions(int idofman); - virtual int giveElementPartition(int ielem); + DofManMode giveDofManState(int idofman) override; + IntArray *giveDofManPartitions(int idofman) override; + int giveElementPartition(int ielem) override; #endif protected: void handleMasterSlaveDofManLinks(); @@ -102,7 +102,7 @@ class OOFEM_EXPORT ParmetisLoadBalancer : public LoadBalancer int unpackSharedDmanPartitions(ProcessCommunicator &pc); void addSharedDofmanPartitions(int _locnum, IntArray _partitions); - virtual const char *giveClassName() const { return "ParmetisLoadBalancer"; } + const char *giveClassName() const override { return "ParmetisLoadBalancer"; } }; } // end namespace oofem diff --git a/src/oofemlib/parser.C b/src/oofemlib/parser.C index d68a53d9c..d220f7fb1 100644 --- a/src/oofemlib/parser.C +++ b/src/oofemlib/parser.C @@ -96,7 +96,13 @@ double Parser :: term(bool get) // multiply and divide } OOFEM_ERROR("divide by 0"); return 1; - + case MOD: + if ( ( d = prim(true) ) ) { + left = fmod(left,d); + break; + } + OOFEM_ERROR("divide by 0"); + return 1; case POW: left = pow( left, prim(true) ); break; @@ -186,6 +192,11 @@ double Parser :: prim(bool get) // handle primaries double e = agr(true); return exp(e); } + case INT_FUNC: + { + double e = agr(true); + return (int)(e); + } case HEAVISIDE_FUNC: //Heaviside function { double time = look("t")->value; @@ -194,6 +205,13 @@ double Parser :: prim(bool get) // handle primaries return time < e ? 0 : 1; } + case HEAVISIDE_FUNC1: //Heaviside function + { + double e = agr(true); + + return e<0 ? 0 : 1; + } + default: OOFEM_ERROR("primary expected"); return 1; @@ -252,6 +270,7 @@ Parser :: Token_value Parser :: get_token() case '-': case '(': case ')': + case '%': return curr_tok = Token_value(ch); case '=': @@ -323,8 +342,12 @@ Parser :: Token_value Parser :: get_token() return curr_tok = ASIN_FUNC; } else if ( !strncmp(string_value, "acos", 4) ) { return curr_tok = ACOS_FUNC; - } else if ( !strncmp(string_value, "exp", 4) ) { + } else if ( !strncmp(string_value, "exp", 3) ) { return curr_tok = EXP_FUNC; + } else if ( !strncmp(string_value, "int", 3) ) { + return curr_tok = INT_FUNC; + } else if ( !strncmp(string_value, "h1", 2) ) { + return curr_tok = HEAVISIDE_FUNC1; } else if ( !strncmp(string_value, "h", 1) ) { return curr_tok = HEAVISIDE_FUNC; } else if ( !strncmp(string_value, "pi", 2) ) { diff --git a/src/oofemlib/parser.h b/src/oofemlib/parser.h index 6ba646a68..d5639dfe1 100644 --- a/src/oofemlib/parser.h +++ b/src/oofemlib/parser.h @@ -71,8 +71,8 @@ class OOFEM_EXPORT Parser private: enum Token_value { NAME, NUMBER, END, - SQRT_FUNC, SIN_FUNC, COS_FUNC, TAN_FUNC, ATAN_FUNC, ASIN_FUNC, ACOS_FUNC, EXP_FUNC, HEAVISIDE_FUNC, - PLUS='+', MINUS='-', MUL='*', DIV='/', POW='^', BOOL_EQ, BOOL_LE, BOOL_LT, BOOL_GE, BOOL_GT, + SQRT_FUNC, SIN_FUNC, COS_FUNC, TAN_FUNC, ATAN_FUNC, ASIN_FUNC, ACOS_FUNC, EXP_FUNC, INT_FUNC, HEAVISIDE_FUNC, HEAVISIDE_FUNC1, + PLUS='+', MINUS='-', MUL='*', DIV='/', MOD='%', POW='^', BOOL_EQ, BOOL_LE, BOOL_LT, BOOL_GE, BOOL_GT, PRINT=';', ASSIGN='=', LP='(', RP=')' }; diff --git a/src/oofemlib/particlegrid.h b/src/oofemlib/particlegrid.h deleted file mode 100644 index 2a820a5fe..000000000 --- a/src/oofemlib/particlegrid.h +++ /dev/null @@ -1,677 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#ifndef particlegrid_h -#define particlegrid_h - -#include "floatarray.h" -#include "intarray.h" -#include "mathfem.h" - -#include - -namespace oofem -{ - -template< class Point > -class ParticleGridIterator; - -/** - * Particle grid data structure for n-D grids. - * Supports local refinements through recursively implementing sub grids into points. - * @author Mikael Öhman - */ -template -class OOFEM_EXPORT ParticleGrid -{ -public: - /// List iterator type - typedef ParticleGridIterator iterator; - -protected: - /// Recursive data structure for - struct RefinedParticlePoint { - Point *point; - ParticleGrid *subgrid; - }; - - /// Number of dimensions of the grid. - int n; - /// Resolution in each dimension. - IntArray res; - /// Total grid points. - int total; - /// Bounding boxes - FloatArray bb0,bb1; - /// Grid increments. - FloatArray dx; - /// Particle data structure. - RefinedParticlePoint **data; - /// Helper for index <-> position, the cumulative product of res. - IntArray res_prod; - - /** - * Translates from n-D position to total position. - * @param pos n-D position. - * @return Total position. - */ - int giveIndex ( const IntArray &pos ) const; - /** - * Translates from total position to n-D position. - * @param pos n-D position. - * @param index Total position. - */ - void givePosition ( IntArray &pos, int index ) const; - - /** - * Initiation of structure, used by constructors. - * @param res Resolution array. - * @param bb0 Lower bounding box. - * @param bb1 Upper bounding box. - */ - void init ( const IntArray &res, const FloatArray &bb0, const FloatArray &bb1 ); - -public: - /** - * Creates a new empty particle grid - * @param res Resolution in respective direction. - * @param bb0 Lower corner of bounding box. - * @param bb1 Upper corner of bounding box. - */ - ParticleGrid ( const IntArray &res, const FloatArray &bb0, const FloatArray &bb1 ); - /** - * Copies structure of old particle grid, but no content. - * @param old ParticleGrid to copy. - */ - ParticleGrid ( const ParticleGrid *old ); - /// Destructor. - ~ParticleGrid(); - - /// Returns Number of dimensions of grid. - int giveDimensions() { - return n; - } - /// Total number potential points. - int getTotal() const { - return this->total; - } - /// Number of active points. - int getNumberOfPoints() const; - /// Returns true if the entire grid is empty. - bool isEmpty() const; - /// Returns an iterator over the entire grid (with subgrids) - iterator begin(); - /// Returns an iterator over specified region. - iterator beginAt ( const FloatArray &x0, const FloatArray &x1 ); - - /** - * Returns the resolution in given dimension. - * @param i Index of dimension. - * @return Resolution in dimension i. - */ - int getResolution ( int i ) { - return this->res ( i ); - } - /** - * Returns the grid increment. - * @param i Index of dimension. - * @return Grid step in dimension i. - */ - double getGridStep ( int i ) const { - return this->dx ( i ); - } - - /** - * Gives the real coordinates for the given identifier. - * @param[out] answer The coordinate vector. - * @param[in] pos Position for the grid point. - */ - void getGridCoord ( FloatArray &answer, const IntArray &pos ) const; - /** - * Gives the real coordinates for the given identifier. - * @param[out] answer The coordinate vector. - * @param[in] ind Identifier for the grid point. - */ - void getGridCoord ( FloatArray &answer, int ind ) const; - - /** - * Gives the point at the position. - * @param[out] answer The point as requested position - * @param[in] pos The requested position - * @return true if point is active, otherwise false - */ - bool getPoint ( Point *&answer, const IntArray &pos ) const; - bool getPoint ( Point *&answer, int ind ) const; - - /** - * Gives the sub-grid at the position. - * @param[out] subgrid Requested sub-grid. - * @param[in] pos Position. - * @return true if sub-grid is active, otherwise false. - */ - bool getSubGrid ( ParticleGrid *&subgrid, const IntArray &pos ) const; - bool getSubGrid ( ParticleGrid *&subgrid, int ind ) const; - - /** - * Creates a 2 by 2 sub-grid at the given position. - * Any existing point or sub-grid is deleted. - * @param[out] subgrid Newly created sub-grid. - * @param[in] res Resolution of new sub-grid. - * @param[in] pos Position of sub-grid. - */ - void createSubGrid ( ParticleGrid *&subgrid, const IntArray &res, const IntArray &pos ); - - /** - * Sets a point in the grid. Deletes any preexisting data. - * @param[in] point Point to set at position pos. - * @param[in] pos Position. - */ - void setPoint ( Point *point, const IntArray &pos ); - void setPoint ( Point *point, int ind ); - - /** - * Deletes any preexisting data at position. - * @param[in] pos Position to clear. - */ - void clearPosition ( const IntArray &pos ); - void clearPosition ( int ind ); - - void getPointsWithin ( std::list &answer, const FloatArray &x0, const FloatArray &x1 ); - void appendAllPoints ( std::list &answer ); - - /** - * Finds the indices [ind0, ind1) of the bounding box [x0,x1). - * @param[in] x0 Lower limit of box. - * @param[in] x1 Upper limit of box. - * @param[out] ind0 Lower index corresponding to x0. - * @param[out] ind1 Upper index - */ - void getBoundingBox ( const FloatArray &x0, const FloatArray &x1, IntArray &ind0, IntArray &ind1 ) const; - - /** - * Finds the position closest to coordinate x. - * @param[in] x Coordinate. - * @param[out] pos Position of closest grid point. - */ - void getPosition ( const FloatArray &x, IntArray &pos ) const; - - std :: string errorInfo(const char *func) const { return std :: string("ParticleGrid :: ") + func; } - - friend class ParticleGridIterator; -}; - -template -ParticleGrid :: ParticleGrid ( const IntArray &res, const FloatArray &bb0, const FloatArray &bb1 ) -{ - this->init ( res, bb0, bb1 ); -} - -template -ParticleGrid :: ParticleGrid ( const ParticleGrid *old ) -{ - this->init ( old->res, old->bb0, old->bb1 ); -} - -template -void ParticleGrid :: init ( const IntArray &res, const FloatArray &bb0, const FloatArray &bb1 ) -{ - this->res = res; - this->bb0 = bb0; - this->bb1 = bb1; - - this->n = this->res.giveSize(); - this->dx.resize ( this->n ); - this->total = 1; - this->res_prod.resize ( this->n ); - this->res_prod ( 0 ) = 1; - - for ( int i = 0; i < this->n; ++i ) { - this->dx ( i ) = ( this->bb1 ( i ) - this->bb0 ( i ) ) / ( this->res ( i )-1 ); - - this->total *= this->res ( i ); - - this->res_prod ( i ) = 1; - for ( int j = 0; j < i; ++j ) { - this->res_prod ( i ) *= this->res ( j ); - } - } - - this->data = new RefinedParticlePoint*[this->total]; - for ( int i = 0; i < this->total; ++i ) { - this->data[i] = NULL; - } -} - -template -ParticleGrid :: ~ParticleGrid() -{ - // Clear all points - for ( int i = 0; i < this->total; ++i ) { - this->clearPosition ( i ); - } - delete[] this->data; -} - -template -int ParticleGrid :: getNumberOfPoints() const -{ - RefinedParticlePoint *p; - int c = 0; - for ( int i = 0; i < this->total; ++i ) { - p = this->data[i]; - if ( p ) { - if ( p->point ) { - c += 1; - } else if ( p->subgrid ) { - c += p->subgrid->getNumberOfPoints(); - } - } - } - return c; -} - -template -bool ParticleGrid :: isEmpty() const -{ - RefinedParticlePoint *p; - for ( int i = 0; i < this->total; ++i ) { - p = this->data[i]; - if ( p ) { - if ( p->point ) { - return false; - } else if ( p->subgrid ) { - if ( !p->subgrid->isEmpty() ) { - return false; - } - } - } - } - return true; -} - -template -int ParticleGrid :: giveIndex ( const IntArray &pos ) const -{ - int index = 0; - for ( int i = 0; i < this->n; ++i ) { - index += this->res_prod ( i ) *pos ( i ); - } - return index; -} - -template -void ParticleGrid :: givePosition ( IntArray &pos, int index ) const -{ - pos.resize ( this->n ); - for ( int i = 0; i < this->n; ++i ) { - pos ( i ) = ( index/res_prod ( i ) ) % res ( i ); - } -} - -template -void ParticleGrid :: getGridCoord ( FloatArray &answer, const IntArray &pos ) const -{ - answer.resize ( this->n ); - for ( int i = 0; i < this->n; ++i ) { - answer ( i ) = pos ( i ) *this->dx ( i ) + this->bb0 ( i ); - } -} - -template -void ParticleGrid :: getGridCoord ( FloatArray &answer, int ind ) const -{ - IntArray pos; - this->givePosition ( pos, ind ); - this->getGridCoord ( answer, pos ); -} - -template -void ParticleGrid :: getBoundingBox ( const FloatArray &x0, const FloatArray &x1, IntArray &ind0, IntArray &ind1 ) const -{ - ind0.resize ( this->n ); - ind1.resize ( this->n ); - for ( int i = 0; i < this->n; ++i ) { - ind0 ( i ) = max ( ( int ) floor ( ( x0 ( i ) - this->bb0 ( i ) ) /this->dx ( i ) ), 0 ); - ind1 ( i ) = min ( ( int ) ceil ( ( x1 ( i ) - this->bb0 ( i ) ) /this->dx ( i ) ), this->res ( i ) ); - } -} - -template -void ParticleGrid :: getPosition ( const FloatArray &x, IntArray &pos ) const -{ - pos.resize ( this->n ); - for ( int i = 0; i < this->n; ++i ) { - //pos(i) = (int)nearest((x(i) - this->bb0(i))/this->dx(i)); - pos ( i ) = ( int ) floor ( ( x ( i ) - this->bb0 ( i ) ) /this->dx ( i ) + 0.5 ); - pos ( i ) = min ( max ( pos ( i ),0 ),this->res ( i )-1 ); - } -} - -template -typename ParticleGrid::iterator ParticleGrid :: begin() -{ - iterator it ( this ); - return it; -} - -template -typename ParticleGrid::iterator ParticleGrid :: beginAt ( const FloatArray &x0, const FloatArray &x1 ) -{ - IntArray ind0, ind1; - this->getBoundingBox ( x0, x1, ind0, ind1 ); - iterator it ( this, ind0, ind1 ); - return it; -} - -template -void ParticleGrid :: getPointsWithin ( std::list &answer, const FloatArray &x0, const FloatArray &x1 ) -{ - answer.clear(); - - // First find a suitable bounding box of positions (note: this isn't perfect in regards to sub grids) - IntArray p0, p1; - this->getBoundingBox ( x0, x1, p0, p1 ); - - // Get all grid points in that region - IntArray p ( this->n ); - if ( this->n == 2 ) { - for ( int x = p0 ( 0 ); x < p1 ( 0 ); x++ ) { - p ( 0 ) = x; - for ( int y = p0 ( 1 ); y < p1 ( 1 ); y++ ) { - p ( 1 ) = y; - RefinedParticlePoint *rp = this->data[this->giveIndex ( p )]; - if ( rp ) { - if ( rp->subgrid ) { - rp->subgrid->appendAllPoints ( answer ); - } else { - answer.push_front ( rp->point ); - } - } - } - } - } else if ( this->n == 3 ) { - OOFEM_ERROR ( "3D grids not implemented yet" ); - } -} - -template -void ParticleGrid :: appendAllPoints ( std::list &answer ) -{ - for ( int i = 0; i < this->total; ++i ) { - RefinedParticlePoint *rp = this->data[i]; - if ( rp ) { - if ( rp->subgrid ) { - rp->subgrid->appendAllPoints ( answer ); - } else if ( rp->point ) { - answer.push_front ( rp->point ); - } else { - OOFEM_ERROR ( "Refined particle does not contain subgrid or point." ); - } - } - } -} - -template -bool ParticleGrid :: getPoint ( Point *&answer, const IntArray &pos ) const -{ - return this->getPoint ( answer, this->giveIndex ( pos ) ); -} - -template -void ParticleGrid :: setPoint ( Point *point, const IntArray &pos ) -{ - this->setPoint ( point, this->giveIndex ( pos ) ); -} - -template -bool ParticleGrid :: getPoint ( Point *&answer, int ind ) const -{ - RefinedParticlePoint *rp = this->data[ind]; - if ( rp == NULL ) { // Not active - answer = NULL; - return false; - } else { - if ( rp->point ) { // Active and has a point - answer = rp->point; - return true; - } else { // Active and has a sub grid - answer = NULL; - return false; - } - } -} - -template -void ParticleGrid :: setPoint ( Point *point, int ind ) -{ - this->clearPosition ( ind ); - this->data[ind] = new RefinedParticlePoint; - this->data[ind]->point = point; - this->data[ind]->subgrid = NULL; -} - -template -void ParticleGrid :: clearPosition ( const IntArray &pos ) -{ - return this->clearPosition ( this->giveIndex ( pos ) ); -} - -template -void ParticleGrid :: clearPosition ( int ind ) -{ - RefinedParticlePoint *rp = this->data[ind]; - if ( rp ) { - if ( rp->point ) { - delete rp->point; - } - if ( rp->subgrid ) { - delete rp->subgrid; - } - delete rp; - } - this->data[ind] = NULL; -} - -template -bool ParticleGrid :: getSubGrid ( ParticleGrid *&subgrid, int ind ) const -{ - RefinedParticlePoint *rp = this->data[ind]; - if ( rp == NULL ) { - subgrid = NULL; - return false; - } else { - if ( rp->subgrid ) { - subgrid = rp->subgrid; - return true; - } else { - subgrid = NULL; - return false; - } - } -} - -template -bool ParticleGrid :: getSubGrid ( ParticleGrid *&subgrid, const IntArray &pos ) const -{ - return this->getSubGrid ( subgrid, this->giveIndex ( pos ) ); -} - -template -void ParticleGrid :: createSubGrid ( ParticleGrid *&subgrid, const IntArray &res, const IntArray &pos ) -{ - // The bounding boxes for the sub domains. - FloatArray grid_point; - this->getGridCoord ( grid_point, pos ); - FloatArray sub_bb0, sub_bb1; - sub_bb0 = grid_point; - sub_bb0.add ( -0.5, dx ); - sub_bb1 = grid_point; - sub_bb1.add ( 0.5, dx ); - subgrid = new ParticleGrid ( res, sub_bb0, sub_bb1 ); - - int ind = this->giveIndex ( pos ); - this->clearPosition ( ind ); - this->data[ind] = new RefinedParticlePoint; - this->data[ind]->point = NULL; - this->data[ind]->subgrid = subgrid; -} - -/** - * A recursive iterator for a grid with refinements. - */ -template -class ParticleGridIterator -{ -protected: - int index, endind; - ParticleGridIterator *sub_it; - ParticleGrid *grid; - - IntArray pos; - const IntArray ind0, ind1; - bool limited; - -public: - /// Constructor. - ParticleGridIterator() : - index ( 0 ), endind ( 0 ), sub_it ( NULL ), grid ( NULL ), ind0(), ind1(), limited ( false ) {} - /// Constructor. - ParticleGridIterator ( ParticleGrid *g ) : - index ( 0 ), endind ( g->total ), sub_it ( NULL ), grid ( g ), ind0(), ind1(), limited ( false ) { - if ( this->grid->data[this->index] && this->grid->data[this->index]->subgrid ) { - this->sub_it = new ParticleGridIterator ( this->grid->data[this->index]->subgrid ); - } - } - /// Constructor. - ParticleGridIterator ( ParticleGrid *g, IntArray ind0, IntArray ind1 ) : - index ( 0 ), sub_it ( NULL ), grid ( g ), ind0 ( ind0 ), ind1 ( ind1 ), limited ( true ) { - IntArray end = ind1; - end.add ( -1 ); - this->endind = this->grid->giveIndex ( end ) + 1; - this->pos = ind0; - this->index = this->grid->giveIndex ( ind0 ); - if ( this->grid->data[this->index] && this->grid->data[this->index]->subgrid ) { - this->sub_it = new ParticleGridIterator ( this->grid->data[this->index]->subgrid ); - } - } - /// Copy constructor. - ParticleGridIterator ( const ParticleGridIterator &x ) : - index ( x.index ), sub_it ( x.sub_it ), grid ( x.grid ), ind0 ( x.ind0 ), ind1 ( x.ind1 ), limited ( x.limited ) { } - /// Destructor - ~ParticleGridIterator() { - if ( this->sub_it ) { - delete sub_it; - } - } - - bool end() const { - return this->index >= this->endind; - } - - Point *getPoint() { - if ( this->end() ) { - return NULL; - } - if ( this->subGridActive() ) { - return this->sub_it->getPoint(); - } - if ( this->grid->data[this->index] != NULL ) { - return this->grid->data[this->index]->point; - } - return NULL; - } - - int getIndex() { - return this->index; - } - - void setPoint ( Point *p ) { - if ( this->end() ) { - OOFEM_ERROR ( "Can't set element in outside grid" ); - } - if ( this->subGridActive() ) { - this->sub_it->setPoint ( p ); - } - this->grid->setPoint ( p, this->index ); - } - - bool subGridActive() const { - return this->sub_it != NULL; - } - - void getGridPoint ( FloatArray &x ) { - if ( this->subGridActive() ) { - this->sub_it->getGridPoint ( x ); - } else { - this->grid->getGridCoord ( x, this->index ); - } - } - - /// Lets the iterator step forward to the next element. - void operator++() { - if ( this->subGridActive() ) { - this->sub_it++; - if ( !this->sub_it->end() ) { - return; - } else { - delete this->sub_it; - this->sub_it = NULL; - } - } - this->index++; - if ( this->limited ) { - this->pos ( 0 ) ++; - for ( int i = 0; i < this->pos.giveSize() - 1; ++i ) { - if ( this->pos ( i ) >= this->ind1 ( i ) ) { - this->pos ( i ) = this->ind0 ( i ); - this->pos ( i+1 ) ++; - } else { - break; - } - } - index = this->grid->giveIndex ( pos ); - } - if ( !this->end() && this->grid->data[this->index] && this->grid->data[this->index]->subgrid ) { - this->sub_it = new ParticleGridIterator ( this->grid->data[this->index]->subgrid ); - } - } - - std :: string errorInfo(const char *func) const { return std :: string("ParticleGridIterator :: ") + func; } - - friend class ParticleGrid; -}; - -} // end namespace oofem -#endif // particlegrid_h diff --git a/src/oofemlib/particletopologydescription.C b/src/oofemlib/particletopologydescription.C deleted file mode 100644 index d7976842f..000000000 --- a/src/oofemlib/particletopologydescription.C +++ /dev/null @@ -1,1319 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "particletopologydescription.h" -#include "timestep.h" -#include "dofiditem.h" -#include "spatiallocalizer.h" -#include "mathfem.h" -#include "trianglemesherinterface.h" -#include "topologydescription.h" -#include "particlegrid.h" -#include "datareader.h" -#include "element.h" -#include "timer.h" -#include "classfactory.h" -#include "engngm.h" - -#include "mixedgradientpressureneumann.h" -#include "node.h" -#include "activebc.h" -#include "activedof.h" -#include "masterdof.h" -#include "set.h" - -#include -#include -#include -#include - -#ifdef __VTK_MODULE - #include - #include - #include - #include - #include - #include - #include - #include - #include -#endif - -namespace oofem -{ -REGISTER_TopologyDescription(ParticleTopologyDescription); - -ParticleTopologyDescription :: ParticleTopologyDescription(Domain *d) : TopologyDescription(d), resampled(false), maxdisp2(0) -{} - -ParticleTopologyDescription :: ~ParticleTopologyDescription() -{ - if ( this->corners.size() ) { - this->corners.clear(); - } -} - -bool ParticleTopologyDescription :: instanciateYourself(DataReader *dr) -{ - // Required by IR_GIVE_FIELD macro - IRResultType result; - InputRecord *ir; - std :: string name; - int num; - - int res, nsd; - double tubewidth; - IntArray resolution; - FloatArray bb0, bb1; - // Input for geometry types - FloatArray x0, x1, center; - double radius, alpha0, alpha1; - int id, nsegments; - - // Read topology description - ir = dr->giveInputRecord(DataReader :: IR_gbpmRec, 1); - IR_GIVE_FIELD(ir, nsd, _IFT_ParticleTopologyDescription_nsd); - IR_GIVE_FIELD(ir, res, _IFT_ParticleTopologyDescription_baseResolution); - IR_GIVE_FIELD(ir, bb0, _IFT_ParticleTopologyDescription_boundingBoxA); - IR_GIVE_FIELD(ir, bb1, _IFT_ParticleTopologyDescription_boundingBoxB); - IR_GIVE_FIELD(ir, nsegments, _IFT_ParticleTopologyDescription_numberOfSegments); - tubewidth = 1.1; - IR_GIVE_OPTIONAL_FIELD(ir, tubewidth, _IFT_ParticleTopologyDescription_tubeWidth); - IR_GIVE_FIELD(ir, this->m, _IFT_ParticleTopologyDescription_neighbors); - - resolution.resize(nsd); - resolution.zero(); - resolution.add(res); - - // Mappings - IR_GIVE_OPTIONAL_FIELD(ir, this->regionInside, _IFT_ParticleTopologyDescription_regionInside); - IR_GIVE_OPTIONAL_FIELD(ir, this->regionOutside, _IFT_ParticleTopologyDescription_regionOutside); - IR_GIVE_OPTIONAL_FIELD(ir, this->regionElementType, _IFT_Meshing_elementType); - IR_GIVE_OPTIONAL_FIELD(ir, this->regionSet, _IFT_Meshing_set); - - /// @todo Merging surfaces and such. - int n = this->regionInside.giveSize(); - this->controlID.resize(n, n); - this->mergeID.resize(n, n); - - this->tubeWidth = ( bb1(0) - bb0(0) ) / res * tubewidth; - - this->grid.reset( new ParticleGrid< ParticlePoint >(resolution, bb0, bb1) ); - - for ( int i = 1; i <= nsegments; i++ ) { - ir = dr->giveInputRecord(DataReader :: IR_geometryRec, i); - IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num); - IR_GIVE_FIELD(ir, id, _IFT_ParticleTopologyDescription_identification); - if ( name.compare("line") == 0 ) { - IR_GIVE_FIELD(ir, x0, _IFT_Line_start); - IR_GIVE_FIELD(ir, x1, _IFT_Line_end); - this->addLineSegment(id, x0, x1, *this->grid); - } else if ( name.compare("circle") == 0 ) { - IR_GIVE_FIELD(ir, center, _IFT_Circle_center); - IR_GIVE_FIELD(ir, radius, _IFT_Circle_radius); - alpha0 = -180; - alpha1 = 180; - IR_GIVE_OPTIONAL_FIELD(ir, alpha0, _IFT_Circle_start); - IR_GIVE_OPTIONAL_FIELD(ir, alpha1, _IFT_Circle_end); - alpha0 *= M_PI / 180; - alpha1 *= M_PI / 180; - this->addCircleSegment(id, center, radius, alpha0, alpha1, *this->grid); - } else if ( name.compare("cornerpoint") == 0 ) { - IR_GIVE_FIELD(ir, center, _IFT_Point_coords); - this->addCorner(id, center, *this->grid); - } else { - OOFEM_ERROR( "Unknown geometry type '%s'", name.c_str() ); - } - ir->finish(); - } - - this->checkOverlap(); - -#ifdef DEBUG - // this->writeVTKFile("initial_particle.vtp"); -#endif - /// @todo User input. - this->writeVTK = false; - return true; -} - -void ParticleTopologyDescription :: addLineSegment(int id, const FloatArray &p0, const FloatArray &p1, ParticleGrid< ParticlePoint > &g) const -{ - ParticlePoint *point; - double tubeWidth2 = this->tubeWidth * this->tubeWidth; - double distance2, xi; - double line_length; - FloatArray v, new_normal(2), grid_p, new_foot, grid_p_v1; - v.beDifferenceOf(p1, p0); - line_length = v.computeNorm(); - v.times(1 / line_length); // v is the directional vector along the line. - new_normal(0) = -v(1); - new_normal(1) = v(0); - - // Find the bounding box for the segment - FloatArray x0, x1; - x0.beMinOf(p0, p1); - x0.add(-this->tubeWidth); - x1.beMaxOf(p0, p1); - x1.add(this->tubeWidth); - - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->beginAt(x0, x1); !it.end(); ++it ) { - it.getGridPoint(grid_p); - // Find closest point on line, parameterized by xi - grid_p_v1.beDifferenceOf(grid_p, p0); - xi = grid_p_v1.dotProduct(v) / line_length; - if ( xi < 0 || xi > 1 ) { - continue; - } - - // And it's coordinate - new_foot = p0; - new_foot.add(xi * line_length, v); - - distance2 = grid_p.distance_square(new_foot); - - if ( distance2 < tubeWidth2 ) { - if ( ( point = it.getPoint() ) ) { - if ( point->distance2 <= distance2 ) { - continue; // If distance already is smaller, then skip this. - } - } - point = new ParticlePoint(new_foot, id, new_normal, distance2); - it.setPoint(point); - } - } -} - -void ParticleTopologyDescription :: addCircleSegment(int id, const FloatArray &c, double r, double v0, double v1, - ParticleGrid< ParticlePoint > &g) const -{ - ParticlePoint *point; - FloatArray new_foot(2), new_normal(2), grid_p; - double distance2, tubeWidth2 = this->tubeWidth * this->tubeWidth; - - // Find the bounding box for the segment - FloatArray x0, x1; - this->getBoundingBox(x0, x1, c, r + this->tubeWidth); - - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->beginAt(x0, x1); !it.end(); ++it ) { - it.getGridPoint(grid_p); - - double v = atan2( grid_p(1) - c(1), grid_p(0) - c(0) ); - if ( v < v0 || v > v1 ) { - continue; - } - - new_normal(0) = cos(v); - new_normal(1) = sin(v); - new_foot(0) = c(0) + cos(v) * r; - new_foot(1) = c(1) + sin(v) * r; - - distance2 = grid_p.distance_square(new_foot); - - if ( distance2 < tubeWidth2 ) { - if ( ( point = it.getPoint() ) ) { - if ( point->distance2 <= distance2 ) { - continue; // If distance already is smaller, then skip this. - } - } - point = new ParticlePoint(new_foot, id, new_normal, distance2); - it.setPoint(point); - } - } -} - -void ParticleTopologyDescription :: addCorner(int id, const FloatArray &c, ParticleGrid< ParticlePoint > &grid) -{ - /// @todo Remove this structure. - ParticlePoint corner; - corner.id = id; - corner.foot = c; - this->corners.push_front(corner); - - ParticlePoint *point; - // Find the bounding box for the segment - FloatArray x0, x1; - this->getBoundingBox(x0, x1, c, this->tubeWidth); - - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->beginAt(x0, x1); !it.end(); ++it ) { - if ( ( point = it.getPoint() ) ) { - if ( point->id == id ) { - if ( point->corner.giveSize() < 0 || point->foot.distance_square(point->corner) > point->foot.distance_square(c) ) { - point->corner = c; - } - } - } - } -} - -TopologyState ParticleTopologyDescription :: updateYourself(TimeStep *tStep) -{ - Timer timer; - timer.startTimer(); - - TopologyState ts = TS_OK; - - FloatArray displacement, grid_coord; - ParticlePoint *p; - this->maxdisp2 = 0; // Determines whether grid should be resampled. - - // Update all foot points - this->d->giveSpatialLocalizer()->init(true); // For SL we need to update every time step. - - this->resampled = false; - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->begin(); !it.end(); ++it ) { - if ( ( p = it.getPoint() ) != NULL ) { - bool state = this->findDisplacement(displacement, p->id, p->foot, tStep); - if ( state ) { - p->foot.add(displacement); - p->total_displacement.add(displacement); - this->maxdisp2 = max( this->maxdisp2, p->total_displacement.computeSquaredNorm() ); - -#if 0 - if ( p->corner.giveSize() > 0 ) { - this->findDisplacement(displacement, p->id, p->foot, tStep); - p->foot.add(displacement); - p->total_displacement.add(displacement); - this->maxdisp2 = max( this->maxdisp2, p->total_displacement.computeSquaredNorm() ); - } -#endif - } else { // Can't find a suitable element to interpolate from, then just drop the point. - grid->clearPosition( it.getIndex() ); - } - } - } - - // Remove this -#if 1 - for ( std :: list< ParticlePoint > :: iterator it = this->corners.begin(); it != this->corners.end(); ++it ) { - bool state = this->findDisplacement(displacement, it->id, it->foot, tStep); - if ( !state ) { - OOFEM_ERROR("This always needs to find a displacement"); - } - it->foot.add(displacement); - it->total_displacement.add(displacement); - } -#endif - - ts = this->checkOverlap(); - if ( ts != TS_OK || this->maxdisp2 > this->tubeWidth * this->tubeWidth ) { - OOFEM_LOG_INFO("ParticleTopologyDescription :: updateYourself - Resampling\n"); - this->resample(); - } - - timer.stopTimer(); - OOFEM_LOG_INFO( "ParticleTopologyDescription: user time consumed by updating: %.2fs\n", timer.getUtime() ); - - return ts; -} - - -TopologyState ParticleTopologyDescription :: checkOverlap() -{ - TopologyState ts = TS_OK; - FloatArray x0, x1; - std :: list< ParticlePoint * >points; - ParticlePoint *p0; - FloatArray p0p1; - double normal_limit = 0.5, distance_limit = 0.0; // Very lenient requirement... - distance_limit = this->tubeWidth / 2; - - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->begin(); !it.end(); ++it ) { - if ( ( p0 = it.getPoint() ) != NULL && p0->id > 0 ) { - // Use either total distance or the local? - this->getBoundingBox(x0, x1, p0->foot, this->tubeWidth + 2 * p0->total_displacement.computeNorm() + distance_limit); - this->grid->getPointsWithin(points, x0, x1); - - std :: list< ParticlePoint * > :: iterator it_points; - for ( it_points = points.begin(); it_points != points.end(); it_points++ ) { - ParticlePoint *p1 = * it_points; - if ( p1->id == p0->id ) { // For same surfaces, just merge them - if ( p1->normal.dotProduct(p0->normal) < normal_limit ) { - p0p1.beDifferenceOf(p1->foot, p0->foot); - // TODO: Is this a good criteria? - //if (p0->normal.dotProduct(p0p1) < distance_limit ) { - if ( p0p1.computeNorm() < distance_limit ) { - // Mark both for removal. - p0->removal = true; - p1->removal = true; - //ts = TS_NeedsRemeshing; - } - } - } - // This part turned out to be incredibly difficult; Merging of different surfaces (creating a new one, with end points accordingly). -#if 0 - else { - double distance = p0->foot.distance_square(p1->foot); - if ( distance < distance_limit ) { - if ( p0->corner.giveSize() > 0 && distance < p0->foot.distance_square(p0->corner) ) { - p0->removal = true; - p1->removal = true; - } else { - OOFEM_ERROR("Conditions for merging surface not implemented yet."); - // Not this simple, but something along these lines... - int newpid = ( int ) this->mergeID.at(p0->id, p1->id); - int control = ( int ) this->controlID.at(p0->id, p1->id); - if ( p0->id == control ) { - p0->id = newpid; - p1->removal = true; - } else { - p1->id = newpid; - p0->removal = true; - } - ts = TS_NeedsRemeshing; - } - } - } -#endif - } - } - } - - this->removePoints(*this->grid); - return ts; -} - -void ParticleTopologyDescription :: removePoints(ParticleGrid< ParticlePoint > &g) const -{ - ParticlePoint *p; - FloatArray grid_coord; - ParticleGrid< ParticlePoint > *sg; - - for ( int ind = 0; ind < g.getTotal(); ind++ ) { - if ( g.getPoint(p, ind) ) { - if ( p->removal ) { - g.clearPosition(ind); - } - } else if ( this->grid->getSubGrid(sg, ind) ) { - this->removePoints(*sg); - // If all subpoint were removed, then remove the whole grid. - if ( sg->isEmpty() ) { - sg->clearPosition(ind); - } - } - } -} - -void ParticleTopologyDescription :: calculateShortestDistance(const ParticlePoint *p0, std :: list< ParticlePoint * > &neighbors, ParticleGrid< ParticlePoint > &g) const -// This routine is the most complicated one, and it's no unique in it's possible design. -// Current implementation does -// 1. Curve fit a second order polynomial -// 2. Calculate new shortest distances. -{ - int n = neighbors.size(); - FloatArray a; // Coefficients for the polynomial - FloatArray tfooti; // Foot origin and mapped foot point. - FloatArray temp; - FloatArray normal; - - // The matrix representing the mapping to the normal space. - FloatMatrix N; - - normal = p0->normal; - for ( std :: list< ParticlePoint * > :: iterator it = neighbors.begin(); it != neighbors.end(); ++it ) { - normal.add( ( * it )->normal ); - } - normal.normalize(); - N.beLocalCoordSys(normal); - - // The limits of txi - double txi_min = 0, txi_max = 0; - - FloatArray tx(n + 1), ty(n + 1); - tx(0) = ty(0) = 0; // Center point - int i = 1; - for ( std :: list< ParticlePoint * > :: iterator it = neighbors.begin(); it != neighbors.end(); ++it, ++i ) { - // Calculate foot points in local coord.sys. - temp.beDifferenceOf( ( * it )->foot, p0->foot ); - tfooti.beProductOf(N, temp); - tx(i) = tfooti(0); - ty(i) = tfooti(1); - if ( tx(i) < txi_min ) { - txi_min = tx(i); - } else if ( tx(i) > txi_max ) { - txi_max = tx(i); - } - } - ls2fit(tx, ty, a); - - FloatArray x0, x1; - IntArray ind0, ind1; - double radius = this->tubeWidth + max(txi_max, -txi_min); - this->getBoundingBox(x0, x1, p0->foot, radius); - g.getBoundingBox(x0, x1, ind0, ind1); - double tubeWidth2 = this->tubeWidth * this->tubeWidth; - FloatArray new_foot, new_normal; - - double distance2; - ParticlePoint *point; - ParticleGrid< ParticlePoint > *subgrid; - FloatArray grid_point; - IntArray pos(2); - /// @todo Adaptivity - for ( pos(0) = ind0(0); pos(0) < ind1(0); pos(0)++ ) { - for ( pos(1) = ind0(1); pos(1) < ind1(1); pos(1)++ ) { - g.getGridCoord(grid_point, pos); - if ( grid_point.distance_square(p0->foot) > radius * radius ) { // Quick optimization (might give false negatives, but that is acceptable.) - continue; - } - - // Find the closest foot point - distance2 = this->shortestDistanceFromCurve(a, txi_min, txi_max, normal, p0->foot, - grid_point, new_foot, new_normal); - - if ( distance2 < tubeWidth2 ) { // Otherwise we ignore it - if ( g.getPoint(point, pos) ) { - if ( point->distance2 < distance2 ) { - continue; - } - } else if ( g.getSubGrid(subgrid, pos) ) { - OOFEM_ERROR("Not implemented"); - } - point = new ParticlePoint(new_foot, p0->id, new_normal, distance2); - g.setPoint(point, pos); - } - } - } -} - -double ParticleTopologyDescription :: shortestDistanceFromCurve(const FloatArray &a, double txi_min, double txi_max, - const FloatArray &n0, const FloatArray &y0, const FloatArray &p, FloatArray &foot, FloatArray &normal) const -{ - double b3, b2, b1, b0; // Coefficients for the polynomial - double temp1, temp2; - FloatArray p_y0(2), t0(2); - - // Tangent - t0(0) = n0(1); - t0(1) = -n0(0); - - p_y0(0) = y0(0) - p(0); - p_y0(1) = y0(1) - p(1); - - p_y0.beDifferenceOf(y0, p); - temp1 = n0(0) * p_y0(0) + n0(1) * p_y0(1); //n0.dotProduct(p_y0); - temp2 = t0(0) * p_y0(0) + t0(1) * p_y0(1); //t0.dotProduct(p_y0); - - // Same as [1] - b3 = 2 * a(2) * a(2); - b2 = 3 * a(1) * a(2); - // Last terms with "tempX" missing in article [1] - b1 = a(1) * a(1) + 2 * a(0) * a(2) + 1 + 2 * a(2) * temp1; - b0 = a(0) * a(1) + a(1) * temp1 + temp2; - - // Find the roots - int roots; - double r [ 3 ] = { - 0, 0, 0 - }; - cubic(b3, b2, b1, b0, & r [ 0 ], & r [ 1 ], & r [ 2 ], & roots); - // The potential points - double limit = 0.6; // Found to be absolutely necessary for stability of surfaces when corner cases are included. - double txi_list [ 5 ] = { - txi_min *limit, txi_max * limit - }; - int points = 0; - for ( int i = 0; i < roots; i++ ) { - if ( txi_min * limit < r [ i ] && r [ i ] < txi_max * limit ) { - txi_list [ points ] = r [ i ]; - points++; - } - } - - // Normal and foot point in mapped domain (thus the t-prefix) - double min_distance2 = 0.0, min_txi = 0.0; - double dx, dy, distance2, f, fp, txi; - for ( int i = 0; i < points; i++ ) { - txi = txi_list [ i ]; - f = a(0) + a(1) * txi + a(2) * txi * txi; - - dx = n0(0) * f + t0(0) * txi + p_y0(0); - dy = n0(1) * f + t0(1) * txi + p_y0(1); - - distance2 = dx * dx + dy * dy; - - if ( i == 0 || distance2 < min_distance2 ) { - min_distance2 = distance2; - min_txi = txi; - } - } - - if ( min_txi < txi_min || min_txi > txi_max ) { - return 2 * this->tubeWidth * this->tubeWidth; - } - - f = a(0) + a(1) * min_txi + a(2) * min_txi * min_txi; - fp = a(1) + 2 * a(2) * min_txi; - - foot.resize(2); - foot(0) = n0(0) * f + t0(0) * min_txi + y0(0); - foot(1) = n0(1) * f + t0(1) * min_txi + y0(1); - - normal.resize(2); - normal(0) = n0(0) + t0(0) * ( -fp ); - normal(1) = n0(1) + t0(1) * ( -fp ); - normal.normalize(); - - return foot.distance_square(p); -} - -void ParticleTopologyDescription :: resample() -// Copy structure from old grid for a new resampled grid. -{ - if ( this->resampled ) { - return; - } - std :: list< ParticlePoint * >neighbours; - ParticlePoint *origin; - FloatArray grid0; - FloatArray new_foot, new_normal; - std :: unique_ptr< ParticleGrid< ParticlePoint > > new_grid( new ParticleGrid< ParticlePoint >(this->grid.get()) ); - - double maxdisp = sqrt(this->maxdisp2); - int total_points = 0; - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->begin(); !it.end(); ++it ) { - total_points++; - if ( ( origin = it.getPoint() ) != NULL ) { - this->collectNeighbors(neighbours, origin, maxdisp); - this->calculateShortestDistance(origin, neighbours, *new_grid); - } - } - - this->grid = std :: move( new_grid ); - this->resampled = true; -} - -void ParticleTopologyDescription :: getBoundingBox(FloatArray &x0, FloatArray &x1, const FloatArray &c, double width) -{ - x0 = c; - x0.add(-width); - x1 = c; - x1.add(width); -} - -// Helper to sort the pairs -static bool compare_second(std :: pair< ParticlePoint *, double >a, std :: pair< ParticlePoint *, double >b) -{ - return fabs(a.second) < fabs(b.second); -} - -void ParticleTopologyDescription :: collectNeighbors(std :: list< ParticlePoint * > &answer, const ParticlePoint *origin, double dist) const -{ - answer.clear(); - - FloatArray temp; - FloatArray lcoord; - FloatMatrix toLocalCoord; - - toLocalCoord.beLocalCoordSys(origin->normal); - - // The algorithm uses a large bounding box, which should incorporate at least n points for well formed input. - std :: list< ParticlePoint * >points; - - // Bounding box around grid point and collect all the potential points. - FloatArray x0, x1; - this->getBoundingBox(x0, x1, origin->foot, 1.1 * this->tubeWidth + dist); - this->grid->getPointsWithin(points, x0, x1); - - typedef std :: pair< ParticlePoint *, double >dist_pair; - std :: list< dist_pair >valid_points; - - /// @todo Change to the local corner information. - for ( std :: list< ParticlePoint > :: const_iterator it_corners = corners.begin(); it_corners != this->corners.end(); ++it_corners ) { - ParticlePoint *p = ( ParticlePoint * ) & ( * it_corners ); - if ( p->id != origin->id ) { - continue; - } - - if ( origin->foot.distance_square(p->foot) > 4 * this->tubeWidth * this->tubeWidth ) { - continue; - } - temp.beDifferenceOf(p->foot, origin->foot); - lcoord.beProductOf(toLocalCoord, temp); - valid_points.push_front( dist_pair( p, lcoord(0) ) ); - } - - // Apply rejection criteria based on normals (and other things?) - std :: list< ParticlePoint * > :: iterator it_points; - for ( it_points = points.begin(); it_points != points.end(); ++it_points ) { - ParticlePoint *p = * it_points; - if ( p->id != origin->id ) { - continue; - } - - double projection = p->normal.dotProduct(origin->normal); - if ( projection < 0.5 ) { - continue; - } - temp.beDifferenceOf(p->foot, origin->foot); - lcoord.beProductOf(toLocalCoord, temp); - valid_points.push_front( dist_pair( p, lcoord(0) ) ); - } - - valid_points.sort(compare_second); - //valid_points.unique(same_point); - - // Some special effort to take neighbors from both sides as well as - int m_smaller = 0, m_larger = 0; - double limit = 0.01 * this->grid->getGridStep(0); - double smaller = -limit, larger = limit; - // Copy them over to answer - std :: list< dist_pair > :: iterator it = valid_points.begin(); - for ( int i = 0; i < ( int ) valid_points.size(); i++, it++ ) { - if ( m_larger > 0 && m_smaller > 0 && m_larger + m_smaller >= this->m ) { - break; - } - if ( it->second > larger ) { - if ( m_larger >= this->m ) { - continue; - } else { - larger = it->second + limit; - m_larger++; - } - } else if ( it->second < smaller ) { - if ( m_smaller >= this->m ) { - continue; - } else { - smaller = it->second - limit; - m_smaller++; - } - } else { // To close to center, skip it. - continue; - } - answer.push_front(it->first); - } -} - -bool ParticleTopologyDescription :: findDisplacement(FloatArray &displacement, int id, const FloatArray &footpoint, TimeStep *tStep) const -{ - FloatArray lcoords, closest, offset; - IntArray region(1); - region(0) = id; - // Finds a single element close to this point. - Element *e = this->d->giveSpatialLocalizer()->giveElementClosestToPoint(lcoords, closest, footpoint, id); - if ( !e ) { // No element at all for this domain. Then there is no displacement; - OOFEM_WARNING("Couldn't find any element to interpolate from"); - displacement.resize( footpoint.giveSize() ); - displacement.zero(); - return false; - } - offset.beDifferenceOf(closest, footpoint); - double dist = offset.computeSquaredNorm(); - if ( dist > 0.25 * this->grid->getGridStep(0) * this->grid->getGridStep(0) ) { // TODO: Maybe also check normals? - OOFEM_WARNING( "Foot point far from element (%e) (%e, %e)->(%e, %e).\n", sqrt(dist), footpoint.at(1), footpoint.at(2), closest.at(1), closest.at(2) ); - return false; - } - - - if ( this->useDisplacements ) { - e->computeField(VM_Incremental, tStep, lcoords, displacement); // Displacement - } else { - FloatArray fields; - IntArray dofIds; - displacement.resize( this->d->giveNumberOfSpatialDimensions() ); - displacement.zero(); - double dt = tStep->giveTimeIncrement(); - e->computeField(VM_Total, tStep, lcoords, fields); // Velocities + pressures most likely. - e->giveElementDofIDMask(dofIds); - for ( int i = 0; i < dofIds.giveSize(); i++ ) { - if ( dofIds(i) == V_u ) { - displacement(0) = fields(i) * dt; - } else if ( dofIds(i) == V_v ) { - displacement(1) = fields(i) * dt; - } else if ( dofIds(i) == V_w ) { - displacement(2) = fields(i) * dt; - } - } - } - displacement.add(offset); - return true; -} - -void ParticleTopologyDescription :: doOutput(TimeStep *tStep) -{ - std :: ostringstream name; - name << this->d->giveEngngModel()->giveOutputBaseFileName() << "." << tStep->giveNumber() << ".vtp"; - if ( writeVTK ) { - this->writeVTKFile( name.str().c_str() ); - } -} - - -void ParticleTopologyDescription :: writeDataToFile(const char *name) const -{ - // Dumps everything in a ASCII table. - FILE *fid = fopen(name, "w"); - - int dims; - FloatArray grid_coord; - ParticlePoint *p; - - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->begin(); !it.end(); ++it ) { - if ( ( p = it.getPoint() ) != NULL ) { - it.getGridPoint(grid_coord); - - dims = grid_coord.giveSize(); - // First write the grid coordinate - for ( int i = 0; i < dims; i++ ) { - fprintf( fid, "%e ", grid_coord(i) ); - } - // Then the foot point - for ( int i = 0; i < dims; i++ ) { - fprintf( fid, "%e ", p->foot(i) ); - } - // Auxiliary information, like normal - for ( int i = 0; i < dims; i++ ) { - fprintf( fid, "%e ", p->normal(i) ); - } - fprintf(fid, "%d ", p->id); - fprintf(fid, "\n"); - } - } - - fclose(fid); -} - -void ParticleTopologyDescription :: writeVTKFile(const char *name) const -{ -#ifdef __VTK_MODULE - ParticlePoint *p; - int dims = this->grid->giveDimensions(); - // Create points and normals - int npoints = this->grid->getNumberOfPoints(); - vtkSmartPointer< vtkPoints >points = vtkSmartPointer< vtkPoints > :: New(); - vtkSmartPointer< vtkVertex >vertex; - vtkSmartPointer< vtkCellArray >vertices = vtkSmartPointer< vtkCellArray > :: New(); - vtkSmartPointer< vtkDoubleArray >pointNormalsArray = vtkSmartPointer< vtkDoubleArray > :: New(); - vtkSmartPointer< vtkIntArray >pointIDArray = vtkSmartPointer< vtkIntArray > :: New(); - vtkSmartPointer< vtkDoubleArray >pointEndPointsArray = vtkSmartPointer< vtkDoubleArray > :: New(); - - pointIDArray->SetNumberOfComponents(1); - pointNormalsArray->SetNumberOfComponents(3); - pointEndPointsArray->SetNumberOfComponents(3); - - pointIDArray->SetName("ID"); - pointNormalsArray->SetName("Normals"); - pointEndPointsArray->SetName("End points"); - - pointIDArray->SetNumberOfTuples(npoints); - pointNormalsArray->SetNumberOfTuples(npoints); - pointEndPointsArray->SetNumberOfTuples(npoints); - - int i = 0; - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->begin(); !it.end(); ++it ) { - if ( ( p = it.getPoint() ) != NULL ) { - points->InsertNextPoint(p->foot(0), p->foot(1), dims == 3 ? p->foot(2) : 0.0); - vertex = vtkSmartPointer< vtkVertex > :: New(); - vertex->GetPointIds()->SetId(0, i); - vertices->InsertNextCell(vertex); - pointIDArray->SetTuple1(i, p->id); - pointNormalsArray->SetTuple3(i, p->normal(0), p->normal(1), dims == 3 ? p->normal(2) : 0.0); - if ( p->corner.giveSize() > 0 ) { - pointEndPointsArray->InsertNextTuple3(p->corner(0) - p->foot(0), p->corner(1) - p->foot(1), dims == 3 ? p->corner(2) - p->foot(2) : 0.0); - } else { - pointEndPointsArray->InsertNextTuple3(0.0, 0.0, 0.0); - } - ++i; - } - } - - // Create a polydata object and add the points to it. - vtkSmartPointer< vtkPolyData >polydata = vtkSmartPointer< vtkPolyData > :: New(); - polydata->SetPoints(points); - polydata->SetVerts(vertices); - polydata->GetPointData()->SetNormals(pointNormalsArray); - polydata->GetPointData()->SetVectors(pointEndPointsArray); - polydata->GetPointData()->SetScalars(pointIDArray); - - // Write the file - vtkSmartPointer< vtkXMLPolyDataWriter >writer = vtkSmartPointer< vtkXMLPolyDataWriter > :: New(); - writer->SetFileName(name); - writer->SetInput(polydata); - // Optional - set the mode. The default is binary. - //writer->SetDataModeToBinary(); - //writer->SetDataModeToAscii(); - writer->Write(); -#else - OOFEM_WARNING("Not compiled with VTK support."); -#endif -} - -class edge -{ -public: - int first; - int second; - int id; -}; - -class node -{ -public: - FloatArray c; - int id; -}; - -static bool sort_edge(edge a, edge b) -{ - return ( a.first == b.first ) ? a.second > b.second : a.first > b.first; -} - -static bool compare_edge(edge a, edge b) -{ - return a.first == b.first && a.second == b.second; -} - -// There are much room for improvement here. In particular, it should be similar to -void ParticleTopologyDescription :: generatePSLG(Triangle_PSLG &pslg) -{ - this->resample(); - - FloatArray lcoord, temp; - FloatMatrix toLocalCoord; - - // First enumerate all the nodes, removing duplicates - ParticlePoint *origin; - std :: list< node >nodes; - std :: list< ParticlePoint * >points; - FloatArray x0, x1, grid_coord; - - // Nodal merge limit (for very close points, 1/10 of the grid step). - double merge2 = this->grid->getGridStep(1) * this->grid->getGridStep(1) * 1e-2; - // PSLG simplification limit, 1/10 of the grid step. - double limit = this->grid->getGridStep(1) * 0.5; - - int total_nodes = 0; - - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->begin(); !it.end(); ++it ) { - if ( ( origin = it.getPoint() ) != NULL ) { - origin->node = 0; - } - } - - for ( std :: list< ParticlePoint > :: iterator cit = this->corners.begin(); cit != this->corners.end(); ++cit ) { - cit->node = 0; - } - - // Enumerate the corner nodes first; - for ( std :: list< ParticlePoint > :: iterator cit = this->corners.begin(); cit != this->corners.end(); ++cit ) { - if ( cit->node != 0 ) { - continue; - } - total_nodes++; - cit->node = total_nodes; - node n; - n.id = cit->id; - n.c = cit->foot; - nodes.push_back(n); - for ( std :: list< ParticlePoint > :: iterator cit_ = this->corners.begin(); cit_ != this->corners.end(); ++cit_ ) { - if ( cit->foot.distance_square(cit_->foot) <= merge2 && cit_->node == 0 ) { - cit_->node = cit->node; - cit_->foot = cit->foot; // For consistency, merge the points which are merged in the mesh - } - } - - this->getBoundingBox(x0, x1, cit->foot, 2 * this->tubeWidth); - this->grid->getPointsWithin(points, x0, x1); - for ( auto pit = points.begin(); pit != points.end(); pit++ ) { - if ( ( cit->foot.distance_square( ( * pit )->foot ) <= merge2 ) && ( * pit )->node == 0 ) { - ( * pit )->node = cit->node; - ( * pit )->foot = cit->foot; - } - } - } - - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->begin(); !it.end(); ++it ) { - if ( ( origin = it.getPoint() ) != NULL ) { - if ( origin->node != 0 ) { - continue; - } - toLocalCoord.beLocalCoordSys(origin->normal); - total_nodes++; - origin->node = total_nodes; - node n; - n.id = origin->id; - n.c = origin->foot; - nodes.push_back(n); - - this->getBoundingBox(x0, x1, origin->foot, 2 * this->tubeWidth); - this->grid->getPointsWithin(points, x0, x1); - for ( auto pit = points.begin(); pit != points.end(); pit++ ) { - if ( ( * pit )->node == 0 ) { - /* - * temp.beDifferenceOf((*pit)->foot, origin->foot); - * lcoord.beProductOf(toLocalCoord, temp); - * double ln = lcoord.at(lcoord.giveSize()); // Treating the buggy offset differently. - * lcoord.at(lcoord.giveSize()) = 0.0; - * if ( lcoord.computeSquaredNorm() <= limit*limit && (ln < this->tubeWidth && origin->normal.dotProduct((*pit)->normal) ) { - */ - if ( origin->foot.distance_square( ( * pit )->foot ) <= merge2 ) { - ( * pit )->node = origin->node; - ( * pit )->foot = origin->foot; - } - } - } - } - } - - // Find segments - std :: list< edge >edges; - double max_value = 2 * this->tubeWidth; // No connections further away than this. - double front_dist, back_dist, b_front_dist, b_back_dist; - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->begin(); !it.end(); ++it ) { - if ( ( origin = it.getPoint() ) != NULL ) { - toLocalCoord.beLocalCoordSys(origin->normal); - - edge e0, e1; - e0.id = origin->id; - e1.id = origin->id; - e0.second = origin->node; - e1.first = origin->node; - e0.first = 0; - e1.second = 0; - front_dist = max_value; - back_dist = -max_value; - - bool found_front = false, found_back = false; - - // Backup values - b_front_dist = -max_value; - b_back_dist = max_value; - - this->getBoundingBox(x0, x1, origin->foot, max_value); - this->grid->getPointsWithin(points, x0, x1); - - // Loop over corner nodes as well - for ( std :: list< ParticlePoint > :: iterator cit = this->corners.begin(); cit != this->corners.end(); ++cit ) { - points.push_front(& * cit); - } - - for ( auto pit = points.begin(); pit != points.end(); ++pit ) { - ParticlePoint *p = * pit; - - if ( p->id != origin->id || origin->node == p->node ) { - continue; - } - - temp.beDifferenceOf(p->foot, origin->foot); - - if ( temp.computeSquaredNorm() > max_value * max_value ) { - continue; - } - - lcoord.beProductOf(toLocalCoord, temp); - - double projection = p->normal.giveSize() > 0 ? p->normal.dotProduct(origin->normal) : 1.0; - if ( projection < 0.0 ) { // Then take the furthest point -#if 1 - if ( lcoord(0) > b_front_dist && !found_front ) { - b_front_dist = lcoord(0); - e1.second = p->node; - } - if ( lcoord(0) < b_back_dist && !found_back ) { - b_back_dist = lcoord(0); - e0.first = p->node; - } -#endif - continue; - } - - if ( lcoord(0) > 0 ) { - if ( lcoord(0) < front_dist ) { - found_front = true; - front_dist = lcoord(0); - e1.second = p->node; - } - } else { - if ( lcoord(0) > back_dist ) { - found_back = true; - back_dist = lcoord(0); - e0.first = p->node; - } - } - } - if ( e0.first != 0 ) { - edges.push_front(e0); - } - if ( e1.second != 0 ) { - edges.push_front(e1); - } - } - } - edges.sort(sort_edge); - edges.unique(compare_edge); - - Triangle_PSLG fine; - fine.nx.resize( nodes.size() ); - fine.ny.resize( nodes.size() ); - std :: list< node > :: iterator it_node; - int n = 0; - for ( it_node = nodes.begin(); it_node != nodes.end(); it_node++ ) { - fine.nx(n) = it_node->c(0); - fine.ny(n) = it_node->c(1); - n++; - } - - fine.segment_a.resize( edges.size() ); - fine.segment_b.resize( edges.size() ); - fine.segment_marker.resize( edges.size() ); - std :: list< edge > :: iterator it_edge; - n = 0; - for ( it_edge = edges.begin(); it_edge != edges.end(); it_edge++ ) { - fine.segment_a(n) = it_edge->first; - fine.segment_b(n) = it_edge->second; - fine.segment_marker(n) = it_edge->id; - n++; - } - -#if 0 - pslg.nx = fine.nx; - pslg.ny = fine.ny; - pslg.segment_a = fine.segment_a; - pslg.segment_b = fine.segment_b; - pslg.segment_marker = fine.segment_marker; -#else - TriangleMesherInterface :: simplifyPSLG(pslg, fine, limit); -#endif - - // DEBUG: Print all to matlab file -#if 1 - this->writeVTKFile("initial_particle.vtp"); - - FILE *file = fopen("pslg.m", "w"); - - fprintf(file, "edges = ["); - for ( int i = 0; i < pslg.segment_a.giveSize(); i++ ) { - fprintf( file, "%d, %d, %d;\n", pslg.segment_a(i), pslg.segment_b(i), pslg.segment_marker(i) ); - } - fprintf(file, "];\n"); - - fprintf(file, "nodes = ["); - for ( int i = 0; i < pslg.nx.giveSize(); i++ ) { - fprintf( file, "%e, %e;\n", pslg.nx(i), pslg.ny(i) ); - } - fprintf(file, "];\n"); - - fprintf(file, "colors = 'grbkmcygrbkmcygrbkmcy';\n"); - fprintf(file, "hold on, axis equal\n"); - fprintf(file, "for i = 1:size(nodes,1)\n plot(nodes(i,1),nodes(i,2),'rx'); %%text(nodes(i,1),nodes(i,2),num2str(i)); \nend\n"); - //fprintf(file, "for i = 1:size(edges,1)\n plot(nodes(edges(i,1:2),1),nodes(edges(i,1:2),2),colors(edges(i,3)));\nend\n"); - fprintf(file, "for i = 1:size(edges,1)\n quiver(nodes(edges(i,1),1),nodes(edges(i,1),2),nodes(edges(i,2),1)-nodes(edges(i,1),1),nodes(edges(i,2),2)-nodes(edges(i,1),2),1,colors(edges(i,3)));\nend\n"); - fprintf(file, "for i = 1:size(edges,1)\n %%text(mean(nodes(edges(i,1:2),1)),mean(nodes(edges(i,1:2),2)),['\\color{red} ',num2str(i)]);\nend\n"); - - fclose(file); -#endif -} - -void ParticleTopologyDescription :: generateMesh(std :: vector< FloatArray > &nodes, std :: vector< IntArray > &elements, std :: vector< IntArray > &segments, - std :: vector< IntArray > &n_markers, IntArray &e_markers, IntArray &s_markers, IntArray &e_egt, IntArray &s_egt) -{ - double maxArea = 0.05; - IntArray r_markers; - - TriangleMesherInterface tmi(30, maxArea, true); - - Triangle_PSLG pslg; - this->generatePSLG(pslg); - tmi.meshPSLG(pslg, - //holes, regions, r_markers, - this->regionOutside, this->regionInside, // Input - nodes, n_markers, elements, e_markers, segments, s_markers); // Output - - // Append the corner nodes manually. Didn't see any pretty way to do this. -#if 0 // Replace by this... - for ( ParticleGrid< ParticlePoint > :: iterator it = this->grid->begin(); !it.end(); ++it ) { - ParticlePoint *origin; - if ( ( origin = it.getPoint() ) != NULL ) { - double dist2, min_dist2 = 1e100; - int min_i = 0; - for ( int i = 1; i <= ( int ) nodes.size(); ++i ) { - dist2 = nodes [ i - 1 ].distance_square(point->foot); - if ( dist2 < min_dist2 ) { - min_dist2 = dist2; - min_i = i; - } - } - n_markers.at(min_i)->insertSortedOnce(point->id); - } - } -#else - for ( std :: list< ParticlePoint > :: iterator cit = this->corners.begin(); cit != this->corners.end(); ++cit ) { - double dist2, min_dist2 = 1e100; - int min_i = 0; - for ( int i = 1; i <= ( int ) nodes.size(); ++i ) { - dist2 = nodes [ i - 1 ].distance_square(cit->foot); - if ( dist2 < min_dist2 ) { - min_dist2 = dist2; - min_i = i; - } - } - n_markers [ min_i - 1 ].insertSortedOnce(cit->id); - } -#endif - -#if 1 // DEBUG: Print all to matlab file - printf("Printing mesh.m\n"); - FILE *file = fopen("mesh.m", "w"); - fprintf(file, "nodes = ["); - for ( int i = 1; i <= ( int ) nodes.size(); i++ ) { - FloatArray &x = nodes [ i - 1 ]; - for ( int j = 1; j <= 2; j++ ) { - fprintf( file, "%e, ", x.at(j) ); - } - fprintf( file, " %d", n_markers [ i - 1 ].at(1) ); - fprintf(file, ";\n"); - } - fprintf(file, "];\n"); - - fprintf(file, "triangles = ["); - for ( int i = 1; i <= ( int ) elements.size(); i++ ) { - IntArray &x = elements [ i - 1 ]; - for ( int j = 1; j <= x.giveSize(); j++ ) { - fprintf( file, "%d, ", x.at(j) ); - } - fprintf( file, "%d", e_markers.at(i) ); - fprintf(file, ";\n"); - } - fprintf(file, "];\n"); - - fprintf(file, "segments = ["); - for ( int i = 1; i <= ( int ) segments.size(); i++ ) { - IntArray &x = segments [ i - 1 ]; - for ( int j = 1; j <= x.giveSize(); j++ ) { - fprintf( file, "%d, ", x.at(j) ); - } - fprintf( file, "%d", s_markers.at(i) ); - fprintf(file, ";\n"); - } - fprintf(file, "];\n"); - - //fprintf(file, "clf\nhold on\nfor i = 1:size(triangles,1); plot(nodes(triangles(i,[1:3,1]),1), nodes(triangles(i,[1:3,1]),2), 'r'); end\n"); - fprintf(file, "clf\nhold on\n xx = nodes(:,1); yy = nodes(:,2); patch(xx(triangles(:,1:3))',yy(triangles(:,1:3))',triangles(:,end)'); \n"); - fprintf(file, "for i = 1:size(segments,1); plot(nodes(segments(i,1:2),1), nodes(segments(i,1:2),2), 'b'); end\n"); - - fclose(file); -#endif -} - -void ParticleTopologyDescription :: replaceFEMesh() -{ - std :: vector< FloatArray >nodes; - std :: vector< IntArray >elements, segments, n_markers; - ///@todo Boundary sets vs. bulk sets? - std :: vector< IntArray >boundarySets( regionSet.maximum() ); - //std::vector< IntArray >buldSets( regionSet.maximum() ); - IntArray e_markers, s_markers, e_egt, s_egt; - this->generateMesh(nodes, elements, segments, n_markers, e_markers, s_markers, e_egt, s_egt); - - for ( int i = 1; i <= ( int ) elements.size(); ++i ) { - int r = e_markers.at(i); - int set = regionSet.at(r); - if ( set ) { - boundarySets [ set - 1 ].followedBy(i); - boundarySets [ set - 1 ].followedBy(0); - } - } - for ( int i = 1; i <= ( int ) segments.size(); ++i ) { - int r = s_markers.at(i); - int set = regionSet.at(r); - if ( set ) { - boundarySets [ set - 1 ].followedBy( i + elements.size() ); - boundarySets [ set - 1 ].followedBy(0); - } - } - - // Replace all the elements with the new set. - Domain *new_d; - // Should i use a new domain and replace it instead? - new_d = this->d; - - // Clear everything old; - new_d->resizeElements( elements.size() + segments.size() ); - new_d->resizeDofManagers( nodes.size() ); - new_d->resizeSets( regionSet.giveSize() ); - - for ( int i = 1; i <= ( int ) nodes.size(); ++i ) { - //DynamicInputRecord *dir = new DynamicInputRecord(_IFT_Node_Name, i); - //dir->setField(nodes[i-1], _IFT_Node_coords); - //dr->insertInputRecord(IR_dofmanRec, dir); - Node *node = new Node(i, new_d); - node->setCoordinates(nodes [ i - 1 ]); - new_d->setDofManager(i, node); - } - - for ( int i = 1; i <= ( int ) elements.size(); ++i ) { - int r = e_markers.at(i); - //DynamicInputRecord *dir = new DynamicInputRecord(regionElementType[ r-1 ], i); - //dir->setField(r, _IFT_Element_crosssect); - //dir->setField(elements[i-1], _IFT_Element_nodes); - //dr->insertInputRecord(IR_elemRec, dir); - Element *element = classFactory.createElement(this->regionElementType [ r - 1 ].c_str(), i, new_d); - element->setGlobalNumber(i); - element->setCrossSection(r); - element->setDofManagers(elements [ i - 1 ]); - element->setParallelMode(Element_local); - new_d->setElement(element->giveNumber(), element); - } - - for ( int i = 1; i <= ( int ) segments.size(); ++i ) { - int r = s_markers.at(i); - //DynamicInputRecord *dir = new DynamicInputRecord(regionElementType[ r-1 ], segments.size() + i); - //dir->setField(r, _IFT_Element_crosssect); - //dir->setField(segments[i-1], _IFT_Element_nodes); - //dr->insertInputRecord(IR_elemRec, dir); - Element *element = classFactory.createElement(regionElementType [ r - 1 ].c_str(), elements.size() + i, new_d); - if ( !element ) { - printf( "Couldn't create: %s\n", regionElementType [ r - 1 ].c_str() ); - } - element->setGlobalNumber( i + elements.size() ); - element->setCrossSection(r); - element->setDofManagers(segments [ i - 1 ]); - element->setParallelMode(Element_local); - new_d->setElement(element->giveNumber(), element); - } - - for ( int i = 1; i <= ( int ) boundarySets.size(); ++i ) { - //DynamicInputRecord *dir = new DynamicInputRecord(_IFT_Set_Name, i); - //dir->setField(boundarySets[i-1], _IFT_Set_elementBoundaries); - //dr->insertInputRecord(IR_setRec, dir); - Set *set = new Set(1, new_d); - set->setBoundaryList(boundarySets [ i - 1 ]); - new_d->setSet(i, set); - } - - new_d->postInitialize(); - new_d->giveEngngModel()->checkConsistency(); - new_d->giveEngngModel()->forceEquationNumbering(); // TODO: This shouldn't be necessary -} -} diff --git a/src/oofemlib/particletopologydescription.h b/src/oofemlib/particletopologydescription.h deleted file mode 100644 index b484745ee..000000000 --- a/src/oofemlib/particletopologydescription.h +++ /dev/null @@ -1,284 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef particletopologydescription_h -#define particletopologydescription_h - -#include "topologydescription.h" -#include "intarray.h" -#include "floatarray.h" -#include "floatmatrix.h" - -#include -#include -#include -#include - -///@todo These are general enough to be able to use outside this class. -///@name Input fields for Circle -//@{ -#define _IFT_Circle_center "center" -#define _IFT_Circle_radius "radius" -#define _IFT_Circle_start "start" -#define _IFT_Circle_end "end" -//@} - -///@name Input fields for Line -//@{ -#define _IFT_Line_start "start" -#define _IFT_Line_end "end" -//@} - -///@name Input fields for Point -//@{ -#define _IFT_Point_coords "coords" -//@} - -///@name Input fields for Meshing -//@{ -#define _IFT_Meshing_elementType "elementtype" -#define _IFT_Meshing_set "set" -//@} - -///@name Input fields for ParticleTopology -//@{ -#define _IFT_ParticleTopologyDescription_Name "particletopology" -#define _IFT_ParticleTopologyDescription_nsd "nsd" -#define _IFT_ParticleTopologyDescription_baseResolution "baseresolution" -#define _IFT_ParticleTopologyDescription_tubeWidth "tubewidth" -#define _IFT_ParticleTopologyDescription_neighbors "neighbors" -#define _IFT_ParticleTopologyDescription_boundingBoxA "bboxa" -#define _IFT_ParticleTopologyDescription_boundingBoxB "bboxb" -#define _IFT_ParticleTopologyDescription_numberOfSegments "nsegments" -#define _IFT_ParticleTopologyDescription_regionOutside "regionoutside" -#define _IFT_ParticleTopologyDescription_regionInside "regioninside" -#define _IFT_ParticleTopologyDescription_identification "id" -//@} - - -namespace oofem -{ -template< class Point >class ParticleGrid; -class Domain; -struct Triangle_PSLG; - -/// Default point type for describing topology. -struct ParticlePoint { - ParticlePoint() {}; - ParticlePoint(const FloatArray &foot, int id, const FloatArray &normal, double distance2) : - foot(foot), id(id), normal(normal), distance2(distance2), removal(false) {}; - FloatArray foot; ///< Closest coordinate on surface. - // Auxiliary information - FloatArray total_displacement; ///< Total displacement since last resampling. - int id; ///< Id of surface. - FloatArray normal; ///< Surface normal at foot point. - FloatArray corner; ///< Corner particle (for open surfaces). - double distance2; ///< Squared distance stored for efficiency. - int node; ///< Node number (for meshing) - int c_node; ///< Corner node number (for open surfaces). - bool removal; /// Convenience variable for clearing out nodes which have conflicting information. -}; - -/** - * A grid based particle method for describing topology. - * Based on papers: - * Shingyu Leung and Hongkai Zhao, A Grid Based Particle Method for Evolution of Open Curves and Surfaces. Journal of Computational Physics, Volume 228, Issue 20, November 1 2009, Pages 7706-7728. - * Shingyu Leung and Hongkai Zhao, A Grid Based Particle Method for Moving Interface Problems. UCLA-CAM 08-08. Journal of Computational Physics, Volume 228, Issue 8, May 1 2009, Pages 2993-3024. - * with some modifications and missing implementations. - * - * @note Experimental! Both inconvenient to use, and not very robust. - * - * @todo Absolutely vital is the use of adaptivity, which is not yet implemented. - * @todo Merging of regions is still lacking. - * @todo Vanishing pores occasionally experience problems. - * @todo Partial reconstruction should be possible. - * - * @author Mikael Öhman - */ -class ParticleTopologyDescription : public TopologyDescription -{ -protected: - /// Determines if velocity or displacements dofs should be used to update geometry. - bool useDisplacements; - /// Conditional for printing VTK output. - bool writeVTK; - /// Denotes if the active grid is newly resampled. - bool resampled; - /// Maximum squared displacement of any particle. - double maxdisp2; - /// Width of the tube around the interfaces - double tubeWidth; - /// Number of points to use for resampling - int m; - /// The grid of points, the actual topological information - std :: unique_ptr< ParticleGrid< ParticlePoint > > grid; - - /// Corner nodes - std :: list< ParticlePoint >corners; - - /** - * Mapping of regions from delimited by each id. - * This is only needed for remeshing. - * Regions should be strictly different from any id in the domain, as the id's themselves map directly to regions. - * First value is the region on the normals direction, the second value is the other side. - */ - IntArray regionOutside, regionInside; - FloatMatrix mergeID, controlID; - - /** - * Mapping from region to FE components. - */ - std :: vector< std :: string >regionElementType; - IntArray regionSet; - - /** - * Resamples the grid. Entire grid is replaced. - * Finds new foot points for new grid points along the curve. - */ - void resample(); - - /** - * Deactivates points with inconsistent information. - * This is typically due to merging surfaces or vanishing pores. - * @return TS_NeedsRemeshing if points have been deactivated. - */ - TopologyState checkOverlap(); - - /** - * Clears all points marked for removal. - * Works recursively on refined grids. - * @param g Grid to clear. - */ - void removePoints(ParticleGrid< ParticlePoint > &g) const; - - /** - * Finds the displacement for the underlying FE-mesh. - * @param answer The requested displacement. - * @param id Only elements of specified region is taken into account (unless id == 0). - * @param footpoint The spatial coordinate where to find the displacement. - * @param tStep The time step for which to find the displacement. - */ - bool findDisplacement(FloatArray &answer, int id, const FloatArray &footpoint, TimeStep *tStep) const; - - /** - * Collects neighboring points according to some specification. - * Finds a maximum of around m neighbors, could be fewer. - * A optional distance can be added to take into account the displaced foot points. - * @param answer The neighboring particles. - * @param p Point to compute neighbors around. - * @param dist Extra distance to take neighbors from. - */ - void collectNeighbors(std :: list< ParticlePoint * > &answer, const ParticlePoint *p, double dist = 0) const; - - /** - * Helper for common task of fetching a bounding box around a point. - */ - static void getBoundingBox(FloatArray &x0, FloatArray &x1, const FloatArray &c, double width); - - /** - * Shortest distance from least square fit based on 2nd order polynomial. - */ - void calculateShortestDistance(const ParticlePoint *p, std :: list< ParticlePoint * > &points, ParticleGrid< ParticlePoint > &grid) const; - - /** - * Helper for calculateShortestDistance - */ - double shortestDistanceFromCurve(const FloatArray &a, double txi_min, double txi_max, - const FloatArray &n0, const FloatArray &y0, const FloatArray &p, FloatArray &foot, FloatArray &normal) const; - - /** - * Used for initialization, calculating the distance from primitives. - * Adds line segment from p0 to p1. - * @param id ID for segment. - * @param p0 First corner of the edge. - * @param p1 Second corner of the edge. - * @param grid Grid to add points to. - */ - void addLineSegment(int id, const FloatArray &p0, const FloatArray &p1, ParticleGrid< ParticlePoint > &grid) const; - /** - * Used for initialization, calculating the distance from primitives. - * Adds a circle segment from p0 to p1, with center at c. - * @param id ID for segment. - * @param c Center coordinate. - * @param r Radius. - * @param v0 Lower angle [-pi,pi]. - * @param v1 Upper angle [-pi,pi]. - * @param grid Grid to add points to. - */ - void addCircleSegment(int id, const FloatArray &c, double r, double v0, double v1, ParticleGrid< ParticlePoint > &grid) const; - /** - * Adds a corner node. - * @param id ID for corner. - * @param c Coordinate of corner. - * @param grid Grid to add corner to. - */ - void addCorner(int id, const FloatArray &c, ParticleGrid< ParticlePoint > &grid); - - /** - * Generates the PSLG for meshing with Triangle. - * @param PSLG Generated structure ready for meshing. - */ - void generatePSLG(Triangle_PSLG &PSLG); - -public: - ParticleTopologyDescription(Domain *d); - virtual ~ParticleTopologyDescription(); - virtual bool instanciateYourself(DataReader *dr); - - virtual TopologyState updateYourself(TimeStep *tStep); - - /** - * Generates a mesh from the topology. - * @param nodes Nodes created. - * @param elements Bulk elements created. - * @param segments Edge/surface elements describing the topology. - * @param n_markers Node markers. - * @param e_markers Element markers. - * @param s_markers Segment markers. - * @param e_egt Element geometry types. - * @param s_egt Segment geometry types. - */ - virtual void generateMesh(std :: vector< FloatArray > &nodes, std :: vector< IntArray > &elements, std :: vector< IntArray > &segments, - std :: vector< IntArray > &n_markers, IntArray &e_markers, IntArray &s_markers, IntArray &e_egt, IntArray &s_egt); - - virtual void replaceFEMesh(); - - virtual void doOutput(TimeStep *tStep); - virtual void writeDataToFile(const char *name) const; - virtual void writeVTKFile(const char *name) const; - - virtual const char *giveClassName() const { return "ParticleTopologyDescription"; } -}; -} // end namespace oofem -#endif // particletopologydescription_h diff --git a/src/oofemlib/peakfunction.C b/src/oofemlib/peakfunction.C index 3314ce5df..091fe3ce0 100644 --- a/src/oofemlib/peakfunction.C +++ b/src/oofemlib/peakfunction.C @@ -52,14 +52,12 @@ PeakFunction :: evaluateAtTime(double time) } } -IRResultType -PeakFunction :: initializeFrom(InputRecord *ir) +void +PeakFunction :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Function :: initializeFrom(ir); IR_GIVE_FIELD(ir, t, _IFT_PeakFunction_t); IR_GIVE_FIELD(ir, value, _IFT_PeakFunction_ft); - - return Function :: initializeFrom(ir); } } // end namespace oofem diff --git a/src/oofemlib/peakfunction.h b/src/oofemlib/peakfunction.h index cb5fc475b..7b7b0b52a 100644 --- a/src/oofemlib/peakfunction.h +++ b/src/oofemlib/peakfunction.h @@ -65,13 +65,13 @@ class OOFEM_EXPORT PeakFunction : public Function } virtual ~PeakFunction() { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "PeakFunction"; } - virtual const char *giveInputRecordName() const { return _IFT_PeakFunction_Name; } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "PeakFunction"; } + const char *giveInputRecordName() const override { return _IFT_PeakFunction_Name; } - virtual double evaluateAtTime(double); - virtual double evaluateVelocityAtTime(double t) { return 0.; } - virtual double evaluateAccelerationAtTime(double t) { return 0.; } + double evaluateAtTime(double) override; + double evaluateVelocityAtTime(double t) override { return 0.; } + double evaluateAccelerationAtTime(double t) override { return 0.; } }; } // end namespace oofem #endif // peakfunction_h diff --git a/src/oofemlib/periodicpiecewiselinfunction.C b/src/oofemlib/periodicpiecewiselinfunction.C index 3605dbb88..3ce329dde 100644 --- a/src/oofemlib/periodicpiecewiselinfunction.C +++ b/src/oofemlib/periodicpiecewiselinfunction.C @@ -104,17 +104,14 @@ double PeriodicPiecewiseLinFunction :: evaluateVelocityAtTime(double time) return add + PiecewiseLinFunction :: evaluateVelocityAtTime(time); } -IRResultType -PeriodicPiecewiseLinFunction :: initializeFrom(InputRecord *ir) +void +PeriodicPiecewiseLinFunction :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - + PiecewiseLinFunction :: initializeFrom(ir); period = -1.0; IR_GIVE_OPTIONAL_FIELD(ir, period, _IFT_PeriodicPiecewiseLinFunction_period); addTF = 0; IR_GIVE_OPTIONAL_FIELD(ir, addTF, _IFT_PeriodicPiecewiseLinFunction_addtf); - - return PiecewiseLinFunction :: initializeFrom(ir); } diff --git a/src/oofemlib/periodicpiecewiselinfunction.h b/src/oofemlib/periodicpiecewiselinfunction.h index a9f266e2f..b0a8fe53a 100644 --- a/src/oofemlib/periodicpiecewiselinfunction.h +++ b/src/oofemlib/periodicpiecewiselinfunction.h @@ -75,14 +75,14 @@ class OOFEM_EXPORT PeriodicPiecewiseLinFunction : public PiecewiseLinFunction } virtual ~PeriodicPiecewiseLinFunction() { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveClassName() const { return "PeriodicPiecewiseClass"; } - virtual const char *giveInputRecordName() const { return _IFT_PeriodicPiecewiseLinFunction_Name; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveClassName() const override { return "PeriodicPiecewiseClass"; } + const char *giveInputRecordName() const override { return _IFT_PeriodicPiecewiseLinFunction_Name; } - virtual double evaluateAtTime(double); - virtual double evaluateVelocityAtTime(double); - virtual double evaluateAccelerationAtTime(double) { return 0.; } + double evaluateAtTime(double) override; + double evaluateVelocityAtTime(double) override; + double evaluateAccelerationAtTime(double) override { return 0.; } }; } // end namespace oofem #endif // periodicpiecewiselinfunction_h diff --git a/src/oofemlib/petscsolver.h b/src/oofemlib/petscsolver.h index 96bc34176..b4809e5ce 100644 --- a/src/oofemlib/petscsolver.h +++ b/src/oofemlib/petscsolver.h @@ -37,6 +37,8 @@ #include "sparselinsystemnm.h" #include "petscsparsemtrx.h" +#define _IFT_PetscSolver_Name "petsc" + namespace oofem { class Domain; class EngngModel; @@ -58,7 +60,7 @@ class OOFEM_EXPORT PetscSolver : public SparseLinearSystemNM virtual ~PetscSolver(); - virtual NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x); + NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x) override; /** * Solves the given linear system. @@ -69,9 +71,9 @@ class OOFEM_EXPORT PetscSolver : public SparseLinearSystemNM */ NM_Status petsc_solve(PetscSparseMtrx &A, Vec b, Vec x); - virtual const char *giveClassName() const { return "PetscSolver"; } - virtual LinSystSolverType giveLinSystSolverType() const { return ST_Petsc; } - virtual SparseMtrxType giveRecommendedMatrix(bool symmetric) const { return SMT_PetscMtrx; } + const char *giveClassName() const override { return "PetscSolver"; } + LinSystSolverType giveLinSystSolverType() const override { return ST_Petsc; } + SparseMtrxType giveRecommendedMatrix(bool symmetric) const override { return SMT_PetscMtrx; } }; } // end namespace oofem #endif // petscsolver_h diff --git a/src/oofemlib/petscsparsemtrx.C b/src/oofemlib/petscsparsemtrx.C index 7b44f88e2..34deaa682 100644 --- a/src/oofemlib/petscsparsemtrx.C +++ b/src/oofemlib/petscsparsemtrx.C @@ -50,10 +50,17 @@ REGISTER_SparseMtrx(PetscSparseMtrx, SMT_PetscMtrx); PetscSparseMtrx :: PetscSparseMtrx(int n, int m) : SparseMtrx(n, m), - mtrx(NULL), symmFlag(false), leqs(0), geqs(0), blocksize(1), di(0), kspInit(false), newValues(true), localIS(NULL), globalIS(NULL) { } - -PetscSparseMtrx :: PetscSparseMtrx() : SparseMtrx(), - mtrx(NULL), symmFlag(false), leqs(0), geqs(0), blocksize(1), di(0), kspInit(false), newValues(true), localIS(NULL), globalIS(NULL){ } + mtrx(NULL), + symmFlag(false), + leqs(0), + geqs(0), + blocksize(1), + di(0), + kspInit(false), + newValues(true), + localIS(NULL), + globalIS(NULL) +{ } PetscSparseMtrx :: ~PetscSparseMtrx() @@ -69,10 +76,10 @@ PetscSparseMtrx :: ~PetscSparseMtrx() } -SparseMtrx * -PetscSparseMtrx :: GiveCopy() const +std::unique_ptr +PetscSparseMtrx :: clone() const { - PetscSparseMtrx *answer = new PetscSparseMtrx(nRows, nColumns); + std::unique_ptr answer = std::make_unique(nRows, nColumns); MatDuplicate( this->mtrx, MAT_COPY_VALUES, & ( answer->mtrx ) ); answer->symmFlag = this->symmFlag; answer->mType = this->mType; @@ -83,7 +90,7 @@ PetscSparseMtrx :: GiveCopy() const answer->kspInit = false; answer->newValues = this->newValues; - return answer; + return std::move(answer); } void @@ -125,7 +132,7 @@ PetscSparseMtrx :: times(const FloatArray &x, FloatArray &answer) const VecGetArray(globY, & ptr); answer.resize(this->nRows); for ( int i = 0; i < this->nRows; i++ ) { - answer(i) = ptr [ i ]; + answer[i] = ptr [ i ]; } VecRestoreArray(globY, & ptr); @@ -156,7 +163,7 @@ PetscSparseMtrx :: timesT(const FloatArray &x, FloatArray &answer) const VecGetArray(globY, & ptr); answer.resize(this->nColumns); for ( int i = 0; i < this->nColumns; i++ ) { - answer(i) = ptr [ i ]; + answer[i] = ptr [ i ]; } VecRestoreArray(globY, & ptr); @@ -247,13 +254,13 @@ PetscSparseMtrx :: timesT(const FloatMatrix &B, FloatMatrix &answer) const BT.beTranspositionOf(B); MatCreateSeqDense(PETSC_COMM_SELF, BT.giveNumberOfRows(), BT.giveNumberOfColumns(), BT.givePointer(), & globB); MatMatMult(globB, this->mtrx, MAT_INITIAL_MATRIX, PETSC_DEFAULT, & globC); - const double *vals; for ( int r = 0; r < nc; r++ ) { - MatGetRow(globC, r, NULL, NULL, & vals); + const double *vals; + MatGetRow(globC, r, nullptr, nullptr, & vals); for ( int i = 0; i < nr; i++ ) { * aptr++ = vals [ i ]; } - MatRestoreRow(globC, r, NULL, NULL, & vals); + MatRestoreRow(globC, r, nullptr, nullptr, & vals); } MatDestroy(& globB); @@ -335,7 +342,7 @@ PetscSparseMtrx :: buildInternalStructure(EngngModel *eModel, int n, int m, cons total_nnz = 0; for ( int i = 0; i < leqs; i++ ) { - d_nnz(i) = rows_upper [ i ].giveSize() + rows_lower [ i ].giveSize(); + d_nnz[i] = rows_upper [ i ].giveSize() + rows_lower [ i ].giveSize(); } } @@ -443,8 +450,8 @@ PetscSparseMtrx :: buildInternalStructure(EngngModel *eModel, int di, const Unkn total_nnz = 0; for ( int i = 0; i < leqs; i++ ) { - d_nnz(i) = rows_upper [ i ].giveSize() + rows_lower [ i ].giveSize(); - total_nnz += d_nnz(i); + d_nnz[i] = rows_upper [ i ].giveSize() + rows_lower [ i ].giveSize(); + total_nnz += d_nnz[i]; } } @@ -490,8 +497,8 @@ PetscSparseMtrx :: buildInternalStructure(EngngModel *eModel, int di, const Unkn if ( localIS ) { ISDestroy(& localIS); ISDestroy(& globalIS); - localIS = NULL; - globalIS = NULL; + localIS = nullptr; + globalIS = nullptr; } this->emodel = eModel; @@ -577,16 +584,16 @@ PetscSparseMtrx :: buildInternalStructure(EngngModel *eModel, int di, const Unkn } for ( int i = 0; i < leqs; i++ ) { - d_nnz(i) = d_rows_upper [ i ].giveSize() + d_rows_lower [ i ].giveSize(); - o_nnz(i) = o_rows_upper [ i ].giveSize() + o_rows_lower [ i ].giveSize(); + d_nnz[i] = d_rows_upper [ i ].giveSize() + d_rows_lower [ i ].giveSize(); + o_nnz[i] = o_rows_upper [ i ].giveSize() + o_rows_lower [ i ].giveSize(); - d_nnz_sym(i) = d_rows_upper [ i ].giveSize(); - o_nnz_sym(i) = o_rows_upper [ i ].giveSize(); + d_nnz_sym[i] = d_rows_upper [ i ].giveSize(); + o_nnz_sym[i] = o_rows_upper [ i ].giveSize(); } } //fprintf (stderr,"\n[%d]PetscSparseMtrx: Profile ...",rank); - //for (i=0; i PetscSparseMtrx :: giveSubMatrix(const IntArray &rows, const IntArray &cols) { #ifdef __PARALLEL_MODE @@ -887,7 +894,7 @@ PetscSparseMtrx :: giveSubMatrix(const IntArray &rows, const IntArray &cols) prows.add(-1); pcols.add(-1); - PetscSparseMtrx *answer = new PetscSparseMtrx(prows.giveSize(), pcols.giveSize()); + std::unique_ptr answer = std::make_unique(prows.giveSize(), pcols.giveSize()); answer->emodel = this->emodel; IS is_rows; IS is_cols; @@ -898,7 +905,7 @@ PetscSparseMtrx :: giveSubMatrix(const IntArray &rows, const IntArray &cols) ISDestroy(& is_rows); ISDestroy(& is_cols); - return answer; + return std::move(answer); } void @@ -918,22 +925,25 @@ PetscSparseMtrx :: toFloatMatrix(FloatMatrix &answer) const void PetscSparseMtrx :: printStatistics() const { - PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_INFO); + PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_INFO); MatView(this->mtrx, PETSC_VIEWER_STDOUT_SELF); + PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF); } void PetscSparseMtrx :: printYourself() const { - PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_DENSE); + PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_DENSE); MatView(this->mtrx, PETSC_VIEWER_STDOUT_SELF); + PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF); } void PetscSparseMtrx :: printMatlab() const { - PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_MATLAB); + PetscViewerPushFormat(PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_ASCII_MATLAB); MatView(this->mtrx, PETSC_VIEWER_STDOUT_SELF); + PetscViewerPopFormat(PETSC_VIEWER_STDOUT_SELF); } void diff --git a/src/oofemlib/petscsparsemtrx.h b/src/oofemlib/petscsparsemtrx.h index 4d5b7fd6d..18c085efe 100644 --- a/src/oofemlib/petscsparsemtrx.h +++ b/src/oofemlib/petscsparsemtrx.h @@ -38,6 +38,8 @@ #include +#define _IFT_PetscSparseMtrx_Name "petsc" + namespace oofem { /** * This class provides an sparse matrix interface to PETSc Matrices @@ -65,43 +67,41 @@ class OOFEM_EXPORT PetscSparseMtrx : public SparseMtrx IS localIS, globalIS; public: - PetscSparseMtrx(int n, int m); - PetscSparseMtrx(); + PetscSparseMtrx(int n=0, int m=0); virtual ~PetscSparseMtrx(); - // Overloaded methods: - virtual SparseMtrx *GiveCopy() const; - virtual void times(const FloatArray &x, FloatArray &answer) const; - virtual void timesT(const FloatArray &x, FloatArray &answer) const; - virtual void times(const FloatMatrix &B, FloatMatrix &answer) const; - virtual void timesT(const FloatMatrix &B, FloatMatrix &answer) const; - virtual void times(double x); - virtual void add(double x, SparseMtrx &m); - virtual void addDiagonal(double x, FloatArray &m); - virtual int buildInternalStructure(EngngModel *eModel, int n, int m, const IntArray &I, const IntArray &J); - virtual int buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s); - virtual int buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s); - virtual int assemble(const IntArray &loc, const FloatMatrix &mat); - virtual int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat); - virtual int assembleBegin(); - virtual int assembleEnd(); - virtual SparseMtrx *giveSubMatrix(const IntArray &rows, const IntArray &cols); - virtual bool canBeFactorized() const { return false; } - virtual SparseMtrx *factorized() { return NULL; } - virtual FloatArray *backSubstitutionWith(FloatArray &y) const { return NULL; } - virtual void zero(); - virtual double computeNorm() const; - virtual double &at(int i, int j); - virtual double at(int i, int j) const; - virtual void toFloatMatrix(FloatMatrix &answer) const; - virtual void printStatistics() const; - virtual void printYourself() const; + std::unique_ptr clone() const override; + void times(const FloatArray &x, FloatArray &answer) const override; + void timesT(const FloatArray &x, FloatArray &answer) const override; + void times(const FloatMatrix &B, FloatMatrix &answer) const override; + void timesT(const FloatMatrix &B, FloatMatrix &answer) const override; + void times(double x) override; + void add(double x, SparseMtrx &m) override; + void addDiagonal(double x, FloatArray &m) override; + int buildInternalStructure(EngngModel *eModel, int n, int m, const IntArray &I, const IntArray &J) override; + int buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s) override; + int buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) override; + int assemble(const IntArray &loc, const FloatMatrix &mat) override; + int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) override; + int assembleBegin() override; + int assembleEnd() override; + std::unique_ptr giveSubMatrix(const IntArray &rows, const IntArray &cols) override; + bool canBeFactorized() const override { return false; } + SparseMtrx *factorized() override { return NULL; } + FloatArray *backSubstitutionWith(FloatArray &y) const override { return NULL; } + void zero() override; + double computeNorm() const override; + double &at(int i, int j) override; + double at(int i, int j) const override; + void toFloatMatrix(FloatMatrix &answer) const override; + void printStatistics() const override; + void printYourself() const override; void printMatlab() const; - virtual SparseMtrxType giveType() const; - virtual bool isAsymmetric() const; - virtual void writeToFile(const char *fname) const; - virtual const char *giveClassName() const { return "PetscSparseMtrx"; } + SparseMtrxType giveType() const override; + bool isAsymmetric() const override; + void writeToFile(const char *fname) const override; + const char *giveClassName() const override { return "PetscSparseMtrx"; } /// Creates a global vector that fits the instance of this matrix. void createVecGlobal(Vec *answer) const; diff --git a/src/oofemlib/piecewiselinfunction.C b/src/oofemlib/piecewiselinfunction.C index 2659350da..e650bf334 100644 --- a/src/oofemlib/piecewiselinfunction.C +++ b/src/oofemlib/piecewiselinfunction.C @@ -118,13 +118,13 @@ double PiecewiseLinFunction :: evaluateVelocityAtTime(double time) return 0.; } -IRResultType -PiecewiseLinFunction :: initializeFrom(InputRecord *ir) +void +PiecewiseLinFunction :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Function :: initializeFrom(ir); // Optional means, read data from external file (useful for very large sets of data) - if ( ir->hasField(_IFT_PiecewiseLinFunction_dataFile) ) { + if ( ir.hasField(_IFT_PiecewiseLinFunction_dataFile) ) { std :: list< double >t, ft; // Open the file; std :: string fname; @@ -164,8 +164,6 @@ PiecewiseLinFunction :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, values, _IFT_PiecewiseLinFunction_ft); IR_GIVE_OPTIONAL_FIELD(ir, this->parameterType, "paramtype"); } - - return Function :: initializeFrom(ir); } @@ -178,26 +176,22 @@ void PiecewiseLinFunction :: giveInputRecord(DynamicInputRecord &input) -contextIOResultType -PiecewiseLinFunction :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +PiecewiseLinFunction :: saveContext(DataStream &stream, ContextMode mode) { if ( mode & CM_Definition ) { dates.storeYourself(stream); values.storeYourself(stream); } - - return CIO_OK; } -contextIOResultType -PiecewiseLinFunction :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +PiecewiseLinFunction :: restoreContext(DataStream &stream, ContextMode mode) { if ( mode & CM_Definition ) { dates.restoreYourself(stream); values.restoreYourself(stream); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/oofemlib/piecewiselinfunction.h b/src/oofemlib/piecewiselinfunction.h index 8e05c86b9..410feaad5 100644 --- a/src/oofemlib/piecewiselinfunction.h +++ b/src/oofemlib/piecewiselinfunction.h @@ -62,17 +62,17 @@ class OOFEM_EXPORT PiecewiseLinFunction : public Function PiecewiseLinFunction(int i, Domain * d); virtual ~PiecewiseLinFunction() { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveClassName() const { return "PiecewiseLinFunction"; } - virtual const char *giveInputRecordName() const { return _IFT_PiecewiseLinFunction_Name; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveClassName() const override { return "PiecewiseLinFunction"; } + const char *giveInputRecordName() const override { return _IFT_PiecewiseLinFunction_Name; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual double evaluateAtTime(double t); - virtual double evaluateVelocityAtTime(double t); - virtual double evaluateAccelerationAtTime(double t) { return 0.; } + double evaluateAtTime(double t) override; + double evaluateVelocityAtTime(double t) override; + double evaluateAccelerationAtTime(double t) override { return 0.; } }; } // end namespace oofem #endif // piecewiselinfunction_h diff --git a/src/oofemlib/pointload.C b/src/oofemlib/pointload.C index 4d2fc144c..9722be088 100644 --- a/src/oofemlib/pointload.C +++ b/src/oofemlib/pointload.C @@ -53,10 +53,10 @@ PointLoad :: computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArra answer.times(factor); } -IRResultType -PointLoad :: initializeFrom(InputRecord *ir) +void +PointLoad :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Load :: initializeFrom(ir); int dummy; IR_GIVE_FIELD(ir, dummy, "ndofs"); @@ -69,8 +69,6 @@ PointLoad :: initializeFrom(InputRecord *ir) value = 0; IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_PointLoad_cstype); coordSystemType = ( CoordSystType ) value; - - return Load :: initializeFrom(ir); } diff --git a/src/oofemlib/pointload.h b/src/oofemlib/pointload.h index b3cad21f2..a27f1feed 100644 --- a/src/oofemlib/pointload.h +++ b/src/oofemlib/pointload.h @@ -76,26 +76,24 @@ class OOFEM_EXPORT PointLoad : public BodyLoad * @param n Load number. * @param d Domain to which new object will belongs. */ - PointLoad(int n, Domain * d) : BodyLoad(n, d) { - coordSystemType = CST_Global; - } + PointLoad(int n, Domain * d) : BodyLoad(n, d), coordSystemType(CST_Global) { } - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; /** * Gives coordinates of the receiver */ const FloatArray & giveCoordinates() const { return coords; } - virtual CoordSystType giveCoordSystMode() { return coordSystemType; } - //virtual FormulationType giveFormulationType () { return FT_Entity; } + CoordSystType giveCoordSystMode() override { return coordSystemType; } + //FormulationType giveFormulationType () override { return FT_Entity; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual bcType giveType() const { return lType; } - virtual bcGeomType giveBCGeoType() const { return PointLoadBGT; } - virtual const char *giveClassName() const { return "PointLoad"; } - virtual const char *giveInputRecordName() const { return _IFT_PointLoad_Name; } + bcType giveType() const override { return lType; } + bcGeomType giveBCGeoType() const override { return PointLoadBGT; } + const char *giveClassName() const override { return "PointLoad"; } + const char *giveInputRecordName() const override { return _IFT_PointLoad_Name; } }; } // end namespace oofem #endif // pointload_h diff --git a/src/oofemlib/prescribedgradient.C b/src/oofemlib/prescribedgradient.C index 8e81759b5..f58c29075 100644 --- a/src/oofemlib/prescribedgradient.C +++ b/src/oofemlib/prescribedgradient.C @@ -59,13 +59,7 @@ REGISTER_BoundaryCondition(PrescribedGradient); double PrescribedGradient :: give(Dof *dof, ValueModeType mode, double time) { DofIDItem id = dof->giveDofID(); - FloatArray *coords = dof->giveDofManager()->giveCoordinates(); - - if ( coords->giveSize() != this->mCenterCoord.giveSize() ) { - mCenterCoord.resizeWithValues(coords->giveSize()); -// OOFEM_ERROR("Size of coordinate system different from center coordinate in b.c."); -// printf("Warning: Size of coordinate system different from center coordinate in b.c.\n"); - } + const auto &coords = dof->giveDofManager()->giveCoordinates(); double factor = 0; if ( mode == VM_Total ) { @@ -79,9 +73,9 @@ double PrescribedGradient :: give(Dof *dof, ValueModeType mode, double time) } // Reminder: u_i = d_ij . (x_j - xb_j) = d_ij . dx_j FloatArray dx; - dx.beDifferenceOf(* coords, this->mCenterCoord); + dx.beDifferenceOf(coords, this->mCenterCoord); - mGradient.resizeWithData(coords->giveSize(), coords->giveSize()); + mGradient.resizeWithData(coords.giveSize(), coords.giveSize()); FloatArray u; u.beProductOf(mGradient, dx); @@ -90,12 +84,11 @@ double PrescribedGradient :: give(Dof *dof, ValueModeType mode, double time) ///@todo Use the user-specified dofs here instead: int pos = this->dofs.findFirstIndexOf(id); // printf("pos: %d\n", pos); - if(pos > 0 && pos <= u.giveSize()) { - return u.at(pos); - } - else { - // XFEM dofs - return 0.0; + if ( pos > 0 && pos <= u.giveSize() ) { + return u.at(pos); + } else { + // XFEM dofs + return 0.0; } } @@ -126,39 +119,39 @@ void PrescribedGradient :: updateCoefficientMatrix(FloatMatrix &C) } for ( auto &n : domain->giveDofManagers() ) { - FloatArray *coords = n->giveCoordinates(); - Dof *d1 = n->giveDofWithID( this->dofs(0) ); - Dof *d2 = n->giveDofWithID( this->dofs(1) ); + const auto &coords = n->giveCoordinates(); + Dof *d1 = n->giveDofWithID( this->dofs[0] ); + Dof *d2 = n->giveDofWithID( this->dofs[1] ); int k1 = d1->__givePrescribedEquationNumber(); int k2 = d2->__givePrescribedEquationNumber(); if ( nsd == 2 ) { if ( k1 ) { - C.at(k1, 1) = coords->at(1) - xbar; - C.at(k1, 4) = coords->at(2) - ybar; + C.at(k1, 1) = coords.at(1) - xbar; + C.at(k1, 4) = coords.at(2) - ybar; } if ( k2 ) { - C.at(k2, 2) = coords->at(2) - ybar; - C.at(k2, 3) = coords->at(1) - xbar; + C.at(k2, 2) = coords.at(2) - ybar; + C.at(k2, 3) = coords.at(1) - xbar; } } else { // nsd == 3 - Dof *d3 = n->giveDofWithID( this->dofs(2) ); + Dof *d3 = n->giveDofWithID( this->dofs[2] ); int k3 = d3->__givePrescribedEquationNumber(); if ( k1 ) { - C.at(k1, 1) = coords->at(1) - xbar; - C.at(k1, 6) = coords->at(2) - ybar; - C.at(k1, 5) = coords->at(3) - zbar; + C.at(k1, 1) = coords.at(1) - xbar; + C.at(k1, 6) = coords.at(2) - ybar; + C.at(k1, 5) = coords.at(3) - zbar; } if ( k2 ) { - C.at(k2, 2) = coords->at(2) - ybar; - C.at(k2, 9) = coords->at(1) - xbar; - C.at(k2, 4) = coords->at(3) - zbar; + C.at(k2, 2) = coords.at(2) - ybar; + C.at(k2, 9) = coords.at(1) - xbar; + C.at(k2, 4) = coords.at(3) - zbar; } if ( k3 ) { - C.at(k3, 3) = coords->at(3) - zbar; - C.at(k3, 8) = coords->at(1) - xbar; - C.at(k3, 7) = coords->at(2) - ybar; + C.at(k3, 3) = coords.at(3) - zbar; + C.at(k3, 8) = coords.at(1) - xbar; + C.at(k3, 7) = coords.at(2) - ybar; } } } @@ -235,16 +228,16 @@ void PrescribedGradient :: computeTangent(FloatMatrix &tangent, TimeStep *tStep) } -IRResultType PrescribedGradient :: initializeFrom(InputRecord *ir) +void PrescribedGradient :: initializeFrom(InputRecord &ir) { GeneralBoundaryCondition :: initializeFrom(ir); - return PrescribedGradientHomogenization :: initializeFrom(ir); + PrescribedGradientHomogenization :: initializeFrom(ir); } void PrescribedGradient :: giveInputRecord(DynamicInputRecord &input) { GeneralBoundaryCondition :: giveInputRecord(input); - return PrescribedGradientHomogenization :: giveInputRecord(input); + PrescribedGradientHomogenization :: giveInputRecord(input); } } // end namespace oofem diff --git a/src/oofemlib/prescribedgradient.h b/src/oofemlib/prescribedgradient.h index 829b15d89..134f58bc7 100644 --- a/src/oofemlib/prescribedgradient.h +++ b/src/oofemlib/prescribedgradient.h @@ -71,9 +71,9 @@ class OOFEM_EXPORT PrescribedGradient : public BoundaryCondition, public Prescri /// Destructor virtual ~PrescribedGradient() { } - virtual double give(Dof *dof, ValueModeType mode, double time); + double give(Dof *dof, ValueModeType mode, double time) override; - virtual bcType giveType() const { return DirichletBT; } + bcType giveType() const override { return DirichletBT; } /** * Initializes receiver according to object description stored in input record. @@ -83,8 +83,8 @@ class OOFEM_EXPORT PrescribedGradient : public BoundaryCondition, public Prescri * The prescribed tensor's columns must be equal to the size of the center coordinates. * The size of the center coordinates must be equal to the size of the coordinates in the applied nodes. */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; /** * Constructs a coefficient matrix for all prescribed unknowns. @@ -92,26 +92,26 @@ class OOFEM_EXPORT PrescribedGradient : public BoundaryCondition, public Prescri * @todo Perhaps this routine should only give results for the dof it prescribes? * @param C Coefficient matrix to fill. */ - void updateCoefficientMatrix(FloatMatrix &C); + virtual void updateCoefficientMatrix(FloatMatrix &C); /** * Computes the homogenized, macroscopic, field (stress). * @param sigma Output quantity (typically stress). * @param tStep Active time step. */ - virtual void computeField(FloatArray &sigma, TimeStep *tStep); + void computeField(FloatArray &sigma, TimeStep *tStep) override; /** * Computes the macroscopic tangent for homogenization problems through sensitivity analysis. * @param tangent Output tangent. * @param tStep Active time step. */ - virtual void computeTangent(FloatMatrix &tangent, TimeStep *tStep); + void computeTangent(FloatMatrix &tangent, TimeStep *tStep) override; - virtual void scale(double s) { mGradient.times(s); } + void scale(double s) override { mGradient.times(s); } - virtual const char *giveClassName() const { return "PrescribedGradient"; } - virtual const char *giveInputRecordName() const { return _IFT_PrescribedGradient_Name; } + const char *giveClassName() const override { return "PrescribedGradient"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedGradient_Name; } }; } // end namespace oofem diff --git a/src/oofemlib/prescribedgradientbcneumann.C b/src/oofemlib/prescribedgradientbcneumann.C index f07c3aa18..d7c37c67d 100644 --- a/src/oofemlib/prescribedgradientbcneumann.C +++ b/src/oofemlib/prescribedgradientbcneumann.C @@ -50,6 +50,10 @@ #include "engngm.h" #include "mathfem.h" +#ifdef _OPENMP +#include +#endif + namespace oofem { REGISTER_BoundaryCondition(PrescribedGradientBCNeumann); @@ -72,10 +76,10 @@ PrescribedGradientBCNeumann :: ~PrescribedGradientBCNeumann() } -IRResultType PrescribedGradientBCNeumann :: initializeFrom(InputRecord *ir) +void PrescribedGradientBCNeumann :: initializeFrom(InputRecord &ir) { ActiveBoundaryCondition :: initializeFrom(ir); - return PrescribedGradientHomogenization :: initializeFrom(ir); + PrescribedGradientHomogenization :: initializeFrom(ir); } @@ -98,7 +102,9 @@ void PrescribedGradientBCNeumann :: scale(double s) void PrescribedGradientBCNeumann :: assembleVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm) + const UnknownNumberingScheme &s, + FloatArray *eNorm, + void* lock) { IntArray sigma_loc; // For the displacements and stress respectively mpSigmaHom->giveLocationArray(mSigmaIds, sigma_loc, s); @@ -112,8 +118,13 @@ void PrescribedGradientBCNeumann :: assembleVector(FloatArray &answer, TimeStep double loadLevel = this->giveTimeFunction()->evaluateAtTime(tStep->giveTargetTime()); stressLoad.beScaled(-rve_size*loadLevel, gradVoigt); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(stressLoad, sigma_loc); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } else if ( type == InternalForcesVector ) { FloatMatrix Ke; FloatArray fe_v, fe_s; @@ -149,19 +160,28 @@ void PrescribedGradientBCNeumann :: assembleVector(FloatArray &answer, TimeStep // Note: The terms appear negative in the equations: fe_v.negated(); fe_s.negated(); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(fe_s, loc); // Contributions to delta_v equations answer.assemble(fe_v, sigma_loc); // Contribution to delta_s_i equations if ( eNorm != NULL ) { eNorm->assembleSquared(fe_s, masterDofIDs); eNorm->assembleSquared(fe_v, sigmaMasterDofIDs); } +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } } void PrescribedGradientBCNeumann :: assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale) + CharType type, + const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, + double scale, + void* lock) { if ( type == TangentStiffnessMatrix || type == SecantStiffnessMatrix || type == ElasticStiffnessMatrix ) { FloatMatrix Ke, KeT; @@ -189,9 +209,14 @@ void PrescribedGradientBCNeumann :: assemble(SparseMtrx &answer, TimeStep *tStep Ke.negated(); Ke.times(scale); KeT.beTranspositionOf(Ke); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(sigma_loc_r, loc_c, Ke); // Contribution to delta_s_i equations answer.assemble(loc_r, sigma_loc_c, KeT); // Contributions to delta_v equations +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } else { OOFEM_LOG_DEBUG("Skipping assembly in PrescribedGradientBCNeumann::assemble()."); @@ -277,9 +302,9 @@ void PrescribedGradientBCNeumann :: computeTangent(FloatMatrix &tangent, TimeSte } } - std :: unique_ptr< SparseMtrx > Kuu(Kff->giveSubMatrix(loc_u, loc_u)); + std :: unique_ptr< SparseMtrx > Kuu = Kff->giveSubMatrix(loc_u, loc_u); // NOTE: Kus is actually a dense matrix, but we have to make it a dense matrix first - std :: unique_ptr< SparseMtrx > Kus(Kff->giveSubMatrix(loc_u, loc_s)); + std :: unique_ptr< SparseMtrx > Kus = Kff->giveSubMatrix(loc_u, loc_s); FloatMatrix eye(Kus->giveNumberOfColumns(), Kus->giveNumberOfColumns()); eye.beUnitMatrix(); FloatMatrix KusD; @@ -327,26 +352,25 @@ void PrescribedGradientBCNeumann :: integrateTangent(FloatMatrix &oTangent, Elem std :: unique_ptr< IntegrationRule > ir; XfemElementInterface *xfemElInt = dynamic_cast< XfemElementInterface * >( e ); - if ( xfemElInt != NULL && domain->hasXfemManager() ) { - IntArray edgeNodes; + if ( xfemElInt && domain->hasXfemManager() ) { FEInterpolation2d *interp2d = dynamic_cast< FEInterpolation2d * >( interp ); - if ( interp2d == NULL ) { + if ( !interp2d ) { OOFEM_ERROR("failed to cast to FEInterpolation2d.") } - interp2d->computeLocalEdgeMapping(edgeNodes, iBndIndex); + const auto &edgeNodes = interp2d->computeLocalEdgeMapping(iBndIndex); -// const FloatArray &xS = * ( e->giveDofManager( edgeNodes.at(1) )->giveCoordinates() ); -// const FloatArray &xE = * ( e->giveDofManager( edgeNodes.at( edgeNodes.giveSize() ) )->giveCoordinates() ); +// const auto &xS = * ( e->giveDofManager( edgeNodes.at(1) )->giveCoordinates() ); +// const auto &xE = * ( e->giveDofManager( edgeNodes.at( edgeNodes.giveSize() ) )->giveCoordinates() ); std :: vector< Line >segments; std :: vector< FloatArray >intersecPoints; xfemElInt->partitionEdgeSegment(iBndIndex, segments, intersecPoints); MaterialMode matMode = e->giveMaterialMode(); - ir.reset( new DiscontinuousSegmentIntegrationRule(1, e, segments) ); + ir = std::make_unique(1, e, segments); int numPointsPerSeg = 1; ir->SetUpPointsOnLine(numPointsPerSeg, matMode); } else { - ir.reset( interp->giveBoundaryIntegrationRule(order, iBndIndex) ); + ir = interp->giveBoundaryIntegrationRule(order, iBndIndex); } oTangent.clear(); @@ -358,22 +382,23 @@ void PrescribedGradientBCNeumann :: integrateTangent(FloatMatrix &oTangent, Elem // Evaluate the normal; double detJ = interp->boundaryEvalNormal(normal, iBndIndex, lcoords, cellgeo); - interp->boundaryEvalN(n, iBndIndex, lcoords, cellgeo); + // Compute global coordinates of Gauss point + FloatArray globalCoord; + + interp->boundaryLocal2Global(globalCoord, iBndIndex, lcoords, cellgeo); + + // Compute local coordinates on the element + FloatArray bulkElLocCoords; + e->computeLocalCoordinates(bulkElLocCoords, globalCoord); + // If cracks cross the edge, special treatment is necessary. // Exploit the XfemElementInterface to minimize duplication of code. if ( xfemElInt != NULL && domain->hasXfemManager() ) { - // Compute global coordinates of Gauss point - FloatArray globalCoord; - - interp->boundaryLocal2Global(globalCoord, iBndIndex, lcoords, cellgeo); - - // Compute local coordinates on the element - FloatArray locCoord; - e->computeLocalCoordinates(locCoord, globalCoord); - xfemElInt->XfemElementInterface_createEnrNmatrixAt(nMatrix, locCoord, * e, false); + xfemElInt->XfemElementInterface_createEnrNmatrixAt(nMatrix, bulkElLocCoords, * e, false); } else { // Evaluate the velocity/displacement coefficients + interp->evalN(n, bulkElLocCoords, cellgeo); nMatrix.beNMatrixOf(n, nsd); } diff --git a/src/oofemlib/prescribedgradientbcneumann.h b/src/oofemlib/prescribedgradientbcneumann.h index fa057c0d1..cafa31e4a 100644 --- a/src/oofemlib/prescribedgradientbcneumann.h +++ b/src/oofemlib/prescribedgradientbcneumann.h @@ -58,31 +58,32 @@ class OOFEM_EXPORT PrescribedGradientBCNeumann : public ActiveBoundaryCondition, PrescribedGradientBCNeumann(int n, Domain *d); virtual ~PrescribedGradientBCNeumann(); - virtual int giveNumberOfInternalDofManagers() { return 1; } - virtual DofManager *giveInternalDofManager(int i); + int giveNumberOfInternalDofManagers() override { return 1; } + DofManager *giveInternalDofManager(int i) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual bcType giveType() const { return UnknownBT; } + bcType giveType() const override { return UnknownBT; } - virtual void scale(double s); + void scale(double s) override; - virtual void assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm = NULL); + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorm=nullptr, void* lock=nullptr) override; - virtual void assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0); + void assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, + double scale = 1.0, void* lock=nullptr) override; - virtual void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, - const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s); + void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) override; - virtual const char *giveClassName() const { return "PrescribedGradientBCNeumann"; } - virtual const char *giveInputRecordName() const { return _IFT_PrescribedGradientBCNeumann_Name; } + const char *giveClassName() const override { return "PrescribedGradientBCNeumann"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedGradientBCNeumann_Name; } - virtual void computeField(FloatArray &sigma, TimeStep *tStep); - virtual void computeTangent(FloatMatrix &tangent, TimeStep *tStep); + void computeField(FloatArray &sigma, TimeStep *tStep) override; + void computeTangent(FloatMatrix &tangent, TimeStep *tStep) override; void giveStressLocationArray(IntArray &oCols, const UnknownNumberingScheme &r_s); diff --git a/src/oofemlib/prescribedgradientbcperiodic.C b/src/oofemlib/prescribedgradientbcperiodic.C index a3bdcc59c..7c9aa0e6c 100644 --- a/src/oofemlib/prescribedgradientbcperiodic.C +++ b/src/oofemlib/prescribedgradientbcperiodic.C @@ -119,21 +119,21 @@ void PrescribedGradientBCPeriodic :: findSlaveToMasterMap() this->slavemap.clear(); for ( int inode : nodes ) { - Node *masterNode = NULL; + Node *masterNode = nullptr; Node *node = this->domain->giveNode(inode); - const FloatArray &masterCoord = *node->giveCoordinates(); + const auto &masterCoord = node->giveCoordinates(); //printf("node %d\n", node->giveLabel()); masterCoord.printYourself(); // The difficult part, what offset to subtract to find the master side; - for ( FloatArray &testJump : jumps ) { + for ( const FloatArray &testJump : jumps ) { coord.beDifferenceOf(masterCoord, testJump); masterNode = sl->giveNodeClosestToPoint(coord, fabs(jump.at(1))*1e-5); - if ( masterNode != NULL ) { + if ( masterNode ) { //printf("Found master (%d) to node %d (distance = %e)\n", masterNode->giveNumber(), node->giveNumber(), - // masterNode->giveCoordinates()->distance(coord)); + // distance(*masterNode->giveCoordinates(), coord)); break; } } - if ( masterNode != NULL ) { + if ( masterNode ) { this->slavemap.insert({node->giveNumber(), masterNode->giveNumber()}); } else { OOFEM_ERROR("Couldn't find master node!"); @@ -154,7 +154,7 @@ int PrescribedGradientBCPeriodic :: giveNumberOfMasterDofs(ActiveDof *dof) Dof *PrescribedGradientBCPeriodic :: giveMasterDof(ActiveDof *dof, int mdof) { if ( this->isStrainDof(dof) ) { - return NULL; + return nullptr; } if ( mdof == 1 ) { int node = this->slavemap[dof->giveDofManager()->giveNumber()]; @@ -163,8 +163,8 @@ Dof *PrescribedGradientBCPeriodic :: giveMasterDof(ActiveDof *dof, int mdof) return this->domain->giveDofManager(node)->giveDofWithID(dof->giveDofID()); } else { DofIDItem dofid = dof->giveDofID(); - FloatArray *coords = dof->giveDofManager()->giveCoordinates(); - int nsd = coords->giveSize(); + const auto &coords = dof->giveDofManager()->giveCoordinates(); + int nsd = coords.giveSize(); if ( dofid == D_u || dofid == V_u ) { return this->strain->giveDofWithID(strain_id[nsd*(mdof-2)]); } else if ( dofid == D_v || dofid == V_v ) { @@ -262,11 +262,11 @@ void PrescribedGradientBCPeriodic :: computeTangent(FloatMatrix &E, TimeStep *tS void PrescribedGradientBCPeriodic :: computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs) { DofManager *master = this->domain->giveDofManager(this->slavemap[dof->giveDofManager()->giveNumber()]); - FloatArray *coords = dof->giveDofManager()->giveCoordinates(); - FloatArray *masterCoords = master->giveCoordinates(); + const auto &coords = dof->giveDofManager()->giveCoordinates(); + const auto &masterCoords = master->giveCoordinates(); FloatArray dx; - dx.beDifferenceOf(* coords, * masterCoords ); + dx.beDifferenceOf(coords, masterCoords); int nsd = dx.giveSize(); // Number of spatial dimensions @@ -283,10 +283,10 @@ double PrescribedGradientBCPeriodic :: giveUnknown(double val, ValueModeType mod { DofManager *master = this->domain->giveDofManager(this->slavemap[dof->giveDofManager()->giveNumber()]); DofIDItem id = dof->giveDofID(); - FloatArray *coords = dof->giveDofManager()->giveCoordinates(); - FloatArray *masterCoords = master->giveCoordinates(); + const auto &coords = dof->giveDofManager()->giveCoordinates(); + const auto &masterCoords = master->giveCoordinates(); FloatArray dx, uM; - dx.beDifferenceOf(* coords, * masterCoords ); + dx.beDifferenceOf(coords, masterCoords); int ind; if ( id == D_u || id == V_u || id == P_f || id == T_f ) { @@ -368,15 +368,13 @@ bool PrescribedGradientBCPeriodic :: isStrainDof(Dof *dof) } -IRResultType PrescribedGradientBCPeriodic :: initializeFrom(InputRecord *ir) +void PrescribedGradientBCPeriodic :: initializeFrom(InputRecord &ir) { - IRResultType result; + ActiveBoundaryCondition :: initializeFrom(ir); + PrescribedGradientHomogenization::initializeFrom(ir); IR_GIVE_FIELD(ir, this->masterSet, _IFT_PrescribedGradientBCPeriodic_masterSet) IR_GIVE_FIELD(ir, this->jump, _IFT_PrescribedGradientBCPeriodic_jump) - - ActiveBoundaryCondition :: initializeFrom(ir); - return PrescribedGradientHomogenization::initializeFrom(ir); } diff --git a/src/oofemlib/prescribedgradientbcperiodic.h b/src/oofemlib/prescribedgradientbcperiodic.h index e845b5bf6..e5b25cf31 100644 --- a/src/oofemlib/prescribedgradientbcperiodic.h +++ b/src/oofemlib/prescribedgradientbcperiodic.h @@ -65,7 +65,7 @@ class OOFEM_EXPORT PrescribedGradientBCPeriodic : public ActiveBoundaryCondition std :: map< int, int > slavemap; FloatArray jump; - + int masterSet; /** @@ -77,32 +77,31 @@ class OOFEM_EXPORT PrescribedGradientBCPeriodic : public ActiveBoundaryCondition PrescribedGradientBCPeriodic(int n, Domain *d); virtual ~PrescribedGradientBCPeriodic(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void postInitialize(); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void postInitialize() override; - virtual int giveNumberOfInternalDofManagers(); - virtual DofManager *giveInternalDofManager(int i); + int giveNumberOfInternalDofManagers() override; + DofManager *giveInternalDofManager(int i) override; - virtual int giveNumberOfMasterDofs(ActiveDof *dof); - virtual Dof *giveMasterDof(ActiveDof *dof, int mdof); + int giveNumberOfMasterDofs(ActiveDof *dof) override; + Dof *giveMasterDof(ActiveDof *dof, int mdof) override; - virtual void computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs); - virtual void computeField(FloatArray &sigma, TimeStep *tStep); - virtual void computeTangent(FloatMatrix &E, TimeStep *tStep); + void computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs) override; + void computeField(FloatArray &sigma, TimeStep *tStep) override; + void computeTangent(FloatMatrix &E, TimeStep *tStep) override; + double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof) override; + double giveUnknown(ValueModeType mode, TimeStep *tStep, ActiveDof *dof) override; double giveUnknown(double val, ValueModeType mode, TimeStep *tStep, ActiveDof *dof); - virtual double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof); - virtual double giveUnknown(ValueModeType mode, TimeStep *tStep, ActiveDof *dof); - virtual bool isPrimaryDof(ActiveDof *dof); - virtual double giveBcValue(Dof *dof, ValueModeType mode, TimeStep *tStep); - virtual bool hasBc(Dof *dof, TimeStep *tStep); + bool isPrimaryDof(ActiveDof *dof) override; + double giveBcValue(Dof *dof, ValueModeType mode, TimeStep *tStep) override; + bool hasBc(Dof *dof, TimeStep *tStep) override; bool isStrainDof(Dof *dof); - virtual bool requiresActiveDofs() { return true; } - - virtual const char *giveClassName() const { return "PrescribedGradientBCPeriodic"; } - virtual const char *giveInputRecordName() const { return _IFT_PrescribedGradientBCPeriodic_Name; } + bool requiresActiveDofs() override { return true; } + const char *giveClassName() const override { return "PrescribedGradientBCPeriodic"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedGradientBCPeriodic_Name; } }; } // end namespace oofem diff --git a/src/oofemlib/prescribedgradientbcweak.C b/src/oofemlib/prescribedgradientbcweak.C index e399cf60d..a37e653db 100644 --- a/src/oofemlib/prescribedgradientbcweak.C +++ b/src/oofemlib/prescribedgradientbcweak.C @@ -52,8 +52,8 @@ #include "mathfem.h" #include "sparselinsystemnm.h" #include "unknownnumberingscheme.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/EngineeringModels/staticstructural.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/EngineeringModels/staticstructural.h" #include "timer.h" @@ -62,33 +62,26 @@ #include #include #include +#include + +#ifdef _OPENMP +#include +#endif + namespace oofem { void TracSegArray::giveTractionLocationArray(IntArray &rows, CharType type, const UnknownNumberingScheme &s) { - rows.clear(); - - IntArray tracElRows, trac_loc_r; - - mFirstNode->giveLocationArray({Trac_u, Trac_v}, trac_loc_r, s); - tracElRows.followedBy(trac_loc_r); - rows = tracElRows; + mFirstNode->giveLocationArray({Trac_u, Trac_v}, rows, s); } void TracSegArray :: setupIntegrationRuleOnEl() { - - Element *dummyEl = NULL; - mIntRule.reset( new DiscontinuousSegmentIntegrationRule(1, dummyEl, mInteriorSegmentsFine) ); - - // Material mode should not matter here. - MaterialMode matMode = _PlaneStrain; + mIntRule = std::make_unique(1, nullptr, mInteriorSegmentsFine); int numPointsPerSeg = 1; - mIntRule->SetUpPointsOnLine(numPointsPerSeg, matMode); - - + mIntRule->SetUpPointsOnLine(numPointsPerSeg, _PlaneStrain); } @@ -105,7 +98,6 @@ PrescribedGradientBCWeak :: PrescribedGradientBCWeak(int n, Domain *d) : mDuplicateCornerNodes(false), mTangDistPadding(0.0), mTracDofScaling(1.0e0), - mpDisplacementLock(NULL), mLockNodeInd(0), mDispLockScaling(1.0), mSpringNodeInd1(-1), @@ -119,30 +111,19 @@ PrescribedGradientBCWeak :: PrescribedGradientBCWeak(int n, Domain *d) : // Compute bounding box of the domain computeDomainBoundingBox(* d, mLC, mUC); } - } + PrescribedGradientBCWeak :: ~PrescribedGradientBCWeak() { clear(); } + void PrescribedGradientBCWeak :: clear() { - - for ( size_t i = 0; i < mpTracElNew.size(); i++ ) { - if ( mpTracElNew [ i ] != NULL ) { - delete mpTracElNew [ i ]; - mpTracElNew [ i ] = NULL; - } - } mpTracElNew.clear(); - - if ( mpDisplacementLock != NULL ) { - delete mpDisplacementLock; - mpDisplacementLock = NULL; - } - + mpDisplacementLock = nullptr; } //#define DAMAGE_TEST @@ -151,34 +132,29 @@ int PrescribedGradientBCWeak :: giveNumberOfInternalDofManagers() { int numDMan = mpTracElNew.size(); - if ( mpDisplacementLock != NULL ) { + if ( mpDisplacementLock ) { numDMan++; } return numDMan; } + DofManager *PrescribedGradientBCWeak :: giveInternalDofManager(int i) { if ( i - 1 < int( mpTracElNew.size() ) ) { - return mpTracElNew [ i - 1 ]->mFirstNode.get(); - } else { + return mpTracElNew [ i - 1 ].mFirstNode.get(); + } else { OOFEM_ERROR("return mpDisplacementLock") - return mpDisplacementLock; + return mpDisplacementLock.get(); } } -IRResultType PrescribedGradientBCWeak :: initializeFrom(InputRecord *ir) + +void PrescribedGradientBCWeak :: initializeFrom(InputRecord &ir) { - IRResultType result; - result = ActiveBoundaryCondition :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - result = PrescribedGradientHomogenization :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + ActiveBoundaryCondition :: initializeFrom(ir); + PrescribedGradientHomogenization :: initializeFrom(ir); IR_GIVE_FIELD(ir, mTractionInterpOrder, _IFT_PrescribedGradientBCWeak_TractionInterpOrder); // printf("mTractionInterpOrder: %d\n", mTractionInterpOrder); @@ -221,10 +197,9 @@ IRResultType PrescribedGradientBCWeak :: initializeFrom(InputRecord *ir) if ( mMirrorFunction == 0 ) { mPeriodicityNormal = {0.0, 1.0}; } - - return IRRT_OK; } + void PrescribedGradientBCWeak :: giveInputRecord(DynamicInputRecord &input) { ActiveBoundaryCondition :: giveInputRecord(input); @@ -254,7 +229,9 @@ void PrescribedGradientBCWeak :: postInitialize() void PrescribedGradientBCWeak :: assembleVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm) + const UnknownNumberingScheme &s, + FloatArray *eNorm, + void* lock) { int dim = domain->giveNumberOfSpatialDimensions(); @@ -263,46 +240,61 @@ void PrescribedGradientBCWeak :: assembleVector(FloatArray &answer, TimeStep *tS // f_ext = int N^trac H . (x - x_c) - for ( TracSegArray* el : mpTracElNew ) { + for ( auto &el : mpTracElNew ) { FloatArray contrib; - computeExtForceElContrib(contrib, *el, dim, tStep); + computeExtForceElContrib(contrib, el, dim, tStep); IntArray rows; - el->giveTractionLocationArray(rows, type, s); + el.giveTractionLocationArray(rows, type, s); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(contrib, rows); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } else if ( type == InternalForcesVector ) { - for ( TracSegArray* el : mpTracElNew ) { + for ( auto &el : mpTracElNew ) { - for ( GaussPoint *gp: *(el->mIntRule.get()) ) { + for ( auto &gp: *el.mIntRule ) { // Contribution on gamma_plus FloatArray contrib_disp, contrib_trac; IntArray disp_loc_array, trac_loc_array; - computeIntForceGPContrib(contrib_disp, disp_loc_array, contrib_trac, trac_loc_array, *el, *gp, dim, tStep, gp->giveGlobalCoordinates(), 1.0, mode, type, s); + computeIntForceGPContrib(contrib_disp, disp_loc_array, contrib_trac, trac_loc_array, el, *gp, dim, tStep, gp->giveGlobalCoordinates(), 1.0, mode, type, s); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(contrib_disp, disp_loc_array); answer.assemble(contrib_trac, trac_loc_array); - +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif // Contribution on gamma_minus contrib_disp.clear(); contrib_trac.clear(); disp_loc_array.clear(); trac_loc_array.clear(); FloatArray xMinus; this->giveMirroredPointOnGammaMinus(xMinus, gp->giveGlobalCoordinates()); - computeIntForceGPContrib(contrib_disp, disp_loc_array, contrib_trac, trac_loc_array, *el, *gp, dim, tStep, xMinus, -1.0, mode, type, s); + computeIntForceGPContrib(contrib_disp, disp_loc_array, contrib_trac, trac_loc_array, el, *gp, dim, tStep, xMinus, -1.0, mode, type, s); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(contrib_disp, disp_loc_array); answer.assemble(contrib_trac, trac_loc_array); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } - - - if ( mpDisplacementLock != NULL ) { + if ( mpDisplacementLock ) { IntArray dispLockRows; mpDisplacementLock->giveLocationArray(giveDispLockDofIDs(), dispLockRows, s); @@ -317,8 +309,13 @@ void PrescribedGradientBCWeak :: assembleVector(FloatArray &answer, TimeStep *tS } fe_dispLock.times(mDispLockScaling); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(fe_dispLock, dispLockRows); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } @@ -330,7 +327,7 @@ void PrescribedGradientBCWeak :: computeExtForceElContrib(FloatArray &oContrib, oContrib.clear(); FloatArray contrib_gp; - for ( GaussPoint *gp: *(iEl.mIntRule.get()) ) { + for ( auto &gp: *iEl.mIntRule ) { // Fetch global coordinate x const FloatArray &x = gp->giveGlobalCoordinates(); @@ -409,23 +406,28 @@ void PrescribedGradientBCWeak :: computeIntForceGPContrib(FloatArray &oContrib_d oContrib_trac.negated(); } -void PrescribedGradientBCWeak :: assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale) +void PrescribedGradientBCWeak :: assemble( SparseMtrx &answer, + TimeStep *tStep, + CharType type, + const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, + double scale, + void* lock) { std::vector gpCoordArray; if ( type == TangentStiffnessMatrix || type == SecantStiffnessMatrix || type == ElasticStiffnessMatrix ) { - for ( TracSegArray* el : mpTracElNew ) { + for ( auto &el : mpTracElNew ) { - for ( GaussPoint *gp: *(el->mIntRule.get()) ) { + for ( auto &gp: *el.mIntRule ) { gpCoordArray.push_back( gp->giveGlobalCoordinates() ); - assembleGPContrib(answer, tStep, type, r_s, c_s, *el, *gp, scale); + assembleGPContrib(answer, tStep, type, r_s, c_s, el, *gp, scale); } } - if ( mpDisplacementLock != NULL ) { + if ( mpDisplacementLock ) { int nsd = domain->giveNumberOfSpatialDimensions(); FloatMatrix KeDispLock(nsd, nsd); KeDispLock.beUnitMatrix(); @@ -440,14 +442,25 @@ void PrescribedGradientBCWeak :: assemble(SparseMtrx &answer, TimeStep *tStep, mpDisplacementLock->giveLocationArray(giveDispLockDofIDs(), lockCols, c_s); node->giveLocationArray(giveRegularDispDofIDs(), nodeCols, c_s); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(lockRows, nodeCols, KeDispLock); answer.assemble(nodeRows, lockCols, KeDispLock); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif FloatMatrix KZero( lockRows.giveSize(), lockCols.giveSize() ); KZero.zero(); KZero.times(scale); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(lockRows, lockCols, KZero); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } @@ -464,7 +477,13 @@ void PrescribedGradientBCWeak :: assemble(SparseMtrx &answer, TimeStep *tStep, node1->giveLocationArray(giveRegularDispDofIDs(), nodeRows, r_s); node1->giveLocationArray(giveRegularDispDofIDs(), nodeCols, c_s); KeDispLock.times(scale); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(nodeRows, nodeCols, KeDispLock); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } else { @@ -546,7 +565,9 @@ void PrescribedGradientBCWeak :: assembleExtraDisplock(SparseMtrx &answer, TimeS } void PrescribedGradientBCWeak :: assembleGPContrib(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, TracSegArray &iEl, GaussPoint &iGP, double k) + CharType type, const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, TracSegArray &iEl, + GaussPoint &iGP, double k, void* lock) { SpatialLocalizer *localizer = domain->giveSpatialLocalizer(); @@ -571,14 +592,23 @@ void PrescribedGradientBCWeak :: assembleGPContrib(SparseMtrx &answer, TimeStep dispEl->giveLocationArray(disp_cols, c_s); contrib.times(k); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(trac_rows, disp_cols, contrib); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif FloatMatrix contribT; contribT.beTranspositionOf(contrib); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(disp_cols, trac_rows, contribT); - - - +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif /////////////// // Gamma_minus contrib.clear(); @@ -600,19 +630,35 @@ void PrescribedGradientBCWeak :: assembleGPContrib(SparseMtrx &answer, TimeStep disp_cols.clear(); dispEl->giveLocationArray(disp_cols, c_s); contrib.times(k); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(trac_rows, disp_cols, contrib); - +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif contribT.clear(); contribT.beTranspositionOf(contrib); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(disp_cols, trac_rows, contribT); - +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif // Assemble zeros on diagonal (required by PETSc solver) FloatMatrix KZero(1,1); KZero.zero(); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif for ( int i : trac_rows) { answer.assemble(IntArray({i}), IntArray({i}), KZero); } +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } void PrescribedGradientBCWeak :: giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, @@ -626,14 +672,13 @@ void PrescribedGradientBCWeak :: giveTractionLocationArray(IntArray &rows, { // Used for the condensation when computing the macroscopic tangent. - rows.clear(); // Loop over traction elements - for ( TracSegArray* el : mpTracElNew ) { + for ( auto &el : mpTracElNew ) { IntArray trac_loc_r; - el->mFirstNode->giveLocationArray(giveTracDofIDs(), trac_loc_r, s); + el.mFirstNode->giveLocationArray(giveTracDofIDs(), trac_loc_r, s); rows.followedBy(trac_loc_r); } @@ -645,7 +690,7 @@ void PrescribedGradientBCWeak :: giveTractionLocationArray(IntArray &rows, for ( size_t tracElInd = 0; tracElInd < mpTractionElements.size(); tracElInd++ ) { IntArray tracElRows, trac_loc_r; - const TractionElement &tEl = * ( mpTractionElements [ tracElInd ] ); + const TractionElement &tEl = mpTractionElements [ tracElInd ]; for ( int tracNodeInd : tEl.mTractionNodeInd ) { Node *tNode = mpTractionNodes [ tracNodeInd ]; tNode->giveLocationArray(giveTracDofIDs(), trac_loc_r, s); @@ -655,8 +700,7 @@ void PrescribedGradientBCWeak :: giveTractionLocationArray(IntArray &rows, rows.followedBy(tracElRows); } - - if ( mpDisplacementLock != NULL ) { + if ( mpDisplacementLock ) { IntArray dispLock_r; mpDisplacementLock->giveLocationArray(giveDispLockDofIDs(), dispLock_r, s); @@ -665,11 +709,9 @@ void PrescribedGradientBCWeak :: giveTractionLocationArray(IntArray &rows, #endif } -void PrescribedGradientBCWeak :: giveDisplacementLocationArray(IntArray &rows, - const UnknownNumberingScheme &s) +void PrescribedGradientBCWeak :: giveDisplacementLocationArray(IntArray &rows, const UnknownNumberingScheme &s) { // Used for the condensation when computing the macroscopic tangent. - } void PrescribedGradientBCWeak :: compute_x_times_N_1(FloatMatrix &o_x_times_N) @@ -683,18 +725,18 @@ void PrescribedGradientBCWeak :: compute_x_times_N_1(FloatMatrix &o_x_times_N) int num_t_eq = loc_t.giveSize(); -// o_x_times_N.resize(3, num_t_eq); + //o_x_times_N.resize(3, num_t_eq); o_x_times_N.resize(num_t_eq,3); IntArray cols = {1,2,3}; int trac_el_ind = 1; - for ( auto *el: mpTracElNew ) { + for ( auto &el : mpTracElNew ) { IntArray rows = {trac_el_ind*2-1,trac_el_ind*2}; - for ( GaussPoint *gp: *(el->mIntRule.get()) ) { + for ( auto &gp : *el.mIntRule ) { FloatMatrix contrib(2,3); @@ -711,7 +753,7 @@ void PrescribedGradientBCWeak :: compute_x_times_N_1(FloatMatrix &o_x_times_N) // // Compute vector of traction unknowns // FloatArray tracUnknowns; -// el->mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), VM_Total, tStep); +// el.mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), VM_Total, tStep); // FloatArray traction; @@ -746,7 +788,7 @@ void PrescribedGradientBCWeak :: compute_x_times_N_1(FloatMatrix &o_x_times_N) // contrib = coord_mat; - double detJ = 0.5 * el->giveLength(); + double detJ = 0.5 * el.giveLength(); contrib.times( detJ * gp->giveWeight() ); // printf("\n\ncontrib: "); contrib.printYourself(); @@ -771,18 +813,18 @@ void PrescribedGradientBCWeak :: compute_x_times_N_2(FloatMatrix &o_x_times_N) int num_t_eq = loc_t.giveSize(); -// o_x_times_N.resize(4, num_t_eq); + //o_x_times_N.resize(4, num_t_eq); o_x_times_N.resize(3, num_t_eq); IntArray rows = {1,2,3}; int trac_el_ind = 1; - for ( auto *el: mpTracElNew ) { + for ( auto &el : mpTracElNew ) { IntArray cols = {trac_el_ind*2-1,trac_el_ind*2}; - for ( GaussPoint *gp: *(el->mIntRule.get()) ) { + for ( auto &gp : *el.mIntRule ) { FloatMatrix contrib(4,2); @@ -799,7 +841,7 @@ void PrescribedGradientBCWeak :: compute_x_times_N_2(FloatMatrix &o_x_times_N) // // Compute vector of traction unknowns // FloatArray tracUnknowns; -// el->mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), VM_Total, tStep); +// el.mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), VM_Total, tStep); // FloatArray traction; @@ -832,7 +874,7 @@ void PrescribedGradientBCWeak :: compute_x_times_N_2(FloatMatrix &o_x_times_N) // contrib = coord_mat; - double detJ = 0.5 * el->giveLength(); + double detJ = 0.5 * el.giveLength(); contrib.times( detJ * gp->giveWeight() ); // printf("\n\ncontrib: "); contrib.printYourself(); @@ -857,9 +899,9 @@ void PrescribedGradientBCWeak :: computeField(FloatArray &sigma, TimeStep *tStep const int dim = domain->giveNumberOfSpatialDimensions(); FloatMatrix stressMatrix(dim, dim); - for ( auto *el: mpTracElNew ) { + for ( auto &el : mpTracElNew ) { - for ( GaussPoint *gp: *(el->mIntRule.get()) ) { + for ( auto &gp : *el.mIntRule ) { // For now, assume piecewise constant approx FloatArray Ntrac = FloatArray { 1.0*mTracDofScaling }; @@ -873,7 +915,7 @@ void PrescribedGradientBCWeak :: computeField(FloatArray &sigma, TimeStep *tStep // Compute vector of traction unknowns FloatArray tracUnknowns; - el->mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), VM_Total, tStep); + el.mFirstNode->giveUnknownVector(tracUnknowns, giveTracDofIDs(), VM_Total, tStep); FloatArray traction; @@ -885,7 +927,7 @@ void PrescribedGradientBCWeak :: computeField(FloatArray &sigma, TimeStep *tStep FloatMatrix contrib; contrib.beDyadicProductOf(traction, tmp); - double detJ = 0.5 * el->giveLength(); + double detJ = 0.5 * el.giveLength(); contrib.times( detJ * gp->giveWeight() ); for ( int m = 0; m < dim; m++ ) { @@ -953,14 +995,16 @@ void PrescribedGradientBCWeak :: computeTangent(FloatMatrix& E, TimeStep* tStep) OOFEM_ERROR("Couldn't create sparse matrix of type %d\n", stype); } +#ifdef __SM_MODULE StaticStructural *rveStatStruct = dynamic_cast(rve); if ( rveStatStruct ) { -// printf("Successfully casted rve to StaticStructural.\n"); + //printf("Successfully casted rve to StaticStructural.\n"); if ( rveStatStruct->stiffnessMatrix ) { - Kmicro.reset( rveStatStruct->stiffnessMatrix->GiveCopy() ); + Kmicro = rveStatStruct->stiffnessMatrix->clone(); } } +#endif #ifdef TIME_INFO @@ -968,7 +1012,7 @@ void PrescribedGradientBCWeak :: computeTangent(FloatMatrix& E, TimeStep* tStep) #endif if ( Kmicro->giveNumberOfColumns() == 0 ) { -// printf("Rebuilding stiffness matrix.\n"); + //printf("Rebuilding stiffness matrix.\n"); Kmicro->buildInternalStructure(rve, this->domain->giveNumber(), fnum); rve->assemble(*Kmicro, tStep, TangentAssembler(TangentStiffness), fnum, this->domain); } @@ -983,7 +1027,6 @@ void PrescribedGradientBCWeak :: computeTangent(FloatMatrix& E, TimeStep* tStep) printf("Assembly time for RVE tangent: %e\n", assemble_time); #endif - // Fetch displacement and traction location arrays IntArray loc_u, loc_t; @@ -999,25 +1042,21 @@ void PrescribedGradientBCWeak :: computeTangent(FloatMatrix& E, TimeStep* tStep) } } - // Fetch the submatrices - std :: unique_ptr< SparseMtrx > S(Kmicro->giveSubMatrix(loc_u, loc_u)); + std :: unique_ptr< SparseMtrx > S = Kmicro->giveSubMatrix(loc_u, loc_u); // NOTE: Kus is actually a dense matrix, but we have to make it a dense matrix first - std :: unique_ptr< SparseMtrx > C(Kmicro->giveSubMatrix(loc_u, loc_t)); + std :: unique_ptr< SparseMtrx > C = Kmicro->giveSubMatrix(loc_u, loc_t); FloatMatrix Cd; C->toFloatMatrix(Cd); - // Let Sm = C. Solve for m. FloatMatrix m; solver->solve(*S, Cd, m); - // Compute G := C^T m. (Which could, formally, be written as G = C^T S^-1 C.) FloatMatrix G; G.beTProductOf(Cd, m); - // Compute D := \int x \otimes N FloatMatrix D; compute_x_times_N_1(D); @@ -1025,7 +1064,6 @@ void PrescribedGradientBCWeak :: computeTangent(FloatMatrix& E, TimeStep* tStep) // compute_x_times_N_1(DT2); // D.beTranspositionOf(DT); - // Let Gp = D. Solve for p. (Which could, formally, be written as p = G^-1 D = (C^T S^-1 C)^-1 D.) // Need to make G sparse; std :: unique_ptr< SparseMtrx > Gs( classFactory.createSparseMtrx(stype) ); @@ -1034,11 +1072,8 @@ void PrescribedGradientBCWeak :: computeTangent(FloatMatrix& E, TimeStep* tStep) } int num_eq_G = G.giveNumberOfRows(); - IntArray loc_G(num_eq_G); - - for ( int i = 1; i <= num_eq_G; i++) { - loc_G.at(i) = i; - } + IntArray loc_G; + loc_G.enumerate(num_eq_G); Gs->buildInternalStructure(rve, num_eq_G, num_eq_G, loc_G, loc_G); Gs->assemble(loc_G, loc_G, G); @@ -1048,11 +1083,9 @@ void PrescribedGradientBCWeak :: computeTangent(FloatMatrix& E, TimeStep* tStep) // Gs->writeToFile("Gs.txt"); - FloatMatrix p; solver->solve(*Gs, D, p); - // Compute d_sigma_depsilon = D^T p. FloatMatrix Ered; Ered.beTProductOf(D,p); @@ -1061,8 +1094,9 @@ void PrescribedGradientBCWeak :: computeTangent(FloatMatrix& E, TimeStep* tStep) // printf("rve_size: %e\n", rve_size); // Ered.printYourself(); - IntArray indx; - StructuralMaterial :: giveVoigtVectorMask(indx, _PlaneStress); + IntArray indx = {1,2,6,9}; // to make it independednt of sm module + //StructuralMaterial :: giveVoigtVectorMask(indx, _PlaneStress); + // FloatMatrix EredT; // EredT.beTranspositionOf(Ered); @@ -1123,16 +1157,15 @@ void PrescribedGradientBCWeak :: giveBoundaries(IntArray &oBoundaries) void PrescribedGradientBCWeak :: giveTraction(size_t iElInd, FloatArray &oStartTraction, FloatArray &oEndTraction, ValueModeType mode, TimeStep *tStep) { - // For now, assuming piecewise constant traction - mpTracElNew[iElInd]->mFirstNode->giveUnknownVector(oStartTraction, giveTracDofIDs(), mode, tStep); - oStartTraction.times(mTracDofScaling); - mpTracElNew[iElInd]->mFirstNode->giveUnknownVector(oEndTraction, giveTracDofIDs(), mode, tStep); - oEndTraction.times(mTracDofScaling); + // For now, assuming piecewise constant traction + mpTracElNew[iElInd].mFirstNode->giveUnknownVector(oStartTraction, giveTracDofIDs(), mode, tStep); + oStartTraction.times(mTracDofScaling); + mpTracElNew[iElInd].mFirstNode->giveUnknownVector(oEndTraction, giveTracDofIDs(), mode, tStep); + oEndTraction.times(mTracDofScaling); } void PrescribedGradientBCWeak :: recomputeTractionMesh() { -// printf("Recomputing traction mesh.\n"); clear(); postInitialize(); } @@ -1148,7 +1181,6 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici std::vector holeCoordUnsorted, allCoordUnsorted; findHoleCoord(holeCoordUnsorted, allCoordUnsorted); - // Add corner points holeCoordUnsorted.push_back( {mUC[0], mLC[1]} ); allCoordUnsorted.push_back( {mUC[0], mLC[1]} ); @@ -1163,8 +1195,6 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici // Add crack-boundary intersections findCrackBndIntersecCoord(holeCoordUnsorted); - - // Add periodicity points findPeriodicityCoord(holeCoordUnsorted); @@ -1183,30 +1213,24 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici pointsPassed = 0; } - pointsPassed++; } - // Sort again std :: sort( holeCoordUnsorted.begin(), holeCoordUnsorted.end(), ArcPosSortFunction4( mLC, mUC, 1.0e-4 ) ); std :: sort( allCoordUnsorted.begin(), allCoordUnsorted.end(), ArcPosSortFunction4( mLC, mUC, 1.0e-4 ) ); - - // Remove points that are too close to each other removeClosePoints(holeCoordUnsorted, minPointDist); - removeClosePoints(allCoordUnsorted, minPointDist); - // Create two arrays of segments, where each array represents the coarsest possible traction // mesh on one side of the RVE ArcPosSortFunction4 arcPosFunc( mLC, mUC, 1.0e-4 ); - std :: vector< TracSegArray * > tracElNew0, tracElNew1; - tracElNew0.push_back(new TracSegArray()); - tracElNew1.push_back(new TracSegArray()); + std :: vector< TracSegArray > tracElNew0, tracElNew1; + tracElNew0.emplace_back(); + //tracElNew1.emplace_back(); for (size_t i = 1; i < holeCoordUnsorted.size(); i++) { @@ -1217,15 +1241,15 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici const FloatArray xC = {0.5*(xS[0]+xE[0]), 0.5*(xS[1]+xE[1])}; if ( arcPosFunc.calcArcPos(xC) < 2.*l_s ) { - tracElNew0[0]->mInteriorSegments.push_back( Line(xS, xE) ); + tracElNew0[0].mInteriorSegments.emplace_back(xS, xE); } else { - tracElNew1[0]->mInteriorSegments.push_back( Line(xS, xE) ); + tracElNew1[0].mInteriorSegments.emplace_back(xS, xE); } } // Remove segments located in holes - removeSegOverHoles(*(tracElNew0[0]), 1.0e-4); - removeSegOverHoles(*(tracElNew1[0]), 1.0e-4); + removeSegOverHoles(tracElNew0[0], 1.0e-4); + removeSegOverHoles(tracElNew1[0], 1.0e-4); if ( split_at_holes ) { splitSegments(tracElNew0); @@ -1235,8 +1259,6 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici // Identify additional points that can be used to refine the traction mesh - - ////////////////////////////////////////////////// // Create traction dofs int numNodes = domain->giveNumberOfDofManagers(); @@ -1253,37 +1275,37 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici // we can always create on node on each element. // RVE side at x=L - for ( TracSegArray* el : tracElNew0 ) { + for ( auto &el : tracElNew0 ) { ////////////////////////////////////////////////////// // Create first node totNodesCreated++; - el->mFirstNode.reset( new Node(numNodes + 1, domain) ); - el->mFirstNode->setGlobalNumber(numNodes + 1); + el.mFirstNode = std::make_unique(numNodes + 1, domain); + el.mFirstNode->setGlobalNumber(numNodes + 1); for ( auto &dofId: giveTracDofIDs() ) { - el->mFirstNode->appendDof( new MasterDof(el->mFirstNode.get(), ( DofIDItem ) dofId) ); + el.mFirstNode->appendDof( new MasterDof(el.mFirstNode.get(), ( DofIDItem ) dofId) ); } - el->mFirstNode->setCoordinates( el->mInteriorSegments[0].giveVertex(1) ); + el.mFirstNode->setCoordinates( el.mInteriorSegments[0].giveVertex(1) ); numNodes++; } // RVE side at y=L - for ( TracSegArray* el : tracElNew1 ) { + for ( auto &el : tracElNew1 ) { ////////////////////////////////////////////////////// // Create first node totNodesCreated++; - el->mFirstNode.reset( new Node(numNodes + 1, domain) ); - el->mFirstNode->setGlobalNumber(numNodes + 1); + el.mFirstNode = std::make_unique(numNodes + 1, domain); + el.mFirstNode->setGlobalNumber(numNodes + 1); for ( auto &dofId: giveTracDofIDs() ) { - el->mFirstNode->appendDof( new MasterDof(el->mFirstNode.get(), ( DofIDItem ) dofId) ); + el.mFirstNode->appendDof( new MasterDof(el.mFirstNode.get(), ( DofIDItem ) dofId) ); } - el->mFirstNode->setCoordinates( el->mInteriorSegments[0].giveVertex(1) ); + el.mFirstNode->setCoordinates( el.mInteriorSegments[0].giveVertex(1) ); numNodes++; } @@ -1291,12 +1313,12 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici // Lock displacement in one node if we use periodic BCs int numNodes = domain->giveNumberOfDofManagers(); - mpDisplacementLock = new Node(numNodes + 1, domain); + mpDisplacementLock = std::make_unique(numNodes + 1, domain); mLockNodeInd = domain->giveElement(1)->giveNode(1)->giveGlobalNumber(); for ( auto &dofid: giveDispLockDofIDs() ) { - mpDisplacementLock->appendDof( new MasterDof(mpDisplacementLock, ( DofIDItem ) dofid) ); + mpDisplacementLock->appendDof( new MasterDof(mpDisplacementLock.get(), ( DofIDItem ) dofid) ); } } @@ -1326,9 +1348,9 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici // printf("mSpringNodeInd3: %d\n", mSpringNodeInd3 ); - mpTracElNew.reserve(tracElNew0.size() + tracElNew1.size()); - std::move(tracElNew0.begin(), tracElNew0.end(), std::inserter(mpTracElNew, mpTracElNew.end())); - std::move(tracElNew1.begin(), tracElNew1.end(), std::inserter(mpTracElNew, mpTracElNew.end())); + mpTracElNew.reserve(mpTracElNew.size() + tracElNew0.size() + tracElNew1.size()); + std::move(tracElNew0.begin(), tracElNew0.end(), std::back_inserter(mpTracElNew)); + std::move(tracElNew1.begin(), tracElNew1.end(), std::back_inserter(mpTracElNew)); tracElNew0.clear(); tracElNew1.clear(); @@ -1337,12 +1359,12 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici // Segment arrays for Gauss quadrature size_t i = 0; - for ( TracSegArray* el : mpTracElNew ) { + for ( auto & el : mpTracElNew ) { - const FloatArray &xS = el->mInteriorSegments[0].giveVertex(1); + const FloatArray &xS = el.mInteriorSegments[0].giveVertex(1); const double arcPosXS = arcPosFunc.calcArcPos(xS); - const FloatArray &xE = el->mInteriorSegments.back().giveVertex(2); + const FloatArray &xE = el.mInteriorSegments.back().giveVertex(2); const double arcPosXE = arcPosFunc.calcArcPos(xE); while (i < allCoordUnsorted.size()) { @@ -1352,7 +1374,7 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici const double arcPosX = arcPosFunc.calcArcPos(x); if ( arcPosX > (arcPosXS+minPointDist) && arcPosX < (arcPosXE-minPointDist) ) { - el->mInteriorSegmentsPointsFine.push_back(x); + el.mInteriorSegmentsPointsFine.push_back(std::move(x)); } if ( arcPosX > arcPosXE ) { @@ -1365,11 +1387,11 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici // Now we have the necessary points on each traction element. // The next step is to create splitted segments. - for ( TracSegArray* el : mpTracElNew ) { + for ( auto & el : mpTracElNew ) { i = 0; - for ( Line &line : el->mInteriorSegments ) { + for ( auto &line : el.mInteriorSegments ) { FloatArray xS = line.giveVertex(1); xS.resizeWithValues(2); const double arcPosXS = arcPosFunc.calcArcPos(xS); @@ -1378,13 +1400,13 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici xE.resizeWithValues(2); const double arcPosXE = arcPosFunc.calcArcPos(xE); - if ( el->mInteriorSegmentsPointsFine.size() == 0 ) { + if ( el.mInteriorSegmentsPointsFine.size() == 0 ) { Line newLine(xS, xE); - el->mInteriorSegmentsFine.push_back(newLine); + el.mInteriorSegmentsFine.push_back(newLine); } else { - while ( i < el->mInteriorSegmentsPointsFine.size() ) { + while ( i < el.mInteriorSegmentsPointsFine.size() ) { - const FloatArray &x = el->mInteriorSegmentsPointsFine[i]; + const FloatArray &x = el.mInteriorSegmentsPointsFine[i]; const double arcPosX = arcPosFunc.calcArcPos(x); if ( arcPosX < arcPosXS ) { @@ -1394,21 +1416,21 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici if ( arcPosX < arcPosXE ) { // Split from start pos to x Line newLine(xS, x); - el->mInteriorSegmentsFine.push_back(newLine); + el.mInteriorSegmentsFine.push_back(newLine); xS = x; } else { // Split from x to end pos Line newLine(xS, xE); - el->mInteriorSegmentsFine.push_back(newLine); + el.mInteriorSegmentsFine.push_back(newLine); break; } - if ( i == (el->mInteriorSegmentsPointsFine.size()-1) ) { + if ( i == (el.mInteriorSegmentsPointsFine.size()-1) ) { // Split from x to end pos Line newLine(xS, xE); - el->mInteriorSegmentsFine.push_back(newLine); + el.mInteriorSegmentsFine.push_back(newLine); } i++; @@ -1418,16 +1440,16 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici } // Create integration rules - for ( TracSegArray* el : mpTracElNew ) { - el->setupIntegrationRuleOnEl(); + for ( auto & el : mpTracElNew ) { + el.setupIntegrationRuleOnEl(); } // Write discontinuity points to debug vtk std :: vector< FloatArray > discPoints; - for ( TracSegArray* el : mpTracElNew ) { + for ( auto & el : mpTracElNew ) { - discPoints.push_back( el->mInteriorSegments[0].giveVertex(1) ); - discPoints.push_back( el->mInteriorSegments.back().giveVertex(2) ); + discPoints.push_back( el.mInteriorSegments[0].giveVertex(1) ); + discPoints.push_back( el.mInteriorSegments.back().giveVertex(2) ); } // std :: string fileName("DiscontPoints.vtk"); @@ -1435,19 +1457,16 @@ void PrescribedGradientBCWeak :: createTractionMesh(bool iEnforceCornerPeriodici } -void PrescribedGradientBCWeak :: splitSegments(std :: vector< TracSegArray * > &ioElArray) +void PrescribedGradientBCWeak :: splitSegments(std :: vector< TracSegArray > &ioElArray) { - std :: vector< TracSegArray * > newArray; + std :: vector< TracSegArray > newArray; - for ( TracSegArray *el : ioElArray ) { - - for ( Line line : el->mInteriorSegments ) { - TracSegArray *newEl = new TracSegArray(); - newEl->mInteriorSegments.push_back(line); - newArray.push_back(newEl); + for ( auto &el : ioElArray ) { + for ( auto &line : el.mInteriorSegments ) { + TracSegArray newEl; + newEl.mInteriorSegments.push_back(line); + newArray.push_back(std::move(newEl)); } - - delete el; } ioElArray = std::move(newArray); @@ -1483,7 +1502,6 @@ void PrescribedGradientBCWeak :: assembleTangentGPContributionNew(FloatMatrix &o FloatMatrix NtracMat; NtracMat.beNMatrixOf(Ntrac, dim); - ////////////////////////////////// // Compute displacement N-matrix // Identify the displacement element @@ -1494,34 +1512,27 @@ void PrescribedGradientBCWeak :: assembleTangentGPContributionNew(FloatMatrix &o FloatArray dispElLocCoord, closestPoint; Element *dispEl = localizer->giveElementClosestToPoint(dispElLocCoord, closestPoint, iBndCoord ); - // Compute basis functions XfemElementInterface *xfemElInt = dynamic_cast< XfemElementInterface * >( dispEl ); FloatMatrix NdispMat; - if ( xfemElInt != NULL && domain->hasXfemManager() ) { + if ( xfemElInt && domain->hasXfemManager() ) { // If the element is an XFEM element, we use the XfemElementInterface to compute the N-matrix // of the enriched element. xfemElInt->XfemElementInterface_createEnrNmatrixAt(NdispMat, dispElLocCoord, * dispEl, false); } else { // Otherwise, use the usual N-matrix. - const int numNodes = dispEl->giveNumberOfDofManagers(); - FloatArray N(numNodes); + FloatArray N; - const int dim = dispEl->giveSpatialDimension(); + int dim = dispEl->giveSpatialDimension(); - NdispMat.resize(dim, dim * numNodes); - NdispMat.zero(); dispEl->giveInterpolation()->evalN( N, dispElLocCoord, FEIElementGeometryWrapper(dispEl) ); NdispMat.beNMatrixOf(N, dim); } - FloatMatrix contrib; - contrib.beTProductOf(NtracMat, NdispMat); - contrib.times( iScaleFactor * detJ * iGP.giveWeight() ); - - oTangent = contrib; + oTangent.beTProductOf(NtracMat, NdispMat); + oTangent.times( iScaleFactor * detJ * iGP.giveWeight() ); } bool PrescribedGradientBCWeak :: pointIsOnGammaPlus(const FloatArray &iPos) const @@ -1546,35 +1557,26 @@ void PrescribedGradientBCWeak :: giveMirroredPointOnGammaMinus(FloatArray &oPosM oPosMinus = iPosPlus; const double distTol = 1.0e-12; -// if ( iPosPlus.distance(mUC) < distTol ) { -// printf("iPosPlus: %.12e %.12e\n", iPosPlus [ 0 ], iPosPlus [ 1 ]); -// OOFEM_ERROR("Unmappable point.") -// } - - bool mappingPerformed = false; +// if ( distance(iPosPlus, mUC) < distTol ) { +// printf("iPosPlus: %.12e %.12e\n", iPosPlus [ 0 ], iPosPlus [ 1 ]); +// OOFEM_ERROR("Unmappable point.") +// } - if ( iPosPlus [ 0 ] > mUC [ 0 ] - distTol ) { - oPosMinus [ 0 ] = mLC [ 0 ]; - mappingPerformed = true; - return; - } - - if ( iPosPlus [ 1 ] > mUC [ 1 ] - distTol ) { - oPosMinus [ 1 ] = mLC [ 1 ]; - mappingPerformed = true; - return; - } + if ( iPosPlus [ 0 ] > mUC [ 0 ] - distTol ) { + oPosMinus [ 0 ] = mLC [ 0 ]; + return; + } else if ( iPosPlus [ 1 ] > mUC [ 1 ] - distTol ) { + oPosMinus [ 1 ] = mLC [ 1 ]; + return; + } - if ( !mappingPerformed ) { - iPosPlus.printYourself(); - OOFEM_ERROR("Mapping failed.") - } + iPosPlus.printYourself(); + OOFEM_ERROR("Mapping failed.") - // printf("iPosPlus: "); iPosPlus.printYourself(); - // printf("oPosMinus: "); oPosMinus.printYourself(); - //#else - } - else { + // printf("iPosPlus: "); iPosPlus.printYourself(); + // printf("oPosMinus: "); oPosMinus.printYourself(); + //#else + } else { #if 1 @@ -1587,10 +1589,10 @@ void PrescribedGradientBCWeak :: giveMirroredPointOnGammaMinus(FloatArray &oPosM double l_s = mUC[0] - mLC[0]; - // Compute angle - double alpha = 0.0, a = 0.0; - if( fabs(t(0)) > 1.0e-6 && fabs(t(1)) > 1.0e-6 ) { - alpha = atan(t(1)/t(0)); + // Compute angle + double alpha = 0.0, a = 0.0; + if ( fabs(t(0)) > 1.0e-6 && fabs(t(1)) > 1.0e-6 ) { + alpha = atan(t(1)/t(0)); if ( alpha > 45.0*M_PI/180.0 ) { a = l_s/tan(alpha); @@ -1669,36 +1671,27 @@ void PrescribedGradientBCWeak :: giveMirroredPointOnGammaPlus(FloatArray &oPosPl // const double distTol = 1.0e-16; const double distTol = l_box*1.0e-10; -// if ( iPosMinus.distance(mLC) < distTol ) { +// if ( distance(iPosMinus, mLC) < distTol ) { // printf("iPosMinus: %.12e %.12e\n", iPosMinus [ 0 ], iPosMinus [ 1 ]); // OOFEM_ERROR("Unmappable point.") // } - double mappingPerformed = false; - if ( iPosMinus [ 0 ] < mLC [ 0 ] + distTol ) { oPosPlus [ 0 ] = mUC [ 0 ]; - mappingPerformed = true; return; - } - - if ( iPosMinus [ 1 ] < mLC [ 1 ] + distTol ) { + } else if ( iPosMinus [ 1 ] < mLC [ 1 ] + distTol ) { oPosPlus [ 1 ] = mUC [ 1 ]; - mappingPerformed = true; return; } - if ( !mappingPerformed ) { - iPosMinus.printYourself(); - OOFEM_ERROR("Mapping failed.") - } + iPosMinus.printYourself(); + OOFEM_ERROR("Mapping failed.") //#else } else { #if 1 const double distTol = 1.0e-12; -// bool mappingPerformed = false; FloatArray n = mPeriodicityNormal; FloatArray t = {n(1),-n(0)}; @@ -1784,12 +1777,12 @@ void PrescribedGradientBCWeak :: computeDomainBoundingBox(Domain &iDomain, Float int numNodes = iDomain.giveNumberOfDofManagers(); int nsd = iDomain.giveNumberOfSpatialDimensions(); - FloatArray lc = * ( iDomain.giveDofManager(1)->giveCoordinates() ); - FloatArray uc = * ( iDomain.giveDofManager(1)->giveCoordinates() ); + FloatArray lc = iDomain.giveDofManager(1)->giveCoordinates(); + FloatArray uc = iDomain.giveDofManager(1)->giveCoordinates(); for ( int i = 1; i <= numNodes; i++ ) { DofManager *dMan = iDomain.giveDofManager(i); - const FloatArray &coord = * ( dMan->giveCoordinates() ); + const auto &coord = dMan->giveCoordinates(); for ( int j = 0; j < nsd; j++ ) { if ( coord [ j ] < lc [ j ] ) { @@ -1835,7 +1828,6 @@ void PrescribedGradientBCWeak :: findHoleCoord(std::vector &oHoleCoo { Set *setPointer = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = setPointer->giveBoundaryList(); - IntArray bNodes; // Loop over boundary nodes and check how many times they occur: // 1 -> at the edge of an inclusion, therefore must be retained @@ -1847,7 +1839,7 @@ void PrescribedGradientBCWeak :: findHoleCoord(std::vector &oHoleCoo int elIndex = boundaries.at(pos * 2 - 1); Element *e = this->giveDomain()->giveElement( elIndex ); int boundary = boundaries.at(pos * 2); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); DofManager *startNode = e->giveDofManager(bNodes [ 0 ]); int startNodeInd = startNode->giveNumber(); DofManager *endNode = e->giveDofManager(bNodes [ 1 ]); @@ -1878,8 +1870,8 @@ void PrescribedGradientBCWeak :: findHoleCoord(std::vector &oHoleCoo mandatory_to_keep = true; } - DofManager *bndNode = domain->giveDofManager(it->first); - const FloatArray &x = * ( bndNode->giveCoordinates() ); + DofManager *bndNode = domain->giveDofManager(it->first); + const auto &x = bndNode->giveCoordinates(); FloatArray xPlus = x; if ( !boundaryPointIsOnActiveBoundary(x) ) { @@ -1892,28 +1884,26 @@ void PrescribedGradientBCWeak :: findHoleCoord(std::vector &oHoleCoo oAllCoordUnsorted.push_back(xPlus); } - - } + void PrescribedGradientBCWeak :: findCrackBndIntersecCoord(std::vector &oHoleCoordUnsorted) { Set *setPointer = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = setPointer->giveBoundaryList(); - IntArray bNodes; for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); // Add the start and end nodes of the segment - DofManager *startNode = e->giveDofManager(bNodes [ 0 ]); - const FloatArray &xS = * ( startNode->giveCoordinates() ); + DofManager *startNode = e->giveDofManager(bNodes [ 0 ]); + const auto &xS = startNode->giveCoordinates(); - DofManager *endNode = e->giveDofManager(bNodes [ 1 ]); - const FloatArray &xE = * ( endNode->giveCoordinates() ); + DofManager *endNode = e->giveDofManager(bNodes [ 1 ]); + const auto &xE = endNode->giveCoordinates(); FloatArray xC; xC.beScaled(0.5, xS); @@ -1923,7 +1913,7 @@ void PrescribedGradientBCWeak :: findCrackBndIntersecCoord(std::vector( e ); - if ( xfemElInt != NULL && domain->hasXfemManager() ) { + if ( xfemElInt && domain->hasXfemManager() ) { std :: vector< Line >segments; std :: vector< FloatArray >intersecPoints; xfemElInt->partitionEdgeSegment(boundary, segments, intersecPoints, mTangDistPadding); @@ -1938,12 +1928,9 @@ void PrescribedGradientBCWeak :: findCrackBndIntersecCoord(std::vector &o oHoleCoordUnsorted.push_back(std::move(p2Plus)); } } - } + void PrescribedGradientBCWeak :: removeClosePoints(std::vector &ioCoords, const double &iAbsTol) { if ( ioCoords.size() == 0 ) { @@ -1990,12 +1977,11 @@ void PrescribedGradientBCWeak :: removeClosePoints(std::vector &ioCo const double tol2 = iAbsTol*iAbsTol; - std::vector tmp; - tmp.push_back(ioCoords[0]); + std::vector tmp = { ioCoords[0] }; size_t j = 0; for ( size_t i = 1; i < ioCoords.size(); i++ ) { - if ( ioCoords[i].distance_square(tmp[j]) > tol2 ) { + if ( distance_square(ioCoords[i], tmp[j]) > tol2 ) { tmp.push_back(ioCoords[i]); j++; } @@ -2004,6 +1990,7 @@ void PrescribedGradientBCWeak :: removeClosePoints(std::vector &ioCo ioCoords = std::move(tmp); } + void PrescribedGradientBCWeak :: removeSegOverHoles(TracSegArray &ioTSeg, const double &iAbsTol) { // Idea: Loop over segments and check if the center point of each @@ -2016,8 +2003,8 @@ void PrescribedGradientBCWeak :: removeSegOverHoles(TracSegArray &ioTSeg, const const double tol2 = iAbsTol*iAbsTol; for ( auto &l : ioTSeg.mInteriorSegments ) { - const FloatArray &xS = l.giveVertex(1); - const FloatArray &xE = l.giveVertex(2); + const auto &xS = l.giveVertex(1); + const auto &xE = l.giveVertex(2); FloatArray xPlus = {0.5*(xS[0]+xE[0]), 0.5*(xS[1]+xE[1])}; FloatArray lcoordsPlus, closestPlus; @@ -2028,7 +2015,7 @@ void PrescribedGradientBCWeak :: removeSegOverHoles(TracSegArray &ioTSeg, const FloatArray lcoordsMinus, closestMinus; localizer->giveElementClosestToPoint(lcoordsMinus, closestMinus, xMinus); - if ( !(xPlus.distance_square(closestPlus) > tol2 || xMinus.distance_square(closestMinus) > tol2) ) { + if ( !(distance_square(xPlus, closestPlus) > tol2 || distance_square(xMinus, closestMinus) > tol2) ) { tmp.push_back(l); } } diff --git a/src/oofemlib/prescribedgradientbcweak.h b/src/oofemlib/prescribedgradientbcweak.h index 766f45873..32b074a3d 100644 --- a/src/oofemlib/prescribedgradientbcweak.h +++ b/src/oofemlib/prescribedgradientbcweak.h @@ -62,40 +62,39 @@ class GaussPoint; class TracSegArray { public: - TracSegArray() {} + TracSegArray() {} + TracSegArray(TracSegArray &&src) = default; virtual ~TracSegArray() {} void printYourself() { - printf("\nTracSegArray segments:\n"); - for(auto &l: mInteriorSegments) { - printf("\n"); - l.giveVertex(1).printYourself(); - l.giveVertex(2).printYourself(); - } + printf("\nTracSegArray segments:\n"); + for ( auto &l : mInteriorSegments ) { + printf("\n"); + l.giveVertex(1).printYourself(); + l.giveVertex(2).printYourself(); + } } double giveLength() { - double l = 0.0; - for(Line &line : mInteriorSegments) { - l += line.giveLength(); - } + double l = 0.0; + for( auto &line : mInteriorSegments ) { + l += line.giveLength(); + } - return l; + return l; } void giveTractionLocationArray(IntArray &rows, CharType type, const UnknownNumberingScheme &s); void setupIntegrationRuleOnEl(); - std :: vector< Line >mInteriorSegments; + std :: vector< Line > mInteriorSegments; // Interior segments used for Gaussian quadrature std :: vector< Line > mInteriorSegmentsFine; std :: vector< FloatArray > mInteriorSegmentsPointsFine; - - std :: unique_ptr< Node > mFirstNode; std :: unique_ptr< IntegrationRule > mIntRule; @@ -116,40 +115,41 @@ class PrescribedGradientBCWeak : public ActiveBoundaryCondition, public Prescrib void clear(); - virtual double domainSize() {return PrescribedGradientHomogenization::domainSize(this->giveDomain(), this->giveSetNumber());} + double domainSize() override { return PrescribedGradientHomogenization::domainSize(this->giveDomain(), this->giveSetNumber()); } - virtual int giveNumberOfInternalDofManagers(); - virtual DofManager *giveInternalDofManager(int i); + int giveNumberOfInternalDofManagers() override; + DofManager *giveInternalDofManager(int i) override; - virtual bcType giveType() const { return UnknownBT; } + bcType giveType() const override { return UnknownBT; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void postInitialize(); + void postInitialize() override; - virtual void computeField(FloatArray &sigma, TimeStep *tStep); - virtual void computeTangent(FloatMatrix &E, TimeStep *tStep); + void computeField(FloatArray &sigma, TimeStep *tStep) override; + void computeTangent(FloatMatrix &E, TimeStep *tStep) override; - virtual void assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm = NULL); + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorm=nullptr, void* lock=nullptr) override; void computeExtForceElContrib(FloatArray &oContrib, TracSegArray &iEl, int iDim, TimeStep *tStep); void computeIntForceGPContrib(FloatArray &oContrib_disp, IntArray &oDisp_loc_array, FloatArray &oContrib_trac, IntArray &oTrac_loc_array,TracSegArray &iEl, GaussPoint &iGP, int iDim, TimeStep *tStep, const FloatArray &iBndCoord, const double &iScaleFac, ValueModeType mode, CharType type, const UnknownNumberingScheme &s); - virtual void assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0); + void assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0, void* lock=nullptr) override; virtual void assembleExtraDisplock(SparseMtrx &answer, TimeStep *tStep, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s); virtual void assembleGPContrib(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, TracSegArray &iEl, GaussPoint &iGP, double k); + CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, + TracSegArray &iEl, GaussPoint &iGP, double k, void* lock=nullptr); - virtual void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, - const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s); + void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) override; virtual void giveTractionLocationArray(IntArray &rows, const UnknownNumberingScheme &s); @@ -167,12 +167,12 @@ class PrescribedGradientBCWeak : public ActiveBoundaryCondition, public Prescrib // virtual void giveDisplacementLocationArrays(int iTracElInd, IntArray &rows, CharType type, // const UnknownNumberingScheme &s); - virtual const char *giveClassName() const { return "PrescribedGradientBCWeak"; } - virtual const char *giveInputRecordName() const { return _IFT_PrescribedGradientBCWeak_Name; } + const char *giveClassName() const override { return "PrescribedGradientBCWeak"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedGradientBCWeak_Name; } // Routines for postprocessing size_t giveNumberOfTractionElements() const { return mpTracElNew.size(); } - void giveTractionElCoord(size_t iElInd, FloatArray &oStartCoord, FloatArray &oEndCoord) const { oStartCoord = mpTracElNew [ iElInd ]->mInteriorSegments[0].giveVertex(1); oEndCoord = mpTracElNew [ iElInd ]->mInteriorSegments.back().giveVertex(2); } + void giveTractionElCoord(size_t iElInd, FloatArray &oStartCoord, FloatArray &oEndCoord) const { oStartCoord = mpTracElNew [ iElInd ].mInteriorSegments[0].giveVertex(1); oEndCoord = mpTracElNew [ iElInd ].mInteriorSegments.back().giveVertex(2); } void giveTractionElNormal(size_t iElInd, FloatArray &oNormal, FloatArray &oTangent) const; void giveTractionElArcPos(size_t iElInd, double &oXiStart, double &oXiEnd) const; void giveBoundaries(IntArray &oBoundaries); @@ -183,16 +183,16 @@ class PrescribedGradientBCWeak : public ActiveBoundaryCondition, public Prescrib void computeDomainBoundingBox(Domain &iDomain, FloatArray &oLC, FloatArray &oUC); - const IntArray &giveTracDofIDs() const {return mTractionDofIDs;} - const IntArray &giveDispLockDofIDs() const {return mDispLockDofIDs;} - const IntArray &giveRegularDispDofIDs() const {return mRegularDispDofIDs;} + const IntArray &giveTracDofIDs() const { return mTractionDofIDs; } + const IntArray &giveDispLockDofIDs() const { return mDispLockDofIDs; } + const IntArray &giveRegularDispDofIDs() const { return mRegularDispDofIDs; } // Functions mainly for testing - void setPeriodicityNormal(const FloatArray &iPeriodicityNormal) {mPeriodicityNormal = iPeriodicityNormal; }; - void setDomainSize(double iDomainSize) {mDomainSize = std::move(iDomainSize);}; - void setLowerCorner(FloatArray iLC) {mLC = std::move(iLC);}; - void setUpperCorner(FloatArray iUC) {mUC = std::move(iUC);}; + void setPeriodicityNormal(const FloatArray &iPeriodicityNormal) { mPeriodicityNormal = iPeriodicityNormal; } + void setDomainSize(double iDomainSize) { mDomainSize = std::move(iDomainSize); } + void setLowerCorner(FloatArray iLC) { mLC = std::move(iLC); } + void setUpperCorner(FloatArray iUC) { mUC = std::move(iUC); } void setMirrorFunction(int iMirrorFunction) {mMirrorFunction = iMirrorFunction;}; @@ -253,7 +253,7 @@ class PrescribedGradientBCWeak : public ActiveBoundaryCondition, public Prescrib /// Lock displacements in one node if periodic - Node *mpDisplacementLock; + std::unique_ptr mpDisplacementLock; int mLockNodeInd; double mDispLockScaling; @@ -264,7 +264,7 @@ class PrescribedGradientBCWeak : public ActiveBoundaryCondition, public Prescrib /// Elements for the independent traction discretization - std :: vector< TracSegArray * > mpTracElNew; + std :: vector< TracSegArray > mpTracElNew; /** @@ -289,7 +289,7 @@ class PrescribedGradientBCWeak : public ActiveBoundaryCondition, public Prescrib protected: void createTractionMesh(bool iEnforceCornerPeriodicity, int iNumSides); - void splitSegments(std :: vector< TracSegArray * > &ioElArray); + void splitSegments(std :: vector< TracSegArray > &ioElArray); bool damageExceedsTolerance(Element *el); @@ -316,11 +316,10 @@ class ArcPosSortFunction { public: ArcPosSortFunction(const FloatArray &iStartPos) : mStartPos(iStartPos) {} - ~ArcPosSortFunction() {} bool operator()(const FloatArray &iVec1, const FloatArray &iVec2) const { - return mStartPos.distance_square(iVec1) < mStartPos.distance_square(iVec2); + return distance_square(mStartPos, iVec1) < distance_square(mStartPos, iVec2); } private: @@ -338,8 +337,6 @@ class ArcPosSortFunction3 mSideInd(iSideInd) {} - ~ArcPosSortFunction3() {} - bool operator()(const std :: pair< FloatArray, T > &iVec1, const std :: pair< FloatArray, int > &iVec2) const { return calcArcPos(iVec1.first) < calcArcPos(iVec2.first); @@ -352,24 +349,20 @@ class ArcPosSortFunction3 if ( mSideInd == 0 ) { const FloatArray &x = { mUC [ 0 ], mLC [ 1 ] }; - double dist = Lx + iPos.distance(x); - return dist; + return Lx + distance(iPos, x); } if ( mSideInd == 1 ) { - double dist = Lx + Ly + iPos.distance(mUC); - return dist; + return Lx + Ly + distance(iPos, mUC); } if ( mSideInd == 2 ) { const FloatArray &x = { mLC [ 0 ], mUC [ 1 ] }; - double dist = Lx + Ly + Lx + iPos.distance(x); - return dist; + return Lx + Ly + Lx + distance(iPos, x); } if ( mSideInd == 3 ) { - double dist = iPos.distance(mLC); - return dist; + return distance(iPos, mLC); } OOFEM_ERROR("Could not compute distance.") @@ -395,8 +388,6 @@ class ArcPosSortFunction4 mRelTol(iRelTol) {} - ~ArcPosSortFunction4() {} - bool operator()(const FloatArray &iVec1, const FloatArray &iVec2) const { return calcArcPos(iVec1) < calcArcPos(iVec2); @@ -407,45 +398,40 @@ class ArcPosSortFunction4 double Lx = mUC [ 0 ] - mLC [ 0 ]; double Ly = mUC [ 1 ] - mLC [ 1 ]; - int sideInd = -1; - if( iPos[0] > Lx - Lx*mRelTol ) { - sideInd = 0; + if ( iPos[0] > Lx - Lx*mRelTol ) { + sideInd = 0; } - if( iPos[1] > Ly - Ly*mRelTol ) { - sideInd = 1; + if ( iPos[1] > Ly - Ly*mRelTol ) { + sideInd = 1; } - if( iPos[0] < Lx*mRelTol ) { - sideInd = 2; + if ( iPos[0] < Lx*mRelTol ) { + sideInd = 2; } - if( iPos[1] < Ly*mRelTol ) { - sideInd = 3; + if ( iPos[1] < Ly*mRelTol ) { + sideInd = 3; } if ( sideInd == 0 ) { const FloatArray &x = { mUC [ 0 ], mLC [ 1 ] }; - double dist = Lx + iPos.distance(x); - return dist; + return Lx + distance(iPos, x); } if ( sideInd == 1 ) { - double dist = Lx + Ly + iPos.distance(mUC); - return dist; + return Lx + Ly + distance(iPos, mUC); } if ( sideInd == 2 ) { const FloatArray &x = { mLC [ 0 ], mUC [ 1 ] }; - double dist = Lx + Ly + Lx + iPos.distance(x); - return dist; + return Lx + Ly + Lx + distance(iPos, x); } if ( sideInd == 3 ) { - double dist = iPos.distance(mLC); - return dist; + return distance(iPos, mLC); } OOFEM_ERROR("Could not compute distance.") diff --git a/src/oofemlib/prescribedgradientbcweakdirichlet.C b/src/oofemlib/prescribedgradientbcweakdirichlet.C index 9946f76d7..6ac37ced6 100644 --- a/src/oofemlib/prescribedgradientbcweakdirichlet.C +++ b/src/oofemlib/prescribedgradientbcweakdirichlet.C @@ -23,11 +23,10 @@ PrescribedGradientBCWeakDirichlet :: ~PrescribedGradientBCWeakDirichlet() // TODO Auto-generated destructor stub } -IRResultType PrescribedGradientBCWeakDirichlet :: initializeFrom(InputRecord *ir) +void PrescribedGradientBCWeakDirichlet :: initializeFrom(InputRecord &ir) { + PrescribedGradientBCWeak :: initializeFrom(ir); mMeshIsPeriodic = false; - - return PrescribedGradientBCWeak :: initializeFrom(ir); } void PrescribedGradientBCWeakDirichlet :: postInitialize() @@ -50,7 +49,7 @@ void PrescribedGradientBCWeakDirichlet :: checkIfCorner(bool &oIsCorner, bool &o oDuplicatable = false; FloatArray cornerPos = mLC; - if ( iPos.distance(cornerPos) < iNodeDistTol ) { + if ( distance(iPos, cornerPos) < iNodeDistTol ) { oIsCorner = true; oDuplicatable = true; } @@ -58,7 +57,7 @@ void PrescribedGradientBCWeakDirichlet :: checkIfCorner(bool &oIsCorner, bool &o cornerPos = { mUC [ 0 ], mLC [ 1 ] }; - if ( iPos.distance(cornerPos) < iNodeDistTol ) { + if ( distance(iPos, cornerPos) < iNodeDistTol ) { oIsCorner = true; oDuplicatable = true; } @@ -66,7 +65,7 @@ void PrescribedGradientBCWeakDirichlet :: checkIfCorner(bool &oIsCorner, bool &o cornerPos = { mUC [ 0 ], mUC [ 1 ] }; - if ( iPos.distance(cornerPos) < iNodeDistTol ) { + if ( distance(iPos, cornerPos) < iNodeDistTol ) { oIsCorner = true; oDuplicatable = true; } @@ -74,7 +73,7 @@ void PrescribedGradientBCWeakDirichlet :: checkIfCorner(bool &oIsCorner, bool &o cornerPos = { mLC [ 0 ], mUC [ 1 ] }; - if ( iPos.distance(cornerPos) < iNodeDistTol ) { + if ( distance(iPos, cornerPos) < iNodeDistTol ) { oIsCorner = true; oDuplicatable = true; } diff --git a/src/oofemlib/prescribedgradientbcweakdirichlet.h b/src/oofemlib/prescribedgradientbcweakdirichlet.h index 004dcfb80..b1b518562 100644 --- a/src/oofemlib/prescribedgradientbcweakdirichlet.h +++ b/src/oofemlib/prescribedgradientbcweakdirichlet.h @@ -19,17 +19,17 @@ class PrescribedGradientBCWeakDirichlet : public PrescribedGradientBCWeak PrescribedGradientBCWeakDirichlet(int n, Domain *d); virtual ~PrescribedGradientBCWeakDirichlet(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void postInitialize(); + void postInitialize() override; - virtual const char *giveClassName() const { return "PrescribedGradientBCWeakDirichlet"; } - virtual const char *giveInputRecordName() const { return _IFT_PrescribedGradientBCWeakDirichlet_Name; } + const char *giveClassName() const override { return "PrescribedGradientBCWeakDirichlet"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedGradientBCWeakDirichlet_Name; } protected: - virtual void giveBoundaryCoordVector(FloatArray &oX, const FloatArray &iPos) const; - virtual void checkIfCorner(bool &oIsCorner, bool &oDuplicatable, const FloatArray &iPos, const double &iNodeDistTol) const; - virtual bool boundaryPointIsOnActiveBoundary(const FloatArray &iPos) const { return true; } + void giveBoundaryCoordVector(FloatArray &oX, const FloatArray &iPos) const override; + void checkIfCorner(bool &oIsCorner, bool &oDuplicatable, const FloatArray &iPos, const double &iNodeDistTol) const override; + bool boundaryPointIsOnActiveBoundary(const FloatArray &iPos) const override { return true; } }; } /* namespace oofem */ diff --git a/src/oofemlib/prescribedgradientbcweakperiodic.C b/src/oofemlib/prescribedgradientbcweakperiodic.C index 3564f7135..cb3454093 100644 --- a/src/oofemlib/prescribedgradientbcweakperiodic.C +++ b/src/oofemlib/prescribedgradientbcweakperiodic.C @@ -18,11 +18,10 @@ PrescribedGradientBCWeakPeriodic :: PrescribedGradientBCWeakPeriodic(int n, Doma PrescribedGradientBCWeakPeriodic :: ~PrescribedGradientBCWeakPeriodic() {} -IRResultType PrescribedGradientBCWeakPeriodic :: initializeFrom(InputRecord *ir) +void PrescribedGradientBCWeakPeriodic :: initializeFrom(InputRecord &ir) { + PrescribedGradientBCWeak :: initializeFrom(ir); mMeshIsPeriodic = true; - - return PrescribedGradientBCWeak :: initializeFrom(ir); } void PrescribedGradientBCWeakPeriodic :: postInitialize() @@ -49,21 +48,21 @@ void PrescribedGradientBCWeakPeriodic :: checkIfCorner(bool &oIsCorner, bool &oD oDuplicatable = false; FloatArray cornerPos = mLC; - if ( iPos.distance(cornerPos) < iNodeDistTol ) { + if ( distance(iPos, cornerPos) < iNodeDistTol ) { oIsCorner = true; } cornerPos = { mUC [ 0 ], mLC [ 1 ] }; - if ( iPos.distance(cornerPos) < iNodeDistTol ) { + if ( distance(iPos, cornerPos) < iNodeDistTol ) { oIsCorner = true; } cornerPos = { mUC [ 0 ], mUC [ 1 ] }; - if ( iPos.distance(cornerPos) < iNodeDistTol ) { + if ( distance(iPos, cornerPos) < iNodeDistTol ) { oIsCorner = true; if ( mTractionInterpOrder == 1 ) { oDuplicatable = true; @@ -73,7 +72,7 @@ void PrescribedGradientBCWeakPeriodic :: checkIfCorner(bool &oIsCorner, bool &oD cornerPos = { mLC [ 0 ], mUC [ 1 ] }; - if ( iPos.distance(cornerPos) < iNodeDistTol ) { + if ( distance(iPos, cornerPos) < iNodeDistTol ) { oIsCorner = true; } } diff --git a/src/oofemlib/prescribedgradientbcweakperiodic.h b/src/oofemlib/prescribedgradientbcweakperiodic.h index 7f5451ea3..1da111c2f 100644 --- a/src/oofemlib/prescribedgradientbcweakperiodic.h +++ b/src/oofemlib/prescribedgradientbcweakperiodic.h @@ -19,18 +19,18 @@ class PrescribedGradientBCWeakPeriodic : public PrescribedGradientBCWeak PrescribedGradientBCWeakPeriodic(int n, Domain *d); virtual ~PrescribedGradientBCWeakPeriodic(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void postInitialize(); + void postInitialize() override; - virtual const char *giveClassName() const { return "PrescribedGradientBCWeakPeriodic"; } - virtual const char *giveInputRecordName() const { return _IFT_PrescribedGradientBCWeakPeriodic_Name; } + const char *giveClassName() const override { return "PrescribedGradientBCWeakPeriodic"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedGradientBCWeakPeriodic_Name; } protected: - virtual void giveBoundaryCoordVector(FloatArray &oX, const FloatArray &iPos) const; - virtual void checkIfCorner(bool &oIsCorner, bool &oDuplicatable, const FloatArray &iPos, const double &iNodeDistTol) const; + void giveBoundaryCoordVector(FloatArray &oX, const FloatArray &iPos) const override; + void checkIfCorner(bool &oIsCorner, bool &oDuplicatable, const FloatArray &iPos, const double &iNodeDistTol) const override; - virtual bool boundaryPointIsOnActiveBoundary(const FloatArray &iPos) const { return pointIsOnGammaPlus(iPos); } + bool boundaryPointIsOnActiveBoundary(const FloatArray &iPos) const override { return pointIsOnGammaPlus(iPos); } }; } /* namespace oofem */ diff --git a/src/oofemlib/prescribedgradienthomogenization.C b/src/oofemlib/prescribedgradienthomogenization.C index 6ffaa5ef4..be24cd534 100644 --- a/src/oofemlib/prescribedgradienthomogenization.C +++ b/src/oofemlib/prescribedgradienthomogenization.C @@ -42,17 +42,13 @@ namespace oofem { -IRResultType PrescribedGradientHomogenization :: initializeFrom(InputRecord *ir) +void PrescribedGradientHomogenization :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, mGradient, _IFT_PrescribedGradientHomogenization_gradient); mCenterCoord.resize( mGradient.giveNumberOfColumns() ); mCenterCoord.zero(); IR_GIVE_OPTIONAL_FIELD(ir, mCenterCoord, _IFT_PrescribedGradientHomogenization_centercoords) - - return IRRT_OK; } void PrescribedGradientHomogenization :: giveInputRecord(DynamicInputRecord &input) @@ -71,6 +67,12 @@ void PrescribedGradientHomogenization :: setPrescribedGradientVoigt(const FloatA this->mGradient.at(2, 2) = t.at(2); // In voigt form, assuming the use of gamma_12 instead of eps_12 this->mGradient.at(1, 2) = this->mGradient.at(2, 1) = t.at(3) * 0.5; + } else if ( n == 4 ) { // Then 2D + this->mGradient.resize(2, 2); + this->mGradient.at(1, 1) = t.at(1); + this->mGradient.at(2, 2) = t.at(2); + // In voigt form, assuming the use of gamma_12 instead of eps_12 + this->mGradient.at(1, 2) = this->mGradient.at(2, 1) = t.at(4) * 0.5; } else if ( n == 6 ) { // Then 3D this->mGradient.resize(3, 3); this->mGradient.at(1, 1) = t.at(1); diff --git a/src/oofemlib/prescribedgradienthomogenization.h b/src/oofemlib/prescribedgradienthomogenization.h index da5600bf2..7802a4356 100644 --- a/src/oofemlib/prescribedgradienthomogenization.h +++ b/src/oofemlib/prescribedgradienthomogenization.h @@ -74,7 +74,7 @@ class OOFEM_EXPORT PrescribedGradientHomogenization PrescribedGradientHomogenization() { } virtual ~PrescribedGradientHomogenization() { } - virtual double domainSize() {OOFEM_ERROR("Not implemented."); return 0.0;} + virtual double domainSize() { OOFEM_ERROR("Not implemented."); return 0.0; } /** * Initializes receiver according to object description stored in input record. @@ -84,7 +84,7 @@ class OOFEM_EXPORT PrescribedGradientHomogenization * The prescribed gradients columns must be equal to the size of the center coordinates. * The size of the center coordinates must be equal to the size of the coordinates in the applied nodes. */ - virtual IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); virtual void giveInputRecord(DynamicInputRecord &input); /** diff --git a/src/oofemlib/prescribedmean.C b/src/oofemlib/prescribedmean.C index 8c201ffbc..9fdf166c4 100644 --- a/src/oofemlib/prescribedmean.C +++ b/src/oofemlib/prescribedmean.C @@ -42,6 +42,10 @@ #include "function.h" #include "mathfem.h" +#ifdef _OPENMP +#include +#endif + namespace oofem { @@ -50,11 +54,9 @@ double PrescribedMean :: domainSize; REGISTER_BoundaryCondition(PrescribedMean); -IRResultType -PrescribedMean :: initializeFrom(InputRecord *ir) +void +PrescribedMean :: initializeFrom(InputRecord &ir) { - IRResultType result; - GeneralBoundaryCondition :: initializeFrom(ir); IR_GIVE_FIELD(ir, c, _IFT_PrescribedMean_Mean); @@ -67,17 +69,15 @@ PrescribedMean :: initializeFrom(InputRecord *ir) int newdofid = this->domain->giveNextFreeDofID(); lambdaIDs.clear(); lambdaIDs.followedBy(newdofid); - lambdaDman->appendDof( new MasterDof( lambdaDman, ( DofIDItem )newdofid )); + lambdaDman->appendDof( new MasterDof( lambdaDman.get(), ( DofIDItem )newdofid )); domainSize=-1.; - return IRRT_OK; - } void PrescribedMean :: assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, - const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale) + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale, void*lock) { if ( type != TangentStiffnessMatrix && type != StiffnessMatrix ) { @@ -95,7 +95,7 @@ PrescribedMean :: assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, Element *thisElement = this->giveDomain()->giveElement(elementID); FEInterpolation *interpolator = thisElement->giveInterpolation(DofIDItem(dofid)); - IntegrationRule *iRule = (elementEdges) ? (interpolator->giveBoundaryIntegrationRule(3, sides.at(i))) : + auto iRule = (elementEdges) ? (interpolator->giveBoundaryIntegrationRule(3, sides.at(i))) : (interpolator->giveIntegrationRule(3)); for ( GaussPoint * gp: * iRule ) { @@ -103,11 +103,11 @@ PrescribedMean :: assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, FloatArray N; //, a; FloatMatrix temp, tempT; double detJ = 0.0; - IntArray boundaryNodes, dofids={(DofIDItem) this->dofid}, r_Sideloc, c_Sideloc; + IntArray dofids={(DofIDItem) this->dofid}, r_Sideloc, c_Sideloc; if (elementEdges) { // Compute boundary integral - interpolator->boundaryGiveNodes( boundaryNodes, sides.at(i) ); + auto boundaryNodes = interpolator->boundaryGiveNodes(sides.at(i) ); interpolator->boundaryEvalN(N, sides.at(i), lcoords, FEIElementGeometryWrapper(thisElement)); detJ = fabs ( interpolator->boundaryGiveTransformationJacobian(sides.at(i), lcoords, FEIElementGeometryWrapper(thisElement)) ); // Retrieve locations for dofs on boundary @@ -134,34 +134,38 @@ PrescribedMean :: assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, // delta p part: temp = N * (scale * detJ * gp->giveWeight() / domainSize); tempT.beTranspositionOf(temp); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(r_Sideloc, c_loc, temp); answer.assemble(r_loc, c_Sideloc, tempT); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif } - - delete iRule; - } - } void PrescribedMean :: assembleVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm) + const UnknownNumberingScheme &s, FloatArray *eNorm, + void*lock) { if ( type == InternalForcesVector ) { - giveInternalForcesVector(answer, tStep, type, mode, s); + giveInternalForcesVector(answer, tStep, type, mode, s, eNorm, lock); } else if ( type == ExternalForcesVector ) { - giveExternalForcesVector(answer, tStep, type, mode, s); + giveExternalForcesVector(answer, tStep, type, mode, s, lock); } } void PrescribedMean :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm) + const UnknownNumberingScheme &s, + FloatArray *eNorm, + void*lock) { computeDomainSize(); @@ -176,18 +180,19 @@ PrescribedMean :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, Element *thisElement = this->giveDomain()->giveElement(elementID); FEInterpolation *interpolator = thisElement->giveInterpolation(DofIDItem(dofid)); - IntegrationRule *iRule = (elementEdges) ? (interpolator->giveBoundaryIntegrationRule(3, sides.at(i))) : - (interpolator->giveIntegrationRule(3)); + auto iRule = elementEdges ? + interpolator->giveBoundaryIntegrationRule(3, sides.at(i)) : + interpolator->giveIntegrationRule(3); - for ( auto &gp: * iRule ) { + for ( auto &gp: *iRule ) { FloatArray lcoords = gp->giveNaturalCoordinates(); FloatArray a, N, pressureEqns, lambdaEqns; - IntArray boundaryNodes, dofids={(DofIDItem) this->dofid}, locationArray; + IntArray dofids={(DofIDItem) this->dofid}, locationArray; double detJ = 0.0; if (elementEdges) { // Compute integral - interpolator->boundaryGiveNodes( boundaryNodes, sides.at(i) ); + auto boundaryNodes = interpolator->boundaryGiveNodes(sides.at(i) ); thisElement->computeBoundaryVectorOf(boundaryNodes, dofids, VM_Total, tStep, a); interpolator->boundaryEvalN(N, sides.at(i), lcoords, FEIElementGeometryWrapper(thisElement)); detJ = fabs ( interpolator->boundaryGiveTransformationJacobian(sides.at(i), lcoords, FEIElementGeometryWrapper(thisElement)) ); @@ -204,7 +209,7 @@ PrescribedMean :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, thisElement->giveLocationArray(loc, s, &DofIDStemp); locationArray.clear(); - for (int j=1; j<=DofIDStemp.giveSize(); j++) { + for (int j = 1; j <= DofIDStemp.giveSize(); j++) { if ( DofIDStemp.at(j) == dofids.at(1) ) { locationArray.followedBy(loc.at(j)); } @@ -220,14 +225,18 @@ PrescribedMean :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, lambdaEqns.times(detJ*gp->giveWeight()*1.0/domainSize); lambdaEqns.at(1) = lambdaEqns.at(1); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif // delta p part answer.assemble(pressureEqns, locationArray); // delta lambda part answer.assemble(lambdaEqns, lambdaLoc); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } - delete iRule; } } @@ -235,7 +244,8 @@ PrescribedMean :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, void PrescribedMean :: giveExternalForcesVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s) + const UnknownNumberingScheme &s, + void* lock) { computeDomainSize(); @@ -246,8 +256,13 @@ PrescribedMean :: giveExternalForcesVector(FloatArray &answer, TimeStep *tStep, temp.at(1) = c; lambdaDman->giveLocationArray(lambdaIDs, lambdaLoc, s); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(temp, lambdaLoc); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif // Finally, compute value of loadtimefunction double factor; factor = this->giveTimeFunction()->evaluate(tStep, mode); @@ -282,15 +297,11 @@ PrescribedMean :: computeDomainSize() Element *thisElement = this->giveDomain()->giveElement(elementID); FEInterpolation *interpolator = thisElement->giveInterpolation(DofIDItem(dofid)); - IntegrationRule *iRule; - - if ( elementEdges ) { - iRule = interpolator->giveBoundaryIntegrationRule(3, sides.at(i)); - } else { - iRule = interpolator->giveIntegrationRule(3); - } + auto iRule = elementEdges ? + interpolator->giveBoundaryIntegrationRule(3, sides.at(i)) : + interpolator->giveIntegrationRule(3); - for ( GaussPoint * gp: * iRule ) { + for ( auto &gp: *iRule ) { FloatArray lcoords = gp->giveNaturalCoordinates(); double detJ; @@ -301,12 +312,8 @@ PrescribedMean :: computeDomainSize() } domainSize = domainSize + detJ*gp->giveWeight(); } - - delete iRule; } - printf("%f\n", domainSize); - } } diff --git a/src/oofemlib/prescribedmean.h b/src/oofemlib/prescribedmean.h index 724df05ba..535c639a9 100644 --- a/src/oofemlib/prescribedmean.h +++ b/src/oofemlib/prescribedmean.h @@ -58,8 +58,7 @@ namespace oofem class OOFEM_EXPORT PrescribedMean : public ActiveBoundaryCondition { private: - - Node *lambdaDman; + std::unique_ptr lambdaDman; double c; @@ -76,32 +75,34 @@ class OOFEM_EXPORT PrescribedMean : public ActiveBoundaryCondition IntArray lambdaIDs; public: - PrescribedMean (int n, Domain * d) : ActiveBoundaryCondition(n, d), lambdaDman( new Node(0, this->domain) ) {} + PrescribedMean(int n, Domain * d) : ActiveBoundaryCondition(n, d), lambdaDman(std::make_unique(0, this->domain) ) {} + virtual ~PrescribedMean() {} - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, - const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0); + void assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0, void* lock=nullptr) override; - virtual void assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm = NULL); + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorm=nullptr, void* lock=nullptr) override; void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm = NULL); + const UnknownNumberingScheme &s, FloatArray *eNorm=nullptr, + void* lock=nullptr); void giveExternalForcesVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s); - - virtual int giveNumberOfInternalDofManagers() {return 1;} + const UnknownNumberingScheme &s, + void* lock=nullptr); - virtual DofManager *giveInternalDofManager(int i) {return lambdaDman;} + int giveNumberOfInternalDofManagers() override { return 1; } - virtual const char *giveClassName() const { return "PrescribedMean"; } - virtual const char *giveInputRecordName() const { return _IFT_PrescribedMean_Name; } + DofManager *giveInternalDofManager(int i) override { return lambdaDman.get(); } + const char *giveClassName() const override { return "PrescribedMean"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedMean_Name; } }; } diff --git a/src/oofemlib/primaryfield.C b/src/oofemlib/primaryfield.C index b05c66961..4edc58768 100644 --- a/src/oofemlib/primaryfield.C +++ b/src/oofemlib/primaryfield.C @@ -359,7 +359,7 @@ PrimaryField :: __evaluateAt(FloatArray &answer, DofManager *dman, return 0; // ok } } else { - return this->__evaluateAt(answer, * dman->giveCoordinates(), + return this->__evaluateAt(answer, dman->giveCoordinates(), mode, tStep, dofId); } } @@ -503,8 +503,8 @@ PrimaryField :: advanceSolution(TimeStep *tStep) } -contextIOResultType -PrimaryField :: saveContext(DataStream &stream, ContextMode mode) +void +PrimaryField :: saveContext(DataStream &stream) { contextIOResultType iores(CIO_IOERR); @@ -529,16 +529,12 @@ PrimaryField :: saveContext(DataStream &stream, ContextMode mode) } for ( auto &step : solStepList ) { - if ( ( iores = step.saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + step.saveContext(stream); } - - return CIO_OK; } -contextIOResultType -PrimaryField :: restoreContext(DataStream &stream, ContextMode mode) +void +PrimaryField :: restoreContext(DataStream &stream) { contextIOResultType iores(CIO_IOERR); @@ -564,11 +560,7 @@ PrimaryField :: restoreContext(DataStream &stream, ContextMode mode) for ( int i = 0; i <= nHistVectors; i++ ) { solStepList[i] = TimeStep(emodel); - if ( ( iores = solStepList[i].restoreContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + solStepList[i].restoreContext(stream); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/oofemlib/primaryfield.h b/src/oofemlib/primaryfield.h index a08c98681..bb5a7c060 100644 --- a/src/oofemlib/primaryfield.h +++ b/src/oofemlib/primaryfield.h @@ -170,26 +170,10 @@ class OOFEM_EXPORT PrimaryField : public Field * @return Value of interest at given DOF. */ virtual double giveUnknownValue(Dof *dof, ValueModeType mode, TimeStep *tStep); - /** - * Evaluates the field at given point - * @param answer Evaluated field at point. - * @param coords Coordinates of the point of interest. - * @param mode Mode of evaluated unknowns. - * @param tStep Time step of interest. - * @return Error code (0-ok, 1-point not found in domain). - */ - virtual int evaluateAt(FloatArray &answer, const FloatArray &coords, - ValueModeType mode, TimeStep *tStep); - /** - * Evaluates the field at given DofManager - * @param answer Evaluated field at dman. - * @param dman DOF manager to evaluate at. - * @param mode Mode of evaluated unknowns. - * @param tStep Time step of interest. - * @return Error code (0-ok, 1-point not found in domain). - */ - virtual int evaluateAt(FloatArray &answer, DofManager *dman, - ValueModeType mode, TimeStep *tStep); + + int evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) override; + int evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) override; + /** * Evaluates the field at given DOF manager, allows to select specific * dofs using mask @@ -234,11 +218,10 @@ class OOFEM_EXPORT PrimaryField : public Field */ virtual void advanceSolution(TimeStep *tStep); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode); - - virtual const char *giveClassName() const { return "PrimaryField"; } + void saveContext(DataStream &stream) override; + void restoreContext(DataStream &stream) override; + const char *giveClassName() const override { return "PrimaryField"; } int giveActualStepNumber() { return actualStepNumber; } protected: diff --git a/src/oofemlib/primaryunknownmapper.h b/src/oofemlib/primaryunknownmapper.h index 3170924e9..e1ba2048f 100644 --- a/src/oofemlib/primaryunknownmapper.h +++ b/src/oofemlib/primaryunknownmapper.h @@ -91,7 +91,7 @@ class OOFEM_EXPORT PrimaryUnknownMapper * @return Nonzero if o.k. */ virtual int evaluateAt(FloatArray &answer, IntArray &dofMask, ValueModeType mode, - Domain *oldd, FloatArray &coords, IntArray ®List, TimeStep *tStep) = 0; + Domain *oldd, const FloatArray &coords, IntArray ®List, TimeStep *tStep) = 0; protected: /// Returns string for prepending output (used by error reporting macros). std :: string errorInfo(const char *func) const; diff --git a/src/oofemlib/problemcomm.C b/src/oofemlib/problemcomm.C index 64673b10e..e57ed05ab 100644 --- a/src/oofemlib/problemcomm.C +++ b/src/oofemlib/problemcomm.C @@ -78,7 +78,7 @@ NodeCommunicator :: setUpCommunicationMaps(EngngModel *pm, bool excludeSelfCommF Domain *domain = pm->giveDomain(1); int nnodes = domain->giveNumberOfDofManagers(); - + int size = this->processComms.size(); // // receive and send maps are same and are assembled locally // using DofManager's partition lists. @@ -146,7 +146,8 @@ ElementCommunicator :: setUpCommunicationMaps(EngngModel *pm, bool excludeSelfC OOFEM_LOG_RELEVANT("[%d] ElementCommunicator :: Setting up communication maps\n", rank); Domain *domain = pm->giveDomain(1); - + int size = this->processComms.size(); + /* * Initially, each partition knows for which nodes a receive * is needed (and can therefore compute easily the recv map), @@ -221,13 +222,13 @@ ElementCommunicator :: setUpCommunicationMaps(EngngModel *pm, bool excludeSelfC #ifdef __VERBOSE_PARALLEL - for (int i=0; igiveProcessCommunicator(i)->giveToRecvMap()->giveSize() ); - printf ("domain %d-%d: reecv map:",rank,i); - this->giveProcessCommunicator(i)->giveToRecvMap()->printYourself(); + for ( int i = 0; i < size; i++ ) { + fprintf(stderr, "domain %d-%d: domainCommRecvsize is %d\n", rank, i, this->giveProcessCommunicator(i)->giveToRecvMap().giveSize() ); + printf("domain %d-%d: reecv map:", rank, i); + this->giveProcessCommunicator(i)->giveToRecvMap().printYourself(); } #endif - + // to assemble send maps, we must analyze broadcasted remote domain send lists // and we must also broadcast our send list. @@ -347,12 +348,12 @@ WARNING: NOT SUPPORTED MESSAGE PARSING LIBRARY this->setProcessCommunicatorToSendArry(this->giveProcessCommunicator(i), toSendMap); #ifdef __VERBOSE_PARALLEL - fprintf (stderr, "domain %d-%d: domainCommSendsize is %d\n",rank,i,this->giveProcessCommunicator(i)->giveToSendMap()->giveSize() ); - printf ("domain %d-%d: send map:",rank,i); - this->giveProcessCommunicator(i)->giveToSendMap()->printYourself(); - + fprintf(stderr, "domain %d-%d: domainCommSendsize is %d\n", rank, i, this->giveProcessCommunicator(i)->giveToSendMap().giveSize() ); + printf("domain %d-%d: send map:", rank, i); + this->giveProcessCommunicator(i)->giveToSendMap().printYourself(); + #endif - + //this->giveDomainCommunicator(i)->setToSendArry (this->engngModel, toSendMap); } // end receiving broadcasted lists @@ -423,7 +424,6 @@ ProblemCommunicator :: quickSortPartition( IntArray &map, int l, int r, int ( Pr { int i = l - 1, j = r; int v = map.at(r); - int swap; for ( ; ; ) { while ( ( ( this->*cmp )(map.at(++i), v) ) < 0 ) { @@ -440,14 +440,10 @@ ProblemCommunicator :: quickSortPartition( IntArray &map, int l, int r, int ( Pr break; } - swap = map.at(i); - map.at(i) = map.at(j); - map.at(j) = swap; + std::swap(map.at(i), map.at(j)); } - swap = map.at(i); - map.at(i) = map.at(r); - map.at(r) = swap; + std::swap(map.at(i), map.at(r)); return i; } diff --git a/src/oofemlib/problemcomm.h b/src/oofemlib/problemcomm.h index c13f13402..c4ffa67a1 100644 --- a/src/oofemlib/problemcomm.h +++ b/src/oofemlib/problemcomm.h @@ -121,9 +121,9 @@ class OOFEM_EXPORT NodeCommunicator : public ProblemCommunicator NodeCommunicator(EngngModel * emodel, CommunicatorBuff * b, int rank, int size); virtual ~NodeCommunicator() {} - virtual void setUpCommunicationMaps(EngngModel *emodel, bool excludeSelfCommFlag, bool forceReinit = false); - virtual int setProcessCommunicatorToSendArry(ProcessCommunicator *processComm, IntArray &map); - virtual int setProcessCommunicatorToRecvArry(ProcessCommunicator *processComm, IntArray &map); + void setUpCommunicationMaps(EngngModel *emodel, bool excludeSelfCommFlag, bool forceReinit = false) override; + int setProcessCommunicatorToSendArry(ProcessCommunicator *processComm, IntArray &map) override; + int setProcessCommunicatorToRecvArry(ProcessCommunicator *processComm, IntArray &map) override; }; class OOFEM_EXPORT ElementCommunicator : public ProblemCommunicator @@ -132,9 +132,9 @@ class OOFEM_EXPORT ElementCommunicator : public ProblemCommunicator ElementCommunicator(EngngModel * emodel, CommunicatorBuff * b, int rank, int size); virtual ~ElementCommunicator() {} - virtual void setUpCommunicationMaps(EngngModel *emodel, bool excludeSelfCommFlag, bool forceReinit = false); - virtual int setProcessCommunicatorToSendArry(ProcessCommunicator *processComm, IntArray &map); - virtual int setProcessCommunicatorToRecvArry(ProcessCommunicator *processComm, IntArray &map); + void setUpCommunicationMaps(EngngModel *emodel, bool excludeSelfCommFlag, bool forceReinit = false) override; + int setProcessCommunicatorToSendArry(ProcessCommunicator *processComm, IntArray &map) override; + int setProcessCommunicatorToRecvArry(ProcessCommunicator *processComm, IntArray &map) override; }; } // end namespace oofem diff --git a/src/oofemlib/problemsequence.C b/src/oofemlib/problemsequence.C index 0bbeb2d11..a040c09f4 100644 --- a/src/oofemlib/problemsequence.C +++ b/src/oofemlib/problemsequence.C @@ -64,14 +64,14 @@ void ProblemSequence :: solveYourself() } -int ProblemSequence :: instanciateYourself(DataReader *dr, InputRecord *ir, const char *outFileName, const char *desc) +int ProblemSequence :: instanciateYourself(DataReader &dr, InputRecord &ir, const char *outFileName, const char *desc) { int result = EngngModel :: instanciateYourself(dr, ir, dataOutputFileName.c_str(), desc); - ir->finish(); + ir.finish(); for ( auto &s : inputStreamNames ) { OOFEMTXTDataReader dr( inputStreamNames [ i - 1 ] ); - std :: unique_ptr< EngngModel >prob( InstanciateProblem(& dr, this->pMode, this->contextOutputMode, NULL) ); + std :: unique_ptr< EngngModel >prob( InstanciateProblem(dr, this->pMode, this->contextOutputMode, NULL) ); emodelList.emplace_back(std :: move(prob)); if ( prob ) { return 0; @@ -82,11 +82,11 @@ int ProblemSequence :: instanciateYourself(DataReader *dr, InputRecord *ir, cons } -IRResultType ProblemSequence :: initializeFrom(InputRecord *ir) +void ProblemSequence :: initializeFrom(InputRecord &ir) { - IRResultType ret = EngngModel :: initializeFrom(ir); + EngngModel :: initializeFrom(ir); + IR_GIVE_FIELD(ir, inputStreamNames, _IFT_ProblemSequence_engineeringModels); - return ret; } @@ -100,29 +100,27 @@ int ProblemSequence :: checkProblemConsistency() } -contextIOResultType ProblemSequence :: saveContext(DataStream &stream, ContextMode mode) +void ProblemSequence :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType ret = EngngModel :: saveContext(stream, mode); + EngngModel :: saveContext(stream, mode); stream.write(activeModel); - for (auto &emodel : emodelList) { + for ( auto &emodel : emodelList ) { emodel->saveContext(stream, mode); } - return ret; } -contextIOResultType ProblemSequence :: restoreContext(DataStream *stream, ContextMode mode, void *obj) +void ProblemSequence :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType ret = EngngModel :: restoreContext(stream, mode, obj); + EngngModel :: restoreContext(stream, mode); - stream->read(activeModel); + stream.read(activeModel); - for (auto &emodel : emodelList) { - emodel->restoreContext(stream, mode, obj); + for ( auto &emodel : emodelList ) { + emodel->restoreContext(stream, mode); } - return ret; } diff --git a/src/oofemlib/problemsequence.h b/src/oofemlib/problemsequence.h index 5973b5738..4fa5a1c6a 100644 --- a/src/oofemlib/problemsequence.h +++ b/src/oofemlib/problemsequence.h @@ -67,7 +67,7 @@ class OOFEM_EXPORT ProblemSequence : public EngngModel public: /// Constructor - ProblemSequence(int i, EngngModel * _master = NULL); + ProblemSequence(int i, EngngModel *master=nullptr); /// Destructor. virtual ~ProblemSequence(); @@ -76,31 +76,31 @@ class OOFEM_EXPORT ProblemSequence : public EngngModel EngngModel & giveActiveModel() { return *emodelList[activeModel]; } - virtual void solveYourself(); + void solveYourself() override; //virtual void initializeYourself(TimeStep *tStep); - virtual int instanciateYourself(DataReader *dr, InputRecord *ir, const char *outFileName, const char *desc); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int checkProblemConsistency(); + int instanciateYourself(DataReader &dr, InputRecord &ir, const char *outFileName, const char *desc) override; + void initializeFrom(InputRecord &ir) override; + int checkProblemConsistency() override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; // identification - virtual const char *giveClassName() const { return "ProblemSequence"; } - virtual const char *giveInputRecordName() const { return _IFT_ProblemSequence_Name; } + const char *giveClassName() const override { return "ProblemSequence"; } + const char *giveInputRecordName() const { return _IFT_ProblemSequence_Name; } #ifdef __OOFEG - virtual void drawYourself(oofegGraphicContext &gc); - virtual void drawElements(oofegGraphicContext &gc); - virtual void drawNodes(oofegGraphicContext &gc); - virtual void showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep) { } + void drawYourself(oofegGraphicContext &gc) override; + void drawElements(oofegGraphicContext &gc) override; + void drawNodes(oofegGraphicContext &gc) override; + void showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep) override { } #endif - virtual EngngModel *giveSlaveProblem(int i) { return NULL; } - virtual int giveNumberOfSlaveProblems() { return 0; } + EngngModel *giveSlaveProblem(int i) override { return NULL; } + int giveNumberOfSlaveProblems() override { return 0; } - virtual int instanciateDefaultMetaStep(InputRecord *ir) { return 1; } + int instanciateDefaultMetaStep(InputRecord &ir) override { return 1; } }; } // end namespace oofem #endif // problemsequence_h diff --git a/src/oofemlib/processcomm.C b/src/oofemlib/processcomm.C index 71bab5562..53f0a65d6 100644 --- a/src/oofemlib/processcomm.C +++ b/src/oofemlib/processcomm.C @@ -45,28 +45,21 @@ namespace oofem { ProcessCommunicatorBuff :: ProcessCommunicatorBuff(CommBuffType t) { if ( t == CBT_static ) { - send_buff = new StaticCommunicationBuffer(MPI_COMM_WORLD); - recv_buff = new StaticCommunicationBuffer(MPI_COMM_WORLD); + send_buff = std::make_unique(MPI_COMM_WORLD); + recv_buff = std::make_unique(MPI_COMM_WORLD); } else { - send_buff = new DynamicCommunicationBuffer(MPI_COMM_WORLD); - recv_buff = new DynamicCommunicationBuffer(MPI_COMM_WORLD); + send_buff = std::make_unique(MPI_COMM_WORLD); + recv_buff = std::make_unique(MPI_COMM_WORLD); } } ProcessCommunicator :: ProcessCommunicator(ProcessCommunicatorBuff *b, int rank, CommunicatorMode m) : - toSend(), toReceive() + rank(rank), + pcBuffer(b), + toSend(), toReceive(), + mode(m) { - this->rank = rank; - this->pcBuffer = b; - this->mode = m; -} - - -ProcessCommunicatorBuff :: ~ProcessCommunicatorBuff() -{ - delete send_buff; - delete recv_buff; } diff --git a/src/oofemlib/processcomm.h b/src/oofemlib/processcomm.h index b01c57dd2..49c103e86 100644 --- a/src/oofemlib/processcomm.h +++ b/src/oofemlib/processcomm.h @@ -46,6 +46,7 @@ #include "logger.h" #include +#include namespace oofem { /** @@ -65,35 +66,34 @@ class OOFEM_EXPORT ProcessCommunicatorBuff: public DataStream { protected: /// Send buffer. - CommunicationBuffer *send_buff; + std::unique_ptr send_buff; /// Receive buffer. - CommunicationBuffer *recv_buff; + std::unique_ptr recv_buff; public: /// Constructor, creates empty send and receive com buffs in MPI_COMM_WORLD. ProcessCommunicatorBuff(CommBuffType t); - virtual ~ProcessCommunicatorBuff(); - virtual int givePackSizeOfInt(int count) { return send_buff->givePackSizeOfInt(count); } - virtual int givePackSizeOfDouble(int count) { return send_buff->givePackSizeOfDouble(count); } - virtual int givePackSizeOfChar(int count) { return send_buff->givePackSizeOfChar(count); } - virtual int givePackSizeOfBool(int count) { return send_buff->givePackSizeOfBool(count); } - virtual int givePackSizeOfLong(int count) { return send_buff->givePackSizeOfLong(count); } + int givePackSizeOfInt(int count) override { return send_buff->givePackSizeOfInt(count); } + int givePackSizeOfDouble(int count) override { return send_buff->givePackSizeOfDouble(count); } + int givePackSizeOfChar(int count) override { return send_buff->givePackSizeOfChar(count); } + int givePackSizeOfBool(int count) override { return send_buff->givePackSizeOfBool(count); } + int givePackSizeOfLong(int count) override { return send_buff->givePackSizeOfLong(count); } using DataStream::write; - virtual int write(const int *data, int count) { return send_buff->write(data, count); } - virtual int write(const long *data, int count) { return send_buff->write(data, count); } - virtual int write(const unsigned long *data, int count) { return send_buff->write(data, count); } - virtual int write(const double *data, int count) { return send_buff->write(data, count); } - virtual int write(const char *data, int count) { return send_buff->write(data, count); } - virtual int write(bool data) { return send_buff->write(data); } + int write(const int *data, int count) override { return send_buff->write(data, count); } + int write(const long *data, int count) override { return send_buff->write(data, count); } + int write(const unsigned long *data, int count) override { return send_buff->write(data, count); } + int write(const double *data, int count) override { return send_buff->write(data, count); } + int write(const char *data, int count) override { return send_buff->write(data, count); } + int write(bool data) override { return send_buff->write(data); } using DataStream::read; - virtual int read(int *data, int count) { return this->recv_buff->read(data, count); } - virtual int read(long *data, int count) { return this->recv_buff->read(data, count); } - virtual int read(unsigned long *data, int count) { return this->recv_buff->read(data, count); } - virtual int read(double *data, int count) { return this->recv_buff->read(data, count); } - virtual int read(char *data, int count) { return this->recv_buff->read(data, count); } - virtual int read(bool &data) { return recv_buff->read(data); } + int read(int *data, int count) override { return this->recv_buff->read(data, count); } + int read(long *data, int count) override { return this->recv_buff->read(data, count); } + int read(unsigned long *data, int count) override { return this->recv_buff->read(data, count); } + int read(double *data, int count) override { return this->recv_buff->read(data, count); } + int read(char *data, int count) override { return this->recv_buff->read(data, count); } + int read(bool &data) override { return recv_buff->read(data); } /// Initializes send buffer to empty state. All packed data are lost. void initSendBuff() { send_buff->init(); } @@ -160,11 +160,11 @@ class OOFEM_EXPORT ProcessCommunicatorBuff: public DataStream /** * Returns send buffer of receiver. */ - CommunicationBuffer *giveSendBuff() { return send_buff; } + CommunicationBuffer &giveSendBuff() { return *send_buff; } /** * Returns receive buffer of receiver. */ - CommunicationBuffer *giveRecvBuff() { return recv_buff; } + CommunicationBuffer &giveRecvBuff() { return *recv_buff; } }; @@ -198,8 +198,6 @@ class OOFEM_EXPORT ProcessCommunicator * @param m Mode of communicator. */ ProcessCommunicator(ProcessCommunicatorBuff * b, int irank, CommunicatorMode m = CommMode_Static); - /// Destructor - ~ProcessCommunicator() { } /** * Returns corresponding rank of associated partition @@ -220,11 +218,11 @@ class OOFEM_EXPORT ProcessCommunicator /** * Returns receiver to send map. */ - const IntArray *giveToSendMap() { return & toSend; } + const IntArray &giveToSendMap() { return toSend; } /** * Returns receiver to receive map. */ - const IntArray *giveToRecvMap() { return & toReceive; } + const IntArray &giveToRecvMap() { return toReceive; } /** @@ -399,7 +397,7 @@ ProcessCommunicator :: resizeSendBuff(T *emodel, int packUnpackType) { int size; // determine space for send buffer - size = emodel->estimateMaxPackSize(toSend, * giveProcessCommunicatorBuff()->giveSendBuff(), packUnpackType); + size = emodel->estimateMaxPackSize(toSend, giveProcessCommunicatorBuff()->giveSendBuff(), packUnpackType); giveProcessCommunicatorBuff()->resizeSendBuffer(size); //giveSendBuff()->resize (size); return 1; @@ -412,7 +410,7 @@ ProcessCommunicator :: resizeRecvBuff(T *emodel, int packUnpackType) int size; // determine space for recv buffer - size = emodel->estimateMaxPackSize(toReceive, * giveProcessCommunicatorBuff()->giveRecvBuff(), packUnpackType); + size = emodel->estimateMaxPackSize(toReceive, giveProcessCommunicatorBuff()->giveRecvBuff(), packUnpackType); giveProcessCommunicatorBuff()->resizeReceiveBuffer(size); //giveRecvBuff()->resize (size); diff --git a/src/oofemlib/pythonexpression.C b/src/oofemlib/pythonexpression.C index af7d5027c..5b1f0fcd3 100644 --- a/src/oofemlib/pythonexpression.C +++ b/src/oofemlib/pythonexpression.C @@ -55,10 +55,10 @@ PythonExpression :: ~PythonExpression() Py_DECREF(this->main_dict); } -IRResultType -PythonExpression :: initializeFrom(InputRecord *ir) +void +PythonExpression :: initializeFrom(InputRecord &ir) { - IRResultType result; + Function :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->fExpression, _IFT_PythonExpression_f); IR_GIVE_OPTIONAL_FIELD(ir, this->dfdtExpression, _IFT_PythonExpression_dfdt); @@ -73,8 +73,6 @@ PythonExpression :: initializeFrom(InputRecord *ir) PyObject *main_module = PyImport_AddModule("__main__"); this->main_dict = PyModule_GetDict(main_module); } - - return Function :: initializeFrom(ir); } @@ -89,7 +87,7 @@ PythonExpression :: giveInputRecord(DynamicInputRecord &input) PyObject * -PythonExpression :: getDict(std :: map< std :: string, FunctionArgument > &valDict) +PythonExpression :: getDict(const std :: map< std :: string, FunctionArgument > &valDict) { PyObject *local_dict = PyDict_New(); for ( const auto &named_arg: valDict ) { @@ -120,10 +118,10 @@ PythonExpression :: getDict(std :: map< std :: string, FunctionArgument > &valDi void -PythonExpression :: getArray(FloatArray &answer, PyObject *func, std :: map< std :: string, FunctionArgument > &valDict) +PythonExpression :: getArray(FloatArray &answer, PyObject *func, const std :: map< std :: string, FunctionArgument > &valDict) { PyObject *local_dict = getDict(valDict); - PyObject *dummy = PyEval_EvalCode( ( PyCodeObject * ) func, main_dict, local_dict ); + PyObject *dummy = PyEval_EvalCode( func, main_dict, local_dict ); PyObject *ret = PyDict_GetItemString(local_dict, RETURN_VARIABLE); if ( PyList_Check(ret) ) { int size = PyList_GET_SIZE(ret); @@ -141,21 +139,21 @@ PythonExpression :: getArray(FloatArray &answer, PyObject *func, std :: map< std void -PythonExpression :: evaluate(FloatArray &answer, std :: map< std :: string, FunctionArgument > &valDict) +PythonExpression :: evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp, double param) { this->getArray(answer, this->f, valDict); } void -PythonExpression :: evaluateVelocity(FloatArray &answer, std :: map< std :: string, FunctionArgument > &valDict) +PythonExpression :: evaluateVelocity(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict) { this->getArray(answer, this->dfdt, valDict); } void -PythonExpression :: evaluateAcceleration(FloatArray &answer, std :: map< std :: string, FunctionArgument > &valDict) +PythonExpression :: evaluateAcceleration(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict) { this->getArray(answer, this->d2fdt2, valDict); } @@ -166,7 +164,7 @@ PythonExpression :: getScalar(PyObject *func, double time) { PyObject *local_dict = PyDict_New(); PyDict_SetItemString( local_dict, "t", PyFloat_FromDouble(time) ); - PyObject *dummy = PyEval_EvalCode( ( PyCodeObject * ) func, main_dict, local_dict ); + PyObject *dummy = PyEval_EvalCode( func, main_dict, local_dict ); double val = 0.; PyObject *ret = PyDict_GetItemString(local_dict, RETURN_VARIABLE); if ( PyFloat_Check(ret) ) { diff --git a/src/oofemlib/pythonexpression.h b/src/oofemlib/pythonexpression.h index 91777ba22..43d5b86fe 100644 --- a/src/oofemlib/pythonexpression.h +++ b/src/oofemlib/pythonexpression.h @@ -72,9 +72,9 @@ class OOFEM_EXPORT PythonExpression : public Function PyObject *main_dict; /// Helper function to convert the std::map to a Python dictionary. - PyObject *getDict(std :: map< std :: string, FunctionArgument > &valDict); + PyObject *getDict(const std :: map< std :: string, FunctionArgument > &valDict); /// Helper function to run given function for given value dictionary. - void getArray(FloatArray &answer, PyObject *func, std :: map< std :: string, FunctionArgument > &valDict); + void getArray(FloatArray &answer, PyObject *func, const std :: map< std :: string, FunctionArgument > &valDict); /// Helper function to run given function for given time double getScalar(PyObject *func, double time); @@ -94,18 +94,19 @@ class OOFEM_EXPORT PythonExpression : public Function * - dfdt(t) (optional) * - d2fdt2(t) (optional) */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &ir); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &ir) override; - virtual void evaluate(FloatArray &answer, std :: map< std :: string, FunctionArgument > &valDict); - virtual void evaluateVelocity(FloatArray &answer, std :: map< std :: string, FunctionArgument > &valDict); - virtual void evaluateAcceleration(FloatArray &answer, std :: map< std :: string, FunctionArgument > &valDict); - virtual double evaluateAtTime(double t); - virtual double evaluateVelocityAtTime(double t); - virtual double evaluateAccelerationAtTime(double t); + void evaluate(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict, GaussPoint *gp=nullptr, double param=0.) override; + void evaluateVelocity(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict); + void evaluateAcceleration(FloatArray &answer, const std :: map< std :: string, FunctionArgument > &valDict); - virtual const char *giveClassName() const { return "PythonExpression"; } - virtual const char *giveInputRecordName() const { return _IFT_PythonExpression_Name; } + double evaluateAtTime(double t) override; + double evaluateVelocityAtTime(double t) override; + double evaluateAccelerationAtTime(double t) override; + + const char *giveClassName() const override { return "PythonExpression"; } + const char *giveInputRecordName() const override { return _IFT_PythonExpression_Name; } }; } // end namespace oofem #endif // pythonexpression_h diff --git a/src/oofemlib/pythonfield.C b/src/oofemlib/pythonfield.C new file mode 100644 index 000000000..6286014ec --- /dev/null +++ b/src/oofemlib/pythonfield.C @@ -0,0 +1,91 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +//#include +#include + +#include "field.h" +#include "pythonfield.h" +#include "floatarray.h" +#include "timestep.h" + +namespace py = pybind11; + +namespace oofem { +// REGISTER_Material(PythonField); + + +/// Constructor. +PythonField :: PythonField(void) : Field(FieldType::FT_Unknown) +{ + //pybind11::print("Hello, World!"); // use the Python API +} + +void PythonField :: setFunctionName(std::string functionName){ + this->functionName = functionName; +} + + +void PythonField :: setModuleName(std::string moduleName){ + this->moduleName = moduleName; + //this->moduleName.resize(this->moduleName.size()); //remove trailing quotes +} + + +int PythonField :: evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) +{ + // Do not use the raw CPython API functions Py_Initialize and Py_Finalize as these do not properly handle the lifetime of pybind11’s internal data. + // https://pybind11.readthedocs.io/en/stable/advanced/embedding.html + + // py::scoped_interpreter guard{}; // start the interpreter and keep it alive + +// py::initialize_interpreter(); + + py::module calc = py::module::import(moduleName.c_str()); + py::object result = calc.attr(functionName.c_str())(coords, mode, tStep); + answer = result.cast(); +// py::finalize_interpreter(); + + return 0; +} + +int PythonField :: evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) +{ + OOFEM_ERROR("Not implemented"); + return 1; +} + + + +} // end namespace oofem diff --git a/src/oofemlib/pythonfield.h b/src/oofemlib/pythonfield.h new file mode 100644 index 000000000..da81c0bca --- /dev/null +++ b/src/oofemlib/pythonfield.h @@ -0,0 +1,92 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef pythonfield_h +#define pythonfield_h + +#include "field.h" +#include "floatarray.h" +#include "intarray.h" +#include "classfactory.h" +#include "dynamicinputrecord.h" +#include "dofmanager.h" +#include "error.h" +#include + + +///@name Input fields for PythonField +//@{ +#define _IFT_PythonField_Name "pythonmaterial" +#define _IFT_PythonField_moduleName "module" /// The name of the module with the supplied functions (i.e. the name of the python script, without file extension) +//@} + +namespace oofem { +/** + * Custom user supplied python scripts for field. + * The python module should contain the functions + * @code{.py} + * evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) # returns int + * @endcode + * + * @author Vit Smilauer + */ +class OOFEM_EXPORT PythonField : public Field +{ +private: + /// Name of python module containing evaluating function function + std::string moduleName; + std::string functionName; + +public: +// Constructor. + PythonField(void); + + void setFunctionName(std::string functionName); + void setModuleName(std::string moduleName); + + int evaluateAt(FloatArray &answer, const FloatArray &coords, + ValueModeType mode, TimeStep *tStep) override; + + + int evaluateAt(FloatArray &answer, DofManager *dman, + ValueModeType mode, TimeStep *tStep) override; + + void saveContext(DataStream &stream) override { } + void restoreContext(DataStream &stream) override { } + + const char *giveClassName() const override { return "PythonField"; } +}; + +} // end namespace oofem +#endif // pythonfield_h diff --git a/src/oofemlib/qcnode.C b/src/oofemlib/qcnode.C index ee05424a3..b42fe6be3 100644 --- a/src/oofemlib/qcnode.C +++ b/src/oofemlib/qcnode.C @@ -35,7 +35,7 @@ #include "qcnode.h" -#include "../sm/EngineeringModels/qclinearstatic.h" +#include "sm/EngineeringModels/qclinearstatic.h" #include "hangingnode.h" #include "slavedof.h" #include "floatarray.h" @@ -58,17 +58,15 @@ qcNode :: qcNode(int n, Domain *aDomain) : Node(n, aDomain) #endif } -IRResultType qcNode :: initializeFrom(InputRecord *ir) +void qcNode :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - Node :: initializeFrom(ir); this->masterElement = -1; IR_GIVE_OPTIONAL_FIELD(ir, this->masterElement, _IFT_qcNode_masterElement); this->masterRegion = 0; IR_GIVE_OPTIONAL_FIELD(ir, this->masterRegion, _IFT_qcNode_masterRegion); - +#ifdef __SM_MODULE QClinearStatic *em = dynamic_cast< QClinearStatic * >( this->giveDomain()->giveEngngModel() ); if ( em ) { if ( em->giveQcApproachNumber() == 0 ) { @@ -84,9 +82,9 @@ IRResultType qcNode :: initializeFrom(InputRecord *ir) } else { OOFEM_ERROR("\"qcNode\" can be used only in \"QClinearStatic\" EngngModel"); } - - - return IRRT_OK; +#else + OOFEM_ERROR("\"qcNode\" can be used only in \"QClinearStatic\" EngngModel"); +#endif } int qcNode :: checkConsistency() @@ -224,18 +222,25 @@ qcNode :: initializeAsRepnode() */ // if node is in fullsolved domain + +#ifdef __SM_MODULE QClinearStatic *em = dynamic_cast< QClinearStatic * >( this->giveDomain()->giveEngngModel() ); -#ifdef DEBUG if ( !em ) { OOFEM_ERROR("qcNode is used in unsupported Engineering Models"); } -#endif + if ( em->nodeInFullSolvedDomainTest(this) ) { return true; } //else return false; + +#else + OOFEM_ERROR("qcNode is used in unsupported Engineering Models"); + return false; +#endif + } void qcNode :: setAsRepnode() diff --git a/src/oofemlib/qcnode.h b/src/oofemlib/qcnode.h old mode 100755 new mode 100644 index 23e5571a5..6fb09d8fb --- a/src/oofemlib/qcnode.h +++ b/src/oofemlib/qcnode.h @@ -85,24 +85,22 @@ class OOFEM_EXPORT qcNode : public Node /// Destructor. virtual ~qcNode(void) { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void postInitialize(); - virtual void postInitializeAsHangingNode(); - virtual int checkConsistency(); - virtual bool isDofTypeCompatible(dofType type) const { return ( type == DT_master || type == DT_slave ); } + void initializeFrom(InputRecord &ir) override; + void postInitialize() override; + void postInitializeAsHangingNode(); + int checkConsistency() override; + bool isDofTypeCompatible(dofType type) const override { return ( type == DT_master || type == DT_slave ); } - virtual bool initializeAsRepnode(); virtual void setAsRepnode(); virtual void setAsHanging(); - virtual int giveQcNodeType() {return this->qcNodeTypeLabel; } - virtual int giveMasterElementNumber() {return this->masterElement; } + int giveQcNodeType() override { return this->qcNodeTypeLabel; } + virtual int giveMasterElementNumber() { return this->masterElement; } - void printOutputAt(FILE *stream, TimeStep *tStep); - - - virtual const char *giveClassName() const { return "qcNode"; } - virtual const char *giveInputRecordName() const { return _IFT_qcNode_Name; } + void printOutputAt(FILE *stream, TimeStep *tStep) override; + + const char *giveClassName() const override { return "qcNode"; } + const char *giveInputRecordName() const override { return _IFT_qcNode_Name; } }; } // end namespace oofem #endif // qcnode_h diff --git a/src/oofemlib/randommaterialext.C b/src/oofemlib/randommaterialext.C index 3ffd1f9a5..a788a2763 100644 --- a/src/oofemlib/randommaterialext.C +++ b/src/oofemlib/randommaterialext.C @@ -59,22 +59,17 @@ RandomMaterialStatusExtensionInterface :: _setProperty(int key, double value) } -IRResultType -RandomMaterialExtensionInterface :: initializeFrom(InputRecord *ir) +void +RandomMaterialExtensionInterface :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - randVariables.clear(); randomVariableGenerators.clear(); IR_GIVE_OPTIONAL_FIELD(ir, randVariables, _IFT_RandomMaterialExt_randVariables); IR_GIVE_OPTIONAL_FIELD(ir, randomVariableGenerators, _IFT_RandomMaterialExt_randGen); if ( randVariables.giveSize() != randomVariableGenerators.giveSize() ) { - OOFEM_WARNING("Incompatible size of randvars and randdist attrs"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_RandomMaterialExt_randVariables, "Incompatible size of randvars and randdist attrs"); } - - return IRRT_OK; } @@ -87,8 +82,16 @@ RandomMaterialExtensionInterface :: giveInputRecord(DynamicInputRecord &ir) bool -RandomMaterialExtensionInterface :: give(int key, GaussPoint *gp, double &value) +RandomMaterialExtensionInterface :: give(int key, GaussPoint *gp, double &value) const { + MaterialStatus *status = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); + + // check if random material status has been initialized - does not have to be if material is used as a dummy + if ( status->giveInterface(RandomMaterialStatusExtensionInterfaceType) == NULL ) { + return false; + } + + RandomMaterialStatusExtensionInterface *interface = dynamic_cast< RandomMaterialStatusExtensionInterface * > ( gp->giveMaterialStatus()->giveInterface(RandomMaterialStatusExtensionInterfaceType) ); return interface->_giveProperty(key, value); @@ -100,15 +103,15 @@ RandomMaterialExtensionInterface :: _generateStatusVariables(GaussPoint *gp) con // Have to wrap it through the material to ensure that it gets an actual material status (for now at least) int size = randVariables.giveSize(); double value; - MaterialStatus *matStat = static_cast< MaterialStatus* >( gp->giveMaterialStatus() ); + MaterialStatus *matStat = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); RandomMaterialStatusExtensionInterface *status = static_cast< RandomMaterialStatusExtensionInterface * > ( matStat->giveInterface(RandomMaterialStatusExtensionInterfaceType) ); for ( int i = 1; i <= size; i++ ) { FloatArray globalCoordinates; - if ( gp->giveElement()->computeGlobalCoordinates( globalCoordinates, gp->giveSubPatchCoordinates() ) ) { - Function *f = gp->giveElement()->giveDomain()->giveFunction( randomVariableGenerators.at(i) ); - value = f->evaluate({{"x", globalCoordinates}}); + if ( gp->giveElement()->computeGlobalCoordinates(globalCoordinates, gp->giveSubPatchCoordinates() ) ) { + Function *f = gp->giveElement()->giveDomain()->giveFunction(randomVariableGenerators.at(i) ); + value = f->evaluate({{ "x", globalCoordinates } }); status->_setProperty(randVariables.at(i), value); } else { OOFEM_ERROR("computeGlobalCoordinates failed"); diff --git a/src/oofemlib/randommaterialext.h b/src/oofemlib/randommaterialext.h index 9f04755ff..5d6268d49 100644 --- a/src/oofemlib/randommaterialext.h +++ b/src/oofemlib/randommaterialext.h @@ -111,13 +111,13 @@ class OOFEM_EXPORT RandomMaterialExtensionInterface : public Interface * The density of material is read into property dictionary (keyword 'd') * Intended to be called from material initializeFrom service. */ - IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir); void giveInputRecord(DynamicInputRecord &ir); /** * Returns the property in associated status of given integration point if defined. * @returns true if property available, false otherwise */ - bool give(int key, GaussPoint *gp, double &value); + bool give(int key, GaussPoint *gp, double &value) const; protected: diff --git a/src/oofemlib/reinforcement.C b/src/oofemlib/reinforcement.C index 20782420c..7b4b38a46 100644 --- a/src/oofemlib/reinforcement.C +++ b/src/oofemlib/reinforcement.C @@ -39,11 +39,9 @@ namespace oofem { REGISTER_BoundaryCondition(Reinforcement); -IRResultType -Reinforcement :: initializeFrom(InputRecord *ir) +void +Reinforcement :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - # ifdef VERBOSE // VERBOSE_PRINT1 ("Instanciating load ",number) # endif @@ -51,7 +49,5 @@ Reinforcement :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, porosity, _IFT_Reinforcement_porosity); IR_GIVE_FIELD(ir, shapefactor, _IFT_Reinforcement_shapeFactor); IR_GIVE_FIELD(ir, permeability, _IFT_Reinforcement_permeability); - - return IRRT_OK; } } // end namespace oofem diff --git a/src/oofemlib/reinforcement.h b/src/oofemlib/reinforcement.h index d4bd315cd..3c50413fc 100644 --- a/src/oofemlib/reinforcement.h +++ b/src/oofemlib/reinforcement.h @@ -62,7 +62,6 @@ class OOFEM_EXPORT Reinforcement : public BodyLoad double shapefactor; FloatArray permeability; - public: /// Constructor Reinforcement(int i, Domain * d) : BodyLoad(i, d) { } @@ -74,15 +73,15 @@ class OOFEM_EXPORT Reinforcement : public BodyLoad * @param coords Global coordinates, which are used to evaluate components values. * @param mode Determines response mode- */ - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override { computeComponentArrayAt(answer, tStep, mode); } - virtual bcValType giveBCValType() const { return ReinforceBVT; } - virtual bcGeomType giveBCGeoType() const { return BodyLoadBGT; } + bcValType giveBCValType() const override { return ReinforceBVT; } + bcGeomType giveBCGeoType() const override { return BodyLoadBGT; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "Reinforcement"; } - virtual const char *giveInputRecordName() const { return _IFT_Reinforcement_Name; } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "Reinforcement"; } + const char *giveInputRecordName() const override { return _IFT_Reinforcement_Name; } /// Accessor double givePorosity() { return porosity; } diff --git a/src/oofemlib/rigidarmnode.C b/src/oofemlib/rigidarmnode.C index 828461e72..bfe925177 100644 --- a/src/oofemlib/rigidarmnode.C +++ b/src/oofemlib/rigidarmnode.C @@ -48,25 +48,17 @@ RigidArmNode :: RigidArmNode(int n, Domain *aDomain) : Node(n, aDomain) { } -IRResultType -RigidArmNode :: initializeFrom(InputRecord *ir) +void +RigidArmNode :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = Node :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + Node :: initializeFrom(ir); IR_GIVE_FIELD(ir, masterDofMngr, _IFT_RigidArmNode_master); IR_GIVE_FIELD(ir, masterMask, _IFT_DofManager_mastermask); if ( masterMask.giveSize() != this->dofidmask->giveSize() ) { - OOFEM_WARNING("mastermask size mismatch"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_DofManager_mastermask, "mastermask size mismatch"); } - - return IRRT_OK; } void @@ -232,7 +224,11 @@ RigidArmNode :: computeMasterContribution(std::map< DofIDItem, IntArray > &maste bool hasg2l = this->computeL2GTransformation(TG2L, fullDofMask); bool mhasg2l = masterNode->computeL2GTransformation(TMG2L, fullDofMask); - xyz.beDifferenceOf(*this->giveCoordinates(), *masterNode->giveCoordinates()); + xyz.beDifferenceOf(this->giveCoordinates(), masterNode->giveCoordinates()); + + if (xyz.giveSize() < 3) { + xyz.resizeWithValues(3); + } TR.beUnitMatrix(); TR.at(1,5) = xyz.at(3); @@ -262,7 +258,11 @@ RigidArmNode :: computeMasterContribution(std::map< DofIDItem, IntArray > &maste masterContribution [ id ].resize(dofidmask->giveSize()); for (int j = 1; j <= this->dofidmask->giveSize(); j++ ) { - masterContribution [ id ].at(j) = T.at(id, dofidmask->at(j)); + if ( dofidmask->at(j) <= 6 && id <= 6 ) { + masterContribution [ id ].at(j) = T.at(id, dofidmask->at(j)); + } else if ( dofidmask->findFirstIndexOf(id) == j ) { + masterContribution [ id ].at(j) = 1; + } } } diff --git a/src/oofemlib/rigidarmnode.h b/src/oofemlib/rigidarmnode.h index 9dc5c3308..72684e00d 100644 --- a/src/oofemlib/rigidarmnode.h +++ b/src/oofemlib/rigidarmnode.h @@ -93,19 +93,19 @@ class OOFEM_EXPORT RigidArmNode : public Node /// Destructor. virtual ~RigidArmNode(void) { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void postInitialize(); - virtual void updateLocalNumbering(EntityRenumberingFunctor &f); - virtual int checkConsistency(); + void initializeFrom(InputRecord &ir) override; + void postInitialize() override; + void updateLocalNumbering(EntityRenumberingFunctor &f) override; + int checkConsistency() override; /** * Compute vector of master contribution coefficients - SUMA of contributions == 1.0 */ void computeMasterContribution(std::map< DofIDItem, IntArray > &masterDofID, std::map< DofIDItem, FloatArray > &masterContribution); - virtual const char *giveClassName() const { return "RigidArmNode"; } - virtual const char *giveInputRecordName() const { return _IFT_RigidArmNode_Name; } - virtual bool isDofTypeCompatible(dofType type) const { return ( type == DT_master || type == DT_slave ); } + const char *giveClassName() const override { return "RigidArmNode"; } + const char *giveInputRecordName() const override { return _IFT_RigidArmNode_Name; } + bool isDofTypeCompatible(dofType type) const override { return ( type == DT_master || type == DT_slave ); } }; } // end namespace oofem #endif // rigidarmnode_h diff --git a/src/oofemlib/rowcol.C b/src/oofemlib/rowcol.C index 5d177cd0b..7c4f10b9c 100644 --- a/src/oofemlib/rowcol.C +++ b/src/oofemlib/rowcol.C @@ -33,58 +33,56 @@ */ #include "rowcol.h" -#include "floatarray.h" #include "intarray.h" +#include "floatarray.h" #include "mathfem.h" #include "error.h" #include +#include namespace oofem { -RowColumn :: RowColumn(int n, int st) -// Constructor. Creates a row-column with number n, starting at index st. + +RowColumn :: RowColumn(int n): + number(n), + start(n), + row(0), + column(0), + diag(0.) { - int size; - - number = n; - start = st; - diag = 0.; - size = number - start; - if ( size ) { - row = ( double * ) calloc( size, sizeof( double ) ); - column = ( double * ) calloc( size, sizeof( double ) ); - if ( !row || !column ) { - OOFEM_ERROR("Failed to allocate memory"); - } - } else { - row = NULL; - column = NULL; - } } -RowColumn :: ~RowColumn() -// Destructor. +RowColumn :: RowColumn(int n, int start): + number(n), + start(start), + row(n-start), + column(n-start), + diag(0.) { - free(row); - free(column); } #ifdef DEBUG double &RowColumn :: atU(int i) -// Returns the i-th coefficient of the column of the receiver. Slow but -// safe. { this->checkBounds(i); return column [ i - start ]; } -#endif +double RowColumn :: atU(int i) const +{ + this->checkBounds(i); + return column [ i - start ]; +} -#ifdef DEBUG double &RowColumn :: atL(int i) -// Returns the i-th coefficient of the row of the receiver. Slow but safe. +{ + this->checkBounds(i); + return row [ i - start ]; +} + +double RowColumn :: atL(int i) const { this->checkBounds(i); return row [ i - start ]; @@ -92,8 +90,7 @@ double &RowColumn :: atL(int i) #endif -void RowColumn :: checkBounds(int i) -// Checks that the receiver (k) possesses coefficients (i,k) and (k,i). +void RowColumn :: checkBounds(int i) const { if ( i < start || i >= number ) { OOFEM_ERROR("error in bounds of RowColumn %d (start=%d) : no entry %d", number, start, i); @@ -102,12 +99,10 @@ void RowColumn :: checkBounds(int i) void RowColumn :: checkSizeTowards(const IntArray &loc) -// If loc points to a coefficient which out of the receiver's range, -// enlarges the receiver. { - int n, i, j, c, first = start; + int i, c, first = start; - n = loc.giveSize(); + int n = loc.giveSize(); if ( !n ) { OOFEM_ERROR("0-size location array"); } @@ -120,7 +115,7 @@ void RowColumn :: checkSizeTowards(const IntArray &loc) } // get min coefficient in loc - for ( j = i + 1; j <= n; j++ ) { + for ( int j = i + 1; j <= n; j++ ) { if ( ( c = loc.at(j) ) ) { first = min(c, first); } @@ -133,29 +128,26 @@ void RowColumn :: checkSizeTowards(const IntArray &loc) } -double RowColumn :: dot(const FloatArray &b, char c, int first, int last) +double RowColumn :: dot(const FloatArray &b, char c, int first, int last) const // Returns the dot product of the row (c=='R') or the column (c=='C') of // the receiver with array 'b', from indices 'first' to 'last'. { - double answer, *p1; - int i; - - answer = 0.; - i = last - first + 1; - if ( i > 0 ) { - if ( c == 'R' ) { - p1 = row + first - start; - } else { - p1 = column + first - start; - } + double answer = 0.; + int i = last - first + 1; - // I do the bad practice, because it speed up debug runs significantly / Mikael - const double *p2 = b.givePointer() + first-1 ; // bad practice ! - //int pos = first; - while ( i-- ) { - answer += *p1++ * *p2++ ; - //answer += * p1++ * b.at(pos++); - } + const double *p1; + if ( c == 'R' ) { + p1 = row.data() + first - start; + } else { + p1 = column.data() + first - start; + } + + // I do the bad practice, because it speed up debug runs significantly / Mikael + const double *p2 = b.givePointer() + first-1 ; // bad practice ! + //int pos = first; + while ( i-- ) { + answer += *p1++ * *p2++ ; + //answer += * p1.at(pos) * b.at(pos++); } return answer; @@ -164,59 +156,25 @@ double RowColumn :: dot(const FloatArray &b, char c, int first, int last) void RowColumn :: growTo(int newStart) -// Enlarges the receiver (the column upwards, the row leftwards) to -// 'start' = newStart. { - int newSize, size, i; - double *newRow, *newColumn, *p1, *p2; - - if ( newStart == start ) { - return; - } - # ifdef DEBUG if ( newStart <= 0 || newStart > start ) { OOFEM_ERROR("cannot enlarge RowCol %d (start=%d) to %d", number, start, newStart); } - # endif - - newSize = number - newStart; - newRow = ( double * ) calloc( newSize, sizeof( double ) ); - newColumn = ( double * ) calloc( newSize, sizeof( double ) ); - if ( !newRow || !newColumn ) { - OOFEM_ERROR("Failed to allocate memory"); - } - size = number - start; - - if ( size ) { - p1 = row; - p2 = newRow + ( start - newStart ); - i = size; - while ( i-- ) { - * p2++ = * p1++; - } - - free(row); - - p1 = column; - p2 = newColumn + ( start - newStart ); - i = size; - while ( i-- ) { - * p2++ = * p1++; - } - - free(column); + int increase = start - newStart; + row.resize(this->number-newStart); + column.resize(this->number-newStart); + if ( this->number - start > 0 ) { + ///@todo Might be better to just store the data in the opposite order instead, so that a resize "does the right thing" directly. + std::rotate(row.rbegin(), row.rbegin()+increase, row.rend()); + std::rotate(column.rbegin(), column.rbegin()+increase, column.rend()); } - - row = newRow; - column = newColumn; - start = newStart; + start = newStart; } -void RowColumn :: printYourself() -// Prints the receiver on screen. +void RowColumn :: printYourself() const { printf("Row-column %d : start = %d, diag = %.5f\n col : ", number, start, diag); @@ -235,60 +193,10 @@ void RowColumn :: printYourself() void RowColumn :: zero() -// Sets all coefficients of the receiver to 0. { - int size = number - start; - + std::fill(row.begin(), row.end(), 0.); + std::fill(column.begin(), column.end(), 0.); diag = 0.; - if ( size ) { - for ( int i = 0; i < size; i++ ) { - column [ i ] = 0.0; - row [ i ] = 0.0; - } - } } -RowColumn * -RowColumn :: GiveCopy() -{ - int i; - double *newRow, *newColumn, *p1, *p2; - int size = number - start; - - if ( size ) { - newRow = ( double * ) malloc( size * sizeof( double ) ); - newColumn = ( double * ) malloc( size * sizeof( double ) ); - if ( !newRow || !newColumn ) { - OOFEM_ERROR("Failed to allocate memory"); - } - - p1 = row; - p2 = newRow; - i = size; - while ( i-- ) { - * p2++ = * p1++; - } - - p1 = column; - p2 = newColumn; - i = size; - while ( i-- ) { - * p2++ = * p1++; - } - } else { - newRow = newColumn = NULL; - } - - return new RowColumn(this->number, this->start, newRow, newColumn, this->diag); -} - - -RowColumn :: RowColumn(int inumber, int istart, double *irow, double *icol, double idiag) -{ - this->number = inumber; - this->start = istart; - this->row = irow; - this->column = icol; - this->diag = idiag; -} } // end namespace oofem diff --git a/src/oofemlib/rowcol.h b/src/oofemlib/rowcol.h index 9bb588fdc..7dddd8e06 100644 --- a/src/oofemlib/rowcol.h +++ b/src/oofemlib/rowcol.h @@ -37,9 +37,11 @@ #include "oofemcfg.h" +#include "vector" + namespace oofem { -class FloatArray; class IntArray; +class FloatArray; /** * This class implements a segment of a unsymmetric matrix stored in @@ -65,38 +67,37 @@ class IntArray; class OOFEM_NO_EXPORT RowColumn { protected: - int number; int start; - double *row; - double *column; + std::vector row; + std::vector column; double diag; public: - RowColumn(int, int); - ~RowColumn(); + RowColumn(int n); + RowColumn(int n, int start); #ifdef DEBUG double &atU(int); double &atL(int); + double atU(int) const; + double atL(int) const; #else double &atU(int i) { return column [ i - start ]; } double &atL(int i) { return row [ i - start ]; } + double atU(int i) const { return column [ i - start ]; } + double atL(int i) const { return row [ i - start ]; } #endif double &atDiag() { return diag; } - void checkBounds(int); + double atDiag() const { return diag; } + void checkBounds(int) const; void checkSizeTowards(const IntArray &); - double dot(const FloatArray &, char, int, int); - int giveStart() { return start; } + double dot(const FloatArray &, char, int, int) const; + int giveStart() const { return start; } void growTo(int); void zero(); - void printYourself(); - int giveSize() { return 1 + 2 * ( number - start ); } - - RowColumn *GiveCopy(); - -protected: - RowColumn(int, int, double *, double *, double); + void printYourself() const; + int giveSize() const { return 1 + 2 * ( number - start ); } }; } // end namespace oofem #endif // rowcol_h diff --git a/src/oofemlib/scalarfunction.h b/src/oofemlib/scalarfunction.h index 0efa378d0..da91111f6 100644 --- a/src/oofemlib/scalarfunction.h +++ b/src/oofemlib/scalarfunction.h @@ -133,7 +133,7 @@ class ScalarFunction * @param d domain managing external functions */ //double eval(double time, const FloatArray &coords, Domain *d) const; - + /** * True if receiver is defined. */ diff --git a/src/oofemlib/set.C b/src/oofemlib/set.C index 3792e3c05..960d01a57 100644 --- a/src/oofemlib/set.C +++ b/src/oofemlib/set.C @@ -48,13 +48,13 @@ #include namespace oofem { -IRResultType Set :: initializeFrom(InputRecord *ir) +void Set :: initializeFrom(InputRecord &ir) { - IRResultType result; + FEMComponent :: initializeFrom(ir); IntArray inputNodes; std :: list< Range >inputNodeRanges; - if ( ir->hasField(_IFT_Set_allNodes) ) { // generate a list with all the node numbers + if ( ir.hasField(_IFT_Set_allNodes) ) { // generate a list with all the node numbers this->nodes.enumerate(this->giveDomain()->giveNumberOfDofManagers()); } else { IR_GIVE_OPTIONAL_FIELD(ir, inputNodes, _IFT_Set_nodes); @@ -62,7 +62,7 @@ IRResultType Set :: initializeFrom(InputRecord *ir) this->computeIntArray(this->nodes, inputNodes, inputNodeRanges); } - if ( ir->hasField(_IFT_Set_allElements) ) { // generate a list with all the element numbers + if ( ir.hasField(_IFT_Set_allElements) ) { // generate a list with all the element numbers this->elements.enumerate(this->giveDomain()->giveNumberOfElements()); mElementListIsSorted = false; } else { @@ -83,8 +83,6 @@ IRResultType Set :: initializeFrom(InputRecord *ir) this->elementSurfaces.clear(); IR_GIVE_OPTIONAL_FIELD(ir, this->elementSurfaces, _IFT_Set_elementSurfaces); - - return FEMComponent :: initializeFrom(ir); } @@ -150,47 +148,43 @@ const IntArray &Set :: giveNodeList() IntArray afflictedNodes( this->domain->giveNumberOfDofManagers() ); afflictedNodes.zero(); for ( int ielem = 1; ielem <= this->elements.giveSize(); ++ielem ) { - Element *e = this->domain->giveElement( this->elements.at(ielem) ); + auto e = this->domain->giveElement( this->elements.at(ielem) ); for ( int inode = 1; inode <= e->giveNumberOfNodes(); ++inode ) { afflictedNodes.at( e->giveNode(inode)->giveNumber() ) = 1; } } /* boundary entities are obsolete, use edges and/or surfaces instead */ - IntArray bNodes; for ( int ibnd = 1; ibnd <= this->elementBoundaries.giveSize() / 2; ++ibnd ) { - Element *e = this->domain->giveElement( this->elementBoundaries.at(ibnd * 2 - 1) ); - int boundary = this->elementBoundaries.at(ibnd * 2); - FEInterpolation *fei = e->giveInterpolation(); - fei->boundaryGiveNodes(bNodes, boundary); + auto e = this->domain->giveElement( this->elementBoundaries.at(ibnd * 2 - 1) ); + auto boundary = this->elementBoundaries.at(ibnd * 2); + auto fei = e->giveInterpolation(); + auto bNodes = fei->boundaryGiveNodes(boundary); for ( int inode = 1; inode <= bNodes.giveSize(); ++inode ) { afflictedNodes.at( e->giveNode( bNodes.at(inode) )->giveNumber() ) = 1; } } - IntArray eNodes; for ( int iedge = 1; iedge <= this->elementEdges.giveSize() / 2; ++iedge ) { - Element *e = this->domain->giveElement( this->elementEdges.at(iedge * 2 - 1) ); - int edge = this->elementEdges.at(iedge * 2); - FEInterpolation *fei = e->giveInterpolation(); - fei->boundaryEdgeGiveNodes(eNodes, edge); + auto e = this->domain->giveElement( this->elementEdges.at(iedge * 2 - 1) ); + auto edge = this->elementEdges.at(iedge * 2); + auto fei = e->giveInterpolation(); + auto eNodes = fei->boundaryEdgeGiveNodes(edge); for ( int inode = 1; inode <= eNodes.giveSize(); ++inode ) { afflictedNodes.at( e->giveNode( eNodes.at(inode) )->giveNumber() ) = 1; } } for ( int isurf = 1; isurf <= this->elementSurfaces.giveSize() / 2; ++isurf ) { - Element *e = this->domain->giveElement( this->elementSurfaces.at(isurf * 2 - 1) ); - int surf = this->elementSurfaces.at(isurf * 2); - FEInterpolation *fei = e->giveInterpolation(); - fei->boundarySurfaceGiveNodes(eNodes, surf); + auto e = this->domain->giveElement( this->elementSurfaces.at(isurf * 2 - 1) ); + auto surf = this->elementSurfaces.at(isurf * 2); + auto fei = e->giveInterpolation(); + auto eNodes = fei->boundarySurfaceGiveNodes(surf); for ( int inode = 1; inode <= eNodes.giveSize(); ++inode ) { afflictedNodes.at( e->giveNode( eNodes.at(inode) )->giveNumber() ) = 1; } } - - for ( int inode = 1; inode <= this->nodes.giveSize(); ++inode ) { afflictedNodes.at( this->nodes.at(inode) ) = 1; } @@ -264,15 +258,12 @@ void Set :: updateLocalElementNumbering(EntityRenumberingFunctor &f) } -contextIOResultType Set :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void Set :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = FEMComponent :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + FEMComponent :: saveContext(stream, mode); if ( ( mode & CM_Definition ) ) { + contextIOResultType iores; if ( ( iores = elements.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -286,19 +277,14 @@ contextIOResultType Set :: saveContext(DataStream &stream, ContextMode mode, voi THROW_CIOERR(iores); } } - - return CIO_OK; } -contextIOResultType Set :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void Set :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = FEMComponent :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + FEMComponent :: restoreContext(stream, mode); if ( mode & CM_Definition ) { + contextIOResultType iores; if ( ( iores = elements.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -314,7 +300,5 @@ contextIOResultType Set :: restoreContext(DataStream &stream, ContextMode mode, } this->totalNodes.clear(); - - return CIO_OK; } } diff --git a/src/oofemlib/set.h b/src/oofemlib/set.h index 7ce02f330..c5a10464c 100644 --- a/src/oofemlib/set.h +++ b/src/oofemlib/set.h @@ -48,7 +48,7 @@ namespace oofem { #define _IFT_Set_allNodes "allnodes" ///< List of specific node indices. #define _IFT_Set_nodeRanges "noderanges" ///< List of node index ranges. #define _IFT_Set_elements "elements" ///< List of specific element indices. -#define _IFT_Set_allElements "allelements" ///< Will generate a list of att the elements in the domain) +#define _IFT_Set_allElements "allelements" ///< Will generate a list of all elements in the domain. #define _IFT_Set_elementRanges "elementranges" ///< List of element index ranges. #define _IFT_Set_elementBoundaries "elementboundaries" ///< Interleaved array of element index + boundary number #define _IFT_Set_elementEdges "elementedges" ///< Interleaved array of element index + edge number @@ -84,8 +84,8 @@ class OOFEM_EXPORT Set : public FEMComponent Set(int n, Domain * d) : FEMComponent(n, d), mElementListIsSorted(false) { } virtual ~Set() { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; /** * Returns list of elements within set. * @return List of element numbers. @@ -148,7 +148,7 @@ class OOFEM_EXPORT Set : public FEMComponent /// Return True if given element is contained bool hasElement(int elem) const; - virtual void updateLocalNumbering(EntityRenumberingFunctor &f); + void updateLocalNumbering(EntityRenumberingFunctor &f) override; /** * Renumbering of nodes (could change due to load balancing). */ @@ -158,11 +158,11 @@ class OOFEM_EXPORT Set : public FEMComponent */ void updateLocalElementNumbering(EntityRenumberingFunctor &f); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual const char *giveClassName() const { return "Set"; } - virtual const char *giveInputRecordName() const { return _IFT_Set_Name; } + const char *giveClassName() const override { return "Set"; } + const char *giveInputRecordName() const override { return _IFT_Set_Name; } protected: /** diff --git a/src/oofemlib/simpleslavedof.C b/src/oofemlib/simpleslavedof.C index dc5b79c8f..91f42c621 100644 --- a/src/oofemlib/simpleslavedof.C +++ b/src/oofemlib/simpleslavedof.C @@ -146,16 +146,9 @@ SimpleSlaveDof :: giveBcValue(ValueModeType mode, TimeStep *tStep) } -contextIOResultType SimpleSlaveDof :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full node context (saves state variables, that completely describe -// current state) -// -{ - contextIOResultType iores; - if ( ( iores = Dof :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } +void SimpleSlaveDof :: saveContext(DataStream &stream, ContextMode mode) +{ + Dof :: saveContext(stream, mode); if ( mode & CM_Definition ) { @@ -170,22 +163,12 @@ contextIOResultType SimpleSlaveDof :: saveContext(DataStream &stream, ContextMod } } } - - return CIO_OK; } -contextIOResultType SimpleSlaveDof :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full node context (saves state variables, that completely describe -// current state) -// +void SimpleSlaveDof :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = Dof :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + Dof :: restoreContext(stream, mode); if ( mode & CM_Definition ) { if ( !stream.read(masterDofMngr) ) { @@ -194,9 +177,6 @@ contextIOResultType SimpleSlaveDof :: restoreContext(DataStream &stream, Context } this->masterDofIndx = -1; - - - return CIO_OK; } void diff --git a/src/oofemlib/simpleslavedof.h b/src/oofemlib/simpleslavedof.h index 97342ae24..0dc935477 100644 --- a/src/oofemlib/simpleslavedof.h +++ b/src/oofemlib/simpleslavedof.h @@ -89,39 +89,39 @@ class OOFEM_EXPORT SimpleSlaveDof : public Dof /// Destructor. virtual ~SimpleSlaveDof() { } - virtual dofType giveDofType() { return DT_simpleSlave; } - virtual const char *giveClassName() const { return "SimpleSlaveDof"; } + dofType giveDofType() override { return DT_simpleSlave; } + const char *giveClassName() const override { return "SimpleSlaveDof"; } /** * Returns equation number corresponding to receiver. * Slave simply forwards this message to master. * @return Equation number, if active BC exists, returns zero */ - virtual int __giveEquationNumber() const; + int __giveEquationNumber() const override; /** * Returns prescribed equation number corresponding to receiver. * Slave simply forwards this message to master. * @return Prescribed equation number, if active BC exists, returns zero */ - virtual int __givePrescribedEquationNumber(); + int __givePrescribedEquationNumber() override; /** * Asks new equation number. Empty function (master is assumed to receive same message). */ - virtual int askNewEquationNumber(TimeStep *tStep) { return 1; } - virtual double giveUnknown(ValueModeType, TimeStep *); - virtual double giveUnknown(PrimaryField &field, ValueModeType, TimeStep *tStep); - virtual bool hasBc(TimeStep *tStep); - virtual bool hasIc(); - virtual bool hasIcOn(ValueModeType); - virtual int giveBcId(); - virtual int giveIcId(); - virtual double giveBcValue(ValueModeType mode, TimeStep *tStep); + int askNewEquationNumber(TimeStep *tStep) override { return 1; } + double giveUnknown(ValueModeType, TimeStep *) override; + double giveUnknown(PrimaryField &field, ValueModeType, TimeStep *tStep) override; + bool hasBc(TimeStep *tStep) override; + bool hasIc() override; + bool hasIcOn(ValueModeType) override; + int giveBcId() override; + int giveIcId() override; + double giveBcValue(ValueModeType mode, TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; /// Returns Master Dof Manager Number. int giveMasterDofManagerNum() const { return masterDofMngr; } - virtual void giveMasterDofManArray(IntArray &answer) { + void giveMasterDofManArray(IntArray &answer) override { answer.resize(1); answer.at(1) = masterDofMngr; } @@ -130,15 +130,15 @@ class OOFEM_EXPORT SimpleSlaveDof : public Dof /// Returns number of master dof in master dofManager. int giveMasterDofIndx() const { return masterDofIndx; } - virtual void updateLocalNumbering(EntityRenumberingFunctor &f); + void updateLocalNumbering(EntityRenumberingFunctor &f) override; private: /// Returns reference to master dof. Dof *giveMasterDof() const; protected: - BoundaryCondition *giveBc(); - InitialCondition *giveIc(); + BoundaryCondition *giveBc() override; + InitialCondition *giveIc() override; }; } // end namespace oofem #endif // simpleslavedof_h diff --git a/src/oofemlib/skyline.C b/src/oofemlib/skyline.C index 319d35353..254065f57 100644 --- a/src/oofemlib/skyline.C +++ b/src/oofemlib/skyline.C @@ -51,6 +51,7 @@ #include #include +#include #ifdef TIME_REPORT #include "timer.h" @@ -59,44 +60,35 @@ namespace oofem { REGISTER_SparseMtrx(Skyline, SMT_Skyline); -Skyline :: Skyline(int n) : SparseMtrx(n, n) +Skyline :: Skyline(int n) : SparseMtrx(n, n), + isFactorized(false) { - // constructor - // skyline is square mtrx, so size is n,n - // - nwk = 0; - mtrx = NULL; - isFactorized = false; } -Skyline :: Skyline() : SparseMtrx() -{ - // Constructor. Creates a skyline of size 0. - // nRows = nColumns = 0; // set by SparseMtrx constructor - nwk = 0; - mtrx = NULL; - isFactorized = false; -} +Skyline :: Skyline(const Skyline &s) : SparseMtrx(s.giveNumberOfRows(), s.giveNumberOfColumns()), + mtrx(s.mtrx), + adr(s.adr), + isFactorized(s.isFactorized) +{} -Skyline :: ~Skyline() +Skyline :: Skyline(int n, FloatArray mtrx1, IntArray adr1) : SparseMtrx(n, n), + mtrx(std::move(mtrx1)), + adr(std::move(adr1)), + isFactorized(false) +{} + + +std::unique_ptr Skyline :: clone() const { - // Destructor. - if ( this->giveNumberOfRows() ) { - free(mtrx); - } + return std::make_unique(*this); } double & Skyline :: at(int i, int j) { - // returns (i,j) element of the receiver - // indexes are checked if DEBUG is true - - int d1, k, ind; - #ifdef DEBUG // check size if ( ( i > this->giveNumberOfRows() ) || ( j > this->giveNumberOfRows() ) ) { @@ -106,13 +98,11 @@ Skyline :: at(int i, int j) #endif // only upper triangular part of skyline is stored if ( j < i ) { - k = i; - i = j; - j = k; + std::swap(i, j); } - d1 = this->adr.at(j); - ind = d1 + ( j - i ); + int d1 = this->adr.at(j); + int ind = d1 + ( j - i ); if ( ( adr.at(j + 1) - adr.at(j) ) <= ( j - i ) ) { OOFEM_ERROR("request for element which is not in sparse mtrx (%d,%d)", i, j); @@ -125,7 +115,6 @@ Skyline :: at(int i, int j) // } - // increment version flag this->version++; return mtrx [ ind ]; } @@ -133,11 +122,6 @@ Skyline :: at(int i, int j) double Skyline :: at(int i, int j) const { - // returns (i,j) element of the receiver - // indexes are checked if DEBUG is true - - int d1, k, ind; - #ifdef DEBUG // check size if ( ( i > this->giveNumberOfRows() ) || ( j > this->giveNumberOfRows() ) ) { @@ -147,23 +131,14 @@ Skyline :: at(int i, int j) const #endif // only upper triangular part of skyline is stored if ( j < i ) { - k = i; - i = j; - j = k; + std::swap(i, j); } - d1 = this->adr.at(j); - ind = d1 + ( j - i ); + int d1 = this->adr.at(j); + int ind = d1 + ( j - i ); if ( ( adr.at(j + 1) - adr.at(j) ) <= ( j - i ) ) { - OOFEM_ERROR("request for element which is not in sparse mtrx (%d,%d)", i, j); - // - // NOTE: - // - // don't return reference to some zero value; it is true, but possible change - // of its value will require rebuilding internal storage structure - // of sparse matrix - // + return 0.; } return mtrx [ ind ]; @@ -173,45 +148,36 @@ Skyline :: at(int i, int j) const bool Skyline :: isAllocatedAt(int i, int j) const { - int k, answer = 1; - if ( j < i ) { - k = i; - i = j; - j = k; + std::swap(i, j); } if ( ( adr.at(j + 1) - adr.at(j) ) <= ( j - i ) ) { - answer = 0; + return false; } - return (bool)answer; + return true; } void Skyline :: toFloatMatrix(FloatMatrix &answer) const { - // Returns a matrix, the receiver in a full storage form. This is useful - // for debugging and printings. - - int d1, d2, pk, size; + int size = this->giveNumberOfColumns(); - size = this->giveNumberOfColumns(); - # ifdef DEBUG if ( size != this->adr.giveSize() - 1 ) { OOFEM_ERROR("Internal error in skyline matrix: num columns != size(adr)-1: %d != %d", size, this->adr.giveSize() - 1); } -# endif +# endif answer.resize(size, size); answer.zero(); for ( int j = 1; j <= size; j++ ) { - d1 = adr.at(j); - d2 = adr.at(j + 1); - pk = j; + int d1 = adr.at(j); + int d2 = adr.at(j + 1); + int pk = j; for ( int i = d1; i < d2; i++ ) { answer.at(pk, j) = mtrx [ i ]; pk--; @@ -223,10 +189,6 @@ Skyline :: toFloatMatrix(FloatMatrix &answer) const int Skyline :: assemble(const IntArray &loc, const FloatMatrix &mat) { - // Assembles the elemental matrix 'mat' to the receiver, using 'loc' as a - // location array. The values in ke corresponding to a zero coefficient - // in loc are not assembled. - # ifdef DEBUG int dim = mat.giveNumberOfRows(); if ( dim != loc.giveSize() ) { @@ -257,7 +219,6 @@ int Skyline :: assemble(const IntArray &loc, const FloatMatrix &mat) } } - // increment vesion this->version++; return 1; } @@ -279,7 +240,6 @@ int Skyline :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatM } } - // increment version this->version++; return 1; @@ -287,23 +247,19 @@ int Skyline :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatM FloatArray *Skyline :: backSubstitutionWith(FloatArray &y) const -// Returns the solution x of the system U.x = y , where U is the receiver. -// note : x overwrites y { // allocation of answer FloatArray solution( y.giveSize() ); - int ack, ack1, acs, n; - int size = this->giveNumberOfRows(); + int n = this->giveNumberOfRows(); /************************************/ /* modification of right hand side */ /************************************/ - n = size; for ( int k = 2; k <= n; k++ ) { - ack = adr.at(k); - ack1 = adr.at(k + 1); + int ack = adr.at(k); + int ack1 = adr.at(k + 1); double s = 0.0; - acs = k - ( ack1 - ack ) + 1; + int acs = k - ( ack1 - ack ) + 1; for ( int i = ack1 - 1; i > ack; i-- ) { s += mtrx [ i ] * y.at(acs); acs++; @@ -316,15 +272,14 @@ FloatArray *Skyline :: backSubstitutionWith(FloatArray &y) const /* zpetny chod */ /*****************/ for ( int k = 1; k <= n; k++ ) { - acs = adr.at(k); - y.at(k) /= mtrx [ acs ]; + y.at(k) /= mtrx [ adr.at(k) ]; } for ( int k = n; k > 0; k-- ) { - ack = adr.at(k); - ack1 = adr.at(k + 1); + int ack = adr.at(k); + int ack1 = adr.at(k + 1); solution.at(k) = y.at(k); - acs = k - ( ack1 - ack ) + 1; + int acs = k - ( ack1 - ack ) + 1; for ( int i = ack1 - 1; i > ack; i-- ) { y.at(acs) -= mtrx [ i ] * solution.at(k); acs++; @@ -335,25 +290,15 @@ FloatArray *Skyline :: backSubstitutionWith(FloatArray &y) const return & y; } -int Skyline :: setInternalStructure(IntArray &a) +int Skyline :: setInternalStructure(IntArray a) { - // allocates and built structure according to given - // array of maximal column heights - // - adr = a; - int n = a.giveSize(); - nwk = adr.at(n); // check - if ( mtrx ) { - free(mtrx); - } + adr = std::move(a); + int n = adr.giveSize(); + int nwk = adr.at(n); + this->mtrx.resize(nwk); - mtrx = ( double * ) calloc( nwk, sizeof( double ) ); - if ( !mtrx ) { - OOFEM_ERROR("Can't allocate: %d", nwk); - } nRows = nColumns = n - 1; - // increment version this->version++; return true; } @@ -374,10 +319,7 @@ int Skyline :: buildInternalStructure(EngngModel *eModel, int di, const UnknownN neq = s.giveRequiredNumberOfDomainEquation(); } if ( neq == 0 ) { - if ( mtrx ) { - delete mtrx; - } - mtrx = NULL; + mtrx.clear(); adr.clear(); return true; } @@ -433,16 +375,16 @@ int Skyline :: buildInternalStructure(EngngModel *eModel, int di, const UnknownN } } - + if ( domain->hasContactManager() ) { ContactManager *cMan = domain->giveContactManager(); - - for ( int i =1; i <= cMan->giveNumberOfContactDefinitions(); i++ ) { + + for ( int i = 1; i <= cMan->giveNumberOfContactDefinitions(); i++ ) { ContactDefinition *cDef = cMan->giveContactDefinition(i); for ( int k = 1; k <= cDef->giveNumbertOfContactElements(); k++ ) { ContactElement *cEl = cDef->giveContactElement(k); cEl->giveLocationArray(loc, s); - + maxle = INT_MAX; for ( int ieq : loc ) { if ( ieq != 0 ) { @@ -454,12 +396,11 @@ int Skyline :: buildInternalStructure(EngngModel *eModel, int di, const UnknownN if ( ieq != 0 ) { mht.at(ieq) = min( maxle, mht.at(ieq) ); } - } } } } - + // NOTE // add there call to eModel if any possible additional equation added by // eModel @@ -469,7 +410,6 @@ int Skyline :: buildInternalStructure(EngngModel *eModel, int di, const UnknownN // mht is array containing minimal equation number per column // This method also increases column height. - adr.resize(neq + 1); ac1 = 1; @@ -480,17 +420,9 @@ int Skyline :: buildInternalStructure(EngngModel *eModel, int di, const UnknownN adr.at(neq + 1) = ac1; nRows = nColumns = neq; - nwk = ac1; - if ( mtrx ) { - free(mtrx); - } - mtrx = ( double * ) calloc( ac1, sizeof( double ) ); - if ( !mtrx ) { - OOFEM_ERROR("Can't allocate: %d", ac1); - } + mtrx.resize( ac1 ); - // increment version this->version++; return true; } @@ -500,12 +432,6 @@ SparseMtrx *Skyline :: factorized() { // Returns the receiver in U(transp).D.U Crout factorization form. - int aci, aci1, acj, acj1, ack, ack1, ac, acs, acri, acrk, n; - double s, g; - - /************************/ - /* matrix elimination */ - /************************/ if ( isFactorized ) { return this; } @@ -515,31 +441,31 @@ SparseMtrx *Skyline :: factorized() timer.startTimer(); #endif - n = this->giveNumberOfRows(); + int n = this->giveNumberOfRows(); - // report skyline statistics - OOFEM_LOG_DEBUG("Skyline info: neq is %d, nwk is %d\n", n, this->nwk); + OOFEM_LOG_DEBUG("Skyline info: neq is %d, nwk is %d\n", n, this->giveNumberOfNonZeros()); for ( int k = 2; k <= n; k++ ) { /* smycka pres sloupce matice */ - ack = adr.at(k); - ack1 = adr.at(k + 1); - acrk = k - ( ack1 - ack ) + 1; + int ack = adr.at(k); + int ack1 = adr.at(k + 1); + int acrk = k - ( ack1 - ack ) + 1; for ( int i = acrk + 1; i < k; i++ ) { /* smycka pres prvky jednoho sloupce matice */ - aci = adr.at(i); - aci1 = adr.at(i + 1); - acri = i - ( aci1 - aci ) + 1; + int aci = adr.at(i); + int aci1 = adr.at(i + 1); + int acri = i - ( aci1 - aci ) + 1; + int ac; if ( acri < acrk ) { ac = acrk; } else { ac = acri; } - acj = k - ac + ack; - acj1 = k - i + ack; - acs = i - ac + aci; - s = 0.0; + int acj = k - ac + ack; + int acj1 = k - i + ack; + int acs = i - ac + aci; + double s = 0.0; for ( int j = acj; j > acj1; j-- ) { s += mtrx [ j ] * mtrx [ acs ]; acs--; @@ -549,10 +475,10 @@ SparseMtrx *Skyline :: factorized() } /* uprava diagonalniho prvku */ - s = 0.0; + double s = 0.0; for ( int i = ack1 - 1; i > ack; i-- ) { - g = mtrx [ i ]; - acs = adr.at(acrk); + double g = mtrx [ i ]; + int acs = adr.at(acrk); acrk++; mtrx [ i ] /= mtrx [ acs ]; s += mtrx [ i ] * g; @@ -568,39 +494,36 @@ SparseMtrx *Skyline :: factorized() OOFEM_LOG_DEBUG( "Skyline info: user time consumed by factorization: %.2fs\n", timer.getUtime() ); #endif - // increment version //this->version++; return this; } - void Skyline :: times(const FloatArray &x, FloatArray &answer) const { // Computes y, the results of the y = U.x, where U is // the receiver. Returns the result. - int k, acb, acc, aci, aci1, ac, n; - double s; + int n = x.giveSize(); // // first check sizes // - if ( this->giveNumberOfRows() != ( n = x.giveSize() ) ) { + if ( this->giveNumberOfRows() != n ) { OOFEM_ERROR("size mismatch"); } answer.resize(n); answer.zero(); - acc = 1; + int acc = 1; for ( int i = 1; i <= n; i++ ) { - aci = adr.at(i); - aci1 = adr.at(i + 1); - ac = i - ( aci1 - aci ) + 1; - s = 0.0; - acb = ac; - for ( k = aci1 - 1; k >= aci; k-- ) { + int aci = adr.at(i); + int aci1 = adr.at(i + 1); + int ac = i - ( aci1 - aci ) + 1; + double s = 0.0; + int acb = ac; + for ( int k = aci1 - 1; k >= aci; k-- ) { s += mtrx [ k ] * x.at(acb); acb++; } @@ -610,8 +533,7 @@ void Skyline :: times(const FloatArray &x, FloatArray &answer) const for ( int j = ac; j < i; j++ ) { aci1--; - s = mtrx [ aci1 ]; - answer.at(j) += s * x.at(i); + answer.at(j) += mtrx [ aci1 ] * x.at(i); aci++; } } @@ -621,11 +543,8 @@ void Skyline :: times(const FloatArray &x, FloatArray &answer) const void Skyline :: times(double x) { // Multiplies receiver by scalar value. - for ( int j = 0; j < nwk; j++ ) { - mtrx [ j ] *= x; - } + mtrx.times(x); - // increment version this->version++; } @@ -634,18 +553,16 @@ void Skyline :: add(double x, SparseMtrx &m) { Skyline *M = dynamic_cast< Skyline* >( &m ); - for ( int j = 0; j < nwk; j++ ) { - mtrx [ j ] += x * M->mtrx [ j ]; - } + mtrx.add(x, M->mtrx); this->version++; } + void Skyline :: printYourself() const { // Prints the receiver on screen. FloatMatrix copy; - this->toFloatMatrix(copy); copy.printYourself(); } @@ -668,73 +585,29 @@ void Skyline :: writeToFile(const char *fname) const void Skyline :: zero() { - // Returns the receiver with all coefficients set to zero. - for ( int j = 0; j < nwk; j++ ) { - mtrx [ j ] = 0.0; - } - + mtrx.zero(); isFactorized = false; - // increment version this->version++; } -SparseMtrx *Skyline :: GiveCopy() const -{ - Skyline *answer; - double *mtrx1; - int neq; - - neq = this->giveNumberOfRows(); - - mtrx1 = ( double * ) malloc( this->nwk * sizeof( double ) ); - if ( !mtrx1 ) { - OOFEM_ERROR("Can't allocate: %d", this->nwk); - } - - for ( int i = 0; i < this->nwk; i++ ) { - mtrx1 [ i ] = this->mtrx [ i ]; - } - - answer = new Skyline(neq, this->nwk, mtrx1, adr); - - return answer; -} - -Skyline :: Skyline(int neq, int nwk1, double *mtrx1, const IntArray &adr1) : SparseMtrx(neq, neq) -{ - // constructor - // sets internal member data to given parameters - // used only by GiveCopy() member function - - nwk = nwk1; - mtrx = mtrx1; - adr = adr1; - isFactorized = 0; -} - -//Skyline *Skyline :: giveSubMatrix(Skyline &mat, IntArray &rows, IntArray &cols) -//Skyline *Skyline :: beSubMatrixOf(const Skyline &mat, IntArray &rows, IntArray &cols) -//SparseMtrx *Skyline :: beSubMatrixOf(const SparseMtrx &mat, IntArray &rows, IntArray &cols) -SparseMtrx *Skyline :: giveSubMatrix(const IntArray &rows, const IntArray &cols) +std::unique_ptr Skyline :: giveSubMatrix(const IntArray &rows, const IntArray &cols) { - IntArray positions( cols.giveSize() + 1 ); FloatArray values( this->giveNumberOfNonZeros() ); //TODO choose a better initial size? int diagPos = 1; int nnz = 0; // number of nonzeros - + for ( int j = 1; j <= cols.giveSize(); j++ ) { for ( int i = rows.giveSize(); i >= 1; i-- ) { // start from the "bottom of the matrix" - //if( cols.at(j) < rows.at(i) ){ - if( j < i ){ - continue; + if( j < i ){ + continue; } - + bool hasValue = this->isAllocatedAt( rows.at(i), cols.at(j) ); - + if ( hasValue && i == j ) { // allocated diagonal element values.at(++nnz) = this->at( rows.at(i), cols.at(j) ); positions.at(diagPos++) = nnz; @@ -744,42 +617,20 @@ SparseMtrx *Skyline :: giveSubMatrix(const IntArray &rows, const IntArray &cols) } else if ( hasValue ) { values.at(++nnz) = this->at( rows.at(i), cols.at(j) ); } - } } - + positions.at(diagPos++) = ++nnz; - - double *mtrxValues; - mtrxValues = ( double * ) malloc( nnz * sizeof( double ) ); - if ( !mtrxValues ) { - OOFEM_ERROR("Can't allocate: %d", nnz); - } - + + FloatArray mtrxValues(nnz); + for ( int i = 0; i < nnz-1; i++ ) { mtrxValues [ i + 1] = values [ i ]; } int neq = rows.giveSize(); - - Skyline *answer = new Skyline(neq, nnz, mtrxValues, positions); - - - - //this->adr.printYourself(); - //answer->adr.printYourself(); - //this->printYourself(); - - for ( int i = 0; i < nnz; i++ ) { - // printf("old %e, new %e \n", this->mtrx[i], answer->mtrx[i]); - //answer->mtrx.printYourself(); - } - - - - return answer; - -} + return std::make_unique(neq, mtrxValues, positions); +} void Skyline :: rbmodes(FloatMatrix &r, int &nse, IntArray &se, @@ -789,9 +640,8 @@ void Skyline :: rbmodes(FloatMatrix &r, int &nse, IntArray &se, * funkce rozlozi matici A na LDL tvar, pak vypocte * bazove vektory prostoru Ker A */ - int i, j, k, ii, jj, kk, lj, uj, li, ui, lk, uk, mi, ise, ib, neq = this->giveNumberOfRows(); + int neq = this->giveNumberOfRows(); IntArray adrb(7); - double s, g; FloatArray b(6 *neq); /**********************/ @@ -799,31 +649,32 @@ void Skyline :: rbmodes(FloatMatrix &r, int &nse, IntArray &se, /**********************/ // report skyline statistics - OOFEM_LOG_INFO("Skyline info: neq is %d, nwk is %d\n", neq, this->nwk); + OOFEM_LOG_INFO("Skyline info: neq is %d, nwk is %d\n", neq, this->giveNumberOfNonZeros()); if ( tc == 1 || tc == 3 ) { /* pocitadlo singularnich rovnic */ - ise = 1; + int ise = 1; /* pocitadlo v poli singularnich radku */ - ib = 1; + int ib = 1; adrb.at(1) = 1; /* cyklus pres radky, ktere maji byt odkondezovany */ - for ( i = 2; i <= neq; i++ ) { - lj = adr.at(i); - uj = adr.at(i + 1) - 2; + for ( int i = 2; i <= neq; i++ ) { + int lj = adr.at(i); + int uj = adr.at(i + 1) - 2; /* minimalni radkovy index v i tem sloupci */ - mi = i - ( uj - lj ) - 1; - j = mi + 1; + int mi = i - ( uj - lj ) - 1; + int j = mi + 1; /* cyklus pres mimodiagonalni prvky zpracovavaneho radku */ - for ( jj = uj; jj > lj; jj-- ) { - li = adr.at(j); - ui = adr.at(j + 1) - 1; - k = j - ( ui - li ); + for ( int jj = uj; jj > lj; jj-- ) { + int li = adr.at(j); + int ui = adr.at(j + 1) - 1; + int k = j - ( ui - li ); /* vyber nizsiho sloupce a tim urceni rozsahu cyklu */ + int uk, ii; if ( k < mi ) { uk = uj + 1; ii = li + j - mi; @@ -833,8 +684,8 @@ void Skyline :: rbmodes(FloatMatrix &r, int &nse, IntArray &se, } /* cyklus pres prvky nad zpracovavanym prvkem */ - s = 0.0; - for ( kk = uk; kk > jj; kk-- ) { + double s = 0.0; + for ( int kk = uk; kk > jj; kk-- ) { s += mtrx [ kk ] * mtrx [ ii ]; ii--; } @@ -844,10 +695,10 @@ void Skyline :: rbmodes(FloatMatrix &r, int &nse, IntArray &se, } /* uprava diagonalniho prvku */ - s = 0.0; + double s = 0.0; j = mi; - for ( jj = uj + 1; jj > lj; jj-- ) { - g = mtrx [ jj ]; + for ( int jj = uj + 1; jj > lj; jj-- ) { + double g = mtrx [ jj ]; mtrx [ jj ] /= mtrx [ adr.at(j) ]; s += mtrx [ jj ] * g; j++; @@ -862,7 +713,7 @@ void Skyline :: rbmodes(FloatMatrix &r, int &nse, IntArray &se, ise++; /* vynulovani prvku sloupce v poli a a jejich uchovani v poli b */ - for ( jj = uj + 1; jj > lj; jj-- ) { + for ( int jj = uj + 1; jj > lj; jj-- ) { b.at(ib) = mtrx [ jj ]; ib++; mtrx [ jj ] = 0.0; @@ -873,7 +724,7 @@ void Skyline :: rbmodes(FloatMatrix &r, int &nse, IntArray &se, adrb.at(ise) = ib; /* vynulovani prvku radku v poli a */ - for ( j = i + 1; j <= neq; j++ ) { + for ( int j = i + 1; j <= neq; j++ ) { if ( j - ( adr.at(j + 1) - adr.at(j) ) < i ) { mtrx [ adr.at(j) + j - i ] = 0.0; } @@ -886,12 +737,12 @@ void Skyline :: rbmodes(FloatMatrix &r, int &nse, IntArray &se, if ( tc == 2 || tc == 3 ) { /* navrat puvodne vynulovanych slozek */ - ise = nse; - for ( i = 1; i <= ise; i++ ) { - uj = adr.at(se.at(i) + 1) - 1; - lj = adr.at( se.at(i) ); - ib = adrb.at(i); - for ( jj = uj; jj > lj; jj-- ) { + int ise = nse; + for ( int i = 1; i <= ise; i++ ) { + int uj = adr.at(se.at(i) + 1) - 1; + int lj = adr.at( se.at(i) ); + int ib = adrb.at(i); + for ( int jj = uj; jj > lj; jj-- ) { mtrx [ jj ] = b.at(ib); ib++; } @@ -905,30 +756,24 @@ void Skyline :: rbmodes(FloatMatrix &r, int &nse, IntArray &se, r.clear(); } - for ( i = 1; i <= ise; i++ ) { - // ib=i*neq; - for ( j = neq; j > 0; j-- ) { + for ( int i = 1; i <= ise; i++ ) { + for ( int j = neq; j > 0; j-- ) { r.at(se.at(i), i) = 1.0; - s = r.at(j, i); - uk = adr.at(j + 1) - 1; - lk = adr.at(j); - k = j - ( uk - lk ); - for ( kk = uk; kk > lk; kk-- ) { - r.at(k, i) -= mtrx [ kk ] * s; + int uk = adr.at(j + 1) - 1; + int lk = adr.at(j); + int k = j - ( uk - lk ); + for ( int kk = uk; kk > lk; kk-- ) { + r.at(k, i) -= mtrx [ kk ] * r.at(j, i); k++; } } } } - // increment version //this->version++; } - - - void Skyline :: ldl_feti_sky(FloatArray &x, FloatArray &y, int nse, double limit, IntArray &se) /* @@ -948,14 +793,9 @@ void Skyline :: ldl_feti_sky(FloatArray &x, FloatArray &y, * * vystupy * x - vektor reseni - * - * 8.2.1999 */ { - long i, j, k, ii, lj, uj, neq; - double s; - - neq = this->giveNumberOfRows(); + int neq = this->giveNumberOfRows(); /*******************************************************/ /* vypocet pomocneho vektoru z */ @@ -964,12 +804,12 @@ void Skyline :: ldl_feti_sky(FloatArray &x, FloatArray &y, /* slozky vektoru y se prepisuji na slozky vektoru z */ /*******************************************************/ //k = 0; - for ( i = 1; i <= neq; i++ ) { - lj = adr.at(i); - uj = adr.at(i + 1) - 1; - ii = i - uj + lj; - s = 0.0; - for ( j = uj; j > lj; j-- ) { + for ( int i = 1; i <= neq; i++ ) { + int lj = adr.at(i); + int uj = adr.at(i + 1) - 1; + int ii = i - uj + lj; + double s = 0.0; + for ( int j = uj; j > lj; j-- ) { s += mtrx [ j ] * y.at(ii); ii++; } @@ -1011,7 +851,7 @@ void Skyline :: ldl_feti_sky(FloatArray &x, FloatArray &y, /**********************************************************/ /* deleni prvku vektoru prave strany diagonalnimi prvky */ /**********************************************************/ - for ( i = 1; i <= neq; i++ ) { + for ( int i = 1; i <= neq; i++ ) { y.at(i) /= mtrx [ adr.at(i) ]; } @@ -1019,10 +859,10 @@ void Skyline :: ldl_feti_sky(FloatArray &x, FloatArray &y, /* vypocet vektoru x z vektoru z */ /* vypocet se provadi pro m redukovanych neznamych */ /*****************************************************/ - k = nse; - for ( i = neq; i > 0; i-- ) { - lj = adr.at(i); - uj = adr.at(i + 1); + int k = nse; + for ( int i = neq; i > 0; i-- ) { + int lj = adr.at(i); + int uj = adr.at(i + 1); if ( k > 0 ) { if ( se.at(k) == i ) { y.at(i) = 1.0; @@ -1031,15 +871,14 @@ void Skyline :: ldl_feti_sky(FloatArray &x, FloatArray &y, } x.at(i) = y.at(i); - s = x.at(i); - ii = i - 1; - for ( j = lj + 1; j < uj; j++ ) { + double s = x.at(i); + int ii = i - 1; + for ( int j = lj + 1; j < uj; j++ ) { y.at(ii) -= s * mtrx [ j ]; ii--; } } - // increment version //this->version++; } } // end namespace oofem diff --git a/src/oofemlib/skyline.h b/src/oofemlib/skyline.h index fb1f5b8fd..f8fc9c474 100644 --- a/src/oofemlib/skyline.h +++ b/src/oofemlib/skyline.h @@ -37,6 +37,8 @@ #include "sparsemtrx.h" +#define _IFT_Skyline_Name "skyline" + namespace oofem { /** * Class implementing sparse matrix stored in skyline form. This class @@ -50,7 +52,7 @@ namespace oofem { * Attribute 'isFactorized' is True if the skyline is already in U(T).D.U * factorized form, else it is False. * Attribute adr is array of diagonal members, it's size is size+1 (adr[0]=neni, adr[1]=1) - * Attribute mtrx is double pointer to skyline stored in a array form + * Attribute mtrx is matrix values to skyline stored in a array form * (but we start from index 1) * * Tasks: @@ -66,12 +68,10 @@ namespace oofem { class OOFEM_EXPORT Skyline : public SparseMtrx { protected: - /// Total number of nonzero coefficients stored. - int nwk; + /// Vector of stored coefficients. + FloatArray mtrx; /// Integer array holding addresses of diagonal members. IntArray adr; - /// Vector of stored coefficients. - double *mtrx; /// Flag indicating whether factorized. int isFactorized; @@ -80,40 +80,34 @@ class OOFEM_EXPORT Skyline : public SparseMtrx * Constructor. Before any operation an internal profile must be built. * @see builInternalStructure */ - Skyline(int n); - /** - * Constructor. Before any operation an internal profile must be built. - * @see builInternalStructure - */ - Skyline(); + Skyline(int n=0); + Skyline(const Skyline &s); + Skyline(int n, FloatArray mtrx, IntArray adr); /// Destructor - virtual ~Skyline(); + virtual ~Skyline() {} - virtual SparseMtrx *GiveCopy() const; + std::unique_ptr clone() const override; - virtual void times(const FloatArray &x, FloatArray &answer) const; - virtual void timesT(const FloatArray &x, FloatArray &answer) const { this->times(x, answer); } - virtual void times(double x); - virtual void add(double x, SparseMtrx &m); - virtual int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &); + void times(const FloatArray &x, FloatArray &answer) const override; + void timesT(const FloatArray &x, FloatArray &answer) const override { this->times(x, answer); } + void times(double x) override; + void add(double x, SparseMtrx &m) override; + int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &) override; - //virtual Skyline *giveSubMatrix(Skyline &mat, IntArray &rows, IntArray &cols); - //virtual Skyline *beSubMatrixOf(const Skyline &mat, IntArray &rows, IntArray &cols); - //virtual SparseMtrx *beSubMatrixOf(const SparseMtrx &mat, IntArray &rows, IntArray &cols); - virtual SparseMtrx *giveSubMatrix(const IntArray &rows, const IntArray &cols); + std::unique_ptr giveSubMatrix(const IntArray &rows, const IntArray &cols) override; /** * Allocates and builds internal structure according to given * array holding addresses of diagonal members values (adr). */ - int setInternalStructure(IntArray &a); + int setInternalStructure(IntArray a); - virtual int assemble(const IntArray &loc, const FloatMatrix &mat); - virtual int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat); + int assemble(const IntArray &loc, const FloatMatrix &mat) override; + int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) override; - virtual bool canBeFactorized() const { return true; } - virtual SparseMtrx *factorized(); - virtual FloatArray *backSubstitutionWith(FloatArray &) const; - virtual void zero(); + bool canBeFactorized() const override { return true; } + SparseMtrx *factorized() override; + FloatArray *backSubstitutionWith(FloatArray &) const override; + void zero() override; /** * Splits the receiver to LDLT form, * and computes the rigid body motions. @@ -137,26 +131,20 @@ class OOFEM_EXPORT Skyline : public SparseMtrx * @param se indexes of singular equations */ void ldl_feti_sky(FloatArray &x, FloatArray &y, int nse, double limit, IntArray &se); - /// Returns coefficient at position (i,j). - virtual double &at(int, int); - /// Returns coefficient at position (i,j). - virtual double at(int i, int j) const; - /// Returns 0 if the memory is not allocated at position (i,j). - virtual bool isAllocatedAt(int i, int j) const; - int giveNumberOfNonZeros() const { return this->nwk; } - virtual void toFloatMatrix(FloatMatrix &answer) const; - /// Prints receiver to stdout. - virtual void printYourself() const; - virtual void writeToFile(const char *fname) const; - int giveAllocatedSize() { return nwk; } - virtual SparseMtrxType giveType() const { return SMT_Skyline; } - virtual bool isAsymmetric() const { return false; } + double &at(int, int) override; + double at(int i, int j) const override; + bool isAllocatedAt(int i, int j) const override; + int giveNumberOfNonZeros() const { return this->mtrx.giveSize(); } + void toFloatMatrix(FloatMatrix &answer) const override; + void printYourself() const override; + void writeToFile(const char *fname) const override; + int giveAllocatedSize() { return this->mtrx.giveSize(); } - virtual const char *giveClassName() const { return "Skyline"; } + SparseMtrxType giveType() const override { return SMT_Skyline; } + bool isAsymmetric() const override { return false; } -protected: - Skyline(int, int, double *, const IntArray &); + const char *giveClassName() const override { return "Skyline"; } }; } // end namespace oofem #endif // skyline_h diff --git a/src/oofemlib/skylineu.C b/src/oofemlib/skylineu.C index b40626d03..1910d05e0 100644 --- a/src/oofemlib/skylineu.C +++ b/src/oofemlib/skylineu.C @@ -53,48 +53,33 @@ namespace oofem { REGISTER_SparseMtrx(SkylineUnsym, SMT_SkylineU); -SkylineUnsym :: SkylineUnsym(int n) : SparseMtrx(n, n) - // Constructor. Creates an empty skyline unsymmetric. - +SkylineUnsym :: SkylineUnsym(int n) : SparseMtrx(n, n), + isFactorized(false) { - size = n; - rowColumns = NULL; - isFactorized = false; } -SkylineUnsym :: SkylineUnsym() : SparseMtrx() + +SkylineUnsym :: SkylineUnsym(const SkylineUnsym &s) : SparseMtrx(s.nRows, s.nColumns), + rowColumns(s.rowColumns), + isFactorized(s.isFactorized) { - // Constructor. Creates a skyline of size 0. - // nRows = nColumns = 0; // set by SparseMtrx constructor - size = 0; - rowColumns = NULL; - isFactorized = false; } -SkylineUnsym :: ~SkylineUnsym() -// Destructor. +std::unique_ptr +SkylineUnsym :: clone() const { - if ( size ) { - int i = size; - RowColumn **p = rowColumns; - while ( i-- ) { - delete *p++; - } - - delete [] rowColumns; - } + return std::make_unique(*this); } + void SkylineUnsym :: toFloatMatrix(FloatMatrix &answer) const { - int start; - - answer.resize(size, size); + answer.resize(this->giveNumberOfRows(), this->giveNumberOfColumns()); answer.zero(); - for ( int j = 1; j <= size; j++ ) { - start = this->giveRowColumn(j)->giveStart(); + for ( int j = 1; j <= this->giveNumberOfColumns(); j++ ) { + int start = this->rowColumns[j-1].giveStart(); for ( int i = start; i <= j; i++ ) { answer.at(i, j) = this->at(i, j); answer.at(j, i) = this->at(j, i); @@ -105,49 +90,38 @@ SkylineUnsym :: toFloatMatrix(FloatMatrix &answer) const double & SkylineUnsym :: at(int i, int j) -// Returns the (i,j) coefficient of the receiver. Not very efficient. - { - // increment version this->version++; if ( i < j ) { - return this->giveRowColumn(j)->atU(i); + return this->rowColumns[j-1].atU(i); } else if ( i > j ) { - return this->giveRowColumn(i)->atL(j); + return this->rowColumns[i-1].atL(j); } else { - return this->giveRowColumn(i)->atDiag(); + return this->rowColumns[i-1].atDiag(); } } + double SkylineUnsym :: at(int i, int j) const -// Returns the (i,j) coefficient of the receiver. Not very efficient. - { if ( i < j ) { - return this->giveRowColumn(j)->atU(i); + return this->rowColumns[j-1].atU(i); } else if ( i > j ) { - return this->giveRowColumn(i)->atL(j); + return this->rowColumns[i-1].atL(j); } else { - return this->giveRowColumn(i)->atDiag(); + return this->rowColumns[i-1].atDiag(); } } int SkylineUnsym :: assemble(const IntArray &loc, const FloatMatrix &mat) -// Assembles the elemental matrix 'k' to the receiver, using 'loc' as a -// location array. The values in k corresponding to a zero coefficient -// in loc are not assembled. -// Warning : k is not supposed to be an instance of DiagonalMatrix. - { - int dim; - // RowColumn* rowColumnJJ ; // 13 November 1996 - not needed anymore + int dim = mat.giveNumberOfRows(); # ifdef DEBUG - dim = mat.giveNumberOfRows(); if ( dim != loc.giveSize() ) { OOFEM_ERROR("dimension of 'k' and 'loc' mismatch"); } @@ -158,9 +132,6 @@ SkylineUnsym :: assemble(const IntArray &loc, const FloatMatrix &mat) // added to make it work for nonlocal model !!!!!!!!!!!!!!!!!!!!!!!!!! // checkSizeTowards(loc) ; - - dim = mat.giveNumberOfRows(); - for ( int j = 1; j <= dim; j++ ) { int jj = loc.at(j); if ( jj ) { @@ -173,7 +144,6 @@ SkylineUnsym :: assemble(const IntArray &loc, const FloatMatrix &mat) } } - // increment version this->version++; return 1; @@ -182,19 +152,11 @@ SkylineUnsym :: assemble(const IntArray &loc, const FloatMatrix &mat) int SkylineUnsym :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) -// Assembles the elemental matrix 'k' to the receiver, using 'loc1' as a -// location array for rows and 'loc2' as a location array for columns. -// The values in 'k' corresponding to a zero coefficient -// in loc are not assembled. -// Warning : k is not supposed to be an instance of DiagonalMatrix. - { - int dim1, dim2; - this->checkSizeTowards(rloc, cloc); - dim1 = mat.giveNumberOfRows(); - dim2 = mat.giveNumberOfColumns(); + int dim1 = rloc.giveSize(); + int dim2 = cloc.giveSize(); for ( int i = 1; i <= dim1; i++ ) { int ii = rloc.at(i); if ( ii ) { @@ -207,83 +169,57 @@ SkylineUnsym :: assemble(const IntArray &rloc, const IntArray &cloc, const Float } } - // increment version this->version++; return 1; } + void SkylineUnsym :: checkSizeTowards(const IntArray &rloc, const IntArray &cloc) -// Increases the number of columns of the receiver if 'rloc, cloc' points to -// out-of-range columns. { - int maxCol, dim1, dim2; + int maxCol = 0; - maxCol = 0; // the largest coefficient in 'loc' - dim1 = rloc.giveSize(); - dim2 = cloc.giveSize(); - - for ( int i = 1; i <= dim1; i++ ) { - maxCol = max( maxCol, rloc.at(i) ); + for ( auto r : rloc ) { + maxCol = max( maxCol, r ); } - for ( int j = 1; j <= dim2; j++ ) { - maxCol = max( maxCol, cloc.at(j) ); + for ( auto c : cloc ) { + maxCol = max( maxCol, c ); } - if ( maxCol > size ) { // enlarge the matrix + if ( maxCol > this->giveNumberOfColumns() ) { growTo(maxCol); } - for ( int i = 1; i <= dim1; i++ ) { - int ii = rloc.at(i); + for ( auto ii : rloc ) { if ( ii ) { - giveRowColumn(ii)->checkSizeTowards(cloc); + rowColumns[ii-1].checkSizeTowards(cloc); } } - for ( int j = 1; j <= dim2; j++ ) { - int jj = cloc.at(j); + for ( auto jj : cloc ) { if ( jj ) { - giveRowColumn(jj)->checkSizeTowards(rloc); + rowColumns[jj-1].checkSizeTowards(rloc); } } } - int SkylineUnsym :: buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s) { // Instanciates the profile of the receiver and initializes all coefficients to zero. // Warning : case diagonal (lumped) matrix to expected. - IntArray loc; int first, nonlocal; Domain *domain = eModel->giveDomain(di); int neq = eModel->giveNumberOfDomainEquations(di, s); int nelem = domain->giveNumberOfElements(); - Element *elem; - //nonlocal = aDomain -> giveAlgorithm() -> useNonlocalStiffness(); nonlocal = eModel->useNonlocalStiffnessOption(); // clear receiver if exist - - if ( size ) { - RowColumn **_p; - int _i; - _i = size; - _p = rowColumns; - while ( _i-- ) { - delete *_p++; - } - - delete [] rowColumns; - rowColumns = NULL; - size = 0; - } - + this->rowColumns.clear(); this->growTo(neq); // from now on, size = MaxIndex // Set up the array with indices of first nonzero elements in each row @@ -293,7 +229,7 @@ SkylineUnsym :: buildInternalStructure(EngngModel *eModel, int di, const Unknown } for ( int n = 1; n <= nelem; n++ ) { - elem = domain->giveElement(n); + auto elem = domain->giveElement(n); //elem -> giveLocationArray (loc) ; if ( !nonlocal ) { @@ -329,7 +265,7 @@ SkylineUnsym :: buildInternalStructure(EngngModel *eModel, int di, const Unknown for ( int i = 1; i <= nbc; ++i ) { ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( domain->giveBc(i) ); - if ( bc != NULL ) { + if ( bc ) { bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s); for ( std :: size_t j = 0; j < r_locs.size(); j++ ) { IntArray &krloc = r_locs [ j ]; @@ -352,16 +288,13 @@ SkylineUnsym :: buildInternalStructure(EngngModel *eModel, int di, const Unknown } - // Enlarge the rowcolumns for ( int i = 1; i <= neq; i++ ) { - this->giveRowColumn(i)->growTo( firstIndex.at(i) ); + this->rowColumns[i-1].growTo( firstIndex.at(i) ); } - // Print out basic information. this->printStatistics(); nRows = nColumns = neq; - // increment version this->version++; return true; @@ -376,7 +309,6 @@ int SkylineUnsym :: setInternalStructure(IntArray &adr1) IntArray mht, firstIndex; int n = adr1.giveSize(); this->growTo(n - 1); - size = n - 1; // check // build first index array mht.resize(n - 1); @@ -390,14 +322,13 @@ int SkylineUnsym :: setInternalStructure(IntArray &adr1) // Enlarge the rowcolumns for ( int i = 1; i <= n - 1; i++ ) { - this->giveRowColumn(i)->growTo( firstIndex.at(i) ); + this->rowColumns[i-1].growTo( firstIndex.at(i) ); } - // Print out basic information. this->printStatistics(); nRows = nColumns = n - 1; - // increment version + this->version++; return true; @@ -407,59 +338,30 @@ int SkylineUnsym :: setInternalStructure(IntArray &adr1) void SkylineUnsym :: checkSizeTowards(const IntArray &loc) -// Increases the number of columns of the receiver if 'loc' points to -// out-of-range columns. { - int dim, maxCol; - - maxCol = 0; // the largest coefficient in 'loc' - dim = loc.giveSize(); - for ( int i = 1; i <= dim; i++ ) { - maxCol = max( maxCol, loc.at(i) ); + int maxCol = 0; // the largest coefficient in 'loc' + for ( auto c: loc ) { + maxCol = max( maxCol, c ); } - if ( maxCol > size ) { // enlarge the matrix + if ( maxCol > (int)this->rowColumns.size() ) { // enlarge the matrix growTo(maxCol); } - for ( int i = 1; i <= dim; i++ ) { - int ii = loc.at(i); + for ( auto ii: loc ) { if ( ii ) { - giveRowColumn(ii)->checkSizeTowards(loc); + this->rowColumns[ii-1].checkSizeTowards(loc); } } } -/* - * int - * SkylineUnsym :: computeNumberNegativeEigenvalue() - * // Compute the number of negative eigenvalue, equivalent to the number of - * // negative diagonal terms. - * - * { - * int j, count; - * - * if (! isFactorized) factorized(); - * - * count = 0; - * for (j=1 ; j<=size ; j++) { - * if (at(j,j) <= 0.) - * count = count + 1; - * } - * return count; - * } - */ SparseMtrx * SkylineUnsym :: factorized() // Returns the receiver in L.D.U factorized form. From Golub & van Loan, // 1rst edition, pp 83-84. - { - RowColumn *rowColumnK, *rowColumnI; FloatArray r, w; - double diag; - int start, startK, startI; #ifdef TIME_REPORT Timer timer; timer.startTimer(); @@ -469,15 +371,15 @@ SkylineUnsym :: factorized() return this; } - if ( !size ) { + if ( this->rowColumns.empty() ) { OOFEM_WARNING("null-sized matrix factorized"); isFactorized = 1; return this; } - for ( int k = 1; k <= size; k++ ) { - rowColumnK = this->giveRowColumn(k); - startK = rowColumnK->giveStart(); + for ( int k = 1; k <= this->giveNumberOfColumns(); k++ ) { + auto &rowColumnK = this->rowColumns[k-1]; + int startK = rowColumnK.giveStart(); // compute vectors r and w r.resize(k - 1); @@ -485,31 +387,31 @@ SkylineUnsym :: factorized() w.resize(k - 1); w.zero(); for ( int p = startK; p < k; p++ ) { - diag = this->giveRowColumn(p)->atDiag(); - r.at(p) = diag * rowColumnK->atU(p); - w.at(p) = diag * rowColumnK->atL(p); + double diag = this->rowColumns[p-1].atDiag(); + r.at(p) = diag * rowColumnK.atU(p); + w.at(p) = diag * rowColumnK.atL(p); } // compute diagonal coefficient of rowColumn k - rowColumnK->atDiag() -= rowColumnK->dot(r, 'R', startK, k - 1); - diag = rowColumnK->atDiag(); + rowColumnK.atDiag() -= rowColumnK.dot(r, 'R', startK, k - 1); + double diag = rowColumnK.atDiag(); // test pivot not too small if ( fabs(diag) < SkylineUnsym_TINY_PIVOT ) { - rowColumnK->atDiag() = diag = SkylineUnsym_TINY_PIVOT; + rowColumnK.atDiag() = diag = SkylineUnsym_TINY_PIVOT; OOFEM_LOG_DEBUG("SkylineUnsym :: factorized: zero pivot %d artificially set to a small value", k); } // compute off-diagonal coefficients of rowColumns i>k - for ( int i = k + 1; i <= size; i++ ) { - rowColumnI = giveRowColumn(i); - startI = rowColumnI->giveStart(); + for ( int i = k + 1; i <= this->giveNumberOfColumns(); i++ ) { + auto &rowColumnI = this->rowColumns[i-1]; + int startI = rowColumnI.giveStart(); if ( startI <= k ) { - start = max(startI, startK); - rowColumnI->atL(k) -= rowColumnI->dot(r, 'R', start, k - 1); - rowColumnI->atL(k) /= diag; - rowColumnI->atU(k) -= rowColumnI->dot(w, 'C', start, k - 1); - rowColumnI->atU(k) /= diag; + int start = max(startI, startK); + rowColumnI.atL(k) -= rowColumnI.dot(r, 'R', start, k - 1); + rowColumnI.atL(k) /= diag; + rowColumnI.atU(k) -= rowColumnI.dot(w, 'C', start, k - 1); + rowColumnI.atU(k) /= diag; } } } @@ -520,7 +422,7 @@ SkylineUnsym :: factorized() timer.stopTimer(); OOFEM_LOG_DEBUG( "SkylineU info: user time consumed by factorization: %.2fs\n", timer.getUtime() ); #endif - // increment version + //this->version++; return this; @@ -530,36 +432,20 @@ SkylineUnsym :: factorized() FloatArray * SkylineUnsym :: backSubstitutionWith(FloatArray &y) const -// Returns the solution x of the system U.x = y , where U is the upper -// half of the receiver. Note : x overwrites y. - { - int start; - double yK, diag; - RowColumn *rowColumnK; - - - // forwardReductionWith - // if (! isFactorized) this -> factorized(); - - if ( !size ) { - return & y; // null size system - } - - if ( y.giveSize() != size ) { + if ( y.giveSize() != this->giveNumberOfColumns() ) { OOFEM_ERROR("size mismatch"); } - for ( int k = 1; k <= size; k++ ) { - rowColumnK = this->giveRowColumn(k); - start = rowColumnK->giveStart(); - y.at(k) -= rowColumnK->dot(y, 'R', start, k - 1); + for ( int k = 1; k <= this->giveNumberOfColumns(); k++ ) { + auto &rowColumnK = this->rowColumns[k-1]; + int start = rowColumnK.giveStart(); + y.at(k) -= rowColumnK.dot(y, 'R', start, k - 1); } // diagonalScaling - /* uprava diagonalniho prvku */ - for ( int k = 1; k <= size; k++ ) { - diag = this->giveRowColumn(k)->atDiag(); + for ( int k = 1; k <= this->giveNumberOfColumns(); k++ ) { + double diag = this->rowColumns[k-1].atDiag(); # ifdef DEBUG if ( fabs(diag) < SkylineUnsym_TINY_PIVOT ) { OOFEM_ERROR("pivot %d is small", k); @@ -570,152 +456,79 @@ SkylineUnsym :: backSubstitutionWith(FloatArray &y) const } - for ( int k = size; k > 0; k-- ) { - rowColumnK = this->giveRowColumn(k); - yK = y.at(k); - start = rowColumnK->giveStart(); + for ( int k = this->giveNumberOfColumns(); k > 0; k-- ) { + auto &rowColumnK = this->rowColumns[k-1]; + double yK = y.at(k); + int start = rowColumnK.giveStart(); for ( int i = start; i < k; i++ ) { - y.at(i) -= rowColumnK->atU(i) * yK; + y.at(i) -= rowColumnK.atU(i) * yK; } } return & y; } -SparseMtrx * -SkylineUnsym :: GiveCopy() const -{ - RowColumn **newRowColumns, *rowColumni; - newRowColumns = new RowColumn * [ size ]; - SkylineUnsym *answer; - - for ( int i = 1; i <= size; i++ ) { - rowColumni = this->giveRowColumn(i); - if ( rowColumni ) { - newRowColumns [ i - 1 ] = rowColumni->GiveCopy(); - } else { - newRowColumns [ i - 1 ] = NULL; - } - } - - answer = new SkylineUnsym(newRowColumns, this->size, this->isFactorized); - return answer; -} void SkylineUnsym :: times(const FloatArray &x, FloatArray &answer) const { - int starti; - RowColumn *rowColumni; - // - // first check sizes - // - if ( this->size != x.giveSize() ) { + if ( this->giveNumberOfColumns() != x.giveSize() ) { OOFEM_ERROR("size mismatch"); } - answer.resize(this->size); + answer.resize(this->giveNumberOfRows()); answer.zero(); - for ( int i = 1; i <= size; i++ ) { - rowColumni = this->giveRowColumn(i); - starti = rowColumni->giveStart(); - answer.at(i) += rowColumni->dot(x, 'R', starti, i - 1); - answer.at(i) += rowColumni->atDiag() * x.at(i); + for ( int i = 1; i <= this->giveNumberOfColumns(); i++ ) { + auto &rowColumni = this->rowColumns[i-1]; + int starti = rowColumni.giveStart(); + answer.at(i) += rowColumni.dot(x, 'R', starti, i - 1); + answer.at(i) += rowColumni.atDiag() * x.at(i); for ( int j = starti; j <= i - 1; j++ ) { - answer.at(j) += rowColumni->atU(j) * x.at(i); + answer.at(j) += rowColumni.atU(j) * x.at(i); } } } + void SkylineUnsym :: times(double x) { - int starti; - RowColumn *rowColumni; - - for ( int i = 1; i <= size; i++ ) { - rowColumni = this->giveRowColumn(i); - starti = rowColumni->giveStart(); + for ( int i = 1; i <= this->giveNumberOfColumns(); i++ ) { + auto &rowColumni = this->rowColumns[i-1]; + int starti = rowColumni.giveStart(); for ( int j = starti; j <= i - 1; j++ ) { - rowColumni->atU(j) *= x; - rowColumni->atL(j) *= x; + rowColumni.atU(j) *= x; + rowColumni.atL(j) *= x; } - rowColumni->atDiag() *= x; + rowColumni.atDiag() *= x; } - // increment version this->version++; } -RowColumn * -SkylineUnsym :: giveRowColumn(int j) const -// Returns the j-th rowColumn of the receiver. Creates it if necessary. - -{ - if ( size < j ) { - // this -> growTo(j) ; - OOFEM_ERROR("size mismatch"); - } - - if ( !rowColumns [ j - 1 ] ) { - rowColumns [ j - 1 ] = new RowColumn(j, j); - } - - return rowColumns [ j - 1 ]; -} - - void SkylineUnsym :: growTo(int n) -// Enlarges the receiver to n columns. { - RowColumn **newRowColumns, **p1, **p2; - int i; - - if ( n == size ) { - return; - } - -# ifdef DEBUG - else if ( n <= size ) { - OOFEM_ERROR("cannot grow from %d to %d", size, n); - } -# endif - - newRowColumns = new RowColumn * [ n ]; - p1 = rowColumns; - p2 = newRowColumns; - - i = size; - while ( i-- ) { - * p2++ = * p1++; + this->rowColumns.reserve(n); + for (int i = 1; i <= n; ++i ) { + this->rowColumns.emplace_back(i); } - - i = n - size; - while ( i-- ) { - * p2++ = NULL; - } - - if ( rowColumns ) { - delete [] rowColumns; - } - - rowColumns = newRowColumns; - size = n; + this->nRows = n; + this->nColumns = n; } void SkylineUnsym :: printStatistics() const { int nelem = 0; - for ( int i = 1; i <= size; i++ ) { - nelem += this->giveRowColumn(i)->giveSize(); + for ( auto &rc : this->rowColumns ) { + nelem += rc.giveSize(); } - OOFEM_LOG_INFO("Skylineu info: neq is %d, nwk is %d\n", size, nelem); + OOFEM_LOG_INFO("Skylineu info: neq is %d, nwk is %d\n", this->giveNumberOfRows(), nelem); } @@ -737,87 +550,45 @@ SkylineUnsym :: writeToFile(const char *fname) const void SkylineUnsym :: printYourself() const -// Prints the receiver. { FloatMatrix copy; - this->toFloatMatrix(copy); copy.printYourself(); + for ( auto &rc : this->rowColumns ) { + rc.printYourself(); + } } void SkylineUnsym :: zero() { - // Returns the receiver with all coefficients set to zero. - for ( int j = 1; j <= size; j++ ) { - this->giveRowColumn(j)->zero(); + for ( auto &rc : this->rowColumns ) { + rc.zero(); } isFactorized = false; - // increment version this->version++; } -/* - * SkylineSym* SkylineUnsym :: giveSymmetricPart() - * { - * int i, j, rowcolsize, colsize; - * SkylineSym* answer = new SkylineSym(); - * answer -> growTo(size); - * for (i=1; i<=size; i++){ - * rowcolsize = rowColumns[i-1] -> giveSize(); - * colsize = (rowcolsize+1)/2; - * answer -> giveColumn(i) -> growTo(colsize); - * answer->at(i,i) = at(i,i); - * j=i+1-colsize; - * while(jat(j,i) = (at(i,j)+at(j,i))/2.; - * j++; - * } - * } - * return answer; - * } - * - * - * int SkylineUnsym :: computeNumberNegativePivotsOfSymPart() - * { - * SkylineSym* SymPart = giveSymmetricPart(); - * int answer = SymPart -> computeNumberNegativeEigenvalue(); - * delete SymPart; - * return answer; - * } - * - */ - -SkylineUnsym :: SkylineUnsym(RowColumn **newRowCol, int newSize, int isFact) : SparseMtrx(newSize, newSize) -{ - size = newSize; - rowColumns = newRowCol; - isFactorized = isFact; -} void SkylineUnsym :: timesT(const FloatArray &x, FloatArray &answer) const { - int starti; - RowColumn *rowColumni; - - // first check sizes - if ( this->size != x.giveSize() ) { + if ( this->giveNumberOfRows() != x.giveSize() ) { OOFEM_ERROR("size mismatch"); } - answer.resize(this->size); + answer.resize(this->giveNumberOfColumns()); answer.zero(); - for ( int i = 1; i <= size; i++ ) { - rowColumni = this->giveRowColumn(i); - starti = rowColumni->giveStart(); - answer.at(i) += rowColumni->dot(x, 'C', starti, i - 1); - answer.at(i) += rowColumni->atDiag() * x.at(i); + for ( int i = 1; i <= this->giveNumberOfRows(); i++ ) { + auto &rowColumni = this->rowColumns[i-1]; + int starti = rowColumni.giveStart(); + answer.at(i) += rowColumni.dot(x, 'C', starti, i - 1); + answer.at(i) += rowColumni.atDiag() * x.at(i); for ( int j = starti; j <= i - 1; j++ ) { - answer.at(j) += rowColumni->atL(j) * x.at(i); + answer.at(j) += rowColumni.atL(j) * x.at(i); } } } diff --git a/src/oofemlib/skylineu.h b/src/oofemlib/skylineu.h index 55b65f42b..81be47476 100644 --- a/src/oofemlib/skylineu.h +++ b/src/oofemlib/skylineu.h @@ -38,6 +38,9 @@ #include "sparsemtrx.h" #include "rowcol.h" +#define _IFT_SkylineUnsym_Name "skylineu" + + namespace oofem { /// "zero" pivot for SkylineUnsym class #define SkylineUnsym_TINY_PIVOT 1.e-30 @@ -52,9 +55,7 @@ class OOFEM_EXPORT SkylineUnsym : public SparseMtrx { protected: /// Row column segments - RowColumn **rowColumns; - /// Size of receiver - int size; + std::vector rowColumns; /// Factorization flag int isFactorized; @@ -64,45 +65,40 @@ class OOFEM_EXPORT SkylineUnsym : public SparseMtrx * @param n Size of matrix * @see buildInternalStructure */ - SkylineUnsym(int n); - /** - * Constructor. Before any operation an internal profile must be built. - * @see buildInternalStructure - */ - SkylineUnsym(); + SkylineUnsym(int n=0); + SkylineUnsym(const SkylineUnsym &s); /// Destructor - virtual ~SkylineUnsym(); + virtual ~SkylineUnsym() {} // Overloaded methods: - virtual SparseMtrx *GiveCopy() const; - virtual void times(const FloatArray &x, FloatArray &answer) const; - virtual void timesT(const FloatArray &x, FloatArray &answer) const; - virtual void times(double x); - virtual int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &s); + std::unique_ptr clone() const override; + void times(const FloatArray &x, FloatArray &answer) const override; + void timesT(const FloatArray &x, FloatArray &answer) const override; + void times(double x) override; + int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &s) override; int setInternalStructure(IntArray &a); - virtual int assemble(const IntArray &loc, const FloatMatrix &mat); - virtual int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat); - virtual bool canBeFactorized() const { return true; } - virtual SparseMtrx *factorized(); - virtual FloatArray *backSubstitutionWith(FloatArray &) const; - virtual void zero(); - virtual double &at(int i, int j); - virtual double at(int i, int j) const; - virtual void toFloatMatrix(FloatMatrix &answer) const; - virtual void printYourself() const; - virtual void printStatistics() const; - virtual void writeToFile(const char *fname) const; - virtual SparseMtrxType giveType() const { return SMT_SkylineU; } - virtual bool isAsymmetric() const { return true; } - virtual const char *giveClassName() const { return "SkylineU"; } + int assemble(const IntArray &loc, const FloatMatrix &mat) override; + int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) override; + bool canBeFactorized() const override { return true; } + SparseMtrx *factorized() override; + FloatArray *backSubstitutionWith(FloatArray &) const override; + void zero() override; + double &at(int i, int j) override; + double at(int i, int j) const override; + void toFloatMatrix(FloatMatrix &answer) const override; + void printYourself() const override; + void printStatistics() const override; + void writeToFile(const char *fname) const override; + SparseMtrxType giveType() const override { return SMT_SkylineU; } + bool isAsymmetric() const override { return true; } + const char *giveClassName() const override { return "SkylineU"; } protected: void checkSizeTowards(const IntArray &); void checkSizeTowards(const IntArray &rloc, const IntArray &cloc); - RowColumn *giveRowColumn(int j) const; void growTo(int); - SkylineUnsym(RowColumn * *, int, int); + SkylineUnsym(int n, std::vector data, bool isFact); }; } // end namespace oofem #endif // skylineu_h diff --git a/src/oofemlib/slavedof.C b/src/oofemlib/slavedof.C index 21002a13f..abd95a05c 100644 --- a/src/oofemlib/slavedof.C +++ b/src/oofemlib/slavedof.C @@ -212,14 +212,12 @@ int SlaveDof :: __givePrescribedEquationNumber() return 0; } -contextIOResultType SlaveDof :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void SlaveDof :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = Dof :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + Dof :: saveContext(stream, mode); if ( mode & CM_Definition ) { + contextIOResultType iores; if ( !stream.write(countOfMasterDofs) ) { THROW_CIOERR(CIO_IOERR); } @@ -249,18 +247,14 @@ contextIOResultType SlaveDof :: saveContext(DataStream &stream, ContextMode mode THROW_CIOERR(iores); } } // if ( mode & CM_Definition ) - - return CIO_OK; } -contextIOResultType SlaveDof :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void SlaveDof :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = Dof :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + Dof :: restoreContext(stream, mode); if ( mode & CM_Definition ) { + contextIOResultType iores; if ( !stream.read(countOfMasterDofs) ) { THROW_CIOERR(CIO_IOERR); } @@ -286,8 +280,6 @@ contextIOResultType SlaveDof :: restoreContext(DataStream &stream, ContextMode m THROW_CIOERR(iores); } } // if ( mode & CM_Definition ) - - return CIO_OK; } diff --git a/src/oofemlib/slavedof.h b/src/oofemlib/slavedof.h index 47fdb583d..b28352152 100644 --- a/src/oofemlib/slavedof.h +++ b/src/oofemlib/slavedof.h @@ -68,16 +68,16 @@ class OOFEM_EXPORT SlaveDof : public Dof /// Destructor. virtual ~SlaveDof(void) { } - virtual dofType giveDofType() { return DT_slave; } + dofType giveDofType() override { return DT_slave; } void initialize(const IntArray &masterNodes, const IntArray &mstrDofID, const FloatArray &mstrContribution); - virtual int giveNumberOfPrimaryMasterDofs(); - virtual void giveMasterDofManArray(IntArray &answer); - virtual void giveUnknowns(FloatArray &masterUnknowns, ValueModeType mode, TimeStep *tStep); - virtual void giveUnknowns(FloatArray &masterUnknowns, PrimaryField &field, ValueModeType mode, TimeStep *tStep); - virtual void computeDofTransformation(FloatArray &primaryMasterContribs); - virtual void giveEquationNumbers(IntArray &masterEqNumbers, const UnknownNumberingScheme &s); - virtual void giveDofIDs(IntArray &masterDofIDs); + int giveNumberOfPrimaryMasterDofs() override; + void giveMasterDofManArray(IntArray &answer) override; + void giveUnknowns(FloatArray &masterUnknowns, ValueModeType mode, TimeStep *tStep) override; + void giveUnknowns(FloatArray &masterUnknowns, PrimaryField &field, ValueModeType mode, TimeStep *tStep) override; + void computeDofTransformation(FloatArray &primaryMasterContribs) override; + void giveEquationNumbers(IntArray &masterEqNumbers, const UnknownNumberingScheme &s) override; + void giveDofIDs(IntArray &masterDofIDs) override; /** * Returns the value of the unknown associated with the receiver at given time step. @@ -90,8 +90,8 @@ class OOFEM_EXPORT SlaveDof : public Dof * standard method for unknown query returns the corresponding master DOF value. * @see MasterDof::giveUnknown */ - virtual double giveUnknown(ValueModeType mode, TimeStep *tStep); - virtual double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep); + double giveUnknown(ValueModeType mode, TimeStep *tStep) override; + double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep) override; /** * Returns equation number corresponding to receiver. @@ -100,7 +100,7 @@ class OOFEM_EXPORT SlaveDof : public Dof * contributing to several master dofs (displacement to displacement and rotations in master). * @return Prints error message and exits. */ - virtual int __giveEquationNumber() const; + int __giveEquationNumber() const override; /** * Returns equation number corresponding to receiver. * Rigid Arm Slave have equation number undefined. @@ -108,41 +108,41 @@ class OOFEM_EXPORT SlaveDof : public Dof * contributing to several master dofs (displacement to displacement and rotations in master). * @return Prints error message and exits. */ - virtual int __givePrescribedEquationNumber(); + int __givePrescribedEquationNumber() override; /** * Asks new equation number. Empty function (master is assumed to receive same message). */ - virtual int askNewEquationNumber(TimeStep *tStep) { return 1; } + int askNewEquationNumber(TimeStep *tStep) override { return 1; } /** * Returns boundary condition of dof if it is prescribed. * HangingDof can not be subjected to BC, it is only mapping to master * @return NULL if no BC applied, otherwise pointer to corresponding BC. */ - virtual bool hasBc(TimeStep *tStep) { return false; } + bool hasBc(TimeStep *tStep) override { return false; } /** * Returns initial condition of dof if it is prescribed. * HangingDof can not be subjected to IC, it is only mapping to master * @see MasterDof::hasIc */ - virtual bool hasIc() { return false; } + bool hasIc() override { return false; } /** * RigidArmSlaveDof can not be subjected to IC - it is only mapping to master. * @see MasterDof::hasIc */ - virtual bool hasIcOn(ValueModeType) { return false; } + bool hasIcOn(ValueModeType) override { return false; } - virtual int giveBcId() { return 0; } - virtual int giveIcId() { return 0; } + int giveBcId() override { return 0; } + int giveIcId() override { return 0; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual const char *giveClassName() const { return "SlaveDof"; } + const char *giveClassName() const override { return "SlaveDof"; } - virtual void updateLocalNumbering(EntityRenumberingFunctor &f); + void updateLocalNumbering(EntityRenumberingFunctor &f) override; protected: inline Dof *giveMasterDof(int i); diff --git a/src/oofemlib/slavenode.C b/src/oofemlib/slavenode.C index 858eda8ac..30b05590b 100644 --- a/src/oofemlib/slavenode.C +++ b/src/oofemlib/slavenode.C @@ -42,9 +42,9 @@ namespace oofem { REGISTER_DofManager(SlaveNode); -IRResultType SlaveNode :: initializeFrom(InputRecord *ir) +void SlaveNode :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Node :: initializeFrom(ir); IR_GIVE_FIELD(ir, masterDofManagers, _IFT_SlaveNode_masterDofManagers); IR_GIVE_OPTIONAL_FIELD(ir, masterWeights, _IFT_SlaveNode_weights); @@ -53,10 +53,8 @@ IRResultType SlaveNode :: initializeFrom(InputRecord *ir) masterWeights.resize( masterDofManagers.giveSize() ); masterWeights.add( 1 / ( double ) masterDofManagers.giveSize() ); } else if ( masterDofManagers.giveSize() != masterWeights.giveSize() ) { - OOFEM_WARNING("master dof managers and weights size mismatch."); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_SlaveNode_weights, "master dof managers and weights size mismatch."); } - return Node :: initializeFrom(ir); } diff --git a/src/oofemlib/slavenode.h b/src/oofemlib/slavenode.h index e70e66a83..76b814789 100644 --- a/src/oofemlib/slavenode.h +++ b/src/oofemlib/slavenode.h @@ -72,13 +72,13 @@ class OOFEM_EXPORT SlaveNode : public Node /// Destructor. virtual ~SlaveNode(void) { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void postInitialize(); - virtual bool isDofTypeCompatible(dofType type) const { return ( type == DT_master || type == DT_slave ); } - virtual void updateLocalNumbering(EntityRenumberingFunctor &f); + void initializeFrom(InputRecord &ir) override; + void postInitialize() override; + bool isDofTypeCompatible(dofType type) const override { return ( type == DT_master || type == DT_slave ); } + void updateLocalNumbering(EntityRenumberingFunctor &f) override; - virtual const char *giveClassName() const { return "SlaveNode"; } - virtual const char *giveInputRecordName() const { return _IFT_SlaveNode_Name; } + const char *giveClassName() const override { return "SlaveNode"; } + const char *giveInputRecordName() const override { return _IFT_SlaveNode_Name; } }; } // end namespace oofem #endif // slavenode_h diff --git a/src/oofemlib/slepcsolver.C b/src/oofemlib/slepcsolver.C index 14adf8ccb..db8ffecdd 100644 --- a/src/oofemlib/slepcsolver.C +++ b/src/oofemlib/slepcsolver.C @@ -33,23 +33,28 @@ */ #include "slepcsolver.h" - -#define TIME_REPORT #include "petscsparsemtrx.h" #include "engngm.h" #include "floatarray.h" #include "verbose.h" #include "domain.h" +#include "classfactory.h" + +#define TIME_REPORT #ifdef TIME_REPORT #include "timer.h" #endif namespace oofem { -SLEPcSolver :: SLEPcSolver(Domain *d, EngngModel *m) : SparseGeneralEigenValueSystemNM(d, m) +REGISTER_GeneralizedEigenValueSolver(SLEPcSolver, GES_SLEPc); + + +SLEPcSolver :: SLEPcSolver(Domain *d, EngngModel *m) : SparseGeneralEigenValueSystemNM(d, m), + //A(nullptr), + //B(nullptr), + epsInit(false) { - A = B = NULL; - epsInit = false; } @@ -75,8 +80,8 @@ SLEPcSolver :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, FloatMatri OOFEM_ERROR("matrices size mismatch"); } - A = dynamic_cast< PetscSparseMtrx * >(&a); - B = dynamic_cast< PetscSparseMtrx * >(&b); + PetscSparseMtrx* A = dynamic_cast< PetscSparseMtrx * >(&a); + PetscSparseMtrx* B = dynamic_cast< PetscSparseMtrx * >(&b); if ( !A || !B ) { OOFEM_ERROR("PetscSparseMtrx Expected"); @@ -168,7 +173,7 @@ SLEPcSolver :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, FloatMatri FloatArray Vr_loc; for ( int i = 0; i < nconv && i < nroot; i++ ) { - ierr = EPSGetEigenpair(eps, nconv - i - 1, & kr, PETSC_NULL, Vr, PETSC_NULL); + ierr = EPSGetEigenpair(eps, i, & kr, PETSC_NULL, Vr, PETSC_NULL); CHKERRQ(ierr); //Store the eigenvalue diff --git a/src/oofemlib/slepcsolver.h b/src/oofemlib/slepcsolver.h index 7822cdbdd..b787a70ce 100644 --- a/src/oofemlib/slepcsolver.h +++ b/src/oofemlib/slepcsolver.h @@ -41,6 +41,8 @@ #include +#define _IFT_SLEPcSolver_Name "slepc" + namespace oofem { class Domain; class EngngModel; @@ -50,8 +52,8 @@ class PetscSparseMtrx; class OOFEM_EXPORT SLEPcSolver : public SparseGeneralEigenValueSystemNM { private: - PetscSparseMtrx *A; - PetscSparseMtrx *B; + //PetscSparseMtrx *A; + //PetscSparseMtrx *B; /// Eigenvalue solver context. EPS eps; /// Flag if context initialized. @@ -61,8 +63,8 @@ class OOFEM_EXPORT SLEPcSolver : public SparseGeneralEigenValueSystemNM SLEPcSolver(Domain * d, EngngModel * m); virtual ~SLEPcSolver(); - virtual NM_Status solve(SparseMtrx &a, SparseMtrx &b, FloatArray &v, FloatMatrix &x, double rtol, int nroot); - virtual const char *giveClassName() const { return "SLEPcSolver"; } + NM_Status solve(SparseMtrx &a, SparseMtrx &b, FloatArray &v, FloatMatrix &x, double rtol, int nroot) override; + const char *giveClassName() const override { return "SLEPcSolver"; } }; } // end namespace oofem #endif // slepcsolver_h diff --git a/src/oofemlib/sloangraph.C b/src/oofemlib/sloangraph.C index e554179d8..b10446e89 100644 --- a/src/oofemlib/sloangraph.C +++ b/src/oofemlib/sloangraph.C @@ -101,6 +101,7 @@ void SloanGraph :: initialize() dman2map.insert({bc->giveInternalDofManager(j), count}); } } + this->numberOfNodes = count; IntArray connections; for ( auto &elem : domain->giveElements() ) { @@ -196,7 +197,7 @@ SloanGraph :: findPeripheralNodes() } // initial spine - Spine.reset( new SloanLevelStructure(this, InitialRoot) ); + Spine = std::make_unique(this, InitialRoot); this->startNode = InitialRoot; int CurrentDiameter = Spine->giveDepth(); @@ -433,7 +434,7 @@ SloanGraph :: assignNewNumbers() } #ifdef MDC - if ( labeledNodes == domain->giveNumberOfDofManagers() ) { + if ( labeledNodes == this->numberOfNodes ) { break; } diff --git a/src/oofemlib/sloangraph.h b/src/oofemlib/sloangraph.h index 64944bf53..ea61c0255 100644 --- a/src/oofemlib/sloangraph.h +++ b/src/oofemlib/sloangraph.h @@ -87,6 +87,8 @@ class OOFEM_EXPORT SloanGraph std::vector< SloanGraphNode >nodes; /// List of dof managers corresponding to nodes. std::vector< DofManager* >dmans; + /// number of graph nodes (=numberOfNodes+numberOfElementInternalNodes) + int numberOfNodes; /// Start peripheral node. int startNode; /// End peripheral node. @@ -133,6 +135,7 @@ class OOFEM_EXPORT SloanGraph /// Finds the peripheral nodes (rooted in optimal start node) according to receiver quality and current weights. void findPeripheralNodes(); + int getNumberOfNodes() {return numberOfNodes;} int computeTrueDiameter(); int findBestRoot(); int giveFullProfileSize(); diff --git a/src/oofemlib/sloanlevelstruct.C b/src/oofemlib/sloanlevelstruct.C index 3640ae3b7..132a08a7b 100644 --- a/src/oofemlib/sloanlevelstruct.C +++ b/src/oofemlib/sloanlevelstruct.C @@ -62,7 +62,7 @@ SloanLevelStructure :: formYourself(int limitWidth) return 1; } - int nnodes = Graph->giveDomain()->giveNumberOfDofManagers(); + int nnodes = Graph->getNumberOfNodes(); IntArray nodalStatuses(nnodes); IntArray Level = {Root}; diff --git a/src/oofemlib/smoothednodalintvarfield.C b/src/oofemlib/smoothednodalintvarfield.C index 917dac979..e438455b8 100644 --- a/src/oofemlib/smoothednodalintvarfield.C +++ b/src/oofemlib/smoothednodalintvarfield.C @@ -49,12 +49,7 @@ SmoothedNodalInternalVariableField :: SmoothedNodalInternalVariableField(Interna this->domain = d; } -SmoothedNodalInternalVariableField :: ~SmoothedNodalInternalVariableField() -{ - if ( smoother ) { - delete smoother; - } -} +SmoothedNodalInternalVariableField :: ~SmoothedNodalInternalVariableField() { } int SmoothedNodalInternalVariableField :: evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) @@ -99,25 +94,19 @@ SmoothedNodalInternalVariableField :: evaluateAt(FloatArray &answer, const Float int SmoothedNodalInternalVariableField :: evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) { - if ( dman->hasCoordinates() ) { - const FloatArray *val; - int result = this->smoother->giveNodalVector( val, dman->giveNumber() ); - answer = * val; - return ( result == 1 ); - } else { - return 1; // failed -> dman without coordinates - } + const FloatArray *val; + int result = this->smoother->giveNodalVector( val, dman->giveNumber() ); + answer = * val; + return ( result == 1 ); } -contextIOResultType -SmoothedNodalInternalVariableField :: saveContext(DataStream &stream, ContextMode mode) +void +SmoothedNodalInternalVariableField :: saveContext(DataStream &stream) { - return CIO_OK; } -contextIOResultType -SmoothedNodalInternalVariableField :: restoreContext(DataStream &stream, ContextMode mode) +void +SmoothedNodalInternalVariableField :: restoreContext(DataStream &stream) { - return CIO_OK; } } // end namespace oofem diff --git a/src/oofemlib/smoothednodalintvarfield.h b/src/oofemlib/smoothednodalintvarfield.h index 225dddcbe..f10a38cd1 100644 --- a/src/oofemlib/smoothednodalintvarfield.h +++ b/src/oofemlib/smoothednodalintvarfield.h @@ -51,7 +51,7 @@ class OOFEM_EXPORT SmoothedNodalInternalVariableField : public Field /// Smoother type NodalRecoveryModel :: NodalRecoveryModelType stype; /// Smoother - NodalRecoveryModel *smoother; + std::unique_ptr smoother; /// InternalStateType. InternalStateType istType; /// Source domain. @@ -68,13 +68,13 @@ class OOFEM_EXPORT SmoothedNodalInternalVariableField : public Field SmoothedNodalInternalVariableField(InternalStateType ist, FieldType b, NodalRecoveryModel :: NodalRecoveryModelType st, Domain * d); virtual ~SmoothedNodalInternalVariableField(); - virtual int evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep); - virtual int evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep); + int evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) override; + int evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) override; InternalStateType giveInternalType() { return istType; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode); - virtual const char *giveClassName() const { return "SmoothedNodalInternalVariableField"; } + void saveContext(DataStream &stream) override; + void restoreContext(DataStream &stream) override; + const char *giveClassName() const override { return "SmoothedNodalInternalVariableField"; } }; } // end namespace oofem #endif // smoothednodalintvarfieldintvarfield_h diff --git a/src/oofemlib/solutionbasedshapefunction.C b/src/oofemlib/solutionbasedshapefunction.C index 947f3953c..644afaf1e 100644 --- a/src/oofemlib/solutionbasedshapefunction.C +++ b/src/oofemlib/solutionbasedshapefunction.C @@ -61,25 +61,18 @@ void logDataMsg(const char *c, T myArray, const char *c2) { REGISTER_BoundaryCondition(SolutionbasedShapeFunction) -SolutionbasedShapeFunction :: SolutionbasedShapeFunction(int n, Domain *d) : ActiveBoundaryCondition(n, d) -{ - isLoaded = false; - order = 8; - TOL = 1e-5; - bigNorm = 0.0; - - // TODO Auto-generated constructor stub -} +SolutionbasedShapeFunction :: SolutionbasedShapeFunction(int n, Domain *d) : ActiveBoundaryCondition(n, d), + order(8), + TOL(1e-5), + isLoaded(false), + bigNorm(0.0) +{} -SolutionbasedShapeFunction :: ~SolutionbasedShapeFunction() -{ - // TODO Auto-generated destructor stub -} -IRResultType -SolutionbasedShapeFunction :: initializeFrom(InputRecord *ir) +void +SolutionbasedShapeFunction :: initializeFrom(InputRecord &ir) { - IRResultType result; + ActiveBoundaryCondition :: initializeFrom(ir); // Load problem file this->filename = ""; @@ -108,8 +101,6 @@ SolutionbasedShapeFunction :: initializeFrom(InputRecord *ir) } init(); - - return ActiveBoundaryCondition :: initializeFrom(ir); } DofManager * @@ -134,8 +125,8 @@ SolutionbasedShapeFunction :: init() { Node *n1 = this->giveDomain()->giveNode(1); - maxCoord = * n1->giveCoordinates(); - minCoord = * n1->giveCoordinates(); + maxCoord = n1->giveCoordinates(); + minCoord = n1->giveCoordinates(); for ( auto &n :this->giveDomain()->giveDofManagers() ) { for ( int j = 1; j <= maxCoord.giveSize(); j++ ) { @@ -146,7 +137,7 @@ SolutionbasedShapeFunction :: init() } void -SolutionbasedShapeFunction :: computeCorrectionFactors(modeStruct &myMode, IntArray *Dofs, double *am, double *ap) +SolutionbasedShapeFunction :: computeCorrectionFactors(modeStruct &myMode, IntArray &Dofs, double &am, double &ap) { /* * *Compute c0, cp, cm, Bp, Bm, Ap and Am @@ -154,21 +145,21 @@ SolutionbasedShapeFunction :: computeCorrectionFactors(modeStruct &myMode, IntAr double A0p = 0.0, App = 0.0, A0m = 0.0, Amm = 0.0, Bp = 0.0, Bm = 0.0, c0 = 0.0, cp = 0.0, cm = 0.0; - EngngModel *model = myMode.myEngngModel; - Set *mySet = model->giveDomain(1)->giveSet(externalSet); + EngngModel &model = *myMode.myEngngModel; + Set *mySet = model.giveDomain(1)->giveSet(externalSet); IntArray BoundaryList = mySet->giveBoundaryList(); for ( int i = 0; i < BoundaryList.giveSize() / 2; i++ ) { - int ElementID = BoundaryList(2 * i); - int Boundary = BoundaryList(2 * i + 1); + int ElementID = BoundaryList[2 * i]; + int Boundary = BoundaryList[2 * i + 1]; - Element *thisElement = model->giveDomain(1)->giveElement(ElementID); + Element *thisElement = model.giveDomain(1)->giveElement(ElementID); FEInterpolation *geoInterpolation = thisElement->giveInterpolation(); - IntArray bnodes, zNodes, pNodes, mNodes; + IntArray zNodes, pNodes, mNodes; FloatMatrix nodeValues; - geoInterpolation->boundaryGiveNodes(bnodes, Boundary); + auto bnodes = geoInterpolation->boundaryGiveNodes(Boundary); nodeValues.resize( this->dofs.giveSize(), bnodes.giveSize() ); nodeValues.zero(); @@ -178,7 +169,7 @@ SolutionbasedShapeFunction :: computeCorrectionFactors(modeStruct &myMode, IntAr std :: unique_ptr< IntegrationRule >iRule(geoInterpolation->giveBoundaryIntegrationRule(order, Boundary)); - for ( GaussPoint *gp: *iRule ) { + for ( auto &gp: *iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); FloatArray gcoords, normal, N; FloatArray Phi; @@ -189,22 +180,16 @@ SolutionbasedShapeFunction :: computeCorrectionFactors(modeStruct &myMode, IntAr geoInterpolation->boundaryEvalN( N, Boundary, lcoords, FEIElementGeometryWrapper(thisElement) ); geoInterpolation->boundaryLocal2Global( gcoords, Boundary, lcoords, FEIElementGeometryWrapper(thisElement) ); - FloatArray pPhi, mPhi, zPhi; - pPhi.resize( Dofs->giveSize() ); - pPhi.zero(); - mPhi.resize( Dofs->giveSize() ); - mPhi.zero(); - zPhi.resize( Dofs->giveSize() ); - zPhi.zero(); + FloatArray pPhi(Dofs.giveSize()), mPhi(Dofs.giveSize()), zPhi(Dofs.giveSize()); // Build phi (analytical averaging, not projected onto the mesh) - computeBaseFunctionValueAt(Phi, gcoords, * Dofs, * myMode.myEngngModel); + computeBaseFunctionValueAt(Phi, gcoords, Dofs, *myMode.myEngngModel); // Build zPhi for this DofID for ( int l = 1; l <= zNodes.giveSize(); l++ ) { int nodeID = zNodes.at(l); for ( int m = 1; m <= this->dofs.giveSize(); m++ ) { - zPhi.at(m) = zPhi.at(m) + N.at(nodeID) * nodeValues.at(m, nodeID); + zPhi.at(m) += N.at(nodeID) * nodeValues.at(m, nodeID); } } @@ -213,7 +198,7 @@ SolutionbasedShapeFunction :: computeCorrectionFactors(modeStruct &myMode, IntAr for ( int l = 1; l <= pNodes.giveSize(); l++ ) { int nodeID = pNodes.at(l); for ( int m = 1; m <= this->dofs.giveSize(); m++ ) { - pPhi.at(m) = pPhi.at(m) + N.at(nodeID) * nodeValues.at(m, nodeID); + pPhi.at(m) += N.at(nodeID) * nodeValues.at(m, nodeID); } } @@ -221,26 +206,26 @@ SolutionbasedShapeFunction :: computeCorrectionFactors(modeStruct &myMode, IntAr for ( int l = 1; l <= mNodes.giveSize(); l++ ) { int nodeID = mNodes.at(l); for ( int m = 1; m <= this->dofs.giveSize(); m++ ) { - mPhi.at(m) = mPhi.at(m) + N.at(nodeID) * nodeValues.at(m, nodeID); + mPhi.at(m) += N.at(nodeID) * nodeValues.at(m, nodeID); } } - c0 = c0 + zPhi.dotProduct(normal, 3) * detJ; - cp = cp + pPhi.dotProduct(normal, 3) * detJ; - cm = cm + mPhi.dotProduct(normal, 3) * detJ; + c0 += zPhi.dotProduct(normal, 3) * detJ; + cp += pPhi.dotProduct(normal, 3) * detJ; + cm += mPhi.dotProduct(normal, 3) * detJ; - App = App + pPhi.dotProduct(pPhi, 3) * detJ; - Amm = Amm + mPhi.dotProduct(mPhi, 3) * detJ; - A0p = A0p + zPhi.dotProduct(pPhi, 3) * detJ; - A0m = A0m + zPhi.dotProduct(mPhi, 3) * detJ; + App += pPhi.dotProduct(pPhi, 3) * detJ; + Amm += mPhi.dotProduct(mPhi, 3) * detJ; + A0p += zPhi.dotProduct(pPhi, 3) * detJ; + A0m += zPhi.dotProduct(mPhi, 3) * detJ; - Bp = Bp + Phi.dotProduct(pPhi, 3) * detJ; - Bm = Bm + Phi.dotProduct(mPhi, 3) * detJ; + Bp += Phi.dotProduct(pPhi, 3) * detJ; + Bm += Phi.dotProduct(mPhi, 3) * detJ; } } - * am = -( A0m * cp * cp - Bm * cp * cp - A0p * cm * cp + App * c0 * cm + Bp * cm * cp ) / ( App * cm * cm + Amm * cp * cp ); - * ap = -( A0p * cm * cm - Bp * cm * cm - A0m * cm * cp + Amm * c0 * cp + Bm * cm * cp ) / ( App * cm * cm + Amm * cp * cp ); + am = -( A0m * cp * cp - Bm * cp * cp - A0p * cm * cp + App * c0 * cm + Bp * cm * cp ) / ( App * cm * cm + Amm * cp * cp ); + ap = -( A0p * cm * cm - Bp * cm * cm - A0m * cm * cp + Amm * c0 * cp + Bm * cm * cp ) / ( App * cm * cm + Amm * cp * cp ); } void @@ -257,7 +242,7 @@ SolutionbasedShapeFunction :: splitBoundaryNodeIDs(modeStruct &mode, Element &e, bool isPlus = false; bool isMinus = false; - whichBoundary(* dman->giveCoordinates(), isPlus, isMinus, isZero); + whichBoundary(dman->giveCoordinates(), isPlus, isMinus, isZero); if ( isZero ) { zList.insertSorted(j); @@ -269,15 +254,15 @@ SolutionbasedShapeFunction :: splitBoundaryNodeIDs(modeStruct &mode, Element &e, // Find global DofManager and fetch nodal values for ( size_t k = 0; k < mode.SurfaceData.size(); k++ ) { - if ( mode.SurfaceData.at(k)->DofMan == dman ) { + if ( mode.SurfaceData[k].DofMan == dman ) { int IndexOfDofIDItem = 0; for ( int l = 1; l <= dofs.giveSize(); l++ ) { - if ( dofs.at(l) == mode.SurfaceData.at(k)->DofID ) { + if ( dofs.at(l) == mode.SurfaceData[k].DofID ) { IndexOfDofIDItem = l; break; } } - nodeValues.at(IndexOfDofIDItem, j) = mode.SurfaceData.at(k)->value; + nodeValues.at(IndexOfDofIDItem, j) = mode.SurfaceData[k].value; } } } @@ -320,19 +305,19 @@ SolutionbasedShapeFunction :: computeDofTransformation(ActiveDof *dof, FloatArra IntArray dofIDs = {dof->giveDofID()}; bool isPlus, isMinus, isZero, found; - whichBoundary(* dof->giveDofManager()->giveCoordinates(), isPlus, isMinus, isZero); + whichBoundary(dof->giveDofManager()->giveCoordinates(), isPlus, isMinus, isZero); - for ( int i = 1; i <= this->giveDomain()->giveNumberOfSpatialDimensions(); i++ ) { + for ( int i = 0; i < this->giveDomain()->giveNumberOfSpatialDimensions(); i++ ) { double factor = 1.0; found = false; - modeStruct *ms = modes.at(i - 1); - for ( size_t j = 0; j < ms->SurfaceData.size(); j++ ) { - SurfaceDataStruct *sd = ms->SurfaceData.at(j); - if ( sd->DofMan->giveNumber() == dof->giveDofManager()->giveNumber() ) { - if ( sd->DofID == dof->giveDofID() ) { + modeStruct &ms = modes[i]; + for ( size_t j = 0; j < ms.SurfaceData.size(); j++ ) { + SurfaceDataStruct &sd = ms.SurfaceData[j]; + if ( sd.DofMan->giveNumber() == dof->giveDofManager()->giveNumber() ) { + if ( sd.DofID == dof->giveDofID() ) { values.resize(1); - values.at(1) = sd->value; + values.at(1) = sd.value; found = true; break; } @@ -347,11 +332,11 @@ SolutionbasedShapeFunction :: computeDofTransformation(ActiveDof *dof, FloatArra //giveValueAtPoint(values2, *dof->giveDofManager()->giveCoordinates(), dofIDs, *modes.at(i-1)->myEngngModel); //printf ("Mode %u, DofManager: %u, DofIDItem %u, value %10.10f\n", i, dof->giveDofManager()->giveNumber(), dof->giveDofID(), values.at(1)); - factor = isPlus ? modes.at(i - 1)->ap : factor; - factor = isMinus ? modes.at(i - 1)->am : factor; + factor = isPlus ? modes[i].ap : factor; + factor = isMinus ? modes[i].am : factor; factor = isZero ? 1.0 : factor; - masterContribs.at(i) = factor * values.at(1); + masterContribs[i] = factor * values.at(1); } } @@ -375,13 +360,13 @@ SolutionbasedShapeFunction :: loadProblem() // Set up and solve problem OOFEMTXTDataReader drMicro( filename.c_str() ); - EngngModel *myEngngModel = InstanciateProblem(& drMicro, _processor, 0, NULL, false); + auto myEngngModel = InstanciateProblem(drMicro, _processor, 0, NULL, false); drMicro.finish(); myEngngModel->checkProblemConsistency(); myEngngModel->initMetaStepAttributes( myEngngModel->giveMetaStep(1) ); thisTimestep = myEngngModel->giveNextStep(); myEngngModel->init(); - this->setLoads(myEngngModel, i + 1); + this->setLoads(*myEngngModel, i + 1); // Check for ( auto &elem : myEngngModel->giveDomain(1)->giveElements() ) { @@ -392,7 +377,7 @@ SolutionbasedShapeFunction :: loadProblem() for ( int k = 1; k <= elem->giveNumberOfDofManagers(); k++ ) { DofManager *dman = elem->giveDofManager(k); - centerCoord.add( * dman->giveCoordinates() ); + centerCoord.add( dman->giveCoordinates() ); for ( Dof *dof: *dman ) { if ( dof->giveBcId() != 0 ) { vlockCount++; @@ -419,8 +404,8 @@ SolutionbasedShapeFunction :: loadProblem() myEngngModel->doStepOutput(thisTimestep); } - modeStruct *mode = new(modeStruct); - mode->myEngngModel = myEngngModel; + modeStruct mode; + mode.myEngngModel = std::move(myEngngModel); // Check elements @@ -432,13 +417,13 @@ SolutionbasedShapeFunction :: loadProblem() double am=1.0, ap=1.0; if (useCorrectionFactors) { - computeCorrectionFactors(*mode, &dofs, &am, &ap ); + computeCorrectionFactors(mode, dofs, am, ap); } OOFEM_LOG_INFO("Correction factors: am=%f, ap=%f\n", am, ap); - mode->ap = ap; - mode->am = am; + mode.ap = ap; + mode.am = am; updateModelWithFactors(mode); @@ -447,35 +432,35 @@ SolutionbasedShapeFunction :: loadProblem() myEngngModel->doStepOutput(thisTimestep); } - modes.push_back(mode); + modes.push_back(std::move(mode)); - OOFEM_LOG_INFO("************************** Microproblem at %p instanciated \n", myEngngModel); + OOFEM_LOG_INFO("Microproblem at instanciated\n"); } } void -SolutionbasedShapeFunction :: updateModelWithFactors(modeStruct *m) +SolutionbasedShapeFunction :: updateModelWithFactors(modeStruct &m) { //Update values with correction factors - for ( size_t j = 0; j < m->SurfaceData.size(); j++ ) { - SurfaceDataStruct *sd = m->SurfaceData.at(j); - DofManager *dman = sd->DofMan; - Dof *d = dman->giveDofWithID(sd->DofID); + for ( size_t j = 0; j < m.SurfaceData.size(); j++ ) { + SurfaceDataStruct &sd = m.SurfaceData.at(j); + DofManager &dman = *sd.DofMan; + Dof *d = dman.giveDofWithID(sd.DofID); double factor = 1.0; - factor = m->SurfaceData.at(j)->isPlus ? m->ap : factor; - factor = m->SurfaceData.at(j)->isMinus ? m->am : factor; - factor = m->SurfaceData.at(j)->isZeroBoundary ? 1.0 : factor; + factor = sd.isPlus ? m.ap : factor; + factor = sd.isMinus ? m.am : factor; + factor = sd.isZeroBoundary ? 1.0 : factor; - if ( dynamic_cast< MasterDof * >(d) && m->SurfaceData.at(j)->isFree ) { - double u = m->SurfaceData.at(j)->value; - this->setBoundaryConditionOnDof(dman->giveDofWithID(m->SurfaceData.at(j)->DofID), u * factor); + if ( dynamic_cast< MasterDof * >(d) && sd.isFree ) { + double u = sd.value; + this->setBoundaryConditionOnDof(dman.giveDofWithID(sd.DofID), u * factor); } } } void -SolutionbasedShapeFunction :: setLoads(EngngModel *myEngngModel, int d) +SolutionbasedShapeFunction :: setLoads(EngngModel &myEngngModel, int d) { DynamicInputRecord ir; FloatArray gradP; @@ -488,13 +473,12 @@ SolutionbasedShapeFunction :: setLoads(EngngModel *myEngngModel, int d) ir.setField(gradP, _IFT_Load_components); ir.setField(1, _IFT_GeneralBoundaryCondition_timeFunct); - int bcID = myEngngModel->giveDomain(1)->giveNumberOfBoundaryConditions() + 1; - GeneralBoundaryCondition *myBodyLoad; - myBodyLoad = classFactory.createBoundaryCondition( "deadweight", bcID, myEngngModel->giveDomain(1) ); - myBodyLoad->initializeFrom(& ir); - myEngngModel->giveDomain(1)->setBoundaryCondition(bcID, myBodyLoad); + int bcID = myEngngModel.giveDomain(1)->giveNumberOfBoundaryConditions() + 1; + auto myBodyLoad = classFactory.createBoundaryCondition( "deadweight", bcID, myEngngModel.giveDomain(1) ); + myBodyLoad->initializeFrom(ir); + myEngngModel.giveDomain(1)->setBoundaryCondition(bcID, std::move(myBodyLoad)); - for ( auto &elem : myEngngModel->giveDomain(1)->giveElements() ) { + for ( auto &elem : myEngngModel.giveDomain(1)->giveElements() ) { IntArray *blArray; blArray = elem->giveBodyLoadArray(); blArray->resizeWithValues(blArray->giveSize() + 1); @@ -503,7 +487,7 @@ SolutionbasedShapeFunction :: setLoads(EngngModel *myEngngModel, int d) } void -SolutionbasedShapeFunction :: computeBaseFunctionValueAt(FloatArray &answer, FloatArray &coords, IntArray &dofIDs, EngngModel &myEngngModel) +SolutionbasedShapeFunction :: computeBaseFunctionValueAt(FloatArray &answer, const FloatArray &coords, IntArray &dofIDs, EngngModel &myEngngModel) { answer.resize( dofIDs.giveSize() ); answer.zero(); @@ -525,7 +509,7 @@ SolutionbasedShapeFunction :: computeBaseFunctionValueAt(FloatArray &answer, Flo myEngngModel.giveDomain(1)->giveSpatialLocalizer()->init(false); if ( this->giveDomain()->giveNumberOfSpatialDimensions() == 2 ) { - coords.resize(2); + //coords.resize(2); /// FIXME } // Determine if current coordinate is at a max or min point and if so, which type (on a surface, edge or a corner?) @@ -627,10 +611,9 @@ SolutionbasedShapeFunction :: setBoundaryConditionOnDof(Dof *d, double value) bcID = d->giveDofManager()->giveDomain()->giveNumberOfBoundaryConditions() + 1; - GeneralBoundaryCondition *myBC; - myBC = classFactory.createBoundaryCondition( "boundarycondition", bcID, d->giveDofManager()->giveDomain() ); - myBC->initializeFrom(& ir); - d->giveDofManager()->giveDomain()->setBoundaryCondition(bcID, myBC); + auto myBC = classFactory.createBoundaryCondition( "boundarycondition", bcID, d->giveDofManager()->giveDomain() ); + myBC->initializeFrom(ir); + d->giveDofManager()->giveDomain()->setBoundaryCondition(bcID, std::move(myBC)); d->setBcId(bcID); } else { @@ -640,11 +623,11 @@ SolutionbasedShapeFunction :: setBoundaryConditionOnDof(Dof *d, double value) } void -SolutionbasedShapeFunction :: initializeSurfaceData(modeStruct *mode) +SolutionbasedShapeFunction :: initializeSurfaceData(modeStruct &mode) { - EngngModel *m=mode->myEngngModel; - double TOL2=1e-3; + EngngModel &m = *mode.myEngngModel; + double TOL2 = 1e-3; IntArray pNodes, mNodes, zNodes; @@ -653,26 +636,24 @@ SolutionbasedShapeFunction :: initializeSurfaceData(modeStruct *mode) // First add all nodes to pNodes or nNodes respectively depending on coordinate and normal. for ( int i = 0; i < BoundaryList.giveSize() / 2; i++ ) { - int ElementID = BoundaryList(2 * i); - int Boundary = BoundaryList(2 * i + 1); + int ElementID = BoundaryList[2 * i]; + int Boundary = BoundaryList[2 * i + 1]; - Element *e = m->giveDomain(1)->giveElement(ElementID); + Element *e = m.giveDomain(1)->giveElement(ElementID); FEInterpolation *geoInterpolation = e->giveInterpolation(); // Check all sides of element - IntArray bnodes; - #define usePoints 1 #if usePoints == 1 // Check if all nodes are on the boundary - geoInterpolation->boundaryGiveNodes(bnodes, Boundary); + auto bnodes = geoInterpolation->boundaryGiveNodes(Boundary); for ( int k = 1; k <= bnodes.giveSize(); k++ ) { DofManager *dman = e->giveDofManager( bnodes.at(k) ); - for ( int l = 1; l <= dman->giveCoordinates()->giveSize(); l++ ) { - if ( fabs( dman->giveCoordinates()->at(l) - maxCoord.at(l) ) < TOL2 ) { + for ( int l = 1; l <= dman->giveCoordinates().giveSize(); l++ ) { + if ( fabs( dman->giveCoordinates().at(l) - maxCoord.at(l) ) < TOL2 ) { pNodes.insertOnce( dman->giveNumber() ); } - if ( fabs( dman->giveCoordinates()->at(l) - minCoord.at(l) ) < TOL2 ) { + if ( fabs( dman->giveCoordinates().at(l) - minCoord.at(l) ) < TOL2 ) { mNodes.insertOnce( dman->giveNumber() ); } } @@ -794,7 +775,7 @@ SolutionbasedShapeFunction :: initializeSurfaceData(modeStruct *mode) } void -SolutionbasedShapeFunction :: whichBoundary(FloatArray &coord, bool &isPlus, bool &isMinus, bool &isZero) +SolutionbasedShapeFunction :: whichBoundary(const FloatArray &coord, bool &isPlus, bool &isMinus, bool &isZero) { isPlus = false; isMinus = false; @@ -809,23 +790,16 @@ SolutionbasedShapeFunction :: whichBoundary(FloatArray &coord, bool &isPlus, boo } void -SolutionbasedShapeFunction :: copyDofManagersToSurfaceData(modeStruct *mode, IntArray nodeList, bool isPlus, bool isMinus, bool isZeroBoundary) +SolutionbasedShapeFunction :: copyDofManagersToSurfaceData(modeStruct &mode, IntArray nodeList, bool isPlus, bool isMinus, bool isZeroBoundary) { for ( int i = 1; i <= nodeList.giveSize(); i++ ) { FloatArray values; IntArray DofIDs; - DofManager *dman = mode->myEngngModel->giveDomain(1)->giveDofManager(nodeList.at(i)); + DofManager *dman = mode.myEngngModel->giveDomain(1)->giveDofManager(nodeList.at(i)); - computeBaseFunctionValueAt(values, *dman->giveCoordinates(), this->dofs, *mode->myEngngModel ); + computeBaseFunctionValueAt(values, dman->giveCoordinates(), this->dofs, *mode.myEngngModel ); -/* <<<<<<< HEAD -======= - for ( int j = 1; j <= this->dofs.giveSize(); j++ ) { - SurfaceDataStruct *surfaceData = new(SurfaceDataStruct); - Dof *d = dman->giveDofWithID( dofs.at(j) ); ->>>>>>> 147f565295394adef603dae296a820af5f28d9cd -*/ // Check that current node contains current DofID for (int j=1; j<=this->dofs.giveSize(); j++) { for (Dof *d: *dman ){ //int k=1; k<= dman->giveNumberOfDofs(); k++ ) { @@ -833,16 +807,16 @@ SolutionbasedShapeFunction :: copyDofManagersToSurfaceData(modeStruct *mode, Int //Dof *d = dman->dofArray.at(k);// giveDof(k); if (d->giveDofID() == this->dofs.at(j)) { - SurfaceDataStruct *surfaceData = new(SurfaceDataStruct); - surfaceData->DofID = (DofIDItem) this->dofs.at(j); - surfaceData->DofMan = dman; - surfaceData->isPlus = isPlus; - surfaceData->isMinus = isMinus; - surfaceData->isZeroBoundary = isZeroBoundary; - surfaceData->isFree = d->giveBcId() == 0; - surfaceData->value = values.at(j); - - mode->SurfaceData.push_back(surfaceData); + SurfaceDataStruct surfaceData { + isPlus, + isMinus, + isZeroBoundary, + d->giveBcId() == 0, + (DofIDItem) this->dofs.at(j), + dman, + values.at(j), + }; + mode.SurfaceData.emplace_back(std::move(surfaceData)); } } } diff --git a/src/oofemlib/solutionbasedshapefunction.h b/src/oofemlib/solutionbasedshapefunction.h index b85c72363..028c2bca5 100644 --- a/src/oofemlib/solutionbasedshapefunction.h +++ b/src/oofemlib/solutionbasedshapefunction.h @@ -62,8 +62,27 @@ struct SurfaceDataStruct { struct modeStruct { double am, ap; - EngngModel *myEngngModel; - std :: vector< SurfaceDataStruct * >SurfaceData; + std::unique_ptr myEngngModel; + std :: vector SurfaceData; + + /* Visual c++ 2017 compatibility */ +#ifdef _MSC_VER + modeStruct() {} + modeStruct(std::unique_ptr& model) : myEngngModel(std::move(model)) {} + modeStruct(modeStruct&& B) : myEngngModel(std::move(B.myEngngModel)) { am = B.am; ap = B.ap; SurfaceData = B.SurfaceData; } + modeStruct(modeStruct& B) : myEngngModel(std::move(B.myEngngModel)) { am = B.am; ap = B.ap; SurfaceData = B.SurfaceData; } + + modeStruct& operator= (modeStruct& other) { + myEngngModel = std::move(other.myEngngModel); + am = other.am; + ap = other.ap; + SurfaceData = other.SurfaceData; + return *this; + } +#endif /* end of Visual c++ 2017 compatibility */ + + + }; class OOFEM_EXPORT SolutionbasedShapeFunction : public ActiveBoundaryCondition @@ -86,20 +105,20 @@ class OOFEM_EXPORT SolutionbasedShapeFunction : public ActiveBoundaryCondition bool isCoeff(ActiveDof *dof); - std :: vector< modeStruct * >modes; + std :: vector< modeStruct >modes; - void updateModelWithFactors(modeStruct *m); + void updateModelWithFactors(modeStruct &m); TimeStep *thisTimestep; FloatArray maxCoord, minCoord; void setBoundaryConditionOnDof(Dof *d, double value); - void setLoads(EngngModel *myEngngModel, int d); + void setLoads(EngngModel &myEngngModel, int d); void loadProblem(); void init(); - void computeCorrectionFactors(modeStruct &myMode, IntArray *Dofs, double *am, double *ap); + void computeCorrectionFactors(modeStruct &myMode, IntArray &Dofs, double &am, double &ap); /** * @brief giveValueAtPoint @@ -114,38 +133,38 @@ class OOFEM_EXPORT SolutionbasedShapeFunction : public ActiveBoundaryCondition void splitBoundaryNodeIDs(modeStruct &mode, Element &e, IntArray &boundary, IntArray &pList, IntArray &mList, IntArray &zList, FloatMatrix &nodeValues); - void computeBaseFunctionValueAt(FloatArray &answer, FloatArray &coords, IntArray &dofIDs, EngngModel &myEngngModel); + void computeBaseFunctionValueAt(FloatArray &answer, const FloatArray &coords, IntArray &dofIDs, EngngModel &myEngngModel); - void initializeSurfaceData(modeStruct *mode); + void initializeSurfaceData(modeStruct &mode); - void copyDofManagersToSurfaceData(modeStruct *mode, IntArray nodeList, bool isPlus, bool isMinus, bool isZero); + void copyDofManagersToSurfaceData(modeStruct &mode, IntArray nodeList, bool isPlus, bool isMinus, bool isZero); - void whichBoundary(FloatArray &coord, bool &isPlus, bool &isMinus, bool &isZero); + void whichBoundary(const FloatArray &coord, bool &isPlus, bool &isMinus, bool &isZero); public: SolutionbasedShapeFunction(int n, Domain * d); - virtual ~SolutionbasedShapeFunction(); + virtual ~SolutionbasedShapeFunction() {} - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual bool requiresActiveDofs() { return true; } - virtual int giveNumberOfInternalDofManagers() { return 1; } - virtual DofManager *giveInternalDofManager(int i); + bool requiresActiveDofs() override { return true; } + int giveNumberOfInternalDofManagers() override { return 1; } + DofManager *giveInternalDofManager(int i) override; - virtual double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof); - virtual double giveUnknown(ValueModeType mode, TimeStep *tStep, ActiveDof *dof); + double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof) override; + double giveUnknown(ValueModeType mode, TimeStep *tStep, ActiveDof *dof) override; - virtual bool hasBc(Dof *dof, TimeStep *tStep) { return false; } + bool hasBc(Dof *dof, TimeStep *tStep) override { return false; } - virtual bool isPrimaryDof(ActiveDof *dof) { return false; } + bool isPrimaryDof(ActiveDof *dof) override { return false; } - virtual void computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs); + void computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs) override; - virtual int giveNumberOfMasterDofs(ActiveDof *dof); - virtual Dof *giveMasterDof(ActiveDof *dof, int mdof); + int giveNumberOfMasterDofs(ActiveDof *dof) override; + Dof *giveMasterDof(ActiveDof *dof, int mdof) override; - virtual const char *giveClassName() const { return "SolutionbasedShapeFunction"; } - virtual const char *giveInputRecordName() const { return _IFT_SolutionbasedShapeFunction_Name; } + const char *giveClassName() const override { return "SolutionbasedShapeFunction"; } + const char *giveInputRecordName() const override { return _IFT_SolutionbasedShapeFunction_Name; } double checkIncompressibility(EngngModel &myEngngModel); }; diff --git a/src/oofemlib/sparsemtrx.h b/src/oofemlib/sparsemtrx.h index 3d1b24b68..b9799bb44 100644 --- a/src/oofemlib/sparsemtrx.h +++ b/src/oofemlib/sparsemtrx.h @@ -42,6 +42,8 @@ #include "error.h" #include "sparsemtrxtype.h" +#include + namespace oofem { class EngngModel; class TimeStep; @@ -84,9 +86,7 @@ class OOFEM_EXPORT SparseMtrx * Constructor, creates (n,m) sparse matrix. Due to sparsity character of matrix, * not all coefficient are physically stored (in general, zero members are omitted). */ - SparseMtrx(int n, int m) : nRows(n), nColumns(m), version(0) { } - /// Constructor - SparseMtrx() : nRows(0), nColumns(0), version(0) { } + SparseMtrx(int n=0, int m=0) : nRows(n), nColumns(m), version(0) { } /// Destructor virtual ~SparseMtrx() { } @@ -124,9 +124,10 @@ class OOFEM_EXPORT SparseMtrx * care about proper deallocation of allocated space. * @return Newly allocated copy of receiver. */ - virtual SparseMtrx *GiveCopy() const { + virtual std::unique_ptr clone() const + { OOFEM_ERROR("Not implemented"); - return NULL; + return nullptr; } /** @@ -260,8 +261,8 @@ class OOFEM_EXPORT SparseMtrx return 0.0; } - virtual SparseMtrx *giveSubMatrix(const IntArray &rows, const IntArray &cols) - { OOFEM_ERROR("Not implemented"); return NULL; } + virtual std::unique_ptr giveSubMatrix(const IntArray &rows, const IntArray &cols) + { OOFEM_ERROR("Not implemented"); return nullptr; } /// Returns coefficient at position (i,j). virtual double &at(int i, int j) = 0; diff --git a/src/oofemlib/sparsenonlinsystemnm.C b/src/oofemlib/sparsenonlinsystemnm.C index df2e0c1ff..7e6b4e73b 100644 --- a/src/oofemlib/sparsenonlinsystemnm.C +++ b/src/oofemlib/sparsenonlinsystemnm.C @@ -40,16 +40,13 @@ namespace oofem { -IRResultType -SparseNonLinearSystemNM :: initializeFrom(InputRecord *ir) +void +SparseNonLinearSystemNM :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - randPertAmplitude = 0.; IR_GIVE_OPTIONAL_FIELD(ir, randPertAmplitude, _IFT_NonLinearStatic_randPertAmplitude); if ( randPertAmplitude < 0. ) { - OOFEM_WARNING("Random pertubation amplitude can not be negative"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_NonLinearStatic_randPertAmplitude, "Random pertubation amplitude can not be negative"); } randSeed = 0; IR_GIVE_OPTIONAL_FIELD(ir, randSeed, _IFT_NonLinearStatic_randSeed); @@ -61,19 +58,16 @@ SparseNonLinearSystemNM :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, igp_PertWeightArray, _IFT_NonLinearStatic_pertw); if ( igp_PertDmanDofSrcArray.giveSize() ) { if ( ( igp_PertDmanDofSrcArray.giveSize() % 2 ) != 0 ) { - OOFEM_WARNING("Pert map size must be an even number, it contains pairs "); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_NonLinearStatic_pert, "Pert map size must be an even number, it contains pairs "); } int nsize = igp_PertDmanDofSrcArray.giveSize() / 2; if ( igp_PertWeightArray.giveSize() != nsize ) { - OOFEM_WARNING("Pert map size and weight array size mismatch"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_NonLinearStatic_pert, "Pert map size and weight array size mismatch"); } pert_init_needed = true; } else { pert_init_needed = false; } - return IRRT_OK; } void diff --git a/src/oofemlib/sparsenonlinsystemnm.h b/src/oofemlib/sparsenonlinsystemnm.h index 7477effe6..b18943827 100644 --- a/src/oofemlib/sparsenonlinsystemnm.h +++ b/src/oofemlib/sparsenonlinsystemnm.h @@ -94,7 +94,7 @@ class OOFEM_EXPORT SparseNonLinearSystemNM : public NumericalMethod enum referenceLoadInputModeType { rlm_total=0, ///< The reference incremental load vector is defined as totalLoadVector assembled at given time. rlm_incremental=1, ///< The reference load vector is obtained as incremental load vector at given time. - }; + }; /// Constructor SparseNonLinearSystemNM(Domain * d, EngngModel * m) : NumericalMethod(d, m), igp_PertDmanDofSrcArray(), igp_PertWeightArray(), igp_Map(), igp_Weight() { pert_init_needed = false; } @@ -150,9 +150,9 @@ class OOFEM_EXPORT SparseNonLinearSystemNM : public NumericalMethod * Constructs (if necessary) and returns a linear solver. * Public method because some problems require it for sensitivity analysis, etc. even for nonlinear problems (e.g. tangent relations in multiscale simulations). */ - virtual SparseLinearSystemNM *giveLinearSolver() { return NULL; } + virtual SparseLinearSystemNM *giveLinearSolver() { return nullptr; } - IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; virtual void convertPertMap(); virtual void applyPerturbation(FloatArray* displacement); diff --git a/src/oofemlib/spatiallocalizer.C b/src/oofemlib/spatiallocalizer.C index a6769ac83..9b0e97c1c 100644 --- a/src/oofemlib/spatiallocalizer.C +++ b/src/oofemlib/spatiallocalizer.C @@ -54,12 +54,12 @@ SpatialLocalizerInterface :: SpatialLocalizerI_containsPoint(const FloatArray &c void SpatialLocalizerInterface :: SpatialLocalizerI_giveBBox(FloatArray &bb0, FloatArray &bb1) { - bb1 = bb0 = * element->giveNode(1)->giveCoordinates(); + bb1 = bb0 = element->giveNode(1)->giveCoordinates(); for ( int i = 2; i <= element->giveNumberOfNodes(); ++i ) { - FloatArray *coordinates = element->giveNode(i)->giveCoordinates(); - bb0.beMinOf(bb0, * coordinates); - bb1.beMaxOf(bb1, * coordinates); + const auto &coordinates = element->giveNode(i)->giveCoordinates(); + bb0.beMinOf(bb0, coordinates); + bb1.beMaxOf(bb1, coordinates); } } @@ -71,7 +71,7 @@ SpatialLocalizerInterface :: SpatialLocalizerI_giveClosestPoint(FloatArray &lcoo if ( !interp->global2local( lcoords, gcoords, FEIElementGeometryWrapper(element) ) ) { // Outside element interp->local2global( closest, lcoords, FEIElementGeometryWrapper(element) ); - return closest.distance(gcoords); + return distance(closest, gcoords); } else { closest = gcoords; return 0.0; diff --git a/src/oofemlib/spatiallocalizer.h b/src/oofemlib/spatiallocalizer.h index 5fca1c280..061c1b9be 100644 --- a/src/oofemlib/spatiallocalizer.h +++ b/src/oofemlib/spatiallocalizer.h @@ -133,7 +133,7 @@ class OOFEM_EXPORT SpatialLocalizer * @param regionList Only elements within given regions are considered, if NULL all regions are considered. * @return The element belonging to associated domain, containing given point, NULL otherwise. */ - virtual Element *giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList = NULL) = 0; + virtual Element *giveElementContainingPoint(const FloatArray &coords, const IntArray *regionList=nullptr) = 0; /** * Returns the element, containing given point and belonging to one of the region in region list. * @param coords Global problem coordinates of point of interest. diff --git a/src/oofemlib/spoolessolver.C b/src/oofemlib/spoolessolver.C index 4ac5b8300..b9640edc8 100644 --- a/src/oofemlib/spoolessolver.C +++ b/src/oofemlib/spoolessolver.C @@ -93,11 +93,9 @@ SpoolesSolver :: ~SpoolesSolver() } } -IRResultType -SpoolesSolver :: initializeFrom(InputRecord *ir) +void +SpoolesSolver :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - int val; std :: string msgFileName; @@ -112,8 +110,6 @@ SpoolesSolver :: initializeFrom(InputRecord *ir) msgFile = stdout; msgFileCloseFlag = 0; } - - return IRRT_OK; } diff --git a/src/oofemlib/spoolessolver.h b/src/oofemlib/spoolessolver.h index e843ae551..30e5cb98a 100644 --- a/src/oofemlib/spoolessolver.h +++ b/src/oofemlib/spoolessolver.h @@ -46,6 +46,7 @@ extern "C" { ///@name Input fields for SpoolesSolver //@{ +#define _IFT_SpoolesSolver_Name "spooles" #define _IFT_SpoolesSolver_msglvl "msglvl" #define _IFT_SpoolesSolver_msgfile "msgfile" //@} @@ -91,15 +92,15 @@ class OOFEM_EXPORT SpoolesSolver : public SparseLinearSystemNM /** * Solves the given linear system by LDL^T factorization. */ - virtual NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x); + NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x) override; /// Initializes receiver from given record. - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; // identification - virtual const char *giveClassName() const { return "SpoolesSolver"; } - virtual LinSystSolverType giveLinSystSolverType() const { return ST_Spooles; } - virtual SparseMtrxType giveRecommendedMatrix(bool symmetric) const { return SMT_SpoolesMtrx; } + const char *giveClassName() const override { return "SpoolesSolver"; } + LinSystSolverType giveLinSystSolverType() const override { return ST_Spooles; } + SparseMtrxType giveRecommendedMatrix(bool symmetric) const override { return SMT_SpoolesMtrx; } }; } // end namespace oofem #endif // spoolessolver_h diff --git a/src/oofemlib/spoolessparsemtrx.C b/src/oofemlib/spoolessparsemtrx.C index 03c3b2cfd..ba33d1c14 100644 --- a/src/oofemlib/spoolessparsemtrx.C +++ b/src/oofemlib/spoolessparsemtrx.C @@ -40,13 +40,6 @@ namespace oofem { REGISTER_SparseMtrx(SpoolesSparseMtrx, SMT_SpoolesMtrx); -SparseMtrx * -SpoolesSparseMtrx :: GiveCopy() const -{ - OOFEM_ERROR("Not implemented"); - return NULL; -} - void SpoolesSparseMtrx :: times(const FloatArray &x, FloatArray &answer) const { @@ -110,18 +103,16 @@ SpoolesSparseMtrx :: buildInternalStructure(EngngModel *eModel, int di, const Un int SpoolesSparseMtrx :: assemble(const IntArray &loc, const FloatMatrix &mat) { - int i, j, ac1, ac2, ndofe; + int ndofe = mat.giveNumberOfRows(); - ndofe = mat.giveNumberOfRows(); - - for ( i = 1; i <= ndofe; i++ ) { - ac1 = loc.at(i); + for ( int i = 1; i <= ndofe; i++ ) { + int ac1 = loc.at(i); if ( ac1 == 0 ) { continue; } - for ( j = 1; j <= ndofe; j++ ) { - ac2 = loc.at(j); + for ( int j = 1; j <= ndofe; j++ ) { + int ac2 = loc.at(j); if ( ac2 == 0 ) { continue; } @@ -134,7 +125,6 @@ SpoolesSparseMtrx :: assemble(const IntArray &loc, const FloatMatrix &mat) } } - // increment version this->version++; return 1; } @@ -142,15 +132,13 @@ SpoolesSparseMtrx :: assemble(const IntArray &loc, const FloatMatrix &mat) int SpoolesSparseMtrx :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) { - int i, j, ii, jj, dim1, dim2; - - dim1 = mat.giveNumberOfRows(); - dim2 = mat.giveNumberOfColumns(); - for ( i = 1; i <= dim1; i++ ) { - ii = rloc.at(i); + int dim1 = mat.giveNumberOfRows(); + int dim2 = mat.giveNumberOfColumns(); + for ( int i = 1; i <= dim1; i++ ) { + int ii = rloc.at(i); if ( ii ) { - for ( j = 1; j <= dim2; j++ ) { - jj = cloc.at(j); + for ( int j = 1; j <= dim2; j++ ) { + int jj = cloc.at(j); if ( jj ) { InpMtx_inputRealEntry( this->mtrx, ii - 1, jj - 1, mat.at(i, j) ); } @@ -158,7 +146,6 @@ SpoolesSparseMtrx :: assemble(const IntArray &rloc, const IntArray &cloc, const } } - // increment version this->version++; return 1; diff --git a/src/oofemlib/spoolessparsemtrx.h b/src/oofemlib/spoolessparsemtrx.h index b315f32a5..1fd138e5b 100644 --- a/src/oofemlib/spoolessparsemtrx.h +++ b/src/oofemlib/spoolessparsemtrx.h @@ -43,6 +43,8 @@ extern "C" { #include }; +#define _IFT_SpoolesSparseMtrx_Name "spooles" + namespace oofem { /** * This class provides an sparse matrix interface to SPOOLES InpMtrx @@ -52,47 +54,36 @@ class OOFEM_EXPORT SpoolesSparseMtrx : public SparseMtrx protected: InpMtx *mtrx; int type; - int nent; int sflag; public: - SpoolesSparseMtrx(int _type, int _nent, int _sflag, int n, int m) : SparseMtrx(n, m) - { - type = _type; - nent = _nent; - sflag = _sflag; - mtrx = NULL; - } - SpoolesSparseMtrx() : SparseMtrx() { - type = SPOOLES_REAL; - nent = 0; - sflag = SPOOLES_SYMMETRIC; - mtrx = NULL; - } + SpoolesSparseMtrx(int n=0, int m=0, int _sflag=SPOOLES_SYMMETRIC, int _type=SPOOLES_REAL) : SparseMtrx(n, m), + mtrx(nullptr), + type(_type), + sflag(_sflag) + { } virtual ~SpoolesSparseMtrx() { if ( mtrx ) { InpMtx_free(mtrx); } } - // Overloaded methods - virtual SparseMtrx *GiveCopy() const; - virtual void times(const FloatArray &x, FloatArray &answer) const; - virtual void timesT(const FloatArray &x, FloatArray &answer) const; - virtual void times(double x); - virtual int buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s); - virtual int assemble(const IntArray &loc, const FloatMatrix &mat); - virtual int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat); - virtual bool canBeFactorized() const { return false; } - virtual SparseMtrx *factorized() { return NULL; } - virtual FloatArray *backSubstitutionWith(FloatArray &y) const { return NULL; } - virtual void zero(); - virtual double &at(int i, int j); - virtual double at(int i, int j) const; - virtual void printStatistics() const; - virtual void printYourself() const; - virtual SparseMtrxType giveType() const { return SMT_SpoolesMtrx; } - virtual bool isAsymmetric() const { return this->type == SPOOLES_NONSYMMETRIC; } + void times(const FloatArray &x, FloatArray &answer) const override; + void timesT(const FloatArray &x, FloatArray &answer) const override; + void times(double x) override; + int buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s) override; + int assemble(const IntArray &loc, const FloatMatrix &mat) override; + int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) override; + bool canBeFactorized() const override { return false; } + SparseMtrx *factorized() override { return nullptr; } + FloatArray *backSubstitutionWith(FloatArray &y) const override { return nullptr; } + void zero() override; + double &at(int i, int j) override; + double at(int i, int j) const override; + void printStatistics() const override; + void printYourself() const override; + SparseMtrxType giveType() const override { return SMT_SpoolesMtrx; } + bool isAsymmetric() const override { return this->type == SPOOLES_NONSYMMETRIC; } // Exposed internals InpMtx *giveInpMtrx() { return this->mtrx; } diff --git a/src/oofemlib/sprnodalrecoverymodel.C b/src/oofemlib/sprnodalrecoverymodel.C index 982c5f855..e4d829f70 100644 --- a/src/oofemlib/sprnodalrecoverymodel.C +++ b/src/oofemlib/sprnodalrecoverymodel.C @@ -40,6 +40,7 @@ #include "integrationrule.h" #include "gausspoint.h" #include "engngm.h" +#include "classfactory.h" #ifdef __PARALLEL_MODE #include "processcomm.h" @@ -50,6 +51,8 @@ #include namespace oofem { +REGISTER_NodalRecoveryModel(SPRNodalRecoveryModel, NodalRecoveryModel :: NRM_SPR); + SPRNodalRecoveryModel :: SPRNodalRecoveryModel(Domain *d) : NodalRecoveryModel(d) { } @@ -520,8 +523,8 @@ SPRNodalRecoveryModel :: determineValuesFromPatch(FloatArray &dofManValues, IntA FloatArray P, vals; for ( int dofMan = 1; dofMan <= ndofMan; dofMan++ ) { - FloatArray *coords = domain->giveNode( dofManToDetermine.at(dofMan) )->giveCoordinates(); - this->computePolynomialTerms(P, * coords, type); + const auto &coords = domain->giveNode( dofManToDetermine.at(dofMan) )->giveCoordinates(); + this->computePolynomialTerms(P, coords, type); vals.beTProductOf(a, P); // assemble values @@ -535,7 +538,7 @@ SPRNodalRecoveryModel :: determineValuesFromPatch(FloatArray &dofManValues, IntA } void -SPRNodalRecoveryModel :: computePolynomialTerms(FloatArray &P, FloatArray &coords, SPRPatchType type) +SPRNodalRecoveryModel :: computePolynomialTerms(FloatArray &P, const FloatArray &coords, SPRPatchType type) { if ( type == SPRPatchType_2dxy ) { P.resize(3); @@ -643,20 +646,19 @@ SPRNodalRecoveryModel :: exchangeDofManValues(FloatArray &dofManValues, IntArray int SPRNodalRecoveryModel :: packSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm) { - int result = 1, i, j, indx, eq, size; + int result = 1; ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); - IntArray const *toSendMap = processComm.giveToSendMap(); + const IntArray &toSendMap = processComm.giveToSendMap(); - size = toSendMap->giveSize(); - for ( i = 1; i <= size; i++ ) { + for ( int inode : toSendMap ) { // toSendMap contains all shared dofmans with remote partition // one has to check, if particular shared node value is available for given region - indx = s->regionNodalNumbers->at( toSendMap->at(i) ); + int indx = s->regionNodalNumbers->at( inode ); if ( indx && s->dofManPatchCount->at(indx) ) { // pack "1" to indicate that for given shared node this is a valid contribution result &= pcbuff->write(1); - eq = ( indx - 1 ) * s->regionValSize; - for ( j = 1; j <= s->regionValSize; j++ ) { + int eq = ( indx - 1 ) * s->regionValSize; + for ( int j = 1; j <= s->regionValSize; j++ ) { result &= pcbuff->write( s->dofManValues->at(eq + j) ); } } else { @@ -672,21 +674,20 @@ int SPRNodalRecoveryModel :: unpackSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm) { int result = 1; - int i, j, eq, indx, size, flag; - IntArray const *toRecvMap = processComm.giveToRecvMap(); + int flag; + const IntArray &toRecvMap = processComm.giveToRecvMap(); ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); - double value; - size = toRecvMap->giveSize(); - for ( i = 1; i <= size; i++ ) { - indx = s->regionNodalNumbers->at( toRecvMap->at(i) ); + for ( int inode : toRecvMap ) { + int indx = s->regionNodalNumbers->at( inode ); // toRecvMap contains all shared dofmans with remote partition // one has to check, if particular shared node received contribution is available for given region result &= pcbuff->read(flag); if ( flag ) { // "1" to indicates that for given shared node this is a valid contribution - eq = ( indx - 1 ) * s->regionValSize; - for ( j = 1; j <= s->regionValSize; j++ ) { + int eq = ( indx - 1 ) * s->regionValSize; + for ( int j = 1; j <= s->regionValSize; j++ ) { + double value; result &= pcbuff->read(value); if ( indx ) { s->dofManValues->at(eq + j) += value; diff --git a/src/oofemlib/sprnodalrecoverymodel.h b/src/oofemlib/sprnodalrecoverymodel.h index 19d8997e6..a7edfee1e 100644 --- a/src/oofemlib/sprnodalrecoverymodel.h +++ b/src/oofemlib/sprnodalrecoverymodel.h @@ -38,6 +38,8 @@ #include "nodalrecoverymodel.h" #include "interface.h" +#define _IFT_SPRNodalRecoveryModel_Name "spr" + namespace oofem { class GaussPoint; class SPRNodalRecoveryModelInterface; @@ -80,9 +82,9 @@ class OOFEM_EXPORT SPRNodalRecoveryModel : public NodalRecoveryModel /// Destructor. virtual ~SPRNodalRecoveryModel(); - virtual int recoverValues(Set elementSet, InternalStateType type, TimeStep *tStep); + int recoverValues(Set elementSet, InternalStateType type, TimeStep *tStep) override; - virtual const char *giveClassName() const { return "SPRNodalRecoveryModel"; } + const char *giveClassName() const override { return "SPRNodalRecoveryModel"; } private: /** @@ -101,7 +103,7 @@ class OOFEM_EXPORT SPRNodalRecoveryModel : public NodalRecoveryModel void determineValuesFromPatch(FloatArray &dofManValues, IntArray &dofManCount, IntArray ®ionNodalNumbers, IntArray &dofManToDetermine, FloatMatrix &a, SPRPatchType type); - void computePolynomialTerms(FloatArray &P, FloatArray &coords, SPRPatchType type); + void computePolynomialTerms(FloatArray &P, const FloatArray &coords, SPRPatchType type); int giveNumberOfUnknownPolynomialCoefficients(SPRPatchType regType); SPRPatchType determinePatchType(Set &elementList); diff --git a/src/oofemlib/staggeredproblem.C b/src/oofemlib/staggeredproblem.C index ee5e64602..73a20f8be 100644 --- a/src/oofemlib/staggeredproblem.C +++ b/src/oofemlib/staggeredproblem.C @@ -76,18 +76,18 @@ StaggeredProblem :: ~StaggeredProblem() /////////// int -StaggeredProblem :: instanciateYourself(DataReader *dr, InputRecord *ir, const char *dataOutputFileName, const char *desc) +StaggeredProblem :: instanciateYourself(DataReader &dr, InputRecord &ir, const char *dataOutputFileName, const char *desc) { int result; result = EngngModel :: instanciateYourself(dr, ir, dataOutputFileName, desc); - ir->finish(); + ir.finish(); // instanciate slave problems result &= this->instanciateSlaveProblems(); return result; } int -StaggeredProblem :: instanciateDefaultMetaStep(InputRecord *ir) +StaggeredProblem :: instanciateDefaultMetaStep(InputRecord &ir) { if ( timeDefinedByProb ) { /* just set a nonzero number of steps; @@ -108,7 +108,7 @@ StaggeredProblem :: instanciateSlaveProblems() emodelList.resize( inputStreamNames.size() ); if ( timeDefinedByProb ) { OOFEMTXTDataReader dr(inputStreamNames [ timeDefinedByProb - 1 ]); - std :: unique_ptr< EngngModel >prob( InstanciateProblem(& dr, this->pMode, this->contextOutputMode, this) ); + std :: unique_ptr< EngngModel >prob( InstanciateProblem(dr, this->pMode, this->contextOutputMode, this) ); //timeDefProb = prob.get(); emodelList [ timeDefinedByProb - 1 ] = std :: move(prob); } @@ -120,7 +120,7 @@ StaggeredProblem :: instanciateSlaveProblems() OOFEMTXTDataReader dr(inputStreamNames [ i - 1 ]); //the slave problem dictating time needs to have attribute master=NULL, other problems point to the dictating slave - std :: unique_ptr< EngngModel >prob( InstanciateProblem(& dr, this->pMode, this->contextOutputMode, this) ); + std :: unique_ptr< EngngModel >prob( InstanciateProblem(dr, this->pMode, this->contextOutputMode, this) ); emodelList [ i - 1 ] = std :: move(prob); } @@ -128,36 +128,28 @@ StaggeredProblem :: instanciateSlaveProblems() } -IRResultType -StaggeredProblem :: initializeFrom(InputRecord *ir) +void +StaggeredProblem :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, numberOfSteps, _IFT_EngngModel_nsteps); if ( numberOfSteps <= 0 ) { - OOFEM_ERROR("nsteps not specified, bad format"); + throw ValueInputException(ir, _IFT_EngngModel_nsteps, "nsteps must be > 0"); } - if ( ir->hasField(_IFT_StaggeredProblem_deltat) ) { - result = EngngModel :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + if ( ir.hasField(_IFT_StaggeredProblem_deltat) ) { + EngngModel :: initializeFrom(ir); IR_GIVE_FIELD(ir, deltaT, _IFT_StaggeredProblem_deltat); dtFunction = 0; - } else if ( ir->hasField(_IFT_StaggeredProblem_prescribedtimes) ) { - result = EngngModel :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + } else if ( ir.hasField(_IFT_StaggeredProblem_prescribedtimes) ) { + EngngModel :: initializeFrom(ir); IR_GIVE_FIELD(ir, discreteTimes, _IFT_StaggeredProblem_prescribedtimes); dtFunction = 0; - } else if ( ir->hasField(_IFT_StaggeredProblem_dtf) ) { + } else if ( ir.hasField(_IFT_StaggeredProblem_dtf) ) { IR_GIVE_OPTIONAL_FIELD(ir, dtFunction, _IFT_StaggeredProblem_dtf); } else { IR_GIVE_FIELD(ir, timeDefinedByProb, _IFT_StaggeredProblem_timeDefinedByProb); } - if ( ir->hasField(_IFT_StaggeredProblem_adaptiveStepLength) ) { + if ( ir.hasField(_IFT_StaggeredProblem_adaptiveStepLength) ) { adaptiveStepLength = true; this->minStepLength = 0.; IR_GIVE_OPTIONAL_FIELD(ir, minStepLength, _IFT_StaggeredProblem_minsteplength); @@ -174,15 +166,14 @@ StaggeredProblem :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, stepMultiplier, _IFT_StaggeredProblem_stepmultiplier); if ( stepMultiplier < 0 ) { - OOFEM_WARNING("stepMultiplier must be > 0"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_StaggeredProblem_stepmultiplier, "stepMultiplier must be > 0"); } // timeLag = 0.; // IR_GIVE_OPTIONAL_FIELD(ir, timeLag, _IFT_StaggeredProblem_timeLag); inputStreamNames.resize(2); - if ( ir->hasField(_IFT_StaggeredProblem_prob3) ){ + if ( ir.hasField(_IFT_StaggeredProblem_prob3) ){ inputStreamNames.resize(3); } @@ -204,14 +195,14 @@ StaggeredProblem :: initializeFrom(InputRecord *ir) domainList.clear(); } - suppressOutput = ir->hasField(_IFT_EngngModel_suppressOutput); + suppressOutput = ir.hasField(_IFT_EngngModel_suppressOutput); if ( suppressOutput ) { printf("Suppressing output.\n"); } else { if ( ( outputStream = fopen(this->dataOutputFileName.c_str(), "w") ) == NULL ) { - OOFEM_ERROR("Can't open output file %s", this->dataOutputFileName.c_str()); + throw ValueInputException(ir, "None", "can't open output file: " + this->dataOutputFileName); } fprintf(outputStream, "%s", PRG_HEADER); @@ -224,19 +215,13 @@ StaggeredProblem :: initializeFrom(InputRecord *ir) } #endif } - - - - return IRRT_OK; } void StaggeredProblem :: updateAttributes(MetaStep *mStep) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - InputRecord *ir = mStep->giveAttributesRecord(); + auto &ir = mStep->giveAttributesRecord(); EngngModel :: updateAttributes(mStep); @@ -246,14 +231,14 @@ StaggeredProblem :: updateAttributes(MetaStep *mStep) } if ( !timeDefinedByProb ) { - if ( ir->hasField(_IFT_StaggeredProblem_deltat) ) { + if ( ir.hasField(_IFT_StaggeredProblem_deltat) ) { IR_GIVE_FIELD(ir, deltaT, _IFT_StaggeredProblem_deltat); IR_GIVE_OPTIONAL_FIELD(ir, dtFunction, _IFT_StaggeredProblem_dtf); IR_GIVE_OPTIONAL_FIELD(ir, stepMultiplier, _IFT_StaggeredProblem_stepmultiplier); if ( stepMultiplier < 0 ) { OOFEM_ERROR("stepMultiplier must be > 0") } - } else if ( ir->hasField(_IFT_StaggeredProblem_prescribedtimes) ) { + } else if ( ir.hasField(_IFT_StaggeredProblem_prescribedtimes) ) { IR_GIVE_FIELD(ir, discreteTimes, _IFT_StaggeredProblem_prescribedtimes); } } @@ -372,14 +357,25 @@ StaggeredProblem :: giveSolutionStepWhenIcApply(bool force) } else { if ( !stepWhenIcApply ) { int nFirst = giveNumberOfFirstStep(); - //stepWhenIcApply.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, -giveDeltaT(nFirst), giveDeltaT(nFirst), 0) );//previous version for [-dt, 0] - stepWhenIcApply.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, 0., giveDeltaT(nFirst), 0) );//now go from [0, dt] + //stepWhenIcApply = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 0, -giveDeltaT(nFirst), giveDeltaT(nFirst), 0); //previous version for [-dt, 0] + stepWhenIcApply = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 0, 0., giveDeltaT(nFirst), 0); //now go from [0, dt] } return stepWhenIcApply.get(); } } + +EngngModel * +StaggeredProblem :: giveTimeControl(){ + if ( !timeDefinedByProb ) { + return this; + } else { //time dictated by slave problem + return this->giveSlaveProblem(timeDefinedByProb); + } +} + + int StaggeredProblem :: giveNumberOfFirstStep(bool force) { @@ -400,7 +396,7 @@ StaggeredProblem :: giveNextStep() if ( !currentStep ) { // first step -> generate initial step - currentStep.reset( new TimeStep( *giveSolutionStepWhenIcApply() ) ); + currentStep = std::make_unique( *giveSolutionStepWhenIcApply() ); } double dt = this->giveDeltaT(currentStep->giveNumber()+1); @@ -408,20 +404,20 @@ StaggeredProblem :: giveNextStep() totalTime = currentStep->giveTargetTime() + this->giveDeltaT(istep); counter = currentStep->giveSolutionStateCounter() + 1; previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(*previousStep, dt) ); + currentStep = std::make_unique(*previousStep, dt); if ( ( totalTime >= this->endOfTimeOfInterest ) && this->adaptiveStepLength ) { totalTime = this->endOfTimeOfInterest; OOFEM_LOG_INFO("\n==================================================================\n"); OOFEM_LOG_INFO( "\nAdjusting time step length to: %lf \n\n", totalTime - previousStep->giveTargetTime() ); - currentStep.reset( new TimeStep(istep, this, 1, totalTime, totalTime - previousStep->giveTargetTime(), counter) ); + currentStep = std::make_unique(istep, this, 1, totalTime, totalTime - previousStep->giveTargetTime(), counter); this->numberOfSteps = istep; } else { if ( this->adaptiveStepLength ) { OOFEM_LOG_INFO("\n==================================================================\n"); OOFEM_LOG_INFO( "\nAdjusting time step length to: %lf \n\n", totalTime - previousStep->giveTargetTime() ); } - currentStep.reset( new TimeStep(istep, this, 1, totalTime, totalTime - previousStep->giveTargetTime(), counter) ); + currentStep = std::make_unique(istep, this, 1, totalTime, totalTime - previousStep->giveTargetTime(), counter); } // time and dt variables are set eq to 0 for statics - has no meaning @@ -433,11 +429,7 @@ void StaggeredProblem :: solveYourself() { EngngModel *sp; - if ( !timeDefinedByProb ) { - sp = this; - } else { //time dictated by slave problem - sp = this->giveSlaveProblem(timeDefinedByProb); - } + sp = giveTimeControl(); int smstep = 1, sjstep = 1; this->timer.startTimer(EngngModelTimer :: EMTT_AnalysisTimer); @@ -558,27 +550,23 @@ StaggeredProblem :: printOutputAt(FILE *file, TimeStep *tStep) } -contextIOResultType +void StaggeredProblem :: saveContext(DataStream &stream, ContextMode mode) { EngngModel :: saveContext(stream, mode); for ( auto &emodel: emodelList ) { emodel->saveContext(stream, mode); } - - return CIO_OK; } -contextIOResultType -StaggeredProblem :: restoreContext(DataStream *stream, ContextMode mode, void *obj) +void +StaggeredProblem :: restoreContext(DataStream &stream, ContextMode mode) { - EngngModel :: restoreContext(stream, mode, obj); + EngngModel :: restoreContext(stream, mode); for ( auto &emodel: this->emodelList ) { - emodel->restoreContext(stream, mode, obj); + emodel->restoreContext(stream, mode); } - - return CIO_OK; } diff --git a/src/oofemlib/staggeredproblem.h b/src/oofemlib/staggeredproblem.h index 177823c0a..9a47dcbd4 100644 --- a/src/oofemlib/staggeredproblem.h +++ b/src/oofemlib/staggeredproblem.h @@ -140,7 +140,7 @@ class OOFEM_EXPORT StaggeredProblem : public EngngModel /** * Constructor. Creates an engineering model with number i belonging to domain d. */ - StaggeredProblem(int i, EngngModel * _master = NULL); + StaggeredProblem(int i, EngngModel * _master=nullptr); /// Destructor. virtual ~StaggeredProblem(); StaggeredProblem(const StaggeredProblem &) = delete; @@ -148,41 +148,42 @@ class OOFEM_EXPORT StaggeredProblem : public EngngModel void setContextOutputMode(ContextOutputMode contextMode); void setUDContextOutputMode(int cStep); void setProblemMode(problemMode pmode); - virtual void setRenumberFlag(); + void setRenumberFlag() override; - virtual void solveYourself(); - virtual void solveYourselfAt(TimeStep *tStep); - virtual int forceEquationNumbering(); - virtual void updateYourself(TimeStep *tStep); - virtual void initializeYourself(TimeStep *tStep) { } - virtual int initializeAdaptive(int tStepNumber) { return 0; } - virtual void terminate(TimeStep *tStep); - virtual void doStepOutput(TimeStep *tStep); + void solveYourself() override; + void solveYourselfAt(TimeStep *tStep) override; + int forceEquationNumbering() override; + void updateYourself(TimeStep *tStep) override; + void initializeYourself(TimeStep *tStep) override { } + int initializeAdaptive(int tStepNumber) override { return 0; } + void terminate(TimeStep *tStep) override; + void doStepOutput(TimeStep *tStep) override; - virtual int instanciateYourself(DataReader *dr, InputRecord *ir, const char *outFileName, const char *desc); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void updateAttributes(MetaStep *mStep); + int instanciateYourself(DataReader &dr, InputRecord &ir, const char *outFileName, const char *desc) override; + void initializeFrom(InputRecord &ir) override; + void updateAttributes(MetaStep *mStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); - virtual void updateDomainLinks(); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + void updateDomainLinks() override; void printYourself(); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; - virtual TimeStep *giveCurrentStep(bool force = false); - virtual TimeStep *givePreviousStep(bool force = false); - virtual TimeStep *giveSolutionStepWhenIcApply(bool force = false); - virtual int giveNumberOfFirstStep(bool force = false); + TimeStep *giveCurrentStep(bool force = false) override; + TimeStep *givePreviousStep(bool force = false) override; + TimeStep *giveSolutionStepWhenIcApply(bool force = false) override; + EngngModel *giveTimeControl(); + int giveNumberOfFirstStep(bool force = false) override; - virtual TimeStep *giveNextStep(); + TimeStep *giveNextStep() override; // identification - virtual const char *giveClassName() const { return "StaggeredProblem"; } + const char *giveClassName() const override { return "StaggeredProblem"; } virtual const char *giveInputRecordName() const { return _IFT_StaggeredProblem_Name; } - virtual int useNonlocalStiffnessOption() { return 0; } + int useNonlocalStiffnessOption() override { return 0; } - virtual fMode giveFormulation() { return UNKNOWN; } + fMode giveFormulation() override { return UNKNOWN; } /** * Returns time function for time step increment. * Used time function should provide step lengths as function of step number. @@ -204,17 +205,17 @@ class OOFEM_EXPORT StaggeredProblem : public EngngModel void giveCoupledModels(IntArray &answer) { answer = coupledModels; } #ifdef __OOFEG - virtual void drawYourself(oofegGraphicContext &gc); - virtual void drawElements(oofegGraphicContext &gc); - virtual void drawNodes(oofegGraphicContext &gc); - virtual void showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep) { } + void drawYourself(oofegGraphicContext &gc) override; + void drawElements(oofegGraphicContext &gc) override; + void drawNodes(oofegGraphicContext &gc) override; + void showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep) override { } #endif - virtual int checkProblemConsistency(); + int checkProblemConsistency() override; - virtual EngngModel *giveSlaveProblem(int i); - virtual int giveNumberOfSlaveProblems() { return (int)inputStreamNames.size(); } - virtual int instanciateDefaultMetaStep(InputRecord *ir); + EngngModel *giveSlaveProblem(int i) override; + int giveNumberOfSlaveProblems() override { return (int)inputStreamNames.size(); } + int instanciateDefaultMetaStep(InputRecord &ir) override; protected: int instanciateSlaveProblems(); diff --git a/src/oofemlib/staggeredsolver.C b/src/oofemlib/staggeredsolver.C index 2f0944f9f..35be9ff5e 100644 --- a/src/oofemlib/staggeredsolver.C +++ b/src/oofemlib/staggeredsolver.C @@ -76,15 +76,10 @@ StaggeredSolver :: StaggeredSolver(Domain *d, EngngModel *m) : NRSolver(d, m) } -IRResultType -StaggeredSolver :: initializeFrom(InputRecord *ir) +void +StaggeredSolver :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = NRSolver ::initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + NRSolver ::initializeFrom(ir); IR_GIVE_FIELD(ir, this->totalIdList, _IFT_StaggeredSolver_DofIdList); IR_GIVE_FIELD(ir, this->idPos, _IFT_StaggeredSolver_DofIdListPositions); @@ -100,7 +95,6 @@ StaggeredSolver :: initializeFrom(InputRecord *ir) } this->UnknownNumberingSchemeList[i].setDofIdArray(idList); } - return IRRT_OK; } @@ -213,7 +207,7 @@ StaggeredSolver :: solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, OOFEM_LOG_INFO("\nSolving for dof group %d \n", dG+1); engngModel->updateComponent(tStep, NonLinearLhs, domain); - dg.stiffnessMatrixList[dG].reset(k.giveSubMatrix( dg.locArrayList[dG], dg.locArrayList[dG])); + dg.stiffnessMatrixList[dG] = k.giveSubMatrix( dg.locArrayList[dG], dg.locArrayList[dG]); if ( this->prescribedDofsFlag ) { if ( !prescribedEqsInitFlag ) { @@ -258,7 +252,7 @@ StaggeredSolver :: solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, if ( nite > 0 || !mCalcStiffBeforeRes ) { if ( NR_Mode == nrsolverFullNRM || ( NR_Mode == nrsolverAccelNRM && (nite % MANRMSteps) == 0 ) ) { engngModel->updateComponent(tStep, NonLinearLhs, domain); - dg.stiffnessMatrixList[dG].reset(k.giveSubMatrix( dg.locArrayList[dG], dg.locArrayList[dG])); + dg.stiffnessMatrixList[dG] = k.giveSubMatrix( dg.locArrayList[dG], dg.locArrayList[dG]); applyConstraintsToStiffness(*dg.stiffnessMatrixList[dG]); } } diff --git a/src/oofemlib/staggeredsolver.h b/src/oofemlib/staggeredsolver.h index 192721b7c..c7790f089 100644 --- a/src/oofemlib/staggeredsolver.h +++ b/src/oofemlib/staggeredsolver.h @@ -70,12 +70,12 @@ class CustomEquationNumbering : public UnknownNumberingScheme CustomEquationNumbering(); IntArray dofIdArray; // should be private - virtual bool isDefault() const { return true; } + bool isDefault() const override { return true; } void setDofIdArray(IntArray array) { this->dofIdArray = std::move(array); } - virtual int giveDofEquationNumber(Dof *dof) const; + int giveDofEquationNumber(Dof *dof) const override; - virtual int giveRequiredNumberOfDomainEquation() const { return numEqs; } + int giveRequiredNumberOfDomainEquation() const override { return numEqs; } int giveNewEquationNumber() { return ++numEqs; } int giveNewPrescribedEquationNumber() { return ++numPresEqs; } @@ -121,15 +121,15 @@ class OOFEM_EXPORT StaggeredSolver : public NRSolver virtual ~StaggeredSolver() {} // Overloaded methods: - virtual NM_Status solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, - FloatArray &X, FloatArray &dX, FloatArray &F, - const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm, - int &nite, TimeStep *); - - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual const char *giveClassName() const { return "StaggeredSolver"; } - virtual const char *giveInputRecordName() const { return _IFT_StaggeredSolver_Name; } + NM_Status solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, + FloatArray &X, FloatArray &dX, FloatArray &F, + const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm, + int &nite, TimeStep *) override; + + void initializeFrom(InputRecord &ir) override; + + const char *giveClassName() const override { return "StaggeredSolver"; } + const char *giveInputRecordName() const override { return _IFT_StaggeredSolver_Name; } }; } // end namespace oofem #endif // staggeredsolver_h diff --git a/src/oofemlib/subdivision.C b/src/oofemlib/subdivision.C index ed1185889..38dc8eb30 100644 --- a/src/oofemlib/subdivision.C +++ b/src/oofemlib/subdivision.C @@ -68,6 +68,9 @@ #endif namespace oofem { + +REGISTER_Mesher(Subdivision, MPT_SUBDIVISION); + //#define __VERBOSE_PARALLEL #define DEBUG_CHECK //#define DEBUG_INFO @@ -107,14 +110,12 @@ namespace oofem { int Subdivision :: RS_Node :: buildTopLevelNodeConnectivity(ConnectivityTable *ct) { IntArray me(1), connElems; - int i, el; me.at(1) = this->giveNumber(); ct->giveNodeNeighbourList(connElems, me); this->connectedElements.preallocate( connElems.giveSize() ); // estimate size of the list - for ( i = 1; i <= connElems.giveSize(); i++ ) { - el = connElems.at(i); + for ( int el : connElems ) { #ifdef __PARALLEL_MODE if ( this->mesh->giveElement(el)->giveParallelMode() != Element_local ) { @@ -126,23 +127,20 @@ int Subdivision :: RS_Node :: buildTopLevelNodeConnectivity(ConnectivityTable *c this->mesh->giveElement(el)->buildTopLevelNodeConnectivity(this); } - return ( connectedElements.giveSize() ); + return connectedElements.giveSize(); } void Subdivision :: RS_Element :: buildTopLevelNodeConnectivity(Subdivision :: RS_Node *node) { - int el, i; - Subdivision :: RS_Element *elem; - if ( this->isTerminal() ) { node->insertConnectedElement( this->giveNumber() ); return; } - for ( el = 1; el <= this->giveChildren()->giveSize(); el++ ) { - elem = mesh->giveElement( this->giveChildren()->at(el) ); - for ( i = 1; i <= elem->giveNodes()->giveSize(); i++ ) { + for ( int el = 1; el <= this->giveChildren()->giveSize(); el++ ) { + Subdivision::RS_Element *elem = mesh->giveElement( this->giveChildren()->at(el) ); + for ( int i = 1; i <= elem->giveNodes()->giveSize(); i++ ) { if ( elem->giveNode(i) == node->giveNumber() ) { elem->buildTopLevelNodeConnectivity(node); break; @@ -158,14 +156,13 @@ int Subdivision :: RS_Node :: importConnectivity(ConnectivityTable *ct) { IntArray me(1), connElems; - int i, el, cnt = 0; + int cnt = 0; me.at(1) = this->giveNumber(); ct->giveNodeNeighbourList(connElems, me); this->connectedElements.preallocate( connElems.giveSize() ); // estimate size of the list - for ( i = 1; i <= connElems.giveSize(); i++ ) { - el = connElems.at(i); + for ( int el : connElems ) { if ( this->mesh->giveElement(el)->giveParallelMode() != Element_local ) { continue; } @@ -175,7 +172,7 @@ Subdivision :: RS_Node :: importConnectivity(ConnectivityTable *ct) cnt++; } - return ( cnt ); + return cnt; } @@ -183,12 +180,12 @@ Subdivision :: RS_Node :: importConnectivity(ConnectivityTable *ct) void Subdivision :: RS_Node :: numberSharedEdges() { - int ie, num = this->giveNumber(); + int num = this->giveNumber(); IntArray connNodes; - const IntArray *connElems = this->giveConnectedElements(); + const IntArray &connElems = *this->giveConnectedElements(); - for ( ie = 1; ie <= connElems->giveSize(); ie++ ) { - this->mesh->giveElement( connElems->at(ie) )->numberSharedEdges(num, connNodes); + for ( int el : connElems ) { + this->mesh->giveElement( el )->numberSharedEdges(num, connNodes); } } @@ -196,11 +193,9 @@ Subdivision :: RS_Node :: numberSharedEdges() void Subdivision :: RS_Triangle :: numberSharedEdges(int iNode, IntArray &connNodes) { - int eIndex, jnode, jNode, eNum = this->mesh->giveNumberOfEdges(); - Subdivision :: RS_SharedEdge *_edge; + int eNum = this->mesh->giveNumberOfEdges(); - for ( jnode = 1; jnode <= 3; jnode++ ) { - jNode = nodes.at(jnode); + for ( int jNode : nodes ) { if ( jNode == iNode ) { continue; } @@ -217,7 +212,7 @@ Subdivision :: RS_Triangle :: numberSharedEdges(int iNode, IntArray &connNodes) connNodes.followedBy(jNode, 10); - eIndex = giveEdgeIndex(iNode, jNode); + int eIndex = giveEdgeIndex(iNode, jNode); if ( shared_edges.giveSize() ) { if ( shared_edges.at(eIndex) ) { @@ -226,7 +221,7 @@ Subdivision :: RS_Triangle :: numberSharedEdges(int iNode, IntArray &connNodes) } // create edge (even if it might not be shared) - _edge = new Subdivision :: RS_SharedEdge(this->mesh); + Subdivision :: RS_SharedEdge *_edge = new Subdivision :: RS_SharedEdge(this->mesh); _edge->setEdgeNodes(iNode, jNode); this->mesh->addEdge(_edge); @@ -252,12 +247,9 @@ Subdivision :: RS_Triangle :: numberSharedEdges(int iNode, IntArray &connNodes) void Subdivision :: RS_Tetra :: numberSharedEdges(int iNode, IntArray &connNodes) { - int ie, elems, eIndex, jnode, jNode, eNum = this->mesh->giveNumberOfEdges(); - Subdivision :: RS_SharedEdge *_edge; - Subdivision :: RS_Element *elem; + int eNum = this->mesh->giveNumberOfEdges(); - for ( jnode = 1; jnode <= 4; jnode++ ) { - jNode = nodes.at(jnode); + for ( int jNode : nodes ) { if ( jNode == iNode ) { continue; } @@ -274,7 +266,7 @@ Subdivision :: RS_Tetra :: numberSharedEdges(int iNode, IntArray &connNodes) connNodes.followedBy(jNode, 20); - eIndex = giveEdgeIndex(iNode, jNode); + int eIndex = giveEdgeIndex(iNode, jNode); if ( shared_edges.giveSize() ) { if ( shared_edges.at(eIndex) ) { @@ -283,7 +275,7 @@ Subdivision :: RS_Tetra :: numberSharedEdges(int iNode, IntArray &connNodes) } // create edge (even if it might not be shared) - _edge = new Subdivision :: RS_SharedEdge(this->mesh); + Subdivision :: RS_SharedEdge *_edge = new Subdivision :: RS_SharedEdge(this->mesh); _edge->setEdgeNodes(iNode, jNode); this->mesh->addEdge(_edge); @@ -315,15 +307,15 @@ Subdivision :: RS_Tetra :: numberSharedEdges(int iNode, IntArray &connNodes) // I do rely on the fact that the arrays are ordered !!! // I am using zero chunk because common is large enough - elems = iElems->findCommonValuesSorted(* jElems, common, 0); + int elems = iElems->findCommonValuesSorted(* jElems, common, 0); #ifdef DEBUG_CHECK if ( !elems ) { OOFEM_ERROR("potentionally shared edge %d is not shared by common elements", eNum); } #endif - for ( ie = 1; ie <= elems; ie++ ) { - elem = mesh->giveElement( common.at(ie) ); + for ( int ie = 1; ie <= elems; ie++ ) { + Subdivision :: RS_Element *elem = mesh->giveElement( common.at(ie) ); if ( elem == this ) { continue; } @@ -390,7 +382,7 @@ Subdivision :: RS_Element :: giveTopParent() elem = mesh->giveElement( elem->giveParent() ); } - return ( elem->giveNumber() ); + return elem->giveNumber(); } @@ -436,9 +428,9 @@ Subdivision :: RS_Triangle :: evaluateLongestEdge() if ( !this->leIndex ) { // prevent multiple evaluation double elength1, elength2, elength3; - elength1 = mesh->giveNode( this->nodes.at(1) )->giveCoordinates()->distance_square( * ( mesh->giveNode( this->nodes.at(2) )->giveCoordinates() ) ); - elength2 = mesh->giveNode( this->nodes.at(2) )->giveCoordinates()->distance_square( * ( mesh->giveNode( this->nodes.at(3) )->giveCoordinates() ) ); - elength3 = mesh->giveNode( this->nodes.at(3) )->giveCoordinates()->distance_square( * ( mesh->giveNode( this->nodes.at(1) )->giveCoordinates() ) ); + elength1 = distance_square( *mesh->giveNode( this->nodes.at(1) )->giveCoordinates(), * ( mesh->giveNode( this->nodes.at(2) )->giveCoordinates() ) ); + elength2 = distance_square( *mesh->giveNode( this->nodes.at(2) )->giveCoordinates(), * ( mesh->giveNode( this->nodes.at(3) )->giveCoordinates() ) ); + elength3 = distance_square( *mesh->giveNode( this->nodes.at(3) )->giveCoordinates(), * ( mesh->giveNode( this->nodes.at(1) )->giveCoordinates() ) ); leIndex = 1; if ( elength2 > elength1 ) { @@ -533,12 +525,12 @@ Subdivision :: RS_Tetra :: evaluateLongestEdge() ind [ 5 ] = ed [ nd [ 2 ] ] [ nd [ 3 ] ]; // evaluate edge lengths from smallest node id !!! - elength [ 0 ] = mesh->giveNode(l_nd [ 0 ])->giveCoordinates()->distance_square( * ( mesh->giveNode(l_nd [ 1 ])->giveCoordinates() ) ); - elength [ 1 ] = mesh->giveNode(l_nd [ 0 ])->giveCoordinates()->distance_square( * ( mesh->giveNode(l_nd [ 2 ])->giveCoordinates() ) ); - elength [ 2 ] = mesh->giveNode(l_nd [ 0 ])->giveCoordinates()->distance_square( * ( mesh->giveNode(l_nd [ 3 ])->giveCoordinates() ) ); - elength [ 3 ] = mesh->giveNode(l_nd [ 1 ])->giveCoordinates()->distance_square( * ( mesh->giveNode(l_nd [ 2 ])->giveCoordinates() ) ); - elength [ 4 ] = mesh->giveNode(l_nd [ 1 ])->giveCoordinates()->distance_square( * ( mesh->giveNode(l_nd [ 3 ])->giveCoordinates() ) ); - elength [ 5 ] = mesh->giveNode(l_nd [ 2 ])->giveCoordinates()->distance_square( * ( mesh->giveNode(l_nd [ 3 ])->giveCoordinates() ) ); + elength [ 0 ] = distance_square( *mesh->giveNode(l_nd [ 0 ])->giveCoordinates(), * ( mesh->giveNode(l_nd [ 1 ])->giveCoordinates() ) ); + elength [ 1 ] = distance_square( *mesh->giveNode(l_nd [ 0 ])->giveCoordinates(), * ( mesh->giveNode(l_nd [ 2 ])->giveCoordinates() ) ); + elength [ 2 ] = distance_square( *mesh->giveNode(l_nd [ 0 ])->giveCoordinates(), * ( mesh->giveNode(l_nd [ 3 ])->giveCoordinates() ) ); + elength [ 3 ] = distance_square( *mesh->giveNode(l_nd [ 1 ])->giveCoordinates(), * ( mesh->giveNode(l_nd [ 2 ])->giveCoordinates() ) ); + elength [ 4 ] = distance_square( *mesh->giveNode(l_nd [ 1 ])->giveCoordinates(), * ( mesh->giveNode(l_nd [ 3 ])->giveCoordinates() ) ); + elength [ 5 ] = distance_square( *mesh->giveNode(l_nd [ 2 ])->giveCoordinates(), * ( mesh->giveNode(l_nd [ 3 ])->giveCoordinates() ) ); // get absolutely largest edge and the largest edge on individual sides // process edges in the same order in which their length was evaluated !!! @@ -3412,7 +3404,7 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D // all nodes (including remote which are not needed) are imported to ensure consistency between // node number (in the mesh) and its parent number (in the domain) because the domain is used to import connectivities for ( int i = 1; i <= nnodes; i++ ) { - _node = new Subdivision :: RS_Node( i, mesh, i, * ( domain->giveNode ( i )->giveCoordinates() ), + _node = new Subdivision :: RS_Node( i, mesh, i, domain->giveNode ( i )->giveCoordinates(), domain->giveErrorEstimator ( )->giveRemeshingCrit ( )->giveRequiredDofManDensity ( i, tStep ), domain->giveNode ( i )->isBoundary() ); _node->setGlobalNumber( domain->giveNode(i)->giveGlobalNumber() ); @@ -3545,20 +3537,12 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D mesh->giveElement(i)->drawGeometry(); } - ESIEventLoop(YES, "After bisection; Press Ctrl-p to continue"); + ESIEventLoop(YES, (char*) "After bisection; Press Ctrl-p to continue"); #endif #endif Dof *dof; - DofManager *parentNodePtr, *node; - Element *elem; - CrossSection *crossSection; - Material *mat; - NonlocalBarrier *barrier; - GeneralBoundaryCondition *bc; - InitialCondition *ic; - Function *func; - Set *set; + DofManager *parentNodePtr; std :: string name; // create new mesh (missing param for new mesh!) @@ -3570,11 +3554,13 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D ( * dNew )->resizeDofManagers(nnodes); const IntArray dofIDArrayPtr = domain->giveDefaultNodeDofIDArry(); for ( int inode = 1; inode <= nnodes; inode++ ) { + std::unique_ptr newNode; parent = mesh->giveNode(inode)->giveParent(); if ( parent ) { parentNodePtr = domain->giveNode(parent); // inherit all data from parent (bc, ic, load, etc.) - node = classFactory.createDofManager(parentNodePtr->giveInputRecordName(), inode, * dNew); + newNode = classFactory.createDofManager(parentNodePtr->giveInputRecordName(), inode, * dNew); + auto node = newNode.get(); node->setNumberOfDofs(0); node->setLoadArray( * parentNodePtr->giveLoadArray() ); // create individual DOFs @@ -3587,7 +3573,7 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D dof = new SimpleSlaveDof( node, simpleSlaveDofPtr->giveMasterDofManagerNum(), idofPtr->giveDofID() ); } else { OOFEM_ERROR("unsupported DOF type"); - dof = NULL; + dof = nullptr; } } node->appendDof(dof); @@ -3600,7 +3586,8 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D #endif } else { // newly created node (irregular) - node = new Node(inode, *dNew); + newNode = std::make_unique(inode, *dNew); + auto node = newNode.get(); //create new node with default DOFs int ndofs = dofIDArrayPtr.giveSize(); node->setNumberOfDofs(0); @@ -3608,7 +3595,7 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D // create individual DOFs for ( int idof = 1; idof <= ndofs; idof++ ) { #ifdef NM - dof = NULL; + dof = nullptr; FloatArray *coords = mesh->giveNode(inode)->giveCoordinates(); if ( !dof ) { if ( fabs(coords->at(1) - 200.0) < 0.000001 ) { @@ -3646,7 +3633,7 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D #else #ifdef BRAZIL_2D - dof = NULL; + dof = nullptr; FloatArray *coords = mesh->giveNode(inode)->giveCoordinates(); if ( !dof ) { if ( fabs( coords->at(1) ) < 0.000001 ) { @@ -3674,7 +3661,7 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D #else #ifdef THREEPBT_3D - dof = NULL; + dof = nullptr; FloatArray *coords = mesh->giveNode(inode)->giveCoordinates(); if ( !dof ) { if ( fabs( coords->at(1) ) < 0.000001 ) { @@ -3709,7 +3696,7 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D double dist, rad; FloatArray *coords = mesh->giveNode(inode)->giveCoordinates(); - dof = NULL; + dof = nullptr; if ( !dof ) { dist = coords->at(1) * coords->at(1) + coords->at(3) * coords->at(3); if ( coords->at(2) < 88.000001 ) { @@ -3770,9 +3757,9 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D } // set node coordinates - static_cast< Node * >(node)->setCoordinates( * mesh->giveNode(inode)->giveCoordinates() ); - node->setBoundaryFlag( mesh->giveNode(inode)->isBoundary() ); - ( * dNew )->setDofManager(inode, node); + static_cast< Node * >(newNode.get())->setCoordinates( * mesh->giveNode(inode)->giveCoordinates() ); + newNode->setBoundaryFlag( mesh->giveNode(inode)->isBoundary() ); + ( * dNew )->setDofManager(inode, std::move(newNode)); } // end creating dof managers // create elements @@ -3817,15 +3804,15 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D DynamicInputRecord ir( *domain->giveElement ( parent ) ); ir.setField(* mesh->giveElement(ielem)->giveNodes(), _IFT_Element_nodes); ir.giveRecordKeywordField(name); - elem = classFactory.createElement(name.c_str(), eNum, * dNew); - elem->initializeFrom(& ir); + auto elem = classFactory.createElement(name.c_str(), eNum, * dNew); + elem->initializeFrom(ir); elem->setGlobalNumber( mesh->giveElement(ielem)->giveGlobalNumber() ); #ifdef __PARALLEL_MODE //ir.setRecordKeywordNumber( mesh->giveElement(ielem)->giveGlobalNumber() ); // not subdivided elements inherit globNum, subdivided give -1 // local elements have array partitions empty ! #endif - ( * dNew )->setElement(eNum, elem); + ( * dNew )->setElement(eNum, std::move(elem)); } else { OOFEM_ERROR("parent element missing"); } @@ -3839,9 +3826,9 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D DynamicInputRecord ir( *domain->giveCrossSection ( i ) ); ir.giveRecordKeywordField(name); - crossSection = classFactory.createCrossSection(name.c_str(), i, * dNew); - crossSection->initializeFrom(& ir); - ( * dNew )->setCrossSection(i, crossSection); + auto crossSection = classFactory.createCrossSection(name.c_str(), i, * dNew); + crossSection->initializeFrom(ir); + ( * dNew )->setCrossSection(i, std::move(crossSection)); } // materials @@ -3851,9 +3838,9 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D DynamicInputRecord ir( *domain->giveMaterial ( i ) ); ir.giveRecordKeywordField(name); - mat = classFactory.createMaterial(name.c_str(), i, * dNew); - mat->initializeFrom(& ir); - ( * dNew )->setMaterial(i, mat); + auto mat = classFactory.createMaterial(name.c_str(), i, * dNew); + mat->initializeFrom(ir); + ( * dNew )->setMaterial(i, std::move(mat)); } // barriers @@ -3862,10 +3849,10 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D for ( int i = 1; i <= nbarriers; i++ ) { DynamicInputRecord ir( *domain->giveNonlocalBarrier ( i ) ); ir.giveRecordKeywordField(name); - - barrier = classFactory.createNonlocalBarrier(name.c_str(), i, * dNew); - barrier->initializeFrom(& ir); - ( * dNew )->setNonlocalBarrier(i, barrier); + + auto barrier = classFactory.createNonlocalBarrier(name.c_str(), i, * dNew); + barrier->initializeFrom(ir); + ( * dNew )->setNonlocalBarrier(i, std::move(barrier)); } // boundary conditions @@ -3875,10 +3862,9 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D DynamicInputRecord ir( *domain->giveBc ( i ) ); ir.giveRecordKeywordField(name); - - bc = classFactory.createBoundaryCondition(name.c_str(), i, * dNew); - bc->initializeFrom(& ir); - ( * dNew )->setBoundaryCondition(i, bc); + auto bc = classFactory.createBoundaryCondition(name.c_str(), i, * dNew); + bc->initializeFrom(ir); + ( * dNew )->setBoundaryCondition(i, std::move(bc)); } // initial conditions @@ -3887,9 +3873,9 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D for ( int i = 1; i <= nic; i++ ) { DynamicInputRecord ir( *domain->giveIc ( i ) ); - ic = new InitialCondition(i, *dNew); - ic->initializeFrom(& ir); - ( * dNew )->setInitialCondition(i, ic); + auto ic = std::make_unique(i, *dNew); + ic->initializeFrom(ir); + ( * dNew )->setInitialCondition(i, std::move(ic)); } // load time functions @@ -3899,9 +3885,9 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D DynamicInputRecord ir( *domain->giveFunction ( i ) ); ir.giveRecordKeywordField(name); - func = classFactory.createFunction(name.c_str(), i, * dNew); - func->initializeFrom(& ir); - ( * dNew )->setFunction(i, func); + auto func = classFactory.createFunction(name.c_str(), i, * dNew); + func->initializeFrom(ir); + ( * dNew )->setFunction(i, std::move(func)); } // sets @@ -3911,11 +3897,10 @@ Subdivision :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, D DynamicInputRecord ir( *domain->giveSet ( i ) ); ir.giveRecordKeywordField(name); - set = new Set(i, * dNew); - set->initializeFrom(& ir); - ( * dNew )->setSet(i, set); + auto set = std::make_unique(i, * dNew); + set->initializeFrom(ir); + ( * dNew )->setSet(i, std::move(set)); } - // post initialize components ( * dNew )->postInitialize(); @@ -4765,15 +4750,14 @@ Subdivision :: assignGlobalNumbersToElements(Domain *d) #else // local case - int i, nelems, numberOfLocalElementsToNumber = 0; + int numberOfLocalElementsToNumber = 0; int localMaxGlobnum = 0; // idea: first determine the number of local elements waiting for new global id // and also determine max global number assigned up to now - nelems = d->giveNumberOfElements(); - for ( i = 1; i <= nelems; i++ ) { - localMaxGlobnum = max( localMaxGlobnum, d->giveElement(i)->giveGlobalNumber() ); - if ( d->giveElement(i)->giveGlobalNumber() <= 0 ) { + for ( auto &elem : d->giveElements() ) { + localMaxGlobnum = max( localMaxGlobnum, elem->giveGlobalNumber() ); + if ( elem->giveGlobalNumber() <= 0 ) { numberOfLocalElementsToNumber++; } } @@ -4783,9 +4767,9 @@ Subdivision :: assignGlobalNumbersToElements(Domain *d) // lets assign global numbers on each partition to local elements availGlobNum = startOffset; - for ( i = 1; i <= nelems; i++ ) { - if ( d->giveElement(i)->giveGlobalNumber() <= 0 ) { - d->giveElement(i)->setGlobalNumber(++availGlobNum); + for ( auto &elem : d->giveElements() ) { + if ( elem->giveGlobalNumber() <= 0 ) { + elem->setGlobalNumber(++availGlobNum); } } @@ -4835,10 +4819,8 @@ Subdivision :: exchangeSharedIrregulars() int Subdivision :: packSharedIrregulars(Subdivision *s, ProcessCommunicator &pc) { - int pi, iNode, jNode, rproc = pc.giveRank(); + int rproc = pc.giveRank(); int myrank = this->giveRank(); - const IntArray *sharedPartitions; - std :: list< int > :: const_iterator sharedIrregQueueIter; IntArray edgeInfo(2); if ( rproc == myrank ) { @@ -4847,16 +4829,14 @@ Subdivision :: packSharedIrregulars(Subdivision *s, ProcessCommunicator &pc) // query process communicator to use ProcessCommunicatorBuff *pcbuff = pc.giveProcessCommunicatorBuff(); - for ( sharedIrregQueueIter = sharedIrregularsQueue.begin(); - sharedIrregQueueIter != sharedIrregularsQueue.end(); - sharedIrregQueueIter++ ) { - pi = ( * sharedIrregQueueIter ); - sharedPartitions = this->mesh->giveNode(pi)->givePartitions(); + for ( int pi : sharedIrregularsQueue ) { + const IntArray *sharedPartitions = this->mesh->giveNode(pi)->givePartitions(); if ( sharedPartitions->contains(rproc) ) { // the info about new local shared irregular node needs to be sent to remote partition // the new irregular on remote partition is identified using two nodes (glonums) defining // an edge on which irregular node is introduced - ( ( RS_IrregularNode * ) this->mesh->giveNode(pi) )->giveEdgeNodes(iNode, jNode); + int iNode, jNode; + static_cast< RS_IrregularNode * >( this->mesh->giveNode(pi) )->giveEdgeNodes(iNode, jNode); edgeInfo.at(1) = this->mesh->giveNode(iNode)->giveGlobalNumber(); edgeInfo.at(2) = this->mesh->giveNode(jNode)->giveGlobalNumber(); pcbuff->write(SUBDIVISION_SHARED_IRREGULAR_REC_TAG); @@ -4927,7 +4907,7 @@ Subdivision :: unpackSharedIrregulars(Subdivision *s, ProcessCommunicator &pc) // get type of the next record pcbuff->read(_type); continue; - } + } #else if ( !elems ) { OOFEM_ERROR("[%d] no element found sharing nodes %d[%d] and %d[%d]", @@ -5320,16 +5300,16 @@ Subdivision :: exchangeRemoteElements(Domain *d, IntArray &parentMap) com.initExchange(SUBDIVISION_MIGRATE_REMOTE_ELEMENTS_TAG); // remove existing remote elements and null nodes - int i, nelem = d->giveNumberOfElements(); + int nelem = d->giveNumberOfElements(); int nnodes = d->giveNumberOfDofManagers(); DomainTransactionManager *dtm = d->giveTransactionManager(); - for ( i = 1; i <= nnodes; i++ ) { + for ( int i = 1; i <= nnodes; i++ ) { if ( d->giveDofManager(i)->giveParallelMode() == DofManager_null ) { dtm->addDofManTransaction(DomainTransactionManager :: DTT_Remove, d->giveDofManager(i)->giveGlobalNumber(), NULL); } } - for ( i = 1; i <= nelem; i++ ) { + for ( int i = 1; i <= nelem; i++ ) { if ( d->giveElement(i)->giveParallelMode() == Element_remote ) { dtm->addElementTransaction(DomainTransactionManager :: DTT_Remove, d->giveElement(i)->giveGlobalNumber(), NULL); } @@ -5345,11 +5325,7 @@ Subdivision :: packRemoteElements(RS_packRemoteElemsStruct *s, ProcessCommunicat { Domain *d = s->d; int rproc = pc.giveRank(); - int i, inode; - int nn, in; int myrank = this->giveRank(); - DofManager *inodePtr; - Element *elemPtr, *relemPtr; std :: queue< int >elemCandidates; std :: set< int >remoteElements, processedElements, nodesToSend; @@ -5359,7 +5335,7 @@ Subdivision :: packRemoteElements(RS_packRemoteElemsStruct *s, ProcessCommunicat EngngModel *emodel = d->giveEngngModel(); // comMap refers to original (parent) elements - const IntArray *comMap = emodel->giveProblemCommunicator(EngngModel :: PC_nonlocal)->giveProcessCommunicator(rproc)->giveToSendMap(); + const IntArray &comMap = emodel->giveProblemCommunicator(EngngModel :: PC_nonlocal)->giveProcessCommunicator(rproc)->giveToSendMap(); #ifdef __OOFEG #ifdef DRAW_REMOTE_ELEMENTS oofegGraphicContext gc; @@ -5367,9 +5343,9 @@ Subdivision :: packRemoteElements(RS_packRemoteElemsStruct *s, ProcessCommunicat gc.setElementColor( gc.getActiveCrackColor() ); #endif #endif - for ( i = 1; i <= d->giveNumberOfElements(); i++ ) { + for ( int i = 1; i <= d->giveNumberOfElements(); i++ ) { // remote parent skipped - parentElemMap has zero value for them - if ( comMap->contains( s->parentElemMap->at(i) ) ) { + if ( comMap.contains( s->parentElemMap->at(i) ) ) { remoteElements.insert(i); #ifdef __OOFEG #ifdef DRAW_REMOTE_ELEMENTS @@ -5395,10 +5371,10 @@ Subdivision :: packRemoteElements(RS_packRemoteElemsStruct *s, ProcessCommunicat * loop over elements in remoteElements set and add all their nodes (except those that are shared) */ for ( int elNum: remoteElements ) { - relemPtr = d->giveElement(elNum); - nn = relemPtr->giveNumberOfNodes(); - for ( in = 1; in <= nn; in++ ) { - inode = relemPtr->giveDofManagerNumber(in); + Element *relemPtr = d->giveElement(elNum); + int nn = relemPtr->giveNumberOfNodes(); + for ( int in = 1; in <= nn; in++ ) { + int inode = relemPtr->giveDofManagerNumber(in); if ( ( d->giveDofManager(inode)->giveParallelMode() == DofManager_local ) || ( ( d->giveDofManager(inode)->giveParallelMode() == DofManager_shared ) && ( !d->giveDofManager(inode)->givePartitionList()->contains(rproc) ) ) ) { // nodesToSend is set, therefore duplicity is avoided @@ -5413,7 +5389,7 @@ Subdivision :: packRemoteElements(RS_packRemoteElemsStruct *s, ProcessCommunicat ProcessCommunicatorBuff *pcbuff = pc.giveProcessCommunicatorBuff(); // send nodes that define remote_elements gometry for ( int nodeNum: nodesToSend ) { - inodePtr = d->giveDofManager(nodeNum); + DofManager *inodePtr = d->giveDofManager(nodeNum); pcbuff->write( inodePtr->giveInputRecordName() ); pcbuff->write( inodePtr->giveGlobalNumber() ); @@ -5425,7 +5401,7 @@ Subdivision :: packRemoteElements(RS_packRemoteElemsStruct *s, ProcessCommunicat // send elements for ( int elNum: remoteElements ) { - elemPtr = d->giveElement(elNum); + Element *elemPtr = d->giveElement(elNum); // pack local element (node numbers shuld be global ones!!!) // pack type pcbuff->write( elemPtr->giveInputRecordName() ); @@ -5472,7 +5448,7 @@ Subdivision :: unpackRemoteElements(Domain *d, ProcessCommunicator &pc) if ( ( dofman = dtm->giveDofManager(_globnum) ) == NULL ) { // data not available -> create a new one _newentry = true; - dofman = classFactory.createDofManager(_type.c_str(), 0, d); + dofman = classFactory.createDofManager(_type.c_str(), 0, d).release(); ///@todo Can we do better than this unsafe code? } dofman->setGlobalNumber(_globnum); @@ -5495,7 +5471,7 @@ Subdivision :: unpackRemoteElements(Domain *d, ProcessCommunicator &pc) break; } - Element *elem = classFactory.createElement(_type.c_str(), 0, d); + Element *elem = classFactory.createElement(_type.c_str(), 0, d).release(); ///@todo Can we do etter than this unsafe code? elem->restoreContext(*pcbuff, CM_Definition | CM_DefinitionGlobal); elem->setParallelMode(Element_remote); elem->setPartitionList(elemPartitions); @@ -5517,8 +5493,7 @@ Subdivision :: unpackRemoteElements(Domain *d, ProcessCommunicator &pc) void Subdivision :: exchangeSharedEdges() { - int i, pi, iNode, jNode, elems; - std :: list< int > :: const_iterator sharedEdgeQueueIter; + int iNode, jNode, elems; Subdivision :: RS_SharedEdge *edge; Subdivision :: RS_Element *elem; const IntArray *iElems, *jElems; @@ -5547,11 +5522,7 @@ Subdivision :: exchangeSharedEdges() com.packAllData(this, this, & Subdivision :: packSharedEdges); // remove all tentative partitions on queued shared edges after packing relevant data - for ( sharedEdgeQueueIter = sharedEdgesQueue.begin(); - sharedEdgeQueueIter != sharedEdgesQueue.end(); - sharedEdgeQueueIter++ ) { - pi = ( * sharedEdgeQueueIter ); - + for ( int pi : sharedEdgesQueue ) { edge = mesh->giveEdge(pi); edge->removePartitions(); } @@ -5561,10 +5532,7 @@ Subdivision :: exchangeSharedEdges() com.finishExchange(); // unmark unshared edges from elements after unpacking data and before clearing the queue - for ( sharedEdgeQueueIter = sharedEdgesQueue.begin(); - sharedEdgeQueueIter != sharedEdgesQueue.end(); - sharedEdgeQueueIter++ ) { - pi = ( * sharedEdgeQueueIter ); + for ( int pi : sharedEdgesQueue ) { edge = mesh->giveEdge(pi); if ( edge->givePartitions()->giveSize() ) { @@ -5596,7 +5564,7 @@ Subdivision :: exchangeSharedEdges() } #endif - for ( i = 1; i <= elems; i++ ) { + for ( int i = 1; i <= elems; i++ ) { elem = mesh->giveElement( common.at(i) ); #ifdef DEBUG_CHECK if ( !elem->giveSharedEdges()->giveSize() ) { @@ -5618,10 +5586,8 @@ Subdivision :: exchangeSharedEdges() int Subdivision :: packSharedEdges(Subdivision *s, ProcessCommunicator &pc) { - int pi, iNode, jNode, rproc = pc.giveRank(); + int rproc = pc.giveRank(); int myrank = this->giveRank(); - const IntArray *sharedPartitions; - std :: list< int > :: const_iterator sharedEdgeQueueIter; IntArray edgeInfo(2); if ( rproc == myrank ) { @@ -5630,13 +5596,11 @@ Subdivision :: packSharedEdges(Subdivision *s, ProcessCommunicator &pc) // query process communicator to use ProcessCommunicatorBuff *pcbuff = pc.giveProcessCommunicatorBuff(); - for ( sharedEdgeQueueIter = sharedEdgesQueue.begin(); - sharedEdgeQueueIter != sharedEdgesQueue.end(); - sharedEdgeQueueIter++ ) { - pi = ( * sharedEdgeQueueIter ); + for ( int pi : sharedEdgesQueue ) { - sharedPartitions = this->mesh->giveEdge(pi)->givePartitions(); + const IntArray *sharedPartitions = this->mesh->giveEdge(pi)->givePartitions(); if ( sharedPartitions->contains(rproc) ) { + int iNode, jNode; this->mesh->giveEdge(pi)->giveEdgeNodes(iNode, jNode); edgeInfo.at(1) = this->mesh->giveNode(iNode)->giveGlobalNumber(); edgeInfo.at(2) = this->mesh->giveNode(jNode)->giveGlobalNumber(); @@ -5662,7 +5626,6 @@ Subdivision :: unpackSharedEdges(Subdivision *s, ProcessCommunicator &pc) int iNode, jNode, elems; IntArray edgeInfo(2); const IntArray *iElems, *jElems; - std :: list< int > :: const_iterator sharedEdgeQueueIter; Subdivision :: RS_SharedEdge *edge; Subdivision :: RS_Element *elem; int eIndex; @@ -5743,13 +5706,10 @@ Subdivision :: unpackSharedEdges(Subdivision *s, ProcessCommunicator &pc) } - void Subdivision :: RS_Mesh :: insertGlobalSharedNodeMap(Subdivision :: RS_Node *node) { - int key; - key = node->giveGlobalNumber(); - sharedNodeMap [ key ] = node; + sharedNodeMap [ node->giveGlobalNumber() ] = node; } @@ -5771,10 +5731,8 @@ Subdivision :: RS_Mesh :: sharedNodeGlobal2Local(int _globnum) int Subdivision :: RS_CompareNodePositions :: operator() (int i, int j) { - double icoord, jcoord; - - icoord = m->giveNode(i)->giveCoordinates()->at(1); - jcoord = m->giveNode(j)->giveCoordinates()->at(1); + double icoord = m->giveNode(i)->giveCoordinates()->at(1); + double jcoord = m->giveNode(j)->giveCoordinates()->at(1); if ( icoord < jcoord ) { return -1; diff --git a/src/oofemlib/subdivision.h b/src/oofemlib/subdivision.h index 63af74c84..b1a2ea348 100644 --- a/src/oofemlib/subdivision.h +++ b/src/oofemlib/subdivision.h @@ -47,6 +47,8 @@ #include #include +#define _IFT_Subdivision_Name "subdiv" + namespace oofem { #define SHARED_IRREGULAR_DATA_TAG 7654 @@ -93,7 +95,7 @@ class OOFEM_EXPORT Subdivision : public MesherInterface IntArray partitions; #endif public: - RS_Node(int n, Subdivision :: RS_Mesh * m, int parent, FloatArray & c, double rd, bool boundary) { + RS_Node(int n, Subdivision :: RS_Mesh * m, int parent, const FloatArray & c, double rd, bool boundary) { this->number = n; this->mesh = m; this->coords = c; @@ -151,7 +153,7 @@ class OOFEM_EXPORT Subdivision : public MesherInterface i = iNode; j = jNode; } - virtual bool isIrregular() { return true; } + bool isIrregular() override { return true; } }; class RS_Element @@ -254,17 +256,17 @@ class OOFEM_EXPORT Subdivision : public MesherInterface { public: RS_Triangle(int number, Subdivision :: RS_Mesh * mesh, int parent, IntArray & nodes); - int evaluateLongestEdge(); - void bisect(std :: queue< int > &subdivqueue, std :: list< int > &sharedIrregularsQueue); - void generate(std :: list< int > &sharedEdgesQueue); - void update_neighbours(); - double giveDensity(); - bool isNeighborOf(Subdivision :: RS_Element *elem); - void giveSideNodes(int iside, IntArray &snodes); - int giveEdgeIndex(int iNode, int jNode); - virtual void importConnectivity(ConnectivityTable *ct); + int evaluateLongestEdge() override; + void bisect(std :: queue< int > &subdivqueue, std :: list< int > &sharedIrregularsQueue) override; + void generate(std :: list< int > &sharedEdgesQueue) override; + void update_neighbours() override; + double giveDensity() override; + bool isNeighborOf(Subdivision :: RS_Element *elem) override; + void giveSideNodes(int iside, IntArray &snodes) override; + int giveEdgeIndex(int iNode, int jNode) override; + void importConnectivity(ConnectivityTable *ct) override; #ifdef __OOFEG - void drawGeometry(); + void drawGeometry() override; #endif #ifdef __PARALLEL_MODE void numberSharedEdges(int iNode, IntArray &connNodes); @@ -281,17 +283,17 @@ class OOFEM_EXPORT Subdivision : public MesherInterface IntArray side_leIndex; public: RS_Tetra(int number, Subdivision :: RS_Mesh * mesh, int parent, IntArray & nodes); - int evaluateLongestEdge(); - void bisect(std :: queue< int > &subdivqueue, std :: list< int > &sharedIrregularsQueue); - void generate(std :: list< int > &sharedEdgesQueue); - void update_neighbours(); - double giveDensity(); - bool isNeighborOf(Subdivision :: RS_Element *elem); - void giveSideNodes(int iside, IntArray &snodes); - int giveEdgeIndex(int iNode, int jNode); - virtual void importConnectivity(ConnectivityTable *ct); + int evaluateLongestEdge() override; + void bisect(std :: queue< int > &subdivqueue, std :: list< int > &sharedIrregularsQueue) override; + void generate(std :: list< int > &sharedEdgesQueue) override; + void update_neighbours() override; + double giveDensity() override; + bool isNeighborOf(Subdivision :: RS_Element *elem) override; + void giveSideNodes(int iside, IntArray &snodes) override; + int giveEdgeIndex(int iNode, int jNode) override; + void importConnectivity(ConnectivityTable *ct) override; #ifdef __OOFEG - void drawGeometry(); + void drawGeometry() override; #endif #ifdef __PARALLEL_MODE void numberSharedEdges(int iNode, IntArray &connNodes); @@ -416,7 +418,7 @@ class OOFEM_EXPORT Subdivision : public MesherInterface } /// Runs the mesh generation, mesh will be written to corresponding domain din file - virtual returnCode createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, Domain **dNew); + returnCode createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, Domain **dNew) override; const char *giveClassName() { return "Subdivision"; } Domain *giveDomain() { return domain; } diff --git a/src/oofemlib/subspaceit.C b/src/oofemlib/subspaceit.C index 42105151e..e1c1e9aa9 100644 --- a/src/oofemlib/subspaceit.C +++ b/src/oofemlib/subspaceit.C @@ -45,16 +45,15 @@ #include "classfactory.h" namespace oofem { +REGISTER_GeneralizedEigenValueSolver(SubspaceIteration, GES_SubspaceIt); + SubspaceIteration :: SubspaceIteration(Domain *d, EngngModel *m) : - SparseGeneralEigenValueSystemNM(d, m) + SparseGeneralEigenValueSystemNM(d, m), + nitem(40) { - nitem = 40; // max number of iterations } -SubspaceIteration :: ~SubspaceIteration() -{ } - NM_Status SubspaceIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, FloatMatrix &_r, double rtol, int nroot) // @@ -68,14 +67,13 @@ SubspaceIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, Floa FloatArray temp, w, d, tt, f, rtolv, eigv; FloatMatrix r; - int nn, nc1, ij = 0, is; - double rt, art, brt, eigvt; + int nc1, ij = 0; FloatMatrix ar, br, vec; std :: unique_ptr< SparseLinearSystemNM > solver( GiveClassFactory().createSparseLinSolver(ST_Direct, domain, engngModel) ); GJacobi mtd(domain, engngModel); int nc = min(2 * nroot, nroot + 8); - nn = a.giveNumberOfColumns(); + int nn = a.giveNumberOfColumns(); if ( nc > nn ) { nc = nn; } @@ -119,7 +117,7 @@ SubspaceIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, Floa r.setColumn(tt, 1); for ( int j = 2; j <= nc; j++ ) { - rt = 0.0; + double rt = 0.0; for ( int i = 1; i <= nn; i++ ) { if ( fabs( w.at(i) ) >= rt ) { rt = fabs( w.at(i) ); @@ -166,7 +164,7 @@ SubspaceIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, Floa solver->solve(a, f, tt); for ( int i = j; i <= nc; i++ ) { - art = 0.; + double art = 0.; for ( int k = 1; k <= nn; k++ ) { art += r.at(k, i) * tt.at(k); } @@ -188,7 +186,7 @@ SubspaceIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, Floa b.times(tt, temp); for ( int i = j; i <= nc; i++ ) { - brt = 0.; + double brt = 0.; for ( int k = 1; k <= nn; k++ ) { brt += r.at(k, i) * temp.at(k); } @@ -293,18 +291,15 @@ SubspaceIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, Floa // // sorting eigenvalues according to their values // + int is; do { is = 0; // label 350 for ( int i = 1; i <= nc1; i++ ) { if ( fabs( eigv.at(i + 1) ) < fabs( eigv.at(i) ) ) { is++; - eigvt = eigv.at(i + 1); - eigv.at(i + 1) = eigv.at(i); - eigv.at(i) = eigvt; + std::swap(eigv.at(i), eigv.at(i + 1)); for ( int k = 1; k <= nc; k++ ) { - rt = vec.at(k, i + 1); - vec.at(k, i + 1) = vec.at(k, i); - vec.at(k, i) = rt; + std::swap(vec.at(k, i), vec.at(k, i + 1)); } } } // label 360 @@ -325,7 +320,7 @@ SubspaceIteration :: solve(SparseMtrx &a, SparseMtrx &b, FloatArray &_eigv, Floa } for ( int k = 1; k <= nc; k++ ) { - rt = 0.; + double rt = 0.; for ( int j = 1; j <= nc; j++ ) { rt += tt.at(j) * vec.at(j, k); } diff --git a/src/oofemlib/subspaceit.h b/src/oofemlib/subspaceit.h index 042aeca25..9bdbf6e8e 100644 --- a/src/oofemlib/subspaceit.h +++ b/src/oofemlib/subspaceit.h @@ -32,10 +32,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -// **************************************** -// *** CLASS SUBSPACE ITERATION SOLVER *** -// **************************************** - #ifndef subspaceit_h #define subspaceit_h @@ -44,6 +40,8 @@ #include "sparsemtrx.h" #include "floatarray.h" +#define _IFT_SubspaceIteration_Name "subspaceit" + namespace oofem { class Domain; class EngngModel; @@ -86,18 +84,18 @@ class EngngModel; * EIGV(NROOT) - VLASTNI CISLA * R(NN,NROOT) - VLASTNI VEKTORY */ - class OOFEM_EXPORT SubspaceIteration : public SparseGeneralEigenValueSystemNM { private: + /// Max number of iterations int nitem; public: SubspaceIteration(Domain * d, EngngModel * m); - virtual ~SubspaceIteration(); + virtual ~SubspaceIteration() {} - virtual NM_Status solve(SparseMtrx &A, SparseMtrx &B, FloatArray &x, FloatMatrix &v, double rtol, int nroot); - virtual const char *giveClassName() const { return "SubspaceIterationSolver"; } + NM_Status solve(SparseMtrx &A, SparseMtrx &B, FloatArray &x, FloatMatrix &v, double rtol, int nroot) override; + const char *giveClassName() const override { return "SubspaceIterationSolver"; } }; } // end namespace oofem #endif // subspaceit_h diff --git a/src/oofemlib/superlusolver.C b/src/oofemlib/superlusolver.C index 3fb7bfead..c90c7c91c 100644 --- a/src/oofemlib/superlusolver.C +++ b/src/oofemlib/superlusolver.C @@ -54,16 +54,35 @@ REGISTER_SparseLinSolver(SuperLUSolver, ST_SuperLU_MT) SuperLUSolver :: SuperLUSolver(Domain *d, EngngModel *m) : SparseLinearSystemNM(d, m) -{ } - - -SuperLUSolver :: ~SuperLUSolver() { } +{} + + +SuperLUSolver :: ~SuperLUSolver() { + if (this->AAllocated) { + Destroy_SuperMatrix_Store(& this->A); + Destroy_SuperNode_SCP(& this->L); + Destroy_CompCol_NCP(& this->U); + } + if (this->permAllocated) { + SUPERLU_FREE(this->perm_r); + SUPERLU_FREE(this->perm_c); + } +} -IRResultType -SuperLUSolver :: initializeFrom(InputRecord *ir) +void +SuperLUSolver :: initializeFrom(InputRecord &ir) { - return IRRT_OK; + /* + * Get column permutation vector perm_c[], according to permc_spec: + * permc_spec = 0: natural ordering + * permc_spec = 1: minimum degree ordering on structure of A'*A + * permc_spec = 2: minimum degree ordering on structure of A'+A + * permc_spec = 3: approximate minimum degree for unsymmetric matrices + */ + + this->permc_spec = 0; // default + IR_GIVE_OPTIONAL_FIELD(ir, this->permc_spec, _IFT_SuperLUSolver_Permcspec); } NM_Status @@ -75,10 +94,15 @@ SuperLUSolver :: solve(SparseMtrx &Lhs, FloatArray &b, FloatArray &x) //3. Step: call superLU Solve with tranformed input parameters //4. Step: Transfrom result back to FloatArray *x //5. Step: return SUCCESS! +#ifdef TIME_REPORT + Timer timer; + timer.startTimer(); +#endif + CompCol *CC = dynamic_cast< CompCol * >( & Lhs ); + if ( CC ) { - SuperMatrix A, L, U; SuperMatrix B, X; int_t nprocs; fact_t fact; @@ -87,12 +111,10 @@ SuperLUSolver :: solve(SparseMtrx &Lhs, FloatArray &b, FloatArray &x) equed_t equed; double *a; int_t *asub, *xa; - int_t *perm_c; - int_t *perm_r; void *work; superlumt_options_t superlumt_options; int_t info, lwork, nrhs, /*ldx,*/ panel_size, relax; - int_t m, n, nnz, permc_spec; + int_t m, n, nnz; double *rhsb, *rhsx /*, *xact*/; double *R, *C; double *ferr, *berr; @@ -100,10 +122,11 @@ SuperLUSolver :: solve(SparseMtrx &Lhs, FloatArray &b, FloatArray &x) superlu_memusage_t superlu_memusage; void parse_command_line(); + /* Default parameters to control factorization. */ nprocs = omp_get_max_threads(); //omp_get_num_threads() does not work as we are not in parallel region!!; printf("Use number of LU threads: %u\n", nprocs); - fact = EQUILIBRATE; + fact = DOFACT; //EQUILIBRATE; trans = NOTRANS; equed = NOEQUIL; refact = NO; @@ -122,129 +145,151 @@ SuperLUSolver :: solve(SparseMtrx &Lhs, FloatArray &b, FloatArray &x) asub = CC->giveRowIndex().givePointer(); xa = CC->giveColPtr().givePointer(); - /* Command line options to modify default behavior. */ - //parse_command_line(argc, argv, &nprocs, &lwork, &panel_size, &relax, - // &u, &fact, &trans, &refact, &equed); - - if ( lwork > 0 ) { + if (0) { + dCreate_CompCol_Matrix(& this->A, m, n, nnz, a, asub, xa, SLU_NC, SLU_D, SLU_GE); + if ( !( this->perm_r = intMalloc(m) ) ) { + SUPERLU_ABORT("Malloc fails for perm_r[]."); + } + if ( !( this->perm_c = intMalloc(n) ) ) { + SUPERLU_ABORT("Malloc fails for perm_c[]."); + } + dCreate_Dense_Matrix(& B, m, nrhs, b.givePointer(), m, SLU_DN, SLU_D, SLU_GE); + + get_perm_c(this->permc_spec, &this->A, this->perm_c); + //dPrint_Dense_Matrix(&B); + pdgssv(nprocs, &this->A, this->perm_c, this->perm_r, &this->L, &this->U, &B, &info); + //dPrint_Dense_Matrix(&B); + x.resize( m ); + this->convertRhs(& B, x); + Destroy_SuperMatrix_Store(& this->A); + Destroy_SuperMatrix_Store(& B); + Destroy_SuperNode_SCP(& this->L); + Destroy_CompCol_NCP(& this->U); + SUPERLU_FREE(this->perm_r); + SUPERLU_FREE(this->perm_c); + } else { + + /* Command line options to modify default behavior. */ + //parse_command_line(argc, argv, &nprocs, &lwork, &panel_size, &relax, + // &u, &fact, &trans, &refact, &equed); + + if ( lwork > 0 ) { work = SUPERLU_MALLOC(lwork); - printf("Use work space of size LWORK = " IFMT " bytes\n", lwork); + OOFEM_LOG_DEBUG("Use work space of size LWORK = " IFMT " bytes\n", lwork); if ( !work ) { - SUPERLU_ABORT("cannot allocate work[]"); + SUPERLU_ABORT("cannot allocate work[]"); } - } - - //printf("Use work space of size LWORK = " IFMT " bytes\n", lwork); - + } + + //printf("Use work space of size LWORK = " IFMT " bytes\n", lwork); + #if ( PRNTlevel == 1 ) - cpp_defs(); - printf( "int_t %d bytes\n", sizeof( int_t ) ); -#endif - -#ifdef TIME_REPORT - Timer timer; - timer.startTimer(); + cpp_defs(); + printf( "int_t %d bytes\n", sizeof( int_t ) ); #endif - - - - dCreate_CompCol_Matrix(& A, m, n, nnz, a, asub, xa, SLU_NC, SLU_D, SLU_GE); - - - if ( !( rhsb = doubleMalloc(m * nrhs) ) ) { + + if (CC->giveVersion() == this->lhsVersion) { + // reuse existing factorization + fact = FACTORED; + OOFEM_LOG_DEBUG ("SuperLU_MT:LHS already factored\n"); + } else { + fact = DOFACT; //EQUILIBRATE; + // solve for new (updated) lhs + if (this->AAllocated) Destroy_SuperMatrix_Store(& this->A); + dCreate_CompCol_Matrix(& this->A, m, n, nnz, a, asub, xa, SLU_NC, SLU_D, SLU_GE); + this->AAllocated = true; + this->lhsVersion = CC->giveVersion(); + OOFEM_LOG_DEBUG ("SuperLU_MT:Factoring.....\n"); + + if (!this->permAllocated) { + if ( !( this->perm_r = intMalloc(m) ) ) { + SUPERLU_ABORT("Malloc fails for perm_r[]."); + } + if ( !( this->perm_c = intMalloc(n) ) ) { + SUPERLU_ABORT("Malloc fails for perm_c[]."); + } + this->permAllocated = true; + } + } + + if ( !( rhsb = doubleMalloc(m * nrhs) ) ) { SUPERLU_ABORT("Malloc fails for rhsb[]."); - } - if ( !( rhsx = doubleMalloc(m * nrhs) ) ) { + } + if ( !( rhsx = doubleMalloc(m * nrhs) ) ) { SUPERLU_ABORT("Malloc fails for rhsx[]."); - } - dCreate_Dense_Matrix(& B, m, nrhs, b.givePointer(), m, SLU_DN, SLU_D, SLU_GE); - dCreate_Dense_Matrix(& X, m, nrhs, rhsx, m, SLU_DN, SLU_D, SLU_GE); - //dPrint_Dense_Matrix(&B); - //dPrint_Dense_Matrix(&X); - - if ( !( perm_r = intMalloc(m) ) ) { - SUPERLU_ABORT("Malloc fails for perm_r[]."); - } - if ( !( perm_c = intMalloc(n) ) ) { - SUPERLU_ABORT("Malloc fails for perm_c[]."); - } - if ( !( R = ( double * ) SUPERLU_MALLOC( A.nrow * sizeof( double ) ) ) ) { + } + dCreate_Dense_Matrix(& B, m, nrhs, b.givePointer(), m, SLU_DN, SLU_D, SLU_GE); + dCreate_Dense_Matrix(& X, m, nrhs, rhsx, m, SLU_DN, SLU_D, SLU_GE); + //dPrint_Dense_Matrix(&B); + //dPrint_Dense_Matrix(&X); + + if ( !( R = ( double * ) SUPERLU_MALLOC( this->A.nrow * sizeof( double ) ) ) ) { SUPERLU_ABORT("SUPERLU_MALLOC fails for R[]."); - } - if ( !( C = ( double * ) SUPERLU_MALLOC( A.ncol * sizeof( double ) ) ) ) { + } + if ( !( C = ( double * ) SUPERLU_MALLOC( this->A.ncol * sizeof( double ) ) ) ) { SUPERLU_ABORT("SUPERLU_MALLOC fails for C[]."); - } - if ( !( ferr = ( double * ) SUPERLU_MALLOC( nrhs * sizeof( double ) ) ) ) { + } + if ( !( ferr = ( double * ) SUPERLU_MALLOC( nrhs * sizeof( double ) ) ) ) { SUPERLU_ABORT("SUPERLU_MALLOC fails for ferr[]."); - } - if ( !( berr = ( double * ) SUPERLU_MALLOC( nrhs * sizeof( double ) ) ) ) { + } + if ( !( berr = ( double * ) SUPERLU_MALLOC( nrhs * sizeof( double ) ) ) ) { SUPERLU_ABORT("SUPERLU_MALLOC fails for berr[]."); - } - - /* - * Get column permutation vector perm_c[], according to permc_spec: - * permc_spec = 0: natural ordering - * permc_spec = 1: minimum degree ordering on structure of A'*A - * permc_spec = 2: minimum degree ordering on structure of A'+A - * permc_spec = 3: approximate minimum degree for unsymmetric matrices - */ - - permc_spec = 2; - get_perm_c(permc_spec, & A, perm_c); - - superlumt_options.SymmetricMode = YES; - superlumt_options.diag_pivot_thresh = 0.0; - - superlumt_options.nprocs = nprocs; - superlumt_options.fact = fact; - superlumt_options.trans = trans; - superlumt_options.refact = refact; - superlumt_options.panel_size = panel_size; - superlumt_options.relax = relax; - superlumt_options.usepr = usepr; - superlumt_options.drop_tol = drop_tol; - superlumt_options.PrintStat = NO; - superlumt_options.perm_c = perm_c; - superlumt_options.perm_r = perm_r; - //superlumt_options.work = work; - superlumt_options.lwork = lwork; - if ( !( superlumt_options.etree = intMalloc(n) ) ) { - SUPERLU_ABORT("Malloc fails for etree[]."); - } - if ( !( superlumt_options.colcnt_h = intMalloc(n) ) ) { - SUPERLU_ABORT("Malloc fails for colcnt_h[]."); - } - if ( !( superlumt_options.part_super_h = intMalloc(n) ) ) { - SUPERLU_ABORT("Malloc fails for colcnt_h[]."); - } - - printf("sym_mode %d\tdiag_pivot_thresh %.4e\n", - superlumt_options.SymmetricMode, - superlumt_options.diag_pivot_thresh); - - /* - * Solve the system and compute the condition number - * and error bounds using pdgssvx. - */ - pdgssvx(nprocs, & superlumt_options, & A, perm_c, perm_r, & equed, R, C, & L, & U, & B, & X, & rpg, & rcond, ferr, berr, & superlu_memusage, & info); - - //dPrint_Dense_Matrix(&B); - //dPrint_Dense_Matrix(&X); - + } + + get_perm_c(this->permc_spec, & this->A, this->perm_c); + + superlumt_options.SymmetricMode = YES; + superlumt_options.diag_pivot_thresh = 0.0; + + superlumt_options.nprocs = nprocs; + superlumt_options.fact = fact; + superlumt_options.trans = trans; + superlumt_options.refact = refact; + superlumt_options.panel_size = panel_size; + superlumt_options.relax = relax; + superlumt_options.usepr = usepr; + superlumt_options.drop_tol = drop_tol; + superlumt_options.PrintStat = NO; + superlumt_options.perm_c = perm_c; + superlumt_options.perm_r = perm_r; + //superlumt_options.work = work; + superlumt_options.lwork = lwork; + if ( !( superlumt_options.etree = intMalloc(n) ) ) { + SUPERLU_ABORT("Malloc fails for etree[]."); + } + if ( !( superlumt_options.colcnt_h = intMalloc(n) ) ) { + SUPERLU_ABORT("Malloc fails for colcnt_h[]."); + } + if ( !( superlumt_options.part_super_h = intMalloc(n) ) ) { + SUPERLU_ABORT("Malloc fails for colcnt_h[]."); + } + + OOFEM_LOG_DEBUG ("sym_mode %d\tdiag_pivot_thresh %.4e\n", + superlumt_options.SymmetricMode, + superlumt_options.diag_pivot_thresh); + + /* + * Solve the system and compute the condition number + * and error bounds using pdgssvx. + */ + pdgssvx(nprocs, & superlumt_options, & this->A, this->perm_c, this->perm_r, & equed, R, C, & this->L, & this->U, & B, & X, & rpg, & rcond, ferr, berr, & superlu_memusage, & info); + x.resize( b.giveSize() ); + this->convertRhs(& X, x); + #if 0 - printf("psgssvx(): info " IFMT "\n", info); - - if ( info == 0 || info == n + 1 ) { + printf("psgssvx(): info " IFMT "\n", info); + + if ( info == 0 || info == n + 1 ) { SCPformat *Lstore; NCPformat *Ustore; - + printf("Recip. pivot growth = %e\n", rpg); printf("Recip. condition number = %e\n", rcond); printf("%8s%16s%16s\n", "rhs", "FERR", "BERR"); for ( int i = 0; i < nrhs; ++i ) { - printf(IFMT "%16e%16e\n", i + 1, ferr [ i ], berr [ i ]); + printf(IFMT "%16e%16e\n", i + 1, ferr [ i ], berr [ i ]); } - + Lstore = ( SCPformat * ) L.Store; Ustore = ( NCPformat * ) U.Store; printf("No of nonzeros in factor L = " IFMT "\n", Lstore->nnz); @@ -253,56 +298,47 @@ SuperLUSolver :: solve(SparseMtrx &Lhs, FloatArray &b, FloatArray &x) printf("L\\U MB %.3f\ttotal MB needed %.3f\texpansions " IFMT "\n", superlu_memusage.for_lu / 1e6, superlu_memusage.total_needed / 1e6, superlu_memusage.expansions); - + fflush(stdout); - } else if ( info > 0 && lwork == -1 ) { + } else if ( info > 0 && lwork == -1 ) { printf("** Estimated memory: " IFMT " bytes\n", info - n); - } + } #else - if ( info > 0 && lwork == -1 ) { + if ( info > 0 && lwork == -1 ) { printf("** Estimated memory: " IFMT " bytes\n", info - n); - } + } #endif - - //dPrint_Dense_Matrix(&B); - // copy B into x (assuming only one rhs) - x.resize( b.giveSize() ); - this->convertRhs(& X, x); - SUPERLU_FREE(rhsb); - SUPERLU_FREE(rhsx); - //SUPERLU_FREE (xact); - SUPERLU_FREE(perm_r); - SUPERLU_FREE(perm_c); - SUPERLU_FREE(R); - SUPERLU_FREE(C); - SUPERLU_FREE(ferr); - SUPERLU_FREE(berr); - Destroy_SuperMatrix_Store(& A); - Destroy_SuperMatrix_Store(& B); - Destroy_SuperMatrix_Store(& X); - // SUPERLU_FREE (superlumt_options.etree); - // SUPERLU_FREE (superlumt_options.colcnt_h); - /// SUPERLU_FREE (superlumt_options.part_super_h); - if ( lwork == 0 ) { - Destroy_SuperNode_SCP(& L); - Destroy_CompCol_NCP(& U); - } else if ( lwork > 0 ) { + + SUPERLU_FREE(rhsb); + SUPERLU_FREE(rhsx); + //SUPERLU_FREE (xact); + SUPERLU_FREE(R); + SUPERLU_FREE(C); + SUPERLU_FREE(ferr); + SUPERLU_FREE(berr); + //Destroy_SuperMatrix_Store(& this->A); + Destroy_SuperMatrix_Store(& B); + Destroy_SuperMatrix_Store(& X); + // SUPERLU_FREE (superlumt_options.etree); + // SUPERLU_FREE (superlumt_options.colcnt_h); + /// SUPERLU_FREE (superlumt_options.part_super_h); + if ( lwork == 0 ) { + //Destroy_SuperNode_SCP(& this->L); + //Destroy_CompCol_NCP(& this->U); + } else if ( lwork > 0 ) { SUPERLU_FREE(work); - } - + } + } #ifdef TIME_REPORT - timer.stopTimer(); - OOFEM_LOG_INFO( "SuperLU_MT info: user time consumed by solution: %.2fs\n", timer.getUtime() ); - OOFEM_LOG_INFO( "SuperLU_MT info: real time consumed by solution: %.2fs\n", timer.getWtime() ); + timer.stopTimer(); + OOFEM_LOG_INFO( "SuperLU_MT info: user time consumed by solution: %.2fs\n", timer.getUtime() ); + OOFEM_LOG_INFO( "SuperLU_MT info: real time consumed by solution: %.2fs\n", timer.getWtime() ); #endif + } else { - OOFEM_ERROR("Incompatible sparse storage encountered"); + OOFEM_ERROR("Incompatible sparse storage encountered"); } - - - - - + //dPrint_Dense_Matrix(&B); /* * Lstore = (SCPformat *) L.Store; @@ -345,7 +381,6 @@ SuperLUSolver :: convertRhs(SuperMatrix *X, FloatArray &x) int_t SuperLUSolver :: dPrint_CompCol_Matrix(SuperMatrix *A) { NCformat *Astore; - register int_t i; double *dp; printf("\nCompCol matrix: "); @@ -354,15 +389,15 @@ int_t SuperLUSolver :: dPrint_CompCol_Matrix(SuperMatrix *A) dp = ( double * ) Astore->nzval; printf("nrow " IFMT ", ncol " IFMT ", nnz " IFMT "\n", A->nrow, A->ncol, Astore->nnz); printf("\nnzval: "); - for ( i = 0; i < Astore->nnz; ++i ) { + for ( int_t i = 0; i < Astore->nnz; ++i ) { printf("%f ", dp [ i ]); } printf("\nrowind: "); - for ( i = 0; i < Astore->nnz; ++i ) { + for ( int_t i = 0; i < Astore->nnz; ++i ) { printf(IFMT, Astore->rowind [ i ]); } printf("\ncolptr: "); - for ( i = 0; i <= A->ncol; ++i ) { + for ( int_t i = 0; i <= A->ncol; ++i ) { printf(IFMT, Astore->colptr [ i ]); } printf("\nend CompCol matrix.\n"); @@ -373,7 +408,6 @@ int_t SuperLUSolver :: dPrint_CompCol_Matrix(SuperMatrix *A) int_t SuperLUSolver :: dPrint_Dense_Matrix(SuperMatrix *A) { DNformat *Astore; - register int_t i; double *dp; printf("\nDense matrix: "); @@ -383,7 +417,7 @@ int_t SuperLUSolver :: dPrint_Dense_Matrix(SuperMatrix *A) printf("nrow " IFMT ", ncol " IFMT ", lda " IFMT "\n", A->nrow, A->ncol, Astore->lda); printf("\nnzval: "); - for ( i = 0; i < A->nrow; ++i ) { + for ( int_t i = 0; i < A->nrow; ++i ) { printf("%f ", dp [ i ]); } printf("\nend Dense matrix.\n"); @@ -395,11 +429,11 @@ int_t dCheckZeroDiagonal(int_t n, int_t *rowind, int_t *colbeg, int_t *colend, int_t *perm) { - register int_t i, j, nzd, nd = 0; + int_t nd = 0; - for ( j = 0; j < n; ++j ) { - nzd = 0; - for ( i = colbeg [ j ]; i < colend [ j ]; ++i ) { + for ( int_t j = 0; j < n; ++j ) { + int_t nzd = 0; + for ( int_t i = colbeg [ j ]; i < colend [ j ]; ++i ) { if ( perm [ rowind [ i ] ] == j ) { nzd = 1; ++nd; diff --git a/src/oofemlib/superlusolver.h b/src/oofemlib/superlusolver.h index e38a5811c..20f7cb187 100644 --- a/src/oofemlib/superlusolver.h +++ b/src/oofemlib/superlusolver.h @@ -40,6 +40,9 @@ #include "floatarray.h" #include "SUPERLU_MT/include/slu_mt_ddefs.h" +#define _IFT_SuperLUSolver_Name "superlu" +#define _IFT_SuperLUSolver_Permcspec "permcspec" + namespace oofem { class Domain; class EngngModel; @@ -55,7 +58,14 @@ class FloatMatrix; class OOFEM_EXPORT SuperLUSolver : public SparseLinearSystemNM { private: - + SparseMtrx::SparseMtrxVersionType lhsVersion; // timestamp of existing decomposition + SuperMatrix A, L, U; + bool AAllocated=false, LAllocated=false, UAllocated=false; + bool permAllocated = false; + int_t *perm_c; + int_t *perm_r; + int_t permc_spec; + public: SuperLUSolver(Domain * d, EngngModel * m); /// Destructor @@ -67,16 +77,13 @@ class OOFEM_EXPORT SuperLUSolver : public SparseLinearSystemNM * @param x Solution array. * @return Status value. */ - - virtual NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x); - virtual SparseMtrxType giveRecommendedMatrix(bool symmetric) const { - return SMT_CompCol; - } + NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x) override; + SparseMtrxType giveRecommendedMatrix(bool symmetric) const override { return SMT_CompCol; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "SuperLUSolver"; } - virtual LinSystSolverType giveLinSystSolverType() const { return ST_SuperLU_MT; } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "SuperLUSolver"; } + LinSystSolverType giveLinSystSolverType() const override { return ST_SuperLU_MT; } private: diff --git a/src/oofemlib/surfacetensionbc.C b/src/oofemlib/surfacetensionbc.C index 87fc99e9c..0a31db0fc 100644 --- a/src/oofemlib/surfacetensionbc.C +++ b/src/oofemlib/surfacetensionbc.C @@ -53,18 +53,20 @@ #include #include +#ifdef _OPENMP +#include +#endif + namespace oofem { REGISTER_BoundaryCondition(SurfaceTensionBoundaryCondition); -IRResultType SurfaceTensionBoundaryCondition :: initializeFrom(InputRecord *ir) +void SurfaceTensionBoundaryCondition :: initializeFrom(InputRecord &ir) { - IRResultType result; + ActiveBoundaryCondition :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->gamma, _IFT_SurfaceTensionBoundaryCondition_gamma); - this->useTangent = ir->hasField(_IFT_SurfaceTensionBoundaryCondition_useTangent); - - return ActiveBoundaryCondition :: initializeFrom(ir); + this->useTangent = ir.hasField(_IFT_SurfaceTensionBoundaryCondition_useTangent); } void SurfaceTensionBoundaryCondition :: giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, @@ -76,7 +78,6 @@ void SurfaceTensionBoundaryCondition :: giveLocationArrays(std :: vector< IntArr Set *set = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = set->giveBoundaryList(); - IntArray bNodes; rows.resize(boundaries.giveSize() / 2); cols.resize(boundaries.giveSize() / 2); @@ -85,7 +86,7 @@ void SurfaceTensionBoundaryCondition :: giveLocationArrays(std :: vector< IntArr Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(rows [ pos ], bNodes, this->dofs, r_s); e->giveBoundaryLocationArray(cols [ pos ], bNodes, this->dofs, c_s); @@ -93,7 +94,9 @@ void SurfaceTensionBoundaryCondition :: giveLocationArrays(std :: vector< IntArr } void SurfaceTensionBoundaryCondition :: assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale) + CharType type, const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, double scale, + void*lock) { if ( !this->useTangent || type != TangentStiffnessMatrix ) { return; @@ -102,7 +105,7 @@ void SurfaceTensionBoundaryCondition :: assemble(SparseMtrx &answer, TimeStep *t OOFEM_ERROR("Not implemented yet."); FloatMatrix Ke; - IntArray r_loc, c_loc, bNodes; + IntArray r_loc, c_loc; Set *set = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = set->giveBoundaryList(); @@ -111,26 +114,34 @@ void SurfaceTensionBoundaryCondition :: assemble(SparseMtrx &answer, TimeStep *t Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(r_loc, bNodes, this->dofs, r_s); e->giveBoundaryLocationArray(c_loc, bNodes, this->dofs, c_s); this->computeTangentFromElement(Ke, e, boundary, tStep); Ke.times(scale); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(r_loc, c_loc, Ke); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } void SurfaceTensionBoundaryCondition :: assembleVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorms) + const UnknownNumberingScheme &s, + FloatArray *eNorms, + void*lock) { if ( type != ExternalForcesVector ) { return; } FloatArray fe; - IntArray loc, masterdofids, bNodes; + IntArray loc, masterdofids; Set *set = this->giveDomain()->giveSet(this->set); const IntArray &boundaries = set->giveBoundaryList(); @@ -139,14 +150,20 @@ void SurfaceTensionBoundaryCondition :: assembleVector(FloatArray &answer, TimeS Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc, bNodes, this->dofs, s, & masterdofids); this->computeLoadVectorFromElement(fe, e, boundary, tStep); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(fe, loc); if ( eNorms ) { eNorms->assembleSquared(fe, masterdofids); } +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } @@ -282,8 +299,7 @@ void SurfaceTensionBoundaryCondition :: computeLoadVectorFromElement(FloatArray FEInterpolation2d *fei2d = static_cast< FEInterpolation2d * >(fei); ///@todo More of this grunt work should be moved to the interpolation classes - IntArray bnodes; - fei2d->boundaryGiveNodes(bnodes, side); + const auto &bnodes = fei2d->boundaryGiveNodes(side); int nodes = bnodes.giveSize(); FloatMatrix xy(2, nodes); for ( int i = 1; i <= nodes; i++ ) { diff --git a/src/oofemlib/surfacetensionbc.h b/src/oofemlib/surfacetensionbc.h index e535cca01..ced30e450 100644 --- a/src/oofemlib/surfacetensionbc.h +++ b/src/oofemlib/surfacetensionbc.h @@ -69,20 +69,22 @@ class OOFEM_EXPORT SurfaceTensionBoundaryCondition : public ActiveBoundaryCondit /// Destructor. virtual ~SurfaceTensionBoundaryCondition() { } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0); + void assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0, void*lock=nullptr) override; - virtual void assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorms = NULL); + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, + FloatArray *eNorms=nullptr, + void*lock=nullptr) override; - virtual void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, - const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s); + void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) override; - virtual const char *giveClassName() const { return "SurfaceTensionBoundaryCondition"; } - virtual const char *giveInputRecordName() const { return _IFT_SurfaceTensionBoundaryCondition_Name; } + const char *giveClassName() const override { return "SurfaceTensionBoundaryCondition"; } + const char *giveInputRecordName() const override { return _IFT_SurfaceTensionBoundaryCondition_Name; } protected: /** diff --git a/src/oofemlib/symcompcol.C b/src/oofemlib/symcompcol.C index 50e5e823c..449dc3222 100644 --- a/src/oofemlib/symcompcol.C +++ b/src/oofemlib/symcompcol.C @@ -32,8 +32,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -// Class SymCompCol - // inspired by /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /* ******** *** SparseLib++ */ @@ -65,10 +63,6 @@ /* */ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -/* Compressed column symmetric sparse matrix (0-based) */ -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ - #include "symcompcol.h" #include "floatarray.h" #include "engngm.h" @@ -83,31 +77,21 @@ namespace oofem { REGISTER_SparseMtrx(SymCompCol, SMT_SymCompCol); -SymCompCol :: SymCompCol(void) : CompCol() -{ } - SymCompCol :: SymCompCol(int n) : CompCol(n) { } -/*****************************/ -/* Copy constructor */ -/*****************************/ - SymCompCol :: SymCompCol(const SymCompCol &S) : CompCol(S) { } -SparseMtrx *SymCompCol :: GiveCopy() const +std::unique_ptr SymCompCol :: clone() const { - SymCompCol *result = new SymCompCol(*this); - return result; + return std::make_unique(*this); } -#define MAP(i, j) map [ ( j ) * neq - ( j ) * ( ( j ) + 1 ) / 2 + ( i ) ] - int SymCompCol :: buildInternalStructure(EngngModel *eModel, int di, const UnknownNumberingScheme &s) { IntArray loc; @@ -117,7 +101,7 @@ int SymCompCol :: buildInternalStructure(EngngModel *eModel, int di, const Unkno // allocation map std :: vector< std :: set< int > > columns(neq); - this->nz_ = 0; + this->nz = 0; for ( auto &elem : domain->giveElements() ) { elem->giveLocationArray(loc, s); @@ -139,7 +123,7 @@ int SymCompCol :: buildInternalStructure(EngngModel *eModel, int di, const Unkno for ( auto &gbc : domain->giveBcs() ) { ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() ); - if ( bc != NULL ) { + if ( bc ) { bc->giveLocationArrays(r_locs, c_locs, UnknownCharType, s, s); for ( std :: size_t k = 0; k < r_locs.size(); k++ ) { IntArray &krloc = r_locs [ k ]; @@ -157,34 +141,31 @@ int SymCompCol :: buildInternalStructure(EngngModel *eModel, int di, const Unkno } } - - for ( auto &val : columns ) { - this->nz_ += val.size(); + this->nz += val.size(); } - rowind_.resize(nz_); - colptr_.resize(neq + 1); + rowind.resize(nz); + colptr.resize(neq + 1); indx = 0; - for ( int j = 0; j < neq; j++ ) { // column loop - colptr_(j) = indx; - for ( int row: columns [ j ] ) { // row loop - rowind_(indx++) = row; + for ( int j = 0; j < neq; j++ ) { + colptr[j] = indx; + for ( int row: columns [ j ] ) { + rowind[indx++] = row; } } - colptr_(neq) = indx; + colptr[neq] = indx; // allocate value array - val_.resize(nz_); - val_.zero(); + val.resize(nz); + val.zero(); - OOFEM_LOG_INFO("SymCompCol info: neq is %d, nwk is %d\n", neq, nz_); + OOFEM_LOG_INFO("SymCompCol info: neq is %d, nwk is %d\n", neq, nz); - dim_ [ 0 ] = dim_ [ 1 ] = nColumns = nRows = neq; + nColumns = nRows = neq; - // increment version this->version++; return true; @@ -194,41 +175,35 @@ int SymCompCol :: buildInternalStructure(EngngModel *eModel, int di, const Unkno void SymCompCol :: times(const FloatArray &x, FloatArray &answer) const { - int M = dim_ [ 0 ]; - int N = dim_ [ 1 ]; - #if DEBUG - if ( x.giveSize() != N ) { + if ( x.giveSize() != this->giveNumberOfColumns() ) { OOFEM_ERROR("incompatible dimensions"); } #endif - answer.resize(M); + answer.resize(this->giveNumberOfRows()); answer.zero(); - for ( int j = 0; j < N; j++ ) { - double rhs = x(j); + for ( int j = 0; j < this->giveNumberOfColumns(); j++ ) { + double rhs = x[j]; double sum = 0.0; - for ( int t = colptr_(j) + 1; t < colptr_(j + 1); t++ ) { - answer( rowind_(t) ) += val_(t) * rhs; // column loop - sum += val_(t) * x( rowind_(t) ); // row loop + for ( int t = colptr[j] + 1; t < colptr[j + 1]; t++ ) { + answer[ rowind[t] ] += val[t] * rhs; // column loop + sum += val[t] * x[ rowind[t] ]; // row loop } - answer(j) += sum; - answer(j) += val_( colptr_(j) ) * rhs; // diagonal + answer[j] += sum + val[ colptr[j] ] * rhs; // include diagonal } } void SymCompCol :: times(double x) { - val_.times(x); + val.times(x); - // increment version this->version++; } - int SymCompCol :: assemble(const IntArray &loc, const FloatMatrix &mat) { int dim = mat.giveNumberOfRows(); @@ -242,7 +217,7 @@ int SymCompCol :: assemble(const IntArray &loc, const FloatMatrix &mat) for ( int j = 0; j < dim; j++ ) { int jj = loc[j]; if ( jj ) { - int cstart = colptr_[jj - 1]; + int cstart = colptr[jj - 1]; int t = cstart; int last_ii = this->nRows + 1; // Ensures that t is set correctly the first time. for ( int i = 0; i < dim; i++ ) { @@ -253,36 +228,34 @@ int SymCompCol :: assemble(const IntArray &loc, const FloatMatrix &mat) t = cstart; else if ( ii > last_ii ) t++; - for ( ; rowind_[t] < ii - 1; t++ ) { + for ( ; rowind[t] < ii - 1; t++ ) { # ifdef DEBUG - if ( t >= colptr_[jj] ) + if ( t >= colptr[jj] ) OOFEM_ERROR("Couldn't find row %d in the sparse structure", ii); # endif } - val_[t] += mat(i, j); + val[t] += mat(i, j); last_ii = ii; } } } } - // increment version this->version++; return 1; } + int SymCompCol :: assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) { - int dim1, dim2; - - dim1 = mat.giveNumberOfRows(); - dim2 = mat.giveNumberOfColumns(); + int dim1 = mat.giveNumberOfRows(); + int dim2 = mat.giveNumberOfColumns(); for ( int j = 0; j < dim2; j++ ) { int jj = cloc[j]; if ( jj ) { - int cstart = colptr_[jj - 1]; + int cstart = colptr[jj - 1]; int t = cstart; int last_ii = this->nRows + 1; // Ensures that t is set correctly the first time. for ( int i = 0; i < dim1; i++ ) { @@ -293,74 +266,65 @@ int SymCompCol :: assemble(const IntArray &rloc, const IntArray &cloc, const Flo t = cstart; else if ( ii > last_ii ) t++; - for ( ; rowind_[t] < ii - 1; t++ ) { + for ( ; rowind[t] < ii - 1; t++ ) { # ifdef DEBUG - if ( t >= colptr_[jj] ) + if ( t >= colptr[jj] ) OOFEM_ERROR("Couldn't find row %d in the sparse structure", ii); # endif } - val_[t] += mat(i, j); + val[t] += mat(i, j); last_ii = ii; } } } } - // increment version this->version++; return 1; } + void SymCompCol :: zero() { - val_.zero(); + val.zero(); - // increment version this->version++; } -/*********************/ -/* Array access */ -/*********************/ double &SymCompCol :: at(int i, int j) { - int ii = i, jj = j; - if ( ii < jj ) { - ii = j; - jj = i; + if ( i < j ) { + std::swap(i, j); } - // increment version this->version++; - for ( int t = colptr_(jj - 1); t < colptr_(jj); t++ ) { - if ( rowind_(t) == ( ii - 1 ) ) { - return val_(t); + for ( int t = colptr[j - 1]; t < colptr[j]; t++ ) { + if ( rowind[t] == ( i - 1 ) ) { + return val[t]; } } OOFEM_ERROR("Array accessing exception -- out of bounds"); - return val_(0); // return to suppress compiler warning message + return val[0]; // return to suppress compiler warning message } double SymCompCol :: at(int i, int j) const { - int ii = i, jj = j; - if ( ii < jj ) { - ii = j; - jj = i; + if ( i < j ) { + std::swap(i, j); } - for ( int t = colptr_(jj - 1); t < colptr_(jj); t++ ) { - if ( rowind_(t) == ( ii - 1 ) ) { - return val_(t); + for ( int t = colptr[j - 1]; t < colptr[j]; t++ ) { + if ( rowind[t] == ( i - 1 ) ) { + return val[t]; } } - if ( i <= dim_ [ 0 ] && j <= dim_ [ 1 ] ) { + if ( i <= this->giveNumberOfColumns() && j <= this->giveNumberOfRows() ) { return 0.0; } else { OOFEM_ERROR("Array accessing exception -- index out of bounds (%d,%d)", i, j); @@ -370,19 +334,17 @@ double SymCompCol :: at(int i, int j) const double SymCompCol :: operator() (int i, int j) const { - int ii = i, jj = j; - if ( ii < jj ) { - ii = j; - jj = i; + if ( i < j ) { + std::swap(i, j); } - for ( int t = colptr_(jj); t < colptr_(jj + 1); t++ ) { - if ( rowind_(t) == ii ) { - return val_(t); + for ( int t = colptr[j]; t < colptr[j + 1]; t++ ) { + if ( rowind[t] == i ) { + return val[t]; } } - if ( i < dim_ [ 0 ] && j < dim_ [ 1 ] ) { + if ( i < this->giveNumberOfColumns() && j < this->giveNumberOfRows() ) { return 0.0; } else { OOFEM_ERROR("Array accessing exception, index out of bounds (%d,%d)", i, j); @@ -392,22 +354,19 @@ double SymCompCol :: operator() (int i, int j) const double &SymCompCol :: operator() (int i, int j) { - int ii = i, jj = j; - if ( ii < jj ) { - ii = j; - jj = i; + if ( i < j ) { + std::swap(i, j); } - // increment version this->version++; - for ( int t = colptr_(jj); t < colptr_(jj + 1); t++ ) { - if ( rowind_(t) == ii ) { - return val_(t); + for ( int t = colptr[j]; t < colptr[j + 1]; t++ ) { + if ( rowind[t] == i ) { + return val[t]; } } OOFEM_ERROR("Array element (%d,%d) not in sparse structure -- cannot assign", i, j); - return val_(0); // return to suppress compiler warning message + return val[0]; // return to suppress compiler warning message } } // end namespace oofem diff --git a/src/oofemlib/symcompcol.h b/src/oofemlib/symcompcol.h index 3717bcbbb..1dd9277a6 100644 --- a/src/oofemlib/symcompcol.h +++ b/src/oofemlib/symcompcol.h @@ -87,52 +87,28 @@ class OOFEM_EXPORT SymCompCol : public CompCol * @param n Size of matrix * @see buildInternalStructure */ - SymCompCol(int n); - /** - * Constructor. - * Before any operation an internal profile must be built. - * @see buildInternalStructure - */ - SymCompCol(); + SymCompCol(int n=0); /// Copy constructor SymCompCol(const SymCompCol & S); /// Destructor virtual ~SymCompCol() { } - // Overloaded methods - virtual SparseMtrx *GiveCopy() const; - virtual void times(const FloatArray &x, FloatArray &answer) const; - virtual void timesT(const FloatArray &x, FloatArray &answer) const { this->times(x, answer); } - virtual void times(double x); - virtual int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &); - virtual int assemble(const IntArray &loc, const FloatMatrix &mat); - virtual int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat); - virtual bool canBeFactorized() const { return false; } - virtual void zero(); - virtual double &at(int i, int j); - virtual double at(int i, int j) const; - virtual const char* giveClassName() const { return "SymCompCol"; } - virtual SparseMtrxType giveType() const { return SMT_SymCompCol; } - virtual bool isAntisymmetric() const { return false; } - - - const double &val(int i) const { return val_(i); } - const int &row_ind(int i) const { return rowind_(i); } - const int &col_ptr(int i) const { return colptr_(i); } - int dim(int i) const { return dim_ [ i ]; } + std::unique_ptr clone() const override; + void times(const FloatArray &x, FloatArray &answer) const override; + void timesT(const FloatArray &x, FloatArray &answer) const override { this->times(x, answer); } + void times(double x) override; + int buildInternalStructure(EngngModel *, int, const UnknownNumberingScheme &) override; + int assemble(const IntArray &loc, const FloatMatrix &mat) override; + int assemble(const IntArray &rloc, const IntArray &cloc, const FloatMatrix &mat) override; + bool canBeFactorized() const override { return false; } + void zero() override; + double &at(int i, int j) override; + double at(int i, int j) const override; + const char* giveClassName() const override { return "SymCompCol"; } + SparseMtrxType giveType() const override { return SMT_SymCompCol; } + bool isAsymmetric() const override { return false; } protected: - /*******************************/ - /* Access and info functions */ - /*******************************/ - - double &val(int i) { return val_(i); } - int &row_ind(int i) { return rowind_(i); } - int &col_ptr(int i) { return colptr_(i); } - - int size(int i) const { return dim_ [ i ]; } - int NumNonzeros() const { return nz_; } - int base() const { return base_; } /***********************************/ /* General access function (slow) */ diff --git a/src/oofemlib/t3dinterface.C b/src/oofemlib/t3dinterface.C index f648a587d..d4e5569d6 100644 --- a/src/oofemlib/t3dinterface.C +++ b/src/oofemlib/t3dinterface.C @@ -39,12 +39,9 @@ #include "element.h" #include "engngm.h" #include "remeshingcrit.h" - #include "oofemtxtdatareader.h" #include "dynamicinputrecord.h" -#include - #include "crosssection.h" #include "classfactory.h" @@ -55,8 +52,12 @@ #include "function.h" #include "outputmanager.h" +#include namespace oofem { +REGISTER_Mesher(T3DInterface, MPT_T3D); + + MesherInterface :: returnCode T3DInterface :: createMesh(TimeStep *tStep, int domainNumber, int domainSerNum, Domain **dNew) { @@ -287,292 +288,278 @@ T3DInterface :: createInput(Domain *d, TimeStep *tStep) int T3DInterface :: t3d_2_OOFEM(const char *t3dOutFile, Domain **dNew) { - - std::ifstream inputStream; - inputStream.open( t3dOutFile ); - if ( !inputStream.is_open() ) { - OOFEM_ERROR("OOFEMTXTDataReader::OOFEMTXTDataReader: Can't open T3D input stream (%s)", t3dOutFile); - return 0; - } - // create new domain - ( * dNew ) = new Domain( 2, this->domain->giveSerialNumber() + 1, this->domain->giveEngngModel() ); - ( * dNew )->setDomainType( this->domain->giveDomainType() ); - - std::string line; - - //read first line from t3d out file - 4 numbers - // 2 degree of interpolation - // other are not important so far - std::getline(inputStream, line); - //convert const char to char in order to use strtok - char *currentLine = new char[line.size() + 1]; - std::strcpy ( currentLine, line.c_str() ); - // tokenizing line - char *token = std::strtok(currentLine, " "); - // set counter to 0 - int i = 0; - while (token != NULL) { - if(i == 0) - {}//int n1 = atoi(token); - else if (i == 1) - {}//int interp = atoi(token); - else if(i == 2) - {}//int n3 = atoi(token); - else if(i == 3) - {}//int n4 = atoi(token); - else - break; - token = std::strtok(NULL, " "); - i++; - } - - - int nnodes,ntriangles,ntetras; // nedges, - - /*read second line from t3d out file - 4 numbers - 1 - number of nodes - 2 - number of edges - 3 - number of triangles - 4 - number of tetras - */ - std::getline(inputStream, line); - //convert const char to char in order to use strtok - currentLine = new char[line.size() + 1]; - std::strcpy ( currentLine, line.c_str() ); - // tokenizing line - token = std::strtok(currentLine, " "); - // set counter to 0 - i = 0; - while (token != NULL) { - if(i == 0) - nnodes = atoi(token); - else if (i == 1) - {}//nedges = atoi(token); - else if(i == 2) - ntriangles = atoi(token); - else if(i == 3) - ntetras = atoi(token); - else - break; - token = std::strtok(NULL, " "); - i++; - } - // create new domain - (*dNew)->resizeDofManagers(nnodes); - - - //one empty line - std::getline(inputStream, line); - // create nodes - Node *node; - // read dofs - const IntArray dofIDArrayPtr = domain->giveDefaultNodeDofIDArry(); - int ndofs = dofIDArrayPtr.giveSize(); - // loop over number of nodes, read coordinates and create new nodes - for ( int inode = 1; inode <= nnodes; inode++ ) { - FloatArray coords(3); - std::getline(inputStream, line); - //convert const char to char in order to use strtok - currentLine = new char[line.size() + 1]; - std::strcpy ( currentLine, line.c_str() ); - // tokenizing line - token = std::strtok(currentLine, " "); - // set counter to 0 - i = 0; - while (token != NULL) { - if(i == 0) - {}//int nodeNum = atoi(token); - else if (i == 1) - coords.at(1) = atof(token); - else if(i == 2) - coords.at(2) = atof(token); - else if(i == 3) - coords.at(3) = atof(token); - else - break; - token = std::strtok(NULL, " "); - i++; - } - // newly created node - node = new Node(inode, * dNew); - //create new node with default DOFs - node->setNumberOfDofs(ndofs); - node->setCoordinates( coords ); - // how to set boundary condition ?? - // node->setBoundaryFlag( mesh->giveNode(inode)->isBoundary() ); - // ( * dNew )->setDofManager(inode, node); - - }//end loop over nodes - - //read empty line - std::getline(inputStream, line); - + std::ifstream inputStream; + inputStream.open( t3dOutFile ); + if ( !inputStream.is_open() ) { + OOFEM_ERROR("OOFEMTXTDataReader::OOFEMTXTDataReader: Can't open T3D input stream (%s)", t3dOutFile); + return 0; + } + // create new domain + ( * dNew ) = new Domain( 2, this->domain->giveSerialNumber() + 1, this->domain->giveEngngModel() ); + ( * dNew )->setDomainType( this->domain->giveDomainType() ); + std::string line; - Element *parentElementPtr, *elem; - parentElementPtr = domain->giveElement(1); //??km?? - // loop over triangles, read dofman numbers and create new elements - for (int itriangle = 1; itriangle <= ntriangles; itriangle++) { - int elemNumber; - IntArray dofManagers(3); - std::getline(inputStream, line); + //read first line from t3d out file - 4 numbers + // 2 degree of interpolation + // other are not important so far + std::getline(inputStream, line); //convert const char to char in order to use strtok - currentLine = new char[line.size() + 1]; + char *currentLine = new char[line.size() + 1]; std::strcpy ( currentLine, line.c_str() ); // tokenizing line - token = std::strtok(currentLine, " "); + char *token = std::strtok(currentLine, " "); // set counter to 0 - i = 0; - while (token != NULL) { - if(i == 0) - elemNumber = atoi(token); - else if (i >= 1 && i<=4) - dofManagers.at(i) = atof(token); - else - break; - token = std::strtok(NULL, " "); - i++; - } - elem = classFactory.createElement(parentElementPtr->giveClassName(), elemNumber, * dNew); - elem->setDofManagers( dofManagers ); - elem->setMaterial( parentElementPtr->giveMaterial()->giveNumber() ); - elem->setCrossSection( parentElementPtr->giveCrossSection()->giveNumber() ); - // - // ... - // + int i = 0; + while (token != nullptr) { + if(i == 0) + {}//int n1 = atoi(token); + else if (i == 1) + {}//int interp = atoi(token); + else if(i == 2) + {}//int n3 = atoi(token); + else if(i == 3) + {}//int n4 = atoi(token); + else + break; + token = std::strtok(nullptr, " "); + i++; + } - }//end loop over triangles - -// loop over tetras, read dofman numbers and create new elements - for (int itetra = 1; itetra <= ntetras; itetra++) { - int elemNumber; - IntArray dofManagers(4); - std::getline(inputStream, line); + int nnodes = 0, ntriangles = 0, ntetras = 0; // nedges, + + /*read second line from t3d out file + 4 numbers + 1 - number of nodes + 2 - number of edges + 3 - number of triangles + 4 - number of tetras + */ + std::getline(inputStream, line); //convert const char to char in order to use strtok currentLine = new char[line.size() + 1]; std::strcpy ( currentLine, line.c_str() ); // tokenizing line token = std::strtok(currentLine, " "); - // set counter to 0 + // set counter to 0 i = 0; - while (token != NULL) { - if(i == 0) - elemNumber = atoi(token); - else if (i >= 1 && i<=4) - dofManagers.at(i) = atof(token); - else - break; - token = std::strtok(NULL, " "); - i++; - } - //elem = classFactory.createElement(parentElementPtr->giveClassName(), elemNumber, * dNew); - elem = classFactory.createElement("LTRSpace", elemNumber, * dNew); - elem->setDofManagers( dofManagers ); - elem->setMaterial( parentElementPtr->giveMaterial()->giveNumber() ); - elem->setCrossSection( parentElementPtr->giveCrossSection()->giveNumber() ); - (*dNew)->setElement(elemNumber, elem); - }//end loop over tetras - - - - CrossSection *crossSection; - Material *mat; - NonlocalBarrier *barrier; - GeneralBoundaryCondition *bc; - InitialCondition *ic; - //LoadTimeFunction *ltf; - Function *ltf; - std::string name; - - // copy of crossections from old domain - int ncrosssect = domain->giveNumberOfCrossSectionModels(); - ( * dNew )->resizeCrossSectionModels(ncrosssect); - for ( int i = 1; i <= ncrosssect; i++ ) { - DynamicInputRecord ir; - domain->giveCrossSection(i)->giveInputRecord(ir); - ir.giveRecordKeywordField(name); - - crossSection = classFactory.createCrossSection(name.c_str(), i, * dNew); - crossSection->initializeFrom(&ir); - ( * dNew )->setCrossSection(i, crossSection); - } - - // copy of materials from old domain - int nmat = domain->giveNumberOfMaterialModels(); - ( * dNew )->resizeMaterials(nmat); - for ( int i = 1; i <= nmat; i++ ) { - DynamicInputRecord ir; - domain->giveMaterial(i)->giveInputRecord(ir); - ir.giveRecordKeywordField(name); - - mat = classFactory.createMaterial(name.c_str(), i, * dNew); - mat->initializeFrom(&ir); - ( * dNew )->setMaterial(i, mat); - } - - // copy of crossections from old domain - int nbarriers = domain->giveNumberOfNonlocalBarriers(); - ( * dNew )->resizeNonlocalBarriers(nbarriers); - for ( int i = 1; i <= nbarriers; i++ ) { - DynamicInputRecord ir; - domain->giveNonlocalBarrier(i)->giveInputRecord(ir); - ir.giveRecordKeywordField(name); - - barrier = classFactory.createNonlocalBarrier(name.c_str(), i, * dNew); - barrier->initializeFrom(&ir); - ( * dNew )->setNonlocalBarrier(i, barrier); - } - + while (token != nullptr) { + if(i == 0) + nnodes = atoi(token); + else if (i == 1) + {}//nedges = atoi(token); + else if(i == 2) + ntriangles = atoi(token); + else if(i == 3) + ntetras = atoi(token); + else + break; + token = std::strtok(nullptr, " "); + i++; + } + // create new domain + (*dNew)->resizeDofManagers(nnodes); + + //one empty line + std::getline(inputStream, line); + // create nodes + // read dofs + const IntArray dofIDArrayPtr = domain->giveDefaultNodeDofIDArry(); ///@todo This is bad idea, dofs can be autogenerated. Don't fix the dofs. This method should be removed. + int ndofs = dofIDArrayPtr.giveSize(); + // loop over number of nodes, read coordinates and create new nodes + for ( int inode = 1; inode <= nnodes; inode++ ) { + FloatArray coords(3); + std::getline(inputStream, line); + //convert const char to char in order to use strtok + currentLine = new char[line.size() + 1]; + std::strcpy ( currentLine, line.c_str() ); + // tokenizing line + token = std::strtok(currentLine, " "); + // set counter to 0 + i = 0; + while (token != nullptr) { + if(i == 0) + {}//int nodeNum = atoi(token); + else if (i == 1) + coords.at(1) = atof(token); + else if(i == 2) + coords.at(2) = atof(token); + else if(i == 3) + coords.at(3) = atof(token); + else + break; + token = std::strtok(NULL, " "); + i++; + } + // newly created node + auto node = std::make_unique(inode, * dNew); + //create new node with default DOFs + node->setNumberOfDofs(ndofs); + node->setCoordinates( coords ); + // how to set boundary condition ?? + // node->setBoundaryFlag( mesh->giveNode(inode)->isBoundary() ); + // ( * dNew )->setDofManager(inode, std::move(node)); + + }//end loop over nodes + + //read empty line + std::getline(inputStream, line); + + + Element *parentElementPtr = domain->giveElement(1); //??km?? + // loop over triangles, read dofman numbers and create new elements + for (int itriangle = 1; itriangle <= ntriangles; itriangle++) { + int elemNumber = 0; + IntArray dofManagers(3); + std::getline(inputStream, line); + //convert const char to char in order to use strtok + currentLine = new char[line.size() + 1]; + std::strcpy ( currentLine, line.c_str() ); + // tokenizing line + token = std::strtok(currentLine, " "); + // set counter to 0 + i = 0; + while (token != nullptr) { + if(i == 0) + elemNumber = atoi(token); + else if (i >= 1 && i<=4) + dofManagers.at(i) = atof(token); + else + break; + token = std::strtok(nullptr, " "); + i++; + } + auto elem = classFactory.createElement(parentElementPtr->giveClassName(), elemNumber, * dNew); + elem->setDofManagers( dofManagers ); + elem->setMaterial( parentElementPtr->giveMaterial()->giveNumber() ); + elem->setCrossSection( parentElementPtr->giveCrossSection()->giveNumber() ); + // + // ... + // + + }//end loop over triangles + + + // loop over tetras, read dofman numbers and create new elements + for (int itetra = 1; itetra <= ntetras; itetra++) { + int elemNumber = 0; + IntArray dofManagers(4); + std::getline(inputStream, line); + //convert const char to char in order to use strtok + currentLine = new char[line.size() + 1]; + std::strcpy ( currentLine, line.c_str() ); + // tokenizing line + token = std::strtok(currentLine, " "); + // set counter to 0 + i = 0; + while (token != nullptr) { + if(i == 0) + elemNumber = atoi(token); + else if (i >= 1 && i<=4) + dofManagers.at(i) = atof(token); + else + break; + token = std::strtok(nullptr, " "); + i++; + } + //elem = classFactory.createElement(parentElementPtr->giveClassName(), elemNumber, * dNew); + auto elem = classFactory.createElement("LTRSpace", elemNumber, * dNew); + elem->setDofManagers( dofManagers ); + elem->setMaterial( parentElementPtr->giveMaterial()->giveNumber() ); + elem->setCrossSection( parentElementPtr->giveCrossSection()->giveNumber() ); + (*dNew)->setElement(elemNumber, std::move(elem)); + }//end loop over tetras + + + std::string name; + + // copy of crossections from old domain + int ncrosssect = domain->giveNumberOfCrossSectionModels(); + ( * dNew )->resizeCrossSectionModels(ncrosssect); + for ( int i = 1; i <= ncrosssect; i++ ) { + DynamicInputRecord ir; + domain->giveCrossSection(i)->giveInputRecord(ir); + ir.giveRecordKeywordField(name); + + auto crossSection = classFactory.createCrossSection(name.c_str(), i, * dNew); + crossSection->initializeFrom(ir); + ( * dNew )->setCrossSection(i, std::move(crossSection)); + } + + // copy of materials from old domain + int nmat = domain->giveNumberOfMaterialModels(); + ( * dNew )->resizeMaterials(nmat); + for ( int i = 1; i <= nmat; i++ ) { + DynamicInputRecord ir; + domain->giveMaterial(i)->giveInputRecord(ir); + ir.giveRecordKeywordField(name); + + auto mat = classFactory.createMaterial(name.c_str(), i, * dNew); + mat->initializeFrom(ir); + ( * dNew )->setMaterial(i, std::move(mat)); + } + + // copy of crossections from old domain + int nbarriers = domain->giveNumberOfNonlocalBarriers(); + ( * dNew )->resizeNonlocalBarriers(nbarriers); + for ( int i = 1; i <= nbarriers; i++ ) { + DynamicInputRecord ir; + domain->giveNonlocalBarrier(i)->giveInputRecord(ir); + ir.giveRecordKeywordField(name); + + auto barrier = classFactory.createNonlocalBarrier(name.c_str(), i, * dNew); + barrier->initializeFrom(ir); + ( * dNew )->setNonlocalBarrier(i, std::move(barrier)); + } + // copy of boundary conditions from old domain - int nbc = domain->giveNumberOfBoundaryConditions(); - ( * dNew )->resizeBoundaryConditions(nbc); - for ( int i = 1; i <= nbc; i++ ) { - DynamicInputRecord ir; - domain->giveBc(i)->giveInputRecord(ir); - ir.giveRecordKeywordField(name); - - bc = classFactory.createBoundaryCondition(name.c_str(), i, * dNew); - bc->initializeFrom(&ir); - ( * dNew )->setBoundaryCondition(i, bc); - } - - // copy of initial conditions from old domain - int nic = domain->giveNumberOfInitialConditions(); - ( * dNew )->resizeInitialConditions(nic); - for ( int i = 1; i <= nic; i++ ) { - DynamicInputRecord ir; - domain->giveIc(i)->giveInputRecord(ir); - ir.giveRecordKeywordField(name); - - ic = new InitialCondition(i, *dNew); - ic->initializeFrom(&ir); - ( * dNew )->setInitialCondition(i, ic); - } - - // copy of load time functions from old domain - // int nltf = domain->giveNumberOfLoadTimeFunctions(); + int nbc = domain->giveNumberOfBoundaryConditions(); + ( * dNew )->resizeBoundaryConditions(nbc); + for ( int i = 1; i <= nbc; i++ ) { + DynamicInputRecord ir; + domain->giveBc(i)->giveInputRecord(ir); + ir.giveRecordKeywordField(name); + + auto bc = classFactory.createBoundaryCondition(name.c_str(), i, * dNew); + bc->initializeFrom(ir); + ( * dNew )->setBoundaryCondition(i, std::move(bc)); + } + + // copy of initial conditions from old domain + int nic = domain->giveNumberOfInitialConditions(); + ( * dNew )->resizeInitialConditions(nic); + for ( int i = 1; i <= nic; i++ ) { + DynamicInputRecord ir; + domain->giveIc(i)->giveInputRecord(ir); + ir.giveRecordKeywordField(name); + + auto ic = std::make_unique(i, *dNew); + ic->initializeFrom(ir); + ( * dNew )->setInitialCondition(i, std::move(ic)); + } + + // copy of load time functions from old domain + // int nltf = domain->giveNumberOfLoadTimeFunctions(); int nltf = domain->giveNumberOfFunctions(); - // ( * dNew )->resizeLoadTimeFunctions(nltf); - ( * dNew )->resizeFunctions(nltf); - for ( int i = 1; i <= nltf; i++ ) { - DynamicInputRecord ir; - //domain->giveLoadTimeFunction(i)->giveInputRecord(ir); - domain->giveFunction(i)->giveInputRecord(ir); - ir.giveRecordKeywordField(name); - - //ltf = classFactory.createLoadTimeFunction(name.c_str(), i, * dNew); - ltf = classFactory.createFunction(name.c_str(), i, * dNew); - ltf->initializeFrom(&ir); - //( * dNew )->setLoadTimeFunction(i, ltf); - ( * dNew )->setFunction(i, ltf); - } - - // copy output manager settings from old domain - ( * dNew )->giveOutputManager()->beCopyOf( domain->giveOutputManager() ); - return 1; - + // ( * dNew )->resizeLoadTimeFunctions(nltf); + ( * dNew )->resizeFunctions(nltf); + for ( int i = 1; i <= nltf; i++ ) { + DynamicInputRecord ir; + //domain->giveLoadTimeFunction(i)->giveInputRecord(ir); + domain->giveFunction(i)->giveInputRecord(ir); + ir.giveRecordKeywordField(name); + + //ltf = classFactory.createLoadTimeFunction(name.c_str(), i, * dNew); + auto ltf = classFactory.createFunction(name.c_str(), i, * dNew); + ltf->initializeFrom(ir); + //( * dNew )->setLoadTimeFunction(i, ltf); + ( * dNew )->setFunction(i, std::move(ltf)); + } + + // copy output manager settings from old domain + ( * dNew )->giveOutputManager()->beCopyOf( domain->giveOutputManager() ); + return 1; } // used by HTS element to create export mesh to vtk @@ -632,7 +619,7 @@ T3DInterface :: createVTKExportMesh(const char *t3dOutFile,std::vector +#include +#include + +#ifdef FTENSOR_DEBUG +#include +#include +#include +#endif + +namespace FTensor +{ + template class Tensor0; + + template class Tensor1; + template class Tensor1_Expr; + + template class Tensor2; + template + class Tensor2_Expr; + template class Tensor2_number_rhs_0; + template class Tensor2_number_rhs_1; + + template class Tensor2_symmetric; + template + class Tensor2_symmetric_Expr; + + template class Tensor2_antisymmetric; + template + class Tensor2_antisymmetric_Expr; + + template class Tensor3; + template + class Tensor3_Expr; + template class Tensor3_number_rhs_0; + template class Tensor3_number_rhs_2; + template class Tensor3_number_rhs_2; + template class Tensor3_number_rhs_01; + template class Tensor3_number_rhs_02; + template class Tensor3_number_rhs_12; + + template class Dg; + template + class Dg_Expr; + template class Dg_number_rhs_0; + template class Dg_number_rhs_2; + template class Dg_number_rhs_01; + template class Dg_number_rhs_12; + + /*template class Christof; + template + class Christof_Expr;*/ + + template class Tensor3_antisymmetric; + template + class Tensor3_antisymmetric_Expr; + + template class Tensor4; + template + class Tensor4_Expr; + + /*template class Riemann; + template + class Riemann_Expr; + + template class Ddg; + template + class Ddg_Expr; + template class Ddg_number_rhs_01; + template class Ddg_number_rhs_0; + */ + + template class Tensor_Levi_Civita; +} + +#include "FTensor/Index.hpp" +#include "FTensor/Number.hpp" +#include "FTensor/promote.hpp" + +#include "FTensor/Levi_Civita.hpp" +#include "FTensor/cross.hpp" + +//#include "FTensor/Christof.hpp" +//#include "FTensor/Ddg.hpp" +//#include "FTensor/Dg.hpp" +//#include "FTensor/Riemann.hpp" +#include "FTensor/Tensor0.hpp" +#include "FTensor/Tensor1.hpp" +#include "FTensor/Tensor2.hpp" +#include "FTensor/Tensor2_antisymmetric.hpp" +#include "FTensor/Tensor2_symmetric.hpp" +#include "FTensor/Tensor3.hpp" +#include "FTensor/Tensor3/Tensor3_contracted.hpp" +#include "FTensor/Tensor3_antisymmetric.hpp" +#include "FTensor/Tensor4.hpp" +#include "FTensor/Tensor4/Tensor4_contracted.hpp" diff --git a/src/oofemlib/tensor/FTensor/Christof.hpp b/src/oofemlib/tensor/FTensor/Christof.hpp new file mode 100644 index 000000000..d9d90c0a4 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Christof.hpp @@ -0,0 +1,8 @@ +/* Declarations for a Christof. This is symmetric on the last + two indices. */ + +#include "Christof/Christof_number.hpp" +#include "Christof/Christof_numeral.hpp" + +#include "Christof/Christof_pointer.hpp" +#include "Christof/Christof_value.hpp" diff --git a/src/oofemlib/tensor/FTensor/Christof/Christof_number.hpp b/src/oofemlib/tensor/FTensor/Christof/Christof_number.hpp new file mode 100644 index 000000000..474b838c3 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Christof/Christof_number.hpp @@ -0,0 +1,16 @@ +/* This is for expressions where a number is used for one slot, and + an index for the other, yielding a Tensor2_symmetric_Expr. */ + +#pragma once + +namespace FTensor +{ + template class Christof_number_0 + { + const A iterA; + + public: + T operator()(const int N1, const int N2) const { return iterA(N, N1, N2); } + Christof_number_0(const A &a) : iterA(a) {} + }; +} diff --git a/src/oofemlib/tensor/FTensor/Christof/Christof_numeral.hpp b/src/oofemlib/tensor/FTensor/Christof/Christof_numeral.hpp new file mode 100644 index 000000000..a28fcf60d --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Christof/Christof_numeral.hpp @@ -0,0 +1,31 @@ +/* This is for expressions where an int is used for one slot, and an + Index for the others, yielding a Tensor2_symmetric_Expr or + Tensor2_Expr. */ + +#pragma once + +namespace FTensor +{ + template class Christof_numeral_0 + { + const A iterA; + const int N; + + public: + T operator()(const int N1, const int N2) const { return iterA(N, N1, N2); } + Christof_numeral_0(const A &a, const int NN) : iterA(a), N(NN) {} + }; + + /* We can use this version for when there is an int in either of the + last slots, because Christof is symmetric. */ + + template class Christof_numeral_1 + { + const A iterA; + const int N; + + public: + T operator()(const int N1, const int N2) const { return iterA(N1, N, N2); } + Christof_numeral_1(const A &a, const int NN) : iterA(a), N(NN) {} + }; +} diff --git a/src/oofemlib/tensor/FTensor/Christof/Christof_pointer.hpp b/src/oofemlib/tensor/FTensor/Christof/Christof_pointer.hpp new file mode 100644 index 000000000..1da14827a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Christof/Christof_pointer.hpp @@ -0,0 +1,245 @@ +/* A version for pointers */ + +#pragma once + +#include "../Tensor3.hpp" + +namespace FTensor +{ + template + class Christof + { + mutable T *restrict data[Tensor_Dim0][(Tensor_Dim12 * (Tensor_Dim12 + 1)) / 2]; + + public: + template Christof(U *... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Christof() {} + + /* There are two operator(int,int,int)'s, one for non-consts that lets you + change the value, and one for consts that doesn't. */ + + T &operator()(const int N1, const int N2, const int N3) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0 + || N3 >= Tensor_Dim12 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Christof.operator(" << N1 << "," << N2 << "," << N3 + << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N2 > N3 ? *data[N1][N2 + (N3 * (2 * Tensor_Dim12 - N3 - 1)) / 2] + : *data[N1][N3 + (N2 * (2 * Tensor_Dim12 - N2 - 1)) / 2]; + } + + T operator()(const int N1, const int N2, const int N3) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0 + || N3 >= Tensor_Dim12 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Christof.operator(" << N1 << "," << N2 << "," << N3 + << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N2 > N3 ? *data[N1][N2 + (N3 * (2 * Tensor_Dim12 - N3 - 1)) / 2] + : *data[N1][N3 + (N2 * (2 * Tensor_Dim12 - N2 - 1)) / 2]; + } + + T *ptr(const int N1, const int N2, const int N3) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0 + || N3 >= Tensor_Dim12 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Christof.ptr(" << N1 << "," << N2 << "," << N3 << ")" + << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N2 > N3 ? data[N1][N2 + (N3 * (2 * Tensor_Dim12 - N3 - 1)) / 2] + : data[N1][N3 + (N2 * (2 * Tensor_Dim12 - N2 - 1)) / 2]; + } + + /* These operator()'s are the first part in constructing template + expressions. I mix up the indices here so that it behaves like a + Dg. That way I don't have to have a separate wrapper + class Christof_Expr, which simplifies things. */ + + template + Dg_Expr, T, Dim12, Dim0, i, j, k> + operator()(const Index index1, const Index index2, + const Index index3) + { + return Dg_Expr, T, Dim12, Dim0, + i, j, k>(*this); + } + + template + Dg_Expr, T, Dim12, Dim0, i, + j, k> + operator()(const Index index1, const Index index2, + const Index index3) const + { + return Dg_Expr, T, Dim12, + Dim0, i, j, k>(*this); + } + + /* These operators are for internal contractions. */ + + /* const versions */ + + template + Tensor1_Expr, T, Dim12>, + T, Dim0, i> + operator()(const Index index1, const Index index2, + const Index index3) const + { + using TensorExpr + = Tensor3_contracted_12, + T, Dim12>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + Tensor1_Expr, T, Dim02>, + T, Dim1, i> + operator()(const Index index1, const Index index2, + const Index index3) const + { + using TensorExpr + = Tensor3_contracted_02, + T, Dim02>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + Tensor1_Expr, T, Dim01>, + T, Dim2, i> + operator()(const Index index1, const Index index2, + const Index index3) const + { + using TensorExpr + = Tensor3_contracted_01, + T, Dim01>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* non-const versions */ + + template + Tensor1_Expr, T, Dim12>, + T, Dim0, i> + operator()(const Index index1, const Index index2, + const Index index3) + { + using TensorExpr + = Tensor3_contracted_12, + T, Dim12>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + Tensor1_Expr, T, Dim02>, + T, Dim1, i> + operator()(const Index index1, const Index index2, + const Index index3) + { + using TensorExpr + = Tensor3_contracted_02, + T, Dim02>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + Tensor1_Expr, T, Dim01>, + T, Dim2, i> + operator()(const Index index1, const Index index2, + const Index index3) + { + using TensorExpr + = Tensor3_contracted_01, + T, Dim01>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* This is for expressions where a number is used for one slot, and + an index for the others, yielding a Tensor2_symmetric_Expr. */ + + template + Tensor2_symmetric_Expr< + const Christof_number_0, + T, N>, + T, Dim12, i, j> + operator()(const Number n1, const Index index1, + const Index index2) const + { + using TensorExpr + = Christof_number_0, T, + N>; + return Tensor2_symmetric_Expr( + TensorExpr(*this)); + } + + /* An int in one spot, Index for the others, yielding a Tensor2. I + can use the same structure for both, since Christof is + symmetric on the last two indices. */ + + template + Tensor2_Expr, T>, + T, Dim0, Dim2, i, j> + operator()(const Index index1, const int N, + const Index index2) const + { + using TensorExpr + = Christof_numeral_1, T>; + return Tensor2_Expr( + TensorExpr(*this, N)); + } + + template + Tensor2_Expr, T>, + T, Dim0, Dim2, i, j> + operator()(const Index index1, const Index index2, + const int N) const + { + using TensorExpr + = Christof_numeral_1, T>; + return Tensor2_Expr( + TensorExpr(*this, N)); + } + + /* The ++ operator increments the pointer, not the number that the + pointer points to. This allows iterating over a grid. */ + + const Christof &operator++() const + { + for(int i = 0; i < Tensor_Dim0; ++i) + for(int j = 0; j < (Tensor_Dim12 * (Tensor_Dim12 + 1)) / 2; ++j) + ++data[i][j]; + return *this; + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Christof/Christof_value.hpp b/src/oofemlib/tensor/FTensor/Christof/Christof_value.hpp new file mode 100644 index 000000000..395d1d9d8 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Christof/Christof_value.hpp @@ -0,0 +1,327 @@ +/* A general version, not for pointers */ + +#pragma once + +#include "../Dg.hpp" + +namespace FTensor +{ + template class Christof + { + T data[Tensor_Dim0][(Tensor_Dim12 * (Tensor_Dim12 + 1)) / 2]; + + public: + template Christof(U... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Christof() {} + + /* There are two operator(int,int,int)'s, one for non-consts that lets you + change the value, and one for consts that doesn't. */ + + T &operator()(const int N1, const int N2, const int N3) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0 + || N3 >= Tensor_Dim12 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Christof.operator(" << N1 << "," << N2 << "," << N3 << ")" + << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N2 > N3 ? data[N1][N2 + (N3 * (2 * Tensor_Dim12 - N3 - 1)) / 2] + : data[N1][N3 + (N2 * (2 * Tensor_Dim12 - N2 - 1)) / 2]; + } + + T operator()(const int N1, const int N2, const int N3) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0 + || N3 >= Tensor_Dim12 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Christof.operator(" << N1 << "," << N2 << "," << N3 << ") const" + << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N2 > N3 ? data[N1][N2 + (N3 * (2 * Tensor_Dim12 - N3 - 1)) / 2] + : data[N1][N3 + (N2 * (2 * Tensor_Dim12 - N2 - 1)) / 2]; + } + + /* These operator()'s are the first part in constructing template + expressions. I mix up the indices here so that it behaves like a + Dg. That way I don't have to have a separate wrapper + class Christof_Expr, which simplifies things. */ + + template + typename std::enable_if<(Tensor_Dim0 >= Dim0 && Tensor_Dim12 >= Dim12), + Dg_Expr, T, + Dim12, Dim0, i, j, k>>::type + operator()(const Index, const Index, + const Index) + { + return Dg_Expr, T, Dim12, Dim0, i, + j, k>(*this); + } + + template + typename std::enable_if<(Tensor_Dim0 >= Dim0 && Tensor_Dim12 >= Dim12), + Dg_Expr, + T, Dim12, Dim0, i, j, k>>::type + operator()(const Index, const Index, + const Index) const + { + return Dg_Expr, T, Dim12, + Dim0, i, j, k>(*this); + } + + /* This is for expressions where a number is used for two slots, and + an Index for the other, yielding a Tensor1_Expr. The non-const + versions don't actually create a Dg_number_rhs_* object, + while the const versions do create a Dg_number_*. */ + + /* Index in first slot. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim12 > N1 && Tensor_Dim12 > N2), + Tensor1_Expr< + Dg_number_rhs_12, T, N1, N2>, T, + Dim, i>>::type + operator()(const Index, const Number, const Number) + { + using TensorExpr + = Dg_number_rhs_12, T, N1, N2>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim12 > N1 && Tensor_Dim12 > N2), + Tensor1_Expr< + Dg_number_12, T, N1, N2>, T, + Dim, i>>::type + operator()(const Index, const Number, const Number) const + { + using TensorExpr + = Dg_number_12, T, N1, N2>; + return Tensor1_Expr(TensorExpr(*this)); + } + // TODO index on second and third position + + /* These operators are for internal contractions. Some of them are + less general, because, for example, A(j,i,j) with i and j having + different dimensions is ambiguous. */ + + /* const versions */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim12 >= Dim12), + Tensor1_Expr< + Tensor3_contracted_12, T, Dim12>, + T, Dim0, i>>::type + operator()(const Index, const Index, + const Index) const + { + using TensorExpr + = Tensor3_contracted_12, T, + Dim12>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim12 >= Dim), + Tensor1_Expr< + Tensor3_contracted_02, T, Dim>, + T, Dim, i>>::type + operator()(const Index, const Index, + const Index) const + { + using TensorExpr + = Tensor3_contracted_02, T, Dim>; + return Tensor1_Expr(TensorExpr(*this)); + } + // TODO allow different dimensions here ^^^^ with the one below + // template + // Tensor1_Expr,T,Dim02>,T,Dim1,i> + // operator()(const Index index1, const Index index2, + // const Index index3) const + // { + // typedef Tensor3_contracted_02 + // ,T,Dim02> + // TensorExpr; + // return Tensor1_Expr(TensorExpr(*this)); + // } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim12 >= Dim), + Tensor1_Expr< + Tensor3_contracted_01, T, Dim>, + T, Dim, i>>::type + operator()(const Index, const Index, + const Index) const + { + using TensorExpr + = Tensor3_contracted_01, T, Dim>; + return Tensor1_Expr(TensorExpr(*this)); + } + // TODO allow different dimensions here ^^^^ with the one below + // template + // Tensor1_Expr,T,Dim01>,T,Dim2,i> + // operator()(const Index index1, const Index index2, + // const Index index3) const + // { + // typedef Tensor3_contracted_01 + // ,T,Dim01> + // TensorExpr; + // return Tensor1_Expr(TensorExpr(*this)); + // } + + /* non-const versions, needed so that overload resolution doesn't + pick the more general indexing operator. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim12 >= Dim12), + Tensor1_Expr< + Tensor3_contracted_12, T, Dim12>, + T, Dim0, i>>::type + operator()(const Index, const Index, + const Index) + { + using TensorExpr + = Tensor3_contracted_12, T, + Dim12>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim12 >= Dim), + Tensor1_Expr< + Tensor3_contracted_02, T, Dim>, + T, Dim, i>>::type + operator()(const Index, const Index, const Index) + { + using TensorExpr + = Tensor3_contracted_02, T, Dim>; + return Tensor1_Expr(TensorExpr(*this)); + } + // TODO allow different dimensions here ^^^^ with the one below + // template + // Tensor1_Expr,T,Dim02>,T,Dim1,i> + // operator()(const Index index1, const Index index2, + // const Index index3) + // { + // typedef Tensor3_contracted_02 + // ,T,Dim02> + // TensorExpr; + // return Tensor1_Expr(TensorExpr(*this)); + // } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim12 >= Dim), + Tensor1_Expr< + Tensor3_contracted_01, T, Dim>, + T, Dim, i>>::type + operator()(const Index, const Index, const Index) + { + using TensorExpr + = Tensor3_contracted_01, T, Dim>; + return Tensor1_Expr(TensorExpr(*this)); + } + + // template + // Tensor1_Expr,T,Dim01>,T,Dim2,i> + // operator()(const Index index1, const Index index2, + // const Index index3) + // { + // typedef Tensor3_contracted_01 + // ,T,Dim01> + // TensorExpr; + // return Tensor1_Expr(TensorExpr(*this)); + // } + + /* This is for expressions where a Number<> is used for one slot, and + an index for the others, yielding a Tensor2_symmetric_Expr. */ + + template + typename std::enable_if< + (Tensor_Dim0 > N && Tensor_Dim12 >= Dim12), + Tensor2_symmetric_Expr< + Christof_number_0, T, N>, T, + Dim12, i, j>>::type + operator()(const Number, const Index, + const Index) const + { + using TensorExpr + = Christof_number_0, T, N>; + return Tensor2_symmetric_Expr( + TensorExpr(*this)); + } + // TODO Allow multiple dimensions here + /* This is for expressions where an int is used for one slot, and + an index for the others, yielding a Tensor2_symmetric_Expr. */ + + template + typename std::enable_if< + (Tensor_Dim12 >= Dim12), + Tensor2_symmetric_Expr< + Christof_numeral_0, T>, T, + Dim12, i, j>>::type + operator()(const int N, const Index, const Index) const + { + using TensorExpr + = Christof_numeral_0, T>; + return Tensor2_symmetric_Expr( + TensorExpr(*this, N)); + } + // TODO allow multiple dimensions here + /* An int in one spot, Index for the others, yielding a Tensor2. I + can use the same structure for both, since Christof is + symmetric on the last two indices. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim12 >= Dim2), + Tensor2_Expr, T>, + T, Dim0, Dim2, i, j>>::type + operator()(const Index, const int N, const Index) const + { + using TensorExpr + = Christof_numeral_1, T>; + return Tensor2_Expr( + TensorExpr(*this, N)); + } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim12 >= Dim2), + Tensor2_Expr, T>, + T, Dim0, Dim2, i, j>>::type + operator()(const Index, const Index, const int N) const + { + using TensorExpr + = Christof_numeral_1, T>; + return Tensor2_Expr( + TensorExpr(*this, N)); + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Ddg.hpp b/src/oofemlib/tensor/FTensor/Ddg.hpp new file mode 100644 index 000000000..ec29e41a3 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg.hpp @@ -0,0 +1,13 @@ +/* Declaration for Ddg, which is separately symmetric on the + first two and last two indices. */ + +#include "Ddg/Ddg_number.hpp" +#include "Ddg/Ddg_numeral.hpp" + +#include "Ddg/Ddg_pointer.hpp" +#include "Ddg/Ddg_value.hpp" + +/* The Expression files which define the generic intermediate template + as well as a place where assignment gets done. */ + +#include "Ddg/Ddg_Expr.hpp" diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_Expr.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_Expr.hpp new file mode 100644 index 000000000..63db90417 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_Expr.hpp @@ -0,0 +1,66 @@ +/* Declares a wrapper class for rank 4 Tensor expressions symmetric on + the first two and last two indices. */ + +#pragma once + +#include "Ddg_and_Ddg.hpp" +#include "Ddg_and_Tensor2_symmetric.hpp" +#include "Ddg_carat_Ddg.hpp" +#include "Ddg_carat_Tensor2_symmetric.hpp" +#include "Ddg_minus_Ddg.hpp" +#include "Ddg_mod_Tensor2_symmetric.hpp" +#include "Ddg_or_Ddg.hpp" +#include "Ddg_plus_Ddg.hpp" +#include "Ddg_times_Ddg.hpp" +#include "Ddg_times_Tensor1.hpp" +#include "Ddg_times_Tensor2.hpp" +#include "Ddg_times_Tensor2_symmetric.hpp" +#include "Ddg_times_generic.hpp" +#include "minus_Ddg.hpp" +// #include "Ddg_mod_Ddg.hpp" + +namespace FTensor +{ + template + class Ddg_Expr + { + A iter; + + public: + Ddg_Expr(const A &a) : iter(a) {} + T operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iter(N1, N2, N3, N4); + } + }; + + template + class Ddg_Expr, T, Dim01, Dim23, i, j, k, + l> + { + Ddg &iter; + + public: + Ddg_Expr(Ddg &a) : iter(a) {} + T operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iter(N1, N2, N3, N4); + } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + Ddg_Expr, T, Dim01, Dim23, i, j, k, l> & + operator=(const Ddg_Expr &result); + + Ddg_Expr, T, Dim01, Dim23, i, j, k, l> & + operator=(const Ddg_Expr, T, Dim01, + Dim23, i, j, k, l> &result); + }; +} + +#include "Ddg_Expr_equals.hpp" diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_Expr_equals.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_Expr_equals.hpp new file mode 100644 index 000000000..76ea48e5b --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_Expr_equals.hpp @@ -0,0 +1,106 @@ +/* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + +#pragma once + +namespace FTensor +{ + template + void + T4ddg_equals_T4ddg(A &iter, + const Ddg_Expr &result, + const Number &, + const Number &, + const Number &, + const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1, + Current_Dim3 - 1) + = result(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1, + Current_Dim3 - 1); + T4ddg_equals_T4ddg(iter, result, Number(), + Number(), Number(), + Number()); + } + + template + void + T4ddg_equals_T4ddg(A &iter, + const Ddg_Expr &result, + const Number<1> &, const Number &, + const Number &, + const Number &) + { + iter(0, Current_Dim1 - 1, Current_Dim2 - 1, Current_Dim3 - 1) + = result(0, Current_Dim1 - 1, Current_Dim2 - 1, Current_Dim3 - 1); + T4ddg_equals_T4ddg(iter, result, Number(), + Number(), Number(), + Number()); + } + + template + void + T4ddg_equals_T4ddg(A &iter, + const Ddg_Expr &result, + const Number<1> &, const Number<1> &, + const Number &, + const Number &) + { + iter(0, 0, Current_Dim2 - 1, Current_Dim3 - 1) + = result(0, 0, Current_Dim2 - 1, Current_Dim3 - 1); + T4ddg_equals_T4ddg(iter, result, Number(), Number(), + Number(), Number()); + } + + template + void + T4ddg_equals_T4ddg(A &iter, + const Ddg_Expr &result, + const Number<1> &, const Number<1> &, const Number<1> &, + const Number &) + { + iter(0, 0, 0, Current_Dim3 - 1) = result(0, 0, 0, Current_Dim3 - 1); + T4ddg_equals_T4ddg(iter, result, Number(), Number(), + Number(), Number()); + } + + template + void + T4ddg_equals_T4ddg(A &iter, + const Ddg_Expr &result, + const Number<1> &, const Number<1> &, const Number<1> &, + const Number<1> &) + { + iter(0, 0, 0, 0) = result(0, 0, 0, 0); + } + + template + template + Ddg_Expr, T, Dim01, Dim23, i, j, k, l> & + Ddg_Expr, T, Dim01, Dim23, i, j, k, l>:: + operator=(const Ddg_Expr &result) + { + T4ddg_equals_T4ddg(iter, result, Number(), Number(), + Number(), Number()); + return *this; + } + + template + Ddg_Expr, T, Dim01, Dim23, i, j, k, l> & + Ddg_Expr, T, Dim01, Dim23, i, j, k, l>:: + operator=(const Ddg_Expr, T, Dim01, Dim23, + i, j, k, l> &result) + { + return operator=, T>(result); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_and_Ddg.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_and_Ddg.hpp new file mode 100644 index 000000000..3ecee8b7d --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_and_Ddg.hpp @@ -0,0 +1,74 @@ +/* Subtracts Ddg-Ddg -> Riemann */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l) - B(i,l,k,j) */ + + template + class Ddg_and_Ddg0321 + { + Ddg_Expr iterA; + Ddg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N3, N2, N4) - iterB(N1, N4, N3, N2); + } + + Ddg_and_Ddg0321(const Ddg_Expr &a, + const Ddg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Riemann_Expr, + typename promote::V, Dim, i, j, k, l> + operator&&(const Ddg_Expr &a, + const Ddg_Expr &b) + { + using TensorExpr = Ddg_and_Ddg0321; + return Riemann_Expr::V, Dim, i, j, k, l>( + TensorExpr(a, b)); + } + + /* A(i,k,l,j) - B(i,l,k,j) */ + + template + class Ddg_and_Ddg0213 + { + Ddg_Expr iterA; + Ddg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N3, N4, N2) - iterB(N1, N4, N3, N2); + } + + Ddg_and_Ddg0213(const Ddg_Expr &a, + const Ddg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Riemann_Expr, + typename promote::V, Dim, i, j, k, l> + operator&&(const Ddg_Expr &a, + const Ddg_Expr &b) + { + using TensorExpr = Ddg_and_Ddg0213; + return Riemann_Expr::V, Dim, i, j, k, l>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_and_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_and_Tensor2_symmetric.hpp new file mode 100644 index 000000000..81337dada --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_and_Tensor2_symmetric.hpp @@ -0,0 +1,207 @@ +/* Multiply a Tensor2_symmetric and a Ddg together but don't + contract, yielding a Ddg. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Ddg_and_Tensor2_symmetric + {}; + + /* A(i,j,k,l) & B(i,j) -> Ddg */ + + template + class Ddg_and_Tensor2_symmetric + { + Ddg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) * iterB(N1, N2); + } + + Ddg_and_Tensor2_symmetric( + const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* B(i,j) & A(i,j,k,l) -> Ddg */ + + /* A(i,j,k,l) & B(k,l) -> Ddg */ + + template + class Ddg_and_Tensor2_symmetric + { + Ddg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) * iterB(N3, N4); + } + + Ddg_and_Tensor2_symmetric( + const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Ddg_Expr, + typename promote::V, Dim01_0, Dim23_0, i0, j0, k0, l0> + operator&(const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Ddg_and_Tensor2_symmetric; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the & operator"); + return Ddg_Expr::V, Dim01_0, Dim23_0, + i0, j0, k0, l0>(TensorExpr(a, b)); + } + + /* B(k,l) & A(i,j,k,l) -> Ddg */ + + template + Ddg_Expr, + typename promote::V, Dim01_0, Dim23_0, i0, j0, k0, l0> + operator&(const Tensor2_symmetric_Expr &b, + const Ddg_Expr &a) + { + using TensorExpr + = Ddg_and_Tensor2_symmetric; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the & operator"); + return Ddg_Expr::V, Dim01_0, Dim23_0, + i0, j0, k0, l0>(TensorExpr(a, b)); + } + + /* I originally put these declarations for unknown reasons, but they + won't work because the result is not a Ddg. The + multiplication messes up the symmetries. */ + + // /* A(i,j,k,l) & B(j,l) -> Ddg */ + + // template + // class Ddg_and_Tensor2_symmetric_13 + // { + // const Ddg_Expr iterA; + // const Tensor2_symmetric_Expr iterB; + // public: + // typename promote::V operator()(const int N1, const int N2, const + // int N3, + // const int N4) const + // { + // return iterA(N1,N2,N3,N4)*iterB(N2,N4); + // } + + // Ddg_and_Tensor2_symmetric_13 + // (const Ddg_Expr &a, + // const Tensor2_symmetric_Expr &b): iterA(a), iterB(b) {} + // }; + + // template + // const Ddg_Expr + // , + // typename promote::V,Dim,Dim,i,j,k,l> + // operator&(const Ddg_Expr &a, + // const Tensor2_symmetric_Expr &b) + // { + // typedef Ddg_and_Tensor2_symmetric_13 + // TensorExpr; + // return Ddg_Expr::V,Dim,Dim,i,j,k,l> + // (TensorExpr(a,b)); + // } + + // /* B(j,l) & A(i,j,k,l) -> Ddg */ + + // template + // const Ddg_Expr + // , + // typename promote::V,Dim,Dim,i,j,k,l> + // operator&(const Tensor2_symmetric_Expr &b, + // const Ddg_Expr &a) + // { + // typedef Ddg_and_Tensor2_symmetric_13 + // TensorExpr; + // return Ddg_Expr::V,Dim,Dim,i,j,k,l> + // (TensorExpr(a,b)); + // } + + // /* A(i,j,k,l) & B(l,j) -> Ddg */ + + // template + // class Ddg_and_Tensor2_symmetric_31 + // { + // const Ddg_Expr iterA; + // const Tensor2_symmetric_Expr iterB; + // public: + // typename promote::V operator()(const int N1, const int N2, const + // int N3, + // const int N4) const + // { + // return iterA(N1,N2,N3,N4)*iterB(N2,N4); + // } + + // Ddg_and_Tensor2_symmetric_31 + // (const Ddg_Expr &a, + // const Tensor2_symmetric_Expr &b): iterA(a), iterB(b) {} + // }; + + // template + // const Ddg_Expr + // , + // typename promote::V,Dim,Dim,i,j,k,l> + // operator&(const Ddg_Expr &a, + // const Tensor2_symmetric_Expr &b) + // { + // typedef Ddg_and_Tensor2_symmetric_31 + // TensorExpr; + // return Ddg_Expr::V,Dim,Dim,i,j,k,l> + // (TensorExpr(a,b)); + // } + + // /* B(l,j) & A(i,j,k,l) -> Ddg */ + + // template + // const Ddg_Expr + // , + // typename promote::V,Dim,Dim,i,j,k,l> + // operator&(const Tensor2_symmetric_Expr &b, + // const Ddg_Expr &a) + // { + // typedef Ddg_and_Tensor2_symmetric_31 + // TensorExpr; + // return Ddg_Expr::V,Dim,Dim,i,j,k,l> + // (TensorExpr(a,b)); + // } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_carat_Ddg.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_carat_Ddg.hpp new file mode 100644 index 000000000..2aa00a421 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_carat_Ddg.hpp @@ -0,0 +1,67 @@ +/* This file has all of the declarations for expressions like + Ddg^Ddg, yielding a Ddg. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(j,l,m,n) */ + + template + class Ddg_carat_Ddg_13 + { + Ddg_Expr iterA; + Ddg_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const int N3, const int N4, + const Number &, const Number &) const + { + return iterA(Current_Dim0 - 1, N1, Current_Dim1 - 1, N2) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1, N3, N4) + + eval(N1, N2, N3, N4, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const int N3, const int N4, + const Number<1> &, const Number &) const + { + return iterA(0, N1, Current_Dim1 - 1, N2) + * iterB(0, Current_Dim1 - 1, N3, N4) + + eval(N1, N2, N3, N4, Number(), Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const int N4, + const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, 0, N2) * iterB(0, 0, N3, N4); + } + + public: + Ddg_carat_Ddg_13(const Ddg_Expr &a, + const Ddg_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return eval(N1, N2, N3, N4, Number(), Number()); + } + }; + + template + Ddg_Expr, + typename promote::V, Dim, Dim23, i, k, m, n> + operator^(const Ddg_Expr &a, + const Ddg_Expr &b) + { + using TensorExpr + = Ddg_carat_Ddg_13; + return Ddg_Expr::V, Dim, Dim23, i, k, m, + n>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_carat_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_carat_Tensor2_symmetric.hpp new file mode 100644 index 000000000..bf460397f --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_carat_Tensor2_symmetric.hpp @@ -0,0 +1,83 @@ +/* This file has all of the declarations for expressions like + Ddg^Tensor2_symmetric and Tensor2_symmetric^Ddg, + yielding a Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(j,l) */ + + template + class Ddg_carat_Tensor2_symmetric_13 + { + Ddg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, Current_Dim1 - 1, N2) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(0, N1, Current_Dim1 - 1, N2) * iterB(0, Current_Dim1 - 1) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, 0, N2) * iterB(0, 0); + } + + public: + Ddg_carat_Tensor2_symmetric_13( + const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + }; + + template + Tensor2_symmetric_Expr< + Ddg_carat_Tensor2_symmetric_13, + typename promote::V, Dim, i, k> + operator^(const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Ddg_carat_Tensor2_symmetric_13; + return Tensor2_symmetric_Expr::V, Dim, + i, k>(TensorExpr(a, b)); + } + + /* B(j,l)*A(i,j,k,l) */ + + template + Tensor2_symmetric_Expr< + Ddg_carat_Tensor2_symmetric_13, + typename promote::V, Dim, i, k> + operator^(const Tensor2_symmetric_Expr &b, + const Ddg_Expr &a) + { + using TensorExpr + = Ddg_carat_Tensor2_symmetric_13; + return Tensor2_symmetric_Expr::V, Dim, + i, k>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_minus_Ddg.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_minus_Ddg.hpp new file mode 100644 index 000000000..8a9b91e3e --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_minus_Ddg.hpp @@ -0,0 +1,40 @@ +/* Subtracts Ddg-Ddg -> Ddg */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l) - B(i,j,k,l) */ + + template + class Ddg_minus_Ddg + { + Ddg_Expr iterA; + Ddg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) - iterB(N1, N2, N3, N4); + } + + Ddg_minus_Ddg(const Ddg_Expr &a, + const Ddg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Ddg_Expr, + typename promote::V, Dim01, Dim23, i, j, k, l> + operator-(const Ddg_Expr &a, + const Ddg_Expr &b) + { + using TensorExpr = Ddg_minus_Ddg; + return Ddg_Expr::V, Dim01, Dim23, i, j, + k, l>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_mod_Ddg.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_mod_Ddg.hpp new file mode 100644 index 000000000..84c1d583b --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_mod_Ddg.hpp @@ -0,0 +1,40 @@ +/* Subtracts Ddg-Ddg -> Riemann */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l) - B(i,l,k,j) */ + + template + class Ddg_mod_Ddg + { + Ddg_Expr iterA; + Ddg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) - iterB(N1, N4, N3, N2); + } + + Ddg_mod_Ddg(const Ddg_Expr &a, + const Ddg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Riemann_Expr, + typename promote::V, Dim, i, j, k, l> + operator%(const Ddg_Expr &a, + const Ddg_Expr &b) + { + using TensorExpr = Ddg_mod_Ddg; + return Riemann_Expr::V, Dim, i, j, k, l>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_mod_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_mod_Tensor2_symmetric.hpp new file mode 100644 index 000000000..63414d3cb --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_mod_Tensor2_symmetric.hpp @@ -0,0 +1,101 @@ +/* Divide a Ddg by a Tensor2_symmetric without contracting, yielding a + Ddg. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Ddg_mod_Tensor2_symmetric + {}; + + /* A(i,j,k,l) % B(i,j) -> Ddg */ + + template + class Ddg_mod_Tensor2_symmetric + { + Ddg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) / iterB(N1, N2); + } + + Ddg_mod_Tensor2_symmetric( + const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* B(i,j) % A(i,j,k,l) -> Ddg */ + + /* A(i,j,k,l) % B(k,l) -> Ddg */ + + template + class Ddg_mod_Tensor2_symmetric + { + Ddg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) / iterB(N3, N4); + } + + Ddg_mod_Tensor2_symmetric( + const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Ddg_Expr, + typename promote::V, Dim01_0, Dim23_0, i0, j0, k0, l0> + operator%(const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Ddg_mod_Tensor2_symmetric; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the % operator"); + return Ddg_Expr::V, Dim01_0, Dim23_0, + i0, j0, k0, l0>(TensorExpr(a, b)); + } + + /* B(k,l) % A(i,j,k,l) -> Ddg */ + + template + Ddg_Expr, + typename promote::V, Dim01_0, Dim23_0, i0, j0, k0, l0> + operator%(const Tensor2_symmetric_Expr &b, + const Ddg_Expr &a) + { + using TensorExpr + = Ddg_mod_Tensor2_symmetric; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the % operator"); + return Ddg_Expr::V, Dim01_0, Dim23_0, + i0, j0, k0, l0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_number.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_number.hpp new file mode 100644 index 000000000..714a14e69 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_number.hpp @@ -0,0 +1,42 @@ +/* This is for expressions where a number is used for one or more + slots, and an index for the others, yielding a + Tensor2_symmetric_Expr or Dg_Expr. */ + +#pragma once + +namespace FTensor +{ + /* First and second slot. */ + + template class Ddg_number_01 + { + A iterA; + + public: + T operator()(const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4); + } + Ddg_number_01(const A &a) : iterA(a) {} + }; + + template class Ddg_number_rhs_01 + {}; + + /* Only first slot */ + + template class Ddg_number_0 + { + A iterA; + + public: + T operator()(const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4); + } + Ddg_number_0(const A &a) : iterA(a) {} + }; + + template class Ddg_number_rhs_0 + {}; +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_numeral.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_numeral.hpp new file mode 100644 index 000000000..56672084b --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_numeral.hpp @@ -0,0 +1,92 @@ +/* This is for expressions where a number is used for one or more + slots, and an index for the others, yielding a + Tensor2_symmetric_Expr or Dg_Expr. */ + +#pragma once + +namespace FTensor +{ + /* First and second slot. */ + + template class Ddg_numeral_01 + { + A iterA; + int N1, N2; + + public: + T operator()(const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4); + } + Ddg_numeral_01(const A &a, const int NN1, const int NN2) + : iterA(a), N1(NN1), N2(NN2) + {} + }; + + /* Third and fourth slot. */ + + template class Ddg_numeral_23 + { + A iterA; + int N3, N4; + + public: + T operator()(const int N1, const int N2) const + { + return iterA(N1, N2, N3, N4); + } + Ddg_numeral_23(const A &a, const int NN3, const int NN4) + : iterA(a), N3(NN3), N4(NN4) + {} + }; + + /* First and third slot. */ + + template class Ddg_numeral_02 + { + A iterA; + int N1, N3; + + public: + T operator()(const int N2, const int N4) const + { + return iterA(N1, N2, N3, N4); + } + Ddg_numeral_02(const A &a, const int NN1, const int NN3) + : iterA(a), N1(NN1), N3(NN3) + {} + }; + + /* Only first slot */ + + /* I think I have to be careful to make sure that the indices are + matched correctly, because the expression that calls it is a + Dg. */ + + template class Ddg_numeral_0 + { + A iterA; + int N1; + + public: + T operator()(const int N2, const int N3, const int N4) const + { + return iterA(N1, N4, N2, N3); + } + Ddg_numeral_0(const A &a, const int NN1) : iterA(a), N1(NN1) {} + }; + + /* Second, third and fourth slot. */ + + template class Ddg_numeral_123 + { + A iterA; + int N1, N2, N3; + + public: + T operator()(const int N0) const { return iterA(N0, N1, N2, N3); } + Ddg_numeral_123(const A &a, const int NN1, const int NN2, const int NN3) + : iterA(a), N1(NN1), N2(NN2), N3(NN3) + {} + }; +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_or_Ddg.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_or_Ddg.hpp new file mode 100644 index 000000000..12915bfb9 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_or_Ddg.hpp @@ -0,0 +1,40 @@ +/* Declares expressions of Ddg || Ddg. This adds them in + a different way, but still ending up with a Ddg. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)+B(i,l,k,j) -> Ddg */ + + template + class Ddg_or_Ddg + { + Ddg_Expr iterA; + Ddg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N3, N2, N4) + iterB(N1, N4, N2, N3); + } + Ddg_or_Ddg(const Ddg_Expr &a, + const Ddg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Ddg_Expr, typename promote::V, + Dim, Dim, i, k, j, l> + operator||(const Ddg_Expr &a, + const Ddg_Expr &b) + { + using TensorExpr = Ddg_or_Ddg; + return Ddg_Expr::V, Dim, Dim, i, k, j, + l>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_or_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_or_Tensor2_symmetric.hpp new file mode 100644 index 000000000..ffbeb3dc2 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_or_Tensor2_symmetric.hpp @@ -0,0 +1,83 @@ +/* This file has all of the declarations for expressions like + Ddg|Tensor2_symmetric and Tensor2_symmetric|Ddg, + yielding a Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(j,l) */ + + template + class Ddg_or_Tensor2_symmetric_13 + { + Ddg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, Current_Dim1 - 1, N2) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(0, N1, Current_Dim1 - 1, N2) * iterB(0, Current_Dim1 - 1) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, 0, N2) * iterB(0, 0); + } + + public: + Ddg_or_Tensor2_symmetric_13( + const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + }; + + template + Tensor2_symmetric_Expr< + Ddg_or_Tensor2_symmetric_13, + typename promote::V, Dim, i, k> + operator|(const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Ddg_or_Tensor2_symmetric_13; + return Tensor2_symmetric_Expr::V, Dim, + i, k>(TensorExpr(a, b)); + } + + /* B(j,l)*A(i,j,k,l) */ + + template + Tensor2_symmetric_Expr< + Ddg_or_Tensor2_symmetric_13, + typename promote::V, Dim, i, k> + operator|(const Tensor2_symmetric_Expr &b, + const Ddg_Expr &a) + { + using TensorExpr + = Ddg_or_Tensor2_symmetric_13; + return Tensor2_symmetric_Expr::V, Dim, + i, k>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_plus_Ddg.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_plus_Ddg.hpp new file mode 100644 index 000000000..5839fce5b --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_plus_Ddg.hpp @@ -0,0 +1,77 @@ +/* Adds Ddg+Ddg -> Ddg */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Ddg_plus_Ddg + {}; + + /* A(i,j,k,l)+B(i,j,k,l) -> Ddg */ + + template + class Ddg_plus_Ddg + { + Ddg_Expr iterA; + Ddg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) + iterB(N1, N2, N3, N4); + } + + Ddg_plus_Ddg(const Ddg_Expr &a, + const Ddg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k,l)+B(k,l,i,j) -> Ddg */ + // TODO: Add rest of combinations (k,l,j,i), (l,k,i,j), (l,k,j,i) + template + class Ddg_plus_Ddg + { + Ddg_Expr iterA; + Ddg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) + iterB(N3, N4, N1, N2); + } + + Ddg_plus_Ddg(const Ddg_Expr &a, + const Ddg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Ddg_Expr, + typename promote::V, Dim01_0, Dim23_0, i0, j0, k0, l0> + operator+(const Ddg_Expr &a, + const Ddg_Expr &b) + { + using TensorExpr = Ddg_plus_Ddg; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the + operator"); + return Ddg_Expr::V, Dim01_0, Dim23_0, + i0, j0, k0, l0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_pointer.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_pointer.hpp new file mode 100644 index 000000000..60c148020 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_pointer.hpp @@ -0,0 +1,254 @@ +/* A version for pointers. */ + +#pragma once + +namespace FTensor +{ + template + class Ddg + { + mutable T *restrict data[(Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2] + [(Tensor_Dim23 * (Tensor_Dim23 + 1)) / 2]; + + public: + /* There are two operator(int,int,int,int)'s, one for non-consts + that lets you change the value, and one for consts that + doesn't. */ + + T &operator()(const int N1, const int N2, const int N3, const int N4) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0 + || N3 >= Tensor_Dim23 || N3 < 0 || N4 >= Tensor_Dim23 || N4 < 0) + { + std::stringstream s; + s << "Bad index in Dg.operator(" << N1 << "," << N2 << "," << N3 << "," << N4 + << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 + ? (N3 > N4 ? *data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2] + [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2] + : *data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2] + [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2]) + : (N3 > N4 + ? *data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2] + [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2] + : *data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2] + [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2]); + } + + T operator()(const int N1, const int N2, const int N3, const int N4) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0 + || N3 >= Tensor_Dim23 || N3 < 0 || N4 >= Tensor_Dim23 || N4 < 0) + { + std::stringstream s; + s << "Bad index in Dg.operator(" << N1 << "," << N2 << "," << N3 << "," << N4 + << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 + ? (N3 > N4 ? *data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2] + [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2] + : *data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2] + [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2]) + : (N3 > N4 + ? *data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2] + [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2] + : *data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2] + [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2]); + } + + T *ptr(const int N1, const int N2, const int N3, const int N4) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0 + || N3 >= Tensor_Dim23 || N3 < 0 || N4 >= Tensor_Dim23 || N4 < 0) + { + std::stringstream s; + s << "Bad index in Dg.ptr(" << N1 << "," << N2 << "," << N3 << "," << N4 << ")" + << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 + ? (N3 > N4 ? data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2] + [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2] + : data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2] + [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2]) + : (N3 > N4 ? data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2] + [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2] + : data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2] + [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2]); + } + + /* These operator()'s are the first part in constructing template + expressions. They can be used to slice off lower dimensional + parts. They are not entirely safe, since you can accidently use a + higher dimension than what is really allowed (like Dim=5). */ + + template + Ddg_Expr, T, Dim01, Dim23, i, j, k, l> + operator()(const Index index1, const Index index2, + const Index index3, const Index index4) + { + return Ddg_Expr, T, Dim01, Dim23, i, + j, k, l>(*this); + } + + template + Ddg_Expr, T, Dim01, Dim23, i, j, + k, l> + operator()(const Index index1, const Index index2, + const Index index3, + const Index index4) const + { + return Ddg_Expr, T, Dim01, + Dim23, i, j, k, l>(*this); + } + + /* This is for expressions where a number is used for two slots, and + an index for the other two, yielding a Tensor2_symmetric_Expr. */ + + template + Tensor2_symmetric_Expr< + Ddg_number_01, T, N0, N1>, T, + Dim, i, j> + operator()(const Number n1, const Number n2, + const Index index1, const Index index2) const + { + using TensorExpr + = Ddg_number_01, T, N0, N1>; + return Tensor2_symmetric_Expr( + TensorExpr(*this)); + } + + template + Tensor2_symmetric_Expr< + Ddg_number_rhs_01, T, N0, N1>, T, + Dim, i, j> + operator()(const Number n1, const Number n2, + const Index index1, const Index index2) + { + using TensorExpr + = Ddg_number_rhs_01, T, N0, N1>; + return Tensor2_symmetric_Expr(*this); + } + + /* This is for expressions where a number is used for one slot, and + an index for the other three, yielding a Dg_Expr. */ + + template + Dg_Expr, T, N0>, T, + Dim23, Dim1, i, j, k> + operator()(const Number n1, const Index index3, + const Index index1, + const Index index2) const + { + using TensorExpr + = Ddg_number_0, T, N0>; + return Dg_Expr(TensorExpr(*this)); + } + + template + Dg_Expr, T, N0>, T, + Dim23, Dim1, i, j, k> + operator()(const Number n1, const Index index3, + const Index index1, const Index index2) + { + using TensorExpr + = Ddg_number_rhs_0, T, N0>; + return Dg_Expr(*this); + } + + /* This is for expressions where an int (not a Number) is used for + two slots, and an index for the other two, yielding a + Tensor2_symmetric_Expr. */ + + template + Tensor2_symmetric_Expr< + Ddg_numeral_01, T>, T, Dim, i, + j> + operator()(const int N0, const int N1, const Index index1, + const Index index2) const + { + using TensorExpr + = Ddg_numeral_01, T>; + return Tensor2_symmetric_Expr( + TensorExpr(*this, N0, N1)); + } + + template + Tensor2_symmetric_Expr< + Ddg_numeral_23, T>, T, Dim, i, j> + operator()(const Index index1, const Index index2, + const int N2, const int N3) const + { + using TensorExpr + = Ddg_numeral_23, T>; + return Tensor2_symmetric_Expr( + TensorExpr(*this, N2, N3)); + } + + /* int in three slots, Index in the other yielding a Tensor1_Expr. */ + + template + Tensor1_Expr, T>, T, + Dim, i> + operator()(const Index index1, const int N1, const int N2, + const int N3) + { + using TensorExpr + = Ddg_numeral_123, T>; + return Tensor1_Expr( + TensorExpr(*this, N1, N2, N3)); + } + + template + Tensor1_Expr, T>, T, + Dim, i> + operator()(const int N1, const Index index1, const int N2, + const int N3) + { + using TensorExpr + = Ddg_numeral_123, T>; + return Tensor1_Expr( + TensorExpr(*this, N1, N2, N3)); + } + + /* This is for expressions where an int (not a Number) is used for + one slot, and an index for the other three, yielding a + Dg_Expr. */ + + template + Dg_Expr, T>, T, + Dim23, Dim1, i, j, k> + operator()(const int N0, const Index index3, + const Index index1, + const Index index2) const + { + using TensorExpr + = Ddg_numeral_0, T>; + return Dg_Expr( + TensorExpr(*this, N0)); + } + + /* The ++ operator increments the pointer, not the number that the + pointer points to. This allows iterating over a grid. */ + + const Ddg &operator++() const + { + for(int i = 0; i < (Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2; ++i) + for(int j = 0; j < (Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2; ++j) + ++data[i][j]; + return *this; + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Ddg.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Ddg.hpp new file mode 100644 index 000000000..b79a35a3f --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Ddg.hpp @@ -0,0 +1,94 @@ +/* Fully contract a Ddg with a Ddg. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(i,k,j,l) */ + + template + typename promote::V + T4ddg_times_T4ddg_0213(const Ddg_Expr &a, + const Ddg_Expr &b, + const Number &, + const Number &, + const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1, + Current_Dim3 - 1) + * b(Current_Dim0 - 1, Current_Dim2 - 1, Current_Dim1 - 1, + Current_Dim3 - 1) + + T4ddg_times_T4ddg_0213( + a, b, Number(), Number(), + Number(), Number()); + } + + template + typename promote::V + T4ddg_times_T4ddg_0213(const Ddg_Expr &a, + const Ddg_Expr &b, + const Number<1> &, const Number &, + const Number &, + const Number &) + { + return a(0, Current_Dim1 - 1, Current_Dim2 - 1, Current_Dim3 - 1) + * b(0, Current_Dim2 - 1, Current_Dim1 - 1, Current_Dim3 - 1) + + T4ddg_times_T4ddg_0213( + a, b, Number(), Number(), + Number(), Number()); + } + + template + typename promote::V + T4ddg_times_T4ddg_0213(const Ddg_Expr &a, + const Ddg_Expr &b, + const Number<1> &, const Number<1> &, + const Number &, + const Number &) + { + return a(0, 0, Current_Dim2 - 1, Current_Dim3 - 1) + * b(0, Current_Dim2 - 1, 0, Current_Dim3 - 1) + + T4ddg_times_T4ddg_0213(a, b, Number(), Number(), + Number(), + Number()); + } + + template + typename promote::V + T4ddg_times_T4ddg_0213(const Ddg_Expr &a, + const Ddg_Expr &b, + const Number<1> &, const Number<1> &, + const Number<1> &, const Number &) + { + return a(0, 0, 0, Current_Dim3 - 1) * b(0, 0, 0, Current_Dim3 - 1) + + T4ddg_times_T4ddg_0213(a, b, Number(), Number(), + Number(), Number()); + } + + template + typename promote::V + T4ddg_times_T4ddg_0213(const Ddg_Expr &a, + const Ddg_Expr &b, + const Number<1> &, const Number<1> &, + const Number<1> &, const Number<1> &) + { + return a(0, 0, 0, 0) * b(0, 0, 0, 0); + } + + template + typename promote::V + operator*(const Ddg_Expr &a, + const Ddg_Expr &b) + { + return T4ddg_times_T4ddg_0213(a, b, Number(), Number(), + Number(), Number()); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Tensor1.hpp new file mode 100644 index 000000000..bfecceda9 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Tensor1.hpp @@ -0,0 +1,70 @@ +/* This file has all of the declarations for expressions like + Ddg*Tensor1 and Tensor1*Ddg, yielding a + Dg. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(k)->Dg */ + + template + class Ddg_times_Tensor1_2 + { + Ddg_Expr iterA; + Tensor1_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, N2, Current_Dim - 1, N3) * iterB(Current_Dim - 1) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, N2, 0, N3) * iterB(0); + } + + public: + Ddg_times_Tensor1_2(const Ddg_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Dg_Expr, + typename promote::V, Dim01, Dim23, i, j, l> + operator*(const Ddg_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Ddg_times_Tensor1_2; + return Dg_Expr::V, Dim01, Dim23, i, j, + l>(TensorExpr(a, b)); + } + + /* B(k)*A(i,j,k,l)->Dg */ + + template + Dg_Expr, + typename promote::V, Dim01, Dim23, i, j, l> + operator*(const Tensor1_Expr &b, + const Ddg_Expr &a) + { + using TensorExpr + = Ddg_times_Tensor1_2; + return Dg_Expr::V, Dim01, Dim23, i, j, + l>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Tensor2.hpp new file mode 100644 index 000000000..8e8612d7b --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Tensor2.hpp @@ -0,0 +1,156 @@ +/* This file has all of the declarations for expressions like + Ddg*Tensor2 and Tensor2*Ddg, yielding a + Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(k,l) */ + + template + class Ddg_times_Tensor2_23 + { + Ddg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(N1, N2, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(N1, N2, 0, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(N1, N2, 0, 0) * iterB(0, 0); + } + + public: + Ddg_times_Tensor2_23(const Ddg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + }; + + template + Tensor2_symmetric_Expr< + Ddg_times_Tensor2_23, + typename promote::V, Dim01, i, j> + operator*(const Ddg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Ddg_times_Tensor2_23; + return Tensor2_symmetric_Expr::V, Dim01, + i, j>(TensorExpr(a, b)); + } + + /* B(k,l)*A(i,j,k,l) */ + + template + Tensor2_symmetric_Expr< + Ddg_times_Tensor2_23, + typename promote::V, Dim01, i, j> + operator*(const Tensor2_Expr &b, + const Ddg_Expr &a) + { + using TensorExpr + = Ddg_times_Tensor2_23; + return Tensor2_symmetric_Expr::V, Dim01, + i, j>(TensorExpr(a, b)); + } + + /* A(i,j,k,l)*B(l,k) */ + + template + class Ddg_times_Tensor2_32 + { + Ddg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(N1, N2, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(N1, N2, 0, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(N1, N2, 0, 0) * iterB(0, 0); + } + + public: + Ddg_times_Tensor2_32(const Ddg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + }; + + template + Tensor2_symmetric_Expr< + Ddg_times_Tensor2_32, + typename promote::V, Dim01, i, j> + operator*(const Ddg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Ddg_times_Tensor2_32; + return Tensor2_symmetric_Expr::V, Dim01, + i, j>(TensorExpr(a, b)); + } + + /* B(l,k)*A(i,j,k,l) */ + + template + Tensor2_symmetric_Expr< + Ddg_times_Tensor2_32, + typename promote::V, Dim01, i, j> + operator*(const Tensor2_Expr &b, + const Ddg_Expr &a) + { + using TensorExpr + = Ddg_times_Tensor2_32; + return Tensor2_symmetric_Expr::V, Dim01, + i, j>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Tensor2_symmetric.hpp new file mode 100644 index 000000000..e3112bfb0 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_Tensor2_symmetric.hpp @@ -0,0 +1,231 @@ +/* This file has all of the declarations for expressions like + Ddg*Tensor2_symmetric and Tensor2_symmetric*Ddg, + yielding a Tensor2 or Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(j,l) */ + + template + class Ddg_times_Tensor2_symmetric_13 + { + Ddg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, Current_Dim1 - 1, N2) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(0, N1, Current_Dim1 - 1, N2) * iterB(0, Current_Dim1 - 1) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, 0, N2) * iterB(0, 0); + } + + public: + Ddg_times_Tensor2_symmetric_13( + const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim, Dim, i, k> + operator*(const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Ddg_times_Tensor2_symmetric_13; + return Tensor2_Expr::V, Dim, Dim, i, k>( + TensorExpr(a, b)); + } + + /* B(j,l)*A(i,j,k,l) */ + + template + Tensor2_Expr, + typename promote::V, Dim, Dim, i, k> + operator*(const Tensor2_symmetric_Expr &b, + const Ddg_Expr &a) + { + using TensorExpr + = Ddg_times_Tensor2_symmetric_13; + return Tensor2_Expr::V, Dim, Dim, i, k>( + TensorExpr(a, b)); + } + + /* A(i,j,k,l)*B(i,j) */ + + template + class Ddg_times_Tensor2_symmetric_01 + { + Ddg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, Current_Dim1 - 1, N1, N2) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(0, Current_Dim1 - 1, N1, N2) * iterB(0, Current_Dim1 - 1) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(0, 0, N1, N2) * iterB(0, 0); + } + + public: + Ddg_times_Tensor2_symmetric_01( + const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + }; + + template + Tensor2_symmetric_Expr< + Ddg_times_Tensor2_symmetric_01, + typename promote::V, Dim23, k, l> + operator*(const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Ddg_times_Tensor2_symmetric_01; + return Tensor2_symmetric_Expr::V, Dim23, + k, l>(TensorExpr(a, b)); + } + + /* B(i,j)*A(i,j,k,l) */ + + template + Tensor2_symmetric_Expr< + Ddg_times_Tensor2_symmetric_01, + typename promote::V, Dim23, k, l> + operator*(const Tensor2_symmetric_Expr &b, + const Ddg_Expr &a) + { + using TensorExpr + = Ddg_times_Tensor2_symmetric_01; + return Tensor2_symmetric_Expr::V, Dim23, + k, l>(TensorExpr(a, b)); + } + + /* A(i,j,k,l)*B(k,l) */ + + template + class Ddg_times_Tensor2_symmetric_23 + { + Ddg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(N1, N2, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(N1, N2, 0, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(N1, N2, 0, 0) * iterB(0, 0); + } + + public: + Ddg_times_Tensor2_symmetric_23( + const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + }; + + template + Tensor2_symmetric_Expr< + Ddg_times_Tensor2_symmetric_23, + typename promote::V, Dim01, i, j> + operator*(const Ddg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Ddg_times_Tensor2_symmetric_23; + return Tensor2_symmetric_Expr::V, Dim01, + i, j>(TensorExpr(a, b)); + } + + /* B(k,l)*A(i,j,k,l) */ + + template + Tensor2_symmetric_Expr< + Ddg_times_Tensor2_symmetric_23, + typename promote::V, Dim01, i, j> + operator*(const Tensor2_symmetric_Expr &b, + const Ddg_Expr &a) + { + using TensorExpr + = Ddg_times_Tensor2_symmetric_23; + return Tensor2_symmetric_Expr::V, Dim01, + i, j>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_generic.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_generic.hpp new file mode 100644 index 000000000..ee9ff43fd --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_times_generic.hpp @@ -0,0 +1,33 @@ +/* Multiplies a Ddg with a generic, yielding a + Ddg. */ + +#pragma once + +namespace FTensor +{ + template + auto + operator*(const Ddg_Expr &a, const U &d0) + { + auto TensorExpr + = [&a, &d0](const int N1, const int N2, const int N3, const int N4) { + return a(N1, N2, N3, N4) * d0; + }; + return Ddg_Expr::V, Dim01, + Dim23, i, j, k, l>(TensorExpr); + } + + template + auto + operator*(const U &d0, const Ddg_Expr &a) + { + auto TensorExpr + = [&a, &d0](const int N1, const int N2, const int N3, const int N4) { + return d0 * a(N1, N2, N3, N4); + }; + return Ddg_Expr::V, Dim01, + Dim23, i, j, k, l>(TensorExpr); + } +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/Ddg_value.hpp b/src/oofemlib/tensor/FTensor/Ddg/Ddg_value.hpp new file mode 100644 index 000000000..7e98919e6 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/Ddg_value.hpp @@ -0,0 +1,249 @@ +/* A general version, not for pointers. */ + +#pragma once + +namespace FTensor +{ + template class Ddg + { + T data[(Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2] + [(Tensor_Dim23 * (Tensor_Dim23 + 1)) / 2]; + + public: + /* There are two operator(int,int,int,int)'s, one for non-consts + that lets you change the value, and one for consts that + doesn't. */ + + T &operator()(const int N1, const int N2, const int N3, const int N4) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0 + || N3 >= Tensor_Dim23 || N3 < 0 || N4 >= Tensor_Dim23 || N4 < 0) + { + std::stringstream s; + s << "Bad index in Dg.operator(" << N1 << "," << N2 << "," << N3 << "," << N4 + << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 + ? (N3 > N4 ? data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2] + [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2] + : data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2] + [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2]) + : (N3 > N4 ? data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2] + [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2] + : data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2] + [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2]); + } + + T operator()(const int N1, const int N2, const int N3, const int N4) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0 + || N3 >= Tensor_Dim23 || N3 < 0 || N4 >= Tensor_Dim23 || N4 < 0) + { + std::stringstream s; + s << "Bad index in Dg.operator(" << N1 << "," << N2 << "," << N3 << "," << N4 + << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 + ? (N3 > N4 ? data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2] + [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2] + : data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2] + [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2]) + : (N3 > N4 ? data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2] + [N3 + (N4 * (2 * Tensor_Dim23 - N4 - 1)) / 2] + : data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2] + [N4 + (N3 * (2 * Tensor_Dim23 - N3 - 1)) / 2]); + } + + /* These operator()'s are the first part in constructing template + expressions. They can be used to slice off lower dimensional + parts. They are not entirely safe, since you can accidently use a + higher dimension than what is really allowed (like Dim=5). */ + + template + typename std::enable_if<(Tensor_Dim01 >= Dim01 && Tensor_Dim23 >= Dim23), + Ddg_Expr, T, + Dim01, Dim23, i, j, k, l>>::type + operator()(const Index, const Index, + const Index, const Index) + { + return Ddg_Expr, T, Dim01, Dim23, i, + j, k, l>(*this); + } + + template + typename std::enable_if<(Tensor_Dim01 >= Dim01 && Tensor_Dim23 >= Dim23), + Ddg_Expr, + T, Dim01, Dim23, i, j, k, l>>::type + operator()(const Index, const Index, + const Index, const Index) const + { + return Ddg_Expr, T, Dim01, + Dim23, i, j, k, l>(*this); + } + + /* This is for expressions where a number is used for two slots, and + an index for the other two, yielding a Tensor2_symmetric_Expr. */ + + template + typename std::enable_if< + (Tensor_Dim01 > N0 && Tensor_Dim01 > N1 && Tensor_Dim23 >= Dim), + Tensor2_symmetric_Expr< + Ddg_number_01, T, N0, N1>, T, + Dim, i, j>>::type + operator()(const Number, const Number, const Index, + const Index) const + { + using TensorExpr + = Ddg_number_01, T, N0, N1>; + return Tensor2_symmetric_Expr( + TensorExpr(*this)); + } + + template + typename std::enable_if< + (Tensor_Dim01 > N0 && Tensor_Dim01 > N1 && Tensor_Dim23 >= Dim), + Tensor2_symmetric_Expr< + Ddg_number_rhs_01, T, N0, N1>, T, + Dim, i, j>>::type + operator()(const Number, const Number, const Index, + const Index) + { + using TensorExpr + = Ddg_number_rhs_01, T, N0, N1>; + return Tensor2_symmetric_Expr(*this); + } + + /* This is for expressions where a number is used for one slot, and + an index for the other three, yielding a Dg_Expr. */ + + template + typename std::enable_if< + (Tensor_Dim01 > N0 && Tensor_Dim01 >= Dim1 && Tensor_Dim23 >= Dim23), + Dg_Expr, T, N0>, T, + Dim23, Dim1, i, j, k>>::type + operator()(const Number, const Index, const Index, + const Index) const + { + using TensorExpr + = Ddg_number_0, T, N0>; + return Dg_Expr(TensorExpr(*this)); + } + + template + typename std::enable_if< + (Tensor_Dim01 > N0 && Tensor_Dim01 >= Dim1 && Tensor_Dim23 >= Dim23), + Dg_Expr, T, N0>, T, + Dim23, Dim1, i, j, k>>::type + operator()(const Number, const Index, const Index, + const Index) + { + using TensorExpr + = Ddg_number_rhs_0, T, N0>; + return Dg_Expr(*this); + } + + /* This is for expressions where an int (not a Number) is used for + two slots, and an index for the other two, yielding a + Tensor2_symmetric_Expr. */ + + template + typename std::enable_if< + (Tensor_Dim23 >= Dim), + Tensor2_symmetric_Expr< + Ddg_numeral_01, T>, T, Dim, i, + j>>::type + operator()(const int N0, const int N1, const Index, + const Index) const + { + using TensorExpr + = Ddg_numeral_01, T>; + return Tensor2_symmetric_Expr( + TensorExpr(*this, N0, N1)); + } + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim), + Tensor2_symmetric_Expr< + Ddg_numeral_23, T>, T, Dim, i, + j>>::type + operator()(const Index, const Index, const int N2, + const int N3) const + { + using TensorExpr + = Ddg_numeral_23, T>; + return Tensor2_symmetric_Expr( + TensorExpr(*this, N2, N3)); + } + + /* int in two slots but yielding a Tensor2 */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim1 && Tensor_Dim23 >= Dim3), + Tensor2_Expr, T>, + T, Dim1, Dim3, i, j>>::type + operator()(const int N0, const Index, const int N2, + const Index) const + { + using TensorExpr + = Ddg_numeral_02, T>; + return Tensor2_Expr( + TensorExpr(*this, N0, N2)); + } + + /* int in three slots, Index in the other yielding a Tensor1_Expr. */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim), + Tensor1_Expr, T>, + T, Dim, i>>::type + operator()(const Index, const int N1, const int N2, const int N3) + { + using TensorExpr + = Ddg_numeral_123, T>; + return Tensor1_Expr( + TensorExpr(*this, N1, N2, N3)); + } + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim), + Tensor1_Expr, T>, + T, Dim, i>>::type + operator()(const int N1, const Index, const int N2, const int N3) + { + using TensorExpr + = Ddg_numeral_123, T>; + return Tensor1_Expr( + TensorExpr(*this, N1, N2, N3)); + } + + /* This is for expressions where an int (not a Number) is used for + one slot, and an index for the other three, yielding a + Dg_Expr. */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim1 && Tensor_Dim23 >= Dim23), + Dg_Expr, T>, T, + Dim23, Dim1, i, j, k>>::type + operator()(const int N0, const Index, const Index, + const Index) const + { + using TensorExpr + = Ddg_numeral_0, T>; + return Dg_Expr( + TensorExpr(*this, N0)); + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Ddg/minus_Ddg.hpp b/src/oofemlib/tensor/FTensor/Ddg/minus_Ddg.hpp new file mode 100644 index 000000000..82a80b3c8 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Ddg/minus_Ddg.hpp @@ -0,0 +1,31 @@ +/* Unary minus operator. */ + +#pragma once + +namespace FTensor +{ + template + class minus_Ddg + { + public: + Ddg_Expr iterA; + + public: + T operator()(const int N1, const int N2, const int N3, const int N4) const + { + return -iterA(N1, N2, N3, N4); + } + minus_Ddg(const Ddg_Expr &a) : iterA(a) {} + }; + + template + Ddg_Expr, T, Dim01, Dim23, i, j, k, + l> + operator-(const Ddg_Expr &a) + { + using TensorExpr = minus_Ddg; + return Ddg_Expr(TensorExpr(a)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg.hpp b/src/oofemlib/tensor/FTensor/Dg.hpp new file mode 100644 index 000000000..d58bdb9bc --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg.hpp @@ -0,0 +1,10 @@ +/* Declarations for a Dg. This is symmetric on the first two + indices. */ + +#include "Dg/Dg_number.hpp" +#include "Dg/Dg_numeral.hpp" + +#include "Dg/Dg_pointer.hpp" +#include "Dg/Dg_value.hpp" + +#include "Dg/Dg_Expr.hpp" diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_Expr.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_Expr.hpp new file mode 100644 index 000000000..205da0c0c --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_Expr.hpp @@ -0,0 +1,160 @@ +/* Declares a wrapper class for symmetric rank 3 Tensor expressions + that are symmetric on the first two indices. It is also used for + Christof's but with some games played with the + indices. */ + +#pragma once + +#include "Dg_and_Dg.hpp" +#include "Dg_and_Tensor1.hpp" +#include "Dg_and_Tensor2_symmetric.hpp" +#include "Dg_divide_generic.hpp" +#include "Dg_minus_Dg.hpp" +#include "Dg_or_Dg.hpp" +#include "Dg_plus_Dg.hpp" +#include "Dg_times_Dg.hpp" +#include "Dg_times_Tensor1.hpp" +#include "Dg_times_Tensor2.hpp" +#include "Dg_times_Tensor2_symmetric.hpp" +#include "Dg_times_generic.hpp" +#include "minus_Dg.hpp" + +namespace FTensor +{ + template + class Dg_Expr + { + A iter; + + public: + Dg_Expr(const A &a) : iter(a) {} + T operator()(const int N1, const int N2, const int N3) const + { + return iter(N1, N2, N3); + } + }; + + template + class Dg_Expr, T, Dim01, Dim2, i, j, k> + { + Dg &iter; + + public: + Dg_Expr(Dg &a) : iter(a) {} + T &operator()(const int N1, const int N2, const int N3) + { + return iter(N1, N2, N3); + } + T operator()(const int N1, const int N2, const int N3) const + { + return iter(N1, N2, N3); + } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + Dg_Expr, T, Dim01, Dim2, i, j, k> & + operator=(const Dg_Expr &result); + + Dg_Expr, T, Dim01, Dim2, i, j, k> & + operator=(const Dg_Expr, T, Dim01, Dim2, + i, j, k> &result); + + template + Dg_Expr, T, Dim01, Dim2, i, j, k> & + operator=(const U &d); + }; + + /* I need a version for const and non-const Christof, + otherwise it will use the default and the index order will get all + messed up. The class A is either T or T*, depending on whether + Christof has an array of T's or T *'s. */ + + template + class Dg_Expr, T, Dim12, Dim0, + i, j, k> + { + Christof iter; + + public: + Dg_Expr(const Christof &a) : iter(a) {} + + /* Need to switch the index order because a christof tensor is just + a dg tensor with the indices switched. */ + + T operator()(const int N1, const int N2, const int N3) const + { + return iter(N3, N1, N2); + } + }; + + template + class Dg_Expr, T, Dim12, Dim0, i, j, k> + { + Christof &iter; + + public: + Dg_Expr(Christof &a) : iter(a) {} + + /* Need to switch the index order because a christof tensor is just + a dg tensor with the indices switched. I have to explicitly + declare the second operator= because otherwise the compiler will + generate its own and not use the template code. */ + + T operator()(const int N1, const int N2, const int N3) const + { + return iter(N3, N1, N2); + } + template + Dg_Expr, T, Dim12, Dim0, i, j, k> & + operator=(const Dg_Expr &result); + + Dg_Expr, T, Dim12, Dim0, i, j, k> & + operator=(const Dg_Expr, T, Dim12, + Dim0, i, j, k> &result); + + template + Dg_Expr, T, Dim12, Dim0, i, j, k> & + operator=(const U &d); + }; + + /* Specialized for Ddg_number_rhs_0 (Ddg with the + first index explicitly given). */ + + template + class Dg_Expr, T, Dim23, Dim1, i, j, k> + { + A &iter; + + public: + Dg_Expr(A &a) : iter(a) {} + T &operator()(const int N1, const int N2, const int N3) + { + return iter(N0, N1, N2, N3); + } + T operator()(const int N1, const int N2, const int N3) const + { + return iter(N0, N1, N2, N3); + } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + Dg_Expr, T, Dim23, Dim1, i, j, k> & + operator=(const Dg_Expr &result); + + Dg_Expr, T, Dim23, Dim1, i, j, k> & + operator=(const Dg_Expr, T, Dim23, Dim1, i, j, + k> &result); + }; +} + +#include "Dg_Expr_equals.hpp" diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_Expr_equals.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_Expr_equals.hpp new file mode 100644 index 000000000..2a04d5d4a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_Expr_equals.hpp @@ -0,0 +1,353 @@ +/* Various assignment operators, including specializations to + Christof. I have to explicitly declare the second + operator= because otherwise the compiler will generate its own and + not use the template code. */ + +#pragma once + +namespace FTensor +{ + /* T3dg=T3dg */ + + template + void + T3dg_equals_T3dg(A &iter, const Dg_Expr &result, + const Number &, const Number &, + const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + = result(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1); + T3dg_equals_T3dg(iter, result, Number(), + Number(), Number()); + } + + template + void + T3dg_equals_T3dg(A &iter, const Dg_Expr &result, + const Number<1> &, const Number &, + const Number &) + { + iter(0, Current_Dim1 - 1, Current_Dim2 - 1) + = result(0, Current_Dim1 - 1, Current_Dim2 - 1); + T3dg_equals_T3dg(iter, result, Number(), + Number(), Number()); + } + + template + void + T3dg_equals_T3dg(A &iter, const Dg_Expr &result, + const Number<1> &, const Number<1> &, + const Number &) + { + iter(0, 0, Current_Dim2 - 1) = result(0, 0, Current_Dim2 - 1); + T3dg_equals_T3dg(iter, result, Number(), Number(), + Number()); + } + + template + void + T3dg_equals_T3dg(A &iter, const Dg_Expr &result, + const Number<1> &, const Number<1> &, const Number<1> &) + { + iter(0, 0, 0) = result(0, 0, 0); + } + + template + template + Dg_Expr, T, Dim01, Dim2, i, j, k> & + Dg_Expr, T, Dim01, Dim2, i, j, k>:: + operator=(const Dg_Expr &result) + { + T3dg_equals_T3dg(iter, result, Number(), Number(), + Number()); + return *this; + } + + /* T3dg=T3dg_Expr(T3dg) */ + + template + Dg_Expr, T, Dim01, Dim2, i, j, k> & + Dg_Expr, T, Dim01, Dim2, i, j, k>:: + operator=(const Dg_Expr, T, Dim01, Dim2, i, + j, k> &result) + { + return operator=, T>(result); + } + + /* T3dg=U */ + + template + void T3dg_equals_generic(A &iter, const U &u, const Number &, + const Number &, + const Number &, const Number &, + const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) = u; + T3dg_equals_generic(iter, u, Number(), + Number(), Number(), + Number(), Number()); + } + + template + void T3dg_equals_generic(A &iter, const U &u, const Number<1> &, + const Number &, + const Number &, const Number &, + const Number &) + { + iter(0, Current_Dim1 - 1, Current_Dim2 - 1) = u; + T3dg_equals_generic(iter, u, Number(), + Number(), Number(), + Number(), Number()); + } + + template + void T3dg_equals_generic(A &iter, const U &u, const Number<1> &, + const Number<1> &, const Number &, + const Number &, const Number &) + { + iter(0, 0, Current_Dim2 - 1) = u; + T3dg_equals_generic(iter, u, Number(), Number(), + Number(), Number(), + Number()); + } + + template + void T3dg_equals_generic(A &iter, const U &u, const Number<1> &, + const Number<1> &, const Number<1> &, + const Number &, const Number &) + { + iter(0, 0, 0) = u; + } + + template + template + Dg_Expr, T, Dim01, Dim2, i, j, k> & + Dg_Expr, T, Dim01, Dim2, i, j, k>:: + operator=(const U &u) + { + T3dg_equals_generic(iter, u, Number(), Number(), + Number(), Number(), Number()); + return *this; + } + + /* Assignment operators for the specializations to Christof. */ + + /* T3ch=T3dg */ + + template + void + T3ch_equals_T3dg(A &iter, const Dg_Expr &result, + const Number &, const Number &, + const Number &) + { + iter(Current_Dim2 - 1, Current_Dim0 - 1, Current_Dim1 - 1) + = result(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1); + T3ch_equals_T3dg(iter, result, Number(), + Number(), Number()); + } + + template + void + T3ch_equals_T3dg(A &iter, const Dg_Expr &result, + const Number<1> &, const Number &, + const Number &) + { + iter(Current_Dim2 - 1, 0, Current_Dim1 - 1) + = result(0, Current_Dim1 - 1, Current_Dim2 - 1); + T3ch_equals_T3dg(iter, result, Number(), + Number(), Number()); + } + + template + void + T3ch_equals_T3dg(A &iter, const Dg_Expr &result, + const Number<1> &, const Number<1> &, + const Number &) + { + iter(Current_Dim2 - 1, 0, 0) = result(0, 0, Current_Dim2 - 1); + T3ch_equals_T3dg(iter, result, Number(), Number(), + Number()); + } + + template + void + T3ch_equals_T3dg(A &iter, const Dg_Expr &result, + const Number<1> &, const Number<1> &, const Number<1> &) + { + iter(0, 0, 0) = result(0, 0, 0); + } + + template + template + Dg_Expr, T, Dim12, Dim0, i, j, k> & + Dg_Expr, T, Dim12, Dim0, i, j, k>:: + operator=(const Dg_Expr &result) + { + T3ch_equals_T3dg(iter, result, Number(), Number(), + Number()); + return *this; + } + + /* T3ch=T3ch_Expr(T3ch) */ + + template + Dg_Expr, T, Dim12, Dim0, i, j, k> & + Dg_Expr, T, Dim12, Dim0, i, j, k>:: + operator=(const Dg_Expr, T, Dim12, + Dim0, i, j, k> &result) + { + return operator=, T>(result); + } + + /* T3ch=U */ + + template + void T3ch_equals_generic(A &iter, const U &u, const Number &, + const Number &, + const Number &, const Number &, + const Number &) + { + iter(Current_Dim2 - 1, Current_Dim0 - 1, Current_Dim1 - 1) = u; + T3ch_equals_generic(iter, u, Number(), + Number(), Number(), + Number(), Number()); + } + + template + void T3ch_equals_generic(A &iter, const U &u, const Number<1> &, + const Number &, + const Number &, const Number &, + const Number &) + { + iter(Current_Dim2 - 1, 0, Current_Dim1 - 1) = u; + T3ch_equals_generic(iter, u, Number(), + Number(), Number(), + Number(), Number()); + } + + template + void T3ch_equals_generic(A &iter, const U &u, const Number<1> &, + const Number<1> &, const Number &, + const Number &, const Number &) + { + iter(Current_Dim2 - 1, 0, 0) = u; + T3ch_equals_generic(iter, u, Number(), Number(), + Number(), Number(), + Number()); + } + + template + void T3ch_equals_generic(A &iter, const U &u, const Number<1> &, + const Number<1> &, const Number<1> &, + const Number &, const Number &) + { + iter(0, 0, 0) = u; + } + + template + template + Dg_Expr, T, Dim12, Dim0, i, j, k> & + Dg_Expr, T, Dim12, Dim0, i, j, k>:: + operator=(const U &u) + { + T3ch_equals_generic(iter, u, Number(), Number(), + Number(), Number(), Number()); + return *this; + } + + /* Assignment operators for the specializations to Ddg_number_rhs_0. */ + + /* T4ddgrhs0=T3dg */ + + template + void T4ddgrhs0_equals_T3dg(A &iter, + const Dg_Expr &result, + const Number &, + const Number &, + const Number &, const Number &) + { + iter(N, Current_Dim2 - 1, Current_Dim0 - 1, Current_Dim1 - 1) + = result(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1); + T4ddgrhs0_equals_T3dg(iter, result, Number(), + Number(), Number(), + Number()); + } + + template + void T4ddgrhs0_equals_T3dg(A &iter, + const Dg_Expr &result, + const Number<1> &, const Number &, + const Number &, const Number &) + { + iter(N, Current_Dim2 - 1, 0, Current_Dim1 - 1) + = result(0, Current_Dim1 - 1, Current_Dim2 - 1); + T4ddgrhs0_equals_T3dg(iter, result, Number(), + Number(), Number(), + Number()); + } + + template + void T4ddgrhs0_equals_T3dg(A &iter, + const Dg_Expr &result, + const Number<1> &, const Number<1> &, + const Number &, const Number &) + { + iter(N, Current_Dim2 - 1, 0, 0) = result(0, 0, Current_Dim2 - 1); + T4ddgrhs0_equals_T3dg(iter, result, Number(), Number(), + Number(), Number()); + } + + template + void T4ddgrhs0_equals_T3dg(A &iter, + const Dg_Expr &result, + const Number<1> &, const Number<1> &, + const Number<1> &, const Number &) + { + iter(N, 0, 0, 0) = result(0, 0, 0); + } + + template + template + Dg_Expr, T, Dim23, Dim1, i, j, k> & + Dg_Expr, T, Dim23, Dim1, i, j, k>:: + operator=(const Dg_Expr &result) + { + T4ddgrhs0_equals_T3dg(iter, result, Number(), Number(), + Number(), Number()); + return *this; + } + + /* T4ddgrhs0=T4ddgrhs0 */ + + template + Dg_Expr, T, Dim23, Dim1, i, j, k> & + Dg_Expr, T, Dim23, Dim1, i, j, k>::operator=( + const Dg_Expr, T, Dim23, Dim1, i, j, k> &result) + { + return operator=, T>(result); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_and_Dg.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_and_Dg.hpp new file mode 100644 index 000000000..9930e966c --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_and_Dg.hpp @@ -0,0 +1,74 @@ +/* Subtracts a Dg from a Dg, yielding a + Tensor3_antisymmetric. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)-B(i,k,j)->Tensor3_antisymmetric */ + + template + class Dg_and_Dg_12 + { + Dg_Expr iterA; + Dg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) - iterB(N1, N3, N2); + } + + Dg_and_Dg_12(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor3_antisymmetric_Expr, + typename promote::V, Dim, Dim, i, j, k> + operator&&(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr = Dg_and_Dg_12; + return Tensor3_antisymmetric_Expr::V, + Dim, Dim, i, j, k>(TensorExpr(a, b)); + } + + /* A(i,j,k)-B(k,j,i)->Tensor3_antisymmetric */ + /* We have to do a little index gymnastics here because a + Tensor3_antisymmetric is antisymmetric on the last two indices, not + the first and last index. */ + + template + class Dg_and_Dg_02 + { + Dg_Expr iterA; + Dg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N2, N1, N3) - iterB(N3, N1, N2); + } + + Dg_and_Dg_02(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor3_antisymmetric_Expr, + typename promote::V, Dim, Dim, j, i, k> + operator&&(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr = Dg_and_Dg_02; + return Tensor3_antisymmetric_Expr::V, + Dim, Dim, j, i, k>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_and_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_and_Tensor1.hpp new file mode 100644 index 000000000..58d9d2efd --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_and_Tensor1.hpp @@ -0,0 +1,55 @@ +/* Multiply a Tensor1 and a Dg together but don't contract, yielding a + Dg. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k) & B(k) -> Dg */ + + template + class Dg_and_Tensor1 + { + Dg_Expr iterA; + Tensor1_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) * iterB(N3); + } + + Dg_and_Tensor1(const Dg_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + operator&(const Dg_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Dg_and_Tensor1; + return Dg_Expr::V, Dim01, Dim2, i, j, k>( + TensorExpr(a, b)); + } + + /* B(k) & A(i,j,k) -> Dg */ + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + operator&(const Tensor1_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_and_Tensor1; + return Dg_Expr::V, Dim01, Dim2, i, j, k>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_and_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_and_Tensor2_symmetric.hpp new file mode 100644 index 000000000..9dd405412 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_and_Tensor2_symmetric.hpp @@ -0,0 +1,57 @@ +/* Multiply a Tensor2_symmetric and a Dg together but don't + contract, yielding a Dg. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k) & B(i,j) -> Dg */ + + template + class Dg_and_Tensor2_symmetric + { + Dg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) * iterB(N1, N2); + } + + Dg_and_Tensor2_symmetric(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + operator&(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Dg_and_Tensor2_symmetric; + return Dg_Expr::V, Dim01, Dim2, i, j, k>( + TensorExpr(a, b)); + } + + /* B(i,j) & A(i,j,k) -> Dg */ + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + operator&(const Tensor2_symmetric_Expr &b, + const Dg_Expr &a) + { + using TensorExpr + = Dg_and_Tensor2_symmetric; + return Dg_Expr::V, Dim01, Dim2, i, j, k>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_divide_generic.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_divide_generic.hpp new file mode 100644 index 000000000..4efc9294d --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_divide_generic.hpp @@ -0,0 +1,39 @@ +/* Divides a Dg by a generic, yielding a Dg. */ + +#pragma once + +namespace FTensor +{ + template + class Dg_divide_generic + { + Dg_Expr iterA; + U d; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) / d; + } + + Dg_divide_generic(const Dg_Expr &a, + const U &d0) + : iterA(a), d(d0) + {} + }; + + /* A(i,j,k)/d0->Dg */ + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + operator/(const Dg_Expr &a, const U &d0) + { + using TensorExpr = Dg_divide_generic; + return Dg_Expr::V, Dim01, Dim2, i, j, k>( + TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_function_operator.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_function_operator.hpp new file mode 100644 index 000000000..11f160b8b --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_function_operator.hpp @@ -0,0 +1,353 @@ +/* This contains the definitions of the almost all of the indexing + operators for Dg. */ + +#pragma once + +namespace FTensor +{ + /* These operator()'s are the first part in constructing template + expressions. */ + + template + template + Dg_Expr, T, Dim01, Dim2, i, j, k> + Dg:: + operator()(const Index index1, const Index index2, + const Index index3) + { + return Dg_Expr, T, Dim01, Dim2, i, j, k>( + *this); + } + + template + template + Dg_Expr, T, Dim01, Dim2, i, j, k> + Dg:: + operator()(const Index index1, const Index index2, + const Index index3) const + { + return Dg_Expr, T, Dim01, Dim2, i, + j, k>(*this); + } + + /* These operators are for internal contractions. */ + + template + template + Tensor1_Expr< + Tensor3_contracted_12, T, Dim12, i>, + T, Dim, i> + Dg:: + operator()(const Index index1, const Index index2, + const Index index3) const + { + using TensorExpr + = Tensor3_contracted_12, T, Dim12, + i>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + template + Tensor1_Expr< + Tensor3_contracted_02, T, Dim02, i>, + T, Dim, i> + Dg:: + operator()(const Index index1, const Index index2, + const Index index3) const + { + using TensorExpr + = Tensor3_contracted_02, T, Dim02, + i>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + template + Tensor1_Expr< + Tensor3_contracted_01, T, Dim01, i>, + T, Dim, i> + Dg:: + operator()(const Index index1, const Index index2, + const Index index3) const + { + using TensorExpr + = Tensor3_contracted_01, T, Dim01, + i>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* This is for expressions where a number is used for one slot, and + indices for the others, yielding a Tensor2_Expr or + Tensor2_symmetric_Expr. The non-const versions don't actually + create a Dg_number_rhs_* object, while the const versions + do create a Dg_number_*. */ + + /* First slot. */ + + template + template + Tensor2_Expr, T, N>, T, + Dim0, Dim1, i, j> + Dg:: + operator()(const Number n1, const Index index1, + const Index index2) + { + using TensorExpr = Dg_number_rhs_0, T, N>; + return Tensor2_Expr(*this); + } + + template + template + Tensor2_Expr, T, N>, T, + Dim0, Dim1, i, j> + Dg:: + operator()(const Number n1, const Index index1, + const Index index2) const + { + using TensorExpr + = Dg_number_0, T, N>; + return Tensor2_Expr(TensorExpr(*this)); + } + + /* Second slot. */ + + template + template + Tensor2_Expr, T, N>, T, + Dim0, Dim1, i, j> + Dg:: + operator()(const Index index1, const Number n1, + const Index index2) + { + using TensorExpr = Dg_number_rhs_0, T, N>; + return Tensor2_Expr(*this); + } + + template + template + Tensor2_Expr, T, N>, T, + Dim0, Dim1, i, j> + Dg:: + operator()(const Index index1, const Number n1, + const Index index2) const + { + using TensorExpr + = Dg_number_0, T, N>; + return Tensor2_Expr(TensorExpr(*this)); + } + + /* Third slot. */ + + template + template + Tensor2_symmetric_Expr< + Dg_number_rhs_2, T, N>, T, Dim, i, j> + Dg:: + operator()(const Index index1, const Index index2, + const Number n1) + { + using TensorExpr = Dg_number_rhs_2, T, N>; + return Tensor2_symmetric_Expr(*this); + } + + template + template + Tensor2_symmetric_Expr< + Dg_number_2, T, N>, T, Dim, i, j> + Dg:: + operator()(const Index index1, const Index index2, + const Number n1) const + { + using TensorExpr + = Dg_number_2, T, N>; + return Tensor2_symmetric_Expr(TensorExpr(*this)); + } + + /* This is for expressions where a number is used for two slots, and + an Index for the other, yielding a Tensor1_Expr. The non-const + versions don't actually create a Dg_number_rhs_* object, + while the const versions do create a Dg_number_*. */ + + /* Index in first slot. */ + + template + template + Tensor1_Expr, T, N1, N2>, + T, Dim, i> + Dg:: + operator()(const Index index, const Number n1, + const Number n2) + { + using TensorExpr + = Dg_number_rhs_12, T, N1, N2>; + return Tensor1_Expr(*this); + } + + template + template + Tensor1_Expr, T, N1, N2>, + T, Dim, i> + Dg:: + operator()(const Index index, const Number n1, + const Number n2) const + { + using TensorExpr + = Dg_number_12, T, N1, N2>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Index in second slot. I use the same structures as for the Index + in the first slot since the tensor is symmetric on the first two + indices. */ + + template + template + Tensor1_Expr, T, N1, N2>, + T, Dim, i> + Dg:: + operator()(const Number n1, const Index index, + const Number n2) + { + using TensorExpr + = Dg_number_rhs_12, T, N1, N2>; + return Tensor1_Expr(*this); + } + + template + template + Tensor1_Expr, T, N1, N2>, + T, Dim, i> + Dg:: + operator()(const Number n1, const Index index, + const Number n2) const + { + using TensorExpr + = Dg_number_12, T, N1, N2>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Index in third slot. */ + + template + template + Tensor1_Expr, T, N1, N2>, + T, Dim, i> + Dg:: + operator()(const Number n1, const Number n2, + const Index index) + { + using TensorExpr + = Dg_number_rhs_01, T, N1, N2>; + return Tensor1_Expr(*this); + } + + template + template + Tensor1_Expr, T, N1, N2>, + T, Dim, i> + Dg:: + operator()(const Number n1, const Number n2, + const Index index) const + { + using TensorExpr + = Dg_number_01, T, N1, N2>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Specializations for using actual numbers instead of Number<>. + This is for expressions where an actual number is used for one + slot, and indices for the others, yielding a Tensor2_Expr or + Tensor2_symmetric_Expr. I only define the const versions. */ + + /* First slot. */ + + template + template + Tensor2_Expr, T>, T, + Dim0, Dim1, i, j> + Dg:: + operator()(const int N, const Index index1, + const Index index2) const + { + using TensorExpr = Dg_numeral_0, T>; + return Tensor2_Expr(TensorExpr(*this, N)); + } + + /* Second slot. */ + + template + template + Tensor2_Expr, T>, T, + Dim0, Dim1, i, j> + Dg:: + operator()(const Index index1, const int N, + const Index index2) const + { + using TensorExpr = Dg_numeral_0, T>; + return Tensor2_Expr(TensorExpr(*this, N)); + } + + /* Third slot. */ + + template + template + Tensor2_symmetric_Expr< + Dg_numeral_2, T>, T, Dim, i, j> + Dg:: + operator()(const Index index1, const Index index2, + const int N) const + { + using TensorExpr = Dg_numeral_2, T>; + return Tensor2_symmetric_Expr( + TensorExpr(*this, N)); + } + + /* This is for expressions where an actual number is used for two + slots, and an Index for the other, yielding a Tensor1_Expr. I + only define the const versions. */ + + /* Index in first slot. */ + + template + template + Tensor1_Expr, T>, T, + Dim, i> + Dg:: + operator()(const Index index, const int N1, const int N2) const + { + using TensorExpr + = Dg_numeral_12, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } + + /* Index in second slot. I use the same structures as for the Index + in the first slot since the tensor is symmetric on the first two + indices. */ + + template + template + Tensor1_Expr, T>, T, + Dim, i> + Dg:: + operator()(const int N1, const Index index, const int N2) const + { + using TensorExpr + = Dg_numeral_12, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } + + /* Index in third slot. */ + + template + template + Tensor1_Expr, T>, T, + Dim, i> + Dg:: + operator()(const int N1, const int N2, const Index index) const + { + using TensorExpr + = Dg_numeral_01, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_minus_Dg.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_minus_Dg.hpp new file mode 100644 index 000000000..4e50032e1 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_minus_Dg.hpp @@ -0,0 +1,73 @@ +/* Subtracts a Dg from a Dg, yielding a Dg or + Tensor3. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)-B(i,j,k)->Dg */ + + template + class Dg_minus_Dg + { + Dg_Expr iterA; + Dg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) - iterB(N1, N2, N3); + } + + Dg_minus_Dg(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + operator-(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr = Dg_minus_Dg; + return Dg_Expr::V, Dim01, Dim2, i, j, k>( + TensorExpr(a, b)); + } + + /* A(i,j,k)-B(k,j,i)->Tensor3 */ + + template + class Dg_minus_Dg_02 + { + Dg_Expr iterA; + Dg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) - iterB(N3, N2, N1); + } + + Dg_minus_Dg_02(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor3_Expr, + typename promote::V, Dim, Dim, Dim, i, j, k> + operator-(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr = Dg_minus_Dg_02; + return Tensor3_Expr::V, Dim, Dim, Dim, + i, j, k>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_number.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_number.hpp new file mode 100644 index 000000000..e8996f428 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_number.hpp @@ -0,0 +1,64 @@ +/* This is for expressions where a number is used for one or two + slots, and an index for the others, yielding a Tensor1_Expr, + Tensor2_Expr, or Tensor2_symmetric_Expr. */ + +#pragma once + +namespace FTensor +{ + /* First or second slot. */ + + template class Dg_number_0 + { + A iterA; + + public: + T operator()(const int N1, const int N2) const { return iterA(N, N1, N2); } + Dg_number_0(const A &a) : iterA(a) {} + }; + + template class Dg_number_rhs_0 + {}; + + /* Third slot. */ + + template class Dg_number_2 + { + A iterA; + + public: + T operator()(const int N1, const int N2) const { return iterA(N1, N2, N); } + Dg_number_2(const A &a) : iterA(a) {} + }; + + template class Dg_number_rhs_2 + {}; + + /* Second and third slot (or first and third slot). */ + + template class Dg_number_12 + { + A iterA; + + public: + T operator()(const int N) const { return iterA(N, N1, N2); } + Dg_number_12(const A &a) : iterA(a) {} + }; + + template class Dg_number_rhs_12 + {}; + + /* First and second slot. */ + + template class Dg_number_01 + { + A iterA; + + public: + T operator()(const int N) const { return iterA(N1, N2, N); } + Dg_number_01(const A &a) : iterA(a) {} + }; + + template class Dg_number_rhs_01 + {}; +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_numeral.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_numeral.hpp new file mode 100644 index 000000000..f67838fad --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_numeral.hpp @@ -0,0 +1,60 @@ +/* This is for expressions where a number is used for one or two + slots, and an index for the others, yielding a Tensor1_Expr, + Tensor2_Expr, or Tensor2_symmetric_Expr. */ + +#pragma once + +namespace FTensor +{ + /* First or second slot. */ + + template class Dg_numeral_0 + { + A iterA; + int N; + + public: + T operator()(const int N1, const int N2) const { return iterA(N, N1, N2); } + Dg_numeral_0(const A &a, const int NN) : iterA(a), N(NN) {} + }; + + /* Third slot. */ + + template class Dg_numeral_2 + { + A iterA; + int N; + + public: + T operator()(const int N1, const int N2) const { return iterA(N1, N2, N); } + Dg_numeral_2(const A &a, const int NN) : iterA(a), N(NN) {} + }; + + /* Second and third slot (or first and third slot). */ + + template class Dg_numeral_12 + { + A iterA; + int N1, N2; + + public: + T operator()(const int N) const { return iterA(N, N1, N2); } + Dg_numeral_12(const A &a, const int NN1, const int NN2) + : iterA(a), N1(NN1), N2(NN2) + {} + }; + + /* First and second slot. */ + + template class Dg_numeral_01 + { + A iterA; + int N1, N2; + + public: + T operator()(const int N) const { return iterA(N1, N2, N); } + Dg_numeral_01(const A &a, const int NN1, const int NN2) + : iterA(a), N1(NN1), N2(NN2) + {} + }; +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_or_Dg.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_or_Dg.hpp new file mode 100644 index 000000000..2e689de6e --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_or_Dg.hpp @@ -0,0 +1,71 @@ +/* Adds two Dg's to make a Dg, but with different + symmetries. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)+B(i,k,j) -> Dg(j,k,i) */ + + template + class Dg_or_Dg_12 + { + Dg_Expr iterA; + Dg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N3, N1, N2) + iterB(N3, N2, N1); + } + + Dg_or_Dg_12(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Dg_Expr, typename promote::V, + Dim, Dim, j, k, i> + operator||(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr = Dg_or_Dg_12; + return Dg_Expr::V, Dim, Dim, j, k, i>( + TensorExpr(a, b)); + } + + /* A(j,i,k)+B(k,i,j) -> Dg(j,k,i) */ + + template + class Dg_or_Dg_02 + { + Dg_Expr iterA; + Dg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N3, N2) + iterB(N2, N3, N1); + } + + Dg_or_Dg_02(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Dg_Expr, typename promote::V, + Dim, Dim, j, k, i> + operator||(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr = Dg_or_Dg_02; + return Dg_Expr::V, Dim, Dim, j, k, i>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_plus_Dg.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_plus_Dg.hpp new file mode 100644 index 000000000..4e681b390 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_plus_Dg.hpp @@ -0,0 +1,106 @@ +/* Adds two Dg's together, yielding a Dg or Tensor3. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)+B(i,j,k)->Dg */ + + template + class Dg_plus_Dg + { + Dg_Expr iterA; + Dg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) + iterB(N1, N2, N3); + } + + Dg_plus_Dg(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + operator+(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr = Dg_plus_Dg; + return Dg_Expr::V, Dim01, Dim2, i, j, k>( + TensorExpr(a, b)); + } + + /* A(i,j,k)+B(j,i,k)->Dg */ + + template + class Dg_plus_Dg_10 + { + Dg_Expr iterA; + Dg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) + iterB(N1, N2, N3); + } + + Dg_plus_Dg_10(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + operator+(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr = Dg_plus_Dg_10; + return Dg_Expr::V, Dim01, Dim2, i, j, k>( + TensorExpr(a, b)); + } + + /* A(i,j,k)+B(k,j,i)->Tensor3 */ + + template + class Dg_plus_Dg_210 + { + Dg_Expr iterA; + Dg_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) + iterB(N3, N2, N1); + } + + Dg_plus_Dg_210(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor3_Expr, + typename promote::V, Dim, Dim, Dim, i, j, k> + operator+(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr = Dg_plus_Dg_210; + return Tensor3_Expr::V, Dim, Dim, Dim, + i, j, k>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_pointer.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_pointer.hpp new file mode 100644 index 000000000..cb2cbea15 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_pointer.hpp @@ -0,0 +1,429 @@ +/* A version for pointers. */ + +#pragma once + +namespace FTensor +{ + template + class Dg + { + mutable T *restrict + data[(Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2][Tensor_Dim2]; + + public: + template Dg(U *... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Dg() {} + + /* There are two operator(int,int,int)'s, one for non-consts that lets you + change the value, and one for consts that doesn't. */ + + T &operator()(const int N1, const int N2, const int N3) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0 + || N3 >= Tensor_Dim2 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Dg.operator(" << N1 << "," << N2 << "," << N3 << ")" + << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 ? *data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2][N3] + : *data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2][N3]; + } + + T operator()(const int N1, const int N2, const int N3) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0 + || N3 >= Tensor_Dim2 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Dg.operator(" << N1 << "," << N2 << "," << N3 << ") const" + << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 ? *data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2][N3] + : *data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2][N3]; + } + + T *ptr(const int N1, const int N2, const int N3) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0 + || N3 >= Tensor_Dim2 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Dg.ptr(" << N1 << "," << N2 << "," << N3 << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 ? data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2][N3] + : data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2][N3]; + } + + /* These operator()'s are the first part in constructing template + expressions. */ + + template + Dg_Expr, T, Dim01, Dim2, i, j, k> + operator()(const Index index1, const Index index2, + const Index index3) + { + return Dg_Expr, T, Dim01, Dim2, i, j, + k>(*this); + } + + template + Dg_Expr, T, Dim01, Dim2, i, j, k> + operator()(const Index index1, const Index index2, + const Index index3) const + { + return Dg_Expr, T, Dim01, Dim2, + i, j, k>(*this); + } + + /* These operators are for internal contractions. The commented out + versions are more general, but are ambiguous. This means, + unfortunately, that you can't do something like A(i,j,j) where i + and j have different dimensions. */ + + template + Tensor1_Expr< + const Tensor3_contracted_12, T, Dim>, + T, Dim, i> + operator()(const Index index1, const Index index2, + const Index index3) const + { + using TensorExpr + = Tensor3_contracted_12, T, Dim>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + Tensor1_Expr< + const Tensor3_contracted_02, T, Dim>, + T, Dim, i> + operator()(const Index index1, const Index index2, + const Index index3) const + { + using TensorExpr + = Tensor3_contracted_02, T, Dim>; + return Tensor1_Expr(TensorExpr(*this)); + } + + // template + // Tensor1_Expr,T,Dim12>,T,Dim0,i> + // operator()(const Index index1, const Index index2, + // const Index index3) const + // { + // typedef Tensor3_contracted_12, + // T,Dim12> TensorExpr; + // return Tensor1_Expr(TensorExpr(*this)); + // } + + // template + // Tensor1_Expr,T,Dim02>,T,Dim1,i> + // operator()(const Index index1, const Index index2, + // const Index index3) const + // { + // typedef Tensor3_contracted_02, + // T,Dim02> TensorExpr; + // return Tensor1_Expr(TensorExpr(*this)); + // } + + template + Tensor1_Expr< + const Tensor3_contracted_01, T, Dim01>, + T, Dim2, i> + operator()(const Index index1, const Index index2, + const Index index3) const + { + using TensorExpr + = Tensor3_contracted_01, T, Dim01>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* This is for expressions where a number is used for one slot, and + indices for the others, yielding a Tensor2_Expr or + Tensor2_symmetric_Expr. The non-const versions don't actually + create a Dg_number_rhs_* object, while the const versions + do create a Dg_number_*. */ + + /* First slot. */ + + template + Tensor2_Expr, T, N>, T, + Dim1, Dim2, i, j> + operator()(const Number n1, const Index index1, + const Index index2) + { + using TensorExpr + = Dg_number_rhs_0, T, N>; + return Tensor2_Expr(*this); + } + + template + const Tensor2_Expr< + const Dg_number_0, T, N>, T, + Dim1, Dim2, i, j> + operator()(const Number n1, const Index index1, + const Index index2) const + { + using TensorExpr + = Dg_number_0, T, N>; + return Tensor2_Expr(TensorExpr(*this)); + } + + /* Second slot. */ + + template + Tensor2_Expr, T, N>, T, + Dim0, Dim2, i, j> + operator()(const Index index1, const Number n1, + const Index index2) + { + using TensorExpr + = Dg_number_rhs_0, T, N>; + return Tensor2_Expr(*this); + } + + template + const Tensor2_Expr< + const Dg_number_0, T, N>, T, + Dim0, Dim2, i, j> + operator()(const Index index1, const Number n1, + const Index index2) const + { + using TensorExpr + = Dg_number_0, T, N>; + return Tensor2_Expr(TensorExpr(*this)); + } + + /* Third slot. */ + + template + Tensor2_symmetric_Expr< + Dg_number_rhs_2, T, N>, T, Dim, i, j> + operator()(const Index index1, const Index index2, + const Number n1) + { + using TensorExpr + = Dg_number_rhs_2, T, N>; + return Tensor2_symmetric_Expr(*this); + } + + template + const Tensor2_symmetric_Expr< + const Dg_number_2, T, N>, T, + Dim, i, j> + operator()(const Index index1, const Index index2, + const Number n1) const + { + using TensorExpr + = Dg_number_2, T, N>; + return Tensor2_symmetric_Expr( + TensorExpr(*this)); + } + + /* This is for expressions where a number is used for two slots, and + an Index for the other, yielding a Tensor1_Expr. The non-const + versions don't actually create a Dg_number_rhs_* object, + while the const versions do create a Dg_number_*. */ + + /* Index in first slot. */ + + template + Tensor1_Expr, T, N1, N2>, + T, Dim, i> + operator()(const Index index, const Number n1, + const Number n2) + { + using TensorExpr + = Dg_number_rhs_12, T, N1, N2>; + return Tensor1_Expr(*this); + } + + template + const Tensor1_Expr< + const Dg_number_12, T, N1, N2>, + T, Dim, i> + operator()(const Index index, const Number n1, + const Number n2) const + { + using TensorExpr + = Dg_number_12, T, N1, N2>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Index in second slot. I use the same structures as for the Index + in the first slot since the tensor is symmetric on the first two + indices. */ + + template + Tensor1_Expr, T, N1, N2>, + T, Dim, i> + operator()(const Number n1, const Index index, + const Number n2) + { + using TensorExpr + = Dg_number_rhs_12, T, N1, N2>; + return Tensor1_Expr(*this); + } + + template + const Tensor1_Expr< + const Dg_number_12, T, N1, N2>, + T, Dim, i> + operator()(const Number n1, const Index index, + const Number n2) const + { + using TensorExpr + = Dg_number_12, T, N1, N2>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Index in third slot. */ + + template + Tensor1_Expr, T, N1, N2>, + T, Dim, i> + operator()(const Number n1, const Number n2, + const Index index) + { + using TensorExpr + = Dg_number_rhs_01, T, N1, N2>; + return Tensor1_Expr(*this); + } + + template + const Tensor1_Expr< + const Dg_number_01, T, N1, N2>, + T, Dim, i> + operator()(const Number n1, const Number n2, + const Index index) const + { + using TensorExpr + = Dg_number_01, T, N1, N2>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Specializations for using actual numbers instead of Number<>. + This is for expressions where an actual number is used for one + slot, and indices for the others, yielding a Tensor2_Expr or + Tensor2_symmetric_Expr. I only define the const versions. */ + + /* First slot. */ + + template + const Tensor2_Expr< + const Dg_numeral_0, T>, T, Dim1, + Dim2, i, j> + operator()(const int N, const Index index1, + const Index index2) const + { + using TensorExpr + = Dg_numeral_0, T>; + return Tensor2_Expr( + TensorExpr(*this, N)); + } + + /* Second slot. */ + + template + const Tensor2_Expr< + const Dg_numeral_0, T>, T, Dim0, + Dim2, i, j> + operator()(const Index index1, const int N, + const Index index2) const + { + using TensorExpr + = Dg_numeral_0, T>; + return Tensor2_Expr( + TensorExpr(*this, N)); + } + + /* Third slot. */ + + template + const Tensor2_symmetric_Expr< + const Dg_numeral_2, T>, T, Dim, + i, j> + operator()(const Index index1, const Index index2, + const int N) const + { + using TensorExpr + = Dg_numeral_2, T>; + return Tensor2_symmetric_Expr( + TensorExpr(*this, N)); + } + + /* This is for expressions where a numeral is used for two slots, and + an Index for the other, yielding a Tensor1_Expr. */ + + /* Index in first slot. */ + + template + const Tensor1_Expr< + const Dg_numeral_12, T>, T, Dim, + i> + operator()(const Index index, const int N1, const int N2) const + { + using TensorExpr + = Dg_numeral_12, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } + + /* Index in second slot. I use the same structures as for the Index + in the first slot since the tensor is symmetric on the first two + indices. */ + + template + const Tensor1_Expr< + const Dg_numeral_12, T>, T, Dim, + i> + operator()(const int N1, const Index index, const int N2) const + { + using TensorExpr + = Dg_numeral_12, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } + + /* Index in third slot. */ + + template + const Tensor1_Expr< + const Dg_numeral_01, T>, T, Dim, + i> + operator()(const int N1, const int N2, const Index index) const + { + using TensorExpr + = Dg_numeral_01, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } + + /* The ++ operator increments the pointer, not the number that the + pointer points to. This allows iterating over a grid. */ + + const Dg &operator++() const + { + for(int i = 0; i < (Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2; ++i) + for(int j = 0; j < Tensor_Dim2; ++j) + ++data[i][j]; + return *this; + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_times_Dg.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_times_Dg.hpp new file mode 100644 index 000000000..de2d7c0d4 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_times_Dg.hpp @@ -0,0 +1,195 @@ +/* This file has all of the declarations for expressions like + Dg*Dg yielding a Tensor2 or Ddg. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)*B(j,k,l) */ + + template + class Dg_times_Dg_12_01 + { + Dg_Expr iterA; + Dg_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(N1, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1, N2) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(N1, 0, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1, N2) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(N1, 0, 0) * iterB(0, 0, N2); + } + + public: + Dg_times_Dg_12_01(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim01, Dim2, i, l> + operator*(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr = Dg_times_Dg_12_01; + return Tensor2_Expr::V, Dim01, Dim2, i, + l>(TensorExpr(a, b)); + } + + /* B(j,k,l)*A(i,j,k) */ + + template + Tensor2_Expr, + typename promote::V, Dim01, Dim2, i, l> + operator*(const Dg_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Dg_12_01; + return Tensor2_Expr::V, Dim01, Dim2, i, + l>(TensorExpr(a, b)); + } + + /* A(i,j,k)*B(k,l,j) */ + + template + class Dg_times_Dg_12_20 + { + Dg_Expr iterA; + Dg_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(N1, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim1 - 1, N2, Current_Dim0 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(N1, 0, Current_Dim1 - 1) * iterB(Current_Dim1 - 1, N2, 0) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(N1, 0, 0) * iterB(0, N2, 0); + } + + public: + Dg_times_Dg_12_20(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim01, Dim2, i, l> + operator*(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr = Dg_times_Dg_12_20; + return Tensor2_Expr::V, Dim01, Dim2, i, + l>(TensorExpr(a, b)); + } + + /* B(k,l,j)*A(i,j,k) */ + + template + Tensor2_Expr, + typename promote::V, Dim01, Dim2, i, l> + operator*(const Dg_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Dg_12_20; + return Tensor2_Expr::V, Dim01, Dim2, i, + l>(TensorExpr(a, b)); + } + + /* A(i,j,k)*B(l,m,k) -> Ddg */ + + template + class Dg_times_Dg_2 + { + Dg_Expr iterA; + Dg_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const int N3, const int N4, + const Number &) const + { + return iterA(N1, N2, Current_Dim0 - 1) * iterB(N3, N4, Current_Dim0 - 1) + + eval(N1, N2, N3, N4, Number()); + } + typename promote::V eval(const int N1, const int N2, const int N3, + const int N4, const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(N3, N4, 0); + } + + public: + Dg_times_Dg_2(const Dg_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return eval(N1, N2, N3, N4, Number()); + } + }; + + template + Ddg_Expr, + typename promote::V, Dim01, Dim23, i, j, l, m> + operator*(const Dg_Expr &a, + const Dg_Expr &b) + { + using TensorExpr + = Dg_times_Dg_2; + return Ddg_Expr::V, Dim01, Dim23, i, j, + l, m>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_times_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_times_Tensor1.hpp new file mode 100644 index 000000000..aae97057e --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_times_Tensor1.hpp @@ -0,0 +1,185 @@ +/* This file has all of the declarations for expressions like + Dg*Tensor1 and Tensor1*Dg, yielding a + Tensor2_symmetric or Tensor2. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)*B(k)->Tensor2_symmetric */ + + template + class Dg_times_Tensor1_2 + { + Dg_Expr iterA; + Tensor1_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, N2, Current_Dim - 1) * iterB(Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(0); + } + + public: + Dg_times_Tensor1_2(const Dg_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim01, i, j> + operator*(const Dg_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Dg_times_Tensor1_2; + return Tensor2_symmetric_Expr::V, Dim01, + i, j>(TensorExpr(a, b)); + } + + /* B(k)*A(i,j,k)->Tensor2_symmetric */ + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim01, i, j> + operator*(const Tensor1_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor1_2; + return Tensor2_symmetric_Expr::V, Dim01, + i, j>(TensorExpr(a, b)); + } + + /* A(i,k,j)*B(k)->Tensor2 */ + + template + class Dg_times_Tensor1_1 + { + Dg_Expr iterA; + Tensor1_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1, N2) * iterB(Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0, N2) * iterB(0); + } + + public: + Dg_times_Tensor1_1(const Dg_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim01, Dim2, i, j> + operator*(const Dg_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Dg_times_Tensor1_1; + return Tensor2_Expr::V, Dim01, Dim2, i, + j>(TensorExpr(a, b)); + } + + /* B(k)*A(i,k,j)->Tensor2 */ + + template + Tensor2_Expr, + typename promote::V, Dim01, Dim2, i, j> + operator*(const Tensor1_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor1_1; + return Tensor2_Expr::V, Dim01, Dim2, i, + j>(TensorExpr(a, b)); + } + + /* A(k,i,j)*B(k)->Tensor2 */ + + template + class Dg_times_Tensor1_0 + { + Dg_Expr iterA; + Tensor1_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1, N2) * iterB(Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0, N2) * iterB(0); + } + + public: + Dg_times_Tensor1_0(const Dg_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim01, Dim2, i, j> + operator*(const Dg_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Dg_times_Tensor1_0; + return Tensor2_Expr::V, Dim01, Dim2, i, + j>(TensorExpr(a, b)); + } + + /* B(k)*A(k,i,j)->Tensor2 */ + + template + Tensor2_Expr, + typename promote::V, Dim01, Dim2, i, j> + operator*(const Tensor1_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor1_0; + return Tensor2_Expr::V, Dim01, Dim2, i, + j>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_times_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_times_Tensor2.hpp new file mode 100644 index 000000000..f82132a90 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_times_Tensor2.hpp @@ -0,0 +1,658 @@ +/* This file has all of the declarations for expressions like + Dg*Tensor2 and Tensor2*Dg, yielding a + Dg, Tensor3, or Tensor1. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)*B(k,l)->Dg */ + + template + class Dg_times_Tensor2_0 + { + Dg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, N2, Current_Dim - 1) * iterB(Current_Dim - 1, N3) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(0, N3); + } + + public: + Dg_times_Tensor2_0(const Dg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Dg_Expr, + typename promote::V, Dim01, Dim3, i, j, l> + operator*(const Dg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Dg_times_Tensor2_0; + return Dg_Expr::V, Dim01, Dim3, i, j, l>( + TensorExpr(a, b)); + } + + /* B(k,l)*A(i,j,k)->Dg */ + + template + Dg_Expr, + typename promote::V, Dim01, Dim3, i, j, l> + operator*(const Tensor2_Expr &b, + const Dg_Expr &a) + { + using TensorExpr + = Dg_times_Tensor2_0; + return Dg_Expr::V, Dim01, Dim3, i, j, l>( + TensorExpr(a, b)); + } + + /* A(i,j,k)*B(l,k)->Dg */ + + template + class Dg_times_Tensor2_1 + { + Dg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, N2, Current_Dim - 1) * iterB(N3, Current_Dim - 1) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(N3, 0); + } + + public: + Dg_times_Tensor2_1(const Dg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Dg_Expr, + typename promote::V, Dim01, Dim3, i, j, l> + operator*(const Dg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Dg_times_Tensor2_1; + return Dg_Expr::V, Dim01, Dim3, i, j, l>( + TensorExpr(a, b)); + } + + /* B(l,k)*A(i,j,k)->Dg */ + + template + Dg_Expr, + typename promote::V, Dim01, Dim3, i, j, l> + operator*(const Tensor2_Expr &b, + const Dg_Expr &a) + { + using TensorExpr + = Dg_times_Tensor2_1; + return Dg_Expr::V, Dim01, Dim3, i, j, l>( + TensorExpr(a, b)); + } + + /* A(i,j,k)*B(j,l)->Tensor3 */ + + template + class Dg_times_Tensor2_1_0 + { + Dg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, Current_Dim - 1, N2) * iterB(Current_Dim - 1, N3) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, 0, N2) * iterB(0, N3); + } + + public: + Dg_times_Tensor2_1_0(const Dg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Tensor3_Expr, + typename promote::V, Dim01, Dim2, Dim3, i, k, l> + operator*(const Dg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Dg_times_Tensor2_1_0; + return Tensor3_Expr::V, Dim01, Dim2, + Dim3, i, k, l>(TensorExpr(a, b)); + } + + /* B(j,l)*A(i,j,k)->Tensor3 */ + + template + Tensor3_Expr, + typename promote::V, Dim01, Dim2, Dim3, i, k, l> + operator*(const Tensor2_Expr &b, + const Dg_Expr &a) + { + using TensorExpr + = Dg_times_Tensor2_1_0; + return Tensor3_Expr::V, Dim01, Dim2, + Dim3, i, k, l>(TensorExpr(a, b)); + } + + /* A(i,j,k)*B(l,j)->Tensor3 */ + + template + class Dg_times_Tensor2_1_1 + { + Dg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, Current_Dim - 1, N2) * iterB(N3, Current_Dim - 1) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, 0, N2) * iterB(N3, 0); + } + + public: + Dg_times_Tensor2_1_1(const Dg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Tensor3_Expr, + typename promote::V, Dim01, Dim2, Dim3, i, k, l> + operator*(const Dg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Dg_times_Tensor2_1_1; + return Tensor3_Expr::V, Dim01, Dim2, + Dim3, i, k, l>(TensorExpr(a, b)); + } + + /* B(l,j)*A(i,j,k)->Tensor3 */ + + template + Tensor3_Expr, + typename promote::V, Dim01, Dim2, Dim3, i, k, l> + operator*(const Tensor2_Expr &b, + const Dg_Expr &a) + { + using TensorExpr + = Dg_times_Tensor2_1_1; + return Tensor3_Expr::V, Dim01, Dim2, + Dim3, i, k, l>(TensorExpr(a, b)); + } + + /* A(i,j,k)*B(j,k)->Tensor1 */ + + template + class Dg_times_Tensor2_12 + { + Dg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(N1, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(N1, 0, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(N1, 0, 0) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_12(const Dg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim01, i> + operator*(const Dg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Dg_times_Tensor2_12; + return Tensor1_Expr::V, Dim01, i>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(i,j,k)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim01, i> + operator*(const Tensor2_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor2_12; + return Tensor1_Expr::V, Dim01, i>( + TensorExpr(a, b)); + } + + /* A(i,j,k)*B(k,j)->Tensor1 */ + + template + class Dg_times_Tensor2_21 + { + Dg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(N1, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim1 - 1, Current_Dim0 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(N1, 0, Current_Dim1 - 1) * iterB(Current_Dim1 - 1, 0) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(N1, 0, 0) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_21(const Dg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim01, i> + operator*(const Dg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Dg_times_Tensor2_21; + return Tensor1_Expr::V, Dim01, i>( + TensorExpr(a, b)); + } + + /* B(k,j)*A(i,j,k)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim01, i> + operator*(const Tensor2_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor2_21; + return Tensor1_Expr::V, Dim01, i>( + TensorExpr(a, b)); + } + + /* A(j,i,k)*B(j,k)->Tensor1 */ + + template + class Dg_times_Tensor2_02 + { + Dg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(0, N1, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, 0) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_02(const Dg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim01, i> + operator*(const Dg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Dg_times_Tensor2_02; + return Tensor1_Expr::V, Dim01, i>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(j,i,k)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim01, i> + operator*(const Tensor2_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor2_02; + return Tensor1_Expr::V, Dim01, i>( + TensorExpr(a, b)); + } + + /* A(k,i,j)*B(j,k)->Tensor1 */ + + template + class Dg_times_Tensor2_20 + { + Dg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, Current_Dim1 - 1) + * iterB(Current_Dim1 - 1, Current_Dim0 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(0, N1, Current_Dim1 - 1) * iterB(Current_Dim1 - 1, 0) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, 0) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_20(const Dg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim01, i> + operator*(const Dg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Dg_times_Tensor2_20; + return Tensor1_Expr::V, Dim01, i>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(k,i,j)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim01, i> + operator*(const Tensor2_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor2_20; + return Tensor1_Expr::V, Dim01, i>( + TensorExpr(a, b)); + } + + /* A(j,k,i)*B(j,k)->Tensor1 */ + + template + class Dg_times_Tensor2_01 + { + Dg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, Current_Dim1 - 1, N1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(0, Current_Dim1 - 1, N1) * iterB(0, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(0, 0, N1) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_01(const Dg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim2, i> + operator*(const Dg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Dg_times_Tensor2_01; + return Tensor1_Expr::V, Dim2, i>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(j,k,i)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim2, i> + operator*(const Tensor2_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor2_01; + return Tensor1_Expr::V, Dim2, i>( + TensorExpr(a, b)); + } + + /* A(j,k,i)*B(k,j)->Tensor1 */ + + template + class Dg_times_Tensor2_10 + { + Dg_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, Current_Dim1 - 1, N1) + * iterB(Current_Dim1 - 1, Current_Dim0 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(0, Current_Dim1 - 1, N1) * iterB(Current_Dim1 - 1, 0) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(0, 0, N1) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_10(const Dg_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim2, i> + operator*(const Dg_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Dg_times_Tensor2_10; + return Tensor1_Expr::V, Dim2, i>( + TensorExpr(a, b)); + } + + /* B(k,j)*A(j,k,i)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim2, i> + operator*(const Tensor2_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor2_10; + return Tensor1_Expr::V, Dim2, i>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_times_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_times_Tensor2_symmetric.hpp new file mode 100644 index 000000000..7646eb458 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_times_Tensor2_symmetric.hpp @@ -0,0 +1,664 @@ +/* This file has all of the declarations for expressions like + Dg*Tensor2_symmetric and Tensor2_symmetric*Dg, + yielding a Dg, Tensor3, or Tensor1. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)*B(k,l)->Dg */ + + template + class Dg_times_Tensor2_symmetric_0 + { + Dg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, N2, Current_Dim - 1) * iterB(Current_Dim - 1, N3) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(0, N3); + } + + public: + Dg_times_Tensor2_symmetric_0( + const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, l> + operator*(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_0; + return Dg_Expr::V, Dim01, Dim2, i, j, l>( + TensorExpr(a, b)); + } + + /* B(k,l)*A(i,j,k)->Dg */ + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, l> + operator*(const Tensor2_symmetric_Expr &b, + const Dg_Expr &a) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_0; + return Dg_Expr::V, Dim01, Dim2, i, j, l>( + TensorExpr(a, b)); + } + + /* A(i,j,k)*B(l,k)->Dg */ + + template + class Dg_times_Tensor2_symmetric_1 + { + Dg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, N2, Current_Dim - 1) * iterB(N3, Current_Dim - 1) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(N3, 0); + } + + public: + Dg_times_Tensor2_symmetric_1( + const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, l> + operator*(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_1; + return Dg_Expr::V, Dim01, Dim2, i, j, l>( + TensorExpr(a, b)); + } + + /* B(l,k)*A(i,j,k)->Dg */ + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, l> + operator*(const Tensor2_symmetric_Expr &b, + const Dg_Expr &a) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_1; + return Dg_Expr::V, Dim01, Dim2, i, j, l>( + TensorExpr(a, b)); + } + + /* A(i,j,k)*B(j,l)->Tensor3 */ + + template + class Dg_times_Tensor2_symmetric_1_0 + { + Dg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, Current_Dim - 1, N2) * iterB(Current_Dim - 1, N3) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, 0, N2) * iterB(0, N3); + } + + public: + Dg_times_Tensor2_symmetric_1_0( + const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Tensor3_Expr< + Dg_times_Tensor2_symmetric_1_0, + typename promote::V, Dim01, Dim2, Dim01, i, k, l> + operator*(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_1_0; + return Tensor3_Expr::V, Dim01, Dim2, + Dim01, i, k, l>(TensorExpr(a, b)); + } + + /* B(j,l)*A(i,j,k)->Tensor3 */ + + template + Tensor3_Expr< + Dg_times_Tensor2_symmetric_1_0, + typename promote::V, Dim01, Dim2, Dim01, i, k, l> + operator*(const Tensor2_symmetric_Expr &b, + const Dg_Expr &a) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_1_0; + return Tensor3_Expr::V, Dim01, Dim2, + Dim01, i, k, l>(TensorExpr(a, b)); + } + + /* A(i,j,k)*B(l,j)->Tensor3 */ + + template + class Dg_times_Tensor2_symmetric_1_1 + { + Dg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, Current_Dim - 1, N2) * iterB(N3, Current_Dim - 1) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, 0, N2) * iterB(N3, 0); + } + + public: + Dg_times_Tensor2_symmetric_1_1( + const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Tensor3_Expr< + Dg_times_Tensor2_symmetric_1_1, + typename promote::V, Dim01, Dim2, Dim01, i, k, l> + operator*(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_1_1; + return Tensor3_Expr::V, Dim01, Dim2, + Dim01, i, k, l>(TensorExpr(a, b)); + } + + /* B(l,j)*A(i,j,k)->Tensor3 */ + + template + Tensor3_Expr< + Dg_times_Tensor2_symmetric_1_1, + typename promote::V, Dim01, Dim2, Dim01, i, k, l> + operator*(const Tensor2_symmetric_Expr &b, + const Dg_Expr &a) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_1_1; + return Tensor3_Expr::V, Dim01, Dim2, + Dim01, i, k, l>(TensorExpr(a, b)); + } + + /* A(i,j,k)*B(j,k)->Tensor1 */ + + template + class Dg_times_Tensor2_symmetric_12 + { + Dg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(N1, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(N1, 0, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(N1, 0, 0) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_symmetric_12( + const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr = Dg_times_Tensor2_symmetric_12; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(i,j,k)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Tensor2_symmetric_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor2_symmetric_12; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* A(i,j,k)*B(k,j)->Tensor1 */ + + template + class Dg_times_Tensor2_symmetric_21 + { + Dg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(N1, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim1 - 1, Current_Dim0 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(N1, 0, Current_Dim1 - 1) * iterB(Current_Dim1 - 1, 0) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(N1, 0, 0) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_symmetric_21( + const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr = Dg_times_Tensor2_symmetric_21; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* B(k,j)*A(i,j,k)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Tensor2_symmetric_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor2_symmetric_21; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* A(j,i,k)*B(j,k)->Tensor1 */ + + template + class Dg_times_Tensor2_symmetric_02 + { + Dg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(0, N1, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, 0) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_symmetric_02( + const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr = Dg_times_Tensor2_symmetric_02; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(j,i,k)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Tensor2_symmetric_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor2_symmetric_02; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* A(k,i,j)*B(j,k)->Tensor1 */ + + template + class Dg_times_Tensor2_symmetric_20 + { + Dg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, Current_Dim1 - 1) + * iterB(Current_Dim1 - 1, Current_Dim0 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(0, N1, Current_Dim1 - 1) * iterB(Current_Dim1 - 1, 0) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, 0) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_symmetric_20( + const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr = Dg_times_Tensor2_symmetric_20; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(k,i,j)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Tensor2_symmetric_Expr &b, + const Dg_Expr &a) + { + using TensorExpr = Dg_times_Tensor2_symmetric_20; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* A(j,k,i)*B(j,k)->Tensor1 */ + + template + class Dg_times_Tensor2_symmetric_01 + { + Dg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, Current_Dim1 - 1, N1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(0, Current_Dim1 - 1, N1) * iterB(0, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(0, 0, N1) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_symmetric_01( + const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim2, i> + operator*(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_01; + return Tensor1_Expr::V, Dim2, i>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(j,k,i)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim2, i> + operator*(const Tensor2_symmetric_Expr &b, + const Dg_Expr &a) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_01; + return Tensor1_Expr::V, Dim2, i>( + TensorExpr(a, b)); + } + + /* A(j,k,i)*B(k,j)->Tensor1 */ + + template + class Dg_times_Tensor2_symmetric_10 + { + Dg_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, Current_Dim1 - 1, N1) + * iterB(Current_Dim1 - 1, Current_Dim0 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(0, Current_Dim1 - 1, N1) * iterB(Current_Dim1 - 1, 0) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(0, 0, N1) * iterB(0, 0); + } + + public: + Dg_times_Tensor2_symmetric_10( + const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim2, i> + operator*(const Dg_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_10; + return Tensor1_Expr::V, Dim2, i>( + TensorExpr(a, b)); + } + + /* B(k,j)*A(j,k,i)->Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim2, i> + operator*(const Tensor2_symmetric_Expr &b, + const Dg_Expr &a) + { + using TensorExpr + = Dg_times_Tensor2_symmetric_10; + return Tensor1_Expr::V, Dim2, i>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_times_generic.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_times_generic.hpp new file mode 100644 index 000000000..2c71fa43c --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_times_generic.hpp @@ -0,0 +1,51 @@ +/* Multiplies a Dg with a generic, yielding a Dg. */ + +#pragma once + +namespace FTensor +{ + template + class Dg_times_generic + { + Dg_Expr iterA; + U d; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) * d; + } + + Dg_times_generic(const Dg_Expr &a, const U &d0) + : iterA(a), d(d0) + {} + }; + + /* A(i,j,k)*d0->Dg */ + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + operator*(const Dg_Expr &a, const U &d0) + { + using TensorExpr = Dg_times_generic; + return Dg_Expr::V, Dim01, Dim2, i, j, k>( + TensorExpr(a, d0)); + } + + /* d0*A(i,j,k)->Dg */ + + template + Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + operator*(const U &d0, const Dg_Expr &a) + { + using TensorExpr = Dg_times_generic; + return Dg_Expr::V, Dim01, Dim2, i, j, k>( + TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Dg/Dg_value.hpp b/src/oofemlib/tensor/FTensor/Dg/Dg_value.hpp new file mode 100644 index 000000000..6c6090db9 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/Dg_value.hpp @@ -0,0 +1,414 @@ +/* A general version, not for pointers. */ + +#pragma once + +#include "../Tensor3.hpp" + +namespace FTensor +{ + template class Dg + { + T data[(Tensor_Dim01 * (Tensor_Dim01 + 1)) / 2][Tensor_Dim2]; + + public: + template Dg(U... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Dg() {} + + /* There are two operator(int,int,int)'s, one for non-consts that lets you + change the value, and one for consts that doesn't. */ + + T &operator()(const int N1, const int N2, const int N3) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0 + || N3 >= Tensor_Dim2 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Dg.operator(" << N1 << "," << N2 << "," << N3 << ")" + << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 ? data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2][N3] + : data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2][N3]; + } + + T operator()(const int N1, const int N2, const int N3) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim01 || N1 < 0 || N2 >= Tensor_Dim01 || N2 < 0 + || N3 >= Tensor_Dim2 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Dg.operator(" << N1 << "," << N2 << "," << N3 << ") const" + << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 ? data[N1 + (N2 * (2 * Tensor_Dim01 - N2 - 1)) / 2][N3] + : data[N2 + (N1 * (2 * Tensor_Dim01 - N1 - 1)) / 2][N3]; + } + + /* These operator()'s are the first part in constructing template + expressions. */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim01 && Tensor_Dim2 >= Dim2), + Dg_Expr, T, Dim01, Dim2, i, j, k>>::type + operator()(const Index, const Index, + const Index) + { + return Dg_Expr, T, Dim01, Dim2, i, j, k>( + *this); + } + // TODO Add support for multiple dimensions ^^^^^ + template + typename std::enable_if<(Tensor_Dim01 >= Dim01 && Tensor_Dim2 >= Dim2), + Dg_Expr, T, + Dim01, Dim2, i, j, k>>::type + operator()(const Index, const Index, + const Index) const + { + return Dg_Expr, T, Dim01, Dim2, i, + j, k>(*this); + } + + /* These operators are for internal contractions. We can not do + something like A(i,j,j) where i and j have different dimensions, + because it becomes ambiguous. */ + + /* A(i,j,j) */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim && Tensor_Dim2 >= Dim), + Tensor1_Expr< + Tensor3_contracted_12, T, Dim>, T, + Dim, i>>::type + operator()(const Index, const Index, + const Index) const + { + using TensorExpr + = Tensor3_contracted_12, T, Dim>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* A(j,i,j) */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim && Tensor_Dim2 >= Dim), + Tensor1_Expr< + Tensor3_contracted_02, T, Dim>, T, + Dim, i>>::type + operator()(const Index, const Index, + const Index) const + { + using TensorExpr + = Tensor3_contracted_02, T, Dim>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* A(j,j,i) */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim01 && Tensor_Dim2 >= Dim2), + Tensor1_Expr< + Tensor3_contracted_01, T, Dim01>, T, + Dim2, i>>::type + operator()(const Index, const Index, + const Index) const + { + using TensorExpr + = Tensor3_contracted_01, T, Dim01>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* This is for expressions where a number is used for one slot, and + indices for the others, yielding a Tensor2_Expr or + Tensor2_symmetric_Expr. The non-const versions don't actually + create a Dg_number_rhs_* object, while the const versions + do create a Dg_number_*. */ + + /* First slot. */ + + template + typename std::enable_if< + (Tensor_Dim01 > N && Tensor_Dim01 >= Dim1 && Tensor_Dim2 >= Dim2), + Tensor2_Expr, T, N>, T, + Dim1, Dim2, i, j>>::type + operator()(const Number, const Index, const Index) + { + using TensorExpr + = Dg_number_rhs_0, T, N>; + return Tensor2_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim01 > N && Tensor_Dim01 >= Dim1 && Tensor_Dim2 >= Dim2), + Tensor2_Expr, T, N>, + T, Dim1, Dim2, i, j>>::type + operator()(const Number, const Index, + const Index) const + { + using TensorExpr + = Dg_number_0, T, N>; + return Tensor2_Expr(TensorExpr(*this)); + } + + /* Second slot. */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim0 && Tensor_Dim01 > N && Tensor_Dim2 >= Dim2), + Tensor2_Expr, T, N>, T, + Dim0, Dim2, i, j>>::type + operator()(const Index, const Number, const Index) + { + using TensorExpr + = Dg_number_rhs_0, T, N>; + return Tensor2_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim0 && Tensor_Dim01 > N && Tensor_Dim2 >= Dim2), + Tensor2_Expr, T, N>, + T, Dim0, Dim2, i, j>>::type + operator()(const Index, const Number, + const Index) const + { + using TensorExpr + = Dg_number_0, T, N>; + return Tensor2_Expr(TensorExpr(*this)); + } + + /* Third slot. */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim && Tensor_Dim2 > N), + Tensor2_symmetric_Expr< + Dg_number_rhs_2, T, N>, T, Dim, i, + j>>::type + operator()(const Index, const Index, const Number) + { + using TensorExpr + = Dg_number_rhs_2, T, N>; + return Tensor2_symmetric_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim && Tensor_Dim2 > N), + Tensor2_symmetric_Expr< + Dg_number_2, T, N>, T, Dim, i, + j>>::type + operator()(const Index, const Index, const Number) const + { + using TensorExpr + = Dg_number_2, T, N>; + return Tensor2_symmetric_Expr( + TensorExpr(*this)); + } + // TODO add multiple dimensions up here ^^^^^ + /* This is for expressions where a number is used for two slots, and + an Index for the other, yielding a Tensor1_Expr. The non-const + versions don't actually create a Dg_number_rhs_* object, + while the const versions do create a Dg_number_*. */ + + /* Index in first slot. */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim && Tensor_Dim01 > N1 && Tensor_Dim2 > N2), + Tensor1_Expr, T, N1, N2>, + T, Dim, i>>::type + operator()(const Index index, const Number, const Number) + { + using TensorExpr + = Dg_number_rhs_12, T, N1, N2>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim && Tensor_Dim01 > N1 && Tensor_Dim2 > N2), + Tensor1_Expr< + Dg_number_12, T, N1, N2>, T, + Dim, i>>::type + operator()(const Index index, const Number, + const Number) const + { + using TensorExpr + = Dg_number_12, T, N1, N2>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Index in second slot. I use the same structures as for the Index + in the first slot since the tensor is symmetric on the first two + indices. */ + + template + typename std::enable_if< + (Tensor_Dim01 > N0 && Tensor_Dim01 >= Dim && Tensor_Dim2 > N2), + Tensor1_Expr, T, N0, N2>, + T, Dim, i>>::type + operator()(const Number, const Index, const Number) + { + using TensorExpr + = Dg_number_rhs_12, T, N0, N2>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim01 > N0 && Tensor_Dim01 >= Dim && Tensor_Dim2 > N2), + Tensor1_Expr< + Dg_number_12, T, N0, N2>, T, + Dim, i>>::type + operator()(const Number, const Index index, + const Number) const + { + using TensorExpr + = Dg_number_12, T, N0, N2>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Index in third slot. */ + + template + typename std::enable_if< + (Tensor_Dim01 > N0 && Tensor_Dim01 > N1 && Tensor_Dim2 >= Dim), + Tensor1_Expr, T, N0, N1>, + T, Dim, i>>::type + operator()(const Number, const Number, const Index index) + { + using TensorExpr + = Dg_number_rhs_01, T, N0, N1>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim01 > N0 && Tensor_Dim01 > N1 && Tensor_Dim2 >= Dim), + Tensor1_Expr< + Dg_number_01, T, N0, N1>, T, + Dim, i>>::type + operator()(const Number, const Number, const Index) const + { + using TensorExpr + = Dg_number_01, T, N0, N1>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Specializations for using actual numbers instead of Number<>. + This is for expressions where an actual number is used for one + slot, and indices for the others, yielding a Tensor2_Expr or + Tensor2_symmetric_Expr. I only define the const versions. */ + + /* First slot. */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim1 && Tensor_Dim2 >= Dim2), + Tensor2_Expr, T>, T, + Dim1, Dim2, i, j>>::type + operator()(const int N, const Index, const Index) const + { + using TensorExpr + = Dg_numeral_0, T>; + return Tensor2_Expr( + TensorExpr(*this, N)); + } + + /* Second slot. */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim0 && Tensor_Dim2 >= Dim2), + Tensor2_Expr, T>, T, + Dim0, Dim2, i, j>>::type + operator()(const Index, const int N, const Index) const + { + using TensorExpr + = Dg_numeral_0, T>; + return Tensor2_Expr( + TensorExpr(*this, N)); + } + + /* Third slot. */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim), + Tensor2_symmetric_Expr< + Dg_numeral_2, T>, T, Dim, i, + j>>::type + operator()(const Index, const Index, const int N) const + { + using TensorExpr + = Dg_numeral_2, T>; + return Tensor2_symmetric_Expr( + TensorExpr(*this, N)); + } + // TODO Allow two different dimensions in 1 and 2 + /* This is for expressions where a numeral is used for two slots, and + an Index for the other, yielding a Tensor1_Expr. */ + + /* Index in first slot. */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim), + Tensor1_Expr, T>, T, + Dim, i>>::type + operator()(const Index index, const int N1, const int N2) const + { + using TensorExpr + = Dg_numeral_12, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } + + /* Index in second slot. I use the same structures as for the Index + in the first slot since the tensor is symmetric on the first two + indices. */ + + template + typename std::enable_if< + (Tensor_Dim01 >= Dim), + Tensor1_Expr, T>, T, + Dim, i>>::type + operator()(const int N1, const Index index, const int N2) const + { + using TensorExpr + = Dg_numeral_12, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } + + /* Index in third slot. */ + + template + typename std::enable_if< + (Tensor_Dim2 >= Dim), + Tensor1_Expr, T>, T, + Dim, i>>::type + operator()(const int N1, const int N2, const Index) const + { + using TensorExpr + = Dg_numeral_01, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Dg/minus_Dg.hpp b/src/oofemlib/tensor/FTensor/Dg/minus_Dg.hpp new file mode 100644 index 000000000..527a1c53e --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Dg/minus_Dg.hpp @@ -0,0 +1,28 @@ +/* Unary minus operator. */ + +#pragma once + +namespace FTensor +{ + template + class minus_Dg + { + Dg_Expr iterA; + + public: + T operator()(const int N1, const int N2, const int N3) const + { + return -iterA(N1, N2, N3); + } + + minus_Dg(const Dg_Expr &a) : iterA(a) {} + }; + + template + Dg_Expr, T, Dim01, Dim2, i, j, k> + operator-(const Dg_Expr &a) + { + using TensorExpr = minus_Dg; + return Dg_Expr(TensorExpr(a)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Index.hpp b/src/oofemlib/tensor/FTensor/Index.hpp new file mode 100644 index 000000000..893388123 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Index.hpp @@ -0,0 +1,25 @@ +/* A simple index class that tells the operators which template to + instantiate. The usual way to do this is to declare an index like + + Index<'i',3> i; + + It is important that each differently named index has a different + template parameter. So + + Index<'i',3> i; + Index<'j',3> j; // Good + + is the right way, and + + Index<'i',3> i,j; // Bad + + is likely to lead to errors, since the program thinks that i and j + are identical. */ + +#pragma once + +namespace FTensor +{ + template class Index + {}; +} diff --git a/src/oofemlib/tensor/FTensor/Levi_Civita.hpp b/src/oofemlib/tensor/FTensor/Levi_Civita.hpp new file mode 100644 index 000000000..8cd4e026a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Levi_Civita.hpp @@ -0,0 +1,800 @@ +/// Fully Antisymmetric Levi-Civita Tensor + +#pragma once + +namespace FTensor +{ + /// Levi_Civita Classes + template class Levi_Civita + { + public: + /// Rank 2 + constexpr T operator()(const int N1, const int N2) const + { + return (N1 == N2) ? T(0) : ((N1 == 0) ? T(1) : T(-1)); + } + + template + typename std::enable_if< + (Dim0 <= 2 && Dim1 <= 2), + Tensor2_Expr, T, Dim0, Dim1, i, j>>::type + operator()(const Index &, const Index &) + { + return Tensor2_Expr, T, Dim0, Dim1, i, j>(*this); + }; + + template + constexpr auto operator()(const Index &, const int &N1) + { + static_assert( + Dim0 <= 2, + "Index dimension exceeds the maximum for Rank 2 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N1 >= 2 || N1 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(Index<" + + std::basic_string{i} + ", " + std::to_string(Dim0) + ">, " + + std::to_string(N1) + ")\n"); +#endif + auto TensorExpr + = [this, N1](const int &N0) { return this->operator()(N0, N1); }; + return Tensor1_Expr(TensorExpr); + }; + + template + constexpr auto operator()(const int &N0, const Index &) + { + static_assert( + Dim1 <= 2, + "Index dimension exceeds the maximum for Rank 2 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N0 >= 2 || N0 < 0) + throw std::out_of_range("Bad index in Levi_Civita::operator()(" + + std::to_string(N0) + ", Index<" + + std::basic_string{j} + ", " + + std::to_string(Dim1) + ">)\n"); +#endif + auto TensorExpr + = [this, N0](const int &N1) { return this->operator()(N0, N1); }; + return Tensor1_Expr{TensorExpr}; + }; + + /// Rank 3 + constexpr T operator()(const int N1, const int N2, const int N3) const + { + return (N1 == N2 || N1 == N3 || N2 == N3) + ? T(0) + : (((N1 + 1) % 3 == N2) ? T(1) : T(-1)); + } + + template + typename std::enable_if< + (Dim0 <= 3 && Dim1 <= 3 && Dim2 <= 3), + Tensor3_Expr, T, Dim0, Dim1, Dim2, i, j, k>>::type + operator()(const Index &, const Index &, + const Index &) + { + return Tensor3_Expr, T, Dim0, Dim1, Dim2, i, j, k>(*this); + }; + + template + auto + operator()(const Index &, const Index &, const int &N2) + { + static_assert( + Dim0 <= 3 && Dim1 <= 3, + "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N2 >= 3 || N2 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + "Index<" + + std::basic_string{i} + ", " + std::to_string(Dim0) + + ">, " + "Index<" + + std::basic_string{j} + ", " + std::to_string(Dim1) + ">, " + + std::to_string(N2) + ")\n"); +#endif + auto TensorExpr = [this, N2](const int &N0, const int &N1) { + return this->operator()(N0, N1, N2); + }; + return Tensor2_Expr{ + TensorExpr}; + } + + template + auto + operator()(const Index &, const int &N1, const Index &) + { + static_assert( + Dim0 <= 3 && Dim2 <= 3, + "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N1 >= 3 || N1 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + "Index<" + + std::basic_string{i} + ", " + std::to_string(Dim0) + ">, " + + std::to_string(N1) + + ", " + "Index<" + + std::basic_string{k} + ", " + std::to_string(Dim2) + ">)\n"); +#endif + auto TensorExpr = [this, N1](const int &N0, const int &N2) { + return this->operator()(N0, N1, N2); + }; + return Tensor2_Expr{ + TensorExpr}; + } + + template + auto + operator()(const int &N0, const Index &, const Index &) + { + static_assert( + Dim1 <= 3 && Dim2 <= 3, + "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N0 >= 3 || N0 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + std::to_string(N0) + + ", " + "Index<" + + std::basic_string{j} + ", " + std::to_string(Dim1) + + ">, " + "Index<" + + std::basic_string{k} + ", " + std::to_string(Dim2) + ">)\n"); +#endif + auto TensorExpr = [this, N0](const int &N1, const int &N2) { + return this->operator()(N0, N1, N2); + }; + return Tensor2_Expr{ + TensorExpr}; + } + + template + auto operator()(const Index &, const int &N1, const int &N2) + { + static_assert( + Dim0 <= 3, + "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N1 >= 3 || N1 < 0 || N2 >= 3 || N2 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + "Index<" + + std::basic_string{i} + ", " + std::to_string(Dim0) + ">, " + + std::to_string(N1) + ", " + std::to_string(N2) + ")\n"); +#endif + auto TensorExpr = [this, N1, N2](const int &N0) { + return this->operator()(N0, N1, N2); + }; + return Tensor1_Expr{TensorExpr}; + } + + template + auto operator()(const int &N0, const Index &, const int &N2) + { + static_assert( + Dim1 <= 3, + "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N0 >= 3 || N0 < 0 || N2 >= 3 || N2 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + std::to_string(N0) + + ", " + "Index<" + + std::basic_string{j} + ", " + std::to_string(Dim1) + ">, " + + std::to_string(N2) + ")\n"); +#endif + auto TensorExpr = [this, N0, N2](const int &N1) { + return this->operator()(N0, N1, N2); + }; + return Tensor1_Expr{TensorExpr}; + } + + template + auto operator()(const int &N0, const int &N1, const Index &) + { + static_assert( + Dim2 <= 3, + "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N0 >= 3 || N0 < 0 || N1 >= 3 || N1 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + std::to_string(N0) + + ", " + std::to_string(N1) + + ", " + "Index<" + + std::basic_string{k} + ", " + std::to_string(Dim2) + ">)\n"); +#endif + auto TensorExpr = [this, N0, N1](const int &N2) { + return this->operator()(N0, N1, N2); + }; + return Tensor1_Expr{TensorExpr}; + } + + /// Rank 4 + constexpr T + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return (N1 == N2 || N1 == N3 || N1 == N4 || N2 == N3 || N2 == N4 + || N3 == N4) + ? T(0) + : ((N1 + N2 == 1 || N1 + N2 == 5) + ? (((N2 + N3) % 4 == 3) ? T(1) : T(-1)) + : ((N1 + N2 == 2 || N1 + N2 == 4) + ? (((N2 + N3) % 4 == 1) ? T(1) : T(-1)) + : (N1 + N2 == 3 + ? (((N2 + N3) % 4 != 1) ? T(1) : T(-1)) + : T(0)))); + } + + template + typename std::enable_if< + (Dim0 <= 4 && Dim1 <= 4 && Dim2 <= 4 && Dim3 <= 4), + Tensor4_Expr, T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>>::type + operator()(const Index &, const Index &, + const Index &, const Index &) + { + return Tensor4_Expr, T, Dim0, Dim1, Dim2, Dim3, i, j, k, + l>(*this); + } + + template + constexpr auto operator()(const Index &, const Index &, + const Index &, const int &N3) + { + static_assert( + Dim0 <= 4 && Dim1 <= 4 && Dim2 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N3 >= 4 || N3 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + "Index<" + + std::basic_string{i} + ", " + std::to_string(Dim0) + + ">, " + "Index<" + + std::basic_string{j} + ", " + std::to_string(Dim1) + + ">, " + "Index<" + + std::basic_string{k} + ", " + std::to_string(Dim2) + ">, " + + std::to_string(N3) + ")\n"); +#endif + auto TensorExpr + = [this, N3](const int &N0, const int &N1, const int &N2) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor3_Expr{ + TensorExpr}; + } + + template + constexpr auto operator()(const Index &, const Index &, + const int &N2, const Index &) + { + static_assert( + Dim0 <= 4 && Dim1 <= 4 && Dim3 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N2 >= 4 || N2 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + "Index<" + + std::basic_string{i} + ", " + std::to_string(Dim0) + + ">, " + "Index<" + + std::basic_string{j} + ", " + std::to_string(Dim1) + ">, " + + std::to_string(N2) + + ", " + "Index<" + + std::basic_string{l} + ", " + std::to_string(Dim3) + ">)\n"); +#endif + auto TensorExpr + = [this, N2](const int &N0, const int &N1, const int &N3) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor3_Expr{ + TensorExpr}; + } + + template + constexpr auto operator()(const Index &, const int &N1, + const Index &, const Index &) + { + static_assert( + Dim0 <= 4 && Dim2 <= 4 && Dim3 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N1 >= 4 || N1 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + "Index<" + + std::basic_string{i} + ", " + std::to_string(Dim0) + ">, " + + std::to_string(N1) + + ", " + "Index<" + + std::basic_string{k} + ", " + std::to_string(Dim2) + + ">, " + "Index<" + + std::basic_string{l} + ", " + std::to_string(Dim3) + ">)\n"); +#endif + auto TensorExpr + = [this, N1](const int &N0, const int &N2, const int &N3) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor3_Expr{ + TensorExpr}; + } + + template + constexpr auto operator()(const int &N0, const Index &, + const Index &, const Index &) + { + static_assert( + Dim1 <= 4 && Dim2 <= 4 && Dim3 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N0 >= 4 || N0 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + std::to_string(N0) + + ", " + "Index<" + + std::basic_string{j} + ", " + std::to_string(Dim1) + + ">, " + "Index<" + + std::basic_string{k} + ", " + std::to_string(Dim2) + + ">, " + "Index<" + + std::basic_string{l} + ", " + std::to_string(Dim3) + ">)\n"); +#endif + auto TensorExpr + = [this, N0](const int &N1, const int &N2, const int &N3) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor3_Expr{ + TensorExpr}; + } + + template + constexpr auto operator()(const Index &, const Index &, + const int &N2, const int &N3) + { + static_assert( + Dim0 <= 4 && Dim1 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N2 >= 4 || N2 < 0 || N3 >= 4 || N3 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + "Index<" + + std::basic_string{i} + ", " + std::to_string(Dim0) + + ">, " + "Index<" + + std::basic_string{j} + ", " + std::to_string(Dim1) + ">, " + + std::to_string(N2) + ", " + std::to_string(N3) + ")\n"); +#endif + auto TensorExpr = [this, N2, N3](const int &N0, const int &N1) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor2_Expr{ + TensorExpr}; + } + + template + constexpr auto operator()(const Index &, const int &N1, + const Index &, const int &N3) + { + static_assert( + Dim0 <= 4 && Dim2 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N1 >= 4 || N1 < 0 || N3 >= 4 || N3 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + "Index<" + + std::basic_string{i} + ", " + std::to_string(Dim0) + ">, " + + std::to_string(N1) + + ", " + "Index<" + + std::basic_string{k} + ", " + std::to_string(Dim2) + ">, " + + std::to_string(N3) + ")\n"); +#endif + auto TensorExpr = [this, N1, N3](const int &N0, const int &N2) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor2_Expr{ + TensorExpr}; + } + + template + constexpr auto operator()(const int &N0, const Index &, + const Index &, const int &N3) + { + static_assert( + Dim1 <= 4 && Dim2 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N0 >= 4 || N0 < 0 || N3 >= 4 || N3 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + std::to_string(N0) + + ", " + "Index<" + + std::basic_string{j} + ", " + std::to_string(Dim1) + + ">, " + "Index<" + + std::basic_string{k} + ", " + std::to_string(Dim2) + ">, " + + std::to_string(N3) + ")\n"); +#endif + auto TensorExpr = [this, N0, N3](const int &N1, const int &N2) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor2_Expr{ + TensorExpr}; + } + + template + constexpr auto operator()(const Index &, const int &N1, + const int &N2, const Index &) + { + static_assert( + Dim0 <= 4 && Dim3 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N1 >= 4 || N1 < 0 || N2 >= 4 || N2 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + "Index<" + + std::basic_string{i} + ", " + std::to_string(Dim0) + ">, " + + std::to_string(N1) + ", " + std::to_string(N2) + + ", " + "Index<" + + std::basic_string{l} + ", " + std::to_string(Dim3) + ">)\n"); +#endif + auto TensorExpr = [this, N1, N2](const int &N0, const int &N3) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor2_Expr{ + TensorExpr}; + } + + template + constexpr auto operator()(const int &N0, const Index &, + const int &N2, const Index &) + { + static_assert( + Dim1 <= 4 && Dim3 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N0 >= 4 || N0 < 0 || N2 >= 4 || N2 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + std::to_string(N0) + + ", " + "Index<" + + std::basic_string{j} + ", " + std::to_string(Dim1) + ">, " + + std::to_string(N2) + + ", " + "Index<" + + std::basic_string{l} + ", " + std::to_string(Dim3) + ">)\n"); +#endif + auto TensorExpr = [this, N0, N2](const int &N1, const int &N3) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor2_Expr{ + TensorExpr}; + } + + template + constexpr auto operator()(const int &N0, const int &N1, + const Index &, const Index &) + { + static_assert( + Dim2 <= 4 && Dim3 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N0 >= 4 || N0 < 0 || N1 >= 4 || N1 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + std::to_string(N0) + + ", " + std::to_string(N1) + + ", " + "Index<" + + std::basic_string{k} + ", " + std::to_string(Dim2) + + ">, " + "Index<" + + std::basic_string{l} + ", " + std::to_string(Dim3) + ">)\n"); +#endif + auto TensorExpr = [this, N0, N1](const int &N2, const int &N3) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor2_Expr{ + TensorExpr}; + } + + template + constexpr auto operator()(const Index &, const int &N1, + const int &N2, const int &N3) + { + static_assert( + Dim0 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N1 >= 4 || N1 < 0 || N2 >= 4 || N2 < 0 || N3 >= 4 || N3 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + "Index<" + + std::basic_string{i} + ", " + std::to_string(Dim0) + ">, " + + std::to_string(N1) + ", " + std::to_string(N2) + ", " + + std::to_string(N3) + ")\n"); +#endif + auto TensorExpr = [this, N1, N2, N3](const int &N0) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor1_Expr{TensorExpr}; + } + + template + constexpr auto operator()(const int &N0, const Index &, + const int &N2, const int &N3) + { + static_assert( + Dim1 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N0 >= 4 || N0 < 0 || N2 >= 4 || N2 < 0 || N3 >= 4 || N3 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + std::to_string(N0) + + ", " + "Index<" + + std::basic_string{j} + ", " + std::to_string(Dim1) + ">, " + + std::to_string(N2) + ", " + std::to_string(N3) + ")\n"); +#endif + auto TensorExpr = [this, N0, N2, N3](const int &N1) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor1_Expr{TensorExpr}; + } + + template + constexpr auto operator()(const int &N0, const int &N1, + const Index &, const int &N3) + { + static_assert( + Dim2 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N0 >= 4 || N0 < 0 || N1 >= 4 || N1 < 0 || N3 >= 4 || N3 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + std::to_string(N0) + + ", " + std::to_string(N1) + + ", " + "Index<" + + std::basic_string{k} + ", " + std::to_string(Dim2) + ">, " + + std::to_string(N3) + ")\n"); +#endif + auto TensorExpr = [this, N0, N1, N3](const int &N2) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor1_Expr{TensorExpr}; + } + + template + constexpr auto operator()(const int &N0, const int &N1, const int &N2, + const Index &) + { + static_assert( + Dim3 <= 4, + "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor"); +#ifdef FTENSOR_DEBUG + if(N0 >= 4 || N0 < 0 || N1 >= 4 || N1 < 0 || N2 >= 4 || N2 < 0) + throw std::out_of_range( + "Bad index in Levi_Civita::operator()(" + std::to_string(N0) + + ", " + std::to_string(N1) + ", " + std::to_string(N2) + + ", " + "Index<" + + std::basic_string{l} + ", " + std::to_string(Dim3) + ">)\n"); +#endif + auto TensorExpr = [this, N0, N1, N2](const int &N3) { + return this->operator()(N0, N1, N2, N3); + }; + return Tensor1_Expr{TensorExpr}; + } + }; + + /// levi_civita functions to make for easy adhoc use + + /// Normally, this should go in is own file levi_civita.hpp, but + /// not all filesystems can handle files that differ only in case :( + + /// Rank 2 + template + constexpr typename std::enable_if< + (Dim0 <= 2 && Dim1 <= 2), + Tensor2_Expr, T, Dim0, Dim1, i, j>>::type + levi_civita(const Index &, const Index &) + { + return Levi_Civita()(Index(), Index()); + } + + template + constexpr auto levi_civita(const Index &, const int &N1) + { + return Levi_Civita()(Index(), N1); + } + + template + constexpr auto levi_civita(const int &N0, const Index &) + { + return Levi_Civita()(N0, Index()); + } + + /// Rank 3 + template + constexpr typename std::enable_if< + (Dim0 <= 3 && Dim1 <= 3 && Dim2 <= 3), + Tensor3_Expr, T, Dim0, Dim1, Dim2, i, j, k>>::type + levi_civita(const Index &, const Index &, + const Index &) + { + return Levi_Civita()(Index(), Index(), + Index()); + } + + template + constexpr auto + levi_civita(const Index &, const Index &, const int &N2) + { + return Levi_Civita()(Index(), Index(), N2); + } + + template + constexpr auto + levi_civita(const Index &, const int &N1, const Index &) + { + return Levi_Civita()(Index(), N1, Index()); + } + + template + constexpr auto + levi_civita(const int &N0, const Index &, const Index &) + { + return Levi_Civita()(N0, Index(), Index()); + } + + template + constexpr auto + levi_civita(const Index &, const int &N1, const int &N2) + { + return Levi_Civita()(Index(), N1, N2); + } + + template + constexpr auto + levi_civita(const int &N0, const Index &, const int &N2) + { + return Levi_Civita()(N0, Index(), N2); + } + + template + constexpr auto + levi_civita(const int &N0, const int &N1, const Index &) + { + return Levi_Civita()(N0, N1, Index()); + } + + /// Rank 4 + template + constexpr typename std::enable_if< + (Dim0 <= 4 && Dim1 <= 4 && Dim2 <= 4 && Dim3 <= 4), + Tensor4_Expr, T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>>::type + levi_civita(const Index &, const Index &, + const Index &, const Index &) + { + return Levi_Civita()(Index(), Index(), + Index(), Index()); + } + + template + constexpr auto levi_civita(const Index &, const Index &, + const Index &, const int &N3) + { + return Levi_Civita()(Index(), Index(), + Index(), N3); + } + + template + constexpr auto levi_civita(const Index &, const Index &, + const int &N2, const Index &) + { + return Levi_Civita()(Index(), Index(), N2, + Index()); + } + + template + constexpr auto levi_civita(const Index &, const int &N1, + const Index &, const Index &) + { + return Levi_Civita()(Index(), N1, Index(), + Index()); + } + + template + constexpr auto levi_civita(const int &N0, const Index &, + const Index &, const Index &) + { + return Levi_Civita()(N0, Index(), Index(), + Index()); + } + + template + constexpr auto levi_civita(const Index &, const Index &, + const int &N2, const int &N3) + { + return Levi_Civita()(Index(), Index(), N2, N3); + } + + template + constexpr auto levi_civita(const Index &, const int &N1, + const Index &, const int &N3) + { + return Levi_Civita()(Index(), N1, Index(), N3); + } + + template + constexpr auto levi_civita(const int &N0, const Index &, + const Index &, const int &N3) + { + return Levi_Civita()(N0, Index(), Index(), N3); + } + + template + constexpr auto levi_civita(const Index &, const int &N1, + const int &N2, const Index &) + { + return Levi_Civita()(Index(), N1, N2, Index()); + } + + template + constexpr auto levi_civita(const int &N0, const Index &, + const int &N2, const Index &) + { + return Levi_Civita()(N0, Index(), N2, Index()); + } + + template + constexpr auto levi_civita(const int &N0, const int &N1, + const Index &, const Index &) + { + return Levi_Civita()(N0, N1, Index(), Index()); + } + + template + constexpr auto levi_civita(const Index &, const int &N1, + const int &N2, const int &N3) + { + return Levi_Civita()(Index(), N1, N2, N3); + } + + template + constexpr auto levi_civita(const int &N0, const Index &, + const int &N2, const int &N3) + { + return Levi_Civita()(N0, Index(), N2, N3); + } + + template + constexpr auto levi_civita(const int &N0, const int &N1, + const Index &, const int &N3) + { + return Levi_Civita()(N0, N1, Index(), N3); + } + + template + constexpr auto levi_civita(const int &N0, const int &N1, const int &N2, + const Index &) + { + return Levi_Civita()(N0, N1, N2, Index()); + } +} diff --git a/src/oofemlib/tensor/FTensor/Number.hpp b/src/oofemlib/tensor/FTensor/Number.hpp new file mode 100644 index 000000000..5021566b8 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Number.hpp @@ -0,0 +1,17 @@ +/* This index class allows you to explicitly use a part of a tensor. + If you want to explicitly list all of the indices, just use + int's. The usual way to do this is to declare a Number like + + Number<0> N; */ + +#pragma once + +namespace FTensor +{ + template class Number + { + public: + Number(){}; + operator int() const { return N; } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Permutation2.hpp b/src/oofemlib/tensor/FTensor/Permutation2.hpp new file mode 100644 index 000000000..5ef63576c --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Permutation2.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "error_when_instantiated.hpp" + +namespace FTensor +{ + template struct Permutation2 + { + Permutation2() = default; + + template + U eval(const Tensor2_Expr &rhs, const int N0, + const int N1) + { + return rhs(N0, N1); + } + + template + U eval(const Tensor2_Expr &rhs, const int N0, + const int N1) + { + return rhs(N1, N0); + } + + template + U eval(const Tensor2_Expr &rhs, const int N0, + const int N1) + { + static_assert(error_when_instantiated(), "Incompatible indices"); + return rhs(0, 0); + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Permutation3.hpp b/src/oofemlib/tensor/FTensor/Permutation3.hpp new file mode 100644 index 000000000..bd8e1a1de --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Permutation3.hpp @@ -0,0 +1,64 @@ +#pragma once + +#include "error_when_instantiated.hpp" + +namespace FTensor +{ + template + struct Permutation3 + { + Permutation3() = default; + + template + U eval(const Tensor3_Expr &rhs, + const int N0, const int N1, const int N2) + { + return rhs(N0, N1, N2); + } + + template + U eval(const Tensor3_Expr &rhs, + const int N0, const int N1, const int N2) + { + return rhs(N0, N2, N1); + } + + template + U eval(const Tensor3_Expr &rhs, + const int N0, const int N1, const int N2) + { + return rhs(N1, N0, N2); + } + + template + U eval(const Tensor3_Expr &rhs, + const int N0, const int N1, const int N2) + { + return rhs(N1, N2, N0); + } + + template + U eval(const Tensor3_Expr &rhs, + const int N0, const int N1, const int N2) + { + return rhs(N2, N0, N1); + } + + template + U eval(const Tensor3_Expr &rhs, + const int N0, const int N1, const int N2) + { + return rhs(N2, N1, N0); + } + + // Catch-all version for incompatible indices + template + U eval(const Tensor3_Expr &rhs, + const int N0, const int N1, const int N2) + { + static_assert(error_when_instantiated(), "Incompatible indices"); + return rhs(0, 0, 0); + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Permutation4.hpp b/src/oofemlib/tensor/FTensor/Permutation4.hpp new file mode 100644 index 000000000..4b81ebda5 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Permutation4.hpp @@ -0,0 +1,196 @@ +#pragma once + +#include "error_when_instantiated.hpp" + +namespace FTensor +{ + template + struct Permutation4 + { + Permutation4() = default; + + // (i,...) + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N0, N1, N2, N3); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N0, N1, N3, N2); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N0, N2, N1, N3); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N0, N2, N3, N1); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N0, N3, N1, N2); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N0, N3, N2, N1); + } + + // (j,...) + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N1, N0, N2, N3); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N1, N0, N3, N2); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N1, N2, N0, N3); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N1, N2, N3, N0); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N1, N3, N0, N2); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N1, N3, N2, N0); + } + + // (k,...) + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N2, N1, N0, N3); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N2, N1, N3, N0); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N2, N0, N1, N3); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N2, N0, N3, N1); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N2, N3, N1, N0); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N2, N3, N0, N1); + } + + // (l,...) + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N3, N1, N2, N0); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N3, N1, N0, N2); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N3, N2, N1, N0); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N3, N2, N0, N1); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N3, N0, N1, N2); + } + + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return rhs(N3, N0, N2, N1); + } + + // Catch-all version for incompatible indices + template + U eval(const Tensor4_Expr &rhs, + const int N0, const int N1, const int N2, const int N3) + { + static_assert(error_when_instantiated(), "Incompatible indices"); + return rhs(0, 0, 0, 0); + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Riemann.hpp b/src/oofemlib/tensor/FTensor/Riemann.hpp new file mode 100644 index 000000000..5bff75d68 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Riemann.hpp @@ -0,0 +1,200 @@ +/* Declaration for Riemann, which has the symmetries of the + Riemann tensor. Antisymmetric on the first two indices and the + last two indices, and symmetric on a cyclic permutation of the last + three indices. */ + +#pragma once + +namespace FTensor +{ + template class Riemann + {}; + + template class Riemann + { + /* The zero variable is because some of the components of a tensor + with these symmetries are identically zero. */ + + T zero; + T data0101, data0102, data0112, data0202, data0212, data1212; + + public: + Riemann() : zero(0.0) {} + + /* There are two operator(int,int,int,int)'s, one for non-consts + that lets you change the value, and one for consts that doesn't. + The non-const one will give you a wrong answer if you aren't + careful. The problem is that we only store the minimal set of + components, but some have different signs. We can't return the + negative of a component, and assign something to it, because that + would assign something to a temporary. To get the correct answer + if you don't want to change the value, use eval instead. */ + + T operator()(const int N1, const int N2, const int N3, const int N4) const + { + return N1 == 0 + ? (N2 == 0 + ? zero + : (N2 == 1 + ? (N3 == 0 + ? (N4 == 0 ? zero + : (N4 == 1 ? data0101 : data0102)) + : (N3 == 1 + ? (N4 == 0 ? -data0101 + : (N4 == 1 ? zero : data0112)) + : (N4 == 0 ? -data0102 + : (N4 == 1 ? -data0112 : zero)))) + : (N3 == 0 + ? (N4 == 0 ? zero + : (N4 == 1 ? data0102 : data0202)) + : (N3 == 1 + ? (N4 == 0 ? -data0102 + : (N4 == 1 ? zero : data0212)) + : (N4 == 0 + ? -data0202 + : (N4 == 1 ? -data0212 : zero)))))) + : (N1 == 1 + ? (N2 == 0 + ? (N3 == 0 + ? (N4 == 0 ? zero + : (N4 == 1 ? -data0101 : -data0102)) + : (N3 == 1 + ? (N4 == 0 ? data0101 + : (N4 == 1 ? zero : -data0112)) + : (N4 == 0 ? data0102 + : (N4 == 1 ? data0112 : zero)))) + : (N2 == 1 + ? zero + : (N3 == 0 + ? (N4 == 0 ? zero + : (N4 == 1 ? data0112 : data0212)) + : (N3 == 1 + ? (N4 == 0 + ? -data0112 + : (N4 == 1 ? zero : data1212)) + : (N4 == 0 ? -data0212 + : (N4 == 1 ? -data1212 + : zero)))))) + : (N2 == 0 + ? (N3 == 0 + ? (N4 == 0 ? zero + : (N4 == 1 ? -data0102 : -data0202)) + : (N3 == 1 + ? (N4 == 0 ? data0102 + : (N4 == 1 ? zero : -data0212)) + : (N4 == 0 ? data0202 + : (N4 == 1 ? data0212 : zero)))) + : (N2 == 1 + ? (N3 == 0 + ? (N4 == 0 + ? zero + : (N4 == 1 ? -data0112 : -data0212)) + : (N3 == 1 + ? (N4 == 0 + ? data0112 + : (N4 == 1 ? zero : -data1212)) + : (N4 == 0 + ? data0212 + : (N4 == 1 ? data1212 : zero)))) + : zero))); + } + + T eval(const int N1, const int N2, const int N3, const int N4) const + { + return N1 == 0 + ? (N2 == 0 + ? zero + : (N2 == 1 + ? (N3 == 0 + ? (N4 == 0 ? zero + : (N4 == 1 ? data0101 : data0102)) + : (N3 == 1 + ? (N4 == 0 ? -data0101 + : (N4 == 1 ? zero : data0112)) + : (N4 == 0 ? -data0102 + : (N4 == 1 ? -data0112 : zero)))) + : (N3 == 0 + ? (N4 == 0 ? zero + : (N4 == 1 ? data0102 : data0202)) + : (N3 == 1 + ? (N4 == 0 ? -data0102 + : (N4 == 1 ? zero : data0212)) + : (N4 == 0 + ? -data0202 + : (N4 == 1 ? -data0212 : zero)))))) + : (N1 == 1 + ? (N2 == 0 + ? (N3 == 0 + ? (N4 == 0 ? zero + : (N4 == 1 ? -data0101 : -data0102)) + : (N3 == 1 + ? (N4 == 0 ? data0101 + : (N4 == 1 ? zero : -data0112)) + : (N4 == 0 ? data0102 + : (N4 == 1 ? data0112 : zero)))) + : (N2 == 1 + ? zero + : (N3 == 0 + ? (N4 == 0 ? zero + : (N4 == 1 ? data0112 : data0212)) + : (N3 == 1 + ? (N4 == 0 + ? -data0112 + : (N4 == 1 ? zero : data1212)) + : (N4 == 0 ? -data0212 + : (N4 == 1 ? -data1212 + : zero)))))) + : (N2 == 0 + ? (N3 == 0 + ? (N4 == 0 ? zero + : (N4 == 1 ? -data0102 : -data0202)) + : (N3 == 1 + ? (N4 == 0 ? data0102 + : (N4 == 1 ? zero : -data0212)) + : (N4 == 0 ? data0202 + : (N4 == 1 ? data0212 : zero)))) + : (N2 == 1 + ? (N3 == 0 + ? (N4 == 0 + ? zero + : (N4 == 1 ? -data0112 : -data0212)) + : (N3 == 1 + ? (N4 == 0 + ? data0112 + : (N4 == 1 ? zero : -data1212)) + : (N4 == 0 + ? data0212 + : (N4 == 1 ? data1212 : zero)))) + : zero))); + } + + T &operator()(const int N1, const int N2, const int N3, const int N4) + { + return (N1 == 0 && N2 == 1 && N3 == 0 && N4 == 1) + ? data0101 + : ((N1 == 0 && N2 == 1 && N3 == 0 && N4 == 2) + ? data0102 + : ((N1 == 0 && N2 == 1 && N3 == 1 && N4 == 2) + ? data0112 + : ((N1 == 0 && N2 == 2 && N3 == 1 && N4 == 2) + ? data0212 + : ((N1 == 0 && N2 == 2 && N3 == 0 && N4 == 2) + ? data0202 + : ((N1 == 1 && N2 == 2 && N3 == 1 && N4 == 2) + ? data1212 + : zero))))); + } + + /* These operator()'s are the first part in constructing template + expressions. */ + + template + Riemann_Expr, T, 3, i, j, k, l> + operator()(const Index, const Index, const Index, + const Index) + { + return Riemann_Expr, T, 3, i, j, k, l>(*this); + } + }; +} +#include "Riemann/Riemann_Expr.hpp" diff --git a/src/oofemlib/tensor/FTensor/Riemann/Riemann_Expr.hpp b/src/oofemlib/tensor/FTensor/Riemann/Riemann_Expr.hpp new file mode 100644 index 000000000..4c0062936 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Riemann/Riemann_Expr.hpp @@ -0,0 +1,90 @@ +/* Declares a wrapper class for rank 4 Tensor expressions with Riemann + symmetries. */ + +#pragma once + +#include "Riemann_minus_Riemann.hpp" +#include "Riemann_plus_Riemann.hpp" +#include "Riemann_times_Ddg.hpp" +#include "Riemann_times_Tensor1.hpp" +#include "Riemann_times_Tensor2_symmetric.hpp" + +namespace FTensor +{ + template + class Riemann_Expr + { + A iter; + + public: + Riemann_Expr(const A &a) : iter(a) {} + T operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iter(N1, N2, N3, N4); + } + }; + + template + class Riemann_Expr, T, Dim, i, j, k, l> + { + Riemann &iter; + + public: + Riemann_Expr(Riemann &a) : iter(a) {} + T operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iter.eval(N1, N2, N3, N4); + } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + const Riemann_Expr, T, Dim, i, j, k, l> & + operator=(const Riemann_Expr &result) + { + iter(0, 1, 0, 1) = result(0, 1, 0, 1); + iter(0, 1, 0, 2) = result(0, 1, 0, 2); + iter(0, 2, 0, 2) = result(0, 2, 0, 2); + iter(0, 1, 1, 2) = result(0, 1, 1, 2); + iter(0, 2, 1, 2) = result(0, 2, 1, 2); + iter(1, 2, 1, 2) = result(1, 2, 1, 2); + return *this; + } + + const Riemann_Expr, T, Dim, i, j, k, l> & + operator=(const Riemann_Expr, T, Dim, i, j, k, l> &result) + { + return operator=, T>(result); + } + template + const Riemann_Expr, T, Dim, i, j, k, l> & + operator+=(const Riemann_Expr &result) + { + iter(0, 1, 0, 1) += result(0, 1, 0, 1); + iter(0, 1, 0, 2) += result(0, 1, 0, 2); + iter(0, 2, 0, 2) += result(0, 2, 0, 2); + iter(0, 1, 1, 2) += result(0, 1, 1, 2); + iter(0, 2, 1, 2) += result(0, 2, 1, 2); + iter(1, 2, 1, 2) += result(1, 2, 1, 2); + return *this; + } + + /* Add a Riemann with the indices switched, making it a + subtraction. */ + + template + const Riemann_Expr, T, Dim, i, j, k, l> & + operator+=(const Riemann_Expr &result) + { + iter(0, 1, 0, 1) -= result(0, 1, 0, 1); + iter(0, 1, 0, 2) -= result(0, 1, 0, 2); + iter(0, 2, 0, 2) -= result(0, 2, 0, 2); + iter(0, 1, 1, 2) -= result(0, 1, 1, 2); + iter(0, 2, 1, 2) -= result(0, 2, 1, 2); + iter(1, 2, 1, 2) -= result(1, 2, 1, 2); + return *this; + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Riemann/Riemann_minus_Riemann.hpp b/src/oofemlib/tensor/FTensor/Riemann/Riemann_minus_Riemann.hpp new file mode 100644 index 000000000..c66bb49df --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Riemann/Riemann_minus_Riemann.hpp @@ -0,0 +1,39 @@ +/* Subtracts a Riemann from a Riemann, yielding a + Riemann. */ + +#pragma once + +namespace FTensor +{ + template + class Riemann_minus_Riemann + { + Riemann_Expr iterA; + Riemann_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) - iterB(N1, N2, N3, N4); + } + + Riemann_minus_Riemann(const Riemann_Expr &a, + const Riemann_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Riemann_Expr, + typename promote::V, Dim, i, j, k, l> + operator-(const Riemann_Expr &a, + const Riemann_Expr &b) + { + using TensorExpr = Riemann_minus_Riemann; + return Riemann_Expr::V, Dim, i, j, k, l>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Riemann/Riemann_plus_Riemann.hpp b/src/oofemlib/tensor/FTensor/Riemann/Riemann_plus_Riemann.hpp new file mode 100644 index 000000000..4bf0b3cc7 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Riemann/Riemann_plus_Riemann.hpp @@ -0,0 +1,39 @@ +/* Adds a Riemann to a Riemann, yielding a + Riemann. */ + +#pragma once + +namespace FTensor +{ + template + class Riemann_plus_Riemann + { + Riemann_Expr iterA; + Riemann_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) + iterB(N1, N2, N3, N4); + } + + Riemann_plus_Riemann(const Riemann_Expr &a, + const Riemann_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Riemann_Expr, + typename promote::V, Dim, i, j, k, l> + operator+(const Riemann_Expr &a, + const Riemann_Expr &b) + { + using TensorExpr = Riemann_plus_Riemann; + return Riemann_Expr::V, Dim, i, j, k, l>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Ddg.hpp b/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Ddg.hpp new file mode 100644 index 000000000..80b6852cf --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Ddg.hpp @@ -0,0 +1,84 @@ +/* This file has the declaration for Riemann*Ddg + yielding a typename promote::V. I simplify the expression by + removing the identically zero components of Riemann. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(i,j,k,l) */ + + template + typename promote::V + operator*(const Riemann_Expr &a, + const Ddg_Expr &b) + { + return a(1, 0, 0, 1) * b(1, 0, 0, 1) + a(2, 0, 0, 1) * b(2, 0, 0, 1) + + a(0, 1, 0, 1) * b(0, 1, 0, 1) + a(2, 1, 0, 1) * b(2, 1, 0, 1) + + a(0, 2, 0, 1) * b(0, 2, 0, 1) + a(1, 2, 0, 1) * b(1, 2, 0, 1) + + a(1, 0, 0, 2) * b(1, 0, 0, 2) + a(2, 0, 0, 2) * b(2, 0, 0, 2) + + a(0, 1, 0, 2) * b(0, 1, 0, 2) + a(2, 1, 0, 2) * b(2, 1, 0, 2) + + a(0, 2, 0, 2) * b(0, 2, 0, 2) + a(1, 2, 0, 2) * b(1, 2, 0, 2) + + a(1, 0, 1, 0) * b(1, 0, 1, 0) + a(2, 0, 1, 0) * b(2, 0, 1, 0) + + a(0, 1, 1, 0) * b(0, 1, 1, 0) + a(2, 1, 1, 0) * b(2, 1, 1, 0) + + a(0, 2, 1, 0) * b(0, 2, 1, 0) + a(1, 2, 1, 0) * b(1, 2, 1, 0) + + a(1, 0, 1, 2) * b(1, 0, 1, 2) + a(2, 0, 1, 2) * b(2, 0, 1, 2) + + a(0, 1, 1, 2) * b(0, 1, 1, 2) + a(2, 1, 1, 2) * b(2, 1, 1, 2) + + a(0, 2, 1, 2) * b(0, 2, 1, 2) + a(1, 2, 1, 2) * b(1, 2, 1, 2) + + a(1, 0, 2, 0) * b(1, 0, 2, 0) + a(2, 0, 2, 0) * b(2, 0, 2, 0) + + a(0, 1, 2, 0) * b(0, 1, 2, 0) + a(2, 1, 2, 0) * b(2, 1, 2, 0) + + a(0, 2, 2, 0) * b(0, 2, 2, 0) + a(1, 2, 2, 0) * b(1, 2, 2, 0) + + a(1, 0, 2, 1) * b(1, 0, 2, 1) + a(2, 0, 2, 1) * b(2, 0, 2, 1) + + a(0, 1, 2, 1) * b(0, 1, 2, 1) + a(2, 1, 2, 1) * b(2, 1, 2, 1) + + a(0, 2, 2, 1) * b(0, 2, 2, 1) + a(1, 2, 2, 1) * b(1, 2, 2, 1); + } + + template + typename promote::V + operator*(const Ddg_Expr &b, + const Riemann_Expr &a) + + { + return operator*(a, b); + } + + /* A(i,j,k,l)*B(i,k,j,l) */ + + template + typename promote::V + operator*(const Riemann_Expr &a, + const Ddg_Expr &b) + { + return a(1, 0, 0, 1) * b(1, 0, 0, 1) + a(2, 0, 0, 1) * b(2, 0, 0, 1) + + a(0, 1, 0, 1) * b(0, 0, 1, 1) + a(2, 1, 0, 1) * b(2, 0, 1, 1) + + a(0, 2, 0, 1) * b(0, 0, 2, 1) + a(1, 2, 0, 1) * b(1, 0, 2, 1) + + a(1, 0, 0, 2) * b(1, 0, 0, 2) + a(2, 0, 0, 2) * b(2, 0, 0, 2) + + a(0, 1, 0, 2) * b(0, 0, 1, 2) + a(2, 1, 0, 2) * b(2, 0, 1, 2) + + a(0, 2, 0, 2) * b(0, 0, 2, 2) + a(1, 2, 0, 2) * b(1, 0, 2, 2) + + a(1, 0, 1, 0) * b(1, 1, 0, 0) + a(2, 0, 1, 0) * b(2, 1, 0, 0) + + a(0, 1, 1, 0) * b(0, 1, 1, 0) + a(2, 1, 1, 0) * b(2, 1, 1, 0) + + a(0, 2, 1, 0) * b(0, 1, 2, 0) + a(1, 2, 1, 0) * b(1, 1, 2, 0) + + a(1, 0, 1, 2) * b(1, 1, 0, 2) + a(2, 0, 1, 2) * b(2, 1, 0, 2) + + a(0, 1, 1, 2) * b(0, 1, 1, 2) + a(2, 1, 1, 2) * b(2, 1, 1, 2) + + a(0, 2, 1, 2) * b(0, 1, 2, 2) + a(1, 2, 1, 2) * b(1, 1, 2, 2) + + a(1, 0, 2, 0) * b(1, 2, 0, 0) + a(2, 0, 2, 0) * b(2, 2, 0, 0) + + a(0, 1, 2, 0) * b(0, 2, 1, 0) + a(2, 1, 2, 0) * b(2, 2, 1, 0) + + a(0, 2, 2, 0) * b(0, 2, 2, 0) + a(1, 2, 2, 0) * b(1, 2, 2, 0) + + a(1, 0, 2, 1) * b(1, 2, 0, 1) + a(2, 0, 2, 1) * b(2, 2, 0, 1) + + a(0, 1, 2, 1) * b(0, 2, 1, 1) + a(2, 1, 2, 1) * b(2, 2, 1, 1) + + a(0, 2, 2, 1) * b(0, 2, 2, 1) + a(1, 2, 2, 1) * b(1, 2, 2, 1); + } + + template + typename promote::V + operator*(const Ddg_Expr &b, + const Riemann_Expr &a) + + { + return operator*(a, b); + } +} diff --git a/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Tensor1.hpp new file mode 100644 index 000000000..6c7fb4ae7 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Tensor1.hpp @@ -0,0 +1,207 @@ +/* This file has all of the declarations for expressions like + Riemann*Tensor1, yielding a Tensor3_antisymmetric. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(i) */ + + template + class Riemann_times_Tensor1_0 + { + Riemann_Expr iterA; + Tensor1_Expr iterB; + + public: + Riemann_times_Tensor1_0(const Riemann_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(0, N1, N2, N3) * iterB(0) + iterA(1, N1, N2, N3) * iterB(1) + + iterA(2, N1, N2, N3) * iterB(2); + } + }; + + template + Tensor3_antisymmetric_Expr< + Riemann_times_Tensor1_0, + typename promote::V, Dim, Dim, j, k, l> + operator*(const Riemann_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Riemann_times_Tensor1_0; + return Tensor3_antisymmetric_Expr::V, + Dim, Dim, j, k, l>(TensorExpr(a, b)); + } + + /* B(i)*A(i,j,k,l) */ + + template + Tensor3_antisymmetric_Expr< + Riemann_times_Tensor1_0, + typename promote::V, Dim, Dim, j, k, l> + operator*(const Tensor1_Expr &b, + const Riemann_Expr &a) + { + using TensorExpr = Riemann_times_Tensor1_0; + return Tensor3_antisymmetric_Expr::V, + Dim, Dim, j, k, l>(TensorExpr(a, b)); + } + + /* A(i,j,k,l)*B(j) */ + + template + class Riemann_times_Tensor1_1 + { + Riemann_Expr iterA; + Tensor1_Expr iterB; + + public: + Riemann_times_Tensor1_1(const Riemann_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, 0, N2, N3) * iterB(0) + iterA(N1, 1, N2, N3) * iterB(1) + + iterA(N1, 2, N2, N3) * iterB(2); + } + }; + + template + Tensor3_antisymmetric_Expr< + Riemann_times_Tensor1_1, + typename promote::V, Dim, Dim, i, k, l> + operator*(const Riemann_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Riemann_times_Tensor1_1; + return Tensor3_antisymmetric_Expr::V, + Dim, Dim, i, k, l>(TensorExpr(a, b)); + } + + /* B(j)*A(i,j,k,l) */ + + template + Tensor3_antisymmetric_Expr< + Riemann_times_Tensor1_1, + typename promote::V, Dim, Dim, i, k, l> + operator*(const Tensor1_Expr &b, + const Riemann_Expr &a) + { + using TensorExpr = Riemann_times_Tensor1_1; + return Tensor3_antisymmetric_Expr::V, + Dim, Dim, i, k, l>(TensorExpr(a, b)); + } + + /* A(i,j,k,l)*B(k) */ + + template + class Riemann_times_Tensor1_2 + { + Riemann_Expr iterA; + Tensor1_Expr iterB; + + public: + Riemann_times_Tensor1_2(const Riemann_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, 0, N3) * iterB(0) + iterA(N1, N2, 1, N3) * iterB(1) + + iterA(N1, N2, 2, N3) * iterB(2); + } + }; + + template + Tensor3_antisymmetric_Expr< + Riemann_times_Tensor1_2, + typename promote::V, Dim, Dim, i, j, l> + operator*(const Riemann_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Riemann_times_Tensor1_2; + return Tensor3_antisymmetric_Expr::V, + Dim, Dim, i, j, l>(TensorExpr(a, b)); + } + + /* B(k)*A(i,j,k,l) */ + + template + Tensor3_antisymmetric_Expr< + Riemann_times_Tensor1_2, + typename promote::V, Dim, Dim, i, j, l> + operator*(const Tensor1_Expr &b, + const Riemann_Expr &a) + { + using TensorExpr = Riemann_times_Tensor1_2; + return Tensor3_antisymmetric_Expr::V, + Dim, Dim, i, j, l>(TensorExpr(a, b)); + } + + /* A(i,j,k,l)*B(l) */ + + template + class Riemann_times_Tensor1_3 + { + Riemann_Expr iterA; + Tensor1_Expr iterB; + + public: + Riemann_times_Tensor1_3(const Riemann_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3, 0) * iterB(0) + iterA(N1, N2, N3, 1) * iterB(1) + + iterA(N1, N2, N3, 2) * iterB(2); + } + }; + + template + Tensor3_antisymmetric_Expr< + Riemann_times_Tensor1_3, + typename promote::V, Dim, Dim, i, j, k> + operator*(const Riemann_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Riemann_times_Tensor1_3; + return Tensor3_antisymmetric_Expr::V, + Dim, Dim, i, j, k>(TensorExpr(a, b)); + } + + /* B(l)*A(i,j,k,l) */ + + template + Tensor3_antisymmetric_Expr< + Riemann_times_Tensor1_3, + typename promote::V, Dim, Dim, i, j, k> + operator*(const Tensor1_Expr &b, + const Riemann_Expr &a) + { + using TensorExpr = Riemann_times_Tensor1_3; + return Tensor3_antisymmetric_Expr::V, + Dim, Dim, i, j, k>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Tensor2_symmetric.hpp new file mode 100644 index 000000000..374332c19 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Tensor2_symmetric.hpp @@ -0,0 +1,67 @@ +/* This file has all of the declarations for expressions like + Riemann*Tensor2_symmetric and + Tensor2_symmetric*Riemann, yielding a Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(i,k) */ + + template + class Riemann_times_Tensor2_symmetric_0 + { + Riemann_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + Riemann_times_Tensor2_symmetric_0( + const Riemann_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(0, N1, 0, N2) * iterB(0, 0) + + iterA(0, N1, 1, N2) * iterB(0, 1) + + iterA(0, N1, 2, N2) * iterB(0, 2) + + iterA(1, N1, 0, N2) * iterB(1, 0) + + iterA(1, N1, 1, N2) * iterB(1, 1) + + iterA(1, N1, 2, N2) * iterB(1, 2) + + iterA(2, N1, 0, N2) * iterB(2, 0) + + iterA(2, N1, 1, N2) * iterB(2, 1) + + iterA(2, N1, 2, N2) * iterB(2, 2); + } + }; + + template + Tensor2_symmetric_Expr< + Riemann_times_Tensor2_symmetric_0, + typename promote::V, Dim, j, l> + operator*(const Riemann_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Riemann_times_Tensor2_symmetric_0; + return Tensor2_symmetric_Expr::V, Dim, + j, l>(TensorExpr(a, b)); + } + + /* B(i,k)*A(i,j,k,l) */ + + template + Tensor2_symmetric_Expr< + Riemann_times_Tensor2_symmetric_0, + typename promote::V, Dim, j, l> + operator*(const Tensor2_symmetric_Expr &b, + const Riemann_Expr &a) + { + using TensorExpr + = Riemann_times_Tensor2_symmetric_0; + return Tensor2_symmetric_Expr::V, Dim, + j, l>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Tensor4.hpp b/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Tensor4.hpp new file mode 100644 index 000000000..5d8c38e83 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Riemann/Riemann_times_Tensor4.hpp @@ -0,0 +1,97 @@ +/* This file has the declaration for Riemann*Tensor4 yielding + a double. I simplify the expression by removing the identically + zero components of Riemann. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(i,j,k,l) */ + + template + double operator*(const Riemann_Expr &a, + const Tensor4_Expr &b) + { + return a(1, 0, 0, 1) * b(1, 0, 0, 1) + a(2, 0, 0, 1) * b(2, 0, 0, 1) + + a(0, 1, 0, 1) * b(0, 1, 0, 1) + a(2, 1, 0, 1) * b(2, 1, 0, 1) + + a(0, 2, 0, 1) * b(0, 2, 0, 1) + a(1, 2, 0, 1) * b(1, 2, 0, 1) + + a(1, 0, 0, 2) * b(1, 0, 0, 2) + a(2, 0, 0, 2) * b(2, 0, 0, 2) + + a(0, 1, 0, 2) * b(0, 1, 0, 2) + a(2, 1, 0, 2) * b(2, 1, 0, 2) + + a(0, 2, 0, 2) * b(0, 2, 0, 2) + a(1, 2, 0, 2) * b(1, 2, 0, 2) + + a(1, 0, 1, 0) * b(1, 0, 1, 0) + a(2, 0, 1, 0) * b(2, 0, 1, 0) + + a(0, 1, 1, 0) * b(0, 1, 1, 0) + a(2, 1, 1, 0) * b(2, 1, 1, 0) + + a(0, 2, 1, 0) * b(0, 2, 1, 0) + a(1, 2, 1, 0) * b(1, 2, 1, 0) + + a(1, 0, 1, 2) * b(1, 0, 1, 2) + a(2, 0, 1, 2) * b(2, 0, 1, 2) + + a(0, 1, 1, 2) * b(0, 1, 1, 2) + a(2, 1, 1, 2) * b(2, 1, 1, 2) + + a(0, 2, 1, 2) * b(0, 2, 1, 2) + a(1, 2, 1, 2) * b(1, 2, 1, 2) + + a(1, 0, 2, 0) * b(1, 0, 2, 0) + a(2, 0, 2, 0) * b(2, 0, 2, 0) + + a(0, 1, 2, 0) * b(0, 1, 2, 0) + a(2, 1, 2, 0) * b(2, 1, 2, 0) + + a(0, 2, 2, 0) * b(0, 2, 2, 0) + a(1, 2, 2, 0) * b(1, 2, 2, 0) + + a(1, 0, 2, 1) * b(1, 0, 2, 1) + a(2, 0, 2, 1) * b(2, 0, 2, 1) + + a(0, 1, 2, 1) * b(0, 1, 2, 1) + a(2, 1, 2, 1) * b(2, 1, 2, 1) + + a(0, 2, 2, 1) * b(0, 2, 2, 1) + a(1, 2, 2, 1) * b(1, 2, 2, 1); + + // return a(0,0,0,0)*b(0,0,0,0) + a(1,0,0,0)*b(1,0,0,0) + + // a(2,0,0,0)*b(2,0,0,0) + // + a(0,1,0,0)*b(0,1,0,0) + a(1,1,0,0)*b(1,1,0,0) + + // a(2,1,0,0)*b(2,1,0,0) + // + a(0,2,0,0)*b(0,2,0,0) + a(1,2,0,0)*b(1,2,0,0) + + // a(2,2,0,0)*b(2,2,0,0) + // + a(0,0,0,1)*b(0,0,0,1) + a(1,0,0,1)*b(1,0,0,1) + + // a(2,0,0,1)*b(2,0,0,1) + // + a(0,1,0,1)*b(0,1,0,1) + a(1,1,0,1)*b(1,1,0,1) + + // a(2,1,0,1)*b(2,1,0,1) + // + a(0,2,0,1)*b(0,2,0,1) + a(1,2,0,1)*b(1,2,0,1) + + // a(2,2,0,1)*b(2,2,0,1) + // + a(0,0,0,2)*b(0,0,0,2) + a(1,0,0,2)*b(1,0,0,2) + + // a(2,0,0,2)*b(2,0,0,2) + // + a(0,1,0,2)*b(0,1,0,2) + a(1,1,0,2)*b(1,1,0,2) + + // a(2,1,0,2)*b(2,1,0,2) + // + a(0,2,0,2)*b(0,2,0,2) + a(1,2,0,2)*b(1,2,0,2) + + // a(2,2,0,2)*b(2,2,0,2) + // + a(0,0,1,0)*b(0,0,1,0) + a(1,0,1,0)*b(1,0,1,0) + + // a(2,0,1,0)*b(2,0,1,0) + // + a(0,1,1,0)*b(0,1,1,0) + a(1,1,1,0)*b(1,1,1,0) + + // a(2,1,1,0)*b(2,1,1,0) + // + a(0,2,1,0)*b(0,2,1,0) + a(1,2,1,0)*b(1,2,1,0) + + // a(2,2,1,0)*b(2,2,1,0) + // + a(0,0,1,1)*b(0,0,1,1) + a(1,0,1,1)*b(1,0,1,1) + + // a(2,0,1,1)*b(2,0,1,1) + // + a(0,1,1,1)*b(0,1,1,1) + a(1,1,1,1)*b(1,1,1,1) + + // a(2,1,1,1)*b(2,1,1,1) + // + a(0,2,1,1)*b(0,2,1,1) + a(1,2,1,1)*b(1,2,1,1) + + // a(2,2,1,1)*b(2,2,1,1) + // + a(0,0,1,2)*b(0,0,1,2) + a(1,0,1,2)*b(1,0,1,2) + + // a(2,0,1,2)*b(2,0,1,2) + // + a(0,1,1,2)*b(0,1,1,2) + a(1,1,1,2)*b(1,1,1,2) + + // a(2,1,1,2)*b(2,1,1,2) + // + a(0,2,1,2)*b(0,2,1,2) + a(1,2,1,2)*b(1,2,1,2) + + // a(2,2,1,2)*b(2,2,1,2) + // + a(0,0,2,0)*b(0,0,2,0) + a(1,0,2,0)*b(1,0,2,0) + + // a(2,0,2,0)*b(2,0,2,0) + // + a(0,1,2,0)*b(0,1,2,0) + a(1,1,2,0)*b(1,1,2,0) + + // a(2,1,2,0)*b(2,1,2,0) + // + a(0,2,2,0)*b(0,2,2,0) + a(1,2,2,0)*b(1,2,2,0) + + // a(2,2,2,0)*b(2,2,2,0) + // + a(0,0,2,1)*b(0,0,2,1) + a(1,0,2,1)*b(1,0,2,1) + + // a(2,0,2,1)*b(2,0,2,1) + // + a(0,1,2,1)*b(0,1,2,1) + a(1,1,2,1)*b(1,1,2,1) + + // a(2,1,2,1)*b(2,1,2,1) + // + a(0,2,2,1)*b(0,2,2,1) + a(1,2,2,1)*b(1,2,2,1) + + // a(2,2,2,1)*b(2,2,2,1) + // + a(0,0,2,2)*b(0,0,2,2) + a(1,0,2,2)*b(1,0,2,2) + + // a(2,0,2,2)*b(2,0,2,2) + // + a(0,1,2,2)*b(0,1,2,2) + a(1,1,2,2)*b(1,1,2,2) + + // a(2,1,2,2)*b(2,1,2,2) + // + a(0,2,2,2)*b(0,2,2,2) + a(1,2,2,2)*b(1,2,2,2) + + // a(2,2,2,2)*b(2,2,2,2); + } + + template + double operator*(const Tensor4_Expr &b, + const Riemann_Expr &a) + + { + return operator*(a, b); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor0.hpp b/src/oofemlib/tensor/FTensor/Tensor0.hpp new file mode 100644 index 000000000..56aae2942 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor0.hpp @@ -0,0 +1,79 @@ +/* A Tensor0 class that really just ends up being an alias for a + pointer to a templated type T. Note that the T * is mutable, so the + pointer can change, allowing iterating over a array. Also note + that diffusion and interpolate are included at the end of this + file, because it needs the full definition of Tensor0. */ + +#pragma once + +#include "Tensor0/dTensor0.hpp" +#include "Tensor0/d_boundary_Tensor0.hpp" +#include "Tensor0/ddTensor0.hpp" +#include "Tensor0/dd_boundary_Tensor0.hpp" + +namespace FTensor +{ + template class Tensor0 + {}; + + template class Tensor0 + { + mutable T *__restrict data; + + public: + Tensor0(T *d) : data(d) {} + + const Tensor0 &operator=(const Tensor0 &a) + { + *data = *(a.data); + return *this; + } + + template const Tensor0 &operator=(const U &d) + { + *data = d; + return *this; + } + template const Tensor0 &operator+=(const U &d) + { + *data += d; + return *this; + } + template const Tensor0 &operator-=(const U &d) + { + *data -= d; + return *this; + } + template const Tensor0 &operator*=(const U &d) + { + *data *= d; + return *this; + } + template const Tensor0 &operator/=(const U &d) + { + *data /= d; + return *this; + } + + /* Note that the conversion operator& to T * only works on + consts, so it doesn't allow you to change the value of *data. + You have to use the = operators to change that. The idea is that + operator& is only used for stencils and such. */ + + const T *operator&() const { return data; } + operator T() const { return *data; } + + /* The ++ operator increments the pointer, not the number that the + pointer points to. This allows iterating over a grid. */ + + const Tensor0 &operator++() const + { + ++data; + return *this; + } + }; +} + +#include "Tensor0/d_one_sided_Tensor0.hpp" +#include "Tensor0/diffusion_Tensor0.hpp" +#include "Tensor0/interpolate_Tensor0.hpp" diff --git a/src/oofemlib/tensor/FTensor/Tensor0/dTensor0.hpp b/src/oofemlib/tensor/FTensor/Tensor0/dTensor0.hpp new file mode 100644 index 000000000..287d6c239 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor0/dTensor0.hpp @@ -0,0 +1,34 @@ +/* Takes a derivative of a Tensor0 yielding a Tensor1. */ + +#pragma once + +namespace FTensor +{ + template class dTensor0 + { + const Tensor0 &a; + const Tensor1 &d_ijk; + const Tensor1 &d_xyz; + + public: + typename promote::V operator()(const int N) const + { + return (*(&a + d_ijk(N)) - *(&a - d_ijk(N))) * d_xyz(N) * 0.5; + } + dTensor0(const Tensor0 &A, const Tensor1 &D_ijk, + const Tensor1 &D_xyz) + : a(A), d_ijk(D_ijk), d_xyz(D_xyz) + {} + }; + + template + const Tensor1_Expr, typename promote::V, + Dim, i> + d(const Tensor0 &a, const Index index, + const Tensor1 &d_ijk, const Tensor1 &d_xyz) + { + using Tensor_Expr = dTensor0; + return Tensor1_Expr::V, Dim, i>( + Tensor_Expr(a, d_ijk, d_xyz)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor0/d_boundary_Tensor0.hpp b/src/oofemlib/tensor/FTensor/Tensor0/d_boundary_Tensor0.hpp new file mode 100644 index 000000000..1c3928df0 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor0/d_boundary_Tensor0.hpp @@ -0,0 +1,43 @@ +/* Takes a derivative of a Tensor0 yielding a Tensor1. It checks + whether we're at a boundary, and takes a one-sided derivative + there. */ + +#pragma once + +namespace FTensor +{ + template class d_boundary_Tensor0 + { + const Tensor0 &a; + const Tensor1 &d_ijk; + const Tensor1 &d_xyz; + const Tensor2 &boundary; + + public: + typename promote::V operator()(const int N) const + { + return boundary(N, 0) + ? (*(&a + d_ijk(N)) - a) * d_xyz(N) + : (boundary(N, 1) + ? (a - *(&a - d_ijk(N))) * d_xyz(N) + : (*(&a + d_ijk(N)) - *(&a - d_ijk(N))) * d_xyz(N) * 0.5); + } + d_boundary_Tensor0(const Tensor0 &A, const Tensor1 &D_ijk, + const Tensor1 &D_xyz, + const Tensor2 &Boundary) + : a(A), d_ijk(D_ijk), d_xyz(D_xyz), boundary(Boundary) + {} + }; + + template + const Tensor1_Expr, + typename promote::V, Dim, i> + d_boundary(const Tensor0 &a, const Index index, + const Tensor1 &d_ijk, const Tensor1 &d_xyz, + const Tensor2 &boundary) + { + using Tensor_Expr = d_boundary_Tensor0; + return Tensor1_Expr::V, Dim, i>( + Tensor_Expr(a, d_ijk, d_xyz, boundary)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor0/d_one_sided_Tensor0.hpp b/src/oofemlib/tensor/FTensor/Tensor0/d_one_sided_Tensor0.hpp new file mode 100644 index 000000000..ef0568242 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor0/d_one_sided_Tensor0.hpp @@ -0,0 +1,34 @@ +/* Takes a one-sided derivative of a Tensor0 in a particular + direction, yielding a typename promote::V. */ + +#pragma once + +namespace FTensor +{ + template + typename promote::V + d_one_sided(const Tensor0 &a, const Number<0> n1, const int &di, + const int &dj, const int &dk, const double &dx, const double &dy, + const double &dz) + { + return (a - *(&a - di)) * dx; + } + + template + typename promote::V + d_one_sided(const Tensor0 &a, const Number<1> n1, const int &di, + const int &dj, const int &dk, const double &dx, const double &dy, + const double &dz) + { + return (a - *(&a - dj)) * dy; + } + + template + typename promote::V + d_one_sided(const Tensor0 &a, const Number<2> n1, const int &di, + const int &dj, const int &dk, const double &dx, const double &dy, + const double &dz) + { + return (a - *(&a - dk)) * dz; + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor0/ddTensor0.hpp b/src/oofemlib/tensor/FTensor/Tensor0/ddTensor0.hpp new file mode 100644 index 000000000..8b5813fa4 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor0/ddTensor0.hpp @@ -0,0 +1,41 @@ +/* Takes a second derivative of a Tensor0 yielding a Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + template class ddTensor0 + { + const Tensor0 &a; + const Tensor1 &d_ijk; + const Tensor1 &d_xyz; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return N1 == N2 + ? (*(&a + d_ijk(N1)) - 2 * a + *(&a - d_ijk(N1))) * d_xyz(N1) + * d_xyz(N1) + : (*(&a + d_ijk(N1) + d_ijk(N2)) - *(&a - d_ijk(N1) + d_ijk(N2)) + - *(&a + d_ijk(N1) - d_ijk(N2)) + + *(&a - d_ijk(N1) - d_ijk(N2))) + * d_xyz(N1) * d_xyz(N2) * 0.25; + } + ddTensor0(const Tensor0 &A, const Tensor1 &D_ijk, + const Tensor1 &D_xyz) + : a(A), d_ijk(D_ijk), d_xyz(D_xyz) + {} + }; + + template + const Tensor2_symmetric_Expr, + typename promote::V, Dim, i, j> + dd(const Tensor0 &a, const Index index1, + const Index index2, const Tensor1 &d_ijk, + const Tensor1 &d_xyz) + { + using Tensor_Expr = ddTensor0; + return Tensor2_symmetric_Expr::V, + Dim, i, j>(Tensor_Expr(a, d_ijk, d_xyz)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor0/dd_boundary_Tensor0.hpp b/src/oofemlib/tensor/FTensor/Tensor0/dd_boundary_Tensor0.hpp new file mode 100644 index 000000000..9617d427f --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor0/dd_boundary_Tensor0.hpp @@ -0,0 +1,91 @@ +/* Takes a second derivative of a Tensor0 yielding a Tensor1. + This is primarily useful at boundaries, where you have to take + one-sided derivatives. */ + +#pragma once + +namespace FTensor +{ + template class dd_boundary_Tensor0 + { + const Tensor0 &a; + const Tensor1 &d_ijk; + const Tensor1 &d_xyz; + const Tensor2 &boundary; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return N1 == N2 + ? (boundary(N1, 0) + ? (*(&a + 2 * d_ijk(N1)) - 2 * *(&a + d_ijk(N1)) + a) + : (boundary(N1, 1) + ? (a - 2 * *(&a - d_ijk(N1)) + *(&a - 2 * d_ijk(N1))) + : (*(&a + d_ijk(N1)) - 2 * a + *(&a - d_ijk(N1))))) + * d_xyz(N1) * d_xyz(N1) + : (boundary(N1, 0) + ? (boundary(N2, 0) + ? ((*(&a + d_ijk(N1) + d_ijk(N2)) - *(&a + d_ijk(N2)) + - *(&a + d_ijk(N1)) + a) + * d_xyz(N1) * d_xyz(N2)) + : (boundary(N2, 1) ? ((*(&a + d_ijk(N1)) - a + - *(&a + d_ijk(N1) - d_ijk(N2)) + + *(&a - d_ijk(N2))) + * d_xyz(N1) * d_xyz(N2)) + : (*(&a + d_ijk(N1) + d_ijk(N2)) + - *(&a + d_ijk(N2)) + - *(&a + d_ijk(N1) - d_ijk(N2)) + + *(&a - d_ijk(N2))) + * d_xyz(N1) * d_xyz(N2) * 0.5)) + : (boundary(N1, 1) + ? (boundary(N2, 0) + ? ((*(&a + d_ijk(N2)) + - *(&a - d_ijk(N1) + d_ijk(N2)) - a + + *(&a - d_ijk(N1))) + * d_xyz(N1) * d_xyz(N2)) + : (boundary(N2, 1) + ? ((a - *(&a - d_ijk(N1)) - *(&a - d_ijk(N2)) + + *(&a - d_ijk(N1) - d_ijk(N2))) + * d_xyz(N1) * d_xyz(N2)) + : (*(&a + d_ijk(N2)) + - *(&a - d_ijk(N1) + d_ijk(N2)) + - *(&a - d_ijk(N2)) + + *(&a - d_ijk(N1) - d_ijk(N2))) + * d_xyz(N1) * d_xyz(N2) * 0.5)) + : (boundary(N2, 0) + ? ((*(&a + d_ijk(N1) + d_ijk(N2)) + - *(&a - d_ijk(N1) + d_ijk(N2)) + - *(&a + d_ijk(N1)) + *(&a - d_ijk(N1))) + * d_xyz(N1) * d_xyz(N2) * 0.5) + : (boundary(N2, 1) + ? ((*(&a + d_ijk(N1)) - *(&a - d_ijk(N1)) + - *(&a + d_ijk(N1) - d_ijk(N2)) + + *(&a - d_ijk(N1) - d_ijk(N2))) + * d_xyz(N1) * d_xyz(N2) * 0.5) + : ((*(&a + d_ijk(N1) + d_ijk(N2)) + - *(&a - d_ijk(N1) + d_ijk(N2)) + - *(&a + d_ijk(N1) - d_ijk(N2)) + + *(&a - d_ijk(N1) - d_ijk(N2))) + * d_xyz(N1) * d_xyz(N2) * 0.25))))); + } + dd_boundary_Tensor0(const Tensor0 &A, const Tensor1 &D_ijk, + const Tensor1 &D_xyz, + const Tensor2 &Boundary) + : a(A), d_ijk(D_ijk), d_xyz(D_xyz), boundary(Boundary) + {} + }; + + template + const Tensor2_symmetric_Expr, + typename promote::V, Dim, i, j> + dd_boundary(const Tensor0 &a, const Index index3, + const Index index4, const Tensor1 &d_ijk, + const Tensor1 &d_xyz, + const Tensor2 &boundary) + { + using Tensor_Expr = dd_boundary_Tensor0; + return Tensor2_symmetric_Expr::V, + Dim, i, j>( + Tensor_Expr(a, d_ijk, d_xyz, boundary)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor0/diffusion_Tensor0.hpp b/src/oofemlib/tensor/FTensor/Tensor0/diffusion_Tensor0.hpp new file mode 100644 index 000000000..2f9cd7810 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor0/diffusion_Tensor0.hpp @@ -0,0 +1,25 @@ +/* Computes 2*del^2 of a Tensor0_ptr but uses diagonal derivatives for + half of it. */ + +#pragma once + +namespace FTensor +{ + template + typename promote::V + diffusion(const Tensor0 &a, const int &di, const int &dj, const int &dk, + const double &dx) + { + return ((*(&a + di) - 2 * a + *(&a - di)) + + (*(&a + dj) - 2 * a + *(&a - dj)) + + (*(&a + dk) - 2 * a + *(&a - dk)) + + ((*(&a + di + dj) + *(&a + di - dj) + *(&a - di + dj) + + *(&a - di - dj) - 4 * a) + + (*(&a + di + dk) + *(&a + di - dk) + *(&a - di + dk) + + *(&a - di - dk) - 4 * a) + + (*(&a + dj + dk) + *(&a + dj - dk) + *(&a - dj + dk) + + *(&a - dj - dk) - 4 * a)) + / (std::sqrt(2.0))) + * dx * dx; + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor0/interpolate_Tensor0.hpp b/src/oofemlib/tensor/FTensor/Tensor0/interpolate_Tensor0.hpp new file mode 100644 index 000000000..ac1f825b9 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor0/interpolate_Tensor0.hpp @@ -0,0 +1,34 @@ +/* Interpolates to (i0+distance[0], j0+distance[1], k0+distance[2]), + yielding a double. (i0,j0,k0) are 3D array coordinates, + conjugate==1-distance, and (di,dj,dk) are the stride of the array + coordinates. It is assumed that the Tensor0_ptr is zero + centered. */ + +#pragma once + +namespace FTensor +{ + template + typename promote::V + interpolate(const Tensor0 &a, const int &di, const int &dj, + const int &dk, const int &i0, const int &j0, const int &k0, + const double distance[3], const double conjugate[3]) + { + return conjugate[0] * conjugate[1] * conjugate[2] + * (*(&a + di * i0 + dj * j0 + dk * k0)) + + distance[0] * conjugate[1] * conjugate[2] + * (*(&a + di * (i0 + 1) + dj * (j0) + dk * (k0))) + + conjugate[0] * distance[1] * conjugate[2] + * (*(&a + di * (i0) + dj * (j0 + 1) + dk * (k0))) + + distance[0] * distance[1] * conjugate[2] + * (*(&a + di * (i0 + 1) + dj * (j0 + 1) + dk * (k0))) + + conjugate[0] * conjugate[1] * distance[2] + * (*(&a + di * (i0) + dj * (j0) + dk * (k0 + 1))) + + distance[0] * conjugate[1] * distance[2] + * (*(&a + di * (i0 + 1) + dj * (j0) + dk * (k0 + 1))) + + conjugate[0] * distance[1] * distance[2] + * (*(&a + di * (i0) + dj * (j0 + 1) + dk * (k0 + 1))) + + distance[0] * distance[1] * distance[2] + * (*(&a + di * (i0 + 1) + dj * (j0 + 1) + dk * (k0 + 1))); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1.hpp new file mode 100644 index 000000000..3efda3b82 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1.hpp @@ -0,0 +1,6 @@ +/* Declarations for Tensor1. */ + +#include "Tensor1/Tensor1_pointer.hpp" +#include "Tensor1/Tensor1_value.hpp" + +#include "Tensor1/Tensor1_Expr.hpp" diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_Expr.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_Expr.hpp new file mode 100644 index 000000000..a2125eda8 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_Expr.hpp @@ -0,0 +1,257 @@ +/* Declares a wrapper class for rank 1 Tensor expressions. Note that + Tensor1_Expr_equals is included at the end, since it needs the + definition of the class in order to compile. */ + +#pragma once + +#include "Tensor1_and_Tensor1.hpp" +#include "Tensor1_carat_Tensor1.hpp" +#include "Tensor1_divide_generic.hpp" +#include "Tensor1_minus_Tensor1.hpp" +#include "Tensor1_minus_generic.hpp" +#include "Tensor1_or_Tensor1.hpp" +#include "Tensor1_plus_Tensor1.hpp" +#include "Tensor1_plus_generic.hpp" +#include "Tensor1_times_Tensor1.hpp" +#include "Tensor1_times_generic.hpp" +#include "dTensor1.hpp" +#include "d_one_sided_Tensor1.hpp" +#include "ddTensor1.hpp" +#include "diffusion_Tensor1.hpp" +#include "generic_minus_Tensor1.hpp" +#include "interpolate_Tensor1.hpp" +#include "minus_Tensor1.hpp" + +namespace FTensor +{ + template class Tensor1_Expr + { + A iter; + + public: + Tensor1_Expr(const A &a) : iter(a) {} + T operator()(const int N) const { return iter(N); } + }; + + template + class Tensor1_Expr, T, Dim, i> + { + Tensor1 &iter; + + public: + Tensor1_Expr(Tensor1 &a) : iter(a) {} + + T &operator()(const int N) { return iter(N); } + T operator()(const int N) const { return iter(N); } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + const Tensor1_Expr, T, Dim, i> & + operator=(const Tensor1_Expr &result); + + const Tensor1_Expr, T, Dim, i> & + operator=(const Tensor1_Expr, T, Dim, i> &result); + + template + const Tensor1_Expr, T, Dim, i> & + operator+=(const Tensor1_Expr &result); + + template + const Tensor1_Expr, T, Dim, i> & + operator-=(const Tensor1_Expr &result); + + /* General template assignment operators intended mostly for + doubles (type T), but could be applied to anything you want, like + complex, etc. All that is required is that T=B works (or T+=B, + etc.) */ + + template + const Tensor1_Expr, T, Dim, i> & + operator=(const B &d); + template + const Tensor1_Expr, T, Dim, i> & + operator+=(const B &d); + template + const Tensor1_Expr, T, Dim, i> & + operator-=(const B &d); + template + const Tensor1_Expr, T, Dim, i> & + operator*=(const B &d); + template + const Tensor1_Expr, T, Dim, i> & + operator/=(const B &d); + }; + + /* Specialized for Tensor2_number_rhs_0 (Tensor2{_symmetric} with the + first index explicitly given). */ + + template + class Tensor1_Expr, T, Dim1, i> + { + A &iter; + + public: + Tensor1_Expr(A &a) : iter(a) {} + T &operator()(const int N1) { return iter(N, N1); } + T operator()(const int N1) const { return iter(N, N1); } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + const Tensor1_Expr, T, Dim1, i> & + operator=(const Tensor1_Expr &result); + + const Tensor1_Expr, T, Dim1, i> &operator=( + const Tensor1_Expr, T, Dim1, i> &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator+=(const Tensor1_Expr &result); + + const Tensor1_Expr, T, Dim1, i> &operator+=( + const Tensor1_Expr, T, Dim1, i> &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator-=(const Tensor1_Expr &result); + + const Tensor1_Expr, T, Dim1, i> &operator-=( + const Tensor1_Expr, T, Dim1, i> &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator=(const B &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator+=(const B &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator-=(const B &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator*=(const B &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator/=(const B &result); + }; + + /* Specialized for Tensor2_number_rhs_1 (Tensor2{_symmetric} with the + second index explicitly given). */ + + template + class Tensor1_Expr, T, Dim1, i> + { + A &iter; + + public: + Tensor1_Expr(A &a) : iter(a) {} + T &operator()(const int N1) { return iter(N1, N); } + T operator()(const int N1) const { return iter(N1, N); } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + const Tensor1_Expr, T, Dim1, i> & + operator=(const Tensor1_Expr &result); + + const Tensor1_Expr, T, Dim1, i> &operator=( + const Tensor1_Expr, T, Dim1, i> &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator+=(const Tensor1_Expr &result); + + const Tensor1_Expr, T, Dim1, i> &operator+=( + const Tensor1_Expr, T, Dim1, i> &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator-=(const Tensor1_Expr &result); + + const Tensor1_Expr, T, Dim1, i> &operator-=( + const Tensor1_Expr, T, Dim1, i> &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator=(const B &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator+=(const B &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator-=(const B &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator*=(const B &result); + + template + const Tensor1_Expr, T, Dim1, i> & + operator/=(const B &result); + }; + + /* Specialized for Dg_number_rhs_12 (A Dg with + explicit numbers in the (first or second) and third slots). */ + + template + class Tensor1_Expr, T, Dim, i> + { + A &iter; + + public: + Tensor1_Expr(A &a) : iter(a) {} + T &operator()(const int N) { return iter(N, N1, N2); } + T operator()(const int N) const { return iter(N, N1, N2); } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + const Tensor1_Expr, T, Dim, i> & + operator=(const Tensor1_Expr &result); + + const Tensor1_Expr, T, Dim, i> &operator=( + const Tensor1_Expr, T, Dim, i> &result); + }; + + /* Specialized for Dg_number_rhs_01 (A Dg with + explicit numbers in the first and second slots). */ + + template + class Tensor1_Expr, T, Dim, i> + { + A &iter; + + public: + Tensor1_Expr(A &a) : iter(a) {} + T &operator()(const int N) { return iter(N1, N2, N); } + T operator()(const int N) const { return iter(N1, N2, N); } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + const Tensor1_Expr, T, Dim, i> & + operator=(const Tensor1_Expr &result); + + const Tensor1_Expr, T, Dim, i> &operator=( + const Tensor1_Expr, T, Dim, i> &result); + }; +} + +#include "Tensor1_Expr_equals.hpp" diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_Expr_equals.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_Expr_equals.hpp new file mode 100644 index 000000000..f83a9a12a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_Expr_equals.hpp @@ -0,0 +1,798 @@ +/* Various assignment operators for generic Tensor1_Expr's as well as + specializations for Tensor2_number_rhs's. I have to explicitly + declare the second operator= because otherwise the compiler will + generate its own and not use the template code. */ + +/* =T1_Expr */ + +#pragma once + +namespace FTensor +{ + template + void T1_equals_T1(A &iter, const Tensor1_Expr result, + const Number &) + { + iter(Current_Dim - 1) = result(Current_Dim - 1); + T1_equals_T1(iter, result, Number()); + } + + template + void T1_equals_T1(A &iter, const Tensor1_Expr result, + const Number<1> &) + { + iter(0) = result(0); + } + + template + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>:: + operator=(const Tensor1_Expr &result) + { + T1_equals_T1(iter, result, Number()); + return *this; + } + + /* =T1_Expr(T1) */ + + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>:: + operator=(const Tensor1_Expr, T, Dim, i> &result) + { + return operator=, T>(result); + } + + /* +=T1 */ + + template + void T1_plus_equals_T1(A &iter, const Tensor1_Expr result, + const Number &) + { + iter(Current_Dim - 1) += result(Current_Dim - 1); + T1_plus_equals_T1(iter, result, Number()); + } + + template + void T1_plus_equals_T1(A &iter, const Tensor1_Expr result, + const Number<1> &) + { + iter(0) += result(0); + } + + template + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>:: + operator+=(const Tensor1_Expr &result) + { + T1_plus_equals_T1(iter, result, Number()); + return *this; + } + + /* -=T1 */ + + template + void T1_minus_equals_T1(A &iter, const Tensor1_Expr result, + const Number &) + { + iter(Current_Dim - 1) -= result(Current_Dim - 1); + T1_minus_equals_T1(iter, result, Number()); + } + + template + void T1_minus_equals_T1(A &iter, const Tensor1_Expr result, + const Number<1> &) + { + iter(0) -= result(0); + } + + template + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>:: + operator-=(const Tensor1_Expr &result) + { + T1_minus_equals_T1(iter, result, Number()); + return *this; + } + + /* General template assignment operators intended mostly for + doubles (type U), but could be applied to anything you want, like + complex, etc. All that is required is that T=U works (or T+=U, + etc.) */ + + /* =U */ + + template + void T1_equals_generic(A &iter, const U &u, const Number &) + { + iter(Current_Dim - 1) = u; + T1_equals_generic(iter, u, Number()); + } + + template + void T1_equals_generic(A &iter, const U &u, const Number<1> &) + { + iter(0) = u; + } + + template + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>::operator=(const U &u) + { + T1_equals_generic(iter, u, Number()); + return *this; + } + + /* +=U */ + + template + void T1_plus_equals_generic(A &iter, const U &u, const Number &) + { + iter(Current_Dim - 1) += u; + T1_plus_equals_generic(iter, u, Number()); + } + + template + void T1_plus_equals_generic(A &iter, const U &u, const Number<1> &) + { + iter(0) += u; + } + + template + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>::operator+=(const U &u) + { + T1_plus_equals_generic(iter, u, Number()); + return *this; + } + + /* -=U */ + + template + void + T1_minus_equals_generic(A &iter, const U &u, const Number &) + { + iter(Current_Dim - 1) -= u; + T1_minus_equals_generic(iter, u, Number()); + } + + template + void T1_minus_equals_generic(A &iter, const U &u, const Number<1> &) + { + iter(0) -= u; + } + + template + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>::operator-=(const U &u) + { + T1_minus_equals_generic(iter, u, Number()); + return *this; + } + + /* *=U */ + + template + void + T1_times_equals_generic(A &iter, const U &u, const Number &) + { + iter(Current_Dim - 1) *= u; + T1_times_equals_generic(iter, u, Number()); + } + + template + void T1_times_equals_generic(A &iter, const U &u, const Number<1> &) + { + iter(0) *= u; + } + + template + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>::operator*=(const U &u) + { + T1_times_equals_generic(iter, u, Number()); + return *this; + } + + /* /=U */ + + template + void + T1_divide_equals_generic(A &iter, const U &u, const Number &) + { + iter(Current_Dim - 1) /= u; + T1_divide_equals_generic(iter, u, Number()); + } + + template + void T1_divide_equals_generic(A &iter, const U &u, const Number<1> &) + { + iter(0) /= u; + } + + template + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>::operator/=(const U &u) + { + T1_divide_equals_generic(iter, u, Number()); + return *this; + } + + /* Specializations for Tensor2_number_rhs_0's */ + + /* =T1 */ + + template + void T2rhs0_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &N1, const Number &) + { + iter(N, Current_Dim - 1) = result(Current_Dim - 1); + T2rhs0_equals_T1(iter, result, N1, Number()); + } + + template + void T2rhs0_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &, const Number<1> &) + { + iter(N, 0) = result(0); + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator=(const Tensor1_Expr &result) + { + T2rhs0_equals_T1(iter, result, Number(), Number()); + return *this; + } + + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>::operator=( + const Tensor1_Expr, T, Dim1, i> &result) + { + return operator=, T>(result); + } + + /* +=T1 */ + + template + void + T2rhs0_plus_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &N1, const Number &) + { + iter(N, Current_Dim - 1) += result(Current_Dim - 1); + T2rhs0_plus_equals_T1(iter, result, N1, Number()); + } + + template + void + T2rhs0_plus_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &, const Number<1> &) + { + iter(N, 0) += result(0); + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator+=(const Tensor1_Expr &result) + { + T2rhs0_plus_equals_T1(iter, result, Number(), Number()); + return *this; + } + + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>::operator+=( + const Tensor1_Expr, T, Dim1, i> &result) + { + return operator+=, T>(result); + } + + /* -=T1 */ + + template + void + T2rhs0_minus_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &N1, const Number &) + { + iter(N, Current_Dim - 1) -= result(Current_Dim - 1); + T2rhs0_minus_equals_T1(iter, result, N1, Number()); + } + + template + void + T2rhs0_minus_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &, const Number<1> &) + { + iter(N, 0) -= result(0); + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator-=(const Tensor1_Expr &result) + { + T2rhs0_minus_equals_T1(iter, result, Number(), Number()); + return *this; + } + + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>::operator-=( + const Tensor1_Expr, T, Dim1, i> &result) + { + return operator-=, T>(result); + } + + /* =U */ + + template + void T2rhs0_equals_generic(A &iter, const U &u, const Number &N1, + const Number &) + { + iter(N, Current_Dim - 1) = u; + T2rhs0_equals_generic(iter, u, N1, Number()); + } + + template + void T2rhs0_equals_generic(A &iter, const U &u, const Number &, + const Number<1> &) + { + iter(N, 0) = u; + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator=(const U &u) + { + T2rhs0_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* +=U */ + + template + void T2rhs0_plus_equals_generic(A &iter, const U &u, const Number &N1, + const Number &) + { + iter(N, Current_Dim - 1) += u; + T2rhs0_plus_equals_generic(iter, u, N1, Number()); + } + + template + void T2rhs0_plus_equals_generic(A &iter, const U &u, const Number &, + const Number<1> &) + { + iter(N, 0) += u; + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator+=(const U &u) + { + T2rhs0_plus_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* -=U */ + + template + void T2rhs0_minus_equals_generic(A &iter, const U &u, const Number &N1, + const Number &) + { + iter(N, Current_Dim - 1) -= u; + T2rhs0_minus_equals_generic(iter, u, N1, Number()); + } + + template + void T2rhs0_minus_equals_generic(A &iter, const U &u, const Number &, + const Number<1> &) + { + iter(N, 0) -= u; + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator-=(const U &u) + { + T2rhs0_minus_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* *=U */ + + template + void T2rhs0_times_equals_generic(A &iter, const U &u, const Number &N1, + const Number &) + { + iter(N, Current_Dim - 1) *= u; + T2rhs0_times_equals_generic(iter, u, N1, Number()); + } + + template + void T2rhs0_times_equals_generic(A &iter, const U &u, const Number &, + const Number<1> &) + { + iter(N, 0) *= u; + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator*=(const U &u) + { + T2rhs0_times_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* /=U */ + + template + void T2rhs0_divide_equals_generic(A &iter, const U &u, const Number &N1, + const Number &) + { + iter(N, Current_Dim - 1) /= u; + T2rhs0_divide_equals_generic(iter, u, N1, Number()); + } + + template + void T2rhs0_divide_equals_generic(A &iter, const U &u, const Number &, + const Number<1> &) + { + iter(N, 0) /= u; + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator/=(const U &u) + { + T2rhs0_divide_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* Specializations for Tensor2_number_rhs_1's */ + + /* =T1 */ + + template + void T2rhs1_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &N1, const Number &) + { + iter(Current_Dim - 1, N) = result(Current_Dim - 1); + T2rhs1_equals_T1(iter, result, N1, Number()); + } + + template + void T2rhs1_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &, const Number<1> &) + { + iter(0, N) = result(0); + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator=(const Tensor1_Expr &result) + { + T2rhs1_equals_T1(iter, result, Number(), Number()); + return *this; + } + + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>::operator=( + const Tensor1_Expr, T, Dim1, i> &result) + { + return operator=, T>(result); + } + + /* +=T1 */ + + template + void + T2rhs1_plus_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &N1, const Number &) + { + iter(Current_Dim - 1, N) += result(Current_Dim - 1); + T2rhs1_plus_equals_T1(iter, result, N1, Number()); + } + + template + void + T2rhs1_plus_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &, const Number<1> &) + { + iter(0, N) += result(0); + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator+=(const Tensor1_Expr &result) + { + T2rhs1_plus_equals_T1(iter, result, Number(), Number()); + return *this; + } + + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>::operator+=( + const Tensor1_Expr, T, Dim1, i> &result) + { + return operator+=, T>(result); + } + + /* -=T1 */ + + template + void + T2rhs1_minus_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &N1, const Number &) + { + iter(Current_Dim - 1, N) -= result(Current_Dim - 1); + T2rhs1_minus_equals_T1(iter, result, N1, Number()); + } + + template + void + T2rhs1_minus_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &, const Number<1> &) + { + iter(0, N) -= result(0); + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator-=(const Tensor1_Expr &result) + { + T2rhs1_minus_equals_T1(iter, result, Number(), Number()); + return *this; + } + + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>::operator-=( + const Tensor1_Expr, T, Dim1, i> &result) + { + return operator-=, T>(result); + } + + /* =U */ + + template + void T2rhs1_equals_generic(A &iter, const U &u, const Number &N1, + const Number &) + { + iter(Current_Dim - 1, N) = u; + T2rhs1_equals_generic(iter, u, N1, Number()); + } + + template + void T2rhs1_equals_generic(A &iter, const U &u, const Number &, + const Number<1> &) + { + iter(0, N) = u; + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator=(const U &u) + { + T2rhs1_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* +=U */ + + template + void T2rhs1_plus_equals_generic(A &iter, const U &u, const Number &N1, + const Number &) + { + iter(Current_Dim - 1, N) += u; + T2rhs1_plus_equals_generic(iter, u, N1, Number()); + } + + template + void T2rhs1_plus_equals_generic(A &iter, const U &u, const Number &, + const Number<1> &) + { + iter(0, N) += u; + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator+=(const U &u) + { + T2rhs1_plus_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* -=U */ + + template + void T2rhs1_minus_equals_generic(A &iter, const U &u, const Number &N1, + const Number &) + { + iter(Current_Dim - 1, N) -= u; + T2rhs1_minus_equals_generic(iter, u, N1, Number()); + } + + template + void T2rhs1_minus_equals_generic(A &iter, const U &u, const Number &, + const Number<1> &) + { + iter(0, N) -= u; + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator-=(const U &u) + { + T2rhs1_minus_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* *=U */ + + template + void T2rhs1_times_equals_generic(A &iter, const U &u, const Number &N1, + const Number &) + { + iter(Current_Dim - 1, N) *= u; + T2rhs1_times_equals_generic(iter, u, N1, Number()); + } + + template + void T2rhs1_times_equals_generic(A &iter, const U &u, const Number &, + const Number<1> &) + { + iter(0, N) *= u; + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator*=(const U &u) + { + T2rhs1_times_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* /=U */ + + template + void T2rhs1_divide_equals_generic(A &iter, const U &u, const Number &N1, + const Number &) + { + iter(Current_Dim - 1, N) /= u; + T2rhs1_divide_equals_generic(iter, u, N1, Number()); + } + + template + void T2rhs1_divide_equals_generic(A &iter, const U &u, const Number &, + const Number<1> &) + { + iter(0, N) /= u; + } + + template + template + const Tensor1_Expr, T, Dim1, i> & + Tensor1_Expr, T, Dim1, i>:: + operator/=(const U &u) + { + T2rhs1_divide_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* Specializations for Dg_number_rhs_12's */ + + template + void T3dgrhs12_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &NN1, const Number &NN2, + const Number &) + { + iter(Current_Dim - 1, N1, N2) = result(Current_Dim - 1); + T3dgrhs12_equals_T1(iter, result, NN1, NN2, Number()); + } + + template + void T3dgrhs12_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &, const Number &, + const Number<1> &) + { + iter(0, N1, N2) = result(0); + } + + template + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>:: + operator=(const Tensor1_Expr &result) + { + T3dgrhs12_equals_T1(iter, result, Number(), Number(), + Number()); + return *this; + } + + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>::operator=( + const Tensor1_Expr, T, Dim, i> &result) + { + return operator=, T>(result); + } + + /* Specializations for Dg_number_rhs_01's */ + + template + void T3dgrhs01_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &NN1, const Number &NN2, + const Number &) + { + iter(N1, N2, Current_Dim - 1) = result(Current_Dim - 1); + T3dgrhs01_equals_T1(iter, result, NN1, NN2, Number()); + } + + template + void T3dgrhs01_equals_T1(A &iter, const Tensor1_Expr &result, + const Number &, const Number &, + const Number<1> &) + { + iter(N1, N2, 0) = result(0); + } + + template + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>:: + operator=(const Tensor1_Expr &result) + { + T3dgrhs01_equals_T1(iter, result, Number(), Number(), + Number()); + return *this; + } + + template + const Tensor1_Expr, T, Dim, i> & + Tensor1_Expr, T, Dim, i>::operator=( + const Tensor1_Expr, T, Dim, i> &result) + { + return operator=, T>(result); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_and_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_and_Tensor1.hpp new file mode 100644 index 000000000..271168b3f --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_and_Tensor1.hpp @@ -0,0 +1,36 @@ +/* Multiply two Tensor1's together but don't contract, yielding a + Tensor1. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor1_and_Tensor1 + { + Tensor1_Expr iterA; + Tensor1_Expr iterB; + + public: + typename promote::V operator()(const int N) const + { + return iterA(N) * iterB(N); + } + + Tensor1_and_Tensor1(const Tensor1_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator&(const Tensor1_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Tensor1_and_Tensor1; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_carat_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_carat_Tensor1.hpp new file mode 100644 index 000000000..6b0992317 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_carat_Tensor1.hpp @@ -0,0 +1,35 @@ +/* Multiplies two Tensor1's together yielding a Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor1_carat_Tensor1 + { + Tensor1_Expr iterA; + Tensor1_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1) * iterB(N2); + } + + Tensor1_carat_Tensor1(const Tensor1_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim, i, j> + operator^(const Tensor1_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Tensor1_carat_Tensor1; + return Tensor2_symmetric_Expr::V, Dim, + i, j>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_divide_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_divide_generic.hpp new file mode 100644 index 000000000..d9ae5e3d0 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_divide_generic.hpp @@ -0,0 +1,37 @@ +/* Divides a Tensor1 by a generic, yielding a Tensor1. Usually used + for doubles, but could be used for complex, etc. All that it + requires is that you can add an element of the Tensor1 to it. */ + +/* A(i) / d0 -> Tensor1 */ + +#pragma once + +namespace FTensor +{ + template + class Tensor1_divide_generic + { + Tensor1_Expr iterA; + U d; + + public: + typename promote::V operator()(const int N) const + { + return iterA(N) / d; + } + + Tensor1_divide_generic(const Tensor1_Expr &a, const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator/(const Tensor1_Expr &a, const U &d0) + { + using TensorExpr = Tensor1_divide_generic; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_minus_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_minus_Tensor1.hpp new file mode 100644 index 000000000..7ff753e66 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_minus_Tensor1.hpp @@ -0,0 +1,35 @@ +/* Subtracts a Tensor1 from a Tensor1, yielding a Tensor1. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor1_minus_Tensor1 + { + Tensor1_Expr iterA; + Tensor1_Expr iterB; + + public: + typename promote::V operator()(const int N) const + { + return iterA(N) - iterB(N); + } + + Tensor1_minus_Tensor1(const Tensor1_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator-(const Tensor1_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Tensor1_minus_Tensor1; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_minus_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_minus_generic.hpp new file mode 100644 index 000000000..9c618ac85 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_minus_generic.hpp @@ -0,0 +1,38 @@ +/* Subtracts a Tensor1 from a generic (or vice versa), yielding a + Tensor1. Usually used for doubles, but could be used for complex, + etc. All that it requires is that you can add an element of the + Tensor1 to it. */ + +/* A(i) - d0 -> Tensor1 */ + +#pragma once + +namespace FTensor +{ + template + class Tensor1_minus_generic + { + Tensor1_Expr iterA; + U d; + + public: + typename promote::V operator()(const int N) const + { + return iterA(N) - d; + } + + Tensor1_minus_generic(const Tensor1_Expr &a, const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator-(const Tensor1_Expr &a, const U &d0) + { + using TensorExpr = Tensor1_minus_generic; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_or_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_or_Tensor1.hpp new file mode 100644 index 000000000..ca8f8abdc --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_or_Tensor1.hpp @@ -0,0 +1,35 @@ +/* Adds two Tensor1's together yielding a Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor1_or_Tensor1 + { + Tensor1_Expr iterA; + Tensor1_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1) + iterB(N2); + } + + Tensor1_or_Tensor1(const Tensor1_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim, i, j> + operator||(const Tensor1_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Tensor1_or_Tensor1; + return Tensor2_symmetric_Expr::V, Dim, + i, j>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_plus_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_plus_Tensor1.hpp new file mode 100644 index 000000000..b38867032 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_plus_Tensor1.hpp @@ -0,0 +1,35 @@ +/* Adds two Tensor1's together, yielding a Tensor1. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor1_plus_Tensor1 + { + Tensor1_Expr iterA; + Tensor1_Expr iterB; + + public: + typename promote::V operator()(const int N) const + { + return iterA(N) + iterB(N); + } + + Tensor1_plus_Tensor1(const Tensor1_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator+(const Tensor1_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Tensor1_plus_Tensor1; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_plus_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_plus_generic.hpp new file mode 100644 index 000000000..570d1da7a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_plus_generic.hpp @@ -0,0 +1,50 @@ +/* Adds a Tensor1 to a generic (or vice versa), yielding a Tensor1. + Usually used for doubles, but could be used for complex, etc. All + that it requires is that you can add an element of the Tensor1 to + it. */ + +/* A(i) + d0 -> Tensor1 */ + +#pragma once + +namespace FTensor +{ + template + class Tensor1_plus_generic + { + Tensor1_Expr iterA; + U d; + + public: + typename promote::V operator()(const int N) const + { + return iterA(N) + d; + } + + Tensor1_plus_generic(const Tensor1_Expr &a, const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator+(const Tensor1_Expr &a, const U &d0) + { + using TensorExpr = Tensor1_plus_generic; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, d0)); + } + + /* d0 + A(i) -> Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator+(const U &d0, const Tensor1_Expr &a) + { + using TensorExpr = Tensor1_plus_generic; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_pointer.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_pointer.hpp new file mode 100644 index 000000000..15802009a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_pointer.hpp @@ -0,0 +1,99 @@ +/* A version for pointers, useful for previously + constructed arrays. */ + +#pragma once + +namespace FTensor +{ + template class Tensor1 + { + /* Note that the T *'s are mutable, so the pointer can change, + allowing iterating over a array. */ + + //mutable T *restrict data[Tensor_Dim]; + mutable T *__restrict data[Tensor_Dim]; + + public: + /* Initializations for varying numbers of elements. */ + template Tensor1(U *... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Tensor1() {} + + /* There are two operator(int)'s, one for non-consts that lets you + change the value, and one for consts that doesn't. */ + + T &operator()(const int N) + { +#ifdef FTENSOR_DEBUG + if(N >= Tensor_Dim || N < 0) + { + std::stringstream s; + s << "Bad index in Tensor1.operator(" << N + << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return *data[N]; + } + T operator()(const int N) const + { +#ifdef FTENSOR_DEBUG + if(N >= Tensor_Dim || N < 0) + { + std::stringstream s; + s << "Bad index in Tensor1.operator(" << N + << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return *data[N]; + } + T *ptr(const int N) const + { +#ifdef FTENSOR_DEBUG + if(N >= Tensor_Dim || N < 0) + { + std::stringstream s; + s << "Bad index in Tensor1.ptr(" << N << ")" + << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[N]; + } + + /* These operator()'s are the first part in constructing template + expressions. They can be used to slice off lower dimensional + parts. They are not entirely safe, since you can accidentaly use a + higher dimension than what is really allowed (like Dim=5). */ + + template + Tensor1_Expr, T, Dim, i> + operator()(const Index &index) + { + return Tensor1_Expr, T, Dim, i>(*this); + } + + template + Tensor1_Expr, T, Dim, i> + operator()(const Index &index) const + { + return Tensor1_Expr, T, Dim, i>(*this); + } + + /* The ++ operator increments the pointer, not the number that the + pointer points to. This allows iterating over a grid. */ + + const Tensor1 &operator++() const + { + for(int i = 0; i < Tensor_Dim; ++i) + ++data[i]; + return *this; + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_times_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_times_Tensor1.hpp new file mode 100644 index 000000000..715ddee4c --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_times_Tensor1.hpp @@ -0,0 +1,66 @@ +/* Multiplies two Tensor1's together yielding a T (int, double, etc.) + or a Tensor2. */ + +/* A(i)*B(i) -> T */ + +#pragma once + +namespace FTensor +{ + template + typename promote::V + T1_times_T1(const Tensor1_Expr &a, + const Tensor1_Expr &b, const Number &) + { + return a(Current_Dim - 1) * b(Current_Dim - 1) + + T1_times_T1(a, b, Number()); + } + + template + typename promote::V + T1_times_T1(const Tensor1_Expr &a, + const Tensor1_Expr &b, const Number<1> &) + { + return a(0) * b(0); + } + + template + typename promote::V operator*(const Tensor1_Expr &a, + const Tensor1_Expr &b) + { + return T1_times_T1(a, b, Number()); + } + + /* A(i)*B(j) -> Tensor2 */ + + template + class Tensor1_times_Tensor1 + { + Tensor1_Expr iterA; + Tensor1_Expr iterB; + + public: + Tensor1_times_Tensor1(const Tensor1_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1) * iterB(N2); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim1, i, j> + operator*(const Tensor1_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr = Tensor1_times_Tensor1; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_times_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_times_generic.hpp new file mode 100644 index 000000000..d3bbf5b53 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_times_generic.hpp @@ -0,0 +1,50 @@ +/* Multipliess a Tensor1 by a generic (or vice versa), yielding a Tensor1. + Usually used for doubles, but could be used for complex, etc. All + that it requires is that you can add an element of the Tensor1 to + it. */ + +/* A(i) * d0 -> Tensor1 */ + +#pragma once + +namespace FTensor +{ + template + class Tensor1_times_generic + { + Tensor1_Expr iterA; + U d; + + public: + typename promote::V operator()(const int N) const + { + return iterA(N) * d; + } + + Tensor1_times_generic(const Tensor1_Expr &a, const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Tensor1_Expr &a, const U &d0) + { + using TensorExpr = Tensor1_times_generic; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, d0)); + } + + /* d0 * A(i) -> Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const U &d0, const Tensor1_Expr &a) + { + using TensorExpr = Tensor1_times_generic; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_value.hpp b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_value.hpp new file mode 100644 index 000000000..4c3d7ad1b --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/Tensor1_value.hpp @@ -0,0 +1,129 @@ +/* The general version, not for pointers. */ + +#include +#pragma once + +namespace FTensor +{ + template class Tensor1 + { + protected: + T data[Tensor_Dim]; + + public: + /* Initializations for varying numbers of elements. */ + template constexpr Tensor1(U... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + }; + + constexpr Tensor1() {} + + /* There are two operator(int)'s, one for non-consts that lets you + change the value, and one for consts that doesn't. */ + + T &operator()(const int N) + { +#ifdef FTENSOR_DEBUG + if(N >= Tensor_Dim || N < 0) + { + std::stringstream s; + s << "Bad index in Tensor1.operator(" << N + << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[N]; + } + T operator()(const int N) const + { +#ifdef FTENSOR_DEBUG + if(N >= Tensor_Dim || N < 0) + { + std::stringstream s; + s << "Bad index in Tensor1.operator(" << N + << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[N]; + } + + /* These operator()'s are the first part in constructing template + expressions. They can be used to slice off lower dimensional + parts. They are not entirely safe, since you can accidentaly use a + higher dimension than what is really allowed (like Dim=5). */ + + template + typename std::enable_if< + (Tensor_Dim >= Dim), Tensor1_Expr, T, Dim, i>>::type + operator()(const Index &) + { + return Tensor1_Expr, T, Dim, i>(*this); + } + + template + typename std::enable_if< + (Tensor_Dim >= Dim), + Tensor1_Expr, T, Dim, i>>::type + operator()(const Index &) const + { + return Tensor1_Expr, T, Dim, i>(*this); + } + + /* Convenience functions */ + + Tensor1 normalize() + { + const Index<'a', Tensor_Dim> a; + (*this)(a) /= l2(); + return *this; + } + + T l2() const { return sqrt(l2_squared(Number())); } + + template T l2_squared(const Number &) const + { + return data[Current_Dim - 1] * data[Current_Dim - 1] + + l2_squared(Number()); + } + T l2_squared(const Number<1> &) const { return data[0] * data[0]; } + }; +} +/// JSON compatible output + +template +std::ostream & +operator<<(std::ostream &os, const FTensor::Tensor1 &t) +{ + os << '['; + for(int i = 0; i + 1 < Tensor_Dim; ++i) + { + os << t(i) << ','; + } + if(Tensor_Dim > 0) + { + os << t(Tensor_Dim - 1); + } + os << ']'; + return os; +} + +template +std::istream &operator>>(std::istream &is, FTensor::Tensor1 &t) +{ + char c; + is >> c; + for(int i = 0; i + 1 < Tensor_Dim; ++i) + { + is >> t(i) >> c; + } + if(Tensor_Dim > 0) + { + is >> t(Tensor_Dim - 1); + } + is >> c; + return is; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/dTensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/dTensor1.hpp new file mode 100644 index 000000000..b9bf3a5e1 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/dTensor1.hpp @@ -0,0 +1,68 @@ +/* Takes a derivative of a Tensor1, yielding a Tensor2. */ + +// template +// class dTensor1 +// { +// const Tensor1 &a; +// const int di,dj,dk; +// const double dx,dy,dz; +// public: +// typename promote::V operator()(const int N1, const int N2) const +// { +// return N2==0 ? (*(a.ptr(N1)+di)-*(a.ptr(N1)-di))*dx*0.5 +// : (N2==1 ? (*(a.ptr(N1)+dj)-*(a.ptr(N1)-dj))*dy*0.5 +// : (*(a.ptr(N1)+dk)-*(a.ptr(N1)-dk))*dz*0.5); +// } +// dTensor1(const Tensor1 &A, +// const int Di, const int Dj, const int Dk, +// const double Dx, const double Dy, const double Dz): +// a(A), di(Di), dj(Dj), dk(Dk), dx(Dx), dy(Dy), dz(Dz) {} +// }; + +// template +// const Tensor2_Expr, +// typename promote::V,Dim,3,i,j> +// d(const Tensor1 &a, const Index index1, const Index +// index2, +// const int &di, const int &dj, const int &dk, +// const double &dx, const double &dy, const double &dz) +// { +// typedef dTensor1 TensorExpr; +// return Tensor2_Expr::V,Dim,3,i,j> +// (TensorExpr(a,di,dj,dk,dx,dy,dz)); +// } + +#pragma once + +namespace FTensor +{ + template class dTensor1 + { + const Tensor1 &a; + const Tensor1 &d_ijk; + const Tensor1 &d_xyz; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return (*(a.ptr(N1) + d_ijk(N2)) - *(a.ptr(N1) - d_ijk(N2))) * d_xyz(N2) + * 0.5; + } + dTensor1(const Tensor1 &A, const Tensor1 &D_ijk, + const Tensor1 &D_xyz) + : a(A), d_ijk(D_ijk), d_xyz(D_xyz) + {} + }; + + template + const Tensor2_Expr, + typename promote::V, Dim0, Dim1, i, j> + d(const Tensor1 &a, const Index index1, + const Index index2, const Tensor1 &d_ijk, + const Tensor1 &d_xyz) + { + using TensorExpr = dTensor1; + return Tensor2_Expr::V, Dim0, Dim1, + i, j>(TensorExpr(a, d_ijk, d_xyz)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/d_one_sided_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/d_one_sided_Tensor1.hpp new file mode 100644 index 000000000..e355f4703 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/d_one_sided_Tensor1.hpp @@ -0,0 +1,40 @@ +/* Takes a one-sided derivative of a Tensor1 in a particular + direction, yieldind a Tensor1. */ + +#pragma once + +namespace FTensor +{ + template class d_one_sided_Tensor1 + { + const Tensor1 &a; + const int di, dj, dk; + const double dx, dy, dz; + + public: + typename promote::V operator()(const int N1) const + { + return axis == 0 ? (a(N1) - *(a.ptr(N1) - di)) * dx + : (axis == 1 ? (a(N1) - *(a.ptr(N1) - dj)) * dy + : (a(N1) - *(a.ptr(N1) - dk)) * dz); + } + d_one_sided_Tensor1(const Tensor1 &A, const int Di, const int Dj, + const int Dk, const double Dx, const double Dy, + const double Dz) + : a(A), di(Di), dj(Dj), dk(Dk), dx(Dx), dy(Dy), dz(Dz) + {} + }; + + template + const Tensor1_Expr, + typename promote::V, Dim, i> + d_one_sided(const Tensor1 &a, const Number n1, + const Index index1, const int &di, const int &dj, + const int &dk, const double &dx, const double &dy, + const double &dz) + { + using TensorExpr = d_one_sided_Tensor1; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, di, dj, dk, dx, dy, dz)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/ddTensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/ddTensor1.hpp new file mode 100644 index 000000000..bfe4c41b6 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/ddTensor1.hpp @@ -0,0 +1,51 @@ +/* Takes a second derivative of a Tensor1, yielding a Dg, but + with it's indices switched around so that it has the symmetries of + a Christof. */ + +#pragma once + +namespace FTensor +{ + template + class ddTensor1 + { + const Tensor1 &a; + const Tensor1 &d_ijk; + const Tensor1 &d_xyz; + + public: + /* Note the indices switch here. */ + + typename promote::V + operator()(const int N2, const int N3, const int N1) const + { + return N2 == N3 ? (*(a.ptr(N1) + d_ijk(N2)) - 2 * a(N1) + + *(a.ptr(N1) - d_ijk(N2))) + * d_xyz(N2) * d_xyz(N2) + : (*(a.ptr(N1) + d_ijk(N2) + d_ijk(N3)) + - *(a.ptr(N1) - d_ijk(N2) + d_ijk(N3)) + - *(a.ptr(N1) + d_ijk(N2) - d_ijk(N3)) + + *(a.ptr(N1) - d_ijk(N2) - d_ijk(N3))) + * d_xyz(N2) * d_xyz(N3) * 0.25; + } + ddTensor1(const Tensor1 &A, const Tensor1 &D_ijk, + const Tensor1 &D_xyz) + : a(A), d_ijk(D_ijk), d_xyz(D_xyz) + {} + }; + + /* Note that the indices are mixed up here to convert between being + symmetric on the last two indices to the first two indices. */ + + template + const Dg_Expr, + typename promote::V, Dim0, Dim12, i, j, k> + dd(const Tensor1 &a, const Index index0, + const Index index1, const Index index2, + const Tensor1 &d_ijk, const Tensor1 &d_xyz) + { + using TensorExpr = ddTensor1; + return Dg_Expr::V, Dim0, Dim12, i, + j, k>(TensorExpr(a, d_ijk, d_xyz)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/diffusion_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/diffusion_Tensor1.hpp new file mode 100644 index 000000000..2497bed3a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/diffusion_Tensor1.hpp @@ -0,0 +1,48 @@ +/* Computes 2*del^2 of a Tensor1_ptr but uses diagonal derivatives for + half of it. Yields a Tensor1. */ + +#pragma once + +namespace FTensor +{ + template class diffusion_Tensor1 + { + const Tensor1 &a; + const int di, dj, dk; + const double dx; + + public: + typename promote::V operator()(const int N1) const + { + return ((*(a.ptr(N1) + di) - 2 * a(N1) + *(a.ptr(N1) - di)) + + (*(a.ptr(N1) + dj) - 2 * a(N1) + *(a.ptr(N1) - dj)) + + (*(a.ptr(N1) + dk) - 2 * a(N1) + *(a.ptr(N1) - dk)) + + ((*(a.ptr(N1) + di + dj) + *(a.ptr(N1) + di - dj) + + *(a.ptr(N1) - di + dj) + *(a.ptr(N1) - di - dj) + - 4 * a(N1)) + + (*(a.ptr(N1) + di + dk) + *(a.ptr(N1) + di - dk) + + *(a.ptr(N1) - di + dk) + *(a.ptr(N1) - di - dk) + - 4 * a(N1)) + + (*(a.ptr(N1) + dj + dk) + *(a.ptr(N1) + dj - dk) + + *(a.ptr(N1) - dj + dk) + *(a.ptr(N1) - dj - dk) + - 4 * a(N1))) + / (std::sqrt(2.0))) + * dx * dx; + } + diffusion_Tensor1(const Tensor1 &A, const int Di, const int Dj, + const int Dk, const double Dx) + : a(A), di(Di), dj(Dj), dk(Dk), dx(Dx) + {} + }; + + template + const Tensor1_Expr, + typename promote::V, Dim, i> + diffusion(const Tensor1 &a, const Index index1, + const int &di, const int &dj, const int &dk, const double &dx) + { + using Tensor_Expr = diffusion_Tensor1; + return Tensor1_Expr::V, Dim, i>( + Tensor_Expr(a, di, dj, dk, dx)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/generic_minus_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/generic_minus_Tensor1.hpp new file mode 100644 index 000000000..1e2c81a95 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/generic_minus_Tensor1.hpp @@ -0,0 +1,33 @@ +/* Subtracts a Tensor1 from a generic, yielding a Tensor1. */ + +#pragma once + +namespace FTensor +{ + template + class generic_minus_Tensor1 + { + Tensor1_Expr iterA; + U d; + + public: + typename promote::V operator()(const int N) const + { + return d - iterA(N); + } + + generic_minus_Tensor1(const Tensor1_Expr &a, const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator-(const U &d0, const Tensor1_Expr &a) + { + using TensorExpr = generic_minus_Tensor1; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/interpolate_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/interpolate_Tensor1.hpp new file mode 100644 index 000000000..e1b613aad --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/interpolate_Tensor1.hpp @@ -0,0 +1,58 @@ +/* Interpolates to (i0+distance[0], j0+distance[1], k0+distance[2]) + yielding a Tensor1. (i0,j0,k0) are 3D array coordinates, + conjugate==1-distance, and (di,dj,dk) are the stride of the array + coordinates. It is assumed that the Tensor1 is zero + centered. */ + +#pragma once + +namespace FTensor +{ + template class interpolate_Tensor1 + { + const Tensor1 &a; + const int di, dj, dk, i0, j0, k0; + const double *distance, *conjugate; + + public: + typename promote::V operator()(const int N1) const + { + return conjugate[0] * conjugate[1] * conjugate[2] + * (*(a.ptr(N1) + di * i0 + dj * j0 + dk * k0)) + + distance[0] * conjugate[1] * conjugate[2] + * (*(a.ptr(N1) + di * (i0 + 1) + dj * (j0) + dk * (k0))) + + conjugate[0] * distance[1] * conjugate[2] + * (*(a.ptr(N1) + di * (i0) + dj * (j0 + 1) + dk * (k0))) + + distance[0] * distance[1] * conjugate[2] + * (*(a.ptr(N1) + di * (i0 + 1) + dj * (j0 + 1) + dk * (k0))) + + conjugate[0] * conjugate[1] * distance[2] + * (*(a.ptr(N1) + di * (i0) + dj * (j0) + dk * (k0 + 1))) + + distance[0] * conjugate[1] * distance[2] + * (*(a.ptr(N1) + di * (i0 + 1) + dj * (j0) + dk * (k0 + 1))) + + conjugate[0] * distance[1] * distance[2] + * (*(a.ptr(N1) + di * (i0) + dj * (j0 + 1) + dk * (k0 + 1))) + + distance[0] * distance[1] * distance[2] + * (*(a.ptr(N1) + di * (i0 + 1) + dj * (j0 + 1) + + dk * (k0 + 1))); + } + interpolate_Tensor1(const Tensor1 &A, const int Di, const int Dj, + const int Dk, const int I0, const int J0, const int K0, + const double Distance[3], const double Conjugate[3]) + : a(A), di(Di), dj(Dj), dk(Dk), i0(I0), j0(J0), k0(K0), + distance(Distance), conjugate(Conjugate) + {} + }; + + template + const Tensor1_Expr, + typename promote::V, Dim, i> + interpolate(const Tensor1 &a, const Index index1, + const int &di, const int &dj, const int &dk, const int &i0, + const int &j0, const int &k0, const double distance[3], + const double conjugate[3]) + { + using Tensor_Expr = interpolate_Tensor1; + return Tensor1_Expr::V, Dim, i>( + Tensor_Expr(a, di, dj, dk, i0, j0, k0, distance, conjugate)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor1/minus_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor1/minus_Tensor1.hpp new file mode 100644 index 000000000..3401efdee --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor1/minus_Tensor1.hpp @@ -0,0 +1,24 @@ +/* Declares a wrapper class for the unary minus (-) operator. */ + +#pragma once + +namespace FTensor +{ + template class minus_Tensor1 + { + Tensor1_Expr iterA; + + public: + T operator()(const int N) const { return -iterA(N); } + + minus_Tensor1(const Tensor1_Expr &a) : iterA(a) {} + }; + + template + Tensor1_Expr, T, Dim, i> + operator-(const Tensor1_Expr &a) + { + using TensorExpr = minus_Tensor1; + return Tensor1_Expr(TensorExpr(a)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2.hpp new file mode 100644 index 000000000..8c17a3832 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2.hpp @@ -0,0 +1,9 @@ +/* Declarations for Tensor2. */ + +#include "Tensor2/Tensor2_number.hpp" +#include "Tensor2/Tensor2_numeral.hpp" + +#include "Tensor2/Tensor2_pointer.hpp" +#include "Tensor2/Tensor2_value.hpp" + +#include "Tensor2/Tensor2_Expr.hpp" diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_Expr.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_Expr.hpp new file mode 100644 index 000000000..23180fd3d --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_Expr.hpp @@ -0,0 +1,183 @@ +/* Declares a wrapper class for rank 2 Tensor expressions. I + specialize it for when I wrap a simple Tensor2 or Tensor2_ptr so + that it has a reference to the Tensor2(_ptr) and not a copy. + Otherwise assignment wouldn't work. */ + +#pragma once + +#include "Tensor2_and_Tensor1.hpp" +#include "Tensor2_carat_Tensor2.hpp" +#include "Tensor2_divide_generic.hpp" +#include "Tensor2_minus_Tensor2.hpp" +#include "Tensor2_or_Tensor2.hpp" +#include "Tensor2_plus_Tensor2.hpp" +#include "Tensor2_times_Tensor1.hpp" +#include "Tensor2_times_Tensor2.hpp" +#include "Tensor2_times_generic.hpp" +#include "Tensor2_transform.hpp" +#include "conj_Tensor2.hpp" +#include "minus_Tensor2.hpp" + +#include "../permute.hpp" + +namespace FTensor +{ + template + class Tensor2_Expr + { + A iter; + + public: + Tensor2_Expr(const A &a) : iter(a) {} + T operator()(const int N1, const int N2) const { return iter(N1, N2); } + }; + + template + class Tensor2_Expr, T, Dim0, Dim1, i, j> + { + Tensor2 &iter; + + public: + Tensor2_Expr(Tensor2 &a) : iter(a) {} + T &operator()(const int N1, const int N2) { return iter(N1, N2); } + T operator()(const int N1, const int N2) const { return iter(N1, N2); } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + auto &equals(const Tensor2_Expr &rhs) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + { + iter(ii, jj) = permute(*this, rhs, ii, jj); + } + return *this; + } + + template + auto & + operator=(const FTensor::Tensor2_Expr &rhs) + { + return equals(rhs); + } + + auto &operator=(const Tensor2_Expr, T, + Dim0, Dim1, i, j> &rhs) + { + return equals(rhs); + } + + template + auto &operator+=(const Tensor2_Expr &rhs) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + { + iter(ii, jj) += permute(*this, rhs, ii, jj); + } + return *this; + } + + template + auto &operator-=(const Tensor2_Expr &rhs) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + { + iter(ii, jj) -= permute(*this, rhs, ii, jj); + } + return *this; + } + + /* This is for int's, double's, etc. */ + + template auto &operator=(const U &u) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + { + iter(ii, jj) = u; + } + return *this; + } + + template auto &operator+=(const U &u) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + { + iter(ii, jj) += u; + } + return *this; + } + + template auto &operator-=(const U &u) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + { + iter(ii, jj) -= u; + } + return *this; + } + + template auto &operator*=(const U &u) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + { + iter(ii, jj) *= u; + } + return *this; + } + + template auto &operator/=(const U &u) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + { + iter(ii, jj) /= u; + } + return *this; + } + }; + + /* Specialized for Dg_number_rhs_0 (Dg with the + first or second index explicitly given). */ + + template + class Tensor2_Expr, T, Dim0, Dim1, i, j> + { + A &iter; + + public: + Tensor2_Expr(A &a) : iter(a) {} + T &operator()(const int N1, const int N2) { return iter(N, N1, N2); } + T operator()(const int N1, const int N2) const { return iter(N, N1, N2); } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + auto &operator=(const Tensor2_Expr &rhs) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + { + iter(ii, jj) = permute(*this, rhs, ii, jj); + } + return *this; + } + + auto &operator=( + const Tensor2_Expr, T, Dim0, Dim1, i, j> &result) + { + return operator=, T>(result); + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_and_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_and_Tensor1.hpp new file mode 100644 index 000000000..67219e97d --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_and_Tensor1.hpp @@ -0,0 +1,90 @@ +/* Multiply a Tensor1 and a Tensor2 together but don't contract, yielding a + Tensor2. */ + +/* A(i,j) & B(i) -> Tensor2 */ + +#pragma once + +namespace FTensor +{ + // Base Template + template + class Tensor2_and_Tensor1 + {}; + + /* A(i,j) & B(i) -> Tensor2 */ + + template + class Tensor2_and_Tensor1 + { + const Tensor2_Expr iterA; + const Tensor1_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) * iterB(N1); + } + + Tensor2_and_Tensor1(const Tensor2_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j) & B(j) -> Tensor2 */ + + template + class Tensor2_and_Tensor1 + { + const Tensor2_Expr iterA; + const Tensor1_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) * iterB(N2); + } + + Tensor2_and_Tensor1(const Tensor2_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j) & B(i/j) -> Tensor2 */ + + template + auto operator&(const Tensor2_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Tensor2_and_Tensor1; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the & operator"); + return Tensor2_Expr::V, Dim0_0, Dim1_0, + i0, j0>(TensorExpr(a, b)); + } + + /* B(i/j) & A(i,j) -> Tensor2 */ + + // TODO=> We are not respecting operation order, in the really odd case + // someone uses this operation with non + // TODO=> commutable T or U. Any ideas on how should we handel this. + + template + auto operator&(const Tensor1_Expr &b, + const Tensor2_Expr &a) + { + using TensorExpr + = Tensor2_and_Tensor1; + return Tensor2_Expr::V, Dim0_0, Dim1_0, + i0, j0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_carat_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_carat_Tensor2.hpp new file mode 100644 index 000000000..b9bd518e4 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_carat_Tensor2.hpp @@ -0,0 +1,205 @@ +/* Creates a Tensor2_symmetric expression by contracting two Tensor2's + together. There are different versions, depending on where the + contracting indices are located (i.e. whether it is A(i,j)^B(j,k) + or A(i,j)^B(k,j)). The classes are numbered to differentiate + between these. Thus, A(i,j)^B(j,k) has 10 appended to the name + because I count from 0. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor2_carat_Tensor2 + {}; + + /* A(i,j)^B(j,k) */ + + template + class Tensor2_carat_Tensor2 + { + const Tensor2_Expr iterA; + const Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1) * iterB(Current_Dim - 1, N2) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0) * iterB(0, N2); + } + + public: + Tensor2_carat_Tensor2(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + /* A(i,j)^B(k,j) */ + + template + class Tensor2_carat_Tensor2 + { + const Tensor2_Expr iterA; + const Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1) * iterB(N2, Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0) * iterB(N2, 0); + } + + public: + Tensor2_carat_Tensor2(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + /* A(j,i)^B(j,k) */ + + template + class Tensor2_carat_Tensor2 + { + const Tensor2_Expr iterA; + const Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(Current_Dim - 1, N1) * iterB(Current_Dim - 1, N2) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(0, N1) * iterB(0, N2); + } + + public: + Tensor2_carat_Tensor2(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + /* A(j,i)^B(k,j) */ + + template + class Tensor2_carat_Tensor2 + { + const Tensor2_Expr iterA; + const Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(Current_Dim - 1, N1) * iterB(N2, Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(0, N1) * iterB(N2, 0); + } + + public: + Tensor2_carat_Tensor2(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + auto operator^(const Tensor2_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Tensor2_carat_Tensor2; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the ^ operator"); + + // Definition of Helper constexpr variables + constexpr int Dim = (i0 == i1 || i0 == j1) ? Dim1_0 : Dim0_0; + constexpr char i = (i0 == i1 || i0 == j1) ? j0 : i0, + j = (i1 == i0 || i1 == j0) ? j1 : i1; + + return Tensor2_symmetric_Expr::V, Dim, + i, j>(TensorExpr(a, b)); + } + + /* I don't think that this product actually gives a Ddg. */ + + // /* A(i,j)^B(k,l) -> Ddg(i,k,j,l) */ + + // template + // class Tensor2_carat_Tensor2_0213 + // { + // const Tensor2_Expr iterA; + // const Tensor2_Expr iterB; + // public: + // Tensor2_carat_Tensor2_0213(const Tensor2_Expr &a, + // const Tensor2_Expr &b): + // iterA(a), iterB(b) {} + // typename promote::V operator()(const int N1, const int N2, const + // int N3, + // const int N4) const + // { + // return iterA(N1,N3)*iterB(N2,N4); + // } + // }; + + // template + // const Ddg_Expr,typename + // promote::V,Dim01,Dim23,i,k,j,l> operator^(const + // Tensor2_Expr &a, const + // Tensor2_Expr &b) + // { + // typedef Tensor2_carat_Tensor2_0213 + // TensorExpr; + // return Ddg_Expr::V,Dim01,Dim23,i,k,j,l> + // (TensorExpr(a,b)); + // } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_divide_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_divide_generic.hpp new file mode 100644 index 000000000..c835c5388 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_divide_generic.hpp @@ -0,0 +1,34 @@ +/* Divides a Tensor2 by a generic, yielding a Tensor2. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor2_divide_generic + { + const Tensor2_Expr iterA; + const U d; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) / d; + } + + Tensor2_divide_generic(const Tensor2_Expr &a, + const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim1, i, j> + operator/(const Tensor2_Expr &a, const U &d0) + { + using TensorExpr = Tensor2_divide_generic; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_minus_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_minus_Tensor2.hpp new file mode 100644 index 000000000..2b93eeced --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_minus_Tensor2.hpp @@ -0,0 +1,71 @@ +/* Subtracts a Tensor2 from a Tensor2, yielding a Tensor2. */ + +#pragma once + +namespace FTensor +{ + /* Base template */ + template + class Tensor2_minus_Tensor2 + {}; + + /* A(i,j)-B(i,j) */ + + template + class Tensor2_minus_Tensor2 + { + const Tensor2_Expr iterA; + const Tensor2_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) - iterB(N1, N2); + } + + Tensor2_minus_Tensor2(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j)-B(j,i) */ + + template + class Tensor2_minus_Tensor2 + { + const Tensor2_Expr iterA; + const Tensor2_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) - iterB(N2, N1); + } + + Tensor2_minus_Tensor2(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_Expr, + typename promote::V, Dim0_0, Dim1_0, i0, j0> + operator-(const Tensor2_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Tensor2_minus_Tensor2; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the - operator"); + return Tensor2_Expr::V, Dim0_0, Dim1_0, + i0, j0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_number.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_number.hpp new file mode 100644 index 000000000..fd48ee262 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_number.hpp @@ -0,0 +1,31 @@ +/* This is for expressions where a number is used for one slot, and + an index for another, yielding a Tensor1_Expr. */ + +#pragma once + +namespace FTensor +{ + template class Tensor2_number_1 + { + A iterA; + + public: + T operator()(const int N1) const { return iterA(N1, N); } + Tensor2_number_1(const A &a) : iterA(a) {} + }; + + template class Tensor2_number_0 + { + A iterA; + + public: + T operator()(const int N1) const { return iterA(N, N1); } + Tensor2_number_0(const A &a) : iterA(a) {} + }; + + template class Tensor2_number_rhs_0 + {}; + + template class Tensor2_number_rhs_1 + {}; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_numeral.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_numeral.hpp new file mode 100644 index 000000000..ea0ddc270 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_numeral.hpp @@ -0,0 +1,27 @@ +/* This is for expressions where a number is used for one slot, and + an index for another, yielding a Tensor1_Expr. */ + +#pragma once + +namespace FTensor +{ + template class Tensor2_numeral_1 + { + A iterA; + const int N; + + public: + T operator()(const int N1) const { return iterA(N1, N); } + Tensor2_numeral_1(A &a, const int NN) : iterA(a), N(NN) {} + }; + + template class Tensor2_numeral_0 + { + A iterA; + const int N; + + public: + T operator()(const int N1) const { return iterA(N, N1); } + Tensor2_numeral_0(A &a, const int NN) : iterA(a), N(NN) {} + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_or_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_or_Tensor2.hpp new file mode 100644 index 000000000..c0eee1d04 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_or_Tensor2.hpp @@ -0,0 +1,72 @@ +/* Creates a Tensor2_symmetric expression by adding two Tensor2's + together. */ + +/* This version is for expressions like A(i,j)||B(i,j) */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor2_or_Tensor2 + {}; + + /* A(i,j)||B(i,j) */ + + template + class Tensor2_or_Tensor2 + { + Tensor2_Expr iterA; + Tensor2_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) + iterB(N1, N2); + } + + Tensor2_or_Tensor2(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j)||B(j,i) */ + + template + class Tensor2_or_Tensor2 + { + Tensor2_Expr iterA; + Tensor2_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) + iterB(N2, N1); + } + + Tensor2_or_Tensor2(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim0_0, i0, j0> + operator||(const Tensor2_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Tensor2_or_Tensor2; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the || operator"); + return Tensor2_symmetric_Expr::V, + Dim0_0, i0, j0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_plus_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_plus_Tensor2.hpp new file mode 100644 index 000000000..b64aa6770 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_plus_Tensor2.hpp @@ -0,0 +1,71 @@ +/* Adds a Tensor2 to a Tensor2, yielding a Tensor2. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor2_plus_Tensor2 + {}; + + /* A(i,j)+B(i,j) */ + + template + class Tensor2_plus_Tensor2 + { + const Tensor2_Expr iterA; + const Tensor2_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) + iterB(N1, N2); + } + + Tensor2_plus_Tensor2(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j)+B(j,i) */ + + template + class Tensor2_plus_Tensor2 + { + const Tensor2_Expr iterA; + const Tensor2_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) + iterB(N2, N1); + } + + Tensor2_plus_Tensor2(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_Expr, + typename promote::V, Dim0_0, Dim1_0, i0, j0> + operator+(const Tensor2_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Tensor2_plus_Tensor2; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the + operator"); + return Tensor2_Expr::V, Dim0_0, Dim1_0, + i0, j0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_pointer.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_pointer.hpp new file mode 100644 index 000000000..67199cd7e --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_pointer.hpp @@ -0,0 +1,173 @@ +/* A version for pointers. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor2 + { + //mutable T *restrict data[Tensor_Dim0][Tensor_Dim1]; + mutable T *__restrict data[Tensor_Dim0][Tensor_Dim1]; + + public: + /* Initializations for varying numbers of elements. */ + template Tensor2(U *... d) : data{d...} {} + + Tensor2() {} + + /* There are two operator(int,int)'s, one for non-consts that lets you + change the value, and one for consts that doesn't. */ + + T &operator()(const int N1, const int N2) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) + { + std::stringstream s; + s << "Bad index in Tensor2.operator(" << N1 << "," << N2 << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return *data[N1][N2]; + } + + T operator()(const int N1, const int N2) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) + { + std::stringstream s; + s << "Bad index in Tensor2.operator(" << N1 << "," << N2 << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return *data[N1][N2]; + } + + T *ptr(const int N1, const int N2) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) + { + std::stringstream s; + s << "Bad index in Tensor2.ptr(" << N1 << "," << N2 << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[N1][N2]; + } + + /* These operator()'s are the first part in constructing template + expressions. They can be used to slice off lower dimensional + parts. They are not entirely safe, since you can accidentaly use a + higher dimension than what is really allowed (like Dim=5). */ + + template + Tensor2_Expr, T, Dim0, Dim1, i, j> + operator()(const Index, const Index index2) + { + return Tensor2_Expr, T, Dim0, + Dim1, i, j>(*this); + } + + template + Tensor2_Expr, T, Dim0, Dim1, + i, j> + operator()(const Index, const Index index2) const + { + return Tensor2_Expr, T, + Dim0, Dim1, i, j>(*this); + } + + /* This is for expressions where a number is used for one slot, and + an index for another, yielding a Tensor1_Expr. The non-const + versions don't actually create a Tensor2_number_rhs_[01] object. + They create a Tensor1_Expr directly, which provides the + appropriate indexing operators. The const versions do create a + Tensor2_number_[01]. */ + + template + Tensor1_Expr< + Tensor2_number_rhs_1, T, N>, T, + Dim, i> + operator()(const Index, const Number) + { + using TensorExpr + = Tensor2_number_rhs_1, T, N>; + return Tensor1_Expr(*this); + } + + template + Tensor1_Expr< + Tensor2_number_rhs_0, T, N>, T, + Dim, i> + operator()(const Number, const Index) + { + using TensorExpr + = Tensor2_number_rhs_0, T, N>; + return Tensor1_Expr(*this); + } + + template + Tensor1_Expr, T, N>, + T, Dim, i> + operator()(const Index, const Number) const + { + using TensorExpr + = Tensor2_number_1, T, N>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + Tensor1_Expr, T, N>, + T, Dim, i> + operator()(const Number, const Index) const + { + using TensorExpr + = Tensor2_number_0, T, N>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* The ++ operator increments the pointer, not the number that the + pointer points to. This allows iterating over a grid. */ + + const Tensor2 &operator++() const + { + for(int i = 0; i < Tensor_Dim0; ++i) + for(int j = 0; j < Tensor_Dim1; ++j) + ++data[i][j]; + return *this; + } + + /* These two operator()'s return the Tensor2 with internal + contractions, yielding a T. I have to specify one for both + const and non-const because otherwise they compiler will use the + operator() which gives a Tensor2_Expr<>. */ + + template + T operator()(const Index, const Index index2) + { + return internal_contract(Number()); + } + + template + T operator()(const Index, const Index index2) const + { + return internal_contract(Number()); + } + + private: + template T internal_contract(Number) const + { + return *data[N - 1][N - 1] + internal_contract(Number()); + } + + T internal_contract(Number<1>) const { return *data[0][0]; } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_times_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_times_Tensor1.hpp new file mode 100644 index 000000000..5c27bc10e --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_times_Tensor1.hpp @@ -0,0 +1,127 @@ +// This file has all of the declarations for expressions like +// Tensor2*Tensor1 and Tensor1*Tensor2, yielding a Tensor1 or Tensor3. + +#pragma once + +#include "../permute.hpp" + +namespace FTensor +{ + // A(i,j) * B(k) single contraction + template + class Tensor2_times_Tensor1_single + { + const Tensor2_Expr iterA; + const Tensor1_Expr iterB; + + public: + Tensor2_times_Tensor1_single(const Tensor2_Expr &iter_a, + const Tensor1_Expr &iter_b) + : iterA(iter_a), iterB(iter_b) + {} + typename promote::V operator()(const int N1) const + { + typename promote::V result(0); + for(int xx = 0; xx < DimX; ++xx) + { + result += iterB(xx) + * Permutation2().eval(iterA, N1, xx); + } + return result; + } + }; + + // A(i,j)*B(j) + template + auto operator*(const Tensor2_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Tensor2_times_Tensor1_single; + return Tensor1_Expr::V, Dim0, i>( + TensorExpr(a, b)); + } + + // B(j)*A(i,j) + template + auto operator*(const Tensor1_Expr &b, + const Tensor2_Expr &a) + { + return a * b; + } + + // A(i,j)*B(i) + template + auto operator*(const Tensor2_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Tensor2_times_Tensor1_single; + return Tensor1_Expr::V, Dim1, j>( + TensorExpr(a, b)); + } + + // B(i)*A(i,j) + template + auto operator*(const Tensor1_Expr &b, + const Tensor2_Expr &a) + { + return a * b; + } + + /* A(i,j)*B(k) -> Tensor3 */ + + template + class Tensor2_times_Tensor1 + { + const Tensor2_Expr iterA; + const Tensor1_Expr iterB; + + public: + Tensor2_times_Tensor1(const Tensor2_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2) * iterB(N3); + } + }; + + template + Tensor3_Expr, + typename promote::V, Dim0, Dim1, Dim2, i, j, k> + operator*(const Tensor2_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Tensor2_times_Tensor1; + return Tensor3_Expr::V, Dim0, Dim1, + Dim2, i, j, k>(TensorExpr(a, b)); + } + + /* B(k)*A(i,j) -> Tensor3 */ + + template + Tensor3_Expr, + typename promote::V, Dim0, Dim1, Dim2, i, j, k> + operator*(const Tensor1_Expr &b, + const Tensor2_Expr &a) + { + using TensorExpr + = Tensor2_times_Tensor1; + return Tensor3_Expr::V, Dim0, Dim1, + Dim2, i, j, k>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_times_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_times_Tensor2.hpp new file mode 100644 index 000000000..a4af44294 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_times_Tensor2.hpp @@ -0,0 +1,328 @@ +/* This file has all of the declarations for Tensor2*Tensor2. This + includes the double contraction A(i,j)*B(i,j) (yielding a + typename promote) as well as the more complicated single contraction + A(i,j)*B(j,k) (yielding a Tensor2 expression) and no contraction + (yielding a Tensor4). */ + +/* Double contraction. */ + +/* A(i,j)*B(i,j) */ + +#pragma once + +namespace FTensor +{ + template + typename promote::V + T2_times_T2(const Tensor2_Expr &a, + const Tensor2_Expr &b, + const Number &, const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1) + * b(Current_Dim0 - 1, Current_Dim1 - 1) + + T2_times_T2(a, b, Number(), + Number()); + } + + template + typename promote::V + T2_times_T2(const Tensor2_Expr &a, + const Tensor2_Expr &b, const Number<1> &, + const Number &) + { + return a(0, Current_Dim1 - 1) * b(0, Current_Dim1 - 1) + + T2_times_T2(a, b, Number(), Number()); + } + + template + typename promote::V + T2_times_T2(const Tensor2_Expr &a, + const Tensor2_Expr &b, const Number<1> &, + const Number<1> &) + { + return a(0, 0) * b(0, 0); + } + + template + typename promote::V + operator*(const Tensor2_Expr &a, + const Tensor2_Expr &b) + { + return T2_times_T2(a, b, Number(), Number()); + } + + /* A(i,j)*B(j,i) */ + + template + typename promote::V + T2_times_switched_T2(const Tensor2_Expr &a, + const Tensor2_Expr &b, + const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1) + * b(Current_Dim1 - 1, Current_Dim0 - 1) + + T2_times_switched_T2(a, b, Number(), + Number()); + } + + template + typename promote::V + T2_times_switched_T2(const Tensor2_Expr &a, + const Tensor2_Expr &b, + const Number<1> &, const Number &) + { + return a(0, Current_Dim1 - 1) * b(Current_Dim1 - 1, 0) + + T2_times_switched_T2(a, b, Number(), + Number()); + } + + template + typename promote::V + T2_times_switched_T2(const Tensor2_Expr &a, + const Tensor2_Expr &b, + const Number<1> &, const Number<1> &) + { + return a(0, 0) * b(0, 0); + } + + template + typename promote::V + operator*(const Tensor2_Expr &a, + const Tensor2_Expr &b) + { + return T2_times_switched_T2(a, b, Number(), Number()); + } + + /* Single contraction. The wrapper class has a different name for + each possible placing of the indices (e.g. A(i,j)*B(j,k) has the + number 10 because the contraction indices are on the second and + first slots (counting from 0). */ + + /* A(i,j)*B(j,k) */ + + template + class Tensor2_times_Tensor2_10 + { + const Tensor2_Expr iterA; + const Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1) * iterB(Current_Dim - 1, N2) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0) * iterB(0, N2); + } + + public: + Tensor2_times_Tensor2_10(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim2, i, k> + operator*(const Tensor2_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_times_Tensor2_10; + return Tensor2_Expr::V, Dim0, Dim2, i, + k>(TensorExpr(a, b)); + } + + /* A(i,j)*B(k,j) */ + + template + class Tensor2_times_Tensor2_11 + { + Tensor2_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1) * iterB(N2, Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0) * iterB(N2, 0); + } + + public: + Tensor2_times_Tensor2_11(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim2, i, k> + operator*(const Tensor2_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_times_Tensor2_11; + return Tensor2_Expr::V, Dim0, Dim2, i, + k>(TensorExpr(a, b)); + } + + /* A(j,i)*B(j,k) */ + + template + class Tensor2_times_Tensor2_00 + { + Tensor2_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(Current_Dim - 1, N1) * iterB(Current_Dim - 1, N2) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(0, N1) * iterB(0, N2); + } + + public: + Tensor2_times_Tensor2_00(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim2, i, k> + operator*(const Tensor2_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_times_Tensor2_00; + return Tensor2_Expr::V, Dim0, Dim2, i, + k>(TensorExpr(a, b)); + } + + /* A(j,i)*B(k,j) */ + + template + class Tensor2_times_Tensor2_01 + { + Tensor2_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(Current_Dim - 1, N1) * iterB(N2, Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(0, N1) * iterB(N2, 0); + } + + public: + Tensor2_times_Tensor2_01(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim2, i, k> + operator*(const Tensor2_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_times_Tensor2_01; + return Tensor2_Expr::V, Dim0, Dim2, i, + k>(TensorExpr(a, b)); + } + + /* A(i,j)*B(k,l) -> Tensor4 */ + + template + class Tensor2_times_Tensor2 + { + Tensor2_Expr iterA; + Tensor2_Expr iterB; + + public: + Tensor2_times_Tensor2(const Tensor2_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2) * iterB(N3, N4); + } + }; + + template + Tensor4_Expr< + Tensor2_times_Tensor2, + typename promote::V, Dim0, Dim1, Dim2, Dim3, i, j, k, l> + operator*(const Tensor2_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_times_Tensor2; + return Tensor4_Expr::V, Dim0, Dim1, + Dim2, Dim3, i, j, k, l>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_times_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_times_generic.hpp new file mode 100644 index 000000000..23c62ce3a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_times_generic.hpp @@ -0,0 +1,44 @@ +/* Multiplies a Tensor2 with a generic, yielding a Tensor2. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor2_times_generic + { + const Tensor2_Expr iterA; + const U d; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) * d; + } + + Tensor2_times_generic(const Tensor2_Expr &a, + const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim1, i, j> + operator*(const Tensor2_Expr &a, const U &d0) + { + using TensorExpr = Tensor2_times_generic; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, d0)); + } + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim1, i, j> + operator*(const U &d0, const Tensor2_Expr &a) + { + using TensorExpr = Tensor2_times_generic; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_transform.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_transform.hpp new file mode 100644 index 000000000..5cb29cdb4 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_transform.hpp @@ -0,0 +1,33 @@ +/* Applies an arbitrary function to the Tensor2_Expr. */ + +#pragma once + +namespace FTensor +{ + template + class transform_Tensor2 + { + const Tensor2_Expr iterA; + B function; + + public: + T operator()(const int N1, const int N2) const + { + return function(iterA(N1, N2)); + } + + transform_Tensor2(const Tensor2_Expr &a, B func) + : iterA(a), function(func) + {} + }; + + template + Tensor2_Expr, T, Dim0, Dim1, i, + j> + transform(const Tensor2_Expr &a, B function) + { + using TensorExpr = transform_Tensor2; + return Tensor2_Expr( + TensorExpr(a, function)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_value.hpp b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_value.hpp new file mode 100644 index 000000000..dcb38a184 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/Tensor2_value.hpp @@ -0,0 +1,302 @@ +#pragma once + +/* A general version, not for pointers. */ + +#include +#include "floatarrayf.h" + + + +#ifdef FTENSOR_DEBUG +#include +#include +#endif + +#pragma once + +namespace FTensor +{ + template class Tensor2 + { + protected: + T data[Tensor_Dim0][Tensor_Dim1]; + + public: + /* Initializations for varying numbers of elements. */ + template Tensor2(U... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Tensor2() {} + + + /* There are two operator(int,int)'s, one for non-consts that lets you + change the value, and one for consts that doesn't. */ + + T &operator()(const int N1, const int N2) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) + { + std::stringstream s; + s << "Bad index in Tensor2.operator(" << N1 << "," << N2 << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[N1][N2]; + } + + T operator()(const int N1, const int N2) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0) + { + std::stringstream s; + s << "Bad index in Tensor2.operator(" << N1 << "," << N2 << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[N1][N2]; + } + + /* These operator()'s are the first part in constructing template + expressions. They can be used to slice off lower dimensional + parts. They are not entirely safe, since you can accidentaly use a + higher dimension than what is really allowed (like Dim=5). */ + + template + typename std::enable_if<(Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1), + Tensor2_Expr, + T, Dim0, Dim1, i, j>>::type + operator()(const Index, const Index) + { + return Tensor2_Expr, T, Dim0, Dim1, + i, j>(*this); + } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1), + Tensor2_Expr, T, Dim0, Dim1, + i, j>>::type + operator()(const Index, const Index) const + { + return Tensor2_Expr, T, Dim0, + Dim1, i, j>(*this); + } + + /* This is for expressions where a number is used for one slot, and + an index for another, yielding a Tensor1_Expr. The non-const + versions don't actually create a Tensor2_number_rhs_[01] object. + They create a Tensor1_Expr directly, which provides the + appropriate indexing operators. The const versions do create a + Tensor2_number_[01]. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim1 > N), + Tensor1_Expr< + Tensor2_number_rhs_1, T, N>, T, + Dim, i>>::type + operator()(const Index, const Number) + { + using TensorExpr + = Tensor2_number_rhs_1, T, N>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim0 > N && Tensor_Dim1 >= Dim), + Tensor1_Expr< + Tensor2_number_rhs_0, T, N>, T, + Dim, i>>::type + operator()(const Number, const Index) + { + using TensorExpr + = Tensor2_number_rhs_0, T, N>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim1 > N), + Tensor1_Expr, T, N>, + T, Dim, i>>::type + operator()(const Index, const Number) const + { + using TensorExpr + = Tensor2_number_1, T, N>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + typename std::enable_if< + (Tensor_Dim0 > N && Tensor_Dim1 >= Dim), + Tensor1_Expr, T, N>, + T, Dim, i>>::type + operator()(const Number, const Index) const + { + using TensorExpr + = Tensor2_number_0, T, N>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* This is for expressions where an actual number (not a Number<>) + is used for one slot, and an index for another, yielding a + Tensor1_Expr. */ + + /* Unfortunately since this integers can only be checked at run time + i can only partially protect this expressions. We should suggest + when ever possible to use Number<>. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim), + Tensor1_Expr< + Tensor2_numeral_1, T>, T, + Dim, i>>::type + operator()(const Index, const int N) const + { + using TensorExpr + = Tensor2_numeral_1, T>; + return Tensor1_Expr(TensorExpr(*this, N)); + } + + template + typename std::enable_if< + (Tensor_Dim1 >= Dim), + Tensor1_Expr< + Tensor2_numeral_0, T>, T, + Dim, i>>::type + operator()(const int N, const Index) const + { + using TensorExpr + = Tensor2_numeral_0, T>; + return Tensor1_Expr(TensorExpr(*this, N)); + } + + /* These two operator()'s return the Tensor2 with internal + contractions, yielding a T. I have to specify one for both + const and non-const because otherwise the compiler will use the + operator() which gives a Tensor2_Expr<>. */ + + template + typename std::enable_if<(Tensor_Dim0 >= Dim && Tensor_Dim1 >= Dim), T>::type + operator()(const Index, const Index) + { + return internal_contract(Number()); + } + + template + typename std::enable_if<(Tensor_Dim0 >= Dim && Tensor_Dim1 >= Dim), T>::type + operator()(const Index, const Index) const + { + return internal_contract(Number()); + } + + private: + template T internal_contract(Number) const + { + return data[N - 1][N - 1] + internal_contract(Number()); + } + + T internal_contract(Number<1>) const { return data[0][0]; } + }; + + + + +} + +/// JSON compatible output + +namespace FTensor +{ + template + std::ostream & + Tensor2_ostream_row(std::ostream &os, + const FTensor::Tensor2 &t, + const int &i) + { + os << '['; + for(int j = 0; j + 1 < Tensor_Dim1; ++j) + { + os << t(i, j) << ','; + } + if(Tensor_Dim1 > 0) + { + os << t(i, Tensor_Dim1 - 1); + } + os << ']'; + return os; + } +} + +template +std::ostream & +operator<<(std::ostream &os, + const FTensor::Tensor2 &t) +{ + os << '['; + for(int i = 0; i + 1 < Tensor_Dim0; ++i) + { + FTensor::Tensor2_ostream_row(os, t, i); + os << ','; + } + if(Tensor_Dim0 > 0) + { + FTensor::Tensor2_ostream_row(os, t, Tensor_Dim0 - 1); + } + os << ']'; + return os; +} + +namespace FTensor +{ + template + std::istream & + Tensor2_istream_row(std::istream &is, + FTensor::Tensor2 &t, + const int &i) + { + char c; + is >> c; + for(int j = 0; j + 1 < Tensor_Dim1; ++j) + { + is >> t(i, j) >> c; + } + if(Tensor_Dim1 > 0) + { + is >> t(i, Tensor_Dim1 - 1); + } + is >> c; + return is; + } +} + +template +std::istream & +operator>>(std::istream &is, FTensor::Tensor2 &t) +{ + char c; + is >> c; + for(int i = 0; i + 1 < Tensor_Dim0; ++i) + { + FTensor::Tensor2_istream_row(is, t, i); + is >> c; + } + if(Tensor_Dim0 > 0) + { + FTensor::Tensor2_istream_row(is, t, Tensor_Dim0 - 1); + } + is >> c; + return is; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/conj_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2/conj_Tensor2.hpp new file mode 100644 index 000000000..d77f6b85d --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/conj_Tensor2.hpp @@ -0,0 +1,28 @@ +/* complex conjugate operator. */ + +#pragma once + +namespace FTensor +{ + template + class conj_Tensor2 + { + const Tensor2_Expr iterA; + + public: + T operator()(const int N1, const int N2) const + { + return conj(iterA(N1, N2)); + } + + conj_Tensor2(const Tensor2_Expr &a) : iterA(a) {} + }; + + template + Tensor2_Expr, T, Dim0, Dim1, i, j> + conj(const Tensor2_Expr &a) + { + using TensorExpr = conj_Tensor2; + return Tensor2_Expr(TensorExpr(a)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2/minus_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2/minus_Tensor2.hpp new file mode 100644 index 000000000..2fa276157 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2/minus_Tensor2.hpp @@ -0,0 +1,25 @@ +/* Unary minus operator. */ + +#pragma once + +namespace FTensor +{ + template + class minus_Tensor2 + { + const Tensor2_Expr iterA; + + public: + T operator()(const int N1, const int N2) const { return -iterA(N1, N2); } + + minus_Tensor2(const Tensor2_Expr &a) : iterA(a) {} + }; + + template + Tensor2_Expr, T, Dim0, Dim1, i, j> + operator-(const Tensor2_Expr &a) + { + using TensorExpr = minus_Tensor2; + return Tensor2_Expr(TensorExpr(a)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_antisymmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_antisymmetric.hpp new file mode 100644 index 000000000..28301955c --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_antisymmetric.hpp @@ -0,0 +1,8 @@ +/* Declarations for a Tensor2_antisymmetric. This only has a single + dimension parameter, since the dimensions of the two indices must + be the same for it to be antisymmetric. */ + +#include "Tensor2_antisymmetric/Tensor2_antisymmetric_value.hpp" +// TODO implement Tensor2_antisymmetric_pointer.hpp + +#include "Tensor2_antisymmetric/Tensor2_antisymmetric_Expr.hpp" diff --git a/src/oofemlib/tensor/FTensor/Tensor2_antisymmetric/Tensor2_antisymmetric_Expr.hpp b/src/oofemlib/tensor/FTensor/Tensor2_antisymmetric/Tensor2_antisymmetric_Expr.hpp new file mode 100644 index 000000000..a9f51b660 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_antisymmetric/Tensor2_antisymmetric_Expr.hpp @@ -0,0 +1,93 @@ +/* Declares a wrapper class for antisymmetric rank 2 Tensor expressions. + It is specialized for Tensor3_number_rhs_2. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor2_antisymmetric_Expr + { + A iter; + + public: + Tensor2_antisymmetric_Expr(const A &a) : iter(a) {} + T operator()(const int N1, const int N2) const { return iter(N1, N2); } + }; + + template + class Tensor2_antisymmetric_Expr, T, + Dim, i, j> + { + Tensor2_antisymmetric &iter; + + public: + Tensor2_antisymmetric_Expr(Tensor2_antisymmetric &a) + : iter(a) + {} + T &operator()(const int N1, const int N2) { return iter(N1, N2); } + T operator()(const int N1, const int N2) const { return iter(N1, N2); } + + // /* Various assignment operators. I have to explicitly declare the + // second operator= because otherwise the compiler will generate its + // own and not use the template code. */ + + // template + // const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator=(const Tensor2_antisymmetric_Expr &result); + + // const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator=(const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // &result); + + // template + // const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator+=(const Tensor2_antisymmetric_Expr &result); + + // template + // const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator-=(const Tensor2_antisymmetric_Expr &result); + + // template + // const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator&=(const Tensor2_antisymmetric_Expr &result); + + // /* This is for when the indices are switched (i,j) -> (j,i). */ + + // template + // const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator=(const Tensor2_antisymmetric_Expr &result); + + // template + // const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator+=(const Tensor2_antisymmetric_Expr &result); + + // template + // const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator-=(const Tensor2_antisymmetric_Expr &result); + + // /* Operations with just generics. */ + + // template + // const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator=(const U &d); template const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator+=(const U &d); template const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator-=(const U &d); template const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator*=(const U &d); template const + // Tensor2_antisymmetric_Expr,T,Dim,i,j> + // & operator/=(const U &d); + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_antisymmetric/Tensor2_antisymmetric_value.hpp b/src/oofemlib/tensor/FTensor/Tensor2_antisymmetric/Tensor2_antisymmetric_value.hpp new file mode 100644 index 000000000..cd5f2e55d --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_antisymmetric/Tensor2_antisymmetric_value.hpp @@ -0,0 +1,314 @@ +#pragma once + +/* A general version, not for pointers. */ + +#include + +namespace FTensor +{ + template class Tensor2_antisymmetric + { + T data[(Tensor_Dim * (Tensor_Dim - 1)) / 2]; + + public: + template Tensor2_antisymmetric(U... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Tensor2_antisymmetric() {} + + /* There are two ways of accessing the values inside, + unsafe(int,int) and operator(int,int). unsafe(int,int) will give + you a wrong answer if you aren't careful. The problem is that we + only store the minimal set of components, but some have different + signs. We can't return the negative of a component, and assign + something to it, because that would assign something to a + temporary. To get the correct answer if you don't want to change + the value, just use operator(int,int). */ + + T &unsafe(const int N1, const int N2) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim || N1 < 0 || N2 >= Tensor_Dim || N2 < 0 || N1 >= N2) + { + std::stringstream s; + s << "Bad index in Tensor2_antisymmetric.operator(" << N1 << "," << N2 << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[(N2 - 1) + (N1 * (2 * (Tensor_Dim - 1) - N1 - 1)) / 2]; + } + + T operator()(const int N1, const int N2) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim || N1 < 0 || N2 >= Tensor_Dim || N2 < 0) + { + std::stringstream s; + s << "Bad index in Tensor2_antisymmetric.operator(" << N1 << "," << N2 << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 == N2 + ? 0 + : (N1 < N2 + ? data[(N2 - 1) + + (N1 * (2 * (Tensor_Dim - 1) - N1 - 1)) / 2] + : -data[(N1 - 1) + + (N2 * (2 * (Tensor_Dim - 1) - N2 - 1)) / 2]); + } + + /* These operator()'s are the first part in constructing template + expressions. They can be used to slice off lower dimensional + parts. They are not entirely safe, since you can accidently use a + higher dimension than what is really allowed (like Dim=5). */ + + /* This returns a Tensor2_Expr, since the indices are not really + antisymmetric anymore since they cover different dimensions. */ + + template + typename std::enable_if<(Tensor_Dim >= Dim0 && Tensor_Dim >= Dim1), + Tensor2_Expr, + T, Dim0, Dim1, i, j>>::type + operator()(const Index, const Index) + { + return Tensor2_Expr, T, Dim0, Dim1, + i, j>(*this); + } + + template + typename std::enable_if< + (Tensor_Dim >= Dim0 && Tensor_Dim >= Dim1), + Tensor2_Expr, T, Dim0, Dim1, + i, j>>::type + operator()(const Index, const Index) const + { + return Tensor2_Expr, T, Dim0, + Dim1, i, j>(*this); + } + + /* This returns a Tensor2_antisymmetric_Expr, since the indices are still + antisymmetric on the lower dimensions. */ + + template + typename std::enable_if< + (Tensor_Dim >= Dim), + Tensor2_antisymmetric_Expr, T, Dim, + i, j>>::type + operator()(const Index index1, const Index index2) + { + return Tensor2_antisymmetric_Expr, + T, Dim, i, j>(*this); + } + + template + typename std::enable_if< + (Tensor_Dim >= Dim), + Tensor2_antisymmetric_Expr, T, + Dim, i, j>>::type + operator()(const Index index1, const Index index2) const + { + return Tensor2_antisymmetric_Expr< + const Tensor2_antisymmetric, T, Dim, i, j>(*this); + } + + /* This is for expressions where a number is used for one slot, and + an index for another, yielding a Tensor1_Expr. The non-const + versions don't actually create a Tensor2_number_rhs_[01] object. + They create a Tensor1_Expr directly, which provides the + appropriate indexing operators. The const versions do create a + Tensor2_number_[01]. */ + + template + typename std::enable_if< + (Tensor_Dim >= Dim && Tensor_Dim > N), + Tensor1_Expr< + Tensor2_number_rhs_1, T, N>, T, + Dim, i>>::type + operator()(const Index index1, const Number) + { + using TensorExpr + = Tensor2_number_rhs_1, T, N>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim >= Dim && Tensor_Dim > N), + Tensor1_Expr, T, N>, + T, Dim, i>>::type + operator()(const Index index1, const Number) const + { + using TensorExpr + = Tensor2_number_1, T, N>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + typename std::enable_if< + (Tensor_Dim > N && Tensor_Dim >= Dim), + Tensor1_Expr< + Tensor2_number_rhs_0, T, N>, T, + Dim, i>>::type + operator()(const Number, const Index index1) + { + using TensorExpr + = Tensor2_number_rhs_0, T, N>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim > N && Tensor_Dim >= Dim), + Tensor1_Expr, T, N>, + T, Dim, i>>::type + operator()(const Number &n1, const Index index1) const + { + using TensorExpr + = Tensor2_number_0, T, N>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Specializations for using actual numbers instead of Number<> */ + + template + typename std::enable_if< + (Tensor_Dim >= Dim), + Tensor1_Expr< + const Tensor2_numeral_1, T>, + T, Dim, i>>::type + operator()(const Index index1, const int N) const + { + using TensorExpr + = Tensor2_numeral_1, T>; + return Tensor1_Expr(TensorExpr(*this, N)); + } + + template + typename std::enable_if< + (Tensor_Dim >= Dim), + Tensor1_Expr< + const Tensor2_numeral_0, T>, + T, Dim, i>>::type + operator()(const int N, const Index index1) const + { + using TensorExpr + = Tensor2_numeral_0, T>; + return Tensor1_Expr(TensorExpr(*this, N)); + } + + /* These two operator()'s return the Tensor2 with internal + contractions, yielding a T. I have to specify one for both + const and non-const because otherwise the compiler will use the + operator() which gives a Tensor2_Expr<>. */ + + /* TODO Here is a good question. It wont create a problem if i put + a higher dimension Index in here but it would be + grammatically wrong. Im gonna add it for now, we can discuss it*/ + + template + typename std::enable_if<(Tensor_Dim >= Dim), T>::type + operator()(const Index index1, const Index index2) + { + return 0; + } + + template + typename std::enable_if<(Tensor_Dim >= Dim), T>::type + operator()(const Index index1, const Index index2) const + { + return 0; + } + }; +} + +/// JSON compatible output. It only outputs unique, non-zero elments, +/// so a 3x3 antisymmetric matrix only outputs 3 elements. + +namespace FTensor +{ + template + std::ostream &Tensor2_antisymmetric_ostream_row( + std::ostream &os, const FTensor::Tensor2_antisymmetric &t, + const int &i) + { + os << '['; + for(int j = i + 1; j + 1 < Tensor_Dim; ++j) + { + os << t(i, j) << ','; + } + if(Tensor_Dim > 0) + { + os << t(i, Tensor_Dim - 1); + } + os << ']'; + return os; + } +} + +template +std::ostream & +operator<<(std::ostream &os, + const FTensor::Tensor2_antisymmetric &t) +{ + os << '['; + for(int i = 0; i + 2 < Tensor_Dim; ++i) + { + FTensor::Tensor2_antisymmetric_ostream_row(os, t, i); + os << ','; + } + if(Tensor_Dim > 1) + { + FTensor::Tensor2_antisymmetric_ostream_row(os, t, Tensor_Dim - 2); + } + os << ']'; + return os; +} + +namespace FTensor +{ + template + std::istream &Tensor2_antisymmetric_istream_row( + std::istream &is, FTensor::Tensor2_antisymmetric &t, + const int &i) + { + char c; + is >> c; + for(int j = i + 1; j + 1 < Tensor_Dim; ++j) + { + is >> t.unsafe(i, j) >> c; + } + if(Tensor_Dim > 0) + { + is >> t.unsafe(i, Tensor_Dim - 1); + } + is >> c; + return is; + } +} + +template +std::istream & +operator>>(std::istream &is, FTensor::Tensor2_antisymmetric &t) +{ + char c; + is >> c; + for(int i = 0; i + 2 < Tensor_Dim; ++i) + { + FTensor::Tensor2_antisymmetric_istream_row(is, t, i); + is >> c; + } + if(Tensor_Dim > 1) + { + FTensor::Tensor2_antisymmetric_istream_row(is, t, Tensor_Dim - 2); + } + is >> c; + return is; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric.hpp new file mode 100644 index 000000000..9b5c3db44 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric.hpp @@ -0,0 +1,8 @@ +/* Declarations for a Tensor2_symmetric. This only has a single + dimension parameter, since the dimensions of the two indices must + be the same for it to be symmetric. */ + +#include "Tensor2_symmetric/Tensor2_symmetric_pointer.hpp" +#include "Tensor2_symmetric/Tensor2_symmetric_value.hpp" + +#include "Tensor2_symmetric/Tensor2_symmetric_Expr.hpp" diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_Expr.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_Expr.hpp new file mode 100644 index 000000000..686dcec2a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_Expr.hpp @@ -0,0 +1,180 @@ +/* Declares a wrapper class for symmetric rank 2 Tensor expressions. + It is specialized for Tensor3_number_rhs_2. Note that + Tensor2_symmetric_Expr_equals.hpp is included at the end, because it + needs the definition of Tensor2_symmetric_Expr. */ + +#pragma once + +#include "Tensor2_symmetric_and_Tensor2_symmetric.hpp" +#include "Tensor2_symmetric_carat_Tensor2.hpp" +#include "Tensor2_symmetric_divide_generic.hpp" +#include "Tensor2_symmetric_minus_Tensor2.hpp" +#include "Tensor2_symmetric_minus_Tensor2_symmetric.hpp" +#include "Tensor2_symmetric_minus_generic.hpp" +#include "Tensor2_symmetric_mod_Tensor2_symmetric.hpp" +#include "Tensor2_symmetric_plus_Tensor2.hpp" +#include "Tensor2_symmetric_plus_Tensor2_symmetric.hpp" +#include "Tensor2_symmetric_plus_generic.hpp" +#include "Tensor2_symmetric_times_Tensor1.hpp" +#include "Tensor2_symmetric_times_Tensor2.hpp" +#include "Tensor2_symmetric_times_Tensor2_symmetric.hpp" +#include "Tensor2_symmetric_times_generic.hpp" +#include "dTensor2_symmetric.hpp" +#include "d_boundary_Tensor2_symmetric.hpp" +#include "d_one_sided_Tensor2_symmetric.hpp" +#include "ddTensor2_symmetric.hpp" +#include "dd_boundary_Tensor2_symmetric.hpp" +#include "diffusion_Tensor2_symmetric.hpp" +#include "generic_minus_Tensor2_symmetric.hpp" +#include "interpolate_Tensor2_symmetric.hpp" +#include "minus_Tensor2_symmetric.hpp" + +namespace FTensor +{ + template + class Tensor2_symmetric_Expr + { + A iter; + + public: + Tensor2_symmetric_Expr(const A &a) : iter(a) {} + T operator()(const int N1, const int N2) const { return iter(N1, N2); } + }; + + template + class Tensor2_symmetric_Expr, T, Dim, i, j> + { + Tensor2_symmetric &iter; + + public: + Tensor2_symmetric_Expr(Tensor2_symmetric &a) : iter(a) {} + T &operator()(const int N1, const int N2) { return iter(N1, N2); } + T operator()(const int N1, const int N2) const { return iter(N1, N2); } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator=(const Tensor2_symmetric_Expr &result); + + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator=(const Tensor2_symmetric_Expr, T, + Dim, i, j> &result); + + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator+=(const Tensor2_symmetric_Expr &result); + + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator-=(const Tensor2_symmetric_Expr &result); + + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator&=(const Tensor2_symmetric_Expr &result); + + /* This is for when the indices are switched (i,j) -> (j,i). */ + + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator=(const Tensor2_symmetric_Expr &result); + + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator+=(const Tensor2_symmetric_Expr &result); + + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator-=(const Tensor2_symmetric_Expr &result); + + /* Operations with just generics. */ + + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator=(const U &d); + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator+=(const U &d); + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator-=(const U &d); + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator*=(const U &d); + template + const Tensor2_symmetric_Expr, T, Dim, i, + j> & + operator/=(const U &d); + }; + + /* Specialized for Dg_number_rhs_2 (Dg with the + second index explicitly given). */ + + template + class Tensor2_symmetric_Expr, T, Dim, i, j> + { + A &iter; + + public: + Tensor2_symmetric_Expr(A &a) : iter(a) {} + T &operator()(const int N1, const int N2) { return iter(N1, N2, N); } + T operator()(const int N1, const int N2) const { return iter(N1, N2, N); } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + operator=(const Tensor2_symmetric_Expr &result); + + const Tensor2_symmetric_Expr, T, Dim, i, j> & + operator=(const Tensor2_symmetric_Expr, T, Dim, i, + j> &result); + }; + + /* Specialized for Ddg_number_rhs_01 (Ddg with the + first and second index explicitly given). */ + /* + template + class Tensor2_symmetric_Expr, T, Dim, i, j> + { + A &iter; + + public: + Tensor2_symmetric_Expr(A &a) : iter(a) {} + T &operator()(const int N2, const int N3) { return iter(N0, N1, N2, N3); } + T operator()(const int N2, const int N3) const + { + return iter(N0, N1, N2, N3); + }*/ + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + /* + template + const Tensor2_symmetric_Expr, T, Dim, i, j> + &operator=(const Tensor2_symmetric_Expr &result); + + const Tensor2_symmetric_Expr, T, Dim, i, j> + &operator=(const Tensor2_symmetric_Expr, + T, Dim, i, j> &result); + };*/ +} + +#include "Tensor2_symmetric_Expr_equals.hpp" diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_Expr_equals.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_Expr_equals.hpp new file mode 100644 index 000000000..0e5fcf03f --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_Expr_equals.hpp @@ -0,0 +1,547 @@ +/* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + +/* T2s=T2s */ + +#pragma once + +namespace FTensor +{ + template + void + T2s_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number &, const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1) + = result(Current_Dim0 - 1, Current_Dim1 - 1); + T2s_equals_T2s(iter, result, Number(), + Number()); + } + + template + void T2s_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number &) + { + iter(0, Current_Dim1 - 1) = result(0, Current_Dim1 - 1); + T2s_equals_T2s(iter, result, Number(), + Number()); + } + + template + void T2s_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number<1> &) + { + iter(0, 0) = result(0, 0); + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator=(const Tensor2_symmetric_Expr &result) + { + T2s_equals_T2s(iter, result, Number(), Number()); + return *this; + } + + /* T2s=T2s_Expr(T2s) */ + + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator=(const Tensor2_symmetric_Expr, T, + Dim, i, j> &result) + { + return operator=, T>(result); + } + + /* T2s+=T2s */ + + template + void + T2s_plus_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number &, + const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1) + += result(Current_Dim0 - 1, Current_Dim1 - 1); + T2s_plus_equals_T2s(iter, result, Number(), + Number()); + } + + template + void + T2s_plus_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number &) + { + iter(0, Current_Dim1 - 1) += result(0, Current_Dim1 - 1); + T2s_plus_equals_T2s(iter, result, Number(), + Number()); + } + + template + void + T2s_plus_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number<1> &) + { + iter(0, 0) += result(0, 0); + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator+=(const Tensor2_symmetric_Expr &result) + { + T2s_plus_equals_T2s(iter, result, Number(), Number()); + return *this; + } + + /* T2s-=T2s */ + + template + void + T2s_minus_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number &, + const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1) + -= result(Current_Dim0 - 1, Current_Dim1 - 1); + T2s_minus_equals_T2s(iter, result, Number(), + Number()); + } + + template + void + T2s_minus_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number &) + { + iter(0, Current_Dim1 - 1) -= result(0, Current_Dim1 - 1); + T2s_minus_equals_T2s(iter, result, Number(), + Number()); + } + + template + void + T2s_minus_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number<1> &) + { + iter(0, 0) -= result(0, 0); + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator-=(const Tensor2_symmetric_Expr &result) + { + T2s_minus_equals_T2s(iter, result, Number(), Number()); + return *this; + } + + /* T2s&=T2s */ + + template + void + T2s_and_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number &, + const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1) + *= result(Current_Dim0 - 1, Current_Dim1 - 1); + T2s_and_equals_T2s(iter, result, Number(), + Number()); + } + + template + void + T2s_and_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number &) + { + iter(0, Current_Dim1 - 1) *= result(0, Current_Dim1 - 1); + T2s_and_equals_T2s(iter, result, Number(), + Number()); + } + + template + void + T2s_and_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number<1> &) + { + iter(0, 0) *= result(0, 0); + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator&=(const Tensor2_symmetric_Expr &result) + { + T2s_and_equals_T2s(iter, result, Number(), Number()); + return *this; + } + + /* This is for when the indices are switched (i,j) -> (j,i). */ + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator=(const Tensor2_symmetric_Expr &result) + { + T2s_equals_T2s(iter, result, Number(), Number()); + return *this; + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator+=(const Tensor2_symmetric_Expr &result) + { + T2s_plus_equals_T2s(iter, result, Number(), Number()); + return *this; + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator-=(const Tensor2_symmetric_Expr &result) + { + T2s_minus_equals_T2s(iter, result, Number(), Number()); + return *this; + } + + /* Operations with just generics. */ + + /* T2s=U */ + + template + void T2s_equals_generic(A &iter, const U &u, const Number &, + const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1) = u; + T2s_equals_generic(iter, u, Number(), + Number()); + } + + template + void T2s_equals_generic(A &iter, const U &u, const Number<1> &, + const Number &) + { + iter(0, Current_Dim1 - 1) = u; + T2s_equals_generic(iter, u, Number(), + Number()); + } + + template + void + T2s_equals_generic(A &iter, const U &u, const Number<1> &, const Number<1> &) + { + iter(0, 0) = u; + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator=(const U &u) + { + T2s_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* T2s+=U */ + + template + void + T2s_plus_equals_generic(A &iter, const U &u, const Number &, + const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1) += u; + T2s_plus_equals_generic(iter, u, Number(), + Number()); + } + + template + void T2s_plus_equals_generic(A &iter, const U &u, const Number<1> &, + const Number &) + { + iter(0, Current_Dim1 - 1) += u; + T2s_plus_equals_generic(iter, u, Number(), + Number()); + } + + template + void T2s_plus_equals_generic(A &iter, const U &u, const Number<1> &, + const Number<1> &) + { + iter(0, 0) += u; + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator+=(const U &u) + { + T2s_plus_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* T2s-=U */ + + template + void + T2s_minus_equals_generic(A &iter, const U &u, const Number &, + const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1) -= u; + T2s_minus_equals_generic(iter, u, Number(), + Number()); + } + + template + void T2s_minus_equals_generic(A &iter, const U &u, const Number<1> &, + const Number &) + { + iter(0, Current_Dim1 - 1) -= u; + T2s_minus_equals_generic(iter, u, Number(), + Number()); + } + + template + void T2s_minus_equals_generic(A &iter, const U &u, const Number<1> &, + const Number<1> &) + { + iter(0, 0) -= u; + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator-=(const U &u) + { + T2s_minus_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* T2s*=U */ + + template + void + T2s_times_equals_generic(A &iter, const U &u, const Number &, + const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1) *= u; + T2s_times_equals_generic(iter, u, Number(), + Number()); + } + + template + void T2s_times_equals_generic(A &iter, const U &u, const Number<1> &, + const Number &) + { + iter(0, Current_Dim1 - 1) *= u; + T2s_times_equals_generic(iter, u, Number(), + Number()); + } + + template + void T2s_times_equals_generic(A &iter, const U &u, const Number<1> &, + const Number<1> &) + { + iter(0, 0) *= u; + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator*=(const U &u) + { + T2s_times_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* T2s/=U */ + + template + void + T2s_divide_equals_generic(A &iter, const U &u, const Number &, + const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1) /= u; + T2s_divide_equals_generic(iter, u, Number(), + Number()); + } + + template + void T2s_divide_equals_generic(A &iter, const U &u, const Number<1> &, + const Number &) + { + iter(0, Current_Dim1 - 1) /= u; + T2s_divide_equals_generic(iter, u, Number(), + Number()); + } + + template + void T2s_divide_equals_generic(A &iter, const U &u, const Number<1> &, + const Number<1> &) + { + iter(0, 0) /= u; + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator/=(const U &u) + { + T2s_divide_equals_generic(iter, u, Number(), Number()); + return *this; + } + + /* Various assignment operators for Dg_number_rhs_2. I have + to explicitly declare the second operator= because otherwise the + compiler will generate its own and not use the template code. */ + + template + void + T3dgrhs2_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number &, + const Number &, const Number &) + { + iter(Current_Dim0 - 1, Current_Dim1 - 1, N) + = result(Current_Dim0 - 1, Current_Dim1 - 1); + T3dgrhs2_equals_T2s(iter, result, Number(), + Number(), Number()); + } + + template + void + T3dgrhs2_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number &, + const Number &) + { + iter(0, Current_Dim1 - 1, N) = result(0, Current_Dim1 - 1); + T3dgrhs2_equals_T2s(iter, result, Number(), + Number(), Number()); + } + + template + void + T3dgrhs2_equals_T2s(A &iter, + const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number<1> &, const Number &) + { + iter(0, 0, N) = result(0, 0); + } + + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator=(const Tensor2_symmetric_Expr &result) + { + T3dgrhs2_equals_T2s(iter, result, Number(), Number(), + Number()); + return *this; + } + + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator=(const Tensor2_symmetric_Expr, T, Dim, i, + j> &result) + { + return operator=, T>(result); + } + + /* Various assignment operators for Ddg_number_rhs_01. I have + to explicitly declare the second operator= because otherwise the + compiler will generate its own and not use the template code. */ + + template + void T4ddgrhs01_equals_T2s( + A &iter, const Tensor2_symmetric_Expr &result, + const Number &, const Number &, + const Number &, const Number &) + { + iter(N0, N1, Current_Dim0 - 1, Current_Dim1 - 1) + = result(Current_Dim0 - 1, Current_Dim1 - 1); + T4ddgrhs01_equals_T2s(iter, result, Number(), + Number(), Number(), Number()); + } + + template + void T4ddgrhs01_equals_T2s( + A &iter, const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number &, const Number &, + const Number &) + { + iter(N0, N1, 0, Current_Dim1 - 1) = result(0, Current_Dim1 - 1); + T4ddgrhs01_equals_T2s(iter, result, Number(), + Number(), Number(), + Number()); + } + + template + void T4ddgrhs01_equals_T2s( + A &iter, const Tensor2_symmetric_Expr &result, + const Number<1> &, const Number<1> &, const Number &, + const Number &) + { + iter(N0, N1, 0, 0) = result(0, 0); + } + /* + template + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator=(const Tensor2_symmetric_Expr &result) + { + T4ddgrhs01_equals_T2s(iter, result, Number(), Number(), + Number(), Number()); + return *this; + } + + template + const Tensor2_symmetric_Expr, T, Dim, i, j> & + Tensor2_symmetric_Expr, T, Dim, i, j>:: + operator=(const Tensor2_symmetric_Expr, T, + Dim, i, j> &result) + { + return operator=, T>(result); + }*/ +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_and_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_and_Tensor2_symmetric.hpp new file mode 100644 index 000000000..2f3e86571 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_and_Tensor2_symmetric.hpp @@ -0,0 +1,75 @@ +/* Multiply a Tensor2_symmetric and a Tensor2_symmetric together but + don't contract, yielding a Tensor2_symmetric. */ + +/* A(i,j) & B(i,j) -> Tensor2_symmetric */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor2_symmetric_and_Tensor2_symmetric + {}; + + template + class Tensor2_symmetric_and_Tensor2_symmetric + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) * iterB(N1, N2); + } + + Tensor2_symmetric_and_Tensor2_symmetric( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j) & B(j,i) -> Tensor2_symmetric */ + + template + class Tensor2_symmetric_and_Tensor2_symmetric + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) * iterB(N2, N1); + } + + Tensor2_symmetric_and_Tensor2_symmetric( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim_0, i0, j0> + operator&(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_and_Tensor2_symmetric; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the & operator"); + return Tensor2_symmetric_Expr::V, Dim_0, + i0, j0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_carat_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_carat_Tensor2.hpp new file mode 100644 index 000000000..7c5a8af47 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_carat_Tensor2.hpp @@ -0,0 +1,191 @@ +/* Creates a Tensor2_symmetric expression by contracting a + Tensor2_symmetric and a Tensor2 together. There are different + versions, depending on where the contracting indices are located + (i.e. whether it is A(i,j)^B(j,k) or A(i,j)^B(k,j)). The classes + are numbered to differentiate between these. Thus, A(i,j)^B(j,k) + has 10 appended to the name because I count from 0. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor2_symmetric_carat_Tensor2 + {}; + + /* A(i,j)*B(j,k) */ + + template + class Tensor2_symmetric_carat_Tensor2 + { + const Tensor2_symmetric_Expr iterA; + const Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1) * iterB(Current_Dim - 1, N2) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0) * iterB(0, N2); + } + + public: + Tensor2_symmetric_carat_Tensor2( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + /* A(i,j)*B(k,j) */ + + template + class Tensor2_symmetric_carat_Tensor2 + { + const Tensor2_symmetric_Expr iterA; + const Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1) * iterB(N2, Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0) * iterB(N2, 0); + } + + public: + Tensor2_symmetric_carat_Tensor2( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + /* A(j,i)*B(j,k) */ + + template + class Tensor2_symmetric_carat_Tensor2 + { + const Tensor2_symmetric_Expr iterA; + const Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(Current_Dim - 1, N1) * iterB(Current_Dim - 1, N2) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(0, N1) * iterB(0, N2); + } + + public: + Tensor2_symmetric_carat_Tensor2( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + /* A(j,i)*B(k,j) */ + + template + class Tensor2_symmetric_carat_Tensor2 + { + const Tensor2_symmetric_Expr iterA; + const Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(Current_Dim - 1, N1) * iterB(N2, Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(0, N1) * iterB(N2, 0); + } + + public: + Tensor2_symmetric_carat_Tensor2( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + auto operator^(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_carat_Tensor2; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the ^ operator"); + + // Definition of Helper constexpr variables + constexpr char i = (i0 == i1 || i0 == j1) ? j0 : i0, + j = (i1 == i0 || i1 == j0) ? j1 : i1; + + return Tensor2_symmetric_Expr::V, Dim_0, + i, j>(TensorExpr(a, b)); + } + + /* B(k,j)*A(j,i) */ + + template + auto operator^(const Tensor2_Expr &b, + const Tensor2_symmetric_Expr &a) + { + using TensorExpr + = Tensor2_symmetric_carat_Tensor2; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the ^ operator"); + + // Definition of Helper constexpr variables + constexpr char i = (i0 == i1 || i0 == j1) ? j0 : i0, + j = (i1 == i0 || i1 == j0) ? j1 : i1; + + return Tensor2_symmetric_Expr::V, Dim_0, + i, j>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_divide_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_divide_generic.hpp new file mode 100644 index 000000000..322528fd9 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_divide_generic.hpp @@ -0,0 +1,35 @@ +/* Divides a Tensor2_symmetric by a generic, yielding a + Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor2_symmetric_divide_generic + { + Tensor2_symmetric_Expr iterA; + U d; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) / d; + } + + Tensor2_symmetric_divide_generic( + const Tensor2_symmetric_Expr &a, const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim, i, j> + operator/(const Tensor2_symmetric_Expr &a, const U &d0) + { + using TensorExpr = Tensor2_symmetric_divide_generic; + return Tensor2_symmetric_Expr::V, Dim, + i, j>(TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2.hpp new file mode 100644 index 000000000..a8c43e5a1 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2.hpp @@ -0,0 +1,141 @@ +/* Subtracts a Tensor2 from a Tensor2_symmetric (or vice versa), + yielding a Tensor2. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor2_symmetric_minus_Tensor2 + {}; + + /* A(i,j)-B(i,j), A is symmetric, B is not. */ + + template + class Tensor2_symmetric_minus_Tensor2 + { + Tensor2_symmetric_Expr iterA; + Tensor2_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) - iterB(N1, N2); + } + + Tensor2_symmetric_minus_Tensor2( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j)-B(j,i), A is symmetric, B is not. */ + + template + class Tensor2_symmetric_minus_Tensor2 + { + Tensor2_symmetric_Expr iterA; + Tensor2_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) - iterB(N2, N1); + } + + Tensor2_symmetric_minus_Tensor2( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_Expr, + typename promote::V, Dim_0, Dim_0, i0, j0> + operator-(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_minus_Tensor2; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the - operator"); + return Tensor2_Expr::V, Dim_0, Dim_0, + i0, j0>(TensorExpr(a, b)); + } + + // TODO: Maybe we should consider moving the following functions to the space + // of Tensor2 for organization sake + /* B(i,j)-A(i,j), A is symmetric, B is not. */ + + /* Base Template */ + template + class Tensor2_minus_Tensor2_symmetric + {}; + + template + class Tensor2_minus_Tensor2_symmetric + { + Tensor2_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) - iterB(N1, N2); + } + + Tensor2_minus_Tensor2_symmetric( + const Tensor2_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* B(i,j)-A(j,i), A is symmetric, B is not. */ + + template + class Tensor2_minus_Tensor2_symmetric + { + Tensor2_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) - iterB(N2, N1); + } + + Tensor2_minus_Tensor2_symmetric( + const Tensor2_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_Expr, + typename promote::V, Dim0_0, Dim1_0, i0, j0> + operator-(const Tensor2_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor2_minus_Tensor2_symmetric; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the - operator"); + return Tensor2_Expr::V, Dim0_0, Dim1_0, + i0, j0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2_symmetric.hpp new file mode 100644 index 000000000..72ff4c8d9 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2_symmetric.hpp @@ -0,0 +1,75 @@ +/* Subtracts a Tensor2_symmetric from a Tensor2_symmetric, yielding a + Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor2_symmetric_minus_Tensor2_symmetric + {}; + + /* A(i,j) - B(i,j) */ + + template + class Tensor2_symmetric_minus_Tensor2_symmetric + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) - iterB(N1, N2); + } + + Tensor2_symmetric_minus_Tensor2_symmetric( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j) - B(j,i) */ + + template + class Tensor2_symmetric_minus_Tensor2_symmetric + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) - iterB(N1, N2); + } + + Tensor2_symmetric_minus_Tensor2_symmetric( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim_0, i0, j0> + operator-(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_minus_Tensor2_symmetric; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the - operator"); + return Tensor2_symmetric_Expr::V, Dim_0, + i0, j0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_minus_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_minus_generic.hpp new file mode 100644 index 000000000..acd7fbbda --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_minus_generic.hpp @@ -0,0 +1,35 @@ +/* Subtracts a generic from a Tensor2_symmetric, yielding a + Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor2_symmetric_minus_generic + { + const Tensor2_symmetric_Expr iterA; + const U d; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) - d; + } + + Tensor2_symmetric_minus_generic( + const Tensor2_symmetric_Expr &a, const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim, i, j> + operator-(const Tensor2_symmetric_Expr &a, const U &d0) + { + using TensorExpr = Tensor2_symmetric_minus_generic; + return Tensor2_symmetric_Expr::V, Dim, + i, j>(TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_mod_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_mod_Tensor2_symmetric.hpp new file mode 100644 index 000000000..4dcb8ae64 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_mod_Tensor2_symmetric.hpp @@ -0,0 +1,74 @@ +/* Divides a Tensor2_symmetric by a Tensor2_symmetric together but + don't contract, yielding a Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor2_symmetric_mod_Tensor2_symmetric + {}; + + /* A(i,j) % B(i,j) -> Tensor2_symmetric */ + + template + class Tensor2_symmetric_mod_Tensor2_symmetric + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) / iterB(N1, N2); + } + + Tensor2_symmetric_mod_Tensor2_symmetric( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j) % B(j,i) -> Tensor2_symmetric */ + + template + class Tensor2_symmetric_mod_Tensor2_symmetric + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) / iterB(N2, N1); + } + + Tensor2_symmetric_mod_Tensor2_symmetric( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim_0, i0, j0> + operator%(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_mod_Tensor2_symmetric; + static_assert(!std::is_empty::value, + "Index or Dimensions are not compatible with % operator"); + return Tensor2_symmetric_Expr::V, Dim_0, + i0, j0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2.hpp new file mode 100644 index 000000000..466162328 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2.hpp @@ -0,0 +1,95 @@ +/* Adds a Tensor2_symmetric to a Tensor2, yielding a Tensor2. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor2_symmetric_plus_Tensor2 + {}; + + /* A(i,j)+B(i,j), A is symmetric, B is not. */ + + template + class Tensor2_symmetric_plus_Tensor2 + { + Tensor2_symmetric_Expr iterA; + Tensor2_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) + iterB(N1, N2); + } + + Tensor2_symmetric_plus_Tensor2( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j)+B(j,i), A is symmetric, B is not. */ + + template + class Tensor2_symmetric_plus_Tensor2 + { + Tensor2_symmetric_Expr iterA; + Tensor2_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) + iterB(N2, N1); + } + + Tensor2_symmetric_plus_Tensor2( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_Expr, + typename promote::V, Dim_0, Dim_0, i0, j0> + operator+(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_plus_Tensor2; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the + operator"); + return Tensor2_Expr::V, Dim_0, Dim_0, + i0, j0>(TensorExpr(a, b)); + } + + // TODO We are not respecting operation order here. I suggest to use the same + // approach as in Tensor2_symmetric minus Tensor2 + /* B(i,j)+A(i,j), A is symmetric, B is not. */ + /* B(i,j)+A(j,i), A is symmetric, B is not. */ + + template + Tensor2_Expr, + typename promote::V, Dim_0, Dim_0, i0, j0> + operator+(const Tensor2_Expr &b, + const Tensor2_symmetric_Expr &a) + { + using TensorExpr + = Tensor2_symmetric_plus_Tensor2; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the + operator"); + return Tensor2_Expr::V, Dim_0, Dim_0, + i0, j0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2_symmetric.hpp new file mode 100644 index 000000000..ab011776a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2_symmetric.hpp @@ -0,0 +1,75 @@ +/* Adds a Tensor2_symmetric to a Tensor2_symmetric, yielding a + Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor2_symmetric_plus_Tensor2_symmetric + {}; + + /* A(i,j) + B(i,j) */ + + template + class Tensor2_symmetric_plus_Tensor2_symmetric + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) + iterB(N1, N2); + } + + Tensor2_symmetric_plus_Tensor2_symmetric( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j) + B(j,i) */ + + template + class Tensor2_symmetric_plus_Tensor2_symmetric + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return iterA(N1, N2) + iterB(N1, N2); + } + + Tensor2_symmetric_plus_Tensor2_symmetric( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim_0, i0, j0> + operator+(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_plus_Tensor2_symmetric; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the + operator"); + return Tensor2_symmetric_Expr::V, Dim_0, + i0, j0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_plus_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_plus_generic.hpp new file mode 100644 index 000000000..8bcbfd093 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_plus_generic.hpp @@ -0,0 +1,29 @@ +/* Adds a Tensor2_symmetric to a generic, yielding a + Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + template + auto operator+(const Tensor2_symmetric_Expr &a, const U &d0) + { + auto TensorExpr = [&a, d0](const int N1, const int N2) { + return a.operator()(N1, N2) + d0; + }; + return Tensor2_symmetric_Expr::V, Dim, i, j>( + TensorExpr); + } + + template + auto operator+(const U &d0, const Tensor2_symmetric_Expr &a) + { + auto TensorExpr = [&a, d0](const int N1, const int N2) { + return a.operator()(N1, N2) + d0; + }; + return Tensor2_symmetric_Expr::V, Dim, i, j>( + TensorExpr); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_pointer.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_pointer.hpp new file mode 100644 index 000000000..8923618a7 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_pointer.hpp @@ -0,0 +1,223 @@ +/* A version for pointers. */ + +#pragma once + +namespace FTensor +{ + template class Tensor2_symmetric + { + //mutable T *restrict data[(Tensor_Dim * (Tensor_Dim + 1)) / 2]; + mutable T *__restrict data[(Tensor_Dim * (Tensor_Dim + 1)) / 2]; + + public: + template Tensor2_symmetric(U *... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Tensor2_symmetric() {} + + /* There are two operator(int,int)'s, one for non-consts that lets you + change the value, and one for consts that doesn't. */ + + T &operator()(const int N1, const int N2) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim || N1 < 0 || N2 >= Tensor_Dim || N2 < 0) + { + std::stringstream s; + s << "Bad index in Tensor2_symmetric.operator(" << N1 << "," << N2 << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 ? *data[N1 + (N2 * (2 * Tensor_Dim - N2 - 1)) / 2] + : *data[N2 + (N1 * (2 * Tensor_Dim - N1 - 1)) / 2]; + } + + T operator()(const int N1, const int N2) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim || N1 < 0 || N2 >= Tensor_Dim || N2 < 0) + { + std::stringstream s; + s << "Bad index in Tensor2_symmetric.operator(" << N1 << "," << N2 << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 ? *data[N1 + (N2 * (2 * Tensor_Dim - N2 - 1)) / 2] + : *data[N2 + (N1 * (2 * Tensor_Dim - N1 - 1)) / 2]; + } + + T *ptr(const int N1, const int N2) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim || N1 < 0 || N2 >= Tensor_Dim || N2 < 0) + { + std::stringstream s; + s << "Bad index in Tensor2_symmetric.ptr(" + << N1 << "," << N2 << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 ? data[N1 + (N2 * (2 * Tensor_Dim - N2 - 1)) / 2] + : data[N2 + (N1 * (2 * Tensor_Dim - N1 - 1)) / 2]; + } + + /* These operator()'s are the first part in constructing template + expressions. They can be used to slice off lower dimensional + parts. They are not entirely safe, since you can accidentaly use a + higher dimension than what is really allowed (like Dim=5). */ + + /* This returns a Tensor2_Expr, since the indices are not really + symmetric anymore since they cover different dimensions. */ + + template + Tensor2_Expr, T, Dim0, Dim1, i, j> + operator()(const Index index1, const Index index2) + { + return Tensor2_Expr, T, Dim0, Dim1, i, + j>(*this); + } + + template + Tensor2_Expr, T, Dim0, Dim1, i, j> + operator()(const Index index1, const Index index2) const + { + return Tensor2_Expr, T, Dim0, + Dim1, i, j>(*this); + } + + /* This returns a Tensor2_symmetric_Expr, since the indices are still + symmetric on the lower dimensions. */ + + template + Tensor2_symmetric_Expr, T, Dim, i, j> + operator()(const Index index1, const Index index2) + { + return Tensor2_symmetric_Expr, T, Dim, + i, j>(*this); + } + + template + Tensor2_symmetric_Expr, T, Dim, i, + j> + operator()(const Index index1, const Index index2) const + { + return Tensor2_symmetric_Expr, + T, Dim, i, j>(*this); + } + + /* This is for expressions where a number is used for one slot, and + an index for another, yielding a Tensor1_Expr. The non-const + versions don't actually create a Tensor2_number_rhs_[01] object. + They create a Tensor1_Expr directly, which provides the + appropriate indexing operators. The const versions do create a + Tensor2_number_[01]. */ + + template + Tensor1_Expr, T, N>, + T, Dim, i> + operator()(const Index index1, const Number &n1) + { + using TensorExpr + = Tensor2_number_rhs_1, T, N>; + return Tensor1_Expr(*this); + } + + template + Tensor1_Expr< + const Tensor2_number_1, T, N>, + T, Dim, i> + operator()(const Index index1, const Number &n1) const + { + using TensorExpr + = Tensor2_number_1, T, N>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + Tensor1_Expr, T, N>, + T, Dim, i> + operator()(const Number &n1, const Index index1) + { + using TensorExpr + = Tensor2_number_rhs_0, T, N>; + return Tensor1_Expr(*this); + } + + template + Tensor1_Expr< + const Tensor2_number_0, T, N>, + T, Dim, i> + operator()(const Number &n1, const Index index1) const + { + using TensorExpr + = Tensor2_number_0, T, N>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Specializations for using actual numbers instead of Number<> */ + + template + Tensor1_Expr< + const Tensor2_numeral_1, T>, T, + Dim, i> + operator()(const Index index1, const int N) const + { + using TensorExpr + = Tensor2_numeral_1, T>; + return Tensor1_Expr(TensorExpr(*this, N)); + } + + template + Tensor1_Expr< + const Tensor2_numeral_0, T>, T, + Dim, i> + operator()(const int N, const Index index1) const + { + using TensorExpr + = Tensor2_numeral_0, T>; + return Tensor1_Expr(TensorExpr(*this, N)); + } + + /* The ++ operator increments the pointer, not the number that the + pointer points to. This allows iterating over a grid. */ + + const Tensor2_symmetric &operator++() const + { + for(int i = 0; i < (Tensor_Dim * (Tensor_Dim + 1)) / 2; ++i) + ++data[i]; + return *this; + } + + /* These two operator()'s return the Tensor2 with internal + contractions, yielding a T. I have to specify one for both + const and non-const because otherwise the compiler will use the + operator() which gives a Tensor2_Expr<>. */ + + template + T operator()(const Index index1, const Index index2) + { + return internal_contract(Number()); + } + + template + T operator()(const Index index1, const Index index2) const + { + return internal_contract(Number()); + } + + private: + template T internal_contract(Number) const + { + return *data[N - 1 + ((N - 1) * (2 * Tensor_Dim - N)) / 2] + + internal_contract(Number()); + } + + T internal_contract(Number<1>) const { return *data[0]; } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_Tensor1.hpp new file mode 100644 index 000000000..fc0d186e0 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_Tensor1.hpp @@ -0,0 +1,174 @@ +/* This file has all of the declarations for expressions like + Tensor2_symmetric*Tensor1 and Tensor1*Tensor2_symmetric, yielding a + Tensor1 or Dg. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j)*B(j) -> Tensor1 */ + + template + class Tensor2_symmetric_times_Tensor1_1 + { + Tensor2_symmetric_Expr iterA; + Tensor1_Expr iterB; + + template + typename promote::V + eval(const int N1, const Number &) const + { + return iterA(N1, Current_Dim - 1) * iterB(Current_Dim - 1) + + eval(N1, Number()); + } + typename promote::V eval(const int N1, const Number<1> &) const + { + return iterA(N1, 0) * iterB(0); + } + + public: + Tensor2_symmetric_times_Tensor1_1( + const Tensor2_symmetric_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor1_1; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* A(j,i)*B(j) -> Tensor1 */ + + template + class Tensor2_symmetric_times_Tensor1_0 + { + Tensor2_symmetric_Expr iterA; + Tensor1_Expr iterB; + + template + typename promote::V + eval(const int N1, const Number &) const + { + return iterA(Current_Dim - 1, N1) * iterB(Current_Dim - 1) + + eval(N1, Number()); + } + typename promote::V eval(const int N1, const Number<1> &) const + { + return iterA(0, N1) * iterB(0); + } + + public: + Tensor2_symmetric_times_Tensor1_0( + const Tensor2_symmetric_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number()); + } + }; + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor1_0; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* B(j)*A(i,j) -> Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Tensor1_Expr &b, + const Tensor2_symmetric_Expr &a) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor1_1; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* B(j)*A(j,i) -> Tensor1 */ + + template + Tensor1_Expr, + typename promote::V, Dim, i> + operator*(const Tensor1_Expr &b, + const Tensor2_symmetric_Expr &a) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor1_0; + return Tensor1_Expr::V, Dim, i>( + TensorExpr(a, b)); + } + + /* A(i,j)*B(k) -> Dg */ + + template + class Tensor2_symmetric_times_Tensor1 + { + Tensor2_symmetric_Expr iterA; + Tensor1_Expr iterB; + + public: + Tensor2_symmetric_times_Tensor1( + const Tensor2_symmetric_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2) * iterB(N3); + } + }; + + template + Dg_Expr, + typename promote::V, Dim, Dim2, i, j, k> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor1; + return Dg_Expr::V, Dim, Dim2, i, j, k>( + TensorExpr(a, b)); + } + + /* B(k)*A(i,j) -> Dg */ + + template + Dg_Expr, + typename promote::V, Dim, Dim2, i, j, k> + operator*(const Tensor1_Expr &b, + const Tensor2_symmetric_Expr &a) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor1; + return Dg_Expr::V, Dim, Dim2, i, j, k>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_Tensor2.hpp new file mode 100644 index 000000000..21e30c4a5 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_Tensor2.hpp @@ -0,0 +1,386 @@ +/* This file has all of the declarations for + Tensor2_symmetric*Tensor2. This includes the double + contraction A(i,j)*B(i,j) (yielding a double) as well as the more + complicated single contraction A(i,j)*B(j,k) (yielding a Tensor2 + expression). */ + +#pragma once + +namespace FTensor +{ + /* Double contraction. */ + + /* A(i,j)*B(i,j) */ + + template + typename promote::V + T2s_times_T2_01(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b, + const Number &, const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1) + * b(Current_Dim0 - 1, Current_Dim1 - 1) + + T2s_times_T2_01(a, b, Number(), + Number()); + } + + template + typename promote::V + T2s_times_T2_01(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b, + const Number<1> &, const Number &) + { + return a(0, Current_Dim1 - 1) * b(0, Current_Dim1 - 1) + + T2s_times_T2_01(a, b, Number(), Number()); + } + + template + typename promote::V + T2s_times_T2_01(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b, + const Number<1> &, const Number<1> &) + { + return a(0, 0) * b(0, 0); + } + + template + typename promote::V + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + { + return T2s_times_T2_01(a, b, Number(), Number()); + } + + /* B(i,j)*A(i,j) */ + + template + typename promote::V + operator*(const Tensor2_Expr &b, + const Tensor2_symmetric_Expr &a) + + { + return T2s_times_T2_01(a, b, Number(), Number()); + } + + /* Double contraction with switched indices. The perspicacious reader + will note that it just replicated code for the aligned indices case + above, but with B(i,j) -> B(j,i). This is ok, since A is + symmetric. */ + + /* A(i,j)*B(j,i) */ + + template + typename promote::V + T2s_times_T2_01(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b, + const Number &, const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1) + * b(Current_Dim0 - 1, Current_Dim1 - 1) + + T2s_times_T2_01(a, b, Number(), + Number()); + } + + template + typename promote::V + T2s_times_T2_01(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b, + const Number<1> &, const Number &) + { + return a(0, Current_Dim1 - 1) * b(0, Current_Dim1 - 1) + + T2s_times_T2_01(a, b, Number(), Number()); + } + + template + typename promote::V + T2s_times_T2_01(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b, + const Number<1> &, const Number<1> &) + { + return a(0, 0) * b(0, 0); + } + + template + typename promote::V + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + { + return T2s_times_T2_01(a, b, Number(), Number()); + } + + /* B(j,i)*A(i,j) */ + + template + typename promote::V + operator*(const Tensor2_Expr &b, + const Tensor2_symmetric_Expr &a) + + { + return T2s_times_T2_01(a, b, Number(), Number()); + } + + /* Single contraction. The wrapper class has a different name for + each possible placing of the indices (e.g. A(i,j)*B(j,k) has the + number 10 because the contraction indices are on the second and + first slots (counting from 0). */ + + /* A(i,j)*B(j,k) */ + + template + class Tensor2_symmetric_times_Tensor2_10 + { + Tensor2_symmetric_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1) * iterB(Current_Dim - 1, N2) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0) * iterB(0, N2); + } + + public: + Tensor2_symmetric_times_Tensor2_10( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_10, + typename promote::V, Dim, Dim1, i, k> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_10; + return Tensor2_Expr::V, Dim, Dim1, i, k>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(i,j) */ + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_10, + typename promote::V, Dim, Dim1, i, k> + operator*(const Tensor2_Expr &b, + const Tensor2_symmetric_Expr &a) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_10; + return Tensor2_Expr::V, Dim, Dim1, i, k>( + TensorExpr(a, b)); + } + + /* A(i,j)*B(k,j) */ + + template + class Tensor2_symmetric_times_Tensor2_11 + { + Tensor2_symmetric_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1) * iterB(N2, Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0) * iterB(N2, 0); + } + + public: + Tensor2_symmetric_times_Tensor2_11( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_11, + typename promote::V, Dim, Dim1, i, k> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_11; + return Tensor2_Expr::V, Dim, Dim1, i, k>( + TensorExpr(a, b)); + } + + /* B(k,j)*A(i,j) */ + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_11, + typename promote::V, Dim, Dim1, i, k> + operator*(const Tensor2_Expr &b, + const Tensor2_symmetric_Expr &a) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_11; + return Tensor2_Expr::V, Dim, Dim1, i, k>( + TensorExpr(a, b)); + } + + /* A(j,i)*B(j,k) */ + + template + class Tensor2_symmetric_times_Tensor2_00 + { + Tensor2_symmetric_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(Current_Dim - 1, N1) * iterB(Current_Dim - 1, N2) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(0, N1) * iterB(0, N2); + } + + public: + Tensor2_symmetric_times_Tensor2_00( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_00, + typename promote::V, Dim, Dim1, i, k> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_00; + return Tensor2_Expr::V, Dim, Dim1, i, k>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(j,i) */ + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_00, + typename promote::V, Dim, Dim1, i, k> + operator*(const Tensor2_Expr &b, + const Tensor2_symmetric_Expr &a) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_00; + return Tensor2_Expr::V, Dim, Dim1, i, k>( + TensorExpr(a, b)); + } + + /* A(j,i)*B(k,j) */ + + template + class Tensor2_symmetric_times_Tensor2_01 + { + Tensor2_symmetric_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(Current_Dim - 1, N1) * iterB(N2, Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(0, N1) * iterB(N2, 0); + } + + public: + Tensor2_symmetric_times_Tensor2_01( + const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_01, + typename promote::V, Dim, Dim1, i, k> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_01; + return Tensor2_Expr::V, Dim, Dim1, i, k>( + TensorExpr(a, b)); + } + + /* B(k,j)*A(j,i) */ + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_01, + typename promote::V, Dim, Dim1, i, k> + operator*(const Tensor2_Expr &b, + const Tensor2_symmetric_Expr &a) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_01; + return Tensor2_Expr::V, Dim, Dim1, i, k>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_Tensor2_symmetric.hpp new file mode 100644 index 000000000..ed5278e9c --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_Tensor2_symmetric.hpp @@ -0,0 +1,326 @@ +/* This file has all of the declarations for + Tensor2_symmetric*Tensor2_symmetric. This includes the double + contraction A(i,j)*B(i,j) (yielding a typename promote::V) as well as + the more complicated single contraction A(i,j)*B(j,k) (yielding a Tensor2 + expression), and no contractions A(i,j)*B(k,l) -> Ddg */ + +#pragma once + +namespace FTensor +{ + /* Double contraction. */ + + /* A(i,j)*B(i,j) */ + + template + typename promote::V + T2s_times_T2s(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b, + const Number &, const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1) + * b(Current_Dim0 - 1, Current_Dim1 - 1) + + T2s_times_T2s(a, b, Number(), + Number()); + } + + template + typename promote::V + T2s_times_T2s(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b, + const Number<1> &, const Number &) + { + return a(0, Current_Dim1 - 1) * b(0, Current_Dim1 - 1) + + T2s_times_T2s(a, b, Number(), Number()); + } + + template + typename promote::V + T2s_times_T2s(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b, + const Number<1> &, const Number<1> &) + { + return a(0, 0) * b(0, 0); + } + + template + typename promote::V + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + { + return T2s_times_T2s(a, b, Number(), Number()); + } + + /* A(i,j)*B(j,i) */ + + template + typename promote::V + T2s_times_switched_T2s(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b, + const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1) + * b(Current_Dim1 - 1, Current_Dim0 - 1) + + T2s_times_switched_T2s(a, b, Number(), + Number()); + } + + template + typename promote::V + T2s_times_switched_T2s(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b, + const Number<1> &, const Number &) + { + return a(0, Current_Dim1 - 1) * b(Current_Dim1 - 1, 0) + + T2s_times_switched_T2s(a, b, Number(), + Number()); + } + + template + typename promote::V + T2s_times_switched_T2s(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b, + const Number<1> &, const Number<1> &) + { + return a(0, 0) * b(0, 0); + } + + template + typename promote::V + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + { + return T2s_times_switched_T2s(a, b, Number(), Number()); + } + + /* Single contraction. The wrapper class has a different name for + each possible placing of the indices (e.g. A(i,j)*B(j,k) has the + number 10 because the contraction indices are on the second and + first slots (counting from 0). */ + + /* A(i,j)*B(j,k) */ + + template + class Tensor2_symmetric_times_Tensor2_symmetric_10 + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1) * iterB(Current_Dim - 1, N2) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0) * iterB(0, N2); + } + + public: + Tensor2_symmetric_times_Tensor2_symmetric_10( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_symmetric_10, + typename promote::V, Dim, Dim, i, k> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_symmetric_10; + return Tensor2_Expr::V, Dim, Dim, i, k>( + TensorExpr(a, b)); + } + + /* A(i,j)*B(k,j) */ + + template + class Tensor2_symmetric_times_Tensor2_symmetric_11 + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1) * iterB(N2, Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0) * iterB(N2, 0); + } + + public: + Tensor2_symmetric_times_Tensor2_symmetric_11( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_symmetric_11, + typename promote::V, Dim, Dim, i, k> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_symmetric_11; + return Tensor2_Expr::V, Dim, Dim, i, k>( + TensorExpr(a, b)); + } + + /* A(j,i)*B(j,k) */ + + template + class Tensor2_symmetric_times_Tensor2_symmetric_00 + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(Current_Dim - 1, N1) * iterB(Current_Dim - 1, N2) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(0, N1) * iterB(0, N2); + } + + public: + Tensor2_symmetric_times_Tensor2_symmetric_00( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_symmetric_00, + typename promote::V, Dim, Dim, i, k> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_symmetric_00; + return Tensor2_Expr::V, Dim, Dim, i, k>( + TensorExpr(a, b)); + } + + /* A(j,i)*B(k,j) */ + + template + class Tensor2_symmetric_times_Tensor2_symmetric_01 + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(Current_Dim - 1, N1) * iterB(N2, Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(0, N1) * iterB(N2, 0); + } + + public: + Tensor2_symmetric_times_Tensor2_symmetric_01( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr< + Tensor2_symmetric_times_Tensor2_symmetric_01, + typename promote::V, Dim, Dim, i, k> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_symmetric_01; + return Tensor2_Expr::V, Dim, Dim, i, k>( + TensorExpr(a, b)); + } + + /* A(i,j)*B(k,l) -> Ddg */ + + template + class Tensor2_symmetric_times_Tensor2_symmetric + { + Tensor2_symmetric_Expr iterA; + Tensor2_symmetric_Expr iterB; + + public: + Tensor2_symmetric_times_Tensor2_symmetric( + const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2) * iterB(N3, N4); + } + }; + /* + template + Ddg_Expr, + typename promote::V, Dim0, Dim1, i, j, k, l> + operator*(const Tensor2_symmetric_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor2_symmetric_times_Tensor2_symmetric; + return Ddg_Expr::V, Dim0, Dim1, i, j, k, + l>(TensorExpr(a, b)); + }*/ +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_generic.hpp new file mode 100644 index 000000000..205246d5a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_times_generic.hpp @@ -0,0 +1,29 @@ +/* Multiplies a Tensor2_symmetric with a generic, yielding a + Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + template + auto operator*(const Tensor2_symmetric_Expr &a, const U &d0) + { + auto TensorExpr = [&a, d0](const int N1, const int N2) { + return a.operator()(N1, N2) * d0; + }; + return Tensor2_symmetric_Expr::V, Dim, i, j>( + TensorExpr); + } + + template + auto operator*(const U &d0, const Tensor2_symmetric_Expr &a) + { + auto TensorExpr = [&a, d0](const int N1, const int N2) { + return d0 * a.operator()(N1, N2); + }; + return Tensor2_symmetric_Expr::V, Dim, i, j>( + TensorExpr); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_value.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_value.hpp new file mode 100644 index 000000000..6779d301e --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/Tensor2_symmetric_value.hpp @@ -0,0 +1,310 @@ +#pragma once + +/* A general version, not for pointers. */ + +#include +#include "floatarrayf.h" + + +#ifdef FTENSOR_DEBUG +#include +#include +#endif + +namespace FTensor +{ + template class Tensor2_symmetric + { + protected: + T data[(Tensor_Dim * (Tensor_Dim + 1)) / 2]; + + public: + template Tensor2_symmetric(U... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Tensor2_symmetric() {} + + /* There are two operator(int,int)'s, one for non-consts that lets you + change the value, and one for consts that doesn't. */ + + T &operator()(const int N1, const int N2) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim || N1 < 0 || N2 >= Tensor_Dim || N2 < 0) + { + std::stringstream s; + s << "Bad index in Tensor2_symmetric.operator(" << N1 << "," << N2 << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 ? data[N1 + (N2 * (2 * Tensor_Dim - N2 - 1)) / 2] + : data[N2 + (N1 * (2 * Tensor_Dim - N1 - 1)) / 2]; + } + + T operator()(const int N1, const int N2) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim || N1 < 0 || N2 >= Tensor_Dim || N2 < 0) + { + std::stringstream s; + s << "Bad index in Tensor2_symmetric.operator(" << N1 << "," << N2 << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N1 > N2 ? data[N1 + (N2 * (2 * Tensor_Dim - N2 - 1)) / 2] + : data[N2 + (N1 * (2 * Tensor_Dim - N1 - 1)) / 2]; + } + + /* These operator()'s are the first part in constructing template + expressions. They can be used to slice off lower dimensional + parts. They are not entirely safe, since you can accidentaly use a + higher dimension than what is really allowed (like Dim=5). */ + + /* This returns a Tensor2_Expr, since the indices are not really + symmetric anymore since they cover different dimensions. */ + + template + typename std::enable_if< + (Tensor_Dim >= Dim0 && Tensor_Dim >= Dim1), + Tensor2_Expr, T, Dim0, Dim1, i, j>>::type + operator()(const Index, const Index) + { + return Tensor2_Expr, T, Dim0, Dim1, i, + j>(*this); + } + + template + typename std::enable_if<(Tensor_Dim >= Dim0 && Tensor_Dim >= Dim1), + Tensor2_Expr, + T, Dim0, Dim1, i, j>>::type + operator()(const Index, const Index) const + { + return Tensor2_Expr, T, Dim0, + Dim1, i, j>(*this); + } + + /* This returns a Tensor2_symmetric_Expr, since the indices are still + symmetric on the lower dimensions. */ + + template + typename std::enable_if< + (Tensor_Dim >= Dim), + Tensor2_symmetric_Expr, T, Dim, i, j>>::type + operator()(const Index, const Index) + { + return Tensor2_symmetric_Expr, T, Dim, + i, j>(*this); + } + + template + typename std::enable_if< + (Tensor_Dim >= Dim), + Tensor2_symmetric_Expr, T, Dim, i, + j>>::type + operator()(const Index, const Index) const + { + return Tensor2_symmetric_Expr, T, + Dim, i, j>(*this); + } + + /* This is for expressions where a number is used for one slot, and + an index for another, yielding a Tensor1_Expr. The non-const + versions don't actually create a Tensor2_number_rhs_[01] object. + They create a Tensor1_Expr directly, which provides the + appropriate indexing operators. The const versions do create a + Tensor2_number_[01]. */ + + template + typename std::enable_if< + (Tensor_Dim >= Dim && Tensor_Dim > N), + Tensor1_Expr, T, N>, + T, Dim, i>>::type + operator()(const Index, const Number &) + { + using TensorExpr + = Tensor2_number_rhs_1, T, N>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim >= Dim && Tensor_Dim > N), + Tensor1_Expr, T, N>, + T, Dim, i>>::type + operator()(const Index, const Number &) const + { + using TensorExpr + = Tensor2_number_1, T, N>; + return Tensor1_Expr(TensorExpr(*this)); + } + + template + typename std::enable_if< + (Tensor_Dim > N && Tensor_Dim >= Dim), + Tensor1_Expr, T, N>, + T, Dim, i>>::type + operator()(const Number &, const Index) + { + using TensorExpr + = Tensor2_number_rhs_0, T, N>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim > N && Tensor_Dim >= Dim), + Tensor1_Expr, T, N>, + T, Dim, i>>::type + operator()(const Number &, const Index) const + { + using TensorExpr + = Tensor2_number_0, T, N>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Specializations for using actual numbers instead of Number<> */ + + template + typename std::enable_if< + (Tensor_Dim >= Dim), + Tensor1_Expr, T>, + T, Dim, i>>::type + operator()(const Index, const int N) const + { + using TensorExpr + = Tensor2_numeral_1, T>; + return Tensor1_Expr(TensorExpr(*this, N)); + } + + template + typename std::enable_if< + (Tensor_Dim >= Dim), + Tensor1_Expr, T>, + T, Dim, i>>::type + operator()(const int N, const Index) const + { + using TensorExpr + = Tensor2_numeral_0, T>; + return Tensor1_Expr(TensorExpr(*this, N)); + } + + /* These two operator()'s return the Tensor2 with internal + contractions, yielding a T. I have to specify one for both + const and non-const because otherwise the compiler will use the + operator() which gives a Tensor2_Expr<>. */ + + template + typename std::enable_if<(Tensor_Dim >= Dim), T>::type + operator()(const Index, const Index) + { + return internal_contract(Number()); + } + + template + typename std::enable_if<(Tensor_Dim >= Dim), T>::type + operator()(const Index, const Index) const + { + return internal_contract(Number()); + } + + private: + template T internal_contract(const Number &) const + { + return data[N - 1 + ((N - 1) * (2 * Tensor_Dim - N)) / 2] + + internal_contract(Number()); + } + + T internal_contract(const Number<1> &) const { return data[0]; } + }; + +} + +/// JSON compatible output. It only outputs unique elements, so a 3x3 +/// symmetric matrix only outputs 6 elements. + +namespace FTensor +{ + template + std::ostream &Tensor2_symmetric_ostream_row( + std::ostream &os, const FTensor::Tensor2_symmetric &t, + const int &i) + { + os << '['; + for(int j = i; j + 1 < Tensor_Dim; ++j) + { + os << t(i, j) << ','; + } + if(Tensor_Dim > 0) + { + os << t(i, Tensor_Dim - 1); + } + os << ']'; + return os; + } +} + +template +std::ostream &operator<<(std::ostream &os, + const FTensor::Tensor2_symmetric &t) +{ + os << '['; + for(int i = 0; i + 1 < Tensor_Dim; ++i) + { + FTensor::Tensor2_symmetric_ostream_row(os, t, i); + os << ','; + } + if(Tensor_Dim > 0) + { + FTensor::Tensor2_symmetric_ostream_row(os, t, Tensor_Dim - 1); + } + os << ']'; + return os; +} + +namespace FTensor +{ + template + std::istream & + Tensor2_symmetric_istream_row(std::istream &is, + FTensor::Tensor2_symmetric &t, + const int &i) + { + char c; + is >> c; + for(int j = i; j + 1 < Tensor_Dim; ++j) + { + is >> t(i, j) >> c; + } + if(Tensor_Dim > 0) + { + is >> t(i, Tensor_Dim - 1); + } + is >> c; + return is; + } +} + +template +std::istream & +operator>>(std::istream &is, FTensor::Tensor2_symmetric &t) +{ + char c; + is >> c; + for(int i = 0; i + 1 < Tensor_Dim; ++i) + { + FTensor::Tensor2_symmetric_istream_row(is, t, i); + is >> c; + } + if(Tensor_Dim > 0) + { + FTensor::Tensor2_symmetric_istream_row(is, t, Tensor_Dim - 1); + } + is >> c; + return is; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/dTensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/dTensor2_symmetric.hpp new file mode 100644 index 000000000..0e871bd80 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/dTensor2_symmetric.hpp @@ -0,0 +1,39 @@ +/* Takes a derivative of a Tensor2_symmetric, yielding a Dg. */ + +#pragma once + +namespace FTensor +{ + template + class dTensor2_symmetric + { + const Tensor2_symmetric &a; + const Tensor1 &d_ijk; + const Tensor1 &d_xyz; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return (*(a.ptr(N1, N2) + d_ijk(N3)) - *(a.ptr(N1, N2) - d_ijk(N3))) + * d_xyz(N3) * 0.5; + } + dTensor2_symmetric(const Tensor2_symmetric &A, + const Tensor1 &D_ijk, + const Tensor1 &D_xyz) + : a(A), d_ijk(D_ijk), d_xyz(D_xyz) + {} + }; + + template + const Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + d(const Tensor2_symmetric &a, const Index index1, + const Index index2, const Index index3, + const Tensor1 &d_ijk, const Tensor1 &d_xyz) + { + using TensorExpr = dTensor2_symmetric; + return Dg_Expr::V, Dim01, Dim2, i, + j, k>(TensorExpr(a, d_ijk, d_xyz)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/d_boundary_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/d_boundary_Tensor2_symmetric.hpp new file mode 100644 index 000000000..3c04b5eaf --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/d_boundary_Tensor2_symmetric.hpp @@ -0,0 +1,50 @@ +/* Takes a derivative of a Tensor2_symmetric, yielding a Dg. + This is mostly useful near boundaries where you might have to take + one-sided derivatives. */ + +#pragma once + +namespace FTensor +{ + template + class d_boundary_Tensor2_symmetric + { + const Tensor2_symmetric &a; + const Tensor1 &d_ijk; + const Tensor1 &d_xyz; + const Tensor2 &boundary; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return boundary(N3, 0) + ? (*(a.ptr(N1, N2) + d_ijk(N3)) - a(N1, N2)) * d_xyz(N3) + : (boundary(N3, 1) + ? (a(N1, N2) - *(a.ptr(N1, N2) - d_ijk(N3))) * d_xyz(N3) + : (*(a.ptr(N1, N2) + d_ijk(N3)) + - *(a.ptr(N1, N2) - d_ijk(N3))) + * d_xyz(N3) * 0.5); + } + d_boundary_Tensor2_symmetric(const Tensor2_symmetric &A, + const Tensor1 &D_ijk, + const Tensor1 &D_xyz, + const Tensor2 &Boundary) + : a(A), d_ijk(D_ijk), d_xyz(D_xyz), boundary(Boundary) + {} + }; + + template + const Dg_Expr, + typename promote::V, Dim01, Dim2, i, j, k> + d_boundary(const Tensor2_symmetric &a, + const Index index1, const Index index2, + const Index index3, const Tensor1 &d_ijk, + const Tensor1 &d_xyz, + const Tensor2 &boundary) + { + using TensorExpr = d_boundary_Tensor2_symmetric; + return Dg_Expr::V, Dim01, Dim2, i, + j, k>(TensorExpr(a, d_ijk, d_xyz, boundary)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/d_one_sided_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/d_one_sided_Tensor2_symmetric.hpp new file mode 100644 index 000000000..bfa5345ca --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/d_one_sided_Tensor2_symmetric.hpp @@ -0,0 +1,45 @@ +/* Takes a one-sided derivative of a Tensor2_symmetric in a particular + direction, yielding a Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + template + class d_one_sided_Tensor2_symmetric + { + const Tensor2_symmetric &a; + const int di, dj, dk; + const double dx, dy, dz; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return axis == 0 + ? (a(N1, N2) - *(a.ptr(N1, N2) - di)) * dx + : (axis == 1 ? (a(N1, N2) - *(a.ptr(N1, N2) - dj)) * dy + : (a(N1, N2) - *(a.ptr(N1, N2) - dk)) * dz); + } + d_one_sided_Tensor2_symmetric(const Tensor2_symmetric &A, + const int Di, const int Dj, const int Dk, + const double Dx, const double Dy, + const double Dz) + : a(A), di(Di), dj(Dj), dk(Dk), dx(Dx), dy(Dy), dz(Dz) + {} + }; + + template + const Tensor2_symmetric_Expr< + const d_one_sided_Tensor2_symmetric, + typename promote::V, Dim, i, j> + d_one_sided(const Tensor2_symmetric &a, const Number n1, + const Index index1, const Index index2, + const int &di, const int &dj, const int &dk, const double &dx, + const double &dy, const double &dz) + { + using TensorExpr = d_one_sided_Tensor2_symmetric; + return Tensor2_symmetric_Expr::V, + Dim, i, j>( + TensorExpr(a, di, dj, dk, dx, dy, dz)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/ddTensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/ddTensor2_symmetric.hpp new file mode 100644 index 000000000..ef46dd9bf --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/ddTensor2_symmetric.hpp @@ -0,0 +1,47 @@ +/* Takes a second derivative of a Tensor2_symmetric, yielding a + Ddg. */ + +#pragma once + +namespace FTensor +{ + template + class ddTensor2_symmetric + { + const Tensor2_symmetric &a; + const Tensor1 &d_ijk; + const Tensor1 &d_xyz; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return N3 == N4 ? (*(a.ptr(N1, N2) + d_ijk(N3)) - 2 * a(N1, N2) + + *(a.ptr(N1, N2) - d_ijk(N3))) + * d_xyz(N3) * d_xyz(N3) + : (*(a.ptr(N1, N2) + d_ijk(N3) + d_ijk(N4)) + - *(a.ptr(N1, N2) - d_ijk(N3) + d_ijk(N4)) + - *(a.ptr(N1, N2) + d_ijk(N3) - d_ijk(N4)) + + *(a.ptr(N1, N2) - d_ijk(N3) - d_ijk(N4))) + * d_xyz(N3) * d_xyz(N4) * 0.25; + } + ddTensor2_symmetric(const Tensor2_symmetric &A, + const Tensor1 &D_ijk, + const Tensor1 &D_xyz) + : a(A), d_ijk(D_ijk), d_xyz(D_xyz) + {} + }; + /* + template + const Ddg_Expr, + typename promote::V, Dim01, Dim23, i, j, k, l> + dd(const Tensor2_symmetric &a, const Index index1, + const Index index2, const Index index3, + const Index index4, const Tensor1 &d_ijk, + const Tensor1 &d_xyz) + { + using Tensor_Expr = ddTensor2_symmetric; + return Ddg_Expr::V, Dim01, Dim23, + i, j, k, l>(Tensor_Expr(a, d_ijk, d_xyz)); + }*/ +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/dd_boundary_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/dd_boundary_Tensor2_symmetric.hpp new file mode 100644 index 000000000..7a9b5293e --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/dd_boundary_Tensor2_symmetric.hpp @@ -0,0 +1,112 @@ +/* Takes a second derivative of a Tensor2_symmetric, yielding a + Ddg. This is mostly useful near boundaries where you might + have to take one-sided derivatives. */ + +#pragma once + +namespace FTensor +{ + template + class dd_boundary_Tensor2_symmetric + { + const Tensor2_symmetric &a; + const Tensor1 &d_ijk; + const Tensor1 &d_xyz; + const Tensor2 &boundary; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return N3 == N4 + ? (boundary(N3, 0) + ? (*(a.ptr(N1, N2) + 2 * d_ijk(N3)) + - 2 * *(a.ptr(N1, N2) + d_ijk(N3)) + a(N1, N2)) + : (boundary(N3, 1) + ? (a(N1, N2) - 2 * *(a.ptr(N1, N2) - d_ijk(N3)) + + *(a.ptr(N1, N2) - 2 * d_ijk(N3))) + : (*(a.ptr(N1, N2) + d_ijk(N3)) - 2 * a(N1, N2) + + *(a.ptr(N1, N2) - d_ijk(N3))))) + * d_xyz(N3) * d_xyz(N3) + : (boundary(N3, 0) + ? (boundary(N4, 0) + ? ((*(a.ptr(N1, N2) + d_ijk(N3) + d_ijk(N4)) + - *(a.ptr(N1, N2) + d_ijk(N4)) + - *(a.ptr(N1, N2) + d_ijk(N3)) + a(N1, N2)) + * d_xyz(N3) * d_xyz(N4)) + : (boundary(N4, 1) + ? ((*(a.ptr(N1, N2) + d_ijk(N3)) - a(N1, N2) + - *(a.ptr(N1, N2) + d_ijk(N3) - d_ijk(N4)) + + *(a.ptr(N1, N2) - d_ijk(N4))) + * d_xyz(N3) * d_xyz(N4)) + : (*(a.ptr(N1, N2) + d_ijk(N3) + d_ijk(N4)) + - *(a.ptr(N1, N2) + d_ijk(N4)) + - *(a.ptr(N1, N2) + d_ijk(N3) - d_ijk(N4)) + + *(a.ptr(N1, N2) - d_ijk(N4))) + * d_xyz(N3) * d_xyz(N4) * 0.5)) + : (boundary(N3, 1) + ? (boundary(N4, 0) + ? ((*(a.ptr(N1, N2) + d_ijk(N4)) + - *(a.ptr(N1, N2) - d_ijk(N3) + d_ijk(N4)) + - a(N1, N2) + *(a.ptr(N1, N2) - d_ijk(N3))) + * d_xyz(N3) * d_xyz(N4)) + : (boundary(N4, 1) + ? ((a(N1, N2) - *(a.ptr(N1, N2) - d_ijk(N3)) + - *(a.ptr(N1, N2) - d_ijk(N4)) + + *(a.ptr(N1, N2) - d_ijk(N3) + - d_ijk(N4))) + * d_xyz(N3) * d_xyz(N4)) + : (*(a.ptr(N1, N2) + d_ijk(N4)) + - *(a.ptr(N1, N2) - d_ijk(N3) + d_ijk(N4)) + - *(a.ptr(N1, N2) - d_ijk(N4)) + + *(a.ptr(N1, N2) - d_ijk(N3) + - d_ijk(N4))) + * d_xyz(N3) * d_xyz(N4) * 0.5)) + : (boundary(N4, 0) + ? ((*(a.ptr(N1, N2) + d_ijk(N3) + d_ijk(N4)) + - *(a.ptr(N1, N2) - d_ijk(N3) + d_ijk(N4)) + - *(a.ptr(N1, N2) + d_ijk(N3)) + + *(a.ptr(N1, N2) - d_ijk(N3))) + * d_xyz(N3) * d_xyz(N4) * 0.5) + : (boundary(N4, 1) + ? ((*(a.ptr(N1, N2) + d_ijk(N3)) + - *(a.ptr(N1, N2) - d_ijk(N3)) + - *(a.ptr(N1, N2) + d_ijk(N3) + - d_ijk(N4)) + + *(a.ptr(N1, N2) - d_ijk(N3) + - d_ijk(N4))) + * d_xyz(N3) * d_xyz(N4) * 0.5) + : ((*(a.ptr(N1, N2) + d_ijk(N3) + d_ijk(N4)) + - *(a.ptr(N1, N2) - d_ijk(N3) + + d_ijk(N4)) + - *(a.ptr(N1, N2) + d_ijk(N3) + - d_ijk(N4)) + + *(a.ptr(N1, N2) - d_ijk(N3) + - d_ijk(N4))) + * d_xyz(N3) * d_xyz(N4) * 0.25))))); + } + dd_boundary_Tensor2_symmetric(const Tensor2_symmetric &A, + const Tensor1 &D_ijk, + const Tensor1 &D_xyz, + const Tensor2 &Boundary) + : a(A), d_ijk(D_ijk), d_xyz(D_xyz), boundary(Boundary) + {} + }; + /* + template + const Ddg_Expr< + const dd_boundary_Tensor2_symmetric, + typename promote::V, Dim01, Dim23, i, j, k, l> + dd_boundary(const Tensor2_symmetric &a, + const Index index1, const Index index2, + const Index index3, const Index index4, + const Tensor1 &d_ijk, + const Tensor1 &d_xyz, + const Tensor2 &boundary) + { + using Tensor_Expr + = dd_boundary_Tensor2_symmetric; + return Ddg_Expr::V, Dim01, Dim23, + i, j, k, l>(Tensor_Expr(a, d_ijk, d_xyz, boundary)); + }*/ +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/diffusion_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/diffusion_Tensor2_symmetric.hpp new file mode 100644 index 000000000..d9febd15d --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/diffusion_Tensor2_symmetric.hpp @@ -0,0 +1,50 @@ +/* Computes 2*del^2 of a Tensor2_symmetric but uses diagonal + derivatives for half of it. Yields a Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + template class diffusion_Tensor2_symmetric + { + const Tensor2_symmetric &a; + const int di, dj, dk; + const double dx; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return ((*(a.ptr(N1, N2) + di) - 2 * a(N1, N2) + *(a.ptr(N1, N2) - di)) + + (*(a.ptr(N1, N2) + dj) - 2 * a(N1, N2) + *(a.ptr(N1, N2) - dj)) + + (*(a.ptr(N1, N2) + dk) - 2 * a(N1, N2) + *(a.ptr(N1, N2) - dk)) + + ((*(a.ptr(N1, N2) + di + dj) + *(a.ptr(N1, N2) + di - dj) + + *(a.ptr(N1, N2) - di + dj) + *(a.ptr(N1, N2) - di - dj) + - 4 * a(N1, N2)) + + (*(a.ptr(N1, N2) + di + dk) + *(a.ptr(N1, N2) + di - dk) + + *(a.ptr(N1, N2) - di + dk) + *(a.ptr(N1, N2) - di - dk) + - 4 * a(N1, N2)) + + (*(a.ptr(N1, N2) + dj + dk) + *(a.ptr(N1, N2) + dj - dk) + + *(a.ptr(N1, N2) - dj + dk) + *(a.ptr(N1, N2) - dj - dk) + - 4 * a(N1, N2))) + / (std::sqrt(2.0))) + * dx * dx; + } + diffusion_Tensor2_symmetric(const Tensor2_symmetric &A, + const int Di, const int Dj, const int Dk, + const double Dx) + : a(A), di(Di), dj(Dj), dk(Dk), dx(Dx) + {} + }; + + template + const Tensor2_symmetric_Expr, + typename promote::V, Dim, i, j> + diffusion(const Tensor2_symmetric &a, const Index index1, + const Index index2, const int &di, const int &dj, + const int &dk, const double &dx) + { + using Tensor_Expr = diffusion_Tensor2_symmetric; + return Tensor2_symmetric_Expr::V, + Dim, i, j>(Tensor_Expr(a, di, dj, dk, dx)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/generic_minus_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/generic_minus_Tensor2_symmetric.hpp new file mode 100644 index 000000000..b35d9112f --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/generic_minus_Tensor2_symmetric.hpp @@ -0,0 +1,34 @@ +/* Subtracts a generic from a Tensor2_symmetric, yielding a + Tensor2_symmetric. */ + +#pragma once + +namespace FTensor +{ + template + class generic_minus_Tensor2_symmetric + { + Tensor2_symmetric_Expr iterA; + U d; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return d - iterA(N1, N2); + } + generic_minus_Tensor2_symmetric( + const Tensor2_symmetric_Expr &a, const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor2_symmetric_Expr, + typename promote::V, Dim, i, j> + operator-(const U &d0, const Tensor2_symmetric_Expr &a) + { + using TensorExpr = generic_minus_Tensor2_symmetric; + return Tensor2_symmetric_Expr::V, Dim, + i, j>(TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/interpolate_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/interpolate_Tensor2_symmetric.hpp new file mode 100644 index 000000000..71f4b0132 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/interpolate_Tensor2_symmetric.hpp @@ -0,0 +1,65 @@ +/* Interpolates to (i0+distance[0], j0+distance[1], k0+distance[2]) + yielding a Tensor2_symmetric. (i0,j0,k0) are 3D array coordinates, + conjugate==1-distance, and (di,dj,dk) are the stride of the array + coordinates. It is assumed that the Tensor2_symmetric is zero + centered. */ + +#pragma once + +namespace FTensor +{ + template + class interpolate_Tensor2_symmetric + { + const Tensor2_symmetric &a; + const int di, dj, dk, i0, j0, k0; + const double *distance, *conjugate; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return conjugate[0] * conjugate[1] * conjugate[2] + * (*(a.ptr(N1, N2) + di * i0 + dj * j0 + dk * k0)) + + distance[0] * conjugate[1] * conjugate[2] + * (*(a.ptr(N1, N2) + di * (i0 + 1) + dj * (j0) + dk * (k0))) + + conjugate[0] * distance[1] * conjugate[2] + * (*(a.ptr(N1, N2) + di * (i0) + dj * (j0 + 1) + dk * (k0))) + + distance[0] * distance[1] * conjugate[2] + * (*(a.ptr(N1, N2) + di * (i0 + 1) + dj * (j0 + 1) + + dk * (k0))) + + conjugate[0] * conjugate[1] * distance[2] + * (*(a.ptr(N1, N2) + di * (i0) + dj * (j0) + dk * (k0 + 1))) + + distance[0] * conjugate[1] * distance[2] + * (*(a.ptr(N1, N2) + di * (i0 + 1) + dj * (j0) + + dk * (k0 + 1))) + + conjugate[0] * distance[1] * distance[2] + * (*(a.ptr(N1, N2) + di * (i0) + dj * (j0 + 1) + + dk * (k0 + 1))) + + distance[0] * distance[1] * distance[2] + * (*(a.ptr(N1, N2) + di * (i0 + 1) + dj * (j0 + 1) + + dk * (k0 + 1))); + } + interpolate_Tensor2_symmetric(const Tensor2_symmetric &A, + const int Di, const int Dj, const int Dk, + const int I0, const int J0, const int K0, + const double Distance[3], + const double Conjugate[3]) + : a(A), di(Di), dj(Dj), dk(Dk), i0(I0), j0(J0), k0(K0), + distance(Distance), conjugate(Conjugate) + {} + }; + + template + const Tensor2_symmetric_Expr, + typename promote::V, Dim, i, j> + interpolate(const Tensor2_symmetric &a, const Index index1, + const Index index2, const int &di, const int &dj, + const int &dk, const int &i0, const int &j0, const int &k0, + const double distance[3], const double conjugate[3]) + { + using Tensor_Expr = interpolate_Tensor2_symmetric; + return Tensor2_symmetric_Expr::V, + Dim, i, j>( + Tensor_Expr(a, di, dj, dk, i0, j0, k0, distance, conjugate)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor2_symmetric/minus_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/minus_Tensor2_symmetric.hpp new file mode 100644 index 000000000..8537c6e51 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor2_symmetric/minus_Tensor2_symmetric.hpp @@ -0,0 +1,27 @@ +/* Unary minus operator. */ + +#pragma once + +namespace FTensor +{ + template + class minus_Tensor2_symmetric + { + public: + Tensor2_symmetric_Expr iterA; + + public: + T operator()(const int N1, const int N2) const { return -iterA(N1, N2); } + minus_Tensor2_symmetric(const Tensor2_symmetric_Expr &a) + : iterA(a) + {} + }; + + template + Tensor2_symmetric_Expr, T, Dim, i, j> + operator-(const Tensor2_symmetric_Expr &a) + { + using TensorExpr = minus_Tensor2_symmetric; + return Tensor2_symmetric_Expr(TensorExpr(a)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3.hpp b/src/oofemlib/tensor/FTensor/Tensor3.hpp new file mode 100644 index 000000000..bc9a407ce --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3.hpp @@ -0,0 +1,10 @@ +/* Declarations for a Tensor3. */ + +#include "Tensor3/Tensor3_number.hpp" +#include "Tensor3/Tensor3_numeral.hpp" + +#include "Tensor3/Tensor3_value.hpp" + +#include "Tensor3/Tensor3_Expr.hpp" + +#include "Tensor3/Tensor3_contracted.hpp" diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_Expr.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_Expr.hpp new file mode 100644 index 000000000..16333a2c8 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_Expr.hpp @@ -0,0 +1,101 @@ +/* Declare a wrapper class for generic rank 3 Tensor expressions. + There isn't a Tensor3 class yet. I only use Tensor3_Expr as an + intermediate expression which immediately get contracted with + something to make a Tensor2 or Tensor1. */ + +#pragma once + +#include "Tensor3_minus_Tensor3.hpp" +#include "Tensor3_or_Tensor3.hpp" +#include "Tensor3_plus_Tensor3.hpp" +#include "Tensor3_times_Dg.hpp" +#include "Tensor3_times_Tensor1.hpp" +#include "Tensor3_times_Tensor2.hpp" +#include "Tensor3_times_Tensor2_symmetric.hpp" +#include "Tensor3_times_Tensor3.hpp" +#include "Tensor3_times_generic.hpp" + +namespace FTensor +{ + template + class Tensor3_Expr + { + A iter; + + public: + Tensor3_Expr(const A &a) : iter(a) {} + T operator()(const int N1, const int N2, const int N3) const + { + return iter(N1, N2, N3); + } + }; + + template + class Tensor3_Expr, T, + Dim0, Dim1, Dim2, i, j, k> + { + Tensor3 &iter; + + public: + Tensor3_Expr(Tensor3 &a) + : iter(a) + {} + T &operator()(const int N1, const int N2, const int N3) + { + return iter(N1, N2, N3); + } + T operator()(const int N1, const int N2, const int N3) const + { + return iter(N1, N2, N3); + } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + auto & + equals(const Tensor3_Expr &rhs) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + for(int kk = 0; kk < Dim2; ++kk) + { + iter(ii, jj, kk) = permute(*this, rhs, ii, jj, kk); + } + return *this; + } + + template + auto &operator=( + const Tensor3_Expr &rhs) + { + return equals(rhs); + } + + auto &operator=( + const Tensor3_Expr, T, + Dim0, Dim1, Dim2, i, j, k> &rhs) + { + return equals(rhs); + } + + template + Tensor3_Expr, T, Dim0, + Dim1, Dim2, i, j, k> & + operator=(const U &u) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + for(int kk = 0; kk < Dim2; ++kk) + { + iter(ii, jj, kk) = u; + } + return *this; + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_contracted.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_contracted.hpp new file mode 100644 index 000000000..837904318 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_contracted.hpp @@ -0,0 +1,64 @@ +/* A helper class that automatically returns the internal contraction + of a rank 3 tensor. */ + +#pragma once + +namespace FTensor +{ + /* Contracts second and third indices. */ + + template class Tensor3_contracted_12 + { + A iterA; + + template + T eval(const int N, const Number &) const + { + return iterA(N, Current_Dim - 1, Current_Dim - 1) + + eval(N, Number()); + } + T eval(const int N, const Number<1> &) const { return iterA(N, 0, 0); } + + public: + T operator()(const int N) const { return eval(N, Number()); } + Tensor3_contracted_12(const A &a) : iterA(a) {} + }; + + /* Contracts first and third indices. */ + + template class Tensor3_contracted_02 + { + A iterA; + + template + T eval(const int N, const Number &) const + { + return iterA(Current_Dim - 1, N, Current_Dim - 1) + + eval(N, Number()); + } + T eval(const int N, const Number<1> &) const { return iterA(0, N, 0); } + + public: + T operator()(const int N) const { return eval(N, Number()); } + Tensor3_contracted_02(const A &a) : iterA(a) {} + }; + + /* Contracts first and second indices. */ + + template class Tensor3_contracted_01 + { + A iterA; + + template + T eval(const int N, const Number &) const + { + return iterA(Current_Dim - 1, Current_Dim - 1, N) + + eval(N, Number()); + } + T eval(const int N, const Number<1> &) const { return iterA(0, 0, N); } + + public: + T operator()(const int N) const { return eval(N, Number()); } + Tensor3_contracted_01(const A &a) : iterA(a) {} + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_minus_Tensor3.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_minus_Tensor3.hpp new file mode 100644 index 000000000..bf93ef614 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_minus_Tensor3.hpp @@ -0,0 +1,176 @@ +/* Subtracts a Tensor3 from a Tensor3, yielding a Tensor3. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor3_minus_Tensor3 + {}; + + /* A(i,j,k)-B(i,j,k)->Tensor3 */ + + template + class Tensor3_minus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) - iterB(N1, N2, N3); + } + + Tensor3_minus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k)-B(i,k,j)->Tensor3 */ + + template + class Tensor3_minus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) - iterB(N1, N3, N2); + } + + Tensor3_minus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k)-B(j,i,k)->Tensor3 */ + + template + class Tensor3_minus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) - iterB(N2, N1, N3); + } + + Tensor3_minus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k)-B(j,k,i)->Tensor3 */ + + template + class Tensor3_minus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) - iterB(N2, N3, N1); + } + + Tensor3_minus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k)-B(k,i,j)->Tensor3 */ + + template + class Tensor3_minus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) - iterB(N3, N1, N2); + } + + Tensor3_minus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k)-B(k,j,i)->Tensor3 */ + + template + class Tensor3_minus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) - iterB(N3, N2, N1); + } + + Tensor3_minus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor3_Expr, + typename promote::V, Dim0_0, Dim1_0, Dim2_0, i0, j0, k0> + operator-(const Tensor3_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor3_minus_Tensor3; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the - operator"); + return Tensor3_Expr::V, Dim0_0, Dim1_0, + Dim2_0, i0, j0, k0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_number.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_number.hpp new file mode 100644 index 000000000..070175718 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_number.hpp @@ -0,0 +1,92 @@ +/* This is for expressions where a number is used for one or two + slots, and an index for the others, yielding a Tensor1_Expr or + Tensor2_Expr. */ + +#pragma once + +namespace FTensor +{ + /* First slot. */ + + template class Tensor3_number_0 + { + A iterA; + + public: + T operator()(const int N1, const int N2) const { return iterA(N, N1, N2); } + Tensor3_number_0(const A &a) : iterA(a) {} + }; + + template class Tensor3_number_rhs_0 + {}; + + /* Second slot. */ + + template class Tensor3_number_1 + { + A iterA; + + public: + T operator()(const int N1, const int N2) const { return iterA(N1, N, N2); } + Tensor3_number_1(const A &a) : iterA(a) {} + }; + + template class Tensor3_number_rhs_1 + {}; + + /* Third slot. */ + + template class Tensor3_number_2 + { + A iterA; + + public: + T operator()(const int N1, const int N2) const { return iterA(N1, N2, N); } + Tensor3_number_2(const A &a) : iterA(a) {} + }; + + template class Tensor3_number_rhs_2 + {}; + + /* First and second slot. */ + + template class Tensor3_number_01 + { + A iterA; + + public: + T operator()(const int N) const { return iterA(N1, N2, N); } + Tensor3_number_01(const A &a) : iterA(a) {} + }; + + template class Tensor3_number_rhs_01 + {}; + + /* First and third slot. */ + + template class Tensor3_number_02 + { + A iterA; + + public: + T operator()(const int N) const { return iterA(N1, N, N2); } + Tensor3_number_02(const A &a) : iterA(a) {} + }; + + template class Tensor3_number_rhs_02 + {}; + + /* Second and third slot. */ + + template class Tensor3_number_12 + { + A iterA; + + public: + T operator()(const int N) const { return iterA(N, N1, N2); } + Tensor3_number_12(const A &a) : iterA(a) {} + }; + + template class Tensor3_number_rhs_12 + {}; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_numeral.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_numeral.hpp new file mode 100644 index 000000000..42e39029f --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_numeral.hpp @@ -0,0 +1,60 @@ +/* This is for expressions where a number is used for one or two + slots, and an index for the others, yielding a Tensor1_Expr or + Tensor2_Expr. */ + +#pragma once + +namespace FTensor +{ + /* First or second slot. */ + + template class Tensor3_numeral_0 + { + A iterA; + int N; + + public: + T operator()(const int N1, const int N2) const { return iterA(N, N1, N2); } + Tensor3_numeral_0(const A &a, const int NN) : iterA(a), N(NN) {} + }; + + /* Third slot. */ + + template class Tensor3_numeral_2 + { + A iterA; + int N; + + public: + T operator()(const int N1, const int N2) const { return iterA(N1, N2, N); } + Tensor3_numeral_2(const A &a, const int NN) : iterA(a), N(NN) {} + }; + + /* Second and third slot (or first and third slot). */ + + template class Tensor3_numeral_12 + { + A iterA; + int N1, N2; + + public: + T operator()(const int N) const { return iterA(N, N1, N2); } + Tensor3_numeral_12(const A &a, const int NN1, const int NN2) + : iterA(a), N1(NN1), N2(NN2) + {} + }; + + /* First and second slot. */ + + template class Tensor3_numeral_01 + { + A iterA; + int N1, N2; + + public: + T operator()(const int N) const { return iterA(N1, N2, N); } + Tensor3_numeral_01(const A &a, const int NN1, const int NN2) + : iterA(a), N1(NN1), N2(NN2) + {} + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_or_Tensor3.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_or_Tensor3.hpp new file mode 100644 index 000000000..b701f25ce --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_or_Tensor3.hpp @@ -0,0 +1,82 @@ +/* Adds a Tensor3 to a Tensor3, yielding a Dg. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor3_or_Tensor3 + {}; + + /* A(i,j,k)+B(i,k,j)->Dg */ + + template + class Tensor3_or_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N3, N1, N2) + iterB(N3, N2, N1); + } + + Tensor3_or_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k)+B(k,j,i)->Dg */ + + template + class Tensor3_or_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N3, N2) + iterB(N2, N3, N1); + } + + Tensor3_or_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + auto + operator||(const Tensor3_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor3_or_Tensor3; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the || operator"); + + // Definition of Helper constexpr variables + constexpr char i = (i0 == i1) ? j0 : i0, j = (i0 == i1) ? i0 : j0; + + return Dg_Expr::V, Dim0_0, Dim1_0, i, + k0, j>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_plus_Tensor3.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_plus_Tensor3.hpp new file mode 100644 index 000000000..c3cbfcaef --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_plus_Tensor3.hpp @@ -0,0 +1,176 @@ +/* Adds a Tensor3 to a Tensor3, yielding a Tensor3. */ + +#pragma once + +namespace FTensor +{ + /* Base Template */ + template + class Tensor3_plus_Tensor3 + {}; + + /* A(i,j,k)+B(i,j,k)->Tensor3 */ + + template + class Tensor3_plus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) + iterB(N1, N2, N3); + } + + Tensor3_plus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k)+B(i,k,j)->Tensor3 */ + + template + class Tensor3_plus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) + iterB(N1, N3, N2); + } + + Tensor3_plus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k)+B(j,i,k)->Tensor3 */ + + template + class Tensor3_plus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) + iterB(N2, N1, N3); + } + + Tensor3_plus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k)+B(j,k,i)->Tensor3 */ + + template + class Tensor3_plus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) + iterB(N2, N3, N1); + } + + Tensor3_plus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k)+B(k,i,j)->Tensor3 */ + + template + class Tensor3_plus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) + iterB(N3, N1, N2); + } + + Tensor3_plus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + /* A(i,j,k)+B(k,j,i)->Tensor3 */ + + template + class Tensor3_plus_Tensor3 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) + iterB(N3, N2, N1); + } + + Tensor3_plus_Tensor3( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor3_Expr, + typename promote::V, Dim0_0, Dim1_0, Dim2_0, i0, j0, k0> + operator+(const Tensor3_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor3_plus_Tensor3; + static_assert( + !std::is_empty::value, + "Indexes or Dimensions are not compatible with the + operator"); + return Tensor3_Expr::V, Dim0_0, Dim1_0, + Dim2_0, i0, j0, k0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Dg.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Dg.hpp new file mode 100644 index 000000000..27fdf10ab --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Dg.hpp @@ -0,0 +1,506 @@ +/* Contracts a Tensor3 with a Dg, yielding a typename promote::V, + Tensor2, or Tensor4. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)*B(i,j,k) */ + + template + typename promote::V + T3_times_T3dg_012(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + + T3_times_T3dg_012(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_012(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim0 - 1, 0, Current_Dim2 - 1) + + T3_times_T3dg_012(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_012(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(Current_Dim0 - 1, 0, 0) + + T3_times_T3dg_012(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_012(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Dg_Expr &b) + { + return T3_times_T3dg_012(a, b, Number(), Number(), + Number()); + } + + /* A(i,j,k)*B(k,i,j) */ + + template + typename promote::V + T3_times_T3dg_201(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim2 - 1, Current_Dim0 - 1, Current_Dim1 - 1) + + T3_times_T3dg_201(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_201(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim2 - 1, Current_Dim0 - 1, 0) + + T3_times_T3dg_201(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_201(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(0, Current_Dim0 - 1, 0) + + T3_times_T3dg_201(a, b, Number(), + Number(), Number()); + } + + template + typename promote::V + T3_times_T3dg_201(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Dg_Expr &b) + { + return T3_times_T3dg_201(a, b, Number(), Number(), + Number()); + } + + /* A(i,j,k)*B(j,k,i) */ + + template + typename promote::V + T3_times_T3dg_120(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim1 - 1, Current_Dim2 - 1, Current_Dim0 - 1) + + T3_times_T3dg_120(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_120(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(0, Current_Dim2 - 1, Current_Dim0 - 1) + + T3_times_T3dg_120(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_120(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(0, 0, Current_Dim0 - 1) + + T3_times_T3dg_120(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_120(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Dg_Expr &b) + { + return T3_times_T3dg_120(a, b, Number(), Number(), + Number()); + } + + /* A(i,j,k)*B(j,i,k) */ + + template + typename promote::V + T3_times_T3dg_102(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim1 - 1, Current_Dim0 - 1, Current_Dim2 - 1) + + T3_times_T3dg_102(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_102(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(0, Current_Dim0 - 1, Current_Dim2 - 1) + + T3_times_T3dg_102(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_102(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(0, Current_Dim0 - 1, 0) + + T3_times_T3dg_102(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_102(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Dg_Expr &b) + { + return T3_times_T3dg_102(a, b, Number(), Number(), + Number()); + } + + /* A(i,j,k)*B(k,j,i) */ + + template + typename promote::V + T3_times_T3dg_210(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim2 - 1, Current_Dim1 - 1, Current_Dim0 - 1) + + T3_times_T3dg_210(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_210(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim2 - 1, 0, Current_Dim0 - 1) + + T3_times_T3dg_210(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_210(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(0, 0, Current_Dim0 - 1) + + T3_times_T3dg_210(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_210(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Dg_Expr &b) + { + return T3_times_T3dg_210(a, b, Number(), Number(), + Number()); + } + + /* A(i,j,k)*B(i,k,j) */ + + template + typename promote::V + T3_times_T3dg_021(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim0 - 1, Current_Dim2 - 1, Current_Dim1 - 1) + + T3_times_T3dg_021(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_021(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim0 - 1, Current_Dim2 - 1, 0) + + T3_times_T3dg_021(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3dg_021(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(Current_Dim0 - 1, 0, 0) + + T3_times_T3dg_021(a, b, Number(), + Number(), Number()); + } + + template + typename promote::V + T3_times_T3dg_021(const Tensor3_Expr &a, + const Dg_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Dg_Expr &b) + { + return T3_times_T3dg_021(a, b, Number(), Number(), + Number()); + } + + /* A(j,i,k)*B(k,l,j) */ + + template + class Tensor3_times_Dg_02_20 + { + Tensor3_Expr iterA; + Dg_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, Current_Dim1 - 1) + * iterB(Current_Dim1 - 1, N2, Current_Dim0 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(0, N1, Current_Dim1 - 1) * iterB(Current_Dim1 - 1, N2, 0) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, 0) * iterB(0, N2, 0); + } + + public: + Tensor3_times_Dg_02_20( + const Tensor3_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim1, Dim01, i, l> + operator*(const Tensor3_Expr &a, + const Dg_Expr &b) + { + using TensorExpr + = Tensor3_times_Dg_02_20; + return Tensor2_Expr::V, Dim1, Dim01, i, + l>(TensorExpr(a, b)); + } + + /* B(k,l,j)*A(j,i,k) */ + + /* A(i,j,k)*B(l,k,m) -> Tensor4 */ + + template + class Tensor3_times_Dg + { + Tensor3_Expr iterA; + Dg_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const int N3, const int N4, + const Number &) const + { + return iterA(N1, N2, Current_Dim - 1) * iterB(N3, Current_Dim - 1, N4) + + eval(N1, N2, N3, N4, Number()); + } + typename promote::V eval(const int N1, const int N2, const int N3, + const int N4, const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(N3, 0, N4); + } + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return eval(N1, N2, N3, N4, Number()); + } + Tensor3_times_Dg(const Tensor3_Expr &a, + const Dg_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor4_Expr< + Tensor3_times_Dg, + typename promote::V, Dim0, Dim1, Dim, Dim2, i, j, l, m> + operator*(const Tensor3_Expr &a, + const Dg_Expr &b) + { + using TensorExpr + = Tensor3_times_Dg; + return Tensor4_Expr::V, Dim0, Dim1, Dim, + Dim2, i, j, l, m>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor1.hpp new file mode 100644 index 000000000..2a6d04831 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor1.hpp @@ -0,0 +1,192 @@ +/* Declarations for expressions like Tensor3*Tensor1 -> Tensor2 */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)*B(j) -> Tensor2 */ + + template + class Tensor3_times_Tensor1_1 + { + Tensor3_Expr iterA; + Tensor1_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, Current_Dim - 1, N2) * iterB(Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, 0, N2) * iterB(0); + } + + public: + Tensor3_times_Tensor1_1( + const Tensor3_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim2, i, k> + operator*(const Tensor3_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor1_1; + return Tensor2_Expr::V, Dim0, Dim2, i, + k>(TensorExpr(a, b)); + } + + /* B(j)*A(i,j,k) -> Tensor2 */ + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim2, i, k> + operator*(const Tensor1_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr + = Tensor3_times_Tensor1_1; + return Tensor2_Expr::V, Dim0, Dim2, i, + k>(TensorExpr(a, b)); + } + + /* A(i,j,k)*B(i) -> Tensor2 */ + + template + class Tensor3_times_Tensor1_0 + { + Tensor3_Expr iterA; + Tensor1_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(Current_Dim - 1, N1, N2) * iterB(Current_Dim - 1) + + eval(N1, N2, Number()); + } + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(0, N1, N2) * iterB(0); + } + + public: + Tensor3_times_Tensor1_0( + const Tensor3_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim1, Dim2, j, k> + operator*(const Tensor3_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor1_0; + return Tensor2_Expr::V, Dim1, Dim2, j, + k>(TensorExpr(a, b)); + } + + /* B(i)*A(i,j,k) -> Tensor2 */ + + template + Tensor2_Expr, + typename promote::V, Dim1, Dim2, j, k> + operator*(const Tensor1_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr + = Tensor3_times_Tensor1_0; + return Tensor2_Expr::V, Dim1, Dim2, j, + k>(TensorExpr(a, b)); + } + + /* A(i,j,k)*B(k) -> Tensor2 */ + + template + class Tensor3_times_Tensor1_2 + { + Tensor3_Expr iterA; + Tensor1_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &) const + { + return iterA(N1, N2, CurrentDim - 1) * iterB(CurrentDim - 1) + + eval(N1, N2, Number()); + }; + typename promote::V + eval(const int N1, const int N2, const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(0); + }; + + public: + Tensor3_times_Tensor1_2( + const Tensor3_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number()); + } + }; + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim1, i, j> + operator*(const Tensor3_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor1_2; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, b)); + }; + + /* A(i,j,k)*B(k) -> Tensor2 */ + + template + Tensor2_Expr, + typename promote::V, Dim0, Dim1, i, j> + operator*(const Tensor1_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr + = Tensor3_times_Tensor1_2; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, b)); + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor2.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor2.hpp new file mode 100644 index 000000000..6518ef99e --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor2.hpp @@ -0,0 +1,561 @@ +// This file has all of the declarations for expressions like Tensor3*Tensor2 +// and Tensor2*Tensor3, yielding a Tensor3 or Tensor1. + +#pragma once + +#include "../permute.hpp" + +namespace FTensor +{ + // A(i,j,k) * B(l,m) double contraction + template + class Tensor3_times_Tensor2_double + { + Tensor3_Expr iterA; + Tensor2_Expr iterB; + + public: + Tensor3_times_Tensor2_double( + const Tensor3_Expr &Itera, + const Tensor2_Expr &Iterb) + : iterA(Itera), iterB(Iterb) + {} + typename promote::V operator()(const int N1) const + { + typename promote::V result(0); + + for(int xx = 0; xx < DimX; ++xx) + for(int yy = 0; yy < DimY; ++yy) + { + result += Permutation3().eval(iterA, N1, + xx, yy) + * Permutation2().eval(iterB, xx, yy); + } + return result; + } + }; + + // A(i,j,k)*B(j,k) + template + auto operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor2_double; + return Tensor1_Expr::V, Dim0, i>( + TensorExpr(a, b)); + } + + // B(j,k)*A(i,j,k) + template + auto operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + return a * b; + } + + // A(i,j,k)*B(k,j) + template + auto operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor2_double; + return Tensor1_Expr::V, Dim0, i>( + TensorExpr(a, b)); + } + + // B(k,j)*A(i,j,k) + template + auto operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + return a * b; + } + + // A(i,j,k)*B(i,k) + template + auto operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor2_double; + return Tensor1_Expr::V, Dim1, j>( + TensorExpr(a, b)); + } + + // A(i,j,k)*B(i,k) + template + auto operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + return a * b; + } + + // A(i,j,k)*B(k,i) + template + auto operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor2_double; + return Tensor1_Expr::V, Dim1, j>( + TensorExpr(a, b)); + } + + // B(k,i)*A(i,j,k) + template + auto operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + return a * b; + } + + // A(i,j,k)*B(i,j) + template + auto operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor2_double; + return Tensor1_Expr::V, Dim2, k>( + TensorExpr(a, b)); + } + + // B(i,j)*A(i,j,k) + template + auto operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + return a * b; + } + + // A(i,j,k)*B(j,i) + template + auto operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor2_double; + return Tensor1_Expr::V, Dim2, k>( + TensorExpr(a, b)); + } + + // B(j,i)*A(i,j,k) + template + auto operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + return a * b; + } + + /* A(i,j,k)*B(k,l)->Tensor3 */ + + template + class Tensor3_times_Tensor2_2_01 + { + Tensor3_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, N2, Current_Dim - 1) * iterB(Current_Dim - 1, N3) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(0, N3); + } + + public: + Tensor3_times_Tensor2_2_01( + const Tensor3_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Tensor3_Expr< + Tensor3_times_Tensor2_2_01, + typename promote::V, Dim0, Dim1, Dim3, i, j, l> + operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Tensor3_times_Tensor2_2_01; + return Tensor3_Expr::V, Dim0, Dim1, + Dim3, i, j, l>(TensorExpr(a, b)); + } + + /* B(k,l)*A(i,j,k)->Tensor3 */ + + template + Tensor3_Expr< + Tensor3_times_Tensor2_2_01, + typename promote::V, Dim0, Dim1, Dim3, i, j, l> + operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr = Tensor3_times_Tensor2_2_01; + return Tensor3_Expr::V, Dim0, Dim1, + Dim3, i, j, l>(TensorExpr(a, b)); + } + + /* A(i,j,k)*B(l,k)->Tensor3 */ + + template + class Tensor3_times_Tensor2_2_10 + { + Tensor3_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, N2, Current_Dim - 1) * iterB(N3, Current_Dim - 1) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(N3, 0); + } + + public: + Tensor3_times_Tensor2_2_10( + const Tensor3_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Tensor3_Expr< + Tensor3_times_Tensor2_2_10, + typename promote::V, Dim0, Dim1, Dim3, i, j, l> + operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Tensor3_times_Tensor2_2_10; + return Tensor3_Expr::V, Dim0, Dim1, + Dim3, i, j, l>(TensorExpr(a, b)); + } + + /* B(l,k)*A(i,j,k)->Tensor3 */ + + template + Tensor3_Expr< + Tensor3_times_Tensor2_2_10, + typename promote::V, Dim0, Dim1, Dim3, i, j, l> + operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr = Tensor3_times_Tensor2_2_10; + return Tensor3_Expr::V, Dim0, Dim1, + Dim3, i, j, l>(TensorExpr(a, b)); + } + + /* A(i,j,l)*B(j,k)->Tensor3 */ + + template + class Tensor3_times_Tensor2_1_01 + { + Tensor3_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, Current_Dim - 1, N3) * iterB(Current_Dim - 1, N2) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, 0, N3) * iterB(0, N2); + } + + public: + Tensor3_times_Tensor2_1_01( + const Tensor3_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Tensor3_Expr< + Tensor3_times_Tensor2_1_01, + typename promote::V, Dim0, Dim2, Dim3, i, k, l> + operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Tensor3_times_Tensor2_1_01; + return Tensor3_Expr::V, Dim0, Dim2, + Dim3, i, k, l>(TensorExpr(a, b)); + } + + /* B(j,k)*A(i,j,l)->Tensor3 */ + + template + Tensor3_Expr< + Tensor3_times_Tensor2_1_01, + typename promote::V, Dim0, Dim2, Dim3, i, k, l> + operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr = Tensor3_times_Tensor2_1_01; + return Tensor3_Expr::V, Dim0, Dim2, + Dim3, i, k, l>(TensorExpr(a, b)); + } + + /* A(i,j,l)*B(k,j)->Tensor3 */ + + template + class Tensor3_times_Tensor2_1_10 + { + Tensor3_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(N1, Current_Dim - 1, N3) * iterB(N2, Current_Dim - 1) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(N1, 0, N3) * iterB(N2, 0); + } + + public: + Tensor3_times_Tensor2_1_10( + const Tensor3_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Tensor3_Expr< + Tensor3_times_Tensor2_1_10, + typename promote::V, Dim0, Dim2, Dim3, i, k, l> + operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Tensor3_times_Tensor2_1_10; + return Tensor3_Expr::V, Dim0, Dim2, + Dim3, i, k, l>(TensorExpr(a, b)); + } + + /* B(k,j)*A(i,j,l)->Tensor3 */ + + template + Tensor3_Expr< + Tensor3_times_Tensor2_1_10, + typename promote::V, Dim0, Dim2, Dim3, i, k, l> + operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr = Tensor3_times_Tensor2_1_10; + return Tensor3_Expr::V, Dim0, Dim2, + Dim3, i, k, l>(TensorExpr(a, b)); + } + + /* A(i,k,l)*B(i,j)->Tensor3 */ + + template + class Tensor3_times_Tensor2_0_01 + { + Tensor3_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(Current_Dim - 1, N2, N3) * iterB(Current_Dim - 1, N1) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(0, N2, N3) * iterB(0, N1); + } + + public: + Tensor3_times_Tensor2_0_01( + const Tensor3_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Tensor3_Expr< + Tensor3_times_Tensor2_0_01, + typename promote::V, Dim1, Dim2, Dim3, j, k, l> + operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Tensor3_times_Tensor2_0_01; + return Tensor3_Expr::V, Dim1, Dim2, + Dim3, j, k, l>(TensorExpr(a, b)); + } + + /* B(i,j)*A(i,k,l)->Tensor3 */ + + template + Tensor3_Expr< + Tensor3_times_Tensor2_0_01, + typename promote::V, Dim1, Dim2, Dim3, j, k, l> + operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr = Tensor3_times_Tensor2_0_01; + return Tensor3_Expr::V, Dim1, Dim2, + Dim3, j, k, l>(TensorExpr(a, b)); + } + + /* A(i,k,l)*B(j,i)->Tensor3 */ + + template + class Tensor3_times_Tensor2_0_10 + { + Tensor3_Expr iterA; + Tensor2_Expr iterB; + + template + typename promote::V eval(const int N1, const int N2, const int N3, + const Number &) const + { + return iterA(Current_Dim - 1, N2, N3) * iterB(N1, Current_Dim - 1) + + eval(N1, N2, N3, Number()); + } + typename promote::V + eval(const int N1, const int N2, const int N3, const Number<1> &) const + { + return iterA(0, N2, N3) * iterB(N1, 0); + } + + public: + Tensor3_times_Tensor2_0_10( + const Tensor3_Expr &a, + const Tensor2_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return eval(N1, N2, N3, Number()); + } + }; + + template + Tensor3_Expr< + Tensor3_times_Tensor2_0_10, + typename promote::V, Dim1, Dim2, Dim3, j, k, l> + operator*(const Tensor3_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr = Tensor3_times_Tensor2_0_10; + return Tensor3_Expr::V, Dim1, Dim2, + Dim3, j, k, l>(TensorExpr(a, b)); + } + + /* B(j,i)*A(i,k,l)->Tensor3 */ + + template + Tensor3_Expr< + Tensor3_times_Tensor2_0_10, + typename promote::V, Dim1, Dim2, Dim3, j, k, l> + operator*(const Tensor2_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr = Tensor3_times_Tensor2_0_10; + return Tensor3_Expr::V, Dim1, Dim2, + Dim3, j, k, l>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor2_symmetric.hpp new file mode 100644 index 000000000..c40817713 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor2_symmetric.hpp @@ -0,0 +1,224 @@ +/* This file has all of the declarations for expressions like + Tensor3*Tensor2_symmetric and Tensor2_symmetric*Tensor3, yielding a + Tensor1. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)*B(j,k)->Tensor1 */ + + template + class Tensor3_times_Tensor2_symmetric_12 + { + Tensor3_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(N1, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(N1, 0, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(N1, 0, 0) * iterB(0, 0); + } + + public: + Tensor3_times_Tensor2_symmetric_12( + const Tensor3_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr< + Tensor3_times_Tensor2_symmetric_12, + typename promote::V, Dim0, i> + operator*(const Tensor3_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor2_symmetric_12; + return Tensor1_Expr::V, Dim0, i>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(i,j,k)->Tensor1 */ + + template + Tensor1_Expr< + Tensor3_times_Tensor2_symmetric_12, + typename promote::V, Dim0, i> + operator*(const Tensor2_symmetric_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr + = Tensor3_times_Tensor2_symmetric_12; + return Tensor1_Expr::V, Dim0, i>( + TensorExpr(a, b)); + } + + /* A(j,i,k)*B(j,k)->Tensor1 */ + + template + class Tensor3_times_Tensor2_symmetric_02 + { + Tensor3_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(0, N1, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, 0) * iterB(0, 0); + } + + public: + Tensor3_times_Tensor2_symmetric_02( + const Tensor3_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr< + Tensor3_times_Tensor2_symmetric_02, + typename promote::V, Dim1, i> + operator*(const Tensor3_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor2_symmetric_02; + return Tensor1_Expr::V, Dim1, i>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(j,i,k)->Tensor1 */ + + template + Tensor1_Expr< + Tensor3_times_Tensor2_symmetric_02, + typename promote::V, Dim1, i> + operator*(const Tensor2_symmetric_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr + = Tensor3_times_Tensor2_symmetric_02; + return Tensor1_Expr::V, Dim1, i>( + TensorExpr(a, b)); + } + + /* A(j,k,i)*B(j,k)->Tensor1 */ + + template + class Tensor3_times_Tensor2_symmetric_01 + { + Tensor3_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V eval(const int N1, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, Current_Dim1 - 1, N1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + template + typename promote::V + eval(const int N1, const Number<1> &, const Number &) const + { + return iterA(0, Current_Dim1 - 1, N1) * iterB(0, Current_Dim1 - 1) + + eval(N1, Number(), Number()); + } + typename promote::V + eval(const int N1, const Number<1> &, const Number<1> &) const + { + return iterA(0, 0, N1) * iterB(0, 0); + } + + public: + Tensor3_times_Tensor2_symmetric_01( + const Tensor3_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int N1) const + { + return eval(N1, Number(), Number()); + } + }; + + template + Tensor1_Expr< + Tensor3_times_Tensor2_symmetric_01, + typename promote::V, Dim2, i> + operator*(const Tensor3_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor3_times_Tensor2_symmetric_01; + return Tensor1_Expr::V, Dim2, i>( + TensorExpr(a, b)); + } + + /* B(j,k)*A(j,k,i)->Tensor1 */ + + template + Tensor1_Expr< + Tensor3_times_Tensor2_symmetric_01, + typename promote::V, Dim2, i> + operator*(const Tensor2_symmetric_Expr &b, + const Tensor3_Expr &a) + { + using TensorExpr + = Tensor3_times_Tensor2_symmetric_01; + return Tensor1_Expr::V, Dim2, i>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor3.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor3.hpp new file mode 100644 index 000000000..8f11d4cf5 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_Tensor3.hpp @@ -0,0 +1,447 @@ +/* Fully contracts a Tensor3 with a Tensor3, yielding a typename + promote::V. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)*B(i,j,k) */ + + template + typename promote::V + T3_times_T3_012(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + + T3_times_T3_012(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_012(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim0 - 1, 0, Current_Dim2 - 1) + + T3_times_T3_012(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_012(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(Current_Dim0 - 1, 0, 0) + + T3_times_T3_012(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_012(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Tensor3_Expr &b) + { + return T3_times_T3_012(a, b, Number(), Number(), + Number()); + } + + /* A(i,j,k)*B(k,i,j) */ + + template + typename promote::V + T3_times_T3_201(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim2 - 1, Current_Dim0 - 1, Current_Dim1 - 1) + + T3_times_T3_201(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_201(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim2 - 1, Current_Dim0 - 1, 0) + + T3_times_T3_201(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_201(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(0, Current_Dim0 - 1, 0) + + T3_times_T3_201(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_201(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Tensor3_Expr &b) + { + return T3_times_T3_201(a, b, Number(), Number(), + Number()); + } + + /* A(i,j,k)*B(j,k,i) */ + + template + typename promote::V + T3_times_T3_120(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim1 - 1, Current_Dim2 - 1, Current_Dim0 - 1) + + T3_times_T3_120(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_120(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(0, Current_Dim2 - 1, Current_Dim0 - 1) + + T3_times_T3_120(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_120(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(0, 0, Current_Dim0 - 1) + + T3_times_T3_120(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_120(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Tensor3_Expr &b) + { + return T3_times_T3_120(a, b, Number(), Number(), + Number()); + } + + /* A(i,j,k)*B(j,i,k) */ + + template + typename promote::V + T3_times_T3_102(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim1 - 1, Current_Dim0 - 1, Current_Dim2 - 1) + + T3_times_T3_102(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_102(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(0, Current_Dim0 - 1, Current_Dim2 - 1) + + T3_times_T3_102(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_102(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(0, Current_Dim0 - 1, 0) + + T3_times_T3_102(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_102(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Tensor3_Expr &b) + { + return T3_times_T3_102(a, b, Number(), Number(), + Number()); + } + + /* A(i,j,k)*B(k,j,i) */ + + template + typename promote::V + T3_times_T3_210(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim2 - 1, Current_Dim1 - 1, Current_Dim0 - 1) + + T3_times_T3_210(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_210(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim2 - 1, 0, Current_Dim0 - 1) + + T3_times_T3_210(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_210(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(0, 0, Current_Dim0 - 1) + + T3_times_T3_210(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_210(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Tensor3_Expr &b) + { + return T3_times_T3_210(a, b, Number(), Number(), + Number()); + } + + /* A(i,j,k)*B(i,k,j) */ + + template + typename promote::V + T3_times_T3_021(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim0 - 1, Current_Dim2 - 1, Current_Dim1 - 1) + + T3_times_T3_021(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_021(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim0 - 1, Current_Dim2 - 1, 0) + + T3_times_T3_021(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_021(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number<1> &) + { + return a(Current_Dim0 - 1, 0, 0) * b(Current_Dim0 - 1, 0, 0) + + T3_times_T3_021(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + T3_times_T3_021(const Tensor3_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<1> &, const Number<1> &) + { + return a(0, 0, 0) * b(0, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_Expr &a, + const Tensor3_Expr &b) + { + return T3_times_T3_021(a, b, Number(), Number(), + Number()); + } + + /* A(i,j,k)*B(k,l,m) -> Tensor 4 */ + + template + class Tensor3_times_Tensor3_21 + { + Tensor3_Expr iterA; + Tensor3_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const int N3, const int N4, + const Number &) const + { + return iterA(N1, N2, CurrentDim - 1) * iterB(CurrentDim - 1, N3, N4) + + eval(N1, N2, N3, N4, Number()); + } + typename promote::V eval(const int N1, const int N2, const int N3, + const int N4, const Number<1> &) const + { + return iterA(N1, N2, 0) * iterB(0, N3, N4); + } + + public: + Tensor3_times_Tensor3_21( + const Tensor3_Expr &a, + const Tensor3_Expr &b) + : iterA(a), iterB(b) + {} + typename promote::V operator()(const int &N1, const int &N2, + const int &N3, const int &N4) const + { + return eval(N1, N2, N3, N4, Number()); + } + }; + + template + Tensor4_Expr, + typename promote::V, Dim0, Dim1, Dim4, Dim5, i, j, l, m> + operator*(const Tensor3_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr = Tensor3_times_Tensor3_21; + return Tensor4_Expr::V, Dim0, Dim1, + Dim4, Dim5, i, j, l, m>(TensorExpr(a, b)); + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_generic.hpp new file mode 100644 index 000000000..6ed7645eb --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_times_generic.hpp @@ -0,0 +1,34 @@ +/* Multiplies a Tensor3 with a generic, yielding a Tensor3. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)*generic */ + + template + auto operator*(const Tensor3_Expr &a, + const U &d0) + { + auto TensorExpr = [&a, &d0](const int N1, const int N2, const int N3) { + return a.operator()(N1, N2, N3) * d0; + }; + return Tensor3_Expr::V, Dim0, + Dim1, Dim2, i, j, k>(TensorExpr); + } + + /* generic*A(i,j,k) */ + + template + auto operator*(const U &d0, + const Tensor3_Expr &a) + { + auto TensorExpr = [&a, &d0](const int N1, const int N2, const int N3) { + return d0 * a.operator()(N1, N2, N3); + }; + return Tensor3_Expr::V, Dim0, + Dim1, Dim2, i, j, k>(TensorExpr); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_value.hpp b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_value.hpp new file mode 100644 index 000000000..311f6ff06 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3/Tensor3_value.hpp @@ -0,0 +1,582 @@ +/* A general version, not for pointers. */ + +#pragma once + +#include "Tensor3_contracted.hpp" + +#include + +namespace FTensor +{ + template + class Tensor3 + { + T data[Tensor_Dim0][Tensor_Dim1][Tensor_Dim2]; + + public: + template Tensor3(U... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Tensor3() {} + + /* There are two operator(int,int,int)'s, one for non-consts that lets you + change the value, and one for consts that doesn't. */ + + T &operator()(const int N1, const int N2, const int N3) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0 + || N3 >= Tensor_Dim2 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Tensor3.operator(" << N1 << "," << N2 << "," + << N3 << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[N1][N2][N3]; + } + + T operator()(const int N1, const int N2, const int N3) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0 + || N3 >= Tensor_Dim2 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Tensor3.operator(" << N1 << "," << N2 << "," + << N3 << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[N1][N2][N3]; + } + + /* These operator()'s are the first part in constructing template + expressions. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim2), + Tensor3_Expr, T, Dim0, + Dim1, Dim2, i, j, k>>::type + operator()(const Index, const Index, + const Index) + { + return Tensor3_Expr, T, + Dim0, Dim1, Dim2, i, j, k>(*this); + } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim2), + Tensor3_Expr, T, + Dim0, Dim1, Dim2, i, j, k>>::type + operator()(const Index, const Index, + const Index) const + { + return Tensor3_Expr< + const Tensor3, T, Dim0, Dim1, + Dim2, i, j, k>(*this); + } + + /* These operators are for internal contractions. We can not do + something like A(i,j,j) where i and j have different dimensions, + because it becomes ambiguous. */ + /*TODO I dont know how i and j having different dimensions can be + * ambiguous?? Since you do Use that in A(j,j,i)*/ + /* A(i,j,j) */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim1 >= Dim && Tensor_Dim2 >= Dim), + Tensor1_Expr< + Tensor3_contracted_12< + const Tensor3, T, Dim>, + T, Dim, i>>::type + operator()(const Index, const Index, + const Index) const + { + using TensorExpr = Tensor3_contracted_12< + Tensor3, T, Dim>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* A(j,i,j) */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim1 >= Dim && Tensor_Dim2 >= Dim), + Tensor1_Expr< + Tensor3_contracted_02< + const Tensor3, T, Dim>, + T, Dim, i>>::type + operator()(const Index, const Index, + const Index) const + { + using TensorExpr = Tensor3_contracted_02< + const Tensor3, T, Dim>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* A(j,j,i) */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim1 >= Dim && Tensor_Dim2 >= Dim2), + Tensor1_Expr< + Tensor3_contracted_01< + const Tensor3, T, Dim>, + T, Dim2, i>>::type + operator()(const Index, const Index, + const Index) const + { + using TensorExpr = Tensor3_contracted_01< + const Tensor3, T, Dim2>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* This is for expressions where a number is used for one slot, and + indices for the others, yielding a Tensor2_Expr or + Tensor2_symmetric_Expr. The non-const versions don't actually + create a Tensor3_number_rhs_* object, while the const versions + do create a Tensor3_number_*. */ + + /* First slot. */ + + template + typename std::enable_if< + (Tensor_Dim0 > N && Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim2), + Tensor2_Expr, T, N>, + T, Dim1, Dim2, i, j>>::type + operator()(const Number, const Index, const Index) + { + using TensorExpr = Tensor3_number_rhs_0< + Tensor3, T, N>; + return Tensor2_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim0 > N && Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim2), + Tensor2_Expr< + Tensor3_number_0< + const Tensor3, T, N>, + T, Dim1, Dim2, i, j>>::type + operator()(const Number, const Index, + const Index) const + { + using TensorExpr = Tensor3_number_0< + const Tensor3, T, N>; + return Tensor2_Expr(TensorExpr(*this)); + } + + /* Second slot. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim1 > N && Tensor_Dim2 >= Dim2), + Tensor2_Expr, T, N>, + T, Dim0, Dim2, i, j>>::type + operator()(const Index, const Number, const Index) + { + using TensorExpr = Tensor3_number_rhs_0< + Tensor3, T, N>; + return Tensor2_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim1 > N && Tensor_Dim2 >= Dim2), + Tensor2_Expr< + Tensor3_number_0< + const Tensor3, T, N>, + T, Dim0, Dim2, i, j>>::type + operator()(const Index, const Number, + const Index) const + { + using TensorExpr = Tensor3_number_0< + const Tensor3, T, N>; + return Tensor2_Expr(TensorExpr(*this)); + } + + /* Third slot. */ + // TODO allow two different dimensions here + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim1 >= Dim && Tensor_Dim2 > N), + Tensor2_symmetric_Expr< + Tensor3_number_rhs_2, + T, N>, + T, Dim, i, j>>::type + operator()(const Index, const Index, const Number) + { + using TensorExpr = Tensor3_number_rhs_2< + Tensor3, T, N>; + return Tensor2_symmetric_Expr(*this); + } + // TODO allow two different dimensions here + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim1 >= Dim && Tensor_Dim2 > N), + Tensor2_symmetric_Expr< + Tensor3_number_2< + const Tensor3, T, N>, + T, Dim, i, j>>::type + operator()(const Index, const Index, const Number) const + { + using TensorExpr = Tensor3_number_2< + const Tensor3, T, N>; + return Tensor2_symmetric_Expr( + TensorExpr(*this)); + } + + /* This is for expressions where a number is used for two slots, and + an Index for the other, yielding a Tensor1_Expr. The non-const + versions don't actually create a Tensor3_number_rhs_* object, + while the const versions do create a Tensor3_number_*. */ + + /* Index in first slot. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim1 > N1 && Tensor_Dim2 > N2), + Tensor1_Expr< + Tensor3_number_rhs_12< + Tensor3, T, N1, N2>, + T, Dim, i>>::type + operator()(const Index index, const Number, const Number) + { + using TensorExpr = Tensor3_number_rhs_12< + Tensor3, T, N1, N2>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim1 > N1 && Tensor_Dim2 > N2), + Tensor1_Expr< + Tensor3_number_12< + const Tensor3, T, N1, N2>, + T, Dim, i>>::type + operator()(const Index index, const Number, + const Number) const + { + using TensorExpr = Tensor3_number_12< + const Tensor3, T, N1, N2>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Index in second slot. I use the same structures as for the Index + in the first slot since the tensor is symmetric on the first two + indices. */ + + template + typename std::enable_if< + (Tensor_Dim0 > N0 && Tensor_Dim1 >= Dim && Tensor_Dim2 > N2), + Tensor1_Expr< + Tensor3_number_rhs_12< + Tensor3, T, N0, N2>, + T, Dim, i>>::type + operator()(const Number, const Index index, const Number) + { + using TensorExpr = Tensor3_number_rhs_12< + Tensor3, T, N0, N2>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim0 > N0 && Tensor_Dim1 >= Dim && Tensor_Dim2 > N2), + Tensor1_Expr< + Tensor3_number_12< + const Tensor3, T, N0, N2>, + T, Dim, i>>::type + operator()(const Number, const Index index, + const Number) const + { + using TensorExpr = Tensor3_number_12< + const Tensor3, T, N0, N2>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Index in third slot. */ + + template + typename std::enable_if< + (Tensor_Dim0 > N0 && Tensor_Dim1 > N1 && Tensor_Dim2 >= Dim), + Tensor1_Expr< + Tensor3_number_rhs_01< + Tensor3, T, N0, N1>, + T, Dim, i>>::type + operator()(const Number, const Number, const Index index) + { + using TensorExpr = Tensor3_number_rhs_01< + Tensor3, T, N0, N1>; + return Tensor1_Expr(*this); + } + + template + typename std::enable_if< + (Tensor_Dim0 > N0 && Tensor_Dim1 > N1 && Tensor_Dim2 >= Dim), + Tensor1_Expr< + Tensor3_number_01< + const Tensor3, T, N0, N1>, + T, Dim, i>>::type + operator()(const Number, const Number, + const Index index) const + { + using TensorExpr = Tensor3_number_01< + const Tensor3, T, N0, N1>; + return Tensor1_Expr(TensorExpr(*this)); + } + + /* Specializations for using actual numbers instead of Number<>. + This is for expressions where an actual number is used for one + slot, and indices for the others, yielding a Tensor2_Expr or + Tensor2_symmetric_Expr. I only define the const versions. */ + + /* First slot. */ + + template + typename std::enable_if< + (Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim2), + Tensor2_Expr, T>, + T, Dim1, Dim2, i, j>>::type + operator()(const int N, const Index, const Index) const + { + using TensorExpr = Tensor3_numeral_0< + const Tensor3, T>; + return Tensor2_Expr( + TensorExpr(*this, N)); + } + + /* Second slot. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim2 >= Dim2), + Tensor2_Expr, T>, + T, Dim0, Dim2, i, j>>::type + operator()(const Index, const int N, const Index) const + { + using TensorExpr = Tensor3_numeral_0< + const Tensor3, T>; + return Tensor2_Expr( + TensorExpr(*this, N)); + } + + /* Third slot. */ + // TODO Allow multiple dimensions here + template + typename std::enable_if< + (Tensor_Dim0 >= Dim && Tensor_Dim1 >= Dim), + Tensor2_symmetric_Expr< + Tensor3_numeral_2< + const Tensor3, T>, + T, Dim, i, j>>::type + operator()(const Index, const Index, const int N) const + { + using TensorExpr = Tensor3_numeral_2< + const Tensor3, T>; + return Tensor2_symmetric_Expr( + TensorExpr(*this, N)); + } + + /* This is for expressions where a numeral is used for two slots, and + an Index for the other, yielding a Tensor1_Expr. */ + + /* Index in first slot. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim), + Tensor1_Expr, T>, + T, Dim, i>>::type + operator()(const Index index, const int N1, const int N2) const + { + using TensorExpr = Tensor3_numeral_12< + const Tensor3, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } + + /* Index in second slot. I use the same structures as for the Index + in the first slot since the tensor is symmetric on the first two + indices. */ + + template + typename std::enable_if< + (Tensor_Dim1 >= Dim), + Tensor1_Expr, T>, + T, Dim, i>>::type + operator()(const int N1, const Index index, const int N2) const + { + using TensorExpr = Tensor3_numeral_12< + const Tensor3, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } + + /* Index in third slot. */ + + template + typename std::enable_if< + (Tensor_Dim2 >= Dim), + Tensor1_Expr, T>, + T, Dim, i>>::type + operator()(const int N1, const int N2, const Index index) const + { + using TensorExpr = Tensor3_numeral_01< + const Tensor3, T>; + return Tensor1_Expr(TensorExpr(*this, N1, N2)); + } + }; +} + +/// JSON compatible output for numbers. If T is something funky +/// (strings, arrays, etc.) then you are going to have a bad time. + +namespace FTensor +{ + template + std::ostream &Tensor3_ostream_row( + std::ostream &os, + const FTensor::Tensor3 &t, + const int &i, const int &j) + { + os << '['; + for(int k = 0; k + 1 < Tensor_Dim2; ++k) + { + os << t(i, j, k) << ','; + } + if(Tensor_Dim2 > 0) + { + os << t(i, j, Tensor_Dim2 - 1); + } + os << ']'; + return os; + } + + template + std::ostream &Tensor3_ostream_block( + std::ostream &os, + const FTensor::Tensor3 &t, + const int &i) + { + os << '['; + for(int j = 0; j + 1 < Tensor_Dim1; ++j) + { + FTensor::Tensor3_ostream_row(os, t, i, j); + os << ','; + } + if(Tensor_Dim1 > 0) + { + FTensor::Tensor3_ostream_row(os, t, i, Tensor_Dim1 - 1); + } + os << ']'; + return os; + } +} + +template +std::ostream & +operator<<(std::ostream &os, + const FTensor::Tensor3 &t) +{ + os << '['; + for(int i = 0; i + 1 < Tensor_Dim0; ++i) + { + FTensor::Tensor3_ostream_block(os, t, i); + os << ','; + } + if(Tensor_Dim0 > 0) + { + FTensor::Tensor3_ostream_block(os, t, Tensor_Dim0 - 1); + } + os << ']'; + return os; +} + +/// JSON compatible input. It does not validate that separators are +/// actually braces '[' or commas ','. It also ignores errors from +/// missing trailing characters. So you could do something like +/// +/// Tensor3 t3_1; +/// std::stringstream ss(":::3:4:::7:8:::::11:12:::13:14"); +/// ss >> t3_1; + +namespace FTensor +{ + template + std::istream &Tensor3_istream_row( + std::istream &is, + FTensor::Tensor3 &t, + const int &i, const int &j) + { + char c; + is >> c; + for(int k = 0; k + 1 < Tensor_Dim2; ++k) + { + is >> t(i, j, k) >> c; + } + if(Tensor_Dim2 > 0) + { + is >> t(i, j, Tensor_Dim2 - 1); + } + is >> c; + return is; + } + + template + std::istream &Tensor3_istream_block( + std::istream &is, + FTensor::Tensor3 &t, + const int &i) + { + char c; + is >> c; + for(int j = 0; j + 1 < Tensor_Dim1; ++j) + { + Tensor3_istream_row(is, t, i, j); + is >> c; + } + if(Tensor_Dim1 > 0) + { + Tensor3_istream_row(is, t, i, Tensor_Dim1 - 1); + } + is >> c; + return is; + } +} + +template +std::istream & +operator>>(std::istream &is, + FTensor::Tensor3 &t) +{ + char c; + is >> c; + for(int i = 0; i + 1 < Tensor_Dim0; ++i) + { + FTensor::Tensor3_istream_block(is, t, i); + is >> c; + } + if(Tensor_Dim0 > 0) + { + FTensor::Tensor3_istream_block(is, t, Tensor_Dim0 - 1); + } + is >> c; + return is; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric.hpp new file mode 100644 index 000000000..ff42729aa --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric.hpp @@ -0,0 +1,10 @@ +/* Declaration for a Tensor3_antisymmetric. This is antisymmetric on + the last two indices, so in 3 dimensions it only has 9 elements. + The first declaration is for T's (int, double, etc.) while the + second is for pointers to T's, so it is useful for previously + constructed arrays. */ + +#include "Tensor3_antisymmetric/Tensor3_antisymmetric_pointer.hpp" +#include "Tensor3_antisymmetric/Tensor3_antisymmetric_value.hpp" + +#include "Tensor3_antisymmetric/Tensor3_antisymmetric_Expr.hpp" diff --git a/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_Expr.hpp b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_Expr.hpp new file mode 100644 index 000000000..4d171acad --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_Expr.hpp @@ -0,0 +1,71 @@ +/* Declare a wrapper class for rank 3 Tensor expressions, + antisymmetric in the last two indices. I specialize it for when I + wrap a simple Tensor3_antisymmetric(_ptr) so that it has a + reference to the Tensor3_antisymmetric(_ptr) and not a copy. + Otherwise assignment wouldn't work. */ + +#pragma once + +#include "Tensor3_antisymmetric_or_Tensor3_antisymmetric.hpp" +#include "Tensor3_antisymmetric_plus_Tensor3_antisymmetric.hpp" +#include "Tensor3_antisymmetric_times_Tensor3.hpp" +// #include "Tensor3_antisymmetric_mod_Tensor1.hpp" +#include "Tensor3_antisymmetric_times_generic.hpp" + +namespace FTensor +{ + template + class Tensor3_antisymmetric_Expr + { + A iter; + + public: + Tensor3_antisymmetric_Expr(const A &a) : iter(a) {} + T operator()(const int N1, const int N2, const int N3) const + { + return iter(N1, N2, N3); + } + }; + + template + class Tensor3_antisymmetric_Expr, T, + Dim0, Dim12, i, j, k> + { + Tensor3_antisymmetric &iter; + + public: + Tensor3_antisymmetric_Expr(Tensor3_antisymmetric &a) + : iter(a) + {} + T operator()(const int N1, const int N2, const int N3) const + { + return iter(N1, N2, N3); + } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + Tensor3_antisymmetric_Expr, T, Dim0, + Dim12, i, j, k> & + operator=( + const Tensor3_antisymmetric_Expr &result); + + Tensor3_antisymmetric_Expr, T, Dim0, + Dim12, i, j, k> & + operator=( + const Tensor3_antisymmetric_Expr, + T, Dim0, Dim12, i, j, k> &result); + + /* This is for when the indices are switched (i,j,k) -> (i,k,j). */ + + template + Tensor3_antisymmetric_Expr, T, Dim0, + Dim12, i, j, k> & + operator=( + const Tensor3_antisymmetric_Expr &result); + }; +} + +#include "Tensor3_antisymmetric_Expr_equals.hpp" diff --git a/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_Expr_equals.hpp b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_Expr_equals.hpp new file mode 100644 index 000000000..aca0f3e51 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_Expr_equals.hpp @@ -0,0 +1,156 @@ +/* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + +#pragma once + +namespace FTensor +{ + /* T3as=T3as */ + + template + void T3as_equals_T3as( + A &iter, + const Tensor3_antisymmetric_Expr &result, + const Number &, const Number &, + const Number &) + { + iter.unsafe(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + = result(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1); + T3as_equals_T3as(iter, result, Number(), + Number(), Number()); + } + + template + void T3as_equals_T3as( + A &iter, + const Tensor3_antisymmetric_Expr &result, + const Number &, const Number<1> &, + const Number &) + { + iter.unsafe(Current_Dim0 - 1, 0, Current_Dim2 - 1) + = result(Current_Dim0 - 1, 0, Current_Dim2 - 1); + T3as_equals_T3as(iter, result, Number(), + Number(), Number()); + } + + template + void T3as_equals_T3as( + A &iter, + const Tensor3_antisymmetric_Expr &result, + const Number &, const Number<1> &, const Number<2> &) + { + iter.unsafe(Current_Dim0 - 1, 0, 1) = result(Current_Dim0 - 1, 0, 1); + T3as_equals_T3as(iter, result, Number(), + Number(), Number()); + } + + template + void T3as_equals_T3as( + A &iter, + const Tensor3_antisymmetric_Expr &result, + const Number<1> &, const Number<1> &, const Number<2> &) + { + iter.unsafe(0, 0, 1) = result(0, 0, 1); + } + + template + template + Tensor3_antisymmetric_Expr, T, Dim0, + Dim12, i, j, k> & + Tensor3_antisymmetric_Expr, T, Dim0, + Dim12, i, j, k>:: + operator=( + const Tensor3_antisymmetric_Expr &result) + { + T3as_equals_T3as(iter, result, Number(), Number(), + Number()); + return *this; + } + + /* T3as=T3as_Expr(T3as) */ + + template + Tensor3_antisymmetric_Expr, T, Dim0, + Dim12, i, j, k> & + Tensor3_antisymmetric_Expr, T, Dim0, + Dim12, i, j, k>:: + operator=( + const Tensor3_antisymmetric_Expr, T, + Dim0, Dim12, i, j, k> &result) + { + return operator=, T>(result); + } + + /* This is for when the indices are switched (i,j,k) -> (i,k,j). */ + + template + void T3as_switched_equals_T3as( + A &iter, + const Tensor3_antisymmetric_Expr &result, + const Number &, const Number &, + const Number &) + { + iter.unsafe(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + = -result(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1); + T3as_switched_equals_T3as(iter, result, Number(), + Number(), + Number()); + } + + template + void T3as_switched_equals_T3as( + A &iter, + const Tensor3_antisymmetric_Expr &result, + const Number &, const Number<1> &, + const Number &) + { + iter.unsafe(Current_Dim0 - 1, 0, Current_Dim2 - 1) + = -result(Current_Dim0 - 1, 0, Current_Dim2 - 1); + T3as_switched_equals_T3as(iter, result, Number(), + Number(), + Number()); + } + + template + void T3as_switched_equals_T3as( + A &iter, + const Tensor3_antisymmetric_Expr &result, + const Number &, const Number<1> &, const Number<2> &) + { + iter.unsafe(Current_Dim0 - 1, 0, 1) = -result(Current_Dim0 - 1, 0, 1); + T3as_switched_equals_T3as(iter, result, Number(), + Number(), Number()); + } + + template + void T3as_switched_equals_T3as( + A &iter, + const Tensor3_antisymmetric_Expr &result, + const Number<1> &, const Number<1> &, const Number<2> &) + { + iter.unsafe(0, 0, 1) = -result(0, 0, 1); + } + + template + template + Tensor3_antisymmetric_Expr, T, Dim0, + Dim12, i, j, k> & + Tensor3_antisymmetric_Expr, T, Dim0, + Dim12, i, j, k>:: + operator=( + const Tensor3_antisymmetric_Expr &result) + { + T3as_switched_equals_T3as(iter, result, Number(), + Number(), Number()); + return *this; + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_mod_Tensor1.hpp b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_mod_Tensor1.hpp new file mode 100644 index 000000000..8c7f451ad --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_mod_Tensor1.hpp @@ -0,0 +1,58 @@ +/* Multiplies a Tensor3_antisymmetric and a Tensor1, yielding a + Riemann. */ + +#pragma once + +namespace FTensor +{ + /* A(j,k,l)*B(i) */ + + template + class Tensor3_antisymmetric_mod_Tensor1 + { + Tensor3_antisymmetric_Expr iterA; + Tensor1_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N2, N3, N4) * iterB(N1); + } + + Tensor3_antisymmetric_mod_Tensor1( + const Tensor3_antisymmetric_Expr &a, + const Tensor1_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Riemann_Expr, + typename promote::V, Dim, i, j, k, l> + operator%(const Tensor3_antisymmetric_Expr &a, + const Tensor1_Expr &b) + { + using TensorExpr + = Tensor3_antisymmetric_mod_Tensor1; + return Riemann_Expr::V, Dim, i, j, k, l>( + TensorExpr(a, b)); + } + + /* B(i)*A(j,k,l) */ + + template + Riemann_Expr, + typename promote::V, Dim, i, j, k, l> + operator%(const Tensor1_Expr &b, + const Tensor3_antisymmetric_Expr &a) + { + using TensorExpr + = Tensor3_antisymmetric_mod_Tensor1; + return Riemann_Expr::V, Dim, i, j, k, l>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_or_Tensor3_antisymmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_or_Tensor3_antisymmetric.hpp new file mode 100644 index 000000000..bbab9f317 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_or_Tensor3_antisymmetric.hpp @@ -0,0 +1,42 @@ +/* Adds two Tensor3_antisymmetrics together to make a Dg. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k) + B(k,j,i) */ + + template + class Tensor3_antisymmetric_or_Tensor3_antisymmetric + { + Tensor3_antisymmetric_Expr iterA; + Tensor3_antisymmetric_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N3, N2) + iterB(N2, N3, N1); + } + + Tensor3_antisymmetric_or_Tensor3_antisymmetric( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_antisymmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Dg_Expr< + Tensor3_antisymmetric_or_Tensor3_antisymmetric, + typename promote::V, Dim, Dim, i, k, j> + operator||(const Tensor3_antisymmetric_Expr &a, + const Tensor3_antisymmetric_Expr &b) + { + using TensorExpr + = Tensor3_antisymmetric_or_Tensor3_antisymmetric; + return Dg_Expr::V, Dim, Dim, i, k, j>( + TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_plus_Tensor3_antisymmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_plus_Tensor3_antisymmetric.hpp new file mode 100644 index 000000000..92db14d13 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_plus_Tensor3_antisymmetric.hpp @@ -0,0 +1,84 @@ +/* Adds two Tensor3_antisymmetric's together, yielding a + Tensor3_antisymmetric. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k) + B(i,j,k) */ + + template + class Tensor3_antisymmetric_plus_Tensor3_antisymmetric + { + Tensor3_antisymmetric_Expr iterA; + Tensor3_antisymmetric_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) + iterB(N1, N2, N3); + } + + Tensor3_antisymmetric_plus_Tensor3_antisymmetric( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_antisymmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor3_antisymmetric_Expr, + typename promote::V, Dim0, Dim12, i, j, k> + operator+(const Tensor3_antisymmetric_Expr &a, + const Tensor3_antisymmetric_Expr &b) + { + using TensorExpr + = Tensor3_antisymmetric_plus_Tensor3_antisymmetric; + return Tensor3_antisymmetric_Expr::V, + Dim0, Dim12, i, j, k>(TensorExpr(a, b)); + } + + /* A(i,j,k) + B(i,k,j) (which simplifies to A(i,j,k) - B(i,j,k)) */ + + template + class Tensor3_antisymmetric_plus_Tensor3_antisymmetric_12 + { + Tensor3_antisymmetric_Expr iterA; + Tensor3_antisymmetric_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) - iterB(N1, N2, N3); + } + + Tensor3_antisymmetric_plus_Tensor3_antisymmetric_12( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_antisymmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor3_antisymmetric_Expr< + Tensor3_antisymmetric_plus_Tensor3_antisymmetric_12, + typename promote::V, Dim0, Dim12, i, j, k> + operator+(const Tensor3_antisymmetric_Expr &a, + const Tensor3_antisymmetric_Expr &b) + { + using TensorExpr + = Tensor3_antisymmetric_plus_Tensor3_antisymmetric_12; + return Tensor3_antisymmetric_Expr::V, + Dim0, Dim12, i, j, k>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_pointer.hpp b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_pointer.hpp new file mode 100644 index 000000000..a867cec55 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_pointer.hpp @@ -0,0 +1,134 @@ +/* A version for pointers. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor3_antisymmetric + { + //mutable T *restrict + // data[Tensor_Dim0][(Tensor_Dim12 * (Tensor_Dim12 - 1)) / 2]; + mutable T *__restrict + data[Tensor_Dim0][(Tensor_Dim12 * (Tensor_Dim12 - 1)) / 2]; + + + public: + template Tensor3_antisymmetric(U *... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Tensor3_antisymmetric() {} + + /* There are two ways of accessing the values inside, + unsafe(int,int,int) and operator(int,int,int). + unsafe(int,int,int) will give you a wrong answer if you aren't + careful. The problem is that we only store the minimal set of + components, but some have different signs. We can't return the + negative of a component, and assign something to it, because that + would assign something to a temporary. To get the correct answer + if you don't want to change the value, just use + operator(int,int,int). */ + + T &unsafe(const int N1, const int N2, const int N3) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0 + || N3 >= Tensor_Dim12 || N3 < 0 || N2 >= N3) + { + std::stringstream s; + s << "Bad index in Tensor3_antisymmetric.unsafe(" << N1 << "," << N2 << "," << N3 + << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return *data[N1][N3 - 1 + (N2 * (2 * (Tensor_Dim12 - 1) - N2 - 1)) / 2]; + } + + T operator()(const int N1, const int N2, const int N3) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0 + || N3 >= Tensor_Dim12 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Tensor3_antisymmetric.operator(" << N1 << "," << N2 << "," << N3 + << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N2 < N3 + ? *data[N1] + [N3 - 1 + (N2 * (2 * (Tensor_Dim12 - 1) - N2 - 1)) / 2] + : (N2 > N3 + ? -*data[N1][N2 - 1 + + (N3 * (2 * (Tensor_Dim12 - 1) - N3 - 1)) / 2] + : 0.0); + } + + T *ptr(const int N1, const int N2, const int N3) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0 + || N3 >= Tensor_Dim12 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Tensor3_antisymmetric.ptr(" << N1 << "," << N2 << "," << N3 << ")" + << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N2 < N3 + ? data[N1][N3 - 1 + (N2 * (2 * (Tensor_Dim12 - 1) - N2 - 1)) / 2] + : (N2 > N3 + ? -data[N1][N2 - 1 + + (N3 * (2 * (Tensor_Dim12 - 1) - N3 - 1)) / 2] + : 0); + } + + /* These operator()'s are the first part in constructing template + expressions. */ + + template + Tensor3_antisymmetric_Expr< + Tensor3_antisymmetric, T, Dim0, Dim12, i, + j, k> + operator()(const Index index1, const Index index2, + const Index index3) + { + return Tensor3_antisymmetric_Expr< + Tensor3_antisymmetric, T, Dim0, Dim12, + i, j, k>(*this); + } + + template + Tensor3_antisymmetric_Expr< + const Tensor3_antisymmetric, T, Dim0, + Dim12, i, j, k> + operator()(const Index index1, const Index index2, + const Index index3) const + { + return Tensor3_antisymmetric_Expr< + const Tensor3_antisymmetric, T, Dim0, + Dim12, i, j, k>(*this); + } + + /* The ++ operator increments the pointer, not the number that the + pointer points to. This allows iterating over a grid. */ + + const Tensor3_antisymmetric & + operator++() const + { + for(int i = 0; i < Tensor_Dim0; ++i) + for(int j = 0; j < (Tensor_Dim12 * (Tensor_Dim12 - 1)) / 2; ++j) + ++data[i][j]; + return *this; + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_times_Tensor3.hpp b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_times_Tensor3.hpp new file mode 100644 index 000000000..e48071b1c --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_times_Tensor3.hpp @@ -0,0 +1,536 @@ +/* Fully contracts a Tensor3_antisymmetric with a Tensor3, yielding a + typename promote::V. I removed the identically zero components of + Tensor3_antisymmetric.*/ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)*B(i,j,k) */ + + template + typename promote::V T3as_times_T3_012( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + + T3as_times_T3_012(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_012( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim0 - 1, 0, Current_Dim2 - 1) + + T3as_times_T3_012(a, b, Number(), Number(), + Number()); + } + + /* A special case for when the last two indices are equal. */ + + template + typename promote::V T3as_times_T3_012( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return T3as_times_T3_012(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_012( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<2> &, const Number<1> &) + { + return a(Current_Dim0 - 1, 1, 0) * b(Current_Dim0 - 1, 1, 0) + + T3as_times_T3_012(a, b, Number(), + Number(), Number()); + } + + template + typename promote::V T3as_times_T3_012( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<2> &, const Number<1> &) + { + return a(0, 1, 0) * b(0, 1, 0); + } + + template + typename promote::V + operator*(const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b) + { + return T3as_times_T3_012(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + operator*(const Tensor3_Expr &b, + const Tensor3_antisymmetric_Expr &a) + { + return a * b; + } + + /* A(i,j,k)*B(k,i,j) */ + + template + typename promote::V T3as_times_T3_201( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim2 - 1, Current_Dim0 - 1, Current_Dim1 - 1) + + T3as_times_T3_201(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_201( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim2 - 1, Current_Dim0 - 1, 0) + + T3as_times_T3_201(a, b, Number(), Number(), + Number()); + } + + /* A special case for when the last two indices are equal. */ + + template + typename promote::V T3as_times_T3_201( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return T3as_times_T3_201(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_201( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<2> &, const Number<1> &) + { + return a(Current_Dim0 - 1, 1, 0) * b(0, Current_Dim0 - 1, 1) + + T3as_times_T3_201(a, b, Number(), + Number(), Number()); + } + + template + typename promote::V T3as_times_T3_201( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<2> &, const Number<1> &) + { + return a(0, 1, 0) * b(0, 0, 1); + } + + template + typename promote::V + operator*(const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b) + { + return T3as_times_T3_201(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + operator*(const Tensor3_Expr &b, + const Tensor3_antisymmetric_Expr &a) + { + return a * b; + } + + /* A(i,j,k)*B(j,k,i) */ + + template + typename promote::V T3as_times_T3_120( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim1 - 1, Current_Dim2 - 1, Current_Dim0 - 1) + + T3as_times_T3_120(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_120( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(0, Current_Dim2 - 1, Current_Dim0 - 1) + + T3as_times_T3_120(a, b, Number(), Number(), + Number()); + } + + /* A special case for when the last two indices are equal. */ + + template + typename promote::V T3as_times_T3_120( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return T3as_times_T3_120(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_120( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<2> &, const Number<1> &) + { + return a(Current_Dim0 - 1, 1, 0) * b(1, 0, Current_Dim0 - 1) + + T3as_times_T3_120(a, b, Number(), + Number(), Number()); + } + + template + typename promote::V T3as_times_T3_120( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<2> &, const Number<1> &) + { + return a(0, 1, 0) * b(1, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b) + { + return T3as_times_T3_120(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + operator*(const Tensor3_Expr &b, + const Tensor3_antisymmetric_Expr &a) + { + return a * b; + } + + /* A(i,j,k)*B(j,i,k) */ + + template + typename promote::V T3as_times_T3_102( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim1 - 1, Current_Dim0 - 1, Current_Dim2 - 1) + + T3as_times_T3_102(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_102( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(0, Current_Dim0 - 1, Current_Dim2 - 1) + + T3as_times_T3_102(a, b, Number(), Number(), + Number()); + } + + /* A special case for when the last two indices are equal. */ + + template + typename promote::V T3as_times_T3_102( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return T3as_times_T3_102(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_102( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<2> &, const Number<1> &) + { + return a(Current_Dim0 - 1, 1, 0) * b(1, Current_Dim0 - 1, 0) + + T3as_times_T3_102(a, b, Number(), + Number(), Number()); + } + + template + typename promote::V T3as_times_T3_102( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<2> &, const Number<1> &) + { + return a(0, 1, 0) * b(1, 0, 0); + } + + template + typename promote::V + operator*(const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b) + { + return T3as_times_T3_102(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + operator*(const Tensor3_Expr &b, + const Tensor3_antisymmetric_Expr &a) + { + return a * b; + } + + /* A(i,j,k)*B(k,j,i) */ + + template + typename promote::V T3as_times_T3_210( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim2 - 1, Current_Dim1 - 1, Current_Dim0 - 1) + + T3as_times_T3_210(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_210( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim2 - 1, 0, Current_Dim0 - 1) + + T3as_times_T3_210(a, b, Number(), Number(), + Number()); + } + + /* A special case for when the last two indices are equal. */ + + template + typename promote::V T3as_times_T3_210( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return T3as_times_T3_210(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_210( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<2> &, const Number<1> &) + { + return a(Current_Dim0 - 1, 1, 0) * b(0, 1, Current_Dim0 - 1) + + T3as_times_T3_210(a, b, Number(), + Number(), Number()); + } + + template + typename promote::V T3as_times_T3_210( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<2> &, const Number<1> &) + { + return a(0, 1, 0) * b(0, 1, 0); + } + + template + typename promote::V + operator*(const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b) + { + return T3as_times_T3_210(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + operator*(const Tensor3_Expr &b, + const Tensor3_antisymmetric_Expr &a) + { + return a * b; + } + + /* A(i,j,k)*B(i,k,j) */ + + template + typename promote::V T3as_times_T3_012( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return a(Current_Dim0 - 1, Current_Dim1 - 1, Current_Dim2 - 1) + * b(Current_Dim0 - 1, Current_Dim2 - 1, Current_Dim1 - 1) + + T3as_times_T3_012(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_012( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<1> &, + const Number &) + { + return a(Current_Dim0 - 1, 0, Current_Dim2 - 1) + * b(Current_Dim0 - 1, Current_Dim2 - 1, 0) + + T3as_times_T3_012(a, b, Number(), Number(), + Number()); + } + + /* A special case for when the last two indices are equal. */ + + template + typename promote::V T3as_times_T3_012( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number &, + const Number &) + { + return T3as_times_T3_012(a, b, Number(), + Number(), + Number()); + } + + template + typename promote::V T3as_times_T3_012( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number &, const Number<2> &, const Number<1> &) + { + return a(Current_Dim0 - 1, 1, 0) * b(Current_Dim0 - 1, 0, 1) + + T3as_times_T3_012(a, b, Number(), + Number(), Number()); + } + + template + typename promote::V T3as_times_T3_012( + const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b, + const Number<1> &, const Number<2> &, const Number<1> &) + { + return a(0, 1, 0) * b(0, 0, 1); + } + + template + typename promote::V + operator*(const Tensor3_antisymmetric_Expr &a, + const Tensor3_Expr &b) + { + return T3as_times_T3_012(a, b, Number(), Number(), + Number()); + } + + template + typename promote::V + operator*(const Tensor3_Expr &b, + const Tensor3_antisymmetric_Expr &a) + { + return a * b; + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_times_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_times_generic.hpp new file mode 100644 index 000000000..e295f174a --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_times_generic.hpp @@ -0,0 +1,60 @@ +/* Multiplies a Tensor3_antisymmetric with a generic, yielding a + Tensor3_antisymmetric. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k)*generic */ + + template + class Tensor3_antisymmetric_times_generic + { + Tensor3_antisymmetric_Expr iterA; + U d; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3) const + { + return iterA(N1, N2, N3) * d; + } + + Tensor3_antisymmetric_times_generic( + const Tensor3_antisymmetric_Expr &a, + const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor3_antisymmetric_Expr< + Tensor3_antisymmetric_times_generic, + typename promote::V, Dim0, Dim12, i, j, k> + operator*(const Tensor3_antisymmetric_Expr &a, + const U &d0) + { + using TensorExpr + = Tensor3_antisymmetric_times_generic; + return Tensor3_antisymmetric_Expr::V, + Dim0, Dim12, i, j, k>(TensorExpr(a, d0)); + } + + /* generic*A(i,j,k) */ + + template + Tensor3_antisymmetric_Expr< + Tensor3_antisymmetric_times_generic, + typename promote::V, Dim0, Dim12, i, j, k> + operator*(const U &d0, + const Tensor3_antisymmetric_Expr &a) + { + using TensorExpr + = Tensor3_antisymmetric_times_generic; + return Tensor3_antisymmetric_Expr::V, + Dim0, Dim12, i, j, k>(TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_value.hpp b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_value.hpp new file mode 100644 index 000000000..f407bd0ad --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor3_antisymmetric/Tensor3_antisymmetric_value.hpp @@ -0,0 +1,101 @@ +/* A general version, not for pointers. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor3_antisymmetric + { + T data[Tensor_Dim0][(Tensor_Dim12 * (Tensor_Dim12 - 1)) / 2]; + + public: + template Tensor3_antisymmetric(U... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Tensor3_antisymmetric() {} + + /* There are two ways of accessing the values inside, + unsafe(int,int,int) and operator(int,int,int). + unsafe(int,int,int) will give you a wrong answer if you aren't + careful. The problem is that we only store the minimal set of + components, but some have different signs. We can't return the + negative of a component, and assign something to it, because that + would assign something to a temporary. To get the correct answer + if you don't want to change the value, just use + operator(int,int,int). */ + + T &unsafe(const int N1, const int N2, const int N3) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0 + || N3 >= Tensor_Dim12 || N3 < 0 || N2 >= N3) + { + std::stringstream s; + s << "Bad index in Tensor3_antisymmetric.operator(" << N1 << "," << N2 << "," << N3 + << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[N1][N3 - 1 + (N2 * (2 * (Tensor_Dim12 - 1) - N2 - 1)) / 2]; + } + + T operator()(const int N1, const int N2, const int N3) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim12 || N2 < 0 + || N3 >= Tensor_Dim12 || N3 < 0) + { + std::stringstream s; + s << "Bad index in Tensor3_antisymmetric.operator(" << N1 << "," << N2 << "," << N3 + << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return N2 < N3 + ? data[N1][N3 - 1 + (N2 * (2 * (Tensor_Dim12 - 1) - N2 - 1)) / 2] + : (N2 > N3 + ? -data[N1][N2 - 1 + + (N3 * (2 * (Tensor_Dim12 - 1) - N3 - 1)) / 2] + : 0.0); + } + + /* These operator()'s are the first part in constructing template + expressions. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim12 >= Dim12), + Tensor3_antisymmetric_Expr< + Tensor3_antisymmetric, T, Dim0, Dim12, i, + j, k>>::type + operator()(const Index, const Index, + const Index) + { + return Tensor3_antisymmetric_Expr< + Tensor3_antisymmetric, T, Dim0, Dim12, i, + j, k>(*this); + } + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim12 >= Dim12), + Tensor3_antisymmetric_Expr< + const Tensor3_antisymmetric, T, Dim0, + Dim12, i, j, k>>::type + operator()(const Index, const Index, + const Index) const + { + return Tensor3_antisymmetric_Expr< + const Tensor3_antisymmetric, T, Dim0, + Dim12, i, j, k>(*this); + } + // TODO Add the rest of operations with partial index and numbers + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor4.hpp b/src/oofemlib/tensor/FTensor/Tensor4.hpp new file mode 100644 index 000000000..27c6a763f --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor4.hpp @@ -0,0 +1,5 @@ +/* Declarations for Tensor4 */ + +#include "Tensor4/Tensor4_value.hpp" + +#include "Tensor4/Tensor4_Expr.hpp" diff --git a/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_Expr.hpp b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_Expr.hpp new file mode 100644 index 000000000..7cddc1575 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_Expr.hpp @@ -0,0 +1,113 @@ +/* Declare a wrapper class for generic rank 4 Tensor expressions. */ + +#pragma once + +#include "Tensor4_minus_Tensor4.hpp" +#include "Tensor4_plus_Tensor4.hpp" +#include "Tensor4_times_Tensor2_single.hpp" +#include "Tensor4_times_Tensor2_double.hpp" +#include "Tensor4_times_Tensor2_symmetric.hpp" +#include "Tensor4_times_Tensor3_triple.hpp" +#include "Tensor4_times_generic.hpp" + +#include "../permute.hpp" + +namespace FTensor +{ + template + class Tensor4_Expr + { + A iter; + + public: + Tensor4_Expr(const A &a) : iter(a) {} + T operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iter(N1, N2, N3, N4); + } + }; + + template + class Tensor4_Expr, T, Dim0, Dim1, Dim2, + Dim3, i, j, k, l> + { + Tensor4 &iter; + + public: + Tensor4_Expr(Tensor4 &a) : iter(a) {} + T &operator()(const int N1, const int N2, const int N3, const int N4) + { + return iter(N1, N2, N3, N4); + } + T operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iter(N1, N2, N3, N4); + } + + /* Various assignment operators. I have to explicitly declare the + second operator= because otherwise the compiler will generate its + own and not use the template code. */ + + template + auto &equals(const Tensor4_Expr &rhs) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + for(int kk = 0; kk < Dim2; ++kk) + for(int ll = 0; ll < Dim3; ++ll) + { + iter(ii, jj, kk, ll) = permute(*this, rhs, ii, jj, kk, ll); + } + return *this; + } + + template + auto &operator=(const Tensor4_Expr &rhs) + { + return equals(rhs); + } + + auto & + operator=(const Tensor4_Expr, T, Dim0, + Dim1, Dim2, Dim3, i, j, k, l> &rhs) + { + return equals(rhs); + } + + template + auto &operator+=(const Tensor4_Expr &rhs) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + for(int kk = 0; kk < Dim2; ++kk) + for(int ll = 0; ll < Dim3; ++ll) + { + iter(ii, jj, kk, ll) += permute(*this, rhs, ii, jj, kk, ll); + } + return *this; + } + + template + auto &operator-=(const Tensor4_Expr &rhs) + { + for(int ii = 0; ii < Dim0; ++ii) + for(int jj = 0; jj < Dim1; ++jj) + for(int kk = 0; kk < Dim2; ++kk) + for(int ll = 0; ll < Dim3; ++ll) + { + iter(ii, jj, kk, ll) += permute(*this, rhs, ii, jj, kk, ll); + } + return *this; + } + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_contracted.hpp b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_contracted.hpp new file mode 100644 index 000000000..6f2d73b32 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_contracted.hpp @@ -0,0 +1,109 @@ +/* A helper class that automatically returns the internal contraction + of a rank 4 tensor. */ + +#pragma once + +namespace FTensor +{ + template class Tensor4_contracted_23 + { + A iterA; + + public: + T operator()(const int N0, const int N1) const + { + T result(0); + for(int ii = 0; ii < Dim; ++ii) + { + result += iterA(N0, N1, ii, ii); + } + return result; + } + Tensor4_contracted_23(const A &a) : iterA(a) {} + }; + + template class Tensor4_contracted_13 + { + A iterA; + + public: + T operator()(const int N0, const int N1) const + { + T result(0); + for(int ii = 0; ii < Dim; ++ii) + { + result += iterA(N0, ii, N1, ii); + } + return result; + } + Tensor4_contracted_13(const A &a) : iterA(a) {} + }; + + template class Tensor4_contracted_12 + { + A iterA; + + public: + T operator()(const int N0, const int N1) const + { + T result(0); + for(int ii = 0; ii < Dim; ++ii) + { + result += iterA(N0, ii, ii, N1); + } + return result; + } + Tensor4_contracted_12(const A &a) : iterA(a) {} + }; + + template class Tensor4_contracted_03 + { + A iterA; + + public: + T operator()(const int N0, const int N1) const + { + T result(0); + for(int ii = 0; ii < Dim; ++ii) + { + result += iterA(ii, N0, N1, ii); + } + return result; + } + Tensor4_contracted_03(const A &a) : iterA(a) {} + }; + + template class Tensor4_contracted_02 + { + A iterA; + + public: + T operator()(const int N0, const int N1) const + { + T result(0); + for(int ii = 0; ii < Dim; ++ii) + { + result += iterA(ii, N0, ii, N1); + } + return result; + } + Tensor4_contracted_02(const A &a) : iterA(a) {} + }; + + template class Tensor4_contracted_01 + { + A iterA; + + public: + T operator()(const int N0, const int N1) const + { + T result(0); + for(int ii = 0; ii < Dim; ++ii) + { + result += iterA(ii, ii, N0, N1); + } + return result; + } + Tensor4_contracted_01(const A &a) : iterA(a) {} + }; +} diff --git a/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_minus_Tensor4.hpp b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_minus_Tensor4.hpp new file mode 100644 index 000000000..a8f52ae5f --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_minus_Tensor4.hpp @@ -0,0 +1,46 @@ +// Subtracts Tensor4 - Tensor4 -> Tensor4 + +#pragma once + +namespace FTensor +{ + template + class Tensor4_minus_Tensor4 + { + Tensor4_Expr iterA; + Tensor4_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) - permute(iterA, iterB, N1, N2, N3, N4); + } + + Tensor4_minus_Tensor4(const Tensor4_Expr &a, + const Tensor4_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + auto operator-( + const Tensor4_Expr &a, + const Tensor4_Expr &b) + { + using TensorExpr + = Tensor4_minus_Tensor4; + return Tensor4_Expr::V, Dim0_0, Dim1_0, + Dim2_0, Dim3_0, i0, j0, k0, l0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_plus_Tensor4.hpp b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_plus_Tensor4.hpp new file mode 100644 index 000000000..00a38480d --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_plus_Tensor4.hpp @@ -0,0 +1,46 @@ +// Adds Tensor4+Tensor4 -> Tensor4 + +#pragma once + +namespace FTensor +{ + template + class Tensor4_plus_Tensor4 + { + Tensor4_Expr iterA; + Tensor4_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) + permute(iterA, iterB, N1, N2, N3, N4); + } + + Tensor4_plus_Tensor4(const Tensor4_Expr &a, + const Tensor4_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + auto operator+( + const Tensor4_Expr &a, + const Tensor4_Expr &b) + { + using TensorExpr + = Tensor4_plus_Tensor4; + return Tensor4_Expr::V, Dim0_0, Dim1_0, + Dim2_0, Dim3_0, i0, j0, k0, l0>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor2_double.hpp b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor2_double.hpp new file mode 100644 index 000000000..6c7d027d1 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor2_double.hpp @@ -0,0 +1,336 @@ +#pragma once + +namespace FTensor +{ + // A(i,j,k,l) * B(m,n) double contraction + template + class Tensor4_times_Tensor2_double + { + Tensor4_Expr iterA; + Tensor2_Expr iterB; + + public: + typename promote::V operator()(const int N1, const int N2) const + { + typename promote::V result(0); + for(int xx = 0; xx < DimX; ++xx) + for(int yy = 0; yy < DimY; ++yy) + { + // Permutation is where the indices get checked. + result += Permutation4().eval( + iterA, N1, N2, xx, yy) + * Permutation2().eval(iterB, xx, yy); + } + return result; + } + + Tensor4_times_Tensor2_double( + const Tensor4_Expr &iter_a, + const Tensor2_Expr &iter_b) + : iterA(iter_a), iterB(iter_b) + {} + }; + + // A(i,j,k,l)*B(k,l) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, b)); + } + + // B(k,l)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(l,k) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, b)); + } + + // B(l,k)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(j,l) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim0, Dim2, i, + k>(TensorExpr(a, b)); + } + + // B(j,l)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(l,j) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim0, Dim2, i, + k>(TensorExpr(a, b)); + } + + // B(l,j)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(j,k) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim0, Dim3, i, + l>(TensorExpr(a, b)); + } + + // B(j,k)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(k,j) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim0, Dim3, i, + l>(TensorExpr(a, b)); + } + + // A(i,j,k,l)*B(k,j) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(i,l) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim1, Dim2, j, + k>(TensorExpr(a, b)); + } + + // B(i,l)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(l,i) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim1, Dim2, j, + k>(TensorExpr(a, b)); + } + + // B(l,i)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(i,k) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim1, Dim2, j, + l>(TensorExpr(a, b)); + } + + // B(i,k)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(k,i) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim1, Dim2, j, + l>(TensorExpr(a, b)); + } + + // A(i,j,k,l)*B(k,i) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(i,j) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim2, Dim3, k, + l>(TensorExpr(a, b)); + } + + // A(i,j,k,l)*B(i,j) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(j,i) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_double; + return Tensor2_Expr::V, Dim2, Dim3, k, + l>(TensorExpr(a, b)); + } + + // A(i,j,k,l)*B(j,i) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor2_single.hpp b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor2_single.hpp new file mode 100644 index 000000000..5ddee1a66 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor2_single.hpp @@ -0,0 +1,238 @@ +#pragma once + +namespace FTensor +{ + // A(i,j,k,l) * B(m,n) single contraction + template + class Tensor4_times_Tensor2_single + { + Tensor4_Expr iterA; + Tensor2_Expr iterB; + + public: + typename promote::V + operator()(const int N1, const int N2, const int N3, const int N4) const + { + typename promote::V result(0); + for(int xx = 0; xx < DimX; ++xx) + { + // Permutation is where the indices get checked. + result += Permutation4().eval( + iterA, N1, N2, N3, xx) + * Permutation2().eval(iterB, xx, N4); + } + return result; + } + + Tensor4_times_Tensor2_single( + const Tensor4_Expr &iter_a, + const Tensor2_Expr &iter_b) + : iterA(iter_a), iterB(iter_b) + {} + }; + + // A(i,j,k,l)*B(l,m) + + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_single; + return Tensor4_Expr::V, Dim0, Dim1, + Dim2, Dim4, i, j, k, m>(TensorExpr(a, b)); + } + + // B(l,m)*A(i,j,k,l) + + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(m,l) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_single; + return Tensor4_Expr::V, Dim0, Dim1, + Dim2, Dim4, i, j, k, m>(TensorExpr(a, b)); + } + + // B(m,l)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(k,m) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_single; + return Tensor4_Expr::V, Dim0, Dim1, + Dim3, Dim4, i, j, l, m>(TensorExpr(a, b)); + } + + // B(k,m)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(m,k) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_single; + return Tensor4_Expr::V, Dim0, Dim1, + Dim3, Dim4, i, j, l, m>(TensorExpr(a, b)); + } + + // B(m,k)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(j,m) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_single; + return Tensor4_Expr::V, Dim0, Dim2, + Dim3, Dim4, i, k, l, m>(TensorExpr(a, b)); + } + + // B(j,m)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(m,j) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_single; + return Tensor4_Expr::V, Dim0, Dim2, + Dim3, Dim4, i, k, l, m>(TensorExpr(a, b)); + } + + // B(m,j)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(i,m) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_single; + return Tensor4_Expr::V, Dim1, Dim2, + Dim3, Dim4, j, k, l, m>(TensorExpr(a, b)); + } + + // B(i,m)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(m,i) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor2_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_single; + return Tensor4_Expr::V, Dim1, Dim2, + Dim3, Dim4, j, k, l, m>(TensorExpr(a, b)); + } + + // B(m,i)*A(i,j,k,l) + template + auto + operator*(const Tensor2_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor2_symmetric.hpp b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor2_symmetric.hpp new file mode 100644 index 000000000..e056a9ccd --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor2_symmetric.hpp @@ -0,0 +1,398 @@ +/* This file has all of the declarations for expressions like + Tensor4*Tensor2_symmetric and Tensor2_symmetric*Tensor4, yielding a + Tensor2. */ + +#pragma once + +namespace FTensor +{ + /* A(i,j,k,l)*B(k,l) */ + + template + class Tensor4_times_Tensor2_symmetric_23 + { + Tensor4_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(N1, N2, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(N1, N2, 0, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(N1, N2, 0, 0) * iterB(0, 0); + } + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + + Tensor4_times_Tensor2_symmetric_23( + const Tensor4_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_Expr< + Tensor4_times_Tensor2_symmetric_23, + typename promote::V, Dim0, Dim1, i, j> + operator*(const Tensor4_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_symmetric_23; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, b)); + } + + /* B(k,l)*A(i,j,k,l) */ + + template + Tensor2_Expr< + Tensor4_times_Tensor2_symmetric_23, + typename promote::V, Dim0, Dim1, i, j> + operator*(const Tensor2_symmetric_Expr &b, + const Tensor4_Expr &a) + { + using TensorExpr + = Tensor4_times_Tensor2_symmetric_23; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, b)); + } + + /* A(i,j,k,l)*B(l,k) */ + + template + class Tensor4_times_Tensor2_symmetric_32 + { + Tensor4_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(N1, N2, Current_Dim0 - 1, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(N1, N2, 0, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(N1, N2, 0, 0) * iterB(0, 0); + } + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + + Tensor4_times_Tensor2_symmetric_32( + const Tensor4_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_Expr< + Tensor4_times_Tensor2_symmetric_32, + typename promote::V, Dim0, Dim1, i, j> + operator*(const Tensor4_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_symmetric_32; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, b)); + } + + /* B(l,k)*A(i,j,k,l) */ + + template + Tensor2_Expr< + Tensor4_times_Tensor2_symmetric_32, + typename promote::V, Dim0, Dim1, i, j> + operator*(const Tensor2_symmetric_Expr &b, + const Tensor4_Expr &a) + { + using TensorExpr + = Tensor4_times_Tensor2_symmetric_32; + return Tensor2_Expr::V, Dim0, Dim1, i, + j>(TensorExpr(a, b)); + } + + /* A(i,j,k,l)*B(i,l) */ + + template + class Tensor4_times_Tensor2_symmetric_03 + { + Tensor4_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, N2, Current_Dim1 - 1) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(0, N1, N2, Current_Dim1 - 1) * iterB(0, Current_Dim1 - 1) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, N2, 0) * iterB(0, 0); + } + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + + Tensor4_times_Tensor2_symmetric_03( + const Tensor4_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_Expr< + Tensor4_times_Tensor2_symmetric_03, + typename promote::V, Dim1, Dim2, j, k> + operator*(const Tensor4_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_symmetric_03; + return Tensor2_Expr::V, Dim1, Dim2, j, + k>(TensorExpr(a, b)); + } + + /* B(i,l)*A(i,j,k,l) */ + + template + Tensor2_Expr< + Tensor4_times_Tensor2_symmetric_03, + typename promote::V, Dim1, Dim2, j, k> + operator*(const Tensor2_symmetric_Expr &b, + const Tensor4_Expr &a) + { + using TensorExpr + = Tensor4_times_Tensor2_symmetric_03; + return Tensor2_Expr::V, Dim1, Dim2, j, + k>(TensorExpr(a, b)); + } + + /* A(i,j,k,l)*B(l,i) */ + + template + class Tensor4_times_Tensor2_symmetric_30 + { + Tensor4_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, N2, Current_Dim1 - 1) + * iterB(Current_Dim1 - 1, Current_Dim0 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(0, N1, N2, Current_Dim1 - 1) * iterB(Current_Dim1 - 1, 0) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, N2, 0) * iterB(0, 0); + } + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + + Tensor4_times_Tensor2_symmetric_30( + const Tensor4_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_Expr< + Tensor4_times_Tensor2_symmetric_30, + typename promote::V, Dim1, Dim2, j, k> + operator*(const Tensor4_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_symmetric_30; + return Tensor2_Expr::V, Dim1, Dim2, j, + k>(TensorExpr(a, b)); + } + + /* B(l,i)*A(i,j,k,l) */ + + template + Tensor2_Expr< + Tensor4_times_Tensor2_symmetric_30, + typename promote::V, Dim1, Dim2, j, k> + operator*(const Tensor2_symmetric_Expr &b, + const Tensor4_Expr &a) + { + using TensorExpr + = Tensor4_times_Tensor2_symmetric_30; + return Tensor2_Expr::V, Dim1, Dim2, j, + k>(TensorExpr(a, b)); + } + + /* A(i,j,k,l)*B(i,k) */ + + template + class Tensor4_times_Tensor2_symmetric_02 + { + Tensor4_Expr iterA; + Tensor2_symmetric_Expr iterB; + + template + typename promote::V + eval(const int N1, const int N2, const Number &, + const Number &) const + { + return iterA(Current_Dim0 - 1, N1, Current_Dim1 - 1, N2) + * iterB(Current_Dim0 - 1, Current_Dim1 - 1) + + eval(N1, N2, Number(), + Number()); + } + template + typename promote::V + eval(const int N1, const int N2, const Number<1> &, + const Number &) const + { + return iterA(0, N1, Current_Dim1 - 1, N2) * iterB(0, Current_Dim1 - 1) + + eval(N1, N2, Number(), Number()); + } + typename promote::V eval(const int N1, const int N2, + const Number<1> &, const Number<1> &) const + { + return iterA(0, N1, 0, N2) * iterB(0, 0); + } + + public: + typename promote::V operator()(const int N1, const int N2) const + { + return eval(N1, N2, Number(), Number()); + } + + Tensor4_times_Tensor2_symmetric_02( + const Tensor4_Expr &a, + const Tensor2_symmetric_Expr &b) + : iterA(a), iterB(b) + {} + }; + + template + Tensor2_Expr< + Tensor4_times_Tensor2_symmetric_02, + typename promote::V, Dim1, Dim2, j, l> + operator*(const Tensor4_Expr &a, + const Tensor2_symmetric_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor2_symmetric_02; + return Tensor2_Expr::V, Dim1, Dim2, j, + l>(TensorExpr(a, b)); + } + + /* B(i,k)*A(i,j,k,l) */ + + template + Tensor2_Expr< + Tensor4_times_Tensor2_symmetric_02, + typename promote::V, Dim1, Dim2, j, l> + operator*(const Tensor2_symmetric_Expr &b, + const Tensor4_Expr &a) + { + using TensorExpr + = Tensor4_times_Tensor2_symmetric_02; + return Tensor2_Expr::V, Dim1, Dim2, j, + l>(TensorExpr(a, b)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor3_triple.hpp b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor3_triple.hpp new file mode 100644 index 000000000..c884b8e64 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_Tensor3_triple.hpp @@ -0,0 +1,639 @@ +#pragma once + +namespace FTensor +{ + // A(i,j,k,l) * B(m,n,o) triple contraction + template + class Tensor4_times_Tensor3_triple + { + Tensor4_Expr iterA; + Tensor3_Expr iterB; + + public: + typename promote::V operator()(const int N1) const + { + typename promote::V result(0); + for(int xx = 0; xx < DimX; ++xx) + for(int yy = 0; yy < DimY; ++yy) + for(int zz = 0; zz < DimZ; ++zz) + { + // Permutation is where the indices get checked. + result + += Permutation4().eval( + iterA, N1, xx, yy, zz) + * Permutation3().eval(iterB, xx, + yy, zz); + } + return result; + } + + Tensor4_times_Tensor3_triple( + const Tensor4_Expr &iter_a, + const Tensor3_Expr &iter_b) + : iterA(iter_a), iterB(iter_b) + {} + }; + + // A(i,j,k,l)*B(j,k,l) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim0, i>( + TensorExpr(a, b)); + } + + // B(j,k,l)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(j,l,k) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim0, i>( + TensorExpr(a, b)); + } + + // B(j,l,k)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(k,j,l) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim0, i>( + TensorExpr(a, b)); + } + + // B(k,j,l)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(k,l,j) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim0, i>( + TensorExpr(a, b)); + } + + // B(k,l,j)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(l,j,k) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim0, i>( + TensorExpr(a, b)); + } + + // B(l,j,k)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(l,k,j) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim0, i>( + TensorExpr(a, b)); + } + + // B(l,k,j)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(i,k,l) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim1, j>( + TensorExpr(a, b)); + } + + // B(i,k,l)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(i,l,k) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim1, j>( + TensorExpr(a, b)); + } + + // B(i,l,k)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(k,i,l) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim1, j>( + TensorExpr(a, b)); + } + + // B(k,i,l)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(k,l,i) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim1, j>( + TensorExpr(a, b)); + } + + // B(k,l,i)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(l,i,k) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim1, j>( + TensorExpr(a, b)); + } + + // B(l,i,k)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(l,k,i) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim1, j>( + TensorExpr(a, b)); + } + + // B(l,k,i)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(i,j,l) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim2, k>( + TensorExpr(a, b)); + } + + // B(i,j,l)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(i,l,j) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim2, k>( + TensorExpr(a, b)); + } + + // B(i,l,j)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(j,i,l) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim2, k>( + TensorExpr(a, b)); + } + + // B(j,i,l)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(j,l,i) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim2, k>( + TensorExpr(a, b)); + } + + // B(j,l,i)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(l,i,j) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim2, k>( + TensorExpr(a, b)); + } + + // B(l,i,j)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(l,j,i) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim2, k>( + TensorExpr(a, b)); + } + + // B(l,j,i)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(i,j,k) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim3, l>( + TensorExpr(a, b)); + } + + // B(i,j,k)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(i,k,j) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim3, l>( + TensorExpr(a, b)); + } + + // B(i,k,j)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(j,i,k) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim3, l>( + TensorExpr(a, b)); + } + + // B(j,i,k)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(j,k,i) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim3, l>( + TensorExpr(a, b)); + } + + // B(j,k,i)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(k,i,j) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim3, l>( + TensorExpr(a, b)); + } + + // B(k,i,j)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } + + // A(i,j,k,l)*B(k,j,i) + template + auto + operator*(const Tensor4_Expr &a, + const Tensor3_Expr &b) + { + using TensorExpr + = Tensor4_times_Tensor3_triple; + return Tensor1_Expr::V, Dim3, l>( + TensorExpr(a, b)); + } + + // B(k,j,i)*A(i,j,k,l) + template + auto + operator*(const Tensor3_Expr &b, + const Tensor4_Expr &a) + { + return a * b; + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_generic.hpp b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_generic.hpp new file mode 100644 index 000000000..c9576e5b9 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_times_generic.hpp @@ -0,0 +1,44 @@ +/* Multiplies a Tensor4 with a generic, yielding a Tensor2. */ + +#pragma once + +namespace FTensor +{ + template + class Tensor4_times_generic + { + const Tensor4_Expr iterA; + const U d; + + public: + typename promote::V operator()(const int N1, const int N2, const int N3, const int N4) const + { + return iterA(N1, N2, N3, N4) * d; + } + + Tensor4_times_generic(const Tensor4_Expr &a, + const U &d0) + : iterA(a), d(d0) + {} + }; + + template + Tensor4_Expr, + typename promote::V, Dim0, Dim1, Dim2, Dim3, i, j, k, l> + operator*(const Tensor4_Expr &a, const U &d0) + { + using TensorExpr = Tensor4_times_generic; + return Tensor4_Expr::V, Dim0, Dim1, Dim2, Dim3, i, + j, k, l>(TensorExpr(a, d0)); + } + + template + Tensor4_Expr, + typename promote::V, Dim0, Dim1, Dim2, Dim3, i, j, k, l> + operator*(const U &d0, const Tensor4_Expr &a) + { + using TensorExpr = Tensor4_times_generic; + return Tensor4_Expr::V, Dim0, Dim1, Dim2, Dim3, i, + j, k, l>(TensorExpr(a, d0)); + } +} diff --git a/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_value.hpp b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_value.hpp new file mode 100644 index 000000000..ab3864b53 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/Tensor4/Tensor4_value.hpp @@ -0,0 +1,287 @@ +/* A general version, not for pointers. */ + +#pragma once + +#include "Tensor4_contracted.hpp" + +#include +#include "floatmatrixf.h" +#ifdef FTENSOR_DEBUG +#include +#include +#endif + +namespace FTensor +{ + template + class Tensor4 + { + protected: + T data[Tensor_Dim0][Tensor_Dim1][Tensor_Dim2][Tensor_Dim3]; + + public: + /* Initialization operators */ + template Tensor4(U... d) : data{d...} + { + static_assert(sizeof...(d) == sizeof(data) / sizeof(T), + "Incorrect number of Arguments. Constructor should " + "initialize the entire Tensor"); + } + + Tensor4() {} + /* There are two operator(int,int,int,int)'s, one for non-consts + that lets you change the value, and one for consts that + doesn't. */ + T &operator()(const int N1, const int N2, const int N3, const int N4) + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0 + || N3 >= Tensor_Dim2 || N3 < 0 || N4 >= Tensor_Dim3 || N4 < 0) + { + std::stringstream s; + s << "Bad index in Tensor4.operator(" << N1 + << "," << N2 << "," << N3 << "," << N4 << ") const" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[N1][N2][N3][N4]; + } + + T operator()(const int N1, const int N2, const int N3, const int N4) const + { +#ifdef FTENSOR_DEBUG + if(N1 >= Tensor_Dim0 || N1 < 0 || N2 >= Tensor_Dim1 || N2 < 0 + || N3 >= Tensor_Dim2 || N3 < 0 || N4 >= Tensor_Dim3 || N4 < 0) + { + std::stringstream s; + s << "Bad index in Tensor4.operator(" << N1 + << "," << N2 << "," << N3 << "," << N4 << ")" << std::endl; + throw std::out_of_range(s.str()); + } +#endif + return data[N1][N2][N3][N4]; + } + + /* These operator()'s are the first part in constructing template + expressions. They can be used to slice off lower dimensional + parts. */ + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim2 + && Tensor_Dim3 >= Dim3), + Tensor4_Expr, + T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>>::type + operator()(const Index, const Index, + const Index, const Index) + { + return Tensor4_Expr< + Tensor4, T, + Dim0, Dim1, Dim2, Dim3, i, j, k, l>(*this); + }; + + template + typename std::enable_if< + (Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1 && Tensor_Dim2 >= Dim2 + && Tensor_Dim3 >= Dim3), + Tensor4_Expr< + const Tensor4, + T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>>::type + operator()(const Index, const Index, + const Index, const Index) const + { + return Tensor4_Expr< + const Tensor4, + T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>(*this); + }; + + /* These operators are for internal contractions, resulting in a Tensor2. + * For example something like A(k,i,k,j) */ + + // (i,j,k,k) + template + auto operator()(const Index, const Index, + const Index, const Index) const + { + static_assert(Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim1 + && Tensor_Dim2 >= Dim23 && Tensor_Dim3 >= Dim23, + "Incompatible indices"); + + using TensorExpr = Tensor4_contracted_23< + Tensor4, T, + Dim23>; + return Tensor2_Expr(TensorExpr(*this)); + }; + + // (i,j,k,j) + template + auto operator()(const Index, const Index, + const Index, const Index) const + { + static_assert(Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim13 + && Tensor_Dim2 >= Dim2 && Tensor_Dim3 >= Dim13, + "Incompatible indices"); + + using TensorExpr = Tensor4_contracted_13< + Tensor4, T, + Dim13>; + return Tensor2_Expr(TensorExpr(*this)); + }; + + // (i,j,j,l) + template + auto operator()(const Index, const Index, + const Index, const Index) const + { + static_assert(Tensor_Dim0 >= Dim0 && Tensor_Dim1 >= Dim12 + && Tensor_Dim2 >= Dim12 && Tensor_Dim3 >= Dim3, + "Incompatible indices"); + + using TensorExpr = Tensor4_contracted_12< + Tensor4, T, + Dim12>; + return Tensor2_Expr(TensorExpr(*this)); + }; + + // (i,j,k,i) + template + auto operator()(const Index, const Index, + const Index, const Index) const + { + static_assert(Tensor_Dim0 >= Dim03 && Tensor_Dim1 >= Dim1 + && Tensor_Dim2 >= Dim2 && Tensor_Dim3 >= Dim03, + "Incompatible indices"); + + using TensorExpr = Tensor4_contracted_03< + Tensor4, T, + Dim03>; + return Tensor2_Expr(TensorExpr(*this)); + }; + + // (i,j,i,l) + template + auto operator()(const Index, const Index, + const Index, const Index) const + { + static_assert(Tensor_Dim0 >= Dim02 && Tensor_Dim1 >= Dim1 + && Tensor_Dim2 >= Dim02 && Tensor_Dim3 >= Dim3, + "Incompatible indices"); + + using TensorExpr = Tensor4_contracted_02< + Tensor4, T, + Dim02>; + return Tensor2_Expr(TensorExpr(*this)); + }; + + // (i,i,k,l) + template + auto operator()(const Index, const Index, + const Index, const Index) const + { + static_assert(Tensor_Dim0 >= Dim01 && Tensor_Dim1 >= Dim01 + && Tensor_Dim2 >= Dim2 && Tensor_Dim3 >= Dim3, + "Incompatible indices"); + + using TensorExpr = Tensor4_contracted_01< + Tensor4, T, + Dim01>; + return Tensor2_Expr(TensorExpr(*this)); + }; + + /* This is for expressions where a number is used for one slot, and + an index for another, yielding a Tensor3_Expr. The non-const + versions don't actually create a Tensor3_number_rhs_[0123] object. + They create a Tensor3_Expr directly, which provides the + appropriate indexing operators. The const versions do create a + Tensor3_number_[0123]. */ + // TODO + }; + + + +} + +/// JSON compatible output + +namespace FTensor +{ + template + std::ostream &Tensor4_0001( + std::ostream &os, + const Tensor4 &t, + const int &iterator0, const int &iterator1, const int &iterator2) + { + os << '['; + for(int i = 0; i < Tensor_Dim3 - 1; ++i) + { + os << t(iterator0, iterator1, iterator2, i); + os << ','; + } + os << t(iterator0, iterator1, iterator2, Tensor_Dim3 - 1); + os << ']'; + + return os; + } + + template + std::ostream &Tensor4_0010( + std::ostream &os, + const Tensor4 &t, + const int &iterator0, const int &iterator1) + { + os << '['; + for(int i = 0; i < Tensor_Dim2 - 1; ++i) + { + FTensor::Tensor4_0001(os, t, iterator0, iterator1, i); + os << ','; + } + FTensor::Tensor4_0001(os, t, iterator0, iterator1, Tensor_Dim2 - 1); + os << ']'; + + return os; + } + + template + std::ostream &Tensor4_0100( + std::ostream &os, + const Tensor4 &t, + const int &iterator0) + { + os << '['; + for(int i = 0; i < Tensor_Dim1 - 1; ++i) + { + FTensor::Tensor4_0010(os, t, iterator0, i); + os << ','; + } + FTensor::Tensor4_0010(os, t, iterator0, Tensor_Dim1 - 1); + os << ']'; + + return os; + } +} + +template +std::ostream &operator<<(std::ostream &os, + const FTensor::Tensor4 &t) +{ + os << '['; + for(int i = 0; i < Tensor_Dim0 - 1; ++i) + { + FTensor::Tensor4_0100(os, t, i); + os << ','; + } + FTensor::Tensor4_0100(os, t, Tensor_Dim0 - 1); + os << ']'; + + return os; +} diff --git a/src/oofemlib/tensor/FTensor/cross.hpp b/src/oofemlib/tensor/FTensor/cross.hpp new file mode 100644 index 000000000..055b0aa18 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/cross.hpp @@ -0,0 +1,15 @@ +/* Cross product in 3 dimensions */ + +#pragma once + +#include "Levi_Civita.hpp" + +namespace FTensor +{ + template + auto cross(const Tensor1_Expr &a, + const Tensor1_Expr &b, const Index &) + { + return a * b * levi_civita(Index(), Index(), Index()); + } +} diff --git a/src/oofemlib/tensor/FTensor/derivative_delta.hpp b/src/oofemlib/tensor/FTensor/derivative_delta.hpp new file mode 100644 index 000000000..cca803f8b --- /dev/null +++ b/src/oofemlib/tensor/FTensor/derivative_delta.hpp @@ -0,0 +1,16 @@ +template class derivative_delta +{ +public: + Tensor1 d_ijk_plus, d_ijk_minus; + Tensor1 d_xyz; + + derivative_delta(double dx, double dy, double dz, int di, int dj, int dk) + : d_ijk_plus(di, dj, dk), d_ijk_minus(di, dj, dk), d_xyz(dx, dy, dz) + {} + + derivative_delta(double dx, double dy, double dz, int di_plus, int dj_plus, + int dk_plus, int di_minus, int dj_minus, int dk_minus) + : d_ijk_plus(di_plus, dj_plus, dk_plus), + d_ijk_minus(di_minus, dj_minus, dk_minus), d_xyz(dx, dy, dz) + {} +}; diff --git a/src/oofemlib/tensor/FTensor/error_when_instantiated.hpp b/src/oofemlib/tensor/FTensor/error_when_instantiated.hpp new file mode 100644 index 000000000..e3a695983 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/error_when_instantiated.hpp @@ -0,0 +1,11 @@ +#pragma once + +namespace FTensor +{ + // Helper function to so that the generic permute() only fails if + // actually instantiated + template constexpr bool error_when_instantiated() + { + return false; + } +} diff --git a/src/oofemlib/tensor/FTensor/permute.hpp b/src/oofemlib/tensor/FTensor/permute.hpp new file mode 100644 index 000000000..4a8500fd7 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/permute.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "Permutation2.hpp" +#include "Permutation3.hpp" +#include "Permutation4.hpp" + +namespace FTensor +{ + template + U permute(const Tensor2_Expr &, + const Tensor2_Expr &rhs, + const int N0, const int N1) + { + return Permutation2().eval(rhs, N0, N1); + } + + template + U permute(const Tensor3_Expr &, + const Tensor3_Expr &rhs, + const int N0, const int N1, const int N2) + { + return Permutation3().eval(rhs, N0, N1, + N2); + } + + template + U permute( + const Tensor4_Expr &, + const Tensor4_Expr + &rhs, + const int N0, const int N1, const int N2, const int N3) + { + return Permutation4().eval( + rhs, N0, N1, N2, N3); + } +} diff --git a/src/oofemlib/tensor/FTensor/promote.hpp b/src/oofemlib/tensor/FTensor/promote.hpp new file mode 100644 index 000000000..39caf2af4 --- /dev/null +++ b/src/oofemlib/tensor/FTensor/promote.hpp @@ -0,0 +1,35 @@ +/* Traits that allow auto-promotion of int's to double's, double's to + complex, etc. Shamelessly stolen from + + http://extreme.indiana.edu/~tveldhui/papers/techniques/ + + For now, only int, double, and complex are covered. If you + want more, just insert a DECLARE_PROMOTE(A,B,C), where A and B are + the two types, and C is what they should be coerced to. */ + +#pragma once + +namespace FTensor +{ + template class promote + { + public: + using V = T1; + }; + +#define DECLARE_PROMOTE(A, B, C) \ + template <> class promote \ + { \ + public: \ + using V = C; \ + } + + DECLARE_PROMOTE(int, double, double); + DECLARE_PROMOTE(double, int, double); + DECLARE_PROMOTE(int, std::complex, std::complex); + DECLARE_PROMOTE(std::complex, int, std::complex); + DECLARE_PROMOTE(double, std::complex, std::complex); + DECLARE_PROMOTE(std::complex, double, std::complex); + +#undef DECLARE_PROMOTE +} diff --git a/src/oofemlib/irresulttype.h b/src/oofemlib/tensor/index.h similarity index 66% rename from src/oofemlib/irresulttype.h rename to src/oofemlib/tensor/index.h index 50d6b80fa..dbee6edb3 100644 --- a/src/oofemlib/irresulttype.h +++ b/src/oofemlib/tensor/index.h @@ -32,20 +32,33 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef irresulttype_h -#define irresulttype_h +#pragma once +#include "tensor/FTensor.hpp" -namespace oofem { -/** - * Type defining the return values of InputRecord reading operations. - * IRRT_OK the corresponding value to given keyword was successfully read. - * the answer parameter contains the value. - * IRRT_NOTFOUND the keyword is not found; the answer is not modified - * IRRT_BAD_FORMAT the keyword was found but the record is not correctly formatted. - */ -enum IRResultType { IRRT_OK = 0, IRRT_NOTFOUND, IRRT_BAD_FORMAT }; -} +using namespace FTensor; + + +static FTensor::Index<'i', 3> i_3; +static FTensor::Index<'j', 3> j_3; +static FTensor::Index<'k', 3> k_3; +static FTensor::Index<'l', 3> l_3; +static FTensor::Index<'m', 3> m_3; +static FTensor::Index<'n', 3> n_3; + +/*static FTensor::Index<'o', 3> o_3; +static FTensor::Index<'p', 3> p_3; +static FTensor::Index<'q', 3> q_3; +static FTensor::Index<'r', 3> r_3; +static FTensor::Index<'s', 3> s_3; +static FTensor::Index<'t', 3> t_3; +static FTensor::Index<'u', 3> u_3; +static FTensor::Index<'v', 3> v_3; +static FTensor::Index<'w', 3> w_3; +static FTensor::Index<'x', 3> x_3; +static FTensor::Index<'y', 3> y_3; +static FTensor::Index<'z', 3> z_3; +*/ + -#endif // irresulttype_h \ No newline at end of file diff --git a/src/sm/microplane.C b/src/oofemlib/tensor/tensor1.h similarity index 61% rename from src/sm/microplane.C rename to src/oofemlib/tensor/tensor1.h index e39d38b09..e8d4a5568 100644 --- a/src/sm/microplane.C +++ b/src/oofemlib/tensor/tensor1.h @@ -32,44 +32,49 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "microplane.h" +#include "floatarray.h" +#include "mathfem.h" +#include "index.h" +#pragma once + +using namespace FTensor; + -namespace oofem { -Microplane :: Microplane(IntegrationRule *ir, int n, MaterialMode mode) : - GaussPoint(ir, n, FloatArray(), 0., mode) - // Constructor. Creates a Microplane belonging to element e, with number - // n, with coordinates a, with weight w. -{ } +/** + * Functions providing basic operations with tensors + * based on FTensor library + * It provides transformation from the second and fourth order tensors in 3d to FloatArrayF<9> and FloatArray<9,9> + * It provides calculation of determinant, cofactor, inverse, and tensor cross product + * More to be added gradually + * @author Martin Horak + **/ +namespace oofem { -Microplane :: ~Microplane() -// Destructor. -{ } + class Tensor1_3d : public Tensor1 + { + public: + using Tensor1 :: Tensor1; + Tensor1_3d(const oofem::FloatArrayF<3> &array){ + this->data[0] = array.at(1); + this->data[1] = array.at(2); + this->data[2] = array.at(3); + } + const inline FloatArrayF<3> to_voigt_form() + { + return { + this->operator()(0), + this->operator()(1), + this->operator()(2), + }; + } -void -Microplane :: printOutputAt(FILE *File, TimeStep *tStep) -// Prints the strains and stresses on the data file. -{ - /* - * int i ; - * // int n; - * - * - * fprintf (File," GP %d :",number) ; - * if (matStatus) matStatus -> printOutputAt (File,tStep) ; - * - * if ( numberOfGp != 0) // layered material - * { - * fprintf (File,"Layers report \n{\n"); - * for ( i = 0; i< numberOfGp ; i++) - * { - * gaussPoints[i]->printOutputAt (File,tStep); - * } - * fprintf (File,"} end layers report\n"); - * } - */ -} + }; + + } // end namespace oofem + + diff --git a/src/oofemlib/tensor/tensor2.h b/src/oofemlib/tensor/tensor2.h new file mode 100644 index 000000000..98accc941 --- /dev/null +++ b/src/oofemlib/tensor/tensor2.h @@ -0,0 +1,572 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "floatmatrix.h" +#include "floatarray.h" +#include "mathfem.h" +#include "index.h" +#include "tensor1.h" +#include "tensor4.h" +#pragma once + +using namespace FTensor; + + + +/** + * Functions providing basic operations with tensors + * based on FTensor library + * It provides transformation from the second and fourth order tensors in 3d to FloatArrayF<9> and FloatArray<9,9> + * It provides calculation of determinant, cofactor, inverse, and tensor cross product + * More to be added gradually + * @author Martin Horak + **/ + +namespace oofem { +class Tensor2_3d : public Tensor2< double, 3, 3 > +{ +public: + using Tensor2< double, 3, 3 >::Tensor2; + + /** + * Creates second-order tensor in 3d + * Initialized with zeros + */ + + Tensor2_3d() { + this->data [ 0 ] [ 0 ] = 0; + this->data [ 0 ] [ 1 ] = 0.; + this->data [ 0 ] [ 2 ] = 0.; + this->data [ 1 ] [ 0 ] = 0.; + this->data [ 1 ] [ 1 ] = 0.; + this->data [ 1 ] [ 2 ] = 0.; + this->data [ 2 ] [ 0 ] = 0.; + this->data [ 2 ] [ 1 ] = 0.; + this->data [ 2 ] [ 2 ] = 0.; + } + + /** + * Creates a second-order order tensor in 3d from floatarrayf<9> + */ + + Tensor2_3d(const oofem::FloatArrayF< 9 > &array) { + this->data [ 0 ] [ 0 ] = array.at(1); + this->data [ 0 ] [ 1 ] = array.at(6); + this->data [ 0 ] [ 2 ] = array.at(5); + this->data [ 1 ] [ 0 ] = array.at(9); + this->data [ 1 ] [ 1 ] = array.at(2); + this->data [ 1 ] [ 2 ] = array.at(4); + this->data [ 2 ] [ 0 ] = array.at(8); + this->data [ 2 ] [ 1 ] = array.at(7); + this->data [ 2 ] [ 2 ] = array.at(3); + } + + /** + * Transforms a second-order tensor into a floatarrayf<9>, using the Voigt notation + */ + + const inline FloatArrayF< 9 >to_voigt_form() + { + return { + this->operator()(0, 0), + this->operator()(1, 1), + this->operator()(2, 2), + this->operator()(1, 2), + this->operator()(0, 2), + this->operator()(0, 1), + this->operator()(2, 1), + this->operator()(2, 0), + this->operator()(1, 0) + }; + } + + + /** + * Computes power of a second order tensor + * @param pow power + * @param nf tolerance for eigenvalue calculation + * @return Power of a Second-order tensor + */ + Tensor2_3d computeTensorPower(double pow, int nf = 1e-10) + { + auto [ eVals, eVecs ] = this->eigs(nf); + return computeTensorPowerFromEigs(eVals, eVecs, pow); + } + + /** + * Computes power of a second order tensor from eigenvalues and eigenvectors + * @param eVals eigen values + * @param eVecs eigenvectors + * @param m power + * @return Power of a Second-order tensor + */ + + static Tensor2_3d computeTensorPowerFromEigs(const FloatArray &eVals, const FloatMatrix &eVecs, double m) + { + Tensor2_3d Cpow; + for ( int i = 0; i < 3; i++ ) { + for ( int j = 0; j < 3; j++ ) { + Cpow(i, j) = pow(eVals.at(1), m) * eVecs(i, 0) * eVecs(j, 0) + pow(eVals.at(2), m) * eVecs(i, 1) * eVecs(j, 1) + pow(eVals.at(3), m) * eVecs(i, 2) * eVecs(j, 2); + } + } + return Cpow; + } + + /** + * Computes power of a second order tensor from eigenvalues and eigenvectors and given coeffcinets for each eigenvalue + * @param eVals eigen values + * @param eVecs eigenvectors + * @param m power + * @param coeff coefficients + * @return Power of a Second-order tensor + */ + static Tensor2_3d computeTensorPowerFromEigs(const FloatArray &eVals, const FloatMatrix &eVecs, double m, const FloatArray &coeff) + { + Tensor2_3d Cpow; + for ( int i = 0; i < 3; i++ ) { + for ( int j = 0; j < 3; j++ ) { + Cpow(i, j) -= coeff.at(1) * pow(eVals.at(1), m) * eVecs.at(i, 0) * eVecs.at(j, 0) + coeff.at(2) * pow(eVals.at(2), m) * eVecs.at(i, 1) * eVecs.at(j, 1) + coeff.at(3) * pow(eVals.at(3), m) * eVecs.at(i, 2) * eVecs.at(j, 2); + } + } + return Cpow; + } + + + + /** + * Solves the eigenvalues and eigenvectors of symmetric second-order tensor + * adapted from FloatMatrix function jacobi_ + * + * @param nf - number of significant figures + * @return pair of eigenvalues and eigenvectors + */ + std::pair< FloatArrayF< 3 >, FloatMatrixF< 3, 3 > >eigs(int nf = 15) const + { + Tensor2_3d copy(* this); + // Local variables + int neq = 3; + double c_b2 = .10; + + FloatArrayF< 3 >eval; + FloatMatrixF< 3, 3 >v; + + for ( int i = 1; i <= neq; i++ ) { + eval.at(i) = copy(i - 1, i - 1); + } + + double tol = pow(c_b2, nf); + double sum = 0.0; + for ( int i = 1; i <= neq; ++i ) { + for ( int j = 1; j <= neq; ++j ) { + sum += fabs(copy(i - 1, j - 1) ); + v.at(i, j) = 0.0; + } + + v.at(i, i) = 1.0; + } + + if ( sum > 0.0 ) { + // ---- REDUCE MATRIX TO DIAGONAL ---------------- + int ite = 0; + double ssum; + do { + ssum = 0.0; + for ( int j = 2; j <= neq; ++j ) { + int ih = j - 1; + for ( int i = 1; i <= ih; ++i ) { + if ( ( fabs(copy(i - 1, j - 1) ) / sum ) > tol ) { + ssum += fabs(copy(i - 1, j - 1) ); + // ---- CALCULATE ROTATION ANGLE ----------------- + double aa = atan2(copy(i - 1, j - 1) * 2.0, eval.at(i) - eval.at(j) ) / 2.0; + double si = sin(aa); + double co = cos(aa); + // ---- MODIFY "I" AND "J" COLUMNS OF "A" AND "V" + for ( int k = 1; k < i; ++k ) { + double tt = copy(k - 1, i - 1); + copy(k - 1, i - 1) = co * tt + si * copy(k - 1, j - 1); + copy(k - 1, j - 1) = -si * tt + co * copy(k - 1, j - 1); + tt = v.at(k, i); + v.at(k, i) = co * tt + si * v.at(k, j); + v.at(k, j) = -si * tt + co * v.at(k, j); + } + + // diagonal term (i,i) + double tt = eval.at(i); + eval.at(i) = co * tt + si * copy(i - 1, j - 1); + double aij = -si * tt + co * copy(i - 1, j - 1); + tt = v.at(i, i); + v.at(i, i) = co * tt + si * v.at(i, j); + v.at(i, j) = -si * tt + co * v.at(i, j); + + for ( int k = i + 1; k < j; ++k ) { + double tt = copy(i - 1, k - 1); + copy(i - 1, k - 1) = co * tt + si * copy(k - 1, j - 1); + copy(k - 1, j - 1) = -si * tt + co * copy(k - 1, j - 1); + tt = v.at(k, i); + v.at(k, i) = co * tt + si * v.at(k, j); + v.at(k, j) = -si * tt + co * v.at(k, j); + } + + // diagonal term (j,j) + tt = copy(i - 1, j - 1); + double aji = co * tt + si * eval.at(j); + eval.at(j) = -si * tt + co * eval.at(j); + + tt = v.at(j, i); + v.at(j, i) = co * tt + si * v.at(j, j); + v.at(j, j) = -si * tt + co * v.at(j, j); + // + for ( int k = j + 1; k <= neq; ++k ) { + double tt = copy(i - 1, k - 1); + copy(i - 1, k - 1) = co * tt + si * copy(j - 1, k - 1); + copy(j - 1, k - 1) = -si * tt + co * copy(j - 1, k - 1); + tt = v.at(k, i); + v.at(k, i) = co * tt + si * v.at(k, j); + v.at(k, j) = -si * tt + co * v.at(k, j); + } + + // ---- MODIFY DIAGONAL TERMS -------------------- + eval.at(i) = co * eval.at(i) + si * aji; + eval.at(j) = -si * aij + co * eval.at(j); + copy(i - 1, j - 1) = 0.0; + } else { + // ---- A(I,J) MADE ZERO BY ROTATION ------------- + ; + } + } + } + + // ---- CHECK FOR CONVERGENCE -------------------- + if ( ++ite > 50 ) { + OOFEM_ERROR("too many iterations"); + } + } while ( fabs(ssum) / sum > tol ); + } + + return { eval, v }; + } + + + /** + * Calculated derivative of C^m wrt C + * @param m - power + * @param nf - number of significant figures + * @return Second-order tensor dC^m_dC + */ + Tensor4_3d compute_dCm_dC(double m, int nf = 1e-10) + { + auto [ eVals, eVecs ] = this->eigs(nf); + return compute_dCm_dC_fromEigs(m, eVals, eVecs); + } + + + /** + * Calculated derivative of C^m wrt C from given eigenvalues, eigenvectors and power m + * @param m - power + * @param nf - number of significant figures + * @return Second-order tensor dC^m_dC + */ + static Tensor4_3d compute_dCm_dC_fromEigs(double m, const FloatArray &lam, const FloatMatrix &N) + { + FloatArray d(3), c(3); + + c.at(1) = pow(lam.at(1), m); + c.at(2) = pow(lam.at(2), m); + c.at(3) = pow(lam.at(3), m); + + d.at(1) = m * pow(lam.at(1), m - 1.); + d.at(2) = m * pow(lam.at(2), m - 1.); + d.at(3) = m * pow(lam.at(3), m - 1.); + + FloatMatrix theta(3, 3); + + + // compute auxiliary variables + // the computation differes depends on if the eigenvalues of C are equal or not + if ( lam.at(1) != lam.at(2) ) { + if ( lam.at(2) != lam.at(3) ) { + if ( lam.at(1) != lam.at(3) ) { + // all eigenvalues are different + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + if ( i == j ) { + continue; + } else { + theta.at(i, j) = ( c.at(i) - c.at(j) ) / ( lam.at(i) - lam.at(j) ); + } + } + } + } else { //l1 == l3 && l1 != l2 + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + if ( i == j ) { + continue; + } else { + if ( ( i == 1 && j == 3 ) || ( i == 3 && j == 1 ) ) { + theta.at(i, j) = 1. / 2. * d.at(i); + } else { + theta.at(i, j) = ( c.at(i) - c.at(j) ) / ( lam.at(i) - lam.at(j) ); + } + } + } + } + } + } else { //l2 == l3 && l1 != l2 + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + if ( i == j ) { + continue; + } else { + if ( ( i == 2 && j == 3 ) || ( i == 3 && j == 2 ) ) { + theta.at(i, j) = 1. / 2. * d.at(i); + } else { + theta.at(i, j) = ( c.at(i) - c.at(j) ) / ( lam.at(i) - lam.at(j) ); + } + } + } + } + } + } else if ( lam.at(1) != lam.at(3) ) { // l1 == l2 && l1 != l3 + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + if ( i == j ) { + continue; + } else { + if ( ( i == 1 && j == 2 ) || ( i == 2 && j == 1 ) ) { + theta.at(i, j) = 1. / 2. * d.at(i); + } else { + theta.at(i, j) = ( c.at(i) - c.at(j) ) / ( lam.at(i) - lam.at(j) ); + } + } + } + } + } else { // l1 == l2 == l3 + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + theta.at(i, j) = 1. / 2. * d.at(i); + } + } + } + + + FloatMatrix M(9, 9); + std::vector< std::vector< int > >vIindex = {{ 1, 6, 5 }, { 9, 2, 4 }, { 8, 7, 3 } }; + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + for ( int k = 1; k <= 3; k++ ) { + for ( int l = 1; l <= 3; l++ ) { + M.at(vIindex [ i - 1 ] [ j - 1 ], vIindex [ k - 1 ] [ l - 1 ]) = N.at(k, i) * N.at(l, j) + N.at(k, j) * N.at(l, i); + } + } + } + } + + Tensor4_3d dCm_dC; + for ( int k = 1; k <= 3; k++ ) { + for ( int l = 1; l <= 3; l++ ) { + for ( int m = 1; m <= 3; m++ ) { + for ( int n = 1; n <= 3; n++ ) { + for ( int i = 1; i <= 3; i++ ) { + dCm_dC(k - 1, l - 1, m - 1, n - 1) += 0.5 * d.at(i) * N.at(k, i) * N.at(l, i) * M.at(vIindex [ i - 1 ] [ i - 1 ], vIindex [ m - 1 ] [ n - 1 ]); + for ( int j = 1; j <= 3; j++ ) { + if ( j != i ) { + dCm_dC(k - 1, l - 1, m - 1, n - 1) += 0.5 * theta.at(i, j) * N.at(k, i) * N.at(l, j) * M.at(vIindex [ i - 1 ] [ j - 1 ], vIindex [ m - 1 ] [ n - 1 ]); + } + } + } + } + } + } + } + return dCm_dC; + } + + + + + + /** + * Creates second-order unit tensor + * @return Second-order unit tensor + */ + static const Tensor2_3d UnitTensor() + { + return { 1.0, 0., 0., 0., 1.0, 0., 0., 0., 1.0 }; + } + + + /** + * Computes cofactor + * @return Second-order cofactor tensor + */ + inline Tensor2_3d compute_cofactor() const + { + Tensor2_3d cofF; + cofF(i_3, j_3) = 0.5 * this->compute_tensor_cross_product(* this)(i_3, j_3); + return cofF; + } + + /** + * Computes determinant + * @return determinant + */ + inline double compute_determinant() const + { + return ( 1. / 6. * this->compute_tensor_cross_product(* this)(m_3, n_3) * this->operator()(m_3, n_3) ); + } + + /** + * Computes determinant and cofactor + * @return determinant and cofactor + */ + inline std::pair< double, Tensor2_3d >compute_determinant_and_cofactor() const + { + Tensor2_3d cofF; + cofF(i_3, j_3) = 0.5 * this->compute_tensor_cross_product(* this)(i_3, j_3); + auto detF = 1. / 3. * cofF(i_3, j_3) * this->operator()(i_3, j_3); + return { detF, cofF }; + } + + /** + * Computes inverse + * @return inverse second-order tensor + */ + inline Tensor2_3d compute_inverse() const + { + Tensor2_3d iF; + auto [ J, cofF ] = this->compute_determinant_and_cofactor(); + iF(i_3, j_3) = 1. / J * cofF(j_3, i_3); + return iF; + } + + /** + * Computes second-order tensor cross product + * @param tensor to calculate tensor cross product with + * @return tensor cross product, eps_{ikm}eps_{jln}this_{kl}B_{mn} + */ + inline Tensor2_3d compute_tensor_cross_product(const Tensor2_3d &B) const + { + Tensor2_3d C(this->operator()(1, 1) * B(2, 2) - this->operator()(1, 2) * B(2, 1) - this->operator()(2, 1) * B(1, 2) + this->operator()(2, 2) * B(1, 1), this->operator()(1, 2) * B(2, 0) - this->operator()(1, 0) * B(2, 2) + this->operator()(2, 0) * B(1, 2) - this->operator()(2, 2) * B(1, 0), this->operator()(1, 0) * B(2, 1) - this->operator()(1, 1) * B(2, 0) - this->operator()(2, 0) * B(1, 1) + this->operator()(2, 1) * B(1, 0), this->operator()(0, 2) * B(2, 1) - this->operator()(0, 1) * B(2, 2) + this->operator()(2, 1) * B(0, 2) - this->operator()(2, 2) * B(0, 1), this->operator()(0, 0) * B(2, 2) - this->operator()(0, 2) * B(2, 0) - this->operator()(2, 0) * B(0, 2) + this->operator()(2, 2) * B(0, 0), this->operator()(0, 1) * B(2, 0) - this->operator()(0, 0) * B(2, 1) + this->operator()(2, 0) * B(0, 1) - this->operator()(2, 1) * B(0, 0), this->operator()(0, 1) * B(1, 2) - this->operator()(0, 2) * B(1, 1) - this->operator()(1, 1) * B(0, 2) + this->operator()(1, 2) * B(0, 1), this->operator()(0, 2) * B(1, 0) - this->operator()(0, 0) * B(1, 2) + this->operator()(1, 0) * B(0, 2) - this->operator()(1, 2) * B(0, 0), this->operator()(0, 0) * B(1, 1) - this->operator()(0, 1) * B(1, 0) - this->operator()(1, 0) * B(0, 1) + this->operator()(1, 1) * B(0, 0) ); + return C; + } + + + /** + * Computes fourth-order tensor cross product + * @return tensor cross product, eps_{ikm}eps_{jln}this_{mn} + */ + inline Tensor4_3d compute_tensor_cross_product() const + { + Tensor4_3d Ax(0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.); + Ax(1, 1, 0, 0) = this->operator()(2, 2); + Ax(1, 2, 0, 0) = -this->operator()(2, 1); + Ax(2, 1, 0, 0) = -this->operator()(1, 2); + Ax(2, 2, 0, 0) = this->operator()(1, 1); + + Ax(0, 1, 1, 0) = -this->operator()(2, 2); + Ax(0, 2, 1, 0) = this->operator()(2, 1); + Ax(2, 1, 1, 0) = this->operator()(0, 2); + Ax(2, 2, 1, 0) = -this->operator()(0, 1); + + Ax(0, 1, 2, 0) = this->operator()(1, 2); + Ax(0, 2, 2, 0) = -this->operator()(1, 1); + Ax(1, 1, 2, 0) = -this->operator()(0, 2); + Ax(1, 2, 2, 0) = this->operator()(0, 1); + + Ax(1, 0, 0, 1) = -this->operator()(2, 2); + Ax(1, 2, 0, 1) = this->operator()(2, 0); + Ax(2, 0, 0, 1) = this->operator()(1, 2); + Ax(2, 2, 0, 1) = -this->operator()(1, 0); + + Ax(0, 0, 1, 1) = this->operator()(2, 2); + Ax(0, 2, 1, 1) = -this->operator()(2, 0); + Ax(2, 0, 1, 1) = -this->operator()(0, 2); + Ax(2, 2, 1, 1) = this->operator()(0, 0); + + Ax(0, 0, 2, 1) = -this->operator()(1, 2); + Ax(0, 2, 2, 1) = this->operator()(1, 0); + Ax(1, 0, 2, 1) = this->operator()(0, 2); + Ax(1, 2, 2, 1) = -this->operator()(0, 0); + + Ax(1, 0, 0, 2) = this->operator()(2, 1); + Ax(1, 1, 0, 2) = -this->operator()(2, 0); + Ax(2, 0, 0, 2) = -this->operator()(1, 1); + Ax(2, 1, 0, 2) = this->operator()(1, 0); + + Ax(0, 0, 1, 2) = -this->operator()(2, 1); + Ax(0, 1, 1, 2) = this->operator()(2, 0); + Ax(2, 0, 1, 2) = this->operator()(0, 1); + Ax(2, 1, 1, 2) = -this->operator()(0, 0); + + Ax(0, 0, 2, 2) = this->operator()(1, 1); + Ax(0, 1, 2, 2) = -this->operator()(1, 0); + Ax(1, 0, 2, 2) = -this->operator()(0, 1); + Ax(1, 1, 2, 2) = this->operator()(0, 0); + + return Ax; + } +}; + +// not used for now... +class Tensor2sym_3d : public Tensor2_symmetric< double, 3 > +{ +public: + using Tensor2_symmetric< double, 3 >::Tensor2_symmetric; + /* Tensor2sym_3d(const oofem::FloatArrayF<6> &array){ + * this->data[0] = array.at(1); + * this->data[1] = array.at(6); + * this->data[2] = array.at(5); + * this->data[3] = array.at(6); + * this->data[4] = array.at(2); + * this->data[5] = array.at(4); + * this->data[6] = array.at(5); + * this->data[7] = array.at(4); + * this->data[8] = array.at(3); + * } + */ + + + const inline FloatArrayF< 6 >to_voigt_form() + { + return { + this->operator()(0, 0), + this->operator()(1, 1), + this->operator()(2, 2), + this->operator()(1, 2), + this->operator()(0, 2), + this->operator()(0, 1) + }; + } +}; +} // end namespace oofem diff --git a/src/oofemlib/tensor/tensor4.h b/src/oofemlib/tensor/tensor4.h new file mode 100644 index 000000000..009fd2e38 --- /dev/null +++ b/src/oofemlib/tensor/tensor4.h @@ -0,0 +1,285 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "floatmatrix.h" +#include "floatarray.h" +#include "mathfem.h" +#include "index.h" +#pragma once + +using namespace FTensor; + + +/** + * Functions providing basic operations with tensors + * based on FTensor library + * It provides transformation from the second and fourth order tensors in 3d to FloatArrayF<9> and FloatArray<9,9> + * It provides calculation of determinant, cofactor, inverse, and tensor cross product + * More to be added gradually + * @author Martin Horak + **/ + +namespace oofem { +class Tensor4_3d : public Tensor4< double, 3, 3, 3, 3 > +{ +public: + using Tensor4< double, 3, 3, 3, 3 >::Tensor4; + + /** + * Creates fourth-order tensor in 3d + * Initialized with zeros + */ + Tensor4_3d() { + // the first column + this->data [ 0 ] [ 0 ] [ 0 ] [ 0 ] = 0; + this->data [ 0 ] [ 1 ] [ 0 ] [ 0 ] = 0.; + this->data [ 0 ] [ 2 ] [ 0 ] [ 0 ] = 0.; + this->data [ 1 ] [ 0 ] [ 0 ] [ 0 ] = 0.; + this->data [ 1 ] [ 1 ] [ 0 ] [ 0 ] = 0.; + this->data [ 1 ] [ 2 ] [ 0 ] [ 0 ] = 0.; + this->data [ 2 ] [ 0 ] [ 0 ] [ 0 ] = 0.; + this->data [ 2 ] [ 1 ] [ 0 ] [ 0 ] = 0.; + this->data [ 2 ] [ 2 ] [ 0 ] [ 0 ] = 0.; + // the second column + this->data [ 0 ] [ 0 ] [ 1 ] [ 1 ] = 0.; + this->data [ 0 ] [ 1 ] [ 1 ] [ 1 ] = 0.; + this->data [ 0 ] [ 2 ] [ 1 ] [ 1 ] = 0.; + this->data [ 1 ] [ 0 ] [ 1 ] [ 1 ] = 0.; + this->data [ 1 ] [ 1 ] [ 1 ] [ 1 ] = 0.; + this->data [ 1 ] [ 2 ] [ 1 ] [ 1 ] = 0.; + this->data [ 2 ] [ 0 ] [ 1 ] [ 1 ] = 0.; + this->data [ 2 ] [ 1 ] [ 1 ] [ 1 ] = 0.; + this->data [ 2 ] [ 2 ] [ 1 ] [ 1 ] = 0.; + // the third column + this->data [ 0 ] [ 0 ] [ 2 ] [ 2 ] = 0.; + this->data [ 0 ] [ 1 ] [ 2 ] [ 2 ] = 0.; + this->data [ 0 ] [ 2 ] [ 2 ] [ 2 ] = 0.; + this->data [ 1 ] [ 0 ] [ 2 ] [ 2 ] = 0.; + this->data [ 1 ] [ 1 ] [ 2 ] [ 2 ] = 0.; + this->data [ 1 ] [ 2 ] [ 2 ] [ 2 ] = 0.; + this->data [ 2 ] [ 0 ] [ 2 ] [ 2 ] = 0.; + this->data [ 2 ] [ 1 ] [ 2 ] [ 2 ] = 0.; + this->data [ 2 ] [ 2 ] [ 2 ] [ 2 ] = 0.; + // the fourth column + this->data [ 0 ] [ 0 ] [ 1 ] [ 2 ] = 0.; + this->data [ 0 ] [ 1 ] [ 1 ] [ 2 ] = 0.; + this->data [ 0 ] [ 2 ] [ 1 ] [ 2 ] = 0.; + this->data [ 1 ] [ 0 ] [ 1 ] [ 2 ] = 0.; + this->data [ 1 ] [ 1 ] [ 1 ] [ 2 ] = 0.; + this->data [ 1 ] [ 2 ] [ 1 ] [ 2 ] = 0.; + this->data [ 2 ] [ 0 ] [ 1 ] [ 2 ] = 0.; + this->data [ 2 ] [ 1 ] [ 1 ] [ 2 ] = 0.; + this->data [ 2 ] [ 2 ] [ 1 ] [ 2 ] = 0.; + //the fifth column + this->data [ 0 ] [ 0 ] [ 0 ] [ 2 ] = 0.; + this->data [ 0 ] [ 1 ] [ 0 ] [ 2 ] = 0.; + this->data [ 0 ] [ 2 ] [ 0 ] [ 2 ] = 0.; + this->data [ 1 ] [ 0 ] [ 0 ] [ 2 ] = 0.; + this->data [ 1 ] [ 1 ] [ 0 ] [ 2 ] = 0.; + this->data [ 1 ] [ 2 ] [ 0 ] [ 2 ] = 0.; + this->data [ 2 ] [ 0 ] [ 0 ] [ 2 ] = 0.; + this->data [ 2 ] [ 1 ] [ 0 ] [ 2 ] = 0.; + this->data [ 2 ] [ 2 ] [ 0 ] [ 2 ] = 0.; + //the sixth column + this->data [ 0 ] [ 0 ] [ 0 ] [ 1 ] = 0.; + this->data [ 0 ] [ 1 ] [ 0 ] [ 1 ] = 0.; + this->data [ 0 ] [ 2 ] [ 0 ] [ 1 ] = 0.; + this->data [ 1 ] [ 0 ] [ 0 ] [ 1 ] = 0.; + this->data [ 1 ] [ 1 ] [ 0 ] [ 1 ] = 0.; + this->data [ 1 ] [ 2 ] [ 0 ] [ 1 ] = 0.; + this->data [ 2 ] [ 0 ] [ 0 ] [ 1 ] = 0.; + this->data [ 2 ] [ 1 ] [ 0 ] [ 1 ] = 0.; + this->data [ 2 ] [ 2 ] [ 0 ] [ 1 ] = 0.; + //the seventh column + this->data [ 0 ] [ 0 ] [ 2 ] [ 1 ] = 0.; + this->data [ 0 ] [ 1 ] [ 2 ] [ 1 ] = 0.; + this->data [ 0 ] [ 2 ] [ 2 ] [ 1 ] = 0.; + this->data [ 1 ] [ 0 ] [ 2 ] [ 1 ] = 0.; + this->data [ 1 ] [ 1 ] [ 2 ] [ 1 ] = 0.; + this->data [ 1 ] [ 2 ] [ 2 ] [ 1 ] = 0.; + this->data [ 2 ] [ 0 ] [ 2 ] [ 1 ] = 0.; + this->data [ 2 ] [ 1 ] [ 2 ] [ 1 ] = 0.; + this->data [ 2 ] [ 2 ] [ 2 ] [ 1 ] = 0.; + //the eight column + this->data [ 0 ] [ 0 ] [ 2 ] [ 0 ] = 0.; + this->data [ 0 ] [ 1 ] [ 2 ] [ 0 ] = 0.; + this->data [ 0 ] [ 2 ] [ 2 ] [ 0 ] = 0.; + this->data [ 1 ] [ 0 ] [ 2 ] [ 0 ] = 0.; + this->data [ 1 ] [ 1 ] [ 2 ] [ 0 ] = 0.; + this->data [ 1 ] [ 2 ] [ 2 ] [ 0 ] = 0.; + this->data [ 2 ] [ 0 ] [ 2 ] [ 0 ] = 0.; + this->data [ 2 ] [ 1 ] [ 2 ] [ 0 ] = 0.; + this->data [ 2 ] [ 2 ] [ 2 ] [ 0 ] = 0.; + //the nineght column + this->data [ 0 ] [ 0 ] [ 1 ] [ 0 ] = 0.; + this->data [ 0 ] [ 1 ] [ 1 ] [ 0 ] = 0.; + this->data [ 0 ] [ 2 ] [ 1 ] [ 0 ] = 0.; + this->data [ 1 ] [ 0 ] [ 1 ] [ 0 ] = 0.; + this->data [ 1 ] [ 1 ] [ 1 ] [ 0 ] = 0.; + this->data [ 1 ] [ 2 ] [ 1 ] [ 0 ] = 0.; + this->data [ 2 ] [ 0 ] [ 1 ] [ 0 ] = 0.; + this->data [ 2 ] [ 1 ] [ 1 ] [ 0 ] = 0.; + this->data [ 2 ] [ 2 ] [ 1 ] [ 0 ] = 0.; + } + + /** + * Creates fourth-order tensor in 3d from floatmatrixf<9,9> + */ + Tensor4_3d(const oofem::FloatMatrixF< 9, 9 > &mat) { + // the first column + this->data [ 0 ] [ 0 ] [ 0 ] [ 0 ] = mat.at(1, 1); + this->data [ 0 ] [ 1 ] [ 0 ] [ 0 ] = mat.at(6, 1); + this->data [ 0 ] [ 2 ] [ 0 ] [ 0 ] = mat.at(5, 1); + this->data [ 1 ] [ 0 ] [ 0 ] [ 0 ] = mat.at(9, 1); + this->data [ 1 ] [ 1 ] [ 0 ] [ 0 ] = mat.at(2, 1); + this->data [ 1 ] [ 2 ] [ 0 ] [ 0 ] = mat.at(4, 1); + this->data [ 2 ] [ 0 ] [ 0 ] [ 0 ] = mat.at(8, 1); + this->data [ 2 ] [ 1 ] [ 0 ] [ 0 ] = mat.at(7, 1); + this->data [ 2 ] [ 2 ] [ 0 ] [ 0 ] = mat.at(3, 1); + // the second column + this->data [ 0 ] [ 0 ] [ 1 ] [ 1 ] = mat.at(1, 2); + this->data [ 0 ] [ 1 ] [ 1 ] [ 1 ] = mat.at(6, 2); + this->data [ 0 ] [ 2 ] [ 1 ] [ 1 ] = mat.at(5, 2); + this->data [ 1 ] [ 0 ] [ 1 ] [ 1 ] = mat.at(9, 2); + this->data [ 1 ] [ 1 ] [ 1 ] [ 1 ] = mat.at(2, 2); + this->data [ 1 ] [ 2 ] [ 1 ] [ 1 ] = mat.at(4, 2); + this->data [ 2 ] [ 0 ] [ 1 ] [ 1 ] = mat.at(8, 2); + this->data [ 2 ] [ 1 ] [ 1 ] [ 1 ] = mat.at(7, 2); + this->data [ 2 ] [ 2 ] [ 1 ] [ 1 ] = mat.at(3, 2); + // the third column + this->data [ 0 ] [ 0 ] [ 2 ] [ 2 ] = mat.at(1, 3); + this->data [ 0 ] [ 1 ] [ 2 ] [ 2 ] = mat.at(6, 3); + this->data [ 0 ] [ 2 ] [ 2 ] [ 2 ] = mat.at(5, 3); + this->data [ 1 ] [ 0 ] [ 2 ] [ 2 ] = mat.at(9, 3); + this->data [ 1 ] [ 1 ] [ 2 ] [ 2 ] = mat.at(2, 3); + this->data [ 1 ] [ 2 ] [ 2 ] [ 2 ] = mat.at(4, 3); + this->data [ 2 ] [ 0 ] [ 2 ] [ 2 ] = mat.at(8, 3); + this->data [ 2 ] [ 1 ] [ 2 ] [ 2 ] = mat.at(7, 3); + this->data [ 2 ] [ 2 ] [ 2 ] [ 2 ] = mat.at(3, 3); + // the fourth column + this->data [ 0 ] [ 0 ] [ 1 ] [ 2 ] = mat.at(1, 4); + this->data [ 0 ] [ 1 ] [ 1 ] [ 2 ] = mat.at(6, 4); + this->data [ 0 ] [ 2 ] [ 1 ] [ 2 ] = mat.at(5, 4); + this->data [ 1 ] [ 0 ] [ 1 ] [ 2 ] = mat.at(9, 4); + this->data [ 1 ] [ 1 ] [ 1 ] [ 2 ] = mat.at(2, 4); + this->data [ 1 ] [ 2 ] [ 1 ] [ 2 ] = mat.at(4, 4); + this->data [ 2 ] [ 0 ] [ 1 ] [ 2 ] = mat.at(8, 4); + this->data [ 2 ] [ 1 ] [ 1 ] [ 2 ] = mat.at(7, 4); + this->data [ 2 ] [ 2 ] [ 1 ] [ 2 ] = mat.at(3, 4); + //the fifth column + this->data [ 0 ] [ 0 ] [ 0 ] [ 2 ] = mat.at(1, 5); + this->data [ 0 ] [ 1 ] [ 0 ] [ 2 ] = mat.at(6, 5); + this->data [ 0 ] [ 2 ] [ 0 ] [ 2 ] = mat.at(5, 5); + this->data [ 1 ] [ 0 ] [ 0 ] [ 2 ] = mat.at(9, 5); + this->data [ 1 ] [ 1 ] [ 0 ] [ 2 ] = mat.at(2, 5); + this->data [ 1 ] [ 2 ] [ 0 ] [ 2 ] = mat.at(4, 5); + this->data [ 2 ] [ 0 ] [ 0 ] [ 2 ] = mat.at(8, 5); + this->data [ 2 ] [ 1 ] [ 0 ] [ 2 ] = mat.at(7, 5); + this->data [ 2 ] [ 2 ] [ 0 ] [ 2 ] = mat.at(3, 5); + //the sixth column + this->data [ 0 ] [ 0 ] [ 0 ] [ 1 ] = mat.at(1, 6); + this->data [ 0 ] [ 1 ] [ 0 ] [ 1 ] = mat.at(6, 6); + this->data [ 0 ] [ 2 ] [ 0 ] [ 1 ] = mat.at(5, 6); + this->data [ 1 ] [ 0 ] [ 0 ] [ 1 ] = mat.at(9, 6); + this->data [ 1 ] [ 1 ] [ 0 ] [ 1 ] = mat.at(2, 6); + this->data [ 1 ] [ 2 ] [ 0 ] [ 1 ] = mat.at(4, 6); + this->data [ 2 ] [ 0 ] [ 0 ] [ 1 ] = mat.at(8, 6); + this->data [ 2 ] [ 1 ] [ 0 ] [ 1 ] = mat.at(7, 6); + this->data [ 2 ] [ 2 ] [ 0 ] [ 1 ] = mat.at(3, 6); + //the seventh column + this->data [ 0 ] [ 0 ] [ 2 ] [ 1 ] = mat.at(1, 7); + this->data [ 0 ] [ 1 ] [ 2 ] [ 1 ] = mat.at(6, 7); + this->data [ 0 ] [ 2 ] [ 2 ] [ 1 ] = mat.at(5, 7); + this->data [ 1 ] [ 0 ] [ 2 ] [ 1 ] = mat.at(9, 7); + this->data [ 1 ] [ 1 ] [ 2 ] [ 1 ] = mat.at(2, 7); + this->data [ 1 ] [ 2 ] [ 2 ] [ 1 ] = mat.at(4, 7); + this->data [ 2 ] [ 0 ] [ 2 ] [ 1 ] = mat.at(8, 7); + this->data [ 2 ] [ 1 ] [ 2 ] [ 1 ] = mat.at(7, 7); + this->data [ 2 ] [ 2 ] [ 2 ] [ 1 ] = mat.at(3, 7); + //the eight column + this->data [ 0 ] [ 0 ] [ 2 ] [ 0 ] = mat.at(1, 8); + this->data [ 0 ] [ 1 ] [ 2 ] [ 0 ] = mat.at(6, 8); + this->data [ 0 ] [ 2 ] [ 2 ] [ 0 ] = mat.at(5, 8); + this->data [ 1 ] [ 0 ] [ 2 ] [ 0 ] = mat.at(9, 8); + this->data [ 1 ] [ 1 ] [ 2 ] [ 0 ] = mat.at(2, 8); + this->data [ 1 ] [ 2 ] [ 2 ] [ 0 ] = mat.at(4, 8); + this->data [ 2 ] [ 0 ] [ 2 ] [ 0 ] = mat.at(8, 8); + this->data [ 2 ] [ 1 ] [ 2 ] [ 0 ] = mat.at(7, 8); + this->data [ 2 ] [ 2 ] [ 2 ] [ 0 ] = mat.at(3, 8); + //the nineght column + this->data [ 0 ] [ 0 ] [ 1 ] [ 0 ] = mat.at(1, 9); + this->data [ 0 ] [ 1 ] [ 1 ] [ 0 ] = mat.at(6, 9); + this->data [ 0 ] [ 2 ] [ 1 ] [ 0 ] = mat.at(5, 9); + this->data [ 1 ] [ 0 ] [ 1 ] [ 0 ] = mat.at(9, 9); + this->data [ 1 ] [ 1 ] [ 1 ] [ 0 ] = mat.at(2, 9); + this->data [ 1 ] [ 2 ] [ 1 ] [ 0 ] = mat.at(4, 9); + this->data [ 2 ] [ 0 ] [ 1 ] [ 0 ] = mat.at(8, 9); + this->data [ 2 ] [ 1 ] [ 1 ] [ 0 ] = mat.at(7, 9); + this->data [ 2 ] [ 2 ] [ 1 ] [ 0 ] = mat.at(3, 9); + } + + /** + * Transforms a fourth-order tensor into a floatmatrixf<9,9>, using the Voigt notation + */ + + inline FloatMatrixF< 9, 9 >to_voigt_form() + { + return { this->operator()(0, 0, 0, 0), this->operator()(1, 1, 0, 0), this->operator()(2, 2, 0, 0), this->operator()(1, 2, 0, 0), this->operator()(0, 2, 0, 0), this->operator()(0, 1, 0, 0), this->operator()(2, 1, 0, 0), this->operator()(2, 0, 0, 0), this->operator()(1, 0, 0, 0), this->operator()(0, 0, 1, 1), this->operator()(1, 1, 1, 1), this->operator()(2, 2, 1, 1), this->operator()(1, 2, 1, 1), this->operator()(0, 2, 1, 1), this->operator()(0, 1, 1, 1), this->operator()(2, 1, 1, 1), this->operator()(2, 0, 1, 1), this->operator()(1, 0, 1, 1), this->operator()(0, 0, 2, 2), this->operator()(1, 1, 2, 2), this->operator()(2, 2, 2, 2), this->operator()(1, 2, 2, 2), this->operator()(0, 2, 2, 2), this->operator()(0, 1, 2, 2), this->operator()(2, 1, 2, 2), this->operator()(2, 0, 2, 2), this->operator()(1, 0, 2, 2), this->operator()(0, 0, 1, 2), this->operator()(1, 1, 1, 2), this->operator()(2, 2, 1, 2), this->operator()(1, 2, 1, 2), this->operator()(0, 2, 1, 2), this->operator()(0, 1, 1, 2), this->operator()(2, 1, 1, 2), this->operator()(2, 0, 1, 2), this->operator()(1, 0, 1, 2), this->operator()(0, 0, 0, 2), this->operator()(1, 1, 0, 2), this->operator()(2, 2, 0, 2), this->operator()(1, 2, 0, 2), this->operator()(0, 2, 0, 2), this->operator()(0, 1, 0, 2), this->operator()(2, 1, 0, 2), this->operator()(2, 0, 0, 2), this->operator()(1, 0, 0, 2), this->operator()(0, 0, 0, 1), this->operator()(1, 1, 0, 1), this->operator()(2, 2, 0, 1), this->operator()(1, 2, 0, 1), this->operator()(0, 2, 0, 1), this->operator()(0, 1, 0, 1), this->operator()(2, 1, 0, 1), this->operator()(2, 0, 0, 1), this->operator()(1, 0, 0, 1), this->operator()(0, 0, 2, 1), this->operator()(1, 1, 2, 1), this->operator()(2, 2, 2, 1), this->operator()(1, 2, 2, 1), this->operator()(0, 2, 2, 1), this->operator()(0, 1, 2, 1), this->operator()(2, 1, 2, 1), this->operator()(2, 0, 2, 1), this->operator()(1, 0, 2, 1), this->operator()(0, 0, 2, 0), this->operator()(1, 1, 2, 0), this->operator()(2, 2, 2, 0), this->operator()(1, 2, 2, 0), this->operator()(0, 2, 2, 0), this->operator()(0, 1, 2, 0), this->operator()(2, 1, 2, 0), this->operator()(2, 0, 2, 0), this->operator()(1, 0, 2, 0), this->operator()(0, 0, 1, 0), this->operator()(1, 1, 1, 0), this->operator()(2, 2, 1, 0), this->operator()(1, 2, 1, 0), this->operator()(0, 2, 1, 0), this->operator()(0, 1, 1, 0), this->operator()(2, 1, 1, 0), this->operator()(2, 0, 1, 0), this->operator()(1, 0, 1, 0) }; + } + + //@todo, make this working + /* attempt to implement noinline print, but it doesn't work, why? + * void __attribute__((noinline)) printYourself() const + * // Prints the receiver on screen. + * { + * printf("4th order tensor"); + * for ( int i = 1; i <= 3; i++ ) { + * for ( int j = 1; j <= 3; j++ ) { + * for ( int k = 1; k <= 3; k++ ) { + * for ( int l = 1; l <= 3; l++ ) { + * printf( "Component %d %d %d %d is: %10.3e \n", i,j,k,l,this->data[i][j][k][l] ); + * } + * } + * } + * } + * } + * + * void __attribute__((noinline)) printComponent(int i, int j, int k, int l) const + * // Prints the receiver on screen. + * { + * printf( "Component %d %d %d %d is: %10.3e\n ", i,j,k,l,this->data[i][j][k][l] ); + * } + */ +}; +} // end namespace oofem diff --git a/src/oofemlib/timestep.C b/src/oofemlib/timestep.C index 8eda17255..738233669 100644 --- a/src/oofemlib/timestep.C +++ b/src/oofemlib/timestep.C @@ -109,10 +109,7 @@ TimeStep :: operator = ( const TimeStep & src ) } - - TimeStep *TimeStep :: givePreviousStep() -// Not accepted in-line. { if ( isTheCurrentTimeStep() ) { return eModel->givePreviousStep(); @@ -125,18 +122,13 @@ TimeStep *TimeStep :: givePreviousStep() bool TimeStep :: isNotTheLastStep() -// Returns True if the time history contains steps after the receiver, -// else returns False. { return ( number != eModel->giveNumberOfSteps() ); } + bool TimeStep :: isTheFirstStep() { - // Returns True if the receiver is the first time step, - // according to first step number - // else returns False. - return ( number == eModel->giveNumberOfFirstStep() ); } @@ -151,98 +143,77 @@ bool TimeStep :: isIcApply() } - bool TimeStep :: isTheCurrentTimeStep() -// Not accepted in-line. { return this == eModel->giveCurrentStep(); } -contextIOResultType -TimeStep :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +TimeStep :: saveContext(DataStream &stream) { - // write step number if ( !stream.write(number) ) { THROW_CIOERR(CIO_IOERR); } - // write meta step number if ( !stream.write(mStepNumber) ) { THROW_CIOERR(CIO_IOERR); } - // write target time if ( !stream.write(this->targetTime) ) { THROW_CIOERR(CIO_IOERR); } - // write intrinsic time if ( !stream.write(this->intrinsicTime) ) { THROW_CIOERR(CIO_IOERR); } - // write deltaT if ( !stream.write(this->deltaT) ) { THROW_CIOERR(CIO_IOERR); } - // write solutionStateCounter if ( !stream.write(this->solutionStateCounter) ) { THROW_CIOERR(CIO_IOERR); } - // write timeDiscretization int tDiscretization = ( int ) timeDiscretization; if ( !stream.write(tDiscretization) ) { THROW_CIOERR(CIO_IOERR); } - - // return result back - return CIO_OK; } -contextIOResultType -TimeStep :: restoreContext(DataStream &stream, ContextMode mode, void *obj) + +void +TimeStep :: restoreContext(DataStream &stream) { - // read step number if ( !stream.read(number) ) { THROW_CIOERR(CIO_IOERR); } - // read meta step number if ( !stream.read(mStepNumber) ) { THROW_CIOERR(CIO_IOERR); } - // read target time if ( !stream.read(this->targetTime) ) { THROW_CIOERR(CIO_IOERR); } - // read intrinsic time if ( !stream.read(this->intrinsicTime) ) { THROW_CIOERR(CIO_IOERR); } - // read deltaT if ( !stream.read(this->deltaT) ) { THROW_CIOERR(CIO_IOERR); } - // read solutionStateCounter if ( !stream.read(this->solutionStateCounter) ) { THROW_CIOERR(CIO_IOERR); } - // read timeDiscretization int tDiscretization = 0; if ( !stream.read(tDiscretization) ) { THROW_CIOERR(CIO_IOERR); } timeDiscretization = ( TimeDiscretizationType ) tDiscretization; - - // return result back - return CIO_OK; } } // end namespace oofem diff --git a/src/oofemlib/timestep.h b/src/oofemlib/timestep.h index f3da34f6c..f35d6bf27 100644 --- a/src/oofemlib/timestep.h +++ b/src/oofemlib/timestep.h @@ -195,24 +195,18 @@ class OOFEM_EXPORT TimeStep /// Returns time discretization. TimeDiscretizationType giveTimeDiscretization() { return timeDiscretization; } - IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + void initializeFrom(InputRecord &ir) { } /** * Stores receiver state to output stream. - * Receiver should write class-id first in order to allow test - * whether correct data are then restored. * @param stream Output stream. - * @param mode Determines amount of info required in stream (state, definition,...). - * @param obj Special parameter, used only to send particular integration. - * point to material class version of this method. Except this - * case, obj parameter is always NULL pointer. * @exception ContextIOERR If error encountered. */ - contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream); /** * Restores the receiver state previously written in stream. * @see saveContext member function. */ - contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void restoreContext(DataStream &stream); std :: string errorInfo(const char *func) { return std :: string("TimeStep::") + func; } }; diff --git a/src/oofemlib/topologydescription.h b/src/oofemlib/topologydescription.h index 4f7eadcf9..1efaef952 100644 --- a/src/oofemlib/topologydescription.h +++ b/src/oofemlib/topologydescription.h @@ -73,7 +73,7 @@ class OOFEM_EXPORT TopologyDescription /** * Instanciates itself. */ - virtual bool instanciateYourself(DataReader *dr) = 0; + virtual bool instanciateYourself(DataReader &dr) = 0; /** * Updates the topology from the FE solution. diff --git a/src/oofemlib/trianglemesherinterface.C b/src/oofemlib/trianglemesherinterface.C index 9832411b7..5757aa86b 100644 --- a/src/oofemlib/trianglemesherinterface.C +++ b/src/oofemlib/trianglemesherinterface.C @@ -543,13 +543,13 @@ void TriangleMesherInterface :: fixNodeMarkers(const std :: vector< FloatArray > n_markers.resize( nodes.size() ); for ( std :: size_t i = 0; i < segments.size(); ++i ) { - for ( int j = 1; j <= segments [ i ].giveSize(); ++j ) { - n_markers [ segments [ i ].at(j) - 1 ].insertSortedOnce( s_markers(i) ); + for ( int segment : segments [ i ] ) { + n_markers [ segment - 1 ].insertSortedOnce( s_markers[i] ); } } for ( std :: size_t i = 0; i < triangles.size(); ++i ) { - for ( int j = 1; j <= triangles [ i ].giveSize(); ++j ) { - n_markers [ triangles [ i ].at(j) - 1 ].insertSortedOnce( t_markers(i) ); + for ( int triangle : triangles [ i ] ) { + n_markers [ triangle - 1 ].insertSortedOnce( t_markers[i] ); } } } @@ -562,8 +562,8 @@ void TriangleMesherInterface :: simplifyPSLG(Triangle_PSLG &coarse, const Triang // Calculate the inverted connection node->element std :: set< int > *connectivity = new std :: set< int > [ nodes ]; for ( int i = 0; i < segments; i++ ) { - connectivity [ pslg.segment_a(i) - 1 ].insert(i + 1); - connectivity [ pslg.segment_b(i) - 1 ].insert(i + 1); + connectivity [ pslg.segment_a[i] - 1 ].insert(i + 1); + connectivity [ pslg.segment_b[i] - 1 ].insert(i + 1); } // Some conservative error measure @@ -621,21 +621,21 @@ void TriangleMesherInterface :: simplifyPSLG(Triangle_PSLG &coarse, const Triang n1 = i; n2 = seg_a.at(e1) == i ? seg_b.at(e1) : seg_a.at(e1); - ab(0) = pslg.nx.at(n1) - pslg.nx.at(n0); - ab(1) = pslg.ny.at(n1) - pslg.ny.at(n0); - ac(0) = pslg.nx.at(n2) - pslg.nx.at(n0); - ac(1) = pslg.ny.at(n2) - pslg.ny.at(n0); + ab[0] = pslg.nx.at(n1) - pslg.nx.at(n0); + ab[1] = pslg.ny.at(n1) - pslg.ny.at(n0); + ac[0] = pslg.nx.at(n2) - pslg.nx.at(n0); + ac[1] = pslg.ny.at(n2) - pslg.ny.at(n0); abac = ab.dotProduct(ac); acac = ac.computeSquaredNorm(); // Find the error (how far the point would be moved to obtain the following line without it). if ( abac <= 0 || acac == 0 ) { // then -ab - err_vec(0) = -ab(0); - err_vec(1) = -ab(1); + err_vec[0] = -ab[0]; + err_vec[1] = -ab[1]; } else if ( abac >= acac ) { // then bc - err_vec(0) = pslg.nx.at(n2) - pslg.nx.at(n1); - err_vec(1) = pslg.ny.at(n2) - pslg.ny.at(n1); + err_vec[0] = pslg.nx.at(n2) - pslg.nx.at(n1); + err_vec[1] = pslg.ny.at(n2) - pslg.ny.at(n1); } else { err_vec = ac; err_vec.times(abac / acac); @@ -648,8 +648,8 @@ void TriangleMesherInterface :: simplifyPSLG(Triangle_PSLG &coarse, const Triang if ( ev_norm == 0 ) { real_error = 0.0; } else { - error_x.at(n1) += err_vec(0); - error_y.at(n1) += err_vec(1); + error_x.at(n1) += err_vec[0]; + error_y.at(n1) += err_vec[1]; real_error = sqrt( error_x.at(n1) * error_x.at(n1) + error_y.at(n1) * error_y.at(n1) ); } @@ -692,10 +692,10 @@ void TriangleMesherInterface :: simplifyPSLG(Triangle_PSLG &coarse, const Triang n1 = i; n2 = seg_a.at(e1) == i ? seg_b.at(e1) : seg_a.at(e1); - ab(0) = pslg.nx.at(n1) - pslg.nx.at(n0); - ab(1) = pslg.ny.at(n1) - pslg.ny.at(n0); - bc(0) = pslg.nx.at(n2) - pslg.nx.at(n1); - bc(1) = pslg.ny.at(n2) - pslg.ny.at(n1); + ab[0] = pslg.nx.at(n1) - pslg.nx.at(n0); + ab[1] = pslg.ny.at(n1) - pslg.ny.at(n0); + bc[0] = pslg.nx.at(n2) - pslg.nx.at(n1); + bc[1] = pslg.ny.at(n2) - pslg.ny.at(n1); if ( ab.computeSquaredNorm() < minlen * minlen || bc.computeSquaredNorm() < minlen * minlen ) { // Mark node for removal, remove second edge, more first edge connection to next node; diff --git a/src/oofemlib/uniformgridfield.C b/src/oofemlib/uniformgridfield.C index 2ae7309b2..64057a0e1 100644 --- a/src/oofemlib/uniformgridfield.C +++ b/src/oofemlib/uniformgridfield.C @@ -156,12 +156,7 @@ int UniformGridField::evaluateAt(FloatArray &answer, const FloatArray &coords, int UniformGridField :: evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) { - if ( dman->hasCoordinates()) { - int result=evaluateAt(answer,*(dman->giveCoordinates()),mode,tStep); - return ( result == 1 ); - } - // failed -> dman without coordinates - return 1; + return evaluateAt(answer, dman->giveCoordinates(), mode, tStep) == 1; } diff --git a/src/oofemlib/uniformgridfield.h b/src/oofemlib/uniformgridfield.h index c82496027..9da1f9e48 100644 --- a/src/oofemlib/uniformgridfield.h +++ b/src/oofemlib/uniformgridfield.h @@ -35,9 +35,9 @@ #ifndef uniformgridfield_h #define uniformgridfield_h -#include"field.h" -#include"floatarray.h" -#include"intarray.h" +#include "field.h" +#include "floatarray.h" +#include "intarray.h" namespace oofem { /** @@ -74,36 +74,14 @@ class OOFEM_EXPORT UniformGridField: public Field /** Accessor for setting nodal values; checks size of the array for correctness. */ void setValues(const FloatArray& vv); - /** - Implementation of Field::evaluateAt for coordinates. - */ int evaluateAt(FloatArray &answer, const FloatArray &coords, ValueModeType mode, TimeStep *tStep) override; - /** - Implementaton of Field::evaluateAt for DofManager. - */ int evaluateAt(FloatArray &answer, DofManager *dman, ValueModeType mode, TimeStep *tStep) override; - /** - * Stores receiver state to output stream. - * Writes the FEMComponent class-id in order to allow test whether correct data are then restored. - * @param stream Output stream. - * @param mode Determines amount of info in stream (state, definition,...). - * @return contextIOResultType. - * @exception Throws an ContextIOERR exception if error encountered. - */ - contextIOResultType saveContext(DataStream &stream, ContextMode mode) override { return CIO_OK; } - /** - * Restores the receiver state previously written in stream. - * Reads the FEMComponent class-id in order to allow test consistency. - * @param stream Input stream. - * @param mode Determines amount of info in stream (state, definition,...). - * @return contextIOResultType. - * @exception Throws an ContextIOERR exception if error encountered. - */ - contextIOResultType restoreContext(DataStream &stream, ContextMode mode) override { return CIO_OK; } + void saveContext(DataStream &stream) override { } + void restoreContext(DataStream &stream) override { } /// @return Class name of the receiver. const char *giveClassName() const override { return "UniformGridField"; } diff --git a/src/oofemlib/unknownnumberingscheme.h b/src/oofemlib/unknownnumberingscheme.h index 577206eae..3a4ee93e7 100644 --- a/src/oofemlib/unknownnumberingscheme.h +++ b/src/oofemlib/unknownnumberingscheme.h @@ -82,8 +82,8 @@ class OOFEM_EXPORT EModelDefaultEquationNumbering : public UnknownNumberingSchem public: EModelDefaultEquationNumbering(void) : UnknownNumberingScheme() { } - virtual bool isDefault() const { return true; } - virtual int giveDofEquationNumber(Dof *dof) const { + bool isDefault() const override { return true; } + int giveDofEquationNumber(Dof *dof) const override { return dof->__giveEquationNumber(); } }; @@ -99,7 +99,7 @@ class OOFEM_EXPORT EModelDefaultPrescribedEquationNumbering : public UnknownNumb public: EModelDefaultPrescribedEquationNumbering(void) : UnknownNumberingScheme() { } - virtual int giveDofEquationNumber(Dof *dof) const { + int giveDofEquationNumber(Dof *dof) const override { return dof->__givePrescribedEquationNumber(); } }; @@ -119,8 +119,8 @@ class DofIDEquationNumbering : public UnknownNumberingScheme DofIDEquationNumbering(bool prescribed, IntArray dofids) : UnknownNumberingScheme(), dofids(std :: move(dofids)), prescribed(prescribed) { } - virtual bool isDefault() const { return !prescribed; } - virtual int giveDofEquationNumber(Dof *dof) const { + bool isDefault() const override { return !prescribed; } + int giveDofEquationNumber(Dof *dof) const override { DofIDItem id = dof->giveDofID(); if ( dofids.contains(id) ) { return prescribed ? dof->__givePrescribedEquationNumber() : dof->__giveEquationNumber(); diff --git a/src/oofemlib/unknowntype.h b/src/oofemlib/unknowntype.h index 97d5f9bc8..81e514897 100644 --- a/src/oofemlib/unknowntype.h +++ b/src/oofemlib/unknowntype.h @@ -48,7 +48,9 @@ namespace oofem { ENUM_ITEM_WITH_VALUE(Humidity, 7) \ ENUM_ITEM_WITH_VALUE(EigenVector, 8) \ ENUM_ITEM_WITH_VALUE(DirectorField, 15) /* Vector field */ \ - ENUM_ITEM_WITH_VALUE(DeplanationFunction, 16) + ENUM_ITEM_WITH_VALUE(DeplanationFunction, 16) \ + ENUM_ITEM_WITH_VALUE(MacroSlipVector, 17) \ + ENUM_ITEM_WITH_VALUE(ResidualForce, 18) /** * Type representing particular unknown (its physical meaning). */ diff --git a/src/oofemlib/unstructuredgridfield.C b/src/oofemlib/unstructuredgridfield.C index 0a8026533..d69091783 100644 --- a/src/oofemlib/unstructuredgridfield.C +++ b/src/oofemlib/unstructuredgridfield.C @@ -35,24 +35,23 @@ #include "unstructuredgridfield.h" #include "feinterpol.h" namespace oofem { +FEI2dLineLin UnstructuredGridField::Cell::i1(1, 2); +FEI2dLineQuad UnstructuredGridField::Cell::i2(1, 2); +FEI2dTrLin UnstructuredGridField::Cell::i3(1, 2); +FEI2dTrQuad UnstructuredGridField::Cell::i4(1, 2); +FEI2dQuadLin UnstructuredGridField::Cell::i5(1, 2); +FEI2dQuadQuad UnstructuredGridField::Cell::i6(1, 2); +FEI3dTetLin UnstructuredGridField::Cell::i7; +FEI3dHexaLin UnstructuredGridField::Cell::i8; - FEI2dLineLin UnstructuredGridField::Cell::i1 (1,2); - FEI2dLineQuad UnstructuredGridField::Cell::i2 (1,2); - FEI2dTrLin UnstructuredGridField::Cell::i3 (1,2); - FEI2dTrQuad UnstructuredGridField::Cell::i4 (1,2); - FEI2dQuadLin UnstructuredGridField::Cell::i5 (1,2); - FEI2dQuadQuad UnstructuredGridField::Cell::i6 (1,2); - FEI3dTetLin UnstructuredGridField::Cell::i7; - FEI3dHexaLin UnstructuredGridField::Cell::i8; - - FEInterpolation* UnstructuredGridField::Cell::interpTable[] = { - &UnstructuredGridField::Cell::i1, - &UnstructuredGridField::Cell::i2, - &UnstructuredGridField::Cell::i3, - &UnstructuredGridField::Cell::i4, - &UnstructuredGridField::Cell::i5, - &UnstructuredGridField::Cell::i6, - &UnstructuredGridField::Cell::i7, - &UnstructuredGridField::Cell::i8 - }; +FEInterpolation *UnstructuredGridField::Cell::interpTable[] = { + & UnstructuredGridField::Cell::i1, + & UnstructuredGridField::Cell::i2, + & UnstructuredGridField::Cell::i3, + & UnstructuredGridField::Cell::i4, + & UnstructuredGridField::Cell::i5, + & UnstructuredGridField::Cell::i6, + & UnstructuredGridField::Cell::i7, + & UnstructuredGridField::Cell::i8 +}; } // end namespace oofem diff --git a/src/oofemlib/unstructuredgridfield.h b/src/oofemlib/unstructuredgridfield.h index cf57e05c7..69a2b30aa 100644 --- a/src/oofemlib/unstructuredgridfield.h +++ b/src/oofemlib/unstructuredgridfield.h @@ -48,421 +48,408 @@ #include "fei2dquadquad.h" #include "fei3dtetlin.h" #include "fei3dhexalin.h" - -#include "pfem/octreelocalizert.h" +#include "octreelocalizert.h" #include "error.h" namespace oofem { - /** - * Field defined by values fefined on unstructured grid. + * Field defined by values defined on unstructured grid. * This implementation does not require that underlying grid is oofem mesh (composed of DofMagars and Elements), * but rather simple objects (Vertices and Cells) which in turn does not have to provide complex FE services. * Typically used to map extermal field to mupif. + * The performance is robust but quite slow due to excessive searching. For external fields, use rather DofManValueField. */ -class OOFEM_EXPORT UnstructuredGridField: public Field +class OOFEM_EXPORT UnstructuredGridField : public Field { protected: + class Vertex + { + FloatArray coords; +public: + Vertex() : coords() {} + Vertex(FloatArray &c) { coords = c; } + Vertex &operator=(const Vertex &v) { + coords = v.coords; + return * this; + } + const FloatArray &getCoordinates() const { return coords; } + }; + /* Auxiliary class to represent interpolation cell, basically holding vertices defining its shape and interpolation type */ + class Cell + { + Element_Geometry_Type itype; + IntArray vertices; + UnstructuredGridField *mesh; + // array of interpolation instances used for supported ElementGeometryTypes + static FEI2dLineLin i1; + static FEI2dLineQuad i2; + static FEI2dTrLin i3; + static FEI2dTrQuad i4; + static FEI2dQuadLin i5; + static FEI2dQuadQuad i6; + static FEI3dTetLin i7; + static FEI3dHexaLin i8; - class Vertex { - FloatArray coords; - public: - Vertex (): coords() {} - Vertex (FloatArray& c) {coords = c;} - Vertex& operator= (const Vertex& v) { - coords = v.coords; - return *this; - } - const FloatArray* getCoordinates() const {return &coords;} - }; + static FEInterpolation *interpTable[]; + + + /** + * Wrapper around element definition to provide FEICellGeometry interface. + */ + class FEICellGeometryWrapper : public FEICellGeometry + { +protected: + const Cell *cell; +public: + FEICellGeometryWrapper(const Cell *c) : FEICellGeometry() { + this->cell = c; + } + virtual ~FEICellGeometryWrapper() { } + + int giveNumberOfVertices() const override { + return this->cell->giveNumberOfVertices(); + } + const FloatArray &giveVertexCoordinates(int i) const override + { + return ( ( cell->getVertex(i) )->getCoordinates() ); + } + }; +public: + Cell() { + itype = EGT_unknown; + mesh = NULL; + } + Cell(Element_Geometry_Type t, IntArray &v, UnstructuredGridField *m) { + itype = t; + vertices = v; + mesh = m; + } + Cell &operator=(const Cell &c) { + itype = c.itype; + vertices = c.vertices; + mesh = c.mesh; + return * this; + } - /* Auxiliary class to represent interpolation cell, basically holding vertices defining its shape and interpolation type */ - class Cell { - Element_Geometry_Type itype; - IntArray vertices; - UnstructuredGridField *mesh; - - // array of interpolation instances used for supported ElementGeometryTypes - static FEI2dLineLin i1; - static FEI2dLineQuad i2; - static FEI2dTrLin i3; - static FEI2dTrQuad i4; - static FEI2dQuadLin i5; - static FEI2dQuadQuad i6; - static FEI3dTetLin i7; - static FEI3dHexaLin i8; - - static FEInterpolation* interpTable[] ; + int giveNumberOfVertices() const { return vertices.giveSize(); } + bool containsPoint(const FloatArray &coords) const { + FloatArray tmp; + BoundingBox b; + this->giveBoundingBox(b); + if ( b.contains(coords) ) { + const FEICellGeometryWrapper cgw = FEICellGeometryWrapper(this); + return ( this->getInterpolation()->global2local(tmp, coords, cgw) ); + } + return false; + } + void giveBoundingBox(BoundingBox &bb) const { + double size; + FloatArray bb0, bb1; + bb1 = bb0 = this->getVertex(1)->getCoordinates(); - /** - * Wrapper around element definition to provide FEICellGeometry interface. - */ - class FEICellGeometryWrapper : public FEICellGeometry + for ( int i = 2; i <= this->giveNumberOfVertices(); i++ ) { + const auto &coordinates = this->getVertex(i)->getCoordinates(); + bb0.beMinOf(bb0, coordinates); + bb1.beMaxOf(bb1, coordinates); + } + bb1.subtract(bb0); + int nsd = bb1.giveSize(); + IntArray mask(3); + size = bb1.at(1); + for ( int i = 1; i < nsd; i++ ) { size = max(size, bb1 [ i ]); } + for ( int i = 0; i < nsd; i++ ) { mask [ i ] = 1; } + bb.init(bb0, size, mask); + } + + double giveClosestPoint(FloatArray &lcoords, FloatArray &closest, const FloatArray &gcoords) { + FEInterpolation *interp = this->getInterpolation(); + + if ( !interp->global2local(lcoords, gcoords, FEICellGeometryWrapper(this) ) ) { // Outside element + interp->local2global(closest, lcoords, FEICellGeometryWrapper(this) ); + return distance(closest, gcoords); + } else { + closest = gcoords; + return 0.0; + } + } + + FEInterpolation *getInterpolation() const { + if ( this->itype == EGT_line_1 ) { return interpTable [ 0 ]; } else if ( this->itype == EGT_line_2 ) { return interpTable [ 1 ]; } else if ( this->itype == EGT_triangle_1 ) { return interpTable [ 2 ]; } else if ( this->itype == EGT_triangle_2 ) { return interpTable [ 3 ]; } else if ( this->itype == EGT_quad_1 ) { return interpTable [ 4 ]; } else if ( this->itype == EGT_quad_2 ) { return interpTable [ 5 ]; } else if ( this->itype == EGT_tetra_1 ) { return interpTable [ 6 ]; } else if ( this->itype == EGT_hexa_1 ) { return interpTable [ 7 ]; } else { + OOFEM_LOG_ERROR("UnstructuredGridField.Cell:: Unsupported cell type"); + return NULL; + } + } + const Vertex *getVertex(int i) const {//1-based + return mesh->getVertex(vertices [ i - 1 ]); + } + + int interpolate(FloatArray &answer, const FloatArray &pos, FloatArray **vertexVals) { + int i, j, size = vertexVals [ 0 ]->giveSize(); + FloatArray N, lcoords; + + FEInterpolation *it = this->getInterpolation(); + FEICellGeometryWrapper cw(this); + it->global2local(lcoords, pos, cw); + it->evalN(N, lcoords, cw); + + answer.resize(size); + answer.zero(); + for ( i = 0; i < giveNumberOfVertices(); i++ ) { + for ( j = 0; j < size; j++ ) { + answer(j) += N(i) * vertexVals [ i ]->at(j + 1); + } + } + return 1; + } + + int getVertexNum(int i) { //1-based + return this->vertices [ i - 1 ]; + } + }; + + + class CellInsertionFunctor : public SL_Insertion_Functor< Cell > { - protected: - const Cell *cell; - public: - FEICellGeometryWrapper(const Cell * c) : FEICellGeometry() { - this->cell = c; - } - virtual ~FEICellGeometryWrapper() { } - int giveNumberOfVertices() const { - return this->cell->giveNumberOfVertices(); - } - inline const FloatArray *giveVertexCoordinates(int i) const - { - return ((cell->getVertex(i-1))->getCoordinates()); - } +private: +public: + CellInsertionFunctor() {} + bool evaluate(Cell &member, OctantRecT< Cell > *cell) override { + BoundingBox b; + member.giveBoundingBox(b); + OctantRec::BoundingBoxStatus s = cell->testBoundingBox(b); + if ( ( s == OctantRec::BBS_InsideCell ) || ( s == OctantRec::BBS_ContainsCell ) ) { + return true; + } else { + return false; + } + } + + void registerInsertion(Cell &member, LocalInsertionData< Cell >lidata) override {} + std::list< LocalInsertionData< Cell > > *giveInsertionList(Cell &m) override { return nullptr; } }; - public: - Cell () { - itype = EGT_unknown; - mesh=NULL; - } - Cell (Element_Geometry_Type t, IntArray& v, UnstructuredGridField* m) { - itype = t; - vertices = v; - mesh = m; - } + class CellContainingPointFunctor : public SL_Evaluation_Functor< Cell > + { +protected: + FloatArray position; + std::list< Cell >cells; +public: + /** + * Constructor + * @param pos Starting position of the search + * @param d Domain containing nodes the triangles are defined by + */ + CellContainingPointFunctor(const FloatArray &pos) : position(pos) {} + ~CellContainingPointFunctor() { } - Cell& operator= (const Cell& c) { - itype = c.itype; - vertices = c.vertices; - mesh = c.mesh; - return *this; - } - - int giveNumberOfVertices() const {return vertices.giveSize();} - bool containsPoint(const FloatArray &coords) const { - FloatArray tmp; - BoundingBox b; - this->giveBoundingBox(b); - if (b.contains(coords)) { - const FEICellGeometryWrapper cgw = FEICellGeometryWrapper(this); - return (this->getInterpolation()->global2local (tmp, coords, cgw)); - } - return false; - } - - void giveBoundingBox(BoundingBox& bb) const { - double size; - FloatArray bb0, bb1; - bb1 = bb0 = *(this->getVertex(0)->getCoordinates()); - - for ( int i = 1; i < this->giveNumberOfVertices(); ++i ) { - const FloatArray *coordinates = this->getVertex(i)->getCoordinates(); - bb0.beMinOf(bb0, * coordinates); - bb1.beMaxOf(bb1, * coordinates); - } - bb1.subtract(bb0); - int nsd = bb1.giveSize(); - IntArray mask(3); - size = bb1.at(1); - for (int i =1; i< nsd; i++) size=max(size, bb1(i)); - for (int i=0; igetInterpolation(); - - if ( !interp->global2local( lcoords, gcoords, FEICellGeometryWrapper(this) ) ) { // Outside element - interp->local2global( closest, lcoords, FEICellGeometryWrapper(this) ); - return closest.distance(gcoords); - } else { - closest = gcoords; - return 0.0; - } - } + /** + * Evaluates a triangle upon its circumscribed cricle. + * @param DTptr Delaunay triangle. nodeNr Number of the node in the domain list + * @returns true if the circumscribed circle of the Delaunay triangle contains the point, false otherwise + */ + bool evaluate(Cell &c) override + { + if ( c.containsPoint(position) ) { + cells.push_back(c); + return true; + } else { + return false; + } + } - FEInterpolation* getInterpolation () const { - if (this->itype == EGT_line_1) return interpTable[0]; - else if (this->itype == EGT_line_2) return interpTable[1]; - else if (this->itype == EGT_triangle_1) return interpTable[2]; - else if (this->itype == EGT_triangle_2) return interpTable[3]; - else if (this->itype == EGT_quad_1) return interpTable[4]; - else if (this->itype == EGT_quad_2) return interpTable[5]; - else if (this->itype == EGT_tetra_1) return interpTable[6]; - else if (this->itype == EGT_hexa_1) return interpTable[7]; - else { - OOFEM_LOG_ERROR ("UnstructuredGridField.Cell:: Unsupported cell type"); - return NULL; - } - - } - const Vertex* getVertex (int i) const {return mesh->getVertex(vertices(i));} - int interpolate (FloatArray& answer, const FloatArray& pos, FloatArray** vertexVals) { - int i,j, size = vertexVals[0]->giveSize(); - FloatArray N, lcoords; - - FEInterpolation* it = this->getInterpolation(); - FEICellGeometryWrapper cw (this); - it->global2local(lcoords, pos, cw); - it->evalN (N, lcoords, cw); - - answer.resize(size); - answer.zero(); - for (i=0; iat(j+1); + /** + * Gives the starting position of the search + * @param position startingPosition + */ + void giveStartingPosition(FloatArray &answer) override + { + answer = position; } - } - return 1; - } - int getVertexNum (int i) { - return this->vertices(i); - } - }; - - - class CellInsertionFunctor : public SL_Insertion_Functor { - private: - public: - CellInsertionFunctor () {} - virtual bool evaluate (Cell& member, OctantRecT* cell) { - BoundingBox b; - member.giveBoundingBox(b); - OctantRec::BoundingBoxStatus s = cell->testBoundingBox(b); - if ((s == OctantRec :: BBS_InsideCell) || (s == OctantRec :: BBS_ContainsCell)) { - return true; - } else { - return false; - } - } - - void registerInsertion (Cell& member, LocalInsertionData lidata) {} - std::list> *giveInsertionList(Cell& m) {return NULL;} - - }; - - class CellContainingPointFunctor: public SL_Evaluation_Functor< Cell > - { - protected: - FloatArray position; - std :: list cells; - public: + + /** + * Gives the triangles containing the node + * @param answer List containing Delaunay triangles + */ + void giveResult(std::list< Cell > &answer) override + { answer = cells; } + + bool isBBXStage1Defined(BoundingBox &BBXStage1) override { return true; } + bool isBBXStage2Defined(BoundingBox &BBXStage2) override { return false; } + }; + + + std::vector< Cell >cellList; + std::vector< Vertex >vertexList; + std::vector< FloatArray >valueList; /** - * Constructor - * @param pos Starting position of the search - * @param d Domain containing nodes the triangles are defined by + * Spatial Localizer. It is build upon request. + * Provides the spatial localization services. */ - CellContainingPointFunctor(const FloatArray &pos) : position (pos) {} - ~CellContainingPointFunctor() { } - + OctreeSpatialLocalizerT< Cell >spatialLocalizer; + /// octree build time stamp + long int octreeTimeStamp; + /// receiver timestamp + long int timeStamp; + /// octree origin shift + double octreeOriginShift; +public: /** - * Evaluates a triangle upon its circumscribed cricle. - * @param DTptr Delaunay triangle. nodeNr Number of the node in the domain list - * @returns true if the circumscribed circle of the Delaunay triangle contains the point, false otherwise + * Constructor. Creates a field, with unspecified field values. */ - bool evaluate(Cell& c) + UnstructuredGridField(int nvert, int ncells, double octreeOriginShift = 0.0) : Field(FieldType::FT_Unknown), spatialLocalizer() { - if (c.containsPoint(position)) { - cells.push_back(c); - return true; - } else { - return false; - } + this->timeStamp = this->octreeTimeStamp = 0; + this->vertexList.resize(nvert); + this->cellList.resize(ncells); + this->valueList.resize(nvert); + this->octreeOriginShift = octreeOriginShift; } - - /** - * Gives the starting position of the search - * @param position startingPosition - */ - void giveStartingPosition(FloatArray &answer) + virtual ~UnstructuredGridField() { } + + void setVertexValue(int num, const FloatArray &vv) { + valueList [ num - 1 ] = vv; + } + + void addVertex(int num, FloatArray &coords) {//1-based + vertexList [ num - 1 ] = Vertex(coords); + this->timeStamp++; + } + + const FloatArray &getVertexCoordinates(int num) const { - answer = position; + return ( this->vertexList [ num - 1 ].getCoordinates() ); } - /** - * Gives the triangles containing the node - * @param answer List containing Delaunay triangles - */ - void giveResult(std :: list &answer) - { answer=cells;} - - bool isBBXStage1Defined(BoundingBox &BBXStage1) { return true; } - bool isBBXStage2Defined(BoundingBox &BBXStage2) { return false; } - - }; - - - std::vector cellList; - std::vector vertexList; - std::vector valueList; - /** - * Spatial Localizer. It is build upon request. - * Provides the spatial localization services. - */ - OctreeSpatialLocalizerT spatialLocalizer; - /// octree build time stamp - long int octreeTimeStamp; - /// receiver timestamp - long int timeStamp; - /// octree origin shift - double octreeOriginShift; - public: - /** - * Constructor. Creates a field, with unspecified field values. - */ - UnstructuredGridField(int nvert, int ncells, double octreeOriginShift=0.0 ) : Field(FieldType::FT_Unknown), spatialLocalizer() - { this->timeStamp = this->octreeTimeStamp = 0; - this->vertexList.resize(nvert); - this->cellList.resize(ncells); - this->valueList.resize(nvert); - this->octreeOriginShift = octreeOriginShift; + Vertex *getVertex(int num) { //1-based + return & this->vertexList [ num - 1 ]; } - virtual ~UnstructuredGridField() { } - - void setVertexValue(int num, const FloatArray& vv) { - valueList[num] = vv; - } - - void addVertex (int num, FloatArray& coords) { - vertexList[num] = Vertex(coords); - this->timeStamp++; - } - - Vertex* getVertex (int num) {return &this->vertexList[num];} - - void addCell (int num, Element_Geometry_Type type, IntArray& vertices) { - cellList[num]=Cell(type, vertices, this); - this->timeStamp ++; - } - - int evaluateAt(FloatArray &answer, const FloatArray &coords, - ValueModeType mode, TimeStep *tStep) override { - std::list elist; - if ((mode == VM_Total) || (mode == VM_TotalIntrinsic)) { - if(this->cellList.size()>0){ - this->initOctree(); - CellContainingPointFunctor f(coords); - this->spatialLocalizer.giveDataOnFilter(elist, f); - if (elist.size()) { - Cell &c = elist.front(); // take first - // colect vertex values - int size = c.giveNumberOfVertices(); - FloatArray** vertexValues = new FloatArray*[size]; - for (int i=0; ivalueList[c.getVertexNum(i)]); + + void addCell(int num, Element_Geometry_Type type, IntArray &vertices) { //1-based + cellList [ num - 1 ] = Cell(type, vertices, this); + this->timeStamp++; + } + + int evaluateAt(FloatArray &answer, const FloatArray &coords, + ValueModeType mode, TimeStep *tStep) override { + std::list< Cell >elist; + if ( ( mode == VM_Total ) || ( mode == VM_TotalIntrinsic ) ) { + if ( this->cellList.size() > 0 ) { + this->initOctree(); + CellContainingPointFunctor f(coords); + this->spatialLocalizer.giveDataOnFilter(elist, f); + if ( elist.size() ) { + Cell &c = elist.front(); // take first + // colect vertex values + int size = c.giveNumberOfVertices(); + FloatArray **vertexValues = new FloatArray * [ size ]; + for ( int i = 0; i < size; i++ ) { + vertexValues [ i ] = & ( this->valueList [ c.getVertexNum(i + 1) - 1 ] ); + } + c.interpolate(answer, coords, vertexValues); + //answer.printYourself(); + return 0; + } else { + coords.printYourself(); + OOFEM_ERROR("No cells defined"); + return 1; } - c.interpolate (answer, coords, vertexValues); - return 0; } else { - return 1; - } - } else { - if(!this->vertexList.size()) { - return 1; - } - // alternative method - we use the value of the closest point - double minDist=0.,dist=0.; - - int idOfClosestPoint=-1; - for(int i=0;i<(int) this->vertexList.size();i++){ - const FloatArray *pcoords=this->vertexList[i].getCoordinates(); - dist=sqrt( pow(coords[0]-pcoords->at(1),2)+pow(coords[1]-pcoords->at(2),2)+pow(coords[2]-pcoords->at(3),2) ); - if(distvertexList.size() ) { + OOFEM_ERROR("No vertices defined"); + return 1; } + // alternative method - we use the value of the closest point + double minDist = 0., dist = 0.; + + int idOfClosestPoint = -1; + for ( int i = 0; i < ( int ) this->vertexList.size(); i++ ) { + const auto &pcoords = this->vertexList [ i ].getCoordinates(); + dist = sqrt(pow(coords [ 0 ] - pcoords.at(1), 2) + pow(coords [ 1 ] - pcoords.at(2), 2) + pow(coords [ 2 ] - pcoords.at(3), 2) ); + if ( ( dist < minDist ) || ( !i ) ) { + minDist = dist; + idOfClosestPoint = i; + } + } + answer = this->valueList [ idOfClosestPoint ]; + //printf("closest point is %d\n",idOfClosestPoint); + return 0; } - answer=this->valueList[idOfClosestPoint]; - //printf("closest point is %d\n",idOfClosestPoint); - return 0; + } else { + OOFEM_ERROR("Unsupported ValueModeType"); } - } else { - OOFEM_ERROR("Unsupported ValueModeType"); } - } - - /** - Implementaton of Field::evaluateAt for DofManager. - */ - int evaluateAt(FloatArray &answer, DofManager *dman, - ValueModeType mode, TimeStep *tStep) override { - FloatArray* coords = dman->giveCoordinates(); - return this->evaluateAt (answer, *coords, mode, tStep); - } - - /** - * Stores receiver state to output stream. - * Writes the FEMComponent class-id in order to allow test whether correct data are then restored. - * @param stream Output stream. - * @param mode Determines amount of info in stream (state, definition,...). - * @return contextIOResultType. - * @exception Throws an ContextIOERR exception if error encountered. - */ - contextIOResultType saveContext(DataStream &stream, ContextMode mode) override { return CIO_OK; } - /** - * Restores the receiver state previously written in stream. - * Reads the FEMComponent class-id in order to allow test consistency. - * @param stream Input stream. - * @param mode Determines amount of info in stream (state, definition,...). - * @return contextIOResultType. - * @exception Throws an ContextIOERR exception if error encountered. - */ - contextIOResultType restoreContext(DataStream &stream, ContextMode mode) override { return CIO_OK; } - - /// @return Class name of the receiver. - const char *giveClassName() const override { return "UnstructuredGridField"; } - - protected: - void initOctree() { - if (this->timeStamp != this->octreeTimeStamp) { - // rebuild octree - this->spatialLocalizer.clear(); - // get octree bbox - std::vector::iterator it = vertexList.begin(); - FloatArray cmax, cmin; - cmax= cmin = *((*it).getCoordinates()); - int nsd = cmin.giveSize(); - ++it; - for (; it != vertexList.end(); ++it) { - const FloatArray *vc = (*it).getCoordinates(); - for (int j=0; jgiveCoordinates(); + return this->evaluateAt(answer, coords, mode, tStep); + } + + void saveContext(DataStream &stream) override { } + void restoreContext(DataStream &stream) override { } + + /// @return Class name of the receiver. + const char *giveClassName() const override { return "UnstructuredGridField"; } + +protected: + void initOctree() { + if ( this->timeStamp != this->octreeTimeStamp ) { + // rebuild octree + this->spatialLocalizer.clear(); + // get octree bbox + std::vector< Vertex >::iterator it = vertexList.begin(); + FloatArray cmax, cmin; + cmax = cmin = ( * it ).getCoordinates(); + int nsd = cmin.giveSize(); + ++it; + for ( ; it != vertexList.end(); ++it ) { + const auto &vc = ( * it ).getCoordinates(); + for ( int j = 0; j < nsd; j++ ) { + cmax(j) = max(cmax(j), vc(j) ); + cmin(j) = min(cmin(j), vc(j) ); + } + } + // introduce origin shift (if set up) + for ( int j = 0; j < nsd; j++ ) { + cmin(j) -= octreeOriginShift; + } + double size = 0.0; + IntArray mask(3); + for ( int j = 0; j < nsd; j++ ) { + size = max(size, cmax(j) - cmin(j) ); + mask [ j ] = 1; + } + BoundingBox bb; + bb.init(cmin, size, mask); + this->spatialLocalizer.init(bb); + std::vector< Cell >::iterator cit; + CellInsertionFunctor cf; + //int cellcount = 1; + for ( cit = this->cellList.begin(); cit != this->cellList.end(); ++cit ) { + /* + * BoundingBox b; (*cit).giveBoundingBox(b); + * FloatArray o; + * b.giveOrigin(o); + * printf ("Inserting cell %d, Origin, Size:", cellcount++); + * o.printYourself(); + * printf("%lf\n", b.giveSize()); + */ + this->spatialLocalizer.insertMemberIntoOctree(* cit, cf); + } + + // update timestamp + this->octreeTimeStamp = this->timeStamp; } - } - // introduce origin shift (if set up) - for (int j=0; jspatialLocalizer.init (bb); - std::vector::iterator cit; - CellInsertionFunctor cf; - //int cellcount = 1; - for (cit=this->cellList.begin(); cit != this->cellList.end(); ++cit) { - /* - BoundingBox b; (*cit).giveBoundingBox(b); - FloatArray o; - b.giveOrigin(o); - printf ("Inserting cell %d, Origin, Size:", cellcount++); - o.printYourself(); - printf("%lf\n", b.giveSize()); - */ - this->spatialLocalizer.insertMemberIntoOctree(*cit, cf); - } - - // update timestamp - this->octreeTimeStamp = this->timeStamp; } - } }; } // end namespace oofem #endif // unstructuredgridfield_h diff --git a/src/oofemlib/userdefdirichletbc.C b/src/oofemlib/userdefdirichletbc.C index 5defcf911..82b9df9b7 100644 --- a/src/oofemlib/userdefdirichletbc.C +++ b/src/oofemlib/userdefdirichletbc.C @@ -84,7 +84,7 @@ UserDefDirichletBC :: give(Dof *dof, ValueModeType mode, double time) int numArgs = 3; // Create array with node coordinates - int dim = dMan->giveCoordinates()->giveSize(); + int dim = dMan->giveCoordinates().giveSize(); PyObject *pArgArray = PyList_New(dim); PyObject *pArgs = PyTuple_New(numArgs); @@ -128,22 +128,17 @@ UserDefDirichletBC :: give(Dof *dof, ValueModeType mode, double time) } -IRResultType -UserDefDirichletBC :: initializeFrom(InputRecord *ir) +void +UserDefDirichletBC :: initializeFrom(InputRecord &ir) // Sets up the dictionary where the receiver stores the conditions it // imposes. { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = GeneralBoundaryCondition :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + GeneralBoundaryCondition :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->mFileName, _IFT_UserDefDirichletBC_filename); // Import Python file - PyObject *mpName = PyString_FromString( this->mFileName.c_str() ); + PyObject *mpName = PyUnicode_FromString( this->mFileName.c_str() ); mpModule = PyImport_Import(mpName); Py_DECREF(mpName); @@ -151,15 +146,11 @@ UserDefDirichletBC :: initializeFrom(InputRecord *ir) // Load and call Python function mpFunc = PyObject_GetAttrString(mpModule, "giveUserDefBC"); if ( !mpFunc ) { - OOFEM_WARNING("Cannot find function 'giveUserDefBC' in file: %s", this->mFileName.c_str()); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_UserDefDirichletBC_filename, "Cannot find function 'giveUserDefBC' in file: " + mFileName); } } else { - OOFEM_WARNING("Cannot find module in file: %s", this->mFileName.c_str()); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_UserDefDirichletBC_filename, "Cannot find module in file: " + mFileName); } - - return IRRT_OK; } diff --git a/src/oofemlib/userdefdirichletbc.h b/src/oofemlib/userdefdirichletbc.h index 1ebad45d4..3896a0aee 100644 --- a/src/oofemlib/userdefdirichletbc.h +++ b/src/oofemlib/userdefdirichletbc.h @@ -94,15 +94,14 @@ class OOFEM_EXPORT UserDefDirichletBC : public BoundaryCondition /// Destructor virtual ~UserDefDirichletBC(); - virtual double give(Dof *dof, ValueModeType mode, double time); + double give(Dof *dof, ValueModeType mode, double time) override; - // Overloaded methods: - virtual bcType giveType() const { return DirichletBT; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void scale(double s); - virtual const char *giveClassName() const { return "UserDefDirichletBC"; } - virtual const char *giveInputRecordName() const { return _IFT_UserDefDirichletBC_Name; } + bcType giveType() const override { return DirichletBT; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void scale(double s) override; + const char *giveClassName() const override { return "UserDefDirichletBC"; } + const char *giveInputRecordName() const override { return _IFT_UserDefDirichletBC_Name; } }; } // end namespace oofem diff --git a/src/oofemlib/util.C b/src/oofemlib/util.C index 136f74f0d..ae51fd3bf 100644 --- a/src/oofemlib/util.C +++ b/src/oofemlib/util.C @@ -40,28 +40,120 @@ #include "error.h" #include +#if defined ( __GNUC__ ) && defined ( HAVE_EXECINFO_H ) +#include +#include +#include +#include +#endif namespace oofem { -EngngModel *InstanciateProblem(DataReader *dr, problemMode mode, int contextFlag, EngngModel *_master, bool parallelFlag) + +void print_stacktrace(FILE *out, int skip, unsigned int max_frames) +{ +#if defined ( __GNUC__ ) && defined ( HAVE_EXECINFO_H ) +#if 0 + // Much simpler example from SO + void *trace_elems[max_frames]; + int trace_elem_count(backtrace( trace_elems, max_frames )); + char **stack_syms(backtrace_symbols( trace_elems, trace_elem_count )); + for ( int i = 0 ; i < trace_elem_count ; ++i ) { + std::cout << stack_syms[i] << "\n"; + } + free( stack_syms ); +#endif + // Taken from https://idlebox.net/2008/0901-stacktrace-demangled/ which indicated free usage. + int addrlen = 0; + fprintf(out, "stack trace:\n"); + + // storage array for stack trace address data + void *addrlist [ max_frames + 1 ]; + + // retrieve current stack addresses + addrlen = backtrace( addrlist, sizeof( addrlist ) / sizeof( void * ) ); + if ( addrlen == 0 ) { + fprintf(out, " \n"); + return; + } + + // resolve addresses into strings containing "filename(function+address)", + // this array must be free()-ed + char **symbollist; + symbollist = backtrace_symbols(addrlist, addrlen); + // allocate string which will be filled with the demangled function name + size_t funcnamesize = 256; + char *funcname = ( char * ) malloc(funcnamesize); + + // iterate over the returned symbol lines. skip the first, it is the + // address of this function. + for ( int i = skip+1; i < addrlen; i++ ) { + char *begin_name = 0, *begin_offset = 0, *end_offset = 0; + + // find parentheses and +address offset surrounding the mangled name: + // ./module(function+0x15c) [0x8048a6d] + for ( char *p = symbollist [ i ]; * p; ++p ) { + if ( * p == '(' ) { + begin_name = p; + } else if ( * p == '+' ) { + begin_offset = p; + } else if ( * p == ')' && begin_offset ) { + end_offset = p; + break; + } + } + + if ( begin_name && begin_offset && end_offset && + begin_name < begin_offset ) { + * begin_name++ = '\0'; + * begin_offset++ = '\0'; + * end_offset = '\0'; + + // mangled name is now in [begin_name, begin_offset) and caller + // offset in [begin_offset, end_offset). now apply + // __cxa_demangle(): + + int status; + char *ret = abi :: __cxa_demangle(begin_name, + funcname, & funcnamesize, & status); + if ( status == 0 ) { + funcname = ret; // use possibly realloc()-ed string + fprintf(out, " %s : %s+%s\n", + symbollist [ i ], funcname, begin_offset); + } else { + // demangling failed. Output function name as a C function with + // no arguments. + fprintf(out, " %s : %s()+%s\n", + symbollist [ i ], begin_name, begin_offset); + } + } else { + // couldn't parse the line? print the whole line. + fprintf(out, " %s\n", symbollist [ i ]); + } + } + + free(funcname); + free(symbollist); +#else + fprintf(out, "No backtrace available\n"); +#endif +} + + +std::unique_ptr InstanciateProblem(DataReader &dr, problemMode mode, int contextFlag, EngngModel *_master, bool parallelFlag) { - IRResultType result; // Required by IR_GIVE_FIELD macro - EngngModel *problem; std :: string problemName, dataOutputFileName, desc; - dataOutputFileName = dr->giveOutputFileName(); - desc = dr->giveDescription(); + dataOutputFileName = dr.giveOutputFileName(); + desc = dr.giveDescription(); - /* here we need copy of input record. The pointer returned by dr->giveInputRecord can (and will) + /* here we need copy of input record. The pointer returned by dr.giveInputRecord can (and will) * be updated as reading e-model components (nodes, etc). But we need this record being available * through the whole e-model instanciation */ - InputRecord *emodelir = dr->giveInputRecord(DataReader :: IR_emodelRec, 1)->GiveCopy(); - result = emodelir->giveRecordKeywordField(problemName); ///@todo Make this function robust, it can't be allowed to fail (the record keyword is not a normal field-id) - if ( result != IRRT_OK ) { - emodelir->report_error("", __func__, "", result, __FILE__, __LINE__); - } + auto emodelir = dr.giveInputRecord(DataReader :: IR_emodelRec, 1).clone(); + emodelir->giveRecordKeywordField(problemName); ///@todo Make this function robust, it can't be allowed to fail (the record keyword is not a normal field-id) - problem = classFactory.createEngngModel(problemName.c_str(), 1, _master); + auto problem = classFactory.createEngngModel(problemName.c_str(), 1, _master); if ( !problem ) { OOFEM_WARNING( "Failed to construct engineering model of type \"%s\".\n", problemName.c_str() ); return NULL; @@ -74,9 +166,8 @@ EngngModel *InstanciateProblem(DataReader *dr, problemMode mode, int contextFlag problem->setContextOutputMode(COM_Always); } - problem->instanciateYourself( dr, emodelir, dataOutputFileName.c_str(), desc.c_str() ); - - delete emodelir; + problem->instanciateYourself( dr, *emodelir, dataOutputFileName.c_str(), desc.c_str() ); + emodelir->finish(); return problem; } diff --git a/src/oofemlib/util.h b/src/oofemlib/util.h index 074fc1727..768c55af7 100644 --- a/src/oofemlib/util.h +++ b/src/oofemlib/util.h @@ -38,10 +38,18 @@ #include "oofemcfg.h" #include "problemmode.h" +#include +#include + namespace oofem { class DataReader; class EngngModel; +/** + * Helper that prints a stack trace (only available on GCC) + */ +void print_stacktrace(FILE *out = stderr, int skip = 0, unsigned int max_frames = 63); + /** * Instanciates the new problem. * @param dr DataReader containing the problem data. @@ -50,6 +58,6 @@ class EngngModel; * @param parallelFlag Determines if the problem should be run in parallel or not. * @param contextFlag When set, turns on context output after each step. */ -OOFEM_EXPORT EngngModel *InstanciateProblem(DataReader *dr, problemMode mode, int contextFlag, EngngModel *master = 0, bool parallelFlag = false); +OOFEM_EXPORT std::unique_ptr InstanciateProblem(DataReader &dr, problemMode mode, int contextFlag, EngngModel *master = 0, bool parallelFlag = false); } // end namespace oofem #endif // util_h diff --git a/src/oofemlib/valuemodetype.h b/src/oofemlib/valuemodetype.h index 74a3811ef..b44f8ca69 100644 --- a/src/oofemlib/valuemodetype.h +++ b/src/oofemlib/valuemodetype.h @@ -65,7 +65,9 @@ namespace oofem { ENUM_ITEM_WITH_VALUE(VM_RhsIncremental, 6) \ ENUM_ITEM_WITH_VALUE(VM_RhsInitial, 7) \ ENUM_ITEM_WITH_VALUE(VM_Intermediate, 8) \ - ENUM_ITEM_WITH_VALUE(VM_TotalIntrinsic, 9) + ENUM_ITEM_WITH_VALUE(VM_TotalIntrinsic, 9) \ + ENUM_ITEM_WITH_VALUE(VM_Residual, 99) + /** diff --git a/src/oofemlib/vtkbaseexportmodule.C b/src/oofemlib/vtkbaseexportmodule.C new file mode 100644 index 000000000..ba66b76fb --- /dev/null +++ b/src/oofemlib/vtkbaseexportmodule.C @@ -0,0 +1,1182 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "vtkbaseexportmodule.h" +#include "element.h" +#include "gausspoint.h" +#include "timestep.h" +#include "engngm.h" +#include "node.h" +#include "dof.h" +#include "materialinterface.h" +#include "mathfem.h" +#include "cltypes.h" +#include "material.h" +#include "classfactory.h" +#include "crosssection.h" +#include "unknownnumberingscheme.h" + +#include +#include +#include + +namespace oofem { + +void +VTKPiece::setNumberOfNodes(int numNodes) +{ + this->numNodes = numNodes; + this->nodeCoords.resize(numNodes); +} + +void +VTKPiece::setNumberOfCells(int numCells) +{ + this->numCells = numCells; + this->connectivity.resize(numCells); + this->elCellTypes.resize(numCells); + this->elOffsets.resize(numCells); +} + +void +VTKPiece::setConnectivity(int cellNum, IntArray &nodes) +{ + this->connectivity [ cellNum - 1 ] = nodes; +} + +void +VTKPiece::setNodeCoords(int nodeNum, const FloatArray &coords) +{ + this->nodeCoords [ nodeNum - 1 ] = coords; +} + +void +VTKPiece::setNumberOfPrimaryVarsToExport(const IntArray& primVars, int numNodes) +{ + for (int it=1; it<= primVars.giveSize(); it++) { + UnknownType type = (UnknownType) primVars.at(it); + this->nodeVars [type].resize(numNodes); + } +} + +void +VTKPiece::setNumberOfLoadsToExport(int numVars, int numNodes) +{ + this->nodeLoads.resize(numVars); + for ( int i = 1; i <= numVars; i++ ) { + this->nodeLoads [ i - 1 ].resize(numNodes); + } +} + +void +VTKPiece::setNumberOfInternalVarsToExport(const IntArray& ists, int numNodes) +{ + for ( int i = 1; i <= ists.giveSize(); i++ ) { + InternalStateType itype = (InternalStateType) ists.at(i); + this->nodeVarsFromIS [ itype ].resize(numNodes); + } +} + +void +VTKPiece::setNumberOfInternalXFEMVarsToExport(int numVars, int numEnrichmentItems, int numNodes) +{ + this->nodeVarsFromXFEMIS.resize(numVars); + for ( int i = 1; i <= numVars; i++ ) { + this->nodeVarsFromXFEMIS [ i - 1 ].resize(numEnrichmentItems); + for ( int j = 1; j <= numEnrichmentItems; j++ ) { + this->nodeVarsFromXFEMIS [ i - 1 ] [ j - 1 ].resize(numNodes); + } + } +} + +void +VTKPiece::setNumberOfCellVarsToExport(const IntArray& cellVars, int numCells) +{ + for ( int i = 1; i <= cellVars.giveSize(); i++ ) { + InternalStateType type = (InternalStateType) cellVars.at(i); + this->cellVars [ type ].resize(numCells); + } +} + +void +VTKPiece::setPrimaryVarInNode(UnknownType type, int nodeNum, FloatArray valueArray) +{ + this->nodeVars [ type ] [ nodeNum - 1 ] = std::move(valueArray); +} + +void +VTKPiece::setLoadInNode(int varNum, int nodeNum, FloatArray valueArray) +{ + this->nodeLoads [ varNum - 1 ] [ nodeNum - 1 ] = std::move(valueArray); +} + +void +VTKPiece::setInternalVarInNode(InternalStateType type, int nodeNum, FloatArray valueArray) +{ + this->nodeVarsFromIS [ type ] [ nodeNum - 1 ] = std::move(valueArray); +} + +void +VTKPiece::setInternalXFEMVarInNode(int varNum, int eiNum, int nodeNum, FloatArray valueArray) +{ + this->nodeVarsFromXFEMIS [ varNum - 1 ] [ eiNum - 1 ] [ nodeNum - 1 ] = std::move(valueArray); +} + + +void +VTKPiece::setCellVar(InternalStateType type, int cellNum, FloatArray valueArray) +{ + this->cellVars [ type ] [ cellNum - 1 ] = std::move(valueArray); +} + +void +VTKPiece::clear() +{ + ///@todo Will this give a memory leak? / JB + numCells = 0; + numNodes = 0; + this->connectivity.clear(); + this->elCellTypes.clear(); + this->elOffsets.clear(); + this->cellVars.clear(); + this->nodeCoords.clear(); + this->nodeVars.clear(); + this->nodeVarsFromIS.clear(); + this->nodeVarsFromXFEMIS.clear(); +} + +#ifdef _PYBIND_BINDINGS + +py::array_t +VTKPiece::getVertices () { + double* result = new double[this->numNodes*3]; + for (int i=0; inumNodes; i++) { + FloatArray &c = this->giveNodeCoords(i+1); + for (int j=0; j(std::vector{this->numNodes, 3}, &result[0]); +} + +py::array_t +VTKPiece::getCellConnectivity () { + int reqSize = 0; + for (int i=0; inumCells; i++) { + reqSize++; + reqSize+=this->giveCellConnectivity(i+1).giveSize(); + } + int* result = new int[reqSize]; + int pos=0; + for (int i=0; inumCells; i++) { + IntArray &c = this->giveCellConnectivity(i+1); + int csize = c.giveSize(); + result[pos++]=csize; + for (int i = 0; i(reqSize, result); +} + +py::array_t +VTKPiece::getCellTypes (VTKBaseExportModule& m) { + int* result = new int[this->numCells]; + for (int i=0; inumCells; i++) { + result[i]=m.giveCellType(this->regionElInd.at(i+1)); + } + return py::array_t(this->numCells, result); +} + +py::array_t +VTKPiece::getPrimaryVertexValues (UnknownType u) { + + if (this->nodeVars.find(u) != this->nodeVars.end()) { + // key exists + std::vector& nodalVars = this->nodeVars[u]; + // get size of nodal record + int recSize = nodalVars[0].giveSize(); + double* result = new double[this->numNodes*recSize]; + int counter = 0; + for (int i=0;inumNodes; i++) { + FloatArray& v = nodalVars[i]; + for (int j=0; j(std::vector{this->numNodes, recSize}, result); + //return py::array_t(this->numNodes*recSize, result); + } else { + return py::array_t(0); + } +} + +py::array_t +VTKPiece::getInternalVertexValues(InternalStateType u) { + if (this->nodeVarsFromIS.find(u)!=this->nodeVarsFromIS.end()) { + // key exists + std::vector& nodalVars = this->nodeVarsFromIS[u]; + // get size of nodal record + int recSize = nodalVars[0].giveSize(); + double* result = new double[this->numNodes*recSize]; + int counter = 0; + for (int i=0;inumNodes; i++) { + FloatArray& v = nodalVars[i]; + for (int j=0; j(std::vector{this->numNodes, recSize}, result); + } else { + return py::array_t(0); + } +} + +py::array_t +VTKPiece::getCellValues(InternalStateType u) { + if (this->cellVars.find(u)!=this->cellVars.end()) { + // key exists + std::vector& cv = this->cellVars[u]; + // get size of nodal record + int recSize = cv[0].giveSize(); + double* result = new double[this->numCells*recSize]; + int counter = 0; + for (int i=0;inumCells; i++) { + FloatArray& v = cv[i]; + for (int j=0; j(std::vector{this->numCells, recSize}, result); + } else { + return py::array_t(0); + } +} + +#endif + + +// End of VTKPiece class implementation + +// Beginning of VTKBaseExportModule + +IntArray VTKBaseExportModule::redToFull = { + 1, 5, 9, 8, 7, 4, 6, 3, 2 +}; //position of xx, yy, zz, yz, xz, xy in tensor + +VTKBaseExportModule::VTKBaseExportModule(int n, EngngModel *e) : ExportModule(n, e) +{} + +VTKBaseExportModule::~VTKBaseExportModule() +{} + +void +VTKBaseExportModule::initialize() +{ + ExportModule::initialize(); +} + +void +VTKBaseExportModule::terminate() +{} + +void +VTKBaseExportModule::makeFullTensorForm(FloatArray &answer, const FloatArray &reducedForm, InternalStateValueType vtype) +{ + answer.resize(9); + answer.zero(); + + for ( int i = 1; i <= reducedForm.giveSize(); i++ ) { + answer.at(redToFull.at(i) ) = reducedForm.at(i); + } + + if ( vtype == ISVT_TENSOR_S3E ) { + answer.at(4) *= 0.5; + answer.at(7) *= 0.5; + answer.at(8) *= 0.5; + } + + // Symmetrize if needed + if ( vtype != ISVT_TENSOR_G ) { + answer.at(2) = answer.at(4); + answer.at(3) = answer.at(7); + answer.at(6) = answer.at(8); + } +} + +int +VTKBaseExportModule::giveCellType(Element *elem) +{ + Element_Geometry_Type elemGT = elem->giveGeometryType(); + int vtkCellType = 0; + + if ( elemGT == EGT_point ) { + vtkCellType = 1; + } else if ( elemGT == EGT_line_1 ) { + vtkCellType = 3; + } else if ( elemGT == EGT_line_2 ) { + vtkCellType = 21; + } else if ( elemGT == EGT_triangle_1 ) { + vtkCellType = 5; + } else if ( elemGT == EGT_triangle_2 ) { + vtkCellType = 22; + } else if ( elemGT == EGT_tetra_1 ) { + vtkCellType = 10; + } else if ( elemGT == EGT_tetra_2 ) { + vtkCellType = 24; + } else if ( elemGT == EGT_quad_1) { + vtkCellType = 9; + } else if ( elemGT == EGT_quad_21_interface ) { + vtkCellType = 30; + } else if ( elemGT == EGT_quad_2 ) { + vtkCellType = 23; + } else if ( elemGT == EGT_quad9_2 ) { + vtkCellType = 23; + } else if ( elemGT == EGT_hexa_1 || elemGT == EGT_quad_1_interface ) { + vtkCellType = 12; + } else if ( elemGT == EGT_hexa_2 ) { + vtkCellType = 25; + } else if ( elemGT == EGT_hexa_27 ) { + vtkCellType = 29; + } else if ( elemGT == EGT_wedge_1 ) { + vtkCellType = 13; + } else if ( elemGT == EGT_wedge_2 ) { + vtkCellType = 26; + } else { + OOFEM_ERROR("unsupported element geometry type on element %d", elem->giveNumber() ); + } + + return vtkCellType; +} + +int VTKBaseExportModule::giveCellType(int num) { + return giveCellType(this->emodel->giveDomain(1)->giveElement(num)); +} + + +int +VTKBaseExportModule::giveNumberOfNodesPerCell(int cellType) +{ + switch ( cellType ) { + case 1: + return 1; + + case 3: + return 2; + + case 5: + case 21: + return 3; + + case 9: + case 10: + return 4; + + case 14: + return 5; + + case 13: + case 22: + case 30: + return 6; + + case 12: + case 23: + return 8; + + case 24: + return 10; + + case 25: + return 20; + + case 29: + return 27; + + default: + OOFEM_ERROR("unsupported cell type ID"); + } + + return 0; // to make compiler happy +} + + +void +VTKBaseExportModule::giveElementCell(IntArray &answer, Element *elem) +{ + // Gives the node mapping from the order used in OOFEM to that used in VTK + + Element_Geometry_Type elemGT = elem->giveGeometryType(); + IntArray nodeMapping(0); + if ( ( elemGT == EGT_point ) || + ( elemGT == EGT_line_1 ) || ( elemGT == EGT_line_2 ) || + ( elemGT == EGT_triangle_1 ) || ( elemGT == EGT_triangle_2 ) || + ( elemGT == EGT_tetra_1 ) || ( elemGT == EGT_tetra_2 ) || + ( elemGT == EGT_quad_1 ) || ( elemGT == EGT_quad_2 ) || + ( elemGT == EGT_hexa_1 ) || ( elemGT == EGT_quad9_2 ) || + ( elemGT == EGT_wedge_1 ) ) {} else if ( elemGT == EGT_hexa_27 ) { + nodeMapping = { + 5, 8, 7, 6, 1, 4, 3, 2, 16, 15, 14, 13, 12, 11, 10, 9, 17, 20, 19, 18, 23, 25, 26, 24, 22, 21, 27 + }; + } else if ( elemGT == EGT_hexa_2 ) { + nodeMapping = { + 5, 8, 7, 6, 1, 4, 3, 2, 16, 15, 14, 13, 12, 11, 10, 9, 17, 20, 19, 18 + }; + } else if ( elemGT == EGT_wedge_2 ) { + nodeMapping = { + 4, 6, 5, 1, 3, 2, 12, 11, 10, 9, 8, 7, 13, 15, 14 + }; + } else if ( elemGT == EGT_quad_1_interface ) { + nodeMapping = { + 1, 2, 4, 3, 5, 6, 8, 7 + }; + } else if ( elemGT == EGT_quad_21_interface ) { + nodeMapping = { + 1, 2, 5, 4, 3, 6 + }; + } else { + OOFEM_ERROR("VTKXMLExportModule: unsupported element geometry type"); + } + + int nelemNodes = elem->giveNumberOfNodes(); + answer.resize(nelemNodes); + if ( nodeMapping.giveSize() > 0 ) { + for ( int i = 1; i <= nelemNodes; i++ ) { + answer.at(i) = elem->giveNode(nodeMapping.at(i) )->giveNumber(); + } + } else { + for ( int i = 1; i <= nelemNodes; i++ ) { + answer.at(i) = elem->giveNode(i)->giveNumber(); + } + } +} + + +bool +VTKBaseExportModule::isElementComposite(Element *elem) +{ + return ( elem->giveGeometryType() == EGT_Composite ); +} + +void +VTKBaseExportModule::setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, Set ®ion) +{ + Domain *d = emodel->giveDomain(1); + Element *elem; + + // output nodes Region By Region + + + // Assemble local->global and global->local region map and get number of + // single cells to process, the composite cells exported individually. + this->initRegionNodeNumbering(vtkPiece, d, tStep, region); + const IntArray& mapG2L = vtkPiece.getMapG2L(); + const IntArray& mapL2G = vtkPiece.getMapL2G(); + const int numNodes = vtkPiece.giveNumberOfNodes(); + const int numRegionEl = vtkPiece.giveNumberOfCells(); + if ( numNodes > 0 && numRegionEl > 0 ) { + // Export nodes as vtk vertices + vtkPiece.setNumberOfNodes(numNodes); + for ( int inode = 1; inode <= numNodes; inode++ ) { + const auto &coords = d->giveNode(mapL2G.at(inode) )->giveCoordinates(); + vtkPiece.setNodeCoords(inode, coords); + } + + + //------------------------------------------- + // Export all the cell data for the piece + //------------------------------------------- + IntArray cellNodes; + vtkPiece.setNumberOfCells(numRegionEl); + + int offset = 0; + int cellNum = 0; + IntArray elems = region.giveElementList(); + for ( int ei = 1; ei <= elems.giveSize(); ei++ ) { + int elNum = elems.at(ei); + elem = d->giveElement(elNum); + + // Skip elements that: + // are inactivated or of composite type ( these are exported individually later) + if ( this->isElementComposite(elem) || !elem->isActivated(tStep) ) { + continue; + } + + //skip materials with casting time > current time + if ( !elem->isCast(tStep) ) { + continue; + } + + if ( elem->giveParallelMode() != Element_local ) { + continue; + } + + vtkPiece.getRegionCells().followedBy(elNum); + + cellNum++; + + // Set the connectivity + this->giveElementCell(cellNodes, elem); // node numbering of the cell according to the VTK format + + // Map from global to local node numbers for the current piece + int numElNodes = cellNodes.giveSize(); + IntArray connectivity(numElNodes); + for ( int i = 1; i <= numElNodes; i++ ) { + connectivity.at(i) = mapG2L.at(cellNodes.at(i) ); + } + + vtkPiece.setConnectivity(cellNum, connectivity); + + vtkPiece.setCellType(cellNum, this->giveCellType(elem) ); // VTK cell type + + offset += numElNodes; + vtkPiece.setOffset(cellNum, offset); + } + + + +/* +#ifdef _PYBIND_BINDINGS + if ( pythonExport ) { + //Export nodes + py::list vals; + for ( int inode = 1; inode <= numNodes; inode++ ) { + py::list node; + const int numberG = d->giveNode(mapL2G.at(inode))->giveGlobalNumber(); + const int number = d->giveNode(mapL2G.at(inode))->giveNumber(); + const auto &coords = d->giveNode(mapL2G.at(inode))->giveCoordinates(); + node.append(inode); + node.append(number); + node.append(numberG); + node.append(coords); + vals.append(node); + } + std::string s = std::to_string(region.giveNumber()); + this->Py_Nodes[s.c_str()] = vals;//keys as region number (VTKPiece) + + //Export elements + py::list elemVals; + for ( int ei = 1; ei <= vtkPiece.giveNumberOfCells(); ei++ ) { + py::list element; + IntArray &conn = vtkPiece.giveCellConnectivity(ei); + element.append(ei); + element.append(conn); + elemVals.append(element); + } + this->Py_Elements[s.c_str()] = elemVals;//keys as region number (VTKPiece) + } +#endif +*/ + + } // end of default piece for simple geometry elements +} + +//---------------------------------------------------- +// Primary variables - readily available in the nodes +//---------------------------------------------------- +void +VTKBaseExportModule::exportPrimaryVars(VTKPiece &vtkPiece, Set ®ion, IntArray& primaryVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep) +{ + Domain *d = emodel->giveDomain(1); + FloatArray valueArray; + smoother.clear(); // Makes sure primary smoother is up-to-date with potentially new mesh. + + //const IntArray& mapG2L = vtkPiece.getMapG2L(); + const IntArray& mapL2G = vtkPiece.getMapL2G(); + + vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport, mapL2G.giveSize() ); + for ( int i = 1, n = primaryVarsToExport.giveSize(); i <= n; i++ ) { + UnknownType type = ( UnknownType ) primaryVarsToExport.at(i); + + for ( int inode = 1; inode <= mapL2G.giveSize(); inode++ ) { + DofManager *dman = d->giveNode(mapL2G.at(inode) ); + + this->getNodalVariableFromPrimaryField(valueArray, dman, tStep, type, region, smoother); + vtkPiece.setPrimaryVarInNode(type, inode, std::move(valueArray) ); + } + } +} + + +void +VTKBaseExportModule::getNodalVariableFromPrimaryField(FloatArray &answer, DofManager *dman, TimeStep *tStep, UnknownType type, Set ®ion, NodalRecoveryModel& smoother) +{ + // This code is not perfect. It should be rewritten to handle all cases more gracefully. + ///@todo This method needs to be cleaned up - maybe define the common vector types so + /// certain dofid's are associated with them /JB + + IntArray dofIDMask(3); + int size; + const FloatArray *recoveredVal; + + InternalStateType iState = IST_DisplacementVector; // Shouldn't be necessary + + dofIDMask.clear(); + + if ( (type == DisplacementVector) || (type == ResidualForce) ) { + dofIDMask = { + ( int ) Undef, ( int ) Undef, ( int ) Undef + }; + for ( Dof *dof : * dman ) { + DofIDItem id = dof->giveDofID(); + if ( id == D_u ) { + dofIDMask.at(1) = id; + } else if ( id == D_v ) { + dofIDMask.at(2) = id; + } else if ( id == D_w ) { + dofIDMask.at(3) = id; + } + } + + answer.resize(3); + } else if ( type == VelocityVector ) { + dofIDMask = { + ( int ) Undef, ( int ) Undef, ( int ) Undef + }; + for ( Dof *dof : * dman ) { + DofIDItem id = dof->giveDofID(); + if ( id == V_u ) { + dofIDMask.at(1) = id; + } else if ( id == V_v ) { + dofIDMask.at(2) = id; + } else if ( id == V_w ) { + dofIDMask.at(3) = id; + } + } + + answer.resize(3); + } else if ( type == EigenVector ) { + dofIDMask = { + ( int ) Undef, ( int ) Undef, ( int ) Undef + }; + for ( Dof *dof : * dman ) { + DofIDItem id = dof->giveDofID(); + if ( ( id == V_u ) || ( id == D_u ) ) { + dofIDMask.at(1) = id; + } else if ( ( id == V_v ) || ( id == D_v ) ) { + dofIDMask.at(2) = id; + } else if ( ( id == V_w ) || ( id == D_w ) ) { + dofIDMask.at(3) = id; + } + } + + answer.resize(3); + } else if ( type == FluxVector || type == Humidity ) { + dofIDMask.followedBy(C_1); + iState = IST_MassConcentration_1; + answer.resize(1); + } else if ( type == DeplanationFunction ) { + dofIDMask.followedBy(Warp_PsiTheta); + iState = IST_Temperature; + answer.resize(1); + } else if ( type == Temperature ) { + dofIDMask.followedBy(T_f); + iState = IST_Temperature; + answer.resize(1); + } else if ( type == PressureVector ) { + dofIDMask.followedBy(P_f); + iState = IST_Pressure; + answer.resize(1); + } else if ( type == DirectorField ) { + for ( Dof *dof : * dman ) { + DofIDItem id = dof->giveDofID(); + if ( ( id == W_u ) || ( id == W_v ) || ( id == W_w ) ) { + dofIDMask.followedBy(id); + } + + answer.resize(3); + } + + iState = IST_DirectorField; + } else if ( type == MacroSlipVector ) { + for ( Dof *dof : * dman ) { + DofIDItem id = dof->giveDofID(); + if ( ( id == S_u ) || ( id == S_v ) || ( id == S_w ) ) { + dofIDMask.followedBy(id); + } + answer.resize(3); + } + iState = IST_MacroSlipVector; + } else { + OOFEM_ERROR("unsupported unknownType %s", __UnknownTypeToString(type) ); + } + + size = dofIDMask.giveSize(); + answer.zero(); + + for ( int j = 1; j <= size; j++ ) { + DofIDItem id = ( DofIDItem ) dofIDMask.at(j); + if ( id == Undef ) { + answer.at(j) = 0.; + } else if ( iState == IST_DirectorField ) { + answer.at(j) = dman->giveDofWithID(id)->giveUnknown(VM_Total, tStep); + // recover values if not done before + smoother.recoverValues(region, iState, tStep); + smoother.giveNodalVector(recoveredVal, dman->giveNumber() ); + if ( size == recoveredVal->giveSize() ) { + answer.at(j) = recoveredVal->at(j); + } else { + OOFEM_WARNING("Recovered variable size mismatch for %d for id %d", type, id); + answer.at(j) = 0.0; + } + } else if (type == ResidualForce) { + answer.at(j) = dman->giveDofWithID(id)->giveUnknown(VM_Residual, tStep); + } else if ( dman->hasDofID(id) ) { + // primary variable available directly in DOF-manager + answer.at(j) = dman->giveDofWithID(id)->giveUnknown(VM_Total, tStep); + //mj - if incremental value needed: answer.at(j) = dman->giveDofWithID(id)->giveUnknown(VM_Incremental, tStep); + } else if ( iState != IST_Undefined ) { + // primary variable not directly available + // but equivalent InternalStateType provided + // in this case use smoother to recover nodal value + + // This can't deal with ValueModeType, and would recover over and over for some vectorial quantities like velocity + // recover values if not done before. + smoother.recoverValues(region, iState, tStep); + smoother.giveNodalVector(recoveredVal, dman->giveNumber() ); + // here we have a lack of information about how to convert recovered values to response + // if the size is compatible we accept it, otherwise give a warning and zero value. + if ( size == recoveredVal->giveSize() ) { + answer.at(j) = recoveredVal->at(j); + } else { + OOFEM_WARNING("Recovered variable size mismatch for \"%s\" for dof id %d. Size is %d, should be %d", __UnknownTypeToString(type), id, recoveredVal->giveSize(), size); + answer.at(j) = 0.0; + } + } + } + + + + InternalStateValueType valType = giveInternalStateValueType(type); + //rotate back from nodal CS to global CS if applies + if ( valType == ISVT_VECTOR ) { ///@todo in general, shouldn't this apply for 2nd order tensors as well? /JB + Node *node = dynamic_cast< Node * >( dman ); + if ( node && node->hasLocalCS() ) { + answer.rotatedWith(* node->giveLocalCoordinateTriplet(), 't'); + } + } +} + + +//---------------------------------------------------- +// Internal variables and XFEM realted fields (keyword "vars" in OOFEM input file) +//---------------------------------------------------- +void +VTKBaseExportModule::exportIntVars(VTKPiece &vtkPiece, Set& region, IntArray& internalVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep) +{ + Domain *d = emodel->giveDomain(1); + InternalStateType isType; + FloatArray answer; + //IntArray& mapG2L = vtkPiece.getMapG2L(); + IntArray& mapL2G = vtkPiece.getMapL2G(); + + smoother.clear(); // Makes sure smoother is up-to-date with potentially new mesh. + + // Export of Internal State Type fields + vtkPiece.setNumberOfInternalVarsToExport(internalVarsToExport, mapL2G.giveSize() ); + for ( int field = 1; field <= internalVarsToExport.giveSize(); field++ ) { + isType = ( InternalStateType ) internalVarsToExport.at(field); + + for ( int nodeNum = 1; nodeNum <= mapL2G.giveSize(); nodeNum++ ) { + Node *node = d->giveNode(mapL2G.at(nodeNum) ); + this->getNodalVariableFromIS(answer, node, tStep, isType, region, smoother); + vtkPiece.setInternalVarInNode(isType, nodeNum, answer); + } + } + + /* + // Export of XFEM related quantities + if ( d->hasXfemManager() ) { + XfemManager *xFemMan = d->giveXfemManager(); + int nEnrIt = xFemMan->giveNumberOfEnrichmentItems(); + + vtkPiece.setNumberOfInternalXFEMVarsToExport(xFemMan->vtkExportFields.giveSize(), nEnrIt, mapL2G.giveSize() ); + for ( int field = 1; field <= xFemMan->vtkExportFields.giveSize(); field++ ) { + XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields [ field - 1 ]; + + for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) { + for ( int nodeIndx = 1; nodeIndx <= mapL2G.giveSize(); nodeIndx++ ) { + Node *node = d->giveNode(mapL2G.at(nodeIndx) ); + getNodalVariableFromXFEMST(answer, node, tStep, xfemstype, region, xFemMan->giveEnrichmentItem(enrItIndex) ); + vtkPiece.setInternalXFEMVarInNode(field, enrItIndex, nodeIndx, answer); + } + } + } + } + */ +} + + +void +VTKBaseExportModule::getNodalVariableFromIS(FloatArray &answer, Node *node, TimeStep *tStep, InternalStateType type, Set& region, NodalRecoveryModel& smoother) +{ + // Recovers nodal values from Internal States defined in the integration points. + // Should return an array with proper size supported by VTK (1, 3 or 9) + // Domain *d = emodel->giveDomain(1); + IntArray redIndx; + + if ( !( type == IST_DisplacementVector || type == IST_MaterialInterfaceVal ) ) { + smoother.recoverValues(region, type, tStep); + } + + + const FloatArray *val = NULL; + FloatArray valueArray; + InternalStateValueType valType = giveInternalStateValueType(type); + + if ( type == IST_DisplacementVector ) { ///@todo Why does this code exists here? DisplacementVector isn't a internal variable. And if its really desired, then why the special treatment for just displacements? + ///@todo Is this for elements which does not use displacements as primary variables but e.g. the placement x? Move to exportPrimaryVar? /JB + valueArray.resize(3); + val = & valueArray; + for ( int i = 1; i <= 3; i++ ) { + valueArray.at(i) = node->giveUpdatedCoordinate(i, tStep, 1.0) - node->giveCoordinate(i); + } + } else if ( type == IST_MaterialInterfaceVal ) { + MaterialInterface *mi = emodel->giveMaterialInterface(1); + if ( mi ) { + valueArray.resize(1); + val = & valueArray; + valueArray.at(1) = mi->giveNodalScalarRepresentation(node->giveNumber() ); + } + } else { + int found = smoother.giveNodalVector(val, node->giveNumber() ); + if ( !found ) { + valueArray.resize(redIndx.giveSize() ); + val = & valueArray; + } + } + + int ncomponents = giveInternalStateTypeSize(valType); + answer.resize(ncomponents); + int valSize = val->giveSize(); // size of recovered quantity + + // check if valSize corresponds to the expected size otherwise pad with zeros + if ( valType == ISVT_SCALAR ) { + answer.at(1) = valSize ? val->at(1) : 0.0; + } else if ( valType == ISVT_VECTOR ) { + answer = * val; + // bp: hack for BeamForceMomentTensor, which should be splitted into force and momentum vectors + if ( type == IST_BeamForceMomentTensor ) { + answer.resizeWithValues(6); + } else { + answer.resizeWithValues(3); + } + } else if ( valType == ISVT_TENSOR_S3 || valType == ISVT_TENSOR_S3E || valType == ISVT_TENSOR_G ) { + this->makeFullTensorForm(answer, * val, valType); + } else { + OOFEM_ERROR("ISVT_UNDEFINED encountered") + } +} + + + +//---------------------------------------------------- +// Cell vars +//---------------------------------------------------- + +void +VTKBaseExportModule::exportCellVars(VTKPiece &vtkPiece, Set& region, IntArray& cellVarsToExport, TimeStep *tStep) +{ + Domain *d = emodel->giveDomain(1); + FloatArray valueArray; + const IntArray &elems = region.giveElementList(); + + vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport, elems.giveSize() ); + for ( int field = 1; field <= cellVarsToExport.giveSize(); field++ ) { + InternalStateType type = ( InternalStateType ) cellVarsToExport.at(field); + + for ( int subIndex = 1; subIndex <= elems.giveSize(); ++subIndex ) { + Element *el = d->giveElement(elems.at(subIndex) ); ///@todo should be a pointer to an element in the region /JB + if ( el->giveParallelMode() != Element_local ) { + continue; + } + + this->getCellVariableFromIS(valueArray, el, type, tStep); + vtkPiece.setCellVar(type, subIndex, valueArray); + } + } +} + + +void +VTKBaseExportModule::getCellVariableFromIS(FloatArray &answer, Element *el, InternalStateType type, TimeStep *tStep) +{ + InternalStateValueType valType = giveInternalStateValueType(type); + int ncomponents = giveInternalStateTypeSize(valType); + + answer.resize(ncomponents); + + switch ( type ) { + // Special scalars + case IST_MaterialNumber: + // commented by bp: do what user wants + //OOFEM_WARNING1("Material numbers are deprecated, outputing cross section number instead..."); + answer.at(1) = ( double ) el->giveMaterial()->giveNumber(); + break; + case IST_CrossSectionNumber: + answer.at(1) = ( double ) el->giveCrossSection()->giveNumber(); + break; + case IST_ElementNumber: + answer.at(1) = ( double ) el->giveNumber(); + break; + case IST_Pressure: ///@todo This case seems redundant, remove? /JB, /// Why this special treatment for pressure? / Mikael + if ( el->giveNumberOfInternalDofManagers() == 1 ) { + //IntArray pmask(1); pmask.at(1) = P_f; + //el->giveInternalDofManager(1)->giveUnknownVector (answer, pmask, VM_Total, tStep); + //answer.at(1) = answer.at(1); + } + + break; + case IST_AbaqusStateVector: + { + // compute cell average from ip values + IntegrationRule *iRule = el->giveDefaultIntegrationRulePtr(); + computeIPAverage(answer, iRule, el, type, tStep); // if element has more than one iRule?? /JB + } + break; + + // Special vectors + case IST_MaterialOrientation_x: + case IST_MaterialOrientation_y: + case IST_MaterialOrientation_z: + { + FloatMatrix rotMat; + int col = 0; + if ( type == IST_MaterialOrientation_x ) { + col = 1; + } else if ( type == IST_MaterialOrientation_y ) { + col = 2; + } else if ( type == IST_MaterialOrientation_z ) { + col = 3; + } + + if ( !el->giveLocalCoordinateSystem(rotMat) ) { + rotMat.resize(3, 3); + rotMat.beUnitMatrix(); + } + + answer.beColumnOf(rotMat, col); + break; + } + + // Export cell data as average from ip's as default + default: + + // compute cell average from ip values + IntegrationRule *iRule = el->giveDefaultIntegrationRulePtr(); + computeIPAverage(answer, iRule, el, type, tStep); // if element has more than one iRule?? /JB + // Reshape the Voigt vectors to include all components (duplicated if necessary, VTK insists on 9 components for tensors.) + /// @todo Is this part necessary now when giveIPValue returns full form? Only need to symmetrize in case of 6 components /JB + /// @todo Some material models aren't exporting values correctly (yet) / Mikael + if ( valType == ISVT_TENSOR_S3 || valType == ISVT_TENSOR_S3E || valType == ISVT_TENSOR_G ) { + FloatArray temp = answer; + this->makeFullTensorForm(answer, temp, valType); + } else if ( valType == ISVT_VECTOR && answer.giveSize() < 3 ) { + answer.resizeWithValues(3); + } else if ( ncomponents != answer.giveSize() ) { // Trying to gracefully handle bad cases, just output zeros. + answer.resizeWithValues(ncomponents); + } + } +} + + +int +VTKBaseExportModule::initRegionNodeNumbering(VTKPiece& piece, + Domain *domain, TimeStep *tStep, Set& region) +{ + // regionG2LNodalNumbers is array with mapping from global numbering to local region numbering. + // The i-th value contains the corresponding local region number (or zero, if global number is not in region). + + // regionL2GNodalNumbers is array with mapping from local to global numbering. + // The i-th value contains the corresponding global node number. + + + int nnodes = domain->giveNumberOfDofManagers(); + int elemNodes; + int elementNode, node; + int currOffset = 1; + Element *element; + + IntArray ®ionG2LNodalNumbers = piece.getMapG2L(); + IntArray ®ionL2GNodalNumbers = piece.getMapL2G(); + + regionG2LNodalNumbers.resize(nnodes); + regionG2LNodalNumbers.zero(); + int regionDofMans = 0; + int regionSingleCells = 0; + + const IntArray& elements = region.giveElementList(); + for ( int ie = 1; ie <= elements.giveSize(); ie++ ) { + int ielem = elements.at(ie); + element = domain->giveElement(ielem); + + if ( this->isElementComposite(element) ) { + continue; // composite cells exported individually + } + + if ( !element->isActivated(tStep) ) { //skip inactivated elements + continue; + } + + //skip materials with casting time > current time + if ( !element->isCast(tStep) ) { + continue; + } + + if ( element->giveParallelMode() != Element_local ) { + continue; + } + + regionSingleCells++; + elemNodes = element->giveNumberOfNodes(); + // elemSides = element->giveNumberOfSides(); + + // determine local region node numbering + for ( elementNode = 1; elementNode <= elemNodes; elementNode++ ) { + node = element->giveNode(elementNode)->giveNumber(); + if ( regionG2LNodalNumbers.at(node) == 0 ) { // assign new number + /* mark for assignment. This is done later, as it allows to preserve + * natural node numbering. + */ + regionG2LNodalNumbers.at(node) = 1; + regionDofMans++; + } + } + } + + regionL2GNodalNumbers.resize(regionDofMans); + + for ( int i = 1; i <= nnodes; i++ ) { + if ( regionG2LNodalNumbers.at(i) ) { + regionG2LNodalNumbers.at(i) = currOffset++; + regionL2GNodalNumbers.at(regionG2LNodalNumbers.at(i) ) = i; + } + } + + piece.setNumberOfCells(regionSingleCells); + piece.setNumberOfNodes(regionDofMans); + + return 1; +} + +void +VTKBaseExportModule::computeIPAverage(FloatArray &answer, IntegrationRule *iRule, Element *elem, InternalStateType isType, TimeStep *tStep) +{ + // Computes the volume average (over an element) for the quantity defined by isType + double gptot = 0.0; + answer.clear(); + FloatArray temp; + if ( iRule ) { + for ( IntegrationPoint *ip : * iRule ) { + elem->giveIPValue(temp, ip, isType, tStep); + gptot += ip->giveWeight(); + answer.add(ip->giveWeight(), temp); + } + + answer.times(1. / gptot); + } +} + +//---------------------------------------------------- +// Load vectors +//---------------------------------------------------- +void +VTKBaseExportModule::exportExternalForces(VTKPiece &vtkPiece, Set& region, IntArray& externalForcesToExport, TimeStep *tStep) +{ + Domain *d = emodel->giveDomain(1); + //this->givePrimVarSmoother()->clear(); // Makes sure primary smoother is up-to-date with potentially new mesh. + //IntArray& mapG2L = vtkPiece.getMapG2L(); + IntArray& mapL2G = vtkPiece.getMapL2G(); + + if ( externalForcesToExport.giveSize() == 0 ) { + return; + } + + ///@todo Add a more flexible solution here, ask the Engineering model for the equivalent to this (perhaps as part of the primary field?) + /// This should be looked into, just as "getNodalVariableFromPrimaryField" is particularly complicated. + int neq = emodel->giveNumberOfDomainEquations(1, EModelDefaultEquationNumbering() ); + int npeq = emodel->giveNumberOfDomainEquations(1, EModelDefaultPrescribedEquationNumbering() ); + FloatArray extForces(neq), extForcesP(npeq); + emodel->assembleVector(extForces, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), d); + emodel->assembleVector(extForcesP, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultPrescribedEquationNumbering(), d); + + vtkPiece.setNumberOfLoadsToExport(externalForcesToExport.giveSize(), mapL2G.giveSize() ); + for ( int i = 1; i <= externalForcesToExport.giveSize(); i++ ) { + UnknownType type = ( UnknownType ) externalForcesToExport.at(i); + ///@todo Have some mapping for UnknownType -> DofID array + IntArray dofids; + if ( type == VelocityVector ) { + dofids = { + V_u, V_v, V_w + }; + } else if ( type == DisplacementVector ) { + dofids = { + D_u, D_v, D_w + }; + } else if ( type == PressureVector ) { + dofids = { + P_f + }; + } else { + OOFEM_WARNING("Unrecognized UnknownType (%d), no external forces exported", type); + } + + for ( int inode = 1; inode <= mapL2G.giveSize(); inode++ ) { + DofManager *dman = d->giveNode(mapL2G.at(inode) ); + + FloatArray valueArray(dofids.giveSize() ); + for ( int k = 1; k <= dofids.giveSize(); ++k ) { + Dof *dof = dman->giveDofWithID(dofids.at(k) ); + ///@todo Have to make more assumptions here.. we shouldn't assume EModelDefaultEquationNumbering. Do something nicer than extForces and extForcesP instead. + int eq; + if ( ( eq = dof->giveEquationNumber(EModelDefaultEquationNumbering() ) ) > 0 ) { + valueArray.at(k) = extForces.at(eq); + } else if ( ( eq = dof->giveEquationNumber(EModelDefaultPrescribedEquationNumbering() ) ) > 0 ) { + valueArray.at(k) = extForcesP.at(eq); + } + } + //this->getNodalVariableFromPrimaryField(valueArray, dman, tStep, type, region); + vtkPiece.setLoadInNode(i, inode, std::move(valueArray) ); + } + } +} + +// End of VTKBaseExportModule implementation + + + +} // end namespace oofem diff --git a/src/oofemlib/vtkbaseexportmodule.h b/src/oofemlib/vtkbaseexportmodule.h new file mode 100644 index 000000000..202d9a170 --- /dev/null +++ b/src/oofemlib/vtkbaseexportmodule.h @@ -0,0 +1,257 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef vtkbaseexportmodule_h +#define vtkbaseexportmodule_h + +#include "exportmodule.h" +#include "intarray.h" +#include "internalstatevaluetype.h" +#include "internalstatetype.h" +#include "unknowntype.h" +#include "integrationrule.h" +#include "element.h" +#include "nodalrecoverymodel.h" +#include +#include +#include + +#ifdef _PYBIND_BINDINGS + #include + #include //Conversion for lists + #include "pybind11/numpy.h" +namespace py = pybind11; +#endif + +#ifdef _WIN32 + #define NULL_DEVICE "NUL:" +#else + #define NULL_DEVICE "/dev/null" +#endif + + +#include +#include + +using namespace std; +namespace oofem { + +class VTKBaseExportModule; + +///@todo Rename this to something like "ExportPiece" and move it to a separate file (it doesn't actually contain anything VTK-specific). +/// Stores all neccessary data (of a region) in a VTKPiece so it can be exported later. +class OOFEM_EXPORT VTKPiece +{ +public: + VTKPiece() + { + numCells = 0; + numNodes = 0; + } + + void clear(); + + void setNumberOfNodes(int numNodes); + int giveNumberOfNodes() { return this->numNodes; } + + void setNumberOfCells(int numCells); + int giveNumberOfCells() { return this->numCells; } + + void setConnectivity(int cellNum, IntArray &nodes); + IntArray &giveCellConnectivity(int cellNum) { return this->connectivity [ cellNum - 1 ]; } + + void setCellType(int cellNum, int type) { this->elCellTypes.at(cellNum) = type; } + int giveCellType(int cellNum) { return this->elCellTypes.at(cellNum); } + + void setOffset(int cellNum, int offset) { this->elOffsets.at(cellNum) = offset; } + int giveCellOffset(int cellNum) { return this->elOffsets.at(cellNum); } + + void setNodeCoords(int nodeNum, const FloatArray &coords); + FloatArray &giveNodeCoords(int nodeNum) { return this->nodeCoords [ nodeNum - 1 ]; } + + void setNumberOfPrimaryVarsToExport(const IntArray& primVars, int numNodes); + void setNumberOfLoadsToExport(int numVars, int numNodes); + void setNumberOfInternalVarsToExport(const IntArray& ists, int numNodes); + void setNumberOfInternalXFEMVarsToExport(int numVars, int numEnrichmentItems, int numNodes); + void setNumberOfCellVarsToExport(const IntArray& cellVars, int numCells); + + void setPrimaryVarInNode(UnknownType type, int nodeNum, FloatArray valueArray); + FloatArray &givePrimaryVarInNode(UnknownType type, int nodeNum) { return this->nodeVars [ type ] [ nodeNum - 1 ]; } + + void setLoadInNode(int varNum, int nodeNum, FloatArray valueArray); + FloatArray &giveLoadInNode(int varNum, int nodeNum) { return this->nodeLoads [ varNum - 1 ] [ nodeNum - 1 ]; } + + void setInternalVarInNode(InternalStateType type, int nodeNum, FloatArray valueArray); + FloatArray &giveInternalVarInNode (InternalStateType type, int nodeNum) { return this->nodeVarsFromIS [ type ] [ nodeNum - 1 ]; } + + void setInternalXFEMVarInNode(int varNum, int eiNum, int nodeNum, FloatArray valueArray); + FloatArray &giveInternalXFEMVarInNode(int varNum, int eiNum, int nodeNum) { return this->nodeVarsFromXFEMIS [ varNum - 1 ] [ eiNum - 1 ] [ nodeNum - 1 ]; } + + void setCellVar(InternalStateType type, int cellNum, FloatArray valueArray); + FloatArray &giveCellVar(InternalStateType type, int cellNum) { return this->cellVars [ type ] [ cellNum - 1 ]; } + + IntArray& getMapG2L () {return this->mapG2L;} + IntArray& getMapL2G () {return this->mapL2G;} + //void setRegionCells(IntArray& cells) {this->regionElInd = cells;} + IntArray& getRegionCells () {return this->regionElInd;} + +#ifdef _PYBIND_BINDINGS + py::array_t getVertices () ; + py::array_t getCellConnectivity (); + py::array_t getCellTypes (VTKBaseExportModule& m); + py::array_t getPrimaryVertexValues (UnknownType u); + py::array_t getInternalVertexValues(InternalStateType u); + py::array_t getCellValues(InternalStateType u); + +#endif + +private: + int numCells; + int numNodes; + IntArray elCellTypes; + IntArray elOffsets; + // dofman local->global and global->local region map + IntArray mapG2L, mapL2G; + // region elements + IntArray regionElInd; + + + std::vector< FloatArray >nodeCoords; // all the nodes in the piece [node][coords] + std::vector< IntArray >connectivity; // cell connectivity [cell][nodes] + std::map< UnknownType, std::vector< FloatArray > >nodeVars; // [field][node][valArray] + std::vector< std::vector< FloatArray > >nodeLoads; // [field][node][valArray] + std::map< InternalStateType, std::vector< FloatArray > >nodeVarsFromIS; // [field][node][valArray] + std::vector< std::vector< std::vector< FloatArray > > >nodeVarsFromXFEMIS; // [field][ei][node][valArray] + std::map< InternalStateType, std::vector< FloatArray > >cellVars; // [el][field][valArray] +}; + +/** + * Base class for VTK related export modules. Defines commmon methods. + */ +class OOFEM_EXPORT VTKBaseExportModule : public ExportModule +{ +protected: + /// Map from Voigt to full tensor. + static IntArray redToFull; + +public: + /// Constructor. Creates empty Output Manager. By default all components are selected. + VTKBaseExportModule(int n, EngngModel *e); + /// Destructor + virtual ~VTKBaseExportModule(); + + void initialize() override; + void terminate() override; + const char *giveClassName() const override { return "VTKBaseExportModule"; } + /** + * Computes a cell average of an InternalStateType varible based on the weights + * in the integrationpoints (=> volume/area/length average) + */ + static void computeIPAverage(FloatArray &answer, IntegrationRule *iRule, Element *elem, InternalStateType isType, TimeStep *tStep); + /** + * Returns corresponding element cell_type. + * Some common element types are supported, others can be supported via interface concept. + */ + int giveCellType(Element *element); + int giveCellType(int num) ; + +protected: + + virtual void setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, Set& region); + + /** + * Export primary variables. + */ + virtual void exportPrimaryVars(VTKPiece &piece, Set& region, IntArray& primaryVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep); + /** + * Export internal variables by smoothing. + */ + virtual void exportIntVars(VTKPiece &piece, Set& region, IntArray& internalVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep); + /** + * Export external forces. + */ + void exportExternalForces(VTKPiece &piece, int region, TimeStep *tStep); + + //void exportXFEMVarAs(XFEMStateType xfemstype, int regionDofMans, int ireg, TimeStep *tStep, EnrichmentItem *ei); + /// Exports cell variables (typically internal variables). + void exportCellVars(VTKPiece &piece, Set& region, IntArray &cellVarsToExport, TimeStep *tStep); + /** + * Export external forces. + */ + void exportExternalForces(VTKPiece &piece, Set& region, IntArray& externalForcesToExport, TimeStep *tStep); + + + // Tries to find the value of a primary field on the given DofManager. + // Some elements have different interpolation of some fields, and requires some additional code to compute node values (if available). + void getNodalVariableFromPrimaryField(FloatArray &answer, DofManager *dman, TimeStep *tStep, UnknownType type, Set& region, NodalRecoveryModel& smoother); + // + // Exports single internal variable by smoothing. + // + void getNodalVariableFromIS(FloatArray &answer, Node *node, TimeStep *tStep, InternalStateType type, Set& region, NodalRecoveryModel& smoother); + // void getNodalVariableFromXFEMST(FloatArray &answer, Node *node, TimeStep *tStep, XFEMStateType xfemstype,Set& region, EnrichmentItem *ei); + // + // Exports a single cell variable (typically an internal variable). + // + void getCellVariableFromIS(FloatArray &answer, Element *el, InternalStateType type, TimeStep *tStep); + + + /// Gives the full form of given symmetrically stored tensors, missing components are filled with zeros. + static void makeFullTensorForm(FloatArray &answer, const FloatArray &reducedForm, InternalStateValueType vtype); + /** + * Returns number of nodes corresponding to cell type + */ + int giveNumberOfNodesPerCell(int cellType); + /** + * Returns the element cell geometry. + */ + void giveElementCell(IntArray &answer, Element *elem); + /** + * Assembles the region node map. Also computes the total number of nodes in region. + * The region are numbered starting from offset+1. + * If mode == 0 then regionNodalNumbers is array with mapping from global numbering to local region numbering. + * The i-th value contains the corresponding local region number (or zero, if global number is not in region). + * If mode == 1 then regionNodalNumbers is array with mapping from local to global numbering. + * The i-th value contains the corresponding global node number. + */ + virtual int initRegionNodeNumbering(VTKPiece& vtkPiece, + Domain *domain, TimeStep *tStep, Set& region); + + // Export of composite elements (built up from several subcells) + bool isElementComposite(Element *elem); /// Returns true if element geometry type is composite (not a single cell). + void exportCompositeElement(VTKPiece &vtkPiece, Element *el, TimeStep *tStep); + void exportCompositeElement(std::vector< VTKPiece > &vtkPieces, Element *el, TimeStep *tStep); +}; + +} // end namespace oofem +#endif // vtkbaseexportmodule_h diff --git a/src/oofemlib/vtkexportmodule.C b/src/oofemlib/vtkexportmodule.C index c7ee49c40..730c7367e 100644 --- a/src/oofemlib/vtkexportmodule.C +++ b/src/oofemlib/vtkexportmodule.C @@ -66,24 +66,17 @@ namespace oofem { REGISTER_ExportModule(VTKExportModule) -VTKExportModule :: VTKExportModule(int n, EngngModel *e) : ExportModule(n, e), internalVarsToExport(), primaryVarsToExport() -{ - smoother = NULL; -} +VTKExportModule :: VTKExportModule(int n, EngngModel *e) : ExportModule(n, e), internalVarsToExport(), primaryVarsToExport() { } -VTKExportModule :: ~VTKExportModule() -{ - if ( this->smoother ) { - delete this->smoother; - } -} +VTKExportModule :: ~VTKExportModule() { } -IRResultType -VTKExportModule :: initializeFrom(InputRecord *ir) +void +VTKExportModule :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + ExportModule :: initializeFrom(ir); + int val; IR_GIVE_OPTIONAL_FIELD(ir, cellVarsToExport, _IFT_VTKExportModule_cellvars); @@ -93,8 +86,6 @@ VTKExportModule :: initializeFrom(InputRecord *ir) val = NodalRecoveryModel :: NRM_ZienkiewiczZhu; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_VTKExportModule_stype); stype = ( NodalRecoveryModel :: NodalRecoveryModelType ) val; - - return ExportModule :: initializeFrom(ir); } @@ -115,8 +106,7 @@ VTKExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) Domain *d = emodel->giveDomain(1); - FloatArray *coords; - int i, inode, nnodes = d->giveNumberOfDofManagers(); + int inode, nnodes = d->giveNumberOfDofManagers(); this->giveSmoother(); // make sure smoother is created // output points @@ -131,12 +121,12 @@ VTKExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) OOFEM_LOG_DEBUG("vktexportModule: %d %d\n", nnodes, regionDofMans); for ( inode = 1; inode <= regionDofMans; inode++ ) { - coords = d->giveNode( map.at(inode) )->giveCoordinates(); - for ( i = 1; i <= coords->giveSize(); i++ ) { - fprintf( stream, "%e ", coords->at(i) ); + const auto &coords = d->giveNode( map.at(inode) )->giveCoordinates(); + for ( double s : coords ) { + fprintf( stream, "%e ", s ); } - for ( i = coords->giveSize() + 1; i <= 3; i++ ) { + for ( int i = coords.giveSize() + 1; i <= 3; i++ ) { fprintf(stream, "%e ", 0.0); } @@ -176,7 +166,7 @@ VTKExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) nelemNodes = this->giveNumberOfNodesPerCell(vtkCellType); //elem->giveNumberOfNodes(); // It HAS to be the same size as giveNumberOfNodesPerCell, otherwise the file will be incorrect. this->giveElementCell(cellNodes, elem.get(), 0); fprintf(stream, "%d ", nelemNodes); - for ( i = 1; i <= nelemNodes; i++ ) { + for ( int i = 1; i <= nelemNodes; i++ ) { fprintf(stream, "%d ", regionNodalNumbers.at( cellNodes.at(i) ) - 1); } @@ -212,10 +202,7 @@ VTKExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) void VTKExportModule :: initialize() { - if ( this->smoother ) { - delete this->smoother; - this->smoother = NULL; - } + this->smoother.reset(); ExportModule :: initialize(); } @@ -553,7 +540,7 @@ VTKExportModule :: initRegionNodeNumbering(IntArray ®ionNodalNumbers, int &re int offset, Domain *domain, int reg, int mode) { // if mode == 0 then regionNodalNumbers is array with mapping from global numbering to local region numbering. - // The i-th value contains the corresponding local region number (or zero, if global numbar is not in region). + // The i-th value contains the corresponding local region number (or zero, if global number is not in region). // if mode == 1 then regionNodalNumbers is array with mapping from local to global numbering. // The i-th value contains the corresponding global node number. @@ -751,11 +738,11 @@ VTKExportModule :: giveSmoother() { Domain *d = emodel->giveDomain(1); - if ( this->smoother == NULL ) { + if ( !this->smoother ) { this->smoother = classFactory.createNodalRecoveryModel(this->stype, d); } - return this->smoother; + return this->smoother.get(); } diff --git a/src/oofemlib/vtkexportmodule.h b/src/oofemlib/vtkexportmodule.h index 7b09ba812..9bf82b2c0 100644 --- a/src/oofemlib/vtkexportmodule.h +++ b/src/oofemlib/vtkexportmodule.h @@ -83,7 +83,7 @@ class OOFEM_EXPORT VTKExportModule : public ExportModule /// Smoother type. NodalRecoveryModel :: NodalRecoveryModelType stype; /// Smoother. - NodalRecoveryModel *smoother; + std::unique_ptr smoother; /// List of regions to skip. IntArray regionsToSkip; @@ -93,13 +93,13 @@ class OOFEM_EXPORT VTKExportModule : public ExportModule /// Destructor virtual ~VTKExportModule(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void doOutput(TimeStep *tStep, bool forcedOutput = false); - virtual void initialize(); - virtual void terminate(); - virtual const char *giveClassName() const { return "VTKExportModule"; } - virtual const char *giveInputRecordName() const { return _IFT_VTKExportModule_Name; } + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; + void initialize() override; + void terminate() override; + const char *giveClassName() const override { return "VTKExportModule"; } + const char *giveInputRecordName() const { return _IFT_VTKExportModule_Name; } protected: /// Returns the internal smoother. diff --git a/src/oofemlib/vtkmemoryexportmodule.C b/src/oofemlib/vtkmemoryexportmodule.C new file mode 100644 index 000000000..6ab60da49 --- /dev/null +++ b/src/oofemlib/vtkmemoryexportmodule.C @@ -0,0 +1,97 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "vtkmemoryexportmodule.h" +#include "element.h" +#include "timestep.h" +#include "engngm.h" +#include "node.h" +#include "nodalaveragingrecoverymodel.h" +#include "zznodalrecoverymodel.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_ExportModule(VTKMemoryExportModule) + +VTKMemoryExportModule::VTKMemoryExportModule(int n, EngngModel *e) : VTKBaseExportModule(n,e) {} +VTKMemoryExportModule::~VTKMemoryExportModule() {} + +void +VTKMemoryExportModule::initializeFrom(InputRecord &ir) +{ + VTKBaseExportModule::initializeFrom(ir); + + IR_GIVE_OPTIONAL_FIELD(ir, cellVarsToExport, _IFT_VTKXMLExportModule_cellvars); // Macro - see internalstatetype.h + IR_GIVE_OPTIONAL_FIELD(ir, internalVarsToExport, _IFT_VTKXMLExportModule_vars); // Macro - see internalstatetype.h + IR_GIVE_OPTIONAL_FIELD(ir, primaryVarsToExport, _IFT_VTKXMLExportModule_primvars); // Macro - see unknowntype.h + IR_GIVE_OPTIONAL_FIELD(ir, externalForcesToExport, _IFT_VTKXMLExportModule_externalForces); // Macro - see unknowntype.h + IR_GIVE_OPTIONAL_FIELD(ir, ipInternalVarsToExport, _IFT_VTKXMLExportModule_ipvars); // Macro - see internalstatetype.h +} + +void +VTKMemoryExportModule::doOutput(TimeStep *tStep, bool forcedOutput) +{ + if ( !( testTimeStepOutput(tStep) || forcedOutput ) ) { + return; + } + + int nPiecesToExport = this->giveNumberOfRegions(); //old name: region, meaning: sets + ZZNodalRecoveryModel smoother(emodel->giveDomain(1)); + NodalAveragingRecoveryModel primVarSmoother(emodel->giveDomain(1)); + + this->vtkPieces.resize(nPiecesToExport); + + // loop over regular pieces only (no support for composite elements at present) + for ( int pieceNum = 1; pieceNum <= nPiecesToExport; pieceNum++ ) { + VTKPiece& p = this->vtkPieces[pieceNum-1]; + p.clear(); + // Fills a data struct (VTKPiece) with all the necessary data. + Set* region = this->giveRegionSet(pieceNum); + this->setupVTKPiece(p, tStep, *region); + // Export primary, internal and XFEM variables as nodal quantities + this->exportPrimaryVars(p, *region, primaryVarsToExport, primVarSmoother, tStep); + this->exportIntVars(p, *region, internalVarsToExport, smoother, tStep); + this->exportExternalForces(p, *region, externalForcesToExport, tStep); + this->exportCellVars(p, *region, cellVarsToExport, tStep); + + } +} + +std::vector< VTKPiece>& +VTKMemoryExportModule::getVTKPieces() { + return this->vtkPieces; +} + + +} // end namespace oofem diff --git a/src/oofemlib/vtkmemoryexportmodule.h b/src/oofemlib/vtkmemoryexportmodule.h new file mode 100644 index 000000000..20bf6bda1 --- /dev/null +++ b/src/oofemlib/vtkmemoryexportmodule.h @@ -0,0 +1,104 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef vtkmemoryexportmodule_h +#define vtkmemoryexportmodule_h + +#include "vtkbaseexportmodule.h" +#include "intarray.h" +#include "nodalrecoverymodel.h" +#include "internalstatevaluetype.h" +#include +#include +#include + +#ifdef _PYBIND_BINDINGS + #include + #include //Conversion for lists + #include "pybind11/numpy.h" +namespace py = pybind11; +#endif + +#ifdef _WIN32 + #define NULL_DEVICE "NUL:" +#else + #define NULL_DEVICE "/dev/null" +#endif + +///@name Input fields for VTK XML export module +//@{ +#define _IFT_VTKXMLExportModule_cellvars "cellvars" +#define _IFT_VTKXMLExportModule_vars "vars" +#define _IFT_VTKXMLExportModule_primvars "primvars" +#define _IFT_VTKXMLExportModule_externalForces "externalforces" +#define _IFT_VTKXMLExportModule_ipvars "ipvars" +#define _IFT_VTKMemoryExportModule_Name "vtkmemory" +//@} + +using namespace std; +namespace oofem { + + +/** + * VTK-like export class intended mainly to provide easy to use Pythonic interface by providing + * acccess to VTKPieces. + */ +class OOFEM_EXPORT VTKMemoryExportModule : public VTKBaseExportModule +{ +protected: + /// List of InternalStateType values, identifying the selected vars for export. + IntArray internalVarsToExport; + /// List of primary unknowns to export. + IntArray primaryVarsToExport; + /// List of primary unknowns to export. + IntArray externalForcesToExport; + /// List of cell data to export. + IntArray cellVarsToExport; + /// List of internal variables to export directly in Integration Points (no smoothing to nodes) + IntArray ipInternalVarsToExport; + + + std::vector< VTKPiece > vtkPieces; +public: + /// Constructor. Creates empty Output Manager. By default all components are selected. + VTKMemoryExportModule(int n, EngngModel *e); + /// Destructor + virtual ~VTKMemoryExportModule(); + void initializeFrom(InputRecord &ir) override; + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; + std::vector< VTKPiece>& getVTKPieces(); +}; + +} // end namespace oofem +#endif // vtkmemoryexportmodule_h diff --git a/src/oofemlib/vtkpfemexportmodule.C b/src/oofemlib/vtkpfemexportmodule.C new file mode 100644 index 000000000..1780c8613 --- /dev/null +++ b/src/oofemlib/vtkpfemexportmodule.C @@ -0,0 +1,199 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "vtkpfemexportmodule.h" +#include "element.h" +#include "gausspoint.h" +#include "timestep.h" +#include "engngm.h" +#include "node.h" +#include "dof.h" +#include "materialinterface.h" +#include "mathfem.h" +#include "cltypes.h" +#include "material.h" +#include "classfactory.h" +#include "crosssection.h" +#include "unknownnumberingscheme.h" + +#ifdef __PFEM_MODULE + #include "pfem/pfemparticle.h" +#endif + +#include +#include +#include + +namespace oofem { +REGISTER_ExportModule(VTKPFEMXMLExportModule) + + +// Begin VTKPFEMXMLExportModule + +VTKPFEMXMLExportModule::VTKPFEMXMLExportModule(int n, EngngModel *e) : VTKBaseExportModule(n, e) {} + +VTKPFEMXMLExportModule::~VTKPFEMXMLExportModule() { } + +void +VTKPFEMXMLExportModule::initializeFrom(InputRecord &ir) +{ + ExportModule::initializeFrom(ir); +} + +std::string +VTKPFEMXMLExportModule::giveOutputFileName(TimeStep *tStep) +{ + return this->giveOutputBaseFileName(tStep) + ".vtu"; +} + + +std::ofstream +VTKPFEMXMLExportModule::giveOutputStream(TimeStep *tStep) +{ + std::string fileName = giveOutputFileName(tStep); + std::ofstream streamF; + + if ( pythonExport ) { + streamF = std::ofstream(NULL_DEVICE);//do not write anything + } else { + streamF = std::ofstream(fileName); + } + + if ( !streamF.good() ) { + OOFEM_ERROR("failed to open file %s", fileName.c_str() ); + } + + streamF.fill('0');//zero padding + return streamF; +} + + +void +VTKPFEMXMLExportModule::doOutput(TimeStep *tStep, bool forcedOutput) +{ + if ( !( testTimeStepOutput(tStep) || forcedOutput ) ) { + return; + } + + this->fileStream = this->giveOutputStream(tStep); + struct tm *current; + time_t now; + time(& now); + current = localtime(& now); + + // Write output: VTK header + this->fileStream << "\n"; + this->fileStream << "\n"; + this->fileStream << "\n"; + +#ifdef __PFEM_MODULE + // write out the particles (nodes exported as vertices = VTK_VERTEX) + Domain *d = emodel->giveDomain(1); + int nnode = d->giveNumberOfDofManagers(); + + int nActiveNode = 0; + for ( int inode = 1; inode <= nnode; inode++ ) { + PFEMParticle *particle = dynamic_cast< PFEMParticle * >( d->giveNode(inode) ); + if ( particle ) { + if ( particle->isActive() ) { + nActiveNode++; + } + } + } + + DofManager *node; + FloatArray *coords; + this->fileStream << "\n"; + this->fileStream << "\n "; + + for ( int inode = 1; inode <= nnode; inode++ ) { + node = d->giveNode(inode); + PFEMParticle *particle = dynamic_cast< PFEMParticle * >( node ); + if ( particle ) { + if ( particle->isActive() ) { + coords = node->giveCoordinates(); + ///@todo move this below into setNodeCoords since it should alwas be 3 components anyway + for ( int i = 1; i <= coords->giveSize(); i++ ) { + this->fileStream << scientific << coords->at(i) << " "; + } + + for ( int i = coords->giveSize() + 1; i <= 3; i++ ) { + this->fileStream << scientific << 0.0 << " "; + } + } + } + } + + this->fileStream << "\n\n"; + + + // output the cells connectivity data + this->fileStream << "\n"; + this->fileStream << " "; + + for ( int ielem = 1; ielem <= nActiveNode; ielem++ ) { + this->fileStream << ielem - 1 << " "; + } + + this->fileStream << "\n"; + + // output the offsets (index of individual element data in connectivity array) + this->fileStream << " "; + + for ( int ielem = 1; ielem <= nActiveNode; ielem++ ) { + this->fileStream << ielem << " "; + } + this->fileStream << "\n"; + + + // output cell (element) types + this->fileStream << " "; + for ( int ielem = 1; ielem <= nActiveNode; ielem++ ) { + this->fileStream << 1 << " "; + } + + this->fileStream << "\n"; + this->fileStream << "\n"; + this->fileStream << "\n"; +#endif //__PFEM_MODULE + + // Finalize the output: + this->fileStream << "\n"; + if(this->fileStream){ + this->fileStream.close(); + } + + } + +} // end namespace oofem diff --git a/src/oofemlib/vtkpfemexportmodule.h b/src/oofemlib/vtkpfemexportmodule.h new file mode 100644 index 000000000..fb0342dac --- /dev/null +++ b/src/oofemlib/vtkpfemexportmodule.h @@ -0,0 +1,90 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef vtkpfemexportmodule_h +#define vtkpfemexportmodule_h + +#include "vtkbaseexportmodule.h" +#include "intarray.h" +#include "nodalrecoverymodel.h" +#include "interface.h" +#include "internalstatevaluetype.h" +#include "integrationrule.h" +#include "xfem/xfemmanager.h" +#include +#include +#include + +#ifdef _WIN32 + #define NULL_DEVICE "NUL:" +#else + #define NULL_DEVICE "/dev/null" +#endif + + +#include +#include + +///@name Input fields for VTK XML export module + +using namespace std; +namespace oofem { +class Node; + +#define _IFT_VTKPFEMXMLExportModule_Name "vtkpfem" + +class OOFEM_EXPORT VTKPFEMXMLExportModule : public VTKBaseExportModule +{ +protected: + std::ofstream fileStream; +public: + /// Constructor. Creates empty Output Manager. By default all components are selected. + VTKPFEMXMLExportModule(int n, EngngModel *e); + /// Destructor + virtual ~VTKPFEMXMLExportModule(); + + void initializeFrom(InputRecord &ir) override; + + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; +protected: + /// Returns the filename for the given time step. + std::string giveOutputFileName(TimeStep *tStep); + + /// Returns the output stream for given solution step. + std::ofstream giveOutputStream(TimeStep *tStep); + +}; + +} // end namespace oofem +#endif // vtkxmlexportmodule_h diff --git a/src/oofemlib/vtkxfemexportmodule.C b/src/oofemlib/vtkxfemexportmodule.C new file mode 100644 index 000000000..f3b1bb212 --- /dev/null +++ b/src/oofemlib/vtkxfemexportmodule.C @@ -0,0 +1,418 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "vtkxfemexportmodule.h" +#include "element.h" +#include "gausspoint.h" +#include "timestep.h" +#include "engngm.h" +#include "node.h" +#include "dof.h" +#include "materialinterface.h" +#include "mathfem.h" +#include "cltypes.h" +#include "material.h" +#include "classfactory.h" +#include "crosssection.h" +#include "unknownnumberingscheme.h" + +#include "xfem/xfemmanager.h" +#include "xfem/enrichmentitem.h" + +#include +#include +#include + +#ifdef __VTK_MODULE + #include + #include + #include + #include + #include + #include + #include + #include + #include +#endif + +namespace oofem { +REGISTER_ExportModule(VTKXMLXFemExportModule) + + + +// +// VTKXMLXFemExport module +// + +VTKXMLXFemExportModule::VTKXMLXFemExportModule(int n, EngngModel *e) : VTKXMLExportModule(n, e) {} + +VTKXMLXFemExportModule::~VTKXMLXFemExportModule() { } + +void +VTKXMLXFemExportModule::initializeFrom(InputRecord &ir) +{ + ExportModule::initializeFrom(ir); +} + + +std::string +VTKXMLXFemExportModule::giveOutputFileName(TimeStep *tStep) +{ + return this->giveOutputBaseFileName(tStep) + ".vtu"; +} + + +std::ofstream +VTKXMLXFemExportModule::giveOutputStream(TimeStep *tStep) +{ + std::string fileName = giveOutputFileName(tStep); + std::ofstream streamF; + + if ( pythonExport ) { + streamF = std::ofstream(NULL_DEVICE);//do not write anything + } else { + streamF = std::ofstream(fileName); + } + + if ( !streamF.good() ) { + OOFEM_ERROR("failed to open file %s", fileName.c_str() ); + } + + streamF.fill('0');//zero padding + return streamF; +} + +void +VTKXMLXFemExportModule::exportIntVars(VTKPiece &vtkPiece, Set& region, int field, int enrItIndex, IntArray& internalVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep) +{ + Domain *d = emodel->giveDomain(1); + FloatArray answer; + //IntArray& mapG2L = vtkPiece.getMapG2L(); + IntArray& mapL2G = vtkPiece.getMapL2G(); + + // Export of XFEM related quantities + if ( d->hasXfemManager() ) { + XfemManager *xFemMan = d->giveXfemManager(); + vtkPiece.setNumberOfInternalVarsToExport(xFemMan->vtkExportFields, mapL2G.giveSize() ); + XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields [ field - 1 ]; + + for ( int nodeIndx = 1; nodeIndx <= mapL2G.giveSize(); nodeIndx++ ) { + Node *node = d->giveNode(mapL2G.at(nodeIndx) ); + getNodalVariableFromXFEMST(answer, node, tStep, xfemstype, region, xFemMan->giveEnrichmentItem(enrItIndex) ); + vtkPiece.setInternalXFEMVarInNode(field, enrItIndex, nodeIndx, answer); + } + } +} + +void +VTKXMLXFemExportModule::getNodalVariableFromXFEMST(FloatArray &answer, Node *node, TimeStep *tStep, XFEMStateType xfemstype, Set ®ion, EnrichmentItem *ei) +{ + // Recovers nodal values from XFEM state variables (e.g. levelset function) + // Should return an array with proper size supported by VTK (1, 3 or 9) + // This could be moved into EnrichmentItem such that VTKExport doesn't need to know anything about XFEM + + const FloatArray *val = NULL; + FloatArray valueArray; + + Domain *d = emodel->giveDomain(1); + XfemManager *xFemMan = d->giveXfemManager(); + InternalStateValueType valType = xFemMan->giveXFEMStateValueType(xfemstype); + + + // The xfem level set function is defined in the nodes and recovery of nodal values is trivial. + if ( xfemstype == XFEMST_LevelSetPhi ) { + valueArray.resize(1); + val = & valueArray; + ei->evalLevelSetNormalInNode(valueArray.at(1), node->giveNumber(), node->giveCoordinates() ); + } else if ( xfemstype == XFEMST_LevelSetGamma ) { + valueArray.resize(1); + val = & valueArray; + ei->evalLevelSetTangInNode(valueArray.at(1), node->giveNumber(), node->giveCoordinates() ); + } else if ( xfemstype == XFEMST_NodeEnrMarker ) { + valueArray.resize(1); + val = & valueArray; + ei->evalNodeEnrMarkerInNode(valueArray.at(1), node->giveNumber() ); + } else { + //OOFEM_WARNING("invalid data in node %d", inode); + } + + ///@todo duplicated code from getNodalVariableFromIS - uneccessary + int ncomponents = giveInternalStateTypeSize(valType); + answer.resize(ncomponents); + int valSize = val->giveSize(); // size of recovered quantity + + // check if valSize corresponds to the expected size otherwise pad with zeros + if ( valType == ISVT_SCALAR ) { + answer.at(1) = valSize ? val->at(1) : 0.0; + } else if ( valType == ISVT_VECTOR ) { + answer = * val; + answer.resizeWithValues(3); + } else if ( valType == ISVT_TENSOR_S3 || valType == ISVT_TENSOR_S3E || valType == ISVT_TENSOR_G ) { + this->makeFullTensorForm(answer, * val, valType); + } else { + OOFEM_ERROR("ISVT_UNDEFINED encountered") + } +} + + +bool +VTKXMLXFemExportModule::writeXFEMVars(VTKPiece &vtkPiece, int field, int enrItIndex) +{ + Domain *d = emodel->giveDomain(1); + XfemManager *xFemMan = d->giveXfemManager(); + FloatArray valueArray; + + if ( !vtkPiece.giveNumberOfCells() ) { + return false; + } + + XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields.at(field); + const char *namePart = __XFEMStateTypeToString(xfemstype); + InternalStateValueType valType = xFemMan->giveXFEMStateValueType(xfemstype); + int ncomponents = giveInternalStateTypeSize(valType); + ( void ) ncomponents; //silence the warning + + int numNodes = vtkPiece.giveNumberOfNodes(); + + // Header + char name [ 100 ]; // Must I define a fixed size? /JB + sprintf(name, "%s_%d ", namePart, xFemMan->giveEnrichmentItem(enrItIndex)->giveNumber() ); + +#ifdef __VTK_MODULE + vtkSmartPointer< vtkDoubleArray >varArray = vtkSmartPointer< vtkDoubleArray >::New(); + varArray->SetName(name); + varArray->SetNumberOfComponents(ncomponents); + varArray->SetNumberOfTuples(numNodes); + for ( int inode = 1; inode <= numNodes; inode++ ) { + valueArray = vtkPiece.giveInternalXFEMVarInNode(field, enrItIndex, inode); + for ( int i = 1; i <= ncomponents; ++i ) { + varArray->SetComponent(inode - 1, i - 1, valueArray.at(i) ); + } + } + + this->writeVTKPointData(name, varArray); +#else + this->fileStream << " "; + for ( int inode = 1; inode <= numNodes; inode++ ) { + valueArray = vtkPiece.giveInternalXFEMVarInNode(field, enrItIndex, inode); + this->writeVTKPointData(valueArray); + } + this->fileStream << "\n"; +#endif + return true; +} + +void +VTKXMLXFemExportModule::giveDataHeaders(std::string &pointHeader, std::string &cellHeader) +{ + std::string scalars, vectors, tensors; + + Domain *d = emodel->giveDomain(1); + XfemManager *xFemMan = d->giveXfemManager(); + int nEnrIt = xFemMan->giveNumberOfEnrichmentItems(); + for ( int field = 1; field <= xFemMan->vtkExportFields.giveSize(); field++ ) { + for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) { + XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields.at(field); + const char *namePart = __XFEMStateTypeToString(xfemstype); + + // Header + char name [ 100 ]; // Must I define a fixed size? /JB + sprintf(name, "%s_%d ", namePart, xFemMan->giveEnrichmentItem(enrItIndex)->giveNumber() ); + scalars += name; + scalars.append(" "); + } + } + // print header + pointHeader = "\n"; + +} + + +void +VTKXMLXFemExportModule::doOutput(TimeStep *tStep, bool forcedOutput) +{ + if ( !( testTimeStepOutput(tStep) || forcedOutput ) ) { + return; + } + + Domain *d = emodel->giveDomain(1); + //XfemManager *xFemMan = d->giveXfemManager(); +#ifdef __VTK_MODULE + this->fileStream = vtkSmartPointer< vtkUnstructuredGrid >::New(); + this->nodes = vtkSmartPointer< vtkPoints >::New(); + this->elemNodeArray = vtkSmartPointer< vtkIdList >::New(); + +#else + this->fileStream = this->giveOutputStream(tStep); + struct tm *current; + time_t now; + time(& now); + current = localtime(& now); + +#endif + // Write output: VTK header +#ifndef __VTK_MODULE + this->fileStream << "\n"; + this->fileStream << "\n"; + this->fileStream << "\n"; +#endif + + /* Loop over pieces ///@todo: this feature has been broken but not checked if it currently works /JB + * Start default pieces containing all single cell elements. Elements built up from several vtk + * cells (composite elements) are exported as individual pieces after the default ones. + */ + int nPiecesToExport = this->giveNumberOfRegions(); //old name: region, meaning: sets + int anyPieceNonEmpty = 0; + + // Export of XFEM related quantities + + if ( d->hasXfemManager() ) { + XfemManager *xFemMan = d->giveXfemManager(); + int nEnrIt = xFemMan->giveNumberOfEnrichmentItems(); + + for ( int pieceNum = 1; pieceNum <= nPiecesToExport; pieceNum++ ) { + // Fills a data struct (VTKPiece) with all the necessary data. + Set* region = this->giveRegionSet(pieceNum); + this->setupVTKPiece(this->defaultVTKPiece, tStep, *region); + if (this->defaultVTKPiece.giveNumberOfNodes() > 0) { + this->writeVTKPieceProlog(this->defaultVTKPiece, tStep); + this->defaultVTKPiece.setNumberOfInternalVarsToExport(xFemMan->vtkExportFields, this->defaultVTKPiece.getMapL2G().giveSize() ); + + std::string pointHeader, cellHeader; + this->giveDataHeaders(pointHeader, cellHeader); + this->fileStream << pointHeader.c_str(); + + for ( int field = 1; field <= xFemMan->vtkExportFields.giveSize(); field++ ) { + //XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields [ field - 1 ]; + + for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) { + // Fills a data struct (VTKPiece) with all the necessary data. + //this->setupVTKPiece(this->defaultVTKPiece, tStep, *region); + this->exportIntVars(this->defaultVTKPiece, *region, field, enrItIndex, internalVarsToExport, *smoother, tStep); + // Write the VTK piece to file. + anyPieceNonEmpty +=this->writeXFEMVars(this->defaultVTKPiece, field, enrItIndex); + } + } + + this->fileStream << "\n"; + this->writeVTKPieceEpilog(this->defaultVTKPiece, tStep); + this->defaultVTKPiece.clear(); + } + } + + /* + * Output all composite elements - one piece per composite element + * Each element is responsible of setting up a VTKPiece which can then be exported + */ + for ( int pieceNum = 1; pieceNum <= nPiecesToExport; pieceNum++ ) { + const IntArray &elements = this->giveRegionSet(pieceNum)->giveElementList(); + for ( int i = 1; i <= elements.giveSize(); i++ ) { + Element *el = d->giveElement(elements.at(i) ); + if ( this->isElementComposite(el) ) { + if ( el->giveParallelMode() != Element_local ) { + continue; + } +#ifndef __VTK_MODULE + //this->exportCompositeElement(this->defaultVTKPiece, el, tStep); + this->exportCompositeElement(this->defaultVTKPieces, el, tStep); + for ( int j = 0; j < ( int ) this->defaultVTKPieces.size(); j++ ) { + this->writeVTKPieceProlog(this->defaultVTKPieces[j], tStep); + std::string pointHeader, cellHeader; + this->giveDataHeaders(pointHeader, cellHeader); + this->fileStream << pointHeader.c_str(); + + for ( int field = 1; field <= xFemMan->vtkExportFields.giveSize(); field++ ) { + for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) { + anyPieceNonEmpty += this->writeXFEMVars(this->defaultVTKPieces [ j ], field, enrItIndex); + } + } + this->fileStream << "\n"; + this->writeVTKPieceEpilog(this->defaultVTKPieces[j], tStep); + } +#else + // No support for binary export yet +#endif + } + } // end loop over composite elements + } + } + +#ifndef __VTK_MODULE + if ( anyPieceNonEmpty == 0 ) { + // write empty piece, Otherwise ParaView complains if the whole vtu file is without + this->fileStream << "\n"; + this->fileStream << "\n \n\n"; + this->fileStream << "\n"; + } +#endif + + // Finalize the output: + std::string fname = giveOutputFileName(tStep); +#ifdef __VTK_MODULE + + #if 0 + // Code fragment intended for future support of composite elements in binary format + // Doesn't as well as I would want it to, interface to VTK is to limited to control this. + // * The PVTU-file is written by every process (seems to be impossible to avoid). + // * Part files are renamed and time step and everything else is cut off => name collisions + vtkSmartPointer< vtkXMLPUnstructuredGridWriter >writer = vtkSmartPointer< vtkXMLPUnstructuredGridWriter >::New(); + writer->SetTimeStep(tStep->giveNumber() - 1); + writer->SetNumberOfPieces(this->emodel->giveNumberOfProcesses() ); + writer->SetStartPiece(this->emodel->giveRank() ); + writer->SetEndPiece(this->emodel->giveRank() ); + + + #else + vtkSmartPointer< vtkXMLUnstructuredGridWriter >writer = vtkSmartPointer< vtkXMLUnstructuredGridWriter >::New(); + #endif + + writer->SetFileName(fname.c_str() ); + //writer->SetInput(this->fileStream); // VTK 4 + writer->SetInputData(this->fileStream); // VTK 6 + + // Optional - set the mode. The default is binary. + //writer->SetDataModeToBinary(); + writer->SetDataModeToAscii(); + writer->Write(); +#else + this->fileStream << "\n"; + if(this->fileStream){ + this->fileStream.close(); + } +#endif +} + +} // end namespace oofem diff --git a/src/oofemlib/vtkxfemexportmodule.h b/src/oofemlib/vtkxfemexportmodule.h new file mode 100644 index 000000000..eab632ed4 --- /dev/null +++ b/src/oofemlib/vtkxfemexportmodule.h @@ -0,0 +1,108 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef vtkxfemexportmodule_h +#define vtkxfemexportmodule_h + +#include "vtkxmlexportmodule.h" +#include "intarray.h" +#include "nodalrecoverymodel.h" +#include "interface.h" +#include "internalstatevaluetype.h" +#include "integrationrule.h" +#include "xfem/xfemmanager.h" +#include +#include +#include + +#ifdef _WIN32 + #define NULL_DEVICE "NUL:" +#else + #define NULL_DEVICE "/dev/null" +#endif + +#include +#include + +using namespace std; +namespace oofem { +class Node; + +///@name Input fields for VTK XML export module +//@{ +#define _IFT_VTKXMLXFemExportModule_Name "vtkxmlxfem" +//@} + +/** + * Represents VTK (Visualization Toolkit) export module for Xfem. + * It uses VTK (.vtu) file format, Unstructured grid dataset. + * The export of data is done on Region By Region basis, possibly taking care about possible + * nonsmooth character of some internal variables at region boundaries. + * The exported variables are dermined by XFemManager (FemMan->vtkExportFields). + * Each region and each enrichment item is exported as a single piece. + * When region contains composite cells, these are assumed to be + * exported in individual subsequent pieces after the default one for the particular region. + */ +class OOFEM_EXPORT VTKXMLXFemExportModule : public VTKXMLExportModule +{ +protected: + +public: + /// Constructor. Creates empty Output Manager. By default all components are selected. + VTKXMLXFemExportModule(int n, EngngModel *e); + /// Destructor + virtual ~VTKXMLXFemExportModule(); + + void initializeFrom(InputRecord &ir) override; + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; + void terminate() override {} + const char *giveClassName() const override { return "VTKXMLXFemExportModule"; } + +protected: + + /// Returns the filename for the given time step. + std::string giveOutputFileName(TimeStep *tStep); + + /// Returns the output stream for given solution step. + std::ofstream giveOutputStream(TimeStep *tStep); + + bool writeXFEMVars(VTKPiece &vtkPiece, int field, int enrItIndex); + void getNodalVariableFromXFEMST(FloatArray &answer, Node *node, TimeStep *tStep, XFEMStateType xfemstype, Set ®ion, EnrichmentItem *ei); + void exportIntVars(VTKPiece &vtkPiece, Set& region, int field, int enrItIndex, IntArray& internalVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep); + void giveDataHeaders(std::string &pointHeader, std::string &cellHeader) override; // returns the headers +}; + + +} // end namespace oofem +#endif // vtkxfemexportmodule_h diff --git a/src/oofemlib/vtkxmlexportmodule.C b/src/oofemlib/vtkxmlexportmodule.C index 85bed87c1..5d70c4b28 100644 --- a/src/oofemlib/vtkxmlexportmodule.C +++ b/src/oofemlib/vtkxmlexportmodule.C @@ -50,13 +50,15 @@ #include "xfem/xfemmanager.h" #include "xfem/enrichmentitem.h" +#include "nodalaveragingrecoverymodel.h" +#include "zznodalrecoverymodel.h" + #ifdef __PFEM_MODULE #include "pfem/pfemparticle.h" #endif #include #include -#include #include #ifdef __VTK_MODULE @@ -74,33 +76,19 @@ namespace oofem { REGISTER_ExportModule(VTKXMLExportModule) -IntArray VTKXMLExportModule :: redToFull = { - 1, 5, 9, 8, 7, 4, 6, 3, 2 -}; //position of xx, yy, zz, yz, xz, xy in tensor - -VTKXMLExportModule :: VTKXMLExportModule(int n, EngngModel *e) : ExportModule(n, e), internalVarsToExport(), primaryVarsToExport() -{ - primVarSmoother = NULL; - smoother = NULL; -} +VTKXMLExportModule::VTKXMLExportModule(int n, EngngModel *e) : VTKBaseExportModule(n, e), internalVarsToExport(), primaryVarsToExport() +{} -VTKXMLExportModule :: ~VTKXMLExportModule() -{ - if ( this->smoother ) { - delete this->smoother; - } - if ( this->primVarSmoother ) { - delete this->primVarSmoother; - } -} +VTKXMLExportModule::~VTKXMLExportModule() {} -IRResultType -VTKXMLExportModule :: initializeFrom(InputRecord *ir) +void +VTKXMLExportModule::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + ExportModule::initializeFrom(ir); + int val; IR_GIVE_OPTIONAL_FIELD(ir, cellVarsToExport, _IFT_VTKXMLExportModule_cellvars); // Macro - see internalstatetype.h @@ -111,242 +99,62 @@ VTKXMLExportModule :: initializeFrom(InputRecord *ir) val = 1; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_VTKXMLExportModule_stype); // Macro - stype = ( NodalRecoveryModel :: NodalRecoveryModelType ) val; - - this->particleExportFlag = false; - IR_GIVE_OPTIONAL_FIELD(ir, particleExportFlag, _IFT_VTKXMLExportModule_particleexportflag); // Macro - - return ExportModule :: initializeFrom(ir); + stype = ( NodalRecoveryModel::NodalRecoveryModelType ) val; } void -VTKXMLExportModule :: initialize() +VTKXMLExportModule::initialize() { - if ( this->smoother ) { - delete this->smoother; - this->smoother = NULL; - } - - ExportModule :: initialize(); + this->smoother = nullptr; + this->primVarSmoother = nullptr; + VTKBaseExportModule::initialize(); } void -VTKXMLExportModule :: terminate() +VTKXMLExportModule::terminate() { } - -void -VTKXMLExportModule :: makeFullTensorForm(FloatArray &answer, const FloatArray &reducedForm, InternalStateValueType vtype) -{ - answer.resize(9); - answer.zero(); - - for ( int i = 1; i <= reducedForm.giveSize(); i++ ) { - answer.at( redToFull.at(i) ) = reducedForm.at(i); - } - - if ( vtype == ISVT_TENSOR_S3E ) { - answer.at(4) *= 0.5; - answer.at(7) *= 0.5; - answer.at(8) *= 0.5; - } - - // Symmetrize if needed - if ( vtype != ISVT_TENSOR_G ) { - answer.at(2) = answer.at(4); - answer.at(3) = answer.at(7); - answer.at(6) = answer.at(8); - } -} - - -std :: string -VTKXMLExportModule :: giveOutputFileName(TimeStep *tStep) +std::string +VTKXMLExportModule::giveOutputFileName(TimeStep *tStep) { return this->giveOutputBaseFileName(tStep) + ".vtu"; } -FILE * -VTKXMLExportModule :: giveOutputStream(TimeStep *tStep) -{ - FILE *answer; - std :: string fileName = giveOutputFileName(tStep); - if ( ( answer = fopen(fileName.c_str(), "w") ) == NULL ) { - OOFEM_ERROR( "failed to open file %s", fileName.c_str() ); - } - - return answer; -} - -int -VTKXMLExportModule :: giveCellType(Element *elem) -{ - Element_Geometry_Type elemGT = elem->giveGeometryType(); - int vtkCellType = 0; - - if ( elemGT == EGT_point ) { - vtkCellType = 1; - } else if ( elemGT == EGT_line_1 ) { - vtkCellType = 3; - } else if ( elemGT == EGT_line_2 ) { - vtkCellType = 21; - } else if ( elemGT == EGT_triangle_1 ) { - vtkCellType = 5; - } else if ( elemGT == EGT_triangle_2 ) { - vtkCellType = 22; - } else if ( elemGT == EGT_tetra_1 ) { - vtkCellType = 10; - } else if ( elemGT == EGT_tetra_2 ) { - vtkCellType = 24; - } else if ( elemGT == EGT_quad_1 || elemGT == EGT_quad_1_interface ) { - vtkCellType = 9; - } else if ( elemGT == EGT_quad_21_interface ) { - vtkCellType = 30; - } else if ( elemGT == EGT_quad_2 ) { - vtkCellType = 23; - } else if ( elemGT == EGT_quad9_2 ) { - vtkCellType = 23; - } else if ( elemGT == EGT_hexa_1 ) { - vtkCellType = 12; - } else if ( elemGT == EGT_hexa_2 ) { - vtkCellType = 25; - } else if ( elemGT == EGT_hexa_27 ) { - vtkCellType = 29; - } else if ( elemGT == EGT_wedge_1 ) { - vtkCellType = 13; - } else if ( elemGT == EGT_wedge_2 ) { - vtkCellType = 26; - } else { - OOFEM_ERROR( "unsupported element geometry type on element %d", elem->giveNumber() ); - } - - return vtkCellType; -} - -int -VTKXMLExportModule :: giveNumberOfNodesPerCell(int cellType) +std::ofstream +VTKXMLExportModule::giveOutputStream(TimeStep *tStep) { - switch ( cellType ) { - case 1: - return 1; - - case 3: - return 2; - - case 5: - case 21: - return 3; - - case 9: - case 10: - return 4; - - case 14: - return 5; - - case 13: - case 22: - case 30: - return 6; - - case 12: - case 23: - return 8; - - case 24: - return 10; - - case 25: - return 20; + std::string fileName = giveOutputFileName(tStep); + std::ofstream streamF; - case 29: - return 27; - - default: - OOFEM_ERROR("unsupported cell type ID"); - } - - return 0; // to make compiler happy -} - - -void -VTKXMLExportModule :: giveElementCell(IntArray &answer, Element *elem) -{ - // Gives the node mapping from the order used in OOFEM to that used in VTK - - Element_Geometry_Type elemGT = elem->giveGeometryType(); - IntArray nodeMapping(0); - if ( ( elemGT == EGT_point ) || - ( elemGT == EGT_line_1 ) || ( elemGT == EGT_line_2 ) || - ( elemGT == EGT_triangle_1 ) || ( elemGT == EGT_triangle_2 ) || - ( elemGT == EGT_tetra_1 ) || ( elemGT == EGT_tetra_2 ) || - ( elemGT == EGT_quad_1 ) || ( elemGT == EGT_quad_2 ) || - ( elemGT == EGT_hexa_1 ) || ( elemGT == EGT_quad9_2 ) || - ( elemGT == EGT_wedge_1 ) ) {} else if ( elemGT == EGT_hexa_27 ) { - nodeMapping = { - 5, 8, 7, 6, 1, 4, 3, 2, 16, 15, 14, 13, 12, 11, 10, 9, 17, 20, 19, 18, 23, 25, 26, 24, 22, 21, 27 - }; - } else if ( elemGT == EGT_hexa_2 ) { - nodeMapping = { - 5, 8, 7, 6, 1, 4, 3, 2, 16, 15, 14, 13, 12, 11, 10, 9, 17, 20, 19, 18 - }; - } else if ( elemGT == EGT_wedge_2 ) { - nodeMapping = { - 4, 6, 5, 1, 3, 2, 12, 11, 10, 9, 8, 7, 13, 15, 14 - }; - } else if ( elemGT == EGT_quad_1_interface ) { - nodeMapping = { - 1, 2, 4, 3 - }; - } else if ( elemGT == EGT_quad_21_interface ) { -// nodeMapping = { -// 1, 2, 5, 4, 3, 6 -// }; - nodeMapping = { - 1, 2, 5, 4, 3, 6 - }; + if ( pythonExport ) { + streamF = std::ofstream(NULL_DEVICE);//do not write anything } else { - OOFEM_ERROR("VTKXMLExportModule: unsupported element geometry type"); + streamF = std::ofstream(fileName); } - int nelemNodes = elem->giveNumberOfNodes(); - answer.resize(nelemNodes); - if ( nodeMapping.giveSize() > 0 ) { - for ( int i = 1; i <= nelemNodes; i++ ) { - answer.at(i) = elem->giveNode( nodeMapping.at(i) )->giveNumber(); - } - } else { - for ( int i = 1; i <= nelemNodes; i++ ) { - answer.at(i) = elem->giveNode(i)->giveNumber(); - } + if ( !streamF.good() ) { + OOFEM_ERROR("failed to open file %s", fileName.c_str() ); } -} - -bool -VTKXMLExportModule :: isElementComposite(Element *elem) -{ - return ( elem->giveGeometryType() == EGT_Composite ); + streamF.fill('0');//zero padding + return streamF; } void -VTKXMLExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) +VTKXMLExportModule::doOutput(TimeStep *tStep, bool forcedOutput) { if ( !( testTimeStepOutput(tStep) || forcedOutput ) ) { return; } - - - + #ifdef __VTK_MODULE - this->fileStream = vtkSmartPointer< vtkUnstructuredGrid > :: New(); - this->nodes = vtkSmartPointer< vtkPoints > :: New(); - this->elemNodeArray = vtkSmartPointer< vtkIdList > :: New(); + this->fileStream = vtkSmartPointer< vtkUnstructuredGrid >::New(); + this->nodes = vtkSmartPointer< vtkPoints >::New(); + this->elemNodeArray = vtkSmartPointer< vtkIdList >::New(); #else this->fileStream = this->giveOutputStream(tStep); @@ -359,143 +167,81 @@ VTKXMLExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) // Write output: VTK header #ifndef __VTK_MODULE - fprintf(this->fileStream, "\n", tStep->giveTargetTime() * timeScale, current->tm_year + 1900, current->tm_mon + 1, current->tm_mday, current->tm_hour, current->tm_min, current->tm_sec); - fprintf(this->fileStream, "\n"); - fprintf(this->fileStream, "\n"); + this->fileStream << "\n"; + this->fileStream << "\n"; + this->fileStream << "\n"; #endif this->giveSmoother(); // make sure smoother is created, Necessary? If it doesn't exist it is created /JB + /* Loop over pieces ///@todo: this feature has been broken but not checked if it currently works /JB + * Start default pieces containing all single cell elements. Elements built up from several vtk + * cells (composite elements) are exported as individual pieces after the default ones. + */ + int nPiecesToExport = this->giveNumberOfRegions(); //old name: region, meaning: sets + int anyPieceNonEmpty = 0; + NodalRecoveryModel *smoother = giveSmoother(); + NodalRecoveryModel *primVarSmoother = givePrimVarSmoother(); + + for ( int pieceNum = 1; pieceNum <= nPiecesToExport; pieceNum++ ) { + // Fills a data struct (VTKPiece) with all the necessary data. + Set* region = this->giveRegionSet(pieceNum); + this->setupVTKPiece(this->defaultVTKPiece, tStep, *region); + this->writeVTKPieceProlog(this->defaultVTKPiece, tStep); + // Export primary, internal and XFEM variables as nodal quantities + this->exportPrimaryVars(this->defaultVTKPiece, *region, primaryVarsToExport, *primVarSmoother, tStep); + this->exportIntVars(this->defaultVTKPiece, *region, internalVarsToExport, *smoother, tStep); + this->exportExternalForces(this->defaultVTKPiece, *region, externalForcesToExport, tStep); + this->exportCellVars(this->defaultVTKPiece, *region, cellVarsToExport, tStep); - if ( !this->particleExportFlag ) { - /* Loop over pieces ///@todo: this feature has been broken but not checked if it currently works /JB - * Start default pieces containing all single cell elements. Elements built up from several vtk - * cells (composite elements) are exported as individual pieces after the default ones. - */ - int nPiecesToExport = this->giveNumberOfRegions(); //old name: region, meaning: sets - int anyPieceNonEmpty = 0; - - for ( int pieceNum = 1; pieceNum <= nPiecesToExport; pieceNum++ ) { - // Fills a data struct (VTKPiece) with all the necessary data. - this->setupVTKPiece(this->defaultVTKPiece, tStep, pieceNum); - - // Write the VTK piece to file. - anyPieceNonEmpty += this->writeVTKPiece(this->defaultVTKPiece, tStep); - } - - /* - * Output all composite elements - one piece per composite element - * Each element is responsible of setting up a VTKPiece which can then be exported - */ - Domain *d = emodel->giveDomain(1); + // Write the VTK piece to file. + anyPieceNonEmpty += this->writeVTKPieceVariables(this->defaultVTKPiece, tStep); + this->writeVTKPieceEpilog(this->defaultVTKPiece, tStep); + this->defaultVTKPiece.clear(); + } - for ( int pieceNum = 1; pieceNum <= nPiecesToExport; pieceNum++ ) { - const IntArray &elements = this->giveRegionSet(pieceNum)->giveElementList(); - for ( int i = 1; i <= elements.giveSize(); i++ ) { - Element *el = d->giveElement( elements.at(i) ); - if ( this->isElementComposite(el) ) { - if ( el->giveParallelMode() != Element_local ) { - continue; - } + /* + * Output all composite elements - one piece per composite element + * Each element is responsible of setting up a VTKPiece which can then be exported + */ + Domain *d = emodel->giveDomain(1); + for ( int pieceNum = 1; pieceNum <= nPiecesToExport; pieceNum++ ) { + const IntArray &elements = this->giveRegionSet(pieceNum)->giveElementList(); + for ( int i = 1; i <= elements.giveSize(); i++ ) { + Element *el = d->giveElement(elements.at(i) ); + if ( this->isElementComposite(el) ) { + if ( el->giveParallelMode() != Element_local ) { + continue; + } #ifndef __VTK_MODULE - //this->exportCompositeElement(this->defaultVTKPiece, el, tStep); - this->exportCompositeElement(this->defaultVTKPieces, el, tStep); - - for ( int j = 0; j < ( int ) this->defaultVTKPieces.size(); j++ ) { - anyPieceNonEmpty += this->writeVTKPiece(this->defaultVTKPieces [ j ], tStep); - } + //this->exportCompositeElement(this->defaultVTKPiece, el, tStep); + this->exportCompositeElement(this->defaultVTKPieces, el, tStep); + + for ( int j = 0; j < ( int ) this->defaultVTKPieces.size(); j++ ) { + this->writeVTKPieceProlog(this->defaultVTKPieces[j], tStep); + anyPieceNonEmpty += this->writeVTKPieceVariables(this->defaultVTKPieces [ j ], tStep); + this->writeVTKPieceEpilog(this->defaultVTKPieces[j], tStep); + this->defaultVTKPieces [ j ].clear(); + } #else - // No support for binary export yet + // No support for binary export yet #endif - } - } - } // end loop over composite elements - - if (anyPieceNonEmpty == 0) { - // write empty piece, Otherwise ParaView complains if the whole vtu file is without - fprintf(this->fileStream, "\n"); - fprintf(this->fileStream, "\n \n\n"); - fprintf(this->fileStream, "\n"); - } - - - } else { // if (particleExportFlag) -#ifdef __PFEM_MODULE - // write out the particles (nodes exported as vertices = VTK_VERTEX) - Domain *d = emodel->giveDomain(1); - int nnode = d->giveNumberOfDofManagers(); - - int nActiveNode = 0; - for ( int inode = 1; inode <= nnode; inode++ ) { - PFEMParticle *particle = dynamic_cast< PFEMParticle * >( d->giveNode(inode) ); - if ( particle ) { - if ( particle->isActive() ) { - nActiveNode++; - } - } - } - - DofManager *node; - FloatArray *coords; - fprintf(this->fileStream, "\n", nActiveNode, nActiveNode); - fprintf(this->fileStream, "\n "); - - for ( int inode = 1; inode <= nnode; inode++ ) { - node = d->giveNode(inode); - PFEMParticle *particle = dynamic_cast< PFEMParticle * >(node); - if ( particle ) { - if ( particle->isActive() ) { - coords = node->giveCoordinates(); - ///@todo move this below into setNodeCoords since it should alwas be 3 components anyway - for ( int i = 1; i <= coords->giveSize(); i++ ) { - fprintf( this->fileStream, "%e ", coords->at(i) ); - } - - for ( int i = coords->giveSize() + 1; i <= 3; i++ ) { - fprintf(this->fileStream, "%e ", 0.0); - } - } } } + } // end loop over composite elements - fprintf(this->fileStream, "\n\n"); - - - // output the cells connectivity data - fprintf(this->fileStream, "\n"); - fprintf(this->fileStream, " "); - - for ( int ielem = 1; ielem <= nActiveNode; ielem++ ) { - fprintf(this->fileStream, "%d ", ielem - 1); - } - - fprintf(this->fileStream, "\n"); - - // output the offsets (index of individual element data in connectivity array) - fprintf(this->fileStream, " "); - - for ( int ielem = 1; ielem <= nActiveNode; ielem++ ) { - fprintf(this->fileStream, "%d ", ielem); - } - fprintf(this->fileStream, "\n"); - - - // output cell (element) types - fprintf(this->fileStream, " "); - for ( int ielem = 1; ielem <= nActiveNode; ielem++ ) { - fprintf(this->fileStream, "%d ", 1); - } - - fprintf(this->fileStream, "\n"); - fprintf(this->fileStream, "\n"); - fprintf(this->fileStream, "\n"); -#endif //__PFEM_MODULE +#ifndef __VTK_MODULE + if ( anyPieceNonEmpty == 0 ) { + // write empty piece, Otherwise ParaView complains if the whole vtu file is without + this->fileStream << "\n"; + this->fileStream << "\n \n\n"; + this->fileStream << "\n"; } +#endif - - // Finilize the output: - std :: string fname = giveOutputFileName(tStep); + // Finalize the output: + std::string fname = giveOutputFileName(tStep); #ifdef __VTK_MODULE #if 0 @@ -503,41 +249,43 @@ VTKXMLExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) // Doesn't as well as I would want it to, interface to VTK is to limited to control this. // * The PVTU-file is written by every process (seems to be impossible to avoid). // * Part files are renamed and time step and everything else is cut off => name collisions - vtkSmartPointer< vtkXMLPUnstructuredGridWriter >writer = vtkSmartPointer< vtkXMLPUnstructuredGridWriter > :: New(); + vtkSmartPointer< vtkXMLPUnstructuredGridWriter >writer = vtkSmartPointer< vtkXMLPUnstructuredGridWriter >::New(); writer->SetTimeStep(tStep->giveNumber() - 1); - writer->SetNumberOfPieces( this->emodel->giveNumberOfProcesses() ); - writer->SetStartPiece( this->emodel->giveRank() ); - writer->SetEndPiece( this->emodel->giveRank() ); + writer->SetNumberOfPieces(this->emodel->giveNumberOfProcesses() ); + writer->SetStartPiece(this->emodel->giveRank() ); + writer->SetEndPiece(this->emodel->giveRank() ); #else - vtkSmartPointer< vtkXMLUnstructuredGridWriter >writer = vtkSmartPointer< vtkXMLUnstructuredGridWriter > :: New(); + vtkSmartPointer< vtkXMLUnstructuredGridWriter >writer = vtkSmartPointer< vtkXMLUnstructuredGridWriter >::New(); #endif - writer->SetFileName( fname.c_str() ); - writer->SetInput(this->fileStream); // VTK 4 - //writer->SetInputData(this->fileStream); // VTK 6 + writer->SetFileName(fname.c_str() ); + //writer->SetInput(this->fileStream); // VTK 4 + writer->SetInputData(this->fileStream); // VTK 6 // Optional - set the mode. The default is binary. //writer->SetDataModeToBinary(); writer->SetDataModeToAscii(); writer->Write(); #else - fprintf(this->fileStream, "\n"); - fclose(this->fileStream); + this->fileStream << "\n"; + if(this->fileStream){ + this->fileStream.close(); + } #endif // export raw ip values (if required), works only on one domain if ( !this->ipInternalVarsToExport.isEmpty() ) { this->exportIntVarsInGpAs(ipInternalVarsToExport, tStep); if ( !emodel->isParallel() && tStep->giveNumber() >= 1 ) { // For non-parallel enabled OOFEM, then we only check for multiple steps. - std :: ostringstream pvdEntry; - std :: stringstream subStep; + std::ostringstream pvdEntry; + std::stringstream subStep; if ( tstep_substeps_out_flag ) { subStep << "." << tStep->giveSubStepNumber(); } pvdEntry << "giveTargetTime() * this->timeScale << subStep.str() << "\" group=\"\" part=\"\" file=\"" << this->giveOutputBaseFileName(tStep) + ".gp.vtu" << "\"/>"; - this->gpPvdBuffer.push_back( pvdEntry.str() ); + this->gpPvdBuffer.push_back(pvdEntry.str() ); this->writeGPVTKCollection(); } } @@ -548,254 +296,51 @@ VTKXMLExportModule :: doOutput(TimeStep *tStep, bool forcedOutput) ///@todo Should use probably use PVTU-files instead. It is starting to get messy. // For this to work, all processes must have an identical output file name. for ( int i = 0; i < this->emodel->giveNumberOfProcesses(); ++i ) { - std :: ostringstream pvdEntry; - std :: stringstream subStep; + std::ostringstream pvdEntry; + std::stringstream subStep; char fext [ 100 ]; if ( this->emodel->giveNumberOfProcesses() > 1 ) { - sprintf( fext, "_%03d.m%d.%d", i, this->number, tStep->giveNumber() ); + sprintf(fext, "_%03d.m%d.%d", i, this->number, tStep->giveNumber() ); } else { - sprintf( fext, "m%d.%d", this->number, tStep->giveNumber() ); + sprintf(fext, "m%d.%d", this->number, tStep->giveNumber() ); } if ( tstep_substeps_out_flag ) { subStep << "." << tStep->giveSubStepNumber(); } pvdEntry << "giveTargetTime() * this->timeScale << subStep.str() << "\" group=\"\" part=\"" << i << "\" file=\"" << this->emodel->giveOutputBaseFileName() << fext << ".vtu\"/>"; - this->pvdBuffer.push_back( pvdEntry.str() ); + this->pvdBuffer.push_back(pvdEntry.str() ); } this->writeVTKCollection(); } else if ( !emodel->isParallel() && tStep->giveNumber() >= 1 ) { // For non-parallel, then we only check for multiple steps. - std :: ostringstream pvdEntry; - std :: stringstream subStep; + std::ostringstream pvdEntry; + std::stringstream subStep; if ( tstep_substeps_out_flag ) { subStep << "." << tStep->giveSubStepNumber(); } pvdEntry << "giveTargetTime() * this->timeScale << subStep.str() << "\" group=\"\" part=\"\" file=\"" << fname << "\"/>"; - this->pvdBuffer.push_back( pvdEntry.str() ); + this->pvdBuffer.push_back(pvdEntry.str() ); this->writeVTKCollection(); } } -void -VTKPiece :: setNumberOfNodes(int numNodes) -{ - this->numNodes = numNodes; - this->nodeCoords.resize(numNodes); -} - -void -VTKPiece :: setNumberOfCells(int numCells) -{ - this->numCells = numCells; - this->connectivity.resize(numCells); - this->elCellTypes.resize(numCells); - this->elOffsets.resize(numCells); -} - -void -VTKPiece :: setConnectivity(int cellNum, IntArray &nodes) -{ - this->connectivity [ cellNum - 1 ] = nodes; -} - -void -VTKPiece :: setNodeCoords(int nodeNum, FloatArray &coords) -{ - this->nodeCoords [ nodeNum - 1 ] = coords; -} - -void -VTKPiece :: setNumberOfPrimaryVarsToExport(int numVars, int numNodes) -{ - this->nodeVars.resize(numVars); - for ( int i = 1; i <= numVars; i++ ) { - this->nodeVars [ i - 1 ].resize(numNodes); - } -} - -void -VTKPiece :: setNumberOfLoadsToExport(int numVars, int numNodes) -{ - this->nodeLoads.resize(numVars); - for ( int i = 1; i <= numVars; i++ ) { - this->nodeLoads [ i - 1 ].resize(numNodes); - } -} - -void -VTKPiece :: setNumberOfInternalVarsToExport(int numVars, int numNodes) -{ - this->nodeVarsFromIS.resize(numVars); - for ( int i = 1; i <= numVars; i++ ) { - this->nodeVarsFromIS [ i - 1 ].resize(numNodes); - } -} - -void -VTKPiece :: setNumberOfInternalXFEMVarsToExport(int numVars, int numEnrichmentItems, int numNodes) -{ - this->nodeVarsFromXFEMIS.resize(numVars); - for ( int i = 1; i <= numVars; i++ ) { - this->nodeVarsFromXFEMIS [ i - 1 ].resize(numEnrichmentItems); - for ( int j = 1; j <= numEnrichmentItems; j++ ) { - this->nodeVarsFromXFEMIS [ i - 1 ] [ j - 1 ].resize(numNodes); - } - } -} - -void -VTKPiece :: setNumberOfCellVarsToExport(int numVars, int numCells) -{ - this->elVars.resize(numVars); - for ( int i = 1; i <= numVars; i++ ) { - this->elVars [ i - 1 ].resize(numCells); - } -} - -void -VTKPiece :: setPrimaryVarInNode(int varNum, int nodeNum, FloatArray valueArray) -{ - this->nodeVars [ varNum - 1 ] [ nodeNum - 1 ] = std :: move(valueArray); -} - -void -VTKPiece :: setLoadInNode(int varNum, int nodeNum, FloatArray valueArray) -{ - this->nodeLoads [ varNum - 1 ] [ nodeNum - 1 ] = std :: move(valueArray); -} - -void -VTKPiece :: setInternalVarInNode(int varNum, int nodeNum, FloatArray valueArray) -{ - this->nodeVarsFromIS [ varNum - 1 ] [ nodeNum - 1 ] = std :: move(valueArray); -} - -void -VTKPiece :: setInternalXFEMVarInNode(int varNum, int eiNum, int nodeNum, FloatArray valueArray) -{ - this->nodeVarsFromXFEMIS [ varNum - 1 ] [ eiNum - 1 ] [ nodeNum - 1 ] = std :: move(valueArray); -} - - -void -VTKPiece :: setCellVar(int varNum, int cellNum, FloatArray valueArray) -{ - this->elVars [ varNum - 1 ] [ cellNum - 1 ] = std :: move(valueArray); -} - - -void -VTKXMLExportModule :: setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, int region) -{ - // Stores all neccessary data (of a region) in a VTKPiece so it can be exported later. - - Domain *d = emodel->giveDomain(1); - Element *elem; - FloatArray *coords; - - this->giveSmoother(); // make sure smoother is created - - // output nodes Region By Region - int numNodes, numRegionEl; - IntArray mapG2L, mapL2G; - - // Assemble local->global and global->local region map and get number of - // single cells to process, the composite cells exported individually. - this->initRegionNodeNumbering(mapG2L, mapL2G, numNodes, numRegionEl, d, tStep, region); - if ( numNodes > 0 && numRegionEl > 0 ) { - // Export nodes as vtk vertices - vtkPiece.setNumberOfNodes(numNodes); - for ( int inode = 1; inode <= numNodes; inode++ ) { - coords = d->giveNode( mapL2G.at(inode) )->giveCoordinates(); - vtkPiece.setNodeCoords(inode, * coords); - } - - - //------------------------------------------- - // Export all the cell data for the piece - //------------------------------------------- - IntArray cellNodes; - vtkPiece.setNumberOfCells(numRegionEl); - IntArray regionElInd; - - int offset = 0; - int cellNum = 0; - IntArray elems = this->giveRegionSet(region)->giveElementList(); - for ( int ei = 1; ei <= elems.giveSize(); ei++ ) { - int elNum = elems.at(ei); - elem = d->giveElement(elNum); - - // Skip elements that: - // are inactivated or of composite type ( these are exported individually later) - if ( this->isElementComposite(elem) || !elem->isActivated(tStep) ) { - continue; - } - - //skip materials with casting time > current time - if ( !elem->isCast(tStep) ) { - continue; - } - - if ( elem->giveParallelMode() != Element_local ) { - continue; - } - - regionElInd.followedBy(ei); - - cellNum++; - - // Set the connectivity - this->giveElementCell(cellNodes, elem); // node numbering of the cell with according to the VTK format - - // Map from global to local node numbers for the current piece - int numElNodes = cellNodes.giveSize(); - IntArray connectivity(numElNodes); - for ( int i = 1; i <= numElNodes; i++ ) { - connectivity.at(i) = mapG2L.at( cellNodes.at(i) ); - } - - vtkPiece.setConnectivity(cellNum, connectivity); - - vtkPiece.setCellType( cellNum, this->giveCellType(elem) ); // VTK cell type - - offset += numElNodes; - vtkPiece.setOffset(cellNum, offset); - } - - - // Export primary, internal and XFEM variables as nodal quantities - this->exportPrimaryVars(vtkPiece, mapG2L, mapL2G, region, tStep); - this->exportIntVars(vtkPiece, mapG2L, mapL2G, region, tStep); - this->exportExternalForces(vtkPiece, mapG2L, mapL2G, region, tStep); - - this->exportCellVars(vtkPiece, regionElInd, tStep); - } // end of default piece for simple geometry elements -} - - bool -VTKXMLExportModule :: writeVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep) +VTKXMLExportModule::writeVTKPieceProlog(VTKPiece &vtkPiece, TimeStep *tStep) { - // Write a VTK piece to file. This could be the whole domain (most common case) or it can be a - // (so-called) composite element consisting of several VTK cells (layered structures, XFEM, etc.). - - /* - if ( !vtkPiece.giveNumberOfCells() ) { // handle piece with no elements. Otherwise ParaView complains if the whole vtu file is without -// fprintf(this->fileStream, "\n"); -// fprintf(this->fileStream, "\n \n\n"); -// fprintf(this->fileStream, "\n"); - return; - } - */ - if ( !vtkPiece.giveNumberOfCells() ) return false; - + // Writes a VTK piece header + geometry to file. + // This could be the whole domain (most common case) or it can be a + // (so-called) composite element consisting of several VTK cells (layered structures, XFEM, etc.). // Write output: node coords int numNodes = vtkPiece.giveNumberOfNodes(); int numEl = vtkPiece.giveNumberOfCells(); FloatArray coords; + if ( !vtkPiece.giveNumberOfCells() ) { + return false; + } + #ifdef __VTK_MODULE FloatArray vtkCoords(3); for ( int inode = 1; inode <= numNodes; inode++ ) { @@ -805,27 +350,27 @@ VTKXMLExportModule :: writeVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep) vtkCoords.at(i) = coords.at(i); } - this->nodes->InsertNextPoint( vtkCoords.at(1), vtkCoords.at(2), vtkCoords.at(3) ); + this->nodes->InsertNextPoint(vtkCoords.at(1), vtkCoords.at(2), vtkCoords.at(3) ); this->fileStream->SetPoints(nodes); } #else - fprintf(this->fileStream, "\n", numNodes, numEl); - fprintf(this->fileStream, "\n "); + this->fileStream << "\n"; + this->fileStream << "\n "; for ( int inode = 1; inode <= numNodes; inode++ ) { coords = vtkPiece.giveNodeCoords(inode); ///@todo move this below into setNodeCoords since it should alwas be 3 components anyway for ( int i = 1; i <= coords.giveSize(); i++ ) { - fprintf( this->fileStream, "%e ", coords.at(i) ); + this->fileStream << scientific << coords.at(i) << " "; } for ( int i = coords.giveSize() + 1; i <= 3; i++ ) { - fprintf(this->fileStream, "%e ", 0.0); + this->fileStream << scientific << 0.0 << " "; } } - fprintf(this->fileStream, "\n\n"); + this->fileStream << "\n\n"; #endif @@ -835,8 +380,8 @@ VTKXMLExportModule :: writeVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep) #ifdef __VTK_MODULE this->fileStream->Allocate(numEl); #else - fprintf(this->fileStream, "\n"); - fprintf(this->fileStream, " "); + this->fileStream << "\n"; + this->fileStream << " "; #endif IntArray cellNodes; for ( int ielem = 1; ielem <= numEl; ielem++ ) { @@ -844,99 +389,120 @@ VTKXMLExportModule :: writeVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep) #ifdef __VTK_MODULE elemNodeArray->Reset(); - elemNodeArray->SetNumberOfIds( cellNodes.giveSize() ); + elemNodeArray->SetNumberOfIds(cellNodes.giveSize() ); #endif for ( int i = 1; i <= cellNodes.giveSize(); i++ ) { #ifdef __VTK_MODULE elemNodeArray->SetId(i - 1, cellNodes.at(i) - 1); #else - fprintf(this->fileStream, "%d ", cellNodes.at(i) - 1); + this->fileStream << cellNodes.at(i) - 1 << " "; #endif } #ifdef __VTK_MODULE this->fileStream->InsertNextCell(vtkPiece.giveCellType(ielem), elemNodeArray); #else - fprintf(this->fileStream, " "); + this->fileStream << " "; #endif } #ifndef __VTK_MODULE - fprintf(this->fileStream, "\n"); + this->fileStream << "\n"; // output the offsets (index of individual element data in connectivity array) - fprintf(this->fileStream, " "); + this->fileStream << " "; for ( int ielem = 1; ielem <= numEl; ielem++ ) { - fprintf( this->fileStream, "%d ", vtkPiece.giveCellOffset(ielem) ); + this->fileStream << vtkPiece.giveCellOffset(ielem) << " "; } - fprintf(this->fileStream, "\n"); + this->fileStream << "\n"; // output cell (element) types - fprintf(this->fileStream, " "); + this->fileStream << " "; for ( int ielem = 1; ielem <= numEl; ielem++ ) { - fprintf( this->fileStream, "%d ", vtkPiece.giveCellType(ielem) ); + this->fileStream << vtkPiece.giveCellType(ielem) << " "; + } + + this->fileStream << "\n"; + this->fileStream << "\n"; +#endif + return true; + +} + +bool +VTKXMLExportModule::writeVTKPieceEpilog(VTKPiece &vtkPiece, TimeStep *tStep) +{ + if ( !vtkPiece.giveNumberOfCells() ) { + return false; } - fprintf(this->fileStream, "\n"); - fprintf(this->fileStream, "\n"); +#ifndef __VTK_MODULE + this->fileStream << "\n"; +#endif + return true; +} + +bool +VTKXMLExportModule::writeVTKPieceVariables(VTKPiece &vtkPiece, TimeStep *tStep) +{ + // Write a VTK piece variables to file. + // This could be the whole domain (most common case) or it can be a + // (so-called) composite element consisting of several VTK cells (layered structures, XFEM, etc.). + + if ( !vtkPiece.giveNumberOfCells() ) { + return false; + } + + +#ifndef __VTK_MODULE ///@todo giveDataHeaders is currently not updated wrt the new structure -> no file names in headers /JB - std :: string pointHeader, cellHeader; + std::string pointHeader, cellHeader; this->giveDataHeaders(pointHeader, cellHeader); - fprintf( this->fileStream, "%s", pointHeader.c_str() ); + this->fileStream << pointHeader.c_str(); #endif this->writePrimaryVars(vtkPiece); // Primary field this->writeIntVars(vtkPiece); // Internal State Type variables smoothed to the nodes this->writeExternalForces(vtkPiece); // External forces - if ( emodel->giveDomain(1)->hasXfemManager() ) { - this->writeXFEMVars(vtkPiece); // XFEM State Type variables associated with XFEM structure - } + //if ( emodel->giveDomain(1)->hasXfemManager() ) { + // this->writeXFEMVars(vtkPiece); // XFEM State Type variables associated with XFEM structure + //} #ifndef __VTK_MODULE - fprintf(this->fileStream, "\n"); - fprintf( this->fileStream, "%s", cellHeader.c_str() ); + this->fileStream << "\n"; + this->fileStream << cellHeader.c_str(); #endif - this->writeCellVars(vtkPiece); // Single cell variables ( if given in the integration points then an average will be exported) #ifndef __VTK_MODULE - fprintf(this->fileStream, "\n"); - fprintf(this->fileStream, "\n"); + this->fileStream << "\n"; #endif - - //} - - - // Clear object so it can be filled with new data for the next piece - vtkPiece.clear(); return true; } - - #ifndef __VTK_MODULE void -VTKXMLExportModule :: giveDataHeaders(std :: string &pointHeader, std :: string &cellHeader) +VTKXMLExportModule::giveDataHeaders(std::string &pointHeader, std::string &cellHeader) { - std :: string scalars, vectors, tensors; + std::string scalars, vectors, tensors; for ( int i = 1; i <= primaryVarsToExport.giveSize(); i++ ) { UnknownType type = ( UnknownType ) primaryVarsToExport.at(i); - if ( type == DisplacementVector || type == EigenVector || type == VelocityVector || type == DirectorField ) { + if ( type == DisplacementVector || type == EigenVector || type == VelocityVector || type == DirectorField || type == MacroSlipVector || type == ResidualForce ) { vectors += __UnknownTypeToString(type); vectors.append(" "); } else if ( type == FluxVector || type == PressureVector || type == Temperature || type == Humidity || type == DeplanationFunction ) { scalars += __UnknownTypeToString(type); scalars.append(" "); } else { - OOFEM_ERROR( "unsupported UnknownType %s", __UnknownTypeToString(type) ); + OOFEM_ERROR("unsupported UnknownType %s", __UnknownTypeToString(type) ); } } @@ -954,20 +520,20 @@ VTKXMLExportModule :: giveDataHeaders(std :: string &pointHeader, std :: string tensors += __InternalStateTypeToString(isttype); tensors.append(" "); } else { - OOFEM_ERROR( "unsupported variable type %s\n", __InternalStateTypeToString(isttype) ); + OOFEM_ERROR("unsupported variable type %s\n", __InternalStateTypeToString(isttype) ); } } for ( int i = 1; i <= externalForcesToExport.giveSize(); i++ ) { UnknownType type = ( UnknownType ) externalForcesToExport.at(i); if ( type == DisplacementVector || type == VelocityVector || type == DirectorField ) { - vectors += std :: string("Load") + __UnknownTypeToString(type); + vectors += std::string("Load") + __UnknownTypeToString(type); vectors.append(" "); } else if ( type == FluxVector || type == PressureVector || type == Temperature || type == Humidity ) { - scalars += std :: string("Load") + __UnknownTypeToString(type); + scalars += std::string("Load") + __UnknownTypeToString(type); scalars.append(" "); } else { - OOFEM_ERROR( "unsupported UnknownType %s", __UnknownTypeToString(type) ); + OOFEM_ERROR("unsupported UnknownType %s", __UnknownTypeToString(type) ); } } @@ -995,7 +561,7 @@ VTKXMLExportModule :: giveDataHeaders(std :: string &pointHeader, std :: string tensors += __InternalStateTypeToString(isttype); tensors.append(" "); } else { - OOFEM_WARNING( "unsupported variable type %s\n", __InternalStateTypeToString(isttype) ); + OOFEM_WARNING("unsupported variable type %s\n", __InternalStateTypeToString(isttype) ); } } @@ -1007,172 +573,8 @@ VTKXMLExportModule :: giveDataHeaders(std :: string &pointHeader, std :: string #endif - - - - - -//---------------------------------------------------- -// Internal variables and XFEM realted fields (keyword "vars" in OOFEM input file) -//---------------------------------------------------- void -VTKXMLExportModule :: exportIntVars(VTKPiece &vtkPiece, IntArray &mapG2L, IntArray &mapL2G, int region, TimeStep *tStep) -{ - Domain *d = emodel->giveDomain(1); - InternalStateType isType; - FloatArray answer; - - this->giveSmoother()->clear(); // Makes sure smoother is up-to-date with potentially new mesh. - - // Export of Internal State Type fields - vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport.giveSize(), mapL2G.giveSize() ); - for ( int field = 1; field <= internalVarsToExport.giveSize(); field++ ) { - isType = ( InternalStateType ) internalVarsToExport.at(field); - - for ( int nodeNum = 1; nodeNum <= mapL2G.giveSize(); nodeNum++ ) { - Node *node = d->giveNode( mapL2G.at(nodeNum) ); - this->getNodalVariableFromIS(answer, node, tStep, isType, region); - vtkPiece.setInternalVarInNode(field, nodeNum, answer); - } - } - - // Export of XFEM related quantities - if ( d->hasXfemManager() ) { - XfemManager *xFemMan = d->giveXfemManager(); - int nEnrIt = xFemMan->giveNumberOfEnrichmentItems(); - - vtkPiece.setNumberOfInternalXFEMVarsToExport( xFemMan->vtkExportFields.giveSize(), nEnrIt, mapL2G.giveSize() ); - for ( int field = 1; field <= xFemMan->vtkExportFields.giveSize(); field++ ) { - XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields [ field - 1 ]; - - for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) { - for ( int nodeIndx = 1; nodeIndx <= mapL2G.giveSize(); nodeIndx++ ) { - Node *node = d->giveNode( mapL2G.at(nodeIndx) ); - getNodalVariableFromXFEMST( answer, node, tStep, xfemstype, region, xFemMan->giveEnrichmentItem(enrItIndex) ); - vtkPiece.setInternalXFEMVarInNode(field, enrItIndex, nodeIndx, answer); - } - } - } - } -} - - -void -VTKXMLExportModule :: getNodalVariableFromIS(FloatArray &answer, Node *node, TimeStep *tStep, InternalStateType type, int ireg) -{ - // Recovers nodal values from Internal States defined in the integration points. - // Should return an array with proper size supported by VTK (1, 3 or 9) - // Domain *d = emodel->giveDomain(1); - this->giveSmoother(); - IntArray redIndx; - - if ( !( type == IST_DisplacementVector || type == IST_MaterialInterfaceVal ) ) { - this->smoother->recoverValues(* this->giveRegionSet(ireg), type, tStep); - } - - - const FloatArray *val = NULL; - FloatArray valueArray; - InternalStateValueType valType = giveInternalStateValueType(type); - - if ( type == IST_DisplacementVector ) { ///@todo Why does this code exists here? DisplacementVector isn't a internal variable. And if its really desired, then why the special treatment for just displacements? - ///@todo Is this for elements which does not use displacements as primary variables but e.g. the placement x? Move to exportPrimaryVar? /JB - valueArray.resize(3); - val = & valueArray; - for ( int i = 1; i <= 3; i++ ) { - valueArray.at(i) = node->giveUpdatedCoordinate(i, tStep, 1.0) - node->giveCoordinate(i); - } - } else if ( type == IST_MaterialInterfaceVal ) { - MaterialInterface *mi = emodel->giveMaterialInterface(1); - if ( mi ) { - valueArray.resize(1); - val = & valueArray; - valueArray.at(1) = mi->giveNodalScalarRepresentation( node->giveNumber() ); - } - } else { - int found = this->smoother->giveNodalVector( val, node->giveNumber() ); - if ( !found ) { - valueArray.resize( redIndx.giveSize() ); - val = & valueArray; - } - } - - int ncomponents = giveInternalStateTypeSize(valType); - answer.resize(ncomponents); - int valSize = val->giveSize(); // size of recovered quantity - - // check if valSize corresponds to the expected size otherwise pad with zeros - if ( valType == ISVT_SCALAR ) { - answer.at(1) = valSize ? val->at(1) : 0.0; - } else if ( valType == ISVT_VECTOR ) { - answer = * val; - // bp: hack for BeamForceMomentTensor, which should be splitted into force and momentum vectors - if (type == IST_BeamForceMomentTensor) { - answer.resizeWithValues(6); - } else { - answer.resizeWithValues(3); - } - } else if ( valType == ISVT_TENSOR_S3 || valType == ISVT_TENSOR_S3E || valType == ISVT_TENSOR_G ) { - this->makeFullTensorForm(answer, * val, valType); - } else { - OOFEM_ERROR("ISVT_UNDEFINED encountered") - } -} - - -void -VTKXMLExportModule :: getNodalVariableFromXFEMST(FloatArray &answer, Node *node, TimeStep *tStep, XFEMStateType xfemstype, int ireg, EnrichmentItem *ei) -{ - // Recovers nodal values from XFEM state variables (e.g. levelset function) - // Should return an array with proper size supported by VTK (1, 3 or 9) - // This could be moved into EnrichmentItem such that VTKExport doesn't need to know anything about XFEM - - const FloatArray *val = NULL; - FloatArray valueArray; - - Domain *d = emodel->giveDomain(1); - XfemManager *xFemMan = d->giveXfemManager(); - InternalStateValueType valType = xFemMan->giveXFEMStateValueType(xfemstype); - - - // The xfem level set function is defined in the nodes and recovery of nodal values is trivial. - if ( xfemstype == XFEMST_LevelSetPhi ) { - valueArray.resize(1); - val = & valueArray; - ei->evalLevelSetNormalInNode( valueArray.at(1), node->giveNumber(), * ( node->giveCoordinates() ) ); - } else if ( xfemstype == XFEMST_LevelSetGamma ) { - valueArray.resize(1); - val = & valueArray; - ei->evalLevelSetTangInNode( valueArray.at(1), node->giveNumber(), * ( node->giveCoordinates() ) ); - } else if ( xfemstype == XFEMST_NodeEnrMarker ) { - valueArray.resize(1); - val = & valueArray; - ei->evalNodeEnrMarkerInNode( valueArray.at(1), node->giveNumber() ); - } else { - //OOFEM_WARNING("invalid data in node %d", inode); - } - - ///@todo duplicated code from getNodalVariableFromIS - uneccessary - int ncomponents = giveInternalStateTypeSize(valType); - answer.resize(ncomponents); - int valSize = val->giveSize(); // size of recovered quantity - - // check if valSize corresponds to the expected size otherwise pad with zeros - if ( valType == ISVT_SCALAR ) { - answer.at(1) = valSize ? val->at(1) : 0.0; - } else if ( valType == ISVT_VECTOR ) { - answer = * val; - answer.resizeWithValues(3); - } else if ( valType == ISVT_TENSOR_S3 || valType == ISVT_TENSOR_S3E || valType == ISVT_TENSOR_G ) { - this->makeFullTensorForm(answer, * val, valType); - } else { - OOFEM_ERROR("ISVT_UNDEFINED encountered") - } -} - - -void -VTKXMLExportModule :: writeIntVars(VTKPiece &vtkPiece) +VTKXMLExportModule::writeIntVars(VTKPiece &vtkPiece) { int n = internalVarsToExport.giveSize(); for ( int i = 1; i <= n; i++ ) { @@ -1180,22 +582,24 @@ VTKXMLExportModule :: writeIntVars(VTKPiece &vtkPiece) int ncomponents; const char *name = __InternalStateTypeToString(type); + ( void ) name;//silence warning int numNodes = vtkPiece.giveNumberOfNodes(); FloatArray valueArray; - valueArray = vtkPiece.giveInternalVarInNode(i, 1); + valueArray = vtkPiece.giveInternalVarInNode(type, 1); ncomponents = valueArray.giveSize(); + ( void ) ncomponents;//silence warning // Header #ifdef __VTK_MODULE - vtkSmartPointer< vtkDoubleArray >varArray = vtkSmartPointer< vtkDoubleArray > :: New(); + vtkSmartPointer< vtkDoubleArray >varArray = vtkSmartPointer< vtkDoubleArray >::New(); varArray->SetName(name); varArray->SetNumberOfComponents(ncomponents); varArray->SetNumberOfTuples(numNodes); for ( int inode = 1; inode <= numNodes; inode++ ) { - valueArray = vtkPiece.giveInternalVarInNode(i, inode); + valueArray = vtkPiece.giveInternalVarInNode(type, inode); for ( int i = 1; i <= ncomponents; ++i ) { - varArray->SetComponent( inode - 1, i - 1, valueArray.at(i) ); + varArray->SetComponent(inode - 1, i - 1, valueArray.at(i) ); } } @@ -1203,72 +607,21 @@ VTKXMLExportModule :: writeIntVars(VTKPiece &vtkPiece) #else - fprintf(this->fileStream, " ", name, ncomponents); + this->fileStream << " "; for ( int inode = 1; inode <= numNodes; inode++ ) { - valueArray = vtkPiece.giveInternalVarInNode(i, inode); + valueArray = vtkPiece.giveInternalVarInNode(type, inode); this->writeVTKPointData(valueArray); } #endif - - - - - // Footer #ifndef __VTK_MODULE - fprintf(this->fileStream, "\n"); + this->fileStream << "\n"; #endif - } + + } //end of for } -void -VTKXMLExportModule :: writeXFEMVars(VTKPiece &vtkPiece) -{ - Domain *d = emodel->giveDomain(1); - XfemManager *xFemMan = d->giveXfemManager(); - int nEnrIt = xFemMan->giveNumberOfEnrichmentItems(); - FloatArray valueArray; - - - for ( int field = 1; field <= xFemMan->vtkExportFields.giveSize(); field++ ) { - XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields.at(field); - const char *namePart = __XFEMStateTypeToString(xfemstype); - InternalStateValueType valType = xFemMan->giveXFEMStateValueType(xfemstype); - int ncomponents = giveInternalStateTypeSize(valType); - - int numNodes = vtkPiece.giveNumberOfNodes(); - for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) { - // Header - char name [ 100 ]; // Must I define a fixed size? /JB - sprintf( name, "%s_%d ", namePart, xFemMan->giveEnrichmentItem(enrItIndex)->giveNumber() ); - -#ifdef __VTK_MODULE - vtkSmartPointer< vtkDoubleArray >varArray = vtkSmartPointer< vtkDoubleArray > :: New(); - varArray->SetName(name); - varArray->SetNumberOfComponents(ncomponents); - varArray->SetNumberOfTuples(numNodes); - for ( int inode = 1; inode <= numNodes; inode++ ) { - valueArray = vtkPiece.giveInternalXFEMVarInNode(field, enrItIndex, inode); - for ( int i = 1; i <= ncomponents; ++i ) { - varArray->SetComponent( inode - 1, i - 1, valueArray.at(i) ); - } - } - - this->writeVTKPointData(name, varArray); -#else - fprintf(this->fileStream, " ", name, ncomponents); - for ( int inode = 1; inode <= numNodes; inode++ ) { - valueArray = vtkPiece.giveInternalXFEMVarInNode(field, enrItIndex, inode); - this->writeVTKPointData(valueArray); - } - fprintf(this->fileStream, "\n"); -#endif - } - } -} - - //---------------------------------------------------- @@ -1276,7 +629,7 @@ VTKXMLExportModule :: writeXFEMVars(VTKPiece &vtkPiece) //---------------------------------------------------- #ifdef __VTK_MODULE void -VTKXMLExportModule :: writeVTKPointData(const char *name, vtkSmartPointer< vtkDoubleArray >varArray) +VTKXMLExportModule::writeVTKPointData(const char *name, vtkSmartPointer< vtkDoubleArray >varArray) { // Write the data to file int ncomponents = varArray->GetNumberOfComponents(); @@ -1297,22 +650,19 @@ VTKXMLExportModule :: writeVTKPointData(const char *name, vtkSmartPointer< vtkDo } #else void -VTKXMLExportModule :: writeVTKPointData(FloatArray &valueArray) +VTKXMLExportModule::writeVTKPointData(FloatArray &valueArray) { // Write the data to file for ( int i = 1; i <= valueArray.giveSize(); i++ ) { - fprintf( this->fileStream, "%e ", valueArray.at(i) ); + this->fileStream << scientific << valueArray.at(i) << " "; } } #endif - - - #ifdef __VTK_MODULE void -VTKXMLExportModule :: writeVTKCellData(const char *name, vtkSmartPointer< vtkDoubleArray >varArray) +VTKXMLExportModule::writeVTKCellData(const char *name, vtkSmartPointer< vtkDoubleArray >varArray) { // Write the data to file int ncomponents = varArray->GetNumberOfComponents(); @@ -1335,525 +685,97 @@ VTKXMLExportModule :: writeVTKCellData(const char *name, vtkSmartPointer< vtkDou #else void -VTKXMLExportModule :: writeVTKCellData(FloatArray &valueArray) +VTKXMLExportModule::writeVTKCellData(FloatArray &valueArray) { // Write the data to file ///@todo exact copy of writeVTKPointData so remove for ( int i = 1; i <= valueArray.giveSize(); i++ ) { - fprintf( this->fileStream, "%e ", valueArray.at(i) ); + this->fileStream << valueArray.at(i) << " "; } } #endif - - -int -VTKXMLExportModule :: initRegionNodeNumbering(IntArray ®ionG2LNodalNumbers, - IntArray ®ionL2GNodalNumbers, - int ®ionDofMans, - int ®ionSingleCells, - Domain *domain, TimeStep *tStep, int reg) -{ - // regionG2LNodalNumbers is array with mapping from global numbering to local region numbering. - // The i-th value contains the corresponding local region number (or zero, if global numbar is not in region). - - // regionL2GNodalNumbers is array with mapping from local to global numbering. - // The i-th value contains the corresponding global node number. - - - int nnodes = domain->giveNumberOfDofManagers(); - int elemNodes; - int elementNode, node; - int currOffset = 1; - Element *element; - - regionG2LNodalNumbers.resize(nnodes); - regionG2LNodalNumbers.zero(); - regionDofMans = 0; - regionSingleCells = 0; - - IntArray elements = this->giveRegionSet(reg)->giveElementList(); - for ( int ie = 1; ie <= elements.giveSize(); ie++ ) { - int ielem = elements.at(ie); - element = domain->giveElement(ielem); - - if ( this->isElementComposite(element) ) { - continue; // composite cells exported individually - } - - if ( !element->isActivated(tStep) ) { //skip inactivated elements - continue; - } - - //skip materials with casting time > current time - if ( !element->isCast(tStep) ) { - continue; - } - - if ( element->giveParallelMode() != Element_local ) { - continue; - } - - regionSingleCells++; - elemNodes = element->giveNumberOfNodes(); - // elemSides = element->giveNumberOfSides(); - - // determine local region node numbering - for ( elementNode = 1; elementNode <= elemNodes; elementNode++ ) { - node = element->giveNode(elementNode)->giveNumber(); - if ( regionG2LNodalNumbers.at(node) == 0 ) { // assign new number - /* mark for assignment. This is done later, as it allows to preserve - * natural node numbering. - */ - regionG2LNodalNumbers.at(node) = 1; - regionDofMans++; - } - } - } - - regionL2GNodalNumbers.resize(regionDofMans); - - for ( int i = 1; i <= nnodes; i++ ) { - if ( regionG2LNodalNumbers.at(i) ) { - regionG2LNodalNumbers.at(i) = currOffset++; - regionL2GNodalNumbers.at( regionG2LNodalNumbers.at(i) ) = i; - } - } - - return 1; -} - - - - - - - - -//---------------------------------------------------- -// Primary variables - readily available in the nodes -//---------------------------------------------------- -void -VTKXMLExportModule :: exportPrimaryVars(VTKPiece &vtkPiece, IntArray &mapG2L, IntArray &mapL2G, int region, TimeStep *tStep) -{ - Domain *d = emodel->giveDomain(1); - FloatArray valueArray; - this->givePrimVarSmoother()->clear(); // Makes sure primary smoother is up-to-date with potentially new mesh. - - vtkPiece.setNumberOfPrimaryVarsToExport( primaryVarsToExport.giveSize(), mapL2G.giveSize() ); - for ( int i = 1, n = primaryVarsToExport.giveSize(); i <= n; i++ ) { - UnknownType type = ( UnknownType ) primaryVarsToExport.at(i); - - for ( int inode = 1; inode <= mapL2G.giveSize(); inode++ ) { - DofManager *dman = d->giveNode( mapL2G.at(inode) ); - - this->getNodalVariableFromPrimaryField(valueArray, dman, tStep, type, region); - vtkPiece.setPrimaryVarInNode( i, inode, std :: move(valueArray) ); - } - } -} - - -void -VTKXMLExportModule :: getNodalVariableFromPrimaryField(FloatArray &answer, DofManager *dman, TimeStep *tStep, UnknownType type, int ireg) -{ - // This code is not perfect. It should be rewritten to handle all cases more gracefully. - ///@todo This method needs to be cleaned up - maybe define the common vector types so - /// certain dofid's are associated with them /JB - - IntArray dofIDMask(3); - int size; - const FloatArray *recoveredVal; - - InternalStateType iState = IST_DisplacementVector; // Shouldn't be necessary - - dofIDMask.clear(); - - if ( type == DisplacementVector ) { - dofIDMask = { - ( int ) Undef, ( int ) Undef, ( int ) Undef - }; - for ( Dof *dof : *dman ) { - DofIDItem id = dof->giveDofID(); - if ( id == D_u ) { - dofIDMask.at(1) = id; - } else if ( id == D_v ) { - dofIDMask.at(2) = id; - } else if ( id == D_w ) { - dofIDMask.at(3) = id; - } - } - - answer.resize(3); - } else if ( type == VelocityVector ) { - dofIDMask = { - ( int ) Undef, ( int ) Undef, ( int ) Undef - }; - for ( Dof *dof : *dman ) { - DofIDItem id = dof->giveDofID(); - if ( id == V_u ) { - dofIDMask.at(1) = id; - } else if ( id == V_v ) { - dofIDMask.at(2) = id; - } else if ( id == V_w ) { - dofIDMask.at(3) = id; - } - } - - answer.resize(3); - } else if ( type == EigenVector ) { - dofIDMask = { - ( int ) Undef, ( int ) Undef, ( int ) Undef - }; - for ( Dof *dof : *dman ) { - DofIDItem id = dof->giveDofID(); - if ( ( id == V_u ) || ( id == D_u ) ) { - dofIDMask.at(1) = id; - } else if ( ( id == V_v ) || ( id == D_v ) ) { - dofIDMask.at(2) = id; - } else if ( ( id == V_w ) || ( id == D_w ) ) { - dofIDMask.at(3) = id; - } - } - - answer.resize(3); - } else if ( type == FluxVector || type == Humidity ) { - dofIDMask.followedBy(C_1); - iState = IST_MassConcentration_1; - answer.resize(1); - } else if ( type == DeplanationFunction ) { - dofIDMask.followedBy(Warp_PsiTheta); - iState = IST_Temperature; - answer.resize(1); - } else if ( type == Temperature ) { - dofIDMask.followedBy(T_f); - iState = IST_Temperature; - answer.resize(1); - } else if ( type == PressureVector ) { - dofIDMask.followedBy(P_f); - iState = IST_Pressure; - answer.resize(1); - } else if ( type == DirectorField ) { - for ( Dof *dof : *dman ) { - DofIDItem id = dof->giveDofID(); - if ( ( id == W_u ) || ( id == W_v ) || ( id == W_w ) ) { - dofIDMask.followedBy(id); - } - - answer.resize(3); - } - - iState = IST_DirectorField; - } else { - OOFEM_ERROR( "unsupported unknownType %s", __UnknownTypeToString(type) ); - } - - size = dofIDMask.giveSize(); - answer.zero(); - - for ( int j = 1; j <= size; j++ ) { - DofIDItem id = ( DofIDItem ) dofIDMask.at(j); - if ( id == Undef ) { - answer.at(j) = 0.; - } else if ( iState == IST_DirectorField ) { - answer.at(j) = dman->giveDofWithID(id)->giveUnknown(VM_Total, tStep); - // recover values if not done before - this->givePrimVarSmoother()->recoverValues(* this->giveRegionSet(ireg), iState, tStep); - this->givePrimVarSmoother()->giveNodalVector( recoveredVal, dman->giveNumber() ); - if ( size == recoveredVal->giveSize() ) { - answer.at(j) = recoveredVal->at(j); - } else { - OOFEM_WARNING("Recovered variable size mismatch for %d for id %d", type, id); - answer.at(j) = 0.0; - } - } else if ( dman->hasDofID(id) ) { - // primary variable available directly in DOF-manager - answer.at(j) = dman->giveDofWithID(id)->giveUnknown(VM_Total, tStep); - //mj - if incremental value needed: answer.at(j) = dman->giveDofWithID(id)->giveUnknown(VM_Incremental, tStep); - } else if ( iState != IST_Undefined ) { - // primary variable not directly available - // but equivalent InternalStateType provided - // in this case use smoother to recover nodal value - - // This can't deal with ValueModeType, and would recover over and over for some vectorial quantities like velocity - // recover values if not done before. - this->givePrimVarSmoother()->recoverValues(* this->giveRegionSet(ireg), iState, tStep); - this->givePrimVarSmoother()->giveNodalVector( recoveredVal, dman->giveNumber() ); - // here we have a lack of information about how to convert recovered values to response - // if the size is compatible we accept it, otherwise give a warning and zero value. - if ( size == recoveredVal->giveSize() ) { - answer.at(j) = recoveredVal->at(j); - } else { - OOFEM_WARNING("Recovered variable size mismatch for \"%s\" for dof id %d. Size is %d, should be %d", __UnknownTypeToString(type), id, recoveredVal->giveSize(), size); - answer.at(j) = 0.0; - } - } - } - - - - InternalStateValueType valType = giveInternalStateValueType(type); - //rotate back from nodal CS to global CS if applies - if ( valType == ISVT_VECTOR ) { ///@todo in general, shouldn't this apply for 2nd order tensors as well? /JB - Node *node = dynamic_cast< Node * >(dman); - if ( node && node->hasLocalCS() ) { - answer.rotatedWith(* node->giveLocalCoordinateTriplet(), 't'); - } - } -} - void -VTKXMLExportModule :: writePrimaryVars(VTKPiece &vtkPiece) +VTKXMLExportModule::writePrimaryVars(VTKPiece &vtkPiece) { for ( int i = 1; i <= primaryVarsToExport.giveSize(); i++ ) { UnknownType type = ( UnknownType ) primaryVarsToExport.at(i); InternalStateValueType valType = giveInternalStateValueType(type); int ncomponents = giveInternalStateTypeSize(valType); + ( void ) ncomponents; //silence the warning int numNodes = vtkPiece.giveNumberOfNodes(); const char *name = __UnknownTypeToString(type); + ( void ) name; //silence the warning // Header #ifdef __VTK_MODULE - vtkSmartPointer< vtkDoubleArray >varArray = vtkSmartPointer< vtkDoubleArray > :: New(); + vtkSmartPointer< vtkDoubleArray >varArray = vtkSmartPointer< vtkDoubleArray >::New(); varArray->SetName(name); varArray->SetNumberOfComponents(ncomponents); varArray->SetNumberOfTuples(numNodes); for ( int inode = 1; inode <= numNodes; inode++ ) { - FloatArray &valueArray = vtkPiece.givePrimaryVarInNode(i, inode); + FloatArray &valueArray = vtkPiece.givePrimaryVarInNode(type, inode); for ( int j = 1; j <= ncomponents; ++j ) { - varArray->SetComponent( inode - 1, j - 1, valueArray.at(j) ); + varArray->SetComponent(inode - 1, j - 1, valueArray.at(j) ); } } this->writeVTKPointData(name, varArray); #else - fprintf(this->fileStream, " ", name, ncomponents); + this->fileStream << " "; for ( int inode = 1; inode <= numNodes; inode++ ) { - FloatArray &valueArray = vtkPiece.givePrimaryVarInNode(i, inode); + FloatArray &valueArray = vtkPiece.givePrimaryVarInNode(type, inode); this->writeVTKPointData(valueArray); } - fprintf(this->fileStream, "\n"); -#endif - } -} - - -//---------------------------------------------------- -// Load vectors -//---------------------------------------------------- -void -VTKXMLExportModule :: exportExternalForces(VTKPiece &vtkPiece, IntArray &mapG2L, IntArray &mapL2G, int region, TimeStep *tStep) -{ - Domain *d = emodel->giveDomain(1); - this->givePrimVarSmoother()->clear(); // Makes sure primary smoother is up-to-date with potentially new mesh. - - if ( externalForcesToExport.giveSize() == 0 ) { - return; - } - - ///@todo Add a more flexible solution here, ask the Engineering model for the equivalent to this (perhaps as part of the primary field?) - /// This should be looked into, just as "getNodalVariableFromPrimaryField" is particularly complicated. - int neq = emodel->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); - int npeq = emodel->giveNumberOfDomainEquations( 1, EModelDefaultPrescribedEquationNumbering() ); - FloatArray extForces(neq), extForcesP(npeq); - emodel->assembleVector(extForces, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), d); - emodel->assembleVector(extForcesP, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultPrescribedEquationNumbering(), d); - - vtkPiece.setNumberOfLoadsToExport( externalForcesToExport.giveSize(), mapL2G.giveSize() ); - for ( int i = 1; i <= externalForcesToExport.giveSize(); i++ ) { - UnknownType type = ( UnknownType ) externalForcesToExport.at(i); - ///@todo Have some mapping for UnknownType -> DofID array - IntArray dofids; - if ( type == VelocityVector ) { - dofids = { - V_u, V_v, V_w - }; - } else if ( type == DisplacementVector ) { - dofids = { - D_u, D_v, D_w - }; - } else if ( type == PressureVector ) { - dofids = { - P_f - }; - } else { - OOFEM_WARNING("Unrecognized UnknownType (%d), no external forces exported", type); - } + this->fileStream << "\n"; - for ( int inode = 1; inode <= mapL2G.giveSize(); inode++ ) { - DofManager *dman = d->giveNode( mapL2G.at(inode) ); - - FloatArray valueArray( dofids.giveSize() ); - for ( int k = 1; k <= dofids.giveSize(); ++k ) { - Dof *dof = dman->giveDofWithID( dofids.at(k) ); - ///@todo Have to make more assumptions here.. we shouldn't assume EModelDefaultEquationNumbering. Do something nicer than extForces and extForcesP instead. - int eq; - if ( ( eq = dof->giveEquationNumber( EModelDefaultEquationNumbering() ) ) > 0 ) { - valueArray.at(k) = extForces.at(eq); - } else if ( ( eq = dof->giveEquationNumber( EModelDefaultPrescribedEquationNumbering() ) ) > 0 ) { - valueArray.at(k) = extForcesP.at(eq); - } - } - //this->getNodalVariableFromPrimaryField(valueArray, dman, tStep, type, region); - vtkPiece.setLoadInNode( i, inode, std :: move(valueArray) ); - } +#endif } } void -VTKXMLExportModule :: writeExternalForces(VTKPiece &vtkPiece) +VTKXMLExportModule::writeExternalForces(VTKPiece &vtkPiece) { for ( int i = 1; i <= externalForcesToExport.giveSize(); i++ ) { UnknownType type = ( UnknownType ) externalForcesToExport.at(i); InternalStateValueType valType = giveInternalStateValueType(type); int ncomponents = giveInternalStateTypeSize(valType); + ( void ) ncomponents; //silence the warning int numNodes = vtkPiece.giveNumberOfNodes(); - std :: string name = std :: string("Load") + __UnknownTypeToString(type); + std::string name = std::string("Load") + __UnknownTypeToString(type); // Header #ifdef __VTK_MODULE - vtkSmartPointer< vtkDoubleArray >varArray = vtkSmartPointer< vtkDoubleArray > :: New(); - varArray->SetName(name); + vtkSmartPointer< vtkDoubleArray >varArray = vtkSmartPointer< vtkDoubleArray >::New(); + varArray->SetName(name.c_str() ); varArray->SetNumberOfComponents(ncomponents); varArray->SetNumberOfTuples(numNodes); for ( int inode = 1; inode <= numNodes; inode++ ) { FloatArray &valueArray = vtkPiece.giveLoadInNode(i, inode); for ( int j = 1; j <= ncomponents; ++j ) { - varArray->SetComponent( inode - 1, j - 1, valueArray.at(j) ); + varArray->SetComponent(inode - 1, j - 1, valueArray.at(j) ); } } this->writeVTKPointData(name.c_str(), varArray); #else - fprintf(this->fileStream, " ", name.c_str(), ncomponents); + this->fileStream << " "; for ( int inode = 1; inode <= numNodes; inode++ ) { FloatArray &valueArray = vtkPiece.giveLoadInNode(i, inode); this->writeVTKPointData(valueArray); } - fprintf(this->fileStream, "\n"); + this->fileStream << "\n"; #endif } } - - - -//---------------------------------------------------- -// Cell vars -//---------------------------------------------------- - void -VTKXMLExportModule :: exportCellVars(VTKPiece &vtkPiece, const IntArray &elems, TimeStep *tStep) -{ - Domain *d = emodel->giveDomain(1); - FloatArray valueArray; - - vtkPiece.setNumberOfCellVarsToExport( cellVarsToExport.giveSize(), elems.giveSize() ); - for ( int field = 1; field <= cellVarsToExport.giveSize(); field++ ) { - InternalStateType type = ( InternalStateType ) cellVarsToExport.at(field); - - for ( int subIndex = 1; subIndex <= elems.giveSize(); ++subIndex ) { - Element *el = d->giveElement( elems.at(subIndex) ); ///@todo should be a pointer to an element in the region /JB - if ( el->giveParallelMode() != Element_local ) { - continue; - } - - this->getCellVariableFromIS(valueArray, el, type, tStep); - vtkPiece.setCellVar(field, subIndex, valueArray); - } - } -} - - -void -VTKXMLExportModule :: getCellVariableFromIS(FloatArray &answer, Element *el, InternalStateType type, TimeStep *tStep) -{ - InternalStateValueType valType = giveInternalStateValueType(type); - int ncomponents = giveInternalStateTypeSize(valType); - - answer.resize(ncomponents); - - switch ( type ) { - // Special scalars - case IST_MaterialNumber: - // commented by bp: do what user wants - //OOFEM_WARNING1("Material numbers are deprecated, outputing cross section number instead..."); - answer.at(1) = ( double ) el->giveMaterial()->giveNumber(); - break; - case IST_CrossSectionNumber: - answer.at(1) = ( double ) el->giveCrossSection()->giveNumber(); - break; - case IST_ElementNumber: - answer.at(1) = ( double ) el->giveNumber(); - break; - case IST_Pressure: ///@todo This case seems redundant, remove? /JB, /// Why this special treatment for pressure? / Mikael - if ( el->giveNumberOfInternalDofManagers() == 1 ) { - //IntArray pmask(1); pmask.at(1) = P_f; - //el->giveInternalDofManager(1)->giveUnknownVector (answer, pmask, VM_Total, tStep); - //answer.at(1) = answer.at(1); - } - - break; - case IST_AbaqusStateVector: - { - // compute cell average from ip values - IntegrationRule *iRule = el->giveDefaultIntegrationRulePtr(); - computeIPAverage(answer, iRule, el, type, tStep); // if element has more than one iRule?? /JB - } - break; - - // Special vectors - case IST_MaterialOrientation_x: - case IST_MaterialOrientation_y: - case IST_MaterialOrientation_z: - { - FloatMatrix rotMat; - int col = 0; - if ( type == IST_MaterialOrientation_x ) { - col = 1; - } else if ( type == IST_MaterialOrientation_y ) { - col = 2; - } else if ( type == IST_MaterialOrientation_z ) { - col = 3; - } - - if ( !el->giveLocalCoordinateSystem(rotMat) ) { - rotMat.resize(3, 3); - rotMat.beUnitMatrix(); - } - - answer.beColumnOf(rotMat, col); - break; - } - - // Export cell data as average from ip's as default - default: - - // compute cell average from ip values - IntegrationRule * iRule = el->giveDefaultIntegrationRulePtr(); - computeIPAverage(answer, iRule, el, type, tStep); // if element has more than one iRule?? /JB - // Reshape the Voigt vectors to include all components (duplicated if necessary, VTK insists on 9 components for tensors.) - /// @todo Is this part necessary now when giveIPValue returns full form? Only need to symmetrize in case of 6 components /JB - /// @todo Some material models aren't exporting values correctly (yet) / Mikael - if ( valType == ISVT_TENSOR_S3 || valType == ISVT_TENSOR_S3E || valType == ISVT_TENSOR_G ) { - FloatArray temp = answer; - this->makeFullTensorForm(answer, temp, valType); - } else if ( valType == ISVT_VECTOR && answer.giveSize() < 3 ) { - answer.resizeWithValues(3); - } else if ( ncomponents != answer.giveSize() ) { // Trying to gracefully handle bad cases, just output zeros. - answer.resizeWithValues(ncomponents); - } - } -} - - -void -VTKXMLExportModule :: writeCellVars(VTKPiece &vtkPiece) +VTKXMLExportModule::writeCellVars(VTKPiece &vtkPiece) { FloatArray valueArray; int numCells = vtkPiece.giveNumberOfCells(); @@ -1862,102 +784,95 @@ VTKXMLExportModule :: writeCellVars(VTKPiece &vtkPiece) InternalStateValueType valType = giveInternalStateValueType(type); int ncomponents = giveInternalStateTypeSize(valType); const char *name = __InternalStateTypeToString(type); + ( void ) name; //silence the warning // Header #ifdef __VTK_MODULE - vtkSmartPointer< vtkDoubleArray >cellVarsArray = vtkSmartPointer< vtkDoubleArray > :: New(); + vtkSmartPointer< vtkDoubleArray >cellVarsArray = vtkSmartPointer< vtkDoubleArray >::New(); cellVarsArray->SetName(name); cellVarsArray->SetNumberOfComponents(ncomponents); cellVarsArray->SetNumberOfTuples(numCells); for ( int ielem = 1; ielem <= numCells; ielem++ ) { valueArray = vtkPiece.giveCellVar(i, ielem); for ( int i = 1; i <= ncomponents; ++i ) { - cellVarsArray->SetComponent( ielem - 1, i - 1, valueArray.at(i) ); + cellVarsArray->SetComponent(ielem - 1, i - 1, valueArray.at(i) ); } } this->writeVTKCellData(name, cellVarsArray); #else - fprintf(this->fileStream, " ", name, ncomponents); + this->fileStream << " "; valueArray.resize(ncomponents); for ( int ielem = 1; ielem <= numCells; ielem++ ) { - valueArray = vtkPiece.giveCellVar(i, ielem); + valueArray = vtkPiece.giveCellVar(type, ielem); this->writeVTKCellData(valueArray); } - fprintf(this->fileStream, "\n"); + this->fileStream << "\n"; #endif - } + + }//end of for } - void -VTKXMLExportModule :: computeIPAverage(FloatArray &answer, IntegrationRule *iRule, Element *elem, InternalStateType isType, TimeStep *tStep) -{ - // Computes the volume average (over an element) for the quantity defined by isType - double gptot = 0.0; - answer.clear(); - FloatArray temp; - if ( iRule ) { - for ( IntegrationPoint *ip : *iRule ) { - elem->giveIPValue(temp, ip, isType, tStep); - gptot += ip->giveWeight(); - answer.add(ip->giveWeight(), temp); - } - - answer.times(1. / gptot); - } -} - - -void -VTKXMLExportModule :: writeVTKCollection() +VTKXMLExportModule::writeVTKCollection() { struct tm *current; time_t now; time(& now); current = localtime(& now); char buff [ 1024 ]; - std :: string fname; + std::string fname; if ( tstep_substeps_out_flag ) { - fname = this->emodel->giveOutputBaseFileName() + ".m" + std :: to_string(this->number) + ".substep.pvd"; + fname = this->emodel->giveOutputBaseFileName() + ".m" + std::to_string(this->number) + ".substep.pvd"; + } else { + fname = this->emodel->giveOutputBaseFileName() + ".m" + std::to_string(this->number) + ".pvd"; + } + + std::ofstream streamP; + if ( pythonExport ) { + streamP = std::ofstream(NULL_DEVICE);//do not write anything } else { - fname = this->emodel->giveOutputBaseFileName() + ".m" + std :: to_string(this->number) + ".pvd"; + streamP = std::ofstream(fname.c_str() ); } - std :: ofstream outfile( fname.c_str() ); + if ( !streamP.good() ) { + OOFEM_ERROR("failed to open file %s", fname.c_str() ); + } sprintf(buff, "\n", current->tm_year + 1900, current->tm_mon + 1, current->tm_mday, current->tm_hour, current->tm_min, current->tm_sec); // outfile << buff; - outfile << "\n\n\n"; + streamP << "\n\n\n"; for ( auto pvd : this->pvdBuffer ) { - outfile << pvd << "\n"; + streamP << pvd << "\n"; } - outfile << "\n"; + streamP << "\n"; - outfile.close(); + if (streamP){ + streamP.close(); + } } void -VTKXMLExportModule :: writeGPVTKCollection() +VTKXMLExportModule::writeGPVTKCollection() { struct tm *current; time_t now; time(& now); current = localtime(& now); char buff [ 1024 ]; - std :: string fname; + std::string fname; if ( tstep_substeps_out_flag ) { - fname = this->emodel->giveOutputBaseFileName() + ".m" + std :: to_string(this->number) + ".substep.gp.pvd"; + fname = this->emodel->giveOutputBaseFileName() + ".m" + std::to_string(this->number) + ".substep.gp.pvd"; } else { - fname = this->emodel->giveOutputBaseFileName() + ".m" + std :: to_string(this->number) + ".gp.pvd"; + fname = this->emodel->giveOutputBaseFileName() + ".m" + std::to_string(this->number) + ".gp.pvd"; } - std :: ofstream outfile( fname.c_str() ); + std::ofstream outfile(fname.c_str() ); sprintf(buff, "\n", current->tm_year + 1900, current->tm_mon + 1, current->tm_mday, current->tm_hour, current->tm_min, current->tm_sec); // outfile << buff; @@ -1969,15 +884,14 @@ VTKXMLExportModule :: writeGPVTKCollection() outfile << "\n"; - outfile.close(); + if (outfile){ + outfile.close(); + } } - - - // Export of composite elements -void VTKXMLExportModule :: exportCompositeElement(VTKPiece &vtkPiece, Element *el, TimeStep *tStep) +void VTKXMLExportModule::exportCompositeElement(VTKPiece &vtkPiece, Element *el, TimeStep *tStep) { VTKXMLExportModuleElementInterface *interface = static_cast< VTKXMLExportModuleElementInterface * >( el->giveInterface(VTKXMLExportModuleElementInterfaceType) ); @@ -1988,7 +902,7 @@ void VTKXMLExportModule :: exportCompositeElement(VTKPiece &vtkPiece, Element *e } } -void VTKXMLExportModule :: exportCompositeElement(std :: vector< VTKPiece > &vtkPieces, Element *el, TimeStep *tStep) +void VTKXMLExportModule::exportCompositeElement(std::vector< VTKPiece > &vtkPieces, Element *el, TimeStep *tStep) { VTKXMLExportModuleElementInterface *interface = static_cast< VTKXMLExportModuleElementInterface * >( el->giveInterface(VTKXMLExportModuleElementInterfaceType) ); @@ -1999,119 +913,111 @@ void VTKXMLExportModule :: exportCompositeElement(std :: vector< VTKPiece > &vtk } } -void -VTKPiece :: clear() -{ - ///@todo Will this give a memory leak? / JB - numCells = 0; - numNodes = 0; - this->connectivity.clear(); - this->elCellTypes.clear(); - this->elOffsets.clear(); - this->elVars.clear(); - this->nodeCoords.clear(); - this->nodeVars.clear(); - this->nodeVarsFromIS.clear(); - this->nodeVarsFromXFEMIS.clear(); -} - - NodalRecoveryModel * -VTKXMLExportModule :: giveSmoother() +VTKXMLExportModule::giveSmoother() { Domain *d = emodel->giveDomain(1); - if ( this->smoother == NULL ) { + if ( !this->smoother ) { this->smoother = classFactory.createNodalRecoveryModel(this->stype, d); } - return this->smoother; + return this->smoother.get(); } NodalRecoveryModel * -VTKXMLExportModule :: givePrimVarSmoother() +VTKXMLExportModule::givePrimVarSmoother() { Domain *d = emodel->giveDomain(1); - if ( this->primVarSmoother == NULL ) { - this->primVarSmoother = classFactory.createNodalRecoveryModel(NodalRecoveryModel :: NRM_NodalAveraging, d); + if ( !this->primVarSmoother ) { + this->primVarSmoother = classFactory.createNodalRecoveryModel(NodalRecoveryModel::NRM_NodalAveraging, d); } - return this->primVarSmoother; + return this->primVarSmoother.get(); } void -VTKXMLExportModule :: exportIntVarsInGpAs(IntArray valIDs, TimeStep *tStep) +VTKXMLExportModule::exportIntVarsInGpAs(IntArray valIDs, TimeStep *tStep) { Domain *d = emodel->giveDomain(1); int nc = 0; + ( void ) nc; //silence the warning FloatArray gc, value; - FILE *stream; + std::ofstream stream; InternalStateType isttype; InternalStateValueType vtype; - std :: string scalars, vectors, tensors; + std::string scalars, vectors, tensors; // output nodes Region By Region int nregions = this->giveNumberOfRegions(); // aka sets // open output stream - std :: string outputFileName = this->giveOutputBaseFileName(tStep) + ".gp.vtu"; - if ( ( stream = fopen(outputFileName.c_str(), "w") ) == NULL ) { - OOFEM_ERROR( "failed to open file %s", outputFileName.c_str() ); + std::string outputFileName = this->giveOutputBaseFileName(tStep) + ".gp.vtu"; + std::ofstream streamG; + if ( pythonExport ) { + streamG = std::ofstream(NULL_DEVICE); + } else { + streamG = std::ofstream(outputFileName); + } + + if ( !streamG.good() ) { + OOFEM_ERROR("failed to open file %s", outputFileName.c_str() ); } - fprintf(stream, "\n"); - fprintf(stream, "\n"); + streamG << "\n"; + streamG << "\n"; /* loop over regions */ for ( int ireg = 1; ireg <= nregions; ireg++ ) { const IntArray &elements = this->giveRegionSet(ireg)->giveElementList(); int nip = 0; for ( int i = 1; i <= elements.giveSize(); i++ ) { - nip += d->giveElement( elements.at(i) )->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints(); + nip += d->giveElement(elements.at(i) )->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints(); } //Create one cell per each GP - fprintf(stream, "\n", nip, nip); - fprintf(stream, "\n "); + streamG << "\n"; + streamG << "\n "; for ( int i = 1; i <= elements.giveSize(); i++ ) { int ielem = elements.at(i); - for ( GaussPoint *gp : *d->giveElement(ielem)->giveDefaultIntegrationRulePtr() ) { - d->giveElement(ielem)->computeGlobalCoordinates( gc, gp->giveNaturalCoordinates() ); + for ( GaussPoint *gp : * d->giveElement(ielem)->giveDefaultIntegrationRulePtr() ) { + d->giveElement(ielem)->computeGlobalCoordinates(gc, gp->giveNaturalCoordinates() ); for ( double c : gc ) { - fprintf(stream, "%e ", c); + ( void ) c; //silence the warning + streamG << scientific << c << " "; } for ( int k = gc.giveSize() + 1; k <= 3; k++ ) { - fprintf(stream, "%e ", 0.0); + streamG << scientific << 0.0 << " "; } } } - fprintf(stream, " \n"); - fprintf(stream, "\n"); - fprintf(stream, "\n"); - fprintf(stream, " "); + streamG << " \n"; + streamG << "\n"; + streamG << "\n"; + streamG << " "; for ( int j = 0; j < nip; j++ ) { - fprintf(stream, "%d ", j); + streamG << j << " "; } - fprintf(stream, " \n"); - fprintf(stream, " "); + streamG << " \n"; + streamG << " "; for ( int j = 1; j <= nip; j++ ) { - fprintf(stream, "%d ", j); + streamG << j << " "; } - fprintf(stream, " \n"); - fprintf(stream, " "); + streamG << " \n"; + streamG << " "; for ( int j = 1; j <= nip; j++ ) { - fprintf(stream, "1 "); + streamG << "1 "; } - fprintf(stream, " \n"); - fprintf(stream, "\n"); + streamG << " \n"; + streamG << "\n"; // prepare the data header for ( int vi = 1; vi <= valIDs.giveSize(); vi++ ) { isttype = ( InternalStateType ) valIDs.at(vi); @@ -2127,12 +1033,12 @@ VTKXMLExportModule :: exportIntVarsInGpAs(IntArray valIDs, TimeStep *tStep) tensors += __InternalStateTypeToString(isttype); tensors.append(" "); } else { - OOFEM_WARNING( "unsupported variable type %s\n", __InternalStateTypeToString(isttype) ); + OOFEM_WARNING("unsupported variable type %s\n", __InternalStateTypeToString(isttype) ); } } // print collected data summary in header - fprintf( stream, "\n", scalars.c_str(), vectors.c_str(), tensors.c_str() ); + streamG << "\n"; scalars.clear(); vectors.clear(); tensors.clear(); @@ -2145,45 +1051,53 @@ VTKXMLExportModule :: exportIntVarsInGpAs(IntArray valIDs, TimeStep *tStep) nc = 1; } else if ( vtype == ISVT_VECTOR ) { nc = 3; + if ( isttype == IST_BeamForceMomentTensor ) { //AS: to make the hack work + nc = 6; + } } else if ( vtype == ISVT_TENSOR_S3 || vtype == ISVT_TENSOR_S3E || vtype == ISVT_TENSOR_G ) { nc = 9; } else { - OOFEM_WARNING( "unsupported variable type %s\n", __InternalStateTypeToString(isttype) ); + OOFEM_WARNING("unsupported variable type %s\n", __InternalStateTypeToString(isttype) ); } - fprintf(stream, " ", __InternalStateTypeToString(isttype), nc); + streamG << " "; for ( int i = 1; i <= elements.giveSize(); i++ ) { int ielem = elements.at(i); // loop over default IRule gps - for ( GaussPoint *gp : *d->giveElement(ielem)->giveDefaultIntegrationRulePtr() ) { + for ( GaussPoint *gp : * d->giveElement(ielem)->giveDefaultIntegrationRulePtr() ) { d->giveElement(ielem)->giveIPValue(value, gp, isttype, tStep); if ( vtype == ISVT_VECTOR ) { - // bp: hack for BeamForceMomentTensor, which should be splitted into force and momentum vectors - if (isttype == IST_BeamForceMomentTensor) { - value.resizeWithValues(6); - } else { - value.resizeWithValues(3); - } + // bp: hack for BeamForceMomentTensor, which should be splitted into force and momentum vectors + if ( isttype == IST_BeamForceMomentTensor ) { + value.resizeWithValues(6); + } else { + value.resizeWithValues(3); + } } else if ( vtype == ISVT_TENSOR_S3 || vtype == ISVT_TENSOR_S3E || vtype == ISVT_TENSOR_G ) { FloatArray help = value; this->makeFullTensorForm(value, help, vtype); } for ( double v : value ) { - fprintf(stream, "%e ", v); + ( void ) v; //silence the warning + streamG << scientific << v << " "; } } // end loop over IPs } // end loop over elements - fprintf(stream, " \n"); + streamG << " \n"; } // end loop over values to be exported - fprintf(stream, "\n\n"); + streamG << "\n\n"; } // end loop over regions - fprintf(stream, "\n"); - fprintf(stream, "\n"); - fclose(stream); + streamG << "\n"; + streamG << "\n"; + if(streamG){ + streamG.close(); + } } + + } // end namespace oofem diff --git a/src/oofemlib/vtkxmlexportmodule.h b/src/oofemlib/vtkxmlexportmodule.h index 1d7395bda..249a14cf3 100644 --- a/src/oofemlib/vtkxmlexportmodule.h +++ b/src/oofemlib/vtkxmlexportmodule.h @@ -35,20 +35,36 @@ #ifndef vtkxmlexportmodule_h #define vtkxmlexportmodule_h -#include "exportmodule.h" +#include "vtkbaseexportmodule.h" #include "intarray.h" #include "nodalrecoverymodel.h" #include "interface.h" #include "internalstatevaluetype.h" #include "integrationrule.h" #include "xfem/xfemmanager.h" - +#include +#include +#include #ifdef __VTK_MODULE #include #include #endif +#ifdef _PYBIND_BINDINGS + #include + #include //Conversion for lists + #include "pybind11/numpy.h" +namespace py = pybind11; +#endif + +#ifdef _WIN32 + #define NULL_DEVICE "NUL:" +#else + #define NULL_DEVICE "/dev/null" +#endif + + #include #include @@ -61,79 +77,12 @@ #define _IFT_VTKXMLExportModule_externalForces "externalforces" #define _IFT_VTKXMLExportModule_ipvars "ipvars" #define _IFT_VTKXMLExportModule_stype "stype" -#define _IFT_VTKXMLExportModule_particleexportflag "particleexportflag" //@} +using namespace std; namespace oofem { class Node; -///@todo Rename this to something like "ExportPiece" and move it to a separate file (it doesn't actually contain anything VTK-specific). -class VTKPiece -{ -public: - VTKPiece() - { - numCells = 0; - numNodes = 0; - } - - void clear(); - - void setNumberOfNodes(int numNodes); - int giveNumberOfNodes() { return this->numNodes; } - - void setNumberOfCells(int numCells); - int giveNumberOfCells() { return this->numCells; } - - void setConnectivity(int cellNum, IntArray &nodes); - IntArray &giveCellConnectivity(int cellNum) { return this->connectivity [ cellNum - 1 ]; } - - void setCellType(int cellNum, int type) { this->elCellTypes.at(cellNum) = type; } - int giveCellType(int cellNum) { return this->elCellTypes.at(cellNum); } - - void setOffset(int cellNum, int offset) { this->elOffsets.at(cellNum) = offset; } - int giveCellOffset(int cellNum) { return this->elOffsets.at(cellNum); } - - void setNodeCoords(int nodeNum, FloatArray &coords); - FloatArray &giveNodeCoords(int nodeNum) { return this->nodeCoords [ nodeNum - 1 ]; } - - void setNumberOfPrimaryVarsToExport(int numVars, int numNodes); - void setNumberOfLoadsToExport(int numVars, int numNodes); - void setNumberOfInternalVarsToExport(int numVars, int numNodes); - void setNumberOfInternalXFEMVarsToExport(int numVars, int numEnrichmentItems, int numNodes); - void setNumberOfCellVarsToExport(int numVars, int numCells); - - void setPrimaryVarInNode(int varNum, int nodeNum, FloatArray valueArray); - FloatArray &givePrimaryVarInNode(int varNum, int nodeNum) { return this->nodeVars [ varNum - 1 ] [ nodeNum - 1 ]; } - - void setLoadInNode(int varNum, int nodeNum, FloatArray valueArray); - FloatArray &giveLoadInNode(int varNum, int nodeNum) { return this->nodeLoads [ varNum - 1 ] [ nodeNum - 1 ]; } - - void setInternalVarInNode(int varNum, int nodeNum, FloatArray valueArray); - FloatArray &giveInternalVarInNode(int varNum, int nodeNum) { return this->nodeVarsFromIS [ varNum - 1 ] [ nodeNum - 1 ]; } - - void setInternalXFEMVarInNode(int varNum, int eiNum, int nodeNum, FloatArray valueArray); - FloatArray &giveInternalXFEMVarInNode(int varNum, int eiNum, int nodeNum) { return this->nodeVarsFromXFEMIS [ varNum - 1 ] [ eiNum - 1 ] [ nodeNum - 1 ]; } - - void setCellVar(int varNum, int cellNum, FloatArray valueArray); - FloatArray &giveCellVar(int field, int cellNum) { return this->elVars [ field - 1 ] [ cellNum - 1 ]; } - - -private: - int numCells; - int numNodes; - IntArray elCellTypes; - IntArray elOffsets; - std :: vector< FloatArray >nodeCoords; // all the nodes in the piece [node][coords] - std :: vector< IntArray >connectivity; // cell connectivity [cell][nodes] - std :: vector< std :: vector< FloatArray > >nodeVars; // [field][node][valArray] - std :: vector< std :: vector< FloatArray > >nodeLoads; // [field][node][valArray] - std :: vector< std :: vector< FloatArray > >nodeVarsFromIS; // [field][node][valArray] - std :: vector< std :: vector< std :: vector< FloatArray > > >nodeVarsFromXFEMIS; // [field][ei][node][valArray] - std :: vector< std :: vector< FloatArray > >elVars; // [el][field][valArray] -}; - - /** * Represents VTK (Visualization Toolkit) export module. It uses VTK (.vtu) file format, Unstructured grid dataset. * The export of data is done on Region By Region basis, possibly taking care about possible nonsmooth character of @@ -141,7 +90,7 @@ class VTKPiece * Each region is usually exported as a single piece. When region contains composite cells, these are assumed to be * exported in individual subsequent pieces after the default one for the particular region. */ -class OOFEM_EXPORT VTKXMLExportModule : public ExportModule +class OOFEM_EXPORT VTKXMLExportModule : public VTKBaseExportModule { protected: /// List of InternalStateType values, identifying the selected vars for export. @@ -155,46 +104,43 @@ class OOFEM_EXPORT VTKXMLExportModule : public ExportModule /// List of internal variables to export directly in Integration Points (no smoothing to nodes) IntArray ipInternalVarsToExport; - /// Map from Voigt to full tensor. - static IntArray redToFull; + /// Smoother type. - NodalRecoveryModel :: NodalRecoveryModelType stype; + NodalRecoveryModel::NodalRecoveryModelType stype; /// Smoother. - NodalRecoveryModel *smoother; + std::unique_ptr< NodalRecoveryModel >smoother; /// Smoother for primary variables. - NodalRecoveryModel *primVarSmoother; - - /// particle export flag - bool particleExportFlag; + std::unique_ptr< NodalRecoveryModel >primVarSmoother; /// Buffer for earlier time steps exported to *.pvd file. - std :: list< std :: string >pvdBuffer; + std::list< std::string >pvdBuffer; /// Buffer for earlier time steps with gauss points exported to *.gp.pvd file. - std :: list< std :: string >gpPvdBuffer; + std::list< std::string >gpPvdBuffer; + public: /// Constructor. Creates empty Output Manager. By default all components are selected. - VTKXMLExportModule(int n, EngngModel * e); + VTKXMLExportModule(int n, EngngModel *e); /// Destructor virtual ~VTKXMLExportModule(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void doOutput(TimeStep *tStep, bool forcedOutput = false); - virtual void initialize(); - virtual void terminate(); - virtual const char *giveClassName() const { return "VTKXMLExportModule"; } + void initializeFrom(InputRecord &ir) override; + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; + void initialize() override; + void terminate() override; + const char *giveClassName() const override { return "VTKXMLExportModule"; } /** * Prints point data header. */ - void exportPointDataHeader(FILE *fileStream, TimeStep *tStep); - void giveDataHeaders(std :: string &pointHeader, std :: string &cellHeader); // returns the headers + void exportPointDataHeader(std::ofstream fileStream, TimeStep *tStep); + virtual void giveDataHeaders(std::string &pointHeader, std::string &cellHeader); // returns the headers /// Returns the internal smoother. NodalRecoveryModel *giveSmoother(); /// Returns the smoother for primary variables (nodal averaging). NodalRecoveryModel *givePrimVarSmoother(); - + #ifdef __VTK_MODULE vtkSmartPointer< vtkUnstructuredGrid >fileStream; @@ -204,124 +150,53 @@ class OOFEM_EXPORT VTKXMLExportModule : public ExportModule vtkSmartPointer< vtkDoubleArray >intVarArray; vtkSmartPointer< vtkDoubleArray >primVarArray; #else - FILE *fileStream; + std::ofstream fileStream; #endif VTKPiece defaultVTKPiece; - std :: vector < VTKPiece > defaultVTKPieces; - - /** - * Computes a cell average of an InternalStateType varible based on the weights - * in the integrationpoints (=> volume/area/length average) - */ - static void computeIPAverage(FloatArray &answer, IntegrationRule *iRule, Element *elem, InternalStateType isType, TimeStep *tStep); - + std::vector< VTKPiece >defaultVTKPieces; + + VTKPiece& getVTKPieces() {return this->defaultVTKPiece;} protected: - /// Gives the full form of given symmetrically stored tensors, missing components are filled with zeros. - static void makeFullTensorForm(FloatArray &answer, const FloatArray &reducedForm, InternalStateValueType vtype); - /// Returns the filename for the given time step. - std :: string giveOutputFileName(TimeStep *tStep); + std::string giveOutputFileName(TimeStep *tStep); /// Returns the output stream for given solution step. - FILE *giveOutputStream(TimeStep *tStep); - /** - * Returns corresponding element cell_type. - * Some common element types are supported, others can be supported via interface concept. - */ - int giveCellType(Element *element); - /** - * Returns number of nodes corresponding to cell type - */ - int giveNumberOfNodesPerCell(int cellType); - /** - * Returns the element cell geometry. - */ - void giveElementCell(IntArray &answer, Element *elem); - - - /** - * Export internal variables by smoothing. - */ - void exportIntVars(VTKPiece &piece, IntArray &mapG2L, IntArray &mapL2G, int ireg, TimeStep *tStep); + std::ofstream giveOutputStream(TimeStep *tStep); - - /** - * Export primary variables. - */ - void exportPrimaryVars(VTKPiece &piece, IntArray &mapG2L, IntArray &mapL2G, int region, TimeStep *tStep); - - /** - * Export external forces. - */ - void exportExternalForces(VTKPiece &piece, IntArray &mapG2L, IntArray &mapL2G, int region, TimeStep *tStep); - - - // Tries to find the value of a primary field on the given DofManager. - // Some elements have different interpolation of some fields, and requires some additional code to compute node values (if available). - - void getNodalVariableFromPrimaryField(FloatArray &answer, DofManager *dman, TimeStep *tStep, UnknownType type, int ireg); - // - - // - // Exports single internal variable by smoothing. - // - - virtual void setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, int region); void writeIntVars(VTKPiece &vtkPiece); void writeXFEMVars(VTKPiece &vtkPiece); void writePrimaryVars(VTKPiece &vtkPiece); void writeCellVars(VTKPiece &vtkPiece); void writeExternalForces(VTKPiece &vtkPiece); - /** - @return true if piece is not empty and thus written - */ - bool writeVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep); - - - void exportXFEMVarAs(XFEMStateType xfemstype, IntArray &mapG2L, IntArray &mapL2G, int regionDofMans, int ireg, TimeStep *tStep, EnrichmentItem *ei); - - void getNodalVariableFromIS(FloatArray &answer, Node *node, TimeStep *tStep, InternalStateType type, int ireg); - - void getNodalVariableFromXFEMST(FloatArray &answer, Node *node, TimeStep *tStep, XFEMStateType xfemstype, int ireg, EnrichmentItem *ei); - - - // Exports cell variables (typically internal variables). - // - - void exportCellVars(VTKPiece &piece, const IntArray &elems, TimeStep *tStep); - - // - // Exports a single cell variable (typically an internal variable). - // - void getCellVariableFromIS(FloatArray &answer, Element *el, InternalStateType type, TimeStep *tStep); + * Writes Piece header+geometry + * @return true if piece is not empty and thus written + */ + bool writeVTKPieceEpilog(VTKPiece &vtkPiece, TimeStep *tStep); + /** + * Writes Piece variables + * @return true if piece is not empty and thus written + */ + bool writeVTKPieceVariables(VTKPiece &vtkPiece, TimeStep *tStep); + /** + * Writes piece epiloque + * @return true if piece is not empty and thus written + */ + bool writeVTKPieceProlog(VTKPiece &vtkPiece, TimeStep *tStep); /** * Exports given internal variables directly in integration points (raw data, no smoothing) * @param valIDs the UnknownType values identifying the internal variables to export * @param tStep solution step */ void exportIntVarsInGpAs(IntArray valIDs, TimeStep *tStep); - - /** - * Assembles the region node map. Also computes the total number of nodes in region. - * The region are numbered starting from offset+1. - * If mode == 0 then regionNodalNumbers is array with mapping from global numbering to local region numbering. - * The i-th value contains the corresponding local region number (or zero, if global number is not in region). - * If mode == 1 then regionNodalNumbers is array with mapping from local to global numbering. - * The i-th value contains the corresponding global node number. - */ - virtual int initRegionNodeNumbering(IntArray &mapG2L, IntArray &mapL2G, - int ®ionDofMans, - int &totalcells, - Domain *domain, TimeStep *tStep, int reg); /** * Writes a VTK collection file where time step data is stored. */ void writeVTKCollection(); - + /// Writes a VTK collection file for Gauss points. void writeGPVTKCollection(); @@ -338,15 +213,10 @@ class OOFEM_EXPORT VTKXMLExportModule : public ExportModule #endif // Export of composite elements (built up from several subcells) - - bool isElementComposite(Element *elem); /// Returns true if element geometry type is composite (not a single cell). void exportCompositeElement(VTKPiece &vtkPiece, Element *el, TimeStep *tStep); void exportCompositeElement(std::vector< VTKPiece > &vtkPieces, Element *el, TimeStep *tStep); }; - - - /** * Elements with geometry defined as EGT_Composite are exported using individual pieces. * The VTKXMLExportModuleElementInterface serves for this purpose, defining abstract @@ -355,9 +225,9 @@ class OOFEM_EXPORT VTKXMLExportModule : public ExportModule */ class OOFEM_EXPORT VTKXMLExportModuleElementInterface : public Interface { + public: VTKXMLExportModuleElementInterface() : Interface() { } - virtual const char *giveClassName() const { return "VTKXMLExportModuleElementInterface"; } virtual void giveCompositeExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep) { } virtual void giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep) { } }; diff --git a/src/oofemlib/vtkxmllatticeexportmodule.C b/src/oofemlib/vtkxmllatticeexportmodule.C new file mode 100644 index 000000000..d70c73a05 --- /dev/null +++ b/src/oofemlib/vtkxmllatticeexportmodule.C @@ -0,0 +1,860 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "vtkxmllatticeexportmodule.h" +#include "element.h" +#include "gausspoint.h" +#include "timestep.h" +#include "engngm.h" +#include "node.h" +#include "materialinterface.h" +#include "mathfem.h" +#include "cltypes.h" +#include "material.h" +#include "classfactory.h" +#include "crosssection.h" +#include "dof.h" + +#ifdef __SM_MODULE + #include "../sm/Elements/LatticeElements/latticestructuralelement.h" + #include "../sm/Elements/LatticeElements/lattice2dboundary.h" + #include "../sm/Elements/LatticeElements/lattice3dboundary.h" + #include "../sm/Elements/LatticeElements/latticelink3dboundary.h" +#endif + +#ifdef __TM_MODULE + #include "../tm/Elements/LatticeElements/latticetransportelement.h" +#endif + + +namespace oofem { +REGISTER_ExportModule(VTKXMLLatticeExportModule) + +VTKXMLLatticeExportModule::VTKXMLLatticeExportModule(int n, EngngModel *e) : VTKXMLExportModule(n, e) +{ + //Find out the element type and elemNodes +} + + +VTKXMLLatticeExportModule::~VTKXMLLatticeExportModule() +{} + + +void +VTKXMLLatticeExportModule::initializeFrom(InputRecord &ir) +{ + VTKXMLExportModule::initializeFrom(ir); + this->crossSectionExportFlag = false; + IR_GIVE_OPTIONAL_FIELD(ir, this->crossSectionExportFlag, _IFT_VTKXMLLatticeExportModule_cross); +} + +std::string +VTKXMLLatticeExportModule::giveOutputFileNameCross(TimeStep *tStep) +{ + return this->giveOutputBaseFileName(tStep) + ".cross.vtu"; +} + +std::ofstream +VTKXMLLatticeExportModule::giveOutputStreamCross(TimeStep *tStep) +{ + std::string fileName = giveOutputFileNameCross(tStep); + std::ofstream streamC; + + if ( pythonExport ) { + streamC = std::ofstream(NULL_DEVICE);//do not write anything + } else { + streamC = std::ofstream(fileName); + } + + if ( !streamC.good() ) { + OOFEM_ERROR("failed to open file %s", fileName.c_str() ); + } + + streamC.fill('0');//zero padding + return streamC; +} + +void +VTKXMLLatticeExportModule::giveSwitches(IntArray &answer, int location) { + answer.resize(3); + answer.zero(); + int counter = 1; + for ( int x = -1; x < 2; x++ ) { + for ( int y = -1; y < 2; y++ ) { + for ( int z = -1; z < 2; z++ ) { + if ( !( z == 0 && y == 0 && x == 0 ) ) { + if ( counter == location ) { + answer(0) = x; + answer(1) = y; + answer(2) = z; + } + counter++; + } + } + } + } + + return; +} + +void +VTKXMLLatticeExportModule::setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, Set ®ion) +{ + // Stores all neccessary data (of a region) in a VTKPiece so it can be exported later. + + Domain *d = emodel->giveDomain(1); + Element *elem; + + int nnodes = d->giveNumberOfDofManagers(); + + // Assemble local->global and global->local region map and get number of + // single cells to process, the composite cells exported individually. + this->initRegionNodeNumbering(vtkPiece, d, tStep, region); + const IntArray& mapG2L = vtkPiece.getMapG2L(); + const IntArray& mapL2G = vtkPiece.getMapL2G(); + const int numNodes = vtkPiece.giveNumberOfNodes(); + const int numRegionEl = vtkPiece.giveNumberOfCells(); + + + + if ( numNodes > 0 && numRegionEl > 0 ) { + // Export nodes as vtk vertices + vtkPiece.setNumberOfNodes(numNodes); + for ( int inode = 1; inode <= numNodes; inode++ ) { + if ( mapL2G.at(inode) <= nnodes && mapL2G.at(inode) != 0 ) { //DofManagers in domain (input file) + const auto &coords = d->giveNode(mapL2G.at(inode) )->giveCoordinates(); + vtkPiece.setNodeCoords(inode, coords); + } else if ( mapL2G.at(inode) > nnodes && mapL2G.at(inode) <= numNodes && mapL2G.at(inode) != 0 ) { //extra image nodes + FloatArray helpArray(3); + helpArray.at(1) = uniqueNodeTable.at(mapL2G.at(inode), 1); + helpArray.at(2) = uniqueNodeTable.at(mapL2G.at(inode), 2); + helpArray.at(3) = uniqueNodeTable.at(mapL2G.at(inode), 3); + vtkPiece.setNodeCoords(inode, helpArray); + } else { + FloatArray helpArray(3); + helpArray.zero(); + vtkPiece.setNodeCoords(inode, helpArray); + } + } + + + //------------------------------------------- + // Export all the cell data for the piece + //------------------------------------------- + IntArray cellNodes; + vtkPiece.setNumberOfCells(numRegionEl); + + int offset = 0; + int cellNum = 0; + IntArray elems = region.giveElementList(); + int helpCounter = 0; + for ( int ei = 1; ei <= elems.giveSize(); ei++ ) { + int elNum = elems.at(ei); + elem = d->giveElement(elNum); + + // Skip elements that: + // are inactivated or of composite type ( these are exported individually later) + if ( this->isElementComposite(elem) || !elem->isActivated(tStep) ) { + continue; + } + + if ( elem->giveParallelMode() != Element_local ) { + continue; + } + + cellNum++; + + // Set the connectivity +#ifdef __SM_MODULE + if ( dynamic_cast< Lattice3dBoundary * >( elem ) || dynamic_cast< LatticeLink3dBoundary * >( elem ) || dynamic_cast< Lattice2dBoundary * >( elem ) ) { + cellNodes.resize(2); + IntArray loc = elem->giveLocation(); + for ( int ielnode = 1; ielnode <= 2; ielnode++ ) { + if ( loc.at(ielnode) != 0 ) { + helpCounter++; + cellNodes.at(ielnode) = regionToUniqueMap.at(nnodes + helpCounter); + } else { + cellNodes.at(ielnode) = elem->giveNode(ielnode)->giveNumber(); + } + } + } else { //Standard case +#endif + this->giveElementCell(cellNodes, elem); +#ifdef __SM_MODULE + } +#endif + // Map from global to local node numbers for the current piece + int numElNodes = cellNodes.giveSize(); + + + IntArray connectivity(numElNodes); + for ( int i = 1; i <= numElNodes; i++ ) { + connectivity.at(i) = mapG2L.at(cellNodes.at(i) ); + } + + vtkPiece.setConnectivity(cellNum, connectivity); + + vtkPiece.setCellType(cellNum, this->giveCellType(elem) ); // VTK cell type + + offset += numElNodes; + vtkPiece.setOffset(cellNum, offset); + } + } // end of default piece for simple geometry elements +} + + +void +VTKXMLLatticeExportModule::setupVTKPieceCross(VTKPiece &vtkPieceCross, TimeStep *tStep, Set& region) +{ + // Stores all neccessary data (of a region) in a VTKPiece so it can be exported later. + + Domain *domain = emodel->giveDomain(1); + + IntArray elements = region.giveElementList(); + int numberOfElements = elements.giveSize(); + + //Loop over the elements and get crossSectionNodes + int numberOfCrossSectionNodes = 0; + + IntArray crossSectionTable; + crossSectionTable.resize(numberOfElements); + int numberOfNodes = 0; + for ( int ie = 1; ie <= numberOfElements; ie++ ) { + if ( dynamic_cast< LatticeStructuralElement * >( domain->giveElement(elements.at(ie) ) ) ) { + numberOfCrossSectionNodes = ( static_cast< LatticeStructuralElement * >( domain->giveElement(elements.at(ie) ) ) )->giveNumberOfCrossSectionNodes(); + } else if ( dynamic_cast< LatticeTransportElement * >( domain->giveElement(elements.at(ie) ) ) ) { + numberOfCrossSectionNodes = ( static_cast< LatticeTransportElement * >( domain->giveElement(elements.at(ie) ) ) )->giveNumberOfCrossSectionNodes(); + } + crossSectionTable.at(ie) = numberOfCrossSectionNodes; + numberOfNodes += numberOfCrossSectionNodes; + } + + FloatMatrix nodeTable; + nodeTable.resize(numberOfNodes, 3); + + FloatArray crossSectionCoordinates; + FloatArray coords(3); + + //Store node coordinates in table + int nodeCounter = 0; + for ( int ie = 1; ie <= elements.giveSize(); ie++ ) { + if ( dynamic_cast< LatticeStructuralElement * >( domain->giveElement(elements.at(ie) ) ) ) { + numberOfCrossSectionNodes = ( static_cast< LatticeStructuralElement * >( domain->giveElement(elements.at(ie) ) ) )->giveNumberOfCrossSectionNodes(); + ( static_cast< LatticeStructuralElement * >( domain->giveElement(elements.at(ie) ) ) )->giveCrossSectionCoordinates(crossSectionCoordinates); + } else if ( dynamic_cast< LatticeTransportElement * >( domain->giveElement(elements.at(ie) ) ) ) { + numberOfCrossSectionNodes = ( static_cast< LatticeTransportElement * >( domain->giveElement(elements.at(ie) ) ) )->giveNumberOfCrossSectionNodes(); + ( static_cast< LatticeTransportElement * >( domain->giveElement(elements.at(ie) ) ) )->giveCrossSectionCoordinates(crossSectionCoordinates); + } + + for ( int is = 0; is < numberOfCrossSectionNodes; is++ ) { + nodeCounter++; + nodeTable.at(nodeCounter, 1) = crossSectionCoordinates.at(3 * is + 1); + nodeTable.at(nodeCounter, 2) = crossSectionCoordinates.at(3 * is + 2); + nodeTable.at(nodeCounter, 3) = crossSectionCoordinates.at(3 * is + 3); + } + } + + if ( numberOfNodes > 0 && numberOfElements > 0 ) { + // Export nodes as vtk vertices + vtkPieceCross.setNumberOfNodes(numberOfNodes); + for ( int inode = 1; inode <= numberOfNodes; inode++ ) { + coords.at(1) = nodeTable.at(inode, 1); + coords.at(2) = nodeTable.at(inode, 2); + coords.at(3) = nodeTable.at(inode, 3); + vtkPieceCross.setNodeCoords(inode, coords); + } + } + + + //------------------------------------------- + // Export all the cell data for the piece + //------------------------------------------- + IntArray connectivity; + vtkPieceCross.setNumberOfCells(numberOfElements); + int numElNodes; + + int offset = 0; + for ( int ei = 1; ei <= numberOfElements; ei++ ) { + numElNodes = crossSectionTable.at(ei); + + connectivity.resize(numElNodes); + for ( int i = 1; i <= numElNodes; i++ ) { + connectivity.at(i) = offset + i; + } + vtkPieceCross.setConnectivity(ei, connectivity); + + vtkPieceCross.setCellType(ei, 7); + offset += numElNodes; + vtkPieceCross.setOffset(ei, offset); + } + + this->exportCellVars(vtkPieceCross, region, cellVarsToExport, tStep); +} + + +void +VTKXMLLatticeExportModule::doOutput(TimeStep *tStep, bool forcedOutput) +{ + this->doOutputNormal(tStep, forcedOutput); + if ( crossSectionExportFlag ) { + this->doOutputCross(tStep, forcedOutput); + } + this->defaultVTKPiece.clear(); + +} + + +void +VTKXMLLatticeExportModule::doOutputCross(TimeStep *tStep, bool forcedOutput) +{ + if ( !( testTimeStepOutput(tStep) || forcedOutput ) ) { + return; + } + + this->fileStreamCross = this->giveOutputStreamCross(tStep); + struct tm *current; + time_t now; + time(& now); + current = localtime(& now); + + this->fileStreamCross << "\n"; + this->fileStreamCross << "\n"; + this->fileStreamCross << "\n"; + + int nPiecesToExport = this->giveNumberOfRegions(); //old name: region, meaning: sets + int anyPieceNonEmpty = 0; + + for ( int pieceNum = 1; pieceNum <= nPiecesToExport; pieceNum++ ) { + Set* region = this->giveRegionSet(pieceNum); + // Fills a data struct (VTKPiece) with all the necessary data. + this->setupVTKPieceCross(this->defaultVTKPieceCross, tStep, *region); + + // Write the VTK piece to file. + anyPieceNonEmpty += this->writeVTKPieceCross(this->defaultVTKPieceCross, tStep); + this->defaultVTKPieceCross.clear(); + } + + + if ( anyPieceNonEmpty == 0 ) { + // write empty piece, Otherwise ParaView complains if the whole vtu file is without + this->fileStreamCross << "\n"; + this->fileStreamCross << "\n \n\n"; + this->fileStreamCross << "\n"; + } + + this->fileStreamCross << "\n"; + this->fileStreamCross.close(); +} + + +void +VTKXMLLatticeExportModule::doOutputNormal(TimeStep *tStep, bool forcedOutput) +{ + if ( !( testTimeStepOutput(tStep) || forcedOutput ) ) { + return; + } + + this->fileStream = this->giveOutputStream(tStep); + struct tm *current; + time_t now; + time(& now); + current = localtime(& now); + + this->fileStream << "\n"; + + this->fileStream << "\n"; + this->fileStream << "\n"; + + this->giveSmoother(); // make sure smoother is created, Necessary? If it doesn't exist it is created /JB + + int nPiecesToExport = this->giveNumberOfRegions(); //old name: region, meaning: sets + int anyPieceNonEmpty = 0; + + NodalRecoveryModel *smoother = giveSmoother(); + NodalRecoveryModel *primVarSmoother = givePrimVarSmoother(); + + for ( int pieceNum = 1; pieceNum <= nPiecesToExport; pieceNum++ ) { + // Fills a data struct (VTKPiece) with all the necessary data. + Set *region = this->giveRegionSet(pieceNum); + this->setupVTKPiece(this->defaultVTKPiece, tStep, *region); + this->writeVTKPieceProlog(this->defaultVTKPiece, tStep); + // Export primary, internal and XFEM variables as nodal quantities + this->exportPrimaryVars(this->defaultVTKPiece, *region, primaryVarsToExport, *primVarSmoother, tStep); + this->exportIntVars(this->defaultVTKPiece, *region, internalVarsToExport, *smoother, tStep); + //const IntArray &elements = region.giveElementList(); + this->exportCellVars(this->defaultVTKPiece, *region, cellVarsToExport, tStep); + // Write the VTK piece to file. + anyPieceNonEmpty += this->writeVTKPieceVariables(this->defaultVTKPiece, tStep); + this->writeVTKPieceEpilog(this->defaultVTKPiece, tStep); + } + + /* + * Output all composite elements - one piece per composite element + * Each element is responsible of setting up a VTKPiece which can then be exported + */ + Domain *d = emodel->giveDomain(1); + + for ( int pieceNum = 1; pieceNum <= nPiecesToExport; pieceNum++ ) { + const IntArray &elements = this->giveRegionSet(pieceNum)->giveElementList(); + for ( int i = 1; i <= elements.giveSize(); i++ ) { + Element *el = d->giveElement(elements.at(i) ); + if ( this->isElementComposite(el) ) { + if ( el->giveParallelMode() != Element_local ) { + continue; + } + + //this->exportCompositeElement(this->defaultVTKPiece, el, tStep); + this->exportCompositeElement(this->defaultVTKPieces, el, tStep); + + for ( int j = 0; j < ( int ) this->defaultVTKPieces.size(); j++ ) { + this->writeVTKPieceProlog(this->defaultVTKPieces[j], tStep); + anyPieceNonEmpty += this->writeVTKPieceVariables(this->defaultVTKPieces [ j ], tStep); + this->writeVTKPieceEpilog(this->defaultVTKPieces[j], tStep); + } + } + } + } // end loop over composite elements + + if ( anyPieceNonEmpty == 0 ) { + // write empty piece, Otherwise ParaView complains if the whole vtu file is without + this->fileStream << "\n"; + this->fileStream << "\n \n\n"; + this->fileStream << "\n"; + } + + this->fileStream << "\n"; + this->fileStream.close(); +} + + + + +int +VTKXMLLatticeExportModule::initRegionNodeNumbering(VTKPiece& vtkPiece, Domain *domain, TimeStep *tStep, Set& region) +{ + int nnodes = domain->giveNumberOfDofManagers(); + int elementNode, node; + int currOffset = 1; + Element *element; + + int regionDofMans = 0; + int regionSingleCells = 0; + + IntArray elements = region.giveElementList(); + + int extraNodes = 0.; + for ( int ie = 1; ie <= elements.giveSize(); ie++ ) { + element = domain->giveElement(elements.at(ie) ); + +#ifdef __SM_MODULE + if ( dynamic_cast< Lattice3dBoundary * >( element ) || dynamic_cast< LatticeLink3dBoundary * >( element ) || dynamic_cast< Lattice2dBoundary * >( element ) ) { + IntArray loc = element->giveLocation(); + for ( int ielnode = 1; ielnode <= 2; ielnode++ ) { + if ( loc.at(ielnode) != 0 ) { + extraNodes++; + } + } + } +#endif + } + IntArray& regionG2LNodalNumbers = vtkPiece.getMapG2L(); + IntArray& regionL2GNodalNumbers = vtkPiece.getMapL2G(); + + regionG2LNodalNumbers.resize(nnodes + extraNodes); + regionG2LNodalNumbers.zero(); + + periodicMap.resize(nnodes + extraNodes); + regionToUniqueMap.resize(nnodes + extraNodes); + locationMap.resize(nnodes + extraNodes); + + uniqueNodeTable.resize(nnodes + extraNodes, 3); + uniqueNodeTable.zero(); + + int totalNodes = 0; + int uniqueNodes = 0; + + for ( int ie = 1; ie <= elements.giveSize(); ie++ ) { + int ielem = elements.at(ie); + element = domain->giveElement(ielem); + + if ( this->isElementComposite(element) ) { + continue; // composite cells exported individually + } + + if ( !element->isActivated(tStep) ) { //skip inactivated elements + continue; + } + + if ( element->giveParallelMode() != Element_local ) { + continue; + } + + regionSingleCells++; + elemNodes = element->giveNumberOfNodes(); + +#ifdef __SM_MODULE + if ( dynamic_cast< Lattice3dBoundary * >( element ) || dynamic_cast< LatticeLink3dBoundary * >( element ) || dynamic_cast< Lattice2dBoundary * >( element ) ) { + elemNodes = 2; + } +#endif + + for ( elementNode = 1; elementNode <= elemNodes; elementNode++ ) { +#ifdef __SM_MODULE + if ( dynamic_cast< Lattice3dBoundary * >( element ) || dynamic_cast< LatticeLink3dBoundary * >( element ) || dynamic_cast< Lattice2dBoundary * >( element ) ) { //beam elements - only unique nodes + IntArray loc = element->giveLocation(); + FloatArray nodeCoords; + if ( loc.at(elementNode) != 0 ) { //boundary element with mirrored node + totalNodes++; + regionDofMans++; + regionG2LNodalNumbers.at(nnodes + totalNodes) = 1; + node = element->giveNode(elementNode)->giveNumber(); + if ( regionG2LNodalNumbers.at(node) == 0 ) { // assign new number + /* mark for assignment. This is done later, as it allows to preserve + * natural node numbering. + */ + regionG2LNodalNumbers.at(node) = 1; + regionDofMans++; + } + if ( regionG2LNodalNumbers.at(nnodes) == 0 ) { + regionG2LNodalNumbers.at(nnodes) = 1; + regionDofMans++; + } + + periodicMap.at(nnodes + totalNodes) = node; + locationMap.at(nnodes + totalNodes) = loc.at(elementNode); + + element->recalculateCoordinates(elementNode, nodeCoords); + + //get only the unique nodes + int repeatFlag = 0; + for ( int j = nnodes + 1; j <= nnodes + uniqueNodes; j++ ) { + double dx = fabs(uniqueNodeTable.at(j, 1) - nodeCoords.at(1) ); + double dy = fabs(uniqueNodeTable.at(j, 2) - nodeCoords.at(2) ); + double dz = fabs(uniqueNodeTable.at(j, 3) - nodeCoords.at(3) ); + if ( dx < 1e-9 && dy < 1e-9 && dz < 1e-9 ) {//node already present + repeatFlag++; + regionToUniqueMap.at(nnodes + totalNodes) = j; + } + } + + if ( repeatFlag == 0 ) {//new unique node + uniqueNodes++; + uniqueNodeTable.at(nnodes + uniqueNodes, 1) = nodeCoords.at(1); + uniqueNodeTable.at(nnodes + uniqueNodes, 2) = nodeCoords.at(2); + uniqueNodeTable.at(nnodes + uniqueNodes, 3) = nodeCoords.at(3); + regionToUniqueMap.at(nnodes + totalNodes) = nnodes + uniqueNodes; + } + } + } else { //regular element +#endif + node = element->giveNode(elementNode)->giveNumber(); + if ( regionG2LNodalNumbers.at(node) == 0 ) { // assign new number + /* mark for assignment. This is done later, as it allows to preserve + * natural node numbering. + */ + regionG2LNodalNumbers.at(node) = 1; + regionDofMans++; + } +#ifdef __SM_MODULE + } +#endif + } + } + + uniqueNodeTable.resizeWithData(nnodes + uniqueNodes, 3); + regionDofMans = nnodes + uniqueNodes; + vtkPiece.setNumberOfNodes(regionDofMans); + vtkPiece.setNumberOfCells(regionSingleCells); + + regionG2LNodalNumbers.resizeWithValues(regionDofMans); + regionL2GNodalNumbers.resize(regionDofMans); + + for ( int i = 1; i <= regionDofMans; i++ ) { + if ( regionG2LNodalNumbers.at(i) ) { + regionG2LNodalNumbers.at(i) = currOffset++; + regionL2GNodalNumbers.at(regionG2LNodalNumbers.at(i) ) = i; + } + } + return 1; +} + + +void +VTKXMLLatticeExportModule::exportPrimaryVars(VTKPiece &vtkPiece, Set& region, IntArray& primaryVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep) +{ + Domain *d = emodel->giveDomain(1); + int nnodes = d->giveNumberOfDofManagers(); + FloatArray valueArray; + smoother.clear(); // Makes sure primary smoother is up-to-date with potentially new mesh. + + //const IntArray& mapG2L = vtkPiece.getMapG2L(); + const IntArray& mapL2G = vtkPiece.getMapL2G(); + + vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport, mapL2G.giveSize() ); + + //Get the macroscopic field (deformation gradients, curvatures etc.) + DofManager *controlNode = d->giveNode(nnodes); //assuming the control node is last + IntArray dofIdArray; + controlNode->giveCompleteMasterDofIDArray(dofIdArray); + + FloatArray macroField(controlNode->giveNumberOfDofs() ); + for ( int j = 1; j <= controlNode->giveNumberOfDofs(); j++ ) { + macroField.at(j) = controlNode->giveDofWithID(dofIdArray.at(j) )->giveUnknown(VM_Total, tStep); + } + + //Get unit cell size + const auto unitCellSize = controlNode->giveCoordinates(); + + for ( int i = 1, n = primaryVarsToExport.giveSize(); i <= n; i++ ) { + UnknownType type = ( UnknownType ) primaryVarsToExport.at(i); + + for ( int inode = 1; inode <= mapL2G.giveSize(); inode++ ) { + if ( inode <= nnodes && mapL2G.at(inode) <= nnodes && mapL2G.at(inode) != 0 ) { //no special treatment for master nodes + DofManager *dman = d->giveNode(mapL2G.at(inode) ); + + this->getNodalVariableFromPrimaryField(valueArray, dman, tStep, type, region, smoother); + vtkPiece.setPrimaryVarInNode(type, inode, std::move(valueArray) ); + } else { //special treatment for image nodes + //find the periodic node, enough to find the first occurrence + int pos = 0; + if ( mapL2G.at(inode) != 0 ) { + pos = regionToUniqueMap.findFirstIndexOf(mapL2G.at(inode) ); + } + if ( pos ) { + DofManager *dman = d->giveNode(periodicMap.at(pos) ); + IntArray switches; + giveSwitches(switches, locationMap.at(pos) ); + //get the master unknown + FloatArray helpArray; + this->getNodalVariableFromPrimaryField(helpArray, dman, tStep, type, region, smoother); + //recalculate the image unknown + if ( type == DisplacementVector ) { + if ( dofIdArray.giveSize() == 3 && dofIdArray.at(1) == E_xx && dofIdArray.at(2) == E_yy && dofIdArray.at(3) == G_xy ) { //Macroscale: 2D solid using Voigt notation + valueArray.resize(helpArray.giveSize() ); + valueArray.at(1) = helpArray.at(1) + unitCellSize.at(1) * switches.at(1) * macroField.at(1); + valueArray.at(2) = helpArray.at(2) + unitCellSize.at(2) * switches.at(2) * macroField.at(2) + unitCellSize.at(1) * switches.at(1) * macroField.at(3); + valueArray.at(3) = helpArray.at(3); + } else if ( dofIdArray.giveSize() == 1 && dofIdArray.at(1) == E_xx ) { //Macroscale: 3D truss. 1 DOF: EXX + valueArray.resize(helpArray.giveSize() ); + valueArray.at(1) = helpArray.at(1) + unitCellSize.at(1) * switches.at(1) * macroField.at(1); + valueArray.at(2) = helpArray.at(2); + valueArray.at(3) = helpArray.at(3); + } else if ( dofIdArray.giveSize() == 6 && dofIdArray.at(1) == E_xx && dofIdArray.at(2) == E_yy && dofIdArray.at(3) == E_zz && dofIdArray.at(4) == G_yz && dofIdArray.at(5) == G_xz && dofIdArray.at(6) == G_xy ) { //Macroscale: 3D solid using Voigt notation + valueArray.resize(helpArray.giveSize() ); + valueArray.at(1) = helpArray.at(1) + unitCellSize.at(1) * switches.at(1) * macroField.at(1) + + unitCellSize.at(3) * switches.at(3) * macroField.at(5) + unitCellSize.at(2) * switches.at(2) * macroField.at(6); + valueArray.at(2) = helpArray.at(2) + unitCellSize.at(2) * switches.at(2) * macroField.at(2) + + unitCellSize.at(3) * switches.at(3) * macroField.at(4); + valueArray.at(3) = helpArray.at(3) + unitCellSize.at(3) * switches.at(3) * macroField.at(3); + } else { + OOFEM_ERROR("Unknown periodic element type\n"); + } + } + } else { + valueArray.resize(3); + } + vtkPiece.setPrimaryVarInNode(type, inode, std::move(valueArray) ); + } + } + } +} + + +void +VTKXMLLatticeExportModule::exportIntVars(VTKPiece &vtkPiece, Set& region, IntArray& internalVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep) +{ + Domain *d = emodel->giveDomain(1); + int nnodes = d->giveNumberOfDofManagers(); + InternalStateType isType; + FloatArray answer; + + smoother.clear(); // Makes sure smoother is up-to-date with potentially new mesh. + //const IntArray& mapG2L = vtkPiece.getMapG2L(); + const IntArray& mapL2G = vtkPiece.getMapL2G(); + // Export of Internal State Type fields + vtkPiece.setNumberOfInternalVarsToExport(internalVarsToExport, mapL2G.giveSize() ); + for ( int field = 1; field <= internalVarsToExport.giveSize(); field++ ) { + isType = ( InternalStateType ) internalVarsToExport.at(field); + + for ( int nodeNum = 1; nodeNum <= mapL2G.giveSize(); nodeNum++ ) { + if ( nodeNum <= nnodes && mapL2G.at(nodeNum) <= nnodes && mapL2G.at(nodeNum) != 0 ) { //no special treatment for master nodes + Node *node = d->giveNode(mapL2G.at(nodeNum) ); + this->getNodalVariableFromIS(answer, node, tStep, isType, region, smoother); + vtkPiece.setInternalVarInNode(isType, nodeNum, answer); + } else { //special treatment for image nodes + //find the periodic node, enough to find the first occurrence + int pos = 0; + if ( mapL2G.at(nodeNum) != 0 ) { + pos = regionToUniqueMap.findFirstIndexOf(mapL2G.at(nodeNum) ); + } + + if ( pos ) { + Node *node = d->giveNode(periodicMap.at(pos) ); + this->getNodalVariableFromIS(answer, node, tStep, isType, region, smoother); + vtkPiece.setInternalVarInNode(isType, nodeNum, answer); + } else { //fill with zeroes + InternalStateValueType valType = giveInternalStateValueType(isType); + int ncomponents = giveInternalStateTypeSize(valType); + answer.resize(ncomponents); + + if ( isType == IST_BeamForceMomentTensor ) { + answer.resize(6); + } + + answer.zero(); + vtkPiece.setInternalVarInNode(isType, nodeNum, answer); + } + } + } + } +} + + +bool +VTKXMLLatticeExportModule::writeVTKPieceCross(VTKPiece &vtkPieceCross, TimeStep *tStep) +{ + if ( !vtkPieceCross.giveNumberOfCells() ) { + return false; + } + + // Write output: node coords + int numNodes = vtkPieceCross.giveNumberOfNodes(); + int numEl = vtkPieceCross.giveNumberOfCells(); + FloatArray coords; + + this->fileStreamCross << "\n"; + this->fileStreamCross << "\n "; + + for ( int inode = 1; inode <= numNodes; inode++ ) { + coords = vtkPieceCross.giveNodeCoords(inode); + ///@todo move this below into setNodeCoords since it should alwas be 3 components anyway + for ( int i = 1; i <= coords.giveSize(); i++ ) { + this->fileStreamCross << scientific << coords.at(i) << " "; + } + + for ( int i = coords.giveSize() + 1; i <= 3; i++ ) { + this->fileStreamCross << scientific << 0.0 << " "; + } + } + + this->fileStreamCross << "\n\n"; + this->fileStreamCross << "\n"; + this->fileStreamCross << " "; + + IntArray cellNodes; + for ( int ielem = 1; ielem <= numEl; ielem++ ) { + cellNodes = vtkPieceCross.giveCellConnectivity(ielem); + + for ( int i = 1; i <= cellNodes.giveSize(); i++ ) { + this->fileStreamCross << cellNodes.at(i) - 1 << " "; + } + this->fileStreamCross << " "; + } + + this->fileStreamCross << "\n"; + + // output the offsets (index of individual element data in connectivity array) + this->fileStreamCross << " "; + + for ( int ielem = 1; ielem <= numEl; ielem++ ) { + this->fileStreamCross << vtkPieceCross.giveCellOffset(ielem) << " "; + } + + this->fileStreamCross << "\n"; + + + // output cell (element) types + this->fileStreamCross << " "; + for ( int ielem = 1; ielem <= numEl; ielem++ ) { + this->fileStreamCross << vtkPieceCross.giveCellType(ielem) << " "; + } + + this->fileStreamCross << "\n"; + this->fileStreamCross << "\n"; + + + ///@todo giveDataHeaders is currently not updated wrt the new structure -> no file names in headers /JB + std::string pointHeader, cellHeader; + this->giveDataHeaders(pointHeader, cellHeader); + + this->fileStreamCross << pointHeader.c_str(); + this->fileStreamCross << "\n"; + this->fileStreamCross << cellHeader.c_str(); + + this->writeCellVarsCross(vtkPieceCross); + + this->fileStreamCross << "\n"; + this->fileStreamCross << "\n"; + + vtkPieceCross.clear(); + return true; +} + +void +VTKXMLLatticeExportModule::writeCellVarsCross(VTKPiece &vtkPiece) +{ + FloatArray valueArray; + int numCells = vtkPiece.giveNumberOfCells(); + for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) { + InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i); + InternalStateValueType valType = giveInternalStateValueType(type); + int ncomponents = giveInternalStateTypeSize(valType); + const char *name = __InternalStateTypeToString(type); + ( void ) name; //silence the warning + + this->fileStreamCross << " "; + valueArray.resize(ncomponents); + for ( int ielem = 1; ielem <= numCells; ielem++ ) { + valueArray = vtkPiece.giveCellVar(type, ielem); + for ( int i = 1; i <= valueArray.giveSize(); i++ ) { + this->fileStreamCross << valueArray.at(i) << " "; + } + } + this->fileStreamCross << "\n"; + +#ifdef _PYBIND_BINDINGS +#if 0 + if ( pythonExport ) { + py::list vals; + for ( int ielem = 1; ielem <= numCells; ielem++ ) { + valueArray = vtkPiece.giveCellVar(i, ielem); + vals.append(valueArray); + } + this->Py_CellVars [ name ] = vals; + } +#endif +#endif + }//end of for +} +} // end namespace oofem diff --git a/src/oofemlib/vtkxmllatticeexportmodule.h b/src/oofemlib/vtkxmllatticeexportmodule.h new file mode 100644 index 000000000..118d97403 --- /dev/null +++ b/src/oofemlib/vtkxmllatticeexportmodule.h @@ -0,0 +1,111 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef vtkxmllatticeexportmodule_h +#define vtkxmllatticeexportmodule_h + +#include "vtkxmlexportmodule.h" +#include "floatmatrix.h" + + +///@name Input fields for VTK XML Lattice export module +//@{ +#define _IFT_VTKXMLLatticeExportModule_Name "vtkxmllattice" +#define _IFT_VTKXMLLatticeExportModule_cross "cross" +//@} + +namespace oofem { +/** + * + * Represents VTK (Visualization Toolkit) export module for lattice modes. It uses VTK (.vtu) file format + * It extends vtkxmlexportmodule and uses ideas of vtkxmlperiodicmodule by introducing methods to deal with boundary elements of lattice elements. + * It also provides the option to plot mid cross-sections for visualisation of crack patterns + * @author: Peter Grassl + * + */ +class OOFEM_EXPORT VTKXMLLatticeExportModule : public VTKXMLExportModule +{ +protected: + + FloatMatrix uniqueNodeTable; + FloatMatrix uniqueNodeTableCross; + IntArray periodicMap, regionToUniqueMap; + IntArray locationMap; + IntArray elementNodePeriodicMap; + int elemNodes; + + bool crossSectionExportFlag; + + void giveSwitches(IntArray &answer, int location); + +public: + + /// Constructor. Creates empty Output Manager. By default all components are selected. + VTKXMLLatticeExportModule(int n, EngngModel *e); + /// Destructor + virtual ~VTKXMLLatticeExportModule(); + + std::ofstream fileStreamCross; + + VTKPiece defaultVTKPieceCross; + + void initializeFrom(InputRecord &ir) override; + + std::string giveOutputFileNameCross(TimeStep *tStep); + + std::ofstream giveOutputStreamCross(TimeStep *tStep); + + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; + + void doOutputNormal(TimeStep *tStep, bool forcedOutput = false); + + void doOutputCross(TimeStep *tStep, bool forcedOutput = false); + + const char *giveClassName() const override { return "VTKXMLLatticeExportModule"; } + + bool writeVTKPieceCross(VTKPiece &vtkPiece, TimeStep *tStep); + + void setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, Set& region) override; + + void writeCellVarsCross(VTKPiece &vtkPiece); + + void setupVTKPieceCross(VTKPiece &vtkPiece, TimeStep *tStep, Set& region); + + int initRegionNodeNumbering(VTKPiece& piece, Domain *domain, TimeStep *tStep, Set& region) override; + + void exportPrimaryVars(VTKPiece &piece, Set& region, IntArray& primaryVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep) override; + void exportIntVars(VTKPiece &piece, Set& region, IntArray& internalVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep) override; +}; +} // end namespace oofem +#endif // vtkxmllatticeexportmodule_h diff --git a/src/oofemlib/vtkxmlperiodicexportmodule.C b/src/oofemlib/vtkxmlperiodicexportmodule.C new file mode 100644 index 000000000..3e79486e9 --- /dev/null +++ b/src/oofemlib/vtkxmlperiodicexportmodule.C @@ -0,0 +1,614 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "vtkxmlperiodicexportmodule.h" +#include "element.h" +#include "gausspoint.h" +#include "timestep.h" +#include "engngm.h" +#include "node.h" +#include "materialinterface.h" +#include "mathfem.h" +#include "cltypes.h" +#include "material.h" +#include "classfactory.h" +#include "crosssection.h" +#include "dof.h" + +#ifdef __SM_MODULE + #include "../sm/Elements/LatticeElements/lattice2dboundary.h" + #include "../sm/Elements/LatticeElements/lattice3dboundary.h" + #include "../sm/Elements/LatticeElements/latticelink3dboundary.h" + #include "../sm/Elements/3D/ltrspaceboundary.h" + #include "../sm/Elements/Beams/libeam3dboundary.h" +#endif + +namespace oofem { +REGISTER_ExportModule(VTKXMLPeriodicExportModule) + +VTKXMLPeriodicExportModule :: VTKXMLPeriodicExportModule(int n, EngngModel *e) : VTKXMLExportModule(n, e) +{ + //Find out the element type and elemNodes +} + + +VTKXMLPeriodicExportModule :: ~VTKXMLPeriodicExportModule() +{} + + +void +VTKXMLPeriodicExportModule :: initializeFrom(InputRecord &ir) +{ + VTKXMLExportModule :: initializeFrom(ir); +} + + +void +VTKXMLPeriodicExportModule :: giveSwitches(IntArray &answer, int location) { + answer.resize(3); + answer.zero(); + int counter = 1; + for ( int x = -1; x < 2; x++ ) { + for ( int y = -1; y < 2; y++ ) { + for ( int z = -1; z < 2; z++ ) { + if ( !( z == 0 && y == 0 && x == 0 ) ) { + if ( counter == location ) { + answer(0) = x; + answer(1) = y; + answer(2) = z; + } + counter++; + } + } + } + } + + return; +} + + +void +VTKXMLPeriodicExportModule :: setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, Set& region) +{ + // Stores all neccessary data (of a region) in a VTKPiece so it can be exported later. + + Domain *d = emodel->giveDomain(1); + Element *elem; + + int nnodes = d->giveNumberOfDofManagers(); + + this->giveSmoother(); // make sure smoother is created + + // Assemble local->global and global->local region map and get number of + // single cells to process, the composite cells exported individually. + this->initRegionNodeNumbering(vtkPiece, d, tStep, region); + const int numNodes = vtkPiece.giveNumberOfNodes(); + const int numRegionEl = vtkPiece.giveNumberOfCells(); + const IntArray& mapG2L = vtkPiece.getMapG2L(); + const IntArray& mapL2G = vtkPiece.getMapL2G(); + + + if ( numNodes > 0 && numRegionEl > 0 ) { + // Export nodes as vtk vertices + vtkPiece.setNumberOfNodes(numNodes); + for ( int inode = 1; inode <= numNodes; inode++ ) { + if ( mapL2G.at(inode) <= nnodes && mapL2G.at(inode) != 0 ) { //DofManagers in domain (input file) + const auto &coords = d->giveNode(mapL2G.at(inode) )->giveCoordinates(); + vtkPiece.setNodeCoords(inode, coords); + } else if ( mapL2G.at(inode) > nnodes && mapL2G.at(inode) <= numNodes && mapL2G.at(inode) != 0 ) { //extra image nodes + FloatArray helpArray(3); + helpArray.at(1) = uniqueNodeTable.at(mapL2G.at(inode), 1); + helpArray.at(2) = uniqueNodeTable.at(mapL2G.at(inode), 2); + helpArray.at(3) = uniqueNodeTable.at(mapL2G.at(inode), 3); + vtkPiece.setNodeCoords(inode, helpArray); + } else { + FloatArray helpArray(3); + helpArray.zero(); + vtkPiece.setNodeCoords(inode, helpArray); + } + } + + + //------------------------------------------- + // Export all the cell data for the piece + //------------------------------------------- + IntArray cellNodes; + vtkPiece.setNumberOfCells(numRegionEl); + + int offset = 0; + int cellNum = 0; + IntArray elems = region.giveElementList(); + int helpCounter = 0; + for ( int ei = 1; ei <= elems.giveSize(); ei++ ) { + int elNum = elems.at(ei); + elem = d->giveElement(elNum); + + // Skip elements that: + // are inactivated or of composite type ( these are exported individually later) + if ( this->isElementComposite(elem) || !elem->isActivated(tStep) ) { + continue; + } + + if ( elem->giveParallelMode() != Element_local ) { + continue; + } + + cellNum++; + + // Set the connectivity +#ifdef __SM_MODULE + if ( dynamic_cast< LTRSpaceBoundary * >( elem ) ) { + cellNodes.resize(4); + IntArray loc = elem->giveLocation(); + for ( int ielnode = 1; ielnode <= 4; ielnode++ ) { + if ( loc.at(ielnode) != 0 ) { + helpCounter++; + cellNodes.at(ielnode) = regionToUniqueMap.at(nnodes + helpCounter); + } else { + cellNodes.at(ielnode) = elem->giveNode(ielnode)->giveNumber(); + } + } + } else if ( dynamic_cast< LIBeam3dBoundary * >( elem ) || dynamic_cast< Lattice3dBoundary * >( elem ) || dynamic_cast< LatticeLink3dBoundary * >( elem ) || dynamic_cast< Lattice2dBoundary * >( elem ) ) { + cellNodes.resize(2); + IntArray loc = elem->giveLocation(); + for ( int ielnode = 1; ielnode <= 2; ielnode++ ) { + if ( loc.at(ielnode) != 0 ) { + helpCounter++; + cellNodes.at(ielnode) = regionToUniqueMap.at(nnodes + helpCounter); + } else { + cellNodes.at(ielnode) = elem->giveNode(ielnode)->giveNumber(); + } + } + } else { //Standard case +#endif + this->giveElementCell(cellNodes, elem); +#ifdef __SM_MODULE + } +#endif + // Map from global to local node numbers for the current piece + int numElNodes = cellNodes.giveSize(); + + + IntArray connectivity(numElNodes); + for ( int i = 1; i <= numElNodes; i++ ) { + connectivity.at(i) = mapG2L.at(cellNodes.at(i) ); + } + + vtkPiece.setConnectivity(cellNum, connectivity); + + vtkPiece.setCellType(cellNum, this->giveCellType(elem) ); // VTK cell type + + offset += numElNodes; + vtkPiece.setOffset(cellNum, offset); + } + + + // Export primary, internal and XFEM variables as nodal quantities + this->exportPrimaryVars(vtkPiece, region, primaryVarsToExport, *primVarSmoother, tStep); + this->exportIntVars (vtkPiece, region, internalVarsToExport, *smoother, tStep); + + this->exportCellVars(vtkPiece, region, cellVarsToExport, tStep); + + } // end of default piece for simple geometry elements +} + +int +VTKXMLPeriodicExportModule :: initRegionNodeNumbering(VTKPiece& vtkPiece, + Domain *domain, TimeStep *tStep, Set& region) +{ + int nnodes = domain->giveNumberOfDofManagers(); + int elementNode, node; + int currOffset = 1; + Element *element; + + int regionDofMans = 0; + int regionSingleCells = 0; + IntArray& regionG2LNodalNumbers = vtkPiece.getMapG2L(); + IntArray& regionL2GNodalNumbers = vtkPiece.getMapL2G(); + + + IntArray elements = region.giveElementList(); + + int extraNodes = 0.; + for ( int ie = 1; ie <= elements.giveSize(); ie++ ) { + element = domain->giveElement(elements.at(ie) ); + +#ifdef __SM_MODULE + if ( dynamic_cast< LTRSpaceBoundary * >( element ) ) { + IntArray loc = element->giveLocation(); + for ( int ielnode = 1; ielnode <= 4; ielnode++ ) { + if ( loc.at(ielnode) != 0 ) { + extraNodes++; + } + } + } else if ( dynamic_cast< LIBeam3dBoundary * >( element ) || dynamic_cast< Lattice3dBoundary * >( element ) || dynamic_cast< LatticeLink3dBoundary * >( element ) || dynamic_cast< Lattice2dBoundary * >( element ) ) { + IntArray loc = element->giveLocation(); + for ( int ielnode = 1; ielnode <= 2; ielnode++ ) { + if ( loc.at(ielnode) != 0 ) { + extraNodes++; + } + } + } +#endif + } + + regionG2LNodalNumbers.resize(nnodes + extraNodes); + regionG2LNodalNumbers.zero(); + + periodicMap.resize(nnodes + extraNodes); + regionToUniqueMap.resize(nnodes + extraNodes); + locationMap.resize(nnodes + extraNodes); + + uniqueNodeTable.resize(nnodes + extraNodes, 3); + uniqueNodeTable.zero(); + + int totalNodes = 0; + int uniqueNodes = 0; + + for ( int ie = 1; ie <= elements.giveSize(); ie++ ) { + int ielem = elements.at(ie); + element = domain->giveElement(ielem); + + if ( this->isElementComposite(element) ) { + continue; // composite cells exported individually + } + + if ( !element->isActivated(tStep) ) { //skip inactivated elements + continue; + } + + if ( element->giveParallelMode() != Element_local ) { + continue; + } + + regionSingleCells++; + elemNodes = element->giveNumberOfNodes(); + +#ifdef __SM_MODULE + if ( dynamic_cast< LTRSpaceBoundary * >( element ) ) { + elemNodes = 4; + } else if ( dynamic_cast< LIBeam3dBoundary * >( element ) || dynamic_cast< Lattice3dBoundary * >( element ) || dynamic_cast< LatticeLink3dBoundary * >( element ) || dynamic_cast< Lattice2dBoundary * >( element ) ) { + elemNodes = 2; + } +#endif + + for ( elementNode = 1; elementNode <= elemNodes; elementNode++ ) { +#ifdef __SM_MODULE + if ( dynamic_cast< LTRSpaceBoundary * >( element ) ) { + IntArray loc = element->giveLocation(); + FloatArray nodeCoords; + if ( loc.at(elementNode) != 0 ) { //boundary element with mirrored node + totalNodes++; + regionDofMans++; + regionG2LNodalNumbers.at(nnodes + totalNodes) = 1; + node = element->giveNode(elementNode)->giveNumber(); + if ( regionG2LNodalNumbers.at(node) == 0 ) { // assign new number + /* mark for assignment. This is done later, as it allows to preserve + * natural node numbering. + */ + + regionG2LNodalNumbers.at(node) = 1; + regionDofMans++; + } + if ( regionG2LNodalNumbers.at(nnodes) == 0 ) { + regionG2LNodalNumbers.at(nnodes) = 1; + regionDofMans++; + } + + periodicMap.at(nnodes + totalNodes) = node; + locationMap.at(nnodes + totalNodes) = loc.at(elementNode); + + element->recalculateCoordinates(elementNode, nodeCoords); + + //get only the unique nodes + int repeatFlag = 0; + for ( int j = nnodes + 1; j <= nnodes + uniqueNodes; j++ ) { + double dx = fabs(uniqueNodeTable.at(j, 1) - nodeCoords.at(1) ); + double dy = fabs(uniqueNodeTable.at(j, 2) - nodeCoords.at(2) ); + double dz = fabs(uniqueNodeTable.at(j, 3) - nodeCoords.at(3) ); + if ( dx < 1e-9 && dy < 1e-9 && dz < 1e-9 ) {//node already present + repeatFlag++; + regionToUniqueMap.at(nnodes + totalNodes) = j; + } + } + + if ( repeatFlag == 0 ) {//new unique node + uniqueNodes++; + uniqueNodeTable.at(nnodes + uniqueNodes, 1) = nodeCoords.at(1); + uniqueNodeTable.at(nnodes + uniqueNodes, 2) = nodeCoords.at(2); + uniqueNodeTable.at(nnodes + uniqueNodes, 3) = nodeCoords.at(3); + regionToUniqueMap.at(nnodes + totalNodes) = nnodes + uniqueNodes; + } + } else { //boundary element but node not mirrored + node = element->giveNode(elementNode)->giveNumber(); + if ( regionG2LNodalNumbers.at(node) == 0 ) { // assign new number + /* mark for assignment. This is done later, as it allows to preserve + * natural node numbering. + */ + regionG2LNodalNumbers.at(node) = 1; + regionDofMans++; + } + } + } else if ( dynamic_cast< LIBeam3dBoundary * >( element ) || dynamic_cast< Lattice3dBoundary * >( element ) || dynamic_cast< LatticeLink3dBoundary * >( element ) || dynamic_cast< Lattice2dBoundary * >( element ) ) { //beam elements - only unique nodes + IntArray loc = element->giveLocation(); + FloatArray nodeCoords; + if ( loc.at(elementNode) != 0 ) { //boundary element with mirrored node + totalNodes++; + regionDofMans++; + regionG2LNodalNumbers.at(nnodes + totalNodes) = 1; + node = element->giveNode(elementNode)->giveNumber(); + if ( regionG2LNodalNumbers.at(node) == 0 ) { // assign new number + /* mark for assignment. This is done later, as it allows to preserve + * natural node numbering. + */ + + regionG2LNodalNumbers.at(node) = 1; + regionDofMans++; + } + if ( regionG2LNodalNumbers.at(nnodes) == 0 ) { + regionG2LNodalNumbers.at(nnodes) = 1; + regionDofMans++; + } + + periodicMap.at(nnodes + totalNodes) = node; + locationMap.at(nnodes + totalNodes) = loc.at(elementNode); + + element->recalculateCoordinates(elementNode, nodeCoords); + + //get only the unique nodes + int repeatFlag = 0; + for ( int j = nnodes + 1; j <= nnodes + uniqueNodes; j++ ) { + double dx = fabs(uniqueNodeTable.at(j, 1) - nodeCoords.at(1) ); + double dy = fabs(uniqueNodeTable.at(j, 2) - nodeCoords.at(2) ); + double dz = fabs(uniqueNodeTable.at(j, 3) - nodeCoords.at(3) ); + if ( dx < 1e-9 && dy < 1e-9 && dz < 1e-9 ) {//node already present + repeatFlag++; + regionToUniqueMap.at(nnodes + totalNodes) = j; + } + } + + if ( repeatFlag == 0 ) {//new unique node + uniqueNodes++; + uniqueNodeTable.at(nnodes + uniqueNodes, 1) = nodeCoords.at(1); + uniqueNodeTable.at(nnodes + uniqueNodes, 2) = nodeCoords.at(2); + uniqueNodeTable.at(nnodes + uniqueNodes, 3) = nodeCoords.at(3); + regionToUniqueMap.at(nnodes + totalNodes) = nnodes + uniqueNodes; + } + } + } else { //regular element +#endif + node = element->giveNode(elementNode)->giveNumber(); + if ( regionG2LNodalNumbers.at(node) == 0 ) { // assign new number + /* mark for assignment. This is done later, as it allows to preserve + * natural node numbering. + */ + regionG2LNodalNumbers.at(node) = 1; + regionDofMans++; + } +#ifdef __SM_MODULE + } +#endif + } + } + + uniqueNodeTable.resizeWithData(nnodes + uniqueNodes, 3); + regionDofMans = nnodes + uniqueNodes; + regionG2LNodalNumbers.resizeWithValues(regionDofMans); + regionL2GNodalNumbers.resize(regionDofMans); + + vtkPiece.setNumberOfNodes(regionDofMans); + vtkPiece.setNumberOfCells(regionSingleCells); + + for ( int i = 1; i <= regionDofMans; i++ ) { + if ( regionG2LNodalNumbers.at(i) ) { + regionG2LNodalNumbers.at(i) = currOffset++; + regionL2GNodalNumbers.at(regionG2LNodalNumbers.at(i) ) = i; + } + } + return 1; +} + + +void VTKXMLPeriodicExportModule :: exportPrimaryVars(VTKPiece &vtkPiece, Set& region, IntArray& primaryVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep) +{ + Domain *d = emodel->giveDomain(1); + int nnodes = d->giveNumberOfDofManagers(); + FloatArray valueArray; + smoother.clear(); // Makes sure primary smoother is up-to-date with potentially new mesh. + + //const IntArray& mapG2L = vtkPiece.getMapG2L(); + const IntArray& mapL2G = vtkPiece.getMapL2G(); + vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport, mapL2G.giveSize() ); + + //Get the macroscopic field (deformation gradients, curvatures etc.) + DofManager *controlNode = d->giveNode(nnodes); //assuming the control node is last + IntArray dofIdArray; + controlNode->giveCompleteMasterDofIDArray(dofIdArray); + std::vector dofIDVector; + dofIDVector.assign(dofIdArray.begin(), dofIdArray.end()); + + FloatArray macroField(controlNode->giveNumberOfDofs() ); + for ( int j = 1; j <= controlNode->giveNumberOfDofs(); j++ ) { + macroField.at(j) = controlNode->giveDofWithID(dofIdArray.at(j) )->giveUnknown(VM_Total, tStep); + } + + std::vector macroTrussIDs = { E_xx }; + std::vector macroMembraneIDs = { E_xx, E_yy, E_xy, E_yx }; + std::vector macroBeamIDs = { E_xx, E_zx, K_xx }; + std::vector macroPlateIDs = { E_xx, E_yy, E_zy, E_zx, E_xy, E_yx, K_xx, K_yy, K_xy, K_yx }; + std::vector macro3DVoigtIDs = { E_xx, E_yy, E_zz, G_yz, G_xz, G_xy }; + std::vector macro3DIDs = { E_xx, E_yy, E_zz, E_yz, E_zy, E_xz, E_zx, E_xy, E_yx }; + std::vector macro2DIDs = { E_xx, E_yy, G_xy }; + + //Get unit cell size + const auto unitCellSize = controlNode->giveCoordinates(); + + for ( int i = 1, n = primaryVarsToExport.giveSize(); i <= n; i++ ) { + UnknownType type = ( UnknownType ) primaryVarsToExport.at(i); + + for ( int inode = 1; inode <= mapL2G.giveSize(); inode++ ) { + if ( inode <= nnodes && mapL2G.at(inode) <= nnodes && mapL2G.at(inode) != 0 ) { //no special treatment for master nodes + DofManager *dman = d->giveNode(mapL2G.at(inode) ); + + this->getNodalVariableFromPrimaryField(valueArray, dman, tStep, type, region, smoother); + vtkPiece.setPrimaryVarInNode(type, inode, std :: move(valueArray) ); + } else { //special treatment for image nodes + //find the periodic node, enough to find the first occurrence + int pos = 0; + if ( mapL2G.at(inode) != 0 ) { + pos = regionToUniqueMap.findFirstIndexOf(mapL2G.at(inode) ); + } + if ( pos ) { + DofManager *dman = d->giveNode(periodicMap.at(pos) ); + IntArray switches; + giveSwitches(switches, locationMap.at(pos) ); + //get the master unknown + FloatArray helpArray; + this->getNodalVariableFromPrimaryField(helpArray, dman, tStep, type, region, smoother); + //recalculate the image unknown + if ( type == DisplacementVector ) { + if ( dofIDVector == macro3DIDs ) { //Macroscale: 3D SOLID, LTRSpaceBoundary + valueArray.resize(helpArray.giveSize() ); + valueArray.at(1) = helpArray.at(1) + unitCellSize.at(1) * switches.at(1) * macroField.at(1) + + unitCellSize.at(2) * switches.at(2) * macroField.at(8) + unitCellSize.at(3) * switches.at(3) * macroField.at(6); + valueArray.at(2) = helpArray.at(2) + unitCellSize.at(1) * switches.at(1) * macroField.at(9) + + unitCellSize.at(2) * switches.at(2) * macroField.at(2) + unitCellSize.at(3) * switches.at(3) * macroField.at(4); + valueArray.at(3) = helpArray.at(3) + unitCellSize.at(1) * switches.at(1) * macroField.at(7) + + unitCellSize.at(2) * switches.at(2) * macroField.at(5) + unitCellSize.at(3) * switches.at(3) * macroField.at(3); + } else if ( dofIDVector == macroTrussIDs ) { //Macroscale: TRUSS + valueArray.resize(helpArray.giveSize() ); + valueArray.at(1) = helpArray.at(1) + unitCellSize.at(1) * switches.at(1) * macroField.at(1); + valueArray.at(2) = helpArray.at(2); + valueArray.at(3) = helpArray.at(3); + } else if ( dofIDVector == macroMembraneIDs ) { //Macroscale: 2D MEMBRANE, LTRSpaceBoundaryMembrane + valueArray.resize(helpArray.giveSize() ); + valueArray.at(1) = helpArray.at(1) + unitCellSize.at(1) * switches.at(1) * macroField.at(1) + + unitCellSize.at(2) * switches.at(2) * macroField.at(3); + valueArray.at(2) = helpArray.at(2) + unitCellSize.at(1) * switches.at(1) * macroField.at(4) + + unitCellSize.at(2) * switches.at(2) * macroField.at(2); + valueArray.at(3) = helpArray.at(3); + } else if ( dofIDVector == macro2DIDs ) { //Macroscale: 2D plane stress + valueArray.resize(helpArray.giveSize() ); + valueArray.at(1) = helpArray.at(1) + unitCellSize.at(1) * switches.at(1) * macroField.at(1); + valueArray.at(2) = helpArray.at(2) + unitCellSize.at(2) * switches.at(2) * macroField.at(2) + unitCellSize.at(1) * switches.at(1) * macroField.at(3); + valueArray.at(3) = helpArray.at(3); + } else if ( dofIDVector == macroBeamIDs ) { //Macroscale: 2D BEAM, LTRSpaceBoundaryBeam + valueArray.resize(helpArray.giveSize() ); + valueArray.at(1) = helpArray.at(1) + unitCellSize.at(1) * switches.at(1) * macroField.at(1) - + dman->giveCoordinate(3) * unitCellSize.at(1) * switches.at(1) * macroField.at(3); + valueArray.at(2) = helpArray.at(2); + valueArray.at(3) = helpArray.at(3) + unitCellSize.at(1) * switches.at(1) * macroField.at(2); + } else if ( dofIDVector == macroPlateIDs ) { //Macroscale: 2D PLATE, LTRSpaceBoundaryPlate + valueArray.resize(helpArray.giveSize() ); + valueArray.at(1) = helpArray.at(1) + unitCellSize.at(1) * switches.at(1) * macroField.at(1) + + unitCellSize.at(2) * switches.at(2) * macroField.at(5) - + dman->giveCoordinate(3) * unitCellSize.at(1) * switches.at(1) * macroField.at(7) - + dman->giveCoordinate(3) * unitCellSize.at(2) * switches.at(2) * macroField.at(9); + valueArray.at(2) = helpArray.at(2) + unitCellSize.at(1) * switches.at(1) * macroField.at(6) + + unitCellSize.at(2) * switches.at(2) * macroField.at(2) - + dman->giveCoordinate(3) * unitCellSize.at(2) * switches.at(2) * macroField.at(8) - + dman->giveCoordinate(3) * unitCellSize.at(1) * switches.at(1) * macroField.at(10); + valueArray.at(3) = helpArray.at(3) + unitCellSize.at(1) * switches.at(1) * macroField.at(4) + + unitCellSize.at(2) * switches.at(2) * macroField.at(3); + } else if ( dofIDVector == macro3DVoigtIDs ) { //Macroscale: 3D SOLID, LTRSpaceBoundaryVoigt, Lattice3dBoundary + valueArray.resize(helpArray.giveSize() ); + valueArray.at(1) = helpArray.at(1) + unitCellSize.at(1) * switches.at(1) * macroField.at(1) + + unitCellSize.at(3) * switches.at(3) * macroField.at(5) + unitCellSize.at(2) * switches.at(2) * macroField.at(6); + valueArray.at(2) = helpArray.at(2) + unitCellSize.at(2) * switches.at(2) * macroField.at(2) + + unitCellSize.at(3) * switches.at(3) * macroField.at(4); + valueArray.at(3) = helpArray.at(3) + unitCellSize.at(3) * switches.at(3) * macroField.at(3); + } else { + OOFEM_ERROR("Unknown element type\n"); + } + } + } else { + valueArray.resize(3); + } + + vtkPiece.setPrimaryVarInNode(type, inode, std :: move(valueArray) ); + } + } + } +} + +void +VTKXMLPeriodicExportModule :: exportIntVars(VTKPiece &vtkPiece, Set& region, IntArray& internalVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep) +{ + Domain *d = emodel->giveDomain(1); + int nnodes = d->giveNumberOfDofManagers(); + InternalStateType isType; + FloatArray answer; + + smoother.clear(); // Makes sure smoother is up-to-date with potentially new mesh. + //const IntArray& mapG2L = vtkPiece.getMapG2L(); + const IntArray& mapL2G = vtkPiece.getMapL2G(); + + // Export of Internal State Type fields + vtkPiece.setNumberOfInternalVarsToExport(internalVarsToExport, mapL2G.giveSize() ); + for ( int field = 1; field <= internalVarsToExport.giveSize(); field++ ) { + isType = ( InternalStateType ) internalVarsToExport.at(field); + + for ( int nodeNum = 1; nodeNum <= mapL2G.giveSize(); nodeNum++ ) { + if ( nodeNum <= nnodes && mapL2G.at(nodeNum) <= nnodes && mapL2G.at(nodeNum) != 0 ) { //no special treatment for master nodes + Node *node = d->giveNode(mapL2G.at(nodeNum) ); + this->getNodalVariableFromIS(answer, node, tStep, isType, region, smoother); + vtkPiece.setInternalVarInNode(isType, nodeNum, answer); + } else { //special treatment for image nodes + //find the periodic node, enough to find the first occurrence + int pos = 0; + if ( mapL2G.at(nodeNum) != 0 ) { + pos = regionToUniqueMap.findFirstIndexOf(mapL2G.at(nodeNum) ); + } + + if ( pos ) { + Node *node = d->giveNode(periodicMap.at(pos) ); + this->getNodalVariableFromIS(answer, node, tStep, isType, region, smoother); + vtkPiece.setInternalVarInNode(isType, nodeNum, answer); + } else { //fill with zeroes + InternalStateValueType valType = giveInternalStateValueType(isType); + int ncomponents = giveInternalStateTypeSize(valType); + answer.resize(ncomponents); + + if ( isType == IST_BeamForceMomentTensor ) { + answer.resize(6); + } + + answer.zero(); + vtkPiece.setInternalVarInNode(isType, nodeNum, answer); + } + } + } + } +} +} // end namespace oofem diff --git a/src/oofemlib/vtkxmlperiodicexportmodule.h b/src/oofemlib/vtkxmlperiodicexportmodule.h new file mode 100644 index 000000000..d8b480c36 --- /dev/null +++ b/src/oofemlib/vtkxmlperiodicexportmodule.h @@ -0,0 +1,86 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef vtkxmlperiodicexportmodule_h +#define vtkxmlperiodicexportmodule_h + +#include "vtkxmlexportmodule.h" +#include "floatmatrix.h" + + +///@name Input fields for VTK XML export module +//@{ +#define _IFT_VTKXMLPeriodicExportModule_Name "vtkxmlperiodic" +//@} + +namespace oofem { +/** + * + * + * Represents VTK (Visualization Toolkit) export module for periodic cells. It uses VTK (.vtu) file format + * It extends vtkxmlexportmodule by introducing methods to deal with boundary elements. + * @author: Ignatios Athanasiadis, Adam Sciegaj, Peter Grassl + * + */ +class OOFEM_EXPORT VTKXMLPeriodicExportModule : public VTKXMLExportModule +{ +protected: + FloatMatrix uniqueNodeTable; + IntArray periodicMap, regionToUniqueMap; + IntArray locationMap; + IntArray elementNodePeriodicMap; + int elemNodes; + + void giveSwitches(IntArray &answer, int location); + +public: + /// Constructor. Creates empty Output Manager. By default all components are selected. + VTKXMLPeriodicExportModule(int n, EngngModel *e); + /// Destructor + virtual ~VTKXMLPeriodicExportModule(); + + void initializeFrom(InputRecord &ir) override; + + const char *giveClassName() const override { return "VTKXMLPeriodicExportModule"; } + + void setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, Set& region) override; + + int initRegionNodeNumbering(VTKPiece& piece, + Domain *domain, TimeStep *tStep, Set& region) override; + + void exportPrimaryVars(VTKPiece &vtkPiece, Set& region, IntArray& primaryVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep) override; + void exportIntVars(VTKPiece &vtkPiece, Set& region, IntArray& internalVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep) override; +}; +} // end namespace oofem +#endif // vtkxmlperiodicexportmodule_h diff --git a/src/oofemlib/wallclockloadbalancermonitor.C b/src/oofemlib/wallclockloadbalancermonitor.C index b3d2ba4c4..d94b41672 100644 --- a/src/oofemlib/wallclockloadbalancermonitor.C +++ b/src/oofemlib/wallclockloadbalancermonitor.C @@ -223,12 +223,10 @@ WallClockLoadBalancerMonitor :: decide(TimeStep *tStep) } -IRResultType -WallClockLoadBalancerMonitor :: initializeFrom(InputRecord *ir) +void +WallClockLoadBalancerMonitor :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = LoadBalancerMonitor :: initializeFrom(ir); + LoadBalancerMonitor :: initializeFrom(ir); IR_GIVE_OPTIONAL_FIELD(ir, relWallClockImbalanceTreshold, _IFT_WallClockLoadBalancerMonitor_relwct); IR_GIVE_OPTIONAL_FIELD(ir, absWallClockImbalanceTreshold, _IFT_WallClockLoadBalancerMonitor_abswct); @@ -250,8 +248,6 @@ WallClockLoadBalancerMonitor :: initializeFrom(InputRecord *ir) } #endif - - return result; } } diff --git a/src/oofemlib/wallclockloadbalancermonitor.h b/src/oofemlib/wallclockloadbalancermonitor.h index daa2c7df7..6a908286e 100644 --- a/src/oofemlib/wallclockloadbalancermonitor.h +++ b/src/oofemlib/wallclockloadbalancermonitor.h @@ -84,19 +84,20 @@ class OOFEM_EXPORT WallClockLoadBalancerMonitor : public LoadBalancerMonitor FloatArray processingWeights; #endif public: - WallClockLoadBalancerMonitor(EngngModel * em) : LoadBalancerMonitor(em) { - relWallClockImbalanceTreshold = 0.1; - absWallClockImbalanceTreshold = 10.0; - minAbsWallClockImbalanceTreshold = 0.0; - lbstep = 5; - } + WallClockLoadBalancerMonitor(EngngModel * em) : + LoadBalancerMonitor(em), + relWallClockImbalanceTreshold(0.1), + absWallClockImbalanceTreshold(10.0), + minAbsWallClockImbalanceTreshold(0.0), + lbstep(5) + { } - LoadBalancerDecisionType decide(TimeStep *); + LoadBalancerDecisionType decide(TimeStep *) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveClassName() const { return "WallClockLoadBalancerMonitor"; } + const char *giveClassName() const override { return "WallClockLoadBalancerMonitor"; } }; } // end namespace oofem -#endif //wallclockloadbalancer_h \ No newline at end of file +#endif //wallclockloadbalancer_h diff --git a/src/oofemlib/weakperiodicbc.C b/src/oofemlib/weakperiodicbc.C index 390659bda..135a4eea0 100644 --- a/src/oofemlib/weakperiodicbc.C +++ b/src/oofemlib/weakperiodicbc.C @@ -53,9 +53,13 @@ #include "set.h" #include "function.h" +#ifdef _OPENMP +#include +#endif + #include "timestep.h" -// #include "../sm/Elements/tet21ghostsolid.h" -#include "../sm/Elements/nlstructuralelement.h" +// #include "sm/Elements/tet21ghostsolid.h" +#include "sm/Elements/nlstructuralelement.h" namespace oofem { REGISTER_BoundaryCondition(WeakPeriodicBoundaryCondition); @@ -70,15 +74,10 @@ WeakPeriodicBoundaryCondition :: ~WeakPeriodicBoundaryCondition() { } -IRResultType -WeakPeriodicBoundaryCondition :: initializeFrom(InputRecord *ir) +void +WeakPeriodicBoundaryCondition :: initializeFrom(InputRecord &ir) { - IRResultType result; - - result = ActiveBoundaryCondition :: initializeFrom(ir); ///@todo Carl, remove this line and use elementsidespositive/negative instead. - if ( result != IRRT_OK ) { - return result; - } + ActiveBoundaryCondition :: initializeFrom(ir); ///@todo Carl, remove this line and use elementsidespositive/negative instead. orderOfPolygon = 2; IR_GIVE_OPTIONAL_FIELD(ir, orderOfPolygon, _IFT_WeakPeriodicBoundaryCondition_order); @@ -91,13 +90,7 @@ WeakPeriodicBoundaryCondition :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, dofids, _IFT_WeakPeriodicBoundaryCondition_dofids); ndofids = dofids.giveSize(); - ngp = -1; // Pressure as default - IR_GIVE_OPTIONAL_FIELD(ir, ngp, _IFT_WeakPeriodicBoundaryCondition_ngp); - if ( ngp != -1 ) { - OOFEM_WARNING("ngp isn't being used anymore! see how the interpolator constructs the integration rule automatically."); - return IRRT_BAD_FORMAT; - } - + ngp = -1; // ngp is deprecated nlgeo = false; IR_GIVE_OPTIONAL_FIELD(ir, nlgeo, _IFT_WeakPeriodicBoundaryCondition_nlgeo ); @@ -151,8 +144,6 @@ WeakPeriodicBoundaryCondition :: initializeFrom(InputRecord *ir) gamma_ids.followedBy(dofid); gammaDman->appendDof( new MasterDof( gammaDman.get(), ( DofIDItem )dofid ) ); } - - return IRRT_OK; } void WeakPeriodicBoundaryCondition :: computeOrthogonalBasis() @@ -250,7 +241,7 @@ void WeakPeriodicBoundaryCondition :: giveEdgeNormal(FloatArray &answer, int ele } Element *thisElement = this->domain->giveElement(element); - FEInterpolation *interpolation = thisElement->giveInterpolation( ( DofIDItem ) dofids(0) ); + FEInterpolation *interpolation = thisElement->giveInterpolation( ( DofIDItem ) dofids[0] ); interpolation->boundaryEvalNormal( answer, side, xi, FEIElementGeometryWrapper(thisElement) ); } @@ -394,7 +385,7 @@ WeakPeriodicBoundaryCondition :: computeDeformationGradient(FloatMatrix &answer, FloatArray F, u; FloatMatrix dNdx, BH, Fmatrix, Finv; - FEInterpolation *interpolation = e->giveInterpolation( ( DofIDItem ) dofids(0) ); + FEInterpolation *interpolation = e->giveInterpolation( ( DofIDItem ) dofids[0] ); // Fetch displacements e->computeVectorOf({1, 2, 3}, VM_Total, tStep, u); @@ -436,14 +427,13 @@ void WeakPeriodicBoundaryCondition :: computeElementTangent(FloatMatrix &B, Elem OOFEM_ERROR("Function obsolete"); FloatArray gcoords; - IntArray bnodes; FEInterpolation *geoInterpolation = e->giveInterpolation(); // Use correct interpolation for the dofid on which the condition is applied - FEInterpolation *interpolation = e->giveInterpolation( ( DofIDItem ) dofids(0) ); + FEInterpolation *interpolation = e->giveInterpolation( ( DofIDItem ) dofids[0] ); - interpolation->boundaryGiveNodes(bnodes, boundary); + auto bnodes = interpolation->boundaryGiveNodes(boundary); B.resize(bnodes.giveSize(), ndof); B.zero(); @@ -488,7 +478,7 @@ void WeakPeriodicBoundaryCondition :: computeElementTangent(FloatMatrix &B, Elem } } -void WeakPeriodicBoundaryCondition :: assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale) +void WeakPeriodicBoundaryCondition :: assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale, void* lock) { if ( type != TangentStiffnessMatrix && type != StiffnessMatrix ) { return; @@ -515,12 +505,10 @@ void WeakPeriodicBoundaryCondition :: assemble(SparseMtrx &answer, TimeStep *tSt IntArray r_sideLoc, c_sideLoc; // Find dofs for this element which should be periodic - IntArray bNodes; - - FEInterpolation *interpolation = thisElement->giveInterpolation( ( DofIDItem ) dofids(0) ); + FEInterpolation *interpolation = thisElement->giveInterpolation( ( DofIDItem ) dofids[0] ); FEInterpolation *geoInterpolation = thisElement->giveInterpolation(); - interpolation->boundaryGiveNodes( bNodes, side [ thisSide ].at(ielement) ); + auto bNodes = interpolation->boundaryGiveNodes(side [ thisSide ].at(ielement)); thisElement->giveBoundaryLocationArray(r_sideLoc, bNodes, dofids, r_s); thisElement->giveBoundaryLocationArray(c_sideLoc, bNodes, dofids, c_s); @@ -530,8 +518,8 @@ void WeakPeriodicBoundaryCondition :: assemble(SparseMtrx &answer, TimeStep *tSt std :: unique_ptr< IntegrationRule >iRule(geoInterpolation->giveBoundaryIntegrationRule(orderOfPolygon, boundary)); - for ( GaussPoint *gp: *iRule ) { - FloatArray lcoords = gp->giveNaturalCoordinates(); + for ( auto &gp: *iRule ) { + auto const &lcoords = gp->giveNaturalCoordinates(); FloatArray N, gcoords; geoInterpolation->boundaryLocal2Global( gcoords, boundary, lcoords, FEIElementGeometryWrapper(thisElement)); @@ -587,8 +575,16 @@ void WeakPeriodicBoundaryCondition :: assemble(SparseMtrx &answer, TimeStep *tSt B.times(normalSign * scale); BT.beTranspositionOf(B); +#ifdef _OPENMP + if (lock) + omp_set_lock(static_cast(lock)); +#endif answer.assemble(r_sideLoc, c_loc, B); answer.assemble(r_loc, c_sideLoc, BT); +#ifdef _OPENMP + if (lock) + omp_unset_lock(static_cast(lock)); +#endif } } @@ -655,12 +651,12 @@ double WeakPeriodicBoundaryCondition :: computeBaseFunctionValue1D(int baseID, d void WeakPeriodicBoundaryCondition :: assembleVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorms) + const UnknownNumberingScheme &s, FloatArray *eNorms, void* lock) { if ( type == InternalForcesVector ) { - giveInternalForcesVector(answer, tStep, type, mode, s); + giveInternalForcesVector(answer, tStep, type, mode, s, nullptr, lock); } else if ( type == ExternalForcesVector ) { - giveExternalForcesVector(answer, tStep, type, mode, s); + giveExternalForcesVector(answer, tStep, type, mode, s, lock); } } @@ -668,7 +664,7 @@ void WeakPeriodicBoundaryCondition :: assembleVector(FloatArray &answer, TimeSte void WeakPeriodicBoundaryCondition :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorms) + const UnknownNumberingScheme &s, FloatArray *eNorms, void* lock) { // Fetch unknowns of this boundary condition IntArray gammaLoc; @@ -696,12 +692,10 @@ WeakPeriodicBoundaryCondition :: giveInternalForcesVector(FloatArray &answer, Ti int boundary = side [ thisSide ].at(ielement); // Find dofs for this element which should be periodic - IntArray bNodes; - - FEInterpolation *interpolation = thisElement->giveInterpolation( ( DofIDItem ) dofids(0) ); + FEInterpolation *interpolation = thisElement->giveInterpolation( ( DofIDItem ) dofids[0] ); FEInterpolation *geoInterpolation = thisElement->giveInterpolation(); - interpolation->boundaryGiveNodes( bNodes, boundary ); + auto bNodes = interpolation->boundaryGiveNodes(boundary); thisElement->giveBoundaryLocationArray(sideLocation, bNodes, dofids, s, &masterDofIDs); thisElement->computeBoundaryVectorOf(bNodes, dofids, VM_Total, tStep, a); @@ -786,7 +780,9 @@ WeakPeriodicBoundaryCondition :: giveInternalForcesVector(FloatArray &answer, Ti myProdGamma.plusProduct(D, gamma, detJ*gp->giveWeight()*normalSign); */ } - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif if ( eNorms ) { eNorms->assembleSquared( vProd, gamma_ids ); eNorms->assembleSquared( gammaProd, masterDofIDs); @@ -794,6 +790,9 @@ WeakPeriodicBoundaryCondition :: giveInternalForcesVector(FloatArray &answer, Ti answer.assemble(gammaProd, gammaLoc); answer.assemble(vProd, sideLocation); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif // answer.assemble(myProd, gammaLoc); // answer.assemble(myProdGamma, sideLocation); } @@ -803,7 +802,7 @@ WeakPeriodicBoundaryCondition :: giveInternalForcesVector(FloatArray &answer, Ti void WeakPeriodicBoundaryCondition :: giveExternalForcesVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s) + const UnknownNumberingScheme &s, void* lock) { updateSminmax(); @@ -827,7 +826,7 @@ WeakPeriodicBoundaryCondition :: giveExternalForcesVector(FloatArray &answer, Ti std :: unique_ptr< IntegrationRule >iRule(geoInterpolation->giveBoundaryIntegrationRule(orderOfPolygon, side [ thisSide ].at(ielement) )); - for ( GaussPoint *gp: *iRule ) { + for ( auto gp: *iRule ) { FloatArray gcoords; FloatArray lcoords = gp->giveNaturalCoordinates(); @@ -837,22 +836,28 @@ WeakPeriodicBoundaryCondition :: giveExternalForcesVector(FloatArray &answer, Ti // Compute Jacobian double detJ = fabs( geoInterpolation->boundaryGiveTransformationJacobian( side [ thisSide ].at(ielement), lcoords, FEIElementGeometryWrapper(thisElement) ) ); - for (int j=0; jg.dotProduct(gcoords)*fVal*gp->giveWeight()*detJ; + temp.at(j+1) += normalSign*this->g.dotProduct(gcoords)*fVal*gp->giveWeight()*detJ; } } } } - answer.assemble(temp, gammaLoc); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif + answer.assemble(temp, gammaLoc); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif + // bp: can be a bug, answer changed after localization ! // Finally, compute value of loadtimefunction - double factor; - factor = this->giveTimeFunction()->evaluate(tStep, mode); + double factor = this->giveTimeFunction()->evaluate(tStep, mode); answer.times(factor); } diff --git a/src/oofemlib/weakperiodicbc.h b/src/oofemlib/weakperiodicbc.h index 59815af1b..6f027d581 100644 --- a/src/oofemlib/weakperiodicbc.h +++ b/src/oofemlib/weakperiodicbc.h @@ -161,33 +161,33 @@ class OOFEM_EXPORT WeakPeriodicBoundaryCondition : public ActiveBoundaryConditio WeakPeriodicBoundaryCondition(int n, Domain * d); virtual ~WeakPeriodicBoundaryCondition(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; basisType giveBasisType() { return useBasisType; } - virtual void assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, - const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0); + void assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0, void* lock=nullptr) override; - virtual void assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm = NULL); + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorm = nullptr, void* lock=nullptr) override; void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm = NULL); + const UnknownNumberingScheme &s, FloatArray *eNorm = nullptr, void* lock=nullptr); void giveExternalForcesVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s); + const UnknownNumberingScheme &s, void*lock=nullptr); - virtual int giveNumberOfInternalDofManagers(); + int giveNumberOfInternalDofManagers() override; - virtual DofManager *giveInternalDofManager(int i); + DofManager *giveInternalDofManager(int i) override; - virtual void addElementSide(int elem, int side); + void addElementSide(int elem, int side) override; - virtual const char *giveClassName() const { return "WeakPeriodicBoundaryCondition"; } - virtual const char *giveInputRecordName() const { return _IFT_WeakPeriodicBoundaryCondition_Name; } + const char *giveClassName() const override { return "WeakPeriodicBoundaryCondition"; } + const char *giveInputRecordName() const override { return _IFT_WeakPeriodicBoundaryCondition_Name; } protected: void computeElementTangent(FloatMatrix &answer, Element *e, int boundary, TimeStep *tStep); diff --git a/src/oofemlib/xfem/delaunay.C b/src/oofemlib/xfem/delaunay.C index cfc92dd95..e98b99dec 100644 --- a/src/oofemlib/xfem/delaunay.C +++ b/src/oofemlib/xfem/delaunay.C @@ -69,8 +69,8 @@ bool Delaunay :: isInsideCC(const FloatArray &iP, const FloatArray &iP1, const F double r = tr.getRadiusOfCircumCircle(); FloatArray circumCenter; tr.computeCenterOfCircumCircle(circumCenter); - double distance = circumCenter.distance(iP); - if ( distance < r ) { + double dist = distance(circumCenter, iP); + if ( dist < r ) { return true; } else { return false; @@ -90,9 +90,9 @@ void Delaunay :: triangulate(const std :: vector< FloatArray > &iVertices, std : const double relTol2 = 1.0e-6; std :: vector< double >dist_square = { - iVertices [ 0 ].distance_square(iVertices [ 1 ]), - iVertices [ 0 ].distance_square(iVertices [ 2 ]), - iVertices [ 0 ].distance_square(iVertices [ 3 ]) + distance(iVertices [ 0 ], iVertices [ 1 ]), + distance(iVertices [ 0 ], iVertices [ 2 ]), + distance(iVertices [ 0 ], iVertices [ 3 ]) }; std :: sort( dist_square.begin(), dist_square.end() ); @@ -101,16 +101,18 @@ void Delaunay :: triangulate(const std :: vector< FloatArray > &iVertices, std : if ( fabs(dist_square [ 2 ] - dist_square [ 1 ] - dist_square [ 0 ]) < relTol2 * dist_square [ 2 ] ) { // We found a rectangle - double maxDist_square = iVertices [ 0 ].distance_square(iVertices [ 1 ]); + double maxDist_square = distance_square(iVertices [ 0 ], iVertices [ 1 ]); int maxDistInd = 1; - if ( iVertices [ 0 ].distance_square(iVertices [ 2 ]) > maxDist_square ) { - maxDist_square = iVertices [ 0 ].distance_square(iVertices [ 2 ]); + double d2 = distance_square(iVertices [ 0 ], iVertices [ 2 ]); + if ( d2 > maxDist_square ) { + maxDist_square = d2; maxDistInd = 2; } - if ( iVertices [ 0 ].distance_square(iVertices [ 3 ]) > maxDist_square ) { - maxDist_square = iVertices [ 0 ].distance_square(iVertices [ 3 ]); + double d2b = distance_square(iVertices [ 0 ], iVertices [ 3 ]); + if ( d2b > maxDist_square ) { + maxDist_square = d2b; maxDistInd = 3; } diff --git a/src/oofemlib/xfem/directei.h b/src/oofemlib/xfem/directei.h index deffe1220..8f01d9d73 100644 --- a/src/oofemlib/xfem/directei.h +++ b/src/oofemlib/xfem/directei.h @@ -56,12 +56,12 @@ class DirectEI : public GeometryBasedEI DirectEI(int n, XfemManager *xm, Domain *aDomain); virtual ~DirectEI(); - virtual const char *giveClassName() const { return "DirectEI"; } - virtual const char *giveInputRecordName() const { return _IFT_DirectEI_Name; } + const char *giveClassName() const override { return "DirectEI"; } + const char *giveInputRecordName() const override { return _IFT_DirectEI_Name; } - virtual void evalLevelSetNormal(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const; - virtual void evalLevelSetTangential(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const; - virtual void evalGradLevelSetNormal(FloatArray &oGradLevelSet, const FloatArray &iGlobalCoord, const FloatMatrix &idNdX, const IntArray &iNodeInd) const; + void evalLevelSetNormal(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const override; + void evalLevelSetTangential(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const override; + void evalGradLevelSetNormal(FloatArray &oGradLevelSet, const FloatArray &iGlobalCoord, const FloatMatrix &idNdX, const IntArray &iNodeInd) const override; }; } /* namespace oofem */ diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfront.h b/src/oofemlib/xfem/enrichmentfronts/enrichmentfront.h index 9ab672632..542c68a18 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfront.h +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfront.h @@ -122,7 +122,7 @@ class OOFEM_EXPORT EnrichmentFront virtual const char *giveClassName() const = 0; virtual const char *giveInputRecordName() const = 0; - virtual IRResultType initializeFrom(InputRecord *ir) = 0; + virtual void initializeFrom(InputRecord &ir) = 0; virtual void giveInputRecord(DynamicInputRecord &input) = 0; virtual double giveSupportRadius() const = 0; diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontcohesivebranchfunconeel.C b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontcohesivebranchfunconeel.C index fcc1ffa22..f572c99d0 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontcohesivebranchfunconeel.C +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontcohesivebranchfunconeel.C @@ -19,15 +19,11 @@ namespace oofem { REGISTER_EnrichmentFront(EnrFrontCohesiveBranchFuncOneEl) -EnrFrontCohesiveBranchFuncOneEl::EnrFrontCohesiveBranchFuncOneEl() -{ - mpBranchFunc = new CohesiveBranchFunction(); -} +EnrFrontCohesiveBranchFuncOneEl::EnrFrontCohesiveBranchFuncOneEl() : + mpBranchFunc() +{ } -EnrFrontCohesiveBranchFuncOneEl::~EnrFrontCohesiveBranchFuncOneEl() -{ - delete mpBranchFunc; -} +EnrFrontCohesiveBranchFuncOneEl::~EnrFrontCohesiveBranchFuncOneEl() { } void EnrFrontCohesiveBranchFuncOneEl :: MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo) @@ -58,7 +54,7 @@ void EnrFrontCohesiveBranchFuncOneEl :: evaluateEnrFuncAt(std :: vector< double double r = 0.0, theta = 0.0; EnrichmentItem :: calcPolarCoord(r, theta, xTip, pos, n, t, iEfInput, flipTangent); - mpBranchFunc->evaluateEnrFuncAt(oEnrFunc, r, theta); + mpBranchFunc.evaluateEnrFuncAt(oEnrFunc, r, theta); #ifdef DEBUG for ( double val:oEnrFunc ) { @@ -84,7 +80,7 @@ void EnrFrontCohesiveBranchFuncOneEl :: evaluateEnrFuncDerivAt(std :: vector< Fl size_t sizeStart = oEnrFuncDeriv.size(); - mpBranchFunc->evaluateEnrFuncDerivAt(oEnrFuncDeriv, r, theta); + mpBranchFunc.evaluateEnrFuncDerivAt(oEnrFuncDeriv, r, theta); /** * Transform to global coordinates. @@ -107,17 +103,16 @@ void EnrFrontCohesiveBranchFuncOneEl :: evaluateEnrFuncJumps(std :: vector< doub const FloatArray &xTip = mTipInfo.mGlobalCoord; const FloatArray &gpCoord = iGP.giveGlobalCoordinates(); - double radius = gpCoord.distance(xTip); + double radius = distance(gpCoord, xTip); std :: vector< double >jumps; - mpBranchFunc->giveJump(jumps, radius); + mpBranchFunc.giveJump(jumps, radius); oEnrFuncJumps.insert( oEnrFuncJumps.end(), jumps.begin(), jumps.end() ); } -IRResultType EnrFrontCohesiveBranchFuncOneEl :: initializeFrom(InputRecord *ir) +void EnrFrontCohesiveBranchFuncOneEl :: initializeFrom(InputRecord &ir) { - return IRRT_OK; } void EnrFrontCohesiveBranchFuncOneEl :: giveInputRecord(DynamicInputRecord &input) diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontcohesivebranchfunconeel.h b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontcohesivebranchfunconeel.h index 8376d3ccd..a43e94573 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontcohesivebranchfunconeel.h +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontcohesivebranchfunconeel.h @@ -64,26 +64,26 @@ class OOFEM_EXPORT EnrFrontCohesiveBranchFuncOneEl : public EnrichmentFront EnrFrontCohesiveBranchFuncOneEl(); virtual ~EnrFrontCohesiveBranchFuncOneEl(); - virtual void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo); + void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo) override; - virtual int giveNumEnrichments(const DofManager &iDMan) const; - virtual int giveMaxNumEnrichments() const { return 1; } + int giveNumEnrichments(const DofManager &iDMan) const override; + int giveMaxNumEnrichments() const override { return 1; } // Evaluate the enrichment function and its derivative in front nodes. - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const; - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const; - virtual void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const; + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const override; + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const override; + void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const override; - virtual const char *giveClassName() const { return "EnrFrontCohesiveBranchFuncOneEl"; } - virtual const char *giveInputRecordName() const { return _IFT_EnrFrontCohesiveBranchFuncOneEl_Name; } + const char *giveClassName() const override { return "EnrFrontCohesiveBranchFuncOneEl"; } + const char *giveInputRecordName() const override { return _IFT_EnrFrontCohesiveBranchFuncOneEl_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual double giveSupportRadius() const { return 0.0; } + double giveSupportRadius() const override { return 0.0; } private: - CohesiveBranchFunction *mpBranchFunc; + CohesiveBranchFunction mpBranchFunc; }; } /* namespace oofem */ diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontdonothing.h b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontdonothing.h index 870cf3bf4..a508cb971 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontdonothing.h +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontdonothing.h @@ -61,24 +61,24 @@ class OOFEM_EXPORT EnrFrontDoNothing : public EnrichmentFront EnrFrontDoNothing(int iEIindex = 0) : EnrichmentFront(iEIindex) { } virtual ~EnrFrontDoNothing() { } - virtual void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo) { mTipInfo = iTipInfo; } + void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo) override { mTipInfo = iTipInfo; } // No special tip enrichments are applied with this model. - virtual int giveNumEnrichments(const DofManager &iDMan) const { return 0; } - virtual int giveMaxNumEnrichments() const { return 0; } + int giveNumEnrichments(const DofManager &iDMan) const override { return 0; } + int giveMaxNumEnrichments() const override { return 0; } // Evaluate the enrichment function and its derivative in front nodes. - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const { } - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const { } - virtual void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const { } + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const override { } + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const override { } + void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const override { } - virtual const char *giveClassName() const { return "EnrFrontDoNothing"; } - virtual const char *giveInputRecordName() const { return _IFT_EnrFrontDoNothing_Name; } + const char *giveClassName() const override { return "EnrFrontDoNothing"; } + const char *giveInputRecordName() const override { return _IFT_EnrFrontDoNothing_Name; } - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override { } + void giveInputRecord(DynamicInputRecord &input) override; - virtual double giveSupportRadius() const { return 0.0; } + double giveSupportRadius() const override { return 0.0; } }; } // end namespace oofem diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontextend.h b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontextend.h index 67e9cad86..677f3ea39 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontextend.h +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontextend.h @@ -61,26 +61,26 @@ class OOFEM_EXPORT EnrFrontExtend : public EnrichmentFront EnrFrontExtend() { } virtual ~EnrFrontExtend() { } - virtual void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo); + void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo) override; // No special tip enrichments are applied with this model, // it only modifies the set of nodes subject to bulk enrichment. - virtual int giveNumEnrichments(const DofManager &iDMan) const { return 0; } - virtual int giveMaxNumEnrichments() const { return 0; } + int giveNumEnrichments(const DofManager &iDMan) const override { return 0; } + int giveMaxNumEnrichments() const override { return 0; } // Evaluate the enrichment function and its derivative in front nodes. - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const { } - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const { } - virtual void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const { } + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const override { } + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const override { } + void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const override { } - virtual const char *giveClassName() const { return "EnrFrontExtend"; } - virtual const char *giveInputRecordName() const { return _IFT_EnrFrontExtend_Name; } + const char *giveClassName() const override { return "EnrFrontExtend"; } + const char *giveInputRecordName() const override { return _IFT_EnrFrontExtend_Name; } - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override { } + void giveInputRecord(DynamicInputRecord &input) override; - virtual double giveSupportRadius() const { return 0.0; } + double giveSupportRadius() const override { return 0.0; } }; } // end namespace oofem diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontintersection.C b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontintersection.C index 350419dee..98c5a95de 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontintersection.C +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontintersection.C @@ -120,12 +120,9 @@ void EnrFrontIntersection :: evaluateEnrFuncJumps(std :: vector< double > &oEnrF oEnrFuncJumps.insert( oEnrFuncJumps.end(), jumps.begin(), jumps.end() ); } -IRResultType EnrFrontIntersection :: initializeFrom(InputRecord *ir) +void EnrFrontIntersection :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro IR_GIVE_FIELD(ir, mTangent, _IFT_EnrFrontIntersection_Tangent); - - return IRRT_OK; } void EnrFrontIntersection :: giveInputRecord(DynamicInputRecord &input) diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontintersection.h b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontintersection.h index ef7bad004..cca4f35e0 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontintersection.h +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontintersection.h @@ -63,24 +63,24 @@ class EnrFrontIntersection : public EnrichmentFront EnrFrontIntersection(); virtual ~EnrFrontIntersection(); - virtual void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo); + void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo) override; - virtual int giveNumEnrichments(const DofManager &iDMan) const; - virtual int giveMaxNumEnrichments() const { return 1; } + int giveNumEnrichments(const DofManager &iDMan) const override; + int giveMaxNumEnrichments() const override { return 1; } // Evaluate the enrichment function and its derivative in front nodes. - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const; - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const; - virtual void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const; + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const override; + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const override; + void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const override; - virtual const char *giveClassName() const { return "EnrFrontIntersection"; } - virtual const char *giveInputRecordName() const { return _IFT_EnrFrontIntersection_Name; } + const char *giveClassName() const override { return "EnrFrontIntersection"; } + const char *giveInputRecordName() const override { return _IFT_EnrFrontIntersection_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual double giveSupportRadius() const { return 0.0; } - virtual bool propagationIsAllowed() const { return false; } + double giveSupportRadius() const override { return 0.0; } + bool propagationIsAllowed() const override { return false; } void setTangent(FloatArray iTangent) { mTangent = std :: move(iTangent); } diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfunconeel.C b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfunconeel.C index b9a7775f5..53ecab167 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfunconeel.C +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfunconeel.C @@ -46,18 +46,11 @@ namespace oofem { REGISTER_EnrichmentFront(EnrFrontLinearBranchFuncOneEl) -EnrFrontLinearBranchFuncOneEl :: EnrFrontLinearBranchFuncOneEl() -{ - mpBranchFunc = new LinElBranchFunction(); -} +EnrFrontLinearBranchFuncOneEl :: EnrFrontLinearBranchFuncOneEl() : + mpBranchFunc() +{ } -EnrFrontLinearBranchFuncOneEl :: ~EnrFrontLinearBranchFuncOneEl() -{ - if ( mpBranchFunc != NULL ) { - delete mpBranchFunc; - mpBranchFunc = NULL; - } -} +EnrFrontLinearBranchFuncOneEl :: ~EnrFrontLinearBranchFuncOneEl() { } void EnrFrontLinearBranchFuncOneEl :: MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo) @@ -88,7 +81,7 @@ void EnrFrontLinearBranchFuncOneEl :: evaluateEnrFuncAt(std :: vector< double > double r = 0.0, theta = 0.0; EnrichmentItem :: calcPolarCoord(r, theta, xTip, pos, n, t, iEfInput, flipTangent); - mpBranchFunc->evaluateEnrFuncAt(oEnrFunc, r, theta); + mpBranchFunc.evaluateEnrFuncAt(oEnrFunc, r, theta); #ifdef DEBUG for ( double val:oEnrFunc ) { @@ -114,7 +107,7 @@ void EnrFrontLinearBranchFuncOneEl :: evaluateEnrFuncDerivAt(std :: vector< Floa size_t sizeStart = oEnrFuncDeriv.size(); - mpBranchFunc->evaluateEnrFuncDerivAt(oEnrFuncDeriv, r, theta); + mpBranchFunc.evaluateEnrFuncDerivAt(oEnrFuncDeriv, r, theta); /** * Transform to global coordinates. @@ -137,17 +130,16 @@ void EnrFrontLinearBranchFuncOneEl :: evaluateEnrFuncJumps(std :: vector< double const FloatArray &xTip = mTipInfo.mGlobalCoord; const FloatArray &gpCoord = iGP.giveGlobalCoordinates(); - double radius = gpCoord.distance(xTip); + double radius = distance(gpCoord, xTip); std :: vector< double >jumps; - mpBranchFunc->giveJump(jumps, radius); + mpBranchFunc.giveJump(jumps, radius); oEnrFuncJumps.insert( oEnrFuncJumps.end(), jumps.begin(), jumps.end() ); } -IRResultType EnrFrontLinearBranchFuncOneEl :: initializeFrom(InputRecord *ir) +void EnrFrontLinearBranchFuncOneEl :: initializeFrom(InputRecord &ir) { - return IRRT_OK; } void EnrFrontLinearBranchFuncOneEl :: giveInputRecord(DynamicInputRecord &input) diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfunconeel.h b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfunconeel.h index 462ab669a..576b45fb5 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfunconeel.h +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfunconeel.h @@ -63,26 +63,26 @@ class OOFEM_EXPORT EnrFrontLinearBranchFuncOneEl : public EnrichmentFront EnrFrontLinearBranchFuncOneEl(); virtual ~EnrFrontLinearBranchFuncOneEl(); - virtual void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo); + void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo) override; - virtual int giveNumEnrichments(const DofManager &iDMan) const; - virtual int giveMaxNumEnrichments() const { return 4; } + int giveNumEnrichments(const DofManager &iDMan) const override; + int giveMaxNumEnrichments() const override { return 4; } // Evaluate the enrichment function and its derivative in front nodes. - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const; - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const; - virtual void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const; + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const override; + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const override; + void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const override; - virtual const char *giveClassName() const { return "EnrFrontLinearBranchFuncOneEl"; } - virtual const char *giveInputRecordName() const { return _IFT_EnrFrontLinearBranchFuncOneEl_Name; } + const char *giveClassName() const override { return "EnrFrontLinearBranchFuncOneEl"; } + const char *giveInputRecordName() const override { return _IFT_EnrFrontLinearBranchFuncOneEl_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual double giveSupportRadius() const { return 0.0; } + double giveSupportRadius() const override { return 0.0; } private: - LinElBranchFunction *mpBranchFunc; + LinElBranchFunction mpBranchFunc; }; } // end namespace oofem diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfuncradius.C b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfuncradius.C index d2654eb47..06fb30aff 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfuncradius.C +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfuncradius.C @@ -45,18 +45,11 @@ namespace oofem { REGISTER_EnrichmentFront(EnrFrontLinearBranchFuncRadius) EnrFrontLinearBranchFuncRadius :: EnrFrontLinearBranchFuncRadius() : - mEnrichmentRadius(0.0) -{ - mpBranchFunc = new LinElBranchFunction(); -} + mEnrichmentRadius(0.0), + mpBranchFunc() +{ } -EnrFrontLinearBranchFuncRadius :: ~EnrFrontLinearBranchFuncRadius() -{ - if ( mpBranchFunc != NULL ) { - delete mpBranchFunc; - mpBranchFunc = NULL; - } -} +EnrFrontLinearBranchFuncRadius :: ~EnrFrontLinearBranchFuncRadius() { } void EnrFrontLinearBranchFuncRadius :: MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo) { @@ -76,9 +69,9 @@ void EnrFrontLinearBranchFuncRadius :: MarkNodesAsFront(std :: unordered_map< in for ( int i = 1; i <= nNodes; i++ ) { DofManager *dMan = d->giveDofManager(i); - const FloatArray &nodePos = * ( dMan->giveCoordinates() ); + const auto &nodePos = dMan->giveCoordinates(); - double radius2 = iTipInfo.mGlobalCoord.distance_square(nodePos); + double radius2 = distance_square(iTipInfo.mGlobalCoord, nodePos); if ( radius2 < mEnrichmentRadius * mEnrichmentRadius ) { if ( ( ioNodeEnrMarkerMap [ i ] == NodeEnr_START_TIP && iTipInfo.mTipIndex == 1 ) || @@ -120,7 +113,7 @@ void EnrFrontLinearBranchFuncRadius :: evaluateEnrFuncAt(std :: vector< double > double r = 0.0, theta = 0.0; EnrichmentItem :: calcPolarCoord(r, theta, xTip, pos, n, t, iEfInput, flipTangent); - mpBranchFunc->evaluateEnrFuncAt(oEnrFunc, r, theta); + mpBranchFunc.evaluateEnrFuncAt(oEnrFunc, r, theta); } void EnrFrontLinearBranchFuncRadius :: evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const @@ -137,7 +130,7 @@ void EnrFrontLinearBranchFuncRadius :: evaluateEnrFuncDerivAt(std :: vector< Flo size_t sizeStart = oEnrFuncDeriv.size(); - mpBranchFunc->evaluateEnrFuncDerivAt(oEnrFuncDeriv, r, theta); + mpBranchFunc.evaluateEnrFuncDerivAt(oEnrFuncDeriv, r, theta); /** * Transform to global coordinates. @@ -159,21 +152,17 @@ void EnrFrontLinearBranchFuncRadius :: evaluateEnrFuncJumps(std :: vector< doubl { const FloatArray &xTip = mTipInfo.mGlobalCoord; const FloatArray &gpCoord = iGP.giveGlobalCoordinates(); - double radius = gpCoord.distance(xTip); + double radius = distance(gpCoord, xTip); std :: vector< double >jumps; - mpBranchFunc->giveJump(jumps, radius); + mpBranchFunc.giveJump(jumps, radius); oEnrFuncJumps.insert( oEnrFuncJumps.end(), jumps.begin(), jumps.end() ); } -IRResultType EnrFrontLinearBranchFuncRadius :: initializeFrom(InputRecord *ir) +void EnrFrontLinearBranchFuncRadius :: initializeFrom(InputRecord &ir) { - IRResultType result; - IR_GIVE_FIELD(ir, mEnrichmentRadius, _IFT_EnrFrontLinearBranchFuncRadius_Radius); - - return IRRT_OK; } void EnrFrontLinearBranchFuncRadius :: giveInputRecord(DynamicInputRecord &input) diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfuncradius.h b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfuncradius.h index e5a1520e0..087294b00 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfuncradius.h +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontlinbranchfuncradius.h @@ -64,27 +64,27 @@ class OOFEM_EXPORT EnrFrontLinearBranchFuncRadius : public EnrichmentFront EnrFrontLinearBranchFuncRadius(); virtual ~EnrFrontLinearBranchFuncRadius(); - virtual void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo); + void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo) override; - virtual int giveNumEnrichments(const DofManager &iDMan) const; - virtual int giveMaxNumEnrichments() const { return 4; } + int giveNumEnrichments(const DofManager &iDMan) const override; + int giveMaxNumEnrichments() const override { return 4; } // Evaluate the enrichment function and its derivative in front nodes. - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const; - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const; - virtual void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const; + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const override; + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const override; + void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const override; - virtual const char *giveClassName() const { return "EnrFrontLinearBranchFuncRadius"; } - virtual const char *giveInputRecordName() const { return _IFT_EnrFrontLinearBranchFuncRadius_Name; } + const char *giveClassName() const override { return "EnrFrontLinearBranchFuncRadius"; } + const char *giveInputRecordName() const override { return _IFT_EnrFrontLinearBranchFuncRadius_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual double giveSupportRadius() const { return mEnrichmentRadius; } + double giveSupportRadius() const override { return mEnrichmentRadius; } private: double mEnrichmentRadius; - LinElBranchFunction *mpBranchFunc; + LinElBranchFunction mpBranchFunc; }; } // end namespace oofem diff --git a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontreducefront.h b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontreducefront.h index bf123d538..7718beed3 100644 --- a/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontreducefront.h +++ b/src/oofemlib/xfem/enrichmentfronts/enrichmentfrontreducefront.h @@ -61,26 +61,25 @@ class OOFEM_EXPORT EnrFrontReduceFront : public EnrichmentFront EnrFrontReduceFront() {}; virtual ~EnrFrontReduceFront() {}; - virtual void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo); + void MarkNodesAsFront(std :: unordered_map< int, NodeEnrichmentType > &ioNodeEnrMarkerMap, XfemManager &ixFemMan, const std :: unordered_map< int, double > &iLevelSetNormalDirMap, const std :: unordered_map< int, double > &iLevelSetTangDirMap, const TipInfo &iTipInfo) override; // No special tip enrichments are applied with this model, // it only modifies the set of nodes subject to bulk enrichment. - virtual int giveNumEnrichments(const DofManager &iDMan) const { return 0; } - virtual int giveMaxNumEnrichments() const { return 0; } + int giveNumEnrichments(const DofManager &iDMan) const override { return 0; } + int giveMaxNumEnrichments() const override { return 0; } // Evaluate the enrichment function and its derivative in front nodes. - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const {}; - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const {}; - virtual void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const {}; + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const EfInput &iEfInput) const override {} + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const EfInput &iEfInput, const FloatArray &iGradLevelSet) const override {} + void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, GaussPoint &iGP, int iNodeInd, bool iGPLivesOnCurrentCrack, const double &iNormalSignDist) const override {} + const char *giveClassName() const override { return "EnrFrontReduceFront"; } + const char *giveInputRecordName() const override { return _IFT_EnrFrontReduceFront_Name; } - virtual const char *giveClassName() const { return "EnrFrontReduceFront"; } - virtual const char *giveInputRecordName() const { return _IFT_EnrFrontReduceFront_Name; } + void initializeFrom(InputRecord &ir) override { } + void giveInputRecord(DynamicInputRecord &input) override; - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } - virtual void giveInputRecord(DynamicInputRecord &input); - - virtual double giveSupportRadius() const { return 0.0; } + double giveSupportRadius() const override { return 0.0; } }; } // end namespace oofem diff --git a/src/oofemlib/xfem/enrichmentfunction.C b/src/oofemlib/xfem/enrichmentfunction.C index 4ed2c1eaf..e2f5419f0 100644 --- a/src/oofemlib/xfem/enrichmentfunction.C +++ b/src/oofemlib/xfem/enrichmentfunction.C @@ -37,16 +37,15 @@ #include "mathfem.h" #include "feinterpol.h" #include "classfactory.h" -#include "dynamicdatareader.h" +#include "dynamicinputrecord.h" namespace oofem { REGISTER_EnrichmentFunction(DiscontinuousFunction) REGISTER_EnrichmentFunction(HeavisideFunction) REGISTER_EnrichmentFunction(RampFunction) -IRResultType EnrichmentFunction :: initializeFrom(InputRecord *ir) +void EnrichmentFunction :: initializeFrom(InputRecord &ir) { - return IRRT_OK; } void EnrichmentFunction :: giveInputRecord(DynamicInputRecord &input) diff --git a/src/oofemlib/xfem/enrichmentfunction.h b/src/oofemlib/xfem/enrichmentfunction.h index d4c9f7fce..db3581432 100644 --- a/src/oofemlib/xfem/enrichmentfunction.h +++ b/src/oofemlib/xfem/enrichmentfunction.h @@ -59,6 +59,9 @@ class GaussPoint; */ class OOFEM_EXPORT EnrichmentFunction : public FEMComponent { +protected: + int numberOfDofs; + public: /** * Constructor. @@ -80,14 +83,11 @@ class OOFEM_EXPORT EnrichmentFunction : public FEMComponent */ virtual void giveJump(std :: vector< double > &oJumps) const = 0; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveClassName() const { return "EnrichmentFunction"; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveClassName() const override { return "EnrichmentFunction"; } int giveNumberOfDofs() const { return numberOfDofs; } -protected: - - int numberOfDofs; }; /** Class representing Sign EnrichmentFunction. */ @@ -98,16 +98,16 @@ class OOFEM_EXPORT DiscontinuousFunction : public EnrichmentFunction this->numberOfDofs = 1; } - virtual void evaluateEnrFuncAt(double &oEnrFunc, const FloatArray &iPos, const double &iLevelSet) const; - virtual void evaluateEnrFuncDerivAt(FloatArray &oEnrFuncDeriv, const FloatArray &iPos, const double &iLevelSet, const FloatArray &iGradLevelSet) const; + void evaluateEnrFuncAt(double &oEnrFunc, const FloatArray &iPos, const double &iLevelSet) const override; + void evaluateEnrFuncDerivAt(FloatArray &oEnrFuncDeriv, const FloatArray &iPos, const double &iLevelSet, const FloatArray &iGradLevelSet) const override; - virtual void giveJump(std :: vector< double > &oJumps) const { + void giveJump(std :: vector< double > &oJumps) const override { oJumps.clear(); oJumps.push_back(2.0); } - virtual const char *giveClassName() const { return "DiscontinuousFunction"; } - virtual const char *giveInputRecordName() const { return _IFT_DiscontinuousFunction_Name; } + const char *giveClassName() const override { return "DiscontinuousFunction"; } + const char *giveInputRecordName() const override { return _IFT_DiscontinuousFunction_Name; } }; /** @@ -122,16 +122,16 @@ class OOFEM_EXPORT HeavisideFunction : public EnrichmentFunction this->numberOfDofs = 1; } - virtual void evaluateEnrFuncAt(double &oEnrFunc, const FloatArray &iPos, const double &iLevelSet) const; - virtual void evaluateEnrFuncDerivAt(FloatArray &oEnrFuncDeriv, const FloatArray &iPos, const double &iLevelSet, const FloatArray &iGradLevelSet) const; + void evaluateEnrFuncAt(double &oEnrFunc, const FloatArray &iPos, const double &iLevelSet) const override; + void evaluateEnrFuncDerivAt(FloatArray &oEnrFuncDeriv, const FloatArray &iPos, const double &iLevelSet, const FloatArray &iGradLevelSet) const override; - virtual void giveJump(std :: vector< double > &oJumps) const { + void giveJump(std :: vector< double > &oJumps) const override { oJumps.clear(); oJumps.push_back(1.0); } - virtual const char *giveClassName() const { return "HeavisideFunction"; } - virtual const char *giveInputRecordName() const { return _IFT_HeavisideFunction_Name; } + const char *giveClassName() const override { return "HeavisideFunction"; } + const char *giveInputRecordName() const override { return _IFT_HeavisideFunction_Name; } }; /** Class representing the four classical linear elastic branch functions. */ @@ -139,36 +139,34 @@ class OOFEM_EXPORT LinElBranchFunction { public: LinElBranchFunction() { } - virtual ~LinElBranchFunction() { } - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const double &iR, const double &iTheta) const; - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const double &iR, const double &iTheta) const; + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const double &iR, const double &iTheta) const; + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const double &iR, const double &iTheta) const; - virtual void giveJump(std :: vector< double > &oJumps) const; - virtual void giveJump(std :: vector< double > &oJumps, const double &iRadius) const; + void giveJump(std :: vector< double > &oJumps) const; + void giveJump(std :: vector< double > &oJumps, const double &iRadius) const; std :: string errorInfo(const char *func) const { return std :: string( giveClassName() ) + func; } - virtual const char *giveClassName() const { return "LinElBranchFunction"; } + const char *giveClassName() const { return "LinElBranchFunction"; } }; /** Class representing a branch function for cohesive cracks. */ class OOFEM_EXPORT CohesiveBranchFunction { +protected: + double mExponent; + public: - CohesiveBranchFunction():mExponent(0.5) { } - virtual ~CohesiveBranchFunction() { } + CohesiveBranchFunction() : mExponent(0.5) { } - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const double &iR, const double &iTheta) const; - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const double &iR, const double &iTheta) const; + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const double &iR, const double &iTheta) const; + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const double &iR, const double &iTheta) const; - virtual void giveJump(std :: vector< double > &oJumps) const; - virtual void giveJump(std :: vector< double > &oJumps, const double &iRadius) const; + void giveJump(std :: vector< double > &oJumps) const; + void giveJump(std :: vector< double > &oJumps, const double &iRadius) const; std :: string errorInfo(const char *func) const { return std :: string( giveClassName() ) + func; } - virtual const char *giveClassName() const { return "CohesiveBranchFunction"; } - -protected: - double mExponent; + const char *giveClassName() const { return "CohesiveBranchFunction"; } }; /** Class representing bimaterial interface. */ @@ -180,16 +178,16 @@ class OOFEM_EXPORT RampFunction : public EnrichmentFunction this->numberOfDofs = 1; } - virtual void evaluateEnrFuncAt(double &oEnrFunc, const FloatArray &iPos, const double &iLevelSet) const; - virtual void evaluateEnrFuncDerivAt(FloatArray &oEnrFuncDeriv, const FloatArray &iPos, const double &iLevelSet, const FloatArray &iGradLevelSet) const; + void evaluateEnrFuncAt(double &oEnrFunc, const FloatArray &iPos, const double &iLevelSet) const override; + void evaluateEnrFuncDerivAt(FloatArray &oEnrFuncDeriv, const FloatArray &iPos, const double &iLevelSet, const FloatArray &iGradLevelSet) const override; - virtual void giveJump(std :: vector< double > &oJumps) const { + void giveJump(std :: vector< double > &oJumps) const override { oJumps.clear(); oJumps.push_back(0.0); } - virtual const char *giveClassName() const { return "RampFunction"; } - virtual const char *giveInputRecordName() const { return _IFT_RampFunction_Name; } + const char *giveClassName() const override { return "RampFunction"; } + const char *giveInputRecordName() const override { return _IFT_RampFunction_Name; } }; } // end namespace oofem #endif // enrichmentfunction_h diff --git a/src/oofemlib/xfem/enrichmentitem.C b/src/oofemlib/xfem/enrichmentitem.C index a3ab16dad..c4e2e6b3b 100644 --- a/src/oofemlib/xfem/enrichmentitem.C +++ b/src/oofemlib/xfem/enrichmentitem.C @@ -46,7 +46,6 @@ #include "masterdof.h" #include "propagationlaw.h" #include "dynamicinputrecord.h" -#include "dynamicdatareader.h" #include "XFEMDebugTools.h" #include "xfemtolerances.h" #include "spatiallocalizer.h" @@ -67,11 +66,7 @@ const double EnrichmentItem :: mLevelSetRelTol = 1.0e-3; EnrichmentItem :: EnrichmentItem(int n, XfemManager *xMan, Domain *aDomain) : FEMComponent(n, aDomain), - mpEnrichmentFunc(NULL), - mpEnrichmentFrontStart(NULL), - mpEnrichmentFrontEnd(NULL), mEnrFrontIndex(0), - mpPropagationLaw(NULL), mPropLawIndex(0), mInheritBoundaryConditions(false), mInheritOrderedBoundaryConditions(false), @@ -84,16 +79,10 @@ EnrichmentItem :: EnrichmentItem(int n, XfemManager *xMan, Domain *aDomain) : FE EnrichmentItem :: ~EnrichmentItem() { - delete mpEnrichmentFunc; - delete mpEnrichmentFrontStart; - delete mpEnrichmentFrontEnd; - delete mpPropagationLaw; } -IRResultType EnrichmentItem :: initializeFrom(InputRecord *ir) +void EnrichmentItem :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - mEnrFrontIndex = 0; IR_GIVE_OPTIONAL_FIELD(ir, mEnrFrontIndex, _IFT_EnrichmentItem_front); @@ -101,14 +90,12 @@ IRResultType EnrichmentItem :: initializeFrom(InputRecord *ir) mPropLawIndex = 0; IR_GIVE_OPTIONAL_FIELD(ir, mPropLawIndex, _IFT_EnrichmentItem_propagationlaw); - if ( ir->hasField(_IFT_EnrichmentItem_inheritbc) ) { + if ( ir.hasField(_IFT_EnrichmentItem_inheritbc) ) { mInheritBoundaryConditions = true; } - if ( ir->hasField(_IFT_EnrichmentItem_inheritorderedbc) ) { + if ( ir.hasField(_IFT_EnrichmentItem_inheritorderedbc) ) { mInheritOrderedBoundaryConditions = true; } - - return IRRT_OK; } @@ -123,11 +110,11 @@ EnrichmentItem :: giveNumberOfEnrDofs() const { int numEnrDofs = mpEnrichmentFunc->giveNumberOfDofs(); - if ( mpEnrichmentFrontStart != NULL ) { + if ( mpEnrichmentFrontStart ) { numEnrDofs = max( numEnrDofs, mpEnrichmentFrontStart->giveMaxNumEnrichments() ); } - if ( mpEnrichmentFrontEnd != NULL ) { + if ( mpEnrichmentFrontEnd ) { numEnrDofs = max( numEnrDofs, mpEnrichmentFrontEnd->giveMaxNumEnrichments() ); } @@ -147,7 +134,7 @@ bool EnrichmentItem :: isElementEnriched(const Element *element) const int EnrichmentItem :: giveNumDofManEnrichments(const DofManager &iDMan) const { - int nodeInd = iDMan.giveGlobalNumber(); + int nodeInd = iDMan.giveGlobalNumber(); auto res = mNodeEnrMarkerMap.find(nodeInd); if ( res != mNodeEnrMarkerMap.end() ) { @@ -185,7 +172,7 @@ bool EnrichmentItem :: isMaterialModified(GaussPoint &iGP, Element &iEl, CrossSe bool EnrichmentItem :: hasPropagatingFronts() const { - if ( mpPropagationLaw == NULL ) { + if ( mpPropagationLaw == nullptr ) { return false; } @@ -302,21 +289,21 @@ void EnrichmentItem :: createEnrichedDofs() if ( isDofManEnriched(* dMan) ) { //printf("dofMan %i is enriched \n", dMan->giveNumber()); computeEnrichedDofManDofIdArray(EnrDofIdArray, * dMan); - + // Collect boundary condition ID of existing dofs IntArray bcIndexArray; for ( Dof *dof: *dMan ) { bcIndexArray.followedBy(dof->giveBcId()); - } - + } + bool foundBC = false; IntArray nonZeroBC; if ( !bcIndexArray.containsOnlyZeroes() ) { // BC is found on dofs foundBC = true; nonZeroBC.findNonzeros(bcIndexArray); - } - + } + int iDof(1); for ( auto &dofid: EnrDofIdArray ) { if ( !dMan->hasDofID( ( DofIDItem ) ( dofid ) ) ) { @@ -355,7 +342,7 @@ void EnrichmentItem :: createEnrichedDofs() computeEnrichedDofManDofIdArray(EnrDofIdArray, * dMan); std :: vector< DofIDItem >dofsToRemove; - for ( Dof *dof: *dMan ) { + for ( auto &dof: *dMan ) { DofIDItem dofID = dof->giveDofID(); if ( dofID >= DofIDItem(poolStart) && dofID <= DofIDItem(poolEnd) ) { @@ -413,7 +400,7 @@ void EnrichmentItem :: calcPolarCoord(double &oR, double &oTheta, const FloatArr const double tol = 1.0e-20; // Compute polar coordinates - oR = iOrigin.distance(iPos); + oR = distance(iOrigin, iPos); if ( oR > tol ) { q.times(1.0 / oR); @@ -464,14 +451,10 @@ void EnrichmentItem :: calcPolarCoord(double &oR, double &oTheta, const FloatArr } } -void EnrichmentItem :: setPropagationLaw(PropagationLaw *ipPropagationLaw) +void EnrichmentItem :: setPropagationLaw(std::unique_ptr ipPropagationLaw) { - if(mpPropagationLaw != NULL) { - delete mpPropagationLaw; - } - - mpPropagationLaw = ipPropagationLaw; - mPropLawIndex = 1; + mpPropagationLaw = std::move(ipPropagationLaw); + mPropLawIndex = 1; } void EnrichmentItem :: callGnuplotExportModule(GnuplotExportModule &iExpMod, TimeStep *tStep) @@ -479,22 +462,22 @@ void EnrichmentItem :: callGnuplotExportModule(GnuplotExportModule &iExpMod, Tim //iExpMod.outputXFEM(*this); } -void EnrichmentItem :: setEnrichmentFrontStart(EnrichmentFront *ipEnrichmentFrontStart, bool iDeleteOld) +void EnrichmentItem :: setEnrichmentFrontStart(std::unique_ptr ipEnrichmentFrontStart, bool iDeleteOld) { - if(iDeleteOld) { - delete mpEnrichmentFrontStart; - } + if( ! iDeleteOld ) { + mpEnrichmentFrontStart.release(); ///@note This is bad bad code + } - mpEnrichmentFrontStart = ipEnrichmentFrontStart; + mpEnrichmentFrontStart = std::move(ipEnrichmentFrontStart); } -void EnrichmentItem :: setEnrichmentFrontEnd(EnrichmentFront *ipEnrichmentFrontEnd, bool iDeleteOld) +void EnrichmentItem :: setEnrichmentFrontEnd(std::unique_ptr ipEnrichmentFrontEnd, bool iDeleteOld) { - if(iDeleteOld) { - delete mpEnrichmentFrontEnd; - } + if ( !iDeleteOld ) { + mpEnrichmentFrontEnd.release(); ///@note This is bad bad code + } - mpEnrichmentFrontEnd = ipEnrichmentFrontEnd; + mpEnrichmentFrontEnd = std::move(ipEnrichmentFrontEnd); } bool EnrichmentItem :: tipIsTouchingEI(const TipInfo &iTipInfo) @@ -503,7 +486,7 @@ bool EnrichmentItem :: tipIsTouchingEI(const TipInfo &iTipInfo) SpatialLocalizer *localizer = giveDomain()->giveSpatialLocalizer(); Element *tipEl = localizer->giveElementContainingPoint(iTipInfo.mGlobalCoord); - if ( tipEl != NULL ) { + if ( tipEl ) { // Check if the candidate tip is located on the current crack FloatArray N; FloatArray locCoord; diff --git a/src/oofemlib/xfem/enrichmentitem.h b/src/oofemlib/xfem/enrichmentitem.h index 34b541119..f00b84e7a 100644 --- a/src/oofemlib/xfem/enrichmentitem.h +++ b/src/oofemlib/xfem/enrichmentitem.h @@ -41,6 +41,7 @@ #include "intarray.h" #include "dofmanager.h" #include "xfem/enrichmentfronts/enrichmentfront.h" +#include "xfem/enrichmentfunction.h" #include "error.h" #include @@ -110,7 +111,9 @@ class OOFEM_EXPORT EnrichmentItem : public FEMComponent EnrichmentItem(int n, XfemManager *xm, Domain *aDomain); virtual ~EnrichmentItem(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; + virtual int instanciateYourself(DataReader &dr) = 0; + virtual void postInitialize() = 0; /** * Note the special treatment here, the "normal" syntax @@ -120,11 +123,10 @@ class OOFEM_EXPORT EnrichmentItem : public FEMComponent * EnrichmentDomain, EnrichmentFront and PropagationLaw * without have to keep track of them globally. */ - virtual void giveInputRecord(DynamicInputRecord &input) { OOFEM_ERROR("This function must be called with DynamicDataReader as input."); } + void giveInputRecord(DynamicInputRecord &input) override + { OOFEM_ERROR("This function must be called with DynamicDataReader as input."); } virtual void appendInputRecords(DynamicDataReader &oDR) = 0; - virtual int instanciateYourself(DataReader *dr) = 0; - virtual const char *giveClassName() const = 0; const IntArray *giveEnrichesDofsWithIdArray() const { return & mpEnrichesDofsWithIdArray; } int giveNumberOfEnrDofs() const; @@ -153,7 +155,6 @@ class OOFEM_EXPORT EnrichmentItem : public FEMComponent virtual bool hasInitiationCriteria() { return false; } - int giveStartOfDofIdPool() const { return this->startOfDofIdPool; } int giveEndOfDofIdPool() const { return this->endOfDofIdPool; } virtual int giveDofPoolSize() const; @@ -215,8 +216,8 @@ class OOFEM_EXPORT EnrichmentItem : public FEMComponent static double calcXiZeroLevel(const double &iQ1, const double &iQ2); static void calcPolarCoord(double &oR, double &oTheta, const FloatArray &iOrigin, const FloatArray &iPos, const FloatArray &iN, const FloatArray &iT, const EfInput &iEfInput, bool iFlipTangent); - PropagationLaw *givePropagationLaw() { return this->mpPropagationLaw; } - void setPropagationLaw(PropagationLaw *ipPropagationLaw); + PropagationLaw *givePropagationLaw() { return this->mpPropagationLaw.get(); } + void setPropagationLaw(std::unique_ptr ipPropagationLaw); bool hasPropagationLaw() { return this->mPropLawIndex != 0; } @@ -227,26 +228,26 @@ class OOFEM_EXPORT EnrichmentItem : public FEMComponent virtual void giveBoundingSphere(FloatArray &oCenter, double &oRadius) = 0; - EnrichmentFront *giveEnrichmentFrontStart() { return mpEnrichmentFrontStart; } - void setEnrichmentFrontStart(EnrichmentFront *ipEnrichmentFrontStart, bool iDeleteOld = true); + EnrichmentFront *giveEnrichmentFrontStart() { return mpEnrichmentFrontStart.get(); } + void setEnrichmentFrontStart(std::unique_ptr ipEnrichmentFrontStart, bool iDeleteOld = true); - EnrichmentFront *giveEnrichmentFrontEnd() { return mpEnrichmentFrontEnd; } - void setEnrichmentFrontEnd(EnrichmentFront *ipEnrichmentFrontEnd, bool iDeleteOld = true); + EnrichmentFront *giveEnrichmentFrontEnd() { return mpEnrichmentFrontEnd.get(); } + void setEnrichmentFrontEnd(std::unique_ptr ipEnrichmentFrontEnd, bool iDeleteOld = true); bool tipIsTouchingEI(const TipInfo &iTipInfo); - void setEnrichmentFunction(EnrichmentFunction *ipEnrichmentFunc) {mpEnrichmentFunc = ipEnrichmentFunc;} + void setEnrichmentFunction(std::unique_ptr ipEnrichmentFunc) { mpEnrichmentFunc = std::move(ipEnrichmentFunc); } protected: - EnrichmentFunction *mpEnrichmentFunc; + std::unique_ptr mpEnrichmentFunc; - EnrichmentFront *mpEnrichmentFrontStart, *mpEnrichmentFrontEnd; + std::unique_ptr mpEnrichmentFrontStart, mpEnrichmentFrontEnd; /// mEnrFrontIndex: nonzero if an enrichment front is present, zero otherwise. int mEnrFrontIndex; - PropagationLaw *mpPropagationLaw; + std::unique_ptr mpPropagationLaw; /// mPropLawIndex: nonzero if a propagation law is present, zero otherwise. int mPropLawIndex; diff --git a/src/oofemlib/xfem/geometrybasedei.C b/src/oofemlib/xfem/geometrybasedei.C index bd6fbaa1f..9d1ae88d4 100644 --- a/src/oofemlib/xfem/geometrybasedei.C +++ b/src/oofemlib/xfem/geometrybasedei.C @@ -68,59 +68,57 @@ GeometryBasedEI :: GeometryBasedEI(int n, XfemManager *xm, Domain *aDomain) : GeometryBasedEI :: ~GeometryBasedEI() {} -int GeometryBasedEI :: instanciateYourself(DataReader *dr) +int GeometryBasedEI :: instanciateYourself(DataReader &dr) { - IRResultType result; // Required by IR_GIVE_FIELD macro std :: string name; // Instantiate enrichment function - InputRecord *mir = dr->giveInputRecord(DataReader :: IR_enrichFuncRec, 1); - result = mir->giveRecordKeywordField(name); + { + auto &mir = dr.giveInputRecord(DataReader :: IR_enrichFuncRec, 1); + mir.giveRecordKeywordField(name); - if ( result != IRRT_OK ) { - mir->report_error(this->giveClassName(), __func__, "", result, __FILE__, __LINE__); - } - - mpEnrichmentFunc = classFactory.createEnrichmentFunction( name.c_str(), 1, this->giveDomain() ); - if ( mpEnrichmentFunc != NULL ) { - mpEnrichmentFunc->initializeFrom(mir); - } else { - OOFEM_ERROR( "failed to create enrichment function (%s)", name.c_str() ); + mpEnrichmentFunc = classFactory.createEnrichmentFunction( name.c_str(), 1, this->giveDomain() ); + if ( mpEnrichmentFunc ) { + mpEnrichmentFunc->initializeFrom(mir); + } else { + OOFEM_ERROR( "failed to create enrichment function (%s)", name.c_str() ); + } } - // Instantiate geometry - mir = dr->giveInputRecord(DataReader :: IR_geoRec, 1); - result = mir->giveRecordKeywordField(name); - mpBasicGeometry.reset( classFactory.createGeometry( name.c_str() ) ); - if ( !mpBasicGeometry ) { - OOFEM_ERROR( "unknown geometry domain (%s)", name.c_str() ); - } + { + auto &mir = dr.giveInputRecord(DataReader :: IR_geoRec, 1); + mir.giveRecordKeywordField(name); + mpBasicGeometry = classFactory.createGeometry( name.c_str() ); + if ( !mpBasicGeometry ) { + OOFEM_ERROR( "unknown geometry domain (%s)", name.c_str() ); + } - mpBasicGeometry->initializeFrom(mir); + mpBasicGeometry->initializeFrom(mir); + } // Instantiate EnrichmentFront if ( mEnrFrontIndex == 0 ) { - mpEnrichmentFrontStart = new EnrFrontDoNothing(); - mpEnrichmentFrontEnd = new EnrFrontDoNothing(); + mpEnrichmentFrontStart = std::make_unique(); + mpEnrichmentFrontEnd = std::make_unique(); } else { std :: string enrFrontNameStart, enrFrontNameEnd; - InputRecord *enrFrontStartIr = dr->giveInputRecord(DataReader :: IR_enrichFrontRec, mEnrFrontIndex); - result = enrFrontStartIr->giveRecordKeywordField(enrFrontNameStart); + auto &enrFrontStartIr = dr.giveInputRecord(DataReader :: IR_enrichFrontRec, mEnrFrontIndex); + enrFrontStartIr.giveRecordKeywordField(enrFrontNameStart); mpEnrichmentFrontStart = classFactory.createEnrichmentFront( enrFrontNameStart.c_str() ); - if ( mpEnrichmentFrontStart != NULL ) { + if ( mpEnrichmentFrontStart ) { mpEnrichmentFrontStart->initializeFrom(enrFrontStartIr); } else { OOFEM_ERROR( "Failed to create enrichment front (%s)", enrFrontNameStart.c_str() ); } - InputRecord *enrFrontEndIr = dr->giveInputRecord(DataReader :: IR_enrichFrontRec, mEnrFrontIndex); - result = enrFrontEndIr->giveRecordKeywordField(enrFrontNameEnd); + auto &enrFrontEndIr = dr.giveInputRecord(DataReader :: IR_enrichFrontRec, mEnrFrontIndex); + enrFrontEndIr.giveRecordKeywordField(enrFrontNameEnd); mpEnrichmentFrontEnd = classFactory.createEnrichmentFront( enrFrontNameEnd.c_str() ); - if ( mpEnrichmentFrontEnd != NULL ) { + if ( mpEnrichmentFrontEnd ) { mpEnrichmentFrontEnd->initializeFrom(enrFrontEndIr); } else { OOFEM_ERROR( "Failed to create enrichment front (%s)", enrFrontNameEnd.c_str() ); @@ -130,15 +128,15 @@ int GeometryBasedEI :: instanciateYourself(DataReader *dr) // Instantiate PropagationLaw if ( mPropLawIndex == 0 ) { - mpPropagationLaw = new PLDoNothing(); + mpPropagationLaw = std::make_unique(); } else { std :: string propLawName; - InputRecord *propLawir = dr->giveInputRecord(DataReader :: IR_propagationLawRec, mPropLawIndex); - result = propLawir->giveRecordKeywordField(propLawName); + auto &propLawir = dr.giveInputRecord(DataReader :: IR_propagationLawRec, mPropLawIndex); + propLawir.giveRecordKeywordField(propLawName); mpPropagationLaw = classFactory.createPropagationLaw( propLawName.c_str() ); - if ( mpPropagationLaw != NULL ) { + if ( mpPropagationLaw ) { mpPropagationLaw->initializeFrom(propLawir); } else { OOFEM_ERROR( "Failed to create propagation law (%s)", propLawName.c_str() ); @@ -151,16 +149,21 @@ int GeometryBasedEI :: instanciateYourself(DataReader *dr) this->endOfDofIdPool = this->startOfDofIdPool + xDofPoolAllocSize - 1; - XfemManager *xMan = this->giveDomain()->giveXfemManager(); + // mpEnrichmentDomain->CallNodeEnrMarkerUpdate(* this, * xMan); - this->updateNodeEnrMarker(* xMan); - + // this->updateNodeEnrMarker(* xMan); // moved to postInitialize // writeVtkDebug(); return 1; } +void GeometryBasedEI :: postInitialize() +{ + XfemManager *xMan = this->giveDomain()->giveXfemManager(); + this->updateNodeEnrMarker(* xMan); +} + void GeometryBasedEI :: updateDofIdPool() { // Set start of the enrichment dof pool for the given EI @@ -178,7 +181,7 @@ void GeometryBasedEI :: updateDofIdPool() void GeometryBasedEI :: appendInputRecords(DynamicDataReader &oDR) { - DynamicInputRecord *eiRec = new DynamicInputRecord(); + auto eiRec = std::unique_ptr(); FEMComponent :: giveInputRecord(* eiRec); eiRec->setField(mEnrFrontIndex, _IFT_EnrichmentItem_front); @@ -191,36 +194,35 @@ void GeometryBasedEI :: appendInputRecords(DynamicDataReader &oDR) eiRec->setField(_IFT_EnrichmentItem_inheritorderedbc); } - oDR.insertInputRecord(DataReader :: IR_enrichItemRec, eiRec); - + oDR.insertInputRecord(DataReader :: IR_enrichItemRec, std::move(eiRec)); // Enrichment function - DynamicInputRecord *efRec = new DynamicInputRecord(); + auto efRec = std::unique_ptr(); mpEnrichmentFunc->giveInputRecord(* efRec); - oDR.insertInputRecord(DataReader :: IR_enrichFuncRec, efRec); + oDR.insertInputRecord(DataReader :: IR_enrichFuncRec, std::move(efRec)); // Geometry - DynamicInputRecord *geoRec = new DynamicInputRecord(); + auto geoRec = std::unique_ptr(); mpBasicGeometry->giveInputRecord(* geoRec); - oDR.insertInputRecord(DataReader :: IR_geoRec, geoRec); + oDR.insertInputRecord(DataReader :: IR_geoRec, std::move(geoRec)); // Enrichment front if ( mEnrFrontIndex != 0 ) { - DynamicInputRecord *efrRecStart = new DynamicInputRecord(); + auto efrRecStart = std::unique_ptr(); mpEnrichmentFrontStart->giveInputRecord(* efrRecStart); - oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, efrRecStart); + oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, std::move(efrRecStart)); - DynamicInputRecord *efrRecEnd = new DynamicInputRecord(); + auto efrRecEnd = std::unique_ptr(); mpEnrichmentFrontEnd->giveInputRecord(* efrRecEnd); - oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, efrRecEnd); + oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, std::move(efrRecEnd)); } // Propagation law if ( mPropLawIndex != 0 ) { - DynamicInputRecord *plRec = new DynamicInputRecord(); + auto plRec = std::unique_ptr(); this->mpPropagationLaw->giveInputRecord(* plRec); - oDR.insertInputRecord(DataReader :: IR_propagationLawRec, plRec); + oDR.insertInputRecord(DataReader :: IR_propagationLawRec, std::move(plRec)); } } @@ -270,7 +272,7 @@ void GeometryBasedEI :: updateNodeEnrMarker(XfemManager &ixFemMan) int nGlob = el->giveNode(elNodeInd)->giveGlobalNumber(); double levelSetNormalNode = 0.0; - if ( evalLevelSetNormalInNode( levelSetNormalNode, nGlob, el->giveNode(elNodeInd)->giveNodeCoordinates() ) ) { + if ( evalLevelSetNormalInNode( levelSetNormalNode, nGlob, el->giveNode(elNodeInd)->giveCoordinates() ) ) { minSignPhi = std :: min( sgn(minSignPhi), sgn(levelSetNormalNode) ); maxSignPhi = std :: max( sgn(maxSignPhi), sgn(levelSetNormalNode) ); @@ -291,15 +293,14 @@ void GeometryBasedEI :: updateNodeEnrMarker(XfemManager &ixFemMan) int numEdges = el->giveInterpolation()->giveNumberOfEdges(); //JIM for ( int edgeIndex = 1; edgeIndex <= numEdges; edgeIndex++ ) { - IntArray bNodes; - el->giveInterpolation()->boundaryGiveNodes(bNodes, edgeIndex); + const auto &bNodes = el->giveInterpolation()->boundaryGiveNodes(edgeIndex); int niLoc = bNodes.at(1); int niGlob = el->giveNode(niLoc)->giveGlobalNumber(); - const FloatArray &nodePosI = el->giveNode(niLoc)->giveNodeCoordinates(); + const auto &nodePosI = el->giveNode(niLoc)->giveCoordinates(); int njLoc = bNodes.at(2); int njGlob = el->giveNode(njLoc)->giveGlobalNumber(); - const FloatArray &nodePosJ = el->giveNode(njLoc)->giveNodeCoordinates(); + const auto &nodePosJ = el->giveNode(njLoc)->giveCoordinates(); double levelSetNormalNodeI = 0.0; double levelSetNormalNodeJ = 0.0; @@ -310,8 +311,8 @@ void GeometryBasedEI :: updateNodeEnrMarker(XfemManager &ixFemMan) // Compute the exact value of the tangential level set // from the discretized geometry instead of interpolating. double tangDist = 0.0, arcPos = 0.0; - const FloatArray &posI = * ( el->giveDofManager(niLoc)->giveCoordinates() ); - const FloatArray &posJ = * ( el->giveDofManager(njLoc)->giveCoordinates() ); + const auto &posI = el->giveDofManager(niLoc)->giveCoordinates(); + const auto &posJ = el->giveDofManager(njLoc)->giveCoordinates(); FloatArray pos; pos.add(0.5 * ( 1.0 - xi ), posI); pos.add(0.5 * ( 1.0 + xi ), posJ); @@ -370,7 +371,7 @@ void GeometryBasedEI :: updateLevelSets(XfemManager &ixFemMan) Node *node = ixFemMan.giveDomain()->giveNode(nodeNum); // Extract node coord - FloatArray pos( * node->giveCoordinates() ); + FloatArray pos( node->giveCoordinates() ); pos.resizeWithValues(2); // Calc normal sign dist @@ -390,7 +391,7 @@ void GeometryBasedEI :: updateLevelSets(XfemManager &ixFemMan) void GeometryBasedEI :: evaluateEnrFuncInNode(std :: vector< double > &oEnrFunc, const Node &iNode) const { double levelSetGP = 0.0; - const FloatArray &globalCoord = iNode.giveNodeCoordinates(); + const FloatArray &globalCoord = iNode.giveCoordinates(); int nodeInd = iNode.giveNumber(); this->evalLevelSetNormalInNode(levelSetGP, nodeInd, globalCoord); @@ -617,8 +618,7 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o int numEdges = element->giveInterpolation()->giveNumberOfEdges(); for ( int edgeIndex = 1; edgeIndex <= numEdges; edgeIndex++ ) { - IntArray bNodes; - element->giveInterpolation()->boundaryGiveNodes(bNodes, edgeIndex); + const auto &bNodes = element->giveInterpolation()->boundaryGiveNodes(edgeIndex); int nsLoc = bNodes.at(1); int nsGlob = element->giveNode(nsLoc)->giveGlobalNumber(); @@ -626,14 +626,14 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o int neGlob = element->giveNode(neLoc)->giveGlobalNumber(); double phiS = 1.0; - bool foundPhiS = evalLevelSetNormalInNode( phiS, nsGlob, element->giveNode(nsLoc)->giveNodeCoordinates() ); + bool foundPhiS = evalLevelSetNormalInNode( phiS, nsGlob, element->giveNode(nsLoc)->giveCoordinates() ); double phiE = 1.0; - bool foundPhiE = evalLevelSetNormalInNode( phiE, neGlob, element->giveNode(neLoc)->giveNodeCoordinates() ); + bool foundPhiE = evalLevelSetNormalInNode( phiE, neGlob, element->giveNode(neLoc)->giveCoordinates() ); - const FloatArray &xS = * ( element->giveNode(nsLoc)->giveCoordinates() ); - const FloatArray &xE = * ( element->giveNode(neLoc)->giveCoordinates() ); - const double edgeLength2 = xS.distance_square(xE); + const auto &xS = element->giveNode(nsLoc)->giveCoordinates(); + const auto &xE = element->giveNode(neLoc)->giveCoordinates(); + const double edgeLength2 = distance_square(xS, xE); const double gammaRelTol = 1.0e-2; if ( ( foundPhiS && foundPhiE ) && phiS * phiE < mLevelSetRelTol * mLevelSetRelTol * edgeLength2 ) { @@ -644,8 +644,8 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o // Compute the exact value of the tangential level set // from the discretized geometry instead of interpolating. double tangDist = 0.0, arcPos = 0.0; - const FloatArray &posI = * ( element->giveDofManager(nsLoc)->giveCoordinates() ); - const FloatArray &posJ = * ( element->giveDofManager(neLoc)->giveCoordinates() ); + const auto &posI = element->giveDofManager(nsLoc)->giveCoordinates(); + const auto &posJ = element->giveDofManager(neLoc)->giveCoordinates(); FloatArray pos; pos.add(0.5 * ( 1.0 - xi ), posI); pos.add(0.5 * ( 1.0 + xi ), posJ); @@ -659,9 +659,9 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o if ( fabs(phiS - phiE) < mLevelSetTol ) { // If the crack is parallel to the edge. - FloatArray ps( * ( element->giveDofManager(nsLoc)->giveCoordinates() ) ); + FloatArray ps( element->giveDofManager(nsLoc)->giveCoordinates() ); ps.resizeWithValues(2); - FloatArray pe( * ( element->giveDofManager(neLoc)->giveCoordinates() ) ); + FloatArray pe( element->giveDofManager(neLoc)->giveCoordinates() ); pe.resizeWithValues(2); // Check that the intersection points have not already been identified. @@ -672,7 +672,7 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o int numPointsOld = oIntersectionPoints.size(); for ( int k = 1; k <= numPointsOld; k++ ) { - double dist = ps.distance(oIntersectionPoints [ k - 1 ]); + double dist = distance(ps, oIntersectionPoints [ k - 1 ]); if ( dist < mLevelSetTol ) { alreadyFound = true; @@ -694,7 +694,7 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o numPointsOld = oIntersectionPoints.size(); for ( int k = 1; k <= numPointsOld; k++ ) { - double dist = pe.distance(oIntersectionPoints [ k - 1 ]); + double dist = distance(pe, oIntersectionPoints [ k - 1 ]); if ( dist < mLevelSetTol ) { alreadyFound = true; @@ -712,11 +712,10 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o oIntersectedEdgeInd.push_back(edgeIndex); } } else { - FloatArray ps( * ( element->giveDofManager(nsLoc)->giveCoordinates() ) ); - FloatArray pe( * ( element->giveDofManager(neLoc)->giveCoordinates() ) ); + const auto &ps = element->giveDofManager(nsLoc)->giveCoordinates(); + const auto &pe = element->giveDofManager(neLoc)->giveCoordinates(); - FloatArray p; - p.resizeWithValues(2); + FloatArray p(2); for ( int i = 1; i <= 2; i++ ) { ( p.at(i) ) = 0.5 * ( 1.0 - xi ) * ( ( ps.at(i) ) ) + 0.5 * ( 1.0 + xi ) * ( ( pe.at(i) ) ); @@ -732,7 +731,7 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o int numPointsOld = oIntersectionPoints.size(); for ( int k = 1; k <= numPointsOld; k++ ) { - double dist = p.distance(oIntersectionPoints [ k - 1 ]); + double dist = distance(p, oIntersectionPoints [ k - 1 ]); if ( dist < mLevelSetTol ) { alreadyFound = true; @@ -807,28 +806,28 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o bool levelSetDefinedInAllNodes = true; for ( int i = 1; i <= Ns.giveSize(); i++ ) { double phiSNode = 0.0; - if ( evalLevelSetNormalInNode( phiSNode, elNodes [ i - 1 ], element->giveNode(i)->giveNodeCoordinates() ) ) { + if ( evalLevelSetNormalInNode( phiSNode, elNodes [ i - 1 ], element->giveNode(i)->giveCoordinates() ) ) { phiS += Ns.at(i) * phiSNode; } else { levelSetDefinedInAllNodes = false; } double gammaSNode = 0.0; - if ( evalLevelSetTangInNode( gammaSNode, elNodes [ i - 1 ], element->giveNode(i)->giveNodeCoordinates() ) ) { + if ( evalLevelSetTangInNode( gammaSNode, elNodes [ i - 1 ], element->giveNode(i)->giveCoordinates() ) ) { gammaS += Ns.at(i) * gammaSNode; } else { levelSetDefinedInAllNodes = false; } double phiENode = 0.0; - if ( evalLevelSetNormalInNode( phiENode, elNodes [ i - 1 ], element->giveNode(i)->giveNodeCoordinates() ) ) { + if ( evalLevelSetNormalInNode( phiENode, elNodes [ i - 1 ], element->giveNode(i)->giveCoordinates() ) ) { phiE += Ne.at(i) * phiENode; } else { levelSetDefinedInAllNodes = false; } double gammaENode = 0.0; - if ( evalLevelSetTangInNode( gammaENode, elNodes [ i - 1 ], element->giveNode(i)->giveNodeCoordinates() ) ) { + if ( evalLevelSetTangInNode( gammaENode, elNodes [ i - 1 ], element->giveNode(i)->giveCoordinates() ) ) { gammaE += Ne.at(i) * gammaENode; } else { levelSetDefinedInAllNodes = false; @@ -859,7 +858,7 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o int numPointsOld = oIntersectionPoints.size(); for ( int k = 1; k <= numPointsOld; k++ ) { - double dist = ps.distance(oIntersectionPoints [ k - 1 ]); + double dist = distance(ps, oIntersectionPoints [ k - 1 ]); if ( dist < mLevelSetTol ) { alreadyFound = true; @@ -881,7 +880,7 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o numPointsOld = oIntersectionPoints.size(); for ( int k = 1; k <= numPointsOld; k++ ) { - double dist = pe.distance(oIntersectionPoints [ k - 1 ]); + double dist = distance(pe, oIntersectionPoints [ k - 1 ]); if ( dist < mLevelSetTol ) { alreadyFound = true; @@ -920,7 +919,7 @@ void GeometryBasedEI :: computeIntersectionPoints(std :: vector< FloatArray > &o int numPointsOld = oIntersectionPoints.size(); for ( int k = 1; k <= numPointsOld; k++ ) { - double dist = p.distance(oIntersectionPoints [ k - 1 ]); + double dist = distance(p, oIntersectionPoints [ k - 1 ]); if ( dist < mLevelSetTol ) { alreadyFound = true; @@ -1025,8 +1024,9 @@ bool GeometryBasedEI :: giveElementTipCoord(FloatArray &oCoord, double &oArcPos, bool foundTip = false; for ( size_t i = 0; i < tipInfos.size(); i++ ) { - if ( tipInfos [ i ].mGlobalCoord.distance_square(iElCenter) < minDist2 ) { - minDist2 = tipInfos [ i ].mGlobalCoord.distance_square(iElCenter); + double d2 = distance_square(tipInfos [ i ].mGlobalCoord, iElCenter); + if ( d2 < minDist2 ) { + minDist2 = d2; minIndex = i; foundTip = true; } diff --git a/src/oofemlib/xfem/geometrybasedei.h b/src/oofemlib/xfem/geometrybasedei.h index 1e565c14b..52a5a5b59 100644 --- a/src/oofemlib/xfem/geometrybasedei.h +++ b/src/oofemlib/xfem/geometrybasedei.h @@ -57,27 +57,28 @@ class OOFEM_EXPORT GeometryBasedEI : public EnrichmentItem GeometryBasedEI(int n, XfemManager *xm, Domain *aDomain); virtual ~GeometryBasedEI(); - virtual int instanciateYourself(DataReader *dr); + int instanciateYourself(DataReader &dr) override; + void postInitialize() override; virtual void updateDofIdPool(); - virtual void appendInputRecords(DynamicDataReader &oDR); + void appendInputRecords(DynamicDataReader &oDR) override; - virtual const char *giveClassName() const { return "GeometryBasedEI"; } - virtual const char *giveInputRecordName() const { return _IFT_GeometryBasedEI_Name; } + const char *giveClassName() const override { return "GeometryBasedEI"; } + const char *giveInputRecordName() const override { return _IFT_GeometryBasedEI_Name; } - virtual void updateGeometry(); - virtual void updateNodeEnrMarker(XfemManager &ixFemMan); + void updateGeometry() override; + void updateNodeEnrMarker(XfemManager &ixFemMan) override; void updateLevelSets(XfemManager &ixFemMan); - virtual void evaluateEnrFuncInNode(std :: vector< double > &oEnrFunc, const Node &iNode) const; + void evaluateEnrFuncInNode(std :: vector< double > &oEnrFunc, const Node &iNode) const override; - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const; - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl, const FloatArray &iN, const IntArray &iElNodes) const; + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const override; + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl, const FloatArray &iN, const IntArray &iElNodes) const override; - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const; - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl, const FloatArray &iN, const FloatMatrix &idNdX, const IntArray &iElNodes) const; + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const override; + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl, const FloatArray &iN, const FloatMatrix &idNdX, const IntArray &iElNodes) const override; // TODO: Consider moving this function to a separate Cohesive Zone Interface /ES void evaluateEnrFuncJumps(std :: vector< double > &oEnrFuncJumps, int iNodeInd, GaussPoint &iGP, bool iGPLivesOnCurrentCrack) const; @@ -86,14 +87,14 @@ class OOFEM_EXPORT GeometryBasedEI : public EnrichmentItem virtual void computeIntersectionPoints(std :: vector< FloatArray > &oIntersectionPoints, std :: vector< int > &oIntersectedEdgeInd, Element *element, std :: vector< double > &oMinDistArcPos) const; virtual void computeIntersectionPoints(std :: vector< FloatArray > &oIntersectionPoints, std :: vector< int > &oIntersectedEdgeInd, Element *element, const Triangle &iTri, std :: vector< double > &oMinDistArcPos) const; - virtual void writeVtkDebug() const; + void writeVtkDebug() const override; void giveSubPolygon(std :: vector< FloatArray > &oPoints, const double &iXiStart, const double &iXiEnd) const; - virtual void propagateFronts(bool &oFrontsHavePropagated); - virtual bool giveElementTipCoord(FloatArray &oCoord, double &oArcPos, Element &iEl, const FloatArray &iElCenter) const; + void propagateFronts(bool &oFrontsHavePropagated) override; + bool giveElementTipCoord(FloatArray &oCoord, double &oArcPos, Element &iEl, const FloatArray &iElCenter) const override; - virtual void giveBoundingSphere(FloatArray &oCenter, double &oRadius); + void giveBoundingSphere(FloatArray &oCenter, double &oRadius) override; BasicGeometry *giveGeometry() { return mpBasicGeometry.get(); } void setGeometry(std :: unique_ptr< BasicGeometry > &&ipBasicGeometry) {mpBasicGeometry = std::move(ipBasicGeometry);} diff --git a/src/oofemlib/xfem/hybridei.C b/src/oofemlib/xfem/hybridei.C index f6ca4f6e4..1fa9a63cf 100644 --- a/src/oofemlib/xfem/hybridei.C +++ b/src/oofemlib/xfem/hybridei.C @@ -72,7 +72,7 @@ void HybridEI :: interpLevelSet(double &oLevelSet, const FloatArray &iN, const I oLevelSet = 0.0; for ( int i = 1; i <= iN.giveSize(); i++ ) { double levelSetNode = 0.0; - const FloatArray &nodePos = this->giveDomain()->giveNode(iNodeInd [ i - 1 ])->giveNodeCoordinates(); + const auto &nodePos = this->giveDomain()->giveNode(iNodeInd [ i - 1 ])->giveCoordinates(); if ( evalLevelSetNormalInNode(levelSetNode, iNodeInd [ i - 1 ], nodePos) ) { oLevelSet += iN.at(i) * levelSetNode; } @@ -84,7 +84,7 @@ void HybridEI :: interpLevelSetTangential(double &oLevelSet, const FloatArray &i oLevelSet = 0.0; for ( int i = 1; i <= iN.giveSize(); i++ ) { double levelSetNode = 0.0; - const FloatArray &nodePos = this->giveDomain()->giveNode(iNodeInd [ i - 1 ])->giveNodeCoordinates(); + const auto &nodePos = this->giveDomain()->giveNode(iNodeInd [ i - 1 ])->giveCoordinates(); if ( evalLevelSetTangInNode(levelSetNode, iNodeInd [ i - 1 ], nodePos) ) { oLevelSet += iN.at(i) * levelSetNode; } @@ -104,7 +104,7 @@ void HybridEI :: interpGradLevelSet(FloatArray &oGradLevelSet, const FloatMatrix for ( int i = 1; i <= idNdX.giveNumberOfRows(); i++ ) { for ( int j = 1; j <= dim; j++ ) { double levelSetNode = 0.0; - const FloatArray &nodePos = this->giveDomain()->giveNode(iNodeInd [ i - 1 ])->giveNodeCoordinates(); + const auto &nodePos = this->giveDomain()->giveNode(iNodeInd [ i - 1 ])->giveCoordinates(); if ( evalLevelSetNormalInNode(levelSetNode, iNodeInd [ i - 1 ], nodePos) ) { oGradLevelSet.at(j) += idNdX.at(i, j) * levelSetNode; } diff --git a/src/oofemlib/xfem/hybridei.h b/src/oofemlib/xfem/hybridei.h index c590d7b59..a15208f79 100644 --- a/src/oofemlib/xfem/hybridei.h +++ b/src/oofemlib/xfem/hybridei.h @@ -57,12 +57,12 @@ class OOFEM_EXPORT HybridEI : public GeometryBasedEI HybridEI(int n, XfemManager *xm, Domain *aDomain); virtual ~HybridEI(); - virtual const char *giveClassName() const { return "HybridEI"; } - virtual const char *giveInputRecordName() const { return _IFT_HybridEI_Name; } + const char *giveClassName() const override { return "HybridEI"; } + const char *giveInputRecordName() const override { return _IFT_HybridEI_Name; } - virtual void evalLevelSetNormal(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const; - virtual void evalLevelSetTangential(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const; - virtual void evalGradLevelSetNormal(FloatArray &oGradLevelSet, const FloatArray &iGlobalCoord, const FloatMatrix &idNdX, const IntArray &iNodeInd) const; + void evalLevelSetNormal(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const override; + void evalLevelSetTangential(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const override; + void evalGradLevelSetNormal(FloatArray &oGradLevelSet, const FloatArray &iGlobalCoord, const FloatMatrix &idNdX, const IntArray &iNodeInd) const override; // By templating the function this way, we may choose if we want to pass iNodeInd as // an IntArray, a std::vector or something else. diff --git a/src/oofemlib/xfem/inclusion.C b/src/oofemlib/xfem/inclusion.C index 974c11883..055e2dd8f 100644 --- a/src/oofemlib/xfem/inclusion.C +++ b/src/oofemlib/xfem/inclusion.C @@ -83,14 +83,12 @@ bool Inclusion :: isMaterialModified(GaussPoint &iGP, Element &iEl, CrossSection return false; } -IRResultType Inclusion :: initializeFrom(InputRecord *ir) +void Inclusion :: initializeFrom(InputRecord &ir) { - IRResultType result; + EnrichmentItem :: initializeFrom(ir); int crossSectionIndex = 0; IR_GIVE_FIELD(ir, crossSectionIndex, _IFT_Inclusion_CrossSection); mpCrossSection = this->giveDomain()->giveCrossSection(crossSectionIndex); - - return EnrichmentItem :: initializeFrom(ir); } } /* namespace oofem */ diff --git a/src/oofemlib/xfem/inclusion.h b/src/oofemlib/xfem/inclusion.h index 6af3630c1..60d49ae42 100644 --- a/src/oofemlib/xfem/inclusion.h +++ b/src/oofemlib/xfem/inclusion.h @@ -57,15 +57,14 @@ class OOFEM_EXPORT Inclusion : public HybridEI // Returns true if the enrichment item can assign // a different material to any Gauss point. - inline virtual bool canModifyMaterial() const { return true; } + bool canModifyMaterial() const override { return true; } // Returns true if the enrichment item assigns a different material to the Gauss point - virtual bool isMaterialModified(GaussPoint &iGP, Element &iEl, CrossSection * &opCS) const; + bool isMaterialModified(GaussPoint &iGP, Element &iEl, CrossSection * &opCS) const override; - - virtual const char *giveClassName() const { return "Inclusion"; } - virtual const char *giveInputRecordName() const { return _IFT_Inclusion_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "Inclusion"; } + const char *giveInputRecordName() const override { return _IFT_Inclusion_Name; } + void initializeFrom(InputRecord &ir) override; CrossSection *giveCrossSection() { return mpCrossSection; } }; } /* namespace oofem */ diff --git a/src/oofemlib/xfem/integrationrules/discsegintegrationrule.C b/src/oofemlib/xfem/integrationrules/discsegintegrationrule.C index 2ceb84dab..e5df4f2ec 100644 --- a/src/oofemlib/xfem/integrationrules/discsegintegrationrule.C +++ b/src/oofemlib/xfem/integrationrules/discsegintegrationrule.C @@ -90,7 +90,7 @@ int DiscontinuousSegmentIntegrationRule :: SetUpPointsOnLine(int iNumPointsPerSe // Local coordinate along the line segment - double xi = 2.0 * ( global.distance(xS) / totalLength - 0.5 ); + double xi = 2.0 * ( distance(global, xS) / totalLength - 0.5 ); gp->setNaturalCoordinates({ xi }); gp->setSubPatchCoordinates({ xi }); diff --git a/src/oofemlib/xfem/integrationrules/discsegintegrationrule.h b/src/oofemlib/xfem/integrationrules/discsegintegrationrule.h index a03eed910..c04d0ae4b 100644 --- a/src/oofemlib/xfem/integrationrules/discsegintegrationrule.h +++ b/src/oofemlib/xfem/integrationrules/discsegintegrationrule.h @@ -59,7 +59,7 @@ class OOFEM_EXPORT DiscontinuousSegmentIntegrationRule : public GaussIntegration DiscontinuousSegmentIntegrationRule(int n, Element *e, const std :: vector< Line > &iSegments); virtual ~DiscontinuousSegmentIntegrationRule(); - virtual int SetUpPointsOnLine(int iNumPointsPerSeg, MaterialMode mode); + int SetUpPointsOnLine(int iNumPointsPerSeg, MaterialMode mode) override; }; } /* namespace oofem */ diff --git a/src/oofemlib/xfem/listbasedei.h b/src/oofemlib/xfem/listbasedei.h index 5817c795a..4645cdf2a 100644 --- a/src/oofemlib/xfem/listbasedei.h +++ b/src/oofemlib/xfem/listbasedei.h @@ -57,17 +57,17 @@ class OOFEM_EXPORT ListBasedEI : public EnrichmentItem ListBasedEI(int n, XfemManager *xm, Domain *aDomain); virtual ~ListBasedEI(); - virtual const char *giveClassName() const { return "ListBasedEI"; } - virtual const char *giveInputRecordName() const { return _IFT_ListBasedEI_Name; } + const char *giveClassName() const override { return "ListBasedEI"; } + const char *giveInputRecordName() const override { return _IFT_ListBasedEI_Name; } - virtual void updateGeometry(); - virtual void propagateFronts(bool &oFrontsHavePropagated); + void updateGeometry() override; + void propagateFronts(bool &oFrontsHavePropagated) override; virtual void initiateFronts(bool &oFrontsHavePropagated, IntArray &initiateDofMans); - virtual void updateNodeEnrMarker(XfemManager &ixFemMan); + void updateNodeEnrMarker(XfemManager &ixFemMan) override; - virtual bool giveElementTipCoord(FloatArray &oCoord, double &oArcPos, Element &iEl, const FloatArray &iElCenter) const; + bool giveElementTipCoord(FloatArray &oCoord, double &oArcPos, Element &iEl, const FloatArray &iElCenter) const override; - virtual void giveBoundingSphere(FloatArray &oCenter, double &oRadius) { OOFEM_ERROR("Not implemented.") } + void giveBoundingSphere(FloatArray &oCenter, double &oRadius) override { OOFEM_ERROR("Not implemented.") } protected: std :: vector< int >dofManList; diff --git a/src/oofemlib/xfem/nucleationcriterion.C b/src/oofemlib/xfem/nucleationcriterion.C index be1216d3d..4252e5d35 100644 --- a/src/oofemlib/xfem/nucleationcriterion.C +++ b/src/oofemlib/xfem/nucleationcriterion.C @@ -45,57 +45,43 @@ namespace oofem { NucleationCriterion::NucleationCriterion(Domain *ipDomain): -mpDomain(ipDomain), -mpEnrichmentFunc(NULL) -{ + mpDomain(ipDomain) +{ } -} +NucleationCriterion::~NucleationCriterion() { } -NucleationCriterion::~NucleationCriterion() +std::vector> NucleationCriterion::nucleateEnrichmentItems() { - delete mpEnrichmentFunc; -} + OOFEM_ERROR("Not implemented.") -std::vector> NucleationCriterion::nucleateEnrichmentItems() { - OOFEM_ERROR("Not implemented.") - - std::vector> eiList; - return std::move( eiList ); + std::vector> eiList; + return eiList; } -IRResultType NucleationCriterion::initializeFrom(InputRecord *ir) { - - return IRRT_OK; +void NucleationCriterion::initializeFrom(InputRecord &ir) +{ } -int NucleationCriterion::instanciateYourself(DataReader *dr) { - -// printf("Entering NucleationCriterion::instanciateYourself(DataReader *dr)\n"); - - IRResultType result; // Required by IR_GIVE_FIELD macro +int NucleationCriterion::instanciateYourself(DataReader &dr) +{ std :: string name; // Instantiate enrichment function - InputRecord *mir = dr->giveInputRecord(DataReader :: IR_crackNucleationRec, 1); - result = mir->giveRecordKeywordField(name); - - if ( result != IRRT_OK ) { - mir->report_error(this->giveClassName(), __func__, "", result, __FILE__, __LINE__); - } + auto &mir = dr.giveInputRecord(DataReader :: IR_crackNucleationRec, 1); + mir.giveRecordKeywordField(name); mpEnrichmentFunc = classFactory.createEnrichmentFunction( name.c_str(), 1, mpDomain ); - if ( mpEnrichmentFunc != NULL ) { + if ( mpEnrichmentFunc ) { mpEnrichmentFunc->initializeFrom(mir); } else { OOFEM_ERROR( "failed to create enrichment function (%s)", name.c_str() ); } - - return IRRT_OK; + return 1; } void NucleationCriterion :: appendInputRecords(DynamicDataReader &oDR) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); ir->setRecordKeywordField( this->giveInputRecordName(), 1 ); @@ -107,36 +93,36 @@ void NucleationCriterion :: appendInputRecords(DynamicDataReader &oDR) // eiRec->setField(_IFT_EnrichmentItem_inheritbc); // } - oDR.insertInputRecord(DataReader :: IR_crackNucleationRec, ir); + oDR.insertInputRecord(DataReader :: IR_crackNucleationRec, std::move(ir)); // // Enrichment function -// DynamicInputRecord *efRec = new DynamicInputRecord(); +// auto efRec = std::make_unique(); // mpEnrichmentFunc->giveInputRecord(* efRec); -// oDR.insertInputRecord(DataReader :: IR_enrichFuncRec, efRec); +// oDR.insertInputRecord(DataReader :: IR_enrichFuncRec, std::move(efRec)); // // // Geometry -// DynamicInputRecord *geoRec = new DynamicInputRecord(); +// auto geoRec = std::make_unique(); // mpBasicGeometry->giveInputRecord(* geoRec); -// oDR.insertInputRecord(DataReader :: IR_geoRec, geoRec); +// oDR.insertInputRecord(DataReader :: IR_geoRec, std::move(geoRec)); // // // // Enrichment front // if ( mEnrFrontIndex != 0 ) { -// DynamicInputRecord *efrRecStart = new DynamicInputRecord(); +// auto efrRecStart = std::make_unique(); // mpEnrichmentFrontStart->giveInputRecord(* efrRecStart); -// oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, efrRecStart); +// oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, std::move(efrRecStart)); // -// DynamicInputRecord *efrRecEnd = new DynamicInputRecord(); +// auto efrRecEnd = std::make_unique(); // mpEnrichmentFrontEnd->giveInputRecord(* efrRecEnd); -// oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, efrRecEnd); +// oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, std::move(efrRecEnd)); // } // // // Propagation law // if ( mPropLawIndex != 0 ) { -// DynamicInputRecord *plRec = new DynamicInputRecord(); +// auto plRec = std::make_unique(); // this->mpPropagationLaw->giveInputRecord(* plRec); -// oDR.insertInputRecord(DataReader :: IR_propagationLawRec, plRec); +// oDR.insertInputRecord(DataReader :: IR_propagationLawRec, std::move(plRec)); // } } diff --git a/src/oofemlib/xfem/nucleationcriterion.h b/src/oofemlib/xfem/nucleationcriterion.h index 8bb24108a..b3752f0de 100644 --- a/src/oofemlib/xfem/nucleationcriterion.h +++ b/src/oofemlib/xfem/nucleationcriterion.h @@ -36,8 +36,6 @@ #define SRC_OOFEMLIB_XFEM_NUCLEATIONCRITERION_H_ -#include "irresulttype.h" - #include #include @@ -50,15 +48,17 @@ class DynamicDataReader; class InputRecord; class EnrichmentFunction; -class NucleationCriterion { +class NucleationCriterion +{ public: - NucleationCriterion(Domain *ipDomain); - virtual ~NucleationCriterion(); + NucleationCriterion(Domain *ipDomain); + virtual ~NucleationCriterion(); - virtual std::vector> nucleateEnrichmentItems(); + virtual std::vector> nucleateEnrichmentItems(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int instanciateYourself(DataReader *dr); + virtual void initializeFrom(InputRecord &ir); + virtual int instanciateYourself(DataReader &dr); + virtual void postInitialize() {} virtual void appendInputRecords(DynamicDataReader &oDR); @@ -68,9 +68,8 @@ class NucleationCriterion { virtual const char *giveInputRecordName() const = 0; protected: - Domain *mpDomain; - EnrichmentFunction *mpEnrichmentFunc; - + Domain *mpDomain; + std::unique_ptr mpEnrichmentFunc; }; } /* namespace oofem */ diff --git a/src/oofemlib/xfem/patchintegrationrule.C b/src/oofemlib/xfem/patchintegrationrule.C index 004862641..251e2b780 100644 --- a/src/oofemlib/xfem/patchintegrationrule.C +++ b/src/oofemlib/xfem/patchintegrationrule.C @@ -155,18 +155,18 @@ PatchIntegrationRule :: SetUpPointsOnTriangle(int nPoints, MaterialMode mode) } XfemManager *xMan = elem->giveDomain()->giveXfemManager(); - if ( xMan != NULL ) { + if ( xMan ) { if ( xMan->giveVtkDebug() ) { double time = 0.0; Element *el = this->elem; - if ( el != NULL ) { + if ( el ) { Domain *dom = el->giveDomain(); - if ( dom != NULL ) { + if ( dom ) { EngngModel *em = dom->giveEngngModel(); - if ( em != NULL ) { + if ( em ) { TimeStep *ts = em->giveCurrentStep(); - if ( ts != NULL ) { + if ( ts ) { time = ts->giveTargetTime(); } } @@ -272,18 +272,18 @@ PatchIntegrationRule :: SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, Mat } XfemManager *xMan = elem->giveDomain()->giveXfemManager(); - if ( xMan != NULL ) { + if ( xMan ) { if ( xMan->giveVtkDebug() ) { double time = 0.0; Element *el = this->elem; - if ( el != NULL ) { + if ( el ) { Domain *dom = el->giveDomain(); - if ( dom != NULL ) { + if ( dom ) { EngngModel *em = dom->giveEngngModel(); - if ( em != NULL ) { + if ( em ) { TimeStep *ts = em->giveCurrentStep(); - if ( ts != NULL ) { + if ( ts ) { time = ts->giveTargetTime(); } } @@ -304,61 +304,36 @@ PatchIntegrationRule :: SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, Mat } -contextIOResultType -PatchIntegrationRule :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +PatchIntegrationRule :: saveContext(DataStream &stream, ContextMode mode) { - // TODO: Implement - - // - // saves full context (saves state variables, that completely describe - // current state) - // - - // save parent data - contextIOResultType iores; - - if ( ( iores = IntegrationRule :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); + /// @todo Implement me + IntegrationRule :: saveContext(stream, mode); + +#if 0 + // save patch data + if ( this->patch ) { + // store patch type + int _type = this->patch->givePatchType(); + if ( !stream.write(_type) ) { + THROW_CIOERR(CIO_IOERR); + } + patch->saveContext(stream, mode); + } else { + OOFEM_ERROR("can't store NULL patch"); } - - /* - * // save patch data - * if ( this->patch ) { - * // store patch type - * int _type = this->patch->givePatchType(); - * if ( !stream.write(_type) ) { - * THROW_CIOERR(CIO_IOERR); - * } - * - * patch->saveContext(stream, mode, obj); - * } else { - * OOFEM_ERROR("can't store NULL patch"); - * } - */ - return CIO_OK; +#endif } -contextIOResultType -PatchIntegrationRule :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +PatchIntegrationRule :: restoreContext(DataStream &stream, ContextMode mode) { - // TODO: Implement - - // - // restores full element context (saves state variables, that completely describe - // current state) - // - - contextIOResultType iores; - - if ( ( iores = IntegrationRule :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + /// @todo Implement me + IntegrationRule :: restoreContext(stream, mode); int _ptype; if ( !stream.read(_ptype) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/oofemlib/xfem/patchintegrationrule.h b/src/oofemlib/xfem/patchintegrationrule.h index 0fbbd638c..4f633beb3 100644 --- a/src/oofemlib/xfem/patchintegrationrule.h +++ b/src/oofemlib/xfem/patchintegrationrule.h @@ -69,15 +69,15 @@ class OOFEM_EXPORT PatchIntegrationRule : public GaussIntegrationRule /// Destructor. virtual ~PatchIntegrationRule(); - virtual const char *giveClassName() const { return "PatchIntegrationRule"; } + const char *giveClassName() const override { return "PatchIntegrationRule"; } // TODO: Give this function a better name. // Note: the fact that this function is inherited complicates name change. - virtual int SetUpPointsOnTriangle(int nPoints, MaterialMode mode); - virtual int SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, MaterialMode mode); + int SetUpPointsOnTriangle(int nPoints, MaterialMode mode) override; + int SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, MaterialMode mode) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; } // end namespace oofem #endif // patchintegrationrule_h diff --git a/src/oofemlib/xfem/propagationlaw.C b/src/oofemlib/xfem/propagationlaw.C index f14049e26..df850770c 100644 --- a/src/oofemlib/xfem/propagationlaw.C +++ b/src/oofemlib/xfem/propagationlaw.C @@ -63,16 +63,12 @@ void PLDoNothing :: giveInputRecord(DynamicInputRecord &input) input.setRecordKeywordField(this->giveInputRecordName(), number); } -IRResultType PLCrackPrescribedDir :: initializeFrom(InputRecord *ir) +void PLCrackPrescribedDir :: initializeFrom(InputRecord &ir) { - IRResultType result; - IR_GIVE_FIELD(ir, mAngle, _IFT_PLCrackPrescribedDir_Dir); IR_GIVE_FIELD(ir, mIncrementLength, _IFT_PLCrackPrescribedDir_IncLength); // printf("In PLCrackPrescribedDir :: initializeFrom: mAngle: %e mIncrementLength: %e\n", mAngle, mIncrementLength); - - return IRRT_OK; } void PLCrackPrescribedDir :: giveInputRecord(DynamicInputRecord &input) @@ -116,15 +112,11 @@ bool PLCrackPrescribedDir :: propagateInterface(Domain &iDomain, EnrichmentFront return true; } -IRResultType PLnodeRadius :: initializeFrom(InputRecord *ir) +void PLnodeRadius :: initializeFrom(InputRecord &ir) { - IRResultType result; - IR_GIVE_FIELD(ir, mRadius, _IFT_PLnodeRadius_Radius); //printf("In PLnodeRadius :: initializeFrom: mRadius: %e \n", mRadius); - - return IRRT_OK; } void PLnodeRadius :: giveInputRecord(DynamicInputRecord &input) @@ -160,7 +152,7 @@ bool PLnodeRadius :: propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFr //DofManager *dofMan = iDomain.giveDofManager(tipInfo.mTipDofManNumbers.at(i)); //const FloatArray gCoords = dofMan->giveCoordinates(); Node *iNode = iDomain.giveNode(tipInfo.mTipDofManNumbers.at(i)); - const FloatArray gCoords = iNode->giveNodeCoordinates(); + const auto &gCoords = iNode->giveCoordinates(); std :: list< int > nodeList; localizer->giveAllNodesWithinBox(nodeList,gCoords,mRadius); diff --git a/src/oofemlib/xfem/propagationlaw.h b/src/oofemlib/xfem/propagationlaw.h index ef6c689c7..0857f999d 100644 --- a/src/oofemlib/xfem/propagationlaw.h +++ b/src/oofemlib/xfem/propagationlaw.h @@ -70,7 +70,7 @@ class OOFEM_EXPORT PropagationLaw virtual const char *giveClassName() const = 0; virtual const char *giveInputRecordName() const = 0; - virtual IRResultType initializeFrom(InputRecord *ir) = 0; + virtual void initializeFrom(InputRecord &ir) = 0; virtual void giveInputRecord(DynamicInputRecord &input) = 0; virtual bool hasPropagation() const = 0; @@ -87,14 +87,14 @@ class OOFEM_EXPORT PLDoNothing : public PropagationLaw PLDoNothing() { } virtual ~PLDoNothing() { } - virtual const char *giveClassName() const { return "PLDoNothing"; } - virtual const char *giveInputRecordName() const { return _IFT_PLDoNothing_Name; } + const char *giveClassName() const override { return "PLDoNothing"; } + const char *giveInputRecordName() const override { return _IFT_PLDoNothing_Name; } - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override { } + void giveInputRecord(DynamicInputRecord &input) override; - virtual bool hasPropagation() const { return false; } - virtual bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) { return false; } + bool hasPropagation() const override { return false; } + bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) override { return false; } }; /** @@ -107,14 +107,14 @@ class OOFEM_EXPORT PLCrackPrescribedDir : public PropagationLaw PLCrackPrescribedDir() : mAngle(0.0), mIncrementLength(0.0) { } virtual ~PLCrackPrescribedDir() { } - virtual const char *giveClassName() const { return "PLCrackPrescribedDir"; } - virtual const char *giveInputRecordName() const { return _IFT_PLCrackPrescribedDir_Name; } + const char *giveClassName() const override { return "PLCrackPrescribedDir"; } + const char *giveInputRecordName() const override { return _IFT_PLCrackPrescribedDir_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual bool hasPropagation() const { return mIncrementLength > 0.; } - virtual bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp); + bool hasPropagation() const override { return mIncrementLength > 0.; } + bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) override; protected: double mAngle, mIncrementLength; @@ -130,14 +130,14 @@ class OOFEM_EXPORT PLnodeRadius : public PropagationLaw PLnodeRadius() : mRadius(0.0) { } virtual ~PLnodeRadius() { } - virtual const char *giveClassName() const { return "PLnodeRadius"; } - virtual const char *giveInputRecordName() const { return _IFT_PLnodeRadius_Name; } + const char *giveClassName() const override { return "PLnodeRadius"; } + const char *giveInputRecordName() const override { return _IFT_PLnodeRadius_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual bool hasPropagation() const { return mRadius > 0.; } - virtual bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp); + bool hasPropagation() const override { return mRadius > 0.; } + bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) override; protected: double mRadius; diff --git a/src/oofemlib/xfem/xfemelementinterface.C b/src/oofemlib/xfem/xfemelementinterface.C index d7a6b1641..2fc9c98d0 100644 --- a/src/oofemlib/xfem/xfemelementinterface.C +++ b/src/oofemlib/xfem/xfemelementinterface.C @@ -114,7 +114,7 @@ void XfemElementInterface :: ComputeBOrBHMatrix(FloatMatrix &oAnswer, GaussPoint for ( int i = 1; i <= nDofMan; i++ ) { const Node *node = iEl.giveNode(i); - const FloatArray &nodeCoord = node->giveNodeCoordinates(); + const auto &nodeCoord = node->giveCoordinates(); globalCoord.at(1) += N.at(i) * nodeCoord [ 0 ]; globalCoord.at(2) += N.at(i) * nodeCoord [ 1 ]; } @@ -139,7 +139,7 @@ void XfemElementInterface :: ComputeBOrBHMatrix(FloatMatrix &oAnswer, GaussPoint // XFEM part of B-matrix double enrDofsScaleFactor = 1.0; - XfemManager *xMan = NULL; + XfemManager *xMan = nullptr; if ( iEl.giveDomain()->hasXfemManager() ) { xMan = iEl.giveDomain()->giveXfemManager(); enrDofsScaleFactor = xMan->giveEnrDofScaleFactor(); @@ -184,7 +184,7 @@ void XfemElementInterface :: ComputeBOrBHMatrix(FloatMatrix &oAnswer, GaussPoint ei->evaluateEnrFuncAt(efGP, globalCoord, iNaturalGpCoord, globalNodeInd, * element, N, elNodes); - const FloatArray &nodePos = node->giveNodeCoordinates(); + const auto &nodePos = node->giveCoordinates(); // double levelSetNode = 0.0; // ei->evalLevelSetNormalInNode(levelSetNode, globalNodeInd, nodePos); @@ -309,7 +309,7 @@ void XfemElementInterface :: XfemElementInterface_createEnrNmatrixAt(FloatMatrix ei->evaluateEnrFuncAt(efGP, globalCoord, iLocCoord, globalNodeInd, iEl, Nc, elNodes); - const FloatArray &nodePos = * ( dMan->giveCoordinates() ); + const auto &nodePos = dMan->giveCoordinates(); std :: vector< double >efNode; @@ -477,21 +477,21 @@ bool XfemElementInterface :: XfemElementInterface_updateIntegrationRule() void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: vector< std :: vector< FloatArray > > &oPointPartitions, double &oCrackStartXi, double &oCrackEndXi, int iEnrItemIndex, bool &oIntersection) { - int dim = element->giveDofManager(1)->giveCoordinates()->giveSize(); + int dim = element->giveDofManager(1)->giveCoordinates().giveSize(); - FloatArray elCenter( element->giveDofManager(1)->giveCoordinates()->giveSize() ); + FloatArray elCenter( element->giveDofManager(1)->giveCoordinates().giveSize() ); elCenter.zero(); std :: vector< const FloatArray * >nodeCoord; for ( int i = 1; i <= this->element->giveNumberOfDofManagers(); i++ ) { - nodeCoord.push_back( element->giveDofManager(i)->giveCoordinates() ); - elCenter.add( * ( element->giveDofManager(i)->giveCoordinates() ) ); + nodeCoord.push_back( &element->giveDofManager(i)->giveCoordinates() ); + elCenter.add( element->giveDofManager(i)->giveCoordinates() ); } elCenter.times( 1.0 / double( element->giveNumberOfDofManagers() ) ); XfemManager *xMan = this->element->giveDomain()->giveXfemManager(); GeometryBasedEI *ei = dynamic_cast< GeometryBasedEI * >( xMan->giveEnrichmentItem(iEnrItemIndex) ); - if ( ei == NULL ) { + if ( ei == nullptr ) { oIntersection = false; return; } @@ -537,22 +537,20 @@ void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: } int nEdges = this->element->giveInterpolation()->giveNumberOfEdges(); if ( foundTip ) { - oPointPartitions.clear(); + oPointPartitions.clear(); // Divide into subdomains int triPassed = 0; for ( int i = 1; i <= nEdges; i++ ) { - IntArray bNodes; - this->element->giveInterpolation()->boundaryGiveNodes(bNodes, i); + const auto &bNodes = this->element->giveInterpolation()->boundaryGiveNodes(i); - - if( bNodes.giveSize() == 2 ) { + if ( bNodes.giveSize() == 2 ) { int nsLoc = bNodes.at(1); int neLoc = bNodes.at( bNodes.giveSize() ); - const FloatArray &coordS = * ( element->giveDofManager(nsLoc)->giveCoordinates() ); - const FloatArray &coordE = * ( element->giveDofManager(neLoc)->giveCoordinates() ); + const auto &coordS = element->giveDofManager(nsLoc)->giveCoordinates(); + const auto &coordE = element->giveDofManager(neLoc)->giveCoordinates(); if ( i == intersecEdgeInd [ 0 ] ) { oPointPartitions.push_back( std :: vector< FloatArray >() ); @@ -566,32 +564,31 @@ void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: oPointPartitions [ triPassed ].push_back(coordS); oPointPartitions [ triPassed ].push_back(intersecPoints [ 0 ]); triPassed++; - } else { + } else { oPointPartitions.push_back( std :: vector< FloatArray >() ); oPointPartitions [ triPassed ].push_back(tipCoord); oPointPartitions [ triPassed ].push_back(coordS); oPointPartitions [ triPassed ].push_back(coordE); triPassed++; } - } - else if( bNodes.giveSize() == 3 ) { + } else if( bNodes.giveSize() == 3 ) { // Start - const FloatArray &coordS = * ( element->giveDofManager(bNodes(0))->giveCoordinates() ); + const auto &coordS = element->giveDofManager(bNodes[0])->giveCoordinates(); // Center - const FloatArray &coordC = * ( element->giveDofManager(bNodes(2))->giveCoordinates() ); + const auto &coordC = element->giveDofManager(bNodes[2])->giveCoordinates(); // End - const FloatArray &coordE = * ( element->giveDofManager(bNodes(1))->giveCoordinates() ); + const auto &coordE = element->giveDofManager(bNodes[1])->giveCoordinates(); if ( i == intersecEdgeInd [ 0 ] ) { // Check if the intersection point is closer to the start or end, compared to the center point. - double dist_S_2 = intersecPoints[0].distance_square(coordS); -// double dist_E_2 = intersecPoints[0].distance_square(coordE); - double dist_C_2 = coordC.distance_square(coordS); + double dist_S_2 = distance_square(intersecPoints[0], coordS); +// double dist_E_2 = distance_square(intersecPoints[0], coordE); + double dist_C_2 = distance_square(coordC, coordS); if( dist_S_2 < dist_C_2 ) { oPointPartitions.push_back( std :: vector< FloatArray >() ); @@ -612,8 +609,7 @@ void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: oPointPartitions [ triPassed ].push_back(coordC); triPassed++; - } - else { + } else { oPointPartitions.push_back( std :: vector< FloatArray >() ); oPointPartitions [ triPassed ].push_back(coordC); @@ -637,7 +633,7 @@ void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: } - } else { + } else { oPointPartitions.push_back( std :: vector< FloatArray >() ); oPointPartitions [ triPassed ].push_back(tipCoord); oPointPartitions [ triPassed ].push_back(coordS); @@ -669,7 +665,7 @@ void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: oPointPartitions.resize(1); for ( int i = 1; i <= this->element->giveNumberOfDofManagers(); i++ ) { - const FloatArray &nodeCoord = * element->giveDofManager(i)->giveCoordinates(); + const auto &nodeCoord = element->giveDofManager(i)->giveCoordinates(); oPointPartitions [ 0 ].push_back(nodeCoord); } @@ -702,7 +698,7 @@ void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: vector< std :: vector< FloatArray > > &oPointPartitions, double &oCrackStartXi, double &oCrackEndXi, const Triangle &iTri, int iEnrItemIndex, bool &oIntersection) { - int dim = element->giveDofManager(1)->giveCoordinates()->giveSize(); + int dim = element->giveDofManager(1)->giveCoordinates().giveSize(); FloatArray elCenter( iTri.giveVertex(1).giveSize() ); elCenter.zero(); @@ -717,7 +713,7 @@ void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: XfemManager *xMan = this->element->giveDomain()->giveXfemManager(); GeometryBasedEI *ei = dynamic_cast< GeometryBasedEI * >( xMan->giveEnrichmentItem(iEnrItemIndex) ); - if ( ei == NULL ) { + if ( ei == nullptr ) { oIntersection = false; return; } @@ -752,7 +748,7 @@ void XfemElementInterface :: XfemElementInterface_prepareNodesForDelaunay(std :: std :: vector< FloatArray >edgeCoords, nodeCoords; FloatArray tipCoord; - int dim = element->giveDofManager(1)->giveCoordinates()->giveSize(); + int dim = element->giveDofManager(1)->giveCoordinates().giveSize(); tipCoord.resize(dim); bool foundTip = false; @@ -857,16 +853,15 @@ void XfemElementInterface :: partitionEdgeSegment(int iBndIndex, std :: vector< XfemManager *xMan = this->element->giveDomain()->giveXfemManager(); FEInterpolation *interp = element->giveInterpolation(); // Geometry interpolation - IntArray edgeNodes; FEInterpolation2d *interp2d = dynamic_cast< FEInterpolation2d * >( interp ); - if ( interp2d == NULL ) { + if ( interp2d == nullptr ) { OOFEM_ERROR("In XfemElementInterface :: partitionEdgeSegment: failed to cast to FEInterpolation2d.\n") } - interp2d->computeLocalEdgeMapping(edgeNodes, iBndIndex); + const auto &edgeNodes = interp2d->computeLocalEdgeMapping(iBndIndex); // Fetch start and end points. - const FloatArray &xS = * ( element->giveDofManager( edgeNodes.at(1) )->giveCoordinates() ); - const FloatArray &xE = * ( element->giveDofManager( edgeNodes.at(2) )->giveCoordinates() ); + const auto &xS = element->giveDofManager( edgeNodes.at(1) )->giveCoordinates(); + const auto &xE = element->giveDofManager( edgeNodes.at(2) )->giveCoordinates(); // The point of departure is the original edge segment. // This segment will be subdivided as many times as necessary. @@ -887,8 +882,8 @@ void XfemElementInterface :: partitionEdgeSegment(int iBndIndex, std :: vector< for ( size_t segInd = 0; segInd < numSeg; segInd++ ) { // Check if the segment is cut by the current enrichment item - const FloatArray &seg_xS = oSegments [ segInd ].giveVertex(1); - const FloatArray &seg_xE = oSegments [ segInd ].giveVertex(2); + const auto &seg_xS = oSegments [ segInd ].giveVertex(1); + const auto &seg_xE = oSegments [ segInd ].giveVertex(2); // Local coordinates of vertices @@ -915,7 +910,7 @@ void XfemElementInterface :: partitionEdgeSegment(int iBndIndex, std :: vector< for ( int i = 1; i <= Ns.giveSize(); i++ ) { - const FloatArray &nodePos = * ( element->giveNode(i)->giveCoordinates() ); + const auto &nodePos = element->giveNode(i)->giveCoordinates(); double phiNode = 0.0; if ( !ei->evalLevelSetNormalInNode(phiNode, elNodes [ i - 1 ], nodePos) ) { evaluationSucceeded = false; @@ -985,14 +980,14 @@ void XfemElementInterface :: updateYourselfCZ(TimeStep *tStep) size_t numSeg = mpCZIntegrationRules.size(); for ( size_t i = 0; i < numSeg; i++ ) { - if ( mpCZIntegrationRules [ i ] != NULL ) { + if ( mpCZIntegrationRules [ i ] != nullptr ) { mpCZIntegrationRules [ i ]->updateYourself(tStep); } } numSeg = mpCZExtraIntegrationRules.size(); for ( size_t i = 0; i < numSeg; i++ ) { - if ( mpCZExtraIntegrationRules [ i ] != NULL ) { + if ( mpCZExtraIntegrationRules [ i ] != nullptr ) { mpCZExtraIntegrationRules [ i ]->updateYourself(tStep); } } @@ -1046,7 +1041,7 @@ void XfemElementInterface :: computeNCohesive(FloatMatrix &oN, GaussPoint &iGP, GeometryBasedEI *geoEI = dynamic_cast< GeometryBasedEI * >( ei ); - if ( geoEI != NULL ) { + if ( geoEI != nullptr ) { if ( geoEI->isDofManEnriched(* dMan) ) { int numEnr = geoEI->giveNumDofManEnrichments(* dMan); diff --git a/src/oofemlib/xfem/xfemelementinterface.h b/src/oofemlib/xfem/xfemelementinterface.h index c67896965..27f56f136 100644 --- a/src/oofemlib/xfem/xfemelementinterface.h +++ b/src/oofemlib/xfem/xfemelementinterface.h @@ -79,7 +79,7 @@ class OOFEM_EXPORT XfemElementInterface : public Interface /// Flag that tells if plane stress or plane strain is assumed bool mUsePlaneStrain; - virtual const char *giveClassName() const { return "XfemElementInterface"; } + const char *giveClassName() const override { return "XfemElementInterface"; } std :: string errorInfo(const char *func) const { return std :: string( giveClassName() ) + func; } public: diff --git a/src/oofemlib/xfem/xfemmanager.C b/src/oofemlib/xfem/xfemmanager.C index 4a2fa207b..02df53aaf 100644 --- a/src/oofemlib/xfem/xfemmanager.C +++ b/src/oofemlib/xfem/xfemmanager.C @@ -52,8 +52,8 @@ #include "XFEMDebugTools.h" #include "xfemtolerances.h" #include "nucleationcriterion.h" -#include "Elements/Shells/shell7basexfem.h" -#include "EngineeringModels/structengngmodel.h" +#include "sm/Elements/Shells/shell7basexfem.h" +#include "sm/EngineeringModels/structengngmodel.h" namespace oofem { REGISTER_XfemManager(XfemManager) @@ -151,10 +151,8 @@ IntArray XfemManager :: giveEnrichedDofIDs(const DofManager &iDMan) const return dofIdArray; } -IRResultType XfemManager :: initializeFrom(InputRecord *ir) +void XfemManager :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, numberOfEnrichmentItems, _IFT_XfemManager_numberOfEnrichmentItems); IR_GIVE_OPTIONAL_FIELD(ir, numberOfNucleationCriteria, _IFT_XfemManager_numberOfNucleationCriteria); @@ -180,8 +178,6 @@ IRResultType XfemManager :: initializeFrom(InputRecord *ir) // TODO: Read as input. XfemTolerances :: setCharacteristicElementLength(0.001); - - return IRRT_OK; } @@ -207,19 +203,14 @@ void XfemManager :: giveInputRecord(DynamicInputRecord &input) } } -int XfemManager :: instanciateYourself(DataReader *dr) +int XfemManager :: instanciateYourself(DataReader &dr) { - IRResultType result; // Required by IR_GIVE_FIELD macro std :: string name; enrichmentItemList.resize(numberOfEnrichmentItems); for ( int i = 1; i <= numberOfEnrichmentItems; i++ ) { - InputRecord *mir = dr->giveInputRecord(DataReader :: IR_enrichItemRec, i); - result = mir->giveRecordKeywordField(name); - - if ( result != IRRT_OK ) { - mir->report_error(this->giveClassName(), __func__, "", result, __FILE__, __LINE__); - } + auto &mir = dr.giveInputRecord(DataReader :: IR_enrichItemRec, i); + mir.giveRecordKeywordField(name); std :: unique_ptr< EnrichmentItem >ei( classFactory.createEnrichmentItem( name.c_str(), i, this, this->giveDomain() ) ); if ( ei.get() == NULL ) { @@ -233,12 +224,8 @@ int XfemManager :: instanciateYourself(DataReader *dr) mNucleationCriteria.resize(numberOfNucleationCriteria); for ( int i = 1; i <= numberOfNucleationCriteria; i++ ) { - InputRecord *mir = dr->giveInputRecord(DataReader :: IR_crackNucleationRec, i); - result = mir->giveRecordKeywordField(name); - - if ( result != IRRT_OK ) { - mir->report_error(this->giveClassName(), __func__, "", result, __FILE__, __LINE__); - } + auto &mir = dr.giveInputRecord(DataReader :: IR_crackNucleationRec, i); + mir.giveRecordKeywordField(name); std :: unique_ptr< NucleationCriterion >nc( classFactory.createNucleationCriterion( name.c_str(), this->giveDomain() ) ); if ( nc.get() == NULL ) { @@ -251,11 +238,26 @@ int XfemManager :: instanciateYourself(DataReader *dr) } + + return 1; +} + +void XfemManager :: postInitialize() +{ + for ( int i = 1; i <= numberOfEnrichmentItems; i++ ) { + this->giveEnrichmentItem(i)->postInitialize(); + } + + for ( int i = 1; i <= numberOfNucleationCriteria; i++ ) { + giveNucleationCriterion(i)->postInitialize(); + } + updateNodeEnrichmentItemMap(); - return 1; } + + void XfemManager :: setDomain(Domain *ipDomain) { domain = ipDomain; @@ -265,10 +267,8 @@ void XfemManager :: setDomain(Domain *ipDomain) } } -contextIOResultType XfemManager :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void XfemManager :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( mode & CM_Definition ) { if ( !stream.write(this->numberOfEnrichmentItems) ) { THROW_CIOERR(CIO_IOERR); @@ -283,19 +283,13 @@ contextIOResultType XfemManager :: saveContext(DataStream &stream, ContextMode m } } - if ( ( iores = object->saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + object->saveContext(stream, mode); } - - return CIO_OK; } -contextIOResultType XfemManager :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void XfemManager :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( mode & CM_Definition ) { if ( !stream.read(this->numberOfEnrichmentItems) ) { THROW_CIOERR(CIO_IOERR); @@ -318,12 +312,8 @@ contextIOResultType XfemManager :: restoreContext(DataStream &stream, ContextMod obj = this->giveEnrichmentItem(i); } - if ( ( iores = obj->restoreContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(CIO_IOERR); - } + obj->restoreContext(stream, mode); } - - return CIO_OK; } void XfemManager :: updateYourself(TimeStep *tStep) @@ -375,7 +365,8 @@ void XfemManager :: propagateFronts(bool &oAnyFronHasPropagated) void XfemManager :: initiateFronts(bool &oAnyFronHasPropagated, TimeStep *tStep) { - oAnyFronHasPropagated = false; +#ifdef __SM_MODULE + oAnyFronHasPropagated = false; // Loop over EI:s and collect cross sections which have delaminaion EI:s IntArray CSnumbers; @@ -400,7 +391,7 @@ void XfemManager :: initiateFronts(bool &oAnyFronHasPropagated, TimeStep *tStep) for ( auto &ei: enrichmentItemList ) { bool eiHasPropagated = false; - + if ( Delamination *dei = dynamic_cast< Delamination * >( ei.get() ) ) { if ( !failureChecked ) { @@ -427,13 +418,17 @@ void XfemManager :: initiateFronts(bool &oAnyFronHasPropagated, TimeStep *tStep) } else { OOFEM_ERROR(" XfemManager :: initiateFronts not implemented for other than Delamination.") } - if(eiHasPropagated) { oAnyFronHasPropagated = true; } } - updateNodeEnrichmentItemMap(); + +#else + OOFEM_ERROR(" XfemManager :: initiateFronts not implemented for other than Delamination.") +#endif + + } bool XfemManager :: hasPropagatingFronts() diff --git a/src/oofemlib/xfem/xfemmanager.h b/src/oofemlib/xfem/xfemmanager.h index 43c40077b..bf8041b9d 100644 --- a/src/oofemlib/xfem/xfemmanager.h +++ b/src/oofemlib/xfem/xfemmanager.h @@ -158,7 +158,7 @@ class OOFEM_EXPORT XfemManager // IDs of all potential enriched dofs IntArray mXFEMPotentialDofIDs; - + public: /** @@ -192,13 +192,15 @@ class OOFEM_EXPORT XfemManager IntArray giveEnrichedDofIDs(const DofManager &iDMan) const; /// Initializes receiver according to object description stored in input record. - virtual IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); virtual void giveInputRecord(DynamicInputRecord &input); - virtual int instanciateYourself(DataReader *dr); + virtual int instanciateYourself(DataReader &dr); virtual const char *giveClassName() const { return "XfemManager"; } virtual const char *giveInputRecordName() const { return _IFT_XfemManager_Name; } + virtual void postInitialize(); + Domain *giveDomain() { return this->domain; } void setDomain(Domain *ipDomain); @@ -206,20 +208,16 @@ class OOFEM_EXPORT XfemManager * Stores the state of receiver to output stream. * @param stream Context stream. * @param mode Determines amount of info in stream. - * @param obj Special parameter, used to pass optional parameters. - * @return contextIOResultType. * @exception ContextIOERR If error encountered. */ - contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode); /** * Restores the state of receiver from output stream. * @param stream Context file. * @param mode Determines amount of info in stream. - * @param obj Special parameter for sending extra information. - * @return contextIOResultType. * @exception ContextIOERR exception if error encountered. */ - contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void restoreContext(DataStream &stream, ContextMode mode); /** diff --git a/src/oofemlib/zznodalrecoverymodel.C b/src/oofemlib/zznodalrecoverymodel.C index 8c7407a7a..0d49222b5 100644 --- a/src/oofemlib/zznodalrecoverymodel.C +++ b/src/oofemlib/zznodalrecoverymodel.C @@ -43,6 +43,7 @@ #include "feinterpol.h" #include "error.h" #include "engngm.h" +#include "classfactory.h" #include #include @@ -55,6 +56,8 @@ #define ZZNRM_ZERO_VALUE 1.e-12 namespace oofem { +REGISTER_NodalRecoveryModel(ZZNodalRecoveryModel, NodalRecoveryModel :: NRM_ZienkiewiczZhu); + ZZNodalRecoveryModel :: ZZNodalRecoveryModel(Domain *d) : NodalRecoveryModel(d) { } @@ -311,16 +314,15 @@ ZZNodalRecoveryModel :: exchangeDofManValues(FloatArray &lhs, FloatMatrix &rhs, int ZZNodalRecoveryModel :: packSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm) { - int result = 1, indx, nc, size; + int result = 1; ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); - IntArray const *toSendMap = processComm.giveToSendMap(); - nc = s->rhs->giveNumberOfColumns(); + const IntArray &toSendMap = processComm.giveToSendMap(); + int nc = s->rhs->giveNumberOfColumns(); - size = toSendMap->giveSize(); - for ( int i = 1; i <= size; i++ ) { + for ( int inode : toSendMap ) { // toSendMap contains all shared dofmans with remote partition // one has to check, if particular shared node value is available for given region - indx = s->regionNodalNumbers->at( toSendMap->at(i) ); + int indx = s->regionNodalNumbers->at( inode ); if ( indx ) { // pack "1" to indicate that for given shared node this is a valid contribution result &= pcbuff->write(1); @@ -330,7 +332,7 @@ ZZNodalRecoveryModel :: packSharedDofManData(parallelStruct *s, ProcessCommunica } //printf("[%d] ZZ: Sending data for shred node %d[%d]\n", domain->giveEngngModel()->giveRank(), - // toSendMap->at(i), domain->giveDofManager(toSendMap->at(i))->giveGlobalNumber()); + // inode, domain->giveDofManager(inode)->giveGlobalNumber()); } else { // ok shared node is not in active region (determined by s->regionNodalNumbers) result &= pcbuff->write(0); @@ -344,15 +346,14 @@ int ZZNodalRecoveryModel :: unpackSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm) { int result = 1; - int nc, indx, size, flag; - IntArray const *toRecvMap = processComm.giveToRecvMap(); + int flag; + const IntArray &toRecvMap = processComm.giveToRecvMap(); ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); double value; - nc = s->rhs->giveNumberOfColumns(); + int nc = s->rhs->giveNumberOfColumns(); - size = toRecvMap->giveSize(); - for ( int i = 1; i <= size; i++ ) { - indx = s->regionNodalNumbers->at( toRecvMap->at(i) ); + for ( int inode : toRecvMap ) { + int indx = s->regionNodalNumbers->at( inode ); // toRecvMap contains all shared dofmans with remote partition // one has to check, if particular shared node received contribution is available for given region result &= pcbuff->read(flag); @@ -372,7 +373,7 @@ ZZNodalRecoveryModel :: unpackSharedDofManData(parallelStruct *s, ProcessCommuni } //if (indx) printf("[%d] ZZ: Receiving data for shred node %d[%d]\n", domain->giveEngngModel()->giveRank(), - // toRecvMap->at(i), domain->giveDofManager(toRecvMap->at(i))->giveGlobalNumber()); + // inode, domain->giveDofManager(inode)->giveGlobalNumber()); } } diff --git a/src/oofemlib/zznodalrecoverymodel.h b/src/oofemlib/zznodalrecoverymodel.h index efa3249e5..9ae4cabdf 100644 --- a/src/oofemlib/zznodalrecoverymodel.h +++ b/src/oofemlib/zznodalrecoverymodel.h @@ -38,6 +38,8 @@ #include "nodalrecoverymodel.h" #include "interface.h" +#define _IFT_ZZNodalRecoveryModel_Name "zz" + namespace oofem { class GaussPoint; class ZZNodalRecoveryModelInterface; @@ -70,9 +72,9 @@ class OOFEM_EXPORT ZZNodalRecoveryModel : public NodalRecoveryModel /// Destructor. virtual ~ZZNodalRecoveryModel(); - virtual int recoverValues(Set elementSet, InternalStateType type, TimeStep *tStep); + int recoverValues(Set elementSet, InternalStateType type, TimeStep *tStep) override; - virtual const char *giveClassName() const { return "ZZNodalRecoveryModel"; } + const char *giveClassName() const override { return "ZZNodalRecoveryModel"; } private: /** diff --git a/src/sm/CMakeLists.txt b/src/sm/CMakeLists.txt index 13ed29693..bfa78524b 100644 --- a/src/sm/CMakeLists.txt +++ b/src/sm/CMakeLists.txt @@ -9,21 +9,24 @@ set (sm_element Elements/3D/lspace.C Elements/3D/lspacebb.C Elements/3D/qspace.C - Elements/3D/qspacegrad.C Elements/3D/q27space.C Elements/3D/ltrspace.C + Elements/3D/ltrspaceboundary.C + Elements/3D/ltrspaceboundarytruss.C + Elements/3D/ltrspaceboundarymembrane.C + Elements/3D/ltrspaceboundarybeam.C + Elements/3D/ltrspaceboundaryplate.C + Elements/3D/ltrspaceboundaryvoigt.C Elements/3D/qtrspace.C - Elements/3D/qtrspacegrad.C Elements/3D/lwedge.C Elements/3D/qwedge.C Elements/3D/macrolspace.C - Elements/3D/qspacegrad.C - Elements/3D/qwedgegrad.C Elements/Bars/truss1d.C Elements/Bars/truss2d.C Elements/Bars/truss3d.C + Elements/Bars/truss3dnl.C + Elements/Bars/truss3dnl2.C Elements/Bars/qtruss1d.C - Elements/Bars/qtruss1dgrad.C Elements/Beams/libeam2d.C Elements/Beams/libeam2dnl.C Elements/Beams/libeam3d.C @@ -33,6 +36,12 @@ set (sm_element Elements/Beams/beambaseelement.C Elements/Beams/beam2d.C Elements/Beams/beam3d.C + Elements/Beams/libeam3dboundary.C + Elements/Beams/libeam3dboundarytruss.C + Elements/Beams/libeam3dboundarymembrane.C + Elements/Beams/libeam3dboundarybeam.C + Elements/Beams/libeam3dboundaryplate.C + Elements/Beams/libeam3dboundaryvoigt.C Elements/Plates/cct.C Elements/Plates/dkt.C Elements/Plates/qdkt.C @@ -40,7 +49,8 @@ set (sm_element Elements/Plates/dkt3d.C Elements/Shells/rershell.C Elements/Shells/tr_shell01.C - Elements/Shells/tr_shell02.C + Elements/Shells/tr_shell02.C + Elements/Shells/tr_shell11.C Elements/Shells/cct3d.C Elements/Shells/quad1mindlinshell3d.C Elements/Shells/shell7base.C @@ -53,9 +63,7 @@ set (sm_element Elements/Axisymmetry/l4axisymm.C Elements/PlaneStrain/quad1planestrain.C Elements/PlaneStrain/qplanestrain.C - Elements/PlaneStrain/qplanestraingrad.C Elements/PlaneStrain/qtrplanestrain.C - Elements/PlaneStrain/qtrplanestraingrad.C Elements/PlaneStrain/trplanestrain.C Elements/PlaneStress/planestresselementevaluator.C Elements/PlaneStress/trplanrot.C @@ -67,28 +75,58 @@ set (sm_element Elements/PlaneStress/planstrssxfem.C Elements/PlaneStress/trplanstrssxfem.C Elements/PlaneStress/qtrplanstrssxfem.C - Elements/PlaneStress/qtrplstrgrad.C Elements/PlaneStress/trplanrot3d.C - Elements/PlaneStress/qplanestressgrad.C Elements/PlaneStress/trplanestressrotallman.C Elements/PlaneStress/basicelement.C Elements/PlaneStress/trplanestressrotallman3d.C Elements/PlaneStress/linquad3d_planestress.C + Elements/PlaneStress/qtrplstrslip.C + Elements/PlaneStress/qplanstrssslip.C Elements/AbaqusUserElement.C Elements/htselement.C - Elements/latticestructuralelement.C - Elements/graddpelement.C Elements/lumpedmasselement.C Elements/springelement.C - Elements/lattice2d.C + Elements/LatticeElements/latticestructuralelement.C + Elements/LatticeElements/lattice2d.C + Elements/LatticeElements/lattice2dboundary.C + Elements/LatticeElements/lattice3d.C + Elements/LatticeElements/lattice3dboundary.C + Elements/LatticeElements/lattice3dboundarytruss.C + Elements/LatticeElements/latticelink3d.C + Elements/LatticeElements/latticelink3dboundary.C + Elements/LatticeElements/latticebeam3d.C + Elements/LatticeElements/latticebeam3dboundary.C + Elements/LatticeElements/latticeframe3d.C + Elements/LatticeElements/latticeframe3dnl.C Elements/tet21ghostsolid.C Elements/quad1platesubsoil.C Elements/quad2platesubsoil.C Elements/tria1platesubsoil.C + Elements/tria2platesubsoil.C Elements/linedistributedspring.C Elements/trwarp.C Elements/PlaneStress/basicelement.C Elements/nodalspringelement.C + #Gradient damage elements + Elements/GradientDamage/graddamageelement.C + Elements/GradientDamage/Bars/truss1dgraddamage.C + Elements/GradientDamage/Bars/qtruss1dgraddamage.C + Elements/GradientDamage/PlaneStrain/quad1planestraingraddamage.C + Elements/GradientDamage/PlaneStrain/qplanestraingraddamage.C + Elements/GradientDamage/PlaneStrain/qtrplanestraingraddamage.C + Elements/GradientDamage/PlaneStress/trplstrgraddamage.C + Elements/GradientDamage/PlaneStress/qtrplstrgraddamage.C + Elements/GradientDamage/PlaneStress/planestressgraddamage.C + Elements/GradientDamage/PlaneStress/qplanestressgraddamage.C + Elements/GradientDamage/3D/qspacegraddamage.C + Elements/GradientDamage/3D/qtrspacegraddamage.C + Elements/GradientDamage/3D/qspacegraddamage.C + Elements/GradientDamage/3D/qwedgegraddamage.C + #Mixed pressure elements + Elements/MixedPressure/basemixedpressureelement.C + Elements/MixedPressure/PlaneStrain/qtrplanestrainp1.C + Elements/MixedPressure/PlaneStrain/quad1planestrainp1.C + Elements/structural2delement.C Elements/structural3delement.C #Elements/phasefieldelement.C @@ -104,14 +142,25 @@ set (sm_interface_elements Elements/Interfaces/intelline2.C Elements/Interfaces/intelline2intpen.C Elements/Interfaces/intelsurftr1.C + Elements/Interfaces/intelsurfquad1.C + Elements/Interfaces/bondlink3d.C + Elements/Interfaces/bondlink3dboundary.C + # Elements/bondlink3dboundarybeam.C +# Elements/bondlink3dboundaryplate.C Elements/Interfaces/Deprecated/interfaceelement1d.C Elements/Interfaces/Deprecated/interfaceelem2dlin.C Elements/Interfaces/Deprecated/interfaceelem2dquad.C Elements/Interfaces/Deprecated/interfaceelem3dtrlin.C - ) + Elements/Interfaces/bondlink3dtruss.C +) set (sm_boundary_conditions Deprecated/prescribedgenstrainshell7.C + prescribeddispsliphomogenization.C + prescribeddispslipbcdirichletrc.C + prescribeddispslipbcneumannrc.C + prescribeddispslipmultiple.C + transversereinfconstraint.C ) set (sm_crosssection @@ -122,6 +171,7 @@ set (sm_crosssection CrossSections/structuralinterfacecrosssection.C CrossSections/variablecrosssection.C CrossSections/warpingcrosssection.C + CrossSections/latticecrosssection.C ) set (sm_emodel @@ -141,6 +191,7 @@ set (sm_emodel EngineeringModels/freewarping.C EngineeringModels/structuralmaterialevaluator.C EngineeringModels/qclinearstatic.C + EngineeringModels/pdelta.C ) set (sm_loads @@ -173,12 +224,13 @@ set (sm_material Materials/ConcreteMaterials/concretedpm2.C Materials/ConcreteMaterials/idm1.C Materials/ConcreteMaterials/idmnl1.C - Materials/ConcreteMaterials/idmgrad1.C + Materials/ConcreteMaterials/idmgrad.C Materials/ConcreteMaterials/mazarsmodel.C Materials/ConcreteMaterials/mazarsmodelnl.C Materials/ConcreteMaterials/mplasticmaterial2.C Materials/ConcreteMaterials/compodamagemat.C Materials/ConcreteMaterials/concretefcm.C + Materials/ConcreteMaterials/concretefcmviscoelastic.C Materials/ConcreteMaterials/frcfcm.C Materials/ConcreteMaterials/frcfcmnl.C Materials/RheoChainMaterials/rheoChM.C @@ -193,10 +245,10 @@ set (sm_material Materials/RheoChainMaterials/mpsdammat.C Materials/RheoChainMaterials/eurocode2creep.C Materials/structuralfe2material.C + Materials/structuralslipfe2material.C Materials/rcsd.C Materials/rcsde.C Materials/rcsdnl.C - Materials/mooneyrivlin.C Materials/m4.C Materials/microplane_m1.C Materials/druckerPragerPlasticitySM.C @@ -204,15 +256,12 @@ set (sm_material Materials/j2mat.C Materials/mdm.C Materials/micromaterial.C - Materials/hyperelasticmaterial.C Materials/misesmat.C Materials/misesmatgrad.C Materials/misesmatnl.C Materials/rankinemat.C Materials/rankinematgrad.C Materials/rankinematnl.C - Materials/latticematstatus.C - Materials/latticedamage2d.C Materials/dustmat.C Materials/lsmastermat.C Materials/lsmastermatgrad.C @@ -222,14 +271,41 @@ set (sm_material Materials/winklermodel.C Materials/structmatsettable.C Materials/tutorialmaterial.C - Materials/graddpmaterialextensioninterface.C + Materials/graddamagematerialextensioninterface.C Materials/rcm2.C Materials/isodamagemodel.C Materials/steelrelaxmat.C Materials/fcm.C - ) + #Mixed pressure material interface + Materials/MixedPressure/mixedpressurematerialextensioninterface.C + #Hyperelastic materials + Materials/HyperelasticMaterials/basehyperelasticmaterial.C + Materials/HyperelasticMaterials/mooneyrivlincompressiblematerial.C + Materials/HyperelasticMaterials/blatzkomaterial.C + Materials/HyperelasticMaterials/simopistermaterial.C + Materials/HyperelasticMaterials/ogdencompressiblematerial.C + Materials/HyperelasticMaterials/hyperelasticmaterial1d.C + #Lattice models + Materials/LatticeMaterials/latticematstatus.C + Materials/LatticeMaterials/latticestructuralmaterial.C + Materials/LatticeMaterials/latticelinearelastic.C + Materials/LatticeMaterials/latticedamage.C + Materials/LatticeMaterials/latticeviscoelastic.C + Materials/LatticeMaterials/latticedamageviscoelastic.C + Materials/LatticeMaterials/latticebondplasticity.C + Materials/LatticeMaterials/latticeplasticitydamage.C + Materials/LatticeMaterials/latticeslip.C + Materials/LatticeMaterials/latticeplasticitydamageviscoelastic.C + Materials/LatticeMaterials/latticeframeelastic.C + Materials/LatticeMaterials/latticeframesteelplastic.C + Materials/LatticeMaterials/latticeframeconcreteplastic.C + Materials/1D/isoasymm1d.C +) +if (USE_MFRONT) + list (APPEND sm_material Materials/mfrontusermaterial.C) +endif () -if (USE_PYTHON) +if (USE_BOOSTPYTHON_BINDINGS AND USE_PYTHON_EXTENSION) list (APPEND sm_material Materials/structuralpythonmaterial.C) endif () @@ -252,6 +328,7 @@ set (sm_interface_materials Materials/InterfaceMaterials/Deprecated/simpleinterfacemat.C Materials/InterfaceMaterials/masonry02.C Materials/InterfaceMaterials/mat_cebfip90.C + Materials/InterfaceMaterials/linkslip.C ) set (sm_error @@ -301,14 +378,17 @@ set (sm_unsorted particle.C refinedelement.C refinedmesh.C - microplane.C gpinitmodule.C stressstrainbasevector.C stressvector.C strainvector.C mappers/primvarmapper.C Contact/cdefnode2node.C Contact/celnode2node.C + Contact/ActiveBc/node2nodepenaltycontact.C + Contact/ActiveBc/node2nodelagrangianmultipliercontact.C ) + + set (sm_parallel FETISolver/feticommunicator.C FETISolver/fetiboundarydofman.C @@ -350,8 +430,9 @@ set (sm ${sm_obsolete} ${sm_new} ${sm_boundary_conditions} - ${sm_quasicontinuum} - ) + ${sm_quasicontinuum} + Elements/LatticeElements/latticebeam3dboundary.h +) if (USE_PARALLEL) list (APPEND sm ${sm_parallel}) diff --git a/src/sm/Contact/ActiveBc/node2nodelagrangianmultipliercontact.C b/src/sm/Contact/ActiveBc/node2nodelagrangianmultipliercontact.C new file mode 100644 index 000000000..00e668c73 --- /dev/null +++ b/src/sm/Contact/ActiveBc/node2nodelagrangianmultipliercontact.C @@ -0,0 +1,325 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "sm/Contact/ActiveBc/node2nodelagrangianmultipliercontact.h" +#include "set.h" +#include "domain.h" +#include "node.h" +#include "masterdof.h" +#include "floatmatrix.h" +#include "unknownnumberingscheme.h" +#include "sparsemtrx.h" +#include "classfactory.h" + +#ifdef _OPENMP +#include +#endif + +namespace oofem { +REGISTER_BoundaryCondition(Node2NodeLagrangianMultiplierContact); + + +Node2NodeLagrangianMultiplierContact :: Node2NodeLagrangianMultiplierContact(int n, Domain *d) : ActiveBoundaryCondition(n, d), lmdm() +{} + + +void +Node2NodeLagrangianMultiplierContact :: initializeFrom(InputRecord &ir) +{ + ActiveBoundaryCondition :: initializeFrom(ir); + this->useTangent = ir.hasField(_IFT_Node2NodeLagrangianMultiplierContact_useTangent); + IR_GIVE_FIELD(ir, this->masterSet, _IFT_Node2NodeLagrangianMultiplierContact_masterSet); + IR_GIVE_FIELD(ir, this->slaveSet, _IFT_Node2NodeLagrangianMultiplierContact_slaveSet); + + // these are internal lagrange multipliers used to enforce the no penetration for the contacting bodies + for ( int pos = 0; pos < masterSet.giveSize(); ++pos ) { + lmdm.push_back(std :: unique_ptr< Node >(new Node(0, domain) ) ); + lmdm.at(pos)->appendDof(new MasterDof(this->lmdm.at(pos).get(), ( DofIDItem ) ( this->giveDomain()->giveNextFreeDofID() ) ) ); + } +} + + +void +Node2NodeLagrangianMultiplierContact :: assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, + double scale, + void* lock) +{ + if ( !this->useTangent || type != TangentStiffnessMatrix ) { + return; + } + + FloatMatrix K; + IntArray loc, c_loc; + + IntArray dofIdArray = { + D_u, D_v + }; + + if ( masterSet.giveSize() != slaveSet.giveSize() ) { + OOFEM_ERROR("Number of master nodes does not match number of slave nodes") + } + + std :: vector< IntArray >lambdaeq; + this->giveLagrangianMultiplierLocationArray(r_s, lambdaeq); + for ( int pos = 1; pos <= masterSet.giveSize(); ++pos ) { + Node *masterNode = this->giveDomain()->giveNode(masterSet.at(pos) ); + Node *slaveNode = this->giveDomain()->giveNode(slaveSet.at(pos) ); + + masterNode->giveLocationArray(dofIdArray, loc, r_s); + slaveNode->giveLocationArray(dofIdArray, c_loc, c_s); + loc.followedBy(c_loc); + + double gap = this->computeTangentFromContact(K, masterNode, slaveNode, tStep); + if ( gap >= 0 ) { + // to make the equation system regular in the case there is no contact we initialize the allocated equation to the following form 1*labmda = 0, forcing lagrange multiplier of inactive condition to be zero. + FloatArray one(1); + one.at(1) = 1; +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif + answer.assemble(lambdaeq.at(pos - 1), one); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif + } else { +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif + answer.assemble(loc, lambdaeq.at(pos - 1), K); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif + FloatMatrix Kt; + Kt.beTranspositionOf(K); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif + answer.assemble(lambdaeq.at(pos - 1), loc, Kt); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif + } + } +} + +void +Node2NodeLagrangianMultiplierContact :: assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, + FloatArray *eNorms, + void* lock) +{ + if ( masterSet.giveSize() != slaveSet.giveSize() ) { + OOFEM_ERROR("Number of master nodes does not match number of slave nodes"); + } + + + //IntArray dofIdArray = {D_u, D_v, D_w}; + IntArray dofIdArray = { + D_u, D_v + }; + + + if ( type == InternalForcesVector ) { + // assemble lagrangian multiplier contribution to residuum + int size = masterSet.giveSize(); + // assemble location array + for ( int pos = 1; pos <= size; pos++ ) { + IntArray loc, s_loc; + FloatArray n; + Node *masterNode = this->giveDomain()->giveNode(masterSet.at(pos) ); + Node *slaveNode = this->giveDomain()->giveNode(slaveSet.at(pos) ); + this->computeNormalMatrixAt(n, masterNode, slaveNode, tStep); + Dof *mdof = * ( lmdm.at(pos - 1)->begin() ); + n.times(mdof->giveUnknown(mode, tStep) ); + masterNode->giveLocationArray(dofIdArray, loc, s); + slaveNode->giveLocationArray(dofIdArray, s_loc, s); + loc.followedBy(s_loc); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif + answer.assemble(n, loc); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif + } + } else if ( type == ExternalForcesVector ) { + IntArray loc, c_loc; + FloatArray fext; + + + std :: vector< IntArray >lambdaeq; + this->giveLagrangianMultiplierLocationArray(s, lambdaeq); + + for ( int pos = 1; pos <= masterSet.giveSize(); ++pos ) { + Node *masterNode = this->giveDomain()->giveNode(masterSet.at(pos) ); + Node *slaveNode = this->giveDomain()->giveNode(slaveSet.at(pos) ); + this->computeExternalForcesFromContact(fext, masterNode, slaveNode, tStep); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif + answer.assemble(fext, lambdaeq.at(pos - 1) ); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif + } + } +} + + + +double +Node2NodeLagrangianMultiplierContact :: computeTangentFromContact(FloatMatrix &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep) +{ + double gap; + FloatArray Nv; + this->computeGap(gap, masterNode, slaveNode, tStep); + this->computeNormalMatrixAt(Nv, masterNode, slaveNode, tStep); + answer.initFromVector(Nv, false); + + return gap; + //answer.times(this->penalty); + /* if ( gap > 0.0 ) { + * int size = this->masterSet.giveSize(); + * FloatMatrix help(2 * size, 2 * size); + * answer.beUnitMatrix(); + * }*/ +} + +void +Node2NodeLagrangianMultiplierContact :: computeGap(double &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep) +{ + FloatArray uS, uM; + auto xs = slaveNode->giveCoordinates(); + auto xm = masterNode->giveCoordinates(); + FloatArray normal = xs - xm; + double norm = normal.computeNorm(); + if ( norm < 1.0e-8 ) { + OOFEM_ERROR("Couldn't compute normal between master node (num %d) and slave node (num %d), nodes are too close to each other.", masterNode->giveGlobalNumber(), slaveNode->giveGlobalNumber() ); + } else { + normal.times(1.0 / norm); + } + + slaveNode->giveUnknownVector(uS, { D_u, D_v }, VM_Total, tStep, true); + masterNode->giveUnknownVector(uM, { D_u, D_v }, VM_Total, tStep, true); + xs.add(uS); + xm.add(uM); + FloatArray dx = xs - xm; + answer = dx.dotProduct(normal); +} + + +void +Node2NodeLagrangianMultiplierContact :: computeNormalMatrixAt(FloatArray &answer, Node *masterNode, Node *slaveNode, TimeStep *TimeStep) +{ + const auto &xs = slaveNode->giveCoordinates(); + const auto &xm = masterNode->giveCoordinates(); + auto normal = xs - xm; + double norm = normal.computeNorm(); + if ( norm < 1.0e-8 ) { + OOFEM_ERROR("Couldn't compute normal between master node (num %d) and slave node (num %d), nodes are too close to each other.", masterNode->giveGlobalNumber(), slaveNode->giveGlobalNumber() ); + } else { + normal.times(1.0 / norm); + } + // The normal is not updated for node2node which is for small deformations only + // C = {n -n} + answer = { + normal.at(1), normal.at(2), + -normal.at(1), -normal.at(2) + }; +} + + +void +Node2NodeLagrangianMultiplierContact :: computeExternalForcesFromContact(FloatArray &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep) +{ + answer.resize(1); + this->computeGap(answer.at(1), masterNode, slaveNode, tStep); + if ( answer.at(1) > 0.0 ) { + answer.at(1) = 0.0; + } +} + + +void +Node2NodeLagrangianMultiplierContact :: giveLagrangianMultiplierLocationArray(const UnknownNumberingScheme &r_s, std :: vector< IntArray > &answer) +{ + int size = this->masterSet.giveSize(); + answer.resize(size); + IntArray dofIdArray = { + D_u, D_v + }; + + // assemble location array + IntArray l(1); + for ( int i = 0; i < size; i++ ) { + l.at(1) = r_s.giveDofEquationNumber(* lmdm.at(i)->begin() ); + answer.at(i) = l; + } +} + + +void +Node2NodeLagrangianMultiplierContact :: giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) +{ + IntArray r_loc, c_loc; + rows.resize(3 * masterSet.giveSize() ); + cols.resize(3 * masterSet.giveSize() ); + IntArray dofIdArray = { + D_u, D_v + }; + std :: vector< IntArray >lambdaeq; + this->giveLagrangianMultiplierLocationArray(r_s, lambdaeq); + + for ( int pos = 1; pos <= masterSet.giveSize(); pos++ ) { + Node *masterNode = this->giveDomain()->giveNode(masterSet.at(pos) ); + Node *slaveNode = this->giveDomain()->giveNode(slaveSet.at(pos) ); + + masterNode->giveLocationArray(dofIdArray, r_loc, r_s); + slaveNode->giveLocationArray(dofIdArray, c_loc, c_s); + + // column block + rows [ 0 + 3 * ( pos - 1 ) ] = r_loc; + cols [ 0 + 3 * ( pos - 1 ) ] = lambdaeq.at(pos - 1); + // row block + cols [ 1 + 3 * ( pos - 1 ) ] = c_loc; + rows [ 1 + 3 * ( pos - 1 ) ] = lambdaeq.at(pos - 1); + // diagonal enry (some sparse mtrx implementation requaire this) + rows [ 2 + 3 * ( pos - 1 ) ] = lambdaeq.at(pos - 1); + cols [ 2 + 3 * ( pos - 1 ) ] = lambdaeq.at(pos - 1); + } +} +} // namespace oofem diff --git a/src/sm/Contact/ActiveBc/node2nodelagrangianmultipliercontact.h b/src/sm/Contact/ActiveBc/node2nodelagrangianmultipliercontact.h new file mode 100644 index 000000000..3cf1f86a8 --- /dev/null +++ b/src/sm/Contact/ActiveBc/node2nodelagrangianmultipliercontact.h @@ -0,0 +1,114 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef node2nodelagrangianmultipliercontact_h +#define node2nodelagrangianmultipliercontact_h + + +#include "activebc.h" + + +///@name Input fields for _IFT_ContactElement +//@{ +#define _IFT_Node2NodeLagrangianMultiplierContact_Name "n2nlagrangianmultipliercontact" +#define _IFT_Node2NodeLagrangianMultiplierContact_useTangent "usetangent" + +#define _IFT_Node2NodeLagrangianMultiplierContact_masterSet "masterset" +#define _IFT_Node2NodeLagrangianMultiplierContact_slaveSet "slaveset" + + + + +//@} + +namespace oofem { +class Domain; +class SparseMtrx; +class TimeStep; +class DofManager; +class GaussPoint; +class UnknownNumberingScheme; +class FloatMatrix; +class IntegrationRule; +class ContactElement; +class Node; + +class OOFEM_EXPORT Node2NodeLagrangianMultiplierContact : public ActiveBoundaryCondition +{ +protected: + bool useTangent; ///< Determines if tangent should be used. + IntArray slaveSet; + IntArray masterSet; + std :: vector< std :: shared_ptr< DofManager > >lmdm; +public: + + /// Constructor. + Node2NodeLagrangianMultiplierContact(int n, Domain *d); + //: ActiveBoundaryCondition(n, d) { } + /// Destructor. + virtual ~Node2NodeLagrangianMultiplierContact() {}; + + void initializeFrom(InputRecord &ir) override; + + void assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0, + void*lock=nullptr) override; + + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorms = NULL, + void *lock=nullptr) override; + + + const char *giveClassName() const override { return "Node2NodeLagrangianMultiplierContact"; } + const char *giveInputRecordName() const override { return _IFT_Node2NodeLagrangianMultiplierContact_Name; } + + int giveNumberOfInternalDofManagers() override { return masterSet.giveSize(); } + DofManager *giveInternalDofManager(int i) override { return this->lmdm.at(i - 1).get(); } + + + + double computeTangentFromContact(FloatMatrix &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep); + void computeGap(double &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep); + + void computeNormalMatrixAt(FloatArray &answer, Node *masterNode, Node *slaveNode, TimeStep *TimeStep); + + + void computeExternalForcesFromContact(FloatArray &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep); + + void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) override; + void giveLagrangianMultiplierLocationArray(const UnknownNumberingScheme &r_s, std :: vector< IntArray > &answer); +}; +} // end namespace oofem +#endif // node2nodecontact_h diff --git a/src/sm/Contact/ActiveBc/node2nodepenaltycontact.C b/src/sm/Contact/ActiveBc/node2nodepenaltycontact.C new file mode 100644 index 000000000..61312bab7 --- /dev/null +++ b/src/sm/Contact/ActiveBc/node2nodepenaltycontact.C @@ -0,0 +1,256 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "sm/Contact/ActiveBc/node2nodepenaltycontact.h" +#include "set.h" +#include "domain.h" +#include "node.h" +#include "floatmatrix.h" +#include "unknownnumberingscheme.h" +#include "sparsemtrx.h" +#include "classfactory.h" + +#ifdef _OPENMP +#include +#endif + +namespace oofem { +REGISTER_BoundaryCondition(Node2NodePenaltyContact); + + +void +Node2NodePenaltyContact :: initializeFrom(InputRecord &ir) +{ + ActiveBoundaryCondition :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, this->penalty, _IFT_Node2NodePenaltyContact_penalty); + this->useTangent = ir.hasField(_IFT_Node2NodePenaltyContact_useTangent); + + + IR_GIVE_FIELD(ir, this->masterSet, _IFT_Node2NodePenaltyContact_masterSet); + IR_GIVE_FIELD(ir, this->slaveSet, _IFT_Node2NodePenaltyContact_slaveSet); +} + + +void +Node2NodePenaltyContact :: assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, double scale, + void* lock) +{ + if ( !this->useTangent || type != TangentStiffnessMatrix ) { + return; + } + + + FloatMatrix K; + IntArray loc, c_loc; + + IntArray dofIdArray = { + D_u, D_v + }; + + if ( masterSet.giveSize() != slaveSet.giveSize() ) { + OOFEM_ERROR("Number of master nodes does not match number of slave nodes") + } + + for ( int pos = 1; pos <= masterSet.giveSize(); ++pos ) { + Node *masterNode = this->giveDomain()->giveNode(masterSet.at(pos) ); + Node *slaveNode = this->giveDomain()->giveNode(slaveSet.at(pos) ); + + masterNode->giveLocationArray(dofIdArray, loc, r_s); + slaveNode->giveLocationArray(dofIdArray, c_loc, c_s); + loc.followedBy(c_loc); + + this->computeTangentFromContact(K, masterNode, slaveNode, tStep); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif + answer.assemble(loc, K); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif + } +} + +void +Node2NodePenaltyContact :: assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorms, + void*lock) +{ + if ( type != ExternalForcesVector ) { + return; + } + + //IntArray dofIdArray = {D_u, D_v, D_w}; + IntArray dofIdArray = { + D_u, D_v + }; + + IntArray loc, c_loc; + FloatArray fext; + + if ( masterSet.giveSize() != slaveSet.giveSize() ) { + OOFEM_ERROR("Number of master nodes does not match number of slave nodes") + } + + for ( int pos = 1; pos <= masterSet.giveSize(); ++pos ) { + Node *masterNode = this->giveDomain()->giveNode(masterSet.at(pos) ); + Node *slaveNode = this->giveDomain()->giveNode(slaveSet.at(pos) ); + + masterNode->giveLocationArray(dofIdArray, loc, s); + slaveNode->giveLocationArray(dofIdArray, c_loc, s); + this->computeExternalForcesFromContact(fext, masterNode, slaveNode, tStep); + loc.followedBy(c_loc); +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif + answer.assemble(fext, loc); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif + } +} + + + + + + +void +Node2NodePenaltyContact :: giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) +{ + IntArray r_loc, c_loc; + rows.resize(masterSet.giveSize() ); + cols.resize(masterSet.giveSize() ); + IntArray dofIdArray = { + D_u, D_v + }; + + for ( int pos = 1; pos <= masterSet.giveSize(); ++pos ) { + Node *masterNode = this->giveDomain()->giveNode(masterSet.at(pos) ); + Node *slaveNode = this->giveDomain()->giveNode(slaveSet.at(pos) ); + + masterNode->giveLocationArray(dofIdArray, r_loc, r_s); + slaveNode->giveLocationArray(dofIdArray, c_loc, c_s); + + // column block + rows [ pos - 1 ] = r_loc; + cols [ pos - 1 ] = c_loc; + } +} + + + + + + + + + +void +Node2NodePenaltyContact :: computeTangentFromContact(FloatMatrix &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep) +{ + double gap; + FloatArray Nv; + this->computeGap(gap, masterNode, slaveNode, tStep); + this->computeNormalMatrixAt(Nv, masterNode, slaveNode, tStep); + answer.beDyadicProductOf(Nv, Nv); + answer.times(this->penalty); + if ( gap > 0.0 ) { + answer.zero(); + } +} + +void +Node2NodePenaltyContact :: computeGap(double &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep) +{ + FloatArray uS, uM; + auto xs = slaveNode->giveCoordinates(); + auto xm = masterNode->giveCoordinates(); + FloatArray normal = xs - xm; + double norm = normal.computeNorm(); + if ( norm < 1.0e-8 ) { + OOFEM_ERROR("Couldn't compute normal between master node (num %d) and slave node (num %d), nodes are too close to each other.", + masterNode->giveGlobalNumber(), slaveNode->giveGlobalNumber() ); + } else { + normal.times(1.0 / norm); + } + + slaveNode->giveUnknownVector(uS, { D_u, D_v }, VM_Total, tStep, true); + masterNode->giveUnknownVector(uM, { D_u, D_v }, VM_Total, tStep, true); + xs.add(uS); + xm.add(uM); + FloatArray dx = xs - xm; + answer = dx.dotProduct(normal); +} + + +void +Node2NodePenaltyContact :: computeNormalMatrixAt(FloatArray &answer, Node *masterNode, Node *slaveNode, TimeStep *TimeStep) +{ + const auto &xs = slaveNode->giveCoordinates(); + const auto &xm = masterNode->giveCoordinates(); + auto normal = xs - xm; + double norm = normal.computeNorm(); + if ( norm < 1.0e-8 ) { + OOFEM_ERROR("Couldn't compute normal between master node (num %d) and slave node (num %d), nodes are too close to each other.", + masterNode->giveGlobalNumber(), slaveNode->giveGlobalNumber() ); + } else { + normal.times(1.0 / norm); + } + // The normal is not updated for node2node which is for small deformations only + // C = {n -n} + answer = { + normal.at(1), normal.at(2), + -normal.at(1), -normal.at(2) + }; +} + + +void +Node2NodePenaltyContact :: computeExternalForcesFromContact(FloatArray &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep) +{ + double gap; + this->computeGap(gap, masterNode, slaveNode, tStep); + this->computeNormalMatrixAt(answer, masterNode, slaveNode, tStep); + if ( gap < 0.0 ) { + answer.times(penalty * gap); + } else { + answer.times(0); + } +} +} // namespace oofem diff --git a/src/sm/Contact/ActiveBc/node2nodepenaltycontact.h b/src/sm/Contact/ActiveBc/node2nodepenaltycontact.h new file mode 100644 index 000000000..8afaa504f --- /dev/null +++ b/src/sm/Contact/ActiveBc/node2nodepenaltycontact.h @@ -0,0 +1,109 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef node2nodecontact_h +#define node2nodecontact_h + + +#include "activebc.h" + + +///@name Input fields for _IFT_ContactElement +//@{ +#define _IFT_Node2NodePenaltyContact_Name "n2npenaltycontact" +#define _IFT_Node2NodePenaltyContact_penalty "penalty" +#define _IFT_Node2NodePenaltyContact_useTangent "usetangent" + +#define _IFT_Node2NodePenaltyContact_masterSet "masterset" +#define _IFT_Node2NodePenaltyContact_slaveSet "slaveset" + + + + +//@} + +namespace oofem { +class Domain; +class SparseMtrx; +class TimeStep; +class DofManager; +class GaussPoint; +class UnknownNumberingScheme; +class FloatMatrix; +class IntegrationRule; +class ContactElement; +class Node; + +class OOFEM_EXPORT Node2NodePenaltyContact : public ActiveBoundaryCondition +{ +protected: + bool useTangent; ///< Determines if tangent should be used. + double penalty; + IntArray slaveSet; + IntArray masterSet; +public: + + /// Constructor. + Node2NodePenaltyContact(int n, Domain *d) : ActiveBoundaryCondition(n, d) { } + /// Destructor. + virtual ~Node2NodePenaltyContact() {}; + + void initializeFrom(InputRecord &ir) override; + + void assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, + double scale = 1.0, void* lock=nullptr) override; + + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorms = NULL, void*lock=nullptr) override; + + + const char *giveClassName() const override { return "Node2NodePenaltyContact"; } + const char *giveInputRecordName() const override { return _IFT_Node2NodePenaltyContact_Name; } + + + void computeTangentFromContact(FloatMatrix &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep); + void computeGap(double &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep); + + void computeNormalMatrixAt(FloatArray &answer, Node *masterNode, Node *slaveNode, TimeStep *TimeStep); + + + void computeExternalForcesFromContact(FloatArray &answer, Node *masterNode, Node *slaveNode, TimeStep *tStep); + + void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) override; + +}; +} // end namespace oofem +#endif // node2nodecontact_h diff --git a/src/sm/Contact/cdefnode2node.C b/src/sm/Contact/cdefnode2node.C index 8caac2cb9..05b8e9b86 100644 --- a/src/sm/Contact/cdefnode2node.C +++ b/src/sm/Contact/cdefnode2node.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Contact/cdefnode2node.h" -#include "Contact/celnode2node.h" +#include "sm/Contact/cdefnode2node.h" +#include "sm/Contact/celnode2node.h" #include "domain.h" #include "classfactory.h" @@ -45,12 +45,9 @@ REGISTER_ContactDefinition(ContactDefinitionNode2NodeL) ContactDefinitionNode2Node :: ContactDefinitionNode2Node(ContactManager *cMan) : ContactDefinition(cMan){} -IRResultType -ContactDefinitionNode2Node :: initializeFrom(InputRecord *ir) +void +ContactDefinitionNode2Node :: initializeFrom(InputRecord &ir) { - - IRResultType result; // Required by IR_GIVE_FIELD macro - IntArray masterNodes; IntArray slaveNodes; IR_GIVE_FIELD(ir, masterNodes, _IFT_ContactDefinitionNode2Node_MasterNodes); @@ -65,13 +62,9 @@ ContactDefinitionNode2Node :: initializeFrom(InputRecord *ir) this->addContactElement(master); } - - return IRRT_OK; } - - // Same version but with Lagrange multipliers ContactDefinitionNode2NodeL :: ContactDefinitionNode2NodeL(ContactManager *cMan) : ContactDefinitionNode2Node(cMan) { @@ -79,11 +72,9 @@ ContactDefinitionNode2NodeL :: ContactDefinitionNode2NodeL(ContactManager *cMan) } -IRResultType -ContactDefinitionNode2NodeL :: initializeFrom(InputRecord *ir) +void +ContactDefinitionNode2NodeL :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IntArray masterNodes; IntArray slaveNodes; IR_GIVE_FIELD(ir, masterNodes, _IFT_ContactDefinitionNode2Node_MasterNodes); @@ -96,14 +87,6 @@ ContactDefinitionNode2NodeL :: initializeFrom(InputRecord *ir) this->addContactElement(master); } - - - - return IRRT_OK; } - - - - } diff --git a/src/sm/Contact/cdefnode2node.h b/src/sm/Contact/cdefnode2node.h index 359356478..9643dbae5 100644 --- a/src/sm/Contact/cdefnode2node.h +++ b/src/sm/Contact/cdefnode2node.h @@ -68,7 +68,7 @@ class OOFEM_EXPORT ContactDefinitionNode2Node : public ContactDefinition private: double epsN; double epsT; // these should be 'contactmaterial' par - + public: /// Constructor. @@ -76,17 +76,13 @@ class OOFEM_EXPORT ContactDefinitionNode2Node : public ContactDefinition /// Destructor. virtual ~ContactDefinitionNode2Node(){}; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveClassName() const { return "ContactDefinitionNode2Node"; } - virtual const char *giveInputRecordName() const { return _IFT_ContactDefinitionNode2Node_Name; } - + const char *giveClassName() const override { return "ContactDefinitionNode2Node"; } + virtual const char *giveInputRecordName() const { return _IFT_ContactDefinitionNode2Node_Name; } }; - - - /** * This class manages a none to node contact definition with enforcement using Lagrange multipliers. * @@ -102,11 +98,10 @@ class OOFEM_EXPORT ContactDefinitionNode2NodeL : public ContactDefinitionNode2No /// Destructor. virtual ~ContactDefinitionNode2NodeL(){}; - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual const char *giveClassName() const { return "ContactDefinitionNode2NodeL"; } - virtual const char *giveInputRecordName() const { return _IFT_ContactDefinitionNode2NodeL_Name; } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "ContactDefinitionNode2NodeL"; } + const char *giveInputRecordName() const override { return _IFT_ContactDefinitionNode2NodeL_Name; } }; diff --git a/src/sm/Contact/celnode2node.C b/src/sm/Contact/celnode2node.C index a0d90c630..c4f054312 100644 --- a/src/sm/Contact/celnode2node.C +++ b/src/sm/Contact/celnode2node.C @@ -32,33 +32,31 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Contact/celnode2node.h" +#include "sm/Contact/celnode2node.h" #include "floatmatrix.h" #include "masterdof.h" #include "unknownnumberingscheme.h" #include "gaussintegrationrule.h" namespace oofem { - - - + Node2NodeContact :: Node2NodeContact(DofManager *master, DofManager *slave) : ContactElement() -{ +{ this->masterNode = master; this->slaveNode = slave; this->area = 1.0; // should be optional parameter this->epsN = 1.0e6; // penalty - should be given by 'contactmaterial' -}; - +} + + int -Node2NodeContact :: instanciateYourself(DataReader *dr) +Node2NodeContact :: instanciateYourself(DataReader &dr) { // compute normal as direction vector from master node to slave node - FloatArray xs, xm, _normal; - xs = *this->slaveNode->giveCoordinates(); - xm = *this->masterNode->giveCoordinates(); - - _normal = xs-xm; + const auto &xs = this->slaveNode->giveCoordinates(); + const auto &xm = this->masterNode->giveCoordinates(); + + auto _normal = xs - xm; double norm = _normal.computeNorm(); if ( norm < 1.0e-8 ) { OOFEM_ERROR("Couldn't compute normal between master node (num %d) and slave node (num %d), nodes are too close to each other.", @@ -73,44 +71,35 @@ Node2NodeContact :: instanciateYourself(DataReader *dr) void Node2NodeContact :: computeGap(FloatArray &answer, TimeStep *tStep) { - - FloatArray xs, xm, uS, uM; - xs = *this->slaveNode->giveCoordinates(); - xm = *this->masterNode->giveCoordinates(); + FloatArray uS, uM; + auto xs = this->slaveNode->giveCoordinates(); + auto xm = this->masterNode->giveCoordinates(); this->slaveNode->giveUnknownVector(uS, {D_u, D_v, D_w}, VM_Total, tStep, true); this->masterNode->giveUnknownVector(uM, {D_u, D_v, D_w}, VM_Total, tStep, true); xs.add(uS); xm.add(uM); FloatArray dx = xs-xm; - + FloatArray normal = this->giveNormal(); answer = {dx.dotProduct(normal), 0.0, 0.0}; - + //printf("normal gap = %e \n", answer.at(1)); - if ( answer.at(1) < 0.0 ) { - //printf("normal gap = %e \n", answer.at(1)); - this->inContact = true; // store in gp? - } else { - this->inContact = false; - } - + // store in gp? + this->inContact = answer.at(1) < 0.0; } void Node2NodeContact :: computeCmatrixAt(GaussPoint *gp, FloatArray &answer, TimeStep *TimeStep) { - // The normal is not updated for node2node which is for small deformations only // C = {n -n} FloatArray normal = this->giveNormal(); answer = { normal.at(1), normal.at(2), normal.at(3), -normal.at(1), -normal.at(2), -normal.at(3) }; - } - void Node2NodeContact :: computeContactTractionAt(GaussPoint *gp, FloatArray &t, FloatArray &gap, TimeStep *tStep) { @@ -121,44 +110,39 @@ Node2NodeContact :: computeContactTractionAt(GaussPoint *gp, FloatArray &t, Floa } else { t = {0.0, 0.0, 0.0}; } - } - - - void Node2NodeContact :: computeContactForces(FloatArray &answer, TimeStep *tStep, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms) { answer.clear(); FloatArray gap, C; - + this->computeGap(gap, tStep); if ( gap.at(1) < 0.0 ) { GaussPoint *gp = this->integrationRule->getIntegrationPoint(0); FloatArray t; this->computeContactTractionAt(gp, t ,gap, tStep); - + this->computeCmatrixAt(gp, C, tStep); - + // compute load vector // fc = C^T * traction * A, Area - should be optional par answer = t.at(1) * this->area * C; - + } - } - + void Node2NodeContact :: computeContactTangent(FloatMatrix &answer, TimeStep *tStep) { - // Need to set up an integration rule + // Need to set up an integration rule GaussPoint *gp = NULL; FloatArray gap; - + this->computeGap(gap, tStep); FloatArray C; @@ -172,10 +156,6 @@ Node2NodeContact :: computeContactTangent(FloatMatrix &answer, TimeStep *tStep) answer.zero(); } } - - - - void @@ -183,17 +163,16 @@ Node2NodeContact :: giveLocationArray(IntArray &answer, const UnknownNumberingSc { // should return location array for the master and the slave node // TODO this whole thing should be rewritten - - + answer.resize(6); answer.zero(); //TODO should use a proper unknownnumberingscheme IntArray dofIdArray = {D_u, D_v, D_w}; - + // master node for ( int i = 1; i <= dofIdArray.giveSize(); i++ ) { if ( this->masterNode->hasDofID( (DofIDItem)dofIdArray.at(i) ) ) { // add corresponding number - Dof *dof= this->masterNode->giveDofWithID( (DofIDItem)dofIdArray.at(i) ); + Dof *dof = this->masterNode->giveDofWithID( (DofIDItem)dofIdArray.at(i) ); answer.at(i) = s.giveDofEquationNumber( dof ); } } @@ -201,85 +180,64 @@ Node2NodeContact :: giveLocationArray(IntArray &answer, const UnknownNumberingSc // slave node for ( int i = 1; i <= dofIdArray.giveSize(); i++ ) { if ( this->slaveNode->hasDofID( (DofIDItem)dofIdArray.at(i) ) ) { // add corresponding number - Dof *dof= this->slaveNode->giveDofWithID( (DofIDItem)dofIdArray.at(i) ); + Dof *dof = this->slaveNode->giveDofWithID( (DofIDItem)dofIdArray.at(i) ); answer.at(3 + i) = s.giveDofEquationNumber( dof ); - } - } - -} + } + } +} void Node2NodeContact :: setupIntegrationPoints() { // Sets up the integration rule array which contains all the necessary integration points - if ( this->integrationRule == NULL ) { + if ( !this->integrationRule ) { //TODO sets a null pointer for the element in the iRule - this->integrationRule = new GaussIntegrationRule(1, NULL) ; + this->integrationRule = std::make_unique(1, nullptr); this->integrationRule->SetUpPoint(_Unknown); } - - } - - - - - - - - - - - - // node 2 node Lagrange - Node2NodeContactL :: Node2NodeContactL(DofManager *master, DofManager *slave) : Node2NodeContact(master, slave) -{ +{ this->masterNode = master; this->slaveNode = slave; this->area = 1.0; -}; - +} void Node2NodeContactL :: giveLocationArray(IntArray &answer, const UnknownNumberingScheme &s) { - Node2NodeContact :: giveLocationArray(answer, s); - + // Add one lagrange dof if ( this->masterNode->hasDofID( (DofIDItem)this->giveDofIdArray().at(1) ) ) { Dof *dof= this->masterNode->giveDofWithID( (DofIDItem)this->giveDofIdArray().at(1) ); answer.followedBy( s.giveDofEquationNumber(dof) ); } - -} - +} void Node2NodeContactL :: computeContactForces(FloatArray &answer, TimeStep *tStep, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms) { - //Loop through all the master objects and let them do their thing FloatArray gap, C; this->computeGap(gap, tStep); - + GaussPoint *gp = this->integrationRule->getIntegrationPoint(0); FloatArray t; this->computeContactTractionAt(gp, t ,gap, tStep); this->computeCmatrixAt(gp, C, tStep); - + // compute load vector // for Lagrange: fc = traction * C^T * A (traction = lambda) FloatArray temp = t.at(1) *this->area * C; - + answer.resize( C.giveSize() + 1); answer.zero(); if( gap.at(1) < 0.0 ) { @@ -287,7 +245,6 @@ Node2NodeContactL :: computeContactForces(FloatArray &answer, TimeStep *tStep, V answer.at( C.giveSize() + 1 ) = -gap.at(1); } } - void @@ -295,68 +252,51 @@ Node2NodeContactL :: computeContactTangent(FloatMatrix &answer, TimeStep *tStep) { answer.resize(7,7); answer.zero(); - + FloatArray gap; this->computeGap(gap, tStep); - - if( gap.at(1) < 0.0 ) { - + + if ( gap.at(1) < 0.0 ) { + GaussPoint *gp = this->integrationRule->getIntegrationPoint(0); - + FloatArray C; this->computeCmatrixAt(gp, C, tStep); int sz = C.giveSize(); C.times(this->area); - + answer.addSubVectorCol(C, 1, sz + 1); answer.addSubVectorRow(C, sz + 1, 1); } - + //TODO need to add a small number for the solver for ( int i = 1; i <= 7; i++ ) { answer.at(i,i) += 1.0e-8; } - } - - + void Node2NodeContactL :: computeContactTractionAt(GaussPoint *gp, FloatArray &t, FloatArray &gap, TimeStep *tStep) { // should be replaced with a call to constitutive model // gap should be in a local system if ( gap.at(1) < 0.0 ) { - - Dof *dof = masterNode->giveDofWithID( this->giveDofIdArray().at(1) ); + auto dof = masterNode->giveDofWithID( this->giveDofIdArray().at(1) ); double lambda = dof->giveUnknown(VM_Total, tStep); t = {lambda, 0.0, 0.0}; //printf("lambda %e \n\n", lambda); } else { t = {0.0, 0.0, 0.0}; } - -} - - +} + + void Node2NodeContactL :: giveDofManagersToAppendTo(IntArray &answer) { answer = {this->masterNode->giveNumber()}; } - - - -} - - - - - - - - - - +} diff --git a/src/sm/Contact/celnode2node.h b/src/sm/Contact/celnode2node.h index 049d0ba47..2d5198efe 100644 --- a/src/sm/Contact/celnode2node.h +++ b/src/sm/Contact/celnode2node.h @@ -64,11 +64,11 @@ class OOFEM_EXPORT Node2NodeContact : public ContactElement private: DofManager *masterNode; DofManager *slaveNode; - + // should be set by input: double area; // The area associated with the node (default = 1)- in order to represent some physical dimension. double epsN; // penalty stiffness - + FloatArray normal; public: @@ -76,25 +76,23 @@ class OOFEM_EXPORT Node2NodeContact : public ContactElement Node2NodeContact(DofManager *master, DofManager *slave); /// Destructor. virtual ~Node2NodeContact(){}; - virtual int instanciateYourself(DataReader *dr); - virtual void setupIntegrationPoints(); - + int instanciateYourself(DataReader &dr) override; + void setupIntegrationPoints() override; + virtual void computeGap(FloatArray &answer, TimeStep *tStep); virtual void computeContactTractionAt(GaussPoint *gp, FloatArray &t, FloatArray &gap, TimeStep *tStep); virtual void computeCmatrixAt(GaussPoint *gp, FloatArray &answer, TimeStep *TimeStep); FloatArray &giveNormal() { return this->normal; } - - + + // Necessary methods - pure virtual in base class - virtual void computeContactForces(FloatArray &answer, TimeStep *tStep, ValueModeType mode, - const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms); - - virtual void computeContactTangent(FloatMatrix &answer, TimeStep *tStep); - - virtual void giveLocationArray(IntArray &answer, const UnknownNumberingScheme &s); -}; + void computeContactForces(FloatArray &answer, TimeStep *tStep, ValueModeType mode, + const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms) override; + void computeContactTangent(FloatMatrix &answer, TimeStep *tStep) override; + void giveLocationArray(IntArray &answer, const UnknownNumberingScheme &s) override; +}; class OOFEM_EXPORT Node2NodeContactL : public Node2NodeContact @@ -106,30 +104,26 @@ class OOFEM_EXPORT Node2NodeContactL : public Node2NodeContact DofManager *masterNode; DofManager *slaveNode; int lagrangeId; // dof Id associated with the Lagrange multiplier - + // should be set by input: double area; // The area associated with the node (default = 1)- in order to represent some physical dimension. - - -public: +public: /// Constructor. Node2NodeContactL(DofManager *master, DofManager *slave); /// Destructor. virtual ~Node2NodeContactL(){}; - virtual void giveDofManagersToAppendTo(IntArray &answer); - virtual void computeContactTractionAt(GaussPoint *gp, FloatArray &t, FloatArray &gap, TimeStep *tStep); - + void giveDofManagersToAppendTo(IntArray &answer) override; + void computeContactTractionAt(GaussPoint *gp, FloatArray &t, FloatArray &gap, TimeStep *tStep) override; + // Necessary methods - pure virtual in base class - virtual void computeContactForces(FloatArray &answer, TimeStep *tStep, ValueModeType mode, - const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms); - - virtual void computeContactTangent(FloatMatrix &answer, TimeStep *tStep); - - virtual void giveLocationArray(IntArray &answer, const UnknownNumberingScheme &s); -}; + void computeContactForces(FloatArray &answer, TimeStep *tStep, ValueModeType mode, + const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms) override; + void computeContactTangent(FloatMatrix &answer, TimeStep *tStep) override; + void giveLocationArray(IntArray &answer, const UnknownNumberingScheme &s) override; +}; } // end namespace oofem #endif // celnode2node_h diff --git a/src/sm/CrossSections/fiberedcs.C b/src/sm/CrossSections/fiberedcs.C index 2f48d1721..34720b333 100644 --- a/src/sm/CrossSections/fiberedcs.C +++ b/src/sm/CrossSections/fiberedcs.C @@ -32,10 +32,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/CrossSections/fiberedcs.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/CrossSections/fiberedcs.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "gausspoint.h" #include "material.h" #include "floatarray.h" @@ -46,96 +46,183 @@ namespace oofem { REGISTER_CrossSection(FiberedCrossSection); -void -FiberedCrossSection :: giveRealStress_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 6 > +FiberedCrossSection::giveRealStress_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 6 >(); } -void -FiberedCrossSection :: giveRealStress_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 4 > +FiberedCrossSection::giveRealStress_PlaneStrain(const FloatArrayF< 4 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 4 >(); } -void -FiberedCrossSection :: giveRealStress_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 3 > +FiberedCrossSection::giveRealStress_PlaneStress(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 3 >(); } -void -FiberedCrossSection :: giveRealStress_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 1 > +FiberedCrossSection::giveRealStress_1d(const FloatArrayF< 1 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 1 >(); } -void -FiberedCrossSection :: giveRealStress_Warping(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 2 > +FiberedCrossSection::giveRealStress_Warping(const FloatArrayF< 2 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported\n"); + return zeros< 2 >(); } -void -FiberedCrossSection :: giveStiffnessMatrix_3d(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + + +FloatArrayF< 9 > +FiberedCrossSection::giveFirstPKStress_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 9 >(); } -void -FiberedCrossSection :: giveStiffnessMatrix_PlaneStress(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatArrayF< 5 > +FiberedCrossSection::giveFirstPKStress_PlaneStrain(const FloatArrayF< 5 > &vF, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 5 >(); } -void -FiberedCrossSection :: giveStiffnessMatrix_PlaneStrain(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatArrayF< 4 > +FiberedCrossSection::giveFirstPKStress_PlaneStress(const FloatArrayF< 4 > &vF, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 4 >(); } -void -FiberedCrossSection :: giveStiffnessMatrix_1d(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatArrayF< 1 > +FiberedCrossSection::giveFirstPKStress_1d(const FloatArrayF< 1 > &vF, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 1 >(); } -void -FiberedCrossSection :: giveGeneralizedStress_Beam2d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatMatrixF< 6, 6 > +FiberedCrossSection::giveStiffnessMatrix_3d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return FloatMatrixF< 6, 6 >(); +} + + +FloatMatrixF< 3, 3 > +FiberedCrossSection::giveStiffnessMatrix_PlaneStress(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return FloatMatrixF< 3, 3 >(); +} + + +FloatMatrixF< 4, 4 > +FiberedCrossSection::giveStiffnessMatrix_PlaneStrain(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return FloatMatrixF< 4, 4 >(); +} + + +FloatMatrixF< 1, 1 > +FiberedCrossSection::giveStiffnessMatrix_1d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return FloatMatrixF< 1, 1 >(); } + + void -FiberedCrossSection :: giveGeneralizedStress_Beam3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FiberedCrossSection::giveCharMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, + MatResponseMode rMode, + GaussPoint *gp, + TimeStep *tStep) { - double fiberThick, fiberWidth, fiberZCoord, fiberYCoord; - FloatArray fiberStrain, reducedFiberStress; - StructuralElement *element = static_cast< StructuralElement * >( gp->giveElement() ); - FiberedCrossSectionInterface *interface; + OOFEM_ERROR("Not implemented."); +} - if ( ( interface = static_cast< FiberedCrossSectionInterface * >( element->giveInterface(FiberedCrossSectionInterfaceType) ) ) == NULL ) { + +FloatMatrixF< 9, 9 > +FiberedCrossSection::giveStiffnessMatrix_dPdF_3d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return FloatMatrixF< 9, 9 >(); +} + + +FloatMatrixF< 4, 4 > +FiberedCrossSection::giveStiffnessMatrix_dPdF_PlaneStress(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return FloatMatrixF< 4, 4 >(); +} + + +FloatMatrixF< 5, 5 > +FiberedCrossSection::giveStiffnessMatrix_dPdF_PlaneStrain(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return FloatMatrixF< 5, 5 >(); +} + + +FloatMatrixF< 1, 1 > +FiberedCrossSection::giveStiffnessMatrix_dPdF_1d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return FloatMatrixF< 1, 1 >(); +} + + + +FloatArrayF< 3 > +FiberedCrossSection::giveGeneralizedStress_Beam2d(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return zeros< 3 >(); +} + + +FloatArrayF< 6 > +FiberedCrossSection::giveGeneralizedStress_Beam3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const +{ + FloatArray fiberStrain; + auto element = static_cast< StructuralElement * >( gp->giveElement() ); + auto interface = static_cast< FiberedCrossSectionInterface * >( element->giveInterface(FiberedCrossSectionInterfaceType) ); + + if ( interface == nullptr ) { OOFEM_ERROR("element with no fiber support encountered"); } - answer.resize(6); - answer.zero(); + FloatArrayF< 6 >answer; - for ( int i = 1; i <= numberOfFibers; i++ ) { - GaussPoint *fiberGp = this->giveSlaveGaussPoint(gp, i - 1); - StructuralMaterial *fiberMat = static_cast< StructuralMaterial * >( domain->giveMaterial( fiberMaterials.at(i) ) ); + for ( int i = 1; i <= this->fiberMaterials.giveSize(); i++ ) { + auto fiberGp = this->giveSlaveGaussPoint(gp, i - 1); + auto fiberMat = static_cast< StructuralMaterial * >( domain->giveMaterial(fiberMaterials.at(i) ) ); // the question is whether this function should exist ? // if yes the element details will be hidden. // good idea also should be existence of element::GiveBmatrixOfLayer @@ -144,14 +231,14 @@ FiberedCrossSection :: giveGeneralizedStress_Beam3d(FloatArray &answer, GaussPoi // another approach - use several functions with assumed kinematic constraints // resolve current layer z-coordinate - fiberThick = this->fiberThicks.at(i); - fiberWidth = this->fiberWidths.at(i); - fiberYCoord = fiberGp->giveNaturalCoordinate(1); - fiberZCoord = fiberGp->giveNaturalCoordinate(2); + double fiberThick = this->fiberThicks.at(i); + double fiberWidth = this->fiberWidths.at(i); + double fiberYCoord = fiberGp->giveNaturalCoordinate(1); + double fiberZCoord = fiberGp->giveNaturalCoordinate(2); interface->FiberedCrossSectionInterface_computeStrainVectorInFiber(fiberStrain, strain, fiberGp, tStep); - fiberMat->giveRealStressVector_Fiber(reducedFiberStress, fiberGp, fiberStrain, tStep); + auto reducedFiberStress = fiberMat->giveRealStressVector_Fiber(fiberStrain, fiberGp, tStep); // perform integration // 1) membrane terms N, Qz, Qy @@ -166,69 +253,82 @@ FiberedCrossSection :: giveGeneralizedStress_Beam3d(FloatArray &answer, GaussPoi } // now we must update master gp ///@ todo simply chosen the first fiber material as master material /JB - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * > - ( domain->giveMaterial( fiberMaterials.at(1) )->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(fiberMaterials.at(1) )->giveStatus(gp) ); status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); + + return answer; } -void -FiberedCrossSection :: giveGeneralizedStress_Plate(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 5 > +FiberedCrossSection::giveGeneralizedStress_Plate(const FloatArrayF< 5 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 5 >(); } -void -FiberedCrossSection :: giveGeneralizedStress_Shell(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 8 > +FiberedCrossSection::giveGeneralizedStress_Shell(const FloatArrayF< 8 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 8 >(); } +FloatArrayF< 9 > +FiberedCrossSection::giveGeneralizedStress_ShellRot(const FloatArrayF< 9 > &strain, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return zeros< 9 >(); +} -void -FiberedCrossSection :: giveGeneralizedStress_MembraneRot(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) + +FloatArrayF< 4 > +FiberedCrossSection::giveGeneralizedStress_MembraneRot(const FloatArrayF< 4 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported in given cross-section (yet)."); + return zeros< 4 >(); } -void -FiberedCrossSection :: giveGeneralizedStress_PlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 3 > +FiberedCrossSection::giveGeneralizedStress_PlateSubSoil(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) const { - OOFEM_ERROR("Not supported in given cross-section."); + OOFEM_ERROR("Not supported in given cross-section."); + return zeros< 3 >(); } void -FiberedCrossSection :: giveCharMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, - GaussPoint *gp, - TimeStep *tStep) +FiberedCrossSection::giveCharMaterialStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, + GaussPoint *gp, + TimeStep *tStep) { MaterialMode mode = gp->giveMaterialMode(); if ( mode == _2dBeam ) { - this->give2dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->give2dBeamStiffMtrx(rMode, gp, tStep); } else if ( mode == _3dBeam ) { - this->give3dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->give3dBeamStiffMtrx(rMode, gp, tStep); } else if ( mode == _2dPlate ) { - this->give2dPlateStiffMtrx(answer, rMode, gp, tStep); + answer = this->give2dPlateStiffMtrx(rMode, gp, tStep); } else if ( mode == _3dShell ) { - this->give3dShellStiffMtrx(answer, rMode, gp, tStep); + answer = this->give3dShellStiffMtrx(rMode, gp, tStep); } else { OOFEM_ERROR("Not implemented for bulk materials."); } } -void -FiberedCrossSection :: give2dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 3, 3 > +FiberedCrossSection::give2dBeamStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not implemented"); + return FloatMatrixF< 3, 3 >(); } -void -FiberedCrossSection :: give3dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 6, 6 > +FiberedCrossSection::give3dBeamStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const // // General strain fiber vector has one of the following forms: // 1) strainVector3d {eps_x,eps_y,eps_z,gamma_yz,gamma_zx,gamma_xy} @@ -237,86 +337,85 @@ FiberedCrossSection :: give3dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode // 2) strainVectorShell {eps_x, gamma_xz, gamma_xy, \der{phi_x}{x}, kappa_y, kappa_z} // { - FloatMatrix fiberMatrix; - GaussPoint *fiberGp; - double fiberThick, fiberWidth, fiberZCoord, fiberYCoord; - double fiberZCoord2, fiberYCoord2, Ip = 0.0, A = 0.0, Ik, G = 0.0; - - // if (form != ReducedForm) error ("give3dShellMaterialStiffness : full form unsupported"); + FloatMatrixF< 6, 6 >beamStiffness; - answer.resize(6, 6); - answer.zero(); // perform integration over layers - - for ( int i = 1; i <= numberOfFibers; i++ ) { - fiberGp = giveSlaveGaussPoint(gp, i - 1); - this->giveFiberMaterialStiffnessMatrix(fiberMatrix, rMode, fiberGp, tStep); + for ( int i = 1; i <= this->fiberMaterials.giveSize(); i++ ) { + auto fiberGp = giveSlaveGaussPoint(gp, i - 1); + auto mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial(fiberMaterials.at(fiberGp->giveNumber() ) ) ); + auto fiberMatrix = mat->giveFiberStiffMtrx(rMode, fiberGp, tStep); // // resolve current layer z-coordinate // - fiberThick = this->fiberThicks.at(i); - fiberWidth = this->fiberWidths.at(i); - fiberZCoord = fiberZcoords.at(i); - fiberYCoord = fiberYcoords.at(i); - fiberYCoord2 = fiberYCoord * fiberYCoord; - fiberZCoord2 = fiberZCoord * fiberZCoord; + double fiberThick = this->fiberThicks.at(i); + double fiberWidth = this->fiberWidths.at(i); + double fiberZCoord = fiberZcoords.at(i); + double fiberYCoord = fiberYcoords.at(i); + double fiberYCoord2 = fiberYCoord * fiberYCoord; + double fiberZCoord2 = fiberZCoord * fiberZCoord; // // perform integration // // 1) membrane terms N, Qz, Qy - answer.at(1, 1) += fiberMatrix.at(1, 1) * fiberWidth * fiberThick; + beamStiffness.at(1, 1) += fiberMatrix.at(1, 1) * fiberWidth * fiberThick; - answer.at(2, 2) += fiberMatrix.at(2, 2) * fiberWidth * fiberThick; + beamStiffness.at(2, 2) += fiberMatrix.at(2, 2) * fiberWidth * fiberThick; - answer.at(3, 3) += fiberMatrix.at(3, 3) * fiberWidth * fiberThick; + beamStiffness.at(3, 3) += fiberMatrix.at(3, 3) * fiberWidth * fiberThick; // 2) bending terms mx, my, mz + // G*Ik + beamStiffness.at(4, 4) += fiberMatrix.at(2, 2) * ( fiberWidth * fiberThick * fiberZCoord2 + fiberWidth * fiberThick * fiberYCoord2 ); - Ip += fiberWidth * fiberThick * fiberZCoord2 + fiberWidth * fiberThick * fiberYCoord2; - A += fiberWidth * fiberThick; - G = fiberMatrix.at(2, 2) * fiberWidth * fiberThick; - - answer.at(5, 5) += fiberMatrix.at(1, 1) * fiberWidth * fiberThick * fiberZCoord2; - answer.at(6, 6) += fiberMatrix.at(1, 1) * fiberWidth * fiberThick * fiberYCoord2; + beamStiffness.at(5, 5) += fiberMatrix.at(1, 1) * fiberWidth * fiberThick * fiberZCoord2; + beamStiffness.at(6, 6) += fiberMatrix.at(1, 1) * fiberWidth * fiberThick * fiberYCoord2; } - ///@todo This must be wrong, it will use the last evaluated G (from the last fiber), outside the loop. FIXME! - G /= A; - Ik = A * A * A * A / ( 40.0 * Ip ); - answer.at(4, 4) = G * Ik; + return beamStiffness; } -void -FiberedCrossSection :: give2dPlateStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 5, 5 > +FiberedCrossSection::give2dPlateStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not implemented"); + return FloatMatrixF< 5, 5 >(); } -void -FiberedCrossSection :: give3dShellStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 8, 8 > +FiberedCrossSection::give3dShellStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not implemented"); + return FloatMatrixF< 8, 8 >(); } -void -FiberedCrossSection :: giveMembraneRotStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 9, 9 > +FiberedCrossSection::give3dShellRotStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not implemented"); + return FloatMatrixF< 9, 9 >(); } -void -FiberedCrossSection :: give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 4, 4 > +FiberedCrossSection::giveMembraneRotStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - OOFEM_ERROR("Not supported"); + OOFEM_ERROR("Not implemented"); + return FloatMatrixF< 4, 4 >(); +} + +FloatMatrixF< 3, 3 > +FiberedCrossSection::give2dPlateSubSoilStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return FloatMatrixF< 3, 3 >(); } FloatArray * -FiberedCrossSection :: imposeStressConstrainsOnGradient(GaussPoint *gp, - FloatArray *gradientStressVector3d) +FiberedCrossSection::imposeStressConstrainsOnGradient(GaussPoint *gp, + FloatArray *gradientStressVector3d) // // returns modified gradient of stress vector, which is used to // bring stresses back to yield surface. @@ -345,7 +444,7 @@ FiberedCrossSection :: imposeStressConstrainsOnGradient(GaussPoint *gp, break; default: - StructuralCrossSection :: imposeStressConstrainsOnGradient(gp, gradientStressVector3d); + StructuralCrossSection::imposeStressConstrainsOnGradient(gp, gradientStressVector3d); } return gradientStressVector3d; @@ -353,8 +452,8 @@ FiberedCrossSection :: imposeStressConstrainsOnGradient(GaussPoint *gp, FloatArray * -FiberedCrossSection :: imposeStrainConstrainsOnGradient(GaussPoint *gp, - FloatArray *gradientStrainVector3d) +FiberedCrossSection::imposeStrainConstrainsOnGradient(GaussPoint *gp, + FloatArray *gradientStrainVector3d) // // returns modified gradient of strain vector, which is used to // compute plastic strain increment. @@ -377,7 +476,7 @@ FiberedCrossSection :: imposeStrainConstrainsOnGradient(GaussPoint *gp, break; default: - StructuralCrossSection :: imposeStrainConstrainsOnGradient(gp, gradientStrainVector3d); + StructuralCrossSection::imposeStrainConstrainsOnGradient(gp, gradientStrainVector3d); } return gradientStrainVector3d; @@ -385,9 +484,9 @@ FiberedCrossSection :: imposeStrainConstrainsOnGradient(GaussPoint *gp, int -FiberedCrossSection :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +FiberedCrossSection::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - Material *mat = this->giveDomain()->giveMaterial( fiberMaterials.at(1) ); ///@todo For now, create material status according to the first fiber material + Material *mat = this->giveDomain()->giveMaterial(fiberMaterials.at(1) ); ///@todo For now, create material status according to the first fiber material StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) ); if ( type == IST_BeamForceMomentTensor ) { @@ -397,23 +496,22 @@ FiberedCrossSection :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalS answer = status->giveStrainVector(); return 1; } - return CrossSection :: giveIPValue(answer, gp, type, tStep); + // return CrossSection :: giveIPValue(answer, gp, type, tStep); + ///@todo so far this only works for elements where each layer has its own integration rule + int layer = gp->giveIntegrationRule()->giveNumber(); + return this->giveDomain()->giveMaterial(fiberMaterials.at(layer) )->giveIPValue(answer, gp, type, tStep); } -IRResultType -FiberedCrossSection :: initializeFrom(InputRecord *ir) -// -// instanciates receiver from input record -// +void +FiberedCrossSection::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - # ifdef VERBOSE // VERBOSE_PRINT1 ("Instanciating cross section ",this->giveNumber()) # endif - IR_GIVE_FIELD(ir, numberOfFibers, _IFT_FiberedCrossSection_nfibers); + CrossSection::initializeFrom(ir); + IR_GIVE_FIELD(ir, fiberMaterials, _IFT_FiberedCrossSection_fibermaterials); IR_GIVE_FIELD(ir, fiberThicks, _IFT_FiberedCrossSection_thicks); IR_GIVE_FIELD(ir, fiberWidths, _IFT_FiberedCrossSection_widths); @@ -425,60 +523,58 @@ FiberedCrossSection :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, thick, _IFT_FiberedCrossSection_thick); IR_GIVE_FIELD(ir, width, _IFT_FiberedCrossSection_width); - if ( numberOfFibers != fiberMaterials.giveSize() || - numberOfFibers != fiberThicks.giveSize() || - numberOfFibers != fiberWidths.giveSize() || - numberOfFibers != fiberYcoords.giveSize() || - numberOfFibers != fiberZcoords.giveSize() ) { - OOFEM_WARNING("Array size mismatch "); - return IRRT_BAD_FORMAT; + int num = fiberMaterials.giveSize(); + if ( num != fiberThicks.giveSize() || + num != fiberWidths.giveSize() || + num != fiberYcoords.giveSize() || + num != fiberZcoords.giveSize() ) { + throw ValueInputException(ir, _IFT_FiberedCrossSection_fibermaterials, "Array size mismatch "); } - if ( numberOfFibers <= 0 ) { - OOFEM_WARNING("numberOfFibers <= 0 is not allowed"); - return IRRT_BAD_FORMAT; + if ( num <= 0 ) { + throw ValueInputException(ir, _IFT_FiberedCrossSection_fibermaterials, "number of fibers == 0 is not allowed"); } - return IRRT_OK; + area = fiberThicks.dotProduct(fiberWidths); } -void FiberedCrossSection :: createMaterialStatus(GaussPoint &iGP) +void FiberedCrossSection::createMaterialStatus(GaussPoint &iGP) { - for ( int i = 1; i <= numberOfFibers; i++ ) { + for ( int i = 1; i <= fiberMaterials.giveSize(); i++ ) { GaussPoint *fiberGp = this->giveSlaveGaussPoint(& iGP, i - 1); - StructuralMaterial *mat = static_cast< StructuralMaterial * >( domain->giveMaterial( fiberMaterials.at(i) ) ); + Material *mat = domain->giveMaterial(fiberMaterials.at(i) ); MaterialStatus *matStat = mat->CreateStatus(fiberGp); iGP.setMaterialStatus(matStat); } } GaussPoint * -FiberedCrossSection :: giveSlaveGaussPoint(GaussPoint *masterGp, int i) +FiberedCrossSection::giveSlaveGaussPoint(GaussPoint *masterGp, int i) const // // return the i-th slave gauss point of master gp // if slave gp don't exists - create them // { - GaussPoint *slave = masterGp->giveSlaveGaussPoint(i); - if ( slave == NULL ) { + auto slave = masterGp->giveSlaveGaussPoint(i); + if ( !slave ) { // check for proper dimensions - slave can be NULL if index too high or if not // slaves previously defined - if ( i > this->numberOfFibers ) { + if ( i > this->fiberMaterials.giveSize() ) { OOFEM_ERROR("no such fiber defined"); } // create new slave record in masterGp // (requires that this is friend of gp) // resolve slave material mode - MaterialMode slaveMode, masterMode = masterGp->giveMaterialMode(); - slaveMode = this->giveCorrespondingSlaveMaterialMode(masterMode); + auto masterMode = masterGp->giveMaterialMode(); + auto slaveMode = this->giveCorrespondingSlaveMaterialMode(masterMode); - masterGp->gaussPoints.resize( this->numberOfFibers ); + masterGp->gaussPoints.resize(fiberMaterials.giveSize() ); - for ( int j = 0; j < numberOfFibers; j++ ) { + for ( int j = 0; j < fiberMaterials.giveSize(); j++ ) { // in gp - is stored isoparametric coordinate (-1,1) of z-coordinate masterGp->gaussPoints [ j ] = new GaussPoint(masterGp->giveIntegrationRule(), j + 1, - {fiberYcoords.at(j + 1), fiberZcoords.at(j + 1)}, 0., slaveMode); + { fiberYcoords.at(j + 1), fiberZcoords.at(j + 1) }, 0., slaveMode); } slave = masterGp->gaussPoints [ i ]; @@ -489,7 +585,7 @@ FiberedCrossSection :: giveSlaveGaussPoint(GaussPoint *masterGp, int i) void -FiberedCrossSection :: printYourself() +FiberedCrossSection::printYourself() // Prints the receiver on screen. { printf("Cross Section with properties : \n"); @@ -507,72 +603,42 @@ FiberedCrossSection :: printYourself() } -contextIOResultType -FiberedCrossSection :: saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *masterGp) -// -// saves full material context (saves state variables, that completely describe -// current state) -// stores also slaves records of master gp -// +void +FiberedCrossSection::saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *masterGp) { - contextIOResultType iores; - - if ( ( iores = CrossSection :: saveIPContext(stream, mode, masterGp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + CrossSection::saveIPContext(stream, mode, masterGp); // saved master gp record; // and now save slave gp of master: - for ( int i = 1; i <= numberOfFibers; i++ ) { + for ( int i = 1; i <= fiberMaterials.giveSize(); i++ ) { GaussPoint *slaveGP = this->giveSlaveGaussPoint(masterGp, i - 1); - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial( fiberMaterials.at(i) ) ); - if ( ( iores = mat->saveIPContext(stream, mode, slaveGP) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial(fiberMaterials.at(i) ) ); + mat->saveIPContext(stream, mode, slaveGP); } - - return CIO_OK; } -contextIOResultType -FiberedCrossSection :: restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *masterGp) -// -// restores full material context (saves state variables, that completely describe -// current state) -// -// restores also slaves of master gp -// +void +FiberedCrossSection::restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *masterGp) { - contextIOResultType iores; + CrossSection::restoreIPContext(stream, mode, masterGp); - if ( ( iores = CrossSection :: restoreIPContext(stream, mode, masterGp) ) != CIO_OK ) { - THROW_CIOERR(iores); // saved masterGp - } - - for ( int i = 1; i <= numberOfFibers; i++ ) { + for ( int i = 1; i <= fiberMaterials.giveSize(); i++ ) { // creates also slaves if they don't exists GaussPoint *slaveGP = this->giveSlaveGaussPoint(masterGp, i - 1); - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial( fiberMaterials.at(i) ) ); - if ( ( iores = mat->restoreIPContext(stream, mode, slaveGP) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial(fiberMaterials.at(i) ) ); + mat->restoreIPContext(stream, mode, slaveGP); } - - return CIO_OK; } MaterialMode -FiberedCrossSection :: giveCorrespondingSlaveMaterialMode(MaterialMode masterMode) -// -// returns corresponding slave material mode to master mode -// +FiberedCrossSection::giveCorrespondingSlaveMaterialMode(MaterialMode masterMode) { if ( masterMode == _3dBeam ) { return _Fiber; } else { - OOFEM_ERROR("unsupported mode"); + throw std::runtime_error("Unsupported mode"); } return _Unknown; @@ -580,49 +646,27 @@ FiberedCrossSection :: giveCorrespondingSlaveMaterialMode(MaterialMode masterMod double -FiberedCrossSection :: give(CrossSectionProperty aProperty, GaussPoint *gp) +FiberedCrossSection::give(CrossSectionProperty aProperty, GaussPoint *gp) const { if ( aProperty == CS_Thickness ) { return this->thick; } else if ( aProperty == CS_Width ) { return this->width; } else if ( aProperty == CS_Area ) { // not given in input - return this->giveArea(); + return this->area; } - return CrossSection :: give(aProperty, gp); + return CrossSection::give(aProperty, gp); } -double FiberedCrossSection :: giveArea() -{ - if ( this->area <= 0.0 ) { - this->area = 0.0; - for ( int i = 1; i <= numberOfFibers; i++ ) { - this->area += this->fiberThicks.at(i) * this->fiberWidths.at(i); - } - } - - return area; -} - - -void -FiberedCrossSection :: giveFiberMaterialStiffnessMatrix(FloatMatrix &fiberMatrix, - MatResponseMode rMode, GaussPoint *layerGp, - TimeStep *tStep) -{ - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial( fiberMaterials.at( layerGp->giveNumber() ) ) ); - mat->giveStiffnessMatrix(fiberMatrix, rMode, layerGp, tStep); -} - - -bool FiberedCrossSection :: isCharacteristicMtrxSymmetric(MatResponseMode rMode) +bool +FiberedCrossSection::isCharacteristicMtrxSymmetric(MatResponseMode rMode) const { ///@todo As far as I can see, it only uses diagonal components for the 3dbeam, but there is no way to check here. - for ( int i = 1; i <= this->numberOfFibers; i++ ) { - if ( !this->domain->giveMaterial( this->fiberMaterials.at(i) )->isCharacteristicMtrxSymmetric(rMode) ) { + for ( int imat : this->fiberMaterials ) { + if ( !this->domain->giveMaterial(imat)->isCharacteristicMtrxSymmetric(rMode) ) { return false; } } @@ -631,22 +675,37 @@ bool FiberedCrossSection :: isCharacteristicMtrxSymmetric(MatResponseMode rMode) int -FiberedCrossSection :: checkConsistency() -// -// check internal consistency -// mainly tests, whether material and crossSection data -// are safe for conversion to "Structural" versions -// +FiberedCrossSection::checkConsistency() { int result = 1; for ( int i = 1; this->fiberMaterials.giveSize(); i++ ) { - Material *mat = this->giveDomain()->giveMaterial( this->fiberMaterials.at(i) ); - if ( !dynamic_cast< StructuralMaterial * >(mat) ) { - OOFEM_WARNING("material %s without structural support", mat->giveClassName() ); + Material *mat = this->giveDomain()->giveMaterial(this->fiberMaterials.at(i) ); + if ( !dynamic_cast< StructuralMaterial * >( mat ) ) { + OOFEM_WARNING( "material %s without structural support", mat->giveClassName() ); result = 0; continue; } } return result; } + +Material * +FiberedCrossSection::giveMaterial(IntegrationPoint *ip) const +{ + ///@todo We should keep track in integration point (integration rule) what material from layer is assigned. Otherwise difficulties due to different elements and IP numbering. + if ( ip->giveIntegrationRule()->giveIntegrationDomain() == _Cube || + ip->giveIntegrationRule()->giveIntegrationDomain() == _Wedge + ) { + return domain->giveMaterial(fiberMaterials.at(1) ); + //return this->domain->giveMaterial( this->giveLayerMaterial(ip->giveNumber()) ); + } + + if ( ip->hasSlaveGaussPoint() ) { + return domain->giveMaterial(fiberMaterials.at(1) ); //virtual master, has no material assigned in input file + } else { + return domain->giveMaterial(fiberMaterials.at(1) ); //virtual master, has no material assigned in input file + //OOFEM_ERROR("Not implemented.") + } + return nullptr; +} } // end namespace oofem diff --git a/src/sm/CrossSections/fiberedcs.h b/src/sm/CrossSections/fiberedcs.h index 9421fa1aa..39a1b2624 100644 --- a/src/sm/CrossSections/fiberedcs.h +++ b/src/sm/CrossSections/fiberedcs.h @@ -35,8 +35,8 @@ #ifndef fiberedcs_h #define fiberedcs_h -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralmaterial.h" #include "element.h" #include "dictionary.h" #include "floatarray.h" @@ -92,126 +92,116 @@ class FiberedCrossSection : public StructuralCrossSection IntArray fiberMaterials; ///< Material of each fiber. FloatArray fiberThicks; ///< Thickness for each fiber. FloatArray fiberWidths; ///< Width for each fiber. - int numberOfFibers; ///< Number of fibers. - double thick; ///< Total thickness. - double width; ///< Total width. - double area; ///< Total area. + int numberOfFibers = 0; ///< Number of fibers. + double thick = 0.; ///< Total thickness. + double width = 0.; ///< Total width. + double area = 0.; ///< Total area. FloatArray fiberYcoords, fiberZcoords; public: - FiberedCrossSection(int n, Domain * d) : StructuralCrossSection(n, d), fiberMaterials(), fiberThicks(), fiberWidths(), - fiberYcoords(), fiberZcoords() - { - thick = 0.; - width = 0.; - area = -1.0; - } - - virtual ~FiberedCrossSection() { } - - virtual void giveRealStress_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_Warping(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - - virtual void giveStiffnessMatrix_3d(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveStiffnessMatrix_PlaneStress(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveStiffnessMatrix_PlaneStrain(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveStiffnessMatrix_1d(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - - - virtual void giveGeneralizedStress_Beam2d(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_Beam3d(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_Plate(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_Shell(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_MembraneRot(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_PlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - - virtual void giveCharMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - - virtual void give2dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give2dPlateStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dShellStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveMembraneRotStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode mode); - virtual double give(int aProperty, GaussPoint *gp) + FiberedCrossSection(int n, Domain *d) : StructuralCrossSection(n, d) + { } + + FloatArrayF< 6 >giveRealStress_3d(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 4 >giveRealStress_PlaneStrain(const FloatArrayF< 4 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 3 >giveRealStress_PlaneStress(const FloatArrayF< 3 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 1 >giveRealStress_1d(const FloatArrayF< 1 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 2 >giveRealStress_Warping(const FloatArrayF< 2 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + + + FloatMatrixF< 6, 6 >giveStiffnessMatrix_3d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 3, 3 >giveStiffnessMatrix_PlaneStress(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 4, 4 >giveStiffnessMatrix_PlaneStrain(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 1, 1 >giveStiffnessMatrix_1d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatArrayF< 3 >giveGeneralizedStress_Beam2d(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 6 >giveGeneralizedStress_Beam3d(const FloatArrayF< 6 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 5 >giveGeneralizedStress_Plate(const FloatArrayF< 5 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 8 >giveGeneralizedStress_Shell(const FloatArrayF< 8 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 9 >giveGeneralizedStress_ShellRot(const FloatArrayF< 9 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 4 >giveGeneralizedStress_MembraneRot(const FloatArrayF< 4 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 3 >giveGeneralizedStress_PlateSubSoil(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + + void giveCharMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + + FloatMatrixF< 3, 3 >give2dBeamStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 6, 6 >give3dBeamStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 5, 5 >give2dPlateStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 8, 8 >give3dShellStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 9, 9 >give3dShellRotStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 4, 4 >giveMembraneRotStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 3, 3 >give2dPlateSubSoilStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + bool isCharacteristicMtrxSymmetric(MatResponseMode mode) const override; + double give(int aProperty, GaussPoint *gp) const override { OOFEM_ERROR("not implemented yet"); return 0.0; - }; - virtual FloatArray *imposeStressConstrainsOnGradient(GaussPoint *gp, FloatArray *gradientStressVector3d); - virtual FloatArray *imposeStrainConstrainsOnGradient(GaussPoint *gp, FloatArray *gradientStrainVector3d); - - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + } + FloatArray *imposeStressConstrainsOnGradient(GaussPoint *gp, FloatArray *gradientStressVector3d) override; + FloatArray *imposeStrainConstrainsOnGradient(GaussPoint *gp, FloatArray *gradientStrainVector3d) override; - /** - * Method for computing 1d fiber stiffness matrix of receiver. - * Default implementation computes 3d stiffness matrix using give3dMaterialStiffnessMatrix and - * reduces it to 1d fiber stiffness using reduce method described above. - * However, this reduction is quite time consuming and if it is possible, - * it is recommended to overload this method and provide direct method for computing - * particular stiffness matrix. - * @param fiberMatrix Stiffness matrix. - * @param mode Material response mode. - * @param layerGp Integration point. - * @param tStep Time step (most models are able to respond only when tStep is current time step). - */ - void giveFiberMaterialStiffnessMatrix(FloatMatrix &fiberMatrix, MatResponseMode mode, GaussPoint *layerGp, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual double give(CrossSectionProperty a, GaussPoint *gp); + double give(CrossSectionProperty a, GaussPoint *gp) const override; // identification and auxiliary functions - virtual const char *giveInputRecordName() const { return _IFT_FiberedCrossSection_Name; } - virtual const char *giveClassName() const { return "FiberedCrossSection"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_FiberedCrossSection_Name; } + const char *giveClassName() const override { return "FiberedCrossSection"; } + void initializeFrom(InputRecord &ir) override; - virtual void createMaterialStatus(GaussPoint &iGP); // ES + void createMaterialStatus(GaussPoint &iGP) override; // ES - virtual void printYourself(); + void printYourself() override; double computeIntegralThickWidth(); - MaterialMode giveCorrespondingSlaveMaterialMode(MaterialMode); - GaussPoint *giveSlaveGaussPoint(GaussPoint *gp, int); + static MaterialMode giveCorrespondingSlaveMaterialMode(MaterialMode); + GaussPoint *giveSlaveGaussPoint(GaussPoint *gp, int) const; - virtual contextIOResultType saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); - virtual contextIOResultType restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); + void saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override; + void restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override; - virtual int checkConsistency(); + int checkConsistency() override; - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override { OOFEM_ERROR("not implemented"); return 0; } - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override { OOFEM_ERROR("not implemented"); return 0; } - virtual int estimatePackSize(DataStream &buff, GaussPoint *ip) + int estimatePackSize(DataStream &buff, GaussPoint *ip) override { OOFEM_ERROR("not implemented"); return 0; } - virtual void giveFirstPKStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedFIncrement, TimeStep *tStep) - { OOFEM_ERROR("not implemented"); } - virtual void giveCauchyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedFIncrement, TimeStep *tStep) - { OOFEM_ERROR("not implemented"); } - virtual void giveStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + FloatArrayF< 9 >giveFirstPKStress_3d(const FloatArrayF< 9 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 5 >giveFirstPKStress_PlaneStrain(const FloatArrayF< 5 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 4 >giveFirstPKStress_PlaneStress(const FloatArrayF< 4 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 1 >giveFirstPKStress_1d(const FloatArrayF< 1 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override; + + + + void giveCharMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + FloatMatrixF< 9, 9 >giveStiffnessMatrix_dPdF_3d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 5, 5 >giveStiffnessMatrix_dPdF_PlaneStrain(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 4, 4 >giveStiffnessMatrix_dPdF_PlaneStress(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 1, 1 >giveStiffnessMatrix_dPdF_1d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + + + void giveCauchyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedFIncrement, TimeStep *tStep) override { OOFEM_ERROR("not implemented"); } - virtual void giveStiffnessMatrix_dCde(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + void giveStiffnessMatrix_dCde(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("not implemented"); } - -protected: - double giveArea(); + Material *giveMaterial(IntegrationPoint *ip) const override; }; /** diff --git a/src/sm/CrossSections/latticecrosssection.C b/src/sm/CrossSections/latticecrosssection.C new file mode 100644 index 000000000..0d7b2863f --- /dev/null +++ b/src/sm/CrossSections/latticecrosssection.C @@ -0,0 +1,224 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "latticecrosssection.h" +#include "sm/Materials/LatticeMaterials/latticematstatus.h" +#include "sm/Materials/LatticeMaterials/latticestructuralmaterial.h" +#include "dynamicinputrecord.h" +#include "datastream.h" +#include "contextioerr.h" +#include "gausspoint.h" +#include "element.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" + +namespace oofem { +REGISTER_CrossSection(LatticeCrossSection); + +LatticeStructuralMaterial * +LatticeCrossSection::giveLatticeMaterial() const +{ + return static_cast< LatticeStructuralMaterial * >( this->giveDomain()->giveMaterial(this->materialNum) ); +} + +int +LatticeCrossSection::checkConsistency() +{ + // Checks if the given cross section material is a 'LatticeStructuralMaterial' + Material *mat = this->giveDomain()->giveMaterial(this->materialNum); + if ( !dynamic_cast< LatticeStructuralMaterial * >( mat ) ) { + OOFEM_WARNING("material %s is not a structural interface material", mat->giveClassName() ); + return 0; + } + + return 1; +} + +void +LatticeCrossSection::initializeFrom(InputRecord &ir) +{ + CrossSection::initializeFrom(ir); + + double value; + + IR_GIVE_FIELD(ir, this->materialNum, _IFT_LatticeCrossSection_Material); + + this->materialNumber = 0; + IR_GIVE_OPTIONAL_FIELD(ir, this->materialNumber, _IFT_LatticeCrossSection_MaterialNumber); + + double area = 0.0; + IR_GIVE_OPTIONAL_FIELD(ir, area, _IFT_LatticeCrossSection_area); + propertyDictionary.add(CS_Area, area); + + value = 0.0; + IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_LatticeCrossSection_iy); + propertyDictionary.add(CS_InertiaMomentY, value); + + value = 0.0; + IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_LatticeCrossSection_iz); + propertyDictionary.add(CS_InertiaMomentZ, value); + + value = 0.0; + IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_LatticeCrossSection_ik); + propertyDictionary.add(CS_TorsionConstantX, value); + + double beamshearcoeff = 0.0; + IR_GIVE_OPTIONAL_FIELD(ir, beamshearcoeff, _IFT_LatticeCrossSection_shearcoeff); + propertyDictionary.add(CS_BeamShearCoeff, beamshearcoeff); + + value = 0.0; + IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_LatticeCrossSection_shearareay); + if ( value == 0.0 ) { + value = beamshearcoeff * area; + } + propertyDictionary.add(CS_ShearAreaY, value); + + value = 0.0; + IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_LatticeCrossSection_shearareaz); + if ( value == 0.0 ) { + value = beamshearcoeff * area; + } + propertyDictionary.add(CS_ShearAreaZ, value); +} + +double LatticeCrossSection::giveLatticeStress1d(double strain, GaussPoint *gp, TimeStep *tStep) const +{ + return this->giveLatticeMaterial()->giveLatticeStress1d(strain, gp, tStep); +} + +FloatArrayF< 3 >LatticeCrossSection::giveLatticeStress2d(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) const +{ + return this->giveLatticeMaterial()->giveLatticeStress2d(strain, gp, tStep); +} + +FloatArrayF< 6 >LatticeCrossSection::giveLatticeStress3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const +{ + return this->giveLatticeMaterial()->giveLatticeStress3d(strain, gp, tStep); +} + +FloatArrayF< 6 >LatticeCrossSection::giveFrameForces3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const +{ + // Get the forces divided by the sectional properties from material + return this->giveLatticeMaterial()->giveFrameForces3d(strain, gp, tStep); +} + + + +FloatMatrixF< 1, 1 > +LatticeCrossSection::give1dStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + LatticeStructuralMaterial *mat = this->giveLatticeMaterial(); + if ( mat->hasAnalyticalTangentStiffness() ) { + return mat->give1dLatticeStiffnessMatrix(rMode, gp, tStep); + } else { + OOFEM_ERROR("not implemented"); + } +} + +FloatMatrixF< 3, 3 > +LatticeCrossSection::give2dStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + LatticeStructuralMaterial *mat = this->giveLatticeMaterial(); + if ( mat->hasAnalyticalTangentStiffness() ) { + return mat->give2dLatticeStiffnessMatrix(rMode, gp, tStep); + } else { + OOFEM_ERROR("not implemented"); + } +} + +FloatMatrixF< 6, 6 > +LatticeCrossSection::give3dStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + LatticeStructuralMaterial *mat = this->giveLatticeMaterial(); + if ( mat->hasAnalyticalTangentStiffness() ) { + return mat->give3dLatticeStiffnessMatrix(rMode, gp, tStep); + } else { + OOFEM_ERROR("not implemented"); + } +} + +FloatMatrixF< 6, 6 > +LatticeCrossSection::give3dFrameStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + LatticeStructuralMaterial *mat = this->giveLatticeMaterial(); + return mat->give3dFrameStiffnessMatrix(rMode, gp, tStep); +} + + +int +LatticeCrossSection::giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep) +{ + if ( type == IST_CrossSectionNumber ) { + answer.resize(1); + answer.at(1) = this->giveNumber(); + return 1; + } + return this->giveLatticeMaterial()->giveIPValue(answer, ip, type, tStep); +} + +double +LatticeCrossSection::give(int aProperty, GaussPoint *gp) const +{ + return this->giveMaterial(gp)->give(aProperty, gp); +} + +Material *LatticeCrossSection::giveMaterial(IntegrationPoint *ip) const +{ + if ( this->giveMaterialNumber() ) { + return this->giveDomain()->giveMaterial(this->giveMaterialNumber() ); + } else { + return ip->giveElement()->giveMaterial(); + } +} + + +int +LatticeCrossSection::packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) +{ + return this->giveLatticeMaterial()->packUnknowns(buff, tStep, gp); +} + +int +LatticeCrossSection::unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) +{ + return this->giveLatticeMaterial()->unpackAndUpdateUnknowns(buff, tStep, gp); +} + +int +LatticeCrossSection::estimatePackSize(DataStream &buff, GaussPoint *gp) +{ + return this->giveLatticeMaterial()->estimatePackSize(buff, gp); +} +} // end namespace oofem diff --git a/src/sm/CrossSections/latticecrosssection.h b/src/sm/CrossSections/latticecrosssection.h new file mode 100644 index 000000000..e5b235aec --- /dev/null +++ b/src/sm/CrossSections/latticecrosssection.h @@ -0,0 +1,162 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef latticecrosssection_h +#define latticecrosssection_h + +#include "sm/Materials/LatticeMaterials/latticestructuralmaterial.h" +#include "crosssection.h" +#include "classfactory.h" + +///@name Input fields for LatticeCrossSection +//@{ +#define _IFT_LatticeCrossSection_Name "latticecs" +#define _IFT_LatticeCrossSection_Material "material" +#define _IFT_LatticeCrossSection_area "area" +#define _IFT_LatticeCrossSection_MaterialNumber "material" +#define _IFT_LatticeCrossSection_iy "iy" +#define _IFT_LatticeCrossSection_iz "iz" +#define _IFT_LatticeCrossSection_ik "ik" +#define _IFT_LatticeCrossSection_shearcoeff "shearcoeff" +#define _IFT_LatticeCrossSection_shearareay "shearareay" +#define _IFT_LatticeCrossSection_shearareaz "shearareaz" + +//@} + +namespace oofem { +class GaussPoint; +class Element; +class FloatArray; +class FloatMatrix; +typedef GaussPoint IntegrationPoint; + +/** + * Base class for all structural lattice cross section models. + * Keeps track of the lattice material, the geometric thickness (for 2d elements) + * + */ +class LatticeCrossSection : public CrossSection +{ +protected: + int materialNumber = 0; ///< Material number + double area = 0.; + double iy = 0.; + double iz = 0.; + double ik = 0.; + double beamshearcoeff = 0.; + double shearareay = 0.; + double shearareaz = 0.; + + +public: + /** + * Constructor. Creates cross section with given number, belonging to given domain. + * @param n Cross section number. + * @param d Domain to which new cross section will belong. + */ + LatticeCrossSection(int n, Domain *d) : CrossSection(n, d) + { + materialNum = 0; + crossSectionType = CS_LatticeStructuralCapability; + } + /// Destructor. + virtual ~LatticeCrossSection() { } + + void initializeFrom(InputRecord &ir) override; + + int testCrossSectionExtension(CrossSectExtension ext) override { return this->crossSectionType; } + + /** + * Computes the real stress vector for given strain and integration point. + * The service should use previously reached equilibrium history variables. Also + * it should update temporary history variables in status according to newly reached state. + * The temporary history variables are moved into equilibrium ones after global structure + * equilibrium has been reached by iteration process. + * Elements should always pass their requests to their cross section model, which + * performs necessary integration over its volume and invokes necessary material + * services for corresponding material model defined for given integration point. + * @param answer Contains result. + * @param gp Integration point. + * @param reduthiscedF Deformation gradient in reduced form. + * @param tStep Current time step (most models are able to respond only when tStep is current time step). + */ + //@{ + // Pass all calls to the material + + double giveLatticeStress1d(double strain, GaussPoint *gp, TimeStep *tStep) const; + + FloatArrayF< 3 >giveLatticeStress2d(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) const; + + FloatArrayF< 6 >giveLatticeStress3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const; + + FloatArrayF< 6 >giveFrameForces3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const; + + FloatMatrixF< 1, 1 >give1dStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + + FloatMatrixF< 3, 3 >give2dStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + + FloatMatrixF< 6, 6 >give3dStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + + FloatMatrixF< 6, 6 >give3dFrameStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + //@} + + LatticeStructuralMaterial *giveLatticeMaterial() const; + + int checkConsistency() override; + + int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep) override; + + Material *giveMaterial(IntegrationPoint *ip) const override; + int giveMaterialNumber() const { return this->materialNum; } + void setMaterialNumber(int matNum) { this->materialNum = matNum; } + + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) override; + int estimatePackSize(DataStream &buff, GaussPoint *gp) override; + + // identification and auxiliary functions + const char *giveClassName() const override { return "LatticeCrossSection"; } + const char *giveInputRecordName() const override { return _IFT_LatticeCrossSection_Name; } + + virtual double give(int aProperty, GaussPoint *gp) const override; + + // void giveCharMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + + + CrossSectExtension crossSectionType; +private: + int materialNum; +}; +} // end namespace oofem +#endif // structuralcrosssection_h diff --git a/src/sm/CrossSections/layeredcrosssection.C b/src/sm/CrossSections/layeredcrosssection.C index 93558e43c..3e2ece540 100644 --- a/src/sm/CrossSections/layeredcrosssection.C +++ b/src/sm/CrossSections/layeredcrosssection.C @@ -32,13 +32,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/CrossSections/layeredcrosssection.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/CrossSections/layeredcrosssection.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "gausspoint.h" #include "material.h" #include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "contextioerr.h" #include "gaussintegrationrule.h" #include "mathfem.h" @@ -46,13 +48,14 @@ #include "lobattoir.h" #include "dynamicinputrecord.h" #include "cltypes.h" +#include "simplecrosssection.h" namespace oofem { REGISTER_CrossSection(LayeredCrossSection); -void -LayeredCrossSection :: giveRealStress_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 6 > +LayeredCrossSection::giveRealStress_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const { if ( gp->giveIntegrationRule()->giveIntegrationDomain() == _Cube || gp->giveIntegrationRule()->giveIntegrationDomain() == _Wedge ) { // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints) @@ -60,308 +63,322 @@ LayeredCrossSection :: giveRealStress_3d(FloatArray &answer, GaussPoint *gp, con int gpnum = gp->giveNumber(); int gpsperlayer = ngps / this->numberOfLayers; int layer = ( gpnum - 1 ) / gpsperlayer + 1; - Material *layerMat = this->domain->giveMaterial( this->giveLayerMaterial(layer) ); + auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) ); if ( this->layerRots.at(layer) != 0. ) { double rot = this->layerRots.at(layer); double c = cos(rot * M_PI / 180.); double s = sin(rot * M_PI / 180.); - FloatArray rotStress; - FloatArray rotStrain(6); - rotStrain.at(1) = c * c * strain.at(1) - c *s *strain.at(6) + s *s *strain.at(2); - rotStrain.at(2) = c * c * strain.at(2) + c *s *strain.at(6) + s *s *strain.at(1); - rotStrain.at(3) = strain.at(3); - rotStrain.at(4) = c * strain.at(4) + s *strain.at(5); - rotStrain.at(5) = c * strain.at(5) - s *strain.at(4); - rotStrain.at(6) = ( c * c - s * s ) * strain.at(6) + 2 * c * s * ( strain.at(1) - strain.at(2) ); + FloatArrayF< 6 >rotStrain = { + c *c *strain.at(1) - c * s * strain.at(6) + s * s * strain.at(2), + c *c *strain.at(2) + c * s * strain.at(6) + s * s * strain.at(1), + strain.at(3), + c *strain.at(4) + s * strain.at(5), + c *strain.at(5) - s * strain.at(4), + ( c * c - s * s ) * strain.at(6) + 2 * c * s * ( strain.at(1) - strain.at(2) ), + }; - static_cast< StructuralMaterial * >(layerMat)->giveRealStressVector_3d(rotStress, gp, rotStrain, tStep); + auto rotStress = static_cast< StructuralMaterial * >( layerMat )->giveRealStressVector_3d(rotStrain, gp, tStep); - answer = { - c *c * rotStress.at(1) + 2 * c * s * rotStress.at(6) + s * s * rotStress.at(2), - c * c * rotStress.at(2) - 2 * c * s * rotStress.at(6) + s * s * rotStress.at(1), + return { + c *c *rotStress.at(1) + 2 * c * s * rotStress.at(6) + s * s * rotStress.at(2), + c *c *rotStress.at(2) - 2 * c * s * rotStress.at(6) + s * s * rotStress.at(1), rotStress.at(3), - c * rotStress.at(4) - s * rotStress.at(5), - c * rotStress.at(5) + s * rotStress.at(4), + c *rotStress.at(4) - s * rotStress.at(5), + c *rotStress.at(5) + s * rotStress.at(4), ( c * c - s * s ) * rotStress.at(6) - c * s * ( rotStress.at(1) - rotStress.at(2) ), }; } else { - static_cast< StructuralMaterial * >(layerMat)->giveRealStressVector_3d(answer, gp, strain, tStep); + return static_cast< StructuralMaterial * >( layerMat )->giveRealStressVector_3d(strain, gp, tStep); } } else { OOFEM_ERROR("Only cubes and wedges are meaningful for layered cross-sections"); + return zeros< 6 >(); } } -void -LayeredCrossSection :: giveRealStress_3dDegeneratedShell(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) + +FloatArrayF< 6 > +LayeredCrossSection::giveRealStress_3dDegeneratedShell(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { ///@todo - check-V - answer.resize(6); - answer.zero(); + return zeros< 6 >(); } - -void -LayeredCrossSection :: giveRealStress_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 4 > +LayeredCrossSection::giveRealStress_PlaneStrain(const FloatArrayF< 4 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 4 >(); } -void -LayeredCrossSection :: giveRealStress_PlaneStress(FloatArray &answer, GaussPoint *masterGp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 3 > +LayeredCrossSection::giveRealStress_PlaneStress(const FloatArrayF< 3 > &strain, GaussPoint *masterGp, TimeStep *tStep) const { //strain eps_x, eps_y, gamma_xy //stress sig_x, sig_y, tau_xy //answer n_x, n_y, n_xy - - answer.resize(3); - answer.zero(); - - double layerThick, layerZCoord, top, bottom, layerZeta; - FloatArray layerStrain, reducedLayerStress; - - bottom = this->give(CS_BottomZCoord, masterGp); - top = this->give(CS_TopZCoord, masterGp); - - StructuralElement *element = dynamic_cast< StructuralElement * >( masterGp->giveElement() ); - - + + FloatArray layerStrain; + + //double bottom = this->give(CS_BottomZCoord, masterGp); + //double top = this->give(CS_TopZCoord, masterGp); + + auto element = dynamic_cast< StructuralElement * >( masterGp->giveElement() ); + double totThick = 0.0; + + FloatArrayF< 3 >answer; for ( int layer = 1; layer <= numberOfLayers; layer++ ) { - GaussPoint *layerGp = this->giveSlaveGaussPoint(masterGp, layer - 1); - Material *layerMat = this->domain->giveMaterial( this->giveLayerMaterial(layer) ); - LayeredCrossSectionInterface *interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) ); - - // resolve current layer z-coordinate - layerThick = this->layerThicks.at(layer); - layerZeta = layerGp->giveNaturalCoordinate(3); - layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); - - // Compute the layer stress - interface->computeStrainVectorInLayer(layerStrain, strain, masterGp, layerGp, tStep); - dynamic_cast< StructuralMaterial * >(layerMat)->giveRealStressVector_PlaneStress(reducedLayerStress, layerGp, layerStrain, tStep); - answer.at(1) += reducedLayerStress.at(1) * layerThick; - answer.at(2) += reducedLayerStress.at(2) * layerThick * layerZCoord; - answer.at(3) += reducedLayerStress.at(3) * layerThick * ( 5. / 6. ); + for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) { + auto layerGp = this->giveSlaveGaussPoint(masterGp, layer - 1, igp); + auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) ); + auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) ); + auto lgpw = layerGp->giveWeight(); + + // resolve current layer z-coordinate + double layerThick = this->layerThicks.at(layer); + totThick += layerThick * lgpw; + //double layerZeta = layerGp->giveNaturalCoordinate(3); + //double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); + + // Compute the layer stress + interface->computeStrainVectorInLayer(layerStrain, strain, masterGp, layerGp, tStep); + auto reducedLayerStress = dynamic_cast< StructuralMaterial * >( layerMat )->giveRealStressVector_PlaneStress(layerStrain, layerGp, tStep); + answer.at(1) += reducedLayerStress.at(1) * layerThick * lgpw; + answer.at(2) += reducedLayerStress.at(2) * layerThick * lgpw; + answer.at(3) += reducedLayerStress.at(3) * layerThick * lgpw; // * ( 5. / 6. ); + } } - - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * > - ( domain->giveMaterial( layerMaterials.at(1) )->giveStatus(masterGp) ); + answer *= ( 1. / totThick ); + auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(masterGp) ); status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); + + return answer; } -void -LayeredCrossSection :: giveRealStress_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 1 > +LayeredCrossSection::giveRealStress_1d(const FloatArrayF< 1 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 1 >(); } -void -LayeredCrossSection :: giveRealStress_Warping(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 2 > +LayeredCrossSection::giveRealStress_Warping(const FloatArrayF< 2 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 2 >(); } -void -LayeredCrossSection :: giveStiffnessMatrix_3d(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 6, 6 > +LayeredCrossSection::giveStiffnessMatrix_3d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - if ( gp->giveIntegrationRule()->giveIntegrationDomain() == _Cube || gp->giveIntegrationRule()->giveIntegrationDomain() == _Wedge ) { - // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints) - int ngps = gp->giveIntegrationRule()->giveNumberOfIntegrationPoints(); - int gpnum = gp->giveNumber(); - int gpsperlayer = ngps / this->numberOfLayers; - int layer = ( gpnum - 1 ) / gpsperlayer + 1; - Material *layerMat = this->domain->giveMaterial( this->giveLayerMaterial(layer) ); - static_cast< StructuralMaterial * >(layerMat)->give3dMaterialStiffnessMatrix(answer, rMode, gp, tStep); - - if ( this->layerRots.at(layer) != 0. ) { - double rot = this->layerRots.at(layer); - double c = cos(rot * M_PI / 180.); - double s = sin(rot * M_PI / 180.); - - FloatMatrix rotTangent = { - { c *c, s *s, 0, 0, 0, -c *s }, - { s *s, c *c, 0, 0, 0, c *s }, - { 0, 0, 1, 0, 0, 0 }, - { 0, 0, 0, c, s, 0 }, - { 0, 0, 0, -s, c, 0 }, - { 2 * c * s, -2 * c * s, 0, 0, 0, c * c - s * s } - }; - answer.rotatedWith(rotTangent, 't'); - } - } else { + if ( gp->giveIntegrationRule()->giveIntegrationDomain() != _Cube && gp->giveIntegrationRule()->giveIntegrationDomain() != _Wedge ) { OOFEM_ERROR("Only cubes and wedges are meaningful for layered cross-sections"); } + // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints) + int ngps = gp->giveIntegrationRule()->giveNumberOfIntegrationPoints(); + int gpnum = gp->giveNumber(); + int gpsperlayer = ngps / this->numberOfLayers; + int layer = ( gpnum - 1 ) / gpsperlayer + 1; + auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) ); + auto tangent = static_cast< StructuralMaterial * >( layerMat )->give3dMaterialStiffnessMatrix(rMode, gp, tStep); + + if ( this->layerRots.at(layer) != 0. ) { + double rot = this->layerRots.at(layer); + double c = cos(rot * M_PI / 180.); + double s = sin(rot * M_PI / 180.); + + FloatMatrixF< 6, 6 >rotTangent = { + c *c, s *s, 0., 0., 0., -c * s, + s *s, c *c, 0., 0., 0., c *s, + 0., 0., 1., 0., 0., 0., + 0., 0., 0., c, s, 0., + 0., 0., 0., -s, c, 0., + 2 * c * s, -2 * c * s, 0., 0., 0., c *c - s * s, + }; + + return unrotate(tangent, rotTangent); + } else { + return tangent; + } } -void -LayeredCrossSection :: giveStiffnessMatrix_PlaneStress(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *masterGp, TimeStep *tStep) +FloatMatrixF< 3, 3 > +LayeredCrossSection::giveStiffnessMatrix_PlaneStress(MatResponseMode rMode, GaussPoint *masterGp, TimeStep *tStep) const { - answer.resize(3,3); - answer.zero(); + FloatMatrixF< 3, 3 >answer; double totThick = 0.; - + //Average stiffness over all layers for ( int layer = 1; layer <= numberOfLayers; layer++ ) { - FloatMatrix subAnswer; - GaussPoint *slaveGP = this->giveSlaveGaussPoint(masterGp, layer - 1); - Material *layerMat = this->domain->giveMaterial( this->giveLayerMaterial(layer) ); - double layerThick = this->layerThicks.at(layer); - totThick += layerThick; - dynamic_cast< StructuralMaterial * >(layerMat)->givePlaneStressStiffMtrx(subAnswer, rMode, slaveGP, tStep); - subAnswer.times(layerThick); - answer.add(subAnswer); + for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) { + auto slaveGP = this->giveSlaveGaussPoint(masterGp, layer - 1, igp); + auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) ); + auto sgpw = slaveGP->giveWeight(); + double layerThick = this->layerThicks.at(layer); + totThick += layerThick * sgpw; + auto subAnswer = dynamic_cast< StructuralMaterial * >( layerMat )->givePlaneStressStiffMtrx(rMode, slaveGP, tStep); + answer += layerThick * sgpw * subAnswer; + } } - answer.times(1./totThick); + //answer.at(3,3) *= (5./6.); + return answer * ( 1. / totThick ); } -void -LayeredCrossSection :: giveStiffnessMatrix_PlaneStrain(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 4, 4 > +LayeredCrossSection::giveStiffnessMatrix_PlaneStrain(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return FloatMatrixF< 4, 4 >(); } -void -LayeredCrossSection :: giveStiffnessMatrix_1d(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 1, 1 > +LayeredCrossSection::giveStiffnessMatrix_1d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return FloatMatrixF< 1, 1 >(); } -void -LayeredCrossSection :: giveGeneralizedStress_Beam2d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 3 > +LayeredCrossSection::giveGeneralizedStress_Beam2d(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) const { - double layerThick, layerWidth, layerZCoord, top, bottom, layerZeta; - FloatArray layerStrain, reducedLayerStress; - StructuralElement *element = static_cast< StructuralElement * >( gp->giveElement() ); - LayeredCrossSectionInterface *interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) ); + FloatArray layerStrain; + auto element = static_cast< StructuralElement * >( gp->giveElement() ); + auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) ); - answer.resize(3); - answer.zero(); // perform integration over layers - bottom = this->give(CS_BottomZCoord, gp); - top = this->give(CS_TopZCoord, gp); + double bottom = this->give(CS_BottomZCoord, gp); + double top = this->give(CS_TopZCoord, gp); - if ( interface == NULL ) { + if ( interface == nullptr ) { OOFEM_ERROR("element with no layer support encountered"); } + FloatArrayF< 3 >answer; for ( int layer = 1; layer <= numberOfLayers; layer++ ) { - GaussPoint *layerGp = this->giveSlaveGaussPoint(gp, layer - 1); - StructuralMaterial *layerMat = static_cast< StructuralMaterial * >( domain->giveMaterial( layerMaterials.at(layer) ) ); - - // resolve current layer z-coordinate - layerThick = this->layerThicks.at(layer); - layerWidth = this->layerWidths.at(layer); - layerZeta = layerGp->giveNaturalCoordinate(3); - layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); - - // Compute the layer stress - interface->computeStrainVectorInLayer(layerStrain, strain, gp, layerGp, tStep); + for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) { + auto layerGp = this->giveSlaveGaussPoint(gp, layer - 1, igp); + auto layerMat = static_cast< StructuralMaterial * >( domain->giveMaterial(layerMaterials.at(layer) ) ); + auto lgpw = layerGp->giveWeight(); + + // resolve current layer z-coordinate + double layerThick = this->layerThicks.at(layer); + double layerWidth = this->layerWidths.at(layer); + double layerZeta = layerGp->giveNaturalCoordinate(3); + double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); + + // Compute the layer stress + interface->computeStrainVectorInLayer(layerStrain, strain, gp, layerGp, tStep); + + FloatArrayF< 2 >reducedLayerStress; + if ( this->layerRots.at(layer) != 0. ) { + OOFEM_ERROR("Rotation not supported for beams"); + } else { + reducedLayerStress = layerMat->giveRealStressVector_2dBeamLayer(layerStrain, layerGp, tStep); + } - if ( this->layerRots.at(layer) != 0. ) { - OOFEM_ERROR("Rotation not supported for beams"); - } else { - layerMat->giveRealStressVector_2dBeamLayer(reducedLayerStress, layerGp, layerStrain, tStep); + answer.at(1) += reducedLayerStress.at(1) * layerWidth * layerThick * lgpw; //Nx + answer.at(2) += reducedLayerStress.at(1) * layerWidth * layerThick * lgpw * layerZCoord;//My + answer.at(3) += reducedLayerStress.at(2) * layerWidth * layerThick * lgpw * beamShearCoeffxz; //Vz } - - answer.at(1) += reducedLayerStress.at(1) * layerWidth * layerThick; //Nx - answer.at(2) += reducedLayerStress.at(1) * layerWidth * layerThick * layerZCoord;//My - answer.at(3) += reducedLayerStress.at(2) * layerWidth * layerThick; //Vz } // Create material status according to the first layer material ///@todo This should be replaced with a general "CrossSectionStatus" //CrossSectionStatus *status = new CrossSectionStatus(gp); //gp->setMaterialStatus(status); - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * > - ( domain->giveMaterial( layerMaterials.at(1) )->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(gp) ); status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); + + return answer; } -void -LayeredCrossSection :: giveGeneralizedStress_Beam3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 6 > +LayeredCrossSection::giveGeneralizedStress_Beam3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported"); + return zeros< 6 >(); } -void -LayeredCrossSection :: giveGeneralizedStress_Plate(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 5 > +LayeredCrossSection::giveGeneralizedStress_Plate(const FloatArrayF< 5 > &strain, GaussPoint *gp, TimeStep *tStep) const { - double layerThick, layerWidth, layerZCoord, top, bottom, layerZeta; - FloatArray layerStrain, reducedLayerStress; - StructuralElement *element = static_cast< StructuralElement * >( gp->giveElement() ); - LayeredCrossSectionInterface *interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) ); - - answer.resize(5); - answer.zero(); + FloatArray layerStrain; + auto element = static_cast< StructuralElement * >( gp->giveElement() ); + auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) ); // perform integration over layers - bottom = this->give(CS_BottomZCoord, gp); - top = this->give(CS_TopZCoord, gp); + double bottom = this->give(CS_BottomZCoord, gp); + double top = this->give(CS_TopZCoord, gp); - if ( interface == NULL ) { + if ( interface == nullptr ) { OOFEM_ERROR("element with no layer support encountered"); } + FloatArrayF< 5 >answer; for ( int layer = 1; layer <= numberOfLayers; layer++ ) { - GaussPoint *layerGp = this->giveSlaveGaussPoint(gp, layer - 1); - StructuralMaterial *layerMat = static_cast< StructuralMaterial * >( domain->giveMaterial( layerMaterials.at(layer) ) ); - - // resolve current layer z-coordinate - layerThick = this->layerThicks.at(layer); - layerWidth = this->layerWidths.at(layer); - layerZeta = layerGp->giveNaturalCoordinate(3); - layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); + for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) { + auto layerGp = this->giveSlaveGaussPoint(gp, layer - 1, igp); + auto layerMat = static_cast< StructuralMaterial * >( domain->giveMaterial(layerMaterials.at(layer) ) ); + auto lgpw = layerGp->giveWeight(); + + // resolve current layer z-coordinate + double layerThick = this->layerThicks.at(layer); + double layerWidth = this->layerWidths.at(layer); + double layerZeta = layerGp->giveNaturalCoordinate(3); + double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); + + // Compute the layer stress + interface->computeStrainVectorInLayer(layerStrain, strain, gp, layerGp, tStep); + + FloatArrayF< 5 >reducedLayerStress; + if ( this->layerRots.at(layer) != 0. ) { + double rot = this->layerRots.at(layer); + double c = cos(rot * M_PI / 180.); + double s = sin(rot * M_PI / 180.); + + FloatArrayF< 5 >rotStrain = { + c *c *layerStrain.at(1) - c * s * layerStrain.at(5) + s * s * layerStrain.at(2), + c *c *layerStrain.at(2) + c * s * layerStrain.at(5) + s * s * layerStrain.at(1), + c *layerStrain.at(3) + s * layerStrain.at(4), + c *layerStrain.at(4) - s * layerStrain.at(3), + ( c * c - s * s ) * layerStrain.at(5) + c * s * ( layerStrain.at(1) - layerStrain.at(2) ), + }; - // Compute the layer stress - interface->computeStrainVectorInLayer(layerStrain, strain, gp, layerGp, tStep); + auto rotStress = layerMat->giveRealStressVector_PlateLayer(rotStrain, layerGp, tStep); - if ( this->layerRots.at(layer) != 0. ) { - double rot = this->layerRots.at(layer); - double c = cos(rot * M_PI / 180.); - double s = sin(rot * M_PI / 180.); + reducedLayerStress = { + c *c *rotStress.at(1) + 2 * c * s * rotStress.at(5) + s * s * rotStress.at(2), + c *c *rotStress.at(2) - 2 * c * s * rotStress.at(5) + s * s * rotStress.at(1), + c *rotStress.at(3) - s * rotStress.at(4), + c *rotStress.at(4) + s * rotStress.at(3), + ( c * c - s * s ) * rotStress.at(5) - c * s * ( rotStress.at(1) - rotStress.at(2) ), + }; + } else { + reducedLayerStress = layerMat->giveRealStressVector_PlateLayer(layerStrain, layerGp, tStep); + } - FloatArray rotStress; - FloatArray rotStrain = { - c *c * layerStrain.at(1) - c * s * layerStrain.at(5) + s * s * layerStrain.at(2), - c * c * layerStrain.at(2) + c * s * layerStrain.at(5) + s * s * layerStrain.at(1), - c * layerStrain.at(3) + s * layerStrain.at(4), - c * layerStrain.at(4) - s * layerStrain.at(3), - ( c * c - s * s ) * layerStrain.at(5) + c * s * ( layerStrain.at(1) - layerStrain.at(2) ), - }; - - layerMat->giveRealStressVector_PlateLayer(rotStress, layerGp, rotStrain, tStep); - - reducedLayerStress = { - c *c * rotStress.at(1) + 2 * c * s * rotStress.at(5) + s * s * rotStress.at(2), - c * c * rotStress.at(2) - 2 * c * s * rotStress.at(5) + s * s * rotStress.at(1), - c * rotStress.at(3) - s * rotStress.at(4), - c * rotStress.at(4) + s * rotStress.at(3), - ( c * c - s * s ) * rotStress.at(5) - c * s * ( rotStress.at(1) - rotStress.at(2) ), - }; - } else { - layerMat->giveRealStressVector_PlateLayer(reducedLayerStress, layerGp, layerStrain, tStep); + answer.at(1) += reducedLayerStress.at(1) * layerWidth * layerThick * lgpw * layerZCoord; + answer.at(2) += reducedLayerStress.at(2) * layerWidth * layerThick * lgpw * layerZCoord; + answer.at(3) += reducedLayerStress.at(5) * layerWidth * layerThick * lgpw * layerZCoord; + answer.at(4) += reducedLayerStress.at(4) * layerWidth * layerThick * lgpw * ( 5. / 6. ); + answer.at(5) += reducedLayerStress.at(3) * layerWidth * layerThick * lgpw * ( 5. / 6. ); } - - answer.at(1) += reducedLayerStress.at(1) * layerWidth * layerThick * layerZCoord; - answer.at(2) += reducedLayerStress.at(2) * layerWidth * layerThick * layerZCoord; - answer.at(3) += reducedLayerStress.at(5) * layerWidth * layerThick * layerZCoord; - answer.at(4) += reducedLayerStress.at(4) * layerWidth * layerThick; - answer.at(5) += reducedLayerStress.at(3) * layerWidth * layerThick; } // now we must update master gp @@ -369,134 +386,210 @@ LayeredCrossSection :: giveGeneralizedStress_Plate(FloatArray &answer, GaussPoin ///@todo This should be replaced with a general "CrossSectionStatus" //CrossSectionStatus *status = new CrossSectionStatus(gp); //gp->setMaterialStatus(status); - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * > - ( domain->giveMaterial( layerMaterials.at(1) )->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(gp) ); status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); + return answer; } -void -LayeredCrossSection :: giveGeneralizedStress_Shell(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 8 > +LayeredCrossSection::giveGeneralizedStress_Shell(const FloatArrayF< 8 > &strain, GaussPoint *gp, TimeStep *tStep) const { - double layerThick, layerWidth, layerZCoord, top, bottom, layerZeta; - FloatArray layerStrain, reducedLayerStress; - StructuralElement *element = static_cast< StructuralElement * >( gp->giveElement() ); - LayeredCrossSectionInterface *interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) ); - - answer.resize(8); - answer.zero(); + FloatArray layerStrain; + auto element = static_cast< StructuralElement * >( gp->giveElement() ); + auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) ); // perform integration over layers - bottom = this->give(CS_BottomZCoord, gp); - top = this->give(CS_TopZCoord, gp); + double bottom = this->give(CS_BottomZCoord, gp); + double top = this->give(CS_TopZCoord, gp); - if ( interface == NULL ) { + if ( interface == nullptr ) { OOFEM_ERROR("element with no layer support encountered"); } + FloatArrayF< 8 >answer; for ( int layer = 1; layer <= numberOfLayers; layer++ ) { - GaussPoint *layerGp = this->giveSlaveGaussPoint(gp, layer - 1); - StructuralMaterial *layerMat = static_cast< StructuralMaterial * >( domain->giveMaterial( layerMaterials.at(layer) ) ); + for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) { + auto layerGp = this->giveSlaveGaussPoint(gp, layer - 1, igp); + auto layerMat = static_cast< StructuralMaterial * >( domain->giveMaterial(layerMaterials.at(layer) ) ); + auto lgpw = layerGp->giveWeight(); + + // resolve current layer z-coordinate + double layerThick = this->layerThicks.at(layer); + double layerWidth = this->layerWidths.at(layer); + double layerZeta = layerGp->giveNaturalCoordinate(3); + double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); + + // Compute the layer stress + interface->computeStrainVectorInLayer(layerStrain, strain, gp, layerGp, tStep); // FIXME convert to return value fixed size array. + + FloatArrayF< 5 >reducedLayerStress; + if ( this->layerRots.at(layer) != 0. ) { + double rot = this->layerRots.at(layer); + double c = cos(rot * M_PI / 180.); + double s = sin(rot * M_PI / 180.); + + FloatArrayF< 5 >rotStrain = { + c *c *layerStrain.at(1) - c * s * layerStrain.at(5) + s * s * layerStrain.at(2), + c *c *layerStrain.at(2) + c * s * layerStrain.at(5) + s * s * layerStrain.at(1), + c *layerStrain.at(3) + s * layerStrain.at(4), + c *layerStrain.at(4) - s * layerStrain.at(3), + ( c * c - s * s ) * layerStrain.at(5) + c * s * ( layerStrain.at(1) - layerStrain.at(2) ), + }; - // resolve current layer z-coordinate - layerThick = this->layerThicks.at(layer); - layerWidth = this->layerWidths.at(layer); - layerZeta = layerGp->giveNaturalCoordinate(3); - layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); + auto rotStress = layerMat->giveRealStressVector_PlateLayer(rotStrain, layerGp, tStep); - // Compute the layer stress - interface->computeStrainVectorInLayer(layerStrain, strain, gp, layerGp, tStep); + reducedLayerStress = { + c *c *rotStress.at(1) + 2 * c * s * rotStress.at(5) + s * s * rotStress.at(2), + c *c *rotStress.at(2) - 2 * c * s * rotStress.at(5) + s * s * rotStress.at(1), + c *rotStress.at(3) - s * rotStress.at(4), + c *rotStress.at(4) + s * rotStress.at(3), + ( c * c - s * s ) * rotStress.at(5) - c * s * ( rotStress.at(1) - rotStress.at(2) ), + }; + } else { + reducedLayerStress = layerMat->giveRealStressVector_PlateLayer(layerStrain, layerGp, tStep); + } - if ( this->layerRots.at(layer) != 0. ) { - double rot = this->layerRots.at(layer); - double c = cos(rot * M_PI / 180.); - double s = sin(rot * M_PI / 180.); + // 1) membrane terms sx, sy, sxy + answer.at(1) += reducedLayerStress.at(1) * layerWidth * layerThick * lgpw; + answer.at(2) += reducedLayerStress.at(2) * layerWidth * layerThick * lgpw; + answer.at(3) += reducedLayerStress.at(5) * layerWidth * layerThick * lgpw; + // 2) bending terms mx, my, mxy + answer.at(4) += reducedLayerStress.at(1) * layerWidth * layerThick * layerZCoord * lgpw; + answer.at(5) += reducedLayerStress.at(2) * layerWidth * layerThick * layerZCoord * lgpw; + answer.at(6) += reducedLayerStress.at(5) * layerWidth * layerThick * layerZCoord * lgpw; + // 3) shear terms qx, qy + answer.at(7) += reducedLayerStress.at(4) * layerWidth * layerThick * lgpw * ( 5. / 6. ); + answer.at(8) += reducedLayerStress.at(3) * layerWidth * layerThick * lgpw * ( 5. / 6. ); + } + } - FloatArray rotStress; - FloatArray rotStrain = { - c *c * layerStrain.at(1) - c * s * layerStrain.at(5) + s * s * layerStrain.at(2), - c * c * layerStrain.at(2) + c * s * layerStrain.at(5) + s * s * layerStrain.at(1), - c * layerStrain.at(3) + s * layerStrain.at(4), - c * layerStrain.at(4) - s * layerStrain.at(3), - ( c * c - s * s ) * layerStrain.at(5) + c * s * ( layerStrain.at(1) - layerStrain.at(2) ), - }; - layerMat->giveRealStressVector_PlateLayer(rotStress, layerGp, rotStrain, tStep); + // now we must update master gp + ///@todo This should be replaced with a general "CrossSectionStatus" + //CrossSectionStatus *status = new CrossSectionStatus(gp); + //gp->setMaterialStatus(status); + // Create material status according to the first layer material + auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(gp) ); + status->letTempStrainVectorBe(strain); + status->letTempStressVectorBe(answer); - reducedLayerStress = { - c *c * rotStress.at(1) + 2 * c * s * rotStress.at(5) + s * s * rotStress.at(2), - c * c * rotStress.at(2) - 2 * c * s * rotStress.at(5) + s * s * rotStress.at(1), - c * rotStress.at(3) - s * rotStress.at(4), - c * rotStress.at(4) + s * rotStress.at(3), - ( c * c - s * s ) * rotStress.at(5) - c * s * ( rotStress.at(1) - rotStress.at(2) ), - }; - } else { - layerMat->giveRealStressVector_PlateLayer(reducedLayerStress, layerGp, layerStrain, tStep); - } + return answer; +} - // 1) membrane terms sx, sy, sxy - answer.at(1) += reducedLayerStress.at(1) * layerWidth * layerThick; - answer.at(2) += reducedLayerStress.at(2) * layerWidth * layerThick; - answer.at(3) += reducedLayerStress.at(5) * layerWidth * layerThick; - // 2) bending terms mx, my, mxy - answer.at(4) += reducedLayerStress.at(1) * layerWidth * layerThick * layerZCoord; - answer.at(5) += reducedLayerStress.at(2) * layerWidth * layerThick * layerZCoord; - answer.at(6) += reducedLayerStress.at(5) * layerWidth * layerThick * layerZCoord; - // 3) shear terms qx, qy - answer.at(7) += reducedLayerStress.at(4) * layerWidth * layerThick; - answer.at(8) += reducedLayerStress.at(3) * layerWidth * layerThick; +FloatArrayF< 9 > +LayeredCrossSection::giveGeneralizedStress_ShellRot(const FloatArrayF< 9 > &strain, GaussPoint *gp, TimeStep *tStep) const +{ + FloatArrayF< 9 >answer; + FloatArrayF< 8 >rstrain; + for ( int i = 1; i <= 8; i++ ) { + rstrain.at(i) = strain.at(i); + } + FloatArray ra = this->giveGeneralizedStress_Shell(rstrain, gp, tStep); + for ( int i = 1; i <= 8; i++ ) { + answer.at(i) = ra.at(i); } + answer.at(9) = this->give(CS_DrillingStiffness, gp) * strain.at(9); + - // now we must update master gp ///@todo This should be replaced with a general "CrossSectionStatus" //CrossSectionStatus *status = new CrossSectionStatus(gp); //gp->setMaterialStatus(status); // Create material status according to the first layer material - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * > - ( domain->giveMaterial( layerMaterials.at(1) )->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(gp) ); status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); + + return answer; } -void -LayeredCrossSection :: giveGeneralizedStress_MembraneRot(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) + +FloatArrayF< 4 > +LayeredCrossSection::giveGeneralizedStress_MembraneRot(const FloatArrayF< 4 > &strain, GaussPoint *masterGp, TimeStep *tStep) const { - OOFEM_ERROR("Not supported in given cross-section (yet)."); + //strain eps_x, eps_y, gamma_xy + //stress sig_x, sig_y, tau_xy + //answer n_x, n_y, n_xy + + FloatArray layerStrain; + + //double bottom = this->give(CS_BottomZCoord, masterGp); + //double top = this->give(CS_TopZCoord, masterGp); + + auto element = dynamic_cast< StructuralElement * >( masterGp->giveElement() ); + double totThick = 0.0; + + FloatArrayF< 4 >answer; + for ( int layer = 1; layer <= numberOfLayers; layer++ ) { + for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) { + auto layerGp = this->giveSlaveGaussPoint(masterGp, layer - 1, igp); + auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) ); + auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) ); + auto lgpw = layerGp->giveWeight(); + + // resolve current layer z-coordinate + double layerThick = this->layerThicks.at(layer); + totThick += layerThick * lgpw; + //double layerZeta = layerGp->giveNaturalCoordinate(3); + //double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); + + // Compute the layer stress + interface->computeStrainVectorInLayer(layerStrain, strain, masterGp, layerGp, tStep); + // extract membrane part only + FloatArrayF< 3 >layerStrainMembrane( layerStrain.at(1), layerStrain.at(2), layerStrain.at(3) ); + auto reducedLayerStress = dynamic_cast< StructuralMaterial * >( layerMat )->giveRealStressVector_PlaneStress(layerStrainMembrane, layerGp, tStep); + answer.at(1) += reducedLayerStress.at(1) * layerThick * lgpw; + answer.at(2) += reducedLayerStress.at(2) * layerThick * lgpw; + answer.at(3) += reducedLayerStress.at(3) * layerThick * lgpw; + } + } + + // assume rotation term elastic response + auto de = this->giveMembraneRotStiffMtrx(ElasticStiffness, masterGp, tStep); + answer.at(4) = strain.at(4) * de.at(4, 4) * totThick; + answer *= ( 1. / totThick ); + + auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial(layerMaterials.at(1) )->giveStatus(masterGp) ); + status->letTempStrainVectorBe(strain); + status->letTempStressVectorBe(answer); + + return answer; } -void -LayeredCrossSection :: giveGeneralizedStress_PlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep) +FloatArrayF< 3 > +LayeredCrossSection::giveGeneralizedStress_PlateSubSoil(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not supported in given cross-section (yet)."); + return zeros< 3 >(); } void -LayeredCrossSection :: giveCharMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, - GaussPoint *gp, - TimeStep *tStep) +LayeredCrossSection::giveCharMaterialStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, + GaussPoint *gp, + TimeStep *tStep) // // only interface to material class, forcing returned matrix to be in reduced form. // { MaterialMode mode = gp->giveMaterialMode(); if ( mode == _2dBeam ) { - this->give2dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->give2dBeamStiffMtrx(rMode, gp, tStep); } else if ( mode == _3dBeam ) { - this->give3dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->give3dBeamStiffMtrx(rMode, gp, tStep); } else if ( mode == _2dPlate ) { - this->give2dPlateStiffMtrx(answer, rMode, gp, tStep); + answer = this->give2dPlateStiffMtrx(rMode, gp, tStep); } else if ( mode == _3dShell ) { - this->give3dShellStiffMtrx(answer, rMode, gp, tStep); + answer = this->give3dShellStiffMtrx(rMode, gp, tStep); } else { int ngps = gp->giveIntegrationRule()->giveNumberOfIntegrationPoints(); int gpnum = gp->giveNumber(); int gpsperlayer = ngps / this->numberOfLayers; int layer = ( gpnum - 1 ) / gpsperlayer + 1; - StructuralMaterial *mat = static_cast< StructuralMaterial * >( domain->giveMaterial( this->giveLayerMaterial(layer) ) ); - if ( mat->hasMaterialModeCapability( gp->giveMaterialMode() ) ) { + auto mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(layer) ) ); + if ( mat->hasMaterialModeCapability(gp->giveMaterialMode() ) ) { mat->giveStiffnessMatrix(answer, rMode, gp, tStep); } else { OOFEM_ERROR("unsupported StressStrainMode"); @@ -505,11 +598,8 @@ LayeredCrossSection :: giveCharMaterialStiffnessMatrix(FloatMatrix &answer, } -void -LayeredCrossSection :: give2dPlateStiffMtrx(FloatMatrix &answer, - MatResponseMode rMode, - GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF< 5, 5 > +LayeredCrossSection::give2dPlateStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const // // assumption sigma_z = 0. @@ -521,76 +611,71 @@ LayeredCrossSection :: give2dPlateStiffMtrx(FloatMatrix &answer, // 2) strainVectorShell {eps_x,eps_y,gamma_xy, kappa_x, kappa_y, kappa_xy, gamma_zx, gamma_zy} // { - FloatMatrix layerMatrix; - double layerThick, layerWidth, layerZCoord, top, bottom, layerZeta; - double layerZCoord2; - - answer.resize(5, 5); - answer.zero(); - // perform integration over layers - bottom = this->give(CS_BottomZCoord, gp); - top = this->give(CS_TopZCoord, gp); + double bottom = this->give(CS_BottomZCoord, gp); + double top = this->give(CS_TopZCoord, gp); + FloatMatrixF< 5, 5 >answer; for ( int layer = 1; layer <= numberOfLayers; layer++ ) { - GaussPoint *layerGp = giveSlaveGaussPoint(gp, layer - 1); + for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) { + auto layerGp = giveSlaveGaussPoint(gp, layer - 1, igp); + auto lgpw = layerGp->giveWeight(); + + ///@todo Just using the gp number doesn't nicely support more than 1 gp per layer. Must rethink. + auto mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(layer) ) ); + auto layerMatrix = mat->givePlateLayerStiffMtrx(rMode, layerGp, tStep); + if ( this->layerRots.at(layer) != 0. ) { + double rot = this->layerRots.at(layer); + double c = cos(rot * M_PI / 180.); + double s = sin(rot * M_PI / 180.); + + FloatMatrixF< 5, 5 >rotTangent = { + c *c, s *s, 0., 0., -c * s, + s *s, c *c, 0., 0., c *s, + 0., 0., c, s, 0., + 0., 0., -s, c, 0., + 2 * c * s, -2 * c * s, 0., 0., c *c - s * s, + }; + layerMatrix = unrotate(layerMatrix, rotTangent); + } - ///@todo Just using the gp number doesn't nicely support more than 1 gp per layer. Must rethink. - StructuralMaterial *mat = static_cast< StructuralMaterial * >( domain->giveMaterial( this->giveLayerMaterial(layer) ) ); - mat->givePlateLayerStiffMtrx(layerMatrix, rMode, layerGp, tStep); - if ( this->layerRots.at(layer) != 0. ) { - double rot = this->layerRots.at(layer); - double c = cos(rot * M_PI / 180.); - double s = sin(rot * M_PI / 180.); - FloatMatrix rotTangent = { - { c *c, s *s, 0, 0, -c *s }, - { s *s, c *c, 0, 0, c *s }, - { 0, 0, c, s, 0 }, - { 0, 0, -s, c, 0 }, - { 2 * c * s, -2 * c * s, 0, 0, c * c - s * s } - }; - layerMatrix.rotatedWith(rotTangent, 't'); + // + // resolve current layer z-coordinate + // + double layerThick = this->layerThicks.at(layer); + double layerWidth = this->layerWidths.at(layer); + double layerZeta = layerGp->giveNaturalCoordinate(3); + double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); + double layerZCoord2 = layerZCoord * layerZCoord; + // + // perform integration + // + // 1) bending terms mx, my, mxy + answer.at(1, 1) += layerMatrix.at(1, 1) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(1, 2) += layerMatrix.at(1, 2) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(1, 3) += layerMatrix.at(1, 5) * lgpw * layerWidth * layerThick * layerZCoord2; + + answer.at(2, 1) += layerMatrix.at(2, 1) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(2, 2) += layerMatrix.at(2, 2) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(2, 3) += layerMatrix.at(2, 5) * lgpw * layerWidth * layerThick * layerZCoord2; + + answer.at(3, 1) += layerMatrix.at(5, 1) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(3, 2) += layerMatrix.at(5, 2) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(3, 3) += layerMatrix.at(5, 5) * lgpw * layerWidth * layerThick * layerZCoord2; + + // 2) shear terms qx = qxz, qy = qyz + answer.at(4, 4) += layerMatrix.at(4, 4) * lgpw * layerWidth * layerThick * ( 5. / 6. ); + answer.at(4, 5) += layerMatrix.at(4, 3) * lgpw * layerWidth * layerThick * ( 5. / 6. ); + answer.at(5, 4) += layerMatrix.at(3, 4) * lgpw * layerWidth * layerThick * ( 5. / 6. ); + answer.at(5, 5) += layerMatrix.at(3, 3) * lgpw * layerWidth * layerThick * ( 5. / 6. ); } - - // - // resolve current layer z-coordinate - // - layerThick = this->layerThicks.at(layer); - layerWidth = this->layerWidths.at(layer); - layerZeta = layerGp->giveNaturalCoordinate(3); - layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); - layerZCoord2 = layerZCoord * layerZCoord; - // - // perform integration - // - // 1) bending terms mx, my, mxy - - answer.at(1, 1) += layerMatrix.at(1, 1) * layerWidth * layerThick * layerZCoord2; - answer.at(1, 2) += layerMatrix.at(1, 2) * layerWidth * layerThick * layerZCoord2; - answer.at(1, 3) += layerMatrix.at(1, 5) * layerWidth * layerThick * layerZCoord2; - - answer.at(2, 1) += layerMatrix.at(2, 1) * layerWidth * layerThick * layerZCoord2; - answer.at(2, 2) += layerMatrix.at(2, 2) * layerWidth * layerThick * layerZCoord2; - answer.at(2, 3) += layerMatrix.at(2, 5) * layerWidth * layerThick * layerZCoord2; - - answer.at(3, 1) += layerMatrix.at(5, 1) * layerWidth * layerThick * layerZCoord2; - answer.at(3, 2) += layerMatrix.at(5, 2) * layerWidth * layerThick * layerZCoord2; - answer.at(3, 3) += layerMatrix.at(5, 5) * layerWidth * layerThick * layerZCoord2; - - // 2) shear terms qx = qxz, qy = qyz - answer.at(4, 4) += layerMatrix.at(4, 4) * layerWidth * layerThick; - answer.at(4, 5) += layerMatrix.at(4, 3) * layerWidth * layerThick; - answer.at(5, 4) += layerMatrix.at(3, 4) * layerWidth * layerThick; - answer.at(5, 5) += layerMatrix.at(3, 3) * layerWidth * layerThick; } + return answer; } -void -LayeredCrossSection :: give3dShellStiffMtrx(FloatMatrix &answer, - MatResponseMode rMode, - GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF< 8, 8 > +LayeredCrossSection::give3dShellStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const // // assumption sigma_z = 0. // @@ -601,100 +686,117 @@ LayeredCrossSection :: give3dShellStiffMtrx(FloatMatrix &answer, // 2) strainVectorShell {eps_x,eps_y,gamma_xy, kappa_x, kappa_y, kappa_xy, gamma_zx, gamma_zy} // { - FloatMatrix layerMatrix; - double layerThick, layerWidth, layerZCoord, top, bottom, layerZeta; - // double zi, zi1; - double layerZCoord2; - - answer.resize(8, 8); - answer.zero(); // perform integration over layers - bottom = this->give(CS_BottomZCoord, gp); - top = this->give(CS_TopZCoord, gp); + double bottom = this->give(CS_BottomZCoord, gp); + double top = this->give(CS_TopZCoord, gp); + double shearcoeff = 5. / 6.; + FloatMatrixF< 8, 8 >answer; for ( int layer = 1; layer <= numberOfLayers; layer++ ) { - GaussPoint *layerGp = giveSlaveGaussPoint(gp, layer - 1); + for ( int igp = 0; igp < layerIntegrationPoints.at(layer); igp++ ) { + auto layerGp = giveSlaveGaussPoint(gp, layer - 1, igp); + auto lgpw = layerGp->giveWeight(); + + ///@todo The logic in this whole class is pretty messy to support both slave-gp's and normal gps. Rethinking the approach is necessary. + /// Just using the gp number doesn't nicely support more than 1 gp per layer. Must rethink. + auto mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(layer) ) ); + auto layerMatrix = mat->givePlateLayerStiffMtrx(rMode, layerGp, tStep); + if ( this->layerRots.at(layer) != 0. ) { + double rot = this->layerRots.at(layer); + double c = cos(rot); + double s = sin(rot); + + FloatMatrixF< 5, 5 >rotTangent = { + c *c, s *s, 0., 0., -c * s, + s *s, c *c, 0., 0., c *s, + 0., 0., c, s, 0., + 0., 0., -s, c, 0., + 2 * c * s, -2 * c * s, 0., 0., c *c - s * s, + }; + layerMatrix = unrotate(layerMatrix, rotTangent); + } - ///@todo The logic in this whole class is pretty messy to support both slave-gp's and normal gps. Rethinking the approach is necessary. - /// Just using the gp number doesn't nicely support more than 1 gp per layer. Must rethink. - StructuralMaterial *mat = static_cast< StructuralMaterial * >( domain->giveMaterial( this->giveLayerMaterial(layer) ) ); - mat->givePlateLayerStiffMtrx(layerMatrix, rMode, layerGp, tStep); - if ( this->layerRots.at(layer) != 0. ) { - double rot = this->layerRots.at(layer); - double c = cos(rot); - double s = sin(rot); - FloatMatrix rotTangent = { - { c *c, s *s, 0, 0, -c *s }, - { s *s, c *c, 0, 0, c *s }, - { 0, 0, c, s, 0 }, - { 0, 0, -s, c, 0 }, - { 2 * c * s, -2 * c * s, 0, 0, c * c - s * s } - }; - layerMatrix.rotatedWith(rotTangent, 't'); + // + // resolve current layer z-coordinate + // + double layerThick = this->layerThicks.at(layer); + double layerWidth = this->layerWidths.at(layer); + double layerZeta = layerGp->giveNaturalCoordinate(3); + double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); + double layerZCoord2 = layerZCoord * layerZCoord; + // + // perform integration + // + // 1) membrane terms sx, sy, sxy + answer.at(1, 1) += layerMatrix.at(1, 1) * lgpw * layerWidth * layerThick; + answer.at(1, 2) += layerMatrix.at(1, 2) * lgpw * layerWidth * layerThick; + answer.at(1, 3) += layerMatrix.at(1, 5) * lgpw * layerWidth * layerThick; + + answer.at(2, 1) += layerMatrix.at(2, 1) * lgpw * layerWidth * layerThick; + answer.at(2, 2) += layerMatrix.at(2, 2) * lgpw * layerWidth * layerThick; + answer.at(2, 3) += layerMatrix.at(2, 5) * lgpw * layerWidth * layerThick; + + answer.at(3, 1) += layerMatrix.at(5, 1) * lgpw * layerWidth * layerThick; + answer.at(3, 2) += layerMatrix.at(5, 2) * lgpw * layerWidth * layerThick; + answer.at(3, 3) += layerMatrix.at(5, 5) * lgpw * layerWidth * layerThick; + + // 2) bending terms mx, my, mxy + + answer.at(4, 4) += layerMatrix.at(1, 1) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(4, 5) += layerMatrix.at(1, 2) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(4, 6) += layerMatrix.at(1, 5) * lgpw * layerWidth * layerThick * layerZCoord2; + + answer.at(5, 4) += layerMatrix.at(2, 1) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(5, 5) += layerMatrix.at(2, 2) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(5, 6) += layerMatrix.at(2, 5) * lgpw * layerWidth * layerThick * layerZCoord2; + + answer.at(6, 4) += layerMatrix.at(5, 1) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(6, 5) += layerMatrix.at(5, 2) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(6, 6) += layerMatrix.at(5, 5) * lgpw * layerWidth * layerThick * layerZCoord2; + + // 3) shear terms qx, qy + answer.at(7, 7) += layerMatrix.at(4, 4) * lgpw * layerWidth * layerThick * shearcoeff; + answer.at(7, 8) += layerMatrix.at(4, 3) * lgpw * layerWidth * layerThick * shearcoeff; + answer.at(8, 7) += layerMatrix.at(3, 4) * lgpw * layerWidth * layerThick * shearcoeff; + answer.at(8, 8) += layerMatrix.at(3, 3) * lgpw * layerWidth * layerThick * shearcoeff; } - - // - // resolve current layer z-coordinate - // - layerThick = this->layerThicks.at(layer); - layerWidth = this->layerWidths.at(layer); - layerZeta = layerGp->giveNaturalCoordinate(3); - layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); - layerZCoord2 = layerZCoord * layerZCoord; - // - // perform integration - // - // 1) membrane terms sx, sy, sxy - answer.at(1, 1) += layerMatrix.at(1, 1) * layerWidth * layerThick; - answer.at(1, 2) += layerMatrix.at(1, 2) * layerWidth * layerThick; - answer.at(1, 3) += layerMatrix.at(1, 5) * layerWidth * layerThick; - - answer.at(2, 1) += layerMatrix.at(2, 1) * layerWidth * layerThick; - answer.at(2, 2) += layerMatrix.at(2, 2) * layerWidth * layerThick; - answer.at(2, 3) += layerMatrix.at(2, 5) * layerWidth * layerThick; - - answer.at(3, 1) += layerMatrix.at(5, 1) * layerWidth * layerThick; - answer.at(3, 2) += layerMatrix.at(5, 2) * layerWidth * layerThick; - answer.at(3, 3) += layerMatrix.at(5, 5) * layerWidth * layerThick; - - // 2) bending terms mx, my, mxy - - answer.at(4, 4) += layerMatrix.at(1, 1) * layerWidth * layerThick * layerZCoord2; - answer.at(4, 5) += layerMatrix.at(1, 2) * layerWidth * layerThick * layerZCoord2; - answer.at(4, 6) += layerMatrix.at(1, 5) * layerWidth * layerThick * layerZCoord2; - - answer.at(5, 4) += layerMatrix.at(2, 1) * layerWidth * layerThick * layerZCoord2; - answer.at(5, 5) += layerMatrix.at(2, 2) * layerWidth * layerThick * layerZCoord2; - answer.at(5, 6) += layerMatrix.at(2, 5) * layerWidth * layerThick * layerZCoord2; - - answer.at(6, 4) += layerMatrix.at(5, 1) * layerWidth * layerThick * layerZCoord2; - answer.at(6, 5) += layerMatrix.at(5, 2) * layerWidth * layerThick * layerZCoord2; - answer.at(6, 6) += layerMatrix.at(5, 5) * layerWidth * layerThick * layerZCoord2; - - // 3) shear terms qx, qy - answer.at(7, 7) += layerMatrix.at(4, 4) * layerWidth * layerThick; - answer.at(7, 8) += layerMatrix.at(4, 3) * layerWidth * layerThick; - answer.at(8, 7) += layerMatrix.at(3, 4) * layerWidth * layerThick; - answer.at(8, 8) += layerMatrix.at(3, 3) * layerWidth * layerThick; } + return answer; } -void -LayeredCrossSection :: give3dDegeneratedShellStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 9, 9 > +LayeredCrossSection::give3dShellRotStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +// +// assumption sigma_z = 0. +// +// General strain layer vector has one of the following forms: +// 1) strainVector3d {eps_x,eps_y,eps_z,gamma_yz,gamma_zx,gamma_xy} +// +// returned strain or stress vector has the form: +// 2) strainVectorShell {eps_x,eps_y,gamma_xy, kappa_x, kappa_y, kappa_xy, gamma_zx, gamma_zy, eps_normalRotation} +// { - ///@todo - check-V - answer.resize(6,6); + FloatMatrix d, answer; + d = this->give3dShellStiffMtrx(rMode, gp, tStep); + answer.resize(9, 9); answer.zero(); + answer.assemble(d, { 1, 2, 3, 4, 5, 6, 7, 8 }); + answer.at(9, 9) = this->give(CS_DrillingStiffness, gp); + //answer.printYourself("De"); + + return answer; } - +FloatMatrixF< 6, 6 > +LayeredCrossSection::give3dDegeneratedShellStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + ///@todo - check-V + return FloatMatrixF< 6, 6 >(); +} -void -LayeredCrossSection :: give2dBeamStiffMtrx(FloatMatrix &answer, - MatResponseMode rMode, - GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF< 3, 3 > +LayeredCrossSection::give2dBeamStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const // // assumption sigma_z = 0. // @@ -705,75 +807,291 @@ LayeredCrossSection :: give2dBeamStiffMtrx(FloatMatrix &answer, // 2) strainVectorShell {eps_x,eps_y,gamma_xy, kappa_x, kappa_y, kappa_xy, gamma_zx, gamma_zy} // { - FloatMatrix layerMatrix; - double layerThick, layerWidth, layerZCoord, top, bottom, layerZeta; - double layerZCoord2; - // perform integration over layers - bottom = this->give(CS_BottomZCoord, gp); - top = this->give(CS_TopZCoord, gp); - - answer.resize(3, 3); - answer.zero(); + double bottom = this->give(CS_BottomZCoord, gp); + double top = this->give(CS_TopZCoord, gp); + FloatMatrixF< 3, 3 >answer; for ( int i = 1; i <= numberOfLayers; i++ ) { - GaussPoint *layerGp = giveSlaveGaussPoint(gp, i - 1); - - ///@todo The logic in this whole class is pretty messy to support both slave-gp's and normal gps. Rethinking the approach is necessary. - /// Just using the gp number doesn't nicely support more than 1 gp per layer. Must rethink. - StructuralMaterial *mat = static_cast< StructuralMaterial * >( domain->giveMaterial( this->giveLayerMaterial(i) ) ); - mat->give2dBeamLayerStiffMtrx(layerMatrix, rMode, layerGp, tStep); - if ( this->layerRots.at(i) != 0. ) { - OOFEM_ERROR("Doesn't support layer rotations."); - } + for ( int igp = 0; igp < layerIntegrationPoints.at(i); igp++ ) { + auto layerGp = giveSlaveGaussPoint(gp, i - 1, igp); + auto lgpw = layerGp->giveWeight(); + + ///@todo The logic in this whole class is pretty messy to support both slave-gp's and normal gps. Rethinking the approach is necessary. + /// Just using the gp number doesn't nicely support more than 1 gp per layer. Must rethink. + auto mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(i) ) ); + auto layerMatrix = mat->give2dBeamLayerStiffMtrx(rMode, layerGp, tStep); + if ( this->layerRots.at(i) != 0. ) { + OOFEM_ERROR("Doesn't support layer rotations."); + } - // - // resolve current layer z-coordinate - // - layerThick = this->layerThicks.at(i); - layerWidth = this->layerWidths.at(i); - layerZeta = layerGp->giveNaturalCoordinate(3); - layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); - layerZCoord2 = layerZCoord * layerZCoord; - // - // perform integration - // - // 1) membrane terms sx - answer.at(1, 1) += layerMatrix.at(1, 1) * layerWidth * layerThick; - answer.at(1, 3) += layerMatrix.at(1, 2) * layerWidth * layerThick; - // 2) bending terms my - answer.at(2, 2) += layerMatrix.at(1, 1) * layerWidth * layerThick * layerZCoord2; - answer.at(2, 3) += layerMatrix.at(1, 2) * layerWidth * layerThick * layerZCoord2; - // 3) shear terms qx - answer.at(3, 1) += layerMatrix.at(2, 1) * layerWidth * layerThick; - answer.at(3, 3) += layerMatrix.at(2, 2) * layerWidth * layerThick; + // + // resolve current layer z-coordinate + // + double layerThick = this->layerThicks.at(i); + double layerWidth = this->layerWidths.at(i); + double layerZeta = layerGp->giveNaturalCoordinate(3); + double layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); + double layerZCoord2 = layerZCoord * layerZCoord; + // + // perform integration + // + // 1) membrane terms sx + answer.at(1, 1) += layerMatrix.at(1, 1) * lgpw * layerWidth * layerThick; + answer.at(1, 3) += layerMatrix.at(1, 2) * lgpw * layerWidth * layerThick; + // 2) bending terms my + answer.at(2, 2) += layerMatrix.at(1, 1) * lgpw * layerWidth * layerThick * layerZCoord2; + answer.at(2, 3) += layerMatrix.at(1, 2) * lgpw * layerWidth * layerThick * layerZCoord2; + // 3) shear terms qx + answer.at(3, 1) += layerMatrix.at(2, 1) * lgpw * layerWidth * layerThick * beamShearCoeffxz; + answer.at(3, 3) += layerMatrix.at(2, 2) * lgpw * layerWidth * layerThick * beamShearCoeffxz; + } } + return answer; } -void -LayeredCrossSection :: give3dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 6, 6 > +LayeredCrossSection::give3dBeamStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not implemented"); + return FloatMatrixF< 6, 6 >(); } -void -LayeredCrossSection :: giveMembraneRotStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 4, 4 > +LayeredCrossSection::giveMembraneRotStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + auto d = this->giveStiffnessMatrix_PlaneStress(rMode, gp, tStep); + auto de = this->giveStiffnessMatrix_PlaneStress(ElasticStiffness, gp, tStep); + auto ds = assemble< 4, 4 >(d, { 0, 1, 2 }, { 0, 1, 2 }); + ds.at(4, 4) = 2.0 * de.at(3, 3); //this->give(CS_DrillingStiffness, gp); + return ds; +} + +FloatMatrixF< 3, 3 > +LayeredCrossSection::give2dPlateSubSoilStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Not implemented"); + return FloatMatrixF< 3, 3 >(); } + + +FloatArrayF< 9 > +LayeredCrossSection::giveFirstPKStress_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const +{ + if ( gp->giveIntegrationRule()->giveIntegrationDomain() == _Cube || gp->giveIntegrationRule()->giveIntegrationDomain() == _Wedge ) { + // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints) + int ngps = gp->giveIntegrationRule()->giveNumberOfIntegrationPoints(); + int gpnum = gp->giveNumber(); + int gpsperlayer = ngps / this->numberOfLayers; + int layer = ( gpnum - 1 ) / gpsperlayer + 1; + auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) ); + if ( this->layerRots.at(layer) != 0. ) { + double rot = this->layerRots.at(layer); + double c = cos(rot * M_PI / 180.); + double s = sin(rot * M_PI / 180.); + //rotation matrix + //Q = {{c, -s, 0}, {s, c, 0}, {0, 0, 1}}; + FloatMatrixF< 9, 9 >Q = { + c *c, s *s, 0., 0., 0., -c * s, 0., 0., -c * s, + s *s, c *c, 0., 0., 0., c *s, 0., 0., c *s, + 0., 0., 1., 0., 0., 0., 0., 0., 0., + 0., 0., 0., c, s, 0., 0., 0., 0., + 0., 0., 0., -s, c, 0., 0., 0., 0., + c *s, -c * s, 0., 0., 0., c *c, 0., 0., -s * s, + 0., 0., 0., 0., 0., 0., c, s, 0., + 0., 0., 0., 0., 0., 0., -s, c, 0., + c *s, -c * s, 0., 0., 0., -s * s, 0., 0., -c * c, + }; + // Q^T F Q + auto rotvF = dot(Q, vF); + // compute rotated vP + auto rotvP = static_cast< StructuralMaterial * >( layerMat )->giveFirstPKStressVector_3d(rotvF, gp, tStep); + // + auto vP = Tdot(Q, rotvP); + return vP; + } else { + return static_cast< StructuralMaterial * >( layerMat )->giveFirstPKStressVector_3d(vF, gp, tStep); + } + } else { + OOFEM_ERROR("Only cubes and wedges are meaningful for layered cross-sections"); + return zeros< 9 >(); + } +} + + + +FloatArrayF< 5 > +LayeredCrossSection::giveFirstPKStress_PlaneStrain(const FloatArrayF< 5 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return zeros< 5 >(); +} + + +FloatArrayF< 4 > +LayeredCrossSection::giveFirstPKStress_PlaneStress(const FloatArrayF< 4 > &reducedvF, GaussPoint *masterGp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return zeros< 4 >(); + //@todo: implement this for large strains + //strain eps_x, eps_y, gamma_xy + //stress sig_x, sig_y, tau_xy + //answer n_x, n_y, n_xy + + /* FloatArray layerStrain; + * auto element = dynamic_cast< StructuralElement * >( masterGp->giveElement() ); + * double totThick = 0.0; + * + * FloatArrayF<3> answer; + * for ( int layer = 1; layer <= numberOfLayers; layer++ ) { + * for (int igp = 0; igp < layerIntegrationPoints.at(layer); igp++) { + * auto layerGp = this->giveSlaveGaussPoint(masterGp, layer - 1, igp); + * auto layerMat = this->domain->giveMaterial( this->giveLayerMaterial(layer) ); + * auto interface = static_cast< LayeredCrossSectionInterface * >( element->giveInterface(LayeredCrossSectionInterfaceType) ); + * auto lgpw = layerGp->giveWeight(); + * + * // resolve current layer z-coordinate + * double layerThick = this->layerThicks.at(layer); + * totThick += layerThick * lgpw; + * + * // Compute the layer stress + * interface->computeStrainVectorInLayer(layerStrain, strain, masterGp, layerGp, tStep); + * auto reducedLayerStress = dynamic_cast< StructuralMaterial * >(layerMat)->giveRealStressVector_PlaneStress(layerStrain, layerGp, tStep); + * answer.at(1) += reducedLayerStress.at(1) * layerThick* lgpw; + * answer.at(2) += reducedLayerStress.at(2) * layerThick* lgpw; + * answer.at(3) += reducedLayerStress.at(3) * layerThick* lgpw; // * ( 5. / 6. ); + * } + * } + * answer*=(1./totThick); + * auto status = static_cast< StructuralMaterialStatus * >( domain->giveMaterial( layerMaterials.at(1) )->giveStatus(masterGp) ); + * status->letTempStrainVectorBe(strain); + * status->letTempStressVectorBe(answer); + * + * return answer; + */ +} + + +FloatArrayF< 1 > +LayeredCrossSection::giveFirstPKStress_1d(const FloatArrayF< 1 > &strain, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return zeros< 1 >(); +} + + + + void -LayeredCrossSection :: give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +LayeredCrossSection::giveCharMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, + MatResponseMode rMode, + GaussPoint *gp, + TimeStep *tStep) +// +// only interface to material class, forcing returned matrix to be in reduced form. +// { - OOFEM_ERROR("Not implemented"); + // MaterialMode mode = gp->giveMaterialMode(); + int ngps = gp->giveIntegrationRule()->giveNumberOfIntegrationPoints(); + int gpnum = gp->giveNumber(); + int gpsperlayer = ngps / this->numberOfLayers; + int layer = ( gpnum - 1 ) / gpsperlayer + 1; + auto mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(layer) ) ); + if ( mat->hasMaterialModeCapability(gp->giveMaterialMode() ) ) { + mat->giveStiffnessMatrix(answer, rMode, gp, tStep); + } else { + OOFEM_ERROR("unsupported StressStrainMode"); + } +} + + +FloatMatrixF< 9, 9 > +LayeredCrossSection::giveStiffnessMatrix_dPdF_3d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + if ( gp->giveIntegrationRule()->giveIntegrationDomain() != _Cube && gp->giveIntegrationRule()->giveIntegrationDomain() != _Wedge ) { + OOFEM_ERROR("Only cubes and wedges are meaningful for layered cross-sections"); + } + // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints) + int ngps = gp->giveIntegrationRule()->giveNumberOfIntegrationPoints(); + int gpnum = gp->giveNumber(); + int gpsperlayer = ngps / this->numberOfLayers; + int layer = ( gpnum - 1 ) / gpsperlayer + 1; + auto layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) ); + auto tangent = static_cast< StructuralMaterial * >( layerMat )->give3dMaterialStiffnessMatrix_dPdF(rMode, gp, tStep); + + if ( this->layerRots.at(layer) != 0. ) { + double rot = this->layerRots.at(layer); + double c = cos(rot * M_PI / 180.); + double s = sin(rot * M_PI / 180.); + + FloatMatrixF< 9, 9 >Q = { + c *c, s *s, 0., 0., 0., -c * s, 0., 0., -c * s, + s *s, c *c, 0., 0., 0., c *s, 0., 0., c *s, + 0., 0., 1., 0., 0., 0., 0., 0., 0., + 0., 0., 0., c, s, 0., 0., 0., 0., + 0., 0., 0., -s, c, 0., 0., 0., 0., + c *s, -c * s, 0., 0., 0., c *c, 0., 0., -s * s, + 0., 0., 0., 0., 0., 0., c, s, 0., + 0., 0., 0., 0., 0., 0., -s, c, 0., + c *s, -c * s, 0., 0., 0., -s * s, 0., 0., -c * c, + }; + + return unrotate(tangent, Q); + } else { + return tangent; + } +} + + +FloatMatrixF< 4, 4 > +LayeredCrossSection::giveStiffnessMatrix_dPdF_PlaneStress(MatResponseMode rMode, GaussPoint *masterGp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return FloatMatrixF< 4, 4 >(); + /*@todo: implement for large strains + * FloatMatrixF<3,3> answer; + * double totThick = 0.; + * + * //Average stiffness over all layers + * for ( int layer = 1; layer <= numberOfLayers; layer++ ) { + * for (int igp=0; igp< layerIntegrationPoints.at(layer); igp++) { + * auto slaveGP = this->giveSlaveGaussPoint(masterGp, layer - 1, igp); + * auto layerMat = this->domain->giveMaterial( this->giveLayerMaterial(layer) ); + * auto sgpw = slaveGP->giveWeight(); + * double layerThick = this->layerThicks.at(layer); + * totThick += layerThick * sgpw; + * auto subAnswer = dynamic_cast< StructuralMaterial * >(layerMat)->givePlaneStressStiffMtrx(rMode, slaveGP, tStep); + * answer += layerThick * sgpw * subAnswer; + * } + * } + * //answer.at(3,3) *= (5./6.); + * return answer * (1./totThick); + */ +} + + +FloatMatrixF< 5, 5 > +LayeredCrossSection::giveStiffnessMatrix_dPdF_PlaneStrain(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return FloatMatrixF< 5, 5 >(); +} + + +FloatMatrixF< 1, 1 > +LayeredCrossSection::giveStiffnessMatrix_dPdF_1d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Not supported"); + return FloatMatrixF< 1, 1 >(); } FloatArray * -LayeredCrossSection :: imposeStressConstrainsOnGradient(GaussPoint *gp, FloatArray *gradientStressVector3d) +LayeredCrossSection::imposeStressConstrainsOnGradient(GaussPoint *gp, FloatArray *gradientStressVector3d) // // returns modified gradient of stress vector, which is used to // bring stresses back to yield surface. @@ -805,7 +1123,7 @@ LayeredCrossSection :: imposeStressConstrainsOnGradient(GaussPoint *gp, FloatArr break; default: - StructuralCrossSection :: imposeStressConstrainsOnGradient(gp, gradientStressVector3d); + StructuralCrossSection::imposeStressConstrainsOnGradient(gp, gradientStressVector3d); } return gradientStressVector3d; @@ -813,7 +1131,7 @@ LayeredCrossSection :: imposeStressConstrainsOnGradient(GaussPoint *gp, FloatArr FloatArray * -LayeredCrossSection :: imposeStrainConstrainsOnGradient(GaussPoint *gp, FloatArray *gradientStrainVector3d) +LayeredCrossSection::imposeStrainConstrainsOnGradient(GaussPoint *gp, FloatArray *gradientStrainVector3d) // // returns modified gradient of strain vector, which is used to // compute plastic strain increment. @@ -838,65 +1156,59 @@ LayeredCrossSection :: imposeStrainConstrainsOnGradient(GaussPoint *gp, FloatArr break; default: - StructuralCrossSection :: imposeStrainConstrainsOnGradient(gp, gradientStrainVector3d); + StructuralCrossSection::imposeStrainConstrainsOnGradient(gp, gradientStrainVector3d); } return gradientStrainVector3d; } -IRResultType -LayeredCrossSection :: initializeFrom(InputRecord *ir) +void +LayeredCrossSection::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + CrossSection::initializeFrom(ir); - result = CrossSection :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; + IR_GIVE_FIELD(ir, numberOfLayers, _IFT_LayeredCrossSection_nlayers); + if ( numberOfLayers <= 0 ) { + throw ValueInputException(ir, _IFT_LayeredCrossSection_nlayers, "numberOfLayers <= 0 is not allowed"); } - IR_GIVE_FIELD(ir, numberOfLayers, _IFT_LayeredCrossSection_nlayers); - IR_GIVE_FIELD(ir, layerMaterials, _IFT_LayeredCrossSection_layermaterials); - IR_GIVE_FIELD(ir, layerThicks, _IFT_LayeredCrossSection_thicks); - layerWidths.resize(numberOfLayers); - layerWidths.zero(); - IR_GIVE_OPTIONAL_FIELD(ir, layerWidths, _IFT_LayeredCrossSection_widths); - layerRots.resize(numberOfLayers); - layerRots.zero(); - IR_GIVE_OPTIONAL_FIELD(ir, layerRots, _IFT_LayeredCrossSection_layerRotations); - if ( numberOfLayers != layerRots.giveSize() ) { //|| ( numberOfLayers != layerWidths.giveSize() ) ) || numberOfLayers != layerThicks.giveSize() || numberOfLayers != layerMaterials.giveSize() - OOFEM_WARNING("numberOfLayers does not equal given number of layer rotations. "); - return IRRT_BAD_FORMAT; + IR_GIVE_FIELD(ir, layerMaterials, _IFT_LayeredCrossSection_layermaterials); + if ( numberOfLayers != layerMaterials.giveSize() ) { + if ( layerMaterials.giveSize() == 1 ) { + OOFEM_WARNING("Assuming same material in all layers"); + double temp = layerMaterials.at(1); + layerMaterials.resize(numberOfLayers); + layerMaterials.zero(); + layerMaterials.add(temp); + } else { + throw ValueInputException(ir, _IFT_LayeredCrossSection_layermaterials, "numberOfLayers does not equal given number of materials. "); + } } - if ( numberOfLayers != layerThicks.giveSize() ) { + IR_GIVE_FIELD(ir, layerThicks, _IFT_LayeredCrossSection_thicks); + if ( numberOfLayers != layerThicks.giveSize() ) { if ( layerThicks.giveSize() == 1 ) { OOFEM_WARNING("Assuming same thickness in all layers"); double temp = layerThicks.at(1); - layerThicks.resize(numberOfLayers); layerThicks.zero(); + layerThicks.resize(numberOfLayers); + layerThicks.zero(); layerThicks.add(temp); } else { - OOFEM_WARNING("numberOfLayers does not equal given number of thicknesses. "); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_LayeredCrossSection_thicks, "numberOfLayers does not equal given number of thicknesses. "); } } - if ( numberOfLayers != layerMaterials.giveSize() ) { - if ( layerMaterials.giveSize() == 1 ) { - OOFEM_WARNING("Assuming same material in all layers"); - double temp = layerMaterials.at(1); - layerMaterials.resize(numberOfLayers); layerMaterials.zero(); - layerMaterials.add(temp); - } else { - OOFEM_WARNING("numberOfLayers does not equal given number of materials. "); - return IRRT_BAD_FORMAT; - } - } + layerWidths.resize(numberOfLayers); + layerWidths.zero(); + IR_GIVE_OPTIONAL_FIELD(ir, layerWidths, _IFT_LayeredCrossSection_widths); + layerRots.resize(numberOfLayers); + layerRots.zero(); + IR_GIVE_OPTIONAL_FIELD(ir, layerRots, _IFT_LayeredCrossSection_layerRotations); - if ( numberOfLayers <= 0 ) { - OOFEM_WARNING("numberOfLayers<= 0 is not allowed"); - return IRRT_BAD_FORMAT; + if ( numberOfLayers != layerRots.giveSize() ) { //|| ( numberOfLayers != layerWidths.giveSize() ) ) || numberOfLayers != layerThicks.giveSize() || numberOfLayers != layerMaterials.giveSize() + throw ValueInputException(ir, _IFT_LayeredCrossSection_layerRotations, "numberOfLayers does not equal given number of layer rotations. "); } // Interface materials // add check if correct numbers @@ -906,7 +1218,18 @@ LayeredCrossSection :: initializeFrom(InputRecord *ir) numberOfIntegrationPoints = 1; IR_GIVE_OPTIONAL_FIELD(ir, numberOfIntegrationPoints, _IFT_LayeredCrossSection_nintegrationpoints); + this->layerIntegrationPoints.resize(numberOfLayers); + for ( int i = 1; i <= numberOfLayers; i++ ) { + this->layerIntegrationPoints.at(i) = numberOfIntegrationPoints; + } + + IR_GIVE_OPTIONAL_FIELD(ir, layerIntegrationPoints, _IFT_LayeredCrossSection_nlayerintegrationpoints); + if ( layerIntegrationPoints.giveSize() != numberOfLayers ) { + throw ValueInputException(ir, _IFT_LayeredCrossSection_nlayerintegrationpoints, "size of layerIntegrationPoints does not equal given number of layers. "); + } + + this->totalThick = layerThicks.sum(); // read z-coordinate of mid-surface measured from bottom layer midSurfaceZcoordFromBottom = 0.5 * this->computeIntegralThick(); // Default: geometric midplane midSurfaceXiCoordFromBottom = 1.0; // add to IR @@ -914,12 +1237,25 @@ LayeredCrossSection :: initializeFrom(InputRecord *ir) this->setupLayerMidPlanes(); - return IRRT_OK; + this->area = this->layerThicks.dotProduct(this->layerWidths); + IR_GIVE_OPTIONAL_FIELD(ir, beamShearCoeffxz, _IFT_LayeredCrossSection_shearcoeff_xz); + + double value = 0.0; + IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_SimpleCrossSection_drillStiffness); + propertyDictionary.add(CS_DrillingStiffness, value); + + value = 0.0; + IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_SimpleCrossSection_relDrillStiffness); + propertyDictionary.add(CS_RelDrillingStiffness, value); + + value = 0.0; + IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_SimpleCrossSection_drillType); + propertyDictionary.add(CS_DrillingType, value); } -void LayeredCrossSection :: giveInputRecord(DynamicInputRecord &input) +void LayeredCrossSection::giveInputRecord(DynamicInputRecord &input) { - StructuralCrossSection :: giveInputRecord(input); + StructuralCrossSection::giveInputRecord(input); input.setField(this->numberOfLayers, _IFT_LayeredCrossSection_nlayers); input.setField(this->layerMaterials, _IFT_LayeredCrossSection_layermaterials); @@ -927,23 +1263,25 @@ void LayeredCrossSection :: giveInputRecord(DynamicInputRecord &input) input.setField(this->layerWidths, _IFT_LayeredCrossSection_widths); input.setField(this->layerRots, _IFT_LayeredCrossSection_layerRotations); input.setField(this->interfacerMaterials, _IFT_LayeredCrossSection_interfacematerials); - input.setField(this->numberOfIntegrationPoints, _IFT_LayeredCrossSection_nintegrationpoints); + input.setField(this->layerIntegrationPoints, _IFT_LayeredCrossSection_nlayerintegrationpoints); input.setField(this->midSurfaceZcoordFromBottom, _IFT_LayeredCrossSection_midsurf); } -void LayeredCrossSection :: createMaterialStatus(GaussPoint &iGP) +void LayeredCrossSection::createMaterialStatus(GaussPoint &iGP) { for ( int i = 1; i <= numberOfLayers; i++ ) { - GaussPoint *layerGp = giveSlaveGaussPoint(& iGP, i - 1); - StructuralMaterial *mat = static_cast< StructuralMaterial * >( domain->giveMaterial( this->giveLayerMaterial(i) ) ); - MaterialStatus *matStat = mat->CreateStatus(layerGp); - layerGp->setMaterialStatus(matStat); + for ( int k = 0; k < layerIntegrationPoints.at(i); k++ ) { + GaussPoint *layerGp = giveSlaveGaussPoint(& iGP, i - 1, k); + StructuralMaterial *mat = static_cast< StructuralMaterial * >( domain->giveMaterial(this->giveLayerMaterial(i) ) ); + MaterialStatus *matStat = mat->CreateStatus(layerGp); + layerGp->setMaterialStatus(matStat); + } } } void -LayeredCrossSection :: setupLayerMidPlanes() +LayeredCrossSection::setupLayerMidPlanes() { // z-coord of each layer midplane measured from the global cross section z-coord this->layerMidZ.resize(this->numberOfLayers); @@ -957,28 +1295,28 @@ LayeredCrossSection :: setupLayerMidPlanes() Material * -LayeredCrossSection :: giveMaterial(IntegrationPoint *ip) +LayeredCrossSection::giveMaterial(IntegrationPoint *ip) const { ///@todo We should keep track in integration point (integration rule) what material from layer is assigned. Otherwise difficulties due to different elements and IP numbering. if ( ip->giveIntegrationRule()->giveIntegrationDomain() == _Cube || - ip->giveIntegrationRule()->giveIntegrationDomain() == _Wedge - ) { - return domain->giveMaterial( layerMaterials.at(1) ); + ip->giveIntegrationRule()->giveIntegrationDomain() == _Wedge + ) { + return domain->giveMaterial(layerMaterials.at(1) ); //return this->domain->giveMaterial( this->giveLayerMaterial(ip->giveNumber()) ); } - - if (ip->hasSlaveGaussPoint()) { - return domain->giveMaterial( layerMaterials.at(1) );//virtual master, has no material assigned in input file + + if ( ip->hasSlaveGaussPoint() ) { + return domain->giveMaterial(layerMaterials.at(1) ); //virtual master, has no material assigned in input file } else { - return domain->giveMaterial( layerMaterials.at(1) );//virtual master, has no material assigned in input file + return domain->giveMaterial(layerMaterials.at(1) ); //virtual master, has no material assigned in input file //OOFEM_ERROR("Not implemented.") } - return NULL; + return nullptr; } int -LayeredCrossSection :: setupIntegrationPoints(IntegrationRule &irule, int npoints, Element *element) +LayeredCrossSection::setupIntegrationPoints(IntegrationRule &irule, int npoints, Element *element) { ///@todo We must send arrays for integration points instead of just a single scalar. if ( element->giveIntegrationDomain() == _Cube ) { @@ -988,7 +1326,7 @@ LayeredCrossSection :: setupIntegrationPoints(IntegrationRule &irule, int npoint element->giveMaterialMode(), this->layerThicks); #else - int points1 = ( int ) floor(cbrt( double ( npoints ) ) + 0.5); + int points1 = ( int ) floor(cbrt(double ( npoints ) ) + 0.5); // If numberOfIntegrationPoints > 0 then use that, otherwise use the element's default. return irule.SetUpPointsOnCubeLayers(points1, points1, this->numberOfIntegrationPoints ? numberOfIntegrationPoints : points1, element->giveMaterialMode(), this->layerThicks); @@ -1010,94 +1348,117 @@ LayeredCrossSection :: setupIntegrationPoints(IntegrationRule &irule, int npoint } #endif } else { - return irule.setUpIntegrationPoints( element->giveIntegrationDomain(), npoints, element->giveMaterialMode() ); + return irule.setUpIntegrationPoints(element->giveIntegrationDomain(), npoints, element->giveMaterialMode() ); } } int -LayeredCrossSection :: setupIntegrationPoints(IntegrationRule &irule, int nPointsXY, int nPointsZ, Element *element) +LayeredCrossSection::setupIntegrationPoints(IntegrationRule &irule, int nPointsXY, int nPointsZ, Element *element) { switch ( element->giveIntegrationDomain() ) { case _3dDegShell: return irule.SetUpPointsOn3dDegShellLayers(nPointsXY, nPointsZ, element->giveMaterialMode(), this->layerThicks); + default: - OOFEM_ERROR("Unknown mode (%d)", element->giveIntegrationDomain()); + OOFEM_ERROR( "Unknown mode (%d)", element->giveIntegrationDomain() ); } return 0; } + +int +LayeredCrossSection::giveSlaveGPIndex(int ilayer, int igp) const +{ + // slave gps stored at master in sequence + // need to take into account variable number of IPs per layer + int indx = 0; + // count number of gps in preceeding layers + for ( int i = 0; i < ilayer; i++ ) { + indx += layerIntegrationPoints(i); + } + indx += igp; + return indx; +} + + GaussPoint * -LayeredCrossSection :: giveSlaveGaussPoint(GaussPoint *masterGp, int i) +LayeredCrossSection::giveSlaveGaussPoint(GaussPoint *masterGp, int ilayer, int igp) const // // return the i-th slave gauss point of master gp // if slave gp don't exists - create them +// ilayer and igp numbered from 0 // { - GaussPoint *slave = masterGp->giveSlaveGaussPoint(i); - if ( slave == NULL ) { + auto slave = masterGp->giveSlaveGaussPoint( giveSlaveGPIndex(ilayer, igp) ); + if ( slave == nullptr ) { // check for proper dimensions - slave can be NULL if index too high or if not // slaves previously defined - if ( i > this->numberOfLayers ) { + if ( ilayer > this->numberOfLayers ) { OOFEM_ERROR("no such layer defined"); } // create new slave record in masterGp // (requires that this is friend of gp) - double currentZTopCoord, currentZCoord, bottom, top; - const FloatArray &masterCoords = masterGp->giveNaturalCoordinates(); + const auto &masterCoords = masterGp->giveNaturalCoordinates(); // resolve slave material mode - MaterialMode slaveMode, masterMode = masterGp->giveMaterialMode(); - slaveMode = this->giveCorrespondingSlaveMaterialMode(masterMode); + auto masterMode = masterGp->giveMaterialMode(); + auto slaveMode = this->giveCorrespondingSlaveMaterialMode(masterMode); - bottom = this->give(CS_BottomZCoord, masterGp); - top = this->give(CS_TopZCoord, masterGp); + double bottom = this->give(CS_BottomZCoord, masterGp); + double top = this->give(CS_TopZCoord, masterGp); ///@todo Generalize to multiple integration points per layer - masterGp->gaussPoints.resize( numberOfLayers ); - currentZTopCoord = -midSurfaceZcoordFromBottom; + int numberOfSlaves = 0; + for ( int i = 0; i < numberOfLayers; i++ ) { + numberOfSlaves += layerIntegrationPoints(i); + } + masterGp->gaussPoints.resize(numberOfSlaves); + // helper 1d rule + double currentZTopCoord = -midSurfaceZcoordFromBottom; for ( int j = 0; j < numberOfLayers; j++ ) { - FloatArray zCoord(3); + FloatArray sgpc( layerIntegrationPoints.at(j + 1) ); + FloatArray sgpw( layerIntegrationPoints.at(j + 1) ); + GaussIntegrationRule::giveLineCoordsAndWeights(layerIntegrationPoints.at(j + 1), sgpc, sgpw); + currentZTopCoord += this->layerThicks.at(j + 1); - currentZCoord = currentZTopCoord - this->layerThicks.at(j + 1) / 2.0; // z-coord of layer mid surface - if ( masterCoords.giveSize() > 0 ) { - zCoord.at(1) = masterCoords.at(1); // gp x-coord of mid surface - } + for ( int k = 0; k < layerIntegrationPoints.at(j + 1); k++ ) { + FloatArray zCoord(3); - if ( masterCoords.giveSize() > 1 ) { - zCoord.at(2) = masterCoords.at(2); // gp y-coord of mid surface - } + double currentZCoord = currentZTopCoord - this->layerThicks.at(j + 1) * ( 1 + sgpc(k) ) / 2.0; // z-coord of layer gp + if ( masterCoords.giveSize() > 0 ) { + zCoord.at(1) = masterCoords.at(1); // gp x-coord of mid surface + } + + if ( masterCoords.giveSize() > 1 ) { + zCoord.at(2) = masterCoords.at(2); // gp y-coord of mid surface + } - zCoord.at(3) = ( 2.0 * currentZCoord - top - bottom ) / ( top - bottom ); - // in gp - is stored isoparametric coordinate (-1,1) of z-coordinate - masterGp->gaussPoints [ j ] = new GaussPoint(masterGp->giveIntegrationRule(), j + 1, zCoord, 0., slaveMode); + zCoord.at(3) = ( 2.0 * currentZCoord - top - bottom ) / ( top - bottom ); + //printf("SGP %d: currentZTopCoord %e, currentZCoord %e\n", j*numberOfIntegrationPoints+k, currentZTopCoord, currentZCoord); + // in gp - is stored isoparametric coordinate (-1,1) of z-coordinate + masterGp->gaussPoints [ giveSlaveGPIndex(j, k) ] = new GaussPoint(masterGp->giveIntegrationRule(), j + 1, zCoord, sgpw(k) / 2.0, slaveMode); - // test - remove! -// masterGp->gaussPoints [ j ] = new GaussPoint(masterGp->giveIntegrationRule(), j + 1, zCoord, 1.0, slaveMode); + // test - remove! + // masterGp->gaussPoints [ j ] = new GaussPoint(masterGp->giveIntegrationRule(), j + 1, zCoord, 1.0, slaveMode); + } } - slave = masterGp->gaussPoints [ i ]; + slave = masterGp->gaussPoints [ giveSlaveGPIndex(ilayer, igp) ]; } return slave; } double -LayeredCrossSection :: computeIntegralThick() -// -// computes total thickness of receiver -// +LayeredCrossSection::computeIntegralThick() const { - if ( totalThick == 0 ) { - totalThick = layerThicks.sum(); - } - return totalThick; } void -LayeredCrossSection :: printYourself() +LayeredCrossSection::printYourself() // Prints the receiver on screen. { printf("Cross Section with properties: \n"); @@ -1115,66 +1476,42 @@ LayeredCrossSection :: printYourself() } -contextIOResultType -LayeredCrossSection :: saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *masterGp) -// -// saves full material context (saves state variables, that completely describe -// current state) -// stores also slaves records of master gp -// +void +LayeredCrossSection::saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *masterGp) { - contextIOResultType iores; - - if ( ( iores = CrossSection :: saveIPContext(stream, mode, masterGp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + CrossSection::saveIPContext(stream, mode, masterGp); // saved master gp record; - // and now save slave gp of master: for ( int i = 1; i <= numberOfLayers; i++ ) { - GaussPoint *slaveGP = this->giveSlaveGaussPoint(masterGp, i - 1); - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial( layerMaterials.at(i) ) ); - if ( ( iores = mat->saveIPContext(stream, mode, slaveGP) ) != CIO_OK ) { - THROW_CIOERR(iores); + for ( int k = 0; k < layerIntegrationPoints.at(i); k++ ) { + GaussPoint *slaveGP = this->giveSlaveGaussPoint(masterGp, i - 1, k); + StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial(layerMaterials.at(i) ) ); + mat->saveIPContext(stream, mode, slaveGP); } } - - return CIO_OK; } -contextIOResultType -LayeredCrossSection :: restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *masterGp) -// -// restores full material context (saves state variables, that completely describe -// current state) -// -// restores also slaves of master gp -// +void +LayeredCrossSection::restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *masterGp) { - contextIOResultType iores; - - if ( ( iores = CrossSection :: restoreIPContext(stream, mode, masterGp) ) != CIO_OK ) { - THROW_CIOERR(iores); // saved masterGp - } + CrossSection::restoreIPContext(stream, mode, masterGp); // and now save slave gp of master: for ( int i = 1; i <= numberOfLayers; i++ ) { - // creates also slaves if they don't exists - GaussPoint *slaveGP = this->giveSlaveGaussPoint(masterGp, i - 1); - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial( layerMaterials.at(i) ) ); - if ( ( iores = mat->restoreIPContext(stream, mode, slaveGP) ) != CIO_OK ) { - THROW_CIOERR(iores); + for ( int k = 0; k < layerIntegrationPoints.at(i); k++ ) { + // creates also slaves if they don't exists + GaussPoint *slaveGP = this->giveSlaveGaussPoint(masterGp, i - 1, k); + StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial(layerMaterials.at(i) ) ); + mat->restoreIPContext(stream, mode, slaveGP); } } - - return CIO_OK; } MaterialMode -LayeredCrossSection :: giveCorrespondingSlaveMaterialMode(MaterialMode masterMode) +LayeredCrossSection::giveCorrespondingSlaveMaterialMode(MaterialMode masterMode) // // returns corresponding slave material mode to master mode // @@ -1183,16 +1520,16 @@ LayeredCrossSection :: giveCorrespondingSlaveMaterialMode(MaterialMode masterMod return _PlateLayer; } else if ( masterMode == _2dBeam ) { return _2dBeamLayer; - } else if ( masterMode == _PlaneStress ) { - return _PlaneStress; - } else if ( masterMode == _3dShell ) { + } else if ( ( masterMode == _PlaneStress ) || ( masterMode == _PlaneStressRot ) ) { + return _PlaneStress; + } else if ( ( masterMode == _3dShell ) || ( masterMode == _3dShellRot ) ) { return _PlateLayer; } else if ( masterMode == _3dDegeneratedShell ) { return _3dDegeneratedShell; } else if ( masterMode == _3dMat ) { return _3dMat; } else { - OOFEM_ERROR("unsupported material mode %s", __MaterialModeToString(masterMode) ); + throw std::runtime_error("unsupported material mode"); } return _Unknown; @@ -1200,7 +1537,7 @@ LayeredCrossSection :: giveCorrespondingSlaveMaterialMode(MaterialMode masterMod double -LayeredCrossSection :: give(CrossSectionProperty aProperty, GaussPoint *gp) +LayeredCrossSection::give(CrossSectionProperty aProperty, GaussPoint *gp) const { if ( aProperty == CS_Thickness ) { return this->computeIntegralThick(); @@ -1213,35 +1550,33 @@ LayeredCrossSection :: give(CrossSectionProperty aProperty, GaussPoint *gp) return this->giveArea(); } else if ( aProperty == CS_NumLayers ) { return this->numberOfLayers; - //} else if (aProperty == CS_Layer ) { - // return this->giveLayer(gp); + //} else if (aProperty == CS_Layer ) { + // return this->giveLayer(gp); } - return CrossSection :: give(aProperty, gp); + return CrossSection::give(aProperty, gp); } -int -LayeredCrossSection :: giveLayer(GaussPoint *gp) //@todo: works only for equal thickness of each layer +int +LayeredCrossSection::giveLayer(GaussPoint *gp) const //@todo: works only for equal thickness of each layer { FloatArray lCoords; int noLayers = this->giveNumberOfLayers(); - double dh = 2.0/noLayers; + double dh = 2.0 / noLayers; lCoords = gp->giveNaturalCoordinates(); double lowXi = -1.0; - for (int i = 1; i <= noLayers; i++) - { - if (lCoords.at(3) > lowXi && lCoords.at(3) < lowXi+dh) - { + for ( int i = 1; i <= noLayers; i++ ) { + if ( lCoords.at(3) > lowXi && lCoords.at(3) < lowXi + dh ) { return i; } - lowXi+=dh; + lowXi += dh; } OOFEM_ERROR("LayeredCrossSection :: giveLayer - the actual integration point can not be associated with a layer in the cross section"); } double -LayeredCrossSection :: give(CrossSectionProperty aProperty, const FloatArray &coords, Element *elem, bool local) +LayeredCrossSection::give(CrossSectionProperty aProperty, const FloatArray &coords, Element *elem, bool local) const { if ( aProperty == CS_Thickness ) { return this->computeIntegralThick(); @@ -1256,31 +1591,27 @@ LayeredCrossSection :: give(CrossSectionProperty aProperty, const FloatArray &co return this->numberOfLayers; } - return CrossSection :: give(aProperty, coords, elem, local); + return CrossSection::give(aProperty, coords, elem, local); } int -LayeredCrossSection :: giveNumberOfLayers() +LayeredCrossSection::giveNumberOfLayers() const { return this->numberOfLayers; } double -LayeredCrossSection :: giveArea() +LayeredCrossSection::giveArea() const { - if ( this->area <= 0.0 ) { - this->area = this->layerThicks.dotProduct(this->layerWidths); - } - return area; } -bool LayeredCrossSection :: isCharacteristicMtrxSymmetric(MatResponseMode rMode) +bool LayeredCrossSection::isCharacteristicMtrxSymmetric(MatResponseMode rMode) const { for ( int i = 1; i <= this->numberOfLayers; i++ ) { - if ( !this->domain->giveMaterial( this->giveLayerMaterial(i) )->isCharacteristicMtrxSymmetric(rMode) ) { + if ( !this->domain->giveMaterial(this->giveLayerMaterial(i) )->isCharacteristicMtrxSymmetric(rMode) ) { return false; } } @@ -1289,7 +1620,7 @@ bool LayeredCrossSection :: isCharacteristicMtrxSymmetric(MatResponseMode rMode) void -LayeredCrossSection :: giveInterfaceXiCoords(FloatArray &answer) +LayeredCrossSection::giveInterfaceXiCoords(FloatArray &answer) const { // returns an array with the xi-coords corresponding to the boundaries where // the layers meet (size = number of layers -1) @@ -1305,7 +1636,7 @@ LayeredCrossSection :: giveInterfaceXiCoords(FloatArray &answer) } void -LayeredCrossSection :: setupLayeredIntegrationRule(std :: vector< std :: unique_ptr< IntegrationRule > > &integrationRulesArray, Element *el, int numInPlanePoints) +LayeredCrossSection::setupLayeredIntegrationRule(std::vector< std::unique_ptr< IntegrationRule > > &integrationRulesArray, Element *el, int numInPlanePoints) { // Loop over each layer and set up an integration rule as if each layer was an independent element // @todo - only works for wedge integration at the moment @@ -1313,9 +1644,9 @@ LayeredCrossSection :: setupLayeredIntegrationRule(std :: vector< std :: unique_ int numPointsThickness = this->giveNumIntegrationPointsInLayer(); integrationRulesArray.clear(); - integrationRulesArray.reserve( numberOfLayers ); + integrationRulesArray.reserve(numberOfLayers); for ( int i = 0; i < numberOfLayers; i++ ) { - integrationRulesArray.emplace_back( new LayeredIntegrationRule(i + 1, el) ); + integrationRulesArray.emplace_back(new LayeredIntegrationRule(i + 1, el) ); integrationRulesArray.back()->SetUpPointsOnWedge(numInPlanePoints, numPointsThickness, _3dMat); } this->mapLayerGpCoordsToShellCoords(integrationRulesArray); @@ -1323,7 +1654,7 @@ LayeredCrossSection :: setupLayeredIntegrationRule(std :: vector< std :: unique_ void -LayeredCrossSection :: mapLayerGpCoordsToShellCoords(std :: vector< std :: unique_ptr< IntegrationRule > > &layerIntegrationRulesArray) +LayeredCrossSection::mapLayerGpCoordsToShellCoords(std::vector< std::unique_ptr< IntegrationRule > > &layerIntegrationRulesArray) /* * Maps the local xi-coord (z-coord) in each layer [-1,1] to the corresponding * xi-coord in the cross section coordinate system. @@ -1342,8 +1673,7 @@ LayeredCrossSection :: mapLayerGpCoordsToShellCoords(std :: vector< std :: uniqu double totalThickness = this->computeIntegralThick(); int number = 1; for ( int layer = 1; layer <= numberOfLayers; layer++ ) { - for ( GaussPoint *gp: *layerIntegrationRulesArray [ layer - 1 ] ) { - + for ( GaussPoint *gp: * layerIntegrationRulesArray [ layer - 1 ] ) { // Map local layer cs to local shell cs double zMid_i = this->giveLayerMidZ(layer); // global z-coord double xiMid_i = 1.0 - 2.0 * ( totalThickness - this->midSurfaceZcoordFromBottom - zMid_i ) / totalThickness; // local z-coord @@ -1359,30 +1689,28 @@ LayeredCrossSection :: mapLayerGpCoordsToShellCoords(std :: vector< std :: uniqu } -LayeredIntegrationRule :: LayeredIntegrationRule(int n, Element *e, - int startIndx, int endIndx, bool dynamic) : +LayeredIntegrationRule::LayeredIntegrationRule(int n, Element *e, + int startIndx, int endIndx, bool dynamic) : IntegrationRule(n, e, startIndx, endIndx, dynamic) { } -LayeredIntegrationRule :: LayeredIntegrationRule(int n, Element *e) : +LayeredIntegrationRule::LayeredIntegrationRule(int n, Element *e) : IntegrationRule(n, e) { } -LayeredIntegrationRule :: ~LayeredIntegrationRule() -{ } int -LayeredIntegrationRule :: SetUpPointsOnWedge(int nPointsTri, int nPointsThickness, MaterialMode mode) +LayeredIntegrationRule::SetUpPointsOnWedge(int nPointsTri, int nPointsThickness, MaterialMode mode) { // Set up integration rule for a specific layer int nPoints = nPointsTri * nPointsThickness; //@todo - is not really a Gauss point but rather a hybrid. - this->gaussPoints.resize( nPoints ); + this->gaussPoints.resize(nPoints); // uses Gauss integration in the plane and Lobatto in the thickness FloatArray coords_xi1, coords_xi2, coords_xi, weights_tri, weights_thickness; - GaussIntegrationRule :: giveTriCoordsAndWeights(nPointsTri, coords_xi1, coords_xi2, weights_tri); + GaussIntegrationRule::giveTriCoordsAndWeights(nPointsTri, coords_xi1, coords_xi2, weights_tri); //LobattoIntegrationRule :: giveLineCoordsAndWeights(nPointsThickness, coords_xi, weights_thickness ); - GaussIntegrationRule :: giveLineCoordsAndWeights(nPointsThickness, coords_xi, weights_thickness); + GaussIntegrationRule::giveLineCoordsAndWeights(nPointsThickness, coords_xi, weights_thickness); // Assumes that the integration rules of the layers are the same such that the ordering of the ip's are also // the same => upperInterfacePoints.at(i) of one layer is paired with lowerInterfacePoints.at(i) of the next. @@ -1395,8 +1723,8 @@ LayeredIntegrationRule :: SetUpPointsOnWedge(int nPointsTri, int nPointsThicknes for ( int i = 1, ind = 0; i <= nPointsThickness; i++ ) { for ( int j = 1; j <= nPointsTri; j++ ) { this->gaussPoints [ ind ] = - new GaussPoint(this, 1, {coords_xi1.at(j), coords_xi2.at(j), coords_xi.at(i)}, - weights_tri.at ( j ) *weights_thickness.at ( i ), mode); + new GaussPoint(this, 1, { coords_xi1.at(j), coords_xi2.at(j), coords_xi.at(i) }, + weights_tri.at(j) * weights_thickness.at(i), mode); // store interface points if ( i == 1 && nPointsThickness > 1 ) { //then lower surface @@ -1412,7 +1740,7 @@ LayeredIntegrationRule :: SetUpPointsOnWedge(int nPointsTri, int nPointsThicknes int -LayeredCrossSection :: checkConsistency() +LayeredCrossSection::checkConsistency() // // check internal consistency // mainly tests, whether material and crossSection data @@ -1421,9 +1749,9 @@ LayeredCrossSection :: checkConsistency() { int result = 1; for ( int i = 1; this->giveNumberOfLayers(); i++ ) { - Material *mat = this->giveDomain()->giveMaterial( this->giveLayerMaterial(i) ); - if ( !dynamic_cast< StructuralMaterial * >(mat) ) { - OOFEM_WARNING("material %s without structural support", mat->giveClassName() ); + Material *mat = this->giveDomain()->giveMaterial(this->giveLayerMaterial(i) ); + if ( !dynamic_cast< StructuralMaterial * >( mat ) ) { + OOFEM_WARNING( "material %s without structural support", mat->giveClassName() ); result = 0; continue; } @@ -1433,7 +1761,7 @@ LayeredCrossSection :: checkConsistency() int -LayeredCrossSection :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +LayeredCrossSection::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { if ( gp->giveIntegrationRule()->giveIntegrationDomain() == _Cube || gp->giveIntegrationRule()->giveIntegrationDomain() == _Wedge ) { // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints) @@ -1441,7 +1769,7 @@ LayeredCrossSection :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalS int gpnum = gp->giveNumber(); int gpsperlayer = ngps / this->numberOfLayers; int layer = ( gpnum - 1 ) / gpsperlayer + 1; - Material *layerMat = this->domain->giveMaterial( this->giveLayerMaterial(layer) ); + Material *layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) ); if ( this->layerRots.at(layer) != 0. ) { FloatArray rotVal; // the requested value in the material c.s. InternalStateValueType valType = giveInternalStateValueType(type); @@ -1457,25 +1785,25 @@ LayeredCrossSection :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalS // Determine how to rotate it according to the value type if ( valType == ISVT_TENSOR_S3 ) { answer = { - c *c * rotVal.at(1) + 2 * c * s * rotVal.at(6) + s * s * rotVal.at(2), - c * c * rotVal.at(2) - 2 * c * s * rotVal.at(6) + s * s * rotVal.at(1), + c *c *rotVal.at(1) + 2 * c * s * rotVal.at(6) + s * s * rotVal.at(2), + c *c *rotVal.at(2) - 2 * c * s * rotVal.at(6) + s * s * rotVal.at(1), rotVal.at(3), - c * rotVal.at(4) - s * rotVal.at(5), - c * rotVal.at(5) + s * rotVal.at(4), + c *rotVal.at(4) - s * rotVal.at(5), + c *rotVal.at(5) + s * rotVal.at(4), ( c * c - s * s ) * rotVal.at(6) - c * s * ( rotVal.at(1) - rotVal.at(2) ), }; } else if ( valType == ISVT_TENSOR_S3E ) { answer = { - c *c * rotVal.at(1) + c * s * rotVal.at(6) + s * s * rotVal.at(2), - c * c * rotVal.at(2) - c * s * rotVal.at(6) + s * s * rotVal.at(1), + c *c *rotVal.at(1) + c * s * rotVal.at(6) + s * s * rotVal.at(2), + c *c *rotVal.at(2) - c * s * rotVal.at(6) + s * s * rotVal.at(1), rotVal.at(3), - c * rotVal.at(4) - s * rotVal.at(5), - c * rotVal.at(5) + s * rotVal.at(4), + c *rotVal.at(4) - s * rotVal.at(5), + c *rotVal.at(5) + s * rotVal.at(4), ( c * c - s * s ) * rotVal.at(6) - 2 * c * s * ( rotVal.at(1) - rotVal.at(2) ), }; } else if ( valType == ISVT_VECTOR ) { answer = { - c *rotVal.at(1) - s * rotVal.at(2), s * rotVal.at(1) +c * rotVal.at(2), rotVal.at(3) + c *rotVal.at(1) - s * rotVal.at(2), s *rotVal.at(1) + c * rotVal.at(2), rotVal.at(3) }; } else if ( valType == ISVT_SCALAR ) { answer = rotVal; @@ -1491,20 +1819,29 @@ LayeredCrossSection :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalS ///@todo so far this only works for elements where each layer has its own integration rule int layer = gp->giveIntegrationRule()->giveNumber(); - return this->giveDomain()->giveMaterial( this->giveLayerMaterial(layer) )->giveIPValue(answer, gp, type, tStep); + return this->giveDomain()->giveMaterial(this->giveLayerMaterial(layer) )->giveIPValue(answer, gp, type, tStep); } } double -LayeredCrossSection :: give(int aProperty, GaussPoint* gp) +LayeredCrossSection::give(int aProperty, GaussPoint *gp) const { - double average = 0.; - for ( int layer = 1; layer <= numberOfLayers; ++layer ) { - Material *mat = this->giveDomain()->giveMaterial( giveLayerMaterial(layer) ); - average += mat->give(aProperty, gp) * giveLayerThickness(layer); + if ( gp->giveIntegrationRule()->giveIntegrationDomain() == _Cube || gp->giveIntegrationRule()->giveIntegrationDomain() == _Wedge ) { + // Determine which layer the gp belongs to. This code assumes that the gauss point are created consistently (through CrossSection::setupIntegrationPoints) + int ngps = gp->giveIntegrationRule()->giveNumberOfIntegrationPoints(); + int gpnum = gp->giveNumber(); + int gpsperlayer = ngps / this->numberOfLayers; + int layer = ( gpnum - 1 ) / gpsperlayer + 1; + Material *layerMat = this->domain->giveMaterial(this->giveLayerMaterial(layer) ); + return layerMat->give(aProperty, gp); + } else { + double average = 0.; + for ( int layer = 1; layer <= numberOfLayers; ++layer ) { + Material *mat = this->giveDomain()->giveMaterial(giveLayerMaterial(layer) ); + average += mat->give(aProperty, gp) * giveLayerThickness(layer); + } + return average / this->totalThick; } - return average / this->totalThick; } - } // end namespace oofem diff --git a/src/sm/CrossSections/layeredcrosssection.h b/src/sm/CrossSections/layeredcrosssection.h index 67d114740..1a2407d06 100644 --- a/src/sm/CrossSections/layeredcrosssection.h +++ b/src/sm/CrossSections/layeredcrosssection.h @@ -35,7 +35,7 @@ #ifndef layeredcrosssection_h #define layeredcrosssection_h -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "floatarray.h" #include "floatmatrix.h" #include "interface.h" @@ -56,7 +56,9 @@ #define _IFT_LayeredCrossSection_widths "widths" #define _IFT_LayeredCrossSection_midsurf "midsurf" #define _IFT_LayeredCrossSection_nintegrationpoints "nintegrationpoints" +#define _IFT_LayeredCrossSection_nlayerintegrationpoints "layerintegrationpoints" #define _IFT_LayeredCrossSection_initiationlimits "initiationlimits" +#define _IFT_LayeredCrossSection_shearcoeff_xz "beamshearcoeffxz" //@} namespace oofem { @@ -97,30 +99,26 @@ class LayeredCrossSection : public StructuralCrossSection FloatArray layerWidths; ///< Width for each layer. FloatArray layerMidZ; ///< z-coord of the mid plane for each layer FloatArray layerRots; ///< Rotation of the material in each layer. - int numberOfLayers; - int numberOfIntegrationPoints; ///< num integration points per layer - double midSurfaceZcoordFromBottom; - double midSurfaceXiCoordFromBottom; - double totalThick; - double area; - + int numberOfLayers = 0; + int numberOfIntegrationPoints = 1; ///< number of integration points per layer (for 3D elements) + IntArray layerIntegrationPoints; + double midSurfaceZcoordFromBottom = 0.; + double midSurfaceXiCoordFromBottom = 0.; + double totalThick = 0.; + double area = 0.; + double beamShearCoeffxz = 1.0; public: - LayeredCrossSection(int n, Domain * d) : StructuralCrossSection(n, d), layerMaterials(), layerThicks(), layerWidths() - { - numberOfLayers = 0; - totalThick = 0.; - area = -1.0; - } + LayeredCrossSection(int n, Domain *d) : + StructuralCrossSection(n, d) + { } - virtual ~LayeredCrossSection() { } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - - virtual void createMaterialStatus(GaussPoint &iGP); // ES + void createMaterialStatus(GaussPoint &iGP) override; //Create slave integration points - virtual int setupIntegrationPoints(IntegrationRule &irule, int npoints, Element *element); + int setupIntegrationPoints(IntegrationRule &irule, int npoints, Element *element) override; /** * Sets up integration rule for the given element. * Default behavior is just to call the Gauss integration rule, but for example the layered and fibered crosssections need to do their own thing. @@ -130,57 +128,58 @@ class LayeredCrossSection : public StructuralCrossSection * @param element Element which the integration rule belongs to. * @return Number of integration points. */ - virtual int setupIntegrationPoints(IntegrationRule &irule, int npointsXY, int npointsZ, Element *element); - - virtual void giveRealStress_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_3dDegeneratedShell(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_Warping(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - - virtual void giveStiffnessMatrix_3d(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveStiffnessMatrix_PlaneStress(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveStiffnessMatrix_PlaneStrain(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveStiffnessMatrix_1d(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - - - virtual void giveGeneralizedStress_Beam2d(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_Beam3d(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_Plate(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_Shell(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_MembraneRot(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_PlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - - virtual void giveCharMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode mode); - - virtual void give2dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give2dPlateStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dShellStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dDegeneratedShellStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void giveMembraneRotStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - - virtual FloatArray *imposeStressConstrainsOnGradient(GaussPoint *gp, FloatArray *); - virtual FloatArray *imposeStrainConstrainsOnGradient(GaussPoint *gp, FloatArray *); - - virtual double give(CrossSectionProperty a, GaussPoint *gp); - virtual double give(CrossSectionProperty a, const FloatArray &coords, Element *elem, bool local); - int giveNumberOfLayers(); - int giveLayer(GaussPoint *gp); + int setupIntegrationPoints(IntegrationRule &irule, int npointsXY, int npointsZ, Element *element) override; + + FloatArrayF< 6 >giveRealStress_3d(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 6 >giveRealStress_3dDegeneratedShell(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 4 >giveRealStress_PlaneStrain(const FloatArrayF< 4 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 3 >giveRealStress_PlaneStress(const FloatArrayF< 3 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 1 >giveRealStress_1d(const FloatArrayF< 1 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 2 >giveRealStress_Warping(const FloatArrayF< 2 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + + FloatMatrixF< 6, 6 >giveStiffnessMatrix_3d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 3, 3 >giveStiffnessMatrix_PlaneStress(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 4, 4 >giveStiffnessMatrix_PlaneStrain(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 1, 1 >giveStiffnessMatrix_1d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatArrayF< 3 >giveGeneralizedStress_Beam2d(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 6 >giveGeneralizedStress_Beam3d(const FloatArrayF< 6 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 5 >giveGeneralizedStress_Plate(const FloatArrayF< 5 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 8 >giveGeneralizedStress_Shell(const FloatArrayF< 8 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 9 >giveGeneralizedStress_ShellRot(const FloatArrayF< 9 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 4 >giveGeneralizedStress_MembraneRot(const FloatArrayF< 4 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 3 >giveGeneralizedStress_PlateSubSoil(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + + void giveCharMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + + bool isCharacteristicMtrxSymmetric(MatResponseMode mode) const override; + + FloatMatrixF< 3, 3 >give2dBeamStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 6, 6 >give3dBeamStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 5, 5 >give2dPlateStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 8, 8 >give3dShellStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 9, 9 >give3dShellRotStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 6, 6 >give3dDegeneratedShellStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 4, 4 >giveMembraneRotStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 3, 3 >give2dPlateSubSoilStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatArray *imposeStressConstrainsOnGradient(GaussPoint *gp, FloatArray *) override; + FloatArray *imposeStrainConstrainsOnGradient(GaussPoint *gp, FloatArray *) override; + + double give(CrossSectionProperty a, GaussPoint *gp) const override; + double give(CrossSectionProperty a, const FloatArray &coords, Element *elem, bool local) const override; + int giveNumberOfLayers() const; + int giveLayer(GaussPoint *gp) const; /// Returns the total thickness of all layers. - double computeIntegralThick(); + double computeIntegralThick() const; void setupLayerMidPlanes(); - int giveLayerMaterial(int layer) { + int giveLayerMaterial(int layer) const { return this->layerMaterials.at(layer); } - virtual Material *giveMaterial(IntegrationPoint *ip); + Material *giveMaterial(IntegrationPoint *ip) const override; int giveInterfaceMaterialNum(int interface) { return this->interfacerMaterials.at(interface); @@ -189,82 +188,91 @@ class LayeredCrossSection : public StructuralCrossSection Material *giveInterfaceMaterial(int interface) { int matNum = this->giveInterfaceMaterialNum(interface); if ( matNum ) { - return this->giveDomain()->giveMaterial( this->interfacerMaterials.at(interface) ); + return this->giveDomain()->giveMaterial(this->interfacerMaterials.at(interface) ); } else { - return NULL; + return nullptr; } } - virtual int checkConsistency(); + int checkConsistency() override; - double giveLayerMidZ(int layer) { + double giveLayerMidZ(int layer) const { // Gives the z-coord measured from the geometric midplane of the (total) cross section. return this->layerMidZ.at(layer); } - double giveLayerThickness(int layer) { + double giveLayerThickness(int layer) const { return this->layerThicks.at(layer); } - int giveNumIntegrationPointsInLayer() { + int giveNumIntegrationPointsInLayer() const { return this->numberOfIntegrationPoints; } - double giveMidSurfaceZcoordFromBottom() { + double giveMidSurfaceZcoordFromBottom() const { return this->midSurfaceZcoordFromBottom; } - double giveMidSurfaceXiCoordFromBottom() { + double giveMidSurfaceXiCoordFromBottom() const { return this->midSurfaceXiCoordFromBottom; } - void giveInterfaceXiCoords(FloatArray &answer); + void giveInterfaceXiCoords(FloatArray &answer) const; // identification and auxiliary functions - virtual const char *giveInputRecordName() const { return _IFT_LayeredCrossSection_Name; } - virtual const char *giveClassName() const { return "LayeredCrossSection"; } - virtual void printYourself(); + const char *giveInputRecordName() const override { return _IFT_LayeredCrossSection_Name; } + const char *giveClassName() const override { return "LayeredCrossSection"; } + void printYourself() override; - MaterialMode giveCorrespondingSlaveMaterialMode(MaterialMode mode); - GaussPoint *giveSlaveGaussPoint(GaussPoint *gp, int slaveIndex); + static MaterialMode giveCorrespondingSlaveMaterialMode(MaterialMode mode); + GaussPoint *giveSlaveGaussPoint(GaussPoint *gp, int layer, int igp) const; - virtual contextIOResultType saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); - virtual contextIOResultType restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); + void saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override; + void restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override; - void mapLayerGpCoordsToShellCoords(std :: vector< std :: unique_ptr< IntegrationRule > > &layerIntegrationRulesArray); + void mapLayerGpCoordsToShellCoords(std::vector< std::unique_ptr< IntegrationRule > > &layerIntegrationRulesArray); - void setupLayeredIntegrationRule(std :: vector< std :: unique_ptr< IntegrationRule > > &layerIntegrationRulesArray, Element *el, int numInPlanePoints); + void setupLayeredIntegrationRule(std::vector< std::unique_ptr< IntegrationRule > > &layerIntegrationRulesArray, Element *el, int numInPlanePoints); - virtual int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep); - virtual double give(int aProperty, GaussPoint *gp); + int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep) override; + double give(int aProperty, GaussPoint *gp) const override; - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override { OOFEM_ERROR("not implemented"); return 0; } - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override { OOFEM_ERROR("not implemented"); return 0; } - virtual int estimatePackSize(DataStream &buff, GaussPoint *ip) + int estimatePackSize(DataStream &buff, GaussPoint *ip) override { OOFEM_ERROR("not implemented"); return 0; } - virtual void giveFirstPKStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedFIncrement, TimeStep *tStep) - { OOFEM_ERROR("not implemented"); } - virtual void giveCauchyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedFIncrement, TimeStep *tStep) - { OOFEM_ERROR("not implemented"); } - virtual void giveStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + + FloatArrayF< 9 >giveFirstPKStress_3d(const FloatArrayF< 9 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 5 >giveFirstPKStress_PlaneStrain(const FloatArrayF< 5 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 4 >giveFirstPKStress_PlaneStress(const FloatArrayF< 4 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 1 >giveFirstPKStress_1d(const FloatArrayF< 1 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const override; + + + void giveCharMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + FloatMatrixF< 9, 9 >giveStiffnessMatrix_dPdF_3d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 5, 5 >giveStiffnessMatrix_dPdF_PlaneStrain(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 4, 4 >giveStiffnessMatrix_dPdF_PlaneStress(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 1, 1 >giveStiffnessMatrix_dPdF_1d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + void giveCauchyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedFIncrement, TimeStep *tStep) override { OOFEM_ERROR("not implemented"); } - virtual void giveStiffnessMatrix_dCde(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + void giveStiffnessMatrix_dCde(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("not implemented"); } - protected: - double giveArea(); + double giveArea() const; + int giveSlaveGPIndex(int ilayer, int igp) const; }; /** @@ -290,12 +298,10 @@ class LayeredCrossSectionInterface : public Interface class LayeredIntegrationRule : public IntegrationRule { public: - LayeredIntegrationRule(int n, Element * e, int startIndx, int endIndx, bool dynamic = false); - LayeredIntegrationRule(int n, Element * e); - virtual ~LayeredIntegrationRule(); + LayeredIntegrationRule(int n, Element *e, int startIndx, int endIndx, bool dynamic = false); + LayeredIntegrationRule(int n, Element *e); - virtual const char *giveClassName() const { return "LayeredIntegrationRule"; } - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } + const char *giveClassName() const override { return "LayeredIntegrationRule"; } //virtual int getRequiredNumberOfIntegrationPoints(integrationDomain dType, int approxOrder); @@ -303,9 +309,9 @@ class LayeredIntegrationRule : public IntegrationRule // Thus they will correspond to points lying on the interface between layers. IntArray lowerInterfacePoints, upperInterfacePoints; - //virtual int SetUpPointsOnLine(int, MaterialMode); // could be used for beams - //virtual int SetUpPointsOnCube(int, MaterialMode mode); // could be used for plates/shells/solids - virtual int SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, MaterialMode mode); + //int SetUpPointsOnLine(int, MaterialMode) override; // could be used for beams + //int SetUpPointsOnCube(int, MaterialMode mode) override; // could be used for plates/shells/solids + int SetUpPointsOnWedge(int nPointsTri, int nPointsDepth, MaterialMode mode) override; }; } // end namespace oofem #endif // layeredcrosssection_h diff --git a/src/sm/CrossSections/simplecrosssection.C b/src/sm/CrossSections/simplecrosssection.C index 38ed697f1..995a2cd8a 100644 --- a/src/sm/CrossSections/simplecrosssection.C +++ b/src/sm/CrossSections/simplecrosssection.C @@ -32,104 +32,108 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/CrossSections/simplecrosssection.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/CrossSections/simplecrosssection.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Elements/structuralelement.h" #include "gausspoint.h" #include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "classfactory.h" #include "dynamicinputrecord.h" +#include "datastream.h" +#include "contextioerr.h" #include "engngm.h" namespace oofem { REGISTER_CrossSection(SimpleCrossSection); -void -SimpleCrossSection :: giveRealStress_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 6 > +SimpleCrossSection::giveRealStress_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->giveRealStressVector_3d(answer, gp, strain, tStep); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->giveRealStressVector_3d(strain, gp, tStep); } -void -SimpleCrossSection :: giveRealStress_3dDegeneratedShell(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 6 > +SimpleCrossSection::giveRealStress_3dDegeneratedShell(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); IntArray strainControl = { 1, 2, 4, 5, 6 }; - mat->giveRealStressVector_ShellStressControl(answer, gp, strain, strainControl, tStep); + return mat->giveRealStressVector_ShellStressControl(strain, strainControl, gp, tStep); } -void -SimpleCrossSection :: giveRealStress_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 4 > +SimpleCrossSection::giveRealStress_PlaneStrain(const FloatArrayF< 4 > &strain, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->giveRealStressVector_PlaneStrain(answer, gp, strain, tStep); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->giveRealStressVector_PlaneStrain(strain, gp, tStep); } -void -SimpleCrossSection :: giveRealStress_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 3 > +SimpleCrossSection::giveRealStress_PlaneStress(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->giveRealStressVector_PlaneStress(answer, gp, strain, tStep); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->giveRealStressVector_PlaneStress(strain, gp, tStep); } -void -SimpleCrossSection :: giveRealStress_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 1 > +SimpleCrossSection::giveRealStress_1d(const FloatArrayF< 1 > &strain, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->giveRealStressVector_1d(answer, gp, strain, tStep); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->giveRealStressVector_1d(strain, gp, tStep); } -void -SimpleCrossSection :: giveRealStress_Warping(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 2 > +SimpleCrossSection::giveRealStress_Warping(const FloatArrayF< 2 > &strain, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->giveRealStressVector_Warping(answer, gp, strain, tStep); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->giveRealStressVector_Warping(strain, gp, tStep); } -void -SimpleCrossSection :: giveStiffnessMatrix_3d(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 6, 6 > +SimpleCrossSection::giveStiffnessMatrix_3d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->give3dMaterialStiffnessMatrix(answer, rMode, gp, tStep); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->give3dMaterialStiffnessMatrix(rMode, gp, tStep); } -void -SimpleCrossSection :: giveStiffnessMatrix_PlaneStress(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 3, 3 > +SimpleCrossSection::giveStiffnessMatrix_PlaneStress(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->givePlaneStressStiffMtrx(answer, rMode, gp, tStep); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->givePlaneStressStiffMtrx(rMode, gp, tStep); } -void -SimpleCrossSection :: giveStiffnessMatrix_PlaneStrain(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 4, 4 > +SimpleCrossSection::giveStiffnessMatrix_PlaneStrain(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->givePlaneStrainStiffMtrx(answer, rMode, gp, tStep); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->givePlaneStrainStiffMtrx(rMode, gp, tStep); } -void -SimpleCrossSection :: giveStiffnessMatrix_1d(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 1, 1 > +SimpleCrossSection::giveStiffnessMatrix_1d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->give1dStressStiffMtrx(answer, rMode, gp, tStep); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->give1dStressStiffMtrx(rMode, gp, tStep); } -void -SimpleCrossSection :: giveGeneralizedStress_Beam2d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 3 > +SimpleCrossSection::giveGeneralizedStress_Beam2d(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) const { /**Note: (by bp): This assumes that the behaviour is elastic * there exist a nuumber of nonlinear integral material models for beams defined directly in terms of integral forces and moments and corresponding @@ -138,44 +142,45 @@ SimpleCrossSection :: giveGeneralizedStress_Beam2d(FloatArray &answer, GaussPoin * This cross-section assumes you can split the response into inertia moments and pure material response. This is only possible for a constant, elastic response (i.e. elastic). * Therefore, this cross-section may only be allowed to give the elastic response. */ - StructuralMaterial *mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - FloatArray elasticStrain, et, e0; - FloatMatrix tangent; - elasticStrain = strain; + auto mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + auto elasticStrain = strain; + FloatArray et; this->giveTemperatureVector(et, gp, tStep); if ( et.giveSize() > 0 ) { - mat->giveThermalDilatationVector(e0, gp, tStep); + auto e0 = mat->giveThermalDilatationVector(gp, tStep); double thick = this->give(CS_Thickness, gp); elasticStrain.at(1) -= e0.at(1) * ( et.at(1) - mat->giveReferenceTemperature() ); if ( et.giveSize() > 1 ) { elasticStrain.at(2) -= e0.at(1) * et.at(2) / thick; // kappa_x } } - this->give2dBeamStiffMtrx(tangent, ElasticStiffness, gp, tStep); - answer.beProductOf(tangent, elasticStrain); - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) ); + auto tangent = this->give2dBeamStiffMtrx(ElasticStiffness, gp, tStep); + auto answer = dot(tangent, elasticStrain); + + auto status = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) ); status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); + + return answer; } -void -SimpleCrossSection :: giveGeneralizedStress_Beam3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 6 > +SimpleCrossSection::giveGeneralizedStress_Beam3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const { /**Note: (by bp): This assumes that the behaviour is elastic * there exist a nuumber of nonlinear integral material models for beams defined directly in terms of integral forces and moments and corresponding * deformations and curvatures. This would require to implement support at material model level. * Mikael: See earlier response to comment */ - StructuralMaterial *mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - FloatArray elasticStrain, et, e0; - FloatMatrix tangent; - elasticStrain = strain; + auto mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + auto elasticStrain = strain; + FloatArray et; this->giveTemperatureVector(et, gp, tStep); if ( et.giveSize() > 0 ) { double thick = this->give(CS_Thickness, gp); double width = this->give(CS_Width, gp); - mat->giveThermalDilatationVector(e0, gp, tStep); + auto e0 = mat->giveThermalDilatationVector(gp, tStep); elasticStrain.at(1) -= e0.at(1) * ( et.at(1) - mat->giveReferenceTemperature() ); if ( et.giveSize() > 1 ) { elasticStrain.at(5) -= e0.at(1) * et.at(2) / thick; // kappa_y @@ -184,16 +189,19 @@ SimpleCrossSection :: giveGeneralizedStress_Beam3d(FloatArray &answer, GaussPoin } } } - this->give3dBeamStiffMtrx(tangent, ElasticStiffness, gp, tStep); - answer.beProductOf(tangent, elasticStrain); - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) ); + auto tangent = this->give3dBeamStiffMtrx(ElasticStiffness, gp, tStep); + auto answer = dot(tangent, elasticStrain); + + auto status = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) ); status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); + + return answer; } -void -SimpleCrossSection :: giveGeneralizedStress_Plate(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 5 > +SimpleCrossSection::giveGeneralizedStress_Plate(const FloatArrayF< 5 > &strain, GaussPoint *gp, TimeStep *tStep) const { /**Note: (by bp): This assumes that the behaviour is elastic * there exist a number of nonlinear integral material models for beams/plates/shells @@ -201,29 +209,31 @@ SimpleCrossSection :: giveGeneralizedStress_Plate(FloatArray &answer, GaussPoint * deformations and curvatures. This would require to implement support at material model level. * Mikael: See earlier response to comment */ - StructuralMaterial *mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - FloatArray elasticStrain, et, e0; - FloatMatrix tangent; - elasticStrain = strain; - this->giveTemperatureVector(et, gp, tStep); + auto mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + auto elasticStrain = strain; + FloatArray et; + this->giveTemperatureVector(et, gp, tStep); // FIXME use return channel, maybe fixed size/std::pair? if ( et.giveSize() > 0 ) { double thick = this->give(CS_Thickness, gp); - mat->giveThermalDilatationVector(e0, gp, tStep); + auto e0 = mat->giveThermalDilatationVector(gp, tStep); if ( et.giveSize() > 1 ) { elasticStrain.at(1) -= e0.at(1) * et.at(2) / thick; // kappa_x elasticStrain.at(2) -= e0.at(2) * et.at(2) / thick; // kappa_y } } - this->give2dPlateStiffMtrx(tangent, ElasticStiffness, gp, tStep); - answer.beProductOf(tangent, elasticStrain); - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) ); + auto tangent = this->give2dPlateStiffMtrx(ElasticStiffness, gp, tStep); + auto answer = dot(tangent, elasticStrain); + + auto status = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) ); status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); + + return answer; } -void -SimpleCrossSection :: giveGeneralizedStress_Shell(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 8 > +SimpleCrossSection::giveGeneralizedStress_Shell(const FloatArrayF< 8 > &strain, GaussPoint *gp, TimeStep *tStep) const { /**Note: (by bp): This assumes that the behaviour is elastic * there exist a nuumber of nonlinear integral material models for beams/plates/shells @@ -231,14 +241,13 @@ SimpleCrossSection :: giveGeneralizedStress_Shell(FloatArray &answer, GaussPoint * deformations and curvatures. This would require to implement support at material model level. * Mikael: See earlier response to comment */ - StructuralMaterial *mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - FloatArray elasticStrain, et, e0; - FloatMatrix tangent; - elasticStrain = strain; + auto mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + auto elasticStrain = strain; + FloatArray et; this->giveTemperatureVector(et, gp, tStep); if ( et.giveSize() ) { double thick = this->give(CS_Thickness, gp); - mat->giveThermalDilatationVector(e0, gp, tStep); + auto e0 = mat->giveThermalDilatationVector(gp, tStep); elasticStrain.at(1) -= e0.at(1) * ( et.at(1) - mat->giveReferenceTemperature() ); elasticStrain.at(2) -= e0.at(2) * ( et.at(1) - mat->giveReferenceTemperature() ); if ( et.giveSize() > 1 ) { @@ -246,63 +255,95 @@ SimpleCrossSection :: giveGeneralizedStress_Shell(FloatArray &answer, GaussPoint elasticStrain.at(5) -= e0.at(2) * et.at(2) / thick; // kappa_y } } - this->give3dShellStiffMtrx(tangent, ElasticStiffness, gp, tStep); - answer.beProductOf(tangent, elasticStrain); - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) ); + auto tangent = this->give3dShellStiffMtrx(ElasticStiffness, gp, tStep); + auto answer = dot(tangent, elasticStrain); + + auto status = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) ); status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); + + return answer; } -void -SimpleCrossSection :: giveGeneralizedStress_MembraneRot(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArrayF< 9 > +SimpleCrossSection::giveGeneralizedStress_ShellRot(const FloatArrayF< 9 > &strain, GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix tangent; - this->giveMembraneRotStiffMtrx(tangent, ElasticStiffness, gp, tStep); - answer.beProductOf(tangent, strain); + /**Note: (by bp): This assumes that the behaviour is elastic + * there exist a nuumber of nonlinear integral material models for beams/plates/shells + * defined directly in terms of integral forces and moments and corresponding + * deformations and curvatures. This would require to implement support at material model level. + * Mikael: See earlier response to comment + */ - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveMaterial(gp)->giveStatus(gp) ); + FloatArrayF< 9 >answer; + FloatArrayF< 8 >rstrain; + for ( int i = 1; i <= 8; i++ ) { + rstrain.at(i) = strain.at(i); + } + FloatArray ra = this->giveGeneralizedStress_Shell(rstrain, gp, tStep); + for ( int i = 1; i <= 8; i++ ) { + answer.at(i) = ra.at(i); + } + answer.at(9) = this->give(CS_DrillingStiffness, gp) * strain.at(9); + + auto mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( mat->giveStatus(gp) ); status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); + return answer; +} + + +FloatArrayF< 4 > +SimpleCrossSection::giveGeneralizedStress_MembraneRot(const FloatArrayF< 4 > &strain, GaussPoint *gp, TimeStep *tStep) const +{ + auto tangent = this->giveMembraneRotStiffMtrx(ElasticStiffness, gp, tStep); + auto answer = dot(tangent, strain); + + auto status = static_cast< StructuralMaterialStatus * >( this->giveMaterial(gp)->giveStatus(gp) ); + status->letTempStrainVectorBe(strain); + status->letTempStressVectorBe(answer); ///@todo We should support nonlinear behavior for the membrane part. In fact, should be even bundle the rotation part with the membrane? /// We gain nothing from this design anyway as the rotation field is always separate. Separate manual integration by the element would be an option. + return answer; } -void -SimpleCrossSection :: giveGeneralizedStress_PlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep) +FloatArrayF< 3 > +SimpleCrossSection::giveGeneralizedStress_PlateSubSoil(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - return mat->giveRealStressVector_2dPlateSubSoil(answer, gp, generalizedStrain, tStep); + auto mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->giveRealStressVector_2dPlateSubSoil(generalizedStrain, gp, tStep); } void -SimpleCrossSection :: giveCharMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +SimpleCrossSection::giveCharMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mode = gp->giveMaterialMode(); if ( mode == _2dBeam ) { - this->give2dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->give2dBeamStiffMtrx(rMode, gp, tStep); } else if ( mode == _3dBeam ) { - this->give3dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->give3dBeamStiffMtrx(rMode, gp, tStep); } else if ( mode == _2dPlate ) { - this->give2dPlateStiffMtrx(answer, rMode, gp, tStep); + answer = this->give2dPlateStiffMtrx(rMode, gp, tStep); } else if ( mode == _3dShell ) { - this->give3dShellStiffMtrx(answer, rMode, gp, tStep); + answer = this->give3dShellStiffMtrx(rMode, gp, tStep); } else if ( mode == _3dDegeneratedShell ) { - this->give3dDegeneratedShellStiffMtrx(answer, rMode, gp, tStep); + answer = this->give3dDegeneratedShellStiffMtrx(rMode, gp, tStep); } else { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); if ( mode == _3dMat ) { - mat->give3dMaterialStiffnessMatrix(answer, rMode, gp, tStep); + answer = mat->give3dMaterialStiffnessMatrix(rMode, gp, tStep); } else if ( mode == _PlaneStress ) { - mat->givePlaneStressStiffMtrx(answer, rMode, gp, tStep); + answer = mat->givePlaneStressStiffMtrx(rMode, gp, tStep); } else if ( mode == _PlaneStrain ) { - mat->givePlaneStrainStiffMtrx(answer, rMode, gp, tStep); + answer = mat->givePlaneStrainStiffMtrx(rMode, gp, tStep); } else if ( mode == _1dMat ) { - mat->give1dStressStiffMtrx(answer, rMode, gp, tStep); + answer = mat->give1dStressStiffMtrx(rMode, gp, tStep); } else { mat->giveStiffnessMatrix(answer, rMode, gp, tStep); } @@ -310,51 +351,42 @@ SimpleCrossSection :: giveCharMaterialStiffnessMatrix(FloatMatrix &answer, MatRe } -void -SimpleCrossSection :: give2dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 3, 3 > +SimpleCrossSection::give2dBeamStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - - FloatMatrix mat3d; - double area, Iy, shearAreaz; - - mat->give1dStressStiffMtrx(mat3d, rMode, gp, tStep); - area = this->give(CS_Area, gp); - Iy = this->give(CS_InertiaMomentY, gp); - shearAreaz = this->give(CS_ShearAreaZ, gp); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - answer.resize(3, 3); - answer.zero(); + auto mat1d = mat->give1dStressStiffMtrx(rMode, gp, tStep); + auto area = this->give(CS_Area, gp); + auto Iy = this->give(CS_InertiaMomentY, gp); + auto shearAreaz = this->give(CS_ShearAreaZ, gp); - answer.at(1, 1) = mat3d.at(1, 1) * area; - answer.at(2, 2) = mat3d.at(1, 1) * Iy; + FloatMatrixF< 3, 3 >answer; + answer.at(1, 1) = mat1d.at(1, 1) * area; + answer.at(2, 2) = mat1d.at(1, 1) * Iy; answer.at(3, 3) = shearAreaz * mat->give('G', gp); + return answer; } -void -SimpleCrossSection :: give3dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 6, 6 > +SimpleCrossSection::give3dBeamStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - FloatMatrix mat3d; - double area, E, G, Iy, Iz, Ik; - double shearAreay, shearAreaz; - - mat->give1dStressStiffMtrx(mat3d, rMode, gp, tStep); - E = mat3d.at(1, 1); - G = mat->give('G', gp); - area = this->give(CS_Area, gp); - Iy = this->give(CS_InertiaMomentY, gp); - Iz = this->give(CS_InertiaMomentZ, gp); - Ik = this->give(CS_TorsionMomentX, gp); + auto mat1d = mat->give1dStressStiffMtrx(rMode, gp, tStep); + double E = mat1d.at(1, 1); + double G = mat->give('G', gp); + double area = this->give(CS_Area, gp); + double Iy = this->give(CS_InertiaMomentY, gp); + double Iz = this->give(CS_InertiaMomentZ, gp); + double Ik = this->give(CS_TorsionConstantX, gp); // St. Venant torsional constant //shearCoeff = this->give(CS_BeamShearCoeff); - shearAreay = this->give(CS_ShearAreaY, gp); - shearAreaz = this->give(CS_ShearAreaZ, gp); + double shearAreay = this->give(CS_ShearAreaY, gp); + double shearAreaz = this->give(CS_ShearAreaZ, gp); - answer.resize(6, 6); - answer.zero(); + FloatMatrixF< 6, 6 >answer; answer.at(1, 1) = E * area; ///@todo Do this by using the general 3d tangent matrix instead somehow!!! @@ -365,71 +397,80 @@ SimpleCrossSection :: give3dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode r answer.at(4, 4) = G * Ik; answer.at(5, 5) = E * Iy; answer.at(6, 6) = E * Iz; + return answer; } -void -SimpleCrossSection :: give2dPlateStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 5, 5 > +SimpleCrossSection::give2dPlateStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - - FloatMatrix mat3d; - double thickness3, thickness; + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->givePlaneStressStiffMtrx(mat3d, rMode, gp, tStep); - thickness = this->give(CS_Thickness, gp); - thickness3 = thickness * thickness * thickness; + auto mat2d = mat->givePlaneStressStiffMtrx(rMode, gp, tStep); + double thickness = this->give(CS_Thickness, gp); + double thickness3 = thickness * thickness * thickness; - answer.resize(5, 5); - answer.zero(); + FloatMatrixF< 5, 5 >answer; for ( int i = 1; i <= 2; i++ ) { for ( int j = 1; j <= 2; j++ ) { - answer.at(i, j) = mat3d.at(i, j) * thickness3 / 12.; + answer.at(i, j) = mat2d.at(i, j) * thickness3 / 12.; } } - answer.at(3, 3) = mat3d.at(3, 3) * thickness3 / 12.; - answer.at(4, 4) = mat3d.at(3, 3) * thickness * ( 5. / 6. ); + answer.at(3, 3) = mat2d.at(3, 3) * thickness3 / 12.; + answer.at(4, 4) = mat2d.at(3, 3) * thickness * ( 5. / 6. ); answer.at(5, 5) = answer.at(4, 4); + return answer; } -void -SimpleCrossSection :: give3dShellStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 8, 8 > +SimpleCrossSection::give3dShellStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - - FloatMatrix mat3d; + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); double thickness = this->give(CS_Thickness, gp); double thickness3 = thickness * thickness * thickness; - mat->givePlaneStressStiffMtrx(mat3d, rMode, gp, tStep); + auto mat2d = mat->givePlaneStressStiffMtrx(rMode, gp, tStep); - answer.resize(8, 8); - answer.zero(); + FloatMatrixF< 8, 8 >answer; for ( int i = 1; i <= 3; i++ ) { for ( int j = 1; j <= 3; j++ ) { - answer.at(i, j) = mat3d.at(i, j) * thickness; + answer.at(i, j) = mat2d.at(i, j) * thickness; } } for ( int i = 1; i <= 3; i++ ) { for ( int j = 1; j <= 3; j++ ) { - answer.at(i + 3, j + 3) = mat3d.at(i, j) * thickness3 / 12.0; + answer.at(i + 3, j + 3) = mat2d.at(i, j) * thickness3 / 12.0; } } - answer.at(8, 8) = answer.at(7, 7) = mat3d.at(3, 3) * thickness * ( 5. / 6. ); + answer.at(8, 8) = answer.at(7, 7) = mat2d.at(3, 3) * thickness * ( 5. / 6. ); + return answer; } -void -SimpleCrossSection :: give3dDegeneratedShellStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 9, 9 > +SimpleCrossSection::give3dShellRotStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->give3dMaterialStiffnessMatrix(answer, rMode, gp, tStep); + FloatMatrix d, answer; + d = this->give3dShellStiffMtrx(rMode, gp, tStep); + answer.resize(9, 9); + answer.zero(); + answer.assemble(d, { 1, 2, 3, 4, 5, 6, 7, 8 }); + answer.at(9, 9) = this->give(CS_DrillingStiffness, gp); + return answer; +} + + +FloatMatrixF< 6, 6 > +SimpleCrossSection::give3dDegeneratedShellStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + auto answer = mat->give3dMaterialStiffnessMatrix(rMode, gp, tStep); answer.at(1, 1) -= answer.at(1, 3) * answer.at(3, 1) / answer.at(3, 3); answer.at(2, 1) -= answer.at(2, 3) * answer.at(3, 1) / answer.at(3, 3); @@ -441,50 +482,48 @@ SimpleCrossSection :: give3dDegeneratedShellStiffMtrx(FloatMatrix &answer, MatRe answer.at(3, 3) = 0.0; answer.at(2, 3) = 0.0; answer.at(1, 3) = 0.0; + return answer; } -void -SimpleCrossSection :: giveMembraneRotStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 4, 4 > +SimpleCrossSection::giveMembraneRotStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat; - mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->givePlaneStressStiffMtrx(answer, ElasticStiffness, gp, tStep); - answer.resizeWithData(4, 4); - answer.at(4, 4) = this->give(CS_DrillingStiffness, gp); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + auto d = mat->givePlaneStressStiffMtrx(ElasticStiffness, gp, tStep); + auto ds = assemble< 4, 4 >(d, { 0, 1, 2 }, { 0, 1, 2 }); + ds.at(4, 4) = this->give(CS_DrillingStiffness, gp); + return ds; } -void -SimpleCrossSection :: give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 3, 3 > +SimpleCrossSection::give2dPlateSubSoilStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat; - mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->give2dPlateSubSoilStiffMtrx(answer, ElasticStiffness, gp, tStep); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->give2dPlateSubSoilStiffMtrx(ElasticStiffness, gp, tStep); } -IRResultType -SimpleCrossSection :: initializeFrom(InputRecord *ir) -// -// instanciates receiver from input record -// +void +SimpleCrossSection::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + CrossSection::initializeFrom(ir); + double value; double thick = 0.0; - if ( ir->hasField(_IFT_SimpleCrossSection_thick) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_thick) ) { IR_GIVE_OPTIONAL_FIELD(ir, thick, _IFT_SimpleCrossSection_thick); propertyDictionary.add(CS_Thickness, thick); } double width = 0.0; - if ( ir->hasField(_IFT_SimpleCrossSection_width) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_width) ) { IR_GIVE_OPTIONAL_FIELD(ir, width, _IFT_SimpleCrossSection_width); propertyDictionary.add(CS_Width, width); } double area = 0.0; - if ( ir->hasField(_IFT_SimpleCrossSection_area) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_area) ) { IR_GIVE_FIELD(ir, area, _IFT_SimpleCrossSection_area); } else { area = thick * width; @@ -501,7 +540,7 @@ SimpleCrossSection :: initializeFrom(InputRecord *ir) value = 0.0; IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_SimpleCrossSection_ik); - propertyDictionary.add(CS_TorsionMomentX, value); + propertyDictionary.add(CS_TorsionConstantX, value); double beamshearcoeff = 0.0; IR_GIVE_OPTIONAL_FIELD(ir, beamshearcoeff, _IFT_SimpleCrossSection_shearcoeff); @@ -536,7 +575,7 @@ SimpleCrossSection :: initializeFrom(InputRecord *ir) this->materialNumber = 0; IR_GIVE_OPTIONAL_FIELD(ir, this->materialNumber, _IFT_SimpleCrossSection_MaterialNumber); - if ( ir->hasField(_IFT_SimpleCrossSection_directorx) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_directorx) ) { value = 0.0; IR_GIVE_FIELD(ir, value, _IFT_SimpleCrossSection_directorx); propertyDictionary.add(CS_DirectorVectorX, value); @@ -549,15 +588,13 @@ SimpleCrossSection :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_SimpleCrossSection_directorz); propertyDictionary.add(CS_DirectorVectorZ, value); } - - return CrossSection :: initializeFrom(ir); } void -SimpleCrossSection :: giveInputRecord(DynamicInputRecord &input) +SimpleCrossSection::giveInputRecord(DynamicInputRecord &input) { - StructuralCrossSection :: giveInputRecord(input); + StructuralCrossSection::giveInputRecord(input); if ( this->propertyDictionary.includes(CS_Thickness) ) { input.setField(this->propertyDictionary.at(CS_Thickness), _IFT_SimpleCrossSection_thick); @@ -571,8 +608,8 @@ SimpleCrossSection :: giveInputRecord(DynamicInputRecord &input) input.setField(this->propertyDictionary.at(CS_Area), _IFT_SimpleCrossSection_area); } - if ( this->propertyDictionary.includes(CS_TorsionMomentX) ) { - input.setField(this->propertyDictionary.at(CS_TorsionMomentX), _IFT_SimpleCrossSection_ik); + if ( this->propertyDictionary.includes(CS_TorsionConstantX) ) { + input.setField(this->propertyDictionary.at(CS_TorsionConstantX), _IFT_SimpleCrossSection_ik); } if ( this->propertyDictionary.includes(CS_InertiaMomentY) ) { @@ -611,7 +648,7 @@ SimpleCrossSection :: giveInputRecord(DynamicInputRecord &input) } void -SimpleCrossSection :: createMaterialStatus(GaussPoint &iGP) +SimpleCrossSection::createMaterialStatus(GaussPoint &iGP) { Material *mat = domain->giveMaterial(materialNumber); MaterialStatus *matStat = mat->CreateStatus(& iGP); @@ -620,21 +657,21 @@ SimpleCrossSection :: createMaterialStatus(GaussPoint &iGP) bool -SimpleCrossSection :: isCharacteristicMtrxSymmetric(MatResponseMode rMode) +SimpleCrossSection::isCharacteristicMtrxSymmetric(MatResponseMode rMode) const { if ( this->giveMaterialNumber() ) { - return this->domain->giveMaterial( this->giveMaterialNumber() )->isCharacteristicMtrxSymmetric(rMode); + return this->domain->giveMaterial(this->giveMaterialNumber() )->isCharacteristicMtrxSymmetric(rMode); } else { return false; // Bet false... } } -Material -*SimpleCrossSection :: giveMaterial(IntegrationPoint *ip) +Material * +SimpleCrossSection::giveMaterial(IntegrationPoint *ip) const { if ( this->giveMaterialNumber() ) { - return this->giveDomain()->giveMaterial( this->giveMaterialNumber() ); + return this->giveDomain()->giveMaterial(this->giveMaterialNumber() ); } else { return ip->giveElement()->giveMaterial(); } @@ -642,14 +679,14 @@ Material double -SimpleCrossSection :: give(int aProperty, GaussPoint *gp) +SimpleCrossSection::give(int aProperty, GaussPoint *gp) const { return this->giveMaterial(gp)->give(aProperty, gp); } int -SimpleCrossSection :: giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep) +SimpleCrossSection::giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep) { if ( type == IST_CrossSectionNumber ) { answer.resize(1); @@ -662,7 +699,7 @@ SimpleCrossSection :: giveIPValue(FloatArray &answer, GaussPoint *ip, InternalSt int -SimpleCrossSection :: checkConsistency() +SimpleCrossSection::checkConsistency() // // check internal consistency // mainly tests, whether material and crossSection data @@ -671,8 +708,8 @@ SimpleCrossSection :: checkConsistency() { int result = 1; Material *mat = this->giveDomain()->giveMaterial(this->materialNumber); - if ( !dynamic_cast< StructuralMaterial * >(mat) ) { - OOFEM_WARNING( "material %s without structural support", mat->giveClassName() ); + if ( !dynamic_cast< StructuralMaterial * >( mat ) ) { + OOFEM_WARNING("material %s without structural support", mat->giveClassName() ); result = 0; } @@ -681,7 +718,7 @@ SimpleCrossSection :: checkConsistency() Interface -*SimpleCrossSection :: giveMaterialInterface(InterfaceType t, IntegrationPoint *ip) +*SimpleCrossSection::giveMaterialInterface(InterfaceType t, IntegrationPoint *ip) { return this->giveMaterial(ip)->giveInterface(t); } @@ -689,32 +726,9 @@ Interface -void -SimpleCrossSection :: giveFirstPKStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep) -{ - // This function returns the first Piola-Kirchoff stress in vector format - // corresponding to a given deformation gradient according to the stress-deformation - // mode stored in the each gp. - - MaterialMode mode = gp->giveMaterialMode(); - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - - if ( mode == _3dMat ) { - mat->giveFirstPKStressVector_3d(answer, gp, reducedvF, tStep); - } else if ( mode == _PlaneStrain ) { - mat->giveFirstPKStressVector_PlaneStrain(answer, gp, reducedvF, tStep); - } else if ( mode == _PlaneStress ) { - mat->giveFirstPKStressVector_PlaneStress(answer, gp, reducedvF, tStep); - } else if ( mode == _1dMat ) { - mat->giveFirstPKStressVector_1d(answer, gp, reducedvF, tStep); - } else { - OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mode) ); - } -} - void -SimpleCrossSection :: giveCauchyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep) +SimpleCrossSection::giveCauchyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep) { // This function returns the Cauchy stress in vector format // corresponding to a given deformation gradient according to the stress-deformation @@ -735,7 +749,7 @@ SimpleCrossSection :: giveCauchyStresses(FloatArray &answer, GaussPoint *gp, con } void -SimpleCrossSection :: giveEshelbyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep) +SimpleCrossSection::giveEshelbyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep) { MaterialMode mode = gp->giveMaterialMode(); StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); @@ -752,32 +766,99 @@ SimpleCrossSection :: giveEshelbyStresses(FloatArray &answer, GaussPoint *gp, co } -void -SimpleCrossSection :: giveStiffnessMatrix_dPdF(FloatMatrix &answer, - MatResponseMode rMode, GaussPoint *gp, - TimeStep *tStep) + + +FloatArrayF< 9 > +SimpleCrossSection::giveFirstPKStress_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->giveFirstPKStressVector_3d(vF, gp, tStep); +} + + +FloatArrayF< 5 > +SimpleCrossSection::giveFirstPKStress_PlaneStrain(const FloatArrayF< 5 > &vF, GaussPoint *gp, TimeStep *tStep) const +{ + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->giveFirstPKStressVector_PlaneStrain(vF, gp, tStep); +} + + +FloatArrayF< 4 > +SimpleCrossSection::giveFirstPKStress_PlaneStress(const FloatArrayF< 4 > &strain, GaussPoint *gp, TimeStep *tStep) const +{ + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->giveFirstPKStressVector_PlaneStress(strain, gp, tStep); +} + + +FloatArrayF< 1 > +SimpleCrossSection::giveFirstPKStress_1d(const FloatArrayF< 1 > &vF, GaussPoint *gp, TimeStep *tStep) const +{ + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->giveFirstPKStressVector_1d(vF, gp, tStep); +} + + +void +SimpleCrossSection::giveCharMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ MaterialMode mode = gp->giveMaterialMode(); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); if ( mode == _3dMat ) { - mat->give3dMaterialStiffnessMatrix_dPdF(answer, rMode, gp, tStep); + answer = mat->give3dMaterialStiffnessMatrix_dPdF(rMode, gp, tStep); } else if ( mode == _PlaneStress ) { - mat->givePlaneStressStiffMtrx_dPdF(answer, rMode, gp, tStep); + answer = mat->givePlaneStressStiffnessMatrix_dPdF(rMode, gp, tStep); } else if ( mode == _PlaneStrain ) { - mat->givePlaneStrainStiffMtrx_dPdF(answer, rMode, gp, tStep); + answer = mat->givePlaneStrainStiffnessMatrix_dPdF(rMode, gp, tStep); } else if ( mode == _1dMat ) { - mat->give1dStressStiffMtrx_dPdF(answer, rMode, gp, tStep); + answer = mat->give1dStressStiffnessMatrix_dPdF(rMode, gp, tStep); } else { - OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mode) ); + OOFEM_ERROR("Unsupported material mode for large strain analysis"); } } +FloatMatrixF< 9, 9 > +SimpleCrossSection::giveStiffnessMatrix_dPdF_3d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->give3dMaterialStiffnessMatrix_dPdF(rMode, gp, tStep); +} + + +FloatMatrixF< 5, 5 > +SimpleCrossSection::giveStiffnessMatrix_dPdF_PlaneStrain(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->givePlaneStrainStiffnessMatrix_dPdF(rMode, gp, tStep); +} + + + +FloatMatrixF< 4, 4 > +SimpleCrossSection::giveStiffnessMatrix_dPdF_PlaneStress(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->givePlaneStressStiffnessMatrix_dPdF(rMode, gp, tStep); +} + + +FloatMatrixF< 1, 1 > +SimpleCrossSection::giveStiffnessMatrix_dPdF_1d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->give1dStressStiffnessMatrix_dPdF(rMode, gp, tStep); +} + + + + void -SimpleCrossSection :: giveStiffnessMatrix_dCde(FloatMatrix &answer, - MatResponseMode rMode, GaussPoint *gp, - TimeStep *tStep) +SimpleCrossSection::giveStiffnessMatrix_dCde(FloatMatrix &answer, + MatResponseMode rMode, GaussPoint *gp, + TimeStep *tStep) { StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); @@ -791,18 +872,18 @@ SimpleCrossSection :: giveStiffnessMatrix_dCde(FloatMatrix &answer, } else if ( mode == _1dMat ) { mat->give1dStressStiffMtrx_dCde(answer, rMode, gp, tStep); } else { - OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mode) ); + OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mode) ); } } void -SimpleCrossSection :: giveTemperatureVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +SimpleCrossSection::giveTemperatureVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const { Element *elem = gp->giveElement(); answer.clear(); //sum up all prescribed temperatures over an element - StructuralElement *selem = dynamic_cast< StructuralElement * >(elem); + StructuralElement *selem = dynamic_cast< StructuralElement * >( elem ); selem->computeResultingIPTemperatureAt(answer, tStep, gp, VM_Total); /* add external source, if provided */ @@ -813,7 +894,7 @@ SimpleCrossSection :: giveTemperatureVector(FloatArray &answer, GaussPoint *gp, // temperature field registered FloatArray gcoords, et2; int err; - elem->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); + elem->computeGlobalCoordinates(gcoords, gp->giveNaturalCoordinates() ); if ( ( err = tf->evaluateAt(et2, gcoords, VM_Total, tStep) ) ) { OOFEM_ERROR("tf->evaluateAt failed, element %d, error code %d", elem->giveNumber(), err); } @@ -828,20 +909,51 @@ SimpleCrossSection :: giveTemperatureVector(FloatArray &answer, GaussPoint *gp, } int -SimpleCrossSection :: packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) +SimpleCrossSection::packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) { return this->giveMaterial(gp)->packUnknowns(buff, tStep, gp); } int -SimpleCrossSection :: unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) +SimpleCrossSection::unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) { return this->giveMaterial(gp)->unpackAndUpdateUnknowns(buff, tStep, gp); } int -SimpleCrossSection :: estimatePackSize(DataStream &buff, GaussPoint *gp) +SimpleCrossSection::estimatePackSize(DataStream &buff, GaussPoint *gp) { return this->giveMaterial(gp)->estimatePackSize(buff, gp); } + +void +SimpleCrossSection::saveContext(DataStream &stream, ContextMode mode) +{ + StructuralCrossSection::saveContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( !stream.write(materialNumber) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(czMaterialNumber) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + +void +SimpleCrossSection::restoreContext(DataStream &stream, ContextMode mode) +{ + StructuralCrossSection::restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( !stream.read(materialNumber) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(czMaterialNumber) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} } // end namespace oofem diff --git a/src/sm/CrossSections/simplecrosssection.h b/src/sm/CrossSections/simplecrosssection.h index 73f0cc15f..eb3707a18 100644 --- a/src/sm/CrossSections/simplecrosssection.h +++ b/src/sm/CrossSections/simplecrosssection.h @@ -35,8 +35,8 @@ #ifndef simplecrosssection_h #define simplecrosssection_h -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralmaterial.h" #include "floatarray.h" #include "floatmatrix.h" @@ -48,7 +48,7 @@ #define _IFT_SimpleCrossSection_area "area" #define _IFT_SimpleCrossSection_iy "iy" ///< Inertia moment y #define _IFT_SimpleCrossSection_iz "iz" ///< Inertia moment z -#define _IFT_SimpleCrossSection_ik "ik" ///< Torsion moment x +#define _IFT_SimpleCrossSection_ik "ik" ///< Saint-Venant torsional constant #define _IFT_SimpleCrossSection_shearcoeff "beamshearcoeff" #define _IFT_SimpleCrossSection_shearareay "shearareay" ///< Shear area y direction #define _IFT_SimpleCrossSection_shearareaz "shearareaz" ///< Shear area z direction @@ -85,47 +85,63 @@ namespace oofem { */ class OOFEM_EXPORT SimpleCrossSection : public StructuralCrossSection { +protected: + int materialNumber = 0; ///< Material number + int czMaterialNumber = 0; ///< Cohesive zone material number + public: /** * Constructor. * @param n Cross section number. * @param d Associated domain. */ - SimpleCrossSection(int n, Domain *d) : StructuralCrossSection(n, d) { - materialNumber = 0; - czMaterialNumber = 0; - } - - virtual void giveRealStress_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_3dDegeneratedShell(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_Warping(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - - virtual void giveStiffnessMatrix_3d(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveStiffnessMatrix_PlaneStress(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveStiffnessMatrix_PlaneStrain(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveStiffnessMatrix_1d(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - - - virtual void giveGeneralizedStress_Beam2d(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_Beam3d(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_Plate(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_Shell(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_MembraneRot(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - virtual void giveGeneralizedStress_PlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); - - virtual void giveCharMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode mode); - - virtual void give3dDegeneratedShellStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void give2dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give2dPlateStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dShellStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveMembraneRotStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + SimpleCrossSection(int n, Domain *d) : StructuralCrossSection(n, d) { } + + FloatArrayF< 6 >giveRealStress_3d(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 6 >giveRealStress_3dDegeneratedShell(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 4 >giveRealStress_PlaneStrain(const FloatArrayF< 4 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 3 >giveRealStress_PlaneStress(const FloatArrayF< 3 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 1 >giveRealStress_1d(const FloatArrayF< 1 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 2 >giveRealStress_Warping(const FloatArrayF< 2 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + + FloatMatrixF< 6, 6 >giveStiffnessMatrix_3d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 3, 3 >giveStiffnessMatrix_PlaneStress(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 4, 4 >giveStiffnessMatrix_PlaneStrain(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 1, 1 >giveStiffnessMatrix_1d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatArrayF< 3 >giveGeneralizedStress_Beam2d(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 6 >giveGeneralizedStress_Beam3d(const FloatArrayF< 6 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 5 >giveGeneralizedStress_Plate(const FloatArrayF< 5 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 8 >giveGeneralizedStress_Shell(const FloatArrayF< 8 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 9 >giveGeneralizedStress_ShellRot(const FloatArrayF< 9 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 4 >giveGeneralizedStress_MembraneRot(const FloatArrayF< 4 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF< 3 >giveGeneralizedStress_PlateSubSoil(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const override; + + void giveCharMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + bool isCharacteristicMtrxSymmetric(MatResponseMode mode) const override; + + FloatMatrixF< 6, 6 >give3dDegeneratedShellStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 3, 3 >give2dBeamStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 6, 6 >give3dBeamStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 5, 5 >give2dPlateStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 8, 8 >give3dShellStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 9, 9 >give3dShellRotStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 4, 4 >giveMembraneRotStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 3, 3 >give2dPlateSubSoilStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + + //@{ + virtual FloatArrayF< 9 >giveFirstPKStress_3d(const FloatArrayF< 9 > &reducedF, GaussPoint *gp, TimeStep *tStep) const override; + virtual FloatArrayF< 5 >giveFirstPKStress_PlaneStrain(const FloatArrayF< 5 > &reducedF, GaussPoint *gp, TimeStep *tStep) const override; + virtual FloatArrayF< 4 >giveFirstPKStress_PlaneStress(const FloatArrayF< 4 > &reducedF, GaussPoint *gp, TimeStep *tStep) const override; + virtual FloatArrayF< 1 >giveFirstPKStress_1d(const FloatArrayF< 1 > &reducedF, GaussPoint *gp, TimeStep *tStep) const override; + + void giveCharMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + FloatMatrixF< 9, 9 >giveStiffnessMatrix_dPdF_3d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 5, 5 >giveStiffnessMatrix_dPdF_PlaneStrain(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 4, 4 >giveStiffnessMatrix_dPdF_PlaneStress(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 1, 1 >giveStiffnessMatrix_dPdF_1d(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + /** @@ -140,43 +156,39 @@ class OOFEM_EXPORT SimpleCrossSection : public StructuralCrossSection * - 'beamshearcoeff' Beam shear coefficient * @param ir Record to read off. */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void createMaterialStatus(GaussPoint &iGP); // ES + void createMaterialStatus(GaussPoint &iGP) override; - // identification and auxiliary functions - virtual const char *giveClassName() const { return "SimpleCrossSection"; } - virtual const char *giveInputRecordName() const { return _IFT_SimpleCrossSection_Name; } + const char *giveClassName() const override { return "SimpleCrossSection"; } + const char *giveInputRecordName() const override { return _IFT_SimpleCrossSection_Name; } - virtual double give(int aProperty, GaussPoint *gp); - virtual double give(CrossSectionProperty a, GaussPoint *gp) { return CrossSection :: give(a, gp); } - virtual double give(CrossSectionProperty a, const FloatArray &coords, Element *elem, bool local) { return CrossSection :: give(a, coords, elem, local); } - virtual int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep); - virtual Material *giveMaterial(IntegrationPoint *ip); + double give(int aProperty, GaussPoint *gp) const override; + double give(CrossSectionProperty a, GaussPoint *gp) const override { return CrossSection::give(a, gp); } + double give(CrossSectionProperty a, const FloatArray &coords, Element *elem, bool local) const override { return CrossSection::give(a, coords, elem, local); } + int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep) override; + Material *giveMaterial(IntegrationPoint *ip) const override; int giveMaterialNumber() const { return this->materialNumber; } void setMaterialNumber(int matNum) { this->materialNumber = matNum; } - virtual int checkConsistency(); - virtual Interface *giveMaterialInterface(InterfaceType t, IntegrationPoint *ip); + int checkConsistency() override; + Interface *giveMaterialInterface(InterfaceType t, IntegrationPoint *ip) override; - virtual void giveFirstPKStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedFIncrement, TimeStep *tStep); - virtual void giveCauchyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedFIncrement, TimeStep *tStep); - virtual void giveEshelbyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep); - virtual void giveStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveStiffnessMatrix_dCde(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + void giveCauchyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedFIncrement, TimeStep *tStep) override; + void giveEshelbyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep) override; + void giveStiffnessMatrix_dCde(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; - virtual void giveTemperatureVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void giveTemperatureVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const; - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp); - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp); - virtual int estimatePackSize(DataStream &buff, GaussPoint *gp); + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) override; + int estimatePackSize(DataStream &buff, GaussPoint *gp) override; -protected: - int materialNumber; // material number - int czMaterialNumber; // cohesive zone material number + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; } // end namespace oofem #endif // simplecrosssection_h diff --git a/src/sm/CrossSections/structuralcrosssection.C b/src/sm/CrossSections/structuralcrosssection.C index 0eb3c8228..c8f8d96ef 100644 --- a/src/sm/CrossSections/structuralcrosssection.C +++ b/src/sm/CrossSections/structuralcrosssection.C @@ -32,42 +32,46 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "gausspoint.h" #include "element.h" #include "floatarray.h" namespace oofem { -void -StructuralCrossSection :: giveRealStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) +FloatArray +StructuralCrossSection::giveRealStresses(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const { MaterialMode mode = gp->giveMaterialMode(); if ( mode == _2dBeam ) { - this->giveGeneralizedStress_Beam2d(answer, gp, strain, tStep); + return this->giveGeneralizedStress_Beam2d(strain, gp, tStep); } else if ( mode == _3dBeam ) { - this->giveGeneralizedStress_Beam3d(answer, gp, strain, tStep); + return this->giveGeneralizedStress_Beam3d(strain, gp, tStep); } else if ( mode == _2dPlate ) { - this->giveGeneralizedStress_Plate(answer, gp, strain, tStep); + return this->giveGeneralizedStress_Plate(strain, gp, tStep); } else if ( mode == _3dShell ) { - this->giveGeneralizedStress_Shell(answer, gp, strain, tStep); + return this->giveGeneralizedStress_Shell(strain, gp, tStep); + } else if ( mode == _3dShellRot ) { + return this->giveGeneralizedStress_ShellRot(strain, gp, tStep); } else if ( mode == _3dMat ) { - this->giveRealStress_3d(answer, gp, strain, tStep); + return this->giveRealStress_3d(strain, gp, tStep); } else if ( mode == _PlaneStrain ) { - this->giveRealStress_PlaneStrain(answer, gp, strain, tStep); + return this->giveRealStress_PlaneStrain(strain, gp, tStep); } else if ( mode == _PlaneStress ) { - this->giveRealStress_PlaneStress(answer, gp, strain, tStep); + return this->giveRealStress_PlaneStress(strain, gp, tStep); } else if ( mode == _1dMat ) { - this->giveRealStress_1d(answer, gp, strain, tStep); + return this->giveRealStress_1d(strain, gp, tStep); } else if ( mode == _Warping ) { - this->giveRealStress_Warping(answer, gp, strain, tStep); + return this->giveRealStress_Warping(strain, gp, tStep); } else { // This should never happen ? ///@todo this part only works for simple cross section and will be removed soon when new interface elements are done /JB - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - if ( mat->hasMaterialModeCapability( gp->giveMaterialMode() ) ) { + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + if ( mat->hasMaterialModeCapability(mode) ) { + FloatArray answer; mat->giveRealStressVector(answer, gp, strain, tStep); + return answer; } else { OOFEM_ERROR("unsupported mode"); } @@ -75,9 +79,29 @@ StructuralCrossSection :: giveRealStresses(FloatArray &answer, GaussPoint *gp, c } +FloatArray +StructuralCrossSection::giveFirstPKStresses(const FloatArray &reducedF, GaussPoint *gp, TimeStep *tStep) const +{ + MaterialMode mode = gp->giveMaterialMode(); + if ( mode == _3dMat ) { + return this->giveFirstPKStress_3d(reducedF, gp, tStep); + } else if ( mode == _PlaneStrain ) { + return this->giveFirstPKStress_PlaneStrain(reducedF, gp, tStep); + } else if ( mode == _PlaneStress ) { + return this->giveFirstPKStress_PlaneStress(reducedF, gp, tStep); + } else if ( mode == _1dMat ) { + return this->giveFirstPKStress_1d(reducedF, gp, tStep); + } else { + OOFEM_ERROR("unsupported mode"); + } +} + + + + FloatArray * -StructuralCrossSection :: imposeStressConstrainsOnGradient(GaussPoint *gp, - FloatArray *gradientStressVector3d) +StructuralCrossSection::imposeStressConstrainsOnGradient(GaussPoint *gp, + FloatArray *gradientStressVector3d) // // returns modified gradient of stress vector, which is used to // bring stresses back to yield surface. @@ -120,33 +144,32 @@ StructuralCrossSection :: imposeStressConstrainsOnGradient(GaussPoint *gp, break; default: - OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mode) ); + OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mode) ); break; } return gradientStressVector3d; } -void -StructuralCrossSection :: giveGeneralizedStress_3dBeamSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep) +FloatArrayF< 6 > +StructuralCrossSection::giveGeneralizedStress_3dBeamSubSoil(const FloatArrayF< 6 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - return mat->giveRealStressVector_3dBeamSubSoil(answer, gp, generalizedStrain, tStep); + auto mat = static_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->giveRealStressVector_3dBeamSubSoil(generalizedStrain, gp, tStep); } -void -StructuralCrossSection :: give3dBeamSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 6, 6 > +StructuralCrossSection::give3dBeamSubSoilStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterial *mat; - mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); - mat->give3dBeamSubSoilStiffMtrx(answer, ElasticStiffness, gp, tStep); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveMaterial(gp) ); + return mat->give3dBeamSubSoilStiffMtrx(ElasticStiffness, gp, tStep); } - + FloatArray * -StructuralCrossSection :: imposeStrainConstrainsOnGradient(GaussPoint *gp, - FloatArray *gradientStrainVector3d) +StructuralCrossSection::imposeStrainConstrainsOnGradient(GaussPoint *gp, + FloatArray *gradientStrainVector3d) // // returns modified gradient of strain vector, which is used to // compute plastic strain increment. @@ -183,11 +206,10 @@ StructuralCrossSection :: imposeStrainConstrainsOnGradient(GaussPoint *gp, break; default: - OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mode) ); + OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mode) ); break; } return gradientStrainVector3d; } - } // end namespace oofem diff --git a/src/sm/CrossSections/structuralcrosssection.h b/src/sm/CrossSections/structuralcrosssection.h index 5c4b767c9..4e334396c 100644 --- a/src/sm/CrossSections/structuralcrosssection.h +++ b/src/sm/CrossSections/structuralcrosssection.h @@ -36,7 +36,7 @@ #define structuralcrosssection_h #include "crosssection.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" ///@name Input fields for CrossSection //@{ @@ -81,8 +81,6 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param d Domain to which new cross section will belong. */ StructuralCrossSection(int n, Domain *d) : CrossSection(n, d) { } - /// Destructor. - virtual ~StructuralCrossSection() { } /** * Computes the real stress vector for given strain and integration point. @@ -99,13 +97,13 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param tStep Current time step (most models are able to respond only when tStep is current time step). */ //@{ - void giveRealStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStress_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) = 0; - virtual void giveRealStress_3dDegeneratedShell(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) { OOFEM_ERROR("not implemented"); }; - virtual void giveRealStress_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) = 0; - virtual void giveRealStress_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) = 0; - virtual void giveRealStress_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) = 0; - virtual void giveRealStress_Warping(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) = 0; + FloatArray giveRealStresses(const FloatArray &reducedStrain, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatArrayF< 6 >giveRealStress_3d(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 6 >giveRealStress_3dDegeneratedShell(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("not implemented"); }; + virtual FloatArrayF< 4 >giveRealStress_PlaneStrain(const FloatArrayF< 4 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 3 >giveRealStress_PlaneStress(const FloatArrayF< 3 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 1 >giveRealStress_1d(const FloatArrayF< 1 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 2 >giveRealStress_Warping(const FloatArrayF< 2 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; //@} /** @@ -116,10 +114,10 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param tStep Time step (most models are able to respond only when tStep is current time step). */ //@{ - virtual void giveStiffnessMatrix_3d(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; - virtual void giveStiffnessMatrix_PlaneStress(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; - virtual void giveStiffnessMatrix_PlaneStrain(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; - virtual void giveStiffnessMatrix_1d(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + virtual FloatMatrixF< 6, 6 >giveStiffnessMatrix_3d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatMatrixF< 3, 3 >giveStiffnessMatrix_PlaneStress(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatMatrixF< 4, 4 >giveStiffnessMatrix_PlaneStrain(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatMatrixF< 1, 1 >giveStiffnessMatrix_1d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; //@} /** @@ -130,13 +128,14 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param tStep Current time step (most models are able to respond only when tStep is current time step). */ //@{ - virtual void giveGeneralizedStress_Beam2d(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep) = 0; - virtual void giveGeneralizedStress_Beam3d(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep) = 0; - virtual void giveGeneralizedStress_Plate(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep) = 0; - virtual void giveGeneralizedStress_Shell(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep) = 0; - virtual void giveGeneralizedStress_MembraneRot(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep) = 0; - virtual void giveGeneralizedStress_PlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep) = 0; - virtual void giveGeneralizedStress_3dBeamSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &generalizedStrain, TimeStep *tStep); + virtual FloatArrayF< 3 >giveGeneralizedStress_Beam2d(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 6 >giveGeneralizedStress_Beam3d(const FloatArrayF< 6 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 5 >giveGeneralizedStress_Plate(const FloatArrayF< 5 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 8 >giveGeneralizedStress_Shell(const FloatArrayF< 8 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 9 >giveGeneralizedStress_ShellRot(const FloatArrayF< 9 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 4 >giveGeneralizedStress_MembraneRot(const FloatArrayF< 4 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 3 >giveGeneralizedStress_PlateSubSoil(const FloatArrayF< 3 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 6 >giveGeneralizedStress_3dBeamSubSoil(const FloatArrayF< 6 > &generalizedStrain, GaussPoint *gp, TimeStep *tStep) const; //@} /** @@ -153,7 +152,14 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param reducedFIncrement Increment of the deformation gradient vector in reduced form. @todo should this then be in a multiplicative way? /JB * @param tStep Current time step (most models are able to respond only when tStep is current time step). */ - virtual void giveFirstPKStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedFIncrement, TimeStep *tStep) = 0; + virtual FloatArray giveFirstPKStresses(const FloatArray &reducedF, GaussPoint *gp, TimeStep *tStep) const; + //@{ + virtual FloatArrayF< 9 >giveFirstPKStress_3d(const FloatArrayF< 9 > &reducedF, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 5 >giveFirstPKStress_PlaneStrain(const FloatArrayF< 5 > &reducedF, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 4 >giveFirstPKStress_PlaneStress(const FloatArrayF< 4 > &reducedF, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatArrayF< 1 >giveFirstPKStress_1d(const FloatArrayF< 1 > &reducedF, GaussPoint *gp, TimeStep *tStep) const = 0; + //@} + /** @@ -180,20 +186,6 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection */ virtual void giveEshelbyStresses(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep) {}; - /** - * Computes the material stiffness matrix dPdF of receiver in a given integration point, respecting its history. - * The algorithm should use temporary or equilibrium history variables stored in integration point status - * to compute and return required result. - * Elements should always pass their requests to their cross section model, which - * performs necessary integration over its volume and invokes necessary material - * services for corresponding material model defined for given integration point. - * @param answer Contains result. - * @param mode Material response mode. - * @param gp Integration point. - * @param tStep Time step (most models are able to respond only when tStep is current time step). - */ - virtual void giveStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; - /** * Computes the material stiffness matrix dCde of receiver in a given integration point, respecting its history. * The algorithm should use temporary or equilibrium history variables stored in integration point status @@ -230,7 +222,7 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param gp Integration point. * @param tStep Time step. */ - virtual void give2dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + virtual FloatMatrixF< 3, 3 >give2dBeamStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; /** * Computes the stiffness matrix for 2d beams. * @param answer The requested matrix. @@ -238,7 +230,7 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param gp Integration point. * @param tStep Time step. */ - virtual void give3dBeamStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + virtual FloatMatrixF< 6, 6 >give3dBeamStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; /** * Method for computing subsoil stiffness matrix for 2d beams. * @param answer Stiffness matrix. @@ -246,7 +238,7 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). */ - virtual void give3dBeamSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + virtual FloatMatrixF< 6, 6 >give3dBeamSubSoilStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; /** * Method for computing 2d plate stiffness matrix. @@ -255,7 +247,7 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). */ - virtual void give2dPlateStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + virtual FloatMatrixF< 5, 5 >give2dPlateStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; /** * Method for computing 3d shell stiffness matrix. * @param answer Stiffness matrix. @@ -263,7 +255,15 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). */ - virtual void give3dShellStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + virtual FloatMatrixF< 8, 8 >give3dShellStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; + /** + * Method for computing 3d shell (with normal rotation) stiffness matrix. + * @param answer Stiffness matrix. + * @param mode Material response mode. + * @param gp Integration point, which load history is used. + * @param tStep Time step (most models are able to respond only when tStep is current time step). + */ + virtual FloatMatrixF< 9, 9 >give3dShellRotStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; /** * Method for computing 3d shell stiffness matrix on degenerated shell elements. * @param answer Stiffness matrix. @@ -271,7 +271,7 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). */ - virtual void give3dDegeneratedShellStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { OOFEM_ERROR("Implemented in inherited classes"); }; + virtual FloatMatrixF< 6, 6 >give3dDegeneratedShellStiffMtrx(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Implemented in inherited classes"); }; /** * Method for computing membrane stiffness matrix with added drilling stiffness. * @param answer Stiffness matrix. @@ -279,7 +279,7 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). */ - virtual void giveMembraneRotStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + virtual FloatMatrixF< 4, 4 >giveMembraneRotStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; /** * Method for computing subsoil stiffness matrix for plates. * @param answer Stiffness matrix. @@ -287,7 +287,45 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). */ - virtual void give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + virtual FloatMatrixF< 3, 3 >give2dPlateSubSoilStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; + + /** + * Computes the large strain stiffness matrix of receiver in given integration point, respecting its history. + * The algorithm should use temporary or equilibrium history variables stored in integration point status + * to compute and return required result. + * Elements should always pass their requests to their cross section model, which + * performs necessary integration over its volume and invokes necessary material + * services for corresponding material model defined for given integration point. + * @param answer Contains result. + * @param mode Material response mode. + * @param gp Integration point. + * @param tStep Time step (most models are able to respond only when tStep is current time step). + */ + + virtual void giveCharMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + + /** + * Computes the material stiffness matrix dPdF of receiver in a given integration point, respecting its history. + * The algorithm should use temporary or equilibrium history variables stored in integration point status + * to compute and return required result. + * Elements should always pass their requests to their cross section model, which + * performs necessary integration over its volume and invokes necessary material + * services for corresponding material model defined for given integration point. + * @param answer Contains result. + * @param mode Material response mode. + * @param gp Integration point. + * @param tStep Time step (most models are able to respond only when tStep is current time step). + */ + //@{ + virtual FloatMatrixF< 9, 9 >giveStiffnessMatrix_dPdF_3d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatMatrixF< 5, 5 >giveStiffnessMatrix_dPdF_PlaneStrain(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatMatrixF< 4, 4 >giveStiffnessMatrix_dPdF_PlaneStress(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; + virtual FloatMatrixF< 1, 1 >giveStiffnessMatrix_dPdF_1d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; + //@} + + + + /** * Returns modified gradient of stress vector, which is used to * bring stresses back to yield surface. @@ -312,15 +350,16 @@ class OOFEM_EXPORT StructuralCrossSection : public CrossSection */ virtual FloatArray *imposeStrainConstrainsOnGradient(GaussPoint *gp, FloatArray *gradientStressVector3d); - virtual int testCrossSectionExtension(CrossSectExtension ext) { return ( ( ext == CS_StructuralCapability ) ? 1 : 0 ); } + int testCrossSectionExtension(CrossSectExtension ext) override { return ( ( ext == CS_StructuralCapability ) ? 1 : 0 ); } - virtual Material *giveMaterial(IntegrationPoint *ip) { OOFEM_ERROR("Missing implementation"); return NULL; } + ///@todo This shouldn't be optional + Material *giveMaterial(IntegrationPoint *ip) const override { OOFEM_ERROR("Missing implementation"); return nullptr; } + virtual Interface *giveMaterialInterface(InterfaceType t, IntegrationPoint *ip) { return nullptr; } virtual void createMaterialStatus(GaussPoint &iGP) = 0; - virtual int checkConsistency() = 0; - virtual Interface *giveMaterialInterface(InterfaceType t, IntegrationPoint *ip) { return NULL; } - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode mode) = 0; + int checkConsistency() override = 0; + bool isCharacteristicMtrxSymmetric(MatResponseMode mode) const override = 0; }; } // end namespace oofem #endif // structuralcrosssection_h diff --git a/src/sm/CrossSections/structuralinterfacecrosssection.C b/src/sm/CrossSections/structuralinterfacecrosssection.C index 96e5e6a9c..dda9f27bf 100644 --- a/src/sm/CrossSections/structuralinterfacecrosssection.C +++ b/src/sm/CrossSections/structuralinterfacecrosssection.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/CrossSections/structuralinterfacecrosssection.h" -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" #include "gausspoint.h" #include "element.h" #include "floatarray.h" @@ -43,20 +43,11 @@ namespace oofem { REGISTER_CrossSection(StructuralInterfaceCrossSection); StructuralInterfaceMaterial * -StructuralInterfaceCrossSection :: giveInterfaceMaterial() +StructuralInterfaceCrossSection :: giveInterfaceMaterial() const { return static_cast< StructuralInterfaceMaterial * >( this->giveDomain()->giveMaterial(this->materialNum) ); } -const FloatArray & -StructuralInterfaceCrossSection :: giveTraction(IntegrationPoint *ip) -{ - // Returns the traction vector stored in the material status - //return static_cast< StructuralInterfaceMaterialStatus *> ( this->giveInterfaceMaterial()->giveStatus(ip) )->giveTraction(); - return static_cast< StructuralInterfaceMaterialStatus * >( this->giveInterfaceMaterial()->giveStatus(ip) )->giveFirstPKTraction(); -} - - int StructuralInterfaceCrossSection :: checkConsistency() { @@ -70,101 +61,95 @@ StructuralInterfaceCrossSection :: checkConsistency() return 1; } -IRResultType -StructuralInterfaceCrossSection :: initializeFrom(InputRecord *ir) +void +StructuralInterfaceCrossSection :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - CrossSection :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->materialNum, _IFT_StructuralInterfaceCrossSection_Material); double thickness = 0.0; - if ( ir->hasField(_IFT_StructuralInterfaceCrossSection_thickness) ) { + if ( ir.hasField(_IFT_StructuralInterfaceCrossSection_thickness) ) { IR_GIVE_OPTIONAL_FIELD(ir, thickness, _IFT_StructuralInterfaceCrossSection_thickness); propertyDictionary.add(CS_Thickness, thickness); } - - return IRRT_OK; } -void -StructuralInterfaceCrossSection :: give1dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<1,1> +StructuralInterfaceCrossSection :: give1dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { StructuralInterfaceMaterial *mat = this->giveInterfaceMaterial(); if ( mat->useNumericalTangent ) { - mat->give1dStiffnessMatrix_Eng_Num( answer, gp, tStep ); + return mat->give1dStiffnessMatrix_Eng_Num( gp, tStep ); } else if( mat->hasAnalyticalTangentStiffness() ) { - mat->give1dStiffnessMatrix_Eng( answer, rMode, gp, tStep ); + return mat->give1dStiffnessMatrix_Eng( rMode, gp, tStep ); } else { OOFEM_ERROR("Not implemented - use numerical tangent instead (keyword: 'use_num_tangent') "); } } -void -StructuralInterfaceCrossSection :: give2dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<2,2> +StructuralInterfaceCrossSection :: give2dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { StructuralInterfaceMaterial *mat = this->giveInterfaceMaterial(); if ( mat->useNumericalTangent ) { - mat->give2dStiffnessMatrix_Eng_Num( answer, gp, tStep ); + return mat->give2dStiffnessMatrix_Eng_Num( gp, tStep ); } else if ( mat->hasAnalyticalTangentStiffness() ) { - mat->give2dStiffnessMatrix_Eng(answer, rMode, gp, tStep); + return mat->give2dStiffnessMatrix_Eng( rMode, gp, tStep); } else { OOFEM_ERROR("not implemented - use numerical tangent instead (keyword: 'use_num_tangent') "); } } -void -StructuralInterfaceCrossSection :: give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +StructuralInterfaceCrossSection :: give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { StructuralInterfaceMaterial *mat = this->giveInterfaceMaterial( ); if ( mat->useNumericalTangent ) { - mat->give3dStiffnessMatrix_Eng_Num(answer, gp, tStep); + return mat->give3dStiffnessMatrix_Eng_Num(gp, tStep); } else if ( mat->hasAnalyticalTangentStiffness() ) { - mat->give3dStiffnessMatrix_Eng(answer, rMode, gp, tStep); + return mat->give3dStiffnessMatrix_Eng(rMode, gp, tStep); } else { OOFEM_ERROR("Not implemented - use numerical tangent instead (keyword: 'use_num_tangent') "); } } - - -void -StructuralInterfaceCrossSection :: give1dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<1,1> +StructuralInterfaceCrossSection :: give1dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { StructuralInterfaceMaterial *mat = this->giveInterfaceMaterial(); if ( mat->useNumericalTangent ) { - mat->give1dStiffnessMatrix_dTdj_Num( answer, gp, tStep); + return mat->give1dStiffnessMatrix_dTdj_Num(gp, tStep); } else if ( mat->hasAnalyticalTangentStiffness() ) { - mat->give1dStiffnessMatrix_dTdj(answer, rMode, gp, tStep); + return mat->give1dStiffnessMatrix_dTdj(rMode, gp, tStep); } else { OOFEM_ERROR("not implemented - use numerical tangent instead (keyword: 'use_num_tangent') "); } } -void -StructuralInterfaceCrossSection :: give2dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<2,2> +StructuralInterfaceCrossSection :: give2dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { StructuralInterfaceMaterial *mat = this->giveInterfaceMaterial(); if ( mat->useNumericalTangent ) { - mat->give2dStiffnessMatrix_dTdj_Num( answer, gp, tStep ); + return mat->give2dStiffnessMatrix_dTdj_Num(gp, tStep ); } else if ( mat->hasAnalyticalTangentStiffness() ) { - mat->give2dStiffnessMatrix_dTdj(answer, rMode, gp, tStep); + return mat->give2dStiffnessMatrix_dTdj(rMode, gp, tStep); } else { OOFEM_ERROR("not implemented - use numerical tangent instead (keyword: 'use_num_tangent') "); } } -void -StructuralInterfaceCrossSection :: give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +StructuralInterfaceCrossSection :: give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { StructuralInterfaceMaterial *mat = this->giveInterfaceMaterial(); if ( mat->useNumericalTangent ) { - mat->give3dStiffnessMatrix_dTdj_Num(answer, gp, tStep); + return mat->give3dStiffnessMatrix_dTdj_Num(gp, tStep); } else if ( mat->hasAnalyticalTangentStiffness() ) { - mat->give3dStiffnessMatrix_dTdj(answer, rMode, gp, tStep); + return mat->give3dStiffnessMatrix_dTdj(rMode, gp, tStep); } else { OOFEM_ERROR("not implemented - use numerical tangent instead (keyword: 'use_num_tangent') "); } @@ -183,7 +168,7 @@ StructuralInterfaceCrossSection :: giveIPValue(FloatArray &answer, GaussPoint *i } -Material *StructuralInterfaceCrossSection :: giveMaterial(IntegrationPoint *ip) +Material *StructuralInterfaceCrossSection :: giveMaterial(IntegrationPoint *ip) const { if ( this->giveMaterialNumber() ) { return this->giveDomain()->giveMaterial( this->giveMaterialNumber() ); diff --git a/src/sm/CrossSections/structuralinterfacecrosssection.h b/src/sm/CrossSections/structuralinterfacecrosssection.h index 163810d79..f1cfeedbb 100644 --- a/src/sm/CrossSections/structuralinterfacecrosssection.h +++ b/src/sm/CrossSections/structuralinterfacecrosssection.h @@ -35,7 +35,7 @@ #ifndef structuralinterfacecrosssection_h #define structuralinterfacecrosssection_h -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" #include "crosssection.h" #include "classfactory.h" @@ -74,9 +74,9 @@ class StructuralInterfaceCrossSection : public CrossSection /// Destructor. virtual ~StructuralInterfaceCrossSection() { } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual int testCrossSectionExtension(CrossSectExtension ext) { return this->crossSectionType; } + int testCrossSectionExtension(CrossSectExtension ext) override { return this->crossSectionType; } /** * Computes the real stress vector for given strain and integration point. @@ -89,60 +89,58 @@ class StructuralInterfaceCrossSection : public CrossSection * services for corresponding material model defined for given integration point. * @param answer Contains result. * @param gp Integration point. - * @param reducedF Deformation gradient in reduced form. + * @param reduthiscedF Deformation gradient in reduced form. * @param tStep Current time step (most models are able to respond only when tStep is current time step). */ //@{ // Pass all calls to the material - void giveFirstPKTraction_1d( FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const FloatMatrix &F, TimeStep *tStep ) - { this->giveInterfaceMaterial()->giveFirstPKTraction_1d(answer, gp, jump, F, tStep); } - void giveFirstPKTraction_2d( FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const FloatMatrix &F, TimeStep *tStep ) - { this->giveInterfaceMaterial()->giveFirstPKTraction_2d(answer, gp, jump, F, tStep); } - void giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const FloatMatrix &F, TimeStep *tStep) - { this->giveInterfaceMaterial()->giveFirstPKTraction_3d(answer, gp, jump, F, tStep); } + double giveFirstPKTraction_1d(double jump, double F, GaussPoint *gp, TimeStep *tStep ) const + { return this->giveInterfaceMaterial()->giveFirstPKTraction_1d(jump, F, gp, tStep); } + FloatArrayF<2> giveFirstPKTraction_2d( const FloatArrayF<2> &jump, const FloatMatrixF<2,2> &F, GaussPoint *gp, TimeStep *tStep ) const + { return this->giveInterfaceMaterial()->giveFirstPKTraction_2d(jump, F, gp, tStep); } + FloatArrayF<3> giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const + { return this->giveInterfaceMaterial()->giveFirstPKTraction_3d(jump, F, gp, tStep); } - void giveEngTraction_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) + double giveEngTraction_1d(double jump, GaussPoint *gp, TimeStep *tStep) const { - this->giveInterfaceMaterial()->giveEngTraction_1d(answer, gp, jump, tStep); + return this->giveInterfaceMaterial()->giveEngTraction_1d(jump, gp, tStep); } - void giveEngTraction_2d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) + FloatArrayF<2> giveEngTraction_2d(const FloatArrayF<2> &jump, GaussPoint *gp, TimeStep *tStep) const { - this->giveInterfaceMaterial()->giveEngTraction_2d(answer, gp, jump, tStep); + return this->giveInterfaceMaterial()->giveEngTraction_2d(jump, gp, tStep); } - void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) + FloatArrayF<3> giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const { - this->giveInterfaceMaterial()->giveEngTraction_3d(answer, gp, jump, tStep); + return this->giveInterfaceMaterial()->giveEngTraction_3d(jump, gp, tStep); } - void give1dStiffnessMatrix_dTdj( FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ); - void give2dStiffnessMatrix_dTdj( FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ); - void give3dStiffnessMatrix_dTdj( FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ); + FloatMatrixF<1,1> give1dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ) const; + FloatMatrixF<2,2> give2dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ) const; + FloatMatrixF<3,3> give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ) const; - - void give1dStiffnessMatrix_Eng( FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ); - void give2dStiffnessMatrix_Eng( FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ); - void give3dStiffnessMatrix_Eng( FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ); + FloatMatrixF<1,1> give1dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ) const; + FloatMatrixF<2,2> give2dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ) const; + FloatMatrixF<3,3> give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ) const; //@} - StructuralInterfaceMaterial *giveInterfaceMaterial(); - const FloatArray &giveTraction(IntegrationPoint *ip); + StructuralInterfaceMaterial *giveInterfaceMaterial() const; - virtual int checkConsistency(); + int checkConsistency() override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep) override; - virtual Material *giveMaterial(IntegrationPoint *ip); + Material *giveMaterial(IntegrationPoint *ip) const override; int giveMaterialNumber() const { return this->materialNum; } void setMaterialNumber(int matNum) { this->materialNum = matNum; } - - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp); - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp); - virtual int estimatePackSize(DataStream &buff, GaussPoint *gp); + + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) override; + int estimatePackSize(DataStream &buff, GaussPoint *gp) override; // identification and auxiliary functions - virtual const char *giveClassName() const { return "StructuralInterfaceCrossSection"; } - virtual const char *giveInputRecordName() const { return _IFT_StructuralInterfaceCrossSection_Name; } + const char *giveClassName() const override { return "StructuralInterfaceCrossSection"; } + const char *giveInputRecordName() const override { return _IFT_StructuralInterfaceCrossSection_Name; } CrossSectExtension crossSectionType; private: diff --git a/src/sm/CrossSections/variablecrosssection.C b/src/sm/CrossSections/variablecrosssection.C index 4e66aab78..733881b04 100644 --- a/src/sm/CrossSections/variablecrosssection.C +++ b/src/sm/CrossSections/variablecrosssection.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/CrossSections/variablecrosssection.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/CrossSections/variablecrosssection.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "gausspoint.h" #include "floatarray.h" #include "classfactory.h" @@ -49,78 +49,73 @@ namespace oofem { REGISTER_CrossSection(VariableCrossSection); -IRResultType -VariableCrossSection :: initializeFrom(InputRecord *ir) -// -// instanciates receiver from input record -// +void +VariableCrossSection :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - if ( ir->hasField(_IFT_SimpleCrossSection_thick) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_thick) ) { IR_GIVE_OPTIONAL_FIELD(ir, thicknessExpr, _IFT_SimpleCrossSection_thick); } - if ( ir->hasField(_IFT_SimpleCrossSection_width) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_width) ) { IR_GIVE_OPTIONAL_FIELD(ir, widthExpr, _IFT_SimpleCrossSection_width); } - if ( ir->hasField(_IFT_SimpleCrossSection_area) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_area) ) { IR_GIVE_OPTIONAL_FIELD(ir, areaExpr, _IFT_SimpleCrossSection_area); } - if ( ir->hasField(_IFT_SimpleCrossSection_iy) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_iy) ) { IR_GIVE_OPTIONAL_FIELD(ir, iyExpr, _IFT_SimpleCrossSection_iy); } - if ( ir->hasField(_IFT_SimpleCrossSection_iy) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_iy) ) { IR_GIVE_OPTIONAL_FIELD(ir, izExpr, _IFT_SimpleCrossSection_iz); } - if ( ir->hasField(_IFT_SimpleCrossSection_ik) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_ik) ) { IR_GIVE_OPTIONAL_FIELD(ir, ixExpr, _IFT_SimpleCrossSection_ik); } - if ( ir->hasField(_IFT_SimpleCrossSection_shearareay) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_shearareay) ) { IR_GIVE_OPTIONAL_FIELD(ir, shearAreayExpr, _IFT_SimpleCrossSection_shearareay); } - if ( ir->hasField(_IFT_SimpleCrossSection_shearareaz) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_shearareaz) ) { IR_GIVE_OPTIONAL_FIELD(ir, shearAreazExpr, _IFT_SimpleCrossSection_shearareaz); } - if ( ir->hasField(_IFT_SimpleCrossSection_drillStiffness) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_drillStiffness) ) { IR_GIVE_OPTIONAL_FIELD(ir, drillingStiffnessExpr, _IFT_SimpleCrossSection_drillStiffness); } - if ( ir->hasField(_IFT_SimpleCrossSection_relDrillStiffness) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_relDrillStiffness) ) { IR_GIVE_OPTIONAL_FIELD(ir, relDrillingStiffnessExpr, _IFT_SimpleCrossSection_relDrillStiffness); } - if ( ir->hasField(_IFT_SimpleCrossSection_drillType) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_drillType) ) { IR_GIVE_OPTIONAL_FIELD(ir, drillingTypeExpr, _IFT_SimpleCrossSection_drillType); } IR_GIVE_OPTIONAL_FIELD(ir, this->materialNumber, _IFT_SimpleCrossSection_MaterialNumber); directorxExpr.setValue(0.0); - if ( ir->hasField(_IFT_SimpleCrossSection_directorx) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_directorx) ) { IR_GIVE_OPTIONAL_FIELD(ir, directorxExpr, _IFT_SimpleCrossSection_directorx); } directoryExpr.setValue(0.0); - if ( ir->hasField(_IFT_SimpleCrossSection_directory) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_directory) ) { IR_GIVE_OPTIONAL_FIELD(ir, directoryExpr, _IFT_SimpleCrossSection_directory); } directorzExpr.setValue(1.0); - if ( ir->hasField(_IFT_SimpleCrossSection_directorz) ) { + if ( ir.hasField(_IFT_SimpleCrossSection_directorz) ) { IR_GIVE_OPTIONAL_FIELD(ir, directorzExpr, _IFT_SimpleCrossSection_directorz); } // will read density and other inheritted parameters as constants // NOTE: do not call SimpleCrossSection here (as the parameter names are same, but different type is used here!!!!) - return CrossSection :: initializeFrom(ir); + CrossSection :: initializeFrom(ir); } @@ -155,7 +150,7 @@ VariableCrossSection :: giveExpression(const ScalarFunction **expr, CrossSection * expr = & widthExpr; } else if ( aProperty == CS_Area ) { * expr = & areaExpr; - } else if ( aProperty == CS_TorsionMomentX ) { + } else if ( aProperty == CS_TorsionConstantX ) { * expr = & ixExpr; } else if ( aProperty == CS_InertiaMomentY ) { * expr = & iyExpr; @@ -185,14 +180,14 @@ VariableCrossSection :: giveExpression(const ScalarFunction **expr, CrossSection double -VariableCrossSection :: give(CrossSectionProperty aProperty, GaussPoint *gpx) +VariableCrossSection :: give(CrossSectionProperty aProperty, GaussPoint *gpx) const { return this->give(aProperty, gpx->giveNaturalCoordinates(), gpx->giveElement(), true); } double -VariableCrossSection :: give(CrossSectionProperty aProperty, const FloatArray &coords, Element *elem, bool local) +VariableCrossSection :: give(CrossSectionProperty aProperty, const FloatArray &coords, Element *elem, bool local) const { double value = 0.0; const ScalarFunction *expr; diff --git a/src/sm/CrossSections/variablecrosssection.h b/src/sm/CrossSections/variablecrosssection.h index e256a4625..c68d034c1 100644 --- a/src/sm/CrossSections/variablecrosssection.h +++ b/src/sm/CrossSections/variablecrosssection.h @@ -35,9 +35,9 @@ #ifndef variablecrosssection_h #define variablecrosssection_h -#include "../sm/CrossSections/simplecrosssection.h" -#include "../sm/CrossSections/layeredcrosssection.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/simplecrosssection.h" +#include "sm/CrossSections/layeredcrosssection.h" +#include "sm/Materials/structuralmaterial.h" #include "floatarray.h" #include "floatmatrix.h" #include "scalarfunction.h" @@ -116,15 +116,14 @@ class OOFEM_EXPORT VariableCrossSection : public SimpleCrossSection * - 'beamshearcoeff' Beam shear coefficient * @param ir Record to read off. */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - // identification and auxiliary functions - virtual const char *giveClassName() const { return "VariableCrossSection"; } - virtual const char *giveInputRecordName() const { return _IFT_VariableCrossSection_Name; } + const char *giveClassName() const override { return "VariableCrossSection"; } + const char *giveInputRecordName() const override { return _IFT_VariableCrossSection_Name; } - virtual double give(CrossSectionProperty a, GaussPoint *gp); - virtual double give(CrossSectionProperty a, const FloatArray &coords, Element *elem, bool local); + double give(CrossSectionProperty a, GaussPoint *gp) const override; + double give(CrossSectionProperty a, const FloatArray &coords, Element *elem, bool local) const override; protected: void giveExpression(const ScalarFunction **expr, CrossSectionProperty aProperty) const; diff --git a/src/sm/CrossSections/warpingcrosssection.C b/src/sm/CrossSections/warpingcrosssection.C index 44b39188d..908deef88 100644 --- a/src/sm/CrossSections/warpingcrosssection.C +++ b/src/sm/CrossSections/warpingcrosssection.C @@ -40,17 +40,15 @@ namespace oofem { REGISTER_CrossSection(WarpingCrossSection); -IRResultType -WarpingCrossSection :: initializeFrom(InputRecord *ir) +void +WarpingCrossSection :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + SimpleCrossSection :: initializeFrom(ir); int value; IR_GIVE_FIELD(ir, value, _IFT_WarpingCrossSection_WarpingNodeNumber); this->WarpingNodeNumber = value; //propertyDictionary->add(CS_Thickness, thick); - - return SimpleCrossSection :: initializeFrom(ir); } } // end namespace oofem diff --git a/src/sm/CrossSections/warpingcrosssection.h b/src/sm/CrossSections/warpingcrosssection.h index a5c29c2b6..8a801b19d 100644 --- a/src/sm/CrossSections/warpingcrosssection.h +++ b/src/sm/CrossSections/warpingcrosssection.h @@ -36,9 +36,6 @@ #define warpingcrosssection_h #include "simplecrosssection.h" -// #include "structuralmaterial.h" -// #include "floatarray.h" -// #include "floatmatrix.h" ///@name Input fields for SimpleCrossSection //@{ @@ -50,34 +47,29 @@ namespace oofem { /** * description of warping cross section... */ -//class OOFEM_EXPORT WarpingCrossSection : public StructuralCrossSection { class OOFEM_EXPORT WarpingCrossSection : public SimpleCrossSection { -public: - - WarpingCrossSection(int n, Domain *d) : SimpleCrossSection(n, d) { - WarpingNodeNumber = 0; - } +protected: + int WarpingNodeNumber; // number of the 4rd node - virtual IRResultType initializeFrom(InputRecord *ir); +public: + WarpingCrossSection(int n, Domain *d) : SimpleCrossSection(n, d), WarpingNodeNumber(0) { } + void initializeFrom(InputRecord &ir) override; // identification and auxiliary functions - virtual const char *giveClassName() const { + const char *giveClassName() const override { return "WarpingCrossSection"; } - virtual const char *giveInputRecordName() const { + const char *giveInputRecordName() const override { return _IFT_WarpingCrossSection_Name; } int giveWarpingNodeNumber() const { return this->WarpingNodeNumber; - }; - -protected: - int WarpingNodeNumber; // number of the 4rd node + } }; } // end namespace oofem #endif // warpingcrosssection_h diff --git a/src/sm/Deprecated/prescribedgenstrainshell7.C b/src/sm/Deprecated/prescribedgenstrainshell7.C index 9fefdebb7..78a7bbbea 100644 --- a/src/sm/Deprecated/prescribedgenstrainshell7.C +++ b/src/sm/Deprecated/prescribedgenstrainshell7.C @@ -49,7 +49,7 @@ #include "feinterpol.h" #include "sparsemtrx.h" #include "sparselinsystemnm.h" -#include "Elements/Shells/shell7base.h" +#include "sm/Elements/Shells/shell7base.h" namespace oofem { REGISTER_BoundaryCondition(PrescribedGenStrainShell7); @@ -57,9 +57,9 @@ REGISTER_BoundaryCondition(PrescribedGenStrainShell7); double PrescribedGenStrainShell7 :: give(Dof *dof, ValueModeType mode, double time) { DofIDItem id = dof->giveDofID(); - FloatArray *coords = dof->giveDofManager()->giveCoordinates(); + const auto &coords = dof->giveDofManager()->giveCoordinates(); - if ( coords->giveSize() != this->centerCoord.giveSize() ) { + if ( coords.giveSize() != this->centerCoord.giveSize() ) { OOFEM_ERROR("PrescribedGenStrainShell7 :: give - Size of coordinate system different from center coordinate in b.c."); } @@ -76,7 +76,7 @@ double PrescribedGenStrainShell7 :: give(Dof *dof, ValueModeType mode, double ti // Reminder: u_i = F_ij . (x_j - xb_j) = H_ij . dx_j FloatArray dx; - dx.beDifferenceOf(* coords, this->centerCoord); + dx.beDifferenceOf(coords, this->centerCoord); // Assuming the coordinate system to be local, dx(3) = z this->setDeformationGradient( dx.at(3) ); @@ -110,32 +110,31 @@ double PrescribedGenStrainShell7 :: give(Dof *dof, ValueModeType mode, double ti -void -PrescribedGenStrainShell7 :: evalCovarBaseVectorsAt(FloatMatrix &gcov, FloatArray &genEps, double zeta) +FloatMatrixF<3,3> +PrescribedGenStrainShell7 :: evalCovarBaseVectorsAt(FloatArray &genEps, double zeta) { // Evaluates the covariant base vectors in the current configuration - FloatArray g1; FloatArray g2; FloatArray g3; - - FloatArray dxdxi1, dxdxi2, m, dmdxi1, dmdxi2; + FloatArrayF<3> dxdxi1, dxdxi2, m, dmdxi1, dmdxi2; double dgamdxi1, dgamdxi2, gam; Shell7Base :: giveGeneralizedStrainComponents(genEps, dxdxi1, dxdxi2, dmdxi1, dmdxi2, m, dgamdxi1, dgamdxi2, gam); double fac1 = ( zeta + 0.5 * gam * zeta * zeta ); double fac2 = ( 0.5 * zeta * zeta ); double fac3 = ( 1.0 + zeta * gam ); - g1 = dxdxi1 + fac1*dmdxi1 + fac2*dgamdxi1*m; - g2 = dxdxi2 + fac1*dmdxi2 + fac2*dgamdxi2*m; - g3 = fac3*m; - gcov.resize(3,3); + auto g1 = dxdxi1 + fac1*dmdxi1 + fac2*dgamdxi1*m; + auto g2 = dxdxi2 + fac1*dmdxi2 + fac2*dgamdxi2*m; + auto g3 = fac3*m; + FloatMatrixF<3,3> gcov; gcov.setColumn(g1,1); gcov.setColumn(g2,2); gcov.setColumn(g3,3); + return gcov; } -void -PrescribedGenStrainShell7 :: evalInitialCovarBaseVectorsAt(FloatMatrix &Gcov, FloatArray &genEps, double zeta) +FloatMatrixF<3,3> +PrescribedGenStrainShell7 :: evalInitialCovarBaseVectorsAt(FloatArray &genEps, double zeta) { // Evaluates the initial base vectors given the array of generalized strain - FloatArray G1(3), G2(3), G3(3); + FloatArrayF<3> G1, G2, G3; G1.at(1) = genEps.at(1) + zeta * genEps.at(7); G1.at(2) = genEps.at(2) + zeta * genEps.at(8); @@ -150,8 +149,9 @@ PrescribedGenStrainShell7 :: evalInitialCovarBaseVectorsAt(FloatMatrix &Gcov, Fl G3.at(3) = genEps.at(15); - Gcov.resize(3,3); - Gcov.setColumn(G1,1); Gcov.setColumn(G2,2); Gcov.setColumn(G3,3); + FloatMatrixF<3,3> Gcov; + Gcov.setColumn(G1,0); Gcov.setColumn(G2,1); Gcov.setColumn(G3,2); + return Gcov; } @@ -159,16 +159,11 @@ void PrescribedGenStrainShell7 :: setDeformationGradient(double zeta) { // Computes the deformation gradient in matrix form as open product(g_i, G^i) = gcov*Gcon^T - FloatMatrix gcov, Gcon, Gcov; + auto gcov = this->evalCovarBaseVectorsAt(this->genEps, zeta); + auto Gcov = this->evalInitialCovarBaseVectorsAt(this->initialGenEps, zeta); + auto Gcon = Shell7Base :: giveDualBase(Gcov); - this->evalCovarBaseVectorsAt(gcov, this->genEps, zeta); - this->evalInitialCovarBaseVectorsAt(Gcov, this->initialGenEps, zeta); - Shell7Base :: giveDualBase(Gcov, Gcon); - - this->gradient.beProductTOf(gcov, Gcon); - this->gradient.at(1,1) -= 1.0; - this->gradient.at(2,2) -= 1.0; - this->gradient.at(3,3) -= 1.0; + this->gradient = dotT(gcov, Gcon) - eye<3>(); } void @@ -176,23 +171,21 @@ PrescribedGenStrainShell7 :: evaluateHigherOrderContribution(FloatArray &answer, { // Computes the higher order contribution from the second gradient F2_ijk = (g3,3)_i * (G^3)_j * (G^3)_k // Simplified version with only contribtion in the xi-direction - FloatMatrix gcov, Gcon, Gcov; - - this->evalCovarBaseVectorsAt(gcov, this->genEps, zeta); - this->evalInitialCovarBaseVectorsAt(Gcov, this->initialGenEps, zeta); - Shell7Base :: giveDualBase(Gcov, Gcon); + //auto gcov = this->evalCovarBaseVectorsAt(this->genEps, zeta); + auto Gcov = this->evalInitialCovarBaseVectorsAt(this->initialGenEps, zeta); + auto Gcon = Shell7Base :: giveDualBase(Gcov); - FloatArray G3(3), g3prime(3), m(3); + FloatArrayF<3> G3, m; G3.at(1) = Gcon.at(1,3); G3.at(2) = Gcon.at(2,3); G3.at(3) = Gcon.at(3,3); - double factor = G3.dotProduct(dx); + double factor = dot(G3, dx); double gamma = this->genEps.at(18); m.at(1) = this->genEps.at(13); m.at(2) = this->genEps.at(14); m.at(3) = this->genEps.at(15); - g3prime = gamma*m; + auto g3prime = gamma*m; answer = 0.5*factor*factor * g3prime; @@ -228,8 +221,8 @@ void PrescribedGenStrainShell7 :: updateCoefficientMatrix(FloatMatrix &C) for ( int i = 1; i <= nNodes; i++ ) { Node *n = domain->giveNode(i); FloatArray *coords = n->giveCoordinates(); - Dof *d1 = n->giveDofWithID( this->dofs(0) ); - Dof *d2 = n->giveDofWithID( this->dofs(1) ); + Dof *d1 = n->giveDofWithID( this->dofs[0] ); + Dof *d2 = n->giveDofWithID( this->dofs[1] ); int k1 = d1->__givePrescribedEquationNumber(); int k2 = d2->__givePrescribedEquationNumber(); if ( nsd == 2 ) { @@ -287,18 +280,16 @@ double PrescribedGenStrainShell7 :: domainSize() -IRResultType PrescribedGenStrainShell7 :: initializeFrom(InputRecord *ir) +void PrescribedGenStrainShell7 :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + GeneralBoundaryCondition :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->initialGenEps, _IFT_PrescribedGenStrainShell7_initialgeneralizedstrain); IR_GIVE_FIELD(ir, this->genEps, _IFT_PrescribedGenStrainShell7_generalizedstrain); - this->centerCoord.resize( this->gradient.giveNumberOfColumns() ); - this->centerCoord.zero(); - IR_GIVE_OPTIONAL_FIELD(ir, this->centerCoord, _IFT_PrescribedGenStrainShell7_centercoords) - - return GeneralBoundaryCondition :: initializeFrom(ir); + FloatArray c; + IR_GIVE_OPTIONAL_FIELD(ir, c, _IFT_PrescribedGenStrainShell7_centercoords) + this->centerCoord = c; } diff --git a/src/sm/Deprecated/prescribedgenstrainshell7.h b/src/sm/Deprecated/prescribedgenstrainshell7.h index 42edda2ee..abd554a9e 100644 --- a/src/sm/Deprecated/prescribedgenstrainshell7.h +++ b/src/sm/Deprecated/prescribedgenstrainshell7.h @@ -1,4 +1,4 @@ -/* + /* * * ##### ##### ###### ###### ### ### * ## ## ## ## ## ## ## ### ## @@ -41,6 +41,7 @@ #include "valuemodetype.h" #include "floatarray.h" #include "floatmatrix.h" +#include "floatmatrixf.h" ///@name Input fields for PrescribedTensor //@{ @@ -63,7 +64,7 @@ class OOFEM_EXPORT PrescribedGenStrainShell7 : public BoundaryCondition { protected: /// Prescribed gradient @f$ d_{ij} @f$ - FloatMatrix gradient; + FloatMatrixF<3,3> gradient; /** * Initial generalized strain @@ -77,7 +78,7 @@ class OOFEM_EXPORT PrescribedGenStrainShell7 : public BoundaryCondition FloatArray genEps; /// Center coordinate @f$ \bar{x}_i @f$ - FloatArray centerCoord; + FloatArrayF<3> centerCoord; public: /** @@ -90,9 +91,9 @@ class OOFEM_EXPORT PrescribedGenStrainShell7 : public BoundaryCondition /// Destructor virtual ~PrescribedGenStrainShell7() { } - virtual double give(Dof *dof, ValueModeType mode, double time); + double give(Dof *dof, ValueModeType mode, double time) override; - virtual bcType giveType() const { return DirichletBT; } + bcType giveType() const override { return DirichletBT; } /** * Initializes receiver according to object description stored in input record. @@ -102,8 +103,8 @@ class OOFEM_EXPORT PrescribedGenStrainShell7 : public BoundaryCondition * The prescribed tensor's columns must be equal to the size of the center coordinates. * The size of the center coordinates must be equal to the size of the coordinates in the applied nodes. */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; /** * Constructs a coefficient matrix for all prescribed unknowns. @@ -114,8 +115,8 @@ class OOFEM_EXPORT PrescribedGenStrainShell7 : public BoundaryCondition //void updateCoefficientMatrix(FloatMatrix &C); - void evalCovarBaseVectorsAt(FloatMatrix &gcov, FloatArray &genEps, double zeta); - void evalInitialCovarBaseVectorsAt(FloatMatrix &Gcov, FloatArray &genEps, double zeta); + FloatMatrixF<3,3> evalCovarBaseVectorsAt(FloatArray &genEps, double zeta); + FloatMatrixF<3,3> evalInitialCovarBaseVectorsAt(FloatArray &genEps, double zeta); void setDeformationGradient(double zeta); void evaluateHigherOrderContribution(FloatArray &answer, double zeta, FloatArray &dx); @@ -125,10 +126,10 @@ class OOFEM_EXPORT PrescribedGenStrainShell7 : public BoundaryCondition */ virtual void setCenterCoordinate(const FloatArray &x) { centerCoord = x; } /// Returns the center coordinate - virtual FloatArray &giveCenterCoordinate() { return centerCoord; } + virtual FloatArrayF<3> &giveCenterCoordinate() { return centerCoord; } - virtual const char *giveClassName() const { return "PrescribedGenStrainShell7"; } - virtual const char *giveInputRecordName() const { return _IFT_PrescribedGenStrainShell7_Name; } + const char *giveClassName() const override { return "PrescribedGenStrainShell7"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedGenStrainShell7_Name; } protected: double domainSize(); diff --git a/src/sm/Deprecated/prescribedgradientshell7base.C b/src/sm/Deprecated/prescribedgradientshell7base.C index cc6736f7c..27bcf945c 100644 --- a/src/sm/Deprecated/prescribedgradientshell7base.C +++ b/src/sm/Deprecated/prescribedgradientshell7base.C @@ -150,8 +150,8 @@ void PrescribedGenStrainShell7 :: updateCoefficientMatrix(FloatMatrix &C) for ( int i = 1; i <= nNodes; i++ ) { Node *n = domain->giveNode(i); FloatArray *coords = n->giveCoordinates(); - Dof *d1 = n->giveDofWithID( this->dofs(0) ); - Dof *d2 = n->giveDofWithID( this->dofs(1) ); + Dof *d1 = n->giveDofWithID( this->dofs[0] ); + Dof *d2 = n->giveDofWithID( this->dofs[1] ); int k1 = d1->__givePrescribedEquationNumber(); int k2 = d2->__givePrescribedEquationNumber(); if ( nsd == 2 ) { @@ -277,17 +277,15 @@ void PrescribedGenStrainShell7 :: computeTangent(FloatMatrix &tangent, EquationI } -IRResultType PrescribedGenStrainShell7 :: initializeFrom(InputRecord *ir) +void PrescribedGenStrainShell7 :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + GeneralBoundaryCondition :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->gradient, _IFT_PrescribedGenStrainShell7_gradient); this->centerCoord.resize( this->gradient.giveNumberOfColumns() ); this->centerCoord.zero(); IR_GIVE_OPTIONAL_FIELD(ir, this->centerCoord, _IFT_PrescribedGenStrainShell7_centercoords) - - return GeneralBoundaryCondition :: initializeFrom(ir); } diff --git a/src/sm/Deprecated/prescribedgradientshell7base.h b/src/sm/Deprecated/prescribedgradientshell7base.h index 0faa039f3..25f24dfd9 100644 --- a/src/sm/Deprecated/prescribedgradientshell7base.h +++ b/src/sm/Deprecated/prescribedgradientshell7base.h @@ -78,9 +78,9 @@ class OOFEM_EXPORT PrescribedGenStrainShell7 : public BoundaryCondition /// Destructor virtual ~PrescribedGenStrainShell7() { } - virtual double give(Dof *dof, ValueModeType mode, double time); + double give(Dof *dof, ValueModeType mode, double time) override; - virtual bcType giveType() const { return DirichletBT; } + bcType giveType() const override { return DirichletBT; } /** * Initializes receiver according to object description stored in input record. @@ -90,8 +90,8 @@ class OOFEM_EXPORT PrescribedGenStrainShell7 : public BoundaryCondition * The prescribed tensor's columns must be equal to the size of the center coordinates. * The size of the center coordinates must be equal to the size of the coordinates in the applied nodes. */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; /** * Constructs a coefficient matrix for all prescribed unknowns. @@ -117,7 +117,7 @@ class OOFEM_EXPORT PrescribedGenStrainShell7 : public BoundaryCondition */ void computeTangent(FloatMatrix &tangent, EquationID eid, TimeStep *tStep); - virtual void scale(double s) { gradient.times(s); } + void scale(double s) override { gradient.times(s); } /** * Set prescribed tensor. @@ -140,8 +140,8 @@ class OOFEM_EXPORT PrescribedGenStrainShell7 : public BoundaryCondition /// Returns the center coordinate virtual FloatArray &giveCenterCoordinate() { return centerCoord; } - virtual const char *giveClassName() const { return "PrescribedGenStrainShell7"; } - virtual const char *giveInputRecordName() const { return _IFT_PrescribedGenStrainShell7_Name; } + const char *giveClassName() const override { return "PrescribedGenStrainShell7"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedGenStrainShell7_Name; } protected: double domainSize(); diff --git a/src/sm/Elements/3D/lspace.C b/src/sm/Elements/3D/lspace.C index 4dadd06d5..7f91865ef 100644 --- a/src/sm/Elements/3D/lspace.C +++ b/src/sm/Elements/3D/lspace.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/3D/lspace.h" +#include "sm/Elements/3D/lspace.h" #include "fei3dhexalin.h" #include "node.h" #include "gausspoint.h" @@ -48,7 +48,7 @@ #ifdef __OOFEG #include "oofeggraphiccontext.h" #include "oofegutils.h" - #include "Materials/rcm2.h" + #include "sm/Materials/rcm2.h" #endif namespace oofem { @@ -87,14 +87,48 @@ LSpace :: giveInterface(InterfaceType interface) } -IRResultType -LSpace :: initializeFrom(InputRecord *ir) +void +LSpace :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 8; - return Structural3DElement :: initializeFrom(ir); + Structural3DElement :: initializeFrom(ir); + this->reducedShearIntegration = ir.hasField(_IFT_LSpace_reducedShearIntegration); +} + + + +void +LSpace :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +// Returns the [ 6 x (nno*3) ] strain-displacement matrix {B} of the receiver, eva- +// luated at gp. +// B matrix - 6 rows : epsilon-X, epsilon-Y, epsilon-Z, gamma-YZ, gamma-ZX, gamma-XY : +{ + FEInterpolation *interp = this->giveInterpolation(); + FloatMatrix dNdx, dNdxShear; + interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + if ( this->reducedShearIntegration ) { + interp->evaldNdx( dNdxShear, { 0., 0., 0. }, FEIElementGeometryWrapper(this) ); + } else { + dNdxShear = dNdx; + } + + answer.resize(6, dNdx.giveNumberOfRows() * 3); + answer.zero(); + + for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { + answer.at(1, 3 * i - 2) = dNdx.at(i, 1); + answer.at(2, 3 * i - 1) = dNdx.at(i, 2); + answer.at(3, 3 * i - 0) = dNdx.at(i, 3); + + answer.at(5, 3 * i - 2) = answer.at(4, 3 * i - 1) = dNdxShear.at(i, 3); + answer.at(6, 3 * i - 2) = answer.at(4, 3 * i - 0) = dNdxShear.at(i, 2); + answer.at(6, 3 * i - 1) = answer.at(5, 3 * i - 0) = dNdxShear.at(i, 1); + } } + + void LSpace :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) { @@ -151,7 +185,7 @@ LSpace :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int nod int size = 0; - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( GaussPoint *gp : *integrationRulesArray [ 0 ] ) { giveIPValue(val, gp, type, tStep); if ( size == 0 ) { size = val.giveSize(); @@ -254,9 +288,8 @@ LSpace :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refin IntArray &controlNode, IntArray &controlDof, HuertaErrorEstimator :: AnalysisMode aMode) { - FloatArray *corner [ 8 ], midSide [ 12 ], midFace [ 6 ], midNode; double x = 0.0, y = 0.0, z = 0.0; - int inode, nodes = 8, iside, sides = 12, iface, faces = 6, nd, nd1, nd2; + int nodes = 8, sides = 12, faces = 6; static int sideNode [ 12 ] [ 2 ] = { { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 1 }, // bottom { 5, 6 }, { 6, 7 }, { 7, 8 }, { 8, 5 }, // top @@ -273,25 +306,26 @@ LSpace :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refin static int hexaFaceNode [ 8 ] [ 3 ] = { { 1, 3, 6 }, { 1, 4, 3 }, { 1, 5, 4 }, { 1, 6, 5 }, { 2, 6, 3 }, { 2, 3, 4 }, { 2, 4, 5 }, { 2, 5, 6 } }; + FloatArray corner [ 8 ], midSide [ 12 ], midFace [ 6 ], midNode; if ( sMode == HuertaErrorEstimatorInterface :: NodeMode || - ( sMode == HuertaErrorEstimatorInterface :: BCMode && aMode == HuertaErrorEstimator :: HEE_linear ) ) { - for ( inode = 0; inode < nodes; inode++ ) { + ( sMode == HuertaErrorEstimatorInterface :: BCMode && aMode == HuertaErrorEstimator :: HEE_linear ) ) { + for ( int inode = 0; inode < nodes; inode++ ) { corner [ inode ] = this->giveNode(inode + 1)->giveCoordinates(); - x += corner [ inode ]->at(1); - y += corner [ inode ]->at(2); - z += corner [ inode ]->at(3); + x += corner [ inode ].at(1); + y += corner [ inode ].at(2); + z += corner [ inode ].at(3); } - for ( iside = 0; iside < sides; iside++ ) { + for ( int iside = 0; iside < sides; iside++ ) { midSide [ iside ].resize(3); - nd1 = sideNode [ iside ] [ 0 ] - 1; - nd2 = sideNode [ iside ] [ 1 ] - 1; + int nd1 = sideNode [ iside ] [ 0 ] - 1; + int nd2 = sideNode [ iside ] [ 1 ] - 1; - midSide [ iside ].at(1) = ( corner [ nd1 ]->at(1) + corner [ nd2 ]->at(1) ) / 2.0; - midSide [ iside ].at(2) = ( corner [ nd1 ]->at(2) + corner [ nd2 ]->at(2) ) / 2.0; - midSide [ iside ].at(3) = ( corner [ nd1 ]->at(3) + corner [ nd2 ]->at(3) ) / 2.0; + midSide [ iside ].at(1) = ( corner [ nd1 ].at(1) + corner [ nd2 ].at(1) ) / 2.0; + midSide [ iside ].at(2) = ( corner [ nd1 ].at(2) + corner [ nd2 ].at(2) ) / 2.0; + midSide [ iside ].at(3) = ( corner [ nd1 ].at(3) + corner [ nd2 ].at(3) ) / 2.0; } midNode.resize(3); @@ -300,13 +334,13 @@ LSpace :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refin midNode.at(2) = y / nodes; midNode.at(3) = z / nodes; - for ( iface = 0; iface < faces; iface++ ) { + for ( int iface = 0; iface < faces; iface++ ) { x = y = z = 0.0; - for ( inode = 0; inode < 4; inode++ ) { - nd = faceNode [ iface ] [ inode ] - 1; - x += corner [ nd ]->at(1); - y += corner [ nd ]->at(2); - z += corner [ nd ]->at(3); + for ( int inode = 0; inode < 4; inode++ ) { + int nd = faceNode [ iface ] [ inode ] - 1; + x += corner [ nd ].at(1); + y += corner [ nd ].at(2); + z += corner [ nd ].at(3); } midFace [ iface ].resize(3); @@ -397,7 +431,7 @@ void LSpace :: drawTriad(FloatArray &coords, int isurf) // version II // determine surface center - IntArray snodes(4); + //IntArray snodes(4); FloatArray h1(3), h2(3), nn(3), n(3); int j; const char *colors[] = { @@ -405,9 +439,9 @@ void LSpace :: drawTriad(FloatArray &coords, int isurf) }; - this->interpolation.computeSurfaceMapping(snodes, dofManArray, isurf); + IntArray snodes = this->interpolation.computeSurfaceMapping(dofManArray, isurf); for ( i = 1; i <= 4; i++ ) { - gc.add( * ( domain->giveNode( snodes.at(i) )->giveCoordinates() ) ); + gc.add( domain->giveNode( snodes.at(i) )->giveCoordinates() ); } gc.times(1. / 4.); @@ -415,9 +449,9 @@ void LSpace :: drawTriad(FloatArray &coords, int isurf) nn.zero(); for ( i = 1; i <= 4; i++ ) { j = ( i ) % 4 + 1; - h1 = * domain->giveNode( snodes.at(i) )->giveCoordinates(); + h1 = domain->giveNode( snodes.at(i) )->giveCoordinates(); h1.subtract(gc); - h2 = * domain->giveNode( snodes.at(j) )->giveCoordinates(); + h2 = domain->giveNode( snodes.at(j) )->giveCoordinates(); h2.subtract(gc); n.beVectorProductOf(h1, h2); if ( n.dotProduct(n, 3) > 1.e-6 ) { @@ -575,7 +609,7 @@ LSpace :: drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) double length; FloatArray crackDir; - for ( GaussPoint *gp: *this->giveDefaultIntegrationRulePtr() ) { + for ( GaussPoint *gp : *this->giveDefaultIntegrationRulePtr() ) { if ( this->giveIPValue(cf, gp, IST_CrackedFlag, tStep) == 0 ) { return; } @@ -587,7 +621,7 @@ LSpace :: drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) // // obtain gp global coordinates this->computeGlobalCoordinates( gpc, gp->giveNaturalCoordinates() ); - length = 0.3333 * cbrt(this->computeVolumeAround(gp)); + length = 0.3333 * cbrt( this->computeVolumeAround(gp) ); if ( this->giveIPValue(crackDir, gp, IST_CrackDirs, tStep) ) { this->giveIPValue(crackStatuses, gp, IST_CrackStatuses, tStep); @@ -644,17 +678,6 @@ LSpace :: drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) #endif - -IntegrationRule * -LSpace :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Square, approxOrder); - iRule->SetUpPointsOnSquare(npoints, _Unknown); - return iRule; -} - - int LSpace :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) { @@ -676,27 +699,25 @@ LSpace :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPo */ FloatArray gc(3); FloatArray h1(3), h2(3), nn(3), n(3); - IntArray snodes(4); answer.resize(3, 3); - this->interpolation.computeSurfaceMapping(snodes, dofManArray, isurf); + const auto &snodes = this->interpolation.computeSurfaceMapping(dofManArray, isurf); for ( int i = 1; i <= 4; i++ ) { - gc.add( * domain->giveNode( snodes.at(i) )->giveCoordinates() ); + gc.add( domain->giveNode( snodes.at(i) )->giveCoordinates() ); } gc.times(1. / 4.); // determine "average normal" for ( int i = 1; i <= 4; i++ ) { int j = ( i ) % 4 + 1; - h1 = * domain->giveNode( snodes.at(i) )->giveCoordinates(); + h1 = domain->giveNode( snodes.at(i) )->giveCoordinates(); h1.subtract(gc); - h2 = * domain->giveNode( snodes.at(j) )->giveCoordinates(); + h1.normalize(); + h2 = domain->giveNode( snodes.at(j) )->giveCoordinates(); h2.subtract(gc); + h2.normalize(); n.beVectorProductOf(h1, h2); - if ( n.computeSquaredNorm() > 1.e-6 ) { - n.normalize(); - } nn.add(n); } diff --git a/src/sm/Elements/3D/lspace.h b/src/sm/Elements/3D/lspace.h index 956f769d1..bff00e241 100644 --- a/src/sm/Elements/3D/lspace.h +++ b/src/sm/Elements/3D/lspace.h @@ -35,14 +35,15 @@ #ifndef lspace_h #define lspace_h -#include "Elements/structural3delement.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/structural3delement.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "spatiallocalizer.h" #define _IFT_LSpace_Name "lspace" +#define _IFT_LSpace_reducedShearIntegration "reducedshearint" namespace oofem { class FEI3dHexaLin; @@ -58,60 +59,60 @@ class FEI3dHexaLin; * - Calculating its B,D,N matrices and dV. */ class LSpace : public Structural3DElement, public ZZNodalRecoveryModelInterface, -public SPRNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface, -public SpatialLocalizerInterface, -public HuertaErrorEstimatorInterface + public SPRNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface, + public SpatialLocalizerInterface, + public HuertaErrorEstimatorInterface { protected: static FEI3dHexaLin interpolation; - + bool reducedShearIntegration; public: - LSpace(int n, Domain * d); + LSpace(int n, Domain *d); virtual ~LSpace() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual Interface *giveInterface(InterfaceType it); - virtual int testElementExtension(ElementExtension ext) + Interface *giveInterface(InterfaceType it) override; + int testElementExtension(ElementExtension ext) override { return ( ( ( ext == Element_EdgeLoadSupport ) || ( ext == Element_SurfaceLoadSupport ) ) ? 1 : 0 ); } - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; + + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, - IntArray &localNodeIdArray, IntArray &globalNodeIdArray, - HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, - int &localNodeId, int &localElemId, int &localBcId, - IntArray &controlNode, IntArray &controlDof, - HuertaErrorEstimator :: AnalysisMode aMode); - virtual void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); + void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, + IntArray &localNodeIdArray, IntArray &globalNodeIdArray, + HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, + int &localNodeId, int &localElemId, int &localBcId, + IntArray &controlNode, IntArray &controlDof, + HuertaErrorEstimator :: AnalysisMode aMode) override; + void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LSpace_Name; } - virtual const char *giveClassName() const { return "LSpace"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_LSpace_Name; } + const char *giveClassName() const override { return "LSpace"; } + void initializeFrom(InputRecord &ir) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) override; void drawTriad(FloatArray &, int isurf); #endif protected: - virtual int giveNumberOfIPForMassMtrxIntegration() { return 8; } - + int giveNumberOfIPForMassMtrxIntegration() override { return 8; } + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) override; /** * @name Surface load support */ //@{ - virtual IntegrationRule *GetSurfaceIntegrationRule(int iSurf); - virtual int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp); + int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp) override; //@} }; } // end namespace oofem diff --git a/src/sm/Elements/3D/lspacebb.C b/src/sm/Elements/3D/lspacebb.C index 1529980ba..ac7491cca 100644 --- a/src/sm/Elements/3D/lspacebb.C +++ b/src/sm/Elements/3D/lspacebb.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/3D/lspacebb.h" +#include "sm/Elements/3D/lspacebb.h" #include "fei3dhexalin.h" #include "gausspoint.h" #include "floatmatrix.h" diff --git a/src/sm/Elements/3D/lspacebb.h b/src/sm/Elements/3D/lspacebb.h index 8207c6138..5a702d424 100644 --- a/src/sm/Elements/3D/lspacebb.h +++ b/src/sm/Elements/3D/lspacebb.h @@ -35,7 +35,7 @@ #ifndef lspacebb_h #define lspacebb_h -#include "../sm/Elements/3D/lspace.h" +#include "sm/Elements/3D/lspace.h" #define _IFT_LSpaceBB_Name "lspacebb" @@ -51,11 +51,11 @@ class LSpaceBB : public LSpace LSpaceBB(int n, Domain * d); virtual ~LSpaceBB() { } - virtual const char *giveInputRecordName() const { return _IFT_LSpaceBB_Name; } - virtual const char *giveClassName() const { return "LSpaceBB"; } + const char *giveInputRecordName() const override { return _IFT_LSpaceBB_Name; } + const char *giveClassName() const override { return "LSpaceBB"; } protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; }; } // end namespace oofem #endif // lspacebb_h diff --git a/src/sm/Elements/3D/ltrspace.C b/src/sm/Elements/3D/ltrspace.C index efaac6165..fd04361ae 100644 --- a/src/sm/Elements/3D/ltrspace.C +++ b/src/sm/Elements/3D/ltrspace.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/3D/ltrspace.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/3D/ltrspace.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "node.h" #include "material.h" #include "gausspoint.h" @@ -48,7 +48,7 @@ #ifdef __OOFEG #include "oofeggraphiccontext.h" #include "oofegutils.h" - #include "Materials/rcm2.h" + #include "sm/Materials/rcm2.h" #include #endif @@ -187,9 +187,8 @@ LTRSpace :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *ref IntArray &controlNode, IntArray &controlDof, HuertaErrorEstimator :: AnalysisMode aMode) { - FloatArray *corner [ 4 ], midSide [ 6 ], midFace [ 4 ], midNode; double x = 0.0, y = 0.0, z = 0.0; - int inode, nodes = 4, iside, sides = 6, iface, faces = 4, nd, nd1, nd2; + int nodes = 4, sides = 6, faces = 4; static int sideNode [ 6 ] [ 2 ] = { { 1, 2 }, { 2, 3 }, { 3, 1 }, { 1, 4 }, { 2, 4 }, { 3, 4 } }; static int faceNode [ 4 ] [ 3 ] = { { 1, 2, 3 }, { 1, 2, 4 }, { 2, 3, 4 }, { 3, 1, 4 } }; @@ -201,25 +200,26 @@ LTRSpace :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *ref int hexaSideNode [ 4 ] [ 3 ] = { { 1, 3, 4 }, { 2, 1, 5 }, { 3, 2, 6 }, { 4, 6, 5 } }; int hexaFaceNode [ 4 ] [ 3 ] = { { 1, 2, 4 }, { 1, 3, 2 }, { 1, 4, 3 }, { 4, 2, 3 } }; + FloatArray corner [ 4 ], midSide [ 6 ], midFace [ 4 ], midNode; if ( sMode == HuertaErrorEstimatorInterface :: NodeMode || ( sMode == HuertaErrorEstimatorInterface :: BCMode && aMode == HuertaErrorEstimator :: HEE_linear ) ) { - for ( inode = 0; inode < nodes; inode++ ) { + for ( int inode = 0; inode < nodes; inode++ ) { corner [ inode ] = this->giveNode(inode + 1)->giveCoordinates(); - x += corner [ inode ]->at(1); - y += corner [ inode ]->at(2); - z += corner [ inode ]->at(3); + x += corner [ inode ].at(1); + y += corner [ inode ].at(2); + z += corner [ inode ].at(3); } - for ( iside = 0; iside < sides; iside++ ) { + for ( int iside = 0; iside < sides; iside++ ) { midSide [ iside ].resize(3); - nd1 = sideNode [ iside ] [ 0 ] - 1; - nd2 = sideNode [ iside ] [ 1 ] - 1; + int nd1 = sideNode [ iside ] [ 0 ] - 1; + int nd2 = sideNode [ iside ] [ 1 ] - 1; - midSide [ iside ].at(1) = ( corner [ nd1 ]->at(1) + corner [ nd2 ]->at(1) ) / 2.0; - midSide [ iside ].at(2) = ( corner [ nd1 ]->at(2) + corner [ nd2 ]->at(2) ) / 2.0; - midSide [ iside ].at(3) = ( corner [ nd1 ]->at(3) + corner [ nd2 ]->at(3) ) / 2.0; + midSide [ iside ].at(1) = ( corner [ nd1 ].at(1) + corner [ nd2 ].at(1) ) / 2.0; + midSide [ iside ].at(2) = ( corner [ nd1 ].at(2) + corner [ nd2 ].at(2) ) / 2.0; + midSide [ iside ].at(3) = ( corner [ nd1 ].at(3) + corner [ nd2 ].at(3) ) / 2.0; } midNode.resize(3); @@ -228,13 +228,13 @@ LTRSpace :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *ref midNode.at(2) = y / nodes; midNode.at(3) = z / nodes; - for ( iface = 0; iface < faces; iface++ ) { + for ( int iface = 0; iface < faces; iface++ ) { x = y = z = 0.0; - for ( inode = 0; inode < 3; inode++ ) { - nd = faceNode [ iface ] [ inode ] - 1; - x += corner [ nd ]->at(1); - y += corner [ nd ]->at(2); - z += corner [ nd ]->at(3); + for ( int inode = 0; inode < 3; inode++ ) { + int nd = faceNode [ iface ] [ inode ] - 1; + x += corner [ nd ].at(1); + y += corner [ nd ].at(2); + z += corner [ nd ].at(3); } midFace [ iface ].resize(3); @@ -505,16 +505,4 @@ LTRSpace :: drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) #endif - -IntegrationRule * -LTRSpace :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, approxOrder); - iRule->SetUpPointsOnTriangle(npoints, _Unknown); - return iRule; -} - - - } // end namespace oofem diff --git a/src/sm/Elements/3D/ltrspace.h b/src/sm/Elements/3D/ltrspace.h index e2063b535..a2aa30552 100644 --- a/src/sm/Elements/3D/ltrspace.h +++ b/src/sm/Elements/3D/ltrspace.h @@ -35,14 +35,14 @@ #ifndef ltrspace_h #define ltrspace_h -#include "Elements/structural3delement.h" -#include "ErrorEstimators/directerrorindicatorrc.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/structural3delement.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "sprnodalrecoverymodel.h" #include "spatiallocalizer.h" -#include "ErrorEstimators/zzerrorestimator.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" #include "mmashapefunctprojection.h" #define _IFT_LTRSpace_Name "ltrspace" @@ -67,50 +67,41 @@ public HuertaErrorEstimatorInterface LTRSpace(int n, Domain * d); virtual ~LTRSpace() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual int giveNumberOfIPForMassMtrxIntegration() { return 4; } - virtual Interface *giveInterface(InterfaceType it); + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + int giveNumberOfIPForMassMtrxIntegration() override { return 4; } + Interface *giveInterface(InterfaceType it) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LTRSpace_Name; } - virtual const char *giveClassName() const { return "LTRSpace"; } - + const char *giveInputRecordName() const override { return _IFT_LTRSpace_Name; } + const char *giveClassName() const override { return "LTRSpace"; } + #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) override; #endif - virtual double giveRelativeSelfComputationalCost() { return 2.15; } + double giveRelativeSelfComputationalCost() override { return 2.15; } - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; // HuertaErrorEstimatorInterface - virtual void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, - IntArray &localNodeIdArray, IntArray &globalNodeIdArray, - HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, - int &localNodeId, int &localElemId, int &localBcId, - IntArray &controlNode, IntArray &controlDof, - HuertaErrorEstimator :: AnalysisMode aMode); - virtual void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); - -protected: - - /** - * @name Surface load support - */ - //@{ - virtual IntegrationRule *GetSurfaceIntegrationRule(int); - //@} + void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, + IntArray &localNodeIdArray, IntArray &globalNodeIdArray, + HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, + int &localNodeId, int &localElemId, int &localBcId, + IntArray &controlNode, IntArray &controlDof, + HuertaErrorEstimator :: AnalysisMode aMode) override; + void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; }; } // end namespace oofem #endif // ltrspace_h diff --git a/src/sm/Elements/3D/ltrspaceboundary.C b/src/sm/Elements/3D/ltrspaceboundary.C new file mode 100644 index 000000000..c108fb1d5 --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundary.C @@ -0,0 +1,541 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/3D/ltrspaceboundary.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "fei3dtetlin.h" +#include "classfactory.h" +#include "Materials/structuralms.h" + + +namespace oofem { +REGISTER_Element(LTRSpaceBoundary); + +FEI3dTetLin LTRSpaceBoundary :: interpolation; + +LTRSpaceBoundary :: LTRSpaceBoundary(int n, Domain *aDomain) : + Structural3DElement(n, aDomain), NodalAveragingRecoveryModelInterface(), SpatialLocalizerInterface(this) +{ + numberOfDofMans = 5; + numberOfGaussPoints = 1; +} + +void +LTRSpaceBoundary :: initializeFrom(InputRecord &ir) +{ + Structural3DElement :: initializeFrom(ir); + IR_GIVE_FIELD(ir, location, _IFT_LTRSpaceBoundary_Location); +} + +Interface * +LTRSpaceBoundary :: giveInterface(InterfaceType interface) +{ + if ( interface == NodalAveragingRecoveryModelInterfaceType ) { + return static_cast< NodalAveragingRecoveryModelInterface * >( this ); + } else if ( interface == SpatialLocalizerInterfaceType ) { + return static_cast< SpatialLocalizerInterface * >( this ); + } + + return NULL; +} + + +FEInterpolation * +LTRSpaceBoundary :: giveInterpolation() const +{ + return & interpolation; +} + +int +LTRSpaceBoundary :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ + FEInterpolation *fei = this->giveInterpolation(); + FloatArray n; + FEIElementGeometryWrapper cellgeo(this); + + fei->evalN(n, lcoords, cellgeo); //this interpolation doesn't use cell geometry to compute shape functions, so it's ok to have it here + + answer.clear(); + for ( int i = 1; i <= 4; i++ ) { + if ( location.at(i) != 0 ) { //recalculate vertex coordinates + IntArray switches; + FloatArray vertexCoords; + recalculateCoordinates(i, vertexCoords); + + answer.add(n.at(i), vertexCoords); + } else { + answer.add(n.at(i), cellgeo.giveVertexCoordinates(i) ); + } + } + + return true; +} + +void +LTRSpaceBoundary :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 5 ) { + answer = { E_xx, E_xy, E_xz, E_yx, E_yy, E_yz, E_zx, E_zy, E_zz }; + } else { + answer = { D_u, D_v, D_w }; + } +} + +void +LTRSpaceBoundary :: giveSwitches(IntArray &answer, int location) { + answer.resize(3); + int counter = 1; + for ( int x = -1; x < 2; x++ ) { + for ( int y = -1; y < 2; y++ ) { + for ( int z = -1; z < 2; z++ ) { + if ( !( z == 0 && y == 0 && x == 0 ) ) { + if ( counter == location ) { + answer(0) = x; + answer(1) = y; + answer(2) = z; + } + counter++; + } + } + } + } + return; +} + +double +LTRSpaceBoundary :: computeVolumeAround(GaussPoint *gp) +{ + double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4, detJ, weight, volume; + FloatArray v1, v2, v3, v4; + + recalculateCoordinates(1, v1); + recalculateCoordinates(2, v2); + recalculateCoordinates(3, v3); + recalculateCoordinates(4, v4); + + x1 = v1.at(1); + x2 = v2.at(1); + x3 = v3.at(1); + x4 = v4.at(1); + y1 = v1.at(2); + y2 = v2.at(2); + y3 = v3.at(2); + y4 = v4.at(2); + z1 = v1.at(3); + z2 = v2.at(3); + z3 = v3.at(3); + z4 = v4.at(3); + + detJ = ( ( x4 - x1 ) * ( y2 - y1 ) * ( z3 - z1 ) - ( x4 - x1 ) * ( y3 - y1 ) * ( z2 - z1 ) + + ( x3 - x1 ) * ( y4 - y1 ) * ( z2 - z1 ) - ( x2 - x1 ) * ( y4 - y1 ) * ( z3 - z1 ) + + ( x2 - x1 ) * ( y3 - y1 ) * ( z4 - z1 ) - ( x3 - x1 ) * ( y2 - y1 ) * ( z4 - z1 ) ); + + if ( detJ <= 0.0 ) { + OOFEM_ERROR("negative volume"); + } + + weight = gp->giveWeight(); + volume = detJ * weight; + + return volume; +} + +void +LTRSpaceBoundary :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +{ + double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4, detJ; + FloatArray v1, v2, v3, v4; + FloatMatrix dNdx; + + recalculateCoordinates(1, v1); + recalculateCoordinates(2, v2); + recalculateCoordinates(3, v3); + recalculateCoordinates(4, v4); + + x1 = v1.at(1); + x2 = v2.at(1); + x3 = v3.at(1); + x4 = v4.at(1); + y1 = v1.at(2); + y2 = v2.at(2); + y3 = v3.at(2); + y4 = v4.at(2); + z1 = v1.at(3); + z2 = v2.at(3); + z3 = v3.at(3); + z4 = v4.at(3); + + detJ = ( ( x4 - x1 ) * ( y2 - y1 ) * ( z3 - z1 ) - ( x4 - x1 ) * ( y3 - y1 ) * ( z2 - z1 ) + + ( x3 - x1 ) * ( y4 - y1 ) * ( z2 - z1 ) - ( x2 - x1 ) * ( y4 - y1 ) * ( z3 - z1 ) + + ( x2 - x1 ) * ( y3 - y1 ) * ( z4 - z1 ) - ( x3 - x1 ) * ( y2 - y1 ) * ( z4 - z1 ) ); + + if ( detJ <= 0.0 ) { + OOFEM_ERROR("negative volume"); + } + + dNdx.resize(4, 3); + dNdx.at(1, 1) = -( ( y3 - y2 ) * ( z4 - z2 ) - ( y4 - y2 ) * ( z3 - z2 ) ); + dNdx.at(2, 1) = ( y4 - y3 ) * ( z1 - z3 ) - ( y1 - y3 ) * ( z4 - z3 ); + dNdx.at(3, 1) = -( ( y1 - y4 ) * ( z2 - z4 ) - ( y2 - y4 ) * ( z1 - z4 ) ); + dNdx.at(4, 1) = ( y2 - y1 ) * ( z3 - z1 ) - ( y3 - y1 ) * ( z2 - z1 ); + + dNdx.at(1, 2) = -( ( x4 - x2 ) * ( z3 - z2 ) - ( x3 - x2 ) * ( z4 - z2 ) ); + dNdx.at(2, 2) = ( x1 - x3 ) * ( z4 - z3 ) - ( x4 - x3 ) * ( z1 - z3 ); + dNdx.at(3, 2) = -( ( x2 - x4 ) * ( z1 - z4 ) - ( x1 - x4 ) * ( z2 - z4 ) ); + dNdx.at(4, 2) = ( x3 - x1 ) * ( z2 - z1 ) - ( x2 - x1 ) * ( z3 - z1 ); + + dNdx.at(1, 3) = -( ( x3 - x2 ) * ( y4 - y2 ) - ( x4 - x2 ) * ( y3 - y2 ) ); + dNdx.at(2, 3) = ( x4 - x3 ) * ( y1 - y3 ) - ( x1 - x3 ) * ( y4 - y3 ); + dNdx.at(3, 3) = -( ( x1 - x4 ) * ( y2 - y4 ) - ( x2 - x4 ) * ( y1 - y4 ) ); + dNdx.at(4, 3) = ( x2 - x1 ) * ( y3 - y1 ) - ( x3 - x1 ) * ( y2 - y1 ); + dNdx.times(1. / detJ); + + answer.resize(6, dNdx.giveNumberOfRows() * 3); + answer.zero(); + + for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { + answer.at(1, 3 * i - 2) = dNdx.at(i, 1); + answer.at(2, 3 * i - 1) = dNdx.at(i, 2); + answer.at(3, 3 * i - 0) = dNdx.at(i, 3); + + answer.at(5, 3 * i - 2) = answer.at(4, 3 * i - 1) = dNdx.at(i, 3); + answer.at(6, 3 * i - 2) = answer.at(4, 3 * i - 0) = dNdx.at(i, 2); + answer.at(6, 3 * i - 1) = answer.at(5, 3 * i - 0) = dNdx.at(i, 1); + } +} + +void +LTRSpaceBoundary :: computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +{ + FloatArray u; + this->computeVectorOf({ D_u, D_v, D_w }, VM_Total, tStep, u); // solution vector + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + u.resizeWithValues(12); + + // Displacement gradient H = du/dX + FloatMatrix B; + this->computeBHmatrixAt(gp, B); + answer.beProductOf(B, u); + + // Deformation gradient F = H + I + answer.at(1) += 1.0; + answer.at(2) += 1.0; + answer.at(3) += 1.0; +} + +void +LTRSpaceBoundary :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) +// Returns the [ 9 x (nno * 3) ] displacement gradient matrix {BH} of the receiver, +// evaluated at gp. +// BH matrix - 9 rows : du/dx, dv/dy, dw/dz, dv/dz, du/dz, du/dy, dw/dy, dw/dx, dv/dx +{ + double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4, detJ; + FloatArray v1, v2, v3, v4; + FloatMatrix dNdx; + + recalculateCoordinates(1, v1); + recalculateCoordinates(2, v2); + recalculateCoordinates(3, v3); + recalculateCoordinates(4, v4); + + x1 = v1.at(1); + x2 = v2.at(1); + x3 = v3.at(1); + x4 = v4.at(1); + y1 = v1.at(2); + y2 = v2.at(2); + y3 = v3.at(2); + y4 = v4.at(2); + z1 = v1.at(3); + z2 = v2.at(3); + z3 = v3.at(3); + z4 = v4.at(3); + + detJ = ( ( x4 - x1 ) * ( y2 - y1 ) * ( z3 - z1 ) - ( x4 - x1 ) * ( y3 - y1 ) * ( z2 - z1 ) + + ( x3 - x1 ) * ( y4 - y1 ) * ( z2 - z1 ) - ( x2 - x1 ) * ( y4 - y1 ) * ( z3 - z1 ) + + ( x2 - x1 ) * ( y3 - y1 ) * ( z4 - z1 ) - ( x3 - x1 ) * ( y2 - y1 ) * ( z4 - z1 ) ); + + if ( detJ <= 0.0 ) { + OOFEM_ERROR("negative volume"); + } + + dNdx.resize(4, 3); + dNdx.at(1, 1) = -( ( y3 - y2 ) * ( z4 - z2 ) - ( y4 - y2 ) * ( z3 - z2 ) ); + dNdx.at(2, 1) = ( y4 - y3 ) * ( z1 - z3 ) - ( y1 - y3 ) * ( z4 - z3 ); + dNdx.at(3, 1) = -( ( y1 - y4 ) * ( z2 - z4 ) - ( y2 - y4 ) * ( z1 - z4 ) ); + dNdx.at(4, 1) = ( y2 - y1 ) * ( z3 - z1 ) - ( y3 - y1 ) * ( z2 - z1 ); + + dNdx.at(1, 2) = -( ( x4 - x2 ) * ( z3 - z2 ) - ( x3 - x2 ) * ( z4 - z2 ) ); + dNdx.at(2, 2) = ( x1 - x3 ) * ( z4 - z3 ) - ( x4 - x3 ) * ( z1 - z3 ); + dNdx.at(3, 2) = -( ( x2 - x4 ) * ( z1 - z4 ) - ( x1 - x4 ) * ( z2 - z4 ) ); + dNdx.at(4, 2) = ( x3 - x1 ) * ( z2 - z1 ) - ( x2 - x1 ) * ( z3 - z1 ); + + dNdx.at(1, 3) = -( ( x3 - x2 ) * ( y4 - y2 ) - ( x4 - x2 ) * ( y3 - y2 ) ); + dNdx.at(2, 3) = ( x4 - x3 ) * ( y1 - y3 ) - ( x1 - x3 ) * ( y4 - y3 ); + dNdx.at(3, 3) = -( ( x1 - x4 ) * ( y2 - y4 ) - ( x2 - x4 ) * ( y1 - y4 ) ); + dNdx.at(4, 3) = ( x2 - x1 ) * ( y3 - y1 ) - ( x3 - x1 ) * ( y2 - y1 ); + dNdx.times(1. / detJ); + + answer.resize(9, dNdx.giveNumberOfRows() * 3); + answer.zero(); + + for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { + answer.at(1, 3 * i - 2) = dNdx.at(i, 1); // du/dx + answer.at(2, 3 * i - 1) = dNdx.at(i, 2); // dv/dy + answer.at(3, 3 * i - 0) = dNdx.at(i, 3); // dw/dz + answer.at(4, 3 * i - 1) = dNdx.at(i, 3); // dv/dz + answer.at(7, 3 * i - 0) = dNdx.at(i, 2); // dw/dy + answer.at(5, 3 * i - 2) = dNdx.at(i, 3); // du/dz + answer.at(8, 3 * i - 0) = dNdx.at(i, 1); // dw/dx + answer.at(6, 3 * i - 2) = dNdx.at(i, 2); // du/dy + answer.at(9, 3 * i - 1) = dNdx.at(i, 1); // dv/dx + } +} + +void +LTRSpaceBoundary :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +{ + FloatArray u, dispVec; + FloatMatrix B, T; + this->computeVectorOf(VM_Total, tStep, u); + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + this->computeTransformationMatrix(T, tStep); + dispVec.beProductOf(T, u); + + this->computeBmatrixAt(gp, B); + answer.beProductOf(B, dispVec); +} + +void +LTRSpaceBoundary :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + FloatMatrix B, T, Tt; + FloatArray vStress, vStrain, fintsub; + + // zero answer will resize accordingly when adding first contribution + answer.clear(); + fintsub.resize(12); + + for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) { + StructuralMaterialStatus *matStat = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); + + // Engineering (small strain) stress + if ( nlGeometry == 0 ) { + this->computeBmatrixAt(gp, B); + if ( useUpdatedGpRecord == 1 ) { + vStress = matStat->giveStressVector(); + } else { + if ( !this->isActivated(tStep) ) { + vStrain.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); + vStrain.zero(); + } + this->computeStrainVector(vStrain, gp, tStep); + this->computeStressVector(vStress, vStrain, gp, tStep); + } + } + + // Compute nodal internal forces at nodes as f = B^T*Stress dV + double dV = this->computeVolumeAround(gp); + + if ( vStress.giveSize() == 6 ) { + FloatArray stressTemp; + StructuralMaterial :: giveReducedSymVectorForm(stressTemp, vStress, gp->giveMaterialMode() ); + fintsub.plusProduct(B, stressTemp, dV); + } else { + fintsub.plusProduct(B, vStress, dV); + } + } + + this->computeTransformationMatrix(T, tStep); + Tt.beTranspositionOf(T); + + answer.beProductOf(Tt, fintsub); +} + +void +LTRSpaceBoundary :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + FloatMatrix Korig, T, Tt, TtK; + NLStructuralElement :: computeStiffnessMatrix(Korig, rMode, tStep); + + this->computeTransformationMatrix(T, tStep); + Tt.beTranspositionOf(T); + + TtK.beProductOf(Tt, Korig); + answer.beProductOf(TtK, T); +} + +void +LTRSpaceBoundary :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + FloatArray unitCellSize; + unitCellSize.resize(3); + unitCellSize.at(1) = this->giveNode(5)->giveCoordinate(1); + unitCellSize.at(2) = this->giveNode(5)->giveCoordinate(2); + unitCellSize.at(3) = this->giveNode(5)->giveCoordinate(3); + + IntArray switches1, switches2, switches3, switches4; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + this->giveSwitches(switches3, this->location.at(3) ); + this->giveSwitches(switches4, this->location.at(4) ); + + FloatMatrix k1, k2, k3, k4; + k1.resize(3, 9); + k2.resize(3, 9); + k3.resize(3, 9); + k4.resize(3, 9); + + for ( int i = 1; i <= 3; i++ ) { + k1.at(i, 3 * i - 2) = unitCellSize.at(1) * switches1.at(1); + k1.at(i, 3 * i - 1) = unitCellSize.at(2) * switches1.at(2); + k1.at(i, 3 * i) = unitCellSize.at(3) * switches1.at(3); + } + + for ( int i = 1; i <= 3; i++ ) { + k2.at(i, 3 * i - 2) = unitCellSize.at(1) * switches2.at(1); + k2.at(i, 3 * i - 1) = unitCellSize.at(2) * switches2.at(2); + k2.at(i, 3 * i) = unitCellSize.at(3) * switches2.at(3); + } + + for ( int i = 1; i <= 3; i++ ) { + k3.at(i, 3 * i - 2) = unitCellSize.at(1) * switches3.at(1); + k3.at(i, 3 * i - 1) = unitCellSize.at(2) * switches3.at(2); + k3.at(i, 3 * i) = unitCellSize.at(3) * switches3.at(3); + } + + for ( int i = 1; i <= 3; i++ ) { + k4.at(i, 3 * i - 2) = unitCellSize.at(1) * switches4.at(1); + k4.at(i, 3 * i - 1) = unitCellSize.at(2) * switches4.at(2); + k4.at(i, 3 * i) = unitCellSize.at(3) * switches4.at(3); + } + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 21); + + answer.assemble(k1, { 1, 2, 3 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21 }); + answer.assemble(k2, { 4, 5, 6 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21 }); + answer.assemble(k3, { 7, 8, 9 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21 }); + answer.assemble(k4, { 10, 11, 12 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21 }); +} + +void +LTRSpaceBoundary :: recalculateCoordinates(int nodeNumber, FloatArray &coords) +{ + FloatArray unitCellSize; + unitCellSize.resize(3); + unitCellSize.at(1) = this->giveNode(5)->giveCoordinate(1); + unitCellSize.at(2) = this->giveNode(5)->giveCoordinate(2); + unitCellSize.at(3) = this->giveNode(5)->giveCoordinate(3); + + IntArray switches; + this->giveSwitches(switches, this->location.at(nodeNumber) ); + + coords.resize(3); + coords.at(1) = this->giveNode(nodeNumber)->giveCoordinate(1) + switches.at(1) * unitCellSize.at(1); + coords.at(2) = this->giveNode(nodeNumber)->giveCoordinate(2) + switches.at(2) * unitCellSize.at(2); + coords.at(3) = this->giveNode(nodeNumber)->giveCoordinate(3) + switches.at(3) * unitCellSize.at(3); + + return; +} + +int +LTRSpaceBoundary :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +{ + if ( type == IST_DisplacementVector ) { + FloatArray u; + FloatMatrix N; + this->computeVectorOf(VM_Total, tStep, u); + u.resizeWithValues(12); + this->computeNmatrixAt(gp->giveSubPatchCoordinates(), N); //no special treatment needed for this interpolation + answer.beProductOf(N, u); + return 1; + } + return Element :: giveIPValue(answer, gp, type, tStep); +} + +double +LTRSpaceBoundary :: giveLengthInDir(const FloatArray &normalToCrackPlane) +{ + double maxDis, minDis; + int nnode = giveNumberOfNodes() - 1; //don't take control node + + FloatArray coords(3); + recalculateCoordinates(1, coords); + minDis = maxDis = normalToCrackPlane.dotProduct(coords, coords.giveSize() ); + + for ( int i = 2; i <= nnode; i++ ) { + FloatArray coords(3); + recalculateCoordinates(i, coords); + double dis = normalToCrackPlane.dotProduct(coords, coords.giveSize() ); + if ( dis > maxDis ) { + maxDis = dis; + } else if ( dis < minDis ) { + minDis = dis; + } + } + + return maxDis - minDis; +} + +void +LTRSpaceBoundary :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) +{ + GaussPoint *gp; + + if ( numberOfGaussPoints != 1 ) { + answer.clear(); // for more gp's need to be refined + return; + } + + gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + giveIPValue(answer, gp, type, tStep); +} +} // end namespace oofem diff --git a/src/sm/Elements/3D/ltrspaceboundary.h b/src/sm/Elements/3D/ltrspaceboundary.h new file mode 100644 index 000000000..aa4579710 --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundary.h @@ -0,0 +1,102 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ltrspaceboundary_h +#define ltrspaceboundary_h + +#include "sm/Elements/structural3delement.h" +#include "zznodalrecoverymodel.h" +#include "nodalaveragingrecoverymodel.h" +#include "sprnodalrecoverymodel.h" +#include "spatiallocalizer.h" +#include "mmashapefunctprojection.h" + +#define _IFT_LTRSpaceBoundary_Name "ltrspaceboundary" +#define _IFT_LTRSpaceBoundary_Location "location" + +namespace oofem { +class FEI3dTetLin; + +/** + * This class implements a linear tetrahedral four-node finite element. + * Each node has 3 degrees of freedom. This element is used for 3D RVE analyses with Periodic Boundary Conditions. + * At least one node is located at the image boundary. + * These nodes are replaced with a periodic mirror nodes and a control node is used to impose the macroscopic (average) strain. + * MACROSCOPIC INPUT: DEFORMATION GRADIENT TENSOR (3D, 9 COMPONENTS: Exx Exy Exz Eyx Eyy Eyz Ezx Ezy Ezz) + * + * @author: Adam Sciegaj + */ +class LTRSpaceBoundary : public Structural3DElement, public NodalAveragingRecoveryModelInterface, + public SpatialLocalizerInterface +{ +protected: + static FEI3dTetLin interpolation; + IntArray location; + virtual void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep); + void giveSwitches(IntArray &answer, int location); + + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override; + void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + double computeVolumeAround(GaussPoint *gp) override; + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + double giveLengthInDir(const FloatArray &normalToCrackPlane) override; + +public: + LTRSpaceBoundary(int n, Domain *d); + virtual ~LTRSpaceBoundary() { } + + FEInterpolation *giveInterpolation() const override; + + Interface *giveInterface(InterfaceType it) override; + + int computeNumberOfDofs() override { return 21; }; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + const IntArray giveLocation() override { return location; }; + void recalculateCoordinates(int nodeNumber, FloatArray &coords) override; + + // definition & identification + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_LTRSpaceBoundary_Name; } + const char *giveClassName() const override { return "LTRSpaceBoundary"; } + + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; +}; +} // end namespace oofem +#endif // LTRSpaceBoundary_h diff --git a/src/sm/Elements/3D/ltrspaceboundarybeam.C b/src/sm/Elements/3D/ltrspaceboundarybeam.C new file mode 100644 index 000000000..497776532 --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundarybeam.C @@ -0,0 +1,121 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/3D/ltrspaceboundarybeam.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "fei3dtetlin.h" +#include "classfactory.h" +#include "Materials/structuralms.h" + + +namespace oofem { +REGISTER_Element(LTRSpaceBoundaryBeam); + +LTRSpaceBoundaryBeam :: LTRSpaceBoundaryBeam(int n, Domain *aDomain) : + LTRSpaceBoundary(n, aDomain) +{} + +void +LTRSpaceBoundaryBeam :: initializeFrom(InputRecord &ir) +{ + LTRSpaceBoundary :: initializeFrom(ir); +} + +void +LTRSpaceBoundaryBeam :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 5 ) { + answer = { E_xx, E_zx, K_xx }; + } else { + answer = { D_u, D_v, D_w }; + } +} + + +void +LTRSpaceBoundaryBeam :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + double unitCellSize = this->giveNode(5)->giveCoordinate(1); + + IntArray switches1, switches2, switches3, switches4; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + this->giveSwitches(switches3, this->location.at(3) ); + this->giveSwitches(switches4, this->location.at(4) ); + + FloatArray w(4); + for ( int i = 1; i <= 4; i++ ) { + w.at(i) = this->giveNode(i)->giveCoordinate(3); + } + + FloatMatrix k1, k2, k3, k4; + k1.resize(3, 3); + k2.resize(3, 3); + k3.resize(3, 3); + k4.resize(3, 3); + + k1.at(1, 1) = unitCellSize * switches1.at(1); + k1.at(1, 3) = -w.at(1) * unitCellSize * switches1.at(1); + k1.at(3, 2) = unitCellSize * switches1.at(1); + + k2.at(1, 1) = unitCellSize * switches2.at(1); + k2.at(1, 3) = -w.at(2) * unitCellSize * switches2.at(1); + k2.at(3, 2) = unitCellSize * switches2.at(1); + + k3.at(1, 1) = unitCellSize * switches3.at(1); + k3.at(1, 3) = -w.at(3) * unitCellSize * switches3.at(1); + k3.at(3, 2) = unitCellSize * switches3.at(1); + + k4.at(1, 1) = unitCellSize * switches4.at(1); + k4.at(1, 3) = -w.at(4) * unitCellSize * switches4.at(1); + k4.at(3, 2) = unitCellSize * switches4.at(1); + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 15); + + answer.assemble(k1, { 1, 2, 3 }, { 13, 14, 15 }); + answer.assemble(k2, { 4, 5, 6 }, { 13, 14, 15 }); + answer.assemble(k3, { 7, 8, 9 }, { 13, 14, 15 }); + answer.assemble(k4, { 10, 11, 12 }, { 13, 14, 15 }); +} +} // end namespace oofem diff --git a/src/sm/Elements/3D/ltrspaceboundarybeam.h b/src/sm/Elements/3D/ltrspaceboundarybeam.h new file mode 100644 index 000000000..10ddf88cd --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundarybeam.h @@ -0,0 +1,76 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ltrspaceboundarybeam_h +#define ltrspaceboundarybeam_h + +#include "sm/Elements/3D/ltrspaceboundary.h" + +#define _IFT_LTRSpaceBoundaryBeam_Name "ltrspaceboundarybeam" +#define _IFT_LTRSpaceBoundaryBeam_Location "location" + +namespace oofem { +class FEI3dTetLin; + +/** + * This class implements a linear tetrahedral four-node finite element. + * Each node has 3 degrees of freedom. This element is used for 3D RVE analyses with Periodic Boundary Conditions. + * At least one node is located at the image boundary. + * These nodes are replaced with a periodic mirror nodes and a control node is used to impose the macroscopic (average) strain. + * MACROSCOPIC INPUT: DEFORMATIONS AND CURVATURE (BEAM, 3 COMPONENTS: Exx Ezx Kxx) + * Exx = du/dx - axial strain + * Ezx = dw/dx - slope + * Kxx = d^2(w)/dx^2 (Euler-Bernoulli) or d(phi)/dx (Timoshenko) - curvature + * + * @author: Adam Sciegaj + */ +class LTRSpaceBoundaryBeam : public LTRSpaceBoundary +{ +protected: + void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) override; + +public: + LTRSpaceBoundaryBeam(int n, Domain *d); + virtual ~LTRSpaceBoundaryBeam() { } + + int computeNumberOfDofs() override { return 15; }; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_LTRSpaceBoundaryBeam_Name; } + const char *giveClassName() const override { return "LTRSpaceBoundaryBeam"; } +}; +} // end namespace oofem +#endif // LTRSpaceBoundaryBeam_h diff --git a/src/sm/Elements/3D/ltrspaceboundarymembrane.C b/src/sm/Elements/3D/ltrspaceboundarymembrane.C new file mode 100644 index 000000000..f0f21b2ea --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundarymembrane.C @@ -0,0 +1,123 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/3D/ltrspaceboundarymembrane.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "fei3dtetlin.h" +#include "classfactory.h" +#include "Materials/structuralms.h" + + +namespace oofem { +REGISTER_Element(LTRSpaceBoundaryMembrane); + +LTRSpaceBoundaryMembrane :: LTRSpaceBoundaryMembrane(int n, Domain *aDomain) : + LTRSpaceBoundary(n, aDomain) +{} + +void +LTRSpaceBoundaryMembrane :: initializeFrom(InputRecord &ir) +{ + LTRSpaceBoundary :: initializeFrom(ir); +} + +void +LTRSpaceBoundaryMembrane :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 5 ) { + answer = { E_xx, E_xy, E_yx, E_yy }; + } else { + answer = { D_u, D_v, D_w }; + } +} + + +void +LTRSpaceBoundaryMembrane :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + FloatArray unitCellSize; + unitCellSize.resize(2); + unitCellSize.at(1) = this->giveNode(5)->giveCoordinate(1); + unitCellSize.at(2) = this->giveNode(5)->giveCoordinate(2); + + IntArray switches1, switches2, switches3, switches4; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + this->giveSwitches(switches3, this->location.at(3) ); + this->giveSwitches(switches4, this->location.at(4) ); + + FloatMatrix k1, k2, k3, k4; + k1.resize(3, 4); + k2.resize(3, 4); + k3.resize(3, 4); + k4.resize(3, 4); + + k1.at(1, 1) = unitCellSize.at(1) * switches1.at(1); + k1.at(1, 2) = unitCellSize.at(2) * switches1.at(2); + k1.at(2, 3) = unitCellSize.at(1) * switches1.at(1); + k1.at(2, 4) = unitCellSize.at(2) * switches1.at(2); + + k2.at(1, 1) = unitCellSize.at(1) * switches2.at(1); + k2.at(1, 2) = unitCellSize.at(2) * switches2.at(2); + k2.at(2, 3) = unitCellSize.at(1) * switches2.at(1); + k2.at(2, 4) = unitCellSize.at(2) * switches2.at(2); + + k3.at(1, 1) = unitCellSize.at(1) * switches3.at(1); + k3.at(1, 2) = unitCellSize.at(2) * switches3.at(2); + k3.at(2, 3) = unitCellSize.at(1) * switches3.at(1); + k3.at(2, 4) = unitCellSize.at(2) * switches3.at(2); + + k4.at(1, 1) = unitCellSize.at(1) * switches4.at(1), + k4.at(1, 2) = unitCellSize.at(2) * switches4.at(2); + k4.at(2, 3) = unitCellSize.at(1) * switches4.at(1); + k4.at(2, 4) = unitCellSize.at(2) * switches4.at(2); + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 16); + + answer.assemble(k1, { 1, 2, 3 }, { 13, 14, 15, 16 }); + answer.assemble(k2, { 4, 5, 6 }, { 13, 14, 15, 16 }); + answer.assemble(k3, { 7, 8, 9 }, { 13, 14, 15, 16 }); + answer.assemble(k4, { 10, 11, 12 }, { 13, 14, 15, 16 }); +} +} // end namespace oofem diff --git a/src/sm/Elements/3D/ltrspaceboundarymembrane.h b/src/sm/Elements/3D/ltrspaceboundarymembrane.h new file mode 100644 index 000000000..0f6a041e7 --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundarymembrane.h @@ -0,0 +1,73 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ltrspaceboundarymembrane_h +#define ltrspaceboundarymembrane_h + +#include "sm/Elements/3D/ltrspaceboundary.h" + +#define _IFT_LTRSpaceBoundaryMembrane_Name "ltrspaceboundarymembrane" +#define _IFT_LTRSpaceBoundaryMembrane_Location "location" + +namespace oofem { +class FEI3dTetLin; + +/** + * This class implements a linear tetrahedral four-node finite element. + * Each node has 3 degrees of freedom. This element is used for 3D RVE analyses with Periodic Boundary Conditions. + * At least one node is located at the image boundary. + * These nodes are replaced with a periodic mirror nodes and a control node is used to impose the macroscopic (average) strain. + * MACROSCOPIC INPUT: DEFORMATION TENSOR (2D, 4 COMPONENTS: Exx Exy Eyx Eyy) + * + * @author: Adam Sciegaj + */ +class LTRSpaceBoundaryMembrane : public LTRSpaceBoundary +{ +protected: + void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) override; + +public: + LTRSpaceBoundaryMembrane(int n, Domain *d); + virtual ~LTRSpaceBoundaryMembrane() { } + + int computeNumberOfDofs() override { return 16; }; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_LTRSpaceBoundaryMembrane_Name; } + const char *giveClassName() const override { return "LTRSpaceBoundaryMembrane"; } +}; +} // end namespace oofem +#endif // LTRSpaceBoundaryMembrane_h diff --git a/src/sm/Elements/3D/ltrspaceboundaryplate.C b/src/sm/Elements/3D/ltrspaceboundaryplate.C new file mode 100644 index 000000000..32989dca9 --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundaryplate.C @@ -0,0 +1,152 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/3D/ltrspaceboundaryplate.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "fei3dtetlin.h" +#include "classfactory.h" +#include "Materials/structuralms.h" + + +namespace oofem { +REGISTER_Element(LTRSpaceBoundaryPlate); + +LTRSpaceBoundaryPlate :: LTRSpaceBoundaryPlate(int n, Domain *aDomain) : + LTRSpaceBoundary(n, aDomain) +{} + +void +LTRSpaceBoundaryPlate :: initializeFrom(InputRecord &ir) +{ + LTRSpaceBoundary :: initializeFrom(ir); +} + +void +LTRSpaceBoundaryPlate :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 5 ) { + answer = { E_xx, E_xy, E_yx, E_yy, E_zx, E_zy, K_xx, K_yy, K_xy, K_yx }; + } else { + answer = { D_u, D_v, D_w }; + } +} + + +void +LTRSpaceBoundaryPlate :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + FloatArray unitCellSize; + unitCellSize.resize(2); + unitCellSize.at(1) = this->giveNode(5)->giveCoordinate(1); + unitCellSize.at(2) = this->giveNode(5)->giveCoordinate(2); + + IntArray switches1, switches2, switches3, switches4; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + this->giveSwitches(switches3, this->location.at(3) ); + this->giveSwitches(switches4, this->location.at(4) ); + + FloatArray w(4); + for ( int i = 1; i <= 4; i++ ) { + w.at(i) = this->giveNode(i)->giveCoordinate(3); + } + + FloatMatrix k1, k2, k3, k4; + k1.resize(3, 10); + k2.resize(3, 10); + k3.resize(3, 10); + k4.resize(3, 10); + + k1.at(1, 1) = unitCellSize.at(1) * switches1.at(1); + k1.at(1, 2) = unitCellSize.at(2) * switches1.at(2); + k1.at(2, 3) = unitCellSize.at(1) * switches1.at(1); + k1.at(2, 4) = unitCellSize.at(2) * switches1.at(2); + k1.at(3, 5) = unitCellSize.at(1) * switches1.at(1); + k1.at(3, 6) = unitCellSize.at(2) * switches1.at(2); + k1.at(1, 7) = -w.at(1) * unitCellSize.at(1) * switches1.at(1); + k1.at(2, 8) = -w.at(1) * unitCellSize.at(2) * switches1.at(2); + k1.at(1, 9) = -w.at(1) * unitCellSize.at(2) * switches1.at(2); + k1.at(2, 10) = -w.at(1) * unitCellSize.at(1) * switches1.at(1); + + k2.at(1, 1) = unitCellSize.at(1) * switches2.at(1); + k2.at(1, 2) = unitCellSize.at(2) * switches2.at(2); + k2.at(2, 3) = unitCellSize.at(1) * switches2.at(1); + k2.at(2, 4) = unitCellSize.at(2) * switches2.at(2); + k2.at(3, 5) = unitCellSize.at(1) * switches2.at(1); + k2.at(3, 6) = unitCellSize.at(2) * switches2.at(2); + k2.at(1, 7) = -w.at(2) * unitCellSize.at(1) * switches2.at(1); + k2.at(2, 8) = -w.at(2) * unitCellSize.at(2) * switches2.at(2); + k2.at(1, 9) = -w.at(2) * unitCellSize.at(2) * switches2.at(2); + k2.at(2, 10) = -w.at(2) * unitCellSize.at(1) * switches2.at(1); + + k3.at(1, 1) = unitCellSize.at(1) * switches3.at(1); + k3.at(1, 2) = unitCellSize.at(2) * switches3.at(2); + k3.at(2, 3) = unitCellSize.at(1) * switches3.at(1); + k3.at(2, 4) = unitCellSize.at(2) * switches3.at(2); + k3.at(3, 5) = unitCellSize.at(1) * switches3.at(1); + k3.at(3, 6) = unitCellSize.at(2) * switches3.at(2); + k3.at(1, 7) = -w.at(3) * unitCellSize.at(1) * switches3.at(1); + k3.at(2, 8) = -w.at(3) * unitCellSize.at(2) * switches3.at(2); + k3.at(1, 9) = -w.at(3) * unitCellSize.at(2) * switches3.at(2); + k3.at(2, 10) = -w.at(3) * unitCellSize.at(1) * switches3.at(1); + + k4.at(1, 1) = unitCellSize.at(1) * switches4.at(1); + k4.at(1, 2) = unitCellSize.at(2) * switches4.at(2); + k4.at(2, 3) = unitCellSize.at(1) * switches4.at(1); + k4.at(2, 4) = unitCellSize.at(2) * switches4.at(2); + k4.at(3, 5) = unitCellSize.at(1) * switches4.at(1); + k4.at(3, 6) = unitCellSize.at(2) * switches4.at(2); + k4.at(1, 7) = -w.at(4) * unitCellSize.at(1) * switches4.at(1); + k4.at(2, 8) = -w.at(4) * unitCellSize.at(2) * switches4.at(2); + k4.at(1, 9) = -w.at(4) * unitCellSize.at(2) * switches4.at(2); + k4.at(2, 10) = -w.at(4) * unitCellSize.at(1) * switches4.at(1); + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 22); + + answer.assemble(k1, { 1, 2, 3 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }); + answer.assemble(k2, { 4, 5, 6 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }); + answer.assemble(k3, { 7, 8, 9 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }); + answer.assemble(k4, { 10, 11, 12 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }); +} +} // end namespace oofem diff --git a/src/sm/Elements/3D/ltrspaceboundaryplate.h b/src/sm/Elements/3D/ltrspaceboundaryplate.h new file mode 100644 index 000000000..1121c6f46 --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundaryplate.h @@ -0,0 +1,79 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ltrspaceboundaryplate_h +#define ltrspaceboundaryplate_h + +#include "sm/Elements/3D/ltrspaceboundary.h" + +#define _IFT_LTRSpaceBoundaryPlate_Name "ltrspaceboundaryplate" +#define _IFT_LTRSpaceBoundaryPlate_Location "location" + +namespace oofem { +class FEI3dTetLin; + +/** + * This class implements a linear tetrahedral four-node finite element. + * Each node has 3 degrees of freedom. This element is used for 3D RVE analyses with Periodic Boundary Conditions. + * At least one node is located at the image boundary. + * These nodes are replaced with a periodic mirror nodes and a control node is used to impose the macroscopic (average) strain. + * MACROSCOPIC INPUT: DEFORMATIONS AND CURVATURES (PLATE, 10 COMPONENTS: Exx Exy Eyx Eyy Ezx Ezy Kxx Kyy Kxy Kyx) + * Exx = du/dx, Exy = du/dy, Eyx = dv/dx, Eyy = dv/dy (in-plane strains) + * Ezx = dw/dx, Ezy = dw/dy (slopes) + * Kxx = d^2(w)/dx^2 (Kirchhoff) or d(phi_x)/dx (Mindlin) curvature + * Kyy = d^2(w)/dy^2 (Kirchhoff) or d(phi_y)/dy (Mindlin) curvature + * Kxy = d^2(w)/dxdy (Kirchhoff) or d(phi_x)/dy (Mindlin) curvature + * Kyx = d^2(w)/dxdy (Kirchhoff) or d(phi_y)/dx (Mindlin) curvature + * + * @author: Adam Sciegaj + */ +class LTRSpaceBoundaryPlate : public LTRSpaceBoundary +{ +protected: + void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) override; + +public: + LTRSpaceBoundaryPlate(int n, Domain *d); + virtual ~LTRSpaceBoundaryPlate() { } + + int computeNumberOfDofs() override { return 22; }; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_LTRSpaceBoundaryPlate_Name; } + const char *giveClassName() const override { return "LTRSpaceBoundaryPlate"; } +}; +} // end namespace oofem +#endif // LTRSpaceBoundaryPlate_h diff --git a/src/sm/Elements/3D/ltrspaceboundarytruss.C b/src/sm/Elements/3D/ltrspaceboundarytruss.C new file mode 100644 index 000000000..b297b4d8b --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundarytruss.C @@ -0,0 +1,99 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/3D/ltrspaceboundarytruss.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "fei3dtetlin.h" +#include "classfactory.h" +#include "Materials/structuralms.h" + + +namespace oofem { +REGISTER_Element(LTRSpaceBoundaryTruss); + +LTRSpaceBoundaryTruss :: LTRSpaceBoundaryTruss(int n, Domain *aDomain) : + LTRSpaceBoundary(n, aDomain) +{} + +void +LTRSpaceBoundaryTruss :: initializeFrom(InputRecord &ir) +{ + LTRSpaceBoundary :: initializeFrom(ir); +} + +void +LTRSpaceBoundaryTruss :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 5 ) { + answer = { E_xx }; + } else { + answer = { D_u, D_v, D_w }; + } +} + + +void +LTRSpaceBoundaryTruss :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + double unitCellSize = this->giveNode(5)->giveCoordinate(1); + + IntArray switches1, switches2, switches3, switches4; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + this->giveSwitches(switches3, this->location.at(3) ); + this->giveSwitches(switches4, this->location.at(4) ); + + FloatMatrix k; + k.resize(12, 1); + + k.at(1, 1) = unitCellSize * switches1.at(1); + k.at(4, 1) = unitCellSize * switches2.at(1); + k.at(7, 1) = unitCellSize * switches3.at(1); + k.at(10, 1) = unitCellSize * switches4.at(1); + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 13); + + answer.assemble(k, { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }, { 13 }); +} +} // end namespace oofem diff --git a/src/sm/Elements/3D/ltrspaceboundarytruss.h b/src/sm/Elements/3D/ltrspaceboundarytruss.h new file mode 100644 index 000000000..30d4e392d --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundarytruss.h @@ -0,0 +1,73 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ltrspaceboundarytruss_h +#define ltrspaceboundarytruss_h + +#include "sm/Elements/3D/ltrspaceboundary.h" + +#define _IFT_LTRSpaceBoundaryTruss_Name "ltrspaceboundarytruss" +#define _IFT_LTRSpaceBoundaryTruss_Location "location" + +namespace oofem { +class FEI3dTetLin; + +/** + * This class implements a linear tetrahedral four-node finite element. + * Each node has 3 degrees of freedom. This element is used for 3D RVE analyses with Periodic Boundary Conditions. + * At least one node is located at the image boundary. + * These nodes are replaced with a periodic mirror nodes and a control node is used to impose the macroscopic (average) strain. + * MACROSCOPIC INPUT: Exx (1D, 1 COMPONENT) + * + * @author: Adam Sciegaj + */ +class LTRSpaceBoundaryTruss : public LTRSpaceBoundary +{ +protected: + void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) override; + +public: + LTRSpaceBoundaryTruss(int n, Domain *d); + virtual ~LTRSpaceBoundaryTruss() { } + + int computeNumberOfDofs() override { return 13; }; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_LTRSpaceBoundaryTruss_Name; } + const char *giveClassName() const override { return "LTRSpaceBoundaryTruss"; } +}; +} // end namespace oofem +#endif // LTRSpaceBoundaryTruss_h diff --git a/src/sm/Elements/3D/ltrspaceboundaryvoigt.C b/src/sm/Elements/3D/ltrspaceboundaryvoigt.C new file mode 100644 index 000000000..6bafbb72f --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundaryvoigt.C @@ -0,0 +1,144 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/3D/ltrspaceboundaryvoigt.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "fei3dtetlin.h" +#include "classfactory.h" +#include "Materials/structuralms.h" + + +namespace oofem { +REGISTER_Element(LTRSpaceBoundaryVoigt); + +LTRSpaceBoundaryVoigt :: LTRSpaceBoundaryVoigt(int n, Domain *aDomain) : + LTRSpaceBoundary(n, aDomain) +{} + +void +LTRSpaceBoundaryVoigt :: initializeFrom(InputRecord &ir) +{ + LTRSpaceBoundary :: initializeFrom(ir); +} + +void +LTRSpaceBoundaryVoigt :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 5 ) { + answer = { E_xx, E_yy, E_zz, G_yz, G_xz, G_xy }; + } else { + answer = { D_u, D_v, D_w }; + } +} + + +void +LTRSpaceBoundaryVoigt :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + FloatArray unitCellSize; + unitCellSize.resize(3); + unitCellSize.at(1) = this->giveNode(5)->giveCoordinate(1); + unitCellSize.at(2) = this->giveNode(5)->giveCoordinate(2); + unitCellSize.at(3) = this->giveNode(5)->giveCoordinate(3); + + IntArray switches1, switches2, switches3, switches4; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + this->giveSwitches(switches3, this->location.at(3) ); + this->giveSwitches(switches4, this->location.at(4) ); + + FloatMatrix k21_node1, k22_node1, k21_node2, k22_node2, k21_node3, k22_node3, k21_node4, k22_node4; + k21_node1.resize(3, 3); + k22_node1.resize(3, 3); + k21_node2.resize(3, 3); + k22_node2.resize(3, 3); + k21_node3.resize(3, 3); + k22_node3.resize(3, 3); + k21_node4.resize(3, 3); + k22_node4.resize(3, 3); + + k21_node1.at(1, 1) = unitCellSize.at(1) * switches1.at(1); + k21_node1.at(2, 2) = unitCellSize.at(2) * switches1.at(2); + k21_node1.at(3, 3) = unitCellSize.at(3) * switches1.at(3); + + k22_node1.at(1, 2) = unitCellSize.at(3) * switches1.at(3); + k22_node1.at(1, 3) = unitCellSize.at(2) * switches1.at(2); + k22_node1.at(2, 1) = unitCellSize.at(3) * switches1.at(3); + + k21_node2.at(1, 1) = unitCellSize.at(1) * switches2.at(1); + k21_node2.at(2, 2) = unitCellSize.at(2) * switches2.at(2); + k21_node2.at(3, 3) = unitCellSize.at(3) * switches2.at(3); + + k22_node2.at(1, 2) = unitCellSize.at(3) * switches2.at(3); + k22_node2.at(1, 3) = unitCellSize.at(2) * switches2.at(2); + k22_node2.at(2, 1) = unitCellSize.at(3) * switches2.at(3); + + k21_node3.at(1, 1) = unitCellSize.at(1) * switches3.at(1); + k21_node3.at(2, 2) = unitCellSize.at(2) * switches3.at(2); + k21_node3.at(3, 3) = unitCellSize.at(3) * switches3.at(3); + + k22_node3.at(1, 2) = unitCellSize.at(3) * switches3.at(3); + k22_node3.at(1, 3) = unitCellSize.at(2) * switches3.at(2); + k22_node3.at(2, 1) = unitCellSize.at(3) * switches3.at(3); + + k21_node4.at(1, 1) = unitCellSize.at(1) * switches4.at(1); + k21_node4.at(2, 2) = unitCellSize.at(2) * switches4.at(2); + k21_node4.at(3, 3) = unitCellSize.at(3) * switches4.at(3); + + k22_node4.at(1, 2) = unitCellSize.at(3) * switches4.at(3); + k22_node4.at(1, 3) = unitCellSize.at(2) * switches4.at(2); + k22_node4.at(2, 1) = unitCellSize.at(3) * switches4.at(3); + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 18); + + answer.assemble(k21_node1, { 1, 2, 3 }, { 13, 14, 15 }); + answer.assemble(k22_node1, { 1, 2, 3 }, { 16, 17, 18 }); + answer.assemble(k21_node2, { 4, 5, 6 }, { 13, 14, 15 }); + answer.assemble(k22_node2, { 4, 5, 6 }, { 16, 17, 18 }); + answer.assemble(k21_node3, { 7, 8, 9 }, { 13, 14, 15 }); + answer.assemble(k22_node3, { 7, 8, 9 }, { 16, 17, 18 }); + answer.assemble(k21_node4, { 10, 11, 12 }, { 13, 14, 15 }); + answer.assemble(k22_node4, { 10, 11, 12 }, { 16, 17, 18 }); +} +} // end namespace oofem diff --git a/src/sm/Elements/3D/ltrspaceboundaryvoigt.h b/src/sm/Elements/3D/ltrspaceboundaryvoigt.h new file mode 100644 index 000000000..136b8b7bb --- /dev/null +++ b/src/sm/Elements/3D/ltrspaceboundaryvoigt.h @@ -0,0 +1,73 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ltrspaceboundaryvoigt_h +#define ltrspaceboundaryvoigt_h + +#include "sm/Elements/3D/ltrspaceboundary.h" + +#define _IFT_LTRSpaceBoundaryVoigt_Name "ltrspaceboundaryvoigt" +#define _IFT_LTRSpaceBoundaryVoigt_Location "location" + +namespace oofem { +class FEI3dTetLin; + +/** + * This class implements a linear tetrahedral four-node finite element. + * Each node has 3 degrees of freedom. This element is used for 3D RVE analyses with Periodic Boundary Conditions. + * At least one node is located at the image boundary. + * These nodes are replaced with a periodic mirror nodes and a control node is used to impose the macroscopic (average) strain. + * MACROSCOPIC INPUT: STRAIN TENSOR (3D, 6 COMPONENTS, VOIGT NOTATION: Exx Eyy Ezz Gyz Gxz Gxy) + * + * @author: Adam Sciegaj + */ +class LTRSpaceBoundaryVoigt : public LTRSpaceBoundary +{ +protected: + void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) override; + +public: + LTRSpaceBoundaryVoigt(int n, Domain *d); + virtual ~LTRSpaceBoundaryVoigt() { } + + int computeNumberOfDofs() override { return 18; }; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_LTRSpaceBoundaryVoigt_Name; } + const char *giveClassName() const override { return "LTRSpaceBoundaryVoigt"; } +}; +} // end namespace oofem +#endif // LTRSpaceBoundaryVoigt_h diff --git a/src/sm/Elements/3D/lwedge.C b/src/sm/Elements/3D/lwedge.C index 856095e37..36e05830e 100644 --- a/src/sm/Elements/3D/lwedge.C +++ b/src/sm/Elements/3D/lwedge.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/3D/lwedge.h" -#include "Materials/structuralms.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/Elements/3D/lwedge.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei3dwedgelin.h" #include "node.h" #include "material.h" @@ -56,17 +56,16 @@ REGISTER_Element(LWedge); FEI3dWedgeLin LWedge :: interpolation; LWedge :: LWedge(int n, Domain *aDomain) : Structural3DElement(n, aDomain), ZZNodalRecoveryModelInterface(this), SpatialLocalizerInterface(this) - // Constructor. { numberOfDofMans = 6; } -IRResultType -LWedge :: initializeFrom(InputRecord *ir) +void +LWedge :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 6; - return Structural3DElement :: initializeFrom(ir); + Structural3DElement :: initializeFrom(ir); } diff --git a/src/sm/Elements/3D/lwedge.h b/src/sm/Elements/3D/lwedge.h index f0fc09e6c..7de05ac8e 100644 --- a/src/sm/Elements/3D/lwedge.h +++ b/src/sm/Elements/3D/lwedge.h @@ -36,8 +36,8 @@ #ifndef lwedge_h #define lwedge_h -#include "Elements/structural3delement.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/structural3delement.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -60,25 +60,24 @@ class LWedge : public Structural3DElement, public SPRNodalRecoveryModelInterface LWedge(int, Domain *); virtual ~LWedge() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual Interface *giveInterface(InterfaceType); - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } - virtual int giveNumberOfIPForMassMtrxIntegration() { return 9; } + void initializeFrom(InputRecord &ir) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + Interface *giveInterface(InterfaceType) override; + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } + int giveNumberOfIPForMassMtrxIntegration() override { return 9; } - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; + + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LWedge_Name; } - virtual const char *giveClassName() const { return "LWedge"; } - + const char *giveInputRecordName() const override { return _IFT_LWedge_Name; } + const char *giveClassName() const override { return "LWedge"; } }; } // end namespace oofem #endif diff --git a/src/sm/Elements/3D/macrolspace.C b/src/sm/Elements/3D/macrolspace.C index 49ef967c7..47f89cefd 100644 --- a/src/sm/Elements/3D/macrolspace.C +++ b/src/sm/Elements/3D/macrolspace.C @@ -32,10 +32,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/3D/macrolspace.h" -#include "../sm/Materials/micromaterial.h" -#include "../sm/EngineeringModels/structengngmodel.h" -#include "../sm/Elements/3D/lspace.h" +#include "sm/Elements/3D/macrolspace.h" +#include "sm/Materials/micromaterial.h" +#include "sm/EngineeringModels/structengngmodel.h" +#include "sm/Elements/3D/lspace.h" #include "fei3dhexalin.h" #include "constantfunction.h" #include "domain.h" @@ -49,8 +49,6 @@ REGISTER_Element(MacroLSpace); //derived from linear brick element MacroLSpace :: MacroLSpace(int n, Domain *aDomain) : LSpace(n, aDomain) { - this->microMasterNodes.clear(); - this->microBoundaryNodes.clear(); this->firstCall = true; microMaterial = NULL; microDomain = NULL; @@ -62,15 +60,14 @@ MacroLSpace :: MacroLSpace(int n, Domain *aDomain) : LSpace(n, aDomain) MacroLSpace :: ~MacroLSpace() { } -IRResultType MacroLSpace :: initializeFrom(InputRecord *ir) +void MacroLSpace :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + LSpace :: initializeFrom(ir);; IR_GIVE_FIELD(ir, this->microMasterNodes, _IFT_MacroLspace_microMasterNodes); if ( this->microMasterNodes.giveSize() != 8 ) { - OOFEM_WARNING("Need 8 master nodes from the microproblem defined on macroLspace element"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_MacroLspace_microMasterNodes, "Need 8 master nodes from the microproblem defined on macroLspace element"); } IR_GIVE_FIELD(ir, this->microBoundaryNodes, _IFT_MacroLspace_microBoundaryNodes); @@ -78,7 +75,7 @@ IRResultType MacroLSpace :: initializeFrom(InputRecord *ir) microBoundaryDofManager.resize( 3 * microBoundaryNodes.giveSize() ); #if 0 - if ( ir->hasField(_IFT_MacroLspace_stiffMatrxFileName) ) { + if ( ir.hasField(_IFT_MacroLspace_stiffMatrxFileName) ) { IR_GIVE_OPTIONAL_FIELD(ir, this->stiffMatrxFileName, _IFT_MacroLspace_stiffMatrxFileName); if ( fopen(this->stiffMatrxFileName, "r") != NULL ) { //if the file exist stiffMatrxFile = fopen(this->stiffMatrxFileName, "r"); @@ -91,7 +88,6 @@ IRResultType MacroLSpace :: initializeFrom(InputRecord *ir) } } #endif - return LSpace :: initializeFrom(ir);; } @@ -134,7 +130,7 @@ void MacroLSpace :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode this->microEngngModel->giveCurrentStep()->setTimeIncrement(0.); //no time increment this->microEngngModel->initMetaStepAttributes( microEngngModel->giveCurrentMetaStep() ); //updates numerical method - OOFEM_LOG_INFO( "\n** Assembling %s stiffness matrix of microproblem %p on macroElement %d, micTimeStep %d, micTime %f\n", __MatResponseModeToString(rMode), this->microMaterial->problemMicro, this->giveNumber(), this->microEngngModel->giveCurrentStep()->giveNumber(), this->microEngngModel->giveCurrentStep()->giveTargetTime() ); + OOFEM_LOG_INFO( "\n** Assembling %s stiffness matrix of microproblem on macroElement %d, micTimeStep %d, micTime %f\n", __MatResponseModeToString(rMode), this->giveNumber(), this->microEngngModel->giveCurrentStep()->giveNumber(), this->microEngngModel->giveCurrentStep()->giveTargetTime() ); //this->microEngngModel->solveYourselfAt( microEngngModel->giveCurrentStep() ); //this->microEngngModel->terminate( microEngngModel->giveCurrentStep() ); @@ -154,8 +150,6 @@ void MacroLSpace :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode //assign values to DOF on the boundary according to definition on macrolspace and actual displacement stage void MacroLSpace :: changeMicroBoundaryConditions(TimeStep *tStep) { - GeneralBoundaryCondition *GeneralBoundaryCond; - Function *timeFunct; DynamicInputRecord ir_func, ir_bc; FloatArray n(8), answer, localCoords; double displ; @@ -177,11 +171,12 @@ void MacroLSpace :: changeMicroBoundaryConditions(TimeStep *tStep) ir_func.setRecordKeywordField("constantfunction", 1); ir_func.setField(1.0, _IFT_ConstantFunction_f); - if ( ( timeFunct = classFactory.createFunction("constantfunction", 1, microDomain) ) == NULL ) { + auto timeFunct = classFactory.createFunction("constantfunction", 1, microDomain); + if ( !timeFunct ) { OOFEM_ERROR("Couldn't create constant time function"); } - timeFunct->initializeFrom(& ir_func); - microDomain->setFunction(1, timeFunct); + timeFunct->initializeFrom(ir_func); + microDomain->setFunction(1, std::move(timeFunct)); /*assign to each boundary node the form "bc 3 # # #", set 0s on free nodes @@ -193,7 +188,7 @@ void MacroLSpace :: changeMicroBoundaryConditions(TimeStep *tStep) counter = 1; for ( auto &DofMan : microDomain->giveDofManagers() ) { //go through all nodes on microDomain if ( microBoundaryNodes.contains( DofMan->giveGlobalNumber() ) ) { //if the node number is on boundary - this->evalInterpolation( n, microMaterial->microMasterCoords, * DofMan->giveCoordinates() ); + this->evalInterpolation( n, microMaterial->microMasterCoords, DofMan->giveCoordinates() ); //n.printYourself(); for ( Dof *dof: *DofMan ) { @@ -204,15 +199,16 @@ void MacroLSpace :: changeMicroBoundaryConditions(TimeStep *tStep) ir_bc.setRecordKeywordField("boundarycondition", counter); ir_bc.setField(1, _IFT_GeneralBoundaryCondition_timeFunct); ir_bc.setField(displ, _IFT_BoundaryCondition_PrescribedValue); - if ( ( GeneralBoundaryCond = classFactory.createBoundaryCondition("boundarycondition", counter, microDomain) ) == NULL ) { + auto bc = classFactory.createBoundaryCondition("boundarycondition", counter, microDomain); + if ( !bc ) { OOFEM_ERROR("Couldn't create boundary condition."); } - GeneralBoundaryCond->initializeFrom(& ir_bc); - microDomain->setBoundaryCondition(counter, GeneralBoundaryCond); + bc->initializeFrom(ir_bc); + microDomain->setBoundaryCondition(counter, std::move(bc)); counter++; } } else { - for ( Dof *dof: *DofMan ) { + for ( auto &dof: *DofMan ) { dof->setBcId(0); } } @@ -238,7 +234,7 @@ void MacroLSpace :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep if ( useUpdatedGpRecord ) { //printing of data answer = this->internalMacroForcesVector; } else { - OOFEM_LOG_INFO( "\n*** Solving reactions %p of macroElement %d, micTimeStep %d, macIteration %d, micTime %f\n", this->microMaterial->problemMicro, this->giveNumber(), this->microEngngModel->giveCurrentStep()->giveNumber(), this->iteration, this->microEngngModel->giveCurrentStep()->giveTargetTime() ); + OOFEM_LOG_INFO( "\n*** Solving reactions of macroElement %d, micTimeStep %d, macIteration %d, micTime %f\n", this->giveNumber(), this->microEngngModel->giveCurrentStep()->giveNumber(), this->iteration, this->microEngngModel->giveCurrentStep()->giveTargetTime() ); this->iteration++; this->changeMicroBoundaryConditions(tStep); @@ -259,7 +255,7 @@ void MacroLSpace :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep for ( int i = 1; i <= this->microBoundaryDofManager.giveSize() / 3; i++ ) { //Number of DoFManagers stored in triplets DofMan = microDomain->giveDofManager( this->microBoundaryDofManager.at(3 * i - 2) ); - this->evalInterpolation( n, microMaterial->microMasterCoords, * DofMan->giveCoordinates() ); + this->evalInterpolation( n, microMaterial->microMasterCoords, DofMan->giveCoordinates() ); for ( int j = 1; j <= DofMan->giveNumberOfDofs(); j++ ) { //3 reactionForce = reactions.at(3 * i + j - 3); for ( int k = 1; k <= 8; k++ ) { @@ -269,7 +265,7 @@ void MacroLSpace :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep } this->internalMacroForcesVector = answer; - OOFEM_LOG_INFO("*** Reactions done\n", this->microMaterial->problemMicro); + OOFEM_LOG_INFO("*** Reactions done\n"); } //answer.printYourself(); diff --git a/src/sm/Elements/3D/macrolspace.h b/src/sm/Elements/3D/macrolspace.h index b81b8962a..4ba682779 100644 --- a/src/sm/Elements/3D/macrolspace.h +++ b/src/sm/Elements/3D/macrolspace.h @@ -35,7 +35,7 @@ #ifndef macrolspace_h #define macrolspace_h -#include "../sm/Elements/3D/lspace.h" +#include "sm/Elements/3D/lspace.h" ///@name Input fields for MacroLspace //@{ @@ -62,20 +62,20 @@ class MacroLSpace : public LSpace MacroLSpace(int n, Domain * d); virtual ~MacroLSpace(); - virtual const char *giveInputRecordName() const { return _IFT_MacroLSpace_Name; } - virtual const char *giveClassName() const { return "MacroLSpace"; } + const char *giveInputRecordName() const override { return _IFT_MacroLSpace_Name; } + const char *giveClassName() const override { return "MacroLSpace"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; - virtual void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) + void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) override { OOFEM_ERROR("Macro space element doesn't support computing local unknown vector (yet)\n"); } /// Related to setting the boundary conditions of micro problem. virtual void changeMicroBoundaryConditions(TimeStep *tStep); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; /** * Evaluates shape function at a given pointnodal representation of real internal forces obtained from microProblem. @@ -85,7 +85,7 @@ class MacroLSpace : public LSpace */ virtual void evalInterpolation(FloatArray &answer, const std::vector< FloatArray > &coords, const FloatArray &gcoords); - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; protected: /// Array containing the node mapping from microscale (which microMasterNodes corresponds to which macroNode) diff --git a/src/sm/Elements/3D/q27space.C b/src/sm/Elements/3D/q27space.C index 76e271b12..03e9589ab 100644 --- a/src/sm/Elements/3D/q27space.C +++ b/src/sm/Elements/3D/q27space.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/3D/q27space.h" +#include "sm/Elements/3D/q27space.h" #include "node.h" #include "gausspoint.h" #include "gaussintegrationrule.h" @@ -61,11 +61,11 @@ Q27Space :: Q27Space(int n, Domain *aDomain) : Structural3DElement(n, aDomain), } -IRResultType -Q27Space :: initializeFrom(InputRecord *ir) +void +Q27Space :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 27; - return Structural3DElement :: initializeFrom(ir); + Structural3DElement :: initializeFrom(ir); } @@ -73,17 +73,6 @@ Q27Space :: initializeFrom(InputRecord *ir) // *** Surface load support *** // ****************************** -IntegrationRule * -Q27Space :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Square, approxOrder); - iRule->SetUpPointsOnSquare(npoints, _Unknown); - return iRule; -} - - - int Q27Space :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp) { @@ -105,22 +94,21 @@ Q27Space :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, Gauss */ FloatArray gc(3); FloatArray h1(3), h2(3), nn(3), n(3); - IntArray snodes(4); answer.resize(3, 3); answer.zero(); - this->interpolation.computeSurfaceMapping(snodes, dofManArray, iSurf); + const auto &snodes = this->interpolation.computeSurfaceMapping(dofManArray, iSurf); for ( int i = 1; i <= 4; i++ ) { - gc.add( * domain->giveNode( snodes.at(i) )->giveCoordinates() ); + gc.add( domain->giveNode( snodes.at(i) )->giveCoordinates() ); } gc.times(1. / 4.); // determine "average normal" for ( int i = 1; i <= 4; i++ ) { int j = ( i ) % 4 + 1; - h1.beDifferenceOf(* domain->giveNode( snodes.at(i) )->giveCoordinates(), gc); - h2.beDifferenceOf(* domain->giveNode( snodes.at(j) )->giveCoordinates(), gc); + h1.beDifferenceOf(domain->giveNode( snodes.at(i) )->giveCoordinates(), gc); + h2.beDifferenceOf(domain->giveNode( snodes.at(j) )->giveCoordinates(), gc); n.beVectorProductOf(h1, h2); if ( n.computeSquaredNorm() > 1.e-6 ) { n.normalize(); diff --git a/src/sm/Elements/3D/q27space.h b/src/sm/Elements/3D/q27space.h index 3da3b1a35..d6e52eebc 100644 --- a/src/sm/Elements/3D/q27space.h +++ b/src/sm/Elements/3D/q27space.h @@ -35,8 +35,8 @@ #ifndef q27space_h #define q27space_h -#include "Elements/structural3delement.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/structural3delement.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -59,31 +59,30 @@ class Q27Space : public Structural3DElement, public SPRNodalRecoveryModelInterfa Q27Space(int n, Domain * d); virtual ~Q27Space() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Interface *giveInterface(InterfaceType); - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } + void initializeFrom(InputRecord &ir) override; + Interface *giveInterface(InterfaceType) override; + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Q27Space_Name; } - virtual const char *giveClassName() const { return "Q27Space"; } + const char *giveInputRecordName() const override { return _IFT_Q27Space_Name; } + const char *giveClassName() const override { return "Q27Space"; } protected: - virtual int giveNumberOfIPForMassMtrxIntegration() { return 27; } + int giveNumberOfIPForMassMtrxIntegration() override { return 27; } /** * @name Surface load support */ //@{ - virtual IntegrationRule *GetSurfaceIntegrationRule(int); - virtual int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *gp); + int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *gp) override; //@} }; } // end namespace oofem diff --git a/src/sm/Elements/3D/qspace.C b/src/sm/Elements/3D/qspace.C index 10de6d306..6f3442caa 100644 --- a/src/sm/Elements/3D/qspace.C +++ b/src/sm/Elements/3D/qspace.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/3D/qspace.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/Elements/3D/qspace.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei3dhexaquad.h" #include "node.h" #include "gausspoint.h" @@ -50,18 +50,18 @@ REGISTER_Element(QSpace); FEI3dHexaQuad QSpace :: interpolation; -QSpace :: QSpace(int n, Domain *aDomain) : Structural3DElement(n, aDomain), ZZNodalRecoveryModelInterface(this) +QSpace :: QSpace(int n, Domain *aDomain) : Structural3DElement(n, aDomain), ZZNodalRecoveryModelInterface(this), SpatialLocalizerInterface(this) { numberOfDofMans = 20; } -IRResultType -QSpace :: initializeFrom(InputRecord *ir) +void +QSpace :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 27; - return Structural3DElement :: initializeFrom(ir); + Structural3DElement :: initializeFrom(ir); } @@ -71,16 +71,6 @@ FEInterpolation *QSpace :: giveInterpolation() const { return & interpolation; } // *** Surface load support *** // ****************************** -IntegrationRule * -QSpace :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Square, approxOrder); - iRule->SetUpPointsOnSquare(npoints, _Unknown); - return iRule; -} - - int QSpace :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp) { @@ -102,22 +92,21 @@ QSpace :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPo */ FloatArray gc(3); FloatArray h1(3), h2(3), nn(3), n(3); - IntArray snodes(4); answer.resize(3, 3); answer.zero(); - this->interpolation.computeSurfaceMapping(snodes, dofManArray, iSurf); + const auto &snodes = this->interpolation.computeSurfaceMapping(dofManArray, iSurf); for ( int i = 1; i <= 4; i++ ) { - gc.add( * domain->giveNode( snodes.at(i) )->giveCoordinates() ); + gc.add( domain->giveNode( snodes.at(i) )->giveCoordinates() ); } gc.times(1. / 4.); // determine "average normal" for ( int i = 1; i <= 4; i++ ) { int j = ( i ) % 4 + 1; - h1.beDifferenceOf(* domain->giveNode( snodes.at(i) )->giveCoordinates(), gc); - h2.beDifferenceOf(* domain->giveNode( snodes.at(j) )->giveCoordinates(), gc); + h1.beDifferenceOf(domain->giveNode( snodes.at(i) )->giveCoordinates(), gc); + h2.beDifferenceOf(domain->giveNode( snodes.at(j) )->giveCoordinates(), gc); n.beVectorProductOf(h1, h2); if ( n.computeSquaredNorm() > 1.e-6 ) { n.normalize(); @@ -166,6 +155,8 @@ QSpace :: giveInterface(InterfaceType interface) return static_cast< SPRNodalRecoveryModelInterface * >(this); } else if ( interface == NodalAveragingRecoveryModelInterfaceType ) { return static_cast< NodalAveragingRecoveryModelInterface * >(this); + } else if ( interface == SpatialLocalizerInterfaceType ) { + return static_cast< SpatialLocalizerInterface * >(this); } OOFEM_LOG_INFO("Interface on Qspace element not supported"); diff --git a/src/sm/Elements/3D/qspace.h b/src/sm/Elements/3D/qspace.h index 7384f943d..5949c85f8 100644 --- a/src/sm/Elements/3D/qspace.h +++ b/src/sm/Elements/3D/qspace.h @@ -35,11 +35,12 @@ #ifndef qspace_h #define qspace_h -#include "Elements/structural3delement.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/structural3delement.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "sprnodalrecoverymodel.h" +#include "spatiallocalizer.h" #define _IFT_QSpace_Name "qspace" @@ -52,7 +53,7 @@ class FEI3dHexaQuad; * @author Ladislav Svoboda * @author Mikael Öhman */ -class QSpace : public Structural3DElement, public SPRNodalRecoveryModelInterface, public ZZNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface +class QSpace : public Structural3DElement, public SPRNodalRecoveryModelInterface, public ZZNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface, public SpatialLocalizerInterface { protected: static FEI3dHexaQuad interpolation; @@ -63,34 +64,32 @@ class QSpace : public Structural3DElement, public SPRNodalRecoveryModelInterface QSpace(int n, Domain * d); virtual ~QSpace() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual Interface *giveInterface(InterfaceType); - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } + Interface *giveInterface(InterfaceType) override; + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QSpace_Name; } - virtual const char *giveClassName() const { return "QSpace"; } - -protected: + const char *giveInputRecordName() const override { return _IFT_QSpace_Name; } + const char *giveClassName() const override { return "QSpace"; } - virtual int giveNumberOfIPForMassMtrxIntegration() { return 27; } +protected: + int giveNumberOfIPForMassMtrxIntegration() override { return 27; } /** * @name Surface load support */ //@{ - virtual IntegrationRule *GetSurfaceIntegrationRule(int); - virtual int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *gp); + int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *gp) override; //@} }; } // end namespace oofem diff --git a/src/sm/Elements/3D/qtrspace.C b/src/sm/Elements/3D/qtrspace.C index e4ad9a5a1..b56f1fdae 100644 --- a/src/sm/Elements/3D/qtrspace.C +++ b/src/sm/Elements/3D/qtrspace.C @@ -33,9 +33,9 @@ */ -#include "Elements/3D/qtrspace.h" -#include "Materials/structuralms.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/Elements/3D/qtrspace.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "node.h" #include "material.h" #include "gausspoint.h" @@ -62,11 +62,11 @@ QTRSpace :: QTRSpace(int n, Domain *aDomain) : Structural3DElement(n, aDomain), } -IRResultType -QTRSpace :: initializeFrom(InputRecord *ir) +void +QTRSpace :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 4; - return Structural3DElement :: initializeFrom(ir); + Structural3DElement :: initializeFrom(ir); } diff --git a/src/sm/Elements/3D/qtrspace.h b/src/sm/Elements/3D/qtrspace.h index 97df9facf..1a598c692 100644 --- a/src/sm/Elements/3D/qtrspace.h +++ b/src/sm/Elements/3D/qtrspace.h @@ -35,8 +35,8 @@ #ifndef qtrspace_h #define qtrspace_h -#include "Elements/structural3delement.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/structural3delement.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -58,7 +58,6 @@ class FEI3dTetQuad; * - calculating its B,D,N matrices and dV. */ class QTRSpace : public Structural3DElement, public SPRNodalRecoveryModelInterface, public ZZNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface - { protected: static FEI3dTetQuad interpolation; @@ -67,25 +66,24 @@ class QTRSpace : public Structural3DElement, public SPRNodalRecoveryModelInterfa QTRSpace(int, Domain *); virtual ~QTRSpace() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual Interface *giveInterface(InterfaceType); - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } - virtual int giveNumberOfIPForMassMtrxIntegration() { return 5; } + Interface *giveInterface(InterfaceType) override; + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } + int giveNumberOfIPForMassMtrxIntegration() override { return 5; } - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QTRSpace_Name; } - virtual const char *giveClassName() const { return "QTRSpace"; } - + const char *giveInputRecordName() const override { return _IFT_QTRSpace_Name; } + const char *giveClassName() const override { return "QTRSpace"; } }; } // end namespace oofem #endif diff --git a/src/sm/Elements/3D/qwedge.C b/src/sm/Elements/3D/qwedge.C index 646aa5b0c..bba95c43c 100644 --- a/src/sm/Elements/3D/qwedge.C +++ b/src/sm/Elements/3D/qwedge.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/3D/qwedge.h" -#include "Materials/structuralms.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/Elements/3D/qwedge.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei3dwedgequad.h" #include "node.h" #include "material.h" @@ -55,18 +55,18 @@ REGISTER_Element(QWedge); FEI3dWedgeQuad QWedge :: interpolation; -QWedge :: QWedge(int n, Domain *aDomain) : Structural3DElement(n, aDomain), ZZNodalRecoveryModelInterface(this) +QWedge :: QWedge(int n, Domain *aDomain) : Structural3DElement(n, aDomain), ZZNodalRecoveryModelInterface(this), SpatialLocalizerInterface(this) { numberOfDofMans = 15; } -IRResultType -QWedge :: initializeFrom(InputRecord *ir) +void +QWedge :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 9; - return Structural3DElement :: initializeFrom(ir); + Structural3DElement :: initializeFrom(ir); } FEInterpolation * @@ -85,7 +85,9 @@ QWedge :: giveInterface(InterfaceType interface) return static_cast< SPRNodalRecoveryModelInterface * >(this); } else if ( interface == NodalAveragingRecoveryModelInterfaceType ) { return static_cast< NodalAveragingRecoveryModelInterface * >(this); - } + } else if ( interface == SpatialLocalizerInterfaceType ) { + return static_cast< SpatialLocalizerInterface * >(this); + } OOFEM_LOG_INFO("Interface on QWedge element not supported"); return NULL; diff --git a/src/sm/Elements/3D/qwedge.h b/src/sm/Elements/3D/qwedge.h index f74d6f02b..f70412eff 100644 --- a/src/sm/Elements/3D/qwedge.h +++ b/src/sm/Elements/3D/qwedge.h @@ -35,11 +35,12 @@ #ifndef qwedge_h #define qwedge_h -#include "Elements/structural3delement.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/structural3delement.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "sprnodalrecoverymodel.h" +#include "spatiallocalizer.h" #define _IFT_QWedge_Name "qwedge" @@ -52,8 +53,7 @@ class FEI3dWedgeQuad; * * @author Mikael Öhman (among others) */ -class QWedge : public Structural3DElement, public SPRNodalRecoveryModelInterface, public ZZNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface - +class QWedge : public Structural3DElement, public SPRNodalRecoveryModelInterface, public ZZNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface, public SpatialLocalizerInterface { protected: static FEI3dWedgeQuad interpolation; @@ -62,25 +62,24 @@ class QWedge : public Structural3DElement, public SPRNodalRecoveryModelInterface QWedge(int, Domain *); virtual ~QWedge() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int giveNumberOfIPForMassMtrxIntegration() { return 9; } + void initializeFrom(InputRecord &ir) override; + int giveNumberOfIPForMassMtrxIntegration() override { return 9; } - virtual Interface *giveInterface(InterfaceType); - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } + Interface *giveInterface(InterfaceType) override; + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QWedge_Name; } - virtual const char *giveClassName() const { return "QWedge"; } - + const char *giveInputRecordName() const override { return _IFT_QWedge_Name; } + const char *giveClassName() const override { return "QWedge"; } }; } // end namespace oofem #endif diff --git a/src/sm/Elements/3D/qwedgegrad.h b/src/sm/Elements/3D/qwedgegrad.h deleted file mode 100644 index 8b4beb8a3..000000000 --- a/src/sm/Elements/3D/qwedgegrad.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef qwedgegrad_h -#define qwedgegrad_h - -#include "../sm/Elements/3D/qwedge.h" -#include "../sm/Elements/graddpelement.h" - -#define _IFT_QWedgeGrad_Name "qwedgegrad" - -namespace oofem { -class FEI3dWedgeLin; - -/** - * Quadratic 3D element - * @author L. Svoboda - */ -class QWedgeGrad : public QWedge, public GradDpElement -{ -protected: - static FEI3dWedgeLin interpolation_lin; - -public: - QWedgeGrad(int, Domain *); - virtual ~QWedgeGrad() { } - - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - - // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QWedgeGrad_Name; } - virtual const char *giveClassName() const { return "QWedgeGrad"; } - virtual int computeNumberOfDofs() { return 51; } - virtual MaterialMode giveMaterialMode() { return _3dMat; } - -protected: - virtual void computeGaussPoints(); - virtual void computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer); - virtual void computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual StructuralElement *giveStructuralElement() { return this; } - virtual NLStructuralElement *giveNLStructuralElement() { return this; } - - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) { GradDpElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { GradDpElement :: computeStiffnessMatrix(answer, rMode, tStep); } - -}; -} -#endif // end namespace oofem diff --git a/src/sm/Elements/3D/space3delementevaluator.C b/src/sm/Elements/3D/space3delementevaluator.C index 04fa9babd..9c4517d28 100644 --- a/src/sm/Elements/3D/space3delementevaluator.C +++ b/src/sm/Elements/3D/space3delementevaluator.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/3D/space3delementevaluator.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/3D/space3delementevaluator.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "floatarray.h" #include "floatmatrix.h" #include "domain.h" @@ -48,24 +48,24 @@ namespace oofem { /* 3D Space Elements */ -void Space3dStructuralElementEvaluator :: computeNMatrixAt(FloatMatrix &answer, GaussPoint *gp) +void Space3dStructuralElementEvaluator::computeNMatrixAt(FloatMatrix &answer, GaussPoint *gp) { FloatArray N; Element *element = this->giveElement(); FEInterpolation *interp = element->giveInterpolation(); - interp->evalN( N, gp->giveNaturalCoordinates(), FEIIGAElementGeometryWrapper( element, gp->giveIntegrationRule()->giveKnotSpan() ) ); + interp->evalN(N, gp->giveNaturalCoordinates(), FEIIGAElementGeometryWrapper(element, gp->giveIntegrationRule()->giveKnotSpan() ) ); answer.beNMatrixOf(N, 3); } -void Space3dStructuralElementEvaluator :: computeBMatrixAt(FloatMatrix &answer, GaussPoint *gp) +void Space3dStructuralElementEvaluator::computeBMatrixAt(FloatMatrix &answer, GaussPoint *gp) { FloatMatrix d; Element *element = this->giveElement(); FEInterpolation *interp = element->giveInterpolation(); // this uses FEInterpolation::nodes2coords - quite inefficient in this case (large num of dofmans) - interp->evaldNdx( d, gp->giveNaturalCoordinates(), FEIIGAElementGeometryWrapper( element, gp->giveIntegrationRule()->giveKnotSpan() ) ); + interp->evaldNdx(d, gp->giveNaturalCoordinates(), FEIIGAElementGeometryWrapper(element, gp->giveIntegrationRule()->giveKnotSpan() ) ); answer.resize(6, d.giveNumberOfRows() * 3); @@ -87,24 +87,31 @@ void Space3dStructuralElementEvaluator :: computeBMatrixAt(FloatMatrix &answer, } } -double Space3dStructuralElementEvaluator :: computeVolumeAround(GaussPoint *gp) +double Space3dStructuralElementEvaluator::computeVolumeAround(GaussPoint *gp) { - double determinant = fabs( this->giveElement()->giveInterpolation() - ->giveTransformationJacobian( gp->giveNaturalCoordinates(), - FEIIGAElementGeometryWrapper( this->giveElement(), + double determinant = fabs(this->giveElement()->giveInterpolation() + ->giveTransformationJacobian(gp->giveNaturalCoordinates(), + FEIIGAElementGeometryWrapper(this->giveElement(), gp->giveIntegrationRule()->giveKnotSpan() ) ) ); - return determinant *gp->giveWeight(); + return determinant * gp->giveWeight(); } -void Space3dStructuralElementEvaluator :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +void Space3dStructuralElementEvaluator::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralCrossSection * >( this->giveElement()->giveCrossSection() )->giveRealStress_3d(answer, gp, strain, tStep); + answer = static_cast< StructuralCrossSection * >( this->giveElement()->giveCrossSection() )->giveRealStress_3d(strain, gp, tStep); } -void Space3dStructuralElementEvaluator :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +void Space3dStructuralElementEvaluator::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralCrossSection * >( this->giveElement()->giveCrossSection() )->giveStiffnessMatrix_3d(answer, rMode, gp, tStep); + answer = static_cast< StructuralCrossSection * >( this->giveElement()->giveCrossSection() )->giveStiffnessMatrix_3d(rMode, gp, tStep); } + +/* + * void Space3dStructuralElementEvaluator :: computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + * { + * answer = static_cast< StructuralCrossSection * >( this->giveElement()->giveCrossSection() )->giveStiffnessMatrix_dPdF_3d(rMode, gp, tStep); + * } + */ } // end namespace oofem diff --git a/src/sm/Elements/3D/space3delementevaluator.h b/src/sm/Elements/3D/space3delementevaluator.h index bffaab235..957374d2e 100644 --- a/src/sm/Elements/3D/space3delementevaluator.h +++ b/src/sm/Elements/3D/space3delementevaluator.h @@ -35,7 +35,7 @@ #ifndef space3delementevaluator_h #define space3delementevaluator_h -#include "../sm/Elements/structuralelementevaluator.h" +#include "sm/Elements/structuralelementevaluator.h" namespace oofem { /** @@ -52,17 +52,18 @@ class Space3dStructuralElementEvaluator : public StructuralElementEvaluator * Assemble interpolation matrix at given IP * In case of IGAElements, N is assumed to contain only nonzero interpolation functions */ - virtual void computeNMatrixAt(FloatMatrix &answer, GaussPoint *gp); + void computeNMatrixAt(FloatMatrix &answer, GaussPoint *gp) override; /** * Assembles the strain-displacement matrix of the receiver at given integration point * In case of IGAElements, B is assumed to contain only contribution from nonzero interpolation functions */ - virtual void computeBMatrixAt(FloatMatrix &answer, GaussPoint *gp); - virtual double computeVolumeAround(GaussPoint *gp); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeBMatrixAt(FloatMatrix &answer, GaussPoint *gp) override; + double computeVolumeAround(GaussPoint *gp) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + //void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; void giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u, D_v, D_w}; + answer = { D_u, D_v, D_w }; } }; } // end namespace oofem diff --git a/src/sm/Elements/AbaqusUserElement.C b/src/sm/Elements/AbaqusUserElement.C index 7160aa7ac..5aa09d082 100644 --- a/src/sm/Elements/AbaqusUserElement.C +++ b/src/sm/Elements/AbaqusUserElement.C @@ -51,15 +51,15 @@ namespace oofem { REGISTER_Element(AbaqusUserElement); -AbaqusUserElement :: AbaqusUserElement(int n, Domain *d) : - NLStructuralElement(n, d), uelobj(NULL), hasTangentFlag(false), uel(NULL) +AbaqusUserElement::AbaqusUserElement(int n, Domain *d) : + StructuralElement(n, d), uelobj(NULL), hasTangentFlag(false), uel(NULL) {} -AbaqusUserElement :: ~AbaqusUserElement() +AbaqusUserElement::~AbaqusUserElement() { #ifdef _WIN32 if ( this->uelobj ) { - FreeLibrary( ( HMODULE ) this->uelobj ); + FreeLibrary( ( HMODULE ) this->uelobj); } #else if ( this->uelobj ) { @@ -69,14 +69,9 @@ AbaqusUserElement :: ~AbaqusUserElement() } -IRResultType AbaqusUserElement :: initializeFrom(InputRecord *ir) +void AbaqusUserElement::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralElement::initializeFrom(ir); this->numberOfDofMans = dofManArray.giveSize(); @@ -101,12 +96,12 @@ IRResultType AbaqusUserElement :: initializeFrom(InputRecord *ir) #endif #ifdef _WIN32 - this->uelobj = ( void * ) LoadLibrary( filename.c_str() ); + this->uelobj = ( void * ) LoadLibrary(filename.c_str() ); if ( !this->uelobj ) { - OOFEM_ERROR( "couldn't load \"%s\",\ndlerror: %s", filename.c_str() ); + OOFEM_ERROR("couldn't load \"%s\",\ndlerror: %s", filename.c_str() ); } - * ( FARPROC * ) ( & this->uel ) = GetProcAddress( ( HMODULE ) this->uelobj, "uel_" ); //works for MinGW 32bit + * ( FARPROC * ) ( & this->uel ) = GetProcAddress( ( HMODULE ) this->uelobj, "uel_"); //works for MinGW 32bit if ( !this->uel ) { // char *dlresult = GetLastError(); DWORD dlresult = GetLastError(); //works for MinGW 32bit @@ -115,7 +110,7 @@ IRResultType AbaqusUserElement :: initializeFrom(InputRecord *ir) #else this->uelobj = dlopen(filename.c_str(), RTLD_NOW); if ( !this->uelobj ) { - OOFEM_ERROR( "couldn't load \"%s\",\ndlerror: %s", filename.c_str(), dlerror() ); + OOFEM_ERROR("couldn't load \"%s\",\ndlerror: %s", filename.c_str(), dlerror() ); } * ( void ** ) ( & this->uel ) = dlsym(this->uelobj, "uel_"); @@ -124,14 +119,12 @@ IRResultType AbaqusUserElement :: initializeFrom(InputRecord *ir) OOFEM_ERROR("couldn't load symbol uel,\ndlerror: %s\n", dlresult); } #endif - - return IRRT_OK; } -void AbaqusUserElement :: postInitialize() +void AbaqusUserElement::postInitialize() { - NLStructuralElement :: postInitialize(); + StructuralElement::postInitialize(); this->ndofel = this->numberOfDofMans * this->nCoords; this->mlvarx = this->ndofel; @@ -140,7 +133,7 @@ void AbaqusUserElement :: postInitialize() this->amatrx.resize(this->ndofel, this->ndofel); this->svars.resize(this->numSvars); this->lFlags.resize(5); - this->predef.resize( this->npredef * this->numberOfDofMans * 2 ); + this->predef.resize(this->npredef * this->numberOfDofMans * 2); this->energy.resize(8); this->U.resize(this->ndofel); this->V.resize(this->ndofel); @@ -159,9 +152,9 @@ void AbaqusUserElement :: postInitialize() } -void AbaqusUserElement :: giveInputRecord(DynamicInputRecord &input) +void AbaqusUserElement::giveInputRecord(DynamicInputRecord &input) { - StructuralElement :: giveInputRecord(input); + StructuralElement::giveInputRecord(input); input.setField(this->coords, _IFT_AbaqusUserElement_numcoords); input.setField(this->dofs, _IFT_AbaqusUserElement_dofs); @@ -171,17 +164,12 @@ void AbaqusUserElement :: giveInputRecord(DynamicInputRecord &input) input.setField(this->filename, _IFT_AbaqusUserElement_userElement); } -Interface *AbaqusUserElement :: giveInterface(InterfaceType it) -{ - return NULL; -} - -void AbaqusUserElement :: giveDofManDofIDMask(int inode, IntArray &answer) const +void AbaqusUserElement::giveDofManDofIDMask(int inode, IntArray &answer) const { answer = this->dofs; } -void AbaqusUserElement :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +void AbaqusUserElement::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { if ( !hasTangent() ) { // use uel to calculate the tangent @@ -193,22 +181,22 @@ void AbaqusUserElement :: computeStiffnessMatrix(FloatMatrix &answer, MatRespons // add stuff to behave differently if mUseNumericalTangent is set? } -void AbaqusUserElement :: updateYourself(TimeStep *tStep) +void AbaqusUserElement::updateYourself(TimeStep *tStep) { - StructuralElement :: updateYourself(tStep); + StructuralElement::updateYourself(tStep); svars = tempSvars; amatrx = tempAmatrx; rhs = tempRHS; hasTangentFlag = false; } -void AbaqusUserElement :: updateInternalState(TimeStep *tStep) +void AbaqusUserElement::updateInternalState(TimeStep *tStep) { FloatArray tmp; this->giveInternalForcesVector(tmp, tStep, 0); } -void AbaqusUserElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +void AbaqusUserElement::giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { // init U vector this->computeVectorOf(VM_Total, tStep, U); @@ -222,8 +210,8 @@ void AbaqusUserElement :: giveInternalForcesVector(FloatArray &answer, TimeStep this->giveInternalForcesVector(answer, tStep, U, DU, useUpdatedGpRecord); } -void AbaqusUserElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, - FloatArray &U, FloatMatrix &DU, int useUpdatedGpRecord) +void AbaqusUserElement::giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, + FloatArray &U, FloatMatrix &DU, int useUpdatedGpRecord) { if ( useUpdatedGpRecord ) { this->rhs.copyColumn(answer, 1); @@ -242,7 +230,7 @@ void AbaqusUserElement :: giveInternalForcesVector(FloatArray &answer, TimeStep //this->getSvars(); double period = 0., pnewdt = 0.; double dtime = tStep->giveTimeIncrement(); - double time[] = {tStep->giveTargetTime() - dtime, tStep->giveTargetTime()}; + double time[] = { tStep->giveTargetTime() - dtime, tStep->giveTargetTime() }; this->uel( loc_rhs.givePointer(), loc_amatrx.givePointer(), @@ -300,7 +288,7 @@ void AbaqusUserElement :: giveInternalForcesVector(FloatArray &answer, TimeStep void -AbaqusUserElement :: computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity) +AbaqusUserElement::computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity) { answer.resize(ndofel, ndofel); answer.zero(); diff --git a/src/sm/Elements/AbaqusUserElement.h b/src/sm/Elements/AbaqusUserElement.h index d65716726..7b09f919d 100644 --- a/src/sm/Elements/AbaqusUserElement.h +++ b/src/sm/Elements/AbaqusUserElement.h @@ -36,7 +36,6 @@ #define abaqususerelement_h #include "structuralelement.h" -#include "nlstructuralelement.h" #include "floatarray.h" #include "floatmatrix.h" #include "timestep.h" @@ -54,10 +53,9 @@ //@} namespace oofem { - /** * UEL interface from Abaqus user elements. - * + * * The function prototype for UEL is: * SUBROUTINE UEL(RHS,AMATRX,SVARS,ENERGY,NDOFEL,NRHS,NSVARS, * PROPS,NPROPS,COORDS,MCRD,NNODE,U,DU,V,A,JTYPE,TIME, @@ -74,7 +72,7 @@ namespace oofem { * * @author Giovanni */ -class AbaqusUserElement : public NLStructuralElement +class AbaqusUserElement : public StructuralElement { private: /// Dynamically loaded uel @@ -135,10 +133,10 @@ class AbaqusUserElement : public NLStructuralElement int mdLoad = 0; FloatMatrix adlmag, ddlmag; - int *jdltype = NULL; // Temporary init. + int *jdltype = nullptr; // Temporary init. /// params - double params [ 3 ]; + double params[ 3 ]; /// jprops IntArray jprops; @@ -147,16 +145,16 @@ class AbaqusUserElement : public NLStructuralElement bool hasTangentFlag; /// Pointer to the dynamically loaded uel-function (translated to C) - void (*uel)(double *rhs, double *amatrx, double *svars, double energy [ 8 ], int *ndofel, // 5 + void (*uel)(double *rhs, double *amatrx, double *svars, double energy[ 8 ], int *ndofel, // 5 int *nrhs, int *nsvars, double *props, int *nprops, double *coords, int *mcrd, // 6 int *nnode, double *u, double *du, double *v, double *a, int *jtype, // 6 - double time [ 2 ], double *dtime, int *kstep, int *kinc, int *jelem, // 5 - double params [ 3 ], int *ndload, int *jdltyp, double *adlmag, double *predef, // 5 + double time[ 2 ], double *dtime, int *kstep, int *kinc, int *jelem, // 5 + double params[ 3 ], int *ndload, int *jdltyp, double *adlmag, double *predef, // 5 int *npredef, int *lflags, int *mvarx, double *ddlmag, int *mdload, // 5 double *pnewdt, int *jprops, int *njprop, double *period); // 4 - tot 36 /// File containing the uel function - std :: string filename; + std::string filename; public: /// Constructor @@ -165,17 +163,17 @@ class AbaqusUserElement : public NLStructuralElement /// Destructor virtual ~AbaqusUserElement(); - virtual void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL); - //virtual void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) override; + //void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, FloatArray &U, FloatMatrix &DU, int useUpdatedGpRecord); - virtual int computeNumberOfDofs() { return this->ndofel; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) + int computeNumberOfDofs() override { return this->ndofel; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) override { OOFEM_ERROR("Abaqus user element cannot support computing local unknown vector\n"); } - virtual void updateYourself(TimeStep *tStep); - virtual void updateInternalState(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; + void updateInternalState(TimeStep *tStep) override; bool hasTangent() const { return hasTangentFlag; @@ -200,40 +198,33 @@ class AbaqusUserElement : public NLStructuralElement return tempAmatrx; } - virtual Interface *giveInterface(InterfaceType it); - - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void postInitialize(); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void postInitialize() override; // definition & identification - virtual const char *giveClassName() const { return "AbaqusUserElement"; } - virtual const char *giveInputRecordName() const { return _IFT_AbaqusUserElement_Name; } - virtual integrationDomain giveIntegrationDomain() const { - return _UnknownIntegrationDomain; - } - virtual Element_Geometry_Type giveGeometryType() const { - return EGT_line_1; - } + const char *giveClassName() const override { return "AbaqusUserElement"; } + const char *giveInputRecordName() const override { return _IFT_AbaqusUserElement_Name; } + integrationDomain giveIntegrationDomain() const override { return _UnknownIntegrationDomain; } + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } protected: - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("Function not defined for AbaqusUserElement and should never be called. This is a bug."); } - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("Function not defined for AbaqusUserElement and should never be called. This is a bug."); } - virtual void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) { + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override { OOFEM_ERROR("Function not defined for AbaqusUserElement and should never be called. This is a bug."); } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override { OOFEM_ERROR("Function not defined for AbaqusUserElement and should never be called. This is a bug."); return 0; } }; - }// namespace oofem #endif // abaqususerelement_h diff --git a/src/sm/Elements/Axisymmetry/axisymm3d.C b/src/sm/Elements/Axisymmetry/axisymm3d.C index 859339c49..051d942b4 100644 --- a/src/sm/Elements/Axisymmetry/axisymm3d.C +++ b/src/sm/Elements/Axisymmetry/axisymm3d.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/Axisymmetry/axisymm3d.h" +#include "sm/Elements/Axisymmetry/axisymm3d.h" #include "fei2dtrlin.h" #include "node.h" #include "gausspoint.h" @@ -106,24 +106,17 @@ Axisymm3d :: giveArea() } -IRResultType -Axisymm3d :: initializeFrom(InputRecord *ir) +void +Axisymm3d :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - numberOfGaussPoints = 1; - result = StructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralElement :: initializeFrom(ir); if ( !( ( numberOfGaussPoints == 1 ) || ( numberOfGaussPoints == 4 ) || ( numberOfGaussPoints == 7 ) ) ) { numberOfGaussPoints = 1; } - - return IRRT_OK; } diff --git a/src/sm/Elements/Axisymmetry/axisymm3d.h b/src/sm/Elements/Axisymmetry/axisymm3d.h index 5f84e8880..e8143fe88 100644 --- a/src/sm/Elements/Axisymmetry/axisymm3d.h +++ b/src/sm/Elements/Axisymmetry/axisymm3d.h @@ -35,7 +35,7 @@ #ifndef axisymm3d_h #define axisymm3d_h -#include "Elements/structural2delement.h" +#include "sm/Elements/structural2delement.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -71,27 +71,26 @@ public SpatialLocalizerInterface virtual ~Axisymm3d(); virtual double giveArea(); - virtual Interface *giveInterface(InterfaceType it); - virtual FEInterpolation *giveInterpolation() const; + Interface *giveInterface(InterfaceType it) override; + FEInterpolation *giveInterpolation() const override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); - - virtual const char *giveClassName() const { return "Axisymm3d"; } - virtual const char *giveInputRecordName() const { return _IFT_Axisymm3d_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; + const char *giveClassName() const override { return "Axisymm3d"; } + const char *giveInputRecordName() const override { return _IFT_Axisymm3d_Name; } + void initializeFrom(InputRecord &ir) override; }; } // end namespace oofem #endif // axisymm3d_h diff --git a/src/sm/Elements/Axisymmetry/l4axisymm.C b/src/sm/Elements/Axisymmetry/l4axisymm.C index 5e02339e8..1e3363341 100644 --- a/src/sm/Elements/Axisymmetry/l4axisymm.C +++ b/src/sm/Elements/Axisymmetry/l4axisymm.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Axisymmetry/l4axisymm.h" +#include "sm/Elements/Axisymmetry/l4axisymm.h" #include "fei2dquadlin.h" #include "node.h" #include "gausspoint.h" @@ -89,15 +89,11 @@ L4Axisymm :: giveInterface(InterfaceType interface) } -IRResultType -L4Axisymm :: initializeFrom(InputRecord *ir) +void +L4Axisymm :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 4; - IRResultType result = NLStructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - + NLStructuralElement :: initializeFrom(ir); if ( !( ( numberOfGaussPoints == 1 ) || ( numberOfGaussPoints == 4 ) || @@ -107,8 +103,6 @@ L4Axisymm :: initializeFrom(InputRecord *ir) } numberOfFiAndShGaussPoints = 1; - - return IRRT_OK; } diff --git a/src/sm/Elements/Axisymmetry/l4axisymm.h b/src/sm/Elements/Axisymmetry/l4axisymm.h index 5fad4ee08..4186eee2b 100644 --- a/src/sm/Elements/Axisymmetry/l4axisymm.h +++ b/src/sm/Elements/Axisymmetry/l4axisymm.h @@ -35,7 +35,7 @@ #ifndef l4axisymm_h #define l4axisymm_h -#include "Elements/structural2delement.h" +#include "sm/Elements/structural2delement.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" #include "spatiallocalizer.h" @@ -60,30 +60,30 @@ public SpatialLocalizerInterface L4Axisymm(int n, Domain * d); virtual ~L4Axisymm(); - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_L4Axisymm_Name; } - virtual const char *giveClassName() const { return "L4Axisymm"; } + const char *giveInputRecordName() const override { return _IFT_L4Axisymm_Name; } + const char *giveClassName() const override { return "L4Axisymm"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) ; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override; }; } // end namespace oofem #endif // l4axisymm_h diff --git a/src/sm/Elements/Axisymmetry/q4axisymm.C b/src/sm/Elements/Axisymmetry/q4axisymm.C index 1e5ea8aa0..2e33011dc 100644 --- a/src/sm/Elements/Axisymmetry/q4axisymm.C +++ b/src/sm/Elements/Axisymmetry/q4axisymm.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/Axisymmetry/q4axisymm.h" +#include "sm/Elements/Axisymmetry/q4axisymm.h" #include "fei2dquadquad.h" #include "node.h" #include "gausspoint.h" @@ -77,21 +77,15 @@ Q4Axisymm :: giveInterpolation() const -IRResultType -Q4Axisymm :: initializeFrom(InputRecord *ir) +void +Q4Axisymm :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro numberOfGaussPoints = 4; - result = StructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralElement :: initializeFrom(ir); numberOfFiAndShGaussPoints = 1; ///@todo only works for 1 //JB IR_GIVE_OPTIONAL_FIELD(ir, numberOfFiAndShGaussPoints, _IFT_Q4Axisymm_nipfish); - - return result; } diff --git a/src/sm/Elements/Axisymmetry/q4axisymm.h b/src/sm/Elements/Axisymmetry/q4axisymm.h index 4b5483892..ce582ec2c 100644 --- a/src/sm/Elements/Axisymmetry/q4axisymm.h +++ b/src/sm/Elements/Axisymmetry/q4axisymm.h @@ -35,8 +35,8 @@ #ifndef q4axisymm_h #define q4axisymm_h -#include "Elements/structuralelement.h" -#include "Elements/structural2delement.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Elements/structural2delement.h" #include "zznodalrecoverymodel.h" ///@name Input fields for Q4Axisymm @@ -63,21 +63,19 @@ class Q4Axisymm : public AxisymElement, public ZZNodalRecoveryModelInterface Q4Axisymm(int n, Domain * d); virtual ~Q4Axisymm(); - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; // definition & identification - virtual Interface *giveInterface(InterfaceType); - virtual const char *giveInputRecordName() const { return _IFT_Q4Axisymm_Name; } - virtual const char *giveClassName() const { return "Q4axisymm"; } - virtual IRResultType initializeFrom(InputRecord *ir); - -protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) ; - - + Interface *giveInterface(InterfaceType) override; + const char *giveInputRecordName() const override { return _IFT_Q4Axisymm_Name; } + const char *giveClassName() const override { return "Q4axisymm"; } + void initializeFrom(InputRecord &ir) override; + + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override; + #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) override; #endif }; } // end namespace oofem diff --git a/src/sm/Elements/Bars/qtruss1d.C b/src/sm/Elements/Bars/qtruss1d.C index 53a5d04f7..34e5c7d86 100644 --- a/src/sm/Elements/Bars/qtruss1d.C +++ b/src/sm/Elements/Bars/qtruss1d.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Bars/qtruss1d.h" +#include "sm/Elements/Bars/qtruss1d.h" #include "fei1dquad.h" #include "crosssection.h" #include "gausspoint.h" @@ -40,7 +40,7 @@ #include "floatmatrix.h" #include "floatarray.h" #include "intarray.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "mathfem.h" #include "classfactory.h" @@ -51,74 +51,80 @@ namespace oofem { REGISTER_Element(QTruss1d); -FEI1dQuad QTruss1d :: interpolation(1); +FEI1dQuad QTruss1d::interpolation(1); -QTruss1d :: QTruss1d(int n, Domain *aDomain) : NLStructuralElement(n, aDomain) +QTruss1d::QTruss1d(int n, Domain *aDomain) : NLStructuralElement(n, aDomain) { numberOfDofMans = 3; } -IRResultType -QTruss1d :: initializeFrom(InputRecord *ir) +void +QTruss1d::initializeFrom(InputRecord &ir) { - return StructuralElement :: initializeFrom(ir); + StructuralElement::initializeFrom(ir); } void -QTruss1d :: giveDofManDofIDMask(int inode, IntArray &answer) const +QTruss1d::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u}; + answer = { D_u }; } int -QTruss1d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +QTruss1d::computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { - this->interpolation.local2global( answer, lcoords, FEIElementGeometryWrapper(this) ); + this->interpolation.local2global(answer, lcoords, FEIElementGeometryWrapper(this) ); return 1; } void -QTruss1d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +QTruss1d::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->giveRealStress_1d(strain, gp, tStep); +} + +void +QTruss1d::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveRealStress_1d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_1d(rMode, gp, tStep); } void -QTruss1d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +QTruss1d::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveStiffnessMatrix_1d(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_dPdF_1d(rMode, gp, tStep); } double -QTruss1d :: computeVolumeAround(GaussPoint *gp) +QTruss1d::computeVolumeAround(GaussPoint *gp) // Returns the length of the receiver. This method is valid only if 1 // Gauss point is used. { - double detJ = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double detJ = fabs(this->interpolation.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); double weight = gp->giveWeight(); - return detJ *weight *this->giveCrossSection()->give(CS_Area, gp); + return detJ * weight * this->giveCrossSection()->give(CS_Area, gp); } -void QTruss1d :: computeGaussPoints() +void QTruss1d::computeGaussPoints() // Sets up the array of Gauss Points of the receiver.XF { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } void -QTruss1d :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +QTruss1d::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) { - this->interpolation.evaldNdx( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interpolation.evaldNdx(answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); } void -QTruss1d :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) +QTruss1d::computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) { this->computeBmatrixAt(gp, answer); } diff --git a/src/sm/Elements/Bars/qtruss1d.h b/src/sm/Elements/Bars/qtruss1d.h index 8b39c7319..1b43750d6 100644 --- a/src/sm/Elements/Bars/qtruss1d.h +++ b/src/sm/Elements/Bars/qtruss1d.h @@ -35,7 +35,7 @@ #ifndef qtruss1d_h #define qtruss1d_h -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/nlstructuralelement.h" #define _IFT_QTruss1d_Name "qtruss1d" @@ -52,36 +52,36 @@ class QTruss1d : public NLStructuralElement static FEI1dQuad interpolation; public: - QTruss1d(int n, Domain * d); + QTruss1d(int n, Domain *d); virtual ~QTruss1d() { } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual int computeNumberOfDofs() { return 3; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 3; } + void giveDofManDofIDMask(int inode, IntArray &) const override; - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane) + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override { return this->computeLength(); } - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual int testElementExtension(ElementExtension ext) { return 0; } + int testElementExtension(ElementExtension ext) override { return 0; } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QTruss1d_Name; } - virtual const char *giveClassName() const { return "QTruss1d"; } + const char *giveInputRecordName() const override { return _IFT_QTruss1d_Name; } + const char *giveClassName() const override { return "QTruss1d"; } - virtual MaterialMode giveMaterialMode() { return _1dMat; } - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + MaterialMode giveMaterialMode() override { return _1dMat; } + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeGaussPoints(); - + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeGaussPoints() override; }; } // end namespace oofem #endif // truss1d_h diff --git a/src/sm/Elements/Bars/truss1d.C b/src/sm/Elements/Bars/truss1d.C index 0b319a562..44c1be6e0 100644 --- a/src/sm/Elements/Bars/truss1d.C +++ b/src/sm/Elements/Bars/truss1d.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Bars/truss1d.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/Bars/truss1d.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei1dlin.h" #include "node.h" #include "material.h" @@ -52,11 +52,11 @@ namespace oofem { REGISTER_Element(Truss1d); -FEI1dLin Truss1d :: interp(1); // Initiates the static interpolator +FEI1dLin Truss1d::interp(1); // Initiates the static interpolator -Truss1d :: Truss1d(int n, Domain *aDomain) : - StructuralElement(n, aDomain), +Truss1d::Truss1d(int n, Domain *aDomain) : + NLStructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this), NodalAveragingRecoveryModelInterface(), SpatialLocalizerInterface(this), ZZErrorEstimatorInterface(this), @@ -66,21 +66,21 @@ Truss1d :: Truss1d(int n, Domain *aDomain) : } -void Truss1d :: computeGaussPoints() +void Truss1d::computeGaussPoints() // Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } } FEInterpolation * -Truss1d :: giveInterpolation() const { return & interp; } +Truss1d::giveInterpolation() const { return & interp; } void -Truss1d :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +Truss1d::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. This expression is // valid in both local and global axes. { @@ -95,20 +95,20 @@ Truss1d :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) void -Truss1d :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +Truss1d::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // // Returns linear part of geometrical equations of the receiver at gp. // Returns the linear part of the B matrix // { FloatMatrix dN; - this->interp.evaldNdx( dN, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interp.evaldNdx(dN, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.beTranspositionOf(dN); ///@todo It would be more suitable to follow the column-major version as done in FEI-classes } void -Truss1d :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) +Truss1d::computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) // // Returns the [1x2] displacement gradient matrix {BH} of the receiver, // evaluated at gp. @@ -120,12 +120,12 @@ Truss1d :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) void -Truss1d :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +Truss1d::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the displacement interpolation matrix {N} of the receiver, // evaluated at gp. { FloatArray n; - this->interp.evalN( n, iLocCoord, FEIElementGeometryWrapper(this) ); + this->interp.evalN(n, iLocCoord, FEIElementGeometryWrapper(this) ); // Reshape answer.resize(1, 2); ///@todo It would be more suitable to follow the column-major order and just do answer.setColumn(...) answer.at(1, 1) = n.at(1); @@ -134,60 +134,68 @@ Truss1d :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) double -Truss1d :: computeVolumeAround(GaussPoint *gp) +Truss1d::computeVolumeAround(GaussPoint *gp) // Returns the length of the receiver. This method is valid only if 1 // Gauss point is used. { - double detJ = fabs( this->interp.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - return detJ *gp->giveWeight() * this->giveCrossSection()->give(CS_Area, gp); + double detJ = fabs(this->interp.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + return detJ * gp->giveWeight() * this->giveCrossSection()->give(CS_Area, gp); } void -Truss1d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +Truss1d::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveRealStress_1d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveRealStress_1d(strain, gp, tStep); } void -Truss1d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +Truss1d::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveStiffnessMatrix_1d(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_1d(rMode, gp, tStep); } void -Truss1d :: giveDofManDofIDMask(int inode, IntArray &answer) const +Truss1d::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - answer = {D_u}; + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_dPdF_1d(rMode, gp, tStep); +} + +void +Truss1d::giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = { + D_u + }; } void -Truss1d :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, - IntArray &localNodeIdArray, IntArray &globalNodeIdArray, - HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, - int &localNodeId, int &localElemId, int &localBcId, - IntArray &controlNode, IntArray &controlDof, - HuertaErrorEstimator :: AnalysisMode aMode) +Truss1d::HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, + IntArray &localNodeIdArray, IntArray &globalNodeIdArray, + HuertaErrorEstimatorInterface::SetupMode sMode, TimeStep *tStep, + int &localNodeId, int &localElemId, int &localBcId, + IntArray &controlNode, IntArray &controlDof, + HuertaErrorEstimator::AnalysisMode aMode) { - int inode, nodes = 2; - FloatArray *corner [ 2 ], midNode, cor [ 2 ]; - double x = 0.0; + int nodes = 2; - if ( sMode == HuertaErrorEstimatorInterface :: NodeMode || - ( sMode == HuertaErrorEstimatorInterface :: BCMode && aMode == HuertaErrorEstimator :: HEE_linear ) ) { - for ( inode = 0; inode < nodes; inode++ ) { + FloatArray corner[ 2 ], midNode, cor[ 2 ]; + if ( sMode == HuertaErrorEstimatorInterface::NodeMode || + ( sMode == HuertaErrorEstimatorInterface::BCMode && aMode == HuertaErrorEstimator::HEE_linear ) ) { + double x = 0.0; + for ( int inode = 0; inode < nodes; inode++ ) { corner [ inode ] = this->giveNode(inode + 1)->giveCoordinates(); - if ( corner [ inode ]->giveSize() != 3 ) { + if ( corner [ inode ].giveSize() != 3 ) { cor [ inode ].resize(3); - cor [ inode ].at(1) = corner [ inode ]->at(1); + cor [ inode ].at(1) = corner [ inode ].at(1); cor [ inode ].at(2) = 0.0; cor [ inode ].at(3) = 0.0; - corner [ inode ] = & ( cor [ inode ] ); + corner [ inode ] = cor [ inode ]; } - x += corner [ inode ]->at(1); + x += corner [ inode ].at(1); } midNode.resize(3); @@ -204,24 +212,24 @@ Truss1d :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refi } -void Truss1d :: HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) +void Truss1d::HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) { computeNmatrixAt(gp->giveSubPatchCoordinates(), answer); } #ifdef __OOFEG -void Truss1d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +void Truss1d::drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { GraphicObj *go; // if (!go) { // create new one - WCRec p [ 2 ]; /* point */ + WCRec p[ 2 ]; /* point */ if ( !gc.testElementGraphicActivity(this) ) { return; } EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); + EASValsSetColor(gc.getElementColor() ); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); p [ 0 ].y = 0.; @@ -236,18 +244,18 @@ void Truss1d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } -void Truss1d :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +void Truss1d::drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) { GraphicObj *go; double defScale = gc.getDefScale(); // if (!go) { // create new one - WCRec p [ 2 ]; /* point */ + WCRec p[ 2 ]; /* point */ if ( !gc.testElementGraphicActivity(this) ) { return; } EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); p [ 0 ].y = 0.; @@ -262,13 +270,13 @@ void Truss1d :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, U } -void Truss1d :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) +void Truss1d::drawScalar(oofegGraphicContext &gc, TimeStep *tStep) { int i, indx, result = 0; - WCRec p [ 2 ]; + WCRec p[ 2 ]; GraphicObj *tr; FloatArray v1, v2; - double s [ 2 ], defScale; + double s[ 2 ], defScale; if ( !gc.testElementGraphicActivity(this) ) { return; @@ -338,7 +346,7 @@ void Truss1d :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) * tr = CreateLine3D(p); * EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, tr); */ - WCRec pp [ 4 ]; + WCRec pp[ 4 ]; pp [ 0 ].x = p [ 0 ].x; pp [ 0 ].y = 0.0; pp [ 0 ].z = 0.0; @@ -353,14 +361,14 @@ void Truss1d :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) pp [ 3 ].z = 0.0; tr = CreateQuad3D(pp); EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); //EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); EASValsSetFillStyle(FILL_HOLLOW); EGWithMaskChangeAttributes(WIDTH_MASK | FILL_MASK | COLOR_MASK | LAYER_MASK, tr); EMAddGraphicsToModel(ESIModel(), tr); } else { //tr = CreateTriangleWD3D(p, s[0], s[1], s[2]); - EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); tr = CreateLine3D(p); EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, tr); EMAddGraphicsToModel(ESIModel(), tr); @@ -372,18 +380,18 @@ void Truss1d :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) Interface * -Truss1d :: giveInterface(InterfaceType interface) +Truss1d::giveInterface(InterfaceType interface) { if ( interface == ZZNodalRecoveryModelInterfaceType ) { - return static_cast< ZZNodalRecoveryModelInterface * >(this); + return static_cast< ZZNodalRecoveryModelInterface * >( this ); } else if ( interface == NodalAveragingRecoveryModelInterfaceType ) { - return static_cast< NodalAveragingRecoveryModelInterface * >(this); + return static_cast< NodalAveragingRecoveryModelInterface * >( this ); } else if ( interface == SpatialLocalizerInterfaceType ) { - return static_cast< SpatialLocalizerInterface * >(this); + return static_cast< SpatialLocalizerInterface * >( this ); } else if ( interface == ZZErrorEstimatorInterfaceType ) { - return static_cast< ZZErrorEstimatorInterface * >(this); + return static_cast< ZZErrorEstimatorInterface * >( this ); } else if ( interface == HuertaErrorEstimatorInterfaceType ) { - return static_cast< HuertaErrorEstimatorInterface * >(this); + return static_cast< HuertaErrorEstimatorInterface * >( this ); } return NULL; @@ -391,11 +399,10 @@ Truss1d :: giveInterface(InterfaceType interface) void -Truss1d :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep) +Truss1d::NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) { GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); this->giveIPValue(answer, gp, type, tStep); } - } // end namespace oofem diff --git a/src/sm/Elements/Bars/truss1d.h b/src/sm/Elements/Bars/truss1d.h index ed92db541..f0e8723cf 100644 --- a/src/sm/Elements/Bars/truss1d.h +++ b/src/sm/Elements/Bars/truss1d.h @@ -35,10 +35,10 @@ #ifndef truss1d_h #define truss1d_h -#include "../sm/Elements/structuralelement.h" -#include "../sm/ErrorEstimators/directerrorindicatorrc.h" -#include "../sm/ErrorEstimators/zzerrorestimator.h" -#include "../sm/ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/nlstructuralelement.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "spatiallocalizer.h" @@ -53,70 +53,70 @@ class FEI1dLin; * This class implements a two-node truss bar element for one-dimensional * analysis. */ -class Truss1d : public StructuralElement, -public ZZNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface, public SpatialLocalizerInterface, -public ZZErrorEstimatorInterface, -public HuertaErrorEstimatorInterface +class Truss1d : public NLStructuralElement, + public ZZNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface, public SpatialLocalizerInterface, + public ZZErrorEstimatorInterface, + public HuertaErrorEstimatorInterface { protected: static FEI1dLin interp; public: - Truss1d(int n, Domain * d); + Truss1d(int n, Domain *d); virtual ~Truss1d() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual int computeNumberOfDofs() { return 2; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 2; } + void giveDofManDofIDMask(int inode, IntArray &) const override; // characteristic length (for crack band approach) - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane) + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override { return this->computeLength(); } - virtual double computeVolumeAround(GaussPoint *gp); - - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + double computeVolumeAround(GaussPoint *gp) override; - virtual int testElementExtension(ElementExtension ext) { return 0; } + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType it); + int testElementExtension(ElementExtension ext) override { return 0; } + + Interface *giveInterface(InterfaceType it) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Truss1d_Name; } - virtual const char *giveClassName() const { return "Truss1d"; } - virtual MaterialMode giveMaterialMode() { return _1dMat; } + const char *giveInputRecordName() const override { return _IFT_Truss1d_Name; } + const char *giveClassName() const override { return "Truss1d"; } + MaterialMode giveMaterialMode() override { return _1dMat; } // NodalAveragingRecoveryMInterface - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; // HuertaErrorEstimatorInterface - virtual void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, - IntArray &localNodeIdArray, IntArray &globalNodeIdArray, - HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, - int &localNodeId, int &localElemId, int &localBcId, - IntArray &controlNode, IntArray &controlDof, - HuertaErrorEstimator :: AnalysisMode aMode); - virtual void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); + void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, + IntArray &localNodeIdArray, IntArray &globalNodeIdArray, + HuertaErrorEstimatorInterface::SetupMode sMode, TimeStep *tStep, + int &localNodeId, int &localElemId, int &localBcId, + IntArray &controlNode, IntArray &controlDof, + HuertaErrorEstimator::AnalysisMode aMode) override; + void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeGaussPoints(); - + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; ///@todo BH is just used in nlstructuralelement + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeGaussPoints() override; }; } // end namespace oofem #endif // truss1d_h diff --git a/src/sm/Elements/Bars/truss2d.C b/src/sm/Elements/Bars/truss2d.C index 55cd68938..421645672 100644 --- a/src/sm/Elements/Bars/truss2d.C +++ b/src/sm/Elements/Bars/truss2d.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/Bars/truss2d.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/Elements/Bars/truss2d.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "node.h" #include "material.h" #include "gausspoint.h" @@ -52,11 +52,11 @@ namespace oofem { REGISTER_Element(Truss2d); - FEI2dLineLin Truss2d :: interp[3] = {FEI2dLineLin(1,3), - FEI2dLineLin(1,2), - FEI2dLineLin(2,3)}; +FEI2dLineLin Truss2d::interp[ 3 ] = { FEI2dLineLin(1, 3), + FEI2dLineLin(1, 2), + FEI2dLineLin(2, 3) }; -Truss2d :: Truss2d(int n, Domain *aDomain) : +Truss2d::Truss2d(int n, Domain *aDomain) : NLStructuralElement(n, aDomain) { numberOfDofMans = 2; @@ -67,7 +67,7 @@ Truss2d :: Truss2d(int n, Domain *aDomain) : void -Truss2d :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +Truss2d::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // // Returns linear part of geometrical equations of the receiver at gp. // Returns the linear part of the B matrix @@ -100,7 +100,7 @@ Truss2d :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) void -Truss2d :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) +Truss2d::computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) { // Will be the same as the regular B-matrix this->computeBmatrixAt(gp, answer); @@ -108,19 +108,19 @@ Truss2d :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) -void Truss2d :: computeGaussPoints() +void Truss2d::computeGaussPoints() // Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } } void -Truss2d :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +Truss2d::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. This expression is // valid in both local and global axes. { @@ -141,7 +141,7 @@ Truss2d :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) void -Truss2d :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +Truss2d::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the displacement interpolation matrix {N} of the receiver, eva- // luated at gp. { @@ -161,7 +161,7 @@ Truss2d :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) int -Truss2d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +Truss2d::computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { //determine in which plane the truss is defined int c1 = 0, c2 = 0; @@ -175,14 +175,14 @@ Truss2d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoord answer.resize(3); answer.zero(); - answer.at(c1) = n1 * this->giveNode(1)->giveCoordinate(c1) + n2 *this->giveNode(2)->giveCoordinate(c1); - answer.at(c2) = n1 * this->giveNode(1)->giveCoordinate(c2) + n2 *this->giveNode(2)->giveCoordinate(c2); + answer.at(c1) = n1 * this->giveNode(1)->giveCoordinate(c1) + n2 * this->giveNode(2)->giveCoordinate(c1); + answer.at(c2) = n1 * this->giveNode(1)->giveCoordinate(c2) + n2 * this->giveNode(2)->giveCoordinate(c2); return 1; } -double Truss2d :: computeVolumeAround(GaussPoint *gp) +double Truss2d::computeVolumeAround(GaussPoint *gp) // Returns the length of the receiver. This method is valid only if 1 // Gauss point is used. { @@ -191,7 +191,7 @@ double Truss2d :: computeVolumeAround(GaussPoint *gp) } -double Truss2d :: computeLength() +double Truss2d::computeLength() // Returns the length of the receiver. { //determine in which plane the truss is defined @@ -213,7 +213,7 @@ double Truss2d :: computeLength() } -double Truss2d :: givePitch() +double Truss2d::givePitch() // Returns the pitch of the receiver. { double xA, xB, zA, zB; @@ -237,7 +237,7 @@ double Truss2d :: givePitch() int -Truss2d :: giveLocalCoordinateSystem(FloatMatrix &answer) +Truss2d::giveLocalCoordinateSystem(FloatMatrix &answer) // // returns a unit vectors of local coordinate system at element // stored rowwise (mainly used by some materials with ortho and anisotrophy) @@ -248,7 +248,7 @@ Truss2d :: giveLocalCoordinateSystem(FloatMatrix &answer) answer.resize(3, 3); answer.zero(); - sine = sin( this->givePitch() ); + sine = sin(this->givePitch() ); cosine = cos(pitch); answer.at(1, 1) = cosine; @@ -262,7 +262,7 @@ Truss2d :: giveLocalCoordinateSystem(FloatMatrix &answer) void -Truss2d :: resolveCoordIndices(int &c1, int &c2) +Truss2d::resolveCoordIndices(int &c1, int &c2) { if ( cs_mode == 0 ) { //xz-plane @@ -281,52 +281,56 @@ Truss2d :: resolveCoordIndices(int &c1, int &c2) } } -IRResultType -Truss2d :: initializeFrom(InputRecord *ir) +void +Truss2d::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + NLStructuralElement::initializeFrom(ir); cs_mode = 0; IR_GIVE_OPTIONAL_FIELD(ir, cs_mode, _IFT_Truss2d_cs); if ( cs_mode != 0 && cs_mode != 1 && cs_mode != 2 ) { - OOFEM_WARNING("Unsupported value of cs_mode"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Truss2d_cs, "Unsupported mode"); } - - return NLStructuralElement :: initializeFrom(ir); } void -Truss2d :: giveDofManDofIDMask(int inode, IntArray &answer) const +Truss2d::giveDofManDofIDMask(int inode, IntArray &answer) const { if ( cs_mode == 0 ) { - answer = {D_u, D_w}; + answer = { D_u, D_w }; } else if ( cs_mode == 1 ) { - answer = {D_u, D_v}; + answer = { D_u, D_v }; } else if ( cs_mode == 2 ) { - answer = {D_v, D_w}; + answer = { D_v, D_w }; } } void -Truss2d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +Truss2d::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->giveRealStress_1d(strain, gp, tStep); +} + + +void +Truss2d::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveRealStress_1d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_1d(rMode, gp, tStep); } void -Truss2d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +Truss2d::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveStiffnessMatrix_1d(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_dPdF_1d(rMode, gp, tStep); } void -Truss2d :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +Truss2d::giveEdgeDofMapping(IntArray &answer, int iEdge) const { /* * provides dof mapping of local edge dofs (only nonzero are taken into account) @@ -346,7 +350,7 @@ Truss2d :: giveEdgeDofMapping(IntArray &answer, int iEdge) const } double -Truss2d :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +Truss2d::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { if ( iEdge != 1 ) { // edge between nodes 1 2 OOFEM_ERROR("wrong egde number"); @@ -357,7 +361,7 @@ Truss2d :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) } int -Truss2d :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +Truss2d::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -372,7 +376,7 @@ Truss2d :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussP answer.resize(2, 2); answer.zero(); - sine = sin( this->givePitch() ); + sine = sin(this->givePitch() ); cosine = cos(pitch); answer.at(1, 1) = cosine; @@ -384,28 +388,28 @@ Truss2d :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussP } -FEInterpolation *Truss2d :: giveInterpolation() const +FEInterpolation *Truss2d::giveInterpolation() const { // return interpolator - return & interp[cs_mode]; + return & interp [ cs_mode ]; } #ifdef __OOFEG -void Truss2d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +void Truss2d::drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { int c1, c2; resolveCoordIndices(c1, c2); GraphicObj *go; // if (!go) { // create new one - WCRec p [ 2 ]; /* point */ + WCRec p[ 2 ]; /* point */ if ( !gc.testElementGraphicActivity(this) ) { return; } EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); + EASValsSetColor(gc.getElementColor() ); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); if ( cs_mode == 0 ) { p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(c1); @@ -437,7 +441,7 @@ void Truss2d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } -void Truss2d :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +void Truss2d::drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) { int c1, c2; resolveCoordIndices(c1, c2); @@ -445,13 +449,13 @@ void Truss2d :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, U GraphicObj *go; double defScale = gc.getDefScale(); // if (!go) { // create new one - WCRec p [ 2 ]; /* point */ + WCRec p[ 2 ]; /* point */ if ( !gc.testElementGraphicActivity(this) ) { return; } EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); diff --git a/src/sm/Elements/Bars/truss2d.h b/src/sm/Elements/Bars/truss2d.h index da2693ec2..9f7d1c944 100644 --- a/src/sm/Elements/Bars/truss2d.h +++ b/src/sm/Elements/Bars/truss2d.h @@ -35,7 +35,7 @@ #ifndef truss2d_h #define truss2d_h -#include "Elements/nlstructuralelement.h" +#include "sm/Elements/nlstructuralelement.h" ///@name Input fields for 2D truss element //@{ @@ -64,60 +64,61 @@ class Truss2d : public NLStructuralElement double pitch; int cs_mode; // array for diffrent cs_modes - static FEI2dLineLin interp[3]; // only defined it so far... - + static FEI2dLineLin interp[ 3 ]; // only defined it so far... + public: - Truss2d(int n, Domain * d); + Truss2d(int n, Domain *d); virtual ~Truss2d() { } - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual int giveLocalCoordinateSystem(FloatMatrix &answer); + int giveLocalCoordinateSystem(FloatMatrix &answer) override; - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; - virtual int computeNumberOfDofs() { return 4; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + int computeNumberOfDofs() override { return 4; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; // characteristic length (for crack band approach) - virtual double giveCharacteristicLength(const FloatArray &) + double giveCharacteristicLength(const FloatArray &) override { return this->computeLength(); } - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Truss2d_Name; } - virtual const char *giveClassName() const { return "Truss2d"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_Truss2d_Name; } + const char *giveClassName() const override { return "Truss2d"; } + void initializeFrom(InputRecord &ir) override; ///@todo Introduce interpolator and remove these: - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual MaterialMode giveMaterialMode() { return _1dMat; } - virtual FEInterpolation *giveInterpolation() const; - + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + MaterialMode giveMaterialMode() override { return _1dMat; } + FEInterpolation *giveInterpolation() const override; + protected: // edge load support void resolveCoordIndices(int &c1, int &c2); - virtual void giveEdgeDofMapping(IntArray &answer, int) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &, int, GaussPoint *gp); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &, int = 1, int = ALL_STRAINS); - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &); - virtual void computeGaussPoints(); - - virtual double computeLength(); + void giveEdgeDofMapping(IntArray &answer, int) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &, int, GaussPoint *gp) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &) override; + void computeGaussPoints() override; + + double computeLength() override; double givePitch(); }; } // end namespace oofem diff --git a/src/sm/Elements/Bars/truss3d.C b/src/sm/Elements/Bars/truss3d.C index f60922110..f8a5f2cc3 100644 --- a/src/sm/Elements/Bars/truss3d.C +++ b/src/sm/Elements/Bars/truss3d.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Bars/truss3d.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/Bars/truss3d.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei3dlinelin.h" #include "node.h" #include "material.h" @@ -52,25 +52,25 @@ namespace oofem { REGISTER_Element(Truss3d); -FEI3dLineLin Truss3d :: interp; +FEI3dLineLin Truss3d::interp; -Truss3d :: Truss3d(int n, Domain *aDomain) : +Truss3d::Truss3d(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this) { numberOfDofMans = 2; } -FEInterpolation *Truss3d :: giveInterpolation() const { return & interp; } +FEInterpolation *Truss3d::giveInterpolation() const { return & interp; } Interface * -Truss3d :: giveInterface(InterfaceType interface) +Truss3d::giveInterface(InterfaceType interface) { if ( interface == ZZNodalRecoveryModelInterfaceType ) { - return static_cast< ZZNodalRecoveryModelInterface * >(this); + return static_cast< ZZNodalRecoveryModelInterface * >( this ); } else if ( interface == NodalAveragingRecoveryModelInterfaceType ) { - return static_cast< NodalAveragingRecoveryModelInterface * >(this); + return static_cast< NodalAveragingRecoveryModelInterface * >( this ); } //OOFEM_LOG_INFO("Interface on Truss3d element not supported"); @@ -79,7 +79,7 @@ Truss3d :: giveInterface(InterfaceType interface) void -Truss3d :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) +Truss3d::NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) { answer.clear(); OOFEM_WARNING("IP values will not be transferred to nodes. Use ZZNodalRecovery instead (parameter stype 1)"); @@ -87,14 +87,14 @@ Truss3d :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int no void -Truss3d :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +Truss3d::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // // Returns linear part of geometrical equations of the receiver at gp. // Returns the linear part of the B matrix // { FloatMatrix dN; - this->interp.evaldNdx( dN, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interp.evaldNdx(dN, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.resize(1, 6); answer.at(1, 1) = dN.at(1, 1); @@ -107,26 +107,33 @@ Truss3d :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) void -Truss3d :: computeGaussPoints() +Truss3d::computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) +{ + this->computeBmatrixAt(gp, answer); +} + + +void +Truss3d::computeGaussPoints() // Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } } double -Truss3d :: computeLength() +Truss3d::computeLength() { - return this->interp.giveLength( FEIElementGeometryWrapper(this) ); + return this->interp.giveLength(FEIElementGeometryWrapper(this) ); } void -Truss3d :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +Truss3d::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. This expression is // valid in both local and global axes. { @@ -149,29 +156,29 @@ Truss3d :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) void -Truss3d :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +Truss3d::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the displacement interpolation matrix {N} of the receiver, eva- // luated at gp. { FloatArray n; - this->interp.evalN( n, iLocCoord, FEIElementGeometryWrapper(this) ); + this->interp.evalN(n, iLocCoord, FEIElementGeometryWrapper(this) ); answer.beNMatrixOf(n, 3); } double -Truss3d :: computeVolumeAround(GaussPoint *gp) +Truss3d::computeVolumeAround(GaussPoint *gp) // Returns the length of the receiver. This method is valid only if 1 // Gauss point is used. { - double detJ = this->interp.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + double detJ = this->interp.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); double weight = gp->giveWeight(); - return detJ *weight *this->giveCrossSection()->give(CS_Area, gp); + return detJ * weight * this->giveCrossSection()->give(CS_Area, gp); } int -Truss3d :: giveLocalCoordinateSystem(FloatMatrix &answer) +Truss3d::giveLocalCoordinateSystem(FloatMatrix &answer) // // returns a unit vectors of local coordinate system at element // stored rowwise (mainly used by some materials with ortho and anisotrophy) @@ -179,7 +186,7 @@ Truss3d :: giveLocalCoordinateSystem(FloatMatrix &answer) { FloatArray lx, ly(3), lz; - lx.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); + lx.beDifferenceOf(this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); lx.normalize(); ly(0) = lx(1); @@ -203,34 +210,40 @@ Truss3d :: giveLocalCoordinateSystem(FloatMatrix &answer) } -IRResultType -Truss3d :: initializeFrom(InputRecord *ir) +void +Truss3d::initializeFrom(InputRecord &ir) { - return NLStructuralElement :: initializeFrom(ir); + NLStructuralElement::initializeFrom(ir); } void -Truss3d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +Truss3d::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->giveRealStress_1d(strain, gp, tStep); +} + +void +Truss3d::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveRealStress_1d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_1d(rMode, gp, tStep); } void -Truss3d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +Truss3d::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveStiffnessMatrix_1d(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_dPdF_1d(rMode, gp, tStep); } void -Truss3d :: giveDofManDofIDMask(int inode, IntArray &answer) const +Truss3d::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u, D_v, D_w}; + answer = { D_u, D_v, D_w }; } void -Truss3d :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +Truss3d::giveEdgeDofMapping(IntArray &answer, int iEdge) const { /* * provides dof mapping of local edge dofs (only nonzero are taken into account) @@ -252,19 +265,19 @@ Truss3d :: giveEdgeDofMapping(IntArray &answer, int iEdge) const double -Truss3d :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +Truss3d::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { if ( iEdge != 1 ) { // edge between nodes 1 2 OOFEM_ERROR("wrong edge number"); } double weight = gp->giveWeight(); - return this->interp.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) * weight; + return this->interp.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) * weight; } int -Truss3d :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +Truss3d::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -282,17 +295,17 @@ Truss3d :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussP #ifdef __OOFEG -void Truss3d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +void Truss3d::drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { GraphicObj *go; // if (!go) { // create new one - WCRec p [ 2 ]; /* point */ + WCRec p[ 2 ]; /* point */ if ( !gc.testElementGraphicActivity(this) ) { return; } EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); + EASValsSetColor(gc.getElementColor() ); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); @@ -307,18 +320,18 @@ void Truss3d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } -void Truss3d :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +void Truss3d::drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) { GraphicObj *go; double defScale = gc.getDefScale(); // if (!go) { // create new one - WCRec p [ 2 ]; /* point */ + WCRec p[ 2 ]; /* point */ if ( !gc.testElementGraphicActivity(this) ) { return; } EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(2, tStep, defScale); diff --git a/src/sm/Elements/Bars/truss3d.h b/src/sm/Elements/Bars/truss3d.h index aea0df83e..496dcf47d 100644 --- a/src/sm/Elements/Bars/truss3d.h +++ b/src/sm/Elements/Bars/truss3d.h @@ -35,8 +35,8 @@ #ifndef truss3d_h #define truss3d_h -#include "../sm/Elements/nlstructuralelement.h" -#include "../sm/ErrorEstimators/directerrorindicatorrc.h" +#include "sm/Elements/nlstructuralelement.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" @@ -50,63 +50,64 @@ class FEI3dLineLin; * analysis. */ class Truss3d : public NLStructuralElement, -public ZZNodalRecoveryModelInterface, -public NodalAveragingRecoveryModelInterface + public ZZNodalRecoveryModelInterface, + public NodalAveragingRecoveryModelInterface { protected: static FEI3dLineLin interp; public: - Truss3d(int n, Domain * d); + Truss3d(int n, Domain *d); virtual ~Truss3d() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual double computeLength(); + double computeLength() override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { this->computeLumpedMassMatrix(answer, tStep); } - virtual int giveLocalCoordinateSystem(FloatMatrix &answer); + int giveLocalCoordinateSystem(FloatMatrix &answer) override; - virtual int computeNumberOfDofs() { return 6; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 6; } + void giveDofManDofIDMask(int inode, IntArray &) const override; // characteristic length (for crack band approach) - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane) + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override { return this->computeLength(); } - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual int testElementExtension(ElementExtension ext) { return ( ext == Element_EdgeLoadSupport ); } + int testElementExtension(ElementExtension ext) override { return ( ext == Element_EdgeLoadSupport ); } - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Truss3d_Name; } - virtual const char *giveClassName() const { return "Truss3d"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode() { return _1dMat; } - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + const char *giveInputRecordName() const override { return _IFT_Truss3d_Name; } + const char *giveClassName() const override { return "Truss3d"; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _1dMat; } + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; protected: // edge load support - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *gp); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeGaussPoints(); - + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *gp) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeGaussPoints() override; }; } // end namespace oofem #endif // truss3d_h diff --git a/src/sm/Elements/Bars/truss3dnl.C b/src/sm/Elements/Bars/truss3dnl.C new file mode 100644 index 000000000..fc3c7f4a2 --- /dev/null +++ b/src/sm/Elements/Bars/truss3dnl.C @@ -0,0 +1,275 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "../sm/Elements/Bars/truss3dnl.h" +#include "../sm/CrossSections/structuralcrosssection.h" +#include "../sm/Materials/structuralms.h" +#include "fei3dlinelin.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_Element(Truss3dnl); + +Truss3dnl :: Truss3dnl(int n, Domain *aDomain) : Truss3d(n, aDomain) +{ +} + + +void +Truss3dnl :: initializeFrom(InputRecord &ir) +{ + Truss3d :: initializeFrom(ir); + initialStretch = 1; + IR_GIVE_OPTIONAL_FIELD(ir, initialStretch, _IFT_Truss3dnl_initialStretch); +} + + +void +Truss3dnl :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + FloatMatrix B, Be; + FloatArray vStress, vStrain, u; + + // This function can be quite costly to do inside the loops when one has many slave dofs. + this->computeVectorOf(VM_Total, tStep, u); + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + // zero answer will resize accordingly when adding first contribution + answer.clear(); + + for ( auto &gp: *this->giveDefaultIntegrationRulePtr() ) { + StructuralMaterialStatus *matStat = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); + this->computeBmatrixAt(gp, B, tStep, true); + this->computeBmatrixAt(gp, Be, tStep); + if ( useUpdatedGpRecord == 1 ) { + vStress = matStat->giveStressVector(); + } else { + ///@todo Is this really what we should do for inactive elements? + if ( !this->isActivated(tStep) ) { + vStrain.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + vStrain.zero(); + } + vStrain.beProductOf(Be, u); + // add influence of initial stress/stretch + double l2 = initialStretch*initialStretch; + vStrain.times(l2); + FloatArray E0(1); + E0.at(1) = (l2-1.)/2.; + vStrain.add(E0); + // + this->computeStressVector(vStress, vStrain, gp, tStep); + } + + if ( vStress.giveSize() == 0 ) { /// @todo is this check really necessary? + break; + } + + // Compute nodal internal forces at nodes as f = B^T*Stress dV + double dV = this->computeVolumeAround(gp); + + if ( vStress.giveSize() == 6 ) { + // It may happen that e.g. plane strain is computed + // using the default 3D implementation. If so, + // the stress needs to be reduced. + // (Note that no reduction will take place if + // the simulation is actually 3D.) + FloatArray stressTemp; + StructuralMaterial :: giveReducedSymVectorForm( stressTemp, vStress, gp->giveMaterialMode() ); + answer.plusProduct(B, stressTemp, dV); + } else { + answer.plusProduct(B, vStress, dV); + } + + + // If inactive: update fields but do not give any contribution to the internal forces + if ( !this->isActivated(tStep) ) { + answer.zero(); + return; + } + } +} + + + + +void +Truss3dnl :: computeStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, TimeStep *tStep) +{ + StructuralCrossSection *cs = this->giveStructuralCrossSection(); + bool matStiffSymmFlag = cs->isCharacteristicMtrxSymmetric(rMode); + + answer.clear(); + + if ( !this->isActivated(tStep) ) { + return; + } + + // Compute matrix from material stiffness (total stiffness for small def.) - B^T * dS/dE * B + if ( integrationRulesArray.size() == 1 ) { + FloatMatrix B, D, DB, Ksigma; + for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { + this->computeBmatrixAt(gp, B, tStep, true); + this->computeConstitutiveMatrixAt(D, rMode, gp, tStep); + double dV = this->computeVolumeAround(gp); + DB.beProductOf(D, B); + if ( matStiffSymmFlag ) { + answer.plusProductSymmUpper(B, DB, dV); + } else { + answer.plusProductUnsym(B, DB, dV); + } + this->computeInitialStressStiffness(Ksigma, rMode, gp, tStep); + Ksigma.times(dV); + answer.add(Ksigma); + + } + + if ( matStiffSymmFlag ) { + answer.symmetrized(); + } + } +} + + +void +Truss3dnl :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, TimeStep *tStep, bool lin) +{ + FloatMatrix Bl, Bnl; + this->computeBlMatrixAt(gp, Bl); + this->computeBnlMatrixAt(gp, Bnl, tStep, lin); + answer = Bl; + answer.add(Bnl); +} + + + +void +Truss3dnl :: computeBlMatrixAt(GaussPoint *gp, FloatMatrix &answer) +// +// Returns linear part of geometrical equations of the receiver at gp. +// Returns the linear part of the B matrix +// +{ + Truss3d::computeBmatrixAt(gp, answer); +} + + + +void +Truss3dnl :: computeBnlMatrixAt(GaussPoint *gp, FloatMatrix &answer, TimeStep *tStep, bool lin) +// +// Returns linear part of geometrical equations of the receiver at gp. +// Returns the linear part of the B matrix +// +{ + FloatArray d; + this->computeVectorOf(VM_Total, tStep, d); + + FloatMatrix Bnl, A(6,6); + A.at(1,1) = A.at(2,2) = A.at(3,3) = A.at(4,4) = A.at(5,5) = A.at(6,6) = 1.0; + A.at(1,4) = A.at(2,5) = A.at(3,6) = A.at(4,1) = A.at(5,2) = A.at(6,3) = -1.0; + double l0 = this->computeLength(); + double factor = 1/l0/l0; + if(!lin) { + factor /= 2; + } + Bnl.beProductOf(A,d); + Bnl.times(factor); + answer.beTranspositionOf(Bnl); + +} + + +void +Truss3dnl :: computeInitialStressStiffness(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer.resize(6,6); + answer.at(1,1) = answer.at(2,2) = answer.at(3,3) = answer.at(4,4) = answer.at(5,5) = answer.at(6,6) = 1.0; + answer.at(1,4) = answer.at(2,5) = answer.at(3,6) = answer.at(4,1) = answer.at(5,2) = answer.at(6,3) = -1.0; + + FloatArray d, strain; + FloatMatrix B; + this->computeVectorOf(VM_Total, tStep, d); + this->computeBmatrixAt(gp, B, tStep); + strain.beProductOf(B, d); + // add influence of initial stress/stretch + double l2 = initialStretch*initialStretch; + strain.times(l2); + FloatArray E0(1); + E0.at(1) = (l2-1.)/2; + strain.add(E0); + ///////////////////////////////////////////////////////////////////////////////////////// + auto stress = this->giveStructuralCrossSection()->giveRealStress_1d(strain, gp, tStep); + double l0 = this->computeLength(); + double factor = 1/l0/l0; + // prevent zero initial stress stiffness + if ( stress.at(1) == 0 ) { + FloatMatrix D; + this->computeConstitutiveMatrixAt(D, rMode, gp, tStep); + stress.at(1) = D.at(1,1) * 1.e-8; + } + answer.times(stress.at(1)); + answer.times(factor); +} + + +void +Truss3dnl :: computeGaussPoints() +// Sets up the array of Gauss Points of the receiver. +{ + if ( integrationRulesArray.size() == 0 ) { + integrationRulesArray.resize( 1 ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); + this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); + } +} + + + + + +} // end namespace oofem + diff --git a/src/sm/Elements/Bars/truss3dnl.h b/src/sm/Elements/Bars/truss3dnl.h new file mode 100644 index 000000000..c6b80f4fe --- /dev/null +++ b/src/sm/Elements/Bars/truss3dnl.h @@ -0,0 +1,78 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef truss3dnl_h +#define truss3dnl_h + +#include "../sm/Elements/Bars/truss3d.h" + +#define _IFT_Truss3dnl_Name "truss3dnl" + + +#define _IFT_Truss3dnl_initialStretch "initstretch" + +namespace oofem { +/** + * This class implements a nonlinear two-node truss bar element for three-dimensional + * analysis. + */ +class Truss3dnl : public Truss3d +{ +protected: + double initialStretch; + +public: + Truss3dnl(int n, Domain * d); + virtual ~Truss3dnl() { } + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_Truss3dnl_Name; } + const char *giveClassName() const override { return "Truss3dnl"; } + + void initializeFrom(InputRecord &ir) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + +protected: + + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, TimeStep *tStep, bool lin = false); + void computeBlMatrixAt(GaussPoint *gp, FloatMatrix &answer); + void computeBnlMatrixAt(GaussPoint *gp, FloatMatrix &answer, TimeStep *tStep, bool lin = false); + void computeInitialStressStiffness(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeGaussPoints() override; + + +}; +} // end namespace oofem +#endif // truss3dnl_h diff --git a/src/sm/Elements/Bars/truss3dnl2.C b/src/sm/Elements/Bars/truss3dnl2.C new file mode 100644 index 000000000..61ab2e0f1 --- /dev/null +++ b/src/sm/Elements/Bars/truss3dnl2.C @@ -0,0 +1,301 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "../sm/Elements/Bars/truss3dnl2.h" +#include "../sm/CrossSections/structuralcrosssection.h" +#include "../sm/Materials/structuralms.h" +#include "fei3dlinelin.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_Element(Truss3dnl2); + +Truss3dnl2 :: Truss3dnl2(int n, Domain *aDomain) : Truss3d(n, aDomain) +{ + cellGeometryWrapper = NULL; +} + + +void +Truss3dnl2 :: initializeFrom(InputRecord &ir) +{ + Truss3d :: initializeFrom(ir); + X = this-> giveCellGeometryWrapper()->giveVertexCoordinates( 1 ); + X.append(this-> giveCellGeometryWrapper()->giveVertexCoordinates( 2 )); + L = this->computeLength(); +} + + +void +Truss3dnl2 :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + FloatMatrix B, Be; + FloatArray vStress, vStrain, u; + + // This function can be quite costly to do inside the loops when one has many slave dofs. + this->computeVectorOf(VM_Total, tStep, u); + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + // zero answer will resize accordingly when adding first contribution + answer.clear(); + for ( auto &gp: *this->giveDefaultIntegrationRulePtr() ) { + StructuralMaterialStatus *matStat = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); + this->computeBmatrixAt(gp, B, tStep, u); + if ( useUpdatedGpRecord == 1 ) { + vStress = matStat->givePVector(); + } else { + ///@todo Is this really what we should do for inactive elements? + if ( !this->isActivated(tStep) ) { + vStrain.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + vStrain.zero(); + } + // compute strain tensor, i.e., Biot strain + auto vStrain = this->computeStrainVector(gp, u); + // compute stress tensor, i.e., firt Piola-Kirchhoff + vStress = this->giveStructuralCrossSection()->giveFirstPKStresses(vStrain, gp, tStep); + } + + if ( vStress.giveSize() == 0 ) { /// @todo is this check really necessary? + break; + } + + // Compute nodal internal forces at nodes as f = B^T*Stress dV + double dV = this->computeVolumeAround(gp); + + if ( vStress.giveSize() == 6 ) { + // It may happen that e.g. plane strain is computed + // using the default 3D implementation. If so, + // the stress needs to be reduced. + // (Note that no reduction will take place if + // the simulation is actually 3D.) + FloatArray stressTemp; + StructuralMaterial :: giveReducedSymVectorForm( stressTemp, vStress, gp->giveMaterialMode() ); + answer.plusProduct(B, stressTemp, dV); + } else { + answer.plusProduct(B, vStress, dV); + } + + + // If inactive: update fields but do not give any contribution to the internal forces + if ( !this->isActivated(tStep) ) { + answer.zero(); + return; + } + } +} + + +double +Truss3dnl2 :: computeLength() +{ + FloatArray X12; + X12.beProductOf(this->givePmatrix(), X); + return X12.computeNorm(); +} + +double +Truss3dnl2 :: computeDeformedLength(const FloatArray &d) +{ + FloatArray x12, x(X); + x.add(d); + x12.beProductOf(this->givePmatrix(), x); + return x12.computeNorm(); +} + + + + + +FloatArray +Truss3dnl2 :: computeStrainVector(GaussPoint *gp, const FloatArray &d) +{ + FloatArray answer(1); + auto l = this->computeDeformedLength(d); + answer.at(1) = l/this->computeLength(); + return answer; +} + + +void +Truss3dnl2 :: computeStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, TimeStep *tStep) +{ + StructuralCrossSection *cs = this->giveStructuralCrossSection(); + bool matStiffSymmFlag = cs->isCharacteristicMtrxSymmetric(rMode); + + answer.clear(); + + if ( !this->isActivated(tStep) ) { + return; + } + FloatArray u; + this->computeVectorOf(VM_Total, tStep, u); + + // Compute matrix from material stiffness (total stiffness for small def.) - B^T * dS/dE * B + if ( integrationRulesArray.size() == 1 ) { + FloatMatrix B, D, DB, Ksigma; + for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { + this->computeBmatrixAt(gp, B, tStep, u); + this->computeConstitutiveMatrixAt(D, rMode, gp, tStep); + double dV = this->computeVolumeAround(gp); + DB.beProductOf(D, B); + if ( matStiffSymmFlag ) { + answer.plusProductSymmUpper(B, DB, dV); + } else { + answer.plusProductUnsym(B, DB, dV); + } + + this->computeInitialStressStiffness(Ksigma, rMode, gp, tStep,B,u); + Ksigma.times(dV); + answer.add(Ksigma); + } + + if ( matStiffSymmFlag ) { + answer.symmetrized(); + } + } +} + + +void +Truss3dnl2 :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_dPdF_1d(rMode, gp, tStep); +} + + + +void +Truss3dnl2 :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, TimeStep *tStep, const FloatArray &d) +{ + double L = computeLength(); + double l = computeDeformedLength(d); + FloatMatrixF<6,6> A = this->giveAmatrix(); + FloatArray x(X); + x.add(d); + answer.beTProductOf(x,A); + answer.times(1./l/L); +} + + +FloatMatrixF<6,6> +Truss3dnl2 :: giveAmatrix() +{ + FloatMatrix A; + A = {{1, 0, 0, -1, 0, 0}, {0, 1, 0, 0, -1, 0}, {0, 0, 1, 0, 0, -1}, {-1, 0, 0, 1, 0, 0}, {0, -1, 0, 0, 1, 0}, {0, 0, -1, 0, 0, 1}}; + return A; +} + +FloatMatrixF<3,6> +Truss3dnl2 :: givePmatrix() +{ + FloatMatrix P; + P = {{1,0,0},{0,1,0},{0,0,1},{-1,0,0},{0,-1,0},{0,0,-1}}; + return P; +} + + + + + +void +Truss3dnl2 :: computeInitialStressStiffness(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep, const FloatMatrix &B, const FloatArray &d) +// +{ + + FloatMatrix BB, A = this->giveAmatrix(); + double L = computeLength(); + double l = computeDeformedLength(d); + FloatArray x(X); + FloatMatrix xx, Axx, AxxA; + x.add(d); + + xx.beProductTOf(x,x); + Axx.beProductOf(A,xx); + AxxA.beProductOf(Axx,A); + AxxA.times(1./l/l); + + answer = A; + answer.subtract(AxxA); + answer.times(1./l/L); + auto stress = this->giveStructuralCrossSection()->giveFirstPKStresses(this->computeStrainVector(gp, d), gp, tStep); + + // prevent zero initial stress stiffness + if ( stress.at(1) == 0 ) { + FloatMatrix D; + this->computeConstitutiveMatrixAt(D, rMode, gp, tStep); + stress.at(1) = D.at(1,1) * initStressFactor; + + } + answer.times(stress.at(1)); +} + + + +void +Truss3dnl2 :: computeGaussPoints() +// Sets up the array of Gauss Points of the receiver. +{ + if ( integrationRulesArray.size() == 0 ) { + integrationRulesArray.resize( 1 ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); + this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); + } +} + + +FEICellGeometry * +Truss3dnl2 :: giveCellGeometryWrapper() +{ + if ( !cellGeometryWrapper ) { + cellGeometryWrapper = new FEIElementGeometryWrapper(this); + } + + return cellGeometryWrapper; +} + +} // end namespace oofem + diff --git a/src/sm/Elements/Bars/truss3dnl2.h b/src/sm/Elements/Bars/truss3dnl2.h new file mode 100644 index 000000000..ef9b5f9d1 --- /dev/null +++ b/src/sm/Elements/Bars/truss3dnl2.h @@ -0,0 +1,94 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef truss3dnl2_h +#define truss3dnl2_h + +#include "../sm/Elements/Bars/truss3d.h" +#include "fei3dlinelin.h" + +#define _IFT_Truss3dnl2_Name "truss3dnl2" + + +namespace oofem { +/** + * This class implements a nonlinear two-node truss bar element for three-dimensional + * analysis. + */ +class Truss3dnl2 : public Truss3d +{ +protected: + FEICellGeometry* cellGeometryWrapper; + // vector of reference coordinates; + FloatArray X; + // undeformed length + double L; + // init stress factor + double initStressFactor = 0; + + +public: + Truss3dnl2(int n, Domain * d); + virtual ~Truss3dnl2() { } + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_Truss3dnl2_Name; } + const char *giveClassName() const override { return "Truss3dnl2"; } + + void initializeFrom(InputRecord &ir) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + + +protected: + FloatArray computeStrainVector(GaussPoint *gp, const FloatArray &u); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, TimeStep *tStep, const FloatArray &u); + void computeInitialStressStiffness(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep, const FloatMatrix &B, const FloatArray &d); + + std::pair computeDeformedLengthAt(GaussPoint *gp, const FloatArray &d); + virtual FEICellGeometry* giveCellGeometryWrapper(); + + void computeGaussPoints() override; + + + double computeLength() override; + double computeDeformedLength(const FloatArray &d); + FloatMatrixF<6,6> giveAmatrix(); + FloatMatrixF<3,6> givePmatrix(); + +}; +} // end namespace oofem +#endif // truss3dnl_h diff --git a/src/sm/Elements/Beams/beam2d.C b/src/sm/Elements/Beams/beam2d.C index 0028a4e15..550044cd6 100644 --- a/src/sm/Elements/Beams/beam2d.C +++ b/src/sm/Elements/Beams/beam2d.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Beams/beam2d.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/Beams/beam2d.h" +#include "sm/Materials/structuralms.h" #include "fei2dlinelin.h" #include "fei2dlinehermite.h" #include "node.h" @@ -132,7 +132,7 @@ Beam2d :: computeGaussPoints() // the gauss point is used only when methods from crosssection and/or material // classes are requested integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std :: make_unique< GaussIntegrationRule >(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], this->numberOfGaussPoints, this); } } @@ -192,14 +192,14 @@ Beam2d :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, Tim void Beam2d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give2dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give2dBeamStiffMtrx(rMode, gp, tStep); } void Beam2d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Beam2d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Beam2d(strain, gp, tStep); } @@ -377,19 +377,17 @@ Beam2d :: giveLocalCoordinateSystem(FloatMatrix &answer) } -IRResultType -Beam2d :: initializeFrom(InputRecord *ir) +void +Beam2d :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro // first call parent BeamBaseElement :: initializeFrom(ir); - if ( ir->hasField(_IFT_Beam2d_dofstocondense) ) { + if ( ir.hasField(_IFT_Beam2d_dofstocondense) ) { IntArray val; IR_GIVE_FIELD(ir, val, _IFT_Beam2d_dofstocondense); if ( val.giveSize() >= 6 ) { - OOFEM_WARNING("wrong input data for condensed dofs"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Beam2d_dofstocondense, "wrong input data for condensed dofs"); } DofIDItem mask[] = { @@ -409,9 +407,7 @@ Beam2d :: initializeFrom(InputRecord *ir) ghostNodes [ 1 ]->appendDof( new MasterDof(ghostNodes [ 1 ], mask [ val.at(i) - 4 ]) ); } } - } - return IRRT_OK; } @@ -436,7 +432,6 @@ Beam2d :: giveEndForcesVector(FloatArray &answer, TimeStep *tStep) if ( load.isNotEmpty() ) { answer.subtract(load); } - } @@ -461,11 +456,11 @@ Beam2d :: computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->computeNmatrixAt(lcoords, N); - if ( load ) { + if ( load->giveFormulationType() == Load :: FT_Entity ) { + load->computeValues(t, tStep, lcoords, { D_u, D_w, R_v }, mode); + } else { this->computeGlobalCoordinates(coords, lcoords); load->computeValues(t, tStep, coords, { D_u, D_w, R_v }, mode); - } else { - load->computeValues(t, tStep, lcoords, { D_u, D_w, R_v }, mode); } if ( load->giveCoordSystMode() == Load :: CST_Global ) { @@ -478,10 +473,10 @@ Beam2d :: computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, answer.plusProduct(N, t, dl); } - if (global) { - // Loads from sets expects global c.s. - this->computeGtoLRotationMatrix(T); - answer.rotatedWith(T, 't'); + if ( global ) { + // Loads from sets expects global c.s. + this->computeGtoLRotationMatrix(T); + answer.rotatedWith(T, 't'); } } @@ -504,12 +499,12 @@ Beam2d :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type } else if ( type == IST_BeamStrainCurvatureTensor ) { answer = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); return 1; - } else if ( type == IST_ShellForceTensor || type == IST_ShellStrainTensor ) { + } else if ( type == IST_ShellForceTensor || type == IST_ShellStrainTensor ) { // Order in generalized strain is: // {\eps_x, \gamma_xz, \kappa_y} - const FloatArray &help = type == IST_ShellForceTensor ? - static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector() : - static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); + const FloatArray &help = type == IST_ShellForceTensor ? + static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector() : + static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); answer.resize(6); answer.at(1) = help.at(1); // nx @@ -520,9 +515,9 @@ Beam2d :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type answer.at(6) = 0.0; // vxy return 1; } else if ( type == IST_ShellMomentTensor || type == IST_CurvatureTensor ) { - const FloatArray &help = type == IST_ShellMomentTensor ? - static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector() : - static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); + const FloatArray &help = type == IST_ShellMomentTensor ? + static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector() : + static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); answer.resize(6); answer.at(1) = 0.0; // mx answer.at(2) = 0.0; // my @@ -542,7 +537,7 @@ Beam2d :: printOutputAt(FILE *File, TimeStep *tStep) { FloatArray rl, Fl; - fprintf(File, "beam element %d (%8d) :\n", this->giveLabel(), this->giveNumber() ); + fprintf( File, "beam element %d (%8d) :\n", this->giveLabel(), this->giveNumber() ); // ask for global element displacement vector this->computeVectorOf(VM_Total, tStep, rl); @@ -660,6 +655,32 @@ Beam2d :: computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) //answer.beLumpedOf (mass); } +void +Beam2d :: computeLumpedInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + // computes initial stress matrix of receiver (or geometric stiffness matrix) + + FloatMatrix stiff; + FloatArray endForces; + + double l = this->computeLength(); + double N; + + answer.resize(6, 6); + answer.zero(); + + answer.at(2, 2) = 1.; + answer.at(2, 5) =-1.; + answer.at(5, 2) =-1.; + answer.at(5, 5) = 1.; + + // ask end forces in g.c.s + this->giveEndForcesVector(endForces, tStep); + N = ( -endForces.at(1) + endForces.at(4) ) / 2.; + answer.times( N / l); +} + + #ifdef __OOFEG void Beam2d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) diff --git a/src/sm/Elements/Beams/beam2d.h b/src/sm/Elements/Beams/beam2d.h index d2e272773..df7252f85 100644 --- a/src/sm/Elements/Beams/beam2d.h +++ b/src/sm/Elements/Beams/beam2d.h @@ -35,8 +35,8 @@ #ifndef beam2d_h #define beam2d_h -#include "../sm/Elements/Beams/beambaseelement.h" -#include "../sm/CrossSections/layeredcrosssection.h" +#include "sm/Elements/Beams/beambaseelement.h" +#include "sm/CrossSections/layeredcrosssection.h" #include "dofmanager.h" ///@name Input fields for Beam2d @@ -80,25 +80,27 @@ class Beam2d : public BeamBaseElement, public LayeredCrossSectionInterface Beam2d(int n, Domain *aDomain); virtual ~Beam2d(); - virtual void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL); - virtual void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual int giveLocalCoordinateSystem(FloatMatrix &answer); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); - virtual void giveEndForcesVector(FloatArray &answer, TimeStep *tStep); + void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) override; + void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeLumpedInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override; - virtual int testElementExtension(ElementExtension ext) { return ( ext == Element_EdgeLoadSupport ); } + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + void giveEndForcesVector(FloatArray &answer, TimeStep *tStep); - virtual Interface *giveInterface(InterfaceType); + int testElementExtension(ElementExtension ext) override { return ( ext == Element_EdgeLoadSupport ); } - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const { return NULL; } + Interface *giveInterface(InterfaceType) override; - virtual int computeNumberOfDofs() { return 6; } - virtual int computeNumberOfGlobalDofs() { return 6 + this->numberOfCondensedDofs; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual int giveNumberOfInternalDofManagers() const { return ( ghostNodes [ 0 ] != NULL ) + ( ghostNodes [ 1 ] != NULL ); } - virtual DofManager *giveInternalDofManager(int i) const { + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override { return nullptr; } + + int computeNumberOfDofs() override { return 6; } + int computeNumberOfGlobalDofs() override { return 6 + this->numberOfCondensedDofs; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + int giveNumberOfInternalDofManagers() const override { return ( ghostNodes [ 0 ] != nullptr ) + ( ghostNodes [ 1 ] != nullptr ); } + DofManager *giveInternalDofManager(int i) const override { if ( i == 1 ) { if ( ghostNodes [ 0 ] ) { return ghostNodes [ 0 ]; } else { return ghostNodes [ 1 ]; } } else if ( i == 2 ) { // i==2 @@ -108,7 +110,7 @@ class Beam2d : public BeamBaseElement, public LayeredCrossSectionInterface return NULL; } } - virtual void giveInternalDofManDofIDMask(int i, IntArray &answer) const { + void giveInternalDofManDofIDMask(int i, IntArray &answer) const override { if ( i == 1 ) { if ( ghostNodes [ 0 ] ) { ghostNodes [ 0 ]->giveCompleteMasterDofIDArray(answer); @@ -122,49 +124,48 @@ class Beam2d : public BeamBaseElement, public LayeredCrossSectionInterface } } - virtual void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIds = NULL) { + void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIds = NULL) override { giveLocationArray (locationArray, s, dofIds); } - - virtual void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const IntArray &dofIDMask, const UnknownNumberingScheme &s, IntArray *dofIds = NULL) { + + void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const IntArray &dofIDMask, const UnknownNumberingScheme &s, IntArray *dofIds = NULL) override { giveLocationArray (locationArray, dofIDMask, s, dofIds); } - - virtual double computeVolumeAround(GaussPoint *gp); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + double computeVolumeAround(GaussPoint *gp) override; + void printOutputAt(FILE *file, TimeStep *tStep) override; - virtual const char *giveClassName() const { return "Beam2d"; } - virtual const char *giveInputRecordName() const { return _IFT_Beam2d_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "Beam2d"; } + const char *giveInputRecordName() const override { return _IFT_Beam2d_Name; } + void initializeFrom(InputRecord &ir) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext & gc, TimeStep * tStep, UnknownType); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext & gc, TimeStep * tStep, UnknownType) override; #endif - virtual void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep); + void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; protected: - virtual void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int edge, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true); - virtual void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &); - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int edge, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true) override; + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &) override; + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; - void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; double giveKappaCoeff(TimeStep *tStep); - virtual double computeLength(); + double computeLength() override; double givePitch(); - virtual void computeGaussPoints(); - virtual MaterialMode giveMaterialMode() { return _2dBeam; } - virtual int giveNumberOfIPForMassMtrxIntegration() { return 4; } + void computeGaussPoints() override; + MaterialMode giveMaterialMode() override { return _2dBeam; } + int giveNumberOfIPForMassMtrxIntegration() override { return 4; } bool hasDofs2Condense() { return ( ghostNodes [ 0 ] || ghostNodes [ 1 ] ); } }; diff --git a/src/sm/Elements/Beams/beam3d.C b/src/sm/Elements/Beams/beam3d.C index 07a168fbf..1b7864a45 100644 --- a/src/sm/Elements/Beams/beam3d.C +++ b/src/sm/Elements/Beams/beam3d.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Beams/beam3d.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/Beams/beam3d.h" +#include "sm/Materials/structuralms.h" #include "node.h" #include "material.h" #include "crosssection.h" @@ -74,6 +74,7 @@ Beam3d :: Beam3d(int n, Domain *aDomain) : BeamBaseElement(n, aDomain) ghostNodes [ 0 ] = ghostNodes [ 1 ] = NULL; numberOfCondensedDofs = 0; + subsoilMat = 0; } Beam3d :: ~Beam3d() @@ -105,14 +106,14 @@ Beam3d :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) answer.at(1, 7) = 1. / l; answer.at(2, 3) = ( -2. * kappay ) / ( l * c1y ); - answer.at(2, 5) = kappay / (c1y ); + answer.at(2, 5) = kappay / ( c1y ); answer.at(2, 9) = 2. * kappay / ( l * c1y ); - answer.at(2, 11) = kappay / (c1y ); + answer.at(2, 11) = kappay / ( c1y ); answer.at(3, 2) = ( -2. * kappaz ) / ( l * c1z ); - answer.at(3, 6) = -kappaz / (c1z ); + answer.at(3, 6) = -kappaz / ( c1z ); answer.at(3, 8) = 2. * kappaz / ( l * c1z ); - answer.at(3, 12) = -kappaz / (c1z ); + answer.at(3, 12) = -kappaz / ( c1z ); answer.at(4, 4) = -1. / l; @@ -123,9 +124,9 @@ Beam3d :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) answer.at(5, 9) = ( -6. + 12. * ksi ) / ( l * l * c1y ); answer.at(5, 11) = ( -2. * ( 1. - kappay ) + 6. * ksi ) / ( l * c1y ); - answer.at(6, 2) = -1.0*( 6. - 12. * ksi ) / ( l * l * c1z ); + answer.at(6, 2) = -1.0 * ( 6. - 12. * ksi ) / ( l * l * c1z ); answer.at(6, 6) = ( -2. * ( 2. + kappaz ) + 6. * ksi ) / ( l * c1z ); - answer.at(6, 8) = -1.0*( -6. + 12. * ksi ) / ( l * l * c1z ); + answer.at(6, 8) = -1.0 * ( -6. + 12. * ksi ) / ( l * l * c1z ); answer.at(6, 12) = ( -2. * ( 1. - kappaz ) + 6. * ksi ) / ( l * c1z ); } @@ -135,8 +136,8 @@ void Beam3d :: computeGaussPoints() if ( integrationRulesArray.size() == 0 ) { // the gauss point is used only when methods from crosssection and/or material // classes are requested - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std :: make_unique< GaussIntegrationRule >(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], this->numberOfGaussPoints, this); } } @@ -196,7 +197,7 @@ Beam3d :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, Tim double l = this->computeLength(); FloatMatrix B, DB, d; answer.clear(); - for ( auto &gp: *this->giveDefaultIntegrationRulePtr() ) { + for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { this->computeBmatrixAt(gp, B); this->computeConstitutiveMatrixAt(d, rMode, gp, tStep); double dV = gp->giveWeight() * 0.5 * l; @@ -205,10 +206,10 @@ Beam3d :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, Tim } answer.symmetrized(); - if (subsoilMat) { - FloatMatrix k; - this->computeSubSoilStiffnessMatrix(k, rMode, tStep); - answer.add(k); + if ( subsoilMat ) { + FloatMatrix k; + this->computeSubSoilStiffnessMatrix(k, rMode, tStep); + answer.add(k); } } @@ -230,14 +231,14 @@ Beam3d :: computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, FloatArray coords, t; FloatMatrix N, T; - for ( GaussPoint *gp: *this->giveDefaultIntegrationRulePtr() ) { + for ( GaussPoint *gp : *this->giveDefaultIntegrationRulePtr() ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->computeNmatrixAt(lcoords, N); - if ( load ) { - this->computeGlobalCoordinates(coords, lcoords); - load->computeValues(t, tStep, coords, {D_u, D_v, D_w, R_u, R_v, R_w}, mode); + if ( load->giveFormulationType() == Load :: FT_Entity ) { + load->computeValues(t, tStep, lcoords, { D_u, D_v, D_w, R_u, R_v, R_w }, mode); } else { - load->computeValues(t, tStep, lcoords, {D_u, D_v, D_w, R_u, R_v, R_w}, mode); + this->computeGlobalCoordinates(coords, lcoords); + load->computeValues(t, tStep, coords, { D_u, D_v, D_w, R_u, R_v, R_w }, mode); } if ( load->giveCoordSystMode() == Load :: CST_Global ) { @@ -250,10 +251,10 @@ Beam3d :: computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, answer.plusProduct(N, t, dl); } - if (global) { - // Loads from sets expects global c.s. - this->computeGtoLRotationMatrix(T); - answer.rotatedWith(T, 't'); + if ( global ) { + // Loads from sets expects global c.s. + this->computeGtoLRotationMatrix(T); + answer.rotatedWith(T, 't'); } } @@ -302,7 +303,7 @@ Beam3d :: computeGtoLRotationMatrix(FloatMatrix &answer) if ( this->hasDofs2Condense() ) { int condensedDofCounter = 0; DofIDItem dofids[] = { - D_u, D_v, D_w, R_u, R_v, R_w + D_u, D_v, D_w, R_u, R_v, R_w }; FloatMatrix l2p(12, ndofs); // local -> primary l2p.zero(); @@ -330,24 +331,23 @@ Beam3d :: computeGtoLRotationMatrix(FloatMatrix &answer) } - -void -Beam3d :: B3SSMI_getUnknownsGtoLRotationMatrix(FloatMatrix &answer) + +FloatMatrixF<6,6> +Beam3d :: B3SSMI_getUnknownsGtoLRotationMatrix() const // Returns the rotation matrix for element unknowns { FloatMatrix lcs; - - answer.resize(6, 6); - answer.zero(); - this->giveLocalCoordinateSystem(lcs); + FloatMatrixF<6,6> answer; + + const_cast(this)->giveLocalCoordinateSystem(lcs); for ( int i = 1; i <= 3; i++ ) { for ( int j = 1; j <= 3; j++ ) { answer.at(i, j) = lcs.at(i, j); answer.at(i + 3, j + 3) = lcs.at(i, j); } } - + return answer; } double @@ -366,12 +366,12 @@ Beam3d :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type } else if ( type == IST_BeamStrainCurvatureTensor ) { answer = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); return 1; - } else if ( type == IST_ShellForceTensor || type == IST_ShellStrainTensor ) { + } else if ( type == IST_ShellForceTensor || type == IST_ShellStrainTensor ) { // Order in generalized strain is: // {\eps_x, \gamma_xz, \gamma_xy, \der{phi_x}{x}, \kappa_y, \kappa_z} - const FloatArray &help = type == IST_ShellForceTensor ? - static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector() : - static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); + const FloatArray &help = type == IST_ShellForceTensor ? + static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector() : + static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); answer.resize(6); answer.at(1) = help.at(1); // nx @@ -382,9 +382,9 @@ Beam3d :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type answer.at(6) = help.at(3); // vxy return 1; } else if ( type == IST_ShellMomentTensor || type == IST_CurvatureTensor ) { - const FloatArray &help = type == IST_ShellMomentTensor ? - static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector() : - static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); + const FloatArray &help = type == IST_ShellMomentTensor ? + static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector() : + static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); answer.resize(6); answer.at(1) = help.at(4); // mx answer.at(2) = 0.0; // my @@ -486,12 +486,12 @@ Beam3d :: giveLocalCoordinateSystem(FloatMatrix &answer) nodeA = this->giveNode(1); nodeB = this->giveNode(2); - lx.beDifferenceOf(*nodeB->giveCoordinates(), *nodeA->giveCoordinates()); + lx.beDifferenceOf( nodeB->giveCoordinates(), nodeA->giveCoordinates() ); lx.normalize(); if ( this->referenceNode ) { Node *refNode = this->giveDomain()->giveNode(this->referenceNode); - help.beDifferenceOf(*refNode->giveCoordinates(), *nodeA->giveCoordinates()); + help.beDifferenceOf( refNode->giveCoordinates(), nodeA->giveCoordinates() ); lz.beVectorProductOf(lx, help); lz.normalize(); @@ -517,8 +517,10 @@ Beam3d :: giveLocalCoordinateSystem(FloatMatrix &answer) help.at(3) = 1.0; // up-vector // here is ly is used as a temp var - if ( fabs(lx.dotProduct(help)) > 0.999 ) { // Check if it is vertical - ly = {0., 1., 0.}; + if ( fabs( lx.dotProduct(help) ) > 0.999 ) { // Check if it is vertical + ly = { + 0., 1., 0. + }; } else { ly.beVectorProductOf(lx, help); } @@ -541,39 +543,37 @@ Beam3d :: giveLocalCoordinateSystem(FloatMatrix &answer) } -IRResultType -Beam3d :: initializeFrom(InputRecord *ir) +void +Beam3d :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + BeamBaseElement :: initializeFrom(ir); referenceNode = 0; referenceAngle = 0; this->zaxis.clear(); - if ( ir->hasField(_IFT_Beam3d_zaxis) ) { + if ( ir.hasField(_IFT_Beam3d_zaxis) ) { IR_GIVE_FIELD(ir, this->zaxis, _IFT_Beam3d_zaxis); - } else if ( ir->hasField(_IFT_Beam3d_refnode) ) { + } else if ( ir.hasField(_IFT_Beam3d_refnode) ) { IR_GIVE_FIELD(ir, referenceNode, _IFT_Beam3d_refnode); if ( referenceNode == 0 ) { OOFEM_WARNING("wrong reference node specified. Using default orientation."); } - } else if ( ir->hasField(_IFT_Beam3d_refangle) ) { + } else if ( ir.hasField(_IFT_Beam3d_refangle) ) { IR_GIVE_FIELD(ir, referenceAngle, _IFT_Beam3d_refangle); } else { - OOFEM_WARNING("y-axis, reference node or angle not set"); - return IRRT_NOTFOUND; + throw ValueInputException(ir, _IFT_Beam3d_zaxis, "axis, reference node, or angle not set"); } - if ( ir->hasField(_IFT_Beam3d_dofstocondense) ) { + if ( ir.hasField(_IFT_Beam3d_dofstocondense) ) { IntArray val; IR_GIVE_FIELD(ir, val, _IFT_Beam3d_dofstocondense); if ( val.giveSize() >= 12 ) { - OOFEM_WARNING("wrong input data for condensed dofs"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Beam3d_dofstocondense, "wrong input data for condensed dofs"); } //dofsToCondense = new IntArray(val); DofIDItem mask[] = { - D_u, D_v, D_w, R_u, R_v, R_w + D_u, D_v, D_w, R_u, R_v, R_w }; this->numberOfCondensedDofs = val.giveSize(); for ( int i = 1; i <= val.giveSize(); i++ ) { @@ -589,15 +589,12 @@ Beam3d :: initializeFrom(InputRecord *ir) ghostNodes [ 1 ]->appendDof( new MasterDof(ghostNodes [ 1 ], mask [ val.at(i) - 7 ]) ); } } - } else { - //dofsToCondense = NULL; + //dofsToCondense = NULL; } this->subsoilMat = 0; IR_GIVE_OPTIONAL_FIELD(ir, this->subsoilMat, _IFT_Beam3d_subsoilmat); - - return BeamBaseElement :: initializeFrom(ir); } @@ -613,15 +610,15 @@ Beam3d :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useU answer.beProductOf(stiffness, u); #else BeamBaseElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); - if (subsoilMat) { - // add internal forces due to subsoil interaction - // @todo: linear subsoil assumed here; more general approach should integrate internal forces - FloatMatrix k; - FloatArray u, F; - this->computeSubSoilStiffnessMatrix(k, TangentStiffness, tStep); - this->computeVectorOf(VM_Total, tStep, u); - F.beProductOf(k, u); - answer.add(F); + if ( subsoilMat ) { + // add internal forces due to subsoil interaction + // @todo: linear subsoil assumed here; more general approach should integrate internal forces + FloatMatrix k; + FloatArray u, F; + this->computeSubSoilStiffnessMatrix(k, TangentStiffness, tStep); + this->computeVectorOf(VM_Total, tStep, u); + F.beProductOf(k, u); + answer.add(F); } #endif } @@ -630,14 +627,14 @@ Beam3d :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useU void Beam3d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give3dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give3dBeamStiffMtrx(rMode, gp, tStep); } void Beam3d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Beam3d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Beam3d(strain, gp, tStep); } @@ -655,16 +652,16 @@ Beam3d :: giveEndForcesVector(FloatArray &answer, TimeStep *tStep) answer.subtract(loadEndForces); } /* - if (subsoilMat) { - // @todo: linear subsoil assumed here; more general approach should integrate internal forces - FloatMatrix k; - FloatArray u, F; - this->computeSubSoilStiffnessMatrix(k, TangentStiffness, tStep); - this->computeVectorOf(VM_Total, tStep, u); - F.beProductOf(k, u); - answer.add(F); - } - */ + * if (subsoilMat) { + * // @todo: linear subsoil assumed here; more general approach should integrate internal forces + * FloatMatrix k; + * FloatArray u, F; + * this->computeSubSoilStiffnessMatrix(k, TangentStiffness, tStep); + * this->computeVectorOf(VM_Total, tStep, u); + * F.beProductOf(k, u); + * answer.add(F); + * } + */ } @@ -673,7 +670,7 @@ Beam3d :: printOutputAt(FILE *File, TimeStep *tStep) { FloatArray rl, Fl; - fprintf(File, "beam element %d (%8d) :\n", this->giveLabel(), this->giveNumber() ); + fprintf( File, "beam element %d (%8d) :\n", this->giveLabel(), this->giveNumber() ); // ask for global element displacement vector this->computeVectorOf(VM_Total, tStep, rl); @@ -682,17 +679,17 @@ Beam3d :: printOutputAt(FILE *File, TimeStep *tStep) fprintf(File, " local displacements "); for ( auto &val : rl ) { - fprintf( File, " %.4e", val ); + fprintf(File, " %.4e", val); } fprintf(File, "\n local end forces "); for ( auto &val : Fl ) { - fprintf( File, " %.4e", val ); + fprintf(File, " %.4e", val); } fprintf(File, "\n"); - for ( auto &iRule: integrationRulesArray ) { + for ( auto &iRule : integrationRulesArray ) { iRule->printOutputAt(File, tStep); } } @@ -710,7 +707,17 @@ Beam3d :: computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tSte void Beam3d :: computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity) { - FloatMatrix stiff; + if (0) { + StructuralElement::computeConsistentMassMatrix(answer, tStep, mass, ipDensity); + GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + double area = this->giveCrossSection()->give(CS_Area, gp); // constant area assumed + answer.times(area); + mass *= area; + return; + } else { + + + FloatMatrix stiff; GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); /* @@ -730,6 +737,8 @@ Beam3d :: computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, doub } double area = this->giveCrossSection()->give(CS_Area, gp); // constant area assumed + double Ikk = this->giveCrossSection()->give(CS_InertiaMomentY, gp) + + this->giveCrossSection()->give(CS_InertiaMomentZ, gp); // polar moment of inertia double c2y = ( area * density ) / ( ( 1. + 2. * kappay ) * ( 1. + 2. * kappay ) ); double c2z = ( area * density ) / ( ( 1. + 2. * kappaz ) * ( 1. + 2. * kappaz ) ); double c1 = ( area * density ); @@ -740,32 +749,36 @@ Beam3d :: computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, doub answer.at(1, 1) = c1 * l / 3.0; answer.at(1, 7) = c1 * l / 6.0; answer.at(2, 2) = c2z * l * ( 13. / 35. + 7. * kappaz / 5. + 4. * kappaz2 / 3. ); - answer.at(2, 6) = -c2z * l * l * ( 11. / 210. + kappaz * 11. / 60. + kappaz2 / 6. ); + answer.at(2, 6) = c2z * l * l * ( 11. / 210. + kappaz * 11. / 60. + kappaz2 / 6. ); answer.at(2, 8) = c2z * l * ( 9. / 70. + kappaz * 3. / 5. + kappaz2 * 2. / 3. ); - answer.at(2, 12) = c2z * l * l * ( 13. / 420. + kappaz * 3. / 20. + kappaz2 / 6. ); + answer.at(2, 12) = -c2z * l * l * ( 13. / 420. + kappaz * 3. / 20. + kappaz2 / 6. ); answer.at(3, 3) = c2y * l * ( 13. / 35. + 7. * kappay / 5. + 4. * kappay2 / 3. ); answer.at(3, 5) = -c2y * l * l * ( 11. / 210. + kappay * 11. / 60. + kappay2 / 6. ); answer.at(3, 9) = c2y * l * ( 9. / 70. + kappay * 3. / 5. + kappay2 * 2. / 3. ); answer.at(3, 11) = c2y * l * l * ( 13. / 420. + kappay * 3. / 20. + kappay2 / 6. ); + answer.at(4,4) = Ikk*density*l/3.; + answer.at(4,10) = Ikk*density*l/6.; answer.at(5, 5) = c2y * l * l * l * ( 1. / 105. + kappay / 30. + kappay2 / 30. ); answer.at(5, 9) = -c2y * l * l * ( 13. / 420. + kappay * 3. / 20. + kappay2 / 6. ); answer.at(5, 11) = -c2y * l * l * l * ( 1. / 140. + kappay / 30. + kappay2 / 30. ); answer.at(6, 6) = c2z * l * l * l * ( 1. / 105. + kappaz / 30. + kappaz2 / 30. ); - answer.at(6, 8) = -c2z * l * l * ( 13. / 420. + kappaz * 3. / 20. + kappaz2 / 6. ); + answer.at(6, 8) = c2z * l * l * ( 13. / 420. + kappaz * 3. / 20. + kappaz2 / 6. ); answer.at(6, 12) = -c2z * l * l * l * ( 1. / 140. + kappaz / 30. + kappaz2 / 30. ); answer.at(7, 7) = c1 * l / 3.0; answer.at(8, 8) = c2z * l * ( 13. / 35. + kappaz * 7. / 5. + kappaz2 * 4. / 3. ); - answer.at(8, 12) = c2z * l * l * ( 11. / 210. + kappaz * 11. / 60. + kappaz2 / 6. ); + answer.at(8, 12) = -c2z * l * l * ( 11. / 210. + kappaz * 11. / 60. + kappaz2 / 6. ); answer.at(9, 9) = c2y * l * ( 13. / 35. + kappay * 7. / 5. + kappay2 * 4. / 3. ); answer.at(9, 11) = c2y * l * l * ( 11. / 210. + kappay * 11. / 60. + kappay2 / 6. ); + answer.at(10,10) = Ikk*density*l/3.; answer.at(11, 11) = c2y * l * l * l * ( 1. / 105. + kappay / 30. + kappay2 / 30. ); answer.at(12, 12) = c2z * l * l * l * ( 1. / 105. + kappaz / 30. + kappaz2 / 30. ); answer.symmetrized(); mass = area * l * density; + } } @@ -779,9 +792,9 @@ Beam3d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords n2 = ( 1. + ksi ) * 0.5; answer.resize(3); - answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 * this->giveNode(2)->giveCoordinate(1); - answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 * this->giveNode(2)->giveCoordinate(2); - answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 * this->giveNode(2)->giveCoordinate(3); + answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 *this->giveNode(2)->giveCoordinate(1); + answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 *this->giveNode(2)->giveCoordinate(2); + answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 *this->giveNode(2)->giveCoordinate(3); return 1; } @@ -859,6 +872,40 @@ Beam3d :: computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) } +void +Beam3d :: computeLumpedInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + // computes initial stress matrix of receiver (or geometric stiffness matrix) + + FloatMatrix stiff; + FloatArray endForces; + + double l = this->computeLength(); + double N; + + answer.resize(12, 12); + answer.zero(); + + answer.at(2, 2) = 1.; + answer.at(2, 8) =-1.; + answer.at(8, 2) =-1.; + answer.at(8, 8) = 1.; + + answer.at(3, 3) = 1.; + answer.at(3, 9) =-1.; + answer.at(9, 3) =-1.; + answer.at(9, 9) = 1.; + + + // ask end forces in g.c.s + // ask end forces in g.c.s + this->giveEndForcesVector(endForces, tStep); + N = ( -endForces.at(1) + endForces.at(7) ) / 2.; + answer.times(N / l); + +} + + void Beam3d :: FiberedCrossSectionInterface_computeStrainVectorInFiber(FloatArray &answer, const FloatArray &masterGpStrain, GaussPoint *slaveGp, TimeStep *tStep) @@ -871,8 +918,8 @@ Beam3d :: FiberedCrossSectionInterface_computeStrainVectorInFiber(FloatArray &an answer.resize(3); // {Exx,GMzx,GMxy} answer.at(1) = masterGpStrain.at(1) + masterGpStrain.at(5) * layerZCoord - masterGpStrain.at(6) * layerYCoord; - answer.at(2) = masterGpStrain.at(2); - answer.at(3) = masterGpStrain.at(3); + answer.at(2) = masterGpStrain.at(2) + layerYCoord * masterGpStrain.at(4); + answer.at(3) = masterGpStrain.at(3) - layerZCoord * masterGpStrain.at(4); } @@ -880,12 +927,12 @@ Interface * Beam3d :: giveInterface(InterfaceType interface) { if ( interface == FiberedCrossSectionInterfaceType ) { - return static_cast< FiberedCrossSectionInterface * >( this ); - } else if (interface == Beam3dSubsoilMaterialInterfaceType ) { - return static_cast< Beam3dSubsoilMaterialInterface * >( this ); - } else if (interface == VTKXMLExportModuleElementInterfaceType) { - return static_cast< VTKXMLExportModuleElementInterface * >( this ); - } + return static_cast< FiberedCrossSectionInterface * >(this); + } else if ( interface == Beam3dSubsoilMaterialInterfaceType ) { + return static_cast< Beam3dSubsoilMaterialInterface * >(this); + } else if ( interface == VTKXMLExportModuleElementInterfaceType ) { + return static_cast< VTKXMLExportModuleElementInterface * >(this); + } return NULL; } @@ -958,22 +1005,21 @@ void Beam3d :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Un void Beam3d :: computeSubSoilNMatrixAt(GaussPoint *gp, FloatMatrix &answer) { - // only winkler model supported now (passing only unknown interpolation) - this->computeNmatrixAt(gp->giveNaturalCoordinates(), answer); + // only winkler model supported now (passing only unknown interpolation) + this->computeNmatrixAt(gp->giveNaturalCoordinates(), answer); } void Beam3d :: computeSubSoilStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, TimeStep *tStep) + MatResponseMode rMode, TimeStep *tStep) { - - double l = this->computeLength(); - FloatMatrix N, DN, d; + double l = this->computeLength(); + FloatMatrix N, DN, d; answer.clear(); - for ( GaussPoint *gp: *this->giveDefaultIntegrationRulePtr() ) { + for ( GaussPoint *gp : *this->giveDefaultIntegrationRulePtr() ) { this->computeSubSoilNMatrixAt(gp, N); - ((StructuralMaterial*)this->domain->giveMaterial(subsoilMat))->give3dBeamSubSoilStiffMtrx(d, rMode, gp, tStep); + d = static_cast(this->domain->giveMaterial(subsoilMat))->give3dBeamSubSoilStiffMtrx(rMode, gp, tStep); double dV = gp->giveWeight() * 0.5 * l; DN.beProductOf(d, N); answer.plusProductSymmUpper(N, DN, dV); @@ -991,9 +1037,9 @@ Beam3d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords n2 = ( 1. + ksi ) * 0.5; answer.resize(3); - answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 * pCoords.at(1); - answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 * pCoords.at(2); - answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 * pCoords.at(3); + answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 *pCoords.at(1); + answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 *pCoords.at(2); + answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 *pCoords.at(3); return 1; } @@ -1001,24 +1047,25 @@ Beam3d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords void Beam3d :: giveInternalForcesVectorAtPoint(FloatArray &answer, TimeStep *tStep, FloatArray &coords) { - // computes exact global end-forces vector FloatArray loadEndForces, iF; - IntArray leftIndx = {1, 2 , 3, 4, 5 , 6}; + IntArray leftIndx = { + 1, 2, 3, 4, 5, 6 + }; this->giveEndForcesVector(iF, tStep); answer.beSubArrayOf(iF, leftIndx); Node *nodeA; - + nodeA = this->giveNode(1); double dx = nodeA->giveCoordinate(1) - coords.at(1); double dy = nodeA->giveCoordinate(2) - coords.at(2); double dz = nodeA->giveCoordinate(3) - coords.at(3); double ds = sqrt(dx * dx + dy * dy + dz * dz); - answer.at(5) += iF.at(3)*ds; - answer.at(6) -= iF.at(2)*ds; - + answer.at(5) += iF.at(3) * ds; + answer.at(6) -= iF.at(2) * ds; + // loop over body load array first @@ -1030,7 +1077,7 @@ Beam3d :: giveInternalForcesVectorAtPoint(FloatArray &answer, TimeStep *tStep, F Load *load = domain->giveLoad(id); bcGeomType ltype = load->giveBCGeoType(); if ( ( ltype == BodyLoadBGT ) && ( load->giveBCValType() == ForceLoadBVT ) ) { - this->computeInternalForcesFromBodyLoadVectorAtPoint(help,load, tStep, VM_Total, coords, ds); // this one is local + this->computeInternalForcesFromBodyLoadVectorAtPoint(help, load, tStep, VM_Total, coords, ds); // this one is local answer.add(help); } else { if ( load->giveBCValType() != TemperatureBVT && load->giveBCValType() != EigenstrainBVT ) { @@ -1046,18 +1093,17 @@ Beam3d :: giveInternalForcesVectorAtPoint(FloatArray &answer, TimeStep *tStep, F int n = boundaryLoadArray.at(1 + ( i - 1 ) * 2); int id = boundaryLoadArray.at(i * 2); Load *load = domain->giveLoad(n); - BoundaryLoad* bLoad; - if ((bLoad = dynamic_cast (load))) { - bcGeomType ltype = load->giveBCGeoType(); - if ( ltype == EdgeLoadBGT ) { - this->computeInternalForcesFromBoundaryEdgeLoadVectorAtPoint(help, bLoad, id, - ExternalForcesVector, VM_Total, tStep, coords, ds, false); - answer.add(help); - - } else { - OOFEM_ERROR("boundary load %d is of unsupported type (%d)", id, ltype); - } - } + BoundaryLoad *bLoad; + if ( ( bLoad = dynamic_cast< BoundaryLoad * >(load) ) ) { + bcGeomType ltype = load->giveBCGeoType(); + if ( ltype == EdgeLoadBGT ) { + this->computeInternalForcesFromBoundaryEdgeLoadVectorAtPoint(help, bLoad, id, + ExternalForcesVector, VM_Total, tStep, coords, ds, false); + answer.add(help); + } else { + OOFEM_ERROR("boundary load %d is of unsupported type (%d)", id, ltype); + } + } } // add exact end forces due to nonnodal loading // this->computeForceLoadVectorAt(loadEndForces, tStep, VM_Total, coords); // will compute only contribution of loads applied directly on receiver (not using sets) @@ -1067,44 +1113,43 @@ Beam3d :: giveInternalForcesVectorAtPoint(FloatArray &answer, TimeStep *tStep, F // add exact end forces due to nonnodal loading applied indirectly (via sets) BCTracker *bct = this->domain->giveBCTracker(); - BCTracker::entryListType bcList = bct->getElementRecords(this->number); - - for (BCTracker::entryListType::iterator it = bcList.begin(); it != bcList.end(); ++it) { - GeneralBoundaryCondition *bc = this->domain->giveBc((*it).bcNumber); - BodyLoad *bodyLoad; - BoundaryLoad *boundaryLoad; - if (bc->isImposed(tStep)) { - if ((bodyLoad = dynamic_cast(bc))) { // body load - this->computeInternalForcesFromBodyLoadVectorAtPoint(help,bodyLoad, tStep, VM_Total, coords, ds); // this one is local - //answer.subtract(help); - } else if ((boundaryLoad = dynamic_cast(bc))) { - // compute Boundary Edge load vector in GLOBAL CS !!!!!!! - this->computeInternalForcesFromBoundaryEdgeLoadVectorAtPoint(help, boundaryLoad, (*it).boundaryId, - ExternalForcesVector, VM_Total, tStep, coords, ds, false); - } - answer.add(help); - } + BCTracker :: entryListType bcList = bct->getElementRecords(this->number); + + for ( BCTracker :: entryListType :: iterator it = bcList.begin(); it != bcList.end(); ++it ) { + GeneralBoundaryCondition *bc = this->domain->giveBc( ( * it ).bcNumber ); + BodyLoad *bodyLoad; + BoundaryLoad *boundaryLoad; + if ( bc->isImposed(tStep) ) { + if ( ( bodyLoad = dynamic_cast< BodyLoad * >(bc) ) ) { // body load + this->computeInternalForcesFromBodyLoadVectorAtPoint(help, bodyLoad, tStep, VM_Total, coords, ds); // this one is local + //answer.subtract(help); + } else if ( ( boundaryLoad = dynamic_cast< BoundaryLoad * >(bc) ) ) { + // compute Boundary Edge load vector in GLOBAL CS !!!!!!! + this->computeInternalForcesFromBoundaryEdgeLoadVectorAtPoint(help, boundaryLoad, ( * it ).boundaryId, + ExternalForcesVector, VM_Total, tStep, coords, ds, false); + } + answer.add(help); + } } - - if (subsoilMat) { - // @todo: linear subsoil assumed here; more general approach should integrate internal forces - FloatMatrix k; - FloatArray u, F; - this->computeSubSoilStiffnessMatrix(k, TangentStiffness, tStep); - this->computeVectorOf(VM_Total, tStep, u); - F.beProductOf(k, u); - answer.add(F); + + if ( subsoilMat ) { + // @todo: linear subsoil assumed here; more general approach should integrate internal forces + FloatMatrix k; + FloatArray u, F; + this->computeSubSoilStiffnessMatrix(k, TangentStiffness, tStep); + this->computeVectorOf(VM_Total, tStep, u); + F.beProductOf(k, u); + answer.add(F); } answer.times(-1); - } - + void Beam3d :: computeInternalForcesFromBoundaryEdgeLoadVectorAtPoint(FloatArray &answer, BoundaryLoad *load, int edge, CharType type, ValueModeType mode, TimeStep *tStep, FloatArray &pointCoords, double ds, bool global) { @@ -1122,13 +1167,13 @@ Beam3d :: computeInternalForcesFromBoundaryEdgeLoadVectorAtPoint(FloatArray &ans FloatMatrix T; - for ( GaussPoint *gp: *this->giveDefaultIntegrationRulePtr() ) { + for ( GaussPoint *gp : *this->giveDefaultIntegrationRulePtr() ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); - this->computeGlobalCoordinates(coords, lcoords, pointCoords); - if ( load ) { - load->computeValues(t, tStep, coords, {D_u, D_v, D_w, R_u, R_v, R_w}, mode); + this->computeGlobalCoordinates(coords, lcoords, pointCoords); + if ( load->giveFormulationType() == Load :: FT_Entity ) { + load->computeValues(t, tStep, lcoords, { D_u, D_v, D_w, R_u, R_v, R_w }, mode); } else { - load->computeValues(t, tStep, lcoords, {D_u, D_v, D_w, R_u, R_v, R_w}, mode); + load->computeValues(t, tStep, coords, { D_u, D_v, D_w, R_u, R_v, R_w }, mode); } if ( load->giveCoordSystMode() == Load :: CST_Global ) { @@ -1139,17 +1184,17 @@ Beam3d :: computeInternalForcesFromBoundaryEdgeLoadVectorAtPoint(FloatArray &ans double dl = gp->giveWeight() * 0.5 * ds; - FloatArray f; - f = t; - f.at(5) += f.at(3) * (lcoords.at(1)+1)*ds/2; - f.at(6) -= f.at(2) * (lcoords.at(1)+1)*ds/2; + FloatArray f; + f = t; + f.at(5) += f.at(3) * ( lcoords.at(1) + 1 ) * ds / 2; + f.at(6) -= f.at(2) * ( lcoords.at(1) + 1 ) * ds / 2; answer.add(dl, f); } - if (global) { - // Loads from sets expects global c.s. - this->computeGtoLRotationMatrix(T); - answer.rotatedWith(T, 't'); + if ( global ) { + // Loads from sets expects global c.s. + this->computeGtoLRotationMatrix(T); + answer.rotatedWith(T, 't'); } } @@ -1166,11 +1211,11 @@ Beam3d :: computeInternalForcesFromBodyLoadVectorAtPoint(FloatArray &answer, Loa FloatArray force, ntf; FloatMatrix n, T; FloatArray lc(1); - + if ( ( forLoad->giveBCGeoType() != BodyLoadBGT ) || ( forLoad->giveBCValType() != ForceLoadBVT ) ) { OOFEM_ERROR("unknown load type"); } - + // note: force is assumed to be in global coordinate system. forLoad->computeComponentArrayAt(force, tStep, mode); force.times( this->giveCrossSection()->give(CS_Area, lc, this) ); @@ -1182,113 +1227,103 @@ Beam3d :: computeInternalForcesFromBodyLoadVectorAtPoint(FloatArray &answer, Loa answer.clear(); if ( force.giveSize() ) { - for ( GaussPoint *gp: *this->giveDefaultIntegrationRulePtr() ) { - const FloatArray &lcoords = gp->giveNaturalCoordinates(); + for ( GaussPoint *gp : *this->giveDefaultIntegrationRulePtr() ) { + const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->computeNmatrixAt(gp->giveSubPatchCoordinates(), n); dV = gp->giveWeight() * 0.5 * ds; dens = this->giveCrossSection()->give('d', gp); - FloatArray iF; - iF = force; - iF.at(5) += force.at(3) * (lcoords.at(1)+1)*ds/2; - iF.at(6) -= force.at(2) * (lcoords.at(1)+1)*ds/2; + FloatArray iF; + iF = force; + iF.at(5) += force.at(3) * ( lcoords.at(1) + 1 ) * ds / 2; + iF.at(6) -= force.at(2) * ( lcoords.at(1) + 1 ) * ds / 2; answer.add(dV * dens, iF); } } else { return; } - - - } void -Beam3d :: giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ) +Beam3d :: giveCompositeExportData(std :: vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep) { - - - // divide element into several small ones - vtkPieces.resize(1); - vtkPieces[0].setNumberOfCells(Beam3d_nSubBeams); - int nNodes = 2 * Beam3d_nSubBeams; - vtkPieces[0].setNumberOfNodes(nNodes); - FloatArray nodeXi(nNodes), xi(1); - - Node *nodeA, *nodeB; - nodeA = this->giveNode(1); - nodeB = this->giveNode(2); - double dx = (nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1))/Beam3d_nSubBeams; - double dy = (nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2))/Beam3d_nSubBeams; - double dz = (nodeB->giveCoordinate(3) - nodeA->giveCoordinate(3))/Beam3d_nSubBeams; - FloatArray coords(3); - int nodeNumber = 1; - int val = 1; - int offset = 0; - IntArray connectivity(2); - for (int i = 0; i < Beam3d_nSubBeams; i++) { - for (int j = 0; j < 2; j++) { - coords.at(1) = nodeA->giveCoordinate(1) + (i+j) * dx; - coords.at(2) = nodeA->giveCoordinate(2) + (i+j) * dy; - coords.at(3) = nodeA->giveCoordinate(3) + (i+j) * dz; - vtkPieces[0].setNodeCoords(nodeNumber,coords); - nodeXi.at(nodeNumber) = -1.0+(2.0/Beam3d_nSubBeams)*(i+j); - nodeNumber++; - connectivity.at(j+1) = val++; - + // divide element into several small ones + vtkPieces.resize(1); + vtkPieces [ 0 ].setNumberOfCells(Beam3d_nSubBeams); + int nNodes = 2 * Beam3d_nSubBeams; + vtkPieces [ 0 ].setNumberOfNodes(nNodes); + FloatArray nodeXi(nNodes), xi(1); + + Node *nodeA, *nodeB; + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + double dx = ( nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1) ) / Beam3d_nSubBeams; + double dy = ( nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2) ) / Beam3d_nSubBeams; + double dz = ( nodeB->giveCoordinate(3) - nodeA->giveCoordinate(3) ) / Beam3d_nSubBeams; + FloatArray coords(3); + int nodeNumber = 1; + int val = 1; + int offset = 0; + IntArray connectivity(2); + for ( int i = 0; i < Beam3d_nSubBeams; i++ ) { + for ( int j = 0; j < 2; j++ ) { + coords.at(1) = nodeA->giveCoordinate(1) + ( i + j ) * dx; + coords.at(2) = nodeA->giveCoordinate(2) + ( i + j ) * dy; + coords.at(3) = nodeA->giveCoordinate(3) + ( i + j ) * dz; + vtkPieces [ 0 ].setNodeCoords(nodeNumber, coords); + nodeXi.at(nodeNumber) = -1.0 + ( 2.0 / Beam3d_nSubBeams ) * ( i + j ); + nodeNumber++; + connectivity.at(j + 1) = val++; + } + vtkPieces [ 0 ].setConnectivity(i + 1, connectivity); + offset += 2; + vtkPieces [ 0 ].setOffset(i + 1, offset); + vtkPieces [ 0 ].setCellType(i + 1, 3); } - vtkPieces[0].setConnectivity(i+1, connectivity); - offset += 2; - vtkPieces[0].setOffset(i+1, offset); - vtkPieces[0].setCellType(i+1,3); - } - - InternalStateType isttype; - int n = internalVarsToExport.giveSize(); - vtkPieces[0].setNumberOfInternalVarsToExport(n, nNodes); - for ( int i = 1; i <= n; i++ ) { - isttype = ( InternalStateType ) internalVarsToExport.at(i); - for (int nN = 1; nN <= nNodes; nN++) { - if ( isttype == IST_BeamForceMomentTensor ) { - FloatArray coords = vtkPieces[0].giveNodeCoords(nN); - FloatArray endForces; - this->giveInternalForcesVectorAtPoint(endForces, tStep, coords); - vtkPieces[0].setInternalVarInNode( i, nN, endForces ); - } else { - fprintf( stderr, "VTKXMLExportModule::exportIntVars: unsupported variable type %s\n", __InternalStateTypeToString(isttype) ); - } - } - } - primaryVarsToExport.giveSize(); - vtkPieces[0].setNumberOfPrimaryVarsToExport(n, nNodes); - for ( int i = 1; i <= n; i++ ) { - UnknownType utype = (UnknownType) primaryVarsToExport.at(i); - if ( utype == DisplacementVector ) { - FloatMatrix Tgl, n; - FloatArray d(3); - - this->B3SSMI_getUnknownsGtoLRotationMatrix(Tgl); - for (int nN = 1; nN <= nNodes; nN++) { - FloatArray u, dl, dg; - this->computeVectorOf(VM_Total, tStep, u); - xi.at(1) = nodeXi.at(nN); - this->computeNmatrixAt(xi, n); - dl.beProductOf(n,u); // local interpolated displacement - dg.beTProductOf(Tgl, dl); // local displacement tranformed to global c.s. - d.at(1)=dg.at(1); d.at(2)=dg.at(2); d.at(3)=dg.at(3); - vtkPieces[0].setPrimaryVarInNode( i, nN, d ); - } - } else { - fprintf( stderr, "VTKXMLExportModule::exportPrimaryVars: unsupported variable type %s\n", __UnknownTypeToString(utype) ); + InternalStateType isttype; + int n = internalVarsToExport.giveSize(); + vtkPieces [ 0 ].setNumberOfInternalVarsToExport(internalVarsToExport, nNodes); + for ( int i = 1; i <= n; i++ ) { + isttype = ( InternalStateType ) internalVarsToExport.at(i); + for ( int nN = 1; nN <= nNodes; nN++ ) { + if ( isttype == IST_BeamForceMomentTensor ) { + FloatArray coords = vtkPieces [ 0 ].giveNodeCoords(nN); + FloatArray endForces; + this->giveInternalForcesVectorAtPoint(endForces, tStep, coords); + vtkPieces [ 0 ].setInternalVarInNode(isttype, nN, endForces); + } else { + fprintf( stderr, "VTKXMLExportModule::exportIntVars: unsupported variable type %s\n", __InternalStateTypeToString(isttype) ); + } + } } - } + n = primaryVarsToExport.giveSize(); + vtkPieces [ 0 ].setNumberOfPrimaryVarsToExport(primaryVarsToExport, nNodes); + for ( int i = 1; i <= n; i++ ) { + UnknownType utype = ( UnknownType ) primaryVarsToExport.at(i); + if ( utype == DisplacementVector ) { + FloatMatrix Tgl, n; + FloatArray d(3); + + Tgl = this->B3SSMI_getUnknownsGtoLRotationMatrix(); + for ( int nN = 1; nN <= nNodes; nN++ ) { + FloatArray u, dl, dg; + this->computeVectorOf(VM_Total, tStep, u); + xi.at(1) = nodeXi.at(nN); + this->computeNmatrixAt(xi, n); + dl.beProductOf(n, u); // local interpolated displacement + dg.beTProductOf(Tgl, dl); // local displacement tranformed to global c.s. + d.at(1) = dg.at(1); + d.at(2) = dg.at(2); + d.at(3) = dg.at(3); + vtkPieces [ 0 ].setPrimaryVarInNode(utype, nN, d); + } + } else { + fprintf( stderr, "VTKXMLExportModule::exportPrimaryVars: unsupported variable type %s\n", __UnknownTypeToString(utype) ); + } + } } - - - - - } // end namespace oofem diff --git a/src/sm/Elements/Beams/beam3d.h b/src/sm/Elements/Beams/beam3d.h index 9e9ec03fa..e56f5a85d 100644 --- a/src/sm/Elements/Beams/beam3d.h +++ b/src/sm/Elements/Beams/beam3d.h @@ -35,9 +35,9 @@ #ifndef beam3d_h #define beam3d_h -#include "../sm/Elements/Beams/beambaseelement.h" -#include "../sm/CrossSections/fiberedcs.h" -#include "../sm/Materials/winklermodel.h" +#include "sm/Elements/Beams/beambaseelement.h" +#include "sm/CrossSections/fiberedcs.h" +#include "sm/Materials/winklermodel.h" #include "dofmanager.h" #include "vtkxmlexportmodule.h" @@ -94,43 +94,44 @@ class FEI3dLineLin; /// Subsoil material int subsoilMat; - + public: Beam3d(int n, Domain *d); virtual ~Beam3d(); - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL); - virtual void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual int giveLocalCoordinateSystem(FloatMatrix &answer); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *, int useUpdatedGpRecord = 0); + void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) override; + void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeLumpedInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *, int useUpdatedGpRecord = 0) override; void giveEndForcesVector(FloatArray &answer, TimeStep *tStep); - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; - virtual int testElementExtension(ElementExtension ext) { + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } //int hasLayeredSupport () {return 1;} - virtual int computeNumberOfDofs() { return 12; } - virtual int computeNumberOfGlobalDofs() { return 12 + this->numberOfCondensedDofs; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual int giveNumberOfInternalDofManagers() const { return ( ghostNodes [ 0 ] != NULL ) + ( ghostNodes [ 1 ] != NULL ); } - virtual DofManager *giveInternalDofManager(int i) const { + int computeNumberOfDofs() override { return 12; } + int computeNumberOfGlobalDofs() override { return 12 + this->numberOfCondensedDofs; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + int giveNumberOfInternalDofManagers() const override { return ( ghostNodes [ 0 ] != nullptr ) + ( ghostNodes [ 1 ] != nullptr ); } + DofManager *giveInternalDofManager(int i) const override { if ( i == 1 ) { if ( ghostNodes [ 0 ] ) { return ghostNodes [ 0 ]; } else { return ghostNodes [ 1 ]; } } else if ( i == 2 ) { // i==2 return ghostNodes [ 1 ]; } else { OOFEM_ERROR("No such DOF available on Element %d", number); - return NULL; + return nullptr; } } - virtual void giveInternalDofManDofIDMask(int i, IntArray &answer) const { + void giveInternalDofManDofIDMask(int i, IntArray &answer) const override { if ( i == 1 ) { if ( ghostNodes [ 0 ] ) { ghostNodes [ 0 ]->giveCompleteMasterDofIDArray(answer); @@ -143,37 +144,37 @@ class FEI3dLineLin; OOFEM_ERROR("No such DOF available on Element %d", number); } } - virtual void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIds = NULL) { + void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIds = NULL) override { giveLocationArray (locationArray, s, dofIds); } - - virtual void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const IntArray &dofIDMask, const UnknownNumberingScheme &s, IntArray *dofIds = NULL) { + + void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const IntArray &dofIDMask, const UnknownNumberingScheme &s, IntArray *dofIds = NULL) override { giveLocationArray (locationArray, dofIDMask, s, dofIds); } - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; // // fibered cross section support functions // - virtual void FiberedCrossSectionInterface_computeStrainVectorInFiber(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *slaveGp, TimeStep *tStep); + void FiberedCrossSectionInterface_computeStrainVectorInFiber(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *slaveGp, TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; // definition & identification - virtual const char *giveClassName() const { return "Beam3d"; } - virtual const char *giveInputRecordName() const { return _IFT_Beam3d_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "Beam3d"; } + const char *giveInputRecordName() const override { return _IFT_Beam3d_Name; } + void initializeFrom(InputRecord &ir) override; ///@todo Introduce interpolator and remove these two: - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - //virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_Composite; } - virtual void updateLocalNumbering(EntityRenumberingFunctor &f); + integrationDomain giveIntegrationDomain() const override { return _Line; } + //Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + Element_Geometry_Type giveGeometryType() const override { return EGT_Composite; } + void updateLocalNumbering(EntityRenumberingFunctor &f) override; /* /// Subsoil support implemented directly enabling the postprocessing of end-forces @@ -188,41 +189,39 @@ class FEI3dLineLin; return this->computeVolumeAround(gp); } */ - virtual void B3SSMI_getUnknownsGtoLRotationMatrix(FloatMatrix& answer); + FloatMatrixF<6,6> B3SSMI_getUnknownsGtoLRotationMatrix() const override; - virtual void giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ); + void giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ) override; - #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext & gc, TimeStep * tStep, UnknownType); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext & gc, TimeStep * tStep, UnknownType) override; #endif protected: - virtual void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int edge, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); - virtual void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &); - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); + void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int edge, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &) override; + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; double giveKappayCoeff(TimeStep *tStep); double giveKappazCoeff(TimeStep *tStep); void computeKappaCoeffs(TimeStep *tStep); - virtual double computeLength(); - virtual void computeGaussPoints(); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); + double computeLength() override; + void computeGaussPoints() override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; - virtual MaterialMode giveMaterialMode() { return _3dBeam; } - virtual int giveNumberOfIPForMassMtrxIntegration() { return 4; } + MaterialMode giveMaterialMode() override { return _3dBeam; } + int giveNumberOfIPForMassMtrxIntegration() override { return 4; } bool hasDofs2Condense() { return ( ghostNodes [ 0 ] || ghostNodes [ 1 ] ); } void computeSubSoilNMatrixAt(GaussPoint *gp, FloatMatrix &answer); - void computeSubSoilStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, TimeStep *tStep); + void computeSubSoilStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); void giveInternalForcesVectorAtPoint(FloatArray &answer, TimeStep *tStep, FloatArray &coords); void computeInternalForcesFromBoundaryEdgeLoadVectorAtPoint(FloatArray &answer, BoundaryLoad *load, int edge, CharType type, ValueModeType mode, diff --git a/src/sm/Elements/Beams/beambaseelement.C b/src/sm/Elements/Beams/beambaseelement.C index 05bf3fe7e..2e2d9463e 100644 --- a/src/sm/Elements/Beams/beambaseelement.C +++ b/src/sm/Elements/Beams/beambaseelement.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Beams/beambaseelement.h" +#include "sm/Elements/Beams/beambaseelement.h" #include "node.h" #include "gausspoint.h" #include "gaussintegrationrule.h" diff --git a/src/sm/Elements/Beams/beambaseelement.h b/src/sm/Elements/Beams/beambaseelement.h index e33135d90..0c98b53a4 100644 --- a/src/sm/Elements/Beams/beambaseelement.h +++ b/src/sm/Elements/Beams/beambaseelement.h @@ -35,9 +35,9 @@ #ifndef beambaseelement_h #define beambaseelement_h -#include "../sm/Elements/structuralelement.h" -#include "../sm/CrossSections/fiberedcs.h" -#include "../sm/Materials/winklermodel.h" +#include "sm/Elements/structuralelement.h" +#include "sm/CrossSections/fiberedcs.h" +#include "sm/Materials/winklermodel.h" #include "dofmanager.h" namespace oofem { diff --git a/src/sm/Elements/Beams/libeam2d.C b/src/sm/Elements/Beams/libeam2d.C index c78d9a1c1..c5da0b66b 100644 --- a/src/sm/Elements/Beams/libeam2d.C +++ b/src/sm/Elements/Beams/libeam2d.C @@ -10,7 +10,7 @@ * * OOFEM : Object Oriented Finite Element Code * - * Copyright (C) 1993 - 2013 Borek Patzak + * Copyright (C) 1993 - 2021 Borek Patzak * * * @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Beams/libeam2d.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/Beams/libeam2d.h" +#include "sm/Materials/structuralms.h" #include "fei2dlinelin.h" #include "node.h" #include "material.h" @@ -50,7 +50,8 @@ namespace oofem { REGISTER_Element(LIBeam2d); // Set up interpolation coordinates -FEI2dLineLin LIBeam2d :: interpolation(1, 3); +FEI2dLineLin LIBeam2d :: interpolationXZ(1, 3); +FEI2dLineLin LIBeam2d :: interpolationXY(1, 2); LIBeam2d :: LIBeam2d(int n, Domain *aDomain) : StructuralElement(n, aDomain), LayeredCrossSectionInterface() { @@ -60,7 +61,7 @@ LIBeam2d :: LIBeam2d(int n, Domain *aDomain) : StructuralElement(n, aDomain), La } -FEInterpolation *LIBeam2d :: giveInterpolation() const { return & interpolation; } +FEInterpolation *LIBeam2d :: giveInterpolation() const { if (xy) {return & interpolationXY;} else {return & interpolationXZ;} } Interface * @@ -111,7 +112,7 @@ LIBeam2d :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } } @@ -120,14 +121,14 @@ LIBeam2d :: computeGaussPoints() void LIBeam2d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give2dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give2dBeamStiffMtrx(rMode, gp, tStep); } void LIBeam2d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Beam2d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Beam2d(strain, gp, tStep); } @@ -142,7 +143,11 @@ LIBeam2d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoor answer.resize(3); answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 *this->giveNode(2)->giveCoordinate(1); - answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 *this->giveNode(2)->giveCoordinate(3); + if (xy) { + answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 *this->giveNode(2)->giveCoordinate(2); + } else { + answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 *this->giveNode(2)->giveCoordinate(3); + } return 1; } @@ -272,7 +277,11 @@ LIBeam2d :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType ty void LIBeam2d :: giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u, D_w, R_v}; + if (xy) { + answer = {D_u, D_v, R_w}; + } else { + answer = {D_u, D_w, R_v}; + } } @@ -287,7 +296,11 @@ LIBeam2d :: computeLength() nodeA = this->giveNode(1); nodeB = this->giveNode(2); dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); - dy = nodeB->giveCoordinate(3) - nodeA->giveCoordinate(3); + if (xy) { + dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); + } else { + dy = nodeB->giveCoordinate(3) - nodeA->giveCoordinate(3); + } length = sqrt(dx * dx + dy * dy); } @@ -307,8 +320,13 @@ LIBeam2d :: givePitch() nodeB = this->giveNode(2); xA = nodeA->giveCoordinate(1); xB = nodeB->giveCoordinate(1); - yA = nodeA->giveCoordinate(3); - yB = nodeB->giveCoordinate(3); + if (xy) { + yA = nodeA->giveCoordinate(2); + yB = nodeB->giveCoordinate(2); + } else { + yA = nodeA->giveCoordinate(3); + yB = nodeB->giveCoordinate(3); + } pitch = atan2(yB - yA, xB - xA); } @@ -316,10 +334,13 @@ LIBeam2d :: givePitch() } -IRResultType -LIBeam2d :: initializeFrom(InputRecord *ir) +void +LIBeam2d :: initializeFrom(InputRecord &ir) { - return StructuralElement :: initializeFrom(ir); + StructuralElement :: initializeFrom(ir); + xy = ir.hasField(_IFT_LIBeam2d_XY); + xz = ir.hasField(_IFT_LIBeam2d_XZ); + xy ? (xz = false) : (xz = true); } diff --git a/src/sm/Elements/Beams/libeam2d.h b/src/sm/Elements/Beams/libeam2d.h index 72ab5880d..f1034b800 100644 --- a/src/sm/Elements/Beams/libeam2d.h +++ b/src/sm/Elements/Beams/libeam2d.h @@ -10,7 +10,7 @@ * * OOFEM : Object Oriented Finite Element Code * - * Copyright (C) 1993 - 2013 Borek Patzak + * Copyright (C) 1993 - 2021 Borek Patzak * * * @@ -35,10 +35,12 @@ #ifndef libeam2d_h #define libeam2d_h -#include "../sm/Elements/structuralelement.h" -#include "../sm/CrossSections/layeredcrosssection.h" +#include "sm/Elements/structuralelement.h" +#include "sm/CrossSections/layeredcrosssection.h" #define _IFT_LIBeam2d_Name "libeam2d" +#define _IFT_LIBeam2d_XZ "xz" +#define _IFT_LIBeam2d_XY "xy" namespace oofem { class FEI2dLineLin; @@ -51,57 +53,59 @@ class LIBeam2d : public StructuralElement, public LayeredCrossSectionInterface { protected: /// Interpolation - static FEI2dLineLin interpolation; + static FEI2dLineLin interpolationXZ; + static FEI2dLineLin interpolationXY; public: double pitch, length; + bool xz = true; + bool xy = false; //by default element in xz plane LIBeam2d(int n, Domain * aDomain); virtual ~LIBeam2d() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) { computeLumpedMassMatrix(answer, tStep); } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; // layered cross section support functions - virtual void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep); + void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; - virtual Interface *giveInterface(InterfaceType it); - - virtual int computeNumberOfDofs() { return 6; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual double computeVolumeAround(GaussPoint *gp); + Interface *giveInterface(InterfaceType it) override; + int computeNumberOfDofs() override { return 6; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + double computeVolumeAround(GaussPoint *gp) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LIBeam2d_Name; } - virtual const char *giveClassName() const { return "LIBeam2d"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_LIBeam2d_Name; } + const char *giveClassName() const override { return "LIBeam2d"; } + void initializeFrom(InputRecord &ir) override; - virtual MaterialMode giveMaterialMode() { return _2dBeam; } + MaterialMode giveMaterialMode() override { return _2dBeam; } protected: // edge load support - virtual void giveEdgeDofMapping(IntArray &answer, int) const; - virtual double computeEdgeVolumeAround(GaussPoint *, int); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &, int, GaussPoint *); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - virtual void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &); - virtual void computeGaussPoints(); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - - virtual double computeLength(); + void giveEdgeDofMapping(IntArray &answer, int) const override; + double computeEdgeVolumeAround(GaussPoint *, int) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &, int, GaussPoint *) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &) override; + void computeGaussPoints() override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + + double computeLength() override; double givePitch(); }; } // end namespace oofem diff --git a/src/sm/Elements/Beams/libeam2dnl.C b/src/sm/Elements/Beams/libeam2dnl.C index f383d910f..07601d0db 100644 --- a/src/sm/Elements/Beams/libeam2dnl.C +++ b/src/sm/Elements/Beams/libeam2dnl.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Beams/libeam2dnl.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/Beams/libeam2dnl.h" +#include "sm/Materials/structuralms.h" #include "node.h" #include "material.h" #include "crosssection.h" @@ -52,7 +52,7 @@ namespace oofem { REGISTER_Element(LIBeam2dNL); -LIBeam2dNL :: LIBeam2dNL(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), LayeredCrossSectionInterface() +LIBeam2dNL::LIBeam2dNL(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), LayeredCrossSectionInterface() { numberOfDofMans = 2; length = 0.; @@ -60,10 +60,10 @@ LIBeam2dNL :: LIBeam2dNL(int n, Domain *aDomain) : NLStructuralElement(n, aDomai } Interface * -LIBeam2dNL :: giveInterface(InterfaceType interface) +LIBeam2dNL::giveInterface(InterfaceType interface) { if ( interface == LayeredCrossSectionInterfaceType ) { - return static_cast< LayeredCrossSectionInterface * >(this); + return static_cast< LayeredCrossSectionInterface * >( this ); } return NULL; @@ -71,7 +71,7 @@ LIBeam2dNL :: giveInterface(InterfaceType interface) void -LIBeam2dNL :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +LIBeam2dNL::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the strain matrix of the receiver. { double l, ksi, n1, n2, n1x, n2x, n3x; @@ -103,7 +103,7 @@ LIBeam2dNL :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int void -LIBeam2dNL :: computeNLBMatrixAt(FloatMatrix &answer, GaussPoint *gp, int i) +LIBeam2dNL::computeNLBMatrixAt(FloatMatrix &answer, GaussPoint *gp, int i) { // // Returns nonlinear part of geometrical equations of the receiver at gp. @@ -253,7 +253,7 @@ LIBeam2dNL :: computeNLBMatrixAt(FloatMatrix &answer, GaussPoint *gp, int i) void -LIBeam2dNL :: computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) +LIBeam2dNL::computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) { double dV; FloatArray stress; @@ -263,7 +263,7 @@ LIBeam2dNL :: computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) answer.zero(); // assemble initial stress matrix - for ( GaussPoint *gp: *this->giveDefaultIntegrationRulePtr() ) { + for ( GaussPoint *gp: * this->giveDefaultIntegrationRulePtr() ) { dV = this->computeVolumeAround(gp); stress = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); if ( stress.giveSize() ) { @@ -280,19 +280,19 @@ LIBeam2dNL :: computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) } -void LIBeam2dNL :: computeGaussPoints() +void LIBeam2dNL::computeGaussPoints() // Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } } void -LIBeam2dNL :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +LIBeam2dNL::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. This expression is // valid in both local and global axes. { @@ -309,7 +309,7 @@ LIBeam2dNL :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) void -LIBeam2dNL :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +LIBeam2dNL::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the displacement interpolation matrix {N} of the receiver, eva- // luated at gp. { @@ -339,11 +339,11 @@ LIBeam2dNL :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) bool -LIBeam2dNL :: computeGtoLRotationMatrix(FloatMatrix &answer) +LIBeam2dNL::computeGtoLRotationMatrix(FloatMatrix &answer) { double sine, cosine; - sine = sin( this->givePitch() ); + sine = sin(this->givePitch() ); cosine = cos(pitch); answer.resize(6, 6); @@ -364,7 +364,7 @@ LIBeam2dNL :: computeGtoLRotationMatrix(FloatMatrix &answer) } -double LIBeam2dNL :: computeVolumeAround(GaussPoint *gp) +double LIBeam2dNL::computeVolumeAround(GaussPoint *gp) // Returns the length of the receiver. This method is valid only if 1 // Gauss point is used. { @@ -374,10 +374,10 @@ double LIBeam2dNL :: computeVolumeAround(GaussPoint *gp) int -LIBeam2dNL :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +LIBeam2dNL::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - ///@todo This should be a common inheritance for all 3d beams (and a similar one for 2D beams) - /// to support all the sensible moment/force tensors. + ///@todo This should be a common inheritance for all 3d beams (and a similar one for 2D beams) + /// to support all the sensible moment/force tensors. if ( type == IST_BeamForceMomentTensor ) { answer = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); return 1; @@ -385,27 +385,33 @@ LIBeam2dNL :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType answer = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); return 1; } else { - return StructuralElement :: giveIPValue(answer, gp, type, tStep); + return StructuralElement::giveIPValue(answer, gp, type, tStep); } } void -LIBeam2dNL :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +LIBeam2dNL::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Beam2d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Beam2d(strain, gp, tStep); } void -LIBeam2dNL :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +LIBeam2dNL::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give2dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give2dBeamStiffMtrx(rMode, gp, tStep); +} + +void +LIBeam2dNL::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + OOFEM_ERROR("computeConstitutiveMatrix_dPdF_At Not implemented for libeam2dnl"); } void -LIBeam2dNL :: computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) +LIBeam2dNL::computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) // // returns full 3d strain vector of given layer (whose z-coordinate from center-line is // stored in slaveGp) for given tStep @@ -426,14 +432,14 @@ LIBeam2dNL :: computeStrainVectorInLayer(FloatArray &answer, const FloatArray &m void -LIBeam2dNL :: giveDofManDofIDMask(int inode, IntArray &answer) const +LIBeam2dNL::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u, D_w, R_v}; + answer = { D_u, D_w, R_v }; } int -LIBeam2dNL :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +LIBeam2dNL::computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { double ksi, n1, n2; @@ -442,14 +448,14 @@ LIBeam2dNL :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lco n2 = ( 1. + ksi ) * 0.5; answer.resize(3); - answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 *this->giveNode(2)->giveCoordinate(1); - answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 *this->giveNode(2)->giveCoordinate(3); + answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 * this->giveNode(2)->giveCoordinate(1); + answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 * this->giveNode(2)->giveCoordinate(3); return 1; } -double LIBeam2dNL :: computeLength() +double LIBeam2dNL::computeLength() // Returns the length of the receiver. { double dx, dy; @@ -467,7 +473,7 @@ double LIBeam2dNL :: computeLength() } -double LIBeam2dNL :: givePitch() +double LIBeam2dNL::givePitch() // Returns the pitch of the receiver. { double xA, xB, yA, yB; @@ -487,15 +493,15 @@ double LIBeam2dNL :: givePitch() } -IRResultType -LIBeam2dNL :: initializeFrom(InputRecord *ir) +void +LIBeam2dNL::initializeFrom(InputRecord &ir) { - return NLStructuralElement :: initializeFrom(ir); + NLStructuralElement::initializeFrom(ir); } void -LIBeam2dNL :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +LIBeam2dNL::giveEdgeDofMapping(IntArray &answer, int iEdge) const { /* * provides dof mapping of local edge dofs (only nonzero are taken into account) @@ -517,7 +523,7 @@ LIBeam2dNL :: giveEdgeDofMapping(IntArray &answer, int iEdge) const } double -LIBeam2dNL :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +LIBeam2dNL::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { if ( iEdge != 1 ) { // edge between nodes 1 2 OOFEM_ERROR("wrong egde number"); @@ -529,7 +535,7 @@ LIBeam2dNL :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) int -LIBeam2dNL :: computeLoadGToLRotationMtrx(FloatMatrix &answer) +LIBeam2dNL::computeLoadGToLRotationMtrx(FloatMatrix &answer) { /* * Returns transformation matrix from global coordinate system to local @@ -543,7 +549,7 @@ LIBeam2dNL :: computeLoadGToLRotationMtrx(FloatMatrix &answer) answer.resize(3, 3); answer.zero(); - sine = sin( this->givePitch() ); + sine = sin(this->givePitch() ); cosine = cos(pitch); answer.at(1, 1) = cosine; @@ -556,7 +562,7 @@ LIBeam2dNL :: computeLoadGToLRotationMtrx(FloatMatrix &answer) } int -LIBeam2dNL :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +LIBeam2dNL::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -571,16 +577,16 @@ LIBeam2dNL :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gau void -LIBeam2dNL :: computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) +LIBeam2dNL::computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) { FloatArray lc(1); - StructuralElement :: computeBodyLoadVectorAt(answer, load, tStep, mode); - answer.times( this->giveCrossSection()->give(CS_Area, lc, this) ); + StructuralElement::computeBodyLoadVectorAt(answer, load, tStep, mode); + answer.times(this->giveCrossSection()->give(CS_Area, lc, this) ); } #ifdef __OOFEG -void LIBeam2dNL :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +void LIBeam2dNL::drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { GraphicObj *go; @@ -589,9 +595,9 @@ void LIBeam2dNL :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } // if (!go) { // create new one - WCRec p [ 2 ]; /* poin */ + WCRec p[ 2 ]; /* poin */ EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); + EASValsSetColor(gc.getElementColor() ); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); p [ 0 ].y = 0.; @@ -606,7 +612,7 @@ void LIBeam2dNL :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } -void LIBeam2dNL :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +void LIBeam2dNL::drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) { GraphicObj *go; if ( !gc.testElementGraphicActivity(this) ) { @@ -615,9 +621,9 @@ void LIBeam2dNL :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep double defScale = gc.getDefScale(); // if (!go) { // create new one - WCRec p [ 2 ]; /* poin */ + WCRec p[ 2 ]; /* poin */ EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); p [ 0 ].y = 0.; diff --git a/src/sm/Elements/Beams/libeam2dnl.h b/src/sm/Elements/Beams/libeam2dnl.h index 07a9d4f1d..251336475 100644 --- a/src/sm/Elements/Beams/libeam2dnl.h +++ b/src/sm/Elements/Beams/libeam2dnl.h @@ -35,8 +35,8 @@ #ifndef libeam2dnl_h #define libeam2dnl_h -#include "../sm/Elements/nlstructuralelement.h" -#include "../sm/CrossSections/layeredcrosssection.h" +#include "sm/Elements/nlstructuralelement.h" +#include "sm/CrossSections/layeredcrosssection.h" #define _IFT_LIBeam2dNL_Name "libeam2dNL" @@ -52,60 +52,61 @@ class LIBeam2dNL : public NLStructuralElement, public LayeredCrossSectionInterfa double pitch, length; public: - LIBeam2dNL(int n, Domain * d); + LIBeam2dNL(int n, Domain *d); virtual ~LIBeam2dNL() { } - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); - virtual void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep); + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; + void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override; - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; // layered cross section support functions - virtual void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep); + void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual int computeNumberOfDofs() { return 6; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual double computeVolumeAround(GaussPoint *gp); + int computeNumberOfDofs() override { return 6; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + double computeVolumeAround(GaussPoint *gp) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LIBeam2dNL_Name; } - virtual const char *giveClassName() const { return "LIBeam2dNL"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_LIBeam2dNL_Name; } + const char *giveClassName() const override { return "LIBeam2dNL"; } + void initializeFrom(InputRecord &ir) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; #endif - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual MaterialMode giveMaterialMode() { return _2dBeam; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + MaterialMode giveMaterialMode() override { return _2dBeam; } + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } protected: // edge load support - virtual void giveEdgeDofMapping(IntArray &answer, int) const; - virtual double computeEdgeVolumeAround(GaussPoint *, int); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &, int, GaussPoint *); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); + void giveEdgeDofMapping(IntArray &answer, int) const override; + double computeEdgeVolumeAround(GaussPoint *, int) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &, int, GaussPoint *) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; // nonlinear part of geometrical eqs. for i-th component of strain vector. void computeNLBMatrixAt(FloatMatrix &answer, GaussPoint *gp, int); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeGaussPoints(); - virtual double computeLength(); + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeGaussPoints() override; + double computeLength() override; double givePitch(); }; } // end namespace oofem diff --git a/src/sm/Elements/Beams/libeam3d.C b/src/sm/Elements/Beams/libeam3d.C index a5539afbb..8026e8a02 100644 --- a/src/sm/Elements/Beams/libeam3d.C +++ b/src/sm/Elements/Beams/libeam3d.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Beams/libeam3d.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/Beams/libeam3d.h" +#include "sm/Materials/structuralms.h" #include "node.h" #include "material.h" #include "crosssection.h" @@ -109,7 +109,7 @@ LIBeam3d :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } } @@ -118,14 +118,14 @@ LIBeam3d :: computeGaussPoints() void LIBeam3d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give3dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give3dBeamStiffMtrx(rMode, gp, tStep); } void LIBeam3d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Beam3d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Beam3d(strain, gp, tStep); } @@ -282,10 +282,10 @@ LIBeam3d :: computeLength() } -IRResultType -LIBeam3d :: initializeFrom(InputRecord *ir) +void +LIBeam3d :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralElement :: initializeFrom(ir); IR_GIVE_FIELD(ir, referenceNode, _IFT_LIBeam3d_refnode); if ( referenceNode == 0 ) { @@ -299,8 +299,6 @@ LIBeam3d :: initializeFrom(InputRecord *ir) // } else { // dofsToCondense = NULL; // } - - return StructuralElement :: initializeFrom(ir); } @@ -382,6 +380,27 @@ LIBeam3d :: computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tS answer.times( this->giveCrossSection()->give(CS_Area, lc, this) ); } +Node* LIBeam3d :: giveReferenceNode(int refNode) +// +// returns pointer to the reference node in the general case that +// the global number of reference node is not equal to its consecutive number +// in the domain +// +{ + int nnodes = this->giveDomain()->giveNumberOfDofManagers(); + + for ( int i = 1; i <= nnodes; i++ ) { + Node* referenceNode = this->giveDomain()->giveNode(i); + int globalNumber = referenceNode->giveGlobalNumber(); + if ( globalNumber == refNode ) { + return referenceNode; + } + } + + OOFEM_ERROR("Could not find the reference node. Check numbering."); + return nullptr; +} + int LIBeam3d :: giveLocalCoordinateSystem(FloatMatrix &answer) // @@ -397,7 +416,7 @@ LIBeam3d :: giveLocalCoordinateSystem(FloatMatrix &answer) answer.zero(); nodeA = this->giveNode(1); nodeB = this->giveNode(2); - refNode = this->giveDomain()->giveNode(this->referenceNode); + refNode = this->giveReferenceNode(referenceNode); for ( int i = 1; i <= 3; i++ ) { lx.at(i) = ( nodeB->giveCoordinate(i) - nodeA->giveCoordinate(i) ) / length; @@ -434,11 +453,21 @@ LIBeam3d :: FiberedCrossSectionInterface_computeStrainVectorInFiber(FloatArray & answer.at(3) = masterGpStrain.at(3); } +void +LIBeam3d :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) +{ + GaussPoint* gp = integrationRulesArray[0]->getIntegrationPoint(0); + this->giveIPValue(answer, gp, type, tStep); +} + Interface * LIBeam3d :: giveInterface(InterfaceType interface) { if ( interface == FiberedCrossSectionInterfaceType ) { return static_cast< FiberedCrossSectionInterface * >(this); + } else if ( interface == NodalAveragingRecoveryModelInterfaceType ) { + return static_cast< NodalAveragingRecoveryModelInterface * >(this); } return NULL; diff --git a/src/sm/Elements/Beams/libeam3d.h b/src/sm/Elements/Beams/libeam3d.h index 60ac04e08..9e1ab730a 100644 --- a/src/sm/Elements/Beams/libeam3d.h +++ b/src/sm/Elements/Beams/libeam3d.h @@ -35,8 +35,10 @@ #ifndef libeam3d_h #define libeam3d_h -#include "../sm/Elements/structuralelement.h" -#include "../sm/CrossSections/fiberedcs.h" +#include "sm/Elements/structuralelement.h" +#include "sm/CrossSections/fiberedcs.h" +#include "nodalaveragingrecoverymodel.h" +#include "node.h" ///@name Input fields for LIBeam3d //@{ @@ -49,7 +51,7 @@ namespace oofem { * This class implements a 3-dimensional mindlin theory Linear Isoparametric * beam element, with reduced integration. */ -class LIBeam3d : public StructuralElement, public FiberedCrossSectionInterface +class LIBeam3d : public StructuralElement, public FiberedCrossSectionInterface, public NodalAveragingRecoveryModelInterface { private: double length; @@ -59,56 +61,63 @@ class LIBeam3d : public StructuralElement, public FiberedCrossSectionInterface LIBeam3d(int n, Domain * d); virtual ~LIBeam3d() { } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; - virtual int testElementExtension(ElementExtension ext); + int testElementExtension(ElementExtension ext) override; - virtual int computeNumberOfDofs() { return 12; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual double computeVolumeAround(GaussPoint *gp); - virtual int giveLocalCoordinateSystem(FloatMatrix &answer); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + int computeNumberOfDofs() override { return 12; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + double computeVolumeAround(GaussPoint *gp) override; + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + Node* giveReferenceNode(int refNode); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + bool isCast(TimeStep *tStep) override {return true;} + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } // Fibered cross section support functions - virtual void FiberedCrossSectionInterface_computeStrainVectorInFiber(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *slaveGp, TimeStep *tStep); + void FiberedCrossSectionInterface_computeStrainVectorInFiber(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *slaveGp, TimeStep *tStep) override; + + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LIBeam3d_Name; } - virtual const char *giveClassName() const { return "LIBeam3d"; } + const char *giveInputRecordName() const override { return _IFT_LIBeam3d_Name; } + const char *giveClassName() const override { return "LIBeam3d"; } #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; #endif - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual MaterialMode giveMaterialMode() { return _3dBeam; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + MaterialMode giveMaterialMode() override { return _3dBeam; } protected: // edge load support - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *gp); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeGaussPoints(); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - - virtual double computeLength(); + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *gp) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeGaussPoints() override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + + double computeLength() override; }; } // end namespace oofem #endif // libeam3d_h diff --git a/src/sm/Elements/Beams/libeam3d2.C b/src/sm/Elements/Beams/libeam3d2.C index 2d321d048..ffd9a310c 100644 --- a/src/sm/Elements/Beams/libeam3d2.C +++ b/src/sm/Elements/Beams/libeam3d2.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Beams/libeam3d2.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/Beams/libeam3d2.h" +#include "sm/Materials/structuralms.h" #include "node.h" #include "material.h" #include "crosssection.h" @@ -57,7 +57,7 @@ namespace oofem { REGISTER_Element(LIBeam3d2); -LIBeam3d2 :: LIBeam3d2(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), tc(), tempTc() +LIBeam3d2::LIBeam3d2(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), tc(), tempTc() { numberOfDofMans = 2; referenceNode = 0; @@ -68,14 +68,14 @@ LIBeam3d2 :: LIBeam3d2(int n, Domain *aDomain) : NLStructuralElement(n, aDomain) void -LIBeam3d2 :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +LIBeam3d2::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the strain matrix of the receiver. // eeps = {\eps_x, \gamma_xz, \gamma_xy, \der{phi_x}{x}, \kappa_y, \kappa_z}^T { double l, ksi, n1, n2, n1x, n2x; if ( this->nlGeometry ) { - l = this->giveCurrentLength( domain->giveEngngModel()->giveCurrentStep() ); + l = this->giveCurrentLength(domain->giveEngngModel()->giveCurrentStep() ); } else { l = this->computeLength(); } @@ -114,12 +114,12 @@ LIBeam3d2 :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int u } void -LIBeam3d2 :: computeGaussPoints() +LIBeam3d2::computeGaussPoints() // Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } } @@ -127,7 +127,7 @@ LIBeam3d2 :: computeGaussPoints() void -LIBeam3d2 :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +LIBeam3d2::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. This expression is // valid in both local and global axes. { @@ -142,7 +142,7 @@ LIBeam3d2 :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) void -LIBeam3d2 :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +LIBeam3d2::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the displacement interpolation matrix {N} of the receiver, eva- // luated at gp. { @@ -172,16 +172,16 @@ LIBeam3d2 :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) void -LIBeam3d2 :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +LIBeam3d2::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) // Returns the stiffness matrix of the receiver, expressed in the global // axes. { - StructuralElement :: computeStiffnessMatrix(answer, rMode, tStep); + StructuralElement::computeStiffnessMatrix(answer, rMode, tStep); } bool -LIBeam3d2 :: computeGtoLRotationMatrix(FloatMatrix &answer) +LIBeam3d2::computeGtoLRotationMatrix(FloatMatrix &answer) { answer.resize(12, 12); answer.zero(); @@ -199,7 +199,7 @@ LIBeam3d2 :: computeGtoLRotationMatrix(FloatMatrix &answer) } } } else { - this->updateTempTriad( domain->giveEngngModel()->giveCurrentStep() ); + this->updateTempTriad(domain->giveEngngModel()->giveCurrentStep() ); for ( int i = 1; i <= 3; i++ ) { for ( int j = 1; j <= 3; j++ ) { @@ -216,7 +216,7 @@ LIBeam3d2 :: computeGtoLRotationMatrix(FloatMatrix &answer) double -LIBeam3d2 :: computeVolumeAround(GaussPoint *gp) +LIBeam3d2::computeVolumeAround(GaussPoint *gp) // Returns the length of the receiver. This method is valid only if 1 // Gauss point is used. { @@ -226,14 +226,14 @@ LIBeam3d2 :: computeVolumeAround(GaussPoint *gp) void -LIBeam3d2 :: giveDofManDofIDMask(int inode, IntArray &answer) const +LIBeam3d2::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u, D_v, D_w, R_u, R_v, R_w}; + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; } int -LIBeam3d2 :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +LIBeam3d2::computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { double ksi, n1, n2; @@ -242,37 +242,43 @@ LIBeam3d2 :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoo n2 = ( 1. + ksi ) * 0.5; answer.resize(3); - answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 *this->giveNode(2)->giveCoordinate(1); - answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 *this->giveNode(2)->giveCoordinate(2); - answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 *this->giveNode(2)->giveCoordinate(3); + answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 * this->giveNode(2)->giveCoordinate(1); + answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 * this->giveNode(2)->giveCoordinate(2); + answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 * this->giveNode(2)->giveCoordinate(3); return 1; } void -LIBeam3d2 :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +LIBeam3d2::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give3dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give3dBeamStiffMtrx(rMode, gp, tStep); +} + +void +LIBeam3d2::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + OOFEM_ERROR("computeConstitutiveMatrix_dPdF_At Not implemented"); } void -LIBeam3d2 :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +LIBeam3d2::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Beam3d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Beam3d(strain, gp, tStep); } int -LIBeam3d2 :: testElementExtension(ElementExtension ext) +LIBeam3d2::testElementExtension(ElementExtension ext) { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } double -LIBeam3d2 :: computeLength() +LIBeam3d2::computeLength() // Returns the length of the receiver. { double dx, dy, dz; @@ -291,16 +297,11 @@ LIBeam3d2 :: computeLength() } -IRResultType -LIBeam3d2 :: initializeFrom(InputRecord *ir) +void +LIBeam3d2::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - // first call parent - result = NLStructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + NLStructuralElement::initializeFrom(ir); IR_GIVE_FIELD(ir, referenceNode, _IFT_LIBeam3d2_refnode); if ( referenceNode == 0 ) { @@ -318,13 +319,11 @@ LIBeam3d2 :: initializeFrom(InputRecord *ir) FloatMatrix lcs; this->giveLocalCoordinateSystem(lcs); this->tc.beTranspositionOf(lcs); - - return IRRT_OK; } void -LIBeam3d2 :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +LIBeam3d2::giveEdgeDofMapping(IntArray &answer, int iEdge) const { /* * provides dof mapping of local edge dofs (only nonzero are taken into account) @@ -343,7 +342,7 @@ LIBeam3d2 :: giveEdgeDofMapping(IntArray &answer, int iEdge) const double -LIBeam3d2 :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +LIBeam3d2::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { if ( iEdge != 1 ) { // edge between nodes 1 2 OOFEM_ERROR("wrong egde number"); @@ -355,7 +354,7 @@ LIBeam3d2 :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) int -LIBeam3d2 :: computeLoadGToLRotationMtrx(FloatMatrix &answer) +LIBeam3d2::computeLoadGToLRotationMtrx(FloatMatrix &answer) { /* * Returns transformation matrix from global coordinate system to local @@ -383,16 +382,16 @@ LIBeam3d2 :: computeLoadGToLRotationMtrx(FloatMatrix &answer) void -LIBeam3d2 :: computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) +LIBeam3d2::computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) { FloatArray lc(1); - NLStructuralElement :: computeBodyLoadVectorAt(answer, load, tStep, mode); - answer.times( this->giveCrossSection()->give(CS_Area, lc, this) ); + NLStructuralElement::computeBodyLoadVectorAt(answer, load, tStep, mode); + answer.times(this->giveCrossSection()->give(CS_Area, lc, this) ); } int -LIBeam3d2 :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +LIBeam3d2::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -407,7 +406,7 @@ LIBeam3d2 :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gaus int -LIBeam3d2 :: giveLocalCoordinateSystem(FloatMatrix &answer) +LIBeam3d2::giveLocalCoordinateSystem(FloatMatrix &answer) // // returns a unit vectors of local coordinate system at element // stored rowwise (mainly used by some materials with ortho and anisotrophy) @@ -444,7 +443,7 @@ LIBeam3d2 :: giveLocalCoordinateSystem(FloatMatrix &answer) void -LIBeam3d2 :: updateTempTriad(TimeStep *tStep) +LIBeam3d2::updateTempTriad(TimeStep *tStep) { // test if not previously done if ( tStep->giveSolutionStateCounter() == tempTcCounter ) { @@ -473,7 +472,7 @@ LIBeam3d2 :: updateTempTriad(TimeStep *tStep) void -LIBeam3d2 :: computeRotMtrx(FloatMatrix &answer, FloatArray &psi) +LIBeam3d2::computeRotMtrx(FloatMatrix &answer, FloatArray &psi) { FloatMatrix S(3, 3), SS(3, 3); double psiSize; @@ -503,7 +502,7 @@ LIBeam3d2 :: computeRotMtrx(FloatMatrix &answer, FloatArray &psi) void -LIBeam3d2 :: computeSMtrx(FloatMatrix &answer, FloatArray &vec) +LIBeam3d2::computeSMtrx(FloatMatrix &answer, FloatArray &vec) { if ( vec.giveSize() != 3 ) { OOFEM_ERROR("vec param size mismatch"); @@ -522,7 +521,7 @@ LIBeam3d2 :: computeSMtrx(FloatMatrix &answer, FloatArray &vec) void -LIBeam3d2 :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +LIBeam3d2::computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { FloatArray ui, PrevEpsilon; FloatMatrix b; @@ -544,7 +543,7 @@ LIBeam3d2 :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *t double -LIBeam3d2 :: giveCurrentLength(TimeStep *tStep) +LIBeam3d2::giveCurrentLength(TimeStep *tStep) // Returns the length of the receiver. { double dx, dy, dz; @@ -563,10 +562,10 @@ LIBeam3d2 :: giveCurrentLength(TimeStep *tStep) } -void LIBeam3d2 :: updateYourself(TimeStep *tStep) +void LIBeam3d2::updateYourself(TimeStep *tStep) // Updates the receiver at end of step. { - NLStructuralElement :: updateYourself(tStep); + NLStructuralElement::updateYourself(tStep); // update triad this->updateTempTriad(tStep); @@ -580,57 +579,41 @@ void LIBeam3d2 :: updateYourself(TimeStep *tStep) void -LIBeam3d2 :: initForNewStep() +LIBeam3d2::initForNewStep() // initializes receiver to new time step or can be used // if current time step must be restarted { - NLStructuralElement :: initForNewStep(); + NLStructuralElement::initForNewStep(); tempTc = tc; } -contextIOResultType LIBeam3d2 :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full element context (saves state variables, that completely describe -// current state) -// +void LIBeam3d2::saveContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - if ( ( iores = NLStructuralElement :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + NLStructuralElement::saveContext(stream, mode); if ( ( iores = tc.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType LIBeam3d2 :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full element context (saves state variables, that completely describe -// current state) -// +void LIBeam3d2::restoreContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - if ( ( iores = NLStructuralElement :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + NLStructuralElement::restoreContext(stream, mode); if ( ( iores = tc.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } void -LIBeam3d2 :: FiberedCrossSectionInterface_computeStrainVectorInFiber(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *slaveGp, TimeStep *tStep) +LIBeam3d2::FiberedCrossSectionInterface_computeStrainVectorInFiber(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *slaveGp, TimeStep *tStep) { double layerYCoord, layerZCoord; @@ -646,10 +629,10 @@ LIBeam3d2 :: FiberedCrossSectionInterface_computeStrainVectorInFiber(FloatArray Interface * -LIBeam3d2 :: giveInterface(InterfaceType interface) +LIBeam3d2::giveInterface(InterfaceType interface) { if ( interface == FiberedCrossSectionInterfaceType ) { - return static_cast< FiberedCrossSectionInterface * >(this); + return static_cast< FiberedCrossSectionInterface * >( this ); } return NULL; @@ -658,7 +641,7 @@ LIBeam3d2 :: giveInterface(InterfaceType interface) #ifdef __OOFEG void -LIBeam3d2 :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +LIBeam3d2::drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { GraphicObj *go; @@ -667,9 +650,9 @@ LIBeam3d2 :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } // if (!go) { // create new one - WCRec p [ 2 ]; /* poin */ + WCRec p[ 2 ]; /* poin */ EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); + EASValsSetColor(gc.getElementColor() ); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); @@ -685,7 +668,7 @@ LIBeam3d2 :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) void -LIBeam3d2 :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +LIBeam3d2::drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) { GraphicObj *go; @@ -695,13 +678,13 @@ LIBeam3d2 :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Unkn double defScale = gc.getDefScale(); // if (!go) { // create new one - WCRec p [ 2 ]; /* poin */ + WCRec p[ 2 ]; /* poin */ char const *colors[] = { "red", "green", "blue" }; EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(2, tStep, defScale); @@ -725,11 +708,11 @@ LIBeam3d2 :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Unkn // draw t1 for ( i = 1; i <= 3; i++ ) { - p [ 1 ].x = p [ 0 ].x + coeff *tc.at(1, i); - p [ 1 ].y = p [ 0 ].y + coeff *tc.at(2, i); - p [ 1 ].z = p [ 0 ].z + coeff *tc.at(3, i); + p [ 1 ].x = p [ 0 ].x + coeff * tc.at(1, i); + p [ 1 ].y = p [ 0 ].y + coeff * tc.at(2, i); + p [ 1 ].z = p [ 0 ].z + coeff * tc.at(3, i); - EASValsSetColor( ColorGetPixelFromString(const_cast< char * >(colors [ i - 1 ]), & succ) ); + EASValsSetColor(ColorGetPixelFromString(const_cast< char * >( colors [ i - 1 ] ), & succ) ); go = CreateLine3D(p); EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); @@ -739,9 +722,9 @@ LIBeam3d2 :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Unkn void -LIBeam3d2 :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) +LIBeam3d2::drawScalar(oofegGraphicContext &gc, TimeStep *tStep) { - WCRec p [ 2 ]; + WCRec p[ 2 ]; GraphicObj *go; FloatArray v; double defScale; @@ -780,14 +763,14 @@ LIBeam3d2 :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) gc.updateFringeTableMinMax(& s, 1); go = CreateLine3D(p); - EASValsSetColor( gc.getElementColor() ); + EASValsSetColor(gc.getElementColor() ); EASValsSetLayer(OOFEG_VARPLOT_PATTERN_LAYER); EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); EMAddGraphicsToModel(ESIModel(), go); EASValsSetMType(FILLED_CIRCLE_MARKER); - go = CreateMarkerWD3D( p, v.at(1) ); + go = CreateMarkerWD3D(p, v.at(1) ); EGWithMaskChangeAttributes(LAYER_MASK | FILL_MASK | MTYPE_MASK, go); EMAddGraphicsToModel(ESIModel(), go); } diff --git a/src/sm/Elements/Beams/libeam3d2.h b/src/sm/Elements/Beams/libeam3d2.h index aae22d774..6411fa42c 100644 --- a/src/sm/Elements/Beams/libeam3d2.h +++ b/src/sm/Elements/Beams/libeam3d2.h @@ -35,8 +35,8 @@ #ifndef libeam3d2_h #define libeam3d2_h -#include "../sm/Elements/nlstructuralelement.h" -#include "../sm/CrossSections/fiberedcs.h" +#include "sm/Elements/nlstructuralelement.h" +#include "sm/CrossSections/fiberedcs.h" ///@name Input fields for LIBeam3d2 //@{ @@ -71,74 +71,76 @@ class LIBeam3d2 : public NLStructuralElement, public FiberedCrossSectionInterfac StateCounterType tempTcCounter; public: - LIBeam3d2(int n, Domain * d); + LIBeam3d2(int n, Domain *d); virtual ~LIBeam3d2() { } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; - virtual int testElementExtension(ElementExtension ext); + int testElementExtension(ElementExtension ext) override; - virtual int computeNumberOfDofs() { return 12; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual double computeVolumeAround(GaussPoint *gp); - virtual int giveLocalCoordinateSystem(FloatMatrix &answer); - virtual void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + int computeNumberOfDofs() override { return 12; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + double computeVolumeAround(GaussPoint *gp) override; + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); // Fibered cross section support functions void FiberedCrossSectionInterface_computeStrainVectorInFiber(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *slaveGp, TimeStep *tStep); + GaussPoint *slaveGp, TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LIBeam3d2_Name; } - virtual const char *giveClassName() const { return "LIBeam3d2"; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } + const char *giveInputRecordName() const override { return _IFT_LIBeam3d2_Name; } + const char *giveClassName() const override { return "LIBeam3d2"; } + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual MaterialMode giveMaterialMode() { return _3dBeam; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + MaterialMode giveMaterialMode() override { return _3dBeam; } protected: // edge load support - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeGaussPoints(); - virtual double computeLength(); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeGaussPoints() override; + double computeLength() override; // nonlinearity void updateTempTriad(TimeStep *tStep); void computeSMtrx(FloatMatrix &answer, FloatArray &vec); void computeRotMtrx(FloatMatrix &answer, FloatArray &psi); double giveCurrentLength(TimeStep *tStep); - void initForNewStep(); + void initForNewStep() override; }; } // end namespace oofem #endif // libeam3d2_h diff --git a/src/sm/Elements/Beams/libeam3dboundary.C b/src/sm/Elements/Beams/libeam3dboundary.C new file mode 100644 index 000000000..1578ad6ca --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundary.C @@ -0,0 +1,392 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/Beams/libeam3dboundary.h" +#include "sm/Materials/structuralms.h" +#include "node.h" +#include "material.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Element(LIBeam3dBoundary); + +LIBeam3dBoundary :: LIBeam3dBoundary(int n, Domain *aDomain) : LIBeam3d(n, aDomain) + // Constructor. +{ + numberOfDofMans = 3; + referenceNode = 0; + length = 0.; +} + + +void +LIBeam3dBoundary :: initializeFrom(InputRecord &ir) +{ + LIBeam3d :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, referenceNode, _IFT_LIBeam3dBoundary_refnode); + if ( referenceNode == 0 ) { + OOFEM_ERROR("wrong reference node specified"); + } + + IR_GIVE_FIELD(ir, location, _IFT_LIBeam3dBoundary_location); +} + + +void +LIBeam3dBoundary :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 3 ) { + answer = { E_xx, E_xy, E_xz, E_yx, E_yy, E_yz, E_zx, E_zy, E_zz }; + } else { + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; + } +} + + +void +LIBeam3dBoundary :: giveSwitches(IntArray &answer, int location) { + answer.resize(3); + int counter = 1; + for ( int x = -1; x < 2; x++ ) { + for ( int y = -1; y < 2; y++ ) { + for ( int z = -1; z < 2; z++ ) { + if ( !( z == 0 && y == 0 && x == 0 ) ) { + if ( counter == location ) { + answer(0) = x; + answer(1) = y; + answer(2) = z; + } + counter++; + } + } + } + } + return; +} + + +void +LIBeam3dBoundary :: recalculateCoordinates(int nodeNumber, FloatArray &coords) +{ + FloatArray unitCellSize; + unitCellSize.resize(3); + unitCellSize.at(1) = this->giveNode(3)->giveCoordinate(1); + unitCellSize.at(2) = this->giveNode(3)->giveCoordinate(2); + unitCellSize.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray switches; + this->giveSwitches(switches, this->location.at(nodeNumber) ); + + coords.resize(3); + coords.at(1) = this->giveNode(nodeNumber)->giveCoordinate(1) + switches.at(1) * unitCellSize.at(1); + coords.at(2) = this->giveNode(nodeNumber)->giveCoordinate(2) + switches.at(2) * unitCellSize.at(2); + coords.at(3) = this->giveNode(nodeNumber)->giveCoordinate(3) + switches.at(3) * unitCellSize.at(3); + + return; +} + + +double +LIBeam3dBoundary :: computeLength() +// Returns the length of the receiver. +{ + double dx, dy, dz; + FloatArray nodeA, nodeB; + + if ( length == 0. ) { + recalculateCoordinates(1, nodeA); + recalculateCoordinates(2, nodeB); + dx = nodeB.at(1) - nodeA.at(1); + dy = nodeB.at(2) - nodeA.at(2); + dz = nodeB.at(3) - nodeA.at(3); + length = sqrt(dx * dx + dy * dy + dz * dz); + } + + return length; +} + + +int +LIBeam3dBoundary :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ + double ksi, n1, n2; + FloatArray coordsNodeA, coordsNodeB; + + ksi = lcoords.at(1); + n1 = ( 1. - ksi ) * 0.5; + n2 = ( 1. + ksi ) * 0.5; + recalculateCoordinates(1, coordsNodeA); + recalculateCoordinates(2, coordsNodeB); + + answer.resize(3); + answer.at(1) = n1 * coordsNodeA.at(1) + n2 * coordsNodeB.at(1); + answer.at(2) = n1 * coordsNodeA.at(2) + n2 * coordsNodeB.at(2); + answer.at(3) = n1 * coordsNodeA.at(3) + n2 * coordsNodeB.at(3); + + return 1; +} + + +int +LIBeam3dBoundary :: giveLocalCoordinateSystem(FloatMatrix &answer) +// +// returns a unit vectors of local coordinate system at element +// stored rowwise (mainly used by some materials with ortho and anisotrophy) +// +{ + FloatArray lx(3), ly(3), lz(3), help(3); + double length = this->computeLength(); + Node *refNode; + FloatArray coordsNodeA, coordsNodeB; + + answer.resize(3, 3); + answer.zero(); + refNode = this->giveReferenceNode(referenceNode); + recalculateCoordinates(1, coordsNodeA); + recalculateCoordinates(2, coordsNodeB); + + for ( int i = 1; i <= 3; i++ ) { + lx.at(i) = ( coordsNodeB.at(i) - coordsNodeA.at(i) ) / length; + help.at(i) = ( refNode->giveCoordinate(i) - coordsNodeA.at(i) ); + } + + lz.beVectorProductOf(lx, help); + lz.normalize(); + ly.beVectorProductOf(lz, lx); + ly.normalize(); + + for ( int i = 1; i <= 3; i++ ) { + answer.at(1, i) = lx.at(i); + answer.at(2, i) = ly.at(i); + answer.at(3, i) = lz.at(i); + } + + return 1; +} + + +bool +LIBeam3dBoundary :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + + answer.resize(this->computeNumberOfDofs(), this->computeNumberOfDofs() ); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + answer.at(i + 6, j + 6) = lcs.at(i, j); + answer.at(i + 9, j + 9) = lcs.at(i, j); + } + } + //do not rotate extra DOFs + for ( int i = 13; i <= this->computeNumberOfDofs(); i++ ) { + for ( int j = 13; j <= this->computeNumberOfDofs(); j++ ) { + if ( i == j ) { + answer.at(i, j) = 1.; + } + } + } + return true; +} + + +void +LIBeam3dBoundary :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +// Returns the stiffness matrix of the receiver, expressed in the global +// axes. +{ + //get the raw stiffness matrix in local cs + FloatMatrix Korig, GtoL, R, Rt, T, Tt, TtK; + StructuralElement :: computeStiffnessMatrix(Korig, rMode, tStep); + + //rotate to global cs + this->giveRotationMatrix(GtoL); + R.beSubMatrixOf(GtoL, 1, 12, 1, 12); + Korig.rotatedWith(R); + + //transform + this->computeTransformationMatrix(T, tStep); + Tt.beTranspositionOf(T); + TtK.beProductOf(Tt, Korig); + answer.beProductOf(TtK, T); + + //rotate back to local cs + Rt.beTranspositionOf(GtoL); + answer.rotatedWith(Rt); +} + + +void +LIBeam3dBoundary :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + FloatArray unitCellSize; + unitCellSize.resize(3); + unitCellSize.at(1) = this->giveNode(3)->giveCoordinate(1); + unitCellSize.at(2) = this->giveNode(3)->giveCoordinate(2); + unitCellSize.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray switches1, switches2; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + + FloatMatrix k1, k2; + k1.resize(6, 9); + k2.resize(6, 9); + + for ( int i = 1; i <= 3; i++ ) { + k1.at(i, 3 * i - 2) = unitCellSize.at(1) * switches1.at(1); + k1.at(i, 3 * i - 1) = unitCellSize.at(2) * switches1.at(2); + k1.at(i, 3 * i) = unitCellSize.at(3) * switches1.at(3); + } + + for ( int i = 1; i <= 3; i++ ) { + k2.at(i, 3 * i - 2) = unitCellSize.at(1) * switches2.at(1); + k2.at(i, 3 * i - 1) = unitCellSize.at(2) * switches2.at(2); + k2.at(i, 3 * i) = unitCellSize.at(3) * switches2.at(3); + } + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 21); + + answer.assemble(k1, { 1, 2, 3, 4, 5, 6 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21 }); + answer.assemble(k2, { 7, 8, 9, 10, 11, 12 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21 }); +} + + +void +LIBeam3dBoundary :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +{ + FloatArray u, uG, dispVecG, dispVecL; + FloatMatrix B, T, GtoL, GtoLT, R; + this->computeVectorOf(VM_Total, tStep, u); + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + //rotate to global + this->giveRotationMatrix(GtoL); + GtoLT.beTranspositionOf(GtoL); + R.beSubMatrixOf(GtoL, 1, 12, 1, 12); + uG.beProductOf(GtoLT, u); + //transform + this->computeTransformationMatrix(T, tStep); + dispVecG.beProductOf(T, uG); + //rotate to local + dispVecL.beProductOf(R, dispVecG); + + this->computeBmatrixAt(gp, B); + answer.beProductOf(B, dispVecL); +} + + +void +LIBeam3dBoundary :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + FloatMatrix B, T, Tt, GtoL, R, Rt; + FloatArray vStress, vStrain, fintsub, fintG, fintGT; + + //get the raw internal force vector in local cs + answer.clear(); + fintsub.resize(12); + + for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) { + this->computeBmatrixAt(gp, B); + + if ( useUpdatedGpRecord == 1 ) { + StructuralMaterialStatus *matStat = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); + vStress = matStat->giveStressVector(); + } else { + if ( !this->isActivated(tStep) ) { + vStrain.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); + vStrain.zero(); + } + this->computeStrainVector(vStrain, gp, tStep); + this->computeStressVector(vStress, vStrain, gp, tStep); + } + + // Compute nodal internal forces at nodes as f = B^T*Stress dV + double dV = this->computeVolumeAround(gp); + + if ( vStress.giveSize() == 6 ) { + FloatArray stressTemp; + StructuralMaterial :: giveReducedSymVectorForm(stressTemp, vStress, gp->giveMaterialMode() ); + fintsub.plusProduct(B, stressTemp, dV); + } else { + fintsub.plusProduct(B, vStress, dV); + } + } + + //rotate to global cs + this->giveRotationMatrix(GtoL); + R.beSubMatrixOf(GtoL, 1, 12, 1, 12); + Rt.beTranspositionOf(R); + fintG.beProductOf(Rt, fintsub); + //transform + this->computeTransformationMatrix(T, tStep); + Tt.beTranspositionOf(T); + fintGT.beProductOf(Tt, fintG); + //rotate back to local cs + answer.beProductOf(GtoL, fintGT); +} + + +int +LIBeam3dBoundary :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +{ + if ( type == IST_DisplacementVector ) { + FloatArray u; + FloatMatrix N; + this->computeVectorOf(VM_Total, tStep, u); + u.resizeWithValues(12); + this->computeNmatrixAt(gp->giveSubPatchCoordinates(), N); //no special treatment needed for this interpolation + answer.beProductOf(N, u); + return 1; + } + return LIBeam3d :: giveIPValue(answer, gp, type, tStep); +} +} // end namespace oofem diff --git a/src/sm/Elements/Beams/libeam3dboundary.h b/src/sm/Elements/Beams/libeam3dboundary.h new file mode 100644 index 000000000..b41afa6db --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundary.h @@ -0,0 +1,94 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef libeam3dboundary_h +#define libeam3dboundary_h + +#include "sm/Elements/Beams/libeam3d.h" +#include "sm/CrossSections/fiberedcs.h" +#include "nodalaveragingrecoverymodel.h" + +///@name Input fields for LIBeam3dBoundary +//@{ +#define _IFT_LIBeam3dBoundary_Name "libeam3dboundary" +#define _IFT_LIBeam3dBoundary_refnode "refnode" +#define _IFT_LIBeam3dBoundary_location "location" +//@} + +namespace oofem { +/** + * This class implements a boundary version of the 3-dimensional mindlin theory Linear Isoparametric + * beam element, with reduced integration. Useful for prescribing periodicity in multiscale analyses. + * MACROSCOPIC INPUT: DEFORMATION GRADIENT TENSOR (3D, 9 COMPONENTS: Exx Exy Exz Eyx Eyy Eyz Ezx Ezy Ezz) + * + * @author: Adam Sciegaj + */ +class LIBeam3dBoundary : public LIBeam3d +{ +protected: + double length; + int referenceNode; + IntArray location; + +public: + LIBeam3dBoundary(int n, Domain *d); + virtual ~LIBeam3dBoundary() { } + + void initializeFrom(InputRecord &ir) override; + + int computeNumberOfDofs() override { return 21; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + + void recalculateCoordinates(int nodeNumber, FloatArray &coords) override; + const IntArray giveLocation() override { return location; }; + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_LIBeam3dBoundary_Name; } + const char *giveClassName() const override { return "LIBeam3dBoundary"; } + +protected: + virtual void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep); + void giveSwitches(IntArray &answer, int location); + double computeLength() override; + + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; +}; +} // end namespace oofem +#endif // libeam3dboundary_h diff --git a/src/sm/Elements/Beams/libeam3dboundarybeam.C b/src/sm/Elements/Beams/libeam3dboundarybeam.C new file mode 100644 index 000000000..427f7e0fc --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundarybeam.C @@ -0,0 +1,111 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/Beams/libeam3dboundarybeam.h" +#include "sm/Materials/structuralms.h" +#include "node.h" +#include "material.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Element(LIBeam3dBoundaryBeam); + +LIBeam3dBoundaryBeam :: LIBeam3dBoundaryBeam(int n, Domain *aDomain) : LIBeam3dBoundary(n, aDomain) + // Constructor. +{} + + +void +LIBeam3dBoundaryBeam :: initializeFrom(InputRecord &ir) +{ + LIBeam3dBoundary :: initializeFrom(ir); +} + + +void +LIBeam3dBoundaryBeam :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 3 ) { + answer = { E_xx, E_zx, K_xx }; + } else { + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; + } +} + + +void +LIBeam3dBoundaryBeam :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + double unitCellSize; + unitCellSize = this->giveNode(3)->giveCoordinate(1); + + IntArray switches1, switches2; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + + FloatMatrix k1, k2; + k1.resize(6, 3); + k2.resize(6, 3); + + k1.at(1, 1) = unitCellSize * switches1.at(1); + k1.at(1, 3) = -this->giveNode(1)->giveCoordinate(3) * unitCellSize * switches1.at(1); + k1.at(3, 2) = unitCellSize * switches1.at(1); + + //Peter: Add the rules for rotational DOFs (around) y-axes + //rotation around y-axis + k1.at(5, 3) = -unitCellSize *switches1.at(1); + + k2.at(1, 1) = unitCellSize * switches2.at(1); + k2.at(1, 3) = -this->giveNode(2)->giveCoordinate(3) * unitCellSize * switches2.at(1); + k2.at(3, 2) = unitCellSize * switches2.at(1); + + //Peter: Add the rules for rotational DOFs (around) y-axes + //rotation around y-axis + k2.at(5, 3) = -unitCellSize *switches2.at(1); + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 15); + + answer.assemble(k1, { 1, 2, 3, 4, 5, 6 }, { 13, 14, 15 }); + answer.assemble(k2, { 7, 8, 9, 10, 11, 12 }, { 13, 14, 15 }); +} +} // end namespace oofem diff --git a/src/sm/Elements/Beams/libeam3dboundarybeam.h b/src/sm/Elements/Beams/libeam3dboundarybeam.h new file mode 100644 index 000000000..6eae262f8 --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundarybeam.h @@ -0,0 +1,75 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef libeam3dboundarybeam_h +#define libeam3dboundarybeam_h + +#include "sm/Elements/Beams/libeam3dboundary.h" + +///@name Input fields for LIBeam3dBoundaryBeam +//@{ +#define _IFT_LIBeam3dBoundaryBeam_Name "libeam3dboundarybeam" +//@} + +namespace oofem { +/** + * This class implements a boundary version of the 3-dimensional mindlin theory Linear Isoparametric + * beam element, with reduced integration. Useful for prescribing periodicity in multiscale analyses. + * MACROSCOPIC INPUT: DEFORMATIONS AND CURVATURE (BEAM, 3 COMPONENTS: Exx Ezx Kxx) + * Exx = du/dx - axial strain + * Ezx = dw/dx - slope + * Kxx = d^2(w)/dx^2 (Euler-Bernoulli) or d(phi)/dx (Timoshenko) - curvature + * + * @author: Adam Sciegaj + */ +class LIBeam3dBoundaryBeam : public LIBeam3dBoundary +{ +public: + LIBeam3dBoundaryBeam(int n, Domain *d); + virtual ~LIBeam3dBoundaryBeam() { } + + void initializeFrom(InputRecord &ir) override; + + int computeNumberOfDofs() override { return 15; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_LIBeam3dBoundaryBeam_Name; } + const char *giveClassName() const override { return "LIBeam3dBoundaryBeam"; } + +protected: + void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) override; +}; +} // end namespace oofem +#endif // libeam3dboundarybeam_h diff --git a/src/sm/Elements/Beams/libeam3dboundarymembrane.C b/src/sm/Elements/Beams/libeam3dboundarymembrane.C new file mode 100644 index 000000000..afa65c2bd --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundarymembrane.C @@ -0,0 +1,107 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/Beams/libeam3dboundarymembrane.h" +#include "sm/Materials/structuralms.h" +#include "node.h" +#include "material.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Element(LIBeam3dBoundaryMembrane); + +LIBeam3dBoundaryMembrane :: LIBeam3dBoundaryMembrane(int n, Domain *aDomain) : LIBeam3dBoundary(n, aDomain) + // Constructor. +{} + + +void +LIBeam3dBoundaryMembrane :: initializeFrom(InputRecord &ir) +{ + LIBeam3dBoundary :: initializeFrom(ir); +} + + +void +LIBeam3dBoundaryMembrane :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 3 ) { + answer = { E_xx, E_xy, E_yx, E_yy }; + } else { + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; + } +} + + +void +LIBeam3dBoundaryMembrane :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + FloatArray unitCellSize; + unitCellSize.resize(2); + unitCellSize.at(1) = this->giveNode(3)->giveCoordinate(1); + unitCellSize.at(2) = this->giveNode(3)->giveCoordinate(2); + + IntArray switches1, switches2; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + + FloatMatrix k1, k2; + k1.resize(6, 4); + k2.resize(6, 4); + + k1.at(1, 1) = unitCellSize.at(1) * switches1.at(1); + k1.at(1, 2) = unitCellSize.at(2) * switches1.at(2); + k1.at(2, 3) = unitCellSize.at(1) * switches1.at(1); + k1.at(2, 4) = unitCellSize.at(2) * switches1.at(2); + + k2.at(1, 1) = unitCellSize.at(1) * switches2.at(1); + k2.at(1, 2) = unitCellSize.at(2) * switches2.at(2); + k2.at(2, 3) = unitCellSize.at(1) * switches2.at(1); + k2.at(2, 4) = unitCellSize.at(2) * switches2.at(2); + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 16); + + answer.assemble(k1, { 1, 2, 3, 4, 5, 6 }, { 13, 14, 15, 16 }); + answer.assemble(k2, { 7, 8, 9, 10, 11, 12 }, { 13, 14, 15, 16 }); +} +} // end namespace oofem diff --git a/src/sm/Elements/Beams/libeam3dboundarymembrane.h b/src/sm/Elements/Beams/libeam3dboundarymembrane.h new file mode 100644 index 000000000..5cd0a9cc1 --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundarymembrane.h @@ -0,0 +1,72 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef libeam3dboundarymembrane_h +#define libeam3dboundarymembrane_h + +#include "sm/Elements/Beams/libeam3dboundary.h" + +///@name Input fields for LIBeam3dBoundaryMembrane +//@{ +#define _IFT_LIBeam3dBoundaryMembrane_Name "libeam3dboundarymembrane" +//@} + +namespace oofem { +/** + * This class implements a boundary version of the 3-dimensional mindlin theory Linear Isoparametric + * beam element, with reduced integration. Useful for prescribing periodicity in multiscale analyses. + * MACROSCOPIC INPUT: DEFORMATION TENSOR (2D, 4 COMPONENTS: Exx Exy Eyx Eyy) + * + * @author: Adam Sciegaj + */ +class LIBeam3dBoundaryMembrane : public LIBeam3dBoundary +{ +public: + LIBeam3dBoundaryMembrane(int n, Domain *d); + virtual ~LIBeam3dBoundaryMembrane() { } + + void initializeFrom(InputRecord &ir) override; + + int computeNumberOfDofs() override { return 16; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_LIBeam3dBoundaryMembrane_Name; } + const char *giveClassName() const override { return "LIBeam3dBoundaryMembrane"; } + +protected: + void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) override; +}; +} // end namespace oofem +#endif // libeam3dboundarymembrane_h diff --git a/src/sm/Elements/Beams/libeam3dboundaryplate.C b/src/sm/Elements/Beams/libeam3dboundaryplate.C new file mode 100644 index 000000000..0e993104b --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundaryplate.C @@ -0,0 +1,135 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/Beams/libeam3dboundaryplate.h" +#include "sm/Materials/structuralms.h" +#include "node.h" +#include "material.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Element(LIBeam3dBoundaryPlate); + +LIBeam3dBoundaryPlate :: LIBeam3dBoundaryPlate(int n, Domain *aDomain) : LIBeam3dBoundary(n, aDomain) + // Constructor. +{} + + +void +LIBeam3dBoundaryPlate :: initializeFrom(InputRecord &ir) +{ + LIBeam3dBoundary :: initializeFrom(ir); +} + + +void +LIBeam3dBoundaryPlate :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 3 ) { + answer = { E_xx, E_xy, E_yx, E_yy, E_zx, E_zy, K_xx, K_yy, K_xy, K_yx }; + } else { + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; + } +} + + +void +LIBeam3dBoundaryPlate :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + FloatArray unitCellSize; + unitCellSize.resize(2); + unitCellSize.at(1) = this->giveNode(3)->giveCoordinate(1); + unitCellSize.at(2) = this->giveNode(3)->giveCoordinate(2); + + IntArray switches1, switches2; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + + FloatMatrix k1, k2; + k1.resize(6, 10); + k2.resize(6, 10); + + k1.at(1, 1) = unitCellSize.at(1) * switches1.at(1); + k1.at(1, 2) = unitCellSize.at(2) * switches1.at(2); + k1.at(2, 3) = unitCellSize.at(1) * switches1.at(1); + k1.at(2, 4) = unitCellSize.at(2) * switches1.at(2); + k1.at(3, 5) = unitCellSize.at(1) * switches1.at(1); + k1.at(3, 6) = unitCellSize.at(2) * switches1.at(2); + k1.at(1, 7) = -( this->giveNode(1)->giveCoordinate(3) ) * unitCellSize.at(1) * switches1.at(1); + k1.at(2, 8) = -( this->giveNode(1)->giveCoordinate(3) ) * unitCellSize.at(2) * switches1.at(2); + k1.at(1, 9) = -( this->giveNode(1)->giveCoordinate(3) ) * unitCellSize.at(2) * switches1.at(2); + k1.at(2, 10) = -( this->giveNode(1)->giveCoordinate(3) ) * unitCellSize.at(1) * switches1.at(1); + + //Peter: Add the rules for rotational DOFs (around) x- and y-axes + //rotation around x-axis + k1.at(4, 8) = unitCellSize.at(2) * switches1.at(2); + k1.at(4, 10) = unitCellSize.at(1) * switches1.at(1); + //rotation around y-axis + k1.at(5, 7) = -unitCellSize.at(1) * switches1.at(1); + k1.at(5, 9) = -unitCellSize.at(2) * switches1.at(2); + + + k2.at(1, 1) = unitCellSize.at(1) * switches2.at(1); + k2.at(1, 2) = unitCellSize.at(2) * switches2.at(2); + k2.at(2, 3) = unitCellSize.at(1) * switches2.at(1); + k2.at(2, 4) = unitCellSize.at(2) * switches2.at(2); + k2.at(3, 5) = unitCellSize.at(1) * switches2.at(1); + k2.at(3, 6) = unitCellSize.at(2) * switches2.at(2); + k2.at(1, 7) = -( this->giveNode(2)->giveCoordinate(3) ) * unitCellSize.at(1) * switches2.at(1); + k2.at(2, 8) = -( this->giveNode(2)->giveCoordinate(3) ) * unitCellSize.at(2) * switches2.at(2); + k2.at(1, 9) = -( this->giveNode(2)->giveCoordinate(3) ) * unitCellSize.at(2) * switches2.at(2); + k2.at(2, 10) = -( this->giveNode(2)->giveCoordinate(3) ) * unitCellSize.at(1) * switches2.at(1); + //Peter: Add the rules for rotational DOFs (around) x- and y-axes + //rotation around x-axis + k2.at(4, 8) = unitCellSize.at(2) * switches2.at(2); + k2.at(4, 10) = unitCellSize.at(1) * switches2.at(1); + //rotation around y-axis + k2.at(5, 7) = -unitCellSize.at(1) * switches2.at(1); + k2.at(5, 9) = -unitCellSize.at(2) * switches2.at(2); + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 22); + + answer.assemble(k1, { 1, 2, 3, 4, 5, 6 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }); + answer.assemble(k2, { 7, 8, 9, 10, 11, 12 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }); +} +} // end namespace oofem diff --git a/src/sm/Elements/Beams/libeam3dboundaryplate.h b/src/sm/Elements/Beams/libeam3dboundaryplate.h new file mode 100644 index 000000000..df23ace5b --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundaryplate.h @@ -0,0 +1,78 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef libeam3dboundaryplate_h +#define libeam3dboundaryplate_h + +#include "sm/Elements/Beams/libeam3dboundary.h" + +///@name Input fields for LIBeam3dBoundaryPlate +//@{ +#define _IFT_LIBeam3dBoundaryPlate_Name "libeam3dboundaryplate" +//@} + +namespace oofem { +/** + * This class implements a boundary version of the 3-dimensional mindlin theory Linear Isoparametric + * beam element, with reduced integration. Useful for prescribing periodicity in multiscale analyses. + * MACROSCOPIC INPUT: DEFORMATIONS AND CURVATURES (PLATE, 10 COMPONENTS: Exx Exy Eyx Eyy Ezx Ezy Kxx Kyy Kxy Kyx) + * Exx = du/dx, Exy = du/dy, Eyx = dv/dx, Eyy = dv/dy (in-plane strains) + * Ezx = dw/dx, Ezy = dw/dy (slopes) + * Kxx = d^2(w)/dx^2 (Kirchhoff) or d(phi_x)/dx (Mindlin) curvature + * Kyy = d^2(w)/dy^2 (Kirchhoff) or d(phi_y)/dy (Mindlin) curvature + * Kxy = d^2(w)/dxdy (Kirchhoff) or d(phi_x)/dy (Mindlin) curvature + * Kyx = d^2(w)/dxdy (Kirchhoff) or d(phi_y)/dx (Mindlin) curvature + * + * @author: Adam Sciegaj + */ +class LIBeam3dBoundaryPlate : public LIBeam3dBoundary +{ +public: + LIBeam3dBoundaryPlate(int n, Domain *d); + virtual ~LIBeam3dBoundaryPlate() { } + + void initializeFrom(InputRecord &ir) override; + + int computeNumberOfDofs() override { return 22; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_LIBeam3dBoundaryPlate_Name; } + const char *giveClassName() const override { return "LIBeam3dBoundaryPlate"; } + +protected: + void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) override; +}; +} // end namespace oofem +#endif // libeam3dboundaryplate_h diff --git a/src/sm/Elements/Beams/libeam3dboundarytruss.C b/src/sm/Elements/Beams/libeam3dboundarytruss.C new file mode 100644 index 000000000..a5c4e3899 --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundarytruss.C @@ -0,0 +1,98 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/Beams/libeam3dboundarytruss.h" +#include "sm/Materials/structuralms.h" +#include "node.h" +#include "material.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Element(LIBeam3dBoundaryTruss); + +LIBeam3dBoundaryTruss :: LIBeam3dBoundaryTruss(int n, Domain *aDomain) : LIBeam3dBoundary(n, aDomain) + // Constructor. +{} + + +void +LIBeam3dBoundaryTruss :: initializeFrom(InputRecord &ir) +{ + LIBeam3dBoundary :: initializeFrom(ir); +} + + +void +LIBeam3dBoundaryTruss :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 3 ) { + answer = { E_xx }; + } else { + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; + } +} + + +void +LIBeam3dBoundaryTruss :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + double unitCellSize; + unitCellSize = this->giveNode(3)->giveCoordinate(1); + + IntArray switches1, switches2; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + + FloatMatrix k1, k2; + k1.resize(6, 1); + k2.resize(6, 1); + + k1.at(1, 1) = unitCellSize * switches1.at(1); + k2.at(1, 1) = unitCellSize * switches2.at(1); + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 13); + + answer.assemble(k1, { 1, 2, 3, 4, 5, 6 }, { 13 }); + answer.assemble(k2, { 7, 8, 9, 10, 11, 12 }, { 13 }); +} +} // end namespace oofem diff --git a/src/sm/Elements/Beams/libeam3dboundarytruss.h b/src/sm/Elements/Beams/libeam3dboundarytruss.h new file mode 100644 index 000000000..4b7276305 --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundarytruss.h @@ -0,0 +1,72 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef libeam3dboundarytruss_h +#define libeam3dboundarytruss_h + +#include "sm/Elements/Beams/libeam3dboundary.h" + +///@name Input fields for LIBeam3dBoundaryTruss +//@{ +#define _IFT_LIBeam3dBoundaryTruss_Name "libeam3dboundarytruss" +//@} + +namespace oofem { +/** + * This class implements a boundary version of the 3-dimensional mindlin theory Linear Isoparametric + * beam element, with reduced integration. Useful for prescribing periodicity in multiscale analyses. + * MACROSCOPIC INPUT: AXIAL STRAIN Exx (1D, 1 COMPONENT) + * + * @author: Adam Sciegaj + */ +class LIBeam3dBoundaryTruss : public LIBeam3dBoundary +{ +public: + LIBeam3dBoundaryTruss(int n, Domain *d); + virtual ~LIBeam3dBoundaryTruss() { } + + void initializeFrom(InputRecord &ir) override; + + int computeNumberOfDofs() override { return 13; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_LIBeam3dBoundaryTruss_Name; } + const char *giveClassName() const override { return "LIBeam3dBoundaryTruss"; } + +protected: + void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) override; +}; +} // end namespace oofem +#endif // libeam3dboundarytruss_h diff --git a/src/sm/Elements/Beams/libeam3dboundaryvoigt.C b/src/sm/Elements/Beams/libeam3dboundaryvoigt.C new file mode 100644 index 000000000..89ee1c124 --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundaryvoigt.C @@ -0,0 +1,112 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/Beams/libeam3dboundaryvoigt.h" +#include "sm/Materials/structuralms.h" +#include "node.h" +#include "material.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Element(LIBeam3dBoundaryVoigt); + +LIBeam3dBoundaryVoigt :: LIBeam3dBoundaryVoigt(int n, Domain *aDomain) : LIBeam3dBoundary(n, aDomain) + // Constructor. +{} + + +void +LIBeam3dBoundaryVoigt :: initializeFrom(InputRecord &ir) +{ + LIBeam3dBoundary :: initializeFrom(ir); +} + + +void +LIBeam3dBoundaryVoigt :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 3 ) { + answer = { E_xx, E_yy, E_zz, G_yz, G_xz, G_xy }; + } else { + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; + } +} + + +void +LIBeam3dBoundaryVoigt :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + FloatArray unitCellSize; + unitCellSize.resize(3); + unitCellSize.at(1) = this->giveNode(3)->giveCoordinate(1); + unitCellSize.at(2) = this->giveNode(3)->giveCoordinate(2); + unitCellSize.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray switches1, switches2; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + + FloatMatrix k1, k2; + k1.resize(6, 6); + k2.resize(6, 6); + + k1.at(1, 1) = unitCellSize.at(1) * switches1.at(1); + k1.at(1, 5) = unitCellSize.at(3) * switches1.at(3); + k1.at(1, 6) = unitCellSize.at(2) * switches1.at(2); + k1.at(2, 2) = unitCellSize.at(2) * switches1.at(2); + k1.at(2, 4) = unitCellSize.at(3) * switches1.at(3); + k1.at(3, 3) = unitCellSize.at(3) * switches1.at(3); + + k2.at(1, 1) = unitCellSize.at(1) * switches2.at(1); + k2.at(1, 5) = unitCellSize.at(3) * switches2.at(3); + k2.at(1, 6) = unitCellSize.at(2) * switches2.at(2); + k2.at(2, 2) = unitCellSize.at(2) * switches2.at(2); + k2.at(2, 4) = unitCellSize.at(3) * switches2.at(3); + k2.at(3, 3) = unitCellSize.at(3) * switches2.at(3); + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 18); + + answer.assemble(k1, { 1, 2, 3, 4, 5, 6 }, { 13, 14, 15, 16, 17, 18 }); + answer.assemble(k2, { 7, 8, 9, 10, 11, 12 }, { 13, 14, 15, 16, 17, 18 }); +} +} // end namespace oofem diff --git a/src/sm/Elements/Beams/libeam3dboundaryvoigt.h b/src/sm/Elements/Beams/libeam3dboundaryvoigt.h new file mode 100644 index 000000000..b6b70b25f --- /dev/null +++ b/src/sm/Elements/Beams/libeam3dboundaryvoigt.h @@ -0,0 +1,72 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef libeam3dboundaryvoigt_h +#define libeam3dboundaryvoigt_h + +#include "sm/Elements/Beams/libeam3dboundary.h" + +///@name Input fields for LIBeam3dBoundaryVoigt +//@{ +#define _IFT_LIBeam3dBoundaryVoigt_Name "libeam3dboundaryvoigt" +//@} + +namespace oofem { +/** + * This class implements a boundary version of the 3-dimensional mindlin theory Linear Isoparametric + * beam element, with reduced integration. Useful for prescribing periodicity in multiscale analyses. + * MACROSCOPIC INPUT: STRAIN TENSOR (3D, 6 COMPONENTS, VOIGT NOTATION: Exx Eyy Ezz Gyz Gxz Gxy) + * + * @author: Adam Sciegaj + */ +class LIBeam3dBoundaryVoigt : public LIBeam3dBoundary +{ +public: + LIBeam3dBoundaryVoigt(int n, Domain *d); + virtual ~LIBeam3dBoundaryVoigt() { } + + void initializeFrom(InputRecord &ir) override; + + int computeNumberOfDofs() override { return 18; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_LIBeam3dBoundaryVoigt_Name; } + const char *giveClassName() const override { return "LIBeam3dBoundaryVoigt"; } + +protected: + void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) override; +}; +} // end namespace oofem +#endif // libeam3dboundaryvoigt_h diff --git a/src/sm/Elements/Beams/libeam3dnl.C b/src/sm/Elements/Beams/libeam3dnl.C index 160b6b858..5352c6475 100644 --- a/src/sm/Elements/Beams/libeam3dnl.C +++ b/src/sm/Elements/Beams/libeam3dnl.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Beams/libeam3dnl.h" -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/Beams/libeam3dnl.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralms.h" #include "node.h" #include "material.h" #include "gausspoint.h" @@ -53,7 +53,7 @@ namespace oofem { REGISTER_Element(LIBeam3dNL); -LIBeam3dNL :: LIBeam3dNL(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), tc(3, 3), tempTc(3, 3) //, kappa (3) +LIBeam3dNL::LIBeam3dNL(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), tc(3, 3), tempTc(3, 3) //, kappa (3) { numberOfDofMans = 2; l0 = 0.; @@ -65,7 +65,7 @@ LIBeam3dNL :: LIBeam3dNL(int n, Domain *aDomain) : NLStructuralElement(n, aDomai void -LIBeam3dNL :: computeSMtrx(FloatMatrix &answer, FloatArray &vec) +LIBeam3dNL::computeSMtrx(FloatMatrix &answer, FloatArray &vec) { if ( vec.giveSize() != 3 ) { OOFEM_ERROR("vec param size mismatch"); @@ -84,7 +84,7 @@ LIBeam3dNL :: computeSMtrx(FloatMatrix &answer, FloatArray &vec) void -LIBeam3dNL :: computeRotMtrx(FloatMatrix &answer, FloatArray &psi) +LIBeam3dNL::computeRotMtrx(FloatMatrix &answer, FloatArray &psi) { FloatMatrix S(3, 3), SS(3, 3); double psiSize; @@ -114,7 +114,7 @@ LIBeam3dNL :: computeRotMtrx(FloatMatrix &answer, FloatArray &psi) void -LIBeam3dNL :: updateTempTriad(TimeStep *tStep) +LIBeam3dNL::updateTempTriad(TimeStep *tStep) { // test if not previously done if ( tStep->giveSolutionStateCounter() == tempTcCounter ) { @@ -143,7 +143,7 @@ LIBeam3dNL :: updateTempTriad(TimeStep *tStep) void -LIBeam3dNL :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +LIBeam3dNL::computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { FloatArray xd(3), eps(3), curv(3); @@ -171,7 +171,7 @@ LIBeam3dNL :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep * void -LIBeam3dNL :: computeXMtrx(FloatMatrix &answer, TimeStep *tStep) +LIBeam3dNL::computeXMtrx(FloatMatrix &answer, TimeStep *tStep) { FloatArray xd(3); FloatMatrix s(3, 3); @@ -196,7 +196,7 @@ LIBeam3dNL :: computeXMtrx(FloatMatrix &answer, TimeStep *tStep) void -LIBeam3dNL :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +LIBeam3dNL::giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); FloatArray nm(6), stress, strain; @@ -207,7 +207,7 @@ LIBeam3dNL :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int this->updateTempTriad(tStep); if ( useUpdatedGpRecord == 1 ) { - stress = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); + stress = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); } else { this->computeStrainVector(strain, gp, tStep); this->computeStressVector(stress, strain, gp, tStep); @@ -230,7 +230,7 @@ LIBeam3dNL :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int void -LIBeam3dNL :: computeXdVector(FloatArray &answer, TimeStep *tStep) +LIBeam3dNL::computeXdVector(FloatArray &answer, TimeStep *tStep) { FloatArray u(3); @@ -248,7 +248,7 @@ LIBeam3dNL :: computeXdVector(FloatArray &answer, TimeStep *tStep) void -LIBeam3dNL :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +LIBeam3dNL::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { double s1, s2; FloatMatrix d, x, xt(12, 6), dxt, sn, sm, sxd, y; @@ -334,27 +334,22 @@ LIBeam3dNL :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, void -LIBeam3dNL :: computeGaussPoints() +LIBeam3dNL::computeGaussPoints() // Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } } -IRResultType -LIBeam3dNL :: initializeFrom(InputRecord *ir) +void +LIBeam3dNL::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - // first call parent - result = NLStructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + NLStructuralElement::initializeFrom(ir); IR_GIVE_FIELD(ir, referenceNode, _IFT_LIBeam3dNL_refnode); if ( referenceNode == 0 ) { @@ -376,13 +371,12 @@ LIBeam3dNL :: initializeFrom(InputRecord *ir) FloatMatrix lcs; this->giveLocalCoordinateSystem(lcs); this->tc.beTranspositionOf(lcs); - - return IRRT_OK; + this->nlGeometry = 0; // element always nonlinear, this is to force ouput in strains and stresses in GP (see structuralms.C) } double -LIBeam3dNL :: computeLength() +LIBeam3dNL::computeLength() // Returns the original length (l0) of the receiver. { double dx, dy, dz; @@ -402,7 +396,7 @@ LIBeam3dNL :: computeLength() void -LIBeam3dNL :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +LIBeam3dNL::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. This expression is // valid in both local and global axes. { @@ -414,19 +408,20 @@ LIBeam3dNL :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = halfMass; answer.at(7, 7) = answer.at(8, 8) = answer.at(9, 9) = halfMass; - double Ik, Iy, Iz; - Ik = this->giveCrossSection()->give(CS_TorsionMomentX, gp); + double Irr, Iy, Iz; Iy = this->giveCrossSection()->give(CS_InertiaMomentY, gp); Iz = this->giveCrossSection()->give(CS_InertiaMomentZ, gp); + Irr = Iy + Iz; + halfMass = density * this->computeLength() / 2.; - answer.at(4, 4) = answer.at(10, 10) = Ik * halfMass; + answer.at(4, 4) = answer.at(10, 10) = Irr * halfMass; answer.at(5, 5) = answer.at(11, 11) = Iy * halfMass; answer.at(6, 6) = answer.at(12, 12) = Iz * halfMass; } void -LIBeam3dNL :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +LIBeam3dNL::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the displacement interpolation matrix {N} of the receiver, eva- // luated at gp. { @@ -461,7 +456,7 @@ LIBeam3dNL :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) double -LIBeam3dNL :: computeVolumeAround(GaussPoint *gp) +LIBeam3dNL::computeVolumeAround(GaussPoint *gp) // Returns the length of the receiver. This method is valid only if 1 // Gauss point is used. { @@ -471,10 +466,10 @@ LIBeam3dNL :: computeVolumeAround(GaussPoint *gp) int -LIBeam3dNL :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +LIBeam3dNL::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - ///@todo This should be a common inheritance for all 3d beams (and a similar one for 2D beams) - /// to support all the sensible moment/force tensors. + ///@todo This should be a common inheritance for all 3d beams (and a similar one for 2D beams) + /// to support all the sensible moment/force tensors. if ( type == IST_BeamForceMomentTensor ) { answer = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); return 1; @@ -482,20 +477,20 @@ LIBeam3dNL :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType answer = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); return 1; } else { - return StructuralElement :: giveIPValue(answer, gp, type, tStep); + return StructuralElement::giveIPValue(answer, gp, type, tStep); } } void -LIBeam3dNL :: giveDofManDofIDMask(int inode, IntArray &answer) const +LIBeam3dNL::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u, D_v, D_w, R_u, R_v, R_w}; + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; } int -LIBeam3dNL :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +LIBeam3dNL::computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { double ksi, n1, n2; @@ -504,30 +499,36 @@ LIBeam3dNL :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lco n2 = ( 1. + ksi ) * 0.5; answer.resize(3); - answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 *this->giveNode(2)->giveCoordinate(1); - answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 *this->giveNode(2)->giveCoordinate(2); - answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 *this->giveNode(2)->giveCoordinate(3); + answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 * this->giveNode(2)->giveCoordinate(1); + answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 * this->giveNode(2)->giveCoordinate(2); + answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 * this->giveNode(2)->giveCoordinate(3); return 1; } void -LIBeam3dNL :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +LIBeam3dNL::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->give3dBeamStiffMtrx(rMode, gp, tStep); +} + +void +LIBeam3dNL::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give3dBeamStiffMtrx(answer, rMode, gp, tStep); + OOFEM_ERROR("computeConstitutiveMatrix_dPdF_At Not implemented for libeam2dnl"); } void -LIBeam3dNL :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +LIBeam3dNL::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Beam3d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Beam3d(strain, gp, tStep); } void -LIBeam3dNL :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +LIBeam3dNL::giveEdgeDofMapping(IntArray &answer, int iEdge) const { /* * provides dof mapping of local edge dofs (only nonzero are taken into account) @@ -545,7 +546,7 @@ LIBeam3dNL :: giveEdgeDofMapping(IntArray &answer, int iEdge) const double -LIBeam3dNL :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +LIBeam3dNL::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { if ( iEdge != 1 ) { // edge between nodes 1 2 OOFEM_ERROR("wrong egde number"); @@ -557,7 +558,7 @@ LIBeam3dNL :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) int -LIBeam3dNL :: giveLocalCoordinateSystem(FloatMatrix &answer) +LIBeam3dNL::giveLocalCoordinateSystem(FloatMatrix &answer) // // returns a unit vectors of local coordinate system at element // stored rowwise (mainly used by some materials with ortho and anisotrophy) @@ -620,7 +621,7 @@ LIBeam3dNL :: giveLocalCoordinateSystem(FloatMatrix &answer) */ int -LIBeam3dNL :: computeLoadGToLRotationMtrx(FloatMatrix &answer) +LIBeam3dNL::computeLoadGToLRotationMtrx(FloatMatrix &answer) { /* * Returns transformation matrix from global coordinate system to local @@ -649,7 +650,7 @@ LIBeam3dNL :: computeLoadGToLRotationMtrx(FloatMatrix &answer) int -LIBeam3dNL :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +LIBeam3dNL::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -664,19 +665,19 @@ LIBeam3dNL :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gau void -LIBeam3dNL :: computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) +LIBeam3dNL::computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) { FloatArray lc(1); - NLStructuralElement :: computeBodyLoadVectorAt(answer, load, tStep, mode); - answer.times( this->giveCrossSection()->give(CS_Area, lc, this) ); + NLStructuralElement::computeBodyLoadVectorAt(answer, load, tStep, mode); + answer.times(this->giveCrossSection()->give(CS_Area, lc, this) ); } -void LIBeam3dNL :: updateYourself(TimeStep *tStep) +void LIBeam3dNL::updateYourself(TimeStep *tStep) // Updates the receiver at end of step. { - NLStructuralElement :: updateYourself(tStep); + NLStructuralElement::updateYourself(tStep); // update triad this->updateTempTriad(tStep); @@ -689,17 +690,17 @@ void LIBeam3dNL :: updateYourself(TimeStep *tStep) } void -LIBeam3dNL :: initForNewStep() +LIBeam3dNL::initForNewStep() // initializes receiver to new time step or can be used // if current time step must be restarted { - NLStructuralElement :: initForNewStep(); + NLStructuralElement::initForNewStep(); tempTc = tc; } void -LIBeam3dNL :: computeTempCurv(FloatArray &answer, TimeStep *tStep) +LIBeam3dNL::computeTempCurv(FloatArray &answer, TimeStep *tStep) { IntegrationRule *iRule = this->giveDefaultIntegrationRulePtr(); GaussPoint *gp = iRule->getIntegrationPoint(0); @@ -745,7 +746,7 @@ LIBeam3dNL :: computeTempCurv(FloatArray &answer, TimeStep *tStep) #ifdef __OOFEG -void LIBeam3dNL :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +void LIBeam3dNL::drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { GraphicObj *go; @@ -754,9 +755,9 @@ void LIBeam3dNL :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } // if (!go) { // create new one - WCRec p [ 2 ]; /* poin */ + WCRec p[ 2 ]; /* poin */ EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); + EASValsSetColor(gc.getElementColor() ); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); @@ -771,7 +772,7 @@ void LIBeam3dNL :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } -void LIBeam3dNL :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +void LIBeam3dNL::drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) { GraphicObj *go; @@ -781,9 +782,9 @@ void LIBeam3dNL :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep double defScale = gc.getDefScale(); // if (!go) { // create new one - WCRec p [ 2 ]; /* poin */ + WCRec p[ 2 ]; /* poin */ EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(2, tStep, defScale); diff --git a/src/sm/Elements/Beams/libeam3dnl.h b/src/sm/Elements/Beams/libeam3dnl.h index 9e5ef926f..322491ee6 100644 --- a/src/sm/Elements/Beams/libeam3dnl.h +++ b/src/sm/Elements/Beams/libeam3dnl.h @@ -35,7 +35,7 @@ #ifndef libeam3dnl_h #define libeam3dnl_h -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/nlstructuralelement.h" ///@name Input fields for LIBeam3dNL //@{ @@ -68,62 +68,62 @@ class LIBeam3dNL : public NLStructuralElement int referenceNode; public: - LIBeam3dNL(int n, Domain * d); + LIBeam3dNL(int n, Domain *d); virtual ~LIBeam3dNL() { } - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) override { computeLumpedMassMatrix(answer, tStep); } - virtual void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; //int computeGtoLRotationMatrix(FloatMatrix &answer); //void computeInitialStressMatrix(FloatMatrix& answer, TimeStep* tStep); - virtual int computeNumberOfDofs() { return 12; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual double computeVolumeAround(GaussPoint *gp); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + int computeNumberOfDofs() override { return 12; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + double computeVolumeAround(GaussPoint *gp) override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LIBeam3dNL_Name; } - virtual const char *giveClassName() const { return "LIBeam3dNL"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } + const char *giveInputRecordName() const override { return _IFT_LIBeam3dNL_Name; } + const char *giveClassName() const override { return "LIBeam3dNL"; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; #endif - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); - - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual MaterialMode giveMaterialMode() { return _3dBeam; } + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + integrationDomain giveIntegrationDomain() const override { return _Line; } + MaterialMode giveMaterialMode() override { return _3dBeam; } protected: // edge load support - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - - virtual void updateYourself(TimeStep *tStep); - virtual void initForNewStep(); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx, int upperIndx) + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + + void updateYourself(TimeStep *tStep) override; + void initForNewStep() override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx, int upperIndx) override { OOFEM_ERROR("not implemented"); } //int computeGtoLRotationMatrix(FloatMatrix& answer); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeGaussPoints(); - virtual double computeLength(); + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeGaussPoints() override; + double computeLength() override; //double givePitch(); - virtual int giveLocalCoordinateSystem(FloatMatrix &answer); + int giveLocalCoordinateSystem(FloatMatrix &answer) override; /** * Updates the temporary triad at the centre to the state identified by given solution step. * The attribute tempTc is changed to reflect new state and tempTcCounter is set to diff --git a/src/sm/Elements/Beams/libeam3dnl2.C b/src/sm/Elements/Beams/libeam3dnl2.C index 004e126cd..b99fb62c8 100644 --- a/src/sm/Elements/Beams/libeam3dnl2.C +++ b/src/sm/Elements/Beams/libeam3dnl2.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Beams/libeam3dnl2.h" -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/Beams/libeam3dnl2.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralms.h" #include "node.h" #include "material.h" #include "gausspoint.h" @@ -54,7 +54,7 @@ namespace oofem { REGISTER_Element(LIBeam3dNL2); -LIBeam3dNL2 :: LIBeam3dNL2(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), q(4), tempQ(4) //, kappa (3) +LIBeam3dNL2::LIBeam3dNL2(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), q(4), tempQ(4) //, kappa (3) { numberOfDofMans = 2; l0 = 0.; @@ -66,7 +66,7 @@ LIBeam3dNL2 :: LIBeam3dNL2(int n, Domain *aDomain) : NLStructuralElement(n, aDom void -LIBeam3dNL2 :: computeSMtrx(FloatMatrix &answer, FloatArray &vec) +LIBeam3dNL2::computeSMtrx(FloatMatrix &answer, FloatArray &vec) { if ( vec.giveSize() != 3 ) { OOFEM_ERROR("vec param size mismatch"); @@ -85,7 +85,7 @@ LIBeam3dNL2 :: computeSMtrx(FloatMatrix &answer, FloatArray &vec) void -LIBeam3dNL2 :: computeRotMtrx(FloatMatrix &answer, FloatArray &psi) +LIBeam3dNL2::computeRotMtrx(FloatMatrix &answer, FloatArray &psi) { FloatMatrix S(3, 3), SS(3, 3); double psiSize; @@ -115,7 +115,7 @@ LIBeam3dNL2 :: computeRotMtrx(FloatMatrix &answer, FloatArray &psi) void -LIBeam3dNL2 :: updateTempQuaternion(TimeStep *tStep) +LIBeam3dNL2::updateTempQuaternion(TimeStep *tStep) { // test if not previously updated temporary quaternion if ( tStep->giveSolutionStateCounter() != tempQCounter ) { @@ -155,7 +155,7 @@ LIBeam3dNL2 :: updateTempQuaternion(TimeStep *tStep) void -LIBeam3dNL2 :: computeRotMtrxFromQuaternion(FloatMatrix &answer, FloatArray &q) +LIBeam3dNL2::computeRotMtrxFromQuaternion(FloatMatrix &answer, FloatArray &q) { answer.resize(3, 3); @@ -176,7 +176,7 @@ LIBeam3dNL2 :: computeRotMtrxFromQuaternion(FloatMatrix &answer, FloatArray &q) void -LIBeam3dNL2 :: computeQuaternionFromRotMtrx(FloatArray &answer, FloatMatrix &R) +LIBeam3dNL2::computeQuaternionFromRotMtrx(FloatArray &answer, FloatMatrix &R) { // Spurrier's algorithm @@ -215,7 +215,7 @@ LIBeam3dNL2 :: computeQuaternionFromRotMtrx(FloatArray &answer, FloatMatrix &R) kk = 2; } - answer.at(ii) = sqrt( 0.5 * a + 0.25 * ( 1. - trR ) ); + answer.at(ii) = sqrt(0.5 * a + 0.25 * ( 1. - trR ) ); answer.at(4) = 0.25 * ( R.at(kk, jj) - R.at(jj, kk) ) / answer.at(ii); answer.at(jj) = 0.25 * ( R.at(jj, ii) + R.at(ii, jj) ) / answer.at(ii); answer.at(kk) = 0.25 * ( R.at(kk, ii) + R.at(ii, kk) ) / answer.at(ii); @@ -224,7 +224,7 @@ LIBeam3dNL2 :: computeQuaternionFromRotMtrx(FloatArray &answer, FloatMatrix &R) void -LIBeam3dNL2 :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +LIBeam3dNL2::computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { FloatArray xd(3), eps(3), curv(3); FloatMatrix tempTc; @@ -254,7 +254,7 @@ LIBeam3dNL2 :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep void -LIBeam3dNL2 :: computeXMtrx(FloatMatrix &answer, TimeStep *tStep) +LIBeam3dNL2::computeXMtrx(FloatMatrix &answer, TimeStep *tStep) { FloatArray xd(3); FloatMatrix s(3, 3); @@ -279,7 +279,7 @@ LIBeam3dNL2 :: computeXMtrx(FloatMatrix &answer, TimeStep *tStep) void -LIBeam3dNL2 :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +LIBeam3dNL2::giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); FloatArray nm(6), stress, strain; @@ -314,7 +314,7 @@ LIBeam3dNL2 :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int void -LIBeam3dNL2 :: computeXdVector(FloatArray &answer, TimeStep *tStep) +LIBeam3dNL2::computeXdVector(FloatArray &answer, TimeStep *tStep) { FloatArray u(3); @@ -332,7 +332,7 @@ LIBeam3dNL2 :: computeXdVector(FloatArray &answer, TimeStep *tStep) void -LIBeam3dNL2 :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +LIBeam3dNL2::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { double s1, s2; FloatMatrix d, x, xt(12, 6), dxt, sn, sm, sxd, y, tempTc; @@ -419,41 +419,42 @@ LIBeam3dNL2 :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode void -LIBeam3dNL2 :: computeGaussPoints() +LIBeam3dNL2::computeGaussPoints() // Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } } void -LIBeam3dNL2 :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +LIBeam3dNL2::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give3dBeamStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give3dBeamStiffMtrx(rMode, gp, tStep); } - void -LIBeam3dNL2 :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +LIBeam3dNL2::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Beam3d(answer, gp, strain, tStep); + OOFEM_ERROR("computeConstitutiveMatrix_dPdF_At Not implemented"); } -IRResultType -LIBeam3dNL2 :: initializeFrom(InputRecord *ir) +void +LIBeam3dNL2::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - IRResultType result; // Required by IR_GIVE_FIELD macro + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Beam3d(strain, gp, tStep); +} + +void +LIBeam3dNL2::initializeFrom(InputRecord &ir) +{ // first call parent - result = NLStructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + NLStructuralElement::initializeFrom(ir); IR_GIVE_FIELD(ir, referenceNode, _IFT_LIBeam3dNL2_refnode); if ( referenceNode == 0 ) { @@ -477,12 +478,12 @@ LIBeam3dNL2 :: initializeFrom(InputRecord *ir) tc.beTranspositionOf(lcs); this->computeQuaternionFromRotMtrx(q, tc); - return IRRT_OK; + this->nlGeometry = 0; // element always nonlinear, this is to force ouput in strains and stresses in GP (see structuralms.C) } double -LIBeam3dNL2 :: computeLength() +LIBeam3dNL2::computeLength() // Returns the original length (l0) of the receiver. { double dx, dy, dz; @@ -502,7 +503,7 @@ LIBeam3dNL2 :: computeLength() void -LIBeam3dNL2 :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +LIBeam3dNL2::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. This expression is // valid in both local and global axes. { @@ -517,7 +518,7 @@ LIBeam3dNL2 :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) void -LIBeam3dNL2 :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +LIBeam3dNL2::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the displacement interpolation matrix {N} of the receiver, eva- // luated at gp. { @@ -552,7 +553,7 @@ LIBeam3dNL2 :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer double -LIBeam3dNL2 :: computeVolumeAround(GaussPoint *gp) +LIBeam3dNL2::computeVolumeAround(GaussPoint *gp) // Returns the length of the receiver. This method is valid only if 1 // Gauss point is used. { @@ -562,13 +563,13 @@ LIBeam3dNL2 :: computeVolumeAround(GaussPoint *gp) void -LIBeam3dNL2 :: giveDofManDofIDMask(int inode, IntArray &answer) const +LIBeam3dNL2::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u, D_v, D_w, R_u, R_v, R_w}; + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; } int -LIBeam3dNL2 :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +LIBeam3dNL2::computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { double ksi, n1, n2; @@ -577,16 +578,16 @@ LIBeam3dNL2 :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lc n2 = ( 1. + ksi ) * 0.5; answer.resize(3); - answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 *this->giveNode(2)->giveCoordinate(1); - answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 *this->giveNode(2)->giveCoordinate(2); - answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 *this->giveNode(2)->giveCoordinate(3); + answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 * this->giveNode(2)->giveCoordinate(1); + answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 * this->giveNode(2)->giveCoordinate(2); + answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 * this->giveNode(2)->giveCoordinate(3); return 1; } void -LIBeam3dNL2 :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +LIBeam3dNL2::giveEdgeDofMapping(IntArray &answer, int iEdge) const { /* * provides dof mapping of local edge dofs (only nonzero are taken into account) @@ -604,7 +605,7 @@ LIBeam3dNL2 :: giveEdgeDofMapping(IntArray &answer, int iEdge) const double -LIBeam3dNL2 :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +LIBeam3dNL2::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { if ( iEdge != 1 ) { // edge between nodes 1 2 OOFEM_ERROR("wrong egde number"); @@ -616,7 +617,7 @@ LIBeam3dNL2 :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) int -LIBeam3dNL2 :: giveLocalCoordinateSystem(FloatMatrix &answer) +LIBeam3dNL2::giveLocalCoordinateSystem(FloatMatrix &answer) // // returns a unit vectors of local coordinate system at element // stored rowwise (mainly used by some materials with ortho and anisotrophy) @@ -653,7 +654,7 @@ LIBeam3dNL2 :: giveLocalCoordinateSystem(FloatMatrix &answer) int -LIBeam3dNL2 :: computeLoadGToLRotationMtrx(FloatMatrix &answer) +LIBeam3dNL2::computeLoadGToLRotationMtrx(FloatMatrix &answer) { /* * Returns transformation matrix from global coordinate system to local @@ -682,7 +683,7 @@ LIBeam3dNL2 :: computeLoadGToLRotationMtrx(FloatMatrix &answer) int -LIBeam3dNL2 :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +LIBeam3dNL2::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -697,19 +698,19 @@ LIBeam3dNL2 :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Ga void -LIBeam3dNL2 :: computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) +LIBeam3dNL2::computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) { FloatArray lc(1); - NLStructuralElement :: computeBodyLoadVectorAt(answer, load, tStep, mode); - answer.times( this->giveCrossSection()->give(CS_Area, lc, this) ); + NLStructuralElement::computeBodyLoadVectorAt(answer, load, tStep, mode); + answer.times(this->giveCrossSection()->give(CS_Area, lc, this) ); } void -LIBeam3dNL2 :: updateYourself(TimeStep *tStep) +LIBeam3dNL2::updateYourself(TimeStep *tStep) // Updates the receiver at end of step. { - NLStructuralElement :: updateYourself(tStep); + NLStructuralElement::updateYourself(tStep); // update quaternion this->updateTempQuaternion(tStep); @@ -722,17 +723,17 @@ LIBeam3dNL2 :: updateYourself(TimeStep *tStep) } void -LIBeam3dNL2 :: initForNewStep() +LIBeam3dNL2::initForNewStep() // initializes receiver to new time step or can be used // if current time step must be restarted { - NLStructuralElement :: initForNewStep(); + NLStructuralElement::initForNewStep(); tempQ = q; } void -LIBeam3dNL2 :: computeTempCurv(FloatArray &answer, TimeStep *tStep) +LIBeam3dNL2::computeTempCurv(FloatArray &answer, TimeStep *tStep) { GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); FloatArray ui(3), ac(3), PrevEpsilon; @@ -794,7 +795,7 @@ LIBeam3dNL2 :: computeTempCurv(FloatArray &answer, TimeStep *tStep) FloatMatrix h(3, 3); ac.normalize(); om = ac; - om.times( 2. * tan(acSize / 2.) ); + om.times(2. * tan(acSize / 2.) ); coeff = ( 1. - ( acSize / sin(acSize) ) ); for ( int i = 1; i <= 3; i++ ) { @@ -838,48 +839,32 @@ LIBeam3dNL2 :: computeTempCurv(FloatArray &answer, TimeStep *tStep) } -contextIOResultType -LIBeam3dNL2 :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full element context (saves state variables, that completely describe -// current state) -// +void +LIBeam3dNL2::saveContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - if ( ( iores = NLStructuralElement :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + NLStructuralElement::saveContext(stream, mode); if ( ( iores = q.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -LIBeam3dNL2 :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full element context (saves state variables, that completely describe -// current state) -// +void +LIBeam3dNL2::restoreContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - if ( ( iores = NLStructuralElement :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + NLStructuralElement::restoreContext(stream, mode); if ( ( iores = q.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } #ifdef __OOFEG -void LIBeam3dNL2 :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +void LIBeam3dNL2::drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { GraphicObj *go; @@ -888,9 +873,9 @@ void LIBeam3dNL2 :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } // if (!go) { // create new one - WCRec p [ 2 ]; /* poin */ + WCRec p[ 2 ]; /* poin */ EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); + EASValsSetColor(gc.getElementColor() ); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); @@ -905,7 +890,7 @@ void LIBeam3dNL2 :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } -void LIBeam3dNL2 :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +void LIBeam3dNL2::drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) { GraphicObj *go; @@ -915,13 +900,13 @@ void LIBeam3dNL2 :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tSte double defScale = gc.getDefScale(); // if (!go) { // create new one - WCRec p [ 2 ]; /* poin */ + WCRec p[ 2 ]; /* poin */ const char *colors[] = { "red", "green", "blue" }; EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(2, tStep, defScale); @@ -946,11 +931,11 @@ void LIBeam3dNL2 :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tSte // draw t1 for ( i = 1; i <= 3; i++ ) { - p [ 1 ].x = p [ 0 ].x + coeff *tc.at(1, i); - p [ 1 ].y = p [ 0 ].y + coeff *tc.at(2, i); - p [ 1 ].z = p [ 0 ].z + coeff *tc.at(3, i); + p [ 1 ].x = p [ 0 ].x + coeff * tc.at(1, i); + p [ 1 ].y = p [ 0 ].y + coeff * tc.at(2, i); + p [ 1 ].z = p [ 0 ].z + coeff * tc.at(3, i); - EASValsSetColor( ColorGetPixelFromString(const_cast< char * >(colors [ i - 1 ]), & succ) ); + EASValsSetColor(ColorGetPixelFromString(const_cast< char * >( colors [ i - 1 ] ), & succ) ); go = CreateLine3D(p); EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); diff --git a/src/sm/Elements/Beams/libeam3dnl2.h b/src/sm/Elements/Beams/libeam3dnl2.h index cbf495224..0e79d3c80 100644 --- a/src/sm/Elements/Beams/libeam3dnl2.h +++ b/src/sm/Elements/Beams/libeam3dnl2.h @@ -35,7 +35,7 @@ #ifndef libeam3dnl2_h #define libeam3dnl2_h -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/nlstructuralelement.h" ///@name Input fields for LIBeam3dNL2 //@{ @@ -69,62 +69,63 @@ class LIBeam3dNL2 : public NLStructuralElement int referenceNode; public: - LIBeam3dNL2(int n, Domain * d); + LIBeam3dNL2(int n, Domain *d); virtual ~LIBeam3dNL2() { } - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) override { computeLumpedMassMatrix(answer, tStep); } - virtual void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; - virtual int computeNumberOfDofs() { return 12; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual double computeVolumeAround(GaussPoint *gp); + int computeNumberOfDofs() override { return 12; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + double computeVolumeAround(GaussPoint *gp) override; - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LIBeam3dNL2_Name; } - virtual const char *giveClassName() const { return "LIBeam3dNL2"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } + const char *giveInputRecordName() const override { return _IFT_LIBeam3dNL2_Name; } + const char *giveClassName() const override { return "LIBeam3dNL2"; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; #endif - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual MaterialMode giveMaterialMode() { return _3dBeam; } + integrationDomain giveIntegrationDomain() const override { return _Line; } + MaterialMode giveMaterialMode() override { return _3dBeam; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; protected: // edge load support - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - - virtual void updateYourself(TimeStep *tStep); - virtual void initForNewStep(); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int, int) + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + + void updateYourself(TimeStep *tStep) override; + void initForNewStep() override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int, int) override { OOFEM_ERROR("not implemented"); } //int computeGtoLRotationMatrix(FloatMatrix& answer); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeGaussPoints(); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeGaussPoints() override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; - virtual double computeLength(); + double computeLength() override; //double givePitch (); - virtual int giveLocalCoordinateSystem(FloatMatrix &answer); + int giveLocalCoordinateSystem(FloatMatrix &answer) override; /** * Updates the temporary triad at the centre to the state identified by given solution step. diff --git a/src/sm/Elements/3D/qspacegrad.C b/src/sm/Elements/GradientDamage/3D/qspacegraddamage.C similarity index 74% rename from src/sm/Elements/3D/qspacegrad.C rename to src/sm/Elements/GradientDamage/3D/qspacegraddamage.C index 6746c2239..227e83d19 100644 --- a/src/sm/Elements/3D/qspacegrad.C +++ b/src/sm/Elements/GradientDamage/3D/qspacegraddamage.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/3D/qspacegrad.h" +#include "../sm/Elements/GradientDamage/3D/qspacegraddamage.h" #include "fei3dhexalin.h" #include "gausspoint.h" #include "gaussintegrationrule.h" @@ -43,11 +43,11 @@ #include "classfactory.h" namespace oofem { -REGISTER_Element(QSpaceGrad); +REGISTER_Element(QSpaceGradDamage); -FEI3dHexaLin QSpaceGrad :: interpolation_lin; +FEI3dHexaLin QSpaceGradDamage :: interpolation_lin; -QSpaceGrad :: QSpaceGrad(int n, Domain *aDomain) : QSpace(n, aDomain), GradDpElement() +QSpaceGradDamage :: QSpaceGradDamage(int n, Domain *aDomain) : QSpace(n, aDomain), GradientDamageElement() // Constructor. { nPrimNodes = 8; @@ -60,16 +60,16 @@ QSpaceGrad :: QSpaceGrad(int n, Domain *aDomain) : QSpace(n, aDomain), GradDpEl } -IRResultType -QSpaceGrad :: initializeFrom(InputRecord *ir) +void +QSpaceGradDamage :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 27; - return Structural3DElement :: initializeFrom(ir); + Structural3DElement :: initializeFrom(ir); } void -QSpaceGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const +QSpaceGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const { if ( inode <= 4 ) { answer = {D_u, D_v, D_w, G_0}; @@ -78,9 +78,30 @@ QSpaceGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const } } +void +QSpaceGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const +{ + answer = {D_u, D_v, D_w}; +} + + +void +QSpaceGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const +{ + + /* if ( inode <= 4 ) { + answer = {G_0}; + } else { + answer = {}; + } + */ +} + + + void -QSpaceGrad :: computeGaussPoints() +QSpaceGradDamage :: computeGaussPoints() // Sets up the array containing the four Gauss points of the receiver. { integrationRulesArray.resize(1); @@ -91,13 +112,13 @@ QSpaceGrad :: computeGaussPoints() void -QSpaceGrad :: computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer) +QSpaceGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) { this->interpolation_lin.evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); } void -QSpaceGrad :: computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer) +QSpaceGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) { FloatMatrix dnx; this->interpolation_lin.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); diff --git a/src/sm/Elements/3D/qspacegrad.h b/src/sm/Elements/GradientDamage/3D/qspacegraddamage.h similarity index 54% rename from src/sm/Elements/3D/qspacegrad.h rename to src/sm/Elements/GradientDamage/3D/qspacegraddamage.h index e25bec4d3..1f0009add 100644 --- a/src/sm/Elements/3D/qspacegrad.h +++ b/src/sm/Elements/GradientDamage/3D/qspacegraddamage.h @@ -32,46 +32,50 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef qspacegrad_h -#define qspacegrad_h +#ifndef qspacegraddamage_h +#define qspacegraddamage_h #include "../sm/Elements/3D/qspace.h" -#include "../sm/Elements/graddpelement.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" -#define _IFT_QSpaceGrad_Name "qspacegrad" +#define _IFT_QSpaceGradDamage_Name "qspacegraddamage" namespace oofem { class FEI3dHexaLin; /** - * Quadratic 3d 20 - node element with quadratic approximation of displacements and linear approximation of gradient + * Quadratic 3d 20 - node element with quadratic approximation of displacements and linear approximation of gradient damage driving variable * - * @author Ladislav Svoboda + * @author Martin Horak */ -class QSpaceGrad : public QSpace, public GradDpElement +class QSpaceGradDamage : public QSpace, public GradientDamageElement { protected: static FEI3dHexaLin interpolation_lin; public: - QSpaceGrad(int n, Domain * d); - virtual ~QSpaceGrad() { } + QSpaceGradDamage(int n, Domain * d); + virtual ~QSpaceGradDamage() { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + void initializeFrom(InputRecord &ir) override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QSpaceGrad_Name; } - virtual const char *giveClassName() const { return "QSpaceGrad"; } - virtual int computeNumberOfDofs() { return 68; } - virtual MaterialMode giveMaterialMode() { return _3dMat; } + const char *giveInputRecordName() const override { return _IFT_QSpaceGradDamage_Name; } + const char *giveClassName() const override { return "QSpaceGradDamage"; } + int computeNumberOfDofs() override { return 68; } + MaterialMode giveMaterialMode() override { return _3dMat; } protected: - virtual void computeGaussPoints(); - virtual void computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer); - virtual void computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual StructuralElement *giveStructuralElement() { return this; } - virtual NLStructuralElement *giveNLStructuralElement() { return this; } + void computeGaussPoints() override; + void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } + void giveLocationArray_u(IntArray &answer) override { } + void giveLocationArray_d(IntArray &answer) override { } }; } #endif // end namespace oofem diff --git a/src/sm/Elements/3D/qtrspacegrad.C b/src/sm/Elements/GradientDamage/3D/qtrspacegraddamage.C similarity index 75% rename from src/sm/Elements/3D/qtrspacegrad.C rename to src/sm/Elements/GradientDamage/3D/qtrspacegraddamage.C index eb85a3c62..d6eb0460f 100644 --- a/src/sm/Elements/3D/qtrspacegrad.C +++ b/src/sm/Elements/GradientDamage/3D/qtrspacegraddamage.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/3D/qtrspacegrad.h" +#include "../sm/Elements/GradientDamage/3D/qtrspacegraddamage.h" #include "../sm/Materials/structuralms.h" #include "../sm/CrossSections/structuralcrosssection.h" #include "fei3dtetlin.h" @@ -51,11 +51,11 @@ #include namespace oofem { -REGISTER_Element(QTRSpaceGrad); +REGISTER_Element(QTRSpaceGradDamage); -FEI3dTetLin QTRSpaceGrad :: interpolation_lin; +FEI3dTetLin QTRSpaceGradDamage :: interpolation_lin; -QTRSpaceGrad :: QTRSpaceGrad(int n, Domain *aDomain) : QTRSpace(n, aDomain), GradDpElement() +QTRSpaceGradDamage :: QTRSpaceGradDamage(int n, Domain *aDomain) : QTRSpace(n, aDomain), GradientDamageElement() // Constructor. { nPrimNodes = 10; @@ -68,16 +68,16 @@ QTRSpaceGrad :: QTRSpaceGrad(int n, Domain *aDomain) : QTRSpace(n, aDomain), Gr } -IRResultType -QTRSpaceGrad :: initializeFrom(InputRecord *ir) +void +QTRSpaceGradDamage :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 4; - return Structural3DElement :: initializeFrom(ir); + Structural3DElement :: initializeFrom(ir); } void -QTRSpaceGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const +QTRSpaceGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const { if ( inode <= 4 ) { answer = {D_u, D_v, D_w, G_0}; @@ -86,8 +86,29 @@ QTRSpaceGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const } } + +void +QTRSpaceGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const +{ + answer = {D_u, D_v, D_w}; +} + + +void +QTRSpaceGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const +{ + /* if ( inode <= 4 ) { + answer = {G_0}; + } else { + answer = {}; + } + */ + +} + + void -QTRSpaceGrad :: computeGaussPoints() +QTRSpaceGradDamage :: computeGaussPoints() // Sets up the array containing the four Gauss points of the receiver. { integrationRulesArray.resize(1); @@ -97,13 +118,13 @@ QTRSpaceGrad :: computeGaussPoints() void -QTRSpaceGrad :: computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer) +QTRSpaceGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) { this->interpolation_lin.evalN(answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); } void -QTRSpaceGrad :: computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer) +QTRSpaceGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) { FloatMatrix dnx; this->interpolation_lin.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); diff --git a/src/sm/Elements/3D/qtrspacegrad.h b/src/sm/Elements/GradientDamage/3D/qtrspacegraddamage.h similarity index 50% rename from src/sm/Elements/3D/qtrspacegrad.h rename to src/sm/Elements/GradientDamage/3D/qtrspacegraddamage.h index 8986085e6..953e0efa9 100644 --- a/src/sm/Elements/3D/qtrspacegrad.h +++ b/src/sm/Elements/GradientDamage/3D/qtrspacegraddamage.h @@ -32,48 +32,58 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef qtrspacegrad_h -#define qtrspacegrad_h +#ifndef qtrspacegraddamage_h +#define qtrspacegraddamage_h #include "../sm/Elements/3D/qtrspace.h" -#include "../sm/Elements/graddpelement.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" -#define _IFT_QTRSpaceGrad_Name "qtrspacegrad" +#define _IFT_QTRSpaceGrad_Name "qtrspacegraddamage" namespace oofem { class FEI3dTetLin; /** - * Quadratic 3D element - * @author L. Svoboda + * @author M. Horak */ -class QTRSpaceGrad : public QTRSpace, public GradDpElement + + +#define _IFT_QTRSpaceGradDamage_Name "qtrsoacegraddamage" + + + + +class QTRSpaceGradDamage : public QTRSpace, public GradientDamageElement { protected: static FEI3dTetLin interpolation_lin; public: - QTRSpaceGrad(int, Domain *); - virtual ~QTRSpaceGrad() { } + QTRSpaceGradDamage(int, Domain *); + virtual ~QTRSpaceGradDamage() { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + void initializeFrom(InputRecord &ir) override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QTRSpaceGrad_Name; } - virtual const char *giveClassName() const { return "QTRSpaceGrad"; } - virtual int computeNumberOfDofs() { return 34; } + const char *giveInputRecordName() const override { return _IFT_QTRSpaceGradDamage_Name; } + const char *giveClassName() const override { return "QTRSpaceGradDamage"; } + int computeNumberOfDofs() override { return 34; } protected: /////////////////////////////////////////////////////////////////////////////// - void computeGaussPoints(); - void computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer); - void computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer); - StructuralElement *giveStructuralElement() { return this; } - NLStructuralElement *giveNLStructuralElement() { return this; } + void computeGaussPoints() override; + void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) { GradDpElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { GradDpElement :: computeStiffnessMatrix(answer, rMode, tStep); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { GradientDamageElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { GradientDamageElement :: computeStiffnessMatrix(answer, rMode, tStep); } + void giveLocationArray_u(IntArray &answer) override { } + void giveLocationArray_d(IntArray &answer) override { } }; } #endif // end namespace oofem diff --git a/src/sm/Elements/3D/qwedgegrad.C b/src/sm/Elements/GradientDamage/3D/qwedgegraddamage.C similarity index 77% rename from src/sm/Elements/3D/qwedgegrad.C rename to src/sm/Elements/GradientDamage/3D/qwedgegraddamage.C index 606b90403..75b4ab909 100644 --- a/src/sm/Elements/3D/qwedgegrad.C +++ b/src/sm/Elements/GradientDamage/3D/qwedgegraddamage.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/3D/qwedgegrad.h" +#include "../sm/Elements/GradientDamage/3D/qwedgegraddamage.h" #include "../sm/Materials/structuralms.h" #include "../sm/CrossSections/structuralcrosssection.h" #include "fei3dwedgelin.h" @@ -51,11 +51,11 @@ #include namespace oofem { -REGISTER_Element(QWedgeGrad); +REGISTER_Element(QWedgeGradDamage); -FEI3dWedgeLin QWedgeGrad :: interpolation_lin; +FEI3dWedgeLin QWedgeGradDamage :: interpolation_lin; -QWedgeGrad :: QWedgeGrad(int n, Domain *aDomain) : QWedge(n, aDomain), GradDpElement() +QWedgeGradDamage :: QWedgeGradDamage(int n, Domain *aDomain) : QWedge(n, aDomain), GradientDamageElement() // Constructor. { nPrimNodes = 15; @@ -68,16 +68,16 @@ QWedgeGrad :: QWedgeGrad(int n, Domain *aDomain) : QWedge(n, aDomain), GradDpEl } -IRResultType -QWedgeGrad :: initializeFrom(InputRecord *ir) +void +QWedgeGradDamage :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 9; - return Structural3DElement :: initializeFrom(ir); + Structural3DElement :: initializeFrom(ir); } void -QWedgeGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const +QWedgeGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const // returns DofId mask array for inode element node. // DofId mask array determines the dof ordering requsted from node. // DofId mask array contains the DofID constants (defined in cltypes.h) @@ -90,8 +90,30 @@ QWedgeGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const } } + +void +QWedgeGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const +{ + answer = {D_u, D_v, D_w}; +} + + +void +QWedgeGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const +{ + + /* if ( inode <= 6 ) { + answer = {G_0}; + } else { + answer = {}; + } + */ +} + + + void -QWedgeGrad :: computeGaussPoints() +QWedgeGradDamage :: computeGaussPoints() // Sets up the array containing the four Gauss points of the receiver. { integrationRulesArray.resize(1); @@ -101,13 +123,13 @@ QWedgeGrad :: computeGaussPoints() void -QWedgeGrad :: computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer) +QWedgeGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) { this->interpolation_lin.evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); } void -QWedgeGrad :: computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer) +QWedgeGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) { FloatMatrix dnx; this->interpolation_lin.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); diff --git a/src/sm/Elements/GradientDamage/3D/qwedgegraddamage.h b/src/sm/Elements/GradientDamage/3D/qwedgegraddamage.h new file mode 100644 index 000000000..f228f6ee0 --- /dev/null +++ b/src/sm/Elements/GradientDamage/3D/qwedgegraddamage.h @@ -0,0 +1,83 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef qwedgegraddamage_h +#define qwedgegraddamage_h + +#include "../sm/Elements/3D/qwedge.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" + +#define _IFT_QWedgeGradDamage_Name "qwedgegraddamage" + +namespace oofem { +class FEI3dWedgeLin; + +/** + * @author M. Horak + */ +class QWedgeGradDamage : public QWedge, public GradientDamageElement +{ +protected: + static FEI3dWedgeLin interpolation_lin; + +public: + QWedgeGradDamage(int, Domain *); + virtual ~QWedgeGradDamage() { } + + void initializeFrom(InputRecord &ir) override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_QWedgeGradDamage_Name; } + const char *giveClassName() const override { return "QWedgeGradDamage"; } + int computeNumberOfDofs() override { return 51; } + MaterialMode giveMaterialMode() override { return _3dMat; } + +protected: + void computeGaussPoints() override; + void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } + + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { GradientDamageElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { GradientDamageElement :: computeStiffnessMatrix(answer, rMode, tStep); } + void giveLocationArray_u(IntArray &answer) override { } + void giveLocationArray_d(IntArray &answer) override { } + +}; +} +#endif // end namespace oofem diff --git a/src/sm/Elements/Bars/qtruss1dgrad.C b/src/sm/Elements/GradientDamage/Bars/qtruss1dgraddamage.C similarity index 67% rename from src/sm/Elements/Bars/qtruss1dgrad.C rename to src/sm/Elements/GradientDamage/Bars/qtruss1dgraddamage.C index 600a14db3..76ac3b138 100644 --- a/src/sm/Elements/Bars/qtruss1dgrad.C +++ b/src/sm/Elements/GradientDamage/Bars/qtruss1dgraddamage.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Bars/qtruss1dgrad.h" +#include "../sm/Elements/GradientDamage/Bars/qtruss1dgraddamage.h" #include "fei1dlin.h" #include "fei1dquad.h" #include "gausspoint.h" @@ -40,7 +40,7 @@ #include "floatmatrix.h" #include "floatarray.h" #include "intarray.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "crosssection.h" #include "classfactory.h" #ifdef __OOFEG @@ -48,11 +48,11 @@ #endif namespace oofem { -REGISTER_Element(QTruss1dGrad); +REGISTER_Element(QTruss1dGradDamage); -FEI1dLin QTruss1dGrad :: interpolation_lin(1); +FEI1dLin QTruss1dGradDamage :: interpolation_lin(1); -QTruss1dGrad :: QTruss1dGrad(int n, Domain *aDomain) : QTruss1d(n, aDomain), GradDpElement() +QTruss1dGradDamage :: QTruss1dGradDamage(int n, Domain *aDomain) : QTruss1d(n, aDomain), GradientDamageElement() // Constructor. { nPrimNodes = 3; @@ -66,7 +66,7 @@ QTruss1dGrad :: QTruss1dGrad(int n, Domain *aDomain) : QTruss1d(n, aDomain), Gra void -QTruss1dGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const +QTruss1dGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const { if ( inode < 3 ) { answer = {D_u, G_0}; @@ -76,22 +76,37 @@ QTruss1dGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const } -IRResultType -QTruss1dGrad :: initializeFrom(InputRecord *ir) + void +QTruss1dGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const { - return StructuralElement :: initializeFrom(ir); + answer = {D_u}; } void -QTruss1dGrad :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +QTruss1dGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const { - this->giveStructuralCrossSection()->giveStiffnessMatrix_1d(answer, rMode, gp, tStep); + /* + if ( inode <= 3 ) { + answer = {G_0}; + } else { + answer = {}; + } + */ +} + + + + +void +QTruss1dGradDamage :: initializeFrom(InputRecord &ir) +{ + StructuralElement :: initializeFrom(ir); } void -QTruss1dGrad :: computeGaussPoints() +QTruss1dGradDamage :: computeGaussPoints() { integrationRulesArray.resize( 1 ); integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 1) ); @@ -100,35 +115,35 @@ QTruss1dGrad :: computeGaussPoints() void -QTruss1dGrad :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +QTruss1dGradDamage :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { - GradDpElement :: computeStiffnessMatrix(answer, rMode, tStep); + GradientDamageElement :: computeStiffnessMatrix(answer, rMode, tStep); } void -QTruss1dGrad :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +QTruss1dGradDamage :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { - GradDpElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); + GradientDamageElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } void -QTruss1dGrad :: computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer) +QTruss1dGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) { this->interpolation_lin.evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); } void -QTruss1dGrad :: computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer) +QTruss1dGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) { FloatMatrix dnx; this->interpolation_lin.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.beTranspositionOf(dnx); } -void QTruss1dGrad :: computeField(ValueModeType mode, TimeStep* tStep, const FloatArray& lcoords, FloatArray& answer) +void QTruss1dGradDamage :: computeField(ValueModeType mode, TimeStep* tStep, const FloatArray& lcoords, FloatArray& answer) { FloatArray n, unknown; this->interpolation_lin.evalN( n, lcoords, FEIElementGeometryWrapper(this) ); diff --git a/src/sm/Elements/Bars/qtruss1dgrad.h b/src/sm/Elements/GradientDamage/Bars/qtruss1dgraddamage.h similarity index 50% rename from src/sm/Elements/Bars/qtruss1dgrad.h rename to src/sm/Elements/GradientDamage/Bars/qtruss1dgraddamage.h index 26c19dbbc..36d48d285 100644 --- a/src/sm/Elements/Bars/qtruss1dgrad.h +++ b/src/sm/Elements/GradientDamage/Bars/qtruss1dgraddamage.h @@ -32,13 +32,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef qtruss1dgrad_h -#define qtruss1dgrad_h +#ifndef qtruss1dgraddamage_h +#define qtruss1dgraddamage_h #include "../sm/Elements/Bars/qtruss1d.h" -#include "../sm/Elements/graddpelement.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" -#define _IFT_QTruss1dGrad_Name "qtruss1dgrad" +#define _IFT_QTruss1dGradDamage_Name "qtruss1dgraddamage" namespace oofem { class FEI1dLin; @@ -47,34 +47,37 @@ class FEI1dLin; * This class implements a three-node gradient truss bar element for one-dimensional * analysis. */ -class QTruss1dGrad : public QTruss1d, public GradDpElement +class QTruss1dGradDamage : public QTruss1d, public GradientDamageElement { protected: static FEI1dLin interpolation_lin; public: - QTruss1dGrad(int n, Domain * d); - virtual ~QTruss1dGrad() { } + QTruss1dGradDamage(int n, Domain * d); + virtual ~QTruss1dGradDamage() { } - virtual const char *giveInputRecordName() const { return _IFT_QTruss1dGrad_Name; } - virtual const char *giveClassName() const { return "QTruss1dGrad"; } + const char *giveInputRecordName() const override { return _IFT_QTruss1dGradDamage_Name; } + const char *giveClassName() const override { return "QTruss1dGradDamage"; } - virtual MaterialMode giveMaterialMode() { return _1dMat; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int computeNumberOfDofs() { return 5; } - - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + MaterialMode giveMaterialMode() override { return _1dMat; } + void initializeFrom(InputRecord &ir) override; + int computeNumberOfDofs() override { return 5; } protected: - virtual void computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); - virtual void computeGaussPoints(); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual StructuralElement *giveStructuralElement() { return this; } - virtual NLStructuralElement *giveNLStructuralElement() { return this; } + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + void computeGaussPoints() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; + + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } + void giveLocationArray_u(IntArray &answer) override { } + void giveLocationArray_d(IntArray &answer) override { } }; } // end namespace oofem #endif // truss1d_h diff --git a/src/sm/Elements/GradientDamage/Bars/truss1dgraddamage.C b/src/sm/Elements/GradientDamage/Bars/truss1dgraddamage.C new file mode 100644 index 000000000..88cd2693e --- /dev/null +++ b/src/sm/Elements/GradientDamage/Bars/truss1dgraddamage.C @@ -0,0 +1,165 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "../sm/Elements/GradientDamage/Bars/truss1dgraddamage.h" +#include "fei1dlin.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "crosssection.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_Element(Truss1dGradDamage); +IntArray Truss1dGradDamage :: locationArray_u = {1, 3}; +IntArray Truss1dGradDamage :: locationArray_d = {2, 4}; + + +Truss1dGradDamage :: Truss1dGradDamage(int n, Domain *aDomain) : Truss1d(n, aDomain), GradientDamageElement() + // Constructor. +{ + nPrimNodes = 2; + nPrimVars = 1; + nSecNodes = 2; + nSecVars = 1; + totalSize = nPrimVars * nPrimNodes + nSecVars * nSecNodes; + locSize = nPrimVars * nPrimNodes; + nlSize = nSecVars * nSecNodes; +} + + +void +Truss1dGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = {D_u, G_0}; +} + + +void +Truss1dGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const +{ + answer = {D_u}; +} + + +void +Truss1dGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const +{ + answer = {G_0}; + +} + + + + +void +Truss1dGradDamage :: initializeFrom(InputRecord &ir) +{ + GradientDamageElement :: initializeFrom(ir); + StructuralElement :: initializeFrom(ir); +} + + + +void +Truss1dGradDamage :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + GradientDamageElement :: computeStiffnessMatrix(answer, rMode, tStep); +} + + +void +Truss1dGradDamage :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + GradientDamageElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); +} + + +void +Truss1dGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) +{ + this->interp.evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); +} + + +void +Truss1dGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) +{ + FloatMatrix dnx; + this->interp.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + answer.beTranspositionOf(dnx); +} + +void +Truss1dGradDamage :: computeField(ValueModeType mode, TimeStep* tStep, const FloatArray& lcoords, FloatArray& answer) +{ + FloatArray n, unknown; + this->interp.evalN( n, lcoords, FEIElementGeometryWrapper(this) ); + this->computeVectorOf({D_u}, mode, tStep, unknown); + answer.at(1) = n.dotProduct(unknown); + + this->interp.evalN( n, lcoords, FEIElementGeometryWrapper(this) ); + this->computeVectorOf({G_0}, mode, tStep, unknown); + answer.at(2) = n.dotProduct(unknown); +} + + + + +void +Truss1dGradDamage :: giveLocationArray_u(IntArray &answer) +{ + answer = locationArray_u; +} + + +void +Truss1dGradDamage :: giveLocationArray_d(IntArray &answer) +{ + answer = locationArray_d; +} + + +void +Truss1dGradDamage :: postInitialize() +{ + GradientDamageElement:: postInitialize(); + NLStructuralElement :: postInitialize(); +} + + +} diff --git a/src/sm/Elements/GradientDamage/Bars/truss1dgraddamage.h b/src/sm/Elements/GradientDamage/Bars/truss1dgraddamage.h new file mode 100644 index 000000000..dee5d15a7 --- /dev/null +++ b/src/sm/Elements/GradientDamage/Bars/truss1dgraddamage.h @@ -0,0 +1,86 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef truss1dgraddamage_h +#define truss1dgraddamage_h + + +#include "../sm/Elements/Bars/truss1d.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" + +#define _IFT_Truss1dGradDamage_Name "truss1dgraddamage" + +namespace oofem { +class FEI1dLin; + +/** + * This class implements a two-node truss bar element for one-dimensional + * analysis. + */ + class Truss1dGradDamage : public Truss1d, public GradientDamageElement +{ +protected: + static IntArray locationArray_u; + static IntArray locationArray_d; +public: + Truss1dGradDamage(int n, Domain * d); + virtual ~Truss1dGradDamage() {;} + + const char *giveInputRecordName() const override { return _IFT_Truss1dGradDamage_Name; } + const char *giveClassName() const override { return "Truss1dGradDamage"; } + + MaterialMode giveMaterialMode() override { return _1dMat; } + void initializeFrom(InputRecord &ir) override; + int computeNumberOfDofs() override { return 4; } + +protected: + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; + + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } + void giveLocationArray_u(IntArray &answer) override; + void giveLocationArray_d(IntArray &answer) override; + void postInitialize() override; + + +}; +} // end namespace oofem +#endif // truss1dgraddamage_h diff --git a/src/sm/Elements/PlaneStrain/qplanestraingrad.C b/src/sm/Elements/GradientDamage/PlaneStrain/qplanestraingraddamage.C similarity index 73% rename from src/sm/Elements/PlaneStrain/qplanestraingrad.C rename to src/sm/Elements/GradientDamage/PlaneStrain/qplanestraingraddamage.C index d0161d8af..257329fcb 100644 --- a/src/sm/Elements/PlaneStrain/qplanestraingrad.C +++ b/src/sm/Elements/GradientDamage/PlaneStrain/qplanestraingraddamage.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStrain/qplanestraingrad.h" +#include "../sm/Elements/GradientDamage/PlaneStrain/qplanestraingraddamage.h" #include "fei2dquadlin.h" #include "gausspoint.h" #include "gaussintegrationrule.h" @@ -47,11 +47,11 @@ #endif namespace oofem { -REGISTER_Element(QPlaneStrainGrad); +REGISTER_Element(QPlaneStrainGradDamage); -FEI2dQuadLin QPlaneStrainGrad :: interpolation_lin(1, 2); +FEI2dQuadLin QPlaneStrainGradDamage :: interpolation_lin(1, 2); -QPlaneStrainGrad :: QPlaneStrainGrad(int n, Domain *aDomain) : QPlaneStrain(n, aDomain), GradDpElement() +QPlaneStrainGradDamage :: QPlaneStrainGradDamage(int n, Domain *aDomain) : QPlaneStrain(n, aDomain), GradientDamageElement() // Constructor. { nPrimNodes = 8; @@ -65,7 +65,7 @@ QPlaneStrainGrad :: QPlaneStrainGrad(int n, Domain *aDomain) : QPlaneStrain(n, a void -QPlaneStrainGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const +QPlaneStrainGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const { if ( inode <= 4 ) { @@ -76,14 +76,35 @@ QPlaneStrainGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const } -IRResultType -QPlaneStrainGrad :: initializeFrom(InputRecord *ir) +void +QPlaneStrainGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const +{ + answer = {D_u, D_v}; +} + + +void +QPlaneStrainGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const +{ + /* + if ( inode <= 4 ) { + answer = {G_0}; + } else { + answer = {}; + } + */ +} + + + +void +QPlaneStrainGradDamage :: initializeFrom(InputRecord &ir) { - return QPlaneStrain :: initializeFrom(ir); + QPlaneStrain :: initializeFrom(ir); } void -QPlaneStrainGrad :: computeGaussPoints() +QPlaneStrainGradDamage :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); @@ -93,13 +114,13 @@ QPlaneStrainGrad :: computeGaussPoints() } void -QPlaneStrainGrad :: computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer) +QPlaneStrainGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) { this->interpolation_lin.evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); } void -QPlaneStrainGrad :: computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer) +QPlaneStrainGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) { FloatMatrix dnx; this->interpolation_lin.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); diff --git a/src/sm/Elements/GradientDamage/PlaneStrain/qplanestraingraddamage.h b/src/sm/Elements/GradientDamage/PlaneStrain/qplanestraingraddamage.h new file mode 100644 index 000000000..596fa48e7 --- /dev/null +++ b/src/sm/Elements/GradientDamage/PlaneStrain/qplanestraingraddamage.h @@ -0,0 +1,80 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef qplanestraingraddamage_h +#define qplanestraingraddamage_h + +#include "../sm/Elements/PlaneStrain/qplanestrain.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" + +#define _IFT_QPlaneStrainGradDamage_Name "qplanestraingraddamage" + +namespace oofem { +class FEI2dQuadLin; + +class QPlaneStrainGradDamage : public QPlaneStrain, public GradientDamageElement +{ +protected: + static FEI2dQuadLin interpolation_lin; + +public: + QPlaneStrainGradDamage(int n, Domain * d); + virtual ~QPlaneStrainGradDamage() { } + + void initializeFrom(InputRecord &ir) override; + + const char *giveInputRecordName() const override { return _IFT_QPlaneStrainGradDamage_Name; } + const char *giveClassName() const override { return "QPlaneStrainGradDamage"; } + + MaterialMode giveMaterialMode() override { return _PlaneStrain; } + int computeNumberOfDofs() override { return 20; } + +protected: + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { GradientDamageElement :: computeStiffnessMatrix(answer, rMode, tStep); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { GradientDamageElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + + void computeGaussPoints() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; + + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } + void giveLocationArray_u(IntArray &answer) override { } + void giveLocationArray_d(IntArray &answer) override { } +}; +} // end namespace oofem +#endif // qplanestraingrad_h diff --git a/src/sm/Elements/PlaneStrain/qtrplanestraingrad.C b/src/sm/Elements/GradientDamage/PlaneStrain/qtrplanestraingraddamage.C similarity index 69% rename from src/sm/Elements/PlaneStrain/qtrplanestraingrad.C rename to src/sm/Elements/GradientDamage/PlaneStrain/qtrplanestraingraddamage.C index 145776de8..3bcf61d49 100644 --- a/src/sm/Elements/PlaneStrain/qtrplanestraingrad.C +++ b/src/sm/Elements/GradientDamage/PlaneStrain/qtrplanestraingraddamage.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStrain/qtrplanestraingrad.h" +#include "../sm/Elements/GradientDamage/PlaneStrain/qtrplanestraingraddamage.h" #include "fei2dtrlin.h" #include "node.h" #include "gausspoint.h" @@ -47,9 +47,9 @@ namespace oofem { -FEI2dTrLin QTrPlaneStrainGrad :: interpolation_lin(1, 2); +FEI2dTrLin QTrPlaneStrainGradDamage :: interpolation_lin(1, 2); -QTrPlaneStrainGrad :: QTrPlaneStrainGrad(int n, Domain *aDomain) : QTrPlaneStrain(n, aDomain), GradDpElement() +QTrPlaneStrainGradDamage :: QTrPlaneStrainGradDamage(int n, Domain *aDomain) : QTrPlaneStrain(n, aDomain), GradientDamageElement() { nPrimNodes = 6; nPrimVars = 2; @@ -62,7 +62,7 @@ QTrPlaneStrainGrad :: QTrPlaneStrainGrad(int n, Domain *aDomain) : QTrPlaneStrai void -QTrPlaneStrainGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const +QTrPlaneStrainGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const { if ( inode <= 3 ) { answer = {D_u, D_v, G_0}; @@ -71,15 +71,39 @@ QTrPlaneStrainGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const } } -IRResultType -QTrPlaneStrainGrad :: initializeFrom(InputRecord *ir) + + +void +QTrPlaneStrainGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const +{ + answer = {D_u, D_v}; +} + + +void +QTrPlaneStrainGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const +{ + /* + if ( inode <= 3 ) { + answer = {G_0}; + } else { + answer = {}; + } + */ +} + + + + +void +QTrPlaneStrainGradDamage :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 4; - return QTrPlaneStrain :: initializeFrom(ir); + QTrPlaneStrain :: initializeFrom(ir); } void -QTrPlaneStrainGrad :: computeGaussPoints() +QTrPlaneStrainGradDamage :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); @@ -89,13 +113,15 @@ QTrPlaneStrainGrad :: computeGaussPoints() } void -QTrPlaneStrainGrad :: computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer) +QTrPlaneStrainGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatMatrix &answer) { - this->interpolation_lin.evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + FloatArray n; + this->interpolation_lin.evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + answer.beNMatrixOf(n, 1); } void -QTrPlaneStrainGrad :: computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer) +QTrPlaneStrainGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) { FloatMatrix dnx; this->interpolation_lin.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); diff --git a/src/sm/Elements/PlaneStrain/qtrplanestraingrad.h b/src/sm/Elements/GradientDamage/PlaneStrain/qtrplanestraingraddamage.h similarity index 51% rename from src/sm/Elements/PlaneStrain/qtrplanestraingrad.h rename to src/sm/Elements/GradientDamage/PlaneStrain/qtrplanestraingraddamage.h index 98cac195e..f8a0f9c86 100644 --- a/src/sm/Elements/PlaneStrain/qtrplanestraingrad.h +++ b/src/sm/Elements/GradientDamage/PlaneStrain/qtrplanestraingraddamage.h @@ -32,40 +32,43 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef qtrplanestraingrad_h -#define qtrplanestraingrad_h +#ifndef qtrplanestraingraddamage_h +#define qtrplanestraingraddamage_h #include "../sm/Elements/PlaneStrain/qtrplanestrain.h" -#include "../sm/Elements/graddpelement.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" namespace oofem { class FEI2dTrLin; -class QTrPlaneStrainGrad : public QTrPlaneStrain, public GradDpElement +class QTrPlaneStrainGradDamage : public QTrPlaneStrain, public GradientDamageElement { protected: static FEI2dTrLin interpolation_lin; public: - QTrPlaneStrainGrad(int n, Domain * d); - virtual ~QTrPlaneStrainGrad() { } + QTrPlaneStrainGradDamage(int n, Domain * d); + virtual ~QTrPlaneStrainGradDamage() { } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - //virtual const char *giveInputRecordName() const { return _IFT_QtrPlaneStrainGrad_Name; } - virtual const char *giveClassName() const { return "QTrPlaneStrainGrad"; } + //const char *giveInputRecordName() const override { return _IFT_QtrPlaneStrainGradDamage_Name; } + const char *giveClassName() const override { return "QTrPlaneStrainGrad"; } protected: - virtual void computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { GradDpElement :: computeStiffnessMatrix(answer, rMode, tStep); } - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) { GradDpElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeNdMatrixAt(GaussPoint *gp, FloatMatrix &answer); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { GradientDamageElement :: computeStiffnessMatrix(answer, rMode, tStep); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { GradientDamageElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } - virtual int computeNumberOfDofs() { return 15; } - virtual void computeGaussPoints(); - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual StructuralElement *giveStructuralElement() { return this; } - virtual NLStructuralElement *giveNLStructuralElement() { return this; } + int computeNumberOfDofs() override { return 15; } + void computeGaussPoints() override; + void giveDofManDofIDMask(int inode, IntArray &) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; + + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } }; } // end namespace oofem #endif // qtrplanestraingrad_h diff --git a/src/sm/Elements/GradientDamage/PlaneStrain/quad1planestraingraddamage.C b/src/sm/Elements/GradientDamage/PlaneStrain/quad1planestraingraddamage.C new file mode 100644 index 000000000..dcac89298 --- /dev/null +++ b/src/sm/Elements/GradientDamage/PlaneStrain/quad1planestraingraddamage.C @@ -0,0 +1,140 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "Elements/GradientDamage/PlaneStrain/quad1planestraingraddamage.h" +#include "fei2dquadlin.h" +#include "node.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "classfactory.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" + #include "oofegutils.h" + #include "Materials/rcm2.h" +#endif + +namespace oofem { +REGISTER_Element(Quad1PlaneStrainGradDamage); + IntArray Quad1PlaneStrainGradDamage :: locationArray_u = {1, 2, 4, 5, 7, 8, 10, 11}; + IntArray Quad1PlaneStrainGradDamage :: locationArray_d = {3, 6, 9, 12}; + +Quad1PlaneStrainGradDamage :: Quad1PlaneStrainGradDamage(int n, Domain *aDomain) : Quad1PlaneStrain(n, aDomain), GradientDamageElement() +{ + nPrimNodes = 4; + nPrimVars = 2; + nSecNodes = 4; + nSecVars = 1; + totalSize = nPrimVars * nPrimNodes + nSecVars * nSecNodes; + locSize = nPrimVars * nPrimNodes; + nlSize = nSecVars * nSecNodes; + +} + + + + + + + +void +Quad1PlaneStrainGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const + +{ + answer = {D_u, D_v, G_0}; +} + + +void +Quad1PlaneStrainGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const +{ + answer = {D_u, D_v}; +} + + +void +Quad1PlaneStrainGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const +{ + answer = {G_0}; +} + + + + +void +Quad1PlaneStrainGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) +{ + this->interp.evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); +} + +void +Quad1PlaneStrainGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) +{ + FloatMatrix dnx; + this->interp.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + answer.beTranspositionOf(dnx); +} + + +void +Quad1PlaneStrainGradDamage :: giveLocationArray_u(IntArray &answer) +{ + answer = locationArray_u; +} + + +void +Quad1PlaneStrainGradDamage :: giveLocationArray_d(IntArray &answer) +{ + answer = locationArray_d; +} + +void +Quad1PlaneStrainGradDamage :: postInitialize() +{ + GradientDamageElement:: postInitialize(); + NLStructuralElement :: postInitialize(); +} + + + + +} // end namespace oofem + + diff --git a/src/sm/Elements/GradientDamage/PlaneStrain/quad1planestraingraddamage.h b/src/sm/Elements/GradientDamage/PlaneStrain/quad1planestraingraddamage.h new file mode 100644 index 000000000..6c1ffbddd --- /dev/null +++ b/src/sm/Elements/GradientDamage/PlaneStrain/quad1planestraingraddamage.h @@ -0,0 +1,80 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef quad1planestraingraddamage_h +#define quad1planestraingraddamage_h + +#include "../sm/Elements/PlaneStrain/quad1planestrain.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" + +#define _IFT_Quad1PlaneStrainGradDamage_Name "quad1planestraingraddamage" + +namespace oofem { + +class Quad1PlaneStrainGradDamage : public Quad1PlaneStrain, public GradientDamageElement +{ +protected: + static IntArray locationArray_u; + static IntArray locationArray_d; + +public: + Quad1PlaneStrainGradDamage(int n, Domain * d); + virtual ~Quad1PlaneStrainGradDamage() { } + + //void initializeFrom(InputRecord &ir) override; + + const char *giveInputRecordName() const override { return _IFT_Quad1PlaneStrainGradDamage_Name; } + const char *giveClassName() const override { return "Quad1PlaneStrainGradDamage"; } + + MaterialMode giveMaterialMode() override { return _PlaneStrain; } + int computeNumberOfDofs() override { return 12; } + +protected: + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { GradientDamageElement :: computeStiffnessMatrix(answer, rMode, tStep); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { GradientDamageElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; + + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } + void postInitialize() override; + void giveLocationArray_u(IntArray &answer) override; + void giveLocationArray_d(IntArray &answer) override; +}; +} // end namespace oofem +#endif // quad1planestraingrad_h diff --git a/src/sm/Elements/GradientDamage/PlaneStress/planestressgraddamage.C b/src/sm/Elements/GradientDamage/PlaneStress/planestressgraddamage.C new file mode 100644 index 000000000..af2a0dc8a --- /dev/null +++ b/src/sm/Elements/GradientDamage/PlaneStress/planestressgraddamage.C @@ -0,0 +1,148 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "../sm/Elements/GradientDamage/PlaneStress/planestressgraddamage.h" +#include "fei2dquadlin.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "crosssection.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Element(PlaneStressGradDamage); + + IntArray PlaneStressGradDamage :: locationArray_u = {1,2, 4,5, 7,8, 10,11}; + IntArray PlaneStressGradDamage :: locationArray_d = {3,6,9,12}; + +PlaneStressGradDamage :: PlaneStressGradDamage(int n, Domain *aDomain) : PlaneStress2d(n, aDomain), GradientDamageElement() + // Constructor. +{ + nPrimNodes = 4; + nPrimVars = 2; + nSecNodes = 4; + nSecVars = 1; + totalSize = nPrimVars * nPrimNodes + nSecVars * nSecNodes; + locSize = nPrimVars * nPrimNodes; + nlSize = nSecVars * nSecNodes; + numberOfGaussPoints = 4; +} + + +void +PlaneStressGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode <= 4 ) { + answer = {D_u, D_v, G_0}; + } else { + answer = {D_u, D_v}; + } +} + + + + void +PlaneStressGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const +{ + answer = {D_u, D_v}; +} + + +void +PlaneStressGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const +{ + answer = {G_0}; +} + + + + +void +PlaneStressGradDamage :: initializeFrom(InputRecord &ir) +{ + PlaneStress2d :: initializeFrom(ir); +} + + +void +PlaneStressGradDamage :: computeGaussPoints() +{ + if ( integrationRulesArray.size() == 0 ) { + integrationRulesArray.resize( 1 ); + integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); + } +} + +void +PlaneStressGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) +{ + this->interpolation.evalN(answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); +} + +void +PlaneStressGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) +{ + FloatMatrix dnx; + this->interpolation.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + answer.beTranspositionOf(dnx); +} + + +void +PlaneStressGradDamage :: giveLocationArray_u(IntArray &answer) +{ + answer = locationArray_u; +} + + +void +PlaneStressGradDamage :: giveLocationArray_d(IntArray &answer) +{ + answer = locationArray_d; +} + + +void +PlaneStressGradDamage :: postInitialize() +{ + GradientDamageElement:: postInitialize(); + PlaneStress2d :: postInitialize(); +} + + + +} diff --git a/src/sm/Elements/GradientDamage/PlaneStress/planestressgraddamage.h b/src/sm/Elements/GradientDamage/PlaneStress/planestressgraddamage.h new file mode 100644 index 000000000..cd2a72084 --- /dev/null +++ b/src/sm/Elements/GradientDamage/PlaneStress/planestressgraddamage.h @@ -0,0 +1,83 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef planestressgraddamage_h +#define planestressgraddamage_h + +#include "../sm/Elements/PlaneStress/planstrss.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" + +#define _IFT_PlaneStressGradDamage_Name "planestressgraddamage" + +namespace oofem { +class FEI2dQuadLin; + +class PlaneStressGradDamage : public PlaneStress2d, public GradientDamageElement +{ +protected: + static IntArray locationArray_u; + static IntArray locationArray_d; +public: + PlaneStressGradDamage(int n, Domain * d); + virtual ~PlaneStressGradDamage() { } + + void initializeFrom(InputRecord &ir) override; + + const char *giveInputRecordName() const override { return _IFT_PlaneStressGradDamage_Name; } + const char *giveClassName() const override { return "PlaneStressGradDamage"; } + MaterialMode giveMaterialMode() override { return _PlaneStress; } + int computeNumberOfDofs() override { return 12; } + +protected: + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { GradientDamageElement :: computeStiffnessMatrix(answer, rMode, tStep); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { GradientDamageElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + + void computeGaussPoints() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; + + + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } + + void giveLocationArray_u(IntArray &answer) override; + void giveLocationArray_d(IntArray &answer) override; + void postInitialize() override; + +}; +} // end namespace oofem +#endif // planestressgrad_h diff --git a/src/sm/Elements/PlaneStress/qplanestressgrad.C b/src/sm/Elements/GradientDamage/PlaneStress/qplanestressgraddamage.C similarity index 63% rename from src/sm/Elements/PlaneStress/qplanestressgrad.C rename to src/sm/Elements/GradientDamage/PlaneStress/qplanestressgraddamage.C index 2fd7dc59d..6f75319e4 100644 --- a/src/sm/Elements/PlaneStress/qplanestressgrad.C +++ b/src/sm/Elements/GradientDamage/PlaneStress/qplanestressgraddamage.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/qplanestressgrad.h" +#include "../sm/Elements/GradientDamage/PlaneStress/qplanestressgraddamage.h" #include "fei2dquadlin.h" #include "gausspoint.h" #include "gaussintegrationrule.h" @@ -43,11 +43,15 @@ #include "classfactory.h" namespace oofem { -REGISTER_Element(QPlaneStressGrad); +REGISTER_Element(QPlaneStressGradDamage); -FEI2dQuadLin QPlaneStressGrad :: interpolation_lin(1, 2); +FEI2dQuadLin QPlaneStressGradDamage :: interpolation_lin(1, 2); +IntArray QPlaneStressGradDamage :: locationArray_u = {1,2, 4,5, 7,8, 10,11, 13,14,15,16,17,18,19,20}; +IntArray QPlaneStressGradDamage :: locationArray_d = {3,6,9,12}; -QPlaneStressGrad :: QPlaneStressGrad(int n, Domain *aDomain) : QPlaneStress2d(n, aDomain), GradDpElement() + + +QPlaneStressGradDamage :: QPlaneStressGradDamage(int n, Domain *aDomain) : QPlaneStress2d(n, aDomain), GradientDamageElement() // Constructor. { nPrimNodes = 8; @@ -62,7 +66,7 @@ QPlaneStressGrad :: QPlaneStressGrad(int n, Domain *aDomain) : QPlaneStress2d(n, void -QPlaneStressGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const +QPlaneStressGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const { if ( inode <= 4 ) { answer = {D_u, D_v, G_0}; @@ -72,15 +76,38 @@ QPlaneStressGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const } -IRResultType -QPlaneStressGrad :: initializeFrom(InputRecord *ir) + + void +QPlaneStressGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const +{ + answer = {D_u, D_v}; +} + + +void +QPlaneStressGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const +{ + /* + if ( inode <= 4 ) { + answer = {G_0}; + } else { + answer = {}; + } + */ +} + + + + +void +QPlaneStressGradDamage :: initializeFrom(InputRecord &ir) { - return QPlaneStress2d :: initializeFrom(ir); + QPlaneStress2d :: initializeFrom(ir); } void -QPlaneStressGrad :: computeGaussPoints() +QPlaneStressGradDamage :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); @@ -90,16 +117,39 @@ QPlaneStressGrad :: computeGaussPoints() } void -QPlaneStressGrad :: computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer) +QPlaneStressGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) { this->interpolation_lin.evalN(answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); } void -QPlaneStressGrad :: computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer) +QPlaneStressGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) { FloatMatrix dnx; this->interpolation_lin.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.beTranspositionOf(dnx); } + +void +QPlaneStressGradDamage :: giveLocationArray_u(IntArray &answer) +{ + answer = locationArray_u; +} + + +void +QPlaneStressGradDamage :: giveLocationArray_d(IntArray &answer) +{ + answer = locationArray_d; +} + + +void +QPlaneStressGradDamage :: postInitialize() +{ + GradientDamageElement:: postInitialize(); + QPlaneStress2d :: postInitialize(); +} + + } diff --git a/src/sm/Elements/GradientDamage/PlaneStress/qplanestressgraddamage.h b/src/sm/Elements/GradientDamage/PlaneStress/qplanestressgraddamage.h new file mode 100644 index 000000000..80d4eb25e --- /dev/null +++ b/src/sm/Elements/GradientDamage/PlaneStress/qplanestressgraddamage.h @@ -0,0 +1,84 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef qplanestressgraddamage_h +#define qplanestressgraddamage_h + +#include "../sm/Elements/PlaneStress/qplanstrss.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" + +#define _IFT_QPlaneStressGradDamage_Name "qplanestressgraddamage" + +namespace oofem { +class FEI2dQuadLin; + +class QPlaneStressGradDamage : public QPlaneStress2d, public GradientDamageElement +{ +protected: + static IntArray locationArray_u; + static IntArray locationArray_d; + static FEI2dQuadLin interpolation_lin; + +public: + QPlaneStressGradDamage(int n, Domain * d); + virtual ~QPlaneStressGradDamage() { } + + void initializeFrom(InputRecord &ir) override; + + const char *giveInputRecordName() const override { return _IFT_QPlaneStressGradDamage_Name; } + const char *giveClassName() const override { return "QPlaneStressGradDamage"; } + MaterialMode giveMaterialMode() override { return _PlaneStress; } + int computeNumberOfDofs() override { return 20; } + +protected: + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { GradientDamageElement :: computeStiffnessMatrix(answer, rMode, tStep); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { GradientDamageElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + + void computeGaussPoints() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; + + + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } + void giveLocationArray_u(IntArray &answer) override; + void giveLocationArray_d(IntArray &answer) override; + void postInitialize() override; + +}; +} // end namespace oofem +#endif // qplanestressgrad_h diff --git a/src/sm/Elements/PlaneStress/qtrplstrgrad.C b/src/sm/Elements/GradientDamage/PlaneStress/qtrplstrgraddamage.C similarity index 72% rename from src/sm/Elements/PlaneStress/qtrplstrgrad.C rename to src/sm/Elements/GradientDamage/PlaneStress/qtrplstrgraddamage.C index 61d4e9487..762ac3680 100644 --- a/src/sm/Elements/PlaneStress/qtrplstrgrad.C +++ b/src/sm/Elements/GradientDamage/PlaneStress/qtrplstrgraddamage.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/PlaneStress/qtrplstrgrad.h" +#include "Elements/GradientDamage/PlaneStress/qtrplstrgraddamage.h" #include "fei2dtrlin.h" #include "gausspoint.h" #include "gaussintegrationrule.h" @@ -47,11 +47,11 @@ #endif namespace oofem { -REGISTER_Element(QTrPlaneStressGrad); +REGISTER_Element(QTrPlaneStressGradDamage); -FEI2dTrLin QTrPlaneStressGrad :: interpolation_lin(1, 2); +FEI2dTrLin QTrPlaneStressGradDamage :: interpolation_lin(1, 2); -QTrPlaneStressGrad :: QTrPlaneStressGrad(int n, Domain *aDomain) : QTrPlaneStress2d(n, aDomain), GradDpElement() +QTrPlaneStressGradDamage :: QTrPlaneStressGradDamage(int n, Domain *aDomain) : QTrPlaneStress2d(n, aDomain), GradientDamageElement() // Constructor. { nPrimNodes = 6; @@ -66,7 +66,7 @@ QTrPlaneStressGrad :: QTrPlaneStressGrad(int n, Domain *aDomain) : QTrPlaneStres void -QTrPlaneStressGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const +QTrPlaneStressGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const { if ( inode <= 3 ) { @@ -77,15 +77,38 @@ QTrPlaneStressGrad :: giveDofManDofIDMask(int inode, IntArray &answer) const } -IRResultType -QTrPlaneStressGrad :: initializeFrom(InputRecord *ir) + void +QTrPlaneStressGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const { - return QTrPlaneStress2d :: initializeFrom(ir); + answer = {D_u, D_v}; } void -QTrPlaneStressGrad :: computeGaussPoints() +QTrPlaneStressGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const +{ + /* + if ( inode <= 3 ) { + answer = {G_0}; + } else { + answer = {}; + } + */ +} + + + + + +void +QTrPlaneStressGradDamage :: initializeFrom(InputRecord &ir) +{ + QTrPlaneStress2d :: initializeFrom(ir); +} + + +void +QTrPlaneStressGradDamage :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); @@ -95,13 +118,13 @@ QTrPlaneStressGrad :: computeGaussPoints() } void -QTrPlaneStressGrad :: computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer) +QTrPlaneStressGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) { this->interpolation_lin.evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); } void -QTrPlaneStressGrad :: computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer) +QTrPlaneStressGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) { FloatMatrix dnx; this->interpolation_lin.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); diff --git a/src/sm/Elements/GradientDamage/PlaneStress/qtrplstrgraddamage.h b/src/sm/Elements/GradientDamage/PlaneStress/qtrplstrgraddamage.h new file mode 100644 index 000000000..ca5ca11f5 --- /dev/null +++ b/src/sm/Elements/GradientDamage/PlaneStress/qtrplstrgraddamage.h @@ -0,0 +1,80 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef qtrplstrgraddamage_h +#define qtrplstrgraddamage_h + +#include "../sm/Elements/PlaneStress/qtrplstr.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" + +#define _IFT_QTrPlaneStressGradDamage_Name "qtrplstrgraddamage" + +namespace oofem { +class FEI2dTrLin; + +class QTrPlaneStressGradDamage : public QTrPlaneStress2d, public GradientDamageElement +{ +protected: + static FEI2dTrLin interpolation_lin; + +public: + QTrPlaneStressGradDamage(int n, Domain * d); + virtual ~QTrPlaneStressGradDamage() { } + + void initializeFrom(InputRecord &ir) override; + + const char *giveInputRecordName() const override { return _IFT_QTrPlaneStressGradDamage_Name; } + const char *giveClassName() const override { return "QTrPlaneStressGradDamage"; } + + MaterialMode giveMaterialMode() override { return _PlaneStress; } + int computeNumberOfDofs() override { return 15; } + +protected: + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { GradientDamageElement :: computeStiffnessMatrix(answer, rMode, tStep); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { GradientDamageElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + + void computeGaussPoints() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; + + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } + void giveLocationArray_u(IntArray &answer) override { } + void giveLocationArray_d(IntArray &answer) override { } +}; +} // end namespace oofem +#endif // qtrplstrgrad_h diff --git a/src/sm/Elements/GradientDamage/PlaneStress/trplstrgraddamage.C b/src/sm/Elements/GradientDamage/PlaneStress/trplstrgraddamage.C new file mode 100644 index 000000000..dfa88f8a9 --- /dev/null +++ b/src/sm/Elements/GradientDamage/PlaneStress/trplstrgraddamage.C @@ -0,0 +1,155 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "Elements/GradientDamage/PlaneStress/trplstrgraddamage.h" +#include "fei2dtrlin.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "crosssection.h" +#include "classfactory.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { +REGISTER_Element(TrPlaneStressGradDamage); + + +IntArray TrPlaneStressGradDamage :: locationArray_u = {1, 2, 4, 5, 7, 8}; +IntArray TrPlaneStressGradDamage :: locationArray_d = {3, 6, 9}; + +FEI2dTrLin TrPlaneStressGradDamage :: interpolation_lin(1, 2); + +TrPlaneStressGradDamage :: TrPlaneStressGradDamage(int n, Domain *aDomain) : TrPlaneStress2d(n, aDomain), GradientDamageElement() + // Constructor. +{ + nPrimNodes = 3; + nPrimVars = 2; + nSecNodes = 3; + nSecVars = 1; + totalSize = nPrimVars * nPrimNodes + nSecVars * nSecNodes; + locSize = nPrimVars * nPrimNodes; + nlSize = nSecVars * nSecNodes; + numberOfGaussPoints = 1; +} + + +void +TrPlaneStressGradDamage :: giveDofManDofIDMask(int inode, IntArray &answer) const + +{ + answer = {D_u, D_v, G_0}; +} + + + void +TrPlaneStressGradDamage :: giveDofManDofIDMask_u(IntArray &answer) const +{ + answer = {D_u, D_v}; +} + + +void +TrPlaneStressGradDamage :: giveDofManDofIDMask_d(IntArray &answer) const +{ + answer = {G_0}; +} + + + + + +void +TrPlaneStressGradDamage :: initializeFrom(InputRecord &ir) +{ + TrPlaneStress2d :: initializeFrom(ir); +} + + +void +TrPlaneStressGradDamage :: computeGaussPoints() +{ + if ( integrationRulesArray.size() == 0 ) { + integrationRulesArray.resize( 1 ); + integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); + } +} + +void +TrPlaneStressGradDamage :: computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) +{ + this->interpolation_lin.evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); +} + +void +TrPlaneStressGradDamage :: computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) +{ + FloatMatrix dnx; + this->interpolation_lin.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + answer.beTranspositionOf(dnx); +} + + +void +TrPlaneStressGradDamage :: giveLocationArray_u(IntArray &answer) +{ + answer = locationArray_u; +} + + +void +TrPlaneStressGradDamage :: giveLocationArray_d(IntArray &answer) +{ + answer = locationArray_d; +} + + + +void +TrPlaneStressGradDamage :: postInitialize() +{ + GradientDamageElement:: postInitialize(); + NLStructuralElement :: postInitialize(); +} + + + + +} // end namespace oofem + diff --git a/src/sm/Elements/GradientDamage/PlaneStress/trplstrgraddamage.h b/src/sm/Elements/GradientDamage/PlaneStress/trplstrgraddamage.h new file mode 100644 index 000000000..b1440a154 --- /dev/null +++ b/src/sm/Elements/GradientDamage/PlaneStress/trplstrgraddamage.h @@ -0,0 +1,83 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef trplstrgraddamage_h +#define trplstrgraddamage_h + +#include "../sm/Elements/PlaneStress/trplanstrss.h" +#include "../sm/Elements/GradientDamage/graddamageelement.h" + +#define _IFT_TrPlaneStressGradDamage_Name "trplanestressgraddamage" + +namespace oofem { +class FEI2dTrLin; + +class TrPlaneStressGradDamage : public TrPlaneStress2d, public GradientDamageElement +{ +protected: + static FEI2dTrLin interpolation_lin; + static IntArray locationArray_u; + static IntArray locationArray_d; + +public: + TrPlaneStressGradDamage(int n, Domain * d); + virtual ~TrPlaneStressGradDamage() { } + + void initializeFrom(InputRecord &ir) override; + + const char *giveInputRecordName() const override { return _IFT_TrPlaneStressGradDamage_Name; } + const char *giveClassName() const override { return "TrPlaneStressGradDamage"; } + + MaterialMode giveMaterialMode() override { return _PlaneStress; } + int computeNumberOfDofs() override { return 9; } + +protected: + void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { GradientDamageElement :: computeStiffnessMatrix(answer, rMode, tStep); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { GradientDamageElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + + void computeGaussPoints() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) const override; + void giveDofManDofIDMask_d(IntArray &answer) const override; + + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } + void postInitialize() override; + void giveLocationArray_u(IntArray &answer) override; + void giveLocationArray_d(IntArray &answer) override; +}; +} // end namespace oofem +#endif // trplstrgrad_h diff --git a/src/sm/Elements/GradientDamage/graddamageelement.C b/src/sm/Elements/GradientDamage/graddamageelement.C new file mode 100644 index 000000000..d802c6385 --- /dev/null +++ b/src/sm/Elements/GradientDamage/graddamageelement.C @@ -0,0 +1,629 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "../sm/Elements/GradientDamage/graddamageelement.h" +#include "../sm/Materials/structuralms.h" +#include "../sm/CrossSections/structuralcrosssection.h" +#include "../sm/Elements/nlstructuralelement.h" +#include "../sm/Materials/graddamagematerialextensioninterface.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "domain.h" +#include "cltypes.h" +#include "mathfem.h" +#include "nonlocalbarrier.h" +#include "engngm.h" +#include "unknownnumberingscheme.h" + +#include + +namespace oofem { +GradientDamageElement :: GradientDamageElement() +{} + + + +void +GradientDamageElement :: giveLocationArrayOfDofIDs(IntArray &locationArray_u, IntArray &locationArray_d, const UnknownNumberingScheme &s, const IntArray &dofIdArray_u, const IntArray &dofIdArray_d) +{ + // Routine to extract the location array of an element for given dofid array. + locationArray_u.clear(); + locationArray_d.clear(); + NLStructuralElement *el = this->giveNLStructuralElement(); + int k = 0; + IntArray nodalArray; + for ( int i = 1; i <= el->giveNumberOfDofManagers(); i++ ) { + DofManager *dMan = el->giveDofManager(i); + int itt = 1; + for ( int j = 1; j <= dofIdArray_u.giveSize(); j++ ) { + if ( dMan->hasDofID( ( DofIDItem ) dofIdArray_u.at(j) ) ) { + // Dof *d = dMan->giveDofWithID( dofIdArray_u.at( j ) ); + locationArray_u.followedBy(k + itt); + } + itt++; + } + for ( int j = 1; j <= dofIdArray_d.giveSize(); j++ ) { + if ( dMan->hasDofID( ( DofIDItem ) dofIdArray_d.at(j) ) ) { + //Dof *d = dMan->giveDofWithID( dofIdArray_m.at( j ) ); + locationArray_d.followedBy(k + itt); + } + itt++; + } + k += dMan->giveNumberOfDofs(); + } +} + + + + + +/* + * void + * GradientDamageElement :: setDisplacementLocationArray() + * { + * locU.resize(locSize); + * + * for ( int i = 1; i <= totalSize; i++ ) { + * if ( i < nSecNodes * nPrimVars + 1 ) { + * locU.at(i) = i + ( int ) ( ( ( i - 1 ) / nPrimVars ) ) * nSecVars; + * } else if ( i > nSecNodes * ( nPrimVars + nSecVars ) ) { + * locU.at(i - nSecVars * nSecNodes) = i; + * } + * } + * } + * + * void + * GradientDamageElement :: setNonlocalLocationArray() + * { + * locK.resize(nlSize); + * for ( int i = 1; i <= nlSize; i++ ) { + * locK.at(i) = i * nPrimVars + i; + * } + * } + */ + +void +GradientDamageElement :: computeDisplacementDegreesOfFreedom(FloatArray &answer, TimeStep *tStep) +{ + this->giveStructuralElement()->computeVectorOf({ D_u, D_v, D_w }, VM_Total, tStep, answer); +} + +void +GradientDamageElement :: computeNonlocalDegreesOfFreedom(FloatArray &answer, TimeStep *tStep, ValueModeType mode) +{ + this->giveStructuralElement()->computeVectorOf({ G_0 }, mode, tStep, answer); +} + +void +GradientDamageElement :: computeStressVector_and_localDamageDrivingVariable(FloatArray &answer, double &localDamageDrivingVariable, GaussPoint *gp, TimeStep *tStep) +{ + NLStructuralElement *elem = this->giveNLStructuralElement(); + + double nlDamageDrivingVariable; + + int nlGeo = elem->giveGeometryMode(); + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + GradientDamageMaterialExtensionInterface *gdmat = static_cast< GradientDamageMaterialExtensionInterface * >( + cs->giveMaterialInterface(GradientDamageMaterialExtensionInterfaceType, gp) ); + + if ( !gdmat ) { + OOFEM_ERROR("Material doesn't implement the required Gradient damage interface!"); + } + + this->computeNonlocalDamageDrivingVariable(nlDamageDrivingVariable, gp, tStep); + if ( nlGeo == 0 ) { + FloatArray Epsilon; + this->computeStrainVector(Epsilon, gp, tStep); + gdmat->giveRealStressVectorGradientDamage(answer, localDamageDrivingVariable, gp, Epsilon, nlDamageDrivingVariable, tStep); + } else if ( nlGeo == 1 ) { + if ( elem->giveDomain()->giveEngngModel()->giveFormulation() == TL ) { + FloatArray vF; + this->computeDeformationGradientVector(vF, gp, tStep); + gdmat->giveFirstPKStressVectorGradientDamage(answer, localDamageDrivingVariable, gp, vF, nlDamageDrivingVariable, tStep); + } else { + FloatArray vF; + this->computeDeformationGradientVector(vF, gp, tStep); + gdmat->giveCauchyStressVectorGradientDamage(answer, localDamageDrivingVariable, gp, vF, nlDamageDrivingVariable, tStep); + } + } +} + + +void +GradientDamageElement :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +{ + FloatArray u; + FloatMatrix b; + NLStructuralElement *elem = this->giveNLStructuralElement(); + + this->computeDisplacementDegreesOfFreedom(u, tStep); + elem->computeBmatrixAt(gp, b); + answer.beProductOf(b, u); +} + +void +GradientDamageElement :: computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +{ + // Computes the deformation gradient in the Voigt format at the Gauss point gp of + // the receiver at time step tStep. + // Order of components: 11, 22, 33, 23, 13, 12, 32, 31, 21 in the 3D. + + // Obtain the current displacement vector of the element and subtract initial displacements (if present) + FloatArray u; + FloatMatrix B; + NLStructuralElement *elem = this->giveNLStructuralElement(); + + this->computeDisplacementDegreesOfFreedom(u, tStep); + // Displacement gradient H = du/dX + elem->computeBHmatrixAt(gp, B); + answer.beProductOf(B, u); + + // Deformation gradient F = H + I + MaterialMode matMode = gp->giveMaterialMode(); + if ( matMode == _3dMat || matMode == _PlaneStrain ) { + answer.at(1) += 1.0; + answer.at(2) += 1.0; + answer.at(3) += 1.0; + } else if ( matMode == _PlaneStress ) { + answer.at(1) += 1.0; + answer.at(2) += 1.0; + } else if ( matMode == _1dMat ) { + answer.at(1) += 1.0; + } else { + OOFEM_ERROR( "MaterialMode is not supported yet (%s)", __MaterialModeToString(matMode) ); + } +} + +void +GradientDamageElement :: computeNonlocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep) +{ + FloatArray Nd, d; + + this->computeNdMatrixAt(gp, Nd); + this->computeNonlocalDegreesOfFreedom(d, tStep); + answer = Nd.dotProduct(d); +} + + +void +GradientDamageElement :: computeNonlocalDamageDrivingVariableGradient(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +{ + FloatMatrix Bd; + FloatArray d; + + this->computeBdMatrixAt(gp, Bd); + this->computeNonlocalDegreesOfFreedom(d, tStep); + answer.beProductOf(Bd, d); +} + + +void +GradientDamageElement :: giveInternalForcesVector_d(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + NLStructuralElement *elem = this->giveNLStructuralElement(); + + double localDamageDrivingVariable = 0., f_dN = 0., nonlocalDamageDrivingVariable; + FloatArray Nd, stress, d_d, nonlocalDamageDrivingVariable_grad, f_dB; + FloatMatrix Bd; + + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + int size = nSecVars * nSecNodes; + + answer.resize(size); + for ( GaussPoint *gp : *elem->giveIntegrationRule(0) ) { + this->computeNdMatrixAt(gp, Nd); + this->computeBdMatrixAt(gp, Bd); + if ( useUpdatedGpRecord == 1 ) { + StructuralMaterialStatus *ms = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); + stress = ms->giveTempStressVector(); + /* StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + * GradientDamageMaterialStatusExtensionInterface *gdms = dynamic_cast< GradientDamageMaterialStatusExtensionInterface * >(cs->giveMaterialInterface(GradientDamageMaterialStatusExtensionInterfaceType, gp) ); + * localCumulatedStrain = gdms->giveLocalCumulatedStrain(); + */ + } else { + this->computeStressVector_and_localDamageDrivingVariable(stress, localDamageDrivingVariable, gp, tStep); + } + + double dV = elem->computeVolumeAround(gp); + this->computeNonlocalDegreesOfFreedom(d_d, tStep); + + nonlocalDamageDrivingVariable = Nd.dotProduct(d_d); + nonlocalDamageDrivingVariable_grad.beProductOf(Bd, d_d); + + this->computeInternalForces_dN(f_dN, localDamageDrivingVariable, nonlocalDamageDrivingVariable, gp, tStep); + this->computeInternalForces_dB(f_dB, localDamageDrivingVariable, nonlocalDamageDrivingVariable_grad, gp, tStep); + + + GradientDamageMaterialExtensionInterface *gdmat = static_cast< GradientDamageMaterialExtensionInterface * >( cs->giveMaterialInterface(GradientDamageMaterialExtensionInterfaceType, gp) ); + if ( !gdmat ) { + OOFEM_ERROR("Material doesn't implement the required Gradient damage interface!"); + } + + FloatArray N_f, B_f; + N_f = Nd; + N_f.times(f_dN); + B_f.beTProductOf(Bd, f_dB); + answer.add(dV, N_f); + answer.add(dV, B_f); + } + + + // add penalty stiffness + if ( penalty > 0. ) { + FloatArray d; + this->computeNonlocalDegreesOfFreedom(d, tStep, VM_Incremental); + for ( int i = 1; i <= d.giveSize(); i++ ) { + if ( d.at(i) <= 0. ) { + answer.at(i) += penalty * d.at(i); + } + } + } +} + +void +GradientDamageElement :: computeInternalForces_dN(double &answer, double localDamageDrivingVariable, double nonlocalDamageDrivingVariable, GaussPoint *gp, TimeStep *tStep) +{ + NLStructuralElement *elem = this->giveNLStructuralElement(); + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + GradientDamageMaterialExtensionInterface *gdmat = static_cast< GradientDamageMaterialExtensionInterface * >( + cs->giveMaterialInterface(GradientDamageMaterialExtensionInterfaceType, gp) ); + + if ( !gdmat ) { + OOFEM_ERROR("Material doesn't implement the required Gradient damage interface!"); + } + + gdmat->giveNonlocalInternalForces_N_factor(answer, nonlocalDamageDrivingVariable, gp, tStep); +} + + +void +GradientDamageElement :: computeInternalForces_dB(FloatArray &answer, double localDamageDrivingVariable, const FloatArray nonlocalDamageDrivingVariable_grad, GaussPoint *gp, TimeStep *tStep) +{ + NLStructuralElement *elem = this->giveNLStructuralElement(); + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + GradientDamageMaterialExtensionInterface *gdmat = static_cast< GradientDamageMaterialExtensionInterface * >( + cs->giveMaterialInterface(GradientDamageMaterialExtensionInterfaceType, gp) ); + + if ( !gdmat ) { + OOFEM_ERROR("Material doesn't implement the required Gradient damage interface!"); + } + + gdmat->giveNonlocalInternalForces_B_factor(answer, nonlocalDamageDrivingVariable_grad, gp, tStep); +} + + +void +GradientDamageElement :: giveInternalForcesVector_u(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + NLStructuralElement *elem = this->giveNLStructuralElement(); + int nlGeo = elem->giveGeometryMode(); + double localDamageDrivingVariable; + FloatArray BS, vStress, vRedStress; + FloatMatrix B; + + for ( GaussPoint *gp : *elem->giveIntegrationRule(0) ) { + if ( nlGeo == 0 || elem->domain->giveEngngModel()->giveFormulation() == AL ) { + elem->computeBmatrixAt(gp, B); + } else if ( nlGeo == 1 ) { + elem->computeBHmatrixAt(gp, B); + } + + if ( useUpdatedGpRecord == 1 ) { + StructuralMaterialStatus *ms = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); + vStress = ms->giveTempStressVector(); + /* StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + * GradientDamageMaterialStatusExtensionInterface *gdms = dynamic_cast< GradientDamageMaterialStatusExtensionInterface * >(cs->giveMaterialInterface(GradientDamageMaterialStatusExtensionInterfaceType, gp) ); + * localCumulatedStrain = gdms->giveLocalCumulatedStrain(); + */ + } else { + this->computeStressVector_and_localDamageDrivingVariable(vStress, localDamageDrivingVariable, gp, tStep); + } + + StructuralMaterial :: giveReducedSymVectorForm( vRedStress, vStress, gp->giveMaterialMode() ); + + + + + if ( vStress.giveSize() == 0 ) { /// @todo is this check really necessary? + break; + } + + // Compute nodal internal forces at nodes as f = B^T*Stress dV + double dV = elem->computeVolumeAround(gp); + BS.beTProductOf(B, vRedStress); + answer.add(dV, BS); + } +} + + +void +GradientDamageElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + answer.resize(totalSize); + answer.zero(); + FloatArray answerU; + answerU.resize(locSize); + answer.zero(); + FloatArray answerD(nlSize); + answerD.zero(); + + this->giveInternalForcesVector_u(answerU, tStep, useUpdatedGpRecord); + this->giveInternalForcesVector_d(answerD, tStep, useUpdatedGpRecord); + + + answer.assemble(answerU, locationArray_u); + answer.assemble(answerD, locationArray_d); +} + + + + +void +GradientDamageElement :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + answer.resize(totalSize, totalSize); + answer.zero(); + + FloatMatrix answer1, answer2, answer3, answer4; + this->computeStiffnessMatrix_uu(answer1, rMode, tStep); + this->computeStiffnessMatrix_ud(answer2, rMode, tStep); + this->computeStiffnessMatrix_du(answer3, rMode, tStep); + this->computeStiffnessMatrix_dd(answer4, rMode, tStep); + answer.assemble(answer1, locationArray_u); + answer.assemble(answer2, locationArray_u, locationArray_d); + answer.assemble(answer3, locationArray_d, locationArray_u); + answer.assemble(answer4, locationArray_d); +} + + +void +GradientDamageElement :: computeStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + NLStructuralElement *elem = this->giveNLStructuralElement(); + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + FloatMatrix B, D, DB; + + int nlGeo = elem->giveGeometryMode(); + bool matStiffSymmFlag = elem->giveCrossSection()->isCharacteristicMtrxSymmetric(rMode); + answer.clear(); + for ( GaussPoint *gp : *elem->giveIntegrationRule(0) ) { + GradientDamageMaterialExtensionInterface *gdmat = dynamic_cast< GradientDamageMaterialExtensionInterface * >( + cs->giveMaterialInterface(GradientDamageMaterialExtensionInterfaceType, gp) ); + if ( !gdmat ) { + OOFEM_ERROR("Material doesn't implement the required DpGrad interface!"); + } + if ( nlGeo == 0 ) { + elem->computeBmatrixAt(gp, B); + } else if ( nlGeo == 1 ) { + if ( elem->domain->giveEngngModel()->giveFormulation() == AL ) { + elem->computeBmatrixAt(gp, B); + } else { + elem->computeBHmatrixAt(gp, B); + } + } + gdmat->giveGradientDamageStiffnessMatrix_uu(D, rMode, gp, tStep); + double dV = elem->computeVolumeAround(gp); + DB.beProductOf(D, B); + if ( matStiffSymmFlag ) { + answer.plusProductSymmUpper(B, DB, dV); + } else { + answer.plusProductUnsym(B, DB, dV); + } + } + + + if ( matStiffSymmFlag ) { + answer.symmetrized(); + } +} + + +void +GradientDamageElement :: computeStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + double dV; + NLStructuralElement *elem = this->giveNLStructuralElement(); + FloatArray Nd; + FloatMatrix B, DduB, Ddu; + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + + answer.clear(); + + int nlGeo = elem->giveGeometryMode(); + + for ( auto &gp : *elem->giveIntegrationRule(0) ) { + GradientDamageMaterialExtensionInterface *gdmat = dynamic_cast< GradientDamageMaterialExtensionInterface * >( + cs->giveMaterialInterface(GradientDamageMaterialExtensionInterfaceType, gp) ); + if ( !gdmat ) { + OOFEM_ERROR("Material doesn't implement the required DpGrad interface!"); + } + + elem->computeBmatrixAt(gp, B); + if ( nlGeo == 1 ) { + if ( elem->domain->giveEngngModel()->giveFormulation() == AL ) { + elem->computeBmatrixAt(gp, B); + } else { + elem->computeBHmatrixAt(gp, B); + } + } + + gdmat->giveGradientDamageStiffnessMatrix_du(Ddu, rMode, gp, tStep); + this->computeNdMatrixAt(gp, Nd); + dV = elem->computeVolumeAround(gp); + if ( Ddu.giveNumberOfRows() > 0 ) { + DduB.beTProductOf(Ddu, B); + FloatMatrix Ndm(Nd, true); + answer.plusProductUnsym(Ndm, DduB, dV); + } else { + if ( answer.giveNumberOfColumns() == 0 ) { + answer.resize( Nd.giveSize(), B.giveNumberOfColumns() ); + } + } + } +} + + +void +GradientDamageElement :: computeStiffnessMatrix_dd(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + StructuralElement *elem = this->giveStructuralElement(); + double dV; + FloatMatrix Ddd_NN, Ddd_BB, Ddd_BN; + FloatArray Nd; + FloatMatrix Bd; + FloatMatrix Ddd; + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + + answer.clear(); + for ( auto &gp : *elem->giveIntegrationRule(0) ) { + GradientDamageMaterialExtensionInterface *gdmat = dynamic_cast< GradientDamageMaterialExtensionInterface * >( + cs->giveMaterialInterface(GradientDamageMaterialExtensionInterfaceType, gp) ); + if ( !gdmat ) { + OOFEM_ERROR("Material doesn't implement the required Gradient damage interface!"); + } + + this->computeNdMatrixAt(gp, Nd); + FloatMatrix Ndm(Nd, true); + this->computeBdMatrixAt(gp, Bd); + dV = elem->computeVolumeAround(gp); + + gdmat->giveGradientDamageStiffnessMatrix_dd_NN(Ddd_NN, rMode, gp, tStep); + gdmat->giveGradientDamageStiffnessMatrix_dd_BB(Ddd_BB, rMode, gp, tStep); + gdmat->giveGradientDamageStiffnessMatrix_dd_BN(Ddd_BN, rMode, gp, tStep); + + + + if ( Ddd_NN.giveNumberOfRows() > 0 ) { + + Ddd.beProductOf(Ddd_NN, Ndm); + answer.plusProductUnsym(Ndm, Ddd, dV); + } else { + answer.plusProductUnsym(Ndm, Ndm, dV); + } + + Ddd.beProductOf(Ddd_BB, Bd); + answer.plusProductUnsym(Bd, Ddd, dV); + + + + if ( Ddd_BN.giveNumberOfRows() > 0 ) { + Ddd.beProductOf(Ddd_BN, Ndm); + answer.plusProductUnsym(Bd, Ddd, dV); + } + } + + // add penalty stiffness + if ( penalty > 0. ) { + FloatArray d; + this->computeNonlocalDegreesOfFreedom(d, tStep, VM_Incremental); + for ( int i = 1; i <= d.giveSize(); i++ ) { + if ( d.at(i) <= 0. ) { + answer.at(i, i) += penalty; + } + } + } +} + + +void +GradientDamageElement :: computeStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + NLStructuralElement *elem = this->giveNLStructuralElement(); + double dV; + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + int nlGeo = elem->giveGeometryMode(); + FloatArray Nd; + FloatMatrix B; + FloatMatrix Dud, DudN; + + answer.clear(); + + for ( auto &gp : *elem->giveIntegrationRule(0) ) { + GradientDamageMaterialExtensionInterface *gdmat = dynamic_cast< GradientDamageMaterialExtensionInterface * >( + cs->giveMaterialInterface(GradientDamageMaterialExtensionInterfaceType, gp) ); + if ( !gdmat ) { + OOFEM_ERROR("Material doesn't implement the required gradient interface!"); + } + gdmat->giveGradientDamageStiffnessMatrix_ud(Dud, rMode, gp, tStep); + this->computeNdMatrixAt(gp, Nd); + elem->computeBmatrixAt(gp, B); + if ( nlGeo == 1 ) { + if ( elem->domain->giveEngngModel()->giveFormulation() == AL ) { + elem->computeBmatrixAt(gp, B); + } else { + elem->computeBHmatrixAt(gp, B); + } + } + dV = elem->computeVolumeAround(gp); + + DudN.beProductTOf(Dud, Nd); + answer.plusProductUnsym(B, DudN, dV); + } +} + + +void +GradientDamageElement :: initializeFrom(InputRecord &ir) +{ + //nlGeo = 0; + penalty = 0.; + IR_GIVE_OPTIONAL_FIELD(ir, penalty, _IFT_GradientDamageElement_penalty); +} + +void +GradientDamageElement :: postInitialize() +{ + this->giveLocationArray_u(locationArray_u); + this->giveLocationArray_d(locationArray_d); +} + + +/* + * void + * GradientDamageElement :: postInitialize() + * { + * IntArray IdMask_u, IdMask_d; + * this->giveDofManDofIDMask_u( IdMask_u ); + * this->giveDofManDofIDMask_d( IdMask_d ); + * this->giveLocationArrayOfDofIDs(locationArray_u,locationArray_d, EModelDefaultEquationNumbering(), IdMask_u, IdMask_d); + * } + */ +} // end namespace oofem diff --git a/src/sm/Elements/GradientDamage/graddamageelement.h b/src/sm/Elements/GradientDamage/graddamageelement.h new file mode 100644 index 000000000..3efe4013e --- /dev/null +++ b/src/sm/Elements/GradientDamage/graddamageelement.h @@ -0,0 +1,119 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef graddamageelement_h +#define graddamageelement_h + +#include "../sm/Elements/structuralelement.h" +#include "../sm/Elements/nlstructuralelement.h" + +#define _IFT_GradientDamageElement_penalty "penalty" + + +namespace oofem { +/** + * Abstract class for gradient damage models + * It can be also simply combined with damage-plastic models with yield function formulated in the effective stress space and damage driven by the nonlocal(over-nonlocal) cumulated plastic strain. + * The new nonlocal degrees of freedom (they can, for example, have meaning of the nonlocal equivalent strain) are introduced. Usually, they are approximated using lower order approximation functions than the displacement field to avoid spurious stress oscillations. + ***@author Martin Horak + */ + + + + +class GradientDamageElement +{ +protected: + int nPrimNodes, nPrimVars, nSecNodes, nSecVars; + int totalSize, nlSize, locSize; + IntArray locationArray_u; + IntArray locationArray_d; + double penalty; + +public: + GradientDamageElement(); + virtual ~GradientDamageElement() { } + + virtual void initializeFrom(InputRecord &ir); + +protected: + virtual StructuralElement *giveStructuralElement() = 0; + virtual NLStructuralElement *giveNLStructuralElement() = 0; + + virtual void computeNdMatrixAt(GaussPoint *gp, FloatArray &answer) = 0; + virtual void computeBdMatrixAt(GaussPoint *gp, FloatMatrix &answer) = 0; + + virtual void giveDofManDofIDMask_u(IntArray &answer) const = 0; + virtual void giveDofManDofIDMask_d(IntArray &answer) const = 0; + + + void computeStiffnessMatrix(FloatMatrix &, MatResponseMode, TimeStep *); + void computeStiffnessMatrix_uu(FloatMatrix &, MatResponseMode, TimeStep *); + void computeStiffnessMatrix_ud(FloatMatrix &, MatResponseMode, TimeStep *); + void computeStiffnessMatrix_dd(FloatMatrix &, MatResponseMode, TimeStep *); + void computeStiffnessMatrix_du(FloatMatrix &, MatResponseMode, TimeStep *); + + void computeDisplacementDegreesOfFreedom(FloatArray &answer, TimeStep *tStep); + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + + void computeNonlocalDegreesOfFreedom(FloatArray &answer, TimeStep *tStep, ValueModeType vmt = VM_Total); + void computeNonlocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep); + void computeNonlocalDamageDrivingVariableGradient(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + + + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); + void giveInternalForcesVector_u(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); + void giveInternalForcesVector_d(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); + + void computeInternalForces_dN(double &answer, double localDamageDrivingVariable, double damage, GaussPoint *gp, TimeStep *tStep); + void computeInternalForces_dB(FloatArray &answer, double localDamageDrivingVariable, FloatArray damage_grad, GaussPoint *gp, TimeStep *tStep); + + void computeStressVector_and_localDamageDrivingVariable(FloatArray &answer, double &localCumulatedPlasticStrain, GaussPoint *gp, TimeStep *tStep); + + + void giveLocationArrayOfDofIDs(IntArray &locationArray_u, IntArray &locationArray_d, const UnknownNumberingScheme &s, const IntArray &dofIdArray_u, const IntArray &dofIdArray_m); + + virtual void giveLocationArray_u(IntArray &answer) = 0; + virtual void giveLocationArray_d(IntArray &answer) = 0; + + + virtual const char *giveClassName() const { return "GradientDamageElement"; } + + virtual void postInitialize(); +}; +} // end namespace oofem + +#endif // end gradient damage element diff --git a/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dlin.C b/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dlin.C index f92bdd506..d2398c3ac 100644 --- a/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dlin.C +++ b/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dlin.C @@ -37,11 +37,13 @@ #include "gausspoint.h" #include "gaussintegrationrule.h" #include "floatmatrix.h" +#include "floatmatrixf.h" #include "floatarray.h" +#include "floatarrayf.h" #include "intarray.h" #include "mathfem.h" #include "fei2dlinelin.h" -#include "../sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "classfactory.h" #ifdef __OOFEG @@ -90,7 +92,7 @@ InterfaceElem2dLin :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); integrationRulesArray [ 0 ]->SetUpPointsOnLine(2, _2dInterface); } } @@ -117,22 +119,22 @@ InterfaceElem2dLin :: computeVolumeAround(GaussPoint *gp) void InterfaceElem2dLin :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_2d(answer, gp, strain, tStep); + answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_2d(strain, gp, tStep); } void InterfaceElem2dLin :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give2dStiffnessMatrix_Eng(answer, rMode, gp, tStep); + answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give2dStiffnessMatrix_Eng(rMode, gp, tStep); } -IRResultType -InterfaceElem2dLin :: initializeFrom(InputRecord *ir) +void +InterfaceElem2dLin :: initializeFrom(InputRecord &ir) { - this->axisymmode = ir->hasField(_IFT_InterfaceElem2dLin_axisymmode); - return StructuralElement :: initializeFrom(ir); + this->axisymmode = ir.hasField(_IFT_InterfaceElem2dLin_axisymmode); + StructuralElement :: initializeFrom(ir); } diff --git a/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dlin.h b/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dlin.h index 1563b5f80..06495df4a 100644 --- a/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dlin.h +++ b/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dlin.h @@ -35,7 +35,7 @@ #ifndef interfaceelem2dlin_h #define interfaceelem2dlin_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #define _IFT_InterfaceElem2dLin_Name "interface2dlin" #define _IFT_InterfaceElem2dLin_axisymmode "axisymmode" @@ -58,38 +58,36 @@ class InterfaceElem2dLin : public StructuralElement InterfaceElem2dLin(int n, Domain * d); virtual ~InterfaceElem2dLin() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual int computeNumberOfDofs() { return 8; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + int computeNumberOfDofs() override { return 8; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual int testElementExtension(ElementExtension ext) { return 0; } - - virtual Interface *giveInterface(InterfaceType) { return NULL; } + int testElementExtension(ElementExtension ext) override { return 0; } #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_InterfaceElem2dLin_Name; } - virtual const char *giveClassName() const { return "InterfaceElem2dLin"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual MaterialMode giveMaterialMode() { return _2dInterface; } + const char *giveInputRecordName() const override { return _IFT_InterfaceElem2dLin_Name; } + const char *giveClassName() const override { return "InterfaceElem2dLin"; } + void initializeFrom(InputRecord &ir) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + MaterialMode giveMaterialMode() override { return _2dInterface; } protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) { } - virtual void computeGaussPoints(); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override { } + void computeGaussPoints() override; - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; }; } // end namespace oofem #endif // interfaceelem2dlin_h diff --git a/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dquad.C b/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dquad.C index 832b76cdc..53167ef6f 100644 --- a/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dquad.C +++ b/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dquad.C @@ -37,11 +37,13 @@ #include "gausspoint.h" #include "gaussintegrationrule.h" #include "floatmatrix.h" +#include "floatmatrixf.h" #include "floatarray.h" +#include "floatarrayf.h" #include "intarray.h" #include "mathfem.h" #include "fei2dlinequad.h" -#include "../sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "classfactory.h" #ifdef __OOFEG @@ -96,8 +98,8 @@ InterfaceElem2dQuad :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - //integrationRulesArray[0].reset( new LobattoIntegrationRule (1,domain, 1, 2) ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + //integrationRulesArray[0] = std::make_unique(1,domain, 1, 2); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); integrationRulesArray [ 0 ]->SetUpPointsOnLine(4, _2dInterface); } } @@ -141,22 +143,22 @@ InterfaceElem2dQuad :: computeVolumeAround(GaussPoint *gp) void InterfaceElem2dQuad :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_2d(answer, gp, strain, tStep); + answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_2d(strain, gp, tStep); } void InterfaceElem2dQuad :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give2dStiffnessMatrix_Eng(answer, rMode, gp, tStep); + answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give2dStiffnessMatrix_Eng(rMode, gp, tStep); } -IRResultType -InterfaceElem2dQuad :: initializeFrom(InputRecord *ir) +void +InterfaceElem2dQuad :: initializeFrom(InputRecord &ir) { - this->axisymmode = ir->hasField(_IFT_InterfaceElem2dQuad_axisymmode); - return StructuralElement :: initializeFrom(ir); + this->axisymmode = ir.hasField(_IFT_InterfaceElem2dQuad_axisymmode); + StructuralElement :: initializeFrom(ir); } diff --git a/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dquad.h b/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dquad.h index 8d4c97de5..eb7a52b28 100644 --- a/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dquad.h +++ b/src/sm/Elements/Interfaces/Deprecated/interfaceelem2dquad.h @@ -35,7 +35,7 @@ #ifndef interfaceelem2dquad_h #define interfaceelem2dquad_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #define _IFT_InterfaceElem2dQuad_Name "interface2dquad" #define _IFT_InterfaceElem2dQuad_axisymmode "axisymmode" @@ -60,38 +60,38 @@ class InterfaceElem2dQuad : public StructuralElement InterfaceElem2dQuad(int n, Domain * d); virtual ~InterfaceElem2dQuad() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual int computeNumberOfDofs() { return 12; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + int computeNumberOfDofs() override { return 12; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual int testElementExtension(ElementExtension ext) { return 0; } + int testElementExtension(ElementExtension ext) override { return 0; } - virtual Interface *giveInterface(InterfaceType) { return NULL; } + Interface *giveInterface(InterfaceType) override { return NULL; } #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_InterfaceElem2dQuad_Name; } - virtual const char *giveClassName() const { return "InterfaceElem2dQuad"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual MaterialMode giveMaterialMode() { return _2dInterface; } + const char *giveInputRecordName() const override { return _IFT_InterfaceElem2dQuad_Name; } + const char *giveClassName() const override { return "InterfaceElem2dQuad"; } + void initializeFrom(InputRecord &ir) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + MaterialMode giveMaterialMode() override { return _2dInterface; } protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) { } - virtual void computeGaussPoints(); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override { } + void computeGaussPoints() override; - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; }; } // end namespace oofem #endif // interfaceelem2dquad_h diff --git a/src/sm/Elements/Interfaces/Deprecated/interfaceelem3dtrlin.C b/src/sm/Elements/Interfaces/Deprecated/interfaceelem3dtrlin.C index 2adfc6e76..fba209d4a 100644 --- a/src/sm/Elements/Interfaces/Deprecated/interfaceelem3dtrlin.C +++ b/src/sm/Elements/Interfaces/Deprecated/interfaceelem3dtrlin.C @@ -39,10 +39,12 @@ #include "gausspoint.h" #include "gaussintegrationrule.h" #include "floatmatrix.h" +#include "floatmatrixf.h" #include "floatarray.h" +#include "floatarrayf.h" #include "intarray.h" #include "mathfem.h" -#include "../sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "classfactory.h" #ifdef __OOFEG @@ -93,8 +95,8 @@ InterfaceElement3dTrLin :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - //integrationRulesArray[0].reset( new LobattoIntegrationRule (1,domain, 1, 2) ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + //integrationRulesArray[0] = std::make_unique(1,domain, 1, 2); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); integrationRulesArray [ 0 ]->SetUpPointsOnTriangle(4, _3dInterface); } } @@ -138,7 +140,7 @@ InterfaceElement3dTrLin :: computeVolumeAround(GaussPoint *gp) FloatMatrix lcs(3, 3); this->computeLCS(lcs); for ( int i = 1; i <= 3; i++ ) { - lncp[ i - 1 ].beProductOf(lcs, *this->giveNode(i)->giveCoordinates()); + lncp[ i - 1 ].beProductOf(lcs, this->giveNode(i)->giveCoordinates()); } determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lncp) ) ); @@ -153,21 +155,21 @@ InterfaceElement3dTrLin :: computeVolumeAround(GaussPoint *gp) void InterfaceElement3dTrLin :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_3d(answer, gp, strain, tStep); + answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_3d(strain, gp, tStep); } void InterfaceElement3dTrLin :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give3dStiffnessMatrix_Eng(answer, rMode, gp, tStep); + answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give3dStiffnessMatrix_Eng(rMode, gp, tStep); } -IRResultType -InterfaceElement3dTrLin :: initializeFrom(InputRecord *ir) +void +InterfaceElement3dTrLin :: initializeFrom(InputRecord &ir) { - return StructuralElement :: initializeFrom(ir); + StructuralElement :: initializeFrom(ir); } diff --git a/src/sm/Elements/Interfaces/Deprecated/interfaceelem3dtrlin.h b/src/sm/Elements/Interfaces/Deprecated/interfaceelem3dtrlin.h index 6fee94923..b47056b4b 100644 --- a/src/sm/Elements/Interfaces/Deprecated/interfaceelem3dtrlin.h +++ b/src/sm/Elements/Interfaces/Deprecated/interfaceelem3dtrlin.h @@ -35,7 +35,7 @@ #ifndef interfaceelem3dtrlin_h #define interfaceelem3dtrlin_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #define _IFT_InterfaceElement3dTrLin_Name "interface3dtrlin" @@ -57,41 +57,39 @@ class InterfaceElement3dTrLin : public StructuralElement InterfaceElement3dTrLin(int n, Domain * d); virtual ~InterfaceElement3dTrLin() { } - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; - virtual int computeNumberOfDofs() { return 18; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + int computeNumberOfDofs() override { return 18; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual int testElementExtension(ElementExtension ext) { return 0; } - - virtual Interface *giveInterface(InterfaceType) { return NULL; } + int testElementExtension(ElementExtension ext) override { return 0; } #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_InterfaceElement3dTrLin_Name; } - virtual const char *giveClassName() const { return "InterfaceElement3dTrLin"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Element_Geometry_Type giveGeometryType() const { return EGT_wedge_1; } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } + const char *giveInputRecordName() const override { return _IFT_InterfaceElement3dTrLin_Name; } + const char *giveClassName() const override { return "InterfaceElement3dTrLin"; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_wedge_1; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual MaterialMode giveMaterialMode() { return _3dInterface; } + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + MaterialMode giveMaterialMode() override { return _3dInterface; } protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) { } - virtual void computeGaussPoints(); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override { } + void computeGaussPoints() override; - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; void computeLCS(FloatMatrix &answer); }; } // end namespace oofem diff --git a/src/sm/Elements/Interfaces/Deprecated/interfaceelement1d.C b/src/sm/Elements/Interfaces/Deprecated/interfaceelement1d.C index 8f5e30ff1..01a563350 100644 --- a/src/sm/Elements/Interfaces/Deprecated/interfaceelement1d.C +++ b/src/sm/Elements/Interfaces/Deprecated/interfaceelement1d.C @@ -41,8 +41,9 @@ #include "intarray.h" #include "mathfem.h" #include "feinterpol.h" -#include "../sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "classfactory.h" +#include "floatmatrixf.h" #ifdef __OOFEG #include "oofeggraphiccontext.h" @@ -87,9 +88,9 @@ InterfaceElem1d :: computeStressVector(FloatArray &answer, const FloatArray &str { setCoordMode(); switch ( mode ) { - case ie1d_1d: static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_1d(answer, gp, strain, tStep); return; - case ie1d_2d: static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_2d(answer, gp, strain, tStep); return; - case ie1d_3d: static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_3d(answer, gp, strain, tStep); return; + case ie1d_1d: answer = FloatArray{static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_1d(strain.at(1), gp, tStep)}; return; + case ie1d_2d: answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_2d(strain, gp, tStep); return; + case ie1d_3d: answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_3d(strain, gp, tStep); return; } } @@ -99,9 +100,9 @@ InterfaceElem1d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseM { setCoordMode(); switch ( mode ) { - case ie1d_1d: static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give1dStiffnessMatrix_Eng(answer, rMode, gp, tStep); return; - case ie1d_2d: static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give2dStiffnessMatrix_Eng(answer, rMode, gp, tStep); return; - case ie1d_3d: static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give3dStiffnessMatrix_Eng(answer, rMode, gp, tStep); return; + case ie1d_1d: answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give1dStiffnessMatrix_Eng(rMode, gp, tStep); return; + case ie1d_2d: answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give2dStiffnessMatrix_Eng(rMode, gp, tStep); return; + case ie1d_3d: answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give3dStiffnessMatrix_Eng(rMode, gp, tStep); return; } } @@ -241,7 +242,7 @@ InterfaceElem1d :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); integrationRulesArray [ 0 ]->SetUpPointsOnLine(1, this->giveMaterialMode() ); } } @@ -250,7 +251,7 @@ InterfaceElem1d :: computeGaussPoints() int InterfaceElem1d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { - answer = *this->giveNode(1)->giveCoordinates(); + answer = this->giveNode(1)->giveCoordinates(); return 1; } @@ -272,22 +273,17 @@ InterfaceElem1d :: computeVolumeAround(GaussPoint *gp) } -IRResultType -InterfaceElem1d :: initializeFrom(InputRecord *ir) +void +InterfaceElem1d :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralElement :: initializeFrom(ir); IR_GIVE_OPTIONAL_FIELD(ir, referenceNode, _IFT_InterfaceElem1d_refnode); IR_GIVE_OPTIONAL_FIELD(ir, normal, _IFT_InterfaceElem1d_normal); if ( referenceNode == 0 && normal.at(1) == 0 && normal.at(2) == 0 && normal.at(1) == 0 && normal.at(3) == 0 ) { OOFEM_ERROR("wrong reference node or normal specified"); } - if ( ir->hasField(_IFT_InterfaceElem1d_dofIDs) ) { + if ( ir.hasField(_IFT_InterfaceElem1d_dofIDs) ) { IR_GIVE_FIELD(ir, dofids, _IFT_InterfaceElem1d_refnode); } else { switch ( domain->giveNumberOfSpatialDimensions() ) { @@ -306,7 +302,6 @@ InterfaceElem1d :: initializeFrom(InputRecord *ir) } this->computeLocalSlipDir(normal); ///@todo Move into postInitialize ? - return IRRT_OK; } diff --git a/src/sm/Elements/Interfaces/Deprecated/interfaceelement1d.h b/src/sm/Elements/Interfaces/Deprecated/interfaceelement1d.h index 5b68d965b..3fe82f2f8 100644 --- a/src/sm/Elements/Interfaces/Deprecated/interfaceelement1d.h +++ b/src/sm/Elements/Interfaces/Deprecated/interfaceelement1d.h @@ -35,7 +35,7 @@ #ifndef interfaceelement1d_h #define interfaceelement1d_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" ///@name Input fields for Material //@{ @@ -62,41 +62,39 @@ class InterfaceElem1d : public StructuralElement InterfaceElem1d(int n, Domain * d); virtual ~InterfaceElem1d() { } - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) { computeLumpedMassMatrix(answer, tStep); } + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; - virtual int computeNumberOfDofs(); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + int computeNumberOfDofs() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual int testElementExtension(ElementExtension ext) { return 0; } - - virtual Interface *giveInterface(InterfaceType it) { return NULL; } + int testElementExtension(ElementExtension ext) override { return 0; } #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_InterfaceElem1d_Name; } - virtual const char *giveClassName() const { return "InterfaceElem1d"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Element_Geometry_Type giveGeometryType() const { return EGT_point; } - virtual integrationDomain giveIntegrationDomain() const { return _Point; } - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual MaterialMode giveMaterialMode(); + const char *giveInputRecordName() const override { return _IFT_InterfaceElem1d_Name; } + const char *giveClassName() const override { return "InterfaceElem1d"; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_point; } + integrationDomain giveIntegrationDomain() const override { return _Point; } + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + MaterialMode giveMaterialMode() override; protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) { } - virtual void computeGaussPoints(); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override { } + void computeGaussPoints() override; void evaluateLocalCoordinateSystem(FloatMatrix &); void computeLocalSlipDir(FloatArray &normal); diff --git a/src/sm/Elements/Interfaces/bondlink3d.C b/src/sm/Elements/Interfaces/bondlink3d.C new file mode 100644 index 000000000..6dc5251ff --- /dev/null +++ b/src/sm/Elements/Interfaces/bondlink3d.C @@ -0,0 +1,563 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "../sm/Elements/Interfaces/bondlink3d.h" +#include "../sm/Materials/structuralms.h" +#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "intarray.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "mathfem.h" +#include "../sm/Elements/structuralelement.h" +#include "contextioerr.h" +#include "datastream.h" +#include "classfactory.h" +#include "../sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { +REGISTER_Element(BondLink3d); + +BondLink3d :: BondLink3d(int n, Domain *aDomain) : StructuralElement(n, aDomain) +{ + numberOfDofMans = 2; +} + + +double +BondLink3d :: computeVolumeAround(GaussPoint *aGaussPoint) +{ + //Returns artifical volume (bond area times bond length) so that general parts of post processing work (dissipated energy, etc.) + //Later on this artificial volume is divided by the bond length again so that the correct bond area is used. + return pow(this->bondLength, 2.) * this->bondDiameter * M_PI; +} + + +void +BondLink3d :: computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) +// Returns the strain matrix of the receiver. +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + //Assemble Bmatrix based on three rigid arm components + //first node: beam, second node: solid + //rigid.at(1) (tangential), rigid.at(2) (lateral), rigid.at(3) (lateral) + answer.resize(3, 9); + answer.zero(); + + //Normal displacement jump in x-direction + //First node + answer.at(1, 1) = 1.; + answer.at(1, 5) = -this->rigid.at(3); + answer.at(1, 6) = this->rigid.at(2); + //Second node + answer.at(1, 7) = -1.; + + //Shear displacement jump in y-plane + //first node + answer.at(2, 2) = 1.; + answer.at(2, 4) = this->rigid.at(3); + answer.at(2, 6) = -this->rigid.at(1); + + //Second node + answer.at(2, 8) = -1.; + + //Shear displacement jump in z-plane + //first node + answer.at(3, 3) = 1.; + answer.at(3, 4) = -this->rigid.at(2); + answer.at(3, 5) = this->rigid.at(1); + //Second node + answer.at(3, 9) = -1.; + + return; +} + +void +BondLink3d :: giveGPCoordinates(FloatArray &coords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + coords.resize(3); + coords = this->globalCentroid; + return; +} + + +void +BondLink3d :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + FloatMatrix d, b, bt, db; + FloatArray u, slip; + + this->computeVectorOf(VM_Total, tStep, u); + + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + answer.clear(); + + GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); + this->computeBmatrixAt(gp, b); + bt.beTranspositionOf(b); + + if ( !this->isActivated(tStep) ) { + slip.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); + slip.zero(); + } + slip.beProductOf(b, u); + + answer.resize(9, 9); + answer.zero(); + + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + db.beProductOf(d, b); + answer.beProductOf(bt, db); + + //Introduce integration of bond strength + double area = this->computeVolumeAround(gp) / this->giveLength(); + answer.times(area); + + + return; +} + +void BondLink3d :: computeGaussPoints() +// Sets up the array of Gauss Points of the receiver. +{ + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ].reset(new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ]->SetUpPointsOnLine(1, _3dMat); +} + + + + +bool +BondLink3d :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + int i, j; + + answer.resize(9, 9); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( i = 1; i <= 3; i++ ) { + for ( j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + answer.at(i + 6, j + 6) = lcs.at(i, j); + // answer.at(i + 9, j + 9) = lcs.at(i, j); + } + } + + return 1; +} + + +int +BondLink3d :: giveLocalCoordinateSystem(FloatMatrix &answer) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer = this->localCoordinateSystem; + + return 1; +} + +double +BondLink3d :: giveBondLength() +{ + return this->bondLength; +} + +double +BondLink3d :: giveBondEndLength() +{ + return this->bondEndLength; +} + + +double +BondLink3d :: giveBondDiameter() +{ + return this->bondDiameter; +} + + + + +void +BondLink3d :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 1 ) { + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; + } else { + answer = { D_u, D_v, D_w }; + } +} + +void +BondLink3d :: initializeFrom(InputRecord &ir) +{ + // first call parent + StructuralElement :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, this->bondLength, _IFT_BondLink3d_length); + + IR_GIVE_FIELD(ir, this->bondDiameter, _IFT_BondLink3d_diameter); + + IR_GIVE_FIELD(ir, this->directionVector, _IFT_BondLink3d_dirvector); + + IR_GIVE_FIELD(ir, this->bondEndLength, _IFT_BondLink3d_length_end); + + if ( this->bondEndLength < this->bondLength ) { + this->bondLength = this->bondEndLength; + } +} + + +int +BondLink3d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer.resize(3); + answer = this->globalCentroid; + + return 1; +} + + +void +BondLink3d :: computeGeometryProperties() +{ + //coordinates of the two nodes + Node *nodeA, *nodeB; + FloatArray coordsA(3), coordsB(3); + + //Order of nodes. Important, because continuum node does not have rotational DOFs. + //Beam node + nodeA = this->giveNode(1); + //Continuum node + nodeB = this->giveNode(2); + + + //Calculate components of distance from continuum node to lattice node. + for ( int i = 0; i < 3; i++ ) { + coordsA.at(i + 1) = nodeA->giveCoordinate(i + 1); + coordsB.at(i + 1) = nodeB->giveCoordinate(i + 1); + } + + FloatArray rigidGlobal(3); + + //Calculate normal vector + for ( int i = 0; i < 3; i++ ) { + rigidGlobal.at(i + 1) = coordsA.at(i + 1) - coordsB.at(i + 1); + } + + //Construct an initial temporary local coordinate system + FloatArray normal(3), s(3), t(3); + + //Calculate normal vector + normal = this->directionVector; + normal.normalize(); + + //Construct two perpendicular axis so that n is normal to the plane which they create + //Check, if one of the components of the normal-direction is zero + if ( normal.at(1) == 0 ) { + s.at(1) = 0.; + s.at(2) = normal.at(3); + s.at(3) = -normal.at(2); + } else if ( normal.at(2) == 0 ) { + s.at(1) = normal.at(3); + s.at(2) = 0.; + s.at(3) = -normal.at(1); + } else { + s.at(1) = normal.at(2); + s.at(2) = -normal.at(1); + s.at(3) = 0.; + } + + s.normalize(); + + t.beVectorProductOf(normal, s); + t.normalize(); + + //Set up rotation matrix + FloatMatrix lcs(3, 3); + + this->localCoordinateSystem.resize(3, 3); + this->localCoordinateSystem.zero(); + + for ( int i = 1; i <= 3; i++ ) { + this->localCoordinateSystem.at(1, i) = normal.at(i); + this->localCoordinateSystem.at(2, i) = s.at(i); + this->localCoordinateSystem.at(3, i) = t.at(i); + } + + // Rotate rigidarm vector into local coordinate system + + this->rigid.beProductOf(localCoordinateSystem, rigidGlobal); + + + this->globalCentroid.resize(3); + for ( int i = 1; i <= 3; i++ ) { + this->globalCentroid.at(i) = nodeB->giveCoordinate(i); + ; + } + + this->geometryFlag = 1; + + return; +} + +void +BondLink3d :: saveContext(DataStream &stream, ContextMode mode) +{ + StructuralElement :: saveContext(stream, mode); +} + + +void +BondLink3d :: restoreContext(DataStream &stream, ContextMode mode) +{ + StructuralElement :: restoreContext(stream, mode); +} + + +void +BondLink3d :: giveInternalForcesVector(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) +// +// returns nodal representation of real internal forces - necessary only for +// non-linear analysis. +// if useGpRecord == 1 then data stored in gp->giveStressVector() are used +// instead computing stressVector through this->ComputeStressVector(); +// this must be done after you want internal forces after element->updateYourself() +// has been called for the same time step. +// +{ + FloatMatrix b; + FloatArray u, stress, strain; + + // This function can be quite costly to do inside the loops when one has many slave dofs. + this->computeVectorOf(VM_Total, tStep, u); + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + // zero answer will resize accordingly when adding first contribution + answer.clear(); + + for ( GaussPoint *gp : * this->giveDefaultIntegrationRulePtr() ) { + this->computeBmatrixAt(gp, b); + + if ( useUpdatedGpRecord == 1 ) { + auto status = gp->giveMaterialStatus(); + StructuralMaterialStatus *matStat = dynamic_cast< StructuralMaterialStatus * >( status ); + if ( matStat ) { + stress = matStat->giveStressVector(); + } else { + StructuralInterfaceMaterialStatus *ms = static_cast< StructuralInterfaceMaterialStatus * >( status ); + stress = ms->giveTraction(); + } + } else { + if ( !this->isActivated(tStep) ) { + strain.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); + strain.zero(); + } + strain.beProductOf(b, u); + this->computeStressVector(stress, strain, gp, tStep); + } + + // updates gp stress and strain record acording to current + // increment of displacement + if ( stress.giveSize() == 0 ) { + break; + } + + // now every gauss point has real stress vector + // compute nodal representation of internal forces using f = B^T*Sigma dV + double dV = this->computeVolumeAround(gp) / this->giveLength(); + ; + if ( stress.giveSize() == 6 ) { + // It may happen that e.g. plane strain is computed + // using the default 3D implementation. If so, + // the stress needs to be reduced. + // (Note that no reduction will take place if + // the simulation is actually 3D.) + FloatArray stressTemp; + StructuralMaterial :: giveReducedSymVectorForm(stressTemp, stress, gp->giveMaterialMode() ); + answer.plusProduct(b, stressTemp, dV); + } else { + answer.plusProduct(b, stress, dV); + } + } + + // if inactive update state, but no contribution to global system + if ( !this->isActivated(tStep) ) { + answer.zero(); + return; + } +} + + +double +BondLink3d :: giveLength() +{ + //returns the bond length, not the length between the two nodes + return this->bondLength; +} + +void +BondLink3d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< StructuralInterfaceCrossSection * >( this->giveCrossSection() )->give3dStiffnessMatrix_Eng(rMode, gp, tStep); +} + +void +BondLink3d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< StructuralInterfaceCrossSection * >( this->giveCrossSection() )->giveEngTraction_3d(strain, gp, tStep); +} + + + +#ifdef __OOFEG + +void +BondLink3d :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + } else if ( mode == OGC_deformedGeometry ) { + this->drawDeformedGeometry(gc, tStep, DisplacementVector); + } else if ( mode == OGC_eigenVectorGeometry ) { + this->drawDeformedGeometry(gc, tStep, EigenVector); + } else if ( mode == OGC_scalarPlot ) { + this->drawScalar(gc, tStep); + } else if ( mode == OGC_elemSpecial ) { + this->drawSpecial(gc, tStep); + } else { + OOFEM_ERROR("unsupported mode"); + } +} + + + +void BondLink3d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + WCRec p [ 2 ]; /* points */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getElementColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + +void BondLink3d :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ + GraphicObj *go; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + double defScale = gc.getDefScale(); + + WCRec p [ 2 ]; /* points */ + + EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(3, tStep, defScale); + + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(3, tStep, defScale); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EMAddGraphicsToModel(ESIModel(), go); +} + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/Interfaces/bondlink3d.h b/src/sm/Elements/Interfaces/bondlink3d.h new file mode 100644 index 000000000..fb6cd941d --- /dev/null +++ b/src/sm/Elements/Interfaces/bondlink3d.h @@ -0,0 +1,143 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef bondlink3d_h +#define bondlink3d_h + +#include "../structuralelement.h" + +///@name Input fields for BondLink3d +//@{ +#define _IFT_BondLink3d_Name "bondlink3d" +#define _IFT_BondLink3d_length "length" +#define _IFT_BondLink3d_diameter "diameter" +#define _IFT_BondLink3d_dirvector "dirvector" +#define _IFT_BondLink3d_length_end "length_end" +//@} + +namespace oofem { +/** + * This class implements a bond link for connecting beam (frame) and continuum elements in unstructured meshes. + * The main idea is to use the rotation of the beam element and the rigid arm from the beam node to the continuum element node + * to compute the displacement jump along the rebar element (and two components, which are perpendicular to each other and lie + * in a plane for which the direction along the rebar is normal to. + * This element differs from the lattice link element, for which both the beam and the lattice nodes have rotational DOFs and + * therefore the lattice node's rotations can be used to compute the displacement jump at the beam element location. + * + * @author: Peter Grassl + */ + +class BondLink3d : public StructuralElement +{ +protected: + double bondLength = 0.; + + FloatMatrix localCoordinateSystem; + double bondDiameter = 0.; + FloatArray directionVector; + int geometryFlag = 0; + double bondEndLength = 0.; + FloatArray rigid; + FloatArray globalCentroid; + +public: + BondLink3d(int n, Domain *); + + double computeVolumeAround(GaussPoint *aGaussPoint) override; + + double giveLength(); + + MaterialMode giveMaterialMode() override { return _3dInterface; } + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + /** + * This function is different from the standard computeGlobalCordinates + * function as it returns the global coordinates of the gausspoint + * independent to the value of the lcoords. + */ + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + virtual double giveBondLength(); + + virtual double giveBondDiameter(); + + virtual double giveBondEndLength(); + + int computeNumberOfDofs() override { return 9; } + + void giveDofManDofIDMask(int inode, IntArray &) const override; + + virtual void giveGPCoordinates(FloatArray &coords); + + virtual void computeGeometryProperties(); + + void giveInternalForcesVector(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) override; + + const char *giveInputRecordName() const override { return _IFT_BondLink3d_Name; } + const char *giveClassName() const override { return "BondLink3d"; } + void initializeFrom(InputRecord &ir) override; + + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; + +#ifdef __OOFEG + void drawYourself(oofegGraphicContext &context, TimeStep *tStep) override; + void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &, TimeStep *tStep, UnknownType) override; +#endif + + +protected: + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + bool computeGtoLRotationMatrix(FloatMatrix &) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + + + /** + * This computes the geometrical properties of the element. It is called only once. + */ + void computePropertiesOfCrossSection(); + + void computeGaussPoints() override; + integrationDomain giveIntegrationDomain() const override { return _Line; } +}; +} // end namespace oofem +#endif diff --git a/src/sm/Elements/Interfaces/bondlink3dboundary.C b/src/sm/Elements/Interfaces/bondlink3dboundary.C new file mode 100644 index 000000000..9eb8a6ae0 --- /dev/null +++ b/src/sm/Elements/Interfaces/bondlink3dboundary.C @@ -0,0 +1,471 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "../sm/Elements/Interfaces/bondlink3dboundary.h" +#include "../sm/Materials/structuralms.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "../sm/Elements/structuralelement.h" +#include "contextioerr.h" +#include "datastream.h" +#include "classfactory.h" +#include "../sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/structuralcrosssection.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { +REGISTER_Element(BondLink3dBoundary); + +BondLink3dBoundary :: BondLink3dBoundary(int n, Domain *aDomain) : BondLink3d(n, aDomain) +{ + numberOfDofMans = 3; + geometryFlag = 0; +} + +BondLink3dBoundary :: ~BondLink3dBoundary() +{} + +void +BondLink3dBoundary :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + FloatMatrix d, b, bt, db; + FloatArray u, slip; + + this->computeVectorOf(VM_Total, tStep, u); + + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + answer.clear(); + + GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); + this->computeBmatrixAt(gp, b); + bt.beTranspositionOf(b); + + if ( !this->isActivated(tStep) ) { + slip.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); + slip.zero(); + } + slip.beProductOf(b, u); + + answer.resize(9, 9); + answer.zero(); + + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + db.beProductOf(d, b); + answer.beProductOf(bt, db); + + //Introduce integration of bond strength + double area = this->computeVolumeAround(gp) / this->giveLength(); + answer.times(area); + + + return; +} + +void +BondLink3dBoundary :: computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + FloatArray unitCellSize; + unitCellSize.resize(3); + unitCellSize.at(1) = this->giveNode(3)->giveCoordinate(1); + unitCellSize.at(2) = this->giveNode(3)->giveCoordinate(2); + unitCellSize.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray switches1, switches2; + this->giveSwitches(switches1, this->location.at(1) ); + this->giveSwitches(switches2, this->location.at(2) ); + + FloatMatrix k1, k2; + k1.resize(6, 9); + k2.resize(6, 9); + + for ( int i = 1; i <= 3; i++ ) { + k1.at(i, 3 * i - 2) = unitCellSize.at(1) * switches1.at(1); + k1.at(i, 3 * i - 1) = unitCellSize.at(2) * switches1.at(2); + k1.at(i, 3 * i) = unitCellSize.at(3) * switches1.at(3); + } + + for ( int i = 1; i <= 3; i++ ) { + k2.at(i, 3 * i - 2) = unitCellSize.at(1) * switches2.at(1); + k2.at(i, 3 * i - 1) = unitCellSize.at(2) * switches2.at(2); + k2.at(i, 3 * i) = unitCellSize.at(3) * switches2.at(3); + } + + answer.resize(12, 12); + answer.beUnitMatrix(); + answer.resizeWithData(12, 21); + + answer.assemble(k1, { 1, 2, 3, 4, 5, 6 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21 }); + answer.assemble(k2, { 7, 8, 9, 10, 11, 12 }, { 13, 14, 15, 16, 17, 18, 19, 20, 21 }); +} + + +bool +BondLink3dBoundary :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + int i, j; + + answer.resize(9, 9); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( i = 1; i <= 3; i++ ) { + for ( j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + answer.at(i + 6, j + 6) = lcs.at(i, j); + // answer.at(i + 9, j + 9) = lcs.at(i, j); + } + } + + return 1; +} + +int +BondLink3dBoundary :: giveLocalCoordinateSystem(FloatMatrix &answer) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer = this->localCoordinateSystem; + + return 1; +} + + + +void +BondLink3dBoundary :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 1 ) { + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; + } else if ( inode == 2 ) { + answer = { D_u, D_v, D_w }; + } else if ( inode == 3 ) { + answer = { E_xx, E_xy, E_xz, E_yx, E_yy, E_yz, E_zx, E_zy, E_zz }; + } +} + +void +BondLink3dBoundary :: initializeFrom(InputRecord &ir) +{ + // first call parent + StructuralElement :: initializeFrom(ir); + + location.resize(2); + IR_GIVE_FIELD(ir, location, _IFT_LatticeLink3dBoundary_location); // Macro +} + + + +void +BondLink3dBoundary :: computeGeometryProperties() +{ + //coordinates of the two nodes + Node *nodeA, *nodeB; + FloatArray coordsA(3), coordsB(3); + + //Order of nodes. Important, because continuum node does not have rotational DOFs. + //Beam node + nodeA = this->giveNode(1); + //Continuum node + nodeB = this->giveNode(2); + + + //Calculate components of distance from continuum node to lattice node. + for ( int i = 0; i < 3; i++ ) { + coordsA.at(i + 1) = nodeA->giveCoordinate(i + 1); + coordsB.at(i + 1) = nodeB->giveCoordinate(i + 1); + } + + FloatArray rigidGlobal(3); + + //Calculate normal vector + for ( int i = 0; i < 3; i++ ) { + rigidGlobal.at(i + 1) = coordsA.at(i + 1) - coordsB.at(i + 1); + } + + //Construct an initial temporary local coordinate system + FloatArray normal(3), s(3), t(3); + + //Calculate normal vector + normal = this->directionVector; + normal.normalize(); + + //Construct two perpendicular axis so that n is normal to the plane which they create + //Check, if one of the components of the normal-direction is zero + if ( normal.at(1) == 0 ) { + s.at(1) = 0.; + s.at(2) = normal.at(3); + s.at(3) = -normal.at(2); + } else if ( normal.at(2) == 0 ) { + s.at(1) = normal.at(3); + s.at(2) = 0.; + s.at(3) = -normal.at(1); + } else { + s.at(1) = normal.at(2); + s.at(2) = -normal.at(1); + s.at(3) = 0.; + } + + s.normalize(); + + t.beVectorProductOf(normal, s); + t.normalize(); + + //Set up rotation matrix + FloatMatrix lcs(3, 3); + + this->localCoordinateSystem.resize(3, 3); + this->localCoordinateSystem.zero(); + + for ( int i = 1; i <= 3; i++ ) { + this->localCoordinateSystem.at(1, i) = normal.at(i); + this->localCoordinateSystem.at(2, i) = s.at(i); + this->localCoordinateSystem.at(3, i) = t.at(i); + } + + // Rotate rigidarm vector into local coordinate system + + this->rigid.beProductOf(localCoordinateSystem, rigidGlobal); + + + this->globalCentroid.resize(3); + for ( int i = 1; i <= 3; i++ ) { + this->globalCentroid.at(i) = nodeB->giveCoordinate(i); + ; + } + + this->geometryFlag = 1; + + return; +} + +void +BondLink3dBoundary :: saveContext(DataStream &stream, ContextMode mode) +{ + StructuralElement :: saveContext(stream, mode); +} + + +void +BondLink3dBoundary :: restoreContext(DataStream &stream, ContextMode mode) +{ + StructuralElement :: restoreContext(stream, mode); +} + + +void +BondLink3dBoundary :: giveInternalForcesVector(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) +{ + FloatMatrix b, bt; + FloatArray u, stress(6), slip(6); + + // This function can be quite costly to do inside the loops when one has many slave dofs. + this->computeVectorOf(VM_Total, tStep, u); + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + // zero answer will resize accordingly when adding first contribution + answer.clear(); + + for ( GaussPoint *gp: * this->giveDefaultIntegrationRulePtr() ) { + StructuralMaterialStatus *matStat = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); + this->computeBmatrixAt(gp, b); + bt.beTranspositionOf(b); + + if ( useUpdatedGpRecord == 1 ) { + stress = matStat->giveStressVector(); + } else { + if ( !this->isActivated(tStep) ) { + slip.resize(6); + slip.zero(); + } + slip.beProductOf(b, u); + this->computeStressVector(stress, slip, gp, tStep); + } + + answer.beProductOf(bt, stress); + + //Introduce integration of bond strength + double area = this->computeVolumeAround(gp) / this->giveLength(); + answer.times(area); + } + + // if inactive update state, but no contribution to global system + if ( !this->isActivated(tStep) ) { + answer.zero(); + return; + } +} + + + +void +BondLink3dBoundary :: giveSwitches(IntArray &answer, int location) { + int counter = 1; + for ( int x = -1; x < 2; x++ ) { + for ( int y = -1; y < 2; y++ ) { + for ( int z = -1; z < 2; z++ ) { + if ( !( z == 0 && y == 0 && x == 0 ) ) { + if ( counter == location ) { + answer(0) = x; + answer(1) = y; + answer(2) = z; + } + counter++; + } + } + } + } + return; +} + + +void +BondLink3dBoundary :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + this->giveStructuralCrossSection()->giveCharMaterialStiffnessMatrix(answer, rMode, gp, tStep); +} + +void +BondLink3dBoundary :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->giveRealStresses(strain, gp, tStep); +} + + + +#ifdef __OOFEG + +void +BondLink3dBoundary :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + } else if ( mode == OGC_deformedGeometry ) { + this->drawDeformedGeometry(gc, tStep, DisplacementVector); + } else if ( mode == OGC_eigenVectorGeometry ) { + this->drawDeformedGeometry(gc, tStep, EigenVector); + } else if ( mode == OGC_scalarPlot ) { + this->drawScalar(gc, tStep); + } else if ( mode == OGC_elemSpecial ) { + this->drawSpecial(gc, tStep); + } else { + OOFEM_ERROR("unsupported mode"); + } +} + + + +void BondLink3dBoundary :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + WCRec p [ 2 ]; /* points */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getElementColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + +void BondLink3dBoundary :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ + GraphicObj *go; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + double defScale = gc.getDefScale(); + + WCRec p [ 2 ]; /* points */ + + EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(3, tStep, defScale); + + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(3, tStep, defScale); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EMAddGraphicsToModel(ESIModel(), go); +} + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/Interfaces/bondlink3dboundary.h b/src/sm/Elements/Interfaces/bondlink3dboundary.h new file mode 100644 index 000000000..2456d0446 --- /dev/null +++ b/src/sm/Elements/Interfaces/bondlink3dboundary.h @@ -0,0 +1,111 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef bondlink3dboundary_h +#define bondlink3dboundary_h + +#include "bondlink3d.h" + +///@name Input fields for BondLink3d +//@{ +#define _IFT_BondLink3dBoundary_Name "bondlink3dboundary" +#define _IFT_LatticeLink3dBoundary_location "location" +//@} + +namespace oofem { +/** + * This class implements a bond link for connecting beam (frame) and continuum elements in unstructured meshes. + * The main idea is to use the rotation of the beam element and the rigid arm from the beam node to the continuum element node + * to compute the displacement jump along the rebar element (and two components, which are perpendicular to each other and lie + * in a plane for which the direction along the rebar is normal to. + * At least one node is located at the image boundary. + * These nodes are replaced with a periodic mirror nodes and a control node is used to impose the macroscopic (average) strain. + * MACROSCOPIC INPUT: DEFORMATION GRADIENT TENSOR (3D, 9 COMPONENTS: Exx Exy Exz Eyx Eyy Eyz Ezx Ezy Ezz) + * + */ + +class BondLink3dBoundary : public BondLink3d +{ +protected: + IntArray location; + +public: + BondLink3dBoundary(int n, Domain *); + virtual ~BondLink3dBoundary(); + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + int computeNumberOfDofs() override { return 18; } + + void giveDofManDofIDMask(int inode, IntArray &) const override; + + void computeGeometryProperties() override; + + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + + const char *giveInputRecordName() const override { return _IFT_BondLink3dBoundary_Name; } + const char *giveClassName() const override { return "BondLink3dBoundary"; } + void initializeFrom(InputRecord &ir) override; + + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; + +#ifdef __OOFEG + void drawYourself(oofegGraphicContext &context, TimeStep *tStep) override; + void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &, TimeStep *tStep, UnknownType) override; +#endif + + +protected: + bool computeGtoLRotationMatrix(FloatMatrix &) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + + virtual void computeTransformationMatrix(FloatMatrix &answer, TimeStep *tStep); + void giveSwitches(IntArray &answer, int location); + + /** + * This computes the geometrical properties of the element. It is called only once. + */ + void computePropertiesOfCrossSection(); + + integrationDomain giveIntegrationDomain() const override { return _Line; } +}; +} // end namespace oofem +#endif //bondlink3dboundary_h diff --git a/src/sm/Elements/Interfaces/bondlink3dtruss.C b/src/sm/Elements/Interfaces/bondlink3dtruss.C new file mode 100644 index 000000000..ee9ac026c --- /dev/null +++ b/src/sm/Elements/Interfaces/bondlink3dtruss.C @@ -0,0 +1,523 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "../sm/Elements/Interfaces/bondlink3dtruss.h" +#include "../sm/Materials/structuralms.h" +#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "intarray.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "mathfem.h" +#include "../sm/Elements/structuralelement.h" +#include "contextioerr.h" +#include "datastream.h" +#include "classfactory.h" +#include "../sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { +REGISTER_Element(BondLink3dTruss); + +BondLink3dTruss::BondLink3dTruss(int n, Domain *aDomain) : StructuralElement(n, aDomain) +{ + numberOfDofMans = 2; +} + + +double +BondLink3dTruss::computeVolumeAround(GaussPoint *aGaussPoint) +{ + //Returns artifical volume (bond area times bond length) so that general parts of post processing work (dissipated energy, etc.) + //Later on this artificial volume is divided by the bond length again so that the correct bond area is used. + return pow(this->bondLength, 2.) * this->bondDiameter * M_PI; +} + + +void +BondLink3dTruss::computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) +// Returns the strain matrix of the receiver. +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + //Assemble Bmatrix based on three rigid arm components + answer.resize(3, 6); + answer.zero(); + + //Normal displacement jump in x-direction + //First node + answer.at(1, 1) = 1.; + //Second node + answer.at(1, 4) = -1.; + + //Shear displacement jump in y-plane + //first node + answer.at(2, 2) = 1.; + //Second node + answer.at(2, 5) = -1.; + + //Shear displacement jump in z-plane + //first node + answer.at(3, 3) = 1.; + //Second node + answer.at(3, 6) = -1.; + + return; +} + +void +BondLink3dTruss::giveGPCoordinates(FloatArray &coords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + coords.resize(3); + coords = this->globalCentroid; + return; +} + + +void +BondLink3dTruss::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + FloatMatrix d, b, bt, db; + FloatArray u, slip; + + this->computeVectorOf(VM_Total, tStep, u); + + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + answer.clear(); + + GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); + this->computeBmatrixAt(gp, b); + bt.beTranspositionOf(b); + + if ( !this->isActivated(tStep) ) { + slip.resize( StructuralMaterial::giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + slip.zero(); + } + slip.beProductOf(b, u); + + answer.resize(6, 6); + answer.zero(); + + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + db.beProductOf(d, b); + answer.beProductOf(bt, db); + + //Introduce integration of bond strength + double area = this->computeVolumeAround(gp) / this->giveLength(); + answer.times(area); + + + return; +} + +void BondLink3dTruss::computeGaussPoints() +// Sets up the array of Gauss Points of the receiver. +{ + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ]->SetUpPointsOnLine(1, _3dMat); +} + + + + +bool +BondLink3dTruss::computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + int i, j; + + answer.resize(6, 6); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( i = 1; i <= 3; i++ ) { + for ( j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + } + } + + return 1; +} + + +int +BondLink3dTruss::giveLocalCoordinateSystem(FloatMatrix &answer) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer = this->localCoordinateSystem; + + return 1; +} + +double +BondLink3dTruss::giveBondLength() +{ + return this->bondLength; +} + + + +double +BondLink3dTruss::giveBondDiameter() +{ + return this->bondDiameter; +} + + +void +BondLink3dTruss::giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = { D_u, D_v, D_w }; +} + +void +BondLink3dTruss::initializeFrom(InputRecord &ir) +{ + // first call parent + StructuralElement::initializeFrom(ir); + + IR_GIVE_FIELD(ir, this->bondLength, _IFT_BondLink3dTruss_length); + + IR_GIVE_FIELD(ir, this->bondDiameter, _IFT_BondLink3dTruss_diameter); + + IR_GIVE_FIELD(ir, this->directionVector, _IFT_BondLink3dTruss_dirvector); +} + + +int +BondLink3dTruss::computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer.resize(3); + answer = this->globalCentroid; + + return 1; +} + + +void +BondLink3dTruss::computeGeometryProperties() +{ + //coordinates of the two nodes + Node *nodeA, *nodeB; + FloatArray coordsA(3), coordsB(3); + + //Order of nodes. Important, because continuum node does not have rotational DOFs. + //Beam node + nodeA = this->giveNode(1); + //Continuum node + nodeB = this->giveNode(2); + + + //Calculate components of distance from continuum node to lattice node. + for ( int i = 0; i < 3; i++ ) { + coordsA.at(i + 1) = nodeA->giveCoordinate(i + 1); + coordsB.at(i + 1) = nodeB->giveCoordinate(i + 1); + } + + //Construct an initial temporary local coordinate system + FloatArray normal(3), s(3), t(3); + + //Calculate normal vector + normal = this->directionVector; + normal.normalize(); + + //Construct two perpendicular axis so that n is normal to the plane which they create + //Check, if one of the components of the normal-direction is zero + if ( normal.at(1) == 0 ) { + s.at(1) = 0.; + s.at(2) = normal.at(3); + s.at(3) = -normal.at(2); + } else if ( normal.at(2) == 0 ) { + s.at(1) = normal.at(3); + s.at(2) = 0.; + s.at(3) = -normal.at(1); + } else { + s.at(1) = normal.at(2); + s.at(2) = -normal.at(1); + s.at(3) = 0.; + } + + s.normalize(); + + t.beVectorProductOf(normal, s); + t.normalize(); + + //Set up rotation matrix + FloatMatrix lcs(3, 3); + + this->localCoordinateSystem.resize(3, 3); + this->localCoordinateSystem.zero(); + + for ( int i = 1; i <= 3; i++ ) { + this->localCoordinateSystem.at(1, i) = normal.at(i); + this->localCoordinateSystem.at(2, i) = s.at(i); + this->localCoordinateSystem.at(3, i) = t.at(i); + } + + this->globalCentroid.resize(3); + for ( int i = 1; i <= 3; i++ ) { + //nodeA and nodeB should be at same point + this->globalCentroid.at(i) = nodeB->giveCoordinate(i); + } + + this->geometryFlag = 1; + + return; +} + +void +BondLink3dTruss::saveContext(DataStream &stream, ContextMode mode) +{ + StructuralElement::saveContext(stream, mode); +} + + +void +BondLink3dTruss::restoreContext(DataStream &stream, ContextMode mode) +{ + StructuralElement::restoreContext(stream, mode); +} + + +void +BondLink3dTruss::giveInternalForcesVector(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) +// +// returns nodal representation of real internal forces - necessary only for +// non-linear analysis. +// if useGpRecord == 1 then data stored in gp->giveStressVector() are used +// instead computing stressVector through this->ComputeStressVector(); +// this must be done after you want internal forces after element->updateYourself() +// has been called for the same time step. +// +{ + FloatMatrix b; + FloatArray u, stress, strain; + + // This function can be quite costly to do inside the loops when one has many slave dofs. + this->computeVectorOf(VM_Total, tStep, u); + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + // zero answer will resize accordingly when adding first contribution + answer.clear(); + + for ( GaussPoint *gp : * this->giveDefaultIntegrationRulePtr() ) { + this->computeBmatrixAt(gp, b); + + if ( useUpdatedGpRecord == 1 ) { + auto status = gp->giveMaterialStatus(); + StructuralMaterialStatus *matStat = dynamic_cast< StructuralMaterialStatus * >( status ); + if ( matStat ) { + stress = matStat->giveStressVector(); + } else { + StructuralInterfaceMaterialStatus *ms = static_cast< StructuralInterfaceMaterialStatus * >( status ); + stress = ms->giveTraction(); + } + } else { + if ( !this->isActivated(tStep) ) { + strain.resize( StructuralMaterial::giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + strain.zero(); + } + strain.beProductOf(b, u); + this->computeStressVector(stress, strain, gp, tStep); + } + + // updates gp stress and strain record acording to current + // increment of displacement + if ( stress.giveSize() == 0 ) { + break; + } + + // now every gauss point has real stress vector + // compute nodal representation of internal forces using f = B^T*Sigma dV + double dV = this->computeVolumeAround(gp) / this->giveLength(); + ; + if ( stress.giveSize() == 6 ) { + // It may happen that e.g. plane strain is computed + // using the default 3D implementation. If so, + // the stress needs to be reduced. + // (Note that no reduction will take place if + // the simulation is actually 3D.) + FloatArray stressTemp; + StructuralMaterial::giveReducedSymVectorForm( stressTemp, stress, gp->giveMaterialMode() ); + answer.plusProduct(b, stressTemp, dV); + } else { + answer.plusProduct(b, stress, dV); + } + } + + // if inactive update state, but no contribution to global system + if ( !this->isActivated(tStep) ) { + answer.zero(); + return; + } +} + + +double +BondLink3dTruss::giveLength() +{ + //returns the bond length, not the length between the two nodes, which should be zero + return this->bondLength; +} + +void +BondLink3dTruss::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< StructuralInterfaceCrossSection * >( this->giveCrossSection() )->give3dStiffnessMatrix_Eng(rMode, gp, tStep); +} + +void +BondLink3dTruss::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< StructuralInterfaceCrossSection * >( this->giveCrossSection() )->giveEngTraction_3d(strain, gp, tStep); +} + + + +#ifdef __OOFEG + +void +BondLink3dTruss::drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + } else if ( mode == OGC_deformedGeometry ) { + this->drawDeformedGeometry(gc, tStep, DisplacementVector); + } else if ( mode == OGC_eigenVectorGeometry ) { + this->drawDeformedGeometry(gc, tStep, EigenVector); + } else if ( mode == OGC_scalarPlot ) { + this->drawScalar(gc, tStep); + } else if ( mode == OGC_elemSpecial ) { + this->drawSpecial(gc, tStep); + } else { + OOFEM_ERROR("unsupported mode"); + } +} + + + +void BondLink3dTruss::drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + WCRec p[ 2 ]; /* points */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor( gc.getElementColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + +void BondLink3dTruss::drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ + GraphicObj *go; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + double defScale = gc.getDefScale(); + + WCRec p[ 2 ]; /* points */ + + EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); + EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(3, tStep, defScale); + + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(3, tStep, defScale); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EMAddGraphicsToModel(ESIModel(), go); +} + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/Interfaces/bondlink3dtruss.h b/src/sm/Elements/Interfaces/bondlink3dtruss.h new file mode 100644 index 000000000..263d7296f --- /dev/null +++ b/src/sm/Elements/Interfaces/bondlink3dtruss.h @@ -0,0 +1,133 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef bondlink3dtruss_h +#define bondlink3dtruss_h + +#include "../structuralelement.h" + +///@name Input fields for BondLink3dTruss +//@{ +#define _IFT_BondLink3dTruss_Name "bondlink3dtruss" +#define _IFT_BondLink3dTruss_length "length" +#define _IFT_BondLink3dTruss_diameter "diameter" +#define _IFT_BondLink3dTruss_dirvector "dirvector" +//@} + +namespace oofem { +/** + * This class implements a bond link for connecting truss and continuum elements with coinciding nodes. + * + * @author: Peter Grassl + */ + +class BondLink3dTruss : public StructuralElement +{ +protected: + double bondLength = 0.; + + FloatMatrix localCoordinateSystem; + double bondDiameter = 0.; + FloatArray directionVector; + int geometryFlag = 0; + FloatArray rigid; + FloatArray globalCentroid; + +public: + BondLink3dTruss(int n, Domain *); + + double computeVolumeAround(GaussPoint *aGaussPoint) override; + + double giveLength(); + + MaterialMode giveMaterialMode() override { return _3dInterface; } + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + /** + * This function is different from the standard computeGlobalCordinates + * function as it returns the global coordinates of the gausspoint + * independent to the value of the lcoords. + */ + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + virtual double giveBondLength(); + + virtual double giveBondDiameter(); + + int computeNumberOfDofs() override { return 6; } + + void giveDofManDofIDMask(int inode, IntArray &) const override; + + virtual void giveGPCoordinates(FloatArray &coords); + + virtual void computeGeometryProperties(); + + void giveInternalForcesVector(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) override; + + const char *giveInputRecordName() const override { return _IFT_BondLink3dTruss_Name; } + const char *giveClassName() const override { return "BondLink3dTruss"; } + void initializeFrom(InputRecord &ir) override; + + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; + +#ifdef __OOFEG + void drawYourself(oofegGraphicContext &context, TimeStep *tStep) override; + void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &, TimeStep *tStep, UnknownType) override; +#endif + + +protected: + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + bool computeGtoLRotationMatrix(FloatMatrix &) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + + /** + * This computes the geometrical properties of the element. It is called only once. + */ + void computePropertiesOfCrossSection(); + + void computeGaussPoints() override; + integrationDomain giveIntegrationDomain() const override { return _Line; } +}; +} // end namespace oofem +#endif diff --git a/src/sm/Elements/Interfaces/cohsur3d.C b/src/sm/Elements/Interfaces/cohsur3d.C index a776243a8..8e74b5482 100644 --- a/src/sm/Elements/Interfaces/cohsur3d.C +++ b/src/sm/Elements/Interfaces/cohsur3d.C @@ -32,16 +32,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Interfaces/cohsur3d.h" +#include "sm/Elements/Interfaces/cohsur3d.h" +#include "element.h" #include "dof.h" #include "node.h" #include "particle.h" #include "gaussintegrationrule.h" #include "floatmatrix.h" +#include "floatmatrixf.h" #include "intarray.h" #include "floatarray.h" +#include "floatarrayf.h" #include "mathfem.h" -#include "../sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "classfactory.h" #ifdef __OOFEG @@ -208,7 +211,7 @@ void CohesiveSurface3d :: computeGaussPoints() // The Gauss point is used only when methods from crosssection and/or material // classes are requested. integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this); } @@ -230,14 +233,14 @@ CohesiveSurface3d :: giveDofManDofIDMask(int inode, IntArray &answer) const void CohesiveSurface3d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_3d(answer, gp, strain, tStep); + answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->giveEngTraction_3d(strain, gp, tStep); } void CohesiveSurface3d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give3dStiffnessMatrix_Eng(answer, rMode, gp, tStep); + answer = static_cast< StructuralInterfaceCrossSection* >(this->giveCrossSection())->give3dStiffnessMatrix_Eng(rMode, gp, tStep); } @@ -360,22 +363,16 @@ CohesiveSurface3d :: evaluateLocalCoordinateSystem() } -IRResultType -CohesiveSurface3d :: initializeFrom(InputRecord *ir) +void +CohesiveSurface3d :: initializeFrom(InputRecord &ir) { - IRResultType result; - // first call parent - result = StructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralElement :: initializeFrom(ir); // read the area from the input file IR_GIVE_FIELD(ir, area, _IFT_CohSur3d_area); if ( area < 0. ) { - OOFEM_WARNING("negative area specified"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_CohSur3d_area, "negative area specified"); } // read shift constants of second (periodic) particle form the input file (if defined) @@ -387,13 +384,11 @@ CohesiveSurface3d :: initializeFrom(InputRecord *ir) // evaluate number of Dof Managers numberOfDofMans = dofManArray.giveSize(); if ( numberOfDofMans <= 0 ) { - OOFEM_WARNING("unread nodes: Element %d", this->giveNumber() ); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Element_nodes, "unread nodes" ); } if ( ( numberOfDofMans == 3 ) & ( kx == 0 ) & ( ky == 0 ) & ( kz == 0 ) ) { - OOFEM_WARNING("no periodic shift defined: Element %d", this->giveNumber() ); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_CohSur3d_kx, "no periodic shift defined" ); } @@ -409,16 +404,13 @@ CohesiveSurface3d :: initializeFrom(InputRecord *ir) // evaluate the length giveLength(); if ( length <= 0. ) { - OOFEM_WARNING("negative length evaluated: Element %d", this->giveNumber() ); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Element_nodes, "negative length evaluated"); // evaluate the coordinates of the center evaluateCenter(); /// @todo This will never execute. Verify this / Mikael } // evaluate the local coordinate system evaluateLocalCoordinateSystem(); - - return IRRT_OK; } diff --git a/src/sm/Elements/Interfaces/cohsur3d.h b/src/sm/Elements/Interfaces/cohsur3d.h index 6f2b84942..072ab3be0 100644 --- a/src/sm/Elements/Interfaces/cohsur3d.h +++ b/src/sm/Elements/Interfaces/cohsur3d.h @@ -35,7 +35,7 @@ #ifndef cohsur3d_h #define cohsur3d_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" ///@name Input fields for CohSur3d //@{ @@ -70,35 +70,35 @@ class CohesiveSurface3d : public StructuralElement CohesiveSurface3d(int n, Domain * d); virtual ~CohesiveSurface3d() { } - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui); - virtual double computeVolumeAround(GaussPoint *gp); - virtual int computeNumberOfDofs() { return 6 * giveNumberOfNodes(); } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) override; + double computeVolumeAround(GaussPoint *gp) override; + int computeNumberOfDofs() override { return 6 * giveNumberOfNodes(); } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; double giveLength(); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) { } - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override { } + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; // definition & identification - virtual const char *giveClassName() const { return "CohesiveSurface3d"; } - virtual const char *giveInputRecordName() const { return _IFT_CohesiveSurface3d_Name; } + const char *giveClassName() const override { return "CohesiveSurface3d"; } + const char *giveInputRecordName() const override { return _IFT_CohesiveSurface3d_Name; } // input and output - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif protected: - virtual void computeGaussPoints(); + void computeGaussPoints() override; void evaluateCenter(); void evaluateLocalCoordinateSystem(); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual MaterialMode giveMaterialMode() { return _3dInterface; } + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + MaterialMode giveMaterialMode() override { return _3dInterface; } }; } // namespace oofem #endif diff --git a/src/sm/Elements/Interfaces/intelline1.C b/src/sm/Elements/Interfaces/intelline1.C index 61c23b32e..c8624fb39 100644 --- a/src/sm/Elements/Interfaces/intelline1.C +++ b/src/sm/Elements/Interfaces/intelline1.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Interfaces/intelline1.h" -#include "../sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/Elements/Interfaces/intelline1.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "node.h" #include "gausspoint.h" #include "gaussintegrationrule.h" @@ -44,6 +44,7 @@ #include "mathfem.h" #include "fei2dlinelin.h" #include "classfactory.h" +#include "nodalaveragingrecoverymodel.h" #ifdef __OOFEG #include "oofeggraphiccontext.h" @@ -60,8 +61,6 @@ IntElLine1 :: IntElLine1(int n, Domain *aDomain) : StructuralInterfaceElement(n, aDomain) { numberOfDofMans = 4; - axisymmode = false; - numberOfGaussPoints = 4; } @@ -70,10 +69,7 @@ void IntElLine1 :: computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer) { // Returns the modified N-matrix which multiplied with u give the spatial jump. - - FloatArray N; - FEInterpolation *interp = this->giveInterpolation(); - interp->evalN( N, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + auto N = interp.evalN(ip->giveNaturalCoordinates().at(1)); answer.resize(2, 8); answer.zero(); @@ -87,27 +83,26 @@ IntElLine1 :: computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer) void IntElLine1 :: computeGaussPoints() -// Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); -// integrationRulesArray[ 0 ].reset( new LobattoIntegrationRule (1,this, 1, 2, false) ); +// integrationRulesArray[ 0 ] = std::make_unique(1,this, 1, 2, false); // integrationRulesArray [ 0 ]->SetUpPointsOnLine(2, _2dInterface); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); integrationRulesArray [ 0 ]->SetUpPointsOnLine(this->numberOfGaussPoints, _2dInterface); } } -void -IntElLine1 :: computeCovarBaseVectorAt(IntegrationPoint *ip, FloatArray &G) +FloatArrayF<2> +IntElLine1 :: computeCovarBaseVectorAt(IntegrationPoint *ip) const { - FloatMatrix dNdxi; FEInterpolation *interp = this->giveInterpolation(); + FloatMatrix dNdxi; interp->evaldNdxi( dNdxi, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - G.resize(2); - G.zero(); + + FloatArrayF<2> G; int numNodes = this->giveNumberOfNodes(); for ( int i = 1; i <= dNdxi.giveNumberOfRows(); i++ ) { double X1_i = 0.5 * ( this->giveNode(i)->giveCoordinate(1) + this->giveNode(i + numNodes / 2)->giveCoordinate(1) ); // (mean) point on the fictious mid surface @@ -115,20 +110,19 @@ IntElLine1 :: computeCovarBaseVectorAt(IntegrationPoint *ip, FloatArray &G) G.at(1) += dNdxi.at(i, 1) * X1_i; G.at(2) += dNdxi.at(i, 1) * X2_i; } + return G; } double IntElLine1 :: computeAreaAround(IntegrationPoint *ip) { - FloatArray G; - this->computeCovarBaseVectorAt(ip, G); + auto G = this->computeCovarBaseVectorAt(ip); - double weight = ip->giveWeight(); - double ds = sqrt( G.dotProduct(G) ) * weight; + double weight = ip->giveWeight(); + double ds = norm(G) * weight; if ( this->axisymmode ) { int numNodes = this->giveNumberOfNodes(); - FloatArray N; - this->interp.evalN( N, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + auto N = this->interp.evalN(ip->giveNaturalCoordinates().at(1)); // interpolate radius double r = 0.0; for ( int i = 1; i <= N.giveSize(); i++ ) { @@ -136,7 +130,6 @@ IntElLine1 :: computeAreaAround(IntegrationPoint *ip) r += N.at(i) * X_i; } return ds * r; - } else { // regular 2d double thickness = this->giveCrossSection()->give(CS_Thickness, ip); return ds * thickness; @@ -144,46 +137,39 @@ IntElLine1 :: computeAreaAround(IntegrationPoint *ip) } -IRResultType -IntElLine1 :: initializeFrom(InputRecord *ir) +void +IntElLine1 :: initializeFrom(InputRecord &ir) { - this->axisymmode = false; - this->axisymmode = ir->hasField(_IFT_IntElLine1_axisymmode); - IRResultType result = StructuralInterfaceElement :: initializeFrom(ir); - + StructuralInterfaceElement :: initializeFrom(ir); + this->axisymmode = ir.hasField(_IFT_IntElLine1_axisymmode); // Check if node numbering is ok int nodeInd1 = this->giveDofManagerNumber(1); int arrayInd1 = domain->giveDofManPlaceInArray(nodeInd1); DofManager *node1 = domain->giveDofManager(arrayInd1); - const FloatArray &x1 = *(node1->giveCoordinates()); + const auto &x1 = node1->giveCoordinates(); // DofManager *node2 = this->giveDofManager(2); int nodeInd2 = this->giveDofManagerNumber(2); int arrayInd2 = domain->giveDofManPlaceInArray(nodeInd2); DofManager *node2 = domain->giveDofManager(arrayInd2); - const FloatArray &x2 = *(node2->giveCoordinates()); + const auto &x2 = node2->giveCoordinates(); // DofManager *node3 = this->giveDofManager(3); int nodeInd3 = this->giveDofManagerNumber(3); int arrayInd3 = domain->giveDofManPlaceInArray(nodeInd3); DofManager *node3 = domain->giveDofManager(arrayInd3); - const FloatArray &x3 = *(node3->giveCoordinates()); + const auto &x3 = node3->giveCoordinates(); - double L2 = x1.distance_square(x2); - double L3 = x1.distance_square(x3); + double L2 = distance_square(x1, x2); + double L3 = distance_square(x1, x3); - - if(L2 < L3) { - printf("Renumbering element %d\n.\n", this->giveNumber()); - IntArray dofManArrayTmp = {dofManArray.at(3), dofManArray.at(1), dofManArray.at(4), dofManArray.at(2)}; - dofManArray = std::move(dofManArrayTmp); + if ( L2 < L3 ) { + printf("Renumbering element %d\n.\n", this->giveNumber()); + dofManArray = {dofManArray.at(3), dofManArray.at(1), dofManArray.at(4), dofManArray.at(2)}; } - - - return result; } @@ -198,9 +184,8 @@ IntElLine1 :: computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) { // Transformation matrix to the local coordinate system // xy plane - FloatArray G; - this->computeCovarBaseVectorAt(gp, G); - G.normalize(); + auto G = this->computeCovarBaseVectorAt(gp); + G /= norm(G); answer.resize(2, 2); // answer.at(1, 1) = G.at(1);//tangent vector @@ -208,10 +193,10 @@ IntElLine1 :: computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) // answer.at(1, 2) = G.at(2); // answer.at(2, 2) = G.at(1); //normal is -G.at(2), G.at(1), perpendicular to nodes 1 2 - answer.at(1, 1) = -G.at(2);//normal vector - answer.at(2, 1) = G.at(1); - answer.at(1, 2) = G.at(1); - answer.at(2, 2) = G.at(2); + answer.at(1, 1) = -G.at(2);//normal vector + answer.at(2, 1) = G.at(1); + answer.at(1, 2) = G.at(1); + answer.at(2, 2) = G.at(2); } FEInterpolation * @@ -221,6 +206,48 @@ IntElLine1 :: giveInterpolation() const } +Interface *IntElLine1::giveInterface( InterfaceType interface ) +{ + if ( interface == NodalAveragingRecoveryModelInterfaceType ) { + return static_cast(this); + } else { + return nullptr; + } +} + +void IntElLine1::NodalAveragingRecoveryMI_computeNodalValue( FloatArray &answer, int node, InternalStateType type, TimeStep *tStep ) +{ + FloatArray nodeMap, gpValsA, gpValsB, N, locCoord; + nodeMap.resize(1); + + FEInterpolation *interp = this->giveInterpolation(); + + //Since it's linear interpolation, it suffices to take first and last Gauss point + //and recover nodal values using only them. + + GaussPoint* gpA = integrationRulesArray[0]->getIntegrationPoint(0); + GaussPoint* gpB = integrationRulesArray[0]->getIntegrationPoint(numberOfGaussPoints-1); + + //Get internal values at Gauss Points A and B + this->giveIPValue(gpValsA, gpA, type, tStep); + this->giveIPValue(gpValsB, gpB, type, tStep); + + if ( (node == 1 ) || (node == 3) ) { //nodes 1 and 3 pertain to gpA + locCoord = gpA->giveNaturalCoordinates(); + } else if ( (node == 2 ) || (node == 4) ) { //nodes 2 and 4 pertain to gpB + locCoord = gpB->giveNaturalCoordinates(); + } + + nodeMap.at(1) = 1/locCoord.at(1); + //Evaluate shape functions (associated with Gauss Points) at element nodes + interp->evalN( N, nodeMap, FEIElementGeometryWrapper(this) ); + answer.resize( gpValsA.giveSize() ); + answer.at(1)= N.at(1)*gpValsA.at(1) + N.at(2)*gpValsB.at(1); + answer.at(2)= N.at(1)*gpValsA.at(2) + N.at(2)*gpValsB.at(2); + answer.at(3)= N.at(1)*gpValsA.at(3) + N.at(2)*gpValsB.at(3); +} + + #ifdef __OOFEG void IntElLine1 :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { diff --git a/src/sm/Elements/Interfaces/intelline1.h b/src/sm/Elements/Interfaces/intelline1.h index 68bbabd84..3909a0f8f 100644 --- a/src/sm/Elements/Interfaces/intelline1.h +++ b/src/sm/Elements/Interfaces/intelline1.h @@ -35,7 +35,9 @@ #ifndef intelline1_h #define intelline1_h -#include "../sm/Elements/Interfaces/structuralinterfaceelement.h" +#include "sm/Elements/Interfaces/structuralinterfaceelement.h" +#include "floatmatrixf.h" +#include "nodalaveragingrecoverymodel.h" #define _IFT_IntElLine1_Name "intelline1" #define _IFT_IntElLine1_axisymmode "axisymmode" @@ -52,56 +54,56 @@ class FEI2dLineLin; * @author Jim Brouzoulis * @author Borek Patzak */ -class IntElLine1 : public StructuralInterfaceElement +class IntElLine1 : public StructuralInterfaceElement, public NodalAveragingRecoveryModelInterface { protected: static FEI2dLineLin interp; /// Flag controlling axisymmetric mode (integration over unit circumferential angle) - bool axisymmode; - + bool axisymmode = false; + public: IntElLine1(int n, Domain * d); - virtual ~IntElLine1() { } - - virtual FEInterpolation *giveInterpolation() const; - virtual int computeNumberOfDofs() { return 8; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + FEInterpolation *giveInterpolation() const override; - virtual double computeAreaAround(GaussPoint *gp); - virtual void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeCovarBaseVectorAt(GaussPoint *gp, FloatArray &G); + int computeNumberOfDofs() override { return 8; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual int testElementExtension(ElementExtension ext) { return 0; } + double computeAreaAround(GaussPoint *gp) override; + void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + virtual FloatArrayF<2> computeCovarBaseVectorAt(GaussPoint *gp) const; - //virtual Interface *giveInterface(InterfaceType) { return NULL; } + int testElementExtension(ElementExtension ext) override { return 0; } + Interface *giveInterface(InterfaceType interface) override; + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_IntElLine1_Name; } - virtual const char *giveClassName() const { return "IntElLine1"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_IntElLine1_Name; } + const char *giveClassName() const override { return "IntElLine1"; } + void initializeFrom(InputRecord &ir) override; - virtual void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) + void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) override { - this->giveInterfaceCrossSection()->giveEngTraction_2d(answer, gp, jump, tStep); + answer = this->giveInterfaceCrossSection()->giveEngTraction_2d(jump, gp, tStep); } - virtual void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) + void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) override { - this->giveInterfaceCrossSection()->give2dStiffnessMatrix_Eng(answer, rMode, ip, tStep); + answer = this->giveInterfaceCrossSection()->give2dStiffnessMatrix_Eng(rMode, ip, tStep); } - #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - #endif - +#ifdef __OOFEG + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; +#endif + protected: - virtual void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeGaussPoints(); + void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeGaussPoints() override; - Element_Geometry_Type giveGeometryType() const { return EGT_quad_1_interface; } + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } }; } // end namespace oofem #endif diff --git a/src/sm/Elements/Interfaces/intelline1intpen.C b/src/sm/Elements/Interfaces/intelline1intpen.C index 4e7b5c9ca..aa349ff64 100644 --- a/src/sm/Elements/Interfaces/intelline1intpen.C +++ b/src/sm/Elements/Interfaces/intelline1intpen.C @@ -12,94 +12,82 @@ #include "fei2dlinelin.h" #include "fei2dlinequad.h" #include "feinterpol.h" -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" namespace oofem { REGISTER_Element(IntElLine1IntPen); -IntElLine1IntPen::IntElLine1IntPen(int n, Domain * d) : IntElLine1(n, d) { +IntElLine1IntPen::IntElLine1IntPen(int n, Domain * d) : IntElLine1(n, d) +{ numberOfDofMans = 6; - numberOfGaussPoints = 4; - -} - -IntElLine1IntPen::~IntElLine1IntPen() { - } -int IntElLine1IntPen :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { +int IntElLine1IntPen :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ FloatArray N; FEInterpolation *interp = this->giveInterpolation(); interp->evalN( N, lcoords, FEIElementGeometryWrapper(this) ); - answer.resize(this->giveDofManager(1)->giveCoordinates()->giveSize()); + answer.resize(this->giveDofManager(1)->giveCoordinates().giveSize()); answer.zero(); - double xi_0 = 0.; FloatArray xiScaled = {0.}; - if(lcoords.at(1) < xi_0 ){ - xiScaled = {lcoords.at(1)*2. + 1.}; - interp->evalN( N, xiScaled, FEIElementGeometryWrapper(this) ); + if ( lcoords.at(1) < xi_0 ) { + xiScaled = {lcoords.at(1)*2. + 1.}; + interp->evalN( N, xiScaled, FEIElementGeometryWrapper(this) ); - const FloatArray &x1 = *(this->giveDofManager(1)->giveCoordinates()); - answer.add(N.at(1), x1 ); + const auto &x1 = this->giveDofManager(1)->giveCoordinates(); + answer.add(N.at(1), x1 ); - const FloatArray &x3 = *(this->giveDofManager(3)->giveCoordinates()); - answer.add(N.at(2), x3 ); - } - else { - xiScaled = {lcoords.at(1)*2. - 1.}; - interp->evalN( N, xiScaled, FEIElementGeometryWrapper(this) ); + const FloatArray &x3 = this->giveDofManager(3)->giveCoordinates(); + answer.add(N.at(2), x3 ); + } else { + xiScaled = {lcoords.at(1)*2. - 1.}; + interp->evalN( N, xiScaled, FEIElementGeometryWrapper(this) ); - const FloatArray &x3 = *(this->giveDofManager(3)->giveCoordinates()); - answer.add(N.at(1), x3 ); + const auto &x3 = this->giveDofManager(3)->giveCoordinates(); + answer.add(N.at(1), x3 ); - const FloatArray &x2 = *(this->giveDofManager(2)->giveCoordinates()); - answer.add(N.at(2), x2 ); + const auto &x2 = this->giveDofManager(2)->giveCoordinates(); + answer.add(N.at(2), x2 ); } - - - return true; } -void -IntElLine1IntPen :: computeCovarBaseVectorAt(IntegrationPoint *ip, FloatArray &G) +FloatArrayF<2> +IntElLine1IntPen :: computeCovarBaseVectorAt(IntegrationPoint *ip) const { -// printf("Entering IntElLine2IntPen :: computeCovarBaseVectorAt\n"); + //printf("Entering IntElLine2IntPen :: computeCovarBaseVectorAt\n"); - // Since we are averaging over the whole element, always evaluate the base vectors at xi = 0. + // Since we are averaging over the whole element, always evaluate the base vectors at xi = 0. - FloatArray xi_0 = {0.0}; -// FloatArray xi_0 = {ip->giveNaturalCoordinate(1)}; + FloatArray xi_0 = {0.0}; + //FloatArray xi_0 = {ip->giveNaturalCoordinate(1)}; FloatMatrix dNdxi; FEInterpolation *interp = this->giveInterpolation(); -// interp->evaldNdxi( dNdxi, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + //interp->evaldNdxi( dNdxi, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); interp->evaldNdxi( dNdxi, xi_0, FEIElementGeometryWrapper(this) ); - G.resize(2); - G.zero(); + FloatArrayF<2> G; double X1_i = 0.5 * ( this->giveNode(1)->giveCoordinate(1) + this->giveNode(4)->giveCoordinate(1) ); // (mean) point on the fictious mid surface double X2_i = 0.5 * ( this->giveNode(1)->giveCoordinate(2) + this->giveNode(4)->giveCoordinate(2) ); G.at(1) += dNdxi.at(1, 1) * X1_i; G.at(2) += dNdxi.at(1, 1) * X2_i; - X1_i = 0.5 * ( this->giveNode(2)->giveCoordinate(1) + this->giveNode(5)->giveCoordinate(1) ); // (mean) point on the fictious mid surface X2_i = 0.5 * ( this->giveNode(2)->giveCoordinate(2) + this->giveNode(5)->giveCoordinate(2) ); G.at(1) += dNdxi.at(2, 1) * X1_i; G.at(2) += dNdxi.at(2, 1) * X2_i; - + return G; } - void IntElLine1IntPen :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { @@ -267,16 +255,10 @@ IntElLine1IntPen :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode } } - if ( matStiffSymmFlag ) { answer.symmetrized(); } - - - #endif - - } @@ -286,11 +268,11 @@ IntElLine1IntPen :: giveInternalForcesVector(FloatArray &answer, { #if 1 // Computes internal forces - // For this element we use an "interior penalty" formulation, where - // the cohesive zone contribution is weakened, i.e. the traction and - // test function for the cohesive zone are projected onto a reduced - // space. The purpose of the projection is to improve the stability - // properties of the formulation, thereby avoiding traction oscilations. + // For this element we use an "interior penalty" formulation, where + // the cohesive zone contribution is weakened, i.e. the traction and + // test function for the cohesive zone are projected onto a reduced + // space. The purpose of the projection is to improve the stability + // properties of the formulation, thereby avoiding traction oscilations. FloatMatrix N; FloatArray u, traction, jump; @@ -466,7 +448,6 @@ for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { } - #endif void @@ -484,45 +465,43 @@ IntElLine1IntPen :: computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer) answer.resize(2, 12); answer.zero(); - if(ip->giveNaturalCoordinate(1) < xi_0 ){ - xiScaled = {ip->giveNaturalCoordinate(1)*2. + 1.}; - interp->evalN( N, xiScaled, FEIElementGeometryWrapper(this) ); + if ( ip->giveNaturalCoordinate(1) < xi_0 ) { + xiScaled = {ip->giveNaturalCoordinate(1)*2. + 1.}; + interp->evalN( N, xiScaled, FEIElementGeometryWrapper(this) ); - answer.at(1, 1) = answer.at(2, 2) = -N.at(1); -// answer.at(1, 3) = answer.at(2, 4) = -N.at(2); - answer.at(1, 5) = answer.at(2, 6) = -N.at(2); + answer.at(1, 1) = answer.at(2, 2) = -N.at(1); + //answer.at(1, 3) = answer.at(2, 4) = -N.at(2); + answer.at(1, 5) = answer.at(2, 6) = -N.at(2); - answer.at(1, 7) = answer.at(2, 8) = N.at(1); -// answer.at(1, 9) = answer.at(2, 10) = N.at(2); - answer.at(1, 11) = answer.at(2, 12) = N.at(2); - } - else { - xiScaled = {ip->giveNaturalCoordinate(1)*2. - 1.}; - interp->evalN( N, xiScaled, FEIElementGeometryWrapper(this) ); + answer.at(1, 7) = answer.at(2, 8) = N.at(1); + //answer.at(1, 9) = answer.at(2, 10) = N.at(2); + answer.at(1, 11) = answer.at(2, 12) = N.at(2); + } else { + xiScaled = {ip->giveNaturalCoordinate(1)*2. - 1.}; + interp->evalN( N, xiScaled, FEIElementGeometryWrapper(this) ); -// answer.at(1, 1) = answer.at(2, 2) = -N.at(1); - answer.at(1, 3) = answer.at(2, 4) = -N.at(2); - answer.at(1, 5) = answer.at(2, 6) = -N.at(1); + //answer.at(1, 1) = answer.at(2, 2) = -N.at(1); + answer.at(1, 3) = answer.at(2, 4) = -N.at(2); + answer.at(1, 5) = answer.at(2, 6) = -N.at(1); -// answer.at(1, 7) = answer.at(2, 8) = N.at(1); - answer.at(1, 9) = answer.at(2, 10) = N.at(2); - answer.at(1, 11) = answer.at(2, 12) = N.at(1); + //answer.at(1, 7) = answer.at(2, 8) = N.at(1); + answer.at(1, 9) = answer.at(2, 10) = N.at(2); + answer.at(1, 11) = answer.at(2, 12) = N.at(1); } } void IntElLine1IntPen :: computeGaussPoints() -// Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); -// integrationRulesArray[ 0 ].reset( new LobattoIntegrationRule (1,this, 1, 2, false) ); +// integrationRulesArray[ 0 ] = std::make_unique(1,this, 1, 2, false); // integrationRulesArray [ 0 ]->SetUpPointsOnLine(2, _2dInterface); int numGP = 4; - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); integrationRulesArray [ 0 ]->SetUpPointsOnLine(numGP, _2dInterface); } } diff --git a/src/sm/Elements/Interfaces/intelline1intpen.h b/src/sm/Elements/Interfaces/intelline1intpen.h index d972657d9..a97ef3320 100644 --- a/src/sm/Elements/Interfaces/intelline1intpen.h +++ b/src/sm/Elements/Interfaces/intelline1intpen.h @@ -46,18 +46,18 @@ class FEI2dLineLin; * with interior penalty formulation. * @author Erik Svenning */ -class IntElLine1IntPen : public IntElLine1 { +class IntElLine1IntPen : public IntElLine1 +{ public: - IntElLine1IntPen(int n, Domain * d); - virtual ~IntElLine1IntPen(); + IntElLine1IntPen(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_IntElLine1IntPen_Name; } - virtual const char *giveClassName() const { return "IntElLine1IntPen"; } + const char *giveInputRecordName() const override { return _IFT_IntElLine1IntPen_Name; } + const char *giveClassName() const override { return "IntElLine1IntPen"; } - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; - virtual void computeCovarBaseVectorAt(GaussPoint *gp, FloatArray &G); + FloatArrayF<2> computeCovarBaseVectorAt(GaussPoint *gp) const override; /** * Computes the stiffness/tangent matrix of receiver. Default implementation computes element stiffness using @@ -76,7 +76,7 @@ class IntElLine1IntPen : public IntElLine1 { * @param rMode Response mode. * @param tStep Time step. */ - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; /** @@ -93,14 +93,13 @@ class IntElLine1IntPen : public IntElLine1 { * nonzero the stresses are taken directly from integration point status (should be derived from StructuralMaterialStatus) * (fast, but engineering model must ensure valid status data in each integration point). */ - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; protected: - virtual void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeGaussPoints(); - - Element_Geometry_Type giveGeometryType() const { return EGT_quad_21_interface; } + void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeGaussPoints() override; + Element_Geometry_Type giveGeometryType() const override { return EGT_quad_21_interface; } }; } /* namespace oofem */ diff --git a/src/sm/Elements/Interfaces/intelline1phf.C b/src/sm/Elements/Interfaces/intelline1phf.C index aa6e0b8ac..6548967d0 100644 --- a/src/sm/Elements/Interfaces/intelline1phf.C +++ b/src/sm/Elements/Interfaces/intelline1phf.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/Interfaces/intelline1phf.h" -#include "CrossSections/structuralinterfacecrosssection.h" -#include "Materials/InterfaceMaterials/structuralinterfacematerialphf.h" +#include "sm/Elements/Interfaces/intelline1phf.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialphf.h" #include "node.h" #include "gausspoint.h" #include "gaussintegrationrule.h" @@ -55,8 +55,6 @@ FEI2dLineLin IntElLine1PhF :: interp(1, 1); IntElLine1PhF :: IntElLine1PhF(int n, Domain *aDomain) : StructuralInterfaceElementPhF(n, aDomain) { numberOfDofMans = 4; - axisymmode = false; - numberOfGaussPoints = 4; } @@ -65,7 +63,6 @@ void IntElLine1PhF :: computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer) { // Returns the modified N-matrix which multiplied with u give the spatial jump. - FloatArray N; FEInterpolation *interp = this->giveInterpolation(); interp->evalN( N, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); @@ -82,24 +79,22 @@ IntElLine1PhF :: computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer) void IntElLine1PhF :: computeGaussPoints() -// Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - //integrationRulesArray[ 0 ].reset( new LobattoIntegrationRule (1,domain, 1, 2) ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + //integrationRulesArray[ 0 ] = std::make_unique(1,domain, 1, 2); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); integrationRulesArray [ 0 ]->SetUpPointsOnLine(this->numberOfGaussPoints, _2dInterface); } } -void -IntElLine1PhF :: computeCovarBaseVectorAt(IntegrationPoint *ip, FloatArray &G) +FloatArrayF<2> +IntElLine1PhF :: computeCovarBaseVectorAt(IntegrationPoint *ip) const { FloatMatrix dNdxi; FEInterpolation *interp = this->giveInterpolation(); interp->evaldNdxi( dNdxi, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - G.resize(2); - G.zero(); + FloatArrayF<2> G; int numNodes = this->giveNumberOfNodes(); for ( int i = 1; i <= dNdxi.giveNumberOfRows(); i++ ) { double X1_i = 0.5 * ( this->giveNode(i)->giveCoordinate(1) + this->giveNode(i + numNodes / 2)->giveCoordinate(1) ); // (mean) point on the fictious mid surface @@ -107,16 +102,17 @@ IntElLine1PhF :: computeCovarBaseVectorAt(IntegrationPoint *ip, FloatArray &G) G.at(1) += dNdxi.at(i, 1) * X1_i; G.at(2) += dNdxi.at(i, 1) * X2_i; } + return G; } + double IntElLine1PhF :: computeAreaAround(IntegrationPoint *ip) { - FloatArray G; - this->computeCovarBaseVectorAt(ip, G); + auto G = this->computeCovarBaseVectorAt(ip); - double weight = ip->giveWeight(); - double ds = sqrt( G.dotProduct(G) ) * weight; + double weight = ip->giveWeight(); + double ds = norm(G) * weight; if ( this->axisymmode ) { int numNodes = this->giveNumberOfNodes(); FloatArray N; @@ -128,7 +124,6 @@ IntElLine1PhF :: computeAreaAround(IntegrationPoint *ip) r += N.at(i) * X_i; } return ds * r; - } else { // regular 2d double thickness = this->giveCrossSection()->give(CS_Thickness, ip); return ds * thickness; @@ -136,13 +131,12 @@ IntElLine1PhF :: computeAreaAround(IntegrationPoint *ip) } -IRResultType -IntElLine1PhF :: initializeFrom(InputRecord *ir) +void +IntElLine1PhF :: initializeFrom(InputRecord &ir) { + StructuralInterfaceElement :: initializeFrom(ir); this->axisymmode = false; - this->axisymmode = ir->hasField(_IFT_IntElLine1PhF_axisymmode); - return StructuralInterfaceElement :: initializeFrom(ir); - + this->axisymmode = ir.hasField(_IFT_IntElLine1PhF_axisymmode); } @@ -156,9 +150,8 @@ void IntElLine1PhF :: computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) { // Transformation matrix to the local coordinate system - FloatArray G; - this->computeCovarBaseVectorAt(gp, G); - G.normalize(); + auto G = this->computeCovarBaseVectorAt(gp, G); + G /= norm(G); answer.resize(2, 2); answer.at(1, 1) = G.at(1); @@ -185,7 +178,7 @@ void IntElLine1PhF :: giveDofManDofIDMask_d(IntArray &answer) { // use temperature for now - answer = {T_f}; + answer = {T_f}; } void @@ -203,12 +196,11 @@ IntElLine1PhF :: getLocationArray_d( IntArray &answer ) void IntElLine1PhF :: giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const double damage, TimeStep *tStep) { - StructuralInterfaceMaterialPhF *mat = static_cast< StructuralInterfaceMaterialPhF * >( this->giveInterfaceCrossSection()->giveInterfaceMaterial() ); //double damage = this->computeDamageAt(gp, VM_Total, tStep); - + //StructuralInterfaceMaterial *mat = this->giveInterfaceCrossSection()->giveInterfaceMaterial(); - mat->giveEngTraction_2d(answer, gp, jump, damage, tStep); + answer = mat->giveEngTraction_2d(jump, damage, gp, tStep); //this->giveInterfaceCrossSection()->giveEngTraction_2d(answer, gp, jump, tStep); } @@ -216,15 +208,11 @@ IntElLine1PhF :: giveEngTraction(FloatArray &answer, GaussPoint *gp, const Float void IntElLine1PhF::computeCovarBaseVectorsAt(GaussPoint *gp, FloatMatrix &G) { - - FloatArray G1; - this->computeCovarBaseVectorAt(gp, G1); - + auto G1 = this->computeCovarBaseVectorAt(gp); + G.resize(2, 1); - G.at(1, 1) = G1.at(1); - G.at(2, 1) = G1.at(2); - - + G.at(1, 1) = G1.at(1); + G.at(2, 1) = G1.at(2); } diff --git a/src/sm/Elements/Interfaces/intelline1phf.h b/src/sm/Elements/Interfaces/intelline1phf.h index d764a048e..dd3b050f5 100644 --- a/src/sm/Elements/Interfaces/intelline1phf.h +++ b/src/sm/Elements/Interfaces/intelline1phf.h @@ -35,7 +35,7 @@ #ifndef intelline1phf_h #define intelline1phf_h -#include "Elements/Interfaces/structuralinterfaceelementphf.h" +#include "sm/Elements/Interfaces/structuralinterfaceelementphf.h" #define _IFT_IntElLine1PhF_Name "intelline1phf" #define _IFT_IntElLine1PhF_axisymmode "axisymmode" @@ -52,48 +52,46 @@ class IntElLine1PhF : public StructuralInterfaceElementPhF protected: static FEI2dLineLin interp; /// Flag controlling axisymmetric mode (integration over unit circumferential angle) - bool axisymmode; - + bool axisymmode = false; + public: IntElLine1PhF(int n, Domain * d); - virtual ~IntElLine1PhF() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - //virtual int computeNumberOfDofs() { return 8; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + //int computeNumberOfDofs() override { return 8; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual double computeAreaAround(GaussPoint *gp); - virtual void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeCovarBaseVectorAt(GaussPoint *gp, FloatArray &G); + double computeAreaAround(GaussPoint *gp) override; + void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + FloatArrayF<2> computeCovarBaseVectorAt(GaussPoint *gp) const; - virtual int testElementExtension(ElementExtension ext) { return 0; } + int testElementExtension(ElementExtension ext) override { return 0; } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_IntElLine1PhF_Name; } - virtual const char *giveClassName() const { return "IntElLine1PhF"; } - virtual IRResultType initializeFrom(InputRecord *ir); - - //virtual void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); - virtual void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const double damage, TimeStep *tStep); - - virtual void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) + const char *giveInputRecordName() const override { return _IFT_IntElLine1PhF_Name; } + const char *giveClassName() const override { return "IntElLine1PhF"; } + void initializeFrom(InputRecord &ir) override; + + //void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) override; + void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const double damage, TimeStep *tStep) override; + + void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) override { - this->giveInterfaceCrossSection()->give2dStiffnessMatrix_Eng(answer, rMode, ip, tStep); + answer = this->giveInterfaceCrossSection()->give2dStiffnessMatrix_Eng(rMode, ip, tStep); } - - virtual void giveDofManDofIDMask_u(IntArray &answer); - virtual void giveDofManDofIDMask_d(IntArray &answer); - virtual void getLocationArray_u( IntArray &answer ); - virtual void getLocationArray_d( IntArray &answer ); - virtual void computeCovarBaseVectorsAt(GaussPoint *gp, FloatMatrix &G); - + void giveDofManDofIDMask_u(IntArray &answer) override; + void giveDofManDofIDMask_d(IntArray &answer) override; + void getLocationArray_u( IntArray &answer) override; + void getLocationArray_d( IntArray &answer) override; + void computeCovarBaseVectorsAt(GaussPoint *gp, FloatMatrix &G) override; + protected: - virtual void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeGaussPoints(); + void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeGaussPoints() override; - Element_Geometry_Type giveGeometryType() const { return EGT_quad_1_interface; }; + Element_Geometry_Type giveGeometryType() const override { return EGT_quad_1_interface; }; }; } // end namespace oofem #endif diff --git a/src/sm/Elements/Interfaces/intelline2.C b/src/sm/Elements/Interfaces/intelline2.C index 91ed81d44..2b64d87dc 100644 --- a/src/sm/Elements/Interfaces/intelline2.C +++ b/src/sm/Elements/Interfaces/intelline2.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Interfaces/intelline2.h" -#include "../sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/Elements/Interfaces/intelline2.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "gausspoint.h" #include "gaussintegrationrule.h" #include "floatmatrix.h" @@ -58,7 +58,6 @@ FEI2dLineLin IntElLine2 :: interpLin(1, 1); IntElLine2 :: IntElLine2(int n, Domain *aDomain) : IntElLine1(n, aDomain) { numberOfDofMans = 6; - numberOfGaussPoints = 4; linear = false; } @@ -67,45 +66,42 @@ IntElLine2 :: IntElLine2(int n, Domain *aDomain) : IntElLine1(n, aDomain) void IntElLine2 :: computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer) { - // Returns the modified N-matrix which multiplied with u give the spatial jump. FloatArray N; answer.resize(2, 12); answer.zero(); - if(linear) { - interpLin.evalN( N, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + if ( linear ) { + interpLin.evalN( N, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - answer.at(1, 1) = answer.at(2, 2) = -N.at(1); - answer.at(1, 3) = answer.at(2, 4) = -N.at(2); -// answer.at(1, 5) = answer.at(2, 6) = -N.at(3); + answer.at(1, 1) = answer.at(2, 2) = -N.at(1); + answer.at(1, 3) = answer.at(2, 4) = -N.at(2); + //answer.at(1, 5) = answer.at(2, 6) = -N.at(3); - answer.at(1, 7) = answer.at(2, 8) = N.at(1); - answer.at(1, 9) = answer.at(2, 10) = N.at(2); -// answer.at(1, 11) = answer.at(2, 12) = N.at(3); - } - else { - interp.evalN( N, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + answer.at(1, 7) = answer.at(2, 8) = N.at(1); + answer.at(1, 9) = answer.at(2, 10) = N.at(2); + //answer.at(1, 11) = answer.at(2, 12) = N.at(3); + } else { + interp.evalN( N, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - answer.at(1, 1) = answer.at(2, 2) = -N.at(1); - answer.at(1, 3) = answer.at(2, 4) = -N.at(2); - answer.at(1, 5) = answer.at(2, 6) = -N.at(3); + answer.at(1, 1) = answer.at(2, 2) = -N.at(1); + answer.at(1, 3) = answer.at(2, 4) = -N.at(2); + answer.at(1, 5) = answer.at(2, 6) = -N.at(3); - answer.at(1, 7) = answer.at(2, 8) = N.at(1); - answer.at(1, 9) = answer.at(2, 10) = N.at(2); - answer.at(1, 11) = answer.at(2, 12) = N.at(3); + answer.at(1, 7) = answer.at(2, 8) = N.at(1); + answer.at(1, 9) = answer.at(2, 10) = N.at(2); + answer.at(1, 11) = answer.at(2, 12) = N.at(3); } } void IntElLine2 :: computeGaussPoints() -// Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - //integrationRulesArray[ 0 ].reset( new LobattoIntegrationRule (1,domain, 1, 2) ); ///@todo - should be able to decide - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + //integrationRulesArray[ 0 ] = std::make_unique(1,domain, 1, 2); ///@todo - should be able to decide + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); integrationRulesArray [ 0 ]->SetUpPointsOnLine(numberOfGaussPoints, _2dInterface); ///@todo - should be a parameter with num of ip } } @@ -117,11 +113,11 @@ IntElLine2 :: giveInterpolation() const } -IRResultType -IntElLine2 :: initializeFrom(InputRecord *ir) +void +IntElLine2 :: initializeFrom(InputRecord &ir) { - linear = ir->hasField(_IFT_IntElLine2_LinearTraction); - return IntElLine1 :: initializeFrom(ir); + IntElLine1 :: initializeFrom(ir); + linear = ir.hasField(_IFT_IntElLine2_LinearTraction); } diff --git a/src/sm/Elements/Interfaces/intelline2.h b/src/sm/Elements/Interfaces/intelline2.h index badceee9c..d76d89f01 100644 --- a/src/sm/Elements/Interfaces/intelline2.h +++ b/src/sm/Elements/Interfaces/intelline2.h @@ -35,7 +35,7 @@ #ifndef intelline2_h #define intelline2_h -#include "../sm/Elements/Interfaces/intelline1.h" +#include "sm/Elements/Interfaces/intelline1.h" #define _IFT_IntElLine2_Name "intelline2" #define _IFT_IntElLine2_LinearTraction "linear" @@ -58,29 +58,28 @@ class IntElLine2 : public IntElLine1 public: IntElLine2(int n, Domain * d); virtual ~IntElLine2() { } - virtual FEInterpolation *giveInterpolation() const; - virtual int computeNumberOfDofs() { return 12; } - virtual IRResultType initializeFrom(InputRecord *ir); - + FEInterpolation *giveInterpolation() const override; + int computeNumberOfDofs() override { return 12; } + void initializeFrom(InputRecord &ir) override; + // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_IntElLine2_Name; } - virtual const char *giveClassName() const { return "IntElLine2"; } + const char *giveInputRecordName() const override { return _IFT_IntElLine2_Name; } + const char *giveClassName() const override { return "IntElLine2"; } + +#ifdef __OOFEG + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; +#endif - #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - #endif - protected: - virtual void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeGaussPoints(); + void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeGaussPoints() override; - Element_Geometry_Type giveGeometryType() const { return EGT_quad_21_interface; } + Element_Geometry_Type giveGeometryType() const override { return EGT_quad_21_interface; } /// If linear interpolation should be used. bool linear; - }; } // end namespace oofem #endif diff --git a/src/sm/Elements/Interfaces/intelline2intpen.C b/src/sm/Elements/Interfaces/intelline2intpen.C index 67e1b3491..8ac95a1f1 100644 --- a/src/sm/Elements/Interfaces/intelline2intpen.C +++ b/src/sm/Elements/Interfaces/intelline2intpen.C @@ -44,23 +44,18 @@ namespace oofem { REGISTER_Element(IntElLine2IntPen); -IntElLine2IntPen::IntElLine2IntPen(int n, Domain * d):IntElLine2(n, d) { +IntElLine2IntPen::IntElLine2IntPen(int n, Domain * d):IntElLine2(n, d) +{ numberOfDofMans = 6; - numberOfGaussPoints = 4; } -IntElLine2IntPen::~IntElLine2IntPen() { - -} -IRResultType -IntElLine2IntPen :: initializeFrom(InputRecord *ir) +void +IntElLine2IntPen :: initializeFrom(InputRecord &ir) { - this->axisymmode = false; - this->axisymmode = ir->hasField(_IFT_IntElLine1_axisymmode); - IRResultType result = StructuralInterfaceElement :: initializeFrom(ir); - + StructuralInterfaceElement :: initializeFrom(ir); + this->axisymmode = ir.hasField(_IFT_IntElLine1_axisymmode); // Check if node numbering is ok // printf("this->dofManArray: "); this->dofManArray.printYourself(); @@ -82,13 +77,13 @@ IntElLine2IntPen :: initializeFrom(InputRecord *ir) // IntArray nodeInd = {dofManArray.at(2), dofManArray.at(3), dofManArray.at(4)}; -// double L2 = x1.distance_square(x2); +// double L2 = distance_square(x1, x2); // printf("L2: %e\n", L2); -// double L3 = x1.distance_square(x3); +// double L3 = distance_square(x1, x3); // printf("L3: %e\n", L3); -// double L4 = x1.distance_square(x4); +// double L4 = distance_square(x1, x4); // printf("L4: %e\n", L4); // // FloatArray dist2 = {L2, L3, L4}; @@ -125,28 +120,24 @@ IntElLine2IntPen :: initializeFrom(InputRecord *ir) // printf("Renumbering element %d\n.\n", this->giveNumber()); // std::swap(dofManArray.at(2), dofManArray.at(3)); // } - - - return result; } -void -IntElLine2IntPen :: computeCovarBaseVectorAt(IntegrationPoint *ip, FloatArray &G) +FloatArrayF<2> +IntElLine2IntPen :: computeCovarBaseVectorAt(IntegrationPoint *ip) const { -// printf("Entering IntElLine2IntPen :: computeCovarBaseVectorAt\n"); + //printf("Entering IntElLine2IntPen :: computeCovarBaseVectorAt\n"); - // Since we are averaging over the whole element, always evaluate the base vectors at xi = 0. + // Since we are averaging over the whole element, always evaluate the base vectors at xi = 0. FloatArray xi_0 = {0.0}; - FloatMatrix dNdxi; FEInterpolation *interp = this->giveInterpolation(); + FloatMatrix dNdxi; // interp->evaldNdxi( dNdxi, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); interp->evaldNdxi( dNdxi, xi_0, FEIElementGeometryWrapper(this) ); - G.resize(2); - G.zero(); + FloatArrayF<2> G; int numNodes = this->giveNumberOfNodes(); for ( int i = 1; i <= dNdxi.giveNumberOfRows(); i++ ) { double X1_i = 0.5 * ( this->giveNode(i)->giveCoordinate(1) + this->giveNode(i + numNodes / 2)->giveCoordinate(1) ); // (mean) point on the fictious mid surface @@ -154,6 +145,7 @@ IntElLine2IntPen :: computeCovarBaseVectorAt(IntegrationPoint *ip, FloatArray &G G.at(1) += dNdxi.at(i, 1) * X1_i; G.at(2) += dNdxi.at(i, 1) * X2_i; } + return G; } void diff --git a/src/sm/Elements/Interfaces/intelline2intpen.h b/src/sm/Elements/Interfaces/intelline2intpen.h index d082f3344..0f4708de6 100644 --- a/src/sm/Elements/Interfaces/intelline2intpen.h +++ b/src/sm/Elements/Interfaces/intelline2intpen.h @@ -47,18 +47,18 @@ class FEI2dLineQuad; * with interior penalty formulation. * @author Erik Svenning */ -class IntElLine2IntPen : public IntElLine2 { +class IntElLine2IntPen : public IntElLine2 +{ public: - IntElLine2IntPen(int n, Domain * d); - virtual ~IntElLine2IntPen(); + IntElLine2IntPen(int n, Domain * d); // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_IntElLine2IntPen_Name; } - virtual const char *giveClassName() const { return "IntElLine2IntPen"; } + const char *giveInputRecordName() const override { return _IFT_IntElLine2IntPen_Name; } + const char *giveClassName() const override { return "IntElLine2IntPen"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void computeCovarBaseVectorAt(GaussPoint *gp, FloatArray &G); + FloatArrayF<2> computeCovarBaseVectorAt(GaussPoint *gp) const override; /** @@ -78,7 +78,7 @@ class IntElLine2IntPen : public IntElLine2 { * @param rMode Response mode. * @param tStep Time step. */ - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; /** @@ -95,7 +95,7 @@ class IntElLine2IntPen : public IntElLine2 { * nonzero the stresses are taken directly from integration point status (should be derived from StructuralMaterialStatus) * (fast, but engineering model must ensure valid status data in each integration point). */ - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; }; diff --git a/src/sm/Elements/Interfaces/intelpoint.C b/src/sm/Elements/Interfaces/intelpoint.C index b12e3613c..5a20d6c07 100644 --- a/src/sm/Elements/Interfaces/intelpoint.C +++ b/src/sm/Elements/Interfaces/intelpoint.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Interfaces/intelpoint.h" -#include "../sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/Elements/Interfaces/intelpoint.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "domain.h" #include "node.h" #include "gaussintegrationrule.h" @@ -42,6 +42,7 @@ #include "intarray.h" #include "mathfem.h" #include "classfactory.h" +//#include "floatarrayf.h" #ifdef __OOFEG #include "oofeggraphiccontext.h" @@ -56,10 +57,6 @@ IntElPoint :: IntElPoint(int n, Domain *aDomain) : StructuralInterfaceElement(n, aDomain) { numberOfDofMans = 2; - referenceNode = 0; - normal.resize(3); - normal.zero(); - area = 1.0; } @@ -107,7 +104,6 @@ IntElPoint :: computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) // { setCoordMode(); - switch ( mode ) { case ie1d_1d: @@ -164,19 +160,17 @@ IntElPoint :: computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) //FloatMatrix test; //test.beLocalCoordSys(normal.normalize()); - FloatArray ly(3), lz(3); - normal.normalize(); - ly.zero(); + FloatArrayF<3> ly; if ( fabs( normal.at(1) ) > fabs( normal.at(2) ) ) { ly.at(2) = 1.; } else { ly.at(1) = 1.; } - lz.beVectorProductOf(normal, ly); - lz.normalize(); - ly.beVectorProductOf(lz, normal); - ly.normalize(); + auto lz = cross(normal, ly); + lz /= norm(lz); + ly = cross(lz, normal); + ly /= norm(ly); answer.resize(3, 3); for ( int i = 1; i <= 3; i++ ) { @@ -196,11 +190,10 @@ IntElPoint :: computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) void IntElPoint :: computeGaussPoints() -// Sets up the array of Gauss Points of the receiver. { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); integrationRulesArray [ 0 ]->setUpIntegrationPoints( _Line, 1, this->giveMaterialMode() ); } } @@ -209,8 +202,8 @@ IntElPoint :: computeGaussPoints() int IntElPoint :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { - answer = *this->giveNode(1)->giveCoordinates(); - answer.add(*this->giveNode(2)->giveCoordinates()); + answer = this->giveNode(1)->giveCoordinates(); + answer.add(this->giveNode(2)->giveCoordinates()); answer.times(0.5); return 1; } @@ -220,34 +213,49 @@ IntElPoint :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lco double IntElPoint :: computeAreaAround(GaussPoint *gp) { + if ( (this->giveCrossSection()->hasProperty(CS_Thickness)) ) { + double thickness = this->giveCrossSection()->give(CS_Thickness, gp); + return thickness*this->length; + } else { // The modeled area/extension around the connected nodes. // Compare with the cs area of a bar. ///@todo replace with cs-property? /JB return this->area; + } } -IRResultType -IntElPoint :: initializeFrom(InputRecord *ir) +void +IntElPoint :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralInterfaceElement :: initializeFrom(ir); - result = StructuralInterfaceElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; + if ( ir.hasField(_IFT_IntElPoint_refnode) &&ir.hasField(_IFT_IntElPoint_normal) ) { + throw ValueInputException(ir, _IFT_IntElPoint_refnode, "Ambiguous input: 'refnode' and 'normal' cannot both be specified"); } - if ( ir->hasField(_IFT_IntElPoint_refnode) && ir->hasField(_IFT_IntElPoint_normal) ) { - OOFEM_WARNING("Ambiguous input: 'refnode' and 'normal' cannot both be specified"); - return IRRT_BAD_FORMAT; - } IR_GIVE_OPTIONAL_FIELD(ir, referenceNode, _IFT_IntElPoint_refnode); - IR_GIVE_OPTIONAL_FIELD(ir, normal, _IFT_IntElPoint_normal); + FloatArray n(3); + IR_GIVE_OPTIONAL_FIELD(ir, n, _IFT_IntElPoint_normal); + normal = n; + /*if ( ir.hasField(_IFT_IntElPoint_refnode) ) { + IR_GIVE_OPTIONAL_FIELD(ir, referenceNode, _IFT_IntElPoint_refnode); + normal = *domain->giveNode(this->referenceNode)->giveCoordinates() - *this->giveNode(1)->giveCoordinates(); + } else { + FloatArray n; + IR_GIVE_OPTIONAL_FIELD(ir, n, _IFT_IntElPoint_normal); + normal = n; + } + normal /= norm(normal); + */ + this->area = 1.0; // Default area ///@todo Make non-optional? /JB IR_GIVE_OPTIONAL_FIELD(ir, this->area, _IFT_IntElPoint_area); - - this->computeLocalSlipDir(normal); - return IRRT_OK; + + this->length = 1.0; + IR_GIVE_OPTIONAL_FIELD(ir, this->length, _IFT_IntElPoint_length); + + this->computeLocalSlipDir(); } @@ -295,22 +303,27 @@ IntElPoint :: giveDofManDofIDMask(int inode, IntArray &answer) const void -IntElPoint :: computeLocalSlipDir(FloatArray &normal) +IntElPoint :: computeLocalSlipDir(void) { - normal.resizeWithValues(3); if ( this->referenceNode ) { // normal - normal.beDifferenceOf(*domain->giveNode(this->referenceNode)->giveCoordinates(), *this->giveNode(1)->giveCoordinates()); + normal = domain->giveNode(this->referenceNode)->giveCoordinates() - this->giveNode(1)->giveCoordinates(); } else { - if ( normal.at(1) == 0 && normal.at(2) == 0 && normal.at(3) == 0 ) { - OOFEM_ERROR("Normal is not defined (referenceNode=0,normal=(0,0,0))"); - } + + if ( normal.at(1) == 0. && normal.at(2) == 0. && normal.at(3) == 0. ) { + // let the element compute the slip direction if the nodes' cooridantes are different + normal = this->giveNode(2)->giveCoordinates() - this->giveNode(1)->giveCoordinates(); + + // final check + if ( normal.at(1) == 0. && normal.at(2) == 0. && normal.at(3) == 0. ) { + OOFEM_ERROR("Normal is not defined (referenceNode=0,normal=(0,0,0))"); + } + } } - normal.normalize(); + normal /= norm(normal); } - - + #ifdef __OOFEG void IntElPoint :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) @@ -395,7 +408,7 @@ void IntElPoint :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) result += giveIPValue(v1, iRule->getIntegrationPoint(0), gc.giveIntVarType(), tStep); - for ( GaussPoint *gp: *iRule ) { + for ( auto &gp: *iRule ) { result = 0; result += giveIPValue(v1, gp, gc.giveIntVarType(), tStep); if ( result != 1 ) { diff --git a/src/sm/Elements/Interfaces/intelpoint.h b/src/sm/Elements/Interfaces/intelpoint.h index f9a95042b..a5ef343bc 100644 --- a/src/sm/Elements/Interfaces/intelpoint.h +++ b/src/sm/Elements/Interfaces/intelpoint.h @@ -35,8 +35,10 @@ #ifndef intelpoint_h #define intelpoint_h -#include "../sm/Elements/Interfaces/structuralinterfaceelement.h" +#include "sm/Elements/Interfaces/structuralinterfaceelement.h" #include "gaussintegrationrule.h" +#include "floatmatrixf.h" +//#include "floatarrayf.h" ///@name Input fields for Material //@{ @@ -44,13 +46,16 @@ #define _IFT_IntElPoint_refnode "refnode" #define _IFT_IntElPoint_normal "normal" #define _IFT_IntElPoint_area "area" +#define _IFT_IntElPoint_length "length" //@} namespace oofem { /** * This class implements an interface element that connects two nodes. * In order to compute the normal and tangential direction of the slip plane, - * a reference node or specific direction must be specified in the input. + * a reference node or specific direction can be specified in the input. + * If neither are specified, then the normal direction are computed from the coordinates + * of the element's nodes. * The class adjusts dimensionality automatically to 1D, 2D, or 3D depending on domain. * @author Jim Brouzoulis * @author Borek Patzak @@ -59,66 +64,65 @@ class IntElPoint : public StructuralInterfaceElement { protected: enum cmode { ie1d_1d, ie1d_2d, ie1d_3d } mode; - int referenceNode; - FloatArray normal; - double area; + int referenceNode = 0; + FloatArrayF<3> normal; + double area = 0.; + double length = 0.; + public: IntElPoint(int n, Domain *d); - virtual ~IntElPoint() { } - - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); - - virtual int computeNumberOfDofs(); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual double computeAreaAround(GaussPoint *gp); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + int computeNumberOfDofs() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + double computeAreaAround(GaussPoint *gp) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_IntElPoint_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } + const char *giveInputRecordName() const override { return _IFT_IntElPoint_Name; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } - virtual MaterialMode giveMaterialMode(); + MaterialMode giveMaterialMode() override; + void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; - virtual void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer); - - virtual void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) + void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) override { if ( this->giveDomain()->giveNumberOfSpatialDimensions() == 3 ) { - this->giveInterfaceCrossSection()->giveEngTraction_3d(answer, gp, jump, tStep); + answer = this->giveInterfaceCrossSection()->giveEngTraction_3d(jump, gp, tStep); } else if ( this->giveDomain()->giveNumberOfSpatialDimensions() == 2 ) { - this->giveInterfaceCrossSection()->giveEngTraction_2d(answer, gp, jump, tStep); + answer = this->giveInterfaceCrossSection()->giveEngTraction_2d(jump, gp, tStep); } else if ( this->giveDomain()->giveNumberOfSpatialDimensions() == 1 ) { - this->giveInterfaceCrossSection()->giveEngTraction_1d(answer, gp, jump, tStep); + answer = {this->giveInterfaceCrossSection()->giveEngTraction_1d(jump.at(1), gp, tStep)}; } } - virtual void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) + void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) override { if ( this->giveDomain()->giveNumberOfSpatialDimensions() == 3 ) { - this->giveInterfaceCrossSection()->give3dStiffnessMatrix_Eng(answer, rMode, ip, tStep); + answer = this->giveInterfaceCrossSection()->give3dStiffnessMatrix_Eng(rMode, ip, tStep); } else if ( this->giveDomain()->giveNumberOfSpatialDimensions() == 2 ) { - this->giveInterfaceCrossSection()->give2dStiffnessMatrix_Eng(answer, rMode, ip, tStep); + answer = this->giveInterfaceCrossSection()->give2dStiffnessMatrix_Eng(rMode, ip, tStep); } else if ( this->giveDomain()->giveNumberOfSpatialDimensions() == 1 ) { - this->giveInterfaceCrossSection()->give1dStiffnessMatrix_Eng(answer, rMode, ip, tStep); + answer = this->giveInterfaceCrossSection()->give1dStiffnessMatrix_Eng(rMode, ip, tStep); } - } #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); -#endif - + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; +#endif + protected: - virtual void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeGaussPoints(); + void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeGaussPoints() override; - void computeLocalSlipDir(FloatArray &normal); + // void computeLocalSlipDir(FloatArrayF &normal); + // void computeLocalSlipDir(FloatArrayF<3> normal); + void computeLocalSlipDir(void); cmode giveCoordMode() const { return this->mode; } void setCoordMode(); }; diff --git a/src/sm/Elements/Interfaces/intelsurfquad1.C b/src/sm/Elements/Interfaces/intelsurfquad1.C new file mode 100644 index 000000000..e5ad638f1 --- /dev/null +++ b/src/sm/Elements/Interfaces/intelsurfquad1.C @@ -0,0 +1,243 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/Interfaces/intelsurfquad1.h" +#include "node.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "classfactory.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" + + #include +#endif + +namespace oofem { +REGISTER_Element(IntElSurfQuad1); + +FEI3dQuadLin IntElSurfQuad1 :: interpolation; + +IntElSurfQuad1 :: IntElSurfQuad1(int n, Domain *aDomain) : + StructuralInterfaceElement(n, aDomain) +{ + numberOfDofMans = 8; +} + + +void +IntElSurfQuad1 :: computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer) +{ + // Returns the modified N-matrix which multiplied with u give the spatial jump. + + FloatArray N; + this->interpolation.evalN( N, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + + answer.resize(3, 24); + answer.zero(); + + answer.at(1, 13) = answer.at(2, 14) = answer.at(3, 15) = N.at(1); + answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = -N.at(1); + + answer.at(1, 16) = answer.at(2, 17) = answer.at(3, 18) = N.at(2); + answer.at(1, 4) = answer.at(2, 5) = answer.at(3, 6) = -N.at(2); + + answer.at(1, 19) = answer.at(2, 20) = answer.at(3, 21) = N.at(3); + answer.at(1, 7) = answer.at(2, 8) = answer.at(3, 9) = -N.at(3); + + answer.at(1, 22) = answer.at(2, 23) = answer.at(3, 24) = N.at(4); + answer.at(1, 10) = answer.at(2, 11) = answer.at(3, 12) = -N.at(4); +} + + +void +IntElSurfQuad1 :: computeGaussPoints() +{ + // Sets up the array of Gauss Points of the receiver. + if ( integrationRulesArray.size() == 0 ) { + integrationRulesArray.resize(1); + //integrationRulesArray[0] = std::make_unique(1,domain, 1, 2); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); + integrationRulesArray [ 0 ]->setUpIntegrationPoints(_Square, 4, _3dInterface); ///@todo add parameter for ngp + } +} + + +void +IntElSurfQuad1 :: computeCovarBaseVectorsAt(IntegrationPoint *ip, FloatArray &G1, FloatArray &G2) +{ + FloatMatrix dNdxi; + this->interpolation.evaldNdxi( dNdxi, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + G1.resize(3); + G2.resize(3); + G1.zero(); + G2.zero(); + + FloatArray meanNode; + int numNodes = this->giveNumberOfNodes(); + for ( int i = 1; i <= dNdxi.giveNumberOfRows(); i++ ) { + meanNode = 0.5 * ( this->giveNode(i)->giveCoordinates() + this->giveNode(i + numNodes / 2)->giveCoordinates() ); + G1 += dNdxi.at(i, 1) * meanNode; + G2 += dNdxi.at(i, 2) * meanNode; + } +} + + +double +IntElSurfQuad1 :: computeAreaAround(IntegrationPoint *ip) +{ + FloatArray G1, G2, G3; + this->computeCovarBaseVectorsAt(ip, G1, G2); + double weight = ip->giveWeight(); + G3.beVectorProductOf(G1, G2); + return G3.computeNorm() * weight; +} + + +void +IntElSurfQuad1 :: initializeFrom(InputRecord &ir) +{ + StructuralInterfaceElement :: initializeFrom(ir); +} + + +void +IntElSurfQuad1 :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = { D_u, D_v, D_w }; +} + +#if 0 +bool +IntElSurfQuad1 :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + computeTransformationMatrixAt(this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0), lcs); + answer.resize(18, 18); + for ( int i = 0; i < 6; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + answer.at(i * 3 + 1, i * 3 + j) = lcs.at(3, j); + answer.at(i * 3 + 2, i * 3 + j) = lcs.at(1, j); + answer.at(i * 3 + 3, i * 3 + j) = lcs.at(2, j); + } + } + + + return 1; +} +#endif + +void +IntElSurfQuad1 :: computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) +{ + // Transformation matrix to the local coordinate system + FloatArray G1, G2, Normal; + this->computeCovarBaseVectorsAt(gp, G1, G2); + Normal.beVectorProductOf(G1, G2); + Normal.normalize(); + answer.beLocalCoordSys(Normal); +} + + + +int +IntElSurfQuad1 :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ + FloatArray N, meanNode; + this->interpolation.evalN( N, lcoords, FEIElementGeometryWrapper(this) ); + answer.resize(3); + answer.zero(); + for ( int i = 1; i <= 4; i++ ) { + meanNode = 0.5 * ( this->giveNode(i)->giveCoordinates() + this->giveNode(i + 3)->giveCoordinates() ); + answer += N.at(i) * meanNode; + } + + return 1; +} + + +bool +IntElSurfQuad1 :: computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) +{ + OOFEM_ERROR("Not implemented"); + return false; +} + +///@todo this code not tested, onlu copied from interfaceelem3dtrlin.C //JB +#ifdef __OOFEG +void IntElSurfQuad1 :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + // if (!go) { // create new one + WCRec p [ 3 ]; /* triangle */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor( gc.getElementColor() ); + EASValsSetEdgeColor( gc.getElementEdgeColor() ); + EASValsSetEdgeFlag(true); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3); + p [ 2 ].x = ( FPNum ) this->giveNode(3)->giveCoordinate(1); + p [ 2 ].y = ( FPNum ) this->giveNode(3)->giveCoordinate(2); + p [ 2 ].z = ( FPNum ) this->giveNode(3)->giveCoordinate(3); + + go = CreateTriangle3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | EDGE_COLOR_MASK | EDGE_FLAG_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + + +void IntElSurfQuad1 :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ } + + +void IntElSurfQuad1 :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) +{ } + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/Interfaces/intelsurfquad1.h b/src/sm/Elements/Interfaces/intelsurfquad1.h new file mode 100644 index 000000000..7b7ec74f6 --- /dev/null +++ b/src/sm/Elements/Interfaces/intelsurfquad1.h @@ -0,0 +1,95 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef intelsurfquad1_h +#define intelsurfquad1_h + +#include "sm/Elements/Interfaces/structuralinterfaceelement.h" +#include "fei3dquadlin.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" + +#define _IFT_IntElSurfQuad1_Name "intelsurfquad1" + +namespace oofem { +/** + * This class implements 3d triangular surface interface element with linear interpolation. + */ +class IntElSurfQuad1 : public StructuralInterfaceElement +{ +protected: + static FEI3dQuadLin interpolation; + +public: + IntElSurfQuad1(int n, Domain *d); + + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; + virtual void computeCovarBaseVectorsAt(IntegrationPoint *ip, FloatArray &G1, FloatArray &G2); + //bool computeGtoLRotationMatrix(FloatMatrix &answer) override; + void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + + int computeNumberOfDofs() override { return 24; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + double computeAreaAround(IntegrationPoint *ip) override; + + void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) override + { + answer = this->giveInterfaceCrossSection()->giveEngTraction_3d(jump, gp, tStep); + } + + void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) override + { + answer = this->giveInterfaceCrossSection()->give3dStiffnessMatrix_Eng(rMode, ip, tStep); + } + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_IntElSurfQuad1_Name; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_quad_1_interface; } + +#ifdef __OOFEG + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; +#endif + +protected: + void computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer) override; + void computeGaussPoints() override; + +}; +} // end namespace oofem +#endif // intelsurfquad1_h diff --git a/src/sm/Elements/Interfaces/intelsurftr1.C b/src/sm/Elements/Interfaces/intelsurftr1.C index 597c5c830..0bf692cd8 100644 --- a/src/sm/Elements/Interfaces/intelsurftr1.C +++ b/src/sm/Elements/Interfaces/intelsurftr1.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Interfaces/intelsurftr1.h" +#include "sm/Elements/Interfaces/intelsurftr1.h" #include "node.h" #include "crosssection.h" #include "gausspoint.h" @@ -89,8 +89,8 @@ IntElSurfTr1 :: computeGaussPoints() // Sets up the array of Gauss Points of the receiver. if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - //integrationRulesArray[0] = new LobattoIntegrationRule (1,domain, 1, 2); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + //integrationRulesArray[0] = std::make_unique(1,domain, 1, 2); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); integrationRulesArray [ 0 ]->setUpIntegrationPoints(_Triangle, 4, _3dInterface); ///@todo add parameter for ngp } } @@ -109,7 +109,7 @@ IntElSurfTr1 :: computeCovarBaseVectorsAt(IntegrationPoint *ip, FloatArray &G1, FloatArray meanNode; int numNodes = this->giveNumberOfNodes(); for ( int i = 1; i <= dNdxi.giveNumberOfRows(); i++ ) { - meanNode = 0.5 * ( *this->giveNode(i)->giveCoordinates() + *this->giveNode(i + numNodes / 2)->giveCoordinates() ); + meanNode = 0.5 * ( this->giveNode(i)->giveCoordinates() + this->giveNode(i + numNodes / 2)->giveCoordinates() ); G1 += dNdxi.at(i, 1) * meanNode; G2 += dNdxi.at(i, 2) * meanNode; } @@ -127,10 +127,10 @@ IntElSurfTr1 :: computeAreaAround(IntegrationPoint *ip) } -IRResultType -IntElSurfTr1 :: initializeFrom(InputRecord *ir) +void +IntElSurfTr1 :: initializeFrom(InputRecord &ir) { - return StructuralInterfaceElement :: initializeFrom(ir); + StructuralInterfaceElement :: initializeFrom(ir); } @@ -181,7 +181,7 @@ IntElSurfTr1 :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &l answer.resize(3); answer.zero(); for ( int i = 1; i <= 3; i++ ) { - meanNode = 0.5 * ( *this->giveNode(i)->giveCoordinates() + *this->giveNode(i + 3)->giveCoordinates() ); + meanNode = 0.5 * ( this->giveNode(i)->giveCoordinates() + this->giveNode(i + 3)->giveCoordinates() ); answer += N.at(i) * meanNode; } diff --git a/src/sm/Elements/Interfaces/intelsurftr1.h b/src/sm/Elements/Interfaces/intelsurftr1.h index f4453a2f5..c050493ee 100644 --- a/src/sm/Elements/Interfaces/intelsurftr1.h +++ b/src/sm/Elements/Interfaces/intelsurftr1.h @@ -35,8 +35,10 @@ #ifndef intelsurftr1_h #define intelsurftr1_h -#include "../sm/Elements/Interfaces/structuralinterfaceelement.h" +#include "sm/Elements/Interfaces/structuralinterfaceelement.h" #include "fei3dtrlin.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #define _IFT_IntElSurfTr1_Name "intelsurftr1" @@ -51,43 +53,42 @@ class IntElSurfTr1 : public StructuralInterfaceElement public: IntElSurfTr1(int n, Domain *d); - virtual ~IntElSurfTr1() { } - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; virtual void computeCovarBaseVectorsAt(IntegrationPoint *ip, FloatArray &G1, FloatArray &G2); - //virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); - virtual void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer); + //bool computeGtoLRotationMatrix(FloatMatrix &answer) override; + void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; - virtual int computeNumberOfDofs() { return 18; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + int computeNumberOfDofs() override { return 18; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual double computeAreaAround(IntegrationPoint *ip); - - virtual void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) + double computeAreaAround(IntegrationPoint *ip) override; + + void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) override { - this->giveInterfaceCrossSection()->giveEngTraction_3d(answer, gp, jump, tStep); + answer = this->giveInterfaceCrossSection()->giveEngTraction_3d(jump, gp, tStep); } - virtual void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) + void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) override { - this->giveInterfaceCrossSection()->give3dStiffnessMatrix_Eng(answer, rMode, ip, tStep); + answer = this->giveInterfaceCrossSection()->give3dStiffnessMatrix_Eng(rMode, ip, tStep); } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_IntElSurfTr1_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Element_Geometry_Type giveGeometryType() const { return EGT_wedge_1; } + const char *giveInputRecordName() const override { return _IFT_IntElSurfTr1_Name; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_wedge_1; } - #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - #endif +#ifdef __OOFEG + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; +#endif protected: - virtual void computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer); - virtual void computeGaussPoints(); + void computeNmatrixAt(GaussPoint *ip, FloatMatrix &answer) override; + void computeGaussPoints() override; }; } // end namespace oofem diff --git a/src/sm/Elements/Interfaces/structuralinterfaceelement.C b/src/sm/Elements/Interfaces/structuralinterfaceelement.C index 2fb599b94..edf5a5b2d 100644 --- a/src/sm/Elements/Interfaces/structuralinterfaceelement.C +++ b/src/sm/Elements/Interfaces/structuralinterfaceelement.C @@ -32,10 +32,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Interfaces/structuralinterfaceelement.h" -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" -#include "../sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/Elements/Interfaces/structuralinterfaceelement.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "feinterpol.h" #include "domain.h" #include "material.h" @@ -49,28 +49,23 @@ namespace oofem { -StructuralInterfaceElement :: StructuralInterfaceElement(int n, Domain *aDomain) : Element(n, aDomain), - interpolation(NULL), - nlGeometry(0) +StructuralInterfaceElement :: StructuralInterfaceElement(int n, Domain *aDomain) : Element(n, aDomain) { } - -StructuralInterfaceElement :: ~StructuralInterfaceElement() -{ } - -int StructuralInterfaceElement :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { +int StructuralInterfaceElement :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ FloatArray N; FEInterpolation *interp = this->giveInterpolation(); interp->evalN( N, lcoords, FEIElementGeometryWrapper(this) ); - answer.resize(this->giveDofManager(1)->giveCoordinates()->giveSize()); + answer.resize(this->giveDofManager(1)->giveCoordinates().giveSize()); answer.zero(); int numNodes = this->giveNumberOfNodes(); - for(int i = 1; i <= numNodes/2; i++) { - FloatArray &nodeCoord = *(this->giveDofManager(i)->giveCoordinates()); - answer.add(N.at(i), nodeCoord ); + for ( int i = 1; i <= numNodes/2; i++ ) { + const auto &nodeCoord = this->giveDofManager(i)->giveCoordinates(); + answer.add(N.at(i), nodeCoord ); } return true; @@ -125,7 +120,10 @@ StructuralInterfaceElement :: computeSpatialJump(FloatArray &answer, Integration FloatArray u; if ( !this->isActivated(tStep) ) { - answer.resize(3); + //match dimensions + //answer.resize(3); + this->computeNmatrixAt(ip, N); + answer.resize(N.giveNumberOfRows()); answer.zero(); return; } @@ -143,8 +141,7 @@ StructuralInterfaceElement :: computeSpatialJump(FloatArray &answer, Integration void -StructuralInterfaceElement :: giveInternalForcesVector(FloatArray &answer, - TimeStep *tStep, int useUpdatedGpRecord) +StructuralInterfaceElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { // Computes internal forces // if useGpRecord == 1 then data stored in ip->giveStressVector() are used @@ -279,6 +276,7 @@ StructuralInterfaceElement :: updateInternalState(TimeStep *tStep) } } + int StructuralInterfaceElement :: checkConsistency() { @@ -298,10 +296,10 @@ StructuralInterfaceElement :: giveIPValue(FloatArray &answer, IntegrationPoint * } -IRResultType -StructuralInterfaceElement :: initializeFrom(InputRecord *ir) +void +StructuralInterfaceElement :: initializeFrom(InputRecord &ir) { - return Element :: initializeFrom(ir); + Element :: initializeFrom(ir); } void StructuralInterfaceElement :: giveInputRecord(DynamicInputRecord &input) diff --git a/src/sm/Elements/Interfaces/structuralinterfaceelement.h b/src/sm/Elements/Interfaces/structuralinterfaceelement.h index 957e1d541..6c07542b4 100644 --- a/src/sm/Elements/Interfaces/structuralinterfaceelement.h +++ b/src/sm/Elements/Interfaces/structuralinterfaceelement.h @@ -35,7 +35,7 @@ #ifndef structuralinterfaceelement_h #define structuralinterfaceelement_h -#include "../sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "element.h" #include "floatmatrix.h" #include "function.h" @@ -66,9 +66,8 @@ class StructuralInterfaceElement : public Element protected: /// Initial displacement vector, describes the initial nodal displacements when element has been casted. FloatArray initialDisplacements; - FEInterpolation *interpolation; /// Flag indicating if geometrical nonlinearities apply. - int nlGeometry; + bool nlGeometry = false; public: /** @@ -77,15 +76,12 @@ class StructuralInterfaceElement : public Element * @param d Domain to which new material will belong. */ StructuralInterfaceElement(int n, Domain * d); - /// Destructor. - virtual ~StructuralInterfaceElement(); - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType, TimeStep *tStep); - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep); + void giveCharacteristicMatrix(FloatMatrix &answer, CharType, TimeStep *tStep) override; + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override; - virtual FEInterpolation *giveInterpolation() const { return interpolation; } /** * Computes the stiffness/tangent matrix of receiver. Default implementation computes element stiffness using * @f$ K=\int_{\Gamma} N^{\mathrm{T}} D N \mathrm{d}V @f$ formulae, where @f$ N @f$ is the element geometric matrix such @@ -122,24 +118,24 @@ class StructuralInterfaceElement : public Element virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); virtual void computeTraction(FloatArray &traction, IntegrationPoint *ip, const FloatArray &jump, TimeStep *tStep); virtual void computeSpatialJump(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType) { return NULL; } + Interface *giveInterface(InterfaceType) override { return nullptr; } //@} // Overloaded methods. - virtual void updateInternalState(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); - virtual int checkConsistency(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveClassName() const { return "StructuralInterfaceElement"; } + void updateInternalState(TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override; + int checkConsistency() override; + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveClassName() const override { return "StructuralInterfaceElement"; } StructuralInterfaceCrossSection *giveInterfaceCrossSection(); virtual double computeAreaAround(GaussPoint *gp) = 0; - virtual Element_Geometry_Type giveGeometryType() const { return EGT_unknown; } + Element_Geometry_Type giveGeometryType() const override { return EGT_unknown; } //virtual methods that should be overloaded by the elements virtual void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); @@ -153,8 +149,8 @@ class StructuralInterfaceElement : public Element { OOFEM_ERROR("not implemented for the current element"); } -protected: +protected: /** * Computes modified interpolation matrix (N) for the element which multiplied * with the unknowns vector (u) produces the spatial jump. @@ -175,7 +171,7 @@ class StructuralInterfaceElement : public Element virtual int giveNumberOfIPForMassMtrxIntegration() { return 0; } virtual int testCrossSectionExtension(CrossSectExtension ext) { return ( ( ext == CS_StructuralInterfaceCapability ) ? 1 : 0 ); } - virtual int testElementExtension(ElementExtension ext) { return 0; } ///@ necessary to define? + int testElementExtension(ElementExtension ext) override { return 0; } ///@ necessary to define? }; } // end namespace oofem #endif // structuralinterfaceelement_h diff --git a/src/sm/Elements/Interfaces/structuralinterfaceelementphf.C b/src/sm/Elements/Interfaces/structuralinterfaceelementphf.C index 4f4fbfb5b..aa8720a90 100644 --- a/src/sm/Elements/Interfaces/structuralinterfaceelementphf.C +++ b/src/sm/Elements/Interfaces/structuralinterfaceelementphf.C @@ -32,11 +32,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Interfaces/structuralinterfaceelementphf.h" -#include "Materials/InterfaceMaterials/structuralinterfacematerialphf.h" -#include "Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "sm/Elements/Interfaces/structuralinterfaceelementphf.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialphf.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" -#include "CrossSections/structuralinterfacecrosssection.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "feinterpol.h" #include "domain.h" #include "material.h" @@ -50,18 +50,12 @@ namespace oofem { -StructuralInterfaceElementPhF :: StructuralInterfaceElementPhF(int n, Domain *aDomain) : StructuralInterfaceElement(n, aDomain), - interpolation(NULL), - nlGeometry(0) +StructuralInterfaceElementPhF :: StructuralInterfaceElementPhF(int n, Domain *aDomain) : StructuralInterfaceElement(n, aDomain) { this->internalLength = 1.0e-1; } -StructuralInterfaceElementPhF :: ~StructuralInterfaceElementPhF() -{ } - - // remove later void StructuralInterfaceElementPhF :: computeDisplacementUnknowns(FloatArray &answer, ValueModeType valueMode, TimeStep *tStep) @@ -70,8 +64,9 @@ StructuralInterfaceElementPhF :: computeDisplacementUnknowns(FloatArray &answer, this->giveDofManDofIDMask_u(dofIdArray); this->computeVectorOf(dofIdArray, valueMode, tStep, answer); } -void + +void StructuralInterfaceElementPhF :: computeDamageUnknowns(FloatArray &answer, ValueModeType valueMode, TimeStep *tStep) { IntArray dofIdArray; @@ -80,10 +75,6 @@ StructuralInterfaceElementPhF :: computeDamageUnknowns(FloatArray &answer, Value } - - - - void StructuralInterfaceElementPhF :: computeLocationArrayOfDofIDs( const IntArray &dofIdArray, IntArray &answer ) { @@ -92,11 +83,10 @@ StructuralInterfaceElementPhF :: computeLocationArrayOfDofIDs( const IntArray &d int k = 0; for(int i = 1; i <= this->giveNumberOfDofManagers(); i++) { DofManager *dMan = this->giveDofManager( i ); - for(int j = 1; j <= dofIdArray.giveSize( ); j++) { + for( int j = 1; j <= dofIdArray.giveSize( ); j++ ) { - if(dMan->hasDofID( (DofIDItem) dofIdArray.at( j ) )) { + if ( dMan->hasDofID( (DofIDItem) dofIdArray.at( j ) ) ) { // hack - answer.followedBy( k + j ); } } @@ -105,7 +95,6 @@ StructuralInterfaceElementPhF :: computeLocationArrayOfDofIDs( const IntArray &d } - void StructuralInterfaceElementPhF :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { @@ -124,19 +113,15 @@ StructuralInterfaceElementPhF :: giveInternalForcesVector(FloatArray &answer, Ti this->giveInternalForcesVector_d(answer_d, tStep, useUpdatedGpRecord); answer.assemble(answer_u, loc_u); answer.assemble(answer_d, loc_d); - } - void StructuralInterfaceElementPhF :: giveInternalForcesVector_u(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { - - FloatMatrix N; FloatArray u, traction, jump; - + IntArray dofIdArray; this->giveDofManDofIDMask_u(dofIdArray); this->computeVectorOf(dofIdArray, VM_Total, tStep, u); @@ -145,37 +130,34 @@ StructuralInterfaceElementPhF :: giveInternalForcesVector_u(FloatArray &answer, if ( initialDisplacements.giveSize() ) { u.subtract(initialDisplacements); } - + // zero answer will resize accordingly when adding first contribution answer.clear(); - + for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { - this->computeNmatrixAt(ip, N); - + jump.beProductOf(N, u); this->computeTraction(traction, ip, jump, tStep); //traction.resize(2); - + // compute internal cohesive forces as f = N^T*traction dA double dA = this->computeAreaAround(ip); answer.plusProduct(N, traction, dA); } - } void StructuralInterfaceElementPhF :: giveInternalForcesVector_d(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { - // computes int_A ( N^t * ( d + l*f ) + B^t * l^2 * gradd(d) )* dA FloatArray BStress, Nd, BS, a_d, grad_d; FloatMatrix B; answer.clear(); this->computeDamageUnknowns( a_d, VM_Total, tStep ); - + double l = this->giveInternalLength(); - + for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { // Part 1 @@ -185,10 +167,10 @@ StructuralInterfaceElementPhF :: giveInternalForcesVector_d(FloatArray &answer, double facN = d + l * mat->giveDrivingForce(ip); this->giveInterpolation()->evalN(Nd, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this)); - + double dA = this->computeAreaAround(ip); answer.add(facN*dA, Nd); - + // Part 2 this->computeBd_matrixAt(ip, B ); grad_d.beProductOf(B, { a_d.at(1), a_d.at(2) }); @@ -196,18 +178,15 @@ StructuralInterfaceElementPhF :: giveInternalForcesVector_d(FloatArray &answer, BS.beTProductOf(B, BStress); answer.add(dA, BS); } - - FloatArray temp; - temp = answer; + + auto temp = answer; answer.resize(4); answer.zero(); answer.assemble(temp,{1,2}); answer.assemble(temp,{3,4}); - } - double StructuralInterfaceElementPhF :: computeDamageAt(GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN) { @@ -221,8 +200,6 @@ StructuralInterfaceElementPhF :: computeDamageAt(GaussPoint *gp, ValueModeType v } - - void StructuralInterfaceElementPhF :: computeNd_matrixAt(const FloatArray &lCoords, FloatMatrix &N) { @@ -235,37 +212,28 @@ StructuralInterfaceElementPhF :: computeNd_matrixAt(const FloatArray &lCoords, F void StructuralInterfaceElementPhF :: computeBd_matrixAt(GaussPoint *gp, FloatMatrix &answer) { - FloatMatrix dNdxi; - FloatMatrix G; this->computeCovarBaseVectorsAt(gp, G); - + this->giveInterpolation( )->evaldNdxi( dNdxi, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper( this ) ); answer.beProductTOf(G,dNdxi); //answer.beTranspositionOf( dNdx ); - - } - - int StructuralInterfaceElementPhF :: computeNumberOfDofs() { //NLStructuralElement *el = static_cast< NLStructuralElement* >(this->giveElement( ) ); int nDofs = 0; - for( int i = 1; i <= this->giveNumberOfDofManagers(); i++) - { + for( int i = 1; i <= this->giveNumberOfDofManagers(); i++) { nDofs += this->giveDofManager( i )->giveNumberOfDofs(); } return nDofs; } - - void StructuralInterfaceElementPhF :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { @@ -277,17 +245,16 @@ StructuralInterfaceElementPhF :: computeStiffnessMatrix(FloatMatrix &answer, Mat this->getLocationArray_u(loc_u); this->getLocationArray_d(loc_d); - + int nDofs = this->computeNumberOfDofs(); answer.resize( nDofs, nDofs ); answer.zero(); - + FloatMatrix answer1, answer2, answer3, answer4; - + this->computeStiffnessMatrix_uu(answer1, rMode, tStep); //StructuralInterfaceElement :: computeStiffnessMatrix(answer1, rMode, tStep); - - + //this->computeStiffnessMatrix_ud(answer2, rMode, tStep); //this->computeStiffnessMatrix_du(answer3, rMode, tStep); //symmetric //answer3.beTranspositionOf( answer2 ); @@ -298,32 +265,28 @@ StructuralInterfaceElementPhF :: computeStiffnessMatrix(FloatMatrix &answer, Mat //answer.assemble( answer2, loc_u, loc_d ); //answer.assemble( answer3, loc_d, loc_u ); answer.assemble( answer4, loc_d, loc_d ); - } - void StructuralInterfaceElementPhF :: computeStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { - - // This is the regular stiffness matrix times G - + // Computes the stiffness matrix of the receiver K_cohesive = int_A ( N^t * D * N ) dA // with the stiffness D = dT/dj FloatMatrix N, D, DN; bool matStiffSymmFlag = this->giveCrossSection()->isCharacteristicMtrxSymmetric(rMode); answer.clear(); - + FloatMatrix rotationMatGtoL; for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { - + this->giveStiffnessMatrix_Eng(D, rMode, ip, tStep); - + this->computeTransformationMatrixAt(ip, rotationMatGtoL); D.rotatedWith(rotationMatGtoL, 't'); // transform stiffness to global coord system - + this->computeNmatrixAt(ip, N); DN.beProductOf(D, N); double dA = this->computeAreaAround(ip); @@ -333,17 +296,11 @@ StructuralInterfaceElementPhF :: computeStiffnessMatrix_uu(FloatMatrix &answer, answer.plusProductUnsym(N, DN, dA); } } - - + if ( matStiffSymmFlag ) { answer.symmetrized(); } } - - - - - void @@ -352,13 +309,11 @@ StructuralInterfaceElementPhF :: computeStiffnessMatrix_ud(FloatMatrix &answer, FloatMatrix B, DB, N_d, DN, S(3,1); FloatArray stress; #if 1 - - answer.resize(0,0); - - for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { - + answer.clear(); + + for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { double dA = this->computeAreaAround(ip); - + // compute int_V ( B^t * D_B * B )dV this->computeNd_matrixAt(ip->giveNaturalCoordinates(), N_d); // stress @@ -375,12 +330,9 @@ StructuralInterfaceElementPhF :: computeStiffnessMatrix_ud(FloatMatrix &answer, } - - void StructuralInterfaceElementPhF :: computeStiffnessMatrix_dd(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { - double l = this->giveInternalLength(); FloatMatrix B_d, N_d; @@ -389,30 +341,27 @@ StructuralInterfaceElementPhF :: computeStiffnessMatrix_dd(FloatMatrix &answer, FloatMatrix rotationMatGtoL; for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { StructuralInterfaceMaterialPhF *mat = static_cast< StructuralInterfaceMaterialPhF * >( this->giveInterfaceCrossSection()->giveInterfaceMaterial() ); - + this->computeNd_matrixAt(ip->giveNaturalCoordinates(), N_d); this->computeBd_matrixAt(ip, B_d); - + // K_dd1 = ( 1 + l*f' ) * N^t*N; // K_dd2 = ( l*l ) * B^t*B; double dA = this->computeAreaAround(ip); - + double fPrime = mat->giveDrivingForcePrime(ip); double factorN = 1.0 + l* fPrime; double factorB = l*l; - + answer.plusProductUnsym(N_d, N_d, factorN * dA); answer.plusProductUnsym(B_d, B_d, factorB * dA); - } - FloatMatrix temp; - temp =answer; + auto temp = answer; answer.resize(4,4); answer.zero(); answer.assemble(temp,{1,2},{1,2}); answer.assemble(temp,{3,4},{3,4}); - } @@ -425,17 +374,13 @@ StructuralInterfaceElementPhF :: computeTraction(FloatArray &traction, Integrati jump.rotatedWith(rotationMatGtoL, 'n'); // transform jump to local coord system double damage = this->computeDamageAt(ip, VM_Total, tStep); - + this->giveEngTraction(traction, ip, jump, damage, tStep); - - + traction.rotatedWith(rotationMatGtoL, 't'); // transform traction to global coord system } - - - void StructuralInterfaceElementPhF :: updateYourself(TimeStep *tStep) { @@ -456,7 +401,7 @@ StructuralInterfaceElementPhF :: updateInternalState(TimeStep *tStep) // force updating strains & stresses for ( auto &iRule: integrationRulesArray ) { - for ( GaussPoint *gp: *iRule ) { + for ( auto &gp: *iRule ) { this->computeSpatialJump(jumpL, gp, tStep); this->computeTraction(tractionG, gp, jumpL, tStep); } @@ -464,9 +409,5 @@ StructuralInterfaceElementPhF :: updateInternalState(TimeStep *tStep) } - - - - } // end namespace oofem diff --git a/src/sm/Elements/Interfaces/structuralinterfaceelementphf.h b/src/sm/Elements/Interfaces/structuralinterfaceelementphf.h index 7f5bc6f8c..9c550517e 100644 --- a/src/sm/Elements/Interfaces/structuralinterfaceelementphf.h +++ b/src/sm/Elements/Interfaces/structuralinterfaceelementphf.h @@ -35,8 +35,8 @@ #ifndef structuralinterfaceelementphf_h #define structuralinterfaceelementphf_h -#include "Elements/Interfaces/structuralinterfaceelement.h" -#include "../sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/Elements/Interfaces/structuralinterfaceelement.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" #include "element.h" #include "floatmatrix.h" #include "function.h" @@ -61,15 +61,10 @@ class FEInterpolation; class StructuralInterfaceElementPhF : public StructuralInterfaceElement { protected: - /// Initial displacement vector, describes the initial nodal displacements when element has been casted. - FloatArray initialDisplacements; - FEInterpolation *interpolation; - /// Flag indicating if geometrical nonlinearities apply. - int nlGeometry; + FEInterpolation *interpolation = nullptr; - IntArray loc_u, loc_d; - + public: /** * Constructor. Creates structural element with given number, belonging to given domain. @@ -77,14 +72,11 @@ class StructuralInterfaceElementPhF : public StructuralInterfaceElement * @param d Domain to which new material will belong. */ StructuralInterfaceElementPhF(int n, Domain * d); - /// Destructor. - virtual ~StructuralInterfaceElementPhF(); - //virtual FEInterpolation *giveInterpolation() const { return interpolation; }; + //FEInterpolation *giveInterpolation() const override { return interpolation; }; - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; - //Phf void computeStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); void computeStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); @@ -97,13 +89,13 @@ class StructuralInterfaceElementPhF : public StructuralInterfaceElement virtual void giveDofManDofIDMask_u(IntArray &answer) = 0; virtual void giveDofManDofIDMask_d(IntArray &answer) = 0; virtual void computeLocationArrayOfDofIDs( const IntArray &dofIdArray, IntArray &answer ); - + virtual void getLocationArray_u( IntArray &answer )=0; virtual void getLocationArray_d( IntArray &answer )=0; - + //remove - int computeNumberOfDofs(); - + int computeNumberOfDofs() override; + ///@todo move these to a cross section model later double internalLength; double giveInternalLength( ) { return internalLength; }; @@ -115,59 +107,45 @@ class StructuralInterfaceElementPhF : public StructuralInterfaceElement //double givePenaltyParameter() { return penaltyParameter; }; //double psiBar0; //double givePsiBar0() { return psiBar0; }; - - + ///@todo put in material model double computeFreeEnergy( GaussPoint *gp, TimeStep *tStep ); - + virtual double computeDamageAt(GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); - void computeDisplacementUnknowns(FloatArray &answer, ValueModeType valueMode, TimeStep *stepN); void computeDamageUnknowns(FloatArray &answer, ValueModeType valueMode, TimeStep *stepN); - - - + void computeBStress_u(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, int useUpdatedGpRecord); void computeNStress_d( FloatArray &answer, GaussPoint *gp, TimeStep *tStep, int useUpdatedGpRecord ); - //Interpolation matrices for phase field virtual void computeBd_matrixAt(GaussPoint *, FloatMatrix &); virtual void computeNd_matrixAt(const FloatArray &lCoords, FloatMatrix &N); - - - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; virtual void computeTraction(FloatArray &traction, IntegrationPoint *ip, FloatArray &jump, TimeStep *tStep); //virtual void computeSpatialJump(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); - //virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + //int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; virtual void computeCovarBaseVectorsAt(GaussPoint *gp, FloatMatrix &G) = 0; - - //@} // Overloaded methods. - virtual void updateInternalState(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); - //virtual int checkConsistency(); - //virtual IRResultType initializeFrom(InputRecord *ir); - //virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveClassName() const { return "StructuralInterfaceElementPhF"; }; + void updateInternalState(TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override; + //int checkConsistency() override; + //void initializeFrom(InputRecord &ir) override; + //void giveInputRecord(DynamicInputRecord &input) override; + const char *giveClassName() const override { return "StructuralInterfaceElementPhF"; }; //StructuralInterfaceCrossSection *giveInterfaceCrossSection(); //virtual methods that should be overloaded by the elements - virtual void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const double damage, TimeStep *tStep) + virtual void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, double damage, TimeStep *tStep) { OOFEM_ERROR("not implemented for the current element"); } - - - -protected: - - }; } // end namespace oofem #endif // structuralinterfaceelement_h diff --git a/src/sm/Elements/lattice2d.C b/src/sm/Elements/LatticeElements/lattice2d.C similarity index 85% rename from src/sm/Elements/lattice2d.C rename to src/sm/Elements/LatticeElements/lattice2d.C index cbefa0388..8fd469907 100644 --- a/src/sm/Elements/lattice2d.C +++ b/src/sm/Elements/LatticeElements/lattice2d.C @@ -10,7 +10,7 @@ * * OOFEM : Object Oriented Finite Element Code * - * Copyright (C) 1993 - 2013 Borek Patzak + * Copyright (C) 1993 - 2019 Borek Patzak * * * @@ -32,18 +32,20 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/lattice2d.h" -#include "../sm/Materials/latticematstatus.h" -#include "../sm/Elements/latticestructuralelement.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/Elements/LatticeElements/lattice2d.h" +#include "sm/Materials/LatticeMaterials/latticematstatus.h" +#include "sm/Elements/LatticeElements/latticestructuralelement.h" +#include "sm/CrossSections/latticecrosssection.h" #include "domain.h" #include "node.h" #include "material.h" #include "gausspoint.h" #include "gaussintegrationrule.h" #include "floatmatrix.h" +#include "floatmatrixf.h" #include "intarray.h" #include "floatarray.h" +#include "floatarrayf.h" #include "mathfem.h" #include "datastream.h" #include "contextioerr.h" @@ -51,7 +53,7 @@ #ifdef __OOFEG #include "oofeggraphiccontext.h" - #include "../sm/Materials/structuralmaterial.h" + #include "sm/Materials/structuralmaterial.h" #endif namespace oofem { @@ -87,16 +89,6 @@ Lattice2d :: giveCrackWidth() return status->giveCrackWidth(); } -double -Lattice2d :: giveOldCrackWidth() -{ - LatticeMaterialStatus *status; - - IntegrationRule *iRule = this->giveDefaultIntegrationRulePtr(); - GaussPoint *gp = iRule->getIntegrationPoint(0); - status = static_cast< LatticeMaterialStatus * >( gp->giveMaterialStatus() ); - return status->giveOldCrackWidth(); -} double @@ -168,15 +160,13 @@ Lattice2d :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int u void Lattice2d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveCharMaterialStiffnessMatrix(answer, rMode, gp, tStep); - //this->giveStructuralCrossSection()->give2dLatticeStiffMtrx(answer, rMode, gp, tStep); + answer = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->give2dStiffnessMatrix(rMode, gp, tStep); } void Lattice2d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveRealStresses(answer, gp, strain, tStep); - //this->giveStructuralCrossSection()->giveLatticeStress(answer, rMode, gp, tStep); + answer = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->giveLatticeStress2d(strain, gp, tStep); } void @@ -190,7 +180,7 @@ Lattice2d :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, answer.zero(); this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), bj); this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); - dV = this->computeVolumeAround( integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); + dV = this->computeVolumeAround(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); dbj.beProductOf(d, bj); answer.plusProductUnsym(bj, dbj, dV); } @@ -202,7 +192,7 @@ void Lattice2d :: computeGaussPoints() // the gauss point is used only when methods from crosssection and/or material // classes are requested integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std :: make_unique< GaussIntegrationRule >(1, this, 1, 3); integrationRulesArray [ 0 ]->SetUpPointsOnLine(1, _2dLattice); } @@ -214,7 +204,7 @@ Lattice2d :: computeGtoLRotationMatrix(FloatMatrix &answer) answer.resize(6, 6); answer.zero(); - sine = sin( this->givePitch() ); + sine = sin(this->givePitch() ); cosine = cos(pitch); answer.at(1, 1) = cosine; answer.at(1, 2) = sine; @@ -285,20 +275,9 @@ double Lattice2d :: givePitch() return pitch; } -double -Lattice2d :: giveNormalStress() -{ - GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); - LatticeMaterialStatus *status = static_cast< LatticeMaterialStatus * >( gp->giveMaterialStatus() ); - double normalStress = 0; - normalStress = status->giveNormalStress(); - - return normalStress; -} - double -Lattice2d :: giveOldNormalStress() +Lattice2d :: giveNormalStress() { LatticeMaterialStatus *status; @@ -306,7 +285,7 @@ Lattice2d :: giveOldNormalStress() GaussPoint *gp = iRule->getIntegrationPoint(0); status = static_cast< LatticeMaterialStatus * >( gp->giveMaterialStatus() ); double normalStress = 0; - normalStress = status->giveOldNormalStress(); + normalStress = status->giveNormalLatticeStress(); return normalStress; } @@ -338,7 +317,7 @@ Lattice2d :: giveLocalCoordinateSystem(FloatMatrix &answer) answer.resize(3, 3); answer.zero(); - sine = sin( this->givePitch() ); + sine = sin(this->givePitch() ); cosine = cos(pitch); answer.at(1, 1) = cosine; @@ -350,10 +329,10 @@ Lattice2d :: giveLocalCoordinateSystem(FloatMatrix &answer) return 1; } -IRResultType -Lattice2d :: initializeFrom(InputRecord *ir) +void +Lattice2d :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + LatticeStructuralElement :: initializeFrom(ir); IR_GIVE_OPTIONAL_FIELD(ir, thickness, _IFT_Lattice2d_thick); @@ -369,9 +348,6 @@ Lattice2d :: initializeFrom(InputRecord *ir) if ( couplingFlag == 1 ) { IR_GIVE_OPTIONAL_FIELD(ir, couplingNumbers.at(1), _IFT_Lattice2d_couplingnumber); } - - // first call parent - return LatticeStructuralElement :: initializeFrom(ir); } @@ -395,16 +371,11 @@ Lattice2d :: giveGpCoordinates(FloatArray &answer) } -contextIOResultType Lattice2d :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void Lattice2d :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = LatticeStructuralElement :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + LatticeStructuralElement :: saveContext(stream, mode); if ( ( mode & CM_Definition ) ) { - if ( !stream.write(width) ) { THROW_CIOERR(CIO_IOERR); } @@ -417,6 +388,7 @@ contextIOResultType Lattice2d :: saveContext(DataStream &stream, ContextMode mod THROW_CIOERR(CIO_IOERR); } + contextIOResultType iores; if ( ( iores = couplingNumbers.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -425,22 +397,14 @@ contextIOResultType Lattice2d :: saveContext(DataStream &stream, ContextMode mod THROW_CIOERR(iores); } } - - return CIO_OK; } - -contextIOResultType Lattice2d :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void Lattice2d :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = LatticeStructuralElement :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + LatticeStructuralElement :: restoreContext(stream, mode); if ( mode & CM_Definition ) { - if ( !stream.read(width) ) { THROW_CIOERR(CIO_IOERR); } @@ -453,6 +417,7 @@ contextIOResultType Lattice2d :: restoreContext(DataStream &stream, ContextMode THROW_CIOERR(CIO_IOERR); } + contextIOResultType iores; if ( ( iores = couplingNumbers.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -460,10 +425,7 @@ contextIOResultType Lattice2d :: restoreContext(DataStream &stream, ContextMode if ( ( iores = gpCoords.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - } - - return CIO_OK; } #ifdef __OOFEG @@ -500,7 +462,7 @@ Lattice2d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); + EASValsSetColor(gc.getElementColor() ); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); @@ -529,7 +491,7 @@ Lattice2d :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Unkn WCRec p [ 2 ]; /* poin */ EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); @@ -576,13 +538,13 @@ Lattice2d :: drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) EASValsSetLayer(OOFEG_CRACK_PATTERN_LAYER); EASValsSetLineWidth(OOFEG_CRACK_PATTERN_WIDTH); if ( ( crackStatuses(0) == 1. ) ) { - EASValsSetColor( gc.getActiveCrackColor() ); + EASValsSetColor(gc.getActiveCrackColor() ); } else if ( crackStatuses(0) == 2. ) { - EASValsSetColor( gc.getCrackPatternColor() ); + EASValsSetColor(gc.getCrackPatternColor() ); } else if ( crackStatuses(0) == 3. ) { - EASValsSetColor( gc.getActiveCrackColor() ); + EASValsSetColor(gc.getActiveCrackColor() ); } else if ( crackStatuses(0) == 4. ) { - EASValsSetColor( gc.getActiveCrackColor() ); + EASValsSetColor(gc.getActiveCrackColor() ); } @@ -606,7 +568,7 @@ Lattice2d :: drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tStep) } EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getCrossSectionColor() ); + EASValsSetColor(gc.getCrossSectionColor() ); EASValsSetLayer(OOFEG_RAW_CROSSSECTION_LAYER); FloatArray coords; diff --git a/src/sm/Elements/LatticeElements/lattice2d.h b/src/sm/Elements/LatticeElements/lattice2d.h new file mode 100644 index 000000000..877398ae4 --- /dev/null +++ b/src/sm/Elements/LatticeElements/lattice2d.h @@ -0,0 +1,134 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef lattice2d_h +#define lattice2d_h + +#include "sm/Elements/LatticeElements/latticestructuralelement.h" + +///@name Input fields for Lattice2d +//@{ +#define _IFT_Lattice2d_Name "lattice2d" +#define _IFT_Lattice2d_thick "thick" +#define _IFT_Lattice2d_width "width" +#define _IFT_Lattice2d_gpcoords "gpcoords" +#define _IFT_Lattice2d_couplingflag "couplingflag" +#define _IFT_Lattice2d_couplingnumber "couplingnumber" +//@} + +namespace oofem { +/** + * This class implements a 2-dimensional lattice element + */ +class Lattice2d : public LatticeStructuralElement +{ +protected: + double kappa, pitch, length; + + double width, thickness; + FloatArray gpCoords; + int couplingFlag; + IntArray couplingNumbers; + +public: + Lattice2d(int n, Domain *d); + virtual ~Lattice2d(); + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + /** + * This function is different from the standard computeGlobalCorrdinates + * function as it returns the global coordinates of the gausspoint + * independent to the value of the lcoords. + */ + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + double giveLength() override; + + double giveNormalStress() override; + + int hasBeenUpdated() override; + + double giveArea() override { return this->width * this->thickness; } + + int computeNumberOfDofs() override { return 6; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + double computeVolumeAround(GaussPoint *gp) override; + + int giveCrackFlag() override; + + double giveCrackWidth() override; + //double giveOldCrackWidth() override; + + double giveDissipation() override; + double giveDeltaDissipation() override; + + int giveCouplingFlag() override { return couplingFlag; } + + void giveCouplingNumbers(IntArray &numbers) override { numbers = this->couplingNumbers; } + // + // definition & identification + // + const char *giveInputRecordName() const override { return _IFT_Lattice2d_Name; } + const char *giveClassName() const override { return "Lattice2d"; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + +#ifdef __OOFEG + void drawYourself(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext & gc, TimeStep *tStep, UnknownType) override; + void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tStep); + void giveCrossSectionCoordinates(FloatArray &coords); +#endif + +protected: + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + bool computeGtoLRotationMatrix(FloatMatrix &) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + + int giveNumberOfCrossSectionNodes() override { return 2; } + double givePitch(); + void computeGaussPoints() override; + integrationDomain giveIntegrationDomain() const override { return _Line; } + void giveGpCoordinates(FloatArray &coords) override; +}; +} // end namespace oofem +#endif diff --git a/src/sm/Elements/LatticeElements/lattice2dboundary.C b/src/sm/Elements/LatticeElements/lattice2dboundary.C new file mode 100644 index 000000000..094dbd1b6 --- /dev/null +++ b/src/sm/Elements/LatticeElements/lattice2dboundary.C @@ -0,0 +1,907 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "../sm/Elements/LatticeElements/lattice2dboundary.h" +#include "../sm/Elements/LatticeElements/lattice2d.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "domain.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "datastream.h" +#include "contextioerr.h" +#include "classfactory.h" +#include "dof.h" +#include "../sm/Materials/structuralmaterial.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { +REGISTER_Element(Lattice2dBoundary); + +Lattice2dBoundary :: Lattice2dBoundary(int n, Domain *aDomain) : Lattice2d(n, aDomain) + // Constructor. +{ + numberOfDofMans = 3; + + kappa = -1; // set kappa to undef value (should be always > 0.) + + pitch = 10.; // a dummy value +} + +Lattice2dBoundary :: ~Lattice2dBoundary() +{ + // destructor +} + +void +Lattice2dBoundary :: computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) +// Returns the strain matrix of the receiver. +{ + double length = this->giveLength(); + double x1, x2, y1, y2, xp, yp; + + FloatArray projectionComponent(2); + giveSwitches(projectionComponent); + + + xp = this->gpCoords.at(1); + yp = this->gpCoords.at(2); + + + //specimen dimension + FloatArray specimenDimension(2); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + + + //Coordinates of the nodes + x1 = this->giveNode(1)->giveCoordinate(1); + y1 = this->giveNode(1)->giveCoordinate(2); + x2 = this->giveNode(2)->giveCoordinate(1) + projectionComponent.at(1) * specimenDimension.at(1); + y2 = this->giveNode(2)->giveCoordinate(2) + projectionComponent.at(2) * specimenDimension.at(2); + + + double ecc; + + double areaHelp = 0.5 * ( x1 * y2 + x2 * yp + xp * y1 - ( xp * y2 + yp * x1 + x2 * y1 ) ); + + ecc = 2 * areaHelp / length; + + // Assemble Bmatrix (used to compute strains and rotations + answer.resize(3, 6); + answer.zero(); + answer.at(1, 1) = -1.; + answer.at(1, 2) = 0.; + answer.at(1, 3) = ecc; + answer.at(1, 4) = 1.; + answer.at(1, 5) = 0.; + answer.at(1, 6) = -ecc; + + answer.at(2, 1) = 0.; + answer.at(2, 2) = -1.; + answer.at(2, 3) = -length / 2.; + answer.at(2, 4) = 0.; + answer.at(2, 5) = 1.; + answer.at(2, 6) = -length / 2.; + + answer.at(3, 1) = 0.; + answer.at(3, 2) = 0.; + answer.at(3, 3) = -this->width / sqrt(12.); + + answer.at(3, 4) = 0.; + answer.at(3, 5) = 0.; + answer.at(3, 6) = this->width / sqrt(12.); + + + answer.times(1. / length); + + return; +} + +const IntArray +Lattice2dBoundary :: giveLocation() +{ + //Map 2D locations to 3D system + int newLocation = 0; + if ( this->location == 1 ) { + newLocation = 22; + } else if ( this->location == 2 ) { + newLocation = 25; + } else if ( this->location == 3 ) { + newLocation = 16; + } else if ( this->location == 4 ) { + newLocation = 8; + } else if ( this->location == 5 ) { + newLocation = 5; + } else if ( this->location == 6 ) { + newLocation = 2; + } else if ( this->location == 7 ) { + newLocation = 11; + } else if ( this->location == 8 ) { + newLocation = 19; + } + + IntArray tempLocation(2); + tempLocation.at(1) = 0; + tempLocation.at(2) = newLocation; + return tempLocation; +} + +void +Lattice2dBoundary :: recalculateCoordinates(int nodeNumber, FloatArray &coords) { + coords.resize(3); + coords.zero(); + Node *node; + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + FloatArray projectionComponent(3); + projectionComponent.zero(); + + node = this->giveNode(2); + if ( location != 0 ) { + giveSwitches(projectionComponent); + } + + for ( int i = 0; i < 3; i++ ) { + coords.at(i + 1) = node->giveCoordinate(i + 1) + projectionComponent.at(i + 1) * specimenDimension.at(i + 1); + } + return; +} + + +void +Lattice2dBoundary :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + double dV; + FloatMatrix d, bi, bj, dbj, dij; + + FloatMatrix answerTemp(6, 6); + answerTemp.zero(); + + + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), bj); + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + dV = this->computeVolumeAround(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); + dbj.beProductOf(d, bj); + answerTemp.plusProductUnsym(bj, dbj, dV); + + answer.resize(computeNumberOfDofs(), computeNumberOfDofs() ); + answer.zero(); + + for ( int m = 1; m <= 6; m++ ) { + for ( int k = 1; k <= 6; k++ ) { + answer.at(m, k) = answerTemp.at(m, k); + } + } + + + //Rotate to global system + FloatMatrix R; + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R); + } + + //Convert normal stiffness matrix to the modified one + + FloatArray projectionComponent(2); + giveSwitches(projectionComponent); + + answer.at(1, 7) = projectionComponent.at(1) * answer.at(1, 4); + answer.at(1, 8) = projectionComponent.at(2) * answer.at(1, 5); + answer.at(1, 9) = projectionComponent.at(1) * answer.at(1, 5); + + answer.at(2, 7) = projectionComponent.at(1) * answer.at(2, 4); + answer.at(2, 8) = projectionComponent.at(2) * answer.at(2, 5); + answer.at(2, 9) = projectionComponent.at(1) * answer.at(2, 5); + + answer.at(3, 7) = projectionComponent.at(1) * answer.at(3, 4); + answer.at(3, 8) = projectionComponent.at(2) * answer.at(3, 5); + answer.at(3, 9) = projectionComponent.at(1) * answer.at(3, 5); + + answer.at(4, 7) = projectionComponent.at(1) * answer.at(4, 4); + answer.at(4, 8) = projectionComponent.at(2) * answer.at(4, 5); + answer.at(4, 9) = projectionComponent.at(1) * answer.at(4, 5); + + answer.at(5, 7) = projectionComponent.at(1) * answer.at(5, 4); + answer.at(5, 8) = projectionComponent.at(2) * answer.at(5, 5); + answer.at(5, 9) = projectionComponent.at(1) * answer.at(5, 5); + + answer.at(6, 7) = projectionComponent.at(1) * answer.at(6, 4); + answer.at(6, 8) = projectionComponent.at(2) * answer.at(6, 5); + answer.at(6, 9) = projectionComponent.at(1) * answer.at(6, 5); + + answer.at(7, 1) = projectionComponent.at(1) * answer.at(4, 1); + answer.at(7, 2) = projectionComponent.at(1) * answer.at(4, 2); + answer.at(7, 3) = projectionComponent.at(1) * answer.at(4, 3); + answer.at(7, 4) = projectionComponent.at(1) * answer.at(4, 4); + answer.at(7, 5) = projectionComponent.at(1) * answer.at(4, 5); + answer.at(7, 6) = projectionComponent.at(1) * answer.at(4, 6); + answer.at(7, 7) = projectionComponent.at(1) * projectionComponent.at(1) * answer.at(4, 4); + answer.at(7, 8) = projectionComponent.at(1) * projectionComponent.at(2) * answer.at(4, 5); + answer.at(7, 9) = projectionComponent.at(1) * projectionComponent.at(1) * answer.at(4, 5); + + answer.at(8, 1) = projectionComponent.at(2) * answer.at(5, 1); + answer.at(8, 2) = projectionComponent.at(2) * answer.at(5, 2); + answer.at(8, 3) = projectionComponent.at(2) * answer.at(5, 3); + answer.at(8, 4) = projectionComponent.at(2) * answer.at(5, 4); + answer.at(8, 5) = projectionComponent.at(2) * answer.at(5, 5); + answer.at(8, 6) = projectionComponent.at(2) * answer.at(5, 6); + answer.at(8, 7) = projectionComponent.at(1) * projectionComponent.at(2) * answer.at(5, 4); + answer.at(8, 8) = projectionComponent.at(2) * projectionComponent.at(2) * answer.at(5, 5); + answer.at(8, 9) = projectionComponent.at(1) * projectionComponent.at(2) * answer.at(5, 5); + + answer.at(9, 1) = projectionComponent.at(1) * answer.at(5, 1); + answer.at(9, 2) = projectionComponent.at(1) * answer.at(5, 2); + answer.at(9, 3) = projectionComponent.at(1) * answer.at(5, 3); + answer.at(9, 4) = projectionComponent.at(1) * answer.at(5, 4); + answer.at(9, 5) = projectionComponent.at(1) * answer.at(5, 5); + answer.at(9, 6) = projectionComponent.at(1) * answer.at(5, 6); + answer.at(9, 7) = projectionComponent.at(1) * projectionComponent.at(1) * answer.at(5, 4); + answer.at(9, 8) = projectionComponent.at(1) * projectionComponent.at(2) * answer.at(5, 5); + answer.at(9, 9) = projectionComponent.at(1) * projectionComponent.at(1) * answer.at(5, 5); + //Rotate back to local system + FloatMatrix Rtranspose; + Rtranspose.beTranspositionOf(R); + answer.rotatedWith(Rtranspose); +} + +void +Lattice2dBoundary :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *stepN) +// Computes the vector containing the strains at the Gauss point gp of +// the receiver, at time step stepN. The nature of these strains depends +// on the element's type. +{ + FloatMatrix b; + FloatArray u; + + //Compute strain vector + //Get the 9 components of the displacement vector of this element + this->computeVectorOf(VM_Total, stepN, u); + this->computeBmatrixAt(gp, b); + + + //Compute projection vector + FloatArray projectionComponent(2); + giveSwitches(projectionComponent); + + FloatMatrix rotationMatrix; + if ( this->computeGtoLRotationMatrix(rotationMatrix) ) { + u.rotatedWith(rotationMatrix, 't'); + } + + //General expressions for the corrected displacements + u.at(4) = u.at(4) + projectionComponent.at(1) * u.at(7); + u.at(5) = u.at(5) + projectionComponent.at(2) * u.at(8) + projectionComponent.at(1) * u.at(9); + + + if ( this->computeGtoLRotationMatrix(rotationMatrix) ) { + u.rotatedWith(rotationMatrix, 'n'); + } + + + //define a temp displacement vector + FloatArray uTemp(6); + + for ( int i = 1; i <= 6; i++ ) { + uTemp.at(i) = u.at(i); + } + + answer.beProductOf(b, uTemp); +} + + +bool +Lattice2dBoundary :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + double sine, cosine; + answer.resize(9, 9); + answer.zero(); + + sine = sin(this->givePitch() ); + cosine = cos(pitch); + answer.at(1, 1) = cosine; + answer.at(1, 2) = sine; + answer.at(2, 1) = -sine; + answer.at(2, 2) = cosine; + answer.at(3, 3) = 1.; + answer.at(4, 4) = cosine; + answer.at(4, 5) = sine; + answer.at(5, 4) = -sine; + answer.at(5, 5) = cosine; + answer.at(6, 6) = 1.; + answer.at(7, 7) = 1.; + answer.at(8, 8) = 1.; + answer.at(9, 9) = 1.; + + return 1; +} + + +double +Lattice2dBoundary :: computeVolumeAround(GaussPoint *aGaussPoint) +{ + double weight = aGaussPoint->giveWeight(); + return weight * 0.5 * this->giveLength() * this->width * this->thickness; +} + + +void +Lattice2dBoundary :: giveDofManDofIDMask(int inode, IntArray &answer) const { + if ( inode == 3 ) { + answer = { E_xx, E_yy, G_xy }; + } else { + answer = { D_u, D_v, R_w }; + } +} + + + +double Lattice2dBoundary :: giveLength() +// Returns the length of the receiver. +{ + //Compute strain vector + FloatArray projectionComponent(2); + giveSwitches(projectionComponent); + + //specimen dimension + FloatArray specimenDimension(2); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + + double dx, dy; + Node *nodeA, *nodeB; + + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + + dx = nodeB->giveCoordinate(1) + projectionComponent.at(1) * specimenDimension.at(1) - nodeA->giveCoordinate(1); + dy = nodeB->giveCoordinate(2) + projectionComponent.at(2) * specimenDimension.at(2) - nodeA->giveCoordinate(2); + + return sqrt(dx * dx + dy * dy); +} + + +double Lattice2dBoundary :: givePitch() +// Returns the pitch of the receiver. +{ + double xA, xB, yA, yB; + Node *nodeA, *nodeB; + + //specimen dimension + FloatArray specimenDimension(2); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + + FloatArray projectionComponent(2); + giveSwitches(projectionComponent); + + if ( pitch == 10. ) { // 10. : dummy initialization value + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + xA = nodeA->giveCoordinate(1); + xB = nodeB->giveCoordinate(1) + projectionComponent.at(1) * specimenDimension.at(1); + yA = nodeA->giveCoordinate(2); + yB = nodeB->giveCoordinate(2) + projectionComponent.at(2) * specimenDimension.at(2); + pitch = atan2(yB - yA, xB - xA); + } + return pitch; +} + + + +void +Lattice2dBoundary :: initializeFrom(InputRecord &ir) +{ + // first call parent + Lattice2d :: initializeFrom(ir); + IR_GIVE_FIELD(ir, location, _IFT_Lattice2dBoundary_location); // Macro + + this->computeGaussPoints(); +} + + + + +void +Lattice2dBoundary :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + Material *mat = this->giveMaterial(); + + FloatMatrix b, bt, A, R, GNT; + FloatArray bs, TotalStressVector, u, strain; + double dV; + + + // This function can be quite costly to do inside the loops when one has many slave dofs. + this->computeVectorOf(VM_Total, tStep, u); + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + answer.resize(9); + answer.zero(); + + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), b); + + bt.beTranspositionOf(b); + // TotalStressVector = gp->giveStressVector() ; + if ( useUpdatedGpRecord == 1 ) { + TotalStressVector = ( ( LatticeMaterialStatus * ) mat->giveStatus(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ) ) + ->giveLatticeStress(); + } else + if ( !this->isActivated(tStep) ) { + strain.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialMode() ) ); + strain.zero(); + } + this->computeStrainVector(strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + // strain.beProductOf(b, u); + + this->computeStressVector(TotalStressVector, strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + // + // compute nodal representation of internal forces using f = B^T*Sigma dV + // + dV = this->computeVolumeAround(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); + bs.beProductOf(bt, TotalStressVector); + bs.times(dV); + + for ( int m = 1; m <= 6; m++ ) { + answer.at(m) = bs.at(m); + } + + //Rotate to global system + + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R, 't'); + } + //Compute strain vector + + FloatArray projectionComponent(2); + giveSwitches(projectionComponent); + + answer.at(7) = projectionComponent.at(1) * answer.at(4); + answer.at(8) = projectionComponent.at(2) * answer.at(5); + answer.at(9) = projectionComponent.at(1) * answer.at(5); + + //Rotate to local system + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R, 'n'); + } + + return; +} + + +void +Lattice2dBoundary :: giveSwitches(FloatArray &answer) { + if ( this->location == 1 ) { + answer(0) = 1; + answer(1) = 0; + } else if ( this->location == 2 ) { + answer(0) = 1; + answer(1) = 1; + } else if ( this->location == 3 ) { + answer(0) = 0; + answer(1) = 1; + } else if ( this->location == 4 ) { + answer(0) = -1; + answer(1) = 1; + } else if ( this->location == 5 ) { + answer(0) = -1; + answer(1) = 0; + } else if ( this->location == 6 ) { + answer(0) = -1; + answer(1) = -1; + } else if ( this->location == 7 ) { + answer(0) = 0; + answer(1) = -1; + } else if ( this->location == 8 ) { + answer(0) = 1; + answer(1) = -1; + } + + return; +} + + +void Lattice2dBoundary :: saveContext(DataStream &stream, ContextMode mode) +{ + Lattice2d :: saveContext(stream, mode); + + + if ( ( mode & CM_Definition ) ) { + if ( !stream.write(location) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +void +Lattice2dBoundary :: restoreContext(DataStream &stream, ContextMode mode) +{ + Lattice2d :: restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( !stream.read(location) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +#ifdef __OOFEG + +void +Lattice2dBoundary :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + this->drawRawCrossSections(gc, tStep); + } else if ( mode == OGC_deformedGeometry ) { + this->drawDeformedGeometry(gc, tStep, DisplacementVector); + } else if ( mode == OGC_elemSpecial ) { + this->drawSpecial(gc, tStep); + } else { + OOFEM_ERROR("unsupported mode"); + } +} + + +void Lattice2dBoundary :: drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + // if (!go) { // create new one + WCRec p [ 2 ]; /* poin */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getCrossSectionColor() ); + EASValsSetLayer(OOFEG_RAW_CROSSSECTION_LAYER); + + //The cs definition is not needed anymore + + FloatArray gpCoords; + giveGpCoordinates(gpCoords); + + FloatArray projectionComponent(2); + giveSwitches(projectionComponent); + + FloatArray specimenDimension(2); + + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + + // double width = cs->give(WIDTH); + + double x1, y1, x2, y2; + x1 = this->giveNode(1)->giveCoordinate(1); + y1 = this->giveNode(1)->giveCoordinate(2); + + x2 = this->giveNode(2)->giveCoordinate(1) + projectionComponent.at(1) * specimenDimension.at(1); + y2 = this->giveNode(2)->giveCoordinate(2) + projectionComponent.at(2) * specimenDimension.at(2); + + //Compute normal and shear direction + FloatArray normalDirection; + FloatArray shearDirection; + normalDirection.resize(2); + normalDirection.zero(); + shearDirection.resize(2); + shearDirection.zero(); + normalDirection.at(1) = x2 - x1; + normalDirection.at(2) = y2 - y1; + normalDirection.normalize(); + if ( normalDirection.at(2) == 0. ) { + shearDirection.at(1) = 0.; + shearDirection.at(2) = 1.; + } else { + shearDirection.at(1) = 1.0; + shearDirection.at(2) = + -normalDirection.at(1) / normalDirection.at(2); + } + shearDirection.normalize(); + + p [ 0 ].x = ( FPNum ) this->gpCoords.at(1) - shearDirection.at(1) * this->width / 2.; + p [ 0 ].y = ( FPNum ) this->gpCoords.at(2) - shearDirection.at(2) * this->width / 2.; + p [ 0 ].z = 0.; + + p [ 1 ].x = ( FPNum ) this->gpCoords.at(1) + shearDirection.at(1) * this->width / 2.; + p [ 1 ].y = ( FPNum ) this->gpCoords.at(2) + shearDirection.at(2) * this->width / 2.; + p [ 1 ].z = 0.; + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + + +void Lattice2dBoundary :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + // if (!go) { // create new one + WCRec p [ 2 ]; /* poin */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getElementColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + FloatArray projectionComponent(2); + giveSwitches(projectionComponent); + + + FloatArray specimenDimension(2); + + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); + p [ 0 ].z = 0.; + + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1) + projectionComponent.at(1) * specimenDimension.at(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2) + projectionComponent.at(2) * specimenDimension.at(2); + p [ 1 ].z = 0.; + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + + + +void Lattice2dBoundary :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ + GraphicObj *go; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + double defScale = gc.getDefScale(); + // if (!go) { // create new one + WCRec p [ 2 ]; /* poin */ + EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); + + + FloatArray projectionComponent(2); + giveSwitches(projectionComponent); + + //specimen dimension + FloatArray specimenDimension(2); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + + double x1, y1, x2, y2; + x1 = this->giveNode(1)->giveCoordinate(1); + y1 = this->giveNode(1)->giveCoordinate(2); + x2 = this->giveNode(2)->giveCoordinate(1) + projectionComponent.at(1) * specimenDimension.at(1); + y2 = this->giveNode(2)->giveCoordinate(2) + projectionComponent.at(2) * specimenDimension.at(2); + + //Node One + FloatArray dispOne(3); + dispOne.at(1) = this->giveNode(1)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispOne.at(2) = this->giveNode(1)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispOne.at(3) = this->giveNode(1)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + //Node Two + FloatArray dispTwo(3); + dispTwo.at(1) = this->giveNode(2)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispTwo.at(2) = this->giveNode(2)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispTwo.at(3) = this->giveNode(2)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + //Node Three + FloatArray dispThree(3); + dispThree.at(1) = this->giveNode(3)->giveDofWithID(E_xx)->giveUnknown(VM_Total, tStep); + dispThree.at(2) = this->giveNode(3)->giveDofWithID(E_yy)->giveUnknown(VM_Total, tStep); + dispThree.at(3) = this->giveNode(3)->giveDofWithID(G_xy)->giveUnknown(VM_Total, tStep); + + //Modify dispOne and dispTwo + dispTwo.at(1) = dispTwo.at(1) + projectionComponent.at(1) * dispThree.at(1); + dispTwo.at(2) = dispTwo.at(2) + projectionComponent.at(2) * dispThree.at(2) + projectionComponent.at(1) * dispThree.at(3); + + p [ 0 ].x = ( FPNum ) x1 + defScale * dispOne.at(1); + p [ 0 ].y = ( FPNum ) y1 + defScale * dispOne.at(2); + p [ 0 ].z = 0.; + + p [ 1 ].x = ( FPNum ) x2 + defScale * dispTwo.at(1); + p [ 1 ].y = ( FPNum ) y2 + defScale * dispTwo.at(2); + p [ 1 ].z = 0.; + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EMAddGraphicsToModel(ESIModel(), go); +} + + + + + + +void +Lattice2dBoundary :: drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) +{ + WCRec l [ 2 ]; + GraphicObj *tr; + StructuralMaterial *mat = ( StructuralMaterial * ) this->giveMaterial(); + GaussPoint *gp; + FloatArray crackStatuses, cf; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + if ( gc.giveIntVarType() == IST_CrackState ) { + gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + mat->giveIPValue(crackStatuses, gp, IST_CrackStatuses, tStep); // printf("crackFlag= %e\n",crackStatuses(0)); + if ( crackStatuses(0) == 1. || crackStatuses(0) == 2. ) { + FloatArray gpCoords; + this->giveGpCoordinates(gpCoords); + + //specimen dimension + FloatArray specimenDimension(2); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + + + FloatArray projectionComponent(2); + giveSwitches(projectionComponent); + + + double x1, y1, x2, y2; + x1 = this->giveNode(1)->giveCoordinate(1); + y1 = this->giveNode(1)->giveCoordinate(2); + x2 = this->giveNode(2)->giveCoordinate(1) + projectionComponent.at(1) * specimenDimension.at(1); + y2 = this->giveNode(2)->giveCoordinate(2) + projectionComponent.at(2) * specimenDimension.at(2); + + //Compute normal and shear direction + FloatArray normalDirection; + FloatArray shearDirection; + normalDirection.resize(2); + normalDirection.zero(); + shearDirection.resize(2); + shearDirection.zero(); + normalDirection.at(1) = x2 - x1; + normalDirection.at(2) = y2 - y1; + normalDirection.normalize(); + if ( normalDirection.at(2) == 0. ) { + shearDirection.at(1) = 0.; + shearDirection.at(2) = 1.; + } else { + shearDirection.at(1) = 1.0; + shearDirection.at(2) = + -normalDirection.at(1) / normalDirection.at(2); + } + shearDirection.normalize(); + + l [ 0 ].x = ( FPNum ) this->gpCoords.at(1) - shearDirection.at(1) * this->width / 2.; + l [ 0 ].y = ( FPNum ) this->gpCoords.at(2) - shearDirection.at(2) * this->width / 2.; + l [ 0 ].z = 0.; + l [ 1 ].x = ( FPNum ) this->gpCoords.at(1) + shearDirection.at(1) * this->width / 2.; + ; + l [ 1 ].y = ( FPNum ) this->gpCoords.at(2) + shearDirection.at(2) * this->width / 2.; + l [ 1 ].z = 0.; + + EASValsSetLayer(OOFEG_CRACK_PATTERN_LAYER); + EASValsSetLineWidth(OOFEG_CRACK_PATTERN_WIDTH); + if ( ( crackStatuses(0) == 1. ) ) { + EASValsSetColor(gc.getActiveCrackColor() ); + } else if ( crackStatuses(0) == 2. ) { + EASValsSetColor(gc.getCrackPatternColor() ); + } + tr = CreateLine3D(l); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, tr); + EMAddGraphicsToModel(ESIModel(), tr); + } + } +} + +void +Lattice2dBoundary :: giveCrossSectionCoordinates(FloatArray &coords) +{ + FloatArray gpCoords; + this->giveGpCoordinates(gpCoords); + FloatArray projectionComponent(2); + giveSwitches(projectionComponent); + + FloatArray specimenDimension(2); + + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + + double x1, y1, x2, y2; + x1 = this->giveNode(1)->giveCoordinate(1); + y1 = this->giveNode(1)->giveCoordinate(2); + + x2 = this->giveNode(2)->giveCoordinate(1) + projectionComponent.at(1) * specimenDimension.at(1); + y2 = this->giveNode(2)->giveCoordinate(2) + projectionComponent.at(2) * specimenDimension.at(2); + + //Compute normal and shear direction + FloatArray normalDirection; + FloatArray shearDirection; + normalDirection.resize(2); + normalDirection.zero(); + shearDirection.resize(2); + shearDirection.zero(); + normalDirection.at(1) = x2 - x1; + normalDirection.at(2) = y2 - y1; + normalDirection.normalize(); + if ( normalDirection.at(2) == 0. ) { + shearDirection.at(1) = 0.; + shearDirection.at(2) = 1.; + } else { + shearDirection.at(1) = 1.0; + shearDirection.at(2) = + -normalDirection.at(1) / normalDirection.at(2); + } + shearDirection.normalize(); + + coords.resize(6); + coords.at(1) = this->gpCoords.at(1) - shearDirection.at(1) * this->width / 2.; + coords.at(2) = this->gpCoords.at(2) - shearDirection.at(2) * this->width / 2.; + coords.at(3) = 0.; + coords.at(4) = this->gpCoords.at(1) + shearDirection.at(1) * this->width / 2.; + coords.at(5) = this->gpCoords.at(2) + shearDirection.at(2) * this->width / 2.; + coords.at(6) = 0.; + + return; +} + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/LatticeElements/lattice2dboundary.h b/src/sm/Elements/LatticeElements/lattice2dboundary.h new file mode 100644 index 000000000..ea0c72b20 --- /dev/null +++ b/src/sm/Elements/LatticeElements/lattice2dboundary.h @@ -0,0 +1,115 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef lattice2dboundary_h +#define lattice2dboundary_h + +#include "../sm/Elements/LatticeElements/lattice2d.h" + +///@name Input fields for Lattice2dboundary +//@{ +#define _IFT_Lattice2dBoundary_Name "latticeboundary2d" +#define _IFT_Lattice2dBoundary_location "location" +//@} + +#define TOL 1.e-8 + +namespace oofem { +class Lattice2dBoundary : public Lattice2d +{ + /* + * This class implements a 2-dimensional lattice element for the + * boundaries of periodic cells. The theory for this element is + * described in the "P. Grassl and M. Jirásek. "Meso-scale approach + * to modelling the fracture process zone of concrete subjected to + * uniaxial tension". International Journal of Solids and Structures. + * Volume 47, Issues 7-8, pp. 957-968, 2010" + * The unknowns of the control node are Exx, Eyy and Gxy. + * Exx = axial strain x-direction + * Eyy = axial strain y-direction + * Gxy = 2Exy (assuming symmetry) + */ +protected: + int location; + +public: + Lattice2dBoundary(int, Domain *); // constructor + ~Lattice2dBoundary(); // destructor + + void giveInternalForcesVector(FloatArray &answer, + TimeStep *, int useUpdatedGpRecord = 0) override; + + const IntArray giveLocation() override; + + int computeNumberOfDofs() override { return 9; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + double computeVolumeAround(GaussPoint *) override; + + // + // definition & identification + // + const char *giveInputRecordName() const override { return _IFT_Lattice2dBoundary_Name; } + const char *giveClassName() const override { return "Lattice2dBoundary"; } + void initializeFrom(InputRecord &ir) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + +#ifdef __OOFEG + void drawYourself(oofegGraphicContext &context, TimeStep *tStep) override; + void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + void drawRawCrossSections(oofegGraphicContext &, TimeStep *tStep); + void drawDeformedGeometry(oofegGraphicContext &, TimeStep *tStep, UnknownType) override; + void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) override; + void giveCrossSectionCoordinates(FloatArray &coords); +#endif + + +protected: + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + bool computeGtoLRotationMatrix(FloatMatrix &) override; + + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *stepN) override; + + double giveLength() override; + double givePitch(); + void recalculateCoordinates(int nodeNumber, FloatArray &coords) override; + void giveSwitches(FloatArray &answer); +}; +} // end namespace oofem + +#endif diff --git a/src/sm/Elements/LatticeElements/lattice3d.C b/src/sm/Elements/LatticeElements/lattice3d.C new file mode 100644 index 000000000..870765072 --- /dev/null +++ b/src/sm/Elements/LatticeElements/lattice3d.C @@ -0,0 +1,865 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "lattice3d.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "intarray.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "mathfem.h" +#include "latticestructuralelement.h" +#include "contextioerr.h" +#include "datastream.h" +#include "classfactory.h" +#include "sm/CrossSections/latticecrosssection.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" + #include "../sm/Materials/structuralmaterial.h" +#endif + +namespace oofem { +REGISTER_Element(Lattice3d); + +Lattice3d :: Lattice3d(int n, Domain *aDomain) : LatticeStructuralElement(n, aDomain) +{ + numberOfDofMans = 2; + geometryFlag = 0; + this->eccS = 0.; + this->eccT = 0.; +} + +Lattice3d :: ~Lattice3d() +{} + + +void +Lattice3d :: computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) +// Returns the strain matrix of the receiver. +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + //Assemble Bmatrix (used to compute strains and rotations} + answer.resize(6, 12); + answer.zero(); + + //Normal displacement jump in x-direction + //First node + answer.at(1, 1) = -1.; + answer.at(1, 2) = 0.; + answer.at(1, 3) = 0.; + answer.at(1, 4) = 0.; + answer.at(1, 5) = -this->eccT; + answer.at(1, 6) = this->eccS; + //Second node + answer.at(1, 7) = 1.; + answer.at(1, 8) = 0.; + answer.at(1, 9) = 0.; + answer.at(1, 10) = 0.; + answer.at(1, 11) = this->eccT; + answer.at(1, 12) = -this->eccS; + + //Shear displacement jump in y-plane + //first node + answer.at(2, 1) = 0.; + answer.at(2, 2) = -1.; + answer.at(2, 3) = 0.; + answer.at(2, 4) = this->eccT; + answer.at(2, 5) = 0; + answer.at(2, 6) = -this->length / 2.; + //Second node + answer.at(2, 7) = 0.; + answer.at(2, 8) = 1.; + answer.at(2, 9) = 0.; + answer.at(2, 10) = -this->eccT; + answer.at(2, 11) = 0; + answer.at(2, 12) = -this->length / 2.; + + //Shear displacement jump in z-plane + //first node + answer.at(3, 1) = 0.; + answer.at(3, 2) = 0.; + answer.at(3, 3) = -1.; + answer.at(3, 4) = -this->eccS; + answer.at(3, 5) = this->length / 2.; + answer.at(3, 6) = 0.; + //Second node + answer.at(3, 7) = 0.; + answer.at(3, 8) = 0.; + answer.at(3, 9) = 1.; + answer.at(3, 10) = this->eccS; + answer.at(3, 11) = this->length / 2.; + answer.at(3, 12) = 0.; + + //Rotation around x-axis + //First node + answer.at(4, 1) = 0.; + answer.at(4, 2) = 0; + answer.at(4, 3) = 0.; + answer.at(4, 4) = -sqrt(Ip / this->area); + answer.at(4, 5) = 0.; + answer.at(4, 6) = 0.; + //Second node + answer.at(4, 7) = 0.; + answer.at(4, 8) = 0.; + answer.at(4, 9) = 0.; + answer.at(4, 10) = sqrt(Ip / this->area); + answer.at(4, 11) = 0.; + answer.at(4, 12) = 0.; + + //Rotation around y-axis + //First node + answer.at(5, 1) = 0.; + answer.at(5, 2) = 0.; + answer.at(5, 3) = 0.; + answer.at(5, 4) = 0.; + answer.at(5, 5) = -sqrt(I1 / this->area); + answer.at(5, 6) = 0.; + //Second node + answer.at(5, 7) = 0.; + answer.at(5, 8) = 0.; + answer.at(5, 9) = 0.; + answer.at(5, 10) = 0.; + answer.at(5, 11) = sqrt(I1 / this->area); + answer.at(5, 12) = 0.; + + //Rotation around z-axis + //First node + answer.at(6, 1) = 0.; + answer.at(6, 2) = 0.; + answer.at(6, 3) = 0.; + answer.at(6, 4) = 0.; + answer.at(6, 5) = 0.; + answer.at(6, 6) = -sqrt(I2 / this->area); + //Second node + answer.at(6, 7) = 0.; + answer.at(6, 8) = 0.; + answer.at(6, 9) = 0.; + answer.at(6, 10) = 0.; + answer.at(6, 11) = 0.; + answer.at(6, 12) = sqrt(I2 / this->area); + + answer.times(1. / this->length); + + return; +} + +void +Lattice3d :: giveGPCoordinates(FloatArray &coords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + coords.resize(3); + coords = this->globalCentroid; + return; +} + +double +Lattice3d :: giveLength() +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + return this->length; +} + + +int +Lattice3d :: giveCrackFlag() +{ + GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); + LatticeMaterialStatus *status = static_cast< LatticeMaterialStatus * >( gp->giveMaterialStatus() ); + int crackFlag = 0; + crackFlag = status->giveCrackFlag(); + + return crackFlag; +} + + +double +Lattice3d :: giveCrackWidth() +{ + GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); + LatticeMaterialStatus *status = static_cast< LatticeMaterialStatus * >( gp->giveMaterialStatus() ); + double crackWidth = 0; + crackWidth = status->giveCrackWidth(); + + return crackWidth; +} + +void +Lattice3d :: givePlasticStrain(FloatArray &plasticStrain) +{ + GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); + LatticeMaterialStatus *status = static_cast< LatticeMaterialStatus * >( this->giveMaterial()->giveStatus(gp) ); + plasticStrain = status->givePlasticLatticeStrain(); + return; +} + +void +Lattice3d :: giveOldPlasticStrain(FloatArray &plasticStrain) +{ + GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); + LatticeMaterialStatus *status = static_cast< LatticeMaterialStatus * >( this->giveMaterial()->giveStatus(gp) ); + plasticStrain = status->giveOldPlasticLatticeStrain(); + return; +} + +void +Lattice3d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->give3dStiffnessMatrix(rMode, gp, tStep); +} + +void +Lattice3d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->giveLatticeStress3d(strain, gp, tStep); +} + +void +Lattice3d :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + FloatMatrix d, bi, bj, bjt, dbj, dij; + + answer.resize(12, 12); + answer.zero(); + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), bj); + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + double volume = this->computeVolumeAround(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); + + for ( int i = 1; i <= 6; i++ ) { + d.at(i, i) *= volume; + } + + dbj.beProductOf(d, bj); + bjt.beTranspositionOf(bj); + answer.beProductOf(bjt, dbj); + + return; +} + +void Lattice3d :: computeGaussPoints() +// Sets up the array of Gauss Points of the receiver. +{ + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ].reset(new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ]->SetUpPointsOnLine(1, _3dLattice); +} + + + +double Lattice3d :: giveArea() { + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + return this->area; +} + + +bool +Lattice3d :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + int i, j; + + answer.resize(12, 12); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( i = 1; i <= 3; i++ ) { + for ( j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + answer.at(i + 6, j + 6) = lcs.at(i, j); + answer.at(i + 9, j + 9) = lcs.at(i, j); + } + } + + return 1; +} + + +double +Lattice3d :: giveNormalStress() +{ + GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); + LatticeMaterialStatus *status = static_cast< LatticeMaterialStatus * >( gp->giveMaterialStatus() ); + double normalStress = 0; + normalStress = status->giveNormalLatticeStress(); + + return normalStress; +} + + +int +Lattice3d :: giveLocalCoordinateSystem(FloatMatrix &answer) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer = this->localCoordinateSystem; + + return 1; +} + + +double +Lattice3d :: computeVolumeAround(GaussPoint *aGaussPoint) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + return this->area * this->length; +} + +void +Lattice3d :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = { + D_u, D_v, D_w, R_u, R_v, R_w + }; +} + +void +Lattice3d :: initializeFrom(InputRecord &ir) +{ + LatticeStructuralElement :: initializeFrom(ir); + + minLength = 1.e-20; + IR_GIVE_OPTIONAL_FIELD(ir, minLength, _IFT_Lattice3d_mlength); + + polygonCoords.resize(0); + IR_GIVE_OPTIONAL_FIELD(ir, polygonCoords, _IFT_Lattice3d_polycoords); + numberOfPolygonVertices = polygonCoords.giveSize() / 3.; + + couplingFlag = 0; + IR_GIVE_OPTIONAL_FIELD(ir, couplingFlag, _IFT_Lattice3d_couplingflag); + + IR_GIVE_OPTIONAL_FIELD(ir, couplingNumbers, _IFT_Lattice3d_couplingnumber); + + pressures.resize(numberOfPolygonVertices); + pressures.zero(); + IR_GIVE_OPTIONAL_FIELD(ir, pressures, _IFT_Lattice3d_pressures); +} + + +int +Lattice3d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer.resize(3); + answer = this->globalCentroid; + + return 1; +} + + +void +Lattice3d :: computeGeometryProperties() +{ + //coordinates of the two nodes + Node *nodeA, *nodeB; + FloatArray coordsA(3), coordsB(3); + + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + + for ( int i = 0; i < 3; i++ ) { + coordsA.at(i + 1) = nodeA->giveCoordinate(i + 1); + coordsB.at(i + 1) = nodeB->giveCoordinate(i + 1); + } + + //Construct an initial temporary local coordinate system + FloatArray s(3), t(3); + + //Calculate normal vector + this->normal.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) = coordsB.at(i + 1) - coordsA.at(i + 1); + } + + this->length = sqrt(pow(normal.at(1), 2.) + pow(normal.at(2), 2.) + pow(normal.at(3), 2.) ); + + // Compute midpoint + this->midPoint.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->midPoint.at(i + 1) = 0.5 * ( coordsB.at(i + 1) + coordsA.at(i + 1) ); + } + + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) /= length; + } + + computeCrossSectionProperties(); + + this->geometryFlag = 1; + + return; +} + + +void +Lattice3d :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +// Returns the lumped mass matrix of the receiver. This expression is +// valid in both local and global axes. +{ + GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + double density = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->give('d', gp); + double halfMass = density * computeVolumeAround(gp) / 2.; + answer.resize(12, 12); + answer.zero(); + answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = halfMass; + answer.at(7, 7) = answer.at(8, 8) = answer.at(9, 9) = halfMass; +} + + + +void +Lattice3d :: computeCrossSectionProperties() { + if ( this->numberOfPolygonVertices < 3 ) { + printf("Too small number of polygon vertices\n"); + return; + } + + //Construct two perpendicular axis so that n is normal to the plane which they create + //Check, if one of the components of the normal-direction is zero + FloatArray s(3), t(3); + if ( this->normal.at(1) == 0 ) { + s.at(1) = 0.; + s.at(2) = this->normal.at(3); + s.at(3) = -this->normal.at(2); + } else if ( this->normal.at(2) == 0 ) { + s.at(1) = this->normal.at(3); + s.at(2) = 0.; + s.at(3) = -this->normal.at(1); + } else { + s.at(1) = this->normal.at(2); + s.at(2) = -this->normal.at(1); + s.at(3) = 0.; + } + + s.normalize(); + + t.beVectorProductOf(this->normal, s); + t.normalize(); + + //Set up rotation matrix + FloatMatrix lcs(3, 3); + + for ( int i = 1; i <= 3; i++ ) { + lcs.at(1, i) = this->normal.at(i); + lcs.at(2, i) = s.at(i); + lcs.at(3, i) = t.at(i); + } + + + //Calculate the local coordinates of the polygon vertices + FloatArray help(3), test(3); + FloatArray lpc(3 * numberOfPolygonVertices); + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + for ( int n = 0; n < 3; n++ ) { + help(n) = polygonCoords(3 * k + n); + } + + test.beProductOf(lcs, help); + for ( int n = 0; n < 3; n++ ) { + lpc(3 * k + n) = test(n); + } + } + + this->area = 0.; + + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + if ( k < numberOfPolygonVertices - 1 ) { + this->area += lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2); + } else { //Back to zero for n+1 + this->area += lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2); + } + } + + this->area *= 0.5; + + FloatArray tempCoords(3 * numberOfPolygonVertices); + if ( this->area < 0 ) { //Set area to a positive value and rearrange the coordinate entries + this->area *= -1.; + + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + for ( int m = 0; m < 3; m++ ) { + tempCoords.at(3 * k + m + 1) = polygonCoords.at(3 * ( numberOfPolygonVertices - k - 1 ) + m + 1); + } + } + + polygonCoords = tempCoords; + + // Calculate again local co-ordinate system for different order + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + for ( int n = 0; n < 3; n++ ) { + help(n) = polygonCoords(3 * k + n); + } + + test.beProductOf(lcs, help); + for ( int n = 0; n < 3; n++ ) { + lpc(3 * k + n) = test(n); + } + } + } + + if ( this->area < pow(minLength, 2.) ) { + this->area = pow(minLength, 2.); + } + + //Calculate centroids + centroid.resize(3); + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + if ( k < numberOfPolygonVertices - 1 ) { + centroid.at(2) += ( lpc(3 * k + 1) + lpc(3 * ( k + 1 ) + 1) ) * ( lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2) ); + centroid.at(3) += ( lpc(3 * k + 2) + lpc(3 * ( k + 1 ) + 2) ) * ( lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2) ); + } else { //Back to zero for n+1 + centroid.at(2) += ( lpc(3 * k + 1) + lpc(1) ) * ( lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2) ); + centroid.at(3) += ( lpc(3 * k + 2) + lpc(2) ) * ( lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2) ); + } + } + + centroid.times(1. / ( 6. * this->area ) ); + + centroid.at(1) = lpc.at(1); //The first component of all lpcs should be the same + + //Shift coordinates to centroid + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + for ( int l = 0; l < 3; l++ ) { + lpc(3 * k + l) -= centroid(l); + } + } + + //Compute second moments of area. + //This is for the temporary coordinate system + double Ixx = 0.; + double Iyy = 0.; + double Ixy = 0.; + double a; + + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + if ( k < numberOfPolygonVertices - 1 ) { + a = lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2); + + Ixx += ( ( pow(lpc(3 * k + 2), 2.) + lpc(3 * k + 2) * lpc(3 * ( k + 1 ) + 2) + pow(lpc(3 * ( k + 1 ) + 2), 2.) ) * a ) / 12.; + + Iyy += ( ( pow(lpc(3 * k + 1), 2.) + lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 1) + pow(lpc(3 * ( k + 1 ) + 1), 2.) ) * a ) / 12.; + + Ixy += ( ( lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) + 2. * lpc(3 * k + 1) * lpc(3 * k + 2) + + 2 * lpc(3 * ( k + 1 ) + 1) * lpc(3 * ( k + 1 ) + 2) + lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2) ) * a ) / 24.; + } else { //Back to zero for n+1 + a = lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2); + + Ixx += ( ( pow(lpc(3 * k + 2), 2.) + lpc(3 * k + 2) * lpc(2) + pow(lpc(2), 2.) ) * a ) / 12.; + + Iyy += ( ( pow(lpc(3 * k + 1), 2.) + lpc(3 * k + 1) * lpc(1) + pow(lpc(1), 2.) ) * a ) / 12.; + + Ixy += ( ( lpc(3 * k + 1) * lpc(2) + 2. * lpc(3 * k + 1) * lpc(3 * k + 2) + + 2 * lpc(1) * lpc(2) + lpc(1) * lpc(3 * k + 2) ) * a ) / 24.; + } + } + + //Compute main axis of the cross-section + double angleChange = 0.; + double sum = fabs(Ixx + Iyy); + double pi = 3.14159265; + if ( ( fabs(Ixx - Iyy) / sum > 1.e-6 ) && fabs(Ixy) / sum > 1.e-6 ) { + angleChange = 0.5 * atan(-2 * Ixy / ( Ixx - Iyy ) ); + } else if ( ( fabs(Ixx - Iyy) / sum < 1.e-6 ) && fabs(Ixy) / sum > 1.e-6 ) { + angleChange = pi / 4.; + } + + if ( Iyy > Ixx ) { + angleChange = angleChange + pi / 2.; + } + + //Moment of inertias saved in the element + + this->I1 = ( Ixx + Iyy ) / 2. + sqrt(pow( ( Ixx - Iyy ) / 2., 2. ) + pow(Ixy, 2.) ); + this->I2 = ( Ixx + Iyy ) / 2. - sqrt(pow( ( Ixx - Iyy ) / 2., 2. ) + pow(Ixy, 2.) ); + + this->Ip = I1 + I2; + + //Rotation around normal axis by angleChange + + FloatMatrix rotationChange(3, 3); + rotationChange.zero(); + + rotationChange.at(1, 1) = 1.; + rotationChange.at(2, 2) = cos(angleChange); + rotationChange.at(2, 3) = -sin(angleChange); + + rotationChange.at(3, 2) = sin(angleChange); + rotationChange.at(3, 3) = cos(angleChange); + + this->localCoordinateSystem.beProductOf(rotationChange, lcs); + + //Calculate the polygon vertices in the new coordinate system + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + for ( int n = 0; n < 3; n++ ) { + help(n) = polygonCoords(3 * k + n); + } + + test.beProductOf(this->localCoordinateSystem, help); + for ( int n = 0; n < 3; n++ ) { + lpc(3 * k + n) = test(n); + } + } + + //Calculate centroid again in local coordinate system + centroid.zero(); + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + if ( k < numberOfPolygonVertices - 1 ) { + centroid.at(2) += ( lpc(3 * k + 1) + lpc(3 * ( k + 1 ) + 1) ) * ( lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2) ); + centroid.at(3) += ( lpc(3 * k + 2) + lpc(3 * ( k + 1 ) + 2) ) * ( lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2) ); + } else { //Back to zero for n+1 + centroid.at(2) += ( lpc(3 * k + 1) + lpc(1) ) * ( lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2) ); + centroid.at(3) += ( lpc(3 * k + 2) + lpc(2) ) * ( lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2) ); + } + } + + centroid.times(1. / ( 6. * this->area ) ); + + centroid.at(1) = lpc.at(1); //The first component of all lpcs should be the same + + FloatArray midPointLocal(3); + midPointLocal.beProductOf(this->localCoordinateSystem, midPoint); + + //eccentricities stored in the element + this->eccS = centroid.at(2) - midPointLocal.at(2); + this->eccT = centroid.at(3) - midPointLocal.at(3); + + FloatMatrix transposeLCS; + transposeLCS.beTranspositionOf(this->localCoordinateSystem); + + this->globalCentroid.beProductOf(transposeLCS, centroid); + + return; +} + + +void +Lattice3d :: saveContext(DataStream &stream, ContextMode mode) +{ + LatticeStructuralElement :: saveContext(stream, mode); + + contextIOResultType iores; + + if ( ( mode & CM_Definition ) ) { + if ( ( iores = polygonCoords.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( !stream.write(couplingFlag) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( ( iores = couplingNumbers.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + } +} + + +void +Lattice3d :: restoreContext(DataStream &stream, ContextMode mode) +{ + LatticeStructuralElement :: restoreContext(stream, mode); + + contextIOResultType iores; + + if ( mode & CM_Definition ) { + if ( ( iores = this->polygonCoords.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( !stream.read(this->couplingFlag) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( ( iores = this->couplingNumbers.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + } +} + +#ifdef __OOFEG + +void +Lattice3d :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + this->drawRawCrossSections(gc, tStep); + } else if ( mode == OGC_deformedGeometry ) { + this->drawDeformedGeometry(gc, tStep, DisplacementVector); + } else if ( mode == OGC_eigenVectorGeometry ) { + this->drawDeformedGeometry(gc, tStep, EigenVector); + } else if ( mode == OGC_scalarPlot ) { + this->drawScalar(gc, tStep); + } else if ( mode == OGC_elemSpecial ) { + this->drawSpecial(gc, tStep); + } else { + OOFEM_ERROR("unsupported mode"); + } +} + + + + +void Lattice3d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + WCRec p [ 2 ]; /* points */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getElementColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + + +void +Lattice3d :: drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + //Create as many points as we have polygon vertices + numberOfPolygonVertices = this->polygonCoords.giveSize() / 3.; + WCRec p [ numberOfPolygonVertices ]; /* poin */ + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + + EASValsSetLayer(OOFEG_RAW_CROSSSECTION_LAYER); + + for ( int i = 0; i < numberOfPolygonVertices; i++ ) { + p [ i ].x = ( FPNum ) polygonCoords(3 * i); + p [ i ].y = ( FPNum ) polygonCoords(3 * i + 1); + p [ i ].z = ( FPNum ) polygonCoords(3 * i + 2); + } + + + WCRec pTemp [ 2 ]; /* points */ + for ( int i = 0; i < numberOfPolygonVertices; i++ ) { + if ( i < numberOfPolygonVertices - 1 ) { + pTemp [ 0 ] = p [ i ]; + pTemp [ 1 ] = p [ i + 1 ]; + } else { + pTemp [ 0 ] = p [ i ]; + pTemp [ 1 ] = p [ 0 ]; + } + + go = CreateLine3D(pTemp); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); + } +} + + + +void Lattice3d :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ + GraphicObj *go; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + double defScale = gc.getDefScale(); + + WCRec p [ 2 ]; /* points */ + + EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(3, tStep, defScale); + + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(3, tStep, defScale); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EMAddGraphicsToModel(ESIModel(), go); +} + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/LatticeElements/lattice3d.h b/src/sm/Elements/LatticeElements/lattice3d.h new file mode 100644 index 000000000..575c38c82 --- /dev/null +++ b/src/sm/Elements/LatticeElements/lattice3d.h @@ -0,0 +1,157 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef lattice3d_h +#define lattice3d_h + +#include "latticestructuralelement.h" + +///@name Input fields for Lattice3d +//@{ +#define _IFT_Lattice3d_Name "lattice3d" +#define _IFT_Lattice3d_mlength "mlength" +#define _IFT_Lattice3d_polycoords "polycoords" +#define _IFT_Lattice3d_couplingflag "couplingflag" +#define _IFT_Lattice3d_couplingnumber "couplingnumber" +#define _IFT_Lattice3d_pressures "pressures" +//@} + +namespace oofem { +/** + * This class implements a 3-dimensional lattice element + */ + +class Lattice3d : public LatticeStructuralElement +{ +protected: + double minLength; + double kappa, length; + double I1, I2, Ip; + FloatArray polygonCoords; + int numberOfPolygonVertices; + FloatMatrix localCoordinateSystem; + double eccS, eccT, area; + FloatArray midPoint, centroid, globalCentroid, normal; + int geometryFlag; + int couplingFlag; + IntArray couplingNumbers; + FloatArray pressures; + +public: + Lattice3d(int n, Domain *); + virtual ~Lattice3d(); + + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + double giveLength() override; + + double giveNormalStress() override; + + double giveArea() override; + + int computeNumberOfDofs() override { return 12; } + + void giveDofManDofIDMask(int inode, IntArray &) const override; + + double computeVolumeAround(GaussPoint *) override; + + int giveNumberOfCrossSectionNodes() override { return numberOfPolygonVertices; } + + int giveCrackFlag() override; + + double giveCrackWidth() override; + + void givePlasticStrain(FloatArray &plas) override; + void giveOldPlasticStrain(FloatArray &plas) override; + + void givePressures(FloatArray &pres) override { pres = pressures; } + + int giveCouplingFlag() override { return couplingFlag; } + + void giveCouplingNumbers(IntArray &numbers) override { numbers = this->couplingNumbers; } + + /** + * This function gives the cross-section coordinates. + */ + void giveCrossSectionCoordinates(FloatArray &coords) override { coords = polygonCoords; } + + virtual void giveGPCoordinates(FloatArray &coords); + + virtual void computeGeometryProperties(); + + virtual void computeCrossSectionProperties(); + + const char *giveInputRecordName() const override { return _IFT_Lattice3d_Name; } + const char *giveClassName() const override { return "Lattice3d"; } + void initializeFrom(InputRecord &ir) override; + + + + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; + +#ifdef __OOFEG + void drawYourself(oofegGraphicContext &context, TimeStep *tStep) override; + void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + void drawRawCrossSections(oofegGraphicContext &, TimeStep *tStep); + void drawDeformedGeometry(oofegGraphicContext &, TimeStep *tStep, UnknownType) override; +#endif + + +protected: + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + bool computeGtoLRotationMatrix(FloatMatrix &) override; + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override + { this->computeLumpedMassMatrix(answer, tStep); } + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + + /** + * This computes the geometrical properties of the element once. + */ + void computePropertiesOfCrossSection(); + + void computeGaussPoints() override; + integrationDomain giveIntegrationDomain() const override { return _Line; } +}; +} // end namespace oofem +#endif diff --git a/src/sm/Elements/LatticeElements/lattice3dboundary.C b/src/sm/Elements/LatticeElements/lattice3dboundary.C new file mode 100644 index 000000000..3fdc93cf8 --- /dev/null +++ b/src/sm/Elements/LatticeElements/lattice3dboundary.C @@ -0,0 +1,864 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "lattice3dboundary.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "latticestructuralelement.h" +#include "classfactory.h" +#include "../sm/Materials/structuralmaterial.h" +#include "contextioerr.h" +#include "datastream.h" +#include "crosssection.h" +#include "dof.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { +REGISTER_Element(Lattice3dBoundary); + +Lattice3dBoundary :: Lattice3dBoundary(int n, Domain *aDomain) : Lattice3d(n, aDomain) +{ + numberOfDofMans = 3; + geometryFlag = 0; +} + +Lattice3dBoundary :: ~Lattice3dBoundary() +{} + + +void +Lattice3dBoundary :: computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) +// Returns the strain matrix of the receiver. +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + //Assemble Bmatrix (used to compute strains and rotations} + answer.resize(6, 12); + answer.zero(); + + //Normal displacement jump in x-direction + //First node + answer.at(1, 1) = -1.; + answer.at(1, 2) = 0.; + answer.at(1, 3) = 0.; + answer.at(1, 4) = 0.; + answer.at(1, 5) = -this->eccT; + answer.at(1, 6) = this->eccS; + //Second node + answer.at(1, 7) = 1.; + answer.at(1, 8) = 0.; + answer.at(1, 9) = 0.; + answer.at(1, 10) = 0.; + answer.at(1, 11) = this->eccT; + answer.at(1, 12) = -this->eccS; + + //Shear displacement jump in y-plane + //first node + answer.at(2, 1) = 0.; + answer.at(2, 2) = -1.; + answer.at(2, 3) = 0.; + answer.at(2, 4) = this->eccT; + answer.at(2, 5) = 0; + answer.at(2, 6) = -this->length / 2.; + //Second node + answer.at(2, 7) = 0.; + answer.at(2, 8) = 1.; + answer.at(2, 9) = 0.; + answer.at(2, 10) = -this->eccT; + answer.at(2, 11) = 0; + answer.at(2, 12) = -this->length / 2.; + + //Shear displacement jump in z-plane + //first node + answer.at(3, 1) = 0.; + answer.at(3, 2) = 0.; + answer.at(3, 3) = -1.; + answer.at(3, 4) = -this->eccS; + answer.at(3, 5) = this->length / 2.; + answer.at(3, 6) = 0.; + //Second node + answer.at(3, 7) = 0.; + answer.at(3, 8) = 0.; + answer.at(3, 9) = 1.; + answer.at(3, 10) = this->eccS; + answer.at(3, 11) = this->length / 2.; + answer.at(3, 12) = 0.; + + //Rotation around x-axis + //First node + answer.at(4, 1) = 0.; + answer.at(4, 2) = 0; + answer.at(4, 3) = 0.; + answer.at(4, 4) = -sqrt(Ip / this->area); + answer.at(4, 5) = 0.; + answer.at(4, 6) = 0.; + //Second node + answer.at(4, 7) = 0.; + answer.at(4, 8) = 0.; + answer.at(4, 9) = 0.; + answer.at(4, 10) = sqrt(Ip / this->area); + answer.at(4, 11) = 0.; + answer.at(4, 12) = 0.; + + //Rotation around y-axis + //First node + answer.at(5, 1) = 0.; + answer.at(5, 2) = 0.; + answer.at(5, 3) = 0.; + answer.at(5, 4) = 0.; + answer.at(5, 5) = -sqrt(I1 / this->area); + answer.at(5, 6) = 0.; + //Second node + answer.at(5, 7) = 0.; + answer.at(5, 8) = 0.; + answer.at(5, 9) = 0.; + answer.at(5, 10) = 0.; + answer.at(5, 11) = sqrt(I1 / this->area); + answer.at(5, 12) = 0.; + + //Rotation around z-axis + //First node + answer.at(6, 1) = 0.; + answer.at(6, 2) = 0.; + answer.at(6, 3) = 0.; + answer.at(6, 4) = 0.; + answer.at(6, 5) = 0.; + answer.at(6, 6) = -sqrt(I2 / this->area); + //Second node + answer.at(6, 7) = 0.; + answer.at(6, 8) = 0.; + answer.at(6, 9) = 0.; + answer.at(6, 10) = 0.; + answer.at(6, 11) = 0.; + answer.at(6, 12) = sqrt(I2 / this->area); + + answer.times(1. / this->length); + + return; +} + +void +Lattice3dBoundary :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + // double dV; + FloatMatrix d, bi, bj, dbj, dij, bjt; + FloatMatrix t(12, 18), tt; + FloatMatrix answerTemp(12, 12), answerHelp, ttk(18, 12); + bool matStiffSymmFlag = this->giveCrossSection()->isCharacteristicMtrxSymmetric(rMode); + answerTemp.zero(); + answerHelp.zero(); + t.zero(); + + + + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + double volume = this->computeVolumeAround(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); + + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), bj); + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + for ( int i = 1; i <= 6; i++ ) { + d.at(i, i) *= volume; + } + + dbj.beProductOf(d, bj); + bjt.beTranspositionOf(bj); + answerTemp.beProductOf(bjt, dbj); + + answer.resize(computeNumberOfDofs(), computeNumberOfDofs() ); + answer.zero(); + + answerHelp.resize(computeNumberOfDofs(), computeNumberOfDofs() ); + answerHelp.zero(); + + for ( int m = 1; m <= 12; m++ ) { + for ( int k = 1; k <= 12; k++ ) { + answer.at(m, k) = answerTemp.at(m, k); + } + } + + if ( matStiffSymmFlag ) { + answer.symmetrized(); + } + + // Rotate to global system add the projections and rotate back to local system. + + FloatMatrix R; + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R); + } + + for ( int m = 1; m <= 12; m++ ) { + for ( int k = 1; k <= 12; k++ ) { + answerTemp.at(m, k) = answer.at(m, k); + } + } + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + for ( int k = 1; k <= 12; k++ ) { + t.at(k, k) = 1.; + } + t.at(1, 13) = projectionComponentNodeOne.at(1); + t.at(2, 14) = projectionComponentNodeOne.at(2); + t.at(3, 15) = projectionComponentNodeOne.at(3); + + + t.at(2, 16) = projectionComponentNodeOne.at(3); + t.at(1, 17) = projectionComponentNodeOne.at(3); + t.at(1, 18) = projectionComponentNodeOne.at(2); + + + t.at(7, 13) = projectionComponentNodeTwo.at(1); + t.at(8, 14) = projectionComponentNodeTwo.at(2); + t.at(9, 15) = projectionComponentNodeTwo.at(3); + + t.at(8, 16) = projectionComponentNodeTwo.at(3); + t.at(7, 17) = projectionComponentNodeTwo.at(3); + t.at(7, 18) = projectionComponentNodeTwo.at(2); + + + tt.beTranspositionOf(t); + + ttk.beProductOf(tt, answerTemp); + answer.beProductOf(ttk, t); + + //Rotate back to local system + FloatMatrix Rtranspose; + Rtranspose.beTranspositionOf(R); + answer.rotatedWith(Rtranspose); + + return; +} + + + +double +Lattice3dBoundary :: computeVolumeAround(GaussPoint *aGaussPoint) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + return this->area * this->length; +} + +void +Lattice3dBoundary :: recalculateCoordinates(int nodeNumber, FloatArray &coords) { + coords.resize(3); + coords.zero(); + Node *node; + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray projectionComponent(3); + projectionComponent.zero(); + + if ( nodeNumber == 1 ) { + node = this->giveNode(1); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponent, location.at(1) ); + } + } else if ( nodeNumber == 2 ) { + node = this->giveNode(2); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponent, location.at(2) ); + } + } else { + OOFEM_ERROR("wrong element used in the vtk module"); + } + + for ( int i = 0; i < 3; i++ ) { + coords.at(i + 1) = node->giveCoordinate(i + 1) + projectionComponent.at(i + 1) * specimenDimension.at(i + 1); + } + return; +} + +void +Lattice3dBoundary :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *stepN) +// Computes the vector containing the strains at the Gauss point gp of +// the receiver, at time step stepN. The nature of these strains depends +// on the element's type. +{ + FloatMatrix b; + FloatArray u; + + + //Compute strain vector + //Get the 18 components of the displacement vector of this element + this->computeVectorOf(VM_Total, stepN, u); + this->computeBmatrixAt(gp, b); + + + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + //Compute projection vector + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + FloatMatrix rotationMatrix; + if ( this->computeGtoLRotationMatrix(rotationMatrix) ) { + u.rotatedWith(rotationMatrix, 't'); + } + + //General expressions for the corrected displacements. Rotations at nodes are not influenced. Only translations + u.at(1) = u.at(1) + projectionComponentNodeOne.at(1) * u.at(13) + projectionComponentNodeOne.at(2) * u.at(18) + projectionComponentNodeOne.at(3) * u.at(17); + u.at(2) = u.at(2) + projectionComponentNodeOne.at(2) * u.at(14) + projectionComponentNodeOne.at(3) * u.at(16); + u.at(3) = u.at(3) + projectionComponentNodeOne.at(3) * u.at(15); + + u.at(7) = u.at(7) + projectionComponentNodeTwo.at(1) * u.at(13) + projectionComponentNodeTwo.at(2) * u.at(18) + projectionComponentNodeTwo.at(3) * u.at(17); + u.at(8) = u.at(8) + projectionComponentNodeTwo.at(2) * u.at(14) + projectionComponentNodeTwo.at(3) * u.at(16); + u.at(9) = u.at(9) + projectionComponentNodeTwo.at(3) * u.at(15); + + + if ( this->computeGtoLRotationMatrix(rotationMatrix) ) { + u.rotatedWith(rotationMatrix, 'n'); + } + //define a temp displacement vector + FloatArray uTemp(12); + + for ( int i = 1; i <= 12; i++ ) { + uTemp.at(i) = u.at(i); + } + + answer.beProductOf(b, uTemp); +} + +bool +Lattice3dBoundary :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + int i, j; + + answer.resize(18, 18); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( i = 1; i <= 3; i++ ) { + for ( j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + answer.at(i + 6, j + 6) = lcs.at(i, j); + answer.at(i + 9, j + 9) = lcs.at(i, j); + } + } + answer.at(13, 13) = 1.; + answer.at(14, 14) = 1.; + answer.at(15, 15) = 1.; + answer.at(16, 16) = 1.; + answer.at(17, 17) = 1.; + answer.at(18, 18) = 1.; + + return 1; +} + +int +Lattice3dBoundary :: giveLocalCoordinateSystem(FloatMatrix &answer) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer = this->localCoordinateSystem; + + return 1; +} + + + +void +Lattice3dBoundary :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 3 ) { + answer = { E_xx, E_yy, E_zz, G_yz, G_xz, G_xy }; + } else { + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; + } +} + +void +Lattice3dBoundary :: initializeFrom(InputRecord &ir) +{ + Lattice3d :: initializeFrom(ir); + + this->location.resize(2); + IR_GIVE_FIELD(ir, location, _IFT_Lattice3dBoundary_location); // Macro +} + + + +void +Lattice3dBoundary :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + Material *mat = this->giveMaterial(); + + FloatMatrix b, bt, A, R, GNT; + FloatArray bs, TotalStressVector, u, strain; + double dV; + + this->computeVectorOf(VM_Total, tStep, u); + + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + answer.resize(18); + answer.zero(); + + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), b); + + bt.beTranspositionOf(b); + if ( useUpdatedGpRecord == 1 ) { + TotalStressVector = ( ( LatticeMaterialStatus * ) mat->giveStatus(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ) ) + ->giveLatticeStress(); + } else + if ( !this->isActivated(tStep) ) { + strain.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialMode() ) ); + strain.zero(); + } + this->computeStrainVector(strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + this->computeStressVector(TotalStressVector, strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + dV = this->computeVolumeAround(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); + bs.beProductOf(bt, TotalStressVector); + bs.times(dV); + + for ( int m = 1; m <= 12; m++ ) { + answer.at(m) = bs.at(m); + } + + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R, 't'); + } + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + //Normal stresses + answer.at(13) = projectionComponentNodeOne.at(1) * answer.at(1) + projectionComponentNodeTwo.at(1) * answer.at(7); + answer.at(14) = projectionComponentNodeOne.at(2) * answer.at(2) + projectionComponentNodeTwo.at(2) * answer.at(8); + answer.at(15) = projectionComponentNodeOne.at(3) * answer.at(3) + projectionComponentNodeTwo.at(3) * answer.at(9); + + //Shear stresses + answer.at(16) = projectionComponentNodeOne.at(3) * answer.at(2) + projectionComponentNodeTwo.at(3) * answer.at(8); + answer.at(17) = projectionComponentNodeOne.at(3) * answer.at(1) + projectionComponentNodeTwo.at(3) * answer.at(7); + answer.at(18) = projectionComponentNodeOne.at(2) * answer.at(1) + projectionComponentNodeTwo.at(2) * answer.at(7); + + //Rotate to local system + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R, 'n'); + } + + return; +} + + +void +Lattice3dBoundary :: giveSwitches(IntArray &answer, int location) { + int counter = 1; + for ( int x = -1; x < 2; x++ ) { + for ( int y = -1; y < 2; y++ ) { + for ( int z = -1; z < 2; z++ ) { + if ( !( z == 0 && y == 0 && x == 0 ) ) { + if ( counter == location ) { + answer(0) = x; + answer(1) = y; + answer(2) = z; + } + counter++; + } + } + } + } + return; +} + + +void +Lattice3dBoundary :: computeGeometryProperties() +{ + Node *nodeA, *nodeB; + + FloatArray coordsA(3); + FloatArray coordsB(3); + + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + for ( int i = 0; i < 3; i++ ) { + coordsA.at(i + 1) = nodeA->giveCoordinate(i + 1) + projectionComponentNodeOne.at(i + 1) * specimenDimension.at(i + 1); + coordsB.at(i + 1) = nodeB->giveCoordinate(i + 1) + projectionComponentNodeTwo.at(i + 1) * specimenDimension.at(i + 1); + } + + //Calculate normal vector + FloatArray s(3), t(3); + this->midPoint.resize(3); + + //Calculate normal vector + this->normal.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) = coordsB.at(i + 1) - coordsA.at(i + 1); + } + + this->length = sqrt(pow(this->normal.at(1), 2.) + pow(this->normal.at(2), 2.) + pow(this->normal.at(3), 2.) ); + + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) /= length; + } + + // Compute midpoint + this->midPoint.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->midPoint.at(i + 1) = 0.5 * ( coordsB.at(i + 1) + coordsA.at(i + 1) ); + } + + computeCrossSectionProperties(); + + //Set geometry flag to 1 so that this is done only once + this->geometryFlag = 1; + + return; +} + + +void +Lattice3dBoundary :: saveContext(DataStream &stream, ContextMode mode) +{ + Lattice3d :: saveContext(stream, mode); + + contextIOResultType iores; + + if ( ( mode & CM_Definition ) ) { + if ( ( iores = location.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + } +} + + + +void +Lattice3dBoundary :: restoreContext(DataStream &stream, ContextMode mode) +{ + Lattice3d :: restoreContext(stream, mode); + + contextIOResultType iores; + + if ( mode & CM_Definition ) { + if ( ( iores = this->location.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + } +} + + + +#ifdef __OOFEG + +void +Lattice3dBoundary :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + this->drawRawCrossSections(gc, tStep); + } else if ( mode == OGC_deformedGeometry ) { + this->drawDeformedGeometry(gc, tStep, DisplacementVector); + } else if ( mode == OGC_elemSpecial ) { + this->drawSpecial(gc, tStep); + } else { + OOFEM_ERROR("drawYourself : unsupported mode"); + } +} + + + + +void Lattice3dBoundary :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + WCRec p [ 2 ]; /* points */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getActiveCrackColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + //Compute projection vector + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1) + projectionComponentNodeOne.at(1) * specimenDimension.at(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2) + projectionComponentNodeOne.at(2) * specimenDimension.at(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3) + projectionComponentNodeOne.at(3) * specimenDimension.at(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1) + projectionComponentNodeTwo.at(1) * specimenDimension.at(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2) + projectionComponentNodeTwo.at(2) * specimenDimension.at(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3) + projectionComponentNodeTwo.at(3) * specimenDimension.at(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + + +void +Lattice3dBoundary :: drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + // if (!go) { // create new one + //Create as many points as we have polygon vertices + numberOfPolygonVertices = this->polygonCoords.giveSize() / 3.; + WCRec p [ numberOfPolygonVertices ]; /* poin */ + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + // EASValsSetColor(gc.getNodeColor()); + EASValsSetLayer(OOFEG_RAW_CROSSSECTION_LAYER); + + for ( int i = 0; i < numberOfPolygonVertices; i++ ) { + p [ i ].x = ( FPNum ) polygonCoords(3 * i); + p [ i ].y = ( FPNum ) polygonCoords(3 * i + 1); + p [ i ].z = ( FPNum ) polygonCoords(3 * i + 2); + } + + + WCRec pTemp [ 2 ]; /* points */ + for ( int i = 0; i < numberOfPolygonVertices; i++ ) { + if ( i < numberOfPolygonVertices - 1 ) { + pTemp [ 0 ] = p [ i ]; + pTemp [ 1 ] = p [ i + 1 ]; + } else { + pTemp [ 0 ] = p [ i ]; + pTemp [ 1 ] = p [ 0 ]; + } + + go = CreateLine3D(pTemp); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); + } +} + + +void Lattice3dBoundary :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ + //That seems to be wrong. The strain field should be ordered exx, eyy, ezz, gyz, gzx, gyx + //Therefore, the x displacement should include 5th and 6th strain components. + GraphicObj *go; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + double defScale = gc.getDefScale(); + + WCRec p [ 2 ]; /* points */ + + EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + FloatArray dispOne(6); + dispOne.at(1) = this->giveNode(1)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispOne.at(2) = this->giveNode(1)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispOne.at(3) = this->giveNode(1)->giveDofWithID(D_w)->giveUnknown(VM_Total, tStep); + dispOne.at(4) = this->giveNode(1)->giveDofWithID(R_u)->giveUnknown(VM_Total, tStep); + dispOne.at(5) = this->giveNode(1)->giveDofWithID(R_v)->giveUnknown(VM_Total, tStep); + dispOne.at(6) = this->giveNode(1)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + FloatArray dispTwo(6); + dispTwo.at(1) = this->giveNode(2)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispTwo.at(2) = this->giveNode(2)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispTwo.at(3) = this->giveNode(2)->giveDofWithID(D_w)->giveUnknown(VM_Total, tStep); + dispTwo.at(4) = this->giveNode(2)->giveDofWithID(R_u)->giveUnknown(VM_Total, tStep); + dispTwo.at(5) = this->giveNode(2)->giveDofWithID(R_v)->giveUnknown(VM_Total, tStep); + dispTwo.at(6) = this->giveNode(2)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + FloatArray dispThree(6); + dispThree.at(1) = this->giveNode(3)->giveDofWithID(E_xx)->giveUnknown(VM_Total, tStep); + dispThree.at(2) = this->giveNode(3)->giveDofWithID(E_yy)->giveUnknown(VM_Total, tStep); + dispThree.at(3) = this->giveNode(3)->giveDofWithID(E_zz)->giveUnknown(VM_Total, tStep); + dispThree.at(4) = this->giveNode(3)->giveDofWithID(G_yz)->giveUnknown(VM_Total, tStep); + dispThree.at(5) = this->giveNode(3)->giveDofWithID(G_xz)->giveUnknown(VM_Total, tStep); + dispThree.at(6) = this->giveNode(3)->giveDofWithID(G_xy)->giveUnknown(VM_Total, tStep); + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + //Modify dispOne and dispTwo + //Seems to be wrong. Should be + dispOne.at(1) = dispOne.at(1) + projectionComponentNodeOne.at(1) * dispThree.at(1) + projectionComponentNodeOne.at(3) * dispThree.at(5) + projectionComponentNodeOne.at(2) * dispThree.at(6); + dispOne.at(2) = dispOne.at(2) + projectionComponentNodeOne.at(2) * dispThree.at(2) + projectionComponentNodeOne.at(3) * dispThree.at(4); + dispOne.at(3) = dispOne.at(3) + projectionComponentNodeOne.at(3) * dispThree.at(3); + + + dispTwo.at(1) = dispTwo.at(1) + projectionComponentNodeTwo.at(1) * dispThree.at(1) + projectionComponentNodeTwo.at(3) * dispThree.at(5) + projectionComponentNodeTwo.at(2) * dispThree.at(6); + dispTwo.at(2) = dispTwo.at(2) + projectionComponentNodeTwo.at(2) * dispThree.at(2) + projectionComponentNodeTwo.at(3) * dispThree.at(4); + dispTwo.at(3) = dispTwo.at(3) + projectionComponentNodeTwo.at(3) * dispThree.at(3); + + double x1, y1, z1, x2, y2, z2; + x1 = this->giveNode(1)->giveCoordinate(1) + projectionComponentNodeOne.at(1) * specimenDimension.at(1); + y1 = this->giveNode(1)->giveCoordinate(2) + projectionComponentNodeOne.at(2) * specimenDimension.at(2); + z1 = this->giveNode(1)->giveCoordinate(3) + projectionComponentNodeOne.at(3) * specimenDimension.at(3); + + x2 = this->giveNode(2)->giveCoordinate(1) + projectionComponentNodeTwo.at(1) * specimenDimension.at(1); + y2 = this->giveNode(2)->giveCoordinate(2) + projectionComponentNodeTwo.at(2) * specimenDimension.at(2); + z2 = this->giveNode(2)->giveCoordinate(3) + projectionComponentNodeTwo.at(3) * specimenDimension.at(3); + + p [ 0 ].x = ( FPNum ) x1 + defScale * dispOne.at(1); + p [ 0 ].y = ( FPNum ) y1 + defScale * dispOne.at(2); + p [ 0 ].z = ( FPNum ) z1 + defScale * dispOne.at(3); + + p [ 1 ].x = ( FPNum ) x2 + defScale * dispTwo.at(1); + p [ 1 ].y = ( FPNum ) y2 + defScale * dispTwo.at(2); + p [ 1 ].z = ( FPNum ) z2 + defScale * dispTwo.at(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EMAddGraphicsToModel(ESIModel(), go); +} + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/LatticeElements/lattice3dboundary.h b/src/sm/Elements/LatticeElements/lattice3dboundary.h new file mode 100644 index 000000000..34dac8cc6 --- /dev/null +++ b/src/sm/Elements/LatticeElements/lattice3dboundary.h @@ -0,0 +1,105 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef lattice3dboundary_h +#define lattice3dboundary_h + +#include "lattice3d.h" + +///@name Input fields for Lattice3d +//@{ +#define _IFT_Lattice3dBoundary_Name "lattice3dboundary" +#define _IFT_Lattice3dBoundary_location "location" +//@} + +namespace oofem { +/** + * This class implements a 3-dimensional lattice element for the boundaries of a periodic cell. + * The firs two nodes have each 6 degrees of freedom (3 translation and 3 rotations). + * At least one nodes is located at the image boundary or outside the specimen. + * These nodes are replaced with the corresponding image nodes and a control node is used to impose the macroscopic (average) strain. + * MACROSCOPIC INPUT: STRAIN TENSOR (3D, 6 COMPONENTS, VOIG NOTATION: Exx Eyy Ezz Gyz Gxz Gxy) + * + * @author: Peter Grassl, Ignatios Athanasiadis + */ + +class Lattice3dBoundary : public Lattice3d +{ +protected: + IntArray location; + +public: + Lattice3dBoundary(int n, Domain *); + virtual ~Lattice3dBoundary(); + + void recalculateCoordinates(int nodeNumber, FloatArray &coords) override; + const IntArray giveLocation() override { return this->location; } + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + int computeNumberOfDofs() override { return 18; } + + double computeVolumeAround(GaussPoint *) override; + + void giveDofManDofIDMask(int inode, IntArray &) const override; + + void giveInternalForcesVector(FloatArray &answer, TimeStep *, int useUpdatedGpRecord = 0) override; + void computeGeometryProperties() override; + + void giveGPCoordinates(FloatArray &coords) override { coords = this->globalCentroid; } + const char *giveInputRecordName() const override { return _IFT_Lattice3dBoundary_Name; } + const char *giveClassName() const override { return "Lattice3dBoundary"; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; + +#ifdef __OOFEG + void drawYourself(oofegGraphicContext &context, TimeStep *tStep) override; + void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + void drawRawCrossSections(oofegGraphicContext &, TimeStep *tStep); + void drawDeformedGeometry(oofegGraphicContext &, TimeStep *tStep, UnknownType) override; +#endif + +protected: + void giveSwitches(IntArray &answer, int location); + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + bool computeGtoLRotationMatrix(FloatMatrix &) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *stepN) override; +}; +} // end namespace oofem +#endif diff --git a/src/sm/Elements/LatticeElements/lattice3dboundarytruss.C b/src/sm/Elements/LatticeElements/lattice3dboundarytruss.C new file mode 100644 index 000000000..b361ac44c --- /dev/null +++ b/src/sm/Elements/LatticeElements/lattice3dboundarytruss.C @@ -0,0 +1,820 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "lattice3dboundarytruss.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "latticestructuralelement.h" +#include "classfactory.h" +#include "../sm/Materials/structuralmaterial.h" +#include "contextioerr.h" +#include "datastream.h" +#include "crosssection.h" +#include "dof.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { +REGISTER_Element(Lattice3dBoundaryTruss); + +Lattice3dBoundaryTruss :: Lattice3dBoundaryTruss(int n, Domain *aDomain) : Lattice3dBoundary(n, aDomain) +{ + numberOfDofMans = 3; + geometryFlag = 0; +} + +Lattice3dBoundaryTruss :: ~Lattice3dBoundaryTruss() +{} + + +void +Lattice3dBoundaryTruss :: computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) +// Returns the strain matrix of the receiver. +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + //Assemble Bmatrix (used to compute strains and rotations} + answer.resize(6, 12); + answer.zero(); + + //Normal displacement jump in x-direction + //First node + answer.at(1, 1) = -1.; + answer.at(1, 2) = 0.; + answer.at(1, 3) = 0.; + answer.at(1, 4) = 0.; + answer.at(1, 5) = -this->eccT; + answer.at(1, 6) = this->eccS; + //Second node + answer.at(1, 7) = 1.; + answer.at(1, 8) = 0.; + answer.at(1, 9) = 0.; + answer.at(1, 10) = 0.; + answer.at(1, 11) = this->eccT; + answer.at(1, 12) = -this->eccS; + + //Shear displacement jump in y-plane + //first node + answer.at(2, 1) = 0.; + answer.at(2, 2) = -1.; + answer.at(2, 3) = 0.; + answer.at(2, 4) = this->eccT; + answer.at(2, 5) = 0; + answer.at(2, 6) = -this->length / 2.; + //Second node + answer.at(2, 7) = 0.; + answer.at(2, 8) = 1.; + answer.at(2, 9) = 0.; + answer.at(2, 10) = -this->eccT; + answer.at(2, 11) = 0; + answer.at(2, 12) = -this->length / 2.; + + //Shear displacement jump in z-plane + //first node + answer.at(3, 1) = 0.; + answer.at(3, 2) = 0.; + answer.at(3, 3) = -1.; + answer.at(3, 4) = -this->eccS; + answer.at(3, 5) = this->length / 2.; + answer.at(3, 6) = 0.; + //Second node + answer.at(3, 7) = 0.; + answer.at(3, 8) = 0.; + answer.at(3, 9) = 1.; + answer.at(3, 10) = this->eccS; + answer.at(3, 11) = this->length / 2.; + answer.at(3, 12) = 0.; + + //Rotation around x-axis + //First node + answer.at(4, 1) = 0.; + answer.at(4, 2) = 0; + answer.at(4, 3) = 0.; + answer.at(4, 4) = -sqrt(Ip / this->area); + answer.at(4, 5) = 0.; + answer.at(4, 6) = 0.; + //Second node + answer.at(4, 7) = 0.; + answer.at(4, 8) = 0.; + answer.at(4, 9) = 0.; + answer.at(4, 10) = sqrt(Ip / this->area); + answer.at(4, 11) = 0.; + answer.at(4, 12) = 0.; + + //Rotation around y-axis + //First node + answer.at(5, 1) = 0.; + answer.at(5, 2) = 0.; + answer.at(5, 3) = 0.; + answer.at(5, 4) = 0.; + answer.at(5, 5) = -sqrt(I1 / this->area); + answer.at(5, 6) = 0.; + //Second node + answer.at(5, 7) = 0.; + answer.at(5, 8) = 0.; + answer.at(5, 9) = 0.; + answer.at(5, 10) = 0.; + answer.at(5, 11) = sqrt(I1 / this->area); + answer.at(5, 12) = 0.; + + //Rotation around z-axis + //First node + answer.at(6, 1) = 0.; + answer.at(6, 2) = 0.; + answer.at(6, 3) = 0.; + answer.at(6, 4) = 0.; + answer.at(6, 5) = 0.; + answer.at(6, 6) = -sqrt(I2 / this->area); + //Second node + answer.at(6, 7) = 0.; + answer.at(6, 8) = 0.; + answer.at(6, 9) = 0.; + answer.at(6, 10) = 0.; + answer.at(6, 11) = 0.; + answer.at(6, 12) = sqrt(I2 / this->area); + + answer.times(1. / this->length); + + return; +} + +void +Lattice3dBoundaryTruss :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + // double dV; + FloatMatrix d, bi, bj, dbj, dij, bjt; + FloatMatrix t(12, 13), tt; + FloatMatrix answerTemp(12, 12), answerHelp, ttk(13, 12); + bool matStiffSymmFlag = this->giveCrossSection()->isCharacteristicMtrxSymmetric(rMode); + answerTemp.zero(); + answerHelp.zero(); + t.zero(); + + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + double volume = this->computeVolumeAround(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); + + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), bj); + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + for ( int i = 1; i <= 6; i++ ) { + d.at(i, i) *= volume; + } + + dbj.beProductOf(d, bj); + bjt.beTranspositionOf(bj); + answerTemp.beProductOf(bjt, dbj); + + answer.resize(computeNumberOfDofs(), computeNumberOfDofs() ); + answer.zero(); + + answerHelp.resize(computeNumberOfDofs(), computeNumberOfDofs() ); + answerHelp.zero(); + + for ( int m = 1; m <= 12; m++ ) { + for ( int k = 1; k <= 12; k++ ) { + answer.at(m, k) = answerTemp.at(m, k); + } + } + + if ( matStiffSymmFlag ) { + answer.symmetrized(); + } + + // Rotate to global system add the projections and rotate back to local system. + + FloatMatrix R; + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R); + } + + for ( int m = 1; m <= 12; m++ ) { + for ( int k = 1; k <= 12; k++ ) { + answerTemp.at(m, k) = answer.at(m, k); + } + } + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + for ( int k = 1; k <= 12; k++ ) { + t.at(k, k) = 1.; + } + t.at(1, 13) = projectionComponentNodeOne.at(1); + t.at(7, 13) = projectionComponentNodeTwo.at(1); + + tt.beTranspositionOf(t); + + ttk.beProductOf(tt, answerTemp); + answer.beProductOf(ttk, t); + + //Rotate back to local system + FloatMatrix Rtranspose; + Rtranspose.beTranspositionOf(R); + answer.rotatedWith(Rtranspose); + + return; +} + + +double +Lattice3dBoundaryTruss :: computeVolumeAround(GaussPoint *aGaussPoint) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + return this->area * this->length; +} + +void +Lattice3dBoundaryTruss :: recalculateCoordinates(int nodeNumber, FloatArray &coords) { + coords.resize(3); + coords.zero(); + Node *node; + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray projectionComponent(3); + projectionComponent.zero(); + + if ( nodeNumber == 1 ) { + node = this->giveNode(1); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponent, location.at(1) ); + } + } else if ( nodeNumber == 2 ) { + node = this->giveNode(2); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponent, location.at(2) ); + } + } else { + OOFEM_ERROR("wrong element used in the vtk module"); + } + + for ( int i = 0; i < 3; i++ ) { + coords.at(i + 1) = node->giveCoordinate(i + 1) + projectionComponent.at(i + 1) * specimenDimension.at(i + 1); + } + return; +} + +void +Lattice3dBoundaryTruss :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *stepN) +// Computes the vector containing the strains at the Gauss point gp of +// the receiver, at time step stepN. The nature of these strains depends +// on the element's type. +{ + FloatMatrix b; + FloatArray u; + + //Compute strain vector + //Get the 13 components of the displacement vector of this element + this->computeVectorOf(VM_Total, stepN, u); + this->computeBmatrixAt(gp, b); + + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + //Compute projection vector + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + FloatMatrix rotationMatrix; + if ( this->computeGtoLRotationMatrix(rotationMatrix) ) { + u.rotatedWith(rotationMatrix, 't'); + } + + //General expressions for the corrected displacements. Rotations at nodes are not influenced. Only translations + u.at(1) = u.at(1) + projectionComponentNodeOne.at(1) * u.at(13); + + u.at(7) = u.at(7) + projectionComponentNodeTwo.at(1) * u.at(13); + + if ( this->computeGtoLRotationMatrix(rotationMatrix) ) { + u.rotatedWith(rotationMatrix, 'n'); + } + //define a temp displacement vector + FloatArray uTemp(12); + + for ( int i = 1; i <= 12; i++ ) { + uTemp.at(i) = u.at(i); + } + + answer.beProductOf(b, uTemp); +} + +bool +Lattice3dBoundaryTruss :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + int i, j; + + answer.resize(13, 13); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( i = 1; i <= 3; i++ ) { + for ( j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + answer.at(i + 6, j + 6) = lcs.at(i, j); + answer.at(i + 9, j + 9) = lcs.at(i, j); + } + } + answer.at(13, 13) = 1.; + + return 1; +} + +int +Lattice3dBoundaryTruss :: giveLocalCoordinateSystem(FloatMatrix &answer) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer = this->localCoordinateSystem; + + return 1; +} + + + +void +Lattice3dBoundaryTruss :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 3 ) { + answer = { E_xx }; + } else { + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; + } +} + +void +Lattice3dBoundaryTruss :: initializeFrom(InputRecord &ir) +{ + Lattice3d :: initializeFrom(ir); + + this->location.resize(2); + IR_GIVE_FIELD(ir, location, _IFT_Lattice3dBoundaryTruss_location); // Macro +} + + + +void +Lattice3dBoundaryTruss :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + Material *mat = this->giveMaterial(); + + FloatMatrix b, bt, A, R, GNT; + FloatArray bs, TotalStressVector, u, strain; + double dV; + + this->computeVectorOf(VM_Total, tStep, u); + + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + answer.resize(13); + answer.zero(); + + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), b); + + bt.beTranspositionOf(b); + if ( useUpdatedGpRecord == 1 ) { + TotalStressVector = ( ( LatticeMaterialStatus * ) mat->giveStatus(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ) ) + ->giveLatticeStress(); + } else + if ( !this->isActivated(tStep) ) { + strain.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialMode() ) ); + strain.zero(); + } + this->computeStrainVector(strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + this->computeStressVector(TotalStressVector, strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + dV = this->computeVolumeAround(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ); + bs.beProductOf(bt, TotalStressVector); + bs.times(dV); + + for ( int m = 1; m <= 12; m++ ) { + answer.at(m) = bs.at(m); + } + + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R, 't'); + } + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + //Normal stresses + answer.at(13) = projectionComponentNodeOne.at(1) * answer.at(1) + projectionComponentNodeTwo.at(1) * answer.at(7); + + //Rotate to local system + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R, 'n'); + } + + return; +} + + +void +Lattice3dBoundaryTruss :: giveSwitches(IntArray &answer, int location) { + int counter = 1; + for ( int x = -1; x < 2; x++ ) { + for ( int y = -1; y < 2; y++ ) { + for ( int z = -1; z < 2; z++ ) { + if ( !( z == 0 && y == 0 && x == 0 ) ) { + if ( counter == location ) { + answer(0) = x; + answer(1) = y; + answer(2) = z; + } + counter++; + } + } + } + } + return; +} + + +void +Lattice3dBoundaryTruss :: computeGeometryProperties() +{ + Node *nodeA, *nodeB; + + FloatArray coordsA(3); + FloatArray coordsB(3); + + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + for ( int i = 0; i < 3; i++ ) { + coordsA.at(i + 1) = nodeA->giveCoordinate(i + 1) + projectionComponentNodeOne.at(i + 1) * specimenDimension.at(i + 1); + coordsB.at(i + 1) = nodeB->giveCoordinate(i + 1) + projectionComponentNodeTwo.at(i + 1) * specimenDimension.at(i + 1); + } + + //Calculate normal vector + FloatArray s(3), t(3); + this->midPoint.resize(3); + + //Calculate normal vector + this->normal.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) = coordsB.at(i + 1) - coordsA.at(i + 1); + } + + this->length = sqrt(pow(this->normal.at(1), 2.) + pow(this->normal.at(2), 2.) + pow(this->normal.at(3), 2.) ); + + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) /= length; + } + + // Compute midpoint + this->midPoint.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->midPoint.at(i + 1) = 0.5 * ( coordsB.at(i + 1) + coordsA.at(i + 1) ); + } + + computeCrossSectionProperties(); + + //Set geometry flag to 1 so that this is done only once + this->geometryFlag = 1; + + return; +} + + +void +Lattice3dBoundaryTruss :: saveContext(DataStream &stream, ContextMode mode) +{ + Lattice3d :: saveContext(stream, mode); + + contextIOResultType iores; + + if ( ( mode & CM_Definition ) ) { + if ( ( iores = location.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + } +} + + + +void +Lattice3dBoundaryTruss :: restoreContext(DataStream &stream, ContextMode mode) +{ + Lattice3d :: restoreContext(stream, mode); + + contextIOResultType iores; + + if ( mode & CM_Definition ) { + if ( ( iores = this->location.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + } +} + + + +#ifdef __OOFEG + +void +Lattice3dBoundaryTruss :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + this->drawRawCrossSections(gc, tStep); + } else if ( mode == OGC_deformedGeometry ) { + this->drawDeformedGeometry(gc, tStep, DisplacementVector); + } else if ( mode == OGC_elemSpecial ) { + this->drawSpecial(gc, tStep); + } else { + OOFEM_ERROR("drawYourself : unsupported mode"); + } +} + + + + +void Lattice3dBoundaryTruss :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + WCRec p [ 2 ]; /* points */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getActiveCrackColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + //Compute projection vector + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1) + projectionComponentNodeOne.at(1) * specimenDimension.at(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2) + projectionComponentNodeOne.at(2) * specimenDimension.at(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3) + projectionComponentNodeOne.at(3) * specimenDimension.at(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1) + projectionComponentNodeTwo.at(1) * specimenDimension.at(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2) + projectionComponentNodeTwo.at(2) * specimenDimension.at(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3) + projectionComponentNodeTwo.at(3) * specimenDimension.at(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + + +void +Lattice3dBoundaryTruss :: drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + // if (!go) { // create new one + //Create as many points as we have polygon vertices + numberOfPolygonVertices = this->polygonCoords.giveSize() / 3.; + WCRec p [ numberOfPolygonVertices ]; /* poin */ + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + // EASValsSetColor(gc.getNodeColor()); + EASValsSetLayer(OOFEG_RAW_CROSSSECTION_LAYER); + + for ( int i = 0; i < numberOfPolygonVertices; i++ ) { + p [ i ].x = ( FPNum ) polygonCoords(3 * i); + p [ i ].y = ( FPNum ) polygonCoords(3 * i + 1); + p [ i ].z = ( FPNum ) polygonCoords(3 * i + 2); + } + + + WCRec pTemp [ 2 ]; /* points */ + for ( int i = 0; i < numberOfPolygonVertices; i++ ) { + if ( i < numberOfPolygonVertices - 1 ) { + pTemp [ 0 ] = p [ i ]; + pTemp [ 1 ] = p [ i + 1 ]; + } else { + pTemp [ 0 ] = p [ i ]; + pTemp [ 1 ] = p [ 0 ]; + } + + go = CreateLine3D(pTemp); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); + } +} + + +void Lattice3dBoundaryTruss :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ + //That seems to be wrong. The strain field should be ordered exx, eyy, ezz, gyz, gzx, gyx + //Therefore, the x displacement should include 5th and 6th strain components. + GraphicObj *go; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + double defScale = gc.getDefScale(); + + WCRec p [ 2 ]; /* points */ + + EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + FloatArray dispOne(6); + dispOne.at(1) = this->giveNode(1)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispOne.at(2) = this->giveNode(1)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispOne.at(3) = this->giveNode(1)->giveDofWithID(D_w)->giveUnknown(VM_Total, tStep); + dispOne.at(4) = this->giveNode(1)->giveDofWithID(R_u)->giveUnknown(VM_Total, tStep); + dispOne.at(5) = this->giveNode(1)->giveDofWithID(R_v)->giveUnknown(VM_Total, tStep); + dispOne.at(6) = this->giveNode(1)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + FloatArray dispTwo(6); + dispTwo.at(1) = this->giveNode(2)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispTwo.at(2) = this->giveNode(2)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispTwo.at(3) = this->giveNode(2)->giveDofWithID(D_w)->giveUnknown(VM_Total, tStep); + dispTwo.at(4) = this->giveNode(2)->giveDofWithID(R_u)->giveUnknown(VM_Total, tStep); + dispTwo.at(5) = this->giveNode(2)->giveDofWithID(R_v)->giveUnknown(VM_Total, tStep); + dispTwo.at(6) = this->giveNode(2)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + FloatArray dispThree(1); + dispThree.at(1) = this->giveNode(3)->giveDofWithID(E_xx)->giveUnknown(VM_Total, tStep); + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + //Modify dispOne and dispTwo + dispOne.at(1) = dispOne.at(1) + projectionComponentNodeOne.at(1) * dispThree.at(1); + dispOne.at(2) = dispOne.at(2); + dispOne.at(3) = dispOne.at(3); + + + dispTwo.at(1) = dispTwo.at(1) + projectionComponentNodeTwo.at(1) * dispThree.at(1); + dispTwo.at(2) = dispTwo.at(2); + dispTwo.at(3) = dispTwo.at(3); + + double x1, y1, z1, x2, y2, z2; + x1 = this->giveNode(1)->giveCoordinate(1) + projectionComponentNodeOne.at(1) * specimenDimension.at(1); + y1 = this->giveNode(1)->giveCoordinate(2) + projectionComponentNodeOne.at(2) * specimenDimension.at(2); + z1 = this->giveNode(1)->giveCoordinate(3) + projectionComponentNodeOne.at(3) * specimenDimension.at(3); + + x2 = this->giveNode(2)->giveCoordinate(1) + projectionComponentNodeTwo.at(1) * specimenDimension.at(1); + y2 = this->giveNode(2)->giveCoordinate(2) + projectionComponentNodeTwo.at(2) * specimenDimension.at(2); + z2 = this->giveNode(2)->giveCoordinate(3) + projectionComponentNodeTwo.at(3) * specimenDimension.at(3); + + p [ 0 ].x = ( FPNum ) x1 + defScale * dispOne.at(1); + p [ 0 ].y = ( FPNum ) y1 + defScale * dispOne.at(2); + p [ 0 ].z = ( FPNum ) z1 + defScale * dispOne.at(3); + + p [ 1 ].x = ( FPNum ) x2 + defScale * dispTwo.at(1); + p [ 1 ].y = ( FPNum ) y2 + defScale * dispTwo.at(2); + p [ 1 ].z = ( FPNum ) z2 + defScale * dispTwo.at(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EMAddGraphicsToModel(ESIModel(), go); +} + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/LatticeElements/lattice3dboundarytruss.h b/src/sm/Elements/LatticeElements/lattice3dboundarytruss.h new file mode 100644 index 000000000..626d2e94d --- /dev/null +++ b/src/sm/Elements/LatticeElements/lattice3dboundarytruss.h @@ -0,0 +1,106 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef lattice3dboundarytruss_h +#define lattice3dboundarytruss_h + +#include "lattice3dboundary.h" + +///@name Input fields for Lattice3dBoundaryTruss +//@{ +#define _IFT_Lattice3dBoundaryTruss_Name "lattice3dboundarytruss" +#define _IFT_Lattice3dBoundaryTruss_location "location" +//@} + +namespace oofem { +/** + * This class implements a 3-dimensional lattice element for the boundaries of a periodic cell representing a truss. + * The first two nodes have each 6 degrees of freedom (3 translation and 3 rotations). + * At least one nodes is located at the image boundary or outside the specimen. + * These nodes are replaced with the corresponding image nodes and a control node is used to impose the macroscopic (average) strain. + * The third node has 1 degree of fredom. + * MACROSCOPIC INPUT: Axial strain (Exx) + * + * @author: Peter Grassl + */ + +class Lattice3dBoundaryTruss : public Lattice3dBoundary +{ +protected: + IntArray location; + +public: + Lattice3dBoundaryTruss(int n, Domain *); + virtual ~Lattice3dBoundaryTruss(); + + void recalculateCoordinates(int nodeNumber, FloatArray &coords) override; + const IntArray giveLocation() override { return this->location; } + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + int computeNumberOfDofs() override { return 13; } + + double computeVolumeAround(GaussPoint *) override; + + void giveDofManDofIDMask(int inode, IntArray &) const override; + + void giveInternalForcesVector(FloatArray &answer, TimeStep *, int useUpdatedGpRecord = 0) override; + void computeGeometryProperties() override; + + void giveGPCoordinates(FloatArray &coords) override { coords = this->globalCentroid; } + const char *giveInputRecordName() const override { return _IFT_Lattice3dBoundaryTruss_Name; } + const char *giveClassName() const override { return "Lattice3dBoundaryTruss"; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; + +#ifdef __OOFEG + void drawYourself(oofegGraphicContext &context, TimeStep *tStep) override; + void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + void drawRawCrossSections(oofegGraphicContext &, TimeStep *tStep); + void drawDeformedGeometry(oofegGraphicContext &, TimeStep *tStep, UnknownType) override; +#endif + +protected: + void giveSwitches(IntArray &answer, int location); + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + bool computeGtoLRotationMatrix(FloatMatrix &) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *stepN) override; +}; +} // end namespace oofem +#endif diff --git a/src/sm/Elements/LatticeElements/latticebeam3d.C b/src/sm/Elements/LatticeElements/latticebeam3d.C new file mode 100644 index 000000000..3f868cc40 --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticebeam3d.C @@ -0,0 +1,489 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "../sm/Elements/LatticeElements/latticebeam3d.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "../sm/Materials/LatticeMaterials/latticelinearelastic.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "../sm/Elements/LatticeElements/latticestructuralelement.h" +#include "contextioerr.h" +#include "datastream.h" +#include "classfactory.h" +#include "sm/CrossSections/latticecrosssection.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" + #include "../sm/Materials/structuralmaterial.h" +#endif + +namespace oofem { +REGISTER_Element(LatticeBeam3d); + +LatticeBeam3d :: LatticeBeam3d(int n, Domain *aDomain) : LatticeStructuralElement(n, aDomain) +{ + geometryFlag = 0; + numberOfDofMans = 2; + myPi = 3.14159; +} + +LatticeBeam3d :: ~LatticeBeam3d() +{} + + +void +LatticeBeam3d :: giveGPCoordinates(FloatArray &coords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + coords.resize(3); + coords = this->globalCentroid; + + return; +} + +double +LatticeBeam3d :: giveLength() +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + return this->length; +} + +void +LatticeBeam3d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->give3dStiffnessMatrix(rMode, gp, tStep); +} + + +void +LatticeBeam3d :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + FloatMatrix d, bi, bj, bjt, dbj, dij; + + GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + + answer.resize(12, 12); + answer.zero(); + + //Stiffness matrix of Bernoulli beam from McGuire + double a = pow(this->diameter / 2., 2.) * myPi; + double iz = pow(this->diameter / 2., 4.) * myPi / 4.; + double iy = iz; + double j = iz + iy; + double l = this->giveLength(); + + double nu = ( static_cast< LatticeLinearElastic * >( this->giveMaterial() ) )->give('n', gp); + double e = ( static_cast< LatticeLinearElastic * >( this->giveMaterial() ) )->give('E', gp); + + answer.at(1, 1) = a / l; + answer.at(1, 7) = -a / l; + + answer.at(2, 2) = 12. * iz / pow(l, 3.); + answer.at(2, 6) = 6. * iz / pow(l, 2.); + answer.at(2, 8) = -12. * iz / pow(l, 3.); + answer.at(2, 12) = 6. * iz / pow(l, 2.); + + answer.at(3, 3) = 12 * iy / pow(l, 3.); + answer.at(3, 5) = -6. * iy / pow(l, 2.); + answer.at(3, 9) = -12. * iy / pow(l, 3.); + answer.at(3, 11) = -6. * iy / pow(l, 2.); + + answer.at(4, 4) = j / ( 2. * ( 1. + nu ) * l ); + answer.at(4, 10) = -j / ( 2. * ( 1. + nu ) * l ); + + answer.at(5, 3) = answer.at(3, 5); + answer.at(5, 5) = 4 * iy / l; + answer.at(5, 9) = 6. * iy / pow(l, 2.); + answer.at(5, 11) = 2. * iy / l; + + answer.at(6, 2) = answer.at(2, 6); + answer.at(6, 6) = 4. * iz / l; + answer.at(6, 8) = -6. * iz / pow(l, 2.); + answer.at(6, 12) = 2. * iz / l; + + answer.at(7, 1) = answer.at(1, 7); + answer.at(7, 7) = a / l; + + answer.at(8, 2) = answer.at(2, 8); + answer.at(8, 6) = answer.at(6, 8); + answer.at(8, 8) = 12. * iz / pow(l, 3.); + answer.at(8, 12) = -6. * iz / pow(l, 2.); + + answer.at(9, 3) = answer.at(3, 9); + answer.at(9, 5) = answer.at(5, 9); + answer.at(9, 9) = 12 * iy / pow(l, 3.); + answer.at(9, 11) = 6 * iy / pow(l, 2.); + + answer.at(10, 4) = answer.at(4, 10.); + answer.at(10, 10) = j / ( 2 * ( 1 + nu ) * l ); + + answer.at(11, 3) = answer.at(3, 11); + answer.at(11, 5) = answer.at(5, 11); + answer.at(11, 9) = answer.at(9, 11); + answer.at(11, 11) = 4 * iy / l; + + answer.at(12, 2) = answer.at(2, 12); + answer.at(12, 6) = answer.at(6, 12); + answer.at(12, 8) = answer.at(8, 12); + answer.at(12, 12) = 4 * iz / l; + + answer.times(e); + + return; +} + +void LatticeBeam3d :: computeGaussPoints() +// Sets up the array of Gauss Points of the receiver. +{ + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ].reset(new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ]->SetUpPointsOnLine(1, _3dLattice); +} + + + +double LatticeBeam3d :: giveArea() { + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + return this->area; +} + + +bool +LatticeBeam3d :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + int i, j; + + answer.resize(12, 12); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( i = 1; i <= 3; i++ ) { + for ( j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + answer.at(i + 6, j + 6) = lcs.at(i, j); + answer.at(i + 9, j + 9) = lcs.at(i, j); + } + } + + return 1; +} + +int +LatticeBeam3d :: giveLocalCoordinateSystem(FloatMatrix &answer) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer = this->localCoordinateSystem; + + return 1; +} + + +double +LatticeBeam3d :: computeVolumeAround(GaussPoint *aGaussPoint) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + return this->area * this->length; +} + + +void +LatticeBeam3d :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = { + D_u, D_v, D_w, R_u, R_v, R_w + }; +} + +void +LatticeBeam3d :: initializeFrom(InputRecord &ir) +{ + LatticeStructuralElement :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, this->diameter, _IFT_LatticeBeam3d_diameter); +} + + +int +LatticeBeam3d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer.resize(3); + answer = this->globalCentroid; + + return 1; +} + + +void +LatticeBeam3d :: computeGeometryProperties() +{ + //coordinates of the two nodes + Node *nodeA, *nodeB; + FloatArray coordsA(3), coordsB(3); + + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + + for ( int i = 0; i < 3; i++ ) { + coordsA.at(i + 1) = nodeA->giveCoordinate(i + 1); + coordsB.at(i + 1) = nodeB->giveCoordinate(i + 1); + } + + //Construct an initial temporary local coordinate system + FloatArray s(3), t(3); + + //Calculate normal vector + this->normal.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) = coordsB.at(i + 1) - coordsA.at(i + 1); + } + + this->length = sqrt(pow(normal.at(1), 2.) + pow(normal.at(2), 2.) + pow(normal.at(3), 2.) ); + + // Compute midpoint + this->midPoint.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->midPoint.at(i + 1) = 0.5 * ( coordsB.at(i + 1) + coordsA.at(i + 1) ); + } + + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) /= length; + } + + this->globalCentroid = this->midPoint; + + computeCrossSectionProperties(); + + this->geometryFlag = 1; + + return; +} + +void +LatticeBeam3d :: computeCrossSectionProperties() { + //Construct two perpendicular axis so that n is normal to the plane which they create + //Check, if one of the components of the normal-direction is zero + FloatArray s(3), t(3); + if ( this->normal.at(1) == 0 ) { + s.at(1) = 0.; + s.at(2) = this->normal.at(3); + s.at(3) = -this->normal.at(2); + } else if ( this->normal.at(2) == 0 ) { + s.at(1) = this->normal.at(3); + s.at(2) = 0.; + s.at(3) = -this->normal.at(1); + } else { + s.at(1) = this->normal.at(2); + s.at(2) = -this->normal.at(1); + s.at(3) = 0.; + } + + s.normalize(); + + t.beVectorProductOf(this->normal, s); + t.normalize(); + + this->localCoordinateSystem.resize(3, 3); + this->localCoordinateSystem.zero(); + + //Set up rotation matrix + for ( int i = 1; i <= 3; i++ ) { + this->localCoordinateSystem.at(1, i) = this->normal.at(i); + this->localCoordinateSystem.at(2, i) = s.at(i); + this->localCoordinateSystem.at(3, i) = t.at(i); + } +} + +void +LatticeBeam3d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->giveLatticeStress3d(strain, gp, tStep); +} + + +void +LatticeBeam3d :: giveInternalForcesVector(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) +{ + FloatArray u; + FloatMatrix stiffness; + + FloatArray strain(6), stress(6); + + GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + + // This function can be quite costly to do inside the loops when one has many slave dofs. + this->computeVectorOf(VM_Total, tStep, u); + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + // printf("Check what u is.\n"); + // u.printYourself(); + + this->computeStiffnessMatrix(stiffness, ElasticStiffness, tStep); + + // zero answer will resize accordingly when adding first contribution + answer.clear(); + answer.beProductOf(stiffness, u); + // printf("answer.at(1) = %e, answer.at(7) = %e\n", answer.at(1), answer.at(7)); + + double area = pow(this->diameter / 2., 2.) * myPi; + //Apply yield limit to axial component + strain.zero(); + strain.at(1) = ( u.at(7) - u.at(1) ) / this->giveLength(); + this->computeStressVector(stress, strain, gp, tStep); + answer.at(1) = -stress.at(1) * area; + answer.at(7) = -answer.at(1); + // printf("answerNew.at(1) = %e, answerNew.at(7) = %e\n", answer.at(1), answer.at(7)); + + // if inactive update state, but no contribution to global system + if ( !this->isActivated(tStep) ) { + answer.zero(); + return; + } + return; +} + +#ifdef __OOFEG + +void +LatticeBeam3d :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + } else if ( mode == OGC_deformedGeometry ) { + this->drawDeformedGeometry(gc, tStep, DisplacementVector); + } else if ( mode == OGC_eigenVectorGeometry ) { + this->drawDeformedGeometry(gc, tStep, EigenVector); + } else if ( mode == OGC_scalarPlot ) { + this->drawScalar(gc, tStep); + } else if ( mode == OGC_elemSpecial ) { + this->drawSpecial(gc, tStep); + } else { + OOFEM_ERROR("unsupported mode"); + } +} + + + +void LatticeBeam3d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + WCRec p [ 2 ]; /* points */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getElementColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + + +void LatticeBeam3d :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ + GraphicObj *go; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + double defScale = gc.getDefScale(); + + WCRec p [ 2 ]; /* points */ + + EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(3, tStep, defScale); + + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(3, tStep, defScale); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EMAddGraphicsToModel(ESIModel(), go); +} + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/LatticeElements/latticebeam3d.h b/src/sm/Elements/LatticeElements/latticebeam3d.h new file mode 100644 index 000000000..bd3ccc078 --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticebeam3d.h @@ -0,0 +1,120 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticebeam3d_h +#define latticebeam3d_h + +#include "latticestructuralelement.h" + +///@name Input fields for Lattice3d +//@{ +#define _IFT_LatticeBeam3d_Name "latticebeam3d" +#define _IFT_LatticeBeam3d_diameter "diameter" +//@} + +namespace oofem { +/** + * This class implements a 3-dimensional elastic bernoulli beam element in the lattice framework + */ + +class LatticeBeam3d : public LatticeStructuralElement +{ +protected: + double kappa, length, diameter; + double I1, I2, Ip; + FloatMatrix localCoordinateSystem; + double area; + FloatArray midPoint, globalCentroid, normal; + int geometryFlag; + double myPi; + +public: + LatticeBeam3d(int n, Domain *); + virtual ~LatticeBeam3d(); + + + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override {}; + + virtual int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + virtual double giveLength() override; + + virtual double giveArea() override; + + virtual int computeNumberOfDofs() override { return 12; } + + virtual void giveDofManDofIDMask(int inode, IntArray &) const override; + + virtual double computeVolumeAround(GaussPoint *) override; + + virtual void giveGPCoordinates(FloatArray &coords); + + virtual void computeGeometryProperties(); + + virtual void computeCrossSectionProperties(); + + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + + const char *giveInputRecordName() const override { return _IFT_LatticeBeam3d_Name; } + const char *giveClassName() const override { return "LatticeBeam3d"; } + void initializeFrom(InputRecord &ir) override; + + virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + + virtual Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + +#ifdef __OOFEG + void drawYourself(oofegGraphicContext &context, TimeStep *tStep) override; + virtual void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + virtual void drawDeformedGeometry(oofegGraphicContext &, TimeStep *tStep, UnknownType) override; +#endif + + +protected: + virtual bool computeGtoLRotationMatrix(FloatMatrix &) override; + virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + + /** + * This computes the geometrical properties of the element. It is called only once. + */ + void computePropertiesOfCrossSection(); + + virtual void computeGaussPoints() override; + virtual integrationDomain giveIntegrationDomain() { return _Line; } +}; +} // end namespace oofem +#endif diff --git a/src/sm/Elements/LatticeElements/latticebeam3dboundary.C b/src/sm/Elements/LatticeElements/latticebeam3dboundary.C new file mode 100644 index 000000000..fc880802d --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticebeam3dboundary.C @@ -0,0 +1,620 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "../sm/Elements/LatticeElements/latticebeam3dboundary.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "../sm/Materials/LatticeMaterials/latticelinearelastic.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "../sm/Elements/LatticeElements/latticestructuralelement.h" +#include "classfactory.h" +#include "../sm/Materials/structuralmaterial.h" +#include "contextioerr.h" +#include "datastream.h" +#include "sm/CrossSections/latticecrosssection.h" +#include "latticebeam3d.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" + #include "dof.h" + +#endif + +namespace oofem { +REGISTER_Element(LatticeBeam3dBoundary); + +LatticeBeam3dBoundary :: LatticeBeam3dBoundary(int n, Domain *aDomain) : LatticeBeam3d(n, aDomain) +{ + numberOfDofMans = 3; + geometryFlag = 0; +} + +LatticeBeam3dBoundary :: ~LatticeBeam3dBoundary() +{} + + +void +LatticeBeam3dBoundary :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + // double dV; + FloatMatrix d, bi, bj, dbj, dij, bjt; + FloatMatrix t(12, 18), tt; + FloatMatrix answerTemp(12, 12), ttk(18, 12); + bool matStiffSymmFlag = this->giveCrossSection()->isCharacteristicMtrxSymmetric(rMode); + answerTemp.zero(); + t.zero(); + + //Call the parent and compute stiffness + LatticeBeam3d :: computeStiffnessMatrix(answerTemp, rMode, tStep); + + answer.resize(computeNumberOfDofs(), computeNumberOfDofs() ); + answer.zero(); + + for ( int m = 1; m <= 12; m++ ) { + for ( int k = 1; k <= 12; k++ ) { + answer.at(m, k) = answerTemp.at(m, k); + } + } + + if ( matStiffSymmFlag ) { + answer.symmetrized(); + } + + // Rotate to global system add the projections and rotate back to local system. + + FloatMatrix R; + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R); + } + + for ( int m = 1; m <= 12; m++ ) { + for ( int k = 1; k <= 12; k++ ) { + answerTemp.at(m, k) = answer.at(m, k); + } + } + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + for ( int k = 1; k <= 12; k++ ) { + t.at(k, k) = 1.; + } + t.at(1, 13) = projectionComponentNodeOne.at(1); + t.at(2, 14) = projectionComponentNodeOne.at(2); + t.at(3, 15) = projectionComponentNodeOne.at(3); + + + t.at(2, 16) = projectionComponentNodeOne.at(3); + t.at(1, 17) = projectionComponentNodeOne.at(3); + t.at(1, 18) = projectionComponentNodeOne.at(2); + + + t.at(7, 13) = projectionComponentNodeTwo.at(1); + t.at(8, 14) = projectionComponentNodeTwo.at(2); + t.at(9, 15) = projectionComponentNodeTwo.at(3); + + t.at(8, 16) = projectionComponentNodeTwo.at(3); + t.at(7, 17) = projectionComponentNodeTwo.at(3); + t.at(7, 18) = projectionComponentNodeTwo.at(2); + + + tt.beTranspositionOf(t); + + ttk.beProductOf(tt, answerTemp); + answer.beProductOf(ttk, t); + + //Rotate back to local system + FloatMatrix Rtranspose; + Rtranspose.beTranspositionOf(R); + answer.rotatedWith(Rtranspose); + + return; +} + + + +double +LatticeBeam3dBoundary :: computeVolumeAround(GaussPoint *aGaussPoint) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + return this->area * this->length; +} + +void +LatticeBeam3dBoundary :: giveVTKCoordinates(int nodeNumber, FloatArray &coords) { + coords.resize(3); + coords.zero(); + Node *node; + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray projectionComponent(3); + projectionComponent.zero(); + + if ( nodeNumber == 1 ) { + node = this->giveNode(1); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponent, location.at(1) ); + } + } else if ( nodeNumber == 2 ) { + node = this->giveNode(2); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponent, location.at(2) ); + } + } else { + OOFEM_ERROR("wrong element used in the vtk module"); + } + + for ( int i = 0; i < 3; i++ ) { + coords.at(i + 1) = node->giveCoordinate(i + 1) + projectionComponent.at(i + 1) * specimenDimension.at(i + 1); + } + return; +} + +bool +LatticeBeam3dBoundary :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + int i, j; + + answer.resize(18, 18); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( i = 1; i <= 3; i++ ) { + for ( j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + answer.at(i + 6, j + 6) = lcs.at(i, j); + answer.at(i + 9, j + 9) = lcs.at(i, j); + } + } + answer.at(13, 13) = 1.; + answer.at(14, 14) = 1.; + answer.at(15, 15) = 1.; + answer.at(16, 16) = 1.; + answer.at(17, 17) = 1.; + answer.at(18, 18) = 1.; + + return 1; +} + +int +LatticeBeam3dBoundary :: giveLocalCoordinateSystem(FloatMatrix &answer) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer = this->localCoordinateSystem; + + return 1; +} + + + +void +LatticeBeam3dBoundary :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = { + D_u, D_v, D_w, R_u, R_v, R_w + }; +} + +void +LatticeBeam3dBoundary :: initializeFrom(InputRecord &ir) +{ + LatticeBeam3d :: initializeFrom(ir); + + location.resize(2); + IR_GIVE_FIELD(ir, location, _IFT_LatticeBeam3dBoundary_location); +} + + + +void +LatticeBeam3dBoundary :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + FloatMatrix stiffness; + FloatArray u; + + this->computeVectorOf(VM_Total, tStep, u); + + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + // //Compute projection vector + // IntArray projectionComponentNodeOne(3); + // projectionComponentNodeOne.zero(); + // if ( location.at(1) != 0 ) { + // giveSwitches( projectionComponentNodeOne, location.at(1) ); + // } + + // IntArray projectionComponentNodeTwo(3); + // projectionComponentNodeTwo.zero(); + + // if ( location.at(2) != 0 ) { + // giveSwitches( projectionComponentNodeTwo, location.at(2) ); + // } + + // //Rotate displacements into global coordinate system + // FloatMatrix rotationMatrix; + // if ( this->computeGtoLRotationMatrix(rotationMatrix) ) { + // u.rotatedWith(rotationMatrix, 't'); + // } + + // //General expressions for the corrected displacements. Rotations at nodes are not influenced. Only translations + // u.at(1) = u.at(1) + projectionComponentNodeOne.at(1) * u.at(13) + projectionComponentNodeOne.at(2) * u.at(18) + projectionComponentNodeOne.at(3) * u.at(17); + // u.at(2) = u.at(2) + projectionComponentNodeOne.at(2) * u.at(14) + projectionComponentNodeOne.at(3) * u.at(16); + // u.at(3) = u.at(3) + projectionComponentNodeOne.at(3) * u.at(15); + + // u.at(7) = u.at(7) + projectionComponentNodeTwo.at(1) * u.at(13) + projectionComponentNodeTwo.at(2) * u.at(18) + projectionComponentNodeTwo.at(3) * u.at(17); + // u.at(8) = u.at(8) + projectionComponentNodeTwo.at(2) * u.at(14) + projectionComponentNodeTwo.at(3) * u.at(16); + // u.at(9) = u.at(9) + projectionComponentNodeTwo.at(3) * u.at(15); + + + // if ( this->computeGtoLRotationMatrix(rotationMatrix) ) { + // u.rotatedWith(rotationMatrix, 'n'); + // } + + this->computeStiffnessMatrix(stiffness, ElasticStiffness, tStep); + + // zero answer will resize accordingly when adding first contribution + answer.clear(); + answer.beProductOf(stiffness, u); + + // if inactive update state, but no contribution to global system + if ( !this->isActivated(tStep) ) { + answer.zero(); + return; + } + return; +} + + +void +LatticeBeam3dBoundary :: giveSwitches(IntArray &answer, int location) { + int counter = 1; + for ( int x = -1; x < 2; x++ ) { + for ( int y = -1; y < 2; y++ ) { + for ( int z = -1; z < 2; z++ ) { + if ( !( z == 0 && y == 0 && x == 0 ) ) { + if ( counter == location ) { + answer(0) = x; + answer(1) = y; + answer(2) = z; + } + counter++; + } + } + } + } + return; +} + + +void +LatticeBeam3dBoundary :: computeGeometryProperties() +{ + Node *nodeA, *nodeB; + + FloatArray coordsA(3); + FloatArray coordsB(3); + + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + for ( int i = 0; i < 3; i++ ) { + coordsA.at(i + 1) = nodeA->giveCoordinate(i + 1) + projectionComponentNodeOne.at(i + 1) * specimenDimension.at(i + 1); + coordsB.at(i + 1) = nodeB->giveCoordinate(i + 1) + projectionComponentNodeTwo.at(i + 1) * specimenDimension.at(i + 1); + } + + //Calculate normal vector + FloatArray s(3), t(3); + this->midPoint.resize(3); + + //Calculate normal vector + this->normal.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) = coordsB.at(i + 1) - coordsA.at(i + 1); + } + + this->length = sqrt(pow(this->normal.at(1), 2.) + pow(this->normal.at(2), 2.) + pow(this->normal.at(3), 2.) ); + + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) /= length; + } + + // Compute midpoint + this->midPoint.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->midPoint.at(i + 1) = 0.5 * ( coordsB.at(i + 1) + coordsA.at(i + 1) ); + } + + this->globalCentroid = this->midPoint; + + computeCrossSectionProperties(); + + //Set geometry flag to 1 so that this is done only once + this->geometryFlag = 1; + + return; +} + + +void +LatticeBeam3dBoundary :: saveContext(DataStream &stream, ContextMode mode) +{ + LatticeBeam3d :: saveContext(stream, mode); + + contextIOResultType iores; + + if ( ( mode & CM_Definition ) ) { + if ( ( iores = location.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + } +} + +void +LatticeBeam3dBoundary :: restoreContext(DataStream &stream, ContextMode mode) +{ + LatticeBeam3d :: restoreContext(stream, mode); + + contextIOResultType iores; + + if ( mode & CM_Definition ) { + if ( ( iores = this->location.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + } +} + + +int +LatticeBeam3dBoundary :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer.resize(3); + answer = this->globalCentroid; + + return 1; +} + + + +#ifdef __OOFEG + +void +LatticeBeam3dBoundary :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + } else if ( mode == OGC_deformedGeometry ) { + this->drawDeformedGeometry(gc, tStep, DisplacementVector); + } else if ( mode == OGC_elemSpecial ) { + this->drawSpecial(gc, tStep); + } else { + OOFEM_ERROR("drawYourself : unsupported mode"); + } +} + + +void LatticeBeam3dBoundary :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + WCRec p [ 2 ]; /* points */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getActiveCrackColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + //Compute projection vector + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1) + projectionComponentNodeOne.at(1) * specimenDimension.at(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2) + projectionComponentNodeOne.at(2) * specimenDimension.at(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3) + projectionComponentNodeOne.at(3) * specimenDimension.at(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1) + projectionComponentNodeTwo.at(1) * specimenDimension.at(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2) + projectionComponentNodeTwo.at(2) * specimenDimension.at(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3) + projectionComponentNodeTwo.at(3) * specimenDimension.at(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + + +void LatticeBeam3dBoundary :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ + GraphicObj *go; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + double defScale = gc.getDefScale(); + + WCRec p [ 2 ]; /* points */ + + EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + FloatArray dispOne(6); + dispOne.at(1) = this->giveNode(1)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispOne.at(2) = this->giveNode(1)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispOne.at(3) = this->giveNode(1)->giveDofWithID(D_w)->giveUnknown(VM_Total, tStep); + dispOne.at(4) = this->giveNode(1)->giveDofWithID(R_u)->giveUnknown(VM_Total, tStep); + dispOne.at(5) = this->giveNode(1)->giveDofWithID(R_v)->giveUnknown(VM_Total, tStep); + dispOne.at(6) = this->giveNode(1)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + FloatArray dispTwo(6); + dispTwo.at(1) = this->giveNode(2)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispTwo.at(2) = this->giveNode(2)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispTwo.at(3) = this->giveNode(2)->giveDofWithID(D_w)->giveUnknown(VM_Total, tStep); + dispTwo.at(4) = this->giveNode(2)->giveDofWithID(R_u)->giveUnknown(VM_Total, tStep); + dispTwo.at(5) = this->giveNode(2)->giveDofWithID(R_v)->giveUnknown(VM_Total, tStep); + dispTwo.at(6) = this->giveNode(2)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + FloatArray dispThree(6); + dispThree.at(1) = this->giveNode(3)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispThree.at(2) = this->giveNode(3)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispThree.at(3) = this->giveNode(3)->giveDofWithID(D_w)->giveUnknown(VM_Total, tStep); + dispThree.at(4) = this->giveNode(3)->giveDofWithID(R_u)->giveUnknown(VM_Total, tStep); + dispThree.at(5) = this->giveNode(3)->giveDofWithID(R_v)->giveUnknown(VM_Total, tStep); + dispThree.at(6) = this->giveNode(3)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + + //Modify dispOne and dispTwo + dispOne.at(1) = dispOne.at(1) + projectionComponentNodeOne.at(1) * dispThree.at(1) + projectionComponentNodeOne.at(2) * dispThree.at(4) + projectionComponentNodeOne.at(3) * dispThree.at(5); + dispOne.at(2) = dispOne.at(2) + projectionComponentNodeOne.at(2) * dispThree.at(2) + projectionComponentNodeOne.at(3) * dispThree.at(6); + dispOne.at(3) = dispOne.at(3) + projectionComponentNodeOne.at(3) * dispThree.at(3); + + + dispTwo.at(1) = dispTwo.at(1) + projectionComponentNodeTwo.at(1) * dispThree.at(1) + projectionComponentNodeTwo.at(2) * dispThree.at(4) + projectionComponentNodeTwo.at(3) * dispThree.at(5); + dispTwo.at(2) = dispTwo.at(2) + projectionComponentNodeTwo.at(2) * dispThree.at(2) + projectionComponentNodeTwo.at(3) * dispThree.at(6); + dispTwo.at(3) = dispTwo.at(3) + projectionComponentNodeTwo.at(3) * dispThree.at(3); + + double x1, y1, z1, x2, y2, z2; + x1 = this->giveNode(1)->giveCoordinate(1) + projectionComponentNodeOne.at(1) * specimenDimension.at(1); + y1 = this->giveNode(1)->giveCoordinate(2) + projectionComponentNodeOne.at(2) * specimenDimension.at(2); + z1 = this->giveNode(1)->giveCoordinate(3) + projectionComponentNodeOne.at(3) * specimenDimension.at(3); + + x2 = this->giveNode(2)->giveCoordinate(1) + projectionComponentNodeTwo.at(1) * specimenDimension.at(1); + y2 = this->giveNode(2)->giveCoordinate(2) + projectionComponentNodeTwo.at(2) * specimenDimension.at(2); + z2 = this->giveNode(2)->giveCoordinate(3) + projectionComponentNodeTwo.at(3) * specimenDimension.at(3); + + p [ 0 ].x = ( FPNum ) x1 + defScale * dispOne.at(1); + p [ 0 ].y = ( FPNum ) y1 + defScale * dispOne.at(2); + p [ 0 ].z = ( FPNum ) z1 + defScale * dispOne.at(3); + + p [ 1 ].x = ( FPNum ) x2 + defScale * dispTwo.at(1); + p [ 1 ].y = ( FPNum ) y2 + defScale * dispTwo.at(2); + p [ 1 ].z = ( FPNum ) z2 + defScale * dispTwo.at(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EMAddGraphicsToModel(ESIModel(), go); +} + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/LatticeElements/latticebeam3dboundary.h b/src/sm/Elements/LatticeElements/latticebeam3dboundary.h new file mode 100644 index 000000000..a116c22af --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticebeam3dboundary.h @@ -0,0 +1,99 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticebeam3dboundary_h +#define latticebeam3dboundary_h + +#include "latticebeam3d.h" + +///@name Input fields for Lattice2d +//@{ +#define _IFT_LatticeBeam3dBoundary_Name "latticebeam3dboundary" +#define _IFT_LatticeBeam3dBoundary_location "location" +//@} + +namespace oofem { +/** + * This class implements a 3-dimensional lattice element for the boundaries of a periodic cell. + */ + +class LatticeBeam3dBoundary : public LatticeBeam3d +{ +protected: + IntArray location; + +public: + LatticeBeam3dBoundary(int n, Domain *); + virtual ~LatticeBeam3dBoundary(); + + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + int computeNumberOfDofs() override { return 18; } + + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + double computeVolumeAround(GaussPoint *) override; + + void giveDofManDofIDMask(int inode, IntArray &) const override; + + virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *, int useUpdatedGpRecord = 0) override; + virtual void computeGeometryProperties() override; + + virtual const char *giveInputRecordName() const override { return _IFT_LatticeBeam3dBoundary_Name; } + virtual const char *giveClassName() const override { return "LatticeBeam3dBoundary"; } + void initializeFrom(InputRecord &ir) override; + virtual Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; + + void giveVTKCoordinates(int nodeNumber, FloatArray &coords); + +#ifdef __OOFEG + virtual void drawYourself(oofegGraphicContext &context, TimeStep *tStep) override; + virtual void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + virtual void drawDeformedGeometry(oofegGraphicContext &, TimeStep *tStep, UnknownType) override; +#endif + +protected: + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override {}; + bool computeGtoLRotationMatrix(FloatMatrix &) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + + void giveSwitches(IntArray &answer, int location); +}; +} // end namespace oofem +#endif diff --git a/src/sm/Elements/LatticeElements/latticeframe3d.C b/src/sm/Elements/LatticeElements/latticeframe3d.C new file mode 100644 index 000000000..542a7eaa0 --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticeframe3d.C @@ -0,0 +1,482 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "latticeframe3d.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "intarray.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "mathfem.h" +#include "latticestructuralelement.h" +#include "contextioerr.h" +#include "datastream.h" +#include "classfactory.h" +#include "sm/CrossSections/latticecrosssection.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" + #include "../sm/Materials/structuralmaterial.h" +#endif + +namespace oofem { +REGISTER_Element(LatticeFrame3d); + +LatticeFrame3d::LatticeFrame3d(int n, Domain *aDomain) : LatticeStructuralElement(n, aDomain) +{ + numberOfDofMans = 2; +} + +LatticeFrame3d::~LatticeFrame3d() +{} + + +void +LatticeFrame3d::computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) +// Returns the strain matrix of the receiver. +{ + //Assemble Bmatrix (used to compute strains and rotations) + answer.resize(6, 12); + answer.zero(); + + this->length = computeLength(); + + //Normal displacement jump in x-direction + //First node + answer.at(1, 1) = -1.; + answer.at(1, 2) = 0.; + answer.at(1, 3) = 0.; + answer.at(1, 4) = 0.; + answer.at(1, 5) = 0.; + answer.at(1, 6) = 0.; + //Second node + answer.at(1, 7) = 1.; + answer.at(1, 8) = 0.; + answer.at(1, 9) = 0.; + answer.at(1, 10) = 0.; + answer.at(1, 11) = 0.; + answer.at(1, 12) = 0.; + + //Shear displacement jump in y-plane + //first node + answer.at(2, 1) = 0.; + answer.at(2, 2) = -1.; + answer.at(2, 3) = 0.; + answer.at(2, 4) = 0.; + answer.at(2, 5) = 0; + answer.at(2, 6) = -this->length*(1.-this->s)/2.; + //Second node + answer.at(2, 7) = 0.; + answer.at(2, 8) = 1.; + answer.at(2, 9) = 0.; + answer.at(2, 10) = 0.; + answer.at(2, 11) = 0; + answer.at(2, 12) = -this->length*(1.+this->s)/2.; + + //Shear displacement jump in z-plane + //first node + answer.at(3, 1) = 0.; + answer.at(3, 2) = 0.; + answer.at(3, 3) = -1.; + answer.at(3, 4) = 0.; + answer.at(3, 5) = this->length*(1.-this->s)/2.; + answer.at(3, 6) = 0.; + //Second node + answer.at(3, 7) = 0.; + answer.at(3, 8) = 0.; + answer.at(3, 9) = 1.; + answer.at(3, 10) = 0.; + answer.at(3, 11) = this->length*(1.+this->s)/2.; + answer.at(3, 12) = 0.; + + //Rotation around x-axis + //First node + answer.at(4, 1) = 0.; + answer.at(4, 2) = 0; + answer.at(4, 3) = 0.; + answer.at(4, 4) = -1.; + answer.at(4, 5) = 0.; + answer.at(4, 6) = 0.; + //Second node + answer.at(4, 7) = 0.; + answer.at(4, 8) = 0.; + answer.at(4, 9) = 0.; + answer.at(4, 10) = 1.; + answer.at(4, 11) = 0.; + answer.at(4, 12) = 0.; + + //Rotation around y-axis + //First node + answer.at(5, 1) = 0.; + answer.at(5, 2) = 0.; + answer.at(5, 3) = 0.; + answer.at(5, 4) = 0.; + answer.at(5, 5) = -1.; + answer.at(5, 6) = 0.; + //Second node + answer.at(5, 7) = 0.; + answer.at(5, 8) = 0.; + answer.at(5, 9) = 0.; + answer.at(5, 10) = 0.; + answer.at(5, 11) = 1.; + answer.at(5, 12) = 0.; + + //Rotation around z-axis + //First node + answer.at(6, 1) = 0.; + answer.at(6, 2) = 0.; + answer.at(6, 3) = 0.; + answer.at(6, 4) = 0.; + answer.at(6, 5) = 0.; + answer.at(6, 6) = -1.; + //Second node + answer.at(6, 7) = 0.; + answer.at(6, 8) = 0.; + answer.at(6, 9) = 0.; + answer.at(6, 10) = 0.; + answer.at(6, 11) = 0.; + answer.at(6, 12) = 1.; + + return; +} + +void +LatticeFrame3d::giveGPCoordinates(FloatArray &coords) +{ + coords.resize(3); + coords = this->globalCentroid; + return; +} + +double +LatticeFrame3d::giveLength() +{ + return this->length; +} + + + +void +LatticeFrame3d::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->give3dFrameStiffnessMatrix(rMode, gp, tStep); +} + +void +LatticeFrame3d::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->giveFrameForces3d(strain, gp, tStep); +} + +int +LatticeFrame3d::computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ + double ksi, n1, n2; + + ksi = lcoords.at(1); + n1 = ( 1. - ksi ) * 0.5; + n2 = ( 1. + ksi ) * 0.5; + + answer.resize(3); + answer.at(1) = n1 * this->giveNode(1)->giveCoordinate(1) + n2 * this->giveNode(2)->giveCoordinate(1); + answer.at(2) = n1 * this->giveNode(1)->giveCoordinate(2) + n2 * this->giveNode(2)->giveCoordinate(2); + answer.at(3) = n1 * this->giveNode(1)->giveCoordinate(3) + n2 * this->giveNode(2)->giveCoordinate(3); + + return 1; +} + + +void +LatticeFrame3d::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + FloatMatrix d, bi, bj, bjt, dbj, dij; + + this->length = computeLength(); + + answer.resize(12, 12); + answer.zero(); + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), bj); + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + dbj.beProductOf(d, bj); + dbj.times(1. / length); + bjt.beTranspositionOf(bj); + answer.beProductOf(bjt, dbj); + //printf("answer/n"); + //answer.printYourself(); + return; +} + +void LatticeFrame3d::computeGaussPoints() +// Sets up the array of Gauss Points of the receiver. +{ + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ]->SetUpPointsOnLine(1, _3dLattice); +} + + + +double LatticeFrame3d::giveArea() { + FloatArray lc(1); + return this->giveCrossSection()->give(CS_Area, lc, this); +} + +double LatticeFrame3d::giveIy() { + FloatArray lc(1); + return this->giveCrossSection()->give(CS_InertiaMomentY, lc, this); +} + +double LatticeFrame3d::giveIz() { + FloatArray lc(1); + return this->giveCrossSection()->give(CS_InertiaMomentZ, lc, this); +} + +double LatticeFrame3d::giveIk() { + FloatArray lc(1); + return this->giveCrossSection()->give(CS_TorsionConstantX, lc, this); +} + +double LatticeFrame3d::giveShearAreaY() { + FloatArray lc(1); + return this->giveCrossSection()->give(CS_ShearAreaY, lc, this); +} + +double LatticeFrame3d::giveShearAreaZ() { + FloatArray lc(1); + return this->giveCrossSection()->give(CS_ShearAreaZ, lc, this); +} + + +void +LatticeFrame3d::giveInternalForcesVector(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) +{ + FloatMatrix b, bt; + FloatArray u, stress, strain; + + this->length = computeLength(); + + this->computeVectorOf(VM_Total, tStep, u); + + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + // zero answer will resize accordingly when adding first contribution + answer.clear(); + + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), b); + + bt.beTranspositionOf(b); + + if ( useUpdatedGpRecord == 1 ) { + LatticeMaterialStatus *lmatStat = dynamic_cast< LatticeMaterialStatus * >( integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialStatus() ); + stress = lmatStat->giveLatticeStress(); + } else { + if ( !this->isActivated(tStep) ) { + strain.zero(); + } + strain.beProductOf(b, u); + strain.times(1./this->length); + this->computeStressVector(stress, strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + } + answer.beProductOf(bt, stress); + if ( !this->isActivated(tStep) ) { + answer.zero(); + return; + } +} + +bool +LatticeFrame3d::computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + answer.resize(12, 12); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + answer.at(i + 6, j + 6) = lcs.at(i, j); + answer.at(i + 9, j + 9) = lcs.at(i, j); + } + } + + return 1; +} + + +int +LatticeFrame3d::giveLocalCoordinateSystem(FloatMatrix &answer) +{ + FloatArray lx, ly, lz, help(3); + Node *nodeA, *nodeB; + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + lx.beDifferenceOf(nodeB->giveCoordinates(), nodeA->giveCoordinates() ); + lx.normalize(); + + + if ( this->referenceNode ) { + Node *refNode = this->giveDomain()->giveNode(this->referenceNode); + help.beDifferenceOf(refNode->giveCoordinates(), nodeA->giveCoordinates() ); + + lz.beVectorProductOf(lx, help); + lz.normalize(); + } else if ( this->zaxis.giveSize() > 0 ) { + lz = this->zaxis; + lz.add(lz.dotProduct(lx), lx); + lz.normalize(); + } else { + FloatMatrix rot(3, 3); + double theta = referenceAngle * M_PI / 180.0; + + rot.at(1, 1) = cos(theta) + pow(lx.at(1), 2) * ( 1 - cos(theta) ); + rot.at(1, 2) = lx.at(1) * lx.at(2) * ( 1 - cos(theta) ) - lx.at(3) * sin(theta); + rot.at(1, 3) = lx.at(1) * lx.at(3) * ( 1 - cos(theta) ) + lx.at(2) * sin(theta); + + rot.at(2, 1) = lx.at(2) * lx.at(1) * ( 1 - cos(theta) ) + lx.at(3) * sin(theta); + rot.at(2, 2) = cos(theta) + pow(lx.at(2), 2) * ( 1 - cos(theta) ); + rot.at(2, 3) = lx.at(2) * lx.at(3) * ( 1 - cos(theta) ) - lx.at(1) * sin(theta); + + rot.at(3, 1) = lx.at(3) * lx.at(1) * ( 1 - cos(theta) ) - lx.at(2) * sin(theta); + rot.at(3, 2) = lx.at(3) * lx.at(2) * ( 1 - cos(theta) ) + lx.at(1) * sin(theta); + rot.at(3, 3) = cos(theta) + pow(lx.at(3), 2) * ( 1 - cos(theta) ); + + help.at(3) = 1.0; // up-vector + // here is ly is used as a temp var + if ( fabs(lx.dotProduct(help) ) > 0.999 ) { // Check if it is vertical + ly = { + 0., 1., 0. + }; + } else { + ly.beVectorProductOf(lx, help); + } + lz.beProductOf(rot, ly); + lz.normalize(); + } + + ly.beVectorProductOf(lz, lx); + ly.normalize(); + + answer.resize(3, 3); + answer.zero(); + for ( int i = 1; i <= 3; i++ ) { + answer.at(1, i) = lx.at(i); + answer.at(2, i) = ly.at(i); + answer.at(3, i) = lz.at(i); + } + + return 1; +} + + +void +LatticeFrame3d::giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = { + D_u, D_v, D_w, R_u, R_v, R_w + }; +} + +void +LatticeFrame3d::initializeFrom(InputRecord &ir) +{ + LatticeStructuralElement::initializeFrom(ir); + + referenceNode = 0; + referenceAngle = 0; + this->zaxis.clear(); + if ( ir.hasField(_IFT_LatticeFrame3d_zaxis) ) { + IR_GIVE_FIELD(ir, this->zaxis, _IFT_LatticeFrame3d_zaxis); + } else if ( ir.hasField(_IFT_LatticeFrame3d_refnode) ) { + IR_GIVE_FIELD(ir, referenceNode, _IFT_LatticeFrame3d_refnode); + if ( referenceNode == 0 ) { + OOFEM_WARNING("wrong reference node specified. Using default orientation."); + } + } else if ( ir.hasField(_IFT_LatticeFrame3d_refangle) ) { + IR_GIVE_FIELD(ir, referenceAngle, _IFT_LatticeFrame3d_refangle); + } else { + throw ValueInputException(ir, _IFT_LatticeFrame3d_zaxis, "axis, reference node, or angle not set"); + } + + this->s = 0.; + IR_GIVE_OPTIONAL_FIELD(ir, s, _IFT_LatticeFrame3d_s); + +} + + +double +LatticeFrame3d::computeLength() +{ + double dx, dy, dz; + Node *nodeA, *nodeB; + + if ( length == 0. ) { + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); + dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); + dz = nodeB->giveCoordinate(3) - nodeA->giveCoordinate(3); + length = sqrt(dx * dx + dy * dy + dz * dz); + } + + return length; +} + +void +LatticeFrame3d::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +// Returns the lumped mass matrix of the receiver. This expression is +// valid in both local and global axes. +{ + GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + double density = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->give('d', gp); + double halfMass = density * computeVolumeAround(gp) / 2.; + answer.resize(12, 12); + answer.zero(); + answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = halfMass; + answer.at(7, 7) = answer.at(8, 8) = answer.at(9, 9) = halfMass; +} +} // end namespace oofem diff --git a/src/sm/Elements/LatticeElements/latticeframe3d.h b/src/sm/Elements/LatticeElements/latticeframe3d.h new file mode 100644 index 000000000..c22c8dda0 --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticeframe3d.h @@ -0,0 +1,125 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticeframe3d_h +#define latticeframe3d_h + +#include "latticestructuralelement.h" + +///@name Input fields for LatticeFrame3d +//@{ +#define _IFT_LatticeFrame3d_Name "latticeframe3d" +#define _IFT_LatticeFrame3d_refnode "refnode" +#define _IFT_LatticeFrame3d_refangle "refangle" +#define _IFT_LatticeFrame3d_zaxis "zaxis" +#define _IFT_LatticeFrame3d_s "s" +//@} + +namespace oofem { +/** + * This class implements a 3-dimensional frame element based on rigid body spring theory presented in Toi 1991 and Toi 1993. It belongs to the group of lattice models in OOFEM. + * Authors: Gumaa Abdelrhim and Peter Grassl + */ + +class LatticeFrame3d : public LatticeStructuralElement +{ +protected: + int referenceNode; + FloatArray zaxis; + double referenceAngle = 0; + double kappa; + double length = 0.; + double iy, iz, ik; + double area, shearareay, shearareaz; + double s; + FloatMatrix localCoordinateSystem; + + FloatArray midPoint, globalCentroid, normal; + +public: + LatticeFrame3d(int n, Domain *); + virtual ~LatticeFrame3d(); + + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + double computeLength() override; + + double giveLength() override; + + double giveArea() override; + + double giveIy() override; + + double giveIz() override; + + double giveIk() override; + + double giveShearAreaY() override; + + double giveShearAreaZ() override; + + int computeNumberOfDofs() override { return 12; } + + void giveDofManDofIDMask(int inode, IntArray &) const override; + + + virtual void giveGPCoordinates(FloatArray &coords); + + const char *giveInputRecordName() const override { return _IFT_LatticeFrame3d_Name; } + const char *giveClassName() const override { return "latticeframe3d"; } + void initializeFrom(InputRecord &ir) override; + + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override; + + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + + + +protected: + virtual void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + bool computeGtoLRotationMatrix(FloatMatrix &) override; + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override + { this->computeLumpedMassMatrix(answer, tStep); } + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeGaussPoints() override; + integrationDomain giveIntegrationDomain() const override { return _Line; } +}; +} // end namespace oofem +#endif diff --git a/src/sm/Elements/LatticeElements/latticeframe3dnl.C b/src/sm/Elements/LatticeElements/latticeframe3dnl.C new file mode 100755 index 000000000..63a5bf950 --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticeframe3dnl.C @@ -0,0 +1,619 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2023 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "latticeframe3dnl.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "intarray.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "mathfem.h" +#include "latticeframe3d.h" +#include "contextioerr.h" +#include "datastream.h" +#include "classfactory.h" +#include "sm/CrossSections/latticecrosssection.h" +#include "engngm.h" + +#ifdef __OOFEG +#include "oofeggraphiccontext.h" + #include "../sm/Materials/structuralmaterial.h" +#endif + +namespace oofem { + REGISTER_Element(LatticeFrame3dNL); + + LatticeFrame3dNL::LatticeFrame3dNL(int n, Domain *aDomain) : LatticeFrame3d(n, aDomain) + { + numberOfDofMans = 2; + } + + LatticeFrame3dNL::~LatticeFrame3dNL() + {} + void + LatticeFrame3dNL::computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) + //Returns the strain matrix of the receiver. + { + FloatArray u; + TimeStep *tStep = this->domain->giveEngngModel()->giveCurrentStep(); + this->computeVectorOf(VM_Total, tStep, u); + + this->length = computeLength(); + double l1 = this->length * ( 1. - this->s ) / 2; + double l2 = this->length * ( 1. + this->s ) / 2; + answer.resize(6, 12); + answer.zero(); +// double cx1=(cos(u.at(5))*cos(u.at(6)))*l1; +// double cy1=(cos(u.at(4))*sin(u.at(6))+sin(u.at(4))*sin(u.at(5))*cos(u.at(6)))*l1; +// double cz1=(sin(u.at(4))*sin(u.at(6))-cos(u.at(4))*sin(u.at(5))*cos(u.at(6)))*l1; +// +// +// double cx2=(cos(u.at(11))*cos(u.at(12)))*l2; +// double cy2=(cos(u.at(10))*sin(u.at(12))+sin(u.at(10))*sin(u.at(11))*cos(u.at(12)))*l2; +// double cz2=(sin(u.at(10))*sin(u.at(12))-cos(u.at(10))*sin(u.at(11))*cos(u.at(12)))*l2; + + double cx1=(cos(u.at(5))*cos(u.at(6)))*l1; + double cy1=(cos(u.at(5))*sin(u.at(6)))*l1; + double cz1=(-sin(u.at(5)))*l1; + + + double cx2=(cos(u.at(11))*cos(u.at(12)))*l2; + double cy2=(cos(u.at(11))*sin(u.at(12)))*l2; + double cz2=(-sin(u.at(11)))*l2; + + + //Normal displacement jump in x-direction + //First node + answer.at(1, 1) = -1.; + answer.at(1, 2) = 0.; + answer.at(1, 3) = 0.; + answer.at(1, 4) = 0.; + answer.at(1, 5) = -cz1; + answer.at(1, 6) = cy1; + //Second node + answer.at(1, 7) = 1.; + answer.at(1, 8) = 0.; + answer.at(1, 9) = 0.; + answer.at(1, 10) = 0.; + answer.at(1, 11) = -cz2; + answer.at(1, 12) = cy2; + + //Shear displacement jump in y-plane + //first node + answer.at(2, 1) = 0.; + answer.at(2, 2) = -1.; + answer.at(2, 3) = 0.; + answer.at(2, 4) = cz1; + answer.at(2, 5) = 0; + answer.at(2, 6) = -cx1; + //Second node + answer.at(2, 7) = 0.; + answer.at(2, 8) = 1.; + answer.at(2, 9) = 0.; + answer.at(2, 10) = cz2; + answer.at(2, 11) = 0; + answer.at(2, 12) = -cx2; + + //Shear displacement jump in z-plane + //first node + answer.at(3, 1) = 0.; + answer.at(3, 2) = 0.; + answer.at(3, 3) = -1.; + answer.at(3, 4) = -cy1; + answer.at(3, 5) = cx1; + answer.at(3, 6) = 0.; + //Second node + answer.at(3, 7) = 0.; + answer.at(3, 8) = 0.; + answer.at(3, 9) = 1.; + answer.at(3, 10) = -cy2; + answer.at(3, 11) = cx2; + answer.at(3, 12) = 0.; + + //Rotation around x-axis + //First node + answer.at(4, 1) = 0.; + answer.at(4, 2) = 0; + answer.at(4, 3) = 0.; + answer.at(4, 4) = -1.; + answer.at(4, 5) = 0.; + answer.at(4, 6) = 0.; + //Second node + answer.at(4, 7) = 0.; + answer.at(4, 8) = 0.; + answer.at(4, 9) = 0.; + answer.at(4, 10) = 1.; + answer.at(4, 11) = 0.; + answer.at(4, 12) = 0.; + + //Rotation around y-axis + //First node + answer.at(5, 1) = 0.; + answer.at(5, 2) = 0.; + answer.at(5, 3) = 0.; + answer.at(5, 4) = 0.; + answer.at(5, 5) = -1.; + answer.at(5, 6) = 0.; + //Second node + answer.at(5, 7) = 0.; + answer.at(5, 8) = 0.; + answer.at(5, 9) = 0.; + answer.at(5, 10) = 0.; + answer.at(5, 11) = 1.; + answer.at(5, 12) = 0.; + + //Rotation around z-axis + //First node + answer.at(6, 1) = 0.; + answer.at(6, 2) = 0.; + answer.at(6, 3) = 0.; + answer.at(6, 4) = 0.; + answer.at(6, 5) = 0.; + answer.at(6, 6) = -1.; + //Second node + answer.at(6, 7) = 0.; + answer.at(6, 8) = 0.; + answer.at(6, 9) = 0.; + answer.at(6, 10) = 0.; + answer.at(6, 11) = 0.; + answer.at(6, 12) = 1.; +// + return; + } + void + LatticeFrame3dNL::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) + { + FloatMatrix d, bt, db, b; + FloatArray u; + + this->computeVectorOf(VM_Total, tStep, u); + this->length = computeLength(); + + answer.resize(12, 12); + answer.zero(); + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), b); + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + db.beProductOf(d, b); + db.times(1. / length); + bt.beTranspositionOf(b); + answer.beProductOf(bt, db); + +// printf("answer/n"); +// answer.printYourself(); + return; + } +// void +// LatticeFrame3dNL::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, +// TimeStep *tStep) +// { +// FloatMatrix d; +// FloatArray u; +// this->length = computeLength(); +// answer.resize(12, 12); +// answer.zero(); +// +// this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); +// +// double l1 = this->length * ( 1. - this->s ) / 2; +// double l2 = this->length * ( 1. + this->s ) / 2; +// +// this->computeVectorOf(VM_Total, tStep, u); +// +// double cx1=(cos(u.at(5))*cos(u.at(6)))*l1; +// double cy1=(cos(u.at(4))*sin(u.at(6))+sin(u.at(4))*sin(u.at(5))*cos(u.at(6)))*l1; +// double cz1=(sin(u.at(4))*sin(u.at(6))-cos(u.at(4))*sin(u.at(5))*cos(u.at(6)))*l1; +// +// +// double cx2=(cos(u.at(11))*cos(u.at(12)))*l2; +// double cy2=(cos(u.at(10))*sin(u.at(12))+sin(u.at(10))*sin(u.at(11))*cos(u.at(12)))*l2; +// double cz2=(sin(u.at(10))*sin(u.at(12))-cos(u.at(10))*sin(u.at(11))*cos(u.at(12)))*l2; +// +// +// +// //Axial 1 +// answer.at(1, 1) = d.at(1, 1); +// answer.at(1, 2) = 0.; +// answer.at(1, 3) = 0.; +// answer.at(1, 4) = 0.; +// answer.at(1, 5) = -d.at(1,1)*(-cz1); +// answer.at(1, 6) = -d.at(1,1)*(cy1); +// answer.at(1, 7) = -d.at(1, 1); +// answer.at(1, 8) = 0.; +// answer.at(1, 9) = 0.; +// answer.at(1, 10) = 0.; +// answer.at(1, 11) = -d.at(1,1)*(-cz2); +// answer.at(1, 12) = -d.at(1,1)*(cy2); +// +// //Shear Y 1 +// answer.at(2, 1) = 0; +// answer.at(2, 2) = d.at(2, 2); +// answer.at(2, 3) = 0.; +// answer.at(2, 4) = -d.at(2,2)*(cz1); +// answer.at(2, 5) = 0; +// answer.at(2, 6) = -d.at(2,2)*(-cx1); +// answer.at(2, 7) = 0.; +// answer.at(2, 8) = -d.at(2,2); +// answer.at(2, 9) = 0.; +// answer.at(2, 10) = -d.at(2,2)*(cz2); +// answer.at(2, 11) = 0; +// answer.at(2, 12) = -d.at(2,2)*(-cx2); +// +// //Shear Z 1 +// answer.at(3, 1) = 0; +// answer.at(3, 2) = 0.; +// answer.at(3, 3) = d.at(3, 3); +// answer.at(3, 4) = -d.at(3,3)*(-cy1); +// answer.at(3, 5) = -d.at(3,3)*(cx1); +// answer.at(3, 6) = 0; +// answer.at(3, 7) = 0.; +// answer.at(3, 8) = 0; +// answer.at(3, 9) = -d.at(3, 3); +// answer.at(3, 10) = -d.at(3,3)*(-cy2); +// answer.at(3, 11) = -d.at(3,3)*(cx2); +// answer.at(3, 12) = 0; +// +// // Mx 1 +// answer.at(4, 1) = 0; +// answer.at(4, 2) = d.at(2,2)*(-cz1); +// answer.at(4, 3) = -d.at(3,3)*(-cy1); +// answer.at(4, 4) = -d.at(3,3)*(-cy1*cy1)+d.at(2,2)*(cz1*cz1)+d.at(4,4); +// answer.at(4, 5) = -d.at(3,3)*(cy1*cx1); +// answer.at(4, 6) = d.at(2,2)*(-cz1*cx1); +// answer.at(4, 7) = 0.; +// answer.at(4, 8) = d.at(2,2)*(cz1); +// answer.at(4, 9) = -d.at(3,3)*(cy1); +// answer.at(4, 10) = d.at(3,3)*(cy1*cy2)+d.at(2,2)*(+cz1*cz2)-d.at(4,4); +// answer.at(4, 11) = -d.at(3,3)*(cy1*cx2); +// answer.at(4, 12) = d.at(2,2)*(-cz1*cx2); +// +// // My 1 +// answer.at(5, 1) = -d.at(1,1)*(-cz1); +// answer.at(5, 2) = 0; +// answer.at(5, 3) = d.at(3,3)*(-cx1); +// answer.at(5, 4) = d.at(3,3)*(-cx1*cy1); +// answer.at(5, 5) = -d.at(1,1)*(-cz1*cz1)+d.at(3,3)*(cx1*cx1)+d.at(5,5); +// answer.at(5, 6) = -d.at(1,1)*(+cz1*cy1); +// answer.at(5, 7) = -d.at(1,1)*(cz1); +// answer.at(5, 8) = 0; +// answer.at(5, 9) = d.at(3,3)*(cx1); +// answer.at(5, 10) = d.at(3,3)*(-cx1*cy2); +// answer.at(5, 11) = -d.at(1,1)*(-cz1*cz2)+d.at(3,3)*(cx1*cx2)-d.at(5,5); +// answer.at(5, 12) = -d.at(1,1)*(cz1*cy2); +// +// // Mz 1 +// answer.at(6, 1) = d.at(1,1)*(-cy1); +// answer.at(6, 2) = -d.at(2,2)*(-cx1); +// answer.at(6, 3) = 0; +// answer.at(6, 4) = -d.at(2,2)*(cx1*cz1); +// answer.at(6, 5) = d.at(1,1)*(-cy1*cz1); +// answer.at(6, 6) = d.at(1,1)*(cy1*cy1)-d.at(2,2)*(-cx1*cx1)+d.at(6,6); +// answer.at(6, 7) = d.at(1,1)*(cy1); +// answer.at(6, 8) = -d.at(2,2)*(cx1); +// answer.at(6, 9) = 0; +// answer.at(6, 10) = -d.at(2,2)*(cx1*cz2); +// answer.at(6, 11) = d.at(1,1)*(-cy1*cz2); +// answer.at(6, 12) = d.at(1,1)*(cy1*cy2)-d.at(2,2)*(-cx1*cx2)-d.at(6,6); +// +// //Axial 2 +// answer.at(7, 1) = -d.at(1, 1); +// answer.at(7, 2) = 0.; +// answer.at(7, 3) = 0.; +// answer.at(7, 4) = 0.; +// answer.at(7, 5) = d.at(1,1)*(-cz1); +// answer.at(7, 6) = d.at(1,1)*(cy1); +// answer.at(7, 7) = d.at(1, 1); +// answer.at(7, 8) = 0.; +// answer.at(7, 9) = 0.; +// answer.at(7, 10) = 0.; +// answer.at(7, 11) = d.at(1,1)*(-cz2); +// answer.at(7, 12) = d.at(1,1)*(cy2); +// +// //Shear Y 2 +// answer.at(8, 1) = 0; +// answer.at(8, 2) = -d.at(2, 2); +// answer.at(8, 3) = 0.; +// answer.at(8, 4) = d.at(2,2)*(cz1); +// answer.at(8, 5) = 0; +// answer.at(8, 6) = d.at(2,2)*(-cx1); +// answer.at(8, 7) = 0.; +// answer.at(8, 8) = d.at(2,2); +// answer.at(8, 9) = 0.; +// answer.at(8, 10) = d.at(2,2)*(cz2); +// answer.at(8, 11) = 0; +// answer.at(8, 12) = d.at(2,2)*(-cx2); +// +// //Shear Z 2 +// answer.at(9, 1) = 0; +// answer.at(9, 2) = 0.; +// answer.at(9, 3) = -d.at(3, 3); +// answer.at(9, 4) = d.at(3,3)*(-cy1); +// answer.at(9, 5) = d.at(3,3)*(cx1); +// answer.at(9, 6) = 0; +// answer.at(9, 7) = 0.; +// answer.at(9, 8) = 0; +// answer.at(9, 9) = d.at(3, 3); +// answer.at(9, 10) = d.at(3,3)*(-cy2); +// answer.at(9, 11) = d.at(3,3)*(cx2); +// answer.at(9, 12) = 0; +// +// // Mx 2 +// answer.at(10, 1) = 0; +// answer.at(10, 2) = -d.at(2,2)*(cz2); +// answer.at(10, 3) = d.at(3,3)*(cy2); +// answer.at(10, 4) = d.at(3,3)*(cy2*cy1)-d.at(2,2)*(-cz2*cz1)-d.at(4,4); +// answer.at(10, 5) = d.at(3,3)*(-cy2*cx1); +// answer.at(10, 6) = -d.at(2,2)*(cz2*cx1); +// answer.at(10, 7) = 0.; +// answer.at(10, 8) = -d.at(2,2)*(-cz2); +// answer.at(10, 9) = d.at(3,3)*(-cy2); +// answer.at(10, 10) = d.at(3,3)*(cy2*cy2)-d.at(2,2)*(-cz2*cz2)+d.at(4,4); +// answer.at(10, 11) = d.at(3,3)*(-cy2*cx2); +// answer.at(10, 12) = -d.at(2,2)*(+cz2*cx2); +// +// // My 2 +// answer.at(11, 1) = d.at(1,1)*(cz2); +// answer.at(11, 2) = 0; +// answer.at(11, 3) = -d.at(3,3)*(cx2); +// answer.at(11, 4) = -d.at(3,3)*(cx2*cy1); +// answer.at(11, 5) = d.at(1,1)*(cz2*cz1)-d.at(3,3)*(-cx2*cx1)-d.at(5,5); +// answer.at(11, 6) = d.at(1,1)*(-cz2*cy1); +// answer.at(11, 7) = d.at(1,1)*(-cz2); +// answer.at(11, 8) = 0; +// answer.at(11, 9) = -d.at(3,3)*(-cx2); +// answer.at(11, 10) = -d.at(3,3)*(cx2*cy2); +// answer.at(11, 11) = d.at(1,1)*(cz2*cz2)-d.at(3,3)*(-cx2*cx2)+d.at(5,5); +// answer.at(11, 12) = d.at(1,1)*(-cz2*cy2); +// +// // Mz 2 +// answer.at(12, 1) = -cy2*d.at(1,1); +// answer.at(12, 2) = cx2*d.at(2,2); +// answer.at(12, 3) = 0; +// answer.at(12, 4) = -cx2*d.at(2,2)*(cz1); +// answer.at(12, 5) = cy2*d.at(1,1)*(-cz1); +// answer.at(12, 6) = cy2*d.at(1,1)*(cy1)-cx2*d.at(2,2)*(-cx1)-d.at(6,6); +// answer.at(12, 7) = cy2*d.at(1,1); +// answer.at(12, 8) = -cx2*d.at(2,2); +// answer.at(12, 9) = 0; +// answer.at(12, 10) = -cx2*d.at(2,2)*(cz2); +// answer.at(12, 11) = cy2*d.at(1,1)*(-cz2); +// answer.at(12, 12) = cy2*d.at(1,1)*(cy2)-cx2*d.at(2,2)*(-cx2)+d.at(6,6); +// +// answer.times(1. / this->length); +// return; +// } + + void + LatticeFrame3dNL::computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) + // Computes the vector containing the strains at the Gauss point gp of + // the receiver, at time step tStep. The nature of these strains depends + // on the element's type. + { + FloatArray u; + this->computeVectorOf(VM_Total, tStep, u); + +// printf("displacement n:"); +// un.printYourself(); + + this->length = computeLength(); + double l1 = this->length * ( 1. - this->s ) / 2; + double l2 = this->length * ( 1. + this->s ) / 2; + // double ln = sqrt(pow(njn.at(1)-nin.at(1), 2) + pow(njn.at(2)-nin.at(2), 2) + pow(njn.at(3)-nin.at(3), 2) ); + LatticeMaterialStatus *lmatStat = dynamic_cast < LatticeMaterialStatus * > ( integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialStatus() ); + auto strain = lmatStat->giveLatticeStrain(); + +// double cx1=(cos(u.at(5))*cos(u.at(6)))*l1; +// double cy1=(cos(u.at(4))*sin(u.at(6))+sin(u.at(4))*sin(u.at(5))*cos(u.at(6)))*l1; +// double cz1=(sin(u.at(4))*sin(u.at(6))-cos(u.at(4))*sin(u.at(5))*cos(u.at(6)))*l1; +// +// +// double cx2=(cos(u.at(11))*cos(u.at(12)))*l2; +// double cy2=(cos(u.at(10))*sin(u.at(12))+sin(u.at(10))*sin(u.at(11))*cos(u.at(12)))*l2; +// double cz2=(sin(u.at(10))*sin(u.at(12))-cos(u.at(10))*sin(u.at(11))*cos(u.at(12)))*l2; + double cx1=(cos(u.at(5))*cos(u.at(6)))*l1; + double cy1=(cos(u.at(5))*sin(u.at(6)))*l1; + double cz1=(-sin(u.at(5)))*l1; + + + double cx2=(cos(u.at(11))*cos(u.at(12)))*l2; + double cy2=(cos(u.at(11))*sin(u.at(12)))*l2; + double cz2=(-sin(u.at(11)))*l2; + // + answer.resize(6); + answer.at(1) = u.at(7)-u.at(1)-cx2 -cx1 +l1+l2; + answer.at(2) = u.at(8)-u.at(2)-cy2 -cy1; + answer.at(3) = u.at(9)-u.at(3)-cz2 -cz1; + answer.at(4) = u.at(10)-u.at(4); + answer.at(5) = u.at(11)-u.at(5); + answer.at(6) = u.at(12)-u.at(6); + answer.times(1. / this->length); + + } + // + void + LatticeFrame3dNL::giveInternalForcesVector(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) + { + FloatMatrix b, bt, bf, d; + FloatArray u, stress, strain; + this->computeVectorOf(VM_Total, tStep, u); + // this->computeVectorOf(VM_Incremental, tStep, u); + this->length = computeLength(); + GaussPoint *gp = this->integrationRulesArray [ 0 ]->getIntegrationPoint(0); + // Total stress + this->computeStrainVector(strain, gp, tStep); + this->computeStressVector(stress, strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + // Old stresses + LatticeMaterialStatus *lmatStat = dynamic_cast < LatticeMaterialStatus * > ( integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialStatus() ); + auto oldStress = lmatStat->giveLatticeStress(); + // + auto oldInternalForces = lmatStat->giveInternalForces(); + double l1 = this->length * ( 1. - this->s ) / 2; + double l2 = this->length * ( 1. + this->s ) / 2; + // +// double cx1=(cos(u.at(5))*cos(u.at(6)))*l1; +// double cy1=(cos(u.at(4))*sin(u.at(6))+sin(u.at(4))*sin(u.at(5))*cos(u.at(6)))*l1; +// double cz1=(sin(u.at(4))*sin(u.at(6))-cos(u.at(4))*sin(u.at(5))*cos(u.at(6)))*l1; +// +// +// double cx2=(cos(u.at(11))*cos(u.at(12)))*l2; +// double cy2=(cos(u.at(10))*sin(u.at(12))+sin(u.at(10))*sin(u.at(11))*cos(u.at(12)))*l2; +// double cz2=(sin(u.at(10))*sin(u.at(12))-cos(u.at(10))*sin(u.at(11))*cos(u.at(12)))*l2; + + double cx1=(cos(u.at(5))*cos(u.at(6)))*l1; + double cy1=(cos(u.at(5))*sin(u.at(6)))*l1; + double cz1=(-sin(u.at(5)))*l1; + + + double cx2=(cos(u.at(11))*cos(u.at(12)))*l2; + double cy2=(cos(u.at(11))*sin(u.at(12)))*l2; + double cz2=(-sin(u.at(11)))*l2; + // + // + answer.resize(12); + answer.at(1) = -stress.at(1); + answer.at(2) = -stress.at(2); + answer.at(3) = -stress.at(3); + answer.at(4) = stress.at(2)*cz1- stress.at(3)*cy1- stress.at(4); + answer.at(5) = -stress.at(1)*cz1+ stress.at(3)*cx1- stress.at(5); + answer.at(6) = stress.at(1)*cy1- stress.at(2)*cx1- stress.at(6); + answer.at(7) = stress.at(1); + answer.at(8) = stress.at(2); + answer.at(9) = stress.at(3); + answer.at(10) = stress.at(2)*cz2- stress.at(3)*cy2+ stress.at(4); + answer.at(11) = -stress.at(1)*cz2+ stress.at(3)*cx2+ stress.at(5); + answer.at(12) = stress.at(1)*cy2- stress.at(2)*cx2+ stress.at(6); + // + lmatStat->letTempInternalForcesBe(answer); + + } + + int + LatticeFrame3dNL::giveLocalCoordinateSystem(FloatMatrix &answer) + { + FloatArray lx, ly, lz, help(3); + FloatArray coordA, coordB; + FloatArray uA(6), uAIncr(6), uB(6), uBIncr(6); + IntArray dofid = { + 1, 2, 3, 4, 5, 6 + }; + + TimeStep *tStep = this->domain->giveEngngModel()->giveCurrentStep(); + + Node *nodeA, *nodeB; + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + + //Local coordinate system is determined from the displacement of last step. + + coordA = nodeA->giveCoordinates(); + nodeA->giveUnknownVector(uA, dofid, VM_Total, tStep, false); + nodeA->giveUnknownVector(uAIncr, dofid, VM_Incremental, tStep, false); +// for (int i = 1; i <= 3; i++) { +// coordA.at(i) += uA.at(i) - uAIncr.at(i); +// } + + coordB = nodeB->giveCoordinates(); + nodeB->giveUnknownVector(uB, dofid, VM_Total, tStep, false); + nodeB->giveUnknownVector(uBIncr, dofid, VM_Incremental, tStep, false); + +// for (int i = 1; i <= 3; i++) { +// coordB.at(i) += uB.at(i) - uBIncr.at(i); +// } + + lx.beDifferenceOf(coordB, coordA); + lx.normalize(); + + + if ( this->referenceNode ) { + Node *refNode = this->giveDomain()->giveNode(this->referenceNode); + help.beDifferenceOf( refNode->giveCoordinates(), nodeA->giveCoordinates() ); + + lz.beVectorProductOf(lx, help); + lz.normalize(); + } else if ( this->zaxis.giveSize() > 0 ) { + lz = this->zaxis; + lz.add(lz.dotProduct(lx), lx); + lz.normalize(); + } else { + FloatMatrix rot(3, 3); + double theta = referenceAngle * M_PI / 180.0; + + rot.at(1, 1) = cos(theta) + pow(lx.at(1), 2) * ( 1 - cos(theta) ); + rot.at(1, 2) = lx.at(1) * lx.at(2) * ( 1 - cos(theta) ) - lx.at(3) * sin(theta); + rot.at(1, 3) = lx.at(1) * lx.at(3) * ( 1 - cos(theta) ) + lx.at(2) * sin(theta); + + rot.at(2, 1) = lx.at(2) * lx.at(1) * ( 1 - cos(theta) ) + lx.at(3) * sin(theta); + rot.at(2, 2) = cos(theta) + pow(lx.at(2), 2) * ( 1 - cos(theta) ); + rot.at(2, 3) = lx.at(2) * lx.at(3) * ( 1 - cos(theta) ) - lx.at(1) * sin(theta); + + rot.at(3, 1) = lx.at(3) * lx.at(1) * ( 1 - cos(theta) ) - lx.at(2) * sin(theta); + rot.at(3, 2) = lx.at(3) * lx.at(2) * ( 1 - cos(theta) ) + lx.at(1) * sin(theta); + rot.at(3, 3) = cos(theta) + pow(lx.at(3), 2) * ( 1 - cos(theta) ); + + help.at(3) = 1.0; // up-vector + + // here is ly is used as a temp var + if ( fabs( lx.dotProduct(help) ) > 0.999 ) { // Check if it is vertical + ly = { + 0., 1., 0. + }; + } else { + ly.beVectorProductOf(lx, help); + } + lz.beProductOf(rot, ly); + lz.normalize(); + } + + ly.beVectorProductOf(lz, lx); + ly.normalize(); + + answer.resize(3, 3); + answer.zero(); + for ( int i = 1; i <= 3; i++ ) { + answer.at(1, i) = lx.at(i); + answer.at(2, i) = ly.at(i); + answer.at(3, i) = lz.at(i); + } + + return 1; + } +} // end namespace oofem \ No newline at end of file diff --git a/src/sm/Elements/LatticeElements/latticeframe3dnl.h b/src/sm/Elements/LatticeElements/latticeframe3dnl.h new file mode 100644 index 000000000..dcc9e692f --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticeframe3dnl.h @@ -0,0 +1,76 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2023 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticeframe3dnl_h +#define latticeframe3dnl_h + +#include "latticeframe3d.h" + +///@name Input fields for LatticeFrame3dNL +//@{ +#define _IFT_LatticeFrame3dNL_Name "latticeframe3dnl" + +//@} + +namespace oofem { +/** +This class implements a geometric nonlinear 3-dimensional frame element. It is an extension of a geometric linear 3-dimensional frame element based on rigid body spring theory called LatticeFrame3D presented in Toi 1991 and Toi 1993. It belongs to the group of lattice models in the OOFEM structure, but can be used as a standard 3D beam element. +References: +Toi, Y. (1991). Shifted integration technique in oneâ€dimensional plastic collapse analysis using linear and cubic finite elements. International Journal for Numerical Methods in Engineering, 31(8), 1537-1552. +Toi, Y., & Isobe, D. (1993). Adaptively shifted integration technique for finite element collapse analysis of framed structures. International Journal for Numerical Methods in Engineering, 36(14), 2323-2339. +Authors: Gumaa Abdelrhim and Peter Grassl, 2023 +*/ + + class LatticeFrame3dNL : public LatticeFrame3d + { + protected: + + public: + LatticeFrame3dNL(int n, Domain *); + virtual ~LatticeFrame3dNL(); + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + const char *giveInputRecordName() const override { return _IFT_LatticeFrame3dNL_Name; } + const char *giveClassName() const override { return "latticeframe3dnl"; } + + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override; + + protected: + virtual void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + virtual void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; + }; +} // end namespace oofem +#endif \ No newline at end of file diff --git a/src/sm/Elements/LatticeElements/latticeframe3dnl2.C b/src/sm/Elements/LatticeElements/latticeframe3dnl2.C new file mode 100644 index 000000000..be93ea846 --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticeframe3dnl2.C @@ -0,0 +1,493 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2023 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "latticeframe3dnl2.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "intarray.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "mathfem.h" +#include "latticeframe3d.h" +#include "contextioerr.h" +#include "datastream.h" +#include "classfactory.h" +#include "sm/CrossSections/latticecrosssection.h" +#include "engngm.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" + #include "../sm/Materials/structuralmaterial.h" +#endif + +namespace oofem { + REGISTER_Element(LatticeFrame3dNL2); + + LatticeFrame3dNL2::LatticeFrame3dNL2(int n, Domain *aDomain) : LatticeFrame3d(n, aDomain) + { + numberOfDofMans = 2; + } + + LatticeFrame3dNL2::~LatticeFrame3dNL2() + {} + void + LatticeFrame3dNL2::computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) + //Returns the strain matrix of the receiver. + { + FloatArray u; + TimeStep *tStep = this->domain->giveEngngModel()->giveCurrentStep(); + this->computeVectorOf(VM_Total, tStep, u); + + FloatArray coordA(3), coordB(3); + coordA = giveNode(1)->giveCoordinates(); + coordB = giveNode(2)->giveCoordinates(); + + this->length = computeLength(); + double l1 = this->length * ( 1. + this->s ) / 2.; + double l2 = this->length * ( 1. - this->s ) / 2.; + + double lx1 = ( coordB.at(1) - coordA.at(1) ) * ( 1. + this->s ) / 2.; + double ly1 = ( coordB.at(2) - coordA.at(2) ) * ( 1. + this->s ) / 2.; + double lz1 = ( coordB.at(3) - coordA.at(3) ) * ( 1. + this->s ) / 2.; + + double lx2 = ( coordB.at(1) - coordA.at(1) ) * ( 1. - this->s ) / 2.; + double ly2 = ( coordB.at(2) - coordA.at(2) ) * ( 1. - this->s ) / 2.; + double lz2 = ( coordB.at(3) - coordA.at(3) ) * ( 1. - this->s ) / 2.; + + answer.resize(6, 12); + answer.zero(); + + + double cx1Old = ( cos( u.at(5) ) * cos( u.at(6) ) ) * l1; + double cy1Old = ( cos( u.at(4) ) * sin( u.at(6) ) + sin( u.at(4) ) * sin( u.at(5) ) * cos( u.at(6) ) ) * l1; + double cz1Old = ( sin( u.at(4) ) * sin( u.at(6) ) - cos( u.at(4) ) * sin( u.at(5) ) * cos( u.at(6) ) ) * l1; + + + double cx2Old = ( cos( u.at(11) ) * cos( u.at(12) ) ) * l2; + double cy2Old = ( cos( u.at(10) ) * sin( u.at(12) ) + sin( u.at(10) ) * sin( u.at(11) ) * cos( u.at(12) ) ) * l2; + double cz2Old = ( sin( u.at(10) ) * sin( u.at(12) ) - cos( u.at(10) ) * sin( u.at(11) ) * cos( u.at(12) ) ) * l2; + + + //First node rotations + double thetaX1 = u.at(4); + double thetaY1 = u.at(5); + double thetaZ1 = u.at(6); + + //Second node rotations + double thetaX2 = u.at(10); + double thetaY2 = u.at(11); + double thetaZ2 = u.at(12); + + +// double cx1 = lz1 * sin(thetaY1) + lx1 * cos(thetaY1) * cos(thetaZ1) - ly1 * cos(thetaY1) * sin(thetaZ1); +// double cx2 = lz2 * sin(thetaY2) + lx2 * cos(thetaY2) * cos(thetaZ2) - ly2 * cos(thetaY2) * sin(thetaZ2); +// double cy1 = lx1 * ( cos(thetaX1) * sin(thetaZ1) + cos(thetaZ1) * sin(thetaX1) * sin(thetaY1) ) + ly1 * ( cos(thetaX1) * cos(thetaZ1) - sin(thetaX1) * sin(thetaY1) * sin(thetaZ1) ) - lz1 * cos(thetaY1) * sin(thetaX1); +// double cy2 = lx2 * ( cos(thetaX2) * sin(thetaZ2) + cos(thetaZ2) * sin(thetaX2) * sin(thetaY2) ) + ly2 * ( cos(thetaX2) * cos(thetaZ2) - sin(thetaX2) * sin(thetaY2) * sin(thetaZ2) ) - lz2 * cos(thetaY2) * sin(thetaX2); +// double cz1 = lx1 * ( sin(thetaX1) * sin(thetaZ1) - cos(thetaX1) * cos(thetaZ1) * sin(thetaY1) ) + ly1 * ( cos(thetaZ1) * sin(thetaX1) + cos(thetaX1) * sin(thetaY1) * sin(thetaZ1) ) + lz1 * cos(thetaX1) * cos(thetaY1); +// double cz2 = lx2 * ( sin(thetaX2) * sin(thetaZ2) - cos(thetaX2) * cos(thetaZ2) * sin(thetaY2) ) + ly2 * ( cos(thetaZ2) * sin(thetaX2) + cos(thetaX2) * sin(thetaY2) * sin(thetaZ2) ) + lz2 * cos(thetaX2) * cos(thetaY2); + + double cx1 = (cos(thetaZ1) * cos(thetaY1)) * lx1 + + (-sin(thetaZ1) * cos(thetaX1) + cos(thetaZ1) * sin(thetaY1) * sin(thetaX1)) * ly1 + + (sin(thetaZ1) * sin(thetaX1) + cos(thetaZ1) * sin(thetaY1) * cos(thetaX1)) * lz1; + + double cy1 = (sin(thetaZ1) * cos(thetaY1)) * lx1 + + (cos(thetaZ1) * cos(thetaX1) + sin(thetaZ1) * sin(thetaY1) * sin(thetaX1)) * ly1 + + (-cos(thetaZ1) * sin(thetaX1) + sin(thetaZ1) * sin(thetaY1) * cos(thetaX1)) * lz1; + + double cz1 = (-sin(thetaY1)) * lx1 + + (cos(thetaY1) * sin(thetaX1)) * ly1 + + (cos(thetaY1) * cos(thetaX1)) * lz1; + + double cx2 = (cos(thetaZ2) * cos(thetaY2)) * lx2 + + (-sin(thetaZ2) * cos(thetaX2) + cos(thetaZ2) * sin(thetaY2) * sin(thetaX2)) * ly2 + + (sin(thetaZ2) * sin(thetaX2) + cos(thetaZ2) * sin(thetaY2) * cos(thetaX2)) * lz2; + + double cy2 = (sin(thetaZ2) * cos(thetaY2)) * lx2 + + (cos(thetaZ2) * cos(thetaX2) + sin(thetaX2) * sin(thetaY2) * sin(thetaZ2)) * ly2 + + (-cos(thetaZ2) * sin(thetaX2) + sin(thetaZ2) * sin(thetaY2) * cos(thetaX2)) * lz2; + + double cz2 = (-sin(thetaY2)) * lx2 + + (cos(thetaY2) * sin(thetaX2)) * ly2 + + (cos(thetaY2) * cos(thetaX2)) * lz2; + //Normal displacement jump in x-direction + //First node + answer.at(1, 1) = -1.; + answer.at(1, 2) = 0.; + answer.at(1, 3) = 0.; + answer.at(1, 4) = 0.; + answer.at(1, 5) = -cz1; + answer.at(1, 6) = cy1; + //Second node + answer.at(1, 7) = 1.; + answer.at(1, 8) = 0.; + answer.at(1, 9) = 0.; + answer.at(1, 10) = 0.; + answer.at(1, 11) = -cz2; + answer.at(1, 12) = cy2; + + //Shear displacement jump in y-plane + //first node + answer.at(2, 1) = 0.; + answer.at(2, 2) = -1.; + answer.at(2, 3) = 0.; + answer.at(2, 4) = cz1; + answer.at(2, 5) = 0; + answer.at(2, 6) = -cx1; + //Second node + answer.at(2, 7) = 0.; + answer.at(2, 8) = 1.; + answer.at(2, 9) = 0.; + answer.at(2, 10) = cz2; + answer.at(2, 11) = 0; + answer.at(2, 12) = -cx2; + + //Shear displacement jump in z-plane + //first node + answer.at(3, 1) = 0.; + answer.at(3, 2) = 0.; + answer.at(3, 3) = -1.; + answer.at(3, 4) = -cy1; + answer.at(3, 5) = cx1; + answer.at(3, 6) = 0.; + //Second node + answer.at(3, 7) = 0.; + answer.at(3, 8) = 0.; + answer.at(3, 9) = 1.; + answer.at(3, 10) = -cy2; + answer.at(3, 11) = cx2; + answer.at(3, 12) = 0.; + + //Rotation around x-axis + //First node + answer.at(4, 1) = 0.; + answer.at(4, 2) = 0; + answer.at(4, 3) = 0.; + answer.at(4, 4) = -1.; + answer.at(4, 5) = 0.; + answer.at(4, 6) = 0.; + //Second node + answer.at(4, 7) = 0.; + answer.at(4, 8) = 0.; + answer.at(4, 9) = 0.; + answer.at(4, 10) = 1.; + answer.at(4, 11) = 0.; + answer.at(4, 12) = 0.; + + //Rotation around y-axis + //First node + answer.at(5, 1) = 0.; + answer.at(5, 2) = 0.; + answer.at(5, 3) = 0.; + answer.at(5, 4) = 0.; + answer.at(5, 5) = -1.; + answer.at(5, 6) = 0.; + //Second node + answer.at(5, 7) = 0.; + answer.at(5, 8) = 0.; + answer.at(5, 9) = 0.; + answer.at(5, 10) = 0.; + answer.at(5, 11) = 1.; + answer.at(5, 12) = 0.; + + //Rotation around z-axis + //First node + answer.at(6, 1) = 0.; + answer.at(6, 2) = 0.; + answer.at(6, 3) = 0.; + answer.at(6, 4) = 0.; + answer.at(6, 5) = 0.; + answer.at(6, 6) = -1.; + //Second node + answer.at(6, 7) = 0.; + answer.at(6, 8) = 0.; + answer.at(6, 9) = 0.; + answer.at(6, 10) = 0.; + answer.at(6, 11) = 0.; + answer.at(6, 12) = 1.; + + return; + } + void + LatticeFrame3dNL2::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) + { + FloatMatrix d, bt, db, b; + FloatArray u; + + this->computeVectorOf(VM_Total, tStep, u); + this->length = computeLength(); + + answer.resize(12, 12); + answer.zero(); + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), b); + + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + //Rotate constitutive stiffness matrix + FloatMatrix r(6, 6), rT(6, 6), dR(6, 6), rTDR(6, 6); + computeGtoLStrainRotationMatrix(r); + rT.beTranspositionOf(r); + + dR.beProductOf(d, r); + rTDR.beProductOf(rT, dR); + + db.beProductOf(rTDR, b); + db.times(1. / length); + bt.beTranspositionOf(b); + answer.beProductOf(bt, db); + + return; + } + + void + LatticeFrame3dNL2::computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) + { + //Compute normalised displacement jumps in global coordinate system first and then rotate it to the local coordiante system. + + FloatArray u; + this->computeVectorOf(VM_Total, tStep, u); + + FloatArray coordA(3), coordB(3); + coordA = giveNode(1)->giveCoordinates(); + coordB = giveNode(2)->giveCoordinates(); + + this->length = computeLength(); + + double l1 = this->length * ( 1. + this->s ) / 2.; + double l2 = this->length * ( 1. - this->s ) / 2.; + + double lx1 = ( coordB.at(1) - coordA.at(1) ) * ( 1. + this->s ) / 2.; + double ly1 = ( coordB.at(2) - coordA.at(2) ) * ( 1. + this->s ) / 2.; + double lz1 = ( coordB.at(3) - coordA.at(3) ) * ( 1. + this->s ) / 2.; + + double lx2 = ( coordB.at(1) - coordA.at(1) ) * ( 1. - this->s ) / 2.; + double ly2 = ( coordB.at(2) - coordA.at(2) ) * ( 1. - this->s ) / 2.; + double lz2 = ( coordB.at(3) - coordA.at(3) ) * ( 1. - this->s ) / 2.; + + LatticeMaterialStatus *lmatStat = dynamic_cast < LatticeMaterialStatus * > ( integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialStatus() ); + auto strain = lmatStat->giveLatticeStrain(); + + //First node rotations + double uX1 = u.at(1); + double uY1 = u.at(2); + double uZ1 = u.at(3); + + double thetaX1 = u.at(4); + double thetaY1 = u.at(5); + double thetaZ1 = u.at(6); + + double thetaX2 = u.at(10); + double thetaY2 = u.at(11); + double thetaZ2 = u.at(12); + +// double cx1 = lz1 * sin(thetaY1) + lx1 * cos(thetaY1) * cos(thetaZ1) - ly1 * cos(thetaY1) * sin(thetaZ1); +// double cx2 = lz2 * sin(thetaY2) + lx2 * cos(thetaY2) * cos(thetaZ2) - ly2 * cos(thetaY2) * sin(thetaZ2); +// double cy1 = lx1 * ( cos(thetaX1) * sin(thetaZ1) + cos(thetaZ1) * sin(thetaX1) * sin(thetaY1) ) + ly1 * ( cos(thetaX1) * cos(thetaZ1) - sin(thetaX1) * sin(thetaY1) * sin(thetaZ1) ) - lz1 * cos(thetaY1) * sin(thetaX1); +// double cy2 = lx2 * ( cos(thetaX2) * sin(thetaZ2) + cos(thetaZ2) * sin(thetaX2) * sin(thetaY2) ) + ly2 * ( cos(thetaX2) * cos(thetaZ2) - sin(thetaX2) * sin(thetaY2) * sin(thetaZ2) ) - lz2 * cos(thetaY2) * sin(thetaX2); +// double cz1 = lx1 * ( sin(thetaX1) * sin(thetaZ1) - cos(thetaX1) * cos(thetaZ1) * sin(thetaY1) ) + ly1 * ( cos(thetaZ1) * sin(thetaX1) + cos(thetaX1) * sin(thetaY1) * sin(thetaZ1) ) + lz1 * cos(thetaX1) * cos(thetaY1); +// double cz2 = lx2 * ( sin(thetaX2) * sin(thetaZ2) - cos(thetaX2) * cos(thetaZ2) * sin(thetaY2) ) + ly2 * ( cos(thetaZ2) * sin(thetaX2) + cos(thetaX2) * sin(thetaY2) * sin(thetaZ2) ) + lz2 * cos(thetaX2) * cos(thetaY2); + + double cx1 = (cos(thetaZ1) * cos(thetaY1)) * lx1 + + (-sin(thetaZ1) * cos(thetaX1) + cos(thetaZ1) * sin(thetaY1) * sin(thetaX1)) * ly1 + + (sin(thetaZ1) * sin(thetaX1) + cos(thetaZ1) * sin(thetaY1) * cos(thetaX1)) * lz1; + + double cy1 = (sin(thetaZ1) * cos(thetaY1)) * lx1 + + (cos(thetaZ1) * cos(thetaX1) + sin(thetaX1) * sin(thetaY1) * sin(thetaZ1)) * ly1 + + (-cos(thetaZ1) * sin(thetaX1) + sin(thetaZ1) * sin(thetaY1) * cos(thetaX1)) * lz1; + + double cz1 = (-sin(thetaY1)) * lx1 + + (cos(thetaY1) * sin(thetaX1)) * ly1 + + (cos(thetaY1) * cos(thetaX1)) * lz1; + + double cx2 = (cos(thetaZ2) * cos(thetaY2)) * lx2 + + (-sin(thetaZ2) * cos(thetaX2) + cos(thetaZ2) * sin(thetaY2) * sin(thetaX2)) * ly2 + + (sin(thetaZ2) * sin(thetaX2) + cos(thetaZ2) * sin(thetaY2) * cos(thetaX2)) * lz2; + + double cy2 = (sin(thetaZ2) * cos(thetaY2)) * lx2 + + (cos(thetaZ2) * cos(thetaX2) + sin(thetaX2) * sin(thetaY2) * sin(thetaZ2)) * ly2 + + (-cos(thetaZ2) * sin(thetaX2) + sin(thetaZ2) * sin(thetaY2) * cos(thetaX2)) * lz2; + + double cz2 = (-sin(thetaY2)) * lx2 + + (cos(thetaY2) * sin(thetaX2)) * ly2 + + (cos(thetaY2) * cos(thetaX2)) * lz2; + + answer.resize(6); + answer.at(1) = u.at(7) - u.at(1) - cx1 - cx2 + lx1 + lx2; + answer.at(2) = u.at(8) - u.at(2) - cy1 - cy2 + ly1 + ly2; + answer.at(3) = u.at(9) - u.at(3) - cz1 - cz2 + lz1 + lz2; + answer.at(4) = u.at(10) - u.at(4); + answer.at(5) = u.at(11) - u.at(5); + answer.at(6) = u.at(12) - u.at(6); + + answer.times(1. / this->length); + + //Rotate strain vector to local coordinate system + FloatMatrix rotationMatrix(6, 6); + computeGtoLStrainRotationMatrix(rotationMatrix); + answer.rotatedWith(rotationMatrix, 'n'); + } + + + bool + LatticeFrame3dNL2::computeGtoLStrainRotationMatrix(FloatMatrix &answer) + { + FloatMatrix lcs; + answer.resize(6, 6); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + } + } + + return 1; + } + + + bool + LatticeFrame3dNL2::computeGtoLRotationMatrix(FloatMatrix &answer) + { + return false; + } + + + + // + void + LatticeFrame3dNL2::giveInternalForcesVector(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) + { + FloatMatrix b, bt, bf, d; + FloatArray u, stress, strain; + this->computeVectorOf(VM_Total, tStep, u); + this->length = computeLength(); + GaussPoint *gp = this->integrationRulesArray [ 0 ]->getIntegrationPoint(0); + + FloatArray coordA(3), coordB(3); + coordA = giveNode(1)->giveCoordinates(); + coordB = giveNode(2)->giveCoordinates(); + + this->computeStrainVector(strain, gp, tStep); + this->computeStressVector(stress, strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + /* // Rotate strain vector to local coordinate system */ + FloatMatrix rotationMatrix(6, 6); + computeGtoLStrainRotationMatrix(rotationMatrix); +// bt.beTranspositionOf(rotationMatrix); + stress.rotatedWith(rotationMatrix, 't'); + + //First node rotations + double thetaX1 = u.at(4); + double thetaY1 = u.at(5); + double thetaZ1 = u.at(6); + + //Second node rotations + double thetaX2 = u.at(10); + double thetaY2 = u.at(11); + double thetaZ2 = u.at(12); + + + LatticeMaterialStatus *lmatStat = dynamic_cast < LatticeMaterialStatus * > ( integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialStatus() ); + + double l1 = this->length * ( 1. + this->s ) / 2.; + double l2 = this->length * ( 1. - this->s ) / 2.; + +// + double lx1 = ( coordB.at(1) - coordA.at(1) ) * ( 1. + this->s ) / 2.; + double ly1 = ( coordB.at(2) - coordA.at(2) ) * ( 1. + this->s ) / 2.; + double lz1 = ( coordB.at(3) - coordA.at(3) ) * ( 1. + this->s ) / 2.; + + double lx2 = ( coordB.at(1) - coordA.at(1) ) * ( 1. - this->s ) / 2.; + double ly2 = ( coordB.at(2) - coordA.at(2) ) * ( 1. - this->s ) / 2.; + double lz2 = ( coordB.at(3) - coordA.at(3) ) * ( 1. - this->s ) / 2.; + + +// double cx1 = lz1 * sin(thetaY1) + lx1 * cos(thetaY1) * cos(thetaZ1) - ly1 * cos(thetaY1) * sin(thetaZ1); +// double cx2 = lz2 * sin(thetaY2) + lx2 * cos(thetaY2) * cos(thetaZ2) - ly2 * cos(thetaY2) * sin(thetaZ2); +// double cy1 = lx1 * ( cos(thetaX1) * sin(thetaZ1) + cos(thetaZ1) * sin(thetaX1) * sin(thetaY1) ) + ly1 * ( cos(thetaX1) * cos(thetaZ1) - sin(thetaX1) * sin(thetaY1) * sin(thetaZ1) ) - lz1 * cos(thetaY1) * sin(thetaX1); +// double cy2 = lx2 * ( cos(thetaX2) * sin(thetaZ2) + cos(thetaZ2) * sin(thetaX2) * sin(thetaY2) ) + ly2 * ( cos(thetaX2) * cos(thetaZ2) - sin(thetaX2) * sin(thetaY2) * sin(thetaZ2) ) - lz2 * cos(thetaY2) * sin(thetaX2); +// double cz1 = lx1 * ( sin(thetaX1) * sin(thetaZ1) - cos(thetaX1) * cos(thetaZ1) * sin(thetaY1) ) + ly1 * ( cos(thetaZ1) * sin(thetaX1) + cos(thetaX1) * sin(thetaY1) * sin(thetaZ1) ) + lz1 * cos(thetaX1) * cos(thetaY1); +// double cz2 = lx2 * ( sin(thetaX2) * sin(thetaZ2) - cos(thetaX2) * cos(thetaZ2) * sin(thetaY2) ) + ly2 * ( cos(thetaZ2) * sin(thetaX2) + cos(thetaX2) * sin(thetaY2) * sin(thetaZ2) ) + lz2 * cos(thetaX2) * cos(thetaY2); + + double cx1 = (cos(thetaZ1) * cos(thetaY1)) * lx1 + + (-sin(thetaZ1) * cos(thetaX1) + cos(thetaZ1) * sin(thetaY1) * sin(thetaX1)) * ly1 + + (sin(thetaZ1) * sin(thetaX1) + cos(thetaZ1) * sin(thetaY1) * cos(thetaX1)) * lz1; + + double cy1 = (sin(thetaZ1) * cos(thetaY1)) * lx1 + + (cos(thetaZ1) * cos(thetaX1) + sin(thetaX1) * sin(thetaY1) * sin(thetaZ1)) * ly1 + + (-cos(thetaZ1) * sin(thetaX1) + sin(thetaZ1) * sin(thetaY1) * cos(thetaX1)) * lz1; + + double cz1 = (-sin(thetaY1)) * lx1 + + (cos(thetaY1) * sin(thetaX1)) * ly1 + + (cos(thetaY1) * cos(thetaX1)) * lz1; + + double cx2 = (cos(thetaZ2) * cos(thetaY2)) * lx2 + + (-sin(thetaZ2) * cos(thetaX2) + cos(thetaZ2) * sin(thetaY2) * sin(thetaX2)) * ly2 + + (sin(thetaZ2) * sin(thetaX2) + cos(thetaZ2) * sin(thetaY2) * cos(thetaX2)) * lz2; + + double cy2 = (sin(thetaZ2) * cos(thetaY2)) * lx2 + + (cos(thetaZ2) * cos(thetaX2) + sin(thetaX2) * sin(thetaY2) * sin(thetaZ2)) * ly2 + + (-cos(thetaZ2) * sin(thetaX2) + sin(thetaZ2) * sin(thetaY2) * cos(thetaX2)) * lz2; + + double cz2 = (-sin(thetaY2)) * lx2 + + (cos(thetaY2) * sin(thetaX2)) * ly2 + + (cos(thetaY2) * cos(thetaX2)) * lz2; + + answer.resize(12); + answer.at(1) = -stress.at(1); + answer.at(2) = -stress.at(2); + answer.at(3) = -stress.at(3); + answer.at(4) = stress.at(2) * cz1 - stress.at(3) * cy1 - stress.at(4); + answer.at(5) = -stress.at(1) * cz1 + stress.at(3) * cx1 - stress.at(5); + answer.at(6) = stress.at(1) * cy1 - stress.at(2) * cx1 - stress.at(6); + answer.at(7) = stress.at(1); + answer.at(8) = stress.at(2); + answer.at(9) = stress.at(3); + answer.at(10) = stress.at(2) * cz2 - stress.at(3) * cy2 + stress.at(4); + answer.at(11) = -stress.at(1) * cz2 + stress.at(3) * cx2 + stress.at(5); + answer.at(12) = stress.at(1) * cy2 - stress.at(2) * cx2 + stress.at(6); + + + lmatStat->letTempInternalForcesBe(answer); + } +} // end namespace oofem diff --git a/src/sm/Elements/LatticeElements/latticeframe3dnl3.C b/src/sm/Elements/LatticeElements/latticeframe3dnl3.C new file mode 100644 index 000000000..d66212e9a --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticeframe3dnl3.C @@ -0,0 +1,412 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2023 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "latticeframe3dnl3.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "intarray.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "mathfem.h" +#include "latticeframe3d.h" +#include "contextioerr.h" +#include "datastream.h" +#include "classfactory.h" +#include "sm/CrossSections/latticecrosssection.h" +#include "engngm.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" + #include "../sm/Materials/structuralmaterial.h" +#endif + +namespace oofem { + REGISTER_Element(LatticeFrame3dNL3); + + LatticeFrame3dNL3::LatticeFrame3dNL3(int n, Domain *aDomain) : LatticeFrame3d(n, aDomain) + { + numberOfDofMans = 2; + } + + LatticeFrame3dNL3::~LatticeFrame3dNL3() + {} + void + LatticeFrame3dNL3::computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) + //Returns the strain matrix of the receiver. + { + FloatArray u; + TimeStep *tStep = this->domain->giveEngngModel()->giveCurrentStep(); + this->computeVectorOf(VM_Total, tStep, u); + + FloatArray uGlobal(12); + FloatMatrix r(12, 12), rT(12, 12); + computeGtoLRotationMatrix(r); + rT.beTranspositionOf(r); + uGlobal.beProductOf(rT, u); + + FloatArray uROneGlobal(3); + uROneGlobal.at(1) = uGlobal.at(4); + uROneGlobal.at(2) = uGlobal.at(5); + uROneGlobal.at(3) = uGlobal.at(6); + + FloatArray uRTwoGlobal(3); + uRTwoGlobal.at(1) = uGlobal.at(10); + uRTwoGlobal.at(2) = uGlobal.at(11); + uRTwoGlobal.at(3) = uGlobal.at(12); + + //Compute the two rotation matrices in the local coordinate system + FloatMatrix rotationMatrixOne(3, 3), rotationMatrixTwo(3, 3); + ; + computeLocalRotationMatrix(rotationMatrixOne, uROneGlobal); + computeLocalRotationMatrix(rotationMatrixTwo, uRTwoGlobal); + + this->length = computeLength(); + double l1 = this->length * ( 1. + this->s ) / 2; + double l2 = this->length * ( 1. - this->s ) / 2; + LatticeMaterialStatus *lmatStat = dynamic_cast < LatticeMaterialStatus * > ( integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialStatus() ); + + double cx1 = rotationMatrixOne.at(1, 1) * l1; + double cy1 = rotationMatrixOne.at(2, 1) * l1; + double cz1 = rotationMatrixOne.at(3, 1) * l1; + + double cx2 = rotationMatrixTwo.at(1, 1) * l2; + double cy2 = rotationMatrixTwo.at(2, 1) * l2; + double cz2 = rotationMatrixTwo.at(3, 1) * l2; + + answer.resize(6, 12); + //Normal displacement jump in x-direction + //First node + answer.at(1, 1) = -1.; + answer.at(1, 2) = 0.; + answer.at(1, 3) = 0.; + answer.at(1, 4) = 0.; + answer.at(1, 5) = -cz1; + answer.at(1, 6) = cy1; + //Second node + answer.at(1, 7) = 1.; + answer.at(1, 8) = 0.; + answer.at(1, 9) = 0.; + answer.at(1, 10) = 0.; + answer.at(1, 11) = -cz2; + answer.at(1, 12) = cy2; + + //Shear displacement jump in y-plane + //first node + answer.at(2, 1) = 0.; + answer.at(2, 2) = -1.; + answer.at(2, 3) = 0.; + answer.at(2, 4) = cz1; + answer.at(2, 5) = 0; + answer.at(2, 6) = -cx1; + //Second node + answer.at(2, 7) = 0.; + answer.at(2, 8) = 1.; + answer.at(2, 9) = 0.; + answer.at(2, 10) = cz2; + answer.at(2, 11) = 0; + answer.at(2, 12) = -cx2; + + //Shear displacement jump in z-plane + //first node + answer.at(3, 1) = 0.; + answer.at(3, 2) = 0.; + answer.at(3, 3) = -1.; + answer.at(3, 4) = -cy1; + answer.at(3, 5) = cx1; + answer.at(3, 6) = 0.; + //Second node + answer.at(3, 7) = 0.; + answer.at(3, 8) = 0.; + answer.at(3, 9) = 1.; + answer.at(3, 10) = -cy2; + answer.at(3, 11) = cx2; + answer.at(3, 12) = 0.; + + //Rotation around x-axis + //First node + answer.at(4, 1) = 0.; + answer.at(4, 2) = 0; + answer.at(4, 3) = 0.; + answer.at(4, 4) = -1.; + answer.at(4, 5) = 0.; + answer.at(4, 6) = 0.; + //Second node + answer.at(4, 7) = 0.; + answer.at(4, 8) = 0.; + answer.at(4, 9) = 0.; + answer.at(4, 10) = 1.; + answer.at(4, 11) = 0.; + answer.at(4, 12) = 0.; + + //Rotation around y-axis + //First node + answer.at(5, 1) = 0.; + answer.at(5, 2) = 0.; + answer.at(5, 3) = 0.; + answer.at(5, 4) = 0.; + answer.at(5, 5) = -1.; + answer.at(5, 6) = 0.; + //Second node + answer.at(5, 7) = 0.; + answer.at(5, 8) = 0.; + answer.at(5, 9) = 0.; + answer.at(5, 10) = 0.; + answer.at(5, 11) = 1.; + answer.at(5, 12) = 0.; + + //Rotation around z-axis + //First node + answer.at(6, 1) = 0.; + answer.at(6, 2) = 0.; + answer.at(6, 3) = 0.; + answer.at(6, 4) = 0.; + answer.at(6, 5) = 0.; + answer.at(6, 6) = -1.; + //Second node + answer.at(6, 7) = 0.; + answer.at(6, 8) = 0.; + answer.at(6, 9) = 0.; + answer.at(6, 10) = 0.; + answer.at(6, 11) = 0.; + answer.at(6, 12) = 1.; + + return; + } + void + LatticeFrame3dNL3::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) + { + FloatMatrix d, bt, db, b; + FloatArray u; + + this->computeVectorOf(VM_Total, tStep, u); + this->length = computeLength(); + + answer.resize(12, 12); + answer.zero(); + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), b); + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + db.beProductOf(d, b); + db.times(1. / length); + bt.beTranspositionOf(b); + answer.beProductOf(bt, db); + + return; + } + + void LatticeFrame3dNL3::computeLocalRotationMatrix(FloatMatrix &answer, FloatArray &rotation) { + //Use global rotational DOFs to compute rotation matrix. + //The order for the global rotations is first z, then y and finally x. + double thetaX = rotation.at(1); + double thetaY = rotation.at(2); + double thetaZ = rotation.at(3);; + +// +// FloatMatrix globalR(3, 3); +// globalR.at(1, 1) = cos(thetaY) * cos(thetaZ); +// globalR.at(1, 2) = -cos(thetaY) * sin(thetaZ); +// globalR.at(1, 3) = sin(thetaY); +// globalR.at(2, 1) = cos(thetaX) * sin(thetaZ) + sin(thetaX) * sin(thetaY) * cos(thetaZ); +// globalR.at(2, 2) = -sin(thetaX) * sin(thetaY) * sin(thetaZ) + cos(thetaX) * cos(thetaZ); +// globalR.at(2, 3) = -sin(thetaX) * cos(thetaY); +// globalR.at(3, 1) = sin(thetaX) * sin(thetaZ) - cos(thetaX) * sin(thetaY) * cos(thetaZ); +// globalR.at(3, 2) = cos(thetaX) * sin(thetaY) * sin(thetaZ) + sin(thetaX) * cos(thetaZ); +// globalR.at(3, 3) = cos(thetaX) * cos(thetaY); + + FloatMatrix globalR(3, 3); + globalR.at(1, 1) = cos(thetaZ) * cos(thetaY); + globalR.at(1, 2) = - sin(thetaZ)*cos(thetaX) + cos(thetaZ)*sin(thetaY)*sin(thetaX); + globalR.at(1, 3) = sin(thetaZ) * sin(thetaX) + cos(thetaZ) * sin(thetaY) * cos(thetaX); + globalR.at(2, 1) = sin(thetaZ) * cos(thetaY); + globalR.at(2, 2) = cos(thetaZ) * cos(thetaX) + sin(thetaX) * sin(thetaY) * sin(thetaZ); + globalR.at(2, 3) = - cos(thetaZ) * sin(thetaX)+ sin(thetaZ) * sin(thetaY) * cos(thetaX) ; + globalR.at(3, 1) = -sin(thetaY); + globalR.at(3, 2) = cos(thetaY) * sin(thetaX); + globalR.at(3, 3) = cos(thetaY) * cos(thetaX); + + FloatMatrix transform(3, 3), transformT(3, 3), localR(3, 3), help(3, 3); + this->giveLocalCoordinateSystem(transform); + transformT.beTranspositionOf(transform); + + help.beProductOf(globalR, transformT); + answer.beProductOf(transform, help); + + return; + } + + void + LatticeFrame3dNL3::computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) + { + FloatArray u; + this->computeVectorOf(VM_Total, tStep, u); + + FloatArray uGlobal(12); + FloatMatrix r(12, 12), rT(12, 12); + computeGtoLRotationMatrix(r); + rT.beTranspositionOf(r); + uGlobal.beProductOf(rT, u); + + FloatArray uROneGlobal(3); + uROneGlobal.at(1) = uGlobal.at(4); + uROneGlobal.at(2) = uGlobal.at(5); + uROneGlobal.at(3) = uGlobal.at(6); + + FloatArray uRTwoGlobal(3); + uRTwoGlobal.at(1) = uGlobal.at(10); + uRTwoGlobal.at(2) = uGlobal.at(11); + uRTwoGlobal.at(3) = uGlobal.at(12); + + //Compute the two rotation matrices in the local coordinate system + FloatMatrix rotationMatrixOne(3, 3), rotationMatrixTwo(3, 3); + + computeLocalRotationMatrix(rotationMatrixOne, uROneGlobal); + computeLocalRotationMatrix(rotationMatrixTwo, uRTwoGlobal); + + this->length = computeLength(); + double l1 = this->length * ( 1. + this->s ) / 2; + double l2 = this->length * ( 1. - this->s ) / 2; + LatticeMaterialStatus *lmatStat = dynamic_cast < LatticeMaterialStatus * > ( integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialStatus() ); + + double cx1 = rotationMatrixOne.at(1, 1) * l1; + double cy1 = rotationMatrixOne.at(2, 1) * l1; + double cz1 = rotationMatrixOne.at(3, 1) * l1; + + double cx2 = rotationMatrixTwo.at(1, 1) * l2; + double cy2 = rotationMatrixTwo.at(2, 1) * l2; + double cz2 = rotationMatrixTwo.at(3, 1) * l2; + + // + answer.resize(6); + answer.at(1) = u.at(7) - u.at(1) - cx2 - cx1 + l1 + l2; + answer.at(2) = u.at(8) - u.at(2) - cy2 - cy1; + answer.at(3) = u.at(9) - u.at(3) - cz2 - cz1; + answer.at(4) = u.at(10) - u.at(4); + answer.at(5) = u.at(11) - u.at(5); + answer.at(6) = u.at(12) - u.at(6); + answer.times(1. / this->length); + } + + + bool + LatticeFrame3dNL3::computeGtoLComponentTransformationMatrix(FloatMatrix &answer) + { + FloatMatrix lcs; + answer.resize(3, 3); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + } + } + + return 1; + } + + + void + LatticeFrame3dNL3::giveInternalForcesVector(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) + { + FloatMatrix b, bt, bf, d; + FloatArray u, stress, strain; + this->computeVectorOf(VM_Total, tStep, u); + + GaussPoint *gp = this->integrationRulesArray [ 0 ]->getIntegrationPoint(0); + + this->computeStrainVector(strain, gp, tStep); + this->computeStressVector(stress, strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + LatticeMaterialStatus *lmatStat = dynamic_cast < LatticeMaterialStatus * > ( integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialStatus() ); + + + FloatArray uGlobal(12); + FloatMatrix r(12, 12), rT(12, 12); + computeGtoLRotationMatrix(r); + rT.beTranspositionOf(r); + uGlobal.beProductOf(rT, u); + + FloatArray uROneGlobal(3); + uROneGlobal.at(1) = uGlobal.at(4); + uROneGlobal.at(2) = uGlobal.at(5); + uROneGlobal.at(3) = uGlobal.at(6); + + FloatArray uRTwoGlobal(3); + uRTwoGlobal.at(1) = uGlobal.at(10); + uRTwoGlobal.at(2) = uGlobal.at(11); + uRTwoGlobal.at(3) = uGlobal.at(12); + + //Compute the two rotation matrices in the local coordinate system + FloatMatrix rotationMatrixOne(3, 3), rotationMatrixTwo(3, 3); + ; + computeLocalRotationMatrix(rotationMatrixOne, uROneGlobal); + computeLocalRotationMatrix(rotationMatrixTwo, uRTwoGlobal); + + this->length = computeLength(); + double l1 = this->length * ( 1. + this->s ) / 2; + double l2 = this->length * ( 1. - this->s ) / 2; + + double cx1 = rotationMatrixOne.at(1, 1) * l1; + double cy1 = rotationMatrixOne.at(2, 1) * l1; + double cz1 = rotationMatrixOne.at(3, 1) * l1; + + double cx2 = rotationMatrixTwo.at(1, 1) * l2; + double cy2 = rotationMatrixTwo.at(2, 1) * l2; + double cz2 = rotationMatrixTwo.at(3, 1) * l2; + + answer.resize(12); + answer.at(1) = -stress.at(1); + answer.at(2) = -stress.at(2); + answer.at(3) = -stress.at(3); + answer.at(4) = stress.at(2) * cz1 - stress.at(3) * cy1 - stress.at(4); + answer.at(5) = -stress.at(1) * cz1 + stress.at(3) * cx1 - stress.at(5); + answer.at(6) = stress.at(1) * cy1 - stress.at(2) * cx1 - stress.at(6); + answer.at(7) = stress.at(1); + answer.at(8) = stress.at(2); + answer.at(9) = stress.at(3); + answer.at(10) = stress.at(2) * cz2 - stress.at(3) * cy2 + stress.at(4); + answer.at(11) = -stress.at(1) * cz2 + stress.at(3) * cx2 + stress.at(5); + answer.at(12) = stress.at(1) * cy2 - stress.at(2) * cx2 + stress.at(6); + + lmatStat->letTempInternalForcesBe(answer); + } +} // end namespace oofem diff --git a/src/sm/Elements/LatticeElements/latticelink3d.C b/src/sm/Elements/LatticeElements/latticelink3d.C new file mode 100644 index 000000000..6decea5b1 --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticelink3d.C @@ -0,0 +1,565 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "../sm/Elements/LatticeElements/latticelink3d.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "../sm/Elements/LatticeElements/latticestructuralelement.h" +#include "contextioerr.h" +#include "datastream.h" +#include "classfactory.h" +#include "../sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/latticecrosssection.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { +REGISTER_Element(LatticeLink3d); + +LatticeLink3d :: LatticeLink3d(int n, Domain *aDomain) : LatticeStructuralElement(n, aDomain) +{ + numberOfDofMans = 2; + geometryFlag = 0; +} + +LatticeLink3d :: ~LatticeLink3d() +{} + +double +LatticeLink3d :: computeVolumeAround(GaussPoint *aGaussPoint) +{ + //Returns artifical volume (bond area times bond length) so that general parts of post processing work + return pow(this->bondLength, 2.) * this->bondDiameter * M_PI; +} + + +void +LatticeLink3d :: computeBmatrixAt(GaussPoint *aGaussPoint, FloatMatrix &answer, int li, int ui) +// Returns the strain matrix of the receiver. +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + //Assemble Bmatrix based on three rigid arm components + //rigid.at(1) (tangential), rigid.at(2) (lateral), rigid.at(3) (lateral) + answer.resize(6, 12); + answer.zero(); + + //Normal displacement jump in x-direction + //First node + answer.at(1, 1) = -1.; + answer.at(1, 5) = -this->rigid.at(3); + answer.at(1, 6) = this->rigid.at(2); + //Second node + answer.at(1, 7) = 1.; + + //Shear displacement jump in y-plane + //first node + answer.at(2, 2) = -1.; + answer.at(2, 4) = this->rigid.at(3); + answer.at(2, 6) = -this->rigid.at(1); + //Second node + answer.at(2, 8) = 1.; + + //Shear displacement jump in z-plane + //first node + answer.at(3, 3) = -1.; + answer.at(3, 4) = -this->rigid.at(2); + answer.at(3, 5) = this->rigid.at(1); + //Second node + answer.at(3, 9) = 1.; + + //Rotation around x-axis + //First node + answer.at(4, 4) = -1.; + //Second node + answer.at(4, 10) = 1.; + + //Rotation around y-axis + //First node + answer.at(5, 5) = -1.; + //Second node + answer.at(5, 11) = 1.; + + //Rotation around z-axis + //First node + answer.at(6, 6) = -1.; + //Second node + answer.at(6, 12) = 1.; + + return; +} + +void +LatticeLink3d :: giveGPCoordinates(FloatArray &coords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + coords.resize(3); + coords = this->globalCentroid; + return; +} + + +void +LatticeLink3d :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + FloatMatrix d, b, bt, db; + FloatArray u, strain; + + // This function can be quite costly to do inside the loops when one has many slave dofs. + this->computeVectorOf(VM_Total, tStep, u); + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + // zero answer will resize accordingly when adding first contribution + answer.clear(); + + + GaussPoint *gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); + this->computeBmatrixAt(gp, b); + bt.beTranspositionOf(b); + + if ( !this->isActivated(tStep) ) { + strain.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); + strain.zero(); + } + strain.beProductOf(b, u); + + + answer.resize(12, 12); + answer.zero(); + + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + + db.beProductOf(d, b); + answer.beProductOf(bt, db); + + //Introduce integration of bond strength + double area = this->computeVolumeAround(gp) / this->giveLength(); + answer.times(area); + + return; +} + +void LatticeLink3d :: computeGaussPoints() +// Sets up the array of Gauss Points of the receiver. +{ + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ].reset(new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ]->SetUpPointsOnLine(1, _3dLattice); +} + + + + +bool +LatticeLink3d :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + int i, j; + + answer.resize(12, 12); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( i = 1; i <= 3; i++ ) { + for ( j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + answer.at(i + 6, j + 6) = lcs.at(i, j); + answer.at(i + 9, j + 9) = lcs.at(i, j); + } + } + + return 1; +} + + +int +LatticeLink3d :: giveLocalCoordinateSystem(FloatMatrix &answer) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer = this->localCoordinateSystem; + + return 1; +} + +double +LatticeLink3d :: giveBondLength() +{ + return this->bondLength; +} + +double +LatticeLink3d :: giveBondEndLength() +{ + return this->bondEndLength; +} + + +double +LatticeLink3d :: giveBondDiameter() +{ + return this->bondDiameter; +} + + + + +void +LatticeLink3d :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = { + D_u, D_v, D_w, R_u, R_v, R_w + }; +} + +void +LatticeLink3d :: initializeFrom(InputRecord &ir) +{ + // first call parent + LatticeStructuralElement :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, this->bondLength, _IFT_LatticeLink3d_length); + + IR_GIVE_FIELD(ir, this->bondDiameter, _IFT_LatticeLink3d_diameter); + + IR_GIVE_FIELD(ir, this->directionVector, _IFT_LatticeLink3d_dirvector); + + IR_GIVE_FIELD(ir, this->bondEndLength, _IFT_LatticeLink3d_l_end); +} + + +int +LatticeLink3d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer.resize(3); + answer = this->globalCentroid; + + return 1; +} + + +void +LatticeLink3d :: computeGeometryProperties() +{ + //coordinates of the two nodes + Node *nodeA, *nodeB; + FloatArray coordsA(3), coordsB(3); + + //Order of nodes. However, might not matter. + //Reinforcement node + nodeA = this->giveNode(1); + //Lattice node + nodeB = this->giveNode(2); + + //Calculate components of distance from reinforcement node to lattice node. + + for ( int i = 0; i < 3; i++ ) { + coordsA.at(i + 1) = nodeA->giveCoordinate(i + 1); + coordsB.at(i + 1) = nodeB->giveCoordinate(i + 1); + } + + FloatArray rigidGlobal(3); + + //Calculate normal vector + for ( int i = 0; i < 3; i++ ) { + rigidGlobal.at(i + 1) = coordsB.at(i + 1) - coordsA.at(i + 1); + } + + //Construct an initial temporary local coordinate system + FloatArray normal(3), s(3), t(3); + + //Calculate normal vector + normal = this->directionVector; + normal.normalize(); + + //Construct two perpendicular axis so that n is normal to the plane which they create + //Check, if one of the components of the normal-direction is zero + if ( normal.at(1) == 0 ) { + s.at(1) = 0.; + s.at(2) = normal.at(3); + s.at(3) = -normal.at(2); + } else if ( normal.at(2) == 0 ) { + s.at(1) = normal.at(3); + s.at(2) = 0.; + s.at(3) = -normal.at(1); + } else { + s.at(1) = normal.at(2); + s.at(2) = -normal.at(1); + s.at(3) = 0.; + } + + s.normalize(); + + t.beVectorProductOf(normal, s); + t.normalize(); + + //Set up rotation matrix + FloatMatrix lcs(3, 3); + + this->localCoordinateSystem.resize(3, 3); + this->localCoordinateSystem.zero(); + + for ( int i = 1; i <= 3; i++ ) { + this->localCoordinateSystem.at(1, i) = normal.at(i); + this->localCoordinateSystem.at(2, i) = s.at(i); + this->localCoordinateSystem.at(3, i) = t.at(i); + } + + // Rotate rigidarm vector into local coordinate system + this->rigid.beProductOf(localCoordinateSystem, rigidGlobal); + + this->globalCentroid.resize(3); + for ( int i = 1; i <= 3; i++ ) { + this->globalCentroid.at(i) = nodeA->giveCoordinate(i); + ; + } + + this->geometryFlag = 1; + + return; +} +void +LatticeLink3d :: saveContext(DataStream &stream, ContextMode mode) +{ + LatticeStructuralElement :: saveContext(stream, mode); +} + + +void +LatticeLink3d :: restoreContext(DataStream &stream, ContextMode mode) +{ + LatticeStructuralElement :: restoreContext(stream, mode); +} + + +void +LatticeLink3d :: giveInternalForcesVector(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) +{ + FloatMatrix b, bt; + FloatArray u, stress(6), strain(6); + + // This function can be quite costly to do inside the loops when one has many slave dofs. + this->computeVectorOf(VM_Total, tStep, u); + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + // zero answer will resize accordingly when adding first contribution + answer.clear(); + + for ( GaussPoint *gp: * this->giveDefaultIntegrationRulePtr() ) { + LatticeMaterialStatus *matStat = static_cast< LatticeMaterialStatus * >( gp->giveMaterialStatus() ); + this->computeBmatrixAt(gp, b); + bt.beTranspositionOf(b); + + if ( useUpdatedGpRecord == 1 ) { + stress = matStat->giveLatticeStress(); + } else { + if ( !this->isActivated(tStep) ) { + strain.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); + strain.zero(); + } + strain.beProductOf(b, u); + this->computeStressVector(stress, strain, gp, tStep); + } + + // updates gp stress and strain record acording to current + // increment of displacement + if ( stress.giveSize() == 0 ) { + break; + } + + // now every gauss point has real stress vector + // compute nodal representation of internal forces using f = B^T*Sigma dV + // double dV = this->computeVolumeAround(gp); + // double dV = 1.; + if ( stress.giveSize() == 6 ) { + // It may happen that e.g. plane strain is computed + // using the default 3D implementation. If so, + // the stress needs to be reduced. + // (Note that no reduction will take place if + // the simulation is actually 3D.) + FloatArray stressTemp; + StructuralMaterial :: giveReducedSymVectorForm(stressTemp, stress, gp->giveMaterialMode() ); + + answer.beProductOf(bt, stressTemp); + } else { + answer.beProductOf(bt, stress); + } + + //Introduce integration of bond strength + double area = this->computeVolumeAround(gp) / this->giveLength(); + answer.times(area); + } + + + // if inactive update state, but no contribution to global system + if ( !this->isActivated(tStep) ) { + answer.zero(); + return; + } +} + + +double +LatticeLink3d :: giveLength() +{ + //returns the bond length, not the length between the two nodes + return this->bondLength; +} + +void +LatticeLink3d :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->give3dStiffnessMatrix(rMode, gp, tStep); +} + +void +LatticeLink3d :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +{ + answer = static_cast< LatticeCrossSection * >( this->giveCrossSection() )->giveLatticeStress3d(strain, gp, tStep); +} + + + +#ifdef __OOFEG + +void +LatticeLink3d :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + } else if ( mode == OGC_deformedGeometry ) { + this->drawDeformedGeometry(gc, tStep, DisplacementVector); + } else if ( mode == OGC_eigenVectorGeometry ) { + this->drawDeformedGeometry(gc, tStep, EigenVector); + } else if ( mode == OGC_scalarPlot ) { + this->drawScalar(gc, tStep); + } else if ( mode == OGC_elemSpecial ) { + this->drawSpecial(gc, tStep); + } else { + OOFEM_ERROR("unsupported mode"); + } +} + + + +void LatticeLink3d :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + WCRec p [ 2 ]; /* points */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getElementColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + +void LatticeLink3d :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ + GraphicObj *go; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + double defScale = gc.getDefScale(); + + WCRec p [ 2 ]; /* points */ + + EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveUpdatedCoordinate(3, tStep, defScale); + + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(1, tStep, defScale); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(2, tStep, defScale); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveUpdatedCoordinate(3, tStep, defScale); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EMAddGraphicsToModel(ESIModel(), go); +} + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/LatticeElements/latticelink3d.h b/src/sm/Elements/LatticeElements/latticelink3d.h new file mode 100644 index 000000000..a86560af2 --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticelink3d.h @@ -0,0 +1,129 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticelink3d_h +#define latticelink3d_h + +#include "latticestructuralelement.h" + +///@name Input fields for LatticeLink3d +//@{ +#define _IFT_LatticeLink3d_Name "latticelink3d" +#define _IFT_LatticeLink3d_length "length" +#define _IFT_LatticeLink3d_diameter "diameter" +#define _IFT_LatticeLink3d_dirvector "dirvector" +#define _IFT_LatticeLink3d_l_end "l_end" +//@} + +namespace oofem { +/** + * This class implements a 3-dimensional lattice element + */ + +class LatticeLink3d : public LatticeStructuralElement +{ +protected: + double bondLength; + + FloatMatrix localCoordinateSystem; + double bondDiameter; + FloatArray directionVector; + int geometryFlag; + double bondEndLength; + FloatArray rigid; + FloatArray globalCentroid; + +public: + LatticeLink3d(int n, Domain *); + virtual ~LatticeLink3d(); + + double computeVolumeAround(GaussPoint *aGaussPoint) override; + + double giveLength() override; + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + double giveBondLength() override; + + double giveBondDiameter() override; + + double giveBondEndLength() override; + + int computeNumberOfDofs() override { return 12; } + + void giveDofManDofIDMask(int inode, IntArray &) const override; + + virtual void giveGPCoordinates(FloatArray &coords); + + virtual void computeGeometryProperties(); + + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + + const char *giveInputRecordName() const override { return _IFT_LatticeLink3d_Name; } + const char *giveClassName() const override { return "LatticeLink3d"; } + void initializeFrom(InputRecord &ir) override; + + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; + +#ifdef __OOFEG + void drawYourself(oofegGraphicContext &context, TimeStep *tStep) override; + void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &, TimeStep *tStep, UnknownType) override; +#endif + + +protected: + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + bool computeGtoLRotationMatrix(FloatMatrix &) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + + + /** + * This computes the geometrical properties of the element. It is called only once. + */ + void computePropertiesOfCrossSection(); + + void computeGaussPoints() override; + integrationDomain giveIntegrationDomain() const override { return _Line; } +}; +} // end namespace oofem +#endif diff --git a/src/sm/Elements/LatticeElements/latticelink3dboundary.C b/src/sm/Elements/LatticeElements/latticelink3dboundary.C new file mode 100644 index 000000000..291b2cc20 --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticelink3dboundary.C @@ -0,0 +1,713 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "domain.h" +#include "../sm/Elements/LatticeElements/latticelink3dboundary.h" +#include "../sm/Materials/LatticeMaterials/latticematstatus.h" +#include "node.h" +#include "material.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "intarray.h" +#include "floatarray.h" +#include "mathfem.h" +#include "../sm/Elements/LatticeElements/latticestructuralelement.h" +#include "classfactory.h" +#include "../sm/Materials/structuralmaterial.h" +#include "contextioerr.h" +#include "datastream.h" +#include "crosssection.h" +#include "dof.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { +REGISTER_Element(LatticeLink3dBoundary); + +LatticeLink3dBoundary :: LatticeLink3dBoundary(int n, Domain *aDomain) : LatticeLink3d(n, aDomain) +{ + numberOfDofMans = 3; + geometryFlag = 0; +} + +LatticeLink3dBoundary :: ~LatticeLink3dBoundary() +{} + + +void +LatticeLink3dBoundary :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, + TimeStep *tStep) +// Computes numerically the stiffness matrix of the receiver. +{ + FloatMatrix d, bi, bj, dbj, dij, bjt; + FloatMatrix t(12, 18), tt; + FloatMatrix answerTemp(12, 12), answerHelp, ttk(18, 12); + bool matStiffSymmFlag = this->giveCrossSection()->isCharacteristicMtrxSymmetric(rMode); + answerTemp.zero(); + answerHelp.zero(); + t.zero(); + + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), bj); + this->computeConstitutiveMatrixAt(d, rMode, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + dbj.beProductOf(d, bj); + bjt.beTranspositionOf(bj); + answerTemp.beProductOf(bjt, dbj); + + answer.resize(computeNumberOfDofs(), computeNumberOfDofs() ); + answer.zero(); + + answerHelp.resize(computeNumberOfDofs(), computeNumberOfDofs() ); + answerHelp.zero(); + + for ( int m = 1; m <= 12; m++ ) { + for ( int k = 1; k <= 12; k++ ) { + answer.at(m, k) = answerTemp.at(m, k); + } + } + + if ( matStiffSymmFlag ) { + answer.symmetrized(); + } + + // Rotate to global system add the projections and rotate back to local system. + + FloatMatrix R; + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R); + } + + for ( int m = 1; m <= 12; m++ ) { + for ( int k = 1; k <= 12; k++ ) { + answerTemp.at(m, k) = answer.at(m, k); + } + } + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + for ( int k = 1; k <= 12; k++ ) { + t.at(k, k) = 1.; + } + t.at(1, 13) = projectionComponentNodeOne.at(1); + t.at(2, 14) = projectionComponentNodeOne.at(2); + t.at(3, 15) = projectionComponentNodeOne.at(3); + + + t.at(2, 16) = projectionComponentNodeOne.at(3); + t.at(1, 17) = projectionComponentNodeOne.at(3); + t.at(1, 18) = projectionComponentNodeOne.at(2); + + + t.at(7, 13) = projectionComponentNodeTwo.at(1); + t.at(8, 14) = projectionComponentNodeTwo.at(2); + t.at(9, 15) = projectionComponentNodeTwo.at(3); + + t.at(8, 16) = projectionComponentNodeTwo.at(3); + t.at(7, 17) = projectionComponentNodeTwo.at(3); + t.at(7, 18) = projectionComponentNodeTwo.at(2); + + + tt.beTranspositionOf(t); + + ttk.beProductOf(tt, answerTemp); + answer.beProductOf(ttk, t); + + //Rotate back to local system + FloatMatrix Rtranspose; + Rtranspose.beTranspositionOf(R); + answer.rotatedWith(Rtranspose); + + return; +} + +void +LatticeLink3dBoundary :: recalculateCoordinates(int nodeNumber, FloatArray &coords) { + coords.resize(3); + coords.zero(); + Node *node; + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray projectionComponent(3); + projectionComponent.zero(); + + if ( nodeNumber == 1 ) { + node = this->giveNode(1); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponent, location.at(1) ); + } + } else if ( nodeNumber == 2 ) { + node = this->giveNode(2); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponent, location.at(2) ); + } + } else { + OOFEM_ERROR("wrong element used in the vtk module"); + } + + for ( int i = 0; i < 3; i++ ) { + coords.at(i + 1) = node->giveCoordinate(i + 1) + projectionComponent.at(i + 1) * specimenDimension.at(i + 1); + } + return; +} + +void +LatticeLink3dBoundary :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *stepN) +// Computes the vector containing the strains at the Gauss point gp of +// the receiver, at time step stepN. The nature of these strains depends +// on the element's type. +{ + FloatMatrix b; + FloatArray u; + + + //Compute strain vector + //Get the 18 components of the displacement vector of this element + this->computeVectorOf(VM_Total, stepN, u); + this->computeBmatrixAt(gp, b); + + + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + //Compute projection vector + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + FloatMatrix rotationMatrix; + if ( this->computeGtoLRotationMatrix(rotationMatrix) ) { + u.rotatedWith(rotationMatrix, 't'); + } + + //General expressions for the corrected displacements. Rotations at nodes are not influenced. Only translations + u.at(1) = u.at(1) + projectionComponentNodeOne.at(1) * u.at(13) + projectionComponentNodeOne.at(2) * u.at(18) + projectionComponentNodeOne.at(3) * u.at(17); + u.at(2) = u.at(2) + projectionComponentNodeOne.at(2) * u.at(14) + projectionComponentNodeOne.at(3) * u.at(16); + u.at(3) = u.at(3) + projectionComponentNodeOne.at(3) * u.at(15); + + u.at(7) = u.at(7) + projectionComponentNodeTwo.at(1) * u.at(13) + projectionComponentNodeTwo.at(2) * u.at(18) + projectionComponentNodeTwo.at(3) * u.at(17); + u.at(8) = u.at(8) + projectionComponentNodeTwo.at(2) * u.at(14) + projectionComponentNodeTwo.at(3) * u.at(16); + u.at(9) = u.at(9) + projectionComponentNodeTwo.at(3) * u.at(15); + + + if ( this->computeGtoLRotationMatrix(rotationMatrix) ) { + u.rotatedWith(rotationMatrix, 'n'); + } + //define a temp displacement vector + FloatArray uTemp(12); + + for ( int i = 1; i <= 12; i++ ) { + uTemp.at(i) = u.at(i); + } + + answer.beProductOf(b, uTemp); +} + +bool +LatticeLink3dBoundary :: computeGtoLRotationMatrix(FloatMatrix &answer) +{ + FloatMatrix lcs; + int i, j; + + answer.resize(18, 18); + answer.zero(); + + this->giveLocalCoordinateSystem(lcs); + for ( i = 1; i <= 3; i++ ) { + for ( j = 1; j <= 3; j++ ) { + answer.at(i, j) = lcs.at(i, j); + answer.at(i + 3, j + 3) = lcs.at(i, j); + answer.at(i + 6, j + 6) = lcs.at(i, j); + answer.at(i + 9, j + 9) = lcs.at(i, j); + } + } + answer.at(13, 13) = 1.; + answer.at(14, 14) = 1.; + answer.at(15, 15) = 1.; + answer.at(16, 16) = 1.; + answer.at(17, 17) = 1.; + answer.at(18, 18) = 1.; + + return 1; +} + +int +LatticeLink3dBoundary :: giveLocalCoordinateSystem(FloatMatrix &answer) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer = this->localCoordinateSystem; + + return 1; +} + + +void +LatticeLink3dBoundary :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode == 3 ) { + answer = { E_xx, E_yy, E_zz, G_yz, G_xz, G_xy }; + } else { + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; + } +} + +void +LatticeLink3dBoundary :: initializeFrom(InputRecord &ir) +{ + LatticeLink3d :: initializeFrom(ir); + + location.resize(2); + IR_GIVE_FIELD(ir, location, _IFT_LatticeLink3dBoundary_location); // Macro + +} + + + +void +LatticeLink3dBoundary :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + Material *mat = this->giveMaterial(); + + FloatMatrix b, bt, A, R, GNT; + FloatArray bs, TotalStressVector, u, strain; + + this->computeVectorOf(VM_Total, tStep, u); + + // subtract initial displacements, if defined + if ( initialDisplacements ) { + u.subtract(* initialDisplacements); + } + + answer.resize(18); + answer.zero(); + + this->computeBmatrixAt(integrationRulesArray [ 0 ]->getIntegrationPoint(0), b); + + bt.beTranspositionOf(b); + if ( useUpdatedGpRecord == 1 ) { + TotalStressVector = ( ( StructuralMaterialStatus * ) mat->giveStatus(integrationRulesArray [ 0 ]->getIntegrationPoint(0) ) ) + ->giveStressVector(); + } else + if ( !this->isActivated(tStep) ) { + strain.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(integrationRulesArray [ 0 ]->getIntegrationPoint(0)->giveMaterialMode() ) ); + strain.zero(); + } + this->computeStrainVector(strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + this->computeStressVector(TotalStressVector, strain, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep); + + bs.beProductOf(bt, TotalStressVector); + + for ( int m = 1; m <= 12; m++ ) { + answer.at(m) = bs.at(m); + } + + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R, 't'); + } + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + //Normal stresses + answer.at(13) = projectionComponentNodeOne.at(1) * answer.at(1) + projectionComponentNodeTwo.at(1) * answer.at(7); + answer.at(14) = projectionComponentNodeOne.at(2) * answer.at(2) + projectionComponentNodeTwo.at(2) * answer.at(8); + answer.at(15) = projectionComponentNodeOne.at(3) * answer.at(3) + projectionComponentNodeTwo.at(3) * answer.at(9); + + //Shear stresses + answer.at(16) = projectionComponentNodeOne.at(3) * answer.at(2) + projectionComponentNodeTwo.at(3) * answer.at(8); + answer.at(17) = projectionComponentNodeOne.at(3) * answer.at(1) + projectionComponentNodeTwo.at(3) * answer.at(7); + answer.at(18) = projectionComponentNodeOne.at(2) * answer.at(1) + projectionComponentNodeTwo.at(2) * answer.at(7); + + //Rotate to local system + if ( this->giveRotationMatrix(R) ) { + answer.rotatedWith(R, 'n'); + } + + return; +} + +void +LatticeLink3dBoundary :: giveSwitches(IntArray &answer, int location) { + int counter = 1; + for ( int x = -1; x < 2; x++ ) { + for ( int y = -1; y < 2; y++ ) { + for ( int z = -1; z < 2; z++ ) { + if ( !( z == 0 && y == 0 && x == 0 ) ) { + if ( counter == location ) { + answer(0) = x; + answer(1) = y; + answer(2) = z; + } + counter++; + } + } + } + } + return; +} + +void +LatticeLink3dBoundary :: computeGeometryProperties() +{ + Node *nodeA, *nodeB; + + FloatArray coordsA(3); + FloatArray coordsB(3); + + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + for ( int i = 0; i < 3; i++ ) { + coordsA.at(i + 1) = nodeA->giveCoordinate(i + 1) + projectionComponentNodeOne.at(i + 1) * specimenDimension.at(i + 1); + coordsB.at(i + 1) = nodeB->giveCoordinate(i + 1) + projectionComponentNodeTwo.at(i + 1) * specimenDimension.at(i + 1); + } + + //From here on the normal functions should be valid + + FloatArray rigidGlobal(3); + + //Calculate normal vector + for ( int i = 0; i < 3; i++ ) { + rigidGlobal.at(i + 1) = coordsB.at(i + 1) - coordsA.at(i + 1); + } + + //Construct an initial temporary local coordinate system + FloatArray normal(3), s(3), t(3); + + //Calculate normal vector + normal = this->directionVector; + normal.normalize(); + + //Construct two perpendicular axis so that n is normal to the plane which they create + //Check, if one of the components of the normal-direction is zero + if ( normal.at(1) == 0 ) { + s.at(1) = 0.; + s.at(2) = normal.at(3); + s.at(3) = -normal.at(2); + } else if ( normal.at(2) == 0 ) { + s.at(1) = normal.at(3); + s.at(2) = 0.; + s.at(3) = -normal.at(1); + } else { + s.at(1) = normal.at(2); + s.at(2) = -normal.at(1); + s.at(3) = 0.; + } + + s.normalize(); + + t.beVectorProductOf(normal, s); + t.normalize(); + + //Set up rotation matrix + FloatMatrix lcs(3, 3); + + this->localCoordinateSystem.resize(3, 3); + this->localCoordinateSystem.zero(); + + for ( int i = 1; i <= 3; i++ ) { + this->localCoordinateSystem.at(1, i) = normal.at(i); + this->localCoordinateSystem.at(2, i) = s.at(i); + this->localCoordinateSystem.at(3, i) = t.at(i); + } + + // Rotate rigidarm vector into local coordinate system + + this->rigid.beProductOf(localCoordinateSystem, rigidGlobal); + + this->globalCentroid.resize(3); + for ( int i = 1; i <= 3; i++ ) { + this->globalCentroid.at(i) = coordsA.at(i); + } + + this->geometryFlag = 1; + + return; +} + + +void +LatticeLink3dBoundary :: saveContext(DataStream &stream, ContextMode mode) +{ + LatticeLink3d :: saveContext(stream, mode); + + contextIOResultType iores; + + if ( ( mode & CM_Definition ) ) { + if ( ( iores = location.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + } +} + + + +void +LatticeLink3dBoundary :: restoreContext(DataStream &stream, ContextMode mode) +{ + contextIOResultType iores; + + LatticeLink3d :: restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( ( iores = this->location.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + } +} + + + +#ifdef __OOFEG + +void +LatticeLink3dBoundary :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + } else if ( mode == OGC_deformedGeometry ) { + this->drawDeformedGeometry(gc, tStep, DisplacementVector); + } else if ( mode == OGC_elemSpecial ) { + this->drawSpecial(gc, tStep); + } else { + OOFEM_ERROR("drawYourself : unsupported mode"); + } +} + + + + +void LatticeLink3dBoundary :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + WCRec p [ 2 ]; /* points */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getActiveCrackColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + //Compute projection vector + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1) + projectionComponentNodeOne.at(1) * specimenDimension.at(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2) + projectionComponentNodeOne.at(2) * specimenDimension.at(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3) + projectionComponentNodeOne.at(3) * specimenDimension.at(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1) + projectionComponentNodeTwo.at(1) * specimenDimension.at(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2) + projectionComponentNodeTwo.at(2) * specimenDimension.at(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3) + projectionComponentNodeTwo.at(3) * specimenDimension.at(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + +void LatticeLink3dBoundary :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +{ + GraphicObj *go; + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + double defScale = gc.getDefScale(); + + WCRec p [ 2 ]; /* points */ + + EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); + + FloatArray specimenDimension(3); + specimenDimension.at(1) = this->giveNode(3)->giveCoordinate(1); + specimenDimension.at(2) = this->giveNode(3)->giveCoordinate(2); + specimenDimension.at(3) = this->giveNode(3)->giveCoordinate(3); + + FloatArray dispOne(6); + dispOne.at(1) = this->giveNode(1)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispOne.at(2) = this->giveNode(1)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispOne.at(3) = this->giveNode(1)->giveDofWithID(D_w)->giveUnknown(VM_Total, tStep); + dispOne.at(4) = this->giveNode(1)->giveDofWithID(R_u)->giveUnknown(VM_Total, tStep); + dispOne.at(5) = this->giveNode(1)->giveDofWithID(R_v)->giveUnknown(VM_Total, tStep); + dispOne.at(6) = this->giveNode(1)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + FloatArray dispTwo(6); + dispTwo.at(1) = this->giveNode(2)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispTwo.at(2) = this->giveNode(2)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispTwo.at(3) = this->giveNode(2)->giveDofWithID(D_w)->giveUnknown(VM_Total, tStep); + dispTwo.at(4) = this->giveNode(2)->giveDofWithID(R_u)->giveUnknown(VM_Total, tStep); + dispTwo.at(5) = this->giveNode(2)->giveDofWithID(R_v)->giveUnknown(VM_Total, tStep); + dispTwo.at(6) = this->giveNode(2)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + FloatArray dispThree(6); + dispThree.at(1) = this->giveNode(3)->giveDofWithID(D_u)->giveUnknown(VM_Total, tStep); + dispThree.at(2) = this->giveNode(3)->giveDofWithID(D_v)->giveUnknown(VM_Total, tStep); + dispThree.at(3) = this->giveNode(3)->giveDofWithID(D_w)->giveUnknown(VM_Total, tStep); + dispThree.at(4) = this->giveNode(3)->giveDofWithID(R_u)->giveUnknown(VM_Total, tStep); + dispThree.at(5) = this->giveNode(3)->giveDofWithID(R_v)->giveUnknown(VM_Total, tStep); + dispThree.at(6) = this->giveNode(3)->giveDofWithID(R_w)->giveUnknown(VM_Total, tStep); + + IntArray projectionComponentNodeOne(3); + projectionComponentNodeOne.zero(); + if ( location.at(1) != 0 ) { + giveSwitches(projectionComponentNodeOne, location.at(1) ); + } + + IntArray projectionComponentNodeTwo(3); + projectionComponentNodeTwo.zero(); + if ( location.at(2) != 0 ) { + giveSwitches(projectionComponentNodeTwo, location.at(2) ); + } + + + //Modify dispOne and dispTwo + dispOne.at(1) = dispOne.at(1) + projectionComponentNodeOne.at(1) * dispThree.at(1) + projectionComponentNodeOne.at(2) * dispThree.at(4) + projectionComponentNodeOne.at(3) * dispThree.at(5); + dispOne.at(2) = dispOne.at(2) + projectionComponentNodeOne.at(2) * dispThree.at(2) + projectionComponentNodeOne.at(3) * dispThree.at(6); + dispOne.at(3) = dispOne.at(3) + projectionComponentNodeOne.at(3) * dispThree.at(3); + + + dispTwo.at(1) = dispTwo.at(1) + projectionComponentNodeTwo.at(1) * dispThree.at(1) + projectionComponentNodeTwo.at(2) * dispThree.at(4) + projectionComponentNodeTwo.at(3) * dispThree.at(5); + dispTwo.at(2) = dispTwo.at(2) + projectionComponentNodeTwo.at(2) * dispThree.at(2) + projectionComponentNodeTwo.at(3) * dispThree.at(6); + dispTwo.at(3) = dispTwo.at(3) + projectionComponentNodeTwo.at(3) * dispThree.at(3); + + double x1, y1, z1, x2, y2, z2; + x1 = this->giveNode(1)->giveCoordinate(1) + projectionComponentNodeOne.at(1) * specimenDimension.at(1); + y1 = this->giveNode(1)->giveCoordinate(2) + projectionComponentNodeOne.at(2) * specimenDimension.at(2); + z1 = this->giveNode(1)->giveCoordinate(3) + projectionComponentNodeOne.at(3) * specimenDimension.at(3); + + x2 = this->giveNode(2)->giveCoordinate(1) + projectionComponentNodeTwo.at(1) * specimenDimension.at(1); + y2 = this->giveNode(2)->giveCoordinate(2) + projectionComponentNodeTwo.at(2) * specimenDimension.at(2); + z2 = this->giveNode(2)->giveCoordinate(3) + projectionComponentNodeTwo.at(3) * specimenDimension.at(3); + + p [ 0 ].x = ( FPNum ) x1 + defScale * dispOne.at(1); + p [ 0 ].y = ( FPNum ) y1 + defScale * dispOne.at(2); + p [ 0 ].z = ( FPNum ) z1 + defScale * dispOne.at(3); + + p [ 1 ].x = ( FPNum ) x2 + defScale * dispTwo.at(1); + p [ 1 ].y = ( FPNum ) y2 + defScale * dispTwo.at(2); + p [ 1 ].z = ( FPNum ) z2 + defScale * dispTwo.at(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EMAddGraphicsToModel(ESIModel(), go); +} + +#endif +} // end namespace oofem diff --git a/src/sm/Elements/LatticeElements/latticelink3dboundary.h b/src/sm/Elements/LatticeElements/latticelink3dboundary.h new file mode 100644 index 000000000..35c13be14 --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticelink3dboundary.h @@ -0,0 +1,100 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticelink3dboundary_h +#define latticelink3dboundary_h + +#include "latticelink3d.h" + +///@name Input fields for Latticelink3dboundary +//@{ +#define _IFT_LatticeLink3dBoundary_Name "latticelink3dboundary" +#define _IFT_LatticeLink3dBoundary_location "location" +//@} + +namespace oofem { +/** + * This class implements a 3-dimensional lattice link element for the boundaries of a periodic cell. + * The first two nodes have each 6 degrees of freedom (3 translation and 3 rotations). + * One of the nodes lies either on the boundary or outside the specimen. + * This node is replaced with the corresponding image node. The control node (node 3) is used to impose the macroscopic (average) strain. + * MACROSCOPIC INPUT for the control node: STRAIN TENSOR (3D, 6 COMPONENTS, VOIGT NOTATION: Exx Eyy Ezz Gyz Gxz Gxy) + * @author: Peter Grassl + */ + +class LatticeLink3dBoundary : public LatticeLink3d +{ +protected: + IntArray location; + +public: + LatticeLink3dBoundary(int n, Domain *); + virtual ~LatticeLink3dBoundary(); + + int giveLocalCoordinateSystem(FloatMatrix &answer) override; + + int computeNumberOfDofs() override { return 18; } + + void giveDofManDofIDMask(int inode, IntArray &) const override; + + void giveInternalForcesVector(FloatArray &answer, TimeStep *, int useUpdatedGpRecord = 0) override; + void computeGeometryProperties() override; + + void giveGPCoordinates(FloatArray &coords) override { coords = this->globalCentroid; } + const char *giveInputRecordName() const override { return _IFT_LatticeLink3dBoundary_Name; } + const char *giveClassName() const override { return "LatticeLink3dBoundary"; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + + const IntArray giveLocation() override { return location; }; + void recalculateCoordinates(int nodeNumber, FloatArray &coords) override; + +#ifdef __OOFEG + void drawYourself(oofegGraphicContext &context, TimeStep *tStep) override; + void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &, TimeStep *tStep, UnknownType) override; +#endif + +protected: + bool computeGtoLRotationMatrix(FloatMatrix &) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + + void giveSwitches(IntArray &answer, int location); + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *stepN) override; +}; +} // end namespace oofem +#endif diff --git a/src/sm/Elements/LatticeElements/latticestructuralelement.C b/src/sm/Elements/LatticeElements/latticestructuralelement.C new file mode 100644 index 000000000..1cb9853a5 --- /dev/null +++ b/src/sm/Elements/LatticeElements/latticestructuralelement.C @@ -0,0 +1,63 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/LatticeElements/latticestructuralelement.h" + +namespace oofem { +LatticeStructuralElement :: LatticeStructuralElement(int n, Domain *aDomain) : StructuralElement(n, aDomain) +{ } + +void +LatticeStructuralElement :: initializeFrom(InputRecord &ir) +{ + StructuralElement :: initializeFrom(ir); +} + +void +LatticeStructuralElement :: printOutputAt(FILE *file, TimeStep *tStep) +{ + StructuralElement :: printOutputAt(file, tStep); + + /// FIXME: This output should just be moved to the elements themselves. But, they don't exist yet? / Mikael + FloatArray forces; + if ( this->giveClassName() == std::string("LatticeBeam3d") ) { + this->giveInternalForcesVector(forces, tStep, 0); + fprintf(file, "LatticeBeam forces = %e %e %e %e %e %e.\n", forces.at(7), forces.at(8), forces.at(9), forces.at(10), forces.at(11), forces.at(12) ); + } else if ( this->giveClassName() == std::string("LatticeBeam3dBoundary") ) { + this->giveInternalForcesVector(forces, tStep, 0); + fprintf(file, "LatticeBeam3dBoundary forces = %e %e %e %e %e %e.\n", forces.at(7), forces.at(8), forces.at(9), forces.at(10), forces.at(11), forces.at(12) ); + } +} + +} // end namespace oofem diff --git a/src/sm/Elements/latticestructuralelement.h b/src/sm/Elements/LatticeElements/latticestructuralelement.h similarity index 70% rename from src/sm/Elements/latticestructuralelement.h rename to src/sm/Elements/LatticeElements/latticestructuralelement.h index 3564abe86..6587bf786 100644 --- a/src/sm/Elements/latticestructuralelement.h +++ b/src/sm/Elements/LatticeElements/latticestructuralelement.h @@ -10,7 +10,7 @@ * * OOFEM : Object Oriented Finite Element Code * - * Copyright (C) 1993 - 2013 Borek Patzak + * Copyright (C) 1993 - 2019 Borek Patzak * * * @@ -35,7 +35,7 @@ #ifndef latticestructuralelement_h #define latticestructuralelement_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" namespace oofem { /** @@ -53,10 +53,11 @@ namespace oofem { class LatticeStructuralElement : public StructuralElement { public: - LatticeStructuralElement(int n, Domain * d); - virtual ~LatticeStructuralElement(); + LatticeStructuralElement(int n, Domain *d); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; + + void printOutputAt(FILE *file, TimeStep *tStep) override; /** * Returns the cross-sectional area of the lattice element. @@ -70,6 +71,24 @@ class LatticeStructuralElement : public StructuralElement */ virtual double giveLength() { return 0; } + /** + * Returns the length associated with bond + * @return bond length. + */ + virtual double giveBondLength() { return 0; } + + /** + * Returns the length associated with bond + * @return bond length. + */ + virtual double giveBondEndLength() { return 0; } + + /** + * Returns the length associated with bond + * @return bond length. + */ + virtual double giveBondDiameter() { return 0; } + /** * Returns the crack flag * @return Crack flag. @@ -88,11 +107,10 @@ class LatticeStructuralElement : public StructuralElement virtual double giveCrackWidth() { return 0; } /** - * @return Crack width + * @return oldCrackWidth */ virtual double giveOldCrackWidth() { return 0; } - /** * Returns the energy dissipation computed at the GaussPoint of the element. * This function is used for the lattice specific vtk export. @@ -100,12 +118,29 @@ class LatticeStructuralElement : public StructuralElement */ virtual double giveDissipation() { return 0; } + /** + * Returns pressures + * @return pressures. + */ + virtual void givePressures(FloatArray &pressures) { return; } + + /** + * Returns plastic strains + * @return plasticStrains + */ + virtual void givePlasticStrain(FloatArray &plas) { return; } + + /** + * Returns plastic strains + * @return plasticStrains + */ + virtual void giveOldPlasticStrain(FloatArray &plas) { return; } /** * Usually computes interpolation function, which is not needed for the lattice elements. * However, structural element requires implementation. */ - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) { return; } + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override { return; } /** @@ -122,6 +157,11 @@ class LatticeStructuralElement : public StructuralElement virtual int giveCouplingFlag() { return 0; } + /** + * This function gives the cross-section coordinates. + */ + virtual void giveCrossSectionCoordinates(FloatArray &coords) {; } + /** * Returns the coupling numbers * @return couplingNumbers. @@ -151,6 +191,28 @@ class LatticeStructuralElement : public StructuralElement * Gives the GP coordinates */ virtual void giveGpCoordinates(FloatArray &coords) { return; } + + /** + * Gives the y second moment of area + */ + virtual double giveIy() { return 0.; } + + /** + * Gives the z second moment of area + */ + virtual double giveIz() { return 0.; } + /** + * Gives the polar second moment of area + */ + virtual double giveIk() { return 0.; } + /** + * Gives the shear area y + */ + virtual double giveShearAreaY() { return 0.; } + /** + * Gives the shear area z + */ + virtual double giveShearAreaZ() { return 0.; } }; } // end namespace oofem #endif diff --git a/src/sm/Elements/MixedPressure/PlaneStrain/qtrplanestrainp1.C b/src/sm/Elements/MixedPressure/PlaneStrain/qtrplanestrainp1.C new file mode 100644 index 000000000..e88150f96 --- /dev/null +++ b/src/sm/Elements/MixedPressure/PlaneStrain/qtrplanestrainp1.C @@ -0,0 +1,124 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "../sm/Elements/MixedPressure/PlaneStrain/qtrplanestrainp1.h" +#include "fei2dtrlin.h" +#include "node.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "crosssection.h" +#include "classfactory.h" + + + +namespace oofem { +REGISTER_Element(QTrPlaneStrainP1); + +FEI2dTrLin QTrPlaneStrainP1 :: interpolation_lin(1, 2); + +QTrPlaneStrainP1 :: QTrPlaneStrainP1(int n, Domain *aDomain) : QTrPlaneStrain(n, aDomain), BaseMixedPressureElement() +{ + displacementDofsOrdering = { + 1, 2, 4, 5, 7, 8, 10, 11, 12, 13, 14, 15 + }; + pressureDofsOrdering = { + 3, 6, 9 + }; +} + + +void +QTrPlaneStrainP1 :: computeVolumetricBmatrixAt(GaussPoint *gp, FloatArray &answer, NLStructuralElement *elem) +{ + answer.resize(12); + FloatMatrix dN; + elem->giveInterpolation()->evaldNdx( dN, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + for ( int j = 0, k = 0; j < 6; j++, k += 2 ) { + answer(k) = dN(j, 0); + answer(k + 1) = dN(j, 1); + } +} + +void +QTrPlaneStrainP1 :: computePressureNMatrixAt(GaussPoint *gp, FloatArray &answer) +{ + this->interpolation_lin.evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); +} + + +void +QTrPlaneStrainP1 :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + if ( inode <= 3 ) { + answer = { + D_u, D_v, P_f + }; + } else { + answer = { + D_u, D_v + }; + } +} + + + +void +QTrPlaneStrainP1 :: giveDofManDofIDMask_u(IntArray &answer) +{ + answer = { + D_u, D_v + }; +} + + +void +QTrPlaneStrainP1 :: giveDofManDofIDMask_p(IntArray &answer) +{ + answer = { + P_f + }; +} + + + +void +QTrPlaneStrainP1 :: postInitialize() +{ + BaseMixedPressureElement :: postInitialize(); + QTrPlaneStrain :: postInitialize(); +} +} // end namespace oofem diff --git a/src/sm/Elements/MixedPressure/PlaneStrain/qtrplanestrainp1.h b/src/sm/Elements/MixedPressure/PlaneStrain/qtrplanestrainp1.h new file mode 100644 index 000000000..217f1ab04 --- /dev/null +++ b/src/sm/Elements/MixedPressure/PlaneStrain/qtrplanestrainp1.h @@ -0,0 +1,80 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef qtrplanestrainp1_h +#define qtrplanestrainp1_h + +#include "../sm/Elements/PlaneStrain/qtrplanestrain.h" +#include "../sm/Elements/MixedPressure/basemixedpressureelement.h" + +#define _IFT_QTrPlaneStrainP1_Name "qtrplanestrainp1" + + +namespace oofem { +class FEI2dTrLin; + +class QTrPlaneStrainP1 : public QTrPlaneStrain, public BaseMixedPressureElement +{ +protected: + static FEI2dTrLin interpolation_lin; + +public: + QTrPlaneStrainP1(int n, Domain *d); + virtual ~QTrPlaneStrainP1() { } + +protected: + void computePressureNMatrixAt(GaussPoint *, FloatArray &) override; + void computeVolumetricBmatrixAt(GaussPoint *gp, FloatArray &Bvol, NLStructuralElement *element) override; + NLStructuralElement *giveElement() override { return this; } +public: + const char *giveClassName() const override { return "QTrPlaneStrainP1"; } + const char *giveInputRecordName() const override { return _IFT_QTrPlaneStrainP1_Name; } + + + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) override; + void giveDofManDofIDMask_p(IntArray &answer) override; + + + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) override { BaseMixedPressureElement :: computeStiffnessMatrix(answer, mode, tStep); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override { BaseMixedPressureElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + + + int giveNumberOfPressureDofs() override { return 3; } + int giveNumberOfDisplacementDofs() override { return 12; } + int giveNumberOfDofs() override { return 15; } + void postInitialize() override; +}; +} // end namespace oofem +#endif // qtrplanestrainp1_h diff --git a/src/sm/Elements/MixedPressure/PlaneStrain/quad1planestrainp1.C b/src/sm/Elements/MixedPressure/PlaneStrain/quad1planestrainp1.C new file mode 100644 index 000000000..3258ec883 --- /dev/null +++ b/src/sm/Elements/MixedPressure/PlaneStrain/quad1planestrainp1.C @@ -0,0 +1,114 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "Elements/MixedPressure/PlaneStrain/quad1planestrainp1.h" +#include "node.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "crosssection.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_Element(Quad1PlaneStrainP1); + + +Quad1PlaneStrainP1 :: Quad1PlaneStrainP1(int n, Domain *aDomain) : Quad1PlaneStrain(n, aDomain), BaseMixedPressureElement() +{ + displacementDofsOrdering = { + 1, 2, 4, 5, 7, 8, 10, 11 + }; + pressureDofsOrdering = { + 3, 6, 9, 12 + }; +} + + + +void +Quad1PlaneStrainP1 :: computeVolumetricBmatrixAt(GaussPoint *gp, FloatArray &answer, NLStructuralElement *elem) +{ + answer.resize(8); + FloatMatrix dN; + elem->giveInterpolation()->evaldNdx( dN, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + for ( int j = 0, k = 0; j < 4; j++, k += 2 ) { + answer(k) = dN(j, 0); + answer(k + 1) = dN(j, 1); + } +} + +void +Quad1PlaneStrainP1 :: computePressureNMatrixAt(GaussPoint *gp, FloatArray &answer) +{ + NLStructuralElement *elem = this->giveElement(); + elem->giveInterpolation()->evalN( answer, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); +} + + +void +Quad1PlaneStrainP1 :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = { + D_u, D_v, P_f + }; +} + + +void +Quad1PlaneStrainP1 :: giveDofManDofIDMask_u(IntArray &answer) +{ + answer = { + D_u, D_v + }; +} + + +void +Quad1PlaneStrainP1 :: giveDofManDofIDMask_p(IntArray &answer) +{ + answer = { + P_f + }; +} + +void +Quad1PlaneStrainP1 :: postInitialize() +{ + BaseMixedPressureElement :: postInitialize(); + Quad1PlaneStrain :: postInitialize(); +} +} // end namespace oofem diff --git a/src/sm/Elements/MixedPressure/PlaneStrain/quad1planestrainp1.h b/src/sm/Elements/MixedPressure/PlaneStrain/quad1planestrainp1.h new file mode 100644 index 000000000..468ee079b --- /dev/null +++ b/src/sm/Elements/MixedPressure/PlaneStrain/quad1planestrainp1.h @@ -0,0 +1,76 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2015 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef quad1planestrainp1_h +#define quad1planestrainp1_h + +#include "../sm/Elements/PlaneStrain/quad1planestrain.h" +#include "../sm/Elements/MixedPressure/basemixedpressureelement.h" + + +#define _IFT_Quad1PlaneStrainP1_Name "quad1planestrainp1" + +namespace oofem { +class Quad1PlaneStrainP1 : public Quad1PlaneStrain, public BaseMixedPressureElement +{ +protected: + +public: + Quad1PlaneStrainP1(int n, Domain *d); + virtual ~Quad1PlaneStrainP1() { } + +protected: + void computePressureNMatrixAt(GaussPoint *gp, FloatArray &Np) override; + void computeVolumetricBmatrixAt(GaussPoint *gp, FloatArray &answer, NLStructuralElement *element) override; + NLStructuralElement *giveElement() override { return this; } + +public: + const char *giveInputRecordName() const override { return _IFT_Quad1PlaneStrainP1_Name; } + const char *giveClassName() const override { return "Quad1PlaneStrainP0"; } + + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) override; + void giveDofManDofIDMask_p(IntArray &answer) override; + + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) override { BaseMixedPressureElement :: computeStiffnessMatrix(answer, mode, tStep); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override { BaseMixedPressureElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + + + int giveNumberOfPressureDofs() override { return 4; } + int giveNumberOfDisplacementDofs() override { return 8; } + int giveNumberOfDofs() override { return 12; } + void postInitialize() override; +}; +} // end namespace oofem +#endif // quad1planestrainp1_h diff --git a/src/sm/Elements/MixedPressure/basemixedpressureelement.C b/src/sm/Elements/MixedPressure/basemixedpressureelement.C new file mode 100644 index 000000000..9141ae574 --- /dev/null +++ b/src/sm/Elements/MixedPressure/basemixedpressureelement.C @@ -0,0 +1,400 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * + * Copyright (C) 1993 - 2015 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "../sm/Elements/MixedPressure/basemixedpressureelement.h" +#include "../sm/Materials/MixedPressure/mixedpressurematerialextensioninterface.h" + + +#include "../sm/CrossSections/structuralcrosssection.h" +#include "../sm/Materials/structuralms.h" + +#include "material.h" +#include "node.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "domain.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "unknownnumberingscheme.h" + + +#include + +namespace oofem { +BaseMixedPressureElement :: BaseMixedPressureElement() +{} + + + +void +BaseMixedPressureElement :: giveLocationArrayOfDofIDs(IntArray &locationArray_u, IntArray &locationArray_p, const UnknownNumberingScheme &s, const IntArray &dofIdArray_u, const IntArray &dofIdArray_p) +{ + // Routine to extract the location array of an element for given dofid array. + locationArray_u.clear(); + locationArray_p.clear(); + NLStructuralElement *el = this->giveElement(); + int k = 0; + IntArray nodalArray; + for ( int i = 1; i <= el->giveNumberOfDofManagers(); i++ ) { + DofManager *dMan = el->giveDofManager(i); + int itt = 1; + for ( int j = 1; j <= dofIdArray_u.giveSize(); j++ ) { + if ( dMan->hasDofID( ( DofIDItem ) dofIdArray_u.at(j) ) ) { + // Dof *d = dMan->giveDofWithID( dofIdArray_u.at( j ) ); + locationArray_u.followedBy(k + itt); + } + itt++; + } + for ( int j = 1; j <= dofIdArray_p.giveSize(); j++ ) { + if ( dMan->hasDofID( ( DofIDItem ) dofIdArray_p.at(j) ) ) { + //Dof *d = dMan->giveDofWithID( dofIdArray_m.at( j ) ); + locationArray_p.followedBy(k + itt); + } + itt++; + } + k += dMan->giveNumberOfDofs(); + } +} + + +void +BaseMixedPressureElement :: computeStressVector(FloatArray &stress, GaussPoint *gp, TimeStep *tStep) +{ + NLStructuralElement *elem = this->giveElement(); + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + + MixedPressureMaterialExtensionInterface *mixedPressureMat = static_cast< MixedPressureMaterialExtensionInterface * >( cs->giveMaterialInterface(MixedPressureMaterialExtensionInterfaceType, gp) ); + if ( !mixedPressureMat ) { + OOFEM_ERROR("Material doesn't implement the required Micromorphic interface!"); + } + + double pressure; + + if ( elem->giveGeometryMode() == 0 ) { + FloatArray strain; + this->computeStrainVector(strain, gp, tStep); + this->computePressure(pressure, gp, tStep); + mixedPressureMat->giveRealStressVector(stress, gp, strain, pressure, tStep); + } else { + /* FloatArray devF; + * elem->computeDeviatoricDeformationGradientVector(devF, gp, tStep); + * this->giveDofManDofIDMask_p( IdMask_p ); + * this->computePressure(pressure,IdMask_p, gp, tStep); + * mixedPressureMat->giveFiniteStrainStressVectors(stress, gp, devF, pressure, tStep); + */ + OOFEM_ERROR("Large-strain formulaton is not available yet") + } +} + + +void +BaseMixedPressureElement :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +{ + FloatArray d_u; + FloatMatrix B; + NLStructuralElement *elem = this->giveElement(); + IntArray IdMask_u; + this->giveDofManDofIDMask_u(IdMask_u); + this->giveElement()->computeVectorOf(IdMask_u, VM_Total, tStep, d_u); + elem->computeBmatrixAt(gp, B); + answer.beProductOf(B, d_u); +} + + +void +BaseMixedPressureElement :: computePressure(double &answer, GaussPoint *gp, TimeStep *tStep) +{ + IntArray IdMask_p; + FloatArray d_p, N_p; + + this->giveDofManDofIDMask_p(IdMask_p); + this->giveElement()->computeVectorOf(IdMask_p, VM_Total, tStep, d_p); + this->computePressureNMatrixAt(gp, N_p); + answer = N_p.dotProduct(d_p); +} + + + +void +BaseMixedPressureElement :: giveInternalForcesVector_u(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + NLStructuralElement *elem = this->giveElement(); + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + FloatArray BS, vStress, s, M; + FloatMatrix B; + for ( GaussPoint *gp : *elem->giveIntegrationRule(0) ) { + if ( useUpdatedGpRecord == 1 ) { + if ( this->giveElement()->giveGeometryMode() == 0 ) { + vStress = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveTempStressVector(); + } else { + vStress = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveTempPVector(); + } + } else { + this->computeStressVector(vStress, gp, tStep); + } + + MixedPressureMaterialExtensionInterface *mixedPressureMat = dynamic_cast< MixedPressureMaterialExtensionInterface * >( cs->giveMaterialInterface(MixedPressureMaterialExtensionInterfaceType, gp) ); + if ( !mixedPressureMat ) { + OOFEM_ERROR("Material doesn't implement the required Micromorphic interface!"); + } + // Compute nodal internal forces at nodes as f = B^T*Stress dV + double dV = elem->computeVolumeAround(gp); + elem->computeBmatrixAt(gp, B); + BS.beTProductOf(B, vStress); + answer.add(dV, BS); + } +} + + +void +BaseMixedPressureElement :: giveInternalForcesVector_p(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + double pressure, kappa, factor; + IntArray IdMask_u; + FloatArray N_p, Bvol, d_u; + NLStructuralElement *elem = this->giveElement(); + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + + + for ( GaussPoint *gp : *elem->giveIntegrationRule(0) ) { + MixedPressureMaterialExtensionInterface *mixedPressureMat = dynamic_cast< MixedPressureMaterialExtensionInterface * >( cs->giveMaterialInterface(MixedPressureMaterialExtensionInterfaceType, gp) ); + if ( !mixedPressureMat ) { + OOFEM_ERROR("Material doesn't implement the required Mixed pressure interface!"); + } + // Compute nodal internal forces at nodes as f = B^T*Stress dV + double dV = elem->computeVolumeAround(gp); + this->computePressure(pressure, gp, tStep); + // this->computePressureNMatrixAt(gp, N_p); + this->computeVolumetricBmatrixAt(gp, Bvol, elem); + this->giveDofManDofIDMask_u(IdMask_u); + elem->computeVectorOf(IdMask_u, VM_Total, tStep, d_u); + + double eps_V = Bvol.dotProduct(d_u); + mixedPressureMat->giveInverseOfBulkModulus(kappa, TangentStiffness, gp, tStep); + factor = eps_V + pressure * kappa; + answer.times(dV * factor); + } +} + +void +BaseMixedPressureElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + answer.resize( this->giveNumberOfDofs() ); + answer.zero(); + + FloatArray answer_u( this->giveNumberOfDisplacementDofs() ); + answer_u.zero(); + FloatArray answer_p( this->giveNumberOfPressureDofs() ); + answer_p.zero(); + + + this->giveInternalForcesVector_u(answer_u, tStep, 0); + this->giveInternalForcesVector_p(answer_p, tStep, 0); + answer.assemble(answer_u, locationArray_u); + answer.assemble(answer_p, locationArray_p); +} + +void +BaseMixedPressureElement :: computeForceLoadVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode) +{ + FloatArray localForces( this->giveNumberOfDisplacementDofs() ); + answer.resize( this->giveNumberOfDofs() ); + this->computeLocForceLoadVector(localForces, tStep, mode); + answer.assemble(localForces, locationArray_u); +} + + +/************************************************************************/ +void +BaseMixedPressureElement :: computeLocForceLoadVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode) +// computes the part of load vector, which is imposed by force loads acting +// on element volume (surface). +// When reactions forces are computed, they are computed from element::GiveRealStressVector +// in this vector a real forces are stored (temperature part is subtracted). +// so we need further sobstract part corresponding to non-nodeal loading. +{ + FloatMatrix T; + NLStructuralElement *elem = this->giveElement(); + //@todo check this + // elem->computeLocalForceLoadVector(answer, tStep, mode); + + // transform result from global cs to nodal cs. if necessary + if ( answer.isNotEmpty() ) { + if ( elem->computeGtoLRotationMatrix(T) ) { + // first back to global cs from element local + answer.rotatedWith(T, 't'); + } + } else { + answer.resize( this->giveNumberOfDisplacementDofs() ); + answer.zero(); + } +} + + +void +BaseMixedPressureElement :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + //set displacement and nonlocal location array + answer.resize( this->giveNumberOfDofs(), this->giveNumberOfDofs() ); + answer.zero(); + + FloatMatrix Kuu, Kup, Kpu, Kpp; + this->computeStiffnessMatrix_uu(Kuu, rMode, tStep); + this->computeStiffnessMatrix_up(Kup, rMode, tStep); + Kpu.beTranspositionOf(Kup); + this->computeStiffnessMatrix_pp(Kpp, rMode, tStep); + + answer.assemble(Kuu, locationArray_u); + answer.assemble(Kup, locationArray_u, locationArray_p); + answer.assemble(Kpu, locationArray_p, locationArray_u); + answer.assemble(Kpp, locationArray_p); +} + + +void +BaseMixedPressureElement :: computeStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + NLStructuralElement *elem = this->giveElement(); + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + FloatMatrix B, D, DB; + bool matStiffSymmFlag = elem->giveCrossSection()->isCharacteristicMtrxSymmetric(rMode); + answer.clear(); + for ( GaussPoint *gp : *elem->giveIntegrationRule(0) ) { + MixedPressureMaterialExtensionInterface *mixedPressureMat = dynamic_cast< MixedPressureMaterialExtensionInterface * >( + cs->giveMaterialInterface(MixedPressureMaterialExtensionInterfaceType, gp) ); + if ( !mixedPressureMat ) { + OOFEM_ERROR("Material doesn't implement the required Mixed Pressure Material interface!"); + } + + + mixedPressureMat->giveDeviatoricConstitutiveMatrix(D, rMode, gp, tStep); + elem->computeBmatrixAt(gp, B); + double dV = elem->computeVolumeAround(gp); + DB.beProductOf(D, B); + + if ( matStiffSymmFlag ) { + answer.plusProductSymmUpper(B, DB, dV); + } else { + answer.plusProductUnsym(B, DB, dV); + } + } + + if ( matStiffSymmFlag ) { + answer.symmetrized(); + } +} + + + +void +BaseMixedPressureElement :: computeStiffnessMatrix_up(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + double dV; + FloatArray N_p, Bvol; + NLStructuralElement *elem = this->giveElement(); + + answer.clear(); + + for ( GaussPoint *gp : *elem->giveIntegrationRule(0) ) { + this->computeVolumetricBmatrixAt(gp, Bvol, elem); + this->computePressureNMatrixAt(gp, N_p); + FloatMatrix mNp(N_p, true); + FloatMatrix mBvol(Bvol, true); + + dV = elem->computeVolumeAround(gp); + answer.plusProductUnsym(mBvol, mNp, -dV); + } +} + +void +BaseMixedPressureElement :: computeStiffnessMatrix_pp(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + NLStructuralElement *elem = this->giveElement(); + double dV, kappa; + FloatArray N_p; + StructuralCrossSection *cs = elem->giveStructuralCrossSection(); + answer.clear(); + + for ( GaussPoint *gp : *elem->giveIntegrationRule(0) ) { + MixedPressureMaterialExtensionInterface *mixedPressureMat = dynamic_cast< MixedPressureMaterialExtensionInterface * >( cs->giveMaterialInterface(MixedPressureMaterialExtensionInterfaceType, gp) ); + if ( !mixedPressureMat ) { + OOFEM_ERROR("Material doesn't implement the required Mixed Pressure Material interface!"); + } + + mixedPressureMat->giveInverseOfBulkModulus(kappa, rMode, gp, tStep); + this->computePressureNMatrixAt(gp, N_p); + FloatMatrix mN_p(N_p, true); + dV = elem->computeVolumeAround(gp); + answer.plusProductUnsym(mN_p, mN_p, -dV * kappa); + } +} + + + +void +BaseMixedPressureElement :: initializeFrom(InputRecord &ir) +{ + // @todo Is this function necessary??? +} + +void +BaseMixedPressureElement :: updateInternalState(TimeStep *tStep) +// Updates the receiver at end of step. +{ + FloatArray stress, strain; + /* + * // force updating strains & stresses + * for ( auto &iRule: integrationRulesArray ) { + * for ( GaussPoint *gp: *iRule ) { + * this->computeStrainVector(strain, gp, tStep); + * this->computeStressVector(stress, strain, gp, tStep); + * } + * } + */ +} + + +void +BaseMixedPressureElement :: postInitialize() +{ + IntArray IdMask_u, IdMask_p; + this->giveDofManDofIDMask_u(IdMask_u); + this->giveDofManDofIDMask_p(IdMask_p); + this->giveLocationArrayOfDofIDs(locationArray_u, locationArray_p, EModelDefaultEquationNumbering(), IdMask_u, IdMask_p); +} +} // end namespace oofem diff --git a/src/sm/Elements/MixedPressure/basemixedpressureelement.h b/src/sm/Elements/MixedPressure/basemixedpressureelement.h new file mode 100644 index 000000000..6f44abc31 --- /dev/null +++ b/src/sm/Elements/MixedPressure/basemixedpressureelement.h @@ -0,0 +1,107 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser Base Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser Base Public License for more details. + * + * You should have received a copy of the GNU Lesser Base Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef basemixedpressureelement_h +#define basemixedpressureelement_h + +#include "../sm/Elements/structuralelement.h" +#include "../sm/Elements/nlstructuralelement.h" + +namespace oofem { +/** + * Base class for mixed u-p formulation. + * @author Martin Horak + */ +class BaseMixedPressureElement +{ +protected: + IntArray displacementDofsOrdering, pressureDofsOrdering; + IntArray locationArray_u, locationArray_p; + + +public: + BaseMixedPressureElement(); + virtual ~BaseMixedPressureElement() { } + + virtual void initializeFrom(InputRecord &ir); + +protected: + + /// Pure virtual functions + virtual NLStructuralElement *giveElement() = 0; + virtual void computeVolumetricBmatrixAt(GaussPoint *gp, FloatArray &Bvol, NLStructuralElement *element) = 0; + + virtual void computePressureNMatrixAt(GaussPoint *, FloatArray &) = 0; + + virtual int giveNumberOfPressureDofs() = 0; + virtual int giveNumberOfDisplacementDofs() = 0; + virtual int giveNumberOfDofs() = 0; + + virtual void giveDofManDofIDMask_u(IntArray &answer) = 0; + virtual void giveDofManDofIDMask_p(IntArray &answer) = 0; + /// End of pure virtual functions + + + + virtual void computeStiffnessMatrix(FloatMatrix &, MatResponseMode, TimeStep *); + void computeStiffnessMatrix_uu(FloatMatrix &, MatResponseMode, TimeStep *); + void computeStiffnessMatrix_up(FloatMatrix &, MatResponseMode, TimeStep *); + void computeStiffnessMatrix_pp(FloatMatrix &, MatResponseMode, TimeStep *); + + + + + void computeStressVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computePressure(double &answer, GaussPoint *gp, TimeStep *tStep); + + + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); + void giveInternalForcesVector_u(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); + void giveInternalForcesVector_p(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); + + void computeForceLoadVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode); + void computeLocForceLoadVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode); + + virtual IntArray &giveDisplacementDofsOrdering() { return displacementDofsOrdering; } + virtual IntArray &giveMicromorphicDofsOrdering() { return pressureDofsOrdering; } + // void giveLocationArrayOfDofIDs( IntArray &answer, const UnknownNumberingScheme &s, const IntArray &dofIdArray ); + void giveLocationArrayOfDofIDs(IntArray &locationArray_u, IntArray &locationArray_p, const UnknownNumberingScheme &s, const IntArray &dofIdArray_u, const IntArray &dofIdArray_p); + virtual void postInitialize(); + virtual void updateInternalState(TimeStep *tStep); +}; +} // end namespace oofem + +#endif diff --git a/src/sm/Elements/PlaneStrain/qplanestrain.C b/src/sm/Elements/PlaneStrain/qplanestrain.C index 34bee8e13..9adda8e12 100644 --- a/src/sm/Elements/PlaneStrain/qplanestrain.C +++ b/src/sm/Elements/PlaneStrain/qplanestrain.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/PlaneStrain/qplanestrain.h" +#include "sm/Elements/PlaneStrain/qplanestrain.h" #include "fei2dquadquad.h" #include "classfactory.h" diff --git a/src/sm/Elements/PlaneStrain/qplanestrain.h b/src/sm/Elements/PlaneStrain/qplanestrain.h index 76b15eed2..88a6708b6 100644 --- a/src/sm/Elements/PlaneStrain/qplanestrain.h +++ b/src/sm/Elements/PlaneStrain/qplanestrain.h @@ -35,7 +35,7 @@ #ifndef qplanstrain_h #define qplanstrain_h -#include "Elements/structural2delement.h" +#include "sm/Elements/structural2delement.h" #include "zznodalrecoverymodel.h" #define _IFT_QPlaneStrain_Name "qplanestrain" @@ -56,20 +56,20 @@ class QPlaneStrain : public PlaneStrainElement, public ZZNodalRecoveryModelInter QPlaneStrain(int N, Domain * d); virtual ~QPlaneStrain() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QPlaneStrain_Name; } - virtual const char *giveClassName() const { return "QPlaneStrain"; } + const char *giveInputRecordName() const override { return _IFT_QPlaneStrain_Name; } + const char *giveClassName() const override { return "QPlaneStrain"; } - virtual int testElementExtension(ElementExtension ext) { return 0; } ///@todo //check this probably ok now when derived from PE-element + int testElementExtension(ElementExtension ext) override { return 0; } ///@todo //check this probably ok now when derived from PE-element - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif }; diff --git a/src/sm/Elements/PlaneStrain/qplanestraingrad.h b/src/sm/Elements/PlaneStrain/qplanestraingrad.h index 89f026c38..af0b4b257 100644 --- a/src/sm/Elements/PlaneStrain/qplanestraingrad.h +++ b/src/sm/Elements/PlaneStrain/qplanestraingrad.h @@ -35,8 +35,8 @@ #ifndef qplanestraingrad_h #define qplanestraingrad_h -#include "../sm/Elements/PlaneStrain/qplanestrain.h" -#include "../sm/Elements/graddpelement.h" +#include "sm/Elements/PlaneStrain/qplanestrain.h" +#include "sm/Elements/graddpelement.h" #define _IFT_QPlaneStrainGrad_Name "qplanestraingrad" @@ -52,24 +52,24 @@ class QPlaneStrainGrad : public QPlaneStrain, public GradDpElement QPlaneStrainGrad(int n, Domain * d); virtual ~QPlaneStrainGrad() { } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveInputRecordName() const { return _IFT_QPlaneStrainGrad_Name; } - virtual const char *giveClassName() const { return "QPlaneStrainGrad"; } + const char *giveInputRecordName() const override { return _IFT_QPlaneStrainGrad_Name; } + const char *giveClassName() const override { return "QPlaneStrainGrad"; } - virtual MaterialMode giveMaterialMode() { return _PlaneStrain; } - virtual int computeNumberOfDofs() { return 20; } + MaterialMode giveMaterialMode() override { return _PlaneStrain; } + int computeNumberOfDofs() override { return 20; } protected: - virtual void computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { GradDpElement :: computeStiffnessMatrix(answer, rMode, tStep); } - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) { GradDpElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } + void computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { GradDpElement :: computeStiffnessMatrix(answer, rMode, tStep); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { GradDpElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } - virtual void computeGaussPoints(); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual StructuralElement *giveStructuralElement() { return this; } - virtual NLStructuralElement *giveNLStructuralElement() { return this; } + void computeGaussPoints() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + StructuralElement *giveStructuralElement() override { return this; } + NLStructuralElement *giveNLStructuralElement() override { return this; } }; } // end namespace oofem #endif // qplanestraingrad_h diff --git a/src/sm/Elements/PlaneStrain/qtrplanestrain.C b/src/sm/Elements/PlaneStrain/qtrplanestrain.C index d67e79758..7eba21bfb 100644 --- a/src/sm/Elements/PlaneStrain/qtrplanestrain.C +++ b/src/sm/Elements/PlaneStrain/qtrplanestrain.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStrain/qtrplanestrain.h" +#include "sm/Elements/PlaneStrain/qtrplanestrain.h" #include "fei2dtrquad.h" #include "floatmatrix.h" #include "floatarray.h" @@ -43,7 +43,7 @@ #include "oofeggraphiccontext.h" #include "connectivitytable.h" #include "oofegutils.h" - #include "Materials/rcm2.h" + #include "sm/Materials/rcm2.h" #endif diff --git a/src/sm/Elements/PlaneStrain/qtrplanestrain.h b/src/sm/Elements/PlaneStrain/qtrplanestrain.h index 31e876e0a..be92fe589 100644 --- a/src/sm/Elements/PlaneStrain/qtrplanestrain.h +++ b/src/sm/Elements/PlaneStrain/qtrplanestrain.h @@ -35,8 +35,8 @@ #ifndef qtrplanestrain_h #define qtrplanestrain_h -#include "Elements/structural2delement.h" -#include "ErrorEstimators/directerrorindicatorrc.h" +#include "sm/Elements/structural2delement.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" #include "spatiallocalizer.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -60,32 +60,32 @@ public SPRNodalRecoveryModelInterface, public ZZNodalRecoveryModelInterface QTrPlaneStrain(int n, Domain * d); virtual ~QTrPlaneStrain() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual Interface *giveInterface(InterfaceType it); - virtual double giveParentElSize() const { return 0.5; } + Interface *giveInterface(InterfaceType it) override; + double giveParentElSize() const override { return 0.5; } - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_EdgeLoadSupport ) ? 0 : 0 ); } + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_EdgeLoadSupport ) ? 0 : 0 ); } #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QTrPlaneStrain_Name; } - virtual const char *giveClassName() const { return "QTrPlaneStrain"; } + const char *giveInputRecordName() const override { return _IFT_QTrPlaneStrain_Name; } + const char *giveClassName() const override { return "QTrPlaneStrain"; } - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; protected: - virtual int giveNumberOfIPForMassMtrxIntegration() { return 4; } + int giveNumberOfIPForMassMtrxIntegration() override { return 4; } }; } // end namespace oofem #endif // qtrplanestrain_h diff --git a/src/sm/Elements/PlaneStrain/quad1planestrain.C b/src/sm/Elements/PlaneStrain/quad1planestrain.C index 23dc4dcbb..aa349e956 100644 --- a/src/sm/Elements/PlaneStrain/quad1planestrain.C +++ b/src/sm/Elements/PlaneStrain/quad1planestrain.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/PlaneStrain/quad1planestrain.h" +#include "sm/Elements/PlaneStrain/quad1planestrain.h" #include "fei2dquadlin.h" #include "node.h" #include "crosssection.h" @@ -47,7 +47,7 @@ #ifdef __OOFEG #include "oofeggraphiccontext.h" #include "oofegutils.h" - #include "Materials/rcm2.h" + #include "sm/Materials/rcm2.h" #endif namespace oofem { @@ -148,14 +148,11 @@ Quad1PlaneStrain :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) } -IRResultType -Quad1PlaneStrain :: initializeFrom(InputRecord *ir) +void +Quad1PlaneStrain :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 4; - IRResultType result = PlaneStrainElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + PlaneStrainElement :: initializeFrom(ir); if ( !( ( numberOfGaussPoints == 4 ) || ( numberOfGaussPoints == 1 ) || @@ -163,8 +160,6 @@ Quad1PlaneStrain :: initializeFrom(InputRecord *ir) ( numberOfGaussPoints == 16 ) ) ) { numberOfGaussPoints = 4; } - - return IRRT_OK; } @@ -194,37 +189,37 @@ Quad1PlaneStrain :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElem IntArray &controlNode, IntArray &controlDof, HuertaErrorEstimator :: AnalysisMode aMode) { - int inode, nodes = 4, iside, sides = 4, nd1, nd2; - FloatArray *corner [ 4 ], midSide [ 4 ], midNode, cor [ 4 ]; + int nodes = 4, sides = 4; double x = 0.0, y = 0.0; static int sideNode [ 4 ] [ 2 ] = { { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 1 } }; + FloatArray corner [ 4 ], midSide [ 4 ], midNode, cor [ 4 ]; if ( sMode == HuertaErrorEstimatorInterface :: NodeMode || ( sMode == HuertaErrorEstimatorInterface :: BCMode && aMode == HuertaErrorEstimator :: HEE_linear ) ) { - for ( inode = 0; inode < nodes; inode++ ) { + for ( int inode = 0; inode < nodes; inode++ ) { corner [ inode ] = this->giveNode(inode + 1)->giveCoordinates(); - if ( corner [ inode ]->giveSize() != 3 ) { + if ( corner [ inode ].giveSize() != 3 ) { cor [ inode ].resize(3); - cor [ inode ].at(1) = corner [ inode ]->at(1); - cor [ inode ].at(2) = corner [ inode ]->at(2); + cor [ inode ].at(1) = corner [ inode ].at(1); + cor [ inode ].at(2) = corner [ inode ].at(2); cor [ inode ].at(3) = 0.0; - corner [ inode ] = & ( cor [ inode ] ); + corner [ inode ] = cor [ inode ]; } - x += corner [ inode ]->at(1); - y += corner [ inode ]->at(2); + x += corner [ inode ].at(1); + y += corner [ inode ].at(2); } - for ( iside = 0; iside < sides; iside++ ) { + for ( int iside = 0; iside < sides; iside++ ) { midSide [ iside ].resize(3); - nd1 = sideNode [ iside ] [ 0 ] - 1; - nd2 = sideNode [ iside ] [ 1 ] - 1; + int nd1 = sideNode [ iside ] [ 0 ] - 1; + int nd2 = sideNode [ iside ] [ 1 ] - 1; - midSide [ iside ].at(1) = ( corner [ nd1 ]->at(1) + corner [ nd2 ]->at(1) ) / 2.0; - midSide [ iside ].at(2) = ( corner [ nd1 ]->at(2) + corner [ nd2 ]->at(2) ) / 2.0; + midSide [ iside ].at(1) = ( corner [ nd1 ].at(1) + corner [ nd2 ].at(1) ) / 2.0; + midSide [ iside ].at(2) = ( corner [ nd1 ].at(2) + corner [ nd2 ].at(2) ) / 2.0; midSide [ iside ].at(3) = 0.0; } diff --git a/src/sm/Elements/PlaneStrain/quad1planestrain.h b/src/sm/Elements/PlaneStrain/quad1planestrain.h index 9f9ce0add..b89921654 100644 --- a/src/sm/Elements/PlaneStrain/quad1planestrain.h +++ b/src/sm/Elements/PlaneStrain/quad1planestrain.h @@ -35,9 +35,9 @@ #ifndef quad1planestrain_h #define quad1planestrain_h -#include "Elements/structural2delement.h" -#include "ErrorEstimators/directerrorindicatorrc.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/structural2delement.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" #include "spatiallocalizer.h" @@ -66,40 +66,40 @@ class Quad1PlaneStrain : public PlaneStrainElement, public ZZNodalRecoveryModelI Quad1PlaneStrain(int n, Domain *d); virtual ~Quad1PlaneStrain(); - virtual FEInterpolation *giveInterpolation() const; - virtual Interface *giveInterface(InterfaceType it); + FEInterpolation *giveInterpolation() const override; + Interface *giveInterface(InterfaceType it) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; // HuertaErrorEstimatorInterface - virtual void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, - IntArray &localNodeIdArray, IntArray &globalNodeIdArray, - HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, - int &localNodeId, int &localElemId, int &localBcId, - IntArray &controlNode, IntArray &controlDof, - HuertaErrorEstimator :: AnalysisMode aMode); - virtual void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); + void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, + IntArray &localNodeIdArray, IntArray &globalNodeIdArray, + HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, + int &localNodeId, int &localElemId, int &localBcId, + IntArray &controlNode, IntArray &controlDof, + HuertaErrorEstimator :: AnalysisMode aMode) override; + void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Quad1PlaneStrain_Name; } - virtual const char *giveClassName() const { return "Quad1PlaneStrain"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_Quad1PlaneStrain_Name; } + const char *giveClassName() const override { return "Quad1PlaneStrain"; } + void initializeFrom(InputRecord &ir) override; protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; - virtual int giveNumberOfIPForMassMtrxIntegration() { return 4; } + int giveNumberOfIPForMassMtrxIntegration() override { return 4; } }; } // end namespace oofem #endif // quad1planestrain_h diff --git a/src/sm/Elements/PlaneStrain/trplanestrain.C b/src/sm/Elements/PlaneStrain/trplanestrain.C index fcd0d9fed..1751bff49 100644 --- a/src/sm/Elements/PlaneStrain/trplanestrain.C +++ b/src/sm/Elements/PlaneStrain/trplanestrain.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/PlaneStrain/trplanestrain.h" +#include "sm/Elements/PlaneStrain/trplanestrain.h" #include "fei2dtrlin.h" #include "node.h" #include "crosssection.h" @@ -90,21 +90,15 @@ TrPlaneStrain :: giveInterface(InterfaceType interface) return NULL; } - -IRResultType -TrPlaneStrain :: initializeFrom(InputRecord *ir) +void +TrPlaneStrain :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 1; - IRResultType result = PlaneStrainElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + PlaneStrainElement :: initializeFrom(ir); if ( numberOfGaussPoints != 1 ) { numberOfGaussPoints = 1; } - - return IRRT_OK; } @@ -165,37 +159,37 @@ TrPlaneStrain :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement IntArray &controlNode, IntArray &controlDof, HuertaErrorEstimator :: AnalysisMode aMode) { - int inode, nodes = 3, iside, sides = 3, nd1, nd2; - FloatArray *corner [ 3 ], midSide [ 3 ], midNode, cor [ 3 ]; + int nodes = 3, sides = 3; + FloatArray corner [ 3 ], midSide [ 3 ], midNode, cor [ 3 ]; double x = 0.0, y = 0.0; static int sideNode [ 3 ] [ 2 ] = { { 1, 2 }, { 2, 3 }, { 3, 1 } }; if ( sMode == HuertaErrorEstimatorInterface :: NodeMode || ( sMode == HuertaErrorEstimatorInterface :: BCMode && aMode == HuertaErrorEstimator :: HEE_linear ) ) { - for ( inode = 0; inode < nodes; inode++ ) { + for ( int inode = 0; inode < nodes; inode++ ) { corner [ inode ] = this->giveNode(inode + 1)->giveCoordinates(); - if ( corner [ inode ]->giveSize() != 3 ) { + if ( corner [ inode ].giveSize() != 3 ) { cor [ inode ].resize(3); - cor [ inode ].at(1) = corner [ inode ]->at(1); - cor [ inode ].at(2) = corner [ inode ]->at(2); + cor [ inode ].at(1) = corner [ inode ].at(1); + cor [ inode ].at(2) = corner [ inode ].at(2); cor [ inode ].at(3) = 0.0; - corner [ inode ] = & ( cor [ inode ] ); + corner [ inode ] = cor [ inode ]; } - x += corner [ inode ]->at(1); - y += corner [ inode ]->at(2); + x += corner [ inode ].at(1); + y += corner [ inode ].at(2); } - for ( iside = 0; iside < sides; iside++ ) { + for ( int iside = 0; iside < sides; iside++ ) { midSide [ iside ].resize(3); - nd1 = sideNode [ iside ] [ 0 ] - 1; - nd2 = sideNode [ iside ] [ 1 ] - 1; + int nd1 = sideNode [ iside ] [ 0 ] - 1; + int nd2 = sideNode [ iside ] [ 1 ] - 1; - midSide [ iside ].at(1) = ( corner [ nd1 ]->at(1) + corner [ nd2 ]->at(1) ) / 2.0; - midSide [ iside ].at(2) = ( corner [ nd1 ]->at(2) + corner [ nd2 ]->at(2) ) / 2.0; + midSide [ iside ].at(1) = ( corner [ nd1 ].at(1) + corner [ nd2 ].at(1) ) / 2.0; + midSide [ iside ].at(2) = ( corner [ nd1 ].at(2) + corner [ nd2 ].at(2) ) / 2.0; midSide [ iside ].at(3) = 0.0; } diff --git a/src/sm/Elements/PlaneStrain/trplanestrain.h b/src/sm/Elements/PlaneStrain/trplanestrain.h index f8cb084c7..97c3ceed7 100644 --- a/src/sm/Elements/PlaneStrain/trplanestrain.h +++ b/src/sm/Elements/PlaneStrain/trplanestrain.h @@ -35,10 +35,10 @@ #ifndef trplanstrain_h #define trplanstrain_h -#include "Elements/structural2delement.h" -#include "ErrorEstimators/directerrorindicatorrc.h" -#include "ErrorEstimators/zzerrorestimator.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/structural2delement.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -68,39 +68,39 @@ public HuertaErrorEstimatorInterface TrPlaneStrain(int n, Domain * d); virtual ~TrPlaneStrain() { } - virtual FEInterpolation *giveInterpolation() const; - virtual Interface *giveInterface(InterfaceType it); + FEInterpolation *giveInterpolation() const override; + Interface *giveInterface(InterfaceType it) override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; // HuertaErrorEstimatorInterface - virtual void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, - IntArray &localNodeIdArray, IntArray &globalNodeIdArray, - HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, - int &localNodeId, int &localElemId, int &localBcId, - IntArray &controlNode, IntArray &controlDof, - HuertaErrorEstimator :: AnalysisMode aMode); - virtual void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); + void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, + IntArray &localNodeIdArray, IntArray &globalNodeIdArray, + HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, + int &localNodeId, int &localElemId, int &localBcId, + IntArray &controlNode, IntArray &controlDof, + HuertaErrorEstimator :: AnalysisMode aMode) override; + void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_TrPlaneStrain_Name; } - virtual const char *giveClassName() const { return "TrPlaneStrain"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_TrPlaneStrain_Name; } + const char *giveClassName() const override { return "TrPlaneStrain"; } + void initializeFrom(InputRecord &ir) override; protected: - virtual int giveNumberOfIPForMassMtrxIntegration() { return 1; } + int giveNumberOfIPForMassMtrxIntegration() override { return 1; } }; } // end namespace oofem #endif // trplanstrain_h diff --git a/src/sm/Elements/PlaneStress/basicelement.C b/src/sm/Elements/PlaneStress/basicelement.C index b6583cc88..bc7137a12 100644 --- a/src/sm/Elements/PlaneStress/basicelement.C +++ b/src/sm/Elements/PlaneStress/basicelement.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/PlaneStress/basicelement.h" +#include "sm/Elements/PlaneStress/basicelement.h" #include "fei2dtrlin.h" #include "classfactory.h" diff --git a/src/sm/Elements/PlaneStress/basicelement.h b/src/sm/Elements/PlaneStress/basicelement.h index 71355712f..159daa4c3 100644 --- a/src/sm/Elements/PlaneStress/basicelement.h +++ b/src/sm/Elements/PlaneStress/basicelement.h @@ -35,7 +35,7 @@ #ifndef basicelement_h #define basicelement_h -#include "Elements/structural2delement.h" +#include "sm/Elements/structural2delement.h" #define _IFT_BasicElement_Name "basicelement" namespace oofem { @@ -69,17 +69,17 @@ class BasicElement : public PlaneStressElement /// Destructor. virtual ~BasicElement() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; // Necessary for reading input files: - virtual const char *giveInputRecordName() const { return _IFT_BasicElement_Name; } + const char *giveInputRecordName() const override { return _IFT_BasicElement_Name; } // Necessary for debug messages: - virtual const char *giveClassName() const { return "BasicElement"; } + const char *giveClassName() const override { return "BasicElement"; } protected: // Support for computing the mass matrix needed for dynamic simulations - virtual int giveNumberOfIPForMassMtrxIntegration() { return 4; } + int giveNumberOfIPForMassMtrxIntegration() override { return 4; } }; } // end namespace oofem #endif // basicelement_h diff --git a/src/sm/Elements/PlaneStress/basicelementquad.h b/src/sm/Elements/PlaneStress/basicelementquad.h index f8b2a765f..f11b2d0d8 100644 --- a/src/sm/Elements/PlaneStress/basicelementquad.h +++ b/src/sm/Elements/PlaneStress/basicelementquad.h @@ -35,7 +35,7 @@ #ifndef basicelementquad_h #define basicelementquad_h -#include "Elements/structural2delement.h" +#include "sm/Elements/structural2delement.h" #define _IFT_BasicElementQuad_Name "basicelementquad" namespace oofem { @@ -65,14 +65,14 @@ class BasicElementQuad : public PlaneStressElement /// Destructor. virtual ~BasicElementQuad() { } - virtual FEInterpolation *giveInterpolation() const; - virtual const char *giveInputRecordName() const { return _IFT_BasicElementQuad_Name; } - virtual const char *giveClassName() const { return "BasicElementQuad"; } + FEInterpolation *giveInterpolation() const override; + const char *giveInputRecordName() const override { return _IFT_BasicElementQuad_Name; } + const char *giveClassName() const override { return "BasicElementQuad"; } protected: // - Support for computing the mass matrix needed for dynamic simulations - virtual int giveNumberOfIPForMassMtrxIntegration() { return 4; } + int giveNumberOfIPForMassMtrxIntegration() override { return 4; } }; diff --git a/src/sm/Elements/PlaneStress/linquad3d_planestress.C b/src/sm/Elements/PlaneStress/linquad3d_planestress.C index 0bdc9a4e2..a06893294 100644 --- a/src/sm/Elements/PlaneStress/linquad3d_planestress.C +++ b/src/sm/Elements/PlaneStress/linquad3d_planestress.C @@ -32,17 +32,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/linquad3d_planestress.h" +#include "sm/Elements/PlaneStress/linquad3d_planestress.h" #include "classfactory.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "gausspoint.h" #ifdef __OOFEG #include "oofeggraphiccontext.h" #include "oofegutils.h" #include "connectivitytable.h" - #include "Materials/rcm2.h" + #include "sm/Materials/rcm2.h" #endif namespace oofem { @@ -101,10 +101,9 @@ LinQuad3DPlaneStress :: computeLocalNodalCoordinates(std::vector< FloatArray > & lxy.resize(4); - const FloatArray *nc; for ( int i = 0; i < 4; i++ ) { - nc = this->giveNode(i + 1)->giveCoordinates(); - lxy[i].beProductOf(* GtoLRotationMatrix, *nc); + const auto &nc = this->giveNode(i + 1)->giveCoordinates(); + lxy[i].beProductOf(* GtoLRotationMatrix, nc); } } @@ -133,8 +132,8 @@ LinQuad3DPlaneStress :: computeGtoLRotationMatrix() FloatArray e1, e2, e3, help; // compute e1' = [N2-N1] and help = [N3-N1] - e1.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - help.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); + e1.beDifferenceOf( this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); + help.beDifferenceOf( this->giveNode(3)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); // let us normalize e1' e1.normalize(); diff --git a/src/sm/Elements/PlaneStress/linquad3d_planestress.h b/src/sm/Elements/PlaneStress/linquad3d_planestress.h index 35bd02da6..ad2b6edea 100644 --- a/src/sm/Elements/PlaneStress/linquad3d_planestress.h +++ b/src/sm/Elements/PlaneStress/linquad3d_planestress.h @@ -35,9 +35,9 @@ #ifndef linquad3d_planestress_h #define linquad3d_planestress_h -#include "Elements/PlaneStress/planstrss.h" -#include "ErrorEstimators/directerrorindicatorrc.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/PlaneStress/planstrss.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" #include "spatiallocalizer.h" @@ -79,26 +79,25 @@ class LinQuad3DPlaneStress : public PlaneStress2d LinQuad3DPlaneStress(int n, Domain * d); virtual ~LinQuad3DPlaneStress(); - virtual Interface *giveInterface(InterfaceType it); - virtual FEICellGeometry* giveCellGeometryWrapper(); + Interface *giveInterface(InterfaceType it) override; + FEICellGeometry* giveCellGeometryWrapper() override; void computeLocalNodalCoordinates(std::vector< FloatArray > &lxy); - virtual int computeNumberOfDofs() { return 8; } - virtual int computeNumberOfGlobalDofs() { return 12; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - + int computeNumberOfDofs() override { return 8; } + int computeNumberOfGlobalDofs() override { return 12; } + void giveDofManDofIDMask(int inode, IntArray &) const override; const FloatMatrix *computeGtoLRotationMatrix(); - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; void giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep); // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LinQuad3DPlaneStress_Name; } - virtual const char *giveClassName() const { return "LinQuad3DPlaneStress"; } + const char *giveInputRecordName() const override { return _IFT_LinQuad3DPlaneStress_Name; } + const char *giveClassName() const override { return "LinQuad3DPlaneStress"; } }; } // end namespace oofem #endif // linquad3d_planestress_h diff --git a/src/sm/Elements/PlaneStress/planestresselementevaluator.C b/src/sm/Elements/PlaneStress/planestresselementevaluator.C index 140ec5ecb..d9a1a5c34 100644 --- a/src/sm/Elements/PlaneStress/planestresselementevaluator.C +++ b/src/sm/Elements/PlaneStress/planestresselementevaluator.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/planestresselementevaluator.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/PlaneStress/planestresselementevaluator.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "floatarray.h" #include "floatmatrix.h" #include "domain.h" @@ -94,11 +94,11 @@ double PlaneStressStructuralElementEvaluator :: computeVolumeAround(GaussPoint * void PlaneStressStructuralElementEvaluator :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralCrossSection * >( this->giveElement()->giveCrossSection() )->giveRealStress_PlaneStress(answer, gp, strain, tStep); + answer = static_cast< StructuralCrossSection * >( this->giveElement()->giveCrossSection() )->giveRealStress_PlaneStress(strain, gp, tStep); } void PlaneStressStructuralElementEvaluator :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - static_cast< StructuralCrossSection * >( this->giveElement()->giveCrossSection() )->giveStiffnessMatrix_PlaneStress(answer, rMode, gp, tStep); + answer = static_cast< StructuralCrossSection * >( this->giveElement()->giveCrossSection() )->giveStiffnessMatrix_PlaneStress(rMode, gp, tStep); } } // end namespace oofem diff --git a/src/sm/Elements/PlaneStress/planestresselementevaluator.h b/src/sm/Elements/PlaneStress/planestresselementevaluator.h index 6c8228d3d..eb336f601 100644 --- a/src/sm/Elements/PlaneStress/planestresselementevaluator.h +++ b/src/sm/Elements/PlaneStress/planestresselementevaluator.h @@ -35,7 +35,7 @@ #ifndef planestresselementevaluator_h #define planestresselementevaluator_h -#include "../sm/Elements/structuralelementevaluator.h" +#include "sm/Elements/structuralelementevaluator.h" namespace oofem { /** @@ -51,15 +51,15 @@ class PlaneStressStructuralElementEvaluator : public StructuralElementEvaluator * Assemble interpolation matrix at given IP. * In case of IGAElements, N is assumed to contain only nonzero interpolation functions. */ - virtual void computeNMatrixAt(FloatMatrix &answer, GaussPoint *gp); + void computeNMatrixAt(FloatMatrix &answer, GaussPoint *gp) override; /** * Assembles the strain-displacement matrix of the receiver at given integration point. * In case of IGAElements, B is assumed to contain only contribution from nonzero interpolation functions. */ - virtual void computeBMatrixAt(FloatMatrix &answer, GaussPoint *gp); - virtual double computeVolumeAround(GaussPoint *gp); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeBMatrixAt(FloatMatrix &answer, GaussPoint *gp) override; + double computeVolumeAround(GaussPoint *gp) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; void giveDofManDofIDMask(int inode, IntArray &answer) const { answer = {D_u, D_v}; } diff --git a/src/sm/Elements/PlaneStress/planstrss.C b/src/sm/Elements/PlaneStress/planstrss.C index 48f491190..ac0274bd3 100644 --- a/src/sm/Elements/PlaneStress/planstrss.C +++ b/src/sm/Elements/PlaneStress/planstrss.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/planstrss.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/PlaneStress/planstrss.h" +#include "sm/Materials/structuralms.h" #include "fei2dquadlin.h" #include "node.h" #include "crosssection.h" @@ -51,7 +51,7 @@ #include "oofeggraphiccontext.h" #include "oofegutils.h" #include "connectivitytable.h" - #include "Materials/rcm2.h" + #include "sm/Materials/rcm2.h" #endif namespace oofem { @@ -135,21 +135,17 @@ PlaneStress2d :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) } -IRResultType -PlaneStress2d :: initializeFrom(InputRecord *ir) + +void +PlaneStress2d :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 4; - IRResultType result = PlaneStressElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + PlaneStressElement :: initializeFrom(ir); if ( numberOfGaussPoints != 1 && numberOfGaussPoints != 4 && numberOfGaussPoints != 9 && numberOfGaussPoints != 16 && numberOfGaussPoints != 25 ) { numberOfGaussPoints = 4; OOFEM_WARNING("Number of Gauss points enforced to 4"); } - - return IRRT_OK; } @@ -276,37 +272,37 @@ PlaneStress2d :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement IntArray &controlNode, IntArray &controlDof, HuertaErrorEstimator :: AnalysisMode aMode) { - int inode, nodes = 4, iside, sides = 4, nd1, nd2; - FloatArray *corner [ 4 ], midSide [ 4 ], midNode, cor [ 4 ]; + int nodes = 4, sides = 4; double x = 0.0, y = 0.0; static int sideNode [ 4 ] [ 2 ] = { { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 1 } }; + FloatArray corner [ 4 ], midSide [ 4 ], midNode, cor [ 4 ]; if ( sMode == HuertaErrorEstimatorInterface :: NodeMode || ( sMode == HuertaErrorEstimatorInterface :: BCMode && aMode == HuertaErrorEstimator :: HEE_linear ) ) { - for ( inode = 0; inode < nodes; inode++ ) { + for ( int inode = 0; inode < nodes; inode++ ) { corner [ inode ] = this->giveNode(inode + 1)->giveCoordinates(); - if ( corner [ inode ]->giveSize() != 3 ) { + if ( corner [ inode ].giveSize() != 3 ) { cor [ inode ].resize(3); - cor [ inode ].at(1) = corner [ inode ]->at(1); - cor [ inode ].at(2) = corner [ inode ]->at(2); + cor [ inode ].at(1) = corner [ inode ].at(1); + cor [ inode ].at(2) = corner [ inode ].at(2); cor [ inode ].at(3) = 0.0; - corner [ inode ] = & ( cor [ inode ] ); + corner [ inode ] = cor [ inode ]; } - x += corner [ inode ]->at(1); - y += corner [ inode ]->at(2); + x += corner [ inode ].at(1); + y += corner [ inode ].at(2); } - for ( iside = 0; iside < sides; iside++ ) { + for ( int iside = 0; iside < sides; iside++ ) { midSide [ iside ].resize(3); - nd1 = sideNode [ iside ] [ 0 ] - 1; - nd2 = sideNode [ iside ] [ 1 ] - 1; + int nd1 = sideNode [ iside ] [ 0 ] - 1; + int nd2 = sideNode [ iside ] [ 1 ] - 1; - midSide [ iside ].at(1) = ( corner [ nd1 ]->at(1) + corner [ nd2 ]->at(1) ) / 2.0; - midSide [ iside ].at(2) = ( corner [ nd1 ]->at(2) + corner [ nd2 ]->at(2) ) / 2.0; + midSide [ iside ].at(1) = ( corner [ nd1 ].at(1) + corner [ nd2 ].at(1) ) / 2.0; + midSide [ iside ].at(2) = ( corner [ nd1 ].at(2) + corner [ nd2 ].at(2) ) / 2.0; midSide [ iside ].at(3) = 0.0; } diff --git a/src/sm/Elements/PlaneStress/planstrss.h b/src/sm/Elements/PlaneStress/planstrss.h index 102db39e9..a0fe0f1c5 100644 --- a/src/sm/Elements/PlaneStress/planstrss.h +++ b/src/sm/Elements/PlaneStress/planstrss.h @@ -35,9 +35,9 @@ #ifndef planstrss_h #define planstrss_h -#include "Elements/structural2delement.h" -#include "ErrorEstimators/directerrorindicatorrc.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/structural2delement.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" #include "spatiallocalizer.h" @@ -64,43 +64,43 @@ public HuertaErrorEstimatorInterface PlaneStress2d(int n, Domain * d); virtual ~PlaneStress2d(); - virtual double giveCharacteristicSize(GaussPoint *gp, FloatArray &normalToCrackPlane, ElementCharSizeMethod method); - virtual double giveParentElSize() const { return 4.0; } + double giveCharacteristicSize(GaussPoint *gp, FloatArray &normalToCrackPlane, ElementCharSizeMethod method) override; + double giveParentElSize() const override { return 4.0; } - virtual Interface *giveInterface(InterfaceType it); - virtual FEInterpolation *giveInterpolation() const; + Interface *giveInterface(InterfaceType it) override; + FEInterpolation *giveInterpolation() const override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; - virtual void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, - IntArray &localNodeIdArray, IntArray &globalNodeIdArray, - HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, - int &localNodeId, int &localElemId, int &localBcId, - IntArray &controlNode, IntArray &controlDof, - HuertaErrorEstimator :: AnalysisMode aMode); - virtual void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); + void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, + IntArray &localNodeIdArray, IntArray &globalNodeIdArray, + HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, + int &localNodeId, int &localElemId, int &localBcId, + IntArray &controlNode, IntArray &controlDof, + HuertaErrorEstimator :: AnalysisMode aMode) override; + void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_PlaneStress2d_Name; } - virtual const char *giveClassName() const { return "PlaneStress2d"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_PlaneStress2d_Name; } + const char *giveClassName() const override { return "PlaneStress2d"; } + void initializeFrom(InputRecord &ir) override; protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; - int giveNumberOfIPForMassMtrxIntegration() { return 4; } + int giveNumberOfIPForMassMtrxIntegration() override { return 4; } }; } // end namespace oofem #endif // planstrss_h diff --git a/src/sm/Elements/PlaneStress/planstrssphf.C b/src/sm/Elements/PlaneStress/planstrssphf.C index 3e6e3117b..46808e9b5 100644 --- a/src/sm/Elements/PlaneStress/planstrssphf.C +++ b/src/sm/Elements/PlaneStress/planstrssphf.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/planstrssphf.h" +#include "sm/Elements/PlaneStress/planstrssphf.h" #include "classfactory.h" namespace oofem { diff --git a/src/sm/Elements/PlaneStress/planstrssphf.h b/src/sm/Elements/PlaneStress/planstrssphf.h index ddda77c31..f718320f1 100644 --- a/src/sm/Elements/PlaneStress/planstrssphf.h +++ b/src/sm/Elements/PlaneStress/planstrssphf.h @@ -35,8 +35,8 @@ #ifndef planstrssphf_h #define planstrssphf_h -#include "../sm/Elements/phasefieldelement.h" -#include "../sm/Elements/PlaneStress/planstrss.h" +#include "sm/Elements/phasefieldelement.h" +#include "sm/Elements/PlaneStress/planstrss.h" #define _IFT_PlaneStressPhF2d_Name "PlaneStressPhF2d" @@ -54,21 +54,21 @@ class PlaneStressPhF2d : public PlaneStress2d, public PhaseFieldElement PlaneStressPhF2d(int n, Domain *d); virtual ~PlaneStressPhF2d() { } - NLStructuralElement *giveElement() { return this; } - virtual int computeNumberOfDofs() { return 12; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual void giveDofManDofIDMask_u(IntArray &answer); - virtual void giveDofManDofIDMask_d(IntArray &answer); + NLStructuralElement *giveElement() override { return this; } + int computeNumberOfDofs() override { return 12; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveDofManDofIDMask_u(IntArray &answer) override; + void giveDofManDofIDMask_d(IntArray &answer) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_PlaneStressPhF2d_Name; } - virtual const char *giveClassName() const { return "PlaneStressPhF2d"; } + const char *giveInputRecordName() const override { return _IFT_PlaneStressPhF2d_Name; } + const char *giveClassName() const override { return "PlaneStressPhF2d"; } - virtual void computeStiffnessMatrix( FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep ) + void computeStiffnessMatrix( FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep ) override { PhaseFieldElement :: computeStiffnessMatrix( answer, rMode, tStep ); } - virtual void giveInternalForcesVector( FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0 ) + void giveInternalForcesVector( FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0 ) override { PhaseFieldElement :: giveInternalForcesVector( answer, tStep, useUpdatedGpRecord ); } diff --git a/src/sm/Elements/PlaneStress/planstrssxfem.C b/src/sm/Elements/PlaneStress/planstrssxfem.C index 8743615c7..59d0dcaa1 100644 --- a/src/sm/Elements/PlaneStress/planstrssxfem.C +++ b/src/sm/Elements/PlaneStress/planstrssxfem.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/planstrssxfem.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/PlaneStress/planstrssxfem.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "xfem/xfemelementinterface.h" #include "xfem/enrichmentfunction.h" #include "xfem/enrichmentitem.h" @@ -295,18 +295,11 @@ void PlaneStress2dXfem :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) #endif -IRResultType -PlaneStress2dXfem :: initializeFrom(InputRecord *ir) +void +PlaneStress2dXfem :: initializeFrom(InputRecord &ir) { - IRResultType result; - - result = PlaneStress2d :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - result = XfemStructuralElementInterface :: initializeCZFrom(ir); - return result; + PlaneStress2d :: initializeFrom(ir); + XfemStructuralElementInterface :: initializeCZFrom(ir); } MaterialMode PlaneStress2dXfem :: giveMaterialMode() @@ -338,7 +331,7 @@ PlaneStress2dXfem :: giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, // Node coordinates std :: vector< FloatArray >nodeCoords; for(int i = 1; i <= 4; i++) { - FloatArray &x = *(giveDofManager(i)->giveCoordinates()); + const auto &x = giveDofManager(i)->giveCoordinates(); nodeCoords.push_back(x); vtkPieces[0].setNodeCoords(i, x); @@ -359,7 +352,7 @@ PlaneStress2dXfem :: giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, // Export nodal variables from primary fields - vtkPieces[0].setNumberOfPrimaryVarsToExport(primaryVarsToExport.giveSize(), numTotalNodes); + vtkPieces[0].setNumberOfPrimaryVarsToExport(primaryVarsToExport, numTotalNodes); for ( int fieldNum = 1; fieldNum <= primaryVarsToExport.giveSize(); fieldNum++ ) { UnknownType type = ( UnknownType ) primaryVarsToExport.at(fieldNum); @@ -392,7 +385,7 @@ PlaneStress2dXfem :: giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, u = {uTemp[0], uTemp[1], 0.0}; } - vtkPieces[0].setPrimaryVarInNode(fieldNum, nodeInd, u); + vtkPieces[0].setPrimaryVarInNode(type, nodeInd, u); } else { printf("fieldNum: %d\n", fieldNum); // TODO: Implement @@ -407,11 +400,11 @@ PlaneStress2dXfem :: giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, // Export nodal variables from internal fields - vtkPieces[0].setNumberOfInternalVarsToExport(0, numTotalNodes); + vtkPieces[0].setNumberOfInternalVarsToExport(internalVarsToExport, numTotalNodes); // Export cell variables - vtkPieces[0].setNumberOfCellVarsToExport(cellVarsToExport.giveSize(), 1); + vtkPieces[0].setNumberOfCellVarsToExport(cellVarsToExport, 1); for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) { InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i); FloatArray average; @@ -438,7 +431,7 @@ PlaneStress2dXfem :: giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, } } - vtkPieces[0].setCellVar( i, 1, averageVoigt ); + vtkPieces[0].setCellVar( type, 1, averageVoigt ); } @@ -473,7 +466,7 @@ PlaneStress2dXfem :: giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, for(int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++) { DofManager *dMan = giveDofManager(elNodeInd); - ei->evalLevelSetNormalInNode(levelSetInNode, dMan->giveGlobalNumber(), *(dMan->giveCoordinates()) ); + ei->evalLevelSetNormalInNode(levelSetInNode, dMan->giveGlobalNumber(), dMan->giveCoordinates() ); levelSet += N.at(elNodeInd)*levelSetInNode; } @@ -487,7 +480,7 @@ PlaneStress2dXfem :: giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, for(int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++) { DofManager *dMan = giveDofManager(elNodeInd); - ei->evalLevelSetTangInNode(levelSetInNode, dMan->giveGlobalNumber(), *(dMan->giveCoordinates()) ); + ei->evalLevelSetTangInNode(levelSetInNode, dMan->giveGlobalNumber(), dMan->giveCoordinates() ); levelSet += N.at(elNodeInd)*levelSetInNode; } diff --git a/src/sm/Elements/PlaneStress/planstrssxfem.h b/src/sm/Elements/PlaneStress/planstrssxfem.h index a3e72a6f3..9cd242108 100644 --- a/src/sm/Elements/PlaneStress/planstrssxfem.h +++ b/src/sm/Elements/PlaneStress/planstrssxfem.h @@ -35,8 +35,8 @@ #ifndef planstrssxfem_h #define planstrssxfem_h -#include "../sm/Elements/PlaneStress/planstrss.h" -#include "../sm/xfem/xfemstructuralelementinterface.h" +#include "sm/Elements/PlaneStress/planstrss.h" +#include "sm/xfem/xfemstructuralelementinterface.h" #include "vtkxmlexportmodule.h" #define _IFT_PlaneStress2dXfem_Name "planestress2dxfem" @@ -50,8 +50,8 @@ namespace oofem { class PlaneStress2dXfem : public PlaneStress2d, public XfemStructuralElementInterface, public VTKXMLExportModuleElementInterface { protected: - virtual void updateYourself(TimeStep *tStep); - virtual void postInitialize(); + void updateYourself(TimeStep *tStep) override; + void postInitialize() override; public: /// Constructor @@ -59,45 +59,45 @@ class PlaneStress2dXfem : public PlaneStress2d, public XfemStructuralElementInte /// Destructor virtual ~PlaneStress2dXfem() { } - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual const char *giveInputRecordName() const { return _IFT_PlaneStress2dXfem_Name; } - virtual const char *giveClassName() const { return "PlaneStress2dXfem"; } - virtual int computeNumberOfDofs(); - virtual void computeGaussPoints(); + const char *giveInputRecordName() const override { return _IFT_PlaneStress2dXfem_Name; } + const char *giveClassName() const override { return "PlaneStress2dXfem"; } + int computeNumberOfDofs() override; + void computeGaussPoints() override; void increaseNumGP(); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, - int lowerIndx = 1, int upperIndx = ALL_STRAINS); - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *, TimeStep *tStep); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; - virtual void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override; - virtual void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) { XfemStructuralElementInterface :: XfemElementInterface_computeConsistentMassMatrix(answer, tStep, mass, ipDensity); } + void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) override + { XfemStructuralElementInterface :: XfemElementInterface_computeConsistentMassMatrix(answer, tStep, mass, ipDensity); } - virtual Element_Geometry_Type giveGeometryType() const; + Element_Geometry_Type giveGeometryType() const override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - //virtual void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep); + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + //void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) override; #endif - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode(); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override; + void giveInputRecord(DynamicInputRecord &input) override; /// VTK Interface - virtual void giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep); + void giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep) override; }; } // end namespace oofem diff --git a/src/sm/Elements/PlaneStress/q9planstrss.C b/src/sm/Elements/PlaneStress/q9planstrss.C index 8c2d01050..2cc78dd13 100644 --- a/src/sm/Elements/PlaneStress/q9planstrss.C +++ b/src/sm/Elements/PlaneStress/q9planstrss.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/PlaneStress/q9planstrss.h" +#include "sm/Elements/PlaneStress/q9planstrss.h" #include "fei2dquadbiquad.h" #include "crosssection.h" #include "gausspoint.h" diff --git a/src/sm/Elements/PlaneStress/q9planstrss.h b/src/sm/Elements/PlaneStress/q9planstrss.h index eaf12ec2f..6da5d8bef 100644 --- a/src/sm/Elements/PlaneStress/q9planstrss.h +++ b/src/sm/Elements/PlaneStress/q9planstrss.h @@ -35,7 +35,7 @@ #ifndef Q9PLANSTRSS_H_ #define Q9PLANSTRSS_H_ -#include "Elements/structural2delement.h" +#include "sm/Elements/structural2delement.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" @@ -60,14 +60,14 @@ class Q9PlaneStress2d : public PlaneStressElement, public ZZNodalRecoveryModelIn virtual ~Q9PlaneStress2d() { } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Q9PlaneStress2d_Name; } - virtual const char *giveClassName() const { return "Q9PlaneStress2d"; } - virtual FEInterpolation *giveInterpolation() const; + const char *giveInputRecordName() const override { return _IFT_Q9PlaneStress2d_Name; } + const char *giveClassName() const override { return "Q9PlaneStress2d"; } + FEInterpolation *giveInterpolation() const override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; }; } // end namespace oofem diff --git a/src/sm/Elements/PlaneStress/qplanestressgrad.h b/src/sm/Elements/PlaneStress/qplanestressgrad.h deleted file mode 100644 index 39a08a231..000000000 --- a/src/sm/Elements/PlaneStress/qplanestressgrad.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef qplanestressgrad_h -#define qplanestressgrad_h - -#include "../sm/Elements/PlaneStress/qplanstrss.h" -#include "../sm/Elements/graddpelement.h" - -#define _IFT_QPlaneStressGrad_Name "qplanestressgrad" - -namespace oofem { -class FEI2dQuadLin; - -class QPlaneStressGrad : public QPlaneStress2d, public GradDpElement -{ -protected: - static FEI2dQuadLin interpolation_lin; - -public: - QPlaneStressGrad(int n, Domain * d); - virtual ~QPlaneStressGrad() { } - - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual const char *giveInputRecordName() const { return _IFT_QPlaneStressGrad_Name; } - virtual const char *giveClassName() const { return "QPlaneStressGrad"; } - virtual MaterialMode giveMaterialMode() { return _PlaneStress; } - virtual int computeNumberOfDofs() { return 20; } - -protected: - virtual void computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { GradDpElement :: computeStiffnessMatrix(answer, rMode, tStep); } - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) { GradDpElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } - - virtual void computeGaussPoints(); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual StructuralElement *giveStructuralElement() { return this; } - virtual NLStructuralElement *giveNLStructuralElement() { return this; } -}; -} // end namespace oofem -#endif // qplanestressgrad_h diff --git a/src/sm/Elements/PlaneStress/qplanstrss.C b/src/sm/Elements/PlaneStress/qplanstrss.C index 96a6919a5..ca33924f7 100644 --- a/src/sm/Elements/PlaneStress/qplanstrss.C +++ b/src/sm/Elements/PlaneStress/qplanstrss.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/qplanstrss.h" +#include "sm/Elements/PlaneStress/qplanstrss.h" #include "fei2dquadquad.h" #include "crosssection.h" #include "gausspoint.h" diff --git a/src/sm/Elements/PlaneStress/qplanstrss.h b/src/sm/Elements/PlaneStress/qplanstrss.h index 9ac8bb116..8c81ce056 100644 --- a/src/sm/Elements/PlaneStress/qplanstrss.h +++ b/src/sm/Elements/PlaneStress/qplanstrss.h @@ -36,7 +36,7 @@ #ifndef qplanstrss_h #define qplanstrss_h -#include "Elements/structural2delement.h" +#include "sm/Elements/structural2delement.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" @@ -58,21 +58,21 @@ class QPlaneStress2d : public PlaneStressElement, public ZZNodalRecoveryModelInt QPlaneStress2d(int n, Domain * d); virtual ~QPlaneStress2d() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QPlaneStress2d_Name; } - virtual const char *giveClassName() const { return "QPlaneStress2d"; } - - virtual Interface *giveInterface(InterfaceType it); + const char *giveInputRecordName() const override { return _IFT_QPlaneStress2d_Name; } + const char *giveClassName() const override { return "QPlaneStress2d"; } - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + Interface *giveInterface(InterfaceType it) override; + + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif }; diff --git a/src/sm/Elements/PlaneStress/qplanstrssphf.C b/src/sm/Elements/PlaneStress/qplanstrssphf.C index f2b046e40..2827cc7f6 100644 --- a/src/sm/Elements/PlaneStress/qplanstrssphf.C +++ b/src/sm/Elements/PlaneStress/qplanstrssphf.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/qplanstrssphf.h" +#include "sm/Elements/PlaneStress/qplanstrssphf.h" #include "classfactory.h" namespace oofem { diff --git a/src/sm/Elements/PlaneStress/qplanstrssphf.h b/src/sm/Elements/PlaneStress/qplanstrssphf.h index 75488a424..966aff01d 100644 --- a/src/sm/Elements/PlaneStress/qplanstrssphf.h +++ b/src/sm/Elements/PlaneStress/qplanstrssphf.h @@ -35,8 +35,8 @@ #ifndef qplanstrssphf_h #define qplanstrssphf_h -#include "../sm/Elements/phasefieldelement.h" -#include "../sm/Elements/PlaneStress/qplanstrss.h" +#include "sm/Elements/phasefieldelement.h" +#include "sm/Elements/PlaneStress/qplanstrss.h" #define _IFT_QPlaneStressPhF2d_Name "QPlaneStressPhF2d" @@ -52,23 +52,22 @@ class QPlaneStressPhF2d : public QPlaneStress2d, public PhaseFieldElement QPlaneStressPhF2d(int n, Domain *d); virtual ~QPlaneStressPhF2d() { } - NLStructuralElement *giveElement() { return this; } + NLStructuralElement *giveElement() override { return this; } - virtual int computeNumberOfDofs() { return 24; } - virtual void giveDofManDofIDMask( int inode, IntArray &answer ) const; - virtual void giveDofManDofIDMask_u( IntArray &answer ); - virtual void giveDofManDofIDMask_d( IntArray &answer ); + int computeNumberOfDofs() override { return 24; } + void giveDofManDofIDMask( int inode, IntArray &answer ) const override; + void giveDofManDofIDMask_u( IntArray &answer ) override; + void giveDofManDofIDMask_d( IntArray &answer ) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QPlaneStressPhF2d_Name; } - virtual const char *giveClassName() const { return "QPlaneStressPhF2d"; } + const char *giveInputRecordName() const override { return _IFT_QPlaneStressPhF2d_Name; } + const char *giveClassName() const override { return "QPlaneStressPhF2d"; } - - virtual void computeStiffnessMatrix( FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep ) + void computeStiffnessMatrix( FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep ) override { PhaseFieldElement :: computeStiffnessMatrix( answer, rMode, tStep ); } - virtual void giveInternalForcesVector( FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0 ) + void giveInternalForcesVector( FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0 ) override { PhaseFieldElement :: giveInternalForcesVector( answer, tStep, useUpdatedGpRecord ); } diff --git a/src/sm/Elements/PlaneStress/qplanstrssslip.C b/src/sm/Elements/PlaneStress/qplanstrssslip.C new file mode 100644 index 000000000..7ba07f644 --- /dev/null +++ b/src/sm/Elements/PlaneStress/qplanstrssslip.C @@ -0,0 +1,285 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/PlaneStress/qplanstrssslip.h" +#include "fei2dquadquad.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "classfactory.h" +#include "Materials/structuralmaterial.h" +#include "Materials/structuralms.h" +#include "Materials/structuralslipfe2material.h" +#include "CrossSections/structuralcrosssection.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" +#endif + +namespace oofem { +REGISTER_Element(QPlaneStress2dSlip); + +QPlaneStress2dSlip :: QPlaneStress2dSlip(int n, Domain *aDomain) : QPlaneStress2d(n, aDomain) + // Constructor. +{ +} + + +void QPlaneStress2dSlip::initializeFrom( InputRecord &ir ) +{ + QPlaneStress2d::initializeFrom(ir); +} + + +void QPlaneStress2dSlip :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = { + D_u, D_v, S_u, S_v + }; +} + + +void QPlaneStress2dSlip :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ + int ndof=this->computeNumberOfDofs(); + + FloatMatrix Kaa, Kab, Kba, Kbb, daa, dab1, dab2, dba1, dba2, dbb1, dbb2, dbb3, dbb4; + + for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { + FloatMatrix Ba, Bb, Nb; + double dV; + this->computeBmatrixAt(gp, Ba); + this->computeBHmatrixAt(gp, Bb); + this->computeNmatrixAt(gp->giveNaturalCoordinates(), Nb); + dV = this->computeVolumeAround(gp); + + //Compute the sensitivities + FloatMatrix dStressdEps, dStressdS, dStressdG, dBStressdEps, dBStressdS, dBStressdG, dRStressdEps, dRStressdS, dRStressdG; + this->giveSensitivities(dStressdEps, dStressdS, dStressdG, dBStressdEps, dBStressdS, dBStressdG, dRStressdEps, dRStressdS, dRStressdG, rMode, gp, tStep ); + + daa.beProductOf(dStressdEps, Ba); + dab1.beProductOf(dStressdS,Nb); + dab2.beProductOf(dStressdG,Bb); + dba1.beProductOf(dBStressdEps,Ba); + dba2.beProductOf(dRStressdEps,Ba); + dbb1.beProductOf(dBStressdS,Nb); + dbb2.beProductOf(dBStressdG,Bb); + dbb3.beProductOf(dRStressdS,Nb); + dbb4.beProductOf(dRStressdG,Bb); + + Kaa.plusProductUnsym(Ba, daa, dV); + Kab.plusProductUnsym(Ba, dab1, dV); + Kab.plusProductUnsym(Ba, dab2, dV); + Kba.plusProductUnsym(Nb,dba1,dV); + Kba.plusProductUnsym(Bb,dba2,dV); + Kbb.plusProductUnsym(Nb,dbb1,dV); + Kbb.plusProductUnsym(Nb,dbb2,dV); + Kbb.plusProductUnsym(Bb,dbb3,dV); + Kbb.plusProductUnsym(Bb,dbb4,dV); + } + + answer.resize(ndof,ndof); + answer.assemble(Kaa,aMask,aMask); + answer.assemble(Kbb,bMask,bMask); + answer.assemble(Kab,aMask,bMask); + answer.assemble(Kba,bMask,aMask); +} + +void QPlaneStress2dSlip :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +{ + int ndof=this->computeNumberOfDofs(); + + //Compute local fields at nodes + FloatArray u, a, b; + this->computeVectorOf(VM_Total, tStep, u); + + a.beSubArrayOf(u,aMask); + b.beSubArrayOf(u,bMask); + + FloatArray vStrain, vSlip, vSlipGradient; + FloatArray Stress, bStress, rStress; + FloatArray finta, fintb; + + for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { + FloatMatrix Ba, Bb, Nb; + FloatArray f; + double dV; + this->computeBmatrixAt(gp, Ba); + this->computeBHmatrixAt(gp, Bb); + this->computeNmatrixAt(gp->giveNaturalCoordinates(), Nb); + dV = this->computeVolumeAround(gp); + + vStrain.beProductOf(Ba, a); + vSlip.beProductOf(Nb, b); + vSlipGradient.beProductOf(Bb, b); + + this->giveHomogenizedFields(Stress, bStress, rStress, vStrain, vSlip, vSlipGradient, gp , tStep); + + finta.plusProduct(Ba,Stress,dV); + fintb.plusProduct(Nb,bStress,dV); + fintb.plusProduct(Bb,rStress,dV); + } + + answer.resize(ndof); + for (int i=1; i <= ndof/2 ; i++) { + if (i % 2 == 1) { + answer.at(2*i-1) = finta.at(i); + answer.at(2*i+1) = fintb.at(i); + } else if (i % 2 == 0) { + answer.at(2*i-2) = finta.at(i); + answer.at(2*i) = fintb.at(i); + } + } +} + + + +int QPlaneStress2dSlip :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +{ + if ( type == IST_DisplacementVector ) { + FloatArray u, a; + FloatMatrix N; + this->computeVectorOf(VM_Total, tStep, u); + a.beSubArrayOf(u, aMask); + this->computeNmatrixAt(gp->giveSubPatchCoordinates(), N); + answer.beProductOf(N, a); + return 1; + } else if ( type == IST_MacroSlipVector ) { + FloatArray u, b; + FloatMatrix N; + this->computeVectorOf(VM_Total, tStep, u); + b.beSubArrayOf(u,bMask); + this->computeNmatrixAt(gp->giveSubPatchCoordinates(), N); + answer.beProductOf(N, b); + return 1; + } else if ( type == IST_TransferStress ) { + StructuralSlipFE2MaterialStatus* status=static_cast< StructuralSlipFE2MaterialStatus * >( gp->giveMaterialStatus() ); + answer = status->giveTransferStressVector(); + return 1; + } else if ( type == IST_MacroSlipGradient ) { + FloatArray u, b; + FloatMatrix B; + this->computeVectorOf(VM_Total, tStep, u); + b.beSubArrayOf(u,bMask); + this->computeBHmatrixAt(gp, B); + answer.beProductOf(B, b); + return 1; + } else if (type == IST_ReinfMembraneStress ) { + StructuralSlipFE2MaterialStatus* status=static_cast< StructuralSlipFE2MaterialStatus *>( gp->giveMaterialStatus() ); + answer = status->giveReinfStressVector(); + return 1; + } else { + return Element :: giveIPValue(answer, gp, type, tStep); + } +} + + +void QPlaneStress2dSlip::giveHomogenizedFields( FloatArray &stress, FloatArray &bStress, FloatArray &rStress, const FloatArray &strain, const FloatArray &slip, const FloatArray &slipGradient, GaussPoint *gp, TimeStep *tStep ) +{ + StructuralSlipFE2Material *mat = dynamic_cast( this->giveStructuralCrossSection()->giveMaterial(gp) ); + if ( mat ) { + mat->giveHomogenizedFields(stress, bStress, rStress, strain, slip, slipGradient, gp, tStep); + } else { + OOFEM_ERROR("Can't homogenize the fields. StructuralSlipFE2Material needed."); + } + +} + + +void QPlaneStress2dSlip::giveSensitivities( FloatMatrix &dStressdEps, FloatMatrix &dStressdS, FloatMatrix &dStressdG, FloatMatrix &dBStressdEps, FloatMatrix &dBStressdS, FloatMatrix &dBStressdG, FloatMatrix &dRStressdEps, FloatMatrix &dRStressdS, FloatMatrix &dRStressdG, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep ) +{ + StructuralSlipFE2Material *mat = dynamic_cast( this->giveStructuralCrossSection()->giveMaterial(gp) ); + if ( mat ) { + mat->giveSensitivities(dStressdEps, dStressdS, dStressdG, dBStressdEps, dBStressdS, dBStressdG, dRStressdEps, dRStressdS, dRStressdG, mode, gp, tStep); + /// for debugging +// printf("dSdE \n"); +// dStressdEps.printYourself(); +// printf("dBSdE \n"); +// dBStressdEps.printYourself(); +// printf("dRSdE \n"); +// dRStressdEps.printYourself(); +// printf("dSdS \n"); +// dStressdS.printYourself(); +// printf("dBSdS \n"); +// dBStressdS.printYourself(); +// printf("dRSdS \n"); +// dRStressdS.printYourself(); +// printf("dSdG \n"); +// dStressdG.printYourself(); +// printf("dBSdG \n"); +// dBStressdG.printYourself(); +// printf("dRSdG \n"); +// dRStressdG.printYourself(); + } else { + OOFEM_ERROR("Can't compute sensitivities. StructuralSlipFE2Material needed."); + } +} + + +void QPlaneStress2dSlip::NodalAveragingRecoveryMI_computeNodalValue( FloatArray &answer, int node, InternalStateType type, TimeStep *tStep ) +{ + if ( numberOfGaussPoints == 9 ) { + GaussPoint *gp; + + int i=0; + switch ( node ) { + case 1: i = 9; + break; + case 2: i = 3; + break; + case 3: i = 1; + break; + case 4: i = 7; + break; + case 5: i = 6; + break; + case 6: i = 2; + break; + case 7: i = 4; + break; + case 8: i = 8; + break; + } + + gp = integrationRulesArray [ 0 ]->getIntegrationPoint(i - 1); + this->giveIPValue(answer, gp, type, tStep); + } else { + QPlaneStress2d::NodalAveragingRecoveryMI_computeNodalValue( answer, node, type, tStep ); + } +} + + +} // end namespace oofem diff --git a/src/sm/Elements/PlaneStress/qplanstrssslip.h b/src/sm/Elements/PlaneStress/qplanstrssslip.h new file mode 100644 index 000000000..f22c6a984 --- /dev/null +++ b/src/sm/Elements/PlaneStress/qplanstrssslip.h @@ -0,0 +1,89 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef qplanstrssslip_h +#define qplanstrssslip_h + +#include "sm/Elements/structural2delement.h" +#include "sm/Elements/PlaneStress/qplanstrss.h" +#include "nodalaveragingrecoverymodel.h" + +#define _IFT_QPlaneStress2dSlip_Name "qplanestress2dslip" + +namespace oofem { +class FEI2dQuadQuad; + +/** + * This class implements a quadratic isoparametric 8-node quadrilateral plane- + * stress elasticity finite element with independent slip field. Each node has 4 degrees of freedom. + * Currently works only in FE2 setting, i.e., with StructuralSlipFE2Material. + * + * @author Adam Sciegaj + */ +class QPlaneStress2dSlip : public QPlaneStress2d +{ +protected: + static FEI2dQuadQuad interpolation; + +public: + QPlaneStress2dSlip(int n, Domain * d); + virtual ~QPlaneStress2dSlip() { } + + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_QPlaneStress2dSlip_Name; } + const char *giveClassName() const override { return "QPlaneStress2dSlip"; } + void initializeFrom(InputRecord &ir) override; + + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; + + +protected: + IntArray aMask = {1,2,5,6,9,10,13,14,17,18,21,22,25,26,29,30}; //dof numbers of displacement field + IntArray bMask = {3,4,7,8,11,12,15,16,19,20,23,24,27,28,31,32}; //dof numbers of slip field + + void giveHomogenizedFields(FloatArray &stress, FloatArray &bStress, FloatArray &rStress, const FloatArray &strain, const FloatArray &slip, const FloatArray &slipGradient, GaussPoint *gp, TimeStep *tStep); + void giveSensitivities(FloatMatrix &dStressdEps, FloatMatrix &dStressdS, FloatMatrix &dStressdG, FloatMatrix &dBStressdEps, FloatMatrix &dBStressdS, + FloatMatrix &dBStressdG, FloatMatrix &dRStressdEps, FloatMatrix &dRStressdS, FloatMatrix &dRStressdG, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + +}; +} // end namespace oofem +#endif // qplanstrssslip_h diff --git a/src/sm/Elements/PlaneStress/qtrplanstrssxfem.C b/src/sm/Elements/PlaneStress/qtrplanstrssxfem.C index 96f1642ca..0c027c313 100644 --- a/src/sm/Elements/PlaneStress/qtrplanstrssxfem.C +++ b/src/sm/Elements/PlaneStress/qtrplanstrssxfem.C @@ -34,8 +34,8 @@ #include "qtrplanstrssxfem.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "vtkxmlexportmodule.h" #include "xfem/xfemelementinterface.h" #include "xfem/enrichmentfunction.h" @@ -219,29 +219,19 @@ QTrPlaneStress2dXFEM :: giveGeometryType() const } } -IRResultType -QTrPlaneStress2dXFEM :: initializeFrom(InputRecord *ir) +void +QTrPlaneStress2dXFEM :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - result = QTrPlaneStress2d :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + QTrPlaneStress2d :: initializeFrom(ir); + XfemStructuralElementInterface :: initializeCZFrom(ir); - result = XfemStructuralElementInterface :: initializeCZFrom(ir); - if ( result != IRRT_OK ) { - return result; + if ( ir.hasField(_IFT_QTrPlaneStress2dXFEM_RegCoeff) ) { + ir.giveOptionalField(mRegCoeff, _IFT_QTrPlaneStress2dXFEM_RegCoeff); } - if(ir->hasField(_IFT_QTrPlaneStress2dXFEM_RegCoeff) ) { - ir->giveOptionalField(mRegCoeff, _IFT_QTrPlaneStress2dXFEM_RegCoeff); + if ( ir.hasField(_IFT_QTrPlaneStress2dXFEM_RegCoeffTol) ) { + ir.giveOptionalField(mRegCoeffTol, _IFT_QTrPlaneStress2dXFEM_RegCoeffTol); } - - if(ir->hasField(_IFT_QTrPlaneStress2dXFEM_RegCoeffTol) ) { - ir->giveOptionalField(mRegCoeffTol, _IFT_QTrPlaneStress2dXFEM_RegCoeffTol); - } - - return result; } MaterialMode QTrPlaneStress2dXFEM :: giveMaterialMode() @@ -290,7 +280,7 @@ QTrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiec // Node coordinates std :: vector< FloatArray >nodeCoords; for(int i = 1; i <= 6; i++) { - FloatArray &x = *(giveDofManager(i)->giveCoordinates()); + const auto &x = giveDofManager(i)->giveCoordinates(); nodeCoords.push_back(x); vtkPieces[0].setNodeCoords(i, x); @@ -311,7 +301,7 @@ QTrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiec // Export nodal variables from primary fields - vtkPieces[0].setNumberOfPrimaryVarsToExport(primaryVarsToExport.giveSize(), numTotalNodes); + vtkPieces[0].setNumberOfPrimaryVarsToExport(primaryVarsToExport, numTotalNodes); for ( int fieldNum = 1; fieldNum <= primaryVarsToExport.giveSize(); fieldNum++ ) { UnknownType type = ( UnknownType ) primaryVarsToExport.at(fieldNum); @@ -344,7 +334,7 @@ QTrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiec u = {uTemp[0], uTemp[1], 0.0}; } - vtkPieces[0].setPrimaryVarInNode(fieldNum, nodeInd, u); + vtkPieces[0].setPrimaryVarInNode(type, nodeInd, u); } else { printf("fieldNum: %d\n", fieldNum); // TODO: Implement @@ -359,11 +349,11 @@ QTrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiec // Export nodal variables from internal fields - vtkPieces[0].setNumberOfInternalVarsToExport(0, numTotalNodes); + vtkPieces[0].setNumberOfInternalVarsToExport(internalVarsToExport, numTotalNodes); // Export cell variables - vtkPieces[0].setNumberOfCellVarsToExport(cellVarsToExport.giveSize(), 1); + vtkPieces[0].setNumberOfCellVarsToExport(cellVarsToExport, 1); for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) { InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i); FloatArray average; @@ -374,7 +364,7 @@ QTrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiec } if(average.giveSize() == 1) { - vtkPieces[0].setCellVar( i, 1, average ); + vtkPieces[0].setCellVar( type, 1, average ); } if(average.giveSize() == 6) { @@ -386,7 +376,7 @@ QTrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiec averageV9.at(3) = averageV9.at(7) = average.at(5); averageV9.at(2) = averageV9.at(4) = average.at(6); - vtkPieces[0].setCellVar( i, 1, averageV9 ); + vtkPieces[0].setCellVar( type, 1, averageV9 ); } } @@ -422,7 +412,7 @@ QTrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiec for(int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++) { DofManager *dMan = giveDofManager(elNodeInd); - ei->evalLevelSetNormalInNode(levelSetInNode, dMan->giveGlobalNumber(), *(dMan->giveCoordinates()) ); + ei->evalLevelSetNormalInNode(levelSetInNode, dMan->giveGlobalNumber(), dMan->giveCoordinates() ); levelSet += N.at(elNodeInd)*levelSetInNode; } @@ -436,7 +426,7 @@ QTrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiec for(int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++) { DofManager *dMan = giveDofManager(elNodeInd); - ei->evalLevelSetTangInNode(levelSetInNode, dMan->giveGlobalNumber(), *(dMan->giveCoordinates()) ); + ei->evalLevelSetTangInNode(levelSetInNode, dMan->giveGlobalNumber(), dMan->giveCoordinates() ); levelSet += N.at(elNodeInd)*levelSetInNode; } diff --git a/src/sm/Elements/PlaneStress/qtrplanstrssxfem.h b/src/sm/Elements/PlaneStress/qtrplanstrssxfem.h index c9788f2d8..8ba7f25b3 100644 --- a/src/sm/Elements/PlaneStress/qtrplanstrssxfem.h +++ b/src/sm/Elements/PlaneStress/qtrplanstrssxfem.h @@ -35,8 +35,8 @@ #ifndef QTRPLANSTRSSXFEM_H_ #define QTRPLANSTRSSXFEM_H_ -#include "../sm/Elements/PlaneStress/qtrplstr.h" -#include "../sm/xfem/xfemstructuralelementinterface.h" +#include "sm/Elements/PlaneStress/qtrplstr.h" +#include "sm/xfem/xfemstructuralelementinterface.h" #include "vtkxmlexportmodule.h" #include "domain.h" @@ -56,8 +56,8 @@ namespace oofem { class QTrPlaneStress2dXFEM : public QTrPlaneStress2d, public XfemStructuralElementInterface, public VTKXMLExportModuleElementInterface { protected: - virtual void updateYourself(TimeStep *tStep); - virtual void postInitialize(); + void updateYourself(TimeStep *tStep) override; + void postInitialize() override; double mRegCoeff, mRegCoeffTol; @@ -65,43 +65,41 @@ class QTrPlaneStress2dXFEM : public QTrPlaneStress2d, public XfemStructuralEleme QTrPlaneStress2dXFEM(int n, Domain * d) : QTrPlaneStress2d(n, d), XfemStructuralElementInterface(this), VTKXMLExportModuleElementInterface() { numberOfDofMans = 6; mRegCoeff = 1.0e-6; mRegCoeffTol = 1.0e-6; } virtual ~QTrPlaneStress2dXFEM(); - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual const char *giveInputRecordName() const { return _IFT_QTrPlaneStress2dXFEM_Name; } - virtual const char *giveClassName() const { return "QTrPlaneStress2dXFEM"; } + const char *giveInputRecordName() const override { return _IFT_QTrPlaneStress2dXFEM_Name; } + const char *giveClassName() const override { return "QTrPlaneStress2dXFEM"; } + int computeNumberOfDofs() override; + void computeGaussPoints() override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, + int lowerIndx = 1, int upperIndx = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; - virtual int computeNumberOfDofs(); - virtual void computeGaussPoints(); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, - int lowerIndx = 1, int upperIndx = ALL_STRAINS); - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *, TimeStep *tStep); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; - virtual void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override; + void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) override { XfemStructuralElementInterface :: XfemElementInterface_computeConsistentMassMatrix(answer, tStep, mass, ipDensity); } - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); - virtual void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) { XfemStructuralElementInterface :: XfemElementInterface_computeConsistentMassMatrix(answer, tStep, mass, ipDensity); } + Element_Geometry_Type giveGeometryType() const override; - virtual Element_Geometry_Type giveGeometryType() const; + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode(); - virtual void giveInputRecord(DynamicInputRecord &input); - - virtual void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer); + void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) override; /// VTK Interface - virtual void giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep); + void giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep) override; protected: - virtual int giveNumberOfIPForMassMtrxIntegration() { return 6; } // TODO: Check - + int giveNumberOfIPForMassMtrxIntegration() override { return 6; } // TODO: Check }; } /* namespace OOFEM */ diff --git a/src/sm/Elements/PlaneStress/qtrplstr.C b/src/sm/Elements/PlaneStress/qtrplstr.C index a7b94917a..256f295cb 100644 --- a/src/sm/Elements/PlaneStress/qtrplstr.C +++ b/src/sm/Elements/PlaneStress/qtrplstr.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/qtrplstr.h" +#include "sm/Elements/PlaneStress/qtrplstr.h" #include "fei2dtrquad.h" #include "node.h" #include "gausspoint.h" @@ -47,7 +47,7 @@ #ifdef __OOFEG #include "oofeggraphiccontext.h" #include "oofegutils.h" - #include "Materials/rcm2.h" + #include "sm/Materials/rcm2.h" #endif namespace oofem { @@ -87,11 +87,11 @@ QTrPlaneStress2d :: giveInterface(InterfaceType interface) } -IRResultType -QTrPlaneStress2d :: initializeFrom(InputRecord *ir) +void +QTrPlaneStress2d :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 4; - return PlaneStressElement :: initializeFrom(ir); + PlaneStressElement :: initializeFrom(ir); } diff --git a/src/sm/Elements/PlaneStress/qtrplstr.h b/src/sm/Elements/PlaneStress/qtrplstr.h index bb128fa0d..79cf89308 100644 --- a/src/sm/Elements/PlaneStress/qtrplstr.h +++ b/src/sm/Elements/PlaneStress/qtrplstr.h @@ -35,8 +35,8 @@ #ifndef qtrplstr_h #define qtrplstr_h -#include "Elements/structural2delement.h" -#include "ErrorEstimators/directerrorindicatorrc.h" +#include "sm/Elements/structural2delement.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" #include "spatiallocalizer.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -60,29 +60,29 @@ public SPRNodalRecoveryModelInterface QTrPlaneStress2d(int n, Domain * d); virtual ~QTrPlaneStress2d() { } - virtual Interface *giveInterface(InterfaceType it); - virtual FEInterpolation *giveInterpolation() const; - virtual double giveParentElSize() const { return 0.5; } + Interface *giveInterface(InterfaceType it) override; + FEInterpolation *giveInterpolation() const override; + double giveParentElSize() const override { return 0.5; } #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QTrPlaneStress2d_Name; } - virtual const char *giveClassName() const { return "QTrPlaneStress2d"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_QTrPlaneStress2d_Name; } + const char *giveClassName() const override { return "QTrPlaneStress2d"; } + void initializeFrom(InputRecord &ir) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; protected: - virtual int giveNumberOfIPForMassMtrxIntegration() { return 4; } + int giveNumberOfIPForMassMtrxIntegration() override { return 4; } }; } // end namespace oofem diff --git a/src/sm/Elements/PlaneStress/qtrplstrgrad.h b/src/sm/Elements/PlaneStress/qtrplstrgrad.h deleted file mode 100644 index 7d38b394a..000000000 --- a/src/sm/Elements/PlaneStress/qtrplstrgrad.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef qtrplstrgrad_h -#define qtrplstrgrad_h - -#include "../sm/Elements/PlaneStress/qtrplstr.h" -#include "../sm/Elements/graddpelement.h" - -#define _IFT_QTrPlaneStressGrad_Name "qtrplstrgrad" - -namespace oofem { -class FEI2dTrLin; - -class QTrPlaneStressGrad : public QTrPlaneStress2d, public GradDpElement -{ -protected: - static FEI2dTrLin interpolation_lin; - -public: - QTrPlaneStressGrad(int n, Domain * d); - virtual ~QTrPlaneStressGrad() { } - - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual const char *giveInputRecordName() const { return _IFT_QTrPlaneStressGrad_Name; } - virtual const char *giveClassName() const { return "QTrPlaneStressGrad"; } - - virtual MaterialMode giveMaterialMode() { return _PlaneStress; } - virtual int computeNumberOfDofs() { return 15; } - -protected: - virtual void computeBkappaMatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeNkappaMatrixAt(GaussPoint *gp, FloatArray &answer); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { GradDpElement :: computeStiffnessMatrix(answer, rMode, tStep); } - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) { GradDpElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); } - - virtual void computeGaussPoints(); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual StructuralElement *giveStructuralElement() { return this; } - virtual NLStructuralElement *giveNLStructuralElement() { return this; } -}; -} // end namespace oofem -#endif // qtrplstrgrad_h diff --git a/src/sm/Elements/PlaneStress/qtrplstrslip.C b/src/sm/Elements/PlaneStress/qtrplstrslip.C new file mode 100644 index 000000000..e1bee3b48 --- /dev/null +++ b/src/sm/Elements/PlaneStress/qtrplstrslip.C @@ -0,0 +1,253 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/PlaneStress/qtrplstrslip.h" +#include "fei2dtrquad.h" +#include "node.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "crosssection.h" +#include "gaussintegrationrule.h" +#include "mathfem.h" +#include "classfactory.h" +#include "Materials/structuralmaterial.h" +#include "Materials/structuralms.h" +#include "Materials/structuralslipfe2material.h" +#include "CrossSections/structuralcrosssection.h" + + +namespace oofem { +REGISTER_Element(QTrPlaneStress2dSlip); + +QTrPlaneStress2dSlip :: QTrPlaneStress2dSlip(int n, Domain *aDomain) : + QTrPlaneStress2d(n, aDomain) +{ +} + + +void +QTrPlaneStress2dSlip :: initializeFrom(InputRecord &ir) +{ + numberOfGaussPoints = 4; + QTrPlaneStress2d :: initializeFrom(ir); +} + + +void QTrPlaneStress2dSlip::giveDofManDofIDMask( int inode, IntArray &answer ) const +{ + answer = { + D_u, D_v, S_u, S_v + }; +} + + +void QTrPlaneStress2dSlip::computeStiffnessMatrix( FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep ) +{ + int ndof=this->computeNumberOfDofs(); + + FloatMatrix Kaa, Kab, Kba, Kbb, daa, dab1, dab2, dba1, dba2, dbb1, dbb2, dbb3, dbb4; + + for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { + FloatMatrix Ba, Bb, Nb; + double dV; + this->computeBmatrixAt(gp, Ba); + this->computeBHmatrixAt(gp, Bb); + this->computeNmatrixAt(gp->giveNaturalCoordinates(), Nb); + dV = this->computeVolumeAround(gp); + + //Get the sensitivities + FloatMatrix dStressdEps, dStressdS, dStressdG, dBStressdEps, dBStressdS, dBStressdG, dRStressdEps, dRStressdS, dRStressdG; + this->giveSensitivities(dStressdEps, dStressdS, dStressdG, dBStressdEps, dBStressdS, dBStressdG, dRStressdEps, dRStressdS, dRStressdG, rMode, gp, tStep ); + + daa.beProductOf(dStressdEps, Ba); + dab1.beProductOf(dStressdS,Nb); + dab2.beProductOf(dStressdG,Bb); + dba1.beProductOf(dBStressdEps,Ba); + dba2.beProductOf(dRStressdEps,Ba); + dbb1.beProductOf(dBStressdS,Nb); + dbb2.beProductOf(dBStressdG,Bb); + dbb3.beProductOf(dRStressdS,Nb); + dbb4.beProductOf(dRStressdG,Bb); + + Kaa.plusProductUnsym(Ba, daa, dV); + Kab.plusProductUnsym(Ba, dab1, dV); + Kab.plusProductUnsym(Ba, dab2, dV); + Kba.plusProductUnsym(Nb,dba1,dV); + Kba.plusProductUnsym(Bb,dba2,dV); + Kbb.plusProductUnsym(Nb,dbb1,dV); + Kbb.plusProductUnsym(Nb,dbb2,dV); + Kbb.plusProductUnsym(Bb,dbb3,dV); + Kbb.plusProductUnsym(Bb,dbb4,dV); + } + + answer.resize(ndof,ndof); + answer.assemble(Kaa,aMask,aMask); + answer.assemble(Kbb,bMask,bMask); + answer.assemble(Kab,aMask,bMask); + answer.assemble(Kba,bMask,aMask); + +} + + +void QTrPlaneStress2dSlip::giveInternalForcesVector( FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord ) +{ + int ndof=this->computeNumberOfDofs(); + + //Compute local fields at nodes + FloatArray u, a, b; + this->computeVectorOf(VM_Total, tStep, u); + + a.beSubArrayOf(u,aMask); + b.beSubArrayOf(u,bMask); + + FloatArray vStrain, vSlip, vSlipGradient; + FloatArray Stress, bStress, rStress; + FloatArray finta, fintb; + + for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { + FloatMatrix Ba, Bb, Nb; + FloatArray f; + double dV; + this->computeBmatrixAt(gp, Ba); + this->computeBHmatrixAt(gp, Bb); + this->computeNmatrixAt(gp->giveNaturalCoordinates(), Nb); + dV = this->computeVolumeAround(gp); + + vStrain.beProductOf(Ba, a); + vSlip.beProductOf(Nb, b); + vSlipGradient.beProductOf(Bb, b); + + this->giveHomogenizedFields(Stress, bStress, rStress, vStrain, vSlip, vSlipGradient, gp , tStep); + + finta.plusProduct(Ba,Stress,dV); + fintb.plusProduct(Nb,bStress,dV); + fintb.plusProduct(Bb,rStress,dV); + } + + answer.resize(ndof); + for (int i=1; i <= ndof/2 ; i++) { + if (i % 2 == 1) { + answer.at(2*i-1) = finta.at(i); + answer.at(2*i+1) = fintb.at(i); + } else if (i % 2 == 0) { + answer.at(2*i-2) = finta.at(i); + answer.at(2*i) = fintb.at(i); + } + } +} + + +int QTrPlaneStress2dSlip::giveIPValue( FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep ) +{ + if ( type == IST_DisplacementVector ) { + FloatArray u, a; + FloatMatrix N; + this->computeVectorOf(VM_Total, tStep, u); + a.beSubArrayOf(u, aMask); + this->computeNmatrixAt(gp->giveSubPatchCoordinates(), N); + answer.beProductOf(N, a); + return 1; + } else if ( type == IST_MacroSlipVector ) { + FloatArray u, b; + FloatMatrix N; + this->computeVectorOf(VM_Total, tStep, u); + b.beSubArrayOf(u,bMask); + this->computeNmatrixAt(gp->giveSubPatchCoordinates(), N); + answer.beProductOf(N, b); + return 1; + } else if ( type == IST_TransferStress ) { + StructuralSlipFE2MaterialStatus* status=static_cast< StructuralSlipFE2MaterialStatus * >( gp->giveMaterialStatus() ); + answer = status->giveTransferStressVector(); + return 1; + } else if ( type == IST_MacroSlipGradient ) { + FloatArray u, b; + FloatMatrix B; + this->computeVectorOf(VM_Total, tStep, u); + b.beSubArrayOf(u,bMask); + this->computeBHmatrixAt(gp, B); + answer.beProductOf(B, b); + return 1; + } else if (type == IST_ReinfMembraneStress ) { + StructuralSlipFE2MaterialStatus* status=static_cast< StructuralSlipFE2MaterialStatus *>( gp->giveMaterialStatus() ); + answer = status->giveReinfStressVector(); + return 1; + } else { + return Element :: giveIPValue(answer, gp, type, tStep); + } +} + + +void QTrPlaneStress2dSlip::giveHomogenizedFields( FloatArray &stress, FloatArray &bStress, FloatArray &rStress, const FloatArray &strain, const FloatArray &slip, const FloatArray &slipGradient, GaussPoint *gp, TimeStep *tStep ) +{ + StructuralSlipFE2Material *mat = dynamic_cast( this->giveStructuralCrossSection()->giveMaterial(gp) ); + if ( mat ) { + mat->giveHomogenizedFields(stress, bStress, rStress, strain, slip, slipGradient, gp, tStep); + } else { + OOFEM_ERROR("Can't homogenize the fields. StructuralSlipFE2Material needed."); + } +} + + +void QTrPlaneStress2dSlip::giveSensitivities( FloatMatrix &dStressdEps, FloatMatrix &dStressdS, FloatMatrix &dStressdG, FloatMatrix &dBStressdEps, FloatMatrix &dBStressdS, + FloatMatrix &dBStressdG, FloatMatrix &dRStressdEps, FloatMatrix &dRStressdS, FloatMatrix &dRStressdG, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep ) +{ + StructuralSlipFE2Material *mat = dynamic_cast( this->giveStructuralCrossSection()->giveMaterial(gp) ); + if ( mat ) { + mat->giveSensitivities(dStressdEps, dStressdS, dStressdG, dBStressdEps, dBStressdS, dBStressdG, dRStressdEps, dRStressdS, dRStressdG, mode, gp, tStep); + /// for debugging +// printf("dSdE \n"); +// dStressdEps.printYourself(); +// printf("dBSdE \n"); +// dBStressdEps.printYourself(); +// printf("dRSdE \n"); +// dRStressdEps.printYourself(); +// printf("dSdS \n"); +// dStressdS.printYourself(); +// printf("dBSdS \n"); +// dBStressdS.printYourself(); +// printf("dRSdS \n"); +// dRStressdS.printYourself(); +// printf("dSdG \n"); +// dStressdG.printYourself(); +// printf("dBSdG \n"); +// dBStressdG.printYourself(); +// printf("dRSdG \n"); +// dRStressdG.printYourself(); + } else { + OOFEM_ERROR("Can't compute sensitivities. StructuralSlipFE2Material needed."); + } +} +} // end namespace oofem \ No newline at end of file diff --git a/src/sm/Elements/PlaneStress/qtrplstrslip.h b/src/sm/Elements/PlaneStress/qtrplstrslip.h new file mode 100644 index 000000000..c743dd42e --- /dev/null +++ b/src/sm/Elements/PlaneStress/qtrplstrslip.h @@ -0,0 +1,86 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef qtrplstrslip_h +#define qtrplstrslip_h + +#include "sm/Elements/structural2delement.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" +#include "spatiallocalizer.h" +#include "zznodalrecoverymodel.h" +#include "sprnodalrecoverymodel.h" +#include "sm/Elements/PlaneStress/qtrplstr.h" + +#define _IFT_QTrPlaneStress2dSlip_Name "qtrplstrslip" + +namespace oofem { +class FEI2dTrQuad; + +/** + * This class implements a quadratic triangular 6-node plane- + * stress for structural problems with independent macroscopic reinforcement slip field. + * Each node has 4 degrees of freedom. + * Currently works only in FE2 setting, i.e., with StructuralSlipFE2Material + * + * @author Adam Sciegaj + */ +class QTrPlaneStress2dSlip : public QTrPlaneStress2d +{ +public: + QTrPlaneStress2dSlip(int n, Domain * d); + virtual ~QTrPlaneStress2dSlip() { } + + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_QTrPlaneStress2dSlip_Name; } + const char *giveClassName() const override { return "QTrPlaneStress2dSlip"; } + void initializeFrom(InputRecord &ir) override; + + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override; + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + +protected: + IntArray aMask = {1,2,5,6,9,10,13,14,17,18,21,22}; //dof numbers of displacement field + IntArray bMask = {3,4,7,8,11,12,15,16,19,20,23,24}; //dof numbers of slip field + + void giveHomogenizedFields(FloatArray &stress, FloatArray &bStress, FloatArray &rStress, const FloatArray &strain, const FloatArray &slip, const FloatArray &slipGradient, GaussPoint *gp, TimeStep *tStep); + void giveSensitivities(FloatMatrix &dStressdEps, FloatMatrix &dStressdS, FloatMatrix &dStressdG, FloatMatrix &dBStressdEps, FloatMatrix &dBStressdS, + FloatMatrix &dBStressdG, FloatMatrix &dRStressdEps, FloatMatrix &dRStressdS, FloatMatrix &dRStressdG, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + +}; +} // end namespace oofem +#endif // qtrplstrslip_h \ No newline at end of file diff --git a/src/sm/Elements/PlaneStress/trplanestressrotallman.C b/src/sm/Elements/PlaneStress/trplanestressrotallman.C index 218bde736..33819e23f 100644 --- a/src/sm/Elements/PlaneStress/trplanestressrotallman.C +++ b/src/sm/Elements/PlaneStress/trplanestressrotallman.C @@ -32,8 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/trplanestressrotallman.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/PlaneStress/trplanestressrotallman.h" #include "fei2dtrquad.h" #include "fei2dtrlin.h" #include "node.h" @@ -57,7 +56,7 @@ REGISTER_Element(TrPlanestressRotAllman); FEI2dTrQuad TrPlanestressRotAllman :: qinterpolation(1, 2); TrPlanestressRotAllman :: TrPlanestressRotAllman(int n, Domain *aDomain) : - TrPlaneStress2d(n, aDomain), LayeredCrossSectionInterface() + TrPlaneStress2d(n, aDomain) { numberOfDofMans = 3; numberOfGaussPoints = 4; @@ -84,7 +83,7 @@ TrPlanestressRotAllman :: computeLocalNodalCoordinates(std::vector< FloatArray > { lxy.resize(6); for ( int i = 0; i < 3; i++ ) { - lxy [ i ] = * this->giveNode(i + 1)->giveCoordinates(); + lxy [ i ] = this->giveNode(i + 1)->giveCoordinates(); } lxy [ 3 ].resize(2); lxy [ 4 ].resize(2); @@ -249,7 +248,7 @@ void TrPlanestressRotAllman :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } @@ -259,12 +258,11 @@ TrPlanestressRotAllman :: computeEgdeNMatrixAt(FloatMatrix &answer, int iedge, G { std::vector< FloatArray > lxy; FloatArray l, n; - IntArray en; FEI2dTrQuad qi(1, 2); this->computeLocalNodalCoordinates(lxy); // get ready for tranformation into 3d qi.edgeEvalN( n, iedge, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lxy) ); - qi.computeLocalEdgeMapping(en, iedge); // get edge mapping + const auto &en = qi.computeLocalEdgeMapping(iedge); // get edge mapping this->interp.edgeEvalN( l, iedge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.resize(3, 6); @@ -313,27 +311,6 @@ TrPlanestressRotAllman :: giveEdgeDofMapping(IntArray &answer, int iEdge) const } } -// -// layered cross section support functions -// -void -TrPlanestressRotAllman :: computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) -// returns full 3d strain vector of given layer (whose z-coordinate from center-line is -// stored in slaveGp) for given tStep -{ - double layerZeta, layerZCoord, top, bottom; - - top = this->giveCrossSection()->give(CS_TopZCoord, masterGp); - bottom = this->giveCrossSection()->give(CS_BottomZCoord, masterGp); - layerZeta = slaveGp->giveNaturalCoordinate(3); - layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); - answer.resize(3); // {eps_xx,eps_yy,gamma_yz} - - answer.at(1) = masterGpStrain.at(1) * layerZCoord; - answer.at(2) = masterGpStrain.at(2) * layerZCoord; - answer.at(3) = masterGpStrain.at(3); -} - void TrPlanestressRotAllman :: computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global) { answer.clear(); @@ -475,15 +452,11 @@ void TrPlanestressRotAllman :: computeBoundaryEdgeLoadVector(FloatArray &answer, * } */ -IRResultType -TrPlanestressRotAllman :: initializeFrom(InputRecord *ir) +void +TrPlanestressRotAllman :: initializeFrom(InputRecord &ir) { - IRResultType result = TrPlaneStress2d :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + TrPlaneStress2d :: initializeFrom(ir); numberOfGaussPoints = 4; - return IRRT_OK; } diff --git a/src/sm/Elements/PlaneStress/trplanestressrotallman.h b/src/sm/Elements/PlaneStress/trplanestressrotallman.h index 60d01b703..1b50c27ab 100644 --- a/src/sm/Elements/PlaneStress/trplanestressrotallman.h +++ b/src/sm/Elements/PlaneStress/trplanestressrotallman.h @@ -35,8 +35,7 @@ #ifndef trplanestressrotallman_h #define trplanestressrotallman_h -#include "../sm/Elements/PlaneStress/trplanstrss.h" -#include "../sm/CrossSections/layeredcrosssection.h" +#include "sm/Elements/PlaneStress/trplanstrss.h" ///@name Input fields for TrPlaneStrRotAllman @@ -56,7 +55,7 @@ class FEI2dTrQuad; * A compatible triangular element including vertex rotations for plane elasticity analysis. * Computers & Structures Vol. 19, No. 1-2, pp. 1-8, 1984. */ -class TrPlanestressRotAllman : public TrPlaneStress2d, public LayeredCrossSectionInterface +class TrPlanestressRotAllman : public TrPlaneStress2d { protected: static FEI2dTrQuad qinterpolation; // quadratic interpolation for constructing shape functons @@ -65,13 +64,11 @@ class TrPlanestressRotAllman : public TrPlaneStress2d, public LayeredCrossSectio TrPlanestressRotAllman(int, Domain *); virtual ~TrPlanestressRotAllman() { } - - protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; - virtual double giveArea(); + double giveArea() override; virtual void computeLocalNodalCoordinates(std::vector< FloatArray > &lxy); /** * Computes the stiffness matrix stabilization of zero energy mode (equal rotations) @@ -83,26 +80,23 @@ class TrPlanestressRotAllman : public TrPlaneStress2d, public LayeredCrossSectio void computeStiffnessMatrixZeroEnergyStabilization(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); public: // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_TrPlanestressRotAllman_Name; } - virtual const char *giveClassName() const { return "TrPlanestressRotAllman"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode() { return _PlaneStress; } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } + const char *giveInputRecordName() const override { return _IFT_TrPlanestressRotAllman_Name; } + const char *giveClassName() const override { return "TrPlanestressRotAllman"; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _PlaneStress; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } /** Computes the stiffness matrix of receiver. Overloaded to add stabilization of zero-energy mode (equal rotations) */ - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void computeGaussPoints(); - virtual int computeNumberOfDofs() { return 9; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeGaussPoints() override; + int computeNumberOfDofs() override { return 9; } + void giveDofManDofIDMask(int inode, IntArray &) const override; - Interface *giveInterface(InterfaceType interface); - // layered cross section support functions - virtual void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep); + Interface *giveInterface(InterfaceType interface) override; - void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global); + void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global) override; void computeEgdeNMatrixAt(FloatMatrix &answer, int iedge, GaussPoint *gp); - void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - int SPRNodalRecoveryMI_giveNumberOfIP(); + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; }; } // end namespace oofem #endif // trplanestressrotallman_h diff --git a/src/sm/Elements/PlaneStress/trplanestressrotallman3d.C b/src/sm/Elements/PlaneStress/trplanestressrotallman3d.C index 92703ad10..b84a2c5e3 100644 --- a/src/sm/Elements/PlaneStress/trplanestressrotallman3d.C +++ b/src/sm/Elements/PlaneStress/trplanestressrotallman3d.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/trplanestressrotallman3d.h" -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/PlaneStress/trplanestressrotallman3d.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralms.h" #include "material.h" #include "node.h" #include "load.h" @@ -66,10 +66,9 @@ TrPlanestressRotAllman3d :: computeLocalNodalCoordinates(std :: vector< FloatArr lxy.resize(6); - const FloatArray *nc; for ( int i = 0; i < 3; i++ ) { - nc = this->giveNode(i + 1)->giveCoordinates(); - lxy [ i ].beProductOf(* GtoLRotationMatrix, * nc); + const auto &nc = this->giveNode(i + 1)->giveCoordinates(); + lxy [ i ].beProductOf(* GtoLRotationMatrix, nc); } lxy [ 3 ].resize(3); lxy [ 4 ].resize(3); @@ -121,8 +120,8 @@ TrPlanestressRotAllman3d :: computeGtoLRotationMatrix() FloatArray e1(3), e2(3), e3(3), help(3); // compute e1' = [N2-N1] and help = [N3-N1] - e1.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - help.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); + e1.beDifferenceOf(this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates()); + help.beDifferenceOf(this->giveNode(3)->giveCoordinates(), this->giveNode(1)->giveCoordinates()); // let us normalize e1' e1.normalize(); diff --git a/src/sm/Elements/PlaneStress/trplanestressrotallman3d.h b/src/sm/Elements/PlaneStress/trplanestressrotallman3d.h index 355067535..842bcc61e 100644 --- a/src/sm/Elements/PlaneStress/trplanestressrotallman3d.h +++ b/src/sm/Elements/PlaneStress/trplanestressrotallman3d.h @@ -35,7 +35,7 @@ #ifndef trplanestressrotallman3d_h #define trplanestressrotallman3d_h -#include "../sm/Elements/PlaneStress/trplanestressrotallman.h" +#include "sm/Elements/PlaneStress/trplanestressrotallman.h" #define _IFT_TrPlanestressRotAllman3d_Name "trplanestressrotallman3d" @@ -78,29 +78,29 @@ class TrPlanestressRotAllman3d : public TrPlanestressRotAllman } protected: - void computeLocalNodalCoordinates(std::vector< FloatArray > &lxy); + void computeLocalNodalCoordinates(std::vector< FloatArray > &lxy) override; - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; void giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode); + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) override; public: // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_TrPlanestressRotAllman3d_Name; } - virtual const char *giveClassName() const { return "TrPlaneStressRotAllman3d"; } + const char *giveInputRecordName() const override { return _IFT_TrPlanestressRotAllman3d_Name; } + const char *giveClassName() const override { return "TrPlaneStressRotAllman3d"; } - virtual int computeNumberOfDofs() { return 9; } - virtual int computeNumberOfGlobalDofs() { return 18; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int computeNumberOfDofs() override { return 9; } + int computeNumberOfGlobalDofs() override { return 18; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; const FloatMatrix *computeGtoLRotationMatrix(); - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); - virtual int testElementExtension(ElementExtension ext) + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; }; } // end namespace oofem #endif // trplanestressrotallman3d_h diff --git a/src/sm/Elements/PlaneStress/trplanrot.C b/src/sm/Elements/PlaneStress/trplanrot.C index 9ef2ab6bc..be9b9a1bb 100644 --- a/src/sm/Elements/PlaneStress/trplanrot.C +++ b/src/sm/Elements/PlaneStress/trplanrot.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/trplanrot.h" -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/PlaneStress/trplanrot.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralms.h" #include "node.h" #include "material.h" #include "gausspoint.h" @@ -66,7 +66,7 @@ TrPlaneStrRot :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } @@ -330,23 +330,22 @@ TrPlaneStrRot :: giveArea() void TrPlaneStrRot :: giveNodeCoordinates(FloatArray &x, FloatArray &y) { - FloatArray *nc1, *nc2, *nc3; - nc1 = this->giveNode(1)->giveCoordinates(); - nc2 = this->giveNode(2)->giveCoordinates(); - nc3 = this->giveNode(3)->giveCoordinates(); + const auto &nc1 = this->giveNode(1)->giveCoordinates(); + const auto &nc2 = this->giveNode(2)->giveCoordinates(); + const auto &nc3 = this->giveNode(3)->giveCoordinates(); - x.at(1) = nc1->at(1); - x.at(2) = nc2->at(1); - x.at(3) = nc3->at(1); + x.at(1) = nc1.at(1); + x.at(2) = nc2.at(1); + x.at(3) = nc3.at(1); - y.at(1) = nc1->at(2); - y.at(2) = nc2->at(2); - y.at(3) = nc3->at(2); + y.at(1) = nc1.at(2); + y.at(2) = nc2.at(2); + y.at(3) = nc3.at(2); //if (z) { - // z[0] = nc1->at(3); - // z[1] = nc2->at(3); - // z[2] = nc3->at(3); + // z[0] = nc1.at(3); + // z[1] = nc2.at(3); + // z[2] = nc3.at(3); //} } @@ -558,16 +557,11 @@ TrPlaneStrRot :: GiveDerivativeVY(const FloatArray &lCoords) } -IRResultType -TrPlaneStrRot :: initializeFrom(InputRecord *ir) +void +TrPlaneStrRot :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - numberOfGaussPoints = 4; - result = TrPlaneStress2d :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + TrPlaneStress2d :: initializeFrom(ir); numberOfRotGaussPoints = 1; IR_GIVE_OPTIONAL_FIELD(ir, numberOfRotGaussPoints, _IFT_TrPlaneStrRot_niprot); @@ -583,24 +577,22 @@ TrPlaneStrRot :: initializeFrom(InputRecord *ir) if ( numberOfRotGaussPoints != 1 ) { OOFEM_ERROR("numberOfRotGaussPoints size mismatch - must be equal to one"); } - - return IRRT_OK; } void TrPlaneStrRot :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - StructuralCrossSection *cs = this->giveStructuralCrossSection(); - cs->giveMembraneRotStiffMtrx(answer, rMode, gp, tStep); + auto cs = this->giveStructuralCrossSection(); + answer = cs->giveMembraneRotStiffMtrx(rMode, gp, tStep); } void TrPlaneStrRot :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - StructuralCrossSection *cs = this->giveStructuralCrossSection(); - cs->giveGeneralizedStress_MembraneRot(answer, gp, strain, tStep); + auto cs = this->giveStructuralCrossSection(); + answer = cs->giveGeneralizedStress_MembraneRot(strain, gp, tStep); } diff --git a/src/sm/Elements/PlaneStress/trplanrot.h b/src/sm/Elements/PlaneStress/trplanrot.h index d6992c7df..beffecfe5 100644 --- a/src/sm/Elements/PlaneStress/trplanrot.h +++ b/src/sm/Elements/PlaneStress/trplanrot.h @@ -35,7 +35,7 @@ #ifndef trplanrot_h #define trplanrot_h -#include "../sm/Elements/PlaneStress/trplanstrss.h" +#include "sm/Elements/PlaneStress/trplanstrss.h" ///@name Input fields for TrPlaneStrRot //@{ @@ -63,40 +63,40 @@ class TrPlaneStrRot : public TrPlaneStress2d virtual ~TrPlaneStrRot() { } protected: - virtual void computeGaussPoints(); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); + void computeGaussPoints() override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; - virtual double giveArea(); + double giveArea() override; virtual void giveNodeCoordinates(FloatArray &x, FloatArray &y); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode); + void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) override; public: // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_TrPlaneStrRot_Name; } - virtual const char *giveClassName() const { return "TrPlaneStrRot"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode() { return _PlaneStressRot; } + const char *giveInputRecordName() const override { return _IFT_TrPlaneStrRot_Name; } + const char *giveClassName() const override { return "TrPlaneStrRot"; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _PlaneStressRot; } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual int computeNumberOfDofs() { return 9; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 9; } + void giveDofManDofIDMask(int inode, IntArray &) const override; - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane); + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override; FloatArray GivePitch(); FloatArray GiveDerivativeUX(const FloatArray &lCoords); FloatArray GiveDerivativeVX(const FloatArray &lCoords); FloatArray GiveDerivativeUY(const FloatArray &lCoords); FloatArray GiveDerivativeVY(const FloatArray &lCoords); - //virtual void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + //void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; - virtual int testElementExtension(ElementExtension ext) { return 0; } + int testElementExtension(ElementExtension ext) override { return 0; } }; } // end namespace oofem #endif // trplanrot_h diff --git a/src/sm/Elements/PlaneStress/trplanrot3d.C b/src/sm/Elements/PlaneStress/trplanrot3d.C index 4a0eb1aa4..3b7cedeb8 100644 --- a/src/sm/Elements/PlaneStress/trplanrot3d.C +++ b/src/sm/Elements/PlaneStress/trplanrot3d.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/PlaneStress/trplanrot3d.h" -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/PlaneStress/trplanrot3d.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralms.h" #include "material.h" #include "node.h" #include "load.h" @@ -53,7 +53,7 @@ TrPlaneStrRot3d :: TrPlaneStrRot3d(int n, Domain *aDomain) : TrPlaneStrRot(n, aD void -TrPlaneStrRot3d :: giveLocalCoordinates(FloatArray &answer, FloatArray &global) +TrPlaneStrRot3d :: giveLocalCoordinates(FloatArray &answer, const FloatArray &global) // Returns global coordinates given in global vector // transformed into local coordinate system of the // receiver @@ -70,7 +70,7 @@ TrPlaneStrRot3d :: giveLocalCoordinates(FloatArray &answer, FloatArray &global) } FloatArray offset = global; - offset.subtract( * this->giveNode(1)->giveCoordinates() ); + offset.subtract( this->giveNode(1)->giveCoordinates() ); answer.beProductOf(GtoLRotationMatrix, offset); } @@ -95,9 +95,9 @@ TrPlaneStrRot3d :: giveNodeCoordinates(FloatArray &x, FloatArray &y) { FloatArray nc1(3), nc2(3), nc3(3); - this->giveLocalCoordinates( nc1, * ( this->giveNode(1)->giveCoordinates() ) ); - this->giveLocalCoordinates( nc2, * ( this->giveNode(2)->giveCoordinates() ) ); - this->giveLocalCoordinates( nc3, * ( this->giveNode(3)->giveCoordinates() ) ); + this->giveLocalCoordinates( nc1, this->giveNode(1)->giveCoordinates() ); + this->giveLocalCoordinates( nc2, this->giveNode(2)->giveCoordinates() ); + this->giveLocalCoordinates( nc3, this->giveNode(3)->giveCoordinates() ); x.resize(3); x.at(1) = nc1.at(1); @@ -140,8 +140,8 @@ TrPlaneStrRot3d :: computeGtoLRotationMatrix() FloatArray e1, e2, e3, help; // compute e1' = [N2-N1] and help = [N3-N1] - e1.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - help.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); + e1.beDifferenceOf( this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); + help.beDifferenceOf( this->giveNode(3)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); // let us normalize e1' e1.normalize(); @@ -414,14 +414,6 @@ TrPlaneStrRot3d :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const } } -IntegrationRule * -TrPlaneStrRot3d :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, approxOrder); - iRule->SetUpPointsOnTriangle(npoints, _Unknown); - return iRule; -} double TrPlaneStrRot3d :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) diff --git a/src/sm/Elements/PlaneStress/trplanrot3d.h b/src/sm/Elements/PlaneStress/trplanrot3d.h index 78705f429..e5fea4071 100644 --- a/src/sm/Elements/PlaneStress/trplanrot3d.h +++ b/src/sm/Elements/PlaneStress/trplanrot3d.h @@ -35,7 +35,7 @@ #ifndef trplanrot3d_h #define trplanrot3d_h -#include "../sm/Elements/PlaneStress/trplanrot.h" +#include "sm/Elements/PlaneStress/trplanrot.h" #define _IFT_TrPlaneStrRot3d_Name "trplanestrrot3d" @@ -74,25 +74,24 @@ class TrPlaneStrRot3d : public TrPlaneStrRot */ FloatMatrix GtoLRotationMatrix; - void giveLocalCoordinates(FloatArray &answer, FloatArray &global); - virtual void giveNodeCoordinates(FloatArray &x, FloatArray &y); + void giveLocalCoordinates(FloatArray &answer, const FloatArray &global); + void giveNodeCoordinates(FloatArray &x, FloatArray &y) override; - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; void giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) override; friend class TR_SHELL01; /** * @name Surface load support */ //@{ - virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); - virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const; - virtual IntegrationRule *GetSurfaceIntegrationRule(int iSurf); - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf); - virtual int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override; + double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) override; + int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp) override; //@} public: @@ -100,19 +99,19 @@ class TrPlaneStrRot3d : public TrPlaneStrRot virtual ~TrPlaneStrRot3d() { } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_TrPlaneStrRot3d_Name; } - virtual const char *giveClassName() const { return "TrPlaneStrRot3d"; } + const char *giveInputRecordName() const override { return _IFT_TrPlaneStrRot3d_Name; } + const char *giveClassName() const override { return "TrPlaneStrRot3d"; } - virtual int computeNumberOfDofs() { return 9; } - virtual int computeNumberOfGlobalDofs() { return 18; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 9; } + int computeNumberOfGlobalDofs() override { return 18; } + void giveDofManDofIDMask(int inode, IntArray &) const override; const FloatMatrix *computeGtoLRotationMatrix(); - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); - virtual int testElementExtension(ElementExtension ext) + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; }; } // end namespace oofem #endif // trplanrot3d_h diff --git a/src/sm/Elements/PlaneStress/trplanstrss.C b/src/sm/Elements/PlaneStress/trplanstrss.C index 8b0de09aa..22fafc929 100644 --- a/src/sm/Elements/PlaneStress/trplanstrss.C +++ b/src/sm/Elements/PlaneStress/trplanstrss.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/PlaneStress/trplanstrss.h" +#include "sm/Elements/PlaneStress/trplanstrss.h" #include "fei2dtrlin.h" #include "node.h" #include "crosssection.h" @@ -47,7 +47,7 @@ #ifdef __OOFEG #include "oofeggraphiccontext.h" #include "oofegutils.h" - #include "Materials/rcm2.h" + #include "sm/Materials/rcm2.h" #endif namespace oofem { @@ -59,7 +59,8 @@ TrPlaneStress2d :: TrPlaneStress2d(int n, Domain *aDomain) : PlaneStressElement(n, aDomain), ZZNodalRecoveryModelInterface(this), NodalAveragingRecoveryModelInterface(), SPRNodalRecoveryModelInterface(), SpatialLocalizerInterface(this), ZZErrorEstimatorInterface(this), - HuertaErrorEstimatorInterface() + HuertaErrorEstimatorInterface(), + LayeredCrossSectionInterface() { numberOfDofMans = 3; area = -1; @@ -83,6 +84,8 @@ TrPlaneStress2d :: giveInterface(InterfaceType interface) return static_cast< ZZErrorEstimatorInterface * >(this); } else if ( interface == HuertaErrorEstimatorInterfaceType ) { return static_cast< HuertaErrorEstimatorInterface * >(this); + } else if ( interface == LayeredCrossSectionInterfaceType ) { + return static_cast< LayeredCrossSectionInterface * >(this); } return NULL; @@ -200,37 +203,37 @@ TrPlaneStress2d :: HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedEleme IntArray &controlNode, IntArray &controlDof, HuertaErrorEstimator :: AnalysisMode aMode) { - int inode, nodes = 3, iside, sides = 3, nd1, nd2; - FloatArray *corner [ 3 ], midSide [ 3 ], midNode, cor [ 3 ]; + int nodes = 3, sides = 3; double x = 0.0, y = 0.0; static int sideNode [ 3 ] [ 2 ] = { { 1, 2 }, { 2, 3 }, { 3, 1 } }; + FloatArray corner [ 3 ], midSide [ 3 ], midNode, cor [ 3 ]; if ( sMode == HuertaErrorEstimatorInterface :: NodeMode || ( sMode == HuertaErrorEstimatorInterface :: BCMode && aMode == HuertaErrorEstimator :: HEE_linear ) ) { - for ( inode = 0; inode < nodes; inode++ ) { + for ( int inode = 0; inode < nodes; inode++ ) { corner [ inode ] = this->giveNode(inode + 1)->giveCoordinates(); - if ( corner [ inode ]->giveSize() != 3 ) { + if ( corner [ inode ].giveSize() != 3 ) { cor [ inode ].resize(3); - cor [ inode ].at(1) = corner [ inode ]->at(1); - cor [ inode ].at(2) = corner [ inode ]->at(2); + cor [ inode ].at(1) = corner [ inode ].at(1); + cor [ inode ].at(2) = corner [ inode ].at(2); cor [ inode ].at(3) = 0.0; - corner [ inode ] = & ( cor [ inode ] ); + corner [ inode ] = cor [ inode ]; } - x += corner [ inode ]->at(1); - y += corner [ inode ]->at(2); + x += corner [ inode ].at(1); + y += corner [ inode ].at(2); } - for ( iside = 0; iside < sides; iside++ ) { + for ( int iside = 0; iside < sides; iside++ ) { midSide [ iside ].resize(3); - nd1 = sideNode [ iside ] [ 0 ] - 1; - nd2 = sideNode [ iside ] [ 1 ] - 1; + int nd1 = sideNode [ iside ] [ 0 ] - 1; + int nd2 = sideNode [ iside ] [ 1 ] - 1; - midSide [ iside ].at(1) = ( corner [ nd1 ]->at(1) + corner [ nd2 ]->at(1) ) / 2.0; - midSide [ iside ].at(2) = ( corner [ nd1 ]->at(2) + corner [ nd2 ]->at(2) ) / 2.0; + midSide [ iside ].at(1) = ( corner [ nd1 ].at(1) + corner [ nd2 ].at(1) ) / 2.0; + midSide [ iside ].at(2) = ( corner [ nd1 ].at(2) + corner [ nd2 ].at(2) ) / 2.0; midSide [ iside ].at(3) = 0.0; } @@ -534,4 +537,11 @@ TrPlaneStress2d :: SPRNodalRecoveryMI_givePatchType() return SPRPatchType_2dxy; } +void +TrPlaneStress2d :: computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) +{ + answer=masterGpStrain; +} + + } // end namespace oofem diff --git a/src/sm/Elements/PlaneStress/trplanstrss.h b/src/sm/Elements/PlaneStress/trplanstrss.h index f18d89fd6..dd639e3b2 100644 --- a/src/sm/Elements/PlaneStress/trplanstrss.h +++ b/src/sm/Elements/PlaneStress/trplanstrss.h @@ -35,16 +35,18 @@ #ifndef trplanstrss_h #define trplanstrss_h -#include "Elements/structural2delement.h" -#include "ErrorEstimators/directerrorindicatorrc.h" -#include "ErrorEstimators/zzerrorestimator.h" -#include "ErrorEstimators/huertaerrorestimator.h" +#include "sm/Elements/structural2delement.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" +#include "sm/CrossSections/layeredcrosssection.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "sprnodalrecoverymodel.h" #include "spatiallocalizer.h" #include "mmashapefunctprojection.h" + #define _IFT_TrPlaneStress2d_Name "trplanestress2d" namespace oofem { @@ -61,7 +63,8 @@ class TrPlaneStress2d : public PlaneStressElement, public ZZNodalRecoveryModelIn public NodalAveragingRecoveryModelInterface, public SPRNodalRecoveryModelInterface, public SpatialLocalizerInterface, public ZZErrorEstimatorInterface, -public HuertaErrorEstimatorInterface +public HuertaErrorEstimatorInterface, +public LayeredCrossSectionInterface { protected: static FEI2dTrLin interp; @@ -71,43 +74,45 @@ public HuertaErrorEstimatorInterface TrPlaneStress2d(int n, Domain * d); virtual ~TrPlaneStress2d() { } - virtual FEInterpolation *giveInterpolation() const; - virtual double giveCharacteristicSize(GaussPoint *gp, FloatArray &normalToCrackPlane, ElementCharSizeMethod method); - virtual double giveParentElSize() const { return 0.5; } - virtual Interface *giveInterface(InterfaceType); + FEInterpolation *giveInterpolation() const override; + double giveCharacteristicSize(GaussPoint *gp, FloatArray &normalToCrackPlane, ElementCharSizeMethod method) override; + double giveParentElSize() const override { return 0.5; } + Interface *giveInterface(InterfaceType) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_TrPlaneStress2d_Name; } - virtual const char *giveClassName() const { return "TrPlaneStress2d"; } + const char *giveInputRecordName() const override { return _IFT_TrPlaneStress2d_Name; } + const char *giveClassName() const override { return "TrPlaneStress2d"; } - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; // HuertaErrorEstimatorInterface - virtual void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, - IntArray &localNodeIdArray, IntArray &globalNodeIdArray, - HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, - int &localNodeId, int &localElemId, int &localBcId, - IntArray &controlNode, IntArray &controlDof, - HuertaErrorEstimator :: AnalysisMode aMode); - virtual void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); + void HuertaErrorEstimatorI_setupRefinedElementProblem(RefinedElement *refinedElement, int level, int nodeId, + IntArray &localNodeIdArray, IntArray &globalNodeIdArray, + HuertaErrorEstimatorInterface :: SetupMode sMode, TimeStep *tStep, + int &localNodeId, int &localElemId, int &localBcId, + IntArray &controlNode, IntArray &controlDof, + HuertaErrorEstimator :: AnalysisMode aMode) override; + void HuertaErrorEstimatorI_computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + // Methods to implement LayeredCrossSectionInterface + void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) override; protected: virtual double giveArea(); - virtual int giveNumberOfIPForMassMtrxIntegration() { return 4; } + int giveNumberOfIPForMassMtrxIntegration() override { return 4; } }; } // end namespace oofem #endif // trplanstrss_h diff --git a/src/sm/Elements/PlaneStress/trplanstrssxfem.C b/src/sm/Elements/PlaneStress/trplanstrssxfem.C index 4fda35eec..621fd5e47 100644 --- a/src/sm/Elements/PlaneStress/trplanstrssxfem.C +++ b/src/sm/Elements/PlaneStress/trplanstrssxfem.C @@ -5,10 +5,10 @@ * Author: svennine */ -#include "../sm/Elements/PlaneStress/trplanstrssxfem.h" +#include "sm/Elements/PlaneStress/trplanstrssxfem.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "vtkxmlexportmodule.h" #include "xfem/xfemelementinterface.h" #include "xfem/enrichmentfunction.h" @@ -296,29 +296,19 @@ void TrPlaneStress2dXFEM :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) } #endif -IRResultType -TrPlaneStress2dXFEM :: initializeFrom(InputRecord *ir) +void +TrPlaneStress2dXFEM :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - result = TrPlaneStress2d :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + TrPlaneStress2d :: initializeFrom(ir); + XfemStructuralElementInterface :: initializeCZFrom(ir); - result = XfemStructuralElementInterface :: initializeCZFrom(ir); - if ( result != IRRT_OK ) { - return result; + if ( ir.hasField(_IFT_TrPlaneStress2dXFEM_RegCoeff) ) { + ir.giveOptionalField(mRegCoeff, _IFT_TrPlaneStress2dXFEM_RegCoeff); } - if(ir->hasField(_IFT_TrPlaneStress2dXFEM_RegCoeff) ) { - ir->giveOptionalField(mRegCoeff, _IFT_TrPlaneStress2dXFEM_RegCoeff); + if ( ir.hasField(_IFT_TrPlaneStress2dXFEM_RegCoeffTol) ) { + ir.giveOptionalField(mRegCoeffTol, _IFT_TrPlaneStress2dXFEM_RegCoeffTol); } - - if(ir->hasField(_IFT_TrPlaneStress2dXFEM_RegCoeffTol) ) { - ir->giveOptionalField(mRegCoeffTol, _IFT_TrPlaneStress2dXFEM_RegCoeffTol); - } - - return result; } MaterialMode TrPlaneStress2dXFEM :: giveMaterialMode() @@ -376,7 +366,7 @@ TrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiece // Node coordinates std :: vector< FloatArray >nodeCoords; for(int i = 1; i <= 3; i++) { - FloatArray &x = *(giveDofManager(i)->giveCoordinates()); + const auto &x = giveDofManager(i)->giveCoordinates(); nodeCoords.push_back(x); vtkPieces[0].setNodeCoords(i, x); @@ -397,7 +387,7 @@ TrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiece // Export nodal variables from primary fields - vtkPieces[0].setNumberOfPrimaryVarsToExport(primaryVarsToExport.giveSize(), numTotalNodes); + vtkPieces[0].setNumberOfPrimaryVarsToExport(primaryVarsToExport, numTotalNodes); for ( int fieldNum = 1; fieldNum <= primaryVarsToExport.giveSize(); fieldNum++ ) { UnknownType type = ( UnknownType ) primaryVarsToExport.at(fieldNum); @@ -430,7 +420,7 @@ TrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiece u = {uTemp[0], uTemp[1], 0.0}; } - vtkPieces[0].setPrimaryVarInNode(fieldNum, nodeInd, u); + vtkPieces[0].setPrimaryVarInNode(type, nodeInd, u); } else { printf("fieldNum: %d\n", fieldNum); // TODO: Implement @@ -445,11 +435,11 @@ TrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiece // Export nodal variables from internal fields - vtkPieces[0].setNumberOfInternalVarsToExport(0, numTotalNodes); + vtkPieces[0].setNumberOfInternalVarsToExport(internalVarsToExport, numTotalNodes); // Export cell variables - vtkPieces[0].setNumberOfCellVarsToExport(cellVarsToExport.giveSize(), 1); + vtkPieces[0].setNumberOfCellVarsToExport(cellVarsToExport, 1); for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) { InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i); FloatArray average; @@ -460,7 +450,7 @@ TrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiece } if(average.giveSize() == 1) { - vtkPieces[0].setCellVar( i, 1, average ); + vtkPieces[0].setCellVar( type, 1, average ); } if(average.giveSize() == 6) { @@ -472,7 +462,7 @@ TrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiece averageV9.at(3) = averageV9.at(7) = average.at(5); averageV9.at(2) = averageV9.at(4) = average.at(6); - vtkPieces[0].setCellVar( i, 1, averageV9 ); + vtkPieces[0].setCellVar( type, 1, averageV9 ); } } @@ -508,7 +498,7 @@ TrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiece for(int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++) { DofManager *dMan = giveDofManager(elNodeInd); - ei->evalLevelSetNormalInNode(levelSetInNode, dMan->giveGlobalNumber(), *(dMan->giveCoordinates()) ); + ei->evalLevelSetNormalInNode(levelSetInNode, dMan->giveGlobalNumber(), dMan->giveCoordinates() ); levelSet += N.at(elNodeInd)*levelSetInNode; } @@ -522,7 +512,7 @@ TrPlaneStress2dXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPiece for(int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++) { DofManager *dMan = giveDofManager(elNodeInd); - ei->evalLevelSetTangInNode(levelSetInNode, dMan->giveGlobalNumber(), *(dMan->giveCoordinates()) ); + ei->evalLevelSetTangInNode(levelSetInNode, dMan->giveGlobalNumber(), dMan->giveCoordinates() ); levelSet += N.at(elNodeInd)*levelSetInNode; } diff --git a/src/sm/Elements/PlaneStress/trplanstrssxfem.h b/src/sm/Elements/PlaneStress/trplanstrssxfem.h index 9f17713da..6cc0f96e3 100644 --- a/src/sm/Elements/PlaneStress/trplanstrssxfem.h +++ b/src/sm/Elements/PlaneStress/trplanstrssxfem.h @@ -35,8 +35,8 @@ #ifndef TRPLANSTRSSXFEM_H_ #define TRPLANSTRSSXFEM_H_ -#include "../sm/Elements/PlaneStress/trplanstrss.h" -#include "../sm/xfem/xfemstructuralelementinterface.h" +#include "sm/Elements/PlaneStress/trplanstrss.h" +#include "sm/xfem/xfemstructuralelementinterface.h" #include "vtkxmlexportmodule.h" @@ -53,8 +53,8 @@ namespace oofem { class TrPlaneStress2dXFEM : public TrPlaneStress2d, public XfemStructuralElementInterface, public VTKXMLExportModuleElementInterface { protected: - virtual void updateYourself(TimeStep *tStep); - virtual void postInitialize(); + void updateYourself(TimeStep *tStep) override; + void postInitialize() override; double mRegCoeff, mRegCoeffTol; @@ -63,51 +63,50 @@ class TrPlaneStress2dXFEM : public TrPlaneStress2d, public XfemStructuralElement virtual ~TrPlaneStress2dXFEM(); - virtual int checkConsistency(); + int checkConsistency() override; - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual const char *giveInputRecordName() const { return _IFT_TrPlaneStress2dXFEM_Name; } - virtual const char *giveClassName() const { return "TrPlaneStress2dXFEM"; } + const char *giveInputRecordName() const override { return _IFT_TrPlaneStress2dXFEM_Name; } + const char *giveClassName() const override { return "TrPlaneStress2dXFEM"; } - virtual int computeNumberOfDofs(); - virtual void computeGaussPoints(); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, - int lowerIndx = 1, int upperIndx = ALL_STRAINS); - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *, TimeStep *tStep); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + int computeNumberOfDofs() override; + void computeGaussPoints() override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; - virtual void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override; - virtual void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) { XfemStructuralElementInterface :: XfemElementInterface_computeConsistentMassMatrix(answer, tStep, mass, ipDensity); } + void computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL) override { XfemStructuralElementInterface :: XfemElementInterface_computeConsistentMassMatrix(answer, tStep, mass, ipDensity); } - virtual Element_Geometry_Type giveGeometryType() const; + Element_Geometry_Type giveGeometryType() const override; #ifdef __OOFEG // TODO: Implement OOFEG functions - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - //virtual void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep); + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + //void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep) override; #endif - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode(); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer); - virtual void giveElementDofIDMask(IntArray &answer) const; + void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) override; + void giveElementDofIDMask(IntArray &answer) const override; /// VTK Interface - virtual void giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep); + void giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep) override; }; } /* namespace oofem */ diff --git a/src/sm/Elements/Plates/cct.C b/src/sm/Elements/Plates/cct.C index 35cad6a2d..00aaed912 100644 --- a/src/sm/Elements/Plates/cct.C +++ b/src/sm/Elements/Plates/cct.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Plates/cct.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/Plates/cct.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei2dtrlin.h" #include "node.h" #include "material.h" @@ -55,11 +55,11 @@ namespace oofem { REGISTER_Element(CCTPlate); -FEI2dTrLin CCTPlate :: interp_lin(1, 2); +FEI2dTrLin CCTPlate::interp_lin(1, 2); //FEI2dTrRot CCTPlate :: interp_rot(1, 2); -CCTPlate :: CCTPlate(int n, Domain *aDomain) : - NLStructuralElement(n, aDomain), +CCTPlate::CCTPlate(int n, Domain *aDomain) : + StructuralElement(n, aDomain), LayeredCrossSectionInterface(), ZZNodalRecoveryModelInterface(this), NodalAveragingRecoveryModelInterface(), SPRNodalRecoveryModelInterface(), ZZErrorEstimatorInterface(this) { @@ -70,11 +70,11 @@ CCTPlate :: CCTPlate(int n, Domain *aDomain) : FEInterpolation * -CCTPlate :: giveInterpolation() const { return & interp_lin; } +CCTPlate::giveInterpolation() const { return & interp_lin; } FEInterpolation * -CCTPlate :: giveInterpolation(DofIDItem id) const +CCTPlate::giveInterpolation(DofIDItem id) const { if ( id == D_w ) { return & interp_lin; @@ -85,19 +85,19 @@ CCTPlate :: giveInterpolation(DofIDItem id) const void -CCTPlate :: computeGaussPoints() +CCTPlate::computeGaussPoints() // Sets up the array containing the four Gauss points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 5) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 5); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } void -CCTPlate :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) +CCTPlate::computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) // Computes numerically the load vector of the receiver due to the body loads, at tStep. // load is assumed to be in global cs. // load vector is then transformed to coordinate system in each node. @@ -142,13 +142,13 @@ CCTPlate :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep void -CCTPlate :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +CCTPlate::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the [5x9] strain-displacement matrix {B} of the receiver, // evaluated at gp. { // get node coordinates - double x1, x2, x3, y1, y2, y3, z1, z2, z3; - this->giveNodeCoordinates(x1, x2, x3, y1, y2, y3, z1, z2, z3); + double x1, x2, x3, y1, y2, y3, z1, z2, z3; + this->giveNodeCoordinates(x1, x2, x3, y1, y2, y3, z1, z2, z3); // double area, b1, b2, b3, c1, c2, c3, l1, l2, l3; @@ -205,18 +205,18 @@ CCTPlate :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui answer.at(5, 8) = ( -b2 * c3 * l1 - b2 * c1 * l3 + b1 * c2 * l3 + b1 * c3 * l2 ) * 0.5 - l3 * 2. * area; answer.at(5, 9) = ( -c3 * c2 * l1 + c3 * c1 * l2 ) * 0.5; - answer.times( 1. / ( 2. * area ) ); + answer.times(1. / ( 2. * area ) ); } void -CCTPlate :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +CCTPlate::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the [3x9] displacement interpolation matrix {N} of the receiver, // evaluated at gp. { // get node coordinates - double x1, x2, x3, y1, y2, y3, z1, z2, z3; - this->giveNodeCoordinates(x1, x2, x3, y1, y2, y3, z1, z2, z3); + double x1, x2, x3, y1, y2, y3, z1, z2, z3; + this->giveNodeCoordinates(x1, x2, x3, y1, y2, y3, z1, z2, z3); // double l1, l2, l3, b1, b2, b3, c1, c2, c3; @@ -258,79 +258,77 @@ CCTPlate :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) void -CCTPlate :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +CCTPlate::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Plate(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Plate(strain, gp, tStep); } void -CCTPlate :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +CCTPlate::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give2dPlateStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give2dPlateStiffMtrx(rMode, gp, tStep); } void -CCTPlate :: giveNodeCoordinates(double &x1, double &x2, double &x3, - double &y1, double &y2, double &y3, - double &z1, double &z2, double &z3) +CCTPlate::giveNodeCoordinates(double &x1, double &x2, double &x3, + double &y1, double &y2, double &y3, + double &z1, double &z2, double &z3) { - FloatArray *nc1, *nc2, *nc3; - nc1 = this->giveNode(1)->giveCoordinates(); - nc2 = this->giveNode(2)->giveCoordinates(); - nc3 = this->giveNode(3)->giveCoordinates(); - - x1 = nc1->at(1); - x2 = nc2->at(1); - x3 = nc3->at(1); - - y1 = nc1->at(2); - y2 = nc2->at(2); - y3 = nc3->at(2); - - z1 = nc1->at(3); - z2 = nc2->at(3); - z3 = nc3->at(3); - + const auto &nc1 = this->giveNode(1)->giveCoordinates(); + const auto &nc2 = this->giveNode(2)->giveCoordinates(); + const auto &nc3 = this->giveNode(3)->giveCoordinates(); + + x1 = nc1.at(1); + x2 = nc2.at(1); + x3 = nc3.at(1); + + y1 = nc1.at(2); + y2 = nc2.at(2); + y3 = nc3.at(2); + + z1 = nc1.at(3); + z2 = nc2.at(3); + z3 = nc3.at(3); } double -CCTPlate :: computeArea () +CCTPlate::computeArea() // returns the area occupied by the receiver { - // get node coordinates - double x1, x2, x3, y1, y2, y3, z1, z2, z3; - this->giveNodeCoordinates(x1, x2, x3, y1, y2, y3, z1, z2, z3); - - if (area > 0) return area; // check if previously computed - - return (area = 0.5*(x2*y3+x1*y2+y1*x3-x2*y1-x3*y2-x1*y3)) ; - + // get node coordinates + double x1, x2, x3, y1, y2, y3, z1, z2, z3; + this->giveNodeCoordinates(x1, x2, x3, y1, y2, y3, z1, z2, z3); + + if ( area > 0 ) { + return area; // check if previously computed + } + return ( area = 0.5 * ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 ) ); } -IRResultType -CCTPlate :: initializeFrom(InputRecord *ir) +void +CCTPlate::initializeFrom(InputRecord &ir) { numberOfGaussPoints = 1; - return NLStructuralElement :: initializeFrom(ir); + StructuralElement::initializeFrom(ir); } void -CCTPlate :: giveDofManDofIDMask(int inode, IntArray &answer) const +CCTPlate::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_w, R_u, R_v}; + answer = { D_w, R_u, R_v }; } void -CCTPlate :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) +CCTPlate::computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) // returns normal vector to midPlane in GaussPoinr gp of receiver { FloatArray u, v; - u.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - v.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); + u.beDifferenceOf(this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); + v.beDifferenceOf(this->giveNode(3)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); answer.beVectorProductOf(u, v); answer.normalize(); @@ -338,7 +336,7 @@ CCTPlate :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) double -CCTPlate :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) +CCTPlate::giveCharacteristicLength(const FloatArray &normalToCrackPlane) // returns receiver's characteristic length (for crack band models) // for a crack formed in the plane with normal normalToCrackPlane. { @@ -347,24 +345,24 @@ CCTPlate :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) double -CCTPlate :: computeVolumeAround(GaussPoint *gp) +CCTPlate::computeVolumeAround(GaussPoint *gp) // Returns the portion of the receiver which is attached to gp. { double detJ, weight; - std :: vector< FloatArray > lc = {FloatArray(3), FloatArray(3), FloatArray(3)}; - this->giveNodeCoordinates(lc[0].at(1), lc[1].at(1), lc[2].at(1), - lc[0].at(2), lc[1].at(2), lc[2].at(2), - lc[0].at(3), lc[1].at(3), lc[2].at(3)); + std::vector< FloatArray >lc = { FloatArray(3), FloatArray(3), FloatArray(3) }; + this->giveNodeCoordinates( lc [ 0 ].at(1), lc [ 1 ].at(1), lc [ 2 ].at(1), + lc [ 0 ].at(2), lc [ 1 ].at(2), lc [ 2 ].at(2), + lc [ 0 ].at(3), lc [ 1 ].at(3), lc [ 2 ].at(3) ); weight = gp->giveWeight(); - detJ = fabs( this->interp_lin.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lc) ) ); + detJ = fabs(this->interp_lin.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lc) ) ); return detJ * weight; ///@todo What about thickness? } void -CCTPlate :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +CCTPlate::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. { answer.resize(9, 9); @@ -373,11 +371,11 @@ CCTPlate :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) double mass = 0.0; IntegrationRule *iRule = this->giveDefaultIntegrationRulePtr(); if ( iRule ) { - for ( GaussPoint *gp: *iRule ) { - mass += this->computeVolumeAround(gp) * this->giveStructuralCrossSection()->give('d', gp) * this->giveCrossSection()->give(CS_Thickness, gp); + for ( GaussPoint *gp: * iRule ) { + mass += this->computeVolumeAround(gp) * this->giveStructuralCrossSection()->give('d', gp) * this->giveCrossSection()->give(CS_Thickness, gp); } } - double mass3 = mass/3.0; + double mass3 = mass / 3.0; answer.at(1, 1) = mass3; answer.at(4, 4) = mass3; @@ -386,18 +384,18 @@ CCTPlate :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) Interface * -CCTPlate :: giveInterface(InterfaceType interface) +CCTPlate::giveInterface(InterfaceType interface) { if ( interface == LayeredCrossSectionInterfaceType ) { - return static_cast< LayeredCrossSectionInterface * >(this); + return static_cast< LayeredCrossSectionInterface * >( this ); } else if ( interface == ZZNodalRecoveryModelInterfaceType ) { - return static_cast< ZZNodalRecoveryModelInterface * >(this); + return static_cast< ZZNodalRecoveryModelInterface * >( this ); } else if ( interface == NodalAveragingRecoveryModelInterfaceType ) { - return static_cast< NodalAveragingRecoveryModelInterface * >(this); + return static_cast< NodalAveragingRecoveryModelInterface * >( this ); } else if ( interface == SPRNodalRecoveryModelInterfaceType ) { - return static_cast< SPRNodalRecoveryModelInterface * >(this); + return static_cast< SPRNodalRecoveryModelInterface * >( this ); } else if ( interface == ZZErrorEstimatorInterfaceType ) { - return static_cast< ZZErrorEstimatorInterface * >(this); + return static_cast< ZZErrorEstimatorInterface * >( this ); } @@ -408,7 +406,7 @@ CCTPlate :: giveInterface(InterfaceType interface) #define POINT_TOL 1.e-3 bool -CCTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) +CCTPlate::computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) //converts global coordinates to local planar area coordinates, //does not return a coordinate in the thickness direction, but //does check that the point is in the element thickness @@ -418,7 +416,7 @@ CCTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords this->giveNodeCoordinates(x1, x2, x3, y1, y2, y3, z1, z2, z3); // Fetch local coordinates. - bool ok = this->interp_lin.global2local( answer, coords, FEIElementGeometryWrapper(this) ) > 0; + bool ok = this->interp_lin.global2local(answer, coords, FEIElementGeometryWrapper(this) ) > 0; //get midplane location at this point double midplZ; @@ -429,7 +427,7 @@ CCTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords StructuralCrossSection *cs = this->giveStructuralCrossSection(); double elthick = cs->give(CS_Thickness, & _gp); - if ( elthick / 2.0 + midplZ - fabs( coords.at(3) ) < -POINT_TOL ) { + if ( elthick / 2.0 + midplZ - fabs(coords.at(3) ) < -POINT_TOL ) { answer.zero(); return false; } @@ -450,7 +448,7 @@ CCTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords int -CCTPlate :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +CCTPlate::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { FloatArray help; answer.resize(6); @@ -481,17 +479,17 @@ CCTPlate :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType ty answer.at(6) = help.at(3); // mxy return 1; } else { - return NLStructuralElement :: giveIPValue(answer, gp, type, tStep); + return StructuralElement::giveIPValue(answer, gp, type, tStep); } } void -CCTPlate :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep) +CCTPlate::NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) { GaussPoint *gp; if ( ( type == IST_ShellForceTensor ) || ( type == IST_ShellMomentTensor ) || - ( type == IST_ShellStrainTensor ) || ( type == IST_CurvatureTensor ) ) { + ( type == IST_ShellStrainTensor ) || ( type == IST_CurvatureTensor ) ) { gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); this->giveIPValue(answer, gp, type, tStep); } else { @@ -501,7 +499,7 @@ CCTPlate :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int n void -CCTPlate :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) +CCTPlate::SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) { pap.resize(3); pap.at(1) = this->giveNode(1)->giveNumber(); @@ -511,12 +509,12 @@ CCTPlate :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) void -CCTPlate :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) +CCTPlate::SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) { answer.resize(1); if ( ( pap == this->giveNode(1)->giveNumber() ) || - ( pap == this->giveNode(2)->giveNumber() ) || - ( pap == this->giveNode(3)->giveNumber() ) ) { + ( pap == this->giveNode(2)->giveNumber() ) || + ( pap == this->giveNode(3)->giveNumber() ) ) { answer.at(1) = pap; } else { OOFEM_ERROR("node unknown"); @@ -525,7 +523,7 @@ CCTPlate :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, in SPRPatchType -CCTPlate :: SPRNodalRecoveryMI_givePatchType() +CCTPlate::SPRNodalRecoveryMI_givePatchType() { return SPRPatchType_2dxy; } @@ -535,8 +533,8 @@ CCTPlate :: SPRNodalRecoveryMI_givePatchType() // layered cross section support functions // void -CCTPlate :: computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) +CCTPlate::computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) // returns full 3d strain vector of given layer (whose z-coordinate from center-line is // stored in slaveGp) for given tStep { @@ -558,36 +556,36 @@ CCTPlate :: computeStrainVectorInLayer(FloatArray &answer, const FloatArray &mas // Edge load support /* -void -CCTPlate :: computeEgdeNMatrixAt(FloatMatrix &answer, int iedge, GaussPoint *gp) -{ - IntArray edgeNodes; - FloatArray n; - double b, c, n12; - - this->interp_lin.edgeEvalN( n, iedge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - this->interp_lin.computeLocalEdgeMapping(edgeNodes, iedge); - - n12 = 0.5 * n.at(1) * n.at(2); - b = this->giveNode( edgeNodes.at(1) )->giveCoordinate(2) - this->giveNode( edgeNodes.at(2) )->giveCoordinate(2); - c = this->giveNode( edgeNodes.at(2) )->giveCoordinate(1) - this->giveNode( edgeNodes.at(1) )->giveCoordinate(1); - - - answer.resize(3, 6); - answer.at(1, 1) = n.at(1); - answer.at(1, 2) = n12 * b; - answer.at(1, 3) = n12 * c; - answer.at(1, 4) = n.at(2); - answer.at(1, 5) = -n12 * b; - answer.at(1, 6) = -n12 * c; - // - answer.at(2, 2) = answer.at(3, 3) = n.at(1); - answer.at(2, 5) = answer.at(3, 6) = n.at(2); -} -*/ + * void + * CCTPlate :: computeEgdeNMatrixAt(FloatMatrix &answer, int iedge, GaussPoint *gp) + * { + * IntArray edgeNodes; + * FloatArray n; + * double b, c, n12; + * + * this->interp_lin.edgeEvalN( n, iedge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + * this->interp_lin.computeLocalEdgeMapping(edgeNodes, iedge); + * + * n12 = 0.5 * n.at(1) * n.at(2); + * b = this->giveNode( edgeNodes.at(1) )->giveCoordinate(2) - this->giveNode( edgeNodes.at(2) )->giveCoordinate(2); + * c = this->giveNode( edgeNodes.at(2) )->giveCoordinate(1) - this->giveNode( edgeNodes.at(1) )->giveCoordinate(1); + * + * + * answer.resize(3, 6); + * answer.at(1, 1) = n.at(1); + * answer.at(1, 2) = n12 * b; + * answer.at(1, 3) = n12 * c; + * answer.at(1, 4) = n.at(2); + * answer.at(1, 5) = -n12 * b; + * answer.at(1, 6) = -n12 * c; + * // + * answer.at(2, 2) = answer.at(3, 3) = n.at(1); + * answer.at(2, 5) = answer.at(3, 6) = n.at(2); + * } + */ void -CCTPlate :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +CCTPlate::giveEdgeDofMapping(IntArray &answer, int iEdge) const { /* * provides dof mapping of local edge dofs (only nonzero are taken into account) @@ -622,15 +620,15 @@ CCTPlate :: giveEdgeDofMapping(IntArray &answer, int iEdge) const } double -CCTPlate :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +CCTPlate::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { - double detJ = this->interp_lin.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - return detJ *gp->giveWeight(); + double detJ = this->interp_lin.edgeGiveTransformationJacobian(iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + return detJ * gp->giveWeight(); } int -CCTPlate :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +CCTPlate::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -639,22 +637,17 @@ CCTPlate :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gauss // // i.e. f(element local) = T * f(edge local) // - double dx, dy, length; - IntArray edgeNodes; - Node *nodeA, *nodeB; + const auto &edgeNodes = this->interp_lin.computeLocalEdgeMapping(iEdge); - answer.resize(3, 3); - answer.zero(); - - this->interp_lin.computeLocalEdgeMapping(edgeNodes, iEdge); + auto nodeA = this->giveNode(edgeNodes.at(1) ); + auto nodeB = this->giveNode(edgeNodes.at(2) ); - nodeA = this->giveNode( edgeNodes.at(1) ); - nodeB = this->giveNode( edgeNodes.at(2) ); - - dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); - dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); - length = sqrt(dx * dx + dy * dy); + double dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); + double dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); + double length = sqrt(dx * dx + dy * dy); + answer.resize(3, 3); + answer.zero(); answer.at(1, 1) = 1.0; answer.at(2, 2) = dx / length; answer.at(2, 3) = -dy / length; @@ -668,33 +661,33 @@ CCTPlate :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gauss void CCTPlate::computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) { - if (boundaryID == 1) { - this->computeNmatrixAt(lcoords, answer); - } else { - OOFEM_ERROR("computeSurfaceNMatrix: Unsupported surface id"); - } + if ( boundaryID == 1 ) { + this->computeNmatrixAt(lcoords, answer); + } else { + OOFEM_ERROR("computeSurfaceNMatrix: Unsupported surface id"); + } } - + // // io routines // #ifdef __OOFEG void -CCTPlate :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +CCTPlate::drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { - WCRec p [ 3 ]; + WCRec p[ 3 ]; GraphicObj *go; if ( !gc.testElementGraphicActivity(this) ) { return; } - if ( this->giveMaterial()->isActivated(tStep) ) { + if ( this->isActivated(tStep) ) { EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); - EASValsSetEdgeColor( gc.getElementEdgeColor() ); + EASValsSetColor(gc.getElementColor() ); + EASValsSetEdgeColor(gc.getElementEdgeColor() ); EASValsSetEdgeFlag(true); EASValsSetFillStyle(FILL_SOLID); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); @@ -717,9 +710,9 @@ CCTPlate :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) void -CCTPlate :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +CCTPlate::drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) { - WCRec p [ 3 ]; + WCRec p[ 3 ]; GraphicObj *go; double defScale = gc.getDefScale(); @@ -727,10 +720,10 @@ CCTPlate :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Unkno return; } - if ( this->giveMaterial()->isActivated(tStep) ) { + if ( this->isActivated(tStep) ) { EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); - EASValsSetEdgeColor( gc.getElementEdgeColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetEdgeColor(gc.getElementEdgeColor() ); EASValsSetEdgeFlag(true); EASValsSetFillStyle(FILL_SOLID); EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); @@ -752,19 +745,19 @@ CCTPlate :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Unkno void -CCTPlate :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) +CCTPlate::drawScalar(oofegGraphicContext &gc, TimeStep *tStep) { int i, indx, result = 0; - WCRec p [ 3 ]; + WCRec p[ 3 ]; GraphicObj *tr; FloatArray v1, v2, v3; - double s [ 3 ], defScale; + double s[ 3 ], defScale; if ( !gc.testElementGraphicActivity(this) ) { return; } - if ( !this->giveMaterial()->isActivated(tStep) ) { + if ( !this->isActivated(tStep) ) { return; } diff --git a/src/sm/Elements/Plates/cct.h b/src/sm/Elements/Plates/cct.h index 8f6ede216..9f67eba80 100644 --- a/src/sm/Elements/Plates/cct.h +++ b/src/sm/Elements/Plates/cct.h @@ -35,9 +35,9 @@ #ifndef cct_h #define cct_h -#include "../sm/Elements/nlstructuralelement.h" -#include "../sm/CrossSections/layeredcrosssection.h" -#include "../sm/ErrorEstimators/zzerrorestimator.h" +#include "sm/Elements/nlstructuralelement.h" +#include "sm/CrossSections/layeredcrosssection.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" #include "mathfem.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" @@ -55,10 +55,10 @@ class FEI2dTrLin; * Tasks: * - calculating its B,D,N matrices and dV. */ -class CCTPlate : public NLStructuralElement, -public LayeredCrossSectionInterface, public ZZNodalRecoveryModelInterface, -public NodalAveragingRecoveryModelInterface, public SPRNodalRecoveryModelInterface, -public ZZErrorEstimatorInterface +class CCTPlate : public StructuralElement, + public LayeredCrossSectionInterface, public ZZNodalRecoveryModelInterface, + public NodalAveragingRecoveryModelInterface, public SPRNodalRecoveryModelInterface, + public ZZErrorEstimatorInterface { protected: static FEI2dTrLin interp_lin; @@ -67,25 +67,25 @@ public ZZErrorEstimatorInterface double area; public: - CCTPlate(int n, Domain * d); + CCTPlate(int n, Domain *d); virtual ~CCTPlate() { } - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; - virtual MaterialMode giveMaterialMode() { return _2dPlate; } - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } + MaterialMode giveMaterialMode() override { return _2dPlate; } + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } // overloaded to take into account possible element local cs (in derived cct3d) - virtual double computeArea(); + double computeArea() override; protected: - virtual void computeGaussPoints(); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); + void computeGaussPoints() override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; virtual void giveNodeCoordinates(double &x1, double &x2, double &x3, @@ -94,54 +94,53 @@ public ZZErrorEstimatorInterface //virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, GaussPoint *gp) { answer.clear(); } - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; //virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const { answer.clear(); } - //virtual IntegrationRule *GetSurfaceIntegrationRule(int i) { return NULL; } - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; //virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { return 0.; } - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; public: // definition & identification - virtual const char *giveClassName() const { return "CCTPlate"; } - virtual const char *giveInputRecordName() const { return _IFT_CCTPlate_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "CCTPlate"; } + const char *giveInputRecordName() const override { return _IFT_CCTPlate_Name; } + void initializeFrom(InputRecord &ir) override; - virtual int computeNumberOfDofs() { return 9; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 9; } + void giveDofManDofIDMask(int inode, IntArray &) const override; - virtual void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp); + void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) override; - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane); - virtual double computeVolumeAround(GaussPoint *gp); + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override; + double computeVolumeAround(GaussPoint *gp) override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP() { return 1; } - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override { return 1; } + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; // layered cross section support functions - virtual void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep); + void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) override; // boundary load support - virtual void computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords); + void computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif }; } // end namespace oofem diff --git a/src/sm/Elements/Plates/dkt.C b/src/sm/Elements/Plates/dkt.C index 37bb5e70d..1ff15843e 100644 --- a/src/sm/Elements/Plates/dkt.C +++ b/src/sm/Elements/Plates/dkt.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Plates/dkt.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/Plates/dkt.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei2dtrlin.h" #include "node.h" #include "material.h" @@ -55,10 +55,10 @@ namespace oofem { REGISTER_Element(DKTPlate); -FEI2dTrLin DKTPlate :: interp_lin(1, 2); +FEI2dTrLin DKTPlate::interp_lin(1, 2); -DKTPlate :: DKTPlate(int n, Domain *aDomain) : - NLStructuralElement(n, aDomain), +DKTPlate::DKTPlate(int n, Domain *aDomain) : + StructuralElement(n, aDomain), LayeredCrossSectionInterface(), ZZNodalRecoveryModelInterface(this), NodalAveragingRecoveryModelInterface(), SPRNodalRecoveryModelInterface(), ZZErrorEstimatorInterface(this) { @@ -69,30 +69,30 @@ DKTPlate :: DKTPlate(int n, Domain *aDomain) : FEInterpolation * -DKTPlate :: giveInterpolation() const { return & interp_lin; } +DKTPlate::giveInterpolation() const { return & interp_lin; } FEInterpolation * -DKTPlate :: giveInterpolation(DofIDItem id) const +DKTPlate::giveInterpolation(DofIDItem id) const { return & interp_lin; } void -DKTPlate :: computeGaussPoints() +DKTPlate::computeGaussPoints() // Sets up the array containing the four Gauss points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 5) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 5); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } void -DKTPlate :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) +DKTPlate::computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) // Computes numerically the load vector of the receiver due to the body loads, at tStep. // load is assumed to be in global cs. // load vector is then transformed to coordinate system in each node. @@ -136,7 +136,7 @@ DKTPlate :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep void -DKTPlate :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +DKTPlate::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the [5x9] strain-displacement matrix {B} of the receiver, // evaluated at gp. // strain components xx, yy, zz, xz, yz @@ -290,7 +290,7 @@ DKTPlate :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui void -DKTPlate :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +DKTPlate::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the [3x9] displacement interpolation matrix {N} of the receiver, // evaluated at gp. // Note: this interpolation is not available, as the deflection is cubic along the edges, @@ -302,72 +302,70 @@ DKTPlate :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) answer.resize(3, 9); answer.zero(); - giveInterpolation()->evalN( N, iLocCoord, FEIElementGeometryWrapper(this) ); + giveInterpolation()->evalN(N, iLocCoord, FEIElementGeometryWrapper(this) ); answer.beNMatrixOf(N, 3); } void -DKTPlate :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +DKTPlate::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Plate(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Plate(strain, gp, tStep); } void -DKTPlate :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +DKTPlate::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give2dPlateStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give2dPlateStiffMtrx(rMode, gp, tStep); } void -DKTPlate :: giveNodeCoordinates(double &x1, double &x2, double &x3, - double &y1, double &y2, double &y3, - double &z1, double &z2, double &z3) +DKTPlate::giveNodeCoordinates(double &x1, double &x2, double &x3, + double &y1, double &y2, double &y3, + double &z1, double &z2, double &z3) { - FloatArray *nc1, *nc2, *nc3; - nc1 = this->giveNode(1)->giveCoordinates(); - nc2 = this->giveNode(2)->giveCoordinates(); - nc3 = this->giveNode(3)->giveCoordinates(); + const auto &nc1 = this->giveNode(1)->giveCoordinates(); + const auto &nc2 = this->giveNode(2)->giveCoordinates(); + const auto &nc3 = this->giveNode(3)->giveCoordinates(); - x1 = nc1->at(1); - x2 = nc2->at(1); - x3 = nc3->at(1); + x1 = nc1.at(1); + x2 = nc2.at(1); + x3 = nc3.at(1); - y1 = nc1->at(2); - y2 = nc2->at(2); - y3 = nc3->at(2); - - z1 = nc1->at(3); - z2 = nc2->at(3); - z3 = nc3->at(3); + y1 = nc1.at(2); + y2 = nc2.at(2); + y3 = nc3.at(2); + z1 = nc1.at(3); + z2 = nc2.at(3); + z3 = nc3.at(3); } -IRResultType -DKTPlate :: initializeFrom(InputRecord *ir) +void +DKTPlate::initializeFrom(InputRecord &ir) { - return NLStructuralElement :: initializeFrom(ir); + StructuralElement::initializeFrom(ir); } void -DKTPlate :: giveDofManDofIDMask(int inode, IntArray &answer) const +DKTPlate::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_w, R_u, R_v}; + answer = { D_w, R_u, R_v }; } void -DKTPlate :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) +DKTPlate::computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) // returns normal vector to midPlane in GaussPoinr gp of receiver { FloatArray u, v; - u.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - v.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); + u.beDifferenceOf(this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); + v.beDifferenceOf(this->giveNode(3)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); answer.beVectorProductOf(u, v); answer.normalize(); @@ -375,7 +373,7 @@ DKTPlate :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) double -DKTPlate :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) +DKTPlate::giveCharacteristicLength(const FloatArray &normalToCrackPlane) // // returns receiver's characteristic length for crack band models // for a crack formed in the plane with normal normalToCrackPlane. @@ -386,23 +384,23 @@ DKTPlate :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) double -DKTPlate :: computeVolumeAround(GaussPoint *gp) +DKTPlate::computeVolumeAround(GaussPoint *gp) // Returns the portion of the receiver which is attached to gp. { double detJ, weight; - std :: vector< FloatArray > lc = {FloatArray(3), FloatArray(3), FloatArray(3)}; - this->giveNodeCoordinates(lc[0].at(1), lc[1].at(1), lc[2].at(1), - lc[0].at(2), lc[1].at(2), lc[2].at(2), - lc[0].at(3), lc[1].at(3), lc[2].at(3)); + std::vector< FloatArray >lc = { FloatArray(3), FloatArray(3), FloatArray(3) }; + this->giveNodeCoordinates( lc [ 0 ].at(1), lc [ 1 ].at(1), lc [ 2 ].at(1), + lc [ 0 ].at(2), lc [ 1 ].at(2), lc [ 2 ].at(2), + lc [ 0 ].at(3), lc [ 1 ].at(3), lc [ 2 ].at(3) ); weight = gp->giveWeight(); - detJ = fabs( this->interp_lin.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lc) ) ); + detJ = fabs(this->interp_lin.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lc) ) ); return detJ * weight; ///@todo What about thickness? } void -DKTPlate :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +DKTPlate::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. { answer.resize(9, 9); @@ -421,18 +419,18 @@ DKTPlate :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) Interface * -DKTPlate :: giveInterface(InterfaceType interface) +DKTPlate::giveInterface(InterfaceType interface) { if ( interface == LayeredCrossSectionInterfaceType ) { - return static_cast< LayeredCrossSectionInterface * >(this); + return static_cast< LayeredCrossSectionInterface * >( this ); } else if ( interface == ZZNodalRecoveryModelInterfaceType ) { - return static_cast< ZZNodalRecoveryModelInterface * >(this); + return static_cast< ZZNodalRecoveryModelInterface * >( this ); } else if ( interface == NodalAveragingRecoveryModelInterfaceType ) { - return static_cast< NodalAveragingRecoveryModelInterface * >(this); + return static_cast< NodalAveragingRecoveryModelInterface * >( this ); } else if ( interface == SPRNodalRecoveryModelInterfaceType ) { - return static_cast< SPRNodalRecoveryModelInterface * >(this); + return static_cast< SPRNodalRecoveryModelInterface * >( this ); } else if ( interface == ZZErrorEstimatorInterfaceType ) { - return static_cast< ZZErrorEstimatorInterface * >(this); + return static_cast< ZZErrorEstimatorInterface * >( this ); } @@ -443,7 +441,7 @@ DKTPlate :: giveInterface(InterfaceType interface) #define POINT_TOL 1.e-3 bool -DKTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) +DKTPlate::computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) //converts global coordinates to local planar area coordinates, //does not return a coordinate in the thickness direction, but //does check that the point is in the element thickness @@ -453,7 +451,7 @@ DKTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords this->giveNodeCoordinates(x1, x2, x3, y1, y2, y3, z1, z2, z3); // Fetch local coordinates. - bool ok = this->interp_lin.global2local( answer, coords, FEIElementGeometryWrapper(this) ) > 0; + bool ok = this->interp_lin.global2local(answer, coords, FEIElementGeometryWrapper(this) ) > 0; //check that the point is in the element and set flag for ( int i = 1; i <= 3; i++ ) { @@ -474,7 +472,7 @@ DKTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords StructuralCrossSection *cs = this->giveStructuralCrossSection(); double elthick = cs->give(CS_Thickness, answer, this); - if ( elthick / 2.0 + midplZ - fabs( coords.at(3) ) < -POINT_TOL ) { + if ( elthick / 2.0 + midplZ - fabs(coords.at(3) ) < -POINT_TOL ) { answer.zero(); return false; } @@ -485,7 +483,7 @@ DKTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords int -DKTPlate :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +DKTPlate::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { FloatArray help; answer.resize(6); @@ -516,7 +514,7 @@ DKTPlate :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType ty answer.at(6) = help.at(3); // mxy return 1; } else { - return NLStructuralElement :: giveIPValue(answer, gp, type, tStep); + return StructuralElement::giveIPValue(answer, gp, type, tStep); } } @@ -525,12 +523,12 @@ DKTPlate :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType ty // The element interface required by NodalAveragingRecoveryModel // void -DKTPlate :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep) +DKTPlate::NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) { GaussPoint *gp; if ( ( type == IST_ShellForceTensor ) || ( type == IST_ShellMomentTensor ) || - ( type == IST_ShellStrainTensor ) || ( type == IST_CurvatureTensor ) ) { + ( type == IST_ShellStrainTensor ) || ( type == IST_CurvatureTensor ) ) { gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); this->giveIPValue(answer, gp, type, tStep); } else { @@ -543,7 +541,7 @@ DKTPlate :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int n // The element interface required by SPRNodalRecoveryModelInterface // void -DKTPlate :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) +DKTPlate::SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) { pap.resize(3); pap.at(1) = this->giveNode(1)->giveNumber(); @@ -553,12 +551,12 @@ DKTPlate :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) void -DKTPlate :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) +DKTPlate::SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) { answer.resize(1); if ( ( pap == this->giveNode(1)->giveNumber() ) || - ( pap == this->giveNode(2)->giveNumber() ) || - ( pap == this->giveNode(3)->giveNumber() ) ) { + ( pap == this->giveNode(2)->giveNumber() ) || + ( pap == this->giveNode(3)->giveNumber() ) ) { answer.at(1) = pap; } else { OOFEM_ERROR("node unknown"); @@ -567,18 +565,18 @@ DKTPlate :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, in SPRPatchType -DKTPlate :: SPRNodalRecoveryMI_givePatchType() +DKTPlate::SPRNodalRecoveryMI_givePatchType() { return SPRPatchType_2dxy; } void -DKTPlate::computeEdgeNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray& lcoords) +DKTPlate::computeEdgeNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) { FloatArray n; - this->interp_lin.edgeEvalN( n, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); + this->interp_lin.edgeEvalN(n, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); answer.resize(3, 6); answer.at(1, 1) = n.at(1); @@ -588,13 +586,13 @@ DKTPlate::computeEdgeNMatrix(FloatMatrix &answer, int boundaryID, const FloatArr } - + // // layered cross section support functions // void -DKTPlate :: computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) +DKTPlate::computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) // returns full 3d strain vector of given layer (whose z-coordinate from center-line is // stored in slaveGp) for given tStep { @@ -615,7 +613,7 @@ DKTPlate :: computeStrainVectorInLayer(FloatArray &answer, const FloatArray &mas } void -DKTPlate :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +DKTPlate::giveEdgeDofMapping(IntArray &answer, int iEdge) const { /* * provides dof mapping of local edge dofs (only nonzero are taken into account) @@ -650,15 +648,15 @@ DKTPlate :: giveEdgeDofMapping(IntArray &answer, int iEdge) const } double -DKTPlate :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +DKTPlate::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { - double detJ = this->interp_lin.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - return detJ *gp->giveWeight(); + double detJ = this->interp_lin.edgeGiveTransformationJacobian(iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + return detJ * gp->giveWeight(); } int -DKTPlate :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +DKTPlate::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -667,22 +665,17 @@ DKTPlate :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gauss // // i.e. f(element local) = T * f(edge local) // - double dx, dy, length; - IntArray edgeNodes; - Node *nodeA, *nodeB; - - answer.resize(3, 3); - answer.zero(); + const auto &edgeNodes = this->interp_lin.computeLocalEdgeMapping(iEdge); - this->interp_lin.computeLocalEdgeMapping(edgeNodes, iEdge); + auto nodeA = this->giveNode(edgeNodes.at(1) ); + auto nodeB = this->giveNode(edgeNodes.at(2) ); - nodeA = this->giveNode( edgeNodes.at(1) ); - nodeB = this->giveNode( edgeNodes.at(2) ); - - dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); - dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); - length = sqrt(dx * dx + dy * dy); + double dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); + double dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); + double length = sqrt(dx * dx + dy * dy); + answer.resize(3, 3); + answer.zero(); answer.at(1, 1) = 1.0; answer.at(2, 2) = dx / length; answer.at(2, 3) = -dy / length; @@ -695,13 +688,13 @@ DKTPlate :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gauss void -DKTPlate :: computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) +DKTPlate::computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) { this->computeNmatrixAt(sgp->giveNaturalCoordinates(), answer); } void -DKTPlate :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +DKTPlate::giveSurfaceDofMapping(IntArray &answer, int iSurf) const { answer.resize(9); answer.zero(); @@ -714,30 +707,22 @@ DKTPlate :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const } } -IntegrationRule * -DKTPlate :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, approxOrder); - iRule->SetUpPointsOnTriangle(npoints, _Unknown); - return iRule; -} double -DKTPlate :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) +DKTPlate::computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { return this->computeVolumeAround(gp); } int -DKTPlate :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) +DKTPlate::computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) { return 0; } void -DKTPlate :: computeVertexBendingMoments(FloatMatrix &answer, TimeStep *tStep) +DKTPlate::computeVertexBendingMoments(FloatMatrix &answer, TimeStep *tStep) { #ifdef DKT_EnableVertexMomentsCache if ( stateCounter == tStep->giveSolutionStateCounter() ) { @@ -751,7 +736,7 @@ DKTPlate :: computeVertexBendingMoments(FloatMatrix &answer, TimeStep *tStep) answer.resize(5, 3); FloatArray eps, m; - FloatArray coords [ 3 ]; // vertex local coordinates + FloatArray coords[ 3 ]; // vertex local coordinates coords [ 0 ] = { 1.0, 0.0 }; @@ -769,7 +754,7 @@ DKTPlate :: computeVertexBendingMoments(FloatMatrix &answer, TimeStep *tStep) for ( int i = 1; i <= this->numberOfDofMans; i++ ) { vgp->setNaturalCoordinates(coords [ i - 1 ]); this->computeStrainVector(eps, vgp, tStep); - this->giveStructuralCrossSection()->giveGeneralizedStress_Plate(m, vgp, eps, tStep); + m = this->giveStructuralCrossSection()->giveGeneralizedStress_Plate(eps, vgp, tStep); answer.setColumn(m, i); } @@ -780,14 +765,14 @@ DKTPlate :: computeVertexBendingMoments(FloatMatrix &answer, TimeStep *tStep) } void -DKTPlate :: computeShearForces(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +DKTPlate::computeShearForces(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { // as shear strains are enforced to be zero (art least on element edges) the shear forces are computed from equlibrium FloatMatrix m, dndx; answer.resize(5); this->computeVertexBendingMoments(m, tStep); - this->interp_lin.evaldNdx( dndx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interp_lin.evaldNdx(dndx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); for ( int i = 1; i <= this->numberOfDofMans; i++ ) { answer.at(4) += m.at(1, i) * dndx.at(i, 1) + m.at(3, i) * dndx.at(i, 2); //dMxdx + dMxydy answer.at(5) += m.at(2, i) * dndx.at(i, 2) + m.at(3, i) * dndx.at(i, 1); //dMydy + dMxydx @@ -800,9 +785,9 @@ DKTPlate :: computeShearForces(FloatArray &answer, GaussPoint *gp, TimeStep *tSt // #ifdef __OOFEG void -DKTPlate :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +DKTPlate::drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { - WCRec p [ 3 ]; + WCRec p[ 3 ]; GraphicObj *go; if ( !gc.testElementGraphicActivity(this) ) { @@ -811,8 +796,8 @@ DKTPlate :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) if ( this->giveMaterial()->isActivated(tStep) ) { EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); - EASValsSetEdgeColor( gc.getElementEdgeColor() ); + EASValsSetColor(gc.getElementColor() ); + EASValsSetEdgeColor(gc.getElementEdgeColor() ); EASValsSetEdgeFlag(true); EASValsSetFillStyle(FILL_SOLID); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); @@ -835,9 +820,9 @@ DKTPlate :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) void -DKTPlate :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +DKTPlate::drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) { - WCRec p [ 3 ]; + WCRec p[ 3 ]; GraphicObj *go; double defScale = gc.getDefScale(); @@ -847,8 +832,8 @@ DKTPlate :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Unkno if ( this->giveMaterial()->isActivated(tStep) ) { EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); - EASValsSetEdgeColor( gc.getElementEdgeColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetEdgeColor(gc.getElementEdgeColor() ); EASValsSetEdgeFlag(true); EASValsSetFillStyle(FILL_SOLID); EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); @@ -870,13 +855,13 @@ DKTPlate :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Unkno void -DKTPlate :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) +DKTPlate::drawScalar(oofegGraphicContext &gc, TimeStep *tStep) { int i, indx, result = 0; - WCRec p [ 3 ]; + WCRec p[ 3 ]; GraphicObj *tr; FloatArray v1, v2, v3; - double s [ 3 ], defScale; + double s[ 3 ], defScale; if ( !gc.testElementGraphicActivity(this) ) { return; diff --git a/src/sm/Elements/Plates/dkt.h b/src/sm/Elements/Plates/dkt.h index 63388c991..5e4cf1009 100644 --- a/src/sm/Elements/Plates/dkt.h +++ b/src/sm/Elements/Plates/dkt.h @@ -35,9 +35,9 @@ #ifndef dkt_h #define dkt_h -#include "../sm/Elements/nlstructuralelement.h" -#include "../sm/CrossSections/layeredcrosssection.h" -#include "../sm/ErrorEstimators/zzerrorestimator.h" +#include "sm/Elements/structuralelement.h" +#include "sm/CrossSections/layeredcrosssection.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" #include "mathfem.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" @@ -64,7 +64,7 @@ class FEI2dTrLin; * Tasks: * - calculating its B,D,N matrices and dV. */ -class DKTPlate : public NLStructuralElement, +class DKTPlate : public StructuralElement, public LayeredCrossSectionInterface, public ZZNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface, public SPRNodalRecoveryModelInterface, public ZZErrorEstimatorInterface @@ -82,23 +82,22 @@ class DKTPlate : public NLStructuralElement, DKTPlate(int n, Domain *d); virtual ~DKTPlate() { } - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; - virtual MaterialMode giveMaterialMode() { return _2dPlate; } - virtual int testElementExtension(ElementExtension ext) { return ( ( ( ext == Element_EdgeLoadSupport ) || ( ext == Element_SurfaceLoadSupport ) ) ? 1 : 0 ); } + MaterialMode giveMaterialMode() override { return _2dPlate; } + int testElementExtension(ElementExtension ext) override { return ( ( ( ext == Element_EdgeLoadSupport ) || ( ext == Element_SurfaceLoadSupport ) ) ? 1 : 0 ); } + void computeEdgeNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) override; - virtual void computeEdgeNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray& lcoords); - protected: - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; virtual void giveNodeCoordinates(double &x1, double &x2, double &x3, @@ -110,65 +109,64 @@ class DKTPlate : public NLStructuralElement, * @name Edge load support */ //@{ - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; //@} /** * @name Surface load support */ //@{ - virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); - virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const; - virtual IntegrationRule *GetSurfaceIntegrationRule(int iSurf); - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf); - virtual int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override; + double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) override; + int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp) override; //@} public: // definition & identification - virtual const char *giveClassName() const { return "DKTPlate"; } - virtual const char *giveInputRecordName() const { return _IFT_DKTPlate_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "DKTPlate"; } + const char *giveInputRecordName() const override { return _IFT_DKTPlate_Name; } + void initializeFrom(InputRecord &ir) override; - virtual void computeGaussPoints(); - virtual int computeNumberOfDofs() { return 9; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + void computeGaussPoints() override; + int computeNumberOfDofs() override { return 9; } + void giveDofManDofIDMask(int inode, IntArray &) const override; - virtual void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp); + void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) override; - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane); - virtual double computeVolumeAround(GaussPoint *gp); + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override; + double computeVolumeAround(GaussPoint *gp) override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP() { return this->numberOfGaussPoints; } - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override { return this->numberOfGaussPoints; } + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; // layered cross section support functions - virtual void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep); + void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) override; void computeVertexBendingMoments(FloatMatrix &answer, TimeStep *tStep); // postproccess the shear forces on the element void computeShearForces(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif }; } // end namespace oofem diff --git a/src/sm/Elements/Plates/dkt3d.C b/src/sm/Elements/Plates/dkt3d.C index dfb50e3fe..6f56cad1d 100644 --- a/src/sm/Elements/Plates/dkt3d.C +++ b/src/sm/Elements/Plates/dkt3d.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Plates/dkt3d.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/Plates/dkt3d.h" +#include "sm/Materials/structuralms.h" #include "fei2dtrlin.h" #include "node.h" #include "load.h" @@ -47,43 +47,36 @@ namespace oofem { REGISTER_Element(DKTPlate3d); -DKTPlate3d :: DKTPlate3d(int n, Domain *aDomain) : DKTPlate(n, aDomain) -{ -} +DKTPlate3d::DKTPlate3d(int n, Domain *aDomain) : DKTPlate(n, aDomain) +{} void -DKTPlate3d :: giveLocalCoordinates(FloatArray &answer, FloatArray &global) -// Returns global coordinates given in global vector -// transformed into local coordinate system of the -// receiver +DKTPlate3d::giveLocalCoordinates(FloatArray &answer, const FloatArray &global) { - FloatArray offset; - // test the parametr if ( global.giveSize() != 3 ) { OOFEM_ERROR("cannot transform coordinates - size mismatch"); - exit(1); } // first ensure that receiver's GtoLRotationMatrix[3,3] is defined this->computeGtoLRotationMatrix(); - offset = global; - offset.subtract( * this->giveNode(1)->giveCoordinates() ); + FloatArray offset; + offset.beDifferenceOf( global, this->giveNode(1)->giveCoordinates() ); answer.beProductOf(GtoLRotationMatrix, offset); } void -DKTPlate3d :: giveNodeCoordinates(double &x1, double &x2, double &x3, - double &y1, double &y2, double &y3, - double &z1, double &z2, double &z3) +DKTPlate3d::giveNodeCoordinates(double &x1, double &x2, double &x3, + double &y1, double &y2, double &y3, + double &z1, double &z2, double &z3) { FloatArray nc1(3), nc2(3), nc3(3); - this->giveLocalCoordinates( nc1, * ( this->giveNode(1)->giveCoordinates() ) ); - this->giveLocalCoordinates( nc2, * ( this->giveNode(2)->giveCoordinates() ) ); - this->giveLocalCoordinates( nc3, * ( this->giveNode(3)->giveCoordinates() ) ); + this->giveLocalCoordinates(nc1, this->giveNode(1)->giveCoordinates() ); + this->giveLocalCoordinates(nc2, this->giveNode(2)->giveCoordinates() ); + this->giveLocalCoordinates(nc3, this->giveNode(3)->giveCoordinates() ); x1 = nc1.at(1); x2 = nc2.at(1); @@ -96,19 +89,18 @@ DKTPlate3d :: giveNodeCoordinates(double &x1, double &x2, double &x3, z1 = nc1.at(3); z2 = nc2.at(3); z3 = nc3.at(3); - } void -DKTPlate3d :: giveDofManDofIDMask(int inode, IntArray &answer) const +DKTPlate3d::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u, D_v, D_w, R_u, R_v, R_w}; + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; } const FloatMatrix * -DKTPlate3d :: computeGtoLRotationMatrix() +DKTPlate3d::computeGtoLRotationMatrix() // Returns the rotation matrix of the receiver of the size [3,3] // coords(local) = T * coords(global) // @@ -123,8 +115,8 @@ DKTPlate3d :: computeGtoLRotationMatrix() FloatArray e1, e2, e3, help; // compute e1' = [N2-N1] and help = [N3-N1] - e1.beDifferenceOf(*this->giveNode(2)->giveCoordinates(), *this->giveNode(1)->giveCoordinates()); - help.beDifferenceOf(*this->giveNode(3)->giveCoordinates(), *this->giveNode(1)->giveCoordinates()); + e1.beDifferenceOf( this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); + help.beDifferenceOf( this->giveNode(3)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); // let us normalize e1' e1.normalize(); @@ -147,12 +139,12 @@ DKTPlate3d :: computeGtoLRotationMatrix() } } - return &GtoLRotationMatrix; + return & GtoLRotationMatrix; } bool -DKTPlate3d :: computeGtoLRotationMatrix(FloatMatrix &answer) +DKTPlate3d::computeGtoLRotationMatrix(FloatMatrix &answer) // Returns the rotation matrix of the receiver of the size [9,18] // r(local) = T * r(global) // for one node (r written transposed): {w,r1,r2} = T * {u,v,w,r1,r2,r3} @@ -172,7 +164,7 @@ DKTPlate3d :: computeGtoLRotationMatrix(FloatMatrix &answer) } void -DKTPlate3d :: giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep) +DKTPlate3d::giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep) // returns characteristic tensor of the receiver at given gp and tStep // strain vector = (Kappa_x, Kappa_y, Kappa_xy, Gamma_zx, Gamma_zy) { @@ -220,7 +212,7 @@ DKTPlate3d :: giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, Gau } if ( ( type == GlobalForceTensor ) || ( type == GlobalMomentTensor ) || - ( type == GlobalStrainTensor ) || ( type == GlobalCurvatureTensor ) ) { + ( type == GlobalStrainTensor ) || ( type == GlobalCurvatureTensor ) ) { this->computeGtoLRotationMatrix(); answer.rotatedWith(GtoLRotationMatrix); } @@ -228,7 +220,7 @@ DKTPlate3d :: giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, Gau int -DKTPlate3d :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +DKTPlate3d::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { FloatMatrix globTensor; CharTensor cht; @@ -247,9 +239,9 @@ DKTPlate3d :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType answer.at(1) = globTensor.at(1, 1); //xx answer.at(2) = globTensor.at(2, 2); //yy answer.at(3) = globTensor.at(3, 3); //zz - answer.at(4) = 2*globTensor.at(2, 3); //yz - answer.at(5) = 2*globTensor.at(1, 3); //xz - answer.at(6) = 2*globTensor.at(1, 2); //xy + answer.at(4) = 2 * globTensor.at(2, 3); //yz + answer.at(5) = 2 * globTensor.at(1, 3); //xz + answer.at(6) = 2 * globTensor.at(1, 2); //xy return 1; } else if ( type == IST_ShellMomentTensor || type == IST_ShellForceTensor ) { @@ -270,12 +262,12 @@ DKTPlate3d :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType return 1; } else { - return NLStructuralElement :: giveIPValue(answer, gp, type, tStep); + return StructuralElement::giveIPValue(answer, gp, type, tStep); } } int -DKTPlate3d :: computeLoadGToLRotationMtrx(FloatMatrix &answer) +DKTPlate3d::computeLoadGToLRotationMtrx(FloatMatrix &answer) // Returns the rotation matrix of the receiver of the size [6,6] // f(local) = T * f(global) { @@ -294,7 +286,7 @@ DKTPlate3d :: computeLoadGToLRotationMtrx(FloatMatrix &answer) } void -DKTPlate3d :: computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) +DKTPlate3d::computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) { FloatMatrix ne; this->computeNmatrixAt(sgp->giveNaturalCoordinates(), ne); @@ -316,7 +308,7 @@ DKTPlate3d :: computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint } void -DKTPlate3d :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +DKTPlate3d::giveSurfaceDofMapping(IntArray &answer, int iSurf) const { answer.resize(18); answer.zero(); @@ -337,58 +329,57 @@ DKTPlate3d :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const } } -IntegrationRule * -DKTPlate3d :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, approxOrder); - iRule->SetUpPointsOnTriangle(npoints, _Unknown); - return iRule; -} double -DKTPlate3d :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) +DKTPlate3d::computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { return this->computeVolumeAround(gp); } int -DKTPlate3d :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) +DKTPlate3d::computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) { return 0; } void -DKTPlate3d :: printOutputAt(FILE *file, TimeStep *tStep) +DKTPlate3d::printOutputAt(FILE *file, TimeStep *tStep) // Performs end-of-step operations. { FloatArray v; - fprintf( file, "element %d (%8d) :\n", this->giveLabel(), this->giveNumber() ); + fprintf(file, "element %d (%8d) :\n", this->giveLabel(), this->giveNumber() ); - for ( int i = 0; i < (int)integrationRulesArray.size(); i++ ) { - for ( GaussPoint *gp: *integrationRulesArray [ i ] ) { - - fprintf( file, " GP %2d.%-2d :", i + 1, gp->giveNumber() ); + for ( int i = 0; i < ( int ) integrationRulesArray.size(); i++ ) { + for ( GaussPoint *gp: * integrationRulesArray [ i ] ) { + fprintf(file, " GP %2d.%-2d :", i + 1, gp->giveNumber() ); this->giveIPValue(v, gp, IST_ShellStrainTensor, tStep); fprintf(file, " strains "); // eps_x, eps_y, eps_z, eps_yz, eps_xz, eps_xy (global) - for ( auto &val : v ) fprintf(file, " %.4e", val); + for ( auto &val : v ) { + fprintf(file, " %.4e", val); + } this->giveIPValue(v, gp, IST_CurvatureTensor, tStep); fprintf(file, "\n curvatures "); - for ( auto &val : v ) fprintf(file, " %.4e", val); + for ( auto &val : v ) { + fprintf(file, " %.4e", val); + } // Forces - Moments this->giveIPValue(v, gp, IST_ShellForceTensor, tStep); fprintf(file, "\n stresses "); - for ( auto &val : v ) fprintf(file, " %.4e", val); + for ( auto &val : v ) { + fprintf(file, " %.4e", val); + } this->giveIPValue(v, gp, IST_ShellMomentTensor, tStep); fprintf(file, "\n moments "); - for ( auto &val : v ) fprintf(file, " %.4e", val); + for ( auto &val : v ) { + fprintf(file, " %.4e", val); + } fprintf(file, "\n"); } @@ -397,7 +388,7 @@ DKTPlate3d :: printOutputAt(FILE *file, TimeStep *tStep) void -DKTPlate3d :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +DKTPlate3d::giveEdgeDofMapping(IntArray &answer, int iEdge) const { /* * provides dof mapping of local edge dofs (only nonzero are taken into account) @@ -433,15 +424,15 @@ DKTPlate3d :: giveEdgeDofMapping(IntArray &answer, int iEdge) const } double -DKTPlate3d :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +DKTPlate3d::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { - double detJ = this->interp_lin.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - return detJ *gp->giveWeight(); + double detJ = this->interp_lin.edgeGiveTransformationJacobian(iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + return detJ * gp->giveWeight(); } int -DKTPlate3d :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +DKTPlate3d::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -450,26 +441,22 @@ DKTPlate3d :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gau // // i.e. f(element local) = T * f(edge local) // - double dx, dy, length; - IntArray edgeNodes; - Node *nodeA, *nodeB; - - answer.resize(3, 3); - answer.zero(); - this->interp_lin.computeLocalEdgeMapping(edgeNodes, iEdge); + const auto &edgeNodes = this->interp_lin.computeLocalEdgeMapping(iEdge); - nodeA = this->giveNode( edgeNodes.at(1) ); - nodeB = this->giveNode( edgeNodes.at(2) ); + auto nodeA = this->giveNode(edgeNodes.at(1) ); + auto nodeB = this->giveNode(edgeNodes.at(2) ); FloatArray cb(3), ca(3); - this->giveLocalCoordinates (ca, * (nodeA->giveCoordinates() ) ); - this->giveLocalCoordinates (cb, * (nodeB->giveCoordinates() ) ); + this->giveLocalCoordinates( ca, nodeA->giveCoordinates() ); + this->giveLocalCoordinates( cb, nodeB->giveCoordinates() ); - dx = cb.at(1) - ca.at(1); - dy = cb.at(2) - ca.at(2); - length = sqrt(dx * dx + dy * dy); + double dx = cb.at(1) - ca.at(1); + double dy = cb.at(2) - ca.at(2); + double length = sqrt(dx * dx + dy * dy); + answer.resize(3, 3); + answer.zero(); answer.at(1, 1) = 1.0; answer.at(2, 2) = dx / length; answer.at(2, 3) = -dy / length; @@ -480,48 +467,48 @@ DKTPlate3d :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gau } bool -DKTPlate3d :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) +DKTPlate3d::computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) //converts global coordinates to local planar area coordinates, //does not return a coordinate in the thickness direction, but //does check that the point is in the element thickness { // rotate the input point Coordinate System into the element CS FloatArray inputCoords_ElCS; - std::vector< FloatArray > lc(3); + std::vector< FloatArray >lc(3); FloatArray llc; - this->giveLocalCoordinates( inputCoords_ElCS, const_cast< FloatArray & >(coords) ); + this->giveLocalCoordinates(inputCoords_ElCS, coords); for ( int _i = 0; _i < 3; _i++ ) { - this->giveLocalCoordinates( lc [ _i ], * this->giveNode(_i + 1)->giveCoordinates() ); + this->giveLocalCoordinates(lc [ _i ], this->giveNode(_i + 1)->giveCoordinates() ); } FEI2dTrLin _interp(1, 2); - bool inplane = _interp.global2local(llc, inputCoords_ElCS, FEIVertexListGeometryWrapper(lc)) > 0; + bool inplane = _interp.global2local( llc, inputCoords_ElCS, FEIVertexListGeometryWrapper(lc) ) > 0; answer.resize(2); answer.at(1) = inputCoords_ElCS.at(1); answer.at(2) = inputCoords_ElCS.at(2); GaussPoint _gp(NULL, 1, answer, 2.0, _2dPlate); // now check if the third local coordinate is within the thickness of element - bool outofplane = ( fabs( inputCoords_ElCS.at(3) ) <= this->giveCrossSection()->give(CS_Thickness, & _gp) / 2. ); + bool outofplane = ( fabs(inputCoords_ElCS.at(3) ) <= this->giveCrossSection()->give(CS_Thickness, & _gp) / 2. ); return inplane && outofplane; } int -DKTPlate3d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +DKTPlate3d::computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { double l1 = lcoords.at(1); double l2 = lcoords.at(2); double l3 = 1. - l2 - l1; - + answer.resize(3); for ( int _i = 1; _i <= 3; _i++ ) { - answer.at(_i) = l1 * this->giveNode(1)->giveCoordinate(_i) + l2 *this->giveNode(2)->giveCoordinate(_i) + l3 *this->giveNode(3)->giveCoordinate(_i); + answer.at(_i) = l1 * this->giveNode(1)->giveCoordinate(_i) + l2 * this->giveNode(2)->giveCoordinate(_i) + l3 * this->giveNode(3)->giveCoordinate(_i); } return true; } void -DKTPlate3d :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) +DKTPlate3d::computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) // Computes numerically the load vector of the receiver due to the body loads, at tStep. // load is assumed to be in global cs. // load vector is then transformed to coordinate system in each node. diff --git a/src/sm/Elements/Plates/dkt3d.h b/src/sm/Elements/Plates/dkt3d.h index cd516360f..72090e079 100644 --- a/src/sm/Elements/Plates/dkt3d.h +++ b/src/sm/Elements/Plates/dkt3d.h @@ -81,59 +81,58 @@ class DKTPlate3d : public DKTPlate virtual ~DKTPlate3d() {} protected: - void giveLocalCoordinates(FloatArray &answer, FloatArray &global); - virtual void giveNodeCoordinates(double &x1, double &x2, double &x3, - double &y1, double &y2, double &y3, - double &z1, double &z2, double &z3); + void giveLocalCoordinates(FloatArray &answer, const FloatArray &global); + void giveNodeCoordinates(double &x1, double &x2, double &x3, + double &y1, double &y2, double &y3, + double &z1, double &z2, double &z3) override; void giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode); + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) override; /** * @name Edge load support */ //@{ - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; //@} /** * @name Surface load support */ //@{ - virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); - virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const; - virtual IntegrationRule *GetSurfaceIntegrationRule(int iSurf); - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf); - virtual int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override; + double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) override; + int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp) override; //@} public: // definition & identification - virtual const char *giveClassName() const { return "DktPlate3d"; } - virtual const char *giveInputRecordName() const { return _IFT_DKTPlate3d_Name; } + const char *giveClassName() const override { return "DktPlate3d"; } + const char *giveInputRecordName() const override { return _IFT_DKTPlate3d_Name; } - virtual int computeNumberOfDofs() { return 9; } - virtual int computeNumberOfGlobalDofs() { return 18; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int computeNumberOfDofs() override { return 9; } + int computeNumberOfGlobalDofs() override { return 18; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual const FloatMatrix *computeGtoLRotationMatrix(); - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + const FloatMatrix *computeGtoLRotationMatrix(); + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords); - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; - virtual int giveLocalCoordinateSystem(FloatMatrix &answer) + int giveLocalCoordinateSystem(FloatMatrix &answer) override { OOFEM_ERROR("calling of this function id not allowed"); return 0; } - virtual int testElementExtension(ElementExtension ext) + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; }; } // end namespace oofem #endif // dkt3d_h diff --git a/src/sm/Elements/Plates/qdkt.C b/src/sm/Elements/Plates/qdkt.C index 5fe5e6790..f8ded45a4 100644 --- a/src/sm/Elements/Plates/qdkt.C +++ b/src/sm/Elements/Plates/qdkt.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Plates/qdkt.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/Plates/qdkt.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei2dquadlin.h" #include "node.h" #include "material.h" @@ -55,10 +55,10 @@ namespace oofem { REGISTER_Element(QDKTPlate); -FEI2dQuadLin QDKTPlate :: interp_lin(1, 2); +FEI2dQuadLin QDKTPlate::interp_lin(1, 2); -QDKTPlate :: QDKTPlate(int n, Domain *aDomain) : - NLStructuralElement(n, aDomain), +QDKTPlate::QDKTPlate(int n, Domain *aDomain) : + StructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this), SPRNodalRecoveryModelInterface(), ZZErrorEstimatorInterface(this) @@ -69,221 +69,221 @@ QDKTPlate :: QDKTPlate(int n, Domain *aDomain) : FEInterpolation * -QDKTPlate :: giveInterpolation() const { return & interp_lin; } +QDKTPlate::giveInterpolation() const { return & interp_lin; } FEInterpolation * -QDKTPlate :: giveInterpolation(DofIDItem id) const +QDKTPlate::giveInterpolation(DofIDItem id) const { return & interp_lin; } void -QDKTPlate :: computeGaussPoints() +QDKTPlate::computeGaussPoints() // Sets up the array containing the four Gauss points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 5) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 5); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } void -QDKTPlate :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +QDKTPlate::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the [5x12] strain-displacement matrix {B} of the receiver, // evaluated at gp. { // get node coordinates - double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4; - this->giveNodeCoordinates(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4); + double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4; + this->giveNodeCoordinates(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4); // get gp coordinates double ksi = gp->giveNaturalCoordinate(1); double eta = gp->giveNaturalCoordinate(2); // geometrical characteristics of element sides - double dx4 = x2-x1; - double dy4 = y2-y1; - double l4 = sqrt(dx4*dx4+dy4*dy4); - - double dx5 = x3-x2; - double dy5 = y3-y2; - double l5 = sqrt(dx5*dx5+dy5*dy5); - - double dx6 = x4-x3; - double dy6 = y4-y3; - double l6 = sqrt(dx6*dx6+dy6*dy6); - - double dx7 = x1-x4; - double dy7 = y1-y4; - double l7 = sqrt(dx7*dx7+dy7*dy7); - - double c4 = dy4/l4; - double s4 = -dx4/l4; - - double c5 = dy5/l5; - double s5 = -dx5/l5; - - double c6 = dy6/l6; - double s6 = -dx6/l6; - - double c7 = dy7/l7; - double s7 = -dx7/l7; + double dx4 = x2 - x1; + double dy4 = y2 - y1; + double l4 = sqrt(dx4 * dx4 + dy4 * dy4); + + double dx5 = x3 - x2; + double dy5 = y3 - y2; + double l5 = sqrt(dx5 * dx5 + dy5 * dy5); + + double dx6 = x4 - x3; + double dy6 = y4 - y3; + double l6 = sqrt(dx6 * dx6 + dy6 * dy6); + + double dx7 = x1 - x4; + double dy7 = y1 - y4; + double l7 = sqrt(dx7 * dx7 + dy7 * dy7); + + double c4 = dy4 / l4; + double s4 = -dx4 / l4; + + double c5 = dy5 / l5; + double s5 = -dx5 / l5; + + double c6 = dy6 / l6; + double s6 = -dx6 / l6; + + double c7 = dy7 / l7; + double s7 = -dx7 / l7; // transformation matrix from vertex dofs (w,fi_x, fi_y) to quadratic rotation DOFs - double T101 = -3./2./l4*c4; - double T102 = -1./4.*c4*c4+1./2.*s4*s4; - double T103 = -1./4.*c4*s4-1./2.*c4*s4; - double T104 = 3./2./l4*c4; - double T105 = -1./4.*c4*c4+1./2.*s4*s4; - double T106 = -1./4.*c4*s4-1./2.*c4*s4; - - double T201 = -3./2./l4*s4; - double T202 = -1./4.*c4*s4-1./2.*c4*s4; - double T203 = -1./4.*s4*s4+1./2.*c4*c4; - double T204 = 3./2./l4*s4; - double T205 = -1./4.*c4*s4-1./2.*c4*s4; - double T206 = -1./4.*s4*s4+1./2.*c4*c4; - - double T304 = -3./2./l5*c5; - double T305 = -1./4.*c5*c5+1./2.*s5*s5; - double T306 = -1./4.*c5*s5-1./2.*c5*s5; - double T307 = 3./2./l5*c5; - double T308 = -1./4.*c5*c5+1./2.*s5*s5; - double T309 = -1./4.*c5*s5-1./2.*c5*s5; - - double T404 = -3./2./l5*s5; - double T405 = -1./4.*c5*s5-1./2.*c5*s5; - double T406 = -1./4.*s5*s5+1./2.*c5*c5; - double T407 = 3./2./l5*s5; - double T408 = -1./4.*c5*s5-1./2.*c5*s5; - double T409 = -1./4.*s5*s5+1./2.*c5*c5; - - double T507 = -3./2./l6*c6; - double T508 = -1./4.*c6*c6+1./2.*s6*s6; - double T509 = -1./4.*c6*s6-1./2.*c6*s6; - double T510 = 3./2./l6*c6; - double T511 = -1./4.*c6*c6+1./2.*s6*s6; - double T512 = -1./4.*c6*s6-1./2.*c6*s6; - - double T607 = -3./2./l6*s6; - double T608 = -1./4.*c6*s6-1./2.*c6*s6; - double T609 = -1./4.*s6*s6+1./2.*c6*c6; - double T610 = 3./2./l6*s6; - double T611 = -1./4.*c6*s6-1./2.*c6*s6; - double T612 = -1./4.*s6*s6+1./2.*c6*c6; - - double T701 = 3./2./l7*c7; - double T702 = -1./4.*c7*c7+1./2.*s7*s7; - double T703 = -1./4.*c7*s7-1./2.*c7*s7; - double T710 = -3./2./l7*c7; - double T711 = -1./4.*c7*c7+1./2.*s7*s7; - double T712 = -1./4.*c7*s7-1./2.*c7*s7; - - double T801 = 3./2./l7*s7; - double T802 = -1./4.*c7*s7-1./2.*c7*s7; - double T803 = -1./4.*s7*s7+1./2.*c7*c7; - double T810 = -3./2./l7*s7; - double T811 = -1./4.*c7*s7-1./2.*c7*s7; - double T812 = -1./4.*s7*s7+1./2.*c7*c7; + double T101 = -3. / 2. / l4 * c4; + double T102 = -1. / 4. * c4 * c4 + 1. / 2. * s4 * s4; + double T103 = -1. / 4. * c4 * s4 - 1. / 2. * c4 * s4; + double T104 = 3. / 2. / l4 * c4; + double T105 = -1. / 4. * c4 * c4 + 1. / 2. * s4 * s4; + double T106 = -1. / 4. * c4 * s4 - 1. / 2. * c4 * s4; + + double T201 = -3. / 2. / l4 * s4; + double T202 = -1. / 4. * c4 * s4 - 1. / 2. * c4 * s4; + double T203 = -1. / 4. * s4 * s4 + 1. / 2. * c4 * c4; + double T204 = 3. / 2. / l4 * s4; + double T205 = -1. / 4. * c4 * s4 - 1. / 2. * c4 * s4; + double T206 = -1. / 4. * s4 * s4 + 1. / 2. * c4 * c4; + + double T304 = -3. / 2. / l5 * c5; + double T305 = -1. / 4. * c5 * c5 + 1. / 2. * s5 * s5; + double T306 = -1. / 4. * c5 * s5 - 1. / 2. * c5 * s5; + double T307 = 3. / 2. / l5 * c5; + double T308 = -1. / 4. * c5 * c5 + 1. / 2. * s5 * s5; + double T309 = -1. / 4. * c5 * s5 - 1. / 2. * c5 * s5; + + double T404 = -3. / 2. / l5 * s5; + double T405 = -1. / 4. * c5 * s5 - 1. / 2. * c5 * s5; + double T406 = -1. / 4. * s5 * s5 + 1. / 2. * c5 * c5; + double T407 = 3. / 2. / l5 * s5; + double T408 = -1. / 4. * c5 * s5 - 1. / 2. * c5 * s5; + double T409 = -1. / 4. * s5 * s5 + 1. / 2. * c5 * c5; + + double T507 = -3. / 2. / l6 * c6; + double T508 = -1. / 4. * c6 * c6 + 1. / 2. * s6 * s6; + double T509 = -1. / 4. * c6 * s6 - 1. / 2. * c6 * s6; + double T510 = 3. / 2. / l6 * c6; + double T511 = -1. / 4. * c6 * c6 + 1. / 2. * s6 * s6; + double T512 = -1. / 4. * c6 * s6 - 1. / 2. * c6 * s6; + + double T607 = -3. / 2. / l6 * s6; + double T608 = -1. / 4. * c6 * s6 - 1. / 2. * c6 * s6; + double T609 = -1. / 4. * s6 * s6 + 1. / 2. * c6 * c6; + double T610 = 3. / 2. / l6 * s6; + double T611 = -1. / 4. * c6 * s6 - 1. / 2. * c6 * s6; + double T612 = -1. / 4. * s6 * s6 + 1. / 2. * c6 * c6; + + double T701 = 3. / 2. / l7 * c7; + double T702 = -1. / 4. * c7 * c7 + 1. / 2. * s7 * s7; + double T703 = -1. / 4. * c7 * s7 - 1. / 2. * c7 * s7; + double T710 = -3. / 2. / l7 * c7; + double T711 = -1. / 4. * c7 * c7 + 1. / 2. * s7 * s7; + double T712 = -1. / 4. * c7 * s7 - 1. / 2. * c7 * s7; + + double T801 = 3. / 2. / l7 * s7; + double T802 = -1. / 4. * c7 * s7 - 1. / 2. * c7 * s7; + double T803 = -1. / 4. * s7 * s7 + 1. / 2. * c7 * c7; + double T810 = -3. / 2. / l7 * s7; + double T811 = -1. / 4. * c7 * s7 - 1. / 2. * c7 * s7; + double T812 = -1. / 4. * s7 * s7 + 1. / 2. * c7 * c7; // derivatives of quadratic interpolation functions // we do not have "midside" nodes -> explicit here - double N1dk = 0.25*(2.0*ksi+eta)*(1.0+eta); - double N2dk = 0.25*(2.0*ksi-eta)*(1.0+eta); - double N3dk = 0.25*(2.0*ksi+eta)*(1.0-eta); - double N4dk = 0.25*(2.0*ksi-eta)*(1.0-eta); - double N7dk = -ksi*(1.0-eta); - double N8dk = 0.5*(1.0-eta*eta); - double N5dk = -ksi*(1.0+eta); - double N6dk = -0.5*(1.0-eta*eta); - - double N3de = 0.25*(2.0*eta+ksi)*(1.0-ksi); - double N4de = 0.25*(2.0*eta-ksi)*(1.0+ksi); - double N1de = 0.25*(2.0*eta+ksi)*(1.0+ksi); - double N2de = 0.25*(2.0*eta-ksi)*(1.0-ksi); - double N7de = -0.5*(1.0-ksi*ksi); - double N8de = -eta*(1.0+ksi); - double N5de = 0.5*(1.0-ksi*ksi); - double N6de = -eta*(1.0-ksi); - - double detJ = 1./8.*((y4-y2)*(x3-x1)-(y3-y1)*(x4-x2))+ - ksi/8*((y3-y4)*(x2-x1)-(y2-y1)*(x3-x4))+ - eta/8*((y4-y1)*(x3-x2)-(y3-y2)*(x4-x1)); - - double dxdk = -1.0/detJ * ((y3-y2)+(y4-y1+ksi*(y1-y2+y3-y4)))/4.0; - double dxde = 1.0/detJ * ((y2-y1)+(y3-y4+eta*(y1-y2+y3-y4)))/4.0; - double dydk = 1.0/detJ * ((x3-x2)+(x4-x1+ksi*(x1-x2+x3-x4)))/4.0; - double dyde = -1.0/detJ * ((x2-x1)+(x3-x4+eta*(x1-x2+x3-x4)))/4.0; - - double dN102 = N1dk*dxdk+N1de*dxde; - double dN104 = N2dk*dxdk+N2de*dxde; - double dN106 = N3dk*dxdk+N3de*dxde; - double dN108 = N4dk*dxdk+N4de*dxde; - double dN110 = N5dk*dxdk+N5de*dxde; - double dN112 = N6dk*dxdk+N6de*dxde; - double dN114 = N7dk*dxdk+N7de*dxde; - double dN116 = N8dk*dxdk+N8de*dxde; - - double dN201 = -N1dk*dydk-N1de*dyde; - double dN203 = -N2dk*dydk-N2de*dyde; - double dN205 = -N3dk*dydk-N3de*dyde; - double dN207 = -N4dk*dydk-N4de*dyde; - double dN209 = -N5dk*dydk-N5de*dyde; - double dN211 = -N6dk*dydk-N6de*dyde; - double dN213 = -N7dk*dydk-N7de*dyde; - double dN215 = -N8dk*dydk-N8de*dyde; + double N1dk = 0.25 * ( 2.0 * ksi + eta ) * ( 1.0 + eta ); + double N2dk = 0.25 * ( 2.0 * ksi - eta ) * ( 1.0 + eta ); + double N3dk = 0.25 * ( 2.0 * ksi + eta ) * ( 1.0 - eta ); + double N4dk = 0.25 * ( 2.0 * ksi - eta ) * ( 1.0 - eta ); + double N7dk = -ksi * ( 1.0 - eta ); + double N8dk = 0.5 * ( 1.0 - eta * eta ); + double N5dk = -ksi * ( 1.0 + eta ); + double N6dk = -0.5 * ( 1.0 - eta * eta ); + + double N3de = 0.25 * ( 2.0 * eta + ksi ) * ( 1.0 - ksi ); + double N4de = 0.25 * ( 2.0 * eta - ksi ) * ( 1.0 + ksi ); + double N1de = 0.25 * ( 2.0 * eta + ksi ) * ( 1.0 + ksi ); + double N2de = 0.25 * ( 2.0 * eta - ksi ) * ( 1.0 - ksi ); + double N7de = -0.5 * ( 1.0 - ksi * ksi ); + double N8de = -eta * ( 1.0 + ksi ); + double N5de = 0.5 * ( 1.0 - ksi * ksi ); + double N6de = -eta * ( 1.0 - ksi ); + + double detJ = 1. / 8. * ( ( y4 - y2 ) * ( x3 - x1 ) - ( y3 - y1 ) * ( x4 - x2 ) ) + + ksi / 8 * ( ( y3 - y4 ) * ( x2 - x1 ) - ( y2 - y1 ) * ( x3 - x4 ) ) + + eta / 8 * ( ( y4 - y1 ) * ( x3 - x2 ) - ( y3 - y2 ) * ( x4 - x1 ) ); + + double dxdk = -1.0 / detJ * ( ( y3 - y2 ) + ( y4 - y1 + ksi * ( y1 - y2 + y3 - y4 ) ) ) / 4.0; + double dxde = 1.0 / detJ * ( ( y2 - y1 ) + ( y3 - y4 + eta * ( y1 - y2 + y3 - y4 ) ) ) / 4.0; + double dydk = 1.0 / detJ * ( ( x3 - x2 ) + ( x4 - x1 + ksi * ( x1 - x2 + x3 - x4 ) ) ) / 4.0; + double dyde = -1.0 / detJ * ( ( x2 - x1 ) + ( x3 - x4 + eta * ( x1 - x2 + x3 - x4 ) ) ) / 4.0; + + double dN102 = N1dk * dxdk + N1de * dxde; + double dN104 = N2dk * dxdk + N2de * dxde; + double dN106 = N3dk * dxdk + N3de * dxde; + double dN108 = N4dk * dxdk + N4de * dxde; + double dN110 = N5dk * dxdk + N5de * dxde; + double dN112 = N6dk * dxdk + N6de * dxde; + double dN114 = N7dk * dxdk + N7de * dxde; + double dN116 = N8dk * dxdk + N8de * dxde; + + double dN201 = -N1dk * dydk - N1de * dyde; + double dN203 = -N2dk * dydk - N2de * dyde; + double dN205 = -N3dk * dydk - N3de * dyde; + double dN207 = -N4dk * dydk - N4de * dyde; + double dN209 = -N5dk * dydk - N5de * dyde; + double dN211 = -N6dk * dydk - N6de * dyde; + double dN213 = -N7dk * dydk - N7de * dyde; + double dN215 = -N8dk * dydk - N8de * dyde; answer.resize(5, 12); answer.zero(); - - answer.at(1,1) = T201*dN110 + T801*dN116; - answer.at(1,2) = T202*dN110 + T802*dN116; - answer.at(1,3) = dN102 + T203*dN110 + T803*dN116; - answer.at(1,4) = T204*dN110 + T404*dN112; - answer.at(1,5) = T205*dN110 + T405*dN112; - answer.at(1,6) = dN104 + T206*dN110 + T406*dN112; - answer.at(1,7) = T407*dN112 + T607*dN114; - answer.at(1,8) = T408*dN112 + T608*dN114; - answer.at(1,9) = dN106 + T409*dN112 + T609*dN114; - answer.at(1,10)= T610*dN114 + T810*dN116; - answer.at(1,11)= T611*dN114 + T811*dN116; - answer.at(1,12)= dN108 + T612*dN114 + T812*dN116; - - answer.at(2,1) = T101*dN209 + T701*dN215; - answer.at(2,2) = dN201 + T102*dN209 + T702*dN215; - answer.at(2,3) = T103*dN209 + T703*dN215; - answer.at(2,4) = T104*dN209 + T304*dN211; - answer.at(2,5) = dN203 + T105*dN209 + T305*dN211; - answer.at(2,6) = T106*dN209 + T306*dN211; - answer.at(2,7) = T307*dN211 + T507*dN213; - answer.at(2,8) = dN205 + T308*dN211 + T508*dN213; - answer.at(2,9) = T309*dN211 + T509*dN213; - answer.at(2,10)= T510*dN213 + T710*dN215; - answer.at(2,11)= dN207 + T511*dN213 + T711*dN215; - answer.at(2,12)= T512*dN213 + T712*dN215; - - answer.at(3,1) = - T101*dN110 - T201*dN209 - T701*dN116 - T801*dN215; - answer.at(3,2) = - dN102 - T102*dN110 - T202*dN209 - T702*dN116 - T802*dN215; - answer.at(3,3) = - dN201 - T103*dN110 - T203*dN209 - T703*dN116 - T803*dN215; - answer.at(3,4) = - T104*dN110 - T204*dN209 - T304*dN112 - T404*dN211; - answer.at(3,5) = - dN104 - T105*dN110 - T205*dN209 - T305*dN112 - T405*dN211; - answer.at(3,6) = - dN203 - T106*dN110 - T206*dN209 - T306*dN112 - T406*dN211; - answer.at(3,7) = - T307*dN112 - T407*dN211 - T507*dN114 - T607*dN213; - answer.at(3,8) = - dN106 - T308*dN112 - T408*dN211 - T508*dN114 - T608*dN213; - answer.at(3,9) = - dN205 - T309*dN112 - T409*dN211 - T509*dN114 - T609*dN213; - answer.at(3,10)= - T510*dN114 - T610*dN213 - T710*dN116 - T810*dN215; - answer.at(3,11)= - dN108 - T511*dN114 - T611*dN213 - T711*dN116 - T811*dN215; - answer.at(3,12)= - dN207 - T512*dN114 - T612*dN213 - T712*dN116 - T812*dN215; + + answer.at(1, 1) = T201 * dN110 + T801 * dN116; + answer.at(1, 2) = T202 * dN110 + T802 * dN116; + answer.at(1, 3) = dN102 + T203 * dN110 + T803 * dN116; + answer.at(1, 4) = T204 * dN110 + T404 * dN112; + answer.at(1, 5) = T205 * dN110 + T405 * dN112; + answer.at(1, 6) = dN104 + T206 * dN110 + T406 * dN112; + answer.at(1, 7) = T407 * dN112 + T607 * dN114; + answer.at(1, 8) = T408 * dN112 + T608 * dN114; + answer.at(1, 9) = dN106 + T409 * dN112 + T609 * dN114; + answer.at(1, 10) = T610 * dN114 + T810 * dN116; + answer.at(1, 11) = T611 * dN114 + T811 * dN116; + answer.at(1, 12) = dN108 + T612 * dN114 + T812 * dN116; + + answer.at(2, 1) = T101 * dN209 + T701 * dN215; + answer.at(2, 2) = dN201 + T102 * dN209 + T702 * dN215; + answer.at(2, 3) = T103 * dN209 + T703 * dN215; + answer.at(2, 4) = T104 * dN209 + T304 * dN211; + answer.at(2, 5) = dN203 + T105 * dN209 + T305 * dN211; + answer.at(2, 6) = T106 * dN209 + T306 * dN211; + answer.at(2, 7) = T307 * dN211 + T507 * dN213; + answer.at(2, 8) = dN205 + T308 * dN211 + T508 * dN213; + answer.at(2, 9) = T309 * dN211 + T509 * dN213; + answer.at(2, 10) = T510 * dN213 + T710 * dN215; + answer.at(2, 11) = dN207 + T511 * dN213 + T711 * dN215; + answer.at(2, 12) = T512 * dN213 + T712 * dN215; + + answer.at(3, 1) = -T101 * dN110 - T201 * dN209 - T701 * dN116 - T801 * dN215; + answer.at(3, 2) = -dN102 - T102 * dN110 - T202 * dN209 - T702 * dN116 - T802 * dN215; + answer.at(3, 3) = -dN201 - T103 * dN110 - T203 * dN209 - T703 * dN116 - T803 * dN215; + answer.at(3, 4) = -T104 * dN110 - T204 * dN209 - T304 * dN112 - T404 * dN211; + answer.at(3, 5) = -dN104 - T105 * dN110 - T205 * dN209 - T305 * dN112 - T405 * dN211; + answer.at(3, 6) = -dN203 - T106 * dN110 - T206 * dN209 - T306 * dN112 - T406 * dN211; + answer.at(3, 7) = -T307 * dN112 - T407 * dN211 - T507 * dN114 - T607 * dN213; + answer.at(3, 8) = -dN106 - T308 * dN112 - T408 * dN211 - T508 * dN114 - T608 * dN213; + answer.at(3, 9) = -dN205 - T309 * dN112 - T409 * dN211 - T509 * dN114 - T609 * dN213; + answer.at(3, 10) = -T510 * dN114 - T610 * dN213 - T710 * dN116 - T810 * dN215; + answer.at(3, 11) = -dN108 - T511 * dN114 - T611 * dN213 - T711 * dN116 - T811 * dN215; + answer.at(3, 12) = -dN207 - T512 * dN114 - T612 * dN213 - T712 * dN116 - T812 * dN215; // Note: no shear strains, no shear forces => the 4th and 5th rows are zero } void -QDKTPlate :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +QDKTPlate::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the [3x9] displacement interpolation matrix {N} of the receiver, // evaluated at gp. // Note: this interpolation is not available, as the deflection is cubic along the edges, @@ -293,77 +293,74 @@ QDKTPlate :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) { FloatArray N; - giveInterpolation()->evalN( N, iLocCoord, FEIElementGeometryWrapper(this) ); + giveInterpolation()->evalN(N, iLocCoord, FEIElementGeometryWrapper(this) ); answer.beNMatrixOf(N, 3); - } void -QDKTPlate :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +QDKTPlate::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Plate(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Plate(strain, gp, tStep); } void -QDKTPlate :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +QDKTPlate::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give2dPlateStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give2dPlateStiffMtrx(rMode, gp, tStep); } void -QDKTPlate :: giveNodeCoordinates(double &x1, double &x2, double &x3, double &x4, - double &y1, double &y2, double &y3, double &y4, - double &z1, double &z2, double &z3, double &z4) +QDKTPlate::giveNodeCoordinates(double &x1, double &x2, double &x3, double &x4, + double &y1, double &y2, double &y3, double &y4, + double &z1, double &z2, double &z3, double &z4) { - FloatArray *nc1, *nc2, *nc3, *nc4; - nc1 = this->giveNode(1)->giveCoordinates(); - nc2 = this->giveNode(2)->giveCoordinates(); - nc3 = this->giveNode(3)->giveCoordinates(); - nc4 = this->giveNode(4)->giveCoordinates(); + const auto &nc1 = this->giveNode(1)->giveCoordinates(); + const auto &nc2 = this->giveNode(2)->giveCoordinates(); + const auto &nc3 = this->giveNode(3)->giveCoordinates(); + const auto &nc4 = this->giveNode(4)->giveCoordinates(); - x1 = nc1->at(1); - x2 = nc2->at(1); - x3 = nc3->at(1); - x4 = nc4->at(1); + x1 = nc1.at(1); + x2 = nc2.at(1); + x3 = nc3.at(1); + x4 = nc4.at(1); - y1 = nc1->at(2); - y2 = nc2->at(2); - y3 = nc3->at(2); - y4 = nc4->at(2); + y1 = nc1.at(2); + y2 = nc2.at(2); + y3 = nc3.at(2); + y4 = nc4.at(2); - z1 = nc1->at(3); - z2 = nc2->at(3); - z3 = nc3->at(3); - z4 = nc4->at(3); - + z1 = nc1.at(3); + z2 = nc2.at(3); + z3 = nc3.at(3); + z4 = nc4.at(3); } -IRResultType -QDKTPlate :: initializeFrom(InputRecord *ir) +void +QDKTPlate::initializeFrom(InputRecord &ir) { - return NLStructuralElement :: initializeFrom(ir); + StructuralElement::initializeFrom(ir); } void -QDKTPlate :: giveDofManDofIDMask(int inode, IntArray &answer) const +QDKTPlate::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_w, R_u, R_v}; + answer = { D_w, R_u, R_v }; } void -QDKTPlate :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) +QDKTPlate::computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) // returns normal vector to midPlane in GaussPoinr gp of receiver { FloatArray u, v; - u.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - v.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); + u.beDifferenceOf(this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); + v.beDifferenceOf(this->giveNode(3)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); answer.beVectorProductOf(u, v); answer.normalize(); @@ -371,7 +368,7 @@ QDKTPlate :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) double -QDKTPlate :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) +QDKTPlate::giveCharacteristicLength(const FloatArray &normalToCrackPlane) // // returns receiver's characteristic length for crack band models // for a crack formed in the plane with normal normalToCrackPlane. @@ -382,28 +379,28 @@ QDKTPlate :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) double -QDKTPlate :: computeVolumeAround(GaussPoint *gp) +QDKTPlate::computeVolumeAround(GaussPoint *gp) // Returns the portion of the receiver which is attached to gp. { double detJ, weight; weight = gp->giveWeight(); - detJ = fabs( this->interp_lin.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + detJ = fabs(this->interp_lin.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); return detJ * weight; ///@todo What about thickness? } Interface * -QDKTPlate :: giveInterface(InterfaceType interface) +QDKTPlate::giveInterface(InterfaceType interface) { if ( interface == LayeredCrossSectionInterfaceType ) { - return static_cast< LayeredCrossSectionInterface * >(this); + return static_cast< LayeredCrossSectionInterface * >( this ); } else if ( interface == ZZNodalRecoveryModelInterfaceType ) { - return static_cast< ZZNodalRecoveryModelInterface * >(this); + return static_cast< ZZNodalRecoveryModelInterface * >( this ); } else if ( interface == SPRNodalRecoveryModelInterfaceType ) { - return static_cast< SPRNodalRecoveryModelInterface * >(this); + return static_cast< SPRNodalRecoveryModelInterface * >( this ); } else if ( interface == ZZErrorEstimatorInterfaceType ) { - return static_cast< ZZErrorEstimatorInterface * >(this); + return static_cast< ZZErrorEstimatorInterface * >( this ); } @@ -411,7 +408,7 @@ QDKTPlate :: giveInterface(InterfaceType interface) } void -QDKTPlate :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) +QDKTPlate::computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) // Computes numerically the load vector of the receiver due to the body // loads, at tStep. // load is assumed to be in global cs. @@ -437,7 +434,7 @@ QDKTPlate :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep answer.clear(); if ( force.giveSize() ) { - for ( GaussPoint *gp: *this->giveDefaultIntegrationRulePtr() ) { + for ( GaussPoint *gp: * this->giveDefaultIntegrationRulePtr() ) { this->computeNmatrixAt(gp->giveSubPatchCoordinates(), n); dV = this->computeVolumeAround(gp) * this->giveCrossSection()->give(CS_Thickness, gp); dens = this->giveCrossSection()->give('d', gp); @@ -453,17 +450,17 @@ QDKTPlate :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep #define POINT_TOL 1.e-3 bool -QDKTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) +QDKTPlate::computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) //converts global coordinates to local planar area coordinates, //does not return a coordinate in the thickness direction, but //does check that the point is in the element thickness { // get node coordinates - double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4; + double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4; this->giveNodeCoordinates(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4); // Fetch local coordinates. - bool ok = this->interp_lin.global2local( answer, coords, FEIElementGeometryWrapper(this) ) > 0; + bool ok = this->interp_lin.global2local(answer, coords, FEIElementGeometryWrapper(this) ) > 0; //check that the point is in the element and set flag for ( int i = 1; i <= 4; i++ ) { @@ -484,7 +481,7 @@ QDKTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coord StructuralCrossSection *cs = this->giveStructuralCrossSection(); double elthick = cs->give(CS_Thickness, answer, this); - if ( elthick / 2.0 + midplZ - fabs( coords.at(3) ) < -POINT_TOL ) { + if ( elthick / 2.0 + midplZ - fabs(coords.at(3) ) < -POINT_TOL ) { answer.zero(); return false; } @@ -495,7 +492,7 @@ QDKTPlate :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coord int -QDKTPlate :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +QDKTPlate::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { FloatArray help; answer.resize(6); @@ -526,13 +523,13 @@ QDKTPlate :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType t answer.at(6) = help.at(3); // mxy return 1; } else { - return NLStructuralElement :: giveIPValue(answer, gp, type, tStep); + return StructuralElement::giveIPValue(answer, gp, type, tStep); } } void -QDKTPlate :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) +QDKTPlate::SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) { pap.resize(4); pap.at(1) = this->giveNode(1)->giveNumber(); @@ -543,14 +540,14 @@ QDKTPlate :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) void -QDKTPlate :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) +QDKTPlate::SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) { answer.resize(1); if ( ( pap == this->giveNode(1)->giveNumber() ) || - ( pap == this->giveNode(2)->giveNumber() ) || - ( pap == this->giveNode(3)->giveNumber() ) || - ( pap == this->giveNode(4)->giveNumber() ) ) { - answer.at(1) = pap; + ( pap == this->giveNode(2)->giveNumber() ) || + ( pap == this->giveNode(3)->giveNumber() ) || + ( pap == this->giveNode(4)->giveNumber() ) ) { + answer.at(1) = pap; } else { OOFEM_ERROR("node unknown"); } @@ -558,7 +555,7 @@ QDKTPlate :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, i SPRPatchType -QDKTPlate :: SPRNodalRecoveryMI_givePatchType() +QDKTPlate::SPRNodalRecoveryMI_givePatchType() { return SPRPatchType_2dxy; } @@ -568,8 +565,8 @@ QDKTPlate :: SPRNodalRecoveryMI_givePatchType() // layered cross section support functions // void -QDKTPlate :: computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) +QDKTPlate::computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) // returns full 3d strain vector of given layer (whose z-coordinate from center-line is // stored in slaveGp) for given tStep { @@ -590,31 +587,31 @@ QDKTPlate :: computeStrainVectorInLayer(FloatArray &answer, const FloatArray &ma } void -QDKTPlate :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +QDKTPlate::giveEdgeDofMapping(IntArray &answer, int iEdge) const { if ( iEdge == 1 ) { // edge between nodes 1 2 - answer = {1, 2, 3, 4, 5, 6}; + answer = { 1, 2, 3, 4, 5, 6 }; } else if ( iEdge == 2 ) { // edge between nodes 2 3 - answer = {4, 5, 6, 7, 8, 9}; + answer = { 4, 5, 6, 7, 8, 9 }; } else if ( iEdge == 3 ) { // edge between nodes 3 4 - answer = {7, 8, 9, 10, 11, 12}; + answer = { 7, 8, 9, 10, 11, 12 }; } else if ( iEdge == 4 ) { // edge between nodes 4 1 - answer = {10, 11, 12, 1, 2, 3}; + answer = { 10, 11, 12, 1, 2, 3 }; } else { OOFEM_ERROR("wrong edge number"); } } double -QDKTPlate :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +QDKTPlate::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { - double detJ = this->interp_lin.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - return detJ *gp->giveWeight(); + double detJ = this->interp_lin.edgeGiveTransformationJacobian(iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + return detJ * gp->giveWeight(); } int -QDKTPlate :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +QDKTPlate::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -623,22 +620,18 @@ QDKTPlate :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gaus // // i.e. f(element local) = T * f(edge local) // - double dx, dy, length; - IntArray edgeNodes; - Node *nodeA, *nodeB; - answer.resize(3, 3); - answer.zero(); + const auto &edgeNodes = this->interp_lin.computeLocalEdgeMapping(iEdge); - this->interp_lin.computeLocalEdgeMapping(edgeNodes, iEdge); + auto nodeA = this->giveNode(edgeNodes.at(1) ); + auto nodeB = this->giveNode(edgeNodes.at(2) ); - nodeA = this->giveNode( edgeNodes.at(1) ); - nodeB = this->giveNode( edgeNodes.at(2) ); - - dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); - dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); - length = sqrt(dx * dx + dy * dy); + double dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); + double dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); + double length = sqrt(dx * dx + dy * dy); + answer.resize(3, 3); + answer.zero(); answer.at(1, 1) = 1.0; answer.at(2, 2) = dx / length; answer.at(2, 3) = -dy / length; @@ -650,26 +643,26 @@ QDKTPlate :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gaus void -QDKTPlate :: computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) +QDKTPlate::computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) { this->computeNmatrixAt(sgp->giveNaturalCoordinates(), answer); } void -QDKTPlate::computeSurfaceNMatrix (FloatMatrix &answer, int boundaryID, const FloatArray& lcoords) +QDKTPlate::computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) { - FloatArray n_vec; - this->giveInterpolation()->boundarySurfaceEvalN(n_vec, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); - answer.beNMatrixOf(n_vec, 3); + FloatArray n_vec; + this->giveInterpolation()->boundarySurfaceEvalN( n_vec, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); + answer.beNMatrixOf(n_vec, 3); } void -QDKTPlate :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +QDKTPlate::giveSurfaceDofMapping(IntArray &answer, int iSurf) const { answer.resize(12); answer.zero(); if ( iSurf == 1 ) { - for (int i = 1; i<=12; i++) { + for ( int i = 1; i <= 12; i++ ) { answer.at(i) = i; } } else { @@ -677,24 +670,16 @@ QDKTPlate :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const } } -IntegrationRule * -QDKTPlate :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Square, approxOrder); - iRule->SetUpPointsOnSquare(npoints, _Unknown); - return iRule; -} double -QDKTPlate :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) +QDKTPlate::computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { return this->computeVolumeAround(gp); } int -QDKTPlate :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) +QDKTPlate::computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) { return 0; } @@ -705,9 +690,9 @@ QDKTPlate :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, Gaus // #ifdef __OOFEG void -QDKTPlate :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +QDKTPlate::drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) { - WCRec p [ 4 ]; + WCRec p[ 4 ]; GraphicObj *go; if ( !gc.testElementGraphicActivity(this) ) { @@ -716,8 +701,8 @@ QDKTPlate :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) if ( this->giveMaterial()->isActivated(tStep) ) { EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); - EASValsSetEdgeColor( gc.getElementEdgeColor() ); + EASValsSetColor(gc.getElementColor() ); + EASValsSetEdgeColor(gc.getElementEdgeColor() ); EASValsSetEdgeFlag(true); EASValsSetFillStyle(FILL_SOLID); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); @@ -743,9 +728,9 @@ QDKTPlate :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) void -QDKTPlate :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) +QDKTPlate::drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) { - WCRec p [ 4 ]; + WCRec p[ 4 ]; GraphicObj *go; double defScale = gc.getDefScale(); @@ -755,8 +740,8 @@ QDKTPlate :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Unkn if ( this->giveMaterial()->isActivated(tStep) ) { EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); - EASValsSetColor( gc.getDeformedElementColor() ); - EASValsSetEdgeColor( gc.getElementEdgeColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); + EASValsSetEdgeColor(gc.getElementEdgeColor() ); EASValsSetEdgeFlag(true); EASValsSetFillStyle(FILL_SOLID); EASValsSetLayer(OOFEG_DEFORMED_GEOMETRY_LAYER); @@ -781,13 +766,13 @@ QDKTPlate :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Unkn void -QDKTPlate :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) +QDKTPlate::drawScalar(oofegGraphicContext &gc, TimeStep *tStep) { int i, indx, result = 0; - WCRec p [ 4 ]; + WCRec p[ 4 ]; GraphicObj *tr; - FloatArray v [ 4 ]; - double s [ 4 ], defScale; + FloatArray v[ 4 ]; + double s[ 4 ], defScale; if ( !gc.testElementGraphicActivity(this) ) { return; @@ -829,7 +814,6 @@ QDKTPlate :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) tr = CreateQuadWD3D(p, s [ 0 ], s [ 1 ], s [ 2 ], s [ 3 ]); EGWithMaskChangeAttributes(LAYER_MASK, tr); EMAddGraphicsToModel(ESIModel(), tr); - } else if ( ( gc.getScalarAlgo() == SA_ZPROFILE ) || ( gc.getScalarAlgo() == SA_COLORZPROFILE ) ) { double landScale = gc.getLandScale(); @@ -853,7 +837,7 @@ QDKTPlate :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) } if ( gc.getScalarAlgo() == SA_ZPROFILE ) { - EASValsSetColor( gc.getDeformedElementColor() ); + EASValsSetColor(gc.getDeformedElementColor() ); EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); tr = CreateQuad3D(p); EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, tr); @@ -871,7 +855,7 @@ QDKTPlate :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) } IntArray ind(4); - WCRec pp [ 9 ]; + WCRec pp[ 9 ]; for ( i = 0; i < 4; i++ ) { if ( gc.getInternalVarsDefGeoFlag() ) { @@ -901,7 +885,7 @@ QDKTPlate :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) pp [ 8 ].y = 0.25 * ( pp [ 0 ].y + pp [ 1 ].y + pp [ 2 ].y + pp [ 3 ].y ); pp [ 8 ].z = 0.25 * ( pp [ 0 ].z + pp [ 1 ].z + pp [ 2 ].z + pp [ 3 ].z ); - for ( GaussPoint *gp: *this->giveDefaultIntegrationRulePtr() ) { + for ( GaussPoint *gp: * this->giveDefaultIntegrationRulePtr() ) { const FloatArray &gpCoords = gp->giveNaturalCoordinates(); if ( ( gpCoords.at(1) > 0. ) && ( gpCoords.at(2) > 0. ) ) { ind.at(1) = 0; diff --git a/src/sm/Elements/Plates/qdkt.h b/src/sm/Elements/Plates/qdkt.h index 94d211d34..520cf65fe 100644 --- a/src/sm/Elements/Plates/qdkt.h +++ b/src/sm/Elements/Plates/qdkt.h @@ -35,9 +35,9 @@ #ifndef qdkt_h #define qdkt_h -#include "../sm/Elements/nlstructuralelement.h" -#include "../sm/CrossSections/layeredcrosssection.h" -#include "../sm/ErrorEstimators/zzerrorestimator.h" +#include "sm/Elements/structuralelement.h" +#include "sm/CrossSections/layeredcrosssection.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" #include "zznodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -60,96 +60,92 @@ class FEI2dQuadLin; * Tasks: * - calculating its B,D,N matrices and dV. */ -class QDKTPlate : public NLStructuralElement, -public ZZNodalRecoveryModelInterface, -public SPRNodalRecoveryModelInterface, -public LayeredCrossSectionInterface, -public ZZErrorEstimatorInterface +class QDKTPlate : public StructuralElement, + public ZZNodalRecoveryModelInterface, + public SPRNodalRecoveryModelInterface, + public LayeredCrossSectionInterface, + public ZZErrorEstimatorInterface { protected: /// Element geometry approximation static FEI2dQuadLin interp_lin; public: - QDKTPlate(int n, Domain * d); + QDKTPlate(int n, Domain *d); virtual ~QDKTPlate() { } - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; - virtual MaterialMode giveMaterialMode() { return _2dPlate; } - virtual int testElementExtension(ElementExtension ext) { return ( ( ( ext == Element_EdgeLoadSupport ) || ( ext == Element_SurfaceLoadSupport ) ) ? 1 : 0 ); } + MaterialMode giveMaterialMode() override { return _2dPlate; } + int testElementExtension(ElementExtension ext) override { return ( ( ( ext == Element_EdgeLoadSupport ) || ( ext == Element_SurfaceLoadSupport ) ) ? 1 : 0 ); } protected: - virtual void computeGaussPoints(); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); + void computeGaussPoints() override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; virtual void giveNodeCoordinates(double &x1, double &x2, double &x3, double &x4, double &y1, double &y2, double &y3, double &y4, double &z1, double &z2, double &z3, double &z4); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode); + void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) override; /** * @name Surface load support */ //@{ - virtual void computeSurfaceNMatrix (FloatMatrix &answer, int boundaryID, const FloatArray& lcoords); - virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); - virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const; - virtual IntegrationRule *GetSurfaceIntegrationRule(int iSurf); - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf); - virtual int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) override; + void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override; + double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) override; + int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp) override; //@} /** * @name Edge load support */ //@{ - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); - //@} - - - + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; + //@} public: // definition & identification - virtual const char *giveClassName() const { return "QDKTPlate"; } - virtual const char *giveInputRecordName() const { return _IFT_QDKTPlate_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "QDKTPlate"; } + const char *giveInputRecordName() const override { return _IFT_QDKTPlate_Name; } + void initializeFrom(InputRecord &ir) override; - virtual int computeNumberOfDofs() { return 12; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 12; } + void giveDofManDofIDMask(int inode, IntArray &) const override; - virtual void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp); + void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) override; - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane); - virtual double computeVolumeAround(GaussPoint *gp); + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override; + double computeVolumeAround(GaussPoint *gp) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP() { return this->numberOfGaussPoints; } - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override { return this->numberOfGaussPoints; } + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; // layered cross section support functions - virtual void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep); + void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif }; } // end namespace oofem diff --git a/src/sm/Elements/Plates/quad1mindlin.C b/src/sm/Elements/Plates/quad1mindlin.C index 8bc27439a..26a5b140a 100644 --- a/src/sm/Elements/Plates/quad1mindlin.C +++ b/src/sm/Elements/Plates/quad1mindlin.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Plates/quad1mindlin.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/Plates/quad1mindlin.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "node.h" #include "material.h" #include "crosssection.h" @@ -51,46 +51,44 @@ namespace oofem { REGISTER_Element(Quad1Mindlin); -FEI2dQuadLin Quad1Mindlin :: interp_lin(1, 2); +FEI2dQuadLin Quad1Mindlin::interp_lin(1, 2); -Quad1Mindlin :: Quad1Mindlin(int n, Domain *aDomain) : - NLStructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this), +Quad1Mindlin::Quad1Mindlin(int n, Domain *aDomain) : + StructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this), SPRNodalRecoveryModelInterface() { numberOfGaussPoints = 4; numberOfDofMans = 4; - this->reducedIntegrationFlag = false; } FEInterpolation * -Quad1Mindlin :: giveInterpolation() const +Quad1Mindlin::giveInterpolation() const { return & interp_lin; } FEInterpolation * -Quad1Mindlin :: giveInterpolation(DofIDItem id) const +Quad1Mindlin::giveInterpolation(DofIDItem id) const { return & interp_lin; } void -Quad1Mindlin :: computeGaussPoints() +Quad1Mindlin::computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 5) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 5); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } void -Quad1Mindlin :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) +Quad1Mindlin::computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) { // Only gravity load - double dV, load; - FloatArray force, gravity, n; + FloatArray gravity; if ( ( forLoad->giveBCGeoType() != BodyLoadBGT ) || ( forLoad->giveBCValType() != ForceLoadBVT ) ) { OOFEM_ERROR("unknown load type"); @@ -99,21 +97,18 @@ Quad1Mindlin :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeS // note: force is assumed to be in global coordinate system. forLoad->computeComponentArrayAt(gravity, tStep, mode); - force.clear(); if ( gravity.giveSize() ) { + FloatArrayF< 4 >force; ///@todo Other/higher integration for lumped mass matrices perhaps? - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { - - this->interp_lin.evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - dV = this->computeVolumeAround(gp) * this->giveCrossSection()->give(CS_Thickness, gp); - load = this->giveStructuralCrossSection()->give('d', gp) * gravity.at(3) * dV; - - force.add(load, n); + for ( auto &gp: * integrationRulesArray [ 0 ] ) { + auto n = this->interp_lin.evalN( gp->giveNaturalCoordinates() ); + double dV = this->computeVolumeAround(gp) * this->giveCrossSection()->give(CS_Thickness, gp); + double load = this->giveStructuralCrossSection()->give('d', gp) * gravity.at(3) * dV; + force += load * n; } answer.resize(12); answer.zero(); - answer.at(1) = force.at(1); answer.at(4) = force.at(2); answer.at(7) = force.at(3); @@ -125,116 +120,108 @@ Quad1Mindlin :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeS void -Quad1Mindlin :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +Quad1Mindlin::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the [5x9] strain-displacement matrix {B} of the receiver, // evaluated at gp. { - FloatArray n, ns; - FloatMatrix dn, dns; - - this->interp_lin.evaldNdx( dn, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - this->interp_lin.evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - - answer.resize(5, 12); - answer.zero(); + auto dn = this->interp_lin.evaldNdx( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ).second; + auto n = this->interp_lin.evalN( gp->giveNaturalCoordinates() ); // enforce one-point reduced integration if requested + FloatArrayF< 4 >ns; + FloatMatrixF< 2, 4 >dns; if ( this->reducedIntegrationFlag ) { - FloatArray lc(2); - lc.zero(); // set to element center coordinates - - this->interp_lin.evaldNdx( dns, lc, FEIElementGeometryWrapper(this)); - this->interp_lin.evalN( ns, lc, FEIElementGeometryWrapper(this)); - } else { + FloatArrayF< 2 >lc; // set to element center coordinates + dns = this->interp_lin.evaldNdx( lc, FEIElementGeometryWrapper(this) ).second; + ns = this->interp_lin.evalN(lc); + } else { dns = dn; ns = n; } + answer.resize(5, 12); + answer.zero(); + ///@todo Check sign here for ( int i = 0; i < 4; ++i ) { - answer(0, 2 + i * 3) = dn(i, 0); // kappa_x = d(fi_y)/dx - answer(1, 1 + i * 3) = -dn(i, 1); // kappa_y = -d(fi_x)/dy - answer(2, 2 + i * 3) = dn(i, 1); // kappa_xy=d(fi_y)/dy-d(fi_x)/dx - answer(2, 1 + i * 3) = -dn(i, 0); - - answer(3, 0 + i * 3) = dns(i, 0); // gamma_xz = fi_y+dw/dx - answer(3, 2 + i * 3) = ns(i); - answer(4, 0 + i * 3) = dns(i, 1);// gamma_yz = -fi_x+dw/dy - answer(4, 1 + i * 3) = -ns(i); + answer(0, 2 + i * 3) = dn(0, i);// kappa_x = d(fi_y)/dx + answer(1, 1 + i * 3) = -dn(1, i); // kappa_y = -d(fi_x)/dy + answer(2, 2 + i * 3) = dn(1, i);// kappa_xy=d(fi_y)/dy-d(fi_x)/dx + answer(2, 1 + i * 3) = -dn(0, i); + + answer(3, 0 + i * 3) = dns(0, i); // gamma_xz = fi_y+dw/dx + answer(3, 2 + i * 3) = ns [ i ]; + answer(4, 0 + i * 3) = dns(1, i);// gamma_yz = -fi_x+dw/dy + answer(4, 1 + i * 3) = -ns [ i ]; } } void -Quad1Mindlin :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +Quad1Mindlin::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Plate(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Plate(strain, gp, tStep); } void -Quad1Mindlin :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +Quad1Mindlin::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give2dPlateStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give2dPlateStiffMtrx(rMode, gp, tStep); } -IRResultType -Quad1Mindlin :: initializeFrom(InputRecord *ir) +void +Quad1Mindlin::initializeFrom(InputRecord &ir) { this->numberOfGaussPoints = 4; - this->reducedIntegrationFlag = ir->hasField(_IFT_Quad1Mindlin_ReducedIntegration); - return NLStructuralElement :: initializeFrom(ir); + this->reducedIntegrationFlag = ir.hasField(_IFT_Quad1Mindlin_ReducedIntegration); + StructuralElement::initializeFrom(ir); } void -Quad1Mindlin :: giveDofManDofIDMask(int inode, IntArray &answer) const +Quad1Mindlin::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_w, R_u, R_v}; + answer = { D_w, R_u, R_v }; } void -Quad1Mindlin :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) +Quad1Mindlin::computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) { - FloatArray u, v; - u.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - v.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); + FloatArrayF< 3 >u = this->giveNode(2)->giveCoordinates() - this->giveNode(1)->giveCoordinates(); + FloatArrayF< 3 >v = this->giveNode(3)->giveCoordinates() - this->giveNode(1)->giveCoordinates(); - answer.beVectorProductOf(u, v); - answer.normalize(); + auto n = cross(u, v); + answer = n / norm(n); } double -Quad1Mindlin :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) +Quad1Mindlin::giveCharacteristicLength(const FloatArray &normalToCrackPlane) { return this->giveCharacteristicLengthForPlaneElements(normalToCrackPlane); } double -Quad1Mindlin :: computeVolumeAround(GaussPoint *gp) +Quad1Mindlin::computeVolumeAround(GaussPoint *gp) { - double detJ, weight; - - weight = gp->giveWeight(); - detJ = fabs( this->interp_lin.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double weight = gp->giveWeight(); + double detJ = fabs(this->interp_lin.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); return detJ * weight; } void -Quad1Mindlin :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +Quad1Mindlin::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. { - double dV, mass = 0.; - ///@todo Other/higher integration for lumped mass matrices perhaps? - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { - - dV = this->computeVolumeAround(gp); + double mass = 0.; + for ( GaussPoint *gp: * integrationRulesArray [ 0 ] ) { + double dV = this->computeVolumeAround(gp); mass += dV * this->giveStructuralCrossSection()->give('d', gp); } @@ -248,52 +235,44 @@ Quad1Mindlin :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) int -Quad1Mindlin :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +Quad1Mindlin::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - FloatArray help; answer.resize(6); + auto ms = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); if ( type == IST_ShellForceTensor || type == IST_ShellStrainTensor ) { - if ( type == IST_ShellForceTensor ) { - help = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); - } else { - help = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); - } + const auto &s = type == IST_ShellForceTensor ? ms->giveStressVector() : ms->giveStrainVector(); answer.at(1) = 0.0; // nx answer.at(2) = 0.0; // ny answer.at(3) = 0.0; // nz - answer.at(4) = help.at(5); // vyz - answer.at(5) = help.at(4); // vxz + answer.at(4) = s.at(5); // vyz + answer.at(5) = s.at(4); // vxz answer.at(6) = 0.0; // vxy return 1; } else if ( type == IST_ShellMomentTensor || type == IST_CurvatureTensor ) { - if ( type == IST_ShellMomentTensor ) { - help = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); - } else { - help = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); - } - answer.at(1) = help.at(1); // mx - answer.at(2) = help.at(2); // my - answer.at(3) = 0.0; // mz - answer.at(4) = 0.0; // myz - answer.at(5) = 0.0; // mxz - answer.at(6) = help.at(3); // mxy + const auto &s = type == IST_ShellMomentTensor ? ms->giveStressVector() : ms->giveStrainVector(); + answer.at(1) = s.at(1); // mx + answer.at(2) = s.at(2); // my + answer.at(3) = 0.0; // mz + answer.at(4) = 0.0; // myz + answer.at(5) = 0.0; // mxz + answer.at(6) = s.at(3); // mxy return 1; } else { - return NLStructuralElement :: giveIPValue(answer, gp, type, tStep); + return StructuralElement::giveIPValue(answer, gp, type, tStep); } } void -Quad1Mindlin :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +Quad1Mindlin::giveEdgeDofMapping(IntArray &answer, int iEdge) const { if ( iEdge == 1 ) { // edge between nodes 1 2 - answer = {1, 2, 3, 4, 5, 6}; + answer = { 1, 2, 3, 4, 5, 6 }; } else if ( iEdge == 2 ) { // edge between nodes 2 3 - answer = {4, 5, 6, 7, 8, 9}; + answer = { 4, 5, 6, 7, 8, 9 }; } else if ( iEdge == 3 ) { // edge between nodes 3 4 - answer = {7, 8, 9, 10, 11, 12}; + answer = { 7, 8, 9, 10, 11, 12 }; } else if ( iEdge == 4 ) { // edge between nodes 4 1 - answer = {10, 11, 12, 1, 2, 3}; + answer = { 10, 11, 12, 1, 2, 3 }; } else { OOFEM_ERROR("wrong edge number"); } @@ -301,32 +280,27 @@ Quad1Mindlin :: giveEdgeDofMapping(IntArray &answer, int iEdge) const double -Quad1Mindlin :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +Quad1Mindlin::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { - double detJ = this->interp_lin.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - return detJ *gp->giveWeight(); + double detJ = this->interp_lin.edgeGiveTransformationJacobian(iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + return detJ * gp->giveWeight(); } int -Quad1Mindlin :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +Quad1Mindlin::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { - double dx, dy, length; - IntArray edgeNodes; - Node *nodeA, *nodeB; + const auto &edgeNodes = this->interp_lin.computeLocalEdgeMapping(iEdge); - answer.resize(3, 3); - answer.zero(); - - this->interp_lin.computeLocalEdgeMapping(edgeNodes, iEdge); + auto nodeA = this->giveNode(edgeNodes.at(1) ); + auto nodeB = this->giveNode(edgeNodes.at(2) ); - nodeA = this->giveNode( edgeNodes.at(1) ); - nodeB = this->giveNode( edgeNodes.at(2) ); - - dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); - dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); - length = sqrt(dx * dx + dy * dy); + double dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); + double dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); + double length = sqrt(dx * dx + dy * dy); + answer.resize(3, 3); + answer.zero(); answer.at(1, 1) = 1.0; answer.at(2, 2) = dx / length; answer.at(2, 3) = -dy / length; @@ -336,21 +310,21 @@ Quad1Mindlin :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, G return 1; } Interface * -Quad1Mindlin :: giveInterface(InterfaceType interface) +Quad1Mindlin::giveInterface(InterfaceType interface) { if ( interface == ZZNodalRecoveryModelInterfaceType ) { - return static_cast< ZZNodalRecoveryModelInterface * >(this); + return static_cast< ZZNodalRecoveryModelInterface * >( this ); } else if ( interface == SPRNodalRecoveryModelInterfaceType ) { - return static_cast< SPRNodalRecoveryModelInterface * >(this); + return static_cast< SPRNodalRecoveryModelInterface * >( this ); } - return NULL; + return nullptr; } void -Quad1Mindlin :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) +Quad1Mindlin::SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) { pap.resize(4); for ( int i = 1; i < 5; i++ ) { @@ -359,7 +333,7 @@ Quad1Mindlin :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) } void -Quad1Mindlin :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) +Quad1Mindlin::SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) { int found = 0; answer.resize(1); diff --git a/src/sm/Elements/Plates/quad1mindlin.h b/src/sm/Elements/Plates/quad1mindlin.h index 2d0dc9597..acd45d319 100644 --- a/src/sm/Elements/Plates/quad1mindlin.h +++ b/src/sm/Elements/Plates/quad1mindlin.h @@ -35,7 +35,7 @@ #ifndef quad1mindlin_H #define quad1mindlin_H -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/structuralelement.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -61,64 +61,60 @@ class FEI2dQuadLin; * * @author Mikael Öhman */ -class Quad1Mindlin : public NLStructuralElement, -public ZZNodalRecoveryModelInterface, -public SPRNodalRecoveryModelInterface +class Quad1Mindlin : public StructuralElement, + public ZZNodalRecoveryModelInterface, + public SPRNodalRecoveryModelInterface { protected: static FEI2dQuadLin interp_lin; /// Flag controlling reduced (one - point) integration for shear - bool reducedIntegrationFlag; + bool reducedIntegrationFlag = false; public: - Quad1Mindlin(int n, Domain * d); - virtual ~Quad1Mindlin() { } + Quad1Mindlin(int n, Domain *d); - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; - virtual MaterialMode giveMaterialMode() { return _2dPlate; } - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } + MaterialMode giveMaterialMode() override { return _2dPlate; } + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Quad1Mindlin_Name; } - virtual const char *giveClassName() const { return "Quad1Mindlin"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_Quad1Mindlin_Name; } + const char *giveClassName() const override { return "Quad1Mindlin"; } + void initializeFrom(InputRecord &ir) override; - virtual int computeNumberOfDofs() { return 12; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 12; } + void giveDofManDofIDMask(int inode, IntArray &) const override; - virtual void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp); + void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) override; - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane); - virtual double computeVolumeAround(GaussPoint *gp); + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override; + double computeVolumeAround(GaussPoint *gp) override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual Interface *giveInterface(InterfaceType it); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + Interface *giveInterface(InterfaceType it) override; protected: - virtual void computeGaussPoints(); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); - //virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, GaussPoint *gp) { answer.clear(); } - //virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const { answer.clear(); } - //virtual IntegrationRule *GetSurfaceIntegrationRule(int i) { return NULL; } - //virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { return 0.; } - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP() { return this->numberOfGaussPoints; } - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType() { return SPRPatchType_2dxy; } + void computeGaussPoints() override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; + + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override { return this->numberOfGaussPoints; } + SPRPatchType SPRNodalRecoveryMI_givePatchType() override { return SPRPatchType_2dxy; } }; } // end namespace oofem #endif // quad1mindlin_H diff --git a/src/sm/Elements/Shells/cct3d.C b/src/sm/Elements/Shells/cct3d.C index e94b3267f..271df6e62 100644 --- a/src/sm/Elements/Shells/cct3d.C +++ b/src/sm/Elements/Shells/cct3d.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Shells/cct3d.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/Shells/cct3d.h" +#include "sm/Materials/structuralms.h" #include "fei2dtrlin.h" #include "node.h" #include "load.h" @@ -47,43 +47,36 @@ namespace oofem { REGISTER_Element(CCTPlate3d); -CCTPlate3d :: CCTPlate3d(int n, Domain *aDomain) : CCTPlate(n, aDomain) -{ -} +CCTPlate3d::CCTPlate3d(int n, Domain *aDomain) : CCTPlate(n, aDomain) +{} void -CCTPlate3d :: giveLocalCoordinates(FloatArray &answer, FloatArray &global) -// Returns global coordinates given in global vector -// transformed into local coordinate system of the -// receiver +CCTPlate3d::giveLocalCoordinates(FloatArray &answer, const FloatArray &global) { - FloatArray offset; - // test the parametr if ( global.giveSize() != 3 ) { OOFEM_ERROR("cannot transform coordinates - size mismatch"); - exit(1); } // first ensure that receiver's GtoLRotationMatrix[3,3] is defined this->computeGtoLRotationMatrix(); - offset = global; - offset.subtract( * this->giveNode(1)->giveCoordinates() ); + FloatArray offset; + offset.beDifferenceOf( global, this->giveNode(1)->giveCoordinates() ); answer.beProductOf(GtoLRotationMatrix, offset); } void -CCTPlate3d :: giveNodeCoordinates(double &x1, double &x2, double &x3, - double &y1, double &y2, double &y3, - double &z1, double &z2, double &z3) +CCTPlate3d::giveNodeCoordinates(double &x1, double &x2, double &x3, + double &y1, double &y2, double &y3, + double &z1, double &z2, double &z3) { FloatArray nc1(3), nc2(3), nc3(3); - this->giveLocalCoordinates( nc1, * ( this->giveNode(1)->giveCoordinates() ) ); - this->giveLocalCoordinates( nc2, * ( this->giveNode(2)->giveCoordinates() ) ); - this->giveLocalCoordinates( nc3, * ( this->giveNode(3)->giveCoordinates() ) ); + this->giveLocalCoordinates(nc1, this->giveNode(1)->giveCoordinates() ); + this->giveLocalCoordinates(nc2, this->giveNode(2)->giveCoordinates() ); + this->giveLocalCoordinates(nc3, this->giveNode(3)->giveCoordinates() ); x1 = nc1.at(1); x2 = nc2.at(1); @@ -96,46 +89,45 @@ CCTPlate3d :: giveNodeCoordinates(double &x1, double &x2, double &x3, z1 = nc1.at(3); z2 = nc2.at(3); z3 = nc3.at(3); - } void -CCTPlate3d :: giveDofManDofIDMask(int inode, IntArray &answer) const +CCTPlate3d::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u, D_v, D_w, R_u, R_v, R_w}; + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; } bool -CCTPlate3d :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) +CCTPlate3d::computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) //converts global coordinates to local planar area coordinates, //does not return a coordinate in the thickness direction, but //does check that the point is in the element thickness { // rotate the input point Coordinate System into the element CS FloatArray inputCoords_ElCS; - std::vector< FloatArray > lc(3); + std::vector< FloatArray >lc(3); FloatArray llc; - this->giveLocalCoordinates( inputCoords_ElCS, const_cast< FloatArray & >(coords) ); + this->giveLocalCoordinates(inputCoords_ElCS, coords); for ( int _i = 0; _i < 3; _i++ ) { - this->giveLocalCoordinates( lc [ _i ], * this->giveNode(_i + 1)->giveCoordinates() ); + this->giveLocalCoordinates(lc [ _i ], this->giveNode(_i + 1)->giveCoordinates() ); } FEI2dTrLin _interp(1, 2); - bool inplane = _interp.global2local(llc, inputCoords_ElCS, FEIVertexListGeometryWrapper(lc)) > 0; + bool inplane = _interp.global2local( llc, inputCoords_ElCS, FEIVertexListGeometryWrapper(lc) ) > 0; answer.resize(2); answer.at(1) = inputCoords_ElCS.at(1); answer.at(2) = inputCoords_ElCS.at(2); GaussPoint _gp(NULL, 1, answer, 2.0, _2dPlate); // now check if the third local coordinate is within the thickness of element - bool outofplane = ( fabs( inputCoords_ElCS.at(3) ) <= this->giveCrossSection()->give(CS_Thickness, & _gp) / 2. ); + bool outofplane = ( fabs(inputCoords_ElCS.at(3) ) <= this->giveCrossSection()->give(CS_Thickness, & _gp) / 2. ); return inplane && outofplane; } int -CCTPlate3d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +CCTPlate3d::computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { double l1 = lcoords.at(1); double l2 = lcoords.at(2); @@ -143,14 +135,14 @@ CCTPlate3d :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lco answer.resize(3); for ( int _i = 1; _i <= 3; _i++ ) { - answer.at(_i) = l1 * this->giveNode(1)->giveCoordinate(_i) + l2 *this->giveNode(2)->giveCoordinate(_i) + l3 *this->giveNode(3)->giveCoordinate(_i); + answer.at(_i) = l1 * this->giveNode(1)->giveCoordinate(_i) + l2 * this->giveNode(2)->giveCoordinate(_i) + l3 * this->giveNode(3)->giveCoordinate(_i); } return true; } const FloatMatrix * -CCTPlate3d :: computeGtoLRotationMatrix() +CCTPlate3d::computeGtoLRotationMatrix() // Returns the rotation matrix of the receiver of the size [3,3] // coords(local) = T * coords(global) // @@ -165,8 +157,8 @@ CCTPlate3d :: computeGtoLRotationMatrix() FloatArray e1, e2, e3, help; // compute e1' = [N2-N1] and help = [N3-N1] - e1.beDifferenceOf(*this->giveNode(2)->giveCoordinates(), *this->giveNode(1)->giveCoordinates()); - help.beDifferenceOf(*this->giveNode(3)->giveCoordinates(), *this->giveNode(1)->giveCoordinates()); + e1.beDifferenceOf( this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); + help.beDifferenceOf( this->giveNode(3)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); // let us normalize e1' e1.normalize(); @@ -189,12 +181,12 @@ CCTPlate3d :: computeGtoLRotationMatrix() } } - return &GtoLRotationMatrix; + return & GtoLRotationMatrix; } bool -CCTPlate3d :: computeGtoLRotationMatrix(FloatMatrix &answer) +CCTPlate3d::computeGtoLRotationMatrix(FloatMatrix &answer) // Returns the rotation matrix of the receiver of the size [9,18] // r(local) = T * r(global) // for one node (r written transposed): {w,r1,r2} = T * {u,v,w,r1,r2,r3} @@ -214,7 +206,7 @@ CCTPlate3d :: computeGtoLRotationMatrix(FloatMatrix &answer) } void -CCTPlate3d :: giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep) +CCTPlate3d::giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep) // returns characteristic tensor of the receiver at given gp and tStep // strain vector = (Kappa_x, Kappa_y, Kappa_xy, Gamma_zx, Gamma_zy) { @@ -262,7 +254,7 @@ CCTPlate3d :: giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, Gau } if ( ( type == GlobalForceTensor ) || ( type == GlobalMomentTensor ) || - ( type == GlobalStrainTensor ) || ( type == GlobalCurvatureTensor ) ) { + ( type == GlobalStrainTensor ) || ( type == GlobalCurvatureTensor ) ) { this->computeGtoLRotationMatrix(); answer.rotatedWith(GtoLRotationMatrix); } @@ -270,7 +262,7 @@ CCTPlate3d :: giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, Gau int -CCTPlate3d :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +CCTPlate3d::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { FloatMatrix globTensor; CharTensor cht; @@ -312,12 +304,12 @@ CCTPlate3d :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType return 1; } else { - return NLStructuralElement :: giveIPValue(answer, gp, type, tStep); + return StructuralElement::giveIPValue(answer, gp, type, tStep); } } int -CCTPlate3d :: computeLoadGToLRotationMtrx(FloatMatrix &answer) +CCTPlate3d::computeLoadGToLRotationMtrx(FloatMatrix &answer) // Returns the rotation matrix of the receiver of the size [6,6] // f(local) = T * f(global) { @@ -336,7 +328,7 @@ CCTPlate3d :: computeLoadGToLRotationMtrx(FloatMatrix &answer) } void -CCTPlate3d :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) +CCTPlate3d::computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) // Computes numerically the load vector of the receiver due to the body loads, at tStep. // load is assumed to be in global cs. // load vector is then transformed to coordinate system in each node. @@ -394,7 +386,7 @@ CCTPlate3d :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeSte } void -CCTPlate3d :: computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) +CCTPlate3d::computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) { FloatMatrix ne; this->computeNmatrixAt(sgp->giveNaturalCoordinates(), ne); @@ -416,7 +408,7 @@ CCTPlate3d :: computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint } void -CCTPlate3d :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +CCTPlate3d::giveSurfaceDofMapping(IntArray &answer, int iSurf) const { answer.resize(18); answer.zero(); @@ -437,57 +429,56 @@ CCTPlate3d :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const } } -IntegrationRule * -CCTPlate3d :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, approxOrder); - iRule->SetUpPointsOnTriangle(npoints, _Unknown); - return iRule; -} double -CCTPlate3d :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) +CCTPlate3d::computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { return this->computeVolumeAround(gp); } int -CCTPlate3d :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) +CCTPlate3d::computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) { return 0; } void -CCTPlate3d :: printOutputAt(FILE *file, TimeStep *tStep) +CCTPlate3d::printOutputAt(FILE *file, TimeStep *tStep) // Performs end-of-step operations. { FloatArray v; - fprintf( file, "element %d (%8d) :\n", this->giveLabel(), this->giveNumber() ); - - for ( int i = 0; i < (int)integrationRulesArray.size(); i++ ) { - for ( GaussPoint *gp: *integrationRulesArray [ i ] ) { + fprintf(file, "element %d (%8d) :\n", this->giveLabel(), this->giveNumber() ); - fprintf( file, " GP %2d.%-2d :", i + 1, gp->giveNumber() ); + for ( int i = 0; i < ( int ) integrationRulesArray.size(); i++ ) { + for ( GaussPoint *gp: * integrationRulesArray [ i ] ) { + fprintf(file, " GP %2d.%-2d :", i + 1, gp->giveNumber() ); this->giveIPValue(v, gp, IST_ShellStrainTensor, tStep); fprintf(file, " strains "); - for ( auto &val : v ) fprintf(file, " %.4e", val); + for ( auto &val : v ) { + fprintf(file, " %.4e", val); + } this->giveIPValue(v, gp, IST_CurvatureTensor, tStep); fprintf(file, "\n curvatures "); - for ( auto &val : v ) fprintf(file, " %.4e", val); + for ( auto &val : v ) { + fprintf(file, " %.4e", val); + } // Forces - Moments this->giveIPValue(v, gp, IST_ShellForceTensor, tStep); fprintf(file, "\n stresses "); - for ( auto &val : v ) fprintf(file, " %.4e", val); + for ( auto &val : v ) { + fprintf(file, " %.4e", val); + } this->giveIPValue(v, gp, IST_ShellMomentTensor, tStep); fprintf(file, "\n moments "); - for ( auto &val : v ) fprintf(file, " %.4e", val); + for ( auto &val : v ) { + fprintf(file, " %.4e", val); + } fprintf(file, "\n"); } diff --git a/src/sm/Elements/Shells/cct3d.h b/src/sm/Elements/Shells/cct3d.h index b72333029..9c12332c6 100644 --- a/src/sm/Elements/Shells/cct3d.h +++ b/src/sm/Elements/Shells/cct3d.h @@ -35,7 +35,7 @@ #ifndef cct3d_h #define cct3d_h -#include "../sm/Elements/Plates/cct.h" +#include "sm/Elements/Plates/cct.h" #include "floatmatrix.h" #define _IFT_CCTPlate3d_Name "cctplate3d" @@ -83,52 +83,51 @@ class CCTPlate3d : public CCTPlate virtual ~CCTPlate3d() {} protected: - void giveLocalCoordinates(FloatArray &answer, FloatArray &global); - virtual void giveNodeCoordinates(double &x1, double &x2, double &x3, - double &y1, double &y2, double &y3, - double &z1, double &z2, double &z3); + void giveLocalCoordinates(FloatArray &answer, const FloatArray &global); + void giveNodeCoordinates(double &x1, double &x2, double &x3, + double &y1, double &y2, double &y3, + double &z1, double &z2, double &z3) override; void giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) override; friend class TR_SHELL01; /** * @name Surface load support */ //@{ - virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); - virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const; - virtual IntegrationRule *GetSurfaceIntegrationRule(int iSurf); - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf); - virtual int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override; + double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) override; + int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp) override; //@} public: // definition & identification - virtual const char *giveClassName() const { return "CCTPlate3d"; } - virtual const char *giveInputRecordName() const { return _IFT_CCTPlate3d_Name; } + const char *giveClassName() const override { return "CCTPlate3d"; } + const char *giveInputRecordName() const override { return _IFT_CCTPlate3d_Name; } - virtual int computeNumberOfDofs() { return 9; } - virtual int computeNumberOfGlobalDofs() { return 18; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 9; } + int computeNumberOfGlobalDofs() override { return 18; } + void giveDofManDofIDMask(int inode, IntArray &) const override; virtual const FloatMatrix *computeGtoLRotationMatrix(); - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords); - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; - virtual int giveLocalCoordinateSystem(FloatMatrix &answer) + int giveLocalCoordinateSystem(FloatMatrix &answer) override { OOFEM_ERROR("calling of this function id not allowed"); return 0; } - virtual int testElementExtension(ElementExtension ext) + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; }; } // end namespace oofem #endif // cct3d_h diff --git a/src/sm/Elements/Shells/mitc4.C b/src/sm/Elements/Shells/mitc4.C index 47f6002ea..70df1a670 100644 --- a/src/sm/Elements/Shells/mitc4.C +++ b/src/sm/Elements/Shells/mitc4.C @@ -32,19 +32,21 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Shells/mitc4.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/Shells/mitc4.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei2dquadlin.h" #include "node.h" #include "material.h" #include "crosssection.h" #include "gausspoint.h" -#include "../sm/CrossSections/variablecrosssection.h" +#include "sm/CrossSections/variablecrosssection.h" #include "gaussintegrationrule.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" #include "intarray.h" #include "load.h" #include "boundaryload.h" @@ -55,50 +57,49 @@ namespace oofem { REGISTER_Element(MITC4Shell); -FEI2dQuadLin MITC4Shell :: interp_lin(1, 2); +FEI2dQuadLin MITC4Shell::interp_lin(1, 2); -MITC4Shell :: MITC4Shell(int n, Domain *aDomain) : - NLStructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this), - SPRNodalRecoveryModelInterface(), SpatialLocalizerInterface(this) +MITC4Shell::MITC4Shell(int n, Domain *aDomain) : + StructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this), + SPRNodalRecoveryModelInterface(), SpatialLocalizerInterface(this), + nPointsXY(4), + nPointsZ(2) { numberOfDofMans = 4; - nPointsXY = 4; - nPointsZ = 2; - numberOfGaussPoints = nPointsXY * nPointsZ; } FEInterpolation * -MITC4Shell :: giveInterpolation() const { return & interp_lin; } +MITC4Shell::giveInterpolation() const { return & interp_lin; } FEInterpolation * -MITC4Shell :: giveInterpolation(DofIDItem id) const +MITC4Shell::giveInterpolation(DofIDItem id) const { return & interp_lin; } Interface * -MITC4Shell :: giveInterface(InterfaceType interface) +MITC4Shell::giveInterface(InterfaceType interface) { if ( interface == ZZNodalRecoveryModelInterfaceType ) { - return static_cast< ZZNodalRecoveryModelInterface * >(this); + return static_cast< ZZNodalRecoveryModelInterface * >( this ); } else if ( interface == SPRNodalRecoveryModelInterfaceType ) { - return static_cast< SPRNodalRecoveryModelInterface * >(this); + return static_cast< SPRNodalRecoveryModelInterface * >( this ); } else if ( interface == NodalAveragingRecoveryModelInterfaceType ) { - return static_cast< NodalAveragingRecoveryModelInterface * >(this); + return static_cast< NodalAveragingRecoveryModelInterface * >( this ); } else if ( interface == SpatialLocalizerInterfaceType ) { - return static_cast< SpatialLocalizerInterface * >(this); + return static_cast< SpatialLocalizerInterface * >( this ); } - return NULL; + return nullptr; } void -MITC4Shell :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) +MITC4Shell::SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) { pap.resize(numberOfDofMans); for ( int i = 1; i <= numberOfDofMans; i++ ) { @@ -108,7 +109,7 @@ MITC4Shell :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) void -MITC4Shell :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) +MITC4Shell::SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) { int found = 0; answer.resize(1); @@ -128,280 +129,163 @@ MITC4Shell :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int -MITC4Shell :: SPRNodalRecoveryMI_giveNumberOfIP() +MITC4Shell::SPRNodalRecoveryMI_giveNumberOfIP() { return this->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints(); } SPRPatchType -MITC4Shell :: SPRNodalRecoveryMI_givePatchType() +MITC4Shell::SPRNodalRecoveryMI_givePatchType() { return SPRPatchType_3dBiLin; } void -MITC4Shell :: computeGaussPoints() -// Sets up the array containing the eight Gauss points of the receiver. +MITC4Shell::computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 10) ); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 10); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], nPointsXY, nPointsZ, this); } } -void -MITC4Shell :: giveDirectorVectors(FloatArray &V1, FloatArray &V2, FloatArray &V3, FloatArray &V4) +std::array< FloatArrayF< 3 >, 4 > +MITC4Shell::giveDirectorVectors() { if ( directorType == 0 ) { // normal to the midplane - FloatArray e1, e2, e3; - this->computeLocalBaseVectors(e1, e2, e3); - V1 = e3; - V2 = e3; - V3 = e3; - V4 = e3; + auto e = this->computeLocalBaseVectors(); + return { e [ 2 ], e [ 2 ], e [ 2 ], e [ 2 ] }; } else if ( directorType == 1 ) { // nodal average - FloatArray e1, e2, e3; - FloatMatrix directors; - FloatArray nodeDir; - nodeDir.resize(3); - directors.resize(3, 4); int csNum = this->giveCrossSection()->giveNumber(); - // OOFEM_ERROR("DirectorType 1 not implemented yet."); + std::array< FloatArrayF< 3 >, 4 >directors; + IntArray neighbours; ConnectivityTable *conTable = this->giveDomain()->giveConnectivityTable(); IntArray node(1); - int count; for ( int i = 1; i <= 4; i++ ) { - count = 0; - nodeDir.zero(); + FloatArrayF< 3 >nodeDir; node.at(1) = this->giveNode(i)->giveNumber(); conTable->giveNodeNeighbourList(neighbours, node); for ( int j = 1; j <= neighbours.giveSize(); j++ ) { - MITC4Shell *neighbour = dynamic_cast< MITC4Shell * >( this->giveDomain()->giveElement( neighbours.at(j) ) ); + auto neighbour = dynamic_cast< MITC4Shell * >( this->giveDomain()->giveElement(neighbours.at(j) ) ); if ( neighbour ) { if ( neighbour->giveCrossSection()->giveNumber() == csNum ) { - neighbour->computeLocalBaseVectors(e1, e2, e3); - nodeDir.add(e3); - count++; + auto e = neighbour->computeLocalBaseVectors(); + nodeDir += e [ 2 ]; } } } - directors.at(1, i) = nodeDir.at(1) / count; - directors.at(2, i) = nodeDir.at(2) / count; - directors.at(3, i) = nodeDir.at(3) / count; + directors [ i-1 ] = normalize(nodeDir); } - V1.beColumnOf(directors, 1); - V2.beColumnOf(directors, 2); - V3.beColumnOf(directors, 3); - V4.beColumnOf(directors, 4); - - V1.normalize(); - V2.normalize(); - V3.normalize(); - V4.normalize(); + return directors; } else if ( directorType == 2 ) { // specified at crosssection - V1.resize(3); - V2.resize(3); - V3.resize(3); - V4.resize(3); - FloatArray *c1, *c2, *c3, *c4; - c1 = this->giveNode(1)->giveCoordinates(); - c2 = this->giveNode(2)->giveCoordinates(); - c3 = this->giveNode(3)->giveCoordinates(); - c4 = this->giveNode(4)->giveCoordinates(); - V1.at(1) = this->giveCrossSection()->give(CS_DirectorVectorX, * c1, this, false); - V1.at(2) = this->giveCrossSection()->give(CS_DirectorVectorY, * c1, this, false); - V1.at(3) = this->giveCrossSection()->give(CS_DirectorVectorZ, * c1, this, false); - - V2.at(1) = this->giveCrossSection()->give(CS_DirectorVectorX, * c2, this, false); - V2.at(2) = this->giveCrossSection()->give(CS_DirectorVectorY, * c2, this, false); - V2.at(3) = this->giveCrossSection()->give(CS_DirectorVectorZ, * c2, this, false); - - V3.at(1) = this->giveCrossSection()->give(CS_DirectorVectorX, * c3, this, false); - V3.at(2) = this->giveCrossSection()->give(CS_DirectorVectorY, * c3, this, false); - V3.at(3) = this->giveCrossSection()->give(CS_DirectorVectorZ, * c3, this, false); - - V4.at(1) = this->giveCrossSection()->give(CS_DirectorVectorX, * c4, this, false); - V4.at(2) = this->giveCrossSection()->give(CS_DirectorVectorY, * c4, this, false); - V4.at(3) = this->giveCrossSection()->give(CS_DirectorVectorZ, * c4, this, false); - - V1.normalize(); - V2.normalize(); - V3.normalize(); - V4.normalize(); + std::array< FloatArrayF< 3 >, 4 >V; + for ( int i = 0; i < 4; ++i ) { + const auto &c = this->giveNode(i + 1)->giveCoordinates(); + FloatArrayF< 3 >v = { + this->giveCrossSection()->give(CS_DirectorVectorX, c, this, false), + this->giveCrossSection()->give(CS_DirectorVectorY, c, this, false), + this->giveCrossSection()->give(CS_DirectorVectorZ, c, this, false), + }; + V [ i ] = normalize(v); + } + return V; } else { - OOFEM_ERROR("Unsupported directorType"); + throw std::runtime_error("Unsupported directorType"); } } -void -MITC4Shell :: giveLocalDirectorVectors(FloatArray &V1, FloatArray &V2, FloatArray &V3, FloatArray &V4) +std::array< FloatArrayF< 3 >, 4 > +MITC4Shell::giveLocalDirectorVectors() { - FloatArray V1g, V2g, V3g, V4g; - this->giveDirectorVectors(V1g, V2g, V3g, V4g); - this->computeGtoLRotationMatrix(); - - V1.beProductOf(GtoLRotationMatrix, V1g); - V2.beProductOf(GtoLRotationMatrix, V2g); - V3.beProductOf(GtoLRotationMatrix, V3g); - V4.beProductOf(GtoLRotationMatrix, V4g); + auto Vg = this->giveDirectorVectors(); + return { + dot(GtoLRotationMatrix, Vg [ 0 ]), + dot(GtoLRotationMatrix, Vg [ 1 ]), + dot(GtoLRotationMatrix, Vg [ 2 ]), + dot(GtoLRotationMatrix, Vg [ 3 ]), + }; } void -MITC4Shell :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +MITC4Shell::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // Returns the [6x24] displacement interpolation matrix {N} of the receiver, // evaluated at gp. // Zeroes in rows 4, 5, 6. { - FloatArray h(4); - - interp_lin.evalN( h, iLocCoord, FEIElementGeometryWrapper(this) ); - - double a1, a2, a3, a4; - this->giveThickness(a1, a2, a3, a4); - - FloatArray V1, V2, V3, V4; - this->giveLocalDirectorVectors(V1, V2, V3, V4); - - FloatArray e2 = { - 0, 1, 0 - }; + auto h = interp_lin.evalN(FloatArrayF< 3 >(iLocCoord) [ { 0, 1 } ]); + auto a = this->giveThickness(); + auto V = this->giveLocalDirectorVectors(); - FloatArray V11(3), V12(3), V13(3), V14(3), V21(3), V22(3), V23(3), V24(3); - V11.beVectorProductOf(e2, V1); - V11.normalize(); - V12.beVectorProductOf(e2, V2); - V12.normalize(); - V13.beVectorProductOf(e2, V3); - V13.normalize(); - V14.beVectorProductOf(e2, V4); - V14.normalize(); - - V21.beVectorProductOf(V1, V11); - V22.beVectorProductOf(V2, V12); - V23.beVectorProductOf(V3, V13); - V24.beVectorProductOf(V4, V14); + FloatArrayF< 3 >e2 = { 0., 1., 0. }; - answer.resize(6, 24); + answer.resize(6, 6 * 4); answer.zero(); - - answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = h.at(1); - answer.at(1, 4) = -iLocCoord.at(3) / 2.0 *a1 *h.at(1) * V21.at(1); - answer.at(1, 5) = iLocCoord.at(3) / 2.0 *a1 *h.at(1) * V11.at(1); - answer.at(2, 4) = -iLocCoord.at(3) / 2.0 *a1 *h.at(1) * V21.at(2); - answer.at(2, 5) = iLocCoord.at(3) / 2.0 *a1 *h.at(1) * V11.at(2); - answer.at(3, 4) = -iLocCoord.at(3) / 2.0 *a1 *h.at(1) * V21.at(3); - answer.at(3, 5) = iLocCoord.at(3) / 2.0 *a1 *h.at(1) * V11.at(3); - - answer.at(1, 7) = answer.at(2, 8) = answer.at(3, 9) = h.at(2); - answer.at(1, 10) = -iLocCoord.at(3) / 2.0 *a2 *h.at(2) * V22.at(1); - answer.at(1, 11) = iLocCoord.at(3) / 2.0 *a2 *h.at(2) * V12.at(1); - answer.at(2, 10) = -iLocCoord.at(3) / 2.0 *a2 *h.at(2) * V22.at(2); - answer.at(2, 11) = iLocCoord.at(3) / 2.0 *a2 *h.at(2) * V12.at(2); - answer.at(3, 10) = -iLocCoord.at(3) / 2.0 *a2 *h.at(2) * V22.at(3); - answer.at(3, 11) = iLocCoord.at(3) / 2.0 *a2 *h.at(2) * V12.at(3); - - answer.at(1, 13) = answer.at(2, 14) = answer.at(3, 15) = h.at(3); - answer.at(1, 16) = -iLocCoord.at(3) / 2.0 *a3 *h.at(3) * V23.at(1); - answer.at(1, 17) = iLocCoord.at(3) / 2.0 *a3 *h.at(3) * V13.at(1); - answer.at(2, 16) = -iLocCoord.at(3) / 2.0 *a3 *h.at(3) * V23.at(2); - answer.at(2, 17) = iLocCoord.at(3) / 2.0 *a3 *h.at(3) * V13.at(2); - answer.at(3, 16) = -iLocCoord.at(3) / 2.0 *a3 *h.at(3) * V23.at(3); - answer.at(3, 17) = iLocCoord.at(3) / 2.0 *a3 *h.at(3) * V13.at(3); - - answer.at(1, 19) = answer.at(2, 20) = answer.at(3, 21) = h.at(4); - answer.at(1, 23) = -iLocCoord.at(3) / 2.0 *a4 *h.at(4) * V24.at(1); - answer.at(1, 24) = iLocCoord.at(3) / 2.0 *a4 *h.at(4) * V14.at(1); - answer.at(2, 23) = -iLocCoord.at(3) / 2.0 *a4 *h.at(4) * V24.at(2); - answer.at(2, 24) = iLocCoord.at(3) / 2.0 *a4 *h.at(4) * V14.at(2); - answer.at(3, 23) = -iLocCoord.at(3) / 2.0 *a4 *h.at(4) * V24.at(3); - answer.at(3, 24) = iLocCoord.at(3) / 2.0 *a4 *h.at(4) * V14.at(3); + for ( int i = 0; i < 4; ++i ) { + auto Ve = normalize( cross(e2, V [ i ]) ); + auto VVe = cross(V [ i ], Ve); + answer.at(1, 1 + i * 6) = answer.at(2, 2 + i * 6) = answer.at(3, 3 + i * 6) = h [ i ]; + answer.at(1, 4 + i * 6) = -iLocCoord.at(3) / 2.0 * a [ i ] * h [ i ] * VVe.at(1); + answer.at(1, 5 + i * 6) = iLocCoord.at(3) / 2.0 * a [ i ] * h [ i ] * Ve.at(1); + answer.at(2, 4 + i * 6) = -iLocCoord.at(3) / 2.0 * a [ i ] * h [ i ] * VVe.at(2); + answer.at(2, 5 + i * 6) = iLocCoord.at(3) / 2.0 * a [ i ] * h [ i ] * Ve.at(2); + answer.at(3, 4 + i * 6) = -iLocCoord.at(3) / 2.0 * a [ i ] * h [ i ] * VVe.at(3); + answer.at(3, 5 + i * 6) = iLocCoord.at(3) / 2.0 * a [ i ] * h [ i ] * Ve.at(3); + } } void -MITC4Shell :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +MITC4Shell::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - StructuralCrossSection *scs = dynamic_cast< StructuralCrossSection * >( this->giveCrossSection() ); - //SimpleCrossSection *cs = dynamic_cast< SimpleCrossSection * >( this->giveCrossSection() ); - scs->give3dDegeneratedShellStiffMtrx(answer, rMode, gp, tStep); + auto scs = dynamic_cast< StructuralCrossSection * >( this->giveCrossSection() ); + //auto cs = dynamic_cast< SimpleCrossSection * >( this->giveCrossSection() ); + answer = scs->give3dDegeneratedShellStiffMtrx(rMode, gp, tStep); } -void -MITC4Shell :: giveNodeCoordinates(double &x1, double &x2, double &x3, double &x4, - double &y1, double &y2, double &y3, double &y4, - double &z1, double &z2, double &z3, double &z4) +std::array< FloatArrayF< 3 >, 4 > +MITC4Shell::giveNodeCoordinates() { - FloatArray nc1(3), nc2(3), nc3(3), nc4(3); - - this->giveLocalCoordinates( nc1, * ( this->giveNode(1)->giveCoordinates() ) ); - this->giveLocalCoordinates( nc2, * ( this->giveNode(2)->giveCoordinates() ) ); - this->giveLocalCoordinates( nc3, * ( this->giveNode(3)->giveCoordinates() ) ); - this->giveLocalCoordinates( nc4, * ( this->giveNode(4)->giveCoordinates() ) ); - - x1 = nc1.at(1); - x2 = nc2.at(1); - x3 = nc3.at(1); - x4 = nc4.at(1); - - y1 = nc1.at(2); - y2 = nc2.at(2); - y3 = nc3.at(2); - y4 = nc4.at(2); - - z1 = nc1.at(3); - z2 = nc2.at(3); - z3 = nc3.at(3); - z4 = nc4.at(3); + std::array< FloatArrayF< 3 >, 4 >c; + for ( int i = 0; i < 4; ++i ) { + c [ i ] = this->giveLocalCoordinates( this->giveNode(i + 1)->giveCoordinates() ); + } + return c; } -void -MITC4Shell :: giveLocalCoordinates(FloatArray &answer, FloatArray &global) -// Returns global coordinates given in global vector -// transformed into local coordinate system of the -// receiver +FloatArrayF< 3 > +MITC4Shell::giveLocalCoordinates(const FloatArrayF< 3 > &global) { - FloatArray offset; - // test the parametr - if ( global.giveSize() != 3 ) { - OOFEM_ERROR("cannot transform coordinates - size mismatch"); - exit(1); - } - - this->computeGtoLRotationMatrix(); - - offset = global; - offset.subtract( * this->giveNode(1)->giveCoordinates() ); - answer.beProductOf(GtoLRotationMatrix, offset); + auto offset = global - FloatArrayF< 3 >( this->giveNode(1)->giveCoordinates() ); + return dot(GtoLRotationMatrix, offset); } -IRResultType -MITC4Shell :: initializeFrom(InputRecord *ir) +void +MITC4Shell::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralElement::initializeFrom(ir); IR_GIVE_OPTIONAL_FIELD(ir, nPointsXY, _IFT_Element_nip); IR_GIVE_OPTIONAL_FIELD(ir, nPointsZ, _IFT_MITC4Shell_nipZ); - IR_GIVE_OPTIONAL_FIELD(ir, nlGeometry, _IFT_NLStructuralElement_nlgeoflag); + //@todo: extend for nonlinear geometry + //IR_GIVE_OPTIONAL_FIELD(ir, nlGeometry, _IFT_NLStructuralElement_nlgeoflag); directorType = 0; // default IR_GIVE_OPTIONAL_FIELD(ir, directorType, _IFT_MITC4Shell_directorType); - - return this->NLStructuralElement :: initializeFrom(ir); } void -MITC4Shell :: giveDofManDofIDMask(int inode, IntArray &answer) const +MITC4Shell::giveDofManDofIDMask(int inode, IntArray &answer) const { answer = { D_u, D_v, D_w, R_u, R_v, R_w @@ -409,75 +293,60 @@ MITC4Shell :: giveDofManDofIDMask(int inode, IntArray &answer) const } double -MITC4Shell :: computeVolumeAround(GaussPoint *gp) -// Returns the portion of the receiver which is attached to gp. +MITC4Shell::computeVolumeAround(GaussPoint *gp) { - double detJ, weight; - FloatMatrix jacobianMatrix(3, 3); - - FloatArray lcoords(3); - lcoords.at(1) = gp->giveNaturalCoordinate(1); - lcoords.at(2) = gp->giveNaturalCoordinate(2); - lcoords.at(3) = gp->giveNaturalCoordinate(3); - - weight = gp->giveWeight(); - - this->giveJacobian(lcoords, jacobianMatrix); + FloatArrayF< 3 >lcoords = { + gp->giveNaturalCoordinate(1), + gp->giveNaturalCoordinate(2), + gp->giveNaturalCoordinate(3), + }; - detJ = jacobianMatrix.giveDeterminant(); - return detJ * weight; + auto jacobianMatrix = this->giveJacobian(lcoords); + return det(jacobianMatrix) * gp->giveWeight(); } -void -MITC4Shell :: giveJacobian(FloatArray lcoords, FloatMatrix &jacobianMatrix) -// Returns the jacobianMatrix +FloatMatrixF< 3, 3 > +MITC4Shell::giveJacobian(const FloatArrayF< 3 > &lcoords) { - FloatArray h(4); - FloatMatrix dn(4, 2); - FloatMatrix dndx(4, 2); + // derivatives of interpolation functions + auto dn = interp_lin.evaldNdxi(lcoords [ { 0, 1 } ]); + auto hk1 = dn.row< 0 >(); // dh(r1,r2)/dr1 + auto hk2 = dn.row< 1 >(); // dh(r1,r2)/dr2 - jacobianMatrix.resize(3, 3); - // get node coordinates - double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4; - this->giveNodeCoordinates(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4); + // interpolation functions - h(r1,r2) + //auto [h1, h2, h3, h4] = interp_lin.evalN(lcoords[{0, 1}]); + auto h = interp_lin.evalN(lcoords [ { 0, 1 } ]); + double h1 = h [ 0 ]; + double h2 = h [ 1 ]; + double h3 = h [ 2 ]; + double h4 = h [ 3 ]; + + //auto [a1, a2, a3, a4] = this->giveThickness(); + auto a = this->giveThickness(); + double a1 = a [ 0 ]; + double a2 = a [ 1 ]; + double a3 = a [ 2 ]; + double a4 = a [ 3 ]; + // get node coordinates double r3 = lcoords.at(3); - - // get local director vector - FloatArray V1, V2, V3, V4; - this->giveLocalDirectorVectors(V1, V2, V3, V4); - - // get thickness - double a1, a2, a3, a4; - this->giveThickness(a1, a2, a3, a4); - - interp_lin.evalN( h, lcoords, FEIElementGeometryWrapper(this) ); - interp_lin.evaldNdxi(dn, lcoords, FEIElementGeometryWrapper(this) ); - - FloatArray hk1(4); - // derivatives of interpolation functions - // dh(r1,r2)/dr1 - hk1.at(1) = dn.at(1, 1); - hk1.at(2) = dn.at(2, 1); - hk1.at(3) = dn.at(3, 1); - hk1.at(4) = dn.at(4, 1); - - FloatArray hk2(4); - // dh(r1,r2)/dr2 - hk2.at(1) = dn.at(1, 2); - hk2.at(2) = dn.at(2, 2); - hk2.at(3) = dn.at(3, 2); - hk2.at(4) = dn.at(4, 2); - - double h1, h2, h3, h4; - // interpolation functions - h(r1,r2) - h1 = h.at(1); - h2 = h.at(2); - h3 = h.at(3); - h4 = h.at(4); + auto c = this->giveNodeCoordinates(); + //auto [x1, y1, z1] = c[0]; + //auto [x2, y2, z2] = c[1]; + //auto [x3, y3, z3] = c[2]; + //auto [x4, y4, z4] = c[3]; + double x1 = c [ 0 ] [ 0 ], y1 = c [ 0 ] [ 1 ]; + double x2 = c [ 1 ] [ 0 ], y2 = c [ 1 ] [ 1 ]; + double x3 = c [ 2 ] [ 0 ], y3 = c [ 2 ] [ 1 ]; + double x4 = c [ 3 ] [ 0 ], y4 = c [ 3 ] [ 1 ]; + + //auto [V1, V2, V3, V4] = this->giveLocalDirectorVectors(); + auto V = this->giveLocalDirectorVectors(); + auto V1 = V [ 0 ], V2 = V [ 1 ], V3 = V [ 2 ], V4 = V [ 3 ]; // Jacobian Matrix + FloatMatrixF< 3, 3 >jacobianMatrix; jacobianMatrix.at(1, 1) = hk1.at(1) * x1 + hk1.at(2) * x2 + hk1.at(3) * x3 + hk1.at(4) * x4 + r3 / 2. * ( a1 * hk1.at(1) * V1.at(1) + a2 * hk1.at(2) * V2.at(1) + a3 * hk1.at(3) * V3.at(1) + a4 * hk1.at(4) * V4.at(1) ); jacobianMatrix.at(1, 2) = hk1.at(1) * y1 + hk1.at(2) * y2 + hk1.at(3) * y3 + hk1.at(4) * y4 + r3 / 2. * ( a1 * hk1.at(1) * V1.at(2) + a2 * hk1.at(2) * V2.at(2) + a3 * hk1.at(3) * V3.at(2) + a4 * hk1.at(4) * V4.at(2) ); jacobianMatrix.at(1, 3) = r3 / 2. * ( a1 * hk1.at(1) * V1.at(3) + a2 * hk1.at(2) * V2.at(3) + a3 * hk1.at(3) * V3.at(3) + a4 * hk1.at(4) * V4.at(3) ); @@ -487,21 +356,22 @@ MITC4Shell :: giveJacobian(FloatArray lcoords, FloatMatrix &jacobianMatrix) jacobianMatrix.at(3, 1) = 1. / 2. * ( a1 * h1 * V1.at(1) + a2 * h2 * V2.at(1) + a3 * h3 * V3.at(1) + a4 * h4 * V4.at(1) ); jacobianMatrix.at(3, 2) = 1. / 2. * ( a1 * h1 * V1.at(2) + a2 * h2 * V2.at(2) + a3 * h3 * V3.at(2) + a4 * h4 * V4.at(2) ); jacobianMatrix.at(3, 3) = 1. / 2. * ( a1 * h1 * V1.at(3) + a2 * h2 * V2.at(3) + a3 * h3 * V3.at(3) + a4 * h4 * V4.at(3) ); + return jacobianMatrix; } void -MITC4Shell :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +MITC4Shell::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { // This element adds an additional stiffness for the so called drilling dofs. - NLStructuralElement :: computeStiffnessMatrix(answer, rMode, tStep); + StructuralElement::computeStiffnessMatrix(answer, rMode, tStep); - bool drillType = this->giveStructuralCrossSection()->give( CS_DrillingType, this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0) ); + bool drillType = this->giveStructuralCrossSection()->give(CS_DrillingType, this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0) ); if ( drillType == 1 ) { - double relDrillCoeff = this->giveStructuralCrossSection()->give( CS_RelDrillingStiffness, this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0) ); - FloatArray n; - IntArray drillDofs = { - 6, 12, 18, 24 - }; + double relDrillCoeff = this->giveStructuralCrossSection()->give(CS_RelDrillingStiffness, this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0) ); + if ( relDrillCoeff == 0.0 ) { + relDrillCoeff = 0.001; // default + } + int j = 1; while ( answer.at(j, j) == 0 ) { j++; @@ -514,45 +384,39 @@ MITC4Shell :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, } } - if ( relDrillCoeff == 0.0 ) { - relDrillCoeff = 0.001; // default - } drillCoeff *= relDrillCoeff; + IntArray drillDofs = { 6, 12, 18, 24 }; + auto drillStiffness = eye< 4 >() * drillCoeff; +#if 0 FloatMatrix drillStiffness; - drillStiffness.resize(4, 4); - drillStiffness.zero(); - for ( int i = 1; i <= 4; i++ ) { - drillStiffness.at(i, i) = drillCoeff; + for ( auto &gp : * integrationRulesArray [ 0 ] ) { + double dV = this->computeVolumeAround(gp); + // double drillCoeff = this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp); + double coeff = drillCoeff; + if ( this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp) > 0 ) { + drillCoeff *= this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp); + } + // Drilling stiffness is here for improved numerical properties + this->interp_lin.evalN(n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); + for ( int j = 0; j < 4; j++ ) { + n [ j ] -= 0.25; + } + drillStiffness.plusDyadSymmUpper(n, coeff * dV); } - - /* - * for ( GaussPoint *gp : *integrationRulesArray [ 0 ] ) { - * double dV = this->computeVolumeAround(gp); - * // double drillCoeff = this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp); - * double coeff = drillCoeff; - * if ( this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp)> 0) - * drillCoeff *= this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp); - * // Drilling stiffness is here for improved numerical properties - * this->interp_lin.evalN( n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); - * for ( int j = 0; j < 4; j++ ) { - * n(j) -= 0.25; - * } - * drillStiffness.plusDyadSymmUpper(n, coeff * dV); - * }*/ - - // drillStiffness.symmetrized(); + drillStiffness.symmetrized(); +#endif answer.assemble(drillStiffness, drillDofs); } } void -MITC4Shell :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +MITC4Shell::giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { // This element adds an additional stiffness for the so called drilling dofs. - NLStructuralElement :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); + StructuralElement::giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); - bool drillType = this->giveStructuralCrossSection()->give( CS_DrillingType, this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0) ); + bool drillType = this->giveStructuralCrossSection()->give(CS_DrillingType, this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0) ); if ( drillType == 1 ) { FloatArray n, tmp; @@ -563,22 +427,23 @@ MITC4Shell :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int this->computeVectorOf(VM_Total, tStep, tmp); drillUnknowns.beSubArrayOf(tmp, drillDofs); - /* - * for ( GaussPoint *gp : *integrationRulesArray [ 0 ] ) { - * double dV = this->computeVolumeAround(gp); - * // double drillCoeff = this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp); - * double coeff = drillCoeff; - * if ( this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp)> 0) - * drillCoeff *= this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp); - * - * this->interp_lin.evalN( n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); - * for ( int j = 0; j < 4; j++ ) { - * n(j) -= 0.25; - * } - * double dtheta = n.dotProduct(drillUnknowns); - * drillMoment.add(coeff * dV * dtheta, n); - * } - */ +#if 0 + for ( auto &gp : * integrationRulesArray [ 0 ] ) { + double dV = this->computeVolumeAround(gp); + // double drillCoeff = this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp); + double coeff = drillCoeff; + if ( this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp) > 0 ) { + drillCoeff *= this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp); + } + + this->interp_lin.evalN(n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); + for ( int j = 0; j < 4; j++ ) { + n [ j ] -= 0.25; + } + double dtheta = n.dotProduct(drillUnknowns); + drillMoment.add(coeff * dV * dtheta, n); + } +#endif FloatMatrix drillStiffness; drillStiffness.resize(4, 4); @@ -594,154 +459,135 @@ MITC4Shell :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int } void -MITC4Shell :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +MITC4Shell::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the [6x20] strain-displacement matrix {B} of the receiver, // evaluated at gp. { - FloatArray h(4); - FloatMatrix jacobianMatrix(3, 3); - FloatMatrix dn(4, 2); - FloatMatrix dndx(4, 2); + //auto [c1, c2, c3, c4] = this->giveNodeCoordinates(); + auto c = this->giveNodeCoordinates(); + auto c1 = c [ 0 ], c2 = c [ 1 ], c3 = c [ 2 ], c4 = c [ 3 ]; - answer.resize(6, 24); - // get node coordinates - double x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4; - this->giveNodeCoordinates(x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4); - - // get gp coordinates double r1 = gp->giveNaturalCoordinate(1); double r2 = gp->giveNaturalCoordinate(2); double r3 = gp->giveNaturalCoordinate(3); + FloatArrayF< 3 >lcoords = { r1, r2, r3 }; - FloatArray lcoords(3); - lcoords.at(1) = r1; - lcoords.at(2) = r2; - lcoords.at(3) = r3; + //auto [a1, a2, a3, a4] = this->giveThickness(); + auto a = this->giveThickness(); + double a1 = a [ 0 ], a2 = a [ 1 ], a3 = a [ 2 ], a4 = a [ 3 ]; - // get director vector - FloatArray V1, V2, V3, V4; - this->giveLocalDirectorVectors(V1, V2, V3, V4); + //auto h = interp_lin.evalN(lcoords); + //auto dn = interp_lin.evaldNdxi(lcoords); - // get thickness - double a1, a2, a3, a4; - this->giveThickness(a1, a2, a3, a4); + //auto [hkx, hky] = this->givedNdx(lcoords); + auto hk = this->givedNdx(lcoords); + auto hkx = hk [ 0 ], hky = hk [ 1 ]; - interp_lin.evalN( h, lcoords, FEIElementGeometryWrapper(this) ); - interp_lin.evaldNdxi(dn, lcoords, FEIElementGeometryWrapper(this) ); + auto J = this->giveJacobian(lcoords); + auto invJ = inv(J); + double sb = 2 * invJ.at(1, 1) * invJ.at(3, 3); + double sa = 2 * invJ.at(1, 2) * invJ.at(3, 3); + double cb = 2 * invJ.at(2, 1) * invJ.at(3, 3); + double ca = 2 * invJ.at(2, 2) * invJ.at(3, 3); - FloatArray hkx, hky; - this->givedNdx(hkx, hky, lcoords); + //auto [V1, V2, V3, V4] = this->giveLocalDirectorVectors(); + auto V = this->giveLocalDirectorVectors(); + auto V1 = V [ 0 ], V2 = V [ 1 ], V3 = V [ 2 ], V4 = V [ 3 ]; - // Jacobian Matrix - this->giveJacobian(lcoords, jacobianMatrix); - FloatMatrix inv(3, 3); - FloatMatrix inv2(2, 2); - inv.beInverseOf(jacobianMatrix); - - double sb = 2 * inv.at(1, 1) * inv.at(3, 3); - double sa = 2 * inv.at(1, 2) * inv.at(3, 3); - double cb = 2 * inv.at(2, 1) * inv.at(3, 3); - double ca = 2 * inv.at(2, 2) * inv.at(3, 3); - - FloatArray e2 = { - 0, 1, 0 - }; - - FloatArray V11(3), V12(3), V13(3), V14(3), V21(3), V22(3), V23(3), V24(3); - V11.beVectorProductOf(e2, V1); - V11.normalize(); - V12.beVectorProductOf(e2, V2); - V12.normalize(); - V13.beVectorProductOf(e2, V3); - V13.normalize(); - V14.beVectorProductOf(e2, V4); - V14.normalize(); + FloatArrayF< 3 >e2 = { 0., 1., 0. }; - V21.beVectorProductOf(V1, V11); - V22.beVectorProductOf(V2, V12); - V23.beVectorProductOf(V3, V13); - V24.beVectorProductOf(V4, V14); + auto V11 = normalize( cross(e2, V1) ); + auto V12 = normalize( cross(e2, V2) ); + auto V13 = normalize( cross(e2, V3) ); + auto V14 = normalize( cross(e2, V4) ); + auto V21 = cross(V1, V11); + auto V22 = cross(V2, V12); + auto V23 = cross(V3, V13); + auto V24 = cross(V4, V14); + answer.resize(6, 24); answer.zero(); + answer.at(4, 1) = 1. / 32. * ( ( a1 * V1.at(1) + a2 * V2.at(1) ) * ( cb * ( 1. + r2 ) ) + ( a1 * V1.at(1) + a4 * V4.at(1) ) * ( ca * ( 1. + r1 ) ) ); answer.at(4, 2) = 1. / 32. * ( ( a1 * V1.at(2) + a2 * V2.at(2) ) * ( cb * ( 1. + r2 ) ) + ( a1 * V1.at(2) + a4 * V4.at(2) ) * ( ca * ( 1. + r1 ) ) ); answer.at(4, 3) = 1. / 32. * ( ( a1 * V1.at(3) + a2 * V2.at(3) ) * ( cb * ( 1. + r2 ) ) + ( a1 * V1.at(3) + a4 * V4.at(3) ) * ( ca * ( 1. + r1 ) ) ); - answer.at(4, 4) = -a1 / 32. * ( ( V21.dotProduct({ x1 - x2, y1 - y2, z1 - z2 }) * ( cb * ( 1. + r2 ) ) ) + ( V21.dotProduct({ x1 - x4, y1 - y4, z1 - z4 }) * ( ca * ( 1. + r1 ) ) ) ); - answer.at(4, 5) = a1 / 32. * ( ( V11.dotProduct({ x1 - x2, y1 - y2, z1 - z2 }) * ( cb * ( 1. + r2 ) ) ) + ( V11.dotProduct({ x1 - x4, y1 - y4, z1 - z4 }) * ( ca * ( 1. + r1 ) ) ) ); + answer.at(4, 4) = -a1 / 32. * ( ( dot(V21, c1 - c2) * ( cb * ( 1. + r2 ) ) ) + ( dot(V21, c1 - c4) * ( ca * ( 1. + r1 ) ) ) ); + answer.at(4, 5) = a1 / 32. * ( ( dot(V11, c1 - c2) * ( cb * ( 1. + r2 ) ) ) + ( dot(V11, c1 - c4) * ( ca * ( 1. + r1 ) ) ) ); answer.at(4, 7) = 1. / 32. * ( -( a1 * V1.at(1) + a2 * V2.at(1) ) * ( cb * ( 1. + r2 ) ) + ( a2 * V2.at(1) + a3 * V3.at(1) ) * ( ca * ( 1. - r1 ) ) ); answer.at(4, 8) = 1. / 32. * ( -( a1 * V1.at(2) + a2 * V2.at(2) ) * ( cb * ( 1. + r2 ) ) + ( a2 * V2.at(2) + a3 * V3.at(2) ) * ( ca * ( 1. - r1 ) ) ); answer.at(4, 9) = 1. / 32. * ( -( a1 * V1.at(3) + a2 * V2.at(3) ) * ( cb * ( 1. + r2 ) ) + ( a2 * V2.at(3) + a3 * V3.at(3) ) * ( ca * ( 1. - r1 ) ) ); - answer.at(4, 10) = -a1 / 32. * ( ( V21.dotProduct({ x1 - x2, y1 - y2, z1 - z2 }) * ( cb * ( 1. + r2 ) ) ) + ( V21.dotProduct({ x2 - x3, y2 - y3, z2 - z3 }) * ( ca * ( 1. - r1 ) ) ) ); - answer.at(4, 11) = a1 / 32. * ( ( V11.dotProduct({ x1 - x2, y1 - y2, z1 - z2 }) * ( cb * ( 1. + r2 ) ) ) + ( V11.dotProduct({ x2 - x3, y2 - y3, z2 - z3 }) * ( ca * ( 1. - r1 ) ) ) ); + answer.at(4, 10) = -a1 / 32. * ( ( dot(V21, c1 - c2) * ( cb * ( 1. + r2 ) ) ) + ( dot(V21, c2 - c3) * ( ca * ( 1. - r1 ) ) ) ); + answer.at(4, 11) = a1 / 32. * ( ( dot(V11, c1 - c2) * ( cb * ( 1. + r2 ) ) ) + ( dot(V11, c2 - c3) * ( ca * ( 1. - r1 ) ) ) ); answer.at(4, 13) = 1. / 32. * ( -( a3 * V3.at(1) + a4 * V4.at(1) ) * ( cb * ( 1. - r2 ) ) - ( a2 * V2.at(1) + a3 * V3.at(1) ) * ( ca * ( 1. - r1 ) ) ); answer.at(4, 14) = 1. / 32. * ( -( a3 * V3.at(2) + a4 * V4.at(2) ) * ( cb * ( 1. - r2 ) ) - ( a2 * V2.at(2) + a3 * V3.at(2) ) * ( ca * ( 1. - r1 ) ) ); answer.at(4, 15) = 1. / 32. * ( -( a3 * V3.at(3) + a4 * V4.at(3) ) * ( cb * ( 1. - r2 ) ) - ( a2 * V2.at(3) + a3 * V3.at(3) ) * ( ca * ( 1. - r1 ) ) ); - answer.at(4, 16) = -a1 / 32. * ( ( V21.dotProduct({ x4 - x3, y4 - y3, z4 - z3 }) * ( cb * ( 1. - r2 ) ) ) + ( V21.dotProduct({ x2 - x3, y2 - y3, z2 - z3 }) * ( ca * ( 1. - r1 ) ) ) ); - answer.at(4, 17) = a1 / 32. * ( ( V11.dotProduct({ x4 - x3, y4 - y3, z4 - z3 }) * ( cb * ( 1. - r2 ) ) ) + ( V11.dotProduct({ x2 - x3, y2 - y3, z2 - z3 }) * ( ca * ( 1. - r1 ) ) ) ); + answer.at(4, 16) = -a1 / 32. * ( ( dot(V21, c4 - c3) * ( cb * ( 1. - r2 ) ) ) + ( dot(V21, c2 - c3) * ( ca * ( 1. - r1 ) ) ) ); + answer.at(4, 17) = a1 / 32. * ( ( dot(V11, c4 - c3) * ( cb * ( 1. - r2 ) ) ) + ( dot(V11, c2 - c3) * ( ca * ( 1. - r1 ) ) ) ); answer.at(4, 19) = 1. / 32. * ( ( a3 * V3.at(1) + a4 * V4.at(1) ) * ( cb * ( 1. - r2 ) ) - ( a1 * V1.at(1) + a4 * V4.at(1) ) * ( ca * ( 1. + r1 ) ) ); answer.at(4, 20) = 1. / 32. * ( ( a3 * V3.at(2) + a4 * V4.at(2) ) * ( cb * ( 1. - r2 ) ) - ( a1 * V1.at(2) + a4 * V4.at(2) ) * ( ca * ( 1. + r1 ) ) ); answer.at(4, 21) = 1. / 32. * ( ( a3 * V3.at(3) + a4 * V4.at(3) ) * ( cb * ( 1. - r2 ) ) - ( a1 * V1.at(3) + a4 * V4.at(3) ) * ( ca * ( 1. + r1 ) ) ); - answer.at(4, 22) = -a1 / 32. * ( ( V21.dotProduct({ x4 - x3, y4 - y3, z4 - z3 }) * ( cb * ( 1. - r2 ) ) ) + ( V21.dotProduct({ x1 - x4, y1 - y4, z1 - z4 }) * ( ca * ( 1. + r1 ) ) ) ); - answer.at(4, 23) = a1 / 32. * ( ( V11.dotProduct({ x4 - x3, y4 - y3, z4 - z3 }) * ( cb * ( 1. - r2 ) ) ) + ( V11.dotProduct({ x1 - x4, y1 - y4, z1 - z4 }) * ( ca * ( 1. + r1 ) ) ) ); + answer.at(4, 22) = -a1 / 32. * ( ( dot(V21, c4 - c3) * ( cb * ( 1. - r2 ) ) ) + ( dot(V21, c1 - c4) * ( ca * ( 1. + r1 ) ) ) ); + answer.at(4, 23) = a1 / 32. * ( ( dot(V11, c4 - c3) * ( cb * ( 1. - r2 ) ) ) + ( dot(V11, c1 - c4) * ( ca * ( 1. + r1 ) ) ) ); answer.at(5, 1) = 1. / 32. * ( ( a1 * V1.at(1) + a2 * V2.at(1) ) * ( sb * ( 1. + r2 ) ) + ( a1 * V1.at(1) + a4 * V4.at(1) ) * ( sa * ( 1. + r1 ) ) ); answer.at(5, 2) = 1. / 32. * ( ( a1 * V1.at(2) + a2 * V2.at(2) ) * ( sb * ( 1. + r2 ) ) + ( a1 * V1.at(2) + a4 * V4.at(2) ) * ( sa * ( 1. + r1 ) ) ); answer.at(5, 3) = 1. / 32. * ( ( a1 * V1.at(3) + a2 * V2.at(3) ) * ( sb * ( 1. + r2 ) ) + ( a1 * V1.at(3) + a4 * V4.at(3) ) * ( sa * ( 1. + r1 ) ) ); - answer.at(5, 4) = -a1 / 32. * ( ( V21.dotProduct({ x1 - x2, y1 - y2, z1 - z2 }) * ( sb * ( 1. + r2 ) ) ) + ( V21.dotProduct({ x1 - x4, y1 - y4, z1 - z4 }) * ( sa * ( 1. + r1 ) ) ) ); - answer.at(5, 5) = a1 / 32. * ( ( V11.dotProduct({ x1 - x2, y1 - y2, z1 - z2 }) * ( sb * ( 1. + r2 ) ) ) + ( V11.dotProduct({ x1 - x4, y1 - y4, z1 - z4 }) * ( sa * ( 1. + r1 ) ) ) ); + answer.at(5, 4) = -a1 / 32. * ( ( dot(V21, c1 - c2) * ( sb * ( 1. + r2 ) ) ) + ( dot(V21, c1 - c4) * ( sa * ( 1. + r1 ) ) ) ); + answer.at(5, 5) = a1 / 32. * ( ( dot(V11, c1 - c2) * ( sb * ( 1. + r2 ) ) ) + ( dot(V11, c1 - c4) * ( sa * ( 1. + r1 ) ) ) ); answer.at(5, 7) = 1. / 32. * ( -( a1 * V1.at(1) + a2 * V2.at(1) ) * ( sb * ( 1. + r2 ) ) + ( a2 * V2.at(1) + a3 * V3.at(1) ) * ( sa * ( 1. - r1 ) ) ); answer.at(5, 8) = 1. / 32. * ( -( a1 * V1.at(2) + a2 * V2.at(2) ) * ( sb * ( 1. + r2 ) ) + ( a2 * V2.at(2) + a3 * V3.at(2) ) * ( sa * ( 1. - r1 ) ) ); answer.at(5, 9) = 1. / 32. * ( -( a1 * V1.at(3) + a2 * V2.at(3) ) * ( sb * ( 1. + r2 ) ) + ( a2 * V2.at(3) + a3 * V3.at(3) ) * ( sa * ( 1. - r1 ) ) ); - answer.at(5, 10) = -a1 / 32. * ( ( V21.dotProduct({ x1 - x2, y1 - y2, z1 - z2 }) * ( sb * ( 1. + r2 ) ) ) + ( V21.dotProduct({ x2 - x3, y2 - y3, z2 - z3 }) * ( sa * ( 1. - r1 ) ) ) ); - answer.at(5, 11) = a1 / 32. * ( ( V11.dotProduct({ x1 - x2, y1 - y2, z1 - z2 }) * ( sb * ( 1. + r2 ) ) ) + ( V11.dotProduct({ x2 - x3, y2 - y3, z2 - z3 }) * ( sa * ( 1. - r1 ) ) ) ); + answer.at(5, 10) = -a1 / 32. * ( ( dot(V21, c1 - c2) * ( sb * ( 1. + r2 ) ) ) + ( dot(V21, c2 - c3) * ( sa * ( 1. - r1 ) ) ) ); + answer.at(5, 11) = a1 / 32. * ( ( dot(V11, c1 - c2) * ( sb * ( 1. + r2 ) ) ) + ( dot(V11, c2 - c3) * ( sa * ( 1. - r1 ) ) ) ); answer.at(5, 13) = 1. / 32. * ( -( a3 * V3.at(1) + a4 * V4.at(1) ) * ( sb * ( 1. - r2 ) ) - ( a2 * V2.at(1) + a3 * V3.at(1) ) * ( sa * ( 1. - r1 ) ) ); answer.at(5, 14) = 1. / 32. * ( -( a3 * V3.at(2) + a4 * V4.at(2) ) * ( sb * ( 1. - r2 ) ) - ( a2 * V2.at(2) + a3 * V3.at(2) ) * ( sa * ( 1. - r1 ) ) ); answer.at(5, 15) = 1. / 32. * ( -( a3 * V3.at(3) + a4 * V4.at(3) ) * ( sb * ( 1. - r2 ) ) - ( a2 * V2.at(3) + a3 * V3.at(3) ) * ( sa * ( 1. - r1 ) ) ); - answer.at(5, 16) = -a1 / 32. * ( ( V21.dotProduct({ x4 - x3, y4 - y3, z4 - z3 }) * ( sb * ( 1. - r2 ) ) ) + ( V21.dotProduct({ x2 - x3, y2 - y3, z2 - z3 }) * ( sa * ( 1. - r1 ) ) ) ); - answer.at(5, 17) = a1 / 32. * ( ( V11.dotProduct({ x4 - x3, y4 - y3, z4 - z3 }) * ( sb * ( 1. - r2 ) ) ) + ( V11.dotProduct({ x2 - x3, y2 - y3, z2 - z3 }) * ( sa * ( 1. - r1 ) ) ) ); + answer.at(5, 16) = -a1 / 32. * ( ( dot(V21, c4 - c3) * ( sb * ( 1. - r2 ) ) ) + ( dot(V21, c2 - c3) * ( sa * ( 1. - r1 ) ) ) ); + answer.at(5, 17) = a1 / 32. * ( ( dot(V11, c4 - c3) * ( sb * ( 1. - r2 ) ) ) + ( dot(V11, c2 - c3) * ( sa * ( 1. - r1 ) ) ) ); answer.at(5, 19) = 1. / 32. * ( ( a3 * V3.at(1) + a4 * V4.at(1) ) * ( sb * ( 1. - r2 ) ) - ( a1 * V1.at(1) + a4 * V4.at(1) ) * ( sa * ( 1. + r1 ) ) ); answer.at(5, 20) = 1. / 32. * ( ( a3 * V3.at(2) + a4 * V4.at(2) ) * ( sb * ( 1. - r2 ) ) - ( a1 * V1.at(2) + a4 * V4.at(2) ) * ( sa * ( 1. + r1 ) ) ); answer.at(5, 21) = 1. / 32. * ( ( a3 * V3.at(3) + a4 * V4.at(3) ) * ( sb * ( 1. - r2 ) ) - ( a1 * V1.at(3) + a4 * V4.at(3) ) * ( sa * ( 1. + r1 ) ) ); - answer.at(5, 22) = -a1 / 32. * ( ( V21.dotProduct({ x4 - x3, y4 - y3, z4 - z3 }) * ( sb * ( 1. - r2 ) ) ) + ( V21.dotProduct({ x1 - x4, y1 - y4, z1 - z4 }) * ( sa * ( 1. + r1 ) ) ) ); - answer.at(5, 23) = a1 / 32. * ( ( V11.dotProduct({ x4 - x3, y4 - y3, z4 - z3 }) * ( sb * ( 1. - r2 ) ) ) + ( V11.dotProduct({ x1 - x4, y1 - y4, z1 - z4 }) * ( sa * ( 1. + r1 ) ) ) ); - - + answer.at(5, 22) = -a1 / 32. * ( ( dot(V21, c4 - c3) * ( sb * ( 1. - r2 ) ) ) + ( dot(V21, c1 - c4) * ( sa * ( 1. + r1 ) ) ) ); + answer.at(5, 23) = a1 / 32. * ( ( dot(V11, c4 - c3) * ( sb * ( 1. - r2 ) ) ) + ( dot(V11, c1 - c4) * ( sa * ( 1. + r1 ) ) ) ); answer.at(1, 1) = hkx.at(1); - answer.at(1, 4) = -r3 / 2. *a1 *hkx.at(1) * V21.at(1); - answer.at(1, 5) = r3 / 2. *a1 *hkx.at(1) * V11.at(1); + answer.at(1, 4) = -r3 / 2. * a1 * hkx.at(1) * V21.at(1); + answer.at(1, 5) = r3 / 2. * a1 * hkx.at(1) * V11.at(1); + answer.at(1, 7) = hkx.at(2); - answer.at(1, 10) = -r3 / 2. *a2 *hkx.at(2) * V22.at(1); - answer.at(1, 11) = r3 / 2. *a2 *hkx.at(2) * V12.at(1); - answer.at(1, 13) = hkx.at(3); - answer.at(1, 16) = -r3 / 2. *a3 *hkx.at(3) * V23.at(1); - answer.at(1, 17) = r3 / 2. *a3 *hkx.at(3) * V13.at(1); + answer.at(1, 10) = -r3 / 2. * a2 * hkx.at(2) * V22.at(1); + answer.at(1, 11) = r3 / 2. * a2 * hkx.at(2) * V12.at(1); + + answer.at(1, 13) = hkx.at(3); + answer.at(1, 16) = -r3 / 2. * a3 * hkx.at(3) * V23.at(1); + answer.at(1, 17) = r3 / 2. * a3 * hkx.at(3) * V13.at(1); + answer.at(1, 19) = hkx.at(4); - answer.at(1, 22) = -r3 / 2. *a4 *hkx.at(4) * V24.at(1); - answer.at(1, 23) = r3 / 2. *a4 *hkx.at(4) * V14.at(1); + answer.at(1, 22) = -r3 / 2. * a4 * hkx.at(4) * V24.at(1); + answer.at(1, 23) = r3 / 2. * a4 * hkx.at(4) * V14.at(1); answer.at(2, 2) = hky.at(1); - answer.at(2, 4) = -r3 / 2. *a1 *hky.at(1) * V21.at(2); - answer.at(2, 5) = r3 / 2. *a1 *hky.at(1) * V11.at(2); + answer.at(2, 4) = -r3 / 2. * a1 * hky.at(1) * V21.at(2); + answer.at(2, 5) = r3 / 2. * a1 * hky.at(1) * V11.at(2); answer.at(2, 8) = hky.at(2); - answer.at(2, 10) = -r3 / 2. *a2 *hky.at(2) * V22.at(2); - answer.at(2, 11) = r3 / 2. *a2 *hky.at(2) * V12.at(2); + answer.at(2, 10) = -r3 / 2. * a2 * hky.at(2) * V22.at(2); + answer.at(2, 11) = r3 / 2. * a2 * hky.at(2) * V12.at(2); answer.at(2, 14) = hky.at(3); - answer.at(2, 16) = -r3 / 2. *a3 *hky.at(3) * V23.at(2); - answer.at(2, 17) = r3 / 2. *a3 *hky.at(3) * V13.at(2); + answer.at(2, 16) = -r3 / 2. * a3 * hky.at(3) * V23.at(2); + answer.at(2, 17) = r3 / 2. * a3 * hky.at(3) * V13.at(2); answer.at(2, 20) = hky.at(4); - answer.at(2, 22) = -r3 / 2. *a4 *hky.at(4) * V24.at(2); - answer.at(2, 23) = r3 / 2. *a4 *hky.at(4) * V14.at(2); + answer.at(2, 22) = -r3 / 2. * a4 * hky.at(4) * V24.at(2); + answer.at(2, 23) = r3 / 2. * a4 * hky.at(4) * V14.at(2); answer.at(6, 1) = hky.at(1); answer.at(6, 2) = hkx.at(1); @@ -764,98 +610,64 @@ MITC4Shell :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int answer.at(6, 23) = r3 / 2. * a4 * ( hky.at(4) * V14.at(1) + hky.at(4) * V14.at(2) ); } -void -MITC4Shell :: giveThickness(double &a1, double &a2, double &a3, double &a4) + +std::array< double, 4 > +MITC4Shell::giveThickness() { - FloatArray *c1, *c2, *c3, *c4; - c1 = this->giveNode(1)->giveCoordinates(); - c2 = this->giveNode(2)->giveCoordinates(); - c3 = this->giveNode(3)->giveCoordinates(); - c4 = this->giveNode(4)->giveCoordinates(); - - a1 = this->giveCrossSection()->give(CS_Thickness, * c1, this, false); - a2 = this->giveCrossSection()->give(CS_Thickness, * c2, this, false); - a3 = this->giveCrossSection()->give(CS_Thickness, * c3, this, false); - a4 = this->giveCrossSection()->give(CS_Thickness, * c4, this, false); + const auto &c1 = this->giveNode(1)->giveCoordinates(); + const auto &c2 = this->giveNode(2)->giveCoordinates(); + const auto &c3 = this->giveNode(3)->giveCoordinates(); + const auto &c4 = this->giveNode(4)->giveCoordinates(); + + return { + this->giveCrossSection()->give(CS_Thickness, c1, this, false), + this->giveCrossSection()->give(CS_Thickness, c2, this, false), + this->giveCrossSection()->give(CS_Thickness, c3, this, false), + this->giveCrossSection()->give(CS_Thickness, c4, this, false), + }; } -const FloatMatrix * -MITC4Shell :: computeGtoLRotationMatrix() -// Returns the rotation matrix of the receiver of the size [3,3] -// coords(local) = T * coords(global) -// -// local coordinate (described by vector triplet e1',e2',e3') is defined as follows: -// -// e1' : [N4-N3] Ni - means i - th node -// help : [N2-N3] -// e3' : e1' x help -// e2' : e3' x e1' +void +MITC4Shell::postInitialize() { - if ( !GtoLRotationMatrix.isNotEmpty() ) { - FloatArray e1, e2, e3; + StructuralElement::postInitialize(); + auto e = this->computeLocalBaseVectors(); - this->computeLocalBaseVectors(e1, e2, e3); - - GtoLRotationMatrix.resize(3, 3); - - for ( int i = 1; i <= 3; i++ ) { - GtoLRotationMatrix.at(1, i) = e1.at(i); - GtoLRotationMatrix.at(2, i) = e2.at(i); - GtoLRotationMatrix.at(3, i) = e3.at(i); - } + for ( int i = 1; i <= 3; i++ ) { + GtoLRotationMatrix.at(1, i) = e [ 0 ].at(i); + GtoLRotationMatrix.at(2, i) = e [ 1 ].at(i); + GtoLRotationMatrix.at(3, i) = e [ 2 ].at(i); } - - return & GtoLRotationMatrix; } -void -MITC4Shell :: computeLocalBaseVectors(FloatArray &e1, FloatArray &e2, FloatArray &e3) +std::array< FloatArrayF< 3 >, 3 > +MITC4Shell::computeLocalBaseVectors() { - FloatArray help; - FloatArray coordA, coordB; - // compute A - (node2+node3)/2 - coordA.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(3)->giveCoordinates() ); - coordA.times(0.5); - coordA.add( * this->giveNode(3)->giveCoordinates() ); - + auto coordA = 0.5 * ( FloatArrayF< 3 >( this->giveNode(2)->giveCoordinates() ) + FloatArrayF< 3 >( this->giveNode(3)->giveCoordinates() ) ); // compute B - (node1+node4)/2 - coordB.beDifferenceOf( * this->giveNode(1)->giveCoordinates(), * this->giveNode(4)->giveCoordinates() ); - coordB.times(0.5); - coordB.add( * this->giveNode(4)->giveCoordinates() ); - + auto coordB = 0.5 * ( FloatArrayF< 3 >( this->giveNode(1)->giveCoordinates() ) + FloatArrayF< 3 >( this->giveNode(4)->giveCoordinates() ) ); // compute e1' = [B-A] - e1.beDifferenceOf(coordB, coordA); - + auto e1 = normalize(coordB - coordA); // compute A - (node3+node4)/2 - coordA.beDifferenceOf( * this->giveNode(4)->giveCoordinates(), * this->giveNode(3)->giveCoordinates() ); - coordA.times(0.5); - coordA.add( * this->giveNode(3)->giveCoordinates() ); - + auto coordC = 0.5 * ( FloatArrayF< 3 >( this->giveNode(4)->giveCoordinates() ) + FloatArrayF< 3 >( this->giveNode(3)->giveCoordinates() ) ); // compute B - (node2+node1)/2 - coordB.beDifferenceOf( * this->giveNode(1)->giveCoordinates(), * this->giveNode(2)->giveCoordinates() ); - coordB.times(0.5); - coordB.add( * this->giveNode(2)->giveCoordinates() ); - - // compute help = [B-A] - help.beDifferenceOf(coordB, coordA); - - // let us normalize e1' - e1.normalize(); + auto coordD = 0.5 * ( FloatArrayF< 3 >( this->giveNode(1)->giveCoordinates() ) + FloatArrayF< 3 >( this->giveNode(2)->giveCoordinates() ) ); + // compute help = [D-C] + auto help = coordD - coordC; // compute e3' : vector product of e1' x help - e3.beVectorProductOf(e1, help); - e3.normalize(); - + auto e3 = normalize( cross(e1, help) ); // now from e3' x e1' compute e2' - e2.beVectorProductOf(e3, e1); + auto e2 = cross(e3, e1); + return { e1, e2, e3 }; } -void -MITC4Shell :: computeLToDirectorRotationMatrix(FloatMatrix &answer1, FloatMatrix &answer2, FloatMatrix &answer3, FloatMatrix &answer4) +std::array< FloatMatrixF< 3, 3 >, 4 > +MITC4Shell::computeLToDirectorRotationMatrix() // Returns the rotation matrix of the reciever of the size [3,3] // {alpha_i,beta_i} = Ti * {rotL_xi, rotL_yi, rotL_zi} // alpha_i, beta_i - rotations about the components of director vector at node i @@ -868,201 +680,111 @@ MITC4Shell :: computeLToDirectorRotationMatrix(FloatMatrix &answer1, FloatMatrix // e3' : e1' x help // e2' : e3' x e1' { - FloatArray e1, e2, e3; - - this->computeLocalBaseVectors(e1, e2, e3); - - // get director vector - FloatArray V1, V2, V3, V4; - this->giveDirectorVectors(V1, V2, V3, V4); - - FloatArray V11(3), V12(3), V13(3), V14(3), V21(3), V22(3), V23(3), V24(3); - V11.beVectorProductOf(e2, V1); - V11.normalize(); - V12.beVectorProductOf(e2, V2); - V12.normalize(); - V13.beVectorProductOf(e2, V3); - V13.normalize(); - V14.beVectorProductOf(e2, V4); - V14.normalize(); - - V21.beVectorProductOf(V1, V11); - V22.beVectorProductOf(V2, V12); - V23.beVectorProductOf(V3, V13); - V24.beVectorProductOf(V4, V14); - - answer1.resize(3, 3); - answer2.resize(3, 3); - answer3.resize(3, 3); - answer4.resize(3, 3); - - answer1.at(1, 1) = V11.dotProduct(e1); - answer1.at(1, 2) = V11.dotProduct(e2); - answer1.at(1, 3) = V11.dotProduct(e3); - answer1.at(2, 1) = V21.dotProduct(e1); - answer1.at(2, 2) = V21.dotProduct(e2); - answer1.at(2, 3) = V21.dotProduct(e3); - answer1.at(3, 1) = V1.dotProduct(e1); - answer1.at(3, 2) = V1.dotProduct(e2); - answer1.at(3, 3) = V1.dotProduct(e3); - - answer2.at(1, 1) = V12.dotProduct(e1); - answer2.at(1, 2) = V12.dotProduct(e2); - answer2.at(1, 3) = V12.dotProduct(e3); - answer2.at(2, 1) = V22.dotProduct(e1); - answer2.at(2, 2) = V22.dotProduct(e2); - answer2.at(2, 3) = V22.dotProduct(e3); - answer2.at(3, 1) = V2.dotProduct(e1); - answer2.at(3, 2) = V2.dotProduct(e2); - answer2.at(3, 3) = V2.dotProduct(e3); - - answer3.at(1, 1) = V13.dotProduct(e1); - answer3.at(1, 2) = V13.dotProduct(e2); - answer3.at(1, 3) = V13.dotProduct(e3); - answer3.at(2, 1) = V23.dotProduct(e1); - answer3.at(2, 2) = V23.dotProduct(e2); - answer3.at(2, 3) = V23.dotProduct(e3); - answer3.at(3, 1) = V3.dotProduct(e1); - answer3.at(3, 2) = V3.dotProduct(e2); - answer3.at(3, 3) = V3.dotProduct(e3); - - answer4.at(1, 1) = V14.dotProduct(e1); - answer4.at(1, 2) = V14.dotProduct(e2); - answer4.at(1, 3) = V14.dotProduct(e3); - answer4.at(2, 1) = V24.dotProduct(e1); - answer4.at(2, 2) = V24.dotProduct(e2); - answer4.at(2, 3) = V24.dotProduct(e3); - answer4.at(3, 1) = V4.dotProduct(e1); - answer4.at(3, 2) = V4.dotProduct(e2); - answer4.at(3, 3) = V4.dotProduct(e3); + //auto [e1, e2, e3, e4] = this->computeLocalBaseVectors(); + auto e = this->computeLocalBaseVectors(); + auto V = this->giveDirectorVectors(); + + std::array< FloatMatrixF< 3, 3 >, 4 >answer; + for ( int i = 0; i < 4; ++i ) { + auto Ve = normalize( cross(e [ 1 ], V [ i ]) ); + auto VV = cross(V [ i ], Ve); + + answer [ i ].at(1, 1) = dot(Ve, e [ 0 ]); + answer [ i ].at(1, 2) = dot(Ve, e [ 1 ]); + answer [ i ].at(1, 3) = dot(Ve, e [ 2 ]); + + answer [ i ].at(2, 1) = dot(VV, e [ 0 ]); + answer [ i ].at(2, 2) = dot(VV, e [ 1 ]); + answer [ i ].at(2, 3) = dot(VV, e [ 2 ]); + + answer [ i ].at(3, 1) = dot(V [ i ], e [ 0 ]); + answer [ i ].at(3, 2) = dot(V [ i ], e [ 1 ]); + answer [ i ].at(3, 3) = dot(V [ i ], e [ 2 ]); + } + return answer; } + bool -MITC4Shell :: computeGtoLRotationMatrix(FloatMatrix &answer) +MITC4Shell::computeGtoLRotationMatrix(FloatMatrix &answer) // Returns the rotation matrix of the receiver of the size [24,24] // r(local) = T * r(global) // for one node (r written transposed): {u,v,w,alpha,beta} = T * {u,v,w,r1,r2,r3} - { - this->computeGtoLRotationMatrix(); + auto LtoDir = this->computeLToDirectorRotationMatrix(); answer.resize(24, 24); answer.zero(); - FloatMatrix LtoDir1, LtoDir2, LtoDir3, LtoDir4; - this->computeLToDirectorRotationMatrix(LtoDir1, LtoDir2, LtoDir3, LtoDir4); - for ( int i = 0; i <= 3; i++ ) { answer.setSubMatrix(GtoLRotationMatrix, i * 6 + 1, i * 6 + 1); + auto help = dot(LtoDir [ i ], GtoLRotationMatrix); + answer.setSubMatrix(help, i * 6 + 4, i * 6 + 4); } - //// - FloatMatrix help; - - help.beProductOf(LtoDir1, GtoLRotationMatrix); - answer.setSubMatrix(help, 4, 4); - - help.beProductOf(LtoDir2, GtoLRotationMatrix); - answer.setSubMatrix(help, 10, 10); - - help.beProductOf(LtoDir3, GtoLRotationMatrix); - answer.setSubMatrix(help, 16, 16); - - help.beProductOf(LtoDir4, GtoLRotationMatrix); - answer.setSubMatrix(help, 22, 22); return 1; } void -MITC4Shell :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +MITC4Shell::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveRealStress_3dDegeneratedShell(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveRealStress_3dDegeneratedShell(strain, gp, tStep); } -void -MITC4Shell :: giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep) -// returns characteristic tensor of the receiver at given gp and tStep +FloatMatrix +MITC4Shell::giveCharacteristicTensor(CharTensor type, GaussPoint *gp, TimeStep *tStep) { - answer.resize(3, 3); - answer.zero(); - this->computeGtoLRotationMatrix(); - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveStructuralCrossSection()->giveMaterial(gp) ); + auto mat = dynamic_cast< StructuralMaterial * >( this->giveStructuralCrossSection()->giveMaterial(gp) ); if ( type == GlobalForceTensor ) { - FloatArray stress, localStress, localStrain; + FloatArray localStress, localStrain; this->computeStrainVector(localStrain, gp, tStep); this->computeStressVector(localStress, localStrain, gp, tStep); - mat->transformStressVectorTo(stress, GtoLRotationMatrix, localStress, false); - - answer.at(1, 1) = stress.at(1); - answer.at(2, 2) = stress.at(2); - answer.at(3, 3) = stress.at(3); - answer.at(1, 2) = stress.at(4); - answer.at(2, 1) = stress.at(4); - answer.at(2, 3) = stress.at(5); - answer.at(3, 2) = stress.at(5); - answer.at(1, 3) = stress.at(6); - answer.at(3, 1) = stress.at(6); + auto stress = mat->transformStressVectorTo(GtoLRotationMatrix, localStress, false); + return from_voigt_stress(stress); } else if ( type == GlobalStrainTensor ) { - FloatArray strain, localStrain; + FloatArray localStrain; this->computeStrainVector(localStrain, gp, tStep); - mat->transformStrainVectorTo(strain, GtoLRotationMatrix, localStrain, false); - - answer.at(1, 1) = strain.at(1); - answer.at(2, 2) = strain.at(2); - answer.at(3, 3) = strain.at(3); - answer.at(2, 3) = strain.at(4) / 2.; - answer.at(3, 2) = strain.at(4) / 2.; - answer.at(1, 3) = strain.at(5) / 2.; - answer.at(3, 1) = strain.at(5) / 2.; - answer.at(1, 2) = strain.at(6) / 2.; - answer.at(2, 1) = strain.at(6) / 2.; + auto strain = mat->transformStrainVectorTo(GtoLRotationMatrix, localStrain, false); + return from_voigt_strain(strain); } else { - OOFEM_ERROR("unsupported tensor mode"); - exit(1); + throw std::runtime_error("unsupported tensor mode"); } } void -MITC4Shell :: printOutputAt(FILE *file, TimeStep *tStep) -// Performs end-of-step operations. +MITC4Shell::printOutputAt(FILE *file, TimeStep *tStep) { FloatArray v; - GaussPoint *gp; - fprintf(file, "element %d (%8d):\n", this->giveLabel(), number); for ( int i = 0; i < nPointsXY; i++ ) { fprintf(file, " GP %d :", i + 1); - this->giveMidplaneIPValue(v, i, IST_ShellForceTensor, tStep); fprintf(file, " forces "); - for ( auto &val : v ) { + for ( auto &val : this->giveMidplaneIPValue(i, IST_ShellForceTensor, tStep) ) { fprintf(file, " %.4e", val); } - this->giveMidplaneIPValue(v, i, IST_ShellMomentTensor, tStep); fprintf(file, "\n moments "); - for ( auto &val : v ) { + for ( auto &val : this->giveMidplaneIPValue(i, IST_ShellMomentTensor, tStep) ) { fprintf(file, " %.4e", val); } - this->giveMidplaneIPValue(v, i, IST_ShellStrainTensor, tStep); fprintf(file, "\n strains "); - for ( auto &val : v ) { + for ( auto &val : this->giveMidplaneIPValue(i, IST_ShellStrainTensor, tStep) ) { fprintf(file, " %.4e", val); } - this->giveMidplaneIPValue(v, i, IST_CurvatureTensor, tStep); fprintf(file, "\n curvatures "); - for ( auto &val : v ) { + for ( auto &val : this->giveMidplaneIPValue(i, IST_CurvatureTensor, tStep) ) { fprintf(file, " %.4e", val); } for ( int j = 0; j < nPointsZ; j++ ) { - gp = integrationRulesArray [ 0 ]->getIntegrationPoint(nPointsZ * i + j); + auto gp = integrationRulesArray [ 0 ]->getIntegrationPoint(nPointsZ * i + j); fprintf(file, "\n GP %d.%d :", i + 1, j + 1); @@ -1082,200 +804,130 @@ MITC4Shell :: printOutputAt(FILE *file, TimeStep *tStep) } } -void -MITC4Shell :: giveMidplaneIPValue(FloatArray &answer, int gpXY, InternalStateType type, TimeStep *tStep) +FloatArray +MITC4Shell::giveMidplaneIPValue(int gpXY, InternalStateType type, TimeStep *tStep) { - GaussPoint *gp = NULL; - if ( type == IST_ShellMomentTensor || type == IST_ShellForceTensor ) { - double J, thickness, z, w; - FloatArray mLocal; - mLocal.resize(6); - mLocal.zero(); + FloatArrayF< 6 >mLocal; for ( int i = 0; i < nPointsZ; i++ ) { - gp = integrationRulesArray [ 0 ]->getIntegrationPoint(nPointsZ * gpXY + i); - thickness = this->giveCrossSection()->give(CS_Thickness, gp->giveGlobalCoordinates(), this, false); - J = thickness / 2.0; + auto gp = integrationRulesArray [ 0 ]->getIntegrationPoint(nPointsZ * gpXY + i); + double thickness = this->giveCrossSection()->give(CS_Thickness, gp->giveGlobalCoordinates(), this, false); + double J = thickness / 2.0; + double z; if ( type == IST_ShellMomentTensor ) { z = gp->giveNaturalCoordinates().at(3) * ( thickness / 2 ); - } else if ( type == IST_ShellForceTensor ) { + } else { /*if ( type == IST_ShellForceTensor )*/ z = 1; } - w = gp->giveWeight() * J * z; + double w = gp->giveWeight() * J * z; FloatArray localStress, localStrain; this->computeStrainVector(localStrain, gp, tStep); this->computeStressVector(localStress, localStrain, gp, tStep); - mLocal.add(w, localStress); + mLocal += w * FloatArrayF< 6 >(localStress); } // local to global - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveStructuralCrossSection()->giveMaterial(gp) ); - this->computeGtoLRotationMatrix(); - mat->transformStressVectorTo(answer, GtoLRotationMatrix, mLocal, false); + return StructuralMaterial::transformStressVectorTo(GtoLRotationMatrix, mLocal, false); } else if ( type == IST_CurvatureTensor ) { - FloatArray h; - FloatMatrix dn; - FloatArray coords; - - gp = integrationRulesArray [ 0 ]->getIntegrationPoint(nPointsZ * gpXY); - coords = gp->giveNaturalCoordinates(); + auto gp = integrationRulesArray [ 0 ]->getIntegrationPoint(nPointsZ * gpXY); + const auto &coords = gp->giveNaturalCoordinates(); - StructuralMaterial *mat = dynamic_cast< StructuralMaterial * >( this->giveStructuralCrossSection()->giveMaterial(gp) ); - - FloatArray hkx, hky; - this->givedNdx(hkx, hky, coords); + //auto [hkx, hky] = this->givedNdx(coords); + auto hk = this->givedNdx(coords); FloatArray dofs(24); - - - FloatArray rotX(4), rotY(4); - this->computeVectorOf(VM_Total, tStep, dofs); + + FloatArrayF< 4 >rotX, rotY; for ( int i = 0; i < 4; i++ ) { - rotX(i) = dofs.at(i * 6 + 4); - rotY(i) = dofs.at(i * 6 + 5); + rotX [ i ] = dofs.at(i * 6 + 4); + rotY [ i ] = dofs.at(i * 6 + 5); } - FloatArray cLocal(6); - cLocal.zero(); - cLocal.at(1) = rotY.dotProduct(hkx); - cLocal.at(2) = -rotX.dotProduct(hky); - cLocal.at(6) = rotY.dotProduct(hky) - rotX.dotProduct(hkx); + FloatArrayF< 6 >cLocal; + cLocal.at(1) = dot(rotY, hk [ 0 ]); + cLocal.at(2) = -dot(rotX, hk [ 1 ]); + cLocal.at(6) = dot(rotY, hk [ 1 ]) - dot(rotX, hk [ 0 ]); - mat->transformStrainVectorTo(answer, GtoLRotationMatrix, cLocal, false); + return StructuralMaterial::transformStrainVectorTo(GtoLRotationMatrix, cLocal, false); } else if ( type == IST_ShellStrainTensor ) { - FloatArray coords; - gp = integrationRulesArray [ 0 ]->getIntegrationPoint(nPointsZ * gpXY); - coords = gp->giveNaturalCoordinates(); - coords.at(3) = 0; //set to midplane - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 10); - GaussPoint *midGP = new GaussPoint( iRule, 1, coords, 1, this->giveMaterialMode() ); - - this->giveIPValue(answer, midGP, IST_StrainTensor, tStep); + auto gp = integrationRulesArray [ 0 ]->getIntegrationPoint(nPointsZ * gpXY); + auto coords = gp->giveNaturalCoordinates(); + coords.at(3) = 0.; //set to midplane + GaussIntegrationRule iRule(1, this, 1, 10); + GaussPoint midGP(& iRule, 1, coords, 1, this->giveMaterialMode() ); + + FloatArray answer; + this->giveIPValue(answer, & midGP, IST_StrainTensor, tStep); + return answer; } else { - OOFEM_ERROR("MITC4Shell :: giveMidplaneIPValue - unknown type"); + throw std::runtime_error("unknown type"); } - - return; } -void -MITC4Shell :: givedNdx(FloatArray &hkx, FloatArray &hky, FloatArray coords) +std::array< FloatArrayF< 4 >, 2 > +MITC4Shell::givedNdx(const FloatArrayF< 3 > &coords) { - FloatArray h, hk1(4), hk2(4); - FloatMatrix dn, dndx, jacobianMatrix, inv, inv2; - - interp_lin.evalN( h, coords, FEIElementGeometryWrapper(this) ); - interp_lin.evaldNdxi(dn, coords, FEIElementGeometryWrapper(this) ); - - // derivatives of interpolation functions - // dh(r1,r2)/dr1 - hk1.at(1) = dn.at(1, 1); - hk1.at(2) = dn.at(2, 1); - hk1.at(3) = dn.at(3, 1); - hk1.at(4) = dn.at(4, 1); - - // dh(r1,r2)/dr2 - hk2.at(1) = dn.at(1, 2); - hk2.at(2) = dn.at(2, 2); - hk2.at(3) = dn.at(3, 2); - hk2.at(4) = dn.at(4, 2); - - // Jacobian Matrix - this->giveJacobian(coords, jacobianMatrix); - inv.beInverseOf(jacobianMatrix); - - inv2.beSubMatrixOf(inv, 1, 2, 1, 2); - dndx.beProductTOf(dn, inv2); - - hkx.resize(4); - hkx.at(1) = dndx.at(1, 1); - hkx.at(2) = dndx.at(2, 1); - hkx.at(3) = dndx.at(3, 1); - hkx.at(4) = dndx.at(4, 1); - - hky.resize(4); - hky.at(1) = dndx.at(1, 2); - hky.at(2) = dndx.at(2, 2); - hky.at(3) = dndx.at(3, 2); - hky.at(4) = dndx.at(4, 2); - - return; + auto dn = interp_lin.evaldNdxi(coords [ { 0, 1 } ]); + auto J = this->giveJacobian(coords); + auto invJ = inv(J); + auto invJ2 = invJ({ 0, 1 }, { 0, 1 }); + auto dndx = dot(invJ2, dn); + + auto hkx = dndx.row< 0 >(); + auto hky = dndx.row< 1 >(); + return { hkx, hky }; } void -MITC4Shell :: setupIRForMassMtrxIntegration(IntegrationRule &iRule) +MITC4Shell::setupIRForMassMtrxIntegration(IntegrationRule &iRule) { - iRule.setUpIntegrationPoints( this->giveIntegrationDomain(), nPointsXY, nPointsZ, this->giveMaterialMode() ); + iRule.setUpIntegrationPoints(this->giveIntegrationDomain(), nPointsXY, nPointsZ, this->giveMaterialMode() ); } int -MITC4Shell :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +MITC4Shell::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - FloatMatrix globTensor; - CharTensor cht; - - answer.resize(6); - - if ( type == IST_StrainTensor ) { - cht = GlobalStrainTensor; - - this->giveCharacteristicTensor(globTensor, cht, gp, tStep); - - answer.at(1) = globTensor.at(1, 1); //xx - answer.at(2) = globTensor.at(2, 2); //yy - answer.at(3) = globTensor.at(3, 3); //zz - answer.at(4) = 2 * globTensor.at(2, 3); //yz - answer.at(5) = 2 * globTensor.at(1, 3); //xz - answer.at(6) = 2 * globTensor.at(1, 2); //xy - + if ( type == IST_StrainTensor ) { + auto globTensor = this->giveCharacteristicTensor(GlobalStrainTensor, gp, tStep); + answer = to_voigt_strain(globTensor); return 1; } else if ( type == IST_StressTensor ) { - cht = GlobalForceTensor; - - this->giveCharacteristicTensor(globTensor, cht, gp, tStep); - - answer.at(1) = globTensor.at(1, 1); //xx - answer.at(2) = globTensor.at(2, 2); //yy - answer.at(3) = globTensor.at(3, 3); //zz - answer.at(4) = globTensor.at(2, 3); //yz - answer.at(5) = globTensor.at(1, 3); //xz - answer.at(6) = globTensor.at(1, 2); //xy - + auto globTensor = this->giveCharacteristicTensor(GlobalForceTensor, gp, tStep); + answer = to_voigt_stress(globTensor); return 1; } else if ( type == IST_ShellMomentTensor || type == IST_ShellForceTensor || type == IST_CurvatureTensor || type == IST_ShellStrainTensor ) { int gpnXY = ( gp->giveNumber() - 1 ) / 2; - this->giveMidplaneIPValue(answer, gpnXY, type, tStep); + answer = this->giveMidplaneIPValue(gpnXY, type, tStep); return 1; } else { - return NLStructuralElement :: giveIPValue(answer, gp, type, tStep); + return StructuralElement::giveIPValue(answer, gp, type, tStep); } } bool -MITC4Shell :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) +MITC4Shell::computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) //converts global coordinates to local planar area coordinates, //does not return a coordinate in the thickness direction, but //does check that the point is in the element thickness { // rotate the input point Coordinate System into the element CS - FloatArray inputCoords_ElCS; - std :: vector< FloatArray >lc(3); FloatArray llc; - this->giveLocalCoordinates( inputCoords_ElCS, const_cast< FloatArray & >(coords) ); + auto inputCoords_ElCS = this->giveLocalCoordinates(coords); + std::vector< FloatArray >lc(3); for ( int _i = 0; _i < 4; _i++ ) { - this->giveLocalCoordinates( lc [ _i ], * this->giveNode(_i + 1)->giveCoordinates() ); + lc [ _i ] = this->giveLocalCoordinates( this->giveNode(_i + 1)->giveCoordinates() ); } - bool inplane = interp_lin.global2local( llc, inputCoords_ElCS, FEIVertexListGeometryWrapper(lc) ) > 0; + bool inplane = interp_lin.global2local(llc, inputCoords_ElCS, FEIVertexListGeometryWrapper(lc) ) > 0; answer.resize(2); answer.at(1) = inputCoords_ElCS.at(1); answer.at(2) = inputCoords_ElCS.at(2); - GaussPoint _gp(NULL, 1, answer, 2.0, _2dPlate); + GaussPoint _gp(nullptr, 1, answer, 2.0, _2dPlate); // now check if the third local coordinate is within the thickness of element - bool outofplane = ( fabs( inputCoords_ElCS.at(3) ) <= this->giveCrossSection()->give(CS_Thickness, & _gp) / 2. ); + bool outofplane = ( fabs(inputCoords_ElCS.at(3) ) <= this->giveCrossSection()->give(CS_Thickness, & _gp) / 2. ); return inplane && outofplane; } @@ -1283,30 +935,24 @@ MITC4Shell :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coor int -MITC4Shell :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +MITC4Shell::computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { - //double l1 = lcoords.at(1); - //double l2 = lcoords.at(2); - //double l3 = lcoords.at(3); FloatMatrix N; - computeNmatrixAt(lcoords, N); answer.resize(3); for ( int _i = 1; _i <= 3; _i++ ) { - answer.at(_i) = N.at(_i,_i) * this->giveNode(1)->giveCoordinate(_i) + N.at(_i,_i+6) *this->giveNode(2)->giveCoordinate(_i) + N.at(_i,_i+12)*this->giveNode(3)->giveCoordinate(_i) + N.at(_i,_i+18)*this->giveNode(4)->giveCoordinate(_i); + answer.at(_i) = N.at(_i, _i) * this->giveNode(1)->giveCoordinate(_i) + N.at(_i, _i + 6) * this->giveNode(2)->giveCoordinate(_i) + N.at(_i, _i + 12) * this->giveNode(3)->giveCoordinate(_i) + N.at(_i, _i + 18) * this->giveNode(4)->giveCoordinate(_i); } return true; } int -MITC4Shell :: computeLoadGToLRotationMtrx(FloatMatrix &answer) +MITC4Shell::computeLoadGToLRotationMtrx(FloatMatrix &answer) // Returns the rotation matrix of the receiver of the size [5,6] // f(local) = T * f(global) { - this->computeGtoLRotationMatrix(); - answer.resize(6, 6); answer.zero(); @@ -1321,31 +967,23 @@ MITC4Shell :: computeLoadGToLRotationMtrx(FloatMatrix &answer) void -MITC4Shell :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep) +MITC4Shell::NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) { - double x1 = 0.0, x2 = 0.0, y = 0.0; - FloatMatrix A(3, 3); - FloatMatrix b, r; + FloatMatrixF< 3, 3 >A; + std::vector< FloatArrayF< 3 > >r; FloatArray val; - double u, v; - - int size = 0; - - for ( GaussPoint *gp : *integrationRulesArray [ 0 ] ) { + for ( GaussPoint *gp : * integrationRulesArray [ 0 ] ) { giveIPValue(val, gp, type, tStep); if ( size == 0 ) { size = val.giveSize(); - b.resize(3, size); - r.resize(3, size); - A.zero(); - r.zero(); + r.resize(size); } - const FloatArray &coord = gp->giveNaturalCoordinates(); - u = coord.at(1); - v = coord.at(2); + const auto &coord = gp->giveNaturalCoordinates(); + double u = coord.at(1); + double v = coord.at(2); A.at(1, 1) += 1; A.at(1, 2) += u; @@ -1358,15 +996,20 @@ MITC4Shell :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int A.at(3, 3) += v * v; for ( int j = 1; j <= size; j++ ) { - y = val.at(j); - r.at(1, j) += y; - r.at(2, j) += y * u; - r.at(3, j) += y * v; + double y = val.at(j); + r [ j ].at(1) += y; + r [ j ].at(2) += y * u; + r [ j ].at(3) += y * v; } } - A.solveForRhs(r, b); + auto invA = inv(A); + std::vector< FloatArrayF< 3 > >b(size); + for ( int i = 0; i < size; ++i ) { + b [ i ] = dot(invA, r [ i ]); + } + double x1 = 0.0, x2 = 0.0; switch ( node ) { case 1: x1 = 1.0; @@ -1390,13 +1033,13 @@ MITC4Shell :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int answer.resize(size); for ( int j = 1; j <= size; j++ ) { - answer.at(j) = b.at(1, j) + x1 *b.at(2, j) + x2 *b.at(3, j); + answer.at(j) = b [ j ].at(1) + x1 * b [ j ].at(2) + x2 * b [ j ].at(3); } } void -MITC4Shell :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +MITC4Shell::giveEdgeDofMapping(IntArray &answer, int iEdge) const { if ( iEdge == 1 ) { // edge between nodes 1 2 answer = { @@ -1421,66 +1064,59 @@ MITC4Shell :: giveEdgeDofMapping(IntArray &answer, int iEdge) const double -MITC4Shell :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +MITC4Shell::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { - std :: vector< FloatArray >lc = { - FloatArray(3), FloatArray(3), FloatArray(3), FloatArray(3) - }; - this->giveNodeCoordinates( lc [ 0 ].at(1), lc [ 1 ].at(1), lc [ 2 ].at(1), lc [ 3 ].at(1), - lc [ 0 ].at(2), lc [ 1 ].at(2), lc [ 2 ].at(2), lc [ 3 ].at(2), - lc [ 0 ].at(3), lc [ 1 ].at(3), lc [ 2 ].at(3), lc [ 3 ].at(3) ); - - - double detJ = this->interp_lin.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lc) ); + auto lcF = this->giveNodeCoordinates(); + std::vector< FloatArray >lc; + lc [ 0 ] = lcF [ 0 ]; + lc [ 1 ] = lcF [ 1 ]; + lc [ 2 ] = lcF [ 2 ]; + lc [ 3 ] = lcF [ 3 ]; + double detJ = this->interp_lin.edgeGiveTransformationJacobian(iEdge, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lc) ); return detJ * gp->giveWeight(); } -/* - * void - * MITC4Shell :: computeEdgeIpGlobalCoords(FloatArray &answer, GaussPoint *gp, int iEdge) - * { - * std :: vector< FloatArray > lc = {FloatArray(3), FloatArray(3), FloatArray(3), FloatArray(3)}; - * this->giveNodeCoordinates(lc[0].at(1), lc[1].at(1), lc[2].at(1), lc[3].at(1), - * lc[0].at(2), lc[1].at(2), lc[2].at(2), lc[3].at(2), - * lc[0].at(3), lc[1].at(3), lc[2].at(3), lc[3].at(3)); - * - * FloatArray local; - * this->interp_lin.edgeLocal2global( local, iEdge, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lc) ); - * local.resize(3); - * local.at(3) = 0.; - * - * answer = local; // MITC4 - todo - * // answer.beProductOf(this->lcsMatrix, local); - * } - */ +#if 0 +void +MITC4Shell::computeEdgeIpGlobalCoords(FloatArray &answer, GaussPoint *gp, int iEdge) +{ + auto lc = this->giveNodeCoordinates(); + + FloatArray local; + this->interp_lin.edgeLocal2global(local, iEdge, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lc) ); + local.resize(3); + local.at(3) = 0.; + + answer = local; // MITC4 - todo + // answer.beProductOf(this->lcsMatrix, local); +} +#endif int -MITC4Shell :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +MITC4Shell::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { - FloatArray e1, e2, e3, xl, yl; - this->computeLocalBaseVectors(e1, e2, e3); + auto e = this->computeLocalBaseVectors(); - IntArray edgeNodes; - this->interp_lin.computeLocalEdgeMapping(edgeNodes, iEdge); + const auto &edgeNodes = this->interp_lin.computeLocalEdgeMapping(iEdge); - xl.beDifferenceOf( * this->giveNode( edgeNodes.at(2) )->giveCoordinates(), * this->giveNode( edgeNodes.at(1) )->giveCoordinates() ); + auto n1 = FloatArrayF< 3 >( this->giveNode(edgeNodes.at(1) )->giveCoordinates() ); + auto n2 = FloatArrayF< 3 >( this->giveNode(edgeNodes.at(2) )->giveCoordinates() ); - xl.normalize(); - yl.beVectorProductOf(e3, xl); + auto xl = normalize(n1 - n2); + auto yl = cross(e [ 2 ], xl); answer.resize(6, 6); answer.zero(); - answer.at(1, 1) = answer.at(4, 4) = e1.dotProduct(xl); - answer.at(1, 2) = answer.at(4, 5) = e1.dotProduct(yl); - answer.at(1, 3) = answer.at(4, 6) = e1.dotProduct(e3); - answer.at(2, 1) = answer.at(5, 4) = e2.dotProduct(xl); - answer.at(2, 2) = answer.at(5, 5) = e2.dotProduct(yl); - answer.at(2, 3) = answer.at(5, 6) = e2.dotProduct(e3); - answer.at(3, 1) = answer.at(6, 4) = e3.dotProduct(xl); - answer.at(3, 2) = answer.at(6, 5) = e3.dotProduct(yl); - answer.at(3, 3) = answer.at(6, 6) = e3.dotProduct(e3); - + answer.at(1, 1) = answer.at(4, 4) = dot(e [ 0 ], xl); + answer.at(1, 2) = answer.at(4, 5) = dot(e [ 0 ], yl); + answer.at(1, 3) = answer.at(4, 6) = dot(e [ 0 ], e [ 2 ]); + answer.at(2, 1) = answer.at(5, 4) = dot(e [ 1 ], xl); + answer.at(2, 2) = answer.at(5, 5) = dot(e [ 1 ], yl); + answer.at(2, 3) = answer.at(5, 6) = dot(e [ 1 ], e [ 2 ]); + answer.at(3, 1) = answer.at(6, 4) = dot(e [ 2 ], xl); + answer.at(3, 2) = answer.at(6, 5) = dot(e [ 2 ], yl); + answer.at(3, 3) = answer.at(6, 6) = dot(e [ 2 ], e [ 2 ]); return 1; } @@ -1488,87 +1124,62 @@ MITC4Shell :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, Gau void -MITC4Shell :: computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) +MITC4Shell::computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) { - const FloatArray &coords2 = sgp->giveNaturalCoordinates(); - FloatArray coords(3); - coords.at(1) = coords2.at(1); - coords.at(2) = coords2.at(2); - coords.at(3) = 0.0; + const auto &coords2 = sgp->giveNaturalCoordinates(); + FloatArray coords = { coords2 [ 0 ], coords [ 1 ], 0. }; this->computeNmatrixAt(coords, answer); } void -MITC4Shell :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +MITC4Shell::giveSurfaceDofMapping(IntArray &answer, int iSurf) const { - int i; - answer.resize(24); - answer.zero(); if ( iSurf == 1 ) { - for ( i = 1; i <= 24; i++ ) { - answer.at(i) = i; - } + answer.enumerate(24); } else { OOFEM_ERROR("wrong surface number"); } } -IntegrationRule * -MITC4Shell :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Square, approxOrder); - iRule->SetUpPointsOnSquare(npoints, _Unknown); - return iRule; -} - - - double -MITC4Shell :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) +MITC4Shell::computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { - double detJ, weight; - FloatMatrix jacobianMatrix(2, 2); - FloatMatrix dn; - FloatArray lcoords(2); - lcoords.at(1) = gp->giveNaturalCoordinate(1); - lcoords.at(2) = gp->giveNaturalCoordinate(2); - FloatArray x(4), y(4), z(4); - this->giveNodeCoordinates( x.at(1), x.at(2), x.at(3), x.at(4), y.at(1), y.at(2), y.at(3), y.at(4), z.at(1), z.at(2), z.at(3), z.at(4) ); - - - weight = gp->giveWeight(); + FloatArrayF< 2 >lcoords = { + gp->giveNaturalCoordinate(1), + gp->giveNaturalCoordinate(2), + }; - interp_lin.evaldNdxi(dn, lcoords, FEIElementGeometryWrapper(this) ); + auto xyz = this->giveNodeCoordinates(); + auto dn = interp_lin.evaldNdxi(lcoords); - for ( int i = 1; i <= dn.giveNumberOfRows(); i++ ) { - double xl = x.at(i); - double yl = y.at(i); + FloatMatrixF< 2, 2 >jacobianMatrix; + for ( std::size_t i = 0; i < dn.cols(); i++ ) { + double x = xyz [ i ] [ 0 ]; + double y = xyz [ i ] [ 1 ]; - jacobianMatrix.at(1, 1) += dn.at(i, 1) * xl; - jacobianMatrix.at(1, 2) += dn.at(i, 1) * yl; - jacobianMatrix.at(2, 1) += dn.at(i, 2) * xl; - jacobianMatrix.at(2, 2) += dn.at(i, 2) * yl; + jacobianMatrix(0, 0) += dn(0, i) * x; + jacobianMatrix(0, 1) += dn(0, i) * y; + jacobianMatrix(1, 0) += dn(1, i) * x; + jacobianMatrix(1, 1) += dn(1, i) * y; } - detJ = jacobianMatrix.giveDeterminant(); - return detJ * weight; + return det(jacobianMatrix) * gp->giveWeight(); } void -MITC4Shell :: computeEdgeNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) +MITC4Shell::computeEdgeNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) { FloatArray n_vec; - this->giveInterpolation()->boundaryEdgeEvalN( n_vec, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); + this->giveInterpolation()->boundaryEdgeEvalN(n_vec, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); answer.beNMatrixOf(n_vec, 6); } void -MITC4Shell :: computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) +MITC4Shell::computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) { FloatArray n_vec; - this->giveInterpolation()->boundarySurfaceEvalN( n_vec, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); + this->giveInterpolation()->boundarySurfaceEvalN(n_vec, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); answer.beNMatrixOf(n_vec, 6); } } // end namespace oofem diff --git a/src/sm/Elements/Shells/mitc4.h b/src/sm/Elements/Shells/mitc4.h index 50e588823..0d72b6420 100644 --- a/src/sm/Elements/Shells/mitc4.h +++ b/src/sm/Elements/Shells/mitc4.h @@ -35,12 +35,13 @@ #ifndef mitc4_h #define mitc4_h -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/structuralelement.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" #include "spatiallocalizer.h" #include "load.h" +#include "floatmatrixf.h" //#include "eleminterpmapperinterface.h"// #define _IFT_MITC4Shell_Name "mitc4shell" @@ -68,7 +69,7 @@ enum CharTensor { * - calculating its B,D matrices and dV. */ -class MITC4Shell : public NLStructuralElement, public ZZNodalRecoveryModelInterface, +class MITC4Shell : public StructuralElement, public ZZNodalRecoveryModelInterface, public SPRNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface, public SpatialLocalizerInterface { @@ -79,89 +80,79 @@ class MITC4Shell : public NLStructuralElement, public ZZNodalRecoveryModelInterf * Transformation Matrix form GtoL(3,3) is stored * at the element level for computation efficiency. */ - FloatMatrix GtoLRotationMatrix; - int nPointsXY, nPointsZ, directorType; - double drillCoeff; + FloatMatrixF< 3, 3 >GtoLRotationMatrix; + int nPointsXY = 0, nPointsZ = 0, directorType = 0; + double drillCoeff = 0.; public: - MITC4Shell(int n, Domain *d); - virtual ~MITC4Shell() { } - - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; - virtual int testElementExtension(ElementExtension ext) { return ( ( ( ext == Element_EdgeLoadSupport ) || ( ext == Element_SurfaceLoadSupport ) ) ? 1 : 0 ); } - - virtual Interface *giveInterface(InterfaceType interface); - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; + int testElementExtension(ElementExtension ext) override { return ( ( ( ext == Element_EdgeLoadSupport ) || ( ext == Element_SurfaceLoadSupport ) ) ? 1 : 0 ); } + Interface *giveInterface(InterfaceType interface) override; + // definition & identification + const char *giveClassName() const override { return "MITC4Shell"; } + const char *giveInputRecordName() const override { return _IFT_MITC4Shell_Name; } + integrationDomain giveIntegrationDomain() const override { return _3dDegShell; } + MaterialMode giveMaterialMode() override { return _3dDegeneratedShell; } + void initializeFrom(InputRecord &ir) override; + void postInitialize() override; + int computeNumberOfDofs() override { return 24; } + int computeNumberOfGlobalDofs() override { return 24; } + + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override; // transformation - bool computeGtoLRotationMatrix(FloatMatrix &answer); - int computeLoadGToLRotationMtrx(FloatMatrix &answer); - void computeLToDirectorRotationMatrix(FloatMatrix &answer1, FloatMatrix &answer2, FloatMatrix &answer3, FloatMatrix &answer4); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); - + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + std::array< FloatMatrixF< 3, 3 >, 4 >computeLToDirectorRotationMatrix(); + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; protected: - - virtual void computeGaussPoints(); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); + void computeGaussPoints() override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; private: - void giveNodeCoordinates(double &x1, double &x2, double &x3, double &x4, - double &y1, double &y2, double &y3, double &y4, - double &z1, double &z2, double &z3, double &z4); - void giveDirectorVectors(FloatArray &V1, FloatArray &V2, FloatArray &V3, FloatArray &V4); - void giveLocalDirectorVectors(FloatArray &V1, FloatArray &V2, FloatArray &V3, FloatArray &V4); - void giveThickness(double &a1, double &a2, double &a3, double &a4); - void giveJacobian(FloatArray lcoords, FloatMatrix &jacobianMatrix); - void giveLocalCoordinates(FloatArray &answer, FloatArray &global); - const FloatMatrix *computeGtoLRotationMatrix(); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - void giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &coords); - virtual double computeVolumeAround(GaussPoint *gp); - void computeLocalBaseVectors(FloatArray &e1, FloatArray &e2, FloatArray &e3); - void givedNdx(FloatArray &hkx, FloatArray &hky, FloatArray coords); - - void giveMidplaneIPValue(FloatArray &answer, int gpXY, InternalStateType type, TimeStep *tStep); - - // definition & identification - virtual const char *giveClassName() const { return "MITC4Shell"; } - virtual const char *giveInputRecordName() const { return _IFT_MITC4Shell_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int computeNumberOfDofs() { return 24; } - virtual int computeNumberOfGlobalDofs() { return 24; } - virtual integrationDomain giveIntegrationDomain() const { return _3dDegShell; } - virtual MaterialMode giveMaterialMode() { return _3dDegeneratedShell; } - + std::array< FloatArrayF< 3 >, 4 >giveNodeCoordinates(); + std::array< FloatArrayF< 3 >, 4 >giveDirectorVectors(); + std::array< FloatArrayF< 3 >, 4 >giveLocalDirectorVectors(); + std::array< double, 4 >giveThickness(); + FloatMatrixF< 3, 3 >giveJacobian(const FloatArrayF< 3 > &lcoords); + FloatArrayF< 3 >giveLocalCoordinates(const FloatArrayF< 3 > &global); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + FloatMatrix giveCharacteristicTensor(CharTensor type, GaussPoint *gp, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) override; + double computeVolumeAround(GaussPoint *gp) override; + std::array< FloatArrayF< 3 >, 3 >computeLocalBaseVectors(); + std::array< FloatArrayF< 4 >, 2 >givedNdx(const FloatArrayF< 3 > &coords); + + FloatArray giveMidplaneIPValue(int gpXY, InternalStateType type, TimeStep *tStep); // edge & body load - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf); - virtual IntegrationRule *GetSurfaceIntegrationRule(int approxOrder); - virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp); - virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const; - - virtual void computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords); - virtual void computeEdgeNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords); - virtual void setupIRForMassMtrxIntegration(IntegrationRule &iRule); + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + void giveDofManDofIDMask(int inode, IntArray &) const override; + double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) override; + void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp); ///@note This method isn't overloaded, it's never called for any class + void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override; + + void computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) override; + void computeEdgeNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) override; + void setupIRForMassMtrxIntegration(IntegrationRule &iRule) override; }; } // end namespace oofem #endif // mitc4_h diff --git a/src/sm/Elements/Shells/quad1mindlinshell3d.C b/src/sm/Elements/Shells/quad1mindlinshell3d.C index f7b22c5c9..cafdd9ddd 100644 --- a/src/sm/Elements/Shells/quad1mindlinshell3d.C +++ b/src/sm/Elements/Shells/quad1mindlinshell3d.C @@ -32,10 +32,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Shells/quad1mindlinshell3d.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Loads/constantpressureload.h" +#include "sm/Elements/Shells/quad1mindlinshell3d.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Loads/constantpressureload.h" #include "node.h" #include "material.h" #include "crosssection.h" @@ -43,6 +43,8 @@ #include "gaussintegrationrule.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" #include "intarray.h" #include "load.h" #include "mathfem.h" @@ -52,12 +54,12 @@ namespace oofem { REGISTER_Element(Quad1MindlinShell3D); -FEI2dQuadLin Quad1MindlinShell3D :: interp(1, 2); -IntArray Quad1MindlinShell3D :: shellOrdering = { 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23}; -IntArray Quad1MindlinShell3D :: drillOrdering = { 6, 12, 18, 24}; +FEI2dQuadLin Quad1MindlinShell3D::interp(1, 2); +IntArray Quad1MindlinShell3D::shellOrdering = { 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 19, 20, 21, 22, 23 }; +IntArray Quad1MindlinShell3D::drillOrdering = { 6, 12, 18, 24 }; -Quad1MindlinShell3D :: Quad1MindlinShell3D(int n, Domain *aDomain) : - NLStructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this), +Quad1MindlinShell3D::Quad1MindlinShell3D(int n, Domain *aDomain) : + StructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this), SPRNodalRecoveryModelInterface(), lnodes(4) { @@ -67,32 +69,27 @@ Quad1MindlinShell3D :: Quad1MindlinShell3D(int n, Domain *aDomain) : } -Quad1MindlinShell3D :: ~Quad1MindlinShell3D() -{ -} - - FEInterpolation * -Quad1MindlinShell3D :: giveInterpolation() const +Quad1MindlinShell3D::giveInterpolation() const { return & interp; } FEInterpolation * -Quad1MindlinShell3D :: giveInterpolation(DofIDItem id) const +Quad1MindlinShell3D::giveInterpolation(DofIDItem id) const { return & interp; } void -Quad1MindlinShell3D :: computeGaussPoints() +Quad1MindlinShell3D::computeGaussPoints() // Sets up the array containing the four Gauss points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 5) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 5); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } ///@todo Deal with updated geometries and such. @@ -101,10 +98,9 @@ Quad1MindlinShell3D :: computeGaussPoints() void -Quad1MindlinShell3D :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) +Quad1MindlinShell3D::computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) { // Only gravity load - double dV, density; FloatArray forceX, forceY, forceZ, glob_gravity, gravity, n; if ( ( forLoad->giveBCGeoType() != BodyLoadBGT ) || ( forLoad->giveBCValType() != ForceLoadBVT ) ) { @@ -117,11 +113,10 @@ Quad1MindlinShell3D :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad gravity.beProductOf(this->lcsMatrix, glob_gravity); ///@todo Check potential transpose here. if ( gravity.giveSize() ) { - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { - - this->interp.evalN( n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); - dV = this->computeVolumeAround(gp) * this->giveCrossSection()->give(CS_Thickness, gp); - density = this->giveStructuralCrossSection()->give('d', gp); + for ( GaussPoint *gp: * integrationRulesArray [ 0 ] ) { + this->interp.evalN(n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); + double dV = this->computeVolumeAround(gp) * this->giveCrossSection()->give(CS_Thickness, gp); + double density = this->giveStructuralCrossSection()->give('d', gp); forceX.add(density * gravity.at(1) * dV, n); forceY.add(density * gravity.at(2) * dV, n); @@ -151,23 +146,23 @@ Quad1MindlinShell3D :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad } } -/* +#if 0 void -Quad1MindlinShell3D :: computeSurfaceLoadVectorAt(FloatArray &answer, Load *load, - int iSurf, TimeStep *tStep, ValueModeType mode) +Quad1MindlinShell3D::computeSurfaceLoadVectorAt(FloatArray &answer, Load *load, + int iSurf, TimeStep *tStep, ValueModeType mode) { - BoundaryLoad *surfLoad = static_cast< BoundaryLoad * >(load); - if ( dynamic_cast< ConstantPressureLoad * >(surfLoad) ) { // Just checking the type of b.c. + BoundaryLoad *surfLoad = static_cast< BoundaryLoad * >( load ); + if ( dynamic_cast< ConstantPressureLoad * >( surfLoad ) ) { // Just checking the type of b.c. // EXPERIMENTAL CODE: FloatArray n, gcoords, pressure; answer.resize(24); answer.zero(); - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( GaussPoint *gp: * integrationRulesArray [ 0 ] ) { double dV = this->computeVolumeAround(gp); - this->interp.evalN( n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); - this->interp.local2global( gcoords, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interp.evalN(n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); + this->interp.local2global(gcoords, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); surfLoad->computeValueAt(pressure, tStep, gcoords, mode); answer.at(3) += n.at(1) * pressure.at(1) * dV; @@ -183,55 +178,54 @@ Quad1MindlinShell3D :: computeSurfaceLoadVectorAt(FloatArray &answer, Load *load OOFEM_ERROR("only supports constant pressure boundary load."); } } -*/ +#endif void -Quad1MindlinShell3D :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +Quad1MindlinShell3D::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) { - FloatArray n, ns; - FloatMatrix dn, dns; - const FloatArray &localCoords = gp->giveNaturalCoordinates(); + const auto &localCoords = gp->giveNaturalCoordinates(); - this->interp.evaldNdx( dn, localCoords, FEIVertexListGeometryWrapper(lnodes) ); - this->interp.evalN( n, localCoords, FEIVoidCellGeometry() ); - - answer.resize(8, 4 * 5); - answer.zero(); + auto tmp = this->interp.evaldNdx( localCoords, FEIVertexListGeometryWrapper(lnodes) ); + auto dn = tmp.second; + auto n = this->interp.evalN(localCoords); // enforce one-point reduced integration if requested + FloatArrayF< 4 >ns; + FloatMatrixF< 2, 4 >dns; if ( this->reducedIntegrationFlag ) { - FloatArray lc(2); - lc.zero(); // set to element center coordinates - - this->interp.evaldNdx( dns, lc, FEIVertexListGeometryWrapper(lnodes) ); - this->interp.evalN( ns, lc, FEIVoidCellGeometry() ); + FloatArray lc(2); // set to element center coordinates + auto tmp = this->interp.evaldNdx( lc, FEIVertexListGeometryWrapper(lnodes) ); + dns = tmp.second; + ns = this->interp.evalN(lc); } else { dns = dn; ns = n; } + answer.resize(8, 4 * 5); + answer.zero(); // Note: This is just 5 dofs (sixth column is all zero, torsional stiffness handled separately.) for ( int i = 0; i < 4; ++i ) { ///@todo Check the rows for both parts here, to be consistent with _3dShell material definition // Part related to the membrane (columns represent coefficients for D_u, D_v) - answer(0, 0 + i * 5) = dn(i, 0);//eps_x = du/dx - answer(1, 1 + i * 5) = dn(i, 1);//eps_y = dv/dy - answer(2, 0 + i * 5) = dn(i, 1);//gamma_xy = du/dy+dv/dx - answer(2, 1 + i * 5) = dn(i, 0); + answer(0, 0 + i * 5) = dn(0, i); // eps_x = du/dx + answer(1, 1 + i * 5) = dn(1, i); // eps_y = dv/dy + answer(2, 0 + i * 5) = dn(1, i); // gamma_xy = du/dy+dv/dx + answer(2, 1 + i * 5) = dn(0, i); // Part related to the plate (columns represent the dofs D_w, R_u, R_v) ///@todo Check sign here - answer(3 + 0, 2 + 2 + i * 5) = dn(i, 0);// kappa_x = d(fi_y)/dx - answer(3 + 1, 2 + 1 + i * 5) =-dn(i, 1);// kappa_y = -d(fi_x)/dy - answer(3 + 2, 2 + 2 + i * 5) = dn(i, 1);// kappa_xy=d(fi_y)/dy-d(fi_x)/dx - answer(3 + 2, 2 + 1 + i * 5) =-dn(i, 0); + answer(3 + 0, 2 + 2 + i * 5) = dn(0, i); // kappa_x = d(fi_y)/dx + answer(3 + 1, 2 + 1 + i * 5) = -dn(1, i); // kappa_y = -d(fi_x)/dy + answer(3 + 2, 2 + 2 + i * 5) = dn(1, i); // kappa_xy=d(fi_y)/dy-d(fi_x)/dx + answer(3 + 2, 2 + 1 + i * 5) = -dn(0, i); // shear strains - answer(3 + 3, 2 + 0 + i * 5) = dns(i, 0);// gamma_xz = fi_y+dw/dx - answer(3 + 3, 2 + 2 + i * 5) = ns(i); - answer(3 + 4, 2 + 0 + i * 5) = dns(i, 1);// gamma_yz = -fi_x+dw/dy - answer(3 + 4, 2 + 1 + i * 5) = -ns(i); + answer(3 + 3, 2 + 0 + i * 5) = dns(0, i); // gamma_xz = fi_y+dw/dx + answer(3 + 3, 2 + 2 + i * 5) = ns [ i ]; + answer(3 + 4, 2 + 0 + i * 5) = dns(1, i); // gamma_yz = -fi_x+dw/dy + answer(3 + 4, 2 + 1 + i * 5) = -ns [ i ]; } @@ -244,18 +238,18 @@ Quad1MindlinShell3D :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int double y1, y2, y3, y4; double Ax, Bx, Cx, Ay, By, Cy; - double r = localCoords[0]; - double s = localCoords[1]; + double r = localCoords [ 0 ]; + double s = localCoords [ 1 ]; - x1 = lnodes[0][0]; - x2 = lnodes[1][0]; - x3 = lnodes[2][0]; - x4 = lnodes[3][0]; + x1 = lnodes [ 0 ] [ 0 ]; + x2 = lnodes [ 1 ] [ 0 ]; + x3 = lnodes [ 2 ] [ 0 ]; + x4 = lnodes [ 3 ] [ 0 ]; - y1 = lnodes[0][1]; - y2 = lnodes[1][1]; - y3 = lnodes[2][1]; - y4 = lnodes[3][1]; + y1 = lnodes [ 0 ] [ 1 ]; + y2 = lnodes [ 1 ] [ 1 ]; + y3 = lnodes [ 2 ] [ 1 ]; + y4 = lnodes [ 3 ] [ 1 ]; Ax = x1 - x2 - x3 + x4; Bx = x1 - x2 + x3 - x4; @@ -266,18 +260,18 @@ Quad1MindlinShell3D :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int Cy = y1 + y2 - y3 - y4; FloatMatrix jac; - this->interp.giveJacobianMatrixAt(jac, localCoords, FEIVertexListGeometryWrapper(lnodes) ); + this->interp.giveJacobianMatrixAt( jac, localCoords, FEIVertexListGeometryWrapper(lnodes) ); double detJ = jac.giveDeterminant(); - double rz = sqrt( sqr(Cx + r*Bx) + sqr(Cy + r*By)) / ( 16 * detJ ); - double sz = sqrt( sqr(Ax + s*Bx) + sqr(Ay + s*By)) / ( 16 * detJ ); + double rz = sqrt(sqr(Cx + r * Bx) + sqr(Cy + r * By) ) / ( 16 * detJ ); + double sz = sqrt(sqr(Ax + s * Bx) + sqr(Ay + s * By) ) / ( 16 * detJ ); // TODO: Not sure about this part (the reference is not explicit about these angles. / Mikael // Not sure about the transpose either. OOFEM_WARNING("The MITC4 implementation isn't verified yet. Highly experimental"); - FloatArray dxdr = {jac(0,0), jac(0,1)}; + FloatArray dxdr = { jac(0, 0), jac(0, 1) }; dxdr.normalize(); - FloatArray dxds = {jac(1,0), jac(1,1)}; + FloatArray dxds = { jac(1, 0), jac(1, 1) }; dxds.normalize(); double c_b = dxdr(0); //cos(beta); @@ -286,60 +280,60 @@ Quad1MindlinShell3D :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int double s_a = dxds(1); //sin(alpha); // gamma_xz = "fi_y+dw/dx" in standard formulation - answer(6, 2 + 5*0) = rz * s_b * ( (1+s)) - sz * s_a * ( (1+r)); - answer(6, 2 + 5*1) = rz * s_b * (-(1+s)) - sz * s_a * ( (1-r)); - answer(6, 2 + 5*2) = rz * s_b * (-(1-s)) - sz * s_a * (-(1-r)); - answer(6, 2 + 5*3) = rz * s_b * ( (1-s)) - sz * s_a * (-(1+r)); + answer(6, 2 + 5 * 0) = rz * s_b * ( ( 1 + s ) ) - sz * s_a * ( ( 1 + r ) ); + answer(6, 2 + 5 * 1) = rz * s_b * ( -( 1 + s ) ) - sz * s_a * ( ( 1 - r ) ); + answer(6, 2 + 5 * 2) = rz * s_b * ( -( 1 - s ) ) - sz * s_a * ( -( 1 - r ) ); + answer(6, 2 + 5 * 3) = rz * s_b * ( ( 1 - s ) ) - sz * s_a * ( -( 1 + r ) ); - answer(6, 3 + 5*0) = rz * s_b * (y2-y1) * 0.5 * (1+s) - sz * s_a * (y4-y1) * 0.5 * (1+r); // tx1 - answer(6, 4 + 5*0) = rz * s_b * (x1-x2) * 0.5 * (1+s) - sz * s_a * (x1-x4) * 0.5 * (1+r); // ty1 + answer(6, 3 + 5 * 0) = rz * s_b * ( y2 - y1 ) * 0.5 * ( 1 + s ) - sz * s_a * ( y4 - y1 ) * 0.5 * ( 1 + r ); // tx1 + answer(6, 4 + 5 * 0) = rz * s_b * ( x1 - x2 ) * 0.5 * ( 1 + s ) - sz * s_a * ( x1 - x4 ) * 0.5 * ( 1 + r ); // ty1 - answer(6, 3 + 5*1) = rz * s_b * (y2-y1) * 0.5 * (1+s) - sz * s_a * (y3-x2) * 0.5 * (1+r); // tx2 - answer(6, 4 + 5*1) = rz * s_b * (x1-x2) * 0.5 * (1+s) - sz * s_a * (x2-x3) * 0.5 * (1+r); // ty2 + answer(6, 3 + 5 * 1) = rz * s_b * ( y2 - y1 ) * 0.5 * ( 1 + s ) - sz * s_a * ( y3 - x2 ) * 0.5 * ( 1 + r ); // tx2 + answer(6, 4 + 5 * 1) = rz * s_b * ( x1 - x2 ) * 0.5 * ( 1 + s ) - sz * s_a * ( x2 - x3 ) * 0.5 * ( 1 + r ); // ty2 - answer(6, 3 + 5*2) = rz * s_b * (y3-y4) * 0.5 * (1-s) - sz * s_a * (y3-y2) * 0.5 * (1-r); // tx3 - answer(6, 4 + 5*2) = rz * s_b * (x4-x3) * 0.5 * (1-s) - sz * s_a * (x2-x3) * 0.5 * (1-r); // ty3 + answer(6, 3 + 5 * 2) = rz * s_b * ( y3 - y4 ) * 0.5 * ( 1 - s ) - sz * s_a * ( y3 - y2 ) * 0.5 * ( 1 - r ); // tx3 + answer(6, 4 + 5 * 2) = rz * s_b * ( x4 - x3 ) * 0.5 * ( 1 - s ) - sz * s_a * ( x2 - x3 ) * 0.5 * ( 1 - r ); // ty3 - answer(6, 3 + 5*3) = rz * s_b * (y3-y4) * 0.5 * (1-s) - sz * s_a * (y4-y1) * 0.5 * (1-r); // tx4 - answer(6, 4 + 5*3) = rz * s_b * (x4-x3) * 0.5 * (1-s) - sz * s_a * (x1-x4) * 0.5 * (1-r); // ty4 + answer(6, 3 + 5 * 3) = rz * s_b * ( y3 - y4 ) * 0.5 * ( 1 - s ) - sz * s_a * ( y4 - y1 ) * 0.5 * ( 1 - r ); // tx4 + answer(6, 4 + 5 * 3) = rz * s_b * ( x4 - x3 ) * 0.5 * ( 1 - s ) - sz * s_a * ( x1 - x4 ) * 0.5 * ( 1 - r ); // ty4 // gamma_yz = -fi_x+dw/dy in standard formulation - answer(7, 2 + 5*0) = - rz * c_b * ( (1+s)) + sz * c_a * ( (1+r)); - answer(7, 2 + 5*1) = - rz * c_b * (-(1+s)) + sz * c_a * ( (1-r)); - answer(7, 2 + 5*2) = - rz * c_b * (-(1-s)) + sz * c_a * (-(1-r)); - answer(7, 2 + 5*3) = - rz * c_b * ( (1-s)) + sz * c_a * (-(1+r)); + answer(7, 2 + 5 * 0) = -rz * c_b * ( ( 1 + s ) ) + sz * c_a * ( ( 1 + r ) ); + answer(7, 2 + 5 * 1) = -rz * c_b * ( -( 1 + s ) ) + sz * c_a * ( ( 1 - r ) ); + answer(7, 2 + 5 * 2) = -rz * c_b * ( -( 1 - s ) ) + sz * c_a * ( -( 1 - r ) ); + answer(7, 2 + 5 * 3) = -rz * c_b * ( ( 1 - s ) ) + sz * c_a * ( -( 1 + r ) ); - answer(7, 3 + 5*0) = - rz * c_b * (y2-y1) * 0.5 * (1+s) + sz * c_a * (y4-y1) * 0.5 * (1+r); // tx1 - answer(7, 4 + 5*0) = - rz * c_b * (x1-x2) * 0.5 * (1+s) + sz * c_a * (x1-x4) * 0.5 * (1+r); // ty1 + answer(7, 3 + 5 * 0) = -rz * c_b * ( y2 - y1 ) * 0.5 * ( 1 + s ) + sz * c_a * ( y4 - y1 ) * 0.5 * ( 1 + r ); // tx1 + answer(7, 4 + 5 * 0) = -rz * c_b * ( x1 - x2 ) * 0.5 * ( 1 + s ) + sz * c_a * ( x1 - x4 ) * 0.5 * ( 1 + r ); // ty1 - answer(7, 3 + 5*1) = - rz * c_b * (y2-y1) * 0.5 * (1+s) + sz * c_a * (y3-x2) * 0.5 * (1+r); // tx2 - answer(7, 4 + 5*1) = - rz * c_b * (x1-x2) * 0.5 * (1+s) + sz * c_a * (x2-x3) * 0.5 * (1+r); // ty2 + answer(7, 3 + 5 * 1) = -rz * c_b * ( y2 - y1 ) * 0.5 * ( 1 + s ) + sz * c_a * ( y3 - x2 ) * 0.5 * ( 1 + r ); // tx2 + answer(7, 4 + 5 * 1) = -rz * c_b * ( x1 - x2 ) * 0.5 * ( 1 + s ) + sz * c_a * ( x2 - x3 ) * 0.5 * ( 1 + r ); // ty2 - answer(7, 3 + 5*2) = - rz * c_b * (y3-y4) * 0.5 * (1-s) + sz * c_a * (y3-y2) * 0.5 * (1-r); // tx3 - answer(7, 4 + 5*2) = - rz * c_b * (x4-x3) * 0.5 * (1-s) + sz * c_a * (x2-x3) * 0.5 * (1-r); // ty3 + answer(7, 3 + 5 * 2) = -rz * c_b * ( y3 - y4 ) * 0.5 * ( 1 - s ) + sz * c_a * ( y3 - y2 ) * 0.5 * ( 1 - r ); // tx3 + answer(7, 4 + 5 * 2) = -rz * c_b * ( x4 - x3 ) * 0.5 * ( 1 - s ) + sz * c_a * ( x2 - x3 ) * 0.5 * ( 1 - r ); // ty3 - answer(7, 3 + 5*3) = - rz * c_b * (y3-y4) * 0.5 * (1-s) + sz * c_a * (y4-y1) * 0.5 * (1-r); // tx4 - answer(7, 4 + 5*3) = - rz * c_b * (x4-x3) * 0.5 * (1-s) + sz * c_a * (x1-x4) * 0.5 * (1-r); // ty4 + answer(7, 3 + 5 * 3) = -rz * c_b * ( y3 - y4 ) * 0.5 * ( 1 - s ) + sz * c_a * ( y4 - y1 ) * 0.5 * ( 1 - r ); // tx4 + answer(7, 4 + 5 * 3) = -rz * c_b * ( x4 - x3 ) * 0.5 * ( 1 - s ) + sz * c_a * ( x1 - x4 ) * 0.5 * ( 1 - r ); // ty4 #endif } void -Quad1MindlinShell3D :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +Quad1MindlinShell3D::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Shell(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Shell(strain, gp, tStep); } void -Quad1MindlinShell3D :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +Quad1MindlinShell3D::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give3dShellStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give3dShellStiffMtrx(rMode, gp, tStep); } void -Quad1MindlinShell3D :: computeVectorOfUnknowns(ValueModeType mode, TimeStep *tStep, FloatArray &shell, FloatArray &drill) +Quad1MindlinShell3D::computeVectorOfUnknowns(ValueModeType mode, TimeStep *tStep, FloatArray &shell, FloatArray &drill) { FloatArray tmp; this->computeVectorOf(mode, tStep, tmp); @@ -349,7 +343,7 @@ Quad1MindlinShell3D :: computeVectorOfUnknowns(ValueModeType mode, TimeStep *tSt void -Quad1MindlinShell3D :: computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +Quad1MindlinShell3D::computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { FloatArray shellUnknowns, tmp; FloatMatrix b; @@ -362,7 +356,7 @@ Quad1MindlinShell3D :: computeStrainVector(FloatArray &answer, GaussPoint *gp, T void -Quad1MindlinShell3D :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +Quad1MindlinShell3D::giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { // We need to overload this for practical reasons (this 3d shell has all 9 dofs, but the shell part only cares for the first 8) // This elements adds an additional stiffness for the so called drilling dofs, meaning we need to work with all 9 components. @@ -377,7 +371,7 @@ Quad1MindlinShell3D :: giveInternalForcesVector(FloatArray &answer, TimeStep *tS FloatArray shellForces, drillMoment; StructuralCrossSection *cs = this->giveStructuralCrossSection(); - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( GaussPoint *gp: * integrationRulesArray [ 0 ] ) { this->computeBmatrixAt(gp, b); double dV = this->computeVolumeAround(gp); double drillCoeff = cs->give(CS_DrillingStiffness, gp); @@ -386,13 +380,13 @@ Quad1MindlinShell3D :: giveInternalForcesVector(FloatArray &answer, TimeStep *tS stress = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); } else { strain.beProductOf(b, shellUnknowns); - cs->giveGeneralizedStress_Shell(stress, gp, strain, tStep); + stress = cs->giveGeneralizedStress_Shell(strain, gp, tStep); } shellForces.plusProduct(b, stress, dV); // Drilling stiffness is here for improved numerical properties if ( drillCoeff > 0. ) { - this->interp.evalN( n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); + this->interp.evalN(n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); for ( int j = 0; j < 4; j++ ) { n(j) -= 0.25; } @@ -413,7 +407,7 @@ Quad1MindlinShell3D :: giveInternalForcesVector(FloatArray &answer, TimeStep *tS void -Quad1MindlinShell3D :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +Quad1MindlinShell3D::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { // We need to overload this for practical reasons (this 3d shell has all 9 dofs, but the shell part only cares for the first 8) // This elements adds an additional stiffness for the so called drilling dofs, meaning we need to work with all 9 components. @@ -423,7 +417,7 @@ Quad1MindlinShell3D :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMo FloatMatrix shellStiffness, drillStiffness; - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: * integrationRulesArray [ 0 ] ) { this->computeBmatrixAt(gp, b); double dV = this->computeVolumeAround(gp); double drillCoeff = this->giveStructuralCrossSection()->give(CS_DrillingStiffness, gp); @@ -435,7 +429,7 @@ Quad1MindlinShell3D :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMo // Drilling stiffness is here for improved numerical properties if ( drillCoeff > 0. ) { - this->interp.evalN( n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); + this->interp.evalN(n, gp->giveNaturalCoordinates(), FEIVoidCellGeometry() ); for ( int j = 0; j < 4; j++ ) { n(j) -= 0.25; } @@ -456,58 +450,55 @@ Quad1MindlinShell3D :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMo } -IRResultType -Quad1MindlinShell3D :: initializeFrom(InputRecord *ir) +void +Quad1MindlinShell3D::initializeFrom(InputRecord &ir) { - this->reducedIntegrationFlag = ir->hasField(_IFT_Quad1MindlinShell3D_ReducedIntegration); - return NLStructuralElement :: initializeFrom(ir); + StructuralElement::initializeFrom(ir); + this->reducedIntegrationFlag = ir.hasField(_IFT_Quad1MindlinShell3D_ReducedIntegration); } void -Quad1MindlinShell3D :: giveDofManDofIDMask(int inode, IntArray &answer) const +Quad1MindlinShell3D::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u, D_v, D_w, R_u, R_v, R_w}; + answer = { D_u, D_v, D_w, R_u, R_v, R_w }; } void -Quad1MindlinShell3D :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) +Quad1MindlinShell3D::computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) { - FloatArray u, v; - u.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - v.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); + FloatArrayF< 3 >u = this->giveNode(2)->giveCoordinates() - this->giveNode(1)->giveCoordinates(); + FloatArrayF< 3 >v = this->giveNode(3)->giveCoordinates() - this->giveNode(1)->giveCoordinates(); - answer.beVectorProductOf(u, v); - answer.normalize(); + auto n = cross(u, v); + answer = n / norm(n); } double -Quad1MindlinShell3D :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) +Quad1MindlinShell3D::giveCharacteristicLength(const FloatArray &normalToCrackPlane) { return this->giveLengthInDir(normalToCrackPlane); } double -Quad1MindlinShell3D :: computeVolumeAround(GaussPoint *gp) +Quad1MindlinShell3D::computeVolumeAround(GaussPoint *gp) { - double detJ, weight; - - weight = gp->giveWeight(); - detJ = fabs( this->interp.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lnodes) ) ); + double weight = gp->giveWeight(); + double detJ = fabs(this->interp.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lnodes) ) ); return detJ * weight; } void -Quad1MindlinShell3D :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) +Quad1MindlinShell3D::computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. { double mass = 0.; - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { + for ( auto &gp: * integrationRulesArray [ 0 ] ) { mass += this->computeVolumeAround(gp) * this->giveStructuralCrossSection()->give('d', gp); } @@ -522,53 +513,53 @@ Quad1MindlinShell3D :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tS int -Quad1MindlinShell3D :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +Quad1MindlinShell3D::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - FloatArray help; + FloatArray s; answer.resize(6); if ( type == IST_ShellForceTensor || type == IST_ShellStrainTensor ) { if ( type == IST_ShellForceTensor ) { - help = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); + s = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); } else { - help = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); + s = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); } - answer.at(1) = help.at(1); // nx - answer.at(2) = help.at(2); // ny + answer.at(1) = s.at(1); // nx + answer.at(2) = s.at(2); // ny answer.at(3) = 0.0; // nz - answer.at(4) = help.at(8); // vyz - answer.at(5) = help.at(7); // vxy - answer.at(6) = help.at(3); // vxy + answer.at(4) = s.at(8); // vyz + answer.at(5) = s.at(7); // vxy + answer.at(6) = s.at(3); // vxy return 1; } else if ( type == IST_ShellMomentTensor || type == IST_CurvatureTensor ) { if ( type == IST_ShellMomentTensor ) { - help = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); + s = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStressVector(); } else { - help = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); + s = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveStrainVector(); } - answer.at(1) = help.at(4); // mx - answer.at(2) = help.at(5); // my + answer.at(1) = s.at(4); // mx + answer.at(2) = s.at(5); // my answer.at(3) = 0.0; // mz answer.at(4) = 0.0; // mzy answer.at(5) = 0.0; // mzx - answer.at(6) = help.at(6); // mxy + answer.at(6) = s.at(6); // mxy return 1; } else { - return NLStructuralElement :: giveIPValue(answer, gp, type, tStep); + return StructuralElement::giveIPValue(answer, gp, type, tStep); } } void -Quad1MindlinShell3D :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +Quad1MindlinShell3D::giveEdgeDofMapping(IntArray &answer, int iEdge) const { if ( iEdge == 1 ) { // edge between nodes 1 2 - answer = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + answer = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; } else if ( iEdge == 2 ) { // edge between nodes 2 3 - answer = { 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; + answer = { 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }; } else if ( iEdge == 3 ) { // edge between nodes 3 4 - answer = {13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}; + answer = { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; } else if ( iEdge == 4 ) { // edge between nodes 4 1 - answer = {19, 20, 21, 22, 23, 24, 1, 2, 3, 4, 5, 6}; + answer = { 19, 20, 21, 22, 23, 24, 1, 2, 3, 4, 5, 6 }; } else { OOFEM_ERROR("wrong edge number"); } @@ -576,44 +567,39 @@ Quad1MindlinShell3D :: giveEdgeDofMapping(IntArray &answer, int iEdge) const double -Quad1MindlinShell3D :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +Quad1MindlinShell3D::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { - double detJ = this->interp.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lnodes) ); - return detJ *gp->giveWeight(); + double detJ = this->interp.edgeGiveTransformationJacobian(iEdge, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lnodes) ); + return detJ * gp->giveWeight(); } /* -void -Quad1MindlinShell3D :: computeEdgeIpGlobalCoords(FloatArray &answer, GaussPoint *gp, int iEdge) -{ - FloatArray local; - this->interp.edgeLocal2global( local, iEdge, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lnodes) ); - local.resize(3); - local.at(3) = 0.; - answer.beProductOf(this->lcsMatrix, local); -} -*/ + * void + * Quad1MindlinShell3D :: computeEdgeIpGlobalCoords(FloatArray &answer, GaussPoint *gp, int iEdge) + * { + * FloatArray local; + * this->interp.edgeLocal2global( local, iEdge, gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lnodes) ); + * local.resize(3); + * local.at(3) = 0.; + * answer.beProductOf(this->lcsMatrix, local); + * } + */ int -Quad1MindlinShell3D :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +Quad1MindlinShell3D::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { - double dx, dy, length; - IntArray edgeNodes; - Node *nodeA, *nodeB; - - answer.resize(3, 3); - answer.zero(); + const auto &edgeNodes = this->interp.computeLocalEdgeMapping(iEdge); - this->interp.computeLocalEdgeMapping(edgeNodes, iEdge); + auto nodeA = this->giveNode(edgeNodes.at(1) ); + auto nodeB = this->giveNode(edgeNodes.at(2) ); - nodeA = this->giveNode( edgeNodes.at(1) ); - nodeB = this->giveNode( edgeNodes.at(2) ); - - dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); - dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); - length = sqrt(dx * dx + dy * dy); + double dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); + double dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); + double length = sqrt(dx * dx + dy * dy); /// @todo I haven't even looked at this code yet / Mikael + answer.resize(3, 3); + answer.zero(); answer.at(1, 1) = 1.0; answer.at(2, 2) = dx / length; answer.at(2, 3) = -dy / length; @@ -625,18 +611,17 @@ Quad1MindlinShell3D :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int i void -Quad1MindlinShell3D :: computeLCS() +Quad1MindlinShell3D::computeLCS() { - lcsMatrix.resize(3, 3); // Note! G -> L transformation matrix - FloatArray e1, e2, e3, help; - // compute e1' = [N2-N1] and help = [N4-N1] - e1.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - help.beDifferenceOf( * this->giveNode(4)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - e1.normalize(); - e3.beVectorProductOf(e1, help); - e3.normalize(); - e2.beVectorProductOf(e3, e1); + //auto e1 = normalize(node(2).coord - node(1).coord); + //auto help = node(4).coord - node(1).coord; + auto e1 = normalize( FloatArrayF< 3 >( this->giveNode(2)->giveCoordinates() ) - FloatArrayF< 3 >( this->giveNode(1)->giveCoordinates() ) ); + auto help = FloatArrayF< 3 >( this->giveNode(4)->giveCoordinates() ) - FloatArrayF< 3 >( this->giveNode(1)->giveCoordinates() ); + auto e3 = normalize( cross(e1, help) ); + auto e2 = cross(e3, e1); + + lcsMatrix.resize(3, 3); // Note! G -> L transformation matrix for ( int i = 1; i <= 3; i++ ) { this->lcsMatrix.at(1, i) = e1.at(i); this->lcsMatrix.at(2, i) = e2.at(i); @@ -644,13 +629,13 @@ Quad1MindlinShell3D :: computeLCS() } for ( int i = 1; i <= 4; i++ ) { - this->lnodes [ i - 1 ].beProductOf( this->lcsMatrix, * this->giveNode(i)->giveCoordinates() ); + this->lnodes [ i - 1 ].beProductOf(this->lcsMatrix, this->giveNode(i)->giveCoordinates() ); } } bool -Quad1MindlinShell3D :: computeGtoLRotationMatrix(FloatMatrix &answer) +Quad1MindlinShell3D::computeGtoLRotationMatrix(FloatMatrix &answer) { answer.resize(24, 24); answer.zero(); @@ -665,21 +650,21 @@ Quad1MindlinShell3D :: computeGtoLRotationMatrix(FloatMatrix &answer) } Interface * -Quad1MindlinShell3D :: giveInterface(InterfaceType interface) +Quad1MindlinShell3D::giveInterface(InterfaceType interface) { if ( interface == ZZNodalRecoveryModelInterfaceType ) { - return static_cast< ZZNodalRecoveryModelInterface * >(this); + return static_cast< ZZNodalRecoveryModelInterface * >( this ); } else if ( interface == SPRNodalRecoveryModelInterfaceType ) { - return static_cast< SPRNodalRecoveryModelInterface * >(this); + return static_cast< SPRNodalRecoveryModelInterface * >( this ); } - return NULL; + return nullptr; } void -Quad1MindlinShell3D :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) +Quad1MindlinShell3D::SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) { pap.resize(4); for ( int i = 1; i < 5; i++ ) { @@ -688,7 +673,7 @@ Quad1MindlinShell3D :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) } void -Quad1MindlinShell3D :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) +Quad1MindlinShell3D::SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) { int found = 0; answer.resize(1); diff --git a/src/sm/Elements/Shells/quad1mindlinshell3d.h b/src/sm/Elements/Shells/quad1mindlinshell3d.h index 1624e3298..08bd02a99 100644 --- a/src/sm/Elements/Shells/quad1mindlinshell3d.h +++ b/src/sm/Elements/Shells/quad1mindlinshell3d.h @@ -35,7 +35,7 @@ #ifndef quad1mindlinshell3d_h #define quad1mindlinshell3d_h -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/structuralelement.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -66,13 +66,13 @@ class FEI2dQuadLin; * * @author Mikael Öhman */ -class Quad1MindlinShell3D : public NLStructuralElement, -public ZZNodalRecoveryModelInterface, -public SPRNodalRecoveryModelInterface +class Quad1MindlinShell3D : public StructuralElement, + public ZZNodalRecoveryModelInterface, + public SPRNodalRecoveryModelInterface { protected: /// Cached nodal coordinates in local c.s., - std::vector< FloatArray > lnodes; + std::vector< FloatArray >lnodes; /// Cached coordinates in local c.s., FloatMatrix lcsMatrix; /// Flag controlling reduced (one - point) integration for shear @@ -86,65 +86,62 @@ public SPRNodalRecoveryModelInterface static IntArray drillOrdering; public: - Quad1MindlinShell3D(int n, Domain * d); - virtual ~Quad1MindlinShell3D(); + Quad1MindlinShell3D(int n, Domain *d); - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; - virtual MaterialMode giveMaterialMode() { return _3dShell; } - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } + MaterialMode giveMaterialMode() override { return _3dShell; } + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Quad1MindlinShell3D_Name; } - virtual const char *giveClassName() const { return "Quad1MindlinShell3D"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_Quad1MindlinShell3D_Name; } + const char *giveClassName() const override { return "Quad1MindlinShell3D"; } + void initializeFrom(InputRecord &ir) override; - virtual int computeNumberOfDofs() { return 24; } - virtual int computeNumberOfGlobalDofs() { return 24; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 24; } + int computeNumberOfGlobalDofs() override { return 24; } + void giveDofManDofIDMask(int inode, IntArray &) const override; - virtual void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp); + void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) override; - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane); - virtual double computeVolumeAround(GaussPoint *gp); + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override; + double computeVolumeAround(GaussPoint *gp) override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; virtual void computeLCS(); - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; - virtual Interface *giveInterface(InterfaceType it); - - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP() { return this->numberOfGaussPoints; } - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType() { return SPRPatchType_2dxy; } + Interface *giveInterface(InterfaceType it) override; + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override { return this->numberOfGaussPoints; } + SPRPatchType SPRNodalRecoveryMI_givePatchType() override { return SPRPatchType_2dxy; } protected: - virtual void computeGaussPoints(); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - - virtual void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); - void computeVectorOfUnknowns(ValueModeType mode, TimeStep* tStep, FloatArray &shellUnknowns, FloatArray &drillUnknowns); + void computeGaussPoints() override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; + void computeVectorOfUnknowns(ValueModeType mode, TimeStep *tStep, FloatArray &shellUnknowns, FloatArray &drillUnknowns); //virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, GaussPoint *gp) { answer.clear(); } //virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const { answer.clear(); } - //virtual IntegrationRule *GetSurfaceIntegrationRule(int i) { return NULL; } //virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { return 0.; } }; } // end namespace oofem diff --git a/src/sm/Elements/Shells/rershell.C b/src/sm/Elements/Shells/rershell.C index cbde83583..ed7427744 100644 --- a/src/sm/Elements/Shells/rershell.C +++ b/src/sm/Elements/Shells/rershell.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Shells/rershell.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/Shells/rershell.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "node.h" #include "material.h" #include "crosssection.h" @@ -91,15 +91,15 @@ RerShell :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui FloatArray b(3), c(3), nodeCoords; double x1, x2, x3, y1, y2, y3, area; - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(1)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(1)->giveCoordinates() ); x1 = nodeCoords.at(1); y1 = nodeCoords.at(2); - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(2)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(2)->giveCoordinates() ); x2 = nodeCoords.at(1); y2 = nodeCoords.at(2); - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(3)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(3)->giveCoordinates() ); x3 = nodeCoords.at(1); y3 = nodeCoords.at(2); @@ -165,7 +165,7 @@ RerShell :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 8) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 8); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } @@ -183,15 +183,15 @@ RerShell :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) l2 = iLocCoord.at(2); l3 = 1.0 - l1 - l2; - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(1)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(1)->giveCoordinates() ); x1 = nodeCoords.at(1); y1 = nodeCoords.at(2); - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(2)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(2)->giveCoordinates() ); x2 = nodeCoords.at(1); y2 = nodeCoords.at(2); - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(3)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(3)->giveCoordinates() ); x3 = nodeCoords.at(1); y3 = nodeCoords.at(2); @@ -255,15 +255,15 @@ RerShell :: giveArea() double x1, x2, x3, y1, y2, y3; - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(1)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(1)->giveCoordinates() ); x1 = nodeCoords.at(1); y1 = nodeCoords.at(2); - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(2)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(2)->giveCoordinates() ); x2 = nodeCoords.at(1); y2 = nodeCoords.at(2); - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(3)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(3)->giveCoordinates() ); x3 = nodeCoords.at(1); y3 = nodeCoords.at(2); @@ -271,33 +271,28 @@ RerShell :: giveArea() } -IRResultType -RerShell :: initializeFrom(InputRecord *ir) +void +RerShell :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 1; - IRResultType result = StructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralElement :: initializeFrom(ir); if ( numberOfGaussPoints != 1 ) { numberOfGaussPoints = 1; } - - return IRRT_OK; } void RerShell :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give3dShellStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give3dShellStiffMtrx(rMode, gp, tStep); } void RerShell :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_Shell(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_Shell(strain, gp, tStep); } void @@ -398,24 +393,24 @@ RerShell :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords //rotate the input point Coordinate System into the element CS FloatArray inputCoords_ElCS; - this->giveLocalCoordinates( inputCoords_ElCS, const_cast< FloatArray & >(coords) ); + this->giveLocalCoordinates( inputCoords_ElCS, coords ); //Nodes are defined in the global CS, so they also need to be rotated into the element CS, therefore get the node points and //rotate them into the element CS FloatArray nodeCoords; double x1, x2, x3, y1, y2, y3, z1, z2, z3; - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(1)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(1)->giveCoordinates() ); x1 = nodeCoords.at(1); y1 = nodeCoords.at(2); z1 = nodeCoords.at(3); - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(2)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(2)->giveCoordinates() ); x2 = nodeCoords.at(1); y2 = nodeCoords.at(2); z2 = nodeCoords.at(3); - this->giveLocalCoordinates( nodeCoords, * ( this->giveNode(3)->giveCoordinates() ) ); + this->giveLocalCoordinates( nodeCoords, this->giveNode(3)->giveCoordinates() ); x3 = nodeCoords.at(1); y3 = nodeCoords.at(2); z3 = nodeCoords.at(3); @@ -498,16 +493,9 @@ RerShell :: computeGtoLRotationMatrix(FloatMatrix &answer) void RerShell :: giveLocalCoordinates(FloatArray &answer, const FloatArray &global) -// -// Returns global coordinates given in global vector -// transformed into local coordinate system of the -// receiver -// { - // test the parameter if ( global.giveSize() != 3 ) { OOFEM_ERROR("cannot transform coordinates- size mismatch"); - exit(1); } // first ensure that receiver's GtoLRotationMatrix[3,3] diff --git a/src/sm/Elements/Shells/rershell.h b/src/sm/Elements/Shells/rershell.h index 1ebcad010..e23df3dcd 100644 --- a/src/sm/Elements/Shells/rershell.h +++ b/src/sm/Elements/Shells/rershell.h @@ -35,8 +35,8 @@ #ifndef rershell_h #define rershell_h -#include "../sm/Elements/Shells/cct3d.h" -#include "../sm/CrossSections/layeredcrosssection.h" +#include "sm/Elements/Shells/cct3d.h" +#include "sm/CrossSections/layeredcrosssection.h" #define _IFT_RerShell_Name "rershell" @@ -67,66 +67,62 @@ class RerShell : public CCTPlate3d public: RerShell(int n, Domain * d); - virtual ~RerShell() { - } + virtual ~RerShell() { } - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual int giveLocalCoordinateSystem(FloatMatrix &answer); + int giveLocalCoordinateSystem(FloatMatrix &answer) override; void giveLocalCoordinates(FloatArray &answer, const FloatArray &global); - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords); + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; // void giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - - virtual const FloatMatrix *computeGtoLRotationMatrix() {return CCTPlate3d::computeGtoLRotationMatrix();} - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); - + void printOutputAt(FILE *file, TimeStep *tStep) override; + const FloatMatrix *computeGtoLRotationMatrix() override { return CCTPlate3d::computeGtoLRotationMatrix(); } + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; // layered cross section support functions - virtual void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, - GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep); - - virtual Interface *giveInterface(InterfaceType it); + void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) override; - virtual int computeNumberOfDofs() { return 18; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + Interface *giveInterface(InterfaceType it) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int computeNumberOfDofs() override { return 18; } + void giveDofManDofIDMask(int inode, IntArray &) const override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; // io routines #ifdef __OOFEG //void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep); - //virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + //void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_RerShell_Name; } - virtual const char *giveClassName() const { return "RerShell"; } + const char *giveInputRecordName() const override { return _IFT_RerShell_Name; } + const char *giveClassName() const override { return "RerShell"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } - virtual MaterialMode giveMaterialMode() { return _3dShell; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } + MaterialMode giveMaterialMode() override { return _3dShell; } protected: - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void computeGaussPoints(); - virtual double giveArea(); + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeGaussPoints() override; + double giveArea(); }; } // end namespace oofem #endif // rershell_h diff --git a/src/sm/Elements/Shells/shell7base.C b/src/sm/Elements/Shells/shell7base.C index 3cce92959..741794e61 100644 --- a/src/sm/Elements/Shells/shell7base.C +++ b/src/sm/Elements/Shells/shell7base.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Shells/shell7base.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/Loads/constantpressureload.h" +#include "sm/Elements/Shells/shell7base.h" +#include "sm/Materials/structuralms.h" +#include "sm/Loads/constantpressureload.h" #include "node.h" #include "load.h" #include "mathfem.h" @@ -46,6 +46,8 @@ #include "vtkxmlexportmodule.h" #include "fracturemanager.h" #include "dof.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "connectivitytable.h" #include @@ -60,14 +62,13 @@ Shell7Base :: Shell7Base(int n, Domain *aDomain) : NLStructuralElement(n, aDomai recoverStress(false) {} -IRResultType Shell7Base :: initializeFrom(InputRecord *ir) +void Shell7Base :: initializeFrom(InputRecord &ir) { - IRResultType result = NLStructuralElement :: initializeFrom(ir); + NLStructuralElement :: initializeFrom(ir); //IR_GIVE_OPTIONAL_FIELD(ir, this->recoverStress, _IFT_Shell7base_recoverStress); - if ( ir->hasField(_IFT_Shell7base_recoverStress) ) { + if ( ir.hasField(_IFT_Shell7base_recoverStress) ) { this->recoverStress = true; } - return result; } @@ -101,7 +102,6 @@ Shell7Base :: postInitialize() { 9, 2, 4 }, { 8, 7, 3 } }; - this->nlGeometry = 1; } @@ -136,7 +136,7 @@ Interface *Shell7Base :: giveInterface(InterfaceType it) return static_cast< FailureModuleElementInterface * >( this ); default: - return StructuralElement :: giveInterface(it); + return NLStructuralElement :: giveInterface(it); } } @@ -154,6 +154,7 @@ Shell7Base :: giveNumberOfDofs() return 7 * this->giveNumberOfDofManagers(); } + int Shell7Base :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { @@ -169,16 +170,15 @@ Shell7Base :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lco answer.clear(); for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) { - FloatArray &xbar = *this->giveNode(i)->giveCoordinates(); - const FloatArray &M = this->giveInitialNodeDirector(i); + const auto &xbar = this->giveNode(i)->giveCoordinates(); + const auto &M = this->giveInitialNodeDirector(i); answer.add(N.at(i), ( xbar + zeta * M )); } - - return 1; } + int Shell7Base :: computeGlobalCoordinatesOnEdge(FloatArray &answer, const FloatArray &lcoords, const int iEdge) { @@ -197,9 +197,8 @@ Shell7Base :: computeGlobalCoordinatesOnEdge(FloatArray &answer, const FloatArra } - double -Shell7Base::giveGlobalZcoord( const FloatArray &lCoords ) +Shell7Base::giveGlobalZcoord( const FloatArrayF<3> &lCoords ) { return lCoords.at(3) * this->layeredCS->give( CS_Thickness, lCoords, this, false ) * 0.5; } @@ -213,119 +212,118 @@ Shell7Base :: giveGlobalZcoordInLayer(double xi, int layer) } - // Base vectors #if 1 -void -Shell7Base :: evalInitialCovarBaseVectorsAt(const FloatArray &lcoords, FloatMatrix &Gcov) +FloatMatrixF<3,3> +Shell7Base :: evalInitialCovarBaseVectorsAt(const FloatArrayF<3> &lcoords) { double zeta = giveGlobalZcoord( lcoords ); - FloatArray M; FloatMatrix dNdxi; // In plane base vectors this->fei->evaldNdxi( dNdxi, lcoords, FEIElementGeometryWrapper(this) ); - FloatArray G1, G2, nodeCoords; + FloatArrayF<3> G1, G2; for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) { - FloatArray &xbar = * this->giveNode(i)->giveCoordinates(); - M = this->giveInitialNodeDirector(i); - nodeCoords = (xbar + zeta*M); - G1.add(dNdxi.at(i, 1), nodeCoords); - G2.add(dNdxi.at(i, 2), nodeCoords); + const auto &xbar = FloatArrayF<3>(this->giveNode(i)->giveCoordinates()); + const auto &M = this->giveInitialNodeDirector(i); + const auto &nodeCoords = (xbar + zeta*M); + G1 += dNdxi.at(i, 1) * nodeCoords; + G2 += dNdxi.at(i, 2) * nodeCoords; } // Out of plane base vector = director - FloatArray G3; - this->evalInitialDirectorAt(lcoords, G3); // G3=M + auto G3 = this->evalInitialDirectorAt(lcoords); // G3=M - Gcov.resize(3,3); - Gcov.setColumn(G1,1); Gcov.setColumn(G2,2); Gcov.setColumn(G3,3); + FloatMatrixF<3,3> gcov; + gcov.setColumn(G1, 0); + gcov.setColumn(G2, 1); + gcov.setColumn(G3, 2); + return gcov; } -void -Shell7Base :: edgeEvalInitialCovarBaseVectorsAt(const FloatArray &lcoords, const int iedge, FloatArray &G1, FloatArray &G3) +std::pair, FloatArrayF<3>> +Shell7Base :: edgeEvalInitialCovarBaseVectorsAt(const FloatArrayF<1> &lcoords, const int iedge) { double zeta = 0.0; // no variation i z (yet) - FloatArray M, dNdxi, nodeCoords; - IntArray edgeNodes; - this->fei->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->fei->computeLocalEdgeMapping(iedge); + FloatArray dNdxi; this->fei->edgeEvaldNdxi( dNdxi, iedge, lcoords, FEIElementGeometryWrapper(this) ); // Base vector along edge - G1.clear(); + FloatArrayF<3> G1; for ( int i = 1; i <= edgeNodes.giveSize(); i++ ) { - FloatArray &xbar = * this->giveNode(edgeNodes.at(i))->giveCoordinates(); - M = this->giveInitialNodeDirector(edgeNodes.at(i)); - nodeCoords = (xbar + zeta*M); - G1.add(dNdxi.at(i), nodeCoords); + const auto &xbar = FloatArrayF<3>(this->giveNode(edgeNodes.at(i))->giveCoordinates()); + auto M = this->giveInitialNodeDirector(edgeNodes.at(i)); + auto nodeCoords = (xbar + zeta*M); + G1 += dNdxi.at(i) * nodeCoords; } // Director will be the second base vector - this->edgeEvalInitialDirectorAt(lcoords, G3, iedge); + auto G3 = this->edgeEvalInitialDirectorAt(lcoords, iedge); + + return {G1, G3}; } -void -Shell7Base :: evalInitialContravarBaseVectorsAt(const FloatArray &lCoords, FloatMatrix &Gcon) +FloatMatrixF<3,3> +Shell7Base :: evalInitialContravarBaseVectorsAt(const FloatArrayF<3> &lCoords) { - FloatMatrix Gcov; - this->evalInitialCovarBaseVectorsAt(lCoords, Gcov); - this->giveDualBase(Gcov, Gcon); + auto Gcov = this->evalInitialCovarBaseVectorsAt(lCoords); + return this->giveDualBase(Gcov); } -void -Shell7Base :: giveDualBase( FloatMatrix &base1, FloatMatrix &base2) +FloatMatrixF<3,3> +Shell7Base :: giveDualBase( FloatMatrixF<3,3> &base1) { // Computes the dual base through thte inversion of the metric tensor - FloatMatrix gMetric, ginv; - gMetric.beTProductOf(base1,base1); // Metric tensor - ginv.beInverseOf(gMetric); - base2.beProductTOf(base1,ginv); + auto gMetric = Tdot(base1,base1); // Metric tensor + auto ginv = inv(gMetric); + return dotT(base1, ginv); } -void -Shell7Base :: evalInitialDirectorAt(const FloatArray &lcoords, FloatArray &answer) +FloatArrayF<3> +Shell7Base :: evalInitialDirectorAt(const FloatArrayF<3> &lcoords) { // Interpolates between the node directors FloatArray N; this->fei->evalN( N, lcoords, FEIElementGeometryWrapper(this) ); - answer.clear(); + FloatArrayF<3> g3; for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) { - answer.add( N.at(i), this->giveInitialNodeDirector(i) ); + g3 += N.at(i) * this->giveInitialNodeDirector(i); } + return g3; } -void -Shell7Base :: edgeEvalInitialDirectorAt(const FloatArray &lcoords, FloatArray &answer, const int iEdge) +FloatArrayF<3> +Shell7Base :: edgeEvalInitialDirectorAt(const FloatArrayF<1> &lcoords, const int iEdge) { // Interpolates between the node directors along an edge FloatArray N; - IntArray edgeNodes; - this->fei->computeLocalEdgeMapping(edgeNodes, iEdge); + const auto &edgeNodes = this->fei->computeLocalEdgeMapping(iEdge); this->fei->edgeEvalN( N, iEdge, lcoords, FEIElementGeometryWrapper(this) ); - answer.clear(); + FloatArrayF<3> answer; for ( int i = 1; i <= edgeNodes.giveSize(); i++ ) { - answer.add( N.at(i), this->giveInitialNodeDirector( edgeNodes.at(i) ) ); + answer += N.at(i) * this->giveInitialNodeDirector( edgeNodes.at(i) ); } + return answer; } - void Shell7Base :: setupInitialNodeDirectors() { // Compute directors as normals to the surface - FloatArray M(3), G1(3), G2(3), lcoords(2); + FloatArray lcoords; FloatMatrix localNodeCoords; this->giveInterpolation()->giveLocalNodeCoords(localNodeCoords); @@ -336,31 +334,25 @@ Shell7Base :: setupInitialNodeDirectors() lcoords.beColumnOf(localNodeCoords,node); this->fei->evaldNdxi( dNdxi, lcoords, FEIElementGeometryWrapper(this) ); - G1.zero(); - G2.zero(); + FloatArrayF<3> G1, G2; // base vectors of the initial surface for ( int i = 1; i <= nDofMan; i++ ) { - FloatArray *nodeI = this->giveNode(i)->giveCoordinates(); - G1.add(dNdxi.at(i, 1), * nodeI); - G2.add(dNdxi.at(i, 2), * nodeI); + const auto &nodeI = FloatArrayF<3>(this->giveNode(i)->giveCoordinates()); + G1 += dNdxi.at(i, 1) * nodeI; + G2 += dNdxi.at(i, 2) * nodeI; } - - M.beVectorProductOf(G1, G2); - M.normalize(); - this->initialNodeDirectors [ node - 1 ] = M; + this->initialNodeDirectors [ node - 1 ] = normalize(cross(G1, G2)); } } - -void -Shell7Base :: evalCovarBaseVectorsAt(const FloatArray &lcoords, FloatMatrix &gcov, FloatArray &genEps, TimeStep *tStep) +FloatMatrixF<3,3> +Shell7Base :: evalCovarBaseVectorsAt(const FloatArrayF<3> &lcoords, FloatArray &genEps, TimeStep *tStep) { // Evaluates the covariant base vectors in the current configuration - FloatArray g1; FloatArray g2; FloatArray g3; double zeta = giveGlobalZcoord( lcoords ); - FloatArray dxdxi1, dxdxi2, m, dmdxi1, dmdxi2; + FloatArrayF<3> dxdxi1, dxdxi2, m, dmdxi1, dmdxi2; double dgamdxi1, dgamdxi2, gam; this->giveGeneralizedStrainComponents(genEps, dxdxi1, dxdxi2, dmdxi1, dmdxi2, m, dgamdxi1, dgamdxi2, gam); @@ -368,36 +360,35 @@ Shell7Base :: evalCovarBaseVectorsAt(const FloatArray &lcoords, FloatMatrix &gco double fac2 = ( 0.5 * zeta * zeta ); double fac3 = ( 1.0 + zeta * gam ); - g1 = dxdxi1 + fac1*dmdxi1 + fac2*dgamdxi1*m; - g2 = dxdxi2 + fac1*dmdxi2 + fac2*dgamdxi2*m; - g3 = fac3*m; + auto g1 = dxdxi1 + fac1*dmdxi1 + fac2*dgamdxi1*m; + auto g2 = dxdxi2 + fac1*dmdxi2 + fac2*dgamdxi2*m; + auto g3 = fac3*m; - gcov.resize(3,3); - gcov.setColumn(g1,1); gcov.setColumn(g2,2); gcov.setColumn(g3,3); + FloatMatrixF<3,3> gcov; + gcov.setColumn(g1,0); gcov.setColumn(g2,1); gcov.setColumn(g3,2); + return gcov; } -void -Shell7Base :: edgeEvalCovarBaseVectorsAt(const FloatArray &lcoords, const int iedge, FloatMatrix &gcov, TimeStep *tStep) +FloatMatrixF<3,3> +Shell7Base :: edgeEvalCovarBaseVectorsAt(const FloatArrayF<3> &lcoords, const int iedge, TimeStep *tStep) { // Evaluates the covariant base vectors in the current configuration for an edge double zeta = lcoords.at(3); FloatArray solVecEdge; FloatMatrix B; - IntArray edgeNodes; - this->fei->computeLocalEdgeMapping(edgeNodes, iedge); + //const auto &edgeNodes = this->fei->computeLocalEdgeMapping(iedge); this->edgeComputeBmatrixAt(lcoords, B, 1, ALL_STRAINS); this->edgeGiveUpdatedSolutionVector(solVecEdge, iedge, tStep); FloatArray genEpsEdge; // generalized strain genEpsEdge.beProductOf(B, solVecEdge); // [dxdxi, dmdxi, m, dgamdxi, gam]^T - FloatArray dxdxi, m, dmdxi; - dxdxi = { 3, genEpsEdge.at(1), genEpsEdge.at(2), genEpsEdge.at(3) }; - dmdxi = { genEpsEdge.at(4), genEpsEdge.at(5), genEpsEdge.at(6) }; - m = { genEpsEdge.at(7), genEpsEdge.at(8), genEpsEdge.at(9) }; + FloatArrayF<3> dxdxi = { genEpsEdge.at(1), genEpsEdge.at(2), genEpsEdge.at(3) }; + FloatArrayF<3> dmdxi = { genEpsEdge.at(4), genEpsEdge.at(5), genEpsEdge.at(6) }; + FloatArrayF<3> m = { genEpsEdge.at(7), genEpsEdge.at(8), genEpsEdge.at(9) }; double dgamdxi = genEpsEdge.at(10); double gam = genEpsEdge.at(11); @@ -405,18 +396,15 @@ Shell7Base :: edgeEvalCovarBaseVectorsAt(const FloatArray &lcoords, const int ie double fac2 = ( 0.5 * zeta * zeta ); double fac3 = ( 1.0 + zeta * gam ); - FloatArray g1, g2, g3; - g2 = dxdxi + fac1*dmdxi + fac2*dgamdxi*m; // base vector along the edge - g3 = fac3*m; // director field + auto g2 = normalize(dxdxi + fac1*dmdxi + fac2*dgamdxi*m); // base vector along the edge + auto g3 = normalize(fac3*m); // director field + auto g1 = normalize(cross(g2, g3)); - g2.normalize(); - g3.normalize(); - g1.beVectorProductOf(g2, g3); - g1.normalize(); - gcov.resize(3,3); - gcov.setColumn(g1,1); - gcov.setColumn(g2,2); - gcov.setColumn(g3,3); + FloatMatrixF<3,3> gcov; + gcov.setColumn(g1, 0); + gcov.setColumn(g2, 1); + gcov.setColumn(g3, 2); + return gcov; } @@ -432,7 +420,6 @@ Shell7Base :: edgeEvalCovarBaseVectorsAt(const FloatArray &lcoords, const int ie void Shell7Base :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { - FloatArray solVec; this->giveUpdatedSolutionVector(solVec, tStep); // a @@ -456,14 +443,14 @@ Shell7Base :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, } -void -Shell7Base :: computeLambdaGMatrices(FloatMatrix lambda [ 3 ], FloatArray &genEps, double zeta) +std::array, 3> +Shell7Base :: computeLambdaGMatrices(FloatArray &genEps, double zeta) { // computes the lambda^g matrices associated with the variation and linearization of the base vectors g_i. // \delta g_i = lambda_i * \delta n and \Delta g_i = lambda_i * \Delta n // \delta n = B * \delta a and \Delta n = B * \Delta a // @todo optimize method - FloatArray m(3), dm1(3), dm2(3), temp1; + FloatArrayF<3> m, dm1, dm2, temp1; double dgam1, dgam2, gam; this->giveGeneralizedStrainComponents(genEps, temp1, temp1, dm1, dm2, m, dgam1, dgam2, gam); @@ -472,47 +459,42 @@ Shell7Base :: computeLambdaGMatrices(FloatMatrix lambda [ 3 ], FloatArray &genEp double b = 0.5 * zeta * zeta; double c = 1.0 + gam * zeta; - // lambda1 = ( I, 0, a*I, 0 , b*dgam1*I, b*m, 0 , b*dm1 ) - // lambda2 = ( 0, I, 0 , a*I, b*dgam2*I, 0 , b*m, b*dm2 ) - - FloatMatrix eye(3,3), aEye(3,3); - eye.beUnitMatrix(); - aEye=eye; aEye.times(a); - lambda[ 0 ].resize(3,18); lambda[ 0 ].zero(); - lambda[ 1 ].resize(3,18); lambda[ 1 ].zero(); - - lambda[ 0 ].setSubMatrix(eye,1,1); lambda[ 0 ].setSubMatrix(aEye,1,7); - lambda[ 1 ].setSubMatrix(eye,1,4); lambda[ 1 ].setSubMatrix(aEye,1,10); + auto bm = b * m; + auto bdm1 = b * dm1; + auto bdm2 = b * dm2; - FloatMatrix bdg1eye(3,3), bdg2eye(3,3); - bdg1eye = eye; bdg1eye.times(b*dgam1); - bdg2eye = eye; bdg2eye.times(b*dgam2); - lambda[ 0 ].setSubMatrix(bdg1eye,1,13); - lambda[ 1 ].setSubMatrix(bdg2eye,1,13); + std::array, 3> lambda; - FloatArray bm(3), bdm1(3), bdm2(3); - bm = b*m; - bdm1 = b*dm1; - bdm2 = b*dm2; - lambda[ 0 ].setColumn(bm,16); lambda[ 0 ].setColumn(bdm1,18); - lambda[ 1 ].setColumn(bm,17); lambda[ 1 ].setColumn(bdm2,18); + // lambda1 = ( I, 0, a*I, 0 , b*dgam1*I, b*m, 0 , b*dm1 ) + lambda[ 0 ](0,0) = lambda[ 0 ](1,1) = lambda[ 0 ](2,2) = 1.; + lambda[ 0 ](0,6) = lambda[ 0 ](1,7) = lambda[ 0 ](2,8) = a; + lambda[ 0 ](0,12) = lambda[ 0 ](1,13) = lambda[ 0 ](2,14) = b * dgam1; + lambda[ 0 ].setColumn(bm, 15); + lambda[ 0 ].setColumn(bdm1, 17); + + // lambda2 = ( 0, I, 0 , a*I, b*dgam2*I, 0 , b*m, b*dm2 ) + lambda[ 1 ](0,3) = lambda[ 1 ](1,4) = lambda[ 1 ](2,5) = 1.; + lambda[ 1 ](0,9) = lambda[ 1 ](1,10) = lambda[ 1 ](2,11) = a; + lambda[ 1 ](0,12) = lambda[ 1 ](1,13) = lambda[ 1 ](2,14) = b * dgam2; + lambda[ 1 ].setColumn(bm, 16); + lambda[ 1 ].setColumn(bdm2, 17); // lambda3 = ( 0, 0, 0 , 0 , c*I , 0 , 0 , xi*m ) - lambda[ 2 ].resize(3,18); lambda[ 2 ].zero(); - lambda[ 2 ].at(1,13) = lambda[ 2 ].at(2,14) = lambda[ 2 ].at(3,15) = c; - FloatArray zm(3); - zm = zeta*m; - lambda[ 2 ].setColumn(zm,18); + lambda[ 2 ](0,12) = lambda[ 2 ](1,13) = lambda[ 2 ](2,14) = c; + auto zm = zeta * m; + lambda[ 2 ].setColumn(zm, 17); + + return lambda; } -void -Shell7Base :: computeLambdaNMatrix(FloatMatrix &lambda, FloatArray &genEps, double zeta) + +FloatMatrixF<3,7> +Shell7Base :: computeLambdaNMatrix(FloatArray &genEps, double zeta) { // computes the lambda^n matrix associated with the variation and linearization of the position vector x. // \delta x = lambda * \delta \hat{x} with \hat{x} = [\bar{x}, m, \gamma] - FloatArray m(3); - m = { genEps.at(13), genEps.at(14), genEps.at(15) }; + FloatArrayF<3> m = { genEps.at(13), genEps.at(14), genEps.at(15) }; double gam = genEps.at(18); // thickness coefficients @@ -520,19 +502,18 @@ Shell7Base :: computeLambdaNMatrix(FloatMatrix &lambda, FloatArray &genEps, doub double b = 0.5 * zeta * zeta; // lambda = ( I, a*I, b*m ) - lambda.resize(3,7); - lambda.zero(); + FloatMatrixF<3,7> lambda; lambda.at(1,1) = lambda.at(2,2) = lambda.at(3,3) = 1.0; lambda.at(1,4) = lambda.at(2,5) = lambda.at(3,6) = a; - lambda.setColumn(b*m,7); - + lambda.setColumn(b*m, 6); + return lambda; } void Shell7Base :: computeBulkTangentMatrix(FloatMatrix &answer, FloatArray &solVec, TimeStep *tStep) { - FloatMatrix A [ 3 ] [ 3 ], lambda[ 3 ], A_lambda(3,18), LB; + FloatMatrix A [ 3 ] [ 3 ], A_lambda(3,18), LB; FloatMatrix L(18,18), B; FloatMatrix tempAnswer; @@ -547,7 +528,7 @@ Shell7Base :: computeBulkTangentMatrix(FloatMatrix &answer, FloatArray &solVec, StructuralMaterial *mat = static_cast< StructuralMaterial* >( domain->giveMaterial( this->layeredCS->giveLayerMaterial(layer) ) ); for ( GaussPoint *gp : *integrationRulesArray [ layer - 1 ] ) { - const FloatArray &lCoords = gp->giveNaturalCoordinates(); + const auto &lCoords = gp->giveNaturalCoordinates(); this->computeBmatrixAt(lCoords, B); genEps.beProductOf(B, solVec); @@ -555,7 +536,7 @@ Shell7Base :: computeBulkTangentMatrix(FloatMatrix &answer, FloatArray &solVec, Shell7Base :: computeLinearizedStiffness(gp, mat, tStep, A); double zeta = giveGlobalZcoord(lCoords); - this->computeLambdaGMatrices(lambda, genEps, zeta); + auto lambda = this->computeLambdaGMatrices(genEps, zeta); // L = sum_{i,j} (lambdaI_i)^T * A^ij * lambdaJ_j // note: L will only be symmetric if lambdaI = lambdaJ (not the case for xfem) @@ -576,23 +557,22 @@ Shell7Base :: computeBulkTangentMatrix(FloatMatrix &answer, FloatArray &solVec, } tempAnswer.symmetrized(); - const IntArray &ordering = this->giveOrderingDofTypes(); + const auto &ordering = this->giveOrderingDofTypes(); answer.assemble(tempAnswer, ordering, ordering); } + void Shell7Base :: computeLinearizedStiffness(GaussPoint *gp, StructuralMaterial *mat, TimeStep *tStep, FloatMatrix A [ 3 ] [ 3 ]) { - const FloatArray &lcoords = gp->giveNaturalCoordinates(); - FloatMatrix D; + const auto &lcoords = gp->giveNaturalCoordinates(); // Material stiffness when internal work is formulated in terms of P and F: // \Delta(P*G^I) = L^IJ * \Delta g_J // A[I][J] = L^IJ = L_klmn * [G^I]_l * [G^J]_n - mat->give3dMaterialStiffnessMatrix_dPdF(D, TangentStiffness, gp, tStep); // D_ijkl - cartesian system (Voigt) - FloatMatrix G; - this->evalInitialContravarBaseVectorsAt(lcoords, G); + auto D = mat->give3dMaterialStiffnessMatrix_dPdF(TangentStiffness, gp, tStep); // D_ijkl - cartesian system (Voigt) + auto G = this->evalInitialContravarBaseVectorsAt(lcoords); for (int I = 1; I <= 3; I++) { for (int J = I; J <= 3; J++) { A[I - 1][J - 1].resize(3, 3); @@ -620,11 +600,9 @@ Shell7Base :: computeLinearizedStiffness(GaussPoint *gp, StructuralMaterial *mat // position 32 A [ 2 ] [ 1 ].beTranspositionOf( A [ 1 ] [ 2 ] ); - - - } + void Shell7Base :: computePressureTangentMatrix(FloatMatrix &answer, Load *load, const int iSurf, TimeStep *tStep) { @@ -636,10 +614,9 @@ Shell7Base :: computePressureTangentMatrix(FloatMatrix &answer, Load *load, cons GaussIntegrationRule iRule(1, this); iRule.SetUpPointsOnWedge(nPointsTri, 1, _3dMat); ///@todo replce with triangle which has a xi3-coord - FloatMatrix N, B, LB, NLB, L(7, 18), gcov, W1, W2; + FloatMatrix N, B, LB, NLB, L(7, 18); FloatArray lcoords(3), solVec, pressure; - FloatArray g1, g2, genEps; - FloatMatrix lambdaG [ 3 ], lambdaN; + FloatArray genEps; double xi = pLoad->giveLoadOffset(); this->giveUpdatedSolutionVector(solVec, tStep); @@ -659,14 +636,14 @@ Shell7Base :: computePressureTangentMatrix(FloatMatrix &answer, Load *load, cons // Traction tangent, L = lambdaN * ( W2*lambdaG_1 - W1*lambdaG_2 ) load->computeValueAt(pressure, tStep, ip->giveNaturalCoordinates(), VM_Total); // pressure component - this->evalCovarBaseVectorsAt(lcoords, gcov, genEps, tStep); - g1.beColumnOf(gcov,1); - g2.beColumnOf(gcov,2); - W1 = this->giveAxialMatrix(g1); - W2 = this->giveAxialMatrix(g2); + auto gcov = this->evalCovarBaseVectorsAt(lcoords, genEps, tStep); + auto g1 = gcov.column(0); + auto g2 = gcov.column(1); + auto W1 = this->giveAxialMatrix(g1); + auto W2 = this->giveAxialMatrix(g2); - this->computeLambdaGMatrices(lambdaG, genEps, zeta); - this->computeLambdaNMatrix(lambdaN, genEps, zeta); + auto lambdaG = this->computeLambdaGMatrices(genEps, zeta); + auto lambdaN = this->computeLambdaNMatrix(genEps, zeta); FloatMatrix W2L, W1L; W2L.beProductOf(W2,lambdaG[0]); W1L.beProductOf(W1,lambdaG[1]); @@ -683,8 +660,8 @@ Shell7Base :: computePressureTangentMatrix(FloatMatrix &answer, Load *load, cons } -FloatMatrix -Shell7Base :: giveAxialMatrix(const FloatArray &v) +FloatMatrixF<3,3> +Shell7Base :: giveAxialMatrix(const FloatArrayF<3> &v) { // creates the skew-symmetric matrix W defined such that // crossProduct(u,v) = W(v)*u @@ -692,8 +669,7 @@ Shell7Base :: giveAxialMatrix(const FloatArray &v) // -v(3) 0 v(1) // v(2) -v(1) 0 ] // - FloatMatrix answer(3,3); - answer.zero(); + FloatMatrixF<3,3> answer; answer.at(2, 3) = v.at(1); answer.at(3, 2) = -v.at(1); answer.at(1, 3) = -v.at(2); @@ -711,25 +687,23 @@ Shell7Base :: giveAxialMatrix(const FloatArray &v) #if 1 -void -Shell7Base :: computeFAt(const FloatArray &lCoords, FloatMatrix &answer, FloatArray &genEps, TimeStep *tStep) +FloatMatrixF<3,3> +Shell7Base :: computeFAt(const FloatArrayF<3> &lCoords, FloatArray &genEps, TimeStep *tStep) { // Computes the deformation gradient in matrix form as open product(g_i, G^i) = gcov*Gcon^T - FloatMatrix gcov, Gcon; - this->evalCovarBaseVectorsAt(lCoords, gcov, genEps, tStep); - this->evalInitialContravarBaseVectorsAt(lCoords, Gcon); - answer.beProductTOf(gcov, Gcon); + auto gcov = this->evalCovarBaseVectorsAt(lCoords, genEps, tStep); + auto Gcon = this->evalInitialContravarBaseVectorsAt(lCoords); + return dotT(gcov, Gcon); } -void -Shell7Base :: computeStressMatrix(FloatMatrix &answer, FloatArray &genEps, GaussPoint *gp, Material *mat, TimeStep *tStep) + +FloatMatrixF<3,3> +Shell7Base :: computeStressMatrix(FloatArray &genEps, GaussPoint *gp, Material *mat, TimeStep *tStep) { - FloatMatrix F; - FloatArray vF, vP; - computeFAt(gp->giveNaturalCoordinates(), F, genEps, tStep); - vF.beVectorForm(F); - static_cast< StructuralMaterial * >( mat )->giveFirstPKStressVector_3d(vP, gp, vF, tStep); - answer.beMatrixForm(vP); + auto F = computeFAt(gp->giveNaturalCoordinates(), genEps, tStep); + auto vF = to_voigt_form(F); + auto vP = static_cast< StructuralMaterial * >( mat )->giveFirstPKStressVector_3d(vF, gp, tStep); + return from_voigt_form(vP); } @@ -739,14 +713,13 @@ Shell7Base :: computeCauchyStressVector(FloatArray &answer, GaussPoint *gp, Time // Compute Cauchy stress from 2nd Piola stress FloatArray solVec; this->giveUpdatedSolutionVector(solVec, tStep); - FloatMatrix B; - const FloatArray &lCoords = gp->giveNaturalCoordinates(); + const auto &lCoords = gp->giveNaturalCoordinates(); + FloatMatrix B; this->computeBmatrixAt(lCoords, B); FloatArray genEps; - genEps.beProductOf(B, solVec); - FloatMatrix F; - this->computeFAt(lCoords, F, genEps, tStep); + + auto F = this->computeFAt(lCoords, genEps, tStep); FloatArray vS; giveIPValue(vS, gp, IST_StressTensor, tStep); // expects Second PK stress @@ -755,7 +728,7 @@ Shell7Base :: computeCauchyStressVector(FloatArray &answer, GaussPoint *gp, Time S.beMatrixFormOfStress(vS); temp.beProductTOf(S,F); sigma.beProductOf(F,temp); - sigma.times( 1.0/F.giveDeterminant() ); + sigma.times( 1.0/ det(F) ); answer.beSymVectorForm(sigma); } @@ -834,16 +807,13 @@ Shell7Base :: computeSectionalForcesAt(FloatArray §ionalForces, IntegrationP { // New, in terms of PK1 stress // \Lambda_i * P * G^I - FloatArray PG1(3), PG2(3), PG3(3); - FloatMatrix lambda[3], Gcon, P, PG; - this->computeStressMatrix(P, genEps, ip, mat, tStep); - - this->evalInitialContravarBaseVectorsAt(ip->giveNaturalCoordinates(), Gcon); - PG.beProductOf(P,Gcon); - PG1.beColumnOf(PG, 1); - PG2.beColumnOf(PG, 2); - PG3.beColumnOf(PG, 3); - this->computeLambdaGMatrices(lambda, genEps, zeta); // associated with the variation of the test functions + auto P = this->computeStressMatrix(genEps, ip, mat, tStep); + auto Gcon = this->evalInitialContravarBaseVectorsAt(ip->giveNaturalCoordinates()); + auto PG = dot(P, Gcon); + auto PG1 = PG.column(0); + auto PG2 = PG.column(1); + auto PG3 = PG.column(2); + auto lambda = this->computeLambdaGMatrices(genEps, zeta); // associated with the variation of the test functions // f = lambda_1^T * P*G^1 + lambda_2^T * P*G^2 + lambda_3^T * P*G^3 sectionalForces.clear(); @@ -866,12 +836,12 @@ Shell7Base :: computeThicknessMappingCoeff(GaussPoint *gp, FloatArray &answer) { //thickness jacobian = ratio between volume and area: j0 = a3 + a2*zeta^2 + a1 * zeta // Returns array with a1-a3, used in expression for analytical integration of mass matrix. - const FloatArray &lcoords = gp->giveNaturalCoordinates(); + const auto &lcoords = gp->giveNaturalCoordinates(); FloatMatrix dNdxi; this->fei->evaldNdxi( dNdxi, lcoords, FEIElementGeometryWrapper(this) ); - FloatArray M, dM1(3), dM2(3), dX1(3), dX2(3); + FloatArrayF<3> M, dM1, dM2, dX1, dX2; double gam, dg1, dg2; FloatMatrix B; this->computeBmatrixAt(lcoords, B); @@ -881,21 +851,17 @@ Shell7Base :: computeThicknessMappingCoeff(GaussPoint *gp, FloatArray &answer) genEps.beProductOf(B, initSolVec); this->giveGeneralizedStrainComponents(genEps, dX1, dX2, dM1, dM2, M, dg1, dg2, gam); - - FloatArray temp, temp2; - temp.beVectorProductOf(dX1, dX2); - double sc = temp.computeNorm(); + auto temp = cross(dX1, dX2); + double sc = norm(temp); answer.resize(3); - answer.at(3) = M.dotProduct(temp) / sc; + answer.at(3) = dot(M, temp) / sc; - temp.beVectorProductOf(dX1, dM2); - temp2.beVectorProductOf(dX2, dM1); - temp.add(temp2); - answer.at(2) = M.dotProduct(temp) / sc; + temp = cross(dX1, dM2) + cross(dX2, dM1); + answer.at(2) = dot(M, temp) / sc; - temp.beVectorProductOf(dM1, dM2); - //answer.at(1) = M.dotProduct(temp)/sc; - answer.at(1) = temp.computeNorm() / sc; + temp = cross(dM1, dM2); + //answer.at(1) = dot(M, temp)/sc; + answer.at(1) = norm(temp) / sc; } void @@ -1022,15 +988,15 @@ Shell7Base :: computeMassMatrixNum(FloatMatrix &answer, TimeStep *tStep) for ( auto &gp: *integrationRulesArray [ layer - 1 ] ) { const FloatArray &lCoords = gp->giveNaturalCoordinates(); - FloatMatrix lambda, B, N, temp; + FloatMatrix B, N, temp; FloatArray genEps; this->computeBmatrixAt(lCoords, B); genEps.beProductOf(B, solVec); double zeta = giveGlobalZcoord(gp->giveNaturalCoordinates()); - this->computeLambdaNMatrix(lambda, genEps, zeta); + auto lambda = this->computeLambdaNMatrix(genEps, zeta); // could also create lambda*N and then plusProdSymm - probably faster - mass.beTProductOf(lambda,lambda); + mass = Tdot(lambda, lambda); this->computeNmatrixAt(lCoords, N); temp.beProductOf(mass,N); @@ -1165,18 +1131,20 @@ Shell7Base :: computePressureForce(FloatArray &answer, FloatArray solVec, const } int nPointsTri = 6; //todo generalize - IntegrationRule *iRule = new GaussIntegrationRule(1, this); + auto iRule = std::make_unique(1, this); // iRule->SetUpPointsOnWedge(nPointsTri, 1, _3dMat); //@todo replce with triangle which has a xi3-coord iRule->SetUpPointsOnTriangle(nPointsTri, _3dMat); FloatMatrix N, B, lambda; - FloatArray Fp, fp, genEps, genEpsC, lCoords(3), traction, solVecC; + FloatArray Fp, fp, genEps, genEpsC, traction, solVecC; for ( auto *ip: *iRule ) { // rule #2 for surface integration - lCoords.at(1) = ip->giveNaturalCoordinate(1); - lCoords.at(2) = ip->giveNaturalCoordinate(2); - lCoords.at(3) = xi; + FloatArrayF<3> lCoords = { + ip->giveNaturalCoordinate(1), + ip->giveNaturalCoordinate(2), + xi, + }; double zeta = giveGlobalZcoord( lCoords ); this->computeBmatrixAt(lCoords, B); this->computeNmatrixAt(lCoords, N); @@ -1185,7 +1153,7 @@ Shell7Base :: computePressureForce(FloatArray &answer, FloatArray solVec, const this->computePressureForceAt(ip, traction, iSurf, genEpsC, surfLoad, tStep, mode); genEps.beProductOf(B, solVec); - this->computeLambdaNMatrix(lambda, genEps, zeta); + lambda = this->computeLambdaNMatrix(genEps, zeta); fp.beTProductOf(lambda,traction); double dA = this->computeAreaAround(ip, xi); @@ -1216,7 +1184,7 @@ Shell7Base :: computePressureForceAt(GaussPoint *gp, FloatArray &traction, const lcoords.at(2) = gp->giveNaturalCoordinate(2); lcoords.at(3) = pLoad->giveLoadOffset(); - this->evalCovarBaseVectorsAt(lcoords, gcov, genEps, tStep); + gcov = this->evalCovarBaseVectorsAt(lcoords, genEps, tStep); g1.beColumnOf(gcov,1); g2.beColumnOf(gcov,2); surfLoad->computeValueAt(load, tStep, lcoords, mode); // pressure component @@ -1239,28 +1207,22 @@ Shell7Base :: computePressureForceAt(GaussPoint *gp, FloatArray &traction, const } -void -Shell7Base :: evalCovarNormalAt(FloatArray &nCov, const FloatArray &lCoords, FloatArray &genEpsC, TimeStep *tStep) +FloatArrayF<3> +Shell7Base :: evalCovarNormalAt(const FloatArrayF<3> &lCoords, FloatArray &genEpsC, TimeStep *tStep) { - FloatMatrix gcov; - this->evalCovarBaseVectorsAt(lCoords, gcov, genEpsC, tStep); - FloatArray g1, g2; - g1.beColumnOf(gcov,1); - g2.beColumnOf(gcov,2); - nCov.beVectorProductOf(g1, g2); - nCov.normalize(); + auto gcov = this->evalCovarBaseVectorsAt(lCoords, genEpsC, tStep); + auto g1 = gcov.column(0); + auto g2 = gcov.column(1); + return normalize(cross(g1, g2)); } -void -Shell7Base :: evalInitialCovarNormalAt(FloatArray &nCov, const FloatArray &lCoords) +FloatArrayF<3> +Shell7Base :: evalInitialCovarNormalAt(const FloatArrayF<3> &lCoords) { - FloatMatrix Gcov; - this->evalInitialCovarBaseVectorsAt(lCoords, Gcov); - FloatArray G1, G2; - G1.beColumnOf(Gcov,1); - G2.beColumnOf(Gcov,2); - nCov.beVectorProductOf(G1, G2); - nCov.normalize(); + auto Gcov = this->evalInitialCovarBaseVectorsAt(lCoords); + auto G1 = Gcov.column(0); + auto G2 = Gcov.column(1); + return normalize(cross(G1, G2)); } void @@ -1286,8 +1248,7 @@ Shell7Base :: computeTractionForce(FloatArray &answer, const int iEdge, Boundary if ( coordSystType == Load :: CST_UpdatedGlobal ) { // Updated global coord system - FloatMatrix gcov; - this->edgeEvalCovarBaseVectorsAt(lCoords, iEdge, gcov, tStep); + auto gcov = this->edgeEvalCovarBaseVectorsAt(lCoords, iEdge, tStep); Q.beTranspositionOf(gcov); FloatArray distrForces(3), distrMoments(3), t1, t2; @@ -1343,11 +1304,11 @@ Shell7Base :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeSte double Shell7Base :: edgeComputeLengthAround(GaussPoint *gp, const int iedge) { - FloatArray G1, G3; - double detJ; - const FloatArray &lcoords = gp->giveNaturalCoordinates(); - this->edgeEvalInitialCovarBaseVectorsAt(lcoords, iedge, G1, G3); - detJ = G1.computeNorm(); + const auto &lcoords = gp->giveNaturalCoordinates(); + //auto [G1, G3] = this->edgeEvalInitialCovarBaseVectorsAt(lcoords, iedge); + auto tmp = this->edgeEvalInitialCovarBaseVectorsAt(lcoords, iedge); + auto G1 = tmp.first; + double detJ = norm(G1); return detJ * gp->giveWeight(); } #endif @@ -1358,13 +1319,6 @@ Shell7Base :: edgeComputeLengthAround(GaussPoint *gp, const int iedge) #if 1 -void Shell7Base :: NodalAveragingRecoveryMI_computeSideValue(FloatArray &answer, int side, InternalStateType type, TimeStep *tStep) -{ - // what is this? - answer.resize(0); -} - - void Shell7Base :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) { if ( type == IST_DirectorField ) { @@ -1388,23 +1342,20 @@ Shell7Base :: NodalRecoveryMI_computeNValProduct(FloatMatrix &answer, int layer, // N(nsigma, nsigma*nnodes) // Definition : sigmaVector = N * nodalSigmaVector FloatArray stressVector, n; - Element *elem = this->ZZNodalRecoveryMI_giveElement(); - //int size = ZZNodalRecoveryMI_giveDofManRecordSize(type); int size = 6; ///@todo this is hard coded for stress recovery answer.zero(); for ( auto *gp: *integrationRulesArray [ layer - 1 ] ) { double dV = this->computeVolumeAroundLayer(gp, layer); - if ( !elem->giveIPValue(stressVector, gp, type, tStep) ) { + if ( !this->giveIPValue(stressVector, gp, type, tStep) ) { stressVector.resize(size); stressVector.zero(); } this->ZZNodalRecoveryMI_ComputeEstimatedInterpolationMtrx(n, gp, type); answer.plusDyadUnsym(n, stressVector, dV); - } } @@ -1500,8 +1451,7 @@ Shell7Base :: temp_computeBoundaryVectorOf(IntArray &dofIdArray, int boundary, V // Routine to extract vector given an array of dofid items // If a certain dofId does not exist a zero is used as value - IntArray bNodes; - this->fei->computeLocalEdgeMapping(bNodes, boundary); + const auto &bNodes = this->fei->computeLocalEdgeMapping(boundary); this->computeBoundaryVectorOf(bNodes, dofIdArray, u, tStep, answer); ///@todo uses new standard method //answer.resize( dofIdArray.giveSize() * bNodes.giveSize() ); @@ -1546,11 +1496,11 @@ Shell7Base :: setupInitialSolutionVector() // Reference position and directors for ( int i = 1, j = 0; i <= this->giveNumberOfDofManagers(); i++, j += 3 ) { - FloatArray *Xi = this->giveNode(i)->giveCoordinates(); - FloatArray Mi = this->giveInitialNodeDirector(i); - this->initialSolutionVector.at(1 + j) = Xi->at(1); - this->initialSolutionVector.at(2 + j) = Xi->at(2); - this->initialSolutionVector.at(3 + j) = Xi->at(3); + const auto &Xi = this->giveNode(i)->giveCoordinates(); + const auto &Mi = this->giveInitialNodeDirector(i); + this->initialSolutionVector.at(1 + j) = Xi.at(1); + this->initialSolutionVector.at(2 + j) = Xi.at(2); + this->initialSolutionVector.at(3 + j) = Xi.at(3); this->initialSolutionVector.at(ndofs_xm + 1 + j) = Mi.at(1); this->initialSolutionVector.at(ndofs_xm + 2 + j) = Mi.at(2); this->initialSolutionVector.at(ndofs_xm + 3 + j) = Mi.at(3); @@ -1583,15 +1533,14 @@ Shell7Base :: setupInitialEdgeSolutionVector() FloatArray &solVec = this->initialEdgeSolutionVectors[iEdge-1]; solVec.resize( this->giveNumberOfEdgeDofs() ); solVec.zero(); - IntArray edgeNodes; - this->fei->computeLocalEdgeMapping(edgeNodes, iEdge); + const auto &edgeNodes = this->fei->computeLocalEdgeMapping(iEdge); int ndofs_x = 3 * edgeNodes.giveSize(); for ( int i = 1, j = 0; i <= edgeNodes.giveSize(); i++, j += 3 ) { - FloatArray *Xi = this->giveNode( edgeNodes.at(i) )->giveCoordinates(); - FloatArray Mi = this->giveInitialNodeDirector( edgeNodes.at(i) ); - solVec.at(1 + j) = Xi->at(1); - solVec.at(2 + j) = Xi->at(2); - solVec.at(3 + j) = Xi->at(3); + const auto &Xi = this->giveNode( edgeNodes.at(i) )->giveCoordinates(); + const auto &Mi = this->giveInitialNodeDirector( edgeNodes.at(i) ); + solVec.at(1 + j) = Xi.at(1); + solVec.at(2 + j) = Xi.at(2); + solVec.at(3 + j) = Xi.at(3); solVec.at(ndofs_x + 1 + j) = Mi.at(1); solVec.at(ndofs_x + 2 + j) = Mi.at(2); solVec.at(ndofs_x + 3 + j) = Mi.at(3); @@ -1601,8 +1550,8 @@ Shell7Base :: setupInitialEdgeSolutionVector() } void -Shell7Base :: giveGeneralizedStrainComponents(FloatArray genEps, FloatArray &dphidxi1, FloatArray &dphidxi2, FloatArray &dmdxi1, - FloatArray &dmdxi2, FloatArray &m, double &dgamdxi1, double &dgamdxi2, double &gam) +Shell7Base :: giveGeneralizedStrainComponents(FloatArray genEps, FloatArrayF<3> &dphidxi1, FloatArrayF<3> &dphidxi2, FloatArrayF<3> &dmdxi1, + FloatArrayF<3> &dmdxi2, FloatArrayF<3> &m, double &dgamdxi1, double &dgamdxi2, double &gam) { // generealized strain vector [dxdxi, dmdxi, m, dgamdxi, gam]^T dphidxi1 = { genEps.at(1), genEps.at(2), genEps.at(3) }; @@ -1612,12 +1561,12 @@ Shell7Base :: giveGeneralizedStrainComponents(FloatArray genEps, FloatArray &dph m = { genEps.at(13), genEps.at(14), genEps.at(15) }; dgamdxi1 = genEps.at(16); dgamdxi2 = genEps.at(17); - gam = genEps.at(18); + gam = genEps.at(18); } void -Shell7Base :: giveUnknownsAt(const FloatArray &lCoords, FloatArray &solVec, FloatArray &x, FloatArray &m, double &gam, TimeStep *tStep) +Shell7Base :: giveUnknownsAt(const FloatArrayF<3> &lCoords, const FloatArray &solVec, FloatArrayF<3> &x, FloatArrayF<3> &m, double &gam, TimeStep *tStep) { // returns the unknowns evaluated at a point (xi1, xi2, xi3) FloatMatrix N; @@ -1808,48 +1757,48 @@ Shell7Base :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) // VTK export #if 1 -void -Shell7Base :: vtkEvalInitialGlobalCoordinateAt(const FloatArray &localCoords, int layer, FloatArray &globalCoords) +FloatArrayF<3> +Shell7Base :: vtkEvalInitialGlobalCoordinateAt(const FloatArrayF<3> &localCoords, int layer) { double zeta = giveGlobalZcoordInLayer(localCoords.at(3), layer); FloatArray N; this->fei->evalN( N, localCoords, FEIElementGeometryWrapper(this) ); - globalCoords.clear(); + FloatArrayF<3> globalCoords; for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) { - FloatArray &xbar = *this->giveNode(i)->giveCoordinates(); - const FloatArray &M = this->giveInitialNodeDirector(i); - globalCoords.add(N.at(i), ( xbar + zeta * M )); + const auto &xbar = FloatArrayF<3>(this->giveNode(i)->giveCoordinates()); + const auto &M = this->giveInitialNodeDirector(i); + globalCoords += N.at(i) * ( xbar + zeta * M ); } - + return globalCoords; } -void -Shell7Base :: vtkEvalInitialGlobalCZCoordinateAt(const FloatArray &localCoords, int interface, FloatArray &globalCoords) +FloatArrayF<3> +Shell7Base :: vtkEvalInitialGlobalCZCoordinateAt(const FloatArrayF<3> &localCoords, int interface) { double zeta = giveGlobalZcoordInLayer(1.0, interface); FloatArray N; this->fei->evalN( N, localCoords, FEIElementGeometryWrapper(this) ); - globalCoords.clear(); + FloatArrayF<3> globalCoords; for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) { - FloatArray &xbar = *this->giveNode(i)->giveCoordinates(); - const FloatArray &M = this->giveInitialNodeDirector(i); - globalCoords.add(N.at(i), ( xbar + zeta * M )); + const auto &xbar = FloatArrayF<3>(this->giveNode(i)->giveCoordinates()); + const auto &M = this->giveInitialNodeDirector(i); + globalCoords += N.at(i) * ( xbar + zeta * M ); } - + return globalCoords; } -void -Shell7Base :: vtkEvalUpdatedGlobalCoordinateAt(const FloatArray &localCoords, int layer, FloatArray &globalCoords, TimeStep *tStep) +FloatArrayF<3> +Shell7Base :: vtkEvalUpdatedGlobalCoordinateAt(const FloatArrayF<3> &localCoords, int layer, TimeStep *tStep) { FloatArray solVec; this->giveUpdatedSolutionVector(solVec, tStep); - FloatArray x, m; double gam=0; + FloatArrayF<3> x, m; double gam=0; this->giveUnknownsAt(localCoords, solVec, x, m, gam, tStep); double zeta = giveGlobalZcoordInLayer(localCoords.at(3), layer); double fac = ( zeta + 0.5 * gam * zeta * zeta ); - globalCoords = x + fac*m; + return x + fac*m; } void @@ -1870,7 +1819,6 @@ Shell7Base :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExp vtkPiece.setNumberOfCells(numCells); vtkPiece.setNumberOfNodes(numTotalNodes); - std::vector nodeCoords; int val = 1; int offset = 0; IntArray nodes(numCellNodes); @@ -1880,7 +1828,7 @@ Shell7Base :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExp for ( int layer = 1; layer <= numCells; layer++ ) { // Node coordinates - this->giveFictiousNodeCoordsForExport(nodeCoords, layer); + auto nodeCoords = this->giveFictiousNodeCoordsForExport(layer); for ( int node = 1; node <= numCellNodes; node++ ) { vtkPiece.setNodeCoords(nodeNum, nodeCoords[node-1] ); @@ -1903,9 +1851,8 @@ Shell7Base :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExp // Export nodal variables from primary fields - vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport.giveSize(), numTotalNodes); + vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport, numTotalNodes); - std::vector updatedNodeCoords; FloatArray u(3); std::vector values; for ( int fieldNum = 1; fieldNum <= primaryVarsToExport.giveSize(); fieldNum++ ) { @@ -1914,19 +1861,19 @@ Shell7Base :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExp for ( int layer = 1; layer <= numCells; layer++ ) { if ( type == DisplacementVector ) { // compute displacement as u = x - X - this->giveFictiousNodeCoordsForExport(nodeCoords, layer); - this->giveFictiousUpdatedNodeCoordsForExport(updatedNodeCoords, layer, tStep); + auto nodeCoords = this->giveFictiousNodeCoordsForExport(layer); + auto updatedNodeCoords = this->giveFictiousUpdatedNodeCoordsForExport(layer, tStep); for ( int j = 1; j <= numCellNodes; j++ ) { u = updatedNodeCoords[j-1]; u.subtract(nodeCoords[j-1]); - vtkPiece.setPrimaryVarInNode(fieldNum, nodeNum, u); + vtkPiece.setPrimaryVarInNode(type, nodeNum, u); nodeNum += 1; } } else { NodalRecoveryMI_recoverValues(values, layer, ( InternalStateType ) 1, tStep); // does not work well - fix for ( int j = 1; j <= numCellNodes; j++ ) { - vtkPiece.setPrimaryVarInNode(fieldNum, nodeNum, values[j-1]); + vtkPiece.setPrimaryVarInNode(type, nodeNum, values[j-1]); nodeNum += 1; } } @@ -1935,7 +1882,7 @@ Shell7Base :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExp // Export nodal variables from internal fields - vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport.giveSize(), numTotalNodes ); + vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport, numTotalNodes ); for ( int fieldNum = 1; fieldNum <= internalVarsToExport.giveSize(); fieldNum++ ) { InternalStateType type = ( InternalStateType ) internalVarsToExport.at(fieldNum); nodeNum = 1; @@ -1948,7 +1895,7 @@ Shell7Base :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExp for ( int layer = 1; layer <= numCells; layer++ ) { recoverValuesFromIP(values, layer, type, tStep); for ( int j = 1; j <= numCellNodes; j++ ) { - vtkPiece.setInternalVarInNode( fieldNum, nodeNum, values[j-1] ); + vtkPiece.setInternalVarInNode( type, nodeNum, values[j-1] ); //ZZNodalRecoveryMI_recoverValues(el.nodeVars[fieldNum], layer, type, tStep); nodeNum += 1; } @@ -1958,18 +1905,18 @@ Shell7Base :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExp // Export cell variables FloatArray average; - vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport.giveSize(), numCells); + vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport, numCells); for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) { InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i); for ( int layer = 1; layer <= numCells; layer++ ) { std :: unique_ptr< IntegrationRule > &iRuleL = integrationRulesArray [ layer - 1 ]; - VTKXMLExportModule::computeIPAverage(average, iRuleL.get(), this, type, tStep); + VTKBaseExportModule::computeIPAverage(average, iRuleL.get(), this, type, tStep); if ( average.giveSize() == 6 ) { - vtkPiece.setCellVar(i, layer, convV6ToV9Stress(average) ); + vtkPiece.setCellVar(type, layer, convV6ToV9Stress(average) ); } else { - vtkPiece.setCellVar(i, layer, average ); + vtkPiece.setCellVar(type, layer, average ); } } } @@ -2032,7 +1979,7 @@ Shell7Base :: CopyIPvaluesToNodes(std::vector &recoveredValues, int IntegrationPoint *ip = iRule->getIntegrationPoint(j); const FloatArray &ipCoords = ip->giveNaturalCoordinates(); ///TODO z-coord in parent shell. - double dist = nodeCoords.distance(ipCoords); + double dist = distance(nodeCoords, ipCoords); if ( dist < distOld ) { closestIPArray.at(i) = j; distOld = dist; @@ -2102,8 +2049,7 @@ Shell7Base :: nodalLeastSquareFitFromIP(std::vector &recoveredValues ipValues.addSubVectorRow(tempIPvalues,i+1,1); // set up virtual cell geometry for an qwedge - std::vector nodes; - giveFictiousNodeCoordsForExport(nodes, layer); + auto nodes = giveFictiousNodeCoordsForExport(layer); FEInterpolation *interpol = static_cast< FEInterpolation * >( &this->interpolationForExport ); FloatArray N; interpol->evalN( N, ip->giveNaturalCoordinates(), FEIVertexListGeometryWrapper( nodes ) ); @@ -2122,9 +2068,9 @@ Shell7Base :: nodalLeastSquareFitFromIP(std::vector &recoveredValues if ( valueType == ISVT_TENSOR_S3 ) { FloatArray nodalStresses; nodalStresses.beColumnOf(temprecovedValuesT,i+1); - recoveredValues[strangeNodeNumbering(i)-1] = convV6ToV9Stress(nodalStresses); + recoveredValues[strangeNodeNumbering[i]-1] = convV6ToV9Stress(nodalStresses); } else { - recoveredValues[strangeNodeNumbering(i)-1].beColumnOf(temprecovedValuesT,i+1); + recoveredValues[strangeNodeNumbering[i]-1].beColumnOf(temprecovedValuesT,i+1); } } } @@ -2139,7 +2085,6 @@ Shell7Base :: giveL2contribution(FloatMatrix &ipValues, FloatMatrix &Nbar, int l int numNodes = localNodeCoords.giveNumberOfColumns(); std :: unique_ptr< IntegrationRule > &iRule = integrationRulesArray [ layer - 1 ]; - IntegrationPoint *ip; int numIP = iRule->giveNumberOfIntegrationPoints(); FloatArray nodeCoords, ipCoords; InternalStateValueType valueType = giveInternalStateValueType(type); @@ -2152,14 +2097,13 @@ Shell7Base :: giveL2contribution(FloatMatrix &ipValues, FloatMatrix &Nbar, int l ipValues.resize(numIP,numSC); for ( int i = 0; i < numIP; i++ ) { - ip = iRule->getIntegrationPoint(i); + auto *ip = iRule->getIntegrationPoint(i); FloatArray tempIPvalues; this->giveIPValue(tempIPvalues, ip, type, tStep); ipValues.addSubVectorRow(tempIPvalues,i+1,1); // set up virtual cell geometry for an qwedge - std::vector nodes; - giveFictiousNodeCoordsForExport(nodes, layer); + auto nodes = giveFictiousNodeCoordsForExport(layer); FEInterpolation *interpol = static_cast< FEInterpolation * >( &this->interpolationForExport ); FloatArray N; interpol->evalN( N, ip->giveNaturalCoordinates(), FEIVertexListGeometryWrapper( nodes ) ); @@ -3118,62 +3062,57 @@ Shell7Base :: computeBmatrixForStressRecAt(FloatArray &lcoords, FloatMatrix &ans -void -Shell7Base :: giveFictiousNodeCoordsForExport(std::vector &nodes, int layer) +std::vector +Shell7Base :: giveFictiousNodeCoordsForExport(int layer) { // compute fictious node coords FloatMatrix localNodeCoords; this->interpolationForExport.giveLocalNodeCoords(localNodeCoords); - nodes.resize(localNodeCoords.giveNumberOfColumns()); + std::vector nodes(localNodeCoords.giveNumberOfColumns()); for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){ - FloatArray coords, localCoords(3); + FloatArray localCoords(3); localCoords.beColumnOf(localNodeCoords,i); - this->vtkEvalInitialGlobalCoordinateAt(localCoords, layer, coords); - nodes[i-1].resize(3); - nodes[i-1] = coords; + nodes[i-1] = this->vtkEvalInitialGlobalCoordinateAt(localCoords, layer); } - + return nodes; } -void -Shell7Base :: giveFictiousCZNodeCoordsForExport(std::vector &nodes, int interface) +std::vector +Shell7Base :: giveFictiousCZNodeCoordsForExport(int interface) { // compute fictious node coords FloatMatrix localNodeCoords; this->interpolationForCZExport.giveLocalNodeCoords(localNodeCoords); - nodes.resize(localNodeCoords.giveNumberOfColumns()); + std::vector nodes(localNodeCoords.giveNumberOfColumns()); for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){ - FloatArray coords, localCoords(3); + FloatArray localCoords(3); localCoords.beColumnOf(localNodeCoords,i); localCoords.at(3) = 1.0; - this->vtkEvalInitialGlobalCoordinateAt(localCoords, interface, coords); - nodes[i-1].resize(3); - nodes[i-1] = coords; + nodes[i-1] = this->vtkEvalInitialGlobalCoordinateAt(localCoords, interface); } - + return nodes; } -void -Shell7Base :: giveFictiousUpdatedNodeCoordsForExport(std::vector &nodes, int layer, TimeStep *tStep) +std::vector +Shell7Base :: giveFictiousUpdatedNodeCoordsForExport(int layer, TimeStep *tStep) { // compute fictious node coords FloatMatrix localNodeCoords; this->interpolationForExport.giveLocalNodeCoords(localNodeCoords); - nodes.resize(localNodeCoords.giveNumberOfColumns()); + std::vector nodes(localNodeCoords.giveNumberOfColumns()); for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){ - FloatArray coords, localCoords(3); + FloatArray localCoords(3); localCoords.beColumnOf(localNodeCoords,i); - this->vtkEvalUpdatedGlobalCoordinateAt(localCoords, layer, coords, tStep); - nodes[i-1].resize(3); - nodes[i-1] = coords; + nodes[i-1] = this->vtkEvalUpdatedGlobalCoordinateAt(localCoords, layer, tStep); } + return nodes; } @@ -3183,10 +3122,10 @@ Shell7Base :: giveFictiousUpdatedNodeCoordsForExport(std::vector &no // Misc functions -FloatArray -Shell7Base :: convV6ToV9Stress(const FloatArray &V6) +FloatArrayF<9> +Shell7Base :: convV6ToV9Stress(const FloatArrayF<6> &V6) { - FloatArray answer(9); + FloatArrayF<9> answer; answer.at(1) = V6.at(1); answer.at(2) = V6.at(2); answer.at(3) = V6.at(3); @@ -3220,7 +3159,7 @@ Shell7Base :: computeInterLaminarStressesAt(int interfaceNum, TimeStep *tStep, s ip = irLower->getIntegrationPoint( irLower->upperInterfacePoints.at(i) ); this->giveIPValue(vSLower, ip, IST_CauchyStressTensor, tStep); - this->evalInitialCovarNormalAt(nCov, ip->giveNaturalCoordinates()); + nCov = this->evalInitialCovarNormalAt(ip->giveNaturalCoordinates()); vSMean = 0.5 * ( vSUpper + vSLower ); SMean.beMatrixFormOfStress(vSMean); stressVec.beProductOf(SMean,nCov); diff --git a/src/sm/Elements/Shells/shell7base.h b/src/sm/Elements/Shells/shell7base.h index f73c9586a..63f7d229a 100644 --- a/src/sm/Elements/Shells/shell7base.h +++ b/src/sm/Elements/Shells/shell7base.h @@ -35,8 +35,8 @@ #ifndef Shell7Base_h #define Shell7Base_h -#include "CrossSections/layeredcrosssection.h" -#include "Elements/nlstructuralelement.h" +#include "sm/CrossSections/layeredcrosssection.h" +#include "sm/Elements/nlstructuralelement.h" #include "eleminterpmapperinterface.h" #include "nodalaveragingrecoverymodel.h" #include "vtkxmlexportmodule.h" @@ -46,7 +46,7 @@ #include "fracturemanager.h" #include "cltypes.h" #include -#include "EngineeringModels/structengngmodel.h" +#include "sm/EngineeringModels/structengngmodel.h" ///@name Input fields for shell7base //@{ @@ -65,48 +65,51 @@ class BoundaryLoad; * @author Jim Brouzoulis * @date 2012-11-01 */ -class Shell7Base : public NLStructuralElement, public NodalAveragingRecoveryModelInterface, public LayeredCrossSectionInterface, +class Shell7Base : public NLStructuralElement, public NodalAveragingRecoveryModelInterface, public LayeredCrossSectionInterface, public VTKXMLExportModuleElementInterface, public ZZNodalRecoveryModelInterface, public FailureModuleElementInterface { public: Shell7Base(int n, Domain *d); // constructor - virtual ~Shell7Base() {} - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); + + void giveDofManDofIDMask(int inode, IntArray &) const override; + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; virtual int computeGlobalCoordinatesOnEdge(FloatArray &answer, const FloatArray &lcoords, const int iEdge); - virtual int computeNumberOfDofs() { return this->giveNumberOfDofs(); } - virtual int checkConsistency(); - virtual void postInitialize(); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + int computeNumberOfDofs() override { return this->giveNumberOfDofs(); } + int checkConsistency() override; + void postInitialize() override; + void printOutputAt(FILE *file, TimeStep *tStep) override; // Definition & identification - virtual const char *giveClassName() const { return "Shell7Base"; } - virtual MaterialMode giveMaterialMode() { return _3dMat; } + const char *giveClassName() const override { return "Shell7Base"; } + MaterialMode giveMaterialMode() override { return _3dMat; } // Element specific virtual int giveNumberOfInPlaneIP() { return numInPlaneIP; }; - virtual int giveNumberOfDofs(); + int giveNumberOfDofs() override; virtual int giveNumberOfEdgeDofs() = 0; virtual int giveNumberOfEdgeDofManagers() = 0; - virtual Element *ZZNodalRecoveryMI_giveElement() { return this; } - void evalInitialCovarBaseVectorsAt(const FloatArray &lCoords, FloatMatrix &Gcov); + FloatMatrixF< 3, 3 >evalInitialCovarBaseVectorsAt(const FloatArrayF< 3 > &lCoords); + + static void giveGeneralizedStrainComponents(FloatArray genEps, FloatArrayF< 3 > &dphidxi1, FloatArrayF< 3 > &dphidxi2, FloatArrayF< 3 > &dmdxi1, + FloatArrayF< 3 > &dmdxi2, FloatArrayF< 3 > &m, double &dgamdxi1, double &dgamdxi2, double &gam); + static FloatMatrixF< 3, 3 >giveDualBase(FloatMatrixF< 3, 3 > &base1); + LayeredCrossSection *giveLayeredCS() { return this->layeredCS; } - static void giveGeneralizedStrainComponents(FloatArray genEps, FloatArray &dphidxi1, FloatArray &dphidxi2, FloatArray &dmdxi1, - FloatArray &dmdxi2, FloatArray &m, double &dgamdxi1, double &dgamdxi2, double &gam); - static void giveDualBase(FloatMatrix &base1, FloatMatrix &base2); - LayeredCrossSection *giveLayeredCS() {return this->layeredCS; } + // Overloaded, as the element is using enhanced approximation + void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global) override; + + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override + { OOFEM_ERROR("calling of this funciton is not allowed"); } - // Overloaded, as the element is using enhanced approximation - void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global); protected: // Recover transverse stresses using momentum balance, cf. Främby, Fagerström & Bouzoulis, 'Adaptive modelling of delamination initiation and propagation using an equivalent single-layer shell approach', IJNME, 2016 bool recoverStress; - - virtual Interface *giveInterface(InterfaceType it); + + Interface *giveInterface(InterfaceType it) override; LayeredCrossSection *layeredCS; - static FEI3dTrQuad interpolationForCZExport; + static FEI3dTrQuad interpolationForCZExport; static FEI3dWedgeQuad interpolationForExport; FEInterpolation3d *fei; @@ -114,9 +117,9 @@ class Shell7Base : public NLStructuralElement, public NodalAveragingRecoveryMode virtual const IntArray &giveOrderingDofTypes() const = 0; virtual const IntArray &giveOrderingNodes() const = 0; virtual const IntArray &giveOrderingEdgeNodes() const = 0; - - std :: vector< FloatArray >initialNodeDirectors; - FloatArray &giveInitialNodeDirector(int i) { + + std::vector< FloatArrayF< 3 > >initialNodeDirectors; + FloatArrayF< 3 > &giveInitialNodeDirector(int i) { return this->initialNodeDirectors [ i - 1 ]; } @@ -125,23 +128,20 @@ class Shell7Base : public NLStructuralElement, public NodalAveragingRecoveryMode return this->initialSolutionVector; } - std :: vector< FloatArray >initialEdgeSolutionVectors; + std::vector< FloatArray >initialEdgeSolutionVectors; FloatArray &giveInitialEdgeSolutionVector(int i) { return this->initialEdgeSolutionVectors [ i - 1 ]; } // Element specific methods int numInPlaneIP; - virtual void computeGaussPoints() = 0; + void computeGaussPoints() override = 0; virtual double computeVolumeAroundLayer(GaussPoint *mastergp, int layer) = 0; virtual double computeAreaAround(GaussPoint *gp, double xi) = 0; - virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const = 0; - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const = 0; - - - virtual IRResultType initializeFrom(InputRecord *ir); - + void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override = 0; + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override = 0; + void initializeFrom(InputRecord &ir) override; // Integration virtual double edgeComputeLengthAround(GaussPoint *gp, const int iedge); @@ -149,39 +149,37 @@ class Shell7Base : public NLStructuralElement, public NodalAveragingRecoveryMode // Base vectors and directors virtual void setupInitialNodeDirectors(); - void evalInitialDirectorAt(const FloatArray &lCoords, FloatArray &answer); + FloatArrayF< 3 >evalInitialDirectorAt(const FloatArrayF< 3 > &lCoords); + + FloatMatrixF< 3, 3 >evalInitialContravarBaseVectorsAt(const FloatArrayF< 3 > &lCoords); - void evalInitialContravarBaseVectorsAt(const FloatArray &lCoords, FloatMatrix &Gcon); + virtual FloatMatrixF< 3, 3 >evalCovarBaseVectorsAt(const FloatArrayF< 3 > &lCoords, FloatArray &genEps, TimeStep *tStep); - - - virtual void evalCovarBaseVectorsAt(const FloatArray &lCoords, FloatMatrix &gcov, FloatArray &genEps, TimeStep *tStep); + virtual FloatArrayF< 3 >evalCovarNormalAt(const FloatArrayF< 3 > &lCoords, FloatArray &genEpsC, TimeStep *tStep); + virtual FloatArrayF< 3 >evalInitialCovarNormalAt(const FloatArrayF< 3 > &lCoords); - virtual void evalCovarNormalAt(FloatArray &nCov, const FloatArray &lCoords, FloatArray &genEpsC, TimeStep *tStep); - virtual void evalInitialCovarNormalAt(FloatArray &nCov, const FloatArray &lCoords); - - void edgeEvalInitialDirectorAt(const FloatArray &lCoords, FloatArray &answer, const int iEdge); + FloatArrayF< 3 >edgeEvalInitialDirectorAt(const FloatArrayF< 1 > &lCoords, const int iEdge); - void edgeEvalInitialCovarBaseVectorsAt(const FloatArray &lCoords, const int iedge, FloatArray &G1, FloatArray &G3); + std::pair< FloatArrayF< 3 >, FloatArrayF< 3 > >edgeEvalInitialCovarBaseVectorsAt(const FloatArrayF< 1 > &lCoords, const int iedge); - void edgeEvalCovarBaseVectorsAt(const FloatArray &lCoords, const int iedge, FloatMatrix &gcov, TimeStep *tStep); + FloatMatrixF< 3, 3 >edgeEvalCovarBaseVectorsAt(const FloatArrayF< 3 > &lCoords, const int iedge, TimeStep *tStep); - virtual double giveGlobalZcoord(const FloatArray &lCoords); + virtual double giveGlobalZcoord(const FloatArrayF< 3 > &lCoords); virtual double giveGlobalZcoordInLayer(double xi, int layer); - FloatMatrix giveAxialMatrix(const FloatArray &vec); + FloatMatrixF< 3, 3 >giveAxialMatrix(const FloatArrayF< 3 > &vec); // Stress and strain - void computeFAt(const FloatArray &lCoords, FloatMatrix &answer, FloatArray &genEps, TimeStep *tStep); - void computeStressMatrix(FloatMatrix &answer, FloatArray &genEps, GaussPoint *gp, Material *mat, TimeStep *tStep); + FloatMatrixF< 3, 3 >computeFAt(const FloatArrayF< 3 > &lCoords, FloatArray &genEps, TimeStep *tStep); + FloatMatrixF< 3, 3 >computeStressMatrix(FloatArray &genEps, GaussPoint *gp, Material *mat, TimeStep *tStep); virtual void computeCauchyStressVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); // Mass matrices - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep); // analytically integrated through the thickness + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; // analytically integrated through the thickness virtual void computeMassMatrixNum(FloatMatrix &answer, TimeStep *tStep); // numerical integration in B_X virtual void giveMassFactorsAt(GaussPoint *gp, FloatArray &answer, double &gam); void computeConvectiveMassForce(FloatArray &answer, TimeStep *tStep); @@ -189,24 +187,23 @@ class Shell7Base : public NLStructuralElement, public NodalAveragingRecoveryMode // Tangent matrices - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; virtual void computeBulkTangentMatrix(FloatMatrix &answer, FloatArray &solVec, TimeStep *tStep); - void computeLinearizedStiffness(GaussPoint * gp, StructuralMaterial * mat, TimeStep * tStep, FloatMatrix A [ 3 ] [ 3 ]); + void computeLinearizedStiffness(GaussPoint *gp, StructuralMaterial *mat, TimeStep *tStep, FloatMatrix A[ 3 ] [ 3 ]); void computePressureTangentMatrix(FloatMatrix &answer, Load *load, const int iSurf, TimeStep *tStep); - void computeLambdaGMatrices(FloatMatrix lambda [ 3 ], FloatArray &genEps, double zeta); - void computeLambdaNMatrix(FloatMatrix &lambda, FloatArray &genEps, double zeta); + std::array< FloatMatrixF< 3, 18 >, 3 >computeLambdaGMatrices(FloatArray &genEps, double zeta); + FloatMatrixF< 3, 7 >computeLambdaNMatrix(FloatArray &genEps, double zeta); // Internal forces - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); - void computeSectionalForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVec, int useUpdatedGpRecord = 0); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + void computeSectionalForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVec, int useUpdatedGpRecord = 0); void computeSectionalForcesAt(FloatArray §ionalForces, IntegrationPoint *ip, Material *mat, TimeStep *tStep, FloatArray &genEpsC, double zeta); // External forces - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode); + void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) override; void computePressureForce(FloatArray &answer, FloatArray solVec, const int iSurf, BoundaryLoad *surfLoad, TimeStep *tStep, ValueModeType mode); void computePressureForceAt(GaussPoint *gp, FloatArray &answer, const int iSurf, FloatArray genEps, BoundaryLoad *surfLoad, TimeStep *tStep, ValueModeType mode); - virtual void computeTractionForce(FloatArray &answer, const int iedge, BoundaryLoad *edgeLoad, TimeStep *tStep, ValueModeType mode, bool map2elementDOFs=false); - + virtual void computeTractionForce(FloatArray &answer, const int iedge, BoundaryLoad *edgeLoad, TimeStep *tStep, ValueModeType mode, bool map2elementDOFs = false); // Solution vectors @@ -220,76 +217,72 @@ class Shell7Base : public NLStructuralElement, public NodalAveragingRecoveryMode //void giveInitialSolutionVector(FloatArray &answer); void giveUpdatedSolutionVector(FloatArray &answer, TimeStep *tStep); - void giveUnknownsAt(const FloatArray &lcoords, FloatArray &solVec, FloatArray &x, FloatArray &m, double &gam, TimeStep *tStep); + void giveUnknownsAt(const FloatArrayF< 3 > &lcoords, const FloatArray &solVec, FloatArrayF< 3 > &x, FloatArrayF< 3 > &m, double &gam, TimeStep *tStep); // Nodal averaging interface: - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); - virtual void NodalAveragingRecoveryMI_computeSideValue(FloatArray &answer, int side, InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; // ZZ recovery - virtual void ZZNodalRecoveryMI_ComputeEstimatedInterpolationMtrx(FloatArray &answer, GaussPoint *gp, InternalStateType type); + void ZZNodalRecoveryMI_ComputeEstimatedInterpolationMtrx(FloatArray &answer, GaussPoint *gp, InternalStateType type); void NodalRecoveryMI_computeNValProduct(FloatMatrix &answer, int layer, InternalStateType type, TimeStep *tStep); void NodalRecoveryMI_computeNNMatrix(FloatArray &answer, int layer, InternalStateType type); - void NodalRecoveryMI_recoverValues(std::vector &recoveredValues, int layer, InternalStateType type, TimeStep *tStep); + void NodalRecoveryMI_recoverValues(std::vector< FloatArray > &recoveredValues, int layer, InternalStateType type, TimeStep *tStep); // VTK interface - virtual void vtkEvalInitialGlobalCoordinateAt(const FloatArray &localCoords, int layer, FloatArray &globalCoords); - virtual void vtkEvalUpdatedGlobalCoordinateAt(const FloatArray &localCoords, int layer, FloatArray &globalCoords, TimeStep *tStep); - - virtual void vtkEvalInitialGlobalCZCoordinateAt(const FloatArray &localCoords, int interface, FloatArray &globalCoords); - - virtual void giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ); - virtual void giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ); - - void giveFictiousNodeCoordsForExport(std::vector &nodes, int layer); - void giveFictiousCZNodeCoordsForExport(std::vector &nodes, int interface); - void giveFictiousUpdatedNodeCoordsForExport(std::vector &nodes, int layer, TimeStep *tStep); + virtual FloatArrayF< 3 >vtkEvalInitialGlobalCoordinateAt(const FloatArrayF< 3 > &localCoords, int layer); + virtual FloatArrayF< 3 >vtkEvalUpdatedGlobalCoordinateAt(const FloatArrayF< 3 > &localCoords, int layer, TimeStep *tStep); + virtual FloatArrayF< 3 >vtkEvalInitialGlobalCZCoordinateAt(const FloatArrayF< 3 > &localCoords, int interface); + + void giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep) override; + virtual void giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep); + + std::vector< FloatArray >giveFictiousNodeCoordsForExport(int layer); + std::vector< FloatArray >giveFictiousCZNodeCoordsForExport(int interface); + std::vector< FloatArray >giveFictiousUpdatedNodeCoordsForExport(int layer, TimeStep *tStep); //void giveLocalNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, FloatArray &nodeLocalXi2Coords, FloatArray &nodeLocalXi3Coords); - + // Recovery of through thickness stresses by momentum balance - enum stressRecoveryType {copyIPvalue, LSfit, L2fit}; - virtual void giveRecoveredTransverseInterfaceStress(std::vector &transverseStress, TimeStep *tStep); + enum stressRecoveryType { copyIPvalue, LSfit, L2fit }; + virtual void giveRecoveredTransverseInterfaceStress(std::vector< FloatMatrix > &transverseStress, TimeStep *tStep); void giveTractionBC(FloatMatrix &tractionTop, FloatMatrix &tractionBtm, TimeStep *tStep); - void recoverValuesFromIP(std::vector &nodes, int layer, InternalStateType type, TimeStep *tStep, stressRecoveryType SRtype = copyIPvalue); - void CopyIPvaluesToNodes(std::vector &recoveredValues, int layer, InternalStateType type, TimeStep *tStep); - void nodalLeastSquareFitFromIP(std::vector &recoveredValues, int layer, InternalStateType type, TimeStep *tStep); + void recoverValuesFromIP(std::vector< FloatArray > &nodes, int layer, InternalStateType type, TimeStep *tStep, stressRecoveryType SRtype = copyIPvalue); + void CopyIPvaluesToNodes(std::vector< FloatArray > &recoveredValues, int layer, InternalStateType type, TimeStep *tStep); + void nodalLeastSquareFitFromIP(std::vector< FloatArray > &recoveredValues, int layer, InternalStateType type, TimeStep *tStep); virtual void recoverShearStress(TimeStep *tStep); void giveLayerContributionToSR(FloatMatrix &dSmat, FloatMatrix &dSmatLayerIP, int layer, double zeroThicknessLevel, TimeStep *tStep); - void fitRecoveredStress2BC(std::vector &answer1, std::vector &answer2, std::vector &dSmat, std::vector &dSmatIP, FloatMatrix &SmatOld, FloatMatrix &tractionBtm, FloatMatrix &tractionTop, double zeroThicknessLevel, FloatArray fulfillBC, int startLayer, int endLayer); + void fitRecoveredStress2BC(std::vector< FloatMatrix > &answer1, std::vector< FloatMatrix > &answer2, std::vector< FloatMatrix > &dSmat, std::vector< FloatMatrix > &dSmatIP, FloatMatrix &SmatOld, FloatMatrix &tractionBtm, FloatMatrix &tractionTop, double zeroThicknessLevel, FloatArray fulfillBC, int startLayer, int endLayer); void updateLayerTransvStressesSR(FloatMatrix &dSmatLayerIP, int layer); void updateLayerTransvShearStressesSR(FloatMatrix &dSmatLayerIP, FloatMatrix &SmatOld, int layer); void updateLayerTransvNormalStressSR(FloatMatrix &dSzzMatLayerIP, FloatArray &SzzMatOld, int layer); -// void computeBmatrixForStressRecAt(FloatArray &lcoords, FloatMatrix &answer, int layer, bool intSzz = false); -// void givePolynomial2GradientForStressRecAt(FloatArray &answer, FloatArray &coords); + // void computeBmatrixForStressRecAt(FloatArray &lcoords, FloatMatrix &answer, int layer, bool intSzz = false); + // void givePolynomial2GradientForStressRecAt(FloatArray &answer, FloatArray &coords); void giveZintegratedPolynomialGradientForStressRecAt(FloatArray &answer, FloatArray &coords); -// void giveZintegratedPolynomial2GradientForStressRecAt(FloatArray &answer, FloatArray &coords); + // void giveZintegratedPolynomial2GradientForStressRecAt(FloatArray &answer, FloatArray &coords); void giveZ2integratedPolynomial2GradientForStressRecAt(FloatArray &answer, FloatArray &coords); void giveL2contribution(FloatMatrix &ipValues, FloatMatrix &Nbar, int layer, InternalStateType type, TimeStep *tStep); void giveSPRcontribution(FloatMatrix &eltIPvalues, FloatMatrix &eltPolynomialValues, int layer, InternalStateType type, TimeStep *tStep); - // N and B matrices - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li = 1, int ui = ALL_STRAINS) { answer.clear(); } + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li = 1, int ui = ALL_STRAINS) override { answer.clear(); } virtual void computeBmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, int li = 1, int ui = ALL_STRAINS); - virtual void computeNmatrixAt(const FloatArray &iLocCoords, FloatMatrix &answer); + void computeNmatrixAt(const FloatArray &iLocCoords, FloatMatrix &answer) override; virtual void edgeComputeNmatrixAt(const FloatArray &lCoords, FloatMatrix &answer); - virtual void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) + void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) override { OOFEM_ERROR("ComputeStrainVectorInLayer - Should not be called! Not meaningful for this element."); } virtual void edgeComputeBmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, int li = 1, int ui = ALL_STRAINS); - FloatArray convV6ToV9Stress(const FloatArray &V6); + static FloatArrayF< 9 >convV6ToV9Stress(const FloatArrayF< 6 > &V6); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - void computeInterLaminarStressesAt(int interfaceNum, TimeStep *tStep, std::vector < FloatArray > &interLamStresses); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + void computeInterLaminarStressesAt(int interfaceNum, TimeStep *tStep, std::vector< FloatArray > &interLamStresses); virtual void evaluateFailureCriteriaQuantities(FailureCriteriaStatus *fc, TimeStep *tStep); int giveSymVoigtIndex(int ind1, int ind2); int giveVoigtIndex(int ind1, int ind2); - std::vector< std::vector > voigtIndices; - + std::vector< std::vector< int > >voigtIndices; }; } // end namespace oofem #endif diff --git a/src/sm/shell7basePhFi.C b/src/sm/Elements/Shells/shell7basePhFi.C similarity index 97% rename from src/sm/shell7basePhFi.C rename to src/sm/Elements/Shells/shell7basePhFi.C index 820a4312d..b388071de 100644 --- a/src/sm/shell7basePhFi.C +++ b/src/sm/Elements/Shells/shell7basePhFi.C @@ -63,10 +63,9 @@ Shell7BasePhFi :: Shell7BasePhFi(int n, Domain *aDomain) : Shell7Base(n, aDomain this->numberOfLayers = nLayers; } -IRResultType Shell7BasePhFi :: initializeFrom(InputRecord *ir) +void Shell7BasePhFi :: initializeFrom(InputRecord &ir) { Shell7Base :: initializeFrom(ir); - return IRRT_OK; } @@ -1031,7 +1030,7 @@ Shell7BasePhFi :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT // Export nodal variables from primary fields - vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport.giveSize(), numTotalNodes); + vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport, numTotalNodes); std::vector updatedNodeCoords; FloatArray u(3), damage(1); @@ -1079,7 +1078,7 @@ Shell7BasePhFi :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT // Export nodal variables from internal fields - vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport.giveSize(), numTotalNodes ); + vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport, numTotalNodes ); for ( int fieldNum = 1; fieldNum <= internalVarsToExport.giveSize(); fieldNum++ ) { InternalStateType type = ( InternalStateType ) internalVarsToExport.at(fieldNum); nodeNum = 1; @@ -1097,7 +1096,7 @@ Shell7BasePhFi :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT // Export cell variables FloatArray average; - vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport.giveSize(), numCells); + vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport, numCells); for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) { InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i);; @@ -1148,7 +1147,7 @@ Shell7BasePhFi :: recoverValuesFromIP(std::vector &recoveredValues, for ( int j = 0; j < iRule->giveNumberOfIntegrationPoints(); j++ ) { ip = iRule->getIntegrationPoint(j); ipCoords = *ip->giveCoordinates(); - double dist = nodeCoords.distance(ipCoords); + double dist = distance(nodeCoords, ipCoords); if ( dist < distOld ) { closestIPArray.at(i) = j; distOld = dist; @@ -1285,11 +1284,8 @@ Shell7BasePhFi :: computeBmatrixForStressRecAt(FloatArray &lcoords, FloatMatrix } - - - -void -Shell7BasePhFi :: giveFictiousNodeCoordsForExport(std::vector &nodes, int layer) +std::vector +Shell7BasePhFi :: giveFictiousNodeCoordsForExport(int layer) { // compute fictious node coords FloatMatrix localNodeCoords; @@ -1297,53 +1293,48 @@ Shell7BasePhFi :: giveFictiousNodeCoordsForExport(std::vector &nodes nodes.resize(localNodeCoords.giveNumberOfColumns()); for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){ - FloatArray coords, localCoords(3); + FloatArray localCoords(3); localCoords.beColumnOf(localNodeCoords,i); - this->vtkEvalInitialGlobalCoordinateAt(localCoords, layer, coords); - nodes[i-1].resize(3); - nodes[i-1] = coords; + nodes[i-1] = this->vtkEvalInitialGlobalCoordinateAt(localCoords, layer); } - + return nodes; } -void -Shell7BasePhFi :: giveFictiousCZNodeCoordsForExport(std::vector &nodes, int interface) +std::vector +Shell7BasePhFi :: giveFictiousCZNodeCoordsForExport(int interface) { // compute fictious node coords FloatMatrix localNodeCoords; this->interpolationForCZExport.giveLocalNodeCoords(localNodeCoords); - nodes.resize(localNodeCoords.giveNumberOfColumns()); + std::vector nodes(localNodeCoords.giveNumberOfColumns()); for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){ - FloatArray coords, localCoords(3); + FloatArray localCoords(3); localCoords.beColumnOf(localNodeCoords,i); localCoords.at(3) = 1.0; - this->vtkEvalInitialGlobalCoordinateAt(localCoords, interface, coords); - nodes[i-1].resize(3); - nodes[i-1] = coords; + nodes[i-1] = this->vtkEvalInitialGlobalCoordinateAt(localCoords, interface); } - + return nodes; } void -Shell7BasePhFi :: giveFictiousUpdatedNodeCoordsForExport(std::vector &nodes, int layer, TimeStep *tStep) +Shell7BasePhFi :: giveFictiousUpdatedNodeCoordsForExport(int layer, TimeStep *tStep) { // compute fictious node coords FloatMatrix localNodeCoords; this->interpolationForExport.giveLocalNodeCoords(localNodeCoords); - nodes.resize(localNodeCoords.giveNumberOfColumns()); + std::vector nodes(localNodeCoords.giveNumberOfColumns()); for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){ - FloatArray coords, localCoords(3); + FloatArray localCoords; localCoords.beColumnOf(localNodeCoords,i); - this->vtkEvalUpdatedGlobalCoordinateAt(localCoords, layer, coords, tStep); - nodes[i-1].resize(3); - nodes[i-1] = coords; + nodes[i-1] = this->vtkEvalUpdatedGlobalCoordinateAt(localCoords, layer, tStep); } + return nodes; } diff --git a/src/sm/shell7basePhFi.H b/src/sm/Elements/Shells/shell7basePhFi.H similarity index 66% rename from src/sm/shell7basePhFi.H rename to src/sm/Elements/Shells/shell7basePhFi.H index 1bad3489d..c016e6cc8 100644 --- a/src/sm/shell7basePhFi.H +++ b/src/sm/Elements/Shells/shell7basePhFi.H @@ -59,116 +59,113 @@ class BoundaryLoad; * This class represent a 7 parameter shell element with isotropic damage in each layer modelled by phase field theory. * Each node has 7 degrees of freedom (displ. vec., director vec., inhomogeneous thickness strain ). * @todo Add ref. to paper! - * @author Martin Fagerström + * @author Martin Fagerstr�m * @date 2014-06-03 */ class Shell7BasePhFi : public Shell7Base, public PhaseFieldElement { public: - int startIDdamage, endIDdamage; + int startIDdamage, endIDdamage; Shell7BasePhFi(int n, Domain *d); // constructor virtual ~Shell7BasePhFi() {} virtual void giveDofManDofIDMask(int inode, EquationID, IntArray &) const; virtual void giveDofManDofIDMask_u(IntArray &answer) const; virtual void giveDofManDofIDMask_d(IntArray &answer) const; - //virtual void giveUpdatedSolutionVector(FloatArray &answer, TimeStep *tStep); - - - double computeGInLayer(int layer, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); - double computeGInLayer_dist(int layer, int indx, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); - double computeGprimInLayer(int layer, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); - double computeGprimInLayer_dist(int layer, int indx, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); - double computeGbisInLayer(int layer, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); + //virtual void giveUpdatedSolutionVector(FloatArray &answer, TimeStep *tStep); + + + double computeGInLayer(int layer, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); + double computeGInLayer_dist(int layer, int indx, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); + double computeGprimInLayer(int layer, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); + double computeGprimInLayer_dist(int layer, int indx, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); + double computeGbisInLayer(int layer, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); double computeDamageInLayerAt(int layer, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); - double computeOldDamageInLayerAt(int layer, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); - double computeDamageInLayerAt_dist(int layer, int indx, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); - IntArray computeDamageIndexArray(int layer); + double computeOldDamageInLayerAt(int layer, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); + double computeDamageInLayerAt_dist(int layer, int indx, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); + IntArray computeDamageIndexArray(int layer); - virtual int computeNumberOfDofs() { return this->giveNumberOfDofs(); } - //virtual int checkConsistency(); - virtual void postInitialize(); + int computeNumberOfDofs() override { return this->giveNumberOfDofs(); } + //int checkConsistency() override; + void postInitialize() override; // Definition & identification - virtual const char *giveClassName() const { return "Shell7BasePhFi"; } + const char *giveClassName() const override { return "Shell7BasePhFi"; } // virtual classType giveClassID() const { return Shell7BasePhFiClass; } // Element specific - virtual int giveNumberOfDofs(); //@todo: should be protected? - virtual int giveNumberOfuDofs(); //@todo: should be protected? - virtual int giveNumberOfdDofs(); //@todo: should be protected? + int giveNumberOfDofs() override; + virtual int giveNumberOfuDofs(); + virtual int giveNumberOfdDofs(); //virtual int giveNumberOfEdgeDofs() = 0; //todo: used for PhFi??? //virtual int giveNumberOfEdgeDofManagers() = 0; - virtual Element *ZZNodalRecoveryMI_giveElement() { return this; } - double neg_MaCauley(double par); double neg_MaCauleyPrime(double par); protected: - enum SolutionFieldPhFi { + enum SolutionFieldPhFi { Midplane, ///< phi_bar 7 x_bar (3 dofs) Director, ///< m (3 dofs) InhomStrain, ///< gamma (1 dofs) - inhomogenious thickness strain - Displacement, ///< phi_bar, m, gamma - Damage, ///< d (n dofs where n is the number of layers in the layeredCS + Displacement, ///< phi_bar, m, gamma + Damage, ///< d (n dofs where n is the number of layers in the layeredCS All, AllInv, EdgeInv, }; - int numberOfLayers; + int numberOfLayers; virtual const IntArray &giveOrdering(SolutionField fieldType) const { OOFEM_ERROR("Shell7BasePhFi :: giveOrdering not implemented: Use Shell7BasePhFi :: giveOrderingPhFi instead"); - return 0; + return 0; }; - - virtual const IntArray &giveOrderingPhFi(SolutionFieldPhFi fieldType) const = 0; + + virtual const IntArray &giveOrderingPhFi(SolutionFieldPhFi fieldType) const = 0; virtual const IntArray &giveOrdering_Disp() const = 0; virtual const IntArray &giveOrdering_Damage() const = 0; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; // Tangent matrices - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; virtual void new_computeBulkTangentMatrix(FloatMatrix &answer, FloatArray &solVec, FloatArray &solVecI, FloatArray &solVecJ, MatResponseMode rMode, TimeStep *tStep); void computeStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode, TimeStep *); void computeStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode, TimeStep *); - void computeStiffnessMatrixNum_ud(FloatMatrix &answer, MatResponseMode, TimeStep *); - void computeStiffnessMatrixNum_dd(FloatMatrix &answer, MatResponseMode, TimeStep *); + void computeStiffnessMatrixNum_ud(FloatMatrix &answer, MatResponseMode, TimeStep *); + void computeStiffnessMatrixNum_dd(FloatMatrix &answer, MatResponseMode, TimeStep *); void computeStiffnessMatrix_dd(FloatMatrix &answer, MatResponseMode, TimeStep *); void computeStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode, TimeStep *); // Internal forces virtual void computeSectionalForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVec, int useUpdatedGpRecord = 0); virtual void computeSectionalForces_dist(FloatArray &answer, int indx, TimeStep *tStep, FloatArray &solVec, int useUpdatedGpRecord = 0); - virtual void computeSectionalForcesAt_d(double &ans_scalar, FloatArray &answer, IntegrationPoint *ip, Material *mat, TimeStep *tStep, double zeta, int layer, FloatArray &Ddam_Dxi); - virtual void computeSectionalForcesAt_d_dist(double &ans_scalar, FloatArray &answer, int indx, IntegrationPoint *ip, Material *mat, TimeStep *tStep, double zeta, int layer, FloatArray &Ddam_Dxi); + virtual void computeSectionalForcesAt_d(double &ans_scalar, FloatArray &answer, IntegrationPoint *ip, Material *mat, TimeStep *tStep, double zeta, int layer, FloatArray &Ddam_Dxi); + virtual void computeSectionalForcesAt_d_dist(double &ans_scalar, FloatArray &answer, int indx, IntegrationPoint *ip, Material *mat, TimeStep *tStep, double zeta, int layer, FloatArray &Ddam_Dxi); - // Solution vectors + // Solution vectors //void giveSolutionVector_u(FloatArray &answer, const IntArray &dofIdArray, TimeStep *tStep); void giveSolutionVector_d(FloatArray &answer, const IntArray &dofIdArray, TimeStep *tStep); void computeVectorOfDofIDs(const IntArray &dofIdArray, ValueModeType u, TimeStep *stepN, FloatArray &answer); void giveUpdatedSolutionVector_d(FloatArray &answer, TimeStep *tStep); - + // VTK interface virtual void giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ); // N and B matrices - virtual void computeBdmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li = 1, int ui = ALL_STRAINS) + virtual void computeBdmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li = 1, int ui = ALL_STRAINS) { OOFEM_ERROR1("Shell7BasePhFi :: computeBdmatrixAt should not be called"); }; - virtual void computeBdmatrixAt(FloatArray &lCoords, FloatMatrix &answer); + virtual void computeBdmatrixAt(FloatArray &lCoords, FloatMatrix &answer); - virtual void computeNdvectorAt(const FloatArray &iLocCoords, FloatArray &answer); + virtual void computeNdvectorAt(const FloatArray &iLocCoords, FloatArray &answer); virtual void computeNdMatrixAt(const FloatArray &iLocCoords, FloatMatrix &answer); // same as vector but saved as a FloatMatrix - }; } // end namespace oofem #endif diff --git a/src/sm/Elements/Shells/shell7basexfem.C b/src/sm/Elements/Shells/shell7basexfem.C index 9e5434939..ac44a8a9b 100644 --- a/src/sm/Elements/Shells/shell7basexfem.C +++ b/src/sm/Elements/Shells/shell7basexfem.C @@ -32,12 +32,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/Shells/shell7basexfem.h" -#include "Elements/Shells/shell7base.h" +#include "sm/Elements/Shells/shell7basexfem.h" +#include "sm/Elements/Shells/shell7base.h" #include "Loads/constantpressureload.h" #include "constantsurfaceload.h" -#include "Materials/InterfaceMaterials/intmatbilinczfagerstrom.h" -#include "Materials/InterfaceMaterials/intmatbilinczjansson.h" +#include "sm/Materials/InterfaceMaterials/intmatbilinczfagerstrom.h" +#include "sm/Materials/InterfaceMaterials/intmatbilinczjansson.h" #include "xfem/enrichmentitems/crack.h" #include "xfem/enrichmentitems/shellcrack.h" #include "feinterpol3d.h" @@ -60,11 +60,6 @@ Shell7BaseXFEM :: Shell7BaseXFEM(int n, Domain *aDomain) : Shell7Base(n, aDomain { } -Shell7BaseXFEM :: ~Shell7BaseXFEM() -{ - -} - int Shell7BaseXFEM :: checkConsistency() { @@ -77,7 +72,7 @@ Shell7BaseXFEM :: postInitialize() { Shell7Base :: postInitialize(); this->xMan = this->giveDomain()->giveXfemManager(); - + // Set up ordering arrays and arrays with the actived dofs int numEI = xMan->giveNumberOfEnrichmentItems(); this->orderingArrays.resize(numEI); @@ -92,11 +87,9 @@ Shell7BaseXFEM :: postInitialize() } - void Shell7BaseXFEM :: computeFailureCriteriaQuantities(FailureCriteriaStatus *fcStatus, TimeStep *tStep) { - // Compute necessary quantities for evaluation of failure criterias ///@todo Ugly code and not tested in a while so probably broken @@ -165,20 +158,15 @@ Shell7BaseXFEM :: computeFailureCriteriaQuantities(FailureCriteriaStatus *fcStat // } // } // break; - } - - - -IRResultType Shell7BaseXFEM :: initializeFrom(InputRecord *ir) +void Shell7BaseXFEM :: initializeFrom(InputRecord &ir) { - if ( ir->hasField(_IFT_Shell7BaseXFEM_CohesiveZoneMaterial) ) { + Shell7Base :: initializeFrom(ir); + if ( ir.hasField(_IFT_Shell7BaseXFEM_CohesiveZoneMaterial) ) { OOFEM_ERROR("'czmaterial' this keyword is not in use anymore! Instead define cz material for each interface in the cross secton, ex: interfacematerials 3 x x x "); } - - return Shell7Base :: initializeFrom(ir); } bool @@ -226,25 +214,25 @@ Shell7BaseXFEM :: giveDofManDofIDMask(int inode, IntArray &answer) const } -void -Shell7BaseXFEM :: evalCovarBaseVectorsAt(const FloatArray &lCoords, FloatMatrix &gcov, FloatArray &genEpsC, TimeStep *tStep) +FloatMatrixF<3,3> +Shell7BaseXFEM :: evalCovarBaseVectorsAt(const FloatArrayF<3> &lCoords, FloatArray &genEpsC, TimeStep *tStep) { // Continuous part g_c - Shell7Base :: evalCovarBaseVectorsAt(lCoords, gcov, genEpsC, tStep); + auto gcov = Shell7Base :: evalCovarBaseVectorsAt(lCoords, genEpsC, tStep); // Discontinuous part g_d FloatArray dGenEps; - FloatMatrix gcovd; std :: vector< double > ef; for ( int i = 1; i <= this->xMan->giveNumberOfEnrichmentItems(); i++ ) { EnrichmentItem *ei = this->xMan->giveEnrichmentItem(i); if ( ei->isElementEnriched(this) ) { computeDiscGeneralizedStrainVector(dGenEps, lCoords, ei, tStep); - Shell7Base :: evalCovarBaseVectorsAt(lCoords, gcovd, dGenEps, tStep); - gcov.add(gcovd); + auto gcovd = Shell7Base :: evalCovarBaseVectorsAt(lCoords, dGenEps, tStep); + gcov += gcovd; } } + return gcov; } @@ -271,20 +259,20 @@ Shell7BaseXFEM :: computeDiscSolutionVector(IntArray &dofIdArray , TimeStep *tSt answer.resize(temp.giveSize()); answer.zero(); answer.assemble( temp, this->giveOrderingNodes() ); - } -void -Shell7BaseXFEM :: computeInterfaceJumpAt(int interf, FloatArray &lCoords, TimeStep *tStep, FloatArray &answer) +FloatArrayF<3> +Shell7BaseXFEM :: computeInterfaceJumpAt(int interf, const FloatArrayF<3> &lCoords, TimeStep *tStep) { + auto plus = lCoords; + plus.at(3) += 1.0e-9; // bottom position for plus side + num. perturbation + auto gplus = this->vtkEvalUpdatedGlobalCoordinateAt(plus, interf + 1, tStep); // position vector at + side - FloatArray temp; - lCoords.at(3) += 1.0e-9; // bottom position for plus side + num. perturbation - this->vtkEvalUpdatedGlobalCoordinateAt(lCoords, interf + 1, answer, tStep); // position vector at + side - lCoords.at(3) -= 2.0e-9; // top position for minus side - num. perturbation - this->vtkEvalUpdatedGlobalCoordinateAt(lCoords, interf, temp, tStep); // position vector at - side - answer.subtract(temp); // jump = x(+) - x(-) - + auto minus = lCoords; + minus.at(3) -= 2.0e-9; // top position for minus side - num. perturbation + auto gminus = this->vtkEvalUpdatedGlobalCoordinateAt(minus, interf, tStep); // position vector at - side + + return gplus - gminus; // jump = x(+) - x(-) } int @@ -334,20 +322,19 @@ Shell7BaseXFEM :: computeOrderingArray( IntArray &orderingArray, IntArray &activ int activeDofPos = 0, activeDofIndex = 0, orderingDofIndex = 0; - + IntArray dofManDofIdMask, dofManDofIdMaskAll; for ( int i = 1; i <= numberOfDofMans; i++ ) { DofManager *dMan = this->giveDofManager(i); - - if ( ei == NULL) { // return mask corresponding to the regular id's + if ( ei == nullptr ) { // return mask corresponding to the regular id's Shell7Base :: giveDofManDofIDMask(i, dofManDofIdMask); } else { if ( ei->isDofManEnriched(*dMan) ) { ei->giveEIDofIdArray(dofManDofIdMask); } } - + for (int j = 1; j <= dofManDofIdMask.giveSize(); j++ ) { int pos = dMan->findDofWithDofId( ( DofIDItem ) dofManDofIdMask.at(j) ) - dMan->begin() + 1; activeDofPos++; @@ -360,11 +347,11 @@ Shell7BaseXFEM :: computeOrderingArray( IntArray &orderingArray, IntArray &activ dofManDofIdMask.clear(); } - + // Reduce arrays to actual size int numActiveDofs = activeDofPos; orderingArray.resize(numActiveDofs), activeDofsArray.resize(numActiveDofs); - + for ( int i = 1; i <= numActiveDofs; i++ ) { orderingArray.at(i) = ordering_temp.at(i); activeDofsArray.at(i) = activeDofsArrayTemp.at(i); @@ -409,11 +396,11 @@ Shell7BaseXFEM :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, // If there are only delaminations present the we only have one contribution per ei. // If there are intralmainar cracks then we get several potential extra terms. // Therefore we must go through them all and check. - + for ( int j = 1; j <= this->xMan->giveNumberOfEnrichmentItems(); j++ ) { if ( this->xMan->giveEnrichmentItem(j)->isElementEnriched(this) ) { this->computeCohesiveForces( fCZ, tStep, solVec, solVecD, ei, this->xMan->giveEnrichmentItem(j)); - + tempRed.beSubArrayOf(fCZ, this->activeDofsArrays[j-1]); answer.assemble(tempRed, this->orderingArrays[j-1]); } @@ -421,7 +408,6 @@ Shell7BaseXFEM :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, } } } - } @@ -438,20 +424,19 @@ Shell7BaseXFEM :: discComputeSectionalForces(FloatArray &answer, TimeStep *tStep for ( int layer = 1; layer <= numberOfLayers; layer++ ) { Material *mat = domain->giveMaterial( this->layeredCS->giveLayerMaterial(layer) ); - for ( GaussPoint *gp: *integrationRulesArray [ layer - 1 ] ) { + for ( auto &gp: *integrationRulesArray [ layer - 1 ] ) { lCoords = gp->giveNaturalCoordinates(); this->computeEnrichedBmatrixAt(lCoords, B, NULL); this->computeEnrichedBmatrixAt(lCoords, BEnr, ei); genEps.beProductOf(B, solVec); double zeta = giveGlobalZcoord(lCoords); - this->computeSectionalForcesAt(Nd, gp, mat, tStep, genEps, zeta); + Nd = this->computeSectionalForcesAt(gp, mat, tStep, genEps, zeta); // Computation of nodal forces: f = B^t*[N M T Ms Ts]^t ftemp.beTProductOf( BEnr, Nd ); double dV = this->computeVolumeAroundLayer(gp, layer); f.add( dV, ftemp ); - } } @@ -461,36 +446,31 @@ Shell7BaseXFEM :: discComputeSectionalForces(FloatArray &answer, TimeStep *tStep } -void -Shell7BaseXFEM :: computeSectionalForcesAt(FloatArray §ionalForces, IntegrationPoint *ip, Material *mat, TimeStep *tStep, FloatArray &genEps, double zeta) +FloatArray +Shell7BaseXFEM :: computeSectionalForcesAt(IntegrationPoint *ip, Material *mat, TimeStep *tStep, FloatArray &genEps, double zeta) { // New, in terms of PK1 stress // f = \Lambda_i * P * G^I - FloatArray PG1(3), PG2(3), PG3(3); - FloatMatrix lambda[3], Gcon, P, PG; - this->computeStressMatrix(P, genEps, ip, mat, tStep); - - const FloatArray &lCoords = ip->giveNaturalCoordinates(); - this->evalInitialContravarBaseVectorsAt(lCoords, Gcon); - PG.beProductOf(P,Gcon); - PG1.beColumnOf(PG, 1); - PG2.beColumnOf(PG, 2); - PG3.beColumnOf(PG, 3); - this->computeLambdaGMatricesDis(lambda, zeta); // associated with the variation of the test functions - + auto P = this->computeStressMatrix(genEps, ip, mat, tStep); + + const auto &lCoords = ip->giveNaturalCoordinates(); + auto Gcon = this->evalInitialContravarBaseVectorsAt(lCoords); + auto PG = dot(P, Gcon); + auto PG1 = PG.column(0); + auto PG2 = PG.column(1); + auto PG3 = PG.column(2); + + auto lambda = this->computeLambdaGMatricesDis(zeta); // associated with the variation of the test functions + // f = lambda_1^T * P*G^1 + lambda_2^T * P*G^2 + lambda_3^T * P*G^3 - sectionalForces.clear(); + FloatArray sectionalForces; sectionalForces.plusProduct(lambda[0], PG1, 1.0); sectionalForces.plusProduct(lambda[1], PG2, 1.0); sectionalForces.plusProduct(lambda[2], PG3, 1.0); - + return sectionalForces; } - - - - double Shell7BaseXFEM :: evaluateLevelSet(const FloatArray &lCoords, EnrichmentItem *ei) { @@ -507,7 +487,7 @@ Shell7BaseXFEM :: evaluateLevelSet(const FloatArray &lCoords, EnrichmentItem *ei crack->interpLevelSet(levelSet, N, elNodes); } else { OOFEM_ERROR("error in evaluation of levelset"); - } + } return levelSet; } @@ -526,20 +506,18 @@ Shell7BaseXFEM :: edgeEvaluateLevelSet(const FloatArray &lCoords, EnrichmentItem FloatArray N; //const IntArray &elNodes = this->giveDofManArray(); //const IntArray &elNodes = this->giveInterpolation()->givee - + IntArray edgeNodes, globalNums; static_cast< FEInterpolation3d* >(this->giveInterpolation())->computeLocalEdgeMapping(edgeNodes, edge); globalNums.resize(edgeNodes.giveSize()); for ( int i = 1; i <= edgeNodes.giveSize(); i++ ) { globalNums.at(i) = this->giveNode(edgeNodes.at(i))->giveGlobalNumber(); } - this->fei->edgeEvalN( N, edge, lCoords, FEIElementGeometryWrapper(this) ); crack->interpLevelSet(levelSet, N, globalNums); - } else { OOFEM_ERROR("error in evaluation of levelset"); - } + } return levelSet; } #endif @@ -554,7 +532,6 @@ Shell7BaseXFEM :: evaluateHeavisideXi(double xi, ShellCrack *ei) double xiTop = ei->xiTop; return this->evaluateCutHeaviside(xi, xiBottom, xiTop); - } double @@ -565,7 +542,6 @@ Shell7BaseXFEM :: evaluateHeavisideXi(double xi, Delamination *ei) double xiTop = ei->giveBoundingDelamXiCoord(); return this->evaluateCutHeaviside(xi, xiBottom, xiTop); - } double @@ -574,12 +550,12 @@ Shell7BaseXFEM :: evaluateCutHeaviside(const double xi, const double xiBottom, c // Evaluates the "cut" Heaviside defined as: // H(xi - xi1) - H(xi - xi2) or? // H(xi - xi1) * ( 1 - H(xi - xi2) ) - + if ( ( xiBottom <= xi ) && ( xi <= xiTop ) ) { return 1.0; } else { return 0.0; - } + } } @@ -605,14 +581,11 @@ Shell7BaseXFEM :: giveMaxCZDamages(FloatArray &answer, TimeStep *tStep) } } - answer(i) = max; + answer(i) = max; } else { answer(i) = 0.0; } } - - - } @@ -635,37 +608,37 @@ Shell7BaseXFEM :: computeCohesiveForces(FloatArray &answer, TimeStep *tStep, Flo FloatMatrix lambdaD, lambdaN, Q; FloatArray Fcoh, T, nCov, jump, unknowns, genEpsC, genEpsD; - - for ( GaussPoint *gp: *czIntegrationRulesArray [ delamNum - 1 ] ) { + + for ( auto &gp: *czIntegrationRulesArray [ delamNum - 1 ] ) { double xi = dei->giveDelamXiCoord(); lCoords.at(1) = gp->giveNaturalCoordinate(1); lCoords.at(2) = gp->giveNaturalCoordinate(2); lCoords.at(3) = xi; - + this->computeBmatrixAt(lCoords, B); this->computeCohesiveNmatrixAt(lCoords, Ncoh, coupledToEi); - + // Compute jump vector - this->computeInterfaceJumpAt(dei->giveDelamInterfaceNum(), lCoords, tStep, jump); // -> numerical tol. issue -> normal jump = 1e-10 - + jump = this->computeInterfaceJumpAt(dei->giveDelamInterfaceNum(), lCoords, tStep); // -> numerical tol. issue -> normal jump = 1e-10 + genEpsC.beProductOf(B, solVecC); - this->computeFAt(lCoords, F, genEpsC, tStep); + F = this->computeFAt(lCoords, genEpsC, tStep); // Transform xd and F to a local coord system - this->evalInitialCovarNormalAt(nCov, lCoords); + nCov = this->evalInitialCovarNormalAt(lCoords); Q.beLocalCoordSys(nCov); jump.rotatedWith(Q,'n'); F.rotatedWith(Q,'n'); // Compute cohesive traction based on jump - intMat->giveFirstPKTraction_3d(T, gp, jump, F, tStep); - + T = intMat->giveFirstPKTraction_3d(jump, F, gp, tStep); + //zzjump.printYourself("spatial jump"); //T.printYourself("Traction"); T.rotatedWith(Q,'t'); // transform back to global coord system double zeta = xi * this->layeredCS->computeIntegralThick() * 0.5; - this->computeLambdaNMatrixDis(lambdaD,zeta); + lambdaD = this->computeLambdaNMatrixDis(zeta); lambdaN.beProductOf(lambdaD, Ncoh); Fcoh.beTProductOf(lambdaN, T); double dA = this->computeAreaAround(gp,xi); @@ -679,9 +652,9 @@ Shell7BaseXFEM :: computeCohesiveForces(FloatArray &answer, TimeStep *tStep, Flo } } + void Shell7BaseXFEM :: updateYourself(TimeStep *tStep) -// Updates the receiver at end of step. { Shell7Base :: updateYourself(tStep); @@ -690,12 +663,9 @@ Shell7BaseXFEM :: updateYourself(TimeStep *tStep) czIntegrationRulesArray [ i ]->updateYourself(tStep); } } - - } - void Shell7BaseXFEM :: computeCohesiveTangent(FloatMatrix &answer, TimeStep *tStep) { @@ -721,9 +691,8 @@ Shell7BaseXFEM :: computeCohesiveTangent(FloatMatrix &answer, TimeStep *tStep) // dei is the current delamination where the material tangent d(trac)/d(jump) is evaluated Delamination *dei = dynamic_cast< Delamination * >( this->xMan->giveEnrichmentItem(i) ); - if ( dei != NULL && dei->isElementEnriched(this) && this->hasCohesiveZone(i) ) { - - + if ( dei && dei->isElementEnriched(this) && this->hasCohesiveZone(i) ) { + for ( int j = 1; j <= this->xMan->giveNumberOfEnrichmentItems(); j++ ) { for ( int k = j; k <= this->xMan->giveNumberOfEnrichmentItems(); k++ ) { // upper triangular part // Coupling enrichments @@ -732,13 +701,13 @@ Shell7BaseXFEM :: computeCohesiveTangent(FloatMatrix &answer, TimeStep *tStep) //EnrichmentItem *ei_k = this->xMan->giveEnrichmentItem(k); Delamination *dei_k = dynamic_cast< Delamination * >( this->xMan->giveEnrichmentItem(k) ); if ( dei_j && dei_j->isElementEnriched(this) && dei_k && dei_k->isElementEnriched(this) ) { - + this->computeCohesiveTangentAt(temp, tStep, dei, dei_j, dei_k); // Assemble part correpsonding to active dofs tempRed.beSubMatrixOf(temp, this->activeDofsArrays[dei_j->giveNumber()-1], this->activeDofsArrays[dei_k->giveNumber()-1]); answer.assemble(tempRed, this->orderingArrays[dei_j->giveNumber()-1], this->orderingArrays[dei_k->giveNumber()-1]); - + if( j != k ) { // add off diagonal contributions tempRedT.beTranspositionOf(tempRed); answer.assemble(tempRedT, this->orderingArrays[dei_k->giveNumber()-1], this->orderingArrays[dei_j->giveNumber()-1]); @@ -760,8 +729,7 @@ Shell7BaseXFEM :: computeCohesiveTangentAt(FloatMatrix &answer, TimeStep *tStep, * K_cz = Ncoh_j^t*lambda*t * dT/dj * lambda * Ncoh_k * */ - FloatArray lCoords(3); - FloatMatrix answerTemp, Ncoh_j, Ncoh_k, lambda, D, temp, tangent; + FloatMatrix answerTemp, Ncoh_j, Ncoh_k, temp, tangent; int nDofs = Shell7Base :: giveNumberOfDofs(); answerTemp.resize(nDofs, nDofs); answerTemp.zero(); @@ -773,27 +741,24 @@ Shell7BaseXFEM :: computeCohesiveTangentAt(FloatMatrix &answer, TimeStep *tStep, double xi = dei->giveDelamXiCoord(); - FloatMatrix Q; - FloatArray nCov; - for ( GaussPoint *gp: *iRuleL ) { - lCoords = { gp->giveNaturalCoordinate(1), gp->giveNaturalCoordinate(2), xi}; + for ( auto &gp: *iRuleL ) { + FloatArrayF<3> lCoords = { gp->giveNaturalCoordinate(1), gp->giveNaturalCoordinate(2), xi}; + + auto D = intMat->give3dStiffnessMatrix_dTdj(TangentStiffness, gp, tStep); - intMat->give3dStiffnessMatrix_dTdj(D, TangentStiffness, gp, tStep); - //IntMatBilinearCZJanssonStatus *status = static_cast< IntMatBilinearCZJanssonStatus * >( intMat->giveStatus(gp) ); //double damage = status->giveTempDamage(); //if ( damage >= 1 ) { printf("Full damage in elt %i \n",damage,this->giveNumber()); } - - - this->evalInitialCovarNormalAt(nCov, lCoords); - Q.beLocalCoordSys(nCov); - D.rotatedWith(Q,'t'); // rotate back to global coord system + + auto nCov = this->evalInitialCovarNormalAt(lCoords); + auto Q = local_cs(nCov); + D = unrotate(D, Q); // rotate back to global coord system double zeta = giveGlobalZcoord( lCoords); - this->computeLambdaNMatrixDis( lambda, zeta ); + auto lambda = this->computeLambdaNMatrixDis(zeta); this->computeCohesiveNmatrixAt(lCoords, Ncoh_j, ei_j); this->computeCohesiveNmatrixAt(lCoords, Ncoh_k, ei_k); - + ///@todo Use N*lambda and then apply plusProductUnsym instead; this->computeTripleProduct(temp, lambda, D, lambda); this->computeTripleProduct(tangent, Ncoh_j, temp, Ncoh_k); @@ -820,7 +785,7 @@ Shell7BaseXFEM :: computeCohesiveNmatrixAt(const FloatArray &lCoords, FloatMatri FloatArray perturbedCoords = lCoords; perturbedCoords.at(3) = lCoords.at(3) + 1.0e-9; // make sure we are on the plus side this->computeEnrichedNmatrixAt(perturbedCoords, answer, ei); - + perturbedCoords.at(3) = lCoords.at(3) - 1.0e-9; // make sure we are on the minus side this->computeEnrichedNmatrixAt(perturbedCoords, N_minus_side, ei); answer.subtract(N_minus_side); @@ -831,44 +796,40 @@ Shell7BaseXFEM :: computeCohesiveNmatrixAt(const FloatArray &lCoords, FloatMatri void Shell7BaseXFEM :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { - this->OLDcomputeStiffnessMatrix(answer, rMode, tStep); return; int ndofs = this->giveNumberOfDofs(); answer.resize(ndofs, ndofs); answer.zero(); - + int numberOfLayers = this->layeredCS->giveNumberOfLayers(); FloatMatrix tempRed, tempRedT; FloatMatrix KCC, KDC, KDD; FloatMatrix LCC, LDD, LDC; FloatMatrix B, BenrM, BenrK; - - + IntArray orderingC, activeDofsC; this->computeOrderingArray(orderingC, activeDofsC, NULL); FloatArray solVec; this->giveUpdatedSolutionVector(solVec, tStep); - + FloatMatrix A [ 3 ] [ 3 ], LB, KOrdered; KOrdered.resize(ndofs,ndofs); - const IntArray &ordering = this->giveOrderingDofTypes(); - + for ( int layer = 1; layer <= numberOfLayers; layer++ ) { StructuralMaterial *layerMaterial = static_cast< StructuralMaterial* >( domain->giveMaterial( this->layeredCS->giveLayerMaterial(layer) ) ); - for ( GaussPoint *gp: *integrationRulesArray [ layer - 1 ] ) { + for ( auto &gp: *integrationRulesArray [ layer - 1 ] ) { const FloatArray &lCoords = gp->giveNaturalCoordinates(); Shell7Base :: computeBmatrixAt(lCoords,B); double dV = this->computeVolumeAroundLayer(gp, layer); - - + Shell7Base :: computeLinearizedStiffness(gp, layerMaterial, tStep, A); // called L in new formulation this->discComputeStiffness(LCC, LDD, LDC, gp, layer, A, tStep); // called D in new formulation - + LB.beProductOf(LCC, B); KCC.clear(); KCC.plusProductSymmUpper(B, LB, dV); @@ -877,7 +838,7 @@ Shell7BaseXFEM :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rM KOrdered.assemble(KCC, ordering, ordering); // from dof group to node ordering tempRed.beSubMatrixOf(KOrdered, activeDofsC, activeDofsC); answer.assemble(tempRed, orderingC, orderingC); // position in element stiffness matrix - + // Discontinuous part int numEI = this->xMan->giveNumberOfEnrichmentItems(); for ( int m = 1; m <= numEI; m++ ) { @@ -890,18 +851,17 @@ Shell7BaseXFEM :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rM KDC.plusProductUnsym(BenrM, LB, dV); KOrdered.zero(); KOrdered.assemble(KDC, ordering, ordering); - + tempRed.beSubMatrixOf(KOrdered, this->activeDofsArrays[m-1], activeDofsC); tempRedT.beTranspositionOf(tempRed); answer.assemble(tempRed, this->orderingArrays[m-1], orderingC); - answer.assemble(tempRedT, orderingC, this->orderingArrays[m-1]); - + answer.assemble(tempRedT, orderingC, this->orderingArrays[m-1]); // K_{dk,dl} for ( int k = 1; k <= numEI; k++ ) { EnrichmentItem *eiK = this->xMan->giveEnrichmentItem(k); this->computeEnrichedBmatrixAt(lCoords, BenrK, eiK); - + if ( eiK->isElementEnriched(this) ) { if ( this->activeDofsArrays[m-1].giveSize() != 0 && this->activeDofsArrays[k-1].giveSize() != 0 ) { LB.beProductOf(LDD, BenrK); @@ -913,13 +873,10 @@ Shell7BaseXFEM :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rM tempRed.beSubMatrixOf(KOrdered, this->activeDofsArrays[m-1], this->activeDofsArrays[k-1]); answer.assemble(tempRed, this->orderingArrays[m-1], this->orderingArrays[k-1]); } - } - } } } - } } @@ -949,7 +906,7 @@ Shell7BaseXFEM :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rM IntegrationRule *iRule = specialIntegrationRulesArray [ 1 ]; - for ( GaussPoint *gp: *iRule ) { + for ( auto &gp: *iRule ) { this->computePressureTangentMatrixDis(KCC, KCD, KDD, gp, load, iSurf, tStep); KCD.times(DISC_DOF_SCALE_FAC); KDD.times(DISC_DOF_SCALE_FAC*DISC_DOF_SCALE_FAC); @@ -965,7 +922,7 @@ Shell7BaseXFEM :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rM if ( deiM !=NULL && deiM->isElementEnriched(this) ) { double levelSetM = pLoad->giveLoadOffset() - deiM->giveDelamXiCoord(); deiM->evaluateEnrFuncAt(efM, lCoords, levelSetM); - + IntArray &orderingJ = orderingArrays[m-1]; IntArray &activeDofsJ = activeDofsArrays[m-1]; @@ -990,16 +947,10 @@ Shell7BaseXFEM :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rM answer.assemble(tempRed, orderingJ, orderingK); } } - } } - } - } - - - } } #endif @@ -1015,22 +966,20 @@ Shell7BaseXFEM :: discComputeStiffness(FloatMatrix &LCC, FloatMatrix &LDD, Float // L_DD = lambdaD_i^T * A_ij * lambdaD_j // L_CD = lambdaC_i^T * A_ij * lambdaD_j FloatMatrix B; - FloatMatrix lambdaC [ 3 ], lambdaD [ 3 ]; - const FloatArray &lCoords = ip->giveNaturalCoordinates(); + const auto &lCoords = ip->giveNaturalCoordinates(); FloatArray solVecC, genEpsC; Shell7Base :: computeBmatrixAt(lCoords,B); - + double zeta = giveGlobalZcoord( lCoords ); this->giveUpdatedSolutionVector(solVecC, tStep); genEpsC.beProductOf(B,solVecC); - this->computeLambdaGMatrices(lambdaC, genEpsC, zeta); - this->computeLambdaGMatricesDis(lambdaD, zeta); + auto lambdaC = this->computeLambdaGMatrices(genEpsC, zeta); + auto lambdaD = this->computeLambdaGMatricesDis(zeta); FloatMatrix A_lambdaC(3,18), A_lambdaD(3,18); LCC.clear(); LDD.clear(); LDC.clear(); - - + for (int i = 0; i < 3; i++) { A_lambdaC.zero(); A_lambdaD.zero(); for (int j = 0; j < 3; j++) { @@ -1043,8 +992,6 @@ Shell7BaseXFEM :: discComputeStiffness(FloatMatrix &LCC, FloatMatrix &LDD, Float } LCC.symmetrized(); LDD.symmetrized(); - - } @@ -1069,38 +1016,41 @@ Shell7BaseXFEM :: OLDcomputeStiffnessMatrix(FloatMatrix &answer, MatResponseMode FloatMatrix A [ 3 ] [ 3 ]; Shell7Base :: computeBulkTangentMatrix(KCC, solVec, tStep ); + answer.assemble(KCC, orderingC, orderingC); + for ( int layer = 1; layer <= numberOfLayers; layer++ ) { StructuralMaterial *layerMaterial = static_cast< StructuralMaterial* >( domain->giveMaterial( this->layeredCS->giveLayerMaterial(layer) ) ); - - for ( GaussPoint *gp: *integrationRulesArray [ layer - 1 ] ) { + + for ( auto &gp: *integrationRulesArray [ layer - 1 ] ) { const FloatArray &lCoords = gp->giveNaturalCoordinates(); this->computeEnrichedBmatrixAt(lCoords, Bc, NULL); - + Shell7Base :: computeLinearizedStiffness(gp, layerMaterial, tStep, A); - + // Continuous part K_{c,c} //this->discComputeBulkTangentMatrix(KCC, gp, NULL, NULL, layer, A, tStep); //answer.assemble(KCC, orderingC, orderingC); - + // Discontinuous part int numEI = this->xMan->giveNumberOfEnrichmentItems(); for ( int m = 1; m <= numEI; m++ ) { EnrichmentItem *eiM = this->xMan->giveEnrichmentItem(m); - + if ( eiM->isElementEnriched(this) ) { - + this->discComputeBulkTangentMatrix(KCD, gp, NULL, eiM, layer, A, tStep); tempRed.beSubMatrixOf(KCD, activeDofsC, this->activeDofsArrays[m-1]); answer.assemble(tempRed, orderingC, this->orderingArrays[m-1]); + tempRedT.beTranspositionOf(tempRed); answer.assemble(tempRedT, this->orderingArrays[m-1], orderingC); - + // K_{dk,dl} for ( int k = 1; k <= numEI; k++ ) { EnrichmentItem *eiK = this->xMan->giveEnrichmentItem(k); - + if ( eiK->isElementEnriched(this) ) { this->discComputeBulkTangentMatrix(KDD, gp, eiM, eiK, layer, A, tStep); if ( this->activeDofsArrays[m-1].giveSize() != 0 && this->activeDofsArrays[k-1].giveSize() != 0 ) { @@ -1117,7 +1067,6 @@ Shell7BaseXFEM :: OLDcomputeStiffnessMatrix(FloatMatrix &answer, MatResponseMode } } - // Cohesive zones #if 1 FloatMatrix Kcoh; @@ -1138,31 +1087,31 @@ for ( int k = 1; k <= nLoads; k++ ) { // For each pressure load that is appl int iSurf = this->boundaryLoadArray.at(2 * k); // load_id Load *load = this->domain->giveLoad(load_number); std :: vector< double > efM, efK; - + if ( ConstantPressureLoad * pLoad = dynamic_cast< ConstantPressureLoad * >(load) ) { - + IntegrationRule *iRule = specialIntegrationRulesArray [ 1 ]; - - for ( GaussPoint *gp: *iRule ) { + + for ( auto &gp: *iRule ) { this->computePressureTangentMatrixDis(KCC, KCD, KDD, gp, load, iSurf, tStep); KCD.times(DISC_DOF_SCALE_FAC); KDD.times(DISC_DOF_SCALE_FAC*DISC_DOF_SCALE_FAC); - + // Continuous part answer.assemble(KCC, orderingC, orderingC); - + // Discontinuous part int numEI = this->xMan->giveNumberOfEnrichmentItems(); for ( int m = 1; m <= numEI; m++ ) { Delamination *deiM = dynamic_cast< Delamination * >( this->xMan->giveEnrichmentItem(m) ); - + if ( deiM !=NULL && deiM->isElementEnriched(this) ) { double levelSetM = pLoad->giveLoadOffset() - deiM->giveDelamXiCoord(); deiM->evaluateEnrFuncAt(efM, lCoords, levelSetM); - + IntArray &orderingJ = orderingArrays[m-1]; IntArray &activeDofsJ = activeDofsArrays[m-1]; - + // con-dis & dis-con if ( efM[0] > 0.1 ) { tempRed.beSubMatrixOf(KCD, activeDofsC, activeDofsJ); @@ -1192,8 +1141,6 @@ for ( int k = 1; k <= numEI; k++ ) { } - - } } #endif @@ -1206,32 +1153,31 @@ Shell7BaseXFEM :: discComputeBulkTangentMatrix(FloatMatrix &KdIJ, IntegrationPoi { FloatMatrix temp, B1, B2; - FloatMatrix lambda1 [ 3 ], lambda2 [ 3 ]; + std::array, 3> lambda1, lambda2; - const FloatArray &lCoords = ip->giveNaturalCoordinates(); + const auto &lCoords = ip->giveNaturalCoordinates(); this->computeEnrichedBmatrixAt(lCoords, B1, ei1); this->computeEnrichedBmatrixAt(lCoords, B2, ei2); int eiNum1 = 0, eiNum2 = 0; double zeta = giveGlobalZcoord( lCoords ); if ( ei1 ) { - this->computeLambdaGMatricesDis(lambda1, zeta); + lambda1 = this->computeLambdaGMatricesDis(zeta); eiNum1 = ei1->giveNumber(); } else { FloatArray solVecC, genEpsC; this->giveUpdatedSolutionVector(solVecC, tStep); genEpsC.beProductOf(B1,solVecC); - this->computeLambdaGMatrices(lambda1, genEpsC, zeta); + lambda1 = this->computeLambdaGMatrices(genEpsC, zeta); } - if ( ei2 ) { - this->computeLambdaGMatricesDis(lambda2, zeta); + lambda2 = this->computeLambdaGMatricesDis(zeta); eiNum2 = ei2->giveNumber(); } else { FloatArray solVecC, genEpsC; this->giveUpdatedSolutionVector(solVecC, tStep); genEpsC.beProductOf(B2,solVecC); - this->computeLambdaGMatrices(lambda2, genEpsC, zeta); + lambda2 = this->computeLambdaGMatrices(genEpsC, zeta); } double dV = this->computeVolumeAroundLayer(ip, layer); @@ -1244,7 +1190,7 @@ Shell7BaseXFEM :: discComputeBulkTangentMatrix(FloatMatrix &KdIJ, IntegrationPoi if ( eiNum1 == eiNum2 ) { // diagonal element //if (0 ) { // diagonal element - + for (int i = 0; i < 3; i++) { A_lambda.zero(); for (int j = 0; j < 3; j++) { @@ -1264,8 +1210,8 @@ Shell7BaseXFEM :: discComputeBulkTangentMatrix(FloatMatrix &KdIJ, IntegrationPoi L.add(dV,temp); } } - this->computeTripleProduct(KDDtemp, B1, L, B2 ); - } + this->computeTripleProduct(KDDtemp, B1, L, B2 ); + } KdIJ.resize(ndofs,ndofs); KdIJ.zero(); @@ -1276,10 +1222,8 @@ Shell7BaseXFEM :: discComputeBulkTangentMatrix(FloatMatrix &KdIJ, IntegrationPoi } - - -void -Shell7BaseXFEM :: computeLambdaGMatricesDis(FloatMatrix lambda [ 3 ], double zeta) +std::array, 3> +Shell7BaseXFEM :: computeLambdaGMatricesDis(double zeta) { // computes the lambda^g matrices associated with the variation and linearization // of the discontinuous base vectors gd_i. @@ -1288,49 +1232,46 @@ Shell7BaseXFEM :: computeLambdaGMatricesDis(FloatMatrix lambda [ 3 ], double zet double a = zeta ; double c = 1.0 ; + std::array, 3> lambda; // lambda1 = ( I, 0, a*I, 0 , 0, 0 , 0, 0 ) + lambda[ 0 ].at(1,1) = lambda[ 0 ].at(2,2) = lambda[ 0 ].at(3,3) = 1.; + lambda[ 0 ].at(1,7) = lambda[ 0 ].at(2,8) = lambda[ 0 ].at(3,9) = a; + // lambda2 = ( 0, I, 0 , a*I, 0, 0 , 0, 0 ) - FloatMatrix eye(3,3), aEye(3,3); - eye.beUnitMatrix(); - aEye=eye; aEye.times(a); - lambda[ 0 ].resize(3,18); lambda[ 0 ].zero(); - lambda[ 1 ].resize(3,18); lambda[ 1 ].zero(); - lambda[ 0 ].setSubMatrix(eye,1,1); lambda[ 0 ].setSubMatrix(aEye,1,7); - lambda[ 1 ].setSubMatrix(eye,1,4); lambda[ 1 ].setSubMatrix(aEye,1,10); + lambda[ 1 ].at(1,4) = lambda[ 1 ].at(2,5) = lambda[ 1 ].at(3,6) = 1.; + lambda[ 1 ].at(1,10) = lambda[ 1 ].at(2,11) = lambda[ 1 ].at(3,12) = a; // lambda3 = ( 0, 0, 0 , 0 , c*I , 0 , 0 , 0 ) - lambda[ 2 ].resize(3,18); lambda[ 2 ].zero(); lambda[ 2 ].at(1,13) = lambda[ 2 ].at(2,14) = lambda[ 2 ].at(3,15) = c; + return lambda; } -void -Shell7BaseXFEM :: computeLambdaNMatrixDis(FloatMatrix &lambda_xd, double zeta) + +FloatMatrixF<3,7> +Shell7BaseXFEM :: computeLambdaNMatrixDis(double zeta) { // computes the lambda_x matrix associated with the variation and linearization of the // discontinuous position vector x_di. (\delta x_{di} = lambda_{xd}*\delta n_x) - + // lambda_x = ( I, a*I, 0 ) - lambda_xd.resize(3,7); - lambda_xd.zero(); + FloatMatrixF<3,7> lambda_xd; lambda_xd.at(1,1) = lambda_xd.at(2,2) = lambda_xd.at(3,3) = 1.0; lambda_xd.at(1,4) = lambda_xd.at(2,5) = lambda_xd.at(3,6) = zeta; + return lambda_xd; } - void Shell7BaseXFEM :: computePressureTangentMatrixDis(FloatMatrix &KCC, FloatMatrix &KCD, FloatMatrix &KDD, IntegrationPoint *ip, Load *load, const int iSurf, TimeStep *tStep) { // Computes tangent matrix associated with the linearization of pressure loading. Assumes constant pressure. ConstantPressureLoad* pLoad = dynamic_cast< ConstantPressureLoad * >( load ); - - FloatMatrix N, B, gcov, W1, W2; - FloatArray lCoords, solVec, pressure; - FloatArray g1, g2, genEps; - FloatMatrix lambdaGC [ 3 ], lambdaNC, lambdaGD [ 3 ], lambdaND; + + FloatMatrix N, B; + FloatArray solVec, pressure; double xi = pLoad->giveLoadOffset(); - lCoords = ip->giveNaturalCoordinates(); + FloatArrayF<3> lCoords = ip->giveNaturalCoordinates(); lCoords.at(3) = xi; // local coord where load is applied double zeta = this->giveGlobalZcoord( lCoords ); this->giveUpdatedSolutionVector(solVec, tStep); @@ -1338,50 +1279,37 @@ Shell7BaseXFEM :: computePressureTangentMatrixDis(FloatMatrix &KCC, FloatMatrix // compute w1,w2, KC this->computeNmatrixAt(lCoords, N); this->computeBmatrixAt(lCoords, B); + FloatArray genEps; genEps.beProductOf(B, solVec); - - FloatMatrix LCC, LCD, LDD; - //(xc+xd)*(g1xg2)=xc*g1xg2 + xd*g1xg2 -> xc*(W2*Dg1 - W1*Dg2) + xd*(W2*Dg1 - W1*Dg2) // Traction tangent, L = lambdaN * ( W2*lambdaG_1 - W1*lambdaG_2 ) load->computeValueAt(pressure, tStep, ip->giveNaturalCoordinates(), VM_Total); // pressure component - this->evalCovarBaseVectorsAt(lCoords, gcov, genEps, tStep); - g1.beColumnOf(gcov,1); - g2.beColumnOf(gcov,2); - W1 = this->giveAxialMatrix(g1); - W2 = this->giveAxialMatrix(g2); - - this->computeLambdaGMatrices(lambdaGC, genEps, zeta); - this->computeLambdaNMatrix(lambdaNC, genEps, zeta); - this->computeLambdaGMatricesDis(lambdaGD, zeta); - this->computeLambdaNMatrixDis(lambdaND, zeta); - - FloatMatrix W2L, W1L; - W2L.beProductOf(W2,lambdaGC[0]); - W1L.beProductOf(W1,lambdaGC[1]); - W2L.subtract(W1L); - LCC.beTProductOf(lambdaNC, W2L); - LCC.times( -pressure.at(1) ); - - W2L.beProductOf(W2,lambdaGD[0]); - W1L.beProductOf(W1,lambdaGD[1]); - W2L.subtract(W1L); - LCD.beTProductOf(lambdaNC, W2L); - LCD.times( -pressure.at(1) ); - - W2L.beProductOf(W2,lambdaGD[0]); - W1L.beProductOf(W1,lambdaGD[1]); - W2L.subtract(W1L); - LDD.beTProductOf(lambdaND, W2L); - LDD.times( -pressure.at(1) ); + auto gcov = this->evalCovarBaseVectorsAt(lCoords, genEps, tStep); + auto g1 = gcov.column(0); + auto g2 = gcov.column(1); + auto W1 = this->giveAxialMatrix(g1); + auto W2 = this->giveAxialMatrix(g2); + + auto lambdaGC = this->computeLambdaGMatrices(genEps, zeta); + auto lambdaNC = this->computeLambdaNMatrix(genEps, zeta); + auto lambdaGD = this->computeLambdaGMatricesDis(zeta); + auto lambdaND = this->computeLambdaNMatrixDis(zeta); + + auto W2L = dot(W2,lambdaGC[0]) - dot(W1,lambdaGC[1]); + auto LCC =-pressure.at(1) * Tdot(lambdaNC, W2L); + + W2L = dot(W2,lambdaGD[0]) - dot(W1,lambdaGD[1]); + auto LCD = -pressure.at(1) * Tdot(lambdaNC, W2L); + W2L = dot(W2,lambdaGD[0]) - dot(W1,lambdaGD[1]); + auto LDD = -pressure.at(1) * Tdot(lambdaND, W2L); FloatMatrix KCCtemp, KCDtemp, KDDtemp; this->computeTripleProduct(KCCtemp, N, LCC, B ); ///@todo Fix 090814 this->computeTripleProduct(KCDtemp, N, LCD, B ); this->computeTripleProduct(KDDtemp, N, LDD, B ); - + int ndofs = Shell7Base :: giveNumberOfDofs(); KCC.resize(ndofs,ndofs); KCD.resize(ndofs,ndofs); KDD.resize(ndofs,ndofs); KCC.zero(); KCD.zero(); KDD.zero(); @@ -1487,7 +1415,6 @@ Shell7BaseXFEM :: computeMassMatrixNum(FloatMatrix &answer, TimeStep *tStep) M33.add(0.25 * rho * dV, M33temp); } - answer.resize(ndofs, ndofs); answer.zero(); @@ -1572,8 +1499,7 @@ Shell7BaseXFEM :: computeEnrTractionForce(FloatArray &answer, const int iEdge, B int numberOfGaussPoints = ( int ) ceil( ( approxOrder + 1. ) / 2. ); GaussIntegrationRule iRule(1, this, 1, 1); iRule.SetUpPointsOnLine(numberOfGaussPoints, _Unknown); - - GaussPoint *gp; + FloatMatrix N, Q; FloatArray fT(7), components, lCoords; @@ -1581,15 +1507,14 @@ Shell7BaseXFEM :: computeEnrTractionForce(FloatArray &answer, const int iEdge, B FloatArray Nftemp(21), Nf(21); Nf.zero(); - for ( int i = 0; i < iRule.giveNumberOfIntegrationPoints(); i++ ) { - gp = iRule.getIntegrationPoint(i); - const FloatArray &lCoords = gp->giveNaturalCoordinates(); + for ( auto &gp : *iRule ) { + const auto &lCoords = gp->giveNaturalCoordinates(); edgeLoad->computeValueAt(components, tStep, lCoords, mode); this->edgeComputeEnrichedNmatrixAt(lCoords, N, ei, iEdge); if ( coordSystType == Load :: CST_UpdatedGlobal ) { - + // Updated global coord system FloatMatrix gcov; this->edgeEvalEnrCovarBaseVectorsAt(lCoords, iEdge, gcov, tStep, ei); @@ -1614,7 +1539,7 @@ Shell7BaseXFEM :: computeEnrTractionForce(FloatArray &answer, const int iEdge, B } double dL = this->edgeComputeLengthAround(gp, iEdge); - + Nftemp.beTProductOf(N, fT*dL); Nf.add(Nftemp); } @@ -1624,7 +1549,7 @@ Shell7BaseXFEM :: computeEnrTractionForce(FloatArray &answer, const int iEdge, B answer.resize( Shell7Base :: giveNumberOfDofs() ); answer.zero(); answer.assemble(Nf, mask); - + answer.printYourself("f_ext old"); #else @@ -1641,9 +1566,9 @@ Shell7BaseXFEM :: computeEnrTractionForce(FloatArray &answer, const int iEdge, B answer.zero(); Nf.resize( Shell7Base :: giveNumberOfDofs() ); Nf.zero(); - for ( GaussPoint *gp : iRule ) { + for ( auto &gp : iRule ) { const FloatArray &lCoordsEdge = gp->giveNaturalCoordinates(); - + this->fei->edgeLocal2global( gCoords, iEdge, lCoordsEdge, FEIElementGeometryWrapper(this) ); this->fei->global2local( lCoords, gCoords, FEIElementGeometryWrapper(this) ); @@ -1653,13 +1578,12 @@ Shell7BaseXFEM :: computeEnrTractionForce(FloatArray &answer, const int iEdge, B lCoords.at(3) = components.at(8); } this->computeEnrichedNmatrixAt(lCoords, N, ei); - + if ( coordSystType == Load :: CST_UpdatedGlobal ) { - + // Updated global coord system - FloatMatrix gcov; - this->edgeEvalEnrCovarBaseVectorsAt(lCoordsEdge, iEdge, gcov, tStep, ei); - Q.beTranspositionOf(gcov); + auto gcov = this->edgeEvalEnrCovarBaseVectorsAt(lCoordsEdge, iEdge, tStep, ei); + Q = transpose(gcov); FloatArray distrForces, distrMoments, t1, t2; distrForces = { components.at(1), components.at(2), components.at(3) }; @@ -1688,26 +1612,24 @@ Shell7BaseXFEM :: computeEnrTractionForce(FloatArray &answer, const int iEdge, B #endif } -void -Shell7BaseXFEM :: edgeEvalEnrCovarBaseVectorsAt(const FloatArray &lcoords, const int iedge, FloatMatrix &gcov, TimeStep *tStep, EnrichmentItem *ei) +FloatMatrixF<3,3> +Shell7BaseXFEM :: edgeEvalEnrCovarBaseVectorsAt(const FloatArrayF<3> &lcoords, const int iedge, TimeStep *tStep, EnrichmentItem *ei) { // Evaluates the covariant base vectors in the current configuration for an edge double zeta = lcoords.at(3); FloatArray solVecEdge; FloatMatrix B; - IntArray edgeNodes; - this->fei->computeLocalEdgeMapping(edgeNodes, iedge); + const auto &edgeNodes = this->fei->computeLocalEdgeMapping(iedge); this->edgeComputeEnrichedBmatrixAt(lcoords, B, ei, iedge); this->edgeGiveUpdatedSolutionVector(solVecEdge, iedge, tStep); FloatArray genEpsEdge; // generalized strain genEpsEdge.beProductOf(B, solVecEdge); // [dxdxi, dmdxi, m, dgamdxi, gam]^T - FloatArray dxdxi, m, dmdxi; - dxdxi = { genEpsEdge.at(1), genEpsEdge.at(2), genEpsEdge.at(3) }; - dmdxi = { genEpsEdge.at(4), genEpsEdge.at(5), genEpsEdge.at(6) }; - m = { genEpsEdge.at(7), genEpsEdge.at(8), genEpsEdge.at(9) }; + FloatArrayF<3> dxdxi = { genEpsEdge.at(1), genEpsEdge.at(2), genEpsEdge.at(3) }; + FloatArrayF<3> dmdxi = { genEpsEdge.at(4), genEpsEdge.at(5), genEpsEdge.at(6) }; + FloatArrayF<3> m = { genEpsEdge.at(7), genEpsEdge.at(8), genEpsEdge.at(9) }; double dgamdxi = genEpsEdge.at(10); double gam = genEpsEdge.at(11); @@ -1715,18 +1637,14 @@ Shell7BaseXFEM :: edgeEvalEnrCovarBaseVectorsAt(const FloatArray &lcoords, const double fac2 = ( 0.5 * zeta * zeta ); double fac3 = ( 1.0 + zeta * gam ); - FloatArray g1, g2, g3; - g2 = dxdxi + fac1*dmdxi + fac2*dgamdxi*m; // base vector along the edge - g3 = fac3*m; // director field + const auto g2 = normalize(dxdxi + fac1*dmdxi + fac2*dgamdxi*m); // base vector along the edge + const auto g3 = normalize(fac3*m); // director field + const auto g1 = normalize(cross(g2, g3)); - g2.normalize(); - g3.normalize(); - g1.beVectorProductOf(g2, g3); - g1.normalize(); - gcov = {g1, g2, g3}; + return FloatMatrixF<3,3>({g1, g2, g3}); } - + // Surface /* void @@ -1871,7 +1789,6 @@ Shell7BaseXFEM :: computeEnrichedBmatrixAt(const FloatArray &lCoords, FloatMatri answer.at(17, ndofs_xm * 2 + 1 + i-1) = dNdxi.at(i, 2) * factor; answer.at(18, ndofs_xm * 2 + 1 + i-1) = N.at(i) * factor; } - answer.times( this->evaluateHeavisideXi(lCoords.at(3), static_cast< ShellCrack* >(ei)) ); answer.times(DISC_DOF_SCALE_FAC); @@ -1888,20 +1805,19 @@ Shell7BaseXFEM :: computeEnrichedBmatrixAt(const FloatArray &lCoords, FloatMatri } } + double Shell7BaseXFEM :: EvaluateEnrFuncInDofMan(int dofManNum, EnrichmentItem *ei) { - DofManager *dMan = this->giveDofManager(dofManNum); if ( ei->isDofManEnriched(*dMan) ) { - int globalNodeInd = dMan->giveGlobalNumber(); // global number in order to pick levelset value in that node double levelSetNode = 0.0; - ei->evalLevelSetNormalInNode( levelSetNode, globalNodeInd, *(dMan->giveCoordinates()) ); + ei->evalLevelSetNormalInNode( levelSetNode, globalNodeInd, dMan->giveCoordinates() ); std :: vector< double >efNode; //const FloatArray &nodePos = * ( dMan->giveCoordinates() ); // evaluateEnrFuncAt requires coords to be size 2 - FloatArray nodePos = * ( dMan->giveCoordinates() ); + FloatArray nodePos = dMan->giveCoordinates(); nodePos.resizeWithValues(2); FloatArray localCoord; @@ -1919,7 +1835,6 @@ Shell7BaseXFEM :: EvaluateEnrFuncInDofMan(int dofManNum, EnrichmentItem *ei) } else { return 0.0; } - } @@ -1984,7 +1899,6 @@ Shell7BaseXFEM :: computeEnrichedNmatrixAt(const FloatArray &lCoords, FloatMatri } - void Shell7BaseXFEM :: edgeComputeEnrichedNmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei, const int edge) { @@ -2066,8 +1980,6 @@ Shell7BaseXFEM :: edgeComputeEnrichedBmatrixAt(const FloatArray &lCoords, FloatM answer.zero(); FloatArray N, dNdxi; - - if ( ei && dynamic_cast< Crack*>(ei) ) { this->fei->edgeEvalN( N, 1, lCoords, FEIElementGeometryWrapper(this) ); @@ -2100,7 +2012,7 @@ Shell7BaseXFEM :: edgeComputeEnrichedBmatrixAt(const FloatArray &lCoords, FloatM ei->evaluateEnrFuncAt(efGP, gcoords, lCoords, nodeInd, *this, N, giveDofManArray()); double factor = efGP [ 0 ] - EvaluateEnrFuncInDofMan(i, ei); - + answer.at(1, 1 + j) = dNdxi.at(i) * factor; answer.at(2, 2 + j) = dNdxi.at(i) * factor; answer.at(3, 3 + j) = dNdxi.at(i) * factor; @@ -2154,29 +2066,26 @@ Shell7BaseXFEM :: edgeComputeEnrichedBmatrixAt(const FloatArray &lCoords, FloatM - - - // Delamination specific -void -Shell7BaseXFEM :: vtkEvalUpdatedGlobalCoordinateAt(const FloatArray &localCoords, int layer, FloatArray &globalCoords, TimeStep *tStep) +FloatArrayF<3> +Shell7BaseXFEM :: vtkEvalUpdatedGlobalCoordinateAt(const FloatArrayF<3> &localCoords, int layer, TimeStep *tStep) { double zeta = this->giveGlobalZcoord( localCoords ); // Continuous part FloatArray solVec; this->giveUpdatedSolutionVector(solVec, tStep); - FloatArray xc, mc; double gamc=0; + FloatArrayF<3> xc, mc; + double gamc = 0; Shell7Base :: giveUnknownsAt(localCoords, solVec, xc, mc, gamc, tStep); double fac_cont = ( zeta + 0.5 * gamc * zeta * zeta ); - globalCoords = xc; - globalCoords.add(fac_cont,mc); + auto globalCoords = xc + fac_cont * mc; #if 1 // Discontinuous part - FloatArray solVecD, xd, md, xtemp(3); + FloatArray solVecD; double gamd = 0; for ( int i = 1; i <= this->xMan->giveNumberOfEnrichmentItems(); i++ ) { EnrichmentItem *ei = this->xMan->giveEnrichmentItem(i); @@ -2185,20 +2094,20 @@ Shell7BaseXFEM :: vtkEvalUpdatedGlobalCoordinateAt(const FloatArray &localCoords IntArray eiDofIdArray; ei->giveEIDofIdArray(eiDofIdArray); this->computeDiscSolutionVector(eiDofIdArray, tStep, solVecD); + FloatArrayF<3> xd, md; this->giveDisUnknownsAt(localCoords, ei, solVecD, xd, md, gamd, tStep); double fac_disc = ( zeta + 0.5 * gamd * zeta * zeta ); - xtemp = xd; - xtemp.add(fac_disc,md); - globalCoords.add(xtemp); + auto xtemp = xd + fac_disc * md; + globalCoords += xtemp; } - } #endif + return globalCoords; } void -Shell7BaseXFEM :: giveDisUnknownsAt(const FloatArray &lcoords, EnrichmentItem *ei, FloatArray &solVec, FloatArray &x, FloatArray &m, double &gam, TimeStep *tStep) +Shell7BaseXFEM :: giveDisUnknownsAt(const FloatArrayF<3> &lcoords, EnrichmentItem *ei, const FloatArray &solVec, FloatArrayF<3> &x, FloatArrayF<3> &m, double &gam, TimeStep *tStep) { // returns the unknowns evaluated at a point (xi1, xi2, xi3) FloatArray vec; @@ -2208,29 +2117,23 @@ Shell7BaseXFEM :: giveDisUnknownsAt(const FloatArray &lcoords, EnrichmentItem *e x = {vec.at(1), vec.at(2), vec.at(3)}; m = {vec.at(4), vec.at(5), vec.at(6)}; gam = vec.at(7); - } - void Shell7BaseXFEM :: giveCompositeExportData(std::vector< VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ) { vtkPieces.resize(1); this->giveShellExportData(vtkPieces[0], primaryVarsToExport, internalVarsToExport, cellVarsToExport, tStep ); //this->giveCZExportData(vtkPieces[1], primaryVarsToExport, internalVarsToExport, cellVarsToExport, tStep ); - } - void Shell7BaseXFEM :: giveCompositeExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ) { - this->giveCZExportData(vtkPiece, primaryVarsToExport, internalVarsToExport, cellVarsToExport, tStep ); //this->giveShellExportData(vtkPiece, primaryVarsToExport, internalVarsToExport, cellVarsToExport, tStep ); - } void @@ -2238,7 +2141,6 @@ Shell7BaseXFEM :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT { int numSubCells = 1; - int numLayers = this->layeredCS->giveNumberOfLayers(); //int numCells = numLayers * numSubCells; // Go through each layer and count the number of subcells @@ -2269,22 +2171,22 @@ Shell7BaseXFEM :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT // Node coordinates if ( numSubCells == 1 ) { - Shell7Base :: giveFictiousNodeCoordsForExport(nodeCoords, layer); + nodeCoords = Shell7Base :: giveFictiousNodeCoordsForExport(layer); } else { - this->giveFictiousNodeCoordsForExport(nodeCoords, layer, subCell); + nodeCoords = this->giveFictiousNodeCoordsForExport(layer, subCell); } - + for ( int node = 1; node <= numCellNodes; node++ ) { vtkPiece.setNodeCoords(nodeNum, nodeCoords[node-1] ); nodeNum += 1; } - // Connectivity + // Connectivity for ( int i = 1; i <= numCellNodes; i++ ) { nodes.at(i) = val++; } vtkPiece.setConnectivity(currentCell, nodes); - + // Offset offset += numCellNodes; vtkPiece.setOffset(currentCell, offset); @@ -2297,23 +2199,20 @@ Shell7BaseXFEM :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT } } - - - // Export nodal variables from primary fields - vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport.giveSize(), numTotalNodes); + vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport, numTotalNodes); std::vector updatedNodeCoords; FloatArray u(3); std::vector values; for ( int fieldNum = 1; fieldNum <= primaryVarsToExport.giveSize(); fieldNum++ ) { - + // if ( recoverStress ) { // // Recover shear stresses // //printf("Shell7BaseXFEM: recover shear stress function \n"); // this->recoverShearStress(tStep); // } - + UnknownType type = ( UnknownType ) primaryVarsToExport.at(fieldNum); nodeNum = 1; currentCell = 1; @@ -2323,62 +2222,56 @@ Shell7BaseXFEM :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT for ( int subCell = 1; subCell <= numSubCells; subCell++ ) { if ( type == DisplacementVector ) { // compute displacement as u = x - X - if ( numSubCells == 1 ) { - Shell7Base :: giveFictiousNodeCoordsForExport(nodeCoords, layer); - this->giveFictiousUpdatedNodeCoordsForExport(updatedNodeCoords, layer, tStep, 0); - } else { - this->giveFictiousNodeCoordsForExport(nodeCoords, layer, subCell); - this->giveFictiousUpdatedNodeCoordsForExport(updatedNodeCoords, layer, tStep, subCell); - } + auto nodeCoords = numSubCells == 1 ? + Shell7Base :: giveFictiousNodeCoordsForExport(layer) : + this->giveFictiousNodeCoordsForExport(layer, subCell); + auto updatedNodeCoords = this->giveFictiousUpdatedNodeCoordsForExport(layer, tStep, numSubCells == 1 ? 0 : subCell); for ( int j = 1; j <= numCellNodes; j++ ) { u = updatedNodeCoords[j-1]; u.subtract(nodeCoords[j-1]); - vtkPiece.setPrimaryVarInNode(fieldNum, nodeNum, u); + vtkPiece.setPrimaryVarInNode(type, nodeNum, u); nodeNum += 1; } } else { NodalRecoveryMI_recoverValues(values, layer, ( InternalStateType ) 1, tStep); // does not work well - fix for ( int j = 1; j <= numCellNodes; j++ ) { - vtkPiece.setPrimaryVarInNode(fieldNum, nodeNum, values[j-1]); + vtkPiece.setPrimaryVarInNode(type, nodeNum, values[j-1]); nodeNum += 1; } } - currentCell++; } } } - // Export nodal variables from internal fields - - vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport.giveSize(), numTotalNodes ); + + vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport, numTotalNodes ); for ( int fieldNum = 1; fieldNum <= internalVarsToExport.giveSize(); fieldNum++ ) { InternalStateType type = ( InternalStateType ) internalVarsToExport.at(fieldNum); nodeNum = 1; - + //int currentCell = 1; for ( int layer = 1; layer <= numLayers; layer++ ) { numSubCells = (int)this->numSubDivisionsArray[layer - 1]; for ( int subCell = 1; subCell <= numSubCells; subCell++ ) { recoverValuesFromIP(values, layer, type, tStep); - + for ( int j = 1; j <= numCellNodes; j++ ) { - vtkPiece.setInternalVarInNode( fieldNum, nodeNum, values[j-1] ); + vtkPiece.setInternalVarInNode( type, nodeNum, values[j-1] ); //ZZNodalRecoveryMI_recoverValues(el.nodeVars[fieldNum], layer, type, tStep); nodeNum += 1; - } + } } - } + } } - // Export cell variables FloatArray average; - vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport.giveSize(), numCells); + vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport, numCells); for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) { InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i); InternalStateValueType valueType = giveInternalStateValueType(type); @@ -2389,9 +2282,9 @@ Shell7BaseXFEM :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT std :: unique_ptr< IntegrationRule > &iRuleL = integrationRulesArray [ layer - 1 ]; VTKXMLExportModule :: computeIPAverage(average, iRuleL.get(), this, type, tStep); if ( valueType == ISVT_TENSOR_S3 ) { - vtkPiece.setCellVar(i, currentCell, convV6ToV9Stress(average) ); + vtkPiece.setCellVar(type, currentCell, convV6ToV9Stress(average) ); } else { - vtkPiece.setCellVar(i, currentCell, average); + vtkPiece.setCellVar(type, currentCell, average); } currentCell += 1; } @@ -2400,11 +2293,7 @@ Shell7BaseXFEM :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT } - - #if 1 - - // Export of XFEM related quantities XfemManager *xFemMan = this->xMan; int nEnrIt = xFemMan->giveNumberOfEnrichmentItems(); @@ -2416,7 +2305,7 @@ Shell7BaseXFEM :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT vtkPiece.setNumberOfInternalXFEMVarsToExport(xFemMan->vtkExportFields.giveSize(), nEnrIt, numTotalNodes); for ( int field = 1; field <= xFemMan->vtkExportFields.giveSize(); field++ ) { XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields [ field - 1 ]; - + for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) { EnrichmentItem *ei = xFemMan->giveEnrichmentItem(enrItIndex); nodeNum = 1; @@ -2448,7 +2337,7 @@ Shell7BaseXFEM :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT } else if ( xfemstype == XFEMST_LevelSetGamma ) { valueArray.resize(1); //val = & valueArray; - ei->evalLevelSetTangInNode( valueArray.at(1), node->giveNumber(), node->giveNodeCoordinates() ); + ei->evalLevelSetTangInNode( valueArray.at(1), node->giveNumber(), node->giveCoordinates() ); } else if ( xfemstype == XFEMST_NodeEnrMarker ) { valueArray.resize(1); //val = & valueArray; @@ -2464,14 +2353,13 @@ Shell7BaseXFEM :: giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsT } } } -#endif - +#endif } -void -Shell7BaseXFEM :: giveFictiousNodeCoordsForExport(std::vector &nodes, int layer, int subCell) +std::vector +Shell7BaseXFEM :: giveFictiousNodeCoordsForExport(int layer, int subCell) { // compute fictious node coords @@ -2482,7 +2370,7 @@ Shell7BaseXFEM :: giveFictiousNodeCoordsForExport(std::vector &nodes //this->interpolationForExport.giveLocalNodeCoords(localNodeCoords); - nodes.resize(localNodeCoords.giveNumberOfColumns()); + std::vector nodes(localNodeCoords.giveNumberOfColumns()); for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){ FloatArray localCoords(3); localCoords.at(1) = nodeLocalXi1Coords.at(i); @@ -2491,34 +2379,34 @@ Shell7BaseXFEM :: giveFictiousNodeCoordsForExport(std::vector &nodes ///@todo Check this Jim, you overwrite "localCoords" the the code above is useless. localCoords.beColumnOf(localNodeCoords,i); - this->vtkEvalInitialGlobalCoordinateAt(localCoords, layer, nodes[i-1]); + nodes[i-1] = this->vtkEvalInitialGlobalCoordinateAt(localCoords, layer); } - + return nodes; } -void -Shell7BaseXFEM :: giveFictiousCZNodeCoordsForExport(std::vector &nodes, int layer, int subCell) +std::vector +Shell7BaseXFEM :: giveFictiousCZNodeCoordsForExport(int layer, int subCell) { - // compute fictious node coords FloatArray nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords; FloatMatrix localNodeCoords; // need to return local coordinates corresponding to the nodes of the sub triangles giveLocalCZNodeCoordsForExport(nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, subCell, localNodeCoords); - nodes.resize(localNodeCoords.giveNumberOfColumns()); + std::vector nodes(localNodeCoords.giveNumberOfColumns()); for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){ FloatArray localCoords(3); localCoords.beColumnOf(localNodeCoords,i); - this->vtkEvalInitialGlobalCZCoordinateAt(localCoords, layer, nodes[i-1]); + nodes[i-1] = this->vtkEvalInitialGlobalCZCoordinateAt(localCoords, layer); } - + return nodes; } -void -Shell7BaseXFEM :: giveFictiousUpdatedNodeCoordsForExport(std::vector &nodes, int layer, TimeStep *tStep, int subCell) + +std::vector +Shell7BaseXFEM :: giveFictiousUpdatedNodeCoordsForExport(int layer, TimeStep *tStep, int subCell) { // compute fictious node coords FloatArray nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords; @@ -2529,11 +2417,10 @@ Shell7BaseXFEM :: giveFictiousUpdatedNodeCoordsForExport(std::vector if ( subCell == 0) { this->interpolationForExport.giveLocalNodeCoords(localNodeCoords); // must get local z-coord in terms of the total thickness not layerwise - } else { giveLocalNodeCoordsForExport(nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, subCell, layer, localNodeCoords); } - nodes.resize(localNodeCoords.giveNumberOfColumns()); + std::vector nodes(localNodeCoords.giveNumberOfColumns()); for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){ FloatArray localCoords(3); localCoords.beColumnOf(localNodeCoords, i); @@ -2546,12 +2433,14 @@ Shell7BaseXFEM :: giveFictiousUpdatedNodeCoordsForExport(std::vector double deltaxi = localCoords.at(3) * this->layeredCS->giveLayerThickness(layer) / totalThickness; // distance from layer mid localCoords.at(3) = xiMid_i + deltaxi * scaleFactor; - this->vtkEvalUpdatedGlobalCoordinateAt(localCoords, layer, nodes[i-1], tStep); + nodes[i-1] = this->vtkEvalUpdatedGlobalCoordinateAt(localCoords, layer, tStep); } + return nodes; } -void -Shell7BaseXFEM :: giveFictiousUpdatedCZNodeCoordsForExport(std::vector &nodes, int interface, TimeStep *tStep, int subCell) + +std::vector +Shell7BaseXFEM :: giveFictiousUpdatedCZNodeCoordsForExport(int interface, TimeStep *tStep, int subCell) { // compute fictious node coords FloatArray nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords; @@ -2562,11 +2451,10 @@ Shell7BaseXFEM :: giveFictiousUpdatedCZNodeCoordsForExport(std::vectorinterpolationForCZExport.giveLocalNodeCoords(localNodeCoords); // must get local z-coord in terms of the total thickness not layerwise - } else { giveLocalCZNodeCoordsForExport(nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, subCell, localNodeCoords); } - nodes.resize(localNodeCoords.giveNumberOfColumns()); + std::vector nodes(localNodeCoords.giveNumberOfColumns()); for ( int i = 1; i <= localNodeCoords.giveNumberOfColumns(); i++ ){ FloatArray localCoords(3); localCoords.beColumnOf(localNodeCoords, i); @@ -2579,8 +2467,9 @@ Shell7BaseXFEM :: giveFictiousUpdatedCZNodeCoordsForExport(std::vectorlayeredCS->giveLayerThickness(interface) / totalThickness; // distance from layer mid localCoords.at(3) = xiMid_i + deltaxi * scaleFactor; - this->vtkEvalUpdatedGlobalCoordinateAt(localCoords, interface, nodes[i-1], tStep); + nodes[i-1] = this->vtkEvalUpdatedGlobalCoordinateAt(localCoords, interface, tStep); } + return nodes; } @@ -2602,7 +2491,6 @@ Shell7BaseXFEM :: mapXi3FromLocalToShell(FloatArray &answer, FloatArray &local, } - void Shell7BaseXFEM :: giveLocalNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, FloatArray &nodeLocalXi2Coords, FloatArray &nodeLocalXi3Coords, int subCell, int layer, FloatMatrix &localNodeCoords) { @@ -2611,23 +2499,19 @@ Shell7BaseXFEM :: giveLocalNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, F double z = 1.0*scale; // Triangle coordinates - FloatArray g1, g2, g3; //g1 = this->allTri[subCell-1].giveVertex(1); //g2 = this->allTri[subCell-1].giveVertex(2); //g3 = this->allTri[subCell-1].giveVertex(3); - g1 = this->crackSubdivisions[layer-1][subCell-1].giveVertex(1); - g2 = this->crackSubdivisions[layer-1][subCell-1].giveVertex(2); - g3 = this->crackSubdivisions[layer-1][subCell-1].giveVertex(3); + auto g1 = this->crackSubdivisions[layer-1][subCell-1].giveVertex(1); + auto g2 = this->crackSubdivisions[layer-1][subCell-1].giveVertex(2); + auto g3 = this->crackSubdivisions[layer-1][subCell-1].giveVertex(3); - FloatArray gs1(2), gs2(2), gs3(2); - gs1.zero(); gs2.zero(); gs3.zero(); // Move the triangle nodes slightly towards the center to avoid numerical problems - controlled by 'scale' double alpha1 = scale; double alpha2 = (1.0-alpha1)*0.5; double alpha3 = alpha2; - //g1.printYourself(); g2.printYourself(); g3.printYourself(); g1.resizeWithValues(2); g2.resizeWithValues(2); g3.resizeWithValues(2); - gs1 = alpha1*g1 + alpha2*g2 + alpha3*g3; - gs2 = alpha2*g1 + alpha1*g2 + alpha3*g3; - gs3 = alpha2*g1 + alpha3*g2 + alpha1*g3; + auto gs1 = alpha1*g1 + alpha2*g2 + alpha3*g3; + auto gs2 = alpha2*g1 + alpha1*g2 + alpha3*g3; + auto gs3 = alpha2*g1 + alpha3*g2 + alpha1*g3; // Local coordinates for the (scaled) triangle coordinates FloatArray loc1, loc2, loc3; @@ -2636,10 +2520,9 @@ Shell7BaseXFEM :: giveLocalNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, F this->computeLocalCoordinates(loc3, gs3); // Compute coordinates for the three mid nodes - FloatArray loc12, loc23, loc31; - loc12 = 0.5 * (loc1 + loc2); - loc23 = 0.5 * (loc2 + loc3); - loc31 = 0.5 * (loc3 + loc1); + auto loc12 = 0.5 * (loc1 + loc2); + auto loc23 = 0.5 * (loc2 + loc3); + auto loc31 = 0.5 * (loc3 + loc1); double a = loc1.at(1); double b = loc2.at(1); double c = loc3.at(1); @@ -2657,11 +2540,10 @@ Shell7BaseXFEM :: giveLocalNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, F nodeLocalXi2Coords = { a, b, c, a, b, c, d, e, f, d, e, f, a, b, c }; nodeLocalXi3Coords = { -z, -z, -z, z, z, z, -z, -z, -z, z, z, z, 0., 0., 0. }; - + FloatMatrix localNodeCoordsT; localNodeCoordsT = {nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords}; localNodeCoords.beTranspositionOf(localNodeCoordsT); - } @@ -2673,17 +2555,15 @@ Shell7BaseXFEM :: giveLocalCZNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, //double z = 1.0*scale; // Triangle coordinates - FloatArray g1, g2, g3; - g1 = this->allTri[subCell-1].giveVertex(1); - g2 = this->allTri[subCell-1].giveVertex(2); - g3 = this->allTri[subCell-1].giveVertex(3); + auto g1 = this->allTri[subCell-1].giveVertex(1); + auto g2 = this->allTri[subCell-1].giveVertex(2); + auto g3 = this->allTri[subCell-1].giveVertex(3); - FloatArray gs1, gs2, gs3; // Move the triangle nodes slightly towards the center to avoid numerical problems - controlled by 'scale' double alpha1 = scale; double alpha2 = (1.0-alpha1)*0.5; double alpha3 = alpha2; - gs1 = alpha1*g1 + alpha2*g2 + alpha3*g3; - gs2 = alpha2*g1 + alpha1*g2 + alpha3*g3; - gs3 = alpha2*g1 + alpha3*g2 + alpha1*g3; + auto gs1 = alpha1*g1 + alpha2*g2 + alpha3*g3; + auto gs2 = alpha2*g1 + alpha1*g2 + alpha3*g3; + auto gs3 = alpha2*g1 + alpha3*g2 + alpha1*g3; // Local coordinates for the (scaled) triangle coordinates FloatArray loc1, loc2, loc3; @@ -2692,10 +2572,9 @@ Shell7BaseXFEM :: giveLocalCZNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, this->computeLocalCoordinates(loc3, gs3); // Compute coordinates for the three mid nodes - FloatArray loc12, loc23, loc31; - loc12 = 0.5 * (loc1 + loc2); - loc23 = 0.5 * (loc2 + loc3); - loc31 = 0.5 * (loc3 + loc1); + auto loc12 = 0.5 * (loc1 + loc2); + auto loc23 = 0.5 * (loc2 + loc3); + auto loc31 = 0.5 * (loc3 + loc1); double a = loc1.at(1); double b = loc2.at(1); double c = loc3.at(1); @@ -2713,11 +2592,10 @@ Shell7BaseXFEM :: giveLocalCZNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, nodeLocalXi2Coords = { a, b, c, d, e, f }; nodeLocalXi3Coords = { 0., 0., 0., 0., 0., 0. }; - + FloatMatrix localNodeCoordsT; localNodeCoordsT = {nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords}; localNodeCoords.beTranspositionOf(localNodeCoordsT); - } void @@ -2728,10 +2606,10 @@ Shell7BaseXFEM :: giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToEx if ( this->allTri.size() ) { numSubCells = (int)this->allTri.size(); } - + int numInterfaces = this->layeredCS->giveNumberOfLayers()-1; int numCells = numInterfaces * numSubCells; - + int numCellNodes = 6; // quadratic triangle int numTotalNodes = numCellNodes*numCells; @@ -2739,7 +2617,6 @@ Shell7BaseXFEM :: giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToEx vtkPiece.setNumberOfCells(numCells); vtkPiece.setNumberOfNodes(numTotalNodes); - std::vector nodeCoords; int val = 1; int offset = 0; int currentCell = 1; @@ -2748,16 +2625,14 @@ Shell7BaseXFEM :: giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToEx // Compute fictious node coords int nodeNum = 1; for ( int layer = 1; layer <= numInterfaces; layer++ ) { - + for ( int subCell = 1; subCell <= numSubCells; subCell++ ) { // Node coordinates - if ( numSubCells == 1 ) { - Shell7Base :: giveFictiousCZNodeCoordsForExport(nodeCoords, layer); - } else { - this->giveFictiousCZNodeCoordsForExport(nodeCoords, layer, subCell); - } - + auto nodeCoords = numSubCells == 1 ? + Shell7Base :: giveFictiousCZNodeCoordsForExport(layer) : + this->giveFictiousCZNodeCoordsForExport(layer, subCell); + for ( int node = 1; node <= numCellNodes; node++ ) { vtkPiece.setNodeCoords(nodeNum, nodeCoords[node-1] ); nodeNum += 1; @@ -2768,7 +2643,7 @@ Shell7BaseXFEM :: giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToEx nodes.at(i) = val++; } vtkPiece.setConnectivity(currentCell, nodes); - + // Offset offset += numCellNodes; vtkPiece.setOffset(currentCell, offset); @@ -2780,41 +2655,34 @@ Shell7BaseXFEM :: giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToEx } } - - - // Export nodal variables from primary fields - vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport.giveSize(), numTotalNodes); + vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport, numTotalNodes); - std::vector updatedNodeCoords; - FloatArray u(3); std::vector values; for ( int fieldNum = 1; fieldNum <= primaryVarsToExport.giveSize(); fieldNum++ ) { UnknownType type = ( UnknownType ) primaryVarsToExport.at(fieldNum); nodeNum = 1; currentCell = 1; for ( int layer = 1; layer <= numInterfaces; layer++ ) { - for ( int subCell = 1; subCell <= numSubCells; subCell++ ) { if ( type == DisplacementVector ) { // compute displacement as u = x - X - if ( numSubCells == 1 ) { - Shell7Base :: giveFictiousCZNodeCoordsForExport(nodeCoords, layer); - this->giveFictiousUpdatedCZNodeCoordsForExport(updatedNodeCoords, layer, tStep, 0); - } else { - this->giveFictiousCZNodeCoordsForExport(nodeCoords, layer, subCell); - this->giveFictiousUpdatedCZNodeCoordsForExport(updatedNodeCoords, layer, tStep, subCell); - } + auto nodeCoords = numSubCells == 1 ? + Shell7Base :: giveFictiousCZNodeCoordsForExport(layer) : + this->giveFictiousCZNodeCoordsForExport(layer, subCell); + + auto updatedNodeCoords = this->giveFictiousUpdatedCZNodeCoordsForExport(layer, tStep, numSubCells == 1 ? 0 : subCell); + for ( int j = 1; j <= numCellNodes; j++ ) { - u.beDifferenceOf(updatedNodeCoords[j-1], nodeCoords[j-1]); - vtkPiece.setPrimaryVarInNode(fieldNum, nodeNum, u); + auto u = updatedNodeCoords[j-1] - nodeCoords[j-1]; + vtkPiece.setPrimaryVarInNode(type, nodeNum, u); nodeNum += 1; } } else { NodalRecoveryMI_recoverValues(values, layer, ( InternalStateType ) 1, tStep); // does not work well - fix for ( int j = 1; j <= numCellNodes; j++ ) { - vtkPiece.setPrimaryVarInNode(fieldNum, nodeNum, values[j-1]); + vtkPiece.setPrimaryVarInNode(type, nodeNum, values[j-1]); nodeNum += 1; } } @@ -2824,33 +2692,31 @@ Shell7BaseXFEM :: giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToEx } } - - // Export nodal variables from internal fields - - vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport.giveSize(), numTotalNodes ); + + vtkPiece.setNumberOfInternalVarsToExport( internalVarsToExport, numTotalNodes ); for ( int fieldNum = 1; fieldNum <= internalVarsToExport.giveSize(); fieldNum++ ) { InternalStateType type = ( InternalStateType ) internalVarsToExport.at(fieldNum); nodeNum = 1; - + //int currentCell = 1; for ( int layer = 1; layer <= numInterfaces; layer++ ) { for ( int subCell = 1; subCell <= numSubCells; subCell++ ) { this->recoverValuesFromCZIP(values, layer, type, tStep); - + for ( int j = 1; j <= numCellNodes; j++ ) { - vtkPiece.setInternalVarInNode( fieldNum, nodeNum, values[j-1] ); + vtkPiece.setInternalVarInNode( type, nodeNum, values[j-1] ); //ZZNodalRecoveryMI_recoverValues(el.nodeVars[fieldNum], layer, type, tStep); nodeNum += 1; - } + } } - } + } } // Export cell variables FloatArray average; - vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport.giveSize(), numCells); + vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport, numCells); for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) { InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i); InternalStateValueType valueType = giveInternalStateValueType(type); @@ -2864,9 +2730,9 @@ Shell7BaseXFEM :: giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToEx VTKXMLExportModule::computeIPAverage(average, iRuleL.get(), this, type, tStep); } if ( valueType == ISVT_TENSOR_S3 ) { - vtkPiece.setCellVar(i, currentCell, convV6ToV9Stress(average) ); + vtkPiece.setCellVar(type, currentCell, convV6ToV9Stress(average) ); } else { - vtkPiece.setCellVar(i, currentCell, average); + vtkPiece.setCellVar(type, currentCell, average); } currentCell += 1; } @@ -2875,8 +2741,6 @@ Shell7BaseXFEM :: giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToEx } - - #if 0 @@ -2891,13 +2755,13 @@ Shell7BaseXFEM :: giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToEx vtkPiece.setNumberOfInternalXFEMVarsToExport(xFemMan->vtkExportFields.giveSize(), nEnrIt, numTotalNodes); for ( int field = 1; field <= xFemMan->vtkExportFields.giveSize(); field++ ) { XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields [ field - 1 ]; - + for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) { EnrichmentItem *ei = xFemMan->giveEnrichmentItem(enrItIndex); int nodeNum = 1; for ( int layer = 1; layer <= numInterfaces; layer++ ) { FloatMatrix localNodeCoords; - + for ( int subCell = 1; subCell <= numSubCells; subCell++ ) { FloatArray nodeLocalXi1Coords, nodeLocalXi2Coords, nodeLocalXi3Coords, nodeLocalXi3CoordsMapped; if ( numSubCells == 1) { @@ -2938,9 +2802,7 @@ Shell7BaseXFEM :: giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToEx } } } -#endif - - +#endif } void @@ -2954,7 +2816,7 @@ Shell7BaseXFEM :: recoverValuesFromCZIP(std::vector &recoveredValues this->interpolationForCZExport.giveLocalNodeCoords(localNodeCoords); int numNodes = localNodeCoords.giveNumberOfColumns(); recoveredValues.resize(numNodes); - + std :: unique_ptr< IntegrationRule > &iRule = this->czIntegrationRulesArray [ interfce - 1 ]; // Find closest ip to the nodes @@ -2966,7 +2828,7 @@ Shell7BaseXFEM :: recoverValuesFromCZIP(std::vector &recoveredValues double distOld = 3.0; // should not be larger for ( int j = 0; j < iRule->giveNumberOfIntegrationPoints(); j++ ) { IntegrationPoint *ip = iRule->getIntegrationPoint(j); - double dist = nodeCoords.distance(ip->giveNaturalCoordinates()); + double dist = distance(nodeCoords, ip->giveNaturalCoordinates()); if ( dist < distOld ) { closestIPArray.at(i) = j; distOld = dist; @@ -2991,7 +2853,6 @@ Shell7BaseXFEM :: recoverValuesFromCZIP(std::vector &recoveredValues } else if ( ipValues.giveSize() == 0 ) { recoveredValues[i-1].resize(giveInternalStateTypeSize(valueType)); recoveredValues[i-1].zero(); - } else if ( valueType == ISVT_TENSOR_S3 ) { recoveredValues[i-1] = convV6ToV9Stress(ipValues); @@ -2999,11 +2860,9 @@ Shell7BaseXFEM :: recoverValuesFromCZIP(std::vector &recoveredValues recoveredValues[i-1] = ipValues; } } - } - void Shell7BaseXFEM :: computeTripleProduct(FloatMatrix &answer, const FloatMatrix &a, const FloatMatrix &b, const FloatMatrix &c) { @@ -3018,15 +2877,15 @@ void Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) { // Recover shear stresses at ip by numerical integration of the momentum balance through the thickness (overloaded from shell7base) - + int numberOfLayers = this->layeredCS->giveNumberOfLayers(); - + // Check if delamination/CZ is active. Then use hasCohesiveZone to decide whether the cohforces need to be calculated (otherwise traction BC need to be found) // Find (possible) layer/interface BC, starting from bottom // IntArray layerHasBC(numberOfLayers+1); layerHasBC.zero(); IntArray delaminationInterface; delaminationInterface.clear(); // interface (starting from 1) which contains delamination IntArray interfaceEI(numberOfLayers-1); - + bool hasDelamination = false; int numEI = this->xMan->giveNumberOfEnrichmentItems(); for ( int iEI = 1; iEI <= numEI; iEI++ ) { @@ -3043,18 +2902,18 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) } } delaminationInterface.sort(); - + if ( hasDelamination ) { - + int numInPlaneIP = 6; ///TODO generalise this int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer(); if (numThicknessIP < 2) { // Polynomial fit involves linear z-component at the moment OOFEM_ERROR("To few thickness IP per layer to do polynomial fit"); - } - + } + int numDel = delaminationInterface.giveSize(); - + // Find top and bottom BC NB: assumes constant over element surface. // traction BC added to vector of BC. std::vector tractionBC; tractionBC.resize(numDel+2); @@ -3062,7 +2921,7 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) tractionBC[0].resize(3,numInPlaneIP); giveTractionBC(tractionBC[numDel+1],tractionBC[0], tStep); //if (this->giveGlobalNumber() == 8 || this->giveGlobalNumber() == 50) {tractionBC[numDel+1].printYourself("tractionTop"); tractionBC[0].printYourself("tractionBtm");} - + #if 0 FloatArray tractionTop, tractionBtm; giveTractionBC(tractionTop,tractionBtm, tStep); @@ -3077,15 +2936,15 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) #endif // Find delamination traction BC for (int iDel = 1 ; iDel <= numDel ; iDel++) { - + tractionBC[iDel].resize(3,numInPlaneIP); - + int interfaceNum = delaminationInterface.at(iDel); EnrichmentItem *ei = this->xMan->giveEnrichmentItem(interfaceEI.at(interfaceNum)); Delamination *dei = dynamic_cast< Delamination * >( ei ); - + if ( this->hasCohesiveZone( interfaceNum ) ) { -#if 1 +#if 1 // CZ traction std :: unique_ptr< IntegrationRule > &iRuleI = this->czIntegrationRulesArray [ interfaceNum - 1 ]; if (czIntegrationRulesArray [ interfaceNum - 1 ]->giveNumberOfIntegrationPoints() != numInPlaneIP ) { @@ -3095,7 +2954,7 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) if (intMat == 0) { OOFEM_ERROR("NULL pointer to material, shell element %i",this->giveGlobalNumber()); } - + FloatArray lCoords(3), nCov, CZPKtraction(3); FloatMatrix Q; int iIGP = 1; @@ -3104,11 +2963,11 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) lCoords.at(1) = gp->giveNaturalCoordinate(1); lCoords.at(2) = gp->giveNaturalCoordinate(2); lCoords.at(3) = xi; - + //FloatArray GPcoords = gp->giveGlobalCoordinates(); //if (this->giveGlobalNumber() == 126) { GPcoords.printYourself("interface GPs"); } // this->evalInitialCovarNormalAt(nCov, lCoords); // intial coords - + // Find PK-traction in current coords. FloatArray solVecC; this->giveUpdatedSolutionVector(solVecC, tStep); @@ -3116,14 +2975,14 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) this->computeEnrichedBmatrixAt(lCoords, B, NULL); // NULL => Shell7base :: computeBmatrixAt, otherwise include dei FloatArray genEpsC; genEpsC.beProductOf(B, solVecC); - this->evalCovarNormalAt(nCov, lCoords, genEpsC, tStep); // Denna verkar ta hänsyn till hoppet, men hur ser jag till att det är normalen ovanför delamineringen? + nCov = this->evalCovarNormalAt(lCoords, genEpsC, tStep); // Denna verkar ta hänsyn till hoppet, men hur ser jag till att det är normalen ovanför delamineringen? Q.beLocalCoordSys(nCov); - + #if 0 // Compute 1PK traction from jump vector FloatArray jump; this->computeInterfaceJumpAt(dei->giveDelamInterfaceNum(), lCoords, tStep, jump); // -> numerical tol. issue -> normal jump = 1e-10 - + genEpsC.beProductOf(B, solVecC); FloatMatrix F; this->computeFAt(lCoords, F, genEpsC, tStep); @@ -3147,7 +3006,7 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) CZPKtraction.rotatedWith(Q,'t'); // transform back to global coord system //if (this->giveGlobalNumber() == 9 ) { CZPKtraction.printYourself("CZPKtraction");} - + // Set BC stresses tractionBC[iDel].at(1,iIGP) = CZPKtraction.at(1); tractionBC[iDel].at(2,iIGP) = CZPKtraction.at(2); @@ -3161,13 +3020,13 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) } //if (this->giveGlobalNumber() == 50) {tractionBC[iDel].printYourself("tractionDel");} } - + FloatMatrix SmatOld(3,numInPlaneIP); // 3 stress components (S_xz, S_yz, S_zz) * num of in plane ip double totalThickness = this->layeredCS->computeIntegralThick(); double zeroThicknessLevel = - 0.5 * totalThickness; // assumes midplane is the geometric midplane of layered structure. FloatMatrix dSmat(3,numInPlaneIP); // 3 stress components (S_xz, S_yz, S_zz) * num of in plane ip FloatMatrix dSmatLayerIP(3,numInPlaneIP*numThicknessIP); // 3 stress components (S_xz, S_yz, S_zz) * num of wedge ip - + int layerOld = 0; int iInt = 0; delaminationInterface.followedBy(numberOfLayers); // creates an array of the layer index of the top layer in a delamination (NB: index = numberOfLayers will allways be the last) @@ -3178,20 +3037,19 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) std::vector dSmat; dSmat.resize(numDelLayers); //recovered stress values at delamination top std::vector dSmatIPupd; dSmatIPupd.resize(numDelLayers); //recovered stress values in wedge IPs adjusted for top and btm traction BC. std::vector dSmatupd; dSmatupd.resize(numDelLayers); //recovered stress values at delamination top, adjusted for top and btm traction BC - + // Recovered stresses in delaminated layers double dz = 0.0; for ( int delLayer = 1 ; delLayer <= numDelLayers; delLayer++ ) { - this->giveLayerContributionToSR(dSmat[delLayer-1], dSmatIP[delLayer-1], delLayer+layerOld, zeroThicknessLevel + dz, tStep); SmatOld.add(dSmat[delLayer-1]); // Integrated stress over laminate dz += this->layeredCS->giveLayerThickness(delLayer+layerOld); - + } - + // Adjust recovered stresses to traction BC (divide integration error 50/50 at top and btm of delamination) this->fitRecoveredStress2BC(dSmatIPupd, dSmatupd, dSmat, dSmatIP, SmatOld, tractionBC[iInt], tractionBC[iInt+1], zeroThicknessLevel, {0.0,0.0,1.0}, layerOld+1, topLayer); - + for ( int layer = 1 ; layer <= numDelLayers; layer++ ) { //if (this->giveGlobalNumber() == 48 ) { dSmatIPupd[layer-1].printYourself(); } this->updateLayerTransvStressesSR( dSmatIPupd[layer-1], layer+layerOld); @@ -3202,29 +3060,29 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) } #if 0 for ( int layer = 1; layer <= numberOfLayers; layer++ ) { - + // Bör det vara this här istället för Shell7Base? // Shell7Base :: giveLayerContributionToSR(dSmat, dSmatLayerIP, layer, zeroThicknessLevel, tStep); // NB: performed in global system this->giveLayerContributionToSR(dSmat, dSmatLayerIP, layer, zeroThicknessLevel, tStep); // NB: performed in global system - + // Shell7Base :: updateLayerStressesSR(dSmatLayerIP, SmatOld, layer); this->updateLayerTransvStressesSR(dSmatLayerIP, SmatOld, layer); //dSmatLayerIP.printYourself(); //printf("enr func in dofman %d = %e \n", layer, layer); - + SmatOld.add(dSmat); if (this->giveGlobalNumber() == 126) { SmatOld.printYourself(); } zeroThicknessLevel += this->layeredCS->giveLayerThickness(layer); ///TODO add jump? - + // Add traction from delamination CZ. NB: assumes same number order of GPs in interface and shell elements if ( layerHasBC.at(layer+1) ) { - + EnrichmentItem *ei = this->xMan->giveEnrichmentItem(layerHasBC.at(layer+1)); Delamination *dei = dynamic_cast< Delamination * >( ei ); int interfaceNum = dei->giveDelamInterfaceNum(); - + if ( this->hasCohesiveZone( interfaceNum ) ) { #if 1 // CZ traction @@ -3232,7 +3090,7 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) if (iRuleI->giveNumberOfIntegrationPoints() != numInPlaneIP ) { OOFEM_ERROR("Interface IPs doesn't match the element IPs"); } - + FloatArray lCoords(3), nCov, CZPKtraction(3); CZPKtraction.zero(); FloatMatrix Q; @@ -3249,7 +3107,7 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) } #endif // this->evalInitialCovarNormalAt(nCov, lCoords); // intial coords - + // Find PK-traction in current coords. FloatArray solVecC; this->giveUpdatedSolutionVector(solVecC, tStep); @@ -3259,12 +3117,12 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) genEpsC.beProductOf(B, solVecC); this->evalCovarNormalAt(nCov, lCoords, genEpsC, tStep); // Denna verkar ta hänsyn till hoppet, men hur ser jag till att det är normalen ovanför delamineringen? Q.beLocalCoordSys(nCov); - + StructuralInterfaceMaterialStatus* intMatStatus = static_cast < StructuralInterfaceMaterialStatus* > ( gp->giveMaterialStatus() ); if (intMatStatus == 0) { OOFEM_ERROR("NULL pointer to material status"); } - + CZPKtraction = intMatStatus->giveFirstPKTraction(); // 3 components in local coords CZPKtraction.rotatedWith(Q,'t'); // transform back to global coord system @@ -3292,7 +3150,7 @@ Shell7BaseXFEM :: recoverShearStress(TimeStep *tStep) } } #endif - + } else { Shell7Base :: recoverShearStress(tStep); } @@ -3307,7 +3165,7 @@ Shell7BaseXFEM :: giveFailedInterfaceNumber(IntArray &failedInterfaces, FloatArr // Assumes three stress components in initiationStress: (Sxz, Syz, Szz) // Returns any new interface that needs to be enriched. ///TODO: add general failure criterion. - + failedInterfaces.clear(); std :: vector < FloatMatrix > transverseInterfaceStresses; if (recoverStresses) { @@ -3322,22 +3180,22 @@ Shell7BaseXFEM :: giveFailedInterfaceNumber(IntArray &failedInterfaces, FloatArr FloatArray interfaceXiCoords; this->giveLayeredCS()->giveInterfaceXiCoords(interfaceXiCoords); FloatMatrix failurestresses(2,this->layeredCS->giveNumberOfLayers()); - + for ( int iInterface = 1 ; iInterface < this->layeredCS->giveNumberOfLayers() ; iInterface++ ) { - + bool initiateElt = false; int interfaceMatNumber(this->giveLayeredCS()->giveInterfaceMaterialNum(iInterface)); - + if (interfaceMatNumber && !this->DelaminatedInterfaceList.findSorted(iInterface)) { - + std :: unique_ptr< IntegrationRule > &iRuleI = this->czIntegrationRulesArray [ iInterface - 1 ]; - + IntArray failedSC; StructuralInterfaceMaterial *intMat = dynamic_cast < StructuralInterfaceMaterial * > (this->layeredCS->giveInterfaceMaterial(iInterface) ); if (intMat == 0) { OOFEM_ERROR("NULL pointer to material, shell %i interface %i",this->giveGlobalNumber(),iInterface); } - + FloatArray sigF = {1,1,1}; FloatArray temp = intMat->giveInterfaceStrength(); if (temp.giveSize() == 1 && temp.at(1) > 0) { @@ -3351,42 +3209,42 @@ Shell7BaseXFEM :: giveFailedInterfaceNumber(IntArray &failedInterfaces, FloatArr } else { OOFEM_ERROR( "Intitiation stress for delaminations not found or incorrect on CZ-material" ); } - + //if (this->giveGlobalNumber() == 9) {transverseInterfaceStresses[iInterface-1].printYourself("Interface stresses elt 9"); initiationStress.printYourself("initiationStress");} - + for ( int iGP = 1 ; iGP <= transverseInterfaceStresses[iInterface-1].giveNumberOfColumns() ; iGP++ ) { if ( transverseInterfaceStresses[iInterface-1].giveNumberOfRows() != numSC ) { OOFEM_ERROR( "Wrong number of stress components" ); } - + // Collect interface stresses FloatArray interfaceStresses; interfaceStresses.beColumnOf(transverseInterfaceStresses[iInterface-1],iGP); // global coords - + //Rotate to element coord. FloatArray lCoords; lCoords.resize(3); GaussPoint *gp = iRuleI->getIntegrationPoint(iGP-1); lCoords.at(1) = gp->giveNaturalCoordinate(1); lCoords.at(2) = gp->giveNaturalCoordinate(2); lCoords.at(3) = interfaceXiCoords.at(iInterface); - + FloatArray solVecC, nCov; this->giveUpdatedSolutionVector(solVecC, tStep); FloatMatrix Q,B; this->computeEnrichedBmatrixAt(lCoords, B, NULL); // NULL => Shell7base :: computeBmatrixAt, otherwise include dei FloatArray genEpsC; genEpsC.beProductOf(B, solVecC); - this->evalCovarNormalAt(nCov, lCoords, genEpsC, tStep); + nCov = this->evalCovarNormalAt(lCoords, genEpsC, tStep); Q.beLocalCoordSys(nCov); - + //if (this->giveGlobalNumber() == 61) {interfaceStresses.printYourself("interfaceStresses global"); lCoords.printYourself("lCoords"); } - + interfaceStresses.rotatedWith(Q,'n'); // local coords double S1(interfaceStresses.at(1)); //Shear x double S2(interfaceStresses.at(2)); //Shear y double N(interfaceStresses.at(3)); //normal //if (this->giveGlobalNumber() == 61) {Q.printYourself("Q"); interfaceStresses.printYourself("interfaceStresses local");} - + // polynom law double NM = 0.5*(N + fabs(N)); double failCrit = NM*NM/(sigF.at(3)*sigF.at(3)) + (S1*S1 + S2*S2)/(sigF.at(1)*sigF.at(1)); @@ -3395,7 +3253,7 @@ Shell7BaseXFEM :: giveFailedInterfaceNumber(IntArray &failedInterfaces, FloatArr failurestresses.at(1,iInterface) = NM; failurestresses.at(2,iInterface) = sqrt(S1*S1 + S2*S2); } - + // Max stress criterion // for ( int iSC = 1 ; iSC <= numSC ; iSC++ ) { // if ( transverseInterfaceStresses[iInterface-1].at(iSC,iGP) > sigF.at(iSC) || (-transverseInterfaceStresses[iInterface-1].at(iSC,iGP)) > sigF.at(iSC)) { @@ -3440,15 +3298,15 @@ Shell7BaseXFEM::giveAverageTransverseInterfaceStress(std::vector< FloatMatrix >& transverseStress.resize(numberOfLayers-1); int numThicknessIP = this->layeredCS->giveNumIntegrationPointsInLayer(); int numInPlaneIP = 6; ///TODO generalise this; - + for ( int layer = 1; layer <= numberOfLayers; layer++ ) { std :: unique_ptr< IntegrationRule > &iRule = this->integrationRulesArray[layer-1]; if (layer < numberOfLayers) { transverseStress[layer-1].resize(3,numInPlaneIP); } - + for ( int j = 0; j < numInPlaneIP; j++ ) { - + // thickness GPs for ( int i = 0; i < numThicknessIP; i++ ) { @@ -3457,7 +3315,7 @@ Shell7BaseXFEM::giveAverageTransverseInterfaceStress(std::vector< FloatMatrix >& // Collect IP-value FloatArray tempIPvalues; this->giveIPValue(tempIPvalues, ip, IST_StressTensor, tStep); - + for ( int iInt = layer-1 ; iInt <= layer ; iInt++ ) { if ( iInt > 0 && iInt < numberOfLayers ) { transverseStress[iInt-1].at(1,j+1) += (0.5/numThicknessIP)*tempIPvalues.at(5); @@ -3476,12 +3334,12 @@ Shell7BaseXFEM :: giveRecoveredTransverseInterfaceStress(std::vectorlayeredCS->giveNumberOfLayers(); - + IntArray delaminationInterface; delaminationInterface.clear(); // interface (starting from 1) which contains delamination IntArray interfaceEI(numberOfLayers-1); - + bool hasDelamination = false; int numEI = this->xMan->giveNumberOfEnrichmentItems(); for ( int iEI = 1; iEI <= numEI; iEI++ ) { @@ -3497,35 +3355,35 @@ Shell7BaseXFEM :: giveRecoveredTransverseInterfaceStress(std::vectorlayeredCS->giveNumIntegrationPointsInLayer(); if (numThicknessIP < 2) { // Polynomial fit involves linear z-component at the moment OOFEM_ERROR("To few thickness IP per layer to do polynomial fit"); - } - + } + int numDel = delaminationInterface.giveSize(); - + // Find top and bottom BC NB: assumes constant over element surface. // traction BC added to vector of BC. std::vector tractionBC; tractionBC.resize(numDel+2); tractionBC[numDel+1].resize(3,numInPlaneIP); tractionBC[0].resize(3,numInPlaneIP); giveTractionBC(tractionBC[numDel+1],tractionBC[0], tStep); - + // Find delamination traction BC for (int iDel = 1 ; iDel <= numDel ; iDel++) { - + tractionBC[iDel].resize(3,numInPlaneIP); - + int interfaceNum = delaminationInterface.at(iDel); EnrichmentItem *ei = this->xMan->giveEnrichmentItem(interfaceEI.at(interfaceNum)); Delamination *dei = dynamic_cast< Delamination * >( ei ); - + if ( this->hasCohesiveZone( interfaceNum ) ) { // CZ traction std :: unique_ptr< IntegrationRule > &iRuleI = this->czIntegrationRulesArray [ interfaceNum - 1 ]; @@ -3534,17 +3392,17 @@ Shell7BaseXFEM :: giveRecoveredTransverseInterfaceStress(std::vector (this->layeredCS->giveInterfaceMaterial(interfaceNum) ); - + FloatArray lCoords(3), nCov, CZPKtraction(3); CZPKtraction.zero(); FloatMatrix Q; int iIGP = 1; - for ( GaussPoint *gp : *iRuleI ) { + for ( auto &gp : *iRuleI ) { double xi = dei->giveDelamXiCoord(); lCoords.at(1) = gp->giveNaturalCoordinate(1); lCoords.at(2) = gp->giveNaturalCoordinate(2); lCoords.at(3) = xi; - + // Find PK-traction in current coords. FloatArray solVecC; this->giveUpdatedSolutionVector(solVecC, tStep); @@ -3552,14 +3410,14 @@ Shell7BaseXFEM :: giveRecoveredTransverseInterfaceStress(std::vectorcomputeEnrichedBmatrixAt(lCoords, B, NULL); // NULL => Shell7base :: computeBmatrixAt, otherwise include dei FloatArray genEpsC; genEpsC.beProductOf(B, solVecC); - this->evalCovarNormalAt(nCov, lCoords, genEpsC, tStep); // Denna verkar ta hänsyn till hoppet, men hur ser jag till att det är normalen ovanför delamineringen? + nCov = this->evalCovarNormalAt(lCoords, genEpsC, tStep); // Denna verkar ta hänsyn till hoppet, men hur ser jag till att det är normalen ovanför delamineringen? Q.beLocalCoordSys(nCov); - + #if 0 // Compute 1PK traction from jump vector FloatArray jump; this->computeInterfaceJumpAt(dei->giveDelamInterfaceNum(), lCoords, tStep, jump); // -> numerical tol. issue -> normal jump = 1e-10 - + genEpsC.beProductOf(B, solVecC); FloatMatrix F; this->computeFAt(lCoords, F, genEpsC, tStep); @@ -3580,28 +3438,27 @@ Shell7BaseXFEM :: giveRecoveredTransverseInterfaceStress(std::vectorgiveTempFirstPKTraction(); // 3 components in local coords #endif - + CZPKtraction.rotatedWith(Q,'t'); // transform back to global coord system - + // Set BC stresses tractionBC[iDel].at(1,iIGP) = CZPKtraction.at(1); tractionBC[iDel].at(2,iIGP) = CZPKtraction.at(2); tractionBC[iDel].at(3,iIGP) = CZPKtraction.at(3); iIGP++; } - } else { // Delamination zero traction tractionBC[iDel].zero(); } } - + FloatMatrix SmatOld(3,numInPlaneIP); // 3 stress components (S_xz, S_yz, S_zz) * num of in plane ip double totalThickness = this->layeredCS->computeIntegralThick(); double zeroThicknessLevel = - 0.5 * totalThickness; // assumes midplane is the geometric midplane of layered structure. FloatMatrix dSmat(3,numInPlaneIP); // 3 stress components (S_xz, S_yz, S_zz) * num of in plane ip FloatMatrix dSmatLayerIP(3,numInPlaneIP*numThicknessIP); // 3 stress components (S_xz, S_yz, S_zz) * num of wedge ip - + int layerOld = 0; int iInt = 0; delaminationInterface.followedBy(numberOfLayers); // creates an array of the layer index of the top layer in a delamination (NB: index = numberOfLayers will allways be the last) @@ -3612,36 +3469,33 @@ Shell7BaseXFEM :: giveRecoveredTransverseInterfaceStress(std::vector dSmat; dSmat.resize(numDelLayers); //recovered stress values at delamination top std::vector dSmatIPupd; dSmatIPupd.resize(numDelLayers); //recovered stress values in wedge IPs adjusted for top and btm traction BC. std::vector dSmatupd; dSmatupd.resize(numDelLayers); //recovered stress values at delamination top, adjusted for top and btm traction BC - + // Recovered stresses in delaminated layers double dz = 0.0; for ( int delLayer = 1 ; delLayer <= numDelLayers; delLayer++ ) { - this->giveLayerContributionToSR(dSmat[delLayer-1], dSmatIP[delLayer-1], delLayer+layerOld, zeroThicknessLevel + dz, tStep); SmatOld.add(dSmat[delLayer-1]); // Integrated stress over laminate dz += this->layeredCS->giveLayerThickness(delLayer+layerOld); - } - + // Adjust recovered stresses to traction BC (divide integration error 50/50 at top and btm of delamination) - + this->fitRecoveredStress2BC(dSmatIPupd, dSmatupd, dSmat, dSmatIP, SmatOld, tractionBC[iInt], tractionBC[iInt+1], zeroThicknessLevel, {0.0,0.0,1.0}, layerOld+1, topLayer); - + for ( int delLayer = 1 ; delLayer <= numDelLayers; delLayer++ ) { if ( (delLayer + layerOld) < numberOfLayers ) { transverseStress[delLayer+layerOld-1] = dSmatupd[delLayer-1]; } } - + zeroThicknessLevel += dz; layerOld = topLayer; iInt++; } - + } else { Shell7Base :: giveRecoveredTransverseInterfaceStress(transverseStress, tStep); } - } diff --git a/src/sm/Elements/Shells/shell7basexfem.h b/src/sm/Elements/Shells/shell7basexfem.h index dcf72bd71..7e37f6aca 100644 --- a/src/sm/Elements/Shells/shell7basexfem.h +++ b/src/sm/Elements/Shells/shell7basexfem.h @@ -35,8 +35,8 @@ #ifndef Shell7BaseXFEM_h #define Shell7BaseXFEM_h -#include "../sm/Elements/Shells/shell7base.h" -#include "../sm/xfem/enrichmentitems/delamination.h" +#include "sm/Elements/Shells/shell7base.h" +#include "sm/xfem/enrichmentitems/delamination.h" #include "xfem/xfemelementinterface.h" #include "fei3dtrquad.h" @@ -63,45 +63,45 @@ class Shell7BaseXFEM : public Shell7Base, public XfemElementInterface { protected: XfemManager *xMan; - virtual void updateYourself(TimeStep *tStep); - virtual void postInitialize(); + void updateYourself(TimeStep *tStep) override; + void postInitialize() override; void computeOrderingArray(IntArray &orderingArray, IntArray &activeDofsArray, EnrichmentItem *ei); - virtual void evalCovarBaseVectorsAt(const FloatArray &lCoords, FloatMatrix &gcon, FloatArray &solVec, TimeStep *tStep); + FloatMatrixF<3,3> evalCovarBaseVectorsAt(const FloatArrayF<3> &lCoords, FloatArray &solVec, TimeStep *tStep) override; void discGiveInitialSolutionVector(FloatArray &answer, IntArray &eiDofIdArray); // should be replaced with general function void computeDiscGeneralizedStrainVector(FloatArray &dGenEps, const FloatArray &lCoords, EnrichmentItem *ei, TimeStep *tStep); void computeDiscSolutionVector(IntArray &dofIdArray , TimeStep *tStep, FloatArray &solVecD); - void computeInterfaceJumpAt(int interf, FloatArray &lCoords, TimeStep *tStep, FloatArray &answer); + FloatArrayF<3> computeInterfaceJumpAt(int interf, const FloatArrayF<3> &lCoords, TimeStep *tStep); // Internal forces - void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override; void discComputeSectionalForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVec, FloatArray &solVecD, EnrichmentItem *ei); - void computeSectionalForcesAt(FloatArray §ionalForces, IntegrationPoint *ip, Material *mat, TimeStep *tStep, FloatArray &genEps, double zeta); - + FloatArray computeSectionalForcesAt(IntegrationPoint *ip, Material *mat, TimeStep *tStep, FloatArray &genEps, double zeta); + double evaluateLevelSet(const FloatArray &lCoords, EnrichmentItem *ei); // double edgeEvaluateLevelSet(const FloatArray &lCoords, EnrichmentItem *ei, const int edge); double evaluateHeavisideXi(double xi, ShellCrack *ei); double evaluateHeavisideXi(double xi, Delamination *ei); double evaluateCutHeaviside(const double xi, const double xiBottom, const double xiTop) const; void computeCohesiveForces(FloatArray &answer, TimeStep *tStep, FloatArray &solVec, FloatArray &solVecD, EnrichmentItem *ei, EnrichmentItem *coupledToEi); - + // Tangent matrices - void computeLambdaGMatricesDis(FloatMatrix lambdaD [ 3 ], double zeta); - void computeLambdaNMatrixDis(FloatMatrix &lambda_xd, double zeta); + std::array, 3> computeLambdaGMatricesDis(double zeta); + FloatMatrixF<3,7> computeLambdaNMatrixDis(double zeta); virtual void OLDcomputeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; virtual void discComputeBulkTangentMatrix(FloatMatrix &KdIJ, IntegrationPoint *ip, EnrichmentItem *eiI, EnrichmentItem *eiJ, int layer, FloatMatrix A [ 3 ] [ 3 ], TimeStep *tStep); virtual void discComputeStiffness(FloatMatrix &LCC, FloatMatrix &LDD, FloatMatrix &LDC, IntegrationPoint *ip, int layer, FloatMatrix A [ 3 ] [ 3 ], TimeStep *tStep); - + double EvaluateEnrFuncInDofMan(int dofManNum, EnrichmentItem *ei); void computeEnrichedBmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei); void computeEnrichedNmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei); void computeCohesiveNmatrixAt(const FloatArray &lCoords, FloatMatrix &answer, EnrichmentItem *ei); - - virtual void edgeGiveUpdatedSolutionVector(FloatArray &answer, const int iedge, TimeStep *tStep); - void edgeEvalEnrCovarBaseVectorsAt(const FloatArray &lCoords, const int iedge, FloatMatrix &gcov, TimeStep *tStep, EnrichmentItem *ei); + void edgeGiveUpdatedSolutionVector(FloatArray &answer, const int iedge, TimeStep *tStep) override; + + FloatMatrixF<3,3> edgeEvalEnrCovarBaseVectorsAt(const FloatArrayF<3> &lCoords, const int iedge, TimeStep *tStep, EnrichmentItem *ei); void computeCohesiveTangent(FloatMatrix &answer, TimeStep *tStep); void computeCohesiveTangentAt(FloatMatrix &answer, TimeStep *tStep, Delamination *dei, EnrichmentItem *ei_j, EnrichmentItem *ei_k); @@ -112,28 +112,27 @@ class Shell7BaseXFEM : public Shell7Base, public XfemElementInterface // External loads // Overloaded, as the element is using enhanced approximation - void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global); + void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global) override; // overloaded, the computeBoundaryEdgeLoadVector returns full element DOFs - virtual void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIdArray) + void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIdArray) override { this->giveLocationArray (locationArray, s, dofIdArray);} - void computeEnrTractionForce(FloatArray &answer, const int iedge, BoundaryLoad *edgeLoad, TimeStep *tStep, ValueModeType mode, EnrichmentItem *ei); // Mass matrices - void computeMassMatrixNum(FloatMatrix &answer, TimeStep *tStep); + void computeMassMatrixNum(FloatMatrix &answer, TimeStep *tStep) override; // VTK - virtual void giveCompositeExportData(std::vector < VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ); - virtual void giveCompositeExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ); - virtual void giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ); - virtual void giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ); + void giveCompositeExportData(std::vector < VTKPiece > &vtkPieces, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ) override; + void giveCompositeExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ) override; + void giveShellExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ) override; + void giveCZExportData(VTKPiece &vtkPiece, IntArray &primaryVarsToExport, IntArray &internalVarsToExport, IntArray cellVarsToExport, TimeStep *tStep ); - virtual void vtkEvalUpdatedGlobalCoordinateAt(const FloatArray &localCoords, int layer, FloatArray &globalCoords, TimeStep *tStep); - void giveDisUnknownsAt(const FloatArray &lCoords, EnrichmentItem *ei, FloatArray &solVec, FloatArray &x, FloatArray &m, double &gam, TimeStep *tStep); + FloatArrayF<3> vtkEvalUpdatedGlobalCoordinateAt(const FloatArrayF<3> &localCoords, int layer, TimeStep *tStep) override; + void giveDisUnknownsAt(const FloatArrayF<3> &lCoords, EnrichmentItem *ei, const FloatArray &solVec, FloatArrayF<3> &x, FloatArrayF<3> &m, double &gam, TimeStep *tStep); IntArray DelaminatedInterfaceList; - void computeFailureCriteriaQuantities(FailureCriteriaStatus *fc, TimeStep *tStep); + void computeFailureCriteriaQuantities(FailureCriteriaStatus *fc, TimeStep *tStep) override; // Subdivision @@ -141,11 +140,11 @@ class Shell7BaseXFEM : public Shell7Base, public XfemElementInterface std :: vector < std :: vector< Triangle > > crackSubdivisions; IntArray numSubDivisionsArray; - - void giveFictiousNodeCoordsForExport(std::vector &nodes, int layer, int subCell); - void giveFictiousCZNodeCoordsForExport(std::vector &nodes, int layer, int subCell); - void giveFictiousUpdatedNodeCoordsForExport(std::vector &nodes, int layer, TimeStep *tStep, int subCell); - void giveFictiousUpdatedCZNodeCoordsForExport(std::vector &nodes, int layer, TimeStep *tStep, int subCell); + + std::vector giveFictiousNodeCoordsForExport(int layer, int subCell); + std::vector giveFictiousCZNodeCoordsForExport(int layer, int subCell); + std::vector giveFictiousUpdatedNodeCoordsForExport(int layer, TimeStep *tStep, int subCell); + std::vector giveFictiousUpdatedCZNodeCoordsForExport(int layer, TimeStep *tStep, int subCell); void giveLocalNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, FloatArray &nodeLocalXi2Coords, FloatArray &nodeLocalXi3Coords, int subCell, int layer, FloatMatrix &localNodeCoords); void giveLocalCZNodeCoordsForExport(FloatArray &nodeLocalXi1Coords, FloatArray &nodeLocalXi2Coords, FloatArray &nodeLocalXi3Coords, int subCell, FloatMatrix &localNodeCoords); void mapXi3FromLocalToShell(FloatArray &answer, FloatArray &local, int layer); @@ -156,31 +155,29 @@ class Shell7BaseXFEM : public Shell7Base, public XfemElementInterface std::vector< IntArray > orderingArrays; std::vector< IntArray > activeDofsArrays; - + void computeTripleProduct(FloatMatrix &answer, const FloatMatrix &a, const FloatMatrix &b, const FloatMatrix &c); - + // Recovery of through thickness stresses by momentum balance - void recoverShearStress(TimeStep *tStep); - + void recoverShearStress(TimeStep *tStep) override; public: Shell7BaseXFEM(int n, Domain * d); - virtual ~Shell7BaseXFEM(); - virtual int checkConsistency(); + int checkConsistency() override; void giveMaxCZDamages(FloatArray &answer, TimeStep *tStep); - virtual const char *giveClassName() const { return "Shell7BaseXFEM"; } + const char *giveClassName() const override { return "Shell7BaseXFEM"; } std :: string errorInfo(const char *func) const { return std :: string(giveClassName()) + func; } - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; + + void initializeFrom(InputRecord &ir) override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + int giveNumberOfDofs() override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual int giveNumberOfDofs(); - // Recovery of through thickness stresses by momentum balance - virtual void giveFailedInterfaceNumber(IntArray &failedInterfaces, FloatArray &initiationFactor, TimeStep *tStep, bool recoverStresses = true); - virtual void giveAverageTransverseInterfaceStress(std::vector &transverseStress, TimeStep *tStep); - virtual void giveRecoveredTransverseInterfaceStress(std::vector &transverseStress, TimeStep *tStep); + void giveFailedInterfaceNumber(IntArray &failedInterfaces, FloatArray &initiationFactor, TimeStep *tStep, bool recoverStresses = true); + void giveAverageTransverseInterfaceStress(std::vector &transverseStress, TimeStep *tStep); + void giveRecoveredTransverseInterfaceStress(std::vector &transverseStress, TimeStep *tStep) override; bool hasCohesiveZone(int interfaceNum); std :: vector< std :: unique_ptr< IntegrationRule > > czIntegrationRulesArray; diff --git a/src/sm/Elements/Shells/solidshell.C b/src/sm/Elements/Shells/solidshell.C index a4968e21c..4499e3a4b 100644 --- a/src/sm/Elements/Shells/solidshell.C +++ b/src/sm/Elements/Shells/solidshell.C @@ -32,13 +32,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/Shells/solidshell.h" +#include "sm/Elements/Shells/solidshell.h" #include #include "classfactory.h" #include "fei3dhexalin.h" #include "gausspoint.h" #include "gaussintegrationrule.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" namespace oofem { REGISTER_Element(SolidShell); @@ -49,28 +49,27 @@ SolidShell :: SolidShell(int n, Domain *aDomain) : LSpace(n, aDomain) { numberOfDofMans = 8; numberOfGaussPoints = 8; - } void -SolidShell :: postInitialize() { - +SolidShell :: postInitialize() +{ LSpace :: postInitialize(); - + int numEASparam = 0; - + switch ( this->EAS_type) { - case 1: + case 1: numEASparam = 1; break; - + case 2: numEASparam = 3; break; } - + this->u_k.resize(numberOfDofMans*3); this->u_k.zero(); this->fE.resize(numEASparam); @@ -81,7 +80,6 @@ SolidShell :: postInitialize() { this->invKEE.zero(); this->alpha.resize(numEASparam); this->alpha.zero(); - } void @@ -90,7 +88,7 @@ SolidShell :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ] = new GaussIntegrationRule(1, this, 1, 6); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 6); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } @@ -98,26 +96,18 @@ SolidShell :: computeGaussPoints() FEInterpolation *SolidShell :: giveInterpolation() const { return & interpolation; } -IRResultType -SolidShell :: initializeFrom(InputRecord *ir) +void +SolidShell :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 8; - IRResultType result = this->NLStructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + NLStructuralElement :: initializeFrom(ir); - // Check if EAS should be used this->EAS_type = 0; - if ( ir->hasField(_IFT_SolidShell_EAS_type) ) { - + if ( ir.hasField(_IFT_SolidShell_EAS_type) ) { IR_GIVE_FIELD(ir, this->EAS_type, _IFT_SolidShell_EAS_type); - - } - - return IRRT_OK; + } } @@ -130,34 +120,33 @@ SolidShell :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int { FEInterpolation *interp = this->giveInterpolation(); FloatMatrix dNdx; - FloatArray lCoords = * gp->giveNaturalCoordinates(); + const FloatArray &lCoords = gp->giveNaturalCoordinates(); interp->evaldNdx( dNdx, lCoords, FEIElementGeometryWrapper(this) ); - + answer.resize(6, dNdx.giveNumberOfRows() * 3); answer.zero(); - + // Do ANS // Need to evaluate strain at four points FloatArray A = { 0.0, -1.0, 0.0}; FloatArray B = { 1.0, 0.0, 0.0}; FloatArray C = { 0.0, 1.0, 0.0}; FloatArray D = {-1.0, 0.0, 0.0}; - + FloatMatrix dNdxA, dNdxB, dNdxC, dNdxD; interp->evaldNdx( dNdxA, A, FEIElementGeometryWrapper(this) ); interp->evaldNdx( dNdxB, B, FEIElementGeometryWrapper(this) ); interp->evaldNdx( dNdxC, C, FEIElementGeometryWrapper(this) ); interp->evaldNdx( dNdxD, D, FEIElementGeometryWrapper(this) ); - + FloatMatrix dNdx0; interp->evaldNdx( dNdx0, {lCoords.at(1), lCoords.at(2), 0.0}, FEIElementGeometryWrapper(this) ); - - + double NA = 0.5 * ( 1.0 - lCoords.at(2) ); double NC = 0.5 * ( 1.0 + lCoords.at(2) ); double NB = 0.5 * ( 1.0 - lCoords.at(1) ); double ND = 0.5 * ( 1.0 + lCoords.at(1) ); - + // E_xz = E(5) = N_A(gp) * B(A)(5,:) + N_C(gp) * B(C)(5,:) // E_yz = E(4) = N_B(gp) * B(B)(4,:) + N_D(gp) * B(D)(4,:) @@ -166,7 +155,7 @@ SolidShell :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int answer.at(2, 3 * i - 1) = dNdx.at(i, 2); answer.at(6, 3 * i - 2) = dNdx.at(i, 2); answer.at(6, 3 * i - 1) = dNdx.at(i, 1); - + // Evaluate thickness strain at the mid-surface //answer.at(3, 3 * i - 0) = dNdx.at(i, 3); answer.at(3, 3 * i - 0) = dNdx0.at(i, 3); @@ -174,7 +163,6 @@ SolidShell :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int answer.at(4, 3 * i - 1) = NB * dNdxB.at(i, 3) + ND * dNdxD.at(i, 3); answer.at(4, 3 * i - 0) = NB * dNdxB.at(i, 2) + ND * dNdxD.at(i, 2); - answer.at(5, 3 * i - 2) = NA * dNdxA.at(i, 3) + NC * dNdxC.at(i, 3); answer.at(5, 3 * i - 0) = NA * dNdxA.at(i, 1) + NC * dNdxC.at(i, 1); } @@ -187,12 +175,11 @@ SolidShell :: computeBHmatrixAt(FloatArray &lCoords, FloatMatrix &answer) // luated at gp. // B matrix - 6 rows : epsilon-X, epsilon-Y, epsilon-Z, gamma-YZ, gamma-ZX, gamma-XY : { - #if 1 FEInterpolation *interp = this->giveInterpolation(); FloatMatrix dNdx; interp->evaldNdx( dNdx, lCoords, FEIElementGeometryWrapper(this) ); - + answer.resize(9, dNdx.giveNumberOfRows() * 3); answer.zero(); for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { @@ -206,38 +193,35 @@ SolidShell :: computeBHmatrixAt(FloatArray &lCoords, FloatMatrix &answer) answer.at(6, 3 * i - 2) = dNdx.at(i, 2); // du/dy answer.at(9, 3 * i - 1) = dNdx.at(i, 1); // dv/dx } - + #else FEInterpolation *interp = this->giveInterpolation(); FloatMatrix dNdx; interp->evaldNdx( dNdx, lCoords, FEIElementGeometryWrapper(this) ); - + answer.resize(9, dNdx.giveNumberOfRows() * 3); answer.zero(); - // Need to evaluate strain at four points FloatArray A = { 0.0, -1.0, 0.0}; FloatArray B = { 1.0, 0.0, 0.0}; FloatArray C = { 0.0, 1.0, 0.0}; FloatArray D = {-1.0, 0.0, 0.0}; - - + FloatMatrix dNdxA, dNdxB, dNdxC, dNdxD; interp->evaldNdx( dNdxA, A, FEIElementGeometryWrapper(this) ); interp->evaldNdx( dNdxB, B, FEIElementGeometryWrapper(this) ); interp->evaldNdx( dNdxC, C, FEIElementGeometryWrapper(this) ); interp->evaldNdx( dNdxD, D, FEIElementGeometryWrapper(this) ); - + FloatMatrix dNdx0; interp->evaldNdx( dNdx0, {lCoords.at(1), lCoords.at(2), 0.0}, FEIElementGeometryWrapper(this) ); - - + double NA = 0.5 * ( 1.0 - lCoords.at(2) ); double NC = 0.5 * ( 1.0 + lCoords.at(2) ); double NB = 0.5 * ( 1.0 - lCoords.at(1) ); double ND = 0.5 * ( 1.0 + lCoords.at(1) ); - + // E_xz = E(5) = N_A(gp) * B(A)(5,:) + N_C(gp) * B(C)(5,:) // E_yz = E(4) = N_B(gp) * B(B)(4,:) + N_D(gp) * B(D)(4,:) @@ -267,31 +251,26 @@ SolidShell :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) // luated at gp. // B matrix - 6 rows : epsilon-X, epsilon-Y, epsilon-Z, gamma-YZ, gamma-ZX, gamma-XY : { - - this->computeBHmatrixAt( *gp->giveNaturalCoordinates(), answer); - + this->computeBHmatrixAt(gp->giveNaturalCoordinates(), answer); } void SolidShell :: computeEASBmatrixAt(GaussPoint *gp, FloatMatrix &answer) { - - FloatArray lCoords = *gp->giveNaturalCoordinates(); + const FloatArray &lCoords = gp->giveNaturalCoordinates(); double xi = lCoords.at(1); double eta = lCoords.at(2); double zeta = lCoords.at(3); FloatMatrix M; - + switch ( this->EAS_type) { case 1: - // alt 1 M.resize(6,1); M.zero(); M.at(3,1) = zeta; break; - case 2: // alt 2 M.resize(6,3); @@ -301,7 +280,7 @@ SolidShell :: computeEASBmatrixAt(GaussPoint *gp, FloatMatrix &answer) M.at(3,3) = zeta; break; } - + FEInterpolation *interp = this->giveInterpolation(); FloatMatrix J0mat; FloatArray center = {0.0, 0.0, 0.0}; @@ -310,38 +289,33 @@ SolidShell :: computeEASBmatrixAt(GaussPoint *gp, FloatMatrix &answer) // double J0 = interp->giveTransformationJacobian(center, FEIElementGeometryWrapper(this) ); double J0 = J0mat.giveDeterminant(); double J = interp->giveTransformationJacobian(lCoords, FEIElementGeometryWrapper(this) ); - + FloatMatrix T(6,6); this->computeBondTransformationMatrix(T, J0mat); //T.printYourself("T"); - //T.beUnitMatrix(); answer.clear(); answer.plusProductUnsym(T, M, J/J0); - - } - void SolidShell :: computeBondTransformationMatrix(FloatMatrix &answer, FloatMatrix &base) { - // given a bases {g1, g2, g3} compute the Bond (Voigt form) transformation matrix. - // TODO is this with OOFEM ordering of components? - FloatArray x, y, z; - x.beColumnOf(base,1); - y.beColumnOf(base,2); - z.beColumnOf(base,3); - answer = { + // given a bases {g1, g2, g3} compute the Bond (Voigt form) transformation matrix. + // TODO is this with OOFEM ordering of components? + FloatArray x, y, z; + x.beColumnOf(base,1); + y.beColumnOf(base,2); + z.beColumnOf(base,3); + answer = { { x(0) * x(0), x(1) * x(1), x(2) * x(2), x(1) * x(2), x(0) * x(2), x(0) * x(1) }, { y(0) * y(0), y(1) * y(1), y(2) * y(2), y(1) * y(2), y(0) * y(2), y(0) * y(1) }, { z(0) * z(0), z(1) * z(1), z(2) * z(2), z(1) * z(2), z(0) * z(2), z(0) * z(1) }, { 2 * y(0) * z(0), 2 * y(1) * z(1), 2 * y(2) * z(2), y(2) * z(1) + y(1) * z(2), y(2) * z(0) + y(0) * z(2), y(1) * z(0) + y(0) * z(1) }, { 2 * x(0) * z(0), 2 * x(1) * z(1), 2 * x(2) * z(2), x(2) * z(1) + x(1) * z(2), x(2) * z(0) + x(0) * z(2), x(1) * z(0) + x(0) * z(1) }, { 2 * x(0) * y(0), 2 * x(1) * y(1), 2 * x(2) * y(2), x(2) * y(1) + x(1) * y(2), x(2) * y(0) + x(0) * y(2), x(1) * y(0) + x(0) * y(1) } - }; - + }; } void @@ -350,7 +324,7 @@ SolidShell :: computeAlpha(FloatArray &answer, FloatArray &u) // compute alpha based on displacement update FloatArray deltaU; deltaU.beDifferenceOf(u,this->u_k); - + FloatMatrix KEE_inv = this->invKEE; FloatArray fE = this->fE; FloatMatrix KEC = this->KEC; @@ -358,11 +332,10 @@ SolidShell :: computeAlpha(FloatArray &answer, FloatArray &u) temp.beProductOf(KEC, deltaU); temp.add(fE); deltaAlpha.beProductOf(KEE_inv,temp); - + FloatArray oldAlpha = this->alpha; // last converged values answer = this->alpha - deltaAlpha; - - + // set current u-displcement this->u_k = u; } @@ -375,87 +348,77 @@ SolidShell :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int FloatMatrix KEE, KBE, BC, BE, D; fE.clear(); fC.clear(); - + KEE.clear(); - + this->computeVectorOf(VM_Total, tStep, u); FloatArray alpha; this->computeAlpha(alpha, u ); StructuralCrossSection *cs = this->giveStructuralCrossSection(); - for ( GaussPoint *gp: *this->giveDefaultIntegrationRulePtr() ) { - + for ( auto &gp: *this->giveDefaultIntegrationRulePtr() ) { if ( nlGeometry == 0 ) { computeBmatrixAt(gp, BC); this->computeEASBmatrixAt(gp, BE); - + vStrainC.beProductOf(BC, u); vStrainE.beProductOf(BE, alpha); vStrainC.add(vStrainE); //this->computeStressVector(vStress, vStrainC, gp, tStep); cs->giveRealStresses(vStress, gp, vStrainC, tStep); - + } else if ( nlGeometry == 1 ) { // First Piola-Kirchhoff stress - + this->computeBHmatrixAt(gp, BC); FloatArray vFC, VFE; vFC.beProductOf(BC, u); //vFE.beProductOf(BE, alpha); //vFC.add(VFE); cs->giveFirstPKStresses(vStress, gp, vFC, tStep); - + } else if ( nlGeometry == 2 ) { // Second Piola-Kirchhoff stress this->computeBEmatrixAt(gp, BC, tStep); this->computeEASBmatrixAt(gp, BE); - this->computeEVector(vStrainC, *gp->giveNaturalCoordinates(), u); + this->computeEVector(vStrainC, gp->giveNaturalCoordinates(), u); vStrainE.beProductOf(BE, alpha); vStrainC.add(vStrainE); cs->giveRealStresses(vStress, gp, vStrainC, tStep); - } - - + double dV = this->computeVolumeAround(gp); - // Compute nodal internal forces at nodes as f = B^T*Stress dV fC.plusProduct(BC, vStress, dV); fE.plusProduct(BE, vStress, dV); - } this->fE = fE; - + FloatMatrix KEE_inv, KEC; KEE_inv = this->invKEE; KEC = this->KEC; - + FloatArray temp, f; temp.beProductOf(KEE_inv,fE); answer = fC; answer.plusProduct(KEC, temp, -1.0); - } else { - LSpace :: giveInternalForcesVector(answer, tStep, useUpdatedGpRecord); - } - - } void SolidShell :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { - if ( this->EAS_type ) { + if ( this->EAS_type ) { FloatArray fC, fE, strain, u, vStrainC, vStrainE, vStress; FloatMatrix KEE, KEC, KCC, KCC_geo, BC, BE, D, DBC, DBE; - + KEC.clear(); KEE.clear(); KCC.clear(); - + StructuralCrossSection *cs = this->giveStructuralCrossSection(); for ( GaussPoint *gp: *this->giveDefaultIntegrationRulePtr() ) { if ( nlGeometry == 0 ) { @@ -466,15 +429,15 @@ SolidShell :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, this->computeConstitutiveMatrixAt(D, rMode, gp, tStep); DBC.beProductOf(D, BC); DBE.beProductOf(D, BE); - + KCC.plusProductUnsym(BC, DBC, dV); KEC.plusProductUnsym(BE, DBC, dV); KEE.plusProductUnsym(BE, DBE, dV); - + } else if ( nlGeometry == 1 ) { this->computeBHmatrixAt(gp, BC); cs->giveStiffnessMatrix_dPdF(D, rMode, gp, tStep); - + } else if ( nlGeometry == 2 ) { this->computeBEmatrixAt(gp, BC, tStep); this->computeEASBmatrixAt(gp, BE); @@ -483,89 +446,79 @@ SolidShell :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, this->computeConstitutiveMatrixAt(D, rMode, gp, tStep); DBC.beProductOf(D, BC); DBE.beProductOf(D, BE); - + KCC.plusProductUnsym(BC, DBC, dV); KEC.plusProductUnsym(BE, DBC, dV); KEE.plusProductUnsym(BE, DBE, dV); - + //TODO add geometric stiffness this->computeGeometricStiffness(KCC_geo, gp, tStep); KCC.add(dV, KCC_geo); - } } - FloatMatrix KEE_inv; KEE_inv.beInverseOf(KEE); this->invKEE = KEE_inv; this->KEC = KEC; - - answer= KCC; - + + answer = KCC; + FloatMatrix K, tempmat; tempmat.beProductOf(KEE_inv, KEC); - answer.plusProductUnsym(KEC, tempmat, -1.0); - } else { - LSpace :: computeStiffnessMatrix(answer, rMode, tStep); - } } - - - + void SolidShell :: computeBEmatrixAt(GaussPoint *gp, FloatMatrix &answer, TimeStep *tStep) { FloatMatrix dN, F; FloatArray vF; // compute the derivatives of shape functions - this->interpolation.evaldNdx( dN, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - + this->interpolation.evaldNdx( dN, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + FloatArray u; this->computeVectorOf(VM_Total, tStep, u); // solution vector - - this->computeFVector(vF, *gp->giveNaturalCoordinates(), u); + + this->computeFVector(vF, gp->giveNaturalCoordinates(), u); F.beMatrixForm(vF); - + answer.resize(6, 24); answer.zero(); #if 1 for ( int i = 1, col = 0; i <= dN.giveNumberOfRows(); i++, col += 3 ) { - for ( int j = 1; j <= 3; j++ ) { - answer.at(1,col + j) = F.at(j,1) * dN.at(i, 1); - answer.at(2,col + j) = F.at(j,2) * dN.at(i, 2); - answer.at(3,col + j) = F.at(j,3) * dN.at(i, 3); - answer.at(4,col + j) = F.at(j,2) * dN.at(i, 3) + F.at(j,3) * dN.at(i, 2); - answer.at(5,col + j) = F.at(j,1) * dN.at(i, 3) + F.at(j,3) * dN.at(i, 1); - answer.at(6,col + j) = F.at(j,1) * dN.at(i, 2) + F.at(j,2) * dN.at(i, 1); - } + for ( int j = 1; j <= 3; j++ ) { + answer.at(1,col + j) = F.at(j,1) * dN.at(i, 1); + answer.at(2,col + j) = F.at(j,2) * dN.at(i, 2); + answer.at(3,col + j) = F.at(j,3) * dN.at(i, 3); + answer.at(4,col + j) = F.at(j,2) * dN.at(i, 3) + F.at(j,3) * dN.at(i, 2); + answer.at(5,col + j) = F.at(j,1) * dN.at(i, 3) + F.at(j,3) * dN.at(i, 1); + answer.at(6,col + j) = F.at(j,1) * dN.at(i, 2) + F.at(j,2) * dN.at(i, 1); + } } - #else FEInterpolation *interp = this->giveInterpolation(); FloatMatrix dNdx; - FloatArray lCoords = * gp->giveNaturalCoordinates(); + const FloatArray &lCoords = gp->giveNaturalCoordinates(); interp->evaldNdx( dNdx, lCoords, FEIElementGeometryWrapper(this) ); - // Do ANS // Need to evaluate strain at four points FloatArray A = { 0.0, -1.0, 0.0}; FloatArray B = { 1.0, 0.0, 0.0}; FloatArray C = { 0.0, 1.0, 0.0}; FloatArray D = {-1.0, 0.0, 0.0}; - + FloatMatrix dNdxA, dNdxB, dNdxC, dNdxD; interp->evaldNdx( dNdxA, A, FEIElementGeometryWrapper(this) ); interp->evaldNdx( dNdxB, B, FEIElementGeometryWrapper(this) ); interp->evaldNdx( dNdxC, C, FEIElementGeometryWrapper(this) ); interp->evaldNdx( dNdxD, D, FEIElementGeometryWrapper(this) ); - + // Eval deformation gradients FloatArray vFA, vFB, vFC, vFD; this->computeFVector(vFA, A, u); @@ -577,46 +530,36 @@ SolidShell :: computeBEmatrixAt(GaussPoint *gp, FloatMatrix &answer, TimeStep *t FB.beMatrixForm(vFB); FC.beMatrixForm(vFC); FD.beMatrixForm(vFD); - + FloatMatrix dNdx0; interp->evaldNdx( dNdx0, {lCoords.at(1), lCoords.at(2), 0.0}, FEIElementGeometryWrapper(this) ); - - + double NA = 0.5 * ( 1.0 - lCoords.at(2) ); double NC = 0.5 * ( 1.0 + lCoords.at(2) ); double NB = 0.5 * ( 1.0 - lCoords.at(1) ); double ND = 0.5 * ( 1.0 + lCoords.at(1) ); - + // E_xz = E(5) = N_A(gp) * B(A)(5,:) + N_C(gp) * B(C)(5,:) // E_yz = E(4) = N_B(gp) * B(B)(4,:) + N_D(gp) * B(D)(4,:) - for ( int i = 1, col = 0; i <= dN.giveNumberOfRows(); i++, col += 3 ) { - for ( int j = 1; j <= 3; j++ ) { - answer.at(1,col + j) = F.at(j,1) * dN.at(i, 1); - answer.at(2,col + j) = F.at(j,2) * dN.at(i, 2); - answer.at(3,col + j) = F.at(j,3) * dN.at(i, 3); - answer.at(6,col + j) = F.at(j,1) * dN.at(i, 2) + F.at(j,2) * dN.at(i, 1); - - answer.at(4,col + j) = NB * ( FB.at(j,2) * dNdxB.at(i, 3) + FB.at(j,3) * dNdxB.at(i, 2) ) + ND * ( FD.at(j,2) * dNdxD.at(i, 3) + FD.at(j,3) * dNdxD.at(i, 2) ) ; - answer.at(5,col + j) = NA * ( FA.at(j,1) * dNdxA.at(i, 3) + FA.at(j,3) * dNdxA.at(i, 1) ) + NC * ( FC.at(j,1) * dNdxC.at(i, 3) + FC.at(j,3) * dNdxC.at(i, 1) ); - - } - } - - + for ( int j = 1; j <= 3; j++ ) { + answer.at(1,col + j) = F.at(j,1) * dN.at(i, 1); + answer.at(2,col + j) = F.at(j,2) * dN.at(i, 2); + answer.at(3,col + j) = F.at(j,3) * dN.at(i, 3); + answer.at(6,col + j) = F.at(j,1) * dN.at(i, 2) + F.at(j,2) * dN.at(i, 1); + + answer.at(4,col + j) = NB * ( FB.at(j,2) * dNdxB.at(i, 3) + FB.at(j,3) * dNdxB.at(i, 2) ) + ND * ( FD.at(j,2) * dNdxD.at(i, 3) + FD.at(j,3) * dNdxD.at(i, 2) ) ; + answer.at(5,col + j) = NA * ( FA.at(j,1) * dNdxA.at(i, 3) + FA.at(j,3) * dNdxA.at(i, 1) ) + NC * ( FC.at(j,1) * dNdxC.at(i, 3) + FC.at(j,3) * dNdxC.at(i, 1) ); + } + } #endif - - - } - void SolidShell :: computeFVector(FloatArray &answer, FloatArray &lCoords, FloatArray &ae) { - FloatMatrix B; this->computeBHmatrixAt(lCoords, B); answer.beProductOf(B, ae); @@ -624,9 +567,7 @@ SolidShell :: computeFVector(FloatArray &answer, FloatArray &lCoords, FloatArray answer.at(1) += 1.0; answer.at(2) += 1.0; answer.at(3) += 1.0; - } - void @@ -634,8 +575,7 @@ SolidShell :: computeEVector(FloatArray &answer, FloatArray &lCoords, FloatArray { FloatArray vF; this->computeFVector(vF, lCoords, u); - -#if 0 +#if 0 FloatMatrix F, E; F.beMatrixForm(vF); E.beTProductOf(F, F); @@ -643,10 +583,8 @@ SolidShell :: computeEVector(FloatArray &answer, FloatArray &lCoords, FloatArray E.at(2, 2) -= 1.0; E.at(3, 3) -= 1.0; E.times(0.5); - answer.beSymVectorFormOfStrain(E); - + answer.beSymVectorFormOfStrain(E); #else - FloatMatrix F, E; F.beMatrixForm(vF); E.beTProductOf(F, F); @@ -656,15 +594,12 @@ SolidShell :: computeEVector(FloatArray &answer, FloatArray &lCoords, FloatArray E.times(0.5); answer.beSymVectorFormOfStrain(E); - - // Need to evaluate strain at four points FloatArray A = { 0.0, -1.0, 0.0}; FloatArray B = { 1.0, 0.0, 0.0}; FloatArray C = { 0.0, 1.0, 0.0}; FloatArray D = {-1.0, 0.0, 0.0}; - - + // Eval deformation gradients FloatArray vFA, vFB, vFC, vFD; this->computeFVector(vFA, A, u); @@ -676,51 +611,48 @@ SolidShell :: computeEVector(FloatArray &answer, FloatArray &lCoords, FloatArray FB.beMatrixForm(vFB); FC.beMatrixForm(vFC); FD.beMatrixForm(vFD); - + EA.beTProductOf(FA,FA); EA.times(0.5); EB.beTProductOf(FB,FB); EB.times(0.5); EC.beTProductOf(FC,FC); EC.times(0.5); ED.beTProductOf(FD,FD); ED.times(0.5); - + // FloatMatrix dNdx0; // interp->evaldNdx( dNdx0, {lCoords.at(1), lCoords.at(2), 0.0}, FEIElementGeometryWrapper(this) ); - - + double NA = 0.5 * ( 1.0 - lCoords.at(2) ); double NC = 0.5 * ( 1.0 + lCoords.at(2) ); double NB = 0.5 * ( 1.0 - lCoords.at(1) ); double ND = 0.5 * ( 1.0 + lCoords.at(1) ); - + answer.at(4) = NB * EB.at(2,3) + ND * ED.at(2,3); answer.at(5) = NA * EA.at(2,3) + NC * EC.at(2,3); - #endif - } - + + void SolidShell :: computeGeometricStiffness(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) { - answer.resize(24,24); answer.zero(); - + StructuralMaterialStatus *matStat = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); if ( !matStat ) { // no matstat created yet return; } FloatArray vS; vS = matStat->giveStressVector(); - + FloatMatrix S, dNdx, temp, G_ij; S.beMatrixFormOfStress(vS); - this->interpolation.evaldNdx( dNdx, * gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - + this->interpolation.evaldNdx( dNdx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + temp.beProductTOf(S,dNdx); G_ij.beProductOf(dNdx, temp); FloatMatrix K_ij(3,3); K_ij.zero(); - + for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) { for ( int j = i; j <= dNdx.giveNumberOfRows(); j++ ) { K_ij.at(1,1) = K_ij.at(2,2) = K_ij.at(3,3) = G_ij.at(i,j); @@ -728,8 +660,6 @@ SolidShell :: computeGeometricStiffness(FloatMatrix &answer, GaussPoint *gp, Tim } } answer.symmetrized(); - } - } // end namespace oofem diff --git a/src/sm/Elements/Shells/solidshell.h b/src/sm/Elements/Shells/solidshell.h index cd2c0d19d..451c0c8bc 100644 --- a/src/sm/Elements/Shells/solidshell.h +++ b/src/sm/Elements/Shells/solidshell.h @@ -35,7 +35,7 @@ #ifndef solidshell_h #define solidshell_h -#include "Elements/3D/lspace.h" +#include "sm/Elements/3D/lspace.h" #define _IFT_SolidShell_Name "solidshell" @@ -61,27 +61,27 @@ class SolidShell : public LSpace public: SolidShell(int n, Domain * d); virtual ~SolidShell() { } - virtual FEInterpolation *giveInterpolation() const; - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS); - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeBHmatrixAt(FloatArray &lCoords, FloatMatrix &answer); - + FEInterpolation *giveInterpolation() const override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeBHmatrixAt(FloatArray &lCoords, FloatMatrix &answer); + virtual void computeBEmatrixAt(GaussPoint *gp, FloatMatrix &answer, TimeStep *tStep); - virtual void computeGaussPoints(); + void computeGaussPoints() override; virtual void computeEASBmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; void computeGeometricStiffness(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); void computeFVector(FloatArray &answer, FloatArray &lCoords, FloatArray &ae); void computeEVector(FloatArray &answer, FloatArray &lCoords, FloatArray &ae); void computeEASfield(FloatArray &answer, TimeStep *tStep); - + // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LSpace_Name; } - virtual const char *giveClassName() const { return "SolidShell"; } - virtual IRResultType initializeFrom(InputRecord *ir); - + const char *giveInputRecordName() const override { return _IFT_LSpace_Name; } + const char *giveClassName() const override { return "SolidShell"; } + void initializeFrom(InputRecord &ir) override; + // variables associated with EAS int EAS_type; FloatArray tempAlpha; @@ -91,13 +91,12 @@ class SolidShell : public LSpace FloatMatrix KEC; FloatArray fE; void computeAlpha(FloatArray &answer, FloatArray &u); - + void computeBondTransformationMatrix(FloatMatrix &answer, FloatMatrix &base); - virtual void postInitialize(); - virtual int checkConsistency(){ return 1; }; - - - private: + void postInitialize() override; + int checkConsistency() override{ return 1; }; + +private: void x(int arg1); }; } // end namespace oofem diff --git a/src/sm/Elements/Shells/tr2shell7.C b/src/sm/Elements/Shells/tr2shell7.C index 97d16b941..660c7d4e1 100644 --- a/src/sm/Elements/Shells/tr2shell7.C +++ b/src/sm/Elements/Shells/tr2shell7.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Shells/tr2shell7.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/Shells/tr2shell7.h" +#include "sm/Materials/structuralms.h" #include "node.h" #include "load.h" #include "mathfem.h" @@ -180,7 +180,7 @@ Tr2Shell7 :: computeAreaAround(GaussPoint *gp, double xi) lcoords.at(1) = gp->giveNaturalCoordinate(1); lcoords.at(2) = gp->giveNaturalCoordinate(2); lcoords.at(3) = xi; - this->evalInitialCovarBaseVectorsAt(lcoords, Gcov); + Gcov = this->evalInitialCovarBaseVectorsAt(lcoords); G1.beColumnOf(Gcov, 1); G2.beColumnOf(Gcov, 2); temp.beVectorProductOf(G1, G2); @@ -193,12 +193,9 @@ Tr2Shell7 :: computeAreaAround(GaussPoint *gp, double xi) double Tr2Shell7 :: computeVolumeAroundLayer(GaussPoint *gp, int layer) { - double detJ; - FloatMatrix Gcov; - FloatArray lcoords; - lcoords = gp->giveNaturalCoordinates(); - this->evalInitialCovarBaseVectorsAt(lcoords, Gcov); - detJ = Gcov.giveDeterminant() * 0.5 * this->layeredCS->giveLayerThickness(layer); + const auto &lcoords = gp->giveNaturalCoordinates(); + auto Gcov = this->evalInitialCovarBaseVectorsAt(lcoords); + double detJ = det(Gcov) * 0.5 * this->layeredCS->giveLayerThickness(layer); return detJ *gp->giveWeight(); } diff --git a/src/sm/Elements/Shells/tr2shell7.h b/src/sm/Elements/Shells/tr2shell7.h index d147d1e6e..8ce536d12 100644 --- a/src/sm/Elements/Shells/tr2shell7.h +++ b/src/sm/Elements/Shells/tr2shell7.h @@ -35,9 +35,9 @@ #ifndef Tr2Shell7_h #define Tr2Shell7_h -#include "../sm/Elements/Shells/shell7base.h" -#include "../sm/CrossSections/layeredcrosssection.h" -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/Shells/shell7base.h" +#include "sm/CrossSections/layeredcrosssection.h" +#include "sm/Elements/nlstructuralelement.h" #include "nodalaveragingrecoverymodel.h" #define _IFT_Tr2Shell7_Name "tr2shell7" @@ -70,42 +70,41 @@ class Tr2Shell7 : public Shell7Base static IntArray orderingNodes; static IntArray orderingEdgeNodes; - virtual const IntArray &giveOrderingDofTypes() const; - virtual const IntArray &giveOrderingNodes() const; - virtual const IntArray &giveOrderingEdgeNodes() const; + const IntArray &giveOrderingDofTypes() const override; + const IntArray &giveOrderingNodes() const override; + const IntArray &giveOrderingEdgeNodes() const override; //specific - void giveSurfaceDofMapping(IntArray &answer, int iSurf) const; - void giveEdgeDofMapping(IntArray &answer, int iEdge) const; + void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override; + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; - virtual double computeVolumeAroundLayer(GaussPoint *mastergp, int layer); - virtual double computeAreaAround(GaussPoint *gp, double xi); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) + double computeVolumeAroundLayer(GaussPoint *mastergp, int layer) override; + double computeAreaAround(GaussPoint *gp, double xi) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("calling of this function is not allowed"); } - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("calling of this funciton is not allowed"); } - virtual void computeGaussPoints(); + void computeGaussPoints() override; //only used for debuging void compareMatrices(const FloatMatrix &matrix1, const FloatMatrix &matrix2, FloatMatrix &answer); - virtual FEInterpolation *giveInterpolation() const; - + FEInterpolation *giveInterpolation() const override; public: Tr2Shell7(int n, Domain * d); // constructor virtual ~Tr2Shell7() { } // destructor -> declaring as virtual will make each subclass call their respective destr. // definition & identification - virtual int giveNumberOfDofs() { return 42; } - virtual int giveNumberOfEdgeDofs() { return 21; } - virtual int giveNumberOfEdgeDofManagers() { return 3; } - virtual const char *giveInputRecordName() const { return _IFT_Tr2Shell7_Name; } - virtual const char *giveClassName() const { return "Tr2Shell7"; } - //virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_2; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_Composite; } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } // write new wedge-like type 'layeredWedge' + int giveNumberOfDofs() override { return 42; } + int giveNumberOfEdgeDofs() override { return 21; } + int giveNumberOfEdgeDofManagers() override { return 3; } + const char *giveInputRecordName() const override { return _IFT_Tr2Shell7_Name; } + const char *giveClassName() const override { return "Tr2Shell7"; } + //Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_2; } + Element_Geometry_Type giveGeometryType() const override { return EGT_Composite; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } // write new wedge-like type 'layeredWedge' - virtual void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIdArray); + void giveBoundaryLocationArray(IntArray &locationArray, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIdArray) override; }; } // end namespace oofem #endif diff --git a/src/sm/tr2shell7PhFi.C b/src/sm/Elements/Shells/tr2shell7PhFi.C similarity index 87% rename from src/sm/tr2shell7PhFi.C rename to src/sm/Elements/Shells/tr2shell7PhFi.C index 747fe872b..29deed54e 100644 --- a/src/sm/tr2shell7PhFi.C +++ b/src/sm/Elements/Shells/tr2shell7PhFi.C @@ -63,53 +63,48 @@ IntArray Tr2Shell7PhFi :: ordering_gr_edge(21); bool Tr2Shell7PhFi :: __initialized = Tr2Shell7PhFi :: initOrdering(); - Tr2Shell7PhFi:: Tr2Shell7PhFi(int n, Domain *aDomain) : Shell7BasePhFi(n, aDomain) { this->numberOfDofMans = 6; - - this->ordering_damage.resize(0); - this->ordering_gr.resize(0); + + this->ordering_damage.resize(0); + this->ordering_gr.resize(0); this->ordering_disp_inv.resize(0); - IntArray localDam, localDisp(7); // hard coded for 7 parameter shell!! + IntArray localDam, localDisp(7); // hard coded for 7 parameter shell!! - localDam.resize(0); - localDisp.setValues(7, 1, 2, 3, 19, 20, 21, 37); + localDam.resize(0); + localDisp.setValues(7, 1, 2, 3, 19, 20, 21, 37); - for (int i = 1; i <= numberOfLayers; i++) - { - //localDam.followedBy(i + this->giveNumberOfuDofs()); + for (int i = 1; i <= numberOfLayers; i++) { + //localDam.followedBy(i + this->giveNumberOfuDofs()); localDam.followedBy(7 + i); - } + } int numDofsPerNode = 7 + numberOfLayers; - for (int i = 1; i <= this->numberOfDofMans; i++) - { - this->ordering_damage.followedBy(localDam); - this->ordering_gr.followedBy(localDisp); - this->ordering_gr.followedBy(localDam); + for (int i = 1; i <= this->numberOfDofMans; i++) { + this->ordering_damage.followedBy(localDam); + this->ordering_gr.followedBy(localDisp); + this->ordering_gr.followedBy(localDam); this->ordering_disp_inv.followedBy(localDisp); - localDisp.at(1) += 3; - localDisp.at(2) += 3; - localDisp.at(3) += 3; - localDisp.at(4) += 3; - localDisp.at(5) += 3; - localDisp.at(6) += 3; - localDisp.at(7) += 1; - - localDam.add(numberOfLayers); - - } + localDisp.at(1) += 3; + localDisp.at(2) += 3; + localDisp.at(3) += 3; + localDisp.at(4) += 3; + localDisp.at(5) += 3; + localDisp.at(6) += 3; + localDisp.at(7) += 1; + localDam.add(numberOfLayers); + } - this->ordering_all.resize(0); - this->ordering_all = this->ordering_disp; - this->ordering_all.followedBy(ordering_damage); - + this->ordering_all.resize(0); + this->ordering_all = this->ordering_disp; + this->ordering_all.followedBy(ordering_damage); + // JB - New IntArray temp_x(0), temp_m(0), temp_dam(0), local_temp_x(0), local_temp_m(0), local_temp_gam(0), local_temp_dam(0); @@ -117,12 +112,11 @@ Tr2Shell7PhFi:: Tr2Shell7PhFi(int n, Domain *aDomain) : Shell7BasePhFi(n, aDomai temp_m.setValues(3, 4, 5, 6); int temp_gam = 7; - for (int i = 1; i <= numberOfLayers; i++) { + for (int i = 1; i <= numberOfLayers; i++) { temp_dam.followedBy(7 + i); - } + } - for (int i = 1; i <= this->numberOfDofMans; i++) - { + for (int i = 1; i <= this->numberOfDofMans; i++) { local_temp_x.followedBy(temp_x); local_temp_m.followedBy(temp_m); local_temp_gam.followedBy(temp_gam); @@ -136,7 +130,7 @@ Tr2Shell7PhFi:: Tr2Shell7PhFi(int n, Domain *aDomain) : Shell7BasePhFi(n, aDomai //local_temp_m.printYourself(); //local_temp_gam.printYourself(); //local_temp_dam.printYourself(); - + // Construct the two orddering arrays ordering_disp.resize(0); ordering_damage.resize(0); @@ -152,13 +146,13 @@ Tr2Shell7PhFi:: Tr2Shell7PhFi(int n, Domain *aDomain) : Shell7BasePhFi(n, aDomai void Tr2Shell7PhFi :: giveDofManDofIDMask_u(IntArray &answer) { - Shell7BasePhFi :: giveDofManDofIDMask_u(answer); + Shell7BasePhFi :: giveDofManDofIDMask_u(answer); } void Tr2Shell7PhFi :: giveDofManDofIDMask_d(IntArray &answer) { - Shell7BasePhFi :: giveDofManDofIDMask_d(answer); + Shell7BasePhFi :: giveDofManDofIDMask_d(answer); } const IntArray & @@ -166,7 +160,6 @@ Tr2Shell7PhFi:: giveOrdering(SolutionField fieldType) const { OOFEM_ERROR("Tr2Shell7PhFi :: giveOrdering not implemented: Use Tr2Shell7PhFi :: giveOrderingPhFi instead"); return 0; - } @@ -182,7 +175,7 @@ Tr2Shell7PhFi:: giveOrderingPhFi(SolutionFieldPhFi fieldType) const } else if ( fieldType == AllInv ) { return this->ordering_gr; } else { /*if ( fieldType == EdgeInv )*/ - OOFEM_ERROR("Tr2Shell7PhFi :: giveOrdering: the requested ordering is not implemented") + OOFEM_ERROR("Tr2Shell7PhFi :: giveOrdering: the requested ordering is not implemented") //return this->ordering_gr_edge; } } @@ -224,7 +217,6 @@ Tr2Shell7PhFi:: giveLocalNodeCoords(FloatArray &nodeLocalXiCoords, FloatArray &n FEInterpolation *Tr2Shell7PhFi:: giveInterpolation() const { return & interpolation; } - void Tr2Shell7PhFi:: computeGaussPoints() { @@ -263,8 +255,6 @@ Tr2Shell7PhFi:: computeGaussPoints() } - - void Tr2Shell7PhFi:: giveEdgeDofMapping(IntArray &answer, int iEdge) const { @@ -289,7 +279,7 @@ Tr2Shell7PhFi:: giveEdgeDofMapping(IntArray &answer, int iEdge) const void -Tr2Shell7PhFi:: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +Tr2Shell7PhFi::giveSurfaceDofMapping(IntArray &answer, int iSurf) const { answer.resize(42); for ( int i = 1; i <= 42; i++ ) { @@ -299,7 +289,7 @@ Tr2Shell7PhFi:: giveSurfaceDofMapping(IntArray &answer, int iSurf) const double -Tr2Shell7PhFi:: computeAreaAround(GaussPoint *gp, double xi) +Tr2Shell7PhFi::computeAreaAround(GaussPoint *gp, double xi) { FloatArray G1, G2, temp; FloatMatrix Gcov; @@ -316,9 +306,8 @@ Tr2Shell7PhFi:: computeAreaAround(GaussPoint *gp, double xi) } - double -Tr2Shell7PhFi:: computeVolumeAroundLayer(GaussPoint *gp, int layer) +Tr2Shell7PhFi::computeVolumeAroundLayer(GaussPoint *gp, int layer) { double detJ; FloatMatrix Gcov; @@ -353,4 +342,5 @@ Tr2Shell7PhFi:: compareMatrices(const FloatMatrix &matrix1, const FloatMatrix &m } } } + } // end namespace oofem diff --git a/src/sm/tr2shell7PhFi.H b/src/sm/Elements/Shells/tr2shell7PhFi.H similarity index 75% rename from src/sm/tr2shell7PhFi.H rename to src/sm/Elements/Shells/tr2shell7PhFi.H index 8594e290d..534586471 100644 --- a/src/sm/tr2shell7PhFi.H +++ b/src/sm/Elements/Shells/tr2shell7PhFi.H @@ -53,32 +53,31 @@ class BoundaryLoad; * Each node has 7 degrees of freedom for the displacement (displ. vec., director vec., inhomogeneous thickness strain ) and one degree of freedom for the damage per layer in the layered cross section. * Only valid for layered cross sections where each layer has the same thickness. NB! No check on that!!!! * Add ref. to paper! - * @author Martin Fagerström + * @author Martin Fagerström * @date 2014-06-12 */ - class Tr2Shell7PhFi : public Shell7BasePhFi { protected: static FEI3dTrQuad interpolation; static bool __initialized; static IntArray ordering_all; - static IntArray ordering_disp; + static IntArray ordering_disp; static IntArray ordering_disp_inv; static IntArray ordering_base; // regular ordering - same as in Shell7Base. Used for compatability with Shell7Base methods static IntArray ordering_base_inv; // inverse ordering - same as in Shell7Base. Used for compatability with Shell7Base methods - static IntArray ordering_damage; + static IntArray ordering_damage; static IntArray ordering_gr; static IntArray ordering_gr_edge; static bool initOrdering() { - //ordering_disp.setValues(42, 1, 2, 3, 8, 9, 10, 15, 16, 17, 22, 23, 24, 29, 30, 31, 36, 37, 38, // midx_i, midy_i, midz_i..., dirx_i,diry_i,dirz_i, ....,gamma_i + //ordering_disp.setValues(42, 1, 2, 3, 8, 9, 10, 15, 16, 17, 22, 23, 24, 29, 30, 31, 36, 37, 38, // midx_i, midy_i, midz_i..., dirx_i,diry_i,dirz_i, ....,gamma_i // 4, 5, 6, 11, 12, 13, 18, 19, 20, 25, 26, 27, 32, 33, 34, 39, 40, 41, // 7, 14, 21, 28, 35, 42); - // - //ordering_all.setValues(42, 1, 2, 3, 8, 9, 10, 15, 16, 17, 22, 23, 24, 29, 30, 31, 36, 37, 38, // midx_i, midy_i, midz_i..., dirx_i,diry_i,dirz_i, ....,gamma_i + // + //ordering_all.setValues(42, 1, 2, 3, 8, 9, 10, 15, 16, 17, 22, 23, 24, 29, 30, 31, 36, 37, 38, // midx_i, midy_i, midz_i..., dirx_i,diry_i,dirz_i, ....,gamma_i // 4, 5, 6, 11, 12, 13, 18, 19, 20, 25, 26, 27, 32, 33, 34, 39, 40, 41, // 7, 14, 21, 28, 35, 42); - ordering_base.setValues(42, 1, 2, 3, 8, 9, 10, 15, 16, 17, 22, 23, 24, 29, 30, 31, 36, 37, 38, // midx_i, midy_i, midz_i..., dirx_i,diry_i,dirz_i, ....,gamma_i + ordering_base.setValues(42, 1, 2, 3, 8, 9, 10, 15, 16, 17, 22, 23, 24, 29, 30, 31, 36, 37, 38, // midx_i, midy_i, midz_i..., dirx_i,diry_i,dirz_i, ....,gamma_i 4, 5, 6, 11, 12, 13, 18, 19, 20, 25, 26, 27, 32, 33, 34, 39, 40, 41, 7, 14, 21, 28, 35, 42); ordering_base_inv.setValues(42, 1, 2, 3, 19, 20, 21, 37, 4, 5, 6, 22, 23, 24, 38, 7, 8, 9, 25, 26, 27, 39, // from OOFEM -> element level @@ -88,7 +87,7 @@ protected: } virtual const IntArray &giveOrdering(SolutionField fieldType) const; - const IntArray &giveOrderingPhFi(SolutionFieldPhFi fieldType) const; + const IntArray &giveOrderingPhFi(SolutionFieldPhFi fieldType) const; virtual const IntArray &giveOrdering_All() const; virtual const IntArray &giveOrdering_AllInv() const; @@ -102,31 +101,30 @@ protected: virtual double computeVolumeAroundLayer(GaussPoint *mastergp, int layer); virtual double computeAreaAround(GaussPoint *gp, double xi); - virtual void computeGaussPoints(); + void computeGaussPoints() override; virtual void giveLocalNodeCoords(FloatArray &nodeLocalXiCoords, FloatArray &nodeLocalEtaCoords); //only used for debuging void compareMatrices(const FloatMatrix &matrix1, const FloatMatrix &matrix2, FloatMatrix &answer); - virtual FEInterpolation *giveInterpolation() const; - + FEInterpolation *giveInterpolation() const override; public: Tr2Shell7PhFi(int n, Domain *d); // constructor virtual ~Tr2Shell7PhFi() { } // destructor -> declaring as virtual will make each subclass call their respective destr. // definition & identification - NLStructuralElement *giveElement() { return this; } - virtual void giveDofManDofIDMask_u(IntArray &answer); - virtual void giveDofManDofIDMask_d(IntArray &answer); - - virtual int giveNumberOfDofs() { int a = Shell7BasePhFi :: giveNumberOfDofs(); return a;} - virtual int giveNumberOfEdgeDofs() { return 3*(7+this->numberOfLayers); } - virtual int giveNumberOfEdgeDofManagers() { return 3; } - virtual const char *giveInputRecordName() const { return _IFT_Tr2Shell7PhFi_Name; } - virtual const char *giveClassName() const { return "Tr2Shell7PhFi"; } - //virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_2; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_Composite; } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } // write new wedge-like type 'layeredWedge' + NLStructuralElement *giveElement() { return this; } + void giveDofManDofIDMask_u(IntArray &answer) override; + void giveDofManDofIDMask_d(IntArray &answer) override; + + int giveNumberOfDofs() override { int a = Shell7BasePhFi :: giveNumberOfDofs(); return a;} + int giveNumberOfEdgeDofs() override { return 3*(7+this->numberOfLayers); } + int giveNumberOfEdgeDofManagers() override { return 3; } + const char *giveInputRecordName() const override { return _IFT_Tr2Shell7PhFi_Name; } + const char *giveClassName() const override { return "Tr2Shell7PhFi"; } + //Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_2; } + Element_Geometry_Type giveGeometryType() const override { return EGT_Composite; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } // write new wedge-like type 'layeredWedge' }; } // end namespace oofem #endif diff --git a/src/sm/Elements/Shells/tr2shell7xfem.C b/src/sm/Elements/Shells/tr2shell7xfem.C index a88a2811d..677b818f4 100644 --- a/src/sm/Elements/Shells/tr2shell7xfem.C +++ b/src/sm/Elements/Shells/tr2shell7xfem.C @@ -32,10 +32,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Shells/tr2shell7xfem.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/xfem/enrichmentitems/crack.h" -#include "../sm/xfem/enrichmentitems/shellcrack.h" +#include "sm/Elements/Shells/tr2shell7xfem.h" +#include "sm/Materials/structuralms.h" +#include "sm/xfem/enrichmentitems/crack.h" +#include "sm/xfem/enrichmentitems/shellcrack.h" #include "node.h" #include "load.h" #include "mathfem.h" @@ -119,7 +119,7 @@ Tr2Shell7XFEM :: computeGaussPoints() int numberOfInterfaces = this->layeredCS->giveNumberOfLayers()-1; czIntegrationRulesArray.resize( numberOfInterfaces ); for ( int j = 0; j < numberOfInterfaces; j++ ) { - czIntegrationRulesArray [ j ].reset( new GaussIntegrationRule(1, this) ); + czIntegrationRulesArray [ j ] = std::make_unique(1, this); czIntegrationRulesArray [ j ]->SetUpPointsOnTriangle(nPointsTri, _3dInterface); } @@ -175,23 +175,21 @@ bool Tr2Shell7XFEM :: updateIntegrationRuleMultiCrack() this->XfemElementInterface_partitionElement(this->crackSubdivisions [ i ], pointPartitions [ j ]); } - - integrationRulesArray [ i ].reset( new PatchIntegrationRule(i + 1, this, this->crackSubdivisions [ i ]) ); - int nPointsTriSubTri = 3; - integrationRulesArray [ i ]->SetUpPointsOnWedge(nPointsTriSubTri, numPointsThickness, _3dMat); + integrationRulesArray [ i ] = std::make_unique(i + 1, this, this->crackSubdivisions [ i ]); + integrationRulesArray [ i ]->SetUpPointsOnWedge(3, numPointsThickness, _3dMat); this->numSubDivisionsArray [ i ] = this->crackSubdivisions [ i ].size(); - createdRule = true; + createdRule = true; continue; } - } + } } } } - + if( !createdRule ) { - integrationRulesArray [ i ].reset( new LayeredIntegrationRule(i + 1, this) ); + integrationRulesArray [ i ] = std::make_unique(i + 1, this); integrationRulesArray [ i ]->SetUpPointsOnWedge(nPointsTri, numPointsThickness, _3dMat); - this->numSubDivisionsArray [ i ] = 1; + this->numSubDivisionsArray [ i ] = 1; } } @@ -204,7 +202,7 @@ bool Tr2Shell7XFEM :: updateIntegrationRuleMultiCrack() int numberOfInterfaces = this->layeredCS->giveNumberOfLayers()-1; czIntegrationRulesArray.resize(numberOfInterfaces); for ( int j = 0; j < numberOfInterfaces; j++ ) { - czIntegrationRulesArray [ j ].reset( new GaussIntegrationRule(1, this) ); + czIntegrationRulesArray [ j ] = std::make_unique(1, this); czIntegrationRulesArray [ j ]->SetUpPointsOnTriangle(nPointsTri, _3dInterface); } } @@ -259,17 +257,15 @@ Tr2Shell7XFEM :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const double Tr2Shell7XFEM :: computeAreaAround(GaussPoint *gp, double xi) { - FloatArray G1, G2, temp; - FloatMatrix Gcov; - FloatArray lCoords(3); + FloatArrayF<3> lCoords; lCoords.at(1) = gp->giveNaturalCoordinate(1); lCoords.at(2) = gp->giveNaturalCoordinate(2); lCoords.at(3) = xi; - this->evalInitialCovarBaseVectorsAt(lCoords, Gcov); - G1.beColumnOf(Gcov,1); - G2.beColumnOf(Gcov,2); - temp.beVectorProductOf(G1, G2); - double detJ = temp.computeNorm(); + auto Gcov = this->evalInitialCovarBaseVectorsAt(lCoords); + auto G1 = Gcov.column(0); + auto G2 = Gcov.column(1); + auto temp = cross(G1, G2); + double detJ = norm(temp); return detJ *gp->giveWeight(); } @@ -277,16 +273,12 @@ Tr2Shell7XFEM :: computeAreaAround(GaussPoint *gp, double xi) double Tr2Shell7XFEM :: computeVolumeAroundLayer(GaussPoint *gp, int layer) { - double detJ; - FloatMatrix Gcov; - FloatArray lcoords; - lcoords = gp->giveNaturalCoordinates(); - this->evalInitialCovarBaseVectorsAt(lcoords, Gcov); - detJ = Gcov.giveDeterminant() * 0.5 * this->layeredCS->giveLayerThickness(layer); + const auto &lcoords = gp->giveNaturalCoordinates(); + auto Gcov = this->evalInitialCovarBaseVectorsAt(lcoords); + double detJ = det(Gcov) * 0.5 * this->layeredCS->giveLayerThickness(layer); return detJ *gp->giveWeight(); } - } // end namespace oofem diff --git a/src/sm/Elements/Shells/tr2shell7xfem.h b/src/sm/Elements/Shells/tr2shell7xfem.h index b0847ce9d..64c84e10d 100644 --- a/src/sm/Elements/Shells/tr2shell7xfem.h +++ b/src/sm/Elements/Shells/tr2shell7xfem.h @@ -35,9 +35,9 @@ #ifndef Tr2Shell7XFEM_h #define Tr2Shell7XFEM_h -#include "../sm/Elements/Shells/shell7basexfem.h" -#include "../sm/CrossSections/layeredcrosssection.h" -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/Shells/shell7basexfem.h" +#include "sm/CrossSections/layeredcrosssection.h" +#include "sm/Elements/nlstructuralelement.h" #include "nodalaveragingrecoverymodel.h" #define _IFT_Tr2Shell7XFEM_Name "tr2shell7xfem" @@ -53,7 +53,6 @@ class BoundaryLoad; * @author Jim Brouzoulis * @date 2012-11-01 */ - class Tr2Shell7XFEM : public Shell7BaseXFEM { protected: @@ -62,27 +61,26 @@ class Tr2Shell7XFEM : public Shell7BaseXFEM static IntArray orderingNodes; static IntArray orderingEdgeNodes; - virtual const IntArray &giveOrderingDofTypes() const; - virtual const IntArray &giveOrderingNodes() const; - virtual const IntArray &giveOrderingEdgeNodes() const; - virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const; - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - + const IntArray &giveOrderingDofTypes() const override; + const IntArray &giveOrderingNodes() const override; + const IntArray &giveOrderingEdgeNodes() const override; + void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override; + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; - virtual double computeVolumeAroundLayer(GaussPoint *mastergp, int layer); - virtual double computeAreaAround(GaussPoint *gp, double xi); + double computeVolumeAroundLayer(GaussPoint *mastergp, int layer) override; + double computeAreaAround(GaussPoint *gp, double xi) override; - virtual void computeGaussPoints(); + void computeGaussPoints() override; bool updateIntegrationRuleMultiCrack(); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("calling of this function is not allowed"); } - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("calling of this funciton is not allowed"); } virtual void giveLocalNodeCoords(FloatArray &nodeLocalXiCoords, FloatArray &nodeLocalEtaCoords); - virtual FEInterpolation *giveInterpolation() const; - virtual double computeArea(); + FEInterpolation *giveInterpolation() const override; + double computeArea() override; // VTK void vtkGiveUpdatedFictiousNodeCoords(FloatArray nodeCoords [ 15 ], int layer, TimeStep *tStep); @@ -90,13 +88,13 @@ class Tr2Shell7XFEM : public Shell7BaseXFEM Tr2Shell7XFEM(int n, Domain * d); virtual ~Tr2Shell7XFEM() { } // destructor -> declaring as virtual will make each subclass call their respective destr. // definition & identification - virtual int giveNumberOfEdgeDofs() { return 21; } - virtual int giveNumberOfEdgeDofManagers() { return 3; } - virtual const char *giveInputRecordName() const { return _IFT_Tr2Shell7XFEM_Name; } - virtual const char *giveClassName() const { return "Tr2Shell7XFEM"; } + int giveNumberOfEdgeDofs() override { return 21; } + int giveNumberOfEdgeDofManagers() override { return 3; } + const char *giveInputRecordName() const override { return _IFT_Tr2Shell7XFEM_Name; } + const char *giveClassName() const override { return "Tr2Shell7XFEM"; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_Composite; } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } // write new wedge-like type 'layeredWedge' + Element_Geometry_Type giveGeometryType() const override { return EGT_Composite; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } // write new wedge-like type 'layeredWedge' }; } // end namespace oofem #endif diff --git a/src/sm/Elements/Shells/tr_shell01.C b/src/sm/Elements/Shells/tr_shell01.C index fc53a681c..05050afc1 100644 --- a/src/sm/Elements/Shells/tr_shell01.C +++ b/src/sm/Elements/Shells/tr_shell01.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Shells/tr_shell01.h" +#include "sm/Elements/Shells/tr_shell01.h" #include "fei2dtrlin.h" #include "contextioerr.h" #include "gaussintegrationrule.h" @@ -54,20 +54,20 @@ IntArray TR_SHELL01 :: loc_plate = {3, 4, 5, 9, 10, 11, 15, 16, 17}; IntArray TR_SHELL01 :: loc_membrane = {1, 2, 6, 7, 8, 12, 13, 14, 18}; TR_SHELL01 :: TR_SHELL01(int n, Domain *aDomain) : StructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this), ZZErrorEstimatorInterface(this), SpatialLocalizerInterface(this), - plate(new CCTPlate3d(-1, aDomain)), membrane(new TrPlaneStrRot3d(-1, aDomain)) + plate(std::make_unique(-1, aDomain)), + membrane(std::make_unique(-1, aDomain)) { numberOfDofMans = 3; } -IRResultType -TR_SHELL01 :: initializeFrom(InputRecord *ir) +void +TR_SHELL01 :: initializeFrom(InputRecord &ir) { // proc tady neni return = this... ??? termitovo - IRResultType result = StructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralElement :: initializeFrom(ir); + plate->initializeFrom(ir); + membrane->initializeFrom(ir); #if 0 IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_Element_nip); @@ -81,17 +81,6 @@ TR_SHELL01 :: initializeFrom(InputRecord *ir) return result; } #endif - - result = plate->initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - result = membrane->initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - return IRRT_OK; } void @@ -100,7 +89,9 @@ TR_SHELL01 :: postInitialize() StructuralElement :: postInitialize(); if ( plate->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints() != membrane->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints() ) { - OOFEM_ERROR("incompatible integration rules detected"); + OOFEM_ERROR("incompatible integration rules detected %d vs %d IPs", + plate->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints(), + membrane->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints()); } } @@ -312,48 +303,43 @@ TR_SHELL01 :: printOutputAt(FILE *file, TimeStep *tStep) fprintf(file, " %.4e %.4e %.4e %.4e %.4e %.4e ", v.at(1), v.at(2), v.at(3), v.at(4), v.at(5), v.at(6) ); + if ( gp->hasSlaveGaussPoint()) { // layered material + fprintf(file, "\n Layers report {\n"); + + for (auto &sgp: gp->giveSlaveGaussPoints()) { + sgp->printOutputAt(file, tStep, " "); + } + fprintf(file, " }\n"); + + } + + fprintf(file, "\n"); } } -contextIOResultType -TR_SHELL01 :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +TR_SHELL01 :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = StructuralElement :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( ( iores = this->plate->saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( ( iores = this->membrane->saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - return iores; + StructuralElement :: saveContext(stream, mode); + this->plate->saveContext(stream, mode); + this->membrane->saveContext(stream, mode); } -contextIOResultType -TR_SHELL01 :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +TR_SHELL01 :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = StructuralElement :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( ( iores = this->plate->restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( ( iores = this->membrane->restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - return iores; + StructuralElement :: restoreContext(stream, mode); + this->plate->restoreContext(stream, mode); + this->membrane->restoreContext(stream, mode); } IntegrationRule * TR_SHELL01 :: ZZErrorEstimatorI_giveIntegrationRule() { if ( !this->compositeIR ) { - this->compositeIR.reset( new GaussIntegrationRule(1, this, 1, 12) ); + this->compositeIR = std::make_unique(1, this, 1, 12); this->compositeIR->SetUpPointsOnTriangle(plate->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints(), _3dShell); } return this->compositeIR.get(); @@ -432,9 +418,9 @@ TR_SHELL01 :: SpatialLocalizerI_giveBBox(FloatArray &bb0, FloatArray &bb1) FloatArray _c; for ( int i = 1; i <= this->giveNumberOfNodes(); ++i ) { - FloatArray *coordinates = this->giveNode(i)->giveCoordinates(); + const auto &coordinates = this->giveNode(i)->giveCoordinates(); - _c = * coordinates; + _c = coordinates; _c.add(gt3); if ( i == 1 ) { bb0 = bb1 = _c; @@ -443,7 +429,7 @@ TR_SHELL01 :: SpatialLocalizerI_giveBBox(FloatArray &bb0, FloatArray &bb1) bb1.beMaxOf(bb1, _c); } - _c = * coordinates; + _c = coordinates; _c.subtract(gt3); bb0.beMinOf(bb0, _c); bb1.beMaxOf(bb1, _c); @@ -465,7 +451,7 @@ TR_SHELL01 :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) return; } - if ( this->giveMaterial()->isActivated(tStep) ) { + if ( this->isActivated(tStep) ) { EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); EASValsSetColor( gc.getElementColor() ); EASValsSetEdgeColor( gc.getElementEdgeColor() ); @@ -500,7 +486,7 @@ TR_SHELL01 :: drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, Unk return; } - if ( this->giveMaterial()->isActivated(tStep) ) { + if ( this->isActivated(tStep) ) { EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH); EASValsSetColor( gc.getDeformedElementColor() ); EASValsSetEdgeColor( gc.getElementEdgeColor() ); @@ -535,7 +521,7 @@ TR_SHELL01 :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) return; } - if ( !this->giveMaterial()->isActivated(tStep) ) { + if ( !this->isActivated(tStep) ) { return; } diff --git a/src/sm/Elements/Shells/tr_shell01.h b/src/sm/Elements/Shells/tr_shell01.h index fc8ed3b7b..16a246e99 100644 --- a/src/sm/Elements/Shells/tr_shell01.h +++ b/src/sm/Elements/Shells/tr_shell01.h @@ -35,11 +35,11 @@ #ifndef tr_shell01_h #define tr_shell01_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "zznodalrecoverymodel.h" -#include "../sm/ErrorEstimators/zzerrorestimator.h" -#include "../sm/Elements/Shells/cct3d.h" -#include "../sm/Elements/PlaneStress/trplanrot3d.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" +#include "sm/Elements/Shells/cct3d.h" +#include "sm/Elements/PlaneStress/trplanrot3d.h" #include "spatiallocalizer.h" #include @@ -77,87 +77,86 @@ class TR_SHELL01 : public StructuralElement, public ZZNodalRecoveryModelInterfac /// Destructor virtual ~TR_SHELL01() {} - virtual FEInterpolation *giveInterpolation() const { return plate->giveInterpolation(); } + FEInterpolation *giveInterpolation() const override { return plate->giveInterpolation(); } - virtual int computeNumberOfDofs() { return 18; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const + int computeNumberOfDofs() override { return 18; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override { plate->giveDofManDofIDMask(inode, answer); } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_TR_SHELL01_Name; } - virtual const char *giveClassName() const { return "TR_SHELL01"; } - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual void giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, TimeStep *tStep); - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep); - virtual double computeVolumeAround(GaussPoint *gp); - virtual bool giveRotationMatrix(FloatMatrix &answer); - - virtual void updateYourself(TimeStep *tStep); - virtual void updateInternalState(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual void postInitialize(); - void updateLocalNumbering(EntityRenumberingFunctor &f); - void setCrossSection(int csIndx); + const char *giveInputRecordName() const override { return _IFT_TR_SHELL01_Name; } + const char *giveClassName() const override { return "TR_SHELL01"; } + void initializeFrom(InputRecord &ir) override; + + void giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, TimeStep *tStep) override; + void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) override; + double computeVolumeAround(GaussPoint *gp) override; + bool giveRotationMatrix(FloatMatrix &answer) override; + + void updateYourself(TimeStep *tStep) override; + void updateInternalState(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + void postInitialize() override; + void updateLocalNumbering(EntityRenumberingFunctor &f) override; + void setCrossSection(int csIndx) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // the membrane and plate irules are same (chacked in initializeFrom) - virtual int giveDefaultIntegrationRule() const { return plate->giveDefaultIntegrationRule(); } - virtual IntegrationRule *giveDefaultIntegrationRulePtr() { return plate->giveDefaultIntegrationRulePtr(); } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_1; } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } - virtual MaterialMode giveMaterialMode() { return _Unknown; } + int giveDefaultIntegrationRule() const override { return plate->giveDefaultIntegrationRule(); } + IntegrationRule *giveDefaultIntegrationRulePtr() override { return plate->giveDefaultIntegrationRulePtr(); } + IntegrationRule *giveIntegrationRule(int i) override { return plate->giveIntegrationRule(i); } + Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_1; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } + MaterialMode giveMaterialMode() override { return _Unknown; } - virtual Interface *giveInterface(InterfaceType it); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + Interface *giveInterface(InterfaceType it) override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual IntegrationRule *ZZErrorEstimatorI_giveIntegrationRule(); - virtual void ZZErrorEstimatorI_computeLocalStress(FloatArray &answer, FloatArray &sig); + IntegrationRule *ZZErrorEstimatorI_giveIntegrationRule() override; + void ZZErrorEstimatorI_computeLocalStress(FloatArray &answer, FloatArray &sig) override; // SpatialLocalizerI - virtual void SpatialLocalizerI_giveBBox(FloatArray &bb0, FloatArray &bb1); + void SpatialLocalizerI_giveBBox(FloatArray &bb0, FloatArray &bb1) override; - - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override { return this->plate->computeGlobalCoordinates(answer, lcoords); } - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) { + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override { return this->plate->computeLocalCoordinates(answer, gcoords); } protected: - virtual void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override { OOFEM_ERROR("calling of this function is not allowed"); } - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &) + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &) override { OOFEM_ERROR("calling of this function is not allowed"); } - /// @todo In time delete protected: - virtual void computeGaussPoints() + void computeGaussPoints() override { this->membrane->computeGaussPoints(); this->plate->computeGaussPoints(); } - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("calling of this function is not allowed"); } - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("calling of this function is not allowed"); } - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode); + void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) override; public: - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { OOFEM_ERROR("calling of this function is not allowed"); } - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { OOFEM_ERROR("calling of this function is not allowed"); } - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override { OOFEM_ERROR("calling of this function is not allowed"); } }; } // end namespace oofem diff --git a/src/sm/Elements/Shells/tr_shell02.C b/src/sm/Elements/Shells/tr_shell02.C index 5fe398121..14a909e12 100644 --- a/src/sm/Elements/Shells/tr_shell02.C +++ b/src/sm/Elements/Shells/tr_shell02.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/Shells/tr_shell02.h" +#include "sm/Elements/Shells/tr_shell02.h" #include "fei2dtrlin.h" #include "contextioerr.h" #include "gaussintegrationrule.h" @@ -55,32 +55,20 @@ IntArray TR_SHELL02 :: loc_plate = {3, 4, 5, 9, 10, 11, 15, 16, 17}; IntArray TR_SHELL02 :: loc_membrane = {1, 2, 6, 7, 8, 12, 13, 14, 18}; TR_SHELL02 :: TR_SHELL02(int n, Domain *aDomain) : StructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this), ZZErrorEstimatorInterface(this), SpatialLocalizerInterface(this), - plate(new DKTPlate3d(-1, aDomain)), membrane(new TrPlanestressRotAllman3d(-1, aDomain)) + plate(std::make_unique(-1, aDomain)), + membrane(std::make_unique(-1, aDomain)) { numberOfDofMans = 3; } -IRResultType -TR_SHELL02 :: initializeFrom(InputRecord *ir) +void +TR_SHELL02 :: initializeFrom(InputRecord &ir) { // proc tady neni return = this... ??? termitovo - IRResultType result = StructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - result = plate->initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - result = membrane->initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - return IRRT_OK; + StructuralElement :: initializeFrom(ir); + plate->initializeFrom(ir); + membrane->initializeFrom(ir); } void @@ -304,44 +292,29 @@ TR_SHELL02 :: printOutputAt(FILE *file, TimeStep *tStep) } - -contextIOResultType -TR_SHELL02 :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +TR_SHELL02 :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = StructuralElement :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( ( iores = this->plate->saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( ( iores = this->membrane->saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - return iores; + StructuralElement :: saveContext(stream, mode); + this->plate->saveContext(stream, mode); + this->membrane->saveContext(stream, mode); } -contextIOResultType -TR_SHELL02 :: restoreContext(DataStream &stream, ContextMode mode, void *obj) + +void +TR_SHELL02 :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = StructuralElement :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( ( iores = this->plate->restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( ( iores = this->membrane->restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - return iores; + StructuralElement :: restoreContext(stream, mode); + this->plate->restoreContext(stream, mode); + this->membrane->restoreContext(stream, mode); } + IntegrationRule * TR_SHELL02 :: ZZErrorEstimatorI_giveIntegrationRule() { if ( !this->compositeIR ) { - this->compositeIR.reset( new GaussIntegrationRule(1, this, 1, 12) ); + this->compositeIR = std::make_unique(1, this, 1, 12); this->compositeIR->SetUpPointsOnTriangle(plate->giveDefaultIntegrationRulePtr()->giveNumberOfIntegrationPoints(), _3dShell); } return this->compositeIR.get(); @@ -420,9 +393,9 @@ TR_SHELL02 :: SpatialLocalizerI_giveBBox(FloatArray &bb0, FloatArray &bb1) FloatArray _c; for ( int i = 1; i <= this->giveNumberOfNodes(); ++i ) { - FloatArray *coordinates = this->giveNode(i)->giveCoordinates(); + const auto &coordinates = this->giveNode(i)->giveCoordinates(); - _c = * coordinates; + _c = coordinates; _c.add(gt3); if ( i == 1 ) { bb0 = bb1 = _c; @@ -431,7 +404,7 @@ TR_SHELL02 :: SpatialLocalizerI_giveBBox(FloatArray &bb0, FloatArray &bb1) bb1.beMaxOf(bb1, _c); } - _c = * coordinates; + _c = coordinates; _c.subtract(gt3); bb0.beMinOf(bb0, _c); bb1.beMaxOf(bb1, _c); diff --git a/src/sm/Elements/Shells/tr_shell02.h b/src/sm/Elements/Shells/tr_shell02.h index a98752de7..65203f9e0 100644 --- a/src/sm/Elements/Shells/tr_shell02.h +++ b/src/sm/Elements/Shells/tr_shell02.h @@ -35,11 +35,11 @@ #ifndef tr_shell02_h #define tr_shell02_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "zznodalrecoverymodel.h" -#include "../sm/ErrorEstimators/zzerrorestimator.h" -#include "../sm/Elements/Plates/dkt3d.h" -#include "../sm/Elements/PlaneStress/trplanestressrotallman3d.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" +#include "sm/Elements/Plates/dkt3d.h" +#include "sm/Elements/PlaneStress/trplanestressrotallman3d.h" #include "spatiallocalizer.h" #include @@ -76,88 +76,87 @@ class TR_SHELL02 : public StructuralElement, public ZZNodalRecoveryModelInterfac /// Destructor virtual ~TR_SHELL02() {} - virtual FEInterpolation *giveInterpolation() const { return plate->giveInterpolation(); } + FEInterpolation *giveInterpolation() const override { return plate->giveInterpolation(); } - virtual int computeNumberOfDofs() { return 18; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const + int computeNumberOfDofs() override { return 18; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override { plate->giveDofManDofIDMask(inode, answer); } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_TR_SHELL02_Name; } - virtual const char *giveClassName() const { return "TR_SHELL02"; } - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual void giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, TimeStep *tStep); - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep); - virtual double computeVolumeAround(GaussPoint *gp); - virtual bool giveRotationMatrix(FloatMatrix &answer); - - virtual void updateYourself(TimeStep *tStep); - virtual void updateInternalState(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual void postInitialize(); - void updateLocalNumbering(EntityRenumberingFunctor &f); - void setCrossSection(int csIndx); + const char *giveInputRecordName() const override { return _IFT_TR_SHELL02_Name; } + const char *giveClassName() const override { return "TR_SHELL02"; } + void initializeFrom(InputRecord &ir) override; + + void giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, TimeStep *tStep) override; + void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) override; + double computeVolumeAround(GaussPoint *gp) override; + bool giveRotationMatrix(FloatMatrix &answer) override; + + void updateYourself(TimeStep *tStep) override; + void updateInternalState(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + void postInitialize() override; + void updateLocalNumbering(EntityRenumberingFunctor &f) override; + void setCrossSection(int csIndx) override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType type) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // the membrane and plate irules are same (chacked in initializeFrom) - virtual int giveDefaultIntegrationRule() const { return plate->giveDefaultIntegrationRule(); } - virtual IntegrationRule *giveDefaultIntegrationRulePtr() { return plate->giveDefaultIntegrationRulePtr(); } - virtual IntegrationRule *giveIntegrationRule(int i) { return plate->giveIntegrationRule(i); } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_1; } - virtual integrationDomain giveIntegrationDomain() const { return _Triangle; } - virtual MaterialMode giveMaterialMode() { return _Unknown; } + int giveDefaultIntegrationRule() const override { return plate->giveDefaultIntegrationRule(); } + IntegrationRule *giveDefaultIntegrationRulePtr() override { return plate->giveDefaultIntegrationRulePtr(); } + IntegrationRule *giveIntegrationRule(int i) override { return plate->giveIntegrationRule(i); } + Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_1; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } + MaterialMode giveMaterialMode() override { return _Unknown; } - virtual Interface *giveInterface(InterfaceType it); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + Interface *giveInterface(InterfaceType it) override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, - InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; - virtual IntegrationRule *ZZErrorEstimatorI_giveIntegrationRule(); - virtual void ZZErrorEstimatorI_computeLocalStress(FloatArray &answer, FloatArray &sig); + IntegrationRule *ZZErrorEstimatorI_giveIntegrationRule() override; + void ZZErrorEstimatorI_computeLocalStress(FloatArray &answer, FloatArray &sig) override; // SpatialLocalizerI - virtual void SpatialLocalizerI_giveBBox(FloatArray &bb0, FloatArray &bb1); + void SpatialLocalizerI_giveBBox(FloatArray &bb0, FloatArray &bb1) override; - - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) { + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override { return this->plate->computeGlobalCoordinates(answer, lcoords); } - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) { + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override { return this->plate->computeLocalCoordinates(answer, gcoords); } protected: - virtual void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override { OOFEM_ERROR("calling of this function is not allowed"); } - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &) + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &) override { OOFEM_ERROR("calling of this function is not allowed"); } /// @todo In time delete protected: - virtual void computeGaussPoints() + void computeGaussPoints() override { this->membrane->computeGaussPoints(); this->plate->computeGaussPoints(); } - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("calling of this function is not allowed"); } - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("calling of this funciton is not allowed"); } - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode); + void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) override; public: - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { OOFEM_ERROR("calling of this function is not allowed"); } - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { OOFEM_ERROR("calling of this function is not allowed"); } - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override { OOFEM_ERROR("calling of this function is not allowed"); } }; } // end namespace oofem diff --git a/src/sm/Elements/Shells/tr_shell11.C b/src/sm/Elements/Shells/tr_shell11.C new file mode 100644 index 000000000..bcd2cc2c9 --- /dev/null +++ b/src/sm/Elements/Shells/tr_shell11.C @@ -0,0 +1,1012 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/Shells/tr_shell11.h" +#include "fei2dtrlin.h" +#include "contextioerr.h" +#include "gaussintegrationrule.h" +#include "gausspoint.h" +#include "classfactory.h" +#include "node.h" +#include "sm/Materials/structuralms.h" +#include "load.h" + +namespace oofem { +REGISTER_Element(TR_SHELL11); + +FEI2dTrLin TR_SHELL11 :: interp_lin(1, 2); + + +TR_SHELL11 :: TR_SHELL11(int n, Domain *aDomain) : StructuralElement(n, aDomain), ZZNodalRecoveryModelInterface(this), ZZErrorEstimatorInterface(this), SpatialLocalizerInterface(this) +{ + numberOfDofMans = 3; + numberOfGaussPoints = 4; + numberOfRotGaussPoints = 1; + area = 0.0; +} + +void +TR_SHELL11 :: computeGaussPoints() +// Sets up the array containing the four Gauss points of the receiver. +{ + if ( integrationRulesArray.size() == 0 ) { + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); + this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); + } +} + +FloatArray +TR_SHELL11 :: GiveDerivativeUX(const FloatArray &lCoords) +{ + // get node coordinates + FloatArray x(3), y(3); + this->giveNodeCoordinates(x, y); + + // + FloatArray b(3), c(3), d(3); + + for ( int i = 1; i <= 3; i++ ) { + int j = i + 1 - i / 3 * 3; + int k = j + 1 - j / 3 * 3; + b.at(i) = y.at(j) - y.at(k); + c.at(i) = x.at(k) - x.at(j); + d.at(i) = sqrt( b.at(i) * b.at(i) + c.at(i) * c.at(i) ); + } + + // + FloatArray angles = this->GivePitch(); + + // + FloatArray shapeFunct(3); + shapeFunct.at(1) = lCoords.at(1); + shapeFunct.at(2) = lCoords.at(2); + shapeFunct.at(3) = 1.0 - shapeFunct.at(1) - shapeFunct.at(2); + + // + FloatArray nx(3); + + for ( int i = 1; i <= 3; i++ ) { + int j = i + 1 - i / 3 * 3; + int k = j + 1 - j / 3 * 3; + nx.at(i) = ( d.at(j) / 2. * ( b.at(k) * shapeFunct.at(i) + shapeFunct.at(k) * b.at(i) ) * sin( angles.at(j) ) - + d.at(k) / 2. * ( b.at(i) * shapeFunct.at(j) + shapeFunct.at(i) * b.at(j) ) * sin( angles.at(k) ) ); + } + + return nx; +} + + +FloatArray +TR_SHELL11 :: GiveDerivativeVX(const FloatArray &lCoords) +{ + // get node coordinates + FloatArray x(3), y(3); + this->giveNodeCoordinates(x, y); + + // + FloatArray b(3), c(3), d(3); + + for ( int i = 1; i <= 3; i++ ) { + int j = i + 1 - i / 3 * 3; + int k = j + 1 - j / 3 * 3; + b.at(i) = y.at(j) - y.at(k); + c.at(i) = x.at(k) - x.at(j); + d.at(i) = sqrt( b.at(i) * b.at(i) + c.at(i) * c.at(i) ); + } + + // + FloatArray angles = this->GivePitch(); + + // + FloatArray shapeFunct(3); + shapeFunct.at(1) = lCoords.at(1); + shapeFunct.at(2) = lCoords.at(2); + shapeFunct.at(3) = 1.0 - shapeFunct.at(1) - shapeFunct.at(2); + + // + FloatArray nx(3); + + for ( int i = 1; i <= 3; i++ ) { + int j = i + 1 - i / 3 * 3; + int k = j + 1 - j / 3 * 3; + nx.at(i) = ( d.at(j) / 2. * ( b.at(k) * shapeFunct.at(i) + shapeFunct.at(k) * b.at(i) ) * cos( angles.at(j) ) - + d.at(k) / 2. * ( b.at(i) * shapeFunct.at(j) + shapeFunct.at(i) * b.at(j) ) * cos( angles.at(k) ) ) * ( -1.0 ); + } + + return nx; +} + + +FloatArray +TR_SHELL11 :: GiveDerivativeUY(const FloatArray &lCoords) +{ + // get node coordinates + FloatArray x(3), y(3); + this->giveNodeCoordinates(x, y); + + // + FloatArray b(3), c(3), d(3); + + for ( int i = 1; i <= 3; i++ ) { + int j = i + 1 - i / 3 * 3; + int k = j + 1 - j / 3 * 3; + b.at(i) = y.at(j) - y.at(k); + c.at(i) = x.at(k) - x.at(j); + d.at(i) = sqrt( b.at(i) * b.at(i) + c.at(i) * c.at(i) ); + } + + // + FloatArray angles = this->GivePitch(); + + // + FloatArray shapeFunct(3); + shapeFunct.at(1) = lCoords.at(1); + shapeFunct.at(2) = lCoords.at(2); + shapeFunct.at(3) = 1.0 - shapeFunct.at(1) - shapeFunct.at(2); + + // + FloatArray ny(3); + + for ( int i = 1; i <= 3; i++ ) { + int j = i + 1 - i / 3 * 3; + int k = j + 1 - j / 3 * 3; + ny.at(i) = ( d.at(j) / 2. * ( c.at(k) * shapeFunct.at(i) + shapeFunct.at(k) * c.at(i) ) * sin( angles.at(j) ) - + d.at(k) / 2. * ( c.at(i) * shapeFunct.at(j) + shapeFunct.at(i) * c.at(j) ) * sin( angles.at(k) ) ); + } + + return ny; +} + + +FloatArray +TR_SHELL11 :: GiveDerivativeVY(const FloatArray &lCoords) +{ + // get node coordinates + FloatArray x(3), y(3); + this->giveNodeCoordinates(x, y); + + // + FloatArray b(3), c(3), d(3); + + for ( int i = 1; i <= 3; i++ ) { + int j = i + 1 - i / 3 * 3; + int k = j + 1 - j / 3 * 3; + b.at(i) = y.at(j) - y.at(k); + c.at(i) = x.at(k) - x.at(j); + d.at(i) = sqrt( b.at(i) * b.at(i) + c.at(i) * c.at(i) ); + } + + // + FloatArray angles = this->GivePitch(); + + // + FloatArray shapeFunct(3); + shapeFunct.at(1) = lCoords.at(1); + shapeFunct.at(2) = lCoords.at(2); + shapeFunct.at(3) = 1.0 - shapeFunct.at(1) - shapeFunct.at(2); + + // + FloatArray ny(3); + + for ( int i = 1; i <= 3; i++ ) { + int j = i + 1 - i / 3 * 3; + int k = j + 1 - j / 3 * 3; + ny.at(i) = ( d.at(j) / 2. * ( c.at(k) * shapeFunct.at(i) + shapeFunct.at(k) * c.at(i) ) * cos( angles.at(j) ) - + d.at(k) / 2. * ( c.at(i) * shapeFunct.at(j) + shapeFunct.at(i) * c.at(j) ) * cos( angles.at(k) ) ) * ( -1.0 ); + } + + return ny; +} + +FloatArray +TR_SHELL11 :: GivePitch() +// Returns angles between each side and global x-axis +{ + // get node coordinates + FloatArray x(3), y(3); + this->giveNodeCoordinates(x, y); + + // + FloatArray angles(3); + + for ( int i = 0; i < 3; i++ ) { + int j = i + 1 - i / 2 * 3; + int k = j + 1 - j / 2 * 3; + if ( x(k) == x(j) ) { + if ( y(k) > y(j) ) { + angles.at(i + 1) = M_PI / 2.; + } else { + angles.at(i + 1) = M_PI * 3. / 2.; + } + } + + if ( x(k) > x(j) ) { + if ( y(k) >= y(j) ) { + angles.at(i + 1) = atan( ( y(k) - y(j) ) / ( x(k) - x(j) ) ); + } else { + angles.at(i + 1) = 2. * M_PI - atan( ( y(j) - y(k) ) / ( x(k) - x(j) ) ); + } + } + + if ( x(k) < x(j) ) { + if ( y(k) >= y(j) ) { + angles.at(i + 1) = M_PI - atan( ( y(k) - y(j) ) / ( x(j) - x(k) ) ); + } else { + angles.at(i + 1) = M_PI + atan( ( y(j) - y(k) ) / ( x(j) - x(k) ) ); + } + } + } + + return angles; +} + +void +TR_SHELL11 :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +// Returns part of strain-displacement matrix {B} of the receiver, +// (epsilon_x,epsilon_y,gamma_xy) = B . r +// type of this part is [3,9] r=(u1,w1,fi1,u2,w2,fi2,u3,w3,fi3) +// evaluated at gp. +// strainVectorShell {eps_x,eps_y,gamma_xy, kappa_x, kappa_y, kappa_xy, gamma_zx, gamma_zy, gamma_rot} +{ + // get node coordinates + FloatArray x(3), y(3); + this->giveNodeCoordinates(x, y); + + FloatArray l(3), b(3), c(3); + + for ( int i = 1; i <= 3; i++ ) { + int j = i + 1 - i / 3 * 3; + int k = j + 1 - j / 3 * 3; + b.at(i) = y.at(j) - y.at(k); + c.at(i) = x.at(k) - x.at(j); + if (i<3) { + l.at(i) = gp->giveNaturalCoordinate(i); + } + } + l.at(3) = 1.-l.at(1)-l.at(2); + + // Derivatives of the shape functions (for this special interpolation) + FloatArray nx = this->GiveDerivativeUX(gp->giveNaturalCoordinates()); + FloatArray ny = this->GiveDerivativeVY(gp->giveNaturalCoordinates()); + + FloatArray center = {0.33333333, 0.33333333}; + FloatArray nxRed = this->GiveDerivativeVX( center ); + FloatArray nyRed = this->GiveDerivativeUY( center ); + + // These are the regular shape functions of a linear triangle evaluated at the center + FloatArray lc = { center.at(1), center.at(2), 1.0 - center.at(1) - center.at(2) }; // = {0, 0, 1} + + double area = this->giveArea(); + double detJ = 1.0 / ( 2.0 * area ); + answer.resize(9, 18); + for ( int i = 1; i <= 3; i++ ) { + int j = i + 1 - i / 3 * 3; + int k = j + 1 - j / 3 * 3; + // eps_x + answer.at(1, 6 * i - 5) = b.at(i) * detJ; + answer.at(1, 6 * i - 0) = nx.at(i) * detJ; + + // eps_y + answer.at(2, 6 * i - 4) = c.at(i) * detJ; + answer.at(2, 6 * i - 0) = ny.at(i) * detJ; + + ///@note The third strain component is evaluated at the element center just as for reduced + ///integration (component 4 below), should it be like this? /JB + // eps_xy + answer.at(3, 6 * i - 5) = c.at(i) * detJ; + answer.at(3, 6 * i - 4) = b.at(i) * detJ; + answer.at(3, 6 * i - 0) = ( nxRed.at(i) + nyRed.at(i) ) * detJ; + + // kappa_x + answer.at(4, 6*i - 1) = b.at(i)*detJ; + // kappa_y + answer.at(5, 6*i - 2) =-c.at(i)*detJ; + // kappa_xy + answer.at(6, 6*i - 2) =-b.at(i)*detJ; + answer.at(6, 6*i - 1) = c.at(i)*detJ; + // gamma_zx + answer.at(7, 6*i - 3) = b.at(i)*detJ; + answer.at(7, 6*i - 2) = (-b.at(i)*b.at(k)*lc.at(j) + b.at(i)*b.at(j)*lc.at(k))*0.5*detJ; + answer.at(7, 6*i - 1) = (-b.at(i)*c.at(k)*lc.at(j)-b.at(j)*c.at(k)*lc.at(i)+b.at(k)*c.at(j)*lc.at(i)+b.at(i)*c.at(j)*lc.at(k))*0.5*detJ+lc.at(i)*2.0*area*detJ; + // gamma_zy + answer.at(8, 6*i - 3) = c.at(i)*detJ; + answer.at(8, 6*i - 2) = (-b.at(k)*c.at(i)*lc.at(j)-b.at(k)*c.at(j)*lc.at(i)+b.at(j)*c.at(k)*lc.at(i)+b.at(j)*c.at(i)*lc.at(k))*0.5*detJ-lc.at(i)*2.0*area*detJ; + answer.at(8, 6*i - 1) = (-c.at(i)*c.at(k)*lc.at(j)+c.at(i)*c.at(j)*lc.at(k))*0.5*detJ; + + // Reduced integration of the fourth strain component + // gamma_rot + answer.at(9, 6 * i - 5) = -1. * c.at(i) * 1.0 / 4.0 / area; + answer.at(9, 6 * i - 4) = b.at(i) * 1.0 / 4.0 / area; + answer.at(9, 6 * i - 0) = ( -4. * area * lc.at(i) + nxRed.at(i) - nyRed.at(i) ) * 1.0 / 4.0 / area; + + } + +} + + + + +void +TR_SHELL11 :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +// Returns the displacement interpolation matrix {N} of the receiver +// evaluated at gp. +{ + // get node coordinates + FloatArray x(3), y(3); + this->giveNodeCoordinates(x, y); + + // + FloatArray b(3), c(3), d(3); + + for ( int i = 1; i <= 3; i++ ) { + int j = i + 1 - i / 3 * 3; + int k = j + 1 - j / 3 * 3; + b.at(i) = y.at(j) - y.at(k); + c.at(i) = x.at(k) - x.at(j); + d.at(i) = sqrt( b.at(i) * b.at(i) + c.at(i) * c.at(i) ); + } + + // + FloatArray angles = this->GivePitch(); + + // + double l1, l2, l3, f11, f12, f13, f21, f22, f23; + + l1 = iLocCoord.at(1); + l2 = iLocCoord.at(2); + l3 = 1. - l1 - l2; + + f11 = d.at(2) / 2. *l1 *l3 *sin( angles.at(2) ) - d.at(3) / 2. *l2 *l1 *sin( angles.at(3) ); + f12 = d.at(3) / 2. *l2 *l1 *sin( angles.at(3) ) - d.at(1) / 2. *l3 *l2 *sin( angles.at(1) ); + f13 = d.at(1) / 2. *l3 *l2 *sin( angles.at(1) ) - d.at(2) / 2. *l1 *l3 *sin( angles.at(2) ); + + f21 = d.at(3) / 2. *l2 *l1 *cos( angles.at(3) ) - d.at(2) / 2. *l1 *l3 *cos( angles.at(2) ); + f22 = d.at(1) / 2. *l3 *l2 *cos( angles.at(1) ) - d.at(3) / 2. *l2 *l1 *cos( angles.at(3) ); + f23 = d.at(2) / 2. *l1 *l3 *cos( angles.at(2) ) - d.at(1) / 2. *l3 *l2 *cos( angles.at(1) ); + + // + answer.resize(6, 18); + answer.zero(); + + answer.at(1, 1) = l1; + answer.at(1, 6) = f11; + answer.at(1, 7) = l2; + answer.at(1, 12) = f12; + answer.at(1, 13) = l3; + answer.at(1, 18) = f13; + + answer.at(2, 2) = l1; + answer.at(2, 6) = f21; + answer.at(2, 8) = l2; + answer.at(2, 12) = f22; + answer.at(2, 14) = l3; + answer.at(2, 18) = f23; + + answer.at(3, 3) = l1; // d_w + answer.at(3, 4) = l1 * ( l2 * b.at(3) - l3 * b.at(2) ) * 0.5; + answer.at(3, 5) = l1 * ( l2 * c.at(3) - l3 * c.at(2) ) * 0.5; + answer.at(3, 9) = l2; + answer.at(3, 10) = l2 * ( l3 * b.at(1) - l1 * b.at(3) ) * 0.5; + answer.at(3, 11) = l2 * ( l3 * c.at(1) - l1 * c.at(3) ) * 0.5; + answer.at(3, 15) = l3; + answer.at(3, 16) = l3 * ( l1 * b.at(2) - l2 * b.at(1) ) * 0.5; + answer.at(3, 17) = l3 * ( l1 * c.at(2) - l2 * c.at(1) ) * 0.5; + + answer.at(4, 4) = l1; // fi_x + answer.at(4, 10) = l2; + answer.at(4, 16) = l3; + + answer.at(5, 5) = l1; // fi_y + answer.at(5, 11) = l2; + answer.at(5, 17) = l3; + + answer.at(6, 6) = l1; // fi_y + answer.at(12, 12) = l2; + answer.at(18, 18) = l3; +} + + +double +TR_SHELL11 :: giveArea() +// returns the area occupied by the receiver +{ + ///@todo replace with call to linear triangle interpolator + if ( fabs(area) > 0 ) { // check if previously computed + return area; + } + + // get node coordinates + FloatArray x(3), y(3); + this->giveNodeCoordinates(x, y); + + // + double x1, x2, x3, y1, y2, y3; + x1 = x.at(1); + x2 = x.at(2); + x3 = x.at(3); + + y1 = y.at(1); + y2 = y.at(2); + y3 = y.at(3); + + //return ( area = fabs( 0.5 * ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 ) ) ); + return ( area = 0.5 * ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 ) ); +} + +void +TR_SHELL11 :: giveLocalCoordinates(FloatArray &answer, const FloatArray &global) +// Returns global coordinates given in global vector +// transformed into local coordinate system of the +// receiver +{ + // test the parameter + if ( global.giveSize() != 3 ) { + OOFEM_ERROR("cannot transform coordinates - size mismatch"); + exit(1); + } + + // first ensure that receiver's GtoLRotationMatrix[3,3] is defined + if ( !GtoLRotationMatrix.isNotEmpty() ) { + this->computeGtoLRotationMatrix(); + } + + FloatArray offset = global; + offset.subtract( this->giveNode(1)->giveCoordinates() ); + answer.beProductOf(GtoLRotationMatrix, offset); +} + + +double +TR_SHELL11 :: computeVolumeAround(GaussPoint *gp) +{ + double detJ, weight; + + FloatArray x, y; + this->giveNodeCoordinates(x, y); + std :: vector< FloatArray > lc = {{x[0], y[0]}, {x[1], y[1]}, {x[2], y[2]}}; + + weight = gp->giveWeight(); + detJ = fabs( this->interp_lin.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIVertexListGeometryWrapper(lc) ) ); + return detJ * weight; // * this->giveStructuralCrossSection()->give(CS_Thickness, gp); +} + + +void +TR_SHELL11 :: giveNodeCoordinates(FloatArray &x, FloatArray &y) +{ + FloatArray nc1(3), nc2(3), nc3(3); + + this->giveLocalCoordinates( nc1, this->giveNode(1)->giveCoordinates() ); + this->giveLocalCoordinates( nc2, this->giveNode(2)->giveCoordinates() ); + this->giveLocalCoordinates( nc3, this->giveNode(3)->giveCoordinates() ); + + x.resize(3); + x.at(1) = nc1.at(1); + x.at(2) = nc2.at(1); + x.at(3) = nc3.at(1); + + y.resize(3); + y.at(1) = nc1.at(2); + y.at(2) = nc2.at(2); + y.at(3) = nc3.at(2); + + //if (z) { + // z[0] = nc1->at(3); + // z[1] = nc2->at(3); + // z[2] = nc3->at(3); + //} +} + + +void +TR_SHELL11 :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = {D_u, D_v, D_w, R_u, R_v, R_w}; +} + + +void +TR_SHELL11 :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->give3dShellRotStiffMtrx(rMode, gp, tStep); +} + + +void +TR_SHELL11 :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_ShellRot(strain, gp, tStep); +} + + +const FloatMatrix * +TR_SHELL11 :: computeGtoLRotationMatrix() +// Returns the rotation matrix of the receiver of the size [3,3] +// coords(local) = T * coords(global) +// +// local coordinate (described by vector triplet e1',e2',e3') is defined as follows: +// +// e1' : [N2-N1] Ni - means i - th node +// help : [N3-N1] +// e3' : e1' x help +// e2' : e3' x e1' +{ + + if ( !GtoLRotationMatrix.isNotEmpty() ) { + FloatArray e1, e2, e3, help; + + // compute e1' = [N2-N1] and help = [N3-N1] + e1.beDifferenceOf( this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); + help.beDifferenceOf( this->giveNode(3)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); + + // let us normalize e1' + e1.normalize(); + + // compute e3' : vector product of e1' x help + e3.beVectorProductOf(e1, help); + // let us normalize + e3.normalize(); + + // now from e3' x e1' compute e2' + e2.beVectorProductOf(e3, e1); + + // + GtoLRotationMatrix.resize(3, 3); + + for ( int i = 1; i <= 3; i++ ) { + GtoLRotationMatrix.at(1, i) = e1.at(i); + GtoLRotationMatrix.at(2, i) = e2.at(i); + GtoLRotationMatrix.at(3, i) = e3.at(i); + } + } + + return &GtoLRotationMatrix; +} + + +bool +TR_SHELL11 :: computeGtoLRotationMatrix(FloatMatrix &answer) +// Returns the rotation matrix of the receiver of the size [18,18] +// r(local) = T * r(global) +// for one node (r written transposed): {u,v,w, r1, r2, r3} = T * {u,v,w,r1,r2,r3} +{ + // test if pereviously computed + if ( !GtoLRotationMatrix.isNotEmpty() ) { + this->computeGtoLRotationMatrix(); + } + + answer.resize(18, 18); + answer.zero(); + + for ( int i = 1; i <= 6; i++ ) { + answer.setSubMatrix(GtoLRotationMatrix, 3*i-2, 3*i-2); + } + + return 1; +} + + +void +TR_SHELL11 :: giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep) +// returns characteristic tensor of the receiver at given gp and tStep +// strain vector = (Eps_X, Eps_y, Gamma_xy, Kappa_z) +{ + FloatArray charVect; + StructuralMaterialStatus *ms = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); + + answer.resize(3, 3); + answer.zero(); + + if ( type == LocalForceTensor || type == GlobalForceTensor ) { + //this->computeStressVector(charVect, gp, tStep); + charVect = ms->giveStressVector(); + + double h = this->giveStructuralCrossSection()->give(CS_Thickness, gp); + answer.at(1, 1) = charVect.at(1) * h; + answer.at(2, 2) = charVect.at(2) * h; + answer.at(1, 2) = charVect.at(3) * h; + answer.at(2, 1) = charVect.at(3) * h; + + answer.at(1, 3) = charVect.at(7); + answer.at(3, 1) = charVect.at(7); + answer.at(2, 3) = charVect.at(8); + answer.at(3, 2) = charVect.at(8); + + } else if ( type == LocalMomentTensor || type == GlobalMomentTensor ) { + //this->computeStressVector(charVect, gp, tStep); + charVect = ms->giveStressVector(); + + //answer.at(3, 3) = charVect.at(4); + answer.at(1, 1) = charVect.at(4); + answer.at(2, 2) = charVect.at(5); + answer.at(1, 2) = charVect.at(6); + answer.at(2, 1) = charVect.at(6); + + } else if ( type == LocalStrainTensor || type == GlobalStrainTensor ) { + //this->computeStrainVector(charVect, gp, tStep); + charVect = ms->giveStrainVector(); + + answer.at(1, 1) = charVect.at(1); + answer.at(2, 2) = charVect.at(2); + answer.at(1, 2) = charVect.at(3) / 2.; + answer.at(2, 1) = charVect.at(3) / 2.; + + answer.at(1, 3) = charVect.at(7) / 2.; + answer.at(3, 1) = charVect.at(7) / 2.; + answer.at(2, 3) = charVect.at(8) / 2.; + answer.at(3, 2) = charVect.at(8) / 2.; + + + } else if ( type == LocalCurvatureTensor || type == GlobalCurvatureTensor ) { + //this->computeStrainVector(charVect, gp, tStep); + charVect = ms->giveStrainVector(); + + //answer.at(3, 3) = charVect.at(4); + + answer.at(1, 1) = charVect.at(4); + answer.at(2, 2) = charVect.at(5); + answer.at(1, 2) = charVect.at(6) / 2.; + answer.at(2, 1) = charVect.at(6) / 2.; + + } else { + OOFEM_ERROR("unsupported tensor mode"); + exit(1); + } + + if ( type == GlobalForceTensor || type == GlobalMomentTensor || + type == GlobalStrainTensor || type == GlobalCurvatureTensor ) { + this->computeGtoLRotationMatrix(); + answer.rotatedWith(GtoLRotationMatrix); + } +} + + +int +TR_SHELL11 :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +{ + FloatMatrix globTensor; + CharTensor cht; + + answer.resize(6); + + if ( type == IST_CurvatureTensor || type == IST_ShellStrainTensor ) { + if ( type == IST_CurvatureTensor ) { + cht = GlobalCurvatureTensor; + } else { + cht = GlobalStrainTensor; + } + + this->giveCharacteristicTensor(globTensor, cht, gp, tStep); + + answer.at(1) = globTensor.at(1, 1); //xx + answer.at(2) = globTensor.at(2, 2); //yy + answer.at(3) = globTensor.at(3, 3); //zz + answer.at(4) = 2 * globTensor.at(2, 3); //yz + answer.at(5) = 2 * globTensor.at(1, 3); //xz + answer.at(6) = 2 * globTensor.at(1, 2); //xy + + return 1; + } else if ( type == IST_ShellMomentTensor || type == IST_ShellForceTensor ) { + if ( type == IST_ShellMomentTensor ) { + cht = GlobalMomentTensor; + } else { + cht = GlobalForceTensor; + } + + this->giveCharacteristicTensor(globTensor, cht, gp, tStep); + + answer.at(1) = globTensor.at(1, 1); //xx + answer.at(2) = globTensor.at(2, 2); //yy + answer.at(3) = globTensor.at(3, 3); //zz + answer.at(4) = globTensor.at(2, 3); //yz + answer.at(5) = globTensor.at(1, 3); //xz + answer.at(6) = globTensor.at(1, 2); //xy + + return 1; + } else { + return StructuralElement :: giveIPValue(answer, gp, type, tStep); + } +} + +int +TR_SHELL11 :: computeLoadGToLRotationMtrx(FloatMatrix &answer) +// Returns the rotation matrix of the receiver of the size [6,6] +// f(local) = T * f(global) +{ + // test if previously computed + if ( !GtoLRotationMatrix.isNotEmpty() ) { + this->computeGtoLRotationMatrix(); + } + + answer.resize(6, 6); + answer.zero(); + + for ( int i = 1; i <= 3; i++ ) { + answer.at(1, i) = answer.at(4, i + 3) = GtoLRotationMatrix.at(1, i); + answer.at(2, i) = answer.at(5, i + 3) = GtoLRotationMatrix.at(2, i); + answer.at(3, i) = answer.at(6, i + 3) = GtoLRotationMatrix.at(3, i); + } + + return 1; +} + + +void +TR_SHELL11 :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) +// Computes numerically the load vector of the receiver due to the body loads, at tStep. +// load is assumed to be in global cs. +// load vector is then transformed to coordinate system in each node. +// (should be global coordinate system, but there may be defined +// different coordinate system in each node) +{ + double dens, dV, load; + FloatArray force; + FloatMatrix T; + + if ( ( forLoad->giveBCGeoType() != BodyLoadBGT ) || ( forLoad->giveBCValType() != ForceLoadBVT ) ) { + OOFEM_ERROR("unknown load type"); + } + + // note: force is assumed to be in global coordinate system; 6 components + forLoad->computeComponentArrayAt(force, tStep, mode); + // get it in local c.s. + this->computeLoadGToLRotationMtrx(T); + force.rotatedWith(T, 'n'); + + if ( force.giveSize() ) { + GaussIntegrationRule iRule (1, this, 1, 1); + iRule.SetUpPointsOnTriangle(1, _Unknown); + GaussPoint *gp = iRule.getIntegrationPoint(0); + + dens = this->giveStructuralCrossSection()->give('d', gp); + dV = this->computeVolumeAround(gp);// * this->giveCrossSection()->give(CS_Thickness, gp); + + answer.resize(18); + answer.zero(); + + load = force.at(1) * dens * dV / 3.0; + answer.at(1) = load; + answer.at(7) = load; + answer.at(13) = load; + + load = force.at(2) * dens * dV / 3.0; + answer.at(2) = load; + answer.at(8) = load; + answer.at(14) = load; + + load = force.at(3) * dens * dV / 3.0; + answer.at(3) = load; + answer.at(9) = load; + answer.at(15) = load; + + // transform result from global cs to local element cs. + //if ( this->computeGtoLRotationMatrix(T) ) { + // answer.rotatedWith(T, 'n'); + //} + } else { + answer.clear(); // nil resultant + } +} + +void +TR_SHELL11 :: computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) +{ + this->computeNmatrixAt(sgp->giveNaturalCoordinates(), answer); +} + +void +TR_SHELL11 :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +{ + answer.resize(18); + answer.zero(); + if ( iSurf == 1 ) { + for (int i=1; i<=18; i++) + answer.at(i)=i; + } else { + OOFEM_ERROR("wrong surface number"); + } +} + + +double +TR_SHELL11 :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) +{ + return this->computeVolumeAround(gp); +} + + +int +TR_SHELL11 :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) +{ + return 0; +} + + +void +TR_SHELL11 :: printOutputAt(FILE *file, TimeStep *tStep) +// Performs end-of-step operations. +{ + FloatArray v; + + fprintf( file, "element %d (%8d) :\n", this->giveLabel(), this->giveNumber() ); + + for ( int i = 0; i < (int)integrationRulesArray.size(); i++ ) { + for ( GaussPoint *gp: *integrationRulesArray [ i ] ) { + + fprintf( file, " GP %2d.%-2d :", i + 1, gp->giveNumber() ); + + this->giveIPValue(v, gp, IST_ShellStrainTensor, tStep); + fprintf(file, " strains "); + for ( auto &val : v ) fprintf(file, " %.4e", val); + + this->giveIPValue(v, gp, IST_CurvatureTensor, tStep); + fprintf(file, "\n curvatures "); + for ( auto &val : v ) fprintf(file, " %.4e", val); + + // Forces - Moments + this->giveIPValue(v, gp, IST_ShellForceTensor, tStep); + fprintf(file, "\n stresses "); + for ( auto &val : v ) fprintf(file, " %.4e", val); + + this->giveIPValue(v, gp, IST_ShellMomentTensor, tStep); + fprintf(file, "\n moments "); + for ( auto &val : v ) fprintf(file, " %.4e", val); + + + if ( gp->hasSlaveGaussPoint()) { // layered material + fprintf(file, "\n Layers report \n{\n"); + + for (auto &sgp: gp->giveSlaveGaussPoints()) { + sgp->printOutputAt(file, tStep); + } + fprintf(file, "} end layers report\n"); + + } + + + fprintf(file, "\n"); + } + } +} + +void +TR_SHELL11 :: initializeFrom(InputRecord &ir) +{ + StructuralElement :: initializeFrom(ir); +} + +Interface * +TR_SHELL11 :: giveInterface(InterfaceType interface) +{ + if ( interface == LayeredCrossSectionInterfaceType ) { + return static_cast< LayeredCrossSectionInterface * >(this); + } else if ( interface == ZZNodalRecoveryModelInterfaceType ) { + return static_cast< ZZNodalRecoveryModelInterface * >(this); + } else if ( interface == NodalAveragingRecoveryModelInterfaceType ) { + return static_cast< NodalAveragingRecoveryModelInterface * >(this); + } else if ( interface == SPRNodalRecoveryModelInterfaceType ) { + return static_cast< SPRNodalRecoveryModelInterface * >(this); + } else if ( interface == ZZErrorEstimatorInterfaceType ) { + return static_cast< ZZErrorEstimatorInterface * >(this); + } + + + return NULL; +} + +void +TR_SHELL11 :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) +{ + GaussPoint *gp; + if ( ( type == IST_ShellForceTensor ) || ( type == IST_ShellMomentTensor ) || + ( type == IST_ShellStrainTensor ) || ( type == IST_CurvatureTensor ) ) { + gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + this->giveIPValue(answer, gp, type, tStep); + } else { + answer.clear(); + } +} + + +void +TR_SHELL11 :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) +{ + pap.resize(3); + pap.at(1) = this->giveNode(1)->giveNumber(); + pap.at(2) = this->giveNode(2)->giveNumber(); + pap.at(3) = this->giveNode(3)->giveNumber(); +} + + +void +TR_SHELL11 :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) +{ + answer.resize(1); + if ( ( pap == this->giveNode(1)->giveNumber() ) || + ( pap == this->giveNode(2)->giveNumber() ) || + ( pap == this->giveNode(3)->giveNumber() ) ) { + answer.at(1) = pap; + } else { + OOFEM_ERROR("node unknown"); + } +} + + +SPRPatchType +TR_SHELL11 :: SPRNodalRecoveryMI_givePatchType() +{ + return SPRPatchType_2dxy; +} + + +// +// layered cross section support functions +// +void +TR_SHELL11 :: computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) +// returns full 3d strain vector of given layer (whose z-coordinate from center-line is +// stored in slaveGp) for given tStep +// // strainVectorShell {eps_x,eps_y,gamma_xy, kappa_x, kappa_y, kappa_xy, gamma_zx, gamma_zy, gamma_rot} +{ + double layerZeta, layerZCoord, top, bottom; + + top = this->giveCrossSection()->give(CS_TopZCoord, masterGp); + bottom = this->giveCrossSection()->give(CS_BottomZCoord, masterGp); + layerZeta = slaveGp->giveNaturalCoordinate(3); + layerZCoord = 0.5 * ( ( 1. - layerZeta ) * bottom + ( 1. + layerZeta ) * top ); + + answer.resize(5); // {Exx,Eyy,GMyz,GMzx,GMxy} + + answer.at(1) = masterGpStrain.at(1)+masterGpStrain.at(4) * layerZCoord; + answer.at(2) = masterGpStrain.at(2)+masterGpStrain.at(5) * layerZCoord; + answer.at(5) = masterGpStrain.at(3)+masterGpStrain.at(6) * layerZCoord; + answer.at(3) = masterGpStrain.at(8); + answer.at(4) = masterGpStrain.at(7); +} + +double +TR_SHELL11 :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) +// +// returns receiver's characteristic length for crack band models +// for a crack formed in the plane with normal normalToCrackPlane. +// +{ + return this->giveCharacteristicLengthForPlaneElements(normalToCrackPlane); +} + + +} // end namespace oofem diff --git a/src/sm/Elements/Shells/tr_shell11.h b/src/sm/Elements/Shells/tr_shell11.h new file mode 100644 index 000000000..548d0ac5b --- /dev/null +++ b/src/sm/Elements/Shells/tr_shell11.h @@ -0,0 +1,140 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef tr_shell11_h +#define tr_shell11_h + +#include "sm/Elements/structuralelement.h" +#include "zznodalrecoverymodel.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" +#include "sprnodalrecoverymodel.h" +#include "sm/CrossSections/layeredcrosssection.h" +#include "sm/Elements/Shells/cct3d.h" +#include "sm/Elements/PlaneStress/trplanrot3d.h" +#include "spatiallocalizer.h" +#include "fei2dtrlin.h" +#include + +#define _IFT_TR_SHELL11_Name "tr_shell11" + +namespace oofem { + +/** + * This class implements an triangular three-node shell finite element, essentially a combination of + * cct3d and trplanrot3d elements. Each node has 6 degrees of freedom. + * + * @author Borek Patzak + */ + class TR_SHELL11 : public StructuralElement, public ZZNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface, public ZZErrorEstimatorInterface, public SPRNodalRecoveryModelInterface, public SpatialLocalizerInterface, public LayeredCrossSectionInterface +{ +protected: + static FEI2dTrLin interp_lin; + double area; + int numberOfRotGaussPoints; + FloatMatrix GtoLRotationMatrix; +public: + /// Constructor + TR_SHELL11(int n, Domain * d); + /// Destructor + virtual ~TR_SHELL11() {} + + FEInterpolation *giveInterpolation() const override { return &interp_lin; } + + int computeNumberOfDofs() override { return 18; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + // definition & identification + const char *giveInputRecordName() const override { return _IFT_TR_SHELL11_Name; } + const char *giveClassName() const override { return "TR_SHELL11"; } + void initializeFrom(InputRecord &ir) override; + + void computeGaussPoints() override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + + double giveArea(); + + + + const FloatMatrix *computeGtoLRotationMatrix(); + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; + void giveLocalCoordinates(FloatArray &answer, const FloatArray &global); + void giveNodeCoordinates(FloatArray &x, FloatArray &y) ; + + void giveCharacteristicTensor(FloatMatrix &answer, CharTensor type, GaussPoint *gp, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + int computeLoadGToLRotationMtrx(FloatMatrix &answer) override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) override; + + void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override; + double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) override; + int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp) override; + + double computeVolumeAround(GaussPoint *gp) override; + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override; + + void printOutputAt(FILE *file, TimeStep *tStep) override; + + Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_1; } + integrationDomain giveIntegrationDomain() const override { return _Triangle; } + MaterialMode giveMaterialMode() override { return _3dShellRot; } + + Interface *giveInterface(InterfaceType it) override; + + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, + InternalStateType type, TimeStep *tStep) override; + + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override { return 4; } + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; + + + // layered cross section support functions + void computeStrainVectorInLayer(FloatArray &answer, const FloatArray &masterGpStrain, + GaussPoint *masterGp, GaussPoint *slaveGp, TimeStep *tStep) override; + + +protected: + FloatArray GiveDerivativeUX(const FloatArray &lCoords); + FloatArray GiveDerivativeVX(const FloatArray &lCoords); + FloatArray GiveDerivativeUY(const FloatArray &lCoords); + FloatArray GiveDerivativeVY(const FloatArray &lCoords); + FloatArray GivePitch(); +}; +}// end namespace oofem +#endif diff --git a/src/sm/Elements/coupledfieldselement.C b/src/sm/Elements/coupledfieldselement.C index ee8d7365a..c7730a167 100644 --- a/src/sm/Elements/coupledfieldselement.C +++ b/src/sm/Elements/coupledfieldselement.C @@ -34,10 +34,10 @@ */ #if 1 -#include "../sm/Elements/coupledfieldselement.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/coupledfieldselement.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/nlstructuralelement.h" #include "node.h" #include "material.h" #include "gausspoint.h" @@ -53,10 +53,8 @@ namespace oofem { CoupledFieldsElement :: CoupledFieldsElement(int i, Domain *aDomain) : NLStructuralElement(i, aDomain) -// Constructor. { nlGeo = 0; - } @@ -65,12 +63,11 @@ CoupledFieldsElement :: computeLocationArrayOfDofIDs(const IntArray &dofIdArray, { // Routine to extract compute the location array an element given an dofid array. answer.resize(0); - + int k = 0; for ( int i = 1; i <= numberOfDofMans; i++ ) { DofManager *dMan = this->giveDofManager(i); for (int j = 1; j <= dofIdArray.giveSize(); j++ ) { - if ( dMan->hasDofID( (DofIDItem) dofIdArray.at(j) ) ) { Dof *d = dMan->giveDofWithID( dofIdArray.at(j) ); answer.followedBy( k + d->giveNumber() ); @@ -87,14 +84,12 @@ CoupledFieldsElement :: computeVectorOfDofIDs(const IntArray &dofIdArray, ValueM { // Routine to extract the solution vector for an element given an dofid array. // Size will be numberOfDofs and if a certain dofId does not exist a zero is used as value. - answer.resize( numberOfDofMans * dofIdArray.giveSize() ); // equal number of nodes for all fields answer.zero(); int k = 1; for ( int i = 1; i <= numberOfDofMans; i++ ) { DofManager *dMan = this->giveDofManager(i); for (int j = 1; j <= dofIdArray.giveSize(); j++ ) { - if ( dMan->hasDofID( (DofIDItem) dofIdArray.at(j) ) ) { Dof *d = dMan->giveDofWithID( dofIdArray.at(j) ); answer.at(k) = d->giveUnknown(valueMode, stepN); @@ -136,15 +131,11 @@ CoupledFieldsElement :: giveInternalForcesVectorGen(FloatArray &answer, TimeStep BS.beTProductOf(B, BStress); answer.add(dV, BS); } - - } } } - - void CoupledFieldsElement :: computeStiffnessMatrixGen(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep, void (*Nfunc)(GaussPoint*, FloatMatrix), @@ -184,12 +175,10 @@ CoupledFieldsElement :: computeStiffnessMatrixGen(FloatMatrix &answer, MatRespon answer.plusProductSymmUpper(B, DB, dV); } else { answer.plusProductUnsym(B, DB, dV); - } + } } - } - if ( matStiffSymmFlag ) { answer.symmetrized(); } @@ -197,16 +186,13 @@ CoupledFieldsElement :: computeStiffnessMatrixGen(FloatMatrix &answer, MatRespon -IRResultType -CoupledFieldsElement :: initializeFrom(InputRecord *ir) +void +CoupledFieldsElement :: initializeFrom(InputRecord &ir) { - //IRResultType result; // Required by IR_GIVE_FIELD macro //nlGeo = 0; - - return IRRT_OK; } } // end namespace oofem -#endif \ No newline at end of file +#endif diff --git a/src/sm/Elements/coupledfieldselement.h b/src/sm/Elements/coupledfieldselement.h index 699a79915..9c7fc9acd 100644 --- a/src/sm/Elements/coupledfieldselement.h +++ b/src/sm/Elements/coupledfieldselement.h @@ -36,7 +36,7 @@ #ifndef coupledfieldselement_h #define coupledfieldselement_h -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/nlstructuralelement.h" namespace oofem { /** @@ -53,19 +53,15 @@ class CoupledFieldsElement : public NLStructuralElement CoupledFieldsElement(int i, Domain *aDomain); virtual ~CoupledFieldsElement() {} - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveDofManDofIDMask (int inode, EquationID ut, IntArray& answer) const = 0; + void initializeFrom(InputRecord &ir) override; protected: - virtual void computeNStressAt(GaussPoint *, FloatArray &) = 0; virtual void computeBStressAt(GaussPoint *, FloatArray &) = 0; - virtual double computeVolumeAround(GaussPoint *) = 0; - void computeStiffnessMatrix(FloatMatrix &, MatResponseMode, TimeStep *) = 0; - void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) = 0; - - + double computeVolumeAround(GaussPoint *) override = 0; + void computeStiffnessMatrix(FloatMatrix &, MatResponseMode, TimeStep *) override = 0; + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override = 0; void computeVectorOfDofIDs(const IntArray &dofIdArray, ValueModeType valueMode, TimeStep *stepN, FloatArray &answer); void computeLocationArrayOfDofIDs(const IntArray &dofIdArray, IntArray &answer); @@ -77,13 +73,10 @@ class CoupledFieldsElement : public NLStructuralElement void (*BStiffness)(FloatMatrix, MatResponseMode, GaussPoint*, TimeStep*), double (*volumeAround)(GaussPoint*) ); - void giveInternalForcesVectorGen(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, void (*Nfunc)(GaussPoint*, FloatMatrix), void (*Bfunc)(GaussPoint*, FloatMatrix, int, int), //(GaussPoint*, FloatMatrix) void (*NStress)(GaussPoint*, FloatArray), void (*BStress)(GaussPoint*, FloatArray), - double (*volumeAround)(GaussPoint*) - ); - + double (*volumeAround)(GaussPoint*) ); }; } // end namespace oofem diff --git a/src/sm/Elements/graddpelement.C b/src/sm/Elements/graddpelement.C index f2fad55fa..13cf598ce 100644 --- a/src/sm/Elements/graddpelement.C +++ b/src/sm/Elements/graddpelement.C @@ -34,11 +34,11 @@ */ -#include "../sm/Elements/graddpelement.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Elements/nlstructuralelement.h" -#include "../sm/Materials/graddpmaterialextensioninterface.h" +#include "sm/Elements/graddpelement.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/nlstructuralelement.h" +#include "sm/Materials/graddpmaterialextensioninterface.h" #include "node.h" #include "material.h" #include "gausspoint.h" @@ -736,12 +736,9 @@ GradDpElement :: computeStiffnessMatrix_uk(FloatMatrix &answer, MatResponseMode } -IRResultType -GradDpElement :: initializeFrom(InputRecord *ir) +void +GradDpElement :: initializeFrom(InputRecord &ir) { - //IRResultType result; // Required by IR_GIVE_FIELD macro //nlGeo = 0; - - return IRRT_OK; } } // end namespace oofem diff --git a/src/sm/Elements/graddpelement.h b/src/sm/Elements/graddpelement.h index ac58e1de6..c59801e86 100644 --- a/src/sm/Elements/graddpelement.h +++ b/src/sm/Elements/graddpelement.h @@ -36,8 +36,8 @@ #ifndef graddpelement_h #define graddpelement_h -#include "../sm/Elements/structuralelement.h" -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Elements/nlstructuralelement.h" namespace oofem { /** @@ -56,7 +56,7 @@ class GradDpElement GradDpElement(); virtual ~GradDpElement() { } - virtual IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); protected: virtual StructuralElement *giveStructuralElement() = 0; diff --git a/src/sm/Elements/htselement.C b/src/sm/Elements/htselement.C index cd5c73119..617ed2fc3 100644 --- a/src/sm/Elements/htselement.C +++ b/src/sm/Elements/htselement.C @@ -33,7 +33,7 @@ */ //last edit: 07/02/2013 by Jan Novak -#include "../sm/Elements/htselement.h" +#include "sm/Elements/htselement.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" @@ -71,20 +71,15 @@ HTSelement :: giveDofManDofIDMask(int inode, IntArray &answer) const } -IRResultType -HTSelement :: initializeFrom(InputRecord *ir) +void +HTSelement :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - result = StructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralElement :: initializeFrom(ir); numberOfGaussPoints = 8; //IR_GIVE_FIELD(ir, numberOfEdges, _IFT_HTSelement_numberOfEdges, "numberOfEdges"); //numberOfEdges = 3; this->computeCenterOfGravity(); - return IRRT_OK; } void @@ -94,7 +89,7 @@ HTSelement :: computeGaussPoints() integrationRulesArray.resize(numberOfEdges); for ( int i = 0; i < numberOfEdges; i++ ) { - integrationRulesArray [ i ].reset( new GaussIntegrationRule(i + 1, this, 1, 100) ); + integrationRulesArray [ i ] = std::make_unique(i + 1, this, 1, 100); integrationRulesArray [ i ]->SetUpPointsOnLine(numberOfGaussPoints, _1dMat); } } diff --git a/src/sm/Elements/htselement.h b/src/sm/Elements/htselement.h index f15fb994e..5030c227a 100644 --- a/src/sm/Elements/htselement.h +++ b/src/sm/Elements/htselement.h @@ -35,7 +35,7 @@ #ifndef htselement_h #define htselement_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "gaussintegrationrule.h" #define _IFT_HTSelement_Name "htselement" @@ -60,37 +60,36 @@ class HTSelement : public StructuralElement HTSelement(int n, Domain * d); virtual ~HTSelement() { } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveInputRecordName() const { return _IFT_HTSelement_Name; } - virtual const char *giveClassName() const { return "HTSelement"; } + const char *giveInputRecordName() const override { return _IFT_HTSelement_Name; } + const char *giveClassName() const override { return "HTSelement"; } protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int, int) {; } - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) {; } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int, int) override { } + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override { } + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; double computeVolumeAroundSide(GaussPoint *gp, int elemSideNumber); Node *giveSideNode(int elementSideNumber, int nodeNumber); double giveSideLength(int sideNumber); - virtual int computeNumberOfDofs() { return 4 * numberOfEdges; } - virtual void computeGaussPoints(); - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 4 * numberOfEdges; } + void computeGaussPoints() override; + void giveDofManDofIDMask(int inode, IntArray &) const override; virtual StructuralElement *giveStructuralElement() { return this; } //jak se pocita deformace??? - virtual void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { answer.resize(numberOfStressDofs); } + void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override { answer.resize(numberOfStressDofs); } //dodelat vypocet napeti!!! - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { answer.resize(numberOfStressDofs); } - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override { answer.resize(numberOfStressDofs); } + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override { OOFEM_ERROR("Function not defined for this element and should never be called. This is a bug."); } //dodelat internal forces, budou potreba pro nelinearni vypocet - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { answer.resize(numberOfDofs); } + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) override { answer.resize(numberOfDofs); } void computePuVectorAt(FloatArray &answer, FloatMatrix N, FloatArray u, GaussPoint *gp, int sideNumber); void computePsVectorAt(FloatArray &answer, FloatArray t, GaussPoint *gp); void computePrescribedDisplacementLoadVectorAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode); - virtual int testElementExtension(ElementExtension ext) { return ( ext == Element_EdgeLoadSupport ); } - + int testElementExtension(ElementExtension ext) override { return ( ext == Element_EdgeLoadSupport ); } void computeFMatrixAt(FloatMatrix &answer, FloatMatrix N, GaussPoint *gp, int sideNumber); void computeAMatrixAt(FloatMatrix &answer, FloatMatrix N, GaussPoint *gp, int sideNumber); @@ -99,9 +98,8 @@ class HTSelement : public StructuralElement void computeUgammaMatrixAt(FloatMatrix &answer, GaussPoint *gp); void computeOutwardNormalMatrix(FloatMatrix &answer, int sideNumber); - void computeCenterOfGravity(); - virtual int giveNumberOfNodes() const { return numberOfEdges; } + int giveNumberOfNodes() const override { return numberOfEdges; } //uv functions void uv1(FloatArray &answer, double x, double y); void uv2(FloatArray &answer, double x, double y); diff --git a/src/sm/Elements/igaelements.C b/src/sm/Elements/igaelements.C index e49b919f8..11b837089 100644 --- a/src/sm/Elements/igaelements.C +++ b/src/sm/Elements/igaelements.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/igaelements.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/igaelements.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "floatarray.h" #include "floatmatrix.h" #include "domain.h" @@ -62,10 +62,10 @@ REGISTER_Element(NURBSSpace3dElement); BsplinePlaneStressElement :: BsplinePlaneStressElement(int n, Domain *aDomain) : IGAElement(n, aDomain), PlaneStressStructuralElementEvaluator(), interpolation(2) { } -IRResultType BsplinePlaneStressElement :: initializeFrom(InputRecord *ir) +void BsplinePlaneStressElement :: initializeFrom(InputRecord &ir) { //PlaneStressStructuralElementEvaluator::initializeFrom(ir); - return IGAElement :: initializeFrom(ir); + IGAElement :: initializeFrom(ir); } @@ -84,10 +84,10 @@ int BsplinePlaneStressElement :: checkConsistency() NURBSPlaneStressElement :: NURBSPlaneStressElement(int n, Domain *aDomain) : IGAElement(n, aDomain), PlaneStressStructuralElementEvaluator(), interpolation(2) { } -IRResultType NURBSPlaneStressElement :: initializeFrom(InputRecord *ir) +void NURBSPlaneStressElement :: initializeFrom(InputRecord &ir) { //PlaneStressStructuralElementEvaluator::initializeFrom(ir); - return IGAElement :: initializeFrom(ir); + IGAElement :: initializeFrom(ir); } @@ -110,10 +110,10 @@ TSplinePlaneStressElement :: TSplinePlaneStressElement(int n, Domain *aDomain) : NURBSSpace3dElement :: NURBSSpace3dElement(int n, Domain *aDomain) : IGAElement(n, aDomain), Space3dStructuralElementEvaluator(), interpolation(3) { } -IRResultType NURBSSpace3dElement :: initializeFrom(InputRecord *ir) +void NURBSSpace3dElement :: initializeFrom(InputRecord &ir) { //PlaneStressStructuralElementEvaluator::initializeFrom(ir); - return IGAElement :: initializeFrom(ir); + IGAElement :: initializeFrom(ir); } @@ -153,7 +153,7 @@ void BsplinePlaneStressElement :: drawScalar(oofegGraphicContext &gc, TimeStep * EASValsSetLayer(OOFEG_VARPLOT_PATTERN_LAYER); EASValsSetFillStyle(FILL_SOLID); - const double *const *knotVector = interp->giveKnotVector(); + const FloatArray *knotVector = interp->giveKnotVector(); const IntArray *span; int j, nsd = this->giveNsd(); FloatArray c [ 4 ], cg [ 4 ], u; @@ -265,7 +265,7 @@ void NURBSPlaneStressElement :: drawScalar(oofegGraphicContext &gc, TimeStep *tS EASValsSetLayer(OOFEG_VARPLOT_PATTERN_LAYER); EASValsSetFillStyle(FILL_SOLID); EASValsSetEdgeFlag(true); - const double *const *knotVector = interp->giveKnotVector(); + const FloatArray *knotVector = interp->giveKnotVector(); const IntArray *span; int j, nsd = this->giveNsd(); FloatArray c [ 4 ], cg [ 4 ]; @@ -467,7 +467,7 @@ void TSplinePlaneStressElement :: drawScalar(oofegGraphicContext &gc, TimeStep * EASValsSetLayer(OOFEG_VARPLOT_PATTERN_LAYER); EASValsSetFillStyle(FILL_SOLID); EASValsSetEdgeFlag(true); - const double *const *knotVector = interp->giveKnotVector(); + const FloatArray *knotVector = interp->giveKnotVector(); const IntArray *span; int j, nsd = this->giveNsd(); FloatArray c [ 4 ], cg [ 4 ], u; @@ -580,7 +580,7 @@ void NURBSSpace3dElement :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep) EASValsSetLayer(OOFEG_VARPLOT_PATTERN_LAYER); EASValsSetFillStyle(FILL_SOLID); EASValsSetEdgeFlag(true); - const double *const *knotVector = interp->giveKnotVector(); + const FloatArray *knotVector = interp->giveKnotVector(); const IntArray *span; int j, nsd = this->giveNsd(); FloatArray c [ 8 ], cg [ 8 ]; diff --git a/src/sm/Elements/igaelements.h b/src/sm/Elements/igaelements.h index 9d2c25b8f..3f83b49dd 100644 --- a/src/sm/Elements/igaelements.h +++ b/src/sm/Elements/igaelements.h @@ -39,8 +39,8 @@ #include "iga/feibspline.h" #include "iga/feinurbs.h" #include "iga/feitspline.h" -#include "../sm/Elements/PlaneStress/planestresselementevaluator.h" -#include "../sm/Elements/3D/space3delementevaluator.h" +#include "sm/Elements/PlaneStress/planestresselementevaluator.h" +#include "sm/Elements/3D/space3delementevaluator.h" #include "floatarray.h" #include "floatmatrix.h" #include "matresponsemode.h" @@ -60,37 +60,37 @@ class BsplinePlaneStressElement : public IGAElement, public PlaneStressStructura public: BsplinePlaneStressElement(int n, Domain * aDomain); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int checkConsistency(); + void initializeFrom(InputRecord &ir) override; + int checkConsistency() override; - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) { + void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) override { PlaneStressStructuralElementEvaluator :: giveCharacteristicMatrix(answer, mtrx, tStep); } - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *t) { + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *t) override { PlaneStressStructuralElementEvaluator :: giveCharacteristicVector(answer, type, mode, t); } - virtual FEInterpolation *giveInterpolation() const { return const_cast< BSplineInterpolation * >(& this->interpolation); } - virtual Element *giveElement() { return this; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const { + FEInterpolation *giveInterpolation() const override { return const_cast< BSplineInterpolation * >(& this->interpolation); } + Element *giveElement() override { return this; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override { PlaneStressStructuralElementEvaluator :: giveDofManDofIDMask(inode, answer); } - virtual int computeNumberOfDofs() { return numberOfDofMans * 2; } - virtual void updateInternalState(TimeStep *tStep) { PlaneStressStructuralElementEvaluator :: updateInternalState(tStep); } + int computeNumberOfDofs() override { return numberOfDofMans * 2; } + void updateInternalState(TimeStep *tStep) override { PlaneStressStructuralElementEvaluator :: updateInternalState(tStep); } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_BsplinePlaneStressElement_Name; } - virtual const char *giveClassName() const { return "BsplinePlaneStressElement"; } + const char *giveInputRecordName() const override { return _IFT_BsplinePlaneStressElement_Name; } + const char *giveClassName() const override { return "BsplinePlaneStressElement"; } #ifdef __OOFEG // Graphics output - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType ut) { + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType ut) override { drawIGAPatchDeformedGeometry(this, this, gc, tStep, ut); } #endif protected: - virtual int giveNsd() { return 2; } + int giveNsd() override { return 2; } }; @@ -102,39 +102,39 @@ class NURBSPlaneStressElement : public IGAElement, public PlaneStressStructuralE public: NURBSPlaneStressElement(int n, Domain * aDomain); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int checkConsistency(); + void initializeFrom(InputRecord &ir) override; + int checkConsistency() override; - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) { + void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) override { PlaneStressStructuralElementEvaluator :: giveCharacteristicMatrix(answer, mtrx, tStep); } - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *t) { + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *t) override { PlaneStressStructuralElementEvaluator :: giveCharacteristicVector(answer, type, mode, t); } - virtual FEInterpolation *giveInterpolation() const { return const_cast< NURBSInterpolation * >(& this->interpolation); } - virtual Element *giveElement() { return this; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const { + FEInterpolation *giveInterpolation() const override { return const_cast< NURBSInterpolation * >(& this->interpolation); } + Element *giveElement() override { return this; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override { PlaneStressStructuralElementEvaluator :: giveDofManDofIDMask(inode, answer); } - virtual int computeNumberOfDofs() { return numberOfDofMans * 2; } - virtual void updateInternalState(TimeStep *tStep) { PlaneStressStructuralElementEvaluator :: updateInternalState(tStep); } + int computeNumberOfDofs() override { return numberOfDofMans * 2; } + void updateInternalState(TimeStep *tStep) override { PlaneStressStructuralElementEvaluator :: updateInternalState(tStep); } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_NURBSPlaneStressElement_Name; } - virtual const char *giveClassName() const { return "NURBSPlaneStressElement"; } + const char *giveInputRecordName() const override { return _IFT_NURBSPlaneStressElement_Name; } + const char *giveClassName() const override { return "NURBSPlaneStressElement"; } #ifdef __OOFEG // // Graphics output // - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType ut) { + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType ut) override { drawIGAPatchDeformedGeometry(this, this, gc, tStep, ut); } #endif protected: - virtual int giveNsd() { return 2; } + int giveNsd() override { return 2; } }; @@ -147,36 +147,35 @@ class TSplinePlaneStressElement : public IGATSplineElement, public PlaneStressSt public: TSplinePlaneStressElement(int n, Domain * aDomain); - virtual IRResultType initializeFrom(InputRecord *ir) { + void initializeFrom(InputRecord &ir) override { IGATSplineElement :: initializeFrom(ir); //PlaneStressStructuralElementEvaluator::initializeFrom(ir); - return IRRT_OK; } - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) { + void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) override { PlaneStressStructuralElementEvaluator :: giveCharacteristicMatrix(answer, mtrx, tStep); } - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *t) { + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *t) override { PlaneStressStructuralElementEvaluator :: giveCharacteristicVector(answer, type, mode, t); } - virtual FEInterpolation *giveInterpolation() const { return const_cast< TSplineInterpolation * >(& this->interpolation); } - virtual Element *giveElement() { return this; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const { + FEInterpolation *giveInterpolation() const override { return const_cast< TSplineInterpolation * >(& this->interpolation); } + Element *giveElement() override { return this; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override { PlaneStressStructuralElementEvaluator :: giveDofManDofIDMask(inode, answer); } - virtual int computeNumberOfDofs() { return numberOfDofMans * 2; } - virtual void updateInternalState(TimeStep *tStep) { PlaneStressStructuralElementEvaluator :: updateInternalState(tStep); } + int computeNumberOfDofs() override { return numberOfDofMans * 2; } + void updateInternalState(TimeStep *tStep) override { PlaneStressStructuralElementEvaluator :: updateInternalState(tStep); } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_TSplinePlaneStressElement_Name; } - virtual const char *giveClassName() const { return "TSplinePlaneStressElement"; } + const char *giveInputRecordName() const override { return _IFT_TSplinePlaneStressElement_Name; } + const char *giveClassName() const override { return "TSplinePlaneStressElement"; } #ifdef __OOFEG // Graphics output - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif protected: - virtual int giveNsd() { return 2; } + int giveNsd() override { return 2; } }; @@ -188,37 +187,37 @@ class NURBSSpace3dElement : public IGAElement, public Space3dStructuralElementEv public: NURBSSpace3dElement(int n, Domain * aDomain); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int checkConsistency(); + void initializeFrom(InputRecord &ir) override; + int checkConsistency() override; - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) { + void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) override { Space3dStructuralElementEvaluator :: giveCharacteristicMatrix(answer, mtrx, tStep); } - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *t) { + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *t) override { Space3dStructuralElementEvaluator :: giveCharacteristicVector(answer, type, mode, t); } - virtual FEInterpolation *giveInterpolation() const { return const_cast< NURBSInterpolation * >(& this->interpolation); } - virtual Element *giveElement() { return this; } + FEInterpolation *giveInterpolation() const override { return const_cast< NURBSInterpolation * >(& this->interpolation); } + Element *giveElement() override { return this; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const { + void giveDofManDofIDMask(int inode, IntArray &answer) const override { Space3dStructuralElementEvaluator :: giveDofManDofIDMask(inode, answer); } - virtual int computeNumberOfDofs() { return numberOfDofMans * 3; } - virtual void updateInternalState(TimeStep *tStep) { Space3dStructuralElementEvaluator :: updateInternalState(tStep); } + int computeNumberOfDofs() override { return numberOfDofMans * 3; } + void updateInternalState(TimeStep *tStep) override { Space3dStructuralElementEvaluator :: updateInternalState(tStep); } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_NURBSSpace3dElement_Name; } - virtual const char *giveClassName() const { return "NURBSSpace3dElement"; } + const char *giveInputRecordName() const override { return _IFT_NURBSSpace3dElement_Name; } + const char *giveClassName() const override { return "NURBSSpace3dElement"; } #ifdef __OOFEG // Graphics output - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType ut) { + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType ut) override { drawIGAPatchDeformedGeometry(this, this, gc, tStep, ut); } #endif protected: - virtual int giveNsd() { return 3; } + int giveNsd() override { return 3; } }; } // end namespace oofem #endif //igaelements_h diff --git a/src/sm/Elements/lattice2d.h b/src/sm/Elements/lattice2d.h deleted file mode 100644 index d3d0de65a..000000000 --- a/src/sm/Elements/lattice2d.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef lattice2d_h -#define lattice2d_h - -#include "../sm/Elements/latticestructuralelement.h" - -///@name Input fields for Lattice2d -//@{ -#define _IFT_Lattice2d_Name "lattice2d" -#define _IFT_Lattice2d_thick "thick" -#define _IFT_Lattice2d_width "width" -#define _IFT_Lattice2d_gpcoords "gpcoords" -#define _IFT_Lattice2d_couplingflag "couplingflag" -#define _IFT_Lattice2d_couplingnumber "couplingnumber" -//@} - -namespace oofem { -/** - * This class implements a 2-dimensional lattice element - */ -class Lattice2d : public LatticeStructuralElement -{ -protected: - double kappa, pitch, length; - - double width, thickness; - FloatArray gpCoords; - int couplingFlag; - IntArray couplingNumbers; - -public: - Lattice2d(int n, Domain *d); - virtual ~Lattice2d(); - - virtual int giveLocalCoordinateSystem(FloatMatrix &answer); - - /** - * This function is different from the standard computeGlobalCorrdinates - * function as it returns the global coordinates of the gausspoint - * independent to the value of the lcoords. - */ - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); - - virtual double giveLength(); - - virtual double giveNormalStress(); - virtual double giveOldNormalStress(); - - virtual int hasBeenUpdated(); - - virtual double giveArea() { return this->width * this->thickness; } - - virtual int computeNumberOfDofs() { return 6; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual double computeVolumeAround(GaussPoint *gp); - - virtual int giveCrackFlag(); - - virtual double giveCrackWidth(); - virtual double giveOldCrackWidth(); - - virtual double giveDissipation(); - virtual double giveDeltaDissipation(); - - virtual int giveCouplingFlag() { return couplingFlag; } - - virtual void giveCouplingNumbers(IntArray &numbers) { numbers = this->couplingNumbers; } - // - // definition & identification - // - virtual const char *giveInputRecordName() const { return _IFT_Lattice2d_Name; } - virtual const char *giveClassName() const { return "Lattice2d"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } - -#ifdef __OOFEG - virtual void drawYourself(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawSpecial(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tStep); - virtual void giveCrossSectionCoordinates(FloatArray &coords); - -#endif - -protected: - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - - virtual void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS); - virtual bool computeGtoLRotationMatrix(FloatMatrix &); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - - virtual int giveNumberOfCrossSectionNodes() { return 2; } - double givePitch(); - virtual void computeGaussPoints(); - virtual integrationDomain giveIntegrationDomain() const { return _Line; } - virtual void giveGpCoordinates(FloatArray &coords); -}; -} // end namespace oofem -#endif diff --git a/src/sm/Elements/linedistributedspring.C b/src/sm/Elements/linedistributedspring.C index 45fec6b87..fecf59b59 100644 --- a/src/sm/Elements/linedistributedspring.C +++ b/src/sm/Elements/linedistributedspring.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/linedistributedspring.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/linedistributedspring.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei3dlinelin.h" #include "node.h" #include "material.h" @@ -79,7 +79,7 @@ LineDistributedSpring :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 5) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 5); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } @@ -150,10 +150,10 @@ LineDistributedSpring::giveInternalForcesVector(FloatArray &answer, -IRResultType -LineDistributedSpring :: initializeFrom(InputRecord *ir) +void +LineDistributedSpring :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralElement::initializeFrom(ir); IR_GIVE_FIELD (ir, dofs, _IFT_LineDistributedSpring_Dofs); IR_GIVE_FIELD (ir, springStiffnesses, _IFT_LineDistributedSpring_Stifnesses); @@ -161,8 +161,6 @@ LineDistributedSpring :: initializeFrom(InputRecord *ir) if (dofs.giveSize() != springStiffnesses.giveSize()) { OOFEM_ERROR ("dofs and k params size mismatch"); } - // from element - return StructuralElement::initializeFrom(ir); } int diff --git a/src/sm/Elements/linedistributedspring.h b/src/sm/Elements/linedistributedspring.h index bec658804..fb7a88a96 100644 --- a/src/sm/Elements/linedistributedspring.h +++ b/src/sm/Elements/linedistributedspring.h @@ -35,7 +35,7 @@ #ifndef linedistributedspring_H #define linedistributedspring_H -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -66,44 +66,44 @@ public SPRNodalRecoveryModelInterface LineDistributedSpring(int n, Domain * d); virtual ~LineDistributedSpring() { } - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; - virtual MaterialMode giveMaterialMode() { return _Unknown; } + MaterialMode giveMaterialMode() override { return _Unknown; } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LineDistributedSpring_Name; } - virtual const char *giveClassName() const { return "LineDistributedSpring"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_LineDistributedSpring_Name; } + const char *giveClassName() const override { return "LineDistributedSpring"; } + void initializeFrom(InputRecord &ir) override; - virtual int computeNumberOfDofs() { return this->dofs.giveSize(); } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return this->dofs.giveSize(); } + void giveDofManDofIDMask(int inode, IntArray &) const override; - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } void giveInternalForcesVector(FloatArray &answer, - TimeStep *tStep, int useUpdatedGpRecord); + TimeStep *tStep, int useUpdatedGpRecord) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual Interface *giveInterface(InterfaceType it); - int checkConsistency(); - void printOutputAt(FILE *File, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + Interface *giveInterface(InterfaceType it) override; + int checkConsistency() override; + void printOutputAt(FILE *File, TimeStep *tStep) override; protected: - virtual void computeGaussPoints(); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); + void computeGaussPoints() override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP() { return this->numberOfGaussPoints; } - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType() { return SPRPatchType_2dxy; } + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override { return this->numberOfGaussPoints; } + SPRPatchType SPRNodalRecoveryMI_givePatchType() override { return SPRPatchType_2dxy; } }; } // end namespace oofem #endif // linedistributedspring_H diff --git a/src/sm/Elements/lumpedmasselement.C b/src/sm/Elements/lumpedmasselement.C index b7b140830..c80026d2c 100644 --- a/src/sm/Elements/lumpedmasselement.C +++ b/src/sm/Elements/lumpedmasselement.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/lumpedmasselement.h" +#include "sm/Elements/lumpedmasselement.h" #include "dofmanager.h" #include "dof.h" #include "floatmatrix.h" @@ -49,7 +49,6 @@ namespace oofem { REGISTER_Element(LumpedMassElement); LumpedMassElement :: LumpedMassElement(int n, Domain *aDomain) : StructuralElement(n, aDomain) - // Constructor. { numberOfDofMans = 1; } @@ -57,8 +56,6 @@ LumpedMassElement :: LumpedMassElement(int n, Domain *aDomain) : StructuralEleme void LumpedMassElement :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) -// Returns the lumped mass matrix of the receiver. This expression is -// valid in both local and global axes. { int ndofs = this->computeNumberOfDofs(); answer.resize(ndofs, ndofs); @@ -67,27 +64,22 @@ LumpedMassElement :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tSte } -IRResultType -LumpedMassElement :: initializeFrom(InputRecord *ir) +void +LumpedMassElement :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralElement :: initializeFrom(ir); + IR_GIVE_FIELD(ir, dofs, _IFT_LumpedMassElement_dofs); IR_GIVE_FIELD(ir, components, _IFT_LumpedMassElement_components); - - return StructuralElement :: initializeFrom(ir); } int LumpedMassElement :: checkConsistency() -// -// check internal consistency -// { int _result = StructuralElement :: checkConsistency(); - int _ndofs = this->computeNumberOfDofs(); - if ( _ndofs != this->components.giveSize() ) { - OOFEM_WARNING("component array size mismatch"); + if ( this->dofs.giveSize() != this->components.giveSize() ) { + OOFEM_WARNING("component/dof array size mismatch"); _result = 0; } @@ -98,37 +90,14 @@ LumpedMassElement :: checkConsistency() int LumpedMassElement :: computeNumberOfDofs() { - DofManager *dman = this->giveDofManager(1); - int answer = 0; - - // simply count all "structural" dofs of element node - for ( Dof *dof: *dman ) { - DofIDItem _dofid = dof->giveDofID(); - if ( ( _dofid == D_u ) || ( _dofid == D_v ) || ( _dofid == D_w ) || - ( _dofid == R_u ) || ( _dofid == R_v ) || ( _dofid == R_w ) ) { - answer++; - } - } - - return answer; + return dofs.giveSize(); } void LumpedMassElement :: giveDofManDofIDMask(int inode, IntArray &answer) const { - answer.resize(6); - answer.clear(); - DofManager *dman = this->giveDofManager(inode); - - // simply collect all "structural" dofs of element node - for ( Dof *dof: *dman ) { - DofIDItem _dofid = dof->giveDofID(); - if ( ( _dofid == D_u ) || ( _dofid == D_v ) || ( _dofid == D_w ) || - ( _dofid == R_u ) || ( _dofid == R_v ) || ( _dofid == R_w ) ) { - answer.followedBy(_dofid); - } - } + answer = dofs; } #ifdef __OOFEG diff --git a/src/sm/Elements/lumpedmasselement.h b/src/sm/Elements/lumpedmasselement.h index 596cce771..ac4db260d 100644 --- a/src/sm/Elements/lumpedmasselement.h +++ b/src/sm/Elements/lumpedmasselement.h @@ -35,12 +35,13 @@ #ifndef lumpedmasselement_h #define lumpedmasselement_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" ///@name Input fields for lumped mass element //@{ #define _IFT_LumpedMassElement_Name "lumpedmass" #define _IFT_LumpedMassElement_components "components" +#define _IFT_LumpedMassElement_dofs "dofs" //@} namespace oofem { @@ -54,52 +55,54 @@ namespace oofem { class LumpedMassElement : public StructuralElement { protected: - ///Mass and moments of inertia corresponding to nodal DOFs + /// Mass and moments of inertia corresponding to the specified DOFs FloatArray components; + /// List of DOFs + IntArray dofs; public: LumpedMassElement(int n, Domain * d); virtual ~LumpedMassElement() { } - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override { answer.clear(); } - virtual void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override { answer.clear(); } - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override { answer.clear(); } - virtual int computeNumberOfDofs(); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + int computeNumberOfDofs() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual void updateInternalState(TimeStep *tStep) { } - virtual void updateYourself(TimeStep *tStep) { } - virtual int checkConsistency(); + void updateInternalState(TimeStep *tStep) override { } + void updateYourself(TimeStep *tStep) override { } + int checkConsistency() override; #ifdef __OOFEG - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_LumpedMassElement_Name; } - virtual const char *giveClassName() const { return "LumpedMassElement"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Element_Geometry_Type giveGeometryType() const { return EGT_point; } + const char *giveInputRecordName() const override { return _IFT_LumpedMassElement_Name; } + const char *giveClassName() const override { return "LumpedMassElement"; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_point; } protected: - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override { answer.clear(); } - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override { answer.clear(); } - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, - int lowerIndx = 1, int upperIndx = ALL_STRAINS) + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, + int lowerIndx = 1, int upperIndx = ALL_STRAINS) override { answer.clear(); } - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) { answer.clear(); } + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override { answer.clear(); } }; } // end namespace oofem #endif // lumpedmasselement_h diff --git a/src/sm/Elements/nlstructuralelement.C b/src/sm/Elements/nlstructuralelement.C index 231147121..41c73b86b 100644 --- a/src/sm/Elements/nlstructuralelement.C +++ b/src/sm/Elements/nlstructuralelement.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/nlstructuralelement.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/nlstructuralelement.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "feinterpol.h" #include "domain.h" #include "material.h" @@ -49,7 +49,7 @@ #include "mathfem.h" namespace oofem { -NLStructuralElement :: NLStructuralElement(int n, Domain *aDomain) : +NLStructuralElement::NLStructuralElement(int n, Domain *aDomain) : StructuralElement(n, aDomain) // Constructor. Creates an element with number n, belonging to aDomain. { @@ -58,10 +58,10 @@ NLStructuralElement :: NLStructuralElement(int n, Domain *aDomain) : double -NLStructuralElement :: computeCurrentVolume(TimeStep *tStep) +NLStructuralElement::computeCurrentVolume(TimeStep *tStep) { - double vol=0.0; - for ( auto &gp: *this->giveDefaultIntegrationRulePtr() ) { + double vol = 0.0; + for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) { FloatArray F; FloatMatrix Fm; @@ -71,7 +71,7 @@ NLStructuralElement :: computeCurrentVolume(TimeStep *tStep) double J = Fm.giveDeterminant(); FEInterpolation *interpolation = this->giveInterpolation(); - double detJ = fabs( ( interpolation->giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ) ); + double detJ = fabs( ( interpolation->giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ) ); vol += gp->giveWeight() * detJ * J; } @@ -81,7 +81,7 @@ NLStructuralElement :: computeCurrentVolume(TimeStep *tStep) void -NLStructuralElement :: computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +NLStructuralElement::computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { // Computes the deformation gradient in the Voigt format at the Gauss point gp of // the receiver at time step tStep. @@ -89,7 +89,7 @@ NLStructuralElement :: computeDeformationGradientVector(FloatArray &answer, Gaus // Obtain the current displacement vector of the element and subtract initial displacements (if present) FloatArray u; - this->computeVectorOf({D_u, D_v, D_w}, VM_Total, tStep, u); // solution vector + this->computeVectorOf({ D_u, D_v, D_w }, VM_Total, tStep, u); // solution vector if ( initialDisplacements ) { u.subtract(* initialDisplacements); } @@ -117,7 +117,7 @@ NLStructuralElement :: computeDeformationGradientVector(FloatArray &answer, Gaus void -NLStructuralElement :: computeFirstPKStressVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +NLStructuralElement::computeFirstPKStressVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { // Computes the first Piola-Kirchhoff stress vector containing the stresses at the Gauss point // gp of the receiver at time step tStep. The deformation gradient F is computed and sent as @@ -126,11 +126,11 @@ NLStructuralElement :: computeFirstPKStressVector(FloatArray &answer, GaussPoint FloatArray vF; this->computeDeformationGradientVector(vF, gp, tStep); - cs->giveFirstPKStresses(answer, gp, vF, tStep); + answer = cs->giveFirstPKStresses(vF, gp, tStep); } void -NLStructuralElement :: computeCauchyStressVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +NLStructuralElement::computeCauchyStressVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { // Computes the first Piola-Kirchhoff stress vector containing the stresses at the Gauss point // gp of the receiver at time step tStep. The deformation gradient F is computed and sent as @@ -143,7 +143,7 @@ NLStructuralElement :: computeCauchyStressVector(FloatArray &answer, GaussPoint } void -NLStructuralElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +NLStructuralElement::giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { FloatMatrix B; FloatArray vStress, vStrain, u; @@ -158,7 +158,7 @@ NLStructuralElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tS // zero answer will resize accordingly when adding first contribution answer.clear(); - for ( auto &gp: *this->giveDefaultIntegrationRulePtr() ) { + for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) { StructuralMaterialStatus *matStat = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); // Engineering (small strain) stress @@ -169,7 +169,7 @@ NLStructuralElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tS } else { ///@todo Is this really what we should do for inactive elements? if ( !this->isActivated(tStep) ) { - vStrain.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + vStrain.resize(StructuralMaterial::giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); vStrain.zero(); } vStrain.beProductOf(B, u); @@ -206,12 +206,12 @@ NLStructuralElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tS if ( nlGeometry == 1 ) { // First Piola-Kirchhoff stress if ( vStress.giveSize() == 9 ) { FloatArray stressTemp; - StructuralMaterial :: giveReducedVectorForm( stressTemp, vStress, gp->giveMaterialMode() ); + StructuralMaterial::giveReducedVectorForm(stressTemp, vStress, gp->giveMaterialMode() ); answer.plusProduct(B, stressTemp, dV); - } else { + } else { answer.plusProduct(B, vStress, dV); } - } else { + } else { if ( vStress.giveSize() == 6 ) { // It may happen that e.g. plane strain is computed // using the default 3D implementation. If so, @@ -219,9 +219,9 @@ NLStructuralElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tS // (Note that no reduction will take place if // the simulation is actually 3D.) FloatArray stressTemp; - StructuralMaterial :: giveReducedSymVectorForm( stressTemp, vStress, gp->giveMaterialMode() ); + StructuralMaterial::giveReducedSymVectorForm(stressTemp, vStress, gp->giveMaterialMode() ); answer.plusProduct(B, stressTemp, dV); - } else { + } else { answer.plusProduct(B, vStress, dV); } } @@ -236,8 +236,8 @@ NLStructuralElement :: giveInternalForcesVector(FloatArray &answer, TimeStep *tS void -NLStructuralElement :: giveInternalForcesVector_withIRulesAsSubcells(FloatArray &answer, - TimeStep *tStep, int useUpdatedGpRecord) +NLStructuralElement::giveInternalForcesVector_withIRulesAsSubcells(FloatArray &answer, + TimeStep *tStep, int useUpdatedGpRecord) { /* * Returns nodal representation of real internal forces computed from first Piola-Kirchoff stress @@ -263,8 +263,8 @@ NLStructuralElement :: giveInternalForcesVector_withIRulesAsSubcells(FloatArray // loop over individual integration rules - for ( auto &iRule: integrationRulesArray ) { - for ( GaussPoint *gp: *iRule ) { + for ( auto &iRule : integrationRulesArray ) { + for ( GaussPoint *gp : * iRule ) { StructuralMaterialStatus *matStat = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); if ( nlGeometry == 0 ) { @@ -304,7 +304,7 @@ NLStructuralElement :: giveInternalForcesVector_withIRulesAsSubcells(FloatArray m->plusProduct(B, vStress, dV); // localize irule contribution into element matrix - if ( this->giveIntegrationRuleLocalCodeNumbers(irlocnum, *iRule) ) { + if ( this->giveIntegrationRuleLocalCodeNumbers(irlocnum, * iRule) ) { answer.assemble(* m, irlocnum); m->clear(); } @@ -324,8 +324,8 @@ NLStructuralElement :: giveInternalForcesVector_withIRulesAsSubcells(FloatArray void -NLStructuralElement :: computeStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, TimeStep *tStep) +NLStructuralElement::computeStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, TimeStep *tStep) { StructuralCrossSection *cs = this->giveStructuralCrossSection(); bool matStiffSymmFlag = cs->isCharacteristicMtrxSymmetric(rMode); @@ -339,8 +339,7 @@ NLStructuralElement :: computeStiffnessMatrix(FloatMatrix &answer, // Compute matrix from material stiffness (total stiffness for small def.) - B^T * dS/dE * B if ( integrationRulesArray.size() == 1 ) { FloatMatrix B, D, DB; - for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { - + for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) { // Engineering (small strain) stiffness if ( nlGeometry == 0 ) { this->computeBmatrixAt(gp, B); @@ -352,8 +351,7 @@ NLStructuralElement :: computeStiffnessMatrix(FloatMatrix &answer, cs->giveStiffnessMatrix_dCde(D, rMode, gp, tStep); } else { // Material stiffness dP/dF this->computeBHmatrixAt(gp, B); - /// @todo We probably need overloaded function (like above) here as well. - cs->giveStiffnessMatrix_dPdF(D, rMode, gp, tStep); + this->computeConstitutiveMatrix_dPdF_At(D, rMode, gp, tStep); } } @@ -378,10 +376,10 @@ NLStructuralElement :: computeStiffnessMatrix(FloatMatrix &answer, int iStartIndx, iEndIndx, jStartIndx, jEndIndx; FloatMatrix Bi, Bj, D, Dij, DBj; - for ( int i = 0; i < (int)integrationRulesArray.size(); i++ ) { + for ( int i = 0; i < ( int ) integrationRulesArray.size(); i++ ) { iStartIndx = integrationRulesArray [ i ]->getStartIndexOfLocalStrainWhereApply(); iEndIndx = integrationRulesArray [ i ]->getEndIndexOfLocalStrainWhereApply(); - for ( int j = 0; j < (int)integrationRulesArray.size(); j++ ) { + for ( int j = 0; j < ( int ) integrationRulesArray.size(); j++ ) { IntegrationRule *iRule; jStartIndx = integrationRulesArray [ j ]->getStartIndexOfLocalStrainWhereApply(); jEndIndx = integrationRulesArray [ j ]->getEndIndexOfLocalStrainWhereApply(); @@ -393,8 +391,7 @@ NLStructuralElement :: computeStiffnessMatrix(FloatMatrix &answer, iRule = integrationRulesArray [ j ].get(); } - for ( GaussPoint *gp: *iRule ) { - + for ( GaussPoint *gp : * iRule ) { // Engineering (small strain) stiffness dSig/dEps if ( nlGeometry == 0 ) { this->computeBmatrixAt(gp, Bi, iStartIndx, iEndIndx); @@ -405,7 +402,8 @@ NLStructuralElement :: computeStiffnessMatrix(FloatMatrix &answer, cs->giveStiffnessMatrix_dCde(D, rMode, gp, tStep); } else { // Material stiffness dP/dF this->computeBHmatrixAt(gp, Bi); - cs->giveStiffnessMatrix_dPdF(D, rMode, gp, tStep); + this->computeConstitutiveMatrix_dPdF_At(D, rMode, gp, tStep); + //cs->giveStiffnessMatrix_dPdF(D, rMode, gp, tStep); } } @@ -444,8 +442,8 @@ NLStructuralElement :: computeStiffnessMatrix(FloatMatrix &answer, void -NLStructuralElement :: computeStiffnessMatrix_withIRulesAsSubcells(FloatMatrix &answer, - MatResponseMode rMode, TimeStep *tStep) +NLStructuralElement::computeStiffnessMatrix_withIRulesAsSubcells(FloatMatrix &answer, + MatResponseMode rMode, TimeStep *tStep) { StructuralCrossSection *cs = this->giveStructuralCrossSection(); bool matStiffSymmFlag = cs->isCharacteristicMtrxSymmetric(rMode); @@ -464,9 +462,8 @@ NLStructuralElement :: computeStiffnessMatrix_withIRulesAsSubcells(FloatMatrix & // Compute matrix from material stiffness FloatMatrix B, D, DB; IntArray irlocnum; - for ( auto &iRule: integrationRulesArray ) { - for ( auto &gp : *iRule ) { - + for ( auto &iRule : integrationRulesArray ) { + for ( auto &gp : * iRule ) { if ( nlGeometry == 0 ) { this->computeBmatrixAt(gp, B); this->computeConstitutiveMatrixAt(D, rMode, gp, tStep); @@ -476,7 +473,8 @@ NLStructuralElement :: computeStiffnessMatrix_withIRulesAsSubcells(FloatMatrix & cs->giveStiffnessMatrix_dCde(D, rMode, gp, tStep); } else { // Material stiffness dP/dF this->computeBHmatrixAt(gp, B); - cs->giveStiffnessMatrix_dPdF(D, rMode, gp, tStep); + this->computeConstitutiveMatrix_dPdF_At(D, rMode, gp, tStep); + //cs->giveStiffnessMatrix_dPdF(D, rMode, gp, tStep); } } @@ -490,7 +488,7 @@ NLStructuralElement :: computeStiffnessMatrix_withIRulesAsSubcells(FloatMatrix & } // localize irule contribution into element matrix - if ( this->giveIntegrationRuleLocalCodeNumbers(irlocnum, *iRule) ) { + if ( this->giveIntegrationRuleLocalCodeNumbers(irlocnum, * iRule) ) { answer.assemble(* m, irlocnum); m->clear(); } @@ -502,77 +500,26 @@ NLStructuralElement :: computeStiffnessMatrix_withIRulesAsSubcells(FloatMatrix & } -void -NLStructuralElement :: computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) -{ - FloatArray stress; - FloatMatrix B, stress_ident, stress_identFull; - IntArray indx; - answer.clear(); - - // assemble initial stress matrix - for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { - // This function fetches the full form of the tensor - this->giveIPValue(stress, gp, IST_StressTensor, tStep); - if ( stress.giveSize() ) { - // Construct the stress_ident matrix - // The complicated part, the not-so-pretty product here: s_il delta_jk - { - stress_identFull.at(1, 1) = stress.at(1); - stress_identFull.at(2, 2) = stress.at(2); - stress_identFull.at(3, 3) = stress.at(3); - stress_identFull.at(4, 4) = stress.at(2) + stress.at(3); - stress_identFull.at(5, 5) = stress.at(1) + stress.at(3); - stress_identFull.at(6, 6) = stress.at(1) + stress.at(2); - - stress_identFull.at(1, 5) = stress.at(5); - stress_identFull.at(1, 6) = stress.at(6); - - stress_identFull.at(2, 4) = stress.at(4); - stress_identFull.at(2, 5) = stress.at(6); - - stress_identFull.at(3, 4) = stress.at(4); - stress_identFull.at(3, 5) = stress.at(5); - - stress_identFull.at(4, 5) = stress.at(6); - stress_identFull.at(4, 6) = stress.at(5); - stress_identFull.at(5, 6) = stress.at(4); - } - stress_ident.beSubMatrixOf(stress_identFull, indx, indx); - stress_ident.symmetrized(); - OOFEM_WARNING("Implementation not tested yet!"); - this->computeBmatrixAt(gp, B); - answer.plusProductSymmUpper( B, stress_ident, this->computeVolumeAround(gp) ); - } - } - - answer.symmetrized(); -} - - - -IRResultType -NLStructuralElement :: initializeFrom(InputRecord *ir) +void +NLStructuralElement::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralElement::initializeFrom(ir); nlGeometry = 0; IR_GIVE_OPTIONAL_FIELD(ir, nlGeometry, _IFT_NLStructuralElement_nlgeoflag); - - return StructuralElement :: initializeFrom(ir); } -void NLStructuralElement :: giveInputRecord(DynamicInputRecord &input) +void NLStructuralElement::giveInputRecord(DynamicInputRecord &input) { - StructuralElement :: giveInputRecord(input); + StructuralElement::giveInputRecord(input); input.setField(nlGeometry, _IFT_NLStructuralElement_nlgeoflag); } int -NLStructuralElement :: checkConsistency() +NLStructuralElement::checkConsistency() { if ( this->nlGeometry == 2 ) { OOFEM_ERROR("nlGeometry = 2 is not supported anymore. If access to F is needed, then the material \n should overload giveFirstPKStressVector which has F as input."); diff --git a/src/sm/Elements/nlstructuralelement.h b/src/sm/Elements/nlstructuralelement.h index 6fa53c69e..d33445f6f 100644 --- a/src/sm/Elements/nlstructuralelement.h +++ b/src/sm/Elements/nlstructuralelement.h @@ -35,7 +35,7 @@ #ifndef nlstructuralelement_h #define nlstructuralelement_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" ///@name Input fields for NLStructuralElement //@{ @@ -95,7 +95,7 @@ class NLStructuralElement : public StructuralElement * @param n Element number. * @param d Domain to which new material will belong. */ - NLStructuralElement(int n, Domain * d); + NLStructuralElement(int n, Domain *d); /// Destructor. virtual ~NLStructuralElement() { } @@ -141,7 +141,8 @@ class NLStructuralElement : public StructuralElement * @param rMode Response mode. * @param tStep Time step. */ - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + /** @@ -152,7 +153,8 @@ class NLStructuralElement : public StructuralElement * @param answer Computed initial stiffness matrix. * @param tStep Time step. */ - virtual void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep); + void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override + { OOFEM_ERROR("Method computeInitialStressMatrix is not implemented"); } /** * Computes the stiffness matrix of receiver. @@ -179,7 +181,20 @@ class NLStructuralElement : public StructuralElement * @param useUpdatedGpRecord If equal to zero, the stresses in integration points are computed (slow but safe). */ - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + + /** + * Computes large strain constitutive matrix of receiver. Default implementation uses element cross section + * giveCharMaterialStiffnessMatrix service. + * @param answer Constitutive matrix. + * @param rMode Material response mode of answer. + * @param gp Integration point for which constitutive matrix is computed. + * @param tStep Time step. + */ + virtual void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, + MatResponseMode rMode, GaussPoint *gp, + TimeStep *tStep) = 0; + /** * Evaluates nodal representation of real internal forces. @@ -193,7 +208,7 @@ class NLStructuralElement : public StructuralElement * @param tStep Time step. * @param useUpdatedGpRecord If equal to zero, the stresses in the integration points are computed (slow but safe). */ - void giveInternalForcesVector_withIRulesAsSubcells(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + void giveInternalForcesVector_withIRulesAsSubcells(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; /** * Computes the deformation gradient in Voigt form at integration point ip and at time @@ -206,19 +221,19 @@ class NLStructuralElement : public StructuralElement virtual void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); /** - * Computes the current volume of element - */ + * Computes the current volume of element + */ double computeCurrentVolume(TimeStep *tStep); // data management - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; // definition - virtual const char *giveClassName() const { return "NLStructuralElement"; } + const char *giveClassName() const override { return "NLStructuralElement"; } protected: - virtual int checkConsistency(); + int checkConsistency() override; /** * Computes a matrix which, multiplied by the column matrix of nodal displacements, * gives the displacement gradient stored by columns. @@ -227,12 +242,11 @@ class NLStructuralElement : public StructuralElement * @param gp Integration point. * @param answer BF matrix at this point. */ - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) { OOFEM_ERROR("method not implemented for this element"); return; } - friend class GradDpElement; + friend class GradientDamageElement; friend class PhaseFieldElement; friend class XfemStructuralElementInterface; }; diff --git a/src/sm/Elements/nodalspringelement.C b/src/sm/Elements/nodalspringelement.C index 2993e35ad..90a929a53 100644 --- a/src/sm/Elements/nodalspringelement.C +++ b/src/sm/Elements/nodalspringelement.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/nodalspringelement.h" +#include "sm/Elements/nodalspringelement.h" #include "floatmatrix.h" #include "intarray.h" #include "floatarray.h" @@ -104,11 +104,9 @@ NodalSpringElement :: computeNumberOfGlobalDofs() } -IRResultType -NodalSpringElement :: initializeFrom(InputRecord *ir) +void +NodalSpringElement :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, dofMask, _IFT_NodalSpringElement_dofmask); IR_GIVE_FIELD(ir, springConstants, _IFT_NodalSpringElement_springConstants); @@ -129,8 +127,6 @@ NodalSpringElement :: initializeFrom(InputRecord *ir) activityTimeFunction = 0; IR_GIVE_OPTIONAL_FIELD(ir, activityTimeFunction, _IFT_Element_activityTimeFunction); IR_GIVE_FIELD(ir, dofManArray, _IFT_Element_nodes); - - return IRRT_OK; } void NodalSpringElement :: printOutputAt(FILE *File, TimeStep *tStep) diff --git a/src/sm/Elements/nodalspringelement.h b/src/sm/Elements/nodalspringelement.h index 6c24776a1..0f5ce685b 100644 --- a/src/sm/Elements/nodalspringelement.h +++ b/src/sm/Elements/nodalspringelement.h @@ -35,7 +35,7 @@ #ifndef nodalspringelement_h #define nodalspringelement_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" ///@name Input fields for spring element //@{ @@ -72,24 +72,24 @@ class NodalSpringElement : public StructuralElement NodalSpringElement(int n, Domain * d); virtual ~NodalSpringElement() { } - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override { answer.clear(); } - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; - virtual int computeNumberOfDofs() { return dofMask.giveSize(); } - virtual int computeNumberOfGlobalDofs(); + int computeNumberOfDofs() override { return dofMask.giveSize(); } + int computeNumberOfGlobalDofs() override; - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual void updateInternalState(TimeStep *tStep) { } - virtual void updateYourself(TimeStep *tStep) { } - virtual int checkConsistency() { return 1; } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void updateInternalState(TimeStep *tStep) override { } + void updateYourself(TimeStep *tStep) override { } + int checkConsistency() override { return 1; } + void printOutputAt(FILE *file, TimeStep *tStep) override; #ifdef __OOFEG //void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); @@ -98,23 +98,23 @@ class NodalSpringElement : public StructuralElement #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_NodalSpringElement_Name; } - virtual const char *giveClassName() const { return "NodalSpringElement"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Element_Geometry_Type giveGeometryType() const { return EGT_point; } - virtual bool isCast(TimeStep *tStep) {return true;} - + const char *giveInputRecordName() const override { return _IFT_NodalSpringElement_Name; } + const char *giveClassName() const override { return "NodalSpringElement"; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_point; } + bool isCast(TimeStep *tStep) override { return true; } + protected: - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override { answer.clear(); } - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override { answer.clear(); } - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, - int lowerIndx = 1, int upperIndx = ALL_STRAINS) + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, + int lowerIndx = 1, int upperIndx = ALL_STRAINS) override { answer.clear(); } - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) { answer.clear(); } - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override { answer.clear(); } + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; }; } // end namespace oofem #endif // nodalspringelement_h diff --git a/src/sm/Elements/phasefieldelement.C b/src/sm/Elements/phasefieldelement.C index cbb385045..0d815f445 100644 --- a/src/sm/Elements/phasefieldelement.C +++ b/src/sm/Elements/phasefieldelement.C @@ -33,9 +33,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/phasefieldelement.h" -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/phasefieldelement.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralms.h" #include "node.h" #include "material.h" #include "gausspoint.h" @@ -383,13 +383,10 @@ PhaseFieldElement :: computeStiffnessMatrix_dd(FloatMatrix &answer, MatResponseM } -IRResultType -PhaseFieldElement :: initializeFrom(InputRecord *ir) +void +PhaseFieldElement :: initializeFrom(InputRecord &ir) { - //IRResultType result; // Required by IR_GIVE_FIELD macro //nlGeo = 0; - - return IRRT_OK; } diff --git a/src/sm/Elements/phasefieldelement.h b/src/sm/Elements/phasefieldelement.h index 6af76da6f..6c0ddc4f9 100644 --- a/src/sm/Elements/phasefieldelement.h +++ b/src/sm/Elements/phasefieldelement.h @@ -36,7 +36,7 @@ #ifndef phasefieldelement_h #define phasefieldelement_h -#include "../sm/Elements/PlaneStress/qplanstrss.h" +#include "sm/Elements/PlaneStress/qplanstrss.h" namespace oofem { /** @@ -53,11 +53,11 @@ class PhaseFieldElement virtual NLStructuralElement *giveElement( ) = 0; - virtual IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); virtual void giveDofManDofIDMask_u(IntArray &answer) = 0; virtual void giveDofManDofIDMask_d(IntArray &answer) = 0; - virtual const char *giveClassName() const { return "PhaseFieldElement"; } + const char *giveClassName() const { return "PhaseFieldElement"; } void computeLocationArrayOfDofIDs(const IntArray &dofIdArray, IntArray &answer); @@ -80,7 +80,7 @@ class PhaseFieldElement void computeStiffnessMatrix_dd(FloatMatrix &, MatResponseMode, TimeStep *); void computeStiffnessMatrix_du(FloatMatrix &, MatResponseMode, TimeStep *); - + double computeG(GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); double computeGPrim(GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); double computeDamageAt(GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); @@ -93,12 +93,11 @@ class PhaseFieldElement void computeDisplacementUnknowns(FloatArray &answer, ValueModeType valueMode, TimeStep *stepN); void computeDamageUnknowns(FloatArray &answer, ValueModeType valueMode, TimeStep *stepN); - + //Interpolation matrices virtual void computeBd_matrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS); virtual void computeNd_matrixAt(const FloatArray &lCoords, FloatMatrix &N); - }; } // end namespace oofem -#endif \ No newline at end of file +#endif diff --git a/src/sm/Elements/quad1platesubsoil.C b/src/sm/Elements/quad1platesubsoil.C index a3c161137..5d597fd08 100644 --- a/src/sm/Elements/quad1platesubsoil.C +++ b/src/sm/Elements/quad1platesubsoil.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/quad1platesubsoil.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/quad1platesubsoil.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei2dquadlin.h" #include "node.h" #include "material.h" @@ -79,7 +79,7 @@ Quad1PlateSubSoil :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 5) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 5); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } @@ -88,7 +88,7 @@ Quad1PlateSubSoil :: computeGaussPoints() void Quad1PlateSubSoil :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, TimeStep *tStep, ValueModeType mode) { - OOFEM_ERROR("Body load not supported, use surface load instead"); + OOFEM_ERROR("Body load not supported, use surface load instead"); } @@ -118,22 +118,22 @@ Quad1PlateSubSoil :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int l void Quad1PlateSubSoil :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_PlateSubSoil(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_PlateSubSoil(strain, gp, tStep); } void Quad1PlateSubSoil :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give2dPlateSubSoilStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give2dPlateSubSoilStiffMtrx(rMode, gp, tStep); } -IRResultType -Quad1PlateSubSoil :: initializeFrom(InputRecord *ir) +void +Quad1PlateSubSoil :: initializeFrom(InputRecord &ir) { this->numberOfGaussPoints = 4; - return StructuralElement :: initializeFrom(ir); + StructuralElement :: initializeFrom(ir); } @@ -148,8 +148,8 @@ void Quad1PlateSubSoil :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) { FloatArray u, v; - u.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - v.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); + u.beDifferenceOf( this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); + v.beDifferenceOf( this->giveNode(3)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); answer.beVectorProductOf(u, v); answer.normalize(); @@ -170,10 +170,8 @@ Quad1PlateSubSoil :: giveCharacteristicLength(const FloatArray &normalToCrackPla double Quad1PlateSubSoil :: computeVolumeAround(GaussPoint *gp) { - double detJ, weight; - - weight = gp->giveWeight(); - detJ = fabs( this->interp_lin.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double weight = gp->giveWeight(); + double detJ = fabs( this->interp_lin.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); return detJ * weight; } @@ -182,7 +180,7 @@ void Quad1PlateSubSoil :: computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) // Returns the lumped mass matrix of the receiver. { - OOFEM_ERROR("Mass matrix not provided"); + OOFEM_ERROR("Mass matrix not provided"); } @@ -244,48 +242,55 @@ Quad1PlateSubSoil :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &a } } - void -Quad1PlateSubSoil :: computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) +Quad1PlateSubSoil ::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +// Returns the [1x4] displacement interpolation matrix {N} { - this->computeNmatrixAt(sgp->giveNaturalCoordinates(), answer); + FloatArray N(4); + giveInterpolation()->evalN(N, iLocCoord, FEIElementGeometryWrapper(this) ); + answer.beNMatrixOf(N, 1); } + void -Quad1PlateSubSoil :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +Quad1PlateSubSoil ::computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) { - answer.resize(4); - answer.zero(); - if ( iSurf == 1 ) { - for (int i = 1; i<=4; i++) { - answer.at(i) = i; - } + if (boundaryID == 1) { + this->computeNmatrixAt(lcoords, answer); } else { - OOFEM_ERROR("wrong surface number"); + OOFEM_ERROR("computeSurfaceNMatrix: Only one surface is supported with id=1"); } } -IntegrationRule * -Quad1PlateSubSoil :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Square, approxOrder); - iRule->SetUpPointsOnSquare(npoints, _Unknown); - return iRule; -} -double -Quad1PlateSubSoil :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) -{ - return this->computeVolumeAround(gp); -} +// void +// Quad1PlateSubSoil :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +// { +// answer.resize(4); +// answer.zero(); +// if ( iSurf == 1 ) { +// for (int i = 1; i <= 4; i++) { +// answer.at(i) = i; +// } +// } else { +// OOFEM_ERROR("wrong surface number"); +// } +// } -int -Quad1PlateSubSoil :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) -{ - return 0; -} + +// double +// Quad1PlateSubSoil :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) +// { +// return this->computeVolumeAround(gp); +// } + + +// int +// Quad1PlateSubSoil :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) +// { +// return 0; +// } } // end namespace oofem diff --git a/src/sm/Elements/quad1platesubsoil.h b/src/sm/Elements/quad1platesubsoil.h index c5ca2f046..833d6045f 100644 --- a/src/sm/Elements/quad1platesubsoil.h +++ b/src/sm/Elements/quad1platesubsoil.h @@ -35,7 +35,7 @@ #ifndef quad1platesubsoil_H #define quad1platesubsoil_H -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -65,53 +65,55 @@ public SPRNodalRecoveryModelInterface Quad1PlateSubSoil(int n, Domain * d); virtual ~Quad1PlateSubSoil() { } - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; - virtual MaterialMode giveMaterialMode() { return _2dPlateSubSoil; } - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } + MaterialMode giveMaterialMode() override { return _2dPlateSubSoil; } + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Quad1PlateSubSoil_Name; } - virtual const char *giveClassName() const { return "Quad1PlateSubSoil"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_Quad1PlateSubSoil_Name; } + const char *giveClassName() const override { return "Quad1PlateSubSoil"; } + void initializeFrom(InputRecord &ir) override; - virtual int computeNumberOfDofs() { return 4; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 4; } + void giveDofManDofIDMask(int inode, IntArray &) const override; - virtual void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp); + void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) override; - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane); - virtual double computeVolumeAround(GaussPoint *gp); + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override; + double computeVolumeAround(GaussPoint *gp) override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual Interface *giveInterface(InterfaceType it); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + Interface *giveInterface(InterfaceType it) override; protected: - virtual void computeGaussPoints(); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); + void computeGaussPoints() override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP() { return this->numberOfGaussPoints; } - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType() { return SPRPatchType_2dxy; } + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override { return this->numberOfGaussPoints; } + SPRPatchType SPRNodalRecoveryMI_givePatchType() override { return SPRPatchType_2dxy; } /** * @name Surface load support */ + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) override; + //@{ - virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); - virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const; - virtual IntegrationRule *GetSurfaceIntegrationRule(int iSurf); - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf); - virtual int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp); + //void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); + //void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override; + //double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) override; + //int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp) override; //@} }; } // end namespace oofem diff --git a/src/sm/Elements/quad2platesubsoil.C b/src/sm/Elements/quad2platesubsoil.C index d99d4a3d2..3c144052d 100644 --- a/src/sm/Elements/quad2platesubsoil.C +++ b/src/sm/Elements/quad2platesubsoil.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/quad2platesubsoil.h" +#include "sm/Elements/quad2platesubsoil.h" #include "fei2dquadquad.h" #include "crosssection.h" #include "gausspoint.h" @@ -69,7 +69,7 @@ Quad2PlateSubSoil :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 5) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 5); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } @@ -99,11 +99,11 @@ Quad2PlateSubSoil :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int l } -IRResultType -Quad2PlateSubSoil :: initializeFrom(InputRecord *ir) +void +Quad2PlateSubSoil :: initializeFrom(InputRecord &ir) { this->numberOfGaussPoints = 4; - return StructuralElement :: initializeFrom(ir); + StructuralElement :: initializeFrom(ir); } @@ -135,5 +135,25 @@ Quad2PlateSubSoil :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &a } } +void +Quad2PlateSubSoil ::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +// Returns the [1x8] displacement interpolation matrix {N} +{ + FloatArray N(8); + giveInterpolation()->evalN(N, iLocCoord, FEIElementGeometryWrapper(this) ); + answer.beNMatrixOf(N, 1); +} + +void +Quad2PlateSubSoil :: computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) +{ + if (boundaryID == 1) { + this->computeNmatrixAt(lcoords, answer); + } else { + OOFEM_ERROR("computeSurfaceNMatrix: Only one surface is supported with id=1"); + } +} + + } // end namespace oofem diff --git a/src/sm/Elements/quad2platesubsoil.h b/src/sm/Elements/quad2platesubsoil.h index 95d59e993..067aaa605 100644 --- a/src/sm/Elements/quad2platesubsoil.h +++ b/src/sm/Elements/quad2platesubsoil.h @@ -35,8 +35,8 @@ #ifndef quad2platesubsoil_H #define quad2platesubsoil_H -#include "../sm/Elements/structuralelement.h" -#include "../sm/Elements/quad1platesubsoil.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Elements/quad1platesubsoil.h" #define _IFT_Quad2PlateSubSoil_Name "quad2platesubsoil" @@ -62,22 +62,28 @@ class Quad2PlateSubSoil : public Quad1PlateSubSoil Quad2PlateSubSoil(int n, Domain * d); virtual ~Quad2PlateSubSoil() { } - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Quad2PlateSubSoil_Name; } - virtual const char *giveClassName() const { return "Quad2PlateSubSoil"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_Quad2PlateSubSoil_Name; } + const char *giveClassName() const override { return "Quad2PlateSubSoil"; } + void initializeFrom(InputRecord &ir) override; - virtual int computeNumberOfDofs() { return 8; } + int computeNumberOfDofs() override { return 8; } protected: - virtual void computeGaussPoints(); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); + void computeGaussPoints() override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + /** + * @name Surface load support + */ + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) override; + }; } // end namespace oofem #endif // quad2platesubsoil_H diff --git a/src/sm/Elements/springelement.C b/src/sm/Elements/springelement.C index a0116f83f..738b4870a 100644 --- a/src/sm/Elements/springelement.C +++ b/src/sm/Elements/springelement.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/springelement.h" +#include "sm/Elements/springelement.h" #include "floatmatrix.h" #include "intarray.h" #include "floatarray.h" @@ -154,10 +154,10 @@ SpringElement :: computeNumberOfGlobalDofs() } -IRResultType -SpringElement :: initializeFrom(InputRecord *ir) +void +SpringElement :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralElement :: initializeFrom(ir); int _mode; IR_GIVE_FIELD(ir, _mode, _IFT_SpringElement_mode); @@ -170,7 +170,6 @@ SpringElement :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, this->dir, _IFT_SpringElement_orientation); this->dir.normalize(); } - return StructuralElement :: initializeFrom(ir); } void SpringElement :: printOutputAt(FILE *File, TimeStep *tStep) diff --git a/src/sm/Elements/springelement.h b/src/sm/Elements/springelement.h index 4342cbc59..c33a39cbc 100644 --- a/src/sm/Elements/springelement.h +++ b/src/sm/Elements/springelement.h @@ -35,7 +35,7 @@ #ifndef springelement_h #define springelement_h -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" ///@name Input fields for spring element //@{ @@ -83,26 +83,26 @@ class SpringElement : public StructuralElement SpringElement(int n, Domain * d); virtual ~SpringElement() { } - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override { answer.clear(); } - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; - virtual int computeNumberOfDofs() { return 2; } - virtual int computeNumberOfGlobalDofs(); + int computeNumberOfDofs() override { return 2; } + int computeNumberOfGlobalDofs() override; - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + + void updateInternalState(TimeStep *tStep) override { } + void updateYourself(TimeStep *tStep) override { } + int checkConsistency() override { return 1; } + void printOutputAt(FILE *file, TimeStep *tStep) override; + bool isCast(TimeStep *tStep) override { return true; } - virtual void updateInternalState(TimeStep *tStep) { } - virtual void updateYourself(TimeStep *tStep) { } - virtual int checkConsistency() { return 1; } - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual bool isCast(TimeStep *tStep) {return true;} - #ifdef __OOFEG //void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType); @@ -110,22 +110,22 @@ class SpringElement : public StructuralElement #endif // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_SpringElement_Name; } - virtual const char *giveClassName() const { return "SpringElement"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Element_Geometry_Type giveGeometryType() const { return EGT_point; } + const char *giveInputRecordName() const override { return _IFT_SpringElement_Name; } + const char *giveClassName() const override { return "SpringElement"; } + void initializeFrom(InputRecord &ir) override; + Element_Geometry_Type giveGeometryType() const override { return EGT_point; } protected: - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override { answer.clear(); } - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override { answer.clear(); } - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, - int lowerIndx = 1, int upperIndx = ALL_STRAINS) + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, + int lowerIndx = 1, int upperIndx = ALL_STRAINS) override { answer.clear(); } - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) { answer.clear(); } - virtual bool computeGtoLRotationMatrix(FloatMatrix &answer); + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override { answer.clear(); } + bool computeGtoLRotationMatrix(FloatMatrix &answer) override; double computeSpringInternalForce(TimeStep *tStep); }; } // end namespace oofem diff --git a/src/sm/Elements/structural2delement.C b/src/sm/Elements/structural2delement.C index 8c237c9fe..e1a085052 100644 --- a/src/sm/Elements/structural2delement.C +++ b/src/sm/Elements/structural2delement.C @@ -32,22 +32,22 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/structural2delement.h" +#include "sm/Elements/structural2delement.h" #include "feinterpol2d.h" #include "gausspoint.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "gaussintegrationrule.h" #include "mathfem.h" namespace oofem { -Structural2DElement :: Structural2DElement(int n, Domain *aDomain) : +Structural2DElement::Structural2DElement(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), matRotation(false) { cellGeometryWrapper = NULL; } -Structural2DElement :: ~Structural2DElement() +Structural2DElement::~Structural2DElement() { if ( cellGeometryWrapper ) { delete cellGeometryWrapper; @@ -55,37 +55,32 @@ Structural2DElement :: ~Structural2DElement() } -IRResultType -Structural2DElement :: initializeFrom(InputRecord *ir) +void +Structural2DElement::initializeFrom(InputRecord &ir) { - IRResultType result = NLStructuralElement :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - matRotation = ir->hasField(_IFT_Structural2DElement_materialCoordinateSystem); //|| this->elemLocalCS.isNotEmpty(); - return IRRT_OK; + NLStructuralElement::initializeFrom(ir); + matRotation = ir.hasField(_IFT_Structural2DElement_materialCoordinateSystem); //|| this->elemLocalCS.isNotEmpty(); } void -Structural2DElement :: postInitialize() +Structural2DElement::postInitialize() { // Element must be created before giveNumberOfNodes can be called - StructuralElement :: postInitialize(); + StructuralElement::postInitialize(); this->numberOfDofMans = this->giveNumberOfNodes(); } int -Structural2DElement :: giveNumberOfNodes() const +Structural2DElement::giveNumberOfNodes() const { return this->giveInterpolation()->giveNumberOfNodes(); } FEICellGeometry * -Structural2DElement :: giveCellGeometryWrapper() +Structural2DElement::giveCellGeometryWrapper() { if ( !cellGeometryWrapper ) { cellGeometryWrapper = new FEIElementGeometryWrapper(this); @@ -96,7 +91,7 @@ Structural2DElement :: giveCellGeometryWrapper() int -Structural2DElement :: computeNumberOfDofs() +Structural2DElement::computeNumberOfDofs() { ///@todo move one hiearchy up and generalize IntArray dofIdMask; @@ -106,7 +101,7 @@ Structural2DElement :: computeNumberOfDofs() void -Structural2DElement :: giveDofManDofIDMask(int inode, IntArray &answer) const +Structural2DElement::giveDofManDofIDMask(int inode, IntArray &answer) const { answer = { D_u, D_v @@ -115,13 +110,13 @@ Structural2DElement :: giveDofManDofIDMask(int inode, IntArray &answer) const double -Structural2DElement :: computeVolumeAround(GaussPoint *gp) +Structural2DElement::computeVolumeAround(GaussPoint *gp) { // Computes the volume element dV associated with the given gp. double weight = gp->giveWeight(); const FloatArray &lCoords = gp->giveNaturalCoordinates(); // local/natural coords of the gp (parent domain) - double detJ = fabs( this->giveInterpolation()->giveTransformationJacobian( lCoords, * this->giveCellGeometryWrapper() ) ); + double detJ = fabs(this->giveInterpolation()->giveTransformationJacobian(lCoords, * this->giveCellGeometryWrapper() ) ); double thickness = this->giveCrossSection()->give(CS_Thickness, gp); // the cross section keeps track of the thickness return detJ * thickness * weight; // dV @@ -129,20 +124,20 @@ Structural2DElement :: computeVolumeAround(GaussPoint *gp) void -Structural2DElement :: computeGaussPoints() +Structural2DElement::computeGaussPoints() { // Sets up the integration rule array which contains all the Gauss points // Default: create one integration rule if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], this->numberOfGaussPoints, this); } } void -Structural2DElement :: giveMaterialOrientationAt(FloatArray &x, FloatArray &y, const FloatArray &lcoords) +Structural2DElement::giveMaterialOrientationAt(FloatArray &x, FloatArray &y, const FloatArray &lcoords) { if ( this->elemLocalCS.isNotEmpty() ) { // User specified orientation x = { @@ -153,7 +148,7 @@ Structural2DElement :: giveMaterialOrientationAt(FloatArray &x, FloatArray &y, c }; } else { FloatMatrix jac; - this->giveInterpolation()->giveJacobianMatrixAt( jac, lcoords, * this->giveCellGeometryWrapper() ); + this->giveInterpolation()->giveJacobianMatrixAt(jac, lcoords, * this->giveCellGeometryWrapper() ); x.beColumnOf(jac, 1); // This is {dx/dxi, dy/dxi, dz/dxi} x.normalize(); y = { @@ -164,7 +159,7 @@ Structural2DElement :: giveMaterialOrientationAt(FloatArray &x, FloatArray &y, c double -Structural2DElement :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) +Structural2DElement::giveCharacteristicLength(const FloatArray &normalToCrackPlane) { return this->giveCharacteristicLengthForPlaneElements(normalToCrackPlane); } @@ -175,14 +170,13 @@ Structural2DElement :: giveCharacteristicLength(const FloatArray &normalToCrackP // Edge support void -Structural2DElement :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +Structural2DElement::giveEdgeDofMapping(IntArray &answer, int iEdge) const { /* * provides dof mapping of local edge dofs (only nonzero are taken into account) * to global element dofs */ - IntArray eNodes; - static_cast< FEInterpolation2d * >( this->giveInterpolation() )->computeLocalEdgeMapping(eNodes, iEdge); + const auto &eNodes = static_cast< FEInterpolation2d * >( this->giveInterpolation() )->computeLocalEdgeMapping(iEdge); answer.resize(eNodes.giveSize() * 2); for ( int i = 1; i <= eNodes.giveSize(); i++ ) { @@ -193,20 +187,20 @@ Structural2DElement :: giveEdgeDofMapping(IntArray &answer, int iEdge) const double -Structural2DElement :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +Structural2DElement::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { /* Returns the line element ds associated with the given gp on the specific edge. * Note: The name is misleading since there is no volume to speak of in this case. * The returned value is used for integration of a line integral (external forces). */ double detJ = static_cast< FEInterpolation2d * >( this->giveInterpolation() )-> - edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); + edgeGiveTransformationJacobian(iEdge, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); return detJ * gp->giveWeight(); } int -Structural2DElement :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +Structural2DElement::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -218,7 +212,7 @@ Structural2DElement :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int i FloatArray normal(2); static_cast< FEInterpolation2d * >( this->giveInterpolation() )-> - edgeEvalNormal( normal, iEdge, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); + edgeEvalNormal(normal, iEdge, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); answer.resize(2, 2); answer.zero(); @@ -236,18 +230,18 @@ Structural2DElement :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int i // Plane stress -PlaneStressElement :: PlaneStressElement(int n, Domain *aDomain) : +PlaneStressElement::PlaneStressElement(int n, Domain *aDomain) : Structural2DElement(n, aDomain) // Constructor. Creates an element with number n, belonging to aDomain. {} void -PlaneStressElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx, int upperIndx) +PlaneStressElement::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx, int upperIndx) { FEInterpolation *interp = this->giveInterpolation(); FloatMatrix dNdx; - interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); + interp->evaldNdx(dNdx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); answer.resize(3, dNdx.giveNumberOfRows() * 2); answer.zero(); @@ -263,14 +257,14 @@ PlaneStressElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int void -PlaneStressElement :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) +PlaneStressElement::computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) { // Returns the [ 4 x (nno*2) ] displacement gradient matrix {BH} of the receiver, // evaluated at gp. /// @todo not checked if correct FloatMatrix dNdx; - this->giveInterpolation()->evaldNdx( dNdx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); + this->giveInterpolation()->evaldNdx(dNdx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); answer.resize(4, dNdx.giveNumberOfRows() * 2); answer.zero(); @@ -285,43 +279,41 @@ PlaneStressElement :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) void -PlaneStressElement :: computeStressVector(FloatArray &answer, const FloatArray &e, GaussPoint *gp, TimeStep *tStep) +PlaneStressElement::computeStressVector(FloatArray &answer, const FloatArray &e, GaussPoint *gp, TimeStep *tStep) { if ( this->matRotation ) { ///@todo This won't work properly with "useUpdatedGpRecord" (!) FloatArray x, y; - FloatArray rotStrain, s; - - this->giveMaterialOrientationAt( x, y, gp->giveNaturalCoordinates() ); + this->giveMaterialOrientationAt(x, y, gp->giveNaturalCoordinates() ); // Transform to material c.s. - rotStrain = { - e(0) * x(0) * x(0) + e(2) * x(0) * x(1) + e(1) * x(1) * x(1), - e(0) * y(0) * y(0) + e(2) * y(0) * y(1) + e(1) * y(1) * y(1), - 2 * e(0) * x(0) * y(0) + 2 * e(1) * x(1) * y(1) + e(2) * ( x(1) * y(0) + x(0) * y(1) ) + FloatArrayF< 3 >rotStrain = { + e [ 0 ] * x [ 0 ] * x [ 0 ] + e [ 2 ] * x [ 0 ] * x [ 1 ] + e [ 1 ] * x [ 1 ] * x [ 1 ], + e [ 0 ] * y [ 0 ] * y [ 0 ] + e [ 2 ] * y [ 0 ] * y [ 1 ] + e [ 1 ] * y [ 1 ] * y [ 1 ], + 2 * e [ 0 ] * x [ 0 ] * y [ 0 ] + 2 * e [ 1 ] * x [ 1 ] * y [ 1 ] + e [ 2 ] * ( x [ 1 ] * y [ 0 ] + x [ 0 ] * y [ 1 ] ) }; - this->giveStructuralCrossSection()->giveRealStress_PlaneStress(s, gp, rotStrain, tStep); + auto s = this->giveStructuralCrossSection()->giveRealStress_PlaneStress(rotStrain, gp, tStep); answer = { - s(0) * x(0) * x(0) + 2 * s(2) * x(0) * y(0) + s(1) * y(0) * y(0), - s(0) * x(1) * x(1) + 2 * s(2) * x(1) * y(1) + s(1) * y(1) * y(1), - s(1) * y(0) * y(1) + s(0) * x(0) * x(1) + s(2) * ( x(1) * y(0) + x(0) * y(1) ) + s [ 0 ] * x [ 0 ] * x [ 0 ] + 2 * s [ 2 ] * x [ 0 ] * y [ 0 ] + s [ 1 ] * y [ 0 ] * y [ 0 ], + s [ 0 ] * x [ 1 ] * x [ 1 ] + 2 * s [ 2 ] * x [ 1 ] * y [ 1 ] + s [ 1 ] * y [ 1 ] * y [ 1 ], + s [ 1 ] * y [ 0 ] * y [ 1 ] + s [ 0 ] * x [ 0 ] * x [ 1 ] + s [ 2 ] * ( x [ 1 ] * y [ 0 ] + x [ 0 ] * y [ 1 ] ) }; } else { - this->giveStructuralCrossSection()->giveRealStress_PlaneStress(answer, gp, e, tStep); + answer = this->giveStructuralCrossSection()->giveRealStress_PlaneStress(e, gp, tStep); } } void -PlaneStressElement :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +PlaneStressElement::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveStiffnessMatrix_PlaneStress(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_PlaneStress(rMode, gp, tStep); if ( this->matRotation ) { FloatArray x, y; FloatMatrix Q; - this->giveMaterialOrientationAt( x, y, gp->giveNaturalCoordinates() ); + this->giveMaterialOrientationAt(x, y, gp->giveNaturalCoordinates() ); Q = { { x(0) * x(0), x(1) * x(1), x(0) * x(1) }, @@ -332,6 +324,26 @@ PlaneStressElement :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatRespon } } +void +PlaneStressElement::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_dPdF_PlaneStress(rMode, gp, tStep); + if ( this->matRotation ) { + FloatArray x, y; + FloatMatrix Q; + + this->giveMaterialOrientationAt(x, y, gp->giveNaturalCoordinates() ); + + Q = { + { x(0) * x(0), x(1) * x(1), x(0) * x(1), x(1) * x(0) }, + { y(0) * y(0), y(1) * y(1), y(0) * y(1), y(1) * y(0) }, + { x(0) * y(0), x(1) * y(1), x(0) * y(1), x(1) * y(0) }, + { y(0) * x(0), y(1) * x(1), y(0) * x(1), y(1) * x(0) } + }; + answer.rotatedWith(Q, 't'); + } +} + @@ -339,20 +351,20 @@ PlaneStressElement :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatRespon // Plane strain -PlaneStrainElement :: PlaneStrainElement(int n, Domain *aDomain) : +PlaneStrainElement::PlaneStrainElement(int n, Domain *aDomain) : Structural2DElement(n, aDomain) // Constructor. Creates an element with number n, belonging to aDomain. {} void -PlaneStrainElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx, int upperIndx) +PlaneStrainElement::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx, int upperIndx) // Returns the [ 4 x (nno*2) ] strain-displacement matrix {B} of the receiver, // evaluated at gp. { FEInterpolation *interp = this->giveInterpolation(); FloatMatrix dNdx; - interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); + interp->evaldNdx(dNdx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); answer.resize(4, dNdx.giveNumberOfRows() * 2); @@ -369,14 +381,14 @@ PlaneStrainElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int void -PlaneStrainElement :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) +PlaneStrainElement::computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) { // Returns the [ 5 x (nno*2) ] displacement gradient matrix {BH} of the receiver, // evaluated at gp. /// @todo not checked if correct FloatMatrix dNdx; - this->giveInterpolation()->evaldNdx( dNdx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); + this->giveInterpolation()->evaldNdx(dNdx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); answer.resize(4, dNdx.giveNumberOfRows() * 2); answer.zero(); @@ -391,43 +403,42 @@ PlaneStrainElement :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) void -PlaneStrainElement :: computeStressVector(FloatArray &answer, const FloatArray &e, GaussPoint *gp, TimeStep *tStep) +PlaneStrainElement::computeStressVector(FloatArray &answer, const FloatArray &e, GaussPoint *gp, TimeStep *tStep) { if ( this->matRotation ) { ///@todo This won't work properly with "useUpdatedGpRecord" (!) FloatArray x, y; - FloatArray rotStrain, s; - this->giveMaterialOrientationAt( x, y, gp->giveNaturalCoordinates() ); + this->giveMaterialOrientationAt(x, y, gp->giveNaturalCoordinates() ); // Transform to material c.s. - rotStrain = { - e(0) * x(0) * x(0) + e(3) * x(0) * x(1) + e(1) * x(1) * x(1), - e(0) * y(0) * y(0) + e(3) * y(0) * y(1) + e(1) * y(1) * y(1), - e(2), - 2 * e(0) * x(0) * y(0) + 2 * e(1) * x(1) * y(1) + e(3) * ( x(1) * y(0) + x(0) * y(1) ) + FloatArrayF< 4 >rotStrain = { + e [ 0 ] * x [ 0 ] * x [ 0 ] + e [ 3 ] * x [ 0 ] * x [ 1 ] + e [ 1 ] * x [ 1 ] * x [ 1 ], + e [ 0 ] * y [ 0 ] * y [ 0 ] + e [ 3 ] * y [ 0 ] * y [ 1 ] + e [ 1 ] * y [ 1 ] * y [ 1 ], + e [ 2 ], + 2 * e [ 0 ] * x [ 0 ] * y [ 0 ] + 2 * e [ 1 ] * x [ 1 ] * y [ 1 ] + e [ 3 ] * ( x [ 1 ] * y [ 0 ] + x [ 0 ] * y [ 1 ] ) }; - this->giveStructuralCrossSection()->giveRealStress_PlaneStrain(s, gp, rotStrain, tStep); + auto s = this->giveStructuralCrossSection()->giveRealStress_PlaneStrain(rotStrain, gp, tStep); answer = { - s(0) * x(0) * x(0) + 2 * s(3) * x(0) * y(0) + s(1) * y(0) * y(0), - s(0) * x(1) * x(1) + 2 * s(3) * x(1) * y(1) + s(1) * y(1) * y(1), - s(2), - y(1) * ( s(3) * x(0) + s(1) * y(0) ) + x(1) * ( s(0) * x(0) + s(3) * y(0) ) + s [ 0 ] * x [ 0 ] * x [ 0 ] + 2 * s [ 3 ] * x [ 0 ] * y [ 0 ] + s [ 1 ] * y [ 0 ] * y [ 0 ], + s [ 0 ] * x [ 1 ] * x [ 1 ] + 2 * s [ 3 ] * x [ 1 ] * y [ 1 ] + s [ 1 ] * y [ 1 ] * y [ 1 ], + s [ 2 ], + y [ 1 ] * ( s [ 3 ] * x [ 0 ] + s [ 1 ] * y [ 0 ] ) + x [ 1 ] * ( s [ 0 ] * x [ 0 ] + s [ 3 ] * y [ 0 ] ) }; } else { - this->giveStructuralCrossSection()->giveRealStress_PlaneStrain(answer, gp, e, tStep); + answer = this->giveStructuralCrossSection()->giveRealStress_PlaneStrain(e, gp, tStep); } } void -PlaneStrainElement :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +PlaneStrainElement::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveStiffnessMatrix_PlaneStrain(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_PlaneStrain(rMode, gp, tStep); if ( this->matRotation ) { FloatArray x, y; FloatMatrix Q; - this->giveMaterialOrientationAt( x, y, gp->giveNaturalCoordinates() ); + this->giveMaterialOrientationAt(x, y, gp->giveNaturalCoordinates() ); Q = { { x(0) * x(0), x(1) * x(1), 0, x(0) * x(1) }, { y(0) * y(0), y(1) * y(1), 0, y(0) * y(1) }, @@ -440,10 +451,33 @@ PlaneStrainElement :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatRespon } +void +PlaneStrainElement::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_dPdF_PlaneStrain(rMode, gp, tStep); + if ( this->matRotation ) { + FloatArray x, y; + FloatMatrix Q; + + this->giveMaterialOrientationAt(x, y, gp->giveNaturalCoordinates() ); + + Q = { + { x(0) * x(0), x(1) * x(1), 0, x(0) * x(1), x(1) * x(0) }, + { y(0) * y(0), y(1) * y(1), 0, y(0) * y(1), y(1) * y(0) }, + { 0, 0, 1, 0, 0 }, + { x(0) * y(0), x(1) * y(1), 0, x(0) * y(1), x(1) * y(0) }, + { y(0) * x(0), y(1) * x(1), 0, y(0) * x(1), y(1) * x(0) } + }; + answer.rotatedWith(Q, 't'); + } +} + + + // Axisymmetry -AxisymElement :: AxisymElement(int n, Domain *aDomain) : +AxisymElement::AxisymElement(int n, Domain *aDomain) : Structural2DElement(n, aDomain) // Constructor. Creates an element with number n, belonging to aDomain. { @@ -452,7 +486,7 @@ AxisymElement :: AxisymElement(int n, Domain *aDomain) : double -AxisymElement :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) +AxisymElement::giveCharacteristicLength(const FloatArray &normalToCrackPlane) // // returns receiver's characteristic length for crack band models // for a crack formed in the plane with normal normalToCrackPlane. @@ -463,21 +497,20 @@ AxisymElement :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) double -AxisymElement :: computeVolumeAround(GaussPoint *gp) +AxisymElement::computeVolumeAround(GaussPoint *gp) // Returns the portion of the receiver which is attached to gp. { - // note: radius is accounted by interpolation (of Fei2d*Axi type) - double determinant = fabs( static_cast< FEInterpolation2d * >( this->giveInterpolation() )-> - giveTransformationJacobian( gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ) ); + // note: radius is accounted by interpolation (of Fei2d*Axi type) + double determinant = fabs(static_cast< FEInterpolation2d * >( this->giveInterpolation() )-> + giveTransformationJacobian(gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ) ); - double weight = gp->giveWeight(); - return determinant * weight; - + double weight = gp->giveWeight(); + return determinant * weight; } void -AxisymElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +AxisymElement::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // // Returns the [ 6 x (nno*2) ] strain-displacement matrix {B} of the receiver, // evaluated at gp. @@ -487,7 +520,7 @@ AxisymElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, i FEInterpolation *interp = this->giveInterpolation(); FloatArray N; - interp->evalN( N, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); + interp->evalN(N, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); double r = 0.0; for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) { double x = this->giveNode(i)->giveCoordinate(1); @@ -495,7 +528,7 @@ AxisymElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, i } FloatMatrix dNdx; - interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); + interp->evaldNdx(dNdx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); answer.resize(6, dNdx.giveNumberOfRows() * 2); answer.zero(); @@ -510,7 +543,7 @@ AxisymElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, i void -AxisymElement :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) +AxisymElement::computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) // Returns the [ 9 x (nno*2) ] displacement gradient matrix {BH} of the receiver, // evaluated at gp. // BH matrix - 9 rows : du/dx, dv/dy, dw/dz = u/r, 0, 0, du/dy, 0, 0, dv/dx @@ -520,8 +553,8 @@ AxisymElement :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) FloatMatrix dnx; FEInterpolation2d *interp = static_cast< FEInterpolation2d * >( this->giveInterpolation() ); - interp->evalN( n, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); - interp->evaldNdx( dnx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); + interp->evalN(n, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); + interp->evaldNdx(dnx, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); int nRows = dnx.giveNumberOfRows(); @@ -550,11 +583,11 @@ AxisymElement :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) double -AxisymElement :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +AxisymElement::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { FloatArray c(2); double result = static_cast< FEInterpolation2d * >( this->giveInterpolation() )-> - edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); + edgeGiveTransformationJacobian(iEdge, gp->giveNaturalCoordinates(), * this->giveCellGeometryWrapper() ); return result * gp->giveWeight(); @@ -563,59 +596,58 @@ AxisymElement :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) void -AxisymElement :: computeGaussPoints() +AxisymElement::computeGaussPoints() { // Sets up the integration rule array which contains all the Gauss points if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 6) ); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 6); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], this->numberOfGaussPoints, this); } } void -AxisymElement :: computeStressVector(FloatArray &answer, const FloatArray &e, GaussPoint *gp, TimeStep *tStep) +AxisymElement::computeStressVector(FloatArray &answer, const FloatArray &e, GaussPoint *gp, TimeStep *tStep) { if ( this->matRotation ) { ///@todo This won't work properly with "useUpdatedGpRecord" (!) FloatArray x, y; - FloatArray rotStrain, s; - this->giveMaterialOrientationAt( x, y, gp->giveNaturalCoordinates() ); + this->giveMaterialOrientationAt(x, y, gp->giveNaturalCoordinates() ); // Transform to material c.s. - rotStrain = { - e(0) * x(0) * x(0) + e(5) * x(0) * x(1) + e(1) * x(1) * x(1), - e(0) * y(0) * y(0) + e(5) * y(0) * y(1) + e(1) * y(1) * y(1), - e(2), - e(4) * y(0) + e(3) * y(1), - e(4) * x(0) + e(3) * x(1), - 2 * e(0) * x(0) * y(0) + 2 * e(1) * x(1) * y(1) + e(5) * ( x(1) * y(0) + x(0) * y(1) ) + FloatArrayF< 6 >rotStrain = { + e [ 0 ] * x [ 0 ] * x [ 0 ] + e [ 5 ] * x [ 0 ] * x [ 1 ] + e [ 1 ] * x [ 1 ] * x [ 1 ], + e [ 0 ] * y [ 0 ] * y [ 0 ] + e [ 5 ] * y [ 0 ] * y [ 1 ] + e [ 1 ] * y [ 1 ] * y [ 1 ], + e [ 2 ], + e [ 4 ] * y [ 0 ] + e [ 3 ] * y [ 1 ], + e [ 4 ] * x [ 0 ] + e [ 3 ] * x [ 1 ], + 2 * e [ 0 ] * x [ 0 ] * y [ 0 ] + 2 * e [ 1 ] * x [ 1 ] * y [ 1 ] + e [ 5 ] * ( x [ 1 ] * y [ 0 ] + x [ 0 ] * y [ 1 ] ) }; - this->giveStructuralCrossSection()->giveRealStress_3d(s, gp, rotStrain, tStep); + auto s = this->giveStructuralCrossSection()->giveRealStress_3d(rotStrain, gp, tStep); answer = { - s(0) * x(0) * x(0) + 2 * s(5) * x(0) * y(0) + s(1) * y(0) * y(0), - s(0) * x(1) * x(1) + 2 * s(5) * x(1) * y(1) + s(1) * y(1) * y(1), - s(2), - s(4) * x(1) + s(3) * y(1), - s(4) * x(0) + s(3) * y(0), - y(1) * ( s(5) * x(0) + s(1) * y(0) ) + x(1) * ( s(0) * x(0) + s(5) * y(0) ) + s [ 0 ] * x [ 0 ] * x [ 0 ] + 2 * s [ 5 ] * x [ 0 ] * y [ 0 ] + s [ 1 ] * y [ 0 ] * y [ 0 ], + s [ 0 ] * x [ 1 ] * x [ 1 ] + 2 * s [ 5 ] * x [ 1 ] * y [ 1 ] + s [ 1 ] * y [ 1 ] * y [ 1 ], + s [ 2 ], + s [ 4 ] * x [ 1 ] + s [ 3 ] * y [ 1 ], + s [ 4 ] * x [ 0 ] + s [ 3 ] * y [ 0 ], + y [ 1 ] * ( s [ 5 ] * x [ 0 ] + s [ 1 ] * y [ 0 ] ) + x [ 1 ] * ( s [ 0 ] * x [ 0 ] + s [ 5 ] * y [ 0 ] ) }; } else { - this->giveStructuralCrossSection()->giveRealStress_3d(answer, gp, e, tStep); + answer = this->giveStructuralCrossSection()->giveRealStress_3d(e, gp, tStep); } } void -AxisymElement :: computeConstitutiveMatrixAt(FloatMatrix &answer, - MatResponseMode rMode, GaussPoint *gp, - TimeStep *tStep) +AxisymElement::computeConstitutiveMatrixAt(FloatMatrix &answer, + MatResponseMode rMode, GaussPoint *gp, + TimeStep *tStep) { - this->giveStructuralCrossSection()->giveStiffnessMatrix_3d(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_3d(rMode, gp, tStep); if ( this->matRotation ) { FloatArray x, y; FloatMatrix Q; - this->giveMaterialOrientationAt( x, y, gp->giveNaturalCoordinates() ); + this->giveMaterialOrientationAt(x, y, gp->giveNaturalCoordinates() ); Q = { { x(0) * x(0), x(1) * x(1), 0, 0, 0, x(0) * x(1) }, { y(0) * y(0), y(1) * y(1), 0, 0, 0, y(0) * y(1) }, @@ -628,4 +660,26 @@ AxisymElement :: computeConstitutiveMatrixAt(FloatMatrix &answer, answer.rotatedWith(Q, 't'); } } + +void +AxisymElement::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_dPdF_3d(rMode, gp, tStep); + if ( this->matRotation ) { + FloatArray x, y; + FloatMatrix Q; + + this->giveMaterialOrientationAt(x, y, gp->giveNaturalCoordinates() ); + Q = { + { x(0) * x(0), x(1) * x(1), 0, 0, 0, x(0) * x(1), 0, 0, x(1) * x(0) }, + { y(0) * y(0), y(1) * y(1), 0, 0, 0, y(0) * y(1), 0, 0, y(1) * y(0) }, + { 0, 0, 1, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, y(1), y(0), 0, 0, 0, 0 }, + { 0, 0, 0, x(1), x(0), 0 }, + { 2 * x(0) * y(0), 2 * x(1) * y(1), 0, 0, 0, x(1) * y(0) + x(0) * y(1) } + }; + + answer.rotatedWith(Q, 't'); + } +} } // end namespace oofem diff --git a/src/sm/Elements/structural2delement.h b/src/sm/Elements/structural2delement.h index 11f4e20d8..2d0f8efd8 100644 --- a/src/sm/Elements/structural2delement.h +++ b/src/sm/Elements/structural2delement.h @@ -35,13 +35,12 @@ #ifndef structural2delement_h #define structural2delement_h -#include "Elements/nlstructuralelement.h" +#include "sm/Elements/nlstructuralelement.h" #include "feinterpol2d.h" #define _IFT_Structural2DElement_materialCoordinateSystem "matcs" ///< [optional] Support for material directions based on element orientation. namespace oofem { - /** * Base class for planar 2D elements. * @@ -49,17 +48,16 @@ namespace oofem { */ class Structural2DElement : public NLStructuralElement { - protected: - /** + /** * To facilitate the transformation of 2d elements into 3d, the complexity of transformation from 3d to * local 2d system can be efficiently hidden in custom FEICellGeometry wrapper, that performs the transformation * into local system. This way, the existing 2d intrpolation classes can be used. - * The element maintain its FEICellGeometry, which is accesible through the giveCellGeometryWrapper. - * Generalization to 3d then would require only substitution of the geometry warpper and definition of + * The element maintain its FEICellGeometry, which is accesible through the giveCellGeometryWrapper. + * Generalization to 3d then would require only substitution of the geometry warpper and definition of * element transformation matrix. */ - FEICellGeometry* cellGeometryWrapper; + FEICellGeometry *cellGeometryWrapper; bool matRotation; @@ -69,89 +67,89 @@ class Structural2DElement : public NLStructuralElement * @param n Element number. * @param d Domain to which new material will belong. */ - Structural2DElement(int n, Domain * d); + Structural2DElement(int n, Domain *d); /// Destructor. virtual ~Structural2DElement(); - virtual void postInitialize(); - virtual int giveNumberOfNodes() const; + void postInitialize() override; + int giveNumberOfNodes() const override; /** * Returns the Cell Geometry Wrapper. Default inplementation creates FEIElementGeometryWrapper. */ - virtual FEICellGeometry* giveCellGeometryWrapper(); - - virtual int computeNumberOfDofs(); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual double computeVolumeAround(GaussPoint *gp); - - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane); - + virtual FEICellGeometry *giveCellGeometryWrapper(); + + int computeNumberOfDofs() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + double computeVolumeAround(GaussPoint *gp) override; + + void initializeFrom(InputRecord &ir) override; + + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override; + protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) = 0 ; - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) = 0; - virtual void computeGaussPoints(); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override = 0; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override = 0; + void computeGaussPoints() override; + + void giveMaterialOrientationAt(FloatArray &x, FloatArray &y, const FloatArray &lcoords); - void giveMaterialOrientationAt( FloatArray &x, FloatArray &y, const FloatArray &lcoords); - // Edge support - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_EdgeLoadSupport ) ? 1 : 0 ); } }; - class PlaneStressElement : public Structural2DElement { public: - PlaneStressElement(int n, Domain * d); + PlaneStressElement(int n, Domain *d); virtual ~PlaneStressElement() { } - virtual MaterialMode giveMaterialMode() { return _PlaneStress; } - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + MaterialMode giveMaterialMode() override { return _PlaneStress; } + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) ; - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; }; class PlaneStrainElement : public Structural2DElement { public: - PlaneStrainElement(int n, Domain * d); + PlaneStrainElement(int n, Domain *d); virtual ~PlaneStrainElement() { } - virtual MaterialMode giveMaterialMode() { return _PlaneStrain; } - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + MaterialMode giveMaterialMode() override { return _PlaneStrain; } + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) ; - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; }; class AxisymElement : public Structural2DElement { public: - AxisymElement(int n, Domain * d); + AxisymElement(int n, Domain *d); virtual ~AxisymElement() { } - virtual MaterialMode giveMaterialMode() { return _3dMat; } - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + MaterialMode giveMaterialMode() override { return _3dMat; } + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; - virtual double giveCharacteristicLength(const FloatArray &crackToNormalPlane); - virtual double computeVolumeAround(GaussPoint *gp); + double giveCharacteristicLength(const FloatArray &crackToNormalPlane) override; + double computeVolumeAround(GaussPoint *gp) override; protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) ; - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeGaussPoints(); - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeGaussPoints() override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; }; - - } // end namespace oofem #endif // structural2delement_h diff --git a/src/sm/Elements/structural3delement.C b/src/sm/Elements/structural3delement.C index e7cc1551c..f820d5d57 100644 --- a/src/sm/Elements/structural3delement.C +++ b/src/sm/Elements/structural3delement.C @@ -32,39 +32,38 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/structural3delement.h" +#include "sm/Elements/structural3delement.h" #include "feinterpol3d.h" #include "gausspoint.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "gaussintegrationrule.h" #include "mathfem.h" namespace oofem { -Structural3DElement :: Structural3DElement(int n, Domain *aDomain) : +Structural3DElement::Structural3DElement(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), matRotation(false) -{ -} +{} -IRResultType -Structural3DElement :: initializeFrom(InputRecord *ir) +void +Structural3DElement::initializeFrom(InputRecord &ir) { - this->matRotation = ir->hasField(_IFT_Structural3DElement_materialCoordinateSystem); - return NLStructuralElement :: initializeFrom(ir); + NLStructuralElement::initializeFrom(ir); + this->matRotation = ir.hasField(_IFT_Structural3DElement_materialCoordinateSystem); } void -Structural3DElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +Structural3DElement::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the [ 6 x (nno*3) ] strain-displacement matrix {B} of the receiver, eva- // luated at gp. // B matrix - 6 rows : epsilon-X, epsilon-Y, epsilon-Z, gamma-YZ, gamma-ZX, gamma-XY : { FEInterpolation *interp = this->giveInterpolation(); - FloatMatrix dNdx; - interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - + FloatMatrix dNdx; + interp->evaldNdx(dNdx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + answer.resize(6, dNdx.giveNumberOfRows() * 3); answer.zero(); @@ -82,15 +81,15 @@ Structural3DElement :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int void -Structural3DElement :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) +Structural3DElement::computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) // Returns the [ 9 x (nno * 3) ] displacement gradient matrix {BH} of the receiver, // evaluated at gp. // BH matrix - 9 rows : du/dx, dv/dy, dw/dz, dv/dz, du/dz, du/dy, dw/dy, dw/dx, dv/dx { FEInterpolation *interp = this->giveInterpolation(); - FloatMatrix dNdx; - interp->evaldNdx( dNdx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - + FloatMatrix dNdx; + interp->evaldNdx(dNdx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + answer.resize(9, dNdx.giveNumberOfRows() * 3); answer.zero(); @@ -105,19 +104,93 @@ Structural3DElement :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) answer.at(6, 3 * i - 2) = dNdx.at(i, 2); // du/dy answer.at(9, 3 * i - 1) = dNdx.at(i, 1); // dv/dx } +} + +void +Structural3DElement::computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + FloatArray stress; + FloatMatrix B, DB, stress_ident; + + answer.clear(); + stress_ident.resize(9, 9); + // assemble initial stress matrix + for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) { + // This function fetches the full form of the tensor + this->giveIPValue(stress, gp, IST_StressTensor, tStep); + stress_ident.zero(); + if ( stress.giveSize() ) { + // Construct the stress_ident matrix + // product answer_ijkl = delta_ik * sigma_jl + /*ij 11 22 33 23 13 12 32 31 21 + * kl + * 11 [ sig11, 0, 0, 0, sig13, sig12, 0, 0, 0] + * 22 [ 0, sig22, 0, sig23, 0, 0, 0, 0, sig12] + * 33 [ 0, 0, sig33, 0, 0, 0, sig23, sig13, 0] + * 23 [ 0, sig23, 0, sig33, 0, 0, 0, 0, sig13] + * 13 [ sig13, 0, 0, 0, sig33, sig23, 0, 0, 0] + * 12 [ sig12, 0, 0, 0, sig23, sig22, 0, 0, 0] + * 32 [ 0, 0, sig23, 0, 0, 0, sig22, sig12, 0] + * 31 [ 0, 0, sig13, 0, 0, 0, sig12, sig11, 0] + * 21 [ 0, sig12, 0, sig13, 0, 0, 0, 0, sig11] + */ + + stress_ident.at(1, 1) = stress.at(1); + stress_ident.at(1, 5) = stress.at(5); + stress_ident.at(1, 6) = stress.at(6); + + stress_ident.at(2, 2) = stress.at(2); + stress_ident.at(2, 4) = stress.at(4); + stress_ident.at(2, 9) = stress.at(6); + + stress_ident.at(3, 3) = stress.at(3); + stress_ident.at(3, 7) = stress.at(4); + stress_ident.at(3, 8) = stress.at(5); + + stress_ident.at(4, 2) = stress.at(4); + stress_ident.at(4, 4) = stress.at(3); + stress_ident.at(4, 9) = stress.at(5); + + stress_ident.at(5, 1) = stress.at(5); + stress_ident.at(5, 5) = stress.at(3); + stress_ident.at(5, 6) = stress.at(4); + + stress_ident.at(6, 1) = stress.at(6); + stress_ident.at(6, 5) = stress.at(4); + stress_ident.at(6, 6) = stress.at(2); + + stress_ident.at(7, 3) = stress.at(4); + stress_ident.at(7, 7) = stress.at(2); + stress_ident.at(7, 8) = stress.at(6); + + stress_ident.at(8, 3) = stress.at(5); + stress_ident.at(8, 7) = stress.at(6); + stress_ident.at(8, 8) = stress.at(1); + + stress_ident.at(9, 2) = stress.at(6); + stress_ident.at(9, 4) = stress.at(5); + stress_ident.at(9, 9) = stress.at(1); + } + + OOFEM_WARNING("Implementation not tested yet!"); + this->computeBHmatrixAt(gp, B); + DB.beProductOf(stress_ident, B); + answer.plusProductUnsym(B, DB, this->computeVolumeAround(gp) ); + } } + MaterialMode -Structural3DElement :: giveMaterialMode() +Structural3DElement::giveMaterialMode() { return _3dMat; } void -Structural3DElement :: giveMaterialOrientationAt(FloatArray &x, FloatArray &y, FloatArray &z, const FloatArray &lcoords) +Structural3DElement::giveMaterialOrientationAt(FloatArray &x, FloatArray &y, FloatArray &z, const FloatArray &lcoords) { if ( this->elemLocalCS.isNotEmpty() ) { // User specified orientation x.beColumnOf(this->elemLocalCS, 1); @@ -127,7 +200,7 @@ Structural3DElement :: giveMaterialOrientationAt(FloatArray &x, FloatArray &y, F ///@todo This is subject to change. I'm not sure which is the best way to define a local c.s. FloatMatrix jac; FloatArray help; - this->giveInterpolation()->giveJacobianMatrixAt( jac, lcoords, FEIElementGeometryWrapper(this) ); + this->giveInterpolation()->giveJacobianMatrixAt(jac, lcoords, FEIElementGeometryWrapper(this) ); x.beColumnOf(jac, 1); // This is {dx/dxi, dy/dxi, dz/dxi} x.normalize(); help.beColumnOf(jac, 2); @@ -139,46 +212,45 @@ Structural3DElement :: giveMaterialOrientationAt(FloatArray &x, FloatArray &y, F void -Structural3DElement :: computeStressVector(FloatArray &answer, const FloatArray &e, GaussPoint *gp, TimeStep *tStep) +Structural3DElement::computeStressVector(FloatArray &answer, const FloatArray &e, GaussPoint *gp, TimeStep *tStep) { if ( this->matRotation ) { ///@todo This won't work properly with "useUpdatedGpRecord" (!) FloatArray x, y, z; - FloatArray rotStrain, s; - this->giveMaterialOrientationAt( x, y, z, gp->giveNaturalCoordinates() ); + this->giveMaterialOrientationAt(x, y, z, gp->giveNaturalCoordinates() ); // Transform from global c.s. to material c.s. - rotStrain = { - e(0) * x(0) * x(0) + e(5) * x(0) * x(1) + e(1) * x(1) * x(1) + e(4) * x(0) * x(2) + e(3) * x(1) * x(2) + e(2) * x(2) * x(2), - e(0) * y(0) * y(0) + e(5) * y(0) * y(1) + e(1) * y(1) * y(1) + e(4) * y(0) * y(2) + e(3) * y(1) * y(2) + e(2) * y(2) * y(2), - e(0) * z(0) * z(0) + e(5) * z(0) * z(1) + e(1) * z(1) * z(1) + e(4) * z(0) * z(2) + e(3) * z(1) * z(2) + e(2) * z(2) * z(2), - 2 * e(0) * y(0) * z(0) + e(4) * y(2) * z(0) + 2 * e(1) * y(1) * z(1) + e(3) * y(2) * z(1) + e(5) * ( y(1) * z(0) + y(0) * z(1) ) + ( e(4) * y(0) + e(3) * y(1) + 2 * e(2) * y(2) ) * z(2), - 2 * e(0) * x(0) * z(0) + e(4) * x(2) * z(0) + 2 * e(1) * x(1) * z(1) + e(3) * x(2) * z(1) + e(5) * ( x(1) * z(0) + x(0) * z(1) ) + ( e(4) * x(0) + e(3) * x(1) + 2 * e(2) * x(2) ) * z(2), - 2 * e(0) * x(0) * y(0) + e(4) * x(2) * y(0) + 2 * e(1) * x(1) * y(1) + e(3) * x(2) * y(1) + e(5) * ( x(1) * y(0) + x(0) * y(1) ) + ( e(4) * x(0) + e(3) * x(1) + 2 * e(2) * x(2) ) * y(2) + FloatArrayF< 6 >rotStrain = { + e [ 0 ] * x [ 0 ] * x [ 0 ] + e [ 5 ] * x [ 0 ] * x [ 1 ] + e [ 1 ] * x [ 1 ] * x [ 1 ] + e [ 4 ] * x [ 0 ] * x [ 2 ] + e [ 3 ] * x [ 1 ] * x [ 2 ] + e [ 2 ] * x [ 2 ] * x [ 2 ], + e [ 0 ] * y [ 0 ] * y [ 0 ] + e [ 5 ] * y [ 0 ] * y [ 1 ] + e [ 1 ] * y [ 1 ] * y [ 1 ] + e [ 4 ] * y [ 0 ] * y [ 2 ] + e [ 3 ] * y [ 1 ] * y [ 2 ] + e [ 2 ] * y [ 2 ] * y [ 2 ], + e [ 0 ] * z [ 0 ] * z [ 0 ] + e [ 5 ] * z [ 0 ] * z [ 1 ] + e [ 1 ] * z [ 1 ] * z [ 1 ] + e [ 4 ] * z [ 0 ] * z [ 2 ] + e [ 3 ] * z [ 1 ] * z [ 2 ] + e [ 2 ] * z [ 2 ] * z [ 2 ], + 2 * e [ 0 ] * y [ 0 ] * z [ 0 ] + e [ 4 ] * y [ 2 ] * z [ 0 ] + 2 * e [ 1 ] * y [ 1 ] * z [ 1 ] + e [ 3 ] * y [ 2 ] * z [ 1 ] + e [ 5 ] * ( y [ 1 ] * z [ 0 ] + y [ 0 ] * z [ 1 ] ) + ( e [ 4 ] * y [ 0 ] + e [ 3 ] * y [ 1 ] + 2 * e [ 2 ] * y [ 2 ] ) * z [ 2 ], + 2 * e [ 0 ] * x [ 0 ] * z [ 0 ] + e [ 4 ] * x [ 2 ] * z [ 0 ] + 2 * e [ 1 ] * x [ 1 ] * z [ 1 ] + e [ 3 ] * x [ 2 ] * z [ 1 ] + e [ 5 ] * ( x [ 1 ] * z [ 0 ] + x [ 0 ] * z [ 1 ] ) + ( e [ 4 ] * x [ 0 ] + e [ 3 ] * x [ 1 ] + 2 * e [ 2 ] * x [ 2 ] ) * z [ 2 ], + 2 * e [ 0 ] * x [ 0 ] * y [ 0 ] + e [ 4 ] * x [ 2 ] * y [ 0 ] + 2 * e [ 1 ] * x [ 1 ] * y [ 1 ] + e [ 3 ] * x [ 2 ] * y [ 1 ] + e [ 5 ] * ( x [ 1 ] * y [ 0 ] + x [ 0 ] * y [ 1 ] ) + ( e [ 4 ] * x [ 0 ] + e [ 3 ] * x [ 1 ] + 2 * e [ 2 ] * x [ 2 ] ) * y [ 2 ] }; - this->giveStructuralCrossSection()->giveRealStress_3d(s, gp, rotStrain, tStep); + auto s = this->giveStructuralCrossSection()->giveRealStress_3d(rotStrain, gp, tStep); answer = { - s(0) * x(0) * x(0) + 2 * s(5) * x(0) * y(0) + s(1) * y(0) * y(0) + 2 * ( s(4) * x(0) + s(3) * y(0) ) * z(0) + s(2) * z(0) * z(0), - s(0) * x(1) * x(1) + 2 * s(5) * x(1) * y(1) + s(1) * y(1) * y(1) + 2 * ( s(4) * x(1) + s(3) * y(1) ) * z(1) + s(2) * z(1) * z(1), - s(0) * x(2) * x(2) + 2 * s(5) * x(2) * y(2) + s(1) * y(2) * y(2) + 2 * ( s(4) * x(2) + s(3) * y(2) ) * z(2) + s(2) * z(2) * z(2), - y(2) * ( s(5) * x(1) + s(1) * y(1) + s(3) * z(1) ) + x(2) * ( s(0) * x(1) + s(5) * y(1) + s(4) * z(1) ) + ( s(4) * x(1) + s(3) * y(1) + s(2) * z(1) ) * z(2), - y(2) * ( s(5) * x(0) + s(1) * y(0) + s(3) * z(0) ) + x(2) * ( s(0) * x(0) + s(5) * y(0) + s(4) * z(0) ) + ( s(4) * x(0) + s(3) * y(0) + s(2) * z(0) ) * z(2), - y(1) * ( s(5) * x(0) + s(1) * y(0) + s(3) * z(0) ) + x(1) * ( s(0) * x(0) + s(5) * y(0) + s(4) * z(0) ) + ( s(4) * x(0) + s(3) * y(0) + s(2) * z(0) ) * z(1) + s [ 0 ] * x [ 0 ] * x [ 0 ] + 2 * s [ 5 ] * x [ 0 ] * y [ 0 ] + s [ 1 ] * y [ 0 ] * y [ 0 ] + 2 * ( s [ 4 ] * x [ 0 ] + s [ 3 ] * y [ 0 ] ) * z [ 0 ] + s [ 2 ] * z [ 0 ] * z [ 0 ], + s [ 0 ] * x [ 1 ] * x [ 1 ] + 2 * s [ 5 ] * x [ 1 ] * y [ 1 ] + s [ 1 ] * y [ 1 ] * y [ 1 ] + 2 * ( s [ 4 ] * x [ 1 ] + s [ 3 ] * y [ 1 ] ) * z [ 1 ] + s [ 2 ] * z [ 1 ] * z [ 1 ], + s [ 0 ] * x [ 2 ] * x [ 2 ] + 2 * s [ 5 ] * x [ 2 ] * y [ 2 ] + s [ 1 ] * y [ 2 ] * y [ 2 ] + 2 * ( s [ 4 ] * x [ 2 ] + s [ 3 ] * y [ 2 ] ) * z [ 2 ] + s [ 2 ] * z [ 2 ] * z [ 2 ], + y [ 2 ] * ( s [ 5 ] * x [ 1 ] + s [ 1 ] * y [ 1 ] + s [ 3 ] * z [ 1 ] ) + x [ 2 ] * ( s [ 0 ] * x [ 1 ] + s [ 5 ] * y [ 1 ] + s [ 4 ] * z [ 1 ] ) + ( s [ 4 ] * x [ 1 ] + s [ 3 ] * y [ 1 ] + s [ 2 ] * z [ 1 ] ) * z [ 2 ], + y [ 2 ] * ( s [ 5 ] * x [ 0 ] + s [ 1 ] * y [ 0 ] + s [ 3 ] * z [ 0 ] ) + x [ 2 ] * ( s [ 0 ] * x [ 0 ] + s [ 5 ] * y [ 0 ] + s [ 4 ] * z [ 0 ] ) + ( s [ 4 ] * x [ 0 ] + s [ 3 ] * y [ 0 ] + s [ 2 ] * z [ 0 ] ) * z [ 2 ], + y [ 1 ] * ( s [ 5 ] * x [ 0 ] + s [ 1 ] * y [ 0 ] + s [ 3 ] * z [ 0 ] ) + x [ 1 ] * ( s [ 0 ] * x [ 0 ] + s [ 5 ] * y [ 0 ] + s [ 4 ] * z [ 0 ] ) + ( s [ 4 ] * x [ 0 ] + s [ 3 ] * y [ 0 ] + s [ 2 ] * z [ 0 ] ) * z [ 1 ] }; } else { - this->giveStructuralCrossSection()->giveRealStress_3d(answer, gp, e, tStep); + answer = this->giveStructuralCrossSection()->giveRealStress_3d(e, gp, tStep); } } void -Structural3DElement :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +Structural3DElement::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveStiffnessMatrix_3d(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_3d(rMode, gp, tStep); if ( this->matRotation ) { FloatArray x, y, z; FloatMatrix Q; - this->giveMaterialOrientationAt( x, y, z, gp->giveNaturalCoordinates() ); + this->giveMaterialOrientationAt(x, y, z, gp->giveNaturalCoordinates() ); Q = { { x(0) * x(0), x(1) * x(1), x(2) * x(2), x(1) * x(2), x(0) * x(2), x(0) * x(1) }, @@ -194,41 +266,68 @@ Structural3DElement :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatRespo void -Structural3DElement :: giveDofManDofIDMask(int inode, IntArray &answer) const +Structural3DElement::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +{ + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_dPdF_3d(rMode, gp, tStep); + if ( this->matRotation ) { + FloatArray x, y, z; + FloatMatrix Q; + this->giveMaterialOrientationAt(x, y, z, gp->giveNaturalCoordinates() ); + Q = { + { x(0) * x(0), x(1) * x(1), x(2) * x(2), x(1) * x(2), x(0) * x(2), x(0) * x(1), x(2) * x(1), x(2) * x(0), x(1) * x(0) }, + { y(0) * y(0), y(1) * y(1), y(2) * y(2), y(1) * y(2), y(0) * y(2), y(0) * y(1), y(2) * y(1), y(2) * y(0), y(1) * y(0) }, + { z(0) * z(0), z(1) * z(1), z(2) * z(2), z(1) * z(2), z(0) * z(2), z(0) * z(1), z(2) * z(1), z(2) * z(0), z(1) * z(0) }, + { y(0) * z(0), y(1) * z(1), y(2) * z(2), y(1) * z(2), y(0) * z(2), y(0) * z(1), y(2) * z(1), y(2) * z(0), y(1) * z(0) }, + { x(0) * z(0), x(1) * z(1), x(2) * z(2), x(1) * z(2), x(0) * z(2), x(0) * z(1), x(2) * z(1), x(2) * z(0), x(1) * z(0) }, + { x(0) * y(0), x(1) * y(1), x(2) * y(2), x(1) * y(2), x(0) * y(2), x(0) * y(1), x(2) * y(1), x(2) * y(0), x(1) * y(0) }, + { z(0) * y(0), z(1) * y(1), z(2) * y(2), z(1) * y(2), z(0) * y(2), z(0) * y(1), z(2) * y(1), z(2) * y(0), z(1) * y(0) }, + { z(0) * x(0), z(1) * x(1), z(2) * x(2), z(1) * x(2), z(0) * x(2), z(0) * x(1), z(2) * x(1), z(2) * x(0), z(1) * x(0) }, + { y(0) * x(0), y(1) * x(1), y(2) * x(2), y(1) * x(2), y(0) * x(2), y(0) * x(1), y(2) * x(1), y(2) * x(0), y(1) * x(0) }, + }; + answer.rotatedWith(Q, 't'); + } +} + + + +void +Structural3DElement::giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {D_u, D_v, D_w}; + answer = { + D_u, D_v, D_w + }; } -int -Structural3DElement :: computeNumberOfDofs() +int +Structural3DElement::computeNumberOfDofs() { ///@todo move one hiearchy up and generalize - IntArray dofIdMask; + IntArray dofIdMask; this->giveDofManDofIDMask(-1, dofIdMask); // ok for standard elements - return this->giveInterpolation()->giveNumberOfNodes() * dofIdMask.giveSize(); + return this->giveInterpolation()->giveNumberOfNodes() * dofIdMask.giveSize(); } -void Structural3DElement :: computeGaussPoints() +void Structural3DElement::computeGaussPoints() // Sets up the array containing the four Gauss points of the receiver. { if ( integrationRulesArray.size() == 0 ) { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 6) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 6); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } -double -Structural3DElement :: computeVolumeAround(GaussPoint *gp) +double +Structural3DElement::computeVolumeAround(GaussPoint *gp) // Returns the portion of the receiver which is attached to gp. { double determinant, weight, volume; - determinant = fabs( this->giveInterpolation()->giveTransformationJacobian( gp->giveNaturalCoordinates(), - FEIElementGeometryWrapper(this) ) ); + determinant = fabs(this->giveInterpolation()->giveTransformationJacobian(gp->giveNaturalCoordinates(), + FEIElementGeometryWrapper(this) ) ); weight = gp->giveWeight(); volume = determinant * weight; @@ -237,43 +336,37 @@ Structural3DElement :: computeVolumeAround(GaussPoint *gp) } - double -Structural3DElement :: giveCharacteristicLength(const FloatArray &normalToCrackPlane) +Structural3DElement::giveCharacteristicLength(const FloatArray &normalToCrackPlane) { return this->giveLengthInDir(normalToCrackPlane); } - - - // Surface support void -Structural3DElement :: computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) +Structural3DElement::computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) { - /* Returns the [ 3 x (nno*3) ] shape function matrix {N} of the receiver, + /* Returns the [ 3 x (nno*3) ] shape function matrix {N} of the receiver, * evaluated at the given gp. * {u} = {N}*{a} gives the displacements at the integration point. - */ - - // Evaluate the shape functions at the position of the gp. + */ + + // Evaluate the shape functions at the position of the gp. FloatArray N; - static_cast< FEInterpolation3d* > ( this->giveInterpolation() )-> - surfaceEvalN( N, iSurf, sgp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + static_cast< FEInterpolation3d * >( this->giveInterpolation() )-> + surfaceEvalN(N, iSurf, sgp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.beNMatrixOf(N, 3); } void -Structural3DElement :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +Structural3DElement::giveSurfaceDofMapping(IntArray &answer, int iSurf) const { - IntArray nodes; const int ndofsn = 3; - static_cast< FEInterpolation3d* > ( this->giveInterpolation() )-> - computeLocalSurfaceMapping(nodes, iSurf); + const auto &nodes = static_cast< FEInterpolation3d * >( this->giveInterpolation() )->computeLocalSurfaceMapping(iSurf); - answer.resize(nodes.giveSize() *3 ); + answer.resize(nodes.giveSize() * 3); for ( int i = 1; i <= nodes.giveSize(); i++ ) { answer.at(i * ndofsn - 2) = nodes.at(i) * ndofsn - 2; @@ -283,45 +376,36 @@ Structural3DElement :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const } double -Structural3DElement :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) +Structural3DElement::computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { - double determinant, weight, volume; - determinant = fabs( static_cast< FEInterpolation3d* > ( this->giveInterpolation() )-> - surfaceGiveTransformationJacobian( iSurf, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double determinant = fabs(static_cast< FEInterpolation3d * >( this->giveInterpolation() )-> + surfaceGiveTransformationJacobian(iSurf, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); - volume = determinant * weight; - - return volume; + double weight = gp->giveWeight(); + return determinant * weight; } - int -Structural3DElement :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *) +Structural3DElement::computeLoadLSToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *) { OOFEM_ERROR("surface local coordinate system not supported"); return 1; } - - - - // Edge support void -Structural3DElement :: giveEdgeDofMapping(IntArray &answer, int iEdge) const +Structural3DElement::giveEdgeDofMapping(IntArray &answer, int iEdge) const { /* * provides dof mapping of local edge dofs (only nonzero are taken into account) * to global element dofs */ - IntArray eNodes; - static_cast< FEInterpolation3d* > ( this->giveInterpolation() )->computeLocalEdgeMapping(eNodes, iEdge); + const auto &eNodes = static_cast< FEInterpolation3d * >( this->giveInterpolation() )->computeLocalEdgeMapping(iEdge); - answer.resize( eNodes.giveSize() * 3 ); + answer.resize(eNodes.giveSize() * 3); for ( int i = 1; i <= eNodes.giveSize(); i++ ) { answer.at(i * 3 - 2) = eNodes.at(i) * 3 - 2; answer.at(i * 3 - 1) = eNodes.at(i) * 3 - 1; @@ -330,22 +414,21 @@ Structural3DElement :: giveEdgeDofMapping(IntArray &answer, int iEdge) const } - double -Structural3DElement :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +Structural3DElement::computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { /* Returns the line element ds associated with the given gp on the specific edge. - * Note: The name is misleading since there is no volume to speak of in this case. + * Note: The name is misleading since there is no volume to speak of in this case. * The returned value is used for integration of a line integral (external forces). */ - double detJ = static_cast< FEInterpolation3d* > ( this->giveInterpolation() )-> - edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + double detJ = static_cast< FEInterpolation3d * >( this->giveInterpolation() )-> + edgeGiveTransformationJacobian(iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); return detJ * gp->giveWeight(); } int -Structural3DElement :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) +Structural3DElement::computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) { // returns transformation matrix from // edge local coordinate system @@ -354,11 +437,8 @@ Structural3DElement :: computeLoadLEToLRotationMatrix(FloatMatrix &answer, int i // // i.e. f(element local) = T * f(edge local) // - ///@todo how should this be supported + ///@todo how should this be supported OOFEM_ERROR("egde local coordinate system not supported"); return 1; } - - - } // end namespace oofem diff --git a/src/sm/Elements/structural3delement.h b/src/sm/Elements/structural3delement.h index b6d850707..f5ecd6ecf 100644 --- a/src/sm/Elements/structural3delement.h +++ b/src/sm/Elements/structural3delement.h @@ -35,7 +35,7 @@ #ifndef structural3delement_h #define structural3delement_h -#include "Elements/nlstructuralelement.h" +#include "sm/Elements/nlstructuralelement.h" #define _IFT_Structural3DElement_materialCoordinateSystem "matcs" ///< [optional] Support for material directions based on element orientation. @@ -63,47 +63,46 @@ class Structural3DElement : public NLStructuralElement * @param n Element number. * @param d Domain to which new material will belong. */ - Structural3DElement(int n, Domain * d); + Structural3DElement(int n, Domain *d); /// Destructor. virtual ~Structural3DElement() { } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual MaterialMode giveMaterialMode(); - virtual int computeNumberOfDofs(); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual double computeVolumeAround(GaussPoint *gp); - - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane); + MaterialMode giveMaterialMode() override; + int computeNumberOfDofs() override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + double computeVolumeAround(GaussPoint *gp) override; + + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override; void giveMaterialOrientationAt(FloatArray &x, FloatArray &y, FloatArray &z, const FloatArray &lcoords); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + + void computeInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) override; + protected: - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS); - virtual void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeGaussPoints(); - - // Edge support - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp); - - virtual int testElementExtension(ElementExtension ext) - { return ( ( ( ext == Element_EdgeLoadSupport ) || ( ext == Element_SurfaceLoadSupport ) ) ? 1 : 0 ); } - - - //virtual IntegrationRule *GetSurfaceIntegrationRule(int); // old - virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); - virtual void giveSurfaceDofMapping(IntArray &answer, int) const; - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int); - virtual int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *gp); - + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int lowerIndx = 1, int upperIndx = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeGaussPoints() override; + + // Edge support + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int computeLoadLEToLRotationMatrix(FloatMatrix &answer, int iEdge, GaussPoint *gp) override; + + int testElementExtension(ElementExtension ext) override + { return ( ( ( ext == Element_EdgeLoadSupport ) || ( ext == Element_SurfaceLoadSupport ) ) ? 1 : 0 ); } + + void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); + void giveSurfaceDofMapping(IntArray &answer, int) const override; + double computeSurfaceVolumeAround(GaussPoint *gp, int) override; + int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int, GaussPoint *gp) override; + private: double dnx(int i, int arg2); }; - - } // end namespace oofem #endif // structural3delement_h diff --git a/src/sm/Elements/structuralelement.C b/src/sm/Elements/structuralelement.C index 36891b87d..2655ffeee 100644 --- a/src/sm/Elements/structuralelement.C +++ b/src/sm/Elements/structuralelement.C @@ -32,12 +32,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Elements/structuralelement.h" -#include "CrossSections/structuralcrosssection.h" -#include "Materials/structuralmaterial.h" -#include "Materials/structuralms.h" +#include "sm/Elements/structuralelement.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "sm/Materials/LatticeMaterials/latticematstatus.h" #include "Loads/structtemperatureload.h" -#include "Materials/structuralnonlocalmaterialext.h" +#include "sm/Materials/structuralnonlocalmaterialext.h" #include "Loads/structeigenstrainload.h" #include "feinterpol.h" #include "domain.h" @@ -64,7 +66,7 @@ namespace oofem { -StructuralElement :: StructuralElement(int n, Domain *aDomain) : + StructuralElement :: StructuralElement(int n, Domain *aDomain) : Element(n, aDomain) {} @@ -93,10 +95,10 @@ void StructuralElement :: computeLoadVector(FloatArray &answer, BodyLoad *load, return; } // Just a wrapper for the deadweight body load computations: - PointLoad *p = dynamic_cast< PointLoad * >(load); + PointLoad *p = dynamic_cast< PointLoad * >( load ); if ( p ) { FloatArray lcoords; - if ( this->computeLocalCoordinates( lcoords, p->giveCoordinates() ) ) { + if ( this->computeLocalCoordinates(lcoords, p->giveCoordinates() ) ) { this->computePointLoadVectorAt(answer, load, tStep, mode); } } else { @@ -122,15 +124,15 @@ void StructuralElement :: computeBoundarySurfaceLoadVector(FloatArray &answer, B FloatArray force, globalIPcoords; //int nsd = fei->giveNsd(); - std :: unique_ptr< IntegrationRule >iRule( this->giveBoundarySurfaceIntegrationRule(load->giveApproxOrder(), boundary) ); + std :: unique_ptr< IntegrationRule >iRule(this->giveBoundarySurfaceIntegrationRule(load->giveApproxOrder(), boundary) ); - for ( GaussPoint *gp : *iRule ) { + for ( GaussPoint *gp : * iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); if ( load->giveFormulationType() == Load :: FT_Entity ) { load->computeValueAt(force, tStep, lcoords, mode); } else { - fei->boundaryLocal2Global( globalIPcoords, boundary, lcoords, FEIElementGeometryWrapper(this) ); + fei->boundaryLocal2Global(globalIPcoords, boundary, lcoords, FEIElementGeometryWrapper(this) ); load->computeValueAt(force, tStep, globalIPcoords, mode); } @@ -142,17 +144,18 @@ void StructuralElement :: computeBoundarySurfaceLoadVector(FloatArray &answer, B } else { ///@todo Support this... // transform from local boundary to element local c.s - /*if ( this->computeLoadLSToLRotationMatrix(T, boundary, gp) ) { - * force.rotatedWith(T, 'n'); - * }*/ - // then to global c.s - if ( this->computeLoadGToLRotationMtrx(T) ) { - force.rotatedWith(T, 't'); + // uncommented since the other (now commented) approach did not work correctly + if ( this->computeLoadLSToLRotationMatrix(T, boundary, gp) ) { + force.rotatedWith(T, 'n'); } + // then to global c.s + //if ( this->computeLoadGToLRotationMtrx(T) ) { + // force.rotatedWith(T, 't'); + //} } // Construct n-matrix - this->computeSurfaceNMatrix(n, boundary, lcoords); // to allow adapttation on element level + this->computeSurfaceNMatrix(n, boundary, lcoords); // to allow adaptation on element level ///@todo Some way to ask for the thickness at a global coordinate maybe? double thickness = 1.0; // Should be the circumference for axisymm-elements. @@ -166,7 +169,7 @@ StructuralElement :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { FEInterpolation *fei = this->giveInterpolation(); const FloatArray &lcoords = gp->giveNaturalCoordinates(); - double J = fei->boundarySurfaceGiveTransformationJacobian( iSurf, lcoords, FEIElementGeometryWrapper(this) ); + double J = fei->boundarySurfaceGiveTransformationJacobian(iSurf, lcoords, FEIElementGeometryWrapper(this) ); return ( gp->giveWeight() * J ); } @@ -175,8 +178,8 @@ void StructuralElement :: computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) { FloatArray n_vec; - this->giveInterpolation()->boundarySurfaceEvalN( n_vec, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); - answer.beNMatrixOf( n_vec, this->giveInterpolation()->giveNsd() ); + this->giveInterpolation()->boundarySurfaceEvalN(n_vec, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); + answer.beNMatrixOf(n_vec, this->giveInterpolation()->giveNsd() ); } @@ -195,15 +198,15 @@ void StructuralElement :: computeBoundaryEdgeLoadVector(FloatArray &answer, Boun FloatMatrix n, T; FloatArray force, globalIPcoords; - std :: unique_ptr< IntegrationRule >iRule( this->giveBoundaryEdgeIntegrationRule(load->giveApproxOrder(), boundary) ); + std :: unique_ptr< IntegrationRule >iRule(this->giveBoundaryEdgeIntegrationRule(load->giveApproxOrder(), boundary) ); - for ( GaussPoint *gp : *iRule ) { + for ( GaussPoint *gp : * iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); if ( load->giveFormulationType() == Load :: FT_Entity ) { load->computeValueAt(force, tStep, lcoords, mode); } else { - fei->boundaryEdgeLocal2Global( globalIPcoords, boundary, lcoords, FEIElementGeometryWrapper(this) ); + fei->boundaryEdgeLocal2Global(globalIPcoords, boundary, lcoords, FEIElementGeometryWrapper(this) ); load->computeValueAt(force, tStep, globalIPcoords, mode); } @@ -239,7 +242,7 @@ StructuralElement :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { FEInterpolation *fei = this->giveInterpolation(); const FloatArray &lcoords = gp->giveNaturalCoordinates(); - double J = fei->boundaryEdgeGiveTransformationJacobian( iEdge, lcoords, FEIElementGeometryWrapper(this) ); + double J = fei->boundaryEdgeGiveTransformationJacobian(iEdge, lcoords, FEIElementGeometryWrapper(this) ); return ( gp->giveWeight() * J ); } @@ -248,8 +251,8 @@ void StructuralElement :: computeEdgeNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) { FloatArray n_vec; - this->giveInterpolation()->boundaryEdgeEvalN( n_vec, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); - answer.beNMatrixOf( n_vec, this->giveInterpolation()->giveNsd() ); + this->giveInterpolation()->boundaryEdgeEvalN(n_vec, boundaryID, lcoords, FEIElementGeometryWrapper(this) ); + answer.beNMatrixOf(n_vec, this->giveInterpolation()->giveNsd() ); } @@ -282,7 +285,7 @@ StructuralElement :: computeBodyLoadVectorAt(FloatArray &answer, Load *forLoad, answer.clear(); if ( force.giveSize() ) { - for ( GaussPoint *gp : *this->giveDefaultIntegrationRulePtr() ) { + for ( GaussPoint *gp : * this->giveDefaultIntegrationRulePtr() ) { this->computeNmatrixAt(gp->giveSubPatchCoordinates(), n); dV = this->computeVolumeAround(gp); dens = this->giveCrossSection()->give('d', gp); @@ -300,10 +303,10 @@ StructuralElement :: computePointLoadVectorAt(FloatArray &answer, Load *load, Ti FloatArray force, lcoords; FloatMatrix T, n; - PointLoad *pointLoad = dynamic_cast< PointLoad * >(load); + PointLoad *pointLoad = dynamic_cast< PointLoad * >( load ); FloatArray coords = pointLoad->giveCoordinates(); pointLoad->computeValueAt(force, tStep, coords, mode); - if ( this->computeLocalCoordinates( lcoords, pointLoad->giveCoordinates() ) ) { + if ( this->computeLocalCoordinates(lcoords, pointLoad->giveCoordinates() ) ) { this->computeNmatrixAt(lcoords, n); answer.beTProductOf(n, force); } else { @@ -394,7 +397,7 @@ StructuralElement :: setupIRForMassMtrxIntegration(IntegrationRule &iRule) if ( ( nip = this->giveNumberOfIPForMassMtrxIntegration() ) == 0 ) { OOFEM_ERROR("no integration points available"); } - iRule.setUpIntegrationPoints( this->giveIntegrationDomain(), nip, this->giveMaterialMode() ); + iRule.setUpIntegrationPoints(this->giveIntegrationDomain(), nip, this->giveMaterialMode() ); } void @@ -477,7 +480,7 @@ StructuralElement :: computeResultingIPTemperatureAt(FloatArray &answer, TimeSte FloatArray gCoords, temperature; int nbc = domain->giveNumberOfBoundaryConditions(); - if ( this->computeGlobalCoordinates( gCoords, gp->giveNaturalCoordinates() ) == 0 ) { + if ( this->computeGlobalCoordinates(gCoords, gp->giveNaturalCoordinates() ) == 0 ) { OOFEM_ERROR("computeGlobalCoordinates failed"); } @@ -496,26 +499,22 @@ StructuralElement :: computeResultingIPTemperatureAt(FloatArray &answer, TimeSte // new approach using sets for ( int i = 1; i <= nbc; ++i ) { + GeneralBoundaryCondition *bc = domain->giveBc(i); - GeneralBoundaryCondition *bc = domain->giveBc(i); - - if (( load = dynamic_cast< StructuralTemperatureLoad * >(bc) )) { - - if ( bc->giveSetNumber() && bc->isImposed(tStep) ) { - if ( load->giveBCValType() == TemperatureBVT ) { - - Set *set = domain->giveSet( bc->giveSetNumber() ); - const IntArray &elements = set->giveElementList(); - - if (elements.contains(this->giveNumber() ) ) { - load->computeValueAt(temperature, tStep, gCoords, mode); - answer.add(temperature); - } - } - } - } + if ( ( load = dynamic_cast< StructuralTemperatureLoad * >( bc ) ) ) { + if ( bc->giveSetNumber() && bc->isImposed(tStep) ) { + if ( load->giveBCValType() == TemperatureBVT ) { + Set *set = domain->giveSet(bc->giveSetNumber() ); + const IntArray &elements = set->giveElementList(); + + if ( elements.contains(this->giveNumber() ) ) { + load->computeValueAt(temperature, tStep, gCoords, mode); + answer.add(temperature); + } + } + } + } } - } void @@ -527,7 +526,7 @@ StructuralElement :: computeResultingIPEigenstrainAt(FloatArray &answer, TimeSte FloatArray gCoords, eigenstrain; int nbc = domain->giveNumberOfBoundaryConditions(); - if ( this->computeGlobalCoordinates( gCoords, gp->giveNaturalCoordinates() ) == 0 ) { + if ( this->computeGlobalCoordinates(gCoords, gp->giveNaturalCoordinates() ) == 0 ) { OOFEM_ERROR("computeGlobalCoordinates failed"); } @@ -548,23 +547,21 @@ StructuralElement :: computeResultingIPEigenstrainAt(FloatArray &answer, TimeSte // new approach using sets for ( int i = 1; i <= nbc; ++i ) { + GeneralBoundaryCondition *bc = domain->giveBc(i); - GeneralBoundaryCondition *bc = domain->giveBc(i); - - if (( load = dynamic_cast< StructuralEigenstrainLoad * >(bc) )) { - if ( bc->giveSetNumber() && bc->isImposed(tStep) ) { - if ( load->giveBCValType() == EigenstrainBVT ) { - - Set *set = domain->giveSet( bc->giveSetNumber() ); - const IntArray &elements = set->giveElementList(); - - if (elements.contains(this->giveNumber() ) ) { - load->computeValueAt(eigenstrain, tStep, gCoords, mode); - answer.add(eigenstrain); - } - } - } - } + if ( ( load = dynamic_cast< StructuralEigenstrainLoad * >( bc ) ) ) { + if ( bc->giveSetNumber() && bc->isImposed(tStep) ) { + if ( load->giveBCValType() == EigenstrainBVT ) { + Set *set = domain->giveSet(bc->giveSetNumber() ); + const IntArray &elements = set->giveElementList(); + + if ( elements.contains(this->giveNumber() ) ) { + load->computeValueAt(eigenstrain, tStep, gCoords, mode); + answer.add(eigenstrain); + } + } + } + } } } @@ -611,7 +608,7 @@ StructuralElement :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode iRule = integrationRulesArray [ j ].get(); } - for ( GaussPoint *gp : *iRule ) { + for ( GaussPoint *gp : * iRule ) { this->computeBmatrixAt(gp, bi, iStartIndx, iEndIndx); this->computeConstitutiveMatrixAt(d, rMode, gp, tStep); dij.beSubMatrixOf(d, iStartIndx, iEndIndx, jStartIndx, jEndIndx); @@ -632,7 +629,7 @@ StructuralElement :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode } } } else { - for ( GaussPoint *gp : *this->giveDefaultIntegrationRulePtr() ) { + for ( GaussPoint *gp : * this->giveDefaultIntegrationRulePtr() ) { this->computeBmatrixAt(gp, bj); this->computeConstitutiveMatrixAt(d, rMode, gp, tStep); dV = this->computeVolumeAround(gp); @@ -669,7 +666,7 @@ void StructuralElement :: computeStiffnessMatrix_withIRulesAsSubcells(FloatMatri // loop over individual integration rules for ( auto &iRule : integrationRulesArray ) { // loop over individual integration points - for ( GaussPoint *gp : *iRule ) { + for ( GaussPoint *gp : * iRule ) { double dV = this->computeVolumeAround(gp); this->computeBmatrixAt(gp, bj); this->computeConstitutiveMatrixAt(d, rMode, gp, tStep); @@ -705,7 +702,7 @@ StructuralElement :: computeStrainVector(FloatArray &answer, GaussPoint *gp, Tim FloatArray u; if ( !this->isActivated(tStep) ) { - answer.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + answer.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); answer.zero(); return; } @@ -753,15 +750,26 @@ StructuralElement :: giveInternalForcesVector(FloatArray &answer, // zero answer will resize accordingly when adding first contribution answer.clear(); - for ( GaussPoint *gp : *this->giveDefaultIntegrationRulePtr() ) { - StructuralMaterialStatus *matStat = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); + for ( GaussPoint *gp : * this->giveDefaultIntegrationRulePtr() ) { this->computeBmatrixAt(gp, b); if ( useUpdatedGpRecord == 1 ) { - stress = matStat->giveStressVector(); + auto status = gp->giveMaterialStatus(); + StructuralMaterialStatus *matStat = dynamic_cast< StructuralMaterialStatus * >( status ); + if ( matStat ) { + stress = matStat->giveStressVector(); + } else { + LatticeMaterialStatus *lmatStat = dynamic_cast< LatticeMaterialStatus * >( status ); + if ( lmatStat ) { + stress = lmatStat->giveLatticeStress(); + } else { + StructuralInterfaceMaterialStatus *ms = static_cast< StructuralInterfaceMaterialStatus * >( status ); + stress = ms->giveTraction(); + } + } } else { if ( !this->isActivated(tStep) ) { - strain.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + strain.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); strain.zero(); } strain.beProductOf(b, u); @@ -784,7 +792,7 @@ StructuralElement :: giveInternalForcesVector(FloatArray &answer, // (Note that no reduction will take place if // the simulation is actually 3D.) FloatArray stressTemp; - StructuralMaterial :: giveReducedSymVectorForm( stressTemp, stress, gp->giveMaterialMode() ); + StructuralMaterial :: giveReducedSymVectorForm(stressTemp, stress, gp->giveMaterialMode() ); answer.plusProduct(b, stressTemp, dV); } else { answer.plusProduct(b, stress, dV); @@ -833,7 +841,7 @@ StructuralElement :: giveInternalForcesVector_withIRulesAsSubcells(FloatArray &a // loop over individual integration rules for ( auto &iRule : integrationRulesArray ) { - for ( GaussPoint *gp : *iRule ) { + for ( GaussPoint *gp : * iRule ) { StructuralMaterialStatus *matStat = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() ); this->computeBmatrixAt(gp, b); @@ -841,7 +849,7 @@ StructuralElement :: giveInternalForcesVector_withIRulesAsSubcells(FloatArray &a stress = matStat->giveStressVector(); } else { if ( !this->isActivated(tStep) ) { - strain.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + strain.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); strain.zero(); } strain.beProductOf(b, u); @@ -899,8 +907,10 @@ StructuralElement :: giveCharacteristicMatrix(FloatMatrix &answer, this->computeLumpedMassMatrix(answer, tStep); } else if ( mtrx == InitialStressMatrix ) { this->computeInitialStressMatrix(answer, tStep); + } else if ( mtrx == LumpedInitialStressMatrix ) { + this->computeLumpedInitialStressMatrix(answer, tStep); } else { - OOFEM_ERROR( "Unknown Type of characteristic mtrx (%s)", __CharTypeToString(mtrx) ); + OOFEM_ERROR("Unknown Type of characteristic mtrx (%s)", __CharTypeToString(mtrx) ); } } @@ -926,12 +936,12 @@ StructuralElement :: giveCharacteristicVector(FloatArray &answer, CharType mtrx, } else if ( mtrx == LumpedMassMatrix ) { FloatMatrix M; this->computeLumpedMassMatrix(M, tStep); - answer.resize( M.giveNumberOfColumns() ); + answer.resize(M.giveNumberOfColumns() ); for ( int i = 0; i < M.giveNumberOfColumns(); ++i ) { answer [ i ] = M(i, i); } } else { - OOFEM_ERROR( "Unknown Type of characteristic mtrx (%s)", __CharTypeToString(mtrx) ); + OOFEM_ERROR("Unknown Type of characteristic mtrx (%s)", __CharTypeToString(mtrx) ); } } @@ -943,7 +953,7 @@ StructuralElement :: updateYourself(TimeStep *tStep) // record initial displacement if element not active if ( activityTimeFunction && !isActivated(tStep) ) { if ( !initialDisplacements ) { - initialDisplacements.reset( new FloatArray() ); + initialDisplacements = std :: make_unique< FloatArray >(); } this->computeVectorOf(VM_Total, tStep, * initialDisplacements); @@ -959,7 +969,7 @@ StructuralElement :: updateInternalState(TimeStep *tStep) // force updating strains & stresses for ( auto &iRule : integrationRulesArray ) { - for ( GaussPoint *gp : *iRule ) { + for ( GaussPoint *gp : * iRule ) { this->computeStrainVector(strain, gp, tStep); this->computeStressVector(stress, strain, gp, tStep); } @@ -984,7 +994,7 @@ StructuralElement :: updateBeforeNonlocalAverage(TimeStep *tStep) // force updating local quantities for ( auto &iRule : integrationRulesArray ) { - for ( GaussPoint *gp : *iRule ) { + for ( GaussPoint *gp : * iRule ) { this->computeStrainVector(epsilon, gp, tStep); // provide material local strain increment - as is provided to computeRealStresVector // allows to update internal vars to be averaged to new state @@ -1013,7 +1023,7 @@ StructuralElement :: checkConsistency() { int result = 1; if ( !this->giveCrossSection()->testCrossSectionExtension(CS_StructuralCapability) ) { - OOFEM_WARNING( "cross-section %s without structural support", this->giveCrossSection()->giveClassName() ); + OOFEM_WARNING("cross-section %s without structural support", this->giveCrossSection()->giveClassName() ); result = 0; } @@ -1030,7 +1040,7 @@ StructuralElement :: computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix & answer.resize(dim, dim * numNodes); answer.zero(); - giveInterpolation()->evalN( N, iLocCoord, FEIElementGeometryWrapper(this) ); + giveInterpolation()->evalN(N, iLocCoord, FEIElementGeometryWrapper(this) ); answer.beNMatrixOf(N, dim); } @@ -1152,9 +1162,9 @@ StructuralElement :: giveNonlocalLocationArray(IntArray &locationArray, const Un locationArray.clear(); // loop over element IP - for ( IntegrationPoint *ip : *this->giveDefaultIntegrationRulePtr() ) { + for ( IntegrationPoint *ip : * this->giveDefaultIntegrationRulePtr() ) { auto interface = static_cast< NonlocalMaterialStiffnessInterface * >( this->giveStructuralCrossSection()-> - giveMaterialInterface(NonlocalMaterialStiffnessInterfaceType, ip) ); + giveMaterialInterface(NonlocalMaterialStiffnessInterfaceType, ip) ); if ( interface == NULL ) { @@ -1163,9 +1173,9 @@ StructuralElement :: giveNonlocalLocationArray(IntArray &locationArray, const Un } auto integrationDomainList = interface-> - NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(ip); + NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(ip); // loop over IP influencing IPs, extract corresponding element numbers and their code numbers - for ( auto &lir : *integrationDomainList ) { + for ( auto &lir : * integrationDomainList ) { lir.nearGp->giveElement()->giveLocationArray(elemLocArry, s); /* * Currently no care given to multiple occurences of code number in locationArray. @@ -1186,9 +1196,9 @@ StructuralElement :: addNonlocalStiffnessContributions(SparseMtrx &dest, const U } // loop over element IP - for ( IntegrationPoint *ip : *this->giveDefaultIntegrationRulePtr() ) { + for ( IntegrationPoint *ip : * this->giveDefaultIntegrationRulePtr() ) { auto interface = static_cast< NonlocalMaterialStiffnessInterface * >( this->giveStructuralCrossSection()-> - giveMaterialInterface(NonlocalMaterialStiffnessInterfaceType, ip) ); + giveMaterialInterface(NonlocalMaterialStiffnessInterfaceType, ip) ); if ( interface == NULL ) { return; } @@ -1205,9 +1215,9 @@ StructuralElement :: adaptiveUpdate(TimeStep *tStep) FloatArray strain; for ( auto &iRule : integrationRulesArray ) { - for ( IntegrationPoint *ip : *iRule ) { + for ( IntegrationPoint *ip : * iRule ) { auto interface = static_cast< MaterialModelMapperInterface * >( this->giveStructuralCrossSection()-> - giveMaterialInterface(MaterialModelMapperInterfaceType, ip) ); + giveMaterialInterface(MaterialModelMapperInterfaceType, ip) ); if ( interface == NULL ) { return 0; @@ -1220,10 +1230,10 @@ StructuralElement :: adaptiveUpdate(TimeStep *tStep) return result; } -IRResultType -StructuralElement :: initializeFrom(InputRecord *ir) +void +StructuralElement :: initializeFrom(InputRecord &ir) { - return Element :: initializeFrom(ir); + Element :: initializeFrom(ir); } void StructuralElement :: giveInputRecord(DynamicInputRecord &input) @@ -1243,7 +1253,7 @@ void StructuralElement :: createMaterialStatus() { StructuralCrossSection *cs = giveStructuralCrossSection(); for ( auto &iRule : integrationRulesArray ) { - for ( GaussPoint *gp : *iRule ) { + for ( GaussPoint *gp : * iRule ) { cs->createMaterialStatus(* gp); } } @@ -1277,13 +1287,13 @@ StructuralElement :: showSparseMtrxStructure(CharType mtrx, oofegGraphicContext mtrx == SecantStiffnessMatrix || mtrx == ElasticStiffnessMatrix ) { int i, j, n; IntArray loc; - this->giveLocationArray( loc, EModelDefaultEquationNumbering() ); + this->giveLocationArray(loc, EModelDefaultEquationNumbering() ); WCRec p [ 4 ]; GraphicObj *go; EASValsSetLineWidth(OOFEG_SPARSE_PROFILE_WIDTH); - EASValsSetColor( gc.getStandardSparseProfileColor() ); + EASValsSetColor(gc.getStandardSparseProfileColor() ); EASValsSetLayer(OOFEG_SPARSE_PROFILE_LAYER); EASValsSetFillStyle(FILL_SOLID); @@ -1359,9 +1369,9 @@ StructuralElement :: showExtendedSparseMtrxStructure(CharType mtrx, oofegGraphic { if ( mtrx == TangentStiffnessMatrix ) { // loop over element IP - for ( IntegrationPoint *ip : *this->giveDefaultIntegrationRulePtr() ) { + for ( IntegrationPoint *ip : * this->giveDefaultIntegrationRulePtr() ) { auto interface = static_cast< NonlocalMaterialStiffnessInterface * >( this->giveStructuralCrossSection()-> - giveMaterialInterface(NonlocalMaterialStiffnessInterfaceType, ip) ); + giveMaterialInterface(NonlocalMaterialStiffnessInterfaceType, ip) ); if ( interface == NULL ) { return; diff --git a/src/sm/Elements/structuralelement.h b/src/sm/Elements/structuralelement.h index 558920b74..c66e1d051 100644 --- a/src/sm/Elements/structuralelement.h +++ b/src/sm/Elements/structuralelement.h @@ -92,11 +92,11 @@ class IDNLMaterial; * Calculating the strains and stresses at its Gauss points. * - Printing its output in the data file and updating itself. */ -class StructuralElement : public Element +class OOFEM_EXPORT StructuralElement : public Element { protected: /// Initial displacement vector, describes the initial nodal displacements when element has been casted. - std :: unique_ptr< FloatArray >initialDisplacements; + std::unique_ptr< FloatArray >initialDisplacements; public: /** @@ -108,8 +108,8 @@ class StructuralElement : public Element /// Destructor. virtual ~StructuralElement(); - virtual void giveCharacteristicMatrix(FloatMatrix & answer, CharType, TimeStep * tStep); - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep); + void giveCharacteristicMatrix(FloatMatrix &answer, CharType, TimeStep *tStep) override; + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override; /** * Computes mass matrix of receiver. Default implementation returns consistent mass matrix and uses @@ -198,8 +198,14 @@ class StructuralElement : public Element { OOFEM_ERROR("not implemented"); } + /** + * Computes lumped initial stress matrix of receiver. + * @param answer Lumped initial stress matrix. + * @param tStep Time step. + */ + virtual void computeLumpedInitialStressMatrix(FloatMatrix &answer, TimeStep *tStep) {} - virtual void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer); + void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) override; // stress equivalent vector in nodes (vector of internal forces) // - mainly for nonLinear Analysis. @@ -235,7 +241,7 @@ class StructuralElement : public Element */ virtual void computeStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; /** * Computes at given time (tStep) the the resulting temperature component array. * This is summation of all temperature load components of receiver. @@ -268,7 +274,7 @@ class StructuralElement : public Element * updateBeforeNonlocalAverage member function of structural nonlocal material class. * @param tStep Time step. */ - virtual void updateBeforeNonlocalAverage(TimeStep *tStep); + void updateBeforeNonlocalAverage(TimeStep *tStep) override; /** * Returns the "nonlocal" location array of receiver. This is necessary, when stiffness matrix * of nonlocal model is assembled. Since model is nonlocal, the value at given IP depends on @@ -286,13 +292,13 @@ class StructuralElement : public Element //@} // Overloaded methods. - virtual int adaptiveUpdate(TimeStep *tStep); - virtual void updateInternalState(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); - virtual int checkConsistency(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveClassName() const { return "StructuralElement"; } + int adaptiveUpdate(TimeStep *tStep) override; + void updateInternalState(TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override; + int checkConsistency() override; + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveClassName() const override { return "StructuralElement"; } #ifdef __OOFEG /** @@ -307,19 +313,19 @@ class StructuralElement : public Element * @param tStep Time step. * @return Nonzero if o.k, zero otherwise. */ - virtual int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *tStep); + int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, + int node, TimeStep *tStep) override; /// Shows sparse structure - virtual void showSparseMtrxStructure(CharType mtrx, oofegGraphicContext &gc, TimeStep *tStep); + void showSparseMtrxStructure(CharType mtrx, oofegGraphicContext &gc, TimeStep *tStep) override; /// Shows extended sparse structure (for example, due to nonlocal interactions for tangent stiffness) - virtual void showExtendedSparseMtrxStructure(CharType mtrx, oofegGraphicContext &gc, TimeStep *tStep); + void showExtendedSparseMtrxStructure(CharType mtrx, oofegGraphicContext &gc, TimeStep *tStep) override; #endif // Interface for body loads applied by Sets: - virtual void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global = true); - virtual void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global = true); + void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; + void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global = true) override; + void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global = true) override; /// computes edge interpolation matrix virtual void computeEdgeNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords); /** @@ -347,6 +353,7 @@ class StructuralElement : public Element virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) = 0; + /// Helper function which returns the structural cross-section for the element. StructuralCrossSection *giveStructuralCrossSection(); @@ -395,8 +402,6 @@ class StructuralElement : public Element */ virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const { answer.clear(); } - ///@todo Old, only kept until all el have changed to the above - virtual IntegrationRule *GetSurfaceIntegrationRule(int order) { return NULL; } /** * Computes volume related to integration point on local edge. * @param gp edge integration point diff --git a/src/sm/Elements/structuralelementevaluator.C b/src/sm/Elements/structuralelementevaluator.C index 627d386c7..d7f61b471 100644 --- a/src/sm/Elements/structuralelementevaluator.C +++ b/src/sm/Elements/structuralelementevaluator.C @@ -32,11 +32,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/structuralelementevaluator.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/CrossSections/structuralcrosssection.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/structuralelementevaluator.h" +#include "sm/Elements/structuralelement.h" +#include "sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "floatarray.h" #include "floatmatrix.h" #include "domain.h" diff --git a/src/sm/Elements/structuralelementevaluator.h b/src/sm/Elements/structuralelementevaluator.h index cf330f841..b3991fc40 100644 --- a/src/sm/Elements/structuralelementevaluator.h +++ b/src/sm/Elements/structuralelementevaluator.h @@ -69,7 +69,7 @@ class StructuralElementEvaluator * Returns the integration rule for mass matrices, if relevant. * @return Number of integration points for mass matrix. */ - virtual IntegrationRule *giveMassMtrxIntegrationRule() { return NULL; } + virtual IntegrationRule *giveMassMtrxIntegrationRule() { return nullptr; } /** * Returns mask indicating, which unknowns (their type and ordering is the same as * element unknown vector) participate in mass matrix integration. @@ -140,6 +140,15 @@ class StructuralElementEvaluator * @param tStep Time step. */ virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) = 0; + /** + * Computes large strain constitutive matrix of receiver. + * @param answer Constitutive matrix. + * @param rMode Material response mode of answer. + * @param gp Integration point for which constitutive matrix is computed. + * @param tStep Time step. + */ + // virtual void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) = 0; + /** * Optimized version, allowing to pass element displacements as parameter. * Standard version has a huge performance leak; in typical IGA element the element vector is VERY large diff --git a/src/sm/Elements/tet21ghostsolid.C b/src/sm/Elements/tet21ghostsolid.C index 1c89d51ff..c462b93a9 100644 --- a/src/sm/Elements/tet21ghostsolid.C +++ b/src/sm/Elements/tet21ghostsolid.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/tet21ghostsolid.h" -#include "../sm/Elements/nlstructuralelement.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/tet21ghostsolid.h" +#include "sm/Elements/nlstructuralelement.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei3dtetquad.h" #include "fei3dtetlin.h" #include "classfactory.h" @@ -53,7 +53,7 @@ #include #ifdef __FM_MODULE - #include "fluiddynamicmaterial.h" + #include "fm/Materials/fluiddynamicmaterial.h" #include "fluidcrosssection.h" #endif @@ -69,20 +69,20 @@ namespace oofem { REGISTER_Element(tet21ghostsolid); -FEI3dTetQuad tet21ghostsolid :: interpolation; -FEI3dTetLin tet21ghostsolid :: interpolation_lin; +FEI3dTetQuad tet21ghostsolid::interpolation; +FEI3dTetLin tet21ghostsolid::interpolation_lin; -IntArray tet21ghostsolid :: momentum_ordering(30); -IntArray tet21ghostsolid :: conservation_ordering(4); -IntArray tet21ghostsolid :: ghostdisplacement_ordering(30); -IntArray tet21ghostsolid :: velocitydofsonside = { +IntArray tet21ghostsolid::momentum_ordering(30); +IntArray tet21ghostsolid::conservation_ordering(4); +IntArray tet21ghostsolid::ghostdisplacement_ordering(30); +IntArray tet21ghostsolid::velocitydofsonside = { 1, 2, 3, 8, 9, 10, 15, 16, 17, 22, 23, 24, 28, 29, 30, 34, 35, 36 }; -IntArray tet21ghostsolid :: displacementdofsonside = { +IntArray tet21ghostsolid::displacementdofsonside = { 4, 5, 6, 11, 12, 13, 18, 19, 20, 25, 26, 27, 31, 32, 33, 37, 38, 39 }; -tet21ghostsolid :: tet21ghostsolid(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), SpatialLocalizerInterface(this) +tet21ghostsolid::tet21ghostsolid(int n, Domain *aDomain) : NLStructuralElement(n, aDomain), SpatialLocalizerInterface(this) { numberOfGaussPoints = 4; numberOfDofMans = 10; @@ -98,27 +98,27 @@ tet21ghostsolid :: tet21ghostsolid(int n, Domain *aDomain) : NLStructuralElement Dghost.at(3, 3) = 1 - nu; Dghost.at(3, 1) = Dghost.at(3, 2) = nu; Dghost.at(4, 4) = Dghost.at(5, 5) = Dghost.at(6, 6) = .5 * ( 1 - 2 * nu ); - Dghost.times( E / ( 1 + nu ) / ( 1 - 2 * nu ) ); + Dghost.times(E / ( 1 + nu ) / ( 1 - 2 * nu ) ); conservation_ordering = { 7, 14, 21, 28 }; for ( int i = 0, j = 1; i < 10; ++i ) { - momentum_ordering(i * 3 + 0) = j++; - momentum_ordering(i * 3 + 1) = j++; - momentum_ordering(i * 3 + 2) = j++; + momentum_ordering [ i * 3 + 0 ] = j++; + momentum_ordering [ i * 3 + 1 ] = j++; + momentum_ordering [ i * 3 + 2 ] = j++; if ( i <= 3 ) { j++; } - j = j + 3; + j += 3; } for ( int i = 0, j = 1; i < 10; ++i ) { - j = j + 3; - ghostdisplacement_ordering(i * 3 + 0) = j++; - ghostdisplacement_ordering(i * 3 + 1) = j++; - ghostdisplacement_ordering(i * 3 + 2) = j++; + j += 3; + ghostdisplacement_ordering [ i * 3 + 0 ] = j++; + ghostdisplacement_ordering [ i * 3 + 1 ] = j++; + ghostdisplacement_ordering [ i * 3 + 2 ] = j++; if ( i <= 3 ) { j++; } @@ -126,13 +126,13 @@ tet21ghostsolid :: tet21ghostsolid(int n, Domain *aDomain) : NLStructuralElement } FEInterpolation * -tet21ghostsolid :: giveInterpolation() const +tet21ghostsolid::giveInterpolation() const { return & interpolation; } FEInterpolation * -tet21ghostsolid :: giveInterpolation(DofIDItem id) const +tet21ghostsolid::giveInterpolation(DofIDItem id) const { if ( id == P_f ) { return & interpolation_lin; @@ -142,18 +142,18 @@ tet21ghostsolid :: giveInterpolation(DofIDItem id) const } void -tet21ghostsolid :: computeGaussPoints() +tet21ghostsolid::computeGaussPoints() // Sets up the array containing the four Gauss points of the receiver. { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 6) ); + integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 6); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } void -tet21ghostsolid :: computeNumericStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +tet21ghostsolid::computeNumericStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { FloatArray a, aPert, intF, intFPert, DintF; double eps = 1e-9; @@ -171,14 +171,14 @@ tet21ghostsolid :: computeNumericStiffnessMatrix(FloatMatrix &answer, MatRespons giveInternalForcesVectorGivenSolution(intFPert, tStep, 0, aPert); - DintF.operator = ( intF - intFPert ); + DintF.operator=(intF - intFPert); DintF.times(-1 / eps); answer.setColumn(DintF, i); } } void -tet21ghostsolid :: computeNumericStiffnessMatrixDebug(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +tet21ghostsolid::computeNumericStiffnessMatrixDebug(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { FloatArray a, aPert, intF, intFPert, DintF; double eps = 1e-9; @@ -196,7 +196,7 @@ tet21ghostsolid :: computeNumericStiffnessMatrixDebug(FloatMatrix &answer, MatRe giveInternalForcesVectorGivenSolutionDebug(intFPert, tStep, 0, aPert, false); - DintF.operator = ( intF - intFPert ); + DintF.operator=(intF - intFPert); DintF.times(-1 / eps); answer.setColumn(DintF, i); } @@ -204,29 +204,35 @@ tet21ghostsolid :: computeNumericStiffnessMatrixDebug(FloatMatrix &answer, MatRe void -tet21ghostsolid :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +tet21ghostsolid::computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveRealStress_3d(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveRealStress_3d(strain, gp, tStep); } void -tet21ghostsolid :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +tet21ghostsolid::computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveStiffnessMatrix_3d(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_3d(rMode, gp, tStep); } + void -tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +tet21ghostsolid::computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { -#if USENUMTAN == 1 + answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_dPdF_3d(rMode, gp, tStep); +} + +void +tet21ghostsolid::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) +{ +#ifdef __FM_MODULE + #if USENUMTAN == 1 computeNumericStiffnessMatrix(answer, rMode, tStep); return; -#endif + #endif -#ifdef __FM_MODULE FluidDynamicMaterial *fluidMaterial = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); -#endif FloatMatrix afDu, afDw, bfuDu, bfuDp, bfpDu, bfpDw, cfwDu; FloatMatrix Kf, G, Kx, Ed, EdB, dNx; @@ -250,10 +256,10 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r if ( !tStep->isTheFirstStep() ) { this->computeVectorOf(VM_Total, tStep->givePreviousStep(), a_prev); } else { - a_prev.resize( a.giveSize() ); + a_prev.resize(a.giveSize() ); a_prev.zero(); } - a_inc.operator = ( a - a_prev ); + a_inc.operator=(a - a_prev); aVelocity.beSubArrayOf(a, momentum_ordering); aPressure.beSubArrayOf(a, conservation_ordering); @@ -261,16 +267,16 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r aIncGhostDisplacement.beSubArrayOf(a_inc, ghostdisplacement_ordering); FloatArray aTotal; - aTotal.operator = ( aVelocity + aIncGhostDisplacement * VELOCITYCOEFF ); // Assume deltaT=1 gives that the increment is the velocity + aTotal.operator=(aVelocity + aIncGhostDisplacement * VELOCITYCOEFF); // Assume deltaT=1 gives that the increment is the velocity - for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { + for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) { // gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); const FloatArray &lcoords = gp->giveNaturalCoordinates(); - double detJ = fabs( ( this->interpolation.giveTransformationJacobian( lcoords, FEIElementGeometryWrapper(this) ) ) ); + double detJ = fabs( ( this->interpolation.giveTransformationJacobian(lcoords, FEIElementGeometryWrapper(this) ) ) ); double weight = gp->giveWeight(); - this->interpolation.evaldNdx( dNx, lcoords, FEIElementGeometryWrapper(this) ); - this->interpolation_lin.evalN( Nlin, lcoords, FEIElementGeometryWrapper(this) ); + this->interpolation.evaldNdx(dNx, lcoords, FEIElementGeometryWrapper(this) ); + this->interpolation_lin.evalN(Nlin, lcoords, FEIElementGeometryWrapper(this) ); // Move to small deformations dNv.resize(30); // dNv = [dN1/dx dN1/dy dN1/dz dN2/dx dN2/dy dN2/dz ... dN10/dz] @@ -280,13 +286,9 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r dNv.at(k * 3 + 3) = dNx.at(k + 1, 3); } -#ifdef __FM_MODULE gp->setMaterialMode(_3dFlow); - fluidMaterial->giveDeviatoricStiffnessMatrix(Ed, TangentStiffness, gp, tStep); + Ed = fluidMaterial->computeTangent3D(TangentStiffness, gp, tStep); gp->setMaterialMode(_3dMat); -#else - OOFEM_ERROR("Fluid module missing\n"); -#endif if ( nlGeometry == 0 ) { FloatMatrix B; @@ -303,8 +305,8 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r // Incompressibility part G.plusDyadUnsym(dNv, Nlin, -detJ * weight); } else { - int Voigt6 [ 3 ] [ 3 ] = { { 1, 6, 5 }, { 6, 2, 4 }, { 5, 4, 3 } }; - int Voigt9 [ 3 ] [ 3 ] = { { 1, 6, 5 }, { 9, 2, 4 }, { 8, 7, 3 } }; + int Voigt6[ 3 ] [ 3 ] = { { 1, 6, 5 }, { 6, 2, 4 }, { 5, 4, 3 } }; + int Voigt9[ 3 ] [ 3 ] = { { 1, 6, 5 }, { 9, 2, 4 }, { 8, 7, 3 } }; // Compute commonly used matrices FloatArray Fa, Finva, FinvTa; @@ -327,24 +329,25 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r NlinFinvTaB.beDyadicProductOf(Nlin, FinvTaB); double J = F.giveDeterminant(); -#if FIXEDJ == 1 + #if FIXEDJ == 1 J = 1; -#endif + #endif // Compute Cauchy stress FloatArray fluidCauchyArray, epsf; FloatMatrix fluidCauchyMatrix; - double epsvol, pressure; + double pressure; epsf.beProductOf(B, aTotal); pressure = Nlin.dotProduct(aPressure); -#if FIXEDpressure == 1 + #if FIXEDpressure == 1 pressure = 1.0; -#endif + #endif gp->setMaterialMode(_3dFlow); - fluidMaterial->computeDeviatoricStressVector(fluidCauchyArray, epsvol, gp, epsf, pressure, tStep); + auto stress_eps = fluidMaterial->computeDeviatoricStress3D(epsf, pressure, gp, tStep); + fluidCauchyArray = stress_eps.first; gp->setMaterialMode(_3dMat); fluidCauchyMatrix.beMatrixFormOfStress(fluidCauchyArray); @@ -360,9 +363,9 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r afuT1.beDyadicProductOf(BTS, FinvTaB); afuT1.times(J * weight * detJ); -#if FIXEDJ == 1 + #if FIXEDJ == 1 afuT1.times(0.0); -#endif + #endif afDu.add(afuT1); // 2nd term ------------ // Works @@ -414,9 +417,9 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r BTK.beTProductOf(BH, K); afuT3.beProductOf(BTK, BH); afuT3.times(-J * weight * detJ); -#if FIXEDFinvT == 1 + #if FIXEDFinvT == 1 afuT3.times(0.0); -#endif + #endif afDu.add(afuT3); // afDw terms ========== // Works @@ -485,9 +488,9 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r bfpT1 = NlinFinvTaB; bfpT1.times(-J * detJ * weight * FinvTaBv); -#if FIXEDJ == 1 + #if FIXEDJ == 1 bfpT1.times(0.0); -#endif + #endif bfpDu.add(bfpT1); @@ -498,9 +501,9 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r AiiB.beTProductOf(BH, A_IVa); bfpT2.beDyadicProductOf(Nlin, AiiB); bfpT2.times(J * detJ * weight); -#if FIXEDFinvT == 1 + #if FIXEDFinvT == 1 bfpT2.times(0.0); -#endif + #endif bfpDu.add(bfpT2); @@ -552,7 +555,7 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r answer.beProductOf(Itransform, temp); // ******************* This is for development purposes only. Compare to numerical stiffness tangent -#if TESTTANGENT + #if TESTTANGENT if ( ( this->globalNumber == 292 ) && ( tStep->giveNumber() > 0 ) ) { double MaxErr = 0.0; FloatMatrix numtan; @@ -585,7 +588,7 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r } } - printf( "globalNumber: %u, i:%u, j:%u, MaxErr: %e, Numtan=%f, Analytic=%f\n", this->globalNumber, imax, jmax, MaxErr, numtan.at(imax, jmax), temp.at(imax, jmax) ); + printf("globalNumber: %u, i:%u, j:%u, MaxErr: %e, Numtan=%f, Analytic=%f\n", this->globalNumber, imax, jmax, MaxErr, numtan.at(imax, jmax), temp.at(imax, jmax) ); numtan.printYourselfToFile("/tmp/numtan.txt", false); temp.printYourselfToFile("/tmp/analytic.txt", false); @@ -593,13 +596,18 @@ tet21ghostsolid :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode r printf("The error is actually quite large..\n"); } } -#endif + #endif +#else // ifdef __FM_MODULE + OOFEM_ERROR("Fluid module missing\n"); +#endif// ifdef __FM_MODULE + + // ******************* //computeNumericStiffnessMatrix(answer, rMode, tStep); } void -tet21ghostsolid :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) +tet21ghostsolid::computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) { // Compute displacements used to compute J @@ -627,10 +635,10 @@ tet21ghostsolid :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharTyp u.beSubArrayOf(a, ghostdisplacement_ordering); u_prev.beSubArrayOf(a_prev, ghostdisplacement_ordering); - for ( auto &gp : *this->integrationRulesArray [ 0 ] ) { + for ( auto &gp : * this->integrationRulesArray [ 0 ] ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); - double detJ = fabs( this->interpolation.giveTransformationJacobian( lcoords, FEIElementGeometryWrapper(this) ) ); + double detJ = fabs(this->interpolation.giveTransformationJacobian(lcoords, FEIElementGeometryWrapper(this) ) ); double dA = detJ * gp->giveWeight(); // Body load @@ -656,7 +664,7 @@ tet21ghostsolid :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharTyp gVector = temp; } - this->interpolation.evalN( N, lcoords, FEIElementGeometryWrapper(this) ); + this->interpolation.evalN(N, lcoords, FEIElementGeometryWrapper(this) ); for ( int j = 0; j < N.giveSize(); j++ ) { temparray(3 * j + 0) += N(j) * rho * gVector(0) * dA; @@ -666,8 +674,8 @@ tet21ghostsolid :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharTyp } // "load" from previous step - this->interpolation.evaldNdx( dNx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - this->interpolation_lin.evalN( N, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interpolation.evaldNdx(dNx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interpolation_lin.evalN(N, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); dNv.resize(30); for ( int k = 0; k < dNx.giveNumberOfRows(); k++ ) { @@ -699,7 +707,7 @@ tet21ghostsolid :: computeLoadVector(FloatArray &answer, BodyLoad *load, CharTyp } void -tet21ghostsolid :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) +tet21ghostsolid::giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { FloatArray a; this->computeVectorOf(VM_Total, tStep, a); @@ -707,7 +715,7 @@ tet21ghostsolid :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, } void -tet21ghostsolid :: giveInternalForcesVectorGivenSolution(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, FloatArray &a) +tet21ghostsolid::giveInternalForcesVectorGivenSolution(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, FloatArray &a) { #ifdef __FM_MODULE FluidDynamicMaterial *fluidMaterial = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); @@ -716,15 +724,15 @@ tet21ghostsolid :: giveInternalForcesVectorGivenSolution(FloatArray &answer, Tim FloatMatrix Kf, G, Kx, B, Ed, dNx; FloatArray Strain, Stress, Nlin, dNv, a_inc, a_prev, aVelocity, aPressure, aGhostDisplacement, aIncGhostDisplacement, fluidStress, epsf, dpdivv; FloatArray momentum, conservation, auxstress, divv; - double pressure, epsvol = 0.0; + double pressure; if ( !tStep->isTheFirstStep() ) { this->computeVectorOf(VM_Total, tStep->givePreviousStep(), a_prev); } else { - a_prev.resize( a.giveSize() ); + a_prev.resize(a.giveSize() ); a_prev.zero(); } - a_inc.operator = ( a - a_prev ); + a_inc.operator=(a - a_prev); aVelocity.beSubArrayOf(a, momentum_ordering); aPressure.beSubArrayOf(a, conservation_ordering); @@ -732,15 +740,15 @@ tet21ghostsolid :: giveInternalForcesVectorGivenSolution(FloatArray &answer, Tim aIncGhostDisplacement.beSubArrayOf(a_inc, ghostdisplacement_ordering); FloatArray aTotal; - aTotal.operator = ( aVelocity + aIncGhostDisplacement * VELOCITYCOEFF ); // Assume deltaT=1 gives that the increment is the velocity + aTotal.operator=(aVelocity + aIncGhostDisplacement * VELOCITYCOEFF); // Assume deltaT=1 gives that the increment is the velocity - for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { + for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); - double detJ = fabs( ( this->interpolation.giveTransformationJacobian( lcoords, FEIElementGeometryWrapper(this) ) ) ); + double detJ = fabs( ( this->interpolation.giveTransformationJacobian(lcoords, FEIElementGeometryWrapper(this) ) ) ); double weight = gp->giveWeight(); - this->interpolation.evaldNdx( dNx, lcoords, FEIElementGeometryWrapper(this) ); - this->interpolation_lin.evalN( Nlin, lcoords, FEIElementGeometryWrapper(this) ); + this->interpolation.evaldNdx(dNx, lcoords, FEIElementGeometryWrapper(this) ); + this->interpolation_lin.evalN(Nlin, lcoords, FEIElementGeometryWrapper(this) ); dNv.resize(30); for ( int k = 0; k < dNx.giveNumberOfRows(); k++ ) { @@ -759,7 +767,8 @@ tet21ghostsolid :: giveInternalForcesVectorGivenSolution(FloatArray &answer, Tim // Momentum equation gp->setMaterialMode(_3dFlow); #ifdef __FM_MODULE - fluidMaterial->computeDeviatoricStressVector(fluidStress, epsvol, gp, epsf, pressure, tStep); + auto val = fluidMaterial->computeDeviatoricStress3D(epsf, pressure, gp, tStep); + fluidStress = val.first; #else OOFEM_ERROR("Missing FM module"); #endif @@ -806,7 +815,8 @@ tet21ghostsolid :: giveInternalForcesVectorGivenSolution(FloatArray &answer, Tim gp->setMaterialMode(_3dFlow); #ifdef __FM_MODULE - fluidMaterial->computeDeviatoricStressVector(fluidCauchyArray, epsvol, gp, epsf, pressure, tStep); + auto val = fluidMaterial->computeDeviatoricStress3D(epsf, pressure, gp, tStep); + fluidCauchyArray = val.first; #else OOFEM_ERROR("Missing FM module"); #endif @@ -860,7 +870,7 @@ tet21ghostsolid :: giveInternalForcesVectorGivenSolution(FloatArray &answer, Tim } void -tet21ghostsolid :: giveInternalForcesVectorGivenSolutionDebug(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, FloatArray &a, bool ExtraLogging) +tet21ghostsolid::giveInternalForcesVectorGivenSolutionDebug(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, FloatArray &a, bool ExtraLogging) { #ifdef __FM_MODULE FluidDynamicMaterial *fluidMaterial = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial(); @@ -869,15 +879,15 @@ tet21ghostsolid :: giveInternalForcesVectorGivenSolutionDebug(FloatArray &answer FloatMatrix Kf, G, Kx, B, Ed, dNx; FloatArray Strain, Stress, Nlin, dNv, a_inc, a_prev, aVelocity, aPressure, aGhostDisplacement, aIncGhostDisplacement, fluidStress, epsf, dpdivv; FloatArray momentum, conservation, auxstress, divv; - double pressure, epsvol = 0.0; + double pressure; if ( !tStep->isTheFirstStep() ) { this->computeVectorOf(VM_Total, tStep->givePreviousStep(), a_prev); } else { - a_prev.resize( a.giveSize() ); + a_prev.resize(a.giveSize() ); a_prev.zero(); } - a_inc.operator = ( a - a_prev ); + a_inc.operator=(a - a_prev); aVelocity.beSubArrayOf(a, momentum_ordering); aPressure.beSubArrayOf(a, conservation_ordering); @@ -885,16 +895,16 @@ tet21ghostsolid :: giveInternalForcesVectorGivenSolutionDebug(FloatArray &answer aIncGhostDisplacement.beSubArrayOf(a_inc, ghostdisplacement_ordering); FloatArray aTotal; - aTotal.operator = ( aVelocity + aIncGhostDisplacement * VELOCITYCOEFF ); // Assume deltaT=1 gives that the increment is the velocity + aTotal.operator=(aVelocity + aIncGhostDisplacement * VELOCITYCOEFF); // Assume deltaT=1 gives that the increment is the velocity - for ( auto &gp : *this->giveDefaultIntegrationRulePtr() ) { + for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) { // gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0); const FloatArray &lcoords = gp->giveNaturalCoordinates(); - double detJ = fabs( ( this->interpolation.giveTransformationJacobian( lcoords, FEIElementGeometryWrapper(this) ) ) ); + double detJ = fabs( ( this->interpolation.giveTransformationJacobian(lcoords, FEIElementGeometryWrapper(this) ) ) ); double weight = gp->giveWeight(); - this->interpolation.evaldNdx( dNx, lcoords, FEIElementGeometryWrapper(this) ); - this->interpolation_lin.evalN( Nlin, lcoords, FEIElementGeometryWrapper(this) ); + this->interpolation.evaldNdx(dNx, lcoords, FEIElementGeometryWrapper(this) ); + this->interpolation_lin.evalN(Nlin, lcoords, FEIElementGeometryWrapper(this) ); dNv.resize(30); for ( int k = 0; k < dNx.giveNumberOfRows(); k++ ) { @@ -916,7 +926,8 @@ tet21ghostsolid :: giveInternalForcesVectorGivenSolutionDebug(FloatArray &answer // Momentum equation gp->setMaterialMode(_3dFlow); #ifdef __FM_MODULE - fluidMaterial->computeDeviatoricStressVector(fluidStress, epsvol, gp, epsf, pressure, tStep); + auto val = fluidMaterial->computeDeviatoricStress3D(epsf, pressure, gp, tStep); + fluidStress = val.first; #else OOFEM_ERROR("Missing FM module"); #endif @@ -974,7 +985,8 @@ tet21ghostsolid :: giveInternalForcesVectorGivenSolutionDebug(FloatArray &answer gp->setMaterialMode(_3dFlow); #ifdef __FM_MODULE - fluidMaterial->computeDeviatoricStressVector(fluidCauchy, epsvol, gp, epsf, pressure, tStep); + auto val = fluidMaterial->computeDeviatoricStress3D(epsf, pressure, gp, tStep); + fluidCauchy = val.first; #else OOFEM_ERROR("Missing FM module"); #endif @@ -1034,7 +1046,7 @@ tet21ghostsolid :: giveInternalForcesVectorGivenSolutionDebug(FloatArray &answer } // **************** DEBUG void -tet21ghostsolid :: giveDofManDofIDMask(int inode, IntArray &answer) const +tet21ghostsolid::giveDofManDofIDMask(int inode, IntArray &answer) const { // Returns the mask for node number inode of this element. @@ -1050,14 +1062,14 @@ tet21ghostsolid :: giveDofManDofIDMask(int inode, IntArray &answer) const } void -tet21ghostsolid :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +tet21ghostsolid::computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) // Returns the [6x30] strain-displacement matrix {B} of the receiver, eva- // luated at gp. // B matrix - 6 rows : epsilon-X, epsilon-Y, epsilon-Z, gamma-YZ, gamma-ZX, gamma-XY : { FloatMatrix dnx; - this->interpolation.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interpolation.evaldNdx(dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.resize(6, 30); answer.zero(); @@ -1079,7 +1091,7 @@ tet21ghostsolid :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, } void -tet21ghostsolid :: computeDeformationGradientVectorAt(FloatArray &answer, FloatArray lcoord, TimeStep *tStep) +tet21ghostsolid::computeDeformationGradientVectorAt(FloatArray &answer, FloatArray lcoord, TimeStep *tStep) { FloatArray F, u; FloatMatrix dNdx, BH, Fmatrix, Finv; @@ -1089,7 +1101,7 @@ tet21ghostsolid :: computeDeformationGradientVectorAt(FloatArray &answer, FloatA this->computeVectorOf({ 1, 2, 3 }, VM_Total, tStep, u); // Compute dNdx in point - interpolation->evaldNdx( dNdx, lcoord, FEIElementGeometryWrapper(this) ); + interpolation->evaldNdx(dNdx, lcoord, FEIElementGeometryWrapper(this) ); // Compute displacement gradient BH BH.resize(9, dNdx.giveNumberOfRows() * 3); @@ -1117,11 +1129,11 @@ tet21ghostsolid :: computeDeformationGradientVectorAt(FloatArray &answer, FloatA } void -tet21ghostsolid :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) +tet21ghostsolid::computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) { FloatMatrix dnx; - this->interpolation.evaldNdx( dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interpolation.evaldNdx(dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.resize(9, 30); answer.zero(); @@ -1140,7 +1152,7 @@ tet21ghostsolid :: computeBHmatrixAt(GaussPoint *gp, FloatMatrix &answer) } void -tet21ghostsolid :: giveUnknownData(FloatArray &u_prev, FloatArray &u, FloatArray &inc, TimeStep *tStep) +tet21ghostsolid::giveUnknownData(FloatArray &u_prev, FloatArray &u, FloatArray &inc, TimeStep *tStep) { this->computeVectorOf(VM_Total, tStep, u); @@ -1148,14 +1160,14 @@ tet21ghostsolid :: giveUnknownData(FloatArray &u_prev, FloatArray &u, FloatArray this->computeVectorOf(VM_Total, tStep->givePreviousStep(), u_prev); this->computeVectorOf(VM_Incremental, tStep, inc); } else { - inc.resize( u.giveSize() ); + inc.resize(u.giveSize() ); inc.zero(); - u_prev.operator = ( inc ); + u_prev.operator=(inc); } } void -tet21ghostsolid :: computeDeformationGradientVectorFromDispl(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, FloatArray &u) +tet21ghostsolid::computeDeformationGradientVectorFromDispl(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, FloatArray &u) { // Computes the deformation gradient in the Voigt format at the Gauss point gp of // the receiver at time step tStep. @@ -1183,12 +1195,12 @@ tet21ghostsolid :: computeDeformationGradientVectorFromDispl(FloatArray &answer, } else if ( matMode == _1dMat ) { answer.at(1) += 1.0; } else { - OOFEM_ERROR( "MaterialMode is not supported yet (%s)", __MaterialModeToString(matMode) ); + OOFEM_ERROR("MaterialMode is not supported yet (%s)", __MaterialModeToString(matMode) ); } } void -tet21ghostsolid :: computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +tet21ghostsolid::computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { FloatArray u; this->computeVectorOf({ 1, 2, 3 }, VM_Total, tStep, u); @@ -1196,10 +1208,10 @@ tet21ghostsolid :: computeDeformationGradientVector(FloatArray &answer, GaussPoi } double -tet21ghostsolid :: computeVolumeAround(GaussPoint *gp) +tet21ghostsolid::computeVolumeAround(GaussPoint *gp) // Returns the portion of the receiver which is attached to gp. { - double determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double determinant = fabs(this->interpolation.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); double weight = gp->giveWeight(); return ( this->computeVolume() ); @@ -1208,14 +1220,14 @@ tet21ghostsolid :: computeVolumeAround(GaussPoint *gp) int -tet21ghostsolid :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +tet21ghostsolid::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { if ( type == IST_Velocity ) { FloatArray N, a; FloatMatrix Nmat; this->computeVectorOf({ V_u, V_v, V_w }, VM_Total, tStep, a); - this->interpolation.evalN( N, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interpolation.evalN(N, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); Nmat.resize(3, N.giveSize() * 3); for ( int i = 1; i <= N.giveSize(); i++ ) { @@ -1230,7 +1242,7 @@ tet21ghostsolid :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalState FloatArray N, a; this->computeVectorOf({ P_f }, VM_Total, tStep, a); - this->interpolation_lin.evalN( N, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interpolation_lin.evalN(N, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.resize(1); answer.at(1) = N.dotProduct(a); @@ -1238,14 +1250,14 @@ tet21ghostsolid :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalState } else { MaterialMode matmode = gp->giveMaterialMode(); gp->setMaterialMode(_3dFlow); - int r = StructuralElement :: giveIPValue(answer, gp, type, tStep); + int r = StructuralElement::giveIPValue(answer, gp, type, tStep); gp->setMaterialMode(matmode); return r; } } bool -tet21ghostsolid :: giveRowTransformationMatrix(TimeStep *tStep) +tet21ghostsolid::giveRowTransformationMatrix(TimeStep *tStep) { // Create a transformation matrix that switch all rows/equations located in OmegaF but not on GammaInt, i.e where we do not have a no slip condition @@ -1274,7 +1286,7 @@ tet21ghostsolid :: giveRowTransformationMatrix(TimeStep *tStep) row2 = m; if ( DofIDs.at(j) == V_u || DofIDs.at(j) == V_v || DofIDs.at(j) == V_w ) { - bool doSwitch = !this->giveDofManager(i)->giveDofWithID( DofIDs.at(j) )->hasBc(tStep); + bool doSwitch = !this->giveDofManager(i)->giveDofWithID(DofIDs.at(j) )->hasBc(tStep); if ( doSwitch ) { // Boundary condition not set, make switch row1 = m; @@ -1287,9 +1299,9 @@ tet21ghostsolid :: giveRowTransformationMatrix(TimeStep *tStep) } } row1List.resizeWithValues(row1List.giveSize() + 1); - row1List.at( row1List.giveSize() ) = row1; + row1List.at(row1List.giveSize() ) = row1; row2List.resizeWithValues(row2List.giveSize() + 1); - row2List.at( row2List.giveSize() ) = row2; + row2List.at(row2List.giveSize() ) = row2; } } m++; @@ -1301,11 +1313,11 @@ tet21ghostsolid :: giveRowTransformationMatrix(TimeStep *tStep) // Create tranformation matrix by switching rows for ( int i = 1; i <= row1List.giveSize(); i++ ) { - Itransform.at( row1List.at(i), row1List.at(i) ) = 0; - Itransform.at( row2List.at(i), row2List.at(i) ) = 0; + Itransform.at(row1List.at(i), row1List.at(i) ) = 0; + Itransform.at(row2List.at(i), row2List.at(i) ) = 0; - Itransform.at( row1List.at(i), row2List.at(i) ) = 1; - Itransform.at( row2List.at(i), row1List.at(i) ) = 1; + Itransform.at(row1List.at(i), row2List.at(i) ) = 1; + Itransform.at(row2List.at(i), row1List.at(i) ) = 1; } computeItransform = false; @@ -1315,30 +1327,30 @@ tet21ghostsolid :: giveRowTransformationMatrix(TimeStep *tStep) // Some extension Interfaces to follow: -Interface *tet21ghostsolid :: giveInterface(InterfaceType it) +Interface *tet21ghostsolid::giveInterface(InterfaceType it) { switch ( it ) { case NodalAveragingRecoveryModelInterfaceType: - return static_cast< NodalAveragingRecoveryModelInterface * >(this); + return static_cast< NodalAveragingRecoveryModelInterface * >( this ); case SpatialLocalizerInterfaceType: - return static_cast< SpatialLocalizerInterface * >(this); + return static_cast< SpatialLocalizerInterface * >( this ); case EIPrimaryUnknownMapperInterfaceType: - return static_cast< EIPrimaryUnknownMapperInterface * >(this); + return static_cast< EIPrimaryUnknownMapperInterface * >( this ); default: - return StructuralElement :: giveInterface(it); + return StructuralElement::giveInterface(it); //return FMElement :: giveInterface(it); } } -void tet21ghostsolid :: EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(ValueModeType mode, - TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) +void tet21ghostsolid::EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(ValueModeType mode, + TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) { FloatArray n, n_lin; - this->interpolation.evalN( n, lcoords, FEIElementGeometryWrapper(this) ); - this->interpolation_lin.evalN( n_lin, lcoords, FEIElementGeometryWrapper(this) ); + this->interpolation.evalN(n, lcoords, FEIElementGeometryWrapper(this) ); + this->interpolation_lin.evalN(n_lin, lcoords, FEIElementGeometryWrapper(this) ); answer.resize(4); answer.zero(); for ( int i = 1; i <= n.giveSize(); i++ ) { @@ -1353,18 +1365,17 @@ void tet21ghostsolid :: EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(Va } void -tet21ghostsolid :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) +tet21ghostsolid::NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) { if ( type == IST_Pressure ) { answer.resize(1); if ( node <= 4 ) { answer.at(1) = this->giveNode(node)->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep); } else { - IntArray eNodes; - this->interpolation.computeLocalEdgeMapping(eNodes, node - 4); + const auto &eNodes = this->interpolation.computeLocalEdgeMapping(node - 4); answer.at(1) = 0.5 * ( - this->giveNode( eNodes.at(1) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) + - this->giveNode( eNodes.at(2) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) ); + this->giveNode(eNodes.at(1) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) + + this->giveNode(eNodes.at(2) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) ); } } else { answer.clear(); @@ -1372,7 +1383,7 @@ tet21ghostsolid :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer } void -tet21ghostsolid :: computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global) +tet21ghostsolid::computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global) { answer.clear(); if ( type != ExternalForcesVector ) { @@ -1390,17 +1401,17 @@ tet21ghostsolid :: computeBoundarySurfaceLoadVector(FloatArray &answer, Boundary int nsd = fei->giveNsd(); f.zero(); - IntegrationRule *iRule = fei->giveBoundaryIntegrationRule(load->giveApproxOrder(), boundary); + auto iRule = fei->giveBoundaryIntegrationRule(load->giveApproxOrder(), boundary); - for ( GaussPoint *gp : *iRule ) { + for ( auto &gp : * iRule ) { FloatArray lcoords = gp->giveNaturalCoordinates(); - if ( load->giveFormulationType() == Load :: FT_Entity ) { + if ( load->giveFormulationType() == Load::FT_Entity ) { load->computeValueAt(force, tStep, lcoords, mode); } else { FloatArray gcoords, elcoords; - this->interpolation.surfaceLocal2global( gcoords, boundary, lcoords, FEIElementGeometryWrapper(this) ); - this->interpolation.global2local( elcoords, gcoords, FEIElementGeometryWrapper(this) ); - NeumannMomentLoad *thisLoad = dynamic_cast< NeumannMomentLoad * >(load); + this->interpolation.surfaceLocal2global(gcoords, boundary, lcoords, FEIElementGeometryWrapper(this) ); + this->interpolation.global2local(elcoords, gcoords, FEIElementGeometryWrapper(this) ); + NeumannMomentLoad *thisLoad = dynamic_cast< NeumannMomentLoad * >( load ); if ( thisLoad != NULL ) { FloatArray temp; thisLoad->computeValueAtBoundary(temp, tStep, gcoords, VM_Total, this, boundary); @@ -1422,7 +1433,7 @@ tet21ghostsolid :: computeBoundarySurfaceLoadVector(FloatArray &answer, Boundary ///@todo Make sure this part is correct. // We always want the global values in the end, so we might as well compute them here directly: // transform force - if ( load->giveCoordSystMode() == Load :: CST_Global ) { + if ( load->giveCoordSystMode() == Load::CST_Global ) { // then just keep it in global c.s } else { ///@todo Support this... @@ -1437,12 +1448,12 @@ tet21ghostsolid :: computeBoundarySurfaceLoadVector(FloatArray &answer, Boundary } // Construct n-matrix - fei->boundaryEvalN( n_vec, boundary, lcoords, FEIElementGeometryWrapper(this) ); + fei->boundaryEvalN(n_vec, boundary, lcoords, FEIElementGeometryWrapper(this) ); n.beNMatrixOf(n_vec, nsd); ///@todo Some way to ask for the thickness at a global coordinate maybe? double thickness = 1.0; // Should be the circumference for axisymm-elements. - double dV = thickness * gp->giveWeight() * fei->boundaryGiveTransformationJacobian( boundary, lcoords, FEIElementGeometryWrapper(this) ); + double dV = thickness * gp->giveWeight() * fei->boundaryGiveTransformationJacobian(boundary, lcoords, FEIElementGeometryWrapper(this) ); f.plusProduct(n, force, dV); } @@ -1452,7 +1463,5 @@ tet21ghostsolid :: computeBoundarySurfaceLoadVector(FloatArray &answer, Boundary answer.resize(39); answer.zero(); answer.assemble(f, this->velocitydofsonside); - - delete iRule; } } diff --git a/src/sm/Elements/tet21ghostsolid.h b/src/sm/Elements/tet21ghostsolid.h index 935a0a689..be9e2fc52 100644 --- a/src/sm/Elements/tet21ghostsolid.h +++ b/src/sm/Elements/tet21ghostsolid.h @@ -35,7 +35,7 @@ #ifndef TET21GHOSTSOLID_H #define TET21GHOSTSOLID_H -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/nlstructuralelement.h" #include "floatmatrix.h" #include "nodalaveragingrecoverymodel.h" #include "spatiallocalizer.h" @@ -64,50 +64,50 @@ class tet21ghostsolid : public NLStructuralElement, public: tet21ghostsolid(int n, Domain *d); - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; - - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual const char *giveInputRecordName() const { return _IFT_tet21ghostsolid_Name; } - virtual int computeNumberOfDofs() { return 70; } - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual MaterialMode giveMaterialMode() { return _3dMat; } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; + + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + const char *giveInputRecordName() const override { return _IFT_tet21ghostsolid_Name; } + int computeNumberOfDofs() override { return 70; } + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + MaterialMode giveMaterialMode() override { return _3dMat; } + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; virtual void computeNumericStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); - virtual void giveInternalForcesVectorGivenSolution(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, FloatArray &SolutionVector); - virtual void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); - virtual void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; + void giveInternalForcesVectorGivenSolution(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, FloatArray &SolutionVector); + void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; + void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global = true) override; - virtual void computeDeformationGradientVectorFromDispl(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, FloatArray &u); - virtual void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); - virtual void computeDeformationGradientVectorAt(FloatArray &answer, FloatArray lcoord, TimeStep *tStep); + void computeDeformationGradientVectorFromDispl(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, FloatArray &u); + void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; + void computeDeformationGradientVectorAt(FloatArray &answer, FloatArray lcoord, TimeStep *tStep); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual double computeVolumeAround(GaussPoint *gp); - virtual bool giveRowTransformationMatrix(TimeStep *tStep); - virtual const char *giveClassName() const { return "tet21ghostsolid"; } + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + double computeVolumeAround(GaussPoint *gp) override; + bool giveRowTransformationMatrix(TimeStep *tStep); + const char *giveClassName() const override { return "tet21ghostsolid"; } - virtual void computeNumericStiffnessMatrixDebug(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - virtual void giveInternalForcesVectorGivenSolutionDebug(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, FloatArray &SolutionVector, bool ExtraLogging); + void computeNumericStiffnessMatrixDebug(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); + void giveInternalForcesVectorGivenSolutionDebug(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, FloatArray &SolutionVector, bool ExtraLogging); - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; // Element interpolation interface: - virtual void EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(ValueModeType u, - TimeStep *tStep, const FloatArray &coords, FloatArray &answer); + void EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(ValueModeType u, TimeStep *tStep, const FloatArray &coords, FloatArray &answer) override; // Nodal averaging interface: - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; protected: static FEI3dTetQuad interpolation; static FEI3dTetLin interpolation_lin; - virtual void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS); - virtual void computeBHmatrixAt(GaussPoint *, FloatMatrix &); - virtual void computeGaussPoints(); + void computeBmatrixAt(GaussPoint *, FloatMatrix &, int = 1, int = ALL_STRAINS) override; + void computeBHmatrixAt(GaussPoint *, FloatMatrix &) override; + void computeGaussPoints() override; /// Ordering of momentum balance equations in element. Used to assemble the element stiffness static IntArray momentum_ordering; diff --git a/src/sm/Elements/tria1platesubsoil.C b/src/sm/Elements/tria1platesubsoil.C index f0eab3aab..7886cf120 100644 --- a/src/sm/Elements/tria1platesubsoil.C +++ b/src/sm/Elements/tria1platesubsoil.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Elements/tria1platesubsoil.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Elements/tria1platesubsoil.h" +#include "sm/Materials/structuralms.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "fei2dtrlin.h" #include "node.h" #include "material.h" @@ -79,7 +79,7 @@ Tria1PlateSubSoil :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 5) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 5); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } @@ -118,22 +118,22 @@ Tria1PlateSubSoil :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int l void Tria1PlateSubSoil :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveGeneralizedStress_PlateSubSoil(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveGeneralizedStress_PlateSubSoil(strain, gp, tStep); } void Tria1PlateSubSoil :: computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->give2dPlateSubSoilStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveStructuralCrossSection()->give2dPlateSubSoilStiffMtrx(rMode, gp, tStep); } -IRResultType -Tria1PlateSubSoil :: initializeFrom(InputRecord *ir) +void +Tria1PlateSubSoil :: initializeFrom(InputRecord &ir) { this->numberOfGaussPoints = 1; - return StructuralElement :: initializeFrom(ir); + StructuralElement :: initializeFrom(ir); } @@ -148,8 +148,8 @@ void Tria1PlateSubSoil :: computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) { FloatArray u, v; - u.beDifferenceOf( * this->giveNode(2)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); - v.beDifferenceOf( * this->giveNode(3)->giveCoordinates(), * this->giveNode(1)->giveCoordinates() ); + u.beDifferenceOf( this->giveNode(2)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); + v.beDifferenceOf( this->giveNode(3)->giveCoordinates(), this->giveNode(1)->giveCoordinates() ); answer.beVectorProductOf(u, v); answer.normalize(); @@ -232,48 +232,53 @@ Tria1PlateSubSoil :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &a } } - void -Tria1PlateSubSoil :: computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *sgp) +Tria1PlateSubSoil ::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +// Returns the [1x3] displacement interpolation matrix {N} { - this->computeNmatrixAt(sgp->giveNaturalCoordinates(), answer); + FloatArray N(3); + giveInterpolation()->evalN(N, iLocCoord, FEIElementGeometryWrapper(this) ); + answer.beNMatrixOf(N, 1); } + void -Tria1PlateSubSoil :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +Tria1PlateSubSoil :: computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) { - answer.resize(3); - answer.zero(); - if ( iSurf == 1 ) { - for (int i = 1; i<=3; i++) { - answer.at(i) = i; - } + if (boundaryID == 1) { + this->computeNmatrixAt(lcoords, answer); } else { - OOFEM_ERROR("wrong surface number"); + OOFEM_ERROR("computeSurfaceNMatrix: Only one surface is supported with id=1"); } } -IntegrationRule * -Tria1PlateSubSoil :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, approxOrder); - iRule->SetUpPointsOnTriangle(npoints, _Unknown); - return iRule; -} - -double -Tria1PlateSubSoil :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) -{ - return this->computeVolumeAround(gp); -} - - -int -Tria1PlateSubSoil :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) -{ - return 0; -} +// void +// Tria1PlateSubSoil :: giveSurfaceDofMapping(IntArray &answer, int iSurf) const +// { +// answer.resize(3); +// answer.zero(); +// if ( iSurf == 1 ) { +// for (int i = 1; i<=3; i++) { +// answer.at(i) = i; +// } +// } else { +// OOFEM_ERROR("wrong surface number"); +// } +// } +// +// +// double +// Tria1PlateSubSoil :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) +// { +// return this->computeVolumeAround(gp); +// } +// +// +// int +// Tria1PlateSubSoil :: computeLoadLSToLRotationMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp) +// { +// return 0; +// } } // end namespace oofem diff --git a/src/sm/Elements/tria1platesubsoil.h b/src/sm/Elements/tria1platesubsoil.h index 6aa86e676..18d516c71 100644 --- a/src/sm/Elements/tria1platesubsoil.h +++ b/src/sm/Elements/tria1platesubsoil.h @@ -35,7 +35,7 @@ #ifndef tria1platesubsoil_H #define tria1platesubsoil_H -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -65,53 +65,55 @@ public SPRNodalRecoveryModelInterface Tria1PlateSubSoil(int n, Domain * d); virtual ~Tria1PlateSubSoil() { } - virtual FEInterpolation *giveInterpolation() const; - virtual FEInterpolation *giveInterpolation(DofIDItem id) const; + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; - virtual MaterialMode giveMaterialMode() { return _2dPlateSubSoil; } - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } + MaterialMode giveMaterialMode() override { return _2dPlateSubSoil; } + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Tria1PlateSubSoil_Name; } - virtual const char *giveClassName() const { return "Tria1PlateSubSoil"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_Tria1PlateSubSoil_Name; } + const char *giveClassName() const override { return "Tria1PlateSubSoil"; } + void initializeFrom(InputRecord &ir) override; - virtual int computeNumberOfDofs() { return 3; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; + int computeNumberOfDofs() override { return 3; } + void giveDofManDofIDMask(int inode, IntArray &) const override; - virtual void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp); + void computeMidPlaneNormal(FloatArray &answer, const GaussPoint *gp) override; - virtual double giveCharacteristicLength(const FloatArray &normalToCrackPlane); - virtual double computeVolumeAround(GaussPoint *gp); + double giveCharacteristicLength(const FloatArray &normalToCrackPlane) override; + double computeVolumeAround(GaussPoint *gp) override; - virtual void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep); - virtual void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) + void computeLumpedMassMatrix(FloatMatrix &answer, TimeStep *tStep) override; + void computeMassMatrix(FloatMatrix &answer, TimeStep *tStep) override { computeLumpedMassMatrix(answer, tStep); } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual Interface *giveInterface(InterfaceType it); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + Interface *giveInterface(InterfaceType it) override; protected: - virtual void computeGaussPoints(); - virtual void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS); + void computeGaussPoints() override; + void computeBodyLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP() { return this->numberOfGaussPoints; } - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType() { return SPRPatchType_2dxy; } + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override { return this->numberOfGaussPoints; } + SPRPatchType SPRNodalRecoveryMI_givePatchType() override { return SPRPatchType_2dxy; } /** * @name Surface load support */ + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) override; + //@{ - virtual void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); - virtual void giveSurfaceDofMapping(IntArray &answer, int iSurf) const; - virtual IntegrationRule *GetSurfaceIntegrationRule(int iSurf); - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf); - virtual int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp); + //void computeSurfaceNMatrixAt(FloatMatrix &answer, int iSurf, GaussPoint *gp); + //void giveSurfaceDofMapping(IntArray &answer, int iSurf) const override; + //double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) override; + //int computeLoadLSToLRotationMatrix(FloatMatrix &answer, int iSurf, GaussPoint *gp) override; //@} }; } // end namespace oofem diff --git a/src/sm/Elements/tria2platesubsoil.C b/src/sm/Elements/tria2platesubsoil.C new file mode 100644 index 000000000..ba189e007 --- /dev/null +++ b/src/sm/Elements/tria2platesubsoil.C @@ -0,0 +1,166 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2014 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Elements/tria2platesubsoil.h" +#include "fei2dtrquad.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Element(Tria2PlateSubSoil); + +FEI2dTrQuad Tria2PlateSubSoil :: interp_quad(1, 2); + +Tria2PlateSubSoil :: Tria2PlateSubSoil(int n, Domain *aDomain) : + Tria1PlateSubSoil(n, aDomain) +{ + numberOfGaussPoints = 4; + numberOfDofMans = 6; +} + + +FEInterpolation * +Tria2PlateSubSoil :: giveInterpolation(DofIDItem id) const +{ + return & interp_quad; +} + + +FEInterpolation * +Tria2PlateSubSoil :: giveInterpolation() const { return & interp_quad; } + + +void +Tria2PlateSubSoil :: computeGaussPoints() +// Sets up the array containing the four Gauss points of the receiver. +{ + if ( integrationRulesArray.size() == 0 ) { + integrationRulesArray.resize( 1 ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 5); + this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); + } +} + + + +void +Tria2PlateSubSoil :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) +// Returns the [3x6] strain-displacement matrix {B} of the receiver, +// evaluated at gp. +{ + FloatArray n; + FloatMatrix dn; + + this->interp_quad.evaldNdx( dn, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + this->interp_quad.evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); + + answer.resize(3, 6); + answer.zero(); + + ///@todo Check sign here + for ( int i = 0; i < 6; ++i ) { + answer(0, i) = n(i); // eps_z + answer(1, i) = dn(i, 0); // gamma_xz + answer(2, i) = dn(i, 1); // gamma_yz + } +} + + + +void +Tria2PlateSubSoil :: initializeFrom(InputRecord &ir) +{ + StructuralElement :: initializeFrom(ir); +} + +//TODO ZZNodalRecoveryModel can not determine some values. This is caused by sum of row entries is zero for (N^T)N matrix for vertices, yielding zero entries in the lumped form. + +void +Tria2PlateSubSoil :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) +{ + pap.resize(3); + pap.at(1) = this->giveNode(1)->giveNumber(); + pap.at(2) = this->giveNode(2)->giveNumber(); + pap.at(3) = this->giveNode(3)->giveNumber(); +} + +void +Tria2PlateSubSoil :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) +{ + answer.resize(3); + if ( pap == this->giveNode(1)->giveNumber() ) { + answer.at(1) = pap; + answer.at(2) = this->giveNode(4)->giveNumber(); + answer.at(3) = this->giveNode(6)->giveNumber(); + } else if ( pap == this->giveNode(2)->giveNumber() ) { + answer.at(1) = pap; + answer.at(2) = this->giveNode(5)->giveNumber(); + answer.at(3) = this->giveNode(4)->giveNumber(); + } else if ( pap == this->giveNode(3)->giveNumber() ) { + answer.at(1) = pap; + answer.at(2) = this->giveNode(6)->giveNumber(); + answer.at(3) = this->giveNode(5)->giveNumber(); + } else { + OOFEM_ERROR("node unknown"); + } +} + +SPRPatchType +Tria2PlateSubSoil :: SPRNodalRecoveryMI_givePatchType() +{ + return SPRPatchType_2dquadratic; +} + +void +Tria2PlateSubSoil ::computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) +// Returns the [1x6] displacement interpolation matrix {N} +{ + FloatArray N(6); + giveInterpolation()->evalN(N, iLocCoord, FEIElementGeometryWrapper(this) ); + answer.beNMatrixOf(N, 1); +} + +void +Tria2PlateSubSoil :: computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) +{ + if (boundaryID == 1) { + this->computeNmatrixAt(lcoords, answer); + } else { + OOFEM_ERROR("computeSurfaceNMatrix: Only one surface is supported with id=1"); + } +} + +} // end namespace oofem diff --git a/src/sm/Elements/tria2platesubsoil.h b/src/sm/Elements/tria2platesubsoil.h new file mode 100644 index 000000000..b153bc523 --- /dev/null +++ b/src/sm/Elements/tria2platesubsoil.h @@ -0,0 +1,90 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2014 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef tria2platesubsoil_H +#define tria2platesubsoil_H + +#include "sm/Elements/tria1platesubsoil.h" + +#define _IFT_Tria2PlateSubSoil_Name "tria2platesubsoil" + +namespace oofem { +class FEI2dTrQuad; + +/** + * This class implements an triangular six-node plate subsoil element with quadratic interpolation in xy plane. + * Each node has 1 degree of freedom (out-of-plane displacement). + * + * Loading types supported; + * + * Reference: + * Bittnar, Sejnoha: Numerical Methods in Structural Mechanics, Thomas Telford, Jan 1, 1996, ISBN-13: 978-0784401705 + * @author Borek Patzak + */ +class Tria2PlateSubSoil : public Tria1PlateSubSoil +{ +protected: + static FEI2dTrQuad interp_quad; + +public: + Tria2PlateSubSoil(int n, Domain * d); + virtual ~Tria2PlateSubSoil() { } + + FEInterpolation *giveInterpolation() const override; + FEInterpolation *giveInterpolation(DofIDItem id) const override; + + // definition & identification + const char *giveInputRecordName() const override { return _IFT_Tria2PlateSubSoil_Name; } + const char *giveClassName() const override { return "Tria2PlateSubSoil"; } + void initializeFrom(InputRecord &ir) override; + + int computeNumberOfDofs() override { return 6; } + + +protected: + void computeGaussPoints() override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int = 1, int = ALL_STRAINS) override; + + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; + + /** + * @name Surface load support + */ + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeSurfaceNMatrix(FloatMatrix &answer, int boundaryID, const FloatArray &lcoords) override; +}; +} // end namespace oofem +#endif // tria2platesubsoil_H diff --git a/src/sm/Elements/trwarp.C b/src/sm/Elements/trwarp.C index f65f8481a..d793f9f00 100644 --- a/src/sm/Elements/trwarp.C +++ b/src/sm/Elements/trwarp.C @@ -33,20 +33,20 @@ #include "trwarp.h" #include "node.h" -#include "CrossSections/warpingcrosssection.h" +#include "sm/CrossSections/warpingcrosssection.h" #include "gausspoint.h" #include "gaussintegrationrule.h" #include "floatmatrix.h" #include "floatarray.h" #include "intarray.h" #include "mathfem.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "classfactory.h" #include "load.h" -#include "EngineeringModels/freewarping.h" +#include "sm/EngineeringModels/freewarping.h" #include "engngm.h" #include "dof.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" @@ -73,39 +73,38 @@ Tr_Warp :: giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueMode // { if ( mtrx == ExternalForcesVector ) { - // include implicit edge contribution - this->computeEdgeLoadVectorAt(answer, NULL, tStep, mode); + // include implicit edge contribution + this->computeEdgeLoadVectorAt(answer, NULL, tStep, mode); } else { - StructuralElement::giveCharacteristicVector(answer, mtrx, mode, tStep); + StructuralElement::giveCharacteristicVector(answer, mtrx, mode, tStep); } } - void Tr_Warp :: computeGaussPoints() // Sets up the array containing the Gauss point of the receiver. { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize(1); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 4) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 4); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } -IRResultType -Tr_Warp :: initializeFrom(InputRecord *ir) +void +Tr_Warp :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 1; - return StructuralElement :: initializeFrom(ir); + StructuralElement :: initializeFrom(ir); } void Tr_Warp :: computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - this->giveStructuralCrossSection()->giveRealStress_Warping(answer, gp, strain, tStep); + answer = this->giveStructuralCrossSection()->giveRealStress_Warping(strain, gp, tStep); } @@ -142,7 +141,7 @@ Tr_Warp :: computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, this->interp.evaldNdx( dN, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); // gausspoint coordinates FloatArray gcoords; - Element *elem = gp->giveElement(); + Element *elem = gp->giveElement(); ///@todo Why?! Is this really called *not* by this elements own GP?!?!?! If so, ouch! / Mikael elem->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); this->transformCoordinates( tc, gcoords, this->giveCrossSection()->giveNumber() ); @@ -239,17 +238,17 @@ Tr_Warp :: computeEdgeLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tSt this->giveEdgeDofMapping(mask, iEdge); // coordinates of the initial and final node of the edge - FloatArray *coord1 = giveNode( mask.at(1) )->giveCoordinates(); - FloatArray *coord2 = giveNode( mask.at(2) )->giveCoordinates(); + const auto &coord1 = giveNode( mask.at(1) )->giveCoordinates(); + const auto &coord2 = giveNode( mask.at(2) )->giveCoordinates(); // components of the edge vector (from the initial to the final node) - double dx = coord2->at(1) - coord1->at(1); - double dy = coord2->at(2) - coord1->at(2); + double dx = coord2.at(1) - coord1.at(1); + double dy = coord2.at(2) - coord1.at(2); // coordinates of the initial node - double x1 = coord1->at(1); - double y1 = coord1->at(2); + double x1 = coord1.at(1); + double y1 = coord1.at(2); // coordinates of the final node - double x2 = coord2->at(1); - double y2 = coord2->at(2); + double x2 = coord2.at(1); + double y2 = coord2.at(2); // transform to coordinates w.r. center of gravity FloatArray tc1(2), c1(2), tc2(2), c2(2); @@ -359,29 +358,26 @@ Tr_Warp :: ZZNodalRecoveryMI_computeNNMatrix(FloatArray &answer, InternalStateTy double volume = 0.0; FloatMatrix fullAnswer; FloatArray n; - Element *elem = this->ZZNodalRecoveryMI_giveElement(); - FEInterpolation *interpol = elem->giveInterpolation(); - IntegrationRule *iRule = elem->giveDefaultIntegrationRulePtr(); + FEInterpolation *interpol = this->giveInterpolation(); + IntegrationRule *iRule = this->giveDefaultIntegrationRulePtr(); if ( !interpol ) { - OOFEM_ERROR( "ZZNodalRecoveryMI_computeNNMatrix: Element %d not providing interpolation", elem->giveNumber() ); + OOFEM_ERROR( "ZZNodalRecoveryMI_computeNNMatrix: Element %d not providing interpolation", this->giveNumber() ); } - int size = 3; //elem->giveNumberOfDofManagers(); + int size = 3; //this->giveNumberOfDofManagers(); fullAnswer.resize(size, size); fullAnswer.zero(); double pok = 0.0; - for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) { - GaussPoint *gp = iRule->getIntegrationPoint(i); - double dV = elem->computeVolumeAround(gp); - interpol->evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(elem) ); + for ( auto &gp : *iRule ) { + double dV = this->computeVolumeAround(gp); + interpol->evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); fullAnswer.plusDyadSymmUpper(n, dV); pok += ( n.at(1) * dV ); ///@todo What is this? Completely unused. volume += dV; } - fullAnswer.symmetrized(); answer.resize(4); for ( int i = 1; i <= 3; i++ ) { @@ -402,20 +398,18 @@ Tr_Warp :: ZZNodalRecoveryMI_computeNValProduct(FloatMatrix &answer, InternalSta // N(nsigma, nsigma*nnodes) // Definition : sigmaVector = N * nodalSigmaVector FloatArray stressVector, n; - Element *elem = this->ZZNodalRecoveryMI_giveElement(); - FEInterpolation *interpol = elem->giveInterpolation(); - IntegrationRule *iRule = elem->giveDefaultIntegrationRulePtr(); + FEInterpolation *interpol = this->giveInterpolation(); + IntegrationRule *iRule = this->giveDefaultIntegrationRulePtr(); answer.clear(); - for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) { - GaussPoint *gp = iRule->getIntegrationPoint(i); - double dV = elem->computeVolumeAround(gp); + for ( auto &gp : *iRule ) { + double dV = this->computeVolumeAround(gp); //this-> computeStressVector(stressVector, gp, tStep); - if ( !elem->giveIPValue(stressVector, gp, type, tStep) ) { + if ( !this->giveIPValue(stressVector, gp, type, tStep) ) { continue; } - interpol->evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(elem) ); + interpol->evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); answer.plusDyadUnsym(n, stressVector, dV); // help.beTProductOf(n,stressVector); diff --git a/src/sm/Elements/trwarp.h b/src/sm/Elements/trwarp.h index 97ea1ff66..411006259 100644 --- a/src/sm/Elements/trwarp.h +++ b/src/sm/Elements/trwarp.h @@ -55,53 +55,50 @@ class Tr_Warp : public StructuralElement, public SpatialLocalizerInterface, publ public: Tr_Warp(int n, Domain *d); virtual ~Tr_Warp(); - virtual void computeFirstMomentOfArea(FloatArray &answer); - virtual double computeVolumeAround(GaussPoint *gp); - virtual void giveEdgeDofMapping(IntArray &answer, int iEdge) const; - virtual void computeEdgeLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); - virtual void giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, - TimeStep *tStep); + void computeFirstMomentOfArea(FloatArray &answer); + double computeVolumeAround(GaussPoint *gp) override; + void giveEdgeDofMapping(IntArray &answer, int iEdge) const override; + void computeEdgeLoadVectorAt(FloatArray &answer, Load *load, TimeStep *tStep, ValueModeType mode); + void giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, TimeStep *tStep) override; // definition - virtual const char *giveInputRecordName() const { return _IFT_Tr_Warp_Name; } - virtual const char *giveClassName() const { return "Tr_WarpElement"; } + const char *giveInputRecordName() const override { return _IFT_Tr_Warp_Name; } + const char *giveClassName() const override { return "Tr_WarpElement"; } - virtual int computeNumberOfDofs() { return 4; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode() { return _Warping; } - virtual double giveThicknessAt(const FloatArray &gcoords); - virtual void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer); - virtual void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui); - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + int computeNumberOfDofs() override { return 4; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _Warping; } + double giveThicknessAt(const FloatArray &gcoords); + void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override; + void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeNmatrixAt(const FloatArray &iLocCoord, FloatMatrix &answer) override; + void computeBmatrixAt(GaussPoint *gp, FloatMatrix &answer, int li, int ui) override; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual Interface *giveInterface(InterfaceType t); + Interface *giveInterface(InterfaceType t) override; - virtual void giveInternalDofManDofIDMask(int inode, IntArray &answer) const; - virtual DofManager *giveInternalDofManager(int i) const; + void giveInternalDofManDofIDMask(int inode, IntArray &answer) const override; + DofManager *giveInternalDofManager(int i) const override; - virtual int giveNumberOfInternalDofManagers() const { return 1; } + int giveNumberOfInternalDofManagers() const override { return 1; } - virtual Element *ZZNodalRecoveryMI_giveElement() { return this; } - virtual void ZZNodalRecoveryMI_computeNNMatrix(FloatArray &answer, InternalStateType type); - virtual bool ZZNodalRecoveryMI_computeNValProduct(FloatMatrix &answer, InternalStateType type, - TimeStep *tStep); - virtual int SpatialLocalizerI_containsPoint(const FloatArray &coords); + void ZZNodalRecoveryMI_computeNNMatrix(FloatArray &answer, InternalStateType type) override; + bool ZZNodalRecoveryMI_computeNValProduct(FloatMatrix &answer, InternalStateType type, TimeStep *tStep) override; + int SpatialLocalizerI_containsPoint(const FloatArray &coords) override; - virtual FEInterpolation *giveInterpolation() const { return & this->interp; } - virtual Element_Geometry_Type giveGeometryType() const { return EGT_triangle_1; } + FEInterpolation *giveInterpolation() const override { return & this->interp; } + Element_Geometry_Type giveGeometryType() const override { return EGT_triangle_1; } #ifdef __OOFEG // Graphics output - //void drawYourself(oofegGraphicContext&); - //virtual void drawRawGeometry(oofegGraphicContext&) {} - //virtual void drawDeformedGeometry(oofegGraphicContext&, UnknownType) {} + //void drawYourself(oofegGraphicContext&) override; + //void drawRawGeometry(oofegGraphicContext&) override {} + //void drawDeformedGeometry(oofegGraphicContext&, UnknownType) override {} #endif protected: - virtual void computeGaussPoints(); - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); + void computeGaussPoints() override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; void transformCoordinates(FloatArray &answer, FloatArray &c, const int CGnumber); - virtual void postInitialize(); + void postInitialize() override; }; } // end namespace oofem #endif // tr_warp_h diff --git a/src/sm/EngineeringModels/adaptlinearstatic.C b/src/sm/EngineeringModels/adaptlinearstatic.C index b1dafec4c..3467c4d39 100644 --- a/src/sm/EngineeringModels/adaptlinearstatic.C +++ b/src/sm/EngineeringModels/adaptlinearstatic.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/adaptlinearstatic.h" +#include "sm/EngineeringModels/adaptlinearstatic.h" #include "remeshingcrit.h" #include "mesherinterface.h" #include "errorestimator.h" @@ -128,21 +128,15 @@ AdaptiveLinearStatic :: initializeAdaptive(int tStepNumber) } -contextIOResultType AdaptiveLinearStatic :: restoreContext(DataStream *stream, ContextMode mode, void *obj) +void AdaptiveLinearStatic :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = LinearStatic :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + LinearStatic :: restoreContext(stream, mode); } -IRResultType -AdaptiveLinearStatic :: initializeFrom(InputRecord *ir) -// input from inputString +void +AdaptiveLinearStatic :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + LinearStatic :: initializeFrom(ir); int meshPackageId = 0; IR_GIVE_OPTIONAL_FIELD(ir, meshPackageId, _IFT_AdaptiveLinearStatic_meshpackage); @@ -154,8 +148,6 @@ AdaptiveLinearStatic :: initializeFrom(InputRecord *ir) } else { meshPackage = MPT_T3D; } - - return LinearStatic :: initializeFrom(ir); } diff --git a/src/sm/EngineeringModels/adaptlinearstatic.h b/src/sm/EngineeringModels/adaptlinearstatic.h index f30a319aa..f97f0152c 100644 --- a/src/sm/EngineeringModels/adaptlinearstatic.h +++ b/src/sm/EngineeringModels/adaptlinearstatic.h @@ -35,7 +35,7 @@ #ifndef adaptlinearstatic_h #define adaptlinearstatic_h -#include "../sm/EngineeringModels/linearstatic.h" +#include "sm/EngineeringModels/linearstatic.h" #include "meshpackagetype.h" ///@name Input fields for AdaptiveLinearStatic @@ -59,28 +59,28 @@ class AdaptiveLinearStatic : public LinearStatic MeshPackageType meshPackage; public: - AdaptiveLinearStatic(int i, EngngModel * _master = NULL) : LinearStatic(i, _master) { } + AdaptiveLinearStatic(int i, EngngModel *master = nullptr) : LinearStatic(i, master) { } virtual ~AdaptiveLinearStatic() { } - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; /** * Initializes the newly generated discretization state according to previous solution. * This process should typically include restoring old solution, instanciating newly * generated domain(s) and by mapping procedure. */ - virtual int initializeAdaptive(int tStepNumber); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + int initializeAdaptive(int tStepNumber) override; + void printOutputAt(FILE *file, TimeStep *tStep) override; - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void updateDomainLinks(); + void updateDomainLinks() override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; // identification - virtual const char *giveClassName() const { return "AdaptiveLinearStatic"; } - virtual const char *giveInputRecordName() const { return _IFT_AdaptiveLinearStatic_Name; } + const char *giveClassName() const override { return "AdaptiveLinearStatic"; } + const char *giveInputRecordName() const override { return _IFT_AdaptiveLinearStatic_Name; } }; } // end namespace oofem #endif // adaptlinearstatic_h diff --git a/src/sm/EngineeringModels/adaptnlinearstatic.C b/src/sm/EngineeringModels/adaptnlinearstatic.C index 591b69e61..f709ddf76 100644 --- a/src/sm/EngineeringModels/adaptnlinearstatic.C +++ b/src/sm/EngineeringModels/adaptnlinearstatic.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/adaptnlinearstatic.h" +#include "sm/EngineeringModels/adaptnlinearstatic.h" #include "mathfem.h" #include "verbose.h" #include "timer.h" @@ -43,6 +43,7 @@ #include "node.h" #include "domain.h" #include "datareader.h" +#include "oofemtxtdatareader.h" #include "remeshingcrit.h" #include "mesherinterface.h" #include "dof.h" @@ -84,10 +85,11 @@ AdaptiveNonLinearStatic :: ~AdaptiveNonLinearStatic() { } -IRResultType -AdaptiveNonLinearStatic :: initializeFrom(InputRecord *ir) +void +AdaptiveNonLinearStatic :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + NonLinearStatic :: initializeFrom(ir); + int _val; int meshPackageId = 0; @@ -100,14 +102,11 @@ AdaptiveNonLinearStatic :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, _val, _IFT_AdaptiveNonLinearStatic_preMappingLoadBalancingFlag); preMappingLoadBalancingFlag = _val > 0; - result = NonLinearStatic :: initializeFrom(ir); // check if error estimator initioalized if (this->defaultErrEstimator == NULL) { OOFEM_ERROR ("AdaptiveNonLinearStatic :: initializeFrom: Error estimator not defined [eetype missing]"); } - - return result; } void @@ -145,14 +144,12 @@ AdaptiveNonLinearStatic :: solveYourselfAt(TimeStep *tStep) this->terminate( this->giveCurrentStep() ); // make output // do remeshing - MesherInterface *mesher = classFactory.createMesherInterface( meshPackage, this->giveDomain(1) ); + auto mesher = classFactory.createMesherInterface( meshPackage, this->giveDomain(1) ); Domain *newDomain; MesherInterface :: returnCode result = mesher->createMesh(this->giveCurrentStep(), 1, this->giveDomain(1)->giveSerialNumber() + 1, & newDomain); - delete mesher; - if ( result == MesherInterface :: MI_OK ) { this->initFlag = 1; this->adaptiveRemap(newDomain); @@ -247,9 +244,9 @@ AdaptiveNonLinearStatic :: initializeAdaptiveFrom(EngngModel *sourceProblem) OOFEM_ERROR("source problem must also be AdaptiveNonlinearStatic."); } - this->currentStep.reset( new TimeStep( * ( sourceProblem->giveCurrentStep() ) ) ); + this->currentStep = std::make_unique( * ( sourceProblem->giveCurrentStep() ) ); if ( sourceProblem->givePreviousStep() ) { - this->previousStep.reset( new TimeStep( * ( sourceProblem->givePreviousStep() ) ) ); + this->previousStep = std::make_unique( * ( sourceProblem->givePreviousStep() ) ); } // map primary unknowns @@ -345,7 +342,7 @@ AdaptiveNonLinearStatic :: initializeAdaptiveFrom(EngngModel *sourceProblem) if ( initFlag ) { - stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( !stiffnessMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } @@ -417,15 +414,9 @@ AdaptiveNonLinearStatic :: initializeAdaptiveFrom(EngngModel *sourceProblem) int AdaptiveNonLinearStatic :: initializeAdaptive(int tStepNumber) { - int stepinfo [ 2 ]; - - stepinfo [ 0 ] = tStepNumber; - stepinfo [ 1 ] = 0; - try { - //FileDataStream stream(this->giveContextFileName(tStepNumber, 0), false); - //this->restoreContext(stream, CM_State); - this->restoreContext(NULL, CM_State, ( void * ) stepinfo); + FileDataStream stream(this->giveContextFileName(tStepNumber, 0), false); + this->restoreContext(stream, CM_State); } catch(ContextIOERR & c) { c.print(); exit(1); @@ -436,13 +427,11 @@ AdaptiveNonLinearStatic :: initializeAdaptive(int tStepNumber) int sernum = this->giveDomain(1)->giveSerialNumber(); OOFEM_LOG_INFO("restoring domain %d.%d\n", 1, sernum + 1); Domain *dNew = new Domain(2, sernum + 1, this); - DataReader *domainDr = this->GiveDomainDataReader(1, sernum + 1, contextMode_read); + OOFEMTXTDataReader domainDr(this->giveDomainFileName(1, sernum + 1)); if ( !dNew->instanciateYourself(domainDr) ) { OOFEM_ERROR("domain Instanciation failed"); } - delete domainDr; - // remap solution to new domain return this->adaptiveRemap(dNew); } @@ -666,7 +655,7 @@ AdaptiveNonLinearStatic :: adaptiveRemap(Domain *dNew) if ( initFlag ) { if ( !stiffnessMatrix ) { - stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( !stiffnessMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } @@ -735,55 +724,26 @@ AdaptiveNonLinearStatic :: adaptiveRemap(Domain *dNew) } -contextIOResultType +void AdaptiveNonLinearStatic :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = NonLinearStatic :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + NonLinearStatic :: saveContext(stream, mode); + contextIOResultType iores; if ( ( iores = timeStepLoadLevels.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -AdaptiveNonLinearStatic :: restoreContext(DataStream *stream, ContextMode mode, void *obj) +void +AdaptiveNonLinearStatic :: restoreContext(DataStream &stream, ContextMode mode) { - int closeFlag = 0; - int istep, iversion; - contextIOResultType iores; - FILE *file = NULL; - - this->resolveCorrespondingStepNumber(istep, iversion, obj); - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - - if ( ( iores = NonLinearStatic :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + NonLinearStatic :: restoreContext(stream, mode); - if ( ( iores = timeStepLoadLevels.restoreYourself(*stream) ) != CIO_OK ) { + contextIOResultType iores; + if ( ( iores = timeStepLoadLevels.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } // ensure consistent records - - return CIO_OK; } @@ -800,12 +760,8 @@ AdaptiveNonLinearStatic :: assembleInitialLoadVector(FloatArray &loadVector, Flo AdaptiveNonLinearStatic *sourceProblem, int domainIndx, TimeStep *tStep) { - IRResultType result; // Required by IR_GIVE_FIELD macro - int mStepNum = tStep->giveMetaStepNumber(); int hasfixed, mode; - InputRecord *ir; - MetaStep *iMStep; FloatArray _incrementalLoadVector, _incrementalLoadVectorOfPrescribed; SparseNonLinearSystemNM :: referenceLoadInputModeType rlm; //Domain* sourceDomain = sourceProblem->giveDomain(domainIndx); @@ -820,9 +776,9 @@ AdaptiveNonLinearStatic :: assembleInitialLoadVector(FloatArray &loadVector, Flo _incrementalLoadVectorOfPrescribed.zero(); for ( int imstep = 1; imstep < mStepNum; imstep++ ) { - iMStep = this->giveMetaStep(imstep); - ir = iMStep->giveAttributesRecord(); - //hasfixed = ir->hasField("fixload"); + auto iMStep = this->giveMetaStep(imstep); + auto &ir = iMStep->giveAttributesRecord(); + //hasfixed = ir.hasField("fixload"); hasfixed = 1; if ( hasfixed ) { // test for control mode @@ -839,7 +795,7 @@ AdaptiveNonLinearStatic :: assembleInitialLoadVector(FloatArray &loadVector, Flo IR_GIVE_OPTIONAL_FIELD(ir, mode, _IFT_AdaptiveNonLinearStatic_controlmode); // check if displacement control takes place - if ( ir->hasField(_IFT_AdaptiveNonLinearStatic_ddm) ) { + if ( ir.hasField(_IFT_AdaptiveNonLinearStatic_ddm) ) { OOFEM_ERROR("fixload recovery not supported for direct displacement control"); } @@ -864,7 +820,7 @@ AdaptiveNonLinearStatic :: assembleInitialLoadVector(FloatArray &loadVector, Flo } } else if ( mode == ( int ) nls_indirectControl ) { // bad practise here - if ( !ir->hasField(_IFT_NonLinearStatic_donotfixload) ) { + if ( !ir.hasField(_IFT_NonLinearStatic_donotfixload) ) { TimeStep *old = new TimeStep(firststep, this, imstep, firststep - 1.0, deltaT, 0); this->assembleIncrementalReferenceLoadVectors(_incrementalLoadVector, _incrementalLoadVectorOfPrescribed, rlm, this->giveDomain(domainIndx), old); @@ -880,8 +836,8 @@ AdaptiveNonLinearStatic :: assembleInitialLoadVector(FloatArray &loadVector, Flo } // end loop over meta-steps /* if direct control; add to initial load also previous steps in same metestep */ - iMStep = this->giveMetaStep(mStepNum); - ir = iMStep->giveAttributesRecord(); + auto iMStep = this->giveMetaStep(mStepNum); + auto &ir = iMStep->giveAttributesRecord(); mode = 0; IR_GIVE_OPTIONAL_FIELD(ir, mode, _IFT_AdaptiveNonLinearStatic_controlmode); int firststep = iMStep->giveFirstStepNumber(); @@ -911,8 +867,6 @@ AdaptiveNonLinearStatic :: assembleInitialLoadVector(FloatArray &loadVector, Flo * AdaptiveNonLinearStatic* sourceProblem, int domainIndx, * TimeStep* tStep) * { - * IRResultType result; // Required by IR_GIVE_FIELD macro - * * int mStepNum = tStep->giveMetaStepNumber() ; * int mode; * InputRecord* ir; @@ -992,28 +946,28 @@ LoadBalancer * AdaptiveNonLinearStatic :: giveLoadBalancer() { if ( lb ) { - return lb; + return lb.get(); } if ( loadBalancingFlag || preMappingLoadBalancingFlag ) { lb = classFactory.createLoadBalancer( "parmetis", this->giveDomain(1) ); - return lb; + return lb.get(); } else { - return NULL; + return nullptr; } } LoadBalancerMonitor * AdaptiveNonLinearStatic :: giveLoadBalancerMonitor() { if ( lbm ) { - return lbm; + return lbm.get(); } if ( loadBalancingFlag || preMappingLoadBalancingFlag ) { lbm = classFactory.createLoadBalancerMonitor( "wallclock", this); - return lbm; + return lbm.get(); } else { - return NULL; + return nullptr; } } #endif diff --git a/src/sm/EngineeringModels/adaptnlinearstatic.h b/src/sm/EngineeringModels/adaptnlinearstatic.h index 9d19e2a2e..28459d697 100644 --- a/src/sm/EngineeringModels/adaptnlinearstatic.h +++ b/src/sm/EngineeringModels/adaptnlinearstatic.h @@ -35,7 +35,7 @@ #ifndef adaptnlinearstatic_h #define adaptnlinearstatic_h -#include "../sm/EngineeringModels/nlinearstatic.h" +#include "sm/EngineeringModels/nlinearstatic.h" #include "sparsemtrx.h" #include "errorestimator.h" #include "meshpackagetype.h" @@ -96,14 +96,14 @@ class AdaptiveNonLinearStatic : public NonLinearStatic FloatArray timeStepLoadLevels; public: - AdaptiveNonLinearStatic(int i, EngngModel * _master = NULL); + AdaptiveNonLinearStatic(int i, EngngModel *master = nullptr); virtual ~AdaptiveNonLinearStatic(); - virtual void solveYourselfAt(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); + void solveYourselfAt(TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof); + void initializeFrom(InputRecord &ir) override; + double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) override; /** * Returns the load level corresponding to given solution step number. @@ -114,7 +114,7 @@ class AdaptiveNonLinearStatic : public NonLinearStatic * This process should typically include restoring old solution, instanciating newly * generated domain(s) and by mapping procedure. */ - virtual int initializeAdaptive(int tStepNumber); + int initializeAdaptive(int tStepNumber) override; /** * Initializes the receiver state according to state of given source problem. * This process should typically include mapping of source solution, internal variable mapping procedures and @@ -128,17 +128,17 @@ class AdaptiveNonLinearStatic : public NonLinearStatic */ virtual int adaptiveRemap(Domain *dNew); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void updateDomainLinks(); + void updateDomainLinks() override; - virtual const char *giveClassName() const { return "AdaptiveNonLinearStatic"; } - virtual const char *giveInputRecordName() const { return _IFT_AdaptiveNonLinearStatic_Name; } + const char *giveClassName() const override { return "AdaptiveNonLinearStatic"; } + const char *giveInputRecordName() const override { return _IFT_AdaptiveNonLinearStatic_Name; } #ifdef __PARALLEL_MODE - virtual LoadBalancer *giveLoadBalancer(); - virtual LoadBalancerMonitor *giveLoadBalancerMonitor(); + LoadBalancer *giveLoadBalancer() override; + LoadBalancerMonitor *giveLoadBalancerMonitor() override; #endif protected: diff --git a/src/sm/EngineeringModels/deidynamic.C b/src/sm/EngineeringModels/deidynamic.C index bcd7848a0..7e7558eb7 100644 --- a/src/sm/EngineeringModels/deidynamic.C +++ b/src/sm/EngineeringModels/deidynamic.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/deidynamic.h" +#include "sm/EngineeringModels/deidynamic.h" #include "timestep.h" #include "dofmanager.h" #include "element.h" @@ -58,15 +58,13 @@ NumericalMethod *DEIDynamic :: giveNumericalMethod(MetaStep *mStep) } -IRResultType -DEIDynamic :: initializeFrom(InputRecord *ir) +void +DEIDynamic :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralEngngModel :: initializeFrom(ir); IR_GIVE_FIELD(ir, dumpingCoef, _IFT_DEIDynamic_dumpcoef); // C = dumpingCoef * M IR_GIVE_FIELD(ir, deltaT, _IFT_DEIDynamic_deltat); - - return StructuralEngngModel :: initializeFrom(ir); } @@ -117,7 +115,7 @@ TimeStep *DEIDynamic :: giveNextStep() } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(istep, this, 1, totalTime, deltaT, counter) ); + currentStep = std::make_unique(istep, this, 1, totalTime, deltaT, counter); return currentStep.get(); } diff --git a/src/sm/EngineeringModels/deidynamic.h b/src/sm/EngineeringModels/deidynamic.h index a32d492c7..1aed491bb 100644 --- a/src/sm/EngineeringModels/deidynamic.h +++ b/src/sm/EngineeringModels/deidynamic.h @@ -35,7 +35,7 @@ #ifndef deidynamic_h #define deidynamic_h -#include "../sm/EngineeringModels/structengngmodel.h" +#include "sm/EngineeringModels/structengngmodel.h" ///@name Input fields for DEIDynamic //@{ @@ -80,26 +80,26 @@ class DEIDynamic : public StructuralEngngModel double dumpingCoef, deltaT; public: - DEIDynamic(int i, EngngModel * _master = NULL) : StructuralEngngModel(i, _master), massMatrix(), loadVector(), + DEIDynamic(int i, EngngModel *master = nullptr) : StructuralEngngModel(i, master), massMatrix(), loadVector(), nextDisplacementVector(), displacementVector(), velocityVector(), accelerationVector() { ndomains = 1; } virtual ~DEIDynamic(); - virtual void solveYourselfAt(TimeStep *tStep); + void solveYourselfAt(TimeStep *tStep) override; - virtual double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual TimeStep *giveNextStep(); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof) override; + void initializeFrom(InputRecord &ir) override; + TimeStep *giveNextStep() override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep); + void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep) override; // identification - virtual const char *giveClassName() const { return "DEIDynamic"; } - virtual const char *giveInputRecordName() const { return _IFT_DEIDynamic_Name; } - virtual fMode giveFormulation() { return TL; } - virtual int giveNumberOfFirstStep(bool force = false) { return 0; } + const char *giveClassName() const override { return "DEIDynamic"; } + const char *giveInputRecordName() const { return _IFT_DEIDynamic_Name; } + fMode giveFormulation() override { return TL; } + int giveNumberOfFirstStep(bool force = false) override { return 0; } }; } // end namespace oofem #endif // deidynamic_h diff --git a/src/sm/EngineeringModels/diidynamic.C b/src/sm/EngineeringModels/diidynamic.C index b5fa12664..3659439e8 100644 --- a/src/sm/EngineeringModels/diidynamic.C +++ b/src/sm/EngineeringModels/diidynamic.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/diidynamic.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/Elements/structuralelementevaluator.h" +#include "sm/EngineeringModels/diidynamic.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelementevaluator.h" #include "timestep.h" #include "element.h" #include "dofmanager.h" @@ -70,7 +70,7 @@ NumericalMethod *DIIDynamic :: giveNumericalMethod(MetaStep *mStep) return nMethod.get(); } - nMethod.reset( classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this) ); + nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); if ( !nMethod ) { OOFEM_ERROR("linear solver creation failed for lstype %d", solverType); } @@ -79,15 +79,10 @@ NumericalMethod *DIIDynamic :: giveNumericalMethod(MetaStep *mStep) } -IRResultType -DIIDynamic :: initializeFrom(InputRecord *ir) +void +DIIDynamic :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StructuralEngngModel :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralEngngModel :: initializeFrom(ir); int val = 0; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_lstype); @@ -127,13 +122,10 @@ DIIDynamic :: initializeFrom(InputRecord *ir) theta = 1.37; } } else { - OOFEM_WARNING("Time-stepping scheme not found!"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_DIIDynamic_ddtScheme, "Time-stepping scheme not found!"); } IR_GIVE_FIELD(ir, deltaT, _IFT_DIIDynamic_deltat); - - return IRRT_OK; } @@ -191,7 +183,7 @@ TimeStep *DIIDynamic :: giveNextStep() previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(istep, this, 1, totalTime, deltaT, counter, td) ); + currentStep = std::make_unique(istep, this, 1, totalTime, deltaT, counter, td); return currentStep.get(); } @@ -258,7 +250,7 @@ void DIIDynamic :: solveYourselfAt(TimeStep *tStep) #ifdef VERBOSE OOFEM_LOG_DEBUG("Assembling stiffness matrix\n"); #endif - stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( !stiffnessMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } @@ -446,27 +438,28 @@ DIIDynamic :: timesMtrx(FloatArray &vec, FloatArray &answer, CharType type, Doma element->giveLocationArray(loc, en); element->giveCharacteristicMatrix(charMtrx, type, tStep); if ( charMtrx.isNotEmpty() ) { - ///@todo This rotation matrix is not flexible enough.. it can only work with full size matrices and doesn't allow for flexibility in the matrixassembler. - if ( element->giveRotationMatrix(R) ) { - charMtrx.rotatedWith(R); - } - } + ///@todo This rotation matrix is not flexible enough.. it can only work with full size matrices and doesn't allow for flexibility in the matrixassembler. + if ( element->giveRotationMatrix(R) ) { + charMtrx.rotatedWith(R); + } + #ifdef DEBUG - if ( loc.giveSize() != charMtrx.giveNumberOfRows() ) { - OOFEM_ERROR("dimension mismatch"); - } + if ( loc.giveSize() != charMtrx.giveNumberOfRows() ) { + OOFEM_ERROR("dimension mismatch"); + } #endif - n = loc.giveSize(); - for ( j = 1; j <= n; j++ ) { - jj = loc.at(j); - if ( jj ) { - for ( k = 1; k <= n; k++ ) { - kk = loc.at(k); - if ( kk ) { - answer.at(jj) += charMtrx.at(j, k) * vec.at(kk); + n = loc.giveSize(); + for ( j = 1; j <= n; j++ ) { + jj = loc.at(j); + if ( jj ) { + for ( k = 1; k <= n; k++ ) { + kk = loc.at(k); + if ( kk ) { + answer.at(jj) += charMtrx.at(j, k) * vec.at(kk); + } } } } @@ -621,13 +614,11 @@ DIIDynamic :: determineConstants(TimeStep *tStep) } -contextIOResultType DIIDynamic :: saveContext(DataStream &stream, ContextMode mode) +void DIIDynamic :: saveContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - if ( ( iores = EngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + EngngModel :: saveContext(stream, mode); if ( ( iores = displacementVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); @@ -648,57 +639,32 @@ contextIOResultType DIIDynamic :: saveContext(DataStream &stream, ContextMode mo if ( ( iores = previousIncrementOfDisplacement.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType DIIDynamic :: restoreContext(DataStream *stream, ContextMode mode, void *obj) +void DIIDynamic :: restoreContext(DataStream &stream, ContextMode mode) { - int closeFlag = 0; - int istep, iversion; contextIOResultType iores; - FILE *file = NULL; - - this->resolveCorrespondingStepNumber(istep, iversion, obj); - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // Override. - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - if ( ( iores = EngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + EngngModel :: restoreContext(stream, mode); - if ( ( iores = displacementVector.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = displacementVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = velocityVector.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = velocityVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = accelerationVector.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = accelerationVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = loadVector.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = loadVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = previousIncrementOfDisplacement.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = previousIncrementOfDisplacement.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/EngineeringModels/diidynamic.h b/src/sm/EngineeringModels/diidynamic.h index 26bd6fae0..4a8ec8c8d 100644 --- a/src/sm/EngineeringModels/diidynamic.h +++ b/src/sm/EngineeringModels/diidynamic.h @@ -35,7 +35,7 @@ #ifndef diidynamic_h #define diidynamic_h -#include "../sm/EngineeringModels/structengngmodel.h" +#include "sm/EngineeringModels/structengngmodel.h" #include "sparselinsystemnm.h" #include "sparsemtrx.h" #include "timediscretizationtype.h" @@ -95,24 +95,24 @@ class DIIDynamic : public StructuralEngngModel std :: unique_ptr< SparseLinearSystemNM > nMethod; public: - DIIDynamic(int i, EngngModel * _master = NULL); + DIIDynamic(int i, EngngModel *master = nullptr); virtual ~DIIDynamic(); - virtual void solveYourself(); - virtual void solveYourselfAt(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); - virtual double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual TimeStep *giveNextStep(); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); - virtual void initializeYourself(TimeStep *tStep); + void solveYourself() override; + void solveYourselfAt(TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override; + double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof) override; + void initializeFrom(InputRecord &ir) override; + TimeStep *giveNextStep() override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; + void initializeYourself(TimeStep *tStep) override; // identification - virtual const char *giveClassName() const { return "DIIDynamic"; } - virtual const char *giveInputRecordName() const { return _IFT_DIIDynamic_Name; } - virtual fMode giveFormulation() { return TL; } + const char *giveClassName() const override { return "DIIDynamic"; } + const char *giveInputRecordName() const { return _IFT_DIIDynamic_Name; } + fMode giveFormulation() override { return TL; } - virtual void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep); + void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep) override; void timesMtrx(FloatArray &answer, FloatArray &vec, CharType type, Domain *domain, TimeStep *tStep); void assembleLoadVector(FloatArray &_loadVector, Domain *domain, ValueModeType mode, TimeStep *tStep); @@ -120,8 +120,8 @@ class DIIDynamic : public StructuralEngngModel void assembleDirichletBcRhsVector (FloatArray& answer, Domain* d, TimeStep *tStep); void determineConstants(TimeStep *tStep); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; TimeDiscretizationType giveInitialTimeDiscretization() { return initialTimeDiscretization; } }; diff --git a/src/sm/EngineeringModels/eigenvaluedynamic.C b/src/sm/EngineeringModels/eigenvaluedynamic.C index 7fa0cea89..9f141ebbd 100644 --- a/src/sm/EngineeringModels/eigenvaluedynamic.C +++ b/src/sm/EngineeringModels/eigenvaluedynamic.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/eigenvaluedynamic.h" +#include "sm/EngineeringModels/eigenvaluedynamic.h" #include "timestep.h" #include "floatmatrix.h" #include "floatarray.h" @@ -55,10 +55,18 @@ namespace oofem { REGISTER_EngngModel(EigenValueDynamic); + +EigenValueDynamic :: EigenValueDynamic(int i, EngngModel *master) : EngngModel(i, master) +{ + numberOfSteps = 1; + ndomains = 1; +} + + NumericalMethod *EigenValueDynamic :: giveNumericalMethod(MetaStep *mStep) { if ( !nMethod ) { - nMethod.reset( classFactory.createGeneralizedEigenValueSolver(solverType, this->giveDomain(1), this) ); + nMethod = classFactory.createGeneralizedEigenValueSolver(solverType, this->giveDomain(1), this); if ( !nMethod ) { OOFEM_ERROR("solver creation failed"); } @@ -67,13 +75,14 @@ NumericalMethod *EigenValueDynamic :: giveNumericalMethod(MetaStep *mStep) return nMethod.get(); } -IRResultType -EigenValueDynamic :: initializeFrom(InputRecord *ir) + +void +EigenValueDynamic :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro //EngngModel::instanciateFrom (ir); IR_GIVE_FIELD(ir, numberOfRequiredEigenValues, _IFT_EigenValueDynamic_nroot); + this->field = std::make_unique(this, 1, FT_Displacements, numberOfRequiredEigenValues); // numberOfSteps set artificially to numberOfRequiredEigenValues // in order to allow @@ -84,9 +93,7 @@ EigenValueDynamic :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, rtolv, _IFT_EigenValueDynamic_rtolv); if ( rtolv < 1.e-12 ) { rtolv = 1.e-12; - } - - if ( rtolv > 0.01 ) { + } else if ( rtolv > 0.01 ) { rtolv = 0.01; } @@ -98,47 +105,31 @@ EigenValueDynamic :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_smtype); sparseMtrxType = ( SparseMtrxType ) val; - suppressOutput = ir->hasField(_IFT_EngngModel_suppressOutput); + suppressOutput = ir.hasField(_IFT_EngngModel_suppressOutput); - if(suppressOutput) { - printf("Suppressing output.\n"); - } - else { + if ( suppressOutput ) { + printf("Suppressing output.\n"); + } else { + if ( ( outputStream = fopen(this->dataOutputFileName.c_str(), "w") ) == NULL ) { + OOFEM_ERROR("Can't open output file %s", this->dataOutputFileName.c_str()); + } - if ( ( outputStream = fopen(this->dataOutputFileName.c_str(), "w") ) == NULL ) { - OOFEM_ERROR("Can't open output file %s", this->dataOutputFileName.c_str()); - } + fprintf(outputStream, "%s", PRG_HEADER); + fprintf(outputStream, "\nStarting analysis on: %s\n", ctime(& this->startTime) ); + fprintf(outputStream, "%s\n", simulationDescription.c_str()); + } +} - fprintf(outputStream, "%s", PRG_HEADER); - fprintf(outputStream, "\nStarting analysis on: %s\n", ctime(& this->startTime) ); - fprintf(outputStream, "%s\n", simulationDescription.c_str()); - } - return IRRT_OK; +int EigenValueDynamic :: giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) +{ + return tStep->giveNumber() % this->numberOfRequiredEigenValues; } double EigenValueDynamic :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) -// returns unknown quantity like displacement, eigenvalue. -// This function translates this request to numerical method language { - int eq = dof->__giveEquationNumber(); -#ifdef DEBUG - if ( eq == 0 ) { - OOFEM_ERROR("invalid equation number"); - } -#endif - - switch ( mode ) { - case VM_Total: // EigenVector - case VM_Incremental: - return eigVec.at( eq, ( int ) tStep->giveTargetTime() ); - - default: - OOFEM_ERROR("Unknown is of undefined type for this problem"); - } - - return 0.; + return field->giveUnknownValue(dof, mode, tStep); } @@ -153,63 +144,45 @@ TimeStep *EigenValueDynamic :: giveNextStep() } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(istep, this, 1, ( double ) istep, 0., counter) ); + currentStep = std::make_unique(istep, this, 1, ( double ) istep, 0., counter); return currentStep.get(); } -void EigenValueDynamic :: solveYourselfAt(TimeStep *tStep) +void EigenValueDynamic :: solveYourself() { - // - // creates system of governing eq's and solves them at given time step - // - // first assemble problem at current time step + this->timer.startTimer(EngngModelTimer :: EMTT_AnalysisTimer); + + TimeStep *tStep = this->giveNextStep(); + this->updateAttributes( this->giveCurrentMetaStep() ); -#ifdef VERBOSE OOFEM_LOG_INFO("Assembling stiffness and mass matrices\n"); -#endif - if ( tStep->giveNumber() == 1 ) { - // - // first step assemble stiffness Matrix - // + FloatMatrix eigVec; + { + std :: unique_ptr< SparseMtrx > stiffnessMatrix; + std :: unique_ptr< SparseMtrx > massMatrix; - stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); stiffnessMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); - massMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + massMatrix = classFactory.createSparseMtrx(sparseMtrxType); massMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); - this->assemble( *stiffnessMatrix, tStep, TangentAssembler(TangentStiffness), - EModelDefaultEquationNumbering(), this->giveDomain(1) ); - this->assemble( *massMatrix, tStep, MassMatrixAssembler(), - EModelDefaultEquationNumbering(), this->giveDomain(1) ); - // - // create resulting objects eigVec and eigVal - // - eigVec.resize(this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ), numberOfRequiredEigenValues); - eigVec.zero(); - eigVal.resize(numberOfRequiredEigenValues); - eigVal.zero(); - } - - // - // set-up numerical model - // - this->giveNumericalMethod( this->giveMetaStep( tStep->giveMetaStepNumber() ) ); + this->assemble( *stiffnessMatrix, tStep, TangentAssembler(TangentStiffness), EModelDefaultEquationNumbering(), this->giveDomain(1) ); + this->assemble( *massMatrix, tStep, MassMatrixAssembler(), EModelDefaultEquationNumbering(), this->giveDomain(1) ); - // - // call numerical model to solve arised problem - // -#ifdef VERBOSE - OOFEM_LOG_INFO("Solving ...\n"); -#endif + this->giveNumericalMethod( this->giveMetaStep( tStep->giveMetaStepNumber() ) ); + OOFEM_LOG_INFO("Solving ...\n"); + nMethod->solve(*stiffnessMatrix, *massMatrix, eigVal, eigVec, rtolv, numberOfRequiredEigenValues); + } + this->field->updateAll(eigVec, EModelDefaultEquationNumbering()); - nMethod->solve(*stiffnessMatrix, *massMatrix, eigVal, eigVec, rtolv, numberOfRequiredEigenValues); + this->terminate( tStep ); - stiffnessMatrix.reset(NULL); - massMatrix.reset(NULL); + double steptime = this->giveSolutionStepTime(); + OOFEM_LOG_INFO("EngngModel info: user time consumed by solution: %.2fs\n", steptime); } @@ -228,7 +201,7 @@ void EigenValueDynamic :: doStepOutput(TimeStep *tStep) // export using export manager tStep->setTime( ( double ) i ); // we use time as intrinsic eigen value index tStep->setNumber(i); - exportModuleManager->doOutput(tStep); + exportModuleManager.doOutput(tStep); } } @@ -253,9 +226,9 @@ void EigenValueDynamic :: printOutputAt(FILE *file, TimeStep *tStep) for ( int i = 1; i <= numberOfRequiredEigenValues; i++ ) { fprintf(file, "\nOutput for eigen value no. %.3e \n", ( double ) i); - fprintf(file, "Printing eigen vector no. %d, corresponding eigen value is %15.8e\n\n", - i, eigVal.at(i) ); + fprintf(file, "Printing eigen vector no. %d, corresponding eigen value is %15.8e\n\n", i, eigVal.at(i) ); tStep->setTime( ( double ) i ); // we use time as intrinsic eigen value index + tStep->setNumber(i); if ( this->requiresUnknownsDictionaryUpdate() ) { for ( auto &dman : domain->giveDofManagers() ) { @@ -269,103 +242,47 @@ void EigenValueDynamic :: printOutputAt(FILE *file, TimeStep *tStep) dman->printOutputAt(file, tStep); } } + + double utsec = this->timer.getUtime(EngngModelTimer :: EMTT_AnalysisTimer); + fprintf(file, "\nUser time consumed by solution step: %.3f [s]\n\n", utsec); } -contextIOResultType EigenValueDynamic :: saveContext(DataStream &stream, ContextMode mode) +void EigenValueDynamic :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = EngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + EngngModel :: saveContext(stream, mode); + contextIOResultType iores; if ( ( iores = eigVal.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( eigVec.storeYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + this->field->saveContext(stream); } -contextIOResultType EigenValueDynamic :: restoreContext(DataStream *stream, ContextMode mode, void *obj) -// -// restore state variable - displacement vector -// +void EigenValueDynamic :: restoreContext(DataStream &stream, ContextMode mode) { - int closeFlag = 0; - int activeVector = this->resolveCorrespondingEigenStepNumber(obj); - int istep = 1, iversion = 0; - contextIOResultType iores; - FILE *file = NULL; - - if ( restoreFlag == 0 ) { // not restored before - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - - // save element context - - if ( ( iores = EngngModel :: restoreContext(stream, mode, ( void * ) & istep) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = eigVal.restoreYourself(*stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = eigVec.restoreYourself(*stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + EngngModel :: restoreContext(stream, mode); - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } // ensure consistent records - } - - if ( activeVector > numberOfRequiredEigenValues ) { - activeVector = numberOfRequiredEigenValues; + contextIOResultType iores; + if ( ( iores = eigVal.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); } - OOFEM_LOG_INFO( "Restoring - corresponding index is %d, EigenValue is %f\n", activeVector, eigVal.at(activeVector) ); - this->giveCurrentStep()->setTime( ( double ) activeVector ); - this->restoreFlag = 1; - - return CIO_OK; + this->field->restoreContext(stream); } -int EigenValueDynamic :: resolveCorrespondingEigenStepNumber(void *obj) +void EigenValueDynamic :: setActiveVector(int i) { - // - // returns corresponding eigen step number - // - if ( obj == NULL ) { - return 1; - } - - int *istep = ( int * ) obj; - - if ( * istep > numberOfRequiredEigenValues ) { - return numberOfRequiredEigenValues; - } - - if ( * istep <= 0 ) { - return 1; + this->activeVector = i; + if ( activeVector > numberOfRequiredEigenValues ) { + activeVector = numberOfRequiredEigenValues; } - return * istep; + this->giveCurrentStep()->setNumber( activeVector ); + this->giveCurrentStep()->setTime( ( double ) activeVector ); } } // end namespace oofem diff --git a/src/sm/EngineeringModels/eigenvaluedynamic.h b/src/sm/EngineeringModels/eigenvaluedynamic.h index 83165a0d7..0d85e127f 100644 --- a/src/sm/EngineeringModels/eigenvaluedynamic.h +++ b/src/sm/EngineeringModels/eigenvaluedynamic.h @@ -41,6 +41,7 @@ #include "floatmatrix.h" #include "floatarray.h" #include "geneigvalsolvertype.h" +#include "eigenvectorprimaryfield.h" ///@name Input fields for EigenValueDynamic //@{ @@ -65,46 +66,39 @@ namespace oofem { class EigenValueDynamic : public EngngModel { private: - std :: unique_ptr< SparseMtrx > stiffnessMatrix; - std :: unique_ptr< SparseMtrx > massMatrix; - SparseMtrxType sparseMtrxType; - FloatMatrix eigVec; + std :: unique_ptr< EigenVectorPrimaryField > field; FloatArray eigVal; - int numberOfRequiredEigenValues; int activeVector; int restoreFlag; + SparseMtrxType sparseMtrxType; + int numberOfRequiredEigenValues; /// Relative tolerance. double rtolv; - /// Numerical method used to solve the problem. std :: unique_ptr< SparseGeneralEigenValueSystemNM > nMethod; GenEigvalSolverType solverType; public: - EigenValueDynamic(int i, EngngModel * _master = NULL) : EngngModel(i, _master) - { - numberOfSteps = 1; - ndomains = 1; - } + EigenValueDynamic(int i, EngngModel *master=nullptr); virtual ~EigenValueDynamic() { } - virtual void solveYourselfAt(TimeStep *tStep); - virtual void doStepOutput(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); + void solveYourself() override; + void doStepOutput(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override; - virtual double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); - virtual TimeStep *giveNextStep(); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); - virtual void setActiveVector(int i) { activeVector = i; } - virtual int resolveCorrespondingEigenStepNumber(void *obj); + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override; + double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof) override; + bool newDofHandling() override { return true; } + void initializeFrom(InputRecord &ir) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + TimeStep *giveNextStep() override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; + void setActiveVector(int i) override; - virtual double giveEigenValue(int eigNum) { return eigVal.at(eigNum); } + double giveEigenValue(int eigNum) override { return eigVal.at(eigNum); } - // identification - virtual const char *giveClassName() const { return "EigenValueDynamic"; } + const char *giveClassName() const override { return "EigenValueDynamic"; } }; } // end namespace oofem #endif // eigenvaluedynamic_h diff --git a/src/sm/EngineeringModels/freewarping.C b/src/sm/EngineeringModels/freewarping.C index acdb7a5a2..f1db02b77 100644 --- a/src/sm/EngineeringModels/freewarping.C +++ b/src/sm/EngineeringModels/freewarping.C @@ -34,16 +34,16 @@ #include "freewarping.h" #include "crosssection.h" -#include "Elements/trwarp.h" +#include "sm/Elements/trwarp.h" #include "nummet.h" #include "timestep.h" #include "element.h" #include "dof.h" #include "sparsemtrx.h" #include "verbose.h" -#include "Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "unknownnumberingscheme.h" -#include "Elements/structuralelementevaluator.h" +#include "sm/Elements/structuralelementevaluator.h" #include "datastream.h" #include "contextioerr.h" #include "classfactory.h" @@ -79,10 +79,10 @@ NumericalMethod *FreeWarping :: giveNumericalMethod(MetaStep *mStep) { if ( isParallel() ) { if ( ( solverType == ST_Petsc ) || ( solverType == ST_Feti ) ) { - nMethod.reset( classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this) ); + nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); } } else { - nMethod.reset( classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this) ); + nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); } if ( !nMethod ) { @@ -92,15 +92,10 @@ NumericalMethod *FreeWarping :: giveNumericalMethod(MetaStep *mStep) return nMethod.get(); } -IRResultType -FreeWarping :: initializeFrom(InputRecord *ir) +void +FreeWarping :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StructuralEngngModel :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralEngngModel :: initializeFrom(ir); int val = 0; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_lstype); @@ -110,9 +105,6 @@ FreeWarping :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_smtype); sparseMtrxType = ( SparseMtrxType ) val; - - - #ifdef __PARALLEL_MODE if ( isParallel() ) { commBuff = new CommunicatorBuff( this->giveNumberOfProcesses() ); @@ -121,9 +113,6 @@ FreeWarping :: initializeFrom(InputRecord *ir) } #endif - - - return IRRT_OK; } @@ -238,7 +227,7 @@ TimeStep *FreeWarping :: giveNextStep() } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(istep, this, 1, ( double ) istep, 0., counter) ); + currentStep = std::make_unique(istep, this, 1, ( double ) istep, 0., counter); return currentStep.get(); } @@ -276,7 +265,7 @@ void FreeWarping :: solveYourselfAt(TimeStep *tStep) // // first step assemble stiffness Matrix // - stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( !stiffnessMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } diff --git a/src/sm/EngineeringModels/freewarping.h b/src/sm/EngineeringModels/freewarping.h index 55a8ed740..70361ac6c 100644 --- a/src/sm/EngineeringModels/freewarping.h +++ b/src/sm/EngineeringModels/freewarping.h @@ -81,31 +81,31 @@ class FreeWarping : public StructuralEngngModel int initFlag; // needed? public: - FreeWarping(int i, EngngModel *_master = NULL); + FreeWarping(int i, EngngModel *master = nullptr); virtual ~FreeWarping(); - virtual void solveYourself(); - virtual void solveYourselfAt(TimeStep *tStep); + void solveYourself() override; + void solveYourselfAt(TimeStep *tStep) override; - virtual double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof); - //virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - //virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof) override; + //void saveContext(DataStream &stream, ContextMode mode) override; + //void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void updateDomainLinks(); + void updateDomainLinks() override; - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; - virtual TimeStep *giveNextStep(); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + TimeStep *giveNextStep() override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; void getCenterOfGravity(FloatMatrix &answer) { answer = this->CG; } // identification - virtual const char *giveInputRecordName() const { return _IFT_FreeWarping_Name; } - virtual const char *giveClassName() const { return "FreeWarping"; } - virtual fMode giveFormulation() { return TL; } + const char *giveInputRecordName() const { return _IFT_FreeWarping_Name; } + const char *giveClassName() const override { return "FreeWarping"; } + fMode giveFormulation() override { return TL; } /** * Gives the sum of the first moment of area. * @return Total moments Sx Sy. @@ -115,7 +115,7 @@ class FreeWarping : public StructuralEngngModel void updateComputedResults(FloatArray &answer, TimeStep *tStep); void updateStiffnessMatrix(SparseMtrx *answer); - int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType); + int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType) override; }; } // end namespace oofem #endif // freewarping_h diff --git a/src/sm/EngineeringModels/incrementallinearstatic.C b/src/sm/EngineeringModels/incrementallinearstatic.C index 00df2079b..5c6943b9b 100644 --- a/src/sm/EngineeringModels/incrementallinearstatic.C +++ b/src/sm/EngineeringModels/incrementallinearstatic.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/incrementallinearstatic.h" +#include "sm/EngineeringModels/incrementallinearstatic.h" #include "timestep.h" #include "dof.h" #include "domain.h" @@ -76,7 +76,7 @@ NumericalMethod *IncrementalLinearStatic :: giveNumericalMethod(MetaStep *mStep) { if ( !nMethod ) { - nMethod.reset( classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this) ); + nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); if ( !nMethod ) { OOFEM_ERROR("linear solver creation failed for lstype %d", solverType); } @@ -86,10 +86,8 @@ NumericalMethod *IncrementalLinearStatic :: giveNumericalMethod(MetaStep *mStep) } -IRResultType IncrementalLinearStatic :: initializeFrom(InputRecord *ir) +void IncrementalLinearStatic :: initializeFrom(InputRecord &ir) { - IRResultType result; - IR_GIVE_OPTIONAL_FIELD(ir, discreteTimes, _IFT_IncrementalLinearStatic_prescribedtimes); if ( discreteTimes.giveSize() > 0 ) { numberOfSteps = discreteTimes.giveSize(); @@ -113,7 +111,7 @@ IRResultType IncrementalLinearStatic :: initializeFrom(InputRecord *ir) sparseMtrxType = ( SparseMtrxType ) val; - suppressOutput = ir->hasField(_IFT_EngngModel_suppressOutput); + suppressOutput = ir.hasField(_IFT_EngngModel_suppressOutput); if(suppressOutput) { printf("Suppressing output.\n"); @@ -130,7 +128,6 @@ IRResultType IncrementalLinearStatic :: initializeFrom(InputRecord *ir) } //StructuralEngngModel::initializeFrom (ir); - return IRRT_OK; } @@ -152,12 +149,12 @@ double IncrementalLinearStatic :: giveDiscreteTime(int iStep) TimeStep *IncrementalLinearStatic :: giveNextStep() { if ( !currentStep ) { - currentStep.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, 0., this->giveDiscreteTime(1), 0) ); + currentStep = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 0, 0., this->giveDiscreteTime(1), 0); } previousStep = std :: move(currentStep); double dt = this->giveDiscreteTime(previousStep->giveNumber()+1) - previousStep->giveTargetTime(); - currentStep.reset( new TimeStep(*previousStep, dt) ); + currentStep = std::make_unique(*previousStep, dt); return currentStep.get(); } @@ -295,7 +292,7 @@ void IncrementalLinearStatic :: solveYourselfAt(TimeStep *tStep) #ifdef VERBOSE OOFEM_LOG_INFO("Assembling stiffness matrix\n"); #endif - stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( !stiffnessMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } @@ -365,43 +362,14 @@ void IncrementalLinearStatic :: updateDofUnknownsDictionary(DofManager *inode, T } -contextIOResultType IncrementalLinearStatic :: saveContext(DataStream &stream, ContextMode mode) +void IncrementalLinearStatic :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = StructuralEngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + StructuralEngngModel :: saveContext(stream, mode); } -contextIOResultType IncrementalLinearStatic :: restoreContext(DataStream *stream, ContextMode mode, void *obj) +void IncrementalLinearStatic :: restoreContext(DataStream &stream, ContextMode mode) { - int closeFlag = 0, istep, iversion; - contextIOResultType iores; - FILE *file = NULL; - this->resolveCorrespondingStepNumber(istep, iversion, obj); - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - - if ( ( iores = StructuralEngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } // ensure consistent records - - return CIO_OK; + StructuralEngngModel :: restoreContext(stream, mode); } } // end namespace oofem diff --git a/src/sm/EngineeringModels/incrementallinearstatic.h b/src/sm/EngineeringModels/incrementallinearstatic.h index d4c5e9eac..050b502cf 100644 --- a/src/sm/EngineeringModels/incrementallinearstatic.h +++ b/src/sm/EngineeringModels/incrementallinearstatic.h @@ -35,7 +35,7 @@ #ifndef incrementallinearstatic_h #define incrementallinearstatic_h -#include "../sm/EngineeringModels/structengngmodel.h" +#include "sm/EngineeringModels/structengngmodel.h" #include "sparselinsystemnm.h" #include "sparsemtrxtype.h" @@ -81,18 +81,18 @@ class IncrementalLinearStatic : public StructuralEngngModel SparseMtrxType sparseMtrxType; public: - IncrementalLinearStatic(int i, EngngModel * _master = NULL); + IncrementalLinearStatic(int i, EngngModel *master = nullptr); virtual ~IncrementalLinearStatic(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void solveYourself(); - virtual void solveYourselfAt(TimeStep *tStep); + void solveYourself() override; + void solveYourselfAt(TimeStep *tStep) override; - virtual double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); - virtual TimeStep *giveNextStep(); + double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + TimeStep *giveNextStep() override; /** * This function returns time valid for iStep time step, used in integration @@ -107,20 +107,20 @@ class IncrementalLinearStatic : public StructuralEngngModel * @param iStep Time step number. */ double giveDiscreteTime(int iStep); - virtual double giveEndOfTimeOfInterest() { return endOfTimeOfInterest; } + double giveEndOfTimeOfInterest() override { return endOfTimeOfInterest; } - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual fMode giveFormulation() { return TL; } + fMode giveFormulation() override { return TL; } - virtual const char *giveInputRecordName() const { return _IFT_IncrementalLinearStatic_Name; } - virtual const char *giveClassName() const { return "IncrementalLinearStatic"; } + const char *giveInputRecordName() const { return _IFT_IncrementalLinearStatic_Name; } + const char *giveClassName() const override { return "IncrementalLinearStatic"; } - virtual int requiresUnknownsDictionaryUpdate() { return true; } - virtual bool requiresEquationRenumbering(TimeStep *) { return true; } - virtual void updateDofUnknownsDictionary(DofManager *, TimeStep *); + int requiresUnknownsDictionaryUpdate() override { return true; } + bool requiresEquationRenumbering(TimeStep *tStep) override { return true; } + void updateDofUnknownsDictionary(DofManager *dman, TimeStep *tStep) override; // Here we store only total and incremental value; so hash is computed from mode value only - virtual int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep); + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override; }; } // end namespace oofem #endif // incrementallinearstatic_h diff --git a/src/sm/EngineeringModels/linearstability.C b/src/sm/EngineeringModels/linearstability.C index 07ee25986..6a18a20ed 100644 --- a/src/sm/EngineeringModels/linearstability.C +++ b/src/sm/EngineeringModels/linearstability.C @@ -35,7 +35,7 @@ // please activate or de-activate next line //#define LIN_STAB_COMPATIBILITY_MODE -#include "../sm/EngineeringModels/linearstability.h" +#include "sm/EngineeringModels/linearstability.h" #include "timestep.h" #include "element.h" #include "contextioerr.h" @@ -49,6 +49,8 @@ #include "dof.h" #include "unknownnumberingscheme.h" #include "outputmanager.h" +#include "eigenvectorprimaryfield.h" + #ifdef __OOFEG #include "oofeggraphiccontext.h" @@ -57,10 +59,20 @@ namespace oofem { REGISTER_EngngModel(LinearStability); +LinearStability :: LinearStability(int i, EngngModel *master) : StructuralEngngModel(i, master), + numberOfRequiredEigenValues(1), + rtolv(1e-6), + solverType(GES_SubspaceIt) +{ + numberOfSteps = 1; + ndomains = 1; +} + + NumericalMethod *LinearStability :: giveNumericalMethod(MetaStep *mStep) { if ( !nMethod ) { - nMethod.reset( classFactory.createGeneralizedEigenValueSolver(solverType, this->giveDomain(1), this) ); + nMethod = classFactory.createGeneralizedEigenValueSolver(solverType, this->giveDomain(1), this); if ( !nMethod ) { OOFEM_ERROR("solver creation failed"); } @@ -69,10 +81,11 @@ NumericalMethod *LinearStability :: giveNumericalMethod(MetaStep *mStep) return nMethod.get(); } + SparseLinearSystemNM *LinearStability :: giveNumericalMethodForLinStaticProblem(TimeStep *tStep) { if ( !nMethodLS ) { - nMethodLS.reset( classFactory.createSparseLinSolver(ST_Direct, this->giveDomain(1), this) ); ///@todo Support other solvers + nMethodLS = classFactory.createSparseLinSolver(ST_Direct, this->giveDomain(1), this); ///@todo Support other solvers if ( !nMethodLS ) { OOFEM_ERROR("solver creation failed"); } @@ -81,24 +94,22 @@ SparseLinearSystemNM *LinearStability :: giveNumericalMethodForLinStaticProblem( return nMethodLS.get(); } -IRResultType -LinearStability :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro +void +LinearStability :: initializeFrom(InputRecord &ir) +{ //StructuralEngngModel::instanciateFrom(ir); IR_GIVE_FIELD(ir, numberOfRequiredEigenValues, _IFT_LinearStability_nroot); // numberOfSteps set artifficially to numberOfRequiredEigenValues // in order to allow // use restoreContext function for different eigenValues numberOfSteps = numberOfRequiredEigenValues; + this->field = std::make_unique(this, 1, FT_Displacements, numberOfRequiredEigenValues + 1); // +1 for eq. solution IR_GIVE_FIELD(ir, rtolv, _IFT_LinearStability_rtolv); if ( rtolv < 1.e-12 ) { rtolv = 1.e-12; - } - - if ( rtolv > 0.01 ) { + } else if ( rtolv > 0.01 ) { rtolv = 0.01; } @@ -106,55 +117,36 @@ LinearStability :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_LinearStability_stype); solverType = ( GenEigvalSolverType ) val; - nMetaSteps = 0; - suppressOutput = ir->hasField(_IFT_EngngModel_suppressOutput); + suppressOutput = ir.hasField(_IFT_EngngModel_suppressOutput); - if(suppressOutput) { - printf("Suppressing output.\n"); - } - else { + if (suppressOutput) { + printf("Suppressing output.\n"); + } else { + if ( ( outputStream = fopen(this->dataOutputFileName.c_str(), "w") ) == NULL ) { + OOFEM_ERROR("Can't open output file %s", this->dataOutputFileName.c_str()); + } - if ( ( outputStream = fopen(this->dataOutputFileName.c_str(), "w") ) == NULL ) { - OOFEM_ERROR("Can't open output file %s", this->dataOutputFileName.c_str()); - } + fprintf(outputStream, "%s", PRG_HEADER); + fprintf(outputStream, "\nStarting analysis on: %s\n", ctime(& this->startTime) ); + fprintf(outputStream, "%s\n", simulationDescription.c_str()); + } +} - fprintf(outputStream, "%s", PRG_HEADER); - fprintf(outputStream, "\nStarting analysis on: %s\n", ctime(& this->startTime) ); - fprintf(outputStream, "%s\n", simulationDescription.c_str()); - } - return IRRT_OK; +int LinearStability :: giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) +{ + return tStep->giveNumber() % (this->numberOfRequiredEigenValues + 1); // +1 for eq. solution } double LinearStability :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) -// returns unknown quantity like displacement, eigen value. { - int eq = dof->__giveEquationNumber(); -#ifdef DEBUG - if ( eq == 0 ) { - OOFEM_ERROR("invalid equation number"); - } -#endif - - int activeVector = ( int ) tStep->giveTargetTime(); - switch ( mode ) { - case VM_Total: // EigenVector - if ( activeVector ) { - return eigVec.at(eq, activeVector); - } - - return displacementVector.at(eq); - - default: - OOFEM_ERROR("Unknown is of undefined type for this problem"); - } - - return 0.; + return field->giveUnknownValue(dof, mode, tStep); } + TimeStep *LinearStability :: giveNextStep() { int istep = giveNumberOfFirstStep(); @@ -166,11 +158,12 @@ TimeStep *LinearStability :: giveNextStep() } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(istep, this, 1, 0., 0., counter) ); + currentStep = std::make_unique(istep, this, 1, 0., 0., counter); return currentStep.get(); } + void LinearStability :: solveYourself() { this->timer.startTimer(EngngModelTimer :: EMTT_AnalysisTimer); @@ -184,138 +177,98 @@ void LinearStability :: solveYourself() void LinearStability :: solveYourselfAt(TimeStep *tStep) { - // + tStep->setNumber(0); + tStep->setTime(0.0); + // creates system of governing eq's and solves them at given time step - // this->giveNumericalMethod( this->giveMetaStep( tStep->giveMetaStepNumber() ) ); this->giveNumericalMethodForLinStaticProblem(tStep); // first assemble problem at current time step - - if ( tStep->giveNumber() == 1 ) { + if ( !stiffnessMatrix ) { // // first step - solve linear static problem // - stiffnessMatrix.reset( classFactory.createSparseMtrx(SMT_Skyline) ); ///@todo Don't hardcode skyline matrix only + stiffnessMatrix = classFactory.createSparseMtrx(SMT_Skyline); ///@todo Don't hardcode skyline matrix only stiffnessMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); - - // - // allocate space for displacement Vector - // - displacementVector.resize( this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ) ); - // - // allocate space for load vector - // - loadVector.resize( this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ) ); } #ifndef LIN_STAB_COMPATIBILITY_MODE - #ifdef VERBOSE OOFEM_LOG_INFO("Assembling stiffness matrix\n"); - #endif stiffnessMatrix->zero(); this->assemble( *stiffnessMatrix, tStep, TangentAssembler(TangentStiffness), EModelDefaultEquationNumbering(), this->giveDomain(1) ); #endif - -#ifdef VERBOSE OOFEM_LOG_INFO("Assembling load\n"); -#endif - - displacementVector.zero(); - loadVector.zero(); + int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); + FloatArray displacementVector(neq), loadVector(neq); // Internal forces first, negated; - this->assembleVector( loadVector, tStep, InternalForceAssembler(), VM_Total, - EModelDefaultEquationNumbering(), this->giveDomain(1) ); + field->update(VM_Total, tStep, displacementVector, EModelDefaultEquationNumbering()); + this->assembleVector( loadVector, tStep, InternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); loadVector.negated(); - this->assembleVector( loadVector, tStep, ExternalForceAssembler(), VM_Total, - EModelDefaultEquationNumbering(), this->giveDomain(1) ); + this->assembleVector( loadVector, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); this->updateSharedDofManagers(loadVector, EModelDefaultEquationNumbering(), ReactionExchangeTag); - // - // call numerical model to solve problem - // -#ifdef VERBOSE OOFEM_LOG_INFO("Solving linear static problem\n"); -#endif - nMethodLS->solve(*stiffnessMatrix, loadVector, displacementVector); + // Initial displacements are stored at position 0; this is a bit of a hack. In the future, a cleaner approach of handling fields could be suitable, + // but currently, it all converges down to the same giveUnknownComponent, so this is the easisest approach. + field->update(VM_Total, tStep, displacementVector, EModelDefaultEquationNumbering()); // terminate linear static computation (necessary, in order to compute stresses in elements). - this->terminateLinStatic( this->giveCurrentStep() ); - /* - * Normal forces already known, proceed with linear stability - */ + // Recompute for updated state: + this->assembleVector( loadVector, tStep, InternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); + this->terminateLinStatic( tStep ); + // Normal forces already known, proceed with linear stability stiffnessMatrix->zero(); if ( !initialStressMatrix ) { - initialStressMatrix.reset( stiffnessMatrix->GiveCopy() ); + initialStressMatrix = stiffnessMatrix->clone(); } else { initialStressMatrix->zero(); } -#ifdef VERBOSE OOFEM_LOG_INFO("Assembling stiffness matrix\n"); -#endif this->assemble( *stiffnessMatrix, tStep, TangentAssembler(TangentStiffness), EModelDefaultEquationNumbering(), this->giveDomain(1) ); -#ifdef VERBOSE + OOFEM_LOG_INFO("Assembling initial stress matrix\n"); -#endif this->assemble( *initialStressMatrix, tStep, InitialStressMatrixAssembler(), EModelDefaultEquationNumbering(), this->giveDomain(1) ); initialStressMatrix->times(-1.0); - // stiffnessMatrix->printYourself(); - // initialStressMatrix->printYourself(); + //stiffnessMatrix->printYourself(); + //initialStressMatrix->printYourself(); - // - // create resulting objects eigVec and eigVal - // - eigVec.resize(this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ), numberOfRequiredEigenValues); + FloatMatrix eigVec(neq, numberOfRequiredEigenValues); eigVal.resize(numberOfRequiredEigenValues); - eigVec.zero(); eigVal.zero(); - // - // call numerical model to solve arised problem - // -#ifdef VERBOSE OOFEM_LOG_INFO("Solving ...\n"); -#endif - nMethod->solve(*stiffnessMatrix, *initialStressMatrix, eigVal, eigVec, rtolv, numberOfRequiredEigenValues); - // compute eigen frequencies - //for (i = 1; i<= numberOfRequiredEigenValues; i++) - // eigVal.at(i) = sqrt(eigVal.at(i)); + this->field->updateAll(eigVec, EModelDefaultEquationNumbering()); } + void LinearStability :: updateYourself(TimeStep *tStep) { } + void LinearStability :: terminateLinStatic(TimeStep *tStep) { Domain *domain = this->giveDomain(1); - tStep->setTime(0.); - - if ( requiresUnknownsDictionaryUpdate() ) { - for ( auto &dman : domain->giveDofManagers() ) { - this->updateDofUnknownsDictionary(dman.get(), tStep); - } - } for ( auto &dman : domain->giveDofManagers() ) { dman->updateYourself(tStep); } # ifdef VERBOSE - VERBOSE_PRINT0("Updated nodes & sides ", domain->giveNumberOfDofManagers()) + VERBOSE_PRINT0("Updated nodes ", domain->giveNumberOfDofManagers()) # endif - for ( auto &elem : domain->giveElements() ) { elem->updateInternalState(tStep); elem->updateYourself(tStep); @@ -350,20 +303,15 @@ void LinearStability :: doStepOutput(TimeStep *tStep) Domain *domain = this->giveDomain(1); // i = 0 represents the linear solution, which is followed by the eigen vectors starting at i = 1 for ( int i = 0; i <= numberOfRequiredEigenValues; i++ ) { - tStep->setTime( ( double ) i ); - - if ( this->requiresUnknownsDictionaryUpdate() ) { - for ( auto &dman : domain->giveDofManagers() ) { - this->updateDofUnknownsDictionary(dman.get(), tStep); - } - } + TimeStep step = *tStep; + step.setTime( ( double ) i ); + step.setNumber(i); for ( auto &dman : domain->giveDofManagers() ) { - dman->updateYourself(tStep); + dman->updateYourself(&step); } - tStep->setNumber(i); - exportModuleManager->doOutput(tStep); + exportModuleManager.doOutput(&step); } } @@ -388,115 +336,62 @@ void LinearStability :: printOutputAt(FILE *file, TimeStep *tStep) fprintf(file, "\n\n"); for ( int i = 0; i <= numberOfRequiredEigenValues; i++ ) { + TimeStep step = *tStep; + step.setTime( ( double ) i ); + step.setNumber(i); + if ( i == 0 ) { fprintf(file, "\nLinear solution\n\n"); } else { - fprintf(file, "\nEigen vector no. %d, correposnding eigen value is %15.8e\n\n", i, eigVal.at(i)); - } - tStep->setTime( ( double ) i ); - - if ( this->requiresUnknownsDictionaryUpdate() ) { - for ( auto &dman : domain->giveDofManagers() ) { - this->updateDofUnknownsDictionary(dman.get(), tStep); - } + fprintf(file, "\nEigen vector no. %d, corresponding eigen value is %15.8e\n\n", i, eigVal.at(i)); } for ( auto &dman : domain->giveDofManagers() ) { - dman->updateYourself(tStep); - dman->printOutputAt(file, tStep); + dman->updateYourself(&step); + dman->printOutputAt(file, &step); } - tStep->setNumber(i); - if ( i == 0 ) { for ( auto &elem : domain->giveElements() ) { - elem->printOutputAt(file, tStep); + elem->printOutputAt(file, &step); } - this->printReactionForces(tStep, 1., file); + this->printReactionForces(&step, 1., file); } } } -contextIOResultType LinearStability :: saveContext(DataStream &stream, ContextMode mode) +void LinearStability :: setActiveVector(int activeVector) { - contextIOResultType iores; + this->giveCurrentStep()->setTime( ( double ) activeVector ); + this->giveCurrentStep()->setNumber( ( double ) activeVector ); +} - if ( ( iores = StructuralEngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( ( iores = displacementVector.storeYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } +void LinearStability :: saveContext(DataStream &stream, ContextMode mode) +{ + StructuralEngngModel :: saveContext(stream, mode); - if ( ( iores = eigVal.storeYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + field->saveContext(stream); - if ( ( iores = eigVec.storeYourself(stream) ) != CIO_OK ) { + contextIOResultType iores; + if ( ( iores = eigVal.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType LinearStability :: restoreContext(DataStream *stream, ContextMode mode, void *obj) +void LinearStability :: restoreContext(DataStream &stream, ContextMode mode) { - int activeVector, version; - int istep = 1, iversion = 1; - int closeFlag = 0; - contextIOResultType iores; - FILE *file = NULL; - - this->resolveCorrespondingStepNumber(activeVector, version, obj); - if ( eigVal.isEmpty() ) { // not restored before - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } + StructuralEngngModel :: restoreContext(stream, mode); - stream = new FileDataStream(file); - closeFlag = 1; - } - - if ( ( iores = StructuralEngngModel :: restoreContext(stream, mode, ( void * ) & istep) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + field->restoreContext(stream); - if ( ( iores = displacementVector.restoreYourself(*stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = eigVal.restoreYourself(*stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = eigVec.restoreYourself(*stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } // ensure consistent records - } - - // if (istep > numberOfRequiredEigenValues) istep = numberOfRequiredEigenValues ; - // printf( "Restoring - corresponding index is %d, EigenValue is %lf\n", - // istep,eigVal.at(istep)); - // setActiveVector (istep); - if ( activeVector > numberOfRequiredEigenValues ) { - activeVector = numberOfRequiredEigenValues; + contextIOResultType iores; + if ( ( iores = eigVal.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); } - - OOFEM_LOG_INFO( "Restoring - corresponding index is %d, EigenValue is %f\n", - activeVector, eigVal.at(activeVector) ); - this->giveCurrentStep()->setTime( ( double ) activeVector ); - - return CIO_OK; } + } // end namespace oofem diff --git a/src/sm/EngineeringModels/linearstability.h b/src/sm/EngineeringModels/linearstability.h index 377526b7f..16ccb88c8 100644 --- a/src/sm/EngineeringModels/linearstability.h +++ b/src/sm/EngineeringModels/linearstability.h @@ -35,7 +35,7 @@ #ifndef linearstability_h #define linearstability_h -#include "../sm/EngineeringModels/structengngmodel.h" +#include "sm/EngineeringModels/structengngmodel.h" #include "geneigvalsolvertype.h" #include "sparsegeneigenvalsystemnm.h" #include "sparselinsystemnm.h" @@ -53,6 +53,10 @@ //@} namespace oofem { + +class EigenVectorPrimaryField; +//class DofDistributedPrimaryField; + /** * This class implements way for examining critical load of structure. * @@ -70,10 +74,10 @@ class LinearStability : public StructuralEngngModel private: std :: unique_ptr< SparseMtrx > stiffnessMatrix; std :: unique_ptr< SparseMtrx > initialStressMatrix; - FloatArray loadVector; - FloatArray displacementVector; - FloatMatrix eigVec; + std :: unique_ptr< EigenVectorPrimaryField > field; + //std :: unique_ptr< DofDistributedPrimaryField > initialDisplacements; FloatArray eigVal; + int numberOfRequiredEigenValues; double rtolv; /// Numerical method used to solve the problem. @@ -83,43 +87,42 @@ class LinearStability : public StructuralEngngModel std :: unique_ptr< SparseLinearSystemNM > nMethodLS; public: - LinearStability(int i, EngngModel * _master = NULL) : StructuralEngngModel(i, _master), - loadVector(), displacementVector(), eigVec(), eigVal() - { - numberOfSteps = 1; - ndomains = 1; - } + LinearStability(int i, EngngModel *master=nullptr); virtual ~LinearStability() { } - virtual void solveYourself(); - virtual void solveYourselfAt(TimeStep *tStep); + void solveYourself() override; + void solveYourselfAt(TimeStep *tStep) override; - virtual void doStepOutput(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void doStepOutput(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) override; + //virtual void printOutputAt(FILE *file, TimeStep *tStep, const IntArray &nodeSets, const IntArray &elementSets); void terminateLinStatic(TimeStep *tStep); int requiresNewLsh() { return 0; } - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; // the intrinsic time of time step defines active eigen value and corresponding vector, // for which values can be requested using // giveUnknownComponent method. // When DisplacementVector is requested, then if time==0 linear elastic solution displacement are returned, // otherwise corresponding eigen vector is considered as displacement vector - virtual double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); - virtual TimeStep *giveNextStep(); + double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof) override; + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override; + bool newDofHandling() override { return true; } + void initializeFrom(InputRecord &ir) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + TimeStep *giveNextStep() override; - virtual double giveEigenValue(int eigNum) { return eigVal.at(eigNum); } + double giveEigenValue(int eigNum) override { return eigVal.at(eigNum); } + void setActiveVector(int i) override; - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; SparseLinearSystemNM *giveNumericalMethodForLinStaticProblem(TimeStep *tStep); // identification - virtual const char *giveInputRecordName() const { return _IFT_LinearStability_Name; } - virtual const char *giveClassName() const { return "LinearStability"; } - virtual fMode giveFormulation() { return TL; } + const char *giveInputRecordName() const { return _IFT_LinearStability_Name; } + const char *giveClassName() const override { return "LinearStability"; } + fMode giveFormulation() override { return TL; } }; } // end namespace oofem #endif // linearstability_h diff --git a/src/sm/EngineeringModels/linearstatic.C b/src/sm/EngineeringModels/linearstatic.C index 47dc0983d..3e358e51c 100644 --- a/src/sm/EngineeringModels/linearstatic.C +++ b/src/sm/EngineeringModels/linearstatic.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/linearstatic.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/Elements/structuralelementevaluator.h" +#include "sm/EngineeringModels/linearstatic.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelementevaluator.h" #include "nummet.h" #include "timestep.h" #include "element.h" @@ -62,13 +62,10 @@ LinearStatic :: LinearStatic(int i, EngngModel *_master) : StructuralEngngModel( ndomains = 1; initFlag = 1; solverType = ST_Direct; - equationNumbering = new EModelDefaultEquationNumbering(); } -LinearStatic :: ~LinearStatic() { - delete equationNumbering; -} +LinearStatic :: ~LinearStatic() {} NumericalMethod *LinearStatic :: giveNumericalMethod(MetaStep *mStep) @@ -76,10 +73,10 @@ NumericalMethod *LinearStatic :: giveNumericalMethod(MetaStep *mStep) if ( !nMethod ) { if ( isParallel() ) { if ( ( solverType == ST_Petsc ) || ( solverType == ST_Feti ) ) { - nMethod.reset( classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this) ); + nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); } } else { - nMethod.reset( classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this) ); + nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); } if ( !nMethod ) { OOFEM_ERROR("linear solver creation failed for lstype %d", solverType); @@ -90,15 +87,10 @@ NumericalMethod *LinearStatic :: giveNumericalMethod(MetaStep *mStep) return nMethod.get(); } -IRResultType -LinearStatic :: initializeFrom(InputRecord *ir) +void +LinearStatic :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StructuralEngngModel :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralEngngModel :: initializeFrom(ir); int val = 0; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_lstype); @@ -116,9 +108,6 @@ LinearStatic :: initializeFrom(InputRecord *ir) } #endif - - - return IRRT_OK; } @@ -159,11 +148,11 @@ TimeStep *LinearStatic :: giveNextStep() { if ( !currentStep ) { // first step -> generate initial step - //currentStep.reset( new TimeStep(*giveSolutionStepWhenIcApply()) ); - currentStep.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., 1., 0) ); + //currentStep = std::make_unique(*giveSolutionStepWhenIcApply()); + currentStep = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., 1., 0); } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(*previousStep, 1.) ); + currentStep = std::make_unique(*previousStep, 1.); return currentStep.get(); } @@ -174,7 +163,7 @@ void LinearStatic :: solveYourself() if ( this->isParallel() ) { #ifdef __VERBOSE_PARALLEL // force equation numbering before setting up comm maps - int neq = this->giveNumberOfDomainEquations(1, *this->giveEquationNumbering()); + int neq = this->giveNumberOfDomainEquations(1, this->giveEquationNumbering()); OOFEM_LOG_INFO("[process rank %d] neq is %d\n", this->giveRank(), neq); #endif @@ -201,15 +190,15 @@ void LinearStatic :: solveYourselfAt(TimeStep *tStep) // // first step assemble stiffness Matrix // - stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( !stiffnessMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } - stiffnessMatrix->buildInternalStructure( this, 1, *this->giveEquationNumbering() ); + stiffnessMatrix->buildInternalStructure( this, 1, this->giveEquationNumbering() ); this->assemble( *stiffnessMatrix, tStep, TangentAssembler(TangentStiffness), - *this->giveEquationNumbering(), this->giveDomain(1) ); + this->giveEquationNumbering(), this->giveDomain(1) ); initFlag = 0; } @@ -221,28 +210,28 @@ void LinearStatic :: solveYourselfAt(TimeStep *tStep) // // allocate space for displacementVector // - displacementVector.resize( this->giveNumberOfDomainEquations( 1, *this->giveEquationNumbering() ) ); // km?? replace EModelDefaultEquationNumbering() with this->giveEquationNumbering(). Use pointer? + displacementVector.resize( this->giveNumberOfDomainEquations( 1, this->giveEquationNumbering() ) ); // km?? replace EModelDefaultEquationNumbering() with this->giveEquationNumbering(). Use pointer? displacementVector.zero(); // // assembling the load vector // - loadVector.resize( this->giveNumberOfDomainEquations( 1, *this->giveEquationNumbering() ) ); + loadVector.resize( this->giveNumberOfDomainEquations( 1, this->giveEquationNumbering() ) ); loadVector.zero(); this->assembleVector( loadVector, tStep, ExternalForceAssembler(), VM_Total, - *this->giveEquationNumbering(), this->giveDomain(1) ); + this->giveEquationNumbering(), this->giveDomain(1) ); // // internal forces (from Dirichlet b.c's, or thermal expansion, etc.) // - FloatArray internalForces( this->giveNumberOfDomainEquations( 1, *this->giveEquationNumbering() ) ); + FloatArray internalForces( this->giveNumberOfDomainEquations( 1, this->giveEquationNumbering() ) ); internalForces.zero(); this->assembleVector( internalForces, tStep, InternalForceAssembler(), VM_Total, - *this->giveEquationNumbering(), this->giveDomain(1) ); + this->giveEquationNumbering(), this->giveDomain(1) ); loadVector.subtract(internalForces); - this->updateSharedDofManagers(loadVector, *this->giveEquationNumbering(), ReactionExchangeTag); + this->updateSharedDofManagers(loadVector, this->giveEquationNumbering(), ReactionExchangeTag); // // set-up numerical model @@ -264,59 +253,25 @@ void LinearStatic :: solveYourselfAt(TimeStep *tStep) } -contextIOResultType LinearStatic :: saveContext(DataStream &stream, ContextMode mode) +void LinearStatic :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = StructuralEngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralEngngModel :: saveContext(stream, mode); + contextIOResultType iores; if ( ( iores = displacementVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType LinearStatic :: restoreContext(DataStream *stream, ContextMode mode, void *obj) -// -// restore state variable - displacement vector -// +void LinearStatic :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - int closeFlag = 0; - int istep, iversion; - FILE *file = NULL; + StructuralEngngModel :: restoreContext(stream, mode); - this->resolveCorrespondingStepNumber(istep, iversion, obj); - - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - - if ( ( iores = StructuralEngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = displacementVector.restoreYourself(*stream) ) != CIO_OK ) { + contextIOResultType iores; + if ( ( iores = displacementVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } - - return CIO_OK; } @@ -350,7 +305,7 @@ LinearStatic :: estimateMaxPackSize(IntArray &commMap, DataStream &buff, int pac // only pcount is relevant here, since only prescribed components are exchanged !!!! // -------------------------------------------------------------------------------- - return ( buff.givePackSizeOfDouble(1) * pcount ); + return buff.givePackSizeOfDouble(1) * pcount; } else if ( packUnpackType == 1 ) { for ( int map: commMap ) { count += domain->giveElement( map )->estimatePackSize(buff); diff --git a/src/sm/EngineeringModels/linearstatic.h b/src/sm/EngineeringModels/linearstatic.h index 83dcc760a..281b5fb3e 100644 --- a/src/sm/EngineeringModels/linearstatic.h +++ b/src/sm/EngineeringModels/linearstatic.h @@ -35,7 +35,7 @@ #ifndef linearstatic_h #define linearstatic_h -#include "../sm/EngineeringModels/structengngmodel.h" +#include "sm/EngineeringModels/structengngmodel.h" #include "sparselinsystemnm.h" #include "sparsemtrxtype.h" #include "unknownnumberingscheme.h" @@ -73,35 +73,34 @@ class LinearStatic : public StructuralEngngModel std :: unique_ptr< SparseLinearSystemNM > nMethod; int initFlag; - EModelDefaultEquationNumbering *equationNumbering; + EModelDefaultEquationNumbering equationNumbering; public: - LinearStatic(int i, EngngModel * _master = NULL); + LinearStatic(int i, EngngModel *master = nullptr); virtual ~LinearStatic(); - virtual void solveYourself(); - virtual void solveYourselfAt(TimeStep *tStep); + void solveYourself() override; + void solveYourselfAt(TimeStep *tStep) override; - virtual double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void updateDomainLinks(); + void updateDomainLinks() override; - virtual TimeStep *giveNextStep(); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + TimeStep *giveNextStep() override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - // EModelDefaultEquationNumbering giveEquationNumbering() {return EModelDefaultEquationNumbering(); } - virtual UnknownNumberingScheme *giveEquationNumbering() {return equationNumbering; } //km?? + virtual UnknownNumberingScheme &giveEquationNumbering() { return equationNumbering; } // identification virtual const char *giveInputRecordName() const { return _IFT_LinearStatic_Name; } - virtual const char *giveClassName() const { return "LinearStatic"; } - virtual fMode giveFormulation() { return TL; } + const char *giveClassName() const override { return "LinearStatic"; } + fMode giveFormulation() override { return TL; } - virtual int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType); + int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType) override; }; } // end namespace oofem #endif // linearstatic_h diff --git a/src/sm/EngineeringModels/nldeidynamic.C b/src/sm/EngineeringModels/nldeidynamic.C index 66fb464d6..f604293b7 100644 --- a/src/sm/EngineeringModels/nldeidynamic.C +++ b/src/sm/EngineeringModels/nldeidynamic.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/nldeidynamic.h" +#include "sm/EngineeringModels/nldeidynamic.h" #include "timestep.h" #include "dofmanager.h" #include "element.h" @@ -59,40 +59,36 @@ REGISTER_EngngModel(NlDEIDynamic); NlDEIDynamic :: NlDEIDynamic(int i, EngngModel *_master) : StructuralEngngModel(i, _master), massMatrix(), loadVector(), previousIncrementOfDisplacementVector(), displacementVector(), velocityVector(), accelerationVector(), internalForces(), - nMethod(NULL) + initFlag(1) { ndomains = 1; - initFlag = 1; } NlDEIDynamic :: ~NlDEIDynamic() { } + NumericalMethod *NlDEIDynamic :: giveNumericalMethod(MetaStep *mStep) { - if ( nMethod ) { - return nMethod; + if ( !nMethod ) { + nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); } - - nMethod = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); - - return nMethod; + return nMethod.get(); } -IRResultType -NlDEIDynamic :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - result = StructuralEngngModel :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } +void +NlDEIDynamic :: initializeFrom(InputRecord &ir) +{ + StructuralEngngModel :: initializeFrom(ir); IR_GIVE_FIELD(ir, dumpingCoef, _IFT_NlDEIDynamic_dumpcoef); // C = dumpingCoef * M IR_GIVE_FIELD(ir, deltaT, _IFT_NlDEIDynamic_deltat); + reductionFactor = 1.; + IR_GIVE_OPTIONAL_FIELD(ir, reductionFactor, _IFT_NlDEIDynamic_reduct); + drFlag = 0; IR_GIVE_OPTIONAL_FIELD(ir, drFlag, _IFT_NlDEIDynamic_drflag); if ( drFlag ) { @@ -105,15 +101,13 @@ NlDEIDynamic :: initializeFrom(InputRecord *ir) communicator = new NodeCommunicator(this, commBuff, this->giveRank(), this->giveNumberOfProcesses()); - if ( ir->hasField(_IFT_NlDEIDynamic_nonlocalext) ) { + if ( ir.hasField(_IFT_NlDEIDynamic_nonlocalext) ) { nonlocalExt = 1; nonlocCommunicator = new ElementCommunicator(this, commBuff, this->giveRank(), this->giveNumberOfProcesses()); } #endif - - return IRRT_OK; } @@ -153,6 +147,7 @@ double NlDEIDynamic :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, return 0.; } + TimeStep *NlDEIDynamic :: giveNextStep() { int istep = 0; @@ -166,13 +161,12 @@ TimeStep *NlDEIDynamic :: giveNextStep() } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(istep, this, 1, totalTime, deltaT, counter) ); + currentStep = std::make_unique(istep, this, 1, totalTime, deltaT, counter); return currentStep.get(); } - void NlDEIDynamic :: solveYourself() { if ( this->isParallel() ) { @@ -196,13 +190,7 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) Domain *domain = this->giveDomain(1); int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); - int nman = domain->giveNumberOfDofManagers(); - - DofManager *node; - - int i, k, j, jj; - double coeff, maxDt, maxOm = 0.; - double prevIncrOfDisplacement, incrOfDisplacement; + double maxOm = 0.; if ( initFlag ) { #ifdef VERBOSE @@ -224,16 +212,12 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) #ifdef __PARALLEL_MODE // Compute the processor part of load vector norm pMp this->pMp = 0.0; - double my_pMp = 0.0, coeff = 1.0; - int eqNum, ndofman = domain->giveNumberOfDofManagers(); - dofManagerParallelMode dofmanmode; - DofManager *dman; - for ( int dm = 1; dm <= ndofman; dm++ ) { - dman = domain->giveDofManager(dm); - dofmanmode = dman->giveParallelMode(); + double my_pMp = 0.0; + for ( auto &dman : domain->giveDofManagers() ) { + dofManagerParallelMode dofmanmode = dman->giveParallelMode(); // Skip all remote and null dofmanagers - coeff = 1.0; + double coeff = 1.0; if ( ( dofmanmode == DofManager_remote ) || ( ( dofmanmode == DofManager_null ) ) ) { continue; } else if ( dofmanmode == DofManager_shared ) { @@ -241,7 +225,8 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) } // For shared nodes we add locally an average = 1/givePartitionsConnectivitySize()*contribution, - for ( Dof *dof: *dman ) { + for ( auto &dof: *dman ) { + int eqNum; if ( dof->isPrimaryDof() && ( eqNum = dof->__giveEquationNumber() ) ) { my_pMp += coeff * loadRefVector.at(eqNum) * loadRefVector.at(eqNum) / massMatrix.at(eqNum); } @@ -252,7 +237,7 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) MPI_Allreduce(& my_pMp, & pMp, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #else this->pMp = 0.0; - for ( i = 1; i <= neq; i++ ) { + for ( int i = 1; i <= neq; i++ ) { pMp += loadRefVector.at(i) * loadRefVector.at(i) / massMatrix.at(i); } #endif @@ -282,9 +267,7 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) accelerationVector.resize(neq); accelerationVector.zero(); - for ( j = 1; j <= nman; j++ ) { - node = domain->giveDofManager(j); - + for ( auto &node : domain->giveDofManagers()) { for ( Dof *dof: *node ) { // Ask for initial values obtained from // bc (boundary conditions) and ic (initial conditions) @@ -293,7 +276,7 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) continue; } - jj = dof->__giveEquationNumber(); + int jj = dof->__giveEquationNumber(); if ( jj ) { displacementVector.at(jj) = dof->giveUnknown(VM_Total, tStep); velocityVector.at(jj) = dof->giveUnknown(VM_Velocity, tStep); @@ -307,15 +290,23 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) // // Try to determine the best deltaT, - maxDt = 2.0 / sqrt(maxOm); - if ( deltaT > maxDt ) { - // Print reduced time step increment and minimum period Tmin - OOFEM_LOG_RELEVANT("deltaT reduced to %e, Tmin is %e\n", maxDt, maxDt * M_PI); - deltaT = maxDt; - tStep->setTimeIncrement(deltaT); + double maxDt = reductionFactor * 2.0 / sqrt(maxOm); + int newNumberOfSteps = this->numberOfSteps; + double newDeltaT = 0; + + if ( deltaT > maxDt ) { + //Scale number of steps based on reduced time step + newDeltaT = maxDt; + newNumberOfSteps = floor(numberOfSteps*deltaT/newDeltaT); + this->giveMetaStep(1)->setNumberOfSteps(newNumberOfSteps); + this->deltaT = newDeltaT; + tStep->setTimeIncrement(deltaT); + + // Print reduced time step increment and minimum period Tmin + OOFEM_LOG_RELEVANT("deltaT reduced to %e, Tmin is %e, nsteps is %d\n", this->deltaT, maxDt * M_PI, newNumberOfSteps); } - for ( j = 1; j <= neq; j++ ) { + for ( int j = 1; j <= neq; j++ ) { previousIncrementOfDisplacementVector.at(j) = velocityVector.at(j) * ( deltaT ); displacementVector.at(j) -= previousIncrementOfDisplacementVector.at(j); } @@ -335,7 +326,7 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) tStep->incrementStateCounter(); // Compute internal forces. - this->giveInternalForces(internalForces, false, 1, tStep); + this->updateInternalRHS(internalForces, tStep, this->giveDomain(1), nullptr); if ( !drFlag ) { // @@ -352,15 +343,11 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) pt = 0.0; #ifdef __PARALLEL_MODE - double my_pt = 0.0, coeff = 1.0; - int eqNum, ndofman = domain->giveNumberOfDofManagers(); - dofManagerParallelMode dofmanmode; - DofManager *dman; - for ( int dm = 1; dm <= ndofman; dm++ ) { - dman = domain->giveDofManager(dm); - dofmanmode = dman->giveParallelMode(); + double my_pt = 0.0; + for ( auto &dman : domain->giveDofManagers() ) { + dofManagerParallelMode dofmanmode = dman->giveParallelMode(); // skip all remote and null dofmanagers - coeff = 1.0; + double coeff = 1.0; if ( ( dofmanmode == DofManager_remote ) || ( dofmanmode == DofManager_null ) ) { continue; } else if ( dofmanmode == DofManager_shared ) { @@ -368,7 +355,8 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) } // For shared nodes we add locally an average= 1/givePartitionsConnectivitySize()*contribution. - for ( Dof *dof: *dman ) { + for ( auto &dof: *dman ) { + int eqNum; if ( dof->isPrimaryDof() && ( eqNum = dof->__giveEquationNumber() ) ) { my_pt += coeff * internalForces.at(eqNum) * loadRefVector.at(eqNum) / massMatrix.at(eqNum); } @@ -378,7 +366,7 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) // Sum up the contributions from processors. MPI_Allreduce(& my_pt, & pt, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #else - for ( k = 1; k <= neq; k++ ) { + for ( int k = 1; k <= neq; k++ ) { pt += internalForces.at(k) * loadRefVector.at(k) / massMatrix.at(k); } @@ -391,7 +379,7 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) } loadVector.resize( this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ) ); - for ( k = 1; k <= neq; k++ ) { + for ( int k = 1; k <= neq; k++ ) { loadVector.at(k) = pt * loadRefVector.at(k) - internalForces.at(k); } @@ -401,11 +389,10 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) #ifdef __PARALLEL_MODE double my_err = 0.0; - for ( int dm = 1; dm <= ndofman; dm++ ) { - dman = domain->giveDofManager(dm); - dofmanmode = dman->giveParallelMode(); + for ( auto &dman : domain->giveDofManagers() ) { + auto dofmanmode = dman->giveParallelMode(); // Skip all remote and null dofmanagers. - coeff = 1.0; + double coeff = 1.0; if ( ( dofmanmode == DofManager_remote ) || ( dofmanmode == DofManager_null ) ) { continue; } else if ( dofmanmode == DofManager_shared ) { @@ -413,7 +400,8 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) } // For shared nodes we add locally an average= 1/givePartitionsConnectivitySize()*contribution. - for ( Dof *dof: *dman ) { + for ( auto &dof: *dman ) { + int eqNum; if ( dof->isPrimaryDof() && ( eqNum = dof->__giveEquationNumber() ) ) { my_err += coeff * loadVector.at(eqNum) * loadVector.at(eqNum) / massMatrix.at(eqNum); } @@ -424,7 +412,7 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) MPI_Allreduce(& my_err, & err, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #else - for ( k = 1; k <= neq; k++ ) { + for ( int k = 1; k <= neq; k++ ) { err = loadVector.at(k) * loadVector.at(k) / massMatrix.at(k); } @@ -433,10 +421,9 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) OOFEM_LOG_RELEVANT("Relative error is %e, loadlevel is %e\n", err, pt); } - for ( j = 1; j <= neq; j++ ) { - coeff = massMatrix.at(j); + for ( int j = 1; j <= neq; j++ ) { loadVector.at(j) += - coeff * ( ( 1. / ( deltaT * deltaT ) ) - dumpingCoef * 1. / ( 2. * deltaT ) ) * + massMatrix.at(j) * ( ( 1. / ( deltaT * deltaT ) ) - dumpingCoef * 1. / ( 2. * deltaT ) ) * previousIncrementOfDisplacementVector.at(j); } @@ -460,9 +447,9 @@ void NlDEIDynamic :: solveYourselfAt(TimeStep *tStep) // } - for ( i = 1; i <= neq; i++ ) { - prevIncrOfDisplacement = previousIncrementOfDisplacementVector.at(i); - incrOfDisplacement = loadVector.at(i) / + for ( int i = 1; i <= neq; i++ ) { + double prevIncrOfDisplacement = previousIncrementOfDisplacementVector.at(i); + double incrOfDisplacement = loadVector.at(i) / ( massMatrix.at(i) * ( 1. / ( deltaT * deltaT ) + dumpingCoef / ( 2. * deltaT ) ) ); accelerationVector.at(i) = ( incrOfDisplacement - prevIncrOfDisplacement ) / ( deltaT * deltaT ); @@ -508,11 +495,8 @@ NlDEIDynamic :: computeMassMtrx(FloatArray &massMatrix, double &maxOm, TimeStep Domain *domain = this->giveDomain(1); int nelem = domain->giveNumberOfElements(); int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); - int i, j, jj, n; - double maxOmi, maxOmEl; FloatMatrix charMtrx, charMtrx2, R; IntArray loc; - Element *element; EModelDefaultEquationNumbering en; #ifndef LOCAL_ZERO_MASS_REPLACEMENT @@ -522,8 +506,8 @@ NlDEIDynamic :: computeMassMtrx(FloatArray &massMatrix, double &maxOm, TimeStep maxOm = 0.; massMatrix.resize(neq); massMatrix.zero(); - for ( i = 1; i <= nelem; i++ ) { - element = domain->giveElement(i); + for ( int i = 1; i <= nelem; i++ ) { + Element *element = domain->giveElement(i); // skip remote elements (these are used as mirrors of remote elements on other domains // when nonlocal constitutive models are used. They introduction is necessary to @@ -535,20 +519,20 @@ NlDEIDynamic :: computeMassMtrx(FloatArray &massMatrix, double &maxOm, TimeStep element->giveLocationArray(loc, en); element->giveCharacteristicMatrix(charMtrx, LumpedMassMatrix, tStep); if ( charMtrx.isNotEmpty() ) { - ///@todo This rotation matrix is not flexible enough.. it can only work with full size matrices and doesn't allow for flexibility in the matrixassembler. - if ( element->giveRotationMatrix(R) ) { - charMtrx.rotatedWith(R); - } + ///@todo This rotation matrix is not flexible enough.. it can only work with full size matrices and doesn't allow for flexibility in the matrixassembler. + if ( element->giveRotationMatrix(R) ) { + charMtrx.rotatedWith(R); + } } #ifdef LOCAL_ZERO_MASS_REPLACEMENT element->giveCharacteristicMatrix(charMtrx2, TangentStiffnessMatrix, tStep); if ( charMtrx2.isNotEmpty() ) { - ///@todo This rotation matrix is not flexible enough.. it can only work with full size matrices and doesn't allow for flexibility in the matrixassembler. - if ( R.isNotEmpty() ) { - charMtrx2.rotatedWith(R); - } - } + ///@todo This rotation matrix is not flexible enough.. it can only work with full size matrices and doesn't allow for flexibility in the matrixassembler. + if ( R.isNotEmpty() ) { + charMtrx2.rotatedWith(R); + } + } #endif #ifdef DEBUG @@ -557,13 +541,12 @@ NlDEIDynamic :: computeMassMtrx(FloatArray &massMatrix, double &maxOm, TimeStep } #endif - n = loc.giveSize(); + int n = loc.giveSize(); #ifdef LOCAL_ZERO_MASS_REPLACEMENT - maxOmEl = 0.; double maxElmass = -1.0; - for ( j = 1; j <= n; j++ ) { + for ( int j = 1; j <= n; j++ ) { maxElmass = max( maxElmass, charMtrx.at(j, j) ); } @@ -571,30 +554,31 @@ NlDEIDynamic :: computeMassMtrx(FloatArray &massMatrix, double &maxOm, TimeStep OOFEM_WARNING("Element (%d) with zero (or negative) lumped mass encountered\n", i); } else { - if (charMtrx2.isNotEmpty() ) { - // in case stifness matrix defined, we can generate artificial mass - // in those DOFs without mass - for ( j = 1; j <= n; j++ ) { - if ( charMtrx.at(j, j) > maxElmass * ZERO_REL_MASS ) { - maxOmi = charMtrx2.at(j, j) / charMtrx.at(j, j); - maxOmEl = ( maxOmEl > maxOmi ) ? ( maxOmEl ) : ( maxOmi ); - } - } - - maxOm = ( maxOm > maxOmEl ) ? ( maxOm ) : ( maxOmEl ); - - for ( j = 1; j <= n; j++ ) { - jj = loc.at(j); - if ( ( jj ) && ( charMtrx.at(j, j) <= maxElmass * ZERO_REL_MASS ) ) { - charMtrx.at(j, j) = charMtrx2.at(j, j) / maxOmEl; - } + if (charMtrx2.isNotEmpty() ) { + // in case stifness matrix defined, we can generate artificial mass + // in those DOFs without mass + double maxOmEl = 0.; + for ( int j = 1; j <= n; j++ ) { + if ( charMtrx.at(j, j) > maxElmass * ZERO_REL_MASS ) { + double maxOmi = charMtrx2.at(j, j) / charMtrx.at(j, j); + maxOmEl = ( maxOmEl > maxOmi ) ? ( maxOmEl ) : ( maxOmi ); + } + } + + maxOm = ( maxOm > maxOmEl ) ? ( maxOm ) : ( maxOmEl ); + + for ( int j = 1; j <= n; j++ ) { + int jj = loc.at(j); + if ( ( jj ) && ( charMtrx.at(j, j) <= maxElmass * ZERO_REL_MASS ) ) { + charMtrx.at(j, j) = charMtrx2.at(j, j) / maxOmEl; + } + } } - } } #endif - for ( j = 1; j <= n; j++ ) { - jj = loc.at(j); + for ( int j = 1; j <= n; j++ ) { + int jj = loc.at(j); if ( jj ) { massMatrix.at(jj) += charMtrx.at(j, j); } @@ -605,20 +589,19 @@ NlDEIDynamic :: computeMassMtrx(FloatArray &massMatrix, double &maxOm, TimeStep // If init step - find minimun period of vibration in order to // determine maximal admisible time step // global variant - for ( i = 1; i <= nelem; i++ ) { - element = domain->giveElement(i); + for ( auto &element : domain->giveElements() ) { element->giveLocationArray(loc, en); element->giveCharacteristicMatrix(charMtrx, TangentStiffnessMatrix, tStep); if ( charMtrx.isNotEmpty() ) { - ///@todo This rotation matrix is not flexible enough.. it can only work with full size matrices and doesn't allow for flexibility in the matrixassembler. - if ( element->giveRotationMatrix(R) ) { - charMtrx.rotatedWith(R); - } + ///@todo This rotation matrix is not flexible enough.. it can only work with full size matrices and doesn't allow for flexibility in the matrixassembler. + if ( element->giveRotationMatrix(R) ) { + charMtrx.rotatedWith(R); + } } - n = loc.giveSize(); - for ( j = 1; j <= n; j++ ) { - jj = loc.at(j); + int n = loc.giveSize(); + for ( int j = 1; j <= n; j++ ) { + int jj = loc.at(j); if ( jj ) { diagonalStiffMtrx.at(jj) += charMtrx.at(j, j); } @@ -627,7 +610,7 @@ NlDEIDynamic :: computeMassMtrx(FloatArray &massMatrix, double &maxOm, TimeStep // Find find global minimun period of vibration double maxElmass = -1.0; - for ( j = 1; j <= n; j++ ) { + for ( int j = 1; j <= n; j++ ) { maxElmass = max( maxElmass, charMtrx.at(j, j) ); } @@ -635,15 +618,15 @@ NlDEIDynamic :: computeMassMtrx(FloatArray &massMatrix, double &maxOm, TimeStep OOFEM_ERROR("Element with zero (or negative) lumped mass encountered"); } - for ( j = 1; j <= neq; j++ ) { + for ( int j = 1; j <= neq; j++ ) { if ( massMatrix.at(j) > maxElmass * ZERO_REL_MASS ) { - maxOmi = diagonalStiffMtrx.at(j) / massMatrix.at(j); - maxOm = ( maxOm > maxOmi ) ? ( maxOm ) : ( maxOmi ); + double maxOmi = diagonalStiffMtrx.at(j) / massMatrix.at(j); + maxOm = ( maxOm > maxOmi ) ? ( maxOm ) : ( maxOmi ); } } // Set ZERO MASS members in massMatrix to value which corresponds to global maxOm. - for ( i = 1; i <= neq; i++ ) { + for ( int i = 1; i <= neq; i++ ) { if ( massMatrix.at(i) <= maxElmass * ZERO_REL_MASS ) { massMatrix.at(i) = diagonalStiffMtrx.at(i) / maxOm; } @@ -709,13 +692,11 @@ NlDEIDynamic :: estimateMaxPackSize(IntArray &commMap, DataStream &buff, int pac return 0; } -contextIOResultType NlDEIDynamic :: saveContext(DataStream &stream, ContextMode mode) +void NlDEIDynamic :: saveContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - if ( ( iores = StructuralEngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralEngngModel :: saveContext(stream, mode); if ( ( iores = previousIncrementOfDisplacementVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); @@ -736,61 +717,34 @@ contextIOResultType NlDEIDynamic :: saveContext(DataStream &stream, ContextMode if ( !stream.write(deltaT) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType NlDEIDynamic :: restoreContext(DataStream *stream, ContextMode mode, void *obj) +void NlDEIDynamic :: restoreContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - int closeFlag = 0; - int istep, iversion; - FILE *file = NULL; - this->resolveCorrespondingStepNumber(istep, iversion, obj); + StructuralEngngModel :: restoreContext(stream, mode); - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - - // Save element context. - if ( ( iores = StructuralEngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { + if ( ( iores = previousIncrementOfDisplacementVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = previousIncrementOfDisplacementVector.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = displacementVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = displacementVector.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = velocityVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = velocityVector.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = accelerationVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = accelerationVector.restoreYourself(*stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( !stream->read(deltaT) ) { + if ( !stream.read(deltaT) ) { THROW_CIOERR(CIO_IOERR); } - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } // ensure consistent records - - return CIO_OK; } diff --git a/src/sm/EngineeringModels/nldeidynamic.h b/src/sm/EngineeringModels/nldeidynamic.h index 432f546ca..4289addd1 100644 --- a/src/sm/EngineeringModels/nldeidynamic.h +++ b/src/sm/EngineeringModels/nldeidynamic.h @@ -35,12 +35,14 @@ #ifndef nldeidynamic_h #define nldeidynamic_h -#include "../sm/EngineeringModels/structengngmodel.h" +#include "sm/EngineeringModels/structengngmodel.h" #include "floatarray.h" #include "floatmatrix.h" #include "sparselinsystemnm.h" #include "sparsemtrxtype.h" +#include + #define LOCAL_ZERO_MASS_REPLACEMENT 1 ///@name Input fields for NlDEIDynamic @@ -52,6 +54,7 @@ #define _IFT_NlDEIDynamic_tau "tau" #define _IFT_NlDEIDynamic_py "py" #define _IFT_NlDEIDynamic_nonlocalext "nonlocalext" +#define _IFT_NlDEIDynamic_reduct "reduct" //@} namespace oofem { @@ -104,7 +107,8 @@ class NlDEIDynamic : public StructuralEngngModel double deltaT; /// Flag indicating the need for initialization. int initFlag; - + /// Optional reduction factor for time step deltaT + double reductionFactor; // dynamic relaxation specific vars /// Flag indicating whether dynamic relaxation takes place. int drFlag; @@ -121,39 +125,38 @@ class NlDEIDynamic : public StructuralEngngModel /// Product of p^tM^(-1)p; where p is reference load vector. double pMp; - SparseMtrx *massMatrixConsistent; LinSystSolverType solverType; SparseMtrxType sparseMtrxType; - SparseLinearSystemNM *nMethod; + std::unique_ptr nMethod; public: - NlDEIDynamic(int i, EngngModel * _master = NULL); + NlDEIDynamic(int i, EngngModel *master = nullptr); virtual ~NlDEIDynamic(); - virtual void solveYourself(); - virtual void solveYourselfAt(TimeStep *tStep); + void solveYourself() override; + void solveYourselfAt(TimeStep *tStep) override; - virtual void updateYourself(TimeStep *tStep); - virtual double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof); - virtual IRResultType initializeFrom(InputRecord *ir); + void updateYourself(TimeStep *tStep) override; + double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof) override; + void initializeFrom(InputRecord &ir) override; - virtual TimeStep *giveNextStep(); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + TimeStep *giveNextStep() override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; - virtual void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep); + void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep) override; // identification - virtual const char *giveInputRecordName() const { return _IFT_NlDEIDynamic_Name; } - virtual const char *giveClassName() const { return "NlDEIDynamic"; } - virtual fMode giveFormulation() { return TL; } + const char *giveInputRecordName() const { return _IFT_NlDEIDynamic_Name; } + const char *giveClassName() const override { return "NlDEIDynamic"; } + fMode giveFormulation() override { return TL; } - virtual int giveNumberOfFirstStep(bool force = false) { return 0; } + int giveNumberOfFirstStep(bool force = false) override { return 0; } protected: /** @@ -177,7 +180,7 @@ class NlDEIDynamic : public StructuralEngngModel void computeMassMtrx2(FloatMatrix &mass, double &maxOm, TimeStep *tStep); public: - virtual int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType); + int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType) override; }; } // end namespace oofem #endif // nldeidynamic_h diff --git a/src/sm/EngineeringModels/nlineardynamic.C b/src/sm/EngineeringModels/nlineardynamic.C index e77c5c9d8..97334d077 100644 --- a/src/sm/EngineeringModels/nlineardynamic.C +++ b/src/sm/EngineeringModels/nlineardynamic.C @@ -35,9 +35,9 @@ #include using namespace std; -#include "../sm/EngineeringModels/nlineardynamic.h" -#include "../sm/Elements/nlstructuralelement.h" -#include "../sm/Elements/structuralelementevaluator.h" +#include "sm/EngineeringModels/nlineardynamic.h" +#include "sm/Elements/nlstructuralelement.h" +#include "sm/Elements/structuralelementevaluator.h" #include "nummet.h" #include "timestep.h" #include "metastep.h" @@ -91,7 +91,7 @@ NumericalMethod *NonLinearDynamic :: giveNumericalMethod(MetaStep *mStep) if ( this->nMethod ) { this->nMethod->reinitialize(); } else { - this->nMethod.reset( new NRSolver(this->giveDomain(1), this) ); + this->nMethod = std::make_unique(this->giveDomain(1), this); } return this->nMethod.get(); @@ -101,9 +101,7 @@ NumericalMethod *NonLinearDynamic :: giveNumericalMethod(MetaStep *mStep) void NonLinearDynamic :: updateAttributes(MetaStep *mStep) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - InputRecord *ir = mStep->giveAttributesRecord(); + auto &ir = mStep->giveAttributesRecord(); StructuralEngngModel :: updateAttributes(mStep); @@ -121,15 +119,10 @@ NonLinearDynamic :: updateAttributes(MetaStep *mStep) } -IRResultType -NonLinearDynamic :: initializeFrom(InputRecord *ir) +void +NonLinearDynamic :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StructuralEngngModel :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralEngngModel :: initializeFrom(ir); int val = 0; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_lstype); @@ -163,8 +156,7 @@ NonLinearDynamic :: initializeFrom(InputRecord *ir) } else if ( initialTimeDiscretization == TD_ThreePointBackward ) { OOFEM_LOG_INFO("Selecting Three-point Backward Euler metod\n"); } else { - OOFEM_WARNING("Time-stepping scheme not found!"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_NonLinearDynamic_ddtScheme, "Time-stepping scheme not found!"); } MANRMSteps = 0; @@ -176,15 +168,13 @@ NonLinearDynamic :: initializeFrom(InputRecord *ir) communicator = new NodeCommunicator(this, commBuff, this->giveRank(), this->giveNumberOfProcesses()); - if ( ir->hasField(_IFT_NonLinearDynamic_nonlocalext) ) { + if ( ir.hasField(_IFT_NonLinearDynamic_nonlocalext) ) { nonlocalExt = 1; nonlocCommunicator = new ElementCommunicator(this, commBuff, this->giveRank(), this->giveNumberOfProcesses()); } } #endif - - return IRRT_OK; } @@ -253,7 +243,7 @@ TimeStep *NonLinearDynamic :: giveNextStep() } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(istep, this, mStepNum, totalTime, deltaTtmp, counter, td) ); + currentStep = std::make_unique(istep, this, mStepNum, totalTime, deltaTtmp, counter, td); return currentStep.get(); } @@ -350,7 +340,7 @@ NonLinearDynamic :: initializeYourself(TimeStep *tStep) } } } - this->giveInternalForces(internalForces, true, 1, tStep); + this->updateInternalRHS(internalForces, tStep, domain, &this->internalForcesEBENorm); } } @@ -371,9 +361,9 @@ NonLinearDynamic :: proceedStep(int di, TimeStep *tStep) // First assemble problem at current time step. // Option to take into account initial conditions. if ( !effectiveStiffnessMatrix ) { - effectiveStiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + effectiveStiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); // create mass matrix as compcol storage, need only mass multiplication by vector, not linear system solution. - massMatrix.reset( classFactory.createSparseMtrx(SMT_CompCol) ); + massMatrix = classFactory.createSparseMtrx(SMT_CompCol); } if ( !effectiveStiffnessMatrix || !massMatrix ) { @@ -557,6 +547,79 @@ void NonLinearDynamic :: updateYourself(TimeStep *tStep) StructuralEngngModel :: updateYourself(tStep); } + +void NonLinearDynamic :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) +{ + // No-op; this still assumes that the solution vector is passed by reference to the NRSolver. + //this->field->update(VM_Total, tStep, solutionVector, EModelDefaultEquationNumbering()); +} + + +void NonLinearDynamic :: updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) +{ +#ifdef VERBOSE + OOFEM_LOG_DEBUG("Updating internal RHS\n"); +#endif +#ifdef TIME_REPORT + Timer timer; + timer.startTimer(); +#endif + if ( ( currentIterations != 0 ) || ( totIterations == 0 ) ) { + StructuralEngngModel::updateInternalRHS(internalForces, tStep, d, eNorm); + + // Updating the residual vector @ NR-solver + help.beScaled(a0 + eta * a1, incrementOfDisplacement); + + massMatrix->times(help, rhs2); + + forcesVector = internalForces; + forcesVector.add(rhs2); + forcesVector.subtract(previousInternalForces); + + if ( delta != 0 ) { + help.beScaled(delta * a1, incrementOfDisplacement); + this->timesMtrx(help, rhs2, TangentStiffnessMatrix, this->giveDomain(1), tStep); + //this->assembleVector(rhs2, tStep, MatrixProductAssembler(TangentAssembler(), help), VM_Total, + // EModelDefaultEquationNumbering(), this->giveDomain(1)); + forcesVector.add(rhs2); + } + } +#ifdef TIME_REPORT + timer.stopTimer(); + OOFEM_LOG_DEBUG( "User time consumed by updating internal RHS: %.2fs\n", timer.getUtime() ); +#endif +} + + +void NonLinearDynamic :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) +{ + // Prevent assembly if already assembled ( totIterations > 0 ) + // Allow if MANRMSteps != 0 + if ( ( totIterations == 0 ) || MANRMSteps ) { +#ifdef VERBOSE + OOFEM_LOG_DEBUG("Updating effective stiffness matrix\n"); +#endif +#ifdef TIME_REPORT + Timer timer; + timer.startTimer(); +#endif +#if 1 + mat.zero(); + this->assemble(mat, tStep, EffectiveTangentAssembler(TangentStiffness, false, 1 + this->delta * a1, this->a0 + this->eta * this->a1), + EModelDefaultEquationNumbering(), d); +#else + this->assemble(mat, tStep, TangentStiffnessMatrix, EModelDefaultEquationNumbering(), d); + mat.times(1. + this->delta * a1); + mat.add(this->a0 + this->eta * this->a1, this->massMatrix); +#endif +#ifdef TIME_REPORT + timer.stopTimer(); + OOFEM_LOG_DEBUG( "User time consumed by updating nonlinear LHS: %.2fs\n", timer.getUtime() ); +#endif + } +} + + void NonLinearDynamic :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) // // Updates some component, which is used by numerical method @@ -605,7 +668,7 @@ void NonLinearDynamic :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Do timer.startTimer(); #endif if ( ( currentIterations != 0 ) || ( totIterations == 0 ) ) { - this->giveInternalForces(internalForces, true, d->giveNumber(), tStep); + StructuralEngngModel::updateInternalRHS(internalForces, tStep, d, &this->internalForcesEBENorm); // Updating the residual vector @ NR-solver help.beScaled(a0 + eta * a1, incrementOfDisplacement); @@ -664,13 +727,11 @@ NonLinearDynamic :: printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep) iDof->printMultipleOutputAt(stream, tStep, dofchar, dofmodes, 3); } -contextIOResultType NonLinearDynamic :: saveContext(DataStream &stream, ContextMode mode) +void NonLinearDynamic :: saveContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - if ( ( iores = EngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + EngngModel :: saveContext(stream, mode); if ( ( iores = incrementOfDisplacement.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); @@ -687,55 +748,30 @@ contextIOResultType NonLinearDynamic :: saveContext(DataStream &stream, ContextM if ( ( iores = accelerationVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType NonLinearDynamic :: restoreContext(DataStream *stream, ContextMode mode, void *obj) +void NonLinearDynamic :: restoreContext(DataStream &stream, ContextMode mode) { - int closeFlag = 0; - int istep, iversion; contextIOResultType iores; - FILE *file = NULL; - - this->resolveCorrespondingStepNumber(istep, iversion, obj); - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); - } - stream = new FileDataStream(file); - closeFlag = 1; - } - - if ( ( iores = EngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + EngngModel :: restoreContext(stream, mode); - if ( ( iores = incrementOfDisplacement.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = incrementOfDisplacement.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = totalDisplacement.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = totalDisplacement.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = velocityVector.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = velocityVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = accelerationVector.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = accelerationVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } // ensure consistent records - - return CIO_OK; } @@ -811,7 +847,7 @@ NonLinearDynamic :: timesMtrx(FloatArray &vec, FloatArray &answer, CharType type int nelem = domain->giveNumberOfElements(); //int neq = this->giveNumberOfDomainEquations(1, EModelDefaultEquationNumbering()); int jj, kk, n; - FloatMatrix charMtrx; + FloatMatrix charMtrx, R; IntArray loc; EModelDefaultEquationNumbering en; @@ -828,26 +864,33 @@ NonLinearDynamic :: timesMtrx(FloatArray &vec, FloatArray &answer, CharType type element->giveLocationArray(loc, en); element->giveCharacteristicMatrix(charMtrx, type, tStep); + + if ( charMtrx.isNotEmpty() ) { + ///@todo This rotation matrix is not flexible enough.. it can only work with full size matrices and doesn't allow for flexibility in the matrixassembler. + if ( element->giveRotationMatrix(R) ) { + charMtrx.rotatedWith(R); + } - // - // assemble it manually - // + // + // assemble it manually + // #ifdef DEBUG - if ( loc.giveSize() != charMtrx.giveNumberOfRows() ) { - OOFEM_ERROR("dimension mismatch"); - } + if ( loc.giveSize() != charMtrx.giveNumberOfRows() ) { + OOFEM_ERROR("dimension mismatch"); + } #endif - n = loc.giveSize(); + n = loc.giveSize(); - for ( int j = 1; j <= n; j++ ) { - jj = loc.at(j); - if ( jj ) { - for ( int k = 1; k <= n; k++ ) { - kk = loc.at(k); - if ( kk ) { - answer.at(jj) += charMtrx.at(j, k) * vec.at(kk); + for ( int j = 1; j <= n; j++ ) { + jj = loc.at(j); + if ( jj ) { + for ( int k = 1; k <= n; k++ ) { + kk = loc.at(k); + if ( kk ) { + answer.at(jj) += charMtrx.at(j, k) * vec.at(kk); + } } } } @@ -894,14 +937,14 @@ LoadBalancer * NonLinearDynamic :: giveLoadBalancer() { if ( lb ) { - return lb; + return lb.get(); } if ( loadBalancingFlag ) { lb = classFactory.createLoadBalancer( "parmetis", this->giveDomain(1) ); - return lb; + return lb.get(); } else { - return NULL; + return nullptr; } } @@ -910,14 +953,14 @@ LoadBalancerMonitor * NonLinearDynamic :: giveLoadBalancerMonitor() { if ( lbm ) { - return lbm; + return lbm.get(); } if ( loadBalancingFlag ) { lbm = classFactory.createLoadBalancerMonitor( "wallclock", this); - return lbm; + return lbm.get(); } else { - return NULL; + return nullptr; } } #endif diff --git a/src/sm/EngineeringModels/nlineardynamic.h b/src/sm/EngineeringModels/nlineardynamic.h index 07f102d55..cf44071bd 100644 --- a/src/sm/EngineeringModels/nlineardynamic.h +++ b/src/sm/EngineeringModels/nlineardynamic.h @@ -35,7 +35,7 @@ #ifndef nlineardynamic_h #define nlineardynamic_h -#include "../sm/EngineeringModels/structengngmodel.h" +#include "sm/EngineeringModels/structengngmodel.h" #include "sparsemtrxtype.h" #include "sparselinsystemnm.h" #include "sparsenonlinsystemnm.h" @@ -112,60 +112,63 @@ class NonLinearDynamic : public StructuralEngngModel double deltaT; public: - NonLinearDynamic(int i, EngngModel * _master = NULL); + NonLinearDynamic(int i, EngngModel *master = nullptr); virtual ~NonLinearDynamic(); - virtual void solveYourself(); - virtual void solveYourselfAt(TimeStep *tStep); + void solveYourself() override; + void solveYourselfAt(TimeStep *tStep) override; - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; + void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep) override; - virtual void updateYourself(TimeStep *tStep); - virtual void updateComponent(TimeStep *tStep, NumericalCmpn, Domain *d); - virtual void updateAttributes(MetaStep *mStep); - virtual void initializeYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; + void updateComponent(TimeStep *tStep, NumericalCmpn, Domain *d) override; + void updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) override; + void updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) override; + void updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) override; + void updateAttributes(MetaStep *mStep) override; + void initializeYourself(TimeStep *tStep) override; - virtual double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof); + double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual TimeStep *giveNextStep(); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + void initializeFrom(InputRecord &ir) override; + TimeStep *giveNextStep() override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void updateDomainLinks(); + void updateDomainLinks() override; // Identification - virtual const char *giveInputRecordName() const { return _IFT_NonLinearDynamic_Name; } - virtual const char *giveClassName() const { return "NonLinearDynamic"; } - virtual fMode giveFormulation() { return nonLinFormulation; } - virtual int useNonlocalStiffnessOption() { return this->nonlocalStiffnessFlag; } - virtual int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) { return ( int ) mode; } + const char *giveInputRecordName() const { return _IFT_NonLinearDynamic_Name; } + const char *giveClassName() const override { return "NonLinearDynamic"; } + fMode giveFormulation() override { return nonLinFormulation; } + int useNonlocalStiffnessOption() override { return this->nonlocalStiffnessFlag; } + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override { return ( int ) mode; } void timesMtrx(FloatArray &answer, FloatArray &vec, CharType type, Domain *domain, TimeStep *tStep); TimeDiscretizationType giveInitialTimeDiscretization() { return initialTimeDiscretization; } #ifdef __OOFEG - virtual void showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep); + void showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep) override; #endif - virtual int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType); + int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType) override; #ifdef __PARALLEL_MODE - virtual LoadBalancer *giveLoadBalancer(); - virtual LoadBalancerMonitor *giveLoadBalancerMonitor(); + LoadBalancer *giveLoadBalancer() override; + LoadBalancerMonitor *giveLoadBalancerMonitor() override; #endif protected: void assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma, - const UnknownNumberingScheme &, Domain *domain); + const UnknownNumberingScheme &, Domain *domain) override; void proceedStep(int di, TimeStep *tStep); void determineConstants(TimeStep *tStep); - virtual void packMigratingData(TimeStep *tStep); - virtual void unpackMigratingData(TimeStep *tStep); + void packMigratingData(TimeStep *tStep) override; + void unpackMigratingData(TimeStep *tStep) override; }; } // end namespace oofem #endif // nlineardynamic_h diff --git a/src/sm/EngineeringModels/nlinearstatic.C b/src/sm/EngineeringModels/nlinearstatic.C index 63e77cfdc..a1976f8a5 100644 --- a/src/sm/EngineeringModels/nlinearstatic.C +++ b/src/sm/EngineeringModels/nlinearstatic.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/nlinearstatic.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/EngineeringModels/nlinearstatic.h" +#include "sm/Elements/structuralelement.h" #include "nummet.h" #include "timestep.h" #include "metastep.h" @@ -53,6 +53,7 @@ #include "dofmanager.h" #include "dof.h" #include "unknownnumberingscheme.h" +#include "function.h" #ifdef __PARALLEL_MODE #include "problemcomm.h" @@ -93,8 +94,6 @@ NonLinearStatic :: ~NonLinearStatic() NumericalMethod *NonLinearStatic :: giveNumericalMethod(MetaStep *mStep) { - IRResultType result; // Required by IR_GIVE_FIELD macro - if ( mStep == NULL ) { OOFEM_ERROR("undefined meta step"); } @@ -135,10 +134,8 @@ NumericalMethod *NonLinearStatic :: giveNumericalMethod(MetaStep *mStep) void NonLinearStatic :: updateAttributes(MetaStep *mStep) { - IRResultType result; // Required by IR_GIVE_FIELD macro - MetaStep *mStep1 = this->giveMetaStep( mStep->giveNumber() ); //this line ensures correct input file in staggered problem - InputRecord *ir = mStep1->giveAttributesRecord(); + auto &ir = mStep1->giveAttributesRecord(); LinearStatic :: updateAttributes(mStep1); @@ -172,6 +169,9 @@ NonLinearStatic :: updateAttributes(MetaStep *mStep) OOFEM_ERROR("deltaT < 0"); } + dtFunction = 0; + IR_GIVE_OPTIONAL_FIELD(ir, dtFunction, _IFT_NonLinearStatic_deltatfunction); + _val = nls_tangentStiffness; IR_GIVE_OPTIONAL_FIELD(ir, _val, _IFT_NonLinearStatic_stiffmode); this->stiffMode = ( NonLinearStatic_stiffnessMode ) _val; @@ -180,47 +180,40 @@ NonLinearStatic :: updateAttributes(MetaStep *mStep) IR_GIVE_OPTIONAL_FIELD(ir, _val, _IFT_NonLinearStatic_refloadmode); this->refLoadInputMode = ( SparseNonLinearSystemNM :: referenceLoadInputModeType ) _val; - mstepCumulateLoadLevelFlag = ir->hasField(_IFT_NonLinearStatic_keepll); + mstepCumulateLoadLevelFlag = ir.hasField(_IFT_NonLinearStatic_keepll); // called just to mark field as recognized, used later - ir->hasField(_IFT_NonLinearStatic_donotfixload); + ir.hasField(_IFT_NonLinearStatic_donotfixload); } -IRResultType -NonLinearStatic :: initializeFrom(InputRecord *ir) +void +NonLinearStatic :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = LinearStatic :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + LinearStatic :: initializeFrom(ir); nonlocalStiffnessFlag = 0; IR_GIVE_OPTIONAL_FIELD(ir, nonlocalStiffnessFlag, _IFT_NonLinearStatic_nonlocstiff); updateElasticStiffnessFlag = false; - if ( ir->hasField(_IFT_NonLinearStatic_updateElasticStiffnessFlag) ) { - updateElasticStiffnessFlag = true; + if ( ir.hasField(_IFT_NonLinearStatic_updateElasticStiffnessFlag) ) { + updateElasticStiffnessFlag = true; } - + #ifdef __PARALLEL_MODE if ( isParallel() ) { //commBuff = new CommunicatorBuff (this->giveNumberOfProcesses(), CBT_dynamic); commBuff = new CommunicatorBuff(this->giveNumberOfProcesses(), CBT_static); - communicator = new NodeCommunicator(this, commBuff, this->giveRank(), - this->giveNumberOfProcesses()); + communicator = new NodeCommunicator( this, commBuff, this->giveRank(), + this->giveNumberOfProcesses() ); - if ( ir->hasField(_IFT_NonLinearStatic_nonlocalext) ) { + if ( ir.hasField(_IFT_NonLinearStatic_nonlocalext) ) { nonlocalExt = 1; - nonlocCommunicator = new ElementCommunicator(this, commBuff, this->giveRank(), - this->giveNumberOfProcesses()); + nonlocCommunicator = new ElementCommunicator( this, commBuff, this->giveRank(), + this->giveNumberOfProcesses() ); } } #endif - - return IRRT_OK; } @@ -228,63 +221,73 @@ double NonLinearStatic :: giveUnknownComponent(ValueModeType mode, TimeStep *tSt // returns unknown quantity like displacement, velocity of equation eq // This function translates this request to numerical method language { - int eq = dof->__giveEquationNumber(); -#ifdef DEBUG - if ( eq == 0 ) { - OOFEM_ERROR("invalid equation number"); - } -#endif - - if ( tStep != this->giveCurrentStep() ) { OOFEM_ERROR("unknown time step encountered"); return 0.; } - switch ( mode ) { - case VM_Incremental: - // return incrementOfDisplacement -> at(eq); - // return nMethod-> giveUnknownComponent(IncrementOfSolution, eq); - if ( incrementOfDisplacement.isNotEmpty() ) { - return incrementOfDisplacement.at(eq); + int eq = dof->__giveEquationNumber(); + if (mode == VM_Residual) { + // evaluate the residual of momentum balance for specific unknown + // evaluate the residual of momentum balance for specific unknown + + if (eq && internalForces.isNotEmpty()) { + double ans = loadLevel*incrementalLoadVector.at(eq)-internalForces.at(eq); + if (initialLoadVector.isNotEmpty()) { + ans += initialLoadVector.at(eq); + } + return ans; } else { return 0.; } - - case VM_Total: + } else if (mode == VM_Total) { +#ifdef DEBUG + if ( eq == 0 ) OOFEM_ERROR("invalid equation number"); +#endif if ( totalDisplacement.isNotEmpty() ) { return totalDisplacement.at(eq); } else { return 0.; } - - case VM_Velocity: + } else if (mode == VM_Incremental) { +#ifdef DEBUG + if ( eq == 0 ) OOFEM_ERROR("invalid equation number"); +#endif + // return incrementOfDisplacement -> at(eq); + // return nMethod-> giveUnknownComponent(IncrementOfSolution, eq); + if ( incrementOfDisplacement.isNotEmpty() ) { + return incrementOfDisplacement.at(eq); + } else { + return 0.; + } + } else if (mode == VM_Velocity) { +#ifdef DEBUG + if ( eq == 0 ) OOFEM_ERROR("invalid equation number"); +#endif if ( incrementOfDisplacement.isNotEmpty() ) { return incrementOfDisplacement.at(eq) / tStep->giveTimeIncrement(); } else { return 0.; } - - default: - OOFEM_ERROR("Unknown is of undefined ValueModeType for this problem"); + } else { + OOFEM_ERROR("Unknown is of undefined ValueModeType for this problem"); } - return 0.0; } TimeStep *NonLinearStatic :: giveSolutionStepWhenIcApply(bool force) { - if ( master && (!force)) { - return master->giveSolutionStepWhenIcApply(); - } else { - if ( !stepWhenIcApply ) { - int inin = giveNumberOfTimeStepWhenIcApply(); - // int nFirst = giveNumberOfFirstStep(); - stepWhenIcApply.reset(new TimeStep(inin, this, 0, -deltaT, deltaT, 0)); - } + if ( master && ( !force ) ) { + return master->giveSolutionStepWhenIcApply(); + } else { + if ( !stepWhenIcApply ) { + int inin = giveNumberOfTimeStepWhenIcApply(); + // int nFirst = giveNumberOfFirstStep(); + stepWhenIcApply = std :: make_unique< TimeStep >(inin, this, 0, -deltaT, deltaT, 0); + } - return stepWhenIcApply.get(); - } + return stepWhenIcApply.get(); + } } @@ -294,19 +297,16 @@ TimeStep *NonLinearStatic :: giveNextStep() int mStepNum = 1; double totalTime = 0.0; StateCounterType counter = 1; - double deltaTtmp = deltaT; - - //do not increase deltaT on microproblem - if ( pScale == microScale ) { - deltaTtmp = 0.; - } + // double deltaTtmp = deltaT; + double deltaTtmp = this->giveDeltaT(istep); if ( currentStep ) { - totalTime = currentStep->giveTargetTime() + deltaTtmp; istep = currentStep->giveNumber() + 1; + deltaTtmp = this->giveDeltaT(istep); + totalTime = currentStep->giveTargetTime() + deltaTtmp; counter = currentStep->giveSolutionStateCounter() + 1; mStepNum = currentStep->giveMetaStepNumber(); - + if ( !this->giveMetaStep(mStepNum)->isStepValid(istep) ) { mStepNum++; if ( mStepNum > nMetaSteps ) { @@ -316,26 +316,54 @@ TimeStep *NonLinearStatic :: giveNextStep() } else { // first step -> generate initial step TimeStep *newStep = giveSolutionStepWhenIcApply(); - currentStep.reset(new TimeStep(*newStep)); + currentStep = std :: make_unique< TimeStep >(* newStep); } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(istep, this, mStepNum, totalTime, deltaTtmp, counter) ); + currentStep = std :: make_unique< TimeStep >(istep, this, mStepNum, totalTime, deltaTtmp, counter); // dt variable are set eq to 0 for statics - has no meaning // *Wrong* It has meaning for viscoelastic materials. return currentStep.get(); } +Function * +NonLinearStatic :: giveDtFunction() +// Returns the load-time function of the receiver. +{ + if ( !dtFunction ) { + return NULL; + } + + return giveDomain(1)->giveFunction(dtFunction); +} + + +double +NonLinearStatic :: giveDeltaT(int n) +{ + + //do not increase deltaT on microproblem + if ( pScale == microScale ) { + return 0.; + } + + if ( giveDtFunction() ) { + return giveDtFunction()->evaluateAtTime(n); + } + + return deltaT; +} + void NonLinearStatic :: solveYourself() { if ( this->isParallel() ) { - #ifdef __VERBOSE_PARALLEL +#ifdef __VERBOSE_PARALLEL // force equation numbering before setting up comm maps int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); OOFEM_LOG_INFO("[process rank %d] neq is %d\n", this->giveRank(), neq); - #endif +#endif // set up communication patterns this->initializeCommMaps(); @@ -369,9 +397,9 @@ NonLinearStatic :: updateLoadVectors(TimeStep *tStep) bool isLastMetaStep = ( tStep->giveNumber() == mstep->giveLastStepNumber() ); if ( controlMode == nls_indirectControl ) { - //if ((tStep->giveNumber() == mstep->giveLastStepNumber()) && ir->hasField("fixload")) { + //if ((tStep->giveNumber() == mstep->giveLastStepNumber()) &&ir.hasField("fixload")) { if ( isLastMetaStep ) { - if ( !mstep->giveAttributesRecord()->hasField(_IFT_NonLinearStatic_donotfixload) ) { + if ( !mstep->giveAttributesRecord().hasField(_IFT_NonLinearStatic_donotfixload) ) { OOFEM_LOG_INFO("Fixed load level\n"); //update initialLoadVector @@ -404,7 +432,7 @@ NonLinearStatic :: updateLoadVectors(TimeStep *tStep) // if (isLastMetaStep) { - if ( isLastMetaStep && !mstep->giveAttributesRecord()->hasField(_IFT_NonLinearStatic_donotfixload) ) { + if ( isLastMetaStep && !mstep->giveAttributesRecord().hasField(_IFT_NonLinearStatic_donotfixload) ) { #ifdef VERBOSE OOFEM_LOG_INFO("Reseting load level\n"); #endif @@ -433,7 +461,7 @@ NonLinearStatic :: proceedStep(int di, TimeStep *tStep) // first step create space for stiffness Matrix // if ( !stiffnessMatrix ) { - stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); } if ( !stiffnessMatrix ) { @@ -503,13 +531,13 @@ NonLinearStatic :: proceedStep(int di, TimeStep *tStep) #ifdef VERBOSE OOFEM_LOG_RELEVANT("Computing initial guess\n"); #endif - FloatArray extrapolatedForces; + FloatArray extrapolatedForces; this->assemblePrescribedExtrapolatedForces( extrapolatedForces, tStep, TangentStiffnessMatrix, this->giveDomain(di) ); extrapolatedForces.negated(); - this->updateComponent( tStep, NonLinearLhs, this->giveDomain(di) ); + this->updateMatrix( * stiffnessMatrix, tStep, this->giveDomain(di) ); SparseLinearSystemNM *linSolver = nMethod->giveLinearSolver(); OOFEM_LOG_RELEVANT("solving for increment\n"); - linSolver->solve(*stiffnessMatrix, extrapolatedForces, incrementOfDisplacement); + linSolver->solve(* stiffnessMatrix, extrapolatedForces, incrementOfDisplacement); OOFEM_LOG_RELEVANT("initial guess found\n"); totalDisplacement.add(incrementOfDisplacement); } else if ( this->initialGuessType != IG_None ) { @@ -520,21 +548,60 @@ NonLinearStatic :: proceedStep(int di, TimeStep *tStep) //totalDisplacement.printYourself(); if ( initialLoadVector.isNotEmpty() ) { - numMetStatus = nMethod->solve(*stiffnessMatrix, incrementalLoadVector, & initialLoadVector, + numMetStatus = nMethod->solve(* stiffnessMatrix, incrementalLoadVector, & initialLoadVector, totalDisplacement, incrementOfDisplacement, internalForces, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, tStep); } else { - numMetStatus = nMethod->solve(*stiffnessMatrix, incrementalLoadVector, NULL, + numMetStatus = nMethod->solve(* stiffnessMatrix, incrementalLoadVector, NULL, totalDisplacement, incrementOfDisplacement, internalForces, internalForcesEBENorm, loadLevel, refLoadInputMode, currentIterations, tStep); } - ///@todo Martin: ta bort!!! - //this->updateComponent(tStep, NonLinearLhs, this->giveDomain(di)); - ///@todo Use temporary variables. updateYourself() should set the final values, while proceedStep should be callable multiple times for each step (if necessary). / Mikael OOFEM_LOG_RELEVANT("Equilibrium reached at load level = %f in %d iterations\n", cumulatedLoadLevel + loadLevel, currentIterations); prevStepLength = currentStepLength; } + +void +NonLinearStatic :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) +{ + // No-op: This can't really be supported in any nice way in nlinearstatic. +} + + +void +NonLinearStatic :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) +{ + if ( stiffMode == nls_tangentStiffness ) { + mat.zero(); // zero stiffness matrix +#ifdef VERBOSE + OOFEM_LOG_DEBUG("Assembling tangent stiffness matrix\n"); +#endif + this->assemble(mat, tStep, TangentAssembler(TangentStiffness), EModelDefaultEquationNumbering(), d); + } else if ( ( stiffMode == nls_secantStiffness ) || ( stiffMode == nls_secantInitialStiffness && initFlag ) ) { +#ifdef VERBOSE + OOFEM_LOG_DEBUG("Assembling secant stiffness matrix\n"); +#endif + mat.zero(); // zero stiffness matrix + this->assemble(mat, tStep, TangentAssembler(SecantStiffness), EModelDefaultEquationNumbering(), d); + initFlag = 0; + } else if ( ( stiffMode == nls_elasticStiffness ) && ( initFlag || + ( this->giveMetaStep( tStep->giveMetaStepNumber() )->giveFirstStepNumber() == tStep->giveNumber() ) || ( updateElasticStiffnessFlag ) ) ) { +#ifdef VERBOSE + OOFEM_LOG_DEBUG("Assembling elastic stiffness matrix\n"); +#endif + mat.zero(); // zero stiffness matrix + this->assemble(mat, tStep, TangentAssembler(ElasticStiffness), + EModelDefaultEquationNumbering(), d); + initFlag = 0; + } else { + // currently no action , this method is mainly intended to + // assemble new tangent stiffness after each iteration + // when secantStiffMode is on, we use the same stiffness + // during iteration process + } +} + + void NonLinearStatic :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) // @@ -551,23 +618,23 @@ NonLinearStatic :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain * #ifdef VERBOSE OOFEM_LOG_DEBUG("Assembling tangent stiffness matrix\n"); #endif - this->assemble(*stiffnessMatrix, tStep, TangentAssembler(TangentStiffness), + this->assemble(* stiffnessMatrix, tStep, TangentAssembler(TangentStiffness), EModelDefaultEquationNumbering(), d); } else if ( ( stiffMode == nls_secantStiffness ) || ( stiffMode == nls_secantInitialStiffness && initFlag ) ) { #ifdef VERBOSE OOFEM_LOG_DEBUG("Assembling secant stiffness matrix\n"); #endif stiffnessMatrix->zero(); // zero stiffness matrix - this->assemble(*stiffnessMatrix, tStep, TangentAssembler(SecantStiffness), + this->assemble(* stiffnessMatrix, tStep, TangentAssembler(SecantStiffness), EModelDefaultEquationNumbering(), d); initFlag = 0; } else if ( ( stiffMode == nls_elasticStiffness ) && ( initFlag || - ( this->giveMetaStep( tStep->giveMetaStepNumber() )->giveFirstStepNumber() == tStep->giveNumber() ) || (updateElasticStiffnessFlag) ) ) { + ( this->giveMetaStep( tStep->giveMetaStepNumber() )->giveFirstStepNumber() == tStep->giveNumber() ) || ( updateElasticStiffnessFlag ) ) ) { #ifdef VERBOSE OOFEM_LOG_DEBUG("Assembling elastic stiffness matrix\n"); #endif stiffnessMatrix->zero(); // zero stiffness matrix - this->assemble(*stiffnessMatrix, tStep, TangentAssembler(ElasticStiffness), + this->assemble(* stiffnessMatrix, tStep, TangentAssembler(ElasticStiffness), EModelDefaultEquationNumbering(), d); initFlag = 0; } else { @@ -583,7 +650,14 @@ NonLinearStatic :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain * OOFEM_LOG_DEBUG("Updating internal forces\n"); #endif // update internalForces and internalForcesEBENorm concurrently - this->giveInternalForces(internalForces, true, d->giveNumber(), tStep); + this->updateInternalRHS(internalForces, tStep, d, & this->internalForcesEBENorm); + break; + + case ExternalRhs: +#ifdef VERBOSE + OOFEM_LOG_DEBUG("Updating external forces\n"); +#endif + this->assembleIncrementalReferenceLoadVectors(incrementalLoadVector, incrementalLoadVectorOfPrescribed, this->refLoadInputMode, d, tStep); break; default: @@ -599,7 +673,7 @@ NonLinearStatic :: printOutputAt(FILE *file, TimeStep *tStep) return; // do not print even Solution step header } - fprintf(file, "\n\nOutput for time %.3e, solution step number %d\n", tStep->giveTargetTime(), tStep->giveNumber() ); + fprintf( file, "\n\nOutput for time %.3e, solution step number %d\n", tStep->giveTargetTime(), tStep->giveNumber() ); fprintf(file, "Reached load level : %20.6f in %d iterations\n\n", cumulatedLoadLevel + loadLevel, currentIterations); @@ -611,14 +685,12 @@ NonLinearStatic :: printOutputAt(FILE *file, TimeStep *tStep) } -contextIOResultType +void NonLinearStatic :: saveContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - if ( ( iores = EngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + EngngModel :: saveContext(stream, mode); if ( ( iores = totalDisplacement.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); @@ -648,78 +720,49 @@ NonLinearStatic :: saveContext(DataStream &stream, ContextMode mode) if ( ( iores = initialLoadVectorOfPrescribed.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -NonLinearStatic :: restoreContext(DataStream *stream, ContextMode mode, void *obj) -// -// restore state variable - displacement vector -// +void +NonLinearStatic :: restoreContext(DataStream &stream, ContextMode mode) { - int closeFlag = 0; - int istep, iversion; contextIOResultType iores; - FILE *file = NULL; - - this->resolveCorrespondingStepNumber(istep, iversion, obj); - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - // save element context - if ( ( iores = EngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + EngngModel :: restoreContext(stream, mode); //if ((iores = this->giveNumericalMethod(giveCurrentStep())->restoreContext (stream)) !=CIO_OK) THROW_CIOERR(iores); - if ( ( iores = totalDisplacement.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = totalDisplacement.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = incrementOfDisplacement.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = incrementOfDisplacement.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } int _cm; - if ( !stream->read(_cm) ) { + if ( !stream.read(_cm) ) { THROW_CIOERR(CIO_IOERR); } controlMode = ( NonLinearStatic_controlType ) _cm; - if ( !stream->read(loadLevel) ) { + if ( !stream.read(loadLevel) ) { THROW_CIOERR(CIO_IOERR); } - if ( !stream->read(cumulatedLoadLevel) ) { + if ( !stream.read(cumulatedLoadLevel) ) { THROW_CIOERR(CIO_IOERR); } // store InitialLoadVector - if ( ( iores = initialLoadVector.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = initialLoadVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - if ( ( iores = initialLoadVectorOfPrescribed.restoreYourself(*stream) ) != CIO_OK ) { + if ( ( iores = initialLoadVectorOfPrescribed.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } // ensure consistent records - - return CIO_OK; } @@ -749,7 +792,7 @@ NonLinearStatic :: assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAss LinearStatic :: assemble(answer, tStep, ma, s, domain); - if ( ( nonlocalStiffnessFlag ) && dynamic_cast< const TangentAssembler* >(&ma) ) { + if ( ( nonlocalStiffnessFlag ) && dynamic_cast< const TangentAssembler * >(& ma) ) { // add nonlocal contribution for ( auto &elem : domain->giveElements() ) { static_cast< StructuralElement * >( elem.get() )->addNonlocalStiffnessContributions(answer, s, tStep); @@ -845,9 +888,9 @@ NonLinearStatic :: estimateMaxPackSize(IntArray &commMap, DataStream &buff, int Domain *domain = this->giveDomain(1); if ( packUnpackType == 0 ) { ///@todo Fix this old ProblemCommMode__NODE_CUT value - for ( int map: commMap ) { - DofManager *dman = domain->giveDofManager( map ); - for ( Dof *dof: *dman ) { + for ( int map : commMap ) { + DofManager *dman = domain->giveDofManager(map); + for ( Dof *dof : *dman ) { if ( dof->isPrimaryDof() && ( dof->__giveEquationNumber() ) ) { count++; } else { @@ -859,8 +902,8 @@ NonLinearStatic :: estimateMaxPackSize(IntArray &commMap, DataStream &buff, int //printf ("\nestimated count is %d\n",count); return ( buff.givePackSizeOfDouble(1) * max(count, pcount) ); } else if ( packUnpackType == 1 ) { - for ( int map: commMap ) { - count += domain->giveElement( map )->estimatePackSize(buff); + for ( int map : commMap ) { + count += domain->giveElement(map)->estimatePackSize(buff); } return count; @@ -875,15 +918,15 @@ LoadBalancer * NonLinearStatic :: giveLoadBalancer() { if ( lb ) { - return lb; + return lb.get(); } if ( loadBalancingFlag ) { ///@todo Make the name possibly optional (but currently, there is just one choice, "parmetis") lb = classFactory.createLoadBalancer( "parmetis", this->giveDomain(1) ); - return lb; + return lb.get(); } else { - return NULL; + return nullptr; } } @@ -892,14 +935,14 @@ LoadBalancerMonitor * NonLinearStatic :: giveLoadBalancerMonitor() { if ( lbm ) { - return lbm; + return lbm.get(); } if ( loadBalancingFlag ) { - lbm = classFactory.createLoadBalancerMonitor( "wallclock", this); - return lbm; + lbm = classFactory.createLoadBalancerMonitor("wallclock", this); + return lbm.get(); } else { - return NULL; + return nullptr; } } #endif @@ -914,7 +957,7 @@ NonLinearStatic :: packMigratingData(TimeStep *tStep) for ( int idofman = 1; idofman <= ndofman; idofman++ ) { DofManager *_dm = domain->giveDofManager(idofman); - for ( Dof *_dof: *_dm ) { + for ( Dof *_dof : *_dm ) { if ( _dof->isPrimaryDof() ) { int _eq; if ( ( _eq = _dof->__giveEquationNumber() ) ) { @@ -961,16 +1004,16 @@ NonLinearStatic :: unpackMigratingData(TimeStep *tStep) for ( int idofman = 1; idofman <= ndofman; idofman++ ) { DofManager *_dm = domain->giveDofManager(idofman); - for ( Dof *_dof: *_dm ) { + for ( Dof *_dof : *_dm ) { if ( _dof->isPrimaryDof() ) { int _eq; if ( ( _eq = _dof->__giveEquationNumber() ) ) { // pack values in solution vectors - totalDisplacement.at(_eq) = _dof->giveUnknownsDictionaryValue( tStep, VM_Total ); - initialLoadVector.at(_eq) = _dof->giveUnknownsDictionaryValue( tStep, VM_RhsInitial ); - incrementalLoadVector.at(_eq) = _dof->giveUnknownsDictionaryValue( tStep, VM_RhsIncremental ); + totalDisplacement.at(_eq) = _dof->giveUnknownsDictionaryValue(tStep, VM_Total); + initialLoadVector.at(_eq) = _dof->giveUnknownsDictionaryValue(tStep, VM_RhsInitial); + incrementalLoadVector.at(_eq) = _dof->giveUnknownsDictionaryValue(tStep, VM_RhsIncremental); - #if 0 +#if 0 // debug print if ( _dm->giveParallelMode() == DofManager_shared ) { fprintf(stderr, "[%d] Shared: %d(%d) -> %d\n", myrank, idofman, idof, _eq); @@ -978,16 +1021,16 @@ NonLinearStatic :: unpackMigratingData(TimeStep *tStep) fprintf(stderr, "[%d] Local : %d(%d) -> %d\n", myrank, idofman, idof, _eq); } - #endif +#endif } else if ( ( _eq = _dof->__givePrescribedEquationNumber() ) ) { // pack values in prescribed solution vectors - initialLoadVectorOfPrescribed.at(_eq) = _dof->giveUnknownsDictionaryValue( tStep, VM_RhsInitial ); - incrementalLoadVectorOfPrescribed.at(_eq) = _dof->giveUnknownsDictionaryValue( tStep, VM_RhsIncremental ); + initialLoadVectorOfPrescribed.at(_eq) = _dof->giveUnknownsDictionaryValue(tStep, VM_RhsInitial); + incrementalLoadVectorOfPrescribed.at(_eq) = _dof->giveUnknownsDictionaryValue(tStep, VM_RhsIncremental); - #if 0 +#if 0 // debug print fprintf(stderr, "[%d] %d(%d) -> %d\n", myrank, idofman, idof, -_eq); - #endif +#endif } } // end primary dof } // end dof loop @@ -1002,5 +1045,4 @@ NonLinearStatic :: unpackMigratingData(TimeStep *tStep) initFlag = true; } - } // end namespace oofem diff --git a/src/sm/EngineeringModels/nlinearstatic.h b/src/sm/EngineeringModels/nlinearstatic.h index d5fa8eab1..e87638cd9 100644 --- a/src/sm/EngineeringModels/nlinearstatic.h +++ b/src/sm/EngineeringModels/nlinearstatic.h @@ -35,14 +35,16 @@ #ifndef nlinearstatic_h #define nlinearstatic_h -#include "../sm/EngineeringModels/linearstatic.h" +#include "sm/EngineeringModels/linearstatic.h" #include "sparsenonlinsystemnm.h" +#include "function.h" ///@name Input fields for NonLinearStatic //@{ #define _IFT_NonLinearStatic_Name "nonlinearstatic" #define _IFT_NonLinearStatic_controlmode "controlmode" #define _IFT_NonLinearStatic_deltat "deltat" +#define _IFT_NonLinearStatic_deltatfunction "deltatfunction" #define _IFT_NonLinearStatic_stiffmode "stiffmode" #define _IFT_NonLinearStatic_refloadmode "refloadmode" #define _IFT_NonLinearStatic_keepll "keepll" @@ -118,6 +120,8 @@ class NonLinearStatic : public LinearStatic NonLinearStatic_controlType controlMode; /// Intrinsic time increment. double deltaT; + /// Associated time function for time step increment. + int dtFunction; /** * The following parameter allows to specify how the reference load vector @@ -134,63 +138,67 @@ class NonLinearStatic : public LinearStatic InitialGuess initialGuessType; public: - NonLinearStatic(int i, EngngModel * _master = NULL); + NonLinearStatic(int i, EngngModel *master = nullptr); virtual ~NonLinearStatic(); - virtual void solveYourself(); - virtual void solveYourselfAt(TimeStep *tStep); - virtual void terminate(TimeStep *tStep); + Function *giveDtFunction(); + double giveDeltaT(int n); + void solveYourself() override; + void solveYourselfAt(TimeStep *tStep) override; + void terminate(TimeStep *tStep) override; - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; - virtual void updateComponent(TimeStep *tStep, NumericalCmpn, Domain *d); - virtual void updateAttributes(MetaStep *mStep); + void updateComponent(TimeStep *tStep, NumericalCmpn, Domain *d) override; + void updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) override; + void updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) override; + void updateAttributes(MetaStep *mStep) override; - virtual double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual TimeStep *giveSolutionStepWhenIcApply(bool force = false); - virtual TimeStep *giveNextStep(); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof) override; + void initializeFrom(InputRecord &ir) override; + TimeStep *giveSolutionStepWhenIcApply(bool force = false) override; + TimeStep *giveNextStep() override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual double giveLoadLevel() { return cumulatedLoadLevel + loadLevel; } + double giveLoadLevel() override { return cumulatedLoadLevel + loadLevel; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void updateDomainLinks(); + void updateDomainLinks() override; // identification - virtual const char *giveClassName() const { return "NonLinearStatic"; } - virtual fMode giveFormulation() { return nonLinFormulation; } - virtual int useNonlocalStiffnessOption() { return this->nonlocalStiffnessFlag; } + const char *giveClassName() const override { return "NonLinearStatic"; } + fMode giveFormulation() override { return nonLinFormulation; } + int useNonlocalStiffnessOption() override { return this->nonlocalStiffnessFlag; } /// For load balancing purposes we store all values so hash is computed from mode value only - virtual int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) { return ( int ) mode; } - virtual int giveCurrentNumberOfIterations() {return currentIterations;} + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override { return ( int ) mode; } + int giveCurrentNumberOfIterations() override { return currentIterations; } #ifdef __OOFEG - virtual void showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep); + void showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep) override; #endif - virtual int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType); + int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType) override; #ifdef __PARALLEL_MODE - virtual LoadBalancer *giveLoadBalancer(); - virtual LoadBalancerMonitor *giveLoadBalancerMonitor(); + LoadBalancer *giveLoadBalancer() override; + LoadBalancerMonitor *giveLoadBalancerMonitor() override; #endif protected: - virtual void assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma, - const UnknownNumberingScheme &, Domain *domain); + void assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma, + const UnknownNumberingScheme &, Domain *domain) override; void proceedStep(int di, TimeStep *tStep); virtual void updateLoadVectors(TimeStep *tStep); - virtual void computeExternalLoadReactionContribution(FloatArray &reactions, TimeStep *tStep, int di); + void computeExternalLoadReactionContribution(FloatArray &reactions, TimeStep *tStep, int di) override; void assembleIncrementalReferenceLoadVectors(FloatArray &_incrementalLoadVector, FloatArray &_incrementalLoadVectorOfPrescribed, SparseNonLinearSystemNM :: referenceLoadInputModeType _refMode, Domain *sourceDomain, TimeStep *tStep); - virtual void packMigratingData(TimeStep *tStep); - virtual void unpackMigratingData(TimeStep *tStep); + void packMigratingData(TimeStep *tStep) override; + void unpackMigratingData(TimeStep *tStep) override; }; } // end namespace oofem #endif // nlinearstatic_h diff --git a/src/sm/EngineeringModels/pdelta.C b/src/sm/EngineeringModels/pdelta.C new file mode 100644 index 000000000..ab77cd2e1 --- /dev/null +++ b/src/sm/EngineeringModels/pdelta.C @@ -0,0 +1,184 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/EngineeringModels/pdelta.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelementevaluator.h" +#include "nummet.h" +#include "timestep.h" +#include "element.h" +#include "dof.h" +#include "sparsemtrx.h" +#include "verbose.h" +#include "classfactory.h" +#include "datastream.h" +#include "contextioerr.h" +#include "classfactory.h" +#include "unknownnumberingscheme.h" + +#ifdef __PARALLEL_MODE + #include "problemcomm.h" + #include "communicator.h" +#endif + +#include + +namespace oofem { +REGISTER_EngngModel(Pdelta); + +Pdelta :: Pdelta(int i, EngngModel *_master) : LinearStatic(i, _master) +{ + ndomains = 1; + initFlag = 1; + solverType = ST_Direct; + lumpedInitialStressMatrix = true; +} + +void +Pdelta :: initializeFrom(InputRecord &ir) +{ + LinearStatic :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, rtolv, _IFT_Pdelta_rtolv); + this->maxiter = 50; + IR_GIVE_OPTIONAL_FIELD(ir, maxiter, _IFT_Pdelta_maxiter); + IR_GIVE_OPTIONAL_FIELD(ir, lumpedInitialStressMatrix, _IFT_Pdelta_lumpedInitialStressMatrix); +} + +void Pdelta :: solveYourselfAt(TimeStep *tStep) +{ + + FloatArray rhs, previousDisplacementVector; + // + // first step assemble stiffness Matrix + // + stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); + if ( !stiffnessMatrix ) { + OOFEM_ERROR("sparse matrix creation failed"); + } + initialStressMatrix = classFactory.createSparseMtrx(sparseMtrxType); + if ( !initialStressMatrix ) { + OOFEM_ERROR("sparse matrix creation failed"); + } + + stiffnessMatrix->buildInternalStructure( this, 1, this->giveEquationNumbering() ); + initialStressMatrix->buildInternalStructure( this, 1, this->giveEquationNumbering() ); + +#ifdef VERBOSE + OOFEM_LOG_DEBUG("Assembling stiffness matrix\n"); +#endif + + this->assemble( *stiffnessMatrix, tStep, TangentAssembler(TangentStiffness), + this->giveEquationNumbering(), this->giveDomain(1) ); + +#ifdef VERBOSE + OOFEM_LOG_DEBUG("Assembling load\n"); +#endif + + // + // allocate space for displacementVector + // + displacementVector.resize( this->giveNumberOfDomainEquations( 1, this->giveEquationNumbering() ) ); // km?? replace EModelDefaultEquationNumbering() with this->giveEquationNumbering(). Use pointer? + displacementVector.zero(); + + // + // assembling the load vector + // + loadVector.resize( this->giveNumberOfDomainEquations( 1, this->giveEquationNumbering() ) ); + loadVector.zero(); + this->assembleVector( loadVector, tStep, ExternalForceAssembler(), VM_Total, + this->giveEquationNumbering(), this->giveDomain(1) ); + + // + // internal forces (from Dirichlet b.c's, or thermal expansion, etc.) + // + FloatArray internalForces( this->giveNumberOfDomainEquations( 1, this->giveEquationNumbering() ) ); + internalForces.zero(); + this->assembleVector( internalForces, tStep, InternalForceAssembler(), VM_Total, + this->giveEquationNumbering(), this->giveDomain(1) ); + + loadVector.subtract(internalForces); + + this->updateSharedDofManagers(loadVector, this->giveEquationNumbering(), ReactionExchangeTag); + + // + // set-up numerical model + // + this->giveNumericalMethod( this->giveMetaStep( tStep->giveMetaStepNumber() ) ); + + // + // call numerical model to solve arose problem + // +#ifdef VERBOSE + OOFEM_LOG_INFO("\n\nSolving ...\n"); +#endif + int iter = 0; + double error; + FloatArray feq(displacementVector.giveSize()); + + do { + previousDisplacementVector = displacementVector; + rhs = loadVector; + if (iter) { + feq.zero(); + if (this->lumpedInitialStressMatrix) { + this->assembleVector(feq, tStep, MatrixProductAssembler(LumpedInitialStressMatrixAssembler()), + VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); + } else { + this->assembleVector(feq, tStep, MatrixProductAssembler(InitialStressMatrixAssembler()), + VM_Total, EModelDefaultEquationNumbering(), this->giveDomain(1) ); + + } + rhs.subtract(feq); + //this->assembleVector(rhs, tStep, EquivalentLateralLoadAssembler(), VM_Total, + // this->giveEquationNumbering(), this->giveDomain(1) ); + } + NM_Status s = nMethod->solve(*stiffnessMatrix, rhs, displacementVector); + + if ( !( s & NM_Success ) ) { + OOFEM_ERROR("No success in solving system."); + } + + tStep->incrementStateCounter(); // update solution state counter + previousDisplacementVector.subtract(displacementVector); + error = previousDisplacementVector.computeNorm()/displacementVector.computeNorm(); + iter++; + } while ((error > rtolv) && (iter <= this->maxiter)); + OOFEM_LOG_INFO("Done in %d iteration(s) (err = %le)\n", iter-1, error); +} + + + + +} // end namespace oofem diff --git a/src/sm/EngineeringModels/pdelta.h b/src/sm/EngineeringModels/pdelta.h new file mode 100644 index 000000000..9fe1fc9c1 --- /dev/null +++ b/src/sm/EngineeringModels/pdelta.h @@ -0,0 +1,85 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef pdelta_h +#define pdelta_h + +#include "sm/EngineeringModels/linearstatic.h" +#include "geneigvalsolvertype.h" +#include "sparsegeneigenvalsystemnm.h" +#include "sparselinsystemnm.h" +#include "sparsemtrx.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "nummet.h" + +///@name Input fields for LinearStability +//@{ +#define _IFT_Pdelta_Name "pdelta" +#define _IFT_Pdelta_rtolv "rtolv" +#define _IFT_Pdelta_stype "stype" +#define _IFT_Pdelta_maxiter "maxiter" +#define _IFT_Pdelta_lumpedInitialStressMatrix "lumped" +//@} + +namespace oofem { + +/** + * This class implements p-delta analysis, where the effects of normal force on deformed configuration + * is taken into account by means of initial stress matrix. + * + * Solution of this problem is base on equation in the form of: @f$ (K+K_\sigma(r))\cdot r=f @f$. + * This is a nonlinear problem solved using simple iteration method. + */ +class Pdelta : public LinearStatic +{ +private: + std :: unique_ptr< SparseMtrx > initialStressMatrix; + double rtolv; + int maxiter; + bool lumpedInitialStressMatrix; + +public: + Pdelta(int i, EngngModel *master=nullptr); + virtual ~Pdelta() { } + + void solveYourselfAt(TimeStep *tStep) override; + void initializeFrom(InputRecord &ir) override; + + // identification + const char *giveInputRecordName() const override { return _IFT_Pdelta_Name; } + const char *giveClassName() const override { return "Pdelta"; } +}; +} // end namespace oofem +#endif // pdelta_h diff --git a/src/sm/EngineeringModels/qclinearstatic.C b/src/sm/EngineeringModels/qclinearstatic.C index 41d87d91f..60890ebff 100644 --- a/src/sm/EngineeringModels/qclinearstatic.C +++ b/src/sm/EngineeringModels/qclinearstatic.C @@ -32,10 +32,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/qclinearstatic.h" -#include "../sm/Quasicontinuum/fullsolveddomain.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/Elements/structuralelementevaluator.h" +#include "sm/EngineeringModels/qclinearstatic.h" +#include "sm/Quasicontinuum/fullsolveddomain.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelementevaluator.h" #include "nummet.h" #include "timestep.h" #include "element.h" @@ -51,12 +51,12 @@ #include "dof.h" #include "crosssection.h" -#include "../sm/Quasicontinuum/quasicontinuum.h" -#include "../sm/Quasicontinuum/fullsolveddomain.h" -#include "../sm/Quasicontinuum/geometrygenerator.h" +#include "sm/Quasicontinuum/quasicontinuum.h" +#include "sm/Quasicontinuum/fullsolveddomain.h" +#include "sm/Quasicontinuum/geometrygenerator.h" #include "unknownnumberingscheme.h" -#include "../sm/Quasicontinuum/quasicontinuumnumberingscheme.h" +#include "sm/Quasicontinuum/quasicontinuumnumberingscheme.h" #include "t3dinterface.h" #ifdef __T3D @@ -75,22 +75,17 @@ REGISTER_EngngModel(QClinearStatic); QClinearStatic :: QClinearStatic(int i, EngngModel *_master) : LinearStatic(i, _master), loadVector(), displacementVector() { - qcEquationNumbering = new QuasicontinuumNumberingscheme(); } QClinearStatic :: ~QClinearStatic() { - delete qcEquationNumbering; } - -IRResultType -QClinearStatic :: initializeFrom(InputRecord *ir) +void +QClinearStatic :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - LinearStatic :: initializeFrom(ir); IR_GIVE_FIELD(ir, qcApproach, _IFT_QuasiContinuum_approach); @@ -159,8 +154,6 @@ QClinearStatic :: initializeFrom(InputRecord *ir) OOFEM_ERROR("Invalid input field \"GenInterpElem\". Value: %d is not supported", generateInterpolationElements); } - - // test of combination of input geometry generating #if DEBUG if ( generateParticles == 1 && generateLinks != 1 ) { @@ -176,8 +169,6 @@ QClinearStatic :: initializeFrom(InputRecord *ir) generateInterpolationElements = 0; } - - #ifdef __PARALLEL_MODE if ( isParallel() ) { commBuff = new CommunicatorBuff( this->giveNumberOfProcesses() ); @@ -186,9 +177,6 @@ QClinearStatic :: initializeFrom(InputRecord *ir) } #endif - - - return IRRT_OK; } @@ -212,7 +200,7 @@ QClinearStatic :: postInitialize() if ( qcApproach > 0 ) { createInterpolationMeshNodes( this->giveDomain(1) ); setRepNodesInVerticesOfInterpolationMesh( this->giveDomain(1) ); - qc.setupInterpolationMesh(this->giveDomain(1), generateInterpolationElements, interpolationElementsMaterialNumber, & interpolationMeshNodes); + qc.setupInterpolationMesh(this->giveDomain(1), generateInterpolationElements, interpolationElementsMaterialNumber, interpolationMeshNodes); qc.createInterpolationElements( this->giveDomain(1) ); qc.addCrosssectionToInterpolationElements( this->giveDomain(1) ); } @@ -229,7 +217,6 @@ QClinearStatic :: postInitialize() EngngModel :: postInitialize(); - // apply QC if ( qcApproach == 0 ) { //A0 - fully solved model @@ -283,27 +270,25 @@ QClinearStatic :: postInitialize() } - void QClinearStatic :: solveYourself() { LinearStatic :: solveYourself(); } + void QClinearStatic :: solveYourselfAt(TimeStep *tStep) { // initialize node eq numbering (for actived nodes only) - if ( !qcEquationNumbering->giveIsInitializedFlag() ) { - qcEquationNumbering->init(this->giveDomain(1), activatedNodeList, tStep); + if ( !qcEquationNumbering.giveIsInitializedFlag() ) { + qcEquationNumbering.init(this->giveDomain(1), activatedNodeList, tStep); } LinearStatic :: solveYourselfAt(tStep); } -IRResultType -QClinearStatic :: initializeFullSolvedDomain(InputRecord *ir) +void +QClinearStatic :: initializeFullSolvedDomain(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_OPTIONAL_FIELD(ir, FullSolvedDomainNodes, _IFT_FullSolvedDomain_nodes); IR_GIVE_OPTIONAL_FIELD(ir, FullSolvedDomainElements, _IFT_FullSolvedDomain_elements); IR_GIVE_OPTIONAL_FIELD(ir, FullSolvedDomainRadius, _IFT_FullSolvedDomain_radius); @@ -317,14 +302,13 @@ QClinearStatic :: initializeFullSolvedDomain(InputRecord *ir) OOFEM_ERROR("invalid format of FullSolvedDomainBox"); } #endif - - return IRRT_OK; } + bool QClinearStatic :: nodeInFullSolvedDomainTest(Node *n) { - FloatArray *coordinates = n->giveCoordinates(); + const auto &coordinates = n->giveCoordinates(); // is tested node in FullSolvedDomainNodes if ( FullSolvedDomainNodes.giveSize() != 0 ) { for ( int i = 1; i <= FullSolvedDomainNodes.giveSize(); i++ ) { @@ -350,9 +334,9 @@ QClinearStatic :: nodeInFullSolvedDomainTest(Node *n) for ( int i = 0; i <= FullSolvedDomainRadius.giveSize() / 4 - 1; i++ ) { FloatArray vector; vector.resize(3); - vector.at(1) = coordinates->at(1) - FullSolvedDomainRadius.at(4 * i + 1); - vector.at(2) = coordinates->at(2) - FullSolvedDomainRadius.at(4 * i + 2); - vector.at(3) = coordinates->at(3) - FullSolvedDomainRadius.at(4 * i + 3); + vector.at(1) = coordinates.at(1) - FullSolvedDomainRadius.at(4 * i + 1); + vector.at(2) = coordinates.at(2) - FullSolvedDomainRadius.at(4 * i + 2); + vector.at(3) = coordinates.at(3) - FullSolvedDomainRadius.at(4 * i + 3); if ( vector.computeNorm() <= FullSolvedDomainRadius.at(4 * i + 4) ) { return true; } @@ -372,15 +356,14 @@ QClinearStatic :: nodeInFullSolvedDomainTest(Node *n) B.at(2) = FullSolvedDomainBox.at(6 * i + 5); B.at(3) = FullSolvedDomainBox.at(6 * i + 4); - if ( ( A.at(1) <= coordinates->at(1) ) && ( coordinates->at(1) <= B.at(1) ) && \ - ( A.at(2) <= coordinates->at(2) ) && ( coordinates->at(2) <= B.at(2) ) && \ - ( A.at(3) <= coordinates->at(3) ) && ( coordinates->at(3) <= B.at(3) ) ) { + if ( ( A.at(1) <= coordinates.at(1) ) && ( coordinates.at(1) <= B.at(1) ) && \ + ( A.at(2) <= coordinates.at(2) ) && ( coordinates.at(2) <= B.at(2) ) && \ + ( A.at(3) <= coordinates.at(3) ) && ( coordinates.at(3) <= B.at(3) ) ) { return true; } } } - return false; } @@ -426,6 +409,7 @@ QClinearStatic :: setQCNodeType(Domain *d) } } + void QClinearStatic :: updateNodeTypes(Domain *d) { @@ -460,12 +444,13 @@ QClinearStatic :: createInterpolationMeshNodes(Domain *d) } } + std :: vector< IntArray > QClinearStatic :: generateInterpolationMesh(Domain *d) { std :: vector< IntArray >newMeshNodes; #ifdef __T3D - T3DInterface *t3dInterface = new T3DInterface( this->giveDomain(1) ); + T3DInterface *t3dInterface( this->giveDomain(1) ); #endif std :: vector< FloatArray >nodeCoords; std :: vector< IntArray >meshNodes; @@ -498,24 +483,25 @@ QClinearStatic :: generateInterpolationMesh(Domain *d) if ( generateInterpolationElements == 1 || generateInterpolationElements == 2 ) { // create interpolation mesh from t3d output file #ifdef __T3D - t3dInterface->createQCInterpolationMesh(t3dOutFile, nodeCoords, meshNodes, cellTypes); + t3dInterface.createQCInterpolationMesh(t3dOutFile, nodeCoords, meshNodes, cellTypes); #endif // map mesh to position of particles newMeshNodes = this->transformMeshToParticles(this->giveDomain(1), nodeCoords, meshNodes); // degenerated elements have been removed - // check if mesch is consistent after removal. ??km?? TO DO ?? How to check it? + // check if mesh is consistent after removal. ??km?? TO DO ?? How to check it? } return newMeshNodes; } + std :: vector< IntArray > QClinearStatic :: loadInterpolationMesh(Domain *d) { std :: vector< IntArray >newMeshNodes; //#ifdef __T3D - T3DInterface *t3dInterface = new T3DInterface( this->giveDomain(1) ); + T3DInterface t3dInterface( this->giveDomain(1) ); //#endif std :: vector< FloatArray >nodeCoords; std :: vector< IntArray >meshNodes; @@ -527,14 +513,14 @@ QClinearStatic :: loadInterpolationMesh(Domain *d) // create interpolation mesh from given t3d output file //#ifdef __T3D - t3dInterface->createQCInterpolationMesh(t3dOutFile, nodeCoords, meshNodes, cellTypes); + t3dInterface.createQCInterpolationMesh(t3dOutFile, nodeCoords, meshNodes, cellTypes); //#endif // map mesh to position of particles newMeshNodes = this->transformMeshToParticles(this->giveDomain(1), nodeCoords, meshNodes); // degenerated elements have been removed - // check if mesch is consistent after removal. ??km?? TO DO ?? How to check it? + // check if mesh is consistent after removal. ??km?? TO DO ?? How to check it? return newMeshNodes; } @@ -576,7 +562,7 @@ QClinearStatic :: transformMeshToParticles(Domain *d, std :: vector< FloatArray // OOFEM_WARNING(" "); } - nodeCoords [ i - 1 ] = * nearestParticle->giveCoordinates(); + nodeCoords [ i - 1 ] = nearestParticle->giveCoordinates(); newNodeNumbers [ i - 1 ] = nearestParticle->giveNumber(); } @@ -633,18 +619,18 @@ QClinearStatic :: transformMeshToParticles(Domain *d, std :: vector< FloatArray newNodeNumbers.at(n3) == newNodeNumbers.at(n4) ) { continue; // skip degenerate element } else { // check degeneration to negative volume - double x1 = d->giveDofManager( newNodeNumbers.at(n1) )->giveCoordinates()->at(1); - double y1 = d->giveDofManager( newNodeNumbers.at(n1) )->giveCoordinates()->at(2); - double z1 = d->giveDofManager( newNodeNumbers.at(n1) )->giveCoordinates()->at(3); - double x2 = d->giveDofManager( newNodeNumbers.at(n2) )->giveCoordinates()->at(1); - double y2 = d->giveDofManager( newNodeNumbers.at(n2) )->giveCoordinates()->at(2); - double z2 = d->giveDofManager( newNodeNumbers.at(n2) )->giveCoordinates()->at(3); - double x3 = d->giveDofManager( newNodeNumbers.at(n3) )->giveCoordinates()->at(1); - double y3 = d->giveDofManager( newNodeNumbers.at(n3) )->giveCoordinates()->at(2); - double z3 = d->giveDofManager( newNodeNumbers.at(n3) )->giveCoordinates()->at(3); - double x4 = d->giveDofManager( newNodeNumbers.at(n4) )->giveCoordinates()->at(1); - double y4 = d->giveDofManager( newNodeNumbers.at(n4) )->giveCoordinates()->at(2); - double z4 = d->giveDofManager( newNodeNumbers.at(n4) )->giveCoordinates()->at(3); + double x1 = d->giveDofManager( newNodeNumbers.at(n1) )->giveCoordinate(1); + double y1 = d->giveDofManager( newNodeNumbers.at(n1) )->giveCoordinate(2); + double z1 = d->giveDofManager( newNodeNumbers.at(n1) )->giveCoordinate(3); + double x2 = d->giveDofManager( newNodeNumbers.at(n2) )->giveCoordinate(1); + double y2 = d->giveDofManager( newNodeNumbers.at(n2) )->giveCoordinate(2); + double z2 = d->giveDofManager( newNodeNumbers.at(n2) )->giveCoordinate(3); + double x3 = d->giveDofManager( newNodeNumbers.at(n3) )->giveCoordinate(1); + double y3 = d->giveDofManager( newNodeNumbers.at(n3) )->giveCoordinate(2); + double z3 = d->giveDofManager( newNodeNumbers.at(n3) )->giveCoordinate(3); + double x4 = d->giveDofManager( newNodeNumbers.at(n4) )->giveCoordinate(1); + double y4 = d->giveDofManager( newNodeNumbers.at(n4) )->giveCoordinate(2); + double z4 = d->giveDofManager( newNodeNumbers.at(n4) )->giveCoordinate(3); double detJ = ( x4 - x1 ) * ( y2 - y1 ) * ( z3 - z1 ) - ( x4 - x1 ) * ( y3 - y1 ) * ( z2 - z1 ) + ( x3 - x1 ) * ( y4 - y1 ) * ( z2 - z1 ) - ( x2 - x1 ) * ( y4 - y1 ) * ( z3 - z1 ) + ( x2 - x1 ) * ( y3 - y1 ) * ( z4 - z1 ) - ( x3 - x1 ) * ( y2 - y1 ) * ( z4 - z1 ); if ( detJ <= 0 ) { OOFEM_WARNING("%d-th interpolation element degenerates to negative volume", i); @@ -664,6 +650,7 @@ QClinearStatic :: transformMeshToParticles(Domain *d, std :: vector< FloatArray return newMeshNodes; } + double QClinearStatic :: computeTotalVolumeOfInterpolationMesh(Domain *d) // TO DO: computeVolumeAreaOrLength() is not working @@ -707,13 +694,12 @@ QClinearStatic :: findNearestParticle(Domain *d, FloatArray coords) { // TO DO: use octree here double minDistance = 1.0e100; - double distance; - DofManager *p; + DofManager *p = nullptr; // loop over all particles (nodes in existing domain) for ( int i = 1; i <= d->giveNumberOfDofManagers(); i++ ) { - distance = coords.distance( d->giveDofManager(i)->giveCoordinates() ); - if ( distance < minDistance ) { - minDistance = distance; + double dist = distance(coords, d->giveDofManager(i)->giveCoordinates() ); + if ( dist < minDistance ) { + minDistance = dist; p = d->giveDofManager(i); } } @@ -721,16 +707,15 @@ QClinearStatic :: findNearestParticle(Domain *d, FloatArray coords) return p; } else { OOFEM_ERROR( "Neares particle for point [%d, %d] not found", coords.at(1), coords.at(2) ); - return NULL; + return nullptr; } } + QCFullsolveddomain * QClinearStatic :: giveFullSolvedDomain() { - QCFullsolveddomain *p; - p = & Fullsolveddomain; - return p; + return &Fullsolveddomain; } @@ -747,6 +732,7 @@ QClinearStatic :: setActivatedNodeList(IntArray nodeList, Domain *d) } } + void QClinearStatic :: setActivatedElementList(IntArray elemList) { @@ -759,4 +745,5 @@ QClinearStatic :: setActivatedElementList(IntArray elemList) } } } + } // end namespace oofem diff --git a/src/sm/EngineeringModels/qclinearstatic.h b/src/sm/EngineeringModels/qclinearstatic.h old mode 100755 new mode 100644 index ed1e82b97..a1c60f3b4 --- a/src/sm/EngineeringModels/qclinearstatic.h +++ b/src/sm/EngineeringModels/qclinearstatic.h @@ -35,13 +35,13 @@ #ifndef qclinearstatic_h #define qclinearstatic_h -#include "../sm/EngineeringModels/linearstatic.h" +#include "sm/EngineeringModels/linearstatic.h" #include "sparselinsystemnm.h" #include "sparsemtrxtype.h" #include "node.h" -#include "../sm/Quasicontinuum/fullsolveddomain.h" -#include "../sm/Quasicontinuum/quasicontinuumnumberingscheme.h" +#include "sm/Quasicontinuum/fullsolveddomain.h" +#include "sm/Quasicontinuum/quasicontinuumnumberingscheme.h" #define _IFT_QClinearStatic_Name "qclinearstatic" #define _IFT_QuasiContinuum_approach "qcapproach" @@ -91,9 +91,8 @@ class QCFullsolveddomain; SparseMtrxType sparseMtrxType; /// Numerical method used to solve the problem. SparseLinearSystemNM *nMethod; - - QuasicontinuumNumberingscheme *qcEquationNumbering; + QuasicontinuumNumberingscheme qcEquationNumbering; int initFlag; @@ -113,10 +112,9 @@ class QCFullsolveddomain; //std :: vector< std :: unique_ptr< Element > > interpolationElementList; //std :: vector< std :: unique_ptr< Element > > links; - std::vector interpolationMeshNodes; int numberOfIntepolationElements; - + QCFullsolveddomain Fullsolveddomain; FloatArray FullSolvedDomainNodes; @@ -125,27 +123,25 @@ class QCFullsolveddomain; FloatArray FullSolvedDomainBox; public: - QClinearStatic(int i, EngngModel * _master = NULL); + QClinearStatic(int i, EngngModel *master = nullptr); virtual ~QClinearStatic(); - virtual void postInitialize(); + void postInitialize() override; + void solveYourself() override; + void solveYourselfAt(TimeStep *tStep) override; - virtual void solveYourself(); - virtual void solveYourselfAt(TimeStep *tStep); - - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; // identification - virtual const char *giveInputRecordName() const { return _IFT_QClinearStatic_Name; } - virtual const char *giveClassName() const { return "QClinearStatic"; } - virtual fMode giveFormulation() { return TL; } - + const char *giveInputRecordName() const override { return _IFT_QClinearStatic_Name; } + const char *giveClassName() const override { return "QClinearStatic"; } + fMode giveFormulation() override { return TL; } virtual void updateNodeTypes(Domain *d); virtual void setQCNodeType(Domain *d); - virtual IRResultType initializeFullSolvedDomain(InputRecord *ir); + virtual void initializeFullSolvedDomain(InputRecord &ir); virtual bool nodeInFullSolvedDomainTest(Node *n); virtual void setRepNodesInVerticesOfInterpolationMesh(Domain *d); @@ -162,19 +158,15 @@ class QCFullsolveddomain; virtual QCFullsolveddomain *giveFullSolvedDomain(); virtual int giveQcApproachNumber() {return qcApproach;} - bool isElementActivated( int elemNum ) { return activatedElementList[elemNum-1]; } - bool isElementActivated( Element *e ) { return activatedElementList[e->giveNumber()-1]; } + bool isElementActivated( int elemNum ) override { return activatedElementList[elemNum-1]; } + bool isElementActivated( Element *e ) override { return activatedElementList[e->giveNumber()-1]; } void setActivatedNodeList( IntArray nodeList, Domain *d); void setActivatedElementList( IntArray elemList); - - virtual UnknownNumberingScheme *giveEquationNumbering() {return this->qcEquationNumbering; } - - - + UnknownNumberingScheme &giveEquationNumbering() override { return this->qcEquationNumbering; } }; } // end namespace oofem -#endif // linearstatic_h +#endif // qclinearstatic_h diff --git a/src/sm/EngineeringModels/staticstructural.C b/src/sm/EngineeringModels/staticstructural.C index 94bda2338..0441ef9f7 100644 --- a/src/sm/EngineeringModels/staticstructural.C +++ b/src/sm/EngineeringModels/staticstructural.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/staticstructural.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/Elements/structuralelementevaluator.h" +#include "sm/EngineeringModels/staticstructural.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelementevaluator.h" #include "dofmanager.h" #include "set.h" #include "timestep.h" @@ -53,6 +53,7 @@ #include "datastream.h" #include "contextioerr.h" #include "classfactory.h" +#include "assemblercallback.h" #ifdef __PARALLEL_MODE #include "problemcomm.h" @@ -62,17 +63,17 @@ namespace oofem { REGISTER_EngngModel(StaticStructural); -StaticStructural :: StaticStructural(int i, EngngModel *_master) : StructuralEngngModel(i, _master), +StaticStructural :: StaticStructural(int i, EngngModel *master) : StructuralEngngModel(i, master), internalForces(), eNorm(), sparseMtrxType(SMT_Skyline), solverType(), stiffMode(TangentStiffness), loadLevel(0.), - deltaT(1.) + deltaT(1.), + mRecomputeStepAfterPropagation(false) { ndomains = 1; - mRecomputeStepAfterPropagation = false; } @@ -84,7 +85,7 @@ StaticStructural :: ~StaticStructural() NumericalMethod *StaticStructural :: giveNumericalMethod(MetaStep *mStep) { if ( !nMethod ) { - nMethod.reset( classFactory.createNonLinearSolver(this->solverType.c_str(), this->giveDomain(1), this) ); + nMethod = classFactory.createNonLinearSolver(this->solverType.c_str(), this->giveDomain(1), this); if ( !nMethod ) { OOFEM_ERROR("Failed to create solver (%s).", this->solverType.c_str()); } @@ -98,15 +99,10 @@ StaticStructural :: giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) return tStep->giveNumber() % 2; } -IRResultType -StaticStructural :: initializeFrom(InputRecord *ir) +void +StaticStructural :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StructuralEngngModel :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralEngngModel :: initializeFrom(ir); int val = SMT_Skyline; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_smtype); @@ -124,7 +120,7 @@ StaticStructural :: initializeFrom(InputRecord *ir) this->solverType = "nrsolver"; IR_GIVE_OPTIONAL_FIELD(ir, solverType, _IFT_StaticStructural_solvertype); - nMethod.reset(NULL); + nMethod = nullptr; int tmp = TangentStiffness; // Default TangentStiffness IR_GIVE_OPTIONAL_FIELD(ir, tmp, _IFT_StaticStructural_stiffmode); @@ -134,7 +130,7 @@ StaticStructural :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, _val, _IFT_EngngModel_initialGuess); this->initialGuessType = ( InitialGuess ) _val; - mRecomputeStepAfterPropagation = ir->hasField(_IFT_StaticStructural_recomputeaftercrackpropagation); + mRecomputeStepAfterPropagation = ir.hasField(_IFT_StaticStructural_recomputeaftercrackpropagation); #ifdef __PARALLEL_MODE ///@todo Where is the best place to create these? @@ -145,7 +141,7 @@ StaticStructural :: initializeFrom(InputRecord *ir) communicator = new NodeCommunicator(this, commBuff, this->giveRank(), this->giveNumberOfProcesses()); - if ( ir->hasField(_IFT_StaticStructural_nonlocalExtension) ) { + if ( ir.hasField(_IFT_StaticStructural_nonlocalExtension) ) { nonlocalExt = 1; nonlocCommunicator = new ElementCommunicator(this, commBuff, this->giveRank(), this->giveNumberOfProcesses()); @@ -154,19 +150,15 @@ StaticStructural :: initializeFrom(InputRecord *ir) #endif - this->field.reset( new DofDistributedPrimaryField(this, 1, FT_Displacements, 0) ); - - return IRRT_OK; + this->field = std::make_unique(this, 1, FT_Displacements, 0); } void StaticStructural :: updateAttributes(MetaStep *mStep) { - IRResultType result; // Required by IR_GIVE_FIELD macro - MetaStep *mStep1 = this->giveMetaStep( mStep->giveNumber() ); //this line ensures correct input file in staggered problem - InputRecord *ir = mStep1->giveAttributesRecord(); + auto &ir = mStep1->giveAttributesRecord(); int val = SMT_Skyline; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_smtype); @@ -186,7 +178,7 @@ StaticStructural :: updateAttributes(MetaStep *mStep) IR_GIVE_OPTIONAL_FIELD(ir, s, _IFT_StaticStructural_solvertype); if ( s.compare(this->solverType) ) { this->solverType = s; - nMethod.reset(NULL); + nMethod = nullptr; } int tmp = TangentStiffness; // Default TangentStiffness @@ -197,7 +189,7 @@ StaticStructural :: updateAttributes(MetaStep *mStep) IR_GIVE_OPTIONAL_FIELD(ir, _val, _IFT_EngngModel_initialGuess); this->initialGuessType = ( InitialGuess ) _val; - mRecomputeStepAfterPropagation = ir->hasField(_IFT_StaticStructural_recomputeaftercrackpropagation); + mRecomputeStepAfterPropagation = ir.hasField(_IFT_StaticStructural_recomputeaftercrackpropagation); EngngModel :: updateAttributes(mStep1); } @@ -207,8 +199,8 @@ TimeStep *StaticStructural :: giveNextStep() { if ( !currentStep ) { // first step -> generate initial step - //currentStep.reset( new TimeStep(*giveSolutionStepWhenIcApply()) ); - currentStep.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., this->deltaT, 0) ); + //currentStep = std::make_unique(*giveSolutionStepWhenIcApply()); + currentStep = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., this->deltaT, 0); } previousStep = std :: move(currentStep); double dt; @@ -217,7 +209,7 @@ TimeStep *StaticStructural :: giveNextStep() } else { dt = this->deltaT; } - currentStep.reset( new TimeStep(*previousStep, dt) ); + currentStep = std::make_unique(*previousStep, dt); return currentStep.get(); } @@ -232,7 +224,6 @@ double StaticStructural :: giveEndOfTimeOfInterest() } - void StaticStructural :: solveYourself() { ///@todo Generalize this to engngmodel? @@ -258,25 +249,14 @@ void StaticStructural :: solveYourself() void StaticStructural :: solveYourselfAt(TimeStep *tStep) { - int neq; int di = 1; + int neq = this->giveNumberOfDomainEquations( di, EModelDefaultEquationNumbering() ); this->field->advanceSolution(tStep); - this->field->applyBoundaryCondition(tStep); ///@todo Temporary hack, advanceSolution should apply the boundary conditions directly. + this->field->initialize(VM_Total, tStep, this->solution, EModelDefaultEquationNumbering() ); - neq = this->giveNumberOfDomainEquations( di, EModelDefaultEquationNumbering() ); - if ( tStep->giveNumber() == 1 ) { - this->field->initialize(VM_Total, tStep, this->solution, EModelDefaultEquationNumbering() ); - } else { - this->field->initialize(VM_Total, tStep->givePreviousStep(), this->solution, EModelDefaultEquationNumbering() ); - this->field->update(VM_Total, tStep, this->solution, EModelDefaultEquationNumbering() ); - } - this->field->applyBoundaryCondition(tStep); ///@todo Temporary hack to override the incorrect values that is set by "update" above. Remove this when that is fixed. - - - // Create "stiffness matrix" if ( !this->stiffnessMatrix ) { - this->stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + this->stiffnessMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( !this->stiffnessMatrix ) { OOFEM_ERROR("Couldn't create requested sparse matrix of type %d", sparseMtrxType); } @@ -318,7 +298,7 @@ void StaticStructural :: solveYourselfAt(TimeStep *tStep) OOFEM_LOG_RELEVANT("Computing old tangent\n"); } - this->updateComponent( tStep, NonLinearLhs, this->giveDomain(di) ); + this->updateMatrix(*stiffnessMatrix, tStep, this->giveDomain(di)); SparseLinearSystemNM *linSolver = nMethod->giveLinearSolver(); if( this->giveProblemScale() == macroScale ) { @@ -332,9 +312,7 @@ void StaticStructural :: solveYourselfAt(TimeStep *tStep) } this->solution.add(incrementOfSolution); - - this->field->update(VM_Total, tStep, this->solution, EModelDefaultEquationNumbering()); - this->field->applyBoundaryCondition(tStep); ///@todo Temporary hack to override the incorrect values that is set by "update" above. Remove this when that is fixed. + this->updateSolution(solution, tStep, this->giveDomain(di)); } } else if ( this->initialGuessType != IG_None ) { OOFEM_ERROR("Initial guess type: %d not supported", initialGuessType); @@ -343,18 +321,20 @@ void StaticStructural :: solveYourselfAt(TimeStep *tStep) } // Build initial/external load - FloatArray externalForces(neq); - this->assembleVector( externalForces, tStep, ExternalForceAssembler(), VM_Total, - EModelDefaultEquationNumbering(), this->giveDomain(1) ); + externalForces.resize(neq); + externalForces.zero(); + this->assembleVector(externalForces, tStep, ExternalForceAssembler(), VM_Total, + EModelDefaultEquationNumbering(), this->giveDomain(di) ); this->updateSharedDofManagers(externalForces, EModelDefaultEquationNumbering(), LoadExchangeTag); // Build reference load (for CALM solver) - FloatArray referenceForces; if ( this->nMethod->referenceLoad() ) { // This check is pretty much only here as to avoid unnecessarily trying to integrate all the loads. referenceForces.resize(neq); - this->assembleVector( referenceForces, tStep, ReferenceForceAssembler(), VM_Total, - EModelDefaultEquationNumbering(), this->giveDomain(1) ); + referenceForces.zero(); + + this->assembleVector(referenceForces, tStep, ReferenceForceAssembler(), VM_Total, + EModelDefaultEquationNumbering(), this->giveDomain(di) ); this->updateSharedDofManagers(referenceForces, EModelDefaultEquationNumbering(), LoadExchangeTag); } @@ -379,7 +359,7 @@ void StaticStructural :: solveYourselfAt(TimeStep *tStep) } else { status = this->nMethod->solve(*this->stiffnessMatrix, externalForces, - NULL, + nullptr, this->solution, incrementOfSolution, this->internalForces, @@ -390,7 +370,7 @@ void StaticStructural :: solveYourselfAt(TimeStep *tStep) tStep); } if ( !( status & NM_Success ) ) { - OOFEM_ERROR("No success in solving problem"); + OOFEM_WARNING("No success in solving problem at step %d", tStep->giveNumber()); } } @@ -409,17 +389,43 @@ void StaticStructural :: terminate(TimeStep *tStep) double StaticStructural :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) { - double val1 = dof->giveUnknownsDictionaryValue(tStep, VM_Total); - if ( mode == VM_Total ) { - return val1; - } else if ( mode == VM_Incremental ) { - double val0 = dof->giveUnknownsDictionaryValue(tStep->givePreviousStep(), VM_Total); - return val1 - val0; + if (mode == VM_Residual) { + // evaluate the residual of momentum balance for specific unknown + // evaluate the residual of momentum balance for specific unknown + int eq = dof->__giveEquationNumber(); + if (eq && internalForces.isNotEmpty()) { + double ans = loadLevel*referenceForces.at(eq)-internalForces.at(eq); + if (externalForces.isNotEmpty()) { + ans += externalForces.at(eq); + } + return ans; + } else { + return 0.; + } } else { - OOFEM_ERROR("Unknown value mode requested"); - return 0; + return this->field->giveUnknownValue(dof, mode, tStep); } - return this->field->giveUnknownValue(dof, mode, tStep); +} + + +void StaticStructural :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) +{ + this->field->update(VM_Total, tStep, solutionVector, EModelDefaultEquationNumbering()); +} + + +void StaticStructural :: updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) +{ + answer.zero(); + this->assembleVector(answer, tStep, InternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), d, eNorm); + this->updateSharedDofManagers(answer, EModelDefaultEquationNumbering(), InternalForcesExchangeTag); +} + + +void StaticStructural :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) +{ + mat.zero(); + this->assemble(mat, tStep, TangentAssembler(this->stiffMode), EModelDefaultEquationNumbering(), d); } @@ -427,9 +433,7 @@ void StaticStructural :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Do { if ( cmpn == InternalRhs ) { // Updates the solution in case it has changed - ///@todo NRSolver should report when the solution changes instead of doing it this way. this->field->update(VM_Total, tStep, this->solution, EModelDefaultEquationNumbering()); - this->field->applyBoundaryCondition(tStep);///@todo Temporary hack to override the incorrect vavues that is set by "update" above. Remove this when that is fixed. this->internalForces.zero(); this->assembleVector(this->internalForces, tStep, InternalForceAssembler(), VM_Total, @@ -446,56 +450,35 @@ void StaticStructural :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Do } -contextIOResultType StaticStructural :: saveContext(DataStream &stream, ContextMode mode) +void +StaticStructural :: computeExternalLoadReactionContribution(FloatArray &reactions, TimeStep *tStep, int di) { - contextIOResultType iores; - - if ( ( iores = StructuralEngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = this->field->saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); + if ( ( di == 1 ) && ( tStep == this->giveCurrentStep() ) ) { + reactions.resize( this->giveNumberOfDomainEquations( di, EModelDefaultPrescribedEquationNumbering() ) ); + reactions.zero(); + this->assembleVector( reactions, tStep, ReferenceForceAssembler(), VM_Total, + EModelDefaultPrescribedEquationNumbering(), this->giveDomain(di) ); + reactions.times(loadLevel); + this->assembleVector( reactions, tStep, ExternalForceAssembler(), VM_Total, + EModelDefaultPrescribedEquationNumbering(), this->giveDomain(di) ); + } else { + OOFEM_ERROR("unable to respond due to invalid solution step or domain"); } - - return CIO_OK; } -contextIOResultType StaticStructural :: restoreContext(DataStream *stream, ContextMode mode, void *obj) -{ - contextIOResultType iores; - int closeFlag = 0; - int istep, iversion; - FILE *file = NULL; - - this->resolveCorrespondingStepNumber(istep, iversion, obj); - - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - - if ( ( iores = StructuralEngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = this->field->restoreContext(*stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } +void StaticStructural :: saveContext(DataStream &stream, ContextMode mode) +{ + StructuralEngngModel :: saveContext(stream, mode); + this->field->saveContext(stream); +} - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } - return CIO_OK; +void StaticStructural :: restoreContext(DataStream &stream, ContextMode mode) +{ + StructuralEngngModel :: restoreContext(stream, mode); + this->field->restoreContext(stream); } @@ -506,20 +489,15 @@ StaticStructural :: updateDomainLinks() this->giveNumericalMethod( this->giveCurrentMetaStep() )->setDomain( this->giveDomain(1) ); } + int StaticStructural :: forceEquationNumbering() { - stiffnessMatrix.reset( NULL ); + stiffnessMatrix = nullptr; return StructuralEngngModel::forceEquationNumbering(); } -void StaticStructural :: setSolution(TimeStep *tStep, const FloatArray &vectorToStore) -{ - this->field->update(VM_Total, tStep, vectorToStore, EModelDefaultEquationNumbering()); -} - - bool StaticStructural :: requiresEquationRenumbering(TimeStep *tStep) { @@ -551,7 +529,7 @@ StaticStructural :: estimateMaxPackSize(IntArray &commMap, DataStream &buff, int if ( packUnpackType == 0 ) { ///@todo Fix this old ProblemCommMode__NODE_CUT value for ( int map: commMap ) { DofManager *dman = domain->giveDofManager( map ); - for ( Dof *dof: *dman ) { + for ( auto &dof: *dman ) { if ( dof->isPrimaryDof() && dof->__giveEquationNumber() > 0 ) { count++; } else { diff --git a/src/sm/EngineeringModels/staticstructural.h b/src/sm/EngineeringModels/staticstructural.h index 2d5ef669c..191934b06 100644 --- a/src/sm/EngineeringModels/staticstructural.h +++ b/src/sm/EngineeringModels/staticstructural.h @@ -35,8 +35,8 @@ #ifndef staticstructural_h #define staticstructural_h -#include "../sm/EngineeringModels/structengngmodel.h" -#include "../sm/EngineeringModels/xfemsolverinterface.h" +#include "sm/EngineeringModels/structengngmodel.h" +#include "sm/EngineeringModels/xfemsolverinterface.h" #include "sparsenonlinsystemnm.h" #include "sparsemtrxtype.h" #include "staggeredsolver.h" @@ -51,6 +51,7 @@ #define _IFT_StaticStructural_recomputeaftercrackpropagation "recomputeaftercrackprop" namespace oofem { class SparseMtrx; +class DofDistributedPrimaryField; /** * Solves a static structural problem. @@ -62,12 +63,13 @@ class StaticStructural : public StructuralEngngModel, public XfemSolverInterface FloatArray solution; FloatArray internalForces; FloatArray eNorm; + FloatArray referenceForces, externalForces; public: std :: unique_ptr< SparseMtrx >stiffnessMatrix; protected: - std :: unique_ptr< PrimaryField >field; + std :: unique_ptr< DofDistributedPrimaryField >field; SparseMtrxType sparseMtrxType; @@ -84,46 +86,48 @@ class StaticStructural : public StructuralEngngModel, public XfemSolverInterface bool mRecomputeStepAfterPropagation; public: - StaticStructural(int i, EngngModel * _master = NULL); + StaticStructural(int i, EngngModel *master=nullptr); virtual ~StaticStructural(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void updateAttributes(MetaStep *mStep); + void initializeFrom(InputRecord &ir) override; + void updateAttributes(MetaStep *mStep) override; - virtual void solveYourself(); - virtual void solveYourselfAt(TimeStep *tStep); + void solveYourself() override; + void solveYourselfAt(TimeStep *tStep) override; - virtual void terminate(TimeStep *tStep); + void terminate(TimeStep *tStep) override; - virtual void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d); - - virtual double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof); + void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) override; + void updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) override; + void updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) override; + void updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) override; - virtual void updateDomainLinks(); + double giveUnknownComponent(ValueModeType type, TimeStep *tStep, Domain *d, Dof *dof) override; + bool newDofHandling() override { return true; } - virtual int forceEquationNumbering(); + void updateDomainLinks() override; - virtual double giveLoadLevel() { return loadLevel; } - virtual TimeStep *giveNextStep(); - virtual double giveEndOfTimeOfInterest(); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); - - virtual fMode giveFormulation() { return TL; } + int forceEquationNumbering() override; - void setSolution(TimeStep *tStep, const FloatArray &vectorToStore); + double giveLoadLevel() override { return loadLevel; } + TimeStep *giveNextStep() override; + double giveEndOfTimeOfInterest() override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual bool requiresEquationRenumbering(TimeStep *tStep); + fMode giveFormulation() override { return TL; } - virtual int requiresUnknownsDictionaryUpdate() { return true; } - virtual int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep); + bool requiresEquationRenumbering(TimeStep *tStep) override; + int requiresUnknownsDictionaryUpdate() override { return true; } + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override; + void computeExternalLoadReactionContribution(FloatArray &reactions, TimeStep *tStep, int di) override; // identification - virtual const char *giveInputRecordName() const { return _IFT_StaticStructural_Name; } - virtual const char *giveClassName() const { return "StaticStructural"; } + const char *giveInputRecordName() const { return _IFT_StaticStructural_Name; } + const char *giveClassName() const override { return "StaticStructural"; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); - - virtual int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + + int estimateMaxPackSize(IntArray &commMap, DataStream &buff, int packUnpackType) override; }; } // end namespace oofem #endif // staticstructural_h diff --git a/src/sm/EngineeringModels/structengngmodel.C b/src/sm/EngineeringModels/structengngmodel.C index a64dade5a..102cc8438 100644 --- a/src/sm/EngineeringModels/structengngmodel.C +++ b/src/sm/EngineeringModels/structengngmodel.C @@ -32,10 +32,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/structengngmodel.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/Elements/structuralelementevaluator.h" -#include "../sm/Elements/Interfaces/structuralinterfaceelement.h" +#include "sm/EngineeringModels/structengngmodel.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelementevaluator.h" +#include "sm/Elements/Interfaces/structuralinterfaceelement.h" #include "dofmanager.h" #include "dof.h" #include "element.h" @@ -45,8 +45,8 @@ #include "assemblercallback.h" #include "unknownnumberingscheme.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/CrossSections/structuralcrosssection.h" namespace oofem { @@ -62,18 +62,14 @@ void LinearizedDilationForceAssembler :: vectorFromElement(FloatArray &vec, Elem vec.clear(); for ( auto &gp : *selem.giveDefaultIntegrationRulePtr() ) { - FloatMatrix B; - FloatArray epsilonTemperature; - - double dV = selem.computeVolumeAround(gp); - selem.computeBmatrixAt(gp, B); - /// @todo Problematic: Needs direct access to material model. Should do without (can be easily done by adding lots of code, but I'm searching for a simple, general, implementation) / Mikael - static_cast< StructuralMaterial *>( selem.giveStructuralCrossSection()->giveMaterial(gp) )->computeStressIndependentStrainVector(epsilonTemperature, gp, tStep, VM_Incremental); + auto epsilonTemperature = static_cast< StructuralMaterial *>( selem.giveStructuralCrossSection()->giveMaterial(gp) )->computeStressIndependentStrainVector(gp, tStep, VM_Incremental); if ( epsilonTemperature.giveSize() > 0 ) { + FloatMatrix D, B; FloatArray s; - FloatMatrix D; + double dV = selem.computeVolumeAround(gp); + selem.computeBmatrixAt(gp, B); selem.computeConstitutiveMatrixAt(D, ElasticStiffness, gp, tStep); s.beProductOf(D, epsilonTemperature); vec.plusProduct(B, s, dV); @@ -86,6 +82,11 @@ void InitialStressMatrixAssembler :: matrixFromElement(FloatMatrix &answer, Elem static_cast< StructuralElement & >( element ).computeInitialStressMatrix(answer, tStep); } +void LumpedInitialStressMatrixAssembler :: matrixFromElement(FloatMatrix &answer, Element &element, TimeStep *tStep) const +{ + static_cast< StructuralElement & >( element ).computeLumpedInitialStressMatrix(answer, tStep); +} + StructuralEngngModel :: StructuralEngngModel(int i, EngngModel *_master) : EngngModel(i, _master), @@ -210,17 +211,17 @@ StructuralEngngModel :: computeExternalLoadReactionContribution(FloatArray &reac void -StructuralEngngModel :: giveInternalForces(FloatArray &answer, bool normFlag, int di, TimeStep *tStep) +StructuralEngngModel :: updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) { - // Simply assembles contributions from each element in domain - Domain *domain = this->giveDomain(di); +#ifdef VERBOSE + OOFEM_LOG_DEBUG("Updating internal forces\n"); +#endif // Update solution state counter tStep->incrementStateCounter(); - answer.resize( this->giveNumberOfDomainEquations( di, EModelDefaultEquationNumbering() ) ); + answer.resize( this->giveNumberOfDomainEquations( d->giveNumber(), EModelDefaultEquationNumbering() ) ); answer.zero(); - this->assembleVector(answer, tStep, InternalForceAssembler(), VM_Total, - EModelDefaultEquationNumbering(), domain, normFlag ? & this->internalForcesEBENorm : NULL); + this->assembleVector(answer, tStep, InternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), d, eNorm); // Redistributes answer so that every process have the full values on all shared equations this->updateSharedDofManagers(answer, EModelDefaultEquationNumbering(), InternalForcesExchangeTag); @@ -277,11 +278,17 @@ StructuralEngngModel :: updateInternalState(TimeStep *tStep) { for ( auto &domain: domainList ) { if ( requiresUnknownsDictionaryUpdate() ) { +#ifdef _OPENMP +#pragma omp parallel for +#endif for ( auto &dman : domain->giveDofManagers() ) { this->updateDofUnknownsDictionary(dman.get(), tStep); } } - + +#ifdef _OPENMP +#pragma omp parallel for +#endif for ( auto &bc : domain->giveBcs() ) { ActiveBoundaryCondition *abc; @@ -294,10 +301,12 @@ StructuralEngngModel :: updateInternalState(TimeStep *tStep) } if ( internalVarUpdateStamp != tStep->giveSolutionStateCounter() ) { +#ifdef _OPENMP +#pragma omp parallel for +#endif for ( auto &elem : domain->giveElements() ) { elem->updateInternalState(tStep); } - internalVarUpdateStamp = tStep->giveSolutionStateCounter(); } } diff --git a/src/sm/EngineeringModels/structengngmodel.h b/src/sm/EngineeringModels/structengngmodel.h index f8b1eac45..6dec5e7b9 100644 --- a/src/sm/EngineeringModels/structengngmodel.h +++ b/src/sm/EngineeringModels/structengngmodel.h @@ -46,7 +46,7 @@ class StructuralElement; ///@todo The need for this is just due to some other design choices. class LastEquilibratedInternalForceAssembler : public InternalForceAssembler { - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; /** @@ -56,7 +56,7 @@ class LastEquilibratedInternalForceAssembler : public InternalForceAssembler class LinearizedDilationForceAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; /** @@ -66,9 +66,18 @@ class LinearizedDilationForceAssembler : public VectorAssembler class InitialStressMatrixAssembler : public MatrixAssembler { public: - virtual void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const; + void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const override; }; +/** + * Callback class for assembling lumped initial stress matrices + * @author Mikael Öhman + */ +class LumpedInitialStressMatrixAssembler : public MatrixAssembler +{ +public: + void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const override; +}; /** * This class implements extension of EngngModel for structural models. @@ -106,14 +115,6 @@ class StructuralEngngModel : public EngngModel * @param di Domain number. */ virtual void computeExternalLoadReactionContribution(FloatArray &reactions, TimeStep *tStep, int di); - /** - * Evaluates the nodal representation of internal forces by assembling contributions from individual elements. - * @param answer Vector of nodal internal forces. - * @param normFlag True if element by element norm of internal forces (internalForcesEBENorm) is to be computed. - * @param di Domain number. - * @param tStep Solution step. - */ - virtual void giveInternalForces(FloatArray &answer, bool normFlag, int di, TimeStep *tStep); /** * Updates nodal values @@ -124,17 +125,17 @@ class StructuralEngngModel : public EngngModel */ void updateInternalState(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; public: /// Creates new StructuralEngngModel with number i, associated to domain d. - StructuralEngngModel(int i, EngngModel * _master = NULL); + StructuralEngngModel(int i, EngngModel *master = nullptr); /// Destructor. virtual ~StructuralEngngModel(); - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual int checkConsistency(); + int checkConsistency() override; /** * Computes reaction forces. The implementation assumes, that real @@ -148,12 +149,8 @@ class StructuralEngngModel : public EngngModel */ void computeReaction(FloatArray &answer, TimeStep *tStep, int di); - /** - * Terminates the solution of time step. Default implementation calls prinOutput() service and if specified, - * context of whole domain is stored and output for given time step is printed. - */ - virtual void terminate(TimeStep *tStep); - + void terminate(TimeStep *tStep) override; + /** * Builds the reaction force table. For each prescribed equation number it will find * corresponding node and dof number. The entries in the restrDofMans, restrDofs, and eqn @@ -167,11 +164,13 @@ class StructuralEngngModel : public EngngModel */ void buildReactionTable(IntArray &restrDofMans, IntArray &restrDofs, IntArray &eqn, TimeStep *tStep, int di); + void updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) override; + #ifdef __OOFEG /** * Shows the sparse structure of required matrix, type == 1 stiffness. */ - virtual void showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep); + void showSparseMtrxStructure(int type, oofegGraphicContext &gc, TimeStep *tStep) override; #endif }; } // end namespace oofem diff --git a/src/sm/EngineeringModels/structuralmaterialevaluator.C b/src/sm/EngineeringModels/structuralmaterialevaluator.C index ce35de58e..e98e946e1 100644 --- a/src/sm/EngineeringModels/structuralmaterialevaluator.C +++ b/src/sm/EngineeringModels/structuralmaterialevaluator.C @@ -37,8 +37,8 @@ #include "timestep.h" #include "domain.h" #include "gausspoint.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "function.h" #include "classfactory.h" @@ -55,10 +55,8 @@ StructuralMaterialEvaluator :: StructuralMaterialEvaluator(int i, EngngModel *_m StructuralMaterialEvaluator :: ~StructuralMaterialEvaluator() { } -IRResultType StructuralMaterialEvaluator :: initializeFrom(InputRecord *ir) +void StructuralMaterialEvaluator :: initializeFrom(InputRecord &ir) { - IRResultType result; - this->deltaT = 1.0; IR_GIVE_OPTIONAL_FIELD(ir, this->deltaT, _IFT_StructuralMaterialEvaluator_deltat); IR_GIVE_FIELD(ir, this->numberOfSteps, _IFT_StructuralMaterialEvaluator_numberOfTimeSteps); @@ -67,7 +65,7 @@ IRResultType StructuralMaterialEvaluator :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, this->cmpntFunctions, _IFT_StructuralMaterialEvaluator_componentFunctions); IR_GIVE_FIELD(ir, this->sControl, _IFT_StructuralMaterialEvaluator_stressControl); - this->keepTangent = ir->hasField(_IFT_StructuralMaterialEvaluator_keepTangent); + this->keepTangent = ir.hasField(_IFT_StructuralMaterialEvaluator_keepTangent); tolerance = 1.0; if ( this->sControl.giveSize() > 0 ) { @@ -84,8 +82,6 @@ IRResultType StructuralMaterialEvaluator :: initializeFrom(InputRecord *ir) eControl.followedBy(i); } } - - return IRRT_OK; } @@ -98,7 +94,7 @@ void StructuralMaterialEvaluator :: solveYourself() gps.clear(); gps.reserve(d->giveNumberOfMaterialModels()); for ( int i = 1; i <= d->giveNumberOfMaterialModels(); i++ ) { - std :: unique_ptr< GaussPoint > gp(new GaussPoint(nullptr, i, FloatArray(0), 1, mode)); + std :: unique_ptr< GaussPoint > gp = std::make_unique(nullptr, i, FloatArray(0), 1, mode); gps.emplace_back( std :: move(gp) ); // Initialize the strain vector; StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( d->giveMaterial(i)->giveStatus( gps[i-1].get() ) ); @@ -154,7 +150,7 @@ void StructuralMaterialEvaluator :: solveYourself() #endif strain.printYourself("Macro strain guess"); - mat->giveRealStressVector_3d(stress, gp, strain, tStep); + stress = mat->giveRealStressVector_3d(strain, gp, tStep); for ( int j = 1; j <= sControl.giveSize(); ++j ) { res.at(j) = stressC.at(j) - stress.at( sControl.at(j) ); } @@ -166,7 +162,7 @@ void StructuralMaterialEvaluator :: solveYourself() break; } else { if ( tangent.giveNumberOfRows() == 0 || !keepTangent ) { - mat->give3dMaterialStiffnessMatrix(tangent, TangentStiffness, gp, tStep); + tangent = mat->give3dMaterialStiffnessMatrix(TangentStiffness, gp, tStep); } // Pick out the stress-controlled part; @@ -240,11 +236,11 @@ TimeStep *StructuralMaterialEvaluator :: giveNextStep() { if ( !currentStep ) { // first step -> generate initial step - //currentStep.reset( new TimeStep(*giveSolutionStepWhenIcApply()) ); - currentStep.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., this->deltaT, 0) ); + //currentStep = std::make_unique(*giveSolutionStepWhenIcApply()); + currentStep = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., this->deltaT, 0); } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(*previousStep, this->deltaT) ); + currentStep = std::make_unique(*previousStep, this->deltaT); return currentStep.get(); } diff --git a/src/sm/EngineeringModels/structuralmaterialevaluator.h b/src/sm/EngineeringModels/structuralmaterialevaluator.h index ff9c627dc..6fb0a81ec 100644 --- a/src/sm/EngineeringModels/structuralmaterialevaluator.h +++ b/src/sm/EngineeringModels/structuralmaterialevaluator.h @@ -78,19 +78,19 @@ class StructuralMaterialEvaluator : public EngngModel double tolerance; public: - StructuralMaterialEvaluator(int i, EngngModel * _master = NULL); + StructuralMaterialEvaluator(int i, EngngModel *master = nullptr); virtual ~StructuralMaterialEvaluator(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void solveYourself(); + void solveYourself() override; - virtual int checkConsistency(); - virtual void doStepOutput(TimeStep *tStep); - virtual TimeStep *giveNextStep(); + int checkConsistency() override; + void doStepOutput(TimeStep *tStep) override; + TimeStep *giveNextStep() override; - virtual const char *giveClassName() const { return "StructuralMaterialEvaluator"; } - virtual const char *giveInputRecordName() const { return _IFT_StructuralMaterialEvaluator_Name; } + const char *giveClassName() const override { return "StructuralMaterialEvaluator"; } + const char *giveInputRecordName() const { return _IFT_StructuralMaterialEvaluator_Name; } }; } // end namespace oofem diff --git a/src/sm/EngineeringModels/xfemsolverinterface.C b/src/sm/EngineeringModels/xfemsolverinterface.C index e38c28d98..50b5e5cf2 100644 --- a/src/sm/EngineeringModels/xfemsolverinterface.C +++ b/src/sm/EngineeringModels/xfemsolverinterface.C @@ -32,12 +32,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/EngineeringModels/xfemsolverinterface.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" -#include "../sm/xfem/xfemstructuralelementinterface.h" -#include "../sm/mappers/primvarmapper.h" +#include "sm/EngineeringModels/xfemsolverinterface.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "sm/xfem/xfemstructuralelementinterface.h" +#include "sm/mappers/primvarmapper.h" #include "timestep.h" #include "structengngmodel.h" #include "staticstructural.h" @@ -53,23 +53,16 @@ namespace oofem { -XfemSolverInterface::XfemSolverInterface(): -mNeedsVariableMapping(false) -{ - -} - -XfemSolverInterface::~XfemSolverInterface() -{ - -} +XfemSolverInterface::XfemSolverInterface() : + mNeedsVariableMapping(false) +{ } void XfemSolverInterface::propagateXfemInterfaces(TimeStep *tStep, StructuralEngngModel &ioEngngModel, bool iRecomputeStepAfterCrackProp) { int domainInd = 1; Domain *domain = ioEngngModel.giveDomain(domainInd); - if(domain->hasXfemManager()) { + if ( domain->hasXfemManager() ) { XfemManager *xMan = domain->giveXfemManager(); bool frontsHavePropagated = false; if ( xMan->hasInitiationCriteria() ) { @@ -78,47 +71,41 @@ void XfemSolverInterface::propagateXfemInterfaces(TimeStep *tStep, StructuralEng xMan->initiateFronts(frontsHavePropagated,tStep); } - if( xMan->hasPropagatingFronts() ) { + if ( xMan->hasPropagatingFronts() ) { // Propagate crack tips xMan->propagateFronts(frontsHavePropagated); - } bool eiWereNucleated = false; - if( xMan->hasNucleationCriteria() ) { + if ( xMan->hasNucleationCriteria() ) { xMan->nucleateEnrichmentItems(eiWereNucleated); - } + } - int numEl = domain->giveNumberOfElements(); - for ( int i = 1; i <= numEl; i++ ) { + for ( auto &elem : domain->giveElements() ) { //////////////////////////////////////////////////////// // Map state variables for enriched elements - XfemElementInterface *xfemElInt = dynamic_cast< XfemElementInterface * >( domain->giveElement(i) ); + XfemElementInterface *xfemElInt = dynamic_cast< XfemElementInterface * >( elem.get() ); - if(xfemElInt) { - xfemElInt->XfemElementInterface_updateIntegrationRule(); + if ( xfemElInt ) { + xfemElInt->XfemElementInterface_updateIntegrationRule(); } - } - - if(frontsHavePropagated || eiWereNucleated) { + if ( frontsHavePropagated || eiWereNucleated ) { mNeedsVariableMapping = false; - + ioEngngModel.giveDomain(1)->postInitialize(); ioEngngModel.forceEquationNumbering(); - if(iRecomputeStepAfterCrackProp) { - printf("Recomputing time step.\n"); + if ( iRecomputeStepAfterCrackProp ) { + OOFEM_LOG_RELEVANT("Recomputing time step.\n"); ioEngngModel.forceEquationNumbering(); ioEngngModel.solveYourselfAt(tStep); ioEngngModel.updateYourself( tStep ); ioEngngModel.terminate( tStep ); - } } } - } diff --git a/src/sm/EngineeringModels/xfemsolverinterface.h b/src/sm/EngineeringModels/xfemsolverinterface.h index 1f5937684..798d5a6cf 100644 --- a/src/sm/EngineeringModels/xfemsolverinterface.h +++ b/src/sm/EngineeringModels/xfemsolverinterface.h @@ -49,11 +49,10 @@ class FloatArray; class XfemSolverInterface { public: XfemSolverInterface(); - virtual ~XfemSolverInterface(); + virtual ~XfemSolverInterface() { } void propagateXfemInterfaces(TimeStep *tStep, StructuralEngngModel &ioEngngModel, bool iRecomputeStepAfterCrackProp); - protected: bool mNeedsVariableMapping; }; diff --git a/src/sm/ErrorEstimators/combinedzzsiee.C b/src/sm/ErrorEstimators/combinedzzsiee.C index 913d70e9b..e9f4e9752 100644 --- a/src/sm/ErrorEstimators/combinedzzsiee.C +++ b/src/sm/ErrorEstimators/combinedzzsiee.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/ErrorEstimators/combinedzzsiee.h" +#include "sm/ErrorEstimators/combinedzzsiee.h" #include "domain.h" #include "element.h" #include "connectivitytable.h" @@ -84,14 +84,14 @@ RemeshingCriteria * CombinedZZSIErrorEstimator :: giveRemeshingCrit() { if ( !this->rc ) { - this->rc.reset( new CombinedZZSIRemeshingCriteria(1, this) ); + this->rc = std::make_unique(1, this); } return this->rc.get(); } -IRResultType -CombinedZZSIErrorEstimator :: initializeFrom(InputRecord *ir) +void +CombinedZZSIErrorEstimator :: initializeFrom(InputRecord &ir) { zzee.initializeFrom(ir); siee.initializeFrom(ir); @@ -160,14 +160,11 @@ CombinedZZSIRemeshingCriteria :: estimateMeshDensities(TimeStep *tStep) return 1; } -IRResultType -CombinedZZSIRemeshingCriteria :: initializeFrom(InputRecord *ir) +void +CombinedZZSIRemeshingCriteria :: initializeFrom(InputRecord &ir) { - IRResultType result = zzrc.initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - return dirc.initializeFrom(ir); + zzrc.initializeFrom(ir); + dirc.initializeFrom(ir); } diff --git a/src/sm/ErrorEstimators/combinedzzsiee.h b/src/sm/ErrorEstimators/combinedzzsiee.h index 6c5d11619..9ff693607 100644 --- a/src/sm/ErrorEstimators/combinedzzsiee.h +++ b/src/sm/ErrorEstimators/combinedzzsiee.h @@ -35,9 +35,11 @@ #ifndef combinedzzsiee_h #define combinedzzsiee_h -#include "../sm/ErrorEstimators/zzerrorestimator.h" -#include "../sm/ErrorEstimators/scalarerrorindicator.h" -#include "../sm/ErrorEstimators/directerrorindicatorrc.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" +#include "sm/ErrorEstimators/scalarerrorindicator.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" + +#define _IFT_CombinedZZSIErrorEstimator_Name "zzscalar" namespace oofem { /** @@ -65,15 +67,15 @@ class CombinedZZSIErrorEstimator : public ErrorEstimator /// Destructor virtual ~CombinedZZSIErrorEstimator() { } - virtual double giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep); - virtual double giveValue(EE_ValueType type, TimeStep *tStep); + double giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep) override; + double giveValue(EE_ValueType type, TimeStep *tStep) override; - virtual int estimateError(EE_ErrorMode mode, TimeStep *tStep); - virtual RemeshingCriteria *giveRemeshingCrit(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveInputRecordName() const { return NULL; } - virtual const char *giveClassName() const { return "CombinedZZSIErrorEstimator"; } - virtual void setDomain(Domain *d); + int estimateError(EE_ErrorMode mode, TimeStep *tStep) override; + RemeshingCriteria *giveRemeshingCrit() override; + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_CombinedZZSIErrorEstimator_Name; } + const char *giveClassName() const override { return "CombinedZZSIErrorEstimator"; } + void setDomain(Domain *d) override; }; /** @@ -101,14 +103,14 @@ class CombinedZZSIRemeshingCriteria : public RemeshingCriteria /// Destructor virtual ~CombinedZZSIRemeshingCriteria() { } - virtual double giveRequiredDofManDensity(int num, TimeStep *tStep, int relative = 0); - virtual double giveDofManDensity(int num); - virtual RemeshingStrategy giveRemeshingStrategy(TimeStep *tStep); - virtual int estimateMeshDensities(TimeStep *tStep); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveInputRecordName() const { return NULL; } - virtual const char *giveClassName() const { return "CombinedZZSIRemeshingCriteria"; } - virtual void setDomain(Domain *d); + double giveRequiredDofManDensity(int num, TimeStep *tStep, int relative = 0) override; + double giveDofManDensity(int num) override; + RemeshingStrategy giveRemeshingStrategy(TimeStep *tStep) override; + int estimateMeshDensities(TimeStep *tStep) override; + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return nullptr; } + const char *giveClassName() const override { return "CombinedZZSIRemeshingCriteria"; } + void setDomain(Domain *d) override; }; } // end namespace oofem #endif // combinedzzsiee_h diff --git a/src/sm/ErrorEstimators/directerrorindicatorrc.C b/src/sm/ErrorEstimators/directerrorindicatorrc.C index be379462c..0ac644b1d 100644 --- a/src/sm/ErrorEstimators/directerrorindicatorrc.C +++ b/src/sm/ErrorEstimators/directerrorindicatorrc.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/ErrorEstimators/directerrorindicatorrc.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" #include "errorestimator.h" #include "domain.h" #include "element.h" @@ -235,11 +235,9 @@ DirectErrorIndicatorRC :: giveRequiredDofManDensity(int num, TimeStep *tStep, in } -IRResultType -DirectErrorIndicatorRC :: initializeFrom(InputRecord *ir) +void +DirectErrorIndicatorRC :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, minIndicatorLimit, _IFT_DirectErrorIndicatorRC_minlim); IR_GIVE_FIELD(ir, maxIndicatorLimit, _IFT_DirectErrorIndicatorRC_maxlim); IR_GIVE_FIELD(ir, minIndicatorDensity, _IFT_DirectErrorIndicatorRC_mindens); @@ -255,7 +253,6 @@ DirectErrorIndicatorRC :: initializeFrom(InputRecord *ir) communicator = new NodeCommunicator(emodel, commBuff, emodel->giveRank(), emodel->giveNumberOfProcesses()); #endif - return IRRT_OK; } RemeshingStrategy @@ -316,13 +313,12 @@ DirectErrorIndicatorRC :: exchangeDofManDensities() int DirectErrorIndicatorRC :: packSharedDofManLocalDensities(ProcessCommunicator &processComm) { - int result = 1, i, size; + int result = 1; ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); - IntArray const *toSendMap = processComm.giveToSendMap(); + const IntArray &toSendMap = processComm.giveToSendMap(); - size = toSendMap->giveSize(); - for ( i = 1; i <= size; i++ ) { - result &= pcbuff->write(this->sharedDofManDensities [ toSendMap->at(i) ]); + for ( int inode : toSendMap ) { + result &= pcbuff->write(this->sharedDofManDensities [ inode ]); } return result; @@ -332,17 +328,15 @@ int DirectErrorIndicatorRC :: unpackSharedDofManLocalDensities(ProcessCommunicator &processComm) { int result = 1; - int i, size; - IntArray const *toRecvMap = processComm.giveToRecvMap(); + const IntArray &toRecvMap = processComm.giveToRecvMap(); ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); double value; - size = toRecvMap->giveSize(); - for ( i = 1; i <= size; i++ ) { + for ( int inode : toRecvMap ) { result &= pcbuff->read(value); - this->sharedDofManDensities [ toRecvMap->at(i) ] = max(value, this->sharedDofManDensities [ toRecvMap->at(i) ]); + this->sharedDofManDensities [ inode ] = max(value, this->sharedDofManDensities [ inode ]); #ifdef __VERBOSE_PARALLEL - OOFEM_LOG_INFO("unpackSharedDofManLocalDensities: node %d[%d], value %f\n", toRecvMap->at(i), domain->giveDofManager( toRecvMap->at(i) )->giveGlobalNumber(), this->sharedDofManDensities [ toRecvMap->at(i) ]); + OOFEM_LOG_INFO("unpackSharedDofManLocalDensities: node %d[%d], value %f\n", inode, domain->giveDofManager( inode )->giveGlobalNumber(), this->sharedDofManDensities [ inode ]); #endif } @@ -376,14 +370,12 @@ DirectErrorIndicatorRC :: exchangeDofManIndicatorVals(TimeStep *tStep) int DirectErrorIndicatorRC :: packSharedDofManLocalIndicatorVals(ProcessCommunicator &processComm) { - int result = 1, i, size; - //Domain *d = this->giveDomain(); + int result = 1; ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); - IntArray const *toSendMap = processComm.giveToSendMap(); + const IntArray &toSendMap = processComm.giveToSendMap(); - size = toSendMap->giveSize(); - for ( i = 1; i <= size; i++ ) { - result &= pcbuff->write(this->sharedDofManIndicatorVals [ toSendMap->at(i) ]); + for ( int inode : toSendMap ) { + result &= pcbuff->write(this->sharedDofManIndicatorVals [ inode ]); } return result; @@ -393,17 +385,15 @@ int DirectErrorIndicatorRC :: unpackSharedDofManLocalIndicatorVals(ProcessCommunicator &processComm) { int result = 1; - int i, size; - IntArray const *toRecvMap = processComm.giveToRecvMap(); + const IntArray &toRecvMap = processComm.giveToRecvMap(); ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); - double value; - size = toRecvMap->giveSize(); - for ( i = 1; i <= size; i++ ) { + for ( int inode : toRecvMap ) { + double value; result &= pcbuff->read(value); - this->sharedDofManIndicatorVals [ toRecvMap->at(i) ] = max(value, this->sharedDofManIndicatorVals [ toRecvMap->at(i) ]); + this->sharedDofManIndicatorVals [ inode ] = max(value, this->sharedDofManIndicatorVals [ inode ]); #ifdef __VERBOSE_PARALLEL - OOFEM_LOG_INFO("unpackSharedDofManLocalIndicatorVals: node %d[%d], value %f\n", toRecvMap->at(i), domain->giveDofManager( toRecvMap->at(i) )->giveGlobalNumber(), this->sharedDofManIndicatorVals [ toRecvMap->at(i) ]); + OOFEM_LOG_INFO("unpackSharedDofManLocalIndicatorVals: node %d[%d], value %f\n", inode, domain->giveDofManager( inode )->giveGlobalNumber(), this->sharedDofManIndicatorVals [ inode ]); #endif } diff --git a/src/sm/ErrorEstimators/directerrorindicatorrc.h b/src/sm/ErrorEstimators/directerrorindicatorrc.h index 033bd09ac..dd85af563 100644 --- a/src/sm/ErrorEstimators/directerrorindicatorrc.h +++ b/src/sm/ErrorEstimators/directerrorindicatorrc.h @@ -95,25 +95,25 @@ class DirectErrorIndicatorRC : public RemeshingCriteria DirectErrorIndicatorRC(int n, ErrorEstimator * e); virtual ~DirectErrorIndicatorRC(); - virtual double giveRequiredDofManDensity(int num, TimeStep *tStep, int relative = 0); - virtual double giveDofManDensity(int num); + double giveRequiredDofManDensity(int num, TimeStep *tStep, int relative = 0) override; + double giveDofManDensity(int num) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual int estimateMeshDensities(TimeStep *tStep); - virtual RemeshingStrategy giveRemeshingStrategy(TimeStep *tStep); + int estimateMeshDensities(TimeStep *tStep) override; + RemeshingStrategy giveRemeshingStrategy(TimeStep *tStep) override; /// Returns the minimum indicator limit. double giveMinIndicatorLimit() { return minIndicatorLimit; } double giveMinIndicatorDensity() { return minIndicatorDensity; } void giveNodeChar(int inode, TimeStep *tStep, double &indicatorVal, double &currDensity); double giveZeroIndicatorDensity() { return zeroIndicatorDensity; } - virtual void reinitialize(); + void reinitialize() override; - virtual void setDomain(Domain *d); + void setDomain(Domain *d) override; - virtual const char *giveInputRecordName() const { return NULL; } - virtual const char *giveClassName() const { return "DirectErrorIndicatorRC"; } + const char *giveInputRecordName() const override { return nullptr; } + const char *giveClassName() const override { return "DirectErrorIndicatorRC"; } protected: double giveLocalDofManDensity(int num); diff --git a/src/sm/ErrorEstimators/huertaerrorestimator.C b/src/sm/ErrorEstimators/huertaerrorestimator.C index f0e4c2a55..bc117686d 100644 --- a/src/sm/ErrorEstimators/huertaerrorestimator.C +++ b/src/sm/ErrorEstimators/huertaerrorestimator.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/ErrorEstimators/huertaerrorestimator.h" -#include "../sm/EngineeringModels/adaptnlinearstatic.h" -#include "../sm/EngineeringModels/adaptlinearstatic.h" +#include "sm/ErrorEstimators/huertaerrorestimator.h" +#include "sm/EngineeringModels/adaptnlinearstatic.h" +#include "sm/EngineeringModels/adaptlinearstatic.h" #include "domain.h" #include "node.h" #include "element.h" @@ -70,6 +70,7 @@ #include #include +#include namespace oofem { @@ -124,7 +125,7 @@ static FloatArray exactCoarseError; //static FloatArray uNormArray; -static DynamicDataReader refinedReader; +static DynamicDataReader refinedReader("huerta"); static int impCSect, perCSect; static FloatArray impPos; @@ -435,9 +436,8 @@ HuertaErrorEstimator :: estimateError(EE_ErrorMode err_mode, TimeStep *tStep) // it would be much cleaner to call restore from engng model while ( tStepNumber < curNumber ) { try { - //FileDataStream stream(this->giveContextFileName(tStepNumber, 0), false); - //model->restoreContext(stream, CM_State ); - model->restoreContext(NULL, CM_State, ( void * ) & tStepNumber); + FileDataStream stream(model->giveContextFileName(tStepNumber, 0), false); + model->restoreContext(stream, CM_State ); } catch(ContextIOERR & c) { c.print(); exit(1); @@ -556,17 +556,16 @@ RemeshingCriteria * HuertaErrorEstimator :: giveRemeshingCrit() { if ( !this->rc ) { - this->rc.reset( new HuertaRemeshingCriteria(1, this) ); + this->rc = std::make_unique(1, this); } return this->rc.get(); } -IRResultType -HuertaErrorEstimator :: initializeFrom(InputRecord *ir) +void +HuertaErrorEstimator :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro int n, level, wErrorFlag = 0; ErrorEstimator :: initializeFrom(ir); @@ -638,8 +637,8 @@ HuertaErrorEstimator :: initializeFrom(InputRecord *ir) } -contextIOResultType -HuertaErrorEstimator :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +HuertaErrorEstimator :: saveContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; TimeStep *tStep = this->domain->giveEngngModel()->giveCurrentStep(); @@ -649,9 +648,7 @@ HuertaErrorEstimator :: saveContext(DataStream &stream, ContextMode mode, void * } // save parent class status - if ( ( iores = ErrorEstimator :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + ErrorEstimator :: saveContext(stream, mode); if ( ( iores = this->eNorms.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); @@ -661,20 +658,16 @@ HuertaErrorEstimator :: saveContext(DataStream &stream, ContextMode mode, void * if ( !stream.write(stateCounter) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -HuertaErrorEstimator :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +HuertaErrorEstimator :: restoreContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; // read parent class status - if ( ( iores = ErrorEstimator :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + ErrorEstimator :: restoreContext(stream, mode); if ( ( iores = eNorms.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); @@ -684,8 +677,6 @@ HuertaErrorEstimator :: restoreContext(DataStream &stream, ContextMode mode, voi if ( !stream.read(stateCounter) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } @@ -984,10 +975,9 @@ HuertaRemeshingCriteria :: estimateMeshDensities(TimeStep *tStep) } -IRResultType -HuertaRemeshingCriteria :: initializeFrom(InputRecord *ir) +void +HuertaRemeshingCriteria :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro double coeff; int noRemeshFlag = 0, wErrorFlag = 0; @@ -1010,8 +1000,6 @@ HuertaRemeshingCriteria :: initializeFrom(InputRecord *ir) if ( coeff > 0.0 && coeff <= 1.0 ) { this->refineCoeff = coeff; } - - return IRRT_OK; } @@ -1083,7 +1071,7 @@ void HuertaErrorEstimatorInterface :: setupRefinedElementProblem1D(Element *element, RefinedElement *refinedElement, int level, int nodeId, IntArray &localNodeIdArray, IntArray &globalNodeIdArray, HuertaErrorEstimatorInterface :: SetupMode mode, TimeStep *tStep, int nodes, - FloatArray **corner, FloatArray &midNode, + FloatArray *corner, FloatArray &midNode, int &localNodeId, int &localElemId, int &localBcId, IntArray &controlNode, IntArray &controlDof, HuertaErrorEstimator :: AnalysisMode aMode, const char *edgetype) @@ -1147,7 +1135,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem1D(Element *element, if ( mode == HuertaErrorEstimatorInterface :: NodeMode ) { double x, y, z, u, du = 1.0 / ( level + 1 ); double xc, yc, zc, xm, ym, zm; - int idof, sideNumBc, bcId, bcDofId; + int sideNumBc, bcId, bcDofId; IntArray sideBcDofId, dofIdArray, *loadArray; FloatMatrix *lcs; bool hasBc; @@ -1155,9 +1143,9 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem1D(Element *element, element->giveElementDofIDMask(dofIdArray); for ( int inode = startNode; inode <= endNode; inode++ ) { - xc = corner [ inode - 1 ]->at(1); - yc = corner [ inode - 1 ]->at(2); - zc = corner [ inode - 1 ]->at(3); + xc = corner [ inode - 1 ].at(1); + yc = corner [ inode - 1 ].at(2); + zc = corner [ inode - 1 ].at(3); xm = midNode.at(1); ym = midNode.at(2); @@ -1178,7 +1166,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem1D(Element *element, for ( int m = 0; m < level + 2; m++, u += du, pos++ ) { nd = connectivity->at(pos); if ( localNodeIdArray.at(nd) == 0 ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); localNodeIdArray.at(nd) = ++localNodeId; globalNodeIdArray.at(localNodeId) = nd; @@ -1259,7 +1247,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem1D(Element *element, // I rely on the fact that bc dofs to be reproduced are ordered with respect to the dof ordering of the corner node bcId = 1; - for ( idof = 1; idof <= dofs; idof++ ) { + for ( int idof = 1; idof <= dofs; idof++ ) { bcDofId = 0; if ( bcId <= sideNumBc ) { auto nodeDof = node->giveDofWithID( sideBcDofId.at(bcId) ); @@ -1286,7 +1274,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem1D(Element *element, } } - refinedReader.insertInputRecord(DataReader :: IR_dofmanRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_dofmanRec, std::move(ir)); } } } @@ -1309,7 +1297,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem1D(Element *element, hasLoad = refinedElement->giveBoundaryLoadArray1D(inode, element, boundaryLoadArray); for ( int m = 0; m < level + 1; m++ ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); localElemId++; ir->setRecordKeywordField(edgetype, localElemId); @@ -1354,7 +1342,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem1D(Element *element, } } - refinedReader.insertInputRecord(DataReader :: IR_elemRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_elemRec, std::move(ir)); } } } @@ -1374,9 +1362,9 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem1D(Element *element, GaussPoint gp(&ir, 1, {}, 1.0, mmode); for ( int inode = startNode; inode <= endNode; inode++ ) { - xc = corner [ inode - 1 ]->at(1); - yc = corner [ inode - 1 ]->at(2); - zc = corner [ inode - 1 ]->at(3); + xc = corner [ inode - 1 ].at(1); + yc = corner [ inode - 1 ].at(2); + zc = corner [ inode - 1 ].at(3); xm = midNode.at(1); ym = midNode.at(2); @@ -1431,11 +1419,11 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem1D(Element *element, // first loadtime function must be constant 1.0 for ( int idof = 1; idof <= dofs; idof++ ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); ir->setRecordKeywordField(_IFT_BoundaryCondition_Name, ++localBcId); ir->setField(1, _IFT_GeneralBoundaryCondition_timeFunct); ir->setField(uFine.at(idof), _IFT_BoundaryCondition_PrescribedValue); - refinedReader.insertInputRecord(DataReader :: IR_bcRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_bcRec, std::move(ir)); } } } @@ -1493,7 +1481,7 @@ void HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, RefinedElement *refinedElement, int level, int nodeId, IntArray &localNodeIdArray, IntArray &globalNodeIdArray, HuertaErrorEstimatorInterface :: SetupMode mode, TimeStep *tStep, int nodes, - FloatArray **corner, FloatArray *midSide, FloatArray &midNode, + FloatArray *corner, FloatArray *midSide, FloatArray &midNode, int &localNodeId, int &localElemId, int &localBcId, IntArray &controlNode, IntArray &controlDof, HuertaErrorEstimator :: AnalysisMode aMode, const char *quadtype) @@ -1573,7 +1561,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, } if ( mode == HuertaErrorEstimatorInterface :: NodeMode ) { - int s1, s2, idof, index; + int s1, s2, index; double x, y, z, u, v, du = 1.0 / ( level + 1 ), dv = 1.0 / ( level + 1 ); double xc, yc, zc, xs1, ys1, zs1, xs2, ys2, zs2, xm, ym, zm; int bcId, bcDofId; @@ -1592,9 +1580,9 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, s2 = nodes; } - xc = corner [ inode - 1 ]->at(1); - yc = corner [ inode - 1 ]->at(2); - zc = corner [ inode - 1 ]->at(3); + xc = corner [ inode - 1 ].at(1); + yc = corner [ inode - 1 ].at(2); + zc = corner [ inode - 1 ].at(3); xs1 = midSide [ s1 - 1 ].at(1); ys1 = midSide [ s1 - 1 ].at(2); @@ -1625,7 +1613,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, for ( m = 0; m < level + 2; m++, u += du, pos++ ) { nd = connectivity->at(pos); if ( localNodeIdArray.at(nd) == 0 ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); ir->setRecordKeywordField("node", localNodeId); localNodeIdArray.at(nd) = ++localNodeId; @@ -1685,7 +1673,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, if ( bc == 1 ) { if ( aMode == HuertaErrorEstimator :: HEE_linear ) { FloatArray bcs(dofs); - for ( idof = 0; idof < dofs; idof++ ) { + for ( int idof = 0; idof < dofs; idof++ ) { bcs.at(idof) = ++localBcId; } ir->setField(bcs, "bc"); @@ -1731,7 +1719,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, const IntArray &sideBcDofId = sideBcDofIdList[index-1]; bcId = 1; - for ( idof = 1; idof <= dofs; idof++ ) { + for ( int idof = 1; idof <= dofs; idof++ ) { bcDofId = 0; if ( bcId <= sideNumBc.at(index) ) { auto nodeDof = node->giveDofWithID( sideBcDofId.at(bcId) ); @@ -1757,7 +1745,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, } } - refinedReader.insertInputRecord(DataReader :: IR_dofmanRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_dofmanRec, std::move(ir)); } } } @@ -1784,7 +1772,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, for ( n = 0; n < level + 1; n++ ) { for ( m = 0; m < level + 1; m++ ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); ir->setRecordKeywordField(quadtype, localElemId); localElemId++; @@ -1847,7 +1835,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, } } - refinedReader.insertInputRecord(DataReader :: IR_elemRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_elemRec, std::move(ir)); } } } @@ -1857,10 +1845,9 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, if ( mode == HuertaErrorEstimatorInterface :: BCMode ) { if ( aMode == HuertaErrorEstimator :: HEE_linear ) { - int s1, s2, idof; + int s1, s2; double u, v, du = 1.0 / ( level + 1 ), dv = 1.0 / ( level + 1 ); double xc, yc, zc, xs1, ys1, zs1, xs2, ys2, zs2, xm, ym, zm; - GaussPoint *gp; FloatArray globCoord(3); FloatMatrix Nmatrix; FloatArray uCoarse, uFine; @@ -1869,7 +1856,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, // create a fictitious integration point IntegrationRule ir(0, element); - gp = new GaussPoint( &ir, 1, {}, 1.0, mmode); + GaussPoint gp( &ir, 1, {}, 1.0, mmode); for ( inode = startNode; inode <= endNode; inode++ ) { s1 = inode; @@ -1877,9 +1864,9 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, s2 = nodes; } - xc = corner [ inode - 1 ]->at(1); - yc = corner [ inode - 1 ]->at(2); - zc = corner [ inode - 1 ]->at(3); + xc = corner [ inode - 1 ].at(1); + yc = corner [ inode - 1 ].at(2); + zc = corner [ inode - 1 ].at(3); xs1 = midSide [ s1 - 1 ].at(1); ys1 = midSide [ s1 - 1 ].at(2); @@ -1952,30 +1939,26 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, // this effectively rewrites the local coordinates of the fictitious integration point FloatArray lcoord; element->computeLocalCoordinates(lcoord, globCoord); - gp->setNaturalCoordinates(lcoord); + gp.setNaturalCoordinates(lcoord); // get N matrix at the fictitious integration point - this->HuertaErrorEstimatorI_computeNmatrixAt(gp, Nmatrix); + this->HuertaErrorEstimatorI_computeNmatrixAt(&gp, Nmatrix); // get displacement at the fictitious integration point uFine.beProductOf(Nmatrix, uCoarse); // first loadtime function must be constant 1.0 - for ( idof = 1; idof <= dofs; idof++ ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + for ( int idof = 1; idof <= dofs; idof++ ) { + auto ir = std::make_unique(); ir->setRecordKeywordField("BoundaryCondition", ++localBcId); ir->setField(1, "Function"); ir->setField(uFine.at(idof), "prescribedvalue"); - refinedReader.insertInputRecord(DataReader :: IR_bcRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_bcRec, std::move(ir)); } } } } } } - - delete gp; } else { - int idof; - for ( inode = startNode; inode <= endNode; inode++ ) { connectivity = refinedElement->giveFineNodeArray(inode); refinedElement->giveBoundaryFlagArray(inode, element, boundary); @@ -2024,7 +2007,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, #endif if ( bc == 1 ) { - for ( idof = 1; idof <= dofs; idof++ ) { + for ( int idof = 1; idof <= dofs; idof++ ) { localBcId++; controlNode.at(localBcId) = -localNodeIdArray.at(nd); controlDof.at(localBcId) = idof; @@ -2035,8 +2018,6 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem2D(Element *element, } } } - - return; } } @@ -2046,7 +2027,7 @@ void HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, RefinedElement *refinedElement, int level, int nodeId, IntArray &localNodeIdArray, IntArray &globalNodeIdArray, HuertaErrorEstimatorInterface :: SetupMode mode, TimeStep *tStep, int nodes, - FloatArray **corner, FloatArray *midSide, FloatArray *midFace, FloatArray &midNode, + FloatArray *corner, FloatArray *midSide, FloatArray *midFace, FloatArray &midNode, int &localNodeId, int &localElemId, int &localBcId, int hexaSideNode [ 1 ] [ 3 ], int hexaFaceNode [ 1 ] [ 3 ], IntArray &controlNode, IntArray &controlDof, @@ -2151,7 +2132,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, } if ( mode == HuertaErrorEstimatorInterface :: NodeMode ) { - int s1, s2, s3, f1, f2, f3, idof, index; + int s1, s2, s3, f1, f2, f3, index; double x, y, z, u, v, w, du = 1.0 / ( level + 1 ), dv = 1.0 / ( level + 1 ), dw = 1.0 / ( level + 1 ); double xc, yc, zc, xm, ym, zm; double xs1, ys1, zs1, xs2, ys2, zs2, xs3, ys3, zs3; @@ -2175,9 +2156,9 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, f2 = hexaFaceNode [ inode - 1 ] [ 1 ]; f3 = hexaFaceNode [ inode - 1 ] [ 2 ]; - xc = corner [ inode - 1 ]->at(1); - yc = corner [ inode - 1 ]->at(2); - zc = corner [ inode - 1 ]->at(3); + xc = corner [ inode - 1 ].at(1); + yc = corner [ inode - 1 ].at(2); + zc = corner [ inode - 1 ].at(3); xs1 = midSide [ s1 - 1 ].at(1); ys1 = midSide [ s1 - 1 ].at(2); @@ -2226,7 +2207,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, for ( m = 0; m < level + 2; m++, u += du, pos++ ) { nd = connectivity->at(pos); if ( localNodeIdArray.at(nd) == 0 ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); ir->setRecordKeywordField("node", localNodeId); localNodeIdArray.at(nd) = ++localNodeId; @@ -2297,7 +2278,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, if ( bc == 1 ) { if ( aMode == HuertaErrorEstimator :: HEE_linear ) { FloatArray bcs(dofs); - for ( idof = 0; idof < dofs; idof++ ) { + for ( int idof = 0; idof < dofs; idof++ ) { bcs.at(idof) = ++localBcId; } ir->setField(bcs, "bc"); @@ -2348,7 +2329,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, const IntArray &sideBcDofId = sideBcDofIdList[index-1]; bcId = 1; - for ( idof = 1; idof <= dofs; idof++ ) { + for ( int idof = 1; idof <= dofs; idof++ ) { bcDofId = 0; if ( bcId <= sideNumBc.at(index) ) { Dof *nodeDof = node->giveDofWithID( sideBcDofId.at(bcId) ); @@ -2383,7 +2364,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, const IntArray &faceBcDofId = faceBcDofIdList[index-1]; bcId = 1; - for ( idof = 1; idof <= dofs; idof++ ) { + for ( int idof = 1; idof <= dofs; idof++ ) { bcDofId = 0; if ( bcId <= faceNumBc.at(index) ) { Dof *nodeDof = node->giveDofWithID( faceBcDofId.at(bcId) ); @@ -2410,7 +2391,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, } } - refinedReader.insertInputRecord(DataReader :: IR_dofmanRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_dofmanRec, std::move(ir)); } } } @@ -2439,7 +2420,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, for ( k = 0; k < level + 1; k++ ) { for ( n = 0; n < level + 1; n++ ) { for ( m = 0; m < level + 1; m++ ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); localElemId++; @@ -2518,7 +2499,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, } } - refinedReader.insertInputRecord(DataReader :: IR_elemRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_elemRec, std::move(ir)); } } } @@ -2529,7 +2510,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, if ( mode == HuertaErrorEstimatorInterface :: BCMode ) { if ( aMode == HuertaErrorEstimator :: HEE_linear ) { - int s1, s2, s3, f1, f2, f3, idof; + int s1, s2, s3, f1, f2, f3; double u, v, w, du = 1.0 / ( level + 1 ), dv = 1.0 / ( level + 1 ), dw = 1.0 / ( level + 1 ); double xc, yc, zc, xm, ym, zm; double xs1, ys1, zs1, xs2, ys2, zs2, xs3, ys3, zs3; @@ -2551,9 +2532,9 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, f2 = hexaFaceNode [ inode - 1 ] [ 1 ]; f3 = hexaFaceNode [ inode - 1 ] [ 2 ]; - xc = corner [ inode - 1 ]->at(1); - yc = corner [ inode - 1 ]->at(2); - zc = corner [ inode - 1 ]->at(3); + xc = corner [ inode - 1 ].at(1); + yc = corner [ inode - 1 ].at(2); + zc = corner [ inode - 1 ].at(3); xs1 = midSide [ s1 - 1 ].at(1); ys1 = midSide [ s1 - 1 ].at(2); @@ -2662,12 +2643,12 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, uFine.beProductOf(Nmatrix, uCoarse); // first loadtime function must be constant 1.0 - for ( idof = 1; idof <= dofs; idof++ ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + for ( int idof = 1; idof <= dofs; idof++ ) { + auto ir = std::make_unique(); ir->setRecordKeywordField("boundarycondition", ++localBcId); ir->setField(1, "Function"); ir->setField(uFine.at(idof), "prescribedvalue"); - refinedReader.insertInputRecord(DataReader :: IR_bcRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_bcRec, std::move(ir)); } } } @@ -2677,8 +2658,6 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, } } else { - int idof; - for ( inode = startNode; inode <= endNode; inode++ ) { connectivity = refinedElement->giveFineNodeArray(inode); refinedElement->giveBoundaryFlagArray(inode, element, boundary); @@ -2736,7 +2715,7 @@ HuertaErrorEstimatorInterface :: setupRefinedElementProblem3D(Element *element, #endif if ( bc == 1 ) { - for ( idof = 1; idof <= dofs; idof++ ) { + for ( int idof = 1; idof <= dofs; idof++ ) { localBcId++; controlNode.at(localBcId) = -localNodeIdArray.at(nd); controlDof.at(localBcId) = idof; @@ -2765,10 +2744,11 @@ HuertaErrorEstimator :: solveRefinedElementProblem(int elemId, IntArray &localNo Element *element; RefinedElement *refinedElement; HuertaErrorEstimatorInterface *interface; - EngngModel *problem, *refinedProblem; + EngngModel *problem; + std::unique_ptr refinedProblem; int localNodeId, localElemId, localBcId, localf; int mats, csects, loads, funcs, nlbarriers; - int inode, idof, dofs, pos, ielem, size; + int inode, dofs, pos, ielem, size; IntArray dofIdArray; FloatArray nodeSolution, uCoarse, elementVector, patchVector, coarseVector; FloatArray elementError, patchError, coarseSolution; @@ -2913,7 +2893,7 @@ HuertaErrorEstimator :: solveRefinedElementProblem(int elemId, IntArray &localNo #ifdef TIME_INFO timer.startTimer(); #endif - refinedProblem = InstanciateProblem(& refinedReader, _processor, contextFlag); + refinedProblem = InstanciateProblem(refinedReader, _processor, contextFlag); refinedReader.finish(); #ifdef TIME_INFO timer.stopTimer(); @@ -2938,9 +2918,9 @@ HuertaErrorEstimator :: solveRefinedElementProblem(int elemId, IntArray &localNo refinedProblem->solveYourself(); refinedProblem->terminateAnalysis(); } else { - AdaptiveNonLinearStatic *prob = dynamic_cast< AdaptiveNonLinearStatic * >(refinedProblem); + AdaptiveNonLinearStatic *prob = dynamic_cast< AdaptiveNonLinearStatic * >(refinedProblem.get()); if ( prob ) { - static_cast< AdaptiveNonLinearStatic * >(refinedProblem)->initializeAdaptiveFrom(problem); + prob->initializeAdaptiveFrom(problem); } else { OOFEM_ERROR("Refined problem must be of the type AdaptiveNonLinearStatic"); } @@ -2971,7 +2951,7 @@ HuertaErrorEstimator :: solveRefinedElementProblem(int elemId, IntArray &localNo for ( inode = 1; inode <= localNodeId; inode++ ) { node = refinedDomain->giveNode(inode); node->giveUnknownVector(nodeSolution, dofIdArray, VM_Total, refinedTStep); - for ( idof = 1; idof <= dofs; idof++, pos++ ) { + for ( int idof = 1; idof <= dofs; idof++, pos++ ) { double sol = nodeSolution.at(idof); nodeDof = node->giveDofWithID(dofIdArray.at(idof)); if ( nodeDof->hasBc(refinedTStep) == 0 ) { @@ -3117,7 +3097,7 @@ HuertaErrorEstimator :: solveRefinedElementProblem(int elemId, IntArray &localNo // be carefull to not overwrite data needed in further calculations // pos = 1; // for(inode = 1; inode <= localNodeId; inode++){ - // for(idof = 1; idof <= dofs; idof++, pos++)primaryUnknownError.at((globalNodeIdArray.at(inode) - 1) * dofs + idof) = + // for(int idof = 1; idof <= dofs; idof++, pos++)primaryUnknownError.at((globalNodeIdArray.at(inode) - 1) * dofs + idof) = // elementError.at(pos) * (1.0 - coeff) + patchError.at(pos); // } @@ -3181,8 +3161,6 @@ HuertaErrorEstimator :: solveRefinedElementProblem(int elemId, IntArray &localNo et_solve, et_error); #endif - - delete refinedProblem; } @@ -3195,7 +3173,8 @@ HuertaErrorEstimator :: solveRefinedPatchProblem(int nodeId, IntArray &localNode Element *element; RefinedElement *refinedElement; HuertaErrorEstimatorInterface *interface; - EngngModel *problem, *refinedProblem; + EngngModel *problem; + std::unique_ptr refinedProblem; int localNodeId, localElemId, localBcId, localf; int mats, csects, loads, funcs, nlbarriers; int inode, elemId, ielem, elems, skipped = 0; @@ -3447,7 +3426,7 @@ HuertaErrorEstimator :: solveRefinedPatchProblem(int nodeId, IntArray &localNode #ifdef TIME_INFO timer.startTimer(); #endif - refinedProblem = InstanciateProblem(& refinedReader, _processor, contextFlag); + refinedProblem = InstanciateProblem(refinedReader, _processor, contextFlag); refinedReader.finish(); #ifdef TIME_INFO timer.stopTimer(); @@ -3467,9 +3446,9 @@ HuertaErrorEstimator :: solveRefinedPatchProblem(int nodeId, IntArray &localNode refinedProblem->solveYourself(); refinedProblem->terminateAnalysis(); } else { - AdaptiveNonLinearStatic *prob = dynamic_cast< AdaptiveNonLinearStatic * >(refinedProblem); + AdaptiveNonLinearStatic *prob = dynamic_cast< AdaptiveNonLinearStatic * >(refinedProblem.get()); if ( prob ) { - static_cast< AdaptiveNonLinearStatic * >(refinedProblem)->initializeAdaptiveFrom(problem); + prob->initializeAdaptiveFrom(problem); } else { OOFEM_ERROR("Refined problem must be of the type AdaptiveNonLinearStatic"); } @@ -3508,8 +3487,6 @@ HuertaErrorEstimator :: solveRefinedPatchProblem(int nodeId, IntArray &localNode et_solve, et_error); #endif - - delete refinedProblem; } @@ -3526,10 +3503,10 @@ HuertaErrorEstimator :: solveRefinedWholeProblem(IntArray &localNodeIdArray, Int Element *element; RefinedElement *refinedElement; HuertaErrorEstimatorInterface *interface; - EngngModel *refinedProblem; + std::unique_ptr refinedProblem; int localNodeId, localElemId, localBcId, localf; int mats, csects, loads, funcs, nlbarriers; - int inode, idof, dofs, elemId, ielem, elems, size; + int inode, dofs, elemId, ielem, elems, size; IntArray dofIdArray; FloatArray nodeSolution, uCoarse, errorVector, coarseVector, fineVector; FloatArray fineSolution, coarseSolution, errorSolution; @@ -3673,7 +3650,7 @@ HuertaErrorEstimator :: solveRefinedWholeProblem(IntArray &localNodeIdArray, Int #ifdef TIME_INFO timer.startTimer(); #endif - refinedProblem = InstanciateProblem(& refinedReader, _processor, contextFlag); + refinedProblem = InstanciateProblem(refinedReader, _processor, contextFlag); #ifdef TIME_INFO timer.stopTimer(); et_init = timer.getUtime(); @@ -3720,7 +3697,7 @@ HuertaErrorEstimator :: solveRefinedWholeProblem(IntArray &localNodeIdArray, Int for ( inode = 1; inode <= localNodeId; inode++ ) { node = refinedDomain->giveNode(inode); node->giveUnknownVector(nodeSolution, dofIdArray, VM_Total, refinedTStep); - for ( idof = 1; idof <= dofs; idof++, pos++ ) { + for ( int idof = 1; idof <= dofs; idof++, pos++ ) { fineSolution.at(pos) = nodeSolution.at(idof); nodeDof = node->giveDofWithID(dofIdArray.at(idof)); if ( nodeDof->hasBc(refinedTStep) == 0 ) { @@ -3870,8 +3847,6 @@ HuertaErrorEstimator :: solveRefinedWholeProblem(IntArray &localNodeIdArray, Int et_solve, et_error); #endif - - delete refinedProblem; } #endif @@ -3883,12 +3858,12 @@ void HuertaErrorEstimator :: extractVectorFrom(Element *element, FloatArray &vector, FloatArray &answer, int dofs, TimeStep *tStep) { - int inode, idof, pos, p = 0; + int p = 0; answer.resize(element->giveNumberOfDofManagers() * dofs); - for ( inode = 1; inode <= element->giveNumberOfNodes(); inode++ ) { - pos = ( element->giveDofManager(inode)->giveNumber() - 1 ) * dofs; - for ( idof = 1; idof <= dofs; idof++ ) { + for ( int inode = 1; inode <= element->giveNumberOfNodes(); inode++ ) { + int pos = ( element->giveDofManager(inode)->giveNumber() - 1 ) * dofs; + for ( int idof = 1; idof <= dofs; idof++ ) { answer.at(++p) = vector.at(pos + idof); } } @@ -3909,7 +3884,6 @@ HuertaErrorEstimator :: setupRefinedProblemProlog(const char *problemName, int p double rtolv = -1.0, minStepLength = 0.0, initialStepLength = -1.0, stepLength = -1.0, psi = 1.0; IntArray ddm, hpc; FloatArray ddv, hpcw; - IRResultType result; // Required by IR_GIVE_FIELD macro #if defined ( USE_OUTPUT_FILE ) || defined ( USE_CONTEXT_FILE ) sprintf(line, "/home/dr/Huerta/%s_%d.out", problemName, problemId); @@ -3929,18 +3903,17 @@ HuertaErrorEstimator :: setupRefinedProblemProlog(const char *problemName, int p refinedReader.setDescription(line); if ( dynamic_cast< AdaptiveLinearStatic * >(problem) ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); ir->setRecordKeywordField(_IFT_LinearStatic_Name, 0); ir->setField(1, _IFT_EngngModel_nsteps); ir->setField(renumber, _IFT_EngngModel_renumberFlag); #ifdef USE_CONTEXT_FILE ir->setField(contextOutputStep, _IFT_EngngModel_contextoutputstep); #endif - refinedReader.insertInputRecord(DataReader :: IR_emodelRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_emodelRec, std::move(ir)); } else if ( dynamic_cast< AdaptiveNonLinearStatic * >(problem) ) { - InputRecord *ir; nmstep = tStep->giveMetaStepNumber(); - ir = problem->giveMetaStep(nmstep)->giveAttributesRecord(); + auto &ir = problem->giveMetaStep(nmstep)->giveAttributesRecord(); IR_GIVE_OPTIONAL_FIELD(ir, stiffMode, _IFT_NonLinearStatic_stiffmode); IR_GIVE_OPTIONAL_FIELD(ir, controlMode, _IFT_NonLinearStatic_controlmode); @@ -3984,7 +3957,7 @@ HuertaErrorEstimator :: setupRefinedProblemProlog(const char *problemName, int p } if ( problemId != 0 ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); int bcSize = controlNode.giveSize(), ddActiveSize = 0; @@ -4056,7 +4029,7 @@ HuertaErrorEstimator :: setupRefinedProblemProlog(const char *problemName, int p ir->setField(0.1, "requiredError"); ir->setField(0.01, "minelemsize"); - refinedReader.insertInputRecord(DataReader :: IR_emodelRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_emodelRec, std::move(ir)); // IMPORTANT: the total number of steps should be equal to the current step number // (to enable skipUpdate) @@ -4064,16 +4037,16 @@ HuertaErrorEstimator :: setupRefinedProblemProlog(const char *problemName, int p // create fictitious metasteps for ( i = 1; i < nmstep; i++ ) { - DynamicInputRecord *ir_meta = new DynamicInputRecord(); + auto ir_meta = std::make_unique(); ir_meta->setRecordKeywordField(_IFT_MetaStep_Name, i); ir_meta->setField(problem->giveMetaStep(i)->giveNumberOfSteps(), _IFT_MetaStep_nsteps); ir_meta->setField(rtolv, "rtolv"); - refinedReader.insertInputRecord(DataReader :: IR_mstepRec, ir_meta); + refinedReader.insertInputRecord(DataReader :: IR_mstepRec, std::move(ir_meta)); nsteps += problem->giveMetaStep(i)->giveNumberOfSteps(); } // create active metastep - ir = new DynamicInputRecord(); + ir = std::make_unique(); ir->setRecordKeywordField(_IFT_MetaStep_Name, nmstep); ir->setField(tStep->giveNumber() - nsteps, _IFT_MetaStep_nsteps); ir->setField(rtolv, "rtolv"); @@ -4129,7 +4102,7 @@ HuertaErrorEstimator :: setupRefinedProblemProlog(const char *problemName, int p // use last funcs to control dd ir->setField(funcs, _IFT_NRSolver_ddfunc); - refinedReader.insertInputRecord(DataReader :: IR_mstepRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_mstepRec, std::move(ir)); } else { // it makes not too much sense to solve exact problem from beginning if adaptive restart is used // because the mesh may be already derefined in regions of no interest (but anyway ...) @@ -4141,7 +4114,7 @@ HuertaErrorEstimator :: setupRefinedProblemProlog(const char *problemName, int p // do not prescribe skipUpdate here !!! // HUHU dodelat metasteps, dodelat paralelni zpracovani - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); ir->setRecordKeywordField("nonlinearstatic", 0); ir->setField( ( int ) ( problem->giveCurrentStep()->giveTargetTime() + 1.5 ), "nsteps" ); ir->setField(renumber, "renumber"); @@ -4199,22 +4172,22 @@ HuertaErrorEstimator :: setupRefinedProblemProlog(const char *problemName, int p break; } - refinedReader.insertInputRecord(DataReader :: IR_emodelRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_emodelRec, std::move(ir)); } } else { OOFEM_ERROR("Unsupported analysis type"); } - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); ir->setField(this->domain->giveNumberOfSpatialDimensions(), _IFT_Domain_numberOfSpatialDimensions); if ( this->domain->isAxisymmetric() ) { ir->setField(_IFT_Domain_axisymmetric); } - refinedReader.insertInputRecord(DataReader :: IR_domainCompRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_domainCompRec, std::move(ir)); - ir = new DynamicInputRecord(); + ir = std::make_unique(); ir->setRecordKeywordField(_IFT_OutputManager_Name, 0); #ifdef USE_OUTPUT_FILE ir->setField(_IFT_OutputManager_tstepall); @@ -4222,9 +4195,9 @@ HuertaErrorEstimator :: setupRefinedProblemProlog(const char *problemName, int p ir->setField(_IFT_OutputManager_elementall); #endif - refinedReader.insertInputRecord(DataReader :: IR_outManRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_outManRec, std::move(ir)); - ir = new DynamicInputRecord(); + ir = std::make_unique(); ir->setRecordKeywordField("", 0); ir->setField(nodes, _IFT_Domain_ndofman); ir->setField(elems, _IFT_Domain_nelem); @@ -4232,7 +4205,7 @@ HuertaErrorEstimator :: setupRefinedProblemProlog(const char *problemName, int p ir->setField(csects, _IFT_Domain_nmat); ir->setField(loads, _IFT_Domain_nbc); ir->setField(funcs, _IFT_Domain_nfunct); - refinedReader.insertInputRecord(DataReader :: IR_domainCompRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_domainCompRec, std::move(ir)); } @@ -4245,21 +4218,21 @@ HuertaErrorEstimator :: setupRefinedProblemEpilog1(int csects, int mats, int loa /* copy csects, mats, loads */ for ( int i = 1; i <= csects; i++ ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); domain->giveCrossSection(i)->giveInputRecord(* ir); - refinedReader.insertInputRecord(DataReader :: IR_crosssectRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_crosssectRec, std::move(ir)); } for ( int i = 1; i <= mats; i++ ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); domain->giveMaterial(i)->giveInputRecord(* ir); - refinedReader.insertInputRecord(DataReader :: IR_matRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_matRec, std::move(ir)); } for ( int i = 1; i <= loads; i++ ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); domain->giveLoad(i)->giveInputRecord(* ir); - refinedReader.insertInputRecord(DataReader :: IR_bcRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_bcRec, std::move(ir)); } } @@ -4273,17 +4246,17 @@ HuertaErrorEstimator :: setupRefinedProblemEpilog2(int funcs) /* copy tfuncs */ for ( int i = 1; i <= funcs; i++ ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); domain->giveFunction(i)->giveInputRecord(* ir); - refinedReader.insertInputRecord(DataReader :: IR_funcRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_funcRec, std::move(ir)); } if ( this->mode == HEE_nlinear ) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); ir->setRecordKeywordField(_IFT_HeavisideTimeFunction_Name, funcs + 1); ir->setField(this->domain->giveEngngModel()->giveCurrentStep()->giveTargetTime() - 0.1, _IFT_HeavisideTimeFunction_origin); ir->setField(1., _IFT_HeavisideTimeFunction_value); - refinedReader.insertInputRecord(DataReader :: IR_funcRec, ir); + refinedReader.insertInputRecord(DataReader :: IR_funcRec, std::move(ir)); } } } // end namespace oofem diff --git a/src/sm/ErrorEstimators/huertaerrorestimator.h b/src/sm/ErrorEstimators/huertaerrorestimator.h index 5b62fed38..1280394d6 100644 --- a/src/sm/ErrorEstimators/huertaerrorestimator.h +++ b/src/sm/ErrorEstimators/huertaerrorestimator.h @@ -35,8 +35,8 @@ #ifndef huertaerrorestimator_h #define huertaerrorestimator_h -#include "../sm/refinedelement.h" -#include "../sm/refinedmesh.h" +#include "sm/refinedelement.h" +#include "sm/refinedmesh.h" #include "errorestimator.h" #include "interface.h" #include "floatarray.h" @@ -47,6 +47,7 @@ ///@name Input fields for HuertaErrorEstimator //@{ +#define _IFT_HuertaErrorEstimator_Name "huerta" #define _IFT_HuertaErrorEstimator_normtype "normtype" #define _IFT_HuertaErrorEstimator_refinelevel "refinelevel" #define _IFT_HuertaErrorEstimator_requirederror "requirederror" @@ -155,23 +156,23 @@ class HuertaErrorEstimator : public ErrorEstimator */ int giveRefinementLevel() { return this->refineLevel; } - virtual double giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep); + double giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep) override; - virtual double giveValue(EE_ValueType type, TimeStep *tStep); + double giveValue(EE_ValueType type, TimeStep *tStep) override; - virtual int estimateError(EE_ErrorMode err_mode, TimeStep *tStep); + int estimateError(EE_ErrorMode err_mode, TimeStep *tStep) override; - virtual RemeshingCriteria *giveRemeshingCrit(); + RemeshingCriteria *giveRemeshingCrit() override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveInputRecordName() const { return NULL; } - virtual const char *giveClassName() const { return "HuertaErrorEstimator"; } + const char *giveInputRecordName() const override { return nullptr; } + const char *giveClassName() const override { return "HuertaErrorEstimator"; } AnalysisMode giveAnalysisMode() { return mode; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; private: /** @@ -249,7 +250,7 @@ class HuertaErrorEstimatorInterface : public Interface void setupRefinedElementProblem1D(Element *element, RefinedElement *refinedElement, int level, int nodeId, IntArray &localNodeIdArray, IntArray &globalNodeIdArray, HuertaErrorEstimatorInterface :: SetupMode mode, TimeStep *tStep, int nodes, - FloatArray **corner, FloatArray &midNode, + FloatArray *corner, FloatArray &midNode, int &localNodeId, int &localElemId, int &localBcId, IntArray &controlNode, IntArray &controlDof, HuertaErrorEstimator :: AnalysisMode aMode, const char *edgetype); @@ -257,7 +258,7 @@ class HuertaErrorEstimatorInterface : public Interface void setupRefinedElementProblem2D(Element *element, RefinedElement *refinedElement, int level, int nodeId, IntArray &localNodeIdArray, IntArray &globalNodeIdArray, HuertaErrorEstimatorInterface :: SetupMode mode, TimeStep *tStep, int nodes, - FloatArray **corner, FloatArray *midSide, FloatArray &midNode, + FloatArray *corner, FloatArray *midSide, FloatArray &midNode, int &localNodeId, int &localElemId, int &localBcId, IntArray &controlNode, IntArray &controlDof, HuertaErrorEstimator :: AnalysisMode aMode, const char *quadtype); @@ -265,7 +266,7 @@ class HuertaErrorEstimatorInterface : public Interface void setupRefinedElementProblem3D(Element *element, RefinedElement *refinedElement, int level, int nodeId, IntArray &localNodeIdArray, IntArray &globalNodeIdArray, HuertaErrorEstimatorInterface :: SetupMode mode, TimeStep *tStep, int nodes, - FloatArray **corner, FloatArray *midSide, FloatArray *midFace, FloatArray &midNode, + FloatArray *corner, FloatArray *midSide, FloatArray *midFace, FloatArray &midNode, int &localNodeId, int &localElemId, int &localBcId, int hexaSideNode [ 1 ] [ 3 ], int hexaFaceNode [ 1 ] [ 3 ], IntArray &controlNode, IntArray &controlDof, @@ -313,14 +314,14 @@ class HuertaRemeshingCriteria : public RemeshingCriteria /// Destructor virtual ~HuertaRemeshingCriteria() { } - virtual double giveRequiredDofManDensity(int num, TimeStep *tStep, int relative = 0); - virtual double giveDofManDensity(int num); - virtual RemeshingStrategy giveRemeshingStrategy(TimeStep *tStep); - virtual int estimateMeshDensities(TimeStep *tStep); - virtual IRResultType initializeFrom(InputRecord *ir); + double giveRequiredDofManDensity(int num, TimeStep *tStep, int relative = 0) override; + double giveDofManDensity(int num) override; + RemeshingStrategy giveRemeshingStrategy(TimeStep *tStep) override; + int estimateMeshDensities(TimeStep *tStep) override; + void initializeFrom(InputRecord &ir) override; - virtual const char *giveInputRecordName() const { return NULL; } - virtual const char *giveClassName() const { return "HuertaErrorEstimator"; } + const char *giveInputRecordName() const override { return nullptr; } + const char *giveClassName() const override { return "HuertaErrorEstimator"; } }; } // end namespace oofem diff --git a/src/sm/ErrorEstimators/scalarerrorindicator.C b/src/sm/ErrorEstimators/scalarerrorindicator.C index b99373833..57df3741d 100644 --- a/src/sm/ErrorEstimators/scalarerrorindicator.C +++ b/src/sm/ErrorEstimators/scalarerrorindicator.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/ErrorEstimators/scalarerrorindicator.h" -#include "../sm/ErrorEstimators/directerrorindicatorrc.h" +#include "sm/ErrorEstimators/scalarerrorindicator.h" +#include "sm/ErrorEstimators/directerrorindicatorrc.h" #include "element.h" #include "integrationrule.h" #include "gausspoint.h" @@ -89,11 +89,9 @@ ScalarErrorIndicator :: giveElementError(EE_ErrorType type, Element *elem, TimeS } -IRResultType -ScalarErrorIndicator :: initializeFrom(InputRecord *ir) +void +ScalarErrorIndicator :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - ErrorEstimator :: initializeFrom(ir); IR_GIVE_FIELD(ir, indicatorType, _IFT_ScalarErrorIndicator_vartype); @@ -108,7 +106,7 @@ RemeshingCriteria * ScalarErrorIndicator :: giveRemeshingCrit() { if ( !this->rc ) { - this->rc.reset( new DirectErrorIndicatorRC(1, this) ); + this->rc = std::make_unique(1, this); } return this->rc.get(); diff --git a/src/sm/ErrorEstimators/scalarerrorindicator.h b/src/sm/ErrorEstimators/scalarerrorindicator.h index 5f2bcadf6..dafffdec1 100644 --- a/src/sm/ErrorEstimators/scalarerrorindicator.h +++ b/src/sm/ErrorEstimators/scalarerrorindicator.h @@ -40,6 +40,7 @@ ///@name Input fields for ScalarErrorIndicator //@{ +#define _IFT_ScalarErrorIndicator_Name "scalar" #define _IFT_ScalarErrorIndicator_vartype "vartype" //@} @@ -67,14 +68,15 @@ class ScalarErrorIndicator : public ErrorEstimator /// Destructor virtual ~ScalarErrorIndicator() { } - virtual double giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep); - virtual double giveValue(EE_ValueType type, TimeStep *tStep) { return 0.0; } - virtual int estimateError(EE_ErrorMode mode, TimeStep *tStep); - virtual RemeshingCriteria *giveRemeshingCrit(); + double giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep) override; + double giveValue(EE_ValueType type, TimeStep *tStep) override { return 0.0; } + int estimateError(EE_ErrorMode mode, TimeStep *tStep) override; + RemeshingCriteria *giveRemeshingCrit() override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveClassName() const { return "ScalarErrorIndicator"; } + const char *giveClassName() const override { return "ScalarErrorIndicator"; } + const char *giveInputRecordName() const override { return _IFT_ScalarErrorIndicator_Name; } }; } // end namespace oofem #endif // scalarerrorindicator_h diff --git a/src/sm/ErrorEstimators/zzerrorestimator.C b/src/sm/ErrorEstimators/zzerrorestimator.C index 478784335..4d2e10f61 100644 --- a/src/sm/ErrorEstimators/zzerrorestimator.C +++ b/src/sm/ErrorEstimators/zzerrorestimator.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/ErrorEstimators/zzerrorestimator.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/ErrorEstimators/zzerrorestimator.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Materials/structuralmaterial.h" #include "domain.h" #include "dofmanager.h" #include "element.h" @@ -205,17 +205,16 @@ RemeshingCriteria * ZZErrorEstimator :: giveRemeshingCrit() { if ( !this->rc ) { - this->rc.reset( new ZZRemeshingCriteria(1, this) ); + this->rc = std::make_unique(1, this); } return this->rc.get(); } -IRResultType -ZZErrorEstimator :: initializeFrom(InputRecord *ir) +void +ZZErrorEstimator :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro int n; ErrorEstimator :: initializeFrom(ir); @@ -453,15 +452,11 @@ ZZRemeshingCriteria :: estimateMeshDensities(TimeStep *tStep) return 1; } -IRResultType -ZZRemeshingCriteria :: initializeFrom(InputRecord *ir) +void +ZZRemeshingCriteria :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, this->requiredError, _IFT_ZZRemeshingCriteria_requirederror); IR_GIVE_FIELD(ir, this->minElemSize, _IFT_ZZRemeshingCriteria_minelemsize); - - return IRRT_OK; } diff --git a/src/sm/ErrorEstimators/zzerrorestimator.h b/src/sm/ErrorEstimators/zzerrorestimator.h index b635dcdc0..e0fd37ec2 100644 --- a/src/sm/ErrorEstimators/zzerrorestimator.h +++ b/src/sm/ErrorEstimators/zzerrorestimator.h @@ -46,6 +46,7 @@ ///@name Input fields for ZZErrorEstimator //@{ +#define _IFT_ZZErrorEstimator_Name "zz" #define _IFT_ZZErrorEstimator_normtype "normtype" #define _IFT_ZZErrorEstimator_recoverytype "recoverytype" //@} @@ -116,14 +117,15 @@ class ZZErrorEstimator : public ErrorEstimator /// Destructor virtual ~ZZErrorEstimator() { } - virtual double giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep); - virtual double giveValue(EE_ValueType type, TimeStep *tStep); + double giveElementError(EE_ErrorType type, Element *elem, TimeStep *tStep) override; + double giveValue(EE_ValueType type, TimeStep *tStep) override; - virtual int estimateError(EE_ErrorMode mode, TimeStep *tStep); - virtual RemeshingCriteria *giveRemeshingCrit(); + int estimateError(EE_ErrorMode mode, TimeStep *tStep) override; + RemeshingCriteria *giveRemeshingCrit() override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "ZZErrorEstimator"; } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "ZZErrorEstimator"; } + const char *giveInputRecordName() const override { return _IFT_ZZErrorEstimator_Name; } }; @@ -204,15 +206,14 @@ class ZZRemeshingCriteria : public RemeshingCriteria /// Destructor virtual ~ZZRemeshingCriteria() { } + double giveRequiredDofManDensity(int num, TimeStep *tStep, int relative = 0) override; + double giveDofManDensity(int num) override; + RemeshingStrategy giveRemeshingStrategy(TimeStep *tStep) override; + int estimateMeshDensities(TimeStep *tStep) override; + void initializeFrom(InputRecord &ir) override; - virtual double giveRequiredDofManDensity(int num, TimeStep *tStep, int relative = 0); - virtual double giveDofManDensity(int num); - virtual RemeshingStrategy giveRemeshingStrategy(TimeStep *tStep); - virtual int estimateMeshDensities(TimeStep *tStep); - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual const char *giveInputRecordName() const { return NULL; } - virtual const char *giveClassName() const { return "ZZErrorEstimator"; } + const char *giveInputRecordName() const override { return nullptr; } + const char *giveClassName() const override { return "ZZErrorEstimator"; } }; } // end namespace oofem diff --git a/src/sm/FETISolver/fetiboundarydofman.C b/src/sm/FETISolver/fetiboundarydofman.C index f9fa2e81d..b95675fca 100644 --- a/src/sm/FETISolver/fetiboundarydofman.C +++ b/src/sm/FETISolver/fetiboundarydofman.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/FETISolver/fetiboundarydofman.h" +#include "sm/FETISolver/fetiboundarydofman.h" #include "error.h" using namespace std; diff --git a/src/sm/FETISolver/feticommunicator.C b/src/sm/FETISolver/feticommunicator.C index bdb7fcf75..7aa256e52 100644 --- a/src/sm/FETISolver/feticommunicator.C +++ b/src/sm/FETISolver/feticommunicator.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/FETISolver/feticommunicator.h" +#include "sm/FETISolver/feticommunicator.h" #include "engngm.h" #include "intarray.h" #include "dofmanager.h" @@ -60,10 +60,11 @@ FETICommunicator :: ~FETICommunicator() void FETICommunicator :: setUpCommunicationMaps(EngngModel *pm) { - int i, j, l, maxRec; + int i, j, maxRec; int globaldofmannum, localNumber, ndofs; int numberOfBoundaryDofMans; int source, tag; + int size = this->processComms.size(); IntArray numberOfPartitionBoundaryDofMans(size); StaticCommunicationBuffer commBuff(MPI_COMM_WORLD); EModelDefaultEquationNumbering dn; @@ -72,7 +73,7 @@ FETICommunicator :: setUpCommunicationMaps(EngngModel *pm) // value is corresponding local master dof manager number map< int, int, less< int > >BoundaryDofManagerMap; // communication maps of slaves - IntArray **commMaps = new IntArray * [ size ]; + std::vector commMaps(size); // location array IntArray locNum; Domain *domain = pm->giveDomain(1); @@ -88,7 +89,7 @@ FETICommunicator :: setUpCommunicationMaps(EngngModel *pm) // // receive data // - for ( i = 1; i < size; i++ ) { + for ( int i = 1; i < size; i++ ) { commBuff.iRecv(MPI_ANY_SOURCE, FETICommunicator :: NumberOfBoundaryDofManagersMsg); while ( !commBuff.testCompletion(source, tag) ) { ; @@ -110,7 +111,7 @@ FETICommunicator :: setUpCommunicationMaps(EngngModel *pm) // determine the total number of boundary dof managers at master int nnodes = domain->giveNumberOfDofManagers(); j = 0; - for ( i = 1; i <= nnodes; i++ ) { + for ( int i = 1; i <= nnodes; i++ ) { if ( domain->giveDofManager(i)->giveParallelMode() == DofManager_shared ) { j++; } @@ -124,7 +125,7 @@ FETICommunicator :: setUpCommunicationMaps(EngngModel *pm) // resize the receive buffer to fit all messages maxRec = 0; - for ( i = 0; i < size; i++ ) { + for ( int i = 0; i < size; i++ ) { if ( numberOfPartitionBoundaryDofMans.at(i + 1) > maxRec ) { maxRec = numberOfPartitionBoundaryDofMans.at(i + 1); } @@ -132,16 +133,16 @@ FETICommunicator :: setUpCommunicationMaps(EngngModel *pm) commBuff.resize( 2 * maxRec * commBuff.givePackSizeOfInt(1) ); // resize communication maps acordingly - for ( i = 0; i < size; i++ ) { + for ( int i = 0; i < size; i++ ) { j = numberOfPartitionBoundaryDofMans.at(i + 1); - commMaps [ i ] = new IntArray(j); + commMaps [ i ].resize(j); } // add local master contribution first // loop over all dofmanager data received i = 0; - for ( j = 1; j <= numberOfPartitionBoundaryDofMans.at(1); j++ ) { + for ( int j = 1; j <= numberOfPartitionBoundaryDofMans.at(1); j++ ) { // fing next shared dofman while ( !( domain->giveDofManager(++i)->giveParallelMode() == DofManager_shared ) ) { ; @@ -150,7 +151,7 @@ FETICommunicator :: setUpCommunicationMaps(EngngModel *pm) globaldofmannum = domain->giveDofManager(i)->giveGlobalNumber(); domain->giveDofManager(i)->giveCompleteLocationArray(locNum, dn); ndofs = 0; - for ( l = 1; l <= locNum.giveSize(); l++ ) { + for ( int l = 1; l <= locNum.giveSize(); l++ ) { if ( locNum.at(l) ) { ndofs++; } @@ -171,14 +172,14 @@ FETICommunicator :: setUpCommunicationMaps(EngngModel *pm) } // remember communication map for particular partition - commMaps [ 0 ]->at(j) = localNumber; + commMaps [ 0 ].at(j) = localNumber; } // // receive data from slave partitions // - for ( i = 1; i < size; i++ ) { + for ( int i = 1; i < size; i++ ) { commBuff.iRecv(MPI_ANY_SOURCE, FETICommunicator :: BoundaryDofManagersRecMsg); while ( !commBuff.testCompletion(source, tag) ) { ; @@ -191,7 +192,7 @@ FETICommunicator :: setUpCommunicationMaps(EngngModel *pm) #endif // loop over all dofmanager data received - for ( j = 1; j <= numberOfPartitionBoundaryDofMans.at(source + 1); j++ ) { + for ( int j = 1; j <= numberOfPartitionBoundaryDofMans.at(source + 1); j++ ) { commBuff.read(globaldofmannum); commBuff.read(ndofs); @@ -210,7 +211,7 @@ FETICommunicator :: setUpCommunicationMaps(EngngModel *pm) } // remember communication map for particular partition - commMaps [ source ]->at(j) = localNumber; + commMaps [ source ].at(j) = localNumber; } commBuff.init(); @@ -222,24 +223,20 @@ FETICommunicator :: setUpCommunicationMaps(EngngModel *pm) // numberOfEquations = 0; numberOfBoundaryDofMans = boundaryDofManList.size(); - for ( i = 1; i <= numberOfBoundaryDofMans; i++ ) { + for ( int i = 1; i <= numberOfBoundaryDofMans; i++ ) { boundaryDofManList [ i - 1 ].setCodeNumbers(numberOfEquations); // updates numberOfEquations } // store the commMaps - for ( i = 0; i < size; i++ ) { + for ( int i = 0; i < size; i++ ) { if ( i != 0 ) { - this->giveProcessCommunicator(i)->setToSendArry(engngModel, * commMaps [ i ], 0); - this->giveProcessCommunicator(i)->setToRecvArry(engngModel, * commMaps [ i ], 0); + this->giveProcessCommunicator(i)->setToSendArry(engngModel, commMaps [ i ], 0); + this->giveProcessCommunicator(i)->setToRecvArry(engngModel, commMaps [ i ], 0); } else { - masterCommMap = * commMaps [ i ]; + masterCommMap = commMaps [ i ]; } - - delete commMaps [ i ]; } - delete commMaps; - MPI_Barrier(MPI_COMM_WORLD); #ifdef __VERBOSE_PARALLEL diff --git a/src/sm/FETISolver/feticommunicator.h b/src/sm/FETISolver/feticommunicator.h index cc23f4c53..f19a1d863 100644 --- a/src/sm/FETISolver/feticommunicator.h +++ b/src/sm/FETISolver/feticommunicator.h @@ -35,7 +35,7 @@ #ifndef feticommunicator_h #define feticommunicator_h -#include "../sm/FETISolver/fetiboundarydofman.h" +#include "sm/FETISolver/fetiboundarydofman.h" #include "communicator.h" #include "error.h" diff --git a/src/sm/FETISolver/fetisolver.C b/src/sm/FETISolver/fetisolver.C index 2723c41c0..7fa35d50a 100644 --- a/src/sm/FETISolver/fetisolver.C +++ b/src/sm/FETISolver/fetisolver.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/FETISolver/feticommunicator.h" +#include "sm/FETISolver/feticommunicator.h" #include "mathfem.h" #include "fetisolver.h" #include "skyline.h" @@ -46,11 +46,13 @@ namespace oofem { REGISTER_SparseLinSolver(FETISolver, ST_Feti); -FETISolver :: FETISolver(Domain *d, EngngModel *m) : SparseLinearSystemNM(d, m), pcbuff(CBT_static), processCommunicator(& pcbuff, 0) +FETISolver :: FETISolver(Domain *d, EngngModel *m) : SparseLinearSystemNM(d, m), + ni(20), + err(1.e-6), + pcbuff(CBT_static), + processCommunicator(& pcbuff, 0), + energyNorm_comput_flag(0) { - err = 1.e-6; - ni = 20; - energyNorm_comput_flag = 0; } @@ -89,11 +91,9 @@ FETISolver :: estimateMaxPackSize(IntArray &map, DataStream &buff, int &packUnpa } -IRResultType -FETISolver :: initializeFrom(InputRecord *ir) +void +FETISolver :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, ni, _IFT_FETISolver_maxiter); IR_GIVE_FIELD(ir, err, _IFT_FETISolver_maxerr); IR_GIVE_FIELD(ir, limit, _IFT_FETISolver_limit); @@ -111,8 +111,6 @@ FETISolver :: initializeFrom(InputRecord *ir) if ( err > 0.1 ) { err = 0.1; } - - return IRRT_OK; } void FETISolver :: setUpCommunicationMaps() @@ -249,25 +247,23 @@ int FETISolver :: packRBM(ProcessCommunicator &processComm) { int result = 1; - int i, ir, size; - int j, ndofs, eqNum; - IntArray const *toSendMap = processComm.giveToSendMap(); - CommunicationBuffer *send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); + const IntArray &toSendMap = processComm.giveToSendMap(); + CommunicationBuffer &send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); IntArray locationArray; EModelDefaultEquationNumbering dn; - size = toSendMap->giveSize(); - for ( i = 1; i <= size; i++ ) { - domain->giveDofManager( toSendMap->at(i) )->giveCompleteLocationArray(locationArray, dn); - ndofs = locationArray.giveSize(); - for ( j = 1; j <= ndofs; j++ ) { + for ( int inode : toSendMap ) { + domain->giveDofManager( inode )->giveCompleteLocationArray(locationArray, dn); + int ndofs = locationArray.giveSize(); + for ( int j = 1; j <= ndofs; j++ ) { + int eqNum; if ( ( eqNum = locationArray.at(j) ) ) { - for ( ir = 1; ir <= nse; ir++ ) { - result &= send_buff->write( rbm.at(eqNum, ir) ); + for ( int ir = 1; ir <= nse; ir++ ) { + result &= send_buff.write( rbm.at(eqNum, ir) ); } if ( nse == 0 ) { - result &= send_buff->write(0.0); + result &= send_buff.write(0.0); } } } @@ -280,42 +276,38 @@ FETISolver :: packRBM(ProcessCommunicator &processComm) int FETISolver :: masterUnpackRBM(ProcessCommunicator &processComm) { - int to, result = 1; - int size, receivedRank; - int nshared, part, eqNum; - IntArray const *toRecvMap = processComm.giveToRecvMap(); - CommunicationBuffer *recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); + int result = 1; + const IntArray &toRecvMap = processComm.giveToRecvMap(); + CommunicationBuffer &recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); IntArray locationArray; - double value; - receivedRank = processComm.giveRank(); - size = toRecvMap->giveSize(); + int receivedRank = processComm.giveRank(); if ( receivedRank != 0 ) { // for (irbm = 1; irbm <= nsem.at(receivedRank+1); irbm++) { - for ( int i = 1; i <= size; i++ ) { - to = toRecvMap->at(i); + for ( int to : toRecvMap ) { // // loop over all dofs for ( int idof = 1; idof <= masterCommunicator->giveDofManager(to)->giveNumberOfDofs(); idof++ ) { for ( int irbm = 1; irbm <= nsem.at(receivedRank + 1); irbm++ ) { // unpack contribution - result &= recv_buff->read(value); + double value; + result &= recv_buff.read(value); if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all // corresponding DOFs in boundary node // localize to corresponding places - nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); + int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); for ( int j = 1; j <= nshared; j++ ) { - part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); + int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); if ( part == processComm.giveRank() ) { continue; } - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); l.at(eqNum, rbmAddr.at(receivedRank + 1) + irbm - 1) = value; } } else { // no reference partition - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); l.at(eqNum, rbmAddr.at(receivedRank + 1) + irbm - 1) = ( -1.0 ) * value; } } @@ -329,9 +321,8 @@ FETISolver :: masterUnpackRBM(ProcessCommunicator &processComm) int FETISolver :: masterMapRBM() { - int to, from, receivedRank = 0, nshared, part, eqNum, result; + int receivedRank = 0, result; IntArray locationArray; - double value; int size = masterCommMap.giveSize(); // master will map its own values directly int locpos; @@ -339,10 +330,10 @@ FETISolver :: masterMapRBM() for ( int irbm = 1; irbm <= nsem.at(1); irbm++ ) { for ( int i = 1; i <= size; i++ ) { - to = masterCommunicator->giveMasterCommMapPtr()->at(i); + int to = masterCommunicator->giveMasterCommMapPtr()->at(i); // use receive map, send map is empty to prevent master to send // itself any data. Note, however, that send and receive maps are same. - from = masterCommMap.at(i); + int from = masterCommMap.at(i); domain->giveDofManager(from)->giveCompleteLocationArray(locationArray, dn); locpos = 1; @@ -363,23 +354,23 @@ FETISolver :: masterMapRBM() } } - value = rbm.at(locationArray.at(locpos), irbm); + double value = rbm.at(locationArray.at(locpos), irbm); if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all // corresponding DOFs in boundary node // localize to corresponding places - nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); + int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); for ( int j = 1; j <= nshared; j++ ) { - part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); + int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); if ( part == 0 ) { continue; } - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); l.at(eqNum, rbmAddr.at(receivedRank + 1) + irbm - 1) = value; } } else { // no reference partition - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); l.at(eqNum, rbmAddr.at(receivedRank + 1) + irbm - 1) = ( -1.0 ) * value; } } @@ -395,11 +386,11 @@ int FETISolver :: packQQProducts(ProcessCommunicator &processComm) { int result = 1; - CommunicationBuffer *send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); + CommunicationBuffer &send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); IntArray locationArray; for ( int i = 1; i <= nse; i++ ) { - result &= send_buff->write( qq.at(i) ); + result &= send_buff.write( qq.at(i) ); } return result; @@ -410,17 +401,16 @@ int FETISolver :: masterUnpackQQProduct(ProcessCommunicator &processComm) { int result = 1; - int receivedRank; - //IntArray const* toRecvMap = processComm.giveToRecvMap(); - CommunicationBuffer *recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); + //const IntArray const &toRecvMap = processComm.giveToRecvMap(); + CommunicationBuffer &recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); IntArray locationArray; //double value; - receivedRank = processComm.giveRank(); + int receivedRank = processComm.giveRank(); if ( receivedRank != 0 ) { for ( int i = 1; i <= nsem.at(receivedRank + 1); i++ ) { - result &= recv_buff->read( q.at(rbmAddr.at(receivedRank + 1) + i - 1) ); + result &= recv_buff.read( q.at(rbmAddr.at(receivedRank + 1) + i - 1) ); } } @@ -446,42 +436,37 @@ int FETISolver :: packSolution(ProcessCommunicator &processComm) { // master - int result = 1; - int size; - int ndofs, eqNum, nshared, part, from; - double val; - IntArray const *toSendMap = processComm.giveToSendMap(); - CommunicationBuffer *send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); + const IntArray &toSendMap = processComm.giveToSendMap(); + CommunicationBuffer &send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); IntArray locationArray; int rank = processComm.giveRank(); - size = toSendMap->giveSize(); - for ( int i = 1; i <= size; i++ ) { - from = toSendMap->at(i); - ndofs = masterCommunicator->giveDofManager(from)->giveNumberOfDofs(); + for ( int from : toSendMap ) { + int ndofs = masterCommunicator->giveDofManager(from)->giveNumberOfDofs(); if ( rank == masterCommunicator->giveDofManager(from)->giveReferencePratition() ) { // summ corresponding values (multipliers) - nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions(); + int nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions(); for ( int k = 1; k <= ndofs; k++ ) { - val = 0.0; + double val = 0.0; for ( int j = 1; j <= nshared; j++ ) { - part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j); + int part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j); if ( part == processComm.giveRank() ) { continue; } - eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, k); + int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, k); val += w.at(eqNum); } - result &= send_buff->write(val); + result &= send_buff.write(val); } } else { masterCommunicator->giveDofManager(from)->giveCompleteLocationArray(rank, locationArray); for ( int j = 1; j <= ndofs; j++ ) { + int eqNum; if ( ( eqNum = locationArray.at(j) ) ) { - result &= send_buff->write( ( -1.0 ) * w.at(eqNum) ); + result &= send_buff.write( ( -1.0 ) * w.at(eqNum) ); } } } @@ -495,23 +480,20 @@ int FETISolver :: unpackSolution(ProcessCommunicator &processComm) { // slaves unpack their slotion contributions - int result = 1, to; - int size; - int ndofs, eqNum; - double value; - IntArray const *toRecvMap = processComm.giveToRecvMap(); - CommunicationBuffer *recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); + int result = 1; + const IntArray &toRecvMap = processComm.giveToRecvMap(); + CommunicationBuffer &recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); IntArray locationArray; EModelDefaultEquationNumbering dn; - size = toRecvMap->giveSize(); - for ( int i = 1; i <= size; i++ ) { - to = toRecvMap->at(i); + for ( int to : toRecvMap ) { domain->giveDofManager(to)->giveCompleteLocationArray(locationArray, dn); - ndofs = locationArray.giveSize(); + int ndofs = locationArray.giveSize(); for ( int j = 1; j <= ndofs; j++ ) { + int eqNum; if ( ( eqNum = locationArray.at(j) ) ) { - result &= recv_buff->read(value); + double value; + result &= recv_buff.read(value); dd.at(eqNum) = value; #ifdef __VERBOSE_PARALLEL @@ -528,20 +510,19 @@ FETISolver :: unpackSolution(ProcessCommunicator &processComm) int FETISolver :: masterMapSolution() { - int to, from, receivedRank = 0, nshared, part, eqNum, result, locpos; + int receivedRank = 0, result; IntArray locationArray; - double value; int size = masterCommMap.giveSize(); EModelDefaultEquationNumbering dn; for ( int i = 1; i <= size; i++ ) { - from = masterCommunicator->giveMasterCommMapPtr()->at(i); + int from = masterCommunicator->giveMasterCommMapPtr()->at(i); // use receive map, send map is empty to prevent master to send // itself any data. Note, however, that send and receive maps are same. - to = masterCommMap.at(i); + int to = masterCommMap.at(i); domain->giveDofManager(to)->giveCompleteLocationArray(locationArray, dn); - locpos = 1; + int locpos = 1; // // loop over all dofs for ( int idof = 1; idof <= masterCommunicator->giveDofManager(from)->giveNumberOfDofs(); idof++, locpos++ ) { @@ -554,23 +535,23 @@ FETISolver :: masterMapSolution() } } - value = 0.0; + double value = 0.0; if ( masterCommunicator->giveDofManager(from)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all // corresponding DOFs in boundary node // localize to corresponding places - nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions(); + int nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions(); for ( int j = 1; j <= nshared; j++ ) { - part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j); + int part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j); if ( part == 0 ) { continue; } - eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, idof); + int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, idof); value += w.at(eqNum); } } else { // no reference partition - eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(receivedRank, idof); + int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(receivedRank, idof); value = ( -1.0 ) * w.at(eqNum); } @@ -591,20 +572,18 @@ FETISolver :: packResiduals(ProcessCommunicator &processComm) // slaves int result = 1; - int size; - int ndofs, eqNum; - IntArray const *toSendMap = processComm.giveToSendMap(); - CommunicationBuffer *send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); + const IntArray &toSendMap = processComm.giveToSendMap(); + CommunicationBuffer &send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); IntArray locationArray; EModelDefaultEquationNumbering dn; - size = toSendMap->giveSize(); - for ( int i = 1; i <= size; i++ ) { - domain->giveDofManager( toSendMap->at(i) )->giveCompleteLocationArray(locationArray, dn); - ndofs = locationArray.giveSize(); + for ( int inode : toSendMap ) { + domain->giveDofManager( inode )->giveCompleteLocationArray(locationArray, dn); + int ndofs = locationArray.giveSize(); for ( int j = 1; j <= ndofs; j++ ) { + int eqNum; if ( ( eqNum = locationArray.at(j) ) ) { - result &= send_buff->write( pp.at(eqNum) ); + result &= send_buff.write( pp.at(eqNum) ); } } } @@ -619,40 +598,36 @@ FETISolver :: unpackResiduals(ProcessCommunicator &processComm) // master int result = 1; - int size, receivedRank, to; - int nshared, part, eqNum; - IntArray const *toRecvMap = processComm.giveToRecvMap(); - CommunicationBuffer *recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); + const IntArray &toRecvMap = processComm.giveToRecvMap(); + CommunicationBuffer &recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); IntArray locationArray; - double value; - receivedRank = processComm.giveRank(); + int receivedRank = processComm.giveRank(); - size = toRecvMap->giveSize(); if ( receivedRank != 0 ) { - for ( int i = 1; i <= size; i++ ) { - to = toRecvMap->at(i); + for ( int to : toRecvMap ) { // // loop over all dofs for ( int idof = 1; idof <= masterCommunicator->giveDofManager(to)->giveNumberOfDofs(); idof++ ) { // unpack contribution - result &= recv_buff->read(value); + double value; + result &= recv_buff.read(value); if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all // corresponding DOFs in boundary node // localize to corresponding places - nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); + int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); for ( int j = 1; j <= nshared; j++ ) { - part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); + int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); if ( part == processComm.giveRank() ) { continue; } - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); g.at(eqNum) += value; } } else { // no reference partition - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); g.at(eqNum) += ( -1.0 ) * value; } } @@ -665,20 +640,19 @@ FETISolver :: unpackResiduals(ProcessCommunicator &processComm) int FETISolver :: masterMapResiduals() { // master will map its own values directly - int to, from, receivedRank = 0, nshared, part, eqNum, result, locpos; + int receivedRank = 0, result; IntArray locationArray; - double value; int size = masterCommMap.giveSize(); EModelDefaultEquationNumbering dn; for ( int i = 1; i <= size; i++ ) { - to = masterCommunicator->giveMasterCommMapPtr()->at(i); + int to = masterCommunicator->giveMasterCommMapPtr()->at(i); // use receive map, send map is empty to prevent master to send // itself any data. Note, however, that send and receive maps are same. - from = masterCommMap.at(i); + int from = masterCommMap.at(i); domain->giveDofManager(from)->giveCompleteLocationArray(locationArray, dn); - locpos = 1; + int locpos = 1; // // ndofs = locationArray.giveSize(); // including supported // for (j=1; j<=ndofs; j++) { @@ -696,23 +670,23 @@ FETISolver :: masterMapResiduals() } } - value = pp.at( locationArray.at(locpos) ); + double value = pp.at( locationArray.at(locpos) ); if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all // corresponding DOFs in boundary node // localize to corresponding places - nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); + int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); for ( int j = 1; j <= nshared; j++ ) { - part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); + int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); if ( part == 0 ) { continue; } - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); g.at(eqNum) += value; } } else { // no reference partition - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); g.at(eqNum) += ( -1.0 ) * value; } } @@ -729,43 +703,37 @@ int FETISolver :: packDirectionVector(ProcessCommunicator &processComm) { // master - int result = 1; - int size; - int ndofs, eqNum, nshared, part, from; - double val; - IntArray const *toSendMap = processComm.giveToSendMap(); - CommunicationBuffer *send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); + const IntArray &toSendMap = processComm.giveToSendMap(); + CommunicationBuffer &send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); IntArray locationArray; int rank = processComm.giveRank(); - size = toSendMap->giveSize(); - for ( int i = 1; i <= size; i++ ) { - from = toSendMap->at(i); - - ndofs = masterCommunicator->giveDofManager(from)->giveNumberOfDofs(); + for ( int from : toSendMap ) { + int ndofs = masterCommunicator->giveDofManager(from)->giveNumberOfDofs(); if ( rank == masterCommunicator->giveDofManager(from)->giveReferencePratition() ) { // summ corresponding values (multipliers) - nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions(); + int nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions(); for ( int k = 1; k <= ndofs; k++ ) { - val = 0.0; + double val = 0.0; for ( int j = 1; j <= nshared; j++ ) { - part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j); + int part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j); if ( part == processComm.giveRank() ) { continue; } - eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, k); + int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, k); val += d.at(eqNum); } - result &= send_buff->write(val); + result &= send_buff.write(val); } } else { masterCommunicator->giveDofManager(from)->giveCompleteLocationArray(rank, locationArray); for ( int j = 1; j <= ndofs; j++ ) { + int eqNum; if ( ( eqNum = locationArray.at(j) ) ) { - result &= send_buff->write( ( -1.0 ) * d.at(eqNum) ); + result &= send_buff.write( ( -1.0 ) * d.at(eqNum) ); } } } @@ -780,22 +748,20 @@ FETISolver :: unpackDirectionVector(ProcessCommunicator &processComm) { // slaves unpack their slotion contributions int result = 1; - int size; - int ndofs, eqNum; - IntArray const *toRecvMap = processComm.giveToRecvMap(); - CommunicationBuffer *recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); + const IntArray &toRecvMap = processComm.giveToRecvMap(); + CommunicationBuffer &recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); IntArray locationArray; // int receivedRank = domainComm.giveRank(); EModelDefaultEquationNumbering dn; - size = toRecvMap->giveSize(); // if (receivedRank != 0) { - for ( int i = 1; i <= size; i++ ) { - domain->giveDofManager( toRecvMap->at(i) )->giveCompleteLocationArray(locationArray, dn); - ndofs = locationArray.giveSize(); + for ( int inode : toRecvMap ) { + domain->giveDofManager( inode )->giveCompleteLocationArray(locationArray, dn); + int ndofs = locationArray.giveSize(); for ( int j = 1; j <= ndofs; j++ ) { + int eqNum; if ( ( eqNum = locationArray.at(j) ) ) { - result &= recv_buff->read( dd.at(eqNum) ); + result &= recv_buff.read( dd.at(eqNum) ); } } } @@ -807,20 +773,19 @@ FETISolver :: unpackDirectionVector(ProcessCommunicator &processComm) int FETISolver :: masterMapDirectionVector() { - int to, from, receivedRank = 0, nshared, part, eqNum, result, locpos; + int receivedRank = 0, result; IntArray locationArray; - double value; int size = masterCommMap.giveSize(); EModelDefaultEquationNumbering dn; for ( int i = 1; i <= size; i++ ) { - from = masterCommunicator->giveMasterCommMapPtr()->at(i); + int from = masterCommunicator->giveMasterCommMapPtr()->at(i); // use receive map, send map is empty to prevent master to send // itself any data. Note, however, that send and receive maps are same. - to = masterCommMap.at(i); + int to = masterCommMap.at(i); domain->giveDofManager(to)->giveCompleteLocationArray(locationArray, dn); - locpos = 1; + int locpos = 1; // // loop over all dofs for ( int idof = 1; idof <= masterCommunicator->giveDofManager(from)->giveNumberOfDofs(); idof++, locpos++ ) { @@ -833,23 +798,23 @@ FETISolver :: masterMapDirectionVector() } } - value = 0.0; + double value = 0.0; if ( masterCommunicator->giveDofManager(from)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all // corresponding DOFs in boundary node // localize to corresponding places - nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions(); + int nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions(); for ( int j = 1; j <= nshared; j++ ) { - part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j); + int part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j); if ( part == 0 ) { continue; } - eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, idof); + int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, idof); value += d.at(eqNum); } } else { // no reference partition - eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(receivedRank, idof); + int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(receivedRank, idof); value = ( -1.0 ) * d.at(eqNum); } @@ -869,20 +834,18 @@ FETISolver :: packPPVector(ProcessCommunicator &processComm) // slaves int result = 1; - int size; - int ndofs, eqNum; - IntArray const *toSendMap = processComm.giveToSendMap(); - CommunicationBuffer *send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); + const IntArray &toSendMap = processComm.giveToSendMap(); + CommunicationBuffer &send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); IntArray locationArray; EModelDefaultEquationNumbering dn; - size = toSendMap->giveSize(); - for ( int i = 1; i <= size; i++ ) { - domain->giveDofManager( toSendMap->at(i) )->giveCompleteLocationArray(locationArray, dn); - ndofs = locationArray.giveSize(); + for ( int inode : toSendMap ) { + domain->giveDofManager( inode )->giveCompleteLocationArray(locationArray, dn); + int ndofs = locationArray.giveSize(); for ( int j = 1; j <= ndofs; j++ ) { + int eqNum; if ( ( eqNum = locationArray.at(j) ) ) { - result &= send_buff->write( pp.at(eqNum) ); + result &= send_buff.write( pp.at(eqNum) ); } } } @@ -897,40 +860,36 @@ FETISolver :: unpackPPVector(ProcessCommunicator &processComm) // master int result = 1; - int size, receivedRank, to; - int nshared, part, eqNum; - IntArray const *toRecvMap = processComm.giveToRecvMap(); - CommunicationBuffer *recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); + const IntArray &toRecvMap = processComm.giveToRecvMap(); + CommunicationBuffer &recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); IntArray locationArray; - double value; - receivedRank = processComm.giveRank(); + int receivedRank = processComm.giveRank(); - size = toRecvMap->giveSize(); if ( receivedRank != 0 ) { - for ( int i = 1; i <= size; i++ ) { - to = toRecvMap->at(i); + for ( int to : toRecvMap ) { // // loop over all dofs for ( int idof = 1; idof <= masterCommunicator->giveDofManager(to)->giveNumberOfDofs(); idof++ ) { // unpack contribution - result &= recv_buff->read(value); + double value; + result &= recv_buff.read(value); if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all // corresponding DOFs in boundary node // localize to corresponding places - nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); + int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); for ( int j = 1; j <= nshared; j++ ) { - part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); + int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); if ( part == processComm.giveRank() ) { continue; } - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); p.at(eqNum) += value; } } else { // no reference partition - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); p.at(eqNum) += ( -1.0 ) * value; } } @@ -943,20 +902,19 @@ FETISolver :: unpackPPVector(ProcessCommunicator &processComm) int FETISolver :: masterMapPPVector() { // master will map its own values directly - int to, from, receivedRank = 0, nshared, part, eqNum, result, locpos; + int receivedRank = 0, result; IntArray locationArray; - double value; int size = masterCommMap.giveSize(); EModelDefaultEquationNumbering dn; for ( int i = 1; i <= size; i++ ) { - to = masterCommunicator->giveMasterCommMapPtr()->at(i); + int to = masterCommunicator->giveMasterCommMapPtr()->at(i); // use receive map, send map is empty to prevent master to send // itself any data. Note, however, that send and receive maps are same. - from = masterCommMap.at(i); + int from = masterCommMap.at(i); domain->giveDofManager(from)->giveCompleteLocationArray(locationArray, dn); - locpos = 1; + int locpos = 1; // // ndofs = locationArray.giveSize(); // including supported // for (j=1; j<=ndofs; j++) { @@ -974,23 +932,23 @@ FETISolver :: masterMapPPVector() } } - value = pp.at( locationArray.at(locpos) ); + double value = pp.at( locationArray.at(locpos) ); if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all // corresponding DOFs in boundary node // localize to corresponding places - nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); + int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions(); for ( int j = 1; j <= nshared; j++ ) { - part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); + int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j); if ( part == 0 ) { continue; } - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof); p.at(eqNum) += value; } } else { // no reference partition - eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); + int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof); p.at(eqNum) += ( -1.0 ) * value; } } @@ -1008,10 +966,10 @@ FETISolver :: packGammas(ProcessCommunicator &processComm) int result = 1; int rank = processComm.giveRank(); - CommunicationBuffer *send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); + CommunicationBuffer &send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); for ( int irbm = 1; irbm <= nsem.at(rank + 1); irbm++ ) { - result &= send_buff->write( gamma.at(rbmAddr.at(rank + 1) + irbm - 1) ); + result &= send_buff.write( gamma.at(rbmAddr.at(rank + 1) + irbm - 1) ); } return result; @@ -1023,11 +981,11 @@ FETISolver :: unpackGammas(ProcessCommunicator &processComm) { // slaves int result = 1; - CommunicationBuffer *recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); + CommunicationBuffer &recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); localGammas.resize(nse); for ( int irbm = 1; irbm <= nse; irbm++ ) { - result &= recv_buff->read( localGammas.at(irbm) ); + result &= recv_buff.read( localGammas.at(irbm) ); } return result; diff --git a/src/sm/FETISolver/fetisolver.h b/src/sm/FETISolver/fetisolver.h index 8d61e9e62..5083f2a41 100644 --- a/src/sm/FETISolver/fetisolver.h +++ b/src/sm/FETISolver/fetisolver.h @@ -35,7 +35,7 @@ #ifndef fetisolver_h #define fetisolver_h -#include "../sm/FETISolver/feticommunicator.h" +#include "sm/FETISolver/feticommunicator.h" #include "sparselinsystemnm.h" #include "sparsemtrx.h" #include "floatarray.h" @@ -44,10 +44,11 @@ ///@name Input fields for FETISolver //@{ - #define _IFT_FETISolver_maxiter "maxiter" - #define _IFT_FETISolver_maxerr "maxerr" - #define _IFT_FETISolver_limit "limit" - #define _IFT_FETISolver_energynormflag "energynormflag" +#define _IFT_FETISolver_Name "feti" +#define _IFT_FETISolver_maxiter "maxiter" +#define _IFT_FETISolver_maxerr "maxerr" +#define _IFT_FETISolver_limit "limit" +#define _IFT_FETISolver_energynormflag "energynormflag" //@} namespace oofem { @@ -110,17 +111,17 @@ class FETISolver : public SparseLinearSystemNM * @param x Solution array * @return NM_Status value */ - virtual NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x); + NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x) override; int estimateMaxPackSize(IntArray &, DataStream &, int &); /// Sets up the communication maps void setUpCommunicationMaps(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; // identification - virtual const char *giveClassName() const { return "FETISolver"; } - virtual LinSystSolverType giveLinSystSolverType() const { return ST_Feti; } + const char *giveClassName() const override { return "FETISolver"; } + LinSystSolverType giveLinSystSolverType() const override { return ST_Feti; } void projection(FloatArray &v, FloatMatrix &l, FloatMatrix &l1); diff --git a/src/sm/InterfaceElements/intelline1PF.C b/src/sm/InterfaceElements/intelline1PF.C index 4adb9827c..ab84f7815 100644 --- a/src/sm/InterfaceElements/intelline1PF.C +++ b/src/sm/InterfaceElements/intelline1PF.C @@ -32,11 +32,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "InterfaceElements/intelline1PF.h" -#include "Elements/Interfaces/intelline1.h" +#include "sm/InterfaceElements/intelline1PF.h" +#include "sm/Elements/Interfaces/intelline1.h" #include "node.h" -#include "CrossSections/structuralinterfacecrosssection.h" -#include "Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "sm/CrossSections/structuralinterfacecrosssection.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" #include "gausspoint.h" #include "gaussintegrationrule.h" #include "floatmatrix.h" @@ -92,20 +92,20 @@ IntElLine1PF :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - //integrationRulesArray[ 0 ].reset( new LobattoIntegrationRule (1,domain, 1, 2) ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + //integrationRulesArray[ 0 ] = std::make_unique(1,domain, 1, 2); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); integrationRulesArray [ 0 ]->SetUpPointsOnLine(this->numberOfGaussPoints, _2dInterface); } } -void -IntElLine1PF :: computeCovarBaseVectorAt(IntegrationPoint *ip, FloatArray &G) + +FloatArrayF<2> +IntElLine1PF :: computeCovarBaseVectorAt(IntegrationPoint *ip) const { - FloatMatrix dNdxi; FEInterpolation *interp = this->giveInterpolation(); + FloatMatrix dNdxi; interp->evaldNdxi( dNdxi, ip->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - G.resize(2); - G.zero(); + FloatArrayF<2> G; int numNodes = this->giveNumberOfNodes(); for ( int i = 1; i <= dNdxi.giveNumberOfRows(); i++ ) { double X1_i = 0.5 * ( this->giveNode(i)->giveCoordinate(1) + this->giveNode(i + numNodes / 2)->giveCoordinate(1) ); // (mean) point on the fictious mid surface @@ -113,35 +113,28 @@ IntElLine1PF :: computeCovarBaseVectorAt(IntegrationPoint *ip, FloatArray &G) G.at(1) += dNdxi.at(i, 1) * X1_i; G.at(2) += dNdxi.at(i, 1) * X2_i; } + return G; } + double IntElLine1PF :: computeAreaAround(IntegrationPoint *ip) { - FloatArray G; - this->computeCovarBaseVectorAt(ip, G); - - double weight = ip->giveWeight(); - double ds = sqrt( G.dotProduct(G) ) * weight; - - double thickness = this->giveCrossSection()->give(CS_Thickness, ip); - return ds * thickness; + auto G = this->computeCovarBaseVectorAt(ip); + auto ds = norm(G) * ip->giveWeight(); + return ds * this->giveCrossSection()->give(CS_Thickness, ip); } -IRResultType -IntElLine1PF :: initializeFrom(InputRecord *ir) +void +IntElLine1PF :: initializeFrom(InputRecord &ir) { - //const char *__proc = "initializeFrom"; // Required by IR_GIVE_FIELD macro - IRResultType result; // Required by IR_GIVE_FIELD macro - if ( ir->hasField(_IFT_IntElLine1PF_prescribedDamage) ) - { + StructuralInterfaceElement :: initializeFrom(ir); + + if ( ir.hasField(_IFT_IntElLine1PF_prescribedDamage) ) { IR_GIVE_FIELD(ir, this->prescribed_damage, _IFT_IntElLine1PF_prescribedDamage); //this->alpha.setValues(2, damage, damage); } - return StructuralInterfaceElement :: initializeFrom(ir); - - } @@ -151,6 +144,7 @@ IntElLine1PF :: giveDofManDofIDMask(int inode, IntArray &answer) const answer = {D_u, D_v, T_f}; } + void IntElLine1PF :: computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) { @@ -167,6 +161,7 @@ IntElLine1PF :: computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answe } + FEInterpolation * IntElLine1PF :: giveInterpolation() const { @@ -174,8 +169,6 @@ IntElLine1PF :: giveInterpolation() const } - - void IntElLine1PF :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { @@ -199,14 +192,13 @@ IntElLine1PF :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMod FloatMatrix temp; solveForLocalDamage(temp, tStep); - FloatMatrix answer1, answer2, answer3, answer4; this->computeStiffnessMatrix_uu(answer1, rMode, tStep); //this->computeStiffnessMatrix_ud(answer2, rMode, tStep); //this->computeStiffnessMatrix_du(answer3, rMode, tStep); //symmetric answer3.beTranspositionOf( answer2 ); this->computeStiffnessMatrix_dd(answer4, rMode, tStep); - + answer.assemble( answer1, loc_u, loc_u ); //answer.assemble( answer2, loc_u, loc_d ); //answer.assemble( answer3, loc_d, loc_u ); @@ -229,8 +221,6 @@ IntElLine1PF :: computeStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode r //IntegrationPoint *ip = iRule->getIntegrationPoint(j); for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { - - if ( this->nlGeometry == 0 ) { this->giveStiffnessMatrix_Eng(D, rMode, ip, tStep); } else if ( this->nlGeometry == 1 ) { @@ -239,7 +229,6 @@ IntElLine1PF :: computeStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode r OOFEM_ERROR("nlgeometry must be 0 or 1!") } - this->computeNmatrixAt(ip, N); this->computeNd_vectorAt(ip->giveNaturalCoordinates(), Nd); @@ -249,7 +238,7 @@ IntElLine1PF :: computeStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode r this->computeTransformationMatrixAt(ip, rotationMatGtoL); GD.rotatedWith(rotationMatGtoL, 't'); // transform stiffness to global coord system - + DN.beProductOf(GD, N); double dA = this->computeAreaAround(ip); @@ -260,7 +249,6 @@ IntElLine1PF :: computeStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode r } } - if ( matStiffSymmFlag ) { answer.symmetrized(); } @@ -275,7 +263,6 @@ IntElLine1PF :: computeStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode r FloatMatrix N, rotationMatGtoL; FloatArray a_u, traction, tractionTemp, jump, fu, fd(2), fd4(4); - fd.zero(); FloatArray a_d_temp, a_d, Bd, Nd; a_u = this->unknownVectorU; @@ -294,9 +281,9 @@ IntElLine1PF :: computeStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode r this->computeTraction(traction, ip, jump, tStep); // compute internal cohesive forces as f = N^T*traction dA - double Gprim = computeGPrim(ip, VM_Total, tStep); + double Gprim = computeGPrim(ip, VM_Total, tStep); double dA = this->computeAreaAround(ip); - + fu.plusProduct(N, traction, dA*Gprim); temp.beDyadicProductOf(fu,Nd); Kud.add(temp); @@ -345,18 +332,18 @@ IntElLine1PF :: computeStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode r this->unknownVectorU = a_u_ref; this->unknownVectorD = a_d_ref; this->deltaUnknownVectorD = delta_a_d_ref; - } + void IntElLine1PF :: computeStiffnessMatrix_dd(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) -{ +{ // Computation of tangent: K_dd = \int Nd^t * ( -kp*neg_Mac'(alpha_dot)/delta_t + g_c/l + G''*Psibar) * Nd + // \int Bd^t * ( g_c * l * [G^1 G^2]^t * [G^1 G^2] ) * Bd // = K_dd1 + K_dd2 int ndofs = 8 + 4; - int ndofs_u = 8; - int ndofs_d = 4; + int ndofs_u = 8; + int ndofs_d = 4; double l = this->giveInternalLength(); double g_c = this->giveCriticalEnergy(); @@ -366,7 +353,6 @@ IntElLine1PF :: computeStiffnessMatrix_dd(FloatMatrix &answer, MatResponseMode r answer.resize( ndofs_d, ndofs_d ); answer.zero(); - //IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ]; FloatMatrix tempN(2,2), tempB(2,2), temp(2,2); FloatArray Nd, Bd; @@ -375,15 +361,14 @@ IntElLine1PF :: computeStiffnessMatrix_dd(FloatMatrix &answer, MatResponseMode r temp.zero(); //for ( int j = 0; j < iRule->giveNumberOfIntegrationPoints(); j++ ) { // IntegrationPoint *ip = iRule->getIntegrationPoint(j); - for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { + for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { computeBd_vectorAt(ip, Bd); computeNd_vectorAt(ip->giveNaturalCoordinates(), Nd); - double dA = this->computeAreaAround(ip); + double dA = this->computeAreaAround(ip); //double Gbis = this->computeGbis() double Gbis = 2.0; - double Psibar = this->computeFreeEnergy( ip, tStep ); - + double Psibar = this->computeFreeEnergy( ip, tStep ); // K_dd1 = ( -kp*neg_Mac'(d_dot) / Delta_t + g_c/ l + G'' * Psibar ) * N^t*N; double Delta_d = computeDamageAt(ip, VM_Incremental, tStep); @@ -392,7 +377,6 @@ IntElLine1PF :: computeStiffnessMatrix_dd(FloatMatrix &answer, MatResponseMode r //double Psibar0 = this->givePsiBar0(); //double factorN = g_c / l + Gbis * this->MaCauley(Psibar-Psibar0); - tempN.beDyadicProductOf(Nd, Nd); temp.add(factorN * dA, tempN); @@ -403,11 +387,9 @@ IntElLine1PF :: computeStiffnessMatrix_dd(FloatMatrix &answer, MatResponseMode r temp.add(factorB * dA, tempB); } - IntArray indx1, indx2; - indx1 = {1, 2}; - indx2 = {3, 4}; - - answer.assemble(temp, indx1, indx1); + IntArray indx1 = {1, 2}, indx2 = {3, 4}; + + answer.assemble(temp, indx1, indx1); answer.assemble(temp, indx2, indx2); #if 0 @@ -443,13 +425,12 @@ IntElLine1PF :: computeStiffnessMatrix_dd(FloatMatrix &answer, MatResponseMode r } - void IntElLine1PF :: solveForLocalDamage(FloatMatrix &answer, TimeStep *tStep) { // approach with dame defined over the element only - if (tStep->giveNumber() == 1 ){ + if ( tStep->giveNumber() == 1 ) { return; } if ( this->prescribed_damage >-1.0e-8 ){ @@ -462,12 +443,11 @@ IntElLine1PF :: solveForLocalDamage(FloatMatrix &answer, TimeStep *tStep) FloatMatrix Kdd(2,2), tempN, tempB; FloatArray delta_a_d; - double kp = this->givePenaltyParameter(); double Delta_t = tStep->giveTimeIncrement(); double l = this->giveInternalLength(); double g_c = this->giveCriticalEnergy(); - + fd.zero(); Kdd.zero(); //a_d.zero(); @@ -494,8 +474,7 @@ IntElLine1PF :: solveForLocalDamage(FloatMatrix &answer, TimeStep *tStep) //double Gprim = computeGPrim(ip, VM_Total, tStep); double Gprim = -2.0 * (1.0 - d); double Psibar = this->computeFreeEnergy( ip, tStep ); - - + double sectionalForcesScal = -kp * neg_MaCauley(Delta_d/Delta_t) + g_c / l * d + Gprim * Psibar; double sectionalForcesVec = g_c * l * gradd; fd = fd + ( Nd*sectionalForcesScal + Bd*sectionalForcesVec ) * dA; @@ -504,7 +483,7 @@ IntElLine1PF :: solveForLocalDamage(FloatMatrix &answer, TimeStep *tStep) // Tangent //double Gbis = this->computeGbis() double Gbis = 2.0; - + // K_dd1 = ( -kp*neg_Mac'(d_dot) / Delta_t + g_c/ l + G'' * Psibar ) * N^t*N; double factorN = -kp * neg_MaCauleyPrime(Delta_d/Delta_t)/Delta_t + g_c / l + Gbis * Psibar; //double factorN = g_c / l + Gbis * Psibar; @@ -520,8 +499,8 @@ IntElLine1PF :: solveForLocalDamage(FloatMatrix &answer, TimeStep *tStep) } //printf("norm %e \n", fd.computeNorm() ); //if( fd.computeNorm() < 1.0e-5 ) { - if( fd.computeNorm()/fd_ref.computeNorm() < 1.0e-3 ) { - this->alpha = a_d; + if ( fd.computeNorm()/fd_ref.computeNorm() < 1.0e-3 ) { + this->alpha = a_d; return; } Kdd.solveForRhs(fd, delta_a_d); @@ -538,35 +517,29 @@ IntElLine1PF :: solveForLocalDamage(FloatMatrix &answer, TimeStep *tStep) void IntElLine1PF :: computeGMatrix(FloatMatrix &answer, const double damage, GaussPoint *gp, ValueModeType valueMode, TimeStep *tStep) { + double d = damage; + if ( this->prescribed_damage > -1.0e-8 ) { + d = prescribed_damage; + } - double d = damage; - - if ( this->prescribed_damage > -1.0e-8 ) { - d = prescribed_damage; - } + StructuralInterfaceMaterialStatus *matStat = static_cast< StructuralInterfaceMaterialStatus * >( gp->giveMaterialStatus() ); + const auto &strain = matStat->giveTempJump(); + double g2 = -1.0; + if ( strain.at(3) < 0.0 ) { // Damage does not affect compressive stresses + g2 = 1.0; + //printf("compression \n"); + } else { + g2 = (1.0 - d) * (1.0 - d); + //printf("g %e \n", g2); + //g2 = 1; + } + double g1 = (1.0 - d) * (1.0 - d); - StructuralInterfaceMaterialStatus *matStat = static_cast< StructuralInterfaceMaterialStatus * >( gp->giveMaterialStatus() ); - FloatArray strain; - - strain = matStat->giveTempJump(); - double g2 = -1.0; - if ( strain.at(3) < 0.0 ) { // Damage does not affect compressive stresses - g2 = 1.0; - //printf("compression \n"); - } else { - g2 = (1.0 - d) * (1.0 - d); - //printf("g %e \n", g2); - //g2 = 1; - } - - double g1 = (1.0 - d) * (1.0 - d); - - answer.resize(2,2); - answer.zero(); - answer.at(1,1) = g1; - answer.at(2,2) = g2; - + answer.resize(2,2); + answer.zero(); + answer.at(1,1) = g1; + answer.at(2,2) = g2; } @@ -594,7 +567,6 @@ IntElLine1PF :: computeDamageAt(GaussPoint *gp, ValueModeType valueMode, TimeSte } - void IntElLine1PF :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord) { @@ -602,13 +574,11 @@ IntElLine1PF :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, in this->computeDisplacementUnknowns( this->unknownVectorU, VM_Total, tStep ); this->computeDamageUnknowns( this->unknownVectorD, VM_Total, tStep ); this->computeDamageUnknowns( this->deltaUnknownVectorD, VM_Incremental, tStep ); - - FloatArray fu, fd; this->giveInternalForcesVectorUD(fu, fd, tStep, useUpdatedGpRecord); - // total vec + // total vec IntArray IdMask_u, IdMask_d; this->giveDofManDofIDMask_u( IdMask_u ); this->giveDofManDofIDMask_d( IdMask_d ); @@ -620,8 +590,9 @@ IntElLine1PF :: giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, in answer.zero(); answer.assemble(fu, loc_u); //answer.assemble(fd, loc_d); - } + + void IntElLine1PF :: giveInternalForcesVectorUD(FloatArray &fu, FloatArray &fd4, TimeStep *tStep, int useUpdatedGpRecord) { @@ -642,7 +613,7 @@ IntElLine1PF :: giveInternalForcesVectorUD(FloatArray &fu, FloatArray &fd4, Time fu.zero(); fd.zero(); - + for ( auto &ip: *this->giveDefaultIntegrationRulePtr() ) { //for ( int i = 0; i < iRule->giveNumberOfIntegrationPoints(); i++ ) { // IntegrationPoint *ip = iRule->getIntegrationPoint(i); @@ -650,11 +621,10 @@ IntElLine1PF :: giveInternalForcesVectorUD(FloatArray &fu, FloatArray &fd4, Time this->computeBd_vectorAt(ip, Bd); this->computeNd_vectorAt(ip->giveNaturalCoordinates(), Nd); - // compute internal cohesive forces as f = N^T * g * traction dA jump.beProductOf(Nu, a_u); this->computeTraction(traction, ip, jump, tStep); - + //FloatMatrix temp; //solveForLocalDamage(temp, tStep); //double g = this->computeG(ip, VM_Total, tStep); @@ -668,7 +638,7 @@ IntElLine1PF :: giveInternalForcesVectorUD(FloatArray &fu, FloatArray &fd4, Time GTraction.beProductOf(Gmat,traction); //double g = this->computeOldG(ip, VM_Total, tStep); double dA = this->computeAreaAround(ip); - + //fu.plusProduct(Nu, traction, dA*g); fu.plusProduct(Nu, GTraction, dA); @@ -685,15 +655,13 @@ IntElLine1PF :: giveInternalForcesVectorUD(FloatArray &fu, FloatArray &fd4, Time double Psibar = this->computeFreeEnergy( ip, tStep ); double gradd = Bd.dotProduct(a_d); // Dalpha/Ds - - + //double Psibar0 = this->givePsiBar0(); //double sectionalForcesScal = g_c / l * d + Gprim * this->MaCauley(Psibar-Psibar0); double sectionalForcesScal = -kp * neg_MaCauley(Delta_d/Delta_t) + g_c / l * d + Gprim * Psibar; //double sectionalForcesScal = g_c / l * d + Gprim * Psibar; double sectionalForcesVec = g_c * l * gradd; fd = fd + ( Nd*sectionalForcesScal + Bd*sectionalForcesVec ) * dA; - } fd4.resize(4); fd4.zero(); @@ -702,21 +670,18 @@ IntElLine1PF :: giveInternalForcesVectorUD(FloatArray &fu, FloatArray &fd4, Time indx2 = {3, 4}; fd4.assemble(fd, indx1); fd4.assemble(fd, indx2); - } - double IntElLine1PF :: computeFreeEnergy(GaussPoint *gp, TimeStep *tStep) { - StructuralInterfaceMaterialStatus *matStat = static_cast< StructuralInterfaceMaterialStatus * >( gp->giveMaterialStatus() ); FloatArray strain, stress; stress = matStat->giveTempFirstPKTraction(); - strain = matStat->giveTempJump(); - //stress = matStat->giveFirstPKTraction(); - //strain = matStat->giveJump(); + strain = matStat->giveTempJump(); + //stress = matStat->giveFirstPKTraction(); + //strain = matStat->giveJump(); //stress.printYourself(); //strain.printYourself(); diff --git a/src/sm/InterfaceElements/intelline1PF.h b/src/sm/InterfaceElements/intelline1PF.h index 8456e887b..a343f5e90 100644 --- a/src/sm/InterfaceElements/intelline1PF.h +++ b/src/sm/InterfaceElements/intelline1PF.h @@ -35,8 +35,9 @@ #ifndef intelline1pf_h #define intelline1pf_h -#include "Elements/Interfaces/structuralinterfaceelement.h" -#include "Elements/phasefieldelement.h" +#include "sm/Elements/Interfaces/structuralinterfaceelement.h" +#include "sm/Elements/phasefieldelement.h" + #define _IFT_IntElLine1PF_Name "IntElLine1PF" #define _IFT_IntElLine1PF_prescribedDamage "prescribeddamage" @@ -56,78 +57,76 @@ class IntElLine1PF : public StructuralInterfaceElement, PhaseFieldElement public: IntElLine1PF(int n, Domain *d); - virtual ~IntElLine1PF() { } - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual int computeNumberOfDofs() { return 12; } - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + int computeNumberOfDofs() override { return 12; } + void giveDofManDofIDMask(int inode, IntArray &answer) const override; - virtual double computeAreaAround(GaussPoint *gp); - virtual void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeCovarBaseVectorAt(GaussPoint *gp, FloatArray &G); + double computeAreaAround(GaussPoint *gp) override; + void computeTransformationMatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + FloatArrayF<2> computeCovarBaseVectorAt(GaussPoint *gp) const; - virtual int testElementExtension(ElementExtension ext) { return 0; } + int testElementExtension(ElementExtension ext) override { return 0; } //virtual Interface *giveInterface(InterfaceType) { return NULL; } // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_IntElLine1PF_Name; } - virtual const char *giveClassName() const { return "IntElLine1PF"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_IntElLine1PF_Name; } + const char *giveClassName() const override { return "IntElLine1PF"; } + void initializeFrom(InputRecord &ir) override; - virtual void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) + void giveEngTraction(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) override { - this->giveInterfaceCrossSection()->giveEngTraction_2d(answer, gp, jump, tStep); + answer = this->giveInterfaceCrossSection()->giveEngTraction_2d(jump, gp, tStep); } - virtual void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) + void giveStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, IntegrationPoint *ip, TimeStep *tStep) override { - this->giveInterfaceCrossSection()->give2dStiffnessMatrix_Eng(answer, rMode, ip, tStep); + answer = this->giveInterfaceCrossSection()->give2dStiffnessMatrix_Eng(rMode, ip, tStep); } - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; // PF - int giveNumberOfDofManagers() const { return 4; } - StructuralInterfaceElement *giveElement() { return this; } - virtual void giveDofManDofIDMask_u(IntArray &answer); - virtual void giveDofManDofIDMask_d(IntArray &answer); + int giveNumberOfDofManagers() const override { return 4; } + StructuralInterfaceElement *giveElement() override { return this; } + void giveDofManDofIDMask_u(IntArray &answer) override; + void giveDofManDofIDMask_d(IntArray &answer) override; virtual void computeStiffnessMatrix_uu(FloatMatrix &, MatResponseMode, TimeStep *); virtual void computeStiffnessMatrix_ud(FloatMatrix &, MatResponseMode, TimeStep *); virtual void computeStiffnessMatrix_dd(FloatMatrix &, MatResponseMode, TimeStep *); //virtual void computeStiffnessMatrix_du(FloatMatrix &, MatResponseMode, TimeStep *); - virtual void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0); + void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord = 0) override; virtual void giveInternalForcesVectorUD(FloatArray &fu, FloatArray &fd, TimeStep *tStep, int useUpdatedGpRecord = 0); virtual double computeDamageAt(GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); virtual void computeLocationArrayOfDofIDs( const IntArray &dofIdArray, IntArray &answer ); virtual void computeBd_vectorAt(GaussPoint *gp, FloatArray &B); virtual void computeNd_vectorAt(const FloatArray &lCoords, FloatArray &N); virtual double computeFreeEnergy(GaussPoint *gp, TimeStep *tStep); - + double computeOldG(GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); - double neg_MaCauley(double par) + double neg_MaCauley(double par) const { - return 0.5 * ( abs(par) - par ); + return 0.5 * ( std::abs(par) - par ); } - double neg_MaCauleyPrime(double par) + double neg_MaCauleyPrime(double par) const { - return 0.5 * ( abs(par)/(par + 1.0e-12) - 1.0 ); // 0.5*(sign - 1) taken from Ragnars code + return 0.5 * ( std::abs(par)/(par + 1.0e-12) - 1.0 ); // 0.5*(sign - 1) taken from Ragnars code } - double MaCauley(double par) + double MaCauley(double par) const { - return 0.5 * ( abs(par) + par ); + return 0.5 * ( std::abs(par) + par ); } - double MaCauleyPrime(double par) + double MaCauleyPrime(double par) const { - return 0.5 * ( abs(par)/(par + 1.0e-12) + 1.0 ); // 0.5*(sign + 1) taken from Ragnars code + return 0.5 * ( std::abs(par)/(par + 1.0e-12) + 1.0 ); // 0.5*(sign + 1) taken from Ragnars code } @@ -135,7 +134,6 @@ class IntElLine1PF : public StructuralInterfaceElement, PhaseFieldElement void computeGMatrix(FloatMatrix &answer, const double damage, GaussPoint *gp, ValueModeType valueMode, TimeStep *stepN); protected: - FloatArray unknownVectorU; FloatArray unknownVectorD; FloatArray deltaUnknownVectorD; @@ -143,13 +141,13 @@ class IntElLine1PF : public StructuralInterfaceElement, PhaseFieldElement FloatArray deltaAlpha; FloatArray alpha; FloatArray oldAlpha; - double prescribed_damage; + double prescribed_damage = 0.; - virtual void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer); - virtual void computeGaussPoints(); + void computeNmatrixAt(GaussPoint *gp, FloatMatrix &answer) override; + void computeGaussPoints() override; virtual int giveApproxOrder() { return 1; } - Element_Geometry_Type giveGeometryType() const { return EGT_quad_1_interface; }; + Element_Geometry_Type giveGeometryType() const override { return EGT_quad_1_interface; }; }; } // end namespace oofem #endif diff --git a/src/sm/Loads/constantpressureload.C b/src/sm/Loads/constantpressureload.C index e5f35ca3a..d7636ba4d 100644 --- a/src/sm/Loads/constantpressureload.C +++ b/src/sm/Loads/constantpressureload.C @@ -47,18 +47,17 @@ ConstantPressureLoad :: ConstantPressureLoad(int i, Domain *d) : SurfaceLoad(i, this->loadOffset = 0.0; } -IRResultType -ConstantPressureLoad :: initializeFrom(InputRecord *ir) +void +ConstantPressureLoad :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + BoundaryLoad :: initializeFrom(ir); + IR_GIVE_OPTIONAL_FIELD(ir, this->loadOffset, _IFT_ConstantPressureLoad_LoadOffset); #if 1 - if ( ir->hasField(_IFT_GeneralBoundaryCondition_dofs) ) { - OOFEM_WARNING("Constant pressure load should not specify DOFs"); - return IRRT_BAD_FORMAT; + if ( ir.hasField(_IFT_GeneralBoundaryCondition_dofs) ) { + throw ValueInputException(ir, _IFT_GeneralBoundaryCondition_dofs, "Constant pressure load should not specify DOFs"); } #endif - return BoundaryLoad :: initializeFrom(ir); } diff --git a/src/sm/Loads/constantpressureload.h b/src/sm/Loads/constantpressureload.h index 19798cb9f..d9bf4b1b5 100644 --- a/src/sm/Loads/constantpressureload.h +++ b/src/sm/Loads/constantpressureload.h @@ -66,13 +66,12 @@ namespace oofem { class ConstantPressureLoad : public SurfaceLoad { public: - //ConstantPressureLoad(int i, Domain *d) : BoundaryLoad(i, d) ConstantPressureLoad(int i, Domain * d); // Overloaded methods: - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); - virtual void computeValues(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, const IntArray &dofids, ValueModeType mode); - virtual int giveApproxOrder() { return 0; } + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; + void computeValues(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, const IntArray &dofids, ValueModeType mode) override; + int giveApproxOrder() override { return 0; } /** * Sets a new load vector. @@ -80,15 +79,15 @@ class ConstantPressureLoad : public SurfaceLoad */ void updateLoad(const FloatArray &newValue) { componentArray = newValue; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual bcGeomType giveBCGeoType() const { return SurfaceLoadBGT; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + bcGeomType giveBCGeoType() const override { return SurfaceLoadBGT; } - virtual const char *giveClassName() const { return "ConstantPressureLoad"; } - virtual const char *giveInputRecordName() const { return _IFT_ConstantPressureLoad_Name; } + const char *giveClassName() const override { return "ConstantPressureLoad"; } + const char *giveInputRecordName() const override { return _IFT_ConstantPressureLoad_Name; } double giveLoadOffset() { return this->loadOffset; } private: - virtual void computeNArray(FloatArray &answer, const FloatArray &coords) const { answer.clear(); } + void computeNArray(FloatArray &answer, const FloatArray &coords) const override { answer.clear(); } double loadOffset; // xi-coord offset of load. xi=-1 -> bottom, xi=0 -> midsurface (default), xi=1 -> top surface }; } // end namespace oofem diff --git a/src/sm/Loads/foreigntempfieldload.C b/src/sm/Loads/foreigntempfieldload.C index 7d2e0a433..359b11aac 100644 --- a/src/sm/Loads/foreigntempfieldload.C +++ b/src/sm/Loads/foreigntempfieldload.C @@ -56,9 +56,8 @@ ForeignTemperatureFieldLoad :: computeValueAt(FloatArray &answer, TimeStep *tSte } } -IRResultType -ForeignTemperatureFieldLoad :: initializeFrom(InputRecord *ir) +void +ForeignTemperatureFieldLoad :: initializeFrom(InputRecord &ir) { - return IRRT_OK; } } // end namespace oofem diff --git a/src/sm/Loads/foreigntempfieldload.h b/src/sm/Loads/foreigntempfieldload.h index 5be9e7f14..65d7cb95e 100644 --- a/src/sm/Loads/foreigntempfieldload.h +++ b/src/sm/Loads/foreigntempfieldload.h @@ -59,7 +59,6 @@ class Field; */ class ForeignTemperatureFieldLoad : public StructuralTemperatureLoad { -private: public: // make public so that it can be simply set from python std::shared_ptr foreignField; @@ -80,12 +79,12 @@ class ForeignTemperatureFieldLoad : public StructuralTemperatureLoad * @param coords Global coordinates, which are used to evaluate components values. * @param mode Determines response mode. */ - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; - virtual const char *giveInputRecordName() const { return _IFT_ForeignTemperatureFieldLoad_Name; } - virtual const char *giveClassName() const { return "ForeignTemperatureFieldLoad"; } + const char *giveInputRecordName() const override { return _IFT_ForeignTemperatureFieldLoad_Name; } + const char *giveClassName() const override { return "ForeignTemperatureFieldLoad"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; }; } // end namespace oofem #endif // foreigntempfield_h diff --git a/src/sm/Loads/rotatingboundary.C b/src/sm/Loads/rotatingboundary.C index a67cb775b..b82a8ccf2 100644 --- a/src/sm/Loads/rotatingboundary.C +++ b/src/sm/Loads/rotatingboundary.C @@ -46,7 +46,7 @@ REGISTER_BoundaryCondition(RotatingBoundary); double RotatingBoundary :: give(Dof *dof, ValueModeType mode, double time) { DofIDItem id = dof->giveDofID(); - FloatArray *coords = dof->giveDofManager()->giveCoordinates(); + const auto &coords = dof->giveDofManager()->giveCoordinates(); FloatArray answer, newcoords; double theta = 0.; @@ -65,11 +65,11 @@ double RotatingBoundary :: give(Dof *dof, ValueModeType mode, double time) } if ( center.giveSize() == 0 ) { - center.resize( coords->giveSize() ); + center.resize( coords.giveSize() ); center.zero(); } - if ( coords == NULL || coords->giveSize() != center.giveSize() ) { + if ( coords.giveSize() != center.giveSize() ) { OOFEM_ERROR("Size of coordinate system different from center of rotation."); } @@ -77,17 +77,17 @@ double RotatingBoundary :: give(Dof *dof, ValueModeType mode, double time) double &ny = axis.at(2); double &nz = axis.at(3); - if ( coords->giveSize() == 1 ) { + if ( coords.giveSize() == 1 ) { R.resize(1, 1); R.at(1, 1) = cos(theta) + nx * nx * ( 1 - cos(theta) ); } - if ( coords->giveSize() == 2 ) { + if ( coords.giveSize() == 2 ) { R.resize(2, 2); R.at(1, 1) = cos(theta) + nx * nx * ( 1 - cos(theta) ); R.at(1, 2) = nx * ny * ( 1 - cos(theta) ) - nz *sin(theta); R.at(2, 1) = ny * nx * ( 1 - cos(theta) ) + nz *sin(theta); R.at(2, 2) = cos(theta) + ny * ny * ( 1 - cos(theta) ); - } else if ( coords->giveSize() == 3 ) { + } else if ( coords.giveSize() == 3 ) { R.resize(3, 3); R.at(1, 1) = cos(theta) + nx * nx * ( 1 - cos(theta) ); @@ -105,10 +105,10 @@ double RotatingBoundary :: give(Dof *dof, ValueModeType mode, double time) OOFEM_ERROR("Size of coordinate system has to be 1, 2 or 3."); } - newcoords.beDifferenceOf(center, *coords); + newcoords.beDifferenceOf(center, coords); answer.beProductOf(R, newcoords); answer.add(center); - answer.subtract(* coords); + answer.subtract(coords); switch ( id ) { case D_u: @@ -125,17 +125,15 @@ double RotatingBoundary :: give(Dof *dof, ValueModeType mode, double time) } } -IRResultType -RotatingBoundary :: initializeFrom(InputRecord *ir) +void +RotatingBoundary :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + GeneralBoundaryCondition :: initializeFrom(ir); IR_GIVE_FIELD(ir, axis, _IFT_RotatingBoundary_axis); axis.normalize(); IR_GIVE_OPTIONAL_FIELD(ir, center, _IFT_RotatingBoundary_center); - - return GeneralBoundaryCondition :: initializeFrom(ir); } void diff --git a/src/sm/Loads/rotatingboundary.h b/src/sm/Loads/rotatingboundary.h index 182a061dd..97326539e 100644 --- a/src/sm/Loads/rotatingboundary.h +++ b/src/sm/Loads/rotatingboundary.h @@ -73,15 +73,15 @@ class RotatingBoundary : public BoundaryCondition /// Destructor. virtual ~RotatingBoundary() { } - virtual double give(Dof *dof, ValueModeType mode, double time); + double give(Dof *dof, ValueModeType mode, double time) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void scale(double s) { } + void scale(double s) override { } - virtual const char *giveInputRecordName() const { return _IFT_RotatingBoundary_Name; } - virtual const char *giveClassName() const { return "RotatingBoundary"; } + const char *giveInputRecordName() const override { return _IFT_RotatingBoundary_Name; } + const char *giveClassName() const override { return "RotatingBoundary"; } }; } // end namespace oofem #endif // rotatingboundary_h diff --git a/src/sm/Loads/structeigenstrainload.h b/src/sm/Loads/structeigenstrainload.h index 694a3f3b6..2150d1bd9 100644 --- a/src/sm/Loads/structeigenstrainload.h +++ b/src/sm/Loads/structeigenstrainload.h @@ -62,12 +62,12 @@ class StructuralEigenstrainLoad : public Load * @param coords Integration point global coordinates, which are used to evaluate components values. * @param mode Determines response mode. */ - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; - virtual const char *giveInputRecordName() const { return _IFT_StructuralEigenstrainLoad_Name; } - virtual const char *giveClassName() const { return "StructuralEigenstrainLoad"; } - virtual bcValType giveBCValType() const { return EigenstrainBVT; } - virtual bcGeomType giveBCGeoType() const { return BodyLoadBGT; } + const char *giveInputRecordName() const override { return _IFT_StructuralEigenstrainLoad_Name; } + const char *giveClassName() const override { return "StructuralEigenstrainLoad"; } + bcValType giveBCValType() const override { return EigenstrainBVT; } + bcGeomType giveBCGeoType() const override { return BodyLoadBGT; } }; } // end namespace oofem #endif // structeigenstrainload_h diff --git a/src/sm/Loads/structtemperatureload.h b/src/sm/Loads/structtemperatureload.h index c6d081a73..e3d7cb9f5 100644 --- a/src/sm/Loads/structtemperatureload.h +++ b/src/sm/Loads/structtemperatureload.h @@ -55,12 +55,12 @@ class StructuralTemperatureLoad : public Load public: StructuralTemperatureLoad(int n, Domain * d) : Load(n, d) { } - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; - virtual bcValType giveBCValType() const { return TemperatureBVT; } - virtual bcGeomType giveBCGeoType() const { return BodyLoadBGT; } - virtual const char *giveInputRecordName() const { return _IFT_StructuralTemperatureLoad_Name; } - virtual const char *giveClassName() const { return "StructuralTemperatureLoad"; } + bcValType giveBCValType() const override { return TemperatureBVT; } + bcGeomType giveBCGeoType() const override { return BodyLoadBGT; } + const char *giveInputRecordName() const override { return _IFT_StructuralTemperatureLoad_Name; } + const char *giveClassName() const override { return "StructuralTemperatureLoad"; } }; } // end namespace oofem #endif // structtemperatureload_h diff --git a/src/sm/Loads/tf1.C b/src/sm/Loads/tf1.C index 69ee3fcac..44b6bfeef 100644 --- a/src/sm/Loads/tf1.C +++ b/src/sm/Loads/tf1.C @@ -68,9 +68,8 @@ TF1 :: computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coo answer.at(1) = result; } -IRResultType -TF1 :: initializeFrom(InputRecord *ir) +void +TF1 :: initializeFrom(InputRecord &ir) { - return IRRT_OK; } } // end namespace oofem diff --git a/src/sm/Loads/tf1.h b/src/sm/Loads/tf1.h index 9342f9703..e87d4d3ef 100644 --- a/src/sm/Loads/tf1.h +++ b/src/sm/Loads/tf1.h @@ -60,12 +60,12 @@ class TF1 : public StructuralTemperatureLoad /// Destructor virtual ~TF1() { } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; - virtual const char *giveInputRecordName() const { return _IFT_TF1_Name; } - virtual const char *giveClassName() const { return "TF1"; } + const char *giveInputRecordName() const override { return _IFT_TF1_Name; } + const char *giveClassName() const override { return "TF1"; } }; } // end namespace oofem #endif // tf1_h diff --git a/src/sm/Loads/usrdeftempfield.C b/src/sm/Loads/usrdeftempfield.C index f71c86ffc..09ca05b21 100644 --- a/src/sm/Loads/usrdeftempfield.C +++ b/src/sm/Loads/usrdeftempfield.C @@ -77,11 +77,9 @@ UserDefinedTemperatureField :: computeValueAt(FloatArray &answer, TimeStep *tSte } } -IRResultType -UserDefinedTemperatureField :: initializeFrom(InputRecord *ir) +void +UserDefinedTemperatureField :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, size, _IFT_UserDefinedTemperatureField_size); if ( size > 3 ) { size = 3; @@ -98,7 +96,5 @@ UserDefinedTemperatureField :: initializeFrom(InputRecord *ir) if ( size > 2 ) { IR_GIVE_FIELD(ir, ftExpression [ 2 ], _IFT_UserDefinedTemperatureField_t3); } - - return IRRT_OK; } } // end namespace oofem diff --git a/src/sm/Loads/usrdeftempfield.h b/src/sm/Loads/usrdeftempfield.h index 43a18fcd3..cfdda68dc 100644 --- a/src/sm/Loads/usrdeftempfield.h +++ b/src/sm/Loads/usrdeftempfield.h @@ -84,12 +84,12 @@ class UserDefinedTemperatureField : public StructuralTemperatureLoad * @param coords Global coordinates, which are used to evaluate components values. * @param mode Determines response mode. */ - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; - virtual const char *giveInputRecordName() const { return _IFT_UserDefinedTemperatureField_Name; } - virtual const char *giveClassName() const { return "UserDefinedTemperatureField"; } + const char *giveInputRecordName() const override { return _IFT_UserDefinedTemperatureField_Name; } + const char *giveClassName() const override { return "UserDefinedTemperatureField"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; }; } // end namespace oofem #endif // usrdeftempfield_h diff --git a/src/sm/Materials/1D/isoasymm1d.C b/src/sm/Materials/1D/isoasymm1d.C new file mode 100644 index 000000000..6d21cf8d4 --- /dev/null +++ b/src/sm/Materials/1D/isoasymm1d.C @@ -0,0 +1,209 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "isoasymm1d.h" +#include "sm/Materials/structuralms.h" +#include "floatmatrix.h" +#include "gausspoint.h" +#include "classfactory.h" +#include "dynamicinputrecord.h" +#include "contextioerr.h" + +namespace oofem { +REGISTER_Material(IsotropicAsymmetric1DMaterial); + +IsotropicAsymmetric1DMaterial :: IsotropicAsymmetric1DMaterial(int n, Domain *d) : + StructuralMaterial(n, d) +{ } + +IsotropicAsymmetric1DMaterial :: IsotropicAsymmetric1DMaterial(int n, Domain *d, + double _Ec, double _Et, + double _efc, double _eft) : + StructuralMaterial(n, d), + Et(_Et), + Ec(_Ec), + efc(_efc), + eft(_eft), + a(0.), + m(15.) +{} + + +void +IsotropicAsymmetric1DMaterial :: initializeFrom(InputRecord &ir) +{ + StructuralMaterial :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, Ec, _IFT_IsotropicAsymmetric1DMaterial_ec); + IR_GIVE_FIELD(ir, Et, _IFT_IsotropicAsymmetric1DMaterial_et); + IR_GIVE_OPTIONAL_FIELD(ir, efc, _IFT_IsotropicAsymmetric1DMaterial_efc); + IR_GIVE_OPTIONAL_FIELD(ir, eft, _IFT_IsotropicAsymmetric1DMaterial_eft); + IR_GIVE_FIELD(ir, a, _IFT_IsotropicAsymmetric1DMaterial_talpha); + IR_GIVE_OPTIONAL_FIELD(ir, m, _IFT_IsotropicAsymmetric1DMaterial_m); + +} + + +void +IsotropicAsymmetric1DMaterial :: giveInputRecord(DynamicInputRecord &input) +{ + StructuralMaterial :: giveInputRecord(input); + + input.setField(this->Ec, _IFT_IsotropicAsymmetric1DMaterial_ec); + input.setField(this->Et, _IFT_IsotropicAsymmetric1DMaterial_et); + input.setField(this->efc, _IFT_IsotropicAsymmetric1DMaterial_efc); + input.setField(this->eft, _IFT_IsotropicAsymmetric1DMaterial_eft); + input.setField(this->a, _IFT_IsotropicAsymmetric1DMaterial_talpha); + input.setField(this->m, _IFT_IsotropicAsymmetric1DMaterial_m); + +} + + +void IsotropicAsymmetric1DMaterial :: saveContext(DataStream &stream, ContextMode mode) +{ + StructuralMaterial :: saveContext(stream, mode); + + if ( ( mode & CM_Definition ) ) { + if ( !stream.write(Ec) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(Et) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(efc) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(eft) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(a) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(m) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +void IsotropicAsymmetric1DMaterial :: restoreContext(DataStream &stream, ContextMode mode) +{ + StructuralMaterial :: restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( !stream.read(Ec) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(Et) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(efc) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(eft) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(a) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(m) ) { + THROW_CIOERR(CIO_IOERR); + } + + } +} + + + +double +IsotropicAsymmetric1DMaterial :: give(int aProperty, GaussPoint *gp) const +{ + return this->StructuralMaterial :: give(aProperty, gp); +} + + +bool +IsotropicAsymmetric1DMaterial:: hasMaterialModeCapability(MaterialMode mode) const +{ + if (mode == _1dMat) + return true; + else + return false; +} + + +FloatMatrixF<1,1> +IsotropicAsymmetric1DMaterial :: give1dStressStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const +{ + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + + double E; + double eps = status->giveTempStrainVector().at(1); + if ((eps >0.0) && (this->eft>0.) && (eps>this->eft)) { // check for tension failure + E = 1.e-6* this->Et; + } else if ((eps<0.0) && (this->efc<0) && (eps efc)) { // check for compression failure + E = 1.e-6* this->Ec; + } else { + // elastic + E = this->Ec+0.5*(1+tanh(this->m*eps))*(this->Et-this->Ec); + } + + return {E}; +} + +FloatArrayF< 1 > +IsotropicAsymmetric1DMaterial::giveRealStressVector_1d(const FloatArrayF< 1 > &reducedE, GaussPoint *gp, TimeStep *tStep) const +{ + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + + double s; + double eps = reducedE.at(1); + + if ((eps >0.0) && (this->eft>0.) && (eps>this->eft)) { // check for tension failure + s = 0.0; + } else if ((eps<0.0) && (this->efc<0) && (eps efc)) { // check for compression failure + s = 0.0; + } else { + s=(0.5*this->Et-0.5*this->Ec)*((log(cosh(this->m*eps)))/(this->m))+eps*(0.5*this->Ec+0.5*this->Et); + } + + status->letTempStressVectorBe({s}); + status->letTempStrainVectorBe(reducedE); + + return {s}; +} + +} // end namespace oofem diff --git a/src/sm/Materials/1D/isoasymm1d.h b/src/sm/Materials/1D/isoasymm1d.h new file mode 100644 index 000000000..3731bf0c2 --- /dev/null +++ b/src/sm/Materials/1D/isoasymm1d.h @@ -0,0 +1,132 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef isoasymm1d_h +#define isoasymm1d_h + +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "floatarray.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" + + +///@name Input fields +//@{ +#define _IFT_IsotropicAsymmetric1DMaterial_Name "isoasymm1d" +#define _IFT_IsotropicAsymmetric1DMaterial_ec "ec" +#define _IFT_IsotropicAsymmetric1DMaterial_et "et" +#define _IFT_IsotropicAsymmetric1DMaterial_efc "efc" +#define _IFT_IsotropicAsymmetric1DMaterial_eft "eft" +#define _IFT_IsotropicAsymmetric1DMaterial_talpha "talpha" +#define _IFT_IsotropicAsymmetric1DMaterial_m "m" + +//@} + +namespace oofem { +class GaussPoint; + +/** + * This class implements an isotropic asymmetric (different stiffness in tension and compression) linear elastic material in a finite element problem. + * + * Tasks: + * - Returning standard material stiffness matrix for 3d-case. + * according to current state determined by using data stored + * in Gausspoint. + * - methods give2dPlaneStressMtrx, givePlaneStrainMtrx, give1dStressMtrx are + * introduced since form of this matrices is well known, and for + * faster response mainly in linear elastic problems. + * - Returning a material property (method 'give'). Only for non-standard elements. + * - Returning real stress state vector(tensor) at gauss point for 3d - case. + */ +class IsotropicAsymmetric1DMaterial : public StructuralMaterial +{ +protected: + /// Young's modulus in tension. + double Et = 0; + /// Young's modulus in compression + double Ec = 0; + // failure strain in compression + double efc = 1.0; // positive value means efc not set, no failure in compression + // failure strain in tension + double eft = -1.0; // negative values means eft not set, no failure in tension + /// Alpha + double a = 0; + /// Regularization parameter + double m = 15; + +public: + /** + * Creates a new IsotropicAsymmetric1DMaterial class instance + * with given number belonging to domain d. + * @param n material model number in domain + * @param d domain which receiver belongs to + */ + IsotropicAsymmetric1DMaterial(int n, Domain *d); + /** + * Creates a new IsotropicAsymmetric1DMaterial class instance + * with given number belonging to domain d. + * @param n Material model number in domain. + * @param d Domain which receiver belongs to. + * @param E Young modulus. + * @param nu Poisson ratio. + */ + IsotropicAsymmetric1DMaterial(int n, Domain *d, double Et, double Ec, double efc, double eft); + + const char *giveClassName() const override { return "IsotropicAsymmetric1DMaterial"; } + const char *giveInputRecordName() const override { return _IFT_IsotropicAsymmetric1DMaterial_Name; } + bool hasMaterialModeCapability(MaterialMode mode) const override; + + /** + * Initializes receiver according to object description stored in input record. + * The E modulus (keyword "E"), Poisson ratio ("nu") and coefficient of thermal dilatation + * alpha ("talpha") are read. The parent class instanciateFrom method is called. + */ + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + + double give(int aProperty, GaussPoint *gp) const override; + + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode, GaussPoint * gp, + TimeStep * tStep) const override; + virtual FloatArrayF< 1 >giveRealStressVector_1d(const FloatArrayF< 1 > &reducedE, GaussPoint *gp, TimeStep *tStep) const override; + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new StructuralMaterialStatus(gp); } + +}; +} // end namespace oofem +#endif // isoasymm1d_h diff --git a/src/sm/Materials/BoneMaterials/trabbone3d.C b/src/sm/Materials/BoneMaterials/trabbone3d.C index 7000fec89..0b6260597 100644 --- a/src/sm/Materials/BoneMaterials/trabbone3d.C +++ b/src/sm/Materials/BoneMaterials/trabbone3d.C @@ -51,134 +51,106 @@ TrabBone3D :: TrabBone3D(int n, Domain *d) : StructuralMaterial(n, d) { } -void TrabBone3D :: computePlasStrainEnerDensity(GaussPoint *gp, const FloatArray &totalStrain, const FloatArray &totalStress) +void TrabBone3D :: computePlasStrainEnerDensity(GaussPoint *gp, const FloatArrayF<6> &strain, const FloatArrayF<6> &stress) const { - TrabBone3DStatus *status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); - double tsed, tempPSED, tempTSED, tempESED; - FloatArray oldTotalDef, tempPlasDef, oldStress; + auto tsed = status->giveTSED(); + auto &oldTotalDef = status->giveStrainVector(); + auto &tempPlasDef = status->giveTempPlasDef(); + auto &oldStress = status->giveTempStressVector(); - oldTotalDef = status->giveStrainVector(); + auto elStrain = strain - tempPlasDef; + auto deltaStrain = strain - oldTotalDef; - tsed = status->giveTSED(); - tempPlasDef = status->giveTempPlasDef(); - oldStress = status->giveTempStressVector(); + auto tmpStress = stress + oldStress; - FloatArray elStrain, deltaStrain, tmpStress; - - elStrain.beDifferenceOf(totalStrain, tempPlasDef); - deltaStrain.beDifferenceOf(totalStrain, oldTotalDef); - - tmpStress = totalStress; - tmpStress.add(oldStress); - - tempESED = 0.5 * elStrain.dotProduct(totalStress); - tempTSED = tsed + 0.5 * deltaStrain.dotProduct(tmpStress); - tempPSED = tempTSED - tempESED; + double tempESED = 0.5 * dot(elStrain, stress); + double tempTSED = tsed + 0.5 * dot(deltaStrain, tmpStress); + double tempPSED = tempTSED - tempESED; status->setTempTSED(tempTSED); status->setTempPSED(tempPSED); } -void -TrabBone3D :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF<6,6> +TrabBone3D :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - double tempDam, beta, tempKappa, kappa; - FloatArray tempEffectiveStress, tempTensor2, prodTensor, plasFlowDirec; - FloatMatrix elasticity, compliance, SSaTensor, secondTerm, thirdTerm, tangentMatrix; - TrabBone3DStatus *status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); if ( mode == ElasticStiffness ) { - this->constructAnisoComplTensor(compliance); - elasticity.beInverseOf(compliance); - answer = elasticity; + auto compliance = this->constructAnisoComplTensor(); + auto elasticity = inv(compliance); + return elasticity; } else if ( mode == SecantStiffness ) { if ( printflag ) { printf("secant\n"); } - this->constructAnisoStiffnessTensor(elasticity); + auto compliance = this->constructAnisoComplTensor(); + auto elasticity = inv(compliance); + auto tempDam = status->giveTempDam(); + return elasticity * (1.0 - tempDam); + } else /*if ( mode == TangentStiffness )*/ { + double kappa = status->giveKappa(); + double tempKappa = status->giveTempKappa(); + double tempDam = status->giveTempDam(); - this->constructAnisoComplTensor(compliance); - elasticity.beInverseOf(compliance); - - tempDam = status->giveTempDam(); - answer = elasticity; - answer.times(1.0 - tempDam); - } else if ( mode == TangentStiffness ) { - kappa = status->giveKappa(); - tempKappa = status->giveTempKappa(); - tempDam = status->giveTempDam(); + FloatMatrixF<6,6> answer; if ( tempKappa > kappa ) { // plastic loading // Imports - tempEffectiveStress = status->giveTempEffectiveStress(); - plasFlowDirec = status->givePlasFlowDirec(); - SSaTensor = status->giveSSaTensor(); - beta = status->giveBeta(); + auto &tempEffectiveStress = status->giveTempEffectiveStress(); + auto &plasFlowDirec = status->givePlasFlowDirec(); + auto &SSaTensor = status->giveSSaTensor(); + auto beta = status->giveBeta(); // Construction of the dyadic product tensor - prodTensor.beTProductOf(SSaTensor, plasFlowDirec); + auto prodTensor = Tdot(SSaTensor, plasFlowDirec); // Construction of the tangent stiffness third term - thirdTerm.beDyadicProductOf(tempEffectiveStress, prodTensor); - thirdTerm.times( -expDam * critDam * exp(-expDam * tempKappa) ); - thirdTerm.times(1. / beta); + auto thirdTerm = dyad(tempEffectiveStress, prodTensor) * ((-expDam * critDam * exp(-expDam * tempKappa)) / beta); // Construction of the tangent stiffness second term - tempTensor2.beProductOf(SSaTensor, plasFlowDirec); - secondTerm.beDyadicProductOf(tempTensor2, prodTensor); - secondTerm.times(-( 1.0 - tempDam ) / beta); + auto tempTensor2 = dot(SSaTensor, plasFlowDirec); + auto secondTerm = dyad(tempTensor2, prodTensor) * (( 1.0 - tempDam ) / beta); // Construction of the tangent stiffness - tangentMatrix = SSaTensor; - tangentMatrix.times(1.0 - tempDam); - tangentMatrix.add(secondTerm); - tangentMatrix.add(thirdTerm); + auto tangentMatrix = SSaTensor * (1.0 - tempDam) + secondTerm + thirdTerm; answer = tangentMatrix; } else { // elastic behavior with damage // Construction of the secant stiffness - this->constructAnisoComplTensor(compliance); - elasticity.beInverseOf(compliance); - answer = elasticity; - answer.times(1.0 - tempDam); + auto compliance = this->constructAnisoComplTensor(); + auto elasticity = inv(compliance); + answer = elasticity * (1.0 - tempDam); } double g = status->giveDensG(); if ( g <= 0. ) { double factor = gammaL0 * pow(rho, rL) + gammaP0 *pow(rho, rP) * ( tDens - 1 ) * pow(g, tDens - 2); // printf("densification"); - tangentMatrix.resize(6, 6); - tangentMatrix.zero(); - tangentMatrix.at(1, 1) = tangentMatrix.at(1, 2) = tangentMatrix.at(1, 3) = 1; - tangentMatrix.at(2, 1) = tangentMatrix.at(2, 2) = tangentMatrix.at(2, 3) = 1; - tangentMatrix.at(3, 1) = tangentMatrix.at(3, 2) = tangentMatrix.at(3, 3) = 1; - tangentMatrix.times(factor); - answer.add(tangentMatrix); + answer += I6_I6 * factor; } + return answer; } - - status->setSmtrx(answer); } double -TrabBone3D :: evaluateCurrentYieldStress(const double kappa) +TrabBone3D :: evaluateCurrentYieldStress(double kappa) const { return ( 1. + plasHardFactor * ( 1.0 - exp(-kappa * expPlasHard) ) ); } double -TrabBone3D :: evaluateCurrentPlasticModulus(const double kappa) +TrabBone3D :: evaluateCurrentPlasticModulus(double kappa) const { return ( plasHardFactor * expPlasHard * exp(-kappa * expPlasHard) ); } double -TrabBone3D :: evaluateCurrentViscousStress(const double deltaKappa, TimeStep *tStep) +TrabBone3D :: evaluateCurrentViscousStress(const double deltaKappa, TimeStep *tStep) const { - double deltaT = tStep->giveTimeIncrement(); + double deltaT = tStep->giveTimeIncrement(); double answer; if ( deltaT == 0 ) { answer = 0; @@ -190,7 +162,7 @@ TrabBone3D :: evaluateCurrentViscousStress(const double deltaKappa, TimeStep *tS } double -TrabBone3D :: evaluateCurrentViscousModulus(const double deltaKappa, TimeStep *tStep) +TrabBone3D :: evaluateCurrentViscousModulus(double deltaKappa, TimeStep *tStep) const { double deltaT = tStep->giveTimeIncrement(); double answer = -viscosity / deltaT; @@ -200,35 +172,30 @@ TrabBone3D :: evaluateCurrentViscousModulus(const double deltaKappa, TimeStep *t void -TrabBone3D :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep) +TrabBone3D :: performPlasticityReturn(GaussPoint *gp, const FloatArrayF<6> &strain, TimeStep *tStep) const { - bool convergence; - double tempKappa; - FloatArray tempPlasDef, tempEffectiveStress, trialEffectiveStress; - FloatMatrix elasticity, compliance; - - TrabBone3DStatus *status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); // elastic compliance - this->constructAnisoComplTensor(compliance); + auto compliance = this->constructAnisoComplTensor(); // elastic stiffness - elasticity.beInverseOf(compliance); + auto elasticity = inv(compliance); // this->constructAnisoStiffnessTensor(elasticity); // initialize the plastic strain and cumulative plastic strain // by values after the previous step - tempPlasDef = status->givePlasDef(); - tempKappa = status->giveKappa(); + auto tempPlasDef = status->givePlasDef(); + double tempKappa = status->giveKappa(); // evaluate the trial stress - trialEffectiveStress.beProductOf(elasticity, totalStrain - tempPlasDef); - tempEffectiveStress = trialEffectiveStress; + auto trialEffectiveStress = dot(elasticity, strain - tempPlasDef); + auto tempEffectiveStress = trialEffectiveStress; // apply the iterative procedure that solves the system of nonlinear equations // consisting of the yield condition and discretized flow rule // and evaluates: // tempKappa ... cumulative plastic strain at the end of the substep // tempEffectiveStress ... effective stress at the end of the substep // tempPlasDef ... plastic strain at the end of the substep - convergence = projectOnYieldSurface(tempKappa, tempEffectiveStress, tempPlasDef, trialEffectiveStress, elasticity, compliance, status, tStep, gp, 0); + bool convergence = projectOnYieldSurface(tempKappa, tempEffectiveStress, tempPlasDef, trialEffectiveStress, elasticity, compliance, status, tStep, gp, 0); if ( convergence ) { status->setTempPlasDef(tempPlasDef); status->setTempKappa(tempKappa); @@ -251,149 +218,129 @@ TrabBone3D :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStr bool -TrabBone3D :: projectOnYieldSurface(double &tempKappa, FloatArray &tempEffectiveStress, FloatArray &tempPlasDef, const FloatArray &trialEffectiveStress, const FloatMatrix &elasticity, const FloatMatrix &compliance, TrabBone3DStatus *status, TimeStep *tStep, GaussPoint *gp, int lineSearchFlag) +TrabBone3D :: projectOnYieldSurface(double &tempKappa, FloatArrayF<6> &tempEffectiveStress, FloatArrayF<6> &tempPlasDef, const FloatArrayF<6> &trialEffectiveStress, const FloatMatrixF<6,6> &elasticity, const FloatMatrixF<6,6> &compliance, TrabBone3DStatus *status, TimeStep *tStep, GaussPoint *gp, int lineSearchFlag) const { bool convergence; - int flagLoop; - double deltaKappa, incKappa, beta, tempScalar, norm, FS, SFS; - double plasCriterion, plasModulus, viscoModulus, toSolveScalar, errorF, errorR; - FloatArray incTempEffectiveStress, errLoop; - FloatArray toSolveTensor, plasFlowDirec, tempTensor2, tensorFF_S, F; - FloatMatrix fabric, SSaTensor, tempTensor4, normAdjust, derivPlasFlowDirec; - this->constructAnisoFabricTensor(fabric); - this->constructAnisoFtensor(F); + auto fabric = this->constructAnisoFabricTensor(); + auto F = this->constructAnisoFtensor(); - tempTensor2.beProductOf(fabric, trialEffectiveStress); - FS = F.dotProduct(trialEffectiveStress); - SFS = sqrt( trialEffectiveStress.dotProduct(tempTensor2) ); - plasCriterion = SFS + FS - this->evaluateCurrentYieldStress(tempKappa); + auto tempTensor2 = dot(fabric, trialEffectiveStress); + auto FS = dot(F, trialEffectiveStress); + auto SFS = sqrt( dot(trialEffectiveStress, tempTensor2) ); + auto plasCriterion = SFS + FS - this->evaluateCurrentYieldStress(tempKappa); + int current_max_num_iter = this->max_num_iter; if ( plasCriterion < rel_yield_tol ) { // trial stress in elastic domain convergence = true; } else { // return to the yield surface needed // Initial valuesr - toSolveTensor.resize(6); - toSolveTensor.zero(); - toSolveScalar = plasCriterion; - errorF = plasCriterion; - errorR = 0; - SSaTensor = elasticity; - this->constructPlasFlowDirec(plasFlowDirec, norm, fabric, F, tempEffectiveStress); - tensorFF_S.beProductOf(fabric, tempEffectiveStress); - deltaKappa = 0.; + FloatArrayF<6> toSolveTensor; + double toSolveScalar = plasCriterion; + double errorF = plasCriterion; + double errorR = 0; + double deltaKappa = 0.; + auto SSaTensor = elasticity; + //auto [plastFloxDirec, norm] = this->constructPlasFlowDirec(fabric, F, tempEffectiveStress); + auto tmp = this->constructPlasFlowDirec(fabric, F, tempEffectiveStress); + auto plasFlowDirec = tmp.first; + double norm = tmp.second; + //auto tensorFF_S = dot(fabric, tempEffectiveStress); // FIXME: unusued in old code /***********************************************************************************************/ double radialReturnFlag = lineSearchFlag; if ( radialReturnFlag == 2 ) { //printf("Radial return"); - double denom, dSYdA, dAlfa; double k = tempKappa; double f = plasCriterion; + double SFSr = sqrt( dot(trialEffectiveStress, tempTensor2) ); + double FSr = dot(F, trialEffectiveStress); + auto normAdjust = this->constructNormAdjustTensor(); + auto tempTensor2 = dot(compliance, trialEffectiveStress); + auto helpArray = dot(normAdjust, tempTensor2); + norm = sqrt( dot(tempTensor2, helpArray) ); double alfa = 1; - FloatArray helpArray, stress; - stress.resize(6); - stress.zero(); - double SFSr = sqrt( trialEffectiveStress.dotProduct(tempTensor2) ); - double FSr = F.dotProduct(trialEffectiveStress); - tempTensor2.beProductOf(compliance, trialEffectiveStress); - this->constructNormAdjustTensor(normAdjust); - helpArray.beProductOf(normAdjust, tempTensor2); - norm = sqrt( tempTensor2.dotProduct(helpArray) ); + FloatArrayF<6> stress; while ( fabs(f) > 1.e-12 ) { - dSYdA = norm * this->evaluateCurrentPlasticModulus(k); + double dSYdA = norm * this->evaluateCurrentPlasticModulus(k); dSYdA *= -norm; - denom = SFSr + FSr - dSYdA; - dAlfa = -f / denom; + double denom = SFSr + FSr - dSYdA; + double dAlfa = -f / denom; alfa += dAlfa; - stress = trialEffectiveStress; - stress.times(alfa); - k = k + ( 1 - alfa ) * norm; - f = evaluatePlasCriterion(fabric, F, stress, k, ( 1 - alfa ) * norm, tStep); + stress = trialEffectiveStress * alfa; + k += ( 1 - alfa ) * norm; + f = evaluatePlasCriterion(fabric, F, stress, k, ( 1 - alfa ) * norm, tStep); } - tempEffectiveStress = stress; + tempEffectiveStress = stress; deltaKappa = k; toSolveScalar = 0; - this->constructPlasFlowDirec(plasFlowDirec, norm, fabric, F, tempEffectiveStress); + tmp = this->constructPlasFlowDirec(fabric, F, tempEffectiveStress); + plasFlowDirec = tmp.first; + norm = tmp.second; if ( tempEffectiveStress.giveSize() != trialEffectiveStress.giveSize() ) { printf( "tempS %d \n", tempEffectiveStress.giveSize() ); printf( "trial S %d \n", trialEffectiveStress.giveSize() ); } - tempTensor2.beProductOf( compliance, ( tempEffectiveStress - trialEffectiveStress ) ); - toSolveTensor = tempTensor2 + deltaKappa * plasFlowDirec; + toSolveTensor = dot( compliance, ( tempEffectiveStress - trialEffectiveStress ) ) + deltaKappa * plasFlowDirec; // Construction of the derivative of the plastic flow - this->constructDerivativeOfPlasFlowDirec(derivPlasFlowDirec, fabric, F, tempEffectiveStress); + auto derivPlasFlowDirec = this->constructDerivativeOfPlasFlowDirec(fabric, F, tempEffectiveStress); // Construction of the gradient Nabla_S of R and SSa tensor - tempTensor4 = derivPlasFlowDirec; - tempTensor4.times(deltaKappa); - tempTensor4.add(compliance); - SSaTensor.beInverseOf(tempTensor4); + SSaTensor = inv(derivPlasFlowDirec * deltaKappa + compliance); } /***********************************************************************************************/ // iteration loop - solution of a set of nonlinear equations - flagLoop = 1; + int flagLoop = 1; do { - plasModulus = evaluateCurrentPlasticModulus(tempKappa + deltaKappa); - viscoModulus = evaluateCurrentViscousModulus(deltaKappa, tStep); + double plasModulus = evaluateCurrentPlasticModulus(tempKappa + deltaKappa); + double viscoModulus = evaluateCurrentViscousModulus(deltaKappa, tStep); //************************************* //Evaluation of the Recursive Equations //************************************* - tempTensor2.beProductOf(SSaTensor, plasFlowDirec); - beta = plasFlowDirec.dotProduct(tempTensor2); - beta += ( plasModulus - viscoModulus ) / norm; //+ viscoModulus; + double beta = dot(plasFlowDirec, dot(SSaTensor, plasFlowDirec)) + ( plasModulus - viscoModulus ) / norm; //+ viscoModulus; // Construction of the equation of Delta Kappa - tempTensor2.beProductOf(SSaTensor, toSolveTensor); - tempScalar = plasFlowDirec.dotProduct(tempTensor2); - incKappa = ( toSolveScalar / norm - tempScalar ) / beta; - tempTensor2 = plasFlowDirec; - tempTensor2.times(incKappa); - tempTensor2 += toSolveTensor; - incTempEffectiveStress.beProductOf(SSaTensor, tempTensor2); + auto tempScalar = dot(plasFlowDirec, dot(SSaTensor, toSolveTensor)); + auto incKappa = ( toSolveScalar / norm - tempScalar ) / beta; + auto incTempEffectiveStress = dot(SSaTensor, plasFlowDirec * incKappa + toSolveTensor); if ( lineSearchFlag == 1 ) { - max_num_iter = 4000; + current_max_num_iter = 4000; double eta = 0.1; beta = 25.e-4; int jMax = 10; double alfa = 1; double M = ( errorR * errorR + errorF * errorF ) / 2; double dM = -2 * M; - double newDeltaKappa; - FloatArray tempStress; for ( int j = 0; ; ++j ) { - tempStress = incTempEffectiveStress; - tempStress.times(-alfa); - tempStress.add(tempEffectiveStress); - newDeltaKappa = deltaKappa + alfa * incKappa; + auto tempStress = incTempEffectiveStress * (-alfa) + tempEffectiveStress; + auto newDeltaKappa = deltaKappa + alfa * incKappa; //************************************* // Evaluation of the f and R //************************************* // Construction of the derivative of the plastic flow - this->constructDerivativeOfPlasFlowDirec(derivPlasFlowDirec, fabric, F, tempStress); + auto derivPlasFlowDirec = this->constructDerivativeOfPlasFlowDirec(fabric, F, tempStress); + // Construction of the gradient Nabla_S of R and SSa tensor - tempTensor4 = derivPlasFlowDirec; - tempTensor4.times(newDeltaKappa); - tempTensor4.add(compliance); - SSaTensor.beInverseOf(tempTensor4); + SSaTensor = inv(derivPlasFlowDirec * newDeltaKappa + compliance); + // Evaluation of R - this->constructPlasFlowDirec(plasFlowDirec, norm, fabric, F, tempStress); - tempTensor2.beProductOf( compliance, ( tempStress - trialEffectiveStress ) ); - toSolveTensor = tempTensor2 + newDeltaKappa * plasFlowDirec; + auto tmp = this->constructPlasFlowDirec(fabric, F, tempStress); + plasFlowDirec = tmp.first; + norm = tmp.second; // FIXME: unusued in old code + + toSolveTensor = dot( compliance, ( tempStress - trialEffectiveStress ) ) + newDeltaKappa * plasFlowDirec; // Evaluation of f - tempTensor2.beProductOf(fabric, tempStress); - SFS = sqrt( tempStress.dotProduct(tempTensor2) ); + //auto SFS = sqrt( dot(tempStress, dot(fabric, tempStress)) ); // FIXME: was unused in old code toSolveScalar = evaluatePlasCriterion(fabric, F, tempStress, tempKappa + newDeltaKappa, newDeltaKappa, tStep); //************************************* // Evaluation of the error //************************************* - errLoop = toSolveTensor; - errorR = sqrt( errLoop.dotProduct(errLoop) ); + errorR = sqrt(dot(toSolveTensor, toSolveTensor)); errorF = fabs(toSolveScalar); double newM = ( errorR * errorR + errorF * errorF ) / 2; //check Goldstein's condition @@ -419,25 +366,24 @@ TrabBone3D :: projectOnYieldSurface(double &tempKappa, FloatArray &tempEffective // Evaluation of the f and R //************************************* // Construction of the derivative of the plastic flow - this->constructDerivativeOfPlasFlowDirec(derivPlasFlowDirec, fabric, F, tempEffectiveStress); + //auto derivPlasFlowDirec = this->constructDerivativeOfPlasFlowDirec(fabric, F, tempEffectiveStress); // FIXME: unused in old code + // Construction of the gradient Nabla_S of R and SSa tensor - tempTensor4 = derivPlasFlowDirec; - tempTensor4.times(deltaKappa); - tempTensor4.add(compliance); - SSaTensor.beInverseOf(tempTensor4); + //auto SSaTensor = inv(derivPlasFlowDirec * deltaKappa + compliance); // FIXME: unused in old code + // Evaluation of R - this->constructPlasFlowDirec(plasFlowDirec, norm, fabric, F, tempEffectiveStress); - tempTensor2.beProductOf( compliance, ( tempEffectiveStress - trialEffectiveStress ) ); - toSolveTensor = tempTensor2 + deltaKappa * plasFlowDirec; + auto tmp = this->constructPlasFlowDirec(fabric, F, tempEffectiveStress); + plasFlowDirec = tmp.first; + norm = tmp.second; + toSolveTensor = dot( compliance, ( tempEffectiveStress - trialEffectiveStress ) ) + deltaKappa * plasFlowDirec; + // Evaluation of f - tempTensor2.beProductOf(fabric, tempEffectiveStress); - SFS = sqrt( tempEffectiveStress.dotProduct(tempTensor2) ); + //auto SFS = sqrt( dot(tempEffectiveStress, dot(fabric, tempEffectiveStress)) ); // FIXME: was unsued in old code? toSolveScalar = evaluatePlasCriterion(fabric, F, tempEffectiveStress, tempKappa + deltaKappa, deltaKappa, tStep); //************************************* // Evaluation of the error //************************************* - errLoop = toSolveTensor; - errorR = sqrt( errLoop.dotProduct(errLoop) ); + errorR = sqrt(dot(toSolveTensor, toSolveTensor)); errorF = fabs(toSolveScalar); } @@ -447,14 +393,13 @@ TrabBone3D :: projectOnYieldSurface(double &tempKappa, FloatArray &tempEffective flagLoop++; convergence = ( fabs(errorF) < rel_yield_tol && errorR < strain_tol ); - } while ( flagLoop <= max_num_iter && !convergence ); + } while ( flagLoop <= current_max_num_iter && !convergence ); if ( convergence ) { - plasModulus = evaluateCurrentPlasticModulus(tempKappa + deltaKappa); - viscoModulus = evaluateCurrentViscousModulus(deltaKappa, tStep); - tempTensor2.beProductOf(SSaTensor, plasFlowDirec); - beta = plasFlowDirec.dotProduct(tempTensor2); - beta += ( plasModulus - viscoModulus ) / norm; + auto plasModulus = evaluateCurrentPlasticModulus(tempKappa + deltaKappa); + auto viscoModulus = evaluateCurrentViscousModulus(deltaKappa, tStep); + auto tempTensor2 = dot(SSaTensor, plasFlowDirec); + auto beta = dot(plasFlowDirec, tempTensor2) + ( plasModulus - viscoModulus ) / norm; tempPlasDef += deltaKappa * plasFlowDirec; tempKappa += deltaKappa; status->setBeta(beta); @@ -466,120 +411,75 @@ TrabBone3D :: projectOnYieldSurface(double &tempKappa, FloatArray &tempEffective return convergence; } -void -TrabBone3D :: constructPlasFlowDirec(FloatArray &answer, double &norm, FloatMatrix &fabric, FloatArray &F, FloatArray &S) +std::pair, double> +TrabBone3D :: constructPlasFlowDirec(FloatMatrixF<6,6> &fabric, const FloatArrayF<6> &F, const FloatArrayF<6> &S) const { - double SFS; - FloatArray FFS, tempTensor2; - FloatMatrix normAdjust; - ////////////////////////////////////////////////// - FFS.beProductOf(fabric, S); - // FS = F.dotProduct(S); - SFS = sqrt( S.dotProduct(FFS) ); + auto FFS = dot(fabric, S); + // FS = dot(F, S); + double SFS = sqrt( dot(S, FFS) ); // scaling matrix - this->constructNormAdjustTensor(normAdjust); + auto normAdjust = this->constructNormAdjustTensor(); //direction of Np - answer = F; - answer.add(1. / SFS, FFS); - tempTensor2.beProductOf(normAdjust, answer); + auto answer = F + FFS * (1. / SFS); + auto tempTensor2 = dot(normAdjust, answer); //norm Np - norm = sqrt( answer.dotProduct(tempTensor2) ); + double norm = sqrt( dot(answer, tempTensor2) ); //plastic flow - answer.times(1.0 / norm); - ////////////////////////////////////////////////// + answer *= 1.0 / norm; + + return {answer, norm}; } -void -TrabBone3D :: constructDerivativeOfPlasFlowDirec(FloatMatrix &answer, FloatMatrix &fabric, FloatArray &F, FloatArray &S) + + +FloatMatrixF<6,6> +TrabBone3D :: constructDerivativeOfPlasFlowDirec(const FloatMatrixF<6,6> &fabric, const FloatArrayF<6> &F, const FloatArrayF<6> &S) const { - double SFS, norm, SGS, h; - FloatArray FFS, FFSF, tempTensor2, tempTensor21, dNorm; - FloatMatrix normAdjust, tempTensor4, dNp, FSFS; - ////////////////////////////////////////////////// - FFS.beProductOf(fabric, S); - SFS = sqrt( S.dotProduct(FFS) ); - - SGS = pow(SFS, -3.); - FloatArray gradientOfG, gradientOfH; - FloatMatrix secondGradientOfG, helpMatrix; - gradientOfG.zero(); - gradientOfG.add(FFS); - gradientOfG.times(1. / SFS); - gradientOfG.add(F); - - helpMatrix.zero(); - helpMatrix.add(fabric); - helpMatrix.times(1. / SFS); - secondGradientOfG.beDyadicProductOf(FFS, FFS); - secondGradientOfG.times(-1. * SGS); - secondGradientOfG.add(helpMatrix); - - h = gradientOfG.dotProduct(gradientOfG); - h = sqrt(h); - - - gradientOfH.beTProductOf(secondGradientOfG, gradientOfG); - gradientOfH.times(1. / h); - - secondGradientOfG.times(h); - FloatMatrix test; - test.beDyadicProductOf(gradientOfG, gradientOfH); - test.times(-1); - test.add(secondGradientOfG); - test.times(1. / h / h); + // FIXME: unused in old code: + //auto FFS = dot(fabric, S); + //auto SFS = sqrt( dot(S, FFS) ); + //auto SGS = pow(SFS, -3.); + //auto secondGradientOfG = dyad(FFS, FFS) * (-1. * SGS) + fabric * (1. / SFS); + //to gradientOfG = FFS * (1. / SFS) + F; + //auto h = norm(gradientOfG)); + //auto gradientOfH = Tdot(secondGradientOfG, gradientOfG) * (1. / h); + //auto test = - dyad(gradientOfG, gradientOfH) + secondGradientOfG * (1./ h/.h); + //secondGradientOfG *= h; ////////////////////////////////////////////////////////////////// - FFS.beProductOf(fabric, S); - SFS = sqrt( S.dotProduct(FFS) ); + auto FFS = dot(fabric, S); + auto SFS = sqrt( dot(S, FFS) ); // scaling matrix - this->constructNormAdjustTensor(normAdjust); + auto normAdjust = this->constructNormAdjustTensor(); //norm - tempTensor2 = FFS; - tempTensor2.times(1. / SFS); - tempTensor2.add(F); - tempTensor21.beProductOf(normAdjust, tempTensor2); + auto tempTensor2 = FFS * (1. / SFS) + F; + auto tempTensor21 = dot(normAdjust, tempTensor2); //norm Np - norm = sqrt( tempTensor2.dotProduct(tempTensor21) ); + auto norm = sqrt( dot(tempTensor2, tempTensor21) ); /////////////////////////////////////////////////////////////////// - FSFS.beDyadicProductOf(FFS, FFS); - dNp.zero(); - dNp.add(FSFS); - dNp.times(-1. / SFS / SFS); - dNp.add(fabric); - dNp.times(1. / SFS / norm); + auto FSFS = dyad(FFS, FFS); + auto dNp = (FSFS * (-1. / SFS / SFS) + fabric) * (1. / SFS / norm); ////////////////////////////////////////////////////////////// - FFSF.zero(); - FFSF.add(FFS); - FFSF.times(1. / SFS); - FFSF.add(F); + auto FFSF = FFS * (1. / SFS) + F; ///////////////////////////////////////////////////////////////// - tempTensor4.zero(); - tempTensor4.add(FSFS); - tempTensor4.times(-1. / SFS / SFS); - tempTensor4.add(fabric); - tempTensor4.times(1. / SFS / norm); - tempTensor2.beProductOf(normAdjust, FFSF); - dNorm.beProductOf(tempTensor4, tempTensor2); + auto tempTensor4 = (FSFS * (-1. / SFS / SFS) + fabric) * (1. / SFS / norm); + tempTensor2 = dot(normAdjust, FFSF); + auto dNorm = dot(tempTensor4, tempTensor2); /////////////////////////////////////////////////////////////////// - tempTensor4.beDyadicProductOf(FFSF, dNorm); - tempTensor4.times(-1. / norm / norm); + tempTensor4 = dyad(FFSF, dNorm) * (-1. / norm / norm); //////////////////////////////////////////////////////////////////// - answer.zero(); - answer.add(dNp); - answer.add(tempTensor4); + return dNp + tempTensor4; } double -TrabBone3D :: evaluatePlasCriterion(FloatMatrix &fabric, FloatArray &F, FloatArray &stress, double kappa, double deltaKappa, TimeStep *tStep) +TrabBone3D :: evaluatePlasCriterion(const FloatMatrixF<6,6> &fabric, const FloatArrayF<6> &F, const FloatArrayF<6> &stress, double kappa, double deltaKappa, TimeStep *tStep) const { - FloatArray FFS; - double FS, SFS; - FFS.beProductOf(fabric, stress); - FS = F.dotProduct(stress); - SFS = sqrt( stress.dotProduct(FFS) ); + auto FFS = dot(fabric, stress); + auto FS = dot(F, stress); + auto SFS = sqrt( dot(stress, FFS) ); return SFS + FS - evaluateCurrentYieldStress(kappa) + this->evaluateCurrentViscousStress(deltaKappa, tStep); } double -TrabBone3D :: computeDamageParam(double tempKappa) +TrabBone3D :: computeDamageParam(double tempKappa) const { double tempDam; if ( tempKappa > 0. ) { @@ -593,11 +493,9 @@ TrabBone3D :: computeDamageParam(double tempKappa) double -TrabBone3D :: computeDamageParamPrime(double tempKappa) +TrabBone3D :: computeDamageParamPrime(double tempKappa) const { - double damagePrime; - damagePrime = critDam * expDam * exp(-expDam * tempKappa); - return damagePrime; + return critDam * expDam * exp(-expDam * tempKappa); } // // END: FUNCTION FOR DAMAGE PARAMETER @@ -609,12 +507,9 @@ TrabBone3D :: computeDamageParamPrime(double tempKappa) // double -TrabBone3D :: computeDamage(GaussPoint *gp, TimeStep *tStep) +TrabBone3D :: computeDamage(GaussPoint *gp, TimeStep *tStep) const { - double tempKappa; - - computeCumPlastStrain(tempKappa, gp, tStep); - + double tempKappa = computeCumPlastStrain( gp, tStep); double tempDam = computeDamageParam(tempKappa); if ( tempDam < 0 ) { OOFEM_ERROR("negative damage"); @@ -624,73 +519,66 @@ TrabBone3D :: computeDamage(GaussPoint *gp, TimeStep *tStep) } -void TrabBone3D :: computeCumPlastStrain(double &tempKappa, GaussPoint *gp, TimeStep *tStep) +double TrabBone3D :: computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const { - TrabBone3DStatus *status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); - tempKappa = status->giveTempKappa(); + auto status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); + return status->giveTempKappa(); } -void TrabBone3D :: computeDensificationStress(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep) +FloatArrayF<6> TrabBone3D :: computeDensificationStress(GaussPoint *gp, const FloatArrayF<6> &strain, TimeStep *tStep) const { - TrabBone3DStatus *status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); - answer.resize(6); - answer.zero(); - double traceLnU = ( totalStrain.at(1) + totalStrain.at(2) + totalStrain.at(3) ); + auto status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); + + FloatArrayF<6> answer; + double traceLnU = ( strain.at(1) + strain.at(2) + strain.at(3) ); double g = traceLnU - densCrit; status->setDensG(g); if ( g <= 0 ) { - answer.at(1) = answer.at(2) = answer.at(3) = 1; double factor = gammaL0 * pow(rho, rL) * g + gammaP0 *pow(rho, rP) * pow(g, tDens - 1); - answer.times(factor); + answer.at(1) = answer.at(2) = answer.at(3) = factor; } + return answer; } -void -TrabBone3D :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &totalStrain, TimeStep *tStep) +FloatArrayF<6> +TrabBone3D :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, + TimeStep *tStep) const { - double tempDam; - FloatArray effStress, densStress; - TrabBone3DStatus *status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); // compute effective stress using the plasticity model - performPlasticityReturn(gp, totalStrain, tStep); - effStress = status->giveTempEffectiveStress(); + this->performPlasticityReturn(gp, strain, tStep); + + auto effStress = status->giveTempEffectiveStress(); // evaluate damage variable - tempDam = computeDamage(gp, tStep); + double tempDam = computeDamage(gp, tStep); // transform effective stress into nominal stress - answer = ( 1 - tempDam ) * effStress; + auto stress = ( 1 - tempDam ) * effStress; - computePlasStrainEnerDensity(gp, totalStrain, answer); + computePlasStrainEnerDensity(gp, strain, stress); // add densification stress, if the densificator is activated if ( densCrit != 0 ) { - computeDensificationStress(densStress, gp, totalStrain, tStep); - answer.add(densStress); + stress += computeDensificationStress(gp, strain, tStep); } // store final damage, strain and stress in status status->setTempDam(tempDam); - status->letTempStrainVectorBe(totalStrain); - status->letTempStressVectorBe(answer); + status->letTempStrainVectorBe(strain); + status->letTempStressVectorBe(stress); + return stress; } -void -TrabBone3D :: constructAnisoComplTensor(FloatMatrix &answer) +FloatMatrixF<6,6> +TrabBone3D :: constructAnisoComplTensor() const { - FloatMatrix D(6, 6); - FloatMatrix DT(6, 6); - FloatMatrix T; - - this->constructFabricTransformationMatrix(T); - double m3 = 3. - m1 - m2; double eps0k = eps0 * pow(rho, expk); double mu0k = mu0 * pow(rho, expk); @@ -698,7 +586,7 @@ TrabBone3D :: constructAnisoComplTensor(FloatMatrix &answer) double m2l = pow(m2, expl); double m3l = pow(m3, expl); - answer.resize(6, 6); + FloatMatrixF<6,6> D; D.at(1, 1) = 1 / ( eps0k * m1l * m1l ); D.at(2, 2) = 1 / ( eps0k * m2l * m2l ); @@ -713,20 +601,20 @@ TrabBone3D :: constructAnisoComplTensor(FloatMatrix &answer) D.at(5, 5) = 1 / ( mu0k * m3l * m1l ); D.at(6, 6) = 1 / ( mu0k * m1l * m2l ); - FloatMatrix stiffness, t; - this->constructStiffnessTransformationMatrix(t); - stiffness.beInverseOf(D); - FloatMatrix ST, TST; - ST.beProductOf(stiffness, t); - TST.beTProductOf(t, ST); +#if 0 + /// Old code also computed this unused expression: + auto t = this->constructStiffnessTransformationMatrix(); + auto stiffness = inv(D); + auto TST = rotate(S, t); +#endif - DT.beProductOf(D, T); - answer.beTProductOf(T, DT); + auto T = this->constructFabricTransformationMatrix(); + return rotate(D, T); } -void -TrabBone3D :: constructAnisoStiffnessTensor(FloatMatrix &answer) +FloatMatrixF<6,6> +TrabBone3D :: constructAnisoStiffnessTensor() const { double m3 = 3. - m1 - m2; double eps0k = eps0 * pow(rho, expk); @@ -735,9 +623,6 @@ TrabBone3D :: constructAnisoStiffnessTensor(FloatMatrix &answer) double m2l = pow(m2, expl); double m3l = pow(m3, expl); - - double eksi, n13, n23, n12, n31, n32, n21; - double E1 = eps0k * m1l * m1l; double E2 = eps0k * m2l * m2l; double E3 = eps0k * m3l * m3l; @@ -746,18 +631,16 @@ TrabBone3D :: constructAnisoStiffnessTensor(FloatMatrix &answer) double G13 = mu0k * m1l * m3l; double G12 = mu0k * m1l * m2l; - n23 = nu0 * m2l / m3l; - n12 = nu0 * m1l / m2l; - n31 = nu0 * m3l / m1l; - n32 = nu0 * m3l / m2l; - n21 = nu0 * m2l / m1l; - n13 = nu0 * m1l / m3l; + double n23 = nu0 * m2l / m3l; + double n12 = nu0 * m1l / m2l; + double n31 = nu0 * m3l / m1l; + double n32 = nu0 * m3l / m2l; + double n21 = nu0 * m2l / m1l; + double n13 = nu0 * m1l / m3l; - eksi = 1. - ( n12 * n21 + n23 * n32 + n31 * n13 ) - ( n12 * n23 * n31 + n21 * n32 * n13 ); + double eksi = 1. - ( n12 * n21 + n23 * n32 + n31 * n13 ) - ( n12 * n23 * n31 + n21 * n32 * n13 ); - //constitutiveMatrix = new FloatMatrix(6,6) ; - FloatMatrix D(6, 6); - D.zero(); + FloatMatrixF<6,6> D; // switched letters from original oofem -> now produces same material stiffness matrix as Abaqus method D.at(1, 1) = E1 * ( 1. - n23 * n32 ) / eksi; D.at(1, 2) = E2 * ( n12 + n13 * n32 ) / eksi; @@ -773,23 +656,18 @@ TrabBone3D :: constructAnisoStiffnessTensor(FloatMatrix &answer) } } - D.at(4, 4) = G23; - D.at(5, 5) = G13; - D.at(6, 6) = G12; + D.at(4, 4) = G23; + D.at(5, 5) = G13; + D.at(6, 6) = G12; - FloatMatrix t; - this->constructStiffnessTransformationMatrix(t); - FloatMatrix DT; - DT.beProductOf(D, t); - answer.beTProductOf(t, DT); + auto t = this->constructStiffnessTransformationMatrix(); + return rotate(D, t); } - -void -TrabBone3D :: constructAnisoFabricTensor(FloatMatrix &answer) +FloatMatrixF<6,6> +TrabBone3D :: constructAnisoFabricTensor() const { - FloatMatrix T; double S0 = ( sig0Pos + sig0Neg ) / ( 2. * sig0Pos * sig0Neg ); double rhoP = pow(rho, 2. * expp); double m3 = 3. - m1 - m2; @@ -797,12 +675,7 @@ TrabBone3D :: constructAnisoFabricTensor(FloatMatrix &answer) double m2q = pow(m2, 2. * expq); double m3q = pow(m3, 2. * expq); - - this->constructFabricTransformationMatrix(T); - - FloatMatrix F(6, 6); - FloatMatrix FT; - + FloatMatrixF<6,6> F; F.at(1, 1) = S0 * S0 / ( rhoP * m1q * m1q ); F.at(2, 2) = S0 * S0 / ( rhoP * m2q * m2q ); F.at(3, 3) = S0 * S0 / ( rhoP * m3q * m3q ); @@ -816,40 +689,34 @@ TrabBone3D :: constructAnisoFabricTensor(FloatMatrix &answer) F.at(5, 5) = 1. / ( tau0 * tau0 * rhoP * m1q * m3q ); F.at(6, 6) = 1. / ( tau0 * tau0 * rhoP * m1q * m2q ); - - FT.beProductOf(F, T); - answer.beTProductOf(T, FT); + auto T = this->constructFabricTransformationMatrix(); + return rotate(F, T); } -void -TrabBone3D :: constructAnisoFtensor(FloatArray &answer) +FloatArrayF<6> +TrabBone3D :: constructAnisoFtensor() const { - FloatMatrix T; - double rhoP = pow(rho, expp); double m3 = 3. - m1 - m2; double m1q = pow(m1, 2. * expq); double m2q = pow(m2, 2. * expq); double m3q = pow(m3, 2. * expq); - - this->constructFabricTransformationMatrix(T); - FloatArray F(6); - F.zero(); - + FloatArrayF<6> F; F.at(1) = -( sig0Pos - sig0Neg ) / ( 2. * sig0Pos * sig0Neg * rhoP * m1q ); F.at(2) = -( sig0Pos - sig0Neg ) / ( 2. * sig0Pos * sig0Neg * rhoP * m2q ); F.at(3) = -( sig0Pos - sig0Neg ) / ( 2. * sig0Pos * sig0Neg * rhoP * m3q ); - - answer.beTProductOf(T, F); + + auto T = this->constructFabricTransformationMatrix(); + return Tdot(T, F); } -void -TrabBone3D :: constructStiffnessTransformationMatrix(FloatMatrix &answer) +FloatMatrixF<6,6> +TrabBone3D :: constructStiffnessTransformationMatrix() const { - answer.resize(6, 6); + FloatMatrixF<6,6> answer; answer.at(1, 1) = x1 * x1; answer.at(1, 2) = x2 * x2; @@ -892,14 +759,15 @@ TrabBone3D :: constructStiffnessTransformationMatrix(FloatMatrix &answer) answer.at(6, 4) = ( x2 * y3 + x3 * y2 ); answer.at(6, 5) = ( x1 * y3 + x3 * y1 ); answer.at(6, 6) = ( x1 * y2 + x2 * y1 ); + + return answer; } -void -TrabBone3D :: constructNormAdjustTensor(FloatMatrix &answer) +FloatMatrixF<6,6> +TrabBone3D :: constructNormAdjustTensor() const { - answer.resize(6, 6); - answer.zero(); + FloatMatrixF<6,6> answer; for ( int i = 1; i <= 3; i++ ) { answer.at(i, i) = 1.; @@ -908,14 +776,15 @@ TrabBone3D :: constructNormAdjustTensor(FloatMatrix &answer) for ( int i = 4; i <= 6; i++ ) { answer.at(i, i) = 0.5; } + return answer; } -void -TrabBone3D :: constructFabricTransformationMatrix(FloatMatrix &answer) +FloatMatrixF<6,6> +TrabBone3D :: constructFabricTransformationMatrix() const { - answer.resize(6, 6); + FloatMatrixF<6,6> answer; answer.at(1, 1) = x1 * x1; answer.at(1, 2) = x2 * x2; @@ -958,12 +827,14 @@ TrabBone3D :: constructFabricTransformationMatrix(FloatMatrix &answer) answer.at(6, 4) = ( x2 * y3 + x3 * y2 ); answer.at(6, 5) = ( x1 * y3 + x3 * y1 ); answer.at(6, 6) = ( x1 * y2 + x2 * y1 ); + + return answer; } -IRResultType -TrabBone3D :: initializeFrom(InputRecord *ir) +void +TrabBone3D :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralMaterial :: initializeFrom(ir); // Mandatory parameters IR_GIVE_FIELD(ir, eps0, _IFT_TrabBone3D_eps0); @@ -999,10 +870,6 @@ TrabBone3D :: initializeFrom(InputRecord *ir) chi0Neg = ( sig0Neg * sig0Neg ) / ( sig0Pos * sig0Pos ) * ( chi0Pos + 1 ) - 1; chi0 = chi0Pos; - - - - //local coordinate system //x' x1 = 1; @@ -1013,9 +880,6 @@ TrabBone3D :: initializeFrom(InputRecord *ir) y2 = 1; y3 = 0; - - - ///@todo Why not use vectors? IR_GIVE_OPTIONAL_FIELD(ir, x1, _IFT_TrabBone3D_x1); IR_GIVE_OPTIONAL_FIELD(ir, x2, _IFT_TrabBone3D_x2); @@ -1052,9 +916,6 @@ TrabBone3D :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, rel_yield_tol, _IFT_TrabBone3D_rel_yield_tol); strain_tol = 1.e-9; IR_GIVE_OPTIONAL_FIELD(ir, strain_tol, _IFT_TrabBone3D_strain_tol); - - - return StructuralMaterial :: initializeFrom(ir); } @@ -1062,7 +923,7 @@ TrabBone3D :: initializeFrom(InputRecord *ir) int TrabBone3D :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - TrabBone3DStatus *status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); if ( type == IST_DamageScalar ) { answer.resize(1); answer.at(1) = status->giveTempDam(); @@ -1098,7 +959,7 @@ TrabBone3D :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType double TrabBone3D :: predictRelativeComputationalCost(GaussPoint *gp) { - TrabBone3DStatus *status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBone3DStatus * >( this->giveStatus(gp) ); if ( status->giveTempDam() > 0.0 ) { return 15.0; @@ -1115,113 +976,13 @@ double TrabBone3D :: predictRelativeRedistributionCost(GaussPoint *gp) -TrabBone3DStatus :: TrabBone3DStatus(int n, Domain *d, GaussPoint *g) : StructuralMaterialStatus(n, d, g) +TrabBone3DStatus :: TrabBone3DStatus(GaussPoint *g) : StructuralMaterialStatus(g) { - kappa = 0.0; - tempKappa = 0.0; - dam = 0.0; - tempDam = 0.0; - tempPSED = 0.0; - tsed = 0.0; - tempTSED = 0.0; - beta = 0.0; - tempEffectiveStress.resize(6); - plasDef.resize(6); - tempPlasDef.resize(6); - plasFlowDirec.resize(6); - smtrx.resize(6, 6); - tangentMatrix.resize(6, 6); - SSaTensor.resize(6, 6); - densG = 1; -} - - - -TrabBone3DStatus :: ~TrabBone3DStatus() -{ } - - -double -TrabBone3DStatus :: giveKappa() -{ - return kappa; -} - -double -TrabBone3DStatus :: giveTempKappa() -{ - return tempKappa; -} - -double -TrabBone3DStatus :: giveDam() -{ - return dam; -} - -double -TrabBone3DStatus :: giveTempDam() -{ - return tempDam; -} - -double -TrabBone3DStatus :: giveTempPSED() -{ - return tempPSED; -} - -double -TrabBone3DStatus :: giveTSED() -{ - return tsed; -} - -double -TrabBone3DStatus :: giveTempTSED() -{ - return tempTSED; -} - -double -TrabBone3DStatus :: giveBeta() -{ - return beta; -} - -const FloatArray & -TrabBone3DStatus :: giveTempEffectiveStress() const -{ - return tempEffectiveStress; -} - -const FloatArray & -TrabBone3DStatus :: givePlasFlowDirec() const -{ - return plasFlowDirec; -} - -const FloatArray & -TrabBone3DStatus :: givePlasDef() const -{ - return plasDef; -} - -const FloatArray & -TrabBone3DStatus :: giveTempPlasDef() const -{ - return tempPlasDef; -} - -const FloatMatrix & -TrabBone3DStatus :: giveSSaTensor() const -{ - return SSaTensor; } void -TrabBone3DStatus :: printOutputAt(FILE *file, TimeStep *tStep) +TrabBone3DStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -1254,15 +1015,13 @@ TrabBone3DStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -TrabBone3DStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +TrabBone3DStatus :: saveContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: saveContext(stream, mode); if ( ( iores = plasDef.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); @@ -1304,19 +1063,16 @@ TrabBone3DStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) * THROW_CIOERR(iores); * } */ - return CIO_OK; } -contextIOResultType -TrabBone3DStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +TrabBone3DStatus :: restoreContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: restoreContext(stream, mode); // read raw data if ( ( iores = plasDef.restoreYourself(stream) ) != CIO_OK ) { @@ -1359,15 +1115,11 @@ TrabBone3DStatus :: restoreContext(DataStream &stream, ContextMode mode, void *o * THROW_CIOERR(iores); * } */ - - - - return CIO_OK; } MaterialStatus *TrabBone3D :: CreateStatus(GaussPoint *gp) const { - return new TrabBone3DStatus(1, StructuralMaterial :: giveDomain(), gp); + return new TrabBone3DStatus(gp); } } //end namespace oofem diff --git a/src/sm/Materials/BoneMaterials/trabbone3d.h b/src/sm/Materials/BoneMaterials/trabbone3d.h index feb7d8022..6474ea42d 100644 --- a/src/sm/Materials/BoneMaterials/trabbone3d.h +++ b/src/sm/Materials/BoneMaterials/trabbone3d.h @@ -34,14 +34,15 @@ #ifndef trabbone3d_h #define trabbone3d_h -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "floatarray.h" #include "floatmatrix.h" #include "cltypes.h" #include "matconst.h" #include "matstatus.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "cltypes.h" +#include "floatmatrixf.h" ///@name Input fields for TrabBone3D //@{ @@ -101,38 +102,41 @@ namespace oofem { class TrabBone3DStatus : public StructuralMaterialStatus { protected: - double kappa, tempKappa, dam, tempDam, tempPSED, tempTSED, tsed, beta; - FloatArray tempPlasDef, plasDef, effectiveStress, tempEffectiveStress, plasFlowDirec, tempStrain; - FloatMatrix smtrx, tangentMatrix, SSaTensor; + double kappa = 0., tempKappa = 0; + double dam = 0., tempDam = 0.; + double tempPSED = 0., tempTSED = 0.; + double tsed = 0.; + double beta = 0.; - /// Densificator criterion - double densG; + FloatArrayF<6> tempPlasDef, plasDef; + FloatArrayF<6> effectiveStress, tempEffectiveStress; + FloatArrayF<6> plasFlowDirec, tempStrain; + + FloatMatrixF<6,6> SSaTensor; + /// Densificator criterion + double densG = 1.; public: - TrabBone3DStatus(int n, Domain *d, GaussPoint *g); - - virtual ~TrabBone3DStatus(); - - virtual void printOutputAt(FILE *file, TimeStep *tStep); - - double giveKappa(); - double giveTempKappa(); - double giveDam(); - double giveTempDam(); - double giveTempPSED(); - double giveTSED(); - double giveTempTSED(); - double giveBeta(); - double giveDensG() { return densG; } - - const FloatArray &givePlasDef() const; - const FloatArray &giveTempPlasDef() const; - const FloatArray &giveTempEffectiveStress() const; - const FloatArray &givePlasFlowDirec() const; - const FloatMatrix &giveTangentMatrix() const; - const FloatMatrix &giveSmtrx() const; - const FloatMatrix &giveSSaTensor() const; + TrabBone3DStatus(GaussPoint *g); + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + double giveKappa() const { return kappa; } + double giveTempKappa() const { return tempKappa; } + double giveDam() const { return dam; } + double giveTempDam() const { return tempDam; } + double giveTempPSED() const { return tempPSED; } + double giveTSED() const { return tsed; } + double giveTempTSED() const { return tempTSED; } + double giveBeta() const { return beta; } + double giveDensG() const { return densG; } + + const FloatArrayF<6> &givePlasDef() const { return plasDef; } + const FloatArrayF<6> &giveTempPlasDef() const { return tempPlasDef; } + const FloatArrayF<6> &givePlasFlowDirec() const { return plasFlowDirec; } + const FloatArrayF<6> &giveTempEffectiveStress() const { return tempEffectiveStress; } + const FloatMatrixF<6,6> &giveSSaTensor() const { return SSaTensor; } void setTempKappa(double al) { tempKappa = al; } void setKappa(double values) { kappa = values; } @@ -140,22 +144,20 @@ class TrabBone3DStatus : public StructuralMaterialStatus void setTempPSED(double pse) { tempPSED = pse; } void setTempTSED(double tse) { tempTSED = tse; } void setBeta(double be) { beta = be; } - void setTempEffectiveStress(FloatArray &sc) { tempEffectiveStress = sc; } - void setTempPlasDef(FloatArray &epsip) { tempPlasDef = epsip; } - void setPlasFlowDirec(FloatArray &pfd) { plasFlowDirec = pfd; } - void setSmtrx(FloatMatrix &smt) { smtrx = smt; } - void setTangentMatrix(FloatMatrix &tmm) { tangentMatrix = tmm; } - void setSSaTensor(FloatMatrix &ssa) { SSaTensor = ssa; } + void setTempEffectiveStress(const FloatArrayF<6> &sc) { tempEffectiveStress = sc; } + void setTempPlasDef(const FloatArrayF<6> &epsip) { tempPlasDef = epsip; } + void setPlasFlowDirec(const FloatArrayF<6> &pfd) { plasFlowDirec = pfd; } + void setSSaTensor(const FloatMatrixF<6,6> &ssa) { SSaTensor = ssa; } void setDensG(double g) { densG = g; } - virtual const char *giveClassName() const { return "TrabBone3DStatus"; } + const char *giveClassName() const override { return "TrabBone3DStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -167,78 +169,86 @@ class TrabBone3DStatus : public StructuralMaterialStatus class TrabBone3D : public StructuralMaterial { protected: - double m1, m2, rho, eps0, nu0, mu0, expk, expl, sig0Pos, sig0Neg, chi0Pos, chi0, chi0Neg, tau0, expq, expp; - double plasHardFactor, expPlasHard, expDam, critDam; - int printflag, max_num_iter; - double rel_yield_tol, strain_tol; + double m1 = 0., m2 = 0.; + double rho = 0.; + double eps0 = 0., nu0 = 0., mu0 = 0.; + double expk = 0., expl = 0.; + double sig0Pos = 0., sig0Neg = 0.; + double chi0Pos = 0., chi0 = 0., chi0Neg = 0.; + double tau0 = 0.; + double expq = 0., expp = 0.; + double plasHardFactor = 0., expPlasHard = 0., expDam = 0., critDam = 0.; + int printflag = 0, max_num_iter = 0; + double rel_yield_tol = 0., strain_tol = 0.; /// Local coordinate system - double x1, x2, x3, y1, y2, y3, z1, z2, z3; + double x1 = 1., x2 = 0., x3 = 0.; + double y1 = 0., y2 = 1., y3 = 0.; + double z1 = 0., z2 = 0., z3 = 1.; /// Densificator properties - double gammaL0, gammaP0, tDens, densCrit, rL, rP, gammaL, gammaP; + double gammaL0 = 0., gammaP0 = 0., tDens = 0., densCrit = 0., rL = 0., rP = 0., gammaL = 0., gammaP = 0.; /// Viscosity parameter - double viscosity; + double viscosity = 0.; public: TrabBone3D(int n, Domain *d); - bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } - double evaluateCurrentYieldStress(const double kappa); - double evaluateCurrentPlasticModulus(const double kappa); - double evaluateCurrentViscousStress(const double deltaKappa, TimeStep *tStep); - double evaluateCurrentViscousModulus(const double deltaKappa, TimeStep *tStep); + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + double evaluateCurrentYieldStress(double kappa) const; + double evaluateCurrentPlasticModulus(double kappa) const; + double evaluateCurrentViscousStress(double deltaKappa, TimeStep *tStep) const; + double evaluateCurrentViscousModulus(double deltaKappa, TimeStep *tStep) const; - bool projectOnYieldSurface(double &tempKappa, FloatArray &tempEffectiveStress, FloatArray &tempPlasDef, const FloatArray &trialEffectiveStress, const FloatMatrix &elasticity, const FloatMatrix &compliance, TrabBone3DStatus *status, TimeStep *tStep, GaussPoint *gp, int lineSearchFlag); + bool projectOnYieldSurface(double &tempKappa, FloatArrayF<6> &tempEffectiveStress, FloatArrayF<6> &tempPlasDef, + const FloatArrayF<6> &trialEffectiveStress, + const FloatMatrixF<6,6> &elasticity, const FloatMatrixF<6,6> &compliance, + TrabBone3DStatus *status, TimeStep *tStep, GaussPoint *gp, int lineSearchFlag) const; - void performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep); + void performPlasticityReturn(GaussPoint *gp, const FloatArrayF<6> &strain, TimeStep *tStep) const; - void constructPlasFlowDirec(FloatArray &answer, double &norm, FloatMatrix &fabric, FloatArray &F, FloatArray &S); - void constructDerivativeOfPlasFlowDirec(FloatMatrix &answer, FloatMatrix &fabric, FloatArray &F, FloatArray &S); - double evaluatePlasCriterion(FloatMatrix &fabric, FloatArray &F, FloatArray &stress, double kappa, double deltaKappa, TimeStep *tStep); + std::pair, double> constructPlasFlowDirec(FloatMatrixF<6,6> &fabric, const FloatArrayF<6> &F, const FloatArrayF<6> &S) const; + FloatMatrixF<6,6> constructDerivativeOfPlasFlowDirec(const FloatMatrixF<6,6> &fabric, const FloatArrayF<6> &F, const FloatArrayF<6> &S) const; + double evaluatePlasCriterion(const FloatMatrixF<6,6> &fabric, const FloatArrayF<6> &F, const FloatArrayF<6> &stress, double kappa, double deltaKappa, TimeStep *tStep) const; - double computeDamageParam(double kappa); - double computeDamageParamPrime(double kappa); + double computeDamageParam(double kappa) const; + double computeDamageParamPrime(double kappa) const; - double computeDamage(GaussPoint *gp, TimeStep *tStep); + double computeDamage(GaussPoint *gp, TimeStep *tStep) const; - virtual void computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *tStep); + virtual double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const; - void computePlasStrainEnerDensity(GaussPoint *gp, const FloatArray &totalStrain, const FloatArray &totalStress); + void computePlasStrainEnerDensity(GaussPoint *gp, const FloatArrayF<6> &strain, const FloatArrayF<6> &stress) const; - void computeDensificationStress(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep); + FloatArrayF<6> computeDensificationStress(GaussPoint *gp, const FloatArrayF<6> &totalStrain, TimeStep *tStep) const; /// Construct anisotropic compliance tensor. - void constructAnisoComplTensor(FloatMatrix &answer); + FloatMatrixF<6,6> constructAnisoComplTensor() const; /// Construct anisotropic stiffness tensor. - void constructAnisoStiffnessTensor(FloatMatrix &answer); + FloatMatrixF<6,6> constructAnisoStiffnessTensor() const; /// Construct anisotropic fabric tensor. - void constructAnisoFabricTensor(FloatMatrix &answer); - void constructAnisoFtensor(FloatArray &answer); + FloatMatrixF<6,6> constructAnisoFabricTensor() const; + FloatArrayF<6> constructAnisoFtensor() const; - void constructStiffnessTransformationMatrix(FloatMatrix &answer); - void constructFabricTransformationMatrix(FloatMatrix &answer); + FloatMatrixF<6,6> constructStiffnessTransformationMatrix() const; + FloatMatrixF<6,6> constructFabricTransformationMatrix() const; /// Construct Tensor to adjust Norm. - void constructNormAdjustTensor(FloatMatrix &answer); - + FloatMatrixF<6,6> constructNormAdjustTensor() const; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix & answer, - MatResponseMode, GaussPoint * gp, - TimeStep * tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode, GaussPoint * gp, TimeStep * tStep) const override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *, - const FloatArray &, TimeStep *); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; - virtual const char *giveInputRecordName() const { return _IFT_TrabBone3D_Name; } - virtual const char *giveClassName() const { return "TrabBone3D"; } + const char *giveInputRecordName() const override { return _IFT_TrabBone3D_Name; } + const char *giveClassName() const override { return "TrabBone3D"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual double predictRelativeComputationalCost(GaussPoint *gp); - virtual double predictRelativeRedistributionCost(GaussPoint *gp); + double predictRelativeComputationalCost(GaussPoint *gp) override; + double predictRelativeRedistributionCost(GaussPoint *gp) override; }; } //end namespace oofem #endif diff --git a/src/sm/Materials/BoneMaterials/trabboneembed.C b/src/sm/Materials/BoneMaterials/trabboneembed.C index b5ff0372f..9b7e483a9 100644 --- a/src/sm/Materials/BoneMaterials/trabboneembed.C +++ b/src/sm/Materials/BoneMaterials/trabboneembed.C @@ -46,49 +46,36 @@ TrabBoneEmbed :: TrabBoneEmbed(int n, Domain *d) : StructuralMaterial(n, d) { } -void TrabBoneEmbed :: computeCumPlastStrain(double &tempAlpha, GaussPoint *gp, TimeStep *tStep) +double TrabBoneEmbed :: computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const { - tempAlpha = 0.; + return 0.; } -void -TrabBoneEmbed :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF<6,6> +TrabBoneEmbed :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - TrabBoneEmbedStatus *status = static_cast< TrabBoneEmbedStatus * >( this->giveStatus(gp) ); - - FloatMatrix elasticity, compliance; + // 'auto status = static_cast< TrabBoneEmbedStatus * >( this->giveStatus(gp) ); - this->constructIsoComplTensor(compliance, eps0, nu0); - elasticity.beInverseOf(compliance); + auto compliance = this->constructIsoComplTensor(eps0, nu0); + auto elasticity = inv(compliance); - answer.resize(6, 6); - answer = elasticity; - - status->setSmtrx(answer); + return elasticity; } void -TrabBoneEmbed :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain) +TrabBoneEmbed :: performPlasticityReturn(GaussPoint *gp, const FloatArrayF<6> &totalStrain) const { - double tempAlpha; - FloatArray tempPlasDef; - - TrabBoneEmbedStatus *status = static_cast< TrabBoneEmbedStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBoneEmbedStatus * >( this->giveStatus(gp) ); - tempPlasDef.resize(6); - tempAlpha = 0.; - - status->setTempPlasDef(tempPlasDef); - status->setTempAlpha(tempAlpha); + status->setTempPlasDef(zeros<6>()); + status->setTempAlpha(0.); } double -TrabBoneEmbed :: computeDamageParam(double alpha, GaussPoint *gp) +TrabBoneEmbed :: computeDamageParam(double alpha, GaussPoint *gp) const { double tempDam = 0.0; @@ -97,12 +84,9 @@ TrabBoneEmbed :: computeDamageParam(double alpha, GaussPoint *gp) double -TrabBoneEmbed :: computeDamage(GaussPoint *gp, TimeStep *tStep) +TrabBoneEmbed :: computeDamage(GaussPoint *gp, TimeStep *tStep) const { - double tempAlpha; - - computeCumPlastStrain(tempAlpha, gp, tStep); - + double tempAlpha = computeCumPlastStrain(gp, tStep); double tempDam = computeDamageParam(tempAlpha, gp); // double dam=0.0; @@ -111,72 +95,62 @@ TrabBoneEmbed :: computeDamage(GaussPoint *gp, TimeStep *tStep) } -void -TrabBoneEmbed :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) +FloatArrayF<6> +TrabBoneEmbed :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, + TimeStep *tStep) const { - double tempDam, tempTSED; - FloatArray plasDef; - FloatArray totalStress; - FloatMatrix compliance, elasticity; + auto status = static_cast< TrabBoneEmbedStatus * >( this->giveStatus(gp) ); - this->constructIsoComplTensor(compliance, eps0, nu0); - elasticity.beInverseOf(compliance); + auto compliance = this->constructIsoComplTensor(eps0, nu0); + auto elasticity = inv(compliance); - TrabBoneEmbedStatus *status = static_cast< TrabBoneEmbedStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); - performPlasticityReturn(gp, totalStrain); + performPlasticityReturn(gp, strain); - tempDam = computeDamage(gp, tStep); + double tempDam = computeDamage(gp, tStep); + //FloatArrayF<6> plasDef; - plasDef.resize(6); + auto stress = dot(elasticity, strain); - totalStress.beProductOf(elasticity, totalStrain); + double tempTSED = 0.5 * dot(strain, stress); - tempTSED = 0.5 * totalStrain.dotProduct(totalStress); - - answer.resize(6); - answer = totalStress; status->setTempDam(tempDam); - status->letTempStrainVectorBe(totalStrain); - status->letTempStressVectorBe(answer); + status->letTempStrainVectorBe(strain); + status->letTempStressVectorBe(stress); status->setTempTSED(tempTSED); + return stress; } -void -TrabBoneEmbed :: constructIsoComplTensor(FloatMatrix &answer, const double eps0, const double nu0) +FloatMatrixF<6,6> +TrabBoneEmbed :: constructIsoComplTensor(double eps0, double nu0) { double mu0 = eps0 / ( 2 * ( 1 + nu0 ) ); - answer.resize(6, 6); - answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = 1 / eps0; - answer.at(1, 2) = answer.at(2, 1) = answer.at(1, 3) = -nu0 / eps0; - answer.at(3, 1) = answer.at(2, 3) = answer.at(3, 2) = -nu0 / eps0; - answer.at(4, 4) = answer.at(5, 5) = answer.at(6, 6) = 1 / mu0; + FloatMatrixF<6,6> c; + c.at(1, 1) = c.at(2, 2) = c.at(3, 3) = 1 / eps0; + c.at(1, 2) = c.at(2, 1) = c.at(1, 3) = -nu0 / eps0; + c.at(3, 1) = c.at(2, 3) = c.at(3, 2) = -nu0 / eps0; + c.at(4, 4) = c.at(5, 5) = c.at(6, 6) = 1 / mu0; + return c; } -IRResultType -TrabBoneEmbed :: initializeFrom(InputRecord *ir) +void +TrabBoneEmbed :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - // Read material properties here + StructuralMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, eps0, _IFT_TrabBoneEmbed_eps0); IR_GIVE_FIELD(ir, nu0, _IFT_TrabBoneEmbed_nu0); - - return StructuralMaterial :: initializeFrom(ir); } int TrabBoneEmbed :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - TrabBoneEmbedStatus *status = static_cast< TrabBoneEmbedStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBoneEmbedStatus * >( this->giveStatus(gp) ); if ( type == IST_DamageScalar ) { answer.resize(1); answer.at(1) = 0.; @@ -216,31 +190,13 @@ TrabBoneEmbed :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateTy //////////////////TRABECULAR BONE STATUS///////////////////////// ///////////////////////////////////////////////////////////////// -TrabBoneEmbedStatus :: TrabBoneEmbedStatus(int n, Domain *d, GaussPoint *g) : StructuralMaterialStatus(n, d, g) +TrabBoneEmbedStatus :: TrabBoneEmbedStatus(GaussPoint *g) : StructuralMaterialStatus(g) { - alpha = 0.0; - dam = 0.0; - tsed = 0.0; - tempAlpha = 0.0; - tempDam = 0.0; - tempTSED = 0.0; - smtrx.resize(6, 6); -} - - -TrabBoneEmbedStatus :: ~TrabBoneEmbedStatus() -{ } - - -double -TrabBoneEmbedStatus :: giveTempTSED() -{ - return tempTSED; } void -TrabBoneEmbedStatus :: printOutputAt(FILE *file, TimeStep *tStep) +TrabBoneEmbedStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -272,46 +228,32 @@ TrabBoneEmbedStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -TrabBoneEmbedStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +TrabBoneEmbedStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: saveContext(stream, mode); // write a raw data //if (fwrite(&kappa,sizeof(double),1,stream) != 1) THROW_CIOERR(CIO_IOERR); //if (fwrite(&damage,sizeof(double),1,stream)!= 1) THROW_CIOERR(CIO_IOERR); - - return CIO_OK; } -contextIOResultType -TrabBoneEmbedStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +TrabBoneEmbedStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: restoreContext(stream, mode); // read raw data //if (fread (&kappa,sizeof(double),1,stream) != 1) THROW_CIOERR(CIO_IOERR); //if (fread (&damage,sizeof(double),1,stream) != 1) THROW_CIOERR(CIO_IOERR); - - return CIO_OK; } MaterialStatus *TrabBoneEmbed :: CreateStatus(GaussPoint *gp) const { - TrabBoneEmbedStatus *status = - new TrabBoneEmbedStatus(1, StructuralMaterial :: giveDomain(), gp); - return status; + return new TrabBoneEmbedStatus(gp); } } // end namespace oofem diff --git a/src/sm/Materials/BoneMaterials/trabboneembed.h b/src/sm/Materials/BoneMaterials/trabboneembed.h index 6e9ec03e9..1298095c1 100644 --- a/src/sm/Materials/BoneMaterials/trabboneembed.h +++ b/src/sm/Materials/BoneMaterials/trabboneembed.h @@ -35,13 +35,15 @@ #ifndef trabboneembed_h #define trabboneembed_h -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "floatarrayf.h" #include "floatarray.h" +#include "floatmatrixf.h" #include "floatmatrix.h" #include "cltypes.h" #include "matconst.h" #include "matstatus.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "cltypes.h" ///@name Input fields for TrabBoneEmbed @@ -58,37 +60,34 @@ namespace oofem { class TrabBoneEmbedStatus : public StructuralMaterialStatus { protected: - double tempAlpha, alpha; - double tempDam, dam; - double tempPSED, psed; - double tempTSED, tsed; - FloatMatrix smtrx, matConstD; - FloatArray densStress, tempPlasDef, plasDef, tempIncPlasDef; + double tempAlpha = 0., alpha = 0.; + double tempDam = 0., dam = 0.; + double tempPSED = 0., psed = 0.; + double tempTSED = 0., tsed = 0.; -public: - TrabBoneEmbedStatus(int n, Domain * d, GaussPoint * g); - virtual ~TrabBoneEmbedStatus(); + FloatMatrixF<6,6> smtrx, matConstD; + FloatArrayF<6> densStress, tempPlasDef, plasDef, tempIncPlasDef; - virtual void printOutputAt(FILE *file, TimeStep *tStep); +public: + TrabBoneEmbedStatus(GaussPoint * g); - double giveTempTSED(); + void printOutputAt(FILE *file, TimeStep *tStep) const override; + double giveTempTSED() const { return tempTSED; } void setTempDam(double da) { tempDam = da; } void setTempTSED(double tse) { tempTSED = tse; } void setTempAlpha(double al) { tempAlpha = al; } - void setTempPlasDef(FloatArray epsip) { tempPlasDef = epsip; } - void setSmtrx(FloatMatrix smt) { smtrx = smt; } + void setTempPlasDef(const FloatArrayF<6> &epsip) { tempPlasDef = epsip; } - const FloatArray &givePlasDef() const { return plasDef; } + const FloatArrayF<6> &givePlasDef() const { return plasDef; } - // definition - virtual const char *giveClassName() const { return "TrabBoneEmbedStatus"; } + const char *giveClassName() const override { return "TrabBoneEmbedStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -98,37 +97,35 @@ class TrabBoneEmbedStatus : public StructuralMaterialStatus class TrabBoneEmbed : public StructuralMaterial { protected: - double eps0, nu0; + double eps0 = 0., nu0 = 0.; public: TrabBoneEmbed(int n, Domain * d); - void performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain); + void performPlasticityReturn(GaussPoint *gp, const FloatArrayF<6> &totalStrain) const; - double computeDamageParam(double alpha, GaussPoint *gp); + double computeDamageParam(double alpha, GaussPoint *gp) const; - double computeDamage(GaussPoint *gp, TimeStep *tStep); + double computeDamage(GaussPoint *gp, TimeStep *tStep) const; - virtual void computeCumPlastStrain(double &alpha, GaussPoint *gp, TimeStep *tStep); + virtual double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const; /// Constructs the anisotropic compliance tensor. - void constructIsoComplTensor(FloatMatrix &answer, const double eps0, const double nu0); + static FloatMatrixF<6,6> constructIsoComplTensor(double eps0, double nu0); - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, + TimeStep *tStep) const override; - virtual const char *giveInputRecordName() const { return _IFT_TrabBoneEmbed_Name; } - virtual const char *giveClassName() const { return "TrabBoneEmbed"; } + const char *giveInputRecordName() const override { return _IFT_TrabBoneEmbed_Name; } + const char *giveClassName() const override { return "TrabBoneEmbed"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; }; } // end namespace oofem #endif diff --git a/src/sm/Materials/BoneMaterials/trabbonegrad3d.C b/src/sm/Materials/BoneMaterials/trabbonegrad3d.C index c07a383ff..2e50e27b6 100644 --- a/src/sm/Materials/BoneMaterials/trabbonegrad3d.C +++ b/src/sm/Materials/BoneMaterials/trabbonegrad3d.C @@ -45,16 +45,12 @@ namespace oofem { REGISTER_Material(TrabBoneGrad3D); -TrabBoneGrad3D :: TrabBoneGrad3D(int n, Domain *d) : TrabBone3D(n, d), GradDpMaterialExtensionInterface(d) +TrabBoneGrad3D :: TrabBoneGrad3D(int n, Domain *d) : TrabBone3D(n, d), GradientDamageMaterialExtensionInterface(d) { - L = 0.; } -TrabBoneGrad3D :: ~TrabBoneGrad3D() -{ } - -int -TrabBoneGrad3D :: hasMaterialModeCapability(MaterialMode mode) +bool +TrabBoneGrad3D :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _3dMat; } @@ -69,12 +65,12 @@ TrabBoneGrad3D :: giveStiffnessMatrix(FloatMatrix &answer, } void -TrabBoneGrad3D :: givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +TrabBoneGrad3D :: giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { case _3dMat: - give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + answer = give3dMaterialStiffnessMatrix(mode, gp, tStep); break; default: OOFEM_ERROR( "givePDGradMatrix_uu : unknown mode (%s)", __MaterialModeToString(mMode) ); @@ -82,7 +78,7 @@ TrabBoneGrad3D :: givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, } void -TrabBoneGrad3D :: givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +TrabBoneGrad3D :: giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { @@ -95,7 +91,7 @@ TrabBoneGrad3D :: givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, } void -TrabBoneGrad3D :: givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +TrabBoneGrad3D :: giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { @@ -107,8 +103,9 @@ TrabBoneGrad3D :: givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, } } + void -TrabBoneGrad3D :: givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +TrabBoneGrad3D :: giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { @@ -121,91 +118,88 @@ TrabBoneGrad3D :: givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, } void -TrabBoneGrad3D :: givePDGradMatrix_LD(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +TrabBoneGrad3D :: giveNonlocalInternalForces_N_factor(double &answer, double nlDamageDrivingVariable, GaussPoint *gp, TimeStep *tStep) { - MaterialMode mMode = gp->giveMaterialMode(); - OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mMode) ); + answer = nlDamageDrivingVariable; +} + +void +TrabBoneGrad3D :: giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlDamageDrivingVariable_grad, GaussPoint *gp, TimeStep *tStep) +{ + answer = nlDamageDrivingVariable_grad; + answer.times(internalLength * internalLength); } void -TrabBoneGrad3D :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +TrabBoneGrad3D :: computeLocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep) { - double tempDam, beta, tempKappa, kappa; - FloatArray tempEffectiveStress, tempTensor2, prodTensor, plasFlowDirec; - FloatMatrix elasticity, compliance, SSaTensor, secondTerm, thirdTerm, tangentMatrix; - TrabBoneGrad3DStatus *status = static_cast< TrabBoneGrad3DStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBoneGrad3DStatus * >( this->giveStatus(gp) ); + answer = status->giveTempKappa(); +} + +FloatMatrixF<6,6> +TrabBoneGrad3D :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto status = static_cast< TrabBoneGrad3DStatus * >( this->giveStatus(gp) ); + FloatMatrixF<6,6> answer; if ( mode == ElasticStiffness ) { - this->constructAnisoComplTensor(compliance); - elasticity.beInverseOf(compliance); + auto compliance = this->constructAnisoComplTensor(); + auto elasticity = inv(compliance); answer = elasticity; } else if ( mode == SecantStiffness ) { if ( printflag ) { printf("secant\n"); } - this->constructAnisoComplTensor(compliance); - elasticity.beInverseOf(compliance); - tempDam = status->giveTempDam(); - answer = elasticity; - answer.times(1.0 - tempDam); + auto compliance = this->constructAnisoComplTensor(); + auto elasticity = inv(compliance); + auto tempDam = status->giveTempDam(); + answer = elasticity * (1.0 - tempDam); } else if ( mode == TangentStiffness ) { - kappa = status->giveKappa(); - tempKappa = status->giveTempKappa(); - tempDam = status->giveTempDam(); + double kappa = status->giveKappa(); + double tempKappa = status->giveTempKappa(); + double tempDam = status->giveTempDam(); if ( tempKappa > kappa ) { // plastic loading // Imports - tempEffectiveStress = status->giveTempEffectiveStress(); - plasFlowDirec = status->givePlasFlowDirec(); - SSaTensor = status->giveSSaTensor(); - beta = status->giveBeta(); + auto &tempEffectiveStress = status->giveTempEffectiveStress(); + auto &plasFlowDirec = status->givePlasFlowDirec(); + auto &SSaTensor = status->giveSSaTensor(); + auto beta = status->giveBeta(); // Construction of the dyadic product tensor - prodTensor.beTProductOf(SSaTensor, plasFlowDirec); + auto prodTensor = Tdot(SSaTensor, plasFlowDirec); // Construction of the tangent stiffness second term - tempTensor2.beProductOf(SSaTensor, plasFlowDirec); - secondTerm.beDyadicProductOf(tempTensor2, prodTensor); - secondTerm.times(-( 1.0 - tempDam ) / beta); + auto tempTensor2 = dot(SSaTensor, plasFlowDirec); + auto secondTerm = dyad(tempTensor2, prodTensor) * (-( 1.0 - tempDam ) / beta); // Construction of the tangent stiffness - tangentMatrix = SSaTensor; - tangentMatrix.times(1.0 - tempDam); - tangentMatrix.add(secondTerm); + auto tangentMatrix = SSaTensor * (1.0 - tempDam) + secondTerm; if ( tempDam > status->giveDam() ) { double nlKappa = status->giveNonlocalCumulatedStrain(); - kappa = mParam * nlKappa + ( 1. - mParam ) * tempKappa; + double kappa = mParam * nlKappa + ( 1. - mParam ) * tempKappa; double gPrime = TrabBone3D :: computeDamageParamPrime(kappa); // Construction of the tangent stiffness third term - thirdTerm.beDyadicProductOf(tempEffectiveStress, prodTensor); - thirdTerm.times(gPrime); - thirdTerm.times( ( 1. - mParam ) / beta ); - tangentMatrix.add(thirdTerm); + auto thirdTerm = dyad(tempEffectiveStress, prodTensor) * gPrime * ( ( 1. - mParam ) / beta ); + tangentMatrix += thirdTerm; } answer = tangentMatrix; } else { // elastic behavior with damage // Construction of the secant stiffness - this->constructAnisoComplTensor(compliance); - elasticity.beInverseOf(compliance); - answer = elasticity; - answer.times(1.0 - tempDam); + auto compliance = this->constructAnisoComplTensor(); + auto elasticity = inv(compliance); + answer = elasticity * (1.0 - tempDam); } } double g = status->giveDensG(); if ( g <= 0 ) { double factor = gammaL0 * pow(rho, rL) + gammaP0 *pow(rho, rP) * ( tDens - 1 ) * pow(g, tDens - 2); - tangentMatrix.resize(6, 6); - tangentMatrix.zero(); - tangentMatrix.at(1, 1) = tangentMatrix.at(1, 2) = tangentMatrix.at(1, 3) = 1; - tangentMatrix.at(2, 1) = tangentMatrix.at(2, 2) = tangentMatrix.at(2, 3) = 1; - tangentMatrix.at(3, 1) = tangentMatrix.at(3, 2) = tangentMatrix.at(3, 3) = 1; - tangentMatrix.times(factor); - answer.add(tangentMatrix); + answer += I6_I6 * factor; } - - status->setSmtrx(answer); + return answer; } @@ -217,20 +211,17 @@ TrabBoneGrad3D :: give3dKappaMatrix(FloatMatrix &answer, MatResponseMode mode, G answer.resize(1, 6); answer.zero(); if ( mode == TangentStiffness ) { - TrabBoneGrad3DStatus *status = static_cast< TrabBoneGrad3DStatus * >( this->giveStatus(gp) ); - double beta; - FloatArray plasFlowDirec, prodTensor; - FloatMatrix SSaTensor; + auto status = static_cast< TrabBoneGrad3DStatus * >( this->giveStatus(gp) ); double kappa = status->giveKappa(); double tempKappa = status->giveTempKappa(); double dKappa = tempKappa - kappa; if ( dKappa > 0.0 ) { - plasFlowDirec = status->givePlasFlowDirec(); - SSaTensor = status->giveSSaTensor(); - beta = status->giveBeta(); - prodTensor.beTProductOf(SSaTensor, plasFlowDirec); + auto &plasFlowDirec = status->givePlasFlowDirec(); + auto &SSaTensor = status->giveSSaTensor(); + double beta = status->giveBeta(); + auto prodTensor = Tdot(SSaTensor, plasFlowDirec); for ( int i = 1; i <= 6; i++ ) { answer.at(1, i) = prodTensor.at(i); } @@ -248,26 +239,21 @@ TrabBoneGrad3D :: give3dGprime(FloatMatrix &answer, MatResponseMode mode, GaussP answer.resize(6, 1); answer.zero(); if ( mode == TangentStiffness ) { - TrabBoneGrad3DStatus *status = static_cast< TrabBoneGrad3DStatus * >( this->giveStatus(gp) ); - double damage, tempDamage; - double nlKappa, kappa; - FloatArray tempEffStress; - double gPrime; + auto status = static_cast< TrabBoneGrad3DStatus * >( this->giveStatus(gp) ); double tempKappa = status->giveTempKappa(); - damage = status->giveDam(); - nlKappa = status->giveNonlocalCumulatedStrain(); - kappa = mParam * nlKappa + ( 1. - mParam ) * tempKappa; - tempDamage = TrabBone3D :: computeDamageParam(kappa); - + double damage = status->giveDam(); + double nlKappa = status->giveNonlocalCumulatedStrain(); + double kappa = mParam * nlKappa + ( 1. - mParam ) * tempKappa; + double tempDamage = TrabBone3D :: computeDamageParam(kappa); if ( ( tempDamage - damage ) > 0 ) { - tempEffStress = status->giveTempEffectiveStress(); + auto &tempEffStress = status->giveTempEffectiveStress(); for ( int i = 1; i <= 6; i++ ) { answer.at(i, 1) = tempEffStress.at(i); } - kappa = mParam * nlKappa + ( 1. - mParam ) * tempKappa; - gPrime = TrabBone3D :: computeDamageParamPrime(kappa); + double kappa = mParam * nlKappa + ( 1. - mParam ) * tempKappa; + double gPrime = TrabBone3D :: computeDamageParamPrime(kappa); answer.times(gPrime * mParam); } } @@ -281,27 +267,23 @@ TrabBoneGrad3D :: giveInternalLength(FloatMatrix &answer, MatResponseMode mode, } void -TrabBoneGrad3D :: giveRealStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) +TrabBoneGrad3D :: giveRealStressVectorGradientDamage(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) { - TrabBoneGrad3DStatus *status = static_cast< TrabBoneGrad3DStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBoneGrad3DStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); TrabBone3D :: performPlasticityReturn(gp, totalStrain, tStep); double tempDamage = computeDamage(gp, tStep); - FloatArray tempEffStress = status->giveTempEffectiveStress(); - answer1.beScaled(1 - tempDamage, tempEffStress); + auto tempEffStress = status->giveTempEffectiveStress(); + answer1 = (1 - tempDamage) * tempEffStress; answer2 = status->giveTempKappa(); - if ( densCrit != 0 ) { - FloatArray densStress; - computeDensificationStress(densStress, gp, totalStrain, tStep); - answer1.add(densStress); + answer1.add(computeDensificationStress(gp, totalStrain, tStep)); } - status->letTempStrainVectorBe(totalStrain); status->setNonlocalCumulatedStrain(nonlocalCumulatedStrain); @@ -311,20 +293,20 @@ TrabBoneGrad3D :: giveRealStressVectorGrad(FloatArray &answer1, double &answer2, } -void -TrabBoneGrad3D :: computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *tStep) +double +TrabBoneGrad3D :: computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const { - TrabBoneGrad3DStatus *status = static_cast< TrabBoneGrad3DStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBoneGrad3DStatus * >( this->giveStatus(gp) ); double localCumPlastStrain = status->giveTempKappa(); double nlCumPlastStrain = status->giveNonlocalCumulatedStrain(); - kappa = mParam * nlCumPlastStrain + ( 1 - mParam ) * localCumPlastStrain; + return mParam * nlCumPlastStrain + ( 1 - mParam ) * localCumPlastStrain; } -IRResultType -TrabBoneGrad3D :: initializeFrom(InputRecord *ir) +void +TrabBoneGrad3D :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + TrabBone3D :: initializeFrom(ir); IR_GIVE_OPTIONAL_FIELD(ir, L, _IFT_TrabBoneGrad3D_L); if ( L < 0.0 ) { @@ -333,24 +315,16 @@ TrabBoneGrad3D :: initializeFrom(InputRecord *ir) mParam = 2.; IR_GIVE_OPTIONAL_FIELD(ir, mParam, _IFT_TrabBoneGrad3D_m); - - return TrabBone3D :: initializeFrom(ir); -} - - -TrabBoneGrad3DStatus :: TrabBoneGrad3DStatus(int n, Domain *d, GaussPoint *g) : - TrabBone3DStatus(n, d, g) -{ - nlKappa = 0; } -TrabBoneGrad3DStatus :: ~TrabBoneGrad3DStatus() -{ } +TrabBoneGrad3DStatus :: TrabBoneGrad3DStatus(GaussPoint *g) : + TrabBone3DStatus(g) +{} void -TrabBoneGrad3DStatus :: printOutputAt(FILE *file, TimeStep *tStep) +TrabBoneGrad3DStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { TrabBone3DStatus :: printOutputAt(file, tStep); } diff --git a/src/sm/Materials/BoneMaterials/trabbonegrad3d.h b/src/sm/Materials/BoneMaterials/trabbonegrad3d.h index 939e48b72..7efb57d40 100644 --- a/src/sm/Materials/BoneMaterials/trabbonegrad3d.h +++ b/src/sm/Materials/BoneMaterials/trabbonegrad3d.h @@ -36,7 +36,7 @@ #define TrabBoneGrad3D_h #include "trabbone3d.h" -#include "../sm/Materials/graddpmaterialextensioninterface.h" +#include "../sm/Materials/graddamagematerialextensioninterface.h" #include "cltypes.h" #define _IFT_TrabBoneGrad3D_Name "trabbonegrad3d" @@ -49,77 +49,78 @@ class LinearElasticMaterial; /** * Gradient bone damage-plastic material status. */ -class TrabBoneGrad3DStatus : public TrabBone3DStatus, GradDpMaterialStatusExtensionInterface +class TrabBoneGrad3DStatus : public TrabBone3DStatus, GradientDamageMaterialStatusExtensionInterface { protected: /// Equivalent strain for avaraging - double nlKappa; + double nlKappa = 0.; /// Reference to the basic elastic material - LinearElasticMaterial *linearElasticMaterial; + LinearElasticMaterial *linearElasticMaterial = nullptr; public: - TrabBoneGrad3DStatus(int n, Domain *d, GaussPoint *g); - virtual ~TrabBoneGrad3DStatus(); + TrabBoneGrad3DStatus(GaussPoint *g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual const char *giveClassName() const { return "TrabBoneGrad3DStatus"; } + const char *giveClassName() const override { return "TrabBoneGrad3DStatus"; } - virtual double giveNonlocalCumulatedStrain() { return nonlocalCumulatedStrain; } - virtual void setNonlocalCumulatedStrain(double nonlocalCumulatedStrain) { this->nonlocalCumulatedStrain = nonlocalCumulatedStrain; } + double giveNonlocalCumulatedStrain() const { return nonlocalDamageDrivingVariable; } + void setNonlocalCumulatedStrain(double nonlocalCumulatedStrain) { this->nonlocalDamageDrivingVariable = nonlocalCumulatedStrain; } - virtual void initTempStatus(); - - virtual void updateYourself(TimeStep *); + void initTempStatus() override; + void updateYourself(TimeStep *) override; }; /** * Gradient bone damage-plastic material model. */ -class TrabBoneGrad3D : public TrabBone3D, GradDpMaterialExtensionInterface +class TrabBoneGrad3D : public TrabBone3D, GradientDamageMaterialExtensionInterface { protected: - double L; - double mParam; + double L = 0.; + double mParam = 0.; public: TrabBoneGrad3D(int n, Domain *d); - virtual ~TrabBoneGrad3D(); - virtual const char *giveClassName() const { return "TrabBoneGrad3D"; } - virtual const char *giveInputRecordName() const { return _IFT_TrabBoneGrad3D_Name; } + const char *giveClassName() const override { return "TrabBoneGrad3D"; } + const char *giveInputRecordName() const override { return _IFT_TrabBoneGrad3D_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual Interface *giveInterface(InterfaceType t) { - if ( t == GradDpMaterialExtensionInterfaceType ) { - return static_cast< GradDpMaterialExtensionInterface * >( this ); + void initializeFrom(InputRecord &ir) override; + bool hasMaterialModeCapability(MaterialMode mode) const override; + Interface *giveInterface(InterfaceType t) override { + if ( t == GradientDamageMaterialExtensionInterfaceType ) { + return static_cast< GradientDamageMaterialExtensionInterface * >( this ); } else { return NULL; } } - virtual void givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_LD(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + void giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; - virtual void giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dMaterialStiffnessMatrix(FloatMatrix & answer, MatResponseMode, GaussPoint * gp, TimeStep * tStep); + void giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode, GaussPoint * gp, TimeStep * tStep) const override; void give3dKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); void give3dGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); void giveInternalLength(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveRealStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep); - virtual void computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *tStep); + + void computeLocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep) override; + void giveNonlocalInternalForces_N_factor(double &answer, double nlddv, GaussPoint *gp, TimeStep *tStep) override; + void giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlddv, GaussPoint *gp, TimeStep *tStep) override; + + void giveRealStressVectorGradientDamage(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) override; + double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const override; void performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain); //LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } protected: // Creates the corresponding material status - MaterialStatus *CreateStatus(GaussPoint *gp) const { return new TrabBoneGrad3DStatus(1, TrabBone3D :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new TrabBoneGrad3DStatus(gp); } }; } // end namespace oofem diff --git a/src/sm/Materials/BoneMaterials/trabbonematerial.C b/src/sm/Materials/BoneMaterials/trabbonematerial.C index 32c558f0a..e5e843391 100644 --- a/src/sm/Materials/BoneMaterials/trabbonematerial.C +++ b/src/sm/Materials/BoneMaterials/trabbonematerial.C @@ -35,7 +35,7 @@ #include "trabbonematerial.h" #include "floatmatrix.h" #include "floatarray.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "contextioerr.h" #include "mathfem.h" #include "classfactory.h" @@ -47,98 +47,80 @@ TrabBoneMaterial :: TrabBoneMaterial(int n, Domain *d) : StructuralMaterial(n, d { } -int -TrabBoneMaterial :: hasMaterialModeCapability(MaterialMode mode) +bool +TrabBoneMaterial :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _1dMat; } -void TrabBoneMaterial :: computeCumPlastStrain(double &alpha, GaussPoint *gp, TimeStep *tStep) +double TrabBoneMaterial :: computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const { - TrabBoneMaterialStatus *status = static_cast< TrabBoneMaterialStatus * >( this->giveStatus(gp) ); - alpha = status->giveTempAlpha(); + auto status = static_cast< TrabBoneMaterialStatus * >( this->giveStatus(gp) ); + return status->giveTempAlpha(); } -void -TrabBoneMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF<1,1> +TrabBoneMaterial :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - TrabBoneMaterialStatus *status = static_cast< TrabBoneMaterialStatus * >( this->giveStatus(gp) ); - - double epsnew; - double epsp, depsp; - double dam, alpha; - double matconstc; - FloatArray epsnewArray; + auto status = static_cast< TrabBoneMaterialStatus * >( this->giveStatus(gp) ); if ( mode == ElasticStiffness ) { - answer.resize(1, 1); - answer.at(1, 1) = E0; + return {E0}; } else if ( mode == SecantStiffness ) { - dam = status->giveTempDam(); - matconstc = status->giveMatConstC(); + double dam = status->giveTempDam(); + double matconstc = status->giveMatConstC(); - answer.resize(1, 1); - answer.at(1, 1) = ( 1.0 - dam ) * E0 + matconstc; + return {( 1.0 - dam ) * E0 + matconstc}; } else { - epsnew = status->giveTempStrainVector().at(1); - epsnewArray = status->giveTempStrainVector(); - epsp = status->giveTempPlasStrainVector().at(1); - depsp = status->giveTempIncPlasStrainVector().at(1); - alpha = status->giveTempAlpha(); - dam = status->giveTempDam(); - - answer.resize(1, 1); - + double epsnew = status->giveTempStrainVector().at(1); + auto &epsnewArray = status->giveTempStrainVector(); + double epsp = status->giveTempPlasStrainVector().at(1); + double depsp = status->giveTempIncPlasStrainVector().at(1); + double alpha = status->giveTempAlpha(); + double dam = status->giveTempDam(); + double matconstc = status->giveMatConstC(); + + /// FIXME: this function call modifies the material state (this should never happen in a tangent computation): computeDensification(gp, epsnewArray); - matconstc = status->giveMatConstC(); - if ( depsp != 0.0 ) { - answer.at(1, 1) = ( 1.0 - dam ) * ( E0 * ( Eil + Ek ) ) / ( E0 + Eil + Ek ) - - E0 * E0 * ( epsnew - epsp ) / ( E0 + Eil + Ek ) * adam * exp(-adam * alpha) * depsp / fabs(depsp) + matconstc; + return {( 1.0 - dam ) * ( E0 * ( Eil + Ek ) ) / ( E0 + Eil + Ek ) + - E0 * E0 * ( epsnew - epsp ) / ( E0 + Eil + Ek ) * adam * exp(-adam * alpha) * depsp / fabs(depsp) + matconstc}; } else { - answer.at(1, 1) = ( 1.0 - dam ) * E0 + matconstc; + return {( 1.0 - dam ) * E0 + matconstc}; } } - - status->setSmtrx( answer.at(1, 1) ); } void -TrabBoneMaterial :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain) +TrabBoneMaterial :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain) const { - double epsnew, epsold; - double epsp, depsp; - double alpha; - double sigp, sigY; - double gNewton, dgNewton; - - TrabBoneMaterialStatus *status = static_cast< TrabBoneMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBoneMaterialStatus * >( this->giveStatus(gp) ); - epsnew = totalStrain.at(1); - epsold = status->giveStrainVector().at(1); - epsp = status->givePlasStrainVector().at(1); - alpha = status->giveAlpha(); - sigp = E0 * epsnew - ( E0 + Ek ) * epsp; + double epsnew = totalStrain.at(1); + double epsold = status->giveStrainVector().at(1); + double epsp = status->givePlasStrainVector().at(1); + double alpha = status->giveAlpha(); + double sigp = E0 * epsnew - ( E0 + Ek ) * epsp; + double sigY; if ( sigp < 0.0 ) { sigY = SigYn; } else { sigY = SigYp; } + double depsp; if ( sigp / fabs(sigp) * sigp > sigY + Eil * alpha + Eie * ( 1 - exp(-kie * alpha) ) ) { depsp = epsnew - epsold; - gNewton = sigp / fabs(sigp) * ( E0 * epsnew - ( E0 + Ek ) * ( epsp + depsp ) ) - ( sigY + Eil * ( alpha + + double gNewton = sigp / fabs(sigp) * ( E0 * epsnew - ( E0 + Ek ) * ( epsp + depsp ) ) - ( sigY + Eil * ( alpha + sigp / fabs(sigp) * depsp ) + Eie * ( 1 - exp( -kie * ( alpha + sigp / fabs(sigp) * depsp ) ) ) ); while ( fabs(gNewton) > 10.e-7 ) { gNewton = sigp / fabs(sigp) * ( E0 * epsnew - ( E0 + Ek ) * ( epsp + depsp ) ) - ( sigY + Eil * ( alpha + sigp / fabs(sigp) * depsp ) + Eie * ( 1 - exp( -kie * ( alpha + sigp / fabs(sigp) * depsp ) ) ) ); - dgNewton = -sigp / fabs(sigp) * ( ( E0 + Ek ) + Eil + + double dgNewton = -sigp / fabs(sigp) * ( ( E0 + Ek ) + Eil + Eie * kie * exp( -kie * ( alpha + sigp / fabs(sigp) * depsp ) ) ); depsp += -gNewton / dgNewton; } @@ -157,15 +139,11 @@ TrabBoneMaterial :: performPlasticityReturn(GaussPoint *gp, const FloatArray &to void -TrabBoneMaterial :: computeDensification(GaussPoint *gp, const FloatArray &totalStrain) +TrabBoneMaterial :: computeDensification(GaussPoint *gp, const FloatArray &totalStrain) const { - double epsnew, sigc; - double matconstc; - - TrabBoneMaterialStatus *status = static_cast< TrabBoneMaterialStatus * >( this->giveStatus(gp) ); - - epsnew = totalStrain.at(1); - + auto status = static_cast< TrabBoneMaterialStatus * >( this->giveStatus(gp) ); + double epsnew = totalStrain.at(1); + double sigc, matconstc; if ( epsnew > EpsC ) { sigc = 0.0; matconstc = 0.0; @@ -180,7 +158,7 @@ TrabBoneMaterial :: computeDensification(GaussPoint *gp, const FloatArray &total double -TrabBoneMaterial :: computeDamageParam(double alpha, GaussPoint *gp) +TrabBoneMaterial :: computeDamageParam(double alpha, GaussPoint *gp) const { double dam; if ( alpha > 0. ) { @@ -199,56 +177,44 @@ TrabBoneMaterial :: computeDamageParam(double alpha, GaussPoint *gp) double -TrabBoneMaterial :: computeDamage(GaussPoint *gp, TimeStep *tStep) +TrabBoneMaterial :: computeDamage(GaussPoint *gp, TimeStep *tStep) const { - double alpha; - - computeCumPlastStrain(alpha, gp, tStep); - - double dam = computeDamageParam(alpha, gp); - - return dam; + double alpha = computeCumPlastStrain(gp, tStep); + return computeDamageParam(alpha, gp); } -void -TrabBoneMaterial :: giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) +FloatArrayF<1> +TrabBoneMaterial :: giveRealStressVector_1d(const FloatArrayF<1> &totalStrain, + GaussPoint *gp, TimeStep *tStep) const { - double epsnew, epsp; - double dam; - double sig, sigc; + auto status = static_cast< TrabBoneMaterialStatus * >( this->giveStatus(gp) ); - TrabBoneMaterialStatus *status = static_cast< TrabBoneMaterialStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); performPlasticityReturn(gp, totalStrain); - epsnew = totalStrain.at(1); - computeDensification(gp, totalStrain); - dam = computeDamage(gp, tStep); + double epsnew = totalStrain.at(1); + double dam = computeDamage(gp, tStep); + double epsp = status->giveTempPlasStrainVector().at(1); + double sigc = status->giveSigC(); + double sig = ( 1 - dam ) * E0 * ( epsnew - epsp ) + sigc; - epsp = status->giveTempPlasStrainVector().at(1); - sigc = status->giveSigC(); - sig = ( 1 - dam ) * E0 * ( epsnew - epsp ) + sigc; - - answer.resize(1); - answer.at(1) = sig; + FloatArrayF<1> answer = {sig}; status->setTempDam(dam); status->letTempStrainVectorBe(totalStrain); status->letTempStressVectorBe(answer); + + return answer; } -IRResultType -TrabBoneMaterial :: initializeFrom(InputRecord *ir) +void +TrabBoneMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - // Read material properties here + StructuralMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, E0, _IFT_TrabBoneMaterial_E0); IR_GIVE_FIELD(ir, Eil, _IFT_TrabBoneMaterial_Eil); @@ -261,8 +227,6 @@ TrabBoneMaterial :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, SigYp, _IFT_TrabBoneMaterial_SigYp); IR_GIVE_FIELD(ir, SigYn, _IFT_TrabBoneMaterial_SigYn); IR_GIVE_FIELD(ir, adam, _IFT_TrabBoneMaterial_adam); - - return StructuralMaterial :: initializeFrom(ir); } @@ -270,103 +234,18 @@ TrabBoneMaterial :: initializeFrom(InputRecord *ir) //////////////////TRABECULAR BONE STATUS///////////////////////// ///////////////////////////////////////////////////////////////// -TrabBoneMaterialStatus :: TrabBoneMaterialStatus(int n, Domain *d, GaussPoint *g) : StructuralMaterialStatus(n, d, g) +TrabBoneMaterialStatus :: TrabBoneMaterialStatus(GaussPoint *g) : StructuralMaterialStatus(g) { - alpha = 0.0; - tempAlpha = 0.0; - dam = 0.0; - tempDam = 0.0; - smtrx = 0.0; - slope = 0.0; - sigC = 0.0; - matConstC = 0.0; - epsp.resize(1); - tempEpsp.resize(1); - epsp.at(1) = 0.0; - tempEpsp.at(1) = 0.0; - tempDepsp.resize(1); - tempDepsp.at(1) = 0.0; -} - - -TrabBoneMaterialStatus :: ~TrabBoneMaterialStatus() -{ } - - -double -TrabBoneMaterialStatus :: giveAlpha() -{ - return alpha; -} - -double -TrabBoneMaterialStatus :: giveTempAlpha() -{ - return tempAlpha; -} - -double -TrabBoneMaterialStatus :: giveDam() -{ - return dam; -} - -double -TrabBoneMaterialStatus :: giveTempDam() -{ - return tempDam; -} - -double -TrabBoneMaterialStatus :: giveSmtrx() -{ - return smtrx; -} - -double -TrabBoneMaterialStatus :: giveSlope() -{ - return slope; -} - -double -TrabBoneMaterialStatus :: giveSigC() -{ - return sigC; -} - -double -TrabBoneMaterialStatus :: giveMatConstC() -{ - return matConstC; -} - -const FloatArray & -TrabBoneMaterialStatus :: givePlasStrainVector() -{ - return epsp; -} - -const FloatArray & -TrabBoneMaterialStatus :: giveTempPlasStrainVector() -{ - return tempEpsp; -} - -const FloatArray & -TrabBoneMaterialStatus :: giveTempIncPlasStrainVector() -{ - return tempDepsp; } void -TrabBoneMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +TrabBoneMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); - fprintf(file, "plastrains %f, alpha %f, dam %f, Slope %f, Smtrx %f ", this->tempEpsp.at(1), - this->tempAlpha, this->tempDam, this->slope, this->smtrx); + fprintf(file, "plastrains %f, alpha %f, dam %f, Slope %f ", this->tempEpsp.at(1), + this->tempAlpha, this->tempDam, this->slope); fprintf(file, "}\n"); } @@ -391,46 +270,32 @@ TrabBoneMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -TrabBoneMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +TrabBoneMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: saveContext(stream, mode); // write a raw data //if (fwrite(&kappa,sizeof(double),1,stream) != CIO_OK) THROW_CIOERR(CIO_IOERR); //if (fwrite(&damage,sizeof(double),1,stream)!= CIO_OK) THROW_CIOERR(CIO_IOERR); - - return CIO_OK; } -contextIOResultType -TrabBoneMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +TrabBoneMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: restoreContext(stream, mode); // read raw data //if (fread (&kappa,sizeof(double),1,stream) != 1) THROW_CIOERR(CIO_IOERR); //if (fread (&damage,sizeof(double),1,stream) != 1) THROW_CIOERR(CIO_IOERR); - - return CIO_OK; } MaterialStatus *TrabBoneMaterial :: CreateStatus(GaussPoint *gp) const { - TrabBoneMaterialStatus *status = - new TrabBoneMaterialStatus(1, StructuralMaterial :: giveDomain(), gp); - return status; + return new TrabBoneMaterialStatus(gp); } } // end namespace oofem diff --git a/src/sm/Materials/BoneMaterials/trabbonematerial.h b/src/sm/Materials/BoneMaterials/trabbonematerial.h index b916e9e20..18459383f 100644 --- a/src/sm/Materials/BoneMaterials/trabbonematerial.h +++ b/src/sm/Materials/BoneMaterials/trabbonematerial.h @@ -35,13 +35,14 @@ #ifndef trabbonematerial_h #define trabbonematerial_h -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "floatarrayf.h" #include "floatarray.h" #include "floatmatrix.h" #include "cltypes.h" #include "matconst.h" #include "matstatus.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "cltypes.h" ///@name Input fields for TrabBoneMaterial @@ -67,88 +68,85 @@ namespace oofem { class TrabBoneMaterialStatus : public StructuralMaterialStatus { protected: - double tempAlpha, alpha; - double tempDam, dam; - double smtrx, slope; - double sigC, matConstC; - FloatArray tempEpsp, epsp, tempDepsp; + double tempAlpha = 0., alpha = 0.; + double tempDam = 0., dam = 0.; + double slope = 0.; + double sigC = 0., matConstC = 0.; + + FloatArrayF<1> tempEpsp, epsp, tempDepsp; public: - TrabBoneMaterialStatus(int n, Domain * d, GaussPoint * g); - virtual ~TrabBoneMaterialStatus(); - - void printOutputAt(FILE *file, TimeStep *tStep); - - double giveAlpha(); - double giveTempAlpha(); - double giveDam(); - double giveTempDam(); - double giveSmtrx(); - double giveSlope(); - double giveSigC(); - double giveMatConstC(); - const FloatArray &givePlasStrainVector(); - const FloatArray &giveTempPlasStrainVector(); - const FloatArray &giveTempIncPlasStrainVector(); + TrabBoneMaterialStatus(GaussPoint * g); + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + double giveAlpha() const { return alpha; } + double giveTempAlpha() const { return tempAlpha; } + double giveDam() const { return dam; } + double giveTempDam() const { return tempDam; } + double giveSlope() const { return slope; } + double giveSigC() const { return sigC; } + double giveMatConstC() const { return matConstC; } + const FloatArrayF<1> &givePlasStrainVector() const { return epsp; } + const FloatArrayF<1> &giveTempPlasStrainVector() const { return tempEpsp; } + const FloatArrayF<1> &giveTempIncPlasStrainVector() const { return tempDepsp; } void setTempAlpha(double al) { tempAlpha = al; } void setTempDam(double da) { tempDam = da; } - void setSmtrx(double smt) { smtrx = smt; } void setSlope(double slp) { slope = slp; } void setSigC(double sc) { sigC = sc; } void setMatConstC(double mcc) { matConstC = mcc; } void setTempEpsp(double epsip) { tempEpsp.at(1) = epsip; } void setTempDepsp(double depsip) { tempDepsp.at(1) = depsip; } + const char *giveClassName() const override { return "TrabBoneMaterialStatus"; } - // definition - virtual const char *giveClassName() const { return "TrabBoneMaterialStatus"; } + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; - /** * Trabecular bone material model. */ class TrabBoneMaterial : public StructuralMaterial { protected: - double E0, Eil, Eie, kie, Ek, Cc, Cc2, EpsC, SigYp, SigYn, adam; + double E0 = 0., Eil = 0., Eie = 0.; + double kie = 0., Ek = 0.; + double Cc = 0., Cc2 = 0., EpsC = 0.; + double SigYp = 0., SigYn = 0.; + double adam = 0.; public: TrabBoneMaterial(int n, Domain * d); - void performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain); + void performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain) const; - void computeDensification(GaussPoint *gp, const FloatArray &totalStrain); + void computeDensification(GaussPoint *gp, const FloatArray &totalStrain) const; - double computeDamageParam(double alpha, GaussPoint *gp); + double computeDamageParam(double alpha, GaussPoint *gp) const; - double computeDamage(GaussPoint *gp, TimeStep *tStep); + double computeDamage(GaussPoint *gp, TimeStep *tStep) const; - virtual void computeCumPlastStrain(double &alpha, GaussPoint *gp, TimeStep *tStep); + virtual double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const; - virtual void give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, + TimeStep *tStep) const override; - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; - virtual int hasMaterialModeCapability(MaterialMode); + bool hasMaterialModeCapability(MaterialMode) const override; - virtual const char *giveInputRecordName() const { return _IFT_TrabBoneMaterial_Name; } - virtual const char *giveClassName() const { return "TrabBoneMaterial"; } + const char *giveInputRecordName() const override { return _IFT_TrabBoneMaterial_Name; } + const char *giveClassName() const override { return "TrabBoneMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; }; } // end namespace oofem #endif diff --git a/src/sm/Materials/BoneMaterials/trabbonenl.C b/src/sm/Materials/BoneMaterials/trabbonenl.C index 65b273e21..02cc9a3b5 100644 --- a/src/sm/Materials/BoneMaterials/trabbonenl.C +++ b/src/sm/Materials/BoneMaterials/trabbonenl.C @@ -57,7 +57,6 @@ REGISTER_Material(TrabBoneNL); TrabBoneNL :: TrabBoneNL(int n, Domain *d) : TrabBoneMaterial(n, d), StructuralNonlocalMaterialExtensionInterface(d) { - R = 0.; } // @@ -65,28 +64,16 @@ TrabBoneNL :: TrabBoneNL(int n, Domain *d) : TrabBoneMaterial(n, d), StructuralN ///////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////// -// BEGIN: DESTRUCTOR -// - -TrabBoneNL :: ~TrabBoneNL() -{ } - -// -// END: DESTRUCTOR -///////////////////////////////////////////////////////////////// - - ///////////////////////////////////////////////////////////////// // BEGIN: SUBROUTINE FOR UPDATE BEFORE NON LOCAL AVERAGE // update local values of accumulated pastic strain void -TrabBoneNL :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) +TrabBoneNL :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const { + auto nlstatus = static_cast< TrabBoneNLStatus * >( this->giveStatus(gp) ); + FloatArray SDstrainVector; - double cumPlastStrain; - TrabBoneNLStatus *nlstatus = static_cast< TrabBoneNLStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); this->giveStressDependentPartOfStrainVector(SDstrainVector, gp, strainVector, tStep, VM_Total); @@ -94,7 +81,7 @@ TrabBoneNL :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoi nlstatus->letTempStrainVectorBe(strainVector); this->performPlasticityReturn(gp, strainVector); - this->computeLocalCumPlastStrain(cumPlastStrain, strainVector, gp, tStep); + double cumPlastStrain = this->computeLocalCumPlastStrain(strainVector, gp, tStep); nlstatus->setLocalCumPlastStrainForAverage(cumPlastStrain); } @@ -107,13 +94,11 @@ TrabBoneNL :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoi // BEGIN: SUBROUTINE FOR EVALUATION OF TOTAL STRESS // -void -TrabBoneNL :: giveRealStressVector_1d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &strainVector, - TimeStep *tStep) +FloatArrayF<1> +TrabBoneNL :: giveRealStressVector_1d(const FloatArrayF<1> &strainVector, + GaussPoint *gp, TimeStep *tStep) const { - TrabBoneNLStatus *nlStatus = static_cast< TrabBoneNLStatus * >( this->giveStatus(gp) ); + auto nlStatus = static_cast< TrabBoneNLStatus * >( this->giveStatus(gp) ); double tempDamage = computeDamage(gp, tStep); double plasStrain = nlStatus->giveTempPlasStrainVector().at(1); @@ -121,12 +106,12 @@ TrabBoneNL :: giveRealStressVector_1d(FloatArray &answer, double effStress = E0 * elasStrain; double sigc = nlStatus->giveSigC(); - answer.resize(1); - answer.at(1) = ( 1. - tempDamage ) * effStress + sigc; + FloatArrayF<1> stress = {( 1. - tempDamage ) * effStress + sigc}; nlStatus->setTempDam(tempDamage); nlStatus->letTempStrainVectorBe(strainVector); - nlStatus->letTempStressVectorBe(answer); + nlStatus->letTempStressVectorBe(stress); + return stress; } // @@ -138,20 +123,20 @@ TrabBoneNL :: giveRealStressVector_1d(FloatArray &answer, // BEGIN: SUBROUTINE OF NONLOCAL ALPHA EVALUATION // -void -TrabBoneNL :: computeCumPlastStrain(double &alpha, GaussPoint *gp, TimeStep *tStep) +double +TrabBoneNL :: computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const { - double nonlocalContribution, nonlocalCumPlastStrain = 0.0; - TrabBoneNLStatus *nonlocStatus, *status = static_cast< TrabBoneNLStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBoneNLStatus * >( this->giveStatus(gp) ); this->buildNonlocalPointTable(gp); this->updateDomainBeforeNonlocAverage(tStep); auto list = status->giveIntegrationDomainList(); + double nonlocalCumPlastStrain = 0.0; for ( auto &lir: *list ) { - nonlocStatus = static_cast< TrabBoneNLStatus * >( this->giveStatus(lir.nearGp) ); - nonlocalContribution = nonlocStatus->giveLocalCumPlastStrainForAverage(); + auto nonlocStatus = static_cast< TrabBoneNLStatus * >( this->giveStatus(lir.nearGp) ); + double nonlocalContribution = nonlocStatus->giveLocalCumPlastStrainForAverage(); nonlocalContribution *= lir.weight; nonlocalCumPlastStrain += nonlocalContribution; } @@ -159,7 +144,7 @@ TrabBoneNL :: computeCumPlastStrain(double &alpha, GaussPoint *gp, TimeStep *tSt nonlocalCumPlastStrain *= 1. / status->giveIntegrationScale(); double localCumPlastStrain = status->giveLocalCumPlastStrainForAverage(); - alpha = mParam * nonlocalCumPlastStrain + ( 1 - mParam ) * localCumPlastStrain; + return mParam * nonlocalCumPlastStrain + ( 1 - mParam ) * localCumPlastStrain; } // @@ -190,20 +175,11 @@ TrabBoneNL :: giveInterface(InterfaceType type) // BEGIN: PARAMETERS OF INPUT FILE // -IRResultType -TrabBoneNL :: initializeFrom(InputRecord *ir) +void +TrabBoneNL :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = TrabBoneMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - result = StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + TrabBoneMaterial :: initializeFrom(ir); + StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); IR_GIVE_FIELD(ir, R, _IFT_TrabBoneNL_r); if ( R < 0.0 ) { @@ -212,8 +188,6 @@ TrabBoneNL :: initializeFrom(InputRecord *ir) mParam = 1.; IR_GIVE_OPTIONAL_FIELD(ir, mParam, _IFT_TrabBoneNL_m); - - return IRRT_OK; } // @@ -244,9 +218,9 @@ TrabBoneNL :: giveInputRecord(DynamicInputRecord &input) // double -TrabBoneNL :: computeWeightFunction(const FloatArray &src, const FloatArray &coord) +TrabBoneNL :: computeWeightFunction(const double R, const FloatArray &src, const FloatArray &coord) const { - double dist = src.distance(coord); + double dist = distance(src, coord); if ( ( dist >= 0. ) && ( dist <= this->R ) ) { double help = ( 1. - dist * dist / ( R * R ) ); @@ -266,39 +240,14 @@ TrabBoneNL :: computeWeightFunction(const FloatArray &src, const FloatArray &coo ///////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////// -// BEGIN: CONSTRUCTOR -// init state variables - -TrabBoneNLStatus :: TrabBoneNLStatus(int n, Domain *d, GaussPoint *g) : - TrabBoneMaterialStatus(n, d, g), StructuralNonlocalMaterialStatusExtensionInterface() +TrabBoneNLStatus :: TrabBoneNLStatus(GaussPoint *g) : + TrabBoneMaterialStatus(g), StructuralNonlocalMaterialStatusExtensionInterface() { - localCumPlastStrainForAverage = 0.0; } -// -// END: CONSTRUCTOR -///////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////// -// BEGIN: DESTRUCTOR -// - -TrabBoneNLStatus :: ~TrabBoneNLStatus() -{ } - -// -// END: DESTRUCTOR -///////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////// -// BEGIN: PRINTOUT -// void -TrabBoneNLStatus :: printOutputAt(FILE *file, TimeStep *tStep) +TrabBoneNLStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status {"); @@ -313,11 +262,6 @@ TrabBoneNLStatus :: printOutputAt(FILE *file, TimeStep *tStep) fprintf(file, "}\n"); } -// -// END: PRINTOUT -///////////////////////////////////////////////////////////////// - - ///////////////////////////////////////////////////////////////// // BEGIN: INITIALIZE TEMP VARIABLE (UPDATED DURING ITERATIONS) // initialize temporary state variables according to equilibriated state vars @@ -358,7 +302,7 @@ TrabBoneNLStatus :: giveInterface(InterfaceType type) if ( type == NonlocalMaterialStatusExtensionInterfaceType ) { return this; } else { - return NULL; + return nullptr; } } diff --git a/src/sm/Materials/BoneMaterials/trabbonenl.h b/src/sm/Materials/BoneMaterials/trabbonenl.h index 96360d3c1..429b66c41 100644 --- a/src/sm/Materials/BoneMaterials/trabbonenl.h +++ b/src/sm/Materials/BoneMaterials/trabbonenl.h @@ -36,7 +36,7 @@ #define trabbonenl_h #include "trabbonematerial.h" -#include "Materials/structuralnonlocalmaterialext.h" +#include "sm/Materials/structuralnonlocalmaterialext.h" #include "nonlocmatstiffinterface.h" #include "cltypes.h" @@ -55,24 +55,23 @@ class TrabBoneNLStatus : public TrabBoneMaterialStatus, public StructuralNonloca { protected: /// Equivalent strain for averaging. - double localCumPlastStrainForAverage; + double localCumPlastStrainForAverage = 0.; public: - TrabBoneNLStatus(int n, Domain * d, GaussPoint * g); - virtual ~TrabBoneNLStatus(); + TrabBoneNLStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - double giveLocalCumPlastStrainForAverage() { return localCumPlastStrainForAverage; } + double giveLocalCumPlastStrainForAverage() const { return localCumPlastStrainForAverage; } void setLocalCumPlastStrainForAverage(double ls) { localCumPlastStrainForAverage = ls; } - virtual const char *giveClassName() const { return "TrabBoneNLStatus"; } + const char *giveClassName() const override { return "TrabBoneNLStatus"; } - virtual void initTempStatus(); + void initTempStatus() override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; }; @@ -82,40 +81,39 @@ class TrabBoneNLStatus : public TrabBoneMaterialStatus, public StructuralNonloca class TrabBoneNL : public TrabBoneMaterial, public StructuralNonlocalMaterialExtensionInterface { protected: - double R; - double mParam; + double R = 0.; + double mParam = 0.; public: TrabBoneNL(int n, Domain * d); - virtual ~TrabBoneNL(); - virtual const char *giveClassName() const { return "TrabBoneNL"; } - virtual const char *giveInputRecordName() const { return _IFT_TrabBoneNL_Name; } + const char *giveClassName() const override { return "TrabBoneNL"; } + const char *giveInputRecordName() const override { return _IFT_TrabBoneNL_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; - virtual void computeCumPlastStrain(double &alpha, GaussPoint *gp, TimeStep *tStep); + double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &strainVector, TimeStep *tStep); + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strainVector, GaussPoint *gp, TimeStep *tStep) const override; - void computeLocalCumPlastStrain(double &alpha, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) + double computeLocalCumPlastStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const { - TrabBoneMaterial :: computeCumPlastStrain(alpha, gp, tStep); + return TrabBoneMaterial :: computeCumPlastStrain(gp, tStep); } - virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep); + void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const override; - virtual double computeWeightFunction(const FloatArray &src, const FloatArray &coord); + double computeWeightFunction(const double cl, const FloatArray &src, const FloatArray &coord) const override; - virtual int hasBoundedSupport() { return 1; } + int hasBoundedSupport() const override { return 1; } - virtual void giveSupportRadius(double &radius) { radius = this->R; } + double giveSupportRadius() const { return this->R; } protected: - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new TrabBoneNLStatus(1, TrabBoneMaterial :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new TrabBoneNLStatus(gp); } }; } // end namespace oofem #endif diff --git a/src/sm/Materials/BoneMaterials/trabbonenl3d.C b/src/sm/Materials/BoneMaterials/trabbonenl3d.C index 19f0a4941..ce5d711a4 100644 --- a/src/sm/Materials/BoneMaterials/trabbonenl3d.C +++ b/src/sm/Materials/BoneMaterials/trabbonenl3d.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "trabbonenl3d.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" @@ -55,20 +55,14 @@ REGISTER_Material(TrabBoneNL3D); TrabBoneNL3D :: TrabBoneNL3D(int n, Domain *d) : TrabBone3D(n, d), StructuralNonlocalMaterialExtensionInterface(d), NonlocalMaterialStiffnessInterface() { - R = 0.; } -TrabBoneNL3D :: ~TrabBoneNL3D() -{ } - - void -TrabBoneNL3D :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) +TrabBoneNL3D :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const { + auto nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); FloatArray SDstrainVector; - double cumPlastStrain; - TrabBoneNL3DStatus *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); this->giveStressDependentPartOfStrainVector(SDstrainVector, gp, strainVector, tStep, VM_Total); @@ -76,35 +70,27 @@ TrabBoneNL3D :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussP nlStatus->letTempStrainVectorBe(strainVector); this->performPlasticityReturn(gp, strainVector, tStep); - this->computeLocalCumPlastStrain(cumPlastStrain, strainVector, gp, tStep); + double cumPlastStrain = this->computeLocalCumPlastStrain(strainVector, gp, tStep); nlStatus->setLocalCumPlastStrainForAverage(cumPlastStrain); } -void -TrabBoneNL3D :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF<6,6> +TrabBoneNL3D :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, + TimeStep *tStep) const { - TrabBoneNL3DStatus *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); - - double tempDam, beta, nlKappa; - FloatArray tempEffectiveStress, tempTensor2, prodTensor, plasFlowDirec; - FloatMatrix elasticity, compliance, SSaTensor, secondTerm, thirdTerm, tangentMatrix; + auto nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); if ( mode == ElasticStiffness ) { - this->constructAnisoComplTensor(compliance); - elasticity.beInverseOf(compliance); - - answer = elasticity; + auto compliance = this->constructAnisoComplTensor(); + auto elasticity = inv(compliance); + return elasticity; } else if ( mode == SecantStiffness ) { - this->constructAnisoComplTensor(compliance); - elasticity.beInverseOf(compliance); - tempDam = nlStatus->giveTempDam(); - - answer = elasticity; - answer.times(1.0 - tempDam); - } else if ( mode == TangentStiffness ) { + auto compliance = this->constructAnisoComplTensor(); + auto elasticity = inv(compliance); + auto tempDam = nlStatus->giveTempDam(); + return elasticity * (1.0 - tempDam); + } else /*if ( mode == TangentStiffness )*/ { double kappa = nlStatus->giveKappa(); double tempKappa = nlStatus->giveTempKappa(); double dKappa = tempKappa - kappa; @@ -114,57 +100,45 @@ TrabBoneNL3D :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, if ( dKappa > 0.0 ) { // Imports - tempEffectiveStress = nlStatus->giveTempEffectiveStress(); - this->computeCumPlastStrain(nlKappa, gp, tStep); - tempDam = nlStatus->giveTempDam(); + auto &tempEffectiveStress = nlStatus->giveTempEffectiveStress(); + double nlKappa = this->computeCumPlastStrain(gp, tStep); + double tempDam = nlStatus->giveTempDam(); double dam = nlStatus->giveDam(); - plasFlowDirec = nlStatus->givePlasFlowDirec(); - SSaTensor = nlStatus->giveSSaTensor(); - beta = nlStatus->giveBeta(); + auto &plasFlowDirec = nlStatus->givePlasFlowDirec(); + auto &SSaTensor = nlStatus->giveSSaTensor(); + double beta = nlStatus->giveBeta(); + // Construction of the dyadic product tensor - prodTensor.beTProductOf(SSaTensor, plasFlowDirec); + auto prodTensor = Tdot(SSaTensor, plasFlowDirec); + // Construction of the tangent stiffness second term + auto secondTerm = dyad(dot(SSaTensor, plasFlowDirec), prodTensor) * (-( 1.0 - tempDam ) / beta); + + auto tangentMatrix = SSaTensor * (1.0 - tempDam) + secondTerm; + // Construction of the tangent stiffness third term if ( tempDam - dam > 0 ) { - thirdTerm.beDyadicProductOf(tempEffectiveStress, prodTensor); - thirdTerm.times(-expDam * critDam * exp(-expDam * nlKappa) * ( 1.0 - mParam ) / beta); - } else { - thirdTerm.resize(6, 6); + tangentMatrix += dyad(tempEffectiveStress, prodTensor) * (-expDam * critDam * exp(-expDam * nlKappa) * ( 1.0 - mParam ) / beta); + } - - // Construction of the tangent stiffness second term - tempTensor2.beProductOf(SSaTensor, plasFlowDirec); - secondTerm.beDyadicProductOf(tempTensor2, prodTensor); - secondTerm.times(-( 1.0 - tempDam ) / beta); - // Construction of the tangent stiffness - tangentMatrix = SSaTensor; - tangentMatrix.times(1.0 - tempDam); - tangentMatrix.add(secondTerm); - tangentMatrix.add(thirdTerm); - - answer = tangentMatrix; + return tangentMatrix; } else { // Import of state variables - tempDam = nlStatus->giveTempDam(); + double tempDam = nlStatus->giveTempDam(); // Construction of the tangent stiffness - this->constructAnisoComplTensor(compliance); - elasticity.beInverseOf(compliance); - answer = elasticity; - answer.times(1.0 - tempDam); + auto compliance = this->constructAnisoComplTensor(); + auto elasticity = inv(compliance); + return elasticity * (1.0 - tempDam); } } - - nlStatus->setSmtrx(answer); } void TrabBoneNL3D :: NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx &dest, const UnknownNumberingScheme &s, GaussPoint *gp, TimeStep *tStep) { - TrabBoneNL3DStatus *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); + auto nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); auto list = nlStatus->giveIntegrationDomainList(); - TrabBoneNL3D *rmat; - double coeff; FloatArray rcontrib, lcontrib; IntArray loc, rloc; @@ -175,10 +149,10 @@ TrabBoneNL3D :: NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx } for ( auto &lir: *list ) { - rmat = dynamic_cast< TrabBoneNL3D * >( lir.nearGp->giveMaterial() ); + auto rmat = dynamic_cast< TrabBoneNL3D * >( lir.nearGp->giveMaterial() ); if ( rmat ) { rmat->giveRemoteNonlocalStiffnessContribution(lir.nearGp, rloc, s, rcontrib, tStep); - coeff = gp->giveElement()->computeVolumeAround(gp) * lir.weight / nlStatus->giveIntegrationScale(); + double coeff = gp->giveElement()->computeVolumeAround(gp) * lir.weight / nlStatus->giveIntegrationScale(); contrib.clear(); contrib.plusDyadUnsym(lcontrib, rcontrib, - 1.0 * coeff); @@ -190,7 +164,7 @@ TrabBoneNL3D :: NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx std :: vector< localIntegrationRecord > * TrabBoneNL3D :: NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(GaussPoint *gp) { - TrabBoneNL3DStatus *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); + auto nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); this->buildNonlocalPointTable(gp); return nlStatus->giveIntegrationDomainList(); } @@ -199,31 +173,28 @@ int TrabBoneNL3D :: giveLocalNonlocalStiffnessContribution(GaussPoint *gp, IntArray &loc, const UnknownNumberingScheme &s, FloatArray &lcontrib, TimeStep *tStep) { - TrabBoneNL3DStatus *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); - StructuralElement *elem = static_cast< StructuralElement * >( gp->giveElement() ); + auto nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); + auto elem = static_cast< StructuralElement * >( gp->giveElement() ); - int nrows, nsize; - double sum, nlKappa, dDamFunc, dam, tempDam; - FloatArray localNu; - FloatMatrix b; - - this->computeCumPlastStrain(nlKappa, gp, tStep); - dam = nlStatus->giveDam(); - tempDam = nlStatus->giveTempDam(); + double nlKappa = this->computeCumPlastStrain(gp, tStep); + double dam = nlStatus->giveDam(); + double tempDam = nlStatus->giveTempDam(); if ( ( tempDam - dam ) > 0.0 ) { + FloatMatrix b; + elem->giveLocationArray(loc, s); - localNu = nlStatus->giveTempEffectiveStress(); + auto &localNu = nlStatus->giveTempEffectiveStress(); elem->giveLocationArray(loc, EModelDefaultEquationNumbering() ); elem->computeBmatrixAt(gp, b); - dDamFunc = expDam * critDam * exp(-expDam * nlKappa); + double dDamFunc = expDam * critDam * exp(-expDam * nlKappa); - nrows = b.giveNumberOfColumns(); - nsize = localNu.giveSize(); + int nrows = b.giveNumberOfColumns(); + int nsize = localNu.giveSize(); lcontrib.resize(nrows); for ( int i = 1; i <= nrows; i++ ) { - sum = 0.0; + double sum = 0.0; for ( int j = 1; j <= nsize; j++ ) { sum += b.at(j, i) * localNu.at(j); } @@ -242,8 +213,8 @@ void TrabBoneNL3D :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray &rloc, const UnknownNumberingScheme &s, FloatArray &rcontrib, TimeStep *tStep) { - TrabBoneNL3DStatus *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); - StructuralElement *elem = static_cast< StructuralElement * >( gp->giveElement() ); + auto nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); + auto elem = static_cast< StructuralElement * >( gp->giveElement() ); FloatMatrix b; @@ -273,57 +244,53 @@ TrabBoneNL3D :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray } -void -TrabBoneNL3D :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &totalStrain, TimeStep *tStep) +FloatArrayF<6> +TrabBoneNL3D :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, + TimeStep *tStep) const { - TrabBoneNL3DStatus *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); + auto nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); - double tempDam; - FloatArray effStress, totalStress, densStress; + performPlasticityReturn(gp, strain, tStep); + auto tempDam = computeDamage(gp, tStep); + auto &effStress = nlStatus->giveTempEffectiveStress(); - performPlasticityReturn(gp, totalStrain, tStep); - tempDam = computeDamage(gp, tStep); - effStress = nlStatus->giveTempEffectiveStress(); - - totalStress = ( 1 - tempDam ) * effStress; + auto stress = ( 1 - tempDam ) * effStress; for ( int i = 1; i <= 6; i++ ) { - if ( sqrt( totalStress.at(i) * totalStress.at(i) ) < 1e-8 ) { - totalStress.at(i) = 0.; + if ( sqrt( stress.at(i) * stress.at(i) ) < 1e-8 ) { + stress.at(i) = 0.; } } - computePlasStrainEnerDensity(gp, totalStrain, totalStress); + computePlasStrainEnerDensity(gp, strain, stress); if ( densCrit != 0. ) { - computeDensificationStress(densStress, gp, totalStrain, tStep); - answer.add(densStress); + stress += computeDensificationStress(gp, strain, tStep); } - answer = totalStress; nlStatus->setTempDam(tempDam); - nlStatus->letTempStrainVectorBe(totalStrain); - nlStatus->letTempStressVectorBe(answer); + nlStatus->letTempStrainVectorBe(strain); + nlStatus->letTempStressVectorBe(stress); + return stress; } -void -TrabBoneNL3D :: computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *tStep) +double +TrabBoneNL3D :: computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const { - double nonlocalContribution, nonlocalCumPlastStrain = 0.0; - TrabBoneNL3DStatus *nonlocStatus, *nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); + auto nlStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(gp) ); this->buildNonlocalPointTable(gp); this->updateDomainBeforeNonlocAverage(tStep); auto list = nlStatus->giveIntegrationDomainList(); + double nonlocalCumPlastStrain = 0.0; for ( auto &lir: *list ) { - nonlocStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(lir.nearGp) ); - nonlocalContribution = nonlocStatus->giveLocalCumPlastStrainForAverage(); + auto nonlocStatus = static_cast< TrabBoneNL3DStatus * >( this->giveStatus(lir.nearGp) ); + double nonlocalContribution = nonlocStatus->giveLocalCumPlastStrainForAverage(); nonlocalContribution *= lir.weight; nonlocalCumPlastStrain += nonlocalContribution; } @@ -331,7 +298,7 @@ TrabBoneNL3D :: computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *t nonlocalCumPlastStrain *= 1. / nlStatus->giveIntegrationScale(); double localCumPlastStrain = nlStatus->giveLocalCumPlastStrainForAverage(); - kappa = mParam * nonlocalCumPlastStrain + ( 1 - mParam ) * localCumPlastStrain; + return mParam * nonlocalCumPlastStrain + ( 1 - mParam ) * localCumPlastStrain; } @@ -343,25 +310,16 @@ TrabBoneNL3D :: giveInterface(InterfaceType type) } else if ( type == NonlocalMaterialStiffnessInterfaceType ) { return static_cast< NonlocalMaterialStiffnessInterface * >(this); } else { - return NULL; + return nullptr; } } -IRResultType -TrabBoneNL3D :: initializeFrom(InputRecord *ir) +void +TrabBoneNL3D :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = TrabBone3D :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - result = StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + TrabBone3D :: initializeFrom(ir); + StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); IR_GIVE_FIELD(ir, R, _IFT_TrabBoneNL3D_r); if ( R < 0.0 ) { @@ -370,8 +328,6 @@ TrabBoneNL3D :: initializeFrom(InputRecord *ir) mParam = 2.; IR_GIVE_OPTIONAL_FIELD(ir, mParam, _IFT_TrabBoneNL3D_m); - - return IRRT_OK; } @@ -386,9 +342,9 @@ TrabBoneNL3D :: giveInputRecord(DynamicInputRecord &input) double -TrabBoneNL3D :: computeWeightFunction(const FloatArray &src, const FloatArray &coord) +TrabBoneNL3D :: computeWeightFunction(const double R, const FloatArray &src, const FloatArray &coord) const { - double dist = src.distance(coord); + double dist = distance(src, coord); if ( ( dist >= 0. ) && ( dist <= this->R ) ) { double help = ( 1. - dist * dist / ( R * R ) ); @@ -403,19 +359,14 @@ TrabBoneNL3D :: computeWeightFunction(const FloatArray &src, const FloatArray &c /////////TRABECULAR BONE NONLOCAL MATERIAL STATUS//////////////// ///////////////////////////////////////////////////////////////// -TrabBoneNL3DStatus :: TrabBoneNL3DStatus(int n, Domain *d, GaussPoint *g) : - TrabBone3DStatus(n, d, g), StructuralNonlocalMaterialStatusExtensionInterface() +TrabBoneNL3DStatus :: TrabBoneNL3DStatus(GaussPoint *g) : + TrabBone3DStatus(g), StructuralNonlocalMaterialStatusExtensionInterface() { - localCumPlastStrainForAverage = 0.0; } -TrabBoneNL3DStatus :: ~TrabBoneNL3DStatus() -{ } - - void -TrabBoneNL3DStatus :: printOutputAt(FILE *file, TimeStep *tStep) +TrabBoneNL3DStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status {"); @@ -454,7 +405,7 @@ TrabBoneNL3DStatus :: giveInterface(InterfaceType type) if ( type == NonlocalMaterialStatusExtensionInterfaceType ) { return this; } else { - return NULL; + return nullptr; } } diff --git a/src/sm/Materials/BoneMaterials/trabbonenl3d.h b/src/sm/Materials/BoneMaterials/trabbonenl3d.h index 7de7d38fd..1a380e3cf 100644 --- a/src/sm/Materials/BoneMaterials/trabbonenl3d.h +++ b/src/sm/Materials/BoneMaterials/trabbonenl3d.h @@ -37,7 +37,7 @@ #define trabbonenl3d_h #include "trabbone3d.h" -#include "Materials/structuralnonlocalmaterialext.h" +#include "sm/Materials/structuralnonlocalmaterialext.h" #include "nonlocmatstiffinterface.h" #include "cltypes.h" @@ -56,24 +56,21 @@ class TrabBoneNL3DStatus : public TrabBone3DStatus, public StructuralNonlocalMat { protected: /// Equivalent strain for averaging. - double localCumPlastStrainForAverage; + double localCumPlastStrainForAverage = 0.; public: - TrabBoneNL3DStatus(int n, Domain * d, GaussPoint * g); - virtual ~TrabBoneNL3DStatus(); + TrabBoneNL3DStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - double giveLocalCumPlastStrainForAverage() { return localCumPlastStrainForAverage; } - const FloatArray *giveLTangentContrib(); + double giveLocalCumPlastStrainForAverage() const { return localCumPlastStrainForAverage; } void setLocalCumPlastStrainForAverage(double ls) { localCumPlastStrainForAverage = ls; } - // definition - virtual const char *giveClassName() const { return "TrabBoneNL3DStatus"; } + const char *giveClassName() const override { return "TrabBoneNL3DStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); - virtual Interface *giveInterface(InterfaceType it); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + Interface *giveInterface(InterfaceType it) override; }; @@ -85,22 +82,21 @@ public StructuralNonlocalMaterialExtensionInterface, public NonlocalMaterialStiffnessInterface { protected: - double R; - double mParam; + double R = 0.; + double mParam = 0.; public: TrabBoneNL3D(int n, Domain * d); - virtual ~TrabBoneNL3D(); - virtual const char *giveClassName() const { return "TrabBoneNL3D"; } - virtual const char *giveInputRecordName() const { return _IFT_TrabBoneNL3D_Name; } + const char *giveClassName() const override { return "TrabBoneNL3D"; } + const char *giveInputRecordName() const override { return _IFT_TrabBoneNL3D_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual void computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *tStep); + double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const override; /** * Computes the local cumulated plastic strain from given strain vector (full form). @@ -109,22 +105,22 @@ public NonlocalMaterialStiffnessInterface * @param gp Integration point. * @param tStep Time step. */ - void computeLocalCumPlastStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) + double computeLocalCumPlastStrain(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const { - TrabBone3D :: computeCumPlastStrain(kappa, gp, tStep); + return TrabBone3D :: computeCumPlastStrain(gp, tStep); } - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; #ifdef __OOFEG // Plots the sparse structure of stiffness contribution. - //virtual void NonlocalMaterialStiffnessInterface_showSparseMtrxStructure(GaussPoint *gp, oofegGraphicContext &gc, TimeStep *tStep); + //void NonlocalMaterialStiffnessInterface_showSparseMtrxStructure(GaussPoint *gp, oofegGraphicContext &gc, TimeStep *tStep) override; #endif - virtual void NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx &dest, const UnknownNumberingScheme &s, - GaussPoint *gp, TimeStep *tStep); + void NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx &dest, const UnknownNumberingScheme &s, + GaussPoint *gp, TimeStep *tStep) override; - virtual std :: vector< localIntegrationRecord > *NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(GaussPoint *gp); + std :: vector< localIntegrationRecord > *NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(GaussPoint *gp) override; /** * Computes the "local" part of nonlocal stiffness contribution assembled for given integration point. @@ -149,23 +145,23 @@ public NonlocalMaterialStiffnessInterface void giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray &rloc, const UnknownNumberingScheme &s, FloatArray &rcontrib, TimeStep *tStep); - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strainVector, TimeStep *tStep); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; - virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep); + void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const override; - virtual double computeWeightFunction(const FloatArray &src, const FloatArray &coord); + double computeWeightFunction(const double cl, const FloatArray &src, const FloatArray &coord) const override; - virtual int hasBoundedSupport() { return 1; } + int hasBoundedSupport() const override { return 1; } /// Determines the width (radius) of limited support of weighting function. virtual void giveSupportRadius(double &radius) { radius = this->R; } - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int estimatePackSize(DataStream &buff, GaussPoint *ip); + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int estimatePackSize(DataStream &buff, GaussPoint *ip) override; protected: - MaterialStatus *CreateStatus(GaussPoint *gp) const { return new TrabBoneNL3DStatus(1, TrabBone3D :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new TrabBoneNL3DStatus(gp); } }; } // end namespace oofem #endif diff --git a/src/sm/Materials/BoneMaterials/trabbonenlembed.C b/src/sm/Materials/BoneMaterials/trabbonenlembed.C index 2047b52cf..1bbdbee21 100644 --- a/src/sm/Materials/BoneMaterials/trabbonenlembed.C +++ b/src/sm/Materials/BoneMaterials/trabbonenlembed.C @@ -53,76 +53,64 @@ REGISTER_Material(TrabBoneNLEmbed); TrabBoneNLEmbed :: TrabBoneNLEmbed(int n, Domain *d) : TrabBoneEmbed(n, d), StructuralNonlocalMaterialExtensionInterface(d) { - R = 0.; } -TrabBoneNLEmbed :: ~TrabBoneNLEmbed() -{ } - void -TrabBoneNLEmbed :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) +TrabBoneNLEmbed :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const { - FloatArray SDstrainVector; - double cumPlastStrain; - TrabBoneNLEmbedStatus *nlstatus = static_cast< TrabBoneNLEmbedStatus * >( this->giveStatus(gp) ); + auto nlstatus = static_cast< TrabBoneNLEmbedStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); + + FloatArray SDstrainVector; this->giveStressDependentPartOfStrainVector(SDstrainVector, gp, strainVector, tStep, VM_Total); nlstatus->letTempStrainVectorBe(strainVector); this->performPlasticityReturn(gp, strainVector); - this->computeLocalCumPlastStrain(cumPlastStrain, strainVector, gp, tStep); + double cumPlastStrain = this->computeLocalCumPlastStrain(strainVector, gp, tStep); nlstatus->setLocalCumPlastStrainForAverage(cumPlastStrain); } -void -TrabBoneNLEmbed :: giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &strainVector, - TimeStep *tStep) +FloatArrayF<6> +TrabBoneNLEmbed :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, + TimeStep *tStep) const { - TrabBoneNLEmbedStatus *nlStatus = static_cast< TrabBoneNLEmbedStatus * >( this->giveStatus(gp) ); + auto nlStatus = static_cast< TrabBoneNLEmbedStatus * >( this->giveStatus(gp) ); + + auto compliance = this->constructIsoComplTensor(eps0, nu0); + auto elasticity = inv(compliance); - double tempDam, tempTSED; - FloatArray plasDef, totalStress; - FloatMatrix compliance, elasticity; + // Unused? + double tempDam = 0; + FloatArrayF<6> plasDef; - compliance.resize(6, 6); - this->constructIsoComplTensor(compliance, eps0, nu0); - elasticity.beInverseOf(compliance); + auto totalStress = dot(elasticity, strain); - tempDam = 0; - plasDef.resize(6); - - totalStress.beProductOf(elasticity, strainVector); - - tempTSED = 0.5 * strainVector.dotProduct(totalStress); - - answer.resize(6); - answer = totalStress; + double tempTSED = 0.5 * dot(strain, totalStress); nlStatus->setTempDam(tempDam); - nlStatus->letTempStrainVectorBe(strainVector); - nlStatus->letTempStressVectorBe(answer); + nlStatus->letTempStrainVectorBe(strain); + nlStatus->letTempStressVectorBe(totalStress); nlStatus->setTempTSED(tempTSED); + return totalStress; } -void -TrabBoneNLEmbed :: computeCumPlastStrain(double &alpha, GaussPoint *gp, TimeStep *tStep) +double +TrabBoneNLEmbed :: computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const { - double nonlocalContribution, nonlocalCumPlastStrain = 0.0; - TrabBoneNLEmbedStatus *nonlocStatus, *status = static_cast< TrabBoneNLEmbedStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TrabBoneNLEmbedStatus * >( this->giveStatus(gp) ); this->buildNonlocalPointTable(gp); this->updateDomainBeforeNonlocAverage(tStep); auto list = status->giveIntegrationDomainList(); + double nonlocalCumPlastStrain = 0.0; for ( auto &lir: *list ) { - nonlocStatus = static_cast< TrabBoneNLEmbedStatus * >( this->giveStatus(lir.nearGp) ); - nonlocalContribution = nonlocStatus->giveLocalCumPlastStrainForAverage(); + auto nonlocStatus = static_cast< TrabBoneNLEmbedStatus * >( this->giveStatus(lir.nearGp) ); + double nonlocalContribution = nonlocStatus->giveLocalCumPlastStrainForAverage(); nonlocalContribution *= lir.weight; nonlocalCumPlastStrain += nonlocalContribution; } @@ -131,7 +119,7 @@ TrabBoneNLEmbed :: computeCumPlastStrain(double &alpha, GaussPoint *gp, TimeStep // double localCumPlastStrain = status->giveLocalCumPlastStrainForAverage(); // alpha = mParam*nonlocalCumPlastStrain +(1-mParam)*localCumPlastStrain ; - alpha = 0.; + return 0.; } Interface * @@ -140,24 +128,15 @@ TrabBoneNLEmbed :: giveInterface(InterfaceType type) if ( type == NonlocalMaterialExtensionInterfaceType ) { return static_cast< StructuralNonlocalMaterialExtensionInterface * >(this); } else { - return NULL; + return nullptr; } } -IRResultType -TrabBoneNLEmbed :: initializeFrom(InputRecord *ir) +void +TrabBoneNLEmbed :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = TrabBoneEmbed :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - result = StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + TrabBoneEmbed :: initializeFrom(ir); + StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); IR_GIVE_FIELD(ir, R, _IFT_TrabBoneNLEmbed_r); if ( R < 0.0 ) { @@ -166,8 +145,6 @@ TrabBoneNLEmbed :: initializeFrom(InputRecord *ir) mParam = 1.5; IR_GIVE_OPTIONAL_FIELD(ir, mParam, _IFT_TrabBoneNLEmbed_m); - - return IRRT_OK; } @@ -181,9 +158,9 @@ TrabBoneNLEmbed :: giveInputRecord(DynamicInputRecord &input) double -TrabBoneNLEmbed :: computeWeightFunction(const FloatArray &src, const FloatArray &coord) +TrabBoneNLEmbed :: computeWeightFunction(const double R, const FloatArray &src, const FloatArray &coord) const { - double dist = src.distance(coord); + double dist = distance(src, coord); if ( ( dist >= 0. ) && ( dist <= this->R ) ) { double help = ( 1. - dist * dist / ( R * R ) ); @@ -193,17 +170,15 @@ TrabBoneNLEmbed :: computeWeightFunction(const FloatArray &src, const FloatArray return 0.0; } -TrabBoneNLEmbedStatus :: TrabBoneNLEmbedStatus(int n, Domain *d, GaussPoint *g) : - TrabBoneEmbedStatus(n, d, g), StructuralNonlocalMaterialStatusExtensionInterface() + +TrabBoneNLEmbedStatus :: TrabBoneNLEmbedStatus(GaussPoint *g) : + TrabBoneEmbedStatus(g), StructuralNonlocalMaterialStatusExtensionInterface() { - localCumPlastStrainForAverage = 0.0; } -TrabBoneNLEmbedStatus :: ~TrabBoneNLEmbedStatus() -{ } void -TrabBoneNLEmbedStatus :: printOutputAt(FILE *file, TimeStep *tStep) +TrabBoneNLEmbedStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status {"); @@ -233,16 +208,16 @@ TrabBoneNLEmbedStatus :: updateYourself(TimeStep *tStep) TrabBoneEmbedStatus :: updateYourself(tStep); } -contextIOResultType -TrabBoneNLEmbedStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +TrabBoneNLEmbedStatus :: saveContext(DataStream &stream, ContextMode mode) { - return TrabBoneEmbedStatus :: saveContext(stream, mode, obj); + TrabBoneEmbedStatus :: saveContext(stream, mode); } -contextIOResultType -TrabBoneNLEmbedStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +TrabBoneNLEmbedStatus :: restoreContext(DataStream &stream, ContextMode mode) { - return TrabBoneEmbedStatus :: restoreContext(stream, mode, obj); + TrabBoneEmbedStatus :: restoreContext(stream, mode); } @@ -252,7 +227,7 @@ TrabBoneNLEmbedStatus :: giveInterface(InterfaceType type) if ( type == NonlocalMaterialStatusExtensionInterfaceType ) { return this; } else { - return NULL; + return nullptr; } } } // end namespace oofem diff --git a/src/sm/Materials/BoneMaterials/trabbonenlembed.h b/src/sm/Materials/BoneMaterials/trabbonenlembed.h index ec9fdd17a..e18364dad 100644 --- a/src/sm/Materials/BoneMaterials/trabbonenlembed.h +++ b/src/sm/Materials/BoneMaterials/trabbonenlembed.h @@ -36,7 +36,7 @@ #define trabbonenlembed_h #include "trabboneembed.h" -#include "Materials/structuralnonlocalmaterialext.h" +#include "sm/Materials/structuralnonlocalmaterialext.h" #include "nonlocmatstiffinterface.h" #include "cltypes.h" @@ -57,29 +57,27 @@ class TrabBoneNLEmbedStatus : public TrabBoneEmbedStatus, public StructuralNonlo { protected: /// Equivalent strain for averaging. - double localCumPlastStrainForAverage; + double localCumPlastStrainForAverage = 0.; public: - TrabBoneNLEmbedStatus(int n, Domain * d, GaussPoint * g); - virtual ~TrabBoneNLEmbedStatus(); + TrabBoneNLEmbedStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; /// Gives the local cumulative plastic strain. - double giveLocalCumPlastStrainForAverage() { return localCumPlastStrainForAverage; } + double giveLocalCumPlastStrainForAverage() const { return localCumPlastStrainForAverage; } /// Sets the local cumulative plastic strain. void setLocalCumPlastStrainForAverage(double ls) { localCumPlastStrainForAverage = ls; } - // definition - virtual const char *giveClassName() const { return "TrabBoneNLEmbedStatus"; } + const char *giveClassName() const override { return "TrabBoneNLEmbedStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; }; /** @@ -88,40 +86,39 @@ class TrabBoneNLEmbedStatus : public TrabBoneEmbedStatus, public StructuralNonlo class TrabBoneNLEmbed : public TrabBoneEmbed, public StructuralNonlocalMaterialExtensionInterface { protected: - double R; - double mParam; + double R = 0.; + double mParam = 0.; public: TrabBoneNLEmbed(int n, Domain * d); - virtual ~TrabBoneNLEmbed(); - virtual const char *giveClassName() const { return "TrabBoneNLEmbed"; } - virtual const char *giveInputRecordName() const { return _IFT_TrabBoneNLEmbed_Name; } + const char *giveClassName() const override { return "TrabBoneNLEmbed"; } + const char *giveInputRecordName() const override { return _IFT_TrabBoneNLEmbed_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; - virtual void computeCumPlastStrain(double &alpha, GaussPoint *gp, TimeStep *tStep); + double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strainVector, TimeStep *tStep); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; - void computeLocalCumPlastStrain(double &alpha, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) + double computeLocalCumPlastStrain(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const { - TrabBoneEmbed :: computeCumPlastStrain(alpha, gp, tStep); + return TrabBoneEmbed :: computeCumPlastStrain(gp, tStep); } - virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep); - virtual double computeWeightFunction(const FloatArray &src, const FloatArray &coord); + void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const override; + double computeWeightFunction(const double cl, const FloatArray &src, const FloatArray &coord) const override; - virtual int hasBoundedSupport() { return 1; } + int hasBoundedSupport() const override { return 1; } /// Determines the width (radius) of limited support of weighting function. virtual void giveSupportRadius(double &radius) { radius = this->R; } protected: - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new TrabBoneNLEmbedStatus(1, TrabBoneEmbed :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new TrabBoneNLEmbedStatus(gp); } }; } // end namespace oofem #endif diff --git a/src/sm/Materials/ConcreteMaterials/compodamagemat.C b/src/sm/Materials/ConcreteMaterials/compodamagemat.C index 2e8eee060..da32492fa 100644 --- a/src/sm/Materials/ConcreteMaterials/compodamagemat.C +++ b/src/sm/Materials/ConcreteMaterials/compodamagemat.C @@ -33,10 +33,10 @@ */ #include "compodamagemat.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "gausspoint.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "mathfem.h" #include "classfactory.h" #include "contextioerr.h" @@ -50,15 +50,11 @@ CompoDamageMat :: CompoDamageMat(int n, Domain *d) : StructuralMaterial(n, d) } -CompoDamageMat :: ~CompoDamageMat() +void CompoDamageMat :: initializeFrom(InputRecord &ir) { -} - + Material :: initializeFrom(ir); -IRResultType CompoDamageMat :: initializeFrom(InputRecord *ir) -{ double value; - IRResultType result; // Required by IR_GIVE_FIELD macro //define transversely othotropic material stiffness parameters IR_GIVE_FIELD(ir, value, _IFT_CompoDamageMat_exx); @@ -110,8 +106,6 @@ IRResultType CompoDamageMat :: initializeFrom(InputRecord *ir) this->afterIter = 0; IR_GIVE_OPTIONAL_FIELD(ir, this->allowSnapBack, _IFT_CompoDamageMat_allowSnapBack); - - return Material :: initializeFrom(ir); } void CompoDamageMat :: giveInputRecord(DynamicInputRecord &input) @@ -122,15 +116,17 @@ void CompoDamageMat :: giveInputRecord(DynamicInputRecord &input) //called at the beginning of each time increment (not iteration), no influence of parameter -void CompoDamageMat :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<6,6> +CompoDamageMat :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix rotationMatrix; //already with reduced components - this->giveUnrotated3dMaterialStiffnessMatrix(answer, mode, gp); + auto d = this->giveUnrotated3dMaterialStiffnessMatrix(mode, gp); + FloatMatrixF<6,6> rotationMatrix; if ( this->giveMatStiffRotationMatrix(rotationMatrix, gp) ) { //material rotation due to lcs - answer.rotatedWith(rotationMatrix); + d = rotate(d, rotationMatrix); } + return d; } //called in each iteration, support for 3D and 1D material mode @@ -168,12 +164,12 @@ void CompoDamageMat :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, } //transform strain to local c.s. - this->transformStrainVectorTo(strainVectorL, elementCs, reducedTotalStrainVector, 0); + strainVectorL = this->transformStrainVectorTo(elementCs, reducedTotalStrainVector, 0); //strainVectorL.printYourself(); //damage criteria based on stress, assuming same damage parameter for tension/compression //determine unequilibrated stress vector - this->giveUnrotated3dMaterialStiffnessMatrix(de, SecantStiffness, gp); + de = this->giveUnrotated3dMaterialStiffnessMatrix(SecantStiffness, gp); tempStressVectorL.beProductOf(de, strainVectorL); i_max = 6; break; @@ -216,9 +212,9 @@ void CompoDamageMat :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, switch ( mMode ) { case _3dMat: ans = st->giveStrainVector(); - this->transformStrainVectorTo(equilStrainVectorL, elementCs, ans, 0); + equilStrainVectorL = this->transformStrainVectorTo(elementCs, ans, 0); ans = st->giveStressVector(); - this->transformStressVectorTo(equilStressVectorL, elementCs, ans, 0); + equilStressVectorL = this->transformStressVectorTo(elementCs, ans, 0); break; case _1dMat: @@ -322,14 +318,14 @@ void CompoDamageMat :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, switch ( mMode ) { case _3dMat: { //already with reduced stiffness components in local c.s. - this->giveUnrotated3dMaterialStiffnessMatrix(de, SecantStiffness, gp); + de = this->giveUnrotated3dMaterialStiffnessMatrix(SecantStiffness, gp); //de.printYourself(); //in local c.s. stressVectorL.beProductOf(de, strainVectorL); //stressVectorL.printYourself(); //transform local c.s to global c.s. st->tempStressMLCS = stressVectorL; - this->transformStressVectorTo(answer, elementCs, stressVectorL, 1); + answer = this->transformStressVectorTo(elementCs, stressVectorL, 1); break; } case _1dMat: { @@ -361,15 +357,14 @@ int CompoDamageMat :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalSt return 1; } -void CompoDamageMat :: giveUnrotated3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp) +FloatMatrixF<6,6> CompoDamageMat :: giveUnrotated3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp) const { double denom; double ex, ey, ez, nxy, nxz, nyz, gyz, gzx, gxy; double a, b, c, d, e, f; FloatArray tempOmega; - answer.resize(6, 6); - answer.zero(); + FloatMatrixF<6,6> answer; CompoDamageMatStatus *st = static_cast< CompoDamageMatStatus * >( this->giveStatus(gp) ); @@ -409,10 +404,11 @@ void CompoDamageMat :: giveUnrotated3dMaterialStiffnessMatrix(FloatMatrix &answe answer.at(6, 6) = gxy; answer.symmetrized(); //answer.printYourself(); + return answer; } //returns material rotation stiffness matrix [6x6] -int CompoDamageMat :: giveMatStiffRotationMatrix(FloatMatrix &answer, GaussPoint *gp) +int CompoDamageMat :: giveMatStiffRotationMatrix(FloatMatrixF<6,6> &answer, GaussPoint *gp) const { FloatMatrix Lt(3, 3); StructuralElement *element = static_cast< StructuralElement * >( gp->giveElement() ); @@ -427,7 +423,7 @@ int CompoDamageMat :: giveMatStiffRotationMatrix(FloatMatrix &answer, GaussPoint } //rotate from unrotated (base) c.s. to local material c.s. - this->giveStrainVectorTranformationMtrx(answer, Lt); + answer = this->giveStrainVectorTranformationMtrx(Lt); return 1; break; @@ -520,7 +516,7 @@ void CompoDamageMat :: checkSnapBack(GaussPoint *gp, MaterialMode mMode) elem_h = charLenModes.at(i); if ( elem_h > 2 * l_ch ) { if ( this->allowSnapBack.contains(i + 6 * j) ) { - OOFEM_LOG_INFO("Allowed snapback of 3D element %d GP %d Gf(%d)=%f, would need Gf>%f\n", gp->giveElement()->giveNumber(), gp->giveNumber(), j == 0 ? i : -i, Gf, ft * ft * elem_h / 2 / modulus); + OOFEM_LOG_INFO("Allowed snapback of 3D element %d GP %d Gf(%d)=%f, would need Gf>%f\n", gp->giveElement()->giveGlobalNumber(), gp->giveNumber(), j == 0 ? i : -i, Gf, ft * ft * elem_h / 2 / modulus); } else { OOFEM_ERROR("Decrease size of 3D element %d or increase Gf(%d)=%f to Gf>%f, possible snap-back problems", gp->giveElement()->giveNumber(), j == 0 ? i : -i, Gf, ft * ft * elem_h / 2 / modulus); } @@ -537,7 +533,7 @@ void CompoDamageMat :: checkSnapBack(GaussPoint *gp, MaterialMode mMode) if ( elem_h > 2 * l_ch ) { ///@todo Check value here for 1d mat (old broken code used undeclared variable) if ( this->allowSnapBack.contains(1 + 6 * j) ) { - OOFEM_LOG_INFO("Allowed snapback of 1D element %d GP %d Gf(%d)=%f, would need Gf>%f\n", gp->giveElement()->giveNumber(), gp->giveNumber(), j == 0 ? 1 : -1, Gf, ft * ft * elem_h / 2 / modulus); + OOFEM_LOG_INFO("Allowed snapback of 1D element %d GP %d Gf(%d)=%f, would need Gf>%f\n", gp->giveElement()->giveGlobalNumber(), gp->giveNumber(), j == 0 ? 1 : -1, Gf, ft * ft * elem_h / 2 / modulus); } else { OOFEM_ERROR("Decrease size of 1D element %d or increase Gf(%d)=%f to Gf>%f, possible snap-back problems", gp->giveElement()->giveNumber(), j == 0 ? 1 : -1, Gf, ft * ft * elem_h / 2 / modulus); } @@ -551,7 +547,7 @@ void CompoDamageMat :: checkSnapBack(GaussPoint *gp, MaterialMode mMode) } // constructor -CompoDamageMatStatus :: CompoDamageMatStatus(int n, Domain *d, GaussPoint *g) : StructuralMaterialStatus(n, d, g) +CompoDamageMatStatus :: CompoDamageMatStatus(GaussPoint *g) : StructuralMaterialStatus(g) { //largest strain ever reached [6 tension, 6 compression] this->kappa.resize(12); @@ -579,16 +575,10 @@ CompoDamageMatStatus :: CompoDamageMatStatus(int n, Domain *d, GaussPoint *g) : this->elemCharLength.resize(3); this->elemCharLength.zero(); - - this->Iteration = 0; } -// destructor -CompoDamageMatStatus :: ~CompoDamageMatStatus() -{ } - -void CompoDamageMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) +void CompoDamageMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { int maxComponents = 0; StructuralMaterialStatus :: printOutputAt(file, tStep); @@ -624,8 +614,6 @@ void CompoDamageMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) fprintf( file, "%.2e ", this->kappa.at(6 * j + i) ); } } - ///todo should we simply not allow a gp to ask for the material? Output cross section number for now. /JB - fprintf( file, " Cross section num %d", gp->giveElement()->giveCrossSection()->giveNumber() ); fprintf(file, "}\n"); } @@ -649,24 +637,13 @@ void CompoDamageMatStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType CompoDamageMatStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj = NULL) +void CompoDamageMatStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + StructuralMaterialStatus :: saveContext(stream, mode); } -contextIOResultType CompoDamageMatStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL) { - contextIOResultType iores; - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; +void CompoDamageMatStatus :: restoreContext(DataStream &stream, ContextMode mode) +{ + StructuralMaterialStatus :: restoreContext(stream, mode); } } // end namespace oofem diff --git a/src/sm/Materials/ConcreteMaterials/compodamagemat.h b/src/sm/Materials/ConcreteMaterials/compodamagemat.h index 5ac28aa30..a9dd20447 100644 --- a/src/sm/Materials/ConcreteMaterials/compodamagemat.h +++ b/src/sm/Materials/ConcreteMaterials/compodamagemat.h @@ -36,9 +36,9 @@ #define compodamagemat_h #include "material.h" -#include "Materials/linearelasticmaterial.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/linearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "intarray.h" #include "floatarray.h" #include "cltypes.h" @@ -68,15 +68,13 @@ class CompoDamageMatStatus : public StructuralMaterialStatus { public: /// Constructor - CompoDamageMatStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~CompoDamageMatStatus(); + CompoDamageMatStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); + void initTempStatus() override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; //tempVal are values used during iteration, Val are equilibrated values, updated after last iteration in previous time step @@ -96,7 +94,7 @@ class CompoDamageMatStatus : public StructuralMaterialStatus FloatArray omega; /// Iteration in the time step - int Iteration; + int Iteration = 0; /// Stress at which damage starts. For uniaxial loading is equal to given maximum stress in the input. The stress is linearly interpolated between increments at IP [6 tension, 6 compression] FloatArray initDamageStress; @@ -111,10 +109,10 @@ class CompoDamageMatStatus : public StructuralMaterialStatus /// Characteristic element length at IP in three perpendicular planes aligned with material orientation FloatArray elemCharLength; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual const char *giveClassName() const { return "CompoDamageMatStatus"; } + const char *giveClassName() const override { return "CompoDamageMatStatus"; } }; @@ -141,38 +139,41 @@ class CompoDamageMat : public StructuralMaterial public: /// Constructor CompoDamageMat(int n, Domain * d); - /// Destructor - virtual ~CompoDamageMat(); - virtual const char *giveClassName() const { return "CompositeDamageMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_CompoDamageMat_Name; } + const char *giveClassName() const override { return "CompositeDamageMaterial"; } + const char *giveInputRecordName() const override { return _IFT_CompoDamageMat_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new CompoDamageMatStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new CompoDamageMatStatus(gp); } - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &, TimeStep *tStep) override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; /** * Optional parameter determining after how many iterations within the time step the damage is calculated. * This is important for stress evaluation which is unequilibrated in the beginning. * Variables strainAtMaxStress, initDamageStress, maxStrainAtZeroStress are evaluated afterIter. */ - int afterIter; + int afterIter = 0; protected: /** @@ -182,7 +183,7 @@ class CompoDamageMat : public StructuralMaterial * @param mode Material mode of stiffness matrix (elastic, secant). * @param gp Integration point. */ - void giveUnrotated3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp); + FloatMatrixF<6,6> giveUnrotated3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp) const; /** * Returns [6x6] rotation matrix in the global coordinate system. * The matrix relates local c.s. to global c.s. Local c.s. can be specified with 'mcs' flag defined on element. @@ -190,7 +191,7 @@ class CompoDamageMat : public StructuralMaterial * @param gp Integration point. * @return 0 if no lcs is defined on element, 1 if defined. */ - int giveMatStiffRotationMatrix(FloatMatrix &answer, GaussPoint *gp); + int giveMatStiffRotationMatrix(FloatMatrixF<6,6> &answer, GaussPoint *gp) const; /// Six stress components of tension components read from the input file. FloatArray inputTension; diff --git a/src/sm/Materials/ConcreteMaterials/concrete2.C b/src/sm/Materials/ConcreteMaterials/concrete2.C index 8068806bb..522203551 100644 --- a/src/sm/Materials/ConcreteMaterials/concrete2.C +++ b/src/sm/Materials/ConcreteMaterials/concrete2.C @@ -45,21 +45,15 @@ namespace oofem { REGISTER_Material(Concrete2); -Concrete2 :: Concrete2(int n, Domain *d) : DeformationTheoryMaterial(n, d) -{ - linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); -} - +Concrete2 :: Concrete2(int n, Domain *d) : DeformationTheoryMaterial(n, d), + linearElasticMaterial(n, d) +{ } -Concrete2 :: ~Concrete2() -{ - delete linearElasticMaterial; -} -IRResultType -Concrete2 :: initializeFrom(InputRecord *ir) +void +Concrete2 :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Material :: initializeFrom(ir); IR_GIVE_FIELD(ir, E, _IFT_Concrete2_e); IR_GIVE_FIELD(ir, n, _IFT_Concrete2_n); @@ -81,21 +75,15 @@ Concrete2 :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, stirrEREF, _IFT_Concrete2_stirr_eref); IR_GIVE_FIELD(ir, stirrLAMBDA, _IFT_Concrete2_stirr_lambda); - result = this->linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - return Material :: initializeFrom(ir); + this->linearElasticMaterial.initializeFrom(ir); } double -Concrete2 :: give(int aProperty, GaussPoint *gp) +Concrete2 :: give(int aProperty, GaussPoint *gp) const // Returns the value of the property aProperty (e.g. the Young's modulus // 'E') of the receiver. { - double value; - switch ( aProperty ) { case c2_SCCC: return this->SCCC; @@ -150,21 +138,18 @@ Concrete2 :: give(int aProperty, GaussPoint *gp) default: if ( propertyDictionary.includes(aProperty) ) { - value = propertyDictionary.at(aProperty); - return value; + return propertyDictionary.at(aProperty); } else { - return this->linearElasticMaterial->give(aProperty, gp); + return this->linearElasticMaterial.give(aProperty, gp); // error ("give: property not defined"); } } } -void -Concrete2 :: giveRealStressVector_PlateLayer(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) +FloatArrayF<5> +Concrete2 :: giveRealStressVector_PlateLayer(const FloatArrayF<5> &totalStrain, + GaussPoint *gp, TimeStep *tStep) const // // returns total stress vector of receiver according to // previous level of stress and current @@ -324,8 +309,9 @@ Concrete2 :: giveRealStressVector_PlateLayer(FloatArray &answer, // plasticStrain->negated()->add (status->givePlasticStrainVector()); // status->givePlasticStrainIncrementVector()-> add(plasticStrain); + FloatArray answer; StructuralMaterial :: giveReducedSymVectorForm( answer, currentStress, gp->giveMaterialMode() ); - return; + return answer; } // @@ -646,13 +632,15 @@ label18: //plasticStrain->negated()->add (status->givePlasticStrainVector()); //status->givePlasticStrainIncrementVector()-> add(plasticStrain); + FloatArray answer; StructuralMaterial :: giveFullSymVectorForm( answer, currentStress, gp->giveMaterialMode() ); + return answer; } void Concrete2 :: dtp3(GaussPoint *gp, FloatArray &e, FloatArray &s, FloatArray &ep, - double SCC, double SCT, int *ifplas) + double SCC, double SCT, int *ifplas) const // // DEFORMATION THEORY OF PLASTICITY, PRNCIPAL STRESSES // CONDITION OF PLASTICITY. @@ -855,7 +843,7 @@ Concrete2 :: dtp3(GaussPoint *gp, FloatArray &e, FloatArray &s, FloatArray &ep, void Concrete2 :: dtp2(GaussPoint *gp, FloatArray &e, FloatArray &s, FloatArray &ep, - double SCC, double SCT, int *ifplas) + double SCC, double SCT, int *ifplas) const // // DEFORMATION THEORY OF PLASTICITY, PRNCIPAL STRESSES // CONDITION OF PLASTICITY. - PLANE STRESS @@ -1003,7 +991,7 @@ Concrete2 :: dtp2(GaussPoint *gp, FloatArray &e, FloatArray &s, FloatArray &ep, void Concrete2 :: strsoft(GaussPoint *gp, double epsult, FloatArray &ep, double &ep1, double &ep2, double &ep3, - double SCC, double SCT, int &ifupd) + double SCC, double SCT, int &ifupd) const // material constant of concrete // stored in this.propertyDictionary // @@ -1168,7 +1156,7 @@ label14: void -Concrete2 :: updateStirrups(GaussPoint *gp, FloatArray &strainIncrement, TimeStep *tStep) +Concrete2 :: updateStirrups(GaussPoint *gp, FloatArray &strainIncrement, TimeStep *tStep) const // stirr (double dez, double srf) // // @@ -1227,11 +1215,10 @@ Concrete2 :: updateStirrups(GaussPoint *gp, FloatArray &strainIncrement, TimeSte -void -Concrete2 :: givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode rMode, +FloatMatrixF<5,5> +Concrete2 :: givePlateLayerStiffMtrx(MatResponseMode rMode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // This material is currently unable compute material stiffness // so it uses slave material (linearElasticMaterial ) to perform this work @@ -1240,53 +1227,28 @@ Concrete2 :: givePlateLayerStiffMtrx(FloatMatrix &answer, // { // error ("givePlateLayerStiffMtrx: unable to compute"); - linearElasticMaterial->givePlateLayerStiffMtrx(answer, rMode, gp, tStep); + return linearElasticMaterial.givePlateLayerStiffMtrx( rMode, gp, tStep); } MaterialStatus * Concrete2 :: CreateStatus(GaussPoint *gp) const -/* - * creates new material status corresponding to this class - */ { - Concrete2MaterialStatus *status; - - status = new Concrete2MaterialStatus(1, this->giveDomain(), gp); - return status; + return new Concrete2MaterialStatus(gp); } -Concrete2MaterialStatus :: Concrete2MaterialStatus(int n, Domain *d, GaussPoint *g) : - StructuralMaterialStatus(n, d, g), plasticStrainVector(), plasticStrainIncrementVector() - // - // constructor - // +Concrete2MaterialStatus :: Concrete2MaterialStatus(GaussPoint *g) : + StructuralMaterialStatus(g) { - SCCM = EPM = E0PM = SRF = SEZ = 0.0; - SCTM = -1.0; // init status if SCTM < 0.; } - -Concrete2MaterialStatus :: ~Concrete2MaterialStatus() -// -// DEstructor -// -{ } - -contextIOResultType -Concrete2MaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// +void +Concrete2MaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: saveContext(stream, mode); // write a raw data if ( !stream.write(SCCM) ) { @@ -1313,26 +1275,19 @@ Concrete2MaterialStatus :: saveContext(DataStream &stream, ContextMode mode, voi THROW_CIOERR(CIO_IOERR); } + contextIOResultType iores; if ( ( iores = plasticStrainVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - // return result back - return CIO_OK; } -contextIOResultType -Concrete2MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restore state variables from stream -// +void +Concrete2MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { contextIOResultType iores; - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: restoreContext(stream, mode); // read raw data if ( !stream.read(SCCM) ) { @@ -1362,13 +1317,9 @@ Concrete2MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, if ( ( iores = plasticStrainVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - // return result back - return CIO_OK; } - void Concrete2MaterialStatus :: initTempStatus() // diff --git a/src/sm/Materials/ConcreteMaterials/concrete2.h b/src/sm/Materials/ConcreteMaterials/concrete2.h index 603522935..feb773bfe 100644 --- a/src/sm/Materials/ConcreteMaterials/concrete2.h +++ b/src/sm/Materials/ConcreteMaterials/concrete2.h @@ -38,10 +38,10 @@ #include "femcmpnn.h" #include "dictionary.h" #include "material.h" -#include "Materials/deformationtheorymaterial.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/deformationtheorymaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "floatarray.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" ///@name Input fields for Concrete2 //@{ @@ -93,19 +93,19 @@ class Concrete2MaterialStatus : public StructuralMaterialStatus FloatArray plasticStrainVector; // full form FloatArray plasticStrainIncrementVector; - double tempSCCM, tempEPM, tempSCTM, tempE0PM, tempSRF, tempSEZ; + double tempSCCM = 0., tempEPM = 0., tempSCTM = 0., tempE0PM = 0., tempSRF = 0., tempSEZ = 0.; - double SCCM; ///< Current pressure strength. - double EPM; ///< Max. eff. plastic strain. - double SCTM; ///< Current tension strength. - double E0PM; ///< Max. vol. plastic strain. - double SRF; ///< current stress in stirrups. - double SEZ; ///< Current strain in transverse (z) direction. + double SCCM = 0.; ///< Current pressure strength. + double EPM = 0.; ///< Max. eff. plastic strain. + double SCTM = -1.; ///< Current tension strength. + double E0PM = 0.; ///< Max. vol. plastic strain. + double SRF = 0.; ///< current stress in stirrups. + double SEZ = 0.; ///< Current strain in transverse (z) direction. public: - Concrete2MaterialStatus(int n, Domain * d, GaussPoint * g); - virtual ~Concrete2MaterialStatus(); - virtual void printOutputAt(FILE *file, TimeStep *tStep) + Concrete2MaterialStatus(GaussPoint * g); + + void printOutputAt(FILE *file, TimeStep *tStep) const override { StructuralMaterialStatus :: printOutputAt(file, tStep); } const FloatArray & givePlasticStrainVector() const { return plasticStrainVector; } @@ -132,15 +132,13 @@ class Concrete2MaterialStatus : public StructuralMaterialStatus double &giveMaxVolPlasticStrain() { return E0PM; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - // saves current context(state) into stream - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - // definition - virtual const char *giveClassName() const { return "Concrete2MaterialStatus"; } + const char *giveClassName() const override { return "Concrete2MaterialStatus"; } }; @@ -152,66 +150,58 @@ class Concrete2MaterialStatus : public StructuralMaterialStatus class Concrete2 : public DeformationTheoryMaterial { private: - double SCCC; ///< Pressure strength. - double SCCT; ///< Tension strength. - double EPP; ///< Threshold eff. plastic strain for softening in compress. - double EPU; ///< Ultimate eff. pl. strain. - double EOPP; ///< Threshold volumetric plastic strain for soft. in tension. - double EOPU; ///< Ultimate vol. pl. strain. + double SCCC = 0.; ///< Pressure strength. + double SCCT = 0.; ///< Tension strength. + double EPP = 0.; ///< Threshold eff. plastic strain for softening in compress. + double EPU = 0.; ///< Ultimate eff. pl. strain. + double EOPP = 0.; ///< Threshold volumetric plastic strain for soft. in tension. + double EOPU = 0.; ///< Ultimate vol. pl. strain. /** * Threshold value of the relative shear deformation * (psi^2/eef) at which shear is considered in layers. for * lower r.s.d. the transverse shear remains elastic decoupled * from bending. default value SHEARTOL = 0.01 */ - double SHEARTOL; + double SHEARTOL = 0.; - double E, n; + double E = 0., n = 0.; // stirrups - double stirrE, stirrFt, stirrA, stirrTOL, stirrEREF, stirrLAMBDA; + double stirrE = 0., stirrFt = 0., stirrA = 0., stirrTOL = 0., stirrEREF = 0., stirrLAMBDA = 0.; /// Indicates that plastic flow (not deformation theory) is used in pressure. - int IS_PLASTIC_FLOW; + int IS_PLASTIC_FLOW = 0; /// Determines if state variables should be updated or not (>0 updates). - int IFAD; + int IFAD = 0; - LinearElasticMaterial *linearElasticMaterial; + IsotropicLinearElasticMaterial linearElasticMaterial; public: Concrete2(int n, Domain * d); - virtual ~Concrete2(); - virtual void giveRealStressVector_PlateLayer(FloatArray &answer, GaussPoint *gp, - const FloatArray &, TimeStep *tStep); + FloatArrayF<5> giveRealStressVector_PlateLayer(const FloatArrayF<5> &strain, GaussPoint *gp,TimeStep *tStep) const override; + + FloatMatrixF<5,5> givePlateLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual void givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + double give(int, GaussPoint *gp) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + const char *giveClassName() const override { return "Concrete2"; } + const char *giveInputRecordName() const override { return _IFT_Concrete2_Name; } + void initializeFrom(InputRecord &ir) override; protected: void dtp3(GaussPoint *gp, FloatArray &e, FloatArray &s, FloatArray &ep, - double SCC, double SCT, int *ifplas); + double SCC, double SCT, int *ifplas) const; void dtp2(GaussPoint *gp, FloatArray &e, FloatArray &s, FloatArray &ep, - double SCC, double SCT, int *ifplas); - void stirr(double dez, double srf); + double SCC, double SCT, int *ifplas) const; + void stirr(double dez, double srf) const; void strsoft(GaussPoint *gp, double epsult, FloatArray &ep, double &ep1, - double &ep2, double &ep3, double SCC, double SCT, int &ifupd); + double &ep2, double &ep3, double SCC, double SCT, int &ifupd) const; // two functions used to initialize and updating temporary variables in // gp's status. These variables are used to control process, when // we try to find equilibrium state. - void updateStirrups(GaussPoint *gp, FloatArray &strainIncrement, TimeStep *tStep); - -public: - virtual double give(int, GaussPoint *gp); - - // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 1; } - virtual const char *giveClassName() const { return "Concrete2"; } - virtual const char *giveInputRecordName() const { return _IFT_Concrete2_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + void updateStirrups(GaussPoint *gp, FloatArray &strainIncrement, TimeStep *tStep) const; }; } // end namespace oofem #endif // concrete2_h diff --git a/src/sm/Materials/ConcreteMaterials/concrete3.C b/src/sm/Materials/ConcreteMaterials/concrete3.C index ca75b7c2a..a172b7ecd 100644 --- a/src/sm/Materials/ConcreteMaterials/concrete3.C +++ b/src/sm/Materials/ConcreteMaterials/concrete3.C @@ -10,7 +10,7 @@ * * OOFEM : Object Oriented Finite Element Code * - * Copyright (C) 1993 - 2013 Borek Patzak + * Copyright (C) 1993 - 2021 Borek Patzak * * * @@ -53,8 +53,7 @@ Concrete3 :: CreateStatus(GaussPoint *gp) const */ { // double Ee, Gf, Et, Etp, Ft, Le, minEffStrainForFullyOpenCrack; - RCM2MaterialStatus *status = static_cast< RCM2MaterialStatus * >( RCM2Material :: CreateStatus(gp) ); - return status; + return RCM2Material :: CreateStatus(gp); } @@ -138,9 +137,17 @@ Concrete3 :: giveMinCrackStrainsForFullyOpenCrack(GaussPoint *gp, int i) Ft = this->computeStrength(gp, Le); return 2.0 * Gf / ( Le * Ft ); - } else { + } else if ( softeningMode == exponentialSoftening ) { //return Gf/(Le*Ft); // Exponential softening return 1.e6; // Exponential softening + } else { + RCM2MaterialStatus *status = static_cast< RCM2MaterialStatus * >( this->giveStatus(gp) ); + double Le, Gf, Ft; + + Le = status->giveCharLength(i); + Gf = this->give(pscm_Gf, gp); + Ft = this->computeStrength(gp, Le); + return 5.136* Gf/(Le*Ft); // Hordijk softening } } @@ -248,6 +255,7 @@ Concrete3 :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, { //double Ee, Gf; double Cf, Gf, Ft, Le, ef, minEffStrainForFullyOpenCrack; + double emax, c1 {3.}, c2 {6.93}; RCM2MaterialStatus *status = static_cast< RCM2MaterialStatus * >( this->giveStatus(gp) ); // @@ -259,6 +267,7 @@ Concrete3 :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, Gf = this->give(pscm_Gf, gp); Ft = this->give(pscm_Ft, gp); ///@todo This isn't used. Is it right?! / Micke Le = status->giveCharLength(i); + emax = status->giveTempMaxCrackStrain(i); Ft = this->computeStrength(gp, Le); minEffStrainForFullyOpenCrack = this->giveMinCrackStrainsForFullyOpenCrack(gp, i); @@ -267,25 +276,37 @@ Concrete3 :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, if ( this->checkSizeLimit(gp, Le) ) { if ( softeningMode == linearSoftening ) { if ( ( crackStrain >= minEffStrainForFullyOpenCrack ) || - ( status->giveTempMaxCrackStrain(i) >= minEffStrainForFullyOpenCrack ) ) { + ( emax >= minEffStrainForFullyOpenCrack ) ) { // fully open crack - no stiffness Cf = 0.; - } else if ( crackStrain >= status->giveTempMaxCrackStrain(i) ) { + } else if ( crackStrain >= emax ) { // further softening Cf = -Ft / minEffStrainForFullyOpenCrack; } else { // unloading or reloading regime - Cf = Ft * ( minEffStrainForFullyOpenCrack - status->giveTempMaxCrackStrain(i) ) / - ( status->giveTempMaxCrackStrain(i) * minEffStrainForFullyOpenCrack ); + Cf = Ft * ( minEffStrainForFullyOpenCrack - emax ) / + ( emax * minEffStrainForFullyOpenCrack ); } - } else { // exponential softening + } else if ( softeningMode == exponentialSoftening ) { // exponential softening ef = Gf / ( Le * Ft ); - if ( crackStrain >= status->giveTempMaxCrackStrain(i) ) { + if ( crackStrain >= emax ) { // further softening Cf = -Ft / ef *exp(-crackStrain / ef); } else { // unloading or reloading regime - Cf = Ft / status->giveTempMaxCrackStrain(i) * exp(-status->giveTempMaxCrackStrain(i) / ef); + Cf = Ft / emax * exp(-emax / ef); + } + } else { //Hodrijk softening + ef = 5.136 * Gf / ( Le * Ft ); + if ( (crackStrain >= ef) || (emax >= ef) ) { + Cf = 0; + } else if ( crackStrain >= emax ) { + //further softening - negative stiffness + //this is derivative of the stress wrt to strain in the softening region + Cf = Ft * ( ( 3. * c1 * c1 * c1 * crackStrain * crackStrain * exp(-( c2 * crackStrain ) / ef) ) / ( ef * ef * ef ) - ( c2 * exp(-( c2 * crackStrain ) / ef) * ( c1 * c1 * c1 * crackStrain * crackStrain * crackStrain + ef * ef * ef ) ) / ( ef * ef * ef * ef ) - ( exp(-c2) * ( c1 * c1 * c1 + 1. ) ) / ef ); + } else { + // unloading or reloading regime + Cf = Ft / emax * ( ( 1. + pow( ( c1 * emax / ef ), 3. ) ) * exp(-c2 * emax / ef) - emax / ef * ( 1. + c1 * c1 * c1 ) * exp(-c2) ); } } } else { @@ -295,17 +316,20 @@ Concrete3 :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, if ( this->checkSizeLimit(gp, Le) ) { if ( softeningMode == linearSoftening ) { if ( ( crackStrain >= minEffStrainForFullyOpenCrack ) || - ( status->giveTempMaxCrackStrain(i) >= minEffStrainForFullyOpenCrack ) ) { + ( emax >= minEffStrainForFullyOpenCrack ) ) { // fully open crack - no stiffness Cf = 0.; } else { // unloading or reloading regime - Cf = Ft * ( minEffStrainForFullyOpenCrack - status->giveTempMaxCrackStrain(i) ) / - ( status->giveTempMaxCrackStrain(i) * minEffStrainForFullyOpenCrack ); + Cf = Ft * ( minEffStrainForFullyOpenCrack - emax ) / + ( emax * minEffStrainForFullyOpenCrack ); } - } else { // exponential softening + } else if ( softeningMode == exponentialSoftening ) { // exponential softening ef = Gf / ( Le * Ft ); - Cf = Ft / status->giveTempMaxCrackStrain(i) * exp(-status->giveTempMaxCrackStrain(i) / ef); + Cf = Ft / emax * exp(-emax / ef); + } else { // Hordijk softening + ef = 5.136 * Gf / ( Le * Ft ); + Cf = Ft / emax * ( ( 1. + pow( ( c1 * emax / ef ), 3. ) ) * exp(-c2 * emax / ef) - emax / ef * ( 1. + c1 * c1 * c1 ) * exp(-c2) ); } } else { Cf = 0.; @@ -364,7 +388,7 @@ Concrete3 :: giveNormalCrackingStress(GaussPoint *gp, double crackStrain, int i) // returns receivers Normal Stress in crack i for given cracking strain // { - double Cf, Ft, Gf, Le, answer, ef, minEffStrainForFullyOpenCrack; + double Cf, Ft, Gf, Le, answer, ef, minEffStrainForFullyOpenCrack, c1 {3.}, c2 {6.93}, emax; RCM2MaterialStatus *status = static_cast< RCM2MaterialStatus * >( this->giveStatus(gp) ); minEffStrainForFullyOpenCrack = this->giveMinCrackStrainsForFullyOpenCrack(gp, i); @@ -372,14 +396,15 @@ Concrete3 :: giveNormalCrackingStress(GaussPoint *gp, double crackStrain, int i) Le = status->giveCharLength(i); Ft = this->computeStrength(gp, Le); Gf = this->give(pscm_Gf, gp); + emax = status->giveTempMaxCrackStrain(i); if ( this->checkSizeLimit(gp, Le) ) { if ( softeningMode == linearSoftening ) { if ( ( crackStrain >= minEffStrainForFullyOpenCrack ) || - ( status->giveTempMaxCrackStrain(i) >= minEffStrainForFullyOpenCrack ) ) { + ( emax >= minEffStrainForFullyOpenCrack ) ) { // fully open crack - no stiffness answer = 0.; - } else if ( crackStrain >= status->giveTempMaxCrackStrain(i) ) { + } else if ( crackStrain >= emax ) { // further softening answer = Ft + Cf * crackStrain; } else if ( crackStrain <= 0. ) { @@ -389,19 +414,35 @@ Concrete3 :: giveNormalCrackingStress(GaussPoint *gp, double crackStrain, int i) } else { // unloading or reloading regime answer = crackStrain * Ft * - ( minEffStrainForFullyOpenCrack - status->giveTempMaxCrackStrain(i) ) / - ( status->giveTempMaxCrackStrain(i) * minEffStrainForFullyOpenCrack ); + ( minEffStrainForFullyOpenCrack - emax ) / + ( emax * minEffStrainForFullyOpenCrack ); } - } else { // Exponential softening + } else if ( softeningMode == linearSoftening ) { // Exponential softening ef = Gf / ( Le * Ft ); - if ( crackStrain >= status->giveTempMaxCrackStrain(i) ) { + if ( crackStrain >= emax ) { // further softening answer = Ft * exp(-crackStrain / ef); } else { // crack closing // or unloading or reloading regime - answer = Ft * crackStrain / status->giveTempMaxCrackStrain(i) * - exp(-status->giveTempMaxCrackStrain(i) / ef); + answer = Ft * crackStrain / emax * + exp(-emax / ef); + } + } else { // Hordijk softening + ef = 5.136 * Gf / ( Le * Ft ); + if ( (crackStrain >= ef) || (emax >= ef) ) { + //fully open crack - no stiffness + answer = 0; + } else if ( crackStrain >= emax ) { + // further softening + answer = Ft * ( ( 1. + pow( ( c1 * crackStrain / ef ), 3. ) ) * exp(-c2 * crackStrain / ef) - crackStrain / ef * ( 1. + c1 * c1 * c1 ) * exp(-c2) ); + } else if ( crackStrain <= 0) { + answer = 0; + } + else { + // crack closing + // or unloading or reloading regime + answer = Ft * crackStrain / emax * ( ( 1. + pow( ( c1 * emax / ef ), 3. ) ) * exp(-c2 * emax / ef) - emax / ef * ( 1. + c1 * c1 * c1 ) * exp(-c2) ); } } } else { @@ -436,19 +477,19 @@ Concrete3 :: giveNormalCrackingStress(GaussPoint *gp, double crackStrain, int i) */ -IRResultType -Concrete3 :: initializeFrom(InputRecord *ir) +void +Concrete3 :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + RCM2Material :: initializeFrom(ir); int exmode = 0; IR_GIVE_OPTIONAL_FIELD(ir, exmode, _IFT_Concrete3_exp_soft); - if ( exmode ) { + if ( exmode == 1 ) { softeningMode = exponentialSoftening; + } else if ( exmode == 2){ + softeningMode = hordijkSoftening; } else { softeningMode = linearSoftening; } - - return RCM2Material :: initializeFrom(ir); } } // end namespace oofem diff --git a/src/sm/Materials/ConcreteMaterials/concrete3.h b/src/sm/Materials/ConcreteMaterials/concrete3.h index 1171709f2..84edc65f6 100644 --- a/src/sm/Materials/ConcreteMaterials/concrete3.h +++ b/src/sm/Materials/ConcreteMaterials/concrete3.h @@ -10,7 +10,7 @@ * * OOFEM : Object Oriented Finite Element Code * - * Copyright (C) 1993 - 2013 Borek Patzak + * Copyright (C) 1993 - 2021 Borek Patzak * * * @@ -35,8 +35,8 @@ #ifndef concrete3_h #define concrete3_h -#include "Materials/rcm2.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/rcm2.h" +#include "sm/Materials/isolinearelasticmaterial.h" ///@name Input fields for Concrete3 //@{ @@ -55,11 +55,11 @@ namespace oofem { */ class Concrete3 : public RCM2Material { - enum Concrete3_softeningMode { linearSoftening, exponentialSoftening }; + enum Concrete3_softeningMode { linearSoftening, exponentialSoftening, hordijkSoftening }; private: //double shearRetFactor; // shearRetentionFactor - Concrete3_softeningMode softeningMode; + Concrete3_softeningMode softeningMode = linearSoftening; public: Concrete3(int n, Domain * d); @@ -67,23 +67,21 @@ class Concrete3 : public RCM2Material delete linearElasticMaterial; } - // identification and auxiliary functions - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int hasNonLinearBehaviour() { return 1; } - virtual const char *giveClassName() const { return "Concrete3"; } - virtual const char *giveInputRecordName() const { return _IFT_Concrete3_Name; } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "Concrete3"; } + const char *giveInputRecordName() const override { return _IFT_Concrete3_Name; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: - virtual double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, - double crackStrain, int i); - //virtual double giveShearRetentionFactor(GaussPoint* gp, double eps_cr, int i); - virtual double giveNormalCrackingStress(GaussPoint *gp, double eps_cr, int i); - virtual double giveMinCrackStrainsForFullyOpenCrack(GaussPoint *gp, int i); - //virtual void updateStatusForNewCrack( GaussPoint*, int, double); - virtual double computeStrength(GaussPoint *, double); - virtual int checkSizeLimit(GaussPoint *gp, double); + double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, + double crackStrain, int i) override; + //double giveShearRetentionFactor(GaussPoint* gp, double eps_cr, int i) override; + double giveNormalCrackingStress(GaussPoint *gp, double eps_cr, int i) override; + double giveMinCrackStrainsForFullyOpenCrack(GaussPoint *gp, int i) override; + //void updateStatusForNewCrack( GaussPoint*, int, double) override; + double computeStrength(GaussPoint *, double) override; + int checkSizeLimit(GaussPoint *gp, double) override; }; } // end namespace oofem #endif // concrete3_h diff --git a/src/sm/Materials/ConcreteMaterials/concretedpm.C b/src/sm/Materials/ConcreteMaterials/concretedpm.C index 63c6ee414..dbc543cc5 100644 --- a/src/sm/Materials/ConcreteMaterials/concretedpm.C +++ b/src/sm/Materials/ConcreteMaterials/concretedpm.C @@ -35,70 +35,56 @@ #include "concretedpm.h" #include "floatarray.h" #include "floatmatrix.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "gausspoint.h" #include "intarray.h" #include "mathfem.h" #include "datastream.h" #include "contextioerr.h" -#include "../sm/Materials/structuralmaterial.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "classfactory.h" namespace oofem { REGISTER_Material(ConcreteDPM); ///@todo Eventually remove this old input string (replacing the name in input files is easy anyway). -static bool __dummy_ConcreteDPM_alt __attribute__((unused)) = GiveClassFactory().registerMaterial("concreteidp", matCreator< ConcreteDPM > ); +//static bool __dummy_ConcreteDPM_alt __attribute__((unused)) = GiveClassFactory().registerMaterial("concreteidp", matCreator< ConcreteDPM > ); +REGISTER_Material_Alt(ConcreteDPM, concreteidp); -ConcreteDPMStatus :: ConcreteDPMStatus(int n, Domain *d, GaussPoint *gp) : - StructuralMaterialStatus(n, d, gp), - plasticStrain(6), - tempPlasticStrain(6) +ConcreteDPMStatus::ConcreteDPMStatus(GaussPoint *gp) : + StructuralMaterialStatus(gp) { strainVector.resize(6); stressVector.resize(6); tempStressVector = stressVector; tempStrainVector = strainVector; - - kappaP = tempKappaP = 0.; - kappaD = tempKappaD = 0.; - damage = tempDamage = 0.; - equivStrain = tempEquivStrain = 0.; - deltaLambda = 0.; - state_flag = temp_state_flag = ConcreteDPMStatus :: ConcreteDPM_Elastic; -#ifdef SOPHISTICATED_SIZEDEPENDENT_ADJUSTMENT - epsloc = -1.; // negative value means that it has not been set yet - tempEpsloc = -1.0; -#endif - le = 0.; } -ConcreteDPMStatus :: ~ConcreteDPMStatus() -{ } void -ConcreteDPMStatus :: initTempStatus() +ConcreteDPMStatus::initTempStatus() { // Call the function of the parent class to initialize the variables defined there. - StructuralMaterialStatus :: initTempStatus(); + StructuralMaterialStatus::initTempStatus(); tempPlasticStrain = plasticStrain; tempKappaP = kappaP; tempKappaD = kappaD; tempDamage = damage; tempEquivStrain = equivStrain; temp_state_flag = state_flag; + tempVertexType = vertexType; tempEpsloc = epsloc; } void -ConcreteDPMStatus :: updateYourself(TimeStep *tStep) +ConcreteDPMStatus::updateYourself(TimeStep *tStep) { #ifdef SOPHISTICATED_SIZEDEPENDENT_ADJUSTMENT epsloc = tempEpsloc; #endif // Call corresponding function of the parent class to update // variables defined there. - StructuralMaterialStatus :: updateYourself(tStep); + StructuralMaterialStatus::updateYourself(tStep); // update variables defined in ConcreteDPMStatus plasticStrain = tempPlasticStrain; @@ -107,56 +93,58 @@ ConcreteDPMStatus :: updateYourself(TimeStep *tStep) damage = tempDamage; equivStrain = tempEquivStrain; state_flag = temp_state_flag; + vertexType = tempVertexType; epsloc = tempEpsloc; } void -ConcreteDPMStatus :: printOutputAt(FILE *file, TimeStep *tStep) +ConcreteDPMStatus::printOutputAt(FILE *file, TimeStep *tStep) const { // Call corresponding function of the parent class to print // variables defined there. - StructuralMaterialStatus :: printOutputAt(file, tStep); + StructuralMaterialStatus::printOutputAt(file, tStep); fprintf(file, "\tstatus { "); // print status flag switch ( state_flag ) { - case ConcreteDPMStatus :: ConcreteDPM_Elastic: + case ConcreteDPMStatus::ConcreteDPM_Elastic: fprintf(file, "statusflag 0 (Elastic),"); break; - case ConcreteDPMStatus :: ConcreteDPM_Unloading: + case ConcreteDPMStatus::ConcreteDPM_Unloading: fprintf(file, "statusflag 1 (Unloading),"); break; - case ConcreteDPMStatus :: ConcreteDPM_Plastic: + case ConcreteDPMStatus::ConcreteDPM_Plastic: fprintf(file, "statusflag 2 (Plastic),"); break; - case ConcreteDPMStatus :: ConcreteDPM_Damage: + case ConcreteDPMStatus::ConcreteDPM_Damage: fprintf(file, "statusflag 3 (Damage),"); break; - case ConcreteDPMStatus :: ConcreteDPM_PlasticDamage: + case ConcreteDPMStatus::ConcreteDPM_PlasticDamage: fprintf(file, "statusflag 4 (PlasticDamage),"); break; - case ConcreteDPMStatus :: ConcreteDPM_VertexCompression: + case ConcreteDPMStatus::ConcreteDPM_VertexCompression: fprintf(file, "statusflag 5 (VertexCompression),"); break; - case ConcreteDPMStatus :: ConcreteDPM_VertexTension: + case ConcreteDPMStatus::ConcreteDPM_VertexTension: fprintf(file, "statusflag 6 (VertexTension),"); break; - case ConcreteDPMStatus :: ConcreteDPM_VertexCompressionDamage: + case ConcreteDPMStatus::ConcreteDPM_VertexCompressionDamage: fprintf(file, "statusflag 7 (VertexCompressionDamage),"); break; - case ConcreteDPMStatus :: ConcreteDPM_VertexTensionDamage: + case ConcreteDPMStatus::ConcreteDPM_VertexTensionDamage: fprintf(file, "statusflag 8 (VertexTensionDamage),"); break; } #if 0 - // print plastic strain vector - FloatArray plasticStrainVector(); - giveFullPlasticStrainVector(plasticStrainVector); - fprintf(file,"plastic strains "); - for ( auto &val : plasticStrainVector ) - fprintf(file," %.4e", val); + // print plastic strain vector + FloatArray plasticStrainVector(); + giveFullPlasticStrainVector(plasticStrainVector); + fprintf(file, "plastic strains "); + for ( auto &val : plasticStrainVector ) { + fprintf(file, " %.4e", val); + } #endif // print hardening/softening parameters and damage @@ -170,25 +158,31 @@ ConcreteDPMStatus :: printOutputAt(FILE *file, TimeStep *tStep) fprintf(file, "}\n"); } -contextIOResultType -ConcreteDPMStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +ConcreteDPMStatus::saveContext(DataStream &stream, ContextMode mode) { + StructuralMaterialStatus::saveContext(stream, mode); + contextIOResultType iores; - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { + if ( ( iores = plasticStrain.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - // write raw data - - if ( ( iores = plasticStrain.storeYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); + if ( !stream.write(tempVolumetricPlasticStrain) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(dFDKappa) ) { + THROW_CIOERR(CIO_IOERR); } + if ( !stream.write(kappaP) ) { THROW_CIOERR(CIO_IOERR); } + if ( !stream.write(le) ) { + THROW_CIOERR(CIO_IOERR); + } if ( !stream.write(kappaD) ) { THROW_CIOERR(CIO_IOERR); @@ -201,41 +195,52 @@ ConcreteDPMStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj if ( !stream.write(damage) ) { THROW_CIOERR(CIO_IOERR); } + if ( !stream.write(deltaEquivStrain) ) { + THROW_CIOERR(CIO_IOERR); + } if ( !stream.write(state_flag) ) { THROW_CIOERR(CIO_IOERR); } - if ( !stream.write(deltaEquivStrain) ) { + if ( !stream.write(vertexType) ) { THROW_CIOERR(CIO_IOERR); } - - if ( !stream.write(le) ) { + + #ifdef SOPHISTICATED_SIZEDEPENDENT_ADJUSTMENT + if ( !stream.write(epsloc) ) { THROW_CIOERR(CIO_IOERR); } + #endif + - return CIO_OK; } -contextIOResultType -ConcreteDPMStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +ConcreteDPMStatus::restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralMaterialStatus::restoreContext(stream, mode); - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { + contextIOResultType iores; + if ( ( iores = plasticStrain.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - // read raw data - if ( ( iores = plasticStrain.restoreYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); + if ( !stream.read(tempVolumetricPlasticStrain) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(dFDKappa) ) { + THROW_CIOERR(CIO_IOERR); } + if ( !stream.read(kappaP) ) { THROW_CIOERR(CIO_IOERR); } + if ( !stream.read(le) ) { + THROW_CIOERR(CIO_IOERR); + } if ( !stream.read(kappaD) ) { THROW_CIOERR(CIO_IOERR); @@ -248,24 +253,28 @@ ConcreteDPMStatus :: restoreContext(DataStream &stream, ContextMode mode, void * if ( !stream.read(damage) ) { THROW_CIOERR(CIO_IOERR); } + if ( !stream.read(deltaEquivStrain) ) { + THROW_CIOERR(CIO_IOERR); + } if ( !stream.read(state_flag) ) { THROW_CIOERR(CIO_IOERR); } - if ( !stream.read(deltaEquivStrain) ) { + if ( !stream.read(vertexType) ) { THROW_CIOERR(CIO_IOERR); } - if ( !stream.read(le) ) { + #ifdef SOPHISTICATED_SIZEDEPENDENT_ADJUSTMENT + if ( !stream.read(epsloc) ) { THROW_CIOERR(CIO_IOERR); } + #endif - return CIO_OK; } int -ConcreteDPMStatus :: setIPValue(const FloatArray &value, InternalStateType type) +ConcreteDPMStatus::setIPValue(const FloatArray &value, InternalStateType type) { if ( type == IST_DamageScalar ) { damage = value.at(1); @@ -285,26 +294,6 @@ ConcreteDPMStatus :: setIPValue(const FloatArray &value, InternalStateType type) return 0; } -void -ConcreteDPMStatus :: restoreConsistency() -{ - ConcreteDPM *mat = static_cast< ConcreteDPM * >( gp->giveElement()->giveMaterial() ); - - // compute kappaD from damage - kappaD = mat->computeInverseDamage(damage, gp); - equivStrain = kappaD; - - // compute plastic strain - // such that the given stress is obtained at zero total strain and given damage - if ( damage < 1. ) { - FloatMatrix D; - FloatArray effectiveStress = stressVector; - effectiveStress.times( -1. / ( 1. - damage ) ); - mat->give3dMaterialStiffnessMatrix(D, ElasticStiffness, gp, NULL); - D.solveForRhs(effectiveStress, plasticStrain); - } -} - // ****************************************************** // *** CLASS CONCRETE DAMAGE-PLASTIC MATERIAL MODEL *** @@ -312,53 +301,28 @@ ConcreteDPMStatus :: restoreConsistency() //#define DPM_ITERATION_LIMIT 1.e-8 -ConcreteDPM :: ConcreteDPM(int n, Domain *d) : +ConcreteDPM::ConcreteDPM(int n, Domain *d) : StructuralMaterial(n, d), - effectiveStress(_Unknown) -{ - tempKappaP = kappaP = 0.; - tempKappaD = kappaD = 0.; - tempDamage = damage = 0.; - yieldTol = 0.; - newtonIter = 0; - helem = 0.; - linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); -#ifdef SOPHISTICATED_SIZEDEPENDENT_ADJUSTMENT - href = 0.; -#endif -} + linearElasticMaterial(n, d) +{} -ConcreteDPM :: ~ConcreteDPM() -{ - delete linearElasticMaterial; -} -IRResultType -ConcreteDPM :: initializeFrom(InputRecord *ir) +void +ConcreteDPM::initializeFrom(InputRecord &ir) { - // Required by IR_GIVE_FIELD macro - IRResultType result; - // call the corresponding service for the linear elastic material - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + StructuralMaterial::initializeFrom(ir); + linearElasticMaterial.initializeFrom(ir); - result = linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - double value; + // double value; // elastic parameters IR_GIVE_FIELD(ir, eM, _IFT_IsotropicLinearElasticMaterial_e); IR_GIVE_FIELD(ir, nu, _IFT_IsotropicLinearElasticMaterial_n); propertyDictionary.add('E', eM); propertyDictionary.add('n', nu); - IR_GIVE_FIELD(ir, value, _IFT_IsotropicLinearElasticMaterial_talpha); - propertyDictionary.add(tAlpha, value); + // IR_GIVE_FIELD(ir, value, _IFT_IsotropicLinearElasticMaterial_talpha); + // propertyDictionary.add(tAlpha, value); gM = eM / ( 2. * ( 1. + nu ) ); kM = eM / ( 3. * ( 1. - 2. * nu ) ); @@ -371,7 +335,7 @@ ConcreteDPM :: initializeFrom(InputRecord *ir) // damage parameters - only exponential softening // [in ef variable the wf (crack opening) is stored] - if ( ir->hasField(_IFT_ConcreteDPM_wf) ) { + if ( ir.hasField(_IFT_ConcreteDPM_wf) ) { IR_GIVE_FIELD(ir, ef, _IFT_ConcreteDPM_wf); // fracture energy } else { @@ -412,18 +376,13 @@ ConcreteDPM :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, yieldTol, _IFT_ConcreteDPM_yieldtol); newtonIter = 100; IR_GIVE_OPTIONAL_FIELD(ir, newtonIter, _IFT_ConcreteDPM_newtoniter); - - return IRRT_OK; } -void -ConcreteDPM :: giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &strainVector, - TimeStep *tStep) +FloatArrayF< 6 > +ConcreteDPM::giveRealStressVector_3d(const FloatArrayF< 6 > &totalStrain, GaussPoint *gp, + TimeStep *tStep) const { - FloatArray strain; - ConcreteDPMStatus *status = giveStatus(gp); + auto status = giveConcreteDPMStatus(gp); // Initialize temp variables for this gauss point status->initTempStatus(); @@ -431,69 +390,74 @@ ConcreteDPM :: giveRealStressVector_3d(FloatArray &answer, // subtract stress-independent part of strain // (due to temperature changes, shrinkage, etc.) - this->giveStressDependentPartOfStrainVector_3d(strain, gp, strainVector, tStep, VM_Total); + auto thermalStrain = this->computeStressIndependentStrainVector_3d(gp, tStep, VM_Total); + auto strain = totalStrain - thermalStrain; // perform plasticity return performPlasticityReturn(gp, strain); // compute damage - tempDamage = computeDamage(strain, gp, tStep); + //auto [tempDamage, tempKappaD] = computeDamage(strain, gp, tStep); // c++17 + auto tempDamKapD = computeDamage(strain, gp, tStep); // c++17 + auto tempDamage = tempDamKapD.first; + auto tempKappaD = tempDamKapD.second; // compute elastic strains and effective stress - FloatArray elasticStrain = strain; - FloatArray tempPlasticStrain = status->giveTempPlasticStrain(); - elasticStrain.subtract(tempPlasticStrain); - applyElasticStiffness(effectiveStress, elasticStrain, eM, nu); + const auto &tempPlasticStrain = status->giveTempPlasticStrain(); + auto elasticStrain = strain - tempPlasticStrain; + auto effectiveStress = applyElasticStiffness(elasticStrain, eM, nu); // compute the nominal stress - answer = effectiveStress; - - answer.times(1. - tempDamage); + auto stress = effectiveStress * ( 1. - tempDamage ); status->letTempKappaDBe(tempKappaD); status->letTempDamageBe(tempDamage); - status->letTempStrainVectorBe(strainVector); - status->letTempStressVectorBe(answer); + status->letTempStrainVectorBe(totalStrain); + status->letTempStressVectorBe(stress); assignStateFlag(gp); + #ifdef SOPHISTICATED_SIZEDEPENDENT_ADJUSTMENT // check whether the second-order work is negative // (must be done !!!before!!! the update of strain and stress) if ( status->giveEpsLoc() < 0. ) { - FloatArray strainIncrement, stressIncrement; - strainIncrement.beDifferenceOf( strainVector, status->giveStrainVector() ); - stressIncrement.beDifferenceOf( answer, status->giveStressVector() ); + auto strainIncrement = totalStrain - status->giveStrainVector(); + auto stressIncrement = stress - FloatArrayF< 6 >(status->giveStressVector() ); int n = strainIncrement.giveSize(); double work = strainIncrement.dotProduct(stressIncrement, n); //printf(" work : %g\n", work); if ( work < 0. ) { double E = this->give('E', gp); double ft = this->give(ft_strength, gp); - double tmpEpsloc = kappaD + damage * ft / E; + double tmpEpsloc = tempKappaD + tempDamage * ft / E; /// is this right? or was is supposed to use the old converged values? status->letTempEpslocBe(tmpEpsloc); } } #endif + return stress; } -double ConcreteDPM :: computeDamage(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +std::pair< double, double > +ConcreteDPM::computeDamage(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const { - ConcreteDPMStatus *status = giveStatus(gp); - double equivStrain; - computeEquivalentStrain(equivStrain, strain, gp, tStep); + auto status = giveConcreteDPMStatus(gp); + double equivStrain = computeEquivalentStrain(strain, gp, tStep); double f = equivStrain - status->giveKappaD(); if ( f <= 0.0 ) { // damage does not grow - tempKappaD = status->giveKappaD(); - tempDamage = status->giveDamage(); + double tempKappaD = status->giveKappaD(); + double tempDamage = status->giveDamage(); + return { + tempDamage, tempKappaD + }; } else { // damage grows - tempKappaD = equivStrain; + double tempKappaD = equivStrain; #ifdef SOPHISTICATED_SIZEDEPENDENT_ADJUSTMENT if ( ( href <= 0. ) || ( status->giveEpsLoc() >= 0. ) ) { // evaluate and store the effective element size (if not known yet) @@ -503,30 +467,31 @@ double ConcreteDPM :: computeDamage(const FloatArray &strain, GaussPoint *gp, Ti #else this->initDamaged(tempKappaD, strain, gp); #endif - tempDamage = computeDamageParam(tempKappaD, gp); + double tempDamage = computeDamageParam(tempKappaD, gp); + return { + tempDamage, tempKappaD + }; } - - return tempDamage; } -void -ConcreteDPM :: computeEquivalentStrain(double &tempEquivStrain, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +double +ConcreteDPM::computeEquivalentStrain(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const { //The equivalent strain is based on the volumetric plastic strain - ConcreteDPMStatus *status = giveStatus(gp); - tempKappaP = status->giveTempKappaP(); - kappaP = status->giveKappaP(); + auto status = giveConcreteDPMStatus(gp); + auto tempKappaP = status->giveTempKappaP(); /// FIXME + auto kappaP = status->giveKappaP(); /// FIXME double equivStrain = status->giveEquivStrain(); double deltaEquivStrain = 0.; + double tempEquivStrain = 0.; if ( tempKappaP <= 1.0 || tempKappaP == kappaP ) { - tempEquivStrain = equivStrain; - return; + return equivStrain; } else if ( tempKappaP > 1.0 && tempKappaP != kappaP ) { - FloatArray plasticStrain = status->givePlasticStrain(); - FloatArray tempPlasticStrain = status->giveTempPlasticStrain(); + const auto &plasticStrain = status->givePlasticStrain(); + const auto &tempPlasticStrain = status->giveTempPlasticStrain(); - double volumetricPlasticStrain = plasticStrain(0) + plasticStrain(1) + plasticStrain(2); - double tempVolumetricPlasticStrain = tempPlasticStrain(0) + tempPlasticStrain(1) + tempPlasticStrain(2); + double volumetricPlasticStrain = plasticStrain [ 0 ] + plasticStrain [ 1 ] + plasticStrain [ 2 ]; + double tempVolumetricPlasticStrain = tempPlasticStrain [ 0 ] + tempPlasticStrain [ 1 ] + tempPlasticStrain [ 2 ]; if ( kappaP < 1.0 ) { //compute volumetric plastic strain at peak double peakVolumetricPlasticStrain = ( 1. - kappaP ) / ( tempKappaP - kappaP ) * @@ -536,10 +501,8 @@ ConcreteDPM :: computeEquivalentStrain(double &tempEquivStrain, const FloatArray peakVolumetricPlasticStrain = 0.; } - deltaEquivStrain = - tempVolumetricPlasticStrain - peakVolumetricPlasticStrain; - tempEquivStrain = - deltaEquivStrain / computeDuctilityMeasureDamage(strain, gp); + deltaEquivStrain = tempVolumetricPlasticStrain - peakVolumetricPlasticStrain; + tempEquivStrain = deltaEquivStrain / computeDuctilityMeasureDamage(strain, gp); if ( tempEquivStrain < 0. ) { tempEquivStrain = 0.; } @@ -556,12 +519,13 @@ ConcreteDPM :: computeEquivalentStrain(double &tempEquivStrain, const FloatArray status->letTempEquivStrainBe(tempEquivStrain); status->letDeltaEquivStrainBe(deltaEquivStrain); + return tempEquivStrain; } double -ConcreteDPM :: computeInverseDamage(double dam, GaussPoint *gp) +ConcreteDPM::computeInverseDamage(double dam, GaussPoint *gp) const { - ConcreteDPMStatus *status = giveStatus(gp); + auto status = giveConcreteDPMStatus(gp); double le = status->giveLe(); if ( le == 0. ) { if ( helem > 0. ) { @@ -580,13 +544,13 @@ ConcreteDPM :: computeInverseDamage(double dam, GaussPoint *gp) #define DPM_DAMAGE_TOLERANCE 1.e-8 double -ConcreteDPM :: computeDamageParam(double kappa, GaussPoint *gp) +ConcreteDPM::computeDamageParam(double kappa, GaussPoint *gp) const { double omega = 0.; if ( kappa > 0. ) { // iteration to achieve mesh objectivity // this is only valid for tension - ConcreteDPMStatus *status = giveStatus(gp); + ConcreteDPMStatus *status = giveConcreteDPMStatus(gp); int nite = 0; double R, Lhs, aux, aux1; @@ -651,30 +615,32 @@ ConcreteDPM :: computeDamageParam(double kappa, GaussPoint *gp) void -ConcreteDPM :: initDamaged(double kappaD, - const FloatArray &strain, - GaussPoint *gp) +ConcreteDPM::initDamaged(double kappaD, + const FloatArrayF< 6 > &strain, + GaussPoint *gp) const { + auto status = giveConcreteDPMStatus(gp); + if ( kappaD <= 0. ) { return; } - int indx = 1; - FloatArray principalStrains, crackPlaneNormal(3); - FloatMatrix principalDir(3, 3); - ConcreteDPMStatus *status = giveStatus(gp); - if ( helem > 0. ) { status->setLe(helem); } else if ( status->giveDamage() == 0. ) { - computePrincipalValDir(principalStrains, principalDir, strain, principal_strain); + //auto [principalStrains, principalDir] = computePrincipalValDir(from_voigt_strain(strain)); // c++17 + auto tmp = computePrincipalValDir(from_voigt_strain(strain) ); + auto principalStrains = tmp.first; + auto principalDir = tmp.second; // find index of max positive principal strain + int indx = 1; for ( int i = 2; i <= 3; i++ ) { if ( principalStrains.at(i) > principalStrains.at(indx) ) { indx = i; } } + FloatArrayF< 3 >crackPlaneNormal; for ( int i = 1; i <= 3; i++ ) { crackPlaneNormal.at(i) = principalDir.at(i, indx); } @@ -691,115 +657,115 @@ ConcreteDPM :: initDamaged(double kappaD, // this happens if the status is initialized from a file // with nonzero damage // le determined as square root of element area or cube root of el. volume - status->setLe(gp->giveElement()->computeMeanSize()); + status->setLe(gp->giveElement()->computeMeanSize() ); } } double -ConcreteDPM :: computeDuctilityMeasureDamage(const FloatArray &strain, GaussPoint *gp) +ConcreteDPM::computeDuctilityMeasureDamage(const FloatArrayF< 6 > &strain, GaussPoint *gp) const { - ConcreteDPMStatus *status = giveStatus(gp); - FloatArray plasticStrain = status->givePlasticStrain(); - FloatArray tempPlasticStrain = status->giveTempPlasticStrain(); - tempPlasticStrain.subtract(plasticStrain); - FloatArray principalStrain; - double ductilityMeasure; - double volStrain = tempPlasticStrain(0) + tempPlasticStrain(1) + tempPlasticStrain(2); - //compute sum of negative principal strains - this->computePrincipalValues(principalStrain, tempPlasticStrain, principal_strain); + auto status = giveConcreteDPMStatus(gp); + const auto &plasticStrain = status->givePlasticStrain(); + auto tempPlasticStrain = status->giveTempPlasticStrain() - plasticStrain; + + double volStrain = tempPlasticStrain [ 0 ] + tempPlasticStrain [ 1 ] + tempPlasticStrain [ 2 ]; + // auto principalStrain = computePrincipalValues(from_voigt_strain(strain)); + auto principalStrain = computePrincipalValues(from_voigt_strain(tempPlasticStrain) ); + double negativeVolStrain = 0.; - for ( int i = 0; i < principalStrain.giveSize(); i++ ) { - if ( principalStrain(i) < 0. ) { - negativeVolStrain += principalStrain(i); + for ( int i = 0; i < 3; i++ ) { + if ( principalStrain [ i ] < 0. ) { + negativeVolStrain += principalStrain [ i ]; } } //compute ductility measure double Rs = -negativeVolStrain / volStrain; if ( Rs < 1.0 ) { - ductilityMeasure = 1. + ASoft *pow(Rs, 2.); + return 1. + ASoft * pow(Rs, 2.); } else { - ductilityMeasure = 1. - 3. * ASoft + 4. *ASoft *sqrt(Rs); + return 1. - 3. * ASoft + 4. * ASoft * sqrt(Rs); } - - return ductilityMeasure; } void -ConcreteDPM :: performPlasticityReturn(GaussPoint *gp, - FloatArray &strain) +ConcreteDPM::performPlasticityReturn(GaussPoint *gp, + FloatArrayF< 6 > &strain) const { - ConcreteDPMStatus *status = static_cast< ConcreteDPMStatus * >( this->giveStatus(gp) ); + auto status = static_cast< ConcreteDPMStatus * >( this->giveStatus(gp) ); status->initTempStatus(); //get temp plastic strain and tempKappa - FloatArray tempPlasticStrain = status->giveTempPlasticStrain(); - tempKappaP = status->giveTempKappaP(); + auto tempPlasticStrain = status->giveTempPlasticStrain(); + auto tempKappaP = status->giveTempKappaP(); /// FIXME // compute elastic strains and trial stress - FloatArray elasticStrain = strain; - elasticStrain.subtract(tempPlasticStrain); - applyElasticStiffness(effectiveStress, elasticStrain, eM, nu); + auto elasticStrain = strain - tempPlasticStrain; + auto effectiveStress = applyElasticStiffness(elasticStrain, eM, nu); /// FIXME //Compute trial coordinates - computeTrialCoordinates(effectiveStress, gp); + //auto [sig, rho, thetaTrial] = computeTrialCoordinates(effectiveStress, gp); // c++17 + auto tmp = computeTrialCoordinates(effectiveStress, gp); // c++17 + double sig = std::get< 0 >(tmp); + double rho = std::get< 1 >(tmp); + double thetaTrial = std::get< 2 >(tmp); double yieldValue = computeYieldValue(sig, rho, thetaTrial, tempKappaP); // choose correct stress return and update state flag if ( yieldValue > yieldTol ) { double apexStress = 0.; - checkForVertexCase(apexStress, sig, tempKappaP); + this->checkForVertexCase(apexStress, sig, tempKappaP, gp); //Make the appropriate return - if ( vertexType == VT_Tension || vertexType == VT_Compression ) { + if ( status->giveTempVertexType() == ConcreteDPMStatus::VT_Tension || status->giveTempVertexType() == ConcreteDPMStatus::VT_Compression ) { performVertexReturn(effectiveStress, apexStress, gp); - if ( vertexType == VT_Regular ) { + if ( status->giveTempVertexType() == ConcreteDPMStatus::VT_Regular ) { //This was no real vertex case //get the original tempKappaP and stress tempKappaP = status->giveTempKappaP(); - applyElasticStiffness(effectiveStress, elasticStrain, eM, nu); + effectiveStress = applyElasticStiffness(elasticStrain, eM, nu); } } - if ( vertexType == VT_Regular ) { - performRegularReturn(effectiveStress, gp); + if ( status->giveTempVertexType() == ConcreteDPMStatus::VT_Regular ) { + performRegularReturn(effectiveStress, gp, thetaTrial); } } // update temp kappaP - status->letTempKappaPBe(tempKappaP); + // status->letTempKappaPBe(tempKappaP); // compute the plastic strains - applyElasticCompliance(elasticStrain, effectiveStress, eM, nu); - tempPlasticStrain = strain; - tempPlasticStrain.subtract(elasticStrain); + elasticStrain = applyElasticCompliance(effectiveStress, eM, nu); + tempPlasticStrain = strain - elasticStrain; status->letTempPlasticStrainBe(tempPlasticStrain); } -bool -ConcreteDPM :: checkForVertexCase(double &answer, - const double sig, - const double tempKappa) +void +ConcreteDPM::checkForVertexCase(double &answer, + const double sig, + const double tempKappa, + GaussPoint *gp) const { + auto status = static_cast< ConcreteDPMStatus * >( this->giveStatus(gp) ); + //Compute sigZero and compare with actual sig - int l = 0; - double FZero = 1.; - double dFZeroDSigZero = 0.; - double sigZero; - const double yieldHardOne = computeHardeningOne(tempKappa); double apexCompression = 0.; //compressive apex if ( ( tempKappa < 1. ) && ( sig < 0. ) ) { - sigZero = -15. * fc; + const double yieldHardOne = computeHardeningOne(tempKappa); + double sigZero = -15. * fc; + double FZero = 1.; + int l = 0; while ( fabs(FZero) > yieldTol && l <= newtonIter ) { l++; FZero = pow( ( 1. - yieldHardOne ), 2. ) * pow( ( sigZero / fc ), 4. ) + - pow(yieldHardOne, 2.) * m * ( sigZero / fc ) - pow(yieldHardOne, 2.); + pow(yieldHardOne, 2.) * m * ( sigZero / fc ) - pow(yieldHardOne, 2.); - dFZeroDSigZero = pow( ( 1. - yieldHardOne ), 2. ) * 4. * pow( ( sigZero / fc ), 3. ) / fc + - pow(yieldHardOne, 2.) * m / fc; + double dFZeroDSigZero = pow( ( 1. - yieldHardOne ), 2. ) * 4. * pow( ( sigZero / fc ), 3. ) / fc + + pow(yieldHardOne, 2.) * m / fc; sigZero = sigZero - FZero / dFZeroDSigZero; } @@ -812,146 +778,125 @@ ConcreteDPM :: checkForVertexCase(double &answer, } if ( ( sig > 0. && tempKappa < 1. ) || ( sig > fc / m && tempKappa >= 1. ) ) { - vertexType = VT_Tension; answer = 0.; + status->letTempVertexTypeBe(ConcreteDPMStatus::VT_Tension); } else if ( sig < apexCompression ) { - vertexType = VT_Compression; answer = apexCompression; + status->letTempVertexTypeBe(ConcreteDPMStatus::VT_Compression); } else { - vertexType = VT_Regular; + status->letTempVertexTypeBe(ConcreteDPMStatus::VT_Regular); } - - return false; } - - void -ConcreteDPM :: performRegularReturn(FloatArray &effectiveStress, - GaussPoint *gp) +ConcreteDPM::performRegularReturn(FloatArrayF< 6 > &effectiveStress, GaussPoint *gp, const double theta) const { - //Define status - ConcreteDPMStatus *status = static_cast< ConcreteDPMStatus * >( this->giveStatus(gp) ); - //Variables - deltaLambda = 0.; - double deltaLambdaIncrement = 0.; - double yieldValue; - double residualNorm; - double rhoTest = 0.; - double deltaLambdaIncrementNew = 0.; - double tempKappaPTest = 0.; - int iterationCount = 0; - int negativeRhoFlag = 0; - FloatArray dGDInv(2); - FloatArray dFDInv(2); - FloatArray residual(3); - FloatArray derivativesOfYieldSurface(3); - FloatArray flowRules(3); - FloatArray answerIncrement(3); - // double residual2; - double dKappaDDeltaLambda; - double dFDKappa = 0.; - FloatMatrix aMatrix; - FloatArray helpVectorA(3); - FloatArray helpVectorB(3); - FloatArray deviatoricStress; + auto status = static_cast< ConcreteDPMStatus * >( this->giveStatus(gp) ); //compute the principal directions of the stress - FloatArray help; - FloatMatrix stressPrincipalDir; - computePrincipalValDir(help, stressPrincipalDir, effectiveStress, principal_stress); + //auto [help, stressPrincipalDir] = computePrincipalValDir(from_voigt_stress(effectiveStress)); // c++17 + auto tmp = computePrincipalValDir(from_voigt_stress(effectiveStress) ); + auto stressPrincipalDir = tmp.second; //compute invariants from stress state - sig = this->computeDeviatoricVolumetricSplit(deviatoricStress, effectiveStress); - rho = computeSecondCoordinate(deviatoricStress); + //auto [deviatoricStress, sig] = this->computeDeviatoricVolumetricSplit(effectiveStress); // c++17 + auto tmp2 = this->computeDeviatoricVolumetricSplit(effectiveStress); + auto deviatoricStress = tmp2.first; + double sig = tmp2.second; /// FIXME: verify + double rho = computeSecondCoordinate(deviatoricStress); /// FIXME: verify + double deltaLambda = 0.; /// FIXME: verify - const double volumetricPlasticStrain = - 3. * status->giveVolumetricPlasticStrain(); + const double volumetricPlasticStrain = 3. * status->giveVolumetricPlasticStrain(); - const double deviatoricPlasticStrainNorm = - status->giveDeviatoricPlasticStrainNorm(); + const double deviatoricPlasticStrainNorm = status->giveDeviatoricPlasticStrainNorm(); double tempVolumetricPlasticStrain = volumetricPlasticStrain; double tempDeviatoricPlasticStrainNorm = deviatoricPlasticStrainNorm; const double kappaP = status->giveKappaP(); - tempKappaP = kappaP; + auto tempKappaP = kappaP; /// FIXME - yieldValue = computeYieldValue(sig, rho, thetaTrial, tempKappaP); - residualNorm = fabs(yieldValue); + auto yieldValue = computeYieldValue(sig, rho, theta, tempKappaP); + double residualNorm = fabs(yieldValue); + int negativeRhoFlag = 0; + + int iterationCount = 0; while ( residualNorm > yieldTol ) { if ( ++iterationCount == newtonIter ) { OOFEM_ERROR("Closest point projection did not converge."); } - //compute the stress, yield value and residuals - computeDGDInv(dGDInv, sig, rho, tempKappaP); - computeDFDInv(dFDInv, sig, rho, tempKappaP); - dFDKappa = computeDFDKappa(sig, rho, tempKappaP); - dKappaDDeltaLambda = computeDKappaDDeltaLambda(sig, rho, tempKappaP); - yieldValue = computeYieldValue(sig, rho, thetaTrial, tempKappaP); + //compute the stress, yield value and resdiuals + auto dGDInv = computeDGDInv(sig, rho, tempKappaP); + auto dFDInv = computeDFDInv(sig, rho, theta, tempKappaP); + auto dFDKappa = computeDFDKappa(sig, rho, theta, tempKappaP); + auto dKappaDDeltaLambda = computeDKappaDDeltaLambda(sig, rho, theta, tempKappaP); + yieldValue = computeYieldValue(sig, rho, theta, tempKappaP); //The residual volumetric plastic strain is defined as eps1+eps2+eps3 - residual(0) = volumetricPlasticStrain - tempVolumetricPlasticStrain + - deltaLambda *dGDInv(0); - residual(1) = deviatoricPlasticStrainNorm - - tempDeviatoricPlasticStrainNorm + deltaLambda *dGDInv(1); - residual(2) = kappaP - tempKappaP + deltaLambda * dKappaDDeltaLambda; + FloatArrayF< 3 >residual; + residual [ 0 ] = volumetricPlasticStrain - tempVolumetricPlasticStrain + + deltaLambda * dGDInv [ 0 ]; + residual [ 1 ] = deviatoricPlasticStrainNorm - + tempDeviatoricPlasticStrainNorm + deltaLambda * dGDInv [ 1 ]; + residual [ 2 ] = kappaP - tempKappaP + deltaLambda * dKappaDDeltaLambda; // weighted norm - residualNorm = pow(residual(0), 2.) + pow(residual(1), 2.) + - pow(residual(2), 2.) + pow(yieldValue, 2.); + //residualNorm = norm(residual); - yieldValue forgotten! + + residualNorm = pow(residual [ 0 ], 2.) + pow(residual [ 1 ], 2.) + + pow(residual [ 2 ], 2.) + pow(yieldValue, 2.); residualNorm = sqrt(residualNorm); + // printf("\n residualNorm= %e\n", residualNorm); if ( residualNorm > yieldTol ) { - computeAMatrix(aMatrix, sig, rho, tempKappaP); + auto aMatrix = computeAMatrix(sig, rho, theta, tempKappaP, deltaLambda); // assemble the derivatives of the yield surface + FloatArrayF< 3 >derivativesOfYieldSurface; for ( int i = 0; i < 2; i++ ) { - derivativesOfYieldSurface(i) = dFDInv(i); + derivativesOfYieldSurface [ i ] = dFDInv [ i ]; } - derivativesOfYieldSurface(2) = dFDKappa; + derivativesOfYieldSurface [ 2 ] = dFDKappa; //assemble flow rules + FloatArrayF< 3 >flowRules; for ( int i = 0; i < 2; i++ ) { - flowRules(i) = dGDInv(i); + flowRules [ i ] = dGDInv [ i ]; } - flowRules(2) = dKappaDDeltaLambda; + flowRules [ 2 ] = dKappaDDeltaLambda; //compute the deltaLambdaIncrement - deltaLambdaIncrement = yieldValue; - helpVectorA.beProductOf(aMatrix, residual); + double deltaLambdaIncrement = yieldValue; + auto helpVectorA = dot(aMatrix, residual); for ( int i = 0; i < 3; i++ ) { - deltaLambdaIncrement -= derivativesOfYieldSurface(i) * helpVectorA(i); + deltaLambdaIncrement -= derivativesOfYieldSurface [ i ] * helpVectorA [ i ]; } - helpVectorB.beProductOf(aMatrix, flowRules); + auto helpVectorB = dot(aMatrix, flowRules); double denominator = 0.; for ( int i = 0; i < 3; i++ ) { - denominator += derivativesOfYieldSurface(i) * helpVectorB(i); + denominator += derivativesOfYieldSurface [ i ] * helpVectorB [ i ]; } deltaLambdaIncrement /= denominator; //compute increment of answer - FloatArray helpVectorC; - helpVectorC = residual; - helpVectorC.add(deltaLambdaIncrement, flowRules); - answerIncrement.beProductOf(aMatrix, helpVectorC); - answerIncrement.negated(); - rhoTest = rho + answerIncrement(1); + auto answerIncrement = -dot(aMatrix, ( residual + deltaLambdaIncrement * flowRules ) ); + auto rhoTest = rho + answerIncrement [ 1 ]; //Special case, if rho changes sign + double tempKappaPTest = 0.; if ( rhoTest < 0. && negativeRhoFlag == 0 ) { //Determine deltaLambdaIncrement, so that rho is equal to zero - answerIncrement(1) = -rho; + answerIncrement [ 1 ] = -rho; - deltaLambdaIncrementNew = - ( -aMatrix(1, 0) * residual(0) - aMatrix(1, 1) * residual(1) - - aMatrix(1, 2) * residual(2) - answerIncrement(1) ) / - ( flowRules(0) * aMatrix(1, 0) + flowRules(1) * aMatrix(1, 1) + - flowRules(2) * aMatrix(1, 2) ); + double deltaLambdaIncrementNew = + ( -aMatrix(1, 0) * residual [ 0 ] - aMatrix(1, 1) * residual [ 1 ] - + aMatrix(1, 2) * residual [ 2 ] - answerIncrement [ 1 ] ) / + ( flowRules [ 0 ] * aMatrix(1, 0) + flowRules [ 1 ] * aMatrix(1, 1) + + flowRules [ 2 ] * aMatrix(1, 2) ); // Special case, if deltaLambdaIncrement is equal to zero. if ( fabs(deltaLambdaIncrementNew) < yieldTol * 1.e3 ) { @@ -959,22 +904,19 @@ ConcreteDPM :: performRegularReturn(FloatArray &effectiveStress, deltaLambdaIncrementNew = deltaLambdaIncrement; } - helpVectorC = residual; - helpVectorC.add(deltaLambdaIncrementNew, flowRules); - answerIncrement.beProductOf(aMatrix, helpVectorC); - answerIncrement.negated(); + answerIncrement = -dot(aMatrix, ( residual + deltaLambdaIncrementNew * flowRules ) ); - sig += answerIncrement(0); - rho += answerIncrement(1); + sig += answerIncrement [ 0 ]; + rho += answerIncrement [ 1 ]; tempKappaPTest = tempKappaP; - tempKappaP += answerIncrement(2); + tempKappaP += answerIncrement [ 2 ]; deltaLambda += deltaLambdaIncrementNew; } else { tempKappaPTest = tempKappaP; - tempKappaP += answerIncrement(2); - sig += answerIncrement(0); - rho += answerIncrement(1); + tempKappaP += answerIncrement [ 2 ]; + sig += answerIncrement [ 0 ]; + rho += answerIncrement [ 1 ]; deltaLambda += deltaLambdaIncrement; } @@ -984,8 +926,8 @@ ConcreteDPM :: performRegularReturn(FloatArray &effectiveStress, tempKappaP = tempKappaPTest; } - tempVolumetricPlasticStrain -= answerIncrement(0) / ( kM ); - tempDeviatoricPlasticStrainNorm -= answerIncrement(1) / ( 2. * gM ); + tempVolumetricPlasticStrain -= answerIncrement [ 0 ] / ( kM ); + tempDeviatoricPlasticStrainNorm -= answerIncrement [ 1 ] / ( 2. * gM ); } //if (gp->giveElement()->giveNumber() == 1301){ @@ -1001,61 +943,58 @@ ConcreteDPM :: performRegularReturn(FloatArray &effectiveStress, // printf("\nnumber of iterations = %i\n", iterationCount); status->letDeltaLambdaBe(deltaLambda); - FloatArray stressPrincipal; - stressPrincipal.zero(); + FloatArrayF< 6 >stressPrincipal; + stressPrincipal [ 0 ] = sig + sqrt(2. / 3.) * rho * cos(theta); + stressPrincipal [ 1 ] = sig + sqrt(2. / 3.) * rho * cos(theta - 2. * M_PI / 3.); + stressPrincipal [ 2 ] = sig + sqrt(2. / 3.) * rho * cos(theta + 2. * M_PI / 3.); - stressPrincipal(0) = sig + sqrt(2. / 3.) * rho * cos(thetaTrial); - stressPrincipal(1) = sig + sqrt(2. / 3.) * rho * cos(thetaTrial - 2. * M_PI / 3.); - stressPrincipal(2) = sig + sqrt(2. / 3.) * rho * cos(thetaTrial + 2. * M_PI / 3.); + effectiveStress = transformStressVectorTo(stressPrincipalDir, stressPrincipal, 1); - transformStressVectorTo(effectiveStress, stressPrincipalDir, stressPrincipal, 1); + // PH + status->letTempKappaPBe(tempKappaP); } void -ConcreteDPM :: performVertexReturn(FloatArray &effectiveStress, - double apexStress, - GaussPoint *gp) +ConcreteDPM::performVertexReturn(FloatArrayF< 6 > &effectiveStress, + double apexStress, + GaussPoint *gp) const { - ConcreteDPMStatus *status = static_cast< ConcreteDPMStatus * >( this->giveStatus(gp) ); - FloatArray deviatoricStressTrial; - double sigTrial; - double yieldValue; - double yieldValueMid; + auto status = static_cast< ConcreteDPMStatus * >( this->giveStatus(gp) ); double sig2 = 0.; - double dSig; - double sigMid; - double sigAnswer; - double ratioPotential; - sigTrial = this->computeDeviatoricVolumetricSplit(deviatoricStressTrial, effectiveStress); + //auto [deviatoricStressTrial, sigTrial] = this->computeDeviatoricVolumetricSplit(effectiveStress); // c++17 + auto tmp = this->computeDeviatoricVolumetricSplit(effectiveStress); + auto deviatoricStressTrial = tmp.first; + auto sigTrial = tmp.second; + const double rhoTrial = computeSecondCoordinate(deviatoricStressTrial); - tempKappaP = status->giveTempKappaP(); + double tempKappaP = status->giveTempKappaP(); /// FIXME verify const double kappaInitial = tempKappaP; - if ( vertexType == VT_Tension ) { + if ( status->giveTempVertexType() == ConcreteDPMStatus::VT_Tension ) { sig2 = -0.1 * ft; - } else if ( vertexType == VT_Compression ) { + } else if ( status->giveTempVertexType() == ConcreteDPMStatus::VT_Compression ) { sig2 = apexStress; } - tempKappaP = - computeTempKappa(kappaInitial, sigTrial, rhoTrial, sigTrial); + tempKappaP = computeTempKappa(kappaInitial, sigTrial, rhoTrial, sigTrial); - yieldValue = - computeYieldValue(sigTrial, 0., 0., tempKappaP); + double yieldValue = computeYieldValue(sigTrial, 0., 0., tempKappaP); - tempKappaP = - computeTempKappa(kappaInitial, sigTrial, rhoTrial, sig2); + tempKappaP = computeTempKappa(kappaInitial, sigTrial, rhoTrial, sig2); - yieldValueMid = - computeYieldValue(sig2, 0., 0., tempKappaP); + double yieldValueMid = computeYieldValue(sig2, 0., 0., tempKappaP); if ( yieldValue * yieldValueMid >= 0. ) { - vertexType = VT_Regular; + status->letTempVertexTypeBe(ConcreteDPMStatus::VT_Regular); return; } + double sigAnswer; + double ratioPotential; + + double dSig; if ( yieldValue < 0.0 ) { dSig = sig2 - sigTrial; sigAnswer = sig2; @@ -1067,11 +1006,10 @@ ConcreteDPM :: performVertexReturn(FloatArray &effectiveStress, for ( int j = 0; j < 250; j++ ) { dSig = 0.5 * dSig; - sigMid = sigAnswer + dSig; + double sigMid = sigAnswer + dSig; - tempKappaP = - computeTempKappa(kappaInitial, sigTrial, rhoTrial, sigMid); + tempKappaP = computeTempKappa(kappaInitial, sigTrial, rhoTrial, sigMid); yieldValueMid = computeYieldValue(sigMid, 0., 0., tempKappaP); @@ -1081,44 +1019,44 @@ ConcreteDPM :: performVertexReturn(FloatArray &effectiveStress, if ( fabs(yieldValueMid) < yieldTol && yieldValueMid <= 0. ) { for ( int i = 0; i < 3; i++ ) { - effectiveStress(i) = sigAnswer; + effectiveStress [ i ] = sigAnswer; } for ( int i = 3; i < effectiveStress.giveSize(); i++ ) { - effectiveStress(i) = 0.; + effectiveStress [ i ] = 0.; } - ratioPotential = - computeRatioPotential(sigAnswer, tempKappaP); + ratioPotential = computeRatioPotential(sigAnswer, tempKappaP); double ratioTrial = rhoTrial / ( sigTrial - sigAnswer ); - if ( ( ( ( ratioPotential >= ratioTrial ) && vertexType == VT_Tension ) ) || - ( ( ratioPotential <= ratioTrial ) && vertexType == VT_Compression ) ) { + + if ( ( ( ( ratioPotential >= ratioTrial ) && status->giveTempVertexType() == ConcreteDPMStatus::VT_Tension ) ) || + ( ( ratioPotential <= ratioTrial ) && status->giveTempVertexType() == ConcreteDPMStatus::VT_Compression ) ) { return; } else { - vertexType = VT_Regular; + status->letTempVertexTypeBe(ConcreteDPMStatus::VT_Regular); return; } } } - vertexType = VT_Regular; + status->letTempVertexTypeBe(ConcreteDPMStatus::VT_Regular); + // PH + status->letTempKappaPBe(tempKappaP); } double -ConcreteDPM :: computeTempKappa(const double kappaInitial, - const double sigTrial, - const double rhoTrial, - const double sig) +ConcreteDPM::computeTempKappa(const double kappaInitial, + const double sigTrial, + const double rhoTrial, + const double sig) const { //This function is called, if stress state is in vertex case - double equivalentDeltaPlasticStrain; - rho = 0.; - equivalentDeltaPlasticStrain = sqrt( 1. / 9. * pow( ( sigTrial - sig ) / ( kM ), 2. ) + - pow(rhoTrial / ( 2. * gM ), 2.) ); + double equivalentDeltaPlasticStrain = sqrt(1. / 9. * pow( ( sigTrial - sig ) / ( kM ), 2. ) + pow(rhoTrial / ( 2. * gM ), 2.) ); + double rho = 0.; /// FIXME: verify double thetaVertex = 0.; double ductilityMeasure = computeDuctilityMeasure(sig, rho, thetaVertex); @@ -1127,10 +1065,10 @@ ConcreteDPM :: computeTempKappa(const double kappaInitial, double -ConcreteDPM :: computeYieldValue(const double sig, - const double rho, - const double theta, - const double tempKappa) const +ConcreteDPM::computeYieldValue(const double sig, + const double rho, + const double theta, + const double tempKappa) const { //compute yieldHard const double yieldHardOne = computeHardeningOne(tempKappa); @@ -1138,14 +1076,14 @@ ConcreteDPM :: computeYieldValue(const double sig, // compute elliptic function r const double rFunction = ( 4. * ( 1. - pow(ecc, 2.) ) * pow(cos(theta), 2.) + - pow( ( 2. * ecc - 1. ), 2. ) ) / + pow( ( 2. * ecc - 1. ), 2. ) ) / ( 2. * ( 1. - pow(ecc, 2.) ) * cos(theta) + - ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - pow(ecc, 2.) ) * pow(cos(theta), 2.) - + 5. * pow(ecc, 2.) - 4. * ecc) ); + ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - pow(ecc, 2.) ) * pow(cos(theta), 2.) + + 5. * pow(ecc, 2.) - 4. * ecc) ); //compute help function Al const double Al = ( 1. - yieldHardOne ) * pow( ( sig / fc + rho / ( sqrt(6.) * fc ) ), 2. ) + - sqrt(3. / 2.) * rho / fc; + sqrt(3. / 2.) * rho / fc; //Compute yield equation return pow(Al, 2.) + @@ -1155,11 +1093,12 @@ ConcreteDPM :: computeYieldValue(const double sig, double -ConcreteDPM :: computeDFDKappa(const double sig, - const double rho, - const double tempKappa) +ConcreteDPM::computeDFDKappa(const double sig, + const double rho, + const double theta, + const double tempKappa) const { - const double theta = thetaTrial; + // const double theta = thetaTrial; //compute yieldHard and yieldSoft const double yieldHardOne = computeHardeningOne(tempKappa); const double yieldHardTwo = computeHardeningOne(tempKappa); @@ -1171,15 +1110,15 @@ ConcreteDPM :: computeDFDKappa(const double sig, const double rFunction = ( 4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) + ( 2. * ecc - 1. ) * ( 2. * ecc - 1. ) ) / ( 2 * ( 1. - ecc * ecc ) * cos(theta) + ( 2. * ecc - 1. ) * - sqrt(4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) + 5. * ecc * ecc - 4. * ecc) ); + sqrt(4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) + 5. * ecc * ecc - 4. * ecc) ); //compute help functions Al, Bl const double Al = ( 1. - yieldHardOne ) * pow( ( sig / fc + rho / ( sqrt(6.) * fc ) ), 2. ) + sqrt(3. / 2.) * rho / fc; const double Bl = sig / fc + rho / ( fc * sqrt(6.) ); - const double dFDYieldHardOne = -2. *Al *pow(Bl, 2.) - + 2. * yieldHardOne * m * ( sig / fc + rho * rFunction / ( sqrt(6.) * fc ) ); + const double dFDYieldHardOne = -2. * Al * pow(Bl, 2.) + + 2. * yieldHardOne * m * ( sig / fc + rho * rFunction / ( sqrt(6.) * fc ) ); const double dFDYieldHardTwo = -2. * yieldHardTwo; @@ -1200,13 +1139,13 @@ ConcreteDPM :: computeDFDKappa(const double sig, return dFDKappa; } -void -ConcreteDPM :: computeDFDInv(FloatArray &answer, - const double sig, - const double rho, - const double tempKappa) const +FloatArrayF< 2 > +ConcreteDPM::computeDFDInv(const double sig, + const double rho, + const double theta, + const double tempKappa) const { - const double theta = thetaTrial; + // const double theta = thetaTrial; //compute yieldHard const double yieldHardOne = computeHardeningOne(tempKappa); @@ -1225,93 +1164,80 @@ ConcreteDPM :: computeDFDInv(FloatArray &answer, //compute dfdrho const double dfdrho = AL / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * BL + 6. ) + rFunction * m * yieldHardOne * yieldHardOne / ( sqrt(6.) * fc ); - answer(0) = dfdsig; - answer(1) = dfdrho; + return { + dfdsig, dfdrho + }; } double -ConcreteDPM :: computeDKappaDDeltaLambda(const double sig, - const double rho, - const double tempKappa) +ConcreteDPM::computeDKappaDDeltaLambda(const double sig, + const double rho, + const double theta, + const double tempKappa) const { //Variables - double equivalentDGDStress; - FloatArray dGDInv(2); - computeDGDInv(dGDInv, sig, rho, tempKappa); + auto dGDInv = computeDGDInv(sig, rho, tempKappa); - equivalentDGDStress = sqrt( 1. / 3. * pow(dGDInv(0), 2.) + - pow(dGDInv(1), 2.) ); + double equivalentDGDStress = sqrt(1. / 3. * pow(dGDInv [ 0 ], 2.) + + pow(dGDInv [ 1 ], 2.) ); - double ductilityMeasure = computeDuctilityMeasure(sig, rho, this->thetaTrial); + double ductilityMeasure = computeDuctilityMeasure(sig, rho, theta); double dKappaDDeltaLambda = equivalentDGDStress / ductilityMeasure; return dKappaDDeltaLambda; } -void -ConcreteDPM :: computeDDKappaDDeltaLambdaDInv(FloatArray &answer, - const double sig, - const double rho, - const double tempKappa) +FloatArrayF< 2 > +ConcreteDPM::computeDDKappaDDeltaLambdaDInv(const double sig, + const double rho, + const double theta, + const double tempKappa) const { - //Variables - double equivalentDGDStress; - FloatArray dGDInv(2); - FloatMatrix dDGDDInv(2, 2); - FloatArray dEquivalentDGDStressDInv(2); - //Compute first and second derivative of plastic potential - computeDGDInv(dGDInv, sig, rho, tempKappa); - computeDDGDDInv(dDGDDInv, sig, rho, tempKappa); + auto dGDInv = computeDGDInv(sig, rho, tempKappa); + auto dDGDDInv = computeDDGDDInv(sig, rho, tempKappa); //Compute equivalentDGDStress - equivalentDGDStress = sqrt( 1. / 3. * pow(dGDInv(0), 2.) + - pow(dGDInv(1), 2.) ); + double equivalentDGDStress = sqrt(1. / 3. * pow(dGDInv [ 0 ], 2.) + + pow(dGDInv [ 1 ], 2.) ); //computeDuctilityMeasure - double ductilityMeasure = computeDuctilityMeasure(sig, rho, this->thetaTrial); + double ductilityMeasure = computeDuctilityMeasure(sig, rho, theta); //Compute dEquivalentDGDStressDInv - dEquivalentDGDStressDInv(0) = - ( 2. / 3. * dGDInv(0) * dDGDDInv(0, 0) + 2. * dGDInv(1) * dDGDDInv(1, 0) ) / ( 2. * equivalentDGDStress ); - dEquivalentDGDStressDInv(1) = - ( 2. / 3. * dGDInv(0) * dDGDDInv(0, 1) + 2. * dGDInv(1) * dDGDDInv(1, 1) ) / ( 2. * equivalentDGDStress ); - - answer.zero(); + FloatArrayF< 2 >dEquivalentDGDStressDInv; + dEquivalentDGDStressDInv [ 0 ] = + ( 2. / 3. * dGDInv [ 0 ] * dDGDDInv(0, 0) + 2. * dGDInv [ 1 ] * dDGDDInv(1, 0) ) / ( 2. * equivalentDGDStress ); + dEquivalentDGDStressDInv [ 1 ] = + ( 2. / 3. * dGDInv [ 0 ] * dDGDDInv(0, 1) + 2. * dGDInv [ 1 ] * dDGDDInv(1, 1) ) / ( 2. * equivalentDGDStress ); // compute the derivative of - FloatArray dDuctilityMeasureDInv(2); - computeDDuctilityMeasureDInv(dDuctilityMeasureDInv, sig, rho, tempKappa); + auto dDuctilityMeasureDInv = computeDDuctilityMeasureDInv(sig, rho, theta, tempKappa); - answer(0) = ( dEquivalentDGDStressDInv(0) * ductilityMeasure - equivalentDGDStress * dDuctilityMeasureDInv(0) ) / pow(ductilityMeasure, 2.); - - answer(1) = ( dEquivalentDGDStressDInv(1) * ductilityMeasure - equivalentDGDStress * dDuctilityMeasureDInv(1) ) / pow(ductilityMeasure, 2.); + FloatArrayF< 2 >answer; + answer [ 0 ] = ( dEquivalentDGDStressDInv [ 0 ] * ductilityMeasure - equivalentDGDStress * dDuctilityMeasureDInv [ 0 ] ) / pow(ductilityMeasure, 2.); + answer [ 1 ] = ( dEquivalentDGDStressDInv [ 1 ] * ductilityMeasure - equivalentDGDStress * dDuctilityMeasureDInv [ 1 ] ) / pow(ductilityMeasure, 2.); + return answer; } double -ConcreteDPM :: computeDDKappaDDeltaLambdaDKappa(const double sig, - const double rho, - const double tempKappa) +ConcreteDPM::computeDDKappaDDeltaLambdaDKappa(const double sig, + const double rho, + const double theta, + const double tempKappa) const { - //Variables - double equivalentDGDStress; - FloatArray dGDInv(2); - FloatArray dDGDInvDKappa(2); - double dEquivalentDGDStressDKappa; - //Compute first and second derivative of plastic potential - computeDGDInv(dGDInv, sig, rho, tempKappa); - computeDDGDInvDKappa(dDGDInvDKappa, sig, rho, tempKappa); + auto dGDInv = computeDGDInv(sig, rho, tempKappa); + auto dDGDInvDKappa = computeDDGDInvDKappa(sig, rho, tempKappa); - equivalentDGDStress = sqrt( 1. / 3. * pow(dGDInv(0), 2.) + - pow(dGDInv(1), 2.) ); + double equivalentDGDStress = sqrt(1. / 3. * pow(dGDInv [ 0 ], 2.) + pow(dGDInv [ 1 ], 2.) ); //computeDuctilityMeasure - double ductilityMeasure = computeDuctilityMeasure(sig, rho, this->thetaTrial); + double ductilityMeasure = computeDuctilityMeasure(sig, rho, theta); //Compute dEquivalentDGDStressDKappa - dEquivalentDGDStressDKappa = - ( 2. / 3. * dGDInv(0) * dDGDInvDKappa(0) + 2. * dGDInv(1) * dDGDInvDKappa(1) ) / ( 2. * equivalentDGDStress ); + double dEquivalentDGDStressDKappa = + ( 2. / 3. * dGDInv [ 0 ] * dDGDInvDKappa [ 0 ] + 2. * dGDInv [ 1 ] * dDGDInvDKappa [ 1 ] ) / ( 2. * equivalentDGDStress ); // compute the derivative of double dDuctilityMeasureDKappa = 0.; @@ -1324,9 +1250,9 @@ ConcreteDPM :: computeDDKappaDDeltaLambdaDKappa(const double sig, } double -ConcreteDPM :: computeDuctilityMeasure(const double sig, - const double rho, - const double theta) +ConcreteDPM::computeDuctilityMeasure(const double sig, + const double rho, + const double theta) const { double thetaConst = pow(2. * cos(theta), 2.); double ductilityMeasure; @@ -1341,7 +1267,7 @@ ConcreteDPM :: computeDuctilityMeasure(const double sig, double BHelp = ( fZero - CHelp ) / fPrimeZero; ductilityMeasure = ( AHelp * exp(x / BHelp) + CHelp ) / thetaConst; } else { - ductilityMeasure = ( AHard + ( BHard - AHard ) * exp( -x / ( CHard ) ) ) / thetaConst; + ductilityMeasure = ( AHard + ( BHard - AHard ) * exp(-x / ( CHard ) ) ) / thetaConst; } if ( ductilityMeasure <= 0. ) { @@ -1351,13 +1277,13 @@ ConcreteDPM :: computeDuctilityMeasure(const double sig, return ductilityMeasure; } -void -ConcreteDPM :: computeDDuctilityMeasureDInv(FloatArray &answer, - const double sig, - const double rho, - const double tempKappa) +FloatArrayF< 2 > +ConcreteDPM::computeDDuctilityMeasureDInv(const double sig, + const double rho, + const double theta, + const double tempKappa) const { - double thetaConst = pow(2. * cos(thetaTrial), 2.); + double thetaConst = pow(2. * cos(theta), 2.); double x = ( -( sig + fc / 3 ) ) / fc; if ( x < 0. ) { double dXDSig = -1. / fc; @@ -1368,23 +1294,24 @@ ConcreteDPM :: computeDDuctilityMeasureDInv(FloatArray &answer, double CHelp = DHard; double AHelp = fZero - CHelp; double BHelp = ( fZero - CHelp ) / fPrimeZero; - double dDuctilityMeasureDX = AHelp / BHelp *exp(x / BHelp) / thetaConst; - answer(0) = dDuctilityMeasureDX * dXDSig; - answer(1) = 0.; + double dDuctilityMeasureDX = AHelp / BHelp * exp(x / BHelp) / thetaConst; + return { + dDuctilityMeasureDX *dXDSig, 0. + }; } else { double dXDSig = -1. / fc; - double dDuctilityMeasureDX = -( BHard - AHard ) / ( CHard ) / thetaConst *exp( -x / ( CHard ) ); - answer(0) = dDuctilityMeasureDX * dXDSig; - answer(1) = 0.; + double dDuctilityMeasureDX = -( BHard - AHard ) / ( CHard ) / thetaConst * exp(-x / ( CHard ) ); + return { + dDuctilityMeasureDX *dXDSig, 0. + }; } } -void -ConcreteDPM :: computeDGDInv(FloatArray &answer, - const double sig, - const double rho, - const double tempKappa) +FloatArrayF< 2 > +ConcreteDPM::computeDGDInv(const double sig, + const double rho, + const double tempKappa) const { //Compute dilation parameter const double R = ( sig - ft / 3. ) / fc; @@ -1404,16 +1331,17 @@ ConcreteDPM :: computeDGDInv(FloatArray &answer, const double dgdsig = 4. * ( 1. - yieldHardOne ) / fc * Al * Bl + yieldHardOne * yieldHardOne * mQ / fc; const double dgdrho = Al / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) + - m *pow(yieldHardOne, 2.) / ( sqrt(6.) * fc ); + m * pow(yieldHardOne, 2.) / ( sqrt(6.) * fc ); - answer(0) = dgdsig; - answer(1) = dgdrho; + return { + dgdsig, dgdrho + }; } double -ConcreteDPM :: computeRatioPotential(const double sig, - const double tempKappa) +ConcreteDPM::computeRatioPotential(const double sig, + const double tempKappa) const { //Compute dilation parameter const double R = ( sig - ft / 3. ) / fc; @@ -1433,7 +1361,7 @@ ConcreteDPM :: computeRatioPotential(const double sig, const double dgdsig = 4. * ( 1. - yieldHardOne ) / fc * Al * Bl + yieldHardOne * yieldHardOne * mQ / fc; const double dgdrho = Al / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) + - m *pow(yieldHardOne, 2.) / ( sqrt(6.) * fc ); + m * pow(yieldHardOne, 2.) / ( sqrt(6.) * fc ); /* Debug: Introduce the factor 2G/K. I am not sure if this is correct. * There might be too many stress states in the vertex case. */ @@ -1441,11 +1369,10 @@ ConcreteDPM :: computeRatioPotential(const double sig, } -void -ConcreteDPM :: computeDDGDInvDKappa(FloatArray &answer, - const double sig, - const double rho, - const double tempKappa) +FloatArrayF< 2 > +ConcreteDPM::computeDDGDInvDKappa(const double sig, + const double rho, + const double tempKappa) const { //Compute dilation parameter const double R = ( sig - ft / 3. ) / fc; @@ -1471,17 +1398,17 @@ ConcreteDPM :: computeDDGDInvDKappa(FloatArray &answer, const double dDGDRhoDKappa = ( dAlDYieldHard / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) - - 4. * Al / ( sqrt(6.) * fc ) * Bl + 2. * m * yieldHardOne / ( sqrt(6.) * fc ) ) * dYieldHardOneDKappa; + 4. * Al / ( sqrt(6.) * fc ) * Bl + 2. * m * yieldHardOne / ( sqrt(6.) * fc ) ) * dYieldHardOneDKappa; - answer(0) = dDGDSigDKappa; - answer(1) = dDGDRhoDKappa; + return { + dDGDSigDKappa, dDGDRhoDKappa + }; } -void -ConcreteDPM :: computeDDGDDInv(FloatMatrix &answer, - const double sig, - const double rho, - const double tempKappa) +FloatMatrixF< 2, 2 > +ConcreteDPM::computeDDGDDInv(const double sig, + const double rho, + const double tempKappa) const { //Compute dilation parameter const double R = ( sig - ft / 3. ) / fc; @@ -1499,7 +1426,7 @@ ConcreteDPM :: computeDDGDDInv(FloatMatrix &answer, const double Bl = sig / fc + rho / ( fc * sqrt(6.) ); const double Al = ( 1. - yieldHardOne ) * pow(Bl, 2.) + - sqrt(3. / 2.) * rho / fc; + sqrt(3. / 2.) * rho / fc; const double dAlDSig = 2. * ( 1. - yieldHardOne ) * Bl / fc; const double dBlDSig = 1. / fc; @@ -1519,51 +1446,46 @@ ConcreteDPM :: computeDDGDDInv(FloatMatrix &answer, const double ddgdRhodSig = dAlDSig / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) + Al / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * dBlDSig ); + FloatMatrixF< 2, 2 >answer; answer(0, 0) = ddgddSig; answer(0, 1) = ddgdSigdRho; answer(1, 0) = ddgdRhodSig; answer(1, 1) = ddgddRho; + return answer; } -void -ConcreteDPM :: computeAMatrix(FloatMatrix &answer, - const double sig, - const double rho, - const double tempKappa) +FloatMatrixF< 3, 3 > +ConcreteDPM::computeAMatrix(const double sig, + const double rho, + const double theta, + const double tempKappa, + const double deltaLambda) const { - FloatMatrix aMatrixInverse(3, 3); - FloatArray dDKappaDDeltaLambdaDInv(2); - FloatMatrix dDGDDInv(2, 2); - FloatArray dDGDInvDKappa(2); - double dDKappaDDeltaLambdaDKappa; - answer.zero(); - computeDDGDDInv(dDGDDInv, sig, rho, tempKappa); - computeDDKappaDDeltaLambdaDInv(dDKappaDDeltaLambdaDInv, sig, rho, - tempKappa); - dDKappaDDeltaLambdaDKappa = - computeDDKappaDDeltaLambdaDKappa(sig, rho, tempKappa); - computeDDGDInvDKappa(dDGDInvDKappa, sig, rho, tempKappa); - - - aMatrixInverse(0, 0) = 1. / ( kM ) + deltaLambda *dDGDDInv(0, 0); + auto dDGDDInv = computeDDGDDInv(sig, rho, tempKappa); + auto dDKappaDDeltaLambdaDInv = computeDDKappaDDeltaLambdaDInv(sig, rho, theta, tempKappa); + auto dDKappaDDeltaLambdaDKappa = computeDDKappaDDeltaLambdaDKappa(sig, rho, theta, tempKappa); + auto dDGDInvDKappa = computeDDGDInvDKappa(sig, rho, tempKappa); + + FloatMatrixF< 3, 3 >aMatrixInverse; + aMatrixInverse(0, 0) = 1. / ( kM ) + deltaLambda * dDGDDInv(0, 0); aMatrixInverse(0, 1) = deltaLambda * dDGDDInv(0, 1); - aMatrixInverse(0, 2) = deltaLambda * dDGDInvDKappa(0); + aMatrixInverse(0, 2) = deltaLambda * dDGDInvDKappa [ 0 ]; aMatrixInverse(1, 0) = deltaLambda * dDGDDInv(1, 0); - aMatrixInverse(1, 1) = 1. / ( 2. * gM ) + deltaLambda *dDGDDInv(1, 1); - aMatrixInverse(1, 2) = deltaLambda * dDGDInvDKappa(1); + aMatrixInverse(1, 1) = 1. / ( 2. * gM ) + deltaLambda * dDGDDInv(1, 1); + aMatrixInverse(1, 2) = deltaLambda * dDGDInvDKappa [ 1 ]; - aMatrixInverse(2, 0) = deltaLambda * dDKappaDDeltaLambdaDInv(0); - aMatrixInverse(2, 1) = deltaLambda * dDKappaDDeltaLambdaDInv(1); + aMatrixInverse(2, 0) = deltaLambda * dDKappaDDeltaLambdaDInv [ 0 ]; + aMatrixInverse(2, 1) = deltaLambda * dDKappaDDeltaLambdaDInv [ 1 ]; aMatrixInverse(2, 2) = -1. + deltaLambda * dDKappaDDeltaLambdaDKappa; - answer.beInverseOf(aMatrixInverse); + return inv(aMatrixInverse); } double -ConcreteDPM :: computeHardeningOne(const double kappa) const +ConcreteDPM::computeHardeningOne(const double kappa) const { if ( kappa <= 0. ) { return yieldHardInitial; @@ -1577,7 +1499,7 @@ ConcreteDPM :: computeHardeningOne(const double kappa) const double -ConcreteDPM :: computeHardeningOnePrime(const double kappa) const +ConcreteDPM::computeHardeningOnePrime(const double kappa) const { if ( kappa < 0. ) { return 3. * ( 1. - yieldHardInitial ); @@ -1588,137 +1510,128 @@ ConcreteDPM :: computeHardeningOnePrime(const double kappa) const } } -void -ConcreteDPM :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF< 6, 6 > +ConcreteDPM::give3dMaterialStiffnessMatrix(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const { - ConcreteDPMStatus *status = giveStatus(gp); - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + auto status = giveConcreteDPMStatus(gp); + auto d = this->linearElasticMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep); if ( mode == SecantStiffness || mode == TangentStiffness ) { double omega = status->giveTempDamage(); if ( omega > 0.9999 ) { omega = 0.9999; } - answer.times(1. - omega); + return d * ( 1. - omega ); + } else { + return d; } } - -void -ConcreteDPM :: computeTrialCoordinates(const FloatArray &stress, GaussPoint *gp) + +std::tuple< double, double, double > +ConcreteDPM::computeTrialCoordinates(const FloatArrayF< 6 > &stress, GaussPoint *gp) const { - FloatArray deviatoricStress; - this->computeDeviatoricVolumetricSplit(deviatoricStress, effectiveStress); - rho = computeSecondCoordinate(deviatoricStress); - thetaTrial = computeThirdCoordinate(deviatoricStress); + //auto [deviatoricStress, sig] = this->computeDeviatoricVolumetricSplit(stress); // c++17 + auto tmp = this->computeDeviatoricVolumetricSplit(stress); + auto deviatoricStress = tmp.first; + double sig = tmp.second; + double rho = computeSecondCoordinate(deviatoricStress); + double thetaTrial = computeThirdCoordinate(deviatoricStress); + return std::tuple< double, double, double > { + sig, rho, thetaTrial + }; } void -ConcreteDPM :: assignStateFlag(GaussPoint *gp) +ConcreteDPM::assignStateFlag(GaussPoint *gp) const { - ConcreteDPMStatus *status = giveStatus(gp); + auto status = giveConcreteDPMStatus(gp); //Get kappaD from status to define state later on - damage = status->giveDamage(); - tempDamage = status->giveTempDamage(); - kappaP = status->giveKappaP(); - tempKappaP = status->giveTempKappaP(); + const auto &damage = status->giveDamage(); + const auto &tempDamage = status->giveTempDamage(); + const auto &kappaP = status->giveKappaP(); + const auto &tempKappaP = status->giveTempKappaP(); if ( tempKappaP > kappaP ) { if ( tempDamage > damage ) { status-> - letTempStateFlagBe(ConcreteDPMStatus :: ConcreteDPM_PlasticDamage); + letTempStateFlagBe(ConcreteDPMStatus::ConcreteDPM_PlasticDamage); } else { - status->letTempStateFlagBe(ConcreteDPMStatus :: ConcreteDPM_Plastic); + status->letTempStateFlagBe(ConcreteDPMStatus::ConcreteDPM_Plastic); } } else { const int state_flag = status->giveStateFlag(); - if ( state_flag == ConcreteDPMStatus :: ConcreteDPM_Elastic ) { + if ( state_flag == ConcreteDPMStatus::ConcreteDPM_Elastic ) { if ( tempDamage > damage ) { status-> - letTempStateFlagBe(ConcreteDPMStatus :: ConcreteDPM_Damage); + letTempStateFlagBe(ConcreteDPMStatus::ConcreteDPM_Damage); } else { status-> - letTempStateFlagBe(ConcreteDPMStatus :: ConcreteDPM_Elastic); + letTempStateFlagBe(ConcreteDPMStatus::ConcreteDPM_Elastic); } } else { if ( tempDamage > damage ) { status-> - letTempStateFlagBe(ConcreteDPMStatus :: ConcreteDPM_Damage); + letTempStateFlagBe(ConcreteDPMStatus::ConcreteDPM_Damage); } else { status-> - letTempStateFlagBe(ConcreteDPMStatus :: ConcreteDPM_Unloading); + letTempStateFlagBe(ConcreteDPMStatus::ConcreteDPM_Unloading); } } } } -void -ConcreteDPM :: computeDRhoDStress(FloatArray &answer, - const FloatArray &stress) const +FloatArrayF< 6 > +ConcreteDPM::computeDRhoDStress(const FloatArrayF< 6 > &stress) const { - int size = 6; //compute volumetric deviatoric split - FloatArray deviatoricStress; - this->computeDeviatoricVolumetricSplit(deviatoricStress, stress); + auto deviatoricStress = this->computeDeviator(stress); double rho = computeSecondCoordinate(deviatoricStress); //compute the derivative of J2 with respect to the stress - FloatArray dJ2DStress; - dJ2DStress = deviatoricStress; - for ( int i = 3; i < size; i++ ) { - dJ2DStress(i) = deviatoricStress(i) * 2.0; + auto dJ2DStress = deviatoricStress; + for ( int i = 3; i < 6; i++ ) { + dJ2DStress [ i ] = deviatoricStress [ i ] * 2.0; } //compute the derivative of rho with respect to stress - FloatArray dRhoDStress; - dRhoDStress = dJ2DStress; - dRhoDStress.times(1. / rho); - - answer = dRhoDStress; + auto dRhoDStress = dJ2DStress * ( 1. / rho ); + return dRhoDStress; } void -ConcreteDPM :: computeDSigDStress(FloatArray &answer) const +ConcreteDPM::computeDSigDStress(FloatArrayF< 6 > &answer) const { int size = 6; for ( int i = 0; i < 3; i++ ) { - answer(i) = 1. / 3.; + answer [ i ] = 1. / 3.; } for ( int i = 3; i < size; i++ ) { - answer(i) = 0.; + answer [ i ] = 0.; } } -void -ConcreteDPM :: computeDDRhoDDStress(FloatMatrix &answer, - const FloatArray &stress) const - +FloatMatrixF< 6, 6 > +ConcreteDPM::computeDDRhoDDStress(const FloatArrayF< 6 > &stress) const { - int size = 6; - //compute volumetric deviatoric split - FloatArray deviatoricStress; - this->computeDeviatoricVolumetricSplit(deviatoricStress, stress); + auto deviatoricStress = this->computeDeviator(stress); double rho = computeSecondCoordinate(deviatoricStress); - //compute first derivative of J2 - FloatArray dJ2dstress; - dJ2dstress = deviatoricStress; - for ( int i = 3; i < deviatoricStress.giveSize(); i++ ) { - dJ2dstress(i) = deviatoricStress(i) * 2.; + auto dJ2dstress = deviatoricStress; + for ( int i = 3; i < 6; i++ ) { + dJ2dstress [ i ] = deviatoricStress [ i ] * 2.; } //compute second derivative of J2 - FloatMatrix ddJ2ddstress(size, size); - ddJ2ddstress.zero(); - for ( int i = 0; i < size; i++ ) { + FloatMatrixF< 6, 6 >ddJ2ddstress; + for ( int i = 0; i < 6; i++ ) { if ( i < 3 ) { ddJ2ddstress(i, i) = 2. / 3.; } @@ -1736,94 +1649,100 @@ ConcreteDPM :: computeDDRhoDDStress(FloatMatrix &answer, ddJ2ddstress(2, 1) = -1. / 3.; //compute square of the first derivative of J2 - FloatMatrix dJ2DJ2(size, size); - for ( int v = 0; v < size; v++ ) { - for ( int w = 0; w < size; ++w ) { - dJ2DJ2(v, w) = dJ2dstress(v) * dJ2dstress(w); - } - } + auto dJ2DJ2 = dyad(dJ2dstress, dJ2dstress); //compute the second derivative of rho - FloatMatrix ddRhoddStress; - ddRhoddStress = ddJ2ddstress; - ddRhoddStress.times(1. / rho); - FloatMatrix help1; - help1 = dJ2DJ2; - help1.times( -1. / ( rho * rho * rho ) ); - ddRhoddStress.add(help1); - answer = ddRhoddStress; + auto ddRhoddStress = ddJ2ddstress * ( 1. / rho ) + dJ2DJ2 * ( -1. / ( rho * rho * rho ) ); + return ddRhoddStress; } -void -ConcreteDPM :: computeDCosThetaDStress(FloatArray &answer, - const FloatArray &stress) const +FloatArrayF< 6 > +ConcreteDPM::computeDCosThetaDStress(const FloatArrayF< 6 > &stress) const { - int size = stress.giveSize(); - //compute volumetric deviatoric split - FloatArray deviatoricStress; - this->computeDeviatoricVolumetricSplit(deviatoricStress, stress); + auto deviatoricStress = computeDeviator(stress); //compute the coordinates double rho = computeSecondCoordinate(deviatoricStress); //compute principal stresses and directions - FloatArray principalDeviatoricStress; - FloatMatrix principalDir; - computePrincipalValDir(principalDeviatoricStress, principalDir, deviatoricStress, principal_stress); + //auto [principalDeviatoricStress, principalDir] = computePrincipalValDir(from_voigt_stress(deviatoricStress)); // c++17 + auto tmp = computePrincipalValDir(from_voigt_stress(deviatoricStress) ); + auto principalDeviatoricStress = tmp.first; + auto principalDir = tmp.second; //compute the derivative of s1 with respect to the cartesian stress - FloatArray ds1DStress(size); - ds1DStress(0) = principalDir(0, 0) * principalDir(0, 0) - 1. / 3.; - ds1DStress(1) = principalDir(1, 0) * principalDir(1, 0) - 1. / 3.; - ds1DStress(2) = principalDir(2, 0) * principalDir(2, 0) - 1. / 3.; - ds1DStress(3) = 2. * principalDir(1, 0) * principalDir(2, 0); - ds1DStress(4) = 2. * principalDir(2, 0) * principalDir(0, 0); - ds1DStress(5) = 2. * principalDir(0, 0) * principalDir(1, 0); + FloatArrayF< 6 >ds1DStress; + ds1DStress [ 0 ] = principalDir(0, 0) * principalDir(0, 0) - 1. / 3.; + ds1DStress [ 1 ] = principalDir(1, 0) * principalDir(1, 0) - 1. / 3.; + ds1DStress [ 2 ] = principalDir(2, 0) * principalDir(2, 0) - 1. / 3.; + ds1DStress [ 3 ] = 2. * principalDir(1, 0) * principalDir(2, 0); + ds1DStress [ 4 ] = 2. * principalDir(2, 0) * principalDir(0, 0); + ds1DStress [ 5 ] = 2. * principalDir(0, 0) * principalDir(1, 0); //compute dCosThetaDStress - FloatArray dCosThetaDStress; - dCosThetaDStress = ds1DStress; - dCosThetaDStress.times( sqrt(3. / 2.) * rho / pow(rho, 2.) ); - FloatArray help(size); - computeDRhoDStress(help, stress); - help.times( -sqrt(3. / 2.) * principalDeviatoricStress(0) / pow(rho, 2.) ); - dCosThetaDStress.add(help); - answer = dCosThetaDStress; + auto dCosThetaDStress = ds1DStress * ( sqrt(3. / 2.) * rho / pow(rho, 2.) ) + + computeDRhoDStress(stress) * ( -sqrt(3. / 2.) * principalDeviatoricStress [ 0 ] / pow(rho, 2.) ); + return dCosThetaDStress; } double -ConcreteDPM :: computeDRDCosTheta(const double theta, const double ecc) const +ConcreteDPM::computeDRDCosTheta(const double theta, const double ecc) const { double ACostheta = 4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) + - ( 2. * ecc - 1. ) * ( 2. * ecc - 1. ); + ( 2. * ecc - 1. ) * ( 2. * ecc - 1. ); double BCostheta = 2. * ( 1. - ecc * ecc ) * cos(theta) + - ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) - + 5. * ecc * ecc - 4. * ecc); + ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) + + 5. * ecc * ecc - 4. * ecc); double A1Costheta = 8. * ( 1. - pow(ecc, 2.) ) * cos(theta); double B1Costheta = 2. * ( 1. - pow(ecc, 2.) ) + 4. * ( 2. * ecc - 1. ) * ( 1. - pow(ecc, 2.) ) * cos(theta) / - sqrt(4. * ( 1. - pow(ecc, 2.) ) * pow(cos(theta), 2.) + - 5. * pow(ecc, 2.) - 4. * ecc); + sqrt(4. * ( 1. - pow(ecc, 2.) ) * pow(cos(theta), 2.) + + 5. * pow(ecc, 2.) - 4. * ecc); double dRDCostheta = A1Costheta / BCostheta - ACostheta / pow(BCostheta, 2.) * B1Costheta; return dRDCostheta; } + +void +ConcreteDPM::restoreConsistency(GaussPoint *gp) +{ + auto status = giveConcreteDPMStatus(gp); + + // compute kappaD from damage + double kappaD = this->computeInverseDamage(status->giveDamage(), gp); + status->letKappaDBe(kappaD); + status->letEquivStrainBe(kappaD); + + const auto &damage = status->giveDamage(); + + // compute plastic strain + // such that the given stress is obtained at zero total strain and given damage + if ( damage < 1. ) { + FloatArrayF< 6 >effectiveStress = status->giveStressVector(); + effectiveStress *= -1. / ( 1. - damage ); + auto D = this->give3dMaterialStiffnessMatrix(ElasticStiffness, gp, nullptr); + auto plasticStrain = solve(D, effectiveStress); + status->letPlasticStrainBe(plasticStrain); + } +} + + int -ConcreteDPM :: setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type) +ConcreteDPM::setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type) { - ConcreteDPMStatus *status = giveStatus(gp); + auto status = giveConcreteDPMStatus(gp); if ( status->setIPValue(value, type) ) { return 1; } else { - return StructuralMaterial :: setIPValue(value, gp, type); + return StructuralMaterial::setIPValue(value, gp, type); } } int -ConcreteDPM :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +ConcreteDPM::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - const ConcreteDPMStatus *status = giveStatus(gp); + const auto status = giveConcreteDPMStatus(gp); //int state_flag = status->giveStateFlag(); //double stateFlagValue = 0.; @@ -1862,14 +1781,165 @@ ConcreteDPM :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType return 1; } - return StructuralMaterial :: giveIPValue(answer, gp, type, tStep); + return StructuralMaterial::giveIPValue(answer, gp, type, tStep); } MaterialStatus * -ConcreteDPM :: CreateStatus(GaussPoint *gp) const +ConcreteDPM::CreateStatus(GaussPoint *gp) const { - ConcreteDPMStatus *status = - new ConcreteDPMStatus(1, StructuralMaterial :: giveDomain(), gp); - return status; + return new ConcreteDPMStatus(gp); } + +void +ConcreteDPM::saveContext(DataStream &stream, ContextMode mode) +{ + StructuralMaterial::saveContext(stream, mode); + if ( ( mode & CM_Definition ) ) { + if ( !stream.write(fc) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(ft) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(ecc) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(AHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(BHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(CHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(DHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(ASoft) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(yieldHardInitial) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(dilationConst) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(m) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(mQ) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(helem) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(eM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(gM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(kM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(nu) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(ef) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(yieldTol) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(newtonIter) ) { + THROW_CIOERR(CIO_IOERR); + } + #ifdef SOPHISTICATED_SIZEDEPENDENT_ADJUSTMENT + if ( !stream.write(href) ) { + THROW_CIOERR(CIO_IOERR); + } + #endif + } + linearElasticMaterial.saveContext(stream, mode); +} + +void +ConcreteDPM::restoreContext(DataStream &stream, ContextMode mode) +{ + StructuralMaterial::restoreContext(stream, mode); + if ( ( mode & CM_Definition ) ) { + if ( !stream.read(fc) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(ft) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(ecc) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(AHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(BHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(CHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(DHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(ASoft) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(yieldHardInitial) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(dilationConst) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(m) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(mQ) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(helem) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(eM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(gM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(kM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(nu) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(ef) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(yieldTol) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(newtonIter) ) { + THROW_CIOERR(CIO_IOERR); + } + #ifdef SOPHISTICATED_SIZEDEPENDENT_ADJUSTMENT + if ( !stream.read(href) ) { + THROW_CIOERR(CIO_IOERR); + } + #endif + } + + linearElasticMaterial.restoreContext(stream, mode); +} + + + + } // end namespace oofem diff --git a/src/sm/Materials/ConcreteMaterials/concretedpm.h b/src/sm/Materials/ConcreteMaterials/concretedpm.h index 305ce009e..5730a2e63 100644 --- a/src/sm/Materials/ConcreteMaterials/concretedpm.h +++ b/src/sm/Materials/ConcreteMaterials/concretedpm.h @@ -35,12 +35,12 @@ #ifndef ConcreteDPM_h #define ConcreteDPM_h -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "floatarray.h" #include "floatmatrix.h" #include "cltypes.h" -#include "../sm/Materials/structuralms.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "gausspoint.h" #include "mathfem.h" @@ -90,78 +90,83 @@ class ConcreteDPMStatus : public StructuralMaterialStatus ConcreteDPM_VertexTensionDamage }; + enum Concrete_VertexType { + VT_Regular, + VT_Tension, + VT_Compression + }; + protected: /// @name History variables of the plasticity model //@{ - FloatArray plasticStrain; - FloatArray tempPlasticStrain; + FloatArrayF< 6 >plasticStrain; + FloatArrayF< 6 >tempPlasticStrain; - double tempVolumetricPlasticStrain; + double tempVolumetricPlasticStrain = 0.; - double dFDKappa; - double deltaLambda; + double dFDKappa = 0.; + double deltaLambda = 0.; //@} /// @name Hardening variable //@{ - double kappaP; - double tempKappaP; + double kappaP = 0.; + double tempKappaP = 0.; //@} - double le; + double le = 0.; /// @name History variables of the damage model //@{ - double equivStrain; - double tempEquivStrain; + double equivStrain = 0.; + double tempEquivStrain = 0.; - double kappaD; - double tempKappaD; + double kappaD = 0.; + double tempKappaD = 0.; - double damage; - double tempDamage; + double damage = 0.; + double tempDamage = 0.; - double deltaEquivStrain; + double deltaEquivStrain = 0.; //@} /// @name Indicates the state (i.e. elastic, unloading, plastic, damage, vertex) of the Gauss point //@{ - int state_flag; - int temp_state_flag; + int state_flag = ConcreteDPM_Elastic; + int temp_state_flag = ConcreteDPM_Elastic; //@} + int vertexType = ConcreteDPMStatus::VT_Regular; + int tempVertexType = ConcreteDPMStatus::VT_Regular; + + #ifdef SOPHISTICATED_SIZEDEPENDENT_ADJUSTMENT /// @name History variable of the modified size-dependent adjustment /// (indicating value of omega*ft/E+kappaD at the onset of localization) - double epsloc; - double tempEpsloc; + double epsloc = -1.; + double tempEpsloc = -1.; #endif public: /// Constructor. - ConcreteDPMStatus(int n, Domain * d, GaussPoint * gp); + ConcreteDPMStatus(GaussPoint *gp); - /// Destructor. - virtual ~ConcreteDPMStatus(); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; int setIPValue(const FloatArray &value, InternalStateType type); - virtual void restoreConsistency(); - virtual const char *giveClassName() const { return "ConcreteDPMStatus"; } + const char *giveClassName() const override { return "ConcreteDPMStatus"; } /** * Get the plastic strain deviator from the material status. * @return Plastic strain deviator. */ - const FloatArray &givePlasticStrain() const { return plasticStrain; } - + const FloatArrayF< 6 > &givePlasticStrain() const { return plasticStrain; } /** * Get the deviatoric plastic strain norm from the material status. @@ -169,19 +174,16 @@ class ConcreteDPMStatus : public StructuralMaterialStatus */ double giveDeviatoricPlasticStrainNorm() { - FloatArray dev; - StructuralMaterial :: computeDeviatoricVolumetricSplit(dev, plasticStrain); - return sqrt( .5 * ( 2. * dev [ 0 ] * dev [ 0 ] + 2. * dev [ 1 ] * dev [ 1 ] + 2. * dev [ 2 ] * dev [ 2 ] + - dev [ 3 ] * dev [ 3 ] + dev [ 4 ] * dev [ 4 ] + dev [ 5 ] * dev [ 5 ] ) ); + auto dev = StructuralMaterial::computeDeviator(plasticStrain); + return sqrt(.5 * ( 2. * dev [ 0 ] * dev [ 0 ] + 2. * dev [ 1 ] * dev [ 1 ] + 2. * dev [ 2 ] * dev [ 2 ] + + dev [ 3 ] * dev [ 3 ] + dev [ 4 ] * dev [ 4 ] + dev [ 5 ] * dev [ 5 ] ) ); } - double giveVolumetricPlasticStrain() const { - return 1. / 3. * ( plasticStrain(0) + plasticStrain(1) + plasticStrain(2) ); + return 1. / 3. * ( plasticStrain [ 0 ] + plasticStrain [ 1 ] + plasticStrain [ 2 ] ); } - /** * Get the hardening variable of the plasticity model. * @return The hardening variable of the plasticity model. @@ -236,7 +238,7 @@ class ConcreteDPMStatus : public StructuralMaterialStatus * Get the temp value of the full plastic strain vector from the material status. * @return Temp value of plastic strain vector. */ - const FloatArray &giveTempPlasticStrain() const { return tempPlasticStrain; } + const FloatArrayF< 6 > &giveTempPlasticStrain() const { return tempPlasticStrain; } /** * Get the temp value of the volumetric plastic strain in plane stress. @@ -281,11 +283,17 @@ class ConcreteDPMStatus : public StructuralMaterialStatus */ int giveTempStateFlag() const { return temp_state_flag; } + int giveTempVertexType() const { return tempVertexType; } + /** * Assign the temp value of deviatoric plastic strain. * @param v New temp value of deviatoric plastic strain. */ - void letTempPlasticStrainBe(const FloatArray &v) { tempPlasticStrain = v; } + void letTempPlasticStrainBe(const FloatArrayF< 6 > &v) { tempPlasticStrain = v; } + /** + * Assigns converged value (only to be used when restoring consistency) + */ + void letPlasticStrainBe(const FloatArrayF< 6 > &v) { plasticStrain = v; } /** * Assign the value of deviatoric plastic strain. @@ -313,12 +321,19 @@ class ConcreteDPMStatus : public StructuralMaterialStatus * @param v New temp value of the hardening variable. */ void letTempKappaDBe(double v) { tempKappaD = v; } - + /** + * Assigns converged value (only to be used when restoring consistency) + */ + void letKappaDBe(double v) { kappaD = v; } /** * Assign the temp value of the hardening variable of the damage model. * @param v New temp value of the hardening variable. */ void letTempEquivStrainBe(double v) { tempEquivStrain = v; } + /** + * Assigns converged value (only to be used when restoring consistency) + */ + void letEquivStrainBe(double v) { equivStrain = v; } /** * Assign the temp value of the damage variable of the damage model. @@ -349,6 +364,8 @@ class ConcreteDPMStatus : public StructuralMaterialStatus * vertex case yielding). */ void letTempStateFlagBe(int v) { temp_state_flag = v; } + + void letTempVertexTypeBe(const int type) { tempVertexType = type; } }; @@ -365,120 +382,114 @@ class ConcreteDPMStatus : public StructuralMaterialStatus class ConcreteDPM : public StructuralMaterial { protected: - enum Concrete_VertexType { VT_Regular, VT_Tension, VT_Compression }; - Concrete_VertexType vertexType; + // enum Concrete_VertexType { VT_Regular, VT_Tension, VT_Compression }; + // mutable Concrete_VertexType vertexType; /// FIXME: This must be removed, material models must never have mutable state. + + /// Linear elastic material + IsotropicLinearElasticMaterial linearElasticMaterial; /** * Parameters of the yield surface of the plasticity model. fc is the uniaxial compressive strength, ft the uniaxial tensile strength and ecc controls the out of roundness of the deviatoric section. */ - double fc, ft, ecc; + double fc = 0., ft = 0., ecc = 0.; /// Parameter of the ductilityMeasure of the plasticity model. - double AHard; + double AHard = 0.; /// Parameter of the ductilityMeasure of the plasticity model. - double BHard; + double BHard = 0.; /// Parameter of the ductilityMeasure of the plasticity model. - double CHard; + double CHard = 0.; /// Parameter of the ductilityMeasure of the plasticity model. - double DHard; + double DHard = 0.; /// Parameter of the ductilityMeasure of the damage model. - double ASoft; + double ASoft = 0.; /// Parameter of the hardening law of the plasticity model. - double yieldHardInitial; + double yieldHardInitial = 0.; /// Control parameter for te volumetric plastic flow of the plastic potential. - double dilationConst; + double dilationConst = 0.; /// Plastic multiplier of the plasticity model. - double deltaLambda; + //double deltaLambda = 0.; /// the volumetric stress. - double sig; + //double sig = 0.; /// The length of the deviatoric stress. - double rho; + //double rho = 0.; /// The lode angle of the trial stress. - double thetaTrial; + // double thetaTrial = 0.; /// The friction parameter of the yield surface. - double m; + double m = 0.; /// The dilation parameter of the plastic potential. - double mQ; + double mQ = 0.; /// Element size (to be used in fracture energy approach (crack band). - double helem; - - /// Pointer for linear elastic material - LinearElasticMaterial *linearElasticMaterial; + double helem = 0.; /// Elastic Young's modulus. - double eM; + double eM = 0.; /// Elastic shear modulus. - double gM; + double gM = 0.; /// Elastic bulk modulus. - double kM; + double kM = 0.; /// Elastic Poisson's ration. - double nu; + double nu = 0.; /// Hardening variable of plasticity model. - double kappaP; - double tempKappaP; + //double kappaP = 0.; + //double tempKappaP = 0.; /// Hardening variable of damage model. - double kappaD; - double tempKappaD; + //double kappaD = 0.; + //double tempKappaD = 0.; /// Damage variable of damage model. - double damage; - double tempDamage; + //double damage = 0.; + //double tempDamage = 0.; /// Control parameter for the exponential softening law. - double ef; + double ef = 0.; /// Yield tolerance for the plasticity model. - double yieldTol; + double yieldTol = 0.; /// Maximum number of iterations for stress return. - int newtonIter; + int newtonIter = 0; /// Stress and its deviatoric part. - FloatArray effectiveStress; + //FloatArray effectiveStress; #ifdef SOPHISTICATED_SIZEDEPENDENT_ADJUSTMENT /// Material parameter of the size-dependent adjustment /// (reference element size) - double href; + double href = 0.; #endif public: /// Constructor - ConcreteDPM(int n, Domain * d); - /// Destructor - virtual ~ConcreteDPM(); + ConcreteDPM(int n, Domain *d); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveClassName() const { return "ConcreteDPM"; } - virtual const char *giveInputRecordName() const { return _IFT_ConcreteDPM_Name; } + const char *giveClassName() const override { return "ConcreteDPM"; } + const char *giveInputRecordName() const override { return _IFT_ConcreteDPM_Name; } - virtual ConcreteDPMStatus *giveStatus(GaussPoint *gp) const - { return static_cast< ConcreteDPMStatus * >( this->Material :: giveStatus(gp) ); } + ConcreteDPMStatus *giveConcreteDPMStatus(GaussPoint *gp) const + { return static_cast< ConcreteDPMStatus * >( this->Material::giveStatus(gp) ); } - LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } - - virtual void giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &reducedStrain, - TimeStep *tStep); + FloatArrayF< 6 >giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, + TimeStep *tStep) const override; /** * @param gp Gauss point. * @param strain Strain vector of this Gauss point. */ - void performPlasticityReturn(GaussPoint *gp, FloatArray &strain); + void performPlasticityReturn(GaussPoint *gp, FloatArrayF< 6 > &strain) const; /** * Check if the trial stress state falls within the vertex region of the plasticity model at the apex of triaxial extension or triaxial compression. @@ -488,17 +499,20 @@ class ConcreteDPM : public StructuralMaterial * @param tempKappa The hardening variable. */ - bool checkForVertexCase(double &answer, + void checkForVertexCase(double &answer, double sig, - double tempKappa); + double tempKappa, + GaussPoint *gp) const; /** * Perform regular stress return for the plasticity model, i.e. if the trial stress state does not lie in the vertex region. * @param stress Stress vector which is computed. * @param gp Gauss point. + * @param theta Lode angle of the stress state. */ - void performRegularReturn(FloatArray &stress, - GaussPoint *gp); + void performRegularReturn(FloatArrayF< 6 > &stress, + GaussPoint *gp, + double theta) const; /** @@ -507,9 +521,9 @@ class ConcreteDPM : public StructuralMaterial * @param apexStress Volumetric stress at the apex of the yield surface. * @param gp Gauss point. */ - void performVertexReturn(FloatArray &stress, + void performVertexReturn(FloatArrayF< 6 > &stress, double apexStress, - GaussPoint *gp); + GaussPoint *gp) const; /** * Compute the yield value based on stress and hardening variable. @@ -546,24 +560,28 @@ class ConcreteDPM : public StructuralMaterial * variable based on the stress state and the hardening variable. * @param sig Volumetric stress. * @param rho Deviatoric length. + * @param theta Lode angle of the stress state. * @param tempKappa Hardening variable. * @return The derivative of the yield surface. */ double computeDFDKappa(double sig, double rho, - double tempKappa); + double theta, + double tempKappa) const; /** * Compute the derivative of kappa with respect of delta * lambda based on the stress state and the hardening variable. * @param sig Volumetric stress. * @param rho Length of the deviatoric stress. + * @param theta Lode angle of the stress state. * @param tempKappa Hardening variable. * @return Derivative of kappa with respect to delta lambda. */ double computeDKappaDDeltaLambda(double sig, double rho, - double tempKappa); + double theta, + double tempKappa) const; /** * Compute the ductility measure based on the stress state. @@ -574,35 +592,35 @@ class ConcreteDPM : public StructuralMaterial */ virtual double computeDuctilityMeasure(double sig, double rho, - double theta); + double theta) const; /** * Computes the first derivative of the ductility measure with respect to * the invariants sig and rho based on the stress state and the hardening parameter. */ - void computeDDuctilityMeasureDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa); + FloatArrayF< 2 >computeDDuctilityMeasureDInv(double sig, + double rho, + double theta, + double tempKappa) const; /** * This matrix is the core of the closest point projection and collects * the derivative of the flow rule and the hardening parameters. */ - void computeAMatrix(FloatMatrix &answer, - double sig, - double rho, - double tempKappa); + FloatMatrixF< 3, 3 >computeAMatrix(double sig, + double rho, + double theta, + double tempKappa, + double deltaLambda) const; /** * Here, the first derivative of the plastic potential with respect * to the invariants sig and rho are computed. */ - void computeDGDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa); + FloatArrayF< 2 >computeDGDInv(double sig, + double rho, + double tempKappa) const; /** * This function computes the ratio of the volumetric and deviatoric component @@ -610,35 +628,33 @@ class ConcreteDPM : public StructuralMaterial * if the vertex return is admissible. */ double computeRatioPotential(double sig, - double tempKappa); + double tempKappa) const; /** * Here, the second derivative of the plastic potential with respect to the * invariants sig and rho are computed. */ - void computeDDGDDInv(FloatMatrix &answer, - double sig, - double rho, - double tempKappa); + FloatMatrixF< 2, 2 >computeDDGDDInv(double sig, + double rho, + double tempKappa) const; /** * Here, the mixed derivative of the plastic potential with respect * to the invariants and the hardening parameter are determined. */ - void computeDDGDInvDKappa(FloatArray &answer, - double sig, - double rho, - double tempKappa); + FloatArrayF< 2 >computeDDGDInvDKappa(double sig, + double rho, + double tempKappa) const; /** * Computes the mixed derivative of the hardening parameter kappa with * respect to the plastic multiplier delta Lambda and the invariants sig * and rho. */ - void computeDDKappaDDeltaLambdaDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa); + FloatArrayF< 2 >computeDDKappaDDeltaLambdaDInv(double sig, + double rho, + double theta, + double tempKappa) const; /** * Computes the derivative of the evolution law of the hardening @@ -646,17 +662,18 @@ class ConcreteDPM : public StructuralMaterial */ double computeDDKappaDDeltaLambdaDKappa(double sig, double rho, - double tempKappa); + double theta, + double tempKappa) const; /** * Computes the derivative of the yield surface with respect to the * invariants sig and rho. */ - void computeDFDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa) const; + FloatArrayF< 2 >computeDFDInv(double sig, + double rho, + double theta, + double tempKappa) const; /** * Compute temporary kappa. @@ -664,8 +681,7 @@ class ConcreteDPM : public StructuralMaterial double computeTempKappa(double kappaInitial, double sigTrial, double rhoTrial, - double sig); - + double sig) const; /** * Perform stress return for the damage model, i.e. if the trial stress state does not violate the plasticity surface. @@ -674,67 +690,67 @@ class ConcreteDPM : public StructuralMaterial * @param tStep Time step. * @return Damage. */ - double computeDamage(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - - + std::pair< double, double >computeDamage(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const; /// Compute damage parameter. - virtual double computeDamageParam(double kappa, GaussPoint *gp); + virtual double computeDamageParam(double kappa, GaussPoint *gp) const; /// Compute the damage-driving variable from given damage. - double computeInverseDamage(double dam, GaussPoint *gp); + double computeInverseDamage(double dam, GaussPoint *gp) const; /// Compute equivalent strain value. - virtual void computeEquivalentStrain(double &kappaD, const FloatArray &elasticStrain, GaussPoint *gp, TimeStep *tStep); - + virtual double computeEquivalentStrain(const FloatArrayF< 6 > &elasticStrain, GaussPoint *gp, TimeStep *tStep) const; /// Compute the ductility measure for the damage model. - double computeDuctilityMeasureDamage(const FloatArray &strain, GaussPoint *gp); + double computeDuctilityMeasureDamage(const FloatArrayF< 6 > &strain, GaussPoint *gp) const; /** * Initialize the characteristic length, if damage is not yet activated. */ void initDamaged(double kappa, - const FloatArray &elasticStrain, - GaussPoint *gp); + const FloatArrayF< 6 > &elasticStrain, + GaussPoint *gp) const; /// Compute the trial coordinates. - void computeTrialCoordinates(const FloatArray &stress, GaussPoint *gp); + std::tuple< double, double, double >computeTrialCoordinates(const FloatArrayF< 6 > &stress, GaussPoint *gp) const; /// Assign state flag. - void assignStateFlag(GaussPoint *gp); + void assignStateFlag(GaussPoint *gp) const; /// Computes the derivative of rho with respect to the stress. - void computeDRhoDStress(FloatArray &answer, const FloatArray &stress) const; + FloatArrayF< 6 >computeDRhoDStress(const FloatArrayF< 6 > &stress) const; /// Computes the derivative of sig with respect to the stress. - void computeDSigDStress(FloatArray &answer) const; + void computeDSigDStress(FloatArrayF< 6 > &answer) const; /// Computes the second derivative of rho with the respect to the stress. - void computeDDRhoDDStress(FloatMatrix &answer, const FloatArray &stress) const; + FloatMatrixF< 6, 6 >computeDDRhoDDStress(const FloatArrayF< 6 > &stress) const; /// Computes the derivative of costheta with respect to the stress. - void computeDCosThetaDStress(FloatArray &answer, const FloatArray &stress) const; + FloatArrayF< 6 >computeDCosThetaDStress(const FloatArrayF< 6 > &stress) const; /// Compute the derivative of R with respect to costheta. double computeDRDCosTheta(double theta, double ecc) const; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF< 6, 6 >give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + int setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type) override; - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } + int giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *tStep) override; - virtual int setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type); + void restoreConsistency(GaussPoint *gp) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual int giveIPValue(FloatArray &answer, - GaussPoint *gp, - InternalStateType type, - TimeStep *tStep); protected: - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; }; } // end namespace oofem #endif diff --git a/src/sm/Materials/ConcreteMaterials/concretedpm2.C b/src/sm/Materials/ConcreteMaterials/concretedpm2.C index aacc1cc3d..ad88833a2 100644 --- a/src/sm/Materials/ConcreteMaterials/concretedpm2.C +++ b/src/sm/Materials/ConcreteMaterials/concretedpm2.C @@ -35,2885 +35,3066 @@ #include "concretedpm2.h" #include "floatarray.h" #include "floatmatrix.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "gausspoint.h" #include "intarray.h" #include "datastream.h" #include "contextioerr.h" #include "timestep.h" -#include "../sm/Materials/structuralmaterial.h" -#include "Materials/isolinearelasticmaterial.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "mathfem.h" #include "classfactory.h" #include namespace oofem { -REGISTER_Material(ConcreteDPM2); + REGISTER_Material(ConcreteDPM2); -ConcreteDPM2Status :: ConcreteDPM2Status(int n, Domain *d, GaussPoint *gp) : - StructuralMaterialStatus(n, d, gp), - plasticStrain(6), - tempPlasticStrain(6) -{ - strainVector.resize(6); - stressVector.resize(6); - tempStressVector = stressVector; - tempStrainVector = strainVector; + ConcreteDPM2Status::ConcreteDPM2Status(GaussPoint *gp) : + StructuralMaterialStatus(gp) + { + strainVector.resize(6); + tempStrainVector.resize(6); + stressVector.resize(6); + tempStressVector.resize(6); + } + + void + ConcreteDPM2Status::initTempStatus() + { + // Call the function of the parent class to initialize the variables defined there. + StructuralMaterialStatus::initTempStatus(); + + tempReducedStrain = reducedStrain; + tempPlasticStrain = plasticStrain; + + tempKappaP = kappaP; + tempAlpha = alpha; - kappaP = tempKappaP = 0.; + //Damage part + tempEquivStrain = equivStrain; - equivStrain = tempEquivStrain = 0.; - equivStrainTension = tempEquivStrainTension = 0.; - equivStrainCompression = tempEquivStrainCompression = 0; + tempEquivStrainTension = equivStrainTension; + tempEquivStrainCompression = equivStrainCompression; - kappaDTension = tempKappaDTension = 0.; - kappaDCompression = tempKappaDCompression = 0.; + tempKappaDTension = kappaDTension; + tempKappaDCompression = kappaDCompression; - kappaDTensionOne = tempKappaDTensionOne = 0.; - kappaDCompressionOne = tempKappaDCompressionOne = 0.; - kappaDTensionTwo = tempKappaDTensionTwo = 0.; - kappaDCompressionTwo = tempKappaDCompressionTwo = 0.; + tempKappaDTensionOne = kappaDTensionOne; + tempKappaDCompressionOne = kappaDCompressionOne; + tempKappaDTensionTwo = kappaDTensionTwo; + tempKappaDCompressionTwo = kappaDCompressionTwo; - alpha = tempAlpha = 0.; + tempDamageTension = damageTension; + tempDamageCompression = damageCompression; - damageTension = tempDamageTension = 0.; - damageCompression = tempDamageCompression = 0.; + temp_state_flag = state_flag; + tempRateFactor = rateFactor; + tempRateStrain = rateStrain; - deltaLambda = 0.; - state_flag = temp_state_flag = ConcreteDPM2Status :: ConcreteDPM2_Elastic; - rateFactor = 1.; - rateStrain = tempRateStrain = 0.; + this->tempDeletionFlag = this->deletionFlag; #ifdef keep_track_of_dissipated_energy - stressWork = tempStressWork = 0.0; - dissWork = tempDissWork = 0.0; + tempStressWork = stressWork; + tempDissWork = dissWork; #endif -} + } + + void + ConcreteDPM2Status::updateYourself(TimeStep *tStep) + { + // Call corresponding function of the parent class to update + // variables defined there. + StructuralMaterialStatus::updateYourself(tStep); + + // update variables defined in ConcreteDPM2Status -ConcreteDPM2Status :: ~ConcreteDPM2Status() -{ } + alpha = tempAlpha; -void -ConcreteDPM2Status :: initTempStatus() -{ - // Call the function of the parent class to initialize the variables defined there. - StructuralMaterialStatus :: initTempStatus(); + reducedStrain = tempReducedStrain; - //Plasticity part - tempPlasticStrain = plasticStrain; - tempKappaP = kappaP; + //Plasticity part + plasticStrain = tempPlasticStrain; + kappaP = tempKappaP; - tempAlpha = alpha; - //Damage part - tempEquivStrain = equivStrain; - tempEquivStrainTension = equivStrainTension; - tempEquivStrainCompression = equivStrainCompression; + //Damage part + equivStrain = tempEquivStrain; + equivStrainTension = tempEquivStrainTension; + equivStrainCompression = tempEquivStrainCompression; - tempKappaDTension = kappaDTension; - tempKappaDCompression = kappaDCompression; + kappaDTension = tempKappaDTension; + kappaDCompression = tempKappaDCompression; - tempKappaDTensionOne = kappaDTensionOne; - tempKappaDCompressionOne = kappaDCompressionOne; - tempKappaDTensionTwo = kappaDTensionTwo; - tempKappaDCompressionTwo = kappaDCompressionTwo; + kappaDTensionOne = tempKappaDTensionOne; + kappaDCompressionOne = tempKappaDCompressionOne; - tempDamageTension = damageTension; - tempDamageCompression = damageCompression; + kappaDTensionTwo = tempKappaDTensionTwo; + kappaDCompressionTwo = tempKappaDCompressionTwo; + + damageTension = tempDamageTension; + damageCompression = tempDamageCompression; + + state_flag = temp_state_flag; + + rateFactor = tempRateFactor; + + rateStrain = tempRateStrain; + + this->deletionFlag = this->tempDeletionFlag; - temp_state_flag = state_flag; - tempRateFactor = rateFactor; - tempRateStrain = rateStrain; #ifdef keep_track_of_dissipated_energy - tempStressWork = stressWork; - tempDissWork = dissWork; + stressWork = tempStressWork; + dissWork = tempDissWork; #endif -} + } + + void + ConcreteDPM2Status::printOutputAt(FILE *file, TimeStep *tStep) const + { + // Call corresponding function of the parent class to print + StructuralMaterialStatus::printOutputAt(file, tStep); + + fprintf(file, "\tstatus { "); + + // print status flag + switch ( state_flag ) { + case ConcreteDPM2Status::ConcreteDPM2_Elastic: + fprintf(file, "Elastic, "); + break; + case ConcreteDPM2Status::ConcreteDPM2_Unloading: + fprintf(file, "Unloading, "); + break; + case ConcreteDPM2Status::ConcreteDPM2_Plastic: + fprintf(file, "Plastic, "); + break; + case ConcreteDPM2Status::ConcreteDPM2_Damage: + fprintf(file, "Damage, "); + break; + case ConcreteDPM2Status::ConcreteDPM2_PlasticDamage: + fprintf(file, "PlasticDamage, "); + break; + } + + // print plastic strain vector and inelastic strain vector + auto inelasticStrainVector = ( ( FloatArrayF < 6 > ( strainVector ) - plasticStrain ) * damageTension + plasticStrain ) * le; + + fprintf(file, " reduced "); + for ( auto &val : reducedStrain ) { + fprintf(file, " %.10e", val); + } -void -ConcreteDPM2Status :: updateYourself(TimeStep *tStep) -{ - // Call corresponding function of the parent class to update - // variables defined there. - StructuralMaterialStatus :: updateYourself(tStep); + fprintf(file, " plastic "); + for ( auto &val : plasticStrain ) { + fprintf(file, " %.10e", val); + } + + fprintf(file, " inelastic "); + for ( auto &val : inelasticStrainVector ) { + fprintf(file, " %.10e", val); + } + + fprintf(file, " equivStrain %.10e,", equivStrain); - // update variables defined in ConcreteDPM2Status + fprintf(file, " kappaDTension %.10e,", kappaDTension); - alpha = tempAlpha; + fprintf(file, " kappaDCompression %.10e,", kappaDCompression); - //Plasticity part - plasticStrain = tempPlasticStrain; - kappaP = tempKappaP; + fprintf(file, " kappaP %.10e,", kappaP); - //Damage part - equivStrain = tempEquivStrain; - equivStrainTension = tempEquivStrainTension; - equivStrainCompression = tempEquivStrainCompression; + fprintf(file, " kappaDTensionOne %.10e,", kappaDTensionOne); - kappaDTension = tempKappaDTension; - kappaDCompression = tempKappaDCompression; + fprintf(file, " kappaDCompressionOne %.10e,", kappaDCompressionOne); - kappaDTensionOne = tempKappaDTensionOne; - kappaDCompressionOne = tempKappaDCompressionOne; + fprintf(file, " kappaDTensionTwo %.10e,", kappaDTensionTwo); - kappaDTensionTwo = tempKappaDTensionTwo; - kappaDCompressionTwo = tempKappaDCompressionTwo; + fprintf(file, " kappaDCompressionTwo %.10e,", kappaDCompressionTwo); - damageTension = tempDamageTension; - damageCompression = tempDamageCompression; + fprintf(file, " damageTension %.10e,", damageTension); - state_flag = temp_state_flag; + fprintf(file, " damageCompression %.10e,", damageCompression); - rateFactor = tempRateFactor; + fprintf(file, " alpha %.10e,", this->alpha); + + fprintf(file, " rateFactor %.10e,", this->rateFactor); - rateStrain = tempRateStrain; #ifdef keep_track_of_dissipated_energy - stressWork = tempStressWork; - dissWork = tempDissWork; + fprintf(file, " dissW %g, freeE %g, stressW %g ", this->dissWork, ( this->stressWork ) - ( this->dissWork ), this->stressWork); #endif -} + fprintf(file, "}\n"); + } -void -ConcreteDPM2Status :: printOutputAt(FILE *file, TimeStep *tStep) -{ - // Call corresponding function of the parent class to print - StructuralMaterialStatus :: printOutputAt(file, tStep); + void + ConcreteDPM2Status::saveContext(DataStream &stream, ContextMode mode) + { + StructuralMaterialStatus::saveContext(stream, mode); - fprintf(file, "\tstatus { "); + contextIOResultType iores; - // print status flag - switch ( state_flag ) { - case ConcreteDPM2Status :: ConcreteDPM2_Elastic: - fprintf(file, "Elastic, "); - break; - case ConcreteDPM2Status :: ConcreteDPM2_Unloading: - fprintf(file, "Unloading, "); - break; - case ConcreteDPM2Status :: ConcreteDPM2_Plastic: - fprintf(file, "Plastic, "); - break; - case ConcreteDPM2Status :: ConcreteDPM2_Damage: - fprintf(file, "Damage, "); - break; - case ConcreteDPM2Status :: ConcreteDPM2_PlasticDamage: - fprintf(file, "PlasticDamage, "); - break; - } - // print plastic strain vector and inelastic strain vector - FloatArray plasticStrainVector = this->givePlasticStrain(); - FloatArray inelasticStrainVector = strainVector; - inelasticStrainVector.subtract(plasticStrainVector); - inelasticStrainVector.times(damageTension); - inelasticStrainVector.add(plasticStrainVector); - inelasticStrainVector.times(le); + if ( ( iores = plasticStrain.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + if ( ( iores = reducedStrain.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } - fprintf(file, " plastic "); - for ( auto &val : plasticStrainVector ) { - fprintf( file, " %.10e", val ); - } - fprintf(file, " inelastic "); - for ( auto &val : inelasticStrainVector ) { - fprintf( file, " %.10e", val ); - } + if ( !stream.write(kappaP) ) { + THROW_CIOERR(CIO_IOERR); + } + + + if ( !stream.write(le) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(alpha) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(equivStrain) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(equivStrainTension) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(equivStrainCompression) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(kappaDTension) ) { + THROW_CIOERR(CIO_IOERR); + } - fprintf(file, " equivStrain %.10e,", equivStrain); + if ( !stream.write(kappaDCompression) ) { + THROW_CIOERR(CIO_IOERR); + } - fprintf(file, " kappaDTension %.10e,", kappaDTension); + if ( !stream.write(kappaDTensionOne) ) { + THROW_CIOERR(CIO_IOERR); + } - fprintf(file, " kappaDCompression %.10e,", kappaDCompression); + if ( !stream.write(kappaDCompressionOne) ) { + THROW_CIOERR(CIO_IOERR); + } - fprintf(file, " kappaP %.10e,", kappaP); + if ( !stream.write(kappaDTensionTwo) ) { + THROW_CIOERR(CIO_IOERR); + } - fprintf(file, " kappaDTensionOne %.10e,", kappaDTensionOne); + if ( !stream.write(kappaDCompressionTwo) ) { + THROW_CIOERR(CIO_IOERR); + } - fprintf(file, " kappaDCompressionOne %.10e,", kappaDCompressionOne); - fprintf(file, " kappaDTensionTwo %.10e,", kappaDTensionTwo); + if ( !stream.write(damageTension) ) { + THROW_CIOERR(CIO_IOERR); + } - fprintf(file, " kappaDCompressionTwo %.10e,", kappaDCompressionTwo); + if ( !stream.write(damageCompression) ) { + THROW_CIOERR(CIO_IOERR); + } - fprintf(file, " damageTension %.10e,", damageTension); + if ( !stream.write(deltaEquivStrain) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(rateFactor) ) { + THROW_CIOERR(CIO_IOERR); + } - fprintf(file, " damageCompression %.10e,", damageCompression); + if ( !stream.write(rateStrain) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(state_flag) ) { + THROW_CIOERR(CIO_IOERR); + } - fprintf(file, " alpha %.10e,", this->alpha); #ifdef keep_track_of_dissipated_energy - fprintf(file, " dissW %g, freeE %g, stressW %g ", this->dissWork, ( this->stressWork ) - ( this->dissWork ), this->stressWork); -#endif - fprintf(file, "}\n"); -} + if ( !stream.write(stressWork) ) { + THROW_CIOERR(CIO_IOERR); + } -contextIOResultType -ConcreteDPM2Status :: saveContext(DataStream &stream, ContextMode mode, void *obj) -{ - contextIOResultType iores; + if ( !stream.write(dissWork) ) { + THROW_CIOERR(CIO_IOERR); + } - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); +#endif } - if ( ( iores = plasticStrain.storeYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( !stream.write(kappaP) ) { - THROW_CIOERR(CIO_IOERR); - } + void + ConcreteDPM2Status::restoreContext(DataStream &stream, ContextMode mode) + { + StructuralMaterialStatus::restoreContext(stream, mode); - if ( !stream.write(deltaLambda) ) { - THROW_CIOERR(CIO_IOERR); - } + contextIOResultType iores; - if ( !stream.write(dFDKappa) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( ( iores = plasticStrain.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + if ( ( iores = reducedStrain.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } - if ( !stream.write(le) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(kappaP) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(alpha) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(le) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(equivStrainTension) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(alpha) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(equivStrainCompression) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(equivStrain) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(kappaDTension) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(equivStrainTension) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(kappaDCompression) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(equivStrainCompression) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(kappaDCompressionOne) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(kappaDTension) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(kappaDTensionTwo) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(kappaDCompression) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(kappaDCompressionTwo) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(kappaDTensionOne) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(kappaDCompressionOne) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(damageTension) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(kappaDTensionTwo) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(damageCompression) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(kappaDCompressionTwo) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(deltaEquivStrain) ) { - THROW_CIOERR(CIO_IOERR); - } - if ( !stream.write(rateFactor) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(damageTension) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(rateStrain) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(damageCompression) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(deltaEquivStrain) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(rateFactor) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(rateStrain) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(state_flag) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(state_flag) ) { - THROW_CIOERR(CIO_IOERR); - } #ifdef keep_track_of_dissipated_energy - if ( !stream.write(stressWork) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(stressWork) ) { + THROW_CIOERR(CIO_IOERR); + } - if ( !stream.write(dissWork) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( !stream.read(dissWork) ) { + THROW_CIOERR(CIO_IOERR); + } #endif - return CIO_OK; -} + } +#ifdef keep_track_of_dissipated_energy + void + ConcreteDPM2Status::computeWork(GaussPoint *gp, double gf) + { + auto tempTotalstrain = tempReducedStrain; + auto totalstrain = reducedStrain; -contextIOResultType -ConcreteDPM2Status :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -{ - contextIOResultType iores; + //Calculate increase or decrease of total strain tensor during iteration/step + auto deltaTotalStrain = tempTotalstrain - totalstrain; - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + //Ask for stress tensor at step + auto stress = tempStressVector; - // read raw data - if ( ( iores = plasticStrain.restoreYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + //Calculate increase/decrease in total work + double dSW = ( dot(tempStressVector, deltaTotalStrain) + dot(stressVector, deltaTotalStrain) ) / 2.; - if ( !stream.read(kappaP) ) { - THROW_CIOERR(CIO_IOERR); - } + double tempStressWork = this->giveTempStressWork() + dSW; - if ( !stream.read(deltaLambda) ) { - THROW_CIOERR(CIO_IOERR); - } + //Calculate temporary elastic strain + auto tempElasticStrain = tempTotalstrain - tempPlasticStrain; - if ( !stream.read(dFDKappa) ) { - THROW_CIOERR(CIO_IOERR); - } + //Calculate elastically stored energy density + double We = dot(tempStressVector, tempElasticStrain) / 2.; - if ( !stream.read(le) ) { - THROW_CIOERR(CIO_IOERR); - } + // dissipative work density + tempDissWork = tempStressWork - We; - if ( !stream.read(alpha) ) { - THROW_CIOERR(CIO_IOERR); - } + // to avoid extremely small negative dissipation due to round-off error + // (note: gf is the dissipation density at complete failure, per unit volume) + //Rough estimation of gf which is ok for this purpose - if ( !stream.read(equivStrainTension) ) { - THROW_CIOERR(CIO_IOERR); - } + if ( fabs(tempDissWork) < 1.e-12 * gf ) { + tempDissWork = 0.; + } - if ( !stream.read(equivStrainCompression) ) { - THROW_CIOERR(CIO_IOERR); + this->setTempStressWork(tempStressWork); + this->setTempDissWork(tempDissWork); } +#endif - if ( !stream.read(kappaDTension) ) { - THROW_CIOERR(CIO_IOERR); - } + // ******************************** + // *** CLASS CONCRETE DAMAGE PLASTICITY MODEL 2 *** + // ******************************** - if ( !stream.read(kappaDCompression) ) { - THROW_CIOERR(CIO_IOERR); - } +#define IDM_ITERATION_LIMIT 1.e-8 - if ( !stream.read(kappaDCompressionOne) ) { - THROW_CIOERR(CIO_IOERR); - } + ConcreteDPM2::ConcreteDPM2(int n, Domain *d) : + StructuralMaterial(n, d), + linearElasticMaterial(n, d) + {} - if ( !stream.read(kappaDTensionTwo) ) { - THROW_CIOERR(CIO_IOERR); - } - if ( !stream.read(kappaDCompressionTwo) ) { - THROW_CIOERR(CIO_IOERR); + bool + ConcreteDPM2::hasMaterialModeCapability(MaterialMode mode) const + // + // returns whether receiver supports given mode + // + { + return mode == _3dMat; } - if ( !stream.read(damageTension) ) { - THROW_CIOERR(CIO_IOERR); - } + void + ConcreteDPM2::initializeFrom(InputRecord &ir) + { + // call the corresponding service for the linear elastic material + StructuralMaterial::initializeFrom(ir); + linearElasticMaterial.initializeFrom(ir); - if ( !stream.read(damageCompression) ) { - THROW_CIOERR(CIO_IOERR); - } + //damage flag + this->damageFlag = 1; //Default value using damage in tension and compression according to IJSS CDPM2 paper. + IR_GIVE_OPTIONAL_FIELD(ir, this->damageFlag, _IFT_ConcreteDPM2_damflag); - if ( !stream.read(deltaEquivStrain) ) { - THROW_CIOERR(CIO_IOERR); - } + // elastic parameters + IR_GIVE_FIELD(ir, this->eM, _IFT_IsotropicLinearElasticMaterial_e) + IR_GIVE_FIELD(ir, this->nu, _IFT_IsotropicLinearElasticMaterial_n); + propertyDictionary.add('E', this->eM); + propertyDictionary.add('n', this->nu); - if ( !stream.read(rateFactor) ) { - THROW_CIOERR(CIO_IOERR); - } + this->gM = this->eM / ( 2. * ( 1. + this->nu ) ); + this->kM = this->eM / ( 3. * ( 1. - 2. * this->nu ) ); + + IR_GIVE_FIELD(ir, this->fc, _IFT_ConcreteDPM2_fc); + IR_GIVE_FIELD(ir, this->ft, _IFT_ConcreteDPM2_ft); + + this->e0 = this->ft / this->eM; + + // default parameters + this->ecc = 0.525; + IR_GIVE_OPTIONAL_FIELD(ir, this->ecc, _IFT_ConcreteDPM2_ecc); + this->yieldHardInitial = 0.3; + IR_GIVE_OPTIONAL_FIELD(ir, this->yieldHardInitial, _IFT_ConcreteDPM2_kinit); + + //Inclination at transition point + this->yieldHardPrimePeak = 0.5; + IR_GIVE_OPTIONAL_FIELD(ir, this->yieldHardPrimePeak, _IFT_ConcreteDPM2_hp); + + if ( this->yieldHardPrimePeak < 0 ) { + this->yieldHardPrimePeak = 0.; + OOFEM_WARNING("kPrimePeak cannot be less than zero"); + } else if ( this->yieldHardPrimePeak > ( 1. - this->yieldHardInitial ) ) { + this->yieldHardPrimePeak = 1. - this->yieldHardInitial; + OOFEM_WARNING("kPrimePeak cannot be greater than 1.-kinit"); + } + + this->AHard = 8.e-2; + IR_GIVE_OPTIONAL_FIELD(ir, this->AHard, _IFT_ConcreteDPM2_ahard); + this->BHard = 3.e-3; + IR_GIVE_OPTIONAL_FIELD(ir, this->BHard, _IFT_ConcreteDPM2_bhard); + this->CHard = 2.; + IR_GIVE_OPTIONAL_FIELD(ir, this->CHard, _IFT_ConcreteDPM2_chard); + this->DHard = 1.e-6; + IR_GIVE_OPTIONAL_FIELD(ir, this->DHard, _IFT_ConcreteDPM2_dhard); + this->dilationConst = 0.85; + IR_GIVE_OPTIONAL_FIELD(ir, this->dilationConst, _IFT_ConcreteDPM2_dilation); + + this->softeningType = 1; //0-Linear softening; 1-Bilinear softening; 2-Exponential + IR_GIVE_OPTIONAL_FIELD(ir, this->softeningType, _IFT_ConcreteDPM2_softeningType); + + if ( softeningType > 2 ) { + throw ValueInputException(ir, _IFT_ConcreteDPM2_softeningType, "softening type not implemented"); + } + + IR_GIVE_FIELD(ir, this->wf, _IFT_ConcreteDPM2_wf); + + if ( this->softeningType == 1 ) { + this->ftOne = 0.3 * this->ft; + IR_GIVE_OPTIONAL_FIELD(ir, this->ftOne, _IFT_ConcreteDPM2_ftOne); + this->wfOne = 0.15 * this->wf; + IR_GIVE_OPTIONAL_FIELD(ir, this->wfOne, _IFT_ConcreteDPM2_wfOne); + } + + this->efCompression = 100.e-6; + IR_GIVE_OPTIONAL_FIELD(ir, this->efCompression, _IFT_ConcreteDPM2_efc); + + this->ASoft = 15.; + IR_GIVE_OPTIONAL_FIELD(ir, this->ASoft, _IFT_ConcreteDPM2_asoft); + + this->BSoft = 1.; + IR_GIVE_OPTIONAL_FIELD(ir, this->BSoft, _IFT_ConcreteDPM2_bsoft); + + this->helem = 0.; + IR_GIVE_OPTIONAL_FIELD(ir, this->helem, _IFT_ConcreteDPM2_helem); - if ( !stream.read(rateStrain) ) { - THROW_CIOERR(CIO_IOERR); - } + //Compute m + m = 3. * ( pow(this->fc, 2.) - pow(this->ft, 2.) ) / ( this->fc * this->ft ) * this->ecc / ( this->ecc + 1. ); - if ( !stream.read(state_flag) ) { - THROW_CIOERR(CIO_IOERR); + //Compute default value of dilationConst + this->yieldTol = 1.e-6; + IR_GIVE_OPTIONAL_FIELD(ir, this->yieldTol, _IFT_ConcreteDPM2_yieldtol); + + this->yieldTolDamage = this->yieldTol * 10.; + + this->newtonIter = 100; + IR_GIVE_OPTIONAL_FIELD(ir, this->newtonIter, _IFT_ConcreteDPM2_newtoniter); + + this->strengthRateType = 0; + IR_GIVE_OPTIONAL_FIELD(ir, this->strengthRateType, _IFT_ConcreteDPM2_strengthratetype); + if ( this->strengthRateType < 0 || this->strengthRateType > 2 ) { + OOFEM_ERROR("strength rate type not implemented. Must be 0, 1 or 2\n"); + } + + this->deltaTime = -1.; + this->energyRateType = 0; + if ( this->strengthRateType > 0 ) { + IR_GIVE_OPTIONAL_FIELD(ir, this->deltaTime, _IFT_ConcreteDPM2_deltatime); + IR_GIVE_OPTIONAL_FIELD(ir, this->energyRateType, _IFT_ConcreteDPM2_energyratetype); + } } -#ifdef keep_track_of_dissipated_energy - if ( !stream.read(stressWork) ) { - THROW_CIOERR(CIO_IOERR); + void + ConcreteDPM2::saveContext(DataStream &stream, ContextMode mode) + { + StructuralMaterial::saveContext(stream, mode); + if ( ( mode & CM_Definition ) ) { + if ( !stream.write(fc) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(ft) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(ecc) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(damageFlag) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(e0) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(AHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(BHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(CHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(DHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(hardeningModulus) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(ASoft) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(yieldHardPrimePeak) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(yieldHardInitial) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(dilationConst) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(m) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(mQ) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(helem) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(eM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(gM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(kM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(nu) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(efCompression) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(wf) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(wfOne) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(ftOne) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(yieldTol) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(yieldTolDamage) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(newtonIter) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(softeningType) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(deltaTime) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(strengthRateType) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(energyRateType) ) { + THROW_CIOERR(CIO_IOERR); + } + } + + + linearElasticMaterial.saveContext(stream, mode); } - if ( !stream.read(dissWork) ) { - THROW_CIOERR(CIO_IOERR); + void + ConcreteDPM2::restoreContext(DataStream &stream, ContextMode mode) + { + StructuralMaterial::restoreContext(stream, mode); + if ( ( mode & CM_Definition ) ) { + if ( !stream.read(fc) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(ft) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(ecc) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(damageFlag) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(e0) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(AHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(BHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(CHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(DHard) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(hardeningModulus) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(ASoft) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(yieldHardPrimePeak) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(yieldHardInitial) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(dilationConst) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(m) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(mQ) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(helem) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(eM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(gM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(kM) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(nu) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(efCompression) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(wf) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(wfOne) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(ftOne) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(yieldTol) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(yieldTolDamage) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(newtonIter) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(softeningType) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(deltaTime) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(strengthRateType) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(energyRateType) ) { + THROW_CIOERR(CIO_IOERR); + } + } + linearElasticMaterial.restoreContext(stream, mode); } -#endif - return CIO_OK; -} -#ifdef keep_track_of_dissipated_energy -void -ConcreteDPM2Status :: computeWork(GaussPoint *gp, double gf) -{ - FloatArray tempTotalstrain = tempStrainVector; - FloatArray totalstrain = strainVector; - //Calculate increase or decrease of total strain tensor during iteration/step - FloatArray deltaTotalStrain = tempTotalstrain; - deltaTotalStrain.subtract(totalstrain); - //Ask for stress tensor at step - FloatArray stress = tempStressVector; - int n = stress.giveSize(); - //Calculate increase/decrease in total work - double dSW = ( tempStressVector.dotProduct(deltaTotalStrain, n) + stressVector.dotProduct(deltaTotalStrain, n) ) / 2.; + FloatArrayF < 6 > + ConcreteDPM2::giveRealStressVector_3d(const FloatArrayF < 6 > & fullStrainVector, GaussPoint * gp, TimeStep * tStep) const + { + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); - double tempStressWork = this->giveTempStressWork() + dSW; + // Initialize temp variables for this gauss point + status->initTempStatus(); - //Calculate temporary elastic strain - FloatArray tempElasticStrain = tempTotalstrain; - tempElasticStrain.subtract(tempPlasticStrain); + FloatArrayF < 6 > stress; - //Calculate elastically stored energy density - double We = tempStressVector.dotProduct(tempElasticStrain, n) / 2.; + if ( status->giveTempDeletionFlag() == 1 ) { + //Deal with deleted element + return stress; + } - // dissipative work density - tempDissWork = tempStressWork - We; + // Remove thermal/shrinkage strains + auto thermalStrain = this->computeStressIndependentStrainVector_3d(gp, tStep, VM_Total); - // to avoid extremely small negative dissipation due to round-off error - // (note: gf is the dissipation density at complete failure, per unit volume) - //Rough estimation of gf which is ok for this purpose + auto strainVector = fullStrainVector - thermalStrain; - if ( fabs(tempDissWork) < 1.e-12 * gf ) { - tempDissWork = 0.; - } + status->letTempReducedStrainBe(strainVector); - this->setTempStressWork(tempStressWork); - this->setTempDissWork(tempDissWork); -} -#endif + //Calculate time increment + double dt = deltaTime; + if ( dt == -1 ) { + if ( tStep->giveTimeIncrement() == 0 ) { //Problem with the first step. For some reason the time increment is zero + dt = 1.; + } else { + dt = tStep->giveTimeIncrement(); + } + } -// ******************************** -// *** CLASS DYNAMIC CONCRETE *** -// ******************************** + auto D = this->linearElasticMaterial.give3dMaterialStiffnessMatrix(ElasticStiffness, gp, tStep); + // perform plasticity return + auto effectiveStress = performPlasticityReturn(gp, D, strainVector); -#define IDM_ITERATION_LIMIT 1.e-8 + FloatArrayF < 6 > effectiveStressTension; + FloatArrayF < 6 > effectiveStressCompression; -ConcreteDPM2 :: ConcreteDPM2(int n, Domain *d) : - StructuralMaterial(n, d) -{ - yieldTol = 0.; - yieldTolDamage = 0.; - newtonIter = 0; - linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); -} + double alpha = 0.; -ConcreteDPM2 :: ~ConcreteDPM2() -{ - delete linearElasticMaterial; -} + if ( this->damageFlag != 0 ) {//Apply damage + alpha = computeAlpha(effectiveStressTension, effectiveStressCompression, effectiveStress); + auto damages = computeDamage(strainVector, D, dt, gp, tStep, alpha, effectiveStress); -IRResultType -ConcreteDPM2 :: initializeFrom(InputRecord *ir) -{ - // Required by IR_GIVE_FIELD macro - IRResultType result; + if ( this->damageFlag == 1 ) { //Default as described in IJSS CDPM2 article + stress = effectiveStressTension * ( 1. - damages.at(1) ) + effectiveStressCompression * ( 1. - damages.at(2) ); + } else if ( this->damageFlag == 2 ) { //Simplified version without split of stress but two damage variables + stress = effectiveStress * ( 1. - ( 1. - alpha ) * damages.at(1) ) * ( 1. - alpha * damages.at(2) ); + } else if ( this->damageFlag == 3 ) { //Consider only tensile damage. Reduction to a fully isotropic model. Similar to CDPM article. + stress = effectiveStress * ( 1. - damages.at(1) ); + } else { + OOFEM_ERROR("Unknown value of damage flag. Must be 0, 1, 2 or 3"); + } + } else { + stress = effectiveStress; + } - // call the corresponding service for the linear elastic material - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; + status->letTempStrainVectorBe(fullStrainVector); + status->letTempAlphaBe(alpha); + status->letTempStressVectorBe(stress); + status->letTempEffectiveStressBe(effectiveStress); +#ifdef keep_track_of_dissipated_energy + double gf = pow(ft, 2) / this->eM; //rough estimation only for this purpose + status->computeWork(gp, gf); +#endif + assignStateFlag(gp); + return stress; } - result = linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - //isotropic flag - isotropicFlag = 0; - IR_GIVE_OPTIONAL_FIELD(ir, isotropicFlag, _IFT_ConcreteDPM2_isoflag); + FloatArrayF < 2 > + ConcreteDPM2::computeDamage(const FloatArrayF < 6 > & strain, + const FloatMatrixF < 6, 6 > & D, + double deltaTime, + GaussPoint * gp, + TimeStep * tStep, + double tempAlpha, + const FloatArrayF < 6 > & effectiveStress) const + { + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); - double value; - // elastic parameters - IR_GIVE_FIELD(ir, eM, _IFT_IsotropicLinearElasticMaterial_e) - IR_GIVE_FIELD(ir, nu, _IFT_IsotropicLinearElasticMaterial_n); - propertyDictionary.add('E', eM); - propertyDictionary.add('n', nu); + double tempEquivStrain; + double deltaPlasticStrainNorm; + double tempDamageTension = 0.0; + double tempDamageCompression = 0.0; - IR_GIVE_FIELD(ir, value, _IFT_IsotropicLinearElasticMaterial_talpha); - propertyDictionary.add(tAlpha, value); + double tempKappaDTension = 0.0, tempKappaDCompression = 0.0; + double tempKappaDTensionOne = 0.0, tempKappaDTensionTwo = 0.0; + double tempKappaDCompressionOne = 0.0, tempKappaDCompressionTwo = 0.0; - gM = eM / ( 2. * ( 1. + nu ) ); - kM = eM / ( 3. * ( 1. - 2. * nu ) ); + double minEquivStrain = 0.; - IR_GIVE_FIELD(ir, fc, _IFT_ConcreteDPM2_fc); - IR_GIVE_FIELD(ir, ft, _IFT_ConcreteDPM2_ft); + double sig, rho, theta; + //Calculate coordinates + computeCoordinates(effectiveStress, sig, rho, theta); - this->e0 = this->ft / this->eM; + int unAndReloadingFlag = checkForUnAndReloading(tempEquivStrain, minEquivStrain, D, gp); - // default parameters - this->ecc = 0.525; - IR_GIVE_OPTIONAL_FIELD(ir, ecc, _IFT_ConcreteDPM2_ecc); - yieldHardInitial = 0.3; - IR_GIVE_OPTIONAL_FIELD(ir, yieldHardInitial, _IFT_ConcreteDPM2_kinit); - //Inclination at transition point - yieldHardPrimePeak = 0.5; - IR_GIVE_OPTIONAL_FIELD(ir, yieldHardPrimePeak, _IFT_ConcreteDPM2_hp); + double rateFactor; + if ( ( status->giveDamageTension() == 0. ) && ( status->giveDamageCompression() == 0. ) ) { + rateFactor = computeRateFactor(tempAlpha, deltaTime, gp, tStep); + } else { + rateFactor = status->giveRateFactor(); + } - if ( yieldHardPrimePeak < 0 ) { - yieldHardPrimePeak = 0.; - OOFEM_WARNING("kPrimePeak cannot be less than zero"); - } else if ( yieldHardPrimePeak > ( 1. - yieldHardInitial ) ) { - yieldHardPrimePeak = 1. - yieldHardInitial; - OOFEM_WARNING("kPrimePeak cannot be greater than 1.-kinit"); - } - AHard = 8.e-2; - IR_GIVE_OPTIONAL_FIELD(ir, AHard, _IFT_ConcreteDPM2_ahard); - BHard = 3.e-3; - IR_GIVE_OPTIONAL_FIELD(ir, BHard, _IFT_ConcreteDPM2_bhard); - CHard = 2.; - IR_GIVE_OPTIONAL_FIELD(ir, CHard, _IFT_ConcreteDPM2_chard); - DHard = 1.e-6; - IR_GIVE_OPTIONAL_FIELD(ir, DHard, _IFT_ConcreteDPM2_dhard); - dilationConst = 0.85; - IR_GIVE_OPTIONAL_FIELD(ir, dilationConst, _IFT_ConcreteDPM2_dilation); + //Compute equivalent strains for tension and compression + double tempEquivStrainTension = 0.; + double tempEquivStrainCompression = 0.; - softeningType = 1; //0-Linear softening; 1-Bilinear softening; 2-Exponential - IR_GIVE_OPTIONAL_FIELD(ir, softeningType, _IFT_ConcreteDPM2_softeningType); + tempEquivStrainTension = status->giveEquivStrainTension() + ( tempEquivStrain - status->giveEquivStrain() ) / rateFactor; - if ( softeningType > 2 ) { - OOFEM_WARNING("softening type not implemented"); - return IRRT_BAD_FORMAT; - } + if ( unAndReloadingFlag == 0 ) { //Standard way + tempEquivStrainCompression = status->giveEquivStrainCompression() + ( tempAlpha * ( tempEquivStrain - status->giveEquivStrain() ) ) / rateFactor; + } else { + tempEquivStrainCompression = status->giveEquivStrainCompression() + status->giveAlpha() * ( minEquivStrain - status->giveEquivStrain() ) / rateFactor + ( tempAlpha * ( tempEquivStrain - minEquivStrain ) ) / rateFactor; + } + + + //If damage threshold is exceeded determine the rate factor from the previous step + if ( ( tempEquivStrainTension > e0 || tempEquivStrainCompression > e0 ) && + ( ( status->giveDamageTension() == 0. ) && ( status->giveDamageCompression() == 0. ) ) && !tStep->isTheFirstStep() ) { + //Rate factor from last step + rateFactor = status->giveRateFactor(); - IR_GIVE_FIELD(ir, this->wf, _IFT_ConcreteDPM2_wf); + tempEquivStrainTension = status->giveEquivStrainTension() + ( tempEquivStrain - status->giveEquivStrain() ) / rateFactor; + if ( unAndReloadingFlag == 0 ) { //Standard way + tempEquivStrainCompression = status->giveEquivStrainCompression() + ( tempAlpha * ( tempEquivStrain - status->giveEquivStrain() ) ) / rateFactor; + } else { + tempEquivStrainCompression = status->giveEquivStrainCompression() + status->giveAlpha() * ( minEquivStrain - status->giveEquivStrain() ) / rateFactor + ( tempAlpha * ( tempEquivStrain - minEquivStrain ) ) / rateFactor; + } + } - if ( softeningType == 1 ) { - this->ftOne = 0.3 * this->ft; - IR_GIVE_OPTIONAL_FIELD(ir, ftOne, _IFT_ConcreteDPM2_ftOne); - this->wfOne = 0.15 * this->wf; - IR_GIVE_OPTIONAL_FIELD(ir, this->wfOne, _IFT_ConcreteDPM2_wfOne); + status->letTempRateFactorBe(rateFactor); + + double fTension = tempEquivStrainTension - status->giveKappaDTension(); + double fCompression = tempEquivStrainCompression - status->giveKappaDCompression(); + + //Normalize the fs + fTension = fTension / e0; + fCompression = fCompression / e0; + + double ductilityMeasure = computeDuctilityMeasureDamage(gp, sig, rho); + double deltaPlasticStrainNormTension, deltaPlasticStrainNormCompression; + + if ( fTension < -yieldTolDamage && fCompression < -yieldTolDamage ) { + //Neither tension nor compression is active + + tempKappaDTension = status->giveKappaDTension(); + tempKappaDTensionOne = status->giveKappaDTensionOne(); + tempKappaDTensionTwo = status->giveKappaDTensionTwo(); + + tempKappaDCompression = status->giveKappaDCompression(); + tempKappaDCompressionOne = status->giveKappaDCompressionOne(); + tempKappaDCompressionTwo = status->giveKappaDCompressionTwo(); + + tempDamageTension = status->giveDamageTension(); + tempDamageCompression = status->giveDamageCompression(); + } else if ( fTension >= -yieldTolDamage && fCompression < -yieldTolDamage ) { //Only tension is active + //Update tension history variables + tempKappaDTension = tempEquivStrainTension; + deltaPlasticStrainNorm = computeDeltaPlasticStrainNormTension(tempKappaDTension, status->giveKappaDTension(), gp); + tempKappaDTensionOne = status->giveKappaDTensionOne() + deltaPlasticStrainNorm / ductilityMeasure / rateFactor; + tempKappaDTensionTwo = status->giveKappaDTensionTwo() + ( tempKappaDTension - status->giveKappaDTension() ) / ductilityMeasure; + + //Nothing changes for compression history variables + tempKappaDCompression = status->giveKappaDCompression(); + tempKappaDCompressionOne = status->giveKappaDCompressionOne(); + tempKappaDCompressionTwo = status->giveKappaDCompressionTwo(); + + //Initialise damage with tensile history variable + this->initDamaged(tempKappaDTension, strain, gp); + + tempDamageTension = computeDamageParamTension(tempKappaDTension, tempKappaDTensionOne, tempKappaDTensionTwo, status->giveLe(), status->giveDamageTension(), rateFactor); + + tempDamageCompression = status->giveDamageCompression(); + } else if ( fTension < -yieldTolDamage && fCompression >= -yieldTolDamage ) { + //Only compression is active + + //Nothing changes for the history variables in tension + tempKappaDTension = status->giveKappaDTension(); + tempKappaDTensionOne = status->giveKappaDTensionOne(); + tempKappaDTensionTwo = status->giveKappaDTensionTwo(); + + //Update compression history variables + tempKappaDCompression = tempEquivStrainCompression; + deltaPlasticStrainNormCompression = computeDeltaPlasticStrainNormCompression(tempAlpha, tempKappaDCompression, status->giveKappaDCompression(), gp, rho); + tempKappaDCompressionOne = status->giveKappaDCompressionOne() + deltaPlasticStrainNormCompression / ( ductilityMeasure * rateFactor ); + tempKappaDCompressionTwo = status->giveKappaDCompressionTwo() + ( tempKappaDCompression - status->giveKappaDCompression() ) / ductilityMeasure; + + //Determine damage parameters + tempDamageTension = status->giveDamageTension(); + tempDamageCompression = computeDamageParamCompression(tempKappaDCompression, tempKappaDCompressionOne, tempKappaDCompressionTwo, status->giveDamageCompression(), rateFactor); + } else if ( fTension >= -yieldTolDamage && fCompression >= -yieldTolDamage ) { + //Both tension and compression is active + + //Update tension history variables + tempKappaDTension = tempEquivStrainTension; + deltaPlasticStrainNormTension = computeDeltaPlasticStrainNormTension(tempKappaDTension, status->giveKappaDTension(), gp); + tempKappaDTensionOne = status->giveKappaDTensionOne() + deltaPlasticStrainNormTension / ( ductilityMeasure * rateFactor ); + tempKappaDTensionTwo = status->giveKappaDTensionTwo() + ( tempKappaDTension - status->giveKappaDTension() ) / ductilityMeasure; + + //Update the compression history variables + tempKappaDCompression = tempEquivStrainCompression; + deltaPlasticStrainNormCompression = + computeDeltaPlasticStrainNormCompression(tempAlpha, tempKappaDCompression, status->giveKappaDCompression(), gp, rho); + tempKappaDCompressionOne = status->giveKappaDCompressionOne() + deltaPlasticStrainNormCompression / ( ductilityMeasure * rateFactor ); + tempKappaDCompressionTwo = status->giveKappaDCompressionTwo() + + ( tempKappaDCompression - status->giveKappaDCompression() ) / ductilityMeasure; + + //Determine the damage parameters + this->initDamaged(tempKappaDTension, strain, gp); + + tempDamageTension = computeDamageParamTension(tempKappaDTension, tempKappaDTensionOne, tempKappaDTensionTwo, status->giveLe(), status->giveDamageTension(), rateFactor); + + tempDamageCompression = computeDamageParamCompression(tempKappaDCompression, tempKappaDCompressionOne, tempKappaDCompressionTwo, status->giveDamageCompression(), rateFactor); + } + + //Write all temp history variables to the status + status->letTempEquivStrainBe(tempEquivStrain); + + //Tension + status->letTempEquivStrainTensionBe(tempEquivStrainTension); + status->letTempKappaDTensionBe(tempKappaDTension); + status->letTempKappaDTensionOneBe(tempKappaDTensionOne); + status->letTempKappaDTensionTwoBe(tempKappaDTensionTwo); + status->letTempDamageTensionBe(tempDamageTension); + + //Compression + status->letTempEquivStrainCompressionBe(tempEquivStrainCompression); + status->letTempKappaDCompressionBe(tempKappaDCompression); + status->letTempKappaDCompressionOneBe(tempKappaDCompressionOne); + status->letTempKappaDCompressionTwoBe(tempKappaDCompressionTwo); + status->letTempDamageCompressionBe(tempDamageCompression); + + return { + tempDamageTension, tempDamageCompression + }; + } + + int + ConcreteDPM2::checkForUnAndReloading(double &tempEquivStrain, + double &minEquivStrain, + const FloatMatrixF < 6, 6 > &D, + GaussPoint *gp) const + { + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); + + //Access old and new strains + const auto &oldStrain = status->giveReducedStrain(); + const auto &strain = status->giveTempReducedStrain(); + + //Compute the temp equivalent strain + auto tempElasticStrain = strain - status->giveTempPlasticStrain(); + auto tempEffectiveStress = dot(D, tempElasticStrain); + + double sigEffective, rhoEffective, thetaEffective; + computeCoordinates(tempEffectiveStress, sigEffective, rhoEffective, thetaEffective); + tempEquivStrain = computeEquivalentStrain(sigEffective, rhoEffective, thetaEffective); + //Get the equivalent strain from the status + double equivStrain = status->giveEquivStrain(); + + //Compute the increment of effective stress + auto elasticStrain = oldStrain - status->givePlasticStrain(); + auto effectiveStress = dot(D, elasticStrain); + + auto deltaEffectiveStress = tempEffectiveStress - effectiveStress; + + //Compute equivalent strains for stress state slightly greater than the effective stress and smaller than the temp effective stress + //For slightly more than effective stress + auto intermediateEffectiveStressPlus = effectiveStress + 0.01 * deltaEffectiveStress; + computeCoordinates(intermediateEffectiveStressPlus, sigEffective, rhoEffective, thetaEffective); + double equivStrainPlus = computeEquivalentStrain(sigEffective, rhoEffective, thetaEffective); + + //For slightly less than temp effective stress + auto intermediateEffectiveStressMinus = effectiveStress + 0.99 * deltaEffectiveStress; + computeCoordinates(intermediateEffectiveStressMinus, sigEffective, rhoEffective, thetaEffective); + double tempEquivStrainMinus = computeEquivalentStrain(sigEffective, rhoEffective, thetaEffective); + + //Check for unloading and reloading in the same step + int unloadingFlag = 0; + minEquivStrain = equivStrain; + + if ( ( equivStrain > equivStrainPlus && tempEquivStrain > tempEquivStrainMinus ) && + ( fabs(equivStrainPlus - equivStrain) > yieldTolDamage / 100. && fabs(tempEquivStrainMinus - tempEquivStrain) > yieldTolDamage / 100. ) ) { + unloadingFlag = 1; + //Unloading and reloading takes place. Find the minimum equivalent strain by subincrementing the effective stress increment + for ( double k = 1.0; k <= 100.0; k = k + 1.0 ) { + auto intermediateEffectiveStress = effectiveStress + k / 100. * deltaEffectiveStress; + computeCoordinates(intermediateEffectiveStress, sigEffective, rhoEffective, thetaEffective); + double midEquivStrain = computeEquivalentStrain(sigEffective, rhoEffective, thetaEffective); + + if ( midEquivStrain <= minEquivStrain ) { + minEquivStrain = midEquivStrain; + } else { + return unloadingFlag; + } + } + } + return unloadingFlag; } - this->efCompression = 100.e-6; - IR_GIVE_OPTIONAL_FIELD(ir, this->efCompression, _IFT_ConcreteDPM2_efc); - this->ASoft = 15; - IR_GIVE_OPTIONAL_FIELD(ir, ASoft, _IFT_ConcreteDPM2_asoft); + double + ConcreteDPM2::computeRateFactor(double alpha, + double deltaTime, + GaussPoint *gp, + TimeStep *tStep) const + { + if ( this->strengthRateType == 0 ) { + return 1; + } + + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); + + const auto &strain = status->giveTempReducedStrain(); + + //Determine the principal values of the strain + + auto principalStrain = StructuralMaterial::computePrincipalValues(from_voigt_strain(strain) ); ///@todo CHECK + + //Determine max and min value; + double maxStrain = -1.e20, minStrain = 1.e20; + for ( int k = 1; k <= principalStrain.giveSize(); k++ ) { + //maximum + if ( principalStrain.at(k) > maxStrain ) { + maxStrain = principalStrain.at(k); + } + + //minimum + if ( principalStrain.at(k) < minStrain ) { + minStrain = principalStrain.at(k); + } + } + + //Evaluate the equivalent strains + double strainRate; + double oldRateStrain = status->giveRateStrain(); + if ( 1. - alpha > CDPM2_TOL ) { //Tension + strainRate = ( maxStrain - oldRateStrain ) / deltaTime; + status->letTempRateStrainBe(maxStrain); + } else { //Compression + strainRate = ( minStrain - oldRateStrain ) / deltaTime; + status->letTempRateStrainBe(minStrain); + } + + //Tension + //For tension according to Model Code 2010 + double rateFactorTension = 1.; + double strainRateRatioTension = strainRate / 1.e-6; - helem = 0.; - IR_GIVE_OPTIONAL_FIELD(ir, helem, _IFT_ConcreteDPM2_helem); + if ( this->strengthRateType == 1 ) { + if ( strainRate < 1.e-6 ) { + rateFactorTension = 1.; + } else if ( 1.e-6 < strainRate ) { + rateFactorTension = pow(strainRateRatioTension, 0.018); + } + } else if ( this->strengthRateType == 2 ) { + if ( strainRate < 1.e-6 ) { + rateFactorTension = 1.; + } else if ( 1.e-6 < strainRate && strainRate < 10 ) { + rateFactorTension = pow(strainRateRatioTension, 0.018); + } else { + rateFactorTension = 0.0062 * pow(strainRateRatioTension, 1. / 3.); + } + } + + //For compression according to Model Code 2010 + double rateFactorCompression = 1.; + double strainRateRatioCompression = strainRate / ( -30.e-6 ); + if ( this->strengthRateType == 1 ) { + if ( strainRate > -30.e-6 ) { + rateFactorCompression = 1.; + } else if ( -30.e-6 > strainRate ) { + rateFactorCompression = pow(strainRateRatioCompression, 0.014); + } + } else if ( this->strengthRateType == 2 ) { + if ( strainRate > -30.e-6 ) { + rateFactorCompression = 1.; + } else if ( -30.e-6 > strainRate && strainRate > -30 ) { + rateFactorCompression = pow(strainRateRatioCompression, 0.014); + } else if ( -30 > strainRate && strengthRateType == 2 ) { + rateFactorCompression = 0.012 * pow(strainRateRatioCompression, 0.333); + } + } + + double rateFactor = ( 1. - alpha ) * rateFactorTension + alpha * rateFactorCompression; + + + return rateFactor; + } - //Compute m - m = 3. * ( pow(fc, 2.) - pow(ft, 2.) ) / ( fc * ft ) * ecc / ( ecc + 1. ); + double + ConcreteDPM2::computeDeltaPlasticStrainNormTension(double tempKappaD, double kappaD, GaussPoint *gp) const + { + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); - //Compute default value of dilationConst - yieldTol = 1.e-6; - IR_GIVE_OPTIONAL_FIELD(ir, yieldTol, _IFT_ConcreteDPM2_yieldtol); + const auto &tempPlasticStrain = status->giveTempPlasticStrain(); + const auto &plasticStrain = status->givePlasticStrain(); - yieldTolDamage = yieldTol * 10.; + auto deltaPlasticStrain = tempPlasticStrain - plasticStrain; - newtonIter = 100; - IR_GIVE_OPTIONAL_FIELD(ir, newtonIter, _IFT_ConcreteDPM2_newtoniter); + double deltaPlasticStrainNorm = 0; - //parameters for rate dependence - strainRateFlag = 0; - IR_GIVE_OPTIONAL_FIELD(ir, strainRateFlag, _IFT_ConcreteDPM2_rateFlag); + //Distinguish pre-peak, peak and post-peak - timeFactor = 1.; - if ( strainRateFlag == 1 ) { - IR_GIVE_FIELD(ir, fcZero, _IFT_ConcreteDPM2_fcZero); - IR_GIVE_OPTIONAL_FIELD(ir, timeFactor, _IFT_ConcreteDPM2_timeFactor); + double factor = 0.; + if ( tempKappaD < e0 * ( 1. - yieldTolDamage ) ) { + deltaPlasticStrainNorm = 0.; + } else if ( tempKappaD > e0 * ( 1. - yieldTolDamage ) && kappaD < e0 * ( 1. - yieldTolDamage ) ) { + factor = ( 1. - ( e0 - kappaD ) / ( tempKappaD - kappaD ) ); + deltaPlasticStrain *= factor; + deltaPlasticStrainNorm = norm(deltaPlasticStrain); + } else { + deltaPlasticStrainNorm = norm(deltaPlasticStrain); + } + + return deltaPlasticStrainNorm; } - return IRRT_OK; -} + double + ConcreteDPM2::computeDeltaPlasticStrainNormCompression(double tempAlpha, double tempKappaD, double kappaD, GaussPoint *gp, const double rho) const + { + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); -void -ConcreteDPM2 :: giveRealStressVector_1d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &strainVector, - TimeStep *tStep) -{ - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); + const auto &tempPlasticStrain = status->giveTempPlasticStrain(); + const auto &plasticStrain = status->givePlasticStrain(); - // Initialize temp variables for this gauss point - this->initTempStatus(gp); + auto deltaPlasticStrain = tempAlpha * ( tempPlasticStrain - plasticStrain ); - //Calculate strain rate - //Time step - double deltaTime = 1.; - if ( strainRateFlag == 1 ) { - if ( tStep->giveTimeIncrement() == 0 ) { //Problem with the first step. For some reason the time increment is zero - deltaTime = this->timeFactor; + double deltaPlasticStrainNorm = 0; + + //Distinguish pre-peak, peak and post-peak + if ( tempKappaD < e0 * ( 1. - yieldTolDamage ) ) { + deltaPlasticStrainNorm = 0.; + } else if ( tempKappaD > e0 * ( 1. - yieldTolDamage ) && kappaD < e0 * ( 1. - yieldTolDamage ) ) { + double factor = ( 1. - ( e0 - kappaD ) / ( tempKappaD - kappaD ) ); + deltaPlasticStrain *= factor; + deltaPlasticStrainNorm = norm(deltaPlasticStrain); } else { - deltaTime = tStep->giveTimeIncrement() * this->timeFactor; + deltaPlasticStrainNorm = norm(deltaPlasticStrain); } - } else { - if ( tStep->giveTimeIncrement() == 0 ) { - deltaTime = 1.; + + double tempKappaP = status->giveTempKappaP(); + double yieldHardTwo = computeHardeningTwo(tempKappaP); + double extraFactor; + if ( rho < 1.e-16 ) { + extraFactor = this->ft * yieldHardTwo * sqrt(2. / 3.) / 1.e-16 / sqrt(1. + 2. * pow(this->dilationConst, 2.) ); } else { - deltaTime = tStep->giveTimeIncrement(); + extraFactor = this->ft * yieldHardTwo * sqrt(2. / 3.) / rho / sqrt(1. + 2. * pow(this->dilationConst, 2.) ); } + + return deltaPlasticStrainNorm * extraFactor; } - FloatMatrix D; - this->giveLinearElasticMaterial()->give1dStressStiffMtrx(D, ElasticStiffness, gp, tStep); - - // perform plasticity return - performPlasticityReturn(gp, D, strainVector); - // compute elastic strains and trial stress - FloatArray effectiveStress; - FloatArray elasticStrain = strainVector; - elasticStrain.subtract( status->giveTempPlasticStrain() ); - effectiveStress.beProductOf(D, elasticStrain); + double + ConcreteDPM2::computeEquivalentStrain(double sig, + double rho, + double theta) const + { + double rFunction = ( 4. * ( 1. - pow(this->ecc, 2.) ) * pow(cos(theta), 2.) + pow(2. * this->ecc - 1., 2.) ) / ( 2. * ( 1. - pow(this->ecc, 2.) ) * cos(theta) + ( 2. * this->ecc - 1. ) * sqrt(4. * ( 1. - pow(this->ecc, 2.) ) * pow(cos(theta), 2.) + 5. * pow(this->ecc, 2.) - 4. * this->ecc) ); + + double pHelp = -this->m * ( rho * rFunction / ( sqrt(6.) * fc ) + sig / fc ); + + double qHelp = -3. / 2. * pow(rho, 2.) / pow(this->fc, 2.); + double help = -0.5 * pHelp + sqrt(pow(pHelp, 2.) / 4. - qHelp); - FloatArray effectiveStressTension; - FloatArray effectiveStressCompression; - double alpha = 0.; - if ( effectiveStress.at(1) >= 0 ) { //1D tensile stress state - alpha = 0.; - effectiveStressTension = effectiveStress; - effectiveStressCompression.zero(); - } else if ( effectiveStress.at(1) < 0 ) { //1D compressive stress state - alpha = 1.; - effectiveStressTension.zero(); - effectiveStressCompression = effectiveStress; + double tempEquivStrain = 0.; + if ( help > 0 ) { + tempEquivStrain = help * e0; + } + return tempEquivStrain; } - FloatArray damages; - computeDamage(damages, strainVector, D, deltaTime, gp, tStep, alpha); - //Split damage in a tension and compression part + double + ConcreteDPM2::computeDamageParamTension(double equivStrain, double kappaOne, double kappaTwo, double le, double omegaOld, double rateFactor) const + { + double omega = 0.; - if ( isotropicFlag == 0 ) { //Default - effectiveStressTension.times( 1. - damages.at(1) ); - effectiveStressCompression.times( 1. - damages.at(2) ); - answer = effectiveStressTension; - answer.add(effectiveStressCompression); - } else { //Consider only tensile damage. Reduction to a fully isotropic model - answer = effectiveStress; - answer.times( 1. - damages.at(1) ); - } + //So that damage does not turn out to be negative if function is entered for equivstrains smaller thatn e0. + double ftTemp = this->ft * ( 1. - yieldTolDamage ); - status->letTempStrainVectorBe(strainVector); - status->letTempAlphaBe(alpha); - status->letTempStressVectorBe(answer); -#ifdef keep_track_of_dissipated_energy - double gf = pow(ft, 2) / this->eM; //rough estimation only for this purpose - status->computeWork(gp, gf); -#endif - assignStateFlag(gp); -} - - -void -ConcreteDPM2 :: giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &strainVector, - TimeStep *tStep) -{ - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); - - // Initialize temp variables for this gauss point - status->initTempStatus(); - - status->letTempStrainVectorBe(strainVector); - - //Calculate strain rate - //Time step - double deltaTime = 1.; - if ( strainRateFlag == 1 ) { - if ( tStep->giveTimeIncrement() == 0 ) { //Problem with the first step. For some reason the time increment is zero - deltaTime = this->timeFactor; - } else { - deltaTime = tStep->giveTimeIncrement() * this->timeFactor; + double wfMod = this->wf; + double wfOneMod = this->wfOne; + + if ( this->strengthRateType > 0 ) { + if ( this->energyRateType == 0 ) { + wfMod /= pow(rateFactor, 2.); + wfOneMod /= pow(rateFactor, 2.); + } else if ( this->energyRateType == 1 ) { + wfMod /= rateFactor; + wfOneMod /= rateFactor; + } } - } else { - if ( tStep->giveTimeIncrement() == 0 ) { - deltaTime = 1.; + + double help; + if ( equivStrain > e0 * ( 1. - yieldTolDamage ) ) { + if ( softeningType == 0 ) { //linear + omega = ( this->eM * equivStrain * wfMod - ftTemp * wfMod + ftTemp * kappaOne * le ) / + ( this->eM * equivStrain * wfMod - ftTemp * le * kappaTwo ); + } else if ( softeningType == 1 ) { //bilinear: Calculate damage parameter for both parts of bilinear curve and check which fulfils limits. + omega = ( this->eM * equivStrain * wfOneMod - ftTemp * wfOneMod - ( this->ftOne - ftTemp ) * kappaOne * le ) / + ( this->eM * equivStrain * wfOneMod + ( this->ftOne - ftTemp ) * le * kappaTwo ); + help = le * kappaOne + le * omega * kappaTwo; + + if ( help >= 0. && help < wfOneMod ) { + return omega; + } + + omega = ( this->eM * equivStrain * ( wfMod - wfOneMod ) - this->ftOne * ( wfMod - wfOneMod ) + + this->ftOne * kappaOne * le - this->ftOne * wfOneMod ) / + ( this->eM * equivStrain * ( wfMod - wfOneMod ) - this->ftOne * le * kappaTwo ); + help = le * kappaOne + le * omega * kappaTwo; + + if ( help > wfOneMod && help < wfMod ) { + return omega; + } + } else if ( softeningType == 2 ) { //exponential: Iterative solution + omega = 1.; //Initial guess + double residual = 0.; + double dResidualDOmega = 0.; + int nite = 0; + + do { + nite++; + + residual = ( 1 - omega ) * this->eM * equivStrain - ftTemp * exp(-le * ( omega * kappaTwo + kappaOne ) / wfMod); + dResidualDOmega = -this->eM * equivStrain + ftTemp * le * kappaTwo / wfMod * exp(-le * ( omega * kappaTwo + kappaOne ) / wfMod); + + omega -= residual / dResidualDOmega; + if ( nite > newtonIter ) { + OOFEM_ERROR("algorithm not converging"); + } + } while ( fabs(residual / ftTemp) >= 1.e-8 ); + } } else { - deltaTime = tStep->giveTimeIncrement(); + omega = 0.; } - } - FloatMatrix D; - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(D, ElasticStiffness, gp, tStep); - // perform plasticity return - performPlasticityReturn(gp, D, strainVector); + if ( omega > 1. ) { + omega = 1.; + } + if ( omega < 0. || omega < omegaOld ) { + omega = omegaOld; + } - // compute elastic strains and trial stress - FloatArray effectiveStress; - FloatArray elasticStrain = strainVector; - elasticStrain.subtract( status->giveTempPlasticStrain() ); - effectiveStress.beProductOf(D, elasticStrain); - FloatArray effectiveStressTension; - FloatArray effectiveStressCompression; - double alpha; + return omega; + } - alpha = computeAlpha(effectiveStressTension, effectiveStressCompression, effectiveStress); + double + ConcreteDPM2::computeDamageParamCompression(double equivStrain, double kappaOne, double kappaTwo, double omegaOld, double rateFactor) const + { + if ( this->damageFlag == 3 ) { + return 0.; + } - FloatArray damages; - computeDamage(damages, strainVector, D, deltaTime, gp, tStep, alpha); + double ftTemp = this->ft * ( 1. - yieldTolDamage ); + double efCompressionMod = this->efCompression; - //Split damage in a tension and compression part + if ( this->strengthRateType > 0 ) { + if ( this->energyRateType == 0 ) { + efCompressionMod /= pow(rateFactor, 2.); + } else if ( this->energyRateType == 1 ) { + efCompressionMod /= rateFactor; + } + } - if ( isotropicFlag == 0 ) { //Default - effectiveStressTension.times( 1. - damages.at(1) ); - effectiveStressCompression.times( 1. - damages.at(2) ); - answer = effectiveStressTension; - answer.add(effectiveStressCompression); - } else { //Consider only tensile damage. Reduction to a fully isotropic model - answer = effectiveStress; - answer.times( 1. - damages.at(1) ); - } + double omega = 1.; + int nite = 0; + double residual = 0.; + double dResidualDOmega = 0.; - status->letTempStrainVectorBe(strainVector); - status->letTempAlphaBe(alpha); - status->letTempStressVectorBe(answer); -#ifdef keep_track_of_dissipated_energy - double gf = pow(ft, 2) / this->eM; //rough estimation only for this purpose - status->computeWork(gp, gf); -#endif - assignStateFlag(gp); -} + if ( equivStrain > e0 * ( 1. - yieldTolDamage ) ) { + do { + nite++; + residual = ( 1. - omega ) * this->eM * equivStrain - ftTemp * exp(-( kappaOne + omega * kappaTwo ) / efCompressionMod); + dResidualDOmega = -this->eM * equivStrain + ftTemp * kappaTwo / efCompressionMod * exp(-( kappaOne + omega * kappaTwo ) / efCompressionMod); -void -ConcreteDPM2 :: computeDamage(FloatArray &answer, - const FloatArray &strain, - const FloatMatrix &D, - double deltaTime, - GaussPoint *gp, - TimeStep *tStep, - double tempAlpha) -{ - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); + omega -= residual / dResidualDOmega; + if ( nite > newtonIter ) { + OOFEM_ERROR("algorithm not converging"); + } + } while ( fabs(residual / ft) >= 1.e-8 ); + } else { + omega = 0.; + } - double tempEquivStrain; - double deltaPlasticStrainNorm; - double tempDamageTension = 0.0; - double tempDamageCompression = 0.0; + if ( omega > 1. ) { + omega = 1.; + } + if ( omega < omegaOld || omega < 0. ) { + omega = omegaOld; + } - double tempKappaDTension = 0.0, tempKappaDCompression = 0.0; - double tempKappaDTensionOne = 0.0, tempKappaDTensionTwo = 0.0; - double tempKappaDCompressionOne = 0.0, tempKappaDCompressionTwo = 0.0; + return omega; + } - double rateFactor; - int unAndReloadingFlag = 0; - double minEquivStrain = 0.; - unAndReloadingFlag = checkForUnAndReloading(tempEquivStrain, minEquivStrain, D, gp); + void + ConcreteDPM2::initDamaged(double kappaD, + const FloatArrayF < 6 > &strain, + GaussPoint *gp) const + { + if ( kappaD <= e0 * ( 1. - yieldTolDamage ) ) { + return; + } - if ( ( status->giveDamageTension() == 0. ) && ( status->giveDamageCompression() == 0. ) ) { - rateFactor = computeRateFactor(tempAlpha, deltaTime, gp, tStep); - } else { - rateFactor = status->giveRateFactor(); - } + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); + + if ( helem > 0. ) { + status->setLe(helem); + } else if ( status->giveDamageTension() == 0. && status->giveDamageCompression() == 0. ) { + //auto [principalStrains, principalDir] = computePrincipalValDir(from_voigt_strain(strain)); // c++17 + auto tmp = computePrincipalValDir(from_voigt_strain(strain) ); + auto principalStrains = tmp.first; + auto principalDir = tmp.second; + + // find index of max positive principal strain + int indx = 1; + for ( int i = 2; i <= 3; i++ ) { + if ( principalStrains.at(i) > principalStrains.at(indx) ) { + indx = i; + } + } - //Compute equivalent strains for tension and compression - double tempEquivStrainTension = 0.; - double tempEquivStrainCompression = 0.; + FloatArray crackPlaneNormal(3); + for ( int i = 1; i <= 3; i++ ) { + crackPlaneNormal.at(i) = principalDir.at(i, indx); + } - tempEquivStrainTension = status->giveEquivStrainTension() + ( tempEquivStrain - status->giveEquivStrain() ) / rateFactor; + // evaluate the projected element size + double le = gp->giveElement()->giveCharacteristicLength(crackPlaneNormal); + if ( le == 0. ) { + le = gp->giveElement()->computeMeanSize(); + } - if ( unAndReloadingFlag == 0 ) { //Standard way - tempEquivStrainCompression = status->giveEquivStrainCompression() + ( tempAlpha * ( tempEquivStrain - status->giveEquivStrain() ) ) / rateFactor; - } else { - tempEquivStrainCompression = status->giveEquivStrainCompression() + status->giveAlpha() * ( minEquivStrain - status->giveEquivStrain() ) / rateFactor + ( tempAlpha * ( tempEquivStrain - minEquivStrain ) ) / rateFactor; + // store le in the corresponding status + status->setLe(le); + } else if ( status->giveLe() == 0. ) { + // this happens if the status is initialized from a file + // with nonzero damage + // le determined as square root of element area or cube root of el. volume + double le = gp->giveElement()->computeMeanSize(); + status->setLe(le); + } } - //If damage threshold is exceeded determine the rate factor from the previous step - if ( ( tempEquivStrainTension > e0 || tempEquivStrainCompression > e0 ) && - ( ( status->giveDamageTension() == 0. ) && ( status->giveDamageCompression() == 0. ) ) && !tStep->isTheFirstStep() ) { - //Rate factor from last step - rateFactor = status->giveRateFactor(); + double + ConcreteDPM2::computeDuctilityMeasureDamage(GaussPoint *gp, const double sig, const double rho) const + { + //1./sqrt(6.)=0.40824829 + double alphaZero = 0.40824829; - tempEquivStrainTension = status->giveEquivStrainTension() + ( tempEquivStrain - status->giveEquivStrain() ) / rateFactor; - if ( unAndReloadingFlag == 0 ) { //Standard way - tempEquivStrainCompression = status->giveEquivStrainCompression() + ( tempAlpha * ( tempEquivStrain - status->giveEquivStrain() ) ) / rateFactor; + double Rs = 0; + if ( sig < 0. ) { + if ( rho > 1.e-16 ) { + Rs = -sig / ( alphaZero * rho ); + } else { //Need to set a dummy valye + Rs = -sig * 1.e16 / alphaZero; + } } else { - tempEquivStrainCompression = status->giveEquivStrainCompression() + status->giveAlpha() * ( minEquivStrain - status->giveEquivStrain() ) / rateFactor + ( tempAlpha * ( tempEquivStrain - minEquivStrain ) ) / rateFactor; + Rs = 0; } + + return 1. + ( this->ASoft - 1. ) * pow(Rs, this->BSoft); // ductilityMeasure } - status->letTempRateFactorBe(rateFactor); - double fTension = tempEquivStrainTension - status->giveKappaDTension(); - double fCompression = tempEquivStrainCompression - status->giveKappaDCompression(); + FloatArrayF < 6 > + ConcreteDPM2::performPlasticityReturn(GaussPoint * gp, const FloatMatrixF < 6, 6 > & D, const FloatArrayF < 6 > & strain) const + { + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); - //Normalize the fs - fTension = fTension / e0; - fCompression = fCompression / e0; + ConcreteDPM2_ReturnResult returnResult = RR_Unknown; + ConcreteDPM2_ReturnType returnType = RT_Unknown; - double ductilityMeasure = computeDuctilityMeasureDamage(strain, gp); - double deltaPlasticStrainNormTension, deltaPlasticStrainNormCompression; + //get plastic strain and kappa + auto tempPlasticStrain = status->givePlasticStrain(); + double tempKappaP = status->giveKappaP(); - if ( fTension < -yieldTolDamage && fCompression < -yieldTolDamage ) { - //Neither tension nor compression is active + //this theta computed here should stay constant for the rest of procedure. - tempKappaDTension = status->giveKappaDTension(); - tempKappaDTensionOne = status->giveKappaDTensionOne(); - tempKappaDTensionTwo = status->giveKappaDTensionTwo(); + const auto &oldStrain = status->giveReducedStrain(); - tempKappaDCompression = status->giveKappaDCompression(); - tempKappaDCompressionOne = status->giveKappaDCompressionOne(); - tempKappaDCompressionTwo = status->giveKappaDCompressionTwo(); + // introduce a strange subincrementation flag + int subIncrementFlag = 0; - tempDamageTension = status->giveDamageTension(); - tempDamageCompression = status->giveDamageCompression(); - } else if ( fTension >= -yieldTolDamage && fCompression < -yieldTolDamage ) { //Only tension is active - //Update tension history variables - tempKappaDTension = tempEquivStrainTension; - deltaPlasticStrainNorm = computeDeltaPlasticStrainNormTension(tempKappaDTension, status->giveKappaDTension(), gp); - tempKappaDTensionOne = status->giveKappaDTensionOne() + deltaPlasticStrainNorm / ductilityMeasure / rateFactor; - tempKappaDTensionTwo = status->giveKappaDTensionTwo() + ( tempKappaDTension - status->giveKappaDTension() ) / ductilityMeasure; - - //Nothing changes for compression history variables - tempKappaDCompression = status->giveKappaDCompression(); - tempKappaDCompressionOne = status->giveKappaDCompressionOne(); - tempKappaDCompressionTwo = status->giveKappaDCompressionTwo(); - - //Initialise damage with tensile history variable - this->initDamaged(tempKappaDTension, strain, gp); - - tempDamageTension = computeDamageParamTension( tempKappaDTension, tempKappaDTensionOne, tempKappaDTensionTwo, status->giveLe(), status->giveDamageTension() ); - - tempDamageCompression = status->giveDamageCompression(); - } else if ( fTension < -yieldTolDamage && fCompression >= -yieldTolDamage ) { - //Only compression is active - - //Nothing changes for the history variables in tension - tempKappaDTension = status->giveKappaDTension(); - tempKappaDTensionOne = status->giveKappaDTensionOne(); - tempKappaDTensionTwo = status->giveKappaDTensionTwo(); - - //Update compression history variables - tempKappaDCompression = tempEquivStrainCompression; - deltaPlasticStrainNormCompression = computeDeltaPlasticStrainNormCompression(tempAlpha, tempKappaDCompression, status->giveKappaDCompression(), gp); - tempKappaDCompressionOne = status->giveKappaDCompressionOne() + deltaPlasticStrainNormCompression / ( ductilityMeasure * rateFactor ); - tempKappaDCompressionTwo = status->giveKappaDCompressionTwo() + ( tempKappaDCompression - status->giveKappaDCompression() ) / ductilityMeasure; - - //Determine damage parameters - tempDamageTension = status->giveDamageTension(); - tempDamageCompression = computeDamageParamCompression( tempKappaDCompression, tempKappaDCompressionOne, tempKappaDCompressionTwo, status->giveDamageCompression() ); - } else if ( fTension >= -yieldTolDamage && fCompression >= -yieldTolDamage ) { - //Both tension and compression is active - - //Update tension history variables - tempKappaDTension = tempEquivStrainTension; - deltaPlasticStrainNormTension = computeDeltaPlasticStrainNormTension(tempKappaDTension, status->giveKappaDTension(), gp); - tempKappaDTensionOne = status->giveKappaDTensionOne() + deltaPlasticStrainNormTension / ( ductilityMeasure * rateFactor ); - tempKappaDTensionTwo = status->giveKappaDTensionTwo() + ( tempKappaDTension - status->giveKappaDTension() ) / ductilityMeasure; - - //Update the compression history variables - tempKappaDCompression = tempEquivStrainCompression; - deltaPlasticStrainNormCompression = - computeDeltaPlasticStrainNormCompression(tempAlpha, tempKappaDCompression, status->giveKappaDCompression(), gp); - tempKappaDCompressionOne = status->giveKappaDCompressionOne() + deltaPlasticStrainNormCompression / ( ductilityMeasure * rateFactor ); - tempKappaDCompressionTwo = status->giveKappaDCompressionTwo() + - ( tempKappaDCompression - status->giveKappaDCompression() ) / ductilityMeasure; - - //Determine the damage parameters - this->initDamaged(tempKappaDTension, strain, gp); - - tempDamageTension = computeDamageParamTension( tempKappaDTension, tempKappaDTensionOne, tempKappaDTensionTwo, status->giveLe(), status->giveDamageTension() ); - - tempDamageCompression = computeDamageParamCompression( tempKappaDCompression, tempKappaDCompressionOne, tempKappaDCompressionTwo, status->giveDamageCompression() ); - } - - //Write all temp history variables to the status - status->letTempEquivStrainBe(tempEquivStrain); - - //Tension - status->letTempEquivStrainTensionBe(tempEquivStrainTension); - status->letTempKappaDTensionBe(tempKappaDTension); - status->letTempKappaDTensionOneBe(tempKappaDTensionOne); - status->letTempKappaDTensionTwoBe(tempKappaDTensionTwo); - status->letTempDamageTensionBe(tempDamageTension); - - //Compression - status->letTempEquivStrainCompressionBe(tempEquivStrainCompression); - status->letTempKappaDCompressionBe(tempKappaDCompression); - status->letTempKappaDCompressionOneBe(tempKappaDCompressionOne); - status->letTempKappaDCompressionTwoBe(tempKappaDCompressionTwo); - status->letTempDamageCompressionBe(tempDamageCompression); - - answer.resize(2); - answer.at(1) = tempDamageTension; - answer.at(2) = tempDamageCompression; -} - -int -ConcreteDPM2 :: checkForUnAndReloading(double &tempEquivStrain, - double &minEquivStrain, - const FloatMatrix &D, - GaussPoint *gp) -{ - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); - - double sigEffective, rhoEffective, thetaEffective; - - //Access old and new strains - FloatArray oldStrain = status->giveStrainVector(); - FloatArray strain = status->giveTempStrainVector(); - - //Compute the temp equivalent strain - FloatArray tempEffectiveStress; - FloatArray tempElasticStrain = strain; - tempElasticStrain.subtract( status->giveTempPlasticStrain() ); - tempEffectiveStress.beProductOf(D, tempElasticStrain); - computeTrialCoordinates(tempEffectiveStress, sigEffective, rhoEffective, thetaEffective); - tempEquivStrain = computeEquivalentStrain(sigEffective, rhoEffective, thetaEffective); - //Get the equivalent strain from the status - double equivStrain = status->giveEquivStrain(); - - //Compute the increment of effective stress - FloatArray effectiveStress; - FloatArray elasticStrain = oldStrain; - for ( int i = 1; i <= elasticStrain.giveSize(); ++i ) elasticStrain.at(i) -= status->givePlasticStrain().at(i); - //elasticStrain.subtract( status->givePlasticStrain() ); - effectiveStress.beProductOf(D, elasticStrain); - FloatArray deltaEffectiveStress; - deltaEffectiveStress = tempEffectiveStress; - deltaEffectiveStress.subtract(effectiveStress); - - //Compute equivalent strains for stress state slightly greater than the effective stress and smaller than the temp effective stress - FloatArray intermediateEffectiveStress; - intermediateEffectiveStress = effectiveStress; - //For slightly more than effective stress - intermediateEffectiveStress.add(0.01 * deltaEffectiveStress); - computeTrialCoordinates(intermediateEffectiveStress, sigEffective, rhoEffective, thetaEffective); - double equivStrainPlus = computeEquivalentStrain(sigEffective, rhoEffective, thetaEffective); - //For slightly less than temp effective stress - intermediateEffectiveStress = effectiveStress; - intermediateEffectiveStress.add(0.99 * deltaEffectiveStress); - computeTrialCoordinates(intermediateEffectiveStress, sigEffective, rhoEffective, thetaEffective); - double tempEquivStrainMinus = computeEquivalentStrain(sigEffective, rhoEffective, thetaEffective); - - //Check for unloading and reloading in the same step - int unloadingFlag = 0; - minEquivStrain = equivStrain; - double midEquivStrain = 0.; - - unloadingFlag = 0; - if ( ( equivStrain > equivStrainPlus && tempEquivStrain > tempEquivStrainMinus ) && ( fabs(equivStrainPlus - equivStrain) > yieldTolDamage / 100. && fabs(tempEquivStrainMinus - tempEquivStrain) > yieldTolDamage / 100. ) ) { - unloadingFlag = 1; - //Unloading and reloading takes place. Find the minimum equivalent strain by subincrementing the effective stress increment - for ( double k = 1.0; k <= 100.0; k = k + 1.0 ) { - intermediateEffectiveStress = effectiveStress; - intermediateEffectiveStress.add(k / 100. * deltaEffectiveStress); - computeTrialCoordinates(intermediateEffectiveStress, sigEffective, rhoEffective, thetaEffective); - midEquivStrain = computeEquivalentStrain(sigEffective, rhoEffective, thetaEffective); - - if ( midEquivStrain <= minEquivStrain ) { - minEquivStrain = midEquivStrain; + double apexStress = 0.; + int subincrementcounter = 0; + //Attempt to implement subincrementation + // initialize variables + subIncrementFlag = 0; + auto convergedStrain = oldStrain; + auto tempStrain = strain; + auto deltaStrain = strain - oldStrain; + + FloatArrayF < 6 > effectiveStress; + + //To get into the loop + returnResult = RR_NotConverged; + while ( returnResult == RR_NotConverged || subIncrementFlag == 1 ) { + auto elasticStrain = tempStrain - tempPlasticStrain; + + effectiveStress = dot(D, elasticStrain); + + double sig, rho, theta; + computeCoordinates(effectiveStress, sig, rho, theta); + double yieldValue = computeYieldValue(sig, rho, theta, tempKappaP); + + apexStress = 0.; + + if ( yieldValue > 0. ) { + checkForVertexCase(apexStress, returnType, sig, tempKappaP, gp); + if ( returnType == RT_Tension || returnType == RT_Compression ) { + tempKappaP = performVertexReturn(effectiveStress, returnResult, returnType, apexStress, tempKappaP, gp); + status->letTempKappaPBe(tempKappaP); + if ( returnType == RT_Tension ) { + status->letTempStateFlagBe(ConcreteDPM2Status::ConcreteDPM2_VertexTension); + } else if ( returnType == RT_Compression ) { + status->letTempStateFlagBe(ConcreteDPM2Status::ConcreteDPM2_VertexCompression); + } + } + if ( returnType == RT_Regular ) { + tempKappaP = performRegularReturn(effectiveStress, returnResult, returnType, tempKappaP, gp, theta); + status->letTempKappaPBe(tempKappaP); + } } else { - return unloadingFlag; + returnResult = RR_Converged; + tempPlasticStrain = status->givePlasticStrain(); + status->letTempPlasticStrainBe(tempPlasticStrain); + status->letTempKappaPBe(tempKappaP); + break; + } + + if ( returnResult == RR_NotConverged ) { + subincrementcounter++; + if ( subincrementcounter > 10 ) { + OOFEM_LOG_INFO("Unstable element %d \n", gp->giveElement()->giveGlobalNumber() ); + OOFEM_LOG_INFO("Old strain vector %g %g %g %g %g %g \n", oldStrain.at(1), oldStrain.at(2), oldStrain.at(3), oldStrain.at(4), oldStrain.at(5), oldStrain.at(6) ); + + const auto &help = status->giveTempPlasticStrain(); + OOFEM_LOG_INFO("Old plastic strain vector %g %g %g %g %g %g \n", help.at(1), help.at(2), help.at(3), help.at(4), help.at(5), help.at(6) ); + OOFEM_LOG_INFO("New strain vector %g %g %g %g %g %g \n", strain.at(1), strain.at(2), strain.at(3), strain.at(4), strain.at(5), strain.at(6) ); + + computeCoordinates(effectiveStress, sig, rho, theta); + double sig1, rho1, theta1; + auto help1 = dot(D, oldStrain - help); + computeCoordinates(help1, sig1, rho1, theta1); + yieldValue = computeYieldValue(sig, rho, theta, tempKappaP); + OOFEM_LOG_INFO("OLD Sig %g rho %g theta %g \n", sig1, rho1, theta1); + OOFEM_LOG_INFO("NEW Sig %g rho %g theta %g \n", sig, rho, theta); + if ( returnType == RT_Tension || returnType == RT_Compression ) { + OOFEM_LOG_INFO("Vertex case apexstress %g\n", apexStress); + } else { + OOFEM_LOG_INFO("Regular case %g \n", 15.18); + } + OOFEM_LOG_INFO("KappaP old %g new %g yieldfun %g\n", status->giveTempKappaP(), tempKappaP, yieldValue); + OOFEM_WARNING("ConcreteDamagePlasticity2:: performPlasticityReturn: Could not reach convergence with small deltaStrain, giving up. Delete Element number %d", gp->giveElement()->giveNumber() ); + //OOFEM_ERROR("Could not reach convergence with small deltaStrain, giving up."); + status->setTempDeletionFlag(1); + for (int k = 0; k < 6; k++) { + effectiveStress.at(k + 1) = 0.; + } + return effectiveStress; + } else if ( subincrementcounter > 9 && tempKappaP < 1. ) { + tempKappaP = 1.; + status->letTempKappaPBe(tempKappaP); + } + + subIncrementFlag = 1; + deltaStrain *= 0.5; + tempStrain = convergedStrain + deltaStrain; + } else if ( returnResult == RR_Converged && subIncrementFlag == 0 ) { + auto C = inv(D); // compliance + elasticStrain = dot(C, effectiveStress); + tempPlasticStrain = strain - elasticStrain; + status->letTempPlasticStrainBe(tempPlasticStrain); + } else if ( returnResult == RR_Converged && subIncrementFlag == 1 ) { + subincrementcounter = 0; + auto C = inv(D); // compliance + elasticStrain = dot(C, effectiveStress); + tempPlasticStrain = tempStrain - elasticStrain; + status->letTempPlasticStrainBe(tempPlasticStrain); + + subIncrementFlag = 0; + returnResult = RR_NotConverged; + convergedStrain = tempStrain; + deltaStrain = strain - convergedStrain; + tempStrain = strain; } } - } - return unloadingFlag; -} + return effectiveStress; + } -double -ConcreteDPM2 :: computeRateFactor(double alpha, - double deltaTime, - GaussPoint *gp, - TimeStep *tStep) -{ - if ( strainRateFlag == 0 ) { - return 1; + void + ConcreteDPM2::checkForVertexCase(double &answer, + ConcreteDPM2_ReturnType &returnType, + double sig, + double tempKappa, + GaussPoint *gp) const + { + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); + + answer = 0.; + if ( sig > 0. ) { + returnType = RT_Tension; + } else if ( sig < 0. && tempKappa < 1. ) { + returnType = RT_Compression; + } else { + returnType = RT_Regular; + } } - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); - //Access old and new strain - FloatArray strain = status->giveTempStrainVector(); + double + ConcreteDPM2::performVertexReturn(FloatArrayF < 6 > &effectiveStress, + ConcreteDPM2_ReturnResult &returnResult, + ConcreteDPM2_ReturnType &returnType, + double apexStress, double tempKappaP, + GaussPoint *gp) const + { + //auto [deviatoricStressTrial, sigTrial] = computeDeviatoricVolumetricSplit(effectiveStress); // c++17 + auto tmp = computeDeviatoricVolumetricSplit(effectiveStress); + auto deviatoricStressTrial = tmp.first; + auto sigTrial = tmp.second; + + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); + + double rhoTrial = computeSecondCoordinate(deviatoricStressTrial); + + double kappaInitial = tempKappaP; + + double sig2 = apexStress; + + tempKappaP = computeTempKappa(kappaInitial, sigTrial, rhoTrial, sigTrial); + + double yieldValue = computeYieldValue(sigTrial, 0., 0., tempKappaP); - //Determine the principal values of the strain - FloatArray principalStrain; - StructuralMaterial :: computePrincipalValues(principalStrain, strain, principal_strain); ///@todo CHECK - //Determine max and min value; - double maxStrain = -1.e20, minStrain = 1.e20; - for ( int k = 1; k <= principalStrain.giveSize(); k++ ) { - //maximum - if ( principalStrain.at(k) > maxStrain ) { - maxStrain = principalStrain.at(k); + tempKappaP = computeTempKappa(kappaInitial, sigTrial, rhoTrial, sig2); + + double yieldValueMid = computeYieldValue(sig2, 0., 0., tempKappaP); + + if ( yieldValue * yieldValueMid >= 0. ) { + returnType = RT_Regular; + returnResult = RR_NotConverged; + return kappaInitial; } - //minimum - if ( principalStrain.at(k) < minStrain ) { - minStrain = principalStrain.at(k); + double dSig, sigAnswer; + if ( yieldValue < 0.0 ) { + dSig = sig2 - sigTrial; + sigAnswer = sig2; + } else { + dSig = sigTrial - sig2; + sigAnswer = sig2; } - } - //Evaluate the equivalent strains - double strainRate; - double oldRateStrain = status->giveRateStrain(); - if ( 1. - alpha > DYNCON_TOL ) { //Tension - strainRate = ( maxStrain - oldRateStrain ) / deltaTime; - status->letTempRateStrainBe(maxStrain); - } else { //Compression - strainRate = ( minStrain - oldRateStrain ) / deltaTime; - status->letTempRateStrainBe(minStrain); - } + for ( int j = 0; j < 250; j++ ) { + dSig = 0.5 * dSig; - //For tension - double deltaS = 1. / ( 1. + 8. * this->fc / this->fcZero ); - double betaS = exp( ( 6 * deltaS - 2. ) * log(10.) ); + double sigMid = sigAnswer + dSig; - double strainRateZeroTension = 1.e-6; - double strainRateZeroCompression = -30.e-6; + tempKappaP = computeTempKappa(kappaInitial, sigTrial, rhoTrial, sigMid); - //For compression - // Fip-Model code 1990 expressions modified to take into account that we have an equivalent strain! - double alphaS = 1. / ( 5. + 9 * this->fc / this->fcZero ); - double gammaS = exp( ( 6.156 * alphaS - 2. ) * log(10.0) ); + yieldValueMid = computeYieldValue(sigMid, 0., 0., tempKappaP); - double strainRateRatioTension, strainRateRatioCompression; + if ( yieldValueMid <= 0. ) { + sigAnswer = sigMid; + } - double rateFactorTension = 1.; - double rateFactorCompression = 1.; + if ( fabs(yieldValueMid) < yieldTol && yieldValueMid <= 0. ) { + double ratioPotential = + computeRatioPotential(sigAnswer, 0, tempKappaP); - strainRateRatioTension = strainRate / strainRateZeroTension; - //Tension - if ( strainRate < 30.e-6 ) { - rateFactorTension = 1.; - } else if ( 30.e-6 < strainRate && strainRate < 1 ) { - rateFactorTension = pow(strainRateRatioTension, deltaS); - } else { - rateFactorTension = betaS * pow(strainRateRatioTension, 0.333); - } + double ratioTrial = rhoTrial / ( sigTrial - sigAnswer ); - //Compression - strainRateRatioCompression = strainRate / strainRateZeroCompression; - if ( strainRate > -30.e-6 ) { - rateFactorCompression = 1.; - } else if ( -30.e-6 > strainRate && strainRate > -30 ) { - rateFactorCompression = pow(strainRateRatioCompression, 1.026 * alphaS); - } else { - rateFactorCompression = gammaS * pow(strainRateRatioCompression, 0.333); - } + if ( ( ( ( ratioPotential >= ratioTrial ) && returnType == RT_Tension ) ) || + ( ( ratioPotential <= ratioTrial ) && returnType == RT_Compression ) ) { + for ( int i = 0; i < 3; i++ ) { + effectiveStress.at(i + 1) = sigAnswer; + } + + for ( int i = 3; i < 6; i++ ) { + effectiveStress.at(i + 1) = 0.; + } + returnResult = RR_Converged; + return tempKappaP; + } else { + returnType = RT_Regular; + returnResult = RR_NotConverged; + return kappaInitial; + } + } + } - double rateFactor = ( 1. - alpha ) * rateFactorTension + alpha * rateFactorCompression; + for ( int i = 0; i < 3; i++ ) { + effectiveStress.at(i + 1) = sigAnswer; + } + + for ( int i = 3; i < 6; i++ ) { + effectiveStress.at(i + 1) = 0.; + } + returnResult = RR_Converged; - return rateFactor; -} + OOFEM_WARNING("Perform vertex return not converged!\n"); + return tempKappaP; + } -double -ConcreteDPM2 :: computeDeltaPlasticStrainNormTension(double tempKappaD, double kappaD, GaussPoint *gp) -{ - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); + double + ConcreteDPM2::computeTempKappa(double kappaInitial, + double sigTrial, + double rhoTrial, + double sig) const + { + //This function is called, if stress state is in vertex case + double equivalentDeltaPlasticStrain = sqrt(1. / 9. * pow( ( sigTrial - sig ) / ( kM ), 2. ) + + pow(rhoTrial / ( 2. * gM ), 2.) ); - const FloatArray &tempPlasticStrain = status->giveTempPlasticStrain(); - const FloatArray &plasticStrain = status->givePlasticStrain(); + double thetaVertex = M_PI / 3.; + double ductilityMeasure = computeDuctilityMeasure(sig, 0., thetaVertex); - FloatArray deltaPlasticStrain = tempPlasticStrain; - for ( int i = 1; i <= deltaPlasticStrain.giveSize(); ++i ) deltaPlasticStrain.at(i) -= plasticStrain.at(i); - //deltaPlasticStrain.subtract(plasticStrain); + return kappaInitial + equivalentDeltaPlasticStrain / ductilityMeasure; + } - double deltaPlasticStrainNorm = 0; - //Distinguish pre-peak, peak and post-peak + double + ConcreteDPM2::computeDuctilityMeasure(double sig, + double rho, + double theta) const + { + double thetaConst = pow(2. * cos(theta), 2.); + double ductilityMeasure; + double x = -( sig + fc / 3 ) / fc; + if ( x < 0. ) { + /*Introduce exponential help function which results in a smooth + * transition. */ + double EHard = BHard - DHard; + double FHard = ( BHard - DHard ) * CHard / ( AHard - BHard ); + ductilityMeasure = ( EHard * exp(x / FHard) + DHard ) / thetaConst; + } else { + ductilityMeasure = ( AHard + ( BHard - AHard ) * exp(-x / ( CHard ) ) ) / thetaConst; + } - double factor = 0.; - if ( tempKappaD < e0 * ( 1. - yieldTolDamage ) ) { - deltaPlasticStrainNorm = 0.; - } else if ( tempKappaD > e0 * ( 1. - yieldTolDamage ) && kappaD < e0 * ( 1. - yieldTolDamage ) ) { - factor = ( 1. - ( e0 - kappaD ) / ( tempKappaD - kappaD ) ); - deltaPlasticStrain.times(factor); - deltaPlasticStrainNorm = deltaPlasticStrain.computeNorm(); - } else { - deltaPlasticStrainNorm = deltaPlasticStrain.computeNorm(); + return ductilityMeasure; } - return deltaPlasticStrainNorm; -} + double + ConcreteDPM2::computeRatioPotential(double sig, + double rho, + double tempKappa) const + { + //compute yieldHard and yieldSoft + double yieldHardOne = computeHardeningOne(tempKappa); + double yieldHardTwo = computeHardeningTwo(tempKappa); + + //Compute dilation parameter + double AGParam = this->ft * yieldHardTwo * 3 / this->fc + m / 2; + double BGParam = + yieldHardTwo / 3. * ( 1. + this->ft / this->fc ) / + ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); + double R = ( sig - ft / 3. * yieldHardTwo ) / fc / BGParam; + double mQ = AGParam * exp(R); -double -ConcreteDPM2 :: computeDeltaPlasticStrainNormCompression(double tempAlpha, double tempKappaD, double kappaD, GaussPoint *gp) -{ - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); + double Bl = sig / fc + rho / ( fc * sqrt(6.) ); - const FloatArray &tempPlasticStrain = status->giveTempPlasticStrain(); - const FloatArray &plasticStrain = status->givePlasticStrain(); + double Al = ( 1. - yieldHardOne ) * pow(Bl, 2.) + sqrt(3. / 2.) * rho / fc; - FloatArray deltaPlasticStrain; - deltaPlasticStrain.add(tempAlpha, tempPlasticStrain); - for ( int i = 1; i <= deltaPlasticStrain.giveSize(); ++i ) deltaPlasticStrain.at(i) -= tempAlpha * plasticStrain.at(i); - //deltaPlasticStrain.add(-tempAlpha, plasticStrain); + double dgdsig = 4. * ( 1. - yieldHardOne ) / fc * Al * Bl + pow(yieldHardOne, 2.) * mQ / fc; - double deltaPlasticStrainNorm = 0; + double dgdrho = Al / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) + - //Distinguish pre-peak, peak and post-peak - if ( tempKappaD < e0 * ( 1. - yieldTolDamage ) ) { - deltaPlasticStrainNorm = 0.; - } else if ( tempKappaD > e0 * ( 1. - yieldTolDamage ) && kappaD < e0 * ( 1. - yieldTolDamage ) ) { - double factor = ( 1. - ( e0 - kappaD ) / ( tempKappaD - kappaD ) ); - deltaPlasticStrain.times(factor); - deltaPlasticStrainNorm = deltaPlasticStrain.computeNorm(); - } else { - deltaPlasticStrainNorm = deltaPlasticStrain.computeNorm(); - } + m * pow(yieldHardOne, 2.) / ( sqrt(6.) * fc ); - double tempKappaP = status->giveTempKappaP(); - double yieldHardTwo = computeHardeningTwo(tempKappaP); - double extraFactor; - if ( rho < 1.e-16 ) { - extraFactor = this->ft * yieldHardTwo * sqrt(2. / 3.) / 1.e-16 / sqrt( 1. + 2. * pow(this->dilationConst, 2.) ); - } else { - extraFactor = this->ft * yieldHardTwo * sqrt(2. / 3.) / this->rho / sqrt( 1. + 2. * pow(this->dilationConst, 2.) ); + return dgdrho / dgdsig * 3. * ( 1. - 2. * nu ) / ( 1. + nu ); } - return deltaPlasticStrainNorm * extraFactor; -} + double + ConcreteDPM2::performRegularReturn(FloatArrayF < 6 > &effectiveStress, + ConcreteDPM2_ReturnResult &returnResult, + ConcreteDPM2_ReturnType &returnType, + double kappaP, + GaussPoint *gp, + double theta) const + { + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); -double -ConcreteDPM2 :: computeEquivalentStrain(double sig, - double rho, - double theta) -{ - double rFunction = ( 4. * ( 1. - pow(this->ecc, 2.) ) * pow(cos(theta), 2.) + pow(2. * this->ecc - 1., 2.) ) / ( 2. * ( 1. - pow(this->ecc, 2.) ) * cos(theta) + ( 2. * this->ecc - 1. ) * sqrt(4. * ( 1. - pow(this->ecc, 2.) ) * pow(cos(theta), 2.) + 5. * pow(this->ecc, 2.) - 4. * this->ecc) ); + //Define stressVariables + double trialSig, trialRho; - double pHelp = -this->m * ( rho * rFunction / ( sqrt(6.) * fc ) + sig / fc ); + auto trialStress = effectiveStress; - double qHelp = -3. / 2. * pow(rho, 2.) / pow(this->fc, 2.); + //compute invariants from stress state + //auto [deviatoricTrialStress, trialSig] = computeDeviatoricVolumetricSplit(trialStress); // c++17 + auto tmp = computeDeviatoricVolumetricSplit(trialStress); + auto deviatoricTrialStress = tmp.first; + trialSig = tmp.second; + trialRho = computeSecondCoordinate(deviatoricTrialStress); - double help = -0.5 * pHelp + sqrt(pow(pHelp, 2.) / 4. - qHelp); + double sig = trialSig; + double rho = trialRho; - double tempEquivStrain = 0.; - if ( help > 0 ) { - tempEquivStrain = help * e0; - } - return tempEquivStrain; -} + // Starting guess: + double tempKappaP = kappaP; + // Look at the magnitudes of the residuals. You have to scale the yieldValue down. + double yieldValue = computeYieldValue(sig, rho, theta, tempKappaP); -double -ConcreteDPM2 :: computeDamageParamTension(double equivStrain, double kappaOne, double kappaTwo, double le, double omegaOld) -{ - double omega = 0.; + //initialise unknowns + FloatArray unknowns; + FloatArray residuals; + residuals.resize(4); + residuals.at(4) = yieldValue; //store in the last element of the array + unknowns.resize(4); + unknowns.at(1) = trialSig; + unknowns.at(2) = trialRho; + unknowns.at(3) = tempKappaP; + unknowns.at(4) = 0.; - double help; - if ( equivStrain > e0 * ( 1. - yieldTolDamage ) ) { - if ( softeningType == 0 ) { //linear - omega = ( this->eM * equivStrain * this->wf - this->ft * this->wf + this->ft * kappaOne * le ) / - ( this->eM * equivStrain * this->wf - this->ft * le * kappaTwo ); - } else if ( softeningType == 1 ) { //bilinear: Calculate damage parameter for both parts of bilinear curve and check which fulfils limits. - omega = ( this->eM * equivStrain * this->wfOne - this->ft * this->wfOne - ( this->ftOne - this->ft ) * kappaOne * le ) / - ( this->eM * equivStrain * this->wfOne + ( this->ftOne - this->ft ) * le * kappaTwo ); - help = le * kappaOne + le * omega * kappaTwo; + double deltaLambda = 0.; + double normOfResiduals = 1.;//just to get into the loop - if ( help >= 0. && help < this->wfOne ) { - return omega; - } + // N.R. iteration for finding the correct plastic return which is found when the norm of the residuals are equal to zero - omega = ( this->eM * equivStrain * ( this->wf - this->wfOne ) - this->ftOne * ( this->wf - this->wfOne ) + - this->ftOne * kappaOne * le - this->ftOne * this->wfOne ) / - ( this->eM * equivStrain * ( this->wf - this->wfOne ) - this->ftOne * le * kappaTwo ); - help = le * kappaOne + le * omega * kappaTwo; + int iterationCount = 0; + while ( normOfResiduals > yieldTol ) { + iterationCount++; + if ( iterationCount == newtonIter ) { + returnResult = RR_NotConverged; - if ( help > this->wfOne && help < this->wf ) { - return omega; + return kappaP; } - } else if ( softeningType == 2 ) { //exponential: Iterative solution - omega = 1.; //Initial guess - double residual = 0.; - double dResidualDOmega = 0.; - int nite = 0; - - do { - nite++; + auto residualsNorm = residuals; + //Normalize residuals. Think about it more. + residualsNorm.at(1) /= this->kM; + residualsNorm.at(2) /= 2. * this->gM; - residual = ( 1 - omega ) * eM * equivStrain - ft *exp(-le * ( omega * kappaTwo + kappaOne ) / wf); - dResidualDOmega = -eM * equivStrain + ft * le * kappaTwo / wf *exp(-le * ( omega * kappaTwo + kappaOne ) / wf); + normOfResiduals = norm(residualsNorm); - omega -= residual / dResidualDOmega; - if ( nite > newtonIter ) { - OOFEM_ERROR("algorithm not converging"); - } - } while ( fabs(residual / ft) >= 1.e-8 ); - } - } else { - omega = 0.; - } + if ( std::isnan(normOfResiduals) ) { + returnResult = RR_NotConverged; + return kappaP; + } + if ( normOfResiduals > yieldTol ) { + // Test to run newton iteration using inverse of Jacobian + auto jacobian = computeJacobian(sig, rho, theta, tempKappaP, deltaLambda, gp); - if ( omega > 1. ) { - omega = 1.; - } + try { + auto deltaIncrement = solve( jacobian, FloatArrayF < 4 > ( residuals ) ); + unknowns -= deltaIncrement; + } catch(...) { + returnResult = RR_NotConverged; + return kappaP; + } - if ( omega < 0. || omega < omegaOld ) { - omega = omegaOld; - } + unknowns.at(2) = max(unknowns.at(2), 0.); //Keep rho greater than zero! + unknowns.at(3) = max(unknowns.at(3), kappaP); //Keep deltaKappa greater than zero! + unknowns.at(4) = max(unknowns.at(4), 0.); //Keep deltaLambda greater than zero! + //compute residuals + sig = unknowns.at(1); + rho = unknowns.at(2); + tempKappaP = unknowns.at(3); + deltaLambda = unknowns.at(4); - return omega; -} + /* Compute the mVector holding the derivatives of the g function and the hardening function*/ + auto dGDInv = computeDGDInv(sig, rho, tempKappaP); + double dKappaDDeltaLambda = computeDKappaDDeltaLambda(sig, rho, theta, tempKappaP); -double -ConcreteDPM2 :: computeDamageParamCompression(double equivStrain, double kappaOne, double kappaTwo, double omegaOld) -{ - if ( isotropicFlag == 1 ) { - return 0.; - } + residuals.at(1) = sig - trialSig + this->kM * deltaLambda * dGDInv.at(1); + residuals.at(2) = rho - trialRho + ( 2. * this->gM ) * deltaLambda * dGDInv.at(2); + residuals.at(3) = -tempKappaP + kappaP + deltaLambda * dKappaDDeltaLambda; + residuals.at(4) = computeYieldValue(sig, rho, theta, tempKappaP); + } + } - double omega = 1.; - int nite = 0; - double residual = 0.; - double dResidualDOmega = 0.; - if ( equivStrain > e0 * ( 1. - yieldTolDamage ) ) { - do { - nite++; + //compute the principal directions of the stress + //auto [helpStress, stressPrincipalDir] = StructuralMaterial :: computePrincipalValDir(from_voigt_stress(trialStress)); // c++17 + auto tmpEig = StructuralMaterial::computePrincipalValDir( from_voigt_stress(trialStress) ); + auto stressPrincipalDir = tmpEig.second; - residual = ( 1. - omega ) * this->eM * equivStrain - this->ft *exp(-( kappaOne + omega * kappaTwo ) / this->efCompression); - dResidualDOmega = -this->eM * equivStrain + this->ft * kappaTwo / this->efCompression *exp(-( kappaOne + omega * kappaTwo ) / this->efCompression); + FloatArrayF < 6 > stressPrincipal; + stressPrincipal [ 0 ] = sig + sqrt(2. / 3.) * rho * cos(theta); + stressPrincipal [ 1 ] = sig + sqrt(2. / 3.) * rho * cos(theta - 2. * M_PI / 3.); + stressPrincipal [ 2 ] = sig + sqrt(2. / 3.) * rho * cos(theta + 2. * M_PI / 3.); + effectiveStress = transformStressVectorTo(stressPrincipalDir, stressPrincipal, 1); + returnResult = RR_Converged; - omega -= residual / dResidualDOmega; - if ( nite > newtonIter ) { - OOFEM_ERROR("algorithm not converging"); - } - } while ( fabs(residual / ft) >= 1.e-8 ); - } else { - omega = 0.; - } + //Store deltaLambda in status + status->letDeltaLambdaBe(deltaLambda); - if ( omega > 1. ) { - omega = 1.; + return tempKappaP; } - if ( omega < omegaOld || omega < 0. ) { - omega = omegaOld; - } - - return omega; -} + FloatMatrixF < 4, 4 > + ConcreteDPM2::computeJacobian(double sig, + double rho, + double theta, + double kappa, + double deltaLambda, + GaussPoint * gp) const + { + auto dFDInv = computeDFDInv(sig, rho, theta, kappa); + auto dGDInv = computeDGDInv(sig, rho, kappa); + auto dDGDDInv = computeDDGDDInv(sig, rho, kappa); + + double dKappaDDeltaLambda = computeDKappaDDeltaLambda(sig, rho, theta, kappa); + double dFDKappa = computeDFDKappa(sig, rho, theta, kappa); + + auto dDGDInvDKappa = computeDDGDInvDKappa(sig, rho, kappa); + + double dDKappaDDeltaLambdaDKappa = computeDDKappaDDeltaLambdaDKappa(sig, rho, theta, kappa); + auto dDKappaDDeltaLambdaDInv = computeDDKappaDDeltaLambdaDInv(sig, rho, theta, kappa); + + FloatMatrixF < 4, 4 > answer; + /* Compute matrix*/ + answer.at(1, 1) = 1. + this->kM * deltaLambda * dDGDDInv.at(1, 1); + answer.at(1, 2) = this->kM * deltaLambda * dDGDDInv.at(1, 2); + answer.at(1, 3) = this->kM * deltaLambda * dDGDInvDKappa.at(1); + answer.at(1, 4) = this->kM * dGDInv.at(1); + /**/ + answer.at(2, 1) = 2. * this->gM * deltaLambda * dDGDDInv.at(2, 1); + answer.at(2, 2) = 1. + 2. * this->gM * deltaLambda * dDGDDInv.at(2, 2); + answer.at(2, 3) = 2. * this->gM * deltaLambda * dDGDInvDKappa.at(2); + answer.at(2, 4) = 2. * this->gM * dGDInv.at(2); + /**/ + answer.at(3, 1) = deltaLambda * dDKappaDDeltaLambdaDInv.at(1); + answer.at(3, 2) = deltaLambda * dDKappaDDeltaLambdaDInv.at(2); + answer.at(3, 3) = deltaLambda * dDKappaDDeltaLambdaDKappa - 1.; + answer.at(3, 4) = dKappaDDeltaLambda; + /**/ + answer.at(4, 1) = dFDInv.at(1); + answer.at(4, 2) = dFDInv.at(2); + answer.at(4, 3) = dFDKappa; + answer.at(4, 4) = 0.; + return answer; + } + + + + + double + ConcreteDPM2::computeYieldValue(double sig, + double rho, + double theta, + double tempKappa) const + { + //compute yieldHard + double yieldHardOne = computeHardeningOne(tempKappa); + double yieldHardTwo = computeHardeningTwo(tempKappa); + + + // compute elliptic function r + double rFunction = ( 4. * ( 1. - pow(ecc, 2.) ) * pow(cos(theta), 2.) + + pow( ( 2. * ecc - 1. ), 2. ) ) / + ( 2. * ( 1. - pow(ecc, 2.) ) * cos(theta) + + ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - pow(ecc, 2.) ) * pow(cos(theta), 2.) + + 5. * pow(ecc, 2.) - 4. * ecc) ); + + //compute help function Al + double Al = ( 1. - yieldHardOne ) * pow( ( sig / fc + rho / ( sqrt(6.) * fc ) ), 2. ) + + sqrt(3. / 2.) * rho / fc; + + //Compute yield equation + return pow(Al, 2.) + + pow(yieldHardOne, 2.) * yieldHardTwo * m * ( sig / fc + rho * rFunction / ( sqrt(6.) * fc ) ) - + pow(yieldHardOne, 2.) * pow(yieldHardTwo, 2.); + } + + + double + ConcreteDPM2::computeDFDKappa(double sig, + double rho, + double theta, + double tempKappa) const + { + double dFDKappa; + //compute yieldHard and yieldSoft + double yieldHardOne = computeHardeningOne(tempKappa); + double yieldHardTwo = computeHardeningTwo(tempKappa); + // compute the derivative of the hardening and softening laws + double dYieldHardOneDKappa = computeHardeningOnePrime(tempKappa); + double dYieldHardTwoDKappa = computeHardeningTwoPrime(tempKappa); + //compute elliptic function r + double rFunction = + ( 4. * ( 1. - pow(ecc, 2) ) * pow(cos(theta), 2) + pow( ( 2. * ecc - 1. ), 2 ) ) / + ( 2 * ( 1. - pow(ecc, 2) ) * cos(theta) + ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - pow(ecc, 2) ) * pow(cos(theta), 2) + 5. * pow(ecc, 2) - 4. * ecc) ); -void -ConcreteDPM2 :: initDamaged(double kappaD, - const FloatArray &strain, - GaussPoint *gp) -{ - if ( kappaD <= 0. ) { - return; - } + //compute help functions Al, Bl + double Al = ( 1. - yieldHardOne ) * pow( ( sig / fc + rho / ( sqrt(6.) * fc ) ), 2.) + sqrt(3. / 2.) * rho / fc; - int indx = 1; - double le; - FloatArray principalStrains, crackPlaneNormal(3); - FloatMatrix principalDir; - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); - if ( helem > 0. ) { - status->setLe(helem); - } else if ( strain.giveSize() == 1 ) { - le = gp->giveElement()->computeLength(); - status->setLe(le); - } else if ( status->giveDamageTension() == 0. && status->giveDamageCompression() == 0. ) { - StructuralMaterial :: computePrincipalValDir(principalStrains, principalDir, strain, principal_strain); - // find index of max positive principal strain - for ( int i = 2; i <= 3; i++ ) { - if ( principalStrains.at(i) > principalStrains.at(indx) ) { - indx = i; - } - } + double Bl = sig / fc + rho / ( fc * sqrt(6.) ); + double dFDYieldHardOne = -2. * Al * pow(Bl, 2.) + + 2. * yieldHardOne * yieldHardTwo * m * ( sig / fc + rho * rFunction / ( sqrt(6.) * fc ) ) - 2. * yieldHardOne * pow(yieldHardTwo, 2.); - for ( int i = 1; i <= 3; i++ ) { - crackPlaneNormal.at(i) = principalDir.at(i, indx); - } + double dFDYieldHardTwo = pow(yieldHardOne, 2.) * m * ( sig / fc + rho * rFunction / ( sqrt(6.) * fc ) ) - 2. * yieldHardTwo * pow(yieldHardOne, 2.); - // evaluate the projected element size - le = gp->giveElement()->giveCharacteristicLength(crackPlaneNormal); - if ( le == 0. ) { - le = gp->giveElement()->computeMeanSize(); + // compute dFDKappa + dFDKappa = dFDYieldHardOne * dYieldHardOneDKappa + + dFDYieldHardTwo * dYieldHardTwoDKappa; + /* + * set dFDKappa to zero, if it becomes greater than zero. + * dFDKappa can only be negative or zero in the converged state for + * the case of hardenig and perfect plasticity. For trial stresses, however, + * it might be psoitive, which may lead to convergency problems. Therefore, + * it is set to zero in this cases. + */ + if ( dFDKappa > 0. ) { + dFDKappa = 0.; } - // store le in the corresponding status - status->setLe(le); - } else if ( status->giveLe() == 0. ) { - // this happens if the status is initialized from a file - // with nonzero damage - // le determined as square root of element area or cube root of el. volume - le = gp->giveElement()->computeMeanSize(); - status->setLe(le); + return dFDKappa; } -} + FloatArrayF < 2 > + ConcreteDPM2::computeDFDInv(double sig, + double rho, + double theta, + double tempKappa) const + { + //compute yieldHard + double yieldHardOne = computeHardeningOne(tempKappa); + double yieldHardTwo = computeHardeningTwo(tempKappa); -double -ConcreteDPM2 :: computeDuctilityMeasureDamage(const FloatArray &strain, GaussPoint *gp) -{ - //Angle in uniaxial compression is atan(1./sqrt(6.))=0.387597 - double alphaZero = 0.40824829; + //compute elliptic function r + double rFunction = ( 4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) + ( 2. * ecc - 1. ) * ( 2. * ecc - 1. ) ) / + ( 2. * ( 1. - ecc * ecc ) * cos(theta) + ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) + + 5. * ecc * ecc - 4. * ecc) ); - double Rs = 0; - if ( this->sig < 0. ) { - if ( this->rho > 1.e-16 ) { - Rs = -this->sig / ( alphaZero * this->rho ); - } else { //Need to set a dummy valye - Rs = -this->sig * 1.e16 / alphaZero; - } - } else { - Rs = 0; - } + //compute help functions AL, BL + double AL = ( 1. - yieldHardOne ) * pow( ( sig / fc + rho / ( sqrt(6.) * fc ) ), 2. ) + sqrt(3. / 2.) * rho / fc; + double BL = sig / fc + rho / ( fc * sqrt(6.) ); - return 1. + ( ASoft - 1. ) * Rs; // ductilityMeasure -} + //compute dfdsig + double dfdsig = 4. * ( 1. - yieldHardOne ) / fc * AL * BL + yieldHardTwo * pow(yieldHardOne, 2.) * m / fc; + //compute dfdrho + double dfdrho = AL / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * BL + 6. ) + rFunction * m * yieldHardTwo * pow(yieldHardOne, 2.) / ( sqrt(6.) * fc ); -void -ConcreteDPM2 :: performPlasticityReturn(GaussPoint *gp, - const FloatMatrix &D, - const FloatArray &strain) -{ - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); + return { + dfdsig, dfdrho + }; + } - FloatMatrix C; - C.beInverseOf(D); - //get temp plastic strain and tempKappa - FloatArray tempPlasticStrain = status->givePlasticStrain(); - double tempKappaP = status->giveKappaP(); + double + ConcreteDPM2::computeDKappaDDeltaLambda(double sig, + double rho, + double theta, + double tempKappa) const + { + auto dGDInv = computeDGDInv(sig, rho, tempKappa); + double equivalentDGDStress = sqrt(1. / 3. * pow(dGDInv [ 0 ], 2.) + pow(dGDInv [ 1 ], 2.) ); + double ductilityMeasure = computeDuctilityMeasure(sig, rho, theta); + return equivalentDGDStress / ductilityMeasure; // dKappaDDeltaLambda + } - // compute elastic strains and trial stress - FloatArray effectiveStress; - FloatArray elasticStrain = strain; - for ( int i = 1; i <= elasticStrain.giveSize(); ++i ) elasticStrain.at(i) -= tempPlasticStrain.at(i); - effectiveStress.beProductOf(D, elasticStrain); + FloatArrayF < 2 > + ConcreteDPM2::computeDDKappaDDeltaLambdaDInv(double sig, + double rho, + double theta, + double tempKappa) const + { + //Compute first and second derivative of plastic potential + auto dGDInv = computeDGDInv(sig, rho, tempKappa); + auto dDGDDInv = computeDDGDDInv(sig, rho, tempKappa); - //Compute trial coordinates - computeTrialCoordinates(effectiveStress, this->sig, this->rho, this->thetaTrial); + //Compute equivalentDGDStress + double equivalentDGDStress = sqrt(1. / 3. * pow(dGDInv [ 0 ], 2.) + pow(dGDInv [ 1 ], 2.) ); - double yieldValue; - - FloatArray convergedStrain; - - //What happens here to thermal strains that are subtracted first? - FloatArray oldStrain = status->giveStrainVector(); - FloatArray tempStrain; - FloatArray deltaStrain; - - // introduce a strange subincrementation flag - int subIncrementFlag = 0; - - double apexStress = 0.; - int subincrementcounter = 0; - //Attempt to implement subincrementation - // initialize variables - subIncrementFlag = 0; - convergedStrain = oldStrain; - tempStrain = strain; - deltaStrain.beDifferenceOf(strain, oldStrain); - //To get into the loop - returnResult = RR_NotConverged; - while ( returnResult == RR_NotConverged || subIncrementFlag == 1 ) { - elasticStrain = tempStrain; - for ( int i = 1; i <= elasticStrain.giveSize(); ++i ) elasticStrain.at(i) -= tempPlasticStrain.at(i); - //elasticStrain.subtract(tempPlasticStrain); - effectiveStress.beProductOf(D, elasticStrain); - double theta; - computeTrialCoordinates(effectiveStress, this->sig, this->rho, theta); - yieldValue = computeYieldValue(this->sig, this->rho, this->thetaTrial, tempKappaP); + //computeDuctilityMeasure + double ductilityMeasure = computeDuctilityMeasure(sig, rho, theta); - apexStress = 0.; + //Compute dEquivalentDGDStressDInv + FloatArrayF < 2 > dEquivalentDGDStressDInv; + dEquivalentDGDStressDInv [ 0 ] = + ( 2. / 3. * dGDInv [ 0 ] * dDGDDInv(0, 0) + 2. * dGDInv [ 1 ] * dDGDDInv(1, 0) ) / ( 2. * equivalentDGDStress ); + dEquivalentDGDStressDInv [ 1 ] = + ( 2. / 3. * dGDInv [ 0 ] * dDGDDInv(0, 1) + 2. * dGDInv [ 1 ] * dDGDDInv(1, 1) ) / ( 2. * equivalentDGDStress ); - if ( yieldValue > 0. ) { - checkForVertexCase(apexStress, sig, tempKappaP, strain.giveSize() == 1); - if ( returnType == RT_Tension || returnType == RT_Compression ) { - tempKappaP = performVertexReturn(effectiveStress, apexStress, tempKappaP, gp); - status->letTempKappaPBe(tempKappaP); - } - if ( returnType == RT_Regular ) { - tempKappaP = performRegularReturn(effectiveStress, tempKappaP, gp); - status->letTempKappaPBe(tempKappaP); - } - } else { - returnResult = RR_Converged; - tempPlasticStrain = status->givePlasticStrain(); - status->letTempPlasticStrainBe(tempPlasticStrain); - status->letTempKappaPBe(tempKappaP); - break; - } - if ( returnResult == RR_NotConverged ) { - subincrementcounter++; - if ( subincrementcounter > 10 ) { - OOFEM_LOG_INFO( "Unstable element %d \n", gp->giveElement()->giveGlobalNumber() ); - OOFEM_LOG_INFO( "Old strain vector %g %g %g %g %g %g \n", oldStrain.at(1), oldStrain.at(2), oldStrain.at(3), oldStrain.at(4), oldStrain.at(5), oldStrain.at(6) ); - FloatArray help = status->giveTempPlasticStrain(); - FloatArray help1; - double sig1, rho1, theta1; - oldStrain.subtract(help); - help1.beProductOf(D, oldStrain); - OOFEM_LOG_INFO( "Old plastic strain vector %g %g %g %g %g %g \n", help.at(1), help.at(2), help.at(3), help.at(4), help.at(5), help.at(6) ); - OOFEM_LOG_INFO( "New strain vector %g %g %g %g %g %g \n", strain.at(1), strain.at(2), strain.at(3), strain.at(4), strain.at(5), strain.at(6) ); - computeTrialCoordinates(effectiveStress, this->sig, this->rho, theta); - computeTrialCoordinates(help1, sig1, rho1, theta1); - yieldValue = computeYieldValue(this->sig, this->rho, this->thetaTrial, tempKappaP); - OOFEM_LOG_INFO("OLD Sig %g rho %g theta %g \n", sig1, rho1, theta1); - OOFEM_LOG_INFO("NEW Sig %g rho %g theta %g \n", sig, rho, theta); - if ( returnType == RT_Tension || returnType == RT_Compression ) { - OOFEM_LOG_INFO("Vertex case apexstress %g\n", apexStress); - } else { - OOFEM_LOG_INFO("Regular case %g \n", 15.18); - } - OOFEM_LOG_INFO("KappaP old %g new %g yieldfun %g\n", status->giveTempKappaP(), tempKappaP, yieldValue); - OOFEM_ERROR("Could not reach convergence with small deltaStrain, giving up."); - } else if ( subincrementcounter > 9 && tempKappaP < 1. ) { - tempKappaP = 1.; - status->letTempKappaPBe(tempKappaP); - } + // compute the derivative of + auto dDuctilityMeasureDInv = computeDDuctilityMeasureDInv(sig, rho, theta, tempKappa); - subIncrementFlag = 1; - deltaStrain.times(0.5); - tempStrain = convergedStrain; - tempStrain.add(deltaStrain); - } else if ( returnResult == RR_Converged && subIncrementFlag == 0 ) { - elasticStrain.beProductOf(C, effectiveStress); - tempPlasticStrain = strain; - tempPlasticStrain.subtract(elasticStrain); - status->letTempPlasticStrainBe(tempPlasticStrain); - } else if ( returnResult == RR_Converged && subIncrementFlag == 1 ) { - OOFEM_LOG_INFO("Subincrementation %d required\n", subincrementcounter); - subincrementcounter = 0; - elasticStrain.beProductOf(C, effectiveStress); - tempPlasticStrain = tempStrain; - tempPlasticStrain.subtract(elasticStrain); - status->letTempPlasticStrainBe(tempPlasticStrain); - - subIncrementFlag = 0; - returnResult = RR_NotConverged; - convergedStrain = tempStrain; - deltaStrain.beDifferenceOf(strain, convergedStrain); - tempStrain = strain; - } + FloatArrayF < 2 > answer; + answer [ 0 ] = ( dEquivalentDGDStressDInv [ 0 ] * ductilityMeasure - equivalentDGDStress * dDuctilityMeasureDInv [ 0 ] ) / pow(ductilityMeasure, 2.); + answer [ 1 ] = ( dEquivalentDGDStressDInv [ 1 ] * ductilityMeasure - equivalentDGDStress * dDuctilityMeasureDInv [ 1 ] ) / pow(ductilityMeasure, 2.); + return answer; } -} + FloatArrayF < 6 > + ConcreteDPM2::computeDDKappaDDeltaLambdaDStress(const FloatArrayF < 6 > & stress, double tempKappa) const + { + auto tmp = computeDeviatoricVolumetricSplit(stress); + auto deviatoricStress = tmp.first; + double sig = tmp.second; -bool -ConcreteDPM2 :: checkForVertexCase(double &answer, - double sig, - double tempKappa, - bool mat1d) -{ - if ( mat1d ) { - returnType = RT_Regular; - return false; - } - - answer = 0.; - if ( sig > 0. ) { - returnType = RT_Tension; - } else if ( sig < 0. && tempKappa < 1. ) { - returnType = RT_Compression; - } else { - returnType = RT_Regular; - } - return false; -} + double rho = computeSecondCoordinate(deviatoricStress); + double theta = computeThirdCoordinate(deviatoricStress); + auto dDKappaDDeltaLambdaDInv = computeDDKappaDDeltaLambdaDInv(sig, rho, theta, tempKappa); + // compute dDKappaDDeltaLambdaDCosTheta + auto dGDInv = computeDGDInv(sig, rho, tempKappa); -double -ConcreteDPM2 :: performVertexReturn(FloatArray &effectiveStress, - double apexStress, double tempKappaP, - GaussPoint *gp) -{ - FloatArray deviatoricStressTrial; - double sigTrial; - double yieldValue = 0.; - double yieldValueMid = 0.; - double sig2 = 0.; - double dSig; - double sigMid; - double sigAnswer; - double ratioPotential; + double equivalentDGDStress = sqrt(1. / 3. * pow(dGDInv [ 0 ], 2.) + pow(dGDInv [ 1 ], 2.) ); - sigTrial = computeDeviatoricVolumetricSplit(deviatoricStressTrial, effectiveStress); - double rhoTrial = computeSecondCoordinate(deviatoricStressTrial); + double ductilityMeasure = computeDuctilityMeasure(sig, rho, theta); - double kappaInitial = tempKappaP; + //Reuse implementation to compute dKappaDDeltaLambdaDCosTheta + //Ductility measure has in denominator (2*cos(theta))^2 + double dDKappaDDeltaLambdaDCosTheta = equivalentDGDStress / ductilityMeasure / cos(theta); + // dDKappaDDeltaLambdaDCosTheta = 0.; - sig2 = apexStress; + auto dSigDStress = computeDSigDStress(); + auto dRhoDStress = computeDRhoDStress(stress); + auto dCosThetaDStress = computeDCosThetaDStress(stress); - tempKappaP = - computeTempKappa(kappaInitial, sigTrial, rhoTrial, sigTrial); + dSigDStress *= dDKappaDDeltaLambdaDInv.at(1); - yieldValue = - computeYieldValue(sigTrial, 0., 0., tempKappaP); + dRhoDStress *= dDKappaDDeltaLambdaDInv.at(2); - tempKappaP = - computeTempKappa(kappaInitial, sigTrial, rhoTrial, sig2); + dCosThetaDStress *= dDKappaDDeltaLambdaDCosTheta; - yieldValueMid = - computeYieldValue(sig2, 0., 0., tempKappaP); + auto dDKappaDDeltaLambdaDStress = dSigDStress + dRhoDStress + dCosThetaDStress; - if ( yieldValue * yieldValueMid >= 0. ) { - returnType = RT_Regular; - returnResult = RR_NotConverged; - return kappaInitial; + return dDKappaDDeltaLambdaDStress; } - if ( yieldValue < 0.0 ) { - dSig = sig2 - sigTrial; - sigAnswer = sig2; - } else { - dSig = sigTrial - sig2; - sigAnswer = sig2; - } + FloatArrayF < 6 > + ConcreteDPM2::computeDDGDStressDKappa(const FloatArrayF < 6 > & stress, double tempKappa) const + { + FloatArrayF < 6 > answer; - for ( int j = 0; j < 250; j++ ) { - dSig = 0.5 * dSig; + auto tmp = computeDeviatoricVolumetricSplit(stress); + auto deviatoricStress = tmp.first; + double sig = tmp.second; - sigMid = sigAnswer + dSig; + double rho = computeSecondCoordinate(deviatoricStress); + // double theta = computeThirdCoordinate(deviatoricStress); + auto dDGDInvDKappa = computeDDGDInvDKappa(sig, rho, tempKappa); + auto dSigDStress = computeDSigDStress(); + auto dRhoDStress = computeDRhoDStress(stress); - tempKappaP = - computeTempKappa(kappaInitial, sigTrial, rhoTrial, sigMid); + answer = dSigDStress; + answer *= dDGDInvDKappa.at(1); - yieldValueMid = computeYieldValue(sigMid, 0., 0., tempKappaP); + FloatArrayF < 6 > temp1; + temp1 = dRhoDStress; + temp1 *= dDGDInvDKappa.at(2); - if ( yieldValueMid <= 0. ) { - sigAnswer = sigMid; - } + answer += temp1; - if ( fabs(yieldValueMid) < yieldTol && yieldValueMid <= 0. ) { - // //Put tempKappaP in the status - // status->letTempKappaPBe(tempKappaP); + return answer; + } - ratioPotential = - computeRatioPotential(sigAnswer, tempKappaP); - double ratioTrial = rhoTrial / ( sigTrial - sigAnswer ); + double + ConcreteDPM2::computeDDKappaDDeltaLambdaDKappa(double sig, double rho, double theta, double tempKappa) const + { + //Compute first and second derivative of plastic potential + auto dGDInv = computeDGDInv(sig, rho, tempKappa); + auto dDGDInvDKappa = computeDDGDInvDKappa(sig, rho, tempKappa); - if ( ( ( ( ratioPotential >= ratioTrial ) && returnType == RT_Tension ) ) || - ( ( ratioPotential <= ratioTrial ) && returnType == RT_Compression ) ) { - for ( int i = 0; i < 3; i++ ) { - effectiveStress(i) = sigAnswer; - } + double equivalentDGDStress = sqrt( 1. / 3. * pow(dGDInv [ 0 ], 2.) + pow(dGDInv [ 1 ], 2.) ); - for ( int i = 3; i < effectiveStress.giveSize(); i++ ) { - effectiveStress(i) = 0.; - } - returnResult = RR_Converged; - return tempKappaP; - } else { - returnType = RT_Regular; - returnResult = RR_NotConverged; - return kappaInitial; - } - } - } + double ductilityMeasure = computeDuctilityMeasure(sig, rho, theta); + //Compute dEquivalentDGDStressDKappa + double dEquivalentDGDStressDKappa = + ( 2. / 3. * dGDInv [ 0 ] * dDGDInvDKappa [ 0 ] + 2. * dGDInv [ 1 ] * dDGDInvDKappa [ 1 ] ) / ( 2. * equivalentDGDStress ); - for ( int i = 0; i < 3; i++ ) { - effectiveStress(i) = sigAnswer; + return dEquivalentDGDStressDKappa / ductilityMeasure; } - for ( int i = 3; i < effectiveStress.giveSize(); i++ ) { - effectiveStress(i) = 0.; + FloatArrayF < 2 > + ConcreteDPM2::computeDDuctilityMeasureDInv(double sig, + double rho, + double theta, + double tempKappa) const + { + double thetaConst = pow(2. * cos(theta), 2.); + double x = ( -( sig + fc / 3. ) ) / fc; + + if ( x < 0. ) { + double dXDSig = -1. / fc; + /* Introduce exponential help function which results in a + * smooth transition. */ + double EHard = BHard - DHard; + double FHard = ( BHard - DHard ) * CHard / ( AHard - BHard ); + + double dDuctilityMeasureDX = EHard / FHard * exp(x / FHard) / thetaConst; + return { + dDuctilityMeasureDX *dXDSig, 0. + }; + } else { + double dXDSig = -1. / fc; + double dDuctilityMeasureDX = -( BHard - AHard ) / ( CHard ) / thetaConst * exp(-x / ( CHard ) ); + return { + dDuctilityMeasureDX *dXDSig, 0. + }; + } } - returnResult = RR_Converged; - //// Warning solution NOT CONVERGED!!!! - return tempKappaP; -} + FloatArrayF < 2 > + ConcreteDPM2::computeDGDInv(double sig, + double rho, + double tempKappa) const + { + //compute yieldHard and yieldSoft + double yieldHardOne = computeHardeningOne(tempKappa); + double yieldHardTwo = computeHardeningTwo(tempKappa); -double -ConcreteDPM2 :: computeTempKappa(double kappaInitial, - double sigTrial, - double rhoTrial, - double sig) -{ - //This function is called, if stress state is in vertex case - double equivalentDeltaPlasticStrain; - rho = 0.; - equivalentDeltaPlasticStrain = sqrt( 1. / 9. * pow( ( sigTrial - sig ) / ( kM ), 2. ) + - pow(rhoTrial / ( 2. * gM ), 2.) ); - - double thetaVertex = M_PI / 3.; - double ductilityMeasure = computeDuctilityMeasure(sig, rho, thetaVertex); - - return kappaInitial + equivalentDeltaPlasticStrain / ductilityMeasure; -} + //Compute dilation parameter + double AGParam = this->ft * yieldHardTwo * 3 / this->fc + m / 2; + double BGParam = + yieldHardTwo / 3. * ( 1. + this->ft / this->fc ) / + ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); + double R = ( sig - ft / 3. * yieldHardTwo ) / fc / BGParam; + double mQ = AGParam * exp(R); -double -ConcreteDPM2 :: computeDuctilityMeasure(double sig, - double rho, - double theta) -{ - double thetaConst = pow(2. * cos(theta), 2.); - double ductilityMeasure; - double x = -( sig + fc / 3 ) / fc; - if ( x < 0. ) { - /*Introduce exponential help function which results in a smooth - * transition. */ - double EHard = BHard - DHard; - double FHard = ( BHard - DHard ) * CHard / ( AHard - BHard ); - ductilityMeasure = ( EHard * exp(x / FHard) + DHard ) / thetaConst; - } else { - ductilityMeasure = ( AHard + ( BHard - AHard ) * exp( -x / ( CHard ) ) ) / thetaConst; - } - - return ductilityMeasure; -} - - -double -ConcreteDPM2 :: computeRatioPotential(double sig, - double tempKappa) -{ - //compute yieldHard and yieldSoft - double yieldHardOne = computeHardeningOne(tempKappa); - double yieldHardTwo = computeHardeningTwo(tempKappa); - - //Compute dilation parameter - double AGParam = this->ft * yieldHardTwo * 3 / this->fc + m / 2; - double BGParam = - yieldHardTwo / 3. * ( 1. + this->ft / this->fc ) / - ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); - - double R = ( sig - ft / 3. * yieldHardTwo ) / fc / BGParam; - double mQ = AGParam * exp(R); - - double Bl = sig / fc + rho / ( fc * sqrt(6.) ); - - double Al = ( 1. - yieldHardOne ) * pow(Bl, 2.) + sqrt(3. / 2.) * rho / fc; - - double dgdsig = 4. * ( 1. - yieldHardOne ) / fc * Al * Bl + pow(yieldHardOne, 2.) * mQ / fc; - - double dgdrho = Al / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) + - - m *pow(yieldHardOne, 2.) / ( sqrt(6.) * fc ); - - return dgdrho / dgdsig * 3. * ( 1. - 2. * nu ) / ( 1. + nu ); -} - - -double -ConcreteDPM2 :: performRegularReturn(FloatArray &effectiveStress, - double kappaP, - GaussPoint *gp) -{ - FloatArray trialStress, deviatoricTrialStress; - FloatArray residuals, residualsNorm, deltaIncrement, dGDInv; - FloatMatrix jacobian; - FloatArray unknowns; - - double yieldValue; - double dKappaDDeltaLambda; - double deltaLambda = 0.; - double normOfResiduals = 0.; - int iterationCount = 0; - bool mode3d = effectiveStress.giveSize() > 1; - - //Define stressVariables - double trialSig, trialRho; - - trialStress = effectiveStress; - - //compute the principal directions of the stress - FloatArray helpStress; - FloatMatrix stressPrincipalDir; - - //compute invariants from stress state - if ( mode3d ) { - StructuralMaterial :: computePrincipalValDir(helpStress, stressPrincipalDir, trialStress, principal_stress); - trialSig = computeDeviatoricVolumetricSplit(deviatoricTrialStress, trialStress); - trialRho = computeSecondCoordinate(deviatoricTrialStress); - } else { //1d case - double angle; // this variable is used only as an input to the function computeTrialCoordinates and is not important and it is already calculated - computeTrialCoordinates(trialStress, trialSig, trialRho, angle); - } + double Bl = sig / fc + rho / ( fc * sqrt(6.) ); - sig = trialSig; - rho = trialRho; + double Al = ( 1. - yieldHardOne ) * pow(Bl, 2.) + sqrt(3. / 2.) * rho / fc; + double dgdsig = 4. * ( 1. - yieldHardOne ) / fc * Al * Bl + pow(yieldHardOne, 2.) * mQ / fc; - // Starting guess: - double tempKappaP = kappaP; + double dgdrho = Al / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) + + m * pow(yieldHardOne, 2.) / ( sqrt(6.) * fc ); - //initialise unknowns - if ( mode3d ) { - residuals.resize(4); - unknowns.resize(4); - unknowns.at(1) = trialSig; - unknowns.at(2) = trialRho; - unknowns.at(3) = tempKappaP; - unknowns.at(4) = 0.; - } else { //1D case - residuals.resize(3); - unknowns.resize(3); - unknowns.at(1) = trialSig * 3.; // It is calculated as the volumetric stress in this case sigma/3 - unknowns.at(2) = tempKappaP; - unknowns.at(3) = 0.; + return { + dgdsig, dgdrho + }; } - // Look at the magnitudes of the residuals. You have to scale the yieldValue down. - yieldValue = computeYieldValue(sig, rho, thetaTrial, tempKappaP); + FloatArrayF < 6 > + ConcreteDPM2::computeDFDStress(const FloatArrayF < 6 > & stress, + double tempKappa) const + { + double sig, rho, theta; + computeCoordinates(stress, sig, rho, theta); + auto dFDInv = computeDFDInv(sig, rho, theta, tempKappa); - //initiate residuals - residuals.zero(); - residuals.at( residuals.giveSize() ) = yieldValue; //store in the last element of the array + double dRDCosTheta = computeDRDCosTheta(theta, this->ecc); - normOfResiduals = 1.; //just to get into the loop + double yieldHardOne = computeHardeningOne(tempKappa); + double yieldHardTwo = computeHardeningTwo(tempKappa); - /* N.R. iteration for finding the correct plastic return which is found when the norm of the residuals are equal to zero*/ - - while ( normOfResiduals > yieldTol ) { - iterationCount++; - if ( iterationCount == newtonIter ) { - returnResult = RR_NotConverged; - return kappaP; - } + //Compute dFDCosTheta. This was not needed for the stress return, but now for the tangent stiffness + auto dFDCosTheta = dRDCosTheta * pow(yieldHardOne, 2.) * yieldHardTwo * m * rho / ( sqrt(6.) * fc ); - residualsNorm = residuals; - if ( effectiveStress.giveSize() > 1 ) { - //Normalize residuals. Think about it more. - residualsNorm.at(1) /= this->kM; - residualsNorm.at(2) /= 2. * this->gM; - } else { //1D case - residualsNorm.at(1) /= this->eM; - } + auto dSigDStress = computeDSigDStress(); + auto dRhoDStress = computeDRhoDStress(stress); + auto dCosThetaDStress = computeDCosThetaDStress(stress); - normOfResiduals = residualsNorm.computeNorm(); + dSigDStress *= dFDInv.at(1); + dRhoDStress *= dFDInv.at(2); + dCosThetaDStress *= dFDCosTheta; - if ( std :: isnan(normOfResiduals) ) { - returnResult = RR_NotConverged; - return kappaP; - } + auto dFDStress = dSigDStress + dRhoDStress + dCosThetaDStress; - if ( normOfResiduals > yieldTol ) { - // Test to run newton iteration using inverse of Jacobian - if ( mode3d ) { - computeJacobian(jacobian, sig, rho, tempKappaP, deltaLambda, gp); + return dFDStress; + } - if ( !jacobian.solveForRhs(residuals, deltaIncrement) ) { - returnResult = RR_NotConverged; - return kappaP; - } + FloatArrayF < 6 > + ConcreteDPM2::computeDGDStress(const FloatArrayF < 6 > & stress, const double tempKappa) const + { + auto tmp = computeDeviatoricVolumetricSplit(stress); + auto deviatoricStress = tmp.first; + double sig = tmp.second; + double rho = computeSecondCoordinate(deviatoricStress); - //compute Unknowns - unknowns.subtract(deltaIncrement); + //compute dGDSig*dSigDStress + dGDRho*dRhoDStress + auto dGDInv = computeDGDInv(sig, rho, tempKappa); + auto dSigDStress = computeDSigDStress(); + auto dRhoDStress = computeDRhoDStress(stress); - if ( unknowns.at(4) <= 0. ) { //Keep deltaLambda greater than zero! - unknowns.at(4) = 0.; - } + dSigDStress *= dGDInv.at(1); + dRhoDStress *= dGDInv.at(2); + dSigDStress += dRhoDStress; - if ( unknowns.at(2) <= 0. ) { //Keep rho greater than zero! - unknowns.at(2) = 0.; - } + return dSigDStress; + } - if ( unknowns.at(3) - kappaP <= 0. ) { //Keep deltaKappa greater than zero! - unknowns.at(3) = kappaP; - } - //compute residuals - sig = unknowns.at(1); - rho = unknowns.at(2); - tempKappaP = unknowns.at(3); - deltaLambda = unknowns.at(4); + //Debug + FloatMatrixF < 8, 8 > + ConcreteDPM2::computeFullJacobian(const FloatArrayF < 6 > & stress, + const double deltaLambda, + GaussPoint * gp, + TimeStep * atTime, + const double tempKappa) const + { + FloatMatrixF < 8, 8 > jacobian; + auto dFDStress = computeDFDStress(stress, tempKappa); + auto dGDStress = computeDGDStress(stress, tempKappa); + auto dDGDDStress = computeDDGDDStress(stress, tempKappa); + auto dDGDStressDKappa = computeDDGDStressDKappa(stress, tempKappa); + auto dDKappaDDeltaLambdaDStress = computeDDKappaDDeltaLambdaDStress(stress, tempKappa); - /* Compute the mVector holding the derivatives of the g function and the hardening function*/ - computeDGDInv(dGDInv, sig, rho, tempKappaP); - dKappaDDeltaLambda = computeDKappaDDeltaLambda(sig, rho, tempKappaP); + double sig, rho, theta; + computeCoordinates(stress, sig, rho, theta); - residuals.at(1) = sig - trialSig + this->kM *deltaLambda *dGDInv.at(1); - residuals.at(2) = rho - trialRho + ( 2. * this->gM ) * deltaLambda * dGDInv.at(2); - residuals.at(3) = -tempKappaP + kappaP + deltaLambda * dKappaDDeltaLambda; - residuals.at(4) = computeYieldValue(sig, rho, thetaTrial, tempKappaP); - } else { - compute1dJacobian(jacobian, 3. * sig, tempKappaP, deltaLambda, gp); + double dFDKappa = computeDFDKappa(sig, rho, theta, tempKappa); + double dKappaDDeltaLambda = computeDKappaDDeltaLambda(sig, rho, theta, tempKappa); - if ( !jacobian.solveForRhs(residuals, deltaIncrement) ) { - returnResult = RR_NotConverged; - return kappaP; - } + double dDKappaDDeltaLambdaDKappa = computeDDKappaDDeltaLambdaDKappa(sig, rho, theta, tempKappa); - //compute Unknowns - unknowns.subtract(deltaIncrement); + auto d = this->linearElasticMaterial.give3dMaterialStiffnessMatrix(ElasticStiffness, gp, atTime); - if ( unknowns.at(3) <= 0. ) { //Keep deltaLambda greater equal than zero! - unknowns.at(3) = 0.; - } + auto helpA = dot(d, dDGDDStress); - if ( unknowns.at(2) - kappaP <= 0. ) { //Keep deltaKappa greater equal than zero! - unknowns.at(2) = kappaP; + //Assign jacobian + for ( int i = 0; i < 6; i++ ) { + for ( int j = 0; j < 6; j++ ) { + if ( i == j ) { + jacobian.at(i + 1, j + 1) = 1. + deltaLambda * helpA.at(i + 1, j + 1); + } else { + jacobian.at(i + 1, j + 1) = deltaLambda * helpA.at(i + 1, j + 1); } - - //compute residuals - sig = unknowns.at(1) / 3.; - rho = unknowns.at(1) * sqrt(2. / 3.); //for the 1d case - - tempKappaP = unknowns.at(2); - deltaLambda = unknowns.at(3); - - /* Compute the mVector holding the derivatives of the g function and the hardening function*/ - double dginv = computeDGDInv1d(unknowns.at(1), tempKappaP); - dKappaDDeltaLambda = computeDKappaDDeltaLambda1d(unknowns.at(1), tempKappaP); - - residuals.at(1) = 3. * ( sig - trialSig ) + this->eM *deltaLambda * dginv; - residuals.at(2) = -tempKappaP + kappaP + deltaLambda * dKappaDDeltaLambda; - residuals.at(3) = computeYieldValue(sig, rho, thetaTrial, tempKappaP); } } - } - returnResult = RR_Converged; - if ( mode3d ) { - FloatArray stressPrincipal(6); - stressPrincipal.zero(); + FloatArrayF < 6 > helpB; + helpB = dot(d, dDGDStressDKappa); - stressPrincipal(0) = sig + sqrt(2. / 3.) * rho * cos(thetaTrial); - stressPrincipal(1) = sig + sqrt(2. / 3.) * rho * cos(thetaTrial - 2. * M_PI / 3.); - stressPrincipal(2) = sig + sqrt(2. / 3.) * rho * cos(thetaTrial + 2. * M_PI / 3.); - transformStressVectorTo(effectiveStress, stressPrincipalDir, stressPrincipal, 1); - } else { - effectiveStress.at(1) = sig * 3; - } + for ( int i = 0; i < 6; i++ ) { + jacobian.at(i + 1, 7) = deltaLambda * helpB.at(i + 1); + } - return tempKappaP; -} + helpB = dot(d, dGDStress); -void -ConcreteDPM2 :: compute1dJacobian(FloatMatrix &answer, - double totalsigma, - double kappa, - double deltaLambda, - GaussPoint *gp) -{ - double dFDInv = computeDFDInv1d(totalsigma, kappa); - double dGDInv = computeDGDInv1d(totalsigma, kappa); - double dDGDDInv = computeDDGDDInv1d(totalsigma, kappa); - double dKappaDDeltaLambda = computeDKappaDDeltaLambda(totalsigma, 1, kappa); - double dFDKappa = computeDFDKappa(totalsigma, 1, kappa, true); - double dDGDInvDKappa = computeDDGDInvDKappa1d(totalsigma, kappa); - double dDKappaDDeltaLambdaDKappa = computeDDKappaDDeltaLambdaDKappa1d(totalsigma, kappa); - double dDKappaDDeltaLambdaDInv = computeDDKappaDDeltaLambdaDInv1d(totalsigma, kappa); - - answer.resize(3, 3); - /* Compute matrix*/ - /* 1st row */ - answer.at(1, 1) = 1. + this->eM * deltaLambda * dDGDDInv; - answer.at(1, 2) = this->eM * deltaLambda * dDGDInvDKappa; - answer.at(1, 3) = this->eM * dGDInv; - /* 2nd row */ - answer.at(2, 1) = deltaLambda * dDKappaDDeltaLambdaDInv; - answer.at(2, 2) = deltaLambda * dDKappaDDeltaLambdaDKappa - 1.; - answer.at(2, 3) = dKappaDDeltaLambda; - /* 3rd row */ - answer.at(3, 1) = dFDInv; - answer.at(3, 2) = dFDKappa; - answer.at(3, 3) = 0.; -} - - -void -ConcreteDPM2 :: computeJacobian(FloatMatrix &answer, - double sig, - double rho, - double kappa, - double deltaLambda, - GaussPoint *gp) -{ - FloatArray dFDInv; - computeDFDInv(dFDInv, sig, rho, kappa); + for ( int i = 0; i < 6; i++ ) { + jacobian.at(i + 1, 8) = helpB.at(i + 1); + } - FloatArray dGDInv; - computeDGDInv(dGDInv, sig, rho, kappa); + for ( int i = 0; i < 6; i++ ) { + jacobian.at(7, i + 1) = deltaLambda * dDKappaDDeltaLambdaDStress.at(i + 1); + } - FloatMatrix dDGDDInv; - computeDDGDDInv(dDGDDInv, sig, rho, kappa); - double dKappaDDeltaLambda = computeDKappaDDeltaLambda(sig, rho, kappa); + jacobian.at(7, 7) = deltaLambda * dDKappaDDeltaLambdaDKappa - 1.; + jacobian.at(7, 8) = dKappaDDeltaLambda; - double dFDKappa = computeDFDKappa(sig, rho, kappa, false); + for ( int i = 0; i < 6; i++ ) { + jacobian.at(8, i + 1) = dFDStress.at(i + 1); + } - FloatArray dDGDInvDKappa; - computeDDGDInvDKappa(dDGDInvDKappa, sig, rho, kappa); + jacobian.at(8, 7) = dFDKappa; + jacobian.at(8, 8) = 0.; + return jacobian; + } - double dDKappaDDeltaLambdaDKappa; - dDKappaDDeltaLambdaDKappa = computeDDKappaDDeltaLambdaDKappa(sig, rho, kappa); + FloatMatrixF < 6, 6 > + ConcreteDPM2::computeDDGDDStress(const FloatArrayF < 6 > & stress, + const double tempKappa) const + { + FloatMatrixF < 6, 6 > answer; - FloatArray dDKappaDDeltaLambdaDInv; - computeDDKappaDDeltaLambdaDInv(dDKappaDDeltaLambdaDInv, sig, rho, kappa); + auto tmp = computeDeviatoricVolumetricSplit(stress); + auto deviatoricStress = tmp.first; + double sig = tmp.second; + double rho = computeSecondCoordinate(deviatoricStress); + //compute deriviates with respect to invariants + auto dDGDDInv = computeDDGDDInv(sig, rho, tempKappa); + auto dGDInv = computeDGDInv(sig, rho, tempKappa); - answer.resize(4, 4); - /* Compute matrix*/ - answer.at(1, 1) = 1. + this->kM *deltaLambda *dDGDDInv.at(1, 1); - answer.at(1, 2) = this->kM * deltaLambda * dDGDDInv.at(1, 2); - answer.at(1, 3) = this->kM * deltaLambda * dDGDInvDKappa.at(1); - answer.at(1, 4) = this->kM * dGDInv.at(1); - /**/ - answer.at(2, 1) = 2. *this->gM *deltaLambda *dDGDDInv.at(2, 1); - answer.at(2, 2) = 1. + 2. *this->gM *deltaLambda *dDGDDInv.at(2, 2); - answer.at(2, 3) = 2. *this->gM *deltaLambda *dDGDInvDKappa.at(2); - answer.at(2, 4) = 2. *this->gM *dGDInv.at(2); - /**/ - answer.at(3, 1) = deltaLambda * dDKappaDDeltaLambdaDInv.at(1); - answer.at(3, 2) = deltaLambda * dDKappaDDeltaLambdaDInv.at(2); - answer.at(3, 3) = deltaLambda * dDKappaDDeltaLambdaDKappa - 1.; - answer.at(3, 4) = dKappaDDeltaLambda; - /**/ - answer.at(4, 1) = dFDInv.at(1); - answer.at(4, 2) = dFDInv.at(2); - answer.at(4, 3) = dFDKappa; - answer.at(4, 4) = 0.; -} + //Compute derivatives of invariants with respect to stress + auto dRhoDStress = computeDRhoDStress(stress); + auto dDRhoDDStress = computeDDRhoDDStress(stress); + auto dSigDStress = computeDSigDStress(); + //Assemble terms -double -ConcreteDPM2 :: computeYieldValue(double sig, - double rho, - double theta, - double tempKappa) const -{ - //compute yieldHard - double yieldHardOne = computeHardeningOne(tempKappa); - double yieldHardTwo = computeHardeningTwo(tempKappa); + //Compute (dDGDDSig*dSigDStress + dDGDSigDRho*dRhoDStress)*dSigDStress + FloatArrayF < 6 > temp1; + temp1 = dSigDStress; + temp1 *= dDGDDInv.at(1, 1); + FloatArrayF < 6 > temp2; + temp2 = dRhoDStress; + temp2 *= dDGDDInv.at(1, 2); - // compute elliptic function r - double rFunction = ( 4. * ( 1. - pow(ecc, 2.) ) * pow(cos(theta), 2.) + - pow( ( 2. * ecc - 1. ), 2. ) ) / - ( 2. * ( 1. - pow(ecc, 2.) ) * cos(theta) + - ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - pow(ecc, 2.) ) * pow(cos(theta), 2.) - + 5. * pow(ecc, 2.) - 4. * ecc) ); + temp1 += temp2; - //compute help function Al - double Al = ( 1. - yieldHardOne ) * pow( ( sig / fc + rho / ( sqrt(6.) * fc ) ), 2. ) + - sqrt(3. / 2.) * rho / fc; + FloatMatrixF < 6, 6 > helpA; + helpA = dyad(temp1, dSigDStress); - //Compute yield equation - return pow(Al, 2.) + - pow(yieldHardOne, 2.) * yieldHardTwo * m * ( sig / fc + rho * rFunction / ( sqrt(6.) * fc ) ) - - pow(yieldHardOne, 2.) * pow(yieldHardTwo, 2.); -} + //Compute (dDGDDRho*dRhoDStress + dDGDRhoDSig*dSigDStress)*dRhoDstress + temp1 = dRhoDStress; + temp1 *= dDGDDInv.at(2, 2); + temp2 = dSigDStress; + temp2 *= dDGDDInv.at(2, 1); -double -ConcreteDPM2 :: computeDFDKappa(double sig, - double rho, - double tempKappa, - bool mode1d) -{ - double dFDKappa; - double theta = thetaTrial; - //compute yieldHard and yieldSoft - double yieldHardOne = computeHardeningOne(tempKappa); - double yieldHardTwo = computeHardeningTwo(tempKappa); - // compute the derivative of the hardening and softening laws - double dYieldHardOneDKappa = computeHardeningOnePrime(tempKappa); - double dYieldHardTwoDKappa = computeHardeningTwoPrime(tempKappa); - //compute elliptic function r - double rFunction = - ( 4. * ( 1. - pow(ecc, 2) ) * pow(cos(theta), 2) + pow( ( 2. * ecc - 1. ), 2 ) ) / - ( 2 * ( 1. - pow(ecc, 2) ) * cos(theta) + ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - pow(ecc, 2) ) * pow(cos(theta), 2) + 5. * pow(ecc, 2) - 4. * ecc) ); - - - if ( !mode1d ) { - //compute help functions Al, Bl - double Al = ( 1. - yieldHardOne ) * pow( ( sig / fc + rho / ( sqrt(6.) * fc ) ), 2. ) + sqrt(3. / 2.) * rho / fc; + temp1 += temp2; - double Bl = sig / fc + rho / ( fc * sqrt(6.) ); + FloatMatrixF < 6, 6 > helpB; + helpB = dyad(temp1, dRhoDStress); - double dFDYieldHardOne = -2. *Al *pow(Bl, 2.) - + 2. * yieldHardOne * yieldHardTwo * m * ( sig / fc + rho * rFunction / ( sqrt(6.) * fc ) ) - 2. *yieldHardOne *pow(yieldHardTwo, 2.); + //compute dGDRho * dDRhoDDStress + FloatMatrixF < 6, 6 > helpC = dDRhoDDStress; + helpC *= dGDInv.at(2); - double dFDYieldHardTwo = pow(yieldHardOne, 2.) * m * ( sig / fc + rho * rFunction / ( sqrt(6.) * fc ) ) - 2. *yieldHardTwo *pow(yieldHardOne, 2.); + //The term dGDSig*dDSigDDStress is zero - // compute dFDKappa - dFDKappa = dFDYieldHardOne * dYieldHardOneDKappa + - dFDYieldHardTwo * dYieldHardTwoDKappa; - } else { //1d case - dFDKappa = -2 * pow(2 * sig / 3 / fc, 2) * ( sig / fc + pow(2 / 3 * sig / fc, 2) * ( 1 - yieldHardOne ) ) * dYieldHardOneDKappa + - ( 1 + rFunction ) * m * sig / 3 / fc * ( dYieldHardOneDKappa * 2. * yieldHardOne * yieldHardTwo + dYieldHardTwoDKappa * yieldHardOne ) - - 2 * ( yieldHardOne * pow(yieldHardTwo, 2) * dYieldHardOneDKappa + yieldHardTwo * pow(yieldHardOne, 2) * dYieldHardTwoDKappa ); - } + //sum up all parts + answer = helpA; + answer += helpB; + answer += helpC; - /* - * set dFDKappa to zero, if it becomes greater than zero. - * dFDKappa can only be negative or zero in the converged state for - * the case of hardenig and perfect plasticity. For trial stresses, however, - * it might be psoitive, which may lead to convergency problems. Therefore, - * it is set to zero in this cases. - */ - if ( dFDKappa > 0. ) { - dFDKappa = 0.; + return answer; } - return dFDKappa; -} - -double -ConcreteDPM2 :: computeDFDInv1d(double sigma, - double tempKappa) const -{ - double theta = thetaTrial; - //compute yieldHard - double yieldHardOne = computeHardeningOne(tempKappa); - double yieldHardTwo = computeHardeningTwo(tempKappa); - //compute elliptic function r - double rFunction = ( 4. * ( 1. - pow(ecc, 2) ) * pow(cos(theta), 2) + pow( ( 2. * ecc - 1. ), 2 ) ) / - ( 2. * ( 1. - pow(ecc, 2) ) * cos(theta) + ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - pow(ecc, 2) ) * pow(cos(theta), 2) + 5. * pow(ecc, 2) - 4. * ecc) ); - return 2 * ( 1 / fc + 8 * sigma / pow(3 * fc, 2) * ( 1 - yieldHardOne ) ) * ( sigma / fc + pow(2 * sigma / 3 / fc, 2) * ( 1 - yieldHardOne ) ) + ( 1 + rFunction ) * m / ( 3 * fc ) * pow(yieldHardOne, 2) * yieldHardTwo; -} - - -void -ConcreteDPM2 :: computeDFDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa) const -{ - double theta = thetaTrial; - - //compute yieldHard - double yieldHardOne = computeHardeningOne(tempKappa); - double yieldHardTwo = computeHardeningTwo(tempKappa); - - //compute elliptic function r - double rFunction = ( 4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) + ( 2. * ecc - 1. ) * ( 2. * ecc - 1. ) ) / - ( 2. * ( 1. - ecc * ecc ) * cos(theta) + ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) - + 5. * ecc * ecc - 4. * ecc) ); - - //compute help functions AL, BL - double AL = ( 1. - yieldHardOne ) * pow( ( sig / fc + rho / ( sqrt(6.) * fc ) ), 2. ) + sqrt(3. / 2.) * rho / fc; - double BL = sig / fc + rho / ( fc * sqrt(6.) ); - - //compute dfdsig - double dfdsig = 4. * ( 1. - yieldHardOne ) / fc * AL * BL + yieldHardTwo *pow(yieldHardOne, 2.) * m / fc; - - //compute dfdrho - double dfdrho = AL / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * BL + 6. ) + rFunction *m *yieldHardTwo *pow(yieldHardOne, 2.) / ( sqrt(6.) * fc ); - - answer.resize(2); - answer(0) = dfdsig; - answer(1) = dfdrho; -} - - -double -ConcreteDPM2 :: computeDKappaDDeltaLambda1d(double sig, double tempKappa) -{ - double equivalentDGDStress = fabs(computeDGDInv1d(sig, tempKappa)); // In 1D is the absolute value - double ductilityMeasure = computeDuctilityMeasure(sig / 3., sqrt(2. / 3.) * sig, this->thetaTrial); - return equivalentDGDStress / ductilityMeasure; // dKappaDDeltaLambda -} - - -double -ConcreteDPM2 :: computeDKappaDDeltaLambda(double sig, - double rho, - double tempKappa) -{ - double equivalentDGDStress; - double ductilityMeasure; + FloatArrayF < 2 > + ConcreteDPM2::computeDDGDInvDKappa(double sig, + double rho, + double tempKappa) const + { + //Compute dilation parameter - FloatArray dGDInv; - computeDGDInv(dGDInv, sig, rho, tempKappa); + //compute yieldHard and yieldSoft + double yieldHardOne = computeHardeningOne(tempKappa); + double yieldHardTwo = computeHardeningTwo(tempKappa); - equivalentDGDStress = sqrt( 1. / 3. * pow(dGDInv(0), 2.) + pow(dGDInv(1), 2.) ); + double dYieldHardOneDKappa = computeHardeningOnePrime(tempKappa); + double dYieldHardTwoDKappa = computeHardeningTwoPrime(tempKappa); - ductilityMeasure = computeDuctilityMeasure(sig, rho, this->thetaTrial); + //Compute dilation parameter + double AGParam = this->ft * yieldHardTwo * 3 / this->fc + m / 2; + double BGParam = + yieldHardTwo / 3. * ( 1. + this->ft / this->fc ) / + ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); - return equivalentDGDStress / ductilityMeasure; // dKappaDDeltaLambda -} + double R = ( sig - ft / 3. * yieldHardTwo ) / ( fc * BGParam ); + double mQ = AGParam * exp(R); -double -ConcreteDPM2 :: computeDDKappaDDeltaLambdaDInv1d(double sigma, double tempKappa) -{ - double dGDInv; - double dDGDDInv; + //Compute the derivative of mQ with respect to kappa - //Compute first and second derivative of plastic potential - dGDInv = computeDGDInv1d(sigma, tempKappa); - dDGDDInv = computeDDGDDInv1d(sigma, tempKappa); + //Derivative of AGParam + double dAGParamDKappa = dYieldHardTwoDKappa * 3. * this->ft / this->fc; + //Derivative of BGParam + double BGParamTop = yieldHardTwo / 3. * ( 1. + this->ft / this->fc ); + double BGParamBottom = ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); - //computeDuctilityMeasure - double ductilityMeasure = computeDuctilityMeasure(sigma / 3., sigma * sqrt(2. / 3.), this->thetaTrial); - - // compute the derivative of - double dDuctilityMeasureDInv = computeDDuctilityMeasureDInv1d(sigma, tempKappa); - if ( dGDInv < 0 ) { - dDGDDInv = -dDGDDInv; - dGDInv = -dGDInv; - } + double dBGParamTopDKappa = dYieldHardTwoDKappa / 3. * ( 1. + this->ft / this->fc ); + double dBGParamBottomDKappa = 1. / AGParam * dAGParamDKappa - 3. * dYieldHardTwoDKappa / ( 3 * yieldHardTwo + m / 2. ); + double dBGParamDKappa = ( dBGParamTopDKappa * BGParamBottom - BGParamTop * dBGParamBottomDKappa ) / pow(BGParamBottom, 2.); - return dDGDDInv / ductilityMeasure - dGDInv * dDuctilityMeasureDInv / pow(ductilityMeasure, 2); -} + //Derivative of R + double RTop = ( sig - ft / 3. * yieldHardTwo ); + double RBottom = fc * BGParam; + double dRTopDKappa = -this->ft / 3. * dYieldHardTwoDKappa; + double dRBottomDKappa = this->fc * dBGParamDKappa; + double dRDKappa = ( dRTopDKappa * RBottom - RTop * dRBottomDKappa ) / pow(RBottom, 2.); + double dMQDKappa = dAGParamDKappa * exp(R) + AGParam * dRDKappa * exp(R); + double Bl = sig / fc + rho / ( fc * sqrt(6.) ); -void -ConcreteDPM2 :: computeDDKappaDDeltaLambdaDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa) -{ - double equivalentDGDStress; - FloatArray dGDInv; - FloatMatrix dDGDDInv; - FloatArray dEquivalentDGDStressDInv(2); + double Al = ( 1. - yieldHardOne ) * pow(Bl, 2.) + sqrt(3. / 2.) * rho / fc; - //Compute first and second derivative of plastic potential - computeDGDInv(dGDInv, sig, rho, tempKappa); - computeDDGDDInv(dDGDDInv, sig, rho, tempKappa); + double dAlDYieldHard = -pow(Bl, 2.); - //Compute equivalentDGDStress - equivalentDGDStress = sqrt( 1. / 3. * pow(dGDInv(0), 2.) + pow(dGDInv(1), 2.) ); + const double dDGDSigDKappa = + ( -4. * Al * Bl / fc + 4. * ( 1 - yieldHardOne ) / fc * dAlDYieldHard * Bl ) * dYieldHardOneDKappa + + dYieldHardOneDKappa * 2 * yieldHardOne * mQ / fc + pow(yieldHardOne, 2.) * dMQDKappa / fc; - //computeDuctilityMeasure - double ductilityMeasure = computeDuctilityMeasure(sig, rho, this->thetaTrial); + //dDGDSigDKappa = 0.; - //Compute dEquivalentDGDStressDInv - dEquivalentDGDStressDInv(0) = - ( 2. / 3. * dGDInv(0) * dDGDDInv(0, 0) + 2. * dGDInv(1) * dDGDDInv(1, 0) ) / ( 2. * equivalentDGDStress ); - dEquivalentDGDStressDInv(1) = - ( 2. / 3. * dGDInv(0) * dDGDDInv(0, 1) + 2. * dGDInv(1) * dDGDDInv(1, 1) ) / ( 2. * equivalentDGDStress ); + const double dDGDRhoDKappa = + ( dAlDYieldHard / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) - + 4. * Al / ( sqrt(6.) * fc ) * Bl + m / ( sqrt(6.) * fc ) * 2 * yieldHardOne ) * dYieldHardOneDKappa; + return { + dDGDSigDKappa, dDGDRhoDKappa + }; + } - // compute the derivative of - FloatArray dDuctilityMeasureDInv(2); - computeDDuctilityMeasureDInv(dDuctilityMeasureDInv, sig, rho, tempKappa); + FloatMatrixF < 2, 2 > + ConcreteDPM2::computeDDGDDInv(double sig, + double rho, + double tempKappa) const + { + //compute yieldHardOne and yieldSoft + double yieldHardOne = computeHardeningOne(tempKappa); + double yieldHardTwo = computeHardeningTwo(tempKappa); - answer.resize(2); - answer(0) = ( dEquivalentDGDStressDInv(0) * ductilityMeasure - equivalentDGDStress * dDuctilityMeasureDInv(0) ) / pow(ductilityMeasure, 2.); + //CoQpute dilation parameter + double AGParam = this->ft * yieldHardTwo * 3 / this->fc + m / 2; + double BGParam = + yieldHardTwo / 3. * ( 1. + this->ft / this->fc ) / + ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); - answer(1) = ( dEquivalentDGDStressDInv(1) * ductilityMeasure - equivalentDGDStress * dDuctilityMeasureDInv(1) ) / pow(ductilityMeasure, 2.); -} + double R = ( sig - ft / 3. * yieldHardTwo ) / fc / BGParam; + double dMQDSig = AGParam / ( BGParam * fc ) * exp(R); -double -ConcreteDPM2 :: computeDDKappaDDeltaLambdaDKappa(double sig, double rho, double tempKappa) -{ - double equivalentDGDStress, dEquivalentDGDStressDKappa, ductilityMeasure; + //compute help parameter Al and Bl and the corresponding derivatives + double Bl = sig / fc + rho / ( fc * sqrt(6.) ); - FloatArray dGDInv, dDGDInvDKappa; + double Al = ( 1. - yieldHardOne ) * pow(Bl, 2.) + + sqrt(3. / 2.) * rho / fc; - //Compute first and second derivative of plastic potential - computeDGDInv(dGDInv, sig, rho, tempKappa); - computeDDGDInvDKappa(dDGDInvDKappa, sig, rho, tempKappa); + double dAlDSig = 2. * ( 1. - yieldHardOne ) * Bl / fc; + double dBlDSig = 1. / fc; - equivalentDGDStress = sqrt( 1. / 3. * pow(dGDInv(0), 2.) + - pow(dGDInv(1), 2.) ); + double dAlDRho = 2. * ( 1. - yieldHardOne ) * Bl / ( fc * sqrt(6.) ) + sqrt(3. / 2.) / fc; + double dBlDRho = 1. / ( fc * sqrt(6.) ); - ductilityMeasure = computeDuctilityMeasure(sig, rho, this->thetaTrial); //computeDuctilityMeasure - //Compute dEquivalentDGDStressDKappa - dEquivalentDGDStressDKappa = - ( 2. / 3. * dGDInv(0) * dDGDInvDKappa(0) + 2. * dGDInv(1) * dDGDInvDKappa(1) ) / ( 2. * equivalentDGDStress ); + //compute second derivatives of g + double ddgddSig = 4. * ( 1. - yieldHardOne ) / fc * ( dAlDSig * Bl + Al * dBlDSig ) + + pow(yieldHardOne, 2.) * dMQDSig / fc; + // ddgddSig = 0.; -#if 0 - // compute the derivative of - double dDuctilityMeasureDKappa = 0.; + double ddgddRho = dAlDRho / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) + + Al * dBlDRho * 4. * ( 1. - yieldHardOne ) / ( sqrt(6.) * fc ); - ///@todo Is this right? This is *NEVER* used. - double dDKappaDDeltaLambdaDKappa = - ( dEquivalentDGDStressDKappa * ductilityMeasure - - equivalentDGDStress * dDuctilityMeasureDKappa ) / pow(ductilityMeasure, 2.); -#endif - return dEquivalentDGDStressDKappa / ductilityMeasure; // dDKappaDDeltaLambdaDKappa -} - - -double -ConcreteDPM2 :: computeDDKappaDDeltaLambdaDKappa1d(double sig, - double tempKappa) -{ - double equivalentDGDStress, dEquivalentDGDStressDKappa, ductilityMeasure; - - equivalentDGDStress = computeDGDInv1d(sig, tempKappa); - dEquivalentDGDStressDKappa = computeDDGDInvDKappa1d(sig, tempKappa); - if ( equivalentDGDStress < 0 ) { - dEquivalentDGDStressDKappa = ( -1 ) * dEquivalentDGDStressDKappa; //We are differentiating the absolute value of the first derivative of G with respect to stress - } - - ductilityMeasure = computeDuctilityMeasure(sig / 3., sig * sqrt(2. / 3.), this->thetaTrial); - - return dEquivalentDGDStressDKappa / ductilityMeasure; // dDKappaDDeltaLambdaDKappa -} - - -double -ConcreteDPM2 :: computeDDuctilityMeasureDInv1d(double sigma, - double tempKappa) -{ - double thetaConst = pow(2. * cos(thetaTrial), 2.); - double x = -( sigma + fc ) / ( 3 * fc ); //R hardening variable - double dXDSigma = -1. / ( 3. * fc ); - if ( x < 0. ) { - /* Introduce exponential help function which results in a - * smooth transition. */ - double EHard = BHard - DHard; - double FHard = ( BHard - DHard ) * CHard / ( AHard - BHard ); - - double dDuctilityMeasureDX = EHard / FHard *exp(x / FHard) / thetaConst; - return dDuctilityMeasureDX * dXDSigma; - } else { - double dDuctilityMeasureDX = ( AHard - BHard ) / CHard / thetaConst *exp(-x / CHard); - return dDuctilityMeasureDX * dXDSigma; - } -} - -void -ConcreteDPM2 :: computeDDuctilityMeasureDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa) -{ - double thetaConst = pow(2. * cos(thetaTrial), 2.); - double x = ( -( sig + fc / 3. ) ) / fc; - - if ( x < 0. ) { - double dXDSig = -1. / fc; - /* Introduce exponential help function which results in a - * smooth transition. */ - double EHard = BHard - DHard; - double FHard = ( BHard - DHard ) * CHard / ( AHard - BHard ); - - double dDuctilityMeasureDX = EHard / FHard *exp(x / FHard) / thetaConst; - answer = {dDuctilityMeasureDX * dXDSig, 0.}; - } else { - double dXDSig = -1. / fc; - double dDuctilityMeasureDX = -( BHard - AHard ) / ( CHard ) / thetaConst *exp( -x / ( CHard ) ); - answer = {dDuctilityMeasureDX * dXDSig, 0.}; - } -} - - -double -ConcreteDPM2 :: computeDGDInv1d(double sigma, - double tempKappa) -{ - //compute yieldHard and yieldSoft - double yieldHardOne = computeHardeningOne(tempKappa); - double yieldHardTwo = computeHardeningTwo(tempKappa); - double AGParam = this->ft * yieldHardTwo * 3 / this->fc + m / 2; - double BGParam = yieldHardTwo / 3. * ( 1. + this->ft / this->fc ) / ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); - double R = ( sigma - yieldHardTwo * ft ) / ( 3 * fc * BGParam ); - double mQ = AGParam * exp(R) / 3; - return 2 * ( 1 / fc + 8 * sigma / pow(3 * fc, 2) * ( 1 - yieldHardOne ) ) * ( sigma / fc + pow(2 * sigma / ( 3 * fc ), 2) * ( 1 - yieldHardOne ) ) + pow(yieldHardOne, 2) / fc * ( m / 3 + mQ ); -} - - -void -ConcreteDPM2 :: computeDGDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa) -{ - //compute yieldHard and yieldSoft - double yieldHardOne = computeHardeningOne(tempKappa); - double yieldHardTwo = computeHardeningTwo(tempKappa); - - //Compute dilation parameter - double AGParam = this->ft * yieldHardTwo * 3 / this->fc + m / 2; - double BGParam = - yieldHardTwo / 3. * ( 1. + this->ft / this->fc ) / - ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); - - double R = ( sig - ft / 3. * yieldHardTwo ) / fc / BGParam; - double mQ = AGParam * exp(R); - - double Bl = sig / fc + rho / ( fc * sqrt(6.) ); - - double Al = ( 1. - yieldHardOne ) * pow(Bl, 2.) + sqrt(3. / 2.) * rho / fc; - - double dgdsig = 4. * ( 1. - yieldHardOne ) / fc * Al * Bl + pow(yieldHardOne, 2.) * mQ / fc; - - double dgdrho = Al / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) + - m *pow(yieldHardOne, 2.) / ( sqrt(6.) * fc ); - - answer = {dgdsig, dgdrho}; -} - -double -ConcreteDPM2 :: computeDDGDInvDKappa1d(double sigma, - double tempKappa) -{ - //compute yieldHard and yieldSoft - double yieldHardOne = computeHardeningOne(tempKappa); - double yieldHardTwo = computeHardeningTwo(tempKappa); - - double dYieldHardOneDKappa = computeHardeningOnePrime(tempKappa); - double dYieldHardTwoDKappa = computeHardeningTwoPrime(tempKappa); - - //Compute dilation parameter - double AGParam = this->ft * yieldHardTwo * 3 / this->fc + m / 2; - double BGParam = - yieldHardTwo / 3. * ( 1. + this->ft / this->fc ) / - ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); - - double R = ( sigma - ft * yieldHardTwo ) / ( 3 * fc * BGParam ); - double mQ = AGParam * exp(R) / 3; - //Compute the derivative of mQ with respect to kappa - - //Derivative of AGParam - double dAGParamDKappa = dYieldHardTwoDKappa * 3. * this->ft / this->fc; - - //Derivative of BGParam - double BGParamTop = yieldHardTwo / 3. * ( 1. + this->ft / this->fc ); - double BGParamBottom = ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); - double dBGParamTopDKappa1 = dYieldHardTwoDKappa * ( 1 + ft / fc ) / 3; - double dBGParamBottomDKappa1 = BGParamBottom; - double dBGParamTopDKappa2 = BGParamTop * ( dAGParamDKappa / AGParam - 3 * dYieldHardTwoDKappa / ( m / 2 + 3 * yieldHardTwo ) ); - double dBGParamBottomDKappa2 = pow(BGParamBottom, 2); - - double dBGParamDKappa = dBGParamTopDKappa1 / dBGParamBottomDKappa1 - dBGParamTopDKappa2 / dBGParamBottomDKappa2; - double dMQDKappa = 1 / 3 * exp(R) * ( dAGParamDKappa - AGParam * ( ( sigma - ft * yieldHardTwo ) * dBGParamDKappa / ( 3 * fc * pow(BGParam, 2) ) + ft * dYieldHardTwoDKappa / 3 / fc / BGParam ) ); - - return -8 / 9 * pow(sigma / fc, 2) * ( 1 / fc + 8 * sigma / pow(3 * fc, 2) * ( 1 - yieldHardOne ) ) * dYieldHardOneDKappa - sigma *pow(4 / 3 / fc, 2) * ( sigma / fc + pow(2 / 3 * sigma / fc, 2) * ( 1 - yieldHardOne ) ) * dYieldHardOneDKappa + 2 * dYieldHardOneDKappa * yieldHardOne / fc * ( this->m / 3 + mQ ) + yieldHardOne / fc * dMQDKappa; -} - - -void -ConcreteDPM2 :: computeDDGDInvDKappa(FloatArray &answer, - double sig, - double rho, - double tempKappa) -{ - //Compute dilation parameter - - //compute yieldHard and yieldSoft - double yieldHardOne = computeHardeningOne(tempKappa); - double yieldHardTwo = computeHardeningTwo(tempKappa); - - double dYieldHardOneDKappa = computeHardeningOnePrime(tempKappa); - double dYieldHardTwoDKappa = computeHardeningTwoPrime(tempKappa); - - //Compute dilation parameter - double AGParam = this->ft * yieldHardTwo * 3 / this->fc + m / 2; - double BGParam = - yieldHardTwo / 3. * ( 1. + this->ft / this->fc ) / - ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); - - double R = ( sig - ft / 3. * yieldHardTwo ) / ( fc * BGParam ); - double mQ = AGParam * exp(R); - - //Compute the derivative of mQ with respect to kappa - - //Derivative of AGParam - double dAGParamDKappa = dYieldHardTwoDKappa * 3. * this->ft / this->fc; - - //Derivative of BGParam - double BGParamTop = yieldHardTwo / 3. * ( 1. + this->ft / this->fc ); - double BGParamBottom = ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); - - double dBGParamTopDKappa = dYieldHardTwoDKappa / 3. * ( 1. + this->ft / this->fc ); - double dBGParamBottomDKappa = 1./AGParam*dAGParamDKappa - 3. * dYieldHardTwoDKappa / ( 3 * yieldHardTwo + m / 2. ); - double dBGParamDKappa = ( dBGParamTopDKappa * BGParamBottom - BGParamTop * dBGParamBottomDKappa ) / pow(BGParamBottom, 2.); - - //Derivative of R - double RTop = ( sig - ft / 3. * yieldHardTwo ); - double RBottom = fc * BGParam; - double dRTopDKappa = -this->ft / 3. * dYieldHardTwoDKappa; - double dRBottomDKappa = this->fc * dBGParamDKappa; - double dRDKappa = ( dRTopDKappa * RBottom - RTop * dRBottomDKappa ) / pow(RBottom, 2.); - - double dMQDKappa = dAGParamDKappa * exp(R) + AGParam *dRDKappa *exp(R); - - double Bl = sig / fc + rho / ( fc * sqrt(6.) ); - - double Al = ( 1. - yieldHardOne ) * pow(Bl, 2.) + sqrt(3. / 2.) * rho / fc; - - double dAlDYieldHard = -pow(Bl, 2.); - - const double dDGDSigDKappa = - ( -4. * Al * Bl / fc + 4. * ( 1 - yieldHardOne ) / fc * dAlDYieldHard * Bl ) * dYieldHardOneDKappa + - dYieldHardOneDKappa * 2 * yieldHardOne * mQ / fc + pow(yieldHardOne,2.) * dMQDKappa / fc; - - const double dDGDRhoDKappa = - ( dAlDYieldHard / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) - - 4. * Al / ( sqrt(6.) * fc ) * Bl + m / ( sqrt(6.) * fc ) * 2 * yieldHardOne) * dYieldHardOneDKappa; - - answer = {dDGDSigDKappa, dDGDRhoDKappa}; -} - -double -ConcreteDPM2 :: computeDDGDDInv1d(double sigma, - double tempKappa) -{ - //compute yieldHardOne and yieldSoft - double yieldHardOne = computeHardeningOne(tempKappa); - double yieldHardTwo = computeHardeningTwo(tempKappa); - double AGParam = this->ft * yieldHardTwo * 3 / this->fc + m / 2; - double BGParam = - yieldHardTwo / 3. * ( 1. + this->ft / this->fc ) / - ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); - double R = ( sigma - ft * yieldHardTwo ) / ( 3 * fc * BGParam ); - double dMQDSigma = AGParam / ( 9 * BGParam * fc ) * exp(R); - return 2 * pow(1 / fc + 8 * sigma / pow(3 * fc, 2) * ( 1 - yieldHardOne ), 2) + pow(4 / 3 / fc, 2) * ( sigma / fc + pow(2 / 3 * sigma / fc, 2) * ( 1 - yieldHardOne ) ) * ( 1 - yieldHardOne ) + pow(yieldHardOne, 2) / fc * dMQDSigma; -} - -void -ConcreteDPM2 :: computeDDGDDInv(FloatMatrix &answer, - double sig, - double rho, - double tempKappa) -{ - //compute yieldHardOne and yieldSoft - double yieldHardOne = computeHardeningOne(tempKappa); - double yieldHardTwo = computeHardeningTwo(tempKappa); + double ddgdSigdRho = 4. * ( 1. - yieldHardOne ) / fc * ( dAlDRho * Bl + Al * dBlDRho ); + // ddgdSigdRho = 0.; - //CoQpute dilation parameter - double AGParam = this->ft * yieldHardTwo * 3 / this->fc + m / 2; - double BGParam = - yieldHardTwo / 3. * ( 1. + this->ft / this->fc ) / - ( log(AGParam) + log(this->dilationConst + 1.) - log(2 * this->dilationConst - 1.) - log(3. * yieldHardTwo + this->m / 2) ); + double ddgdRhodSig = dAlDSig / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) + + Al / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * dBlDSig ); + // ddgdRhodSig = 0.; - double R = ( sig - ft / 3. * yieldHardTwo ) / fc / BGParam; + FloatMatrixF < 2, 2 > answer; + answer.at(1, 1) = ddgddSig; + answer.at(1, 2) = ddgdSigdRho; + answer.at(2, 1) = ddgdRhodSig; + answer.at(2, 2) = ddgddRho; + return answer; + } - double dMQDSig = AGParam / ( BGParam * fc ) * exp(R); - //compute help parameter Al and Bl and the corresponding derivatives - double Bl = sig / fc + rho / ( fc * sqrt(6.) ); - double Al = ( 1. - yieldHardOne ) * pow(Bl, 2.) + - sqrt(3. / 2.) * rho / fc; + double + ConcreteDPM2::computeAlpha(FloatArrayF < 6 > &effectiveStressTension, + FloatArrayF < 6 > &effectiveStressCompression, + const FloatArrayF < 6 > &effectiveStress) const + { + auto tmp = StructuralMaterial::computePrincipalValDir(from_voigt_stress(effectiveStress) ); + auto principalStress = tmp.first; + auto stressPrincipalDir = tmp.second; - double dAlDSig = 2. * ( 1. - yieldHardOne ) * Bl / fc; - double dBlDSig = 1. / fc; + //Split the principal values in a tension and a compression part + FloatArrayF < 6 > principalStressTension; + FloatArrayF < 6 > principalStressCompression; - double dAlDRho = 2. * ( 1. - yieldHardOne ) * Bl / ( fc * sqrt(6.) ) + sqrt(3. / 2.) / fc; - double dBlDRho = 1. / ( fc * sqrt(6.) ); + for ( int i = 1; i <= principalStress.giveSize(); i++ ) { + if ( principalStress.at(i) >= 0 ) { + principalStressTension.at(i) = principalStress.at(i); + principalStressCompression.at(i) = 0.; + } else { + principalStressTension.at(i) = 0.; + principalStressCompression.at(i) = principalStress.at(i); + } + } - //compute second derivatives of g - double ddgddSig = 4. * ( 1. - yieldHardOne ) / fc * ( dAlDSig * Bl + Al * dBlDSig ) + - pow(yieldHardOne, 2.) * dMQDSig / fc; + //Transform the tension and compression principal stresses back to the original coordinate system - double ddgddRho = dAlDRho / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) + - Al * dBlDRho * 4. * ( 1. - yieldHardOne ) / ( sqrt(6.) * fc ); + //Take care of type of stress state for tension + effectiveStressTension = transformStressVectorTo(stressPrincipalDir, principalStressTension, 1); - double ddgdSigdRho = 4. * ( 1. - yieldHardOne ) / fc * ( dAlDRho * Bl + Al * dBlDRho ); + //Take care of type of stress state for compression + effectiveStressCompression = transformStressVectorTo(stressPrincipalDir, principalStressCompression, 1); - double ddgdRhodSig = dAlDSig / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * Bl + 6. ) - + Al / ( sqrt(6.) * fc ) * ( 4. * ( 1. - yieldHardOne ) * dBlDSig ); + //Determine the two factors from the stress - answer.resize(2, 2); - answer(0, 0) = ddgddSig; - answer(0, 1) = ddgdSigdRho; - answer(1, 0) = ddgdRhodSig; - answer(1, 1) = ddgddRho; -} + double squareNormOfPrincipalStress = norm_squared(principalStress); + double alphaTension = 0.; + if ( squareNormOfPrincipalStress > 0 ) { + for ( int i = 1; i <= principalStress.giveSize(); i++ ) { + alphaTension += principalStressTension.at(i) * + ( principalStressTension.at(i) + principalStressCompression.at(i) ) / squareNormOfPrincipalStress; + } + } -double -ConcreteDPM2 :: computeAlpha(FloatArray &effectiveStressTension, - FloatArray &effectiveStressCompression, - FloatArray &effectiveStress) -{ - FloatMatrix stressPrincipalDir; - FloatArray principalStress; - StructuralMaterial :: computePrincipalValDir(principalStress, stressPrincipalDir, effectiveStress, principal_stress); + return 1. - alphaTension; + } - //Split the principal values in a tension and a compression part - FloatArray principalStressTension(6); - FloatArray principalStressCompression(6); - for ( int i = 1; i <= principalStress.giveSize(); i++ ) { - if ( principalStress.at(i) >= 0 ) { - principalStressTension.at(i) = principalStress.at(i); - principalStressCompression.at(i) = 0.; + double + ConcreteDPM2::computeHardeningOne(double kappa) const + { + if ( kappa <= 0. ) { + return yieldHardInitial; + } else if ( kappa > 0. && kappa < 1. ) { + return + ( 1. - yieldHardInitial - yieldHardPrimePeak ) * pow(kappa, 3.) + - ( 3. * ( 1. - yieldHardInitial ) - 3. * yieldHardPrimePeak ) * pow(kappa, 2.) + + ( 3. * ( 1. - yieldHardInitial ) - 2. * yieldHardPrimePeak ) * kappa + + yieldHardInitial; } else { - principalStressTension.at(i) = 0.; - principalStressCompression.at(i) = principalStress.at(i); + return 1.; } } - //Transform the tension and compression principal stresses back to the original coordinate system - - //Take care of type of stress state for tension - transformStressVectorTo(effectiveStressTension, stressPrincipalDir, principalStressTension, 1); - //Take care of type of stress state for compression - transformStressVectorTo(effectiveStressCompression, stressPrincipalDir, principalStressCompression, 1); + double + ConcreteDPM2::computeHardeningOnePrime(double kappa) const + { + if ( kappa <= 0. ) { + return 3. * ( 1 - yieldHardInitial ) - 2. * yieldHardPrimePeak; + } else if ( kappa >= 0. && kappa < 1. ) { + return + 3. * ( 1. - yieldHardInitial - yieldHardPrimePeak ) * pow(kappa, 2.) + - 2. * ( 3. * ( 1. - yieldHardInitial ) - 3. * yieldHardPrimePeak ) * kappa + + ( 3. * ( 1. - yieldHardInitial ) - 2. * yieldHardPrimePeak ); + } else { + return 0.; + } + } - //Determine the two factors from the stress - double squareNormOfPrincipalStress = 0.; - for ( int i = 1; i <= principalStress.giveSize(); i++ ) { - squareNormOfPrincipalStress += pow(principalStress.at(i), 2.); + double + ConcreteDPM2::computeHardeningTwo(double kappa) const + { + if ( kappa <= 0. ) { + return 1.; + } else if ( kappa > 0. && kappa < 1. ) { + return 1.; + } else { + return 1. + ( kappa - 1. ) * yieldHardPrimePeak; + } } - double alphaTension = 0.; - if ( squareNormOfPrincipalStress > 0 ) { - for ( int i = 1; i <= principalStress.giveSize(); i++ ) { - alphaTension += principalStressTension.at(i) * - ( principalStressTension.at(i) + principalStressCompression.at(i) ) / squareNormOfPrincipalStress; - } - } - - return 1. - alphaTension; -} - - -double -ConcreteDPM2 :: computeHardeningOne(double kappa) const -{ - if ( kappa <= 0. ) { - return yieldHardInitial; - } else if ( kappa > 0. && kappa < 1. ) { - return - ( 1. - yieldHardInitial - yieldHardPrimePeak ) * pow(kappa, 3.) - - ( 3. * ( 1. - yieldHardInitial ) - 3. * yieldHardPrimePeak ) * pow(kappa, 2.) - + ( 3. * ( 1. - yieldHardInitial ) - 2. * yieldHardPrimePeak ) * kappa - + yieldHardInitial; - } else { - return 1.; - } -} - - -double -ConcreteDPM2 :: computeHardeningOnePrime(double kappa) const -{ - if ( kappa <= 0. ) { - return 3. * ( 1 - yieldHardInitial ) - 2. * yieldHardPrimePeak; - } else if ( kappa >= 0. && kappa < 1. ) { - return - 3. * ( 1. - yieldHardInitial - yieldHardPrimePeak ) * pow(kappa, 2.) - - 2. * ( 3. * ( 1. - yieldHardInitial ) - 3. * yieldHardPrimePeak ) * kappa - + ( 3. * ( 1. - yieldHardInitial ) - 2. * yieldHardPrimePeak ); - } else { - return 0.; - } -} - - -double -ConcreteDPM2 :: computeHardeningTwo(double kappa) const -{ - if ( kappa <= 0. ) { - return 1.; - } else if ( kappa > 0. && kappa < 1. ) { - return 1.; - } else { - return 1. + ( kappa - 1. ) * yieldHardPrimePeak; - } -} - - -double -ConcreteDPM2 :: computeHardeningTwoPrime(double kappa) const -{ - if ( kappa <= 0. ) { - return 0.; - } else if ( kappa >= 0. && kappa < 1. ) { - return 0.; - } else { - return yieldHardPrimePeak; - } -} - -void -ConcreteDPM2 :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); - if ( mode == ElasticStiffness ) { - answer.resize(1, 1); - answer.at(1, 1) = eM; - } else if ( mode == SecantStiffness ) { - double om; - const FloatArray &strain = status->giveTempStrainVector(); - if ( strain.at(1) >= 0 || isotropicFlag == 1 ) { - om = status->giveTempDamageTension(); + double + ConcreteDPM2::computeHardeningTwoPrime(double kappa) const + { + if ( kappa <= 0. ) { + return 0.; + } else if ( kappa >= 0. && kappa < 1. ) { + return 0.; } else { - om = status->giveTempDamageCompression(); + return yieldHardPrimePeak; } + } - if ( om > 0.999999 ) { - om = 0.999999; + FloatMatrixF < 6, 6 > + ConcreteDPM2::give3dMaterialStiffnessMatrix(MatResponseMode mode, + GaussPoint * gp, + TimeStep * tStep) const + { + auto status = static_cast < ConcreteDPM2Status * > ( giveStatus(gp) ); + if ( mode == SecantStiffness ) { + return this->compute3dSecantStiffness(gp, tStep); } - - answer.resize(1, 1); - answer.at(1, 1) = eM; - answer.times(1.0 - om); - } else { - OOFEM_WARNING("unknown type of stiffness (tangent stiffness not implemented for 1d). Elastic stiffness used!\n"); - answer.resize(1, 1); - answer.at(1, 1) = eM; + //Todo: Tangent stiffness implementation needs to be improved. + // else if ( mode == TangentStiffness ) { + // const int stateFlag = status->giveTempStateFlag(); + // if ( stateFlag == ConcreteDPM2Status::ConcreteDPM2_PlasticDamage || stateFlag == ConcreteDPM2Status::ConcreteDPM2_Plastic ) { + // return this->compute3dTangentStiffness(gp, tStep); + // } else { + // return this->compute3dSecantStiffness(gp, tStep); + // } + // } + //Elastic case + return this->linearElasticMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep); } -} -void -ConcreteDPM2 :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -{ - if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); - } else if ( mode == SecantStiffness ) { - this->compute3dSecantStiffness(answer, gp, tStep); - } else if ( mode == TangentStiffness ) { - OOFEM_WARNING("unknown type of stiffness (tangent stiffness not implemented). Elastic stiffness used!"); - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); - } -} -void -ConcreteDPM2 :: compute3dSecantStiffness(FloatMatrix &answer, - GaussPoint *gp, - TimeStep *tStep) -{ - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( giveStatus(gp) ); + FloatMatrixF < 6, 6 > + ConcreteDPM2::compute3dSecantStiffness(GaussPoint * gp, TimeStep * tStep) const + { + auto status = static_cast < ConcreteDPM2Status * > ( giveStatus(gp) ); - // Damage parameters - double omegaTension = min(status->giveTempDamageTension(), 0.999999); + // Damage parameters + double omegaTension = min(status->giveTempDamageTension(), 0.999999); + double omegaCompression = min(status->giveTempDamageCompression(), 0.999999); - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, ElasticStiffness, gp, tStep); + double alpha = status->giveTempAlpha(); - if ( isotropicFlag == 1 ) { - answer.times(1. - omegaTension); - return; + auto d = this->linearElasticMaterial.give3dMaterialStiffnessMatrix(ElasticStiffness, gp, tStep); + + if ( damageFlag == 2 ) { + d *= ( 1. - omegaTension ); + } else if ( damageFlag == 3 ) { + d *= ( 1. - ( 1. - alpha ) * omegaTension ) * ( 1. - alpha * omegaCompression ); + } + + return d; } + FloatMatrixF < 6, 6 > + ConcreteDPM2::compute3dTangentStiffness(GaussPoint * gp, TimeStep * tStep) const + { + FloatMatrixF < 6, 6 > answer; - FloatArray effectiveStress; - FloatArray elasticStrain = status->giveTempStrainVector(); - elasticStrain.subtract( status->giveTempPlasticStrain() ); - effectiveStress.beProductOf(answer, elasticStrain); + FloatArrayF < 6 > effectiveStress; + auto status = static_cast < ConcreteDPM2Status * > ( giveStatus(gp) ); + effectiveStress = status->giveTempEffectiveStress(); - //Calculate the principal values of the effective stress - FloatArray principalStress; - StructuralMaterial :: computePrincipalValues(principalStress, effectiveStress, principal_stress); + double tempKappa = status->giveTempKappaP(); + double deltaLambda = status->giveDeltaLambda(); - //exclude two special cases. - if ( principalStress.containsOnlyZeroes() ) { - return; - } + //Computes only the plastic part of the tangent stiffness + auto d = this->linearElasticMaterial.give3dMaterialStiffnessMatrix(ElasticStiffness, gp, tStep); - for ( int i = 1; i <= 3; i++ ) { - if ( principalStress.at(i) < -DYNCON_TOL ) { - return; - } - } + // Debug + FloatMatrixF < 8, 8 > fullJacobian = computeFullJacobian(effectiveStress, deltaLambda, gp, tStep, tempKappa); + + FloatMatrixF < 8, 8 > invFullJacobian = inv(fullJacobian); - answer.times(1. - omegaTension); -} + FloatMatrixF < 6, 6 > help; + for ( int i = 1; i <= 6; i++ ) { + for ( int j = 1; j <= 6; j++ ) { + help.at(i, j) = invFullJacobian.at(i, j); + } + } + answer = dot(help, d); + // Damage parameters + double omegaTension = min(status->giveTempDamageTension(), 0.999999); + double omegaCompression = min(status->giveTempDamageCompression(), 0.999999); + double alpha = status->giveTempAlpha(); -void -ConcreteDPM2 :: computeTrialCoordinates(const FloatArray &stress, double &sigNew, double &rhoNew, double &thetaNew) -{ - if ( stress.giveSize() == 1 ) { //1d case - sigNew = stress[0] / 3.; - rhoNew = stress[0] * sqrt(2. / 3.); - if ( sigNew >= 0 ) { - thetaNew = 0.; - } else { - thetaNew = M_PI / 6; + if ( damageFlag == 2 ) { + answer *= ( 1. - ( 1. - alpha ) * omegaTension ) * ( 1. - alpha * omegaCompression ); + } else if ( damageFlag == 3 ) { + answer *= ( 1. - omegaTension ); } - } else { - FloatArray deviatoricStress; - sigNew = computeDeviatoricVolumetricSplit(deviatoricStress, stress); + + return answer; + } + + void + ConcreteDPM2::computeCoordinates(const FloatArrayF < 6 > &stress, double &sigNew, double &rhoNew, double &thetaNew) const + { + auto tmp = computeDeviatoricVolumetricSplit(stress); + auto deviatoricStress = tmp.first; + sigNew = tmp.second; rhoNew = computeSecondCoordinate(deviatoricStress); thetaNew = computeThirdCoordinate(deviatoricStress); } -} + void + ConcreteDPM2::assignStateFlag(GaussPoint *gp) const + { + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); + + //Get kappaD from status to define state later on + double damageTension = status->giveDamageTension(); + double damageCompression = status->giveDamageCompression(); + double tempDamageTension = status->giveTempDamageTension(); + double tempDamageCompression = status->giveTempDamageCompression(); + double kappaP = status->giveKappaP(); + double tempKappaP = status->giveTempKappaP(); + + if ( tempKappaP > kappaP ) { + if ( tempDamageTension > damageTension || tempDamageTension == 1. || + tempDamageCompression > damageCompression || tempDamageCompression == 1. ) { + if ( status->giveTempStateFlag() == ConcreteDPM2Status::ConcreteDPM2_VertexTension ) { + status->letTempStateFlagBe(ConcreteDPM2Status::ConcreteDPM2_VertexTensionDamage); + } else if ( status->giveTempStateFlag() == ConcreteDPM2Status::ConcreteDPM2_VertexTension ) { + status->letTempStateFlagBe(ConcreteDPM2Status::ConcreteDPM2_VertexCompressionDamage); + } else { + status->letTempStateFlagBe(ConcreteDPM2Status::ConcreteDPM2_PlasticDamage); + } + } else { + status->letTempStateFlagBe(ConcreteDPM2Status::ConcreteDPM2_Plastic); + } + } else { + const int state_flag = status->giveStateFlag(); + if ( tempDamageTension > damageTension || tempDamageTension == 1. || + tempDamageCompression > damageCompression || tempDamageCompression == 1. ) { + status->letTempStateFlagBe(ConcreteDPM2Status::ConcreteDPM2_Damage); + } else { + if ( state_flag == ConcreteDPM2Status::ConcreteDPM2_Elastic ) { + status->letTempStateFlagBe(ConcreteDPM2Status::ConcreteDPM2_Elastic); + } else { + status->letTempStateFlagBe(ConcreteDPM2Status::ConcreteDPM2_Unloading); + } + } + } + } -void -ConcreteDPM2 :: assignStateFlag(GaussPoint *gp) -{ - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); - //Get kappaD from status to define state later on - double damageTension = status->giveDamageTension(); - double damageCompression = status->giveDamageCompression(); - double tempDamageTension = status->giveTempDamageTension(); - double tempDamageCompression = status->giveTempDamageCompression(); - double kappaP = status->giveKappaP(); - double tempKappaP = status->giveTempKappaP(); + double + ConcreteDPM2::computeDRDCosTheta(const double theta, const double ecc) const + { + // double thetaCrit = M_PI/3.*0.999; + double ACostheta = 4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) + + ( 2. * ecc - 1. ) * ( 2. * ecc - 1. ); + double BCostheta = 2. * ( 1. - ecc * ecc ) * cos(theta) + + ( 2. * ecc - 1. ) * sqrt(4. * ( 1. - ecc * ecc ) * cos(theta) * cos(theta) + + 5. * ecc * ecc - 4. * ecc); + double A1Costheta = 8. * ( 1. - pow(ecc, 2.) ) * cos(theta); + double B1Costheta = 2. * ( 1. - pow(ecc, 2.) ) + + 4. * ( 2. * ecc - 1. ) * ( 1. - pow(ecc, 2.) ) * cos(theta) / + sqrt(4. * ( 1. - pow(ecc, 2.) ) * pow(cos(theta), 2.) + + 5. * pow(ecc, 2.) - 4. * ecc); + double dRDCostheta = A1Costheta / BCostheta - ACostheta / pow(BCostheta, 2.) * B1Costheta; + return dRDCostheta; + } + + double + ConcreteDPM2::computeDDRDDCosTheta(const double theta, const double ecc) const + { + // double thetaCrit = M_PI/3.*0.999; + // if (thetaCrit + ConcreteDPM2::computeDCosThetaDStress(const FloatArrayF < 6 > & stress) const + { + //compute volumetric deviatoric split + auto deviatoricStress = computeDeviator(stress); + + //compute the coordinates + double rho = computeSecondCoordinate(deviatoricStress); + + //compute principal stresses and directions + //auto [principalDeviatoricStress, principalDir] = computePrincipalValDir(from_voigt_stress(deviatoricStress)); // c++17 + auto tmp = computePrincipalValDir(from_voigt_stress(deviatoricStress) ); + auto principalDeviatoricStress = tmp.first; + auto principalDir = tmp.second; + + //compute the derivative of s1 with respect to the cartesian stress + FloatArrayF < 6 > ds1DStress; + ds1DStress.at(1) = principalDir.at(1, 1) * principalDir.at(1, 1) - 1. / 3.; + ds1DStress.at(2) = principalDir.at(2, 1) * principalDir.at(2, 1) - 1. / 3.; + ds1DStress.at(3) = principalDir.at(3, 1) * principalDir.at(3, 1) - 1. / 3.; + ds1DStress.at(4) = 2. * principalDir.at(2, 1) * principalDir.at(3, 1); + ds1DStress.at(5) = 2. * principalDir.at(3, 1) * principalDir(1, 1); + ds1DStress.at(6) = 2. * principalDir.at(1, 1) * principalDir.at(2, 1); + + //compute dCosThetaDStress + auto dCosThetaDStress = ds1DStress * ( sqrt(3. / 2.) * rho / pow(rho, 2.) ) + + computeDRhoDStress(stress) * ( -sqrt(3. / 2.) * principalDeviatoricStress [ 0 ] / pow(rho, 2.) ); + return dCosThetaDStress; + } + + + FloatMatrixF < 6, 6 > + ConcreteDPM2::computeDDCosThetaDDStress(const FloatArrayF < 6 > & stress) const + { + //compute volumetric deviatoric split + auto deviatoricStress = computeDeviator(stress); + + //compute the coordinate + double rho = computeSecondCoordinate(deviatoricStress); + + //compute principal stresses and directions + //auto [principalDeviatoricStress, principalDir] = computePrincipalValDir(from_voigt_stress(deviatoricStress)); // c++17 + auto tmp = computePrincipalValDir(from_voigt_stress(deviatoricStress) ); + auto principalDeviatoricStress = tmp.first; + auto principalDir = tmp.second; + + + //compute the derivative of s1 with respect to the cartesian stress + FloatArrayF < 6 > dS1DStress; + dS1DStress.at(1) = principalDir.at(1, 1) * principalDir.at(1, 1) - 1. / 3.; + dS1DStress.at(2) = principalDir.at(2, 1) * principalDir.at(2, 1) - 1. / 3.; + dS1DStress.at(3) = principalDir.at(3, 1) * principalDir.at(3, 1) - 1. / 3.; + dS1DStress.at(4) = 2. * principalDir.at(2, 1) * principalDir.at(3, 1); + dS1DStress.at(5) = 2. * principalDir.at(3, 1) * principalDir.at(1, 1); + dS1DStress.at(6) = 2. * principalDir.at(1, 1) * principalDir.at(2, 1); + + //compute the second derivative of costheta + FloatMatrixF < 6, 6 > dDCosThetaDDStress; + //compute the product of dS1DStress and DRhoDStress + auto dRhoDStress = computeDRhoDStress(stress); + FloatMatrixF < 6, 6 > dS1DRho; + for ( int v = 0; v < 6; v++ ) { + for ( int w = 0; w < 6; w++ ) { + dS1DRho.at(v + 1, w + 1) = dS1DStress.at(v + 1) * dRhoDStress.at(w + 1); + } + } - if ( tempKappaP > kappaP ) { - if ( tempDamageTension > damageTension || tempDamageTension == 1. || - tempDamageCompression > damageCompression || tempDamageCompression == 1. ) { - status->letTempStateFlagBe(ConcreteDPM2Status :: ConcreteDPM2_PlasticDamage); - } else { - status->letTempStateFlagBe(ConcreteDPM2Status :: ConcreteDPM2_Plastic); + //compute the square of dRhoDStress and DRhoDStress + FloatMatrixF < 6, 6 > dRhoDRho; + for ( int v = 0; v < 6; v++ ) { + for ( int w = 0; w < 6; w++ ) { + dRhoDRho.at(v + 1, w + 1) = dRhoDStress.at(v + 1) * dRhoDStress.at(w + 1); + } } - } else { - const int state_flag = status->giveStateFlag(); - if ( tempDamageTension > damageTension || tempDamageTension == 1. || - tempDamageCompression > damageCompression || tempDamageCompression == 1. ) { - status->letTempStateFlagBe(ConcreteDPM2Status :: ConcreteDPM2_Damage); - } else { - if ( state_flag == ConcreteDPM2Status :: ConcreteDPM2_Elastic ) { - status->letTempStateFlagBe(ConcreteDPM2Status :: ConcreteDPM2_Elastic); - } else { - status->letTempStateFlagBe(ConcreteDPM2Status :: ConcreteDPM2_Unloading); + + //compute the product of dRhoDStress and DS1DStress + FloatMatrixF < 6, 6 > dRhoDS1; + for ( int v = 0; v < 6; v++ ) { + for ( int w = 0; w < 6; w++ ) { + dRhoDS1.at(v + 1, w + 1) = dRhoDStress.at(v + 1) * dS1DStress.at(w + 1); } } - } -} -void -ConcreteDPM2 :: computeDRhoDStress(FloatArray &answer, - const FloatArray &stress) const -{ - int size = 6; - //compute volumetric deviatoric split - FloatArray deviatoricStress; - computeDeviatoricVolumetricSplit(deviatoricStress, stress); - double rho = computeSecondCoordinate(deviatoricStress); + auto dDRhoDDStress = computeDDRhoDDStress(stress); + dDCosThetaDDStress = dDRhoDDStress; + dDCosThetaDDStress *= ( -sqrt(3. / 2.) * principalDeviatoricStress.at(1) / pow(rho, 2.) ); - //compute the derivative of J2 with respect to the stress - FloatArray dJ2DStress; - dJ2DStress = deviatoricStress; - for ( int i = 3; i < size; i++ ) { - dJ2DStress(i) = deviatoricStress(i) * 2.0; - } + auto helpB1 = dS1DRho; + helpB1 *= ( -sqrt(3. / 2.) / pow(rho, 2.) ); - //compute the derivative of rho with respect to stress - answer = dJ2DStress; - answer.times(1. / rho); -} + auto helpC1 = dRhoDRho; + helpC1 *= ( sqrt(6.) * principalDeviatoricStress.at(1) / pow(rho, 3.) ); -void -ConcreteDPM2 :: computeDSigDStress(FloatArray &answer) const -{ - int size = 6; - for ( int i = 0; i < 3; i++ ) { - answer(i) = 1. / 3.; - } + auto helpD1 = dRhoDS1; + helpD1 *= ( -sqrt(3. / 2.) / pow(rho, 2.) ); + dDCosThetaDDStress += helpB1; + dDCosThetaDDStress += helpC1; + dDCosThetaDDStress += helpD1; - for ( int i = 3; i < size; i++ ) { - answer(i) = 0.; + return dDCosThetaDDStress; } -} - -void -ConcreteDPM2 :: computeDDRhoDDStress(FloatMatrix &answer, - const FloatArray &stress) const -{ - int size = 6; + FloatArrayF < 6 > + ConcreteDPM2::computeDRhoDStress(const FloatArrayF < 6 > & stress) const + { + //compute volumetric deviatoric split + auto deviatoricStress = computeDeviator(stress); + double rho = computeSecondCoordinate(deviatoricStress); - //compute volumetric deviatoric split - FloatArray deviatoricStress; - computeDeviatoricVolumetricSplit(deviatoricStress, stress); - double rho = computeSecondCoordinate(deviatoricStress); + //compute the derivative of J2 with respect to the stress + auto dJ2DStress = deviatoricStress; + for ( int i = 3; i < 6; i++ ) { + dJ2DStress.at(i + 1) = deviatoricStress.at(i + 1) * 2.0; + } + //compute the derivative of rho with respect to stress + return dJ2DStress * ( 1. / rho ); + } - //compute first dericative of J2 - FloatArray dJ2dstress; - dJ2dstress = deviatoricStress; - for ( int i = 3; i < deviatoricStress.giveSize(); i++ ) { - dJ2dstress(i) = deviatoricStress(i) * 2.; + FloatArrayF < 6 > + ConcreteDPM2::computeDSigDStress() const + { + return { + 1. / 3., 1. / 3., 1. / 3., 0., 0., 0. + }; } - //compute second derivative of J2 - FloatMatrix ddJ2ddstress(size, size); - ddJ2ddstress.zero(); - for ( int i = 0; i < size; i++ ) { - if ( i < 3 ) { - ddJ2ddstress(i, i) = 2. / 3.; - } - if ( i > 2 ) { - ddJ2ddstress(i, i) = 2.; + FloatMatrixF < 6, 6 > + ConcreteDPM2::computeDDRhoDDStress(const FloatArrayF < 6 > & stress) const + { + //compute volumetric deviatoric split + auto deviatoricStress = computeDeviator(stress); + double rho = computeSecondCoordinate(deviatoricStress); + + //compute first dericative of J2 + auto dJ2dstress = deviatoricStress; + for ( int i = 3; i < 6; i++ ) { + dJ2dstress.at(i + 1) = deviatoricStress.at(i + 1) * 2.; } - } - ddJ2ddstress(0, 1) = -1. / 3.; - ddJ2ddstress(0, 2) = -1. / 3.; - ddJ2ddstress(1, 0) = -1. / 3.; - ddJ2ddstress(1, 2) = -1. / 3.; - ddJ2ddstress(2, 0) = -1. / 3.; - ddJ2ddstress(2, 1) = -1. / 3.; + //compute second derivative of J2 + FloatMatrixF < 6, 6 > ddJ2ddstress; + for ( int i = 0; i < 6; i++ ) { + if ( i < 3 ) { + ddJ2ddstress.at(i + 1, i + 1) = 2. / 3.; + } - //compute the second derivative of rho - answer = ddJ2ddstress; - answer.times(1. / rho); - //compute square of the first derivative of J2 - answer.plusDyadUnsym(dJ2dstress, dJ2dstress, -1. / ( rho * rho * rho )); -} + if ( i > 2 ) { + ddJ2ddstress.at(i + 1, i + 1) = 2.; + } + } -int -ConcreteDPM2 :: giveIPValue(FloatArray &answer, - GaussPoint *gp, - InternalStateType type, - TimeStep *tStep) -{ - ConcreteDPM2Status *status = static_cast< ConcreteDPM2Status * >( this->giveStatus(gp) ); + ddJ2ddstress.at(1, 2) = -1. / 3.; + ddJ2ddstress.at(1, 3) = -1. / 3.; + ddJ2ddstress.at(2, 1) = -1. / 3.; + ddJ2ddstress.at(2, 3) = -1. / 3.; + ddJ2ddstress.at(3, 1) = -1. / 3.; + ddJ2ddstress.at(3, 2) = -1. / 3.; - switch ( type ) { - case IST_PlasticStrainTensor: - answer = status->givePlasticStrain(); - return 1; + return ddJ2ddstress * ( 1. / rho ) + dyad(dJ2dstress, dJ2dstress) * ( -1. / ( rho * rho * rho ) ); + } - case IST_DamageTensor: - answer.resize(6); - answer.zero(); - answer.at(1) = status->giveDamageTension(); - answer.at(2) = status->giveDamageCompression(); - answer.at(3) = status->giveDissWork(); - return 1; + int + ConcreteDPM2::giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *tStep) + { + auto status = static_cast < ConcreteDPM2Status * > ( this->giveStatus(gp) ); + + switch ( type ) { + case IST_PlasticStrainTensor: + answer = status->givePlasticStrain(); + return 1; + + case IST_DamageTensor: + answer.resize(6); + answer.zero(); + answer.at(1) = status->giveDamageTension(); + answer.at(2) = status->giveDamageCompression(); + answer.at(3) = status->giveDissWork(); + return 1; #ifdef keep_track_of_dissipated_energy - case IST_StressWorkDensity: - answer.resize(1); - answer.at(1) = status->giveStressWork(); - return 1; + case IST_StressWorkDensity: + answer.resize(1); + answer.at(1) = status->giveStressWork(); + return 1; - case IST_DissWorkDensity: - answer.resize(1); - answer.at(1) = status->giveDissWork(); - return 1; + case IST_DissWorkDensity: + answer.resize(1); + answer.at(1) = status->giveDissWork(); + return 1; - case IST_FreeEnergyDensity: - answer.resize(1); - answer.at(1) = status->giveStressWork() - status->giveDissWork(); - return 1; + case IST_FreeEnergyDensity: + answer.resize(1); + answer.at(1) = status->giveStressWork() - status->giveDissWork(); + return 1; #endif - default: - return StructuralMaterial :: giveIPValue(answer, gp, type, tStep); + default: + return StructuralMaterial::giveIPValue(answer, gp, type, tStep); + } } -} -MaterialStatus * -ConcreteDPM2 :: CreateStatus(GaussPoint *gp) const -{ - return new ConcreteDPM2Status(1, StructuralMaterial :: giveDomain(), gp); -} + MaterialStatus * + ConcreteDPM2::CreateStatus(GaussPoint *gp) const + { + return new ConcreteDPM2Status(gp); + } } //end of namespace diff --git a/src/sm/Materials/ConcreteMaterials/concretedpm2.h b/src/sm/Materials/ConcreteMaterials/concretedpm2.h index 6d91acb2b..1aa2aced4 100644 --- a/src/sm/Materials/ConcreteMaterials/concretedpm2.h +++ b/src/sm/Materials/ConcreteMaterials/concretedpm2.h @@ -35,22 +35,21 @@ #ifndef ConcreteDPM2_h #define ConcreteDPM2_h -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "floatarray.h" #include "floatmatrix.h" #include "cltypes.h" -#include "../sm/Materials/structuralms.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "gausspoint.h" #include "mathfem.h" -#define DYNCON_TOL 1.e-6 +#define CDPM2_TOL 1.e-6 #define keep_track_of_dissipated_energy ///@name Input fields for ConcreteDPM2 //@{ #define _IFT_ConcreteDPM2_Name "con2dpm" #define _IFT_ConcreteDPM2_fc "fc" -#define _IFT_ConcreteDPM2_fcZero "fczero" #define _IFT_ConcreteDPM2_ft "ft" #define _IFT_ConcreteDPM2_ecc "ecc" #define _IFT_ConcreteDPM2_kinit "kinit" @@ -60,6 +59,7 @@ #define _IFT_ConcreteDPM2_dhard "dhard" #define _IFT_ConcreteDPM2_dilation "dilation" #define _IFT_ConcreteDPM2_asoft "asoft" +#define _IFT_ConcreteDPM2_bsoft "bsoft" #define _IFT_ConcreteDPM2_hp "hp" #define _IFT_ConcreteDPM2_yieldtol "yieldtol" #define _IFT_ConcreteDPM2_newtoniter "newtoniter" @@ -68,16 +68,20 @@ #define _IFT_ConcreteDPM2_softeningType "stype" #define _IFT_ConcreteDPM2_ftOne "ft1" #define _IFT_ConcreteDPM2_wfOne "wf1" -#define _IFT_ConcreteDPM2_rateFlag "rateflag" -#define _IFT_ConcreteDPM2_timeFactor "timefactor" +#define _IFT_ConcreteDPM2_strengthratetype "sratetype" +#define _IFT_ConcreteDPM2_energyratetype "eratetype" +#define _IFT_ConcreteDPM2_deltatime "deltat" #define _IFT_ConcreteDPM2_helem "helem" -#define _IFT_ConcreteDPM2_isoflag "isoflag" +#define _IFT_ConcreteDPM2_damflag "damflag" //@} namespace oofem { /** * This class implements the material status associated to ConcreteDPM2. - * @author Peter Grassl + * Main article is "CDPM2: A damage-plasticity approach to modelling the failure of concrete" + * International Journal of Solids and Structures, Volume 50, Issue 24, November 2013, Pages 3805-3816 + * See also https://petergrassl.com/Research/Constitutive/index.html for more info. + * @author Peter Grassl, Dimitrios Xenos */ class ConcreteDPM2Status : public StructuralMaterialStatus { @@ -94,118 +98,151 @@ class ConcreteDPM2Status : public StructuralMaterialStatus ConcreteDPM2_VertexCompressionDamage, ConcreteDPM2_VertexTensionDamage }; + + + protected: + /// @name History variables of the plasticity model //@{ - FloatArray plasticStrain; - FloatArray tempPlasticStrain; + FloatArrayF< 6 >plasticStrain; + FloatArrayF< 6 >tempPlasticStrain; - double dFDKappa; - double deltaLambda; + FloatArrayF< 6 >reducedStrain; + FloatArrayF< 6 >tempReducedStrain; + + FloatArrayF< 6 >effectiveStress; + FloatArrayF< 6 >tempEffectiveStress; //@} /// @name Hardening variable //@{ - double kappaP; - double tempKappaP; + double kappaP = 0.; + double tempKappaP = 0.; //@} - double kappaPPeak; + double kappaPPeak = 0.; + + double deltaLambda = 0.; - double le; + double le = 0.; - double alpha; - double tempAlpha; + double alpha = 0.; + double tempAlpha = 0.; - double equivStrain; - double tempEquivStrain; + double equivStrain = 0.; + double tempEquivStrain = 0.; - double equivStrainTension; - double tempEquivStrainTension; + double equivStrainTension = 0.; + double tempEquivStrainTension = 0.; - double equivStrainCompression; - double tempEquivStrainCompression; + double equivStrainCompression = 0.; + double tempEquivStrainCompression = 0.; - double kappaDTension; - double tempKappaDTension; + double kappaDTension = 0.; + double tempKappaDTension = 0.; - double kappaDCompression; - double tempKappaDCompression; + double kappaDCompression = 0.; + double tempKappaDCompression = 0.; - double kappaDTensionOne; - double tempKappaDTensionOne; + double kappaDTensionOne = 0.; + double tempKappaDTensionOne = 0.; - double kappaDCompressionOne; - double tempKappaDCompressionOne; + double kappaDCompressionOne = 0.; + double tempKappaDCompressionOne = 0.; - double kappaDTensionTwo; - double tempKappaDTensionTwo; + double kappaDTensionTwo = 0.; + double tempKappaDTensionTwo = 0.; - double kappaDCompressionTwo; - double tempKappaDCompressionTwo; + double kappaDCompressionTwo = 0.; + double tempKappaDCompressionTwo = 0.; - double damageTension; - double tempDamageTension; + double damageTension = 0.; + double tempDamageTension = 0.; - double damageCompression; - double tempDamageCompression; + double damageCompression = 0.; + double tempDamageCompression = 0.; - double deltaEquivStrain; + double deltaEquivStrain = 0.; - double rateFactor; - double tempRateFactor; + double rateFactor = 1.; + double tempRateFactor = 0.; /// Strains that are used for calculation of strain rates - double rateStrain; - double tempRateStrain; + double rateStrain = 0.; + double tempRateStrain = 0.; /// Indicates the state (i.e. elastic, unloading, plastic, damage, vertex) of the Gauss point - int state_flag; - int temp_state_flag; + int state_flag = ConcreteDPM2Status::ConcreteDPM2_Elastic; + int temp_state_flag = ConcreteDPM2Status::ConcreteDPM2_Elastic; + + int deletionFlag = 0.; + int tempDeletionFlag = 1.; + + #ifdef keep_track_of_dissipated_energy /// Density of total work done by stresses on strain increments. - double stressWork; + double stressWork = 0.; /// Non-equilibrated density of total work done by stresses on strain increments. - double tempStressWork; + double tempStressWork = 0.; /// Density of dissipated work. - double dissWork; + double dissWork = 0.; /// Non-equilibrated density of dissipated work. - double tempDissWork; + double tempDissWork = 0.; #endif public: /// Constructor - ConcreteDPM2Status(int n, Domain *d, GaussPoint *gp); + ConcreteDPM2Status(GaussPoint *gp); + + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) const override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + const char *giveClassName() const override { return "ConcreteDPM2Status"; } - /// Destructor - virtual ~ConcreteDPM2Status(); + void setTempDeletionFlag(int newFlag) { this->tempDeletionFlag = newFlag; } + int giveDeletionFlag() const { return this->deletionFlag; } + int giveTempDeletionFlag() const { return this->tempDeletionFlag; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual contextIOResultType saveContext(DataStream &, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &, ContextMode mode, void *obj = NULL); - virtual const char *giveClassName() const { return "ConcreteDPM2Status"; } // Inline functions for access to state variables /** - * Get the plastic strain deviator from the material status. - * @return Plastic strain deviator. + * Get the reduced strain vector from the material status. + * @return Strain vector. + */ + const FloatArrayF< 6 > &giveReducedStrain() const { return reducedStrain; } + + /** + * Get the reduced strain vector from the material status. + * @return Strain vector. */ - const FloatArray &givePlasticStrain() const { return plasticStrain; } + const FloatArrayF< 6 > &giveTempReducedStrain() const { return tempReducedStrain; } + + /** + * Get the effective stress vector from the material status. + * @return effective stress vector. + */ + const FloatArrayF< 6 > &giveTempEffectiveStress() const { return tempEffectiveStress; } + + /** + * Get the plastic strain vector from the material status. + * @return Strain vector. + */ + const FloatArrayF< 6 > &givePlasticStrain() const { return plasticStrain; } /** * Get the deviatoric plastic strain norm from the material status. * @return DeviatoricPlasticStrainNorm. */ - double giveDeviatoricPlasticStrainNorm() + double giveDeviatoricPlasticStrainNorm() const { - FloatArray dev; - StructuralMaterial :: computeDeviatoricVolumetricSplit(dev, plasticStrain); - return sqrt( .5 * ( 2. * dev [ 0 ] * dev [ 0 ] + 2. * dev [ 1 ] * dev [ 1 ] + 2. * dev [ 2 ] * dev [ 2 ] + - dev [ 3 ] * dev [ 3 ] + dev [ 4 ] * dev [ 4 ] + dev [ 5 ] * dev [ 5 ] ) ); + auto dev = StructuralMaterial::computeDeviator(plasticStrain); + return sqrt(.5 * ( 2. * dev [ 0 ] * dev [ 0 ] + 2. * dev [ 1 ] * dev [ 1 ] + 2. * dev [ 2 ] * dev [ 2 ] + + dev [ 3 ] * dev [ 3 ] + dev [ 4 ] * dev [ 4 ] + dev [ 5 ] * dev [ 5 ] ) ); } /** @@ -214,7 +251,7 @@ class ConcreteDPM2Status : public StructuralMaterialStatus */ double giveVolumetricPlasticStrain() const { - return 1. / 3. * ( plasticStrain(0) + plasticStrain(1) + plasticStrain(2) ); + return 1. / 3. * ( plasticStrain [ 0 ] + plasticStrain [ 1 ] + plasticStrain [ 2 ] ); } /** @@ -292,7 +329,6 @@ class ConcreteDPM2Status : public StructuralMaterialStatus double giveDamageTension() const { return damageTension; } - /** * Get the compressive damage variable of the damage model from the * material status. @@ -301,8 +337,6 @@ class ConcreteDPM2Status : public StructuralMaterialStatus double giveDamageCompression() const { return damageCompression; } - - /** * Get the rate factor of the damage model from the * material status. @@ -326,6 +360,7 @@ class ConcreteDPM2Status : public StructuralMaterialStatus void letTempRateStrainBe(double v) { tempRateStrain = v; } + void letTempAlphaBe(double v) { tempAlpha = v; } @@ -344,14 +379,13 @@ class ConcreteDPM2Status : public StructuralMaterialStatus * Get the temp value of the full plastic strain vector from the material status. * @return Temp value of plastic strain vector. */ - const FloatArray &giveTempPlasticStrain() const { return tempPlasticStrain; } + const FloatArrayF< 6 > &giveTempPlasticStrain() const { return tempPlasticStrain; } /** * Get the temp value of the volumetric plastic strain in plane stress */ double giveTempVolumetricPlasticStrain() const - { return 1. / 3. * ( tempPlasticStrain(0) + tempPlasticStrain(1) + tempPlasticStrain(2) ); } - + { return 1. / 3. * ( tempPlasticStrain [ 0 ] + tempPlasticStrain [ 1 ] + tempPlasticStrain [ 2 ] ); } /** * Get the temp value of the hardening variable of the plasticity model @@ -361,6 +395,8 @@ class ConcreteDPM2Status : public StructuralMaterialStatus double giveTempKappaP() const { return tempKappaP; } + double giveDeltaLambda() const + { return deltaLambda; } /** * Get the temp value of the hardening variable of the damage model @@ -370,9 +406,21 @@ class ConcreteDPM2Status : public StructuralMaterialStatus double giveKappaDTension() const { return kappaDTension; } + /** + * Get value of alpha from the status. + * @return value of alpha. + */ double giveAlpha() const { return alpha; } + /** + * Get value of temp alpha from the status. + * @return value of temp alpha. + */ + double giveTempAlpha() const + { return tempAlpha; } + + /** * Get the temp value of the hardening variable of the damage model @@ -382,7 +430,6 @@ class ConcreteDPM2Status : public StructuralMaterialStatus double giveKappaDCompression() const { return kappaDCompression; } - /** * Get the temp value of the hardening variable of the damage model * from the material status. @@ -391,7 +438,6 @@ class ConcreteDPM2Status : public StructuralMaterialStatus double giveTempDamageTension() const { return tempDamageTension; } - /** * Get the temp value of the hardening variable of the damage model * from the material status. @@ -408,7 +454,6 @@ class ConcreteDPM2Status : public StructuralMaterialStatus double giveDeltaEquivStrain() const { return deltaEquivStrain; } - /** * Get the temp value of the state flag from the material status. * @return Temp value of the state flag (i.e. elastic, unloading, @@ -417,22 +462,22 @@ class ConcreteDPM2Status : public StructuralMaterialStatus int giveTempStateFlag() const { return temp_state_flag; } - // letTemp...be : // Functions used by the material to assign a new value to a temp variable. /** * Assign the temp value of deviatoric plastic strain. * @param v New temp value of deviatoric plastic strain */ - void letTempPlasticStrainBe(const FloatArray &v) + void letTempPlasticStrainBe(const FloatArrayF< 6 > &v) { tempPlasticStrain = v; } - /** - * Assign the temp value of the rate factor of the damage model. - * @param v New temp value of the damage variable - */ - void letDeltaLambdaBe(double v) - { deltaLambda = v; } + + void letTempReducedStrainBe(const FloatArrayF< 6 > &v) + { tempReducedStrain = v; } + + void letTempEffectiveStressBe(const FloatArrayF< 6 > &v) + { tempEffectiveStress = v; } + /** * Assign the temp value of the hardening variable of the plasticity model. @@ -441,6 +486,9 @@ class ConcreteDPM2Status : public StructuralMaterialStatus void letTempKappaPBe(double v) { tempKappaP = v; } + void letDeltaLambdaBe(double v) + { deltaLambda = v; } + /** * Assign the temp value of the rate factor of the damage model. * @param v New temp value of the damage variable @@ -525,16 +573,14 @@ class ConcreteDPM2Status : public StructuralMaterialStatus void letTempEquivStrainCompressionBe(double v) { tempEquivStrainCompression = v; } - /** * Gives the characteristic length. */ - double giveLe() { return le; } + double giveLe() const { return le; } /** * Sets the characteristic length. */ - void setLe(double ls) { le = ls; } /** @@ -545,7 +591,6 @@ class ConcreteDPM2Status : public StructuralMaterialStatus void letTempStateFlagBe(const int v) { temp_state_flag = v; } - void letKappaPPeakBe(double kappa) { kappaPPeak = kappa; } #ifdef keep_track_of_dissipated_energy @@ -573,9 +618,9 @@ class ConcreteDPM2Status : public StructuralMaterialStatus }; -// ******************************** -// *** CLASS DYNAMIC CONCRETE *** -// ******************************** +// ************************************************** +// *** CLASS CONCRETE DAMAGE PLASTICITY MODEL 2 *** +// ************************************************** /** * This class contains the combination of a local plasticity model for concrete with a local isotropic damage model. @@ -584,141 +629,151 @@ class ConcreteDPM2Status : public StructuralMaterialStatus * The plasticity model describes only hardening and perfect plasticity. * It is based on the effective stress. The damage parameter of the isotropic damage model is based on the total volumetric strain. * An exponential softening law is implemented. + * + * @author Peter Grassl, Dimitrios Xenos */ class ConcreteDPM2 : public StructuralMaterial { public: -protected: - enum ConcreteDPM2_ReturnType { RT_Regular, RT_Tension, RT_Compression, RT_Auxiliary }; - ConcreteDPM2_ReturnType returnType; + enum ConcreteDPM2_ReturnResult { + RR_Unknown, + RR_NotConverged, + RR_Converged + }; + + enum ConcreteDPM2_ReturnType { + RT_Unknown, + RT_Regular, + RT_Tension, + RT_Compression, + RT_Auxiliary + }; - enum ConcreteDPM2_ReturnResult { RR_NotConverged, RR_Converged }; - ConcreteDPM2_ReturnResult returnResult; +protected: /// Parameters of the yield surface of the plasticity model. fc is the uniaxial compressive strength, ft the uniaxial tensile strength and ecc controls the out of roundness of the deviatoric section. - double fc, ft, ecc; + double fc = 0., ft = 0., ecc = 0.; - int isotropicFlag; + /** Parameter which controls the type of damage that is used together with plasticity + * 0: tensile and compression damage based on split of stress state + */ + int damageFlag = 0; - double e0; + double e0 = 0.; /// Parameter of the ductilityMeasure of the plasticity model. - double AHard; + double AHard = 0.; /// Parameter of the ductilityMeasure of the plasticity model. - double BHard; + double BHard = 0.; /// Parameter of the ductilityMeasure of the plasticity model. - double CHard; + double CHard = 0.; /// Parameter of the ductilityMeasure of the plasticity model. - double DHard; + double DHard = 0.; /// Hardening modulus. - double hardeningModulus; + double hardeningModulus = 0.; + + /// Parameter of the ductilityMeasure of the damage model. + double ASoft = 0.; /// Parameter of the ductilityMeasure of the damage model. - double ASoft; + double BSoft = 0.; /// Parameter of the hardening law of the plasticity model. - double yieldHardPrimePeak; + double yieldHardPrimePeak = 0.; /// Parameter of the hardening law of the plasticity model. - double yieldHardInitial; + double yieldHardInitial = 0.; /// Control parameter for te volumetric plastic flow of the plastic potential. - double dilationConst; - - ///@todo These values should not be stored by the material model itself. As temp values in the status they would be OK, but this will be thread unsafe (and makes the model into a complete spagetti code) / Mikael -#if 1 - /// Volumetric stress. - double sig; - - /// Length of the deviatoric stress. - double rho; - - /// Lode angle of the trial stress.. - double thetaTrial; -#endif + double dilationConst = 0.; /// Friction parameter of the yield surface. - double m; + double m = 0.; /// Dilation parameter of the plastic potential. - double mQ; + double mQ = 0.; /// Element size (to be used in fracture energy approach (crack band). - double helem; + double helem = 0.; /// Pointer for linear elastic material. - LinearElasticMaterial *linearElasticMaterial; + IsotropicLinearElasticMaterial linearElasticMaterial; /// Elastic Young's modulus. - double eM; + double eM = 0.; /// Elastic shear modulus. - double gM; + double gM = 0.; /// Elastic bulk modulus. - double kM; + double kM = 0.; /// Elastic poisson's ration. - double nu; + double nu = 0.; /// Control parameter for the exponential softening law. - double efCompression; + double efCompression = 0.; /// Control parameter for the linear/bilinear softening law in tension. - double wf; + double wf = 0.; /// Control parameter for the bilinear softening law in tension. - double wfOne; + double wfOne = 0.; /// Control parameter for the bilinear softening law. - double ftOne; + double ftOne = 0.; /// yield tolerance for the plasticity model. - double yieldTol; + double yieldTol = 0.; /// yield tolerance for the damage model. - double yieldTolDamage; + double yieldTolDamage = 0.; /// Maximum number of iterations for stress return. - int newtonIter; + int newtonIter = 0; /// Type of softening function used. - int softeningType; + int softeningType = 0.; /// Input parameter which simulates a loading rate. Only for debugging purposes. - double timeFactor; + double deltaTime = 0.; - /// This parameter is needed for the rate dependence. It should be read in if rate dependence is considered. - double fcZero; - - /// Flag which signals if strainRate effects should be considered. - int strainRateFlag; + /** Type of strength strain rate dependence used. + * 0 = no strain rate (default) + * 1 = Model Code 2010 initial branch of strain rate effect for strength + * 2 = Model Code 2010 initial and second branch of strain rate effect for strength + */ + int strengthRateType = 0; + /** Type of energy strain rate dependence used if strengthRateType >0 . + * 0 = mod. CEB strain rate effect for strength with constant fracture energy + * 1 = CEB strain rate effect for strength and linear for fracture energy + * 2 = mod. CEB strain rate effect for strength and squared for fracture energy + * + */ + int energyRateType = 0; public: /// Constructor ConcreteDPM2(int n, Domain *d); - /// Destructor - virtual ~ConcreteDPM2(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "ConcreteDPM2"; } - virtual const char *giveInputRecordName() const { return _IFT_ConcreteDPM2_Name; } + void initializeFrom(InputRecord &ir) override; - LinearElasticMaterial *giveLinearElasticMaterial() - { return linearElasticMaterial; } + const char *giveClassName() const override { return "ConcreteDPM2"; } + const char *giveInputRecordName() const override { return _IFT_ConcreteDPM2_Name; } - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep); + FloatArrayF< 6 >giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strainVector, TimeStep *tStep); + bool hasMaterialModeCapability(MaterialMode mode) const override; /** * Perform stress return of the plasticity model and compute history variables. * @param gp Gauss point. + * @param D stiffness matrix * @param strain Strain vector of this Gauss point. */ - void performPlasticityReturn(GaussPoint *gp, - const FloatMatrix &D, - const FloatArray &strain); + FloatArrayF< 6 >performPlasticityReturn(GaussPoint *gp, + const FloatMatrixF< 6, 6 > &D, + const FloatArrayF< 6 > &strain) const; /** * Check if the trial stress state falls within the vertex region of the plasticity model at the apex of triaxial extension or triaxial compression. @@ -726,35 +781,28 @@ class ConcreteDPM2 : public StructuralMaterial * @param answer Volumetric apex stress. * @param sig Volumetric stress. * @param tempKappa Hardening variable. + * @param gp Gauss point */ - bool checkForVertexCase(double &answer, + void checkForVertexCase(double &answer, + ConcreteDPM2_ReturnType &returnType, double sig, double tempKappa, - bool mode1d); + GaussPoint *gp) const; /** * Perform regular stress return for the plasticity model, i.e. if the trial stress state does not lie in the vertex region. * @param stress Stress vector which is computed. * @param kappaP Initial guess for kappa P (i.e. previous kappa) * @param gp Gauss point. + * @param theta Load angle of trial stress (remains constant throughout return). */ - double performRegularReturn(FloatArray &stress, + double performRegularReturn(FloatArrayF< 6 > &stress, + ConcreteDPM2_ReturnResult &returnResult, + ConcreteDPM2_ReturnType &returnType, double kappaP, - GaussPoint *gp); - - /** - * Compute jacobian for 1D case - * @param totalsigma stress value - * @param tempKappa plastic strain - * @param deltaLambda plastic multiplier - * @param gp Gauss point - */ + GaussPoint *gp, + double theta) const; - void compute1dJacobian(FloatMatrix &answer, - double totalsigma, - double tempKappa, - double deltaLambda, - GaussPoint *gp); /** * Compute jacobian for 2D(plane strain) and 3d cases * @param sig volumetric strain @@ -763,25 +811,28 @@ class ConcreteDPM2 : public StructuralMaterial * @param deltaLambda plastic multiplier * @param gp Gauss point */ - void computeJacobian(FloatMatrix &answer, - double sig, - double rho, - double tempKappa, - double deltaLambda, - GaussPoint *gp); + FloatMatrixF< 4, 4 >computeJacobian(double sig, + double rho, + double theta, + double tempKappa, + double deltaLambda, + GaussPoint *gp) const; /** * Perform stress return for vertex case of the plasticity model, i.e. if the trial stress state lies within the vertex region. * @param stress Stress vector of this Gauss point. * @param apexStress Volumetric stress at the apex of the yield surface. + * @param theta Lode angle. * @param tempKappaP temporary cummulative plastic strain * @param gp Gauss point. * @returns updated temporary cummulative plastic strain */ - double performVertexReturn(FloatArray &stress, + double performVertexReturn(FloatArrayF< 6 > &stress, + ConcreteDPM2_ReturnResult &returnResult, + ConcreteDPM2_ReturnType &returnType, double apexStress, double tempKappaP, - GaussPoint *gp); + GaussPoint *gp) const; /** * Compute the yield value based on stress and hardening variable. @@ -829,24 +880,24 @@ class ConcreteDPM2 : public StructuralMaterial * variable based on the stress state and the hardening variable * @param sig Volumetric stress. * @param rho Deviatoric length. + * @param theta Lode angle. * @param tempKappa Hardening variable. * @return Derivative of the yield surface. */ double computeDFDKappa(double sig, double rho, - double tempKappa, - bool mode1d); - + double theta, + double tempKappa) const; /** * Compute the derivative of kappa with respect of delta lambda based on the stress state and the hardening variable. * @param sig Volumetric stress. * @param rho Length of the deviatoric stress. + * @param theta Lode angle * @param tempKappa Hardening variable. * @return Derivative of kappa with respect to delta lambda. */ - double computeDKappaDDeltaLambda(double sig, double rho, double tempKappa); - double computeDKappaDDeltaLambda1d(double sig, double tempKappa); + double computeDKappaDDeltaLambda(double sig, double rho, double theta, double tempKappa) const; /** @@ -858,28 +909,20 @@ class ConcreteDPM2 : public StructuralMaterial */ virtual double computeDuctilityMeasure(double sig, double rho, - double theta); - - + double theta) const; /** * Compute derivative the ductility measure with respect to the stress state. * @param answer array of the derivative of the ductility measure with respect to volumetric and deviatoric stress * @param sig Volumetric stress. * @param rho Length of the deviatoric strength. + * @param theta Lode angle. * @param tempKappa plastic strain */ - void computeDDuctilityMeasureDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa); - /** - * Compute derivative the ductility measure with respect to the stress state. - * @return The derivative of the ductility measure with respect to stress - * @param sig stress. - * @param tempKappa plastic strain - */ - double computeDDuctilityMeasureDInv1d(double sigma, double tempKappa); //Dimitris change 1d implementation + FloatArrayF< 2 >computeDDuctilityMeasureDInv(double sig, + double rho, + double theta, + double tempKappa) const; /** * Compute derivative the palstic potential function with respect to the stress state. @@ -888,17 +931,9 @@ class ConcreteDPM2 : public StructuralMaterial * @param rho deviatoric stress. * @param tempKappa plastic strain */ - void computeDGDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa); - /** - * Compute derivative the palstic potential function with respect to the stress state. - * @param return The derivative of the plastic potential with respect to stress - * @param sig stress. - * @param tempKappa plastic strain - */ - double computeDGDInv1d(double sig, double tempKappa); + FloatArrayF< 2 >computeDGDInv(double sig, + double rho, + double tempKappa) const; /** * This function computes the ratio of the volumetric and deviatoric component @@ -906,7 +941,8 @@ class ConcreteDPM2 : public StructuralMaterial * if the vertex return is admissible. */ double computeRatioPotential(double sig, - double tempKappa); + double rho, + double tempKappa) const; /** * This function computes the rate factor which is used to take into account the strain rate dependence of the material. @@ -914,151 +950,193 @@ class ConcreteDPM2 : public StructuralMaterial double computeRateFactor(double alpha, double timeFactor, GaussPoint *gp, - TimeStep *deltaTime); + TimeStep *deltaTime) const; /** - * Here, the second derivative of the plastic potential with respect to the + * Computes the second derivative of the plastic potential with respect to the * invariants sig and rho are computed. */ - void computeDDGDDInv(FloatMatrix &answer, - double sig, - double rho, - double tempKappa); + FloatMatrixF< 2, 2 >computeDDGDDInv(double sig, + double rho, + double tempKappa) const; + + /** - * Here, the second derivative of the plastic potential with respect to the - * invariants sig and rho are computed. + * Computes the second derivative of the plastic potential with respect to the + * stress. + */ + FloatMatrixF< 6, 6 >computeDDGDDStress(const FloatArrayF< 6 > &stress, + const double tempKappa) const; + + + /** + * Computes the derivative of cos theta with respect to the + * stress. + */ + FloatArrayF< 6 >computeDCosThetaDStress(const FloatArrayF< 6 > &stress) const; + + /** + * Computes the second derivative of cos theta with respect to the + * stress. */ - double computeDDGDDInv1d(double sigma, double tempKappa); + FloatMatrixF< 6, 6 >computeDDCosThetaDDStress(const FloatArrayF< 6 > &stress) const; + /** - * Here, the mixed derivative of the plastic potential with respect + * The mixed derivative of the plastic potential with respect * to the invariants and the hardening parameter are determined. */ - void computeDDGDInvDKappa(FloatArray &answer, - double sig, - double rho, - double tempKappa); + FloatArrayF< 2 >computeDDGDInvDKappa(double sig, + double rho, + double tempKappa) const; + - double computeDDGDInvDKappa1d(double sigma, double tempKappa); /** * Computes the mixed derivative of the hardening parameter kappa with * respect to the plastic multiplier delta Lambda and the invariants sig * and rho. */ - void computeDDKappaDDeltaLambdaDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa); + FloatArrayF< 2 >computeDDKappaDDeltaLambdaDInv(double sig, + double rho, + double theta, + double tempKappa) const; + + /** + * Computes the derivative of evolution law of hardening variable with respect to the + * stress. + */ + FloatArrayF< 6 >computeDDKappaDDeltaLambdaDStress(const FloatArrayF< 6 > &stress, double tempKappa) const; + + + /** + * Computes the second mixed derivative of plastic potential with respect to the + * stress and kappa. + */ + FloatArrayF< 6 >computeDDGDStressDKappa(const FloatArrayF< 6 > &stress, double tempKappa) const; - double computeDDKappaDDeltaLambdaDInv1d(double sigma, double tempKappa); /** * Computes the derivative of the evolution law of the hardening parameter kappa with respect to the hardening variable kappa. */ - double computeDDKappaDDeltaLambdaDKappa(double sig, double rho, double tempKappa); - double computeDDKappaDDeltaLambdaDKappa1d(double sig, double tempKappa); + double computeDDKappaDDeltaLambdaDKappa(double sig, double rho, double theta, double tempKappa) const; /** * Computes the derivative of the yield surface with respect to the * invariants sig and rho. */ - void computeDFDInv(FloatArray &answer, - double sig, - double rho, - double tempKappa) const; - double computeDFDInv1d(double sigma, double tempKappa) const; + FloatArrayF< 2 >computeDFDInv(double sig, + double rho, + double theta, + double tempKappa) const; + /** - * Compute tempKappa. + * Computes the derivative of the yield surface with respect to the + * stress. */ - double computeTempKappa(double kappaInitial, - double sigTrial, - double rhoTrial, - double sig); - + FloatArrayF< 6 >computeDFDStress(const FloatArrayF< 6 > &stress, + const double tempKappa) const; /** - * Compute damage parameters + * Computes the derivative of the plastic potential with respect to the + * stress. */ - void computeDamage(FloatArray &answer, const FloatArray &strain, const FloatMatrix &D, double timeFactor, GaussPoint *gp, TimeStep *tStep, double alpha); - + FloatArrayF< 6 >computeDGDStress(const FloatArrayF< 6 > &stress, + const double tempKappa) const; /** - * Check for un- and reloading in the damage part + * Computes full Jacobian used for the algorithmic tangent stiffness */ + FloatMatrixF< 8, 8 >computeFullJacobian(const FloatArrayF< 6 > &stress, + const double deltaLambda, + GaussPoint *gp, + TimeStep *atTime, + const double tempKappa) const; + + /// Compute tempKappa. + double computeTempKappa(double kappaInitial, + double sigTrial, + double rhoTrial, + double sig) const; + + /// Compute damage parameters + FloatArrayF< 2 >computeDamage(const FloatArrayF< 6 > &strain, const FloatMatrixF< 6, 6 > &D, double timeFactor, GaussPoint *gp, TimeStep *tStep, double alpha, const FloatArrayF< 6 > &effectiveStress) const; + + + /// Check for un- and reloading in the damage part int checkForUnAndReloading(double &tempEquivStrain, double &minEquivStrain, - const FloatMatrix &D, - GaussPoint *gp); + const FloatMatrixF< 6, 6 > &D, + GaussPoint *gp) const; - double computeAlpha(FloatArray &effectiveStressTension, FloatArray &effectiveStressCompression, FloatArray &effectiveStress); + /// Compute alpha for rate effect + double computeAlpha(FloatArrayF< 6 > &effectiveStressTension, FloatArrayF< 6 > &effectiveStressCompression, const FloatArrayF< 6 > &effectiveStress) const; - /// Compute damage parameter. - virtual double computeDamageParamTension(double equivStrain, double kappaOne, double kappaTwo, double le, double omegaOld); + /// Compute damage parameter in tension. + virtual double computeDamageParamTension(double equivStrain, double kappaOne, double kappaTwo, double le, double omegaOld, double rateFactor) const; - virtual double computeDamageParamCompression(double equivStrain, double kappaOne, double kappaTwo, double omegaOld); + /// Compute damage parameter in compression. + virtual double computeDamageParamCompression(double equivStrain, double kappaOne, double kappaTwo, double omegaOld, double rateFactor) const; - /// Compute equivalent strain value. - double computeDeltaPlasticStrainNormTension(double tempKappaD, double kappaD, GaussPoint *gp); + /// Compute equivalent strain value for tension. + double computeDeltaPlasticStrainNormTension(double tempKappaD, double kappaD, GaussPoint *gp) const; - double computeDeltaPlasticStrainNormCompression(double tempAlpha, double tempKappaD, double kappaD, GaussPoint *gp); - - virtual double computeEquivalentStrain(double sig, double rho, double theta); + /// Compute equivalent strain value for compression. + double computeDeltaPlasticStrainNormCompression(double tempAlpha, double tempKappaD, double kappaD, GaussPoint *gp, const double rho) const; + /// Compute the base equivalent strain value. + virtual double computeEquivalentStrain(double sig, double rho, double theta) const; /// Compute the ductility measure for the damage model. - double computeDuctilityMeasureDamage(const FloatArray &strain, GaussPoint *gp); + double computeDuctilityMeasureDamage(GaussPoint *gp, const double sig, const double rho) const; /** * Initialize the characteristic length, if damage is not yet activated * Set the increase factor for the strain rate dependence */ void initDamaged(double kappa, - const FloatArray &strain, - GaussPoint *gp); - + const FloatArrayF< 6 > &strain, + GaussPoint *gp) const; - /// Compute the trial coordinates. - void computeTrialCoordinates(const FloatArray &stress, double &sig, double &rho, double &theta); + /// Compute the Haigh-Westergaard coordinates. + void computeCoordinates(const FloatArrayF< 6 > &stress, double &sig, double &rho, double &theta) const; /// Assign state flag. - void assignStateFlag(GaussPoint *gp); + void assignStateFlag(GaussPoint *gp) const; /// Computes the derivative of rho with respect to the stress. - void computeDRhoDStress(FloatArray &answer, - const FloatArray &stress) const; + FloatArrayF< 6 >computeDRhoDStress(const FloatArrayF< 6 > &stress) const; - /// Computes the derivative of sig with respect to the stress. - void computeDSigDStress(FloatArray &answer) const; + /// Computes the derivative of function r with respect to cos theta + double computeDRDCosTheta(const double theta, const double ecc) const; + + /// Computes the second derivative of function r with respect to cos theta + double computeDDRDDCosTheta(const double theta, const double ecc) const; - /// Computes the seconfd derivative of rho with the respect to the stress. - void computeDDRhoDDStress(FloatMatrix &answer, - const FloatArray &stress) const; - /// Computes the derivative of costheta with respect to the stress. - void computeDCosThetaDStress(FloatArray &answer, - const FloatArray &stress) const; + /// Computes the derivative of sig with respect to the stress. + FloatArrayF< 6 >computeDSigDStress() const; - /// Compute the derivative of R with respect to costheta. - double computeDRDCosTheta(double theta, double ecc) const; + /// Computes the second derivative of rho with the respect to the stress. + FloatMatrixF< 6, 6 >computeDDRhoDDStress(const FloatArrayF< 6 > &stress) const; - virtual void give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF< 6, 6 >give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + /// Compute the 3d secant stiffness matrix. + FloatMatrixF< 6, 6 >compute3dSecantStiffness(GaussPoint *gp, TimeStep *tStep) const; - void compute3dSecantStiffness(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); + /// Compute the 3d tangent stiffness matrix. + FloatMatrixF< 6, 6 >compute3dTangentStiffness(GaussPoint *gp, TimeStep *tStep) const; + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual int giveIPValue(FloatArray &answer, - GaussPoint *gp, - InternalStateType type, - TimeStep *tStep); protected: - MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; }; } //end namespace oofem #endif diff --git a/src/sm/Materials/ConcreteMaterials/concretefcm.C b/src/sm/Materials/ConcreteMaterials/concretefcm.C index cafc94d8a..d65d0ac6e 100644 --- a/src/sm/Materials/ConcreteMaterials/concretefcm.C +++ b/src/sm/Materials/ConcreteMaterials/concretefcm.C @@ -42,32 +42,13 @@ namespace oofem { REGISTER_Material(ConcreteFCM); ConcreteFCM :: ConcreteFCM(int n, Domain *d) : FCMMaterial(n, d), RandomMaterialExtensionInterface() -{ - Gf = Ft = 0.; - softType = ST_Unknown; - shearType = SHR_Unknown; - linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); -} +{} -IRResultType -ConcreteFCM :: initializeFrom(InputRecord *ir) +void +ConcreteFCM :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = FCMMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - result = linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - result = RandomMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + FCMMaterial :: initializeFrom(ir); + RandomMaterialExtensionInterface :: initializeFrom(ir); // type of TENSION SOFTENING int softening = 0; @@ -104,13 +85,11 @@ ConcreteFCM :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, soft_function_w, _IFT_ConcreteFCM_soft_function_w); if ( soft_w.at(1) > 0. ) { - OOFEM_WARNING("The first entry in soft_w must be 0."); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_ConcreteFCM_soft_w, "The first entry in soft_w must be 0."); } if ( soft_w.giveSize() != soft_function_w.giveSize() ) { - OOFEM_WARNING("the size of 'soft_w' and 'soft(w)' must be the same"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_ConcreteFCM_soft_function_w, "the size of 'soft_w' and 'soft(w)' must be the same"); } break; @@ -122,7 +101,7 @@ ConcreteFCM :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, Ft, _IFT_ConcreteFCM_ft); if ( this->giveCrackSpacing() > 0. ) { - OOFEM_ERROR("crack spacing must not be defined in strain-defined materials (does not make sense)"); + throw ValueInputException(ir, _IFT_FCM_crackSpacing, "crack spacing must not be defined in strain-defined materials (does not make sense)"); } break; @@ -134,24 +113,21 @@ ConcreteFCM :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, soft_function_eps, _IFT_ConcreteFCM_soft_function_eps); if ( soft_eps.at(1) > 0. ) { - OOFEM_WARNING("The first entry in soft_eps must be 0."); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_ConcreteFCM_soft_eps, "The first entry in soft_eps must be 0."); } if ( soft_eps.giveSize() != soft_function_eps.giveSize() ) { - OOFEM_WARNING("the size of 'soft_eps' and 'soft(eps)' must be the same"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_ConcreteFCM_soft_function_eps, "the size of 'soft_eps' and 'soft(eps)' must be the same"); } if ( this->giveCrackSpacing() > 0. ) { - OOFEM_ERROR("crack spacing must not be defined in strain-defined materials (does not make sense)"); + throw ValueInputException(ir, "foo", "crack spacing must not be defined in strain-defined materials (does not make sense)"); } break; default: - OOFEM_WARNING("Softening type number %d is unknown", softType); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_ConcreteFCM_softType, "Unknown softening type"); } @@ -170,7 +146,7 @@ ConcreteFCM :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, beta, _IFT_ConcreteFCM_beta); if ( beta >= 1. ) { - OOFEM_ERROR("Parameter beta %f must be smaller than one", beta); + throw ValueInputException(ir, _IFT_ConcreteFCM_beta, "Parameter beta must be <= 1"); } break; @@ -181,6 +157,9 @@ ConcreteFCM :: initializeFrom(InputRecord *ir) shearType = SHR_Const_ShearFactorCoeff; sf = 20.; IR_GIVE_OPTIONAL_FIELD(ir, sf, _IFT_ConcreteFCM_sf); + + sf_numer = sf; + IR_GIVE_OPTIONAL_FIELD(ir, sf_numer, _IFT_ConcreteFCM_sf_numer); break; case 3: // w is the maximum reached crack opening, not the current value! @@ -189,15 +168,13 @@ ConcreteFCM :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, beta_function, _IFT_ConcreteFCM_beta_function); if ( beta_w.giveSize() != beta_function.giveSize() ) { - OOFEM_WARNING("the size of 'beta_w' and 'beta(w)' must be the same"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_ConcreteFCM_beta_function, "the size of 'beta_w' and 'beta(w)' must be the same"); } break; default: - OOFEM_WARNING("Shear stiffness reduction type number %d is unknown", softType); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_ConcreteFCM_shearType, "Shear stiffness reduction typ is unknown"); } @@ -223,31 +200,25 @@ ConcreteFCM :: initializeFrom(InputRecord *ir) break; + case 3: + shearStrengthType = SHS_Residual_Ft; + break; + default: - OOFEM_WARNING("Shear stiffness reduction type number %d is unknown", softType); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_ConcreteFCM_shearStrengthType, "Shear stiffness reduction type is unknown"); } - - return IRRT_OK; } double -ConcreteFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) +ConcreteFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep, int i) // // returns current cracking modulus according to crackStrain for i-th // crackplane // { ConcreteFCMStatus *status = static_cast< ConcreteFCMStatus * >( this->giveStatus(gp) ); - - double Cf = 0.; - double ef, emax, c1, c2, Le, Ncr, w; - - double Ft = this->giveTensileStrength(gp); - double Gf = this->giveFractureEnergy(gp); - double ec = status->giveTempCrackStrain(i); - double E = this->computeOverallElasticStiffness(); + double E = this->computeOverallElasticStiffness(gp, tStep); if ( status->giveTempCrackStatus(i) == pscm_NONE ) { return E * fcm_BIGNUMBER; @@ -258,6 +229,27 @@ ConcreteFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) return E * fcm_BIGNUMBER; } + return giveCrackingModulusInTension(rMode, gp, tStep, i); + +} + + +double +ConcreteFCM :: giveCrackingModulusInTension(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep, int i) +{ + + ConcreteFCMStatus *status = static_cast< ConcreteFCMStatus * >( this->giveStatus(gp) ); + + double Cf = 0.; + double ef, emax, c1, c2, Le, Ncr, w; + + double ft = this->giveTensileStrength(gp, tStep); + double Gf = this->giveFractureEnergy(gp, tStep); + double ec = status->giveTempCrackStrain(i); + double E = this->computeOverallElasticStiffness(gp, tStep); + + + emax = max(status->giveMaxCrackStrain(i), ec); Le = status->giveCharLength(i); @@ -273,54 +265,54 @@ ConcreteFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) if ( softType == ST_NONE ) { OOFEM_ERROR("For unknown reason the tensile strength has been exceeded and cracking has been initiated!"); } else if ( softType == ST_Exponential ) { - ef = Gf / ( Ft * Le ); + ef = Gf / ( ft * Le ); if ( emax == 0. ) { // just initiated and closing crack - Cf = -Ft / ef; + Cf = -ft / ef; } else { // further softening - negative stiffness - Cf = -Ft / ef *exp(-ec / ef); + Cf = -ft / ef *exp(-ec / ef); } } else if ( softType == ST_Linear ) { // fracturing strain at zero traction - ef = 2. * Gf / ( Ft * Le ); + ef = 2. * Gf / ( ft * Le ); if ( ( ec >= ef ) || ( emax >= ef ) ) { // fully open crack - no stiffness Cf = 0.; } else { // further softening - negative stiffness - Cf = -Ft / ef; + Cf = -ft / ef; } } else if ( softType == ST_Hordijk ) { c1 = 3.; c2 = 6.93; - ef = 5.14 * Gf / Ft / Le; + ef = 5.14 * Gf / ft / Le; if ( ( ec >= ef ) || ( emax >= ef ) ) { Cf = 0.; } else if ( emax == 0. ) { // just initiated and closing crack - Cf = Ft * ( -c2 / ef - ( exp(-c2) * ( c1 * c1 * c1 + 1. ) ) / ef ); + Cf = ft * ( -c2 / ef - ( exp(-c2) * ( c1 * c1 * c1 + 1. ) ) / ef ); } else { // further softening - negative stiffness - Cf = Ft * ( ( 3. * c1 * c1 * c1 * ec * ec * exp(-( c2 * ec ) / ef) ) / ( ef * ef * ef ) - ( c2 * exp(-( c2 * ec ) / ef) * ( c1 * c1 * c1 * ec * ec * ec + ef * ef * ef ) ) / ( ef * ef * ef * ef ) - ( exp(-c2) * ( c1 * c1 * c1 + 1. ) ) / ef ); + Cf = ft * ( ( 3. * c1 * c1 * c1 * ec * ec * exp(-( c2 * ec ) / ef) ) / ( ef * ef * ef ) - ( c2 * exp(-( c2 * ec ) / ef) * ( c1 * c1 * c1 * ec * ec * ec + ef * ef * ef ) ) / ( ef * ef * ef * ef ) - ( exp(-c2) * ( c1 * c1 * c1 + 1. ) ) / ef ); } } else if ( softType == ST_UserDefinedCrack ) { w = ec * Le; - if ( w > soft_w.at(soft_w.giveSize() ) ) { + if ( w > soft_w.at(soft_w.giveSize() ) ) { Cf = 0.; #ifdef DEBUG OOFEM_WARNING("Crack width is larger than the last user-defined value in the traction-opening law."); #endif } else if ( emax == 0. ) { - Cf = this->Ft * ( soft_function_w.at(2) - soft_function_w.at(1) ) / ( ( soft_w.at(2) - soft_w.at(1) ) / Le ); + Cf = ft * ( soft_function_w.at(2) - soft_function_w.at(1) ) / ( ( soft_w.at(2) - soft_w.at(1) ) / Le ); } else { // softening for ( int i = 1; i <= soft_w.giveSize(); i++ ) { if ( ( w - soft_w.at(i) ) < fcm_SMALL_STRAIN ) { if ( i == 1 ) { - Cf = this->Ft * ( soft_function_w.at(2) - soft_function_w.at(1) ) / ( ( soft_w.at(2) - soft_w.at(1) ) / Le ); + Cf = ft * ( soft_function_w.at(2) - soft_function_w.at(1) ) / ( ( soft_w.at(2) - soft_w.at(1) ) / Le ); break; } else { - Cf = this->Ft * ( soft_function_w.at(i) - soft_function_w.at(i - 1) ) / ( ( soft_w.at(i) - soft_w.at(i - 1) ) / Le ); + Cf = ft * ( soft_function_w.at(i) - soft_function_w.at(i - 1) ) / ( ( soft_w.at(i) - soft_w.at(i - 1) ) / Le ); break; } } @@ -334,21 +326,22 @@ ConcreteFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) Cf = this->H; } } else if ( softType == ST_UserDefinedStrain ) { + if ( ec > soft_eps.at(soft_eps.giveSize() ) ) { Cf = 0.; #ifdef DEBUG OOFEM_WARNING("Crack strain is larger than the last user-defined value in the stress-crack-strain law."); #endif } else if ( emax == 0. ) { - Cf = this->Ft * ( soft_function_eps.at(2) - soft_function_eps.at(1) ) / ( soft_eps.at(2) - soft_eps.at(1) ); + Cf = ft * ( soft_function_eps.at(2) - soft_function_eps.at(1) ) / ( soft_eps.at(2) - soft_eps.at(1) ); } else { // softening for ( int i = 1; i <= soft_eps.giveSize(); i++ ) { if ( ( ec - soft_eps.at(i) ) < fcm_SMALL_STRAIN ) { if ( i == 1 ) { - Cf = this->Ft * ( soft_function_eps.at(2) - soft_function_eps.at(1) ) / ( soft_eps.at(2) - soft_eps.at(1) ); + Cf = ft * ( soft_function_eps.at(2) - soft_function_eps.at(1) ) / ( soft_eps.at(2) - soft_eps.at(1) ); break; } else { - Cf = this->Ft * ( soft_function_eps.at(i) - soft_function_eps.at(i - 1) ) / ( soft_eps.at(i) - soft_eps.at(i - 1) ); + Cf = ft * ( soft_function_eps.at(i) - soft_function_eps.at(i - 1) ) / ( soft_eps.at(i) - soft_eps.at(i - 1) ); break; } } @@ -362,7 +355,7 @@ ConcreteFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) return E * fcm_BIGNUMBER; } - Cf = ConcreteFCM :: giveNormalCrackingStress(gp, emax * Ncr, i); // gets stress + Cf = ConcreteFCM :: giveNormalCrackingStress(gp, tStep, emax * Ncr, i); // gets stress Cf /= ( emax ); // converted into stiffness } @@ -370,8 +363,9 @@ ConcreteFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) return Cf / Ncr; } + double -ConcreteFCM :: giveNormalCrackingStress(GaussPoint *gp, double ec, int i) +ConcreteFCM :: giveNormalCrackingStress(GaussPoint *gp, TimeStep *tStep, double ec, int i) // // returns receivers Normal Stress in crack i for given cracking strain // @@ -380,11 +374,11 @@ ConcreteFCM :: giveNormalCrackingStress(GaussPoint *gp, double ec, int i) double traction; double Le, ef, emax, w, E, c1, c2; - double Gf = this->giveFractureEnergy(gp); - double Ft = this->giveTensileStrength(gp); + double Gf = this->giveFractureEnergy(gp, tStep); + double ft = this->giveTensileStrength(gp, tStep); if ( status->giveTempCrackStatus(i) == pscm_CLOSED ) { - E = this->computeOverallElasticStiffness(); + E = this->computeOverallElasticStiffness(gp, tStep); return E * ec; } @@ -399,68 +393,66 @@ ConcreteFCM :: giveNormalCrackingStress(GaussPoint *gp, double ec, int i) if ( softType == ST_NONE ) { OOFEM_ERROR("For unknown reason the tensile strength has been exceeded and cracking has been initiated!"); } else if ( softType == ST_Exponential ) { - ef = Gf / ( Ft * Le ); + ef = Gf / ( ft * Le ); if ( ec >= emax ) { // further softening - traction = Ft * exp(-ec / ef); + traction = ft * exp(-ec / ef); } else { // crack closing // or unloading or reloading regime - traction = Ft * ec / emax *exp(-emax / ef); + traction = ft * ec / emax *exp(-emax / ef); } } else if ( softType == ST_Linear ) { // fracturing strain at zero traction - ef = 2. * Gf / ( Ft * Le ); + ef = 2. * Gf / ( ft * Le ); if ( ( ec >= ef ) || ( emax >= ef ) ) { // fully open crack - no stiffness traction = 0.; } else if ( ec >= emax ) { // further softening - traction = Ft - Ft * ec / ef; + traction = ft - ft * ec / ef; } else if ( ec <= 0. ) { traction = 0.; } else { - traction = Ft * ec * ( ef - emax ) / ( emax * ef ); + traction = ft * ec * ( ef - emax ) / ( emax * ef ); } } else if ( softType == ST_Hordijk ) { c1 = 3.; c2 = 6.93; - ef = 5.14 * Gf / Ft / Le; + ef = 5.14 * Gf / ft / Le; if ( ( ec >= ef ) || ( emax >= ef ) ) { // fully open crack - no stiffness traction = 0.; } else if ( ec >= emax ) { // further softening - traction = Ft * ( ( 1. + pow( ( c1 * ec / ef ), 3. ) ) * exp(-c2 * ec / ef) - ec / ef * ( 1. + c1 * c1 * c1 ) * exp(-c2) ); + traction = ft * ( ( 1. + pow( ( c1 * ec / ef ), 3. ) ) * exp(-c2 * ec / ef) - ec / ef * ( 1. + c1 * c1 * c1 ) * exp(-c2) ); } else if ( ec <= 0. ) { traction = 0.; } else { - traction = Ft * ec / emax * ( ( 1. + pow( ( c1 * emax / ef ), 3. ) ) * exp(-c2 * emax / ef) - emax / ef * ( 1. + c1 * c1 * c1 ) * exp(-c2) ); + traction = ft * ec / emax * ( ( 1. + pow( ( c1 * emax / ef ), 3. ) ) * exp(-c2 * emax / ef) - emax / ef * ( 1. + c1 * c1 * c1 ) * exp(-c2) ); } } else if ( softType == ST_UserDefinedCrack ) { w = ec * Le; traction = 0.; - - if ( w > soft_w.at(soft_w.giveSize() ) ) { - traction = 0.; - + + if ( w > soft_w.at(soft_w.giveSize() ) ) { + traction = 0.; #ifdef DEBUG OOFEM_WARNING("Crack width is larger than the last user-defined value in the traction-opening law."); -#endif - +#endif } else if ( ec >= emax ) { // softening for ( int i = 1; i <= soft_w.giveSize(); i++ ) { if ( ( w - soft_w.at(i) ) < fcm_SMALL_STRAIN ) { if ( i == 1 ) { // eps \approx 0 bound - traction = soft_function_w.at(i) * this->Ft; + traction = soft_function_w.at(i) * ft; break; } else { traction = soft_function_w.at(i - 1) + ( soft_function_w.at(i) - soft_function_w.at(i - 1) ) / ( soft_w.at(i) - soft_w.at(i - 1) ) * ( w - soft_w.at(i - 1) ); - traction *= this->Ft; + traction *= ft; break; } } @@ -473,11 +465,11 @@ ConcreteFCM :: giveNormalCrackingStress(GaussPoint *gp, double ec, int i) for ( int i = 1; i <= soft_w.giveSize(); i++ ) { if ( ( w - soft_w.at(i) ) < fcm_SMALL_STRAIN ) { if ( i == 1 ) { // eps \approx 0 - traction = soft_function_w.at(i) * this->Ft * ec / emax; + traction = soft_function_w.at(i) * ft * ec / emax; break; } else { traction = soft_function_w.at(i - 1) + ( soft_function_w.at(i) - soft_function_w.at(i - 1) ) / ( soft_w.at(i) - soft_w.at(i - 1) ) * ( w - soft_w.at(i - 1) ); - traction *= this->Ft * ec / emax; + traction *= ft * ec / emax; break; } } @@ -487,29 +479,32 @@ ConcreteFCM :: giveNormalCrackingStress(GaussPoint *gp, double ec, int i) if ( ( ec >= this->eps_f ) || ( emax >= this->eps_f ) ) { traction = 0.; } else if ( emax == 0. ) { - traction = this->Ft; + traction = ft; } else { // unloading or reloading regime // emax * Le = crack width // traction = ( this->Ft + emax * Le * this->H ) * ec / emax; // written in terms of strain and not crack width - traction = ( this->Ft + emax * this->H ) * ec / emax; + traction = ( ft + emax * this->H ) * ec / emax; } } else if ( softType == ST_UserDefinedStrain ) { - if ( emax > soft_eps.at(soft_eps.giveSize() ) ) { - traction = 0.; + + traction = 0.; + + if ( emax > soft_eps.at(soft_eps.giveSize() ) ) { + traction = 0.; #ifdef DEBUG - OOFEM_WARNING("Cracking strain is larger than the last user-defined value in the traction-cracking-strain law."); + OOFEM_WARNING("Cracking strain is larger than the last user-defined value in the traction-cracking-strain law."); #endif - } else if ( ec >= emax ) { // softening - for ( int i = 1; i <= soft_eps.giveSize(); i++ ) { + } else if ( ec >= emax ) { // softening + for ( int i = 1; i <= soft_eps.giveSize(); i++ ) { if ( ( ec - soft_eps.at(i) ) < fcm_SMALL_STRAIN ) { - if ( i == 1 ) { // eps \approx 0 bound - traction = soft_function_eps.at(i) * this->Ft; - break; - } else { + if ( i == 1 ) { // eps \approx 0 bound + traction = soft_function_eps.at(i) * ft; + break; + } else { traction = soft_function_eps.at(i - 1) + ( soft_function_eps.at(i) - soft_function_eps.at(i - 1) ) / ( soft_eps.at(i) - soft_eps.at(i - 1) ) * ( ec - soft_eps.at(i - 1) ); - traction *= this->Ft; + traction *= ft; break; } } @@ -520,11 +515,11 @@ ConcreteFCM :: giveNormalCrackingStress(GaussPoint *gp, double ec, int i) for ( int i = 1; i <= soft_eps.giveSize(); i++ ) { if ( ( emax - soft_eps.at(i) ) < fcm_SMALL_STRAIN ) { if ( i == 1 ) { // eps \approx 0 - traction = soft_function_eps.at(i) * this->Ft * ec / emax; + traction = soft_function_eps.at(i) * ft * ec / emax; break; } else { traction = soft_function_eps.at(i - 1) + ( soft_function_eps.at(i) - soft_function_eps.at(i - 1) ) / ( soft_eps.at(i) - soft_eps.at(i - 1) ) * ( emax - soft_eps.at(i - 1) ); - traction *= this->Ft * ec / emax; + traction *= ft * ec / emax; break; } } @@ -538,13 +533,13 @@ ConcreteFCM :: giveNormalCrackingStress(GaussPoint *gp, double ec, int i) } double -ConcreteFCM :: computeEffectiveShearModulus(GaussPoint *gp, int shearDirection) +ConcreteFCM :: computeEffectiveShearModulus(GaussPoint *gp, TimeStep *tStep, int shearDirection) { double G, Geff, D2tot, N; int crackA, crackB; - G = this->computeOverallElasticShearModulus(); + G = this->computeOverallElasticShearModulus(gp, tStep); if ( this->isIntactForShear(gp, shearDirection) ) { Geff = G; @@ -576,12 +571,12 @@ ConcreteFCM :: computeEffectiveShearModulus(GaussPoint *gp, int shearDirection) Geff = G * this->beta / ( N - this->beta * ( N - 1 ) ); // for N = 1... Geff = G * beta } else if ( this->shearType == SHR_Const_ShearFactorCoeff ) { // contributions from shear terms in: De - De (De + Dcr)^-1 De - D2tot = this->computeTotalD2Modulus(gp, shearDirection); + D2tot = this->computeNumerD2Modulus(gp, tStep, shearDirection); // number of parallel cracks already taken into account Geff = G * D2tot / ( G + D2tot ); } else if ( this->shearType == SHR_UserDefined_ShearRetFactor ) { // contributions from shear terms in: De - De (De + Dcr)^-1 De - D2tot = this->computeTotalD2Modulus(gp, shearDirection); + D2tot = this->computeNumerD2Modulus(gp, tStep, shearDirection); // number of parallel cracks already taken into account Geff = G * D2tot / ( G + D2tot ); } else { @@ -595,7 +590,7 @@ ConcreteFCM :: computeEffectiveShearModulus(GaussPoint *gp, int shearDirection) double -ConcreteFCM :: computeD2ModulusForCrack(GaussPoint *gp, int icrack) +ConcreteFCM :: computeD2ModulusForCrack(GaussPoint *gp, TimeStep *tStep, int icrack) { double D2, N, G, E, w, beta_m; @@ -606,24 +601,24 @@ ConcreteFCM :: computeD2ModulusForCrack(GaussPoint *gp, int icrack) N = this->giveNumberOfCracksInDirection(gp, icrack); if ( this->isIntact(gp, icrack) || ( this->shearType == SHR_NONE ) ) { - E = this->computeOverallElasticStiffness(); + E = this->computeOverallElasticStiffness(gp, tStep); D2 = E * fcm_BIGNUMBER; } else { if ( shearType == SHR_Const_ShearRetFactor ) { - G = this->computeOverallElasticShearModulus(); + G = this->computeOverallElasticShearModulus(gp, tStep); D2 = G * this->beta / ( 1. - this->beta ); D2 /= N; } else if ( shearType == SHR_Const_ShearFactorCoeff ) { // for the number of parallel cracks is taken care of in "giveCrackingModulus" // however, it is essential to reduce the final modulus due to the presence of multiple cracks - D2 = this->sf * this->giveCrackingModulus(SecantStiffness, gp, icrack); + D2 = this->sf * ConcreteFCM::giveCrackingModulusInTension(SecantStiffness, gp, tStep, icrack); D2 /= N; } else if ( this->shearType == SHR_UserDefined_ShearRetFactor ) { // for the number of parallel cracks is taken care of in the evaluation of normalcrackopening // however, it is essential to reduce the final modulus due to the presence of multiple cracks - G = this->computeOverallElasticShearModulus(); - w = max( this->computeNormalCrackOpening(gp, icrack), this->computeMaxNormalCrackOpening(gp, icrack) ); + G = this->computeOverallElasticShearModulus(gp, tStep); + w = max( this->computeNormalCrackOpening(gp, icrack), this->computeMaxNormalCrackOpening(gp, tStep, icrack) ); /// shear retention factor = beta(w) @@ -653,35 +648,73 @@ ConcreteFCM :: computeD2ModulusForCrack(GaussPoint *gp, int icrack) } } + + return D2; } + +double +ConcreteFCM :: computeNumerD2ModulusForCrack(GaussPoint *gp, TimeStep *tStep, int icrack) +{ + double D2, N, E; + + if ( icrack >= 4 ) { + OOFEM_ERROR("Unexpected crack number"); + } + + N = this->giveNumberOfCracksInDirection(gp, icrack); + + if ( this->isIntact(gp, icrack) || ( this->shearType == SHR_NONE ) ) { + E = this->computeOverallElasticStiffness(gp, tStep); + D2 = E * fcm_BIGNUMBER; + } else { + if ( shearType == SHR_Const_ShearRetFactor ) { + D2 = ConcreteFCM :: computeD2ModulusForCrack(gp, tStep, icrack); + } else if ( shearType == SHR_Const_ShearFactorCoeff ) { + // for the number of parallel cracks is taken care of in "giveCrackingModulus" + // however, it is essential to reduce the final modulus due to the presence of multiple cracks + D2 = this->sf_numer * ConcreteFCM::giveCrackingModulusInTension(SecantStiffness, gp, tStep, icrack); + D2 /= N; + } else if ( this->shearType == SHR_UserDefined_ShearRetFactor ) { + D2 = ConcreteFCM :: computeD2ModulusForCrack(gp, tStep, icrack); + } else { + D2 = 0; + OOFEM_ERROR("Unknown Softening Mode"); + } + } + + return D2; +} + + + void -ConcreteFCM :: checkSnapBack(GaussPoint *gp, int i) +ConcreteFCM :: checkSnapBack(GaussPoint *gp, TimeStep *tStep, int i) { ConcreteFCMStatus *status = static_cast< ConcreteFCMStatus * >( this->giveStatus(gp) ); - double E, Gf, Ft, Le; + double E, Gf, ft, Le; double ef = 0.; double slope; double efail, c1, c2; Le = status->giveCharLength(i); - Gf = this->giveFractureEnergy(gp); - Ft = this->giveTensileStrength(gp); + Gf = this->giveFractureEnergy(gp, tStep); + ft = this->giveTensileStrength(gp, tStep); - E = this->computeOverallElasticStiffness(); + E = this->computeOverallElasticStiffness(gp, tStep); if ( softType == ST_NONE ) { OOFEM_ERROR("For unknown reason the tensile strength has been exceeded and cracking has been initiated!"); } else if ( softType == ST_Exponential ) { - ef = Gf / ( Ft * Le ); + ef = Gf / ( ft * Le ); } else if ( softType == ST_Linear ) { - ef = 2. * Gf / ( Ft * Le ); + ef = 2. * Gf / ( ft * Le ); } else if ( softType == ST_Hordijk ) { - efail = 5.14 * Gf / Ft / Le; + efail = 5.14 * Gf / ft / Le; c1 = 3.; c2 = 6.93; // ef = ft / slope of the softening branch at the peak stress @@ -710,25 +743,25 @@ ConcreteFCM :: checkSnapBack(GaussPoint *gp, int i) OOFEM_ERROR("Unknown Softening Mode"); } - if ( ef <= Ft / E ) { - OOFEM_ERROR("ef %e < e0 %e, this leads to material snapback in element %d, characteristic length %f", ef, Ft / E, gp->giveElement()->giveNumber(), Le); + if ( ef <= ft / E ) { + OOFEM_WARNING("ef %e < e0 %e, this leads to material snapback in element %d, characteristic length %f (E=%e, ft=%e)", ef, ft / E, gp->giveElement()->giveGlobalNumber(), Le, E, ft); } } double -ConcreteFCM :: maxShearStress(GaussPoint *gp, int i) { +ConcreteFCM :: maxShearStress(GaussPoint *gp, TimeStep *tStep, int i) { int dir_1, dir_2; double maxTau, crackOpening, wmax, scale; if ( this->isIntactForShear(gp, i) ) { - return Ft * fcm_BIGNUMBER; + return this->giveTensileStrength(gp, tStep) * fcm_BIGNUMBER; } if ( this->shearStrengthType == SHS_NONE ) { - maxTau = Ft * fcm_BIGNUMBER; + maxTau = this->giveTensileStrength(gp, tStep) * fcm_BIGNUMBER; } else if ( this->shearStrengthType == SHS_Const_Ft ) { - maxTau = Ft; + maxTau = this->giveTensileStrength(gp, tStep); } else if ( this->shearStrengthType == SHS_Collins_Interlock ) { if ( i == 4 ) { // y-z dir_1 = 2; @@ -748,12 +781,16 @@ ConcreteFCM :: maxShearStress(GaussPoint *gp, int i) { crackOpening = max( this->computeNormalCrackOpening(gp, dir_1), this->computeNormalCrackOpening(gp, dir_2) ); // from the entire history - wmax = max( this->computeMaxNormalCrackOpening(gp, dir_1), this->computeMaxNormalCrackOpening(gp, dir_2) ); + wmax = max( this->computeMaxNormalCrackOpening(gp, tStep, dir_1), this->computeMaxNormalCrackOpening(gp, tStep, dir_2) ); crackOpening = max(wmax, crackOpening); scale = 1000. / lengthScale; maxTau = 0.18 * sqrt(this->fc) / ( 0.31 + 24. * crackOpening * scale / ( this->ag * scale + 16. ) ); + + } else if ( this->shearStrengthType == SHS_Residual_Ft ) { + maxTau = this->computeResidualTensileStrength(gp, tStep); + } else { OOFEM_ERROR("Unexpected shearStrengthType"); maxTau = 0.; // happy compiler @@ -762,10 +799,40 @@ ConcreteFCM :: maxShearStress(GaussPoint *gp, int i) { return maxTau; } +double +ConcreteFCM :: computeResidualTensileStrength(GaussPoint *gp, TimeStep *tStep) { + + ConcreteFCMStatus *status = static_cast< ConcreteFCMStatus * >( this->giveStatus(gp) ); + + double sigma; + int nCracks; + double emax; + + nCracks = status->giveNumberOfTempCracks(); + + sigma = this->giveTensileStrength(gp, tStep); + + for ( int i = 1; i <= nCracks; i++ ) { + + emax = status->giveMaxCrackStrain(i); + + if (emax > 0.) { + emax /= this->giveNumberOfCracksInDirection(gp, i); + + sigma = ConcreteFCM :: giveNormalCrackingStress(gp, tStep, emax, i); + sigma = min( sigma, this->giveTensileStrength(gp, tStep) ); + } + } + + return sigma; +} + double -ConcreteFCM :: give(int aProperty, GaussPoint *gp) +ConcreteFCM :: give(int aProperty, GaussPoint *gp) const { + this->giveStatus(gp); + double answer; if ( RandomMaterialExtensionInterface :: give(aProperty, gp, answer) ) { return answer; @@ -778,24 +845,39 @@ ConcreteFCM :: give(int aProperty, GaussPoint *gp) } } + int ConcreteFCM :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { + + if ( type == IST_TensileStrength ) { + answer.resize(1); + answer.at(1) = this->giveTensileStrength(gp, tStep); + return 1.; + + } else if ( type == IST_ResidualTensileStrength ) { + + answer.resize(1); + answer.zero(); + answer.at(1) = this->computeResidualTensileStrength(gp, tStep); + + return 1; + } + return FCMMaterial :: giveIPValue(answer, gp, type, tStep); } - MaterialStatus * ConcreteFCM :: giveStatus(GaussPoint *gp) const { MaterialStatus *status = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); - if ( status == NULL ) { + if ( status == nullptr ) { // create a new one status = this->CreateStatus(gp); - if ( status != NULL ) { - gp->setMaterialStatus( status, this->giveNumber() ); + if ( status ) { + gp->setMaterialStatus( status ); this->_generateStatusVariables(gp); } } @@ -806,23 +888,18 @@ ConcreteFCM :: giveStatus(GaussPoint *gp) const - /////////////////////////////////////////////////////////////////// // CONCRETE FCM STATUS /// /////////////////////////////////////////////////////////////////// -ConcreteFCMStatus :: ConcreteFCMStatus(int n, Domain *d, GaussPoint *gp) : - FCMMaterialStatus(n, d, gp), RandomMaterialStatusExtensionInterface() +ConcreteFCMStatus :: ConcreteFCMStatus(GaussPoint *gp) : + FCMMaterialStatus(gp), RandomMaterialStatusExtensionInterface() {} -ConcreteFCMStatus :: ~ConcreteFCMStatus() -{ } - - void -ConcreteFCMStatus :: printOutputAt(FILE *file, TimeStep *tStep) +ConcreteFCMStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { FCMMaterialStatus :: printOutputAt(file, tStep); } @@ -841,7 +918,6 @@ ConcreteFCMStatus :: initTempStatus() } - void ConcreteFCMStatus :: updateYourself(TimeStep *tStep) // @@ -859,42 +935,22 @@ ConcreteFCMStatus :: giveInterface(InterfaceType type) if ( type == RandomMaterialStatusExtensionInterfaceType ) { return static_cast< RandomMaterialStatusExtensionInterface * >(this); } else { - return NULL; + return nullptr; } } - -contextIOResultType -ConcreteFCMStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +ConcreteFCMStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = FCMMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + FCMMaterialStatus :: saveContext(stream, mode); } -contextIOResultType -ConcreteFCMStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// -{ - contextIOResultType iores; - - // read parent class status - if ( ( iores = FCMMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - return CIO_OK; // return succes +void +ConcreteFCMStatus :: restoreContext(DataStream &stream, ContextMode mode) +{ + FCMMaterialStatus :: restoreContext(stream, mode); } + } // end namespace oofem diff --git a/src/sm/Materials/ConcreteMaterials/concretefcm.h b/src/sm/Materials/ConcreteMaterials/concretefcm.h index c490c8209..80641ca11 100644 --- a/src/sm/Materials/ConcreteMaterials/concretefcm.h +++ b/src/sm/Materials/ConcreteMaterials/concretefcm.h @@ -35,7 +35,7 @@ #ifndef concretefcm_h #define concretefcm_h -#include "../fcm.h" +#include "sm/Materials/fcm.h" #include "randommaterialext.h" ///@name Input fields for ConcreteFCM @@ -48,6 +48,7 @@ #define _IFT_ConcreteFCM_ft "ft" #define _IFT_ConcreteFCM_beta "beta" #define _IFT_ConcreteFCM_sf "sf" +#define _IFT_ConcreteFCM_sf_numer "sf_numer" #define _IFT_ConcreteFCM_fc "fc" #define _IFT_ConcreteFCM_ag "ag" #define _IFT_ConcreteFCM_lengthScale "lengthscale" @@ -68,24 +69,20 @@ namespace oofem { class ConcreteFCMStatus : public FCMMaterialStatus, public RandomMaterialStatusExtensionInterface { public: - ConcreteFCMStatus(int n, Domain *d, GaussPoint *g); - virtual ~ConcreteFCMStatus(); - /// Writes information into the output file. - virtual void printOutputAt(FILE *file, TimeStep *tStep); + ConcreteFCMStatus(GaussPoint *g); - // definition - virtual const char *giveClassName() const { return "ConcreteFCMStatus"; } + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + const char *giveClassName() const override { return "ConcreteFCMStatus"; } - virtual Interface *giveInterface(InterfaceType it); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - // saves current context(state) into stream - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); -}; + Interface *giveInterface(InterfaceType it) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; +}; /** @@ -99,43 +96,38 @@ class ConcreteFCM : public FCMMaterial, public RandomMaterialExtensionInterface { public: ConcreteFCM(int n, Domain *d); - virtual ~ConcreteFCM() { - delete linearElasticMaterial; - } - - // identification and auxiliary functions - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int hasNonLinearBehaviour() { return 1; } - virtual const char *giveClassName() const { return "ConcreteFCM"; } - virtual const char *giveInputRecordName() const { return _IFT_ConcreteFCM_Name; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new ConcreteFCMStatus(1, domain, gp); } + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "ConcreteFCM"; } + const char *giveInputRecordName() const override { return _IFT_ConcreteFCM_Name; } - virtual double give(int aProperty, GaussPoint *gp); + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new ConcreteFCMStatus(gp); } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + double give(int aProperty, GaussPoint *gp) const override; - virtual MaterialStatus *giveStatus(GaussPoint *gp) const; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + MaterialStatus *giveStatus(GaussPoint *gp) const override; protected: - /// Fracture energy - double Gf; - /// Tensile strenght - double Ft; + double Gf = 0.; + /// Tensile strength + double Ft = 0.; /// shear retention factor - double beta; + double beta = 0.; /// shear factor - double sf; + double sf = 0.; + /// shear factor for numerical purpose + double sf_numer = 0.; // 3 parameters for collins aggregate interlock: /// Collins' aggregate interlock: compressive strength in MPa - double fc; + double fc = 0.; /// Collins' aggregate interlock: aggregate diameter in appropriate units (same as FE mesh) - double ag; + double ag = 0.; /// Collins' aggregate interlock: 1 for meter, 1000 for analysis in mm - double lengthScale; + double lengthScale = 0.; /// user-defined softening (traction-COD) FloatArray soft_w, soft_function_w; @@ -145,33 +137,24 @@ class ConcreteFCM : public FCMMaterial, public RandomMaterialExtensionInterface FloatArray beta_w, beta_function; /// hardening modulus - double H; + double H = 0.; /// strain at failure - double eps_f; - - /// returns tensile strength (can be random) - virtual double giveTensileStrength(GaussPoint *gp) { return this->give(ft_strength, gp); } - - /// returns fracture energy (can be random) - virtual double giveFractureEnergy(GaussPoint *gp) { return this->give(gf_ID, gp); } - - /// returns stiffness in the normal direction of the i-th crack - virtual double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i); - - /// returns Geff which is necessary in the global stiffness matrix - virtual double computeEffectiveShearModulus(GaussPoint *gp, int i); - - /// shear modulus for a given crack plane (1, 2, 3) - virtual double computeD2ModulusForCrack(GaussPoint *gp, int icrack); + double eps_f = 0.; - /// computes normal stress associated with i-th crack direction - virtual double giveNormalCrackingStress(GaussPoint *gp, double eps_cr, int i); + double giveTensileStrength(GaussPoint *gp, TimeStep *tStep) override { return this->give(ft_strength, gp); } + virtual double giveFractureEnergy(GaussPoint *gp, TimeStep *tStep) { return this->give(gf_ID, gp); } + double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep, int i) override; + double giveCrackingModulusInTension(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep, int i) override; + double computeEffectiveShearModulus(GaussPoint *gp, TimeStep *tStep, int i) override; + double computeD2ModulusForCrack(GaussPoint *gp, TimeStep *tStep, int icrack) override; + double computeNumerD2ModulusForCrack(GaussPoint *gp, TimeStep *tStep, int icrack) override; + double giveNormalCrackingStress(GaussPoint *gp, TimeStep *tStep, double eps_cr, int i) override; + double maxShearStress(GaussPoint *gp, TimeStep *tStep, int i) override; - /// computes the maximum value of the shear stress; if the shear stress exceeds this value, it is cropped - virtual double maxShearStress(GaussPoint *gp, int i); + /// based on the maximum crack opening evaluates the residual strength + virtual double computeResidualTensileStrength(GaussPoint *gp, TimeStep *tStep); - /// checks possible snap-back - virtual void checkSnapBack(GaussPoint *gp, int crack); + void checkSnapBack(GaussPoint *gp, TimeStep *tStep, int crack) override; /// type of post-peak behavior in the normal direction to the crack plane enum SofteningType { ST_NONE, ST_Exponential, ST_Linear, ST_Hordijk, ST_UserDefinedCrack, ST_LinearHardeningStrain, ST_UserDefinedStrain, ST_Unknown }; @@ -179,11 +162,11 @@ class ConcreteFCM : public FCMMaterial, public RandomMaterialExtensionInterface /// type of reduction of the shear stiffness caused by cracking enum ShearRetentionType { SHR_NONE, SHR_Const_ShearRetFactor, SHR_Const_ShearFactorCoeff, SHR_UserDefined_ShearRetFactor, SHR_Unknown }; - ShearRetentionType shearType; + ShearRetentionType shearType = SHR_Unknown; /// defines the maximum value of shear stress - enum ShearStrengthType { SHS_NONE, SHS_Const_Ft, SHS_Collins_Interlock, SHS_Unknown }; - ShearStrengthType shearStrengthType; + enum ShearStrengthType { SHS_NONE, SHS_Const_Ft, SHS_Collins_Interlock, SHS_Residual_Ft, SHS_Unknown }; + ShearStrengthType shearStrengthType = SHS_Unknown; }; } // end namespace oofem #endif // concretefcm_h diff --git a/src/sm/Materials/ConcreteMaterials/concretefcmviscoelastic.C b/src/sm/Materials/ConcreteMaterials/concretefcmviscoelastic.C new file mode 100644 index 000000000..6c75fb5f1 --- /dev/null +++ b/src/sm/Materials/ConcreteMaterials/concretefcmviscoelastic.C @@ -0,0 +1,470 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2015 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "concretefcmviscoelastic.h" +#include "gausspoint.h" +#include "mathfem.h" +#include "classfactory.h" +#include "contextioerr.h" +#include "../RheoChainMaterials/rheoChM.h" + +namespace oofem { +REGISTER_Material(ConcreteFCMViscoElastic); + +ConcreteFCMViscoElastic::ConcreteFCMViscoElastic(int n, Domain *d) : ConcreteFCM(n, d) +{} + + +void +ConcreteFCMViscoElastic::initializeFrom(InputRecord &ir) +{ + ConcreteFCM::initializeFrom(ir); + + IR_GIVE_FIELD(ir, viscoMat, _IFT_ConcreteFCMViscoElastic_viscoMat); + + this->fib = false; + + if ( ir.hasField(_IFT_ConcreteFCMViscoElastic_timedepfracturing) ) { + this->fib = true; + // + IR_GIVE_FIELD(ir, fib_s, _IFT_ConcreteFCMViscoElastic_fib_s); + // the same compressive strength as for the prediction using the B3 formulas + IR_GIVE_FIELD(ir, fib_fcm28, _IFT_ConcreteFCMViscoElastic_fcm28); + + IR_GIVE_FIELD(ir, timeFactor, _IFT_ConcreteFCMViscoElastic_timeFactor); + IR_GIVE_FIELD(ir, stiffnessFactor, _IFT_ConcreteFCMViscoElastic_stiffnessFactor); + + ConcreteFCM::Gf = -1.; + ConcreteFCM::Ft = -1.; + IR_GIVE_OPTIONAL_FIELD(ir, ConcreteFCM::Ft, _IFT_ConcreteFCMViscoElastic_ft28); + IR_GIVE_OPTIONAL_FIELD(ir, ConcreteFCM::Gf, _IFT_ConcreteFCMViscoElastic_gf28); + } + + + if ( propertyDictionary.includes(tAlpha) ) { + if ( propertyDictionary.at(tAlpha) != 0. ) { + OOFEM_ERROR("tAlpha must be set to zero in ConcreteFCMViscoElastic material"); + } + } +} + + +double +ConcreteFCMViscoElastic::give(int aProperty, GaussPoint *gp) const +{ + return ConcreteFCM::give(aProperty, gp); +} + + +void +ConcreteFCMViscoElastic::giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &totalStrain, + TimeStep *tStep) +{ + ConcreteFCMViscoElasticStatus *status = static_cast< ConcreteFCMViscoElasticStatus * >( gp->giveMaterialStatus() ); + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + FloatArray partialStrain; + FloatArray viscoStress; + + FCMMaterial::giveRealStressVector(answer, gp, totalStrain, tStep); + + partialStrain = totalStrain; + + if ( status->giveNumberOfTempCracks() > 0 ) { + FloatArray crackStrain; + FloatMatrix epsL2G = status->giveL2GStrainVectorTransformationMtrx(); + // from local to global + // crackStrain.rotatedWith(epsL2G, 'n'); + crackStrain.beProductOf( epsL2G, status->giveTempCrackStrainVector() ); + partialStrain.subtract(crackStrain); + } + + // viscoStress should be equal to answer - this method is called only for updating + rheoMat->giveRealStressVector(viscoStress, status->giveSlaveGaussPointVisco(), partialStrain, tStep); + + return; +} + +FloatArray +ConcreteFCMViscoElastic::computeStressIndependentStrainVector(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const +{ + // temperature strain is treated ONLY by the rheoMat + + if ( !this->isActivated(tStep) ) { + return FloatArray(); + } + + ConcreteFCMViscoElasticStatus *status = static_cast< ConcreteFCMViscoElasticStatus * >( gp->giveMaterialStatus() ); + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + return rheoMat->computeStressIndependentStrainVector(status->giveSlaveGaussPointVisco(), tStep, mode); +} + + +int +ConcreteFCMViscoElastic::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +{ + ConcreteFCMViscoElasticStatus *status = static_cast< ConcreteFCMViscoElasticStatus * >( gp->giveMaterialStatus() ); + + if ( type == IST_TensileStrength ) { + answer.resize(1); + answer.at(1) = status->giveTensileStrength(); + return 1.; + } else if ( type == IST_ResidualTensileStrength ) { + double sigma; + int nCracks; + double emax; + + nCracks = status->giveNumberOfTempCracks(); + sigma = status->giveTensileStrength(); + + for ( int i = 1; i <= nCracks; i++ ) { + emax = status->giveMaxCrackStrain(i); + + if ( emax > 0. ) { + // normalisation wrt crack number is done inside the function + // emax /= this->giveNumberOfCracksInDirection(gp, i); + + sigma = this->giveNormalCrackingStress(gp, tStep, emax, i); + sigma = min(sigma, this->giveTensileStrength(gp, tStep) ); + } + } + + answer.resize(1); + answer.zero(); + answer.at(1) = sigma; + + return 1; + } else if ( type == IST_CrackIndex ) { + answer.resize(1); + answer.zero(); + + // cracking is initiated + if ( status->giveNumberOfCracks() ) { + answer.at(1) = 1.; + } else { + FloatArray sigma; + FloatArray princStress; + StructuralMaterial::giveFullSymVectorForm( sigma, status->giveStressVector(), gp->giveMaterialMode() ); + this->computePrincipalValues(princStress, sigma, principal_stress); + answer.at(1) = max( 0., princStress.at(1) / status->giveTensileStrength() ); + } + return 1; + } + + // if ( ( type == IST_DryingShrinkageTensor ) || + // ( type == IST_AutogenousShrinkageTensor ) || + // ( type == IST_TotalShrinkageTensor ) || + // ( type == IST_CreepStrainTensor ) || + // ( type == IST_DryingShrinkageTensor ) || + // ( type == IST_ThermalStrainTensor ) ) { + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + if ( rheoMat->giveIPValue(answer, status->giveSlaveGaussPointVisco(), type, tStep) ) { + return 1; + } + + return ConcreteFCM::giveIPValue(answer, gp, type, tStep); +} + + + +MaterialStatus * +ConcreteFCMViscoElastic::giveStatus(GaussPoint *gp) const +{ + MaterialStatus *status = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); + if ( status == NULL ) { + // create a new one + status = this->CreateStatus(gp); + + if ( status != NULL ) { + gp->setMaterialStatus(status); + this->_generateStatusVariables(gp); + } + } + + return status; +} + + +double +ConcreteFCMViscoElastic::giveTensileStrength(GaussPoint *gp, TimeStep *tStep) +{ + // return value + double ftm = 0.; + + ConcreteFCMViscoElasticStatus *status = static_cast< ConcreteFCMViscoElasticStatus * >( gp->giveMaterialStatus() ); + + // check if the fracture properties are constant or time-dependent + if ( fib ) { + // compressive strength + double fcm, fcm28mod; + double equivalentTime; + + // virgin material-> compute! + if ( status->giveNumberOfTempCracks() == 0 ) { + equivalentTime = this->giveEquivalentTime(gp, tStep); + + if ( ConcreteFCM::Ft > 0. ) { // user-specified 28-day strength + fcm28mod = pow(ConcreteFCM::Ft * this->stiffnessFactor / 0.3e6, 3. / 2.) + 8.; + fcm = exp(fib_s * ( 1. - sqrt(28. * this->timeFactor / equivalentTime) ) ) * fcm28mod; + } else { // returns fcm in MPa - formula 5.5-51 + fcm = exp(this->fib_s * ( 1. - sqrt(28. * this->timeFactor / equivalentTime) ) ) * this->fib_fcm28; + } + + // ftm adjusted according to the stiffnessFactor (MPa by default) + if ( fcm >= 58. ) { + ftm = 2.12 * log(1. + 0.1 * fcm) * 1.e6 / this->stiffnessFactor; + } else if ( fcm <= 20. ) { + ftm = 0.07862 * fcm * 1.e6 / this->stiffnessFactor; // 12^(2/3) * 0.3 / 20 = 0.07862 + } else { + ftm = 0.3 * pow(fcm - 8., 2. / 3.) * 1.e6 / this->stiffnessFactor; //5.1-3a + } + + // ftm adjusted according to the stiffnessFactor (MPa by default) + /* if ( fcm >= 20. ) { + * ftm = 0.3 * pow(fcm - 8., 2. / 3.) * 1.e6 / this->stiffnessFactor; //5.1-3a + * } else if ( fcm < 8. ) { + * // upper formula does not hold for concretes with fcm < 8 MPa + * ftm = 0.3 * pow(fcm, 2. / 3.) * 1.e6 / this->stiffnessFactor; + * } else { + * // smooth transition + * ftm = 0.3 * pow(fcm - ( 8. * ( fcm - 8. ) / ( 20. - 8. ) ), 2. / 3.) * 1.e6 / this->stiffnessFactor; + * }*/ + + status->setTensileStrength(ftm); + } else { + ftm = status->giveTensileStrength(); + } + } else { + ftm = ConcreteFCM::giveTensileStrength(gp, tStep); + status->setTensileStrength(ftm); + } + + return ftm; +} + +double +ConcreteFCMViscoElastic::giveFractureEnergy(GaussPoint *gp, TimeStep *tStep) +{ + // return value + double Gf = 0.; + double Gf28; + double ftm, ftm28; + + // check if the fracture properties are constant or time-dependent + if ( fib ) { + ConcreteFCMViscoElasticStatus *status = static_cast< ConcreteFCMViscoElasticStatus * >( gp->giveMaterialStatus() ); + + // virgin material-> compute! + if ( status->giveNumberOfTempCracks() == 0 ) { + // 1) + if ( ConcreteFCM::Gf > 0. ) { + Gf28 = ConcreteFCM::Gf; + } else { + Gf28 = 73. * pow(fib_fcm28, 0.18) / this->stiffnessFactor; + } + + // 2) + ftm = this->giveTensileStrength(gp, tStep); + + if ( ConcreteFCM::Ft > 0. ) { // user-specified 28-day strength + ftm28 = ConcreteFCM::Ft; + } else { + if ( fib_fcm28 >= 58. ) { + ftm28 = 2.12 * log(1. + 0.1 * fib_fcm28) * 1.e6 / this->stiffnessFactor; + } else if ( fib_fcm28 <= 20. ) { + ftm28 = 0.07862 * fib_fcm28 * 1.e6 / this->stiffnessFactor; // 12^(2/3) * 0.3 / 20 = 0.07862 + } else { + ftm28 = 0.3 * pow(fib_fcm28 - 8., 2. / 3.) * 1.e6 / this->stiffnessFactor; //5.1-3a + } + } + + // 3) + Gf = Gf28 * ftm / ftm28; + + status->setFractureEnergy(Gf); + } else { + Gf = status->giveFractureEnergy(); + } + } else { + Gf = ConcreteFCM::giveFractureEnergy(gp, tStep); + } + + return Gf; +} + + +double +ConcreteFCMViscoElastic::computeOverallElasticStiffness(GaussPoint *gp, TimeStep *tStep) { + double stiffness; + + ConcreteFCMViscoElasticStatus *status = static_cast< ConcreteFCMViscoElasticStatus * >( gp->giveMaterialStatus() ); + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + stiffness = rheoMat->giveEModulus(status->giveSlaveGaussPointVisco(), tStep); + + return stiffness; +} + +double +ConcreteFCMViscoElastic::computeOverallElasticShearModulus(GaussPoint *gp, TimeStep *tStep) { + double Evisco; + double Gvisco; + + ConcreteFCMViscoElasticStatus *status = static_cast< ConcreteFCMViscoElasticStatus * >( gp->giveMaterialStatus() ); + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + Evisco = rheoMat->giveEModulus(status->giveSlaveGaussPointVisco(), tStep); + + Gvisco = FCMMaterial::linearElasticMaterial.giveShearModulus() * Evisco / this->give('E', gp); + + return Gvisco; +} + + + +int ConcreteFCMViscoElastic::checkConsistency() +{ + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + MaterialMode helpMM; + helpMM = MaterialMode(_Unknown); + GaussPoint helpGP(NULL, 0, 0., helpMM); + + + if ( rheoMat->givePoissonsRatio() != this->linearElasticMaterial.givePoissonsRatio() ) { + OOFEM_ERROR("The Poisson ratio of the fracturing and viscoelastic material are not equal."); + } + + if ( fabs(this->linearElasticMaterial.give(tAlpha, & helpGP) ) != 0. ) { + OOFEM_ERROR("tAlpha must be set to zero in ConcreteFCMViscoElastic material"); + } + + return FEMComponent::checkConsistency(); +} + +double +ConcreteFCMViscoElastic::giveEquivalentTime(GaussPoint *gp, TimeStep *tStep) +{ + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + ConcreteFCMViscoElasticStatus *status = static_cast< ConcreteFCMViscoElasticStatus * >( gp->giveMaterialStatus() ); + + return rheoMat->giveEquivalentTime(status->giveSlaveGaussPointVisco(), tStep); +} + + + + +/////////////////////////////////////////////////////////////////// +// CONCRETE FCM STATUS /// +/////////////////////////////////////////////////////////////////// + +ConcreteFCMViscoElasticStatus::ConcreteFCMViscoElasticStatus(GaussPoint *gp) : + ConcreteFCMStatus(gp), + slaveGpVisco( std::make_unique< GaussPoint >(gp->giveIntegrationRule(), 0, gp->giveNaturalCoordinates(), 0., gp->giveMaterialMode() ) ) +{} + + +void +ConcreteFCMViscoElasticStatus::printOutputAt(FILE *file, TimeStep *tStep) const +{ + ConcreteFCMStatus::printOutputAt(file, tStep); + + fprintf(file, "remark {Output for slave viscoelastic material}\n"); + this->slaveGpVisco->giveMaterialStatus()->printOutputAt(file, tStep); + fprintf(file, "\n"); +} + + +void +ConcreteFCMViscoElasticStatus::initTempStatus() +// +// initializes temp variables according to variables form previous equlibrium state. +// +{ + ConcreteFCMStatus::initTempStatus(); + + RheoChainMaterialStatus *rheoStatus = static_cast< RheoChainMaterialStatus * >( this->giveSlaveGaussPointVisco()->giveMaterialStatus() ); + + rheoStatus->initTempStatus(); +} + + + +void +ConcreteFCMViscoElasticStatus::updateYourself(TimeStep *tStep) +// +// updates variables (nonTemp variables describing situation at previous equilibrium state) +// after a new equilibrium state has been reached +// temporary variables correspond to newly reched equilibrium. +// +{ + ConcreteFCMStatus::updateYourself(tStep); + + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->updateYourself(tStep); +} + + +void +ConcreteFCMViscoElasticStatus::saveContext(DataStream &stream, ContextMode mode) +// +// saves full information stored in this Status +// no temp variables stored +// +{ + // save cracking status + ConcreteFCMStatus::saveContext(stream, mode); + // save viscoelastic status + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->saveContext(stream, mode); +} + +void +ConcreteFCMViscoElasticStatus::restoreContext(DataStream &stream, ContextMode mode) +// +// restores full information stored in stream to this Status +// +{ + // read parent cracking class status + ConcreteFCMStatus::restoreContext(stream, mode); + + // restore viscoelastic amterial + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->restoreContext(stream, mode); +} +} // end namespace oofem diff --git a/src/sm/Materials/ConcreteMaterials/concretefcmviscoelastic.h b/src/sm/Materials/ConcreteMaterials/concretefcmviscoelastic.h new file mode 100644 index 000000000..502fb2cc9 --- /dev/null +++ b/src/sm/Materials/ConcreteMaterials/concretefcmviscoelastic.h @@ -0,0 +1,149 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2016 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef concretefcmviscoelastic_h +#define concretefcmviscoelastic_h + +#include "concretefcm.h" +// for the unique_ptr +#include + +///@name Input fields for ConcreteFCMViscoElastic +//@{ +#define _IFT_ConcreteFCMViscoElastic_Name "concretefcmviscoelastic" +#define _IFT_ConcreteFCMViscoElastic_viscoMat "viscomat" +#define _IFT_ConcreteFCMViscoElastic_timedepfracturing "timedepfracturing" +#define _IFT_ConcreteFCMViscoElastic_fib_s "fib_s" +#define _IFT_ConcreteFCMViscoElastic_fcm28 "fcm28" +#define _IFT_ConcreteFCMViscoElastic_timeFactor "timefactor" +#define _IFT_ConcreteFCMViscoElastic_stiffnessFactor "stiffnessfactor" +#define _IFT_ConcreteFCMViscoElastic_gf28 "gf28" +#define _IFT_ConcreteFCMViscoElastic_ft28 "ft28" +//@} + +namespace oofem { +/** + * This class manages the status of ConcreteFCMViscoElastic + */ +class ConcreteFCMViscoElasticStatus : public ConcreteFCMStatus +{ + +protected: + std :: unique_ptr< GaussPoint >slaveGpVisco; + + /// hydration-degree dependent tensile strength + double var_ft = 0.; + /// hydration-degree dependent fracture energy + double var_gf = 0.; + +public: + ConcreteFCMViscoElasticStatus(GaussPoint *g); + + double giveFractureEnergy() const { return var_gf; } + void setFractureEnergy(double new_Gf) { var_gf = new_Gf; } + + double giveTensileStrength() const { return var_ft; } + void setTensileStrength(double new_ft) { var_ft = new_ft; } + + GaussPoint *giveSlaveGaussPointVisco() { return this->slaveGpVisco.get(); } + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + const char *giveClassName() const override { return "ConcreteFCMViscoElasticStatus"; } + + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; +}; + + +/** + * add description + */ +class ConcreteFCMViscoElastic : public ConcreteFCM +{ +public: + ConcreteFCMViscoElastic(int n, Domain *d); + + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "ConcreteFCMViscoElastic"; } + const char *giveInputRecordName() const override { return _IFT_ConcreteFCMViscoElastic_Name; } + + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new ConcreteFCMViscoElasticStatus(gp); } + + double give(int aProperty, GaussPoint *gp) const override; + + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; + + FloatArray computeStressIndependentStrainVector(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; + + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + + MaterialStatus *giveStatus(GaussPoint *gp) const override; + +protected: + /// number of the viscoelastic material + int viscoMat = 0; + + bool fib = false; + double fib_s = 0.; + double fib_fcm28 = 0.; + /* scaling time factor, 1 day expressed in the time units of the analysis + * e.g. if the time runs in days it is 1, if in seconds it is 86400 */ + double timeFactor = 0.; + /* scaling factor transforming PREDICTED strength and fracture energy + * e.g. if the stiffness should be in MPa, then stiffnessFactor = 1.e6 */ + double stiffnessFactor = 0.; + + + double giveTensileStrength(GaussPoint *gp, TimeStep *tStep) override; + double giveFractureEnergy(GaussPoint *gp, TimeStep *tStep) override; + + + double computeOverallElasticStiffness(GaussPoint *gp, TimeStep *tStep) override; + double computeOverallElasticShearModulus(GaussPoint *gp, TimeStep *tStep) override; + + + int checkConsistency(void) override; + + /// returns equivalent time (used to compute time-dependent ft and gf) + virtual double giveEquivalentTime(GaussPoint *gp, TimeStep *tStep); + +}; +} // end namespace oofem +#endif // concretefcmviscoelastic_h diff --git a/src/sm/Materials/ConcreteMaterials/frcfcm.C b/src/sm/Materials/ConcreteMaterials/frcfcm.C index 67f35095e..f1525dfb9 100644 --- a/src/sm/Materials/ConcreteMaterials/frcfcm.C +++ b/src/sm/Materials/ConcreteMaterials/frcfcm.C @@ -42,23 +42,13 @@ namespace oofem { REGISTER_Material(FRCFCM); -FRCFCM :: FRCFCM(int n, Domain *d) : ConcreteFCM(n, d) -{ - fiberShearStrengthType = FSS_Unknown; -} +FRCFCM :: FRCFCM(int n, Domain *d) : ConcreteFCM(n, d) {} - -IRResultType -FRCFCM :: initializeFrom(InputRecord *ir) +void +FRCFCM :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = ConcreteFCM :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - + ConcreteFCM :: initializeFrom(ir); this->fibreActivationOpening = 0.e-6; IR_GIVE_OPTIONAL_FIELD(ir, fibreActivationOpening, _IFT_FRCFCM_fibreActivationOpening); @@ -116,8 +106,7 @@ FRCFCM :: initializeFrom(InputRecord *ir) default: fiberShearStrengthType = FSS_Unknown; - OOFEM_WARNING("Softening type number %d is unknown", type); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_FRCFCM_fssType, "Softening type is unknown"); } @@ -143,8 +132,7 @@ FRCFCM :: initializeFrom(InputRecord *ir) default: fiberDamageType = FDAM_Unknown; - OOFEM_WARNING("Fibre damage type number %d is unknown", type); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_FRCFCM_fDamType, "Fibre damage type is unknown"); } @@ -162,18 +150,22 @@ FRCFCM :: initializeFrom(InputRecord *ir) fiberType = FT_SRF; break; + case 3: + fiberType = FT_SRF2D; + break; + default: fiberType = FT_Unknown; - OOFEM_WARNING("Fibre type number %d is unknown", type); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_FRCFCM_fiberType, "Fibre type is unknown"); } if ( ( fiberType == FT_CAF ) || ( fiberType == FT_SAF ) ) { - if ( ir->hasField(_IFT_FRCFCM_orientationVector) ) { + if ( ir.hasField(_IFT_FRCFCM_orientationVector) ) { IR_GIVE_FIELD(ir, orientationVector, _IFT_FRCFCM_orientationVector); if ( !( ( this->orientationVector.giveSize() == 2 ) || ( this->orientationVector.giveSize() == 3 ) ) ) { - OOFEM_ERROR("length of the fibre orientation vector must be 2 for 2D and 3 for 3D analysis"); + throw ValueInputException(ir, _IFT_FRCFCM_orientationVector, + "length of the fibre orientation vector must be 2 for 2D and 3 for 3D analysis"); } // we normalize the user-defined orientation vector @@ -194,23 +186,23 @@ FRCFCM :: initializeFrom(InputRecord *ir) // general properties IR_GIVE_FIELD(ir, Vf, _IFT_FRCFCM_Vf); if ( Vf < 0. ) { - OOFEM_ERROR("fibre volume content must not be negative"); + throw ValueInputException(ir, _IFT_FRCFCM_Vf, "fibre volume content must not be negative"); } IR_GIVE_FIELD(ir, Df, _IFT_FRCFCM_Df); if ( Df <= 0. ) { - OOFEM_ERROR("fibre diameter must be positive"); + throw ValueInputException(ir, _IFT_FRCFCM_Df, "fibre diameter must be positive"); } IR_GIVE_FIELD(ir, Ef, _IFT_FRCFCM_Ef); if ( Ef <= 0. ) { - OOFEM_ERROR("fibre stiffness must be positive"); + throw ValueInputException(ir, _IFT_FRCFCM_Ef, "fibre stiffness must be positive"); } // compute or read shear modulus of fibers double nuf = 0.; Gfib = 0.; - if ( ir->hasField(_IFT_FRCFCM_nuf) ) { + if ( ir.hasField(_IFT_FRCFCM_nuf) ) { IR_GIVE_FIELD(ir, nuf, _IFT_FRCFCM_nuf); Gfib = Ef / ( 2. * ( 1. + nuf ) ); } else { @@ -223,13 +215,13 @@ FRCFCM :: initializeFrom(InputRecord *ir) // debonding IR_GIVE_FIELD(ir, tau_0, _IFT_FRCFCM_tau_0); if ( tau_0 <= 0. ) { - OOFEM_ERROR("shear strength must be positive"); + throw ValueInputException(ir, _IFT_FRCFCM_tau_0, "shear strength must be positive"); } // snubbing coefficient IR_GIVE_FIELD(ir, f, _IFT_FRCFCM_f); if ( f < 0. ) { - OOFEM_ERROR("snubbing coefficient must not be negative"); + throw ValueInputException(ir, _IFT_FRCFCM_f, "snubbing coefficient must not be negative"); } // for SRF only @@ -237,6 +229,10 @@ FRCFCM :: initializeFrom(InputRecord *ir) this->g = 2. * ( 1. + exp(M_PI * f / 2.) ) / ( 4. + f * f ); } + if ( fiberType == FT_SRF2D ) { + this->g = ( exp(M_PI * f / 2.) - f ) / ( 1. + f * f ); + } + double Em; IR_GIVE_FIELD(ir, Em, _IFT_IsotropicLinearElasticMaterial_e); @@ -246,21 +242,18 @@ FRCFCM :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, M, _IFT_FRCFCM_M); - if ( ( fiberType == FT_SAF ) || ( fiberType == FT_SRF ) ) { + if ( ( fiberType == FT_SAF ) || ( fiberType == FT_SRF ) || ( fiberType == FT_SRF2D ) ) { IR_GIVE_FIELD(ir, Lf, _IFT_FRCFCM_Lf); // transitional opening at which sigma_b = max (zero derivative) for SRF and SAF this->w_star = this->Lf * this->Lf * this->tau_0 / ( ( 1. + this->eta ) * this->Ef * this->Df ); } - if ( ir->hasField(_IFT_FRCFCM_computeCrackSpacing) ) { + if ( ir.hasField(_IFT_FRCFCM_computeCrackSpacing) ) { this->crackSpacing = this->computeCrackSpacing(); } - - return IRRT_OK; } - double FRCFCM :: computeCrackFibreAngle(GaussPoint *gp, int index) { @@ -294,7 +287,7 @@ FRCFCM :: computeCrackFibreAngle(GaussPoint *gp, int index) double -FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) +FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep, int i) // // returns current cracking modulus according to crackStrain for i-th // crackplane @@ -314,7 +307,7 @@ FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) // it turns out that the concrete area is in the end independent of the angle // larger angle causes less fiber to cross the crack but also larger area of the fiber section area (an ellipse) // these two effects cancel out and what only matters is the fiber volume Vf - Cfc = ConcreteFCM :: giveCrackingModulus(rMode, gp, i); + Cfc = ConcreteFCM :: giveCrackingModulus(rMode, gp, tStep, i); Cfc *= ( 1. - this->Vf ); @@ -349,7 +342,7 @@ FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) // for zero or negative strain has been taken care of before if ( this->smoothen ) { - if ( ( w_max < this->dw0 ) || ( w < this->dw0 ) ) { + if ( ( w_max <= this->dw0 ) || ( w <= this->dw0 ) ) { return Cfc; } } else { @@ -361,7 +354,7 @@ FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) if ( ( this->smoothen ) && ( w_max > this->dw0 ) && ( w_max < this->dw1 ) ) { if ( w == w_max ) { - omega = this->computeTempDamage(gp); + omega = this->computeTempDamage(gp, tStep); x = w_max - this->dw0; dw_smooth = this->dw1 - this->dw0; @@ -391,6 +384,7 @@ FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) Cff = 3. *C1 *pow(x, 2) + 2. * C2 * x; Cff *= Le; + // reflect fibre orientation wrt crack theta = fabs( this->computeCrackFibreAngle(gp, i) ); Cff *= fabs( cos(theta) ) * exp(theta * this->f); @@ -407,12 +401,35 @@ FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) Cff = 3. *C1 *pow(x, 2) + 2. * C2 * x; Cff *= Le; + + } else if ( fiberType == FT_SRF2D ) { // short random fibers in 2D + + factor = ( 1. - omega ) * this->g * this->Vf * this->Lf * 2. / ( M_PI * this->Df ); + + sig_dw1 = factor * this->tau_0 * ( 2. * sqrt(this->dw1 / this->w_star) - this->dw1 / this->w_star ); + Dsig_dw1 = factor * this->tau_0 * ( 1. / ( this->w_star * sqrt(this->dw1 / this->w_star) ) - 1. / this->w_star ); + + C1 = Dsig_dw1 / pow(dw_smooth, 2) - ( 2 * sig_dw1 ) / pow(dw_smooth, 3); + C2 = ( 3 * sig_dw1 ) / pow(dw_smooth, 2) - Dsig_dw1 / dw_smooth; + + Cff = 3. *C1 *pow(x, 2) + 2. * C2 * x; + Cff *= Le; + } } else { // unlo-relo with smoothing // compute traction for ec == emax - double max_traction = this->computeStressInFibersInCracked(gp, emax * Ncr, i); + double max_traction = this->computeStressInFibersInCracked(gp, tStep, emax * Ncr, i); Cff = ( this->M * max_traction * Le / ( w_max - this->dw0 ) ) * pow( ( w - this->dw0 ) / ( w_max - this->dw0 ), ( this->M - 1 ) ); } + +#if DEBUG + if ( Cff < 0. ) { + OOFEM_WARNING("Negative fiber stress - smooth transition, increase dw1 or decrease dw0"); + return Cfc; + } +#endif + + Cff = max(0., Cff); } else if ( w_max == 0. ) { //zero strain w_max = 1.e-10; @@ -429,6 +446,11 @@ FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) } else if ( fiberType == FT_SRF ) { // short random fibers factor = this->g * this->Vf * this->Lf / ( 2. * this->Df ); Cff = factor * this->tau_0 * ( Le / ( this->w_star * sqrt(w_max / this->w_star) ) - Le / this->w_star ); + + } else if ( fiberType == FT_SRF2D ) { // short random fibers in 2D + factor = this->g * this->Vf * this->Lf * 2. / ( M_PI * this->Df ); + Cff = factor * this->tau_0 * ( Le / ( this->w_star * sqrt(w_max / this->w_star) ) - Le / this->w_star ); + } else { OOFEM_ERROR("Unknown fiber type"); } @@ -438,10 +460,10 @@ FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) // reflect fibre orientation wrt crack Cff *= fabs( cos(theta) ) * exp(theta * this->f); - omega = this->computeTempDamage(gp); + omega = this->computeTempDamage(gp, tStep); Cff *= ( 1. - omega ); } else if ( fiberType == FT_SAF ) { // short aligned fibers - omega = this->computeTempDamage(gp); + omega = this->computeTempDamage(gp, tStep); if ( w_max < this->w_star ) { // debonding + pullout @@ -460,7 +482,7 @@ FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) Cff = 0.; } } else if ( fiberType == FT_SRF ) { // short random fibers - omega = this->computeTempDamage(gp); + omega = this->computeTempDamage(gp, tStep); factor = ( 1. - omega ) * this->g * this->Vf * this->Lf / ( 2. * this->Df ); if ( w_max < this->w_star ) { // debonding + pullout @@ -470,25 +492,40 @@ FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) } else { // fully pulled out Cff = 0.; } + + } else if ( fiberType == FT_SRF2D ) { // short random fibers in 2D + + omega = this->computeTempDamage(gp, tStep); + factor = ( 1. - omega ) * this->g * this->Vf * this->Lf * 2. / ( M_PI * this->Df ); + + if ( w_max < this->w_star ) { // debonding + pullout + Cff = factor * this->tau_0 * ( Le / ( this->w_star * sqrt(w_max / this->w_star) ) - Le / this->w_star ); + } else if ( w_max <= this->Lf / 2. ) { // pullout + Cff = factor * this->computeFiberBond(w_max) * ( 8. * w_max * Le / ( this->Lf * this->Lf ) - 4. * Le / this->Lf ); + } else { // fully pulled out + Cff = 0.; + } + + } else { OOFEM_ERROR("Unknown fiber type"); } } else { // unlo-relo // compute traction for ec == emax - max_traction = this->computeStressInFibersInCracked(gp, emax * Ncr, i); + max_traction = this->computeStressInFibersInCracked(gp, tStep, emax * Ncr, i); Cff = ( this->M * max_traction * Le / w_max ) * pow( ( w / w_max ), ( this->M - 1 ) ); } } else if ( rMode == SecantStiffness ) { if ( this->smoothen ) { - if ( ( w_max < this->dw0 ) || ( w < this->dw0 ) ) { // fibres are not activated + if ( ( w_max <= this->dw0 ) || ( w <= this->dw0 ) ) { // fibres are not activated Cff = 0.; } else if ( ec == emax ) { // softening - Cff = computeStressInFibersInCracked(gp, emax * Ncr, i); // gets stress + Cff = computeStressInFibersInCracked(gp, tStep, emax * Ncr, i); // gets stress Cff /= ( emax ); // converted into stiffness } else { // unlo-relo // compute traction for ec == emax - max_traction = this->computeStressInFibersInCracked(gp, emax * Ncr, i); + max_traction = this->computeStressInFibersInCracked(gp, tStep, emax * Ncr, i); Cff = max_traction * pow( ( ( w - this->dw0 ) / ( w_max - this->dw0 ) ), this->M ) / ec; } } else { @@ -498,14 +535,14 @@ FRCFCM :: giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) w_max = 1.e-10 / Ncr; emax = w_max / Le; - Cff = computeStressInFibersInCracked(gp, emax * Ncr, i); // gets stress + Cff = computeStressInFibersInCracked(gp, tStep, emax * Ncr, i); // gets stress Cff /= ( emax ); // converted into stiffness } else if ( ec == emax ) { // softening - Cff = computeStressInFibersInCracked(gp, emax * Ncr, i); // gets stress + Cff = computeStressInFibersInCracked(gp, tStep, emax * Ncr, i); // gets stress Cff /= ( emax ); // converted into stiffness } else { // unlo-relo // compute traction for ec == emax - max_traction = this->computeStressInFibersInCracked(gp, emax * Ncr, i); + max_traction = this->computeStressInFibersInCracked(gp, tStep, emax * Ncr, i); Cff = max_traction * pow( ( w / w_max ), this->M ) / ec; } @@ -536,11 +573,12 @@ FRCFCM :: computeFiberBond(double w) tau_s = this->tau_0 * ( 1. + sgn(this->b0) * ( 1. - exp(-fabs(this->b0) * w / this->Df) ) ); } else if ( fiberShearStrengthType == FSS_Kabele ) { // Kabele tau_s = this->tau_0 * ( 1 + this->b1 * ( w / this->Df ) + this->b2 * ( w / this->Df ) * ( w / this->Df ) + this->b3 * ( w / this->Df ) * ( w / this->Df ) * ( w / this->Df ) ); + tau_s = max(0., tau_s); } else if ( fiberShearStrengthType == FSS_Havlasek ) { // Havlasek dw = w - this->w_star; - if ( fiberType == FT_SRF ) { - tau_tilde = this->tau_0 / ( ( 1. - this->w_star / this->Lf ) * ( 1. - this->w_star / this->Lf ) ); + if ( fiberType == FT_SRF || ( fiberType == FT_SRF2D ) ) { + tau_tilde = this->tau_0 / ( ( 1. - 2.*this->w_star / this->Lf ) * ( 1. - 2.*this->w_star / this->Lf ) ); } else { // SAF tau_tilde = this->tau_0 * this->Ef * ( 1. + this->eta ) * this->Df / ( this->Ef * ( 1. + this->eta ) * this->Df - 2. * this->Lf * this->tau_0 ); } @@ -548,6 +586,8 @@ FRCFCM :: computeFiberBond(double w) tau_s = tau_tilde + this->tau_0 * ( this->b1 * ( dw / this->Df ) + this->b2 * ( dw / this->Df ) * ( dw / this->Df ) + this->b3 * ( dw / this->Df ) * ( dw / this->Df ) * ( dw / this->Df ) ); + + tau_s = max(0., tau_s); } else { OOFEM_ERROR("Unknown FiberShearStrengthType"); } @@ -559,17 +599,17 @@ FRCFCM :: computeFiberBond(double w) double -FRCFCM :: giveNormalCrackingStress(GaussPoint *gp, double ec, int i) +FRCFCM :: giveNormalCrackingStress(GaussPoint *gp, TimeStep *tStep, double ec, int i) // // returns receivers Normal Stress in crack i for given cracking strain // { double traction_fc, traction_ff; //normal stress in cracked concrete and fibers - traction_fc = ConcreteFCM :: giveNormalCrackingStress(gp, ec, i); + traction_fc = ConcreteFCM :: giveNormalCrackingStress(gp, tStep, ec, i); traction_fc *= ( 1. - this->Vf ); - traction_ff = this->computeStressInFibersInCracked(gp, ec, i); + traction_ff = this->computeStressInFibersInCracked(gp, tStep, ec, i); return traction_fc + traction_ff; @@ -577,7 +617,7 @@ FRCFCM :: giveNormalCrackingStress(GaussPoint *gp, double ec, int i) double -FRCFCM :: computeStressInFibersInCracked(GaussPoint *gp, double ec, int i) +FRCFCM :: computeStressInFibersInCracked(GaussPoint *gp, TimeStep *tStep, double ec, int i) // // returns receivers Normal Stress in crack i for given cracking strain // @@ -617,7 +657,7 @@ FRCFCM :: computeStressInFibersInCracked(GaussPoint *gp, double ec, int i) if ( this->smoothen ) { - if ( ( w_max < this->dw0 ) || ( w < this->dw0 ) ) { + if ( ( w_max <= this->dw0 ) || ( w <= this->dw0 ) ) { return 0.; } } else { @@ -656,10 +696,10 @@ FRCFCM :: computeStressInFibersInCracked(GaussPoint *gp, double ec, int i) traction_ff *= fabs( cos(theta) ) * exp(theta * this->f); // reflect damage - omega = this->computeTempDamage(gp); + omega = this->computeTempDamage(gp, tStep); traction_ff *= ( 1. - omega ); } else if ( fiberType == FT_SAF ) { // short aligned fibers - omega = this->computeTempDamage(gp); + omega = this->computeTempDamage(gp, tStep); // smooth if ( ( this->smoothen ) && ( w_max > this->dw0 ) && ( w_max < this->dw1 ) ) { @@ -698,7 +738,7 @@ FRCFCM :: computeStressInFibersInCracked(GaussPoint *gp, double ec, int i) traction_ff = 0.; } } else if ( fiberType == FT_SRF ) { // short random fibers - omega = this->computeTempDamage(gp); + omega = this->computeTempDamage(gp, tStep); factor = ( 1. - omega ) * this->g * this->Vf * this->Lf / ( 2. * this->Df ); // smooth @@ -720,10 +760,45 @@ FRCFCM :: computeStressInFibersInCracked(GaussPoint *gp, double ec, int i) } else { // fully pulled out traction_ff = 0.; } + + } else if ( fiberType == FT_SRF2D ) { // short random fibers in 2D + + omega = this->computeTempDamage(gp, tStep); + factor = ( 1. - omega ) * this->g * this->Vf * this->Lf * 2./ ( M_PI * this->Df ); + + // smooth + if ( ( this->smoothen ) && ( w_max > this->dw0 ) && ( w_max < this->dw1 ) ) { + sig_dw1 = factor * this->tau_0 * ( 2. * sqrt(this->dw1 / this->w_star) - this->dw1 / this->w_star ); + Dsig_dw1 = factor * this->tau_0 * ( 1. / ( this->w_star * sqrt(this->dw1 / this->w_star) ) - 1. / this->w_star ); + + x = w_max - this->dw0; + dw_smooth = this->dw1 - this->dw0; + + C1 = Dsig_dw1 / pow(dw_smooth, 2) - ( 2 * sig_dw1 ) / pow(dw_smooth, 3); + C2 = ( 3 * sig_dw1 ) / pow(dw_smooth, 2) - Dsig_dw1 / dw_smooth; + + traction_ff = C1 * pow(x, 3) + C2 *pow(x, 2); + } else if ( w_max < this->w_star ) { // debonding + pullout + traction_ff = factor * this->tau_0 * ( 2. * sqrt(w_max / this->w_star) - w_max / this->w_star ); + } else if ( w_max <= this->Lf / 2. ) { // pullout + traction_ff = factor * this->computeFiberBond(w_max) * ( 1. - 2. * w_max / this->Lf ) * ( 1. - 2. * w_max / this->Lf ); + } else { // fully pulled out + traction_ff = 0.; + } + + } else { OOFEM_ERROR("Unknown fiber type"); } +#if DEBUG + if ( traction_ff < 0. ) { + OOFEM_WARNING("Negative fiber stress - smooth transition, increase dw1 or decrease dw0"); + return 0.; + } +#endif + + traction_ff = max(0., traction_ff); if ( ec < emax ) { // unloading-reloading if ( smoothen ) { @@ -739,14 +814,14 @@ FRCFCM :: computeStressInFibersInCracked(GaussPoint *gp, double ec, int i) double -FRCFCM :: computeEffectiveShearModulus(GaussPoint *gp, int shearDirection) +FRCFCM :: computeEffectiveShearModulus(GaussPoint *gp, TimeStep *tStep, int shearDirection) { double G, Geff; double beta_mf; double D2_1, D2_2, D2; int crackA, crackB; - G = this->computeOverallElasticShearModulus(); + G = this->computeOverallElasticShearModulus(gp, tStep); if ( this->isIntactForShear(gp, shearDirection) ) { Geff = G; @@ -770,15 +845,15 @@ FRCFCM :: computeEffectiveShearModulus(GaussPoint *gp, int shearDirection) if ( ( this->isIntact(gp, crackA) ) || ( this->isIntact(gp, crackB) ) ) { if ( this->isIntact(gp, crackA) ) { - D2 = this->computeD2ModulusForCrack(gp, crackB); + D2 = this->computeD2ModulusForCrack(gp, tStep, crackB); } else { - D2 = this->computeD2ModulusForCrack(gp, crackA); + D2 = this->computeD2ModulusForCrack(gp, tStep, crackA); } beta_mf = D2 / ( D2 + G ); } else { - D2_1 = this->computeD2ModulusForCrack(gp, crackA); - D2_2 = this->computeD2ModulusForCrack(gp, crackB); + D2_1 = this->computeD2ModulusForCrack(gp, tStep, crackA); + D2_2 = this->computeD2ModulusForCrack(gp, tStep, crackB); if ( multipleCrackShear ) { beta_mf = 1. / ( 1. + G * ( 1 / D2_1 + 1 / D2_2 ) ); @@ -797,10 +872,10 @@ FRCFCM :: computeEffectiveShearModulus(GaussPoint *gp, int shearDirection) double -FRCFCM :: computeD2ModulusForCrack(GaussPoint *gp, int icrack) +FRCFCM :: computeD2ModulusForCrack(GaussPoint *gp, TimeStep *tStep, int icrack) { - double cos_theta = 0.5; // to reduce Vf for SRF to one half - double E = this->giveLinearElasticMaterial()->giveYoungsModulus(); + double cos_theta; + double E = linearElasticMaterial.giveYoungsModulus(); FRCFCMStatus *status = static_cast< FRCFCMStatus * >( this->giveStatus(gp) ); double crackStrain; double D2m, D2f; @@ -813,12 +888,19 @@ FRCFCM :: computeD2ModulusForCrack(GaussPoint *gp, int icrack) } else { if ( ( this->fiberType == FT_CAF ) || ( this->fiberType == FT_SAF ) ) { cos_theta = fabs( cos( this->computeCrackFibreAngle(gp, icrack) ) ); - } - - D2m = ConcreteFCM :: computeD2ModulusForCrack(gp, icrack); + } else if ( this->fiberType == FT_SRF ) { + cos_theta = 0.5; // to reduce Vf for SRF to one half + } else if ( this->fiberType == FT_SRF2D ) { + cos_theta = 2./M_PI; // reduce Vf + } else { + OOFEM_ERROR("Unknown fiber type"); + } + + + D2m = ConcreteFCM :: computeD2ModulusForCrack(gp, tStep, icrack); D2m *= ( 1. - this->Vf ); - omega = this->computeTempDamage(gp); + omega = this->computeTempDamage(gp, tStep); // fiber shear stiffness is not influenced by the number of parallel cracks D2f = ( 1. - omega ) * this->Vf * cos_theta * this->kfib * this->Gfib / crackStrain; @@ -831,10 +913,10 @@ FRCFCM :: computeD2ModulusForCrack(GaussPoint *gp, int icrack) // the same function as "computeD2ModulusForCrack", only without current value of fiber damage. double -FRCFCM :: estimateD2ModulusForCrack(GaussPoint *gp, int icrack) +FRCFCM :: estimateD2ModulusForCrack(GaussPoint *gp, TimeStep *tStep, int icrack) { - double cos_theta = 0.5; // to reduce Vf for SRF to one half - double E = this->giveLinearElasticMaterial()->giveYoungsModulus(); + double cos_theta; + double E = linearElasticMaterial.giveYoungsModulus(); FRCFCMStatus *status = static_cast< FRCFCMStatus * >( this->giveStatus(gp) ); double crackStrain; double D2m, D2f; @@ -847,9 +929,15 @@ FRCFCM :: estimateD2ModulusForCrack(GaussPoint *gp, int icrack) } else { if ( ( this->fiberType == FT_CAF ) || ( this->fiberType == FT_SAF ) ) { cos_theta = fabs( cos( this->computeCrackFibreAngle(gp, icrack) ) ); - } - - D2m = ConcreteFCM :: computeD2ModulusForCrack(gp, icrack); + } else if ( this->fiberType == FT_SRF ) { + cos_theta = 0.5; // to reduce Vf for SRF to one half + } else if ( this->fiberType == FT_SRF2D ) { + cos_theta = 2./M_PI; // reduce Vf + } else { + OOFEM_ERROR("Unknown fiber type"); + } + + D2m = ConcreteFCM :: computeD2ModulusForCrack(gp, tStep, icrack); D2m *= ( 1. - this->Vf ); omega = status->giveDamage(); @@ -865,7 +953,7 @@ FRCFCM :: estimateD2ModulusForCrack(GaussPoint *gp, int icrack) double -FRCFCM :: computeTempDamage(GaussPoint *gp) { +FRCFCM :: computeTempDamage(GaussPoint *gp, TimeStep *tStep) { // we assume that fibre damage is the same for all crack planes FRCFCMStatus *status = static_cast< FRCFCMStatus * >( this->giveStatus(gp) ); @@ -880,11 +968,11 @@ FRCFCM :: computeTempDamage(GaussPoint *gp) { if ( fiberDamageType != FDAM_NONE ) { // fiber damage is allowed for ( int i = 1; i <= numberOfActiveCracks; i++ ) { if ( !this->isIntact(gp, i) ) { - opening = this->computeMaxNormalCrackOpening(gp, i); + opening = this->computeMaxNormalCrackOpening(gp, tStep, i); // if (opening > 0.) { if ( opening > this->fibreActivationOpening ) { - slip = this->computeShearSlipOnCrack(gp, i); + slip = this->computeShearSlipOnCrack(gp, tStep, i); gammaCrack = max(gammaCrack, slip / opening); } } // initiation condition @@ -912,16 +1000,17 @@ FRCFCM :: computeTempDamage(GaussPoint *gp) { } + double -FRCFCM :: maxShearStress(GaussPoint *gp, int shearDirection) +FRCFCM :: maxShearStress(GaussPoint *gp, TimeStep *tStep, int shearDirection) { double maxTau_m; double minTau_f; - double E = this->giveLinearElasticMaterial()->giveYoungsModulus(); + double E = linearElasticMaterial.giveYoungsModulus(); double crackStrain; double gamma_cr; double omega; - double cos_theta = 0.5; // to reduce Vf for SRF to one half + double cos_theta; MaterialMode mMode = gp->giveMaterialMode(); FRCFCMStatus *status = static_cast< FRCFCMStatus * >( this->giveStatus(gp) ); @@ -930,59 +1019,74 @@ FRCFCM :: maxShearStress(GaussPoint *gp, int shearDirection) int icrack; // max shear in matrix - maxTau_m = ConcreteFCM :: maxShearStress(gp, shearDirection); + maxTau_m = ConcreteFCM :: maxShearStress(gp, tStep, shearDirection); maxTau_m *= ( 1. - this->Vf ); + // for now we simply compute the least allowable stress as a product of crack shear stiffness (fiber contribution) * max shear strain - if ( shearDirection == 4 ) { + omega = this->computeTempDamage(gp, tStep); + minTau_f = E * fcm_BIGNUMBER; + + // TODO - check if behaves reasonably with nonzero damage + // if (omega > 0.) { + + + if ( shearDirection == 4 ) { crackA = 2; crackB = 3; - } else if ( shearDirection == 5 ) { + } else if ( shearDirection == 5 ) { crackA = 1; crackB = 3; - } else if ( shearDirection == 6 ) { + } else if ( shearDirection == 6 ) { crackA = 1; crackB = 2; - } else { + } else { OOFEM_ERROR("Unexpected value of index i (4, 5, 6 permitted only)"); - } + } + + - minTau_f = E * fcm_BIGNUMBER; - - if ( mMode == _PlaneStress ) { + if ( mMode == _PlaneStress ) { gamma_cr = fabs( status->giveTempMaxCrackStrain(3) ); - } else { + } else { gamma_cr = fabs( status->giveTempMaxCrackStrain(shearDirection) ); - } - - for ( int i = 1; i <= 2; i++ ) { + } + + for ( int i = 1; i <= 2; i++ ) { if ( i == 1 ) { - icrack = crackA; + icrack = crackA; } else { // i == 2 - icrack = crackB; + icrack = crackB; } - + crackStrain = status->giveTempMaxCrackStrain(icrack); if ( ( this->isIntact(gp, icrack) ) || ( crackStrain <= 0. ) ) { - minTau_f = min(minTau_f, E * fcm_BIGNUMBER); + minTau_f = min(minTau_f, E * fcm_BIGNUMBER); } else { - if ( ( this->fiberType == FT_CAF ) || ( this->fiberType == FT_SAF ) ) { - cos_theta = fabs( cos( this->computeCrackFibreAngle(gp, icrack) ) ); - } - - omega = this->computeTempDamage(gp); - - minTau_f = min(minTau_f, gamma_cr * ( 1. - omega ) * this->Vf * cos_theta * this->kfib * this->Gfib / crackStrain); + if ( ( this->fiberType == FT_CAF ) || ( this->fiberType == FT_SAF ) ) { + cos_theta = fabs( cos( this->computeCrackFibreAngle(gp, icrack) ) ); + } else if ( this->fiberType == FT_SRF ) { + cos_theta = 0.5; // to reduce Vf for SRF to one half + } else if ( this->fiberType == FT_SRF2D ) { + cos_theta = 2./M_PI; // reduce Vf + } else { + OOFEM_ERROR("Unknown fiber type"); + } + + //omega = this->computeTempDamage(gp, tStep); + + minTau_f = min(minTau_f, gamma_cr * ( 1. - omega ) * this->Vf * cos_theta * this->kfib * this->Gfib / crackStrain); } - } - + } // loop over crack directions + + //} // damage condition + return maxTau_m + minTau_f; } - // computes crack spacing at saturated state // random tensile strength is not supported here // effect of fiber inclination is not considered @@ -996,10 +1100,12 @@ FRCFCM :: computeCrackSpacing() { if ( fiberType == FT_CAF ) { // continuous aligned fibers x = x_CA; } else if ( fiberType == FT_SAF ) { // short aligned fibers - x = 0.5 * sqrt(this->Lf * this->Lf - 4. * this->Lf * x_CA); + x = 0.5 * (this->Lf - sqrt(this->Lf * this->Lf - 4. * this->Lf * x_CA) ); } else if ( fiberType == FT_SRF ) { // short random fibers lambda = ( 2. / M_PI ) * ( 4. + this->f * this->f ) / ( 1. + exp(M_PI * f / 2.) ); x = 0.5 * ( this->Lf - sqrt(this->Lf * this->Lf - 2. * M_PI * this->Lf * lambda * x_CA) ); + } else if ( fiberType == FT_SRF2D ) { // short random fibers in 2D + x = 0.5 * ( this->Lf - sqrt(this->Lf * this->Lf - 2. * M_PI * this->Lf * this->g * x_CA) ); } else { OOFEM_ERROR("Unknown fiber type"); } @@ -1017,15 +1123,15 @@ FRCFCM :: isStrengthExceeded(const FloatMatrix &base, GaussPoint *gp, TimeStep * return false; } - Em = this->giveLinearElasticMaterial()->giveYoungsModulus(); + Em = linearElasticMaterial.giveYoungsModulus(); // matrix is stiffer -> carries higher stress - if ( ( this->Ef <= Em ) && ( trialStress > this->giveTensileStrength(gp) ) ) { + if ( ( this->Ef <= Em ) && ( trialStress > this->giveTensileStrength(gp, tStep) ) ) { return true; } else { sigma_m = trialStress / ( 1. + this->Vf * ( this->Ef / Em - 1. ) ); - if ( sigma_m > this->giveTensileStrength(gp) ) { + if ( sigma_m > this->giveTensileStrength(gp, tStep) ) { return true; } else { return false; @@ -1034,14 +1140,15 @@ FRCFCM :: isStrengthExceeded(const FloatMatrix &base, GaussPoint *gp, TimeStep * } + double -FRCFCM :: computeShearStiffnessRedistributionFactor(GaussPoint *gp, int ithCrackPlane, int jthCrackDirection) +FRCFCM :: computeShearStiffnessRedistributionFactor(GaussPoint *gp, TimeStep *tStep, int ithCrackPlane, int jthCrackDirection) { double factor_ij, D2_i, D2_j; // slightly modified version here. The problem is recursive calling of damage & slip evaluation for the FRCFCM material - D2_i = this->estimateD2ModulusForCrack(gp, ithCrackPlane); - D2_j = this->estimateD2ModulusForCrack(gp, jthCrackDirection); + D2_i = this->estimateD2ModulusForCrack(gp, tStep, ithCrackPlane); + D2_j = this->estimateD2ModulusForCrack(gp, tStep, jthCrackDirection); factor_ij = D2_j / ( D2_i + D2_j ); @@ -1057,7 +1164,7 @@ FRCFCM :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type // nominal stress in fibers if ( type == IST_FiberStressLocal ) { answer.resize(1); - answer.at(1) = this->computeStressInFibersInCracked(gp, status->giveCrackStrain(1), 1); + answer.at(1) = this->computeStressInFibersInCracked(gp, tStep, status->giveCrackStrain(1), 1); return 1; } else if ( type == IST_DamageScalar ) { answer.resize(1); @@ -1069,12 +1176,15 @@ FRCFCM :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type } + + + // computes overall stiffness of the composite material: the main purpose of this method is to adjust the stiffness given by the linear elastic material which corresponds to the matrix. The same method is used by all fiber types. double -FRCFCM :: computeOverallElasticStiffness(void) { +FRCFCM :: computeOverallElasticStiffness(GaussPoint *gp, TimeStep *tStep) { double stiffness = 0.; - double Em = this->giveLinearElasticMaterial()->giveYoungsModulus(); + double Em = linearElasticMaterial.giveYoungsModulus(); if ( this->fiberType == FT_CAF ) { // continuous aligned fibers stiffness = this->Vf * this->Ef + ( 1. - this->Vf ) * Em; @@ -1082,6 +1192,8 @@ FRCFCM :: computeOverallElasticStiffness(void) { stiffness = this->Vf * this->Ef + ( 1. - this->Vf ) * Em; } else if ( this->fiberType == FT_SRF ) { // short random fibers stiffness = this->Vf * this->Ef + ( 1. - this->Vf ) * Em; + } else if ( this->fiberType == FT_SRF2D ) { // short random fibers in 2D + stiffness = this->Vf * this->Ef + ( 1. - this->Vf ) * Em; } else { OOFEM_ERROR("Unknown fiber type"); } @@ -1095,20 +1207,13 @@ FRCFCM :: computeOverallElasticStiffness(void) { /////////////////////////////////////////////////////////////////// -FRCFCMStatus :: FRCFCMStatus(int n, Domain *d, GaussPoint *gp) : - ConcreteFCMStatus(n, d, gp) -{ - damage = tempDamage = 0.0; -} - - -FRCFCMStatus :: ~FRCFCMStatus() +FRCFCMStatus :: FRCFCMStatus(GaussPoint *gp) : + ConcreteFCMStatus(gp) { } - void -FRCFCMStatus :: printOutputAt(FILE *file, TimeStep *tStep) +FRCFCMStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { ConcreteFCMStatus :: printOutputAt(file, tStep); @@ -1152,44 +1257,23 @@ FRCFCMStatus :: updateYourself(TimeStep *tStep) -contextIOResultType -FRCFCMStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +FRCFCMStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = ConcreteFCMStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + ConcreteFCMStatus :: saveContext(stream, mode); if ( !stream.write(damage) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -FRCFCMStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +FRCFCMStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = ConcreteFCMStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + ConcreteFCMStatus :: restoreContext(stream, mode); if ( !stream.read(damage) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; // return succes } } // end namespace oofem diff --git a/src/sm/Materials/ConcreteMaterials/frcfcm.h b/src/sm/Materials/ConcreteMaterials/frcfcm.h index e20b5a131..af2674ae4 100644 --- a/src/sm/Materials/ConcreteMaterials/frcfcm.h +++ b/src/sm/Materials/ConcreteMaterials/frcfcm.h @@ -75,32 +75,29 @@ class FRCFCMStatus : public ConcreteFCMStatus { protected: /// Damage level of material. - double damage; + double damage = 0.; /// Non-equilibrated damage level of material. - double tempDamage; + double tempDamage = 0.; public: - FRCFCMStatus(int n, Domain *d, GaussPoint *g); - virtual ~FRCFCMStatus(); + FRCFCMStatus(GaussPoint *g); /// Returns the last equilibrated damage level. - double giveDamage() { return damage; } + double giveDamage() const { return damage; } /// Returns the temporary damage level. - double giveTempDamage() { return tempDamage; } + double giveTempDamage() const { return tempDamage; } /// Sets the temp damage level to given value. void setTempDamage(double newDamage) { tempDamage = newDamage; } - /// Writes information into the output file. - virtual void printOutputAt(FILE *file, TimeStep *tStep); - // definition - virtual const char *giveClassName() const { return "FRCFCMStatus"; } + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + const char *giveClassName() const override { return "FRCFCMStatus"; } - // saves current context(state) into stream - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -108,66 +105,63 @@ class FRCFCMStatus : public ConcreteFCMStatus * This class implements a FRCFCM material (Fiber Reinforced Concrete base on Fixed Crack Model) * in a finite element problem. This class provides an extension to the ConcreteFCM which * serves as a material model for matrix while the present class FRCFCM adds the contribution - * of fibers + * of fibers. The contribution of the two constituents are defined by Vf parameter = volume of fibers. */ class FRCFCM : public ConcreteFCM { public: FRCFCM(int n, Domain *d); - virtual ~FRCFCM() {} - // identification and auxiliary functions - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new FRCFCMStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new FRCFCMStatus(gp); } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; protected: - /// fiber shear strength at zero slip - double tau_0; + double tau_0 = 0.; /// micromechanical parameter for fiber shear according to Sajdlova - double b0; + double b0 = 0.; /// micromechanical parameter for fiber shear according to Kabele - double b1, b2, b3; + double b1 = 0., b2 = 0., b3 = 0.; /// snubbing factor "f" - double f; + double f = 0.; /// auxiliary parameter computed from snubbing factor "f" - double g; + double g = 0.; /// volume fraction of fibers - double Vf; + double Vf = 0.; /// fiber length - double Lf; + double Lf = 0.; /// fiber diameter - double Df; + double Df = 0.; /// fiber Young's modulus - double Ef; + double Ef = 0.; /// fiber shear modulus - double Gfib; + double Gfib = 0.; /// fiber cross-sectional shear factor - double kfib; + double kfib = 0.; /// transitional opening - double w_star; + double w_star = 0.; /// aux. factor - double eta; + double eta = 0.; /// shear strain at full fibers rupture - double gammaCrackFail; + double gammaCrackFail = 0.; /// minimum opening at which damage can start - double minDamageOpening; + double minDamageOpening = 0.; /** * Exponent in the unloading-reloading constitutive law. @@ -175,13 +169,13 @@ class FRCFCM : public ConcreteFCM * and the stress at maximum cracking strain * sigma(w) = sig_max * w^M / w_max^M */ - int M; + int M = 0; /// orientation of fibres FloatArray orientationVector; /// crack opening at which the crossing fibers begin to be activated - double fibreActivationOpening; + double fibreActivationOpening = 0.; /** * smooth transition of the bridging stress if fibreActivationOpening is applied @@ -189,61 +183,52 @@ class FRCFCM : public ConcreteFCM * dw1 = distance from the fibreActivationOpening where the smooth transition ends * smoothen = flag */ - double dw0, dw1; - bool smoothen; + double dw0 = 0., dw1 = 0.; + bool smoothen = false; /** * Type strength of the shear bond. This is activated only for short fibers (SAF or SRF) * once the maximum crack opening exceeds w* */ enum FiberShearStrengthType { FSS_NONE, FSS_Sajdlova, FSS_Kabele, FSS_Havlasek, FSS_Unknown }; - FiberShearStrengthType fiberShearStrengthType; + FiberShearStrengthType fiberShearStrengthType = FSS_Unknown; /// Type of fibre damage which is triggered by crack shearing strain = w / u enum FiberDamageType { FDAM_NONE, FDAM_GammaCrackLin, FDAM_GammaCrackExp, FDAM_Unknown }; - FiberDamageType fiberDamageType; + FiberDamageType fiberDamageType = FDAM_Unknown; /** * Type fo fibers in the composite. * CAF = continuous aligned fibers * SAF = short aligned fibers * SRF = short random fibers + * SRF2D = short fibers random in 2D */ - enum FiberType { FT_CAF, FT_SAF, FT_SRF, FT_Unknown }; - FiberType fiberType; + enum FiberType { FT_CAF, FT_SAF, FT_SRF, FT_SRF2D, FT_Unknown }; + FiberType fiberType = FT_Unknown; - /// returns stiffness in the normal direction of the i-th crack - virtual double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i); + double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep, int i) override; /// evaluates the fiber bond if w > w* virtual double computeFiberBond(double w); - /// computes normal stress associated with i-th crack direction - virtual double giveNormalCrackingStress(GaussPoint *gp, double eps_cr, int i); + double giveNormalCrackingStress(GaussPoint *gp, TimeStep *tStep, double eps_cr, int i) override; /// compute the nominal stress in fibers in the i-th crack - virtual double computeStressInFibersInCracked(GaussPoint *gp, double eps_cr, int i); - /// returns Geff which is necessary in the global stiffness matrix - virtual double computeEffectiveShearModulus(GaussPoint *gp, int i); - /// shear modulus for a given crack plane (1, 2, 3) - virtual double computeD2ModulusForCrack(GaussPoint *gp, int icrack); + virtual double computeStressInFibersInCracked(GaussPoint *gp, TimeStep *tStep, double eps_cr, int i); + double computeEffectiveShearModulus(GaussPoint *gp, TimeStep *tStep, int i) override; + double computeD2ModulusForCrack(GaussPoint *gp, TimeStep *tStep, int icrack) override; /// estimate shear modulus for a given crack plane (1, 2, 3). Uses equilibrated value of damage. - virtual double estimateD2ModulusForCrack(GaussPoint *gp, int icrack); - /// computes the maximum value of the shear stress; if the shear stress exceeds this value, it is cropped - virtual double maxShearStress(GaussPoint *gp, int i); + virtual double estimateD2ModulusForCrack(GaussPoint *gp, TimeStep *tStep, int icrack); + double maxShearStress(GaussPoint *gp, TimeStep *tStep, int i) override; /// evaluates temporary value of damage caused by fibre shearing - virtual double computeTempDamage(GaussPoint *gp); + virtual double computeTempDamage(GaussPoint *gp, TimeStep *tStep); /// computes crack spacing based on composition of the fibre composite - virtual double computeCrackSpacing(void); + virtual double computeCrackSpacing(); /// compute the angle between the fibre and i-th crack normal virtual double computeCrackFibreAngle(GaussPoint *gp, int i); - /// overrides real checking from concretefcm.C, here we assume that the fibers provide sufficient strength to prevent snapback - virtual void checkSnapBack(GaussPoint *gp, int crack) { return; } - /// the method from fcm is overridden to consider stress split between the matrix and fibers - virtual bool isStrengthExceeded(const FloatMatrix &base, GaussPoint *gp, TimeStep *tStep, int iCrack, double trialStress); - /// function calculating ratio used to split shear slips on two crack planes - virtual double computeShearStiffnessRedistributionFactor(GaussPoint *gp, int ithCrackPlane, int jthCrackDirection); - /// according to the volume fraction of fibers and the Young's moduli estimates the overall stiffness of the composite - virtual double computeOverallElasticStiffness(void); - /// from the Poisson's ratio of matrix and the overall stiffness estimates G - virtual double computeOverallElasticShearModulus(void) { return this->computeOverallElasticStiffness() / ( 2. * ( 1. + this->giveLinearElasticMaterial()->givePoissonsRatio() ) ); } + void checkSnapBack(GaussPoint *gp, TimeStep *tStep, int crack) override { } + bool isStrengthExceeded(const FloatMatrix &base, GaussPoint *gp, TimeStep *tStep, int iCrack, double trialStress) override; + double computeShearStiffnessRedistributionFactor(GaussPoint *gp, TimeStep *tStep, int ithCrackPlane, int jthCrackDirection) override; + double computeOverallElasticStiffness(GaussPoint *gp, TimeStep *tStep) override; + double computeOverallElasticShearModulus(GaussPoint *gp, TimeStep *tStep) override { return this->computeOverallElasticStiffness(gp, tStep) / ( 2. * ( 1. + linearElasticMaterial.givePoissonsRatio() ) ); } }; } // end namespace oofem #endif // frcfcm_h diff --git a/src/sm/Materials/ConcreteMaterials/frcfcmnl.C b/src/sm/Materials/ConcreteMaterials/frcfcmnl.C index 2edd957a3..1c0476636 100644 --- a/src/sm/Materials/ConcreteMaterials/frcfcmnl.C +++ b/src/sm/Materials/ConcreteMaterials/frcfcmnl.C @@ -42,7 +42,7 @@ #include "nonlocalmaterialext.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "floatmatrix.h" #include "floatarray.h" @@ -60,25 +60,13 @@ FRCFCMNL :: FRCFCMNL(int n, Domain *d) : FRCFCM(n, d), StructuralNonlocalMateria {} -IRResultType -FRCFCMNL :: initializeFrom(InputRecord *ir) +void +FRCFCMNL :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = FRCFCM :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - result = StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - + FRCFCM :: initializeFrom(ir); + StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); // IR_GIVE_FIELD(ir, participAngle, _IFT_FRCFCMNL_participAngle); participAngle = 90.; - - return IRRT_OK; } @@ -125,7 +113,7 @@ FRCFCMNL :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, if ( crackStrain > 0. ) { // get local fiber stress - sigma_f_local = this->computeStressInFibersInCracked(gp, crackStrain, iCrack); + sigma_f_local = this->computeStressInFibersInCracked(gp, tStep, crackStrain, iCrack); // set local fiber stress to status status->setTempFiberStressLoc(iCrack, sigma_f_local); } else { @@ -791,37 +779,30 @@ FRCFCMNL :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType ty /////////////////////////////////////////////////////////////////// -FRCFCMNLStatus :: FRCFCMNLStatus(int n, Domain *d, GaussPoint *gp) : - FRCFCMStatus(n, d, gp), StructuralNonlocalMaterialStatusExtensionInterface(), - fiberStressLoc(), tempFiberStressLoc(), fiberStressNL(), tempFiberStressNL() +FRCFCMNLStatus :: FRCFCMNLStatus(GaussPoint *gp) : + FRCFCMStatus(gp), StructuralNonlocalMaterialStatusExtensionInterface(), + fiberStressLoc(this->nMaxCracks), tempFiberStressLoc(), fiberStressNL(), tempFiberStressNL() { - fiberStressLoc.resize(this->nMaxCracks); - fiberStressLoc.zero(); tempFiberStressLoc = fiberStressLoc; fiberStressNL = fiberStressLoc; tempFiberStressNL = fiberStressLoc; } -FRCFCMNLStatus :: ~FRCFCMNLStatus() -{} - - - void -FRCFCMNLStatus :: printOutputAt(FILE *file, TimeStep *tStep) +FRCFCMNLStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { FRCFCMStatus :: printOutputAt(file, tStep); fprintf(file, "maxFiberStressLocal: {"); - for ( int i = 1; i <= this->giveMaxNumberOfCracks(gp); i++ ) { - fprintf( file, " %f", this->giveFiberStressLoc(i) ); + for ( double s: fiberStressLoc ) { + fprintf( file, " %f", s ); } fprintf(file, "}\n"); fprintf(file, "maxFiberStressNL: {"); - for ( int i = 1; i <= this->giveMaxNumberOfCracks(gp); i++ ) { - fprintf( file, " %f", this->giveFiberStressNL(i) ); + for ( double s: fiberStressLoc ) { + fprintf( file, " %f", s ); } fprintf(file, "}\n"); } @@ -858,20 +839,12 @@ FRCFCMNLStatus :: updateYourself(TimeStep *tStep) -contextIOResultType -FRCFCMNLStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +FRCFCMNLStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = FRCFCMStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + FRCFCMStatus :: saveContext(stream, mode); + contextIOResultType iores; if ( ( iores = fiberStressLoc.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -879,24 +852,14 @@ FRCFCMNLStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) if ( ( iores = fiberStressNL.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -FRCFCMNLStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +FRCFCMNLStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = FRCFCMStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - + FRCFCMStatus :: restoreContext(stream, mode); + contextIOResultType iores; if ( ( iores = fiberStressLoc.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -904,8 +867,6 @@ FRCFCMNLStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj if ( ( iores = fiberStressNL.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; // return succes } diff --git a/src/sm/Materials/ConcreteMaterials/frcfcmnl.h b/src/sm/Materials/ConcreteMaterials/frcfcmnl.h index b2d466c9d..b7c562d78 100644 --- a/src/sm/Materials/ConcreteMaterials/frcfcmnl.h +++ b/src/sm/Materials/ConcreteMaterials/frcfcmnl.h @@ -37,7 +37,7 @@ #include "frcfcm.h" -#include "Materials/structuralnonlocalmaterialext.h" +#include "sm/Materials/structuralnonlocalmaterialext.h" ///@name Input fields for frcfcmnl //@{ @@ -57,7 +57,6 @@ class GaussPoint; class FRCFCMNLStatus : public FRCFCMStatus, public StructuralNonlocalMaterialStatusExtensionInterface { protected: - /// bulk stress in fibers - evaluated from crack opening FloatArray fiberStressLoc; /// Non-equilibrated stress (bulk) in fibers. @@ -70,35 +69,30 @@ class FRCFCMNLStatus : public FRCFCMStatus, public StructuralNonlocalMaterialSta public: - FRCFCMNLStatus(int n, Domain *d, GaussPoint *g); - virtual ~FRCFCMNLStatus(); + FRCFCMNLStatus(GaussPoint *g); /// LOCAL FIBER STRESSES (from crack opening) - double giveFiberStressLoc(int icrack) { return fiberStressLoc.at(icrack); } - double giveTempFiberStressLoc(int icrack) { return tempFiberStressLoc.at(icrack); } + double giveFiberStressLoc(int icrack) const { return fiberStressLoc.at(icrack); } + double giveTempFiberStressLoc(int icrack) const { return tempFiberStressLoc.at(icrack); } void setTempFiberStressLoc(int icrack, double newFiberStressLoc) { tempFiberStressLoc.at(icrack) = newFiberStressLoc; } /// NON-LOCAL FIBER STRESSES (from surrounding cracks) - double giveFiberStressNL(int icrack) { return fiberStressNL.at(icrack); } - double giveTempFiberStressNL(int icrack) { return tempFiberStressNL.at(icrack); } + double giveFiberStressNL(int icrack) const { return fiberStressNL.at(icrack); } + double giveTempFiberStressNL(int icrack) const { return tempFiberStressNL.at(icrack); } void setTempFiberStressNL(int icrack, double newFiberStressNL) { tempFiberStressNL.at(icrack) = newFiberStressNL; } - virtual void printOutputAt(FILE *file, TimeStep *tStep); - - // definition - virtual const char *giveClassName() const { return "FRCFCMNLStatus"; } - - virtual void initTempStatus(); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void updateYourself(TimeStep *tStep); + const char *giveClassName() const override { return "FRCFCMNLStatus"; } + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - // saves current context(state) into stream - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; }; @@ -106,34 +100,29 @@ class FRCFCMNL : public FRCFCM, public StructuralNonlocalMaterialExtensionInterf { public: FRCFCMNL(int n, Domain *d); - virtual ~FRCFCMNL() {} - // identification and auxiliary functions - virtual const char *giveClassName() const { return "FRCFCMNL"; } - virtual const char *giveInputRecordName() const { return _IFT_FRCFCMNL_Name; } + const char *giveClassName() const override { return "FRCFCMNL"; } + const char *giveInputRecordName() const override { return _IFT_FRCFCMNL_Name; } - // identification and auxiliary functions - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; + void giveMaterialStiffnessMatrix(FloatMatrix & answer, MatResponseMode, + GaussPoint * gp, + TimeStep * tStep) override; - virtual void giveMaterialStiffnessMatrix(FloatMatrix & answer, MatResponseMode, - GaussPoint * gp, - TimeStep * tStep); + Interface *giveInterface(InterfaceType it) override; - virtual Interface *giveInterface(InterfaceType it); + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new FRCFCMNLStatus(gp); } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new FRCFCMNLStatus(1, FRCFCM :: domain, gp); } - - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; //nothing to update here, is it? - virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) {} - - virtual bool isStrengthExceeded(const FloatMatrix &base, GaussPoint *gp, TimeStep *tStep, int iCrack, double trialStress); + void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const override { } + bool isStrengthExceeded(const FloatMatrix &base, GaussPoint *gp, TimeStep *tStep, int iCrack, double trialStress) override; double computeDebondedLength(double delta); @@ -155,10 +144,9 @@ class FRCFCMNL : public FRCFCM, public StructuralNonlocalMaterialExtensionInterf /// computes an angle between two vectors double computeAngleBetweenVectors(const FloatArray &vec1, const FloatArray &vec2); - protected: /// participation angle. The target gauss point must fall into this angle to contribute to the nonlocal stress - double participAngle; + double participAngle = 0.; }; } // end namespace oofem #endif // frcfcmnl_h diff --git a/src/sm/Materials/ConcreteMaterials/idm1.C b/src/sm/Materials/ConcreteMaterials/idm1.C index b6f16ceb5..17be6da37 100644 --- a/src/sm/Materials/ConcreteMaterials/idm1.C +++ b/src/sm/Materials/ConcreteMaterials/idm1.C @@ -33,7 +33,7 @@ */ #include "idm1.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" @@ -46,7 +46,7 @@ #include "dynamicinputrecord.h" #include "engngm.h" #include "crosssection.h" - +#include "oofemtxtinputrecord.h" namespace oofem { REGISTER_Material(IsotropicDamageMaterial1); @@ -69,65 +69,26 @@ MMALeastSquareProjection IsotropicDamageMaterial1 :: mapper; IsotropicDamageMaterial1 :: IsotropicDamageMaterial1(int n, Domain *d) : IsotropicDamageMaterial(n, d), RandomMaterialExtensionInterface() - // - // constructor - // { // deleted by parent, where linearElasticMaterial instance declared linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); - equivStrainType = EST_Unknown; - softType = ST_Unknown; - k = 0.; - md = 1.; - damageLaw = 0; - e0 = 0.; - ef = 0.; - wf = 0.; - gf = 0.; - wk = 0.; - sk = 0.; - gft = 0.; - ek = 0.; - griff_n = 8.; - c1 = 3.; // default value of Hordijk parameter - c2 = 6.93; // default value of Hordijk parameter - ps_alpha = 0.; - ps_H = 0.; - ecsMethod = ECSM_Unknown; - sourceElemSet = NULL; } IsotropicDamageMaterial1 :: ~IsotropicDamageMaterial1() -// -// destructor -// { if ( sourceElemSet ) { delete sourceElemSet; } } -IRResultType -IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) +void +IsotropicDamageMaterial1 :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - int equivStrainTypeRecord; - result = IsotropicDamageMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - result = RandomMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - result = linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + IsotropicDamageMaterial :: initializeFrom(ir); + RandomMaterialExtensionInterface :: initializeFrom(ir); + linearElasticMaterial->initializeFrom(ir); checkSnapBack = 1; //check by default IR_GIVE_OPTIONAL_FIELD(ir, checkSnapBack, _IFT_IsotropicDamageMaterial1_checkSnapBack); @@ -154,23 +115,22 @@ IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) this->equivStrainType = EST_Griffith; IR_GIVE_OPTIONAL_FIELD(ir, griff_n, _IFT_IsotropicDamageMaterial1_n); } else { - OOFEM_WARNING("Unknown equivStrainType %d", equivStrainType); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_equivstraintype, "Unknown equivStrainType"); } // specify the type of formula for damage evolution law IR_GIVE_OPTIONAL_FIELD(ir, damageLaw, _IFT_IsotropicDamageMaterial1_damageLaw); - if ( ( damageLaw != 6 ) && ( damageLaw != 7 ) ) { + if ( ( damageLaw != 6 ) && ( damageLaw != 7 ) ) { IR_GIVE_FIELD(ir, e0, _IFT_IsotropicDamageMaterial1_e0); } //applies only in this class switch ( damageLaw ) { case 0: // exponential softening - default - if ( ir->hasField(_IFT_IsotropicDamageMaterial1_wf) ) { + if ( ir.hasField(_IFT_IsotropicDamageMaterial1_wf) ) { this->softType = ST_Exponential_Cohesive_Crack; IR_GIVE_FIELD(ir, wf, _IFT_IsotropicDamageMaterial1_wf); - } else if ( ir->hasField(_IFT_IsotropicDamageMaterial1_gf) ) { + } else if ( ir.hasField(_IFT_IsotropicDamageMaterial1_gf) ) { this->softType = ST_Exponential_Cohesive_Crack; IR_GIVE_FIELD(ir, gf, _IFT_IsotropicDamageMaterial1_gf); } else { @@ -180,10 +140,10 @@ IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) break; case 1: // linear softening law - if ( ir->hasField(_IFT_IsotropicDamageMaterial1_wf) ) { + if ( ir.hasField(_IFT_IsotropicDamageMaterial1_wf) ) { this->softType = ST_Linear_Cohesive_Crack; IR_GIVE_FIELD(ir, wf, _IFT_IsotropicDamageMaterial1_wf); - } else if ( ir->hasField(_IFT_IsotropicDamageMaterial1_gf) ) { + } else if ( ir.hasField(_IFT_IsotropicDamageMaterial1_gf) ) { this->softType = ST_Linear_Cohesive_Crack; IR_GIVE_FIELD(ir, gf, _IFT_IsotropicDamageMaterial1_gf); } else { @@ -199,13 +159,13 @@ IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) wf = 0.; wk = 0.; sk = 0.; - if ( ir->hasField(_IFT_IsotropicDamageMaterial1_gf) ) { + if ( ir.hasField(_IFT_IsotropicDamageMaterial1_gf) ) { this->softType = ST_BiLinear_Cohesive_Crack; IR_GIVE_FIELD(ir, gf, _IFT_IsotropicDamageMaterial1_gf); // Gft is for the bilinear law, and corresponds to the total energy required to fail the specimen IR_GIVE_FIELD(ir, gft, _IFT_IsotropicDamageMaterial1_gft); - if ( ir->hasField(_IFT_IsotropicDamageMaterial1_ek) ) { + if ( ir.hasField(_IFT_IsotropicDamageMaterial1_ek) ) { // ek is for the bilinear law, and corresponds to the strain at the knee point IR_GIVE_FIELD(ir, ek, _IFT_IsotropicDamageMaterial1_ek); } else { @@ -217,8 +177,7 @@ IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) dumWf1 = 2. * gf / ( e0 * E ); if ( dumWf1 < wk ) { - OOFEM_WARNING("Bilinear softening: wk is larger then gf allows"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_wk, "Bilinear softening: wk is larger then gf allows"); } sk = ( e0 * E ) * ( 1 - wk / dumWf1 ); wf = 2. * ( gft - e0 * E * wk / 2.0 ) / sk; @@ -227,7 +186,7 @@ IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) gf = 0.; gft = 0.; } - } else if ( ir->hasField(_IFT_IsotropicDamageMaterial1_wk) ) { + } else if ( ir.hasField(_IFT_IsotropicDamageMaterial1_wk) ) { double E; this->softType = ST_BiLinear_Cohesive_Crack; @@ -239,37 +198,32 @@ IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, E, _IFT_IsotropicLinearElasticMaterial_e); if ( wk < 0.0 || wk > wf ) { - OOFEM_WARNING("Bilinear softening: wk must be in interval <0;wf>"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_wk, "Bilinear softening: wk must be in interval <0;wf>"); } if ( sk < 0.0 || sk > e0 * E ) { - OOFEM_WARNING("Bilinear softening: sk must be in interval <0;ft>"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_sk, "Bilinear softening: sk must be in interval <0;ft>"); } - } else if ( ir->hasField(_IFT_IsotropicDamageMaterial1_wkwf) ) { + } else if ( ir.hasField(_IFT_IsotropicDamageMaterial1_wkwf) ) { double dummy, E; this->softType = ST_BiLinear_Cohesive_Crack; IR_GIVE_FIELD(ir, wf, _IFT_IsotropicDamageMaterial1_wf); // wkwf is for the bilinear law, and corresponds to the ratio of crack opening at the knee point and max crack opening IR_GIVE_FIELD(ir, dummy, _IFT_IsotropicDamageMaterial1_wkwf); if ( dummy < 0.0 || dummy > 1.0 ) { - OOFEM_WARNING("Bilinear softening: wk/wf ratio (wkwf) must be in interval <0;1>"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_wkwf, "Bilinear softening: wk/wf ratio (wkwf) must be in interval <0;1>"); } else { wk = dummy * wf; } // sk is for the bilinear law, and corresponds to the ratio of stress at the knee point an tensile strength IR_GIVE_FIELD(ir, dummy, _IFT_IsotropicDamageMaterial1_skft); if ( dummy < 0.0 || dummy > 1.0 ) { - OOFEM_WARNING("Bilinear softening: sk/ft ratio (skft) must be in interval <0;1>"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_skft, "Bilinear softening: sk/ft ratio (skft) must be in interval <0;1>"); } else { IR_GIVE_FIELD(ir, E, _IFT_IsotropicLinearElasticMaterial_e); sk = dummy * e0 * E; } } else { - OOFEM_WARNING("Bilinear softening for ef not implemented"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, "none", "Bilinear softening for ef not implemented"); } // check if the model is reduced to linear softening @@ -278,13 +232,12 @@ IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) this->softType = ST_Linear_Cohesive_Crack; gf = gft; } else if ( gft < gf ) { - OOFEM_WARNING("Bilinear softening: gft < gf"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_gft, "Bilinear softening: gft < gf"); } else if ( wk == 0.0 && wf != 0 ) { OOFEM_WARNING("Bilinear softening: parameters defined as for Linear_Cohesive_Crack"); this->softType = ST_Linear_Cohesive_Crack; } else if ( wf < wk ) { - OOFEM_ERROR("Bilinear softening: wf < wk"); + throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_wf, "Bilinear softening: wf < wk"); } else if ( gf == 0 && sk == 0.0 ) { OOFEM_WARNING("Bilinear softening: parameters defined as for Linear_Cohesive_Crack"); this->softType = ST_Linear_Cohesive_Crack; @@ -298,9 +251,9 @@ IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, c1, _IFT_IsotropicDamageMaterial1_c1); c2 = 6.93; IR_GIVE_OPTIONAL_FIELD(ir, c2, _IFT_IsotropicDamageMaterial1_c2); - if ( ir->hasField(_IFT_IsotropicDamageMaterial1_wf) ) { + if ( ir.hasField(_IFT_IsotropicDamageMaterial1_wf) ) { IR_GIVE_FIELD(ir, wf, _IFT_IsotropicDamageMaterial1_wf); - } else if ( ir->hasField(_IFT_IsotropicDamageMaterial1_gf) ) { + } else if ( ir.hasField(_IFT_IsotropicDamageMaterial1_gf) ) { IR_GIVE_FIELD(ir, gf, _IFT_IsotropicDamageMaterial1_gf); double E; IR_GIVE_FIELD(ir, E, _IFT_IsotropicLinearElasticMaterial_e); @@ -310,8 +263,7 @@ IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) aux -= 0.5 * ( 1. + c1 * c1 * c1 ) * exp(-c2); wf = gf / ( aux * E * e0 ); } else { - OOFEM_WARNING("wf or gf must be specified for Hordijk softening law"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_wf, "wf or gf must be specified for Hordijk softening law"); } break; case 4: @@ -358,13 +310,20 @@ IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, ef, _IFT_IsotropicDamageMaterial1_ef); IR_GIVE_FIELD(ir, md, _IFT_IsotropicDamageMaterial1_md); break; + case 11: // trilinear softening + this->softType = ST_Trilinear_Cohesive_Crack; + IR_GIVE_FIELD(ir, w_k, _IFT_IsotropicDamageMaterial1_w_k); + IR_GIVE_FIELD(ir, w_r, _IFT_IsotropicDamageMaterial1_w_r); + IR_GIVE_FIELD(ir, w_f, _IFT_IsotropicDamageMaterial1_w_f); + IR_GIVE_FIELD(ir, f_k, _IFT_IsotropicDamageMaterial1_f_k); + IR_GIVE_FIELD(ir, f_r, _IFT_IsotropicDamageMaterial1_f_r); + break; default: - OOFEM_WARNING("Softening type number %d is unknown", damageLaw); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IsotropicDamageMaterial1_damageLaw, "Unknown value"); } - if ( ( softType == ST_Exponential_Cohesive_Crack ) || ( softType == ST_Linear_Cohesive_Crack ) || ( softType == ST_BiLinear_Cohesive_Crack ) ) { + if ( ( softType == ST_Exponential_Cohesive_Crack ) || ( softType == ST_Linear_Cohesive_Crack ) || ( softType == ST_BiLinear_Cohesive_Crack ) || ( softType == ST_Trilinear_Cohesive_Crack )) { int ecsm = 0; IR_GIVE_OPTIONAL_FIELD(ir, ecsm, _IFT_IsotropicDamageMaterial1_ecsm); switch ( ecsm ) { @@ -386,8 +345,6 @@ IsotropicDamageMaterial1 :: initializeFrom(InputRecord *ir) } this->mapper.initializeFrom(ir); - - return IRRT_OK; } @@ -461,24 +418,30 @@ IsotropicDamageMaterial1 :: giveInputRecord(DynamicInputRecord &input) input.setField(this->ef, _IFT_IsotropicDamageMaterial1_ef); input.setField(this->md, _IFT_IsotropicDamageMaterial1_md); break; + case 11: // Trilinear softening + input.setField(this->w_k, _IFT_IsotropicDamageMaterial1_w_k); + input.setField(this->w_r, _IFT_IsotropicDamageMaterial1_w_r); + input.setField(this->w_f, _IFT_IsotropicDamageMaterial1_w_f); + input.setField(this->f_k, _IFT_IsotropicDamageMaterial1_f_k); + input.setField(this->f_r, _IFT_IsotropicDamageMaterial1_f_r); + break; } - if ( softType == ST_Exponential_Cohesive_Crack || softType == ST_Linear_Cohesive_Crack || softType == ST_BiLinear_Cohesive_Crack ) { + if ( softType == ST_Exponential_Cohesive_Crack || softType == ST_Linear_Cohesive_Crack || softType == ST_BiLinear_Cohesive_Crack || softType == ST_Trilinear_Cohesive_Crack ) { input.setField(this->ecsMethod, _IFT_IsotropicDamageMaterial1_ecsm); } } -void -IsotropicDamageMaterial1 :: computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +double +IsotropicDamageMaterial1 :: computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const { - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); - FloatArray fullStrain; + auto lmat = this->linearElasticMaterial; if ( strain.isEmpty() ) { - kappa = 0.; - return; + return 0.; } + FloatArray fullStrain; StructuralMaterial :: giveFullSymVectorForm( fullStrain, strain, gp->giveMaterialMode() ); // if plane stress mode -> compute strain in z-direction from condition of zero stress in corresponding direction if ( gp->giveMaterialMode() == _PlaneStress ) { @@ -502,7 +465,7 @@ IsotropicDamageMaterial1 :: computeEquivalentStrain(double &kappa, const FloatAr } } - kappa = sqrt(posNorm); + return sqrt(posNorm); } else if ( ( this->equivStrainType == EST_Rankine_Smooth ) || ( this->equivStrainType == EST_Rankine_Standard ) ) { // EST_Rankine equiv strain measure double sum = 0.; @@ -529,7 +492,7 @@ IsotropicDamageMaterial1 :: computeEquivalentStrain(double &kappa, const FloatAr sum = sqrt(sum); } - kappa = sum / lmat->give('E', gp); + return sum / lmat->give('E', gp); } else if ( ( this->equivStrainType == EST_ElasticEnergy ) || ( this->equivStrainType == EST_ElasticEnergyPositiveStress ) || ( this->equivStrainType == EST_ElasticEnergyPositiveStrain ) ) { // equivalent strain expressions based on elastic energy FloatMatrix de; @@ -556,7 +519,7 @@ IsotropicDamageMaterial1 :: computeEquivalentStrain(double &kappa, const FloatAr OOFEM_ERROR("Elastic energy corresponding to positive part of strain not finished"); } - kappa = sqrt( sum / lmat->give('E', gp) ); + return sqrt( sum / lmat->give('E', gp) ); } else if ( this->equivStrainType == EST_Mises ) { double nu = lmat->give(NYxz, NULL); FloatArray principalStrains; @@ -568,9 +531,8 @@ IsotropicDamageMaterial1 :: computeEquivalentStrain(double &kappa, const FloatAr a = ( k - 1 ) * I1e / ( 2 * k * ( 1 - 2 * nu ) ); b = ( k - 1 ) * ( k - 1 ) * I1e * I1e / ( ( 1 - 2 * nu ) * ( 1 - 2 * nu ) ); c = 12 * k * J2e / ( ( 1 + nu ) * ( 1 + nu ) ); - kappa = a + 1 / ( 2 * k ) * sqrt(b + c); + return a + 1 / ( 2 * k ) * sqrt(b + c); } else if ( this->equivStrainType == EST_Griffith ) { - kappa = 0.0; double kappa1 = 0.0, kappa2 = 0.0; FloatArray stress, fullStress, principalStress; FloatMatrix de; @@ -594,18 +556,18 @@ IsotropicDamageMaterial1 :: computeEquivalentStrain(double &kappa, const FloatAr } else if ( principalStress.at(1) / principalStress.at(3) >= -0.33333 ) { kappa2 = -( principalStress.at(1) - principalStress.at(3) ) * ( principalStress.at(1) - principalStress.at(3) ) / this->griff_n / ( principalStress.at(1) + principalStress.at(3) ) / lmat->give('E', gp); } - kappa = max(kappa1, 0.0); - kappa = max(kappa, kappa2); + return max(max(kappa1, 0.0), kappa2); } else { OOFEM_ERROR("unknown EquivStrainType"); + return 0.; } } //Computes derivative of the equivalent strain with regards to strain, used in tangent formulation void -IsotropicDamageMaterial1 :: computeEta(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +IsotropicDamageMaterial1 :: computeEta(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const { - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); + LinearElasticMaterial *lmat = this->linearElasticMaterial; if ( strain.isEmpty() ) { answer.zero(); @@ -651,7 +613,6 @@ IsotropicDamageMaterial1 :: computeEta(FloatArray &answer, const FloatArray &str if ( i <= dim ) { if ( principalStrains.at(i) > 0.0 ) { n.beColumnOf(N, i); - Eta.plusDyadSymmUpper( n, principalStrains.at(i) ); } } @@ -811,7 +772,11 @@ IsotropicDamageMaterial1 :: computeEta(FloatArray &answer, const FloatArray &str double kappa = sqrt( sum / lmat->give('E', gp) ); answer = stress; - answer.times(1. / lmat->give('E', gp) / kappa); + if ( kappa != 0 ) { + answer.times(1. / lmat->give('E', gp) / kappa); + } else { + answer.times(0.); + } } else { OOFEM_ERROR("unknown EquivStrainType"); } @@ -827,27 +792,26 @@ IsotropicDamageMaterial1 :: computeStrainInvariants(const FloatArray &strainVect J2e = 1. / 2. * ( s1 + s2 + s3 ) - 1. / 6. * ( I1e * I1e ); } -void -IsotropicDamageMaterial1 :: computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *gp) +double +IsotropicDamageMaterial1 :: computeDamageParam(double kappa, const FloatArray &strain, GaussPoint *gp) const { if ( this->softType == ST_Disable_Damage ) { //dummy material with no damage - omega = 0.; + return 0.; } else if ( isCrackBandApproachUsed() ) { // adjustment of softening law according to the element size, given crack opening or fracture energy - computeDamageParamForCohesiveCrack(omega, kappa, gp); + return computeDamageParamForCohesiveCrack(kappa, gp); } else { // no adjustment according to element size, given fracturing strain - omega = damageFunction(kappa, gp); + return damageFunction(kappa, gp); } } -void -IsotropicDamageMaterial1 :: computeDamageParamForCohesiveCrack(double &omega, double kappa, GaussPoint *gp) +double +IsotropicDamageMaterial1 :: computeDamageParamForCohesiveCrack(double kappa, GaussPoint *gp) const { const double e0 = this->give(e0_ID, gp); // e0 is the strain at the peak stress - const double E = this->giveLinearElasticMaterial()->give('E', gp); + const double E = this->linearElasticMaterial->give('E', gp); const double gf = this->give(gf_ID, gp); double wf = this->give(wf_ID, gp); // wf is the crack opening - double Le; - omega = 0.0; + double omega = 0.0; if ( kappa > e0 ) { if ( this->gf != 0. ) { //cohesive crack model @@ -860,15 +824,17 @@ IsotropicDamageMaterial1 :: computeDamageParamForCohesiveCrack(double &omega, do } } else if ( softType == ST_BiLinear_Cohesive_Crack ) { wf = this->wk / ( e0 * E - this->sk ) * ( e0 * E ); + } else if ( softType == ST_Trilinear_Cohesive_Crack ) { + wf = this->w_f; } - IsotropicDamageMaterial1Status *status = static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) ); - Le = status->giveLe(); - ef = wf / Le; //ef is the fracturing strain + auto status = static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) ); + double Le = status->giveLe(); + double ef = wf / Le; //ef is the fracturing strain /// FIXME CHANGES BEHAVIOR! if ( ef < e0 ) { //check that no snapback occurs double minGf = 0.; - OOFEM_WARNING("ef %e < e0 %e, this leads to material snapback in element %d, characteristic length %f", ef, e0, gp->giveElement()->giveNumber(), Le); + OOFEM_WARNING("ef %e < e0 %e, this leads to material snapback in element %d, characteristic length %f", ef, e0, gp->giveElement()->giveGlobalNumber(), Le); if ( gf != 0. ) { //cohesive crack if ( softType == ST_Exponential_Cohesive_Crack ) { //exponential softening minGf = E * e0 * e0 * Le; @@ -943,6 +909,23 @@ IsotropicDamageMaterial1 :: computeDamageParamForCohesiveCrack(double &omega, do OOFEM_ERROR("algorithm not converging"); } } while ( fabs(R) >= e0 * IDM1_ITERATION_LIMIT ); + } else if ( this->softType == ST_Trilinear_Cohesive_Crack ) { + double eps_k = this->w_k/Le + this->f_k/E; + double eps_r = this->w_r/Le + this->f_r/E; + double eps_f = this->w_f/Le ; + double f_t = E*e0; + if ( kappa > e0 && kappa <= eps_k ) { + double slope=((f_k - f_t)/w_k); + omega = E/(E+slope*Le) - (f_t)/(kappa*(E+slope*Le)); + } else if ( kappa > eps_k && kappa <= eps_r ) { + double slope=((f_r - f_k)/(w_r-w_k)); + omega = E/(E+slope*Le) +(1.0/kappa)*(w_k*slope-f_k)/(Le*slope+E); + } else if ( kappa > eps_r && kappa <= eps_f ) { + double slope=(- f_r/(w_f-w_r)); + omega = E/(E+slope*Le) +(1.0/kappa)*(w_r*slope-f_r)/(Le*slope+E); + } else { + omega = 1.0; + } } else { OOFEM_ERROR("Unknown softening type for cohesive crack model."); } @@ -963,9 +946,12 @@ IsotropicDamageMaterial1 :: computeDamageParamForCohesiveCrack(double &omega, do } } } + return omega; } + + double -IsotropicDamageMaterial1 :: damageFunction(double kappa, GaussPoint *gp) +IsotropicDamageMaterial1 :: damageFunction(double kappa, GaussPoint *gp) const { const double e0 = this->give(e0_ID, gp); double ef = 0.; @@ -1027,7 +1013,6 @@ IsotropicDamageMaterial1 :: damageFunction(double kappa, GaussPoint *gp) } else { return 1.0 - s1 *exp( -( kappa - e1 ) / ( ef * ( 1. + pow( ( kappa - e1 ) / e2, nd ) ) ) ) / kappa; } - default: OOFEM_WARNING(":damageFunction ... undefined softening type %d\n", softType); } @@ -1036,11 +1021,11 @@ IsotropicDamageMaterial1 :: damageFunction(double kappa, GaussPoint *gp) } double -IsotropicDamageMaterial1 :: damageFunctionPrime(double kappa, GaussPoint *gp) +IsotropicDamageMaterial1 :: damageFunctionPrime(double kappa, GaussPoint *gp) const { const double e0 = this->give(e0_ID, gp); double ef = 0.; - const double E = this->giveLinearElasticMaterial()->give('E', gp); + const double E = this->linearElasticMaterial->give('E', gp); IsotropicDamageMaterial1Status *status = static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) ); const double Le = status->giveLe(); @@ -1062,7 +1047,8 @@ IsotropicDamageMaterial1 :: damageFunctionPrime(double kappa, GaussPoint *gp) case ST_Exponential: { if ( kappa > e0 ) { - return ( e0 / ( kappa * kappa ) ) * exp( -( kappa - e0 ) / ( ef - e0 ) + e0 / ( kappa * ( ef - e0 ) ) ) * exp( -( kappa - e0 ) / ( ef - e0 ) ); + // return ( e0 / ( kappa * kappa ) ) * exp( -( kappa - e0 ) / ( ef - e0 ) + e0 / ( kappa * ( ef - e0 ) ) ) * exp( -( kappa - e0 ) / ( ef - e0 ) ); + return ( e0 / ( ef - e0 ) / kappa + e0 / ( kappa * kappa ) ) * exp( -( kappa - e0 ) / ( ef - e0 ) ); } else { return 0.0; } @@ -1114,6 +1100,29 @@ IsotropicDamageMaterial1 :: damageFunctionPrime(double kappa, GaussPoint *gp) return 0.0; } } break; + case ST_Trilinear_Cohesive_Crack: + { + double Le = status->giveLe(); + const double E = this->linearElasticMaterial->give('E', gp); + double eps_k = this->w_k/Le + this->f_k/E; + double eps_r = this->w_r/Le + this->f_r/E; + double eps_f = this->w_f/Le ; + double f_t = E*e0; + if ( kappa <= e0 ) { + return 0.0; + } else if ( kappa > e0 && kappa <= eps_k ) { + double slope=((f_k - f_t)/w_k); + return (f_t)/(E+slope*Le)*(1.0/(kappa*kappa)); + } else if ( kappa > eps_k && kappa <= eps_r ) { + double slope=((f_r - f_k)/(w_r-w_k)); + return -(w_k*slope-f_k)/(Le*slope+E)*(1.0/(kappa*kappa)); + } else if ( kappa > eps_r && kappa <= eps_f ) { + double slope=(- f_r/(w_f-w_r)); + return -(w_r*slope-f_r)/(Le*slope+E)*(1.0/(kappa*kappa)); + } else { + return 0.0; + } + } break; default: OOFEM_ERROR("undefined softening type %d\n", softType); } @@ -1122,14 +1131,14 @@ IsotropicDamageMaterial1 :: damageFunctionPrime(double kappa, GaussPoint *gp) } double -IsotropicDamageMaterial1 :: complianceFunction(double kappa, GaussPoint *gp) +IsotropicDamageMaterial1 :: complianceFunction(double kappa, GaussPoint *gp) const { double om = damageFunction(kappa, gp); return om / ( 1. - om ); } double -IsotropicDamageMaterial1 :: evaluatePermanentStrain(double kappa, double omega) +IsotropicDamageMaterial1 :: evaluatePermanentStrain(double kappa, double omega) const { switch ( permStrain ) { case 1: @@ -1156,24 +1165,26 @@ IsotropicDamageMaterial1 :: evaluatePermanentStrain(double kappa, double omega) void -IsotropicDamageMaterial1 :: initDamaged(double kappa, FloatArray &strainVector, GaussPoint *gp) +IsotropicDamageMaterial1 :: initDamaged(double kappa, FloatArray &strainVector, GaussPoint *gp) const { + auto status = static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) ); int indx = 1; double le = 0.; - double E = this->giveLinearElasticMaterial()->give('E', gp); + double E = this->linearElasticMaterial->give('E', gp); FloatArray principalStrains, crackPlaneNormal, fullStrain, crackVect; FloatMatrix principalDir; - IsotropicDamageMaterial1Status *status = static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) ); const double e0 = this->give(e0_ID, gp); const double ef = this->give(ef_ID, gp); const double gf = this->give(gf_ID, gp); double wf = this->give(wf_ID, gp); - if ( softType == ST_Disable_Damage ) { return; } + if ( softType == ST_Trilinear_Cohesive_Crack ) { + wf = this->w_f; + } if ( gf != 0. ) { //cohesive crack model if ( softType == ST_Exponential_Cohesive_Crack ) { // exponential softening @@ -1214,7 +1225,7 @@ IsotropicDamageMaterial1 :: initDamaged(double kappa, FloatArray &strainVector, if ( this->equivStrainType == EST_Griffith ) { FloatArray stress, fullStress, principalStress, crackV(3), crackPlaneN(3); FloatMatrix de; - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); + LinearElasticMaterial *lmat = this->linearElasticMaterial; lmat->giveStiffnessMatrix( de, SecantStiffness, gp, domain->giveEngngModel()->giveCurrentStep() ); stress.beProductOf(de, strainVector); StructuralMaterial :: giveFullSymVectorForm( fullStress, stress, gp->giveMaterialMode() ); @@ -1310,7 +1321,7 @@ IsotropicDamageMaterial1 :: initDamaged(double kappa, FloatArray &strainVector, } double -IsotropicDamageMaterial1 :: give(int aProperty, GaussPoint *gp) +IsotropicDamageMaterial1 :: give(int aProperty, GaussPoint *gp) const { double answer; if ( static_cast< IsotropicDamageMaterial1Status * >( this->giveStatus(gp) )->_giveProperty(aProperty, answer) ) { @@ -1339,7 +1350,34 @@ IsotropicDamageMaterial1 :: giveInterface(InterfaceType type) if ( type == MaterialModelMapperInterfaceType ) { return static_cast< MaterialModelMapperInterface * >(this); } else { - return NULL; + return nullptr; + } +} + +void +IsotropicDamageMaterial1::saveContext(DataStream &stream, ContextMode mode) +{ + if ( ( mode & CM_Definition ) ) { + DynamicInputRecord input; + this->giveInputRecord(input); + if ( !stream.write(input.giveRecordAsString() + ) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +void +IsotropicDamageMaterial1::restoreContext(DataStream &stream, ContextMode mode) +{ + if ( ( mode & CM_Definition ) ) { + std::string input; + if ( !stream.read(input) ) { + THROW_CIOERR(CIO_IOERR); + } + OOFEMTXTInputRecord ir(0, input); + this->initializeFrom(ir); } } @@ -1347,19 +1385,19 @@ IsotropicDamageMaterial1 :: giveInterface(InterfaceType type) MaterialStatus * IsotropicDamageMaterial1 :: CreateStatus(GaussPoint *gp) const { - return new IsotropicDamageMaterial1Status(1, domain, gp); + return new IsotropicDamageMaterial1Status(gp); } MaterialStatus * IsotropicDamageMaterial1 :: giveStatus(GaussPoint *gp) const { MaterialStatus *status = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); - if ( status == NULL ) { + if ( status == nullptr ) { // create a new one status = this->CreateStatus(gp); - if ( status != NULL ) { - gp->setMaterialStatus( status, this->giveNumber() ); + if ( status ) { + gp->setMaterialStatus(status); this->_generateStatusVariables(gp); } } @@ -1458,10 +1496,9 @@ IsotropicDamageMaterial1 :: MMI_finish(TimeStep *tStep) } -IsotropicDamageMaterial1Status :: IsotropicDamageMaterial1Status(int n, Domain *d, GaussPoint *g) : - IsotropicDamageMaterialStatus(n, d, g), RandomMaterialStatusExtensionInterface() -{ -} +IsotropicDamageMaterial1Status :: IsotropicDamageMaterial1Status(GaussPoint *g) : + IsotropicDamageMaterialStatus(g), RandomMaterialStatusExtensionInterface() +{} Interface * IsotropicDamageMaterial1Status :: giveInterface(InterfaceType type) @@ -1472,5 +1509,4 @@ IsotropicDamageMaterial1Status :: giveInterface(InterfaceType type) return NULL; } } - } // end namespace oofem diff --git a/src/sm/Materials/ConcreteMaterials/idm1.h b/src/sm/Materials/ConcreteMaterials/idm1.h index 9c731a853..6ce597df3 100644 --- a/src/sm/Materials/ConcreteMaterials/idm1.h +++ b/src/sm/Materials/ConcreteMaterials/idm1.h @@ -50,9 +50,9 @@ #define IDM_USE_MAPPEDSTRAIN #include "material.h" -#include "Materials/linearelasticmaterial.h" -#include "Materials/isodamagemodel.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/linearelasticmaterial.h" +#include "sm/Materials/isodamagemodel.h" +#include "sm/Materials/structuralms.h" #include "randommaterialext.h" #include "materialmapperinterface.h" @@ -105,6 +105,11 @@ #define _IFT_IsotropicDamageMaterial1_c2 "c2" #define _IFT_IsotropicDamageMaterial1_alphaps "alphaps" #define _IFT_IsotropicDamageMaterial1_h "h" +#define _IFT_IsotropicDamageMaterial1_w_k "w_k" +#define _IFT_IsotropicDamageMaterial1_w_r "w_r" +#define _IFT_IsotropicDamageMaterial1_w_f "w_f" +#define _IFT_IsotropicDamageMaterial1_f_k "f_k" +#define _IFT_IsotropicDamageMaterial1_f_r "f_r" //@} namespace oofem { @@ -118,14 +123,11 @@ class IsotropicDamageMaterial1Status : public IsotropicDamageMaterialStatus, pub { public: /// Constructor - IsotropicDamageMaterial1Status(int n, Domain *d, GaussPoint *g); - /// Destructor - virtual ~IsotropicDamageMaterial1Status() { } + IsotropicDamageMaterial1Status(GaussPoint *g); - // definition - virtual const char *giveClassName() const { return "IsotropicDamageMaterial1Status"; } + const char *giveClassName() const override { return "IsotropicDamageMaterial1Status"; } - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; }; /** @@ -140,11 +142,11 @@ class IsotropicDamageMaterial1 : public IsotropicDamageMaterial, { protected: /// Equivalent strain at stress peak (or a similar parameter). - double e0; + double e0 = 0.; /// Determines ductility -> corresponds to fracturing strain. - double ef; + double ef = 0.; /// Determines ductility -> corresponds to crack opening in the cohesive crack model. - double wf; + double wf = 0.; /** * Determines the softening -> corresponds to the initial fracture energy. For a linear law, it is the area @@ -152,22 +154,25 @@ class IsotropicDamageMaterial1 : public IsotropicDamageMaterial, * and a tangent to the softening part of the curve at the peak stress. For a bilinear law, * gf corresponds to area bounded by elasticity and the first linear softening line projected to zero stress. */ - double gf; + double gf = 0.; /// Determines the softening for the bilinear law -> corresponds to the total fracture energy. - double gft; + double gft = 0.; /// Determines the softening for the bilinear law -> corresponds to the strain at the knee point. - double ek; + double ek = 0.; /// Determines the softening for the bilinear law -> corresponds to the crack opening at the knee point. - double wk; + double wk = 0.; /// Determines the softening for the bilinear law -> corresponds to the stress at the knee point. - double sk; + double sk = 0.; /// Parameters used in Hordijk's softening law - double c1, c2; + double c1 = 3., c2 = 6.93; // default value of Hordijk parameter + + /// Parameters used in Trilinear_Cohesive_Crack softening law + double w_k = 0., w_r = 0., w_f = 0., f_k = 0., f_r = 0.; /** Type characterizing the algorithm used to compute equivalent strain measure. * Note that the assigned numbers to enum values have to correspond to values @@ -186,46 +191,46 @@ class IsotropicDamageMaterial1 : public IsotropicDamageMaterial, EST_Unknown = 100 }; /// Parameter specifying the definition of equivalent strain. - EquivStrainType equivStrainType; + EquivStrainType equivStrainType = EST_Unknown; /// Parameter used in Mises definition of equivalent strain. - double k; + double k = 0.; /// Parameter used in Griffith's criterion - double griff_n; + double griff_n = 8.; /// Temporary parameter reading type of softening law, used in other isotropic damage material models. - int damageLaw; + int damageLaw = 0; /** Type characterizing the formula for the damage law. For example, linear softening can be specified * with fracturing strain or crack opening. */ - enum SofteningType { ST_Unknown, ST_Exponential, ST_Linear, ST_Mazars, ST_Smooth, ST_SmoothExtended, ST_Exponential_Cohesive_Crack, ST_Linear_Cohesive_Crack, ST_BiLinear_Cohesive_Crack, ST_Disable_Damage, ST_PowerExponential, ST_DoubleExponential, ST_Hordijk_Cohesive_Crack, ST_ModPowerExponential }; + enum SofteningType { ST_Unknown, ST_Exponential, ST_Linear, ST_Mazars, ST_Smooth, ST_SmoothExtended, ST_Exponential_Cohesive_Crack, ST_Linear_Cohesive_Crack, ST_BiLinear_Cohesive_Crack, ST_Disable_Damage, ST_PowerExponential, ST_DoubleExponential, ST_Hordijk_Cohesive_Crack, ST_ModPowerExponential, ST_Trilinear_Cohesive_Crack }; /// Parameter specifying the type of softening (damage law). - SofteningType softType; + SofteningType softType = ST_Unknown; /// Parameters used in Mazars damage law. - double At, Bt; + double At = 0., Bt = 0.; /// Parameter used in "smooth damage law". - double md; + double md = 1.; /// Parameters used if softType = 7 (extended smooth damage law) - double e1, e2, s1, nd; + double e1 = 0., e2 = 0., s1 = 0., nd = 0.; /// Check possible snap back flag - int checkSnapBack; + int checkSnapBack = 0; /// auxiliary input variablesfor softType == ST_SmoothExtended - double ep, ft; + double ep = 0., ft = 0.; /// Parameters used by the model with permanent strain - double ps_alpha, ps_H; + double ps_alpha = 0., ps_H = 0.; /// Method used for evaluation of characteristic element size - ElementCharSizeMethod ecsMethod; + ElementCharSizeMethod ecsMethod = ECSM_Unknown; /// Cached source element set used to map internal variables (adaptivity), created on demand - Set *sourceElemSet; + Set *sourceElemSet = nullptr; #ifdef IDM_USE_MMAClosestIPTransfer /// Mapper used to map internal variables in adaptivity. @@ -245,17 +250,15 @@ class IsotropicDamageMaterial1 : public IsotropicDamageMaterial, #endif public: - /// Constructor IsotropicDamageMaterial1(int n, Domain *d); /// Destructor virtual ~IsotropicDamageMaterial1(); - // identification and auxiliary functions - virtual const char *giveClassName() const { return "IsotropicDamageMaterial1"; } - virtual const char *giveInputRecordName() const { return _IFT_IsotropicDamageMaterial1_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + const char *giveClassName() const override { return "IsotropicDamageMaterial1"; } + const char *giveInputRecordName() const override { return _IFT_IsotropicDamageMaterial1_Name; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; /** * Computes invariants I1 and J2 of the strain tensor * from the strain components stored in a vector. @@ -265,11 +268,11 @@ class IsotropicDamageMaterial1 : public IsotropicDamageMaterial, */ static void computeStrainInvariants(const FloatArray &strainVector, double &I1e, double &J2e); - bool isCrackBandApproachUsed() { return ( this->softType == ST_Exponential_Cohesive_Crack || this->softType == ST_Linear_Cohesive_Crack || this->softType == ST_BiLinear_Cohesive_Crack || this->gf != 0. ); } - virtual void computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); + bool isCrackBandApproachUsed() const { return ( this->softType == ST_Exponential_Cohesive_Crack || this->softType == ST_Linear_Cohesive_Crack || this->softType == ST_BiLinear_Cohesive_Crack || this->softType == ST_Trilinear_Cohesive_Crack || this->gf != 0. ); } + double computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const override; - virtual void computeEta(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *gp); + void computeEta(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const override; + double computeDamageParam(double kappa, const FloatArray &strain, GaussPoint *gp) const override; /** * computes the value of damage parameter omega, * based on a given value of equivalent strain, @@ -279,7 +282,7 @@ class IsotropicDamageMaterial1 : public IsotropicDamageMaterial, * @param kappa Equivalent strain measure. * @param gp Integration point. */ - void computeDamageParamForCohesiveCrack(double &omega, double kappa, GaussPoint *gp); + double computeDamageParamForCohesiveCrack(double kappa, GaussPoint *gp) const; /** * Returns the value of damage parameter * corresponding to a given value @@ -289,7 +292,7 @@ class IsotropicDamageMaterial1 : public IsotropicDamageMaterial, * @param kappa Equivalent strain measure. * @param gp Integration point. */ - double damageFunction(double kappa, GaussPoint *gp); + double damageFunction(double kappa, GaussPoint *gp) const; /** * Returns the value of compliance parameter * corresponding to a given value @@ -310,7 +313,7 @@ class IsotropicDamageMaterial1 : public IsotropicDamageMaterial, * @param kappa Equivalent strain measure. * @param gp Integration point. */ - double damageFunctionPrime(double kappa, GaussPoint *gp); + double damageFunctionPrime(double kappa, GaussPoint *gp) const override; /** * Returns the value of compliance parameter * corresponding to a given value @@ -323,23 +326,25 @@ class IsotropicDamageMaterial1 : public IsotropicDamageMaterial, * @param kappa Equivalent strain measure. * @param gp Integration point. */ - double complianceFunction(double kappa, GaussPoint *gp); + double complianceFunction(double kappa, GaussPoint *gp) const; - double evaluatePermanentStrain(double kappa, double omega); + double evaluatePermanentStrain(double kappa, double omega) const override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual int MMI_map(GaussPoint *gp, Domain *oldd, TimeStep *tStep); - virtual int MMI_update(GaussPoint *gp, TimeStep *tStep, FloatArray *estrain = NULL); - virtual int MMI_finish(TimeStep *tStep); + int MMI_map(GaussPoint *gp, Domain *oldd, TimeStep *tStep) override; + int MMI_update(GaussPoint *gp, TimeStep *tStep, FloatArray *estrain = nullptr) override; + int MMI_finish(TimeStep *tStep) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; - virtual MaterialStatus *giveStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + MaterialStatus *giveStatus(GaussPoint *gp) const override; - virtual double give(int aProperty, GaussPoint *gp); + double give(int aProperty, GaussPoint *gp) const override; - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + void restoreContext(DataStream &stream, ContextMode mode) override; + void saveContext(DataStream &stream, ContextMode mode) override; protected: /** * Performs initialization, when damage first appear. The characteristic length is @@ -349,7 +354,7 @@ class IsotropicDamageMaterial1 : public IsotropicDamageMaterial, * @param totalStrainVector Current total strain vector. * @param gp Integration point. */ - virtual void initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp); + void initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) const override; }; } // end namespace oofem #endif // idm1_h diff --git a/src/sm/Materials/ConcreteMaterials/idmgrad.C b/src/sm/Materials/ConcreteMaterials/idmgrad.C new file mode 100644 index 000000000..093c98023 --- /dev/null +++ b/src/sm/Materials/ConcreteMaterials/idmgrad.C @@ -0,0 +1,538 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "idmgrad.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "mathfem.h" +#include "sparsemtrx.h" +#include "Materials/isolinearelasticmaterial.h" +#include "error.h" +#include "nonlocalmaterialext.h" +#include "datastream.h" +#include "contextioerr.h" +#include "stressvector.h" +#include "strainvector.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(IsotropicGradientDamageMaterial); + +IsotropicGradientDamageMaterial :: IsotropicGradientDamageMaterial(int n, Domain *d) : + IsotropicDamageMaterial1(n, d), + GradientDamageMaterialExtensionInterface(d) +{} + + +void +IsotropicGradientDamageMaterial :: initializeFrom(InputRecord &ir) +{ + IsotropicDamageMaterial1 :: initializeFrom(ir); + GradientDamageMaterialExtensionInterface :: initializeFrom(ir); + + int formulationType = 0; + IR_GIVE_OPTIONAL_FIELD(ir, formulationType, _IFT_IsotropicGradientDamageMaterial_formulationType); + if ( formulationType == 0 ) { + this->gradientDamageFormulationType = GDFT_Standard; + } else if ( formulationType == 1 ) { + this->gradientDamageFormulationType = GDFT_DecreasingInteractions; + di_rho = 0.005; + di_eta = 5; + IR_GIVE_OPTIONAL_FIELD(ir, di_rho, _IFT_IsotropicGradientDamageMaterial_di_rho); + IR_GIVE_OPTIONAL_FIELD(ir, di_eta, _IFT_IsotropicGradientDamageMaterial_di_eta); + } else if ( formulationType == 2 ) { + this->gradientDamageFormulationType = GDFT_Eikonal; + } else { + throw ValueInputException(ir, _IFT_IsotropicGradientDamageMaterial_formulationType, "Unknown gradient damage formulation"); + } + + + return this->mapper.initializeFrom(ir); +} + +///////////////////////////////////////////////////////////////////////////// + + + +bool +IsotropicGradientDamageMaterial :: hasMaterialModeCapability(MaterialMode mode) const +{ + return mode == _1dMat || mode == _PlaneStress || mode == _PlaneStrain || mode == _3dMat; +} + +void +IsotropicGradientDamageMaterial :: giveStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +// +// Returns characteristic material stiffness matrix of the receiver +// +{ + OOFEM_ERROR("Shouldn't be called."); +} + + +void +IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + double tempDamage; + if ( mode == ElasticStiffness ) { + tempDamage = 0.0; + } else { + tempDamage = status->giveTempDamage(); + if ( tempDamage > 0.0 ) { + tempDamage = min(tempDamage, maxOmega); + } + } + + this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + answer.times(1.0 - tempDamage); + + + /* + * FloatArray strainP, stressP, oldStrain, oldStress; + * oldStress = status->giveTempStressVector(); + * oldStrain = status->giveTempStrainVector(); + * strainP = oldStrain; + * double pert = 1.e-6 * strainP.at(1); + * strainP.at(1) += pert; + * double lddv; + * double mddv = status->giveTempNonlocalDamageDrivingVariable(); + * this->giveRealStressVectorGradientDamage(stressP, lddv, gp, strainP, mddv, tStep); + * FloatMatrix stiff; + * stiff.resize(1,1); + * stiff.at(1,1) = (stressP.at(1) - oldStress.at(1))/pert; + * this->giveRealStressVectorGradientDamage(stressP, lddv, gp, oldStrain, mddv, tStep); + */ +} + + + + +void +IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + FloatArray stress = status->giveTempStressVector(); + if ( mode == TangentStiffness ) { + double nonlocalDamageDrivingVariable = status->giveTempNonlocalDamageDrivingVariable(); + double gPrime = this->damageFunctionPrime(nonlocalDamageDrivingVariable, gp); + double tempDamage = status->giveTempDamage(); + if ( tempDamage < 1. ) { + stress.times( 1. / ( 1 - tempDamage ) ); + } else { + stress.times(0.); + } + answer.initFromVector(stress, false); + if ( tempDamage > status->giveDamage() ) { + answer.times(-gPrime); + /* + * double lddv; + * FloatArray strainP, stressP, oldStrain, oldStress; + * oldStress = status->giveTempStressVector(); + * oldStrain = status->giveTempStrainVector(); + * double mddv = status->giveTempNonlocalDamageDrivingVariable(); + * double pert = 1.e-6 * mddv; + * strainP = oldStrain; + * double mddvp = mddv + pert; + * this->giveRealStressVectorGradientDamage(stressP, lddv, gp, strainP, mddvp, tStep); + * FloatMatrix stiff; + * stiff.resize(1,1); + * stiff.at(1,1) = (stressP.at(1) -oldStress.at(1))/pert; + * this->giveRealStressVectorGradientDamage(stressP, lddv, gp, oldStrain, mddv, tStep); + */ + } else { + answer.times(0.); + } + // zero block for now + } else { + answer.initFromVector(stress, false); + answer.times(0); + } +} + + +void +IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + + FloatArray eta, reducedStrain; + FloatArray totalStrain = status->giveTempStrainVector(); + StructuralMaterial :: giveReducedSymVectorForm( reducedStrain, totalStrain, gp->giveMaterialMode() ); + this->computeEta(eta, reducedStrain, gp, tStep); + answer.initFromVector(eta, false); + if ( mode == TangentStiffness ) { + double tempDamage = status->giveTempDamage(); + if ( tempDamage > status->giveDamage() ) { + answer.times(-1.); + /* + * FloatArray strainP, stressP, oldStrain, oldStress; + * oldStress = status->giveTempStressVector(); + * oldStrain = status->giveTempStrainVector(); + * double mddv = status->giveTempNonlocalDamageDrivingVariable(); + * double lddv = status->giveTempLocalDamageDrivingVariable(); + * double lddvp; + * strainP = oldStrain; + * double pert = 1.e-6 * strainP.at(1); + * strainP.at(1) += pert; + * this->giveRealStressVectorGradientDamage(stressP, lddvp, gp, strainP, mddv, tStep); + * FloatMatrix stiff; + * stiff.resize(1,1); + * stiff.at(1,1) = (lddvp - lddv) / pert; + * this->giveRealStressVectorGradientDamage(stressP, lddv, gp, oldStrain, mddv, tStep); + */ + + + if ( gradientDamageFormulationType == GDFT_Eikonal ) { + double iA = this->computeEikonalInternalLength_a(gp); + if ( iA != 0 ) { + answer.times(1. / iA); + } else { + answer.times(0); + } + } + } + } else { + answer.times(0); + } +} + + + +void +IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_dd_NN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + if ( gradientDamageFormulationType == GDFT_Eikonal ) { + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + double tempKappa = status->giveTempKappa(); + double iA = this->computeEikonalInternalLength_a(gp); + + answer.resize(1, 1); + answer.zero(); + + if ( iA != 0 ) { + answer.at(1, 1) += 1. / iA; + } + + if ( mode == TangentStiffness ) { + if ( tempKappa > status->giveKappa() && iA != 0 ) { + double iAPrime = this->computeEikonalInternalLength_aPrime(gp); + double gPrime = this->damageFunctionPrime(tempKappa, gp); + double epsEqLocal = status->giveTempLocalDamageDrivingVariable(); + double epsEqNonLocal = status->giveTempNonlocalDamageDrivingVariable(); + answer.at(1, 1) += iAPrime / iA / iA * gPrime * ( epsEqNonLocal - epsEqLocal ); + } + } + } else { + answer.clear(); + } +} + +double +IsotropicGradientDamageMaterial :: computeEikonalInternalLength_a(GaussPoint *gp) +{ + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + + double damage = status->giveTempDamage(); + return sqrt(1. - damage) * internalLength; +} + +double +IsotropicGradientDamageMaterial :: computeEikonalInternalLength_b(GaussPoint *gp) +{ + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + + double damage = status->giveTempDamage(); + return sqrt(1. - damage) * internalLength; +} + + +double +IsotropicGradientDamageMaterial :: computeEikonalInternalLength_aPrime(GaussPoint *gp) +{ + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + + double damage = status->giveTempDamage(); + return -0.5 / sqrt(1. - damage) * internalLength; +} + +double +IsotropicGradientDamageMaterial :: computeEikonalInternalLength_bPrime(GaussPoint *gp) +{ + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + + double damage = status->giveTempDamage(); + return -0.5 / sqrt(1. - damage) * internalLength; +} + + + +void +IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + int n = this->giveDimension(gp); + answer.resize(n, n); + answer.beUnitMatrix(); + + if ( gradientDamageFormulationType == GDFT_Standard ) { + answer.times(internalLength * internalLength); + } else if ( gradientDamageFormulationType == GDFT_DecreasingInteractions ) { + double iL = this->computeInternalLength(gp); + answer.times(iL * iL); + } else if ( gradientDamageFormulationType == GDFT_Eikonal ) { + double iB = this->computeEikonalInternalLength_b(gp); + answer.times(iB); + } else { + OOFEM_WARNING("Unknown internalLengthDependenceType"); + } +} + + +void +IsotropicGradientDamageMaterial :: giveGradientDamageStiffnessMatrix_dd_BN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + if ( mode == TangentStiffness ) { + if ( gradientDamageFormulationType == GDFT_Standard ) { + answer.clear(); + } else if ( gradientDamageFormulationType == GDFT_DecreasingInteractions ) { + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + double damage = status->giveTempDamage(); + double tempKappa = status->giveTempKappa(); + double iL = computeInternalLength(gp); + double nom = -di_eta * ( 1. - di_rho ) * exp(-di_eta * damage); + double denom = sqrt( ( 1. - exp(-di_eta) ) * ( ( 1. - di_rho ) * exp(-di_eta * damage) + di_rho - exp(-di_eta) ) ); + double gPrime = this->damageFunctionPrime(tempKappa, gp); + double factor = iL * internalLength * nom / denom * gPrime; + answer.initFromVector(status->giveTempNonlocalDamageDrivingVariableGrad(), false); + if ( tempKappa > status->giveKappa() ) { + answer.times(factor); + } else { + answer.times(0.); + } + } else if ( gradientDamageFormulationType == GDFT_Eikonal ) { + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + double tempKappa = status->giveTempKappa(); + + double iBPrime = this->computeEikonalInternalLength_bPrime(gp); + double gPrime = this->damageFunctionPrime(tempKappa, gp); + + answer.initFromVector(status->giveTempNonlocalDamageDrivingVariableGrad(), false); + + if ( tempKappa > status->giveKappa() ) { + answer.times(iBPrime * gPrime); + } else { + answer.times(0.); + } + } else { + OOFEM_WARNING("Unknown internalLengthDependenceType"); + } + } else { + answer.clear(); + } +} + + +int +IsotropicGradientDamageMaterial :: giveDimension(GaussPoint *gp) +{ + if ( gp->giveMaterialMode() == _1dMat ) { + return 1; + } else if ( gp->giveMaterialMode() == _PlaneStress ) { + return 2; + } else if ( gp->giveMaterialMode() == _PlaneStrain ) { + return 3; + } else if ( gp->giveMaterialMode() == _3dMat ) { + return 3; + } else { + return 0; + } +} + +void +IsotropicGradientDamageMaterial :: giveNonlocalInternalForces_N_factor(double &answer, double nlDamageDrivingVariable, GaussPoint *gp, TimeStep *tStep) +{ + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + answer = nlDamageDrivingVariable - status->giveTempLocalDamageDrivingVariable(); + + if ( gradientDamageFormulationType == GDFT_Eikonal ) { + double iA = this->computeEikonalInternalLength_a(gp); + if ( iA != 0 ) { + answer = answer / iA; + } + } +} + +void +IsotropicGradientDamageMaterial :: giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlDamageDrivingVariable_grad, GaussPoint *gp, TimeStep *tStep) +{ + answer = nlDamageDrivingVariable_grad; + if ( gradientDamageFormulationType == GDFT_Eikonal ) { + double iB = this->computeEikonalInternalLength_b(gp); + answer.times(iB); + } else { + double iL = computeInternalLength(gp); + answer.times(iL * iL); + } +} + + +double +IsotropicGradientDamageMaterial :: computeInternalLength(GaussPoint *gp) +{ + if ( gradientDamageFormulationType == GDFT_Standard ) { + return internalLength; + } else if ( gradientDamageFormulationType == GDFT_DecreasingInteractions ) { + IsotropicGradientDamageMaterialStatus *status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + double damage = status->giveTempDamage(); + double factor = ( ( 1. - di_rho ) * exp(-di_eta * damage) + di_rho - exp(-di_eta) ) / ( 1. - exp(-di_eta) ); + return internalLength * sqrt(factor); + } else { + OOFEM_WARNING("Unknown internalLengthDependenceType"); + return 0.; + } +} + + +void +IsotropicGradientDamageMaterial :: giveRealStressVectorGradientDamage(FloatArray &stress, double &localDamageDrivingVariable, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalDamageDrivingVariable, TimeStep *tStep) +// +// returns real stress vector in 3d stress space of receiver according to +// previous level of stress and current +// strain increment, the only way, how to correctly update gp records +// +{ + auto status = static_cast< IsotropicGradientDamageMaterialStatus * >( this->giveStatus(gp) ); + auto lmat = this->giveLinearElasticMaterial(); + FloatArray reducedTotalStrainVector, strain; + + FloatMatrix de; + double f, damage, tempKappa = 0.0; + + this->initTempStatus(gp); + + // subtract stress independent part + // note: eigenStrains (temperature) is not contained in mechanical strain stored in gp + // therefore it is necessary to subtract always the total eigen strain value + this->giveStressDependentPartOfStrainVector(reducedTotalStrainVector, gp, totalStrain, tStep, VM_Total); + + + // compute equivalent strain + localDamageDrivingVariable = this->computeEquivalentStrain(reducedTotalStrainVector, gp, tStep); + + if ( llcriteria == idm_strainLevelCR ) { + // compute value of loading function if strainLevel crit apply + f = nonlocalDamageDrivingVariable - status->giveKappa(); + if ( f <= 0.0 ) { + // damage does not grow + tempKappa = status->giveKappa(); + damage = status->giveDamage(); + } else { + // damage grow + tempKappa = nonlocalDamageDrivingVariable; + this->initDamaged(nonlocalDamageDrivingVariable, reducedTotalStrainVector, gp); + // evaluate damage parameter + damage = this->computeDamageParam(nonlocalDamageDrivingVariable, reducedTotalStrainVector, gp); + } + } else if ( llcriteria == idm_damageLevelCR ) { + // evaluate damage parameter first + tempKappa = nonlocalDamageDrivingVariable; + this->initDamaged(nonlocalDamageDrivingVariable, strain, gp); + damage = this->computeDamageParam(nonlocalDamageDrivingVariable, reducedTotalStrainVector, gp); + if ( damage < status->giveDamage() ) { + // unloading takes place + damage = status->giveDamage(); + } + } else { + OOFEM_ERROR("unsupported loading/uloading criteria"); + } + + + lmat->giveStiffnessMatrix(de, SecantStiffness, gp, tStep); + de.times(1.0 - damage); + stress.beProductOf(de, reducedTotalStrainVector); + + // update gp + status->letTempStrainVectorBe(totalStrain); + status->letTempStressVectorBe(stress); + status->setTempLocalDamageDrivingVariable(localDamageDrivingVariable); + status->setTempNonlocalDamageDrivingVariable(nonlocalDamageDrivingVariable); + status->setTempKappa(tempKappa); + status->setTempDamage(damage); +#ifdef keep_track_of_dissipated_energy + status->computeWork(gp); +#endif +} + + + + +MaterialStatus * +IsotropicGradientDamageMaterial :: CreateStatus(GaussPoint *gp) const +{ + return new IsotropicGradientDamageMaterialStatus(gp); +} + + +IsotropicGradientDamageMaterialStatus :: IsotropicGradientDamageMaterialStatus(GaussPoint *g) : IsotropicDamageMaterial1Status(g) +{ } + + +void +IsotropicGradientDamageMaterialStatus :: initTempStatus() +// +// initializes temp variables according to variables form previous equlibrium state. +// builds new crackMap +// +{ + IsotropicDamageMaterial1Status :: initTempStatus(); + GradientDamageMaterialStatusExtensionInterface :: initTempStatus(); + this->tempDamage = this->damage; +} + + + +void +IsotropicGradientDamageMaterialStatus :: updateYourself(TimeStep *tStep) +// +// updates variables (nonTemp variables describing situation at previous equilibrium state) +// after a new equilibrium state has been reached +// temporary variables are having values corresponding to newly reched equilibrium. +// +{ + IsotropicDamageMaterial1Status :: updateYourself(tStep); + GradientDamageMaterialStatusExtensionInterface :: updateYourself(tStep); +} +} // end namespace oofem diff --git a/src/sm/Materials/ConcreteMaterials/idmgrad.h b/src/sm/Materials/ConcreteMaterials/idmgrad.h new file mode 100644 index 000000000..be1dd5612 --- /dev/null +++ b/src/sm/Materials/ConcreteMaterials/idmgrad.h @@ -0,0 +1,132 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef idmgrad_h +#define idmgrad_h + +#include "Materials/ConcreteMaterials/idm1.h" +#include "../sm/Materials/graddamagematerialextensioninterface.h" + +#define _IFT_IsotropicGradientDamageMaterial_Name "idmgrad" + +#define _IFT_IsotropicGradientDamageMaterial_formulationType "formtype" +#define _IFT_IsotropicGradientDamageMaterial_di_rho "di_rho" +#define _IFT_IsotropicGradientDamageMaterial_di_eta "di_eta" + +namespace oofem { +/** + * Gradient-enhanced Isotropic Damage model for concrete in tension, + */ +class IsotropicGradientDamageMaterial : public IsotropicDamageMaterial1, GradientDamageMaterialExtensionInterface +{ +protected: + + /** Type characterizing the dependence of the internal lenght on variable of the state + * Note that the assigned numbers to enum values have to correspond to values + * used in initializeFrom to resolve internalLenghtDependence. If not, the consistency + * between initializeFrom and giveInputRecord methods is lost. + */ + enum GradientDamageFormulationType { + GDFT_Standard = 0, + GDFT_DecreasingInteractions = 1, + GDFT_Eikonal = 2 + }; + + GradientDamageFormulationType gradientDamageFormulationType = GDFT_Standard; + + double di_rho = 0.; + double di_eta = 0.; + + +public: + /// Constructor + IsotropicGradientDamageMaterial(int n, Domain *d); + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + // identification and auxiliary functions + const char *giveClassName() const override { return "IsotropicGradientDamageMaterial"; } + const char *giveInputRecordName() const override { return _IFT_IsotropicGradientDamageMaterial_Name; } + void initializeFrom(InputRecord &ir) override; + + Interface *giveInterface(InterfaceType t) override { + if ( t == GradientDamageMaterialExtensionInterfaceType ) { + return static_cast< GradientDamageMaterialExtensionInterface * >( this ); + } else { + return nullptr; + } + } + bool hasMaterialModeCapability(MaterialMode mode) const override; + + void giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_dd_NN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_dd_BN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + + void giveRealStressVectorGradientDamage(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) override; + + void giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + void computeLocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep) override { } + void giveNonlocalInternalForces_N_factor(double &answer, double nlddv, GaussPoint *gp, TimeStep *tStep) override; + void giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlddv, GaussPoint *gp, TimeStep *tStep) override; +protected: + double computeInternalLength(GaussPoint *gp); + int giveDimension(GaussPoint *gp); + + double computeEikonalInternalLength_a(GaussPoint *gp); + double computeEikonalInternalLength_b(GaussPoint *gp); + double computeEikonalInternalLength_aPrime(GaussPoint *gp); + double computeEikonalInternalLength_bPrime(GaussPoint *gp); +}; + + + + + +/** + * Material status for gradient-enhanced isotropic damage model for concrete in tension. + */ +class IsotropicGradientDamageMaterialStatus : public IsotropicDamageMaterial1Status, public GradientDamageMaterialStatusExtensionInterface +{ +public: + IsotropicGradientDamageMaterialStatus(GaussPoint *g); + + const char *giveClassName() const override { return "IsotropicGradientDamageMaterialStatus"; } + + void initTempStatus() override; + void updateYourself(TimeStep *) override; +}; +} // end namespace oofem +#endif // idmgrad_h diff --git a/src/sm/Materials/ConcreteMaterials/idmgrad1.C b/src/sm/Materials/ConcreteMaterials/idmgrad1.C deleted file mode 100644 index cdcfc428e..000000000 --- a/src/sm/Materials/ConcreteMaterials/idmgrad1.C +++ /dev/null @@ -1,621 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "idmgrad1.h" -#include "gausspoint.h" -#include "floatmatrix.h" -#include "floatarray.h" -#include "mathfem.h" -#include "sparsemtrx.h" -#include "Materials/isolinearelasticmaterial.h" -#include "error.h" -#include "nonlocalmaterialext.h" -#include "datastream.h" -#include "contextioerr.h" -#include "stressvector.h" -#include "strainvector.h" -#include "classfactory.h" - -namespace oofem { -REGISTER_Material(IDGMaterial); - -IDGMaterial :: IDGMaterial(int n, Domain *d) : IsotropicDamageMaterial1(n, d), GradDpMaterialExtensionInterface(d) - // - // constructor - // -{ - internalLength = 0; - averType = 0; -} - - -IDGMaterial :: ~IDGMaterial() -// -// destructor -// -{ } - -IRResultType -IDGMaterial :: initializeFrom(InputRecord *ir) -{ - IRResultType result; - result = IsotropicDamageMaterial1 :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - result = GradDpMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - return this->mapper.initializeFrom(ir); -} - -///////////////////////////////////////////////////////////////////////////// - - - -int -IDGMaterial :: hasMaterialModeCapability(MaterialMode mode) -{ - return mode == _1dMat || mode == _PlaneStress || mode == _PlaneStrain; -} - -void -IDGMaterial :: giveStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) -// -// Returns characteristic material stiffness matrix of the receiver -// -{ - OOFEM_ERROR("Shouldn't be called."); -} - - -void -IDGMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - IsotropicDamageMaterialStatus *status = static_cast< IsotropicDamageMaterialStatus * >( this->giveStatus(gp) ); - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); - double om; - om = status->giveTempDamage(); - om = min(om, maxOmega); - answer.resize(1, 1); - answer.at(1, 1) = lmat->give('E', gp); - answer.times(1.0 - om); -} - -void -IDGMaterial :: give1dKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); - - double kappa = status->giveKappa(); - double tempKappa = status->giveTempKappa(); - FloatArray totalStrain = status->giveTempStrainVector(); - - answer.resize(1, 1); - if ( tempKappa > kappa ) { - FloatArray eta; - this->computeEta(eta, totalStrain, gp, tStep); - answer.at(1, 1) = eta.at(1); - } -} - -void -IDGMaterial :: give1dGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); - - double damage = status->giveDamage(); - double tempDamage = status->giveTempDamage(); - double E = lmat->give('E', gp); - - answer.resize(1, 1); - if ( tempDamage > damage ) { - double nlKappa = status->giveNonlocalCumulatedStrain(); - answer.at(1, 1) = E * status->giveTempStrainVector().at(1); - double gPrime = damageFunctionPrime(nlKappa, gp); - answer.times(gPrime); - } else { - answer.zero(); - } -} - - - -void -IDGMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); - double tempDamage; - if ( mode == ElasticStiffness ) { - tempDamage = 0.0; - } else { - tempDamage = status->giveTempDamage(); - if ( tempDamage > 0.0 ) { - tempDamage = min(tempDamage, maxOmega); - } - } - - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); - answer.times(1.0 - tempDamage); -} - - -void -IDGMaterial :: givePlaneStressKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - answer.resize(1, 3); - answer.zero(); - if ( mode == TangentStiffness ) { - IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); - FloatArray eta; - FloatArray totalStrain = status->giveTempStrainVector(); - this->computeEta(eta, totalStrain, gp, tStep); - answer.at(1, 1) = eta.at(1); - answer.at(1, 2) = eta.at(2); - answer.at(1, 3) = eta.at(3); - } -} - -void -IDGMaterial :: givePlaneStressGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - answer.resize(3, 1); - if ( mode == TangentStiffness ) { - IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); - double tempDamage = status->giveTempDamage(); - tempDamage = min(tempDamage, maxOmega); - double nlKappa = status->giveNonlocalCumulatedStrain(); - double gPrime = this->damageFunctionPrime(nlKappa, gp); - FloatArray stress = status->giveTempStressVector(); - - answer.at(1, 1) = stress.at(1) / ( 1 - tempDamage ); - answer.at(2, 1) = stress.at(2) / ( 1 - tempDamage ); - answer.at(3, 1) = stress.at(3) / ( 1 - tempDamage ); - answer.times(gPrime); - } -} - - -void -IDGMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); - double tempDamage; - if ( mode == ElasticStiffness ) { - tempDamage = 0.0; - } else { - tempDamage = status->giveTempDamage(); - if ( tempDamage > 0.0 ) { - tempDamage = min(tempDamage, maxOmega); - } - } - - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); - answer.times(1.0 - tempDamage); -} - - -void -IDGMaterial :: givePlaneStrainKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); - FloatArray totalStrain = status->giveTempStrainVector(); - FloatArray eta; - - answer.resize(1, 4); - this->computeEta(eta, totalStrain, gp, tStep); - answer.at(1, 1) = eta.at(1); - answer.at(1, 2) = eta.at(2); - answer.at(1, 3) = eta.at(3); - answer.at(1, 4) = eta.at(4); -} - -void -IDGMaterial :: givePlaneStrainGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); - double damage = status->giveDamage(); - double tempDamage = status->giveTempDamage(); - tempDamage = min(tempDamage, maxOmega); - answer.resize(4, 1); - if ( tempDamage > damage ) { - double nlEquivStrain = status->giveNonlocalCumulatedStrain(); - double gPrime = this->damageFunctionPrime(nlEquivStrain, gp); - FloatArray stress = status->giveTempStressVector(); - answer.at(1, 1) = stress.at(1) / ( 1 - tempDamage ); - answer.at(2, 1) = stress.at(2) / ( 1 - tempDamage ); - answer.at(3, 1) = stress.at(3) / ( 1 - tempDamage ); - answer.at(4, 1) = stress.at(4) / ( 1 - tempDamage ); - answer.times(gPrime); - } -} - - -void -IDGMaterial :: giveInternalLength(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) -{ - if ( averType == 0 ) { - answer.resize(1, 1); - answer.at(1, 1) = cl; - } else if ( averType == 1 ) { - answer.resize(1, 1); - FloatArray gpCoords; - if ( gp->giveElement()->computeGlobalCoordinates( gpCoords, gp->giveNaturalCoordinates() ) == 0 ) { - OOFEM_ERROR("computeGlobalCoordinates of GP failed"); - } - - this->giveDistanceBasedCharacteristicLength(gpCoords); - answer.at(1, 1) = cl; - } else if ( averType == 2 ) { - MaterialMode mMode = gp->giveMaterialMode(); - if ( mMode == _PlaneStress ) { - answer.resize(2, 2); - answer.zero(); - IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); - FloatArray stress = status->giveTempStressVector(); - StressVector fullStress(stress, _PlaneStress); - FloatArray sigPrinc; - FloatMatrix nPrinc; - // get principal stresses (ordered) and principal stress directions - fullStress.computePrincipalValDir(sigPrinc, nPrinc); - if ( nPrinc.giveNumberOfRows() == 0 ) { - nPrinc.resize(2, 2); - nPrinc.at(1, 1) = 1; - nPrinc.at(2, 2) = 1; - } - - // principal internal lengths - double l1 = cl0; - double l2 = cl0; - double gamma; - if ( sigPrinc.at(1) > 0 ) { - if ( sigPrinc.at(2) > 0 ) { - gamma = beta + ( 1 - beta ) * sigPrinc.at(2) * sigPrinc.at(2) / ( sigPrinc.at(1) * sigPrinc.at(1) ); - } else { - gamma = beta; - } - } else { - gamma = 1; - } - - l2 = l2 * gamma; - - // compose the internal Length matrix in global coordinates - // the first subscript refers to coordinate - // the second subscript refers to eigenvalue - double n11 = nPrinc.at(1, 1); - double n12 = nPrinc.at(1, 2); - double n21 = nPrinc.at(2, 1); - double n22 = nPrinc.at(2, 2); - - answer.at(1, 1) = l1 * l1 * n11 * n11 + l2 * l2 * n12 * n12; - answer.at(1, 2) = l1 * l1 * n11 * n21 + l2 * l2 * n12 * n22; - answer.at(2, 1) = l1 * l1 * n11 * n21 + l2 * l2 * n12 * n22; - answer.at(2, 2) = l1 * l1 * n21 * n21 + l2 * l2 * n22 * n22; - } else { - OOFEM_ERROR("Unknown material mode."); - } - } -} - - -void -IDGMaterial :: giveInternalLengthDerivative(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - MaterialMode mMode = gp->giveMaterialMode(); - if ( mMode == _PlaneStress ) { - answer.resize(5, 5); - answer.zero(); - if ( mode == TangentStiffness ) { - IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); - FloatArray stress = status->giveTempStressVector(); - stress.resize(3); - StressVector fullStress(stress, _PlaneStress); - FloatArray sigPrinc; - FloatMatrix nPrinc; - // get principal trial stresses (ordered) and principal stress directions - fullStress.computePrincipalValDir(sigPrinc, nPrinc); - if ( sigPrinc.at(1) > 0 ) { - if ( sigPrinc.at(2) > 0 && sigPrinc.at(1) != sigPrinc.at(2) ) { - double gamma = beta + ( 1 - beta ) * sigPrinc.at(2) * sigPrinc.at(2) / ( sigPrinc.at(1) * sigPrinc.at(1) ); - double dL2dS1 = 4. * gamma * cl * cl * ( beta - 1. ) * sigPrinc.at(2) * sigPrinc.at(2) / ( sigPrinc.at(1) * sigPrinc.at(1) * sigPrinc.at(1) ); - double dL2dS2 = 4. * gamma * cl * cl * ( 1. - beta ) * sigPrinc.at(2) / ( sigPrinc.at(1) * sigPrinc.at(1) ); - double dLdN = ( gamma * gamma - 1. ) * cl * cl / ( sigPrinc.at(2) - sigPrinc.at(1) ); - answer.at(1, 1) = nPrinc.at(1, 1); - answer.at(1, 2) = nPrinc.at(1, 2); - answer.at(2, 1) = nPrinc.at(2, 1); - answer.at(2, 2) = nPrinc.at(2, 2); - answer.at(3, 3) = dL2dS1; - answer.at(4, 4) = dL2dS2; - answer.at(5, 5) = dLdN; - } - } - } - } else { - OOFEM_ERROR("Unknown material mode."); - } -} - - - - - - -void -IDGMaterial :: giveRealStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) -// -// returns real stress vector in 3d stress space of receiver according to -// previous level of stress and current -// strain increment, the only way, how to correctly update gp records -// -{ - IDGMaterialStatus *status = static_cast< IDGMaterialStatus * >( this->giveStatus(gp) ); - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); - FloatArray reducedTotalStrainVector, strain; - - FloatMatrix de; - double f, equivStrain, tempKappa = 0.0, omega = 0.0; - - this->initTempStatus(gp); - - // subtract stress independent part - // note: eigenStrains (temperature) is not contained in mechanical strain stored in gp - // therefore it is necessary to subtract always the total eigen strain value - this->giveStressDependentPartOfStrainVector(reducedTotalStrainVector, gp, totalStrain, tStep, VM_Total); - - - // compute equivalent strain - this->computeEquivalentStrain(equivStrain, reducedTotalStrainVector, gp, tStep); - - if ( llcriteria == idm_strainLevelCR ) { - // compute value of loading function if strainLevel crit apply - f = nonlocalCumulatedStrain - status->giveKappa(); - - if ( f <= 0.0 ) { - // damage does not grow - tempKappa = status->giveKappa(); - omega = status->giveDamage(); - } else { - // damage grow - this->initDamaged(tempKappa, reducedTotalStrainVector, gp); - // evaluate damage parameter - this->computeDamageParam(omega, nonlocalCumulatedStrain, reducedTotalStrainVector, gp); - } - } else if ( llcriteria == idm_damageLevelCR ) { - // evaluate damage parameter first - tempKappa = nonlocalCumulatedStrain; - this->initDamaged(tempKappa, strain, gp); - this->computeDamageParam(omega, tempKappa, reducedTotalStrainVector, gp); - if ( omega < status->giveDamage() ) { - // unloading takes place - omega = status->giveDamage(); - //printf ("."); - } - } else { - OOFEM_ERROR("unsupported loading/uloading criteria"); - } - - - lmat->giveStiffnessMatrix(de, SecantStiffness, gp, tStep); - de.times(1.0 - omega); - answer1.beProductOf(de, strain); - answer2 = equivStrain; - - // update gp - - status->letTempStrainVectorBe(totalStrain); - status->letTempStressVectorBe(answer1); - status->setNonlocalCumulatedStrain(nonlocalCumulatedStrain); - status->setTempKappa(tempKappa); - status->setTempDamage(omega); -} - - - - -MaterialStatus * -IDGMaterial :: CreateStatus(GaussPoint *gp) const -{ - return new IDGMaterialStatus(1, IDGMaterial :: domain, gp); -} - - -IDGMaterialStatus :: IDGMaterialStatus(int n, Domain *d, GaussPoint *g) : IsotropicDamageMaterial1Status(n, d, g) -{ } - - -IDGMaterialStatus :: ~IDGMaterialStatus() -{ } - - - - -void -IDGMaterialStatus :: initTempStatus() -// -// initializes temp variables according to variables form previous equlibrium state. -// builds new crackMap -// -{ - IsotropicDamageMaterial1Status :: initTempStatus(); -} - - - -void -IDGMaterialStatus :: updateYourself(TimeStep *tStep) -// -// updates variables (nonTemp variables describing situation at previous equilibrium state) -// after a new equilibrium state has been reached -// temporary variables are having values corresponding to newly reched equilibrium. -// -{ - IsotropicDamageMaterial1Status :: updateYourself(tStep); -} - - - -contextIOResultType -IDGMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// -{ - contextIOResultType iores; - // save parent class status - if ( ( iores = IsotropicDamageMaterial1Status :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write a raw data - if ( !stream.write(le) ) { - THROW_CIOERR(CIO_IOERR); - } - - return CIO_OK; -} - -contextIOResultType -IDGMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// -{ - contextIOResultType iores; - // read parent class status - if ( ( iores = IsotropicDamageMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data - if ( !stream.read(le) ) { - THROW_CIOERR(CIO_IOERR); - } - - return CIO_OK; -} - -void -IDGMaterial :: givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - MaterialMode mMode = gp->giveMaterialMode(); - switch ( mMode ) { - case _1dMat: - give1dStressStiffMtrx(answer, mode, gp, tStep); - break; - case _PlaneStress: - givePlaneStressStiffMtrx(answer, mode, gp, tStep); - break; - case _PlaneStrain: - givePlaneStrainStiffMtrx(answer, mode, gp, tStep); - break; - default: - OOFEM_ERROR("mMode = %d not supported\n", mMode); - } -} - -void -IDGMaterial :: givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - MaterialMode mMode = gp->giveMaterialMode(); - switch ( mMode ) { - case _1dMat: - give1dKappaMatrix(answer, mode, gp, tStep); - break; - case _PlaneStress: - givePlaneStressKappaMatrix(answer, mode, gp, tStep); - break; - case _PlaneStrain: - givePlaneStrainKappaMatrix(answer, mode, gp, tStep); - break; - default: - OOFEM_ERROR("mMode = %d not supported\n", mMode); - } -} - -void -IDGMaterial :: givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - MaterialMode mMode = gp->giveMaterialMode(); - switch ( mMode ) { - case _1dMat: - give1dGprime(answer, mode, gp, tStep); - break; - case _PlaneStress: - givePlaneStressGprime(answer, mode, gp, tStep); - break; - case _PlaneStrain: - givePlaneStrainGprime(answer, mode, gp, tStep); - break; - default: - OOFEM_ERROR("mMode = %d not supported\n", mMode); - } -} - -void -IDGMaterial :: givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - MaterialMode mMode = gp->giveMaterialMode(); - switch ( mMode ) { - case _1dMat: - giveInternalLength(answer, mode, gp, tStep); - break; - case _PlaneStress: - giveInternalLength(answer, mode, gp, tStep); - break; - case _PlaneStrain: - giveInternalLength(answer, mode, gp, tStep); - break; - default: - OOFEM_ERROR("mMode = %d not supported\n", mMode); - } -} - -void -IDGMaterial :: givePDGradMatrix_LD(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - MaterialMode mMode = gp->giveMaterialMode(); - switch ( mMode ) { - case _PlaneStress: - giveInternalLengthDerivative(answer, mode, gp, tStep); - break; - default: - OOFEM_ERROR("mMode = %d not supported\n", mMode); - } -} -} // end namespace oofem diff --git a/src/sm/Materials/ConcreteMaterials/idmgrad1.h b/src/sm/Materials/ConcreteMaterials/idmgrad1.h deleted file mode 100644 index 0fb3d9b8b..000000000 --- a/src/sm/Materials/ConcreteMaterials/idmgrad1.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef idmgrad1_h -#define idmgrad1_h - -#include "Materials/ConcreteMaterials/idm1.h" -#include "../sm/Materials/graddpmaterialextensioninterface.h" - -#define _IFT_IDGMaterial_Name "idmgrad1" - -namespace oofem { -/** - * Gradient-enhanced Isotropic Damage model for concrete in tension, - */ -class IDGMaterial : public IsotropicDamageMaterial1, GradDpMaterialExtensionInterface -{ -protected: - /// Length scale parameter - double internalLength; - /// Parameter specifiying averaging type(0 - classical, 1 - distance based, 2 - stress based) - int averType; - /// Parameters specifying how the length scale parameter l is adjusted - double beta, t; - - -public: - /// Constructor - IDGMaterial(int n, Domain * d); - /// Destructor - virtual ~IDGMaterial(); - - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; - // identification and auxiliary functions - virtual const char *giveClassName() const { return "IDGMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_IDGMaterial_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual Interface *giveInterface(InterfaceType t) { - if ( t == GradDpMaterialExtensionInterfaceType ) { - return static_cast< GradDpMaterialExtensionInterface * >(this); - } else { - return NULL; - } - } - virtual int hasMaterialModeCapability(MaterialMode mode); - - virtual void givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_LD(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveRealStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep); - - void giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode, GaussPoint *gp, TimeStep *tStep); - void give1dKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - void give1dGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - void givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - void givePlaneStressKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - void givePlaneStressGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - void givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - void givePlaneStrainKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - void givePlaneStrainGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - void giveInternalLength(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - void giveInternalLengthDerivative(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); -}; - - -/** - * Material status for gradient-enhanced isotropic damage model for concrete in tension. - */ -class IDGMaterialStatus : public IsotropicDamageMaterial1Status, GradDpMaterialStatusExtensionInterface -{ -public: - IDGMaterialStatus(int n, Domain * d, GaussPoint * g); - virtual ~IDGMaterialStatus(); - - virtual const char *giveClassName() const { return "IDGMaterialStatus"; } - - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *); - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - - virtual double giveNonlocalCumulatedStrain() { return nonlocalCumulatedStrain; } - virtual void setNonlocalCumulatedStrain(double nonlocalCumulatedStrain) { this->nonlocalCumulatedStrain = nonlocalCumulatedStrain; } -}; -} // end namespace oofem -#endif // idmgrad1_h diff --git a/src/sm/Materials/ConcreteMaterials/idmnl1.C b/src/sm/Materials/ConcreteMaterials/idmnl1.C index 7c42a4c37..a295f316d 100644 --- a/src/sm/Materials/ConcreteMaterials/idmnl1.C +++ b/src/sm/Materials/ConcreteMaterials/idmnl1.C @@ -37,7 +37,7 @@ #include "floatmatrix.h" #include "floatarray.h" #include "mathfem.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "sparsemtrx.h" #include "error.h" #include "nonlocalmaterialext.h" @@ -57,21 +57,15 @@ namespace oofem { REGISTER_Material(IDNLMaterial); -IDNLMaterial :: IDNLMaterial(int n, Domain *d) : IsotropicDamageMaterial1(n, d), StructuralNonlocalMaterialExtensionInterface(d), NonlocalMaterialStiffnessInterface() - // - // constructor - // +IDNLMaterial :: IDNLMaterial(int n, Domain *d) : + IsotropicDamageMaterial1(n, d), + StructuralNonlocalMaterialExtensionInterface(d), + NonlocalMaterialStiffnessInterface() {} -IDNLMaterial :: ~IDNLMaterial() -// -// destructor -// -{ } - void -IDNLMaterial :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) +IDNLMaterial :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const { /* Implements the service updating local variables in given integration points, * which take part in nonlocal average process. Actually, no update is necessary, @@ -93,7 +87,7 @@ IDNLMaterial :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussP // compute and store the local variable to be averaged // (typically the local equivalent strain) nlstatus->letTempStrainVectorBe(SDstrainVector); - this->computeLocalEquivalentStrain(equivStrain, SDstrainVector, gp, tStep); + equivStrain = this->computeLocalEquivalentStrain(SDstrainVector, gp, tStep); // nonstandard formulation based on averaging of compliance parameter gamma // note: gamma is stored in a variable named localEquivalentStrainForAverage, which can be misleading @@ -121,9 +115,9 @@ IDNLMaterial :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussP } double -IDNLMaterial :: giveNonlocalMetricModifierAt(GaussPoint *gp) +IDNLMaterial :: giveNonlocalMetricModifierAt(GaussPoint *gp) const { - IDNLMaterialStatus *status = static_cast< IDNLMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< IDNLMaterialStatus * >( this->giveStatus(gp) ); double damage = status->giveTempDamage(); if ( damage == 0. ) { damage = status->giveDamage(); @@ -132,9 +126,9 @@ IDNLMaterial :: giveNonlocalMetricModifierAt(GaussPoint *gp) } void -IDNLMaterial :: computeAngleAndSigmaRatio(double &nx, double &ny, double &ratio, GaussPoint *gp, bool &flag) +IDNLMaterial :: computeAngleAndSigmaRatio(double &nx, double &ny, double &ratio, GaussPoint *gp, bool &flag) const { - IDNLMaterialStatus *status = static_cast< IDNLMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< IDNLMaterialStatus * >( this->giveStatus(gp) ); MaterialMode matMode = gp->giveMaterialMode(); if ( matMode != _PlaneStress ) { //Check if the stress-based approach can be applied OOFEM_ERROR("Stress-based nonlocal averaging is implemented for plane stress only"); @@ -189,7 +183,7 @@ IDNLMaterial :: computeAngleAndSigmaRatio(double &nx, double &ny, double &ratio, double aux = sqrt( ( epsx - epsy ) * ( epsx - epsy ) + gamxy * gamxy ); double e1 = epsx + epsy + aux; // e1 = 2 times the maximum principal strain double e2 = epsx + epsy - aux; // e2 = 2 times the minimum principal strain - const double nu = this->giveLinearElasticMaterial()->give('n', gp); + const double nu = this->linearElasticMaterial->give('n', gp); double s1 = e1 + nu * e2; // s1 = 2*(1-nu*nu)/E times the maximum principal stress double s2 = e2 + nu * e1; // s2 = 2*(1-nu*nu)/E times the minimum principal stress @@ -223,11 +217,11 @@ IDNLMaterial :: computeAngleAndSigmaRatio(double &nx, double &ny, double &ratio, } double -IDNLMaterial :: computeStressBasedWeight(double &nx, double &ny, double &ratio, GaussPoint *gp, GaussPoint *jGp, double weight) +IDNLMaterial :: computeStressBasedWeight(double cl, double &nx, double &ny, double &ratio, GaussPoint *gp, GaussPoint *jGp, double weight) const { // Take into account periodicity, if required if ( this->px > 0. ) { - return computeStressBasedWeightForPeriodicCell(nx, ny, ratio, gp, jGp); + return computeStressBasedWeightForPeriodicCell(cl, nx, ny, ratio, gp, jGp); } //Check if source and receiver point coincide @@ -249,7 +243,7 @@ IDNLMaterial :: computeStressBasedWeight(double &nx, double &ny, double &ratio, double modDistance = sqrt(x1 * x1 + x2 * x2); //Get new weight - double updatedWeight = this->computeWeightFunction(modDistance); + double updatedWeight = this->computeWeightFunction(cl, modDistance); updatedWeight *= jGp->giveElement()->computeVolumeAround(jGp); //weight * (Volume where the weight is applied) return updatedWeight; } @@ -257,7 +251,7 @@ IDNLMaterial :: computeStressBasedWeight(double &nx, double &ny, double &ratio, // This method is a slight modification of IDNLMaterial :: computeStressBasedWeight but is implemented separately, // to keep the basic method as simple (and efficient) as possible double -IDNLMaterial :: computeStressBasedWeightForPeriodicCell(double &nx, double &ny, double &ratio, GaussPoint *gp, GaussPoint *jGp) +IDNLMaterial :: computeStressBasedWeightForPeriodicCell(double cl, double &nx, double &ny, double &ratio, GaussPoint *gp, GaussPoint *jGp) const { double updatedWeight = 0.; FloatArray gpCoords, distance; @@ -278,7 +272,7 @@ IDNLMaterial :: computeStressBasedWeightForPeriodicCell(double &nx, double &ny, double modDistance = sqrt(x1 * x1 + x2 * x2); //Get new weight - double updatedWeightContribution = this->computeWeightFunction(modDistance); + double updatedWeightContribution = this->computeWeightFunction(cl, modDistance); if ( updatedWeightContribution > 0. ) { updatedWeightContribution *= jGp->giveElement()->computeVolumeAround(jGp); //weight * (Volume where the weight is applied) updatedWeight += updatedWeightContribution; @@ -287,8 +281,8 @@ IDNLMaterial :: computeStressBasedWeightForPeriodicCell(double &nx, double &ny, return updatedWeight; } -void -IDNLMaterial :: computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +double +IDNLMaterial :: computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const { double nonlocalContribution, nonlocalEquivalentStrain = 0.0; IDNLMaterialStatus *nonlocStatus, *status = static_cast< IDNLMaterialStatus * >( this->giveStatus(gp) ); @@ -318,8 +312,9 @@ IDNLMaterial :: computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *neargp = lir.nearGp; nonlocStatus = static_cast< IDNLMaterialStatus * >( neargp->giveMaterialStatus() ); nonlocalContribution = nonlocStatus->giveLocalEquivalentStrainForAverage(); + if ( SBAflag ) { //Check if Stress Based Averaging is requested and calculate nonlocal contribution - double stressBasedWeight = computeStressBasedWeight(nx, ny, sigmaRatio, gp, neargp, lir.weight); //Compute new weight + double stressBasedWeight = computeStressBasedWeight(cl, nx, ny, sigmaRatio, gp, neargp, lir.weight); //Compute new weight updatedIntegrationVolume += stressBasedWeight; nonlocalContribution *= stressBasedWeight; } else { @@ -360,7 +355,7 @@ IDNLMaterial :: computeEquivalentStrain(double &kappa, const FloatArray &strain, this->endIPNonlocalAverage(gp); // ??????????????????? - kappa = nonlocalEquivalentStrain; + return nonlocalEquivalentStrain; } Interface * @@ -378,21 +373,11 @@ IDNLMaterial :: giveInterface(InterfaceType type) } -IRResultType -IDNLMaterial :: initializeFrom(InputRecord *ir) +void +IDNLMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = IsotropicDamageMaterial1 :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - result = StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - - return IRRT_OK; + IsotropicDamageMaterial1 :: initializeFrom(ir); + StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); } @@ -403,18 +388,18 @@ IDNLMaterial :: giveInputRecord(DynamicInputRecord &input) StructuralNonlocalMaterialExtensionInterface :: giveInputRecord(input); } -void -IDNLMaterial :: computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *g) +double +IDNLMaterial :: computeDamageParam(double kappa, const FloatArray &strain, GaussPoint *g) const { if ( averagedVar == AVT_Compliance ) { // formulation based on nonlocal gamma (here formally called kappa) - omega = kappa / ( 1. + kappa ); + return kappa / ( 1. + kappa ); } else if ( averagedVar == AVT_Damage ) { // formulation based on nonlocal damage (here formally called kappa) - omega = kappa; + return kappa; } else { // formulation based on nonlocal equivalent strain - omega = damageFunction(kappa, g); + return damageFunction(kappa, g); } } @@ -504,7 +489,7 @@ IDNLMaterial :: NonlocalMaterialStiffnessInterface_showSparseMtrxStructure(Gauss strain = status->giveTempStrainVector(); // compute equivalent strain - this->computeEquivalentStrain(equivStrain, strain, gp, tStep); + equivStrain = this->computeEquivalentStrain(strain, gp, tStep); f = equivStrain - status->giveTempKappa(); if ( ( equivStrain <= e0 ) || ( f < 0.0 ) ) { @@ -584,8 +569,8 @@ IDNLMaterial :: giveLocalNonlocalStiffnessContribution(GaussPoint *gp, IntArray { int nrows, nsize; double sum, f, equivStrain; - IDNLMaterialStatus *status = static_cast< IDNLMaterialStatus * >( this->giveStatus(gp) ); - StructuralElement *elem = static_cast< StructuralElement * >( gp->giveElement() ); + auto status = static_cast< IDNLMaterialStatus * >( this->giveStatus(gp) ); + auto elem = static_cast< StructuralElement * >( gp->giveElement() ); FloatMatrix b, de; FloatArray stress, strain; @@ -602,7 +587,7 @@ IDNLMaterial :: giveLocalNonlocalStiffnessContribution(GaussPoint *gp, IntArray strain = status->giveTempStrainVector(); // compute equivalent strain - this->computeEquivalentStrain(equivStrain, strain, gp, tStep); + equivStrain = this->computeEquivalentStrain(strain, gp, tStep); f = equivStrain - status->giveTempKappa(); if ( ( equivStrain <= e0 ) || ( f < 0.0 ) ) { @@ -733,7 +718,7 @@ IDNLMaterial :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray // if ( gp->giveMaterialMode() != _1dMat ) { - this->giveStressVectorTranformationMtrx(t, princDir, 0); + t = this->giveStressVectorTranformationMtrx(princDir); } // @@ -789,7 +774,7 @@ IDNLMaterial :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray lmat->giveStiffnessMatrix(de, SecantStiffness, gp, tStep); strain = status->giveTempStrainVector(); stress.beProductOf(de, strain); - this->computeLocalEquivalentStrain(equivStrain, strain, gp, tStep); + equivStrain = this->computeLocalEquivalentStrain(strain, gp, tStep); nu = stress; coeff = 1.0 / ( lmat->give('E', gp) * equivStrain ); @@ -819,10 +804,7 @@ IDNLMaterial :: giveNormalElasticStiffnessMatrix(FloatMatrix &answer, { // // return Elastic Stiffness matrix for normal Stresses - LinearElasticMaterial *lMat = this->giveLinearElasticMaterial(); - FloatMatrix de; - - lMat->give3dMaterialStiffnessMatrix(de, rMode, gp, tStep); + auto de = linearElasticMaterial->give3dMaterialStiffnessMatrix(rMode, gp, tStep); // This isn't used? Do we need one with zeroed entries (below) or the general 3d stiffness (above)? //lMat->giveCharacteristicMatrix(de, rMode, gp, tStep); //StructuralMaterial :: giveFullSymMatrixForm( de, deRed, gp->giveMaterialMode()); @@ -837,19 +819,15 @@ IDNLMaterial :: giveNormalElasticStiffnessMatrix(FloatMatrix &answer, } -IDNLMaterialStatus :: IDNLMaterialStatus(int n, Domain *d, GaussPoint *g) : - IsotropicDamageMaterial1Status(n, d, g), StructuralNonlocalMaterialStatusExtensionInterface() +IDNLMaterialStatus :: IDNLMaterialStatus(GaussPoint *g) : + IsotropicDamageMaterial1Status(g), StructuralNonlocalMaterialStatusExtensionInterface() { localEquivalentStrainForAverage = 0.0; } -IDNLMaterialStatus :: ~IDNLMaterialStatus() -{ } - - void -IDNLMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +IDNLMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -891,39 +869,18 @@ IDNLMaterialStatus :: updateYourself(TimeStep *tStep) -contextIOResultType -IDNLMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +IDNLMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // save parent class status - if ( ( iores = IsotropicDamageMaterial1Status :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - + IsotropicDamageMaterial1Status :: saveContext(stream, mode); //if (!stream.write(&localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); - return CIO_OK; } -contextIOResultType -IDNLMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +IDNLMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // read parent class status - if ( ( iores = IsotropicDamageMaterial1Status :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data + IsotropicDamageMaterial1Status :: restoreContext(stream, mode); //if (!stream.read (&localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); - - return CIO_OK; } Interface * diff --git a/src/sm/Materials/ConcreteMaterials/idmnl1.h b/src/sm/Materials/ConcreteMaterials/idmnl1.h index e14352ddb..5a5cb12fc 100644 --- a/src/sm/Materials/ConcreteMaterials/idmnl1.h +++ b/src/sm/Materials/ConcreteMaterials/idmnl1.h @@ -35,8 +35,8 @@ #ifndef idmnl1_h #define idmnl1_h -#include "Materials/ConcreteMaterials/idm1.h" -#include "Materials/structuralnonlocalmaterialext.h" +#include "sm/Materials/ConcreteMaterials/idm1.h" +#include "sm/Materials/structuralnonlocalmaterialext.h" #include "nonlocmatstiffinterface.h" ///@name Input fields for IDNLMaterial @@ -56,7 +56,7 @@ class IDNLMaterialStatus : public IsotropicDamageMaterial1Status, public Structu { protected: /// Equivalent strain for averaging. - double localEquivalentStrainForAverage; + double localEquivalentStrainForAverage = 0.; /* // Variables used to track loading/reloading * public: @@ -66,25 +66,22 @@ class IDNLMaterialStatus : public IsotropicDamageMaterial1Status, public Structu public: /// Constructor. - IDNLMaterialStatus(int n, Domain *d, GaussPoint *g); - /// Destructor. - virtual ~IDNLMaterialStatus(); + IDNLMaterialStatus(GaussPoint *g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; /// Returns the local equivalent strain to be averaged. double giveLocalEquivalentStrainForAverage() { return localEquivalentStrainForAverage; } /// Sets the localEquivalentStrainForAverage to given value. void setLocalEquivalentStrainForAverage(double ls) { localEquivalentStrainForAverage = ls; } - // definition - virtual const char *giveClassName() const { return "IDNLMaterialStatus"; } + const char *giveClassName() const override { return "IDNLMaterialStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; /** * Interface requesting service. @@ -97,7 +94,7 @@ class IDNLMaterialStatus : public IsotropicDamageMaterial1Status, public Structu * returning address of component or using pointer conversion from receiver to base class * NonlocalMaterialStatusExtensionInterface. */ - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; }; @@ -111,19 +108,16 @@ class IDNLMaterial : public IsotropicDamageMaterial1, public StructuralNonlocalM public: /// Constructor IDNLMaterial(int n, Domain *d); - /// Destructor - virtual ~IDNLMaterial(); - // identification and auxiliary functions - virtual const char *giveClassName() const { return "IDNLMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_IDNLMaterial_Name; } + const char *giveClassName() const override { return "IDNLMaterial"; } + const char *giveInputRecordName() const override { return _IFT_IDNLMaterial_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual void computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); + double computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const override; /** * Function used in the Stress based nonlocal variation.In this function the ratio of the first two * eigenvalues is and the angle of the first eigenvector with respect to the horizontal axis is calculated @@ -133,9 +127,10 @@ class IDNLMaterial : public IsotropicDamageMaterial1, public StructuralNonlocalM * @param gp Gauss Point whose nonlocal interactions domain is modified * @param flag showing whether stress based averaging is activated (flag=true).For zero strain states the stress-based averaging is deactivated (flag=false) */ - void computeAngleAndSigmaRatio(double &nx, double &ny, double &ratio, GaussPoint *gp, bool &flag); + void computeAngleAndSigmaRatio(double &nx, double &ny, double &ratio, GaussPoint *gp, bool &flag) const; /** * Function used to compute the new weight based on stress-based averaging. + * @param cl Characteristic length of the nonlocal model * @param nx x-component of the first eigenvector of effective stress. * @param ny y-component of the first eigenvector of effective stress. * @param ratio Value of the ratio of the second over the first eigenvalue of the stress tensor (sigma2/sigma1). @@ -144,36 +139,36 @@ class IDNLMaterial : public IsotropicDamageMaterial1, public StructuralNonlocalM * @param weight Original weight. * @return New weight based on stress-based averaging. */ - double computeStressBasedWeight(double &nx, double &ny, double &ratio, GaussPoint *gp, GaussPoint *jGp, double weight); - double computeStressBasedWeightForPeriodicCell(double &nx, double &ny, double &ratio, GaussPoint *gp, GaussPoint *jGp); + double computeStressBasedWeight(double cl, double &nx, double &ny, double &ratio, GaussPoint *gp, GaussPoint *jGp, double weight) const; + double computeStressBasedWeightForPeriodicCell(double cl, double &nx, double &ny, double &ratio, GaussPoint *gp, GaussPoint *jGp) const; - void computeLocalEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) - { IsotropicDamageMaterial1 :: computeEquivalentStrain(kappa, strain, gp, tStep); } + double computeLocalEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const + { return IsotropicDamageMaterial1 :: computeEquivalentStrain(strain, gp, tStep); } - virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep); + void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const override; /// Compute the factor that specifies how the interaction length should be modified (by eikonal nonlocal damage models) - virtual double giveNonlocalMetricModifierAt(GaussPoint *gp); + double giveNonlocalMetricModifierAt(GaussPoint *gp) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; #ifdef __OOFEG /// Plots the sparse structure of stiffness contribution. - virtual void NonlocalMaterialStiffnessInterface_showSparseMtrxStructure(GaussPoint *gp, oofegGraphicContext &gc, TimeStep *tStep); + void NonlocalMaterialStiffnessInterface_showSparseMtrxStructure(GaussPoint *gp, oofegGraphicContext &gc, TimeStep *tStep) override; #endif - virtual void computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *gp); + double computeDamageParam(double kappa, const FloatArray &strain, GaussPoint *gp) const override; /**@name Services required by NonlocalMaterialStiffnessInterface and related ones to support Nonlocal Stiffness*/ //@{ - virtual void NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx &dest, const UnknownNumberingScheme &s, - GaussPoint *gp, TimeStep *tStep); + void NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx &dest, const UnknownNumberingScheme &s, + GaussPoint *gp, TimeStep *tStep) override; /** * Returns integration list of receiver. Contains localIntegrationRecord structures, containing * references to integration points and their weights that influence to nonlocal average in * receiver's associated integration point. */ - virtual std :: vector< localIntegrationRecord > *NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(GaussPoint *gp); + std :: vector< localIntegrationRecord > *NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(GaussPoint *gp) override; /** * Computes the "local" part of nonlocal stiffness contribution assembled for given integration point. * @param gp Source integration point. @@ -207,16 +202,16 @@ class IDNLMaterial : public IsotropicDamageMaterial1, public StructuralNonlocalM GaussPoint *gp, TimeStep *tStep); //@} - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int estimatePackSize(DataStream &buff, GaussPoint *ip); - virtual double predictRelativeComputationalCost(GaussPoint *gp); - virtual double predictRelativeRedistributionCost(GaussPoint *gp) { return 1.0; } + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int estimatePackSize(DataStream &buff, GaussPoint *ip) override; + double predictRelativeComputationalCost(GaussPoint *gp) override; + double predictRelativeRedistributionCost(GaussPoint *gp) override { return 1.0; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new IDNLMaterialStatus(1, IsotropicDamageMaterial1 :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new IDNLMaterialStatus(gp); } protected: - virtual void initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) { } + void initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) const override { } }; } // end namespace oofem #endif // idmnl1_h diff --git a/src/sm/Materials/ConcreteMaterials/mazarsmodel.C b/src/sm/Materials/ConcreteMaterials/mazarsmodel.C index 6bb3daee8..4173d436c 100644 --- a/src/sm/Materials/ConcreteMaterials/mazarsmodel.C +++ b/src/sm/Materials/ConcreteMaterials/mazarsmodel.C @@ -39,7 +39,7 @@ #include "mathfem.h" #include "datastream.h" #include "contextioerr.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "classfactory.h" namespace oofem { @@ -49,25 +49,15 @@ namespace oofem { REGISTER_Material(MazarsMaterial); MazarsMaterial :: MazarsMaterial(int n, Domain *d) : IsotropicDamageMaterial1(n, d) - // - // constructor - // { // force the loading / unloading control according to max. reached damage level llcriteria = idm_damageLevelCR; } -MazarsMaterial :: ~MazarsMaterial() -// -// destructor -// -{ } - -IRResultType -MazarsMaterial :: initializeFrom(InputRecord *ir) +void +MazarsMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro int ver; // Note: IsotropicDamageMaterial1 :: initializeFrom is not activated @@ -76,13 +66,11 @@ MazarsMaterial :: initializeFrom(InputRecord *ir) // IsotropicDamageMaterial1 :: initializeFrom(ir); this->equivStrainType = EST_Mazars; + this->softType = ST_Mazars; - result = IsotropicDamageMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - result = RandomMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - result = linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) return result; + IsotropicDamageMaterial :: initializeFrom(ir); + RandomMaterialExtensionInterface :: initializeFrom(ir); + linearElasticMaterial->initializeFrom(ir); // E and nu are made available for direct access IR_GIVE_FIELD(ir, E, _IFT_IsotropicLinearElasticMaterial_e); IR_GIVE_FIELD(ir, nu, _IFT_IsotropicLinearElasticMaterial_n); @@ -94,8 +82,7 @@ MazarsMaterial :: initializeFrom(InputRecord *ir) } else if ( ver == 0 ) { this->modelVersion = maz_original; } else { - OOFEM_WARNING("unknown version"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_MazarsMaterial_version, "unknown version"); } IR_GIVE_FIELD(ir, this->e0, _IFT_MazarsMaterial_e0); @@ -121,20 +108,17 @@ MazarsMaterial :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, this->hRefc, _IFT_MazarsMaterial_hrefc); this->mapper.initializeFrom(ir); - - return IRRT_OK; } -void -MazarsMaterial :: computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +double +MazarsMaterial :: computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const { double posNorm = 0.0; FloatArray principalStrains, strainb; if ( strain.isEmpty() ) { - kappa = 0.; - return; + return 0.; } StructuralMaterial :: giveFullSymVectorForm( strainb, strain, gp->giveMaterialMode() ); @@ -173,7 +157,7 @@ MazarsMaterial :: computeEquivalentStrain(double &kappa, const FloatArray &strai } } - kappa = sqrt(posNorm); + return sqrt(posNorm); } /* @@ -200,7 +184,7 @@ MazarsMaterial :: computeEquivalentStrain(double &kappa, const FloatArray &strai */ int -MazarsMaterial :: giveNumberOfSpatialDimensions(GaussPoint *gp) +MazarsMaterial :: giveNumberOfSpatialDimensions(GaussPoint *gp) const { if ( gp->giveMaterialMode() == _1dMat ) { return 1; @@ -212,7 +196,7 @@ MazarsMaterial :: giveNumberOfSpatialDimensions(GaussPoint *gp) } void -MazarsMaterial :: giveNormalBlockOfElasticCompliance(FloatMatrix &answer, GaussPoint *gp) +MazarsMaterial :: giveNormalBlockOfElasticCompliance(FloatMatrix &answer, GaussPoint *gp) const { int ndim = giveNumberOfSpatialDimensions(gp); answer.resize(ndim, ndim); @@ -227,8 +211,8 @@ MazarsMaterial :: giveNormalBlockOfElasticCompliance(FloatMatrix &answer, GaussP } } -void -MazarsMaterial :: computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *gp) +double +MazarsMaterial :: computeDamageParam(double kappa, const FloatArray &strain, GaussPoint *gp) const { // positive_flag = 0, negat_count = 0; FloatMatrix de, ce; @@ -236,8 +220,7 @@ MazarsMaterial :: computeDamageParam(double &omega, double kappa, const FloatArr double gt, gc, alpha_t, alpha_c, alpha, eqStrain2; if ( kappa <= this->e0 ) { // strain below damage threshold - omega = 0.0; - return; + return 0.0; } // strain above damage threshold @@ -354,14 +337,15 @@ MazarsMaterial :: computeDamageParam(double &omega, double kappa, const FloatArr alpha_c = 0.; } - omega = alpha_t * gt + alpha_c * gc; + auto omega = alpha_t * gt + alpha_c * gc; if ( omega > 1.0 ) { omega = 1.0; } + return omega; } // evaluation of tensile damage -double MazarsMaterial :: computeGt(double kappa, GaussPoint *gp) +double MazarsMaterial :: computeGt(double kappa, GaussPoint *gp) const { double gt; if ( hReft <= 0. ) { // material law considered as independent of element size @@ -409,7 +393,7 @@ double MazarsMaterial :: computeGt(double kappa, GaussPoint *gp) } // evaluation of compression damage -double MazarsMaterial :: computeGc(double kappa, GaussPoint *gp) +double MazarsMaterial :: computeGc(double kappa, GaussPoint *gp) const { double gc; if ( hRefc <= 0. ) { // material law considered as independent of element size @@ -441,7 +425,7 @@ double MazarsMaterial :: computeGc(double kappa, GaussPoint *gp) } void -MazarsMaterial :: initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) +MazarsMaterial :: initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) const { int indmin = 1, indmax = 1; double le; @@ -509,50 +493,27 @@ MazarsMaterial :: initDamaged(double kappa, FloatArray &totalStrainVector, Gauss } -MazarsMaterialStatus :: MazarsMaterialStatus(int n, Domain *d, GaussPoint *g) : - IsotropicDamageMaterial1Status(n, d, g) -{ - lec = 0.0; -} +MazarsMaterialStatus :: MazarsMaterialStatus(GaussPoint *g) : + IsotropicDamageMaterial1Status(g) +{} -contextIOResultType -MazarsMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +MazarsMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // save parent class status - if ( ( iores = IsotropicDamageMaterial1Status :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + IsotropicDamageMaterial1Status :: saveContext(stream, mode); - // write a raw data if ( !stream.write(lec) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -MazarsMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +MazarsMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // read parent class status - if ( ( iores = IsotropicDamageMaterial1Status :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + IsotropicDamageMaterial1Status :: restoreContext(stream, mode); - // read raw data if ( !stream.read(lec) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/Materials/ConcreteMaterials/mazarsmodel.h b/src/sm/Materials/ConcreteMaterials/mazarsmodel.h index 5424649fc..80aceaf11 100644 --- a/src/sm/Materials/ConcreteMaterials/mazarsmodel.h +++ b/src/sm/Materials/ConcreteMaterials/mazarsmodel.h @@ -35,9 +35,9 @@ #ifndef mazarsmodel_h #define mazarsmodel_h -#include "Materials/linearelasticmaterial.h" -#include "Materials/ConcreteMaterials/idm1.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/linearelasticmaterial.h" +#include "sm/Materials/ConcreteMaterials/idm1.h" +#include "sm/Materials/structuralms.h" ///@name Input fields for MazarsMaterial //@{ @@ -63,24 +63,21 @@ class MazarsMaterialStatus : public IsotropicDamageMaterial1Status { protected: /// Characteristic element length for compression, fixed as square from element size (for 2d). - double lec; + double lec = 0.; public: /// Constructor. - MazarsMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor. - virtual ~MazarsMaterialStatus() { } + MazarsMaterialStatus(GaussPoint * g); /// Returns characteristic length stored in receiver. double giveLec() { return lec; } /// Sets characteristic length to given value. void setLec(double ls) { lec = ls; } - // definition - virtual const char *giveClassName() const { return "MazarsMaterialStatus"; } + const char *giveClassName() const override { return "MazarsMaterialStatus"; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -96,13 +93,13 @@ class MazarsMaterial : public IsotropicDamageMaterial1 { protected: /// Elastic parameters. - double E, nu; + double E = 0., nu = 0.; /// Model parameters related to the shape of uniaxial stress-strain diagrams. - double At, Bt, Ac, Bc; + double At = 0., Bt = 0., Ac = 0., Bc = 0.; /// Reference elem-length for objectivity. - double hReft, hRefc; + double hReft = 0., hRefc = 0.; /// Beta coefficient reducing the effect of shear; default val = 1.06. - double beta; + double beta = 0.; /// Model variants. enum mazarsModelVariant { maz_original, maz_modTension } modelVersion; @@ -110,19 +107,16 @@ class MazarsMaterial : public IsotropicDamageMaterial1 public: /// Constructor MazarsMaterial(int n, Domain * d); - /// Destructor - virtual ~MazarsMaterial(); - // identification and auxiliary functions - virtual const char *giveInputRecordName() const { return _IFT_MazarsMaterial_Name; } - virtual const char *giveClassName() const { return "MazarsMaterial"; } + const char *giveInputRecordName() const override { return _IFT_MazarsMaterial_Name; } + const char *giveClassName() const override { return "MazarsMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual void computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *gp); + double computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const override; + double computeDamageParam(double kappa, const FloatArray &strain, GaussPoint *gp) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new MazarsMaterialStatus(1, IsotropicDamageMaterial1 :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new MazarsMaterialStatus(gp); } protected: /** @@ -133,7 +127,7 @@ class MazarsMaterial : public IsotropicDamageMaterial1 * @param totalStrainVector Current total strain vector, * @param gp Integration point, */ - virtual void initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp); + void initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) const override; /* * Computes elastic stiffness for normal stress components. * @param answer Result of size (3,3). @@ -147,10 +141,10 @@ class MazarsMaterial : public IsotropicDamageMaterial1 * GaussPoint *gp, TimeStep *tStep); */ - int giveNumberOfSpatialDimensions(GaussPoint *gp); - void giveNormalBlockOfElasticCompliance(FloatMatrix &answer, GaussPoint *gp); - double computeGt(double kappa, GaussPoint *gp); - double computeGc(double kappa, GaussPoint *gp); + int giveNumberOfSpatialDimensions(GaussPoint *gp) const; + void giveNormalBlockOfElasticCompliance(FloatMatrix &answer, GaussPoint *gp) const; + double computeGt(double kappa, GaussPoint *gp) const; + double computeGc(double kappa, GaussPoint *gp) const; }; } // end namespace oofem #endif // mazarsmodel_h diff --git a/src/sm/Materials/ConcreteMaterials/mazarsmodelnl.C b/src/sm/Materials/ConcreteMaterials/mazarsmodelnl.C index 5b4958544..9d70eb8de 100644 --- a/src/sm/Materials/ConcreteMaterials/mazarsmodelnl.C +++ b/src/sm/Materials/ConcreteMaterials/mazarsmodelnl.C @@ -44,35 +44,23 @@ namespace oofem { REGISTER_Material(MazarsNLMaterial); MazarsNLMaterial :: MazarsNLMaterial(int n, Domain *d) : MazarsMaterial(n, d), StructuralNonlocalMaterialExtensionInterface(d) - // - // constructor - // -{ - //linearElasticMaterial = new IsotropicLinearElasticMaterial (n,d); - R = 0.; -} +{} -MazarsNLMaterial :: ~MazarsNLMaterial() -// -// destructor -// -{ } - Interface * MazarsNLMaterial :: giveInterface(InterfaceType type) { if ( type == NonlocalMaterialExtensionInterfaceType ) { return static_cast< StructuralNonlocalMaterialExtensionInterface * >(this); } else { - return NULL; + return nullptr; } } void -MazarsNLMaterial :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) +MazarsNLMaterial :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const { /* Implements the service updating local variables in given integration points, * which take part in nonlocal average process. Actually, no update is necessary, @@ -80,9 +68,9 @@ MazarsNLMaterial :: updateBeforeNonlocAverage(const FloatArray &strainVector, Ga * computation. It is therefore necessary only to store local strain in corresponding status. * This service is declared at StructuralNonlocalMaterial level. */ + auto nlstatus = static_cast< MazarsNLMaterialStatus * >( this->giveStatus(gp) ); FloatArray SDstrainVector; double equivStrain; - MazarsNLMaterialStatus *nlstatus = static_cast< MazarsNLMaterialStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); @@ -92,26 +80,26 @@ MazarsNLMaterial :: updateBeforeNonlocAverage(const FloatArray &strainVector, Ga this->giveStressDependentPartOfStrainVector(SDstrainVector, gp, strainVector, tStep, VM_Total); // compute equivalent strain - this->computeLocalEquivalentStrain(equivStrain, SDstrainVector, gp, tStep); + equivStrain = this->computeLocalEquivalentStrain(SDstrainVector, gp, tStep); nlstatus->setLocalEquivalentStrainForAverage(equivStrain); } -void -MazarsNLMaterial :: computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +double +MazarsNLMaterial :: computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const { - double nonlocalContribution, nonlocalEquivalentStrain = 0.0; - MazarsNLMaterialStatus *nonlocStatus, *status = static_cast< MazarsNLMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MazarsNLMaterialStatus * >( this->giveStatus(gp) ); + double nonlocalEquivalentStrain = 0.0; this->buildNonlocalPointTable(gp); this->updateDomainBeforeNonlocAverage(tStep); // compute nonlocal strain increment first for ( auto &lir: *this->giveIPIntegrationList(gp) ) { - nonlocStatus = static_cast< MazarsNLMaterialStatus * >( this->giveStatus(lir.nearGp) ); - nonlocalContribution = nonlocStatus->giveLocalEquivalentStrainForAverage(); + auto nonlocStatus = static_cast< MazarsNLMaterialStatus * >( this->giveStatus(lir.nearGp) ); + auto nonlocalContribution = nonlocStatus->giveLocalEquivalentStrainForAverage(); nonlocalContribution *= lir.weight; nonlocalEquivalentStrain += nonlocalContribution; @@ -119,18 +107,14 @@ MazarsNLMaterial :: computeEquivalentStrain(double &kappa, const FloatArray &str nonlocalEquivalentStrain *= 1. / status->giveIntegrationScale(); this->endIPNonlocalAverage(gp); // ! - kappa = nonlocalEquivalentStrain; + return nonlocalEquivalentStrain; } -IRResultType -MazarsNLMaterial :: initializeFrom(InputRecord *ir) +void +MazarsNLMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = MazarsMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - result = StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + MazarsMaterial :: initializeFrom(ir); + StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); IR_GIVE_FIELD(ir, R, _IFT_MazarsNLMaterial_r); if ( R < 0.0 ) { @@ -138,17 +122,15 @@ MazarsNLMaterial :: initializeFrom(InputRecord *ir) } this->hReft = this->hRefc = 1.0; - - return IRRT_OK; } double -MazarsNLMaterial :: computeWeightFunction(const FloatArray &src, const FloatArray &coord) +MazarsNLMaterial :: computeWeightFunction(const double R, const FloatArray &src, const FloatArray &coord) const { // Bell shaped function decaying with the distance. - double dist = src.distance(coord); + double dist = distance(src, coord); if ( ( dist >= 0. ) && ( dist <= this->R ) ) { double help = ( 1. - dist * dist / ( R * R ) ); @@ -160,7 +142,7 @@ MazarsNLMaterial :: computeWeightFunction(const FloatArray &src, const FloatArra void -MazarsNLMaterial :: initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) +MazarsNLMaterial :: initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) const { /* * Perfoms initialization, when damage first appear. The Le characteristic length is @@ -175,19 +157,13 @@ MazarsNLMaterial :: initDamaged(double kappa, FloatArray &totalStrainVector, Gau } -MazarsNLMaterialStatus :: MazarsNLMaterialStatus(int n, Domain *d, GaussPoint *g) : - MazarsMaterialStatus(n, d, g), StructuralNonlocalMaterialStatusExtensionInterface() -{ - localEquivalentStrainForAverage = 0.0; -} - - -MazarsNLMaterialStatus :: ~MazarsNLMaterialStatus() -{ } +MazarsNLMaterialStatus :: MazarsNLMaterialStatus(GaussPoint *g) : + MazarsMaterialStatus(g), StructuralNonlocalMaterialStatusExtensionInterface() +{} void -MazarsNLMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +MazarsNLMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -222,40 +198,18 @@ MazarsNLMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -MazarsNLMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +MazarsNLMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = MazarsMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - + MazarsMaterialStatus :: saveContext(stream, mode); //if (!stream.write(&localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); - return CIO_OK; } -contextIOResultType -MazarsNLMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +MazarsNLMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // read parent class status - if ( ( iores = MazarsMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data + MazarsMaterialStatus :: restoreContext(stream, mode); //if (!stream.read (&localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); - - return CIO_OK; } Interface * diff --git a/src/sm/Materials/ConcreteMaterials/mazarsmodelnl.h b/src/sm/Materials/ConcreteMaterials/mazarsmodelnl.h index 23fad657f..572878ece 100644 --- a/src/sm/Materials/ConcreteMaterials/mazarsmodelnl.h +++ b/src/sm/Materials/ConcreteMaterials/mazarsmodelnl.h @@ -36,7 +36,7 @@ #define mazarsmodelnl_h #include "mazarsmodel.h" -#include "Materials/structuralnonlocalmaterialext.h" +#include "sm/Materials/structuralnonlocalmaterialext.h" ///@name Input fields for MazarsNLMaterial //@{ @@ -54,30 +54,26 @@ class MazarsNLMaterialStatus : public MazarsMaterialStatus, public StructuralNon { protected: /// Equivalent strain for averaging. - double localEquivalentStrainForAverage; + double localEquivalentStrainForAverage = 0.; public: /// Constructor - MazarsNLMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~MazarsNLMaterialStatus(); + MazarsNLMaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; /// Returns the local equivalent strain to be averaged. double giveLocalEquivalentStrainForAverage() { return localEquivalentStrainForAverage; } /// Sets the local equivalent strain for average to given value. void setLocalEquivalentStrainForAverage(double ls) { localEquivalentStrainForAverage = ls; } - // definition - virtual const char *giveInputRecordName() const { return _IFT_MazarsNLMaterial_Name; } - virtual const char *giveClassName() const { return "MazarsNLMaterialStatus"; } + const char *giveClassName() const override { return "MazarsNLMaterialStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; /** * Interface requesting service. @@ -90,7 +86,7 @@ class MazarsNLMaterialStatus : public MazarsMaterialStatus, public StructuralNon * returning adress of component or using pointer conversion from receiver to base class * NonlocalMaterialStatusExtension. If no nonlocal extension exists, NULL pointer is returned. */ - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; }; @@ -102,21 +98,18 @@ class MazarsNLMaterial : public MazarsMaterial, public StructuralNonlocalMateria { protected: /// Interaction radius, related to the nonlocal characteristic length of material. - double R; + double R = 0.; public: /// Constructor MazarsNLMaterial(int n, Domain * d); - /// Destructor - virtual ~MazarsNLMaterial(); - // identification and auxiliary functions - virtual const char *giveClassName() const { return "MazarsNLMaterial"; } + const char *giveClassName() const override { return "MazarsNLMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual Interface *giveInterface(InterfaceType it); + void initializeFrom(InputRecord &ir) override; + Interface *giveInterface(InterfaceType it) override; - virtual void computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); + double computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const override; /** * Computes the equivalent local strain measure from given strain vector (full form). * @param[out] kappa Return parameter, containing the corresponding equivalent strain @@ -124,25 +117,25 @@ class MazarsNLMaterial : public MazarsMaterial, public StructuralNonlocalMateria * @param gp Integration point. * @param tStep Time step. */ - void computeLocalEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) - { MazarsMaterial :: computeEquivalentStrain(kappa, strain, gp, tStep); } + double computeLocalEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const + { return MazarsMaterial :: computeEquivalentStrain(strain, gp, tStep); } - virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep); - virtual double computeWeightFunction(const FloatArray &src, const FloatArray &coord); - virtual int hasBoundedSupport() { return 1; } + void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const override; + double computeWeightFunction(const double cl, const FloatArray &src, const FloatArray &coord) const override; + int hasBoundedSupport() const override { return 1; } /** * Determines the width (radius) of limited support of weighting function */ - virtual void giveSupportRadius(double &radius) { radius = this->R; } + virtual double giveSupportRadius() const { return this->R; } - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int estimatePackSize(DataStream &buff, GaussPoint *ip); + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int estimatePackSize(DataStream &buff, GaussPoint *ip) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new MazarsNLMaterialStatus(1, MazarsMaterial :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new MazarsNLMaterialStatus(gp); } protected: - void initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp); + void initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) const override; }; } // end namespace oofem #endif // mazarsmodelnl_h diff --git a/src/sm/Materials/ConcreteMaterials/mplasticmaterial2.C b/src/sm/Materials/ConcreteMaterials/mplasticmaterial2.C index 3ee3607e7..be46da781 100644 --- a/src/sm/Materials/ConcreteMaterials/mplasticmaterial2.C +++ b/src/sm/Materials/ConcreteMaterials/mplasticmaterial2.C @@ -69,8 +69,8 @@ MPlasticMaterial2 :: ~MPlasticMaterial2() } -int -MPlasticMaterial2 :: hasMaterialModeCapability(MaterialMode mode) +bool +MPlasticMaterial2 :: hasMaterialModeCapability(MaterialMode mode) const // // returns whether receiver supports given mode // @@ -87,7 +87,7 @@ MPlasticMaterial2 :: hasMaterialModeCapability(MaterialMode mode) MaterialStatus * MPlasticMaterial2 :: CreateStatus(GaussPoint *gp) const { - return new MPlasticMaterial2Status(1, this->giveDomain(), gp, this->giveSizeOfReducedHardeningVarsVector(gp)); + return new MPlasticMaterial2Status(gp, this->giveSizeOfReducedHardeningVarsVector(gp)); } @@ -151,7 +151,7 @@ MPlasticMaterial2 :: giveRealStressVector(FloatArray &answer, // update state flag - int newState, state = status->giveStateFlag(); + MPlasticMaterial2Status :: state_flag_values newState, state = status->giveStateFlag(); bool yieldFlag = false; for ( int i = 1; i <= nsurf; i++ ) { if ( gamma.at(i) > 0. ) { @@ -188,7 +188,7 @@ MPlasticMaterial2 :: closestPointReturn(FloatArray &answer, const FloatArray &totalStrain, FloatArray &plasticStrainVectorR, FloatArray &strainSpaceHardeningVariables, - TimeStep *tStep) + TimeStep *tStep) const { FloatArray fullStressVector; FloatArray elasticStrainVectorR; @@ -836,7 +836,7 @@ MPlasticMaterial2 :: cuttingPlaneReturn(FloatArray &answer, const FloatArray &totalStrain, FloatArray &plasticStrainVectorR, FloatArray &strainSpaceHardeningVariables, - TimeStep *tStep) + TimeStep *tStep) const { FloatArray elasticStrainVectorR; FloatArray fullStressVector; @@ -1215,7 +1215,7 @@ huhu: //label for goto void MPlasticMaterial2 :: computeReducedStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &strainSpaceHardeningVariables) + const FloatArray &strainSpaceHardeningVariables) const { FloatArray stressGradient; @@ -1229,7 +1229,7 @@ void MPlasticMaterial2 :: computeResidualVector(FloatArray &answer, GaussPoint *gp, const FloatArray &gamma, const IntArray &activeConditionMap, const FloatArray &plasticStrainVectorR, const FloatArray &strainSpaceHardeningVariables, - std :: vector< FloatArray > &gradientVectorR) + std :: vector< FloatArray > &gradientVectorR) const { /* Computes Residual vector for closes point projection algorithm */ @@ -1259,7 +1259,7 @@ MPlasticMaterial2 :: computeResidualVector(FloatArray &answer, GaussPoint *gp, c void MPlasticMaterial2 :: computeTrialStressIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &elasticStrainVectorR, - TimeStep *tStep) + TimeStep *tStep) const { /* Computes the full trial elastic stress vector */ @@ -1280,7 +1280,7 @@ MPlasticMaterial2 :: computeAlgorithmicModuli(FloatMatrix &answer, const FloatArray &gamma, const IntArray &activeConditionMap, const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables) + const FloatArray &strainSpaceHardeningVariables) const { /* returns consistent moduli in reduced form. * stressVector in full form @@ -1335,11 +1335,10 @@ MPlasticMaterial2 :: computeAlgorithmicModuli(FloatMatrix &answer, // ----------------------------------------------------------------------------// -void -MPlasticMaterial2 :: giveConsistentStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrix +MPlasticMaterial2 :: giveConsistentStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { // // returns receiver material matrix for given reached state @@ -1376,8 +1375,9 @@ MPlasticMaterial2 :: giveConsistentStiffnessMatrix(FloatMatrix &answer, // if ( ( status->giveTempStateFlag() == MPlasticMaterial2Status :: PM_Elastic ) || ( status->giveTempStateFlag() == MPlasticMaterial2Status :: PM_Unloading ) ) { - this->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); - return; + FloatMatrix answer; + const_cast(this)->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); + return answer; } // @@ -1486,16 +1486,17 @@ MPlasticMaterial2 :: giveConsistentStiffnessMatrix(FloatMatrix &answer, helpMtrx2.beProductOf(gmatInv, helpMtrx); helpMtrx.beProductOf(consistentModuli, umat); // S U + FloatMatrix answer; answer.beProductOf(helpMtrx, helpMtrx2); // SUGVS answer.negated(); answer.add(consistentModuli); + return answer; } -void -MPlasticMaterial2 :: giveElastoPlasticStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrix +MPlasticMaterial2 :: giveElastoPlasticStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { // // returns receiver material matrix for given reached state @@ -1531,8 +1532,9 @@ MPlasticMaterial2 :: giveElastoPlasticStiffnessMatrix(FloatMatrix &answer, // if ( ( status->giveTempStateFlag() == MPlasticMaterial2Status :: PM_Elastic ) || ( status->giveTempStateFlag() == MPlasticMaterial2Status :: PM_Unloading ) ) { - this->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); - return; + FloatMatrix answer; + const_cast(this)->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); + return answer; } // @@ -1622,9 +1624,11 @@ MPlasticMaterial2 :: giveElastoPlasticStiffnessMatrix(FloatMatrix &answer, helpMtrx.beProductOf(gmatInv, vmat); helpMtrx2.beProductOf(umat, helpMtrx); + FloatMatrix answer; answer.beProductOf(elasticModuli, helpMtrx2); answer.negated(); answer.add(elasticModuli); + return answer; } /* @@ -1656,19 +1660,18 @@ MPlasticMaterial2 :: giveElastoPlasticStiffnessMatrix(FloatMatrix &answer, void MPlasticMaterial2 :: computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { /* Returns elastic moduli in reduced stress-strain space*/ - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); + this->linearElasticMaterial->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); } // overloaded from structural material -void -MPlasticMaterial2 :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +MPlasticMaterial2 :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // // @@ -1685,11 +1688,6 @@ MPlasticMaterial2 :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, // // { - MaterialMode originalMode = gp->giveMaterialMode(); - if ( originalMode != _3dMat ) { - OOFEM_ERROR("Different stressStrain mode encountered"); - } - // we can force 3d response, and we obtain correct 3d tangent matrix, // but in fact, stress integration algorithm will not work // because in stress integration algorithm we are unable to recognize @@ -1700,21 +1698,20 @@ MPlasticMaterial2 :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, // calling GiveMaterailStiffenssMatrix, which imposes constrains correctly. if ( mode == TangentStiffness ) { if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return this->giveElastoPlasticStiffnessMatrix(mode, gp, tStep); } } else { - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->give3dMaterialStiffnessMatrix(mode, gp, tStep); } } -void -MPlasticMaterial2 :: givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +MPlasticMaterial2 :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dPlaneStressMtrx @@ -1726,21 +1723,20 @@ MPlasticMaterial2 :: givePlaneStressStiffMtrx(FloatMatrix &answer, { if ( mode == TangentStiffness ) { if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return this->giveElastoPlasticStiffnessMatrix(mode, gp, tStep); } } else { - this->giveLinearElasticMaterial()->givePlaneStressStiffMtrx(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep); } } -void -MPlasticMaterial2 :: givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<4,4> +MPlasticMaterial2 :: givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // return receiver's 2dPlaneStrainMtrx constructed from @@ -1750,21 +1746,20 @@ MPlasticMaterial2 :: givePlaneStrainStiffMtrx(FloatMatrix &answer, { if ( mode == TangentStiffness ) { if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return this->giveElastoPlasticStiffnessMatrix(mode, gp, tStep); } } else { - this->giveLinearElasticMaterial()->givePlaneStrainStiffMtrx(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlaneStrainStiffMtrx(mode, gp, tStep); } } -void -MPlasticMaterial2 :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<1,1> +MPlasticMaterial2 :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 1dMaterialStiffnessMAtrix @@ -1772,22 +1767,21 @@ MPlasticMaterial2 :: give1dStressStiffMtrx(FloatMatrix &answer, { if ( mode == TangentStiffness ) { if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return this->giveElastoPlasticStiffnessMatrix(mode, gp, tStep); } } else { - this->giveLinearElasticMaterial()->give1dStressStiffMtrx(answer, mode, gp, tStep); + return this->linearElasticMaterial->give1dStressStiffMtrx(mode, gp, tStep); } } -void -MPlasticMaterial2 :: give2dBeamLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<2,2> +MPlasticMaterial2 :: give2dBeamLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dBeamLayerStiffMtrx. // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -1798,22 +1792,21 @@ MPlasticMaterial2 :: give2dBeamLayerStiffMtrx(FloatMatrix &answer, { if ( mode == TangentStiffness ) { if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return this->giveElastoPlasticStiffnessMatrix(mode, gp, tStep); } } else { - this->giveLinearElasticMaterial()->give2dBeamLayerStiffMtrx(answer, mode, gp, tStep); + return this->linearElasticMaterial->give2dBeamLayerStiffMtrx(mode, gp, tStep); } } -void -MPlasticMaterial2 :: givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<5,5> +MPlasticMaterial2 :: givePlateLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dPlateLayerMtrx // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -1824,20 +1817,19 @@ MPlasticMaterial2 :: givePlateLayerStiffMtrx(FloatMatrix &answer, { if ( mode == TangentStiffness ) { if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return this->giveElastoPlasticStiffnessMatrix(mode, gp, tStep); } } else { - this->giveLinearElasticMaterial()->givePlateLayerStiffMtrx(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlateLayerStiffMtrx(mode, gp, tStep); } } -void -MPlasticMaterial2 :: giveFiberStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +MPlasticMaterial2 :: giveFiberStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 1dFiber // (1dFiber ==> sigma_y = sigma_z = tau_yz = 0.) @@ -1848,12 +1840,12 @@ MPlasticMaterial2 :: giveFiberStiffMtrx(FloatMatrix &answer, { if ( mode == TangentStiffness ) { if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return this->giveElastoPlasticStiffnessMatrix(mode, gp, tStep); } } else { - this->giveLinearElasticMaterial()->giveFiberStiffMtrx(answer, mode, gp, tStep); + return this->linearElasticMaterial->giveFiberStiffMtrx(mode, gp, tStep); } } @@ -1883,7 +1875,7 @@ MPlasticMaterial2 :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalSta } long -MPlasticMaterial2 :: getPopulationSignature(IntArray &mask) +MPlasticMaterial2 :: getPopulationSignature(IntArray &mask) const { long val = 0; int size = mask.giveSize(); @@ -1901,7 +1893,7 @@ MPlasticMaterial2 :: getPopulationSignature(IntArray &mask) } int -MPlasticMaterial2 :: testPopulation(long pop) +MPlasticMaterial2 :: testPopulation(long pop) const { if ( populationSet.find(pop) != populationSet.end() ) { return 0; @@ -1911,13 +1903,13 @@ MPlasticMaterial2 :: testPopulation(long pop) } void -MPlasticMaterial2 :: clearPopulationSet() +MPlasticMaterial2 :: clearPopulationSet() const { populationSet.clear(); } void -MPlasticMaterial2 :: addNewPopulation(IntArray &mask) +MPlasticMaterial2 :: addNewPopulation(IntArray &mask) const { long val = getPopulationSignature(mask); populationSet.insert(val); @@ -1925,7 +1917,7 @@ MPlasticMaterial2 :: addNewPopulation(IntArray &mask) int -MPlasticMaterial2 :: getNewPopulation(IntArray &result, IntArray &candidateMask, int degree, int size) +MPlasticMaterial2 :: getNewPopulation(IntArray &result, IntArray &candidateMask, int degree, int size) const { long val = 0; int candDegree = 0, candSize = candidateMask.giveSize(); @@ -2071,22 +2063,14 @@ MPlasticMaterial2 :: getNewPopulation(IntArray &result, IntArray &candidateMask, // SmearedCrackingMaterialStatus Class // -MPlasticMaterial2Status :: MPlasticMaterial2Status(int n, Domain *d, GaussPoint *g, int statusSize) : - StructuralMaterialStatus(n, d, g), plasticStrainVector(), tempPlasticStrainVector(), - strainSpaceHardeningVarsVector(statusSize), tempStrainSpaceHardeningVarsVector(statusSize), - state_flag(MPlasticMaterial2Status :: PM_Elastic), - temp_state_flag(MPlasticMaterial2Status :: PM_Elastic), - damage(0.), - tempDamage(0.), - gamma(), - tempGamma() +MPlasticMaterial2Status :: MPlasticMaterial2Status(GaussPoint *g, int statusSize) : + StructuralMaterialStatus(g), plasticStrainVector(), tempPlasticStrainVector(), + strainSpaceHardeningVarsVector(statusSize), tempStrainSpaceHardeningVarsVector(statusSize) { } -MPlasticMaterial2Status :: ~MPlasticMaterial2Status() -{ } void -MPlasticMaterial2Status :: printOutputAt(FILE *file, TimeStep *tStep) +MPlasticMaterial2Status :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -2160,23 +2144,12 @@ MPlasticMaterial2Status :: updateYourself(TimeStep *tStep) } - - -contextIOResultType -MPlasticMaterial2Status :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +MPlasticMaterial2Status :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralMaterialStatus :: saveContext(stream, mode); - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write a raw data + contextIOResultType iores; if ( ( iores = plasticStrainVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -2196,26 +2169,15 @@ MPlasticMaterial2Status :: saveContext(DataStream &stream, ContextMode mode, voi if ( ( iores = activeConditionMap.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - - return CIO_OK; } - -contextIOResultType -MPlasticMaterial2Status :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +MPlasticMaterial2Status :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: restoreContext(stream, mode); + contextIOResultType iores; if ( ( iores = plasticStrainVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -2224,9 +2186,11 @@ MPlasticMaterial2Status :: restoreContext(DataStream &stream, ContextMode mode, THROW_CIOERR(iores); } - if ( !stream.read(state_flag) ) { + int val; + if ( !stream.read(val) ) { THROW_CIOERR(CIO_IOERR); } + state_flag = (state_flag_values)val; if ( ( iores = gamma.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); @@ -2235,8 +2199,6 @@ MPlasticMaterial2Status :: restoreContext(DataStream &stream, ContextMode mode, if ( ( iores = activeConditionMap.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - - return CIO_OK; // return succes } + } // end namespace oofem diff --git a/src/sm/Materials/ConcreteMaterials/mplasticmaterial2.h b/src/sm/Materials/ConcreteMaterials/mplasticmaterial2.h index 90446c02e..257554da3 100644 --- a/src/sm/Materials/ConcreteMaterials/mplasticmaterial2.h +++ b/src/sm/Materials/ConcreteMaterials/mplasticmaterial2.h @@ -35,13 +35,13 @@ #ifndef mplasticmaterial2_h #define mplasticmaterial2_h -#include "../sm/Materials/structuralmaterial.h" -#include "Materials/linearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/linearelasticmaterial.h" #include "dictionary.h" #include "intarray.h" #include "floatarray.h" #include "floatmatrix.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include #include @@ -82,11 +82,11 @@ class MPlasticMaterial2Status : public StructuralMaterialStatus FloatArray tempStrainSpaceHardeningVarsVector; /// Yield function status indicator. - int state_flag; - int temp_state_flag; + state_flag_values state_flag = MPlasticMaterial2Status :: PM_Elastic; + state_flag_values temp_state_flag = MPlasticMaterial2Status :: PM_Elastic; /// Isotropic damage variables - double damage, tempDamage; + double damage = 0., tempDamage = 0.; /// Consistency parameter values (needed for algorithmic stiffness). FloatArray gamma, tempGamma; @@ -94,16 +94,15 @@ class MPlasticMaterial2Status : public StructuralMaterialStatus IntArray activeConditionMap, tempActiveConditionMap; public: - MPlasticMaterial2Status(int n, Domain * d, GaussPoint * g, int statusSize); - virtual ~MPlasticMaterial2Status(); + MPlasticMaterial2Status(GaussPoint * g, int statusSize); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; /// Returns the equilibrated strain vector. const FloatArray & givePlasticStrainVector() const { return plasticStrainVector; } @@ -123,17 +122,16 @@ class MPlasticMaterial2Status : public StructuralMaterialStatus double giveDamage() { return damage; } double giveTempDamage() { return tempDamage; } - int giveStateFlag() { return state_flag; } - int giveTempStateFlag() { return temp_state_flag; } - void letTempStateFlagBe(int v) { temp_state_flag = v; } + state_flag_values giveStateFlag() { return state_flag; } + state_flag_values giveTempStateFlag() { return temp_state_flag; } + void letTempStateFlagBe(state_flag_values v) { temp_state_flag = v; } const IntArray &giveTempActiveConditionMap() { return tempActiveConditionMap; } void setTempActiveConditionMap(IntArray v) { tempActiveConditionMap = std :: move(v); } const FloatArray &giveTempGamma() { return tempGamma; } void setTempGamma(FloatArray v) { tempGamma = std :: move(v); } - // definition - virtual const char *giveClassName() const { return "MPlasticMaterial2Status"; } + const char *giveClassName() const override { return "MPlasticMaterial2Status"; } }; /** @@ -187,90 +185,94 @@ class MPlasticMaterial2 : public StructuralMaterial /// Flag indicating whether iterative update of a set of active yield conditions takes place. bool iterativeUpdateOfActiveConds; /// Set for keeping record of generated populations of active yield conditions during return. - std :: set< long >populationSet; + mutable std :: set< long >populationSet; // FIXME: Race condition when threaded. public: MPlasticMaterial2(int n, Domain * d); virtual ~MPlasticMaterial2(); - // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 1; } - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual const char *giveClassName() const { return "MPlasticMaterial2"; } + bool hasMaterialModeCapability(MaterialMode mode) const override; + const char *giveClassName() const override { return "MPlasticMaterial2"; } /// Returns reference to undamaged (bulk) material LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return true; } + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return true; } - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) + FloatArrayF<6> giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override { double alpha = this->linearElasticMaterial->give(tAlpha, gp); - answer = {alpha, alpha, alpha, 0, 0, 0}; + return {alpha, alpha, alpha, 0., 0., 0.}; } - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &strain, TimeStep *tStep) override; - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *, - const FloatArray &, TimeStep *); - - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<4> giveRealStressVector_PlaneStrain(const FloatArrayF<4> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } virtual double computeDamage(GaussPoint *gp, const FloatArray &strainSpaceHardeningVariables, TimeStep *tStep); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; // auxiliary functions - virtual int giveSizeOfFullHardeningVarsVector() { return 0; } + virtual int giveSizeOfFullHardeningVarsVector() const { return 0; } virtual int giveSizeOfReducedHardeningVarsVector(GaussPoint *) const { return 0; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: - virtual int giveMaxNumberOfActiveYieldConds(GaussPoint *gp) = 0; + virtual int giveMaxNumberOfActiveYieldConds(GaussPoint *gp) const = 0; void closestPointReturn(FloatArray &answer, IntArray &activeConditionMap, FloatArray &gamma, GaussPoint *gp, const FloatArray &totalStrain, FloatArray &plasticStrainR, - FloatArray &strainSpaceHardeningVariables, TimeStep *tStep); + FloatArray &strainSpaceHardeningVariables, TimeStep *tStep) const; void cuttingPlaneReturn(FloatArray &answer, IntArray &activeConditionMap, FloatArray &gamma, GaussPoint *gp, const FloatArray &totalStrain, FloatArray &plasticStrainR, - FloatArray &strainSpaceHardeningVariables, TimeStep *tStep); + FloatArray &strainSpaceHardeningVariables, TimeStep *tStep) const; // add here some auxiliary functions if needed /* void computeGradientVector (FloatArray& answer, functType ftype, int isurf, GaussPoint* gp, const FloatArray& fullStressVector, * const FloatArray& fullStressSpaceHardeningVars);*/ void computeResidualVector(FloatArray &answer, GaussPoint *gp, const FloatArray &gamma, const IntArray &activeConditionMap, const FloatArray &plasticStrainVectorR, - const FloatArray &strainSpaceHardeningVariables, std :: vector< FloatArray > &gradVec); - virtual void giveConsistentStiffnessMatrix(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); + const FloatArray &strainSpaceHardeningVariables, std :: vector< FloatArray > &gradVec) const; + virtual FloatMatrix giveConsistentStiffnessMatrix(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const; - virtual void giveElastoPlasticStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + virtual FloatMatrix giveElastoPlasticStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; void computeAlgorithmicModuli(FloatMatrix &answer, GaussPoint *gp, const FloatMatrix &elasticModuliInverse, const FloatArray &gamma, const IntArray &activeConditionMap, const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables); + const FloatArray &strainSpaceHardeningVariables) const; /*void computeDiagModuli(FloatMatrix& answer, * GaussPoint *gp, FloatMatrix &elasticModuliInverse, @@ -278,13 +280,13 @@ class MPlasticMaterial2 : public StructuralMaterial /// Computes the value of yield function. virtual double computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, - const FloatArray &strainSpaceHardeningVariables) = 0; + const FloatArray &strainSpaceHardeningVariables) const = 0; /// Computes the stress gradient of yield/loading function (df/d_sigma). virtual void computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &strainSpaceHardeningVariables) = 0; + const FloatArray &strainSpaceHardeningVariables) const = 0; void computeReducedStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &strainSpaceHardeningVariables); + const FloatArray &strainSpaceHardeningVariables) const; /** * Computes the increment of strain-space hardening variables. @@ -297,12 +299,12 @@ class MPlasticMaterial2 : public StructuralMaterial */ virtual void computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &stress, const FloatArray &dlambda, - const FloatArray &dplasticStrain, const IntArray &activeConditionMap) = 0; + const FloatArray &dplasticStrain, const IntArray &activeConditionMap) const = 0; /** * Computes the derivative of yield/loading function with respect to @f$ \kappa @f$ vector */ virtual void computeKGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables) = 0; + const FloatArray &strainSpaceHardeningVariables) const = 0; /** * Computes derivative of @f$ \kappa @f$ vector with respect to stress @@ -310,27 +312,27 @@ class MPlasticMaterial2 : public StructuralMaterial virtual void computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, GaussPoint *gp, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, - const FloatArray &gamma) = 0; + const FloatArray &gamma) const = 0; /// computes derivative of @f$ \kappa @f$ vector with respect to lambda vector virtual void computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPoint *gp, int actSurf, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, - const FloatArray &gamma) = 0; + const FloatArray &gamma) const = 0; /** * Indicates, whether receiver model has hardening/softening behavior or behaves according to perfect plasticity theory. */ - virtual int hasHardening() = 0; + virtual int hasHardening() const = 0; /* virtual void computeReducedGradientMatrix (FloatMatrix& answer, int isurf, * GaussPoint *gp, * const FloatArray& stressVector, * const FloatArray& stressSpaceHardeningVars) = 0;*/ /// Computes second derivative of loading function with respect to stress. virtual void computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables) = 0; + const FloatArray &strainSpaceHardeningVariables) const = 0; /// Computes second derivative of loading function with respect to stress and hardening vars virtual void computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables) = 0; + const FloatArray &strainSpaceHardeningVariables) const = 0; /** * Computes full-space trial stress increment (elastic). @@ -340,44 +342,26 @@ class MPlasticMaterial2 : public StructuralMaterial * @param tStep Solution step. */ virtual void computeTrialStressIncrement(FloatArray &answer, GaussPoint *gp, - const FloatArray &strainIncrement, TimeStep *tStep); + const FloatArray &strainIncrement, TimeStep *tStep) const; virtual void computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep); + TimeStep *tStep) const; //virtual void compute3dElasticModuli(FloatMatrix& answer, GaussPoint *gp, // TimeStep *tStep) = 0; // next functions overloaded rom structural material level - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); - virtual void give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); - virtual void give2dBeamLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); - virtual void givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void giveFiberStiffMtrx(FloatMatrix &answer, - MatResponseMode, GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<2,2> give2dBeamLayerStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<5,5> givePlateLayerStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> giveFiberStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; protected: - long getPopulationSignature(IntArray &mask); - int testPopulation(long pop); - void clearPopulationSet(); - void addNewPopulation(IntArray &mask); - int getNewPopulation(IntArray &result, IntArray &candidateMask, int degree, int size); + long getPopulationSignature(IntArray &mask) const; + int testPopulation(long pop) const; + void clearPopulationSet() const; + void addNewPopulation(IntArray &mask) const; + int getNewPopulation(IntArray &result, IntArray &candidateMask, int degree, int size) const; }; } // end namespace oofem #endif // mplasticmaterial2_h diff --git a/src/sm/Materials/HyperelasticMaterials/basehyperelasticmaterial.C b/src/sm/Materials/HyperelasticMaterials/basehyperelasticmaterial.C new file mode 100644 index 000000000..232d837cc --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/basehyperelasticmaterial.C @@ -0,0 +1,78 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2020 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "basehyperelasticmaterial.h" +#include "dynamicinputrecord.h" + +namespace oofem { +Tensor2_3d +BaseHyperElasticMaterial::compute_dVolumetricEnergy_dF(const Tensor2_3d &F) const + +{ + // compute jacobian and its logarithm + Tensor2_3d dVolumetricEnergy_dF; + if ( VET_Type == VET_Logarithmic ) { + auto J = F.compute_determinant(); + auto lnJ = log(J); + dVolumetricEnergy_dF(i_3, j_3) = K * lnJ / J * this->compute_dJ_dF(F)(i_3, j_3); + } + return dVolumetricEnergy_dF; +} + + +Tensor4_3d +BaseHyperElasticMaterial::compute_d2VolumetricEnergy_dF2(const Tensor2_3d &F) const +{ + // compute jacobian and its logarithm + + Tensor4_3d d2VolumetricEnergy_dF2; + if ( VET_Type == VET_Logarithmic ) { + auto [ J, cofF ] = F.compute_determinant_and_cofactor(); + auto lnJ = log(J); + d2VolumetricEnergy_dF2(i_3, j_3, k_3, l_3) = K * ( 1. - lnJ ) / J / J * cofF(i_3, j_3) * cofF(k_3, l_3) + K * lnJ / J * F.compute_tensor_cross_product()(i_3, j_3, k_3, l_3); + } + return d2VolumetricEnergy_dF2; +} + + + + +void +BaseHyperElasticMaterial::initializeFrom(InputRecord &ir) +{ + // volumetric energy constant, usually bulk modulus + IR_GIVE_FIELD(ir, K, _IFT_BaseHyperElasticMaterial_k); + //IR_GIVE_OPTIONAL_FIELD(ir, type, _IFT_BaseHyperElasticMaterial_type) +} +} // end namespace oofem diff --git a/src/sm/Materials/HyperelasticMaterials/basehyperelasticmaterial.h b/src/sm/Materials/HyperelasticMaterials/basehyperelasticmaterial.h new file mode 100644 index 000000000..1ceba9c80 --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/basehyperelasticmaterial.h @@ -0,0 +1,361 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "dynamicinputrecord.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "mathfem.h" +#include "tensor/tensor2.h" +#include "tensor/tensor4.h" + +#pragma once + + +///@name Input fields for VolumetricEnergyInterface +//@{ +#define _IFT_BaseHyperElasticMaterial_k "k" +#define _IFT_BaseHyperElasticMaterial "type" +//@} + + +namespace oofem { +class InputRecord; +/** + * Abstract base class for hyperelastic materials + * It provides calculation of first and second derivative of principal invariants of the left Cauchy green tensor with respect to deformation gradient + * It provides calculation of volumetric energy(currently only a logarithmic form is supported) + * All the calculations are based on the oofemlib/tensor/tensoralgebra.h file which uses FTensor library + * More to be added gradually + * @author Martin Horak + **/ + +class OOFEM_EXPORT BaseHyperElasticMaterial +{ +protected: + /** + * Type characterizing the volumetric energy of the hyperelastic material + * Type 0: Logarithmic \f$W(J) = 0.5 * K * (ln J)^2 \f$ + * More types can be added ... + * + * @author Martin Horak + **/ + enum VolumetricEnergyType { + VET_Logarithmic = 0 + }; + /// Bulk modulus + double K = 0; + /// volumetric energy type + VolumetricEnergyType VET_Type = VET_Logarithmic; + + +public: + + BaseHyperElasticMaterial() {; } + ~BaseHyperElasticMaterial() {; } + + /// initialization for the input file + void initializeFrom(InputRecord &ir); + + /** + * Compute the first invariant of Cauchy-Green deformation tensor C + * @param Deformation gradient (second-order tensor in 3d) + * @return Trace of Cauchy-Green deformation tensor C + **/ + inline double compute_I1_C_from_F(const Tensor2_3d &F) const + { + return ( F(k_3, 0) * F(k_3, 0) + F(k_3, 1) * F(k_3, 1) + F(k_3, 2) * F(k_3, 2) ); + } + + /** + * Compute the second invariant of Cauchy-Green deformation tensor C + * @param Deformation gradient (second-order tensor in 3d) + * @return The second invariant of Cauchy-Green deformation tensor C + **/ + + inline double compute_I2_C_from_F(const Tensor2_3d &F) const + { + return ( 0.5 * ( ( F(k_3, 0) * F(k_3, 0) + F(k_3, 1) * F(k_3, 1) + F(k_3, 2) * F(k_3, 2) ) * ( F(k_3, 0) * F(k_3, 0) + F(k_3, 1) * F(k_3, 1) + F(k_3, 2) * F(k_3, 2) ) - F(k_3, 0) * F(k_3, l_3) * F(m_3, l_3) * F(m_3, 0) - F(k_3, 1) * F(k_3, l_3) * F(m_3, l_3) * F(m_3, 1) - F(k_3, 2) * F(k_3, l_3) * F(m_3, l_3) * F(m_3, 2) ) ); + } + + + /** + * Compute the third invariant of Cauchy-Green deformation tensor C + * @param Deformation gradient (second-order tensor in 3d) + * @return Determinant of Cauchy-Green deformation tensor C + **/ + inline double compute_I3_C_from_F(const Tensor2_3d &F) const + { + double J = F.compute_determinant(); + return ( J * J ); + } + + /** + * Compute the first invariant of Cauchy-Green deformation tensor C + * @param Cauchy-Green deformation tensor C(second-order tensor in 3d) + * @return Trace of Cauchy-Green deformation tensor C + **/ + inline double compute_I1_C_from_C(const Tensor2_3d &C) const + { + return C(i_3, i_3); + } + + /** + * Compute the second invariant of Cauchy-Green deformation tensor C + * @param Cauchy-Green deformation tensor C(second-order tensor in 3d) + * @return The second invariant of Cauchy-Green deformation tensor C + **/ + inline double compute_I2_C_from_C(const Tensor2_3d &C) const + { + double trC = C(i_3, i_3); + return ( 0.5 * ( trC * trC - ( C(k_3, 0) * C(k_3, 0) + C(k_3, 1) * C(k_3, 1) + C(k_3, 2) * C(k_3, 2) ) ) ); + } + + /** + * Compute the third of Cauchy-Green deformation tensor C + * @param Cauchy-Green deformation tensor C(second-order tensor in 3d) + * @return Determinant of Cauchy-Green deformation tensor C + **/ + inline double compute_I3_C_from_C(const Tensor2_3d &C) const + { + double J2 = C.compute_determinant(); + return J2; + } + + + /** + * Compute the first derivative of the first invariant of the Cauchy-Green deformation tensor C wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return first derivative of the Cauchy-Green deformation tensor C wrt deformation gradient F(second-order tensor in 3d) + **/ + inline Tensor2_3d compute_dI1_C_dF(const Tensor2_3d &F) const + { + Tensor2_3d dI1_C_dF; + dI1_C_dF(i_3, j_3) = 2. * F(i_3, j_3); + return dI1_C_dF; + } + + + /** + * Compute the first derivative of the second invariant of the Cauchy-Green deformation tensor C wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return first derivative of the second invariant of the Cauchy-Green deformation tensor C wrt deformation gradient F(second-order tensor in 3d) + **/ + inline Tensor2_3d compute_dI2_C_dF(const Tensor2_3d &F) const + { + Tensor2_3d dI2_C_dF; + dI2_C_dF(i_3, j_3) = 2. * ( F(k_3, 0) * F(k_3, 0) + F(k_3, 1) * F(k_3, 1) + F(k_3, 2) * F(k_3, 2) ) * F(i_3, j_3) - 2. * F(i_3, m_3) * F(k_3, m_3) * F(k_3, j_3); + return dI2_C_dF; + } + + + + /** + * Compute the first derivative of the third invariant of the Cauchy-Green deformation tensor C wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return first derivative of the third invariant of the Cauchy-Green deformation tensor C wrt deformation gradient F(second-order tensor in 3d) + **/ + inline Tensor2_3d compute_dI3_C_dF(const Tensor2_3d &F) const + { + auto [ detF, cofF ] = F.compute_determinant_and_cofactor(); + Tensor2_3d dI3_C_dF; + dI3_C_dF(i_3, j_3) = 2. * detF * cofF(i_3, j_3); + return dI3_C_dF; + } + + + /** + * Compute the first derivative of the Jacobian(determinant of F) wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return the first derivative of the Jacobian(determinant of F) wrt deformation gradient F (second-order tensor in 3d) + **/ + inline Tensor2_3d compute_dJ_dF(const Tensor2_3d &F) const + { + return F.compute_cofactor(); + } + + + /** + * Compute the second derivative of the first invariant of the Cauchy-Green deformation tensor wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return the second derivative of the first invariant of the Cauchy-Green deformation tensor wrt deformation gradient F (fourth-order tensor in 3d) + **/ + inline Tensor4_3d compute_d2I1_C_dF2(const Tensor2_3d &F) const + { + Tensor2_3d I(1.0, 0., 0., 0., 1.0, 0., 0., 0., 1.0); + Tensor4_3d d2I1_C_dF2; + d2I1_C_dF2(i_3, j_3, k_3, l_3) = 2. * I(i_3, k_3) * I(j_3, l_3); + return d2I1_C_dF2; + } + + /** + * Compute the second derivative of the second invariant of the Cauchy-Green deformation tensor wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return the second derivative of the second invariant of the Cauchy-Green deformation tensor wrt deformation gradient F (fourth-order tensor in 3d) + **/ + inline Tensor4_3d compute_d2I2_C_dF2(const Tensor2_3d &F) const + { + Tensor2_3d I(1.0, 0., 0., 0., 1.0, 0., 0., 0., 1.0); + Tensor4_3d d2I2_C_dF2; + d2I2_C_dF2(i_3, j_3, k_3, l_3) = 4. * F(i_3, j_3) * F(k_3, l_3) - 2. * F(i_3, l_3) * F(k_3, j_3) + 2. * ( F(m_3, 0) * F(m_3, 0) + F(m_3, 1) * F(m_3, 1) + F(m_3, 2) * F(m_3, 2) ) * I(i_3, k_3) * I(j_3, l_3) - 2. * F(m_3, l_3) * F(m_3, j_3) * I(i_3, k_3) - 2. * F(i_3, m_3) * F(k_3, m_3) * I(j_3, l_3); + return d2I2_C_dF2; + } + + + + /** + * Compute the second derivative of the third invariant of the Cauchy-Green deformation tensor wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return the second derivative of the third invariant of the Cauchy-Green deformation tensor wrt deformation gradient F (fourth-order tensor in 3d) + **/ + inline Tensor4_3d compute_d2I3_C_dF2(const Tensor2_3d &F) const + { + auto [ detF, cofF ] = F.compute_determinant_and_cofactor(); + Tensor4_3d d2I3_C_dF2; + d2I3_C_dF2(i_3, j_3, k_3, l_3) = 2. * cofF(i_3, j_3) * cofF(k_3, l_3) + 2 * detF * F.compute_tensor_cross_product()(i_3, j_3, k_3, l_3); + return d2I3_C_dF2; + } + + /** + * Compute the first invariant of the deviatoric Cauchy-Green deformation tensor C + * @param Deformation gradient (second-order tensor in 3d) + * @return Trace of the deviatoric Cauchy-Green deformation tensor C + **/ + inline double compute_I1_Cdev_from_F(const Tensor2_3d &F) const + { + return pow(F.compute_determinant(), -2. / 3.) * compute_I1_C_from_F(F); + } + + /** + * Compute the second invariant of the deviatoric Cauchy-Green deformation tensor C + * @param Deformation gradient (second-order tensor in 3d) + * @return Second invariant of the deviatoric Cauchy-Green deformation tensor C + **/ + inline double compute_I2_Cdev_from_F(const Tensor2_3d &F) const + { + return pow(F.compute_determinant(), -4. / 3.) * compute_I2_C_from_F(F); + } + + + /** + * Compute the first derivatiove of the first invariant of the deviatoric Cauchy-Green deformation tensor C wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return first derivatiove of the first invariant of the deviatoric Cauchy-Green deformation tensor C (second-order tensor) + **/ + inline Tensor2_3d compute_dI1_Cdev_dF(const Tensor2_3d &F) const + { + Tensor2_3d dI1_Cdev_dF; + auto [ J, cofF ] = F.compute_determinant_and_cofactor(); + dI1_Cdev_dF(i_3, j_3) = 2. * pow(J, -2. / 3.) * ( F(i_3, j_3) - compute_I1_C_from_F(F) / ( 3. * J ) * cofF(i_3, j_3) ); + return dI1_Cdev_dF; + } + + /** + * Compute the first derivatiove of the second invariant of the deviatoric Cauchy-Green deformation tensor C wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return first derivatiove of the second invariant of the deviatoric Cauchy-Green deformation tensor C (second-order tensor) + **/ + inline Tensor2_3d compute_dI2_Cdev_dF(const Tensor2_3d &F) const + { + Tensor2_3d iF, dI2_Cdev_dF, C; + auto [ J, cofF ] = F.compute_determinant_and_cofactor(); + C(i_3, j_3) = F(k_3, i_3) * F(k_3, j_3); + auto I2 = compute_I2_C_from_C(C); + + dI2_Cdev_dF(i_3, j_3) = 2. * pow(F.compute_determinant(), -4. / 3.) * ( C(k_3, k_3) * F(i_3, j_3) - F(i_3, k_3) * C(k_3, j_3) - 2. * I2 / ( 3. * J ) * cofF(i_3, j_3) ); + return dI2_Cdev_dF; + } + + /** + * Compute the second derivatiove of the first invariant of the deviatoric Cauchy-Green deformation tensor C wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return second derivatiove of the first invariant of the deviatoric Cauchy-Green deformation tensor C (fourth-order tensor) + **/ + inline Tensor4_3d compute_d2I1_Cdev_dF2(const Tensor2_3d &F) const + { + Tensor2_3d I(1.0, 0., 0., 0., 1.0, 0., 0., 0., 1.0); + auto I1 = compute_I1_C_from_F(F); + auto iF = F.compute_inverse(); + Tensor4_3d d2I1_Cdev_dF2; + d2I1_Cdev_dF2(i_3, j_3, k_3, l_3) = 2. / 3. * pow(F.compute_determinant(), -2. / 3.) * ( 3. * I(i_3, k_3) * I(j_3, l_3) + I1 * iF(j_3, k_3) * iF(l_3, i_3) + 2. / 3. * I1 * iF(j_3, i_3) * iF(l_3, k_3) - 2. * iF(l_3, k_3) * F(i_3, j_3) - 2. * iF(j_3, i_3) * F(k_3, l_3) ); + return d2I1_Cdev_dF2; + } + + /** + * Compute the second derivatiove of the second invariant of the deviatoric Cauchy-Green deformation tensor C wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return Second derivative of the second invariant of the deviatoric Cauchy-Green deformation tensor C (second-order tensor) + **/ + inline Tensor4_3d compute_d2I2_Cdev_dF2(const Tensor2_3d &F) const + { + Tensor2_3d I(1.0, 0., 0., 0., 1.0, 0., 0., 0., 1.0); + auto [ J, cofF ] = F.compute_determinant_and_cofactor(); + auto J_43 = pow(J, -4. / 3.); + Tensor2_3d iF, C, B, FC; + iF(i_3, j_3) = cofF(j_3, i_3) / J; + C(i_3, j_3) = F(k_3, i_3) * F(k_3, j_3); + B(i_3, j_3) = F(i_3, k_3) * F(j_3, k_3); + FC(i_3, j_3) = F(i_3, k_3) * C(k_3, j_3); + auto I1 = compute_I1_C_from_C(C); + auto I2 = compute_I2_C_from_C(C); + Tensor4_3d d2I2_Cdev_dF2; + d2I2_Cdev_dF2(i_3, j_3, k_3, l_3) = 2. * J_43 * ( I1 * I(i_3, k_3) * I(j_3, l_3) + 2. * F(i_3, j_3) * F(k_3, l_3) - 4. / 3. * I1 * F(i_3, j_3) * iF(l_3, k_3) + 8. / 9. * I2 * iF(j_3, i_3) * iF(l_3, k_3) - 4. / 3. * I1 * iF(j_3, i_3) * F(k_3, l_3) + 4. / 3. * FC(k_3, l_3) * iF(j_3, i_3) + 2. / 3. * I2 * iF(j_3, k_3) * iF(l_3, i_3) + 4. / 3. * FC(i_3, j_3) * iF(l_3, k_3) - C(l_3, j_3) * I(i_3, k_3) - F(i_3, l_3) * F(k_3, j_3) - B(i_3, k_3) * I(l_3, j_3) ); + return d2I2_Cdev_dF2; + } + + + /** + * Compute the second derivative of the jacobian(determinant of the deformation gradient) wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return second derivative of the jacobian(determinant of the deformation gradient (fourth-order tensor) + **/ + inline Tensor4_3d compute_d2J_dF2(const Tensor2_3d &F) const + { + return F.compute_tensor_cross_product(); + } + + /** + * Compute the first derivative of the volumetric energy wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return the first derivative of the volumetric energy (second-order tensor) + **/ + Tensor2_3d compute_dVolumetricEnergy_dF(const Tensor2_3d &F) const; + + /** + * Compute the second derivative of the volumetric energy wrt deformation gradient F + * @param Deformation gradient (second-order tensor in 3d) + * @return the second derivative of the volumetric energy (fourth-order tensor) + **/ + Tensor4_3d compute_d2VolumetricEnergy_dF2(const Tensor2_3d &F) const; +}; +} // end namespace oofem diff --git a/src/sm/Materials/HyperelasticMaterials/blatzkomaterial.C b/src/sm/Materials/HyperelasticMaterials/blatzkomaterial.C new file mode 100644 index 000000000..878d8498f --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/blatzkomaterial.C @@ -0,0 +1,94 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2020 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "blatzkomaterial.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_Material(BlatzKoMaterial); + + +void +BlatzKoMaterial::initializeFrom(InputRecord &ir) +{ + StructuralMaterial::initializeFrom(ir); + IR_GIVE_FIELD(ir, mu, _IFT_BlatzKoMaterial_mu); +} + + +FloatMatrixF< 9, 9 > +BlatzKoMaterial::give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + //retrieve deformation from status and convert to matrix form + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + + FloatArrayF< 9 >vF(status->giveTempFVector() ); + Tensor2_3d F(vF); + + double I2 = compute_I2_C_from_F(F); + double I3 = compute_I3_C_from_F(F); + + Tensor2_3d dI2_dF = compute_dI2_C_dF(F); + Tensor2_3d dI3_dF = compute_dI3_C_dF(F); + + Tensor4_3d A; + A(i_3, j_3, k_3, l_3) = 0.5 * mu / I3 * ( compute_d2I2_C_dF2(F)(i_3, j_3, k_3, l_3) - 1. / I3 * ( dI2_dF(i_3, j_3) * dI3_dF(k_3, l_3) + dI3_dF(i_3, j_3) * dI2_dF(k_3, l_3) ) + ( sqrt(I3) - I2 / I3 ) * compute_d2I3_C_dF2(F)(i_3, j_3, k_3, l_3) + ( 2. * I2 / I3 / I3 - 0.5 / sqrt(I3) ) * dI3_dF(i_3, j_3) * dI3_dF(k_3, l_3) ); + + return A.to_voigt_form(); +} + +FloatArrayF< 9 > +BlatzKoMaterial::giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const +{ + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + // compute the first Piola-Kirchhoff + Tensor2_3d F(vF), P; + double I2 = compute_I2_C_from_F(F); + double I3 = compute_I3_C_from_F(F); + P(i_3, j_3) = 0.5 * mu * ( compute_dI2_C_dF(F)(i_3, j_3) / I3 + ( 1. / sqrt(I3) - I2 / I3 / I3 ) * compute_dI3_C_dF(F)(i_3, j_3) ); + // + auto vP = P.to_voigt_form(); + // update gp + status->letTempFVectorBe(vF); + status->letTempPVectorBe(vP); + return vP; +} + +MaterialStatus * +BlatzKoMaterial::CreateStatus(GaussPoint *gp) const +{ + return new StructuralMaterialStatus(gp); +} +}; diff --git a/src/sm/Materials/HyperelasticMaterials/blatzkomaterial.h b/src/sm/Materials/HyperelasticMaterials/blatzkomaterial.h new file mode 100644 index 000000000..b918e58dd --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/blatzkomaterial.h @@ -0,0 +1,86 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2020 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef blatzkomaterial_h +#define blatzkomaterial_h + +#include "../sm/Materials/structuralmaterial.h" +#include "../sm/Materials/structuralms.h" +#include "basehyperelasticmaterial.h" + + +///@name Input fields for MooneyRivlinMaterial +//@{ +#define _IFT_BlatzKoMaterial_Name "blatzkomat" +#define _IFT_BlatzKoMaterial_mu "mu" +//@} + +namespace oofem { +/** + * This class implements the Blatz-Ko model for porous materials. + * The Blatz-Ko strain energy density function is useful for modeling compressible foam type rubbers and can be expressed as: + *\f[ W = \mu\left(\frac{I_2}{I_3}+2\sqrt{I_3}-5\right)\f] + * The model contains only one parametr, shear modulus, Poisson's ratio is fixed to 0.25 + * @author Ondrej Faltus + * @author Martin Horak + * + */ +class BlatzKoMaterial : public StructuralMaterial, public BaseHyperElasticMaterial +{ +protected: + /// Shear modulus + double mu; + +public: + BlatzKoMaterial(int n, Domain *d) : StructuralMaterial(n, d), BaseHyperElasticMaterial() { }; + + void initializeFrom(InputRecord &ir) override; + + FloatMatrixF< 6, 6 >give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } + + FloatArrayF< 6 >giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const override { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } + + FloatMatrixF< 9, 9 >give3dMaterialStiffnessMatrix_dPdF(MatResponseMode, + GaussPoint *gp, + TimeStep *tStep) const override; + + FloatArrayF< 9 >giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const override; + + virtual MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + const char *giveInputRecordName() const override { return _IFT_BlatzKoMaterial_Name; } + const char *giveClassName() const override { return "BlatzKoMaterial"; } +}; +} // end namespace oofem +#endif diff --git a/src/sm/Materials/HyperelasticMaterials/hyperelasticmaterial1d.C b/src/sm/Materials/HyperelasticMaterials/hyperelasticmaterial1d.C new file mode 100644 index 000000000..217b30ee6 --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/hyperelasticmaterial1d.C @@ -0,0 +1,125 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2020 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "hyperelasticmaterial1d.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "classfactory.h" +#include "mathfem.h" + + + +namespace oofem { +REGISTER_Material(HyperelasticMaterial1d); + +HyperelasticMaterial1d::HyperelasticMaterial1d(int n, Domain *d) : StructuralMaterial(n, d) +{ } + +FloatArrayF< 1 > +HyperelasticMaterial1d::giveFirstPKStressVector_1d(const FloatArrayF< 1 > &vF, GaussPoint *gp, TimeStep *tStep) const +// returns 9 components of the first piola kirchhoff stress corresponding to the given deformation gradinet +{ + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + + FloatArrayF<1> vP; + if(this->hyperelasticMaterialType == HEMT_Biot) { + vP.at(1) = this->E * (vF.at(1) - 1.); + } else if(this->hyperelasticMaterialType == HEMT_StVenantKirchhoff) { + vP.at(1) = vF.at(1) * this->E * 0.5 * (vF.at(1) * vF.at(1) - 1.); + } else { + OOFEM_ERROR("Unknow material type"); + } + // update gp + status->letTempFVectorBe(vF); + status->letTempPVectorBe(vP); + // + return vP; +} + + + +FloatMatrixF< 1, 1 > +HyperelasticMaterial1d::give1dStressStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +// returns the 9x9 tangent stiffness matrix - dP/dF +{ + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + + double e = this->E; + if(this->hyperelasticMaterialType == HEMT_Biot) { + return {e}; + } else if(this->hyperelasticMaterialType == HEMT_StVenantKirchhoff) { + FloatArray vF(status->giveTempFVector() ); + FloatMatrix d(1,1); + d.at(1,1)= e * 0.5 * (vF.at(1) * vF.at(1) - 1.) + e * vF.at(1)*vF.at(1); + return d; + } else { + OOFEM_ERROR("Unknow material type"); + } + + +} + + + + + + +MaterialStatus * +HyperelasticMaterial1d::CreateStatus(GaussPoint *gp) const +{ + return new StructuralMaterialStatus(gp); +} + + +void +HyperelasticMaterial1d::initializeFrom(InputRecord &ir) +{ + StructuralMaterial :: initializeFrom(ir); + + int hyperTypeRecord = 0; // default + IR_GIVE_OPTIONAL_FIELD(ir, hyperTypeRecord, _IFT_HyperelasticMaterial1d_type); + // specify the type of hyperelasticmaterial + if ( hyperTypeRecord == 0 ) { + this->hyperelasticMaterialType = HEMT_Biot; + } else if ( hyperTypeRecord == 1 ) { + this->hyperelasticMaterialType = HEMT_StVenantKirchhoff; + } else { + throw ValueInputException(ir, _IFT_HyperelasticMaterial1d_type, "Unknown hyperelastic material type"); + } + + + IR_GIVE_FIELD(ir, this->E, _IFT_HyperelasticMaterial1d_E); + +} +} // end namespace oofem diff --git a/src/sm/Materials/HyperelasticMaterials/hyperelasticmaterial1d.h b/src/sm/Materials/HyperelasticMaterials/hyperelasticmaterial1d.h new file mode 100644 index 000000000..f1bfe747c --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/hyperelasticmaterial1d.h @@ -0,0 +1,96 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2020 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef hyperelasticmaterial1d_h +#define hyperelasticmaterial1d_h + +#include "sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" + + +///@name Input fields for MooneyRivlinMaterial +//@{ +#define _IFT_HyperelasticMaterial1d_Name "hyperelasticmaterial1d" +#define _IFT_HyperelasticMaterial1d_type "mtype" +#define _IFT_HyperelasticMaterial1d_E "e" +//@} + +namespace oofem { +/** + * This class implements several 1d hyperelastic materials. + * Including now Biot and Saint Venant-Kirchhoff materials + * + * @author Martin Horák, nitramkaroh@seznam.cz + * + */ +class HyperelasticMaterial1d : public StructuralMaterial +{ +protected: + double E = 0; + + enum HyperElasticMaterialType { + HEMT_Biot=0, + HEMT_StVenantKirchhoff=1, + HEMT_Unknown = 100 + }; + /// Parameter specifying the definition of used constitutive model + HyperElasticMaterialType hyperelasticMaterialType = HEMT_Unknown; + + +public: + HyperelasticMaterial1d(int n, Domain *d); + + void initializeFrom(InputRecord &ir) override; + + FloatMatrixF< 6, 6 >give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override { OOFEM_ERROR("not implemented, this material supports only 1d case"); } + + FloatArrayF< 6 >giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const override { OOFEM_ERROR("not implemented, this material supports only 1d case"); } + FloatMatrixF< 9, 9 >give3dMaterialStiffnessMatrix_dPdF(MatResponseMode, + GaussPoint *gp, + TimeStep *tStep) const override{OOFEM_ERROR("not implemented, this material supports only 1d case");} + + FloatArrayF< 9 >giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const override{OOFEM_ERROR("not implemented, this material supports only 1d case");} + + + FloatArrayF< 1 > giveFirstPKStressVector_1d(const FloatArrayF< 1 > &vF, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 1, 1 > give1dStressStiffnessMatrix_dPdF(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + const char *giveInputRecordName() const override { return _IFT_HyperelasticMaterial1d_Name; } + const char *giveClassName() const override { return "HyperelasticMaterial1d"; } +}; +} // end namespace oofem +#endif diff --git a/src/sm/Materials/HyperelasticMaterials/mooneyrivlincompressiblematerial.C b/src/sm/Materials/HyperelasticMaterials/mooneyrivlincompressiblematerial.C new file mode 100644 index 000000000..f80c59b65 --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/mooneyrivlincompressiblematerial.C @@ -0,0 +1,98 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2020 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mooneyrivlincompressiblematerial.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "classfactory.h" +#include "mathfem.h" + + + +namespace oofem { +REGISTER_Material(MooneyRivlinCompressibleMaterial); + +MooneyRivlinCompressibleMaterial::MooneyRivlinCompressibleMaterial(int n, Domain *d) : StructuralMaterial(n, d), BaseHyperElasticMaterial() +{ } + +FloatArrayF< 9 > +MooneyRivlinCompressibleMaterial::giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const +// returns 9 components of the first piola kirchhoff stress corresponding to the given deformation gradinet +{ + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + + Tensor2_3d F(vF), P; + // compute the first Piola-Kirchhoff + P(i_3, j_3) = C1 * this->compute_dI1_Cdev_dF(F)(i_3, j_3) + C2 * this->compute_dI2_Cdev_dF(F)(i_3, j_3) + this->compute_dVolumetricEnergy_dF(F)(i_3, j_3); + auto vP = P.to_voigt_form(); + // update gp + status->letTempFVectorBe(vF); + status->letTempPVectorBe(vP); + // + return vP; +} + + + +FloatMatrixF< 9, 9 > +MooneyRivlinCompressibleMaterial::give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +// returns the 9x9 tangent stiffness matrix - dP/dF +{ + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + FloatArrayF< 9 >vF(status->giveTempFVector() ); + Tensor2_3d F(vF); + Tensor4_3d A; + A(i_3, j_3, k_3, l_3) = C1 * this->compute_d2I1_Cdev_dF2(F)(i_3, j_3, k_3, l_3) + C2 * this->compute_d2I2_Cdev_dF2(F)(i_3, j_3, k_3, l_3) + this->compute_d2VolumetricEnergy_dF2(F)(i_3, j_3, k_3, l_3); + return A.to_voigt_form(); +} + + + + +MaterialStatus * +MooneyRivlinCompressibleMaterial::CreateStatus(GaussPoint *gp) const +{ + return new StructuralMaterialStatus(gp); +} + + +void +MooneyRivlinCompressibleMaterial::initializeFrom(InputRecord &ir) +{ + StructuralMaterial::initializeFrom(ir); + BaseHyperElasticMaterial::initializeFrom(ir); + IR_GIVE_FIELD(ir, C1, _IFT_MooneyRivlinCompressibleMaterial_c1); + IR_GIVE_FIELD(ir, C2, _IFT_MooneyRivlinCompressibleMaterial_c2); +} +} // end namespace oofem diff --git a/src/sm/Materials/HyperelasticMaterials/mooneyrivlincompressiblematerial.h b/src/sm/Materials/HyperelasticMaterials/mooneyrivlincompressiblematerial.h new file mode 100644 index 000000000..0ca8d346d --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/mooneyrivlincompressiblematerial.h @@ -0,0 +1,99 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2020 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef mooneyrivlinmaterial_h +#define mooneyrivlinmaterial_h + +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "basehyperelasticmaterial.h" + + +///@name Input fields for MooneyRivlinMaterial +//@{ +#define _IFT_MooneyRivlinCompressibleMaterial_Name "mooneyrivlincompressiblemat" +#define _IFT_MooneyRivlinCompressibleMaterial_c1 "c1" +#define _IFT_MooneyRivlinCompressibleMaterial_c2 "c2" +//@} + +namespace oofem { +/** + * This class implements Compressible Mooney - Rivlin material. + * + * @author Martin Horák, nitramkaroh@seznam.cz + * + * @note References: R.W. Ogden: Non-Linear Elastic Deformations, + * de Souza Neto, Peric, Owen: Computational Methods for Plasticity: Theory and Applications + * + * Free energy is considered as: + * \f$[ + * \rho_0 \psi = C_1(\bar{I}_1 - 3) + C_2(\bar{I}_2-3) + \frac{1}{2} K[ln(J)]^2 + * ]\f$ + * \f$C_1\f$, \f$C_2\f$ , and \f$K\f$ are material parameters. + * + * \f$ \bar{I}_1 = J^{-2/3}I_1 \f$, where \f$I_1 \f$ is the first invariant of the left Cauchy-Green deformation tensor C. + * + * \f$ \bar{I}_2 = J^{-4/3}I_2 \f$, where \f$I_2\f$ is the second invariant of the left Cauchy-Green deformation tensor C + * + * Compressible Neo-Hookean model is obtained by setting @f$C_2 = 0@f$ + */ +class MooneyRivlinCompressibleMaterial : public StructuralMaterial, public BaseHyperElasticMaterial +{ +protected: + // Material parameters + double C1; + double C2; + + +public: + MooneyRivlinCompressibleMaterial(int n, Domain *d); + + void initializeFrom(InputRecord &ir) override; + + FloatMatrixF< 6, 6 >give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } + + FloatArrayF< 6 >giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const override { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } + FloatMatrixF< 9, 9 >give3dMaterialStiffnessMatrix_dPdF(MatResponseMode, + GaussPoint *gp, + TimeStep *tStep) const override; + + FloatArrayF< 9 >giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + const char *giveInputRecordName() const override { return _IFT_MooneyRivlinCompressibleMaterial_Name; } + const char *giveClassName() const override { return "MooneyRivlinCompressibleMaterial"; } +}; +} // end namespace oofem +#endif diff --git a/src/sm/Materials/HyperelasticMaterials/mooneyrivlinmaterial.h b/src/sm/Materials/HyperelasticMaterials/mooneyrivlinmaterial.h new file mode 100644 index 000000000..182d567af --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/mooneyrivlinmaterial.h @@ -0,0 +1,102 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2020 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef mooneyrivlincompressiblematerial_h +#define mooneyrivlincompressiblematerial_h + +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "basehyperelasticmaterial.h" + + +///@name Input fields for MooneyRivlinMaterial +//@{ +#define _IFT_MooneyRivlinCompressibleMaterial_Name "mooneyrivlincompresssiblemat" +#define _IFT_MooneyRivlinCompressibleMaterial_c1 "c1" +#define _IFT_MooneyRivlinCompressibleMaterial_c2 "c2" +//@} + +namespace oofem { +/** + * This class implements Compressible Mooney - Rivlin material. + * + * @author Martin Horák, nitramkaroh@seznam.cz + * + * @note References: R.W. Ogden: Non-Linear Elastic Deformations, + * de Souza Neto, Peric, Owen: Computational Methods for Plasticity: Theory and Applications + * + * Free energy is considered as: + * \f$[ + * \rho_0 \psi = C_1(\bar{I}_1 - 3) + C_2(\bar{I}_2-3) + \frac{1}{2} K[ln(J)]^2 + * ]\f$ + * \f$C_1\f$, \f$C_2\f$ , and \f$K\f$ are material parameters. + * + * \f$ \bar{I}_1 = J^{-2/3}I_1 \f$, where \f$I_1 \f$ is the first invariant of the left Cauchy-Green deformation tensor C. + * + * \f$ \bar{I}_2 = J^{-4/3}I_2 \f$, where \f$I_2\f$ is the second invariant of the left Cauchy-Green deformation tensor C + * + * Compressible Neo-Hookean model is obtained by setting @f$C_2 = 0@f$ + */ + class MooneyRivlinCompressibleMaterial : public StructuralMaterial, public BaseHyperElasticMaterial +{ +protected: + // Material parameters + double C1; + double C2; + + +public: + MooneyRivlinCompressibleMaterial(int n, Domain *d); + + void initializeFrom(InputRecord &ir) override; + + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } + + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override{ OOFEM_ERROR("not implemented, this material is designed for large strains only"); } + FloatMatrixF<9,9> give3dMaterialStiffnessMatrix_dPdF(MatResponseMode, + GaussPoint * gp, + TimeStep * tStep) const override; + + FloatArrayF<9> giveFirstPKStressVector_3d(const FloatArrayF<9> &vF, GaussPoint *gp, TimeStep *tStep) const override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + const char *giveInputRecordName() const override { return _IFT_MooneyRivlinCompressibleMaterial_Name; } + const char *giveClassName() const override { return "MooneyRivlinCompressibleMaterial"; } + + +}; + +} // end namespace oofem +#endif diff --git a/src/sm/Materials/HyperelasticMaterials/ogdencompressiblematerial.C b/src/sm/Materials/HyperelasticMaterials/ogdencompressiblematerial.C new file mode 100644 index 000000000..2a7bfdbc3 --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/ogdencompressiblematerial.C @@ -0,0 +1,176 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2014 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "ogdencompressiblematerial.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "classfactory.h" +#include "mathfem.h" + +namespace oofem { +REGISTER_Material(OgdenCompressibleMaterial); + +OgdenCompressibleMaterial::OgdenCompressibleMaterial(int n, Domain *d) : StructuralMaterial(n, d), BaseHyperElasticMaterial() +{ } + +FloatArrayF< 9 > +OgdenCompressibleMaterial::giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const +// returns 9 components of the first Piola-Kirchhoff stress corresponding to the given deformation gradient +{ + //store deformation gradient into tensor + Tensor2_3d F(vF), P; + Tensor2_3d C, S; + // @todo:replace C by Tensor2sym_3d C = F^F, where ^ is leads to symmetric tensor + C(i_3, j_3) = F(k_3, i_3) * F(k_3, j_3); + S = this->giveDeviatoricSecondPKStressVector_3d(C); + P(i_3, j_3) = F(i_3, k_3) * S(k_3, j_3) + this->compute_dVolumetricEnergy_dF(F)(i_3, j_3); + auto vP = P.to_voigt_form(); + // update gp + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + + status->letTempFVectorBe(vF); + status->letTempPVectorBe(vP); + + // + return vP; +} + + +FloatMatrixF< 9, 9 > +OgdenCompressibleMaterial::give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +// returns the 9x9 tangent stiffness matrix - dP/dF +{ + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + + double J; + FloatArrayF< 9 >vF(status->giveTempFVector() ); + Tensor2_3d F(vF), P, C, iC, Sdev; + Tensor4_3d dSdE, dPdF, iCiC; + + J = F.compute_determinant(); + // + // @todo:replace C by Tensor2sym_3d and C = F^F, where ^ leads to symmetric tensor + C(i_3, j_3) = F(k_3, i_3) * F(k_3, j_3); + // compute eigen values and eigen vectors of C + auto [ eVals, eVecs ] = C.eigs(); + //compute inverse of the right Cauchy-Green tensor + iC = C.compute_inverse(); + //compute symetric dyadic product + iCiC(i_3, j_3, k_3, l_3) = ( iC(i_3, k_3) * iC(j_3, l_3) ) + ( iC(i_3, l_3) * iC(j_3, k_3) ); + for ( int i = 1; i <= N; i++ ) { + double l1a, l2a, l3a, Ja; + // + Ja = pow(J, -alpha.at(i) / 3.); + l1a = pow(eVals.at(1), alpha.at(i) / 2.); + l2a = pow(eVals.at(2), alpha.at(i) / 2.); + l3a = pow(eVals.at(3), alpha.at(i) / 2.); + // + double I1a = ( l1a + l2a + l3a ) / 3.; + // + Tensor2_3d powC, iSdev; + powC = Tensor2_3d::computeTensorPowerFromEigs(eVals, eVecs, ( alpha.at(i) - 2. ) / 2.); + iSdev(i_3, j_3) = mu.at(i) * Ja * ( powC(i_3, j_3) - I1a * iC(i_3, j_3) ); + // + dSdE(i_3, j_3, k_3, l_3) += 2. * mu.at(i) * Ja * ( Tensor2_3d::compute_dCm_dC_fromEigs( ( alpha.at(i) - 2. ) / 2., eVals, eVecs )(i_3, j_3, k_3, l_3) - alpha.at(i) / 6. * iC(i_3, j_3) * powC(k_3, l_3) + I1a / 2. * iCiC(i_3, j_3, k_3, l_3) ) - alpha.at(i) / 3. * iSdev(i_3, j_3) * iC(k_3, l_3); + Sdev(i_3, j_3) += iSdev(i_3, j_3); + } + + // transform the second elasticity tensor to the first elasticity tensor + FloatMatrixF< 9, 9 >mdSdE; + mdSdE = dSdE.to_voigt_form(); + FloatMatrix m2dSdE(mdSdE); + Tensor2_3d I = Tensor2_3d::UnitTensor(); + dPdF(i_3, j_3, k_3, l_3) = I(i_3, k_3) * Sdev(j_3, l_3) + F(i_3, m_3) * dSdE(m_3, j_3, n_3, l_3) * F(k_3, n_3); + // add volumetric part + dPdF(i_3, j_3, k_3, l_3) += this->compute_d2VolumetricEnergy_dF2(F)(i_3, j_3, k_3, l_3); + + FloatMatrix mdP(dPdF.to_voigt_form() ); + return dPdF.to_voigt_form(); +} + + + + + +Tensor2_3d +OgdenCompressibleMaterial::giveDeviatoricSecondPKStressVector_3d(const Tensor2_3d &C) const +{ + // compute eigen values and eigen vectors of C + auto [ eVals, eVecs ] = C.eigs(); + // + double J = sqrt(C.compute_determinant() ); + Tensor2_3d S, iC; + //compute inverse of the right Cauchy-Green tensor + iC = C.compute_inverse(); + for ( int i = 1; i <= N; i++ ) { + double l1a, l2a, l3a, Ja; + Tensor2_3d Si; + // + l1a = pow(eVals.at(1), alpha.at(i) / 2.); + l2a = pow(eVals.at(2), alpha.at(i) / 2.); + l3a = pow(eVals.at(3), alpha.at(i) / 2.); + Ja = pow(J, -alpha.at(i) / 3.); + double I1a = ( l1a + l2a + l3a ) / 3.; + S(i_3, j_3) += mu.at(i) * Ja * ( Tensor2_3d::computeTensorPowerFromEigs(eVals, eVecs, ( alpha.at(i) - 2. ) / 2.)(i_3, j_3) - I1a * iC(i_3, j_3) ); + } + return S; +} + + + + + +MaterialStatus * +OgdenCompressibleMaterial::CreateStatus(GaussPoint *gp) const +{ + return new StructuralMaterialStatus(gp); +} + + +void +OgdenCompressibleMaterial::initializeFrom(InputRecord &ir) +{ + StructuralMaterial::initializeFrom(ir); + BaseHyperElasticMaterial::initializeFrom(ir); + + IR_GIVE_FIELD(ir, alpha, _IFT_OgdenCompressibleMaterial_alpha); + IR_GIVE_FIELD(ir, mu, _IFT_OgdenCompressibleMaterial_mu); + + N = alpha.giveSize(); + int M = mu.giveSize(); + if ( N != M ) { + OOFEM_ERROR("Inconsistent size of alpha and mu"); + } +} +} // end namespace oofem diff --git a/src/sm/Materials/HyperelasticMaterials/ogdencompressiblematerial.h b/src/sm/Materials/HyperelasticMaterials/ogdencompressiblematerial.h new file mode 100644 index 000000000..21706a60d --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/ogdencompressiblematerial.h @@ -0,0 +1,108 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2014 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ogdencompressiblematerial_h +#define ogdencompressiblematerial_h + +#include "../sm/Materials/structuralmaterial.h" +#include "../sm/Materials/structuralms.h" +#include "basehyperelasticmaterial.h" + +///@name Input fields for OgdenMaterial +//@{ +#define _IFT_OgdenCompressibleMaterial_Name "ogdencompressiblemat" + +#define _IFT_OgdenCompressibleMaterial_alpha "alpha" +#define _IFT_OgdenCompressibleMaterial_mu "mu" +//@} + +namespace oofem { +/** + * This class implements Compressible Ogden material. + * + * @author Martin Horák, nitramkaroh@seznam.cz + * + * @Note References: R.W. Ogden: Non-Linear Elastic Deformations, de Souza Neto, Peric, Owen: Computational Methods for Plasticity: Theory and Applications + * + * Free energy is considered as: + * @f[ + * \rho_0 \psi = \sum_I^N \frac{mu_I}{alpha_I}(\lambda_1^{\alpha_I}+\lambda_2^{\alpha_I}+\lambda_3^{\alpha_I}-3) + \frac{1}{2} K[ln(J)]^2 + * @f] + * @f$ \alpha_I @f$, @f$ mu_I @f$, and @f$K@f$ are material parameters. + * + * @f$ \lambda_1@f$, @f$ \lambda_2 @f$, and @f$ \lambda_3 @f$ are principal stretches + * + * Compressible Neo-Hookean model is obtained by setting @f$N = 1@f$, @f$\alpha_1 = 2@f$ + * + * Compressible Mooney-Rivlin model is obtained by setting @f$N = 2@f$, @f$\alpha_1 = 2@f$, and @f$\alpha_2 = -2@f$. + */ +class OgdenCompressibleMaterial : public StructuralMaterial, public BaseHyperElasticMaterial +{ +protected: + /// Array of Exponents alpha + FloatArray alpha; + /// Array of Material parameters mu + FloatArray mu; + /// Number of material parameters in the arrays mu(alpha) + int N; + + +public: + OgdenCompressibleMaterial(int n, Domain *d); + + + FloatMatrixF< 6, 6 >give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } + + FloatArrayF< 6 >giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const override { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } + FloatMatrixF< 9, 9 >give3dMaterialStiffnessMatrix_dPdF(MatResponseMode, + GaussPoint *gp, + TimeStep *tStep) const override; + + FloatArrayF< 9 >giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const override; + + virtual void initializeFrom(InputRecord &ir) override; + virtual MaterialStatus *CreateStatus(GaussPoint *gp) const override; + virtual const char *giveInputRecordName() const override { return _IFT_OgdenCompressibleMaterial_Name; } + virtual const char *giveClassName() const override { return "OgdenCompressibleMaterial"; } + +private: + /** + * Computes the deviatoric part of the second Piola-Kirchhoff stress tensor from the left Cauchy-Green tensor + * @param C the left Cauchy-Green deformation tensor + * @return the second Piola-Kirchhoff stress tensor + **/ + Tensor2_3d giveDeviatoricSecondPKStressVector_3d(const Tensor2_3d &C) const; +}; +} // end namespace oofem +#endif diff --git a/src/sm/Materials/HyperelasticMaterials/simopistermaterial.C b/src/sm/Materials/HyperelasticMaterials/simopistermaterial.C new file mode 100644 index 000000000..5732d57f3 --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/simopistermaterial.C @@ -0,0 +1,93 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2020 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "simopistermaterial.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_Material(SimoPisterMaterial); + +SimoPisterMaterial::SimoPisterMaterial(int n, Domain *d) : StructuralMaterial(n, d), BaseHyperElasticMaterial() +{ } + +FloatMatrixF< 9, 9 > +SimoPisterMaterial::give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +// returns the 9x9 tangent stiffness matrix - dP/dF +{ + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + FloatArrayF< 9 >vF(status->giveTempFVector() ); + Tensor2_3d F(vF); + auto [ J, cofF ] = F.compute_determinant_and_cofactor(); + Tensor4_3d A; + A(i_3, j_3, k_3, l_3) = G * ( 0.5 * this->compute_d2I1_C_dF2(F)(i_3, j_3, k_3, l_3) + 1 / J / J * cofF(i_3, j_3) * cofF(k_3, l_3) - 1. / J * F.compute_tensor_cross_product()(i_3, j_3, k_3, l_3) ) + this->compute_d2VolumetricEnergy_dF2(F)(i_3, j_3, k_3, l_3); + return A.to_voigt_form(); +} + +FloatArrayF< 9 > +SimoPisterMaterial::giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const +// returns 9 components of the first piola kirchhoff stress corresponding to the given deformation gradinet +{ + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + + Tensor2_3d F(vF), P; + auto [ J, cofF ] = F.compute_determinant_and_cofactor(); + // compute the first Piola-Kirchhoff + P(i_3, j_3) = G * ( 0.5 * this->compute_dI1_C_dF(F)(i_3, j_3) - 1. / J * cofF(i_3, j_3) ) + this->compute_dVolumetricEnergy_dF(F)(i_3, j_3); + auto vP = P.to_voigt_form(); + // update gp + status->letTempFVectorBe(vF); + status->letTempPVectorBe(vP); + // + return vP; +} + + +MaterialStatus * +SimoPisterMaterial::CreateStatus(GaussPoint *gp) const +{ + return new StructuralMaterialStatus(gp); +} + + +void +SimoPisterMaterial::initializeFrom(InputRecord &ir) +{ + StructuralMaterial::initializeFrom(ir); + BaseHyperElasticMaterial::initializeFrom(ir); + IR_GIVE_FIELD(ir, G, _IFT_SimoPisterMaterial_g); +} +} // end namespace oofem diff --git a/src/sm/Materials/HyperelasticMaterials/simopistermaterial.h b/src/sm/Materials/HyperelasticMaterials/simopistermaterial.h new file mode 100644 index 000000000..c7e8fe162 --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/simopistermaterial.h @@ -0,0 +1,97 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2020 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef simopistermaterial_h +#define simopistermaterial_h + +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "basehyperelasticmaterial.h" + + +///@name Input fields for SimoPisterMaterial +//@{ +#define _IFT_SimoPisterMaterial_Name "simopistermat" +#define _IFT_SimoPisterMaterial_g "g" +//@} + +namespace oofem { +/** + * Free energy is considered as: + * \f$[ + * \rho_0 \psi = U(J) + G( 0.5 * I_1 - ln J) ]\f$ + * This form of energy corresponds to a neo-Hookean material which is extended to the compressible * range by adding an extra function depending on J. + * @author Martin Horak, nitramkaroh@seznam.cz + * @note Reference: article{simo1984remarks, + * title={Remarks on rate constitutive equations for finite deformation problems: computational implications}, + * author={Simo, Juan C and Pister, Karl S}, + * journal={Computer Methods in Applied Mechanics and Engineering}, + * volume={46}, + * number={2}, + * pages={201--215}, + * year={1984}, + * publisher={Elsevier} + * } + * + * + */ +class SimoPisterMaterial : public StructuralMaterial, public BaseHyperElasticMaterial +{ +protected: + double G = 0.; ///< Shear modulus. + +public: + SimoPisterMaterial(int n, Domain *d); + + void initializeFrom(InputRecord &ir) override; + + FloatMatrixF< 6, 6 >give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } + + FloatArrayF< 6 >giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const override { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } + + + FloatMatrixF< 9, 9 >give3dMaterialStiffnessMatrix_dPdF(MatResponseMode, + GaussPoint *gp, + TimeStep *tStep) const override; + + FloatArrayF< 9 >giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + const char *giveInputRecordName() const override { return _IFT_SimoPisterMaterial_Name; } + const char *giveClassName() const override { return "SimoPisterMaterial"; } +}; +} // end namespace oofem +#endif diff --git a/src/sm/Materials/HyperelasticMaterials/volumetricenergyinterface.C b/src/sm/Materials/HyperelasticMaterials/volumetricenergyinterface.C new file mode 100644 index 000000000..26ea751d1 --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/volumetricenergyinterface.C @@ -0,0 +1,84 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2014 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "volumetricenergyinterface.h" +#include "tensor/tensor.h" +#include "dynamicinputrecord.h" + + + +namespace oofem { + + +Tensor2_3d +VolumetricEnergyInterface :: compute_dVolumetricEnergy_dF(const Tensor2_3d &F) const + +{ + // compute jacobian and its logarithm + Tensor2_3d dVolumetricEnergy_dF; + if(type == 1) { + auto J = compute_determinant(F); + auto lnJ = log(J); + dVolumetricEnergy_dF(i_3,j_3) = K * lnJ / J * compute_dJ_dF(F)(i_3,j_3); + } + return dVolumetricEnergy_dF; +} + + +Tensor4_3d +VolumetricEnergyInterface :: compute_d2VolumetricEnergy_dF2(const Tensor2_3d &F) const +{ + // compute jacobian and its logarithm + + Tensor4_3d d2VolumetricEnergy_dF2; + if(type == 1) { + auto [J, cofF] = compute_determinant_and_cofactor(F); + auto lnJ = log(J); + d2VolumetricEnergy_dF2(i_3,j_3,k_3,l_3) = K * (1.-lnJ) / J / J * cofF(i_3, j_3) * cofF(k_3, l_3) + K * lnJ / J * compute_tensor_cross_product(F)(i_3,j_3,k_3,l_3); + + } + return d2VolumetricEnergy_dF2; +} + + + + +void +VolumetricEnergyInterface :: initializeFrom(InputRecord &ir) +{ + IR_GIVE_FIELD(ir, K, _IFT_VolumetricEnergyInterface_k); + IR_GIVE_OPTIONAL_FIELD(ir, type, _IFT_VolumetricEnergyInterface_type) +} + +} // end namespace oofem diff --git a/src/sm/Materials/HyperelasticMaterials/volumetricenergyinterface.h b/src/sm/Materials/HyperelasticMaterials/volumetricenergyinterface.h new file mode 100644 index 000000000..108df1738 --- /dev/null +++ b/src/sm/Materials/HyperelasticMaterials/volumetricenergyinterface.h @@ -0,0 +1,80 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2014 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef volumetricenergyinterface_h +#define volumetricenergyinterface_h + +#include "tensor/tensor.h" + +///@name Input fields for VolumetricEnergyInterface +//@{ +#define _IFT_VolumetricEnergyInterface_k "k" +#define _IFT_VolumetricEnergyInterface_type "type" +//@} + +namespace oofem { + class InputRecord; + +/** + * This class implements Volumetric form of energy fo Compressible Hyperelastic materials. + * + * @author Martin Horák, nitramkaroh@seznam.cz + * + * References: R.W. Ogden: Non-Linear Elastic Deformations, + * de Souza Neto, Peric, Owen: Computational Methods for Plasticity: Theory and Applications + * + * Free energy is considered as: + * @f[ + * \rho_0 \psi = Kf(J) + */ + +class VolumetricEnergyInterface +{ + + protected: + double K; + int type = 1; + + public: + VolumetricEnergyInterface(){;} + virtual ~VolumetricEnergyInterface(){;} + + Tensor2_3d compute_dVolumetricEnergy_dF(const Tensor2_3d &F) const; + Tensor4_3d compute_d2VolumetricEnergy_dF2(const Tensor2_3d &F) const; + void initializeFrom(InputRecord &ir); +}; + +} // end namespace oofem +#endif diff --git a/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage01.C b/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage01.C index f7b9f40cf..f533e7e4b 100644 --- a/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage01.C +++ b/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage01.C @@ -46,28 +46,20 @@ namespace oofem { REGISTER_Material(IsoInterfaceDamageMaterial); IsoInterfaceDamageMaterial :: IsoInterfaceDamageMaterial(int n, Domain *d) : StructuralInterfaceMaterial(n, d) -{ - maxOmega = 0.999999; - beta = 0.; -} - +{} -IsoInterfaceDamageMaterial :: ~IsoInterfaceDamageMaterial() { } - -void -IsoInterfaceDamageMaterial :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) +FloatArrayF<3> +IsoInterfaceDamageMaterial :: giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const { IsoInterfaceDamageMaterialStatus *status = static_cast< IsoInterfaceDamageMaterialStatus * >( this->giveStatus(gp) ); - FloatMatrix de; - double equivStrain, tempKappa = 0.0, omega = 0.0; // compute equivalent strain - this->computeEquivalentStrain(equivStrain, jump, gp, tStep); + double equivStrain = this->computeEquivalentStrain(jump, gp, tStep); // compute value of loading function if strainLevel crit apply - tempKappa = status->giveKappa(); - + double tempKappa = status->giveKappa(); + double omega; if ( tempKappa >= equivStrain ) { // damage does not grow omega = status->giveDamage(); @@ -75,71 +67,59 @@ IsoInterfaceDamageMaterial :: giveEngTraction_3d(FloatArray &answer, GaussPoint // damage grows tempKappa = equivStrain; // evaluate damage - this->computeDamageParam(omega, tempKappa, jump, gp); + omega = this->computeDamageParam(tempKappa, jump, gp); } - this->give3dStiffnessMatrix_Eng(de, ElasticStiffness, gp, tStep); - de.times(1.0 - omega); - answer.beProductOf(de, jump); + auto de = this->give3dStiffnessMatrix_Eng(ElasticStiffness, gp, tStep); + auto answer = (1.0 - omega) * dot(de, jump); // update gp status->letTempJumpBe(jump); status->letTempTractionBe(answer); status->setTempKappa(tempKappa); status->setTempDamage(omega); + + return answer; } -void -IsoInterfaceDamageMaterial :: give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +IsoInterfaceDamageMaterial :: give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - double om, un; IsoInterfaceDamageMaterialStatus *status = static_cast< IsoInterfaceDamageMaterialStatus * >( this->giveStatus(gp) ); - // assemble eleastic stiffness - answer.resize(3, 3); - answer.zero(); - answer.at(1, 1) = kn; - answer.at(2, 2) = ks; - answer.at(3, 3) = ks; + auto answer = diag<3>({kn, ks, ks}); if ( rMode == ElasticStiffness ) { - return; + return answer; } + double un = status->giveTempJump().at(1); if ( rMode == SecantStiffness ) { - // Secant stiffness - om = status->giveTempDamage(); - un = status->giveTempJump().at(1); - om = min(om, maxOmega); // damage in tension only if ( un >= 0 ) { - answer.times(1.0 - om); + double om = min(status->giveTempDamage(), maxOmega); + answer *= 1.0 - om; } - return; - } else { - // Tangent Stiffness - FloatArray se; - const FloatArray &e = status->giveTempJump(); - se.beProductOf(answer, e); - - om = status->giveTempDamage(); - un = status->giveTempJump().at(1); - om = min(om, maxOmega); + return answer; + } else { // Tangent Stiffness // damage in tension only if ( un >= 0 ) { - answer.times(1.0 - om); - return; + double om = min(status->giveTempDamage(), maxOmega); + answer *= 1.0 - om; #if 0 // Unreachable code - commented out to supress compiler warnings double dom = -( -e0 / un / un * exp( -( ft / gf ) * ( un - e0 ) ) + e0 / un * exp( -( ft / gf ) * ( un - e0 ) ) * ( -( ft / gf ) ) ); if ( ( om > 0. ) && ( status->giveTempKappa() > status->giveKappa() ) ) { + const auto &e = status->giveTempJump(); + auto se = dot(answer, e); answer.at(1, 1) -= se.at(1) * dom; answer.at(2, 1) -= se.at(2) * dom; } #endif } + return answer; } } @@ -176,10 +156,10 @@ IsoInterfaceDamageMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, In } -IRResultType -IsoInterfaceDamageMaterial :: initializeFrom(InputRecord *ir) +void +IsoInterfaceDamageMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralInterfaceMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, kn, _IFT_IsoInterfaceDamageMaterial_kn); IR_GIVE_FIELD(ir, ks, _IFT_IsoInterfaceDamageMaterial_ks); @@ -195,8 +175,6 @@ IsoInterfaceDamageMaterial :: initializeFrom(InputRecord *ir) beta = 0.; IR_GIVE_OPTIONAL_FIELD(ir, beta, _IFT_IsoInterfaceDamageMaterial_beta); - - return StructuralInterfaceMaterial :: initializeFrom(ir); } @@ -215,41 +193,34 @@ IsoInterfaceDamageMaterial :: giveInputRecord(DynamicInputRecord &input) } -void -IsoInterfaceDamageMaterial :: computeEquivalentStrain(double &kappa, const FloatArray &jump, GaussPoint *gp, TimeStep *tStep) +double +IsoInterfaceDamageMaterial :: computeEquivalentStrain(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const { double epsNplus = macbra( jump.at(1) ); double epsT2 = jump.at(2) * jump.at(2); if ( jump.giveSize() == 3 ) { epsT2 += jump.at(3) * jump.at(3); } - kappa = sqrt(epsNplus * epsNplus + beta * epsT2); + return sqrt(epsNplus * epsNplus + beta * epsT2); } -void -IsoInterfaceDamageMaterial :: computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *gp) +double +IsoInterfaceDamageMaterial :: computeDamageParam(double kappa, const FloatArrayF<3> &strain, GaussPoint *gp) const { if ( kappa > this->e0 ) { - omega = 1.0 - ( this->e0 / kappa ) * exp( -( ft / gf ) * ( kappa - e0 ) ); + return 1.0 - ( this->e0 / kappa ) * exp( -( ft / gf ) * ( kappa - e0 ) ); } else { - omega = 0.0; + return 0.0; } } -IsoInterfaceDamageMaterialStatus :: IsoInterfaceDamageMaterialStatus(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g) -{ - kappa = tempKappa = 0.0; - damage = tempDamage = 0.0; -} - - -IsoInterfaceDamageMaterialStatus :: ~IsoInterfaceDamageMaterialStatus() -{ } +IsoInterfaceDamageMaterialStatus :: IsoInterfaceDamageMaterialStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) +{} void -IsoInterfaceDamageMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +IsoInterfaceDamageMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralInterfaceMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -278,17 +249,11 @@ IsoInterfaceDamageMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -IsoInterfaceDamageMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +IsoInterfaceDamageMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralInterfaceMaterialStatus :: saveContext(stream, mode); - // save parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write a raw data if ( !stream.write(kappa) ) { THROW_CIOERR(CIO_IOERR); } @@ -296,21 +261,13 @@ IsoInterfaceDamageMaterialStatus :: saveContext(DataStream &stream, ContextMode if ( !stream.write(damage) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -IsoInterfaceDamageMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +IsoInterfaceDamageMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralInterfaceMaterialStatus :: restoreContext(stream, mode); - // read parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data if ( !stream.read(kappa) ) { THROW_CIOERR(CIO_IOERR); } @@ -318,7 +275,5 @@ IsoInterfaceDamageMaterialStatus :: restoreContext(DataStream &stream, ContextMo if ( !stream.read(damage) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage01.h b/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage01.h index 0e11749e2..a8dc328c2 100644 --- a/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage01.h +++ b/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage01.h @@ -35,8 +35,8 @@ #ifndef isointerfacedamage01_h #define isointerfacedamage01_h -#include "../structuralinterfacematerial.h" -#include "../structuralinterfacematerialstatus.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" ///@name Input fields for IsoInterfaceDamageMaterial //@{ @@ -58,43 +58,40 @@ class IsoInterfaceDamageMaterialStatus : public StructuralInterfaceMaterialStatu { protected: /// Scalar measure of the largest equivalent displacement ever reached in material. - double kappa; + double kappa = 0.; /// Non-equilibrated scalar measure of the largest equivalent displacement. - double tempKappa; + double tempKappa = 0.; /// Damage level of material. - double damage; + double damage = 0.; /// Non-equilibrated damage level of material. - double tempDamage; + double tempDamage = 0.; public: /// Constructor - IsoInterfaceDamageMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~IsoInterfaceDamageMaterialStatus(); + IsoInterfaceDamageMaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; /// Returns the last equilibrated scalar measure of the largest strain level. - double giveKappa() { return kappa; } + double giveKappa() const { return kappa; } /// Returns the temp. scalar measure of the largest strain level. - double giveTempKappa() { return tempKappa; } + double giveTempKappa() const { return tempKappa; } /// Sets the temp scalar measure of the largest strain level to given value. void setTempKappa(double newKappa) { tempKappa = newKappa; } /// Returns the last equilibrated damage level. - double giveDamage() { return damage; } + double giveDamage() const override { return damage; } /// Returns the temp. damage level. - double giveTempDamage() { return tempDamage; } + double giveTempDamage() const override { return tempDamage; } /// Sets the temp damage level to given value. void setTempDamage(double newDamage) { tempDamage = newDamage; } - // definition - virtual const char *giveClassName() const { return "IsoInterfaceDamageMaterialStatus"; } + const char *giveClassName() const override { return "IsoInterfaceDamageMaterialStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -114,54 +111,51 @@ class IsoInterfaceDamageMaterial : public StructuralInterfaceMaterial { protected: /// Coefficient of thermal dilatation. - double tempDillatCoeff; + double tempDillatCoeff = 0.; /// Elastic properties (normal moduli). - double kn; + double kn = 0.; /// Shear moduli. - double ks; + double ks = 0.; /// Tension strength. - double ft; + double ft = 0.; /// Fracture energy. - double gf; + double gf = 0.; /// Limit elastic deformation. - double e0; + double e0 = 0.; /// Maximum limit on omega. The purpose is elimination of a too compliant material which may cause convergency problems. Set to something like 0.99 if needed. - double maxOmega; + double maxOmega = 0.999999; /// Weight factor for the influence of shear component of displacement jump on equivalent strain. - double beta; + double beta = 0.; public: /// Constructor IsoInterfaceDamageMaterial(int n, Domain * d); - /// Destructor - virtual ~IsoInterfaceDamageMaterial(); - virtual int hasNonLinearBehaviour() { return 1; } - virtual bool hasAnalyticalTangentStiffness() const { return true; } + bool hasAnalyticalTangentStiffness() const override { return true; } - virtual const char *giveInputRecordName() const { return _IFT_IsoInterfaceDamageMaterial_Name; } - virtual const char *giveClassName() const { return "IsoInterfaceDamageMaterial"; } + const char *giveInputRecordName() const override { return _IFT_IsoInterfaceDamageMaterial_Name; } + const char *giveClassName() const override { return "IsoInterfaceDamageMaterial"; } - virtual void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); - virtual void give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + FloatArrayF<3> giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - void computeEquivalentStrain(double &kappa, const FloatArray &jump, GaussPoint *gp, TimeStep *tStep); + double computeEquivalentStrain(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const; /** - * computes the value of damage parameter omega, based on given value of equivalent strain. - * @param[out] omega Contains result. + * Computes the value of damage parameter omega, based on given value of equivalent strain. * @param kappa Equivalent strain measure. * @param strain Total strain vector in full form. (unnecessary?) * @param gp Integration point. + * @return omega. */ - virtual void computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *gp); + virtual double computeDamageParam(double kappa, const FloatArrayF<3> &strain, GaussPoint *gp) const; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new IsoInterfaceDamageMaterialStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new IsoInterfaceDamageMaterialStatus(gp); } }; } // end namespace oofem #endif // isointerfacedamage01_h diff --git a/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage02.C b/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage02.C index fa3b8a860..2f8f70386 100644 --- a/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage02.C +++ b/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage02.C @@ -48,27 +48,21 @@ namespace oofem { REGISTER_Material(IsoInterfaceDamageMaterial_2); IsoInterfaceDamageMaterial_2 :: IsoInterfaceDamageMaterial_2(int n, Domain *d) : StructuralInterfaceMaterial(n, d) -{ - maxOmega = 0.999999; -} - +{} -IsoInterfaceDamageMaterial_2 :: ~IsoInterfaceDamageMaterial_2() { } - -void -IsoInterfaceDamageMaterial_2 :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) +FloatArrayF<3> +IsoInterfaceDamageMaterial_2 :: giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const { IsoInterfaceDamageMaterialStatus_2 *status = static_cast< IsoInterfaceDamageMaterialStatus_2 * >( this->giveStatus(gp) ); - FloatMatrix de; - double f, equivStrain, tempKappa = 0.0, omega = 0.0; // compute equivalent strain - equivStrain = macbra( jump.at(1) ); + double equivStrain = macbra( jump.at(1) ); // compute value of loading function if strainLevel crit apply - f = equivStrain - status->giveKappa(); + double f = equivStrain - status->giveKappa(); + double tempKappa = 0.0, omega = 0.0; if ( f <= 0.0 ) { // damage do not grow tempKappa = status->giveKappa(); @@ -77,75 +71,63 @@ IsoInterfaceDamageMaterial_2 :: giveEngTraction_3d(FloatArray &answer, GaussPoin // damage grows tempKappa = equivStrain; // evaluate damage parameter - this->computeDamageParam(omega, tempKappa, jump, gp); + omega = this->computeDamageParam(tempKappa, jump, gp); } - this->give3dStiffnessMatrix_Eng(de, ElasticStiffness, gp, tStep); + auto de = this->give3dStiffnessMatrix_Eng(ElasticStiffness, gp, tStep); + auto answer = dot(de, jump); // damage in tension only if ( equivStrain >= 0.0 ) { - de.times(1.0 - omega); + answer *= 1.0 - omega; } - answer.beProductOf(de, jump); - // update gp status->letTempJumpBe(jump); status->letTempTractionBe(answer); status->setTempKappa(tempKappa); status->setTempDamage(omega); + + return answer; } -void -IsoInterfaceDamageMaterial_2 :: give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +IsoInterfaceDamageMaterial_2 :: give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - double om, un; IsoInterfaceDamageMaterialStatus_2 *status = static_cast< IsoInterfaceDamageMaterialStatus_2 * >( this->giveStatus(gp) ); // assemble eleastic stiffness - answer.resize(3, 3); - answer.zero(); - answer.at(1, 1) = kn; - answer.at(2, 2) = ks; - answer.at(3, 3) = ks; + auto answer = diag<3>({kn, ks, ks}); if ( rMode == ElasticStiffness ) { - return; + return answer; } + double om = min(status->giveTempDamage(), maxOmega); + double un = status->giveTempJump().at(1); if ( rMode == SecantStiffness ) { - // Secant stiffness - om = status->giveTempDamage(); - un = status->giveTempJump().at(1); - om = min(om, maxOmega); // damage in tension only if ( un >= 0 ) { - answer.times(1.0 - om); + answer *= 1.0 - om; } - return; - } else { - // Tangent Stiffness - FloatArray se; - const FloatArray &e = status->giveTempJump(); - se.beProductOf(answer, e); - - om = status->giveTempDamage(); - un = status->giveTempJump().at(1); - om = min(om, maxOmega); + return answer; + } else { // Tangent Stiffness // damage in tension only if ( un >= 0 ) { - answer.times(1.0 - om); - return; + answer *= 1.0 - om; #if 0 // Unreachable code - commented out to supress compiler warnings double dom = -( -e0 / un / un * exp( -( ft / gf ) * ( un - e0 ) ) + e0 / un * exp( -( ft / gf ) * ( un - e0 ) ) * ( -( ft / gf ) ) ); if ( ( om > 0. ) && ( status->giveTempKappa() > status->giveKappa() ) ) { + const auto &e = status->giveTempJump(); + auto se = dot(answer, e); answer.at(1, 1) -= se.at(1) * dom; answer.at(2, 1) -= se.at(2) * dom; } #endif } + return answer; } } @@ -182,10 +164,11 @@ IsoInterfaceDamageMaterial_2 :: giveIPValue(FloatArray &answer, GaussPoint *gp, } -IRResultType -IsoInterfaceDamageMaterial_2 :: initializeFrom(InputRecord *ir) +void +IsoInterfaceDamageMaterial_2 :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralInterfaceMaterial :: initializeFrom(ir); + std :: ifstream is; int nbrOfLinesToRead; @@ -237,8 +220,6 @@ IsoInterfaceDamageMaterial_2 :: initializeFrom(InputRecord *ir) // We add e0 to the strains since strains should be given as the increase in // strain relative to e0. strains.add(e0); - - return StructuralInterfaceMaterial :: initializeFrom(ir); } @@ -255,21 +236,21 @@ IsoInterfaceDamageMaterial_2 :: giveInputRecord(DynamicInputRecord &input) } -void -IsoInterfaceDamageMaterial_2 :: computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) +double +IsoInterfaceDamageMaterial_2 :: computeEquivalentStrain(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const { - kappa = macbra( strain.at(1) ); + return macbra( strain.at(1) ); } -void -IsoInterfaceDamageMaterial_2 :: computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *gp) +double +IsoInterfaceDamageMaterial_2 :: computeDamageParam(double kappa, const FloatArrayF<3> &strain, GaussPoint *gp) const { if ( kappa > this->e0 ) { // Linear interpolation between table values. // If out of bounds damage is set to the last given damage value in the table if ( kappa >= strains.at( strains.giveSize() ) ) { - omega = damages.at( damages.giveSize() ); + return damages.at( damages.giveSize() ); } else { // std::lower_bound uses binary search to find index with value bounding kappa from above int index = (int)(std :: lower_bound(strains.givePointer(), strains.givePointer() + strains.giveSize(), kappa) - strains.givePointer()); @@ -291,27 +272,24 @@ IsoInterfaceDamageMaterial_2 :: computeDamageParam(double &omega, double kappa, double y1 = damages(index ); // Interpolation formula - omega = y0 + ( y1 - y0 ) * ( kappa - x0 ) / ( x1 - x0 ); + return y0 + ( y1 - y0 ) * ( kappa - x0 ) / ( x1 - x0 ); } } else { - omega = 0.0; + return 0.0; } } -IsoInterfaceDamageMaterialStatus_2 :: IsoInterfaceDamageMaterialStatus_2(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g) +IsoInterfaceDamageMaterialStatus_2 :: IsoInterfaceDamageMaterialStatus_2(GaussPoint *g) : + StructuralInterfaceMaterialStatus(g) { kappa = tempKappa = 0.0; damage = tempDamage = 0.0; } -IsoInterfaceDamageMaterialStatus_2 :: ~IsoInterfaceDamageMaterialStatus_2() -{ } - - void -IsoInterfaceDamageMaterialStatus_2 :: printOutputAt(FILE *file, TimeStep *tStep) +IsoInterfaceDamageMaterialStatus_2 :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralInterfaceMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -340,17 +318,11 @@ IsoInterfaceDamageMaterialStatus_2 :: updateYourself(TimeStep *tStep) } -contextIOResultType -IsoInterfaceDamageMaterialStatus_2 :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +IsoInterfaceDamageMaterialStatus_2 :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralInterfaceMaterialStatus :: saveContext(stream, mode); - // write a raw data if ( !stream.write(kappa) ) { THROW_CIOERR(CIO_IOERR); } @@ -358,21 +330,13 @@ IsoInterfaceDamageMaterialStatus_2 :: saveContext(DataStream &stream, ContextMod if ( !stream.write(damage) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -IsoInterfaceDamageMaterialStatus_2 :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +IsoInterfaceDamageMaterialStatus_2 :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralInterfaceMaterialStatus :: restoreContext(stream, mode); - // read parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data if ( !stream.read(kappa) ) { THROW_CIOERR(CIO_IOERR); } @@ -380,7 +344,5 @@ IsoInterfaceDamageMaterialStatus_2 :: restoreContext(DataStream &stream, Context if ( !stream.read(damage) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage02.h b/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage02.h index ed5c12647..61f9ff765 100644 --- a/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage02.h +++ b/src/sm/Materials/InterfaceMaterials/Deprecated/isointerfacedamage02.h @@ -35,8 +35,8 @@ #ifndef isointerfacedamage02_h #define isointerfacedamage02_h -#include "../structuralinterfacematerial.h" -#include "../structuralinterfacematerialstatus.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" #include @@ -60,43 +60,41 @@ class IsoInterfaceDamageMaterialStatus_2 : public StructuralInterfaceMaterialSta { protected: /// Scalar measure of the largest equivalent displacement ever reached in material. - double kappa; + double kappa = 0.; /// Non-equilibrated scalar measure of the largest equivalent displacement. - double tempKappa; + double tempKappa = 0.; /// Damage level of material. - double damage; + double damage = 0.; /// Non-equilibrated damage level of material. - double tempDamage; + double tempDamage = 0.; public: /// Constructor - IsoInterfaceDamageMaterialStatus_2(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~IsoInterfaceDamageMaterialStatus_2(); + IsoInterfaceDamageMaterialStatus_2(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; /// Returns the last equilibrated scalar measure of the largest strain level. - double giveKappa() { return kappa; } + double giveKappa() const { return kappa; } /// Returns the temp. scalar measure of the largest strain level. - double giveTempKappa() { return tempKappa; } + double giveTempKappa() const { return tempKappa; } /// Sets the temp scalar measure of the largest strain level to given value. void setTempKappa(double newKappa) { tempKappa = newKappa; } /// Returns the last equilibrated damage level. - double giveDamage() { return damage; } + double giveDamage() const override { return damage; } /// Returns the temp. damage level. - double giveTempDamage() { return tempDamage; } + double giveTempDamage() const override { return tempDamage; } /// Sets the temp damage level to given value. void setTempDamage(double newDamage) { tempDamage = newDamage; } // definition - virtual const char *giveClassName() const { return "IsoInterfaceDamageMaterialStatus"; } + const char *giveClassName() const override { return "IsoInterfaceDamageMaterialStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -126,15 +124,15 @@ class IsoInterfaceDamageMaterial_2 : public StructuralInterfaceMaterial { protected: /// Elastic properties (normal moduli). - double kn; + double kn = 0.; /// Shear moduli. - double ks; + double ks = 0.; /// Tension strength. - double ft; + double ft = 0.; /// Limit elastic deformation. - double e0; + double e0 = 0.; /// Maximum limit on omega. The purpose is elimination of a too compliant material which may cause convergency problems. Set to something like 0.99 if needed. - double maxOmega; + double maxOmega = 0.999999; /// Name of table file std :: string tablename; /// Damages read from the second column in the table file @@ -145,42 +143,39 @@ class IsoInterfaceDamageMaterial_2 : public StructuralInterfaceMaterial public: /// Constructor IsoInterfaceDamageMaterial_2(int n, Domain * d); - /// Destructor - virtual ~IsoInterfaceDamageMaterial_2(); - virtual int hasNonLinearBehaviour() { return 1; } - virtual bool hasAnalyticalTangentStiffness() const { return true; } + bool hasAnalyticalTangentStiffness() const override { return true; } - virtual const char *giveInputRecordName() const { return _IFT_IsoInterfaceDamageMaterial_2_Name; } - virtual const char *giveClassName() const { return "IsoInterfaceDamageMaterial"; } + const char *giveInputRecordName() const override { return _IFT_IsoInterfaceDamageMaterial_2_Name; } + const char *giveClassName() const override { return "IsoInterfaceDamageMaterial"; } - virtual void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); - virtual void give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + FloatArrayF<3> giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; /** * Computes the equivalent strain measure from given strain vector (full form). - * @param[out] kappa Return parameter containing the corresponding equivalent strain. * @param strain Total strain vector in full form. * @param gp Integration point. * @param tStep Time step. + * @return Equiv strain measure. */ - virtual void computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); + virtual double computeEquivalentStrain(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const; /** * computes the value of damage parameter omega, based on given value of equivalent strain. - * @param[out] omega Contains result. * @param kappa Equivalent strain measure. * @param strain Total strain vector in full form. (unnecessary?) * @param gp Integration point. + * @return Omega. */ - virtual void computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *gp); + virtual double computeDamageParam(double kappa, const FloatArrayF<3> &strain, GaussPoint *gp) const; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new IsoInterfaceDamageMaterialStatus_2(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new IsoInterfaceDamageMaterialStatus_2(gp); } }; } // end namespace oofem #endif // isointerfacedamage01_h diff --git a/src/sm/Materials/InterfaceMaterials/Deprecated/simpleinterfacemat.C b/src/sm/Materials/InterfaceMaterials/Deprecated/simpleinterfacemat.C index fc070a4a8..11e8d7cb7 100644 --- a/src/sm/Materials/InterfaceMaterials/Deprecated/simpleinterfacemat.C +++ b/src/sm/Materials/InterfaceMaterials/Deprecated/simpleinterfacemat.C @@ -33,7 +33,7 @@ */ #include "simpleinterfacemat.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" @@ -48,78 +48,94 @@ REGISTER_Material(SimpleInterfaceMaterial); SimpleInterfaceMaterial :: SimpleInterfaceMaterial(int n, Domain *d) : StructuralInterfaceMaterial(n, d) { } -SimpleInterfaceMaterial :: ~SimpleInterfaceMaterial() { } - - -void -SimpleInterfaceMaterial :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) +FloatArrayF<3> +SimpleInterfaceMaterial :: giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const { SimpleInterfaceMaterialStatus *status = static_cast< SimpleInterfaceMaterialStatus * >( this->giveStatus(gp) ); bool shearYieldingFlag = false; - FloatArray shearJump(2), shearTraction; - FloatArray tempShearStressShift = status->giveShearStressShift(); double normalStrain = jump.at(1); - double normalStress, maxShearStress, dp; + double normalStress, maxShearStress; double shift = -this->kn * this->stiffCoeff * normalClearance; - if ( normalStrain + normalClearance <= 0. ) { + if (regularizedModel) { + normalStress = 0.5*this->kn*(normalClearance+normalStrain)- + ((this->kn*0.5)/(m))*log(fabs(cosh(m*(normalClearance+normalStrain))))+ + 0.5*this->stiffCoeff*this->kn*(normalClearance+normalStrain)+ + ((this->stiffCoeff*this->kn*0.5)/(m))*log(fabs(cosh(m*(normalClearance+normalStrain)))); + maxShearStress = fabs(normalStress) * this->frictCoeff; + } else { + if ( normalStrain + normalClearance <= 0. ) { normalStress = this->kn * ( normalStrain + normalClearance ) + shift; //in compression and after the clearance gap closed maxShearStress = fabs(normalStress) * this->frictCoeff; - } else { + } else { normalStress = this->kn * this->stiffCoeff * ( normalStrain + normalClearance ) + shift; maxShearStress = 0.; + } } - - shearJump.at(1) = jump.at(2); - shearJump.at(2) = jump.at(3); - shearTraction.beScaled(this->ks, shearJump); - shearTraction.subtract(tempShearStressShift); - dp = shearTraction.dotProduct(shearTraction, 2); - if ( dp > maxShearStress * maxShearStress ) { + FloatArrayF<2> tempShearStressShift = status->giveShearStressShift(); + FloatArrayF<2> shearJump = {jump.at(2), jump.at(3)}; + auto shearTraction = this->ks * shearJump - tempShearStressShift; + double dpn = norm(shearTraction); + if ( dpn > maxShearStress ) { shearYieldingFlag = true; - shearTraction.times( maxShearStress / sqrt(dp) ); + shearTraction *= maxShearStress / dpn; } - tempShearStressShift.beScaled(this->ks, shearJump); - tempShearStressShift.subtract(shearTraction); + tempShearStressShift = this->ks * shearJump - shearTraction; double lim = 1.e+50; - answer.resize(3); - answer.at(1) = max(min(normalStress, lim), -lim); //threshold on maximum/minimum - answer.at(2) = shearTraction.at(1); - answer.at(3) = shearTraction.at(2); + FloatArrayF<3> answer = {max(min(normalStress, lim), -lim), shearTraction.at(1), shearTraction.at(2)}; // update gp status->setShearYieldingFlag(shearYieldingFlag); status->setTempShearStressShift(tempShearStressShift); status->letTempJumpBe(jump); status->letTempTractionBe(answer); + return answer; } -void -SimpleInterfaceMaterial :: give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +SimpleInterfaceMaterial :: give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { SimpleInterfaceMaterialStatus *status = static_cast< SimpleInterfaceMaterialStatus * >( this->giveStatus(gp) ); double normalJump = status->giveTempJump().at(1); - answer.resize(3, 3); - if ( rMode == SecantStiffness || rMode == TangentStiffness ) { + FloatMatrixF<3,3> answer; + + if (regularizedModel) { + answer.at(1, 1) = this->kn+0.5*tanh(m*(normalJump+this->normalClearance))*(this->kn*this->stiffCoeff-this->kn); + if ( status->giveShearYieldingFlag() ) { + FloatArray jump = status->giveTempJump(); + FloatArray traction = status->giveTempTraction(); + answer.at(2, 2) = answer.at(3, 3) = traction.at(2)/jump.at(2); + } else { + answer.at(2, 2) = answer.at(3, 3) = ks;//this->kn; //in compression and after the clearance gap closed + } + } else { + + if ( rMode == SecantStiffness || rMode == TangentStiffness ) { if ( normalJump + normalClearance <= 0. ) { - answer.at(1, 1) = kn; - if ( status->giveShearYieldingFlag() ) - answer.at(2, 2) = answer.at(3, 3) = 0; - else - answer.at(2, 2) = answer.at(3, 3) = ks;//this->kn; //in compression and after the clearance gap closed + answer.at(1, 1) = kn; + if ( status->giveShearYieldingFlag() ) { + FloatArray jump = status->giveTempJump(); + FloatArray traction = status->giveTempTraction(); + + answer.at(2, 2) = answer.at(3, 3) = traction.at(2)/jump.at(2); + } else { + answer.at(2, 2) = answer.at(3, 3) = ks;//this->kn; //in compression and after the clearance gap closed + } } else { - answer.at(1, 1) = this->kn * this->stiffCoeff; - answer.at(2, 2) = answer.at(3, 3) = 0; + answer.at(1, 1) = this->kn * this->stiffCoeff; + answer.at(2, 2) = answer.at(3, 3) = 0; } - } else { + } else { answer.at(1, 1) = kn; answer.at(2, 2) = answer.at(3, 3) = this->ks; + } } + return answer; } @@ -130,10 +146,10 @@ SimpleInterfaceMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, Inter } -IRResultType -SimpleInterfaceMaterial :: initializeFrom(InputRecord *ir) +void +SimpleInterfaceMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralInterfaceMaterial :: initializeFrom(ir); frictCoeff = 0.; stiffCoeff = 0.; @@ -144,8 +160,9 @@ SimpleInterfaceMaterial :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, frictCoeff, _IFT_SimpleInterfaceMaterial_frictCoeff); IR_GIVE_OPTIONAL_FIELD(ir, stiffCoeff, _IFT_SimpleInterfaceMaterial_stiffCoeff); IR_GIVE_OPTIONAL_FIELD(ir, normalClearance, _IFT_SimpleInterfaceMaterial_normalClearance); + IR_GIVE_OPTIONAL_FIELD(ir, regularizedModel, _IFT_SimpleInterfaceMaterial_regularizedModel); + IR_GIVE_OPTIONAL_FIELD(ir, m, _IFT_SimpleInterfaceMaterial_regularizationCoeff); - return StructuralInterfaceMaterial :: initializeFrom(ir); } @@ -157,25 +174,19 @@ SimpleInterfaceMaterial :: giveInputRecord(DynamicInputRecord &input) input.setField(this->frictCoeff, _IFT_SimpleInterfaceMaterial_frictCoeff); input.setField(this->stiffCoeff, _IFT_SimpleInterfaceMaterial_stiffCoeff); input.setField(this->normalClearance, _IFT_SimpleInterfaceMaterial_normalClearance); -} - -SimpleInterfaceMaterialStatus :: SimpleInterfaceMaterialStatus(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g) -{ - shearStressShift.resize(2); - tempShearStressShift.resize(2); - shearStressShift.zero(); - tempShearStressShift.zero(); - shearYieldingFlag = false; + input.setField(this->regularizedModel, _IFT_SimpleInterfaceMaterial_regularizedModel); + input.setField(this->m, _IFT_SimpleInterfaceMaterial_regularizationCoeff); + } -SimpleInterfaceMaterialStatus :: ~SimpleInterfaceMaterialStatus() -{ } +SimpleInterfaceMaterialStatus :: SimpleInterfaceMaterialStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) +{} void -SimpleInterfaceMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +SimpleInterfaceMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralInterfaceMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -200,47 +211,24 @@ SimpleInterfaceMaterialStatus :: updateYourself(TimeStep *tStep) } -const FloatArray & -SimpleInterfaceMaterialStatus :: giveShearStressShift() -{ - return shearStressShift; -} - - -contextIOResultType -SimpleInterfaceMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +SimpleInterfaceMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralInterfaceMaterialStatus :: saveContext(stream, mode); - // save parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write a raw data //if ( !stream.write(kappa) ) { //THROW_CIOERR(CIO_IOERR); //} - - return CIO_OK; } -contextIOResultType -SimpleInterfaceMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +SimpleInterfaceMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralInterfaceMaterialStatus :: restoreContext(stream, mode); - // read parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data //if ( !stream.read(kappa) ) { //THROW_CIOERR(CIO_IOERR); //} - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/Materials/InterfaceMaterials/Deprecated/simpleinterfacemat.h b/src/sm/Materials/InterfaceMaterials/Deprecated/simpleinterfacemat.h index 38abda17a..4db5d15e2 100644 --- a/src/sm/Materials/InterfaceMaterials/Deprecated/simpleinterfacemat.h +++ b/src/sm/Materials/InterfaceMaterials/Deprecated/simpleinterfacemat.h @@ -35,8 +35,8 @@ #ifndef simpleinterfacemat_h #define simpleinterfacemat_h -#include "../structuralinterfacematerial.h" -#include "../structuralinterfacematerialstatus.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" ///@name Input fields for SimpleInterfaceMaterial //@{ @@ -46,6 +46,8 @@ #define _IFT_SimpleInterfaceMaterial_frictCoeff "fc" #define _IFT_SimpleInterfaceMaterial_stiffCoeff "stiffcoeff" #define _IFT_SimpleInterfaceMaterial_normalClearance "normalclearance" +#define _IFT_SimpleInterfaceMaterial_regularizedModel "regularized" +#define _IFT_SimpleInterfaceMaterial_regularizationCoeff "m" //@} namespace oofem { @@ -55,31 +57,27 @@ namespace oofem { class SimpleInterfaceMaterialStatus : public StructuralInterfaceMaterialStatus { protected: - bool shearYieldingFlag; - FloatArray shearStressShift, tempShearStressShift; - + bool shearYieldingFlag = false; + FloatArrayF<2> shearStressShift, tempShearStressShift; public: /// Constructor - SimpleInterfaceMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~SimpleInterfaceMaterialStatus(); + SimpleInterfaceMaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - // definition - virtual const char *giveClassName() const { return "SimpleInterfaceMaterialStatus"; } + const char *giveClassName() const override { return "SimpleInterfaceMaterialStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - const FloatArray &giveShearStressShift(); - void setTempShearStressShift(FloatArray newShearStressShift) { tempShearStressShift = newShearStressShift; } - bool giveShearYieldingFlag(){return shearYieldingFlag;} - void setShearYieldingFlag(bool sY){ shearYieldingFlag = sY;} + const FloatArrayF<2> &giveShearStressShift() const { return shearStressShift; } + void setTempShearStressShift(const FloatArrayF<2> &newShearStressShift) { tempShearStressShift = newShearStressShift; } + bool giveShearYieldingFlag() { return shearYieldingFlag; } + void setShearYieldingFlag(bool sY) { shearYieldingFlag = sY; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -92,33 +90,33 @@ class SimpleInterfaceMaterialStatus : public StructuralInterfaceMaterialStatus class SimpleInterfaceMaterial : public StructuralInterfaceMaterial { protected: - double kn, ks; - double stiffCoeff; - double frictCoeff; + double kn = 0., ks = 0.; + double stiffCoeff = 0.; + double frictCoeff = 0.; /// Normal distance which needs to be closed when interface element should act in compression (distance is 0 by default). - double normalClearance; + double normalClearance = 0.; + bool regularizedModel = false; + double m = 15.0; + public: /// Constructor SimpleInterfaceMaterial(int n, Domain * d); - /// Destructor - virtual ~SimpleInterfaceMaterial(); - virtual int hasNonLinearBehaviour() { return 1; } - virtual bool hasAnalyticalTangentStiffness() const { return true; } + bool hasAnalyticalTangentStiffness() const override { return true; } - virtual const char *giveInputRecordName() const { return _IFT_SimpleInterfaceMaterial_Name; } - virtual const char *giveClassName() const { return "SimpleInterfaceMaterial"; } + const char *giveInputRecordName() const override { return _IFT_SimpleInterfaceMaterial_Name; } + const char *giveClassName() const override { return "SimpleInterfaceMaterial"; } - virtual void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); - virtual void give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + FloatArrayF<3> giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new SimpleInterfaceMaterialStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new SimpleInterfaceMaterialStatus(gp); } }; } // end namespace oofem #endif // simpleinterfacemat_h diff --git a/src/sm/Materials/InterfaceMaterials/bondceb.C b/src/sm/Materials/InterfaceMaterials/bondceb.C index ab3668ed5..858bfb3be 100644 --- a/src/sm/Materials/InterfaceMaterials/bondceb.C +++ b/src/sm/Materials/InterfaceMaterials/bondceb.C @@ -46,22 +46,16 @@ namespace oofem { REGISTER_Material(BondCEBMaterial); BondCEBMaterial :: BondCEBMaterial(int n, Domain *d) : StructuralInterfaceMaterial(n, d) -{ - tauf = 0.; - alpha = 0.4; -} - +{} -BondCEBMaterial :: ~BondCEBMaterial() { } - -void -BondCEBMaterial :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) +FloatArrayF<3> +BondCEBMaterial :: giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const { BondCEBMaterialStatus *status = static_cast< BondCEBMaterialStatus * >( this->giveStatus(gp) ); // normal traction evaluated elastically - answer.resize(3); + FloatArrayF<3> answer; answer.at(1) = kn * jump.at(1); // trial values of shear tractions evaluated elastically @@ -96,21 +90,20 @@ BondCEBMaterial :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const status->letTempJumpBe(jump); status->letTempTractionBe(answer); status->setTempKappa(tempKappa); + + return answer; } -void -BondCEBMaterial :: give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +BondCEBMaterial :: give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { ///@todo Only elastic tangent supported - answer.resize(3, 3); - answer.zero(); - answer.at(1, 1) = kn; - answer.at(2, 2) = answer.at(3, 3) = ks; + return diag<3>({kn, ks, ks}); } double -BondCEBMaterial :: evaluateBondStress(const double kappa) +BondCEBMaterial :: evaluateBondStress(const double kappa) const { if ( kappa <= 0. ) return 0.; @@ -137,10 +130,10 @@ BondCEBMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalState } } -IRResultType -BondCEBMaterial :: initializeFrom(InputRecord *ir) +void +BondCEBMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralInterfaceMaterial :: initializeFrom(ir); // mandatory parameters IR_GIVE_FIELD(ir, kn, _IFT_BondCEBMaterial_kn); @@ -155,14 +148,13 @@ BondCEBMaterial :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, alpha, _IFT_BondCEBMaterial_al); // dependent parameter - s0 = pow(pow(s1, -alpha)*taumax/ks, 1./(1.-alpha)); - if ( s0 > s1 ) { - s0 = s1; - ks = taumax/s1; - OOFEM_WARNING("Parameter ks adjusted"); - } - - return StructuralInterfaceMaterial :: initializeFrom(ir); + //@todo: why not simply if ks s1 ) { + s0 = s1; + ks = taumax/s1; + OOFEM_WARNING("Parameter ks adjusted"); + } } @@ -181,18 +173,12 @@ BondCEBMaterial :: giveInputRecord(DynamicInputRecord &input) -BondCEBMaterialStatus :: BondCEBMaterialStatus(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g) -{ - kappa = tempKappa = 0.0; -} - - -BondCEBMaterialStatus :: ~BondCEBMaterialStatus() -{ } +BondCEBMaterialStatus :: BondCEBMaterialStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) +{} void -BondCEBMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +BondCEBMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralInterfaceMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -219,39 +205,23 @@ BondCEBMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -BondCEBMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +BondCEBMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralInterfaceMaterialStatus :: saveContext(stream, mode); - // write a raw data if ( !stream.write(kappa) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -BondCEBMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +BondCEBMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralInterfaceMaterialStatus :: restoreContext(stream, mode); - // read parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data if ( !stream.read(kappa) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/Materials/InterfaceMaterials/bondceb.h b/src/sm/Materials/InterfaceMaterials/bondceb.h index be9d37146..c349ac6a5 100644 --- a/src/sm/Materials/InterfaceMaterials/bondceb.h +++ b/src/sm/Materials/InterfaceMaterials/bondceb.h @@ -60,33 +60,30 @@ class BondCEBMaterialStatus : public StructuralInterfaceMaterialStatus { protected: /// Cumulative slip. - double kappa; + double kappa = 0.; /// Non-equilibrated cumulative slip. - double tempKappa; + double tempKappa = 0.; public: /// Constructor - BondCEBMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~BondCEBMaterialStatus(); + BondCEBMaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; /// Returns the last equilibrated cumulative slip. - double giveKappa() { return kappa; } + double giveKappa() const { return kappa; } /// Returns the temporary cumulative slip. - double giveTempKappa() { return tempKappa; } + double giveTempKappa() const { return tempKappa; } /// Sets the temporary cumulative slip to the given value. void setTempKappa(double newKappa) { tempKappa = newKappa; } - // definition - virtual const char *giveClassName() const { return "BondCEBMaterialStatus"; } + const char *giveClassName() const override { return "BondCEBMaterialStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -106,42 +103,39 @@ class BondCEBMaterial : public StructuralInterfaceMaterial { protected: /// Normal elastic stiffness. - double kn; + double kn = 0.; /// Shear elastic stiffness. - double ks; + double ks = 0.; /// Shear strength. - double taumax; + double taumax = 0.; /// Residual shear stress. - double tauf; + double tauf = 0.; /// Characteristic slip values. - double s0, s1, s2, s3; + double s0 = 0., s1 = 0., s2 = 0., s3 = 0.; /// Exponent. - double alpha; + double alpha = 0.4; public: /// Constructor BondCEBMaterial(int n, Domain * d); - /// Destructor - virtual ~BondCEBMaterial(); - virtual int hasNonLinearBehaviour() { return 1; } - virtual bool hasAnalyticalTangentStiffness() const { return true; } + bool hasAnalyticalTangentStiffness() const override { return true; } - virtual const char *giveInputRecordName() const { return _IFT_BondCEBMaterial_Name; } - virtual const char *giveClassName() const { return "BondCEBMaterial"; } + const char *giveInputRecordName() const override { return _IFT_BondCEBMaterial_Name; } + const char *giveClassName() const override { return "BondCEBMaterial"; } - virtual void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); - virtual void give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + FloatArrayF<3> giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new BondCEBMaterialStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new BondCEBMaterialStatus(gp); } protected: - double evaluateBondStress(const double kappa); - }; + double evaluateBondStress(const double kappa) const; +}; } // end namespace oofem #endif // bondceb_h diff --git a/src/sm/Materials/InterfaceMaterials/cohint.C b/src/sm/Materials/InterfaceMaterials/cohint.C index 24ae9b12f..5ccad17b0 100644 --- a/src/sm/Materials/InterfaceMaterials/cohint.C +++ b/src/sm/Materials/InterfaceMaterials/cohint.C @@ -47,41 +47,39 @@ REGISTER_Material(CohesiveInterfaceMaterial); CohesiveInterfaceMaterial :: CohesiveInterfaceMaterial(int n, Domain *d) : StructuralInterfaceMaterial(n, d) { } -void -CohesiveInterfaceMaterial :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) +FloatArrayF<3> +CohesiveInterfaceMaterial :: giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const { StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus(gp) ); - answer.resize(3); - double x = jump.at(1) + transitionOpening; - - if (stiffCoeffKn == 1.){//tension stiffness = compression stiffness + + FloatArrayF<3> answer; + + if ( stiffCoeffKn == 1. ){ //tension stiffness = compression stiffness answer.at(1) = kn*x; } else { //composed function from two atan's to have smooth intersection between tension and compression answer.at(1) = (M_PI/2. + atan(smoothMag*x))/M_PI*kn*stiffCoeffKn*x + (M_PI/2.-atan(smoothMag*x))/M_PI*kn*x; } - + // shear part of elastic stress-strain law answer.at(2) = ks * jump.at(2); answer.at(3) = ks * jump.at(3); - + // update gp status->letTempJumpBe(jump); status->letTempTractionBe(answer); + return answer; } -void -CohesiveInterfaceMaterial :: give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +CohesiveInterfaceMaterial :: give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - answer.resize(3, 3); - answer.zero(); - StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus(gp) ); + // double normalJump = status->giveTempJump().at(1); - // if (normalJump > 0.) { // if(normalJumpgiveTempJump().at(1) + transitionOpening; - - if (stiffCoeffKn == 1.){//tension stiffness = compression stiffness - answer.at(1,1) = kn; + + double normal; + if ( stiffCoeffKn == 1. ) { //tension stiffness = compression stiffness + normal = kn; } else { //TangentStiffness by derivating traction with regards to x (=relative displacement) - answer.at(1,1) = (M_PI/2. + atan(smoothMag*x))/M_PI*kn*stiffCoeffKn + (M_PI/2.-atan(smoothMag*x))/M_PI*kn + smoothMag*kn*stiffCoeffKn*x/M_PI/(smoothMag*smoothMag*x*x+1) - smoothMag*kn*x/M_PI/(smoothMag*smoothMag*x*x+1); + normal = (M_PI/2. + atan(smoothMag*x))/M_PI*kn*stiffCoeffKn + (M_PI/2.-atan(smoothMag*x))/M_PI*kn + smoothMag*kn*stiffCoeffKn*x/M_PI/(smoothMag*smoothMag*x*x+1) - smoothMag*kn*x/M_PI/(smoothMag*smoothMag*x*x+1); } - - //answer.at(1, 1) = kn; - answer.at(2, 2) = ks; - answer.at(3, 3) = ks; -} -int -CohesiveInterfaceMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) -{ - return StructuralInterfaceMaterial :: giveIPValue(answer, gp, type, tStep); + return diag<3>({normal, ks, ks}); } -IRResultType -CohesiveInterfaceMaterial :: initializeFrom(InputRecord *ir) + +void +CohesiveInterfaceMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; + StructuralInterfaceMaterial :: initializeFrom(ir); // elastic parameters IR_GIVE_FIELD(ir, kn, _IFT_CohesiveInterfaceMaterial_kn); @@ -141,8 +132,6 @@ CohesiveInterfaceMaterial :: initializeFrom(InputRecord *ir) smoothMag = 1.e+8; IR_GIVE_OPTIONAL_FIELD(ir, smoothMag, _IFT_CohesiveInterfaceMaterial_smoothMag); - - return StructuralInterfaceMaterial :: initializeFrom(ir); } void diff --git a/src/sm/Materials/InterfaceMaterials/cohint.h b/src/sm/Materials/InterfaceMaterials/cohint.h index 2ed8de941..6b5f32411 100644 --- a/src/sm/Materials/InterfaceMaterials/cohint.h +++ b/src/sm/Materials/InterfaceMaterials/cohint.h @@ -57,41 +57,36 @@ class CohesiveInterfaceMaterial : public StructuralInterfaceMaterial { protected: /// Elastic properties (normal and shear moduli). - double kn, ks; - + double kn = 0., ks = 0.; + /// Reduction of normal stiffness when in tension - double stiffCoeffKn; - + double stiffCoeffKn = 0.; + /// Opening when material stiffness changes from kn to kn*stiffCoeffKn - double transitionOpening; - + double transitionOpening = 0.; + /// Smoothing region between tension and compression stiffness. /// Uses atan(smoothMag*x) function, where (smoothMag*x) needs to be 6 /// to be 10% off the asymptotic value. SmoothMag is by default 1.e+4. /// Higher values mean sharper transition. - double smoothMag; - + double smoothMag = 0.; + public: /// Constructor CohesiveInterfaceMaterial(int n, Domain * d); - /// Destructor - virtual ~CohesiveInterfaceMaterial() { } - - virtual int hasNonLinearBehaviour() { return 0; } - virtual bool hasAnalyticalTangentStiffness() const { return true; } - virtual const char *giveClassName() const { return "CohesiveInterfaceMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_CohesiveInterfaceMaterial_Name; } + bool hasAnalyticalTangentStiffness() const override { return true; } - virtual void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); - virtual void give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + const char *giveClassName() const override { return "CohesiveInterfaceMaterial"; } + const char *giveInputRecordName() const override { return _IFT_CohesiveInterfaceMaterial_Name; } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + FloatArrayF<3> giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new StructuralInterfaceMaterialStatus(1, FEMComponent :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new StructuralInterfaceMaterialStatus(gp); } }; } // namespace oofem #endif diff --git a/src/sm/Materials/InterfaceMaterials/expczmaterial.C b/src/sm/Materials/InterfaceMaterials/expczmaterial.C index 49b6ad37d..9d8e14f0c 100644 --- a/src/sm/Materials/InterfaceMaterials/expczmaterial.C +++ b/src/sm/Materials/InterfaceMaterials/expczmaterial.C @@ -48,10 +48,6 @@ ExpCZMaterial :: ExpCZMaterial(int n, Domain *d) : StructuralInterfaceMaterial(n { } -ExpCZMaterial :: ~ExpCZMaterial() -{ } - - void ExpCZMaterial :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) { @@ -60,19 +56,17 @@ ExpCZMaterial :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const Fl /// @todo only study normal stress for now // no degradation in shear // jumpVector = [normal shear1 shear2] + //auto [gn, gs1, gs2] = jump; double gn = jump.at(1); double gs1 = jump.at(2); double gs2 = jump.at(3); double gs = sqrt(gs1 * gs1 + gs2 * gs2); - double xin = gn / ( gn0 + tolerance ); - double xit = gs / ( gs0 + tolerance ); - double tn = GIc / gn0 *exp(-xin) * ( xin * exp(-xit * xit) + ( 1.0 - q ) / ( r - 1.0 ) * ( 1.0 - exp(-xit * xit) ) * ( r - xin ) ); + double xin = gn / ( gn0 + tolerance ); + double xit = gs / ( gs0 + tolerance ); + double tn = GIc / gn0 *exp(-xin) * ( xin * exp(-xit * xit) + ( 1.0 - q ) / ( r - 1.0 ) * ( 1.0 - exp(-xit * xit) ) * ( r - xin ) ); - answer.resize(3); - answer.at(1) = tn; - answer.at(2) = 0.0; - answer.at(3) = 0.0; + answer = {tn, 0., 0.}; // update gp status->letTempJumpBe(jump); @@ -85,7 +79,7 @@ ExpCZMaterial :: give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode { ExpCZMaterialStatus *status = static_cast< ExpCZMaterialStatus * >( this->giveStatus(gp) ); - const FloatArray &jumpVector = status->giveTempJump(); + const auto &jumpVector = status->giveTempJump(); // jumpVector = [normal shear1 shear2] double gn = jumpVector.at(1); double gs1 = jumpVector.at(2); @@ -93,14 +87,13 @@ ExpCZMaterial :: give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode double gs = sqrt(gs1 * gs1 + gs2 * gs2); if ( rMode == TangentStiffness ) { - answer.resize(3, 3); - answer.zero(); - double xin = gn / ( gn0 + tolerance ); double xit = gs / ( gs0 + tolerance ); double dtndgn = GIc / gn0 / gn0 *exp(-xin) * ( ( 1.0 - xin ) * exp(-xit * xit) + ( 1.0 - q ) / ( r - 1.0 ) * ( 1.0 - exp(-xit * xit) ) * ( -r + xin - 1.0 ) ); + answer.resize(3, 3); + answer.zero(); answer.at(1, 1) = dtndgn; } else { OOFEM_ERROR("unknown MatResponseMode"); @@ -116,11 +109,9 @@ ExpCZMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateTy } -IRResultType -ExpCZMaterial :: initializeFrom(InputRecord *ir) +void +ExpCZMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, this->GIc, _IFT_ExpCZMaterial_g1c); this->sigfs = 0.0; @@ -137,10 +128,8 @@ ExpCZMaterial :: initializeFrom(InputRecord *ir) // check validity of the material paramters if ( this->GIc < 0.0 ) { - OOFEM_WARNING("GIc is negative (%.2e)", this->GIc); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_ExpCZMaterial_g1c, "GIc must be positive"); } - return IRRT_OK; } int @@ -169,11 +158,8 @@ ExpCZMaterial :: printYourself() printf(" r = %e \n", this->r); } -ExpCZMaterialStatus :: ExpCZMaterialStatus(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g) -{ } - -ExpCZMaterialStatus :: ~ExpCZMaterialStatus() +ExpCZMaterialStatus :: ExpCZMaterialStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) { } @@ -207,17 +193,11 @@ ExpCZMaterialStatus :: updateYourself(TimeStep *tStep) } #if 0 -contextIOResultType -ExpCZMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +ExpCZMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralInterfaceMaterialStatus :: saveContext(stream, mode); - // write a raw data if ( !stream.write(kappa) ) { THROW_CIOERR(CIO_IOERR); } @@ -225,21 +205,13 @@ ExpCZMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *o if ( !stream.write(damage) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -ExpCZMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +ExpCZMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralInterfaceMaterialStatus :: restoreContext(stream, mode); - // read parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data if ( !stream.read(kappa) ) { THROW_CIOERR(CIO_IOERR); } @@ -247,8 +219,6 @@ ExpCZMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void if ( !stream.read(damage) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } #endif } // end namespace oofem diff --git a/src/sm/Materials/InterfaceMaterials/expczmaterial.h b/src/sm/Materials/InterfaceMaterials/expczmaterial.h index 31e8da337..f02f7f6f5 100644 --- a/src/sm/Materials/InterfaceMaterials/expczmaterial.h +++ b/src/sm/Materials/InterfaceMaterials/expczmaterial.h @@ -59,20 +59,17 @@ class ExpCZMaterialStatus : public StructuralInterfaceMaterialStatus public: /// Constructor - ExpCZMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~ExpCZMaterialStatus(); + ExpCZMaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; - // definition - virtual const char *giveClassName() const { return "ExpCZMaterialStatus"; } + const char *giveClassName() const override { return "ExpCZMaterialStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - //virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - //virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + //void saveContext(DataStream &stream, ContextMode mode) override; + //void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -92,42 +89,37 @@ class ExpCZMaterial : public StructuralInterfaceMaterial { protected: /// Material parameters - double kn0; - double ks0; - double GIc; - double GIIc; - double sigfn; - double sigfs; + double kn0 = 0.; + double ks0 = 0.; + double GIc = 0.; + double GIIc = 0.; + double sigfn = 0.; + double sigfs = 0.; /// normal jump at damage initiation - double gn0; + double gn0 = 0.; /// shear jump at damage initiations - double gs0; - double q; - double r; + double gs0 = 0.; + double q = 0.; + double r = 0.; public: /// Constructor ExpCZMaterial(int n, Domain * d); - /// Destructor - virtual ~ExpCZMaterial(); - virtual int hasNonLinearBehaviour() { return 1; } - virtual int checkConsistency(); + int checkConsistency() override; - virtual const char *giveClassName() const { return "ExpCZMaterial"; } + const char *giveClassName() const override { return "ExpCZMaterial"; } - virtual void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); - virtual void give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) override; + void give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual int giveIntVarCompFullIndx(IntArray &answer, InternalStateType type, MaterialMode mmode); - virtual int giveIPValueSize(InternalStateType type, GaussPoint *gp); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new ExpCZMaterialStatus(1, domain, gp); } - virtual void printYourself(); + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new ExpCZMaterialStatus(gp); } + void printYourself() override; }; } // end namespace oofem #endif // isointerfacedamage01_h diff --git a/src/sm/Materials/InterfaceMaterials/intmatbilinczelastic.C b/src/sm/Materials/InterfaceMaterials/intmatbilinczelastic.C index f1dd2e7ff..982a3c975 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatbilinczelastic.C +++ b/src/sm/Materials/InterfaceMaterials/intmatbilinczelastic.C @@ -48,102 +48,70 @@ REGISTER_Material(IntMatBilinearCZElastic); IntMatBilinearCZElastic :: IntMatBilinearCZElastic(int n, Domain *d) : StructuralInterfaceMaterial(n, d) { } -IntMatBilinearCZElastic :: ~IntMatBilinearCZElastic() { } - - -void -IntMatBilinearCZElastic :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jumpVector, - const FloatMatrix &F, TimeStep *tStep) +FloatArrayF<3> +IntMatBilinearCZElastic :: giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const { IntMatBilinearCZElasticStatus *status = static_cast< IntMatBilinearCZElasticStatus * >( this->giveStatus(gp) ); - answer.resize( jumpVector.giveSize() ); - answer.zero(); /// @todo only study normal stress for now // no degradation in shear // jumpVector = [normal shear1 shear2] - double gn = jumpVector.at(1); - double gs1 = jumpVector.at(2); - double gs2 = jumpVector.at(3); + //auto [gn, gs1, gs2] = jump; + double gn = jump.at(1); + double gs1 = jump.at(2); + double gs2 = jump.at(3); + double normal; if ( gn <= 0.0 ) { // compresssion - answer.at(1) = this->knc * gn; - answer.at(2) = this->ks0 * gs1; - answer.at(3) = this->ks0 * gs2; + normal = this->knc * gn; } else if ( gn <= this->gn0 ) { // first linear part - answer.at(1) = this->kn0 * gn; - answer.at(2) = this->ks0 * gs1; - answer.at(3) = this->ks0 * gs2; + normal = this->kn0 * gn; } else if ( gn <= this->gnmax ) { // softening branch - answer.at(1) = this->sigfn + this->kn1 * ( gn - this->gn0 ); - answer.at(2) = this->ks0 * gs1; - answer.at(3) = this->ks0 * gs2; + normal = this->sigfn + this->kn1 * ( gn - this->gn0 ); //printf("Softening branch...\n"); } else { - answer.at(1) = 0.0; // failed - answer.at(2) = this->ks0 * gs1; - answer.at(3) = this->ks0 * gs2; + normal = 0.0; // failed //printf("Failed...\n"); } + FloatArrayF<3> answer = {normal, this->ks0 * gs1, this->ks0 * gs2}; // update gp - status->letTempJumpBe(jumpVector); + status->letTempJumpBe(jump); status->letTempFirstPKTractionBe(answer); status->letTempTractionBe(answer); + return answer; } -void -IntMatBilinearCZElastic :: give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +IntMatBilinearCZElastic :: give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { IntMatBilinearCZElasticStatus *status = static_cast< IntMatBilinearCZElasticStatus * >( this->giveStatus(gp) ); - const FloatArray &jumpVector = status->giveTempJump(); + const auto &jumpVector = status->giveTempJump(); double gn = jumpVector.at(1); - answer.resize(3, 3); - answer.zero(); + double normal; if ( gn <= 0.0 ) { // compresssion - answer.at(1, 1) = this->knc; - answer.at(2, 2) = this->ks0; - answer.at(3, 3) = this->ks0; + normal = this->knc; } else if ( gn <= this->gn0 ) { // first linear part - answer.at(1, 1) = this->kn0; - answer.at(2, 2) = this->ks0; - answer.at(3, 3) = this->ks0; + normal = this->kn0; //printf("Linear branch...\n"); } else if ( gn <= this->gnmax ) { // softening branch - answer.at(1, 1) = this->kn1; - answer.at(2, 2) = this->ks0; // no degradation in shear - answer.at(3, 3) = this->ks0; + normal = this->kn1; //printf("Softening branch...\n"); } else { - answer.at(1, 1) = 0.0; // failed - answer.at(2, 2) = this->ks0; - answer.at(3, 3) = this->ks0; + normal = 0.0; // failed //printf("Failed...\n"); } + return diag<3>({normal, this->ks0, this->ks0}); } -int -IntMatBilinearCZElastic :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) -{ - if ( type == IST_DamageScalar ) { - answer.resize(1); - answer.at(1) = 0.0; // no damage - return 1; - } else { - return StructuralInterfaceMaterial :: giveIPValue(answer, gp, type, tStep); - } -} - const double tolerance = 1.0e-12; // small number -IRResultType -IntMatBilinearCZElastic :: initializeFrom(InputRecord *ir) +void +IntMatBilinearCZElastic :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, kn0, _IFT_IntMatBilinearCZElastic_kn); this->knc = kn0; // Defaults to the same stiffness in compression and tension IR_GIVE_OPTIONAL_FIELD(ir, this->knc, _IFT_IntMatBilinearCZElastic_knc); @@ -162,25 +130,19 @@ IntMatBilinearCZElastic :: initializeFrom(InputRecord *ir) this->gnmax = 2.0 * GIc / sigfn; // @todo defaults to zero - will this cause problems? this->kn1 = -this->sigfn / ( this->gnmax - this->gn0 ); // slope during softening part in normal dir - result = StructuralInterfaceMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + StructuralInterfaceMaterial :: initializeFrom(ir); // check validity of the material paramters double kn0min = 0.5 * this->sigfn * this->sigfn / this->GIc; if ( this->kn0 < 0.0 ) { - OOFEM_WARNING("stiffness kn0 is negative (%.2e)", this->kn0); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZElastic_kn, "stiffness kn0 is negative"); } else if ( this->ks0 < 0.0 ) { - OOFEM_WARNING("stiffness ks0 is negative (%.2e)", this->ks0); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZElastic_ks, "stiffness ks0 is negative"); } else if ( this->GIc < 0.0 ) { - OOFEM_WARNING("GIc is negative (%.2e)", this->GIc); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZElastic_g1c, "GIc is negative"); } else if ( this->kn0 < kn0min ) { // => gn0 > gnmax - //OOFEM_WARNING("kn0 (%.2e) is below minimum stiffness (%.2e), => gn0 > gnmax, which is unphysical", this->kn0, kn0min); - //return IRRT_BAD_FORMAT; + //throw ValueInputException(ir, _IFT_IntMatBilinearCZElastic_kn, "kn0 is below minimum stiffness, which is unphysical"); } - return IRRT_OK; } void IntMatBilinearCZElastic :: giveInputRecord(DynamicInputRecord &input) diff --git a/src/sm/Materials/InterfaceMaterials/intmatbilinczelastic.h b/src/sm/Materials/InterfaceMaterials/intmatbilinczelastic.h index 9d9672656..12898acfc 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatbilinczelastic.h +++ b/src/sm/Materials/InterfaceMaterials/intmatbilinczelastic.h @@ -55,25 +55,20 @@ namespace oofem { */ class IntMatBilinearCZElasticStatus : public StructuralInterfaceMaterialStatus { -protected: - public: /// Constructor - IntMatBilinearCZElasticStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~IntMatBilinearCZElasticStatus(); + IntMatBilinearCZElasticStatus(GaussPoint * g); - double giveDamage() { return 0.0; } // no damage in this model - virtual void printOutputAt(FILE *file, TimeStep *tStep); + double giveDamage() const override { return 0.0; } // no damage in this model + void printOutputAt(FILE *file, TimeStep *tStep) const override; - // definition - virtual const char *giveClassName() const { return "IntMatBilinearCZElasticStatus"; } + const char *giveClassName() const override { return "IntMatBilinearCZElasticStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - //virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - //virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + //void saveContext(DataStream &stream, ContextMode mode) override; + //void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -85,7 +80,7 @@ class IntMatBilinearCZElasticStatus : public StructuralInterfaceMaterialStatus * tractions in normal and tangent direction. * * The behaviour of the model is elastic, described by normal and shear stiffness components. - * Isotropic damage is initiated when the stress reaches the tensile strength. Damage evolution + * Isotropic damage is initiated when the stress reaches the tensile strength. Damage evolution * is governed by normal component of generalized strain vector (normal relative displacement) * by an exponential softening law. */ @@ -93,44 +88,38 @@ class IntMatBilinearCZElastic : public StructuralInterfaceMaterial { protected: /// Material parameters - double kn0; - double ks0; - double knc; // stiffness in compression - double GIc; - double sigfn; - double sigfs; + double kn0 = 0.; + double ks0 = 0.; + double knc = 0.; // stiffness in compression + double GIc = 0.; + double sigfn = 0.; + double sigfs = 0.; - double gn0; // normal jump at damage initiation - double gs0; // shear jump at damage initiations - double gnmax; // max normal jump + double gn0 = 0.; // normal jump at damage initiation + double gs0 = 0.; // shear jump at damage initiations + double gnmax = 0.; // max normal jump - double kn1; // slope during softening part + double kn1 = 0.; // slope during softening part - virtual int checkConsistency(); + int checkConsistency() override; void give3dInterfaceMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); public: /// Constructor IntMatBilinearCZElastic(int n, Domain * d); - /// Destructor - virtual ~IntMatBilinearCZElastic(); - - virtual int hasNonLinearBehaviour() { return 1; } - virtual const char *giveClassName() const { return "IntMatBilinearCZElastic"; } - virtual const char *giveInputRecordName() const { return _IFT_IntMatBilinearCZElastic_Name; } + const char *giveClassName() const override { return "IntMatBilinearCZElastic"; } + const char *giveInputRecordName() const override { return _IFT_IntMatBilinearCZElastic_Name; } - virtual void giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jumpVector, - const FloatMatrix &F, TimeStep *tStep); + FloatArrayF<3> giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new StructuralInterfaceMaterialStatus(1, domain, gp); } - void printYourself(); - virtual bool hasAnalyticalTangentStiffness() const { return true; } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new StructuralInterfaceMaterialStatus(gp); } + void printYourself() override; + bool hasAnalyticalTangentStiffness() const override { return true; } }; } // end namespace oofem #endif // isointerfacedamage01_h diff --git a/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstrom.C b/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstrom.C index 4b7fe8cd9..1395c01af 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstrom.C +++ b/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstrom.C @@ -51,34 +51,26 @@ REGISTER_Material( IntMatBilinearCZFagerstrom ); IntMatBilinearCZFagerstrom :: IntMatBilinearCZFagerstrom(int n, Domain *d) : StructuralInterfaceMaterial(n, d) { } -IntMatBilinearCZFagerstrom :: ~IntMatBilinearCZFagerstrom() { } - -void -IntMatBilinearCZFagerstrom :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &d, - const FloatMatrix &F, TimeStep *tStep) +FloatArrayF<3> +IntMatBilinearCZFagerstrom :: giveFirstPKTraction_3d(const FloatArrayF<3> &d, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const { ///@todo - need to rearrange traction and stiffness matrix so the first component is normal // returns vector in 3d stress space of receiver according to // previous level of stress and current // strain increment, the only way, how to correctly update gp records - + IntMatBilinearCZFagerstromStatus *status = static_cast< IntMatBilinearCZFagerstromStatus * >( this->giveStatus(gp) ); - - FloatMatrix Finv; - Finv.beInverseOf(F); + + auto Finv = inv(F); status->letTempInverseDefGradBe(Finv); - FloatArray dJ; - dJ.beProductOf(Finv,d); + auto dJ = dot(Finv, d); status->letTempMaterialJumpBe(dJ); - double oldDamage = status->giveDamage(); double dAlpha = 0.0; - FloatArray Qold(3), Qtemp(3), Qtemp_comp(3); - Qtemp.zero(); - Qtemp_comp.zero(); + FloatArrayF<3> Qold, Qtemp, Qtemp_comp; if ( dJ.at(3) < 0 ) { Qtemp_comp.at(3) = this->knc*dJ.at(3); @@ -86,33 +78,17 @@ IntMatBilinearCZFagerstrom :: giveFirstPKTraction_3d(FloatArray &answer, GaussPo // SUBROUTINE stress_damage_XFEM_direct_Mandel(dJ,N,Qold,old_alpha,Fci,Q,Ea,new_alpha,adtim,dalpha_new,dalpha_old,diss,sig_f,fall); - if (oldDamage < 0.99) { - - FloatArray Qtrial = status->giveEffectiveMandelTraction(); - - FloatMatrix Kstiff(3,3); - FloatArray help; + if ( oldDamage < 0.99 ) { - Kstiff.zero(); - Kstiff.at(1,1) = this->ks0; - Kstiff.at(2,2) = this->ks0; - Kstiff.at(3,3) = this->kn0; + auto Kstiff = diag<3>({this->ks0, this->ks0, this->kn0}); - dJ.subtract(status->giveOldMaterialJump()); ///@todo Martin: check with Mikael/Jim - help.beProductOf(Kstiff,dJ); - Qtrial.add(help); + dJ -= status->giveOldMaterialJump(); ///@todo Martin: check with Mikael/Jim + auto Qtrial = status->giveEffectiveMandelTraction() - dot(Kstiff, dJ); double Qn = Qtrial.at(3); - FloatArray QN(3); - QN.zero(); - QN.at(3) = Qn; + FloatArrayF<2> QtrialShear = {Qtrial.at(1), Qtrial.at(2)}; - FloatArray QtrialShear; - - QtrialShear = Qtrial; - QtrialShear.subtract(QN); - - double Qt = QtrialShear.computeNorm(); + double Qt = norm(QtrialShear); double sigf = this->sigf; double gamma = this->gamma; double mu = this->mu; @@ -129,24 +105,21 @@ IntMatBilinearCZFagerstrom :: giveFirstPKTraction_3d(FloatArray &answer, GaussPo if ( loadFun/sigf < 1e-7 ) { dAlpha = 0.0; // new_alpha=old_alpha status->letTempEffectiveMandelTractionBe(Qtemp); - Qtemp.times(1-oldDamage); + Qtemp *= 1 - oldDamage; } else { // dalpha = datr - double Qt1,Qt2; - Qt1 = Qtemp.at(1); - Qt2 = Qtemp.at(2); + double Qt1 = Qtemp.at(1); + double Qt2 = Qtemp.at(2); - FloatArray M(3); // M = (/2*Q_t/(sig_f*gamma**2), 2*Q_n/sig_f, 0.d0/) - M.at(1) = 2*Qt1/(pow(gamma,2)*sigf); // Qt = sqrt(Qt1^2 + Qt2^2) - M.at(2) = 2*Qt2/(pow(gamma,2)*sigf); - M.at(3) = 2*Qn_M/sigf; + FloatArrayF<3> M = { // M = (/2*Q_t/(sig_f*gamma**2), 2*Q_n/sig_f, 0.d0/) + 2*Qt1/(pow(gamma,2)*sigf), // Qt = sqrt(Qt1^2 + Qt2^2) + 2*Qt2/(pow(gamma,2)*sigf), + 2*Qn_M/sigf, + }; - FloatArray dJElastic; - dJElastic = dJ; // dJtn_e(1:2) = dJtn_v(1:2) - S*dalpha*M(1:2) - dJElastic.add(-S*dAlpha, M); + auto dJElastic = dJ - S * dAlpha * M; // dJtn_e(1:2) = dJtn_v(1:2) - S*dalpha*M(1:2) - FloatMatrix Smat(4,4), Smati(4,4); - FloatArray R(4), inc(4); + FloatMatrixF<4,4> Smati; const double errorTol = 0.0001; for( int iter = 1; fabs(loadFun)/sigf > errorTol; iter++) { @@ -155,13 +128,14 @@ IntMatBilinearCZFagerstrom :: giveFirstPKTraction_3d(FloatArray &answer, GaussPo OOFEM_ERROR("BilinearCZMaterialFagerstrom :: giveRealStressVector - no convergence in constitutive driver"); } status->letTempDamageDevBe(true); - Smat.zero(); // S_mat=0.d0 + FloatArrayF<4> R; R.at(1) = dJElastic.at(1) - (dJ.at(1) - gammaGf*S*dAlpha*M.at(1)); // R(1:2) = dJtn_e(1:2) - (dJtn_v(1:2) - S*dalpha*M(1:2)) R.at(2) = dJElastic.at(2) - (dJ.at(2) - gammaGf*S*dAlpha*M.at(2)); R.at(3) = dJElastic.at(3) - (dJ.at(3) - S*dAlpha*M.at(3)); R.at(4) = loadFun; // R(3) = F/sig_f + FloatMatrixF<4,4> Smat; // S_mat=0.d0 Smat.at(1,1) = 1.0 + gammaGf*dAlpha*S*2*Kstiff.at(1,1)/(pow(gamma,2)*sigf); // S_mat(1:2,1:2) = eye3(1:2,1:2)+ dalpha*S*dMdJtn_e(1:2,1:2) Smat.at(2,2) = 1.0 + gammaGf*dAlpha*S*2*Kstiff.at(2,2)/(pow(gamma,2)*sigf); //dJElastic.printYourself(); @@ -174,7 +148,7 @@ IntMatBilinearCZFagerstrom :: giveFirstPKTraction_3d(FloatArray &answer, GaussPo Smat.at(1,4) = gammaGf*S*M.at(1); // S_mat(1:2,3) = S*M(1:2) Smat.at(2,4) = gammaGf*S*M.at(2); Smat.at(3,4) = S*M.at(3); - + Smat.at(4,1) = M.at(1)*Kstiff.at(1,1); // S_mat(3,1:2) = MATMUL(M(1:2),Keye3(1:2,1:2)) Smat.at(4,2) = M.at(2)*Kstiff.at(2,2); //Smat.at(4,3) = M.at(3)*Kstiff.at(3,3); @@ -184,22 +158,20 @@ IntMatBilinearCZFagerstrom :: giveFirstPKTraction_3d(FloatArray &answer, GaussPo //bool transpose = false; //Smat.SolveforRhs(R, inc, transpose); - Smati.beInverseOf(Smat); + Smati = inv(Smat); - inc.beProductOf(Smati,R); + auto inc = dot(Smati, R); dJElastic.at(1) -= inc.at(1); dJElastic.at(2) -= inc.at(2); dJElastic.at(3) -= inc.at(3); dAlpha = dAlpha - inc.at(4); - Qtemp.at(1) = Qold.at(1) + Kstiff.at(1,1)*dJElastic.at(1); - Qtemp.at(2) = Qold.at(2) + Kstiff.at(2,2)*dJElastic.at(2); - Qtemp.at(3) = Qold.at(3) + Kstiff.at(3,3)*dJElastic.at(3); + Qtemp = Qold + dot(Kstiff, dJElastic); - Qt1 = Qtemp.at(1); - Qt2 = Qtemp.at(2); - Qt = sqrt(pow(Qt1,2) + pow(Qt2,2)); + double Qt1 = Qtemp.at(1); + double Qt2 = Qtemp.at(2); + Qt = sqrt(Qt1*Qt1 + Qt2*Qt2); Qn = Qtemp.at(3); // Martin: included parameter mu Qn_M = 0.5*(Qtemp.at(3)+fabs(Qtemp.at(3))); @@ -211,28 +183,22 @@ IntMatBilinearCZFagerstrom :: giveFirstPKTraction_3d(FloatArray &answer, GaussPo loadFun = sigf*pow(Qt/(gamma*sigf),2) + (sigf/gamma)*(gamma-mu)*pow((Qn_M/sigf),2) - 1/gamma*(gamma*sigf-mu*Qn); //Martin: included parameter mu } //printf("converged, loadfun = %e, oldDamage = %e \n",loadFun, oldDamage); - + if (oldDamage + dAlpha > 1) { dAlpha = 1. - oldDamage; } - FloatMatrix Iep(3,3); - IntArray Indx(3); - Indx.at(1) = 1; - Indx.at(2) = 2; - Indx.at(3) = 3; - - Iep.beSubMatrixOf(Smati,Indx,Indx); + auto Iep = Smati({0,1,2},{0,1,2}); status->letTempIepBe(Iep); - - FloatArray alpha_v(3); - alpha_v.at(1) = Smati.at(4,1); // alpha_v(1:2) = S_mati(3,1:2) - alpha_v.at(2) = Smati.at(4,2); - alpha_v.at(3) = Smati.at(4,3); - + + FloatArrayF<3> alpha_v = { + Smati.at(4,1), // alpha_v(1:2) = S_mati(3,1:2) + Smati.at(4,2), + Smati.at(4,3), + }; status->letTempAlphavBe(alpha_v); status->letTempEffectiveMandelTractionBe(Qtemp); - Qtemp.times(1-oldDamage-dAlpha); + Qtemp *= 1 - oldDamage - dAlpha; } @@ -247,75 +213,62 @@ IntMatBilinearCZFagerstrom :: giveFirstPKTraction_3d(FloatArray &answer, GaussPo //} } - Qtemp.add(Qtemp_comp); - + Qtemp += Qtemp_comp; - answer.beTProductOf(Finv, Qtemp); // t_1_hat = MATMUL(TRANSPOSE(Fci),Q) - //answer.times(1-oldDamage-dAlpha); // t1_s = (1-al)*t_1_hat + auto answer = Tdot(Finv, Qtemp); // t_1_hat = MATMUL(TRANSPOSE(Fci),Q) + //* (1-oldDamage-dAlpha); // t1_s = (1-al)*t_1_hat - status->letTempDamageBe(oldDamage + dAlpha); //status->letTempEffectiveMandelTractionBe(Qtemp); // NEW! status->letTempJumpBe(d); status->letTempFirstPKTractionBe(answer); status->letTempFBe(F); -} + return answer; +} -void -IntMatBilinearCZFagerstrom :: give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +IntMatBilinearCZFagerstrom :: give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { IntMatBilinearCZFagerstromStatus *status = static_cast< IntMatBilinearCZFagerstromStatus * >( this->giveStatus(gp) ); - if (status->giveOldDamageDev()) { + FloatMatrixF<3,3> answer; + if ( status->giveOldDamageDev() ) { answer = status->giveOlddTdJ(); //answer.printYourself(); status->letOldDamageDevBe(false); } else { double damage = status->giveTempDamage(); - const FloatMatrix &Finv = status->giveTempInverseDefGrad(); - const FloatArray &J = status->giveTempJump(); - FloatMatrix help; - FloatMatrix Kstiff(3,3); + const auto &Finv = status->giveTempInverseDefGrad(); + const auto &J = status->giveTempJump(); + FloatMatrixF<3,3> Kstiff = diag<3>({this->ks0, this->ks0, this->kn0}); //FloatMatrix Rot = status->giveTempRotationMatrix(); - Kstiff.zero(); - Kstiff.at(1,1) = this->ks0; - Kstiff.at(2,2) = this->ks0; - Kstiff.at(3,3) = this->kn0; - //Kstiff.rotatedWith(Rot); + //Kstiff = rotate(Kstiff, Rot); if ( damage >= 1.0 ) { - answer.resize(3,3); - answer.zero(); if ( J.at(3) < 0 ) { - Kstiff.at(1,1) = 0.0; - Kstiff.at(2,2) = 0.0; - Kstiff.at(3,3) = this->knc; - help.beProductOf(Kstiff, Finv); - answer.beTProductOf(Finv, help); + Kstiff = diag<3>({0.0, 0.0, this->knc}); + answer = rotate(Kstiff, Finv); //printf("fully damaged"); //answer.printYourself(); } } else { - if ( status->giveTempDamage() - status->giveDamage()==0.0 ) { if ( J.at(3) < 0 ) { Kstiff.at(3,3) = Kstiff.at(3,3) + (this->knc)/(1-damage); } - help.beProductOf(Kstiff, Finv); - answer.beTProductOf(Finv, help); - answer.times(1-damage); // Ea=(1-new_alpha)*MATMUL(TRANSPOSE(Fci),MATMUL(Keye3,Fci)) - + // Ea=(1-new_alpha)*MATMUL(TRANSPOSE(Fci),MATMUL(Keye3,Fci)) + answer = (1-damage) * rotate(Kstiff, Finv); //printf("elastic step"); } else { - FloatMatrix Iep = status->giveTempIep(); + const auto &Iep = status->giveTempIep(); //Iep.ourselfourself(); //if (J.at(3)<0) { @@ -326,59 +279,41 @@ IntMatBilinearCZFagerstrom :: give3dStiffnessMatrix_dTdj(FloatMatrix &answer, Ma //Kstiff.times((1-damage)); //} - Kstiff.times((1-damage)); - answer.beProductOf(Kstiff, Iep); + answer = (1 - damage) * dot(Kstiff, Iep); //answer.rotatedWith(Rot); // Ea_h = MATMUL(TRANSPOSE(Rot),MATMUL(Keye3,Iep)) // Ea_h = MATMUL(Ea_h,Rot) - FloatArray alpha_v = status->giveTempAlphav(); - //alpha_v.rotatedWith(Rot, 't'); // alpha_v = MATMUL(TRANSPOSE(Rot),alpha_v) + const auto &alpha_v = status->giveTempAlphav(); + //alpha_v = Tdot(Rot, alpha_v); // alpha_v = MATMUL(TRANSPOSE(Rot),alpha_v) - FloatMatrix t1hatFinvOpen; - FloatArray temp1, temp2, Qtemp; - Qtemp = status->giveTempEffectiveMandelTraction(); + const auto &Qtemp = status->giveTempEffectiveMandelTraction(); - temp1.beTProductOf(Finv,Qtemp); // CALL gmopen33(MATMUL(TRANSPOSE(Fci),Q),MATMUL(alpha_v,Fci),t1halFci_o) - temp2.beTProductOf(Finv,alpha_v); + auto temp1 = Tdot(Finv, Qtemp); // CALL gmopen33(MATMUL(TRANSPOSE(Fci),Q),MATMUL(alpha_v,Fci),t1halFci_o) + auto temp2 = Tdot(Finv, alpha_v); - t1hatFinvOpen.beDyadicProductOf(temp1,temp2); + auto t1hatFinvOpen = dyad(temp1, temp2); if ( J.at(3) < 0 ) { answer.at(3,3) = answer.at(3,3) + this->knc; } //printf("plastic step"); - help.beProductOf(answer, Finv); // Ea = (1-new_alpha)*MATMUL(TRANSPOSE(Fci),MATMUL(Ea_h,Fci)) -& - answer.beTProductOf(Finv, help); // t1halFci_o - answer.subtract(t1hatFinvOpen); + // Ea = (1-new_alpha)*MATMUL(TRANSPOSE(Fci),MATMUL(Ea_h,Fci)) - t1halFci_o + answer = rotate(answer, Finv) - t1hatFinvOpen; } } } status->letTempdTdJBe(answer); + return answer; } -int -IntMatBilinearCZFagerstrom :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) -{ - IntMatBilinearCZFagerstromStatus *status = static_cast< IntMatBilinearCZFagerstromStatus * >( this->giveStatus(gp) ); - if ( type == IST_DamageScalar ) { - answer.resize(1); - answer.at(1) = status->giveDamage(); - return 1; - } else { - return StructuralInterfaceMaterial :: giveIPValue(answer, gp, type, tStep); - } - -} //const double tolerance = 1.0e-12; // small number -IRResultType -IntMatBilinearCZFagerstrom :: initializeFrom(InputRecord *ir) +void +IntMatBilinearCZFagerstrom :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, kn0, _IFT_IntMatBilinearCZFagerstrom_kn); this->knc = kn0; // Defaults to the same stiffness in compression and tension IR_GIVE_OPTIONAL_FIELD(ir, this->knc, _IFT_IntMatBilinearCZFagerstrom_knc); @@ -397,28 +332,20 @@ IntMatBilinearCZFagerstrom :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, gamma, _IFT_IntMatBilinearCZFagerstrom_gamma); - result = StructuralInterfaceMaterial ::initializeFrom(ir); - if ( result != IRRT_OK ) return result; + StructuralInterfaceMaterial ::initializeFrom(ir); // check validity of the material paramters if ( this->kn0 < 0.0 ) { - OOFEM_WARNING("Stiffness kn0 is negative (%.2e)", this->kn0); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZFagerstrom_kn, "must be positive"); } else if ( this->ks0 < 0.0 ) { - OOFEM_WARNING("Stiffness ks0 is negative (%.2e)", this->ks0); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZFagerstrom_ks, "must be positive"); } else if ( this->GIc < 0.0 ) { - OOFEM_WARNING("GIc is negative (%.2e)", this->GIc); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZFagerstrom_g2c, "must be positive"); } else if ( this->GIIc < 0.0 ) { - OOFEM_WARNING("GIIc is negative (%.2e)", this->GIIc); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZFagerstrom_g2c, "must be positive"); } else if ( this->gamma < 0.0 ) { - OOFEM_WARNING("gamma (%.2e) is below zero which is unphysical", - this->gamma); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZFagerstrom_gamma, "must be positive"); } - return IRRT_OK; } void IntMatBilinearCZFagerstrom :: giveInputRecord(DynamicInputRecord &input) @@ -464,35 +391,15 @@ IntMatBilinearCZFagerstrom :: printYourself() } -IntMatBilinearCZFagerstromStatus :: IntMatBilinearCZFagerstromStatus(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g) +IntMatBilinearCZFagerstromStatus :: IntMatBilinearCZFagerstromStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) { - oldMaterialJump.resize(3); - oldMaterialJump.zero(); - tempMaterialJump = oldMaterialJump; - - damage = tempDamage = 0.0; - - QEffective = oldMaterialJump; - tempQEffective = oldMaterialJump; - - tempFInv.resize(3,3); - tempFInv.beUnitMatrix(); - - old_dTdJ.resize(3,3); - - oldDamageDev = false; - + tempFInv = eye<3>(); Iep = tempFInv; - alphav = oldMaterialJump; } -IntMatBilinearCZFagerstromStatus :: ~IntMatBilinearCZFagerstromStatus() -{ } - - void -IntMatBilinearCZFagerstromStatus :: printOutputAt(FILE *file, TimeStep *tStep) +IntMatBilinearCZFagerstromStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { ///@todo Martin: check need of this StructuralInterfaceMaterialStatus :: printOutputAt(file, tStep); @@ -516,9 +423,7 @@ IntMatBilinearCZFagerstromStatus :: initTempStatus() tempDamage = damage; tempQEffective = QEffective; - tempFInv.resize(3,3); - tempFInv.beUnitMatrix(); - + tempFInv = eye<3>(); Iep = tempFInv; alphav = oldMaterialJump; diff --git a/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstrom.h b/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstrom.h index 39699572a..ea59f862d 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstrom.h +++ b/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstrom.h @@ -58,93 +58,82 @@ namespace oofem { class IntMatBilinearCZFagerstromStatus : public StructuralInterfaceMaterialStatus { protected: - // material jump - FloatArray oldMaterialJump; + FloatArrayF<3> oldMaterialJump; // temporary material jump - FloatArray tempMaterialJump; + FloatArrayF<3> tempMaterialJump; // damage variable - double damage; + double damage = 0.; // temporary damage value - double tempDamage; + double tempDamage = 0.; // Effective Mandel traction - FloatArray QEffective; + FloatArrayF<3> QEffective; // Temporary effective Mandel traction - FloatArray tempQEffective; + FloatArrayF<3> tempQEffective; // Temporary inverse of deformation gradient - FloatMatrix tempFInv; + FloatMatrixF<3,3> tempFInv; // Temporary array for coordinate transformation - FloatMatrix tempRot; + FloatMatrixF<3,3> tempRot; // tempArrays for stiffness calculation - FloatMatrix Iep; - FloatArray alphav; + FloatMatrixF<3,3> Iep; + FloatArrayF<3> alphav; // indicator for davae development of preceding time step - bool tempDamageDev; - bool oldDamageDev; + bool tempDamageDev = false; + bool oldDamageDev = false; // tangent stiffness from previous time step - FloatMatrix temp_dTdJ; - FloatMatrix old_dTdJ; - - - - - + FloatMatrixF<3,3> temp_dTdJ; + FloatMatrixF<3,3> old_dTdJ; public: /// Constructor - IntMatBilinearCZFagerstromStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~IntMatBilinearCZFagerstromStatus(); + IntMatBilinearCZFagerstromStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - // definition - virtual const char *giveClassName() const { return "IntMatBilinearCZFagerstromStatus"; } + const char *giveClassName() const override { return "IntMatBilinearCZFagerstromStatus"; } - double giveDamage() { return damage; } - double giveTempDamage() { return tempDamage; } - bool giveOldDamageDev() { return oldDamageDev; } + double giveDamage() const override { return damage; } + double giveTempDamage() const override { return tempDamage; } + bool giveOldDamageDev() const { return oldDamageDev; } - const FloatArray &giveOldMaterialJump() { return oldMaterialJump; } - const FloatArray &giveTempMaterialJump() { return tempMaterialJump; } + const FloatArrayF<3> &giveOldMaterialJump() const { return oldMaterialJump; } + const FloatArrayF<3> &giveTempMaterialJump() const { return tempMaterialJump; } - const FloatArray &giveEffectiveMandelTraction() { return QEffective; } - const FloatArray &giveTempEffectiveMandelTraction() { return tempQEffective; } + const FloatArrayF<3> &giveEffectiveMandelTraction() const { return QEffective; } + const FloatArrayF<3> &giveTempEffectiveMandelTraction() const { return tempQEffective; } - const FloatMatrix &giveTempInverseDefGrad() { return tempFInv; } - const FloatMatrix &giveTempRotationMatrix() { return tempRot; } - const FloatMatrix &giveTempIep() { return Iep; } - const FloatArray &giveTempAlphav() { return alphav; } - const FloatMatrix &giveOlddTdJ() {return old_dTdJ; } + const FloatMatrixF<3,3> &giveTempInverseDefGrad() const { return tempFInv; } + const FloatMatrixF<3,3> &giveTempRotationMatrix() const { return tempRot; } + const FloatMatrixF<3,3> &giveTempIep() const { return Iep; } + const FloatArrayF<3> &giveTempAlphav() const { return alphav; } + const FloatMatrixF<3,3> &giveOlddTdJ() const { return old_dTdJ; } void letTempDamageBe(double v) { tempDamage = v; } void letTempDamageDevBe(bool v) { tempDamageDev = v; } void letOldDamageDevBe(bool v) { oldDamageDev = v; } - void letTempEffectiveMandelTractionBe(FloatArray v) { tempQEffective = std :: move(v); } - void letTempMaterialJumpBe(FloatArray v) { tempMaterialJump = std :: move(v); } + void letTempEffectiveMandelTractionBe(const FloatArrayF<3> &v) { tempQEffective = v; } + void letTempMaterialJumpBe(const FloatArrayF<3> &v) { tempMaterialJump = v; } - void letTempdTdJBe(FloatMatrix &v) { temp_dTdJ = v; } + void letTempdTdJBe(const FloatMatrixF<3,3> &v) { temp_dTdJ = v; } - void letTempInverseDefGradBe(FloatMatrix v) { tempFInv = std :: move(v); } - void letTempRotationMatrix(FloatMatrix v) { tempRot = std :: move(v); } - void letTempIepBe(FloatMatrix v) { Iep = std :: move(v); } - void letTempAlphavBe(FloatArray v) { alphav = std :: move(v); } + void letTempInverseDefGradBe(const FloatMatrixF<3,3> &v) { tempFInv = v; } + void letTempRotationMatrix(const FloatMatrixF<3,3> &v) { tempRot = v; } + void letTempIepBe(const FloatMatrixF<3,3> &v) { Iep = v; } + void letTempAlphavBe(const FloatArrayF<3> &v) { alphav = v; } + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); - - //virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - //virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + //void saveContext(DataStream &stream, ContextMode mode) override; + //void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -164,53 +153,44 @@ class IntMatBilinearCZFagerstrom : public StructuralInterfaceMaterial { protected: /// Material parameters - double kn0; // initial normal stiffness - double ks0; // initial shear stiffness - double knc; // stiffness in compression - double GIc; // fracture energy, mode 1 - double GIIc; // fracture energy, mode 1 - double sigf; // max stress + double kn0 = 0.; // initial normal stiffness + double ks0 = 0.; // initial shear stiffness + double knc = 0.; // stiffness in compression + double GIc = 0.; // fracture energy, mode 1 + double GIIc = 0.; // fracture energy, mode 1 + double sigf = 0.; // max stress - double mu; // loading function parameter - double gamma; // loading function parameter + double mu = 0.; // loading function parameter + double gamma = 0.; // loading function parameter - virtual int checkConsistency(); + int checkConsistency() override; void give3dInterfaceMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); public: /// Constructor IntMatBilinearCZFagerstrom(int n, Domain * d); - /// Destructor - virtual ~IntMatBilinearCZFagerstrom(); - - virtual int hasNonLinearBehaviour() { return 1; } - virtual const char *giveClassName() const { return "IntMatBilinearCZFagerstrom"; } - virtual const char *giveInputRecordName() const { return _IFT_IntMatBilinearCZFagerstrom_Name; } + const char *giveClassName() const override { return "IntMatBilinearCZFagerstrom"; } + const char *giveInputRecordName() const override { return _IFT_IntMatBilinearCZFagerstrom_Name; } - - virtual void giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &F, TimeStep *tStep); - virtual void give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + FloatArrayF<3> giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; /** * Tells if the model has implemented analytical tangent stiffness. * If not, the tangent must be computed numerically. */ - virtual bool hasAnalyticalTangentStiffness() const { return true; } + bool hasAnalyticalTangentStiffness() const override { return true; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - - virtual FloatArray giveInterfaceStrength() { return {this->sigf*this->gamma,this->sigf*this->gamma,this->sigf}; } + FloatArray giveInterfaceStrength() override { return {this->sigf*this->gamma,this->sigf*this->gamma,this->sigf}; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new IntMatBilinearCZFagerstromStatus(1, domain, gp); } //@Martin: Why new? - void printYourself(); -protected: + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new IntMatBilinearCZFagerstromStatus(gp); } + void printYourself() override; }; } // end namespace oofem #endif // isointerfacedamage01_h diff --git a/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstromrate.C b/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstromrate.C index 20258ac92..763eb3e3e 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstromrate.C +++ b/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstromrate.C @@ -40,7 +40,7 @@ #include "datastream.h" #include "contextioerr.h" #include "classfactory.h" -#include "Elements/Shells/shell7base.h" +#include "sm/Elements/Shells/shell7base.h" #include "intmatbilinczfagerstromrate.h" //#include "vld.h" @@ -49,61 +49,39 @@ namespace oofem { REGISTER_Material( IntMatBilinearCZFagerstromRate ); IntMatBilinearCZFagerstromRate :: IntMatBilinearCZFagerstromRate(int n, Domain *d) : IntMatBilinearCZFagerstrom(n, d) -{ - // constructor -} +{} -IntMatBilinearCZFagerstromRate :: ~IntMatBilinearCZFagerstromRate() -{ - // destructor -} - ///@todo - need to rearrange traction and stiffness matrix so the first component is normal -void -IntMatBilinearCZFagerstromRate :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &d, - const FloatMatrix &F, TimeStep *tStep) +FloatArrayF<3> +IntMatBilinearCZFagerstromRate :: giveFirstPKTraction_3d(const FloatArrayF<3> &d, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const { // returns real stress vector in 3d stress space of receiver according to // previous level of stress and current // strain increment, the only way, how to correctly update gp records // - IntMatBilinearCZFagerstromStatus *status = static_cast< IntMatBilinearCZFagerstromStatus * >( this->giveStatus(gp) ); - FloatMatrix Finv; - - Finv.beInverseOf(F); + auto Finv = inv(F); status->letTempInverseDefGradBe(Finv); - FloatArray dJ; - dJ.beProductOf(Finv,d); + auto dJ = dot(Finv, d); status->letTempMaterialJumpBe(dJ); double oldDamage = status->giveDamage(); double dAlpha = 0.0; double dt = tStep->giveTimeIncrement(); - FloatArray Qold(3), Qtemp(3), Qtemp_comp(3); - Qtemp.zero(); - Qtemp_comp.zero(); - + FloatArrayF<3> Qold, Qtemp, Qtemp_comp; if ( dJ.at(3) < 0 ) { Qtemp_comp.at(3) = this->knc*dJ.at(3); } - // SUBROUTINE stress_damage_XFEM_direct_Mandel(dJ,N,Qold,old_alpha,Fci,Q,Ea,new_alpha,adtim,dalpha_new,dalpha_old,diss,sig_f,fall); - if (oldDamage < 0.99) { + if ( oldDamage < 0.99 ) { FloatArray Qtrial = status->giveEffectiveMandelTraction(); - FloatMatrix Kstiff(3,3); - FloatArray help; - - Kstiff.zero(); - Kstiff.at(1,1) = this->ks0; - Kstiff.at(2,2) = this->ks0; - Kstiff.at(3,3) = this->kn0; + auto Kstiff = diag<3>({this->ks0, this->ks0, this->kn0}); #if 0 if (dJ.at(3)>=0) { @@ -113,24 +91,16 @@ IntMatBilinearCZFagerstromRate :: giveFirstPKTraction_3d(FloatArray &answer, Gau } #endif - dJ.subtract(status->giveOldMaterialJump()); ///@todo Martin: check with Mikael/Jim + dJ -= status->giveOldMaterialJump(); ///@todo Martin: check with Mikael/Jim //dJ.rotatedWith(Rot,'n'); //dJ.printYourself(); - help.beProductOf(Kstiff, dJ); - Qtrial.add(help); + Qtrial += dot(Kstiff, dJ); double Qn = Qtrial.at(3); - FloatArray QN(3); - QN.zero(); - QN.at(3) = Qn; - - - FloatArray QtrialShear = Qtrial; - QtrialShear.subtract(QN); - - double Qt = QtrialShear.computeNorm(); + auto QtrialShear = {Qtrial.at(1), Qtrial.at(2), 0.}; + double Qt = norm(QtrialShear); //double S = this->GIc/this->sigf; double sigf = this->sigf; @@ -143,11 +113,8 @@ IntMatBilinearCZFagerstromRate :: giveFirstPKTraction_3d(FloatArray &answer, Gau double S = (this->GIc - pow(sigf,2)/(2*this->kn0))/sigf; double gammaGf = gamma*(this->GIIc - pow(gamma*sigf,2)/(2*this->ks0))/(this->GIc - pow(sigf,2)/(2*this->kn0)); - - double Qn_M = 0.5*(Qn + fabs(Qn)); - //double loadFun = sigf*pow(Qt/(gamma*sigf),2) + sigf*pow((Qn_M/sigf),2) - sigf; ///@todo Martin: no use of parameter mu!!! double loadFun = sigf*pow(Qt/(gamma*sigf),2) + (sigf/gamma)*(gamma-mu)*pow((Qn_M/sigf),2) - 1/gamma*(gamma*sigf-mu*Qn); // Added support for parameter mu @@ -162,31 +129,25 @@ IntMatBilinearCZFagerstromRate :: giveFirstPKTraction_3d(FloatArray &answer, Gau // double bbb=1; ///@todo Should this be used for anything Martin? /JB //} - if (loadFun/sigf < 0.0000001) { + if ( loadFun/sigf < 0.0000001 ) { dAlpha = 0.0; // new_alpha=old_alpha status->letTempEffectiveMandelTractionBe(Qtemp); - Qtemp.times(1-oldDamage); + Qtemp *= 1-oldDamage; } else { // dalpha = datr - double Qt1,Qt2; - Qt1 = Qtemp.at(1); - Qt2 = Qtemp.at(2); + double Qt1 = Qtemp.at(1); + double Qt2 = Qtemp.at(2); - FloatArray M(3); // M = (/2*Q_t/(sig_f*gamma**2), 2*Q_n/sig_f, 0.d0/) + FloatArrayF<3> M; // M = (/2*Q_t/(sig_f*gamma**2), 2*Q_n/sig_f, 0.d0/) M.at(1) = 2*Qt1/(pow(gamma,2)*sigf); // Qt = sqrt(Qt1^2 + Qt2^2) M.at(2) = 2*Qt2/(pow(gamma,2)*sigf); M.at(3) = 2*Qn_M/sigf; - FloatArray dJElastic; - dJElastic = dJ; // dJtn_e(1:2) = dJtn_v(1:2) - S*dalpha*M(1:2) - help = M; - + auto dJElastic = dJ - (S * dAlpha) * M; // dJtn_e(1:2) = dJtn_v(1:2) - S*dalpha*M(1:2) //dAlpha = (dt/(c_star*S))*pow(loadFun_M/sigf,m)*(1/M_norm); - help.times(S*dAlpha); - dJElastic.subtract(help); - FloatMatrix Smat(4,4), Smati(4,4); - FloatArray R(4), inc(4), dJp(3); + FloatMatrixF<4,4> Smati; + FloatArrayF<3> dJp; double loadFunDyn = loadFun; const double errorTol = 0.0001; @@ -195,21 +156,20 @@ IntMatBilinearCZFagerstromRate :: giveFirstPKTraction_3d(FloatArray &answer, Gau //double loadFun_M = 0.5*(loadFun + fabs(loadFun)); //double M_norm = sqrt(M.computeSquaredNorm()); - if (iter>40) { + if ( iter > 40 ) { OOFEM_ERROR("BilinearCZMaterialFagerstrom :: giveRealStressVector - no convergence in constitutive driver"); } status->letTempDamageDevBe(true); - Smat.zero(); // S_mat=0.d0 + FloatArrayF<4> R; R.at(1) = dJElastic.at(1) - (dJ.at(1) - gammaGf*S*dAlpha*M.at(1)); // R(1:2) = dJtn_e(1:2) - (dJtn_v(1:2) - S*dalpha*M(1:2)) R.at(2) = dJElastic.at(2) - (dJ.at(2) - gammaGf*S*dAlpha*M.at(2)); R.at(3) = dJElastic.at(3) - (dJ.at(3) - S*dAlpha*M.at(3)); - if (fabs(c_star)>0) { - //R.at(4) = loadFun - c_star*pow((dAlpha/dt),m); - //R.at(4) = loadFun - c_star*pow((sqrt(dJ.computeSquaredNorm())/dt),m); - dJp = dJ; - dJp.subtract(dJElastic); - R.at(4) = loadFun - c_star*pow((sqrt(dJp.computeSquaredNorm())/dt),m); + if ( fabs(c_star) > 0 ) { + //R.at(4) = loadFun - c_star*pow(dAlpha/dt, m); + //R.at(4) = loadFun - c_star*pow(norm(dJ)/dt, m); + dJp = dJ - dJElastic; + R.at(4) = loadFun - c_star*pow(norm(dJp)/dt, m); //R.at(4) = dAlpha - (dt/(c_star*S))*pow(loadFun_M/sigf,m)*(1/M_norm); } else { R.at(4) = loadFun; // R(3) = F/sig_f @@ -224,10 +184,11 @@ IntMatBilinearCZFagerstromRate :: giveFirstPKTraction_3d(FloatArray &answer, Gau // dMdJtn_e = MATMUL(dMdJtn_e,Keye3(1:2,1:2)) + FloatMatrixF<4,4> Smat; // S_mat=0.d0 Smat.at(1,1) = 1.0 + gammaGf*dAlpha*S*2*Kstiff.at(1,1)/(pow(gamma,2)*sigf); // S_mat(1:2,1:2) = eye3(1:2,1:2)+ dalpha*S*dMdJtn_e(1:2,1:2) Smat.at(2,2) = 1.0 + gammaGf*dAlpha*S*2*Kstiff.at(2,2)/(pow(gamma,2)*sigf); //dJElastic.printYourself(); - if (Qn_M>0) { + if ( Qn_M > 0 ) { Smat.at(3,3) = 1.0 + dAlpha*S*2*Kstiff.at(3,3)/(sigf); } else { Smat.at(3,3) = 1.0; @@ -238,13 +199,12 @@ IntMatBilinearCZFagerstromRate :: giveFirstPKTraction_3d(FloatArray &answer, Gau Smat.at(3,4) = S*M.at(3); double fac1; - if (sqrt(dJp.computeSquaredNorm())>0) { - fac1 = c_star*m/(pow(dt,m))*pow(sqrt(dJp.computeSquaredNorm()),m-2); + if ( norm(dJp) > 0 ) { + fac1 = c_star*m/pow(dt, m)*pow(norm(dJp), m-2); } else { fac1 = 0; } - if ( fabs(c_star) > 0 ) { // Rate-dependent case Smat.at(4,1) = M.at(1)*Kstiff.at(1,1) + fac1*dJp.at(1); // S_mat(3,1:2) = MATMUL(M(1:2),Keye3(1:2,1:2)) Smat.at(4,2) = M.at(2)*Kstiff.at(2,2) + fac1*dJp.at(2); @@ -265,23 +225,21 @@ IntMatBilinearCZFagerstromRate :: giveFirstPKTraction_3d(FloatArray &answer, Gau //bool transpose = false; //Smat.SolveforRhs(R, inc, transpose); - Smati.beInverseOf(Smat); + Smati = inv(Smat); - inc.beProductOf(Smati,R); + auto inc = dot(Smati,R); - dJElastic.at(1) = dJElastic.at(1) - inc.at(1); - dJElastic.at(2) = dJElastic.at(2) - inc.at(2); - dJElastic.at(3) = dJElastic.at(3) - inc.at(3); + dJElastic.at(1) -= inc.at(1); + dJElastic.at(2) -= inc.at(2); + dJElastic.at(3) -= inc.at(3); //dJElastic.printYourself(); - dAlpha = dAlpha - inc.at(4); + dAlpha -= inc.at(4); - Qtemp.at(1) = Qold.at(1) + Kstiff.at(1,1)*dJElastic.at(1); - Qtemp.at(2) = Qold.at(2) + Kstiff.at(2,2)*dJElastic.at(2); - Qtemp.at(3) = Qold.at(3) + Kstiff.at(3,3)*dJElastic.at(3); + Qtemp = Qold + dot(Kstiff, dJElastic); - Qt1 = Qtemp.at(1); - Qt2 = Qtemp.at(2); - Qt = sqrt(pow(Qt1,2) + pow(Qt2,2)); + double Qt1 = Qtemp.at(1); + double Qt2 = Qtemp.at(2); + Qt = sqrt(Qt1*Qt1 + Qt2*Qt2); Qn = Qtemp.at(3); // Martin: included parameter mu Qn_M = 0.5*(Qtemp.at(3)+fabs(Qtemp.at(3))); @@ -291,31 +249,25 @@ IntMatBilinearCZFagerstromRate :: giveFirstPKTraction_3d(FloatArray &answer, Gau //loadFun = sigf*pow(Qt/(gamma*sigf),2) + sigf*pow((Qn_M/sigf),2) - sigf; loadFun = sigf*pow(Qt/(gamma*sigf),2) + (sigf/gamma)*(gamma-mu)*pow((Qn_M/sigf),2) - 1/gamma*(gamma*sigf-mu*Qn); //Martin: included parameter mu - loadFunDyn = loadFun - c_star*pow((sqrt(dJp.computeSquaredNorm())/dt),m);; + loadFunDyn = loadFun - c_star*pow(norm(dJp)/dt, m); } //printf("converged, loadfun = %e, oldDamage = %e \n",loadFun, oldDamage); - if (oldDamage + dAlpha > 1) { + if ( oldDamage + dAlpha > 1 ) { dAlpha = 1. - oldDamage; } - FloatMatrix Iep(3,3); - IntArray Indx(3); - Indx.at(1) = 1; - Indx.at(2) = 2; - Indx.at(3) = 3; - - Iep.beSubMatrixOf(Smati,Indx,Indx); + auto Iep = Smati({0,1,2},{0,1,2}); status->letTempIepBe(Iep); - FloatArray alpha_v(3); - alpha_v.at(1) = Smati.at(4,1); // alpha_v(1:2) = S_mati(3,1:2) - alpha_v.at(2) = Smati.at(4,2); - alpha_v.at(3) = Smati.at(4,3); + FloatArrayF<3> alpha_v { + Smati.at(4,1), // alpha_v(1:2) = S_mati(3,1:2) + Smati.at(4,2), + Smati.at(4,3), + }; status->letTempAlphavBe(alpha_v); status->letTempEffectiveMandelTractionBe(Qtemp); - Qtemp.times(1-oldDamage-dAlpha); - + Qtemp *= 1 - oldDamage - dAlpha; } //Qtemp.rotatedWith(Rot,'t'); // Q=Qe @@ -329,30 +281,25 @@ IntMatBilinearCZFagerstromRate :: giveFirstPKTraction_3d(FloatArray &answer, Gau //} } - Qtemp.at(1) = Qtemp.at(1) + Qtemp_comp.at(1); - Qtemp.at(2) = Qtemp.at(2) + Qtemp_comp.at(2); - Qtemp.at(3) = Qtemp.at(3) + Qtemp_comp.at(3); - - - answer.beTProductOf(Finv,Qtemp); // t_1_hat = MATMUL(TRANSPOSE(Fci),Q) -// answer.times(1-oldDamage-dAlpha); // t1_s = (1-al)*t_1_hat + Qtemp += Qtemp_comp; + auto answer = Tdot(Finv,Qtemp); // t_1_hat = MATMUL(TRANSPOSE(Fci),Q) +// answer *= 1 - oldDamage - dAlpha; // t1_s = (1-al)*t_1_hat status->letTempDamageBe(oldDamage + dAlpha); // status->letTempEffectiveMandelTractionBe(Qtemp); // NEW! - status->letTempJumpBe(d); status->letTempFirstPKTractionBe(answer); status->letTempFBe(F); + + return answer; } const double tolerance = 1.0e-12; // small number -IRResultType -IntMatBilinearCZFagerstromRate :: initializeFrom(InputRecord *ir) +void +IntMatBilinearCZFagerstromRate :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, kn0, _IFT_IntMatBilinearCZFagerstrom_kn); this->knc = kn0; // Defaults to the same stiffness in compression and tension IR_GIVE_OPTIONAL_FIELD(ir, this->knc, _IFT_IntMatBilinearCZFagerstrom_knc); @@ -379,7 +326,6 @@ IntMatBilinearCZFagerstromRate :: initializeFrom(InputRecord *ir) this->checkConsistency(); // check validity of the material paramters this->printYourself(); - return IRRT_OK; } void IntMatBilinearCZFagerstromRate :: giveInputRecord(DynamicInputRecord &input) @@ -388,7 +334,6 @@ void IntMatBilinearCZFagerstromRate :: giveInputRecord(DynamicInputRecord &input input.setField(c_star, _IFT_IntMatBilinearCZFagerstromRate_cstar); input.setField(knc, _IFT_IntMatBilinearCZFagerstromRate_m); - } int @@ -416,7 +361,6 @@ IntMatBilinearCZFagerstromRate :: printYourself() printf("-Rate parameters \n"); printf(" c_star = %e \n", this->c_star); printf(" m = %e \n", this->m); - } diff --git a/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstromrate.h b/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstromrate.h index 9ccd4e773..653fd5538 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstromrate.h +++ b/src/sm/Materials/InterfaceMaterials/intmatbilinczfagerstromrate.h @@ -38,8 +38,6 @@ #include "structuralinterfacematerial.h" #include "structuralinterfacematerialstatus.h" #include "intmatbilinczfagerstrom.h" - - #include "dynamicinputrecord.h" ///@name Input fields for IntMatBilinearCZFagerstrom @@ -77,35 +75,20 @@ class IntMatBilinearCZFagerstromRate : public IntMatBilinearCZFagerstrom { protected: /// Rate dependence coefficient - double c_star; + double c_star = 0.; /// Rate dependence exponent - double m; - virtual int checkConsistency(); + double m = 0.; + int checkConsistency() override; - public: /// Constructor IntMatBilinearCZFagerstromRate(int n, Domain *d); - /// Destructor - virtual ~IntMatBilinearCZFagerstromRate(); - - virtual void giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &F, TimeStep *tStep); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - void printYourself(); - - - /** - * Tells if the model has implemented analytical tangent stiffness. - * If not, the tangent must be computed numerically. - */ - virtual bool hasAnalyticalTangentStiffness() const {return true;} - - -protected: - + FloatArrayF<3> giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const override; + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void printYourself() override; + bool hasAnalyticalTangentStiffness() const override { return true; } }; } // end namespace oofem #endif // isointerfacedamage01_h diff --git a/src/sm/Materials/InterfaceMaterials/intmatbilinczjansson.C b/src/sm/Materials/InterfaceMaterials/intmatbilinczjansson.C index 0c952f4e4..28be7e758 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatbilinczjansson.C +++ b/src/sm/Materials/InterfaceMaterials/intmatbilinczjansson.C @@ -46,79 +46,52 @@ namespace oofem { REGISTER_Material( IntMatBilinearCZJansson ); -IntMatBilinearCZJansson :: IntMatBilinearCZJansson(int n, Domain *d) : StructuralInterfaceMaterial(n, d), - mSemiExplicit(false) +IntMatBilinearCZJansson :: IntMatBilinearCZJansson(int n, Domain *d) : StructuralInterfaceMaterial(n, d) { } -IntMatBilinearCZJansson :: ~IntMatBilinearCZJansson() { } - ///@todo - need to rearrange traction and stiffness matrix so the first component is normal -void -IntMatBilinearCZJansson :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &d, - const FloatMatrix &F, TimeStep *tStep) +FloatArrayF<3> +IntMatBilinearCZJansson :: giveFirstPKTraction_3d(const FloatArrayF<3> &d, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const { // returns real stress vector in 3d stress space of receiver according to // previous level of stress and current // strain increment, the only way, how to correctly update gp records - - IntMatBilinearCZJanssonStatus *status = static_cast< IntMatBilinearCZJanssonStatus * >( this->giveStatus(gp) ); - FloatMatrix Finv; + IntMatBilinearCZJanssonStatus *status = static_cast< IntMatBilinearCZJanssonStatus * >( this->giveStatus(gp) ); - Finv.beInverseOf(F); + auto Finv = inv(F); status->letTempInverseDefGradBe(Finv); - FloatArray dJ; - dJ.beProductOf(Finv,d); - - + auto dJ = dot(Finv, d); status->letTempMaterialJumpBe(dJ); double oldDamage = status->giveDamage(); double dAlpha = 0.0; - FloatArray Qold(3), Qtemp(3), Qtemp_comp(3); - Qtemp.zero(); - Qtemp_comp.zero(); + FloatArrayF<3> Qold, Qtemp, Qtemp_comp; if ( dJ.at(3) < 0 ) { Qtemp_comp.at(3) = this->knc*dJ.at(3); } - FloatArray Qtrial = status->giveEffectiveMandelTraction(); + auto Qtrial = status->giveEffectiveMandelTraction(); - if (oldDamage < 0.99) { - + if ( oldDamage < 0.99 ) { //FloatArray Qtrial = status->giveEffectiveMandelTraction(); - FloatMatrix Kstiff(3,3); - FloatArray help; - Kstiff.zero(); - Kstiff.at(1,1) = this->ks0; - Kstiff.at(2,2) = this->ks0; - Kstiff.at(3,3) = this->kn0; + auto Kstiff = diag<3>({this->ks0, this->ks0, this->kn0}); //} else { // Kstiff.at(3,3) = this->kn0/(1-oldDamage); //} - dJ.subtract(status->giveOldMaterialJump()); - - help.beProductOf(Kstiff, dJ); - Qtrial.add(help); + dJ -= status->giveOldMaterialJump(); + Qtrial += dot(Kstiff, dJ); double Qn = Qtrial.at(3); - FloatArray QN(3); - QN.zero(); - QN.at(3) = Qn; - - FloatArray QtrialShear; - - QtrialShear = Qtrial; - QtrialShear.subtract(QN); - - double Qt = QtrialShear.computeNorm(); + FloatArrayF<3> QtrialShear = {Qtrial[0], Qtrial[1], 0.}; + double Qt = norm(QtrialShear); // double S = this->GIc/this->sigf; double sigf = this->sigf; @@ -132,29 +105,27 @@ IntMatBilinearCZJansson :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint double loadFun = sigf*pow(Qt/(gamma*sigf),2) + sigf*(1-c)*pow((Qn_M/sigf),2) + sigf*c*(Qn/sigf) - sigf; - Qold = status->giveEffectiveMandelTraction(); + // completely unused? + //auto Qold = status->giveEffectiveMandelTraction(); Qtemp = Qtrial; //Qold.rotatedWith(Rot,'n'); - - if (loadFun/sigf < 0.0000001) { + if ( loadFun/sigf < 0.0000001 ) { dAlpha = 0.0; // new_alpha=old_alpha status->letTempEffectiveMandelTractionBe(Qtemp); - Qtemp.times(1-oldDamage); + Qtemp *= 1-oldDamage; } else { status->letTempDamageDevBe(true); // dalpha = datr - double C1,C2; - - C1 = (pow((Qt/gamma),2)+(1-c)*pow(Qn_M,2))/(pow(sigf,2)); - C2 = c*Qn_M/sigf; + double C1 = (pow((Qt/gamma),2)+(1-c)*pow(Qn_M,2))/(pow(sigf,2)); + double C2 = c*Qn_M/sigf; //double xi = (-C2 + sqrt(pow(C2,2)+(1-c*Qn_M/sigf)*4*C1))/(2*C1); double xi = 0.0; - if (Qn >=0) { + if ( Qn >= 0 ) { xi = (-C2 + sqrt(pow(C2,2)+4*C1))/(2*C1); } else { if (1-c*Qn/sigf>0) { @@ -167,23 +138,23 @@ IntMatBilinearCZJansson :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint Qt = xi*Qt; Qn = 0.5*((1+xi)-(1-xi)*sgn(Qn))*Qn; Qn_M = 0.5*(Qn + fabs(Qn)); - + double beta = pow(Qt,2)*Kstiff.at(3,3)/(pow(Qn_M,2)*Kstiff.at(1,1) + pow(Qt,2)*Kstiff.at(3,3)); double G_beta = beta*(this->GIIc - pow(gamma*sigf,2)/(2*this->ks0)) + (1-beta)*(this->GIc - pow(sigf,2)/(2*this->kn0)); // assuming linear interpolation between mode I and II - - + + double eta = (pow(Qn_M,2) + pow(Qt,2)*Kstiff.at(3,3)/Kstiff.at(1,1))/(G_beta*sigf); - + dAlpha = (1/xi-1)*sigf/(2*Kstiff.at(3,3))*eta; if ( oldDamage + dAlpha > 1 ) { dAlpha = 1-oldDamage; } - - double Qt_trial = QtrialShear.computeNorm(); - double Qt1,Qt2; + double Qt_trial = norm(QtrialShear); + + double Qt1, Qt2; if ( Qt_trial > 0 ) { Qt1 = Qt*QtrialShear.at(1)/Qt_trial; @@ -194,7 +165,7 @@ IntMatBilinearCZJansson :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint } - FloatArray Mstar(3), M(3); + FloatArrayF<3> Mstar, M; Mstar.at(1) = 2*Qt1*this->kn0/Kstiff.at(1,1)/(sigf); // Qt = sqrt(Qt1^2 + Qt2^2) Mstar.at(2) = 2*Qt2*this->kn0/Kstiff.at(2,2)/(sigf); @@ -209,7 +180,7 @@ IntMatBilinearCZJansson :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint Smat.at(1,1) = 1.0 + dAlpha*(1/eta)*2*this->kn0/(sigf); // S_mat(1:2,1:2) = eye3(1:2,1:2)+ dalpha*S*dMdJtn_e(1:2,1:2) Smat.at(2,2) = 1.0 + dAlpha*(1/eta)*2*this->kn0/(sigf); - + if ( Qn_M > 0 ) { Smat.at(3,3) = 1.0 + dAlpha*(1/eta)*2*Kstiff.at(3,3)/(sigf); } else { @@ -219,7 +190,7 @@ IntMatBilinearCZJansson :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint Smat.at(1,4) = (1/eta)*Mstar.at(1); // S_mat(1:2,3) = S*M(1:2) Smat.at(2,4) = (1/eta)*Mstar.at(2); Smat.at(3,4) = (1/eta)*Mstar.at(3); - + Smat.at(4,1) = M.at(1)*Kstiff.at(1,1); // S_mat(3,1:2) = MATMUL(M(1:2),Keye3(1:2,1:2)) Smat.at(4,2) = M.at(2)*Kstiff.at(2,2); Smat.at(4,3) = M.at(3)*Kstiff.at(3,3); @@ -249,9 +220,7 @@ IntMatBilinearCZJansson :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint dJ = status->giveTempJump(); status->letTempEffectiveMandelTractionBe(Qtemp); - Qtemp.times(1-oldDamage-dAlpha); - - + Qtemp *= 1 - oldDamage - dAlpha; #if 0 if (dJ.at(3)>=0) { @@ -279,90 +248,69 @@ IntMatBilinearCZJansson :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint //} } - Qtemp.add(Qtemp_comp); + Qtemp += Qtemp_comp; + + auto answer = Tdot(Finv, Qtemp); // t_1_hat = MATMUL(TRANSPOSE(Fci),Q) +// answer *= 1-oldDamage-dAlpha; // t1_s = (1-al)*t_1_hat - answer.beTProductOf(Finv,Qtemp); // t_1_hat = MATMUL(TRANSPOSE(Fci),Q) -// answer.times(1-oldDamage-dAlpha); // t1_s = (1-al)*t_1_hat - status->letTempDamageBe(oldDamage + dAlpha); // status->letTempEffectiveMandelTractionBe(Qtemp); // NEW! status->letTempJumpBe(d); status->letTempFirstPKTractionBe(answer); status->letTempFBe(F); - - if(mSemiExplicit) { - - Qtemp = Qtrial; - Qtemp.times(1-oldDamage); - Qtemp.add(Qtemp_comp); - answer.beTProductOf(Finv,Qtemp); // t_1_hat = MATMUL(TRANSPOSE(Fci),Q) + if ( mSemiExplicit ) { + Qtemp = (1-oldDamage) * Qtrial + Qtemp_comp; + answer = Tdot(Finv, Qtemp); // t_1_hat = MATMUL(TRANSPOSE(Fci),Q) } - -} + return answer; +} -void -IntMatBilinearCZJansson :: give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +IntMatBilinearCZJansson :: give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - - answer.resize(3,3); - answer.zero(); + IntMatBilinearCZJanssonStatus *status = static_cast< IntMatBilinearCZJanssonStatus * >( this->giveStatus(gp) ); //this->give3dStiffnessMatrix_dTdj_num(answer, rMode, gp, tStep); //OOFEM_WARNING("numerical tangent"); //answer.printYourself(); - IntMatBilinearCZJanssonStatus *status = static_cast< IntMatBilinearCZJanssonStatus * >( this->giveStatus(gp) ); + FloatMatrixF<3,3> answer; - if (status->giveOldDamageDev()) { + if ( status->giveOldDamageDev() ) { answer = status->giveOlddTdJ(); //answer.printYourself(); status->letOldDamageDevBe(false); } else { - double damage = status->giveTempDamage(); - const FloatMatrix &Finv = status->giveTempInverseDefGrad(); - FloatMatrix help; - FloatMatrix Kstiff(3,3); - const FloatArray &J = status->giveTempJump(); - answer.zero(); + const auto &Finv = status->giveTempInverseDefGrad(); + const auto &J = status->giveTempJump(); //FloatMatrix Rot = status->giveTempRotationMatrix(); - Kstiff.zero(); - Kstiff.at(1,1) = this->ks0; - Kstiff.at(2,2) = this->ks0; - Kstiff.at(3,3) = this->kn0; + auto Kstiff = diag<3>({this->ks0, this->ks0, this->kn0}); //Kstiff.rotatedWith(Rot); - if (damage >= 1.0) { - answer.resize(3,3); - answer.zero(); - if (J.at(3)<0) { + FloatMatrix help; + if ( damage >= 1.0 ) { + if ( J.at(3) < 0 ) { Kstiff.at(1,1) = 0.0; Kstiff.at(2,2) = 0.0; Kstiff.at(3,3) = this->knc; - help.beProductOf(Kstiff, Finv); - answer.beTProductOf(Finv, help); - //answer.printYourself(); + answer = rotate(Kstiff, Finv); } } else { if ( status->giveTempDamage() - status->giveDamage()==0.0 ) { - if ( J.at(3) < 0 ) { - Kstiff.at(3,3) = Kstiff.at(3,3) + (this->knc)/(1-damage); + Kstiff.at(3,3) += this->knc/(1-damage); } - help.beProductOf(Kstiff, Finv); - answer.beTProductOf(Finv, help); - answer.times(1-damage); // Ea=(1-new_alpha)*MATMUL(TRANSPOSE(Fci),MATMUL(Keye3,Fci)) + answer = (1-damage) * rotate(Kstiff, Finv); } else { - FloatMatrix Iep = status->giveTempIep(); - - //Iep.printYourself(); + const auto &Iep = status->giveTempIep(); //if (J.at(3)<0) { // Kstiff.at(1,1) = (1-damage)*Kstiff.at(1,1); @@ -371,32 +319,27 @@ IntMatBilinearCZJansson :: give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatRe //} else { // Kstiff.times((1-damage)); //} - Kstiff.times(1-damage); - answer.beProductOf(Kstiff, Iep); + answer = (1-damage) * dot(Kstiff, Iep); //answer.rotatedWith(Rot); // Ea_h = MATMUL(TRANSPOSE(Rot),MATMUL(Keye3,Iep)) // Ea_h = MATMUL(Ea_h,Rot) - FloatArray alpha_v = status->giveTempAlphav(); + const auto &alpha_v = status->giveTempAlphav(); //alpha_v.rotatedWith(Rot, 't'); // alpha_v = MATMUL(TRANSPOSE(Rot),alpha_v) - FloatMatrix t1hatFinvOpen; - FloatArray temp1, temp2, Qtemp; - Qtemp = status->giveTempEffectiveMandelTraction(); + const auto &Qtemp = status->giveTempEffectiveMandelTraction(); - temp1.beTProductOf(Finv,Qtemp); // CALL gmopen33(MATMUL(TRANSPOSE(Fci),Q),MATMUL(alpha_v,Fci),t1halFci_o) - temp2.beTProductOf(Finv,alpha_v); + auto temp1 = Tdot(Finv, Qtemp); // CALL gmopen33(MATMUL(TRANSPOSE(Fci),Q),MATMUL(alpha_v,Fci),t1halFci_o) + auto temp2 = Tdot(Finv, alpha_v); - t1hatFinvOpen.beDyadicProductOf(temp1,temp2); + auto t1hatFinvOpen = dyad(temp1, temp2); if ( J.at(3) < 0 ) { answer.at(3,3) += this->knc; } - help.beProductOf(answer,Finv); // Ea = (1-new_alpha)*MATMUL(TRANSPOSE(Fci),MATMUL(Ea_h,Fci)) -& - answer.beTProductOf(Finv,help); // t1halFci_o - // answer.times(1-damage); - answer.subtract(t1hatFinvOpen); + // Ea = (1-new_alpha)*MATMUL(TRANSPOSE(Fci),MATMUL(Ea_h,Fci)) -& + answer = rotate(answer, Finv) - t1hatFinvOpen; // t1halFci_o } } } @@ -406,35 +349,15 @@ IntMatBilinearCZJansson :: give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatRe //Kstiff.printYourself(); //printf("analytical tangent \n"); //answer.printYourself(); + return answer; } -int -IntMatBilinearCZJansson :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime) -{ - IntMatBilinearCZJanssonStatus *status = static_cast< IntMatBilinearCZJanssonStatus * >( this->giveStatus(gp) ); - if ( type == IST_DamageScalar ) { - answer.resize(1); - answer.at(1) = status->giveTempDamage(); - return 1; - } else { - return StructuralInterfaceMaterial :: giveIPValue(answer, gp, type, atTime); - } - -} - - - - - - const double tolerance = 1.0e-12; // small number -IRResultType -IntMatBilinearCZJansson :: initializeFrom(InputRecord *ir) +void +IntMatBilinearCZJansson :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, kn0, _IFT_IntMatBilinearCZJansson_kn); this->knc = kn0; // Defaults to the same stiffness in compression and tension IR_GIVE_OPTIONAL_FIELD(ir, this->knc, _IFT_IntMatBilinearCZJansson_knc); @@ -455,28 +378,21 @@ IntMatBilinearCZJansson :: initializeFrom(InputRecord *ir) // check validity of the material paramters if ( this->kn0 < 0.0 ) { - OOFEM_WARNING("stiffness kn0 is negative (%.2e)", this->kn0); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZJansson_kn, "must be positive"); } else if ( this->ks0 < 0.0 ) { - OOFEM_WARNING("stiffness ks0 is negative (%.2e)", this->ks0); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZJansson_ks, "must be positive"); } else if ( this->GIc < 0.0 ) { - OOFEM_WARNING("GIc is negative (%.2e)", this->GIc); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZJansson_g1c, "must be positive"); } else if ( this->GIIc < 0.0 ) { - OOFEM_WARNING("GIIc is negative (%.2e)", this->GIIc); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZJansson_g2c, "must be positive"); } else if ( this->gamma < 0.0 ) { - OOFEM_WARNING("gamma (%.2e) is below zero which is unphysical", this->gamma); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_IntMatBilinearCZJansson_gamma, "must be positive"); } - - if( ir->hasField(_IFT_IntMatBilinearCZJansson_semiexplicit) ) { + + if ( ir.hasField(_IFT_IntMatBilinearCZJansson_semiexplicit) ) { mSemiExplicit = true; printf("In IntMatBilinearCZJansson::initializeFrom: Semi-explicit time integration activated.\n"); } - - return IRRT_OK; } int @@ -505,27 +421,10 @@ IntMatBilinearCZJansson :: printYourself() } -//IntMatBilinearCZJanssonStatus :: IntMatBilinearCZJanssonStatus(int n, Domain *d, GaussPoint *g) : StructuralMaterialStatus(n, d, g) -IntMatBilinearCZJanssonStatus :: IntMatBilinearCZJanssonStatus(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g) +//IntMatBilinearCZJanssonStatus :: IntMatBilinearCZJanssonStatus(GaussPoint *g) : StructuralMaterialStatus(g) +IntMatBilinearCZJanssonStatus :: IntMatBilinearCZJanssonStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) { - oldMaterialJump.resize(3); - oldMaterialJump.zero(); - tempMaterialJump = oldMaterialJump; - - damage = tempDamage = 0.0; - - QEffective = oldMaterialJump; - tempQEffective = oldMaterialJump; - - - tempFInv.resize(3,3); - tempFInv.beUnitMatrix(); - - old_dTdJ.resize(3,3); - old_dTdJ.zero(); - - oldDamageDev = false; - + tempFInv = eye<3>(); #if 0 ///@todo Martin: Very bad implementation of intialisation of Rot @@ -557,16 +456,11 @@ IntMatBilinearCZJanssonStatus :: IntMatBilinearCZJanssonStatus(int n, Domain *d, #endif Iep = tempFInv; - alphav = oldMaterialJump; } -IntMatBilinearCZJanssonStatus :: ~IntMatBilinearCZJanssonStatus() -{ } - - void - IntMatBilinearCZJanssonStatus :: printOutputAt(FILE *file, TimeStep *tStep) +IntMatBilinearCZJanssonStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { ///@todo Martin: check need of this StructuralInterfaceMaterialStatus :: printOutputAt(file, tStep); @@ -590,16 +484,11 @@ IntMatBilinearCZJanssonStatus :: initTempStatus() tempDamage = damage; tempQEffective = QEffective; - tempFInv.resize(3,3); - tempFInv.zero(); + tempFInv = eye<3>(); Iep = tempFInv; alphav = oldMaterialJump; - tempFInv.at(1,1)=1.; - tempFInv.at(2,2)=1.; - tempFInv.at(3,3)=1.; - tempDamageDev = false; } diff --git a/src/sm/Materials/InterfaceMaterials/intmatbilinczjansson.h b/src/sm/Materials/InterfaceMaterials/intmatbilinczjansson.h index 2564714fc..ca5a9a148 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatbilinczjansson.h +++ b/src/sm/Materials/InterfaceMaterials/intmatbilinczjansson.h @@ -59,90 +59,82 @@ namespace oofem { class IntMatBilinearCZJanssonStatus : public StructuralInterfaceMaterialStatus { protected: - // material jump - FloatArray oldMaterialJump; + FloatArrayF<3> oldMaterialJump; // temporary material jump - FloatArray tempMaterialJump; + FloatArrayF<3> tempMaterialJump; // damage variable - double damage; + double damage = 0.; // temporary damage value - double tempDamage; + double tempDamage = 0.; // Effective Mandel traction - FloatArray QEffective; + FloatArrayF<3> QEffective; // Temporary effective Mandel traction - FloatArray tempQEffective; + FloatArrayF<3> tempQEffective; // Temporary inverse of deformation gradient - FloatMatrix tempFInv; + FloatMatrixF<3,3> tempFInv; // Temporary array for coordinate transformation - FloatMatrix tempRot; + FloatMatrixF<3,3> tempRot; // tempArrays for stiffness calculation - FloatMatrix Iep; - FloatArray alphav; + FloatMatrixF<3,3> Iep; + FloatArrayF<3> alphav; // indicator for davae development of preceding time step - bool tempDamageDev; - bool oldDamageDev; + bool tempDamageDev = false; + bool oldDamageDev = false; // tangent stiffness from previous time step - FloatMatrix temp_dTdJ; - FloatMatrix old_dTdJ; - - + FloatMatrixF<3,3> temp_dTdJ; + FloatMatrixF<3,3> old_dTdJ; public: /// Constructor - IntMatBilinearCZJanssonStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~IntMatBilinearCZJanssonStatus(); + IntMatBilinearCZJanssonStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - // definition - virtual const char *giveClassName() const { return "IntMatBilinearCZJanssonStatus"; } + const char *giveClassName() const override { return "IntMatBilinearCZJanssonStatus"; } - double giveDamage() { return damage; } - double giveTempDamage() { return tempDamage; } - bool giveOldDamageDev() {return oldDamageDev;} + double giveDamage() const override { return damage; } + double giveTempDamage() const override { return tempDamage; } + bool giveOldDamageDev() const { return oldDamageDev; } - const FloatArray &giveOldMaterialJump() { return oldMaterialJump; } - const FloatArray &giveTempMaterialJump() { return tempMaterialJump; } + const FloatArrayF<3> &giveOldMaterialJump() const { return oldMaterialJump; } + const FloatArrayF<3> &giveTempMaterialJump() const { return tempMaterialJump; } - const FloatArray &giveEffectiveMandelTraction() { return QEffective; } - const FloatArray &giveTempEffectiveMandelTraction() { return tempQEffective; } + const FloatArrayF<3> &giveEffectiveMandelTraction() const { return QEffective; } + const FloatArrayF<3> &giveTempEffectiveMandelTraction() const { return tempQEffective; } - const FloatMatrix &giveTempInverseDefGrad() { return tempFInv; } - const FloatMatrix &giveTempRotationMatrix() { return tempRot; } - const FloatMatrix &giveTempIep() { return Iep; } - const FloatArray &giveTempAlphav() { return alphav; } - const FloatMatrix &giveOlddTdJ() {return old_dTdJ; } + const FloatMatrixF<3,3> &giveTempInverseDefGrad() const { return tempFInv; } + const FloatMatrixF<3,3> &giveTempRotationMatrix() const { return tempRot; } + const FloatMatrixF<3,3> &giveTempIep() const { return Iep; } + const FloatArrayF<3> &giveTempAlphav() const { return alphav; } + const FloatMatrixF<3,3> &giveOlddTdJ() const { return old_dTdJ; } void letTempDamageBe(double v) { tempDamage = v; } - void letTempEffectiveMandelTractionBe(FloatArray v) { tempQEffective = std :: move(v); } - void letTempMaterialJumpBe(FloatArray v) { tempMaterialJump = std :: move(v); } + void letTempEffectiveMandelTractionBe(const FloatArrayF<3> &v) { tempQEffective = std :: move(v); } + void letTempMaterialJumpBe(const FloatArrayF<3> &v) { tempMaterialJump = std :: move(v); } void letTempDamageDevBe(bool v) { tempDamageDev = v; } void letOldDamageDevBe(bool v) { oldDamageDev = v; } - void letTempdTdJBe(FloatMatrix &v) { temp_dTdJ = v; } - - void letTempInverseDefGradBe(FloatMatrix v) { tempFInv = std :: move(v); } - void letTempRotationMatrix(FloatMatrix v) { tempRot = std :: move(v); } - void letTempIepBe(FloatMatrix v) { Iep = std :: move(v); } - void letTempAlphavBe(FloatArray v) { alphav = std :: move(v); } + void letTempdTdJBe(const FloatMatrix &v) { temp_dTdJ = v; } + void letTempInverseDefGradBe(const FloatMatrixF<3,3> &v) { tempFInv = std :: move(v); } + void letTempRotationMatrix(const FloatMatrixF<3,3> &v) { tempRot = std :: move(v); } + void letTempIepBe(const FloatMatrixF<3,3> &v) { Iep = std :: move(v); } + void letTempAlphavBe(const FloatArrayF<3> &v) { alphav = std :: move(v); } + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); - - //virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - //virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + //void saveContext(DataStream &stream, ContextMode mode) override; + //void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -161,50 +153,39 @@ class IntMatBilinearCZJanssonStatus : public StructuralInterfaceMaterialStatus class IntMatBilinearCZJansson : public StructuralInterfaceMaterial { protected: - /// Material parameters - double kn0; // initial normal stiffness - double ks0; // initial shear stiffness - double knc; // stiffness in compression - double GIc; // fracture energy, mode 1 - double GIIc; // fracture energy, mode 1 - double sigf; // max stress + double kn0 = 0.; // initial normal stiffness + double ks0 = 0.; // initial shear stiffness + double knc = 0.; // stiffness in compression + double GIc = 0.; // fracture energy, mode 1 + double GIIc = 0.; // fracture energy, mode 1 + double sigf = 0.; // max stress - double mu; // loading function parameter - double gamma; // loading function parameter - - bool mSemiExplicit; // If semi-explicit time integration should be used + double mu = 0.; // loading function parameter + double gamma = 0.; // loading function parameter + bool mSemiExplicit = false; // If semi-explicit time integration should be used - virtual int checkConsistency(); + int checkConsistency() override; void give3dInterfaceMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); public: - /// Constructor IntMatBilinearCZJansson(int n, Domain * d); - /// Destructor - virtual ~IntMatBilinearCZJansson(); - virtual int hasNonLinearBehaviour() { return 1; } + const char *giveClassName() const override { return "IntMatBilinearCZJansson"; } + const char *giveInputRecordName() const override { return _IFT_IntMatBilinearCZJansson_Name; } - virtual const char *giveClassName() const { return "IntMatBilinearCZJansson"; } - virtual const char *giveInputRecordName() const { return _IFT_IntMatBilinearCZJansson_Name; } + FloatArrayF<3> giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + bool hasAnalyticalTangentStiffness() const override { return true; } - virtual void giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &F, TimeStep *tStep); - virtual void give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void initializeFrom(InputRecord &ir) override; - virtual bool hasAnalyticalTangentStiffness() const { return true; } + FloatArray giveInterfaceStrength() override { return {this->sigf*this->gamma,this->sigf*this->gamma,this->sigf}; } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual FloatArray giveInterfaceStrength() { return {this->sigf*this->gamma,this->sigf*this->gamma,this->sigf}; } - - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new IntMatBilinearCZJanssonStatus(1, domain, gp); } //@Martin: Why new? - void printYourself(); -protected: + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new IntMatBilinearCZJanssonStatus(gp); } + void printYourself() override; }; } // end namespace oofem #endif // isointerfacedamage01_h diff --git a/src/sm/Materials/InterfaceMaterials/intmatbilinearcz.C b/src/sm/Materials/InterfaceMaterials/intmatbilinearcz.C index 4daa2f346..81bcb4e5f 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatbilinearcz.C +++ b/src/sm/Materials/InterfaceMaterials/intmatbilinearcz.C @@ -47,18 +47,10 @@ REGISTER_Material(IntMatBilinearCZ); ///@todo - need to rearrange traction and stiffness matrix so the first component is normal -IntMatBilinearCZStatus :: IntMatBilinearCZStatus(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g), - mDamageNew(0.), mDamageOld(0.), - mTractionOld(3), mTractionNew(3), - mJumpOld(3), mJumpNew(3), - mPlastMultIncNew(0.), mPlastMultIncOld(0.) -{ -} +IntMatBilinearCZStatus :: IntMatBilinearCZStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) +{} -IntMatBilinearCZStatus :: ~IntMatBilinearCZStatus() -{ } - void IntMatBilinearCZStatus :: initTempStatus() { } @@ -80,8 +72,7 @@ void IntMatBilinearCZStatus :: copyStateVariables(const MaterialStatus &iStatus) { StructuralInterfaceMaterialStatus :: copyStateVariables(iStatus); - MaterialStatus &tmpStat = const_cast< MaterialStatus & >(iStatus); - const IntMatBilinearCZStatus &structStatus = dynamic_cast< IntMatBilinearCZStatus & >(tmpStat); + const IntMatBilinearCZStatus &structStatus = static_cast< const IntMatBilinearCZStatus & >(iStatus); mDamageNew = structStatus.mDamageNew; mDamageOld = structStatus.mDamageOld; @@ -100,80 +91,66 @@ void IntMatBilinearCZStatus :: addStateVariables(const MaterialStatus &iStatus) } -IntMatBilinearCZ :: IntMatBilinearCZ(int n, Domain *d) : StructuralInterfaceMaterial(n, d), - mPenaltyStiffness(0.0), - mGIc(0.0), mGIIc(0.0), - mSigmaF(0.0), - mMu(0.0), - mGamma(0.0), - mSemiExplicit(false) +IntMatBilinearCZ :: IntMatBilinearCZ(int n, Domain *d) : StructuralInterfaceMaterial(n, d) { } -IntMatBilinearCZ :: ~IntMatBilinearCZ() -{ } int IntMatBilinearCZ :: checkConsistency() { return 1; } -void IntMatBilinearCZ :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &F, TimeStep *tStep) +FloatArrayF<3> IntMatBilinearCZ :: giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const { - double maxDamage = 0.99999999; IntMatBilinearCZStatus *status = static_cast< IntMatBilinearCZStatus * >( this->giveStatus(gp) ); status->mJumpNew = jump; - FloatArray jumpInc; - jumpInc.beDifferenceOf(status->mJumpNew, status->mJumpOld); + auto jumpInc = status->mJumpNew - status->mJumpOld; - FloatArray tractionTrial = status->mTractionOld; - tractionTrial.add(mPenaltyStiffness, jumpInc); + auto tractionTrial = status->mTractionOld + mPenaltyStiffness * jumpInc; - double TTrNormal = tractionTrial.at(3); - double TTrTang = sqrt( pow(tractionTrial.at(1), 2.0) + pow(tractionTrial.at(2), 2.0) ); + double TTrNormal = tractionTrial.at(3); + double TTrTang = sqrt( pow(tractionTrial.at(1), 2.0) + pow(tractionTrial.at(2), 2.0) ); double phiTr = computeYieldFunction(TTrNormal, TTrTang); if ( status->mDamageOld > maxDamage ) { status->mDamageNew = maxDamage; status->mDamageOld = maxDamage; status->mPlastMultIncNew = 0.0; - answer.resize(3); - answer.zero(); + FloatArrayF<3> answer; status->mTractionNew = answer; status->letTempJumpBe(jump); status->letTempFirstPKTractionBe(answer); status->letTempTractionBe(answer); - return; + return answer; } - answer = tractionTrial; - if ( phiTr < 0.0 ) { status->mDamageNew = status->mDamageOld; status->mPlastMultIncNew = 0.0; - status->mTractionNew = answer; + status->mTractionNew = tractionTrial; status->letTempJumpBe(jump); - status->letTempFirstPKTractionBe(answer); - status->letTempTractionBe(answer); + status->letTempFirstPKTractionBe(tractionTrial); + status->letTempTractionBe(tractionTrial); + auto answer = tractionTrial; // answer.beScaled( ( 1.0 - status->mDamageNew ), answer ); answer.at(1) *= ( 1.0 - status->mDamageNew ); answer.at(2) *= ( 1.0 - status->mDamageNew ); - if(answer.at(3) > 0.0) { + if ( answer.at(3) > 0.0 ) { answer.at(3) *= ( 1.0 - status->mDamageNew ); } - return; + return answer; } else { // Iterate to find plastic strain increment. int maxIter = 50; @@ -186,10 +163,10 @@ void IntMatBilinearCZ :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint * for ( int iter = 0; iter < maxIter; iter++ ) { // Evaluate residual (i.e. yield function) - computeTraction(answer, tractionTrial, plastMultInc); + auto answer = computeTraction(tractionTrial, plastMultInc); - double TNormal = answer.at(3); - double TTang = sqrt( pow(answer.at(1), 2.0) + pow(answer.at(2), 2.0) ); + double TNormal = answer.at(3); + double TTang = sqrt( pow(answer.at(1), 2.0) + pow(answer.at(2), 2.0) ); double phi = computeYieldFunction(TNormal, TTang); // if(iter > 20) { @@ -220,37 +197,35 @@ void IntMatBilinearCZ :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint * status->letTempFirstPKTractionBe(answer); status->letTempTractionBe(answer); - if(mSemiExplicit) { - computeTraction(answer, tractionTrial, status->mPlastMultIncOld); + if ( mSemiExplicit ) { + answer = computeTraction(tractionTrial, status->mPlastMultIncOld); // answer.beScaled( ( 1.0 - status->mDamageOld ), answer ); answer.at(1) *= ( 1.0 - status->mDamageOld ); answer.at(2) *= ( 1.0 - status->mDamageOld ); - if(answer.at(3) > 0.0) { + if ( answer.at(3) > 0.0 ) { answer.at(3) *= ( 1.0 - status->mDamageOld ); } - } - else { + } else { // answer.beScaled( ( 1.0 - status->mDamageNew ), answer ); answer.at(1) *= ( 1.0 - status->mDamageNew ); answer.at(2) *= ( 1.0 - status->mDamageNew ); - if(answer.at(3) > 0.0) { + if ( answer.at(3) > 0.0 ) { answer.at(3) *= ( 1.0 - status->mDamageNew ); } } - return; + return answer; } // Numerical Jacobian - FloatArray tractionPert(3); - computeTraction(tractionPert, tractionTrial, plastMultInc + eps); - double TNormalPert = tractionPert.at(3); - double TTangPert = sqrt( pow(tractionPert.at(1), 2.0) + pow(tractionPert.at(2), 2.0) ); + auto tractionPert = computeTraction(tractionTrial, plastMultInc + eps); + double TNormalPert = tractionPert.at(3); + double TTangPert = sqrt( pow(tractionPert.at(1), 2.0) + pow(tractionPert.at(2), 2.0) ); double phiPert = computeYieldFunction(TNormalPert, TTangPert); double Jac = ( phiPert - phi ) / eps; @@ -259,29 +234,30 @@ void IntMatBilinearCZ :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint * } OOFEM_ERROR("No convergence in."); + return {0., 0., 0.}; } -void IntMatBilinearCZ :: give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> IntMatBilinearCZ :: give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_WARNING("not implemented. Use numerical Jacobian instead."); - this->give3dStiffnessMatrix_dTdj_Num(answer, gp, tStep); + return this->give3dStiffnessMatrix_dTdj_Num(gp, tStep); } -double IntMatBilinearCZ :: computeYieldFunction(const double &iTractionNormal, const double &iTractionTang) const +double IntMatBilinearCZ :: computeYieldFunction(double iTractionNormal, double iTractionTang) const { - return ( - mSigmaF * pow(fabs(iTractionTang) / ( mGamma * mSigmaF ), 2.0) - + ( mSigmaF / mGamma ) * ( mGamma - 2.0 * mMu ) * pow( ( max(iTractionNormal, 0.0) ) / mSigmaF, 2.0 ) - - ( 1.0 / mGamma ) * ( mGamma * mSigmaF - 2.0 * mMu * iTractionNormal ) ); + return mSigmaF * pow(fabs(iTractionTang) / ( mGamma * mSigmaF ), 2.0) + + ( mSigmaF / mGamma ) * ( mGamma - 2.0 * mMu ) * pow( ( max(iTractionNormal, 0.0) ) / mSigmaF, 2.0 ) + - ( 1.0 / mGamma ) * ( mGamma * mSigmaF - 2.0 * mMu * iTractionNormal ); } -void IntMatBilinearCZ :: computeTraction(FloatArray &oT, const FloatArray &iTTrial, const double &iPlastMultInc) const +FloatArrayF<3> IntMatBilinearCZ :: computeTraction(const FloatArrayF<3> &iTTrial, double iPlastMultInc) const { // Note that the traction vector is assumed to be decomposed into its tangential and normal part, // with tangential directions (1,2) and normal direction (3). - double gammaF = mGIIc / mGIc; + double gammaF = mGIIc / mGIc; + FloatArrayF<3> oT; // Tangential part oT.at(1) = iTTrial.at(1) / ( 1.0 + ( 2.0 * mPenaltyStiffness * gammaF ) * iPlastMultInc / ( mGamma * mGamma * mSigmaF ) ); oT.at(2) = iTTrial.at(2) / ( 1.0 + ( 2.0 * mPenaltyStiffness * gammaF ) * iPlastMultInc / ( mGamma * mGamma * mSigmaF ) ); @@ -292,23 +268,12 @@ void IntMatBilinearCZ :: computeTraction(FloatArray &oT, const FloatArray &iTTri } else { oT.at(3) = iTTrial.at(3) / ( 1.0 + 2.0 * mPenaltyStiffness * iPlastMultInc / mSigmaF ); } + return oT; } -int IntMatBilinearCZ :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) -{ - IntMatBilinearCZStatus *status = static_cast< IntMatBilinearCZStatus * >( this->giveStatus(gp) ); - if ( type == IST_DamageScalar ) { - answer.resize(1); - answer.at(1) = status->mDamageNew; - return 1; - } else { - return StructuralInterfaceMaterial :: giveIPValue(answer, gp, type, tStep); - } -} - -IRResultType IntMatBilinearCZ :: initializeFrom(InputRecord *ir) +void IntMatBilinearCZ :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralInterfaceMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, mPenaltyStiffness, _IFT_IntMatBilinearCZ_PenaltyStiffness); @@ -323,12 +288,10 @@ IRResultType IntMatBilinearCZ :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, mGamma, _IFT_IntMatBilinearCZ_gamma); - if( ir->hasField(_IFT_IntMatBilinearCZ_semiexplicit) ) { - mSemiExplicit = true; - printf("In IntMatBilinearCZ::initializeFrom: Semi-explicit time integration activated.\n"); + if ( ir.hasField(_IFT_IntMatBilinearCZ_semiexplicit) ) { + mSemiExplicit = true; + printf("In IntMatBilinearCZ::initializeFrom: Semi-explicit time integration activated.\n"); } - - return StructuralInterfaceMaterial :: initializeFrom(ir); } void IntMatBilinearCZ :: giveInputRecord(DynamicInputRecord &input) diff --git a/src/sm/Materials/InterfaceMaterials/intmatbilinearcz.h b/src/sm/Materials/InterfaceMaterials/intmatbilinearcz.h index 5a35d1560..d9f5e1e70 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatbilinearcz.h +++ b/src/sm/Materials/InterfaceMaterials/intmatbilinearcz.h @@ -57,32 +57,31 @@ namespace oofem { class IntMatBilinearCZStatus : public StructuralInterfaceMaterialStatus { public: - IntMatBilinearCZStatus(int n, Domain * d, GaussPoint * g); - virtual ~IntMatBilinearCZStatus(); + IntMatBilinearCZStatus(GaussPoint * g); /// damage variable - double mDamageNew, mDamageOld; + double mDamageNew = 0., mDamageOld = 0.; /// Traction - FloatArray mTractionOld, mTractionNew; + FloatArrayF<3> mTractionOld, mTractionNew; /// Discontinuity - FloatArray mJumpOld, mJumpNew; + FloatArrayF<3> mJumpOld, mJumpNew; /** * Increment of plastic multiplier. Storing this allows * semi-explicit update of damage. */ - double mPlastMultIncNew, mPlastMultIncOld; + double mPlastMultIncNew = 0., mPlastMultIncOld = 0.; - virtual const char *giveClassName() const { return "IntMatBilinearCZStatus"; } + const char *giveClassName() const override { return "IntMatBilinearCZStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; /// Functions for MaterialStatusMapperInterface - virtual void copyStateVariables(const MaterialStatus &iStatus); - virtual void addStateVariables(const MaterialStatus &iStatus); + void copyStateVariables(const MaterialStatus &iStatus) override; + void addStateVariables(const MaterialStatus &iStatus) override; }; @@ -93,52 +92,43 @@ class IntMatBilinearCZStatus : public StructuralInterfaceMaterialStatus */ class IntMatBilinearCZ : public StructuralInterfaceMaterial { -public: - IntMatBilinearCZ(int n, Domain * d); - virtual ~IntMatBilinearCZ(); - protected: - /// Material parameters - double mPenaltyStiffness; - double mGIc; // fracture energy, mode 1 - double mGIIc; // fracture energy, mode 2 - double mSigmaF; // max stress + double mPenaltyStiffness = 0.; + double mGIc = 0.; // fracture energy, mode 1 + double mGIIc = 0.; // fracture energy, mode 2 + double mSigmaF = 0.; // max stress - double mMu; // loading function parameter - double mGamma; // loading function parameter + double mMu = 0.; // loading function parameter + double mGamma = 0.; // loading function parameter - bool mSemiExplicit; // If semi-explicit time integration should be used + bool mSemiExplicit = false; // If semi-explicit time integration should be used - virtual int checkConsistency(); + int checkConsistency() override; public: + IntMatBilinearCZ(int n, Domain * d); - virtual int hasNonLinearBehaviour() { return 1; } - - virtual const char *giveClassName() const { return "IntMatBilinearCZ"; } - virtual const char *giveInputRecordName() const { return _IFT_IntMatBilinearCZ_Name; } - + const char *giveClassName() const override { return "IntMatBilinearCZ"; } + const char *giveInputRecordName() const override { return _IFT_IntMatBilinearCZ_Name; } - virtual void giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &F, TimeStep *tStep); + FloatArrayF<3> giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const override; // Dummy implementation, we must rely on numerical computation of the tangent. - virtual void give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<3,3> give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual bool hasAnalyticalTangentStiffness() const { return false; } + bool hasAnalyticalTangentStiffness() const override { return false; } private: // Help functions - double computeYieldFunction(const double &iTractionNormal, const double &iTractionTang) const; - void computeTraction(FloatArray &oT, const FloatArray &iTTrial, const double &iPlastMultInc) const; + double computeYieldFunction(double iTractionNormal, double iTractionTang) const; + FloatArrayF<3> computeTraction(const FloatArrayF<3> &iTTrial, double iPlastMultInc) const; public: - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new IntMatBilinearCZStatus(1, domain, gp); } - virtual void printYourself(); + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new IntMatBilinearCZStatus(gp); } + void printYourself() override; }; } /* namespace oofem */ #endif /* INTMATBILINEARCZ_H_ */ diff --git a/src/sm/Materials/InterfaceMaterials/intmatcoulombcontact.C b/src/sm/Materials/InterfaceMaterials/intmatcoulombcontact.C index 7b414640b..0dbe373fe 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatcoulombcontact.C +++ b/src/sm/Materials/InterfaceMaterials/intmatcoulombcontact.C @@ -46,94 +46,20 @@ REGISTER_Material(IntMatCoulombContact); IntMatCoulombContact :: IntMatCoulombContact(int n, Domain *d) : StructuralInterfaceMaterial(n, d) { } -IntMatCoulombContact :: ~IntMatCoulombContact() { } - -void -IntMatCoulombContact :: giveEngTraction_3d( FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) -{ - IntMatCoulombContactStatus *status = static_cast< IntMatCoulombContactStatus * >( this->giveStatus( gp ) ); - - double normalJump = jump.at( 1 ); - FloatArray shearJump = { jump.at(2), jump.at(3) }; - - double normalStress = 0.0; - FloatArray shearStress, tempShearStressShift = status->giveShearStressShift(); - this->computeEngTraction( normalStress, shearStress, tempShearStressShift, - normalJump, shearJump ); - - // Set stress components in the traction vector - answer.resize( 3 ); - answer.at( 1 ) = normalStress; - answer.at( 2 ) = shearStress.at( 1 ); - answer.at( 3 ) = shearStress.at( 2 ); - - // Update gp - status->setTempShearStressShift( tempShearStressShift ); - status->letTempJumpBe( jump ); - status->letTempTractionBe( answer ); -} - - -void -IntMatCoulombContact :: giveEngTraction_2d( FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep ) -{ - IntMatCoulombContactStatus *status = static_cast< IntMatCoulombContactStatus * >( this->giveStatus( gp ) ); - - double normalJump = jump.at( 1 ); - FloatArray shearJump = FloatArray{ jump.at(2) }; - - double normalStress = 0.0; - FloatArray shearStress, tempShearStressShift = status->giveShearStressShift(); - this->computeEngTraction( normalStress, shearStress, tempShearStressShift, - normalJump, shearJump ); - - // Set stress components in the traction vector - answer.resize( 2 ); - answer.at( 1 ) = normalStress; - answer.at( 2 ) = shearStress.at( 1 ); - - // Update gp - status->setTempShearStressShift( tempShearStressShift ); - status->letTempJumpBe( jump ); - status->letTempTractionBe( answer ); -} - - -void -IntMatCoulombContact :: giveEngTraction_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) +FloatArrayF<3> +IntMatCoulombContact :: giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const { - // Returns the (engineering) traction vector (normal stress only) in 1d based on the - // spatial jump. The shear stress is not relevant in this case. - IntMatCoulombContactStatus *status = static_cast< IntMatCoulombContactStatus * >( this->giveStatus( gp ) ); + auto tempShearStressShift = status->giveShearStressShift(); - double normalJump = jump.at( 1 ); - FloatArray shearJump(0); - - double normalStress = 0.0; - FloatArray shearStress, tempShearStressShift(0); - this->computeEngTraction( normalStress, shearStress, tempShearStressShift, - normalJump, shearJump ); - - // Set stress components in the traction vector - answer.resize( 1 ); - answer.at( 1 ) = normalStress; - - // Update gp - status->letTempJumpBe( jump ); - status->letTempTractionBe( answer ); -} - - -void -IntMatCoulombContact :: computeEngTraction(double &normalStress, FloatArray &shearStress, - FloatArray &tempShearStressShift, double normalJump, const FloatArray &shearJump ) -{ + double normalJump = jump[0]; + FloatArrayF<2> shearJump{ jump[1], jump[2] }; double maxShearStress = 0.0; double shift = -this->kn * this->stiffCoeff * normalClearance; + double normalStress; if ( normalJump + normalClearance <= 0. ) { normalStress = this->kn * ( normalJump + normalClearance ) + shift; //in compression and after the clearance gap closed maxShearStress = fabs( normalStress ) * this->frictCoeff; @@ -141,56 +67,50 @@ IntMatCoulombContact :: computeEngTraction(double &normalStress, FloatArray &she normalStress = this->kn * this->stiffCoeff * ( normalJump + normalClearance ) + shift; maxShearStress = 0.; } + auto shearStress = this->kn * shearJump - tempShearStressShift; + double dp = norm(shearStress); + double eps = 1.0e-15; // small number + if ( dp > maxShearStress ) { + shearStress *= maxShearStress / ( dp + eps ); + } + tempShearStressShift = this->kn * shearJump - shearStress; - if ( shearJump.giveSize() != 0 ) { - - shearStress = this->kn * shearJump - tempShearStressShift; - double dp = shearStress.computeNorm(); - double eps = 1.0e-15; // small number - if ( dp > maxShearStress ) { - shearStress.times( maxShearStress / ( dp + eps ) ); - } - tempShearStressShift = this->kn * shearJump - shearStress; + // Set stress components in the traction vector + FloatArrayF<3> answer = {normalStress, shearStress[0], shearStress[1]}; - } else { // 1d -> no shear stresses - return; - } + // Update gp + status->setTempShearStressShift( tempShearStressShift ); + status->letTempJumpBe( jump ); + status->letTempTractionBe( answer ); + return answer; } -void -IntMatCoulombContact :: giveGeneralStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep, int numSpaceDim) -// -// Returns characteristic material stiffness matrix of the receiver -// +FloatMatrixF<3,3> +IntMatCoulombContact :: give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - IntMatCoulombContactStatus *status = static_cast< IntMatCoulombContactStatus * > ( this->giveStatus(gp) ); - const FloatArray &jump = status->giveTempJump(); + const auto &jump = status->giveTempJump(); + double normalJump = jump[0]; //in status, normal is always the first component - double normalJump = jump.at( 1 );//in status, normal is always the first component - - answer.resize( numSpaceDim, numSpaceDim ); - answer.beUnitMatrix(); + auto answer = eye<3>(); if ( rMode == SecantStiffness || rMode == TangentStiffness ) { if ( normalJump + normalClearance <= 0 ) { - answer.times( this->kn ); //in compression and after the clearance gap closed + answer *= this->kn; //in compression and after the clearance gap closed } else { - answer.times( this->kn * this->stiffCoeff ); + answer *= this->kn * this->stiffCoeff; } } else { - answer.times( this->kn ); + answer *= this->kn; } - + return answer; } -IRResultType -IntMatCoulombContact :: initializeFrom(InputRecord *ir) +void +IntMatCoulombContact :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralInterfaceMaterial :: initializeFrom( ir ); frictCoeff = 0.; stiffCoeff = 0.; @@ -199,8 +119,6 @@ IntMatCoulombContact :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, frictCoeff, _IFT_IntMatCoulombContact_frictCoeff); IR_GIVE_OPTIONAL_FIELD(ir, stiffCoeff, _IFT_IntMatCoulombContact_stiffCoeff); IR_GIVE_OPTIONAL_FIELD(ir, normalClearance, _IFT_IntMatCoulombContact_normalClearance); - - return StructuralInterfaceMaterial :: initializeFrom( ir ); } @@ -215,30 +133,16 @@ IntMatCoulombContact :: giveInputRecord(DynamicInputRecord &input) } -IntMatCoulombContactStatus :: IntMatCoulombContactStatus(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g) -{ - int size = d->giveNumberOfSpatialDimensions() - 1; - shearStressShift.resize(size); - tempShearStressShift.resize(size); - shearStressShift.zero(); - tempShearStressShift.zero(); -} - - -IntMatCoulombContactStatus :: ~IntMatCoulombContactStatus() -{ } +IntMatCoulombContactStatus :: IntMatCoulombContactStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) +{} void -IntMatCoulombContactStatus :: printOutputAt(FILE *file, TimeStep *tStep) +IntMatCoulombContactStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralInterfaceMaterialStatus::printOutputAt( file, tStep ); fprintf(file, "status { "); - if(this->shearStressShift.giveSize() == 2) { - fprintf( file, "shearStressShift (%f, %f)", this->shearStressShift.at( 1 ), this->shearStressShift.at( 2 ) ); - } else if(this->shearStressShift.giveSize() == 1) { - fprintf( file, "shearStressShift (%f)", this->shearStressShift.at( 1 ) ); - } + fprintf( file, "shearStressShift (%f, %f)", this->shearStressShift.at( 1 ), this->shearStressShift.at( 2 ) ); fprintf(file, "}\n"); } @@ -259,47 +163,24 @@ IntMatCoulombContactStatus :: updateYourself(TimeStep *tStep) } -FloatArray -IntMatCoulombContactStatus :: giveShearStressShift() -{ - return shearStressShift; -} - - -contextIOResultType -IntMatCoulombContactStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +IntMatCoulombContactStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralInterfaceMaterialStatus::saveContext( stream, mode ); - // save parent class status - if(( iores = StructuralInterfaceMaterialStatus::saveContext( stream, mode, obj ) ) != CIO_OK) { - THROW_CIOERR(iores); - } - - // write a raw data //if ( !stream.write(kappa) ) { //THROW_CIOERR(CIO_IOERR); //} - - return CIO_OK; } -contextIOResultType -IntMatCoulombContactStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +IntMatCoulombContactStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if(( iores = StructuralInterfaceMaterialStatus::restoreContext( stream, mode, obj ) ) != CIO_OK) { - THROW_CIOERR(iores); - } + StructuralInterfaceMaterialStatus::restoreContext( stream, mode ); - // read raw data //if ( !stream.read(kappa) ) { //THROW_CIOERR(CIO_IOERR); //} - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/Materials/InterfaceMaterials/intmatcoulombcontact.h b/src/sm/Materials/InterfaceMaterials/intmatcoulombcontact.h index 88154f6dc..67d9128e9 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatcoulombcontact.h +++ b/src/sm/Materials/InterfaceMaterials/intmatcoulombcontact.h @@ -58,24 +58,21 @@ namespace oofem { class IntMatCoulombContactStatus : public StructuralInterfaceMaterialStatus { protected: - FloatArray shearStressShift, tempShearStressShift; + FloatArrayF<2> shearStressShift, tempShearStressShift; public: - /// Constructor - IntMatCoulombContactStatus(int n, Domain *d, GaussPoint *g); - /// Destructor - virtual ~IntMatCoulombContactStatus(); + IntMatCoulombContactStatus(GaussPoint *g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - FloatArray giveShearStressShift(); - void setTempShearStressShift(FloatArray newShearStressShift) { tempShearStressShift = newShearStressShift; } + const FloatArrayF<2> &giveShearStressShift() const { return shearStressShift; } + void setTempShearStressShift(const FloatArrayF<2> &newShearStressShift) { tempShearStressShift = newShearStressShift; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -93,60 +90,31 @@ class IntMatCoulombContact : public StructuralInterfaceMaterial { protected: // Normal stiffness - double kn; + double kn = 0.; // Reduction factor of normal stiffness when material goes to tension - double stiffCoeff; + double stiffCoeff = 0.; // Friction coefficient - double frictCoeff; + double frictCoeff = 0.; /// Normal distance which needs to be closed when interface element should act in compression (distance is 0 by default). - double normalClearance; + double normalClearance = 0.; public: - /// Constructor IntMatCoulombContact( int n, Domain *d ); - /// Destructor - virtual ~IntMatCoulombContact(); - virtual int hasNonLinearBehaviour() { return 1; } - virtual const char *giveInputRecordName() const { return _IFT_IntMatCoulombContact_Name; } + const char *giveInputRecordName() const override { return _IFT_IntMatCoulombContact_Name; } + const char *giveClassName() const override { return "IntMatCoulombContact"; } - virtual void giveEngTraction_3d( FloatArray &answer, GaussPoint *gp, - const FloatArray &jump, TimeStep *tStep); + FloatArrayF<3> giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveEngTraction_2d( FloatArray &answer, GaussPoint *gp, - const FloatArray &jump, TimeStep *tStep); + FloatMatrixF<3,3> give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveEngTraction_1d( FloatArray &answer, GaussPoint *gp, - const FloatArray &jump, TimeStep *tStep); + std::pair> computeEngTraction(const FloatArrayF<2> &tempShearStressShift, double normalJump, const FloatArrayF<2> &shearJump ); - virtual void give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep) - { this->giveGeneralStiffnessMatrix(answer, rMode, gp, tStep, 3); } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + bool hasAnalyticalTangentStiffness() const override { return true; } - virtual void give2dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep) - { this->giveGeneralStiffnessMatrix(answer, rMode, gp, tStep, 2); } - - virtual void give1dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep) - { this->giveGeneralStiffnessMatrix(answer, rMode, gp, tStep, 1); } - - // This method returns the stiffness matrix according to the size of - // the spatial jump. - void giveGeneralStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, - GaussPoint *gp, - TimeStep *tStep, int numSpaceDim); - - void computeEngTraction(double &normalStress, FloatArray &shearStress, - FloatArray &tempShearStressShift, - double normalJump, const FloatArray &shearJump ); - - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual bool hasAnalyticalTangentStiffness( ) const { return true; } - - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new IntMatCoulombContactStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new IntMatCoulombContactStatus(gp); } }; } // end namespace oofem #endif // simpleinterfacemat_h diff --git a/src/sm/Materials/InterfaceMaterials/intmatdummycz.C b/src/sm/Materials/InterfaceMaterials/intmatdummycz.C index c262b09c4..81a74f8a4 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatdummycz.C +++ b/src/sm/Materials/InterfaceMaterials/intmatdummycz.C @@ -39,36 +39,26 @@ namespace oofem { REGISTER_Material(IntMatDummyCZ); -IntMatDummyCZ :: IntMatDummyCZ(int n, Domain *d) : StructuralInterfaceMaterial(n, d) -{ - -} - -IntMatDummyCZ :: ~IntMatDummyCZ() -{ - -} +IntMatDummyCZ :: IntMatDummyCZ(int n, Domain *d) : StructuralInterfaceMaterial(n, d) {} -void IntMatDummyCZ :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &F, TimeStep *tStep) +FloatArrayF<3> +IntMatDummyCZ :: giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const { StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus(gp) ); status->letTempJumpBe(jump); - answer.resize(3); - answer.zero(); + return {0., 0., 0.}; } -void IntMatDummyCZ :: give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> IntMatDummyCZ :: give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - answer.resize(3,3); - answer.zero(); + return zero<3,3>(); } -IRResultType IntMatDummyCZ :: initializeFrom(InputRecord *ir) +void IntMatDummyCZ :: initializeFrom(InputRecord &ir) { - return StructuralInterfaceMaterial :: initializeFrom(ir); + StructuralInterfaceMaterial :: initializeFrom(ir); } void IntMatDummyCZ :: giveInputRecord(DynamicInputRecord &input) diff --git a/src/sm/Materials/InterfaceMaterials/intmatdummycz.h b/src/sm/Materials/InterfaceMaterials/intmatdummycz.h index 5ed54b504..6d6da38ba 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatdummycz.h +++ b/src/sm/Materials/InterfaceMaterials/intmatdummycz.h @@ -56,24 +56,22 @@ class IntMatDummyCZ : public StructuralInterfaceMaterial { public: IntMatDummyCZ(int n, Domain *d); - virtual ~IntMatDummyCZ(); - virtual const char *giveClassName() const { return "IntMatBilinearCZ"; } - virtual const char *giveInputRecordName() const { return _IFT_IntMatDummyCZ_Name; } + const char *giveClassName() const override { return "IntMatBilinearCZ"; } + const char *giveInputRecordName() const override { return _IFT_IntMatDummyCZ_Name; } - virtual void giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &F, TimeStep *tStep); + FloatArrayF<3> giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const override; - virtual void give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<3,3> give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual bool hasAnalyticalTangentStiffness() const { return true; } + bool hasAnalyticalTangentStiffness() const override { return true; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new StructuralInterfaceMaterialStatus(1, domain, gp); } - virtual void printYourself(); + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new StructuralInterfaceMaterialStatus(gp); } + void printYourself() override; }; } /* namespace oofem */ diff --git a/src/sm/Materials/InterfaceMaterials/intmatelastic.C b/src/sm/Materials/InterfaceMaterials/intmatelastic.C index 6aecb416e..14e55f15b 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatelastic.C +++ b/src/sm/Materials/InterfaceMaterials/intmatelastic.C @@ -47,38 +47,33 @@ REGISTER_Material(IntMatElastic); IntMatElastic :: IntMatElastic(int n, Domain *d) : StructuralInterfaceMaterial(n, d) { } -IntMatElastic :: ~IntMatElastic() { } - -void -IntMatElastic :: giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jumpVector, - const FloatMatrix &F, TimeStep *tStep) +FloatArrayF<3> +IntMatElastic :: giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const { StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus(gp) ); - answer.beScaled(k, jumpVector); + auto answer = k * jump; - status->letTempJumpBe(jumpVector); + status->letTempJumpBe(jump); status->letTempFirstPKTractionBe(answer); status->letTempTractionBe(answer); + + return answer; } -void -IntMatElastic :: give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +IntMatElastic :: give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - answer.resize(3, 3); - answer.beUnitMatrix(); - answer.times(k); + return eye<3>() * k; } -IRResultType -IntMatElastic :: initializeFrom(InputRecord *ir) +void +IntMatElastic :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralInterfaceMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, k, _IFT_IntMatElastic_kn); - - return StructuralInterfaceMaterial :: initializeFrom(ir); } void IntMatElastic :: giveInputRecord(DynamicInputRecord &input) diff --git a/src/sm/Materials/InterfaceMaterials/intmatelastic.h b/src/sm/Materials/InterfaceMaterials/intmatelastic.h index 1c4cad37c..958034c15 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatelastic.h +++ b/src/sm/Materials/InterfaceMaterials/intmatelastic.h @@ -53,29 +53,25 @@ namespace oofem { */ class IntMatElastic : public StructuralInterfaceMaterial { -public: - IntMatElastic(int n, Domain * d); - virtual ~IntMatElastic(); - - virtual int hasNonLinearBehaviour() { return 0; } +protected: + double k = 0.; - virtual const char *giveClassName() const { return "IntMatElastic"; } - virtual const char *giveInputRecordName() const { return _IFT_IntMatElastic_Name; } +public: + IntMatElastic(int n, Domain * d); - virtual void giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jumpVector, - const FloatMatrix &F, TimeStep *tStep); + const char *giveClassName() const override { return "IntMatElastic"; } + const char *giveInputRecordName() const override { return _IFT_IntMatElastic_Name; } - virtual void give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + FloatArrayF<3> giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + FloatMatrixF<3,3> give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new StructuralInterfaceMaterialStatus(1, domain, gp); } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual bool hasAnalyticalTangentStiffness() const { return true; } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new StructuralInterfaceMaterialStatus(gp); } -protected: - double k; + bool hasAnalyticalTangentStiffness() const override { return true; } }; } /* namespace oofem */ diff --git a/src/sm/Materials/InterfaceMaterials/intmatisodamage.C b/src/sm/Materials/InterfaceMaterials/intmatisodamage.C index be4728a43..2581c7804 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatisodamage.C +++ b/src/sm/Materials/InterfaceMaterials/intmatisodamage.C @@ -46,30 +46,21 @@ namespace oofem { REGISTER_Material(IntMatIsoDamage); IntMatIsoDamage :: IntMatIsoDamage(int n, Domain *d) : StructuralInterfaceMaterial(n, d) -{ - maxOmega = 0.999999; - semiExplicit = false; -} +{} -IntMatIsoDamage :: ~IntMatIsoDamage() -{ } - - -void -IntMatIsoDamage :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &jump, - TimeStep *tStep) +FloatArrayF<3> +IntMatIsoDamage :: giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const { IntMatIsoDamageStatus *status = static_cast< IntMatIsoDamageStatus * >( this->giveStatus(gp) ); - - double f, equivJump, tempKappa = 0.0, omega = 0.0; + + double tempKappa = 0.0, omega = 0.0; // compute equivalent strain - this->computeEquivalentJump(equivJump, jump); + double equivJump = this->computeEquivalentJump(jump); // compute value of loading function - f = equivJump - status->giveKappa(); + double f = equivJump - status->giveKappa(); if ( f <= 0.0 ) { // no damage evolution @@ -79,7 +70,7 @@ IntMatIsoDamage :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, // damage evolution tempKappa = equivJump; // evaluate damage parameter - this->computeDamageParam(omega, tempKappa); + omega = this->computeDamageParam(tempKappa); } double strength = 1.0 - min(omega, maxOmega); @@ -90,7 +81,7 @@ IntMatIsoDamage :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, } //answer = {ks * jump.at(1) * strength, ks * jump.at(2) * strength, kn * jump.at(3)}; - answer = {kn * jump.at(1), ks * jump.at(2) * strength, ks * jump.at(3) * strength}; + FloatArrayF<3> answer = {kn * jump.at(1), ks * jump.at(2) * strength, ks * jump.at(3) * strength}; // damage in tension only if ( jump.at(1) >= 0 ) { answer.at(1) *= strength; @@ -102,37 +93,35 @@ IntMatIsoDamage :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, status->setTempKappa(tempKappa); status->setTempDamage(omega); + + return answer; } -void -IntMatIsoDamage :: giveFirstPKTraction_3d(FloatArray& answer, GaussPoint* gp, const FloatArray& jump, const FloatMatrix& F, TimeStep* tStep) +FloatArrayF<3> +IntMatIsoDamage :: giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint* gp, TimeStep* tStep) const { IntMatIsoDamageStatus *status = static_cast< IntMatIsoDamageStatus * > ( this->giveStatus ( gp ) ); - this->giveEngTraction_3d(answer, gp, jump, tStep); + auto answer = this->giveEngTraction_3d(jump, gp, tStep); status->letTempFirstPKTractionBe(answer); - + return answer; } -void -IntMatIsoDamage :: give2dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<2,2> +IntMatIsoDamage :: give2dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { IntMatIsoDamageStatus *status = static_cast< IntMatIsoDamageStatus * >( this->giveStatus(gp) ); // assemble eleastic stiffness - answer.resize(2, 2); - answer.zero(); - answer.at(1, 1) = kn; - answer.at(2, 2) = ks; + auto answer = diag<2>({kn, ks}); if ( rMode == ElasticStiffness ) { - return; + return answer; } - const FloatArray &jump3d = status->giveTempJump(); - FloatArray jump2d = {jump3d.at(3),jump3d.at(1)}; + const auto &jump3d = status->giveTempJump(); + FloatArray jump2d = {jump3d.at(1),jump3d.at(2)}; double om = min(status->giveTempDamage(), maxOmega); double un = jump2d.at(1); @@ -142,8 +131,6 @@ IntMatIsoDamage :: give2dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMod if ( un >= 0 ) { answer.at(1, 1) *= 1.0 - om; } - - return; } else { // Tangent Stiffness answer.at(2, 2) *= 1.0 - om; // damage in tension only @@ -156,12 +143,11 @@ IntMatIsoDamage :: give2dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMod computeDamageParam(omega, un); computeDamageParam(omega_plus, un + 1.0e-8 ); double dom = (omega_plus - omega)/ 1.0e-8; - + // d( (1-omega)*D*j ) / dj = (1-omega)D - D*j openprod domega/dj double fac = ft*(e0 - un)/gf; dom = e0*exp(fac) /(un*un + 1.0e-9) + e0*ft*exp(fac) / (gf*un + 1.0e-9); - - + dom = -( -e0 / (un * un+1.0e-9) * exp( -( ft / gf ) * ( un - e0 ) ) + e0 / (un+1.0e-9) * exp( -( ft / gf ) * ( un - e0 ) ) * ( -( ft / gf ) ) ); if ( ( om > 0. ) && ( status->giveTempKappa() > status->giveKappa() ) ) { answer.at(1, 2) -= se.at(1) * dom; @@ -170,50 +156,44 @@ IntMatIsoDamage :: give2dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMod #endif } } + return answer; } -void -IntMatIsoDamage :: give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +IntMatIsoDamage :: give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { IntMatIsoDamageStatus *status = static_cast< IntMatIsoDamageStatus * >( this->giveStatus(gp) ); // assemble eleastic stiffness - answer.resize(3, 3); - answer.zero(); - answer.at(1, 1) = kn; - answer.at(2, 2) = ks; - answer.at(3, 3) = ks; + auto answer = diag<3>({kn, ks, ks}); if ( rMode == ElasticStiffness ) { - return; + return answer; } - const FloatArray &jump3d = status->giveTempJump(); + const auto &jump3d = status->giveTempJump(); double om = min(status->giveTempDamage(), maxOmega); double un = jump3d.at(1); if ( rMode == SecantStiffness ) { - // Secant stiffness - answer.at(2, 2) *= 1.0 - om; - answer.at(3, 3) *= 1.0 - om; // damage in tension only if ( un >= 0 ) { answer.at(1, 1) *= 1.0 - om; } - - return; - } else { - // Tangent Stiffness + // Secant stiffness answer.at(2, 2) *= 1.0 - om; answer.at(3, 3) *= 1.0 - om; + } else { // damage in tension only if ( un >= 0 ) { answer.at(1, 1) *= 1.0 - om; } - return; + // Tangent Stiffness + answer.at(2, 2) *= 1.0 - om; + answer.at(3, 3) *= 1.0 - om; } + return answer; } @@ -249,10 +229,10 @@ IntMatIsoDamage :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalState } -IRResultType -IntMatIsoDamage :: initializeFrom(InputRecord *ir) +void +IntMatIsoDamage :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralInterfaceMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, kn, _IFT_IntMatIsoDamage_kn); IR_GIVE_FIELD(ir, ks, _IFT_IntMatIsoDamage_ks); @@ -266,8 +246,6 @@ IntMatIsoDamage :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, maxOmega, _IFT_IntMatIsoDamage_maxOmega); maxOmega = min(maxOmega, 0.999999); maxOmega = max(maxOmega, 0.0); - - return StructuralInterfaceMaterial :: initializeFrom(ir); } @@ -286,36 +264,28 @@ IntMatIsoDamage :: giveInputRecord(DynamicInputRecord &input) } -void -IntMatIsoDamage :: computeEquivalentJump(double &kappa, const FloatArray &jump) +double +IntMatIsoDamage :: computeEquivalentJump(const FloatArray &jump) const { - kappa = jump.at(1); + return jump.at(1); } -void -IntMatIsoDamage :: computeDamageParam(double &omega, double kappa) +double +IntMatIsoDamage :: computeDamageParam(double kappa) const { if ( kappa > this->e0 ) { - omega = 1.0 - ( this->e0 / kappa ) * exp( -( ft / gf ) * ( kappa - e0 ) ); + return 1.0 - ( this->e0 / kappa ) * exp( -( ft / gf ) * ( kappa - e0 ) ); } else { - omega = 0.0; + return 0.; } } -IntMatIsoDamageStatus :: IntMatIsoDamageStatus(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g) -{ - kappa = tempKappa = 0.0; - damage = tempDamage = 0.0; -} - - -IntMatIsoDamageStatus :: ~IntMatIsoDamageStatus() -{ } - +IntMatIsoDamageStatus :: IntMatIsoDamageStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) +{} void -IntMatIsoDamageStatus :: printOutputAt(FILE *file, TimeStep *tStep) +IntMatIsoDamageStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralInterfaceMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -344,17 +314,11 @@ IntMatIsoDamageStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -IntMatIsoDamageStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +IntMatIsoDamageStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralInterfaceMaterialStatus :: saveContext(stream, mode); - // write a raw data if ( !stream.write(kappa) ) { THROW_CIOERR(CIO_IOERR); } @@ -362,21 +326,13 @@ IntMatIsoDamageStatus :: saveContext(DataStream &stream, ContextMode mode, void if ( !stream.write(damage) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -IntMatIsoDamageStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +IntMatIsoDamageStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralInterfaceMaterialStatus :: restoreContext(stream, mode); - // read parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data if ( !stream.read(kappa) ) { THROW_CIOERR(CIO_IOERR); } @@ -384,8 +340,6 @@ IntMatIsoDamageStatus :: restoreContext(DataStream &stream, ContextMode mode, vo if ( !stream.read(damage) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/Materials/InterfaceMaterials/intmatisodamage.h b/src/sm/Materials/InterfaceMaterials/intmatisodamage.h index bf0583e84..1679e3052 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatisodamage.h +++ b/src/sm/Materials/InterfaceMaterials/intmatisodamage.h @@ -60,42 +60,39 @@ class IntMatIsoDamageStatus : public StructuralInterfaceMaterialStatus { protected: /// Scalar measure of the largest equivalent displacement ever reached in material. - double kappa; + double kappa = 0.; /// Non-equilibrated scalar measure of the largest equivalent displacement. - double tempKappa; + double tempKappa = 0.; /// Damage level of material. - double damage; + double damage = 0.; /// Non-equilibrated damage level of material. - double tempDamage; + double tempDamage = 0.; public: /// Constructor - IntMatIsoDamageStatus(int n, Domain *d, GaussPoint *g); - /// Destructor - virtual ~IntMatIsoDamageStatus(); + IntMatIsoDamageStatus(GaussPoint *g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; /// Returns the last equilibrated scalar measure of the largest jump level. - double giveKappa() { return kappa; } + double giveKappa() const { return kappa; } /// Returns the temp. scalar measure of the largest jump level. - double giveTempKappa() { return tempKappa; } + double giveTempKappa() const { return tempKappa; } /// Sets the temp scalar measure of the largest strain level to given value. void setTempKappa(double newKappa) { tempKappa = newKappa; } /// Returns the last equilibrated damage level. - double giveDamage() { return damage; } + double giveDamage() const override { return damage; } /// Returns the temp. damage level. - double giveTempDamage() { return tempDamage; } + double giveTempDamage() const override { return tempDamage; } /// Sets the temp damage level to given value. void setTempDamage(double newDamage) { tempDamage = newDamage; } - // definition - virtual const char *giveClassName() const { return "IntMatIsoDamageStatus"; } + const char *giveClassName() const override { return "IntMatIsoDamageStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -114,66 +111,59 @@ class IntMatIsoDamage : public StructuralInterfaceMaterial { protected: /// Elastic properties (normal moduli). - double kn; + double kn = 0.; /// Shear moduli. - double ks; + double ks = 0.; /// Tension strength. - double ft; + double ft = 0.; /// Fracture energy. - double gf; + double gf = 0.; /// Limit elastic deformation. - double e0; + double e0 = 0.; /// Maximum limit on omega. The purpose is elimination of a too compliant material which may cause convergency problems. Set to something like 0.99 if needed. - double maxOmega; + double maxOmega = 0.999999; - bool semiExplicit; // If semi-explicit time integration should be used + bool semiExplicit = false; // If semi-explicit time integration should be used public: - /// Constructor IntMatIsoDamage(int n, Domain *d); - /// Destructor - virtual ~IntMatIsoDamage(); - virtual const char *giveInputRecordName() const { return _IFT_IntMatIsoDamage_Name; } - virtual bool hasAnalyticalTangentStiffness() const { return true; } + const char *giveInputRecordName() const override { return _IFT_IntMatIsoDamage_Name; } + const char *giveClassName() const override { return "IntMatIsoDamage"; } + + bool hasAnalyticalTangentStiffness() const override { return true; } - virtual void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &jump, TimeStep *tStep); + FloatArrayF<3> giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp,TimeStep *tStep) const override; - virtual void giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &F, TimeStep *tStep); + FloatArrayF<3> giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; /** * Computes the equivalent jump measure from given jump vector (full form). - * @param[out] kappa Return parameter containing the corresponding equivalent jump. * @param jump Jump vector in full form. * @param gp Integration point. * @param tStep Time step. + * @return Return parameter containing the corresponding equivalent jump (kappa) */ - virtual void computeEquivalentJump(double &kappa, const FloatArray &jump); + virtual double computeEquivalentJump(const FloatArray &jump) const; /** * computes the value of damage parameter omega, based on given value of equivalent strain. - * @param[out] omega Contains result. * @param kappa Equivalent strain measure. * @param strain Total strain vector in full form. (unnecessary?) * @param gp Integration point. + * @return omega. */ - virtual void computeDamageParam(double &omega, double kappa); + virtual double computeDamageParam(double kappa) const; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new IntMatIsoDamageStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new IntMatIsoDamageStatus(gp); } -protected: - virtual void give2dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep); - virtual void give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<2,2> give2dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; }; } // end namespace oofem #endif // isointerfacedamage01_h diff --git a/src/sm/Materials/InterfaceMaterials/intmatisodamagetable.C b/src/sm/Materials/InterfaceMaterials/intmatisodamagetable.C index 00c9050cc..0918d5bea 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatisodamagetable.C +++ b/src/sm/Materials/InterfaceMaterials/intmatisodamagetable.C @@ -47,19 +47,14 @@ namespace oofem { REGISTER_Material(IntMatIsoDamageTable); -IntMatIsoDamageTable :: IntMatIsoDamageTable(int n, Domain *d) : IntMatIsoDamage(n, d){} +IntMatIsoDamageTable :: IntMatIsoDamageTable(int n, Domain *d) : IntMatIsoDamage(n, d) {} - -IntMatIsoDamageTable :: ~IntMatIsoDamageTable(){} - - - - -IRResultType -IntMatIsoDamageTable :: initializeFrom(InputRecord *ir) +void +IntMatIsoDamageTable :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralInterfaceMaterial :: initializeFrom(ir); + std :: ifstream is; int nbrOfLinesToRead; @@ -111,8 +106,6 @@ IntMatIsoDamageTable :: initializeFrom(InputRecord *ir) // We add e0 to the tableJumps since these should be given as the increase in // strain relative to e0. tableJumps.add(e0); - - return StructuralInterfaceMaterial :: initializeFrom(ir); } @@ -129,16 +122,15 @@ IntMatIsoDamageTable :: giveInputRecord(DynamicInputRecord &input) } - -void -IntMatIsoDamageTable :: computeDamageParam(double &omega, double kappa) +double +IntMatIsoDamageTable :: computeDamageParam(double kappa) const { if ( kappa > this->e0 ) { // Linear interpolation between able values. // If out of bounds damage is set to the last given damage value in the table if ( kappa >= tableJumps.at( tableJumps.giveSize() ) ) { - omega = tableDamages.at( tableDamages.giveSize() ); + return tableDamages.at( tableDamages.giveSize() ); } else { // std::lower_bound uses binary search to find index with value bounding kappa from above int index = (int)(std :: lower_bound(tableJumps.givePointer(), tableJumps.givePointer() + tableJumps.giveSize(), kappa) - tableJumps.givePointer()); @@ -160,14 +152,11 @@ IntMatIsoDamageTable :: computeDamageParam(double &omega, double kappa) double y1 = tableDamages(index ); // Interpolation formula - omega = y0 + ( y1 - y0 ) * ( kappa - x0 ) / ( x1 - x0 ); + return y0 + ( y1 - y0 ) * ( kappa - x0 ) / ( x1 - x0 ); } } else { - omega = 0.0; + return 0.0; } } - - - } // end namespace oofem diff --git a/src/sm/Materials/InterfaceMaterials/intmatisodamagetable.h b/src/sm/Materials/InterfaceMaterials/intmatisodamagetable.h index 15c7d073a..6318d36de 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatisodamagetable.h +++ b/src/sm/Materials/InterfaceMaterials/intmatisodamagetable.h @@ -79,7 +79,6 @@ namespace oofem { class IntMatIsoDamageTable : public IntMatIsoDamage { protected: - ///Additional parameters /// Name of table file std :: string tablename; /// Damages read from the second column in the table file @@ -90,22 +89,14 @@ class IntMatIsoDamageTable : public IntMatIsoDamage public: /// Constructor IntMatIsoDamageTable(int n, Domain *d); - /// Destructor - virtual ~IntMatIsoDamageTable(); - virtual const char *giveInputRecordName() const { return _IFT_IntMatIsoDamageTable_Name; } + const char *giveClassName() const override { return "IntMatIsoDamageTable"; } + const char *giveInputRecordName() const override { return _IFT_IntMatIsoDamageTable_Name; } - /** - * Computes the value of damage parameter omega, based on given value of equivalent strain. - * It uses a table (jump vs. damage) and interpolates linearly in between. - * @param[out] omega Contains result. - * @param kappa Equivalent strain measure. - */ - virtual void computeDamageParam(double &omega, double kappa); - - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + double computeDamageParam(double kappa) const override; + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; }; } // end namespace oofem #endif // isointerfacedamage01_h diff --git a/src/sm/Materials/InterfaceMaterials/intmatphasefield.C b/src/sm/Materials/InterfaceMaterials/intmatphasefield.C index e4f34df39..8e51434d6 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatphasefield.C +++ b/src/sm/Materials/InterfaceMaterials/intmatphasefield.C @@ -32,7 +32,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "Materials/InterfaceMaterials/structuralinterfacematerialphf.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialphf.h" #include "intmatphasefield.h" #include "gausspoint.h" @@ -45,113 +45,97 @@ #include "dynamicinputrecord.h" namespace oofem { - REGISTER_Material(IntMatPhaseField); +REGISTER_Material(IntMatPhaseField); - IntMatPhaseField::IntMatPhaseField(int n, Domain *d) : StructuralInterfaceMaterialPhF(n, d) { +IntMatPhaseField::IntMatPhaseField(int n, Domain *d) : StructuralInterfaceMaterialPhF(n, d) {} -} - -IntMatPhaseField::~IntMatPhaseField() { - -} -int -IntMatPhaseField :: hasMaterialModeCapability(MaterialMode mode) +bool +IntMatPhaseField :: hasMaterialModeCapability(MaterialMode mode) const { // returns whether receiver supports given mode - if ( mode == _3dInterface ) { - return 1; - } else { - return 0; - } + return mode == _3dInterface; } -void -IntMatPhaseField :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const double damage, TimeStep *tStep) +FloatArrayF<3> +IntMatPhaseField :: giveEngTraction_3d(const FloatArrayF<3> &jump, double damage, GaussPoint *gp, TimeStep *tStep) const { IntMatPhaseFieldStatus *status = static_cast< IntMatPhaseFieldStatus * >( this->giveStatus(gp) ); - - this->initTempStatus(gp); - - double g = compute_g(damage); - - answer.resize( jump.giveSize() ); - - answer.at(1) = g * k*jump.at(1); - answer.at(2) = g * k*jump.at(2); - - if ( jump.at(3) > 0.0 ) { // only degradation in tension - answer.at(3) = g * k*jump.at(3); - } else { - answer.at(3) = k*jump.at(3); - } - - double drivingEnergy = 0.5*k*jump.at(1)*jump.at(1) + 0.5*k*jump.at(2)*jump.at(2); - if ( jump.at(3) > 0.0 ) { - drivingEnergy += 0.5*k*jump.at(3)*jump.at(3); - } - if ( drivingEnergy > status->giveTempDrivingEnergy() ) { // max val - status->letTempDrivingEnergyBe( drivingEnergy ); - } - - status->tempDamage = damage; - - status->letTempJumpBe(jump); - status->letTempTractionBe(answer); - - + + //status->initTempStatus(); + + double g = compute_g(damage); + + FloatArrayF<3> answer; + answer.at(1) = g * k*jump.at(1); + answer.at(2) = g * k*jump.at(2); + + if ( jump.at(3) > 0.0 ) { // only degradation in tension + answer.at(3) = g * k*jump.at(3); + } else { + answer.at(3) = k*jump.at(3); + } + + double drivingEnergy = 0.5*k*jump.at(1)*jump.at(1) + 0.5*k*jump.at(2)*jump.at(2); + if ( jump.at(3) > 0.0 ) { + drivingEnergy += 0.5*k*jump.at(3)*jump.at(3); + } + if ( drivingEnergy > status->giveTempDrivingEnergy() ) { // max val + status->letTempDrivingEnergyBe( drivingEnergy ); + } + + status->tempDamage = damage; + + status->letTempJumpBe(jump); + status->letTempTractionBe(answer); + + return answer; } -void -IntMatPhaseField :: give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +IntMatPhaseField :: give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { IntMatPhaseFieldStatus *status = static_cast< IntMatPhaseFieldStatus * >( this->giveStatus(gp) ); - FloatArray jump; - jump = status->giveTempJump(); - + const auto &jump = status->giveTempJump(); + double damage = status->giveDamage(); double g = compute_g(damage); - - answer.resize(3, 3); - answer.zero(); + FloatMatrixF<3,3> answer; answer.at(1, 1) = g*k; answer.at(2, 2) = g*k; - + if ( jump.at(3) > 0.0 ) { // only degradation in tension answer.at(3,3) = g * k; } else { answer.at(3,3) = k; } - + return answer; } void -IntMatPhaseField :: giveTangents(FloatMatrix &Djj, FloatMatrix &Djd, FloatMatrix &Ddj, FloatMatrix &Ddd, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - +IntMatPhaseField :: giveTangents(FloatMatrix &Djj, FloatMatrix &Djd, FloatMatrix &Ddj, FloatMatrix &Ddd, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ IntMatPhaseFieldStatus *status = static_cast< IntMatPhaseFieldStatus * >( this->giveStatus(gp) ); - - FloatArray jump; - jump = status->giveTempJump(); - + + const auto &jump = status->giveTempJump(); + double damage = status->giveDamage(); double g = compute_g(damage); - + Djj.resize(3, 3); Djj.zero(); - Djj.at(1, 1) = g*k; Djj.at(2, 2) = g*k; - + if ( jump.at(3) > 0.0 ) { // only degradation in tension Djj.at(3,3) = g * k; } else { Djj.at(3,3) = k; } - + double gPrime = compute_gPrime(damage); Djd.at(1, 1) = gPrime*k * jump.at(1); Djd.at(2, 2) = gPrime*k * jump.at(1); @@ -160,34 +144,28 @@ IntMatPhaseField :: giveTangents(FloatMatrix &Djj, FloatMatrix &Djd, FloatMatrix } else { Djd.at(3,3) = 0; } - - + // Df/Dd, f= max[ g'*(psi_s+psi_n+) ] Ddj.beTranspositionOf(Djd); - //Ddd = { g''* } - - - - } -double -IntMatPhaseField :: giveDrivingForce(GaussPoint *gp) +double +IntMatPhaseField :: giveDrivingForce(GaussPoint *gp) const { IntMatPhaseFieldStatus *status = static_cast< IntMatPhaseFieldStatus * >( this->giveStatus(gp) ); double gPrime = compute_gPrime(status->giveDamage()); - - return gPrime / this->Gc * status->giveTempDrivingEnergy(); + + return gPrime / this->Gc * status->giveTempDrivingEnergy(); } -double -IntMatPhaseField :: giveDrivingForcePrime(GaussPoint *gp) +double +IntMatPhaseField :: giveDrivingForcePrime(GaussPoint *gp) const { IntMatPhaseFieldStatus *status = static_cast< IntMatPhaseFieldStatus * >( this->giveStatus(gp) ); double gBis = compute_gBis(status->giveDamage()); - - return gBis / this->Gc * status->giveTempDrivingEnergy(); + + return gBis / this->Gc * status->giveTempDrivingEnergy(); } @@ -207,7 +185,7 @@ IntMatPhaseField :: giveDrivingForcePrime(GaussPoint *gp) double -IntMatPhaseField :: compute_g(const double d) +IntMatPhaseField :: compute_g(double d) const { // computes g = (1-d)^2 + r0 double r0 = 1.0e-10; @@ -216,38 +194,30 @@ IntMatPhaseField :: compute_g(const double d) double -IntMatPhaseField :: compute_gPrime(const double d) +IntMatPhaseField :: compute_gPrime(double d) const { // compute Dg/Dd = -2*(1-d) return -2.0 * (1.0 - d); } double -IntMatPhaseField :: compute_gBis(const double d) +IntMatPhaseField :: compute_gBis(double d) const { // compute DDg/DDd = 2 return 2.0; } - - - - - - -IRResultType -IntMatPhaseField :: initializeFrom(InputRecord *ir) +void +IntMatPhaseField :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, this->k, _IFT_IntMatPhaseField_kn); IR_GIVE_FIELD(ir, this->Gc, _IFT_IntMatPhaseField_gc); StructuralInterfaceMaterial :: initializeFrom(ir); - return IRRT_OK; } + void IntMatPhaseField :: giveInputRecord(DynamicInputRecord &input) { StructuralInterfaceMaterial :: giveInputRecord(input); @@ -258,35 +228,27 @@ void IntMatPhaseField :: giveInputRecord(DynamicInputRecord &input) -IntMatPhaseFieldStatus :: IntMatPhaseFieldStatus(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g) +IntMatPhaseFieldStatus :: IntMatPhaseFieldStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) { - this->tempDrivingEnergy = 0.0; - this->drivingEnergy = 0.0; - this->tempDamage = 0.0; } - void IntMatPhaseFieldStatus :: initTempStatus() { - StructuralInterfaceMaterialStatus :: initTempStatus(); - this->tempDrivingEnergy = 0.0; this->drivingEnergy = 0.0; this->tempDamage = 0.0; } + void IntMatPhaseFieldStatus :: updateYourself(TimeStep *atTime) { - StructuralInterfaceMaterialStatus :: updateYourself(atTime); this->drivingEnergy = this->tempDrivingEnergy; - } - } /* namespace oofem */ diff --git a/src/sm/Materials/InterfaceMaterials/intmatphasefield.h b/src/sm/Materials/InterfaceMaterials/intmatphasefield.h index 9f4d3a8f7..730be80e3 100644 --- a/src/sm/Materials/InterfaceMaterials/intmatphasefield.h +++ b/src/sm/Materials/InterfaceMaterials/intmatphasefield.h @@ -31,11 +31,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* - * - * - * Author: Jim Brouzoulis - */ #ifndef intmatphasefield #define intmatphasefield @@ -50,75 +45,65 @@ #define _IFT_IntMatPhaseField_gc "gc" //@} - namespace oofem { /** * Development cz-model using phase field + * @author Jim Brouzoulis */ - - class IntMatPhaseFieldStatus : public StructuralInterfaceMaterialStatus { public: - IntMatPhaseFieldStatus(int n, Domain * d, GaussPoint * g); - virtual ~IntMatPhaseFieldStatus(){}; - + IntMatPhaseFieldStatus(GaussPoint * g); + /// damage variable - double tempDamage; - double giveDamage() { return tempDamage; } - - - double tempDrivingEnergy; - double drivingEnergy; - double giveTempDrivingEnergy() { return tempDrivingEnergy; } - double giveDrivingEnergy() { return drivingEnergy; } + double tempDamage = 0.; + double tempDrivingEnergy = 0.; + double drivingEnergy = 0.; + + double giveDamage() const override { return tempDamage; } + + double giveTempDrivingEnergy() const { return tempDrivingEnergy; } + double giveDrivingEnergy() const { return drivingEnergy; } void letTempDrivingEnergyBe(double val) { this->tempDrivingEnergy = val; } - - virtual const char *giveClassName() const { return "IntMatPhaseFieldStatus"; } - - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + const char *giveClassName() const override { return "IntMatPhaseFieldStatus"; } + + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; }; -class IntMatPhaseField : public StructuralInterfaceMaterialPhF{ +class IntMatPhaseField : public StructuralInterfaceMaterialPhF +{ +protected: + double k = 0.; + double Gc = 0.; + public: IntMatPhaseField(int n, Domain * d); - virtual ~IntMatPhaseField(); - virtual int hasNonLinearBehaviour() { return 1; } + bool hasMaterialModeCapability(MaterialMode mode) const override; + const char *giveClassName() const override { return "IntMatPhaseField"; } + const char *giveInputRecordName() const override { return _IFT_IntMatPhaseField_Name; } - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual const char *giveClassName() const { return "IntMatPhaseField"; } - virtual const char *giveInputRecordName() const { return _IFT_IntMatPhaseField_Name; } + FloatArrayF<3> giveEngTraction_3d(const FloatArrayF<3> &jump, double damage, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> give3dStiffnessMatrix_Eng(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + void giveTangents(FloatMatrix &jj, FloatMatrix &jd, FloatMatrix &dj, FloatMatrix &dd, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const double damage, TimeStep *tStep); - virtual void give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveTangents(FloatMatrix &jj, FloatMatrix &jd, FloatMatrix &dj, FloatMatrix &dd, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new IntMatPhaseFieldStatus(gp); }; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + bool hasAnalyticalTangentStiffness() const override { return true; }; - //virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new StructuralInterfaceMaterialStatus(1, domain, gp); } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new IntMatPhaseFieldStatus(1, domain, gp); }; - - virtual bool hasAnalyticalTangentStiffness() const { return true; }; - - - virtual double giveDrivingForce(GaussPoint *gp); - virtual double giveDrivingForcePrime(GaussPoint *gp); + double giveDrivingForce(GaussPoint *gp) const override; + double giveDrivingForcePrime(GaussPoint *gp) const override; //double compute_fPrime(const double d); - double compute_g(const double d); - double compute_gPrime(const double d); - double compute_gBis(const double d); - -protected: - double k; - double Gc; + double compute_g(double d) const; + double compute_gPrime(double d) const; + double compute_gBis(double d) const; }; } /* namespace oofem */ diff --git a/src/sm/Materials/InterfaceMaterials/linkslip.C b/src/sm/Materials/InterfaceMaterials/linkslip.C new file mode 100644 index 000000000..b17aac73c --- /dev/null +++ b/src/sm/Materials/InterfaceMaterials/linkslip.C @@ -0,0 +1,280 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "linkslip.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" +#include "engngm.h" +#include "mathfem.h" +#include "Elements/structuralelement.h" +#include "datastream.h" +#include "staggeredproblem.h" +#include "contextioerr.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(LinkSlip); + +/// constructor which creates a dummy material without a status and without random extension interface +LinkSlip::LinkSlip(int n, Domain *d) : StructuralInterfaceMaterial(n, d) +{} + + +void +LinkSlip::initializeFrom(InputRecord &ir) +{ + StructuralInterfaceMaterial::initializeFrom(ir); + ; + + //axial stiffness + IR_GIVE_FIELD(ir, kNormal, _IFT_LinkSlip_kn); // Macro + + //Ratio of lateral to axial stiffness + IR_GIVE_OPTIONAL_FIELD(ir, kLateral, _IFT_LinkSlip_kl); // Macro + + //Two models available + //0 default. Linear elastic-perfect plastic + //1 bond slip according first part of CEB model and then constant + //2 bond slip according to CEB model + IR_GIVE_OPTIONAL_FIELD(ir, type, _IFT_LinkSlip_type); // Macro + + IR_GIVE_FIELD(ir, tauMax, _IFT_LinkSlip_t0); // Macro + + if ( type == 1 || type == 2 ) { + IR_GIVE_FIELD(ir, s1, _IFT_LinkSlip_s1); + IR_GIVE_FIELD(ir, alpha, _IFT_LinkSlip_alpha); + } + + if ( type == 2 ) { + IR_GIVE_FIELD(ir, s2, _IFT_LinkSlip_s2); + IR_GIVE_FIELD(ir, s3, _IFT_LinkSlip_s3); + IR_GIVE_FIELD(ir, tauFinal, _IFT_LinkSlip_tf); + } + + if ( type == 1 || type == 2 ) { + if ( ( type == 1 || type == 2 ) && this->kNormal < this->tauMax / this->s1 ) { + this->kNormal = this->tauMax / this->s1; + OOFEM_WARNING("Parameter kN adjusted"); + } + } +} + + +MaterialStatus * +LinkSlip::CreateStatus(GaussPoint *gp) const +{ + return new LinkSlipStatus(gp); +} + +double +LinkSlip::evaluateBondStress(const double kappa) const +{ + if ( this->type == 0 ) { //elastic-perfectly plastic + return this->tauMax; + } else if ( this->type == 1 ) { //modified bond model + if ( kappa <= 0. ) { + return 0.; + } + if ( kappa <= s1 ) { + return tauMax * pow(kappa / s1, alpha); + } + return tauMax; + } else if ( this->type == 2 ) { + if ( kappa <= 0. ) { + return 0.; + } + if ( kappa <= s1 ) { + return tauMax * pow(kappa / s1, alpha); + } + if ( kappa <= s2 ) { + return tauMax; + } + if ( kappa <= s3 ) { + return tauMax - ( tauMax - tauFinal ) * ( kappa - s2 ) / ( s3 - s2 ); + } + return tauFinal; + } else { //unknown type + OOFEM_ERROR("Unknown bond model type. Type should be 0, 1 or 2."); + } + + return 0.; //Should not be here. +} + + +FloatArrayF< 3 > +LinkSlip::giveEngTraction_3d(const FloatArrayF< 3 > &jump, GaussPoint *gp, TimeStep *tStep) const +{ + auto status = static_cast< LinkSlipStatus * >( this->giveStatus(gp) ); + + //For axial (first) component, strain has the meanig of slip. Stress is traction. + + const auto &oldTraction = status->giveTraction(); + const auto &oldJump = status->giveJump(); + + //evaluate tempKappa (no elastic strain in axial direction) + double tempKappa = status->giveKappa() + fabs( jump.at(1) - oldJump.at(1) ); + + FloatArrayF< 3 >traction; + + //trial stress in axial direction + traction.at(1) = oldTraction.at(1) + ( jump.at(1) - oldJump.at(1) ) * this->kNormal; + + + double f = fabs( traction.at(1) ) - evaluateBondStress(tempKappa); + + if ( f > 0 ) { //plastic response. + //Reduced stress by increasing plastic strain. + traction.at(1) = evaluateBondStress(tempKappa); + ; + } + + //Compute the lateral stress components + for ( int i = 2; i <= 3; i++ ) { // only diagonal terms matter + traction.at(i) = this->kLateral * jump.at(i); + } + + //Set temp values in status needed for dissipation + status->letTempKappaBe(tempKappa); + status->letTempJumpBe(jump); + status->letTempTractionBe(traction); + + return traction; +} + +Interface * +LinkSlip::giveInterface(InterfaceType type) +{ + return nullptr; +} + +FloatMatrixF< 3, 3 > +LinkSlip::give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const +{ + return diag< 3 >({ this->kNormal, this->kLateral, this->kLateral }); +} + +LinkSlipStatus::LinkSlipStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) +{} + + +void +LinkSlipStatus::initTempStatus() +// +// initializes temp variables according to variables form previous equlibrium state. +// builds new crackMap +// +{ + StructuralInterfaceMaterialStatus::initTempStatus(); + this->tempKappa = this->kappa; +} + + +void +LinkSlipStatus::printOutputAt(FILE *file, TimeStep *tStep) const +{ + StructuralInterfaceMaterialStatus::printOutputAt(file, tStep); + fprintf(file, " jump "); + for ( auto &val : this->jump ) { + fprintf(file, " %.4e", val); + } + + fprintf(file, "\n traction "); + for ( auto &val : this->traction ) { + fprintf(file, " %.4e", val); + } + fprintf(file, "\n"); + + fprintf(file, "kappa %.8e\n", this->kappa); + return; +} + +void +LinkSlipStatus::saveContext(DataStream &stream, ContextMode mode) +{ + // save parent class status + + StructuralInterfaceMaterialStatus::saveContext(stream, mode); + + // write a raw data + if ( !stream.write(kappa) ) { + THROW_CIOERR(CIO_IOERR); + } +} + + +void +LinkSlipStatus::restoreContext(DataStream &stream, ContextMode mode) +{ + StructuralInterfaceMaterialStatus::restoreContext(stream, mode); + + // read raw data + if ( !stream.read(kappa) ) { + THROW_CIOERR(CIO_IOERR); + } +} + +void +LinkSlipStatus::updateYourself(TimeStep *atTime) +{ + StructuralInterfaceMaterialStatus::updateYourself(atTime); + this->kappa = this->tempKappa; +} + + +int +LinkSlip::giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) +{ + auto status = static_cast< LinkSlipStatus * >( this->giveStatus(gp) ); + if ( type == IST_InterfaceJump ) { + answer.resize(3); + answer.zero(); + answer = status->giveJump(); + return 1; + } else if ( type == IST_InterfaceTraction ) { + answer.resize(3); + answer.zero(); + answer = status->giveTraction(); + return 1; + } else { + return StructuralInterfaceMaterial::giveIPValue(answer, gp, type, atTime); + } +} +} diff --git a/src/sm/Materials/InterfaceMaterials/linkslip.h b/src/sm/Materials/InterfaceMaterials/linkslip.h new file mode 100644 index 000000000..2155e5519 --- /dev/null +++ b/src/sm/Materials/InterfaceMaterials/linkslip.h @@ -0,0 +1,157 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef linkslip_h +#define linkslip_h + +#include "structuralinterfacematerial.h" +#include "structuralinterfacematerialstatus.h" + +///@name Input fields for LinkSlip +//@{ +#define _IFT_LinkSlip_Name "linkslip" +#define _IFT_LinkSlip_talpha "talpha" +#define _IFT_LinkSlip_kn "kn" +#define _IFT_LinkSlip_kl "kl" +#define _IFT_LinkSlip_type "type" +#define _IFT_LinkSlip_t0 "t0" +#define _IFT_LinkSlip_s1 "s1" +#define _IFT_LinkSlip_s2 "s2" +#define _IFT_LinkSlip_s3 "s3" +#define _IFT_LinkSlip_tf "tf" +#define _IFT_LinkSlip_alpha "alpha" +//@} + +namespace oofem { +/** + * This class implements a constitutive model for a bond link for connecting beam or truss and continuum elements. + * The main idea is to use the displacement jump in the direction of the rebar element (and two components, which are perpendicular to each other and lie + * in a plane for which the direction along the rebar is normal to. + * This constitutive model differs from the standard bond model, because only the first component of the jump is used to determine the bond stress. + * + * @author: Peter Grassl + */ + + +class LinkSlipStatus : public StructuralInterfaceMaterialStatus +{ +protected: + + double kappa = 0; + + double tempKappa = 0; + +public: + + /// Constructor + LinkSlipStatus(GaussPoint *g); + + double giveKappa() { return this->kappa; } + + void letTempKappaBe(const double &v) + { this->tempKappa = v; } + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + const char *giveClassName() const override { return "LinkSlipStatus"; } + + void initTempStatus() override; + + void updateYourself(TimeStep *) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; +}; + +/** + * This class implements a slip model for concrete for lattice elements. + */ +class LinkSlip : public StructuralInterfaceMaterial + // +{ +protected: + + ///Normal modulus + double kNormal = 0.; + + ///Lateral modulus + double kLateral = 0.; + + int type = 0; + + ///Strength for slip component + double tauMax = 0., tauFinal = 0.; + + double s1 = 0., s2 = 0., s3 = 0.; + + double alpha = 0.; + +public: + + LinkSlip(int n, Domain *d); + + bool hasAnalyticalTangentStiffness() const override { return true; } + + const char *giveInputRecordName() const override { return _IFT_LinkSlip_Name; } + const char *giveClassName() const override { return "LinkSlip"; } + + void initializeFrom(InputRecord &ir) override; + + // virtual void computeStressIndependentStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *stepN, ValueModeType mode); + + // virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); // unused for interface materials + + + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + + double evaluateBondStress(const double kappa) const; + + FloatArrayF< 3 >giveEngTraction_3d(const FloatArrayF< 3 > &jump, GaussPoint *gp, TimeStep *tStep) const override; + + FloatMatrixF< 3, 3 >give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + + Interface *giveInterface(InterfaceType) override; + + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + int giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) override; +}; +} // end namespace oofem + +#endif diff --git a/src/sm/Materials/InterfaceMaterials/masonry02.C b/src/sm/Materials/InterfaceMaterials/masonry02.C index 90b660163..bc5fe42b0 100644 --- a/src/sm/Materials/InterfaceMaterials/masonry02.C +++ b/src/sm/Materials/InterfaceMaterials/masonry02.C @@ -33,7 +33,7 @@ */ #include "masonry02.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" @@ -46,9 +46,6 @@ REGISTER_Material(Masonry02); Masonry02 :: Masonry02(int n, Domain *d) : MPlasticMaterial2(n, d) { - // - // constructor - // linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); this->nsurf = 3; //this->rmType = mpm_CuttingPlane; @@ -56,11 +53,9 @@ Masonry02 :: Masonry02(int n, Domain *d) : MPlasticMaterial2(n, d) this->plType = nonassociatedPT; } -Masonry02 :: ~Masonry02() -{ } -int -Masonry02 :: hasMaterialModeCapability(MaterialMode mode) +bool +Masonry02 :: hasMaterialModeCapability(MaterialMode mode) const // // returns whether receiver supports given mode // @@ -68,16 +63,11 @@ Masonry02 :: hasMaterialModeCapability(MaterialMode mode) return mode == _2dInterface; } -IRResultType -Masonry02 :: initializeFrom(InputRecord *ir) +void +Masonry02 :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = MPlasticMaterial2 :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - - result = linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) return result; + MPlasticMaterial2 :: initializeFrom(ir); + linearElasticMaterial->initializeFrom(ir); IR_GIVE_FIELD(ir, ft0, _IFT_Masonry02_ft0); IR_GIVE_FIELD(ir, gfI, _IFT_Masonry02_gfi); @@ -103,17 +93,15 @@ Masonry02 :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, km, _IFT_Masonry02_km); IR_GIVE_FIELD(ir, kr, _IFT_Masonry02_kr); - if ( ir->hasField(_IFT_Masonry02_cplane) ) { + if ( ir.hasField(_IFT_Masonry02_cplane) ) { this->rmType = mpm_CuttingPlane; } - - return IRRT_OK; } double Masonry02 :: computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, - const FloatArray &strainSpaceHardeningVariables) + const FloatArray &strainSpaceHardeningVariables) const { if ( isurf == 1 ) { // tension mode @@ -157,7 +145,7 @@ Masonry02 :: computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &st void Masonry02 :: computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &strainSpaceHardeningVariables) + const FloatArray &strainSpaceHardeningVariables) const { answer.resize(2); answer.zero(); @@ -211,7 +199,7 @@ Masonry02 :: computeStressGradientVector(FloatArray &answer, functType ftype, in void Masonry02 :: computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &stress, const FloatArray &dlambda, - const FloatArray &dplasticStrain, const IntArray &activeConditionMap) + const FloatArray &dplasticStrain, const IntArray &activeConditionMap) const { double help = this->gfI * this->c0 / ( this->gfII * this->ft0 ); @@ -269,7 +257,7 @@ Masonry02 :: computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPo const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, - const FloatArray &dlambda) + const FloatArray &dlambda) const { // computes dk(i)/dLambda(j) int indx; @@ -345,7 +333,7 @@ Masonry02 :: computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPo void Masonry02 :: computeKGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, FloatArray &stressVector, - const FloatArray &strainSpaceHardeningVariables) + const FloatArray &strainSpaceHardeningVariables) const { answer.resize(3); @@ -401,7 +389,7 @@ void Masonry02 :: computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, GaussPoint *gp, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, - const FloatArray &dlambda) + const FloatArray &dlambda) const { // computes dk(i)/dsig(j) gradient matrix answer.resize(3, 2); @@ -423,7 +411,7 @@ Masonry02 :: computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, Gauss void Masonry02 :: computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables) + const FloatArray &strainSpaceHardeningVariables) const { // computes second derivatives of load fuction with respect to stresses gradientMatrix.resize(2, 2); @@ -437,7 +425,7 @@ Masonry02 :: computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int i, void Masonry02 :: computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &strainSpaceHardeningVariables) + const FloatArray &strainSpaceHardeningVariables) const { // computes mixed derivative of load function with respect to stress and hardening variables gradientMatrix.resize(2, 3); @@ -474,7 +462,7 @@ Masonry02 :: computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int i, MaterialStatus * Masonry02 :: CreateStatus(GaussPoint *gp) const { - return new MPlasticMaterial2Status(1, this->giveDomain(), gp, this->giveSizeOfReducedHardeningVarsVector(gp)); + return new MPlasticMaterial2Status(gp, this->giveSizeOfReducedHardeningVarsVector(gp)); /* * // introduce initial pre-softening (using strainSpaceHardeningVarsVector) to * // avoid problems with undefined hardening moduli. @@ -514,9 +502,9 @@ Masonry02 :: give2dInterfaceMaterialStiffnessMatrix(FloatMatrix &answer, MatResp { if ( mode == TangentStiffness ) { if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + answer = this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + answer = this->giveElastoPlasticStiffnessMatrix(mode, gp, tStep); } } else { this->computeReducedElasticModuli(answer, gp, tStep); @@ -527,7 +515,7 @@ Masonry02 :: give2dInterfaceMaterialStiffnessMatrix(FloatMatrix &answer, MatResp void Masonry02 :: computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { /* Returns elastic moduli in reduced stress-strain space*/ MaterialMode mode = gp->giveMaterialMode(); if ( mode == _2dInterface ) { @@ -536,7 +524,7 @@ Masonry02 :: computeReducedElasticModuli(FloatMatrix &answer, answer.at(2, 2) = ks; answer.at(1, 2) = answer.at(2, 1) = 0.0; } else { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); + this->linearElasticMaterial->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); } } @@ -552,7 +540,7 @@ Masonry02 :: computeReducedElasticModuli(FloatMatrix &answer, */ double -Masonry02 :: computeF3HardeningLaw(double k) +Masonry02 :: computeF3HardeningLaw(double k) const { // ideal case @@ -595,7 +583,7 @@ Masonry02 :: computeF3HardeningLaw(double k) } double -Masonry02 :: computeF3HardeningGradient(double k) +Masonry02 :: computeF3HardeningGradient(double k) const { // use secant stiffness if ( k < 0. ) { diff --git a/src/sm/Materials/InterfaceMaterials/masonry02.h b/src/sm/Materials/InterfaceMaterials/masonry02.h index e2e128486..cd0bc8945 100644 --- a/src/sm/Materials/InterfaceMaterials/masonry02.h +++ b/src/sm/Materials/InterfaceMaterials/masonry02.h @@ -35,7 +35,7 @@ #ifndef masonry02_h #define masonry02_h -#include "Materials/ConcreteMaterials/mplasticmaterial2.h" +#include "sm/Materials/ConcreteMaterials/mplasticmaterial2.h" ///@name Input fields for Masonry02 //@{ @@ -76,98 +76,95 @@ class Masonry02 : public MPlasticMaterial2 { protected: /// Tensile strength. - double ft0; + double ft0 = 0.; /// Mode I GF. - double gfI; + double gfI = 0.; /// Mode II GF. - double gfII; + double gfII = 0.; /// Residual friction angle. - double tanfir; + double tanfir = 0.; /// Initial friction angle. - double tanfi0; + double tanfi0 = 0.; /// Initial cohesion of joint. - double c0; + double c0 = 0.; /// Cap mode parameters. - double Cnn, Css, Cn; - // double fm; + double Cnn = 0., Css = 0., Cn = 0.; + // double fm = 0.; /// Elastic properties. - double kn, ks; + double kn = 0., ks = 0.; /// Dilatancy angle. - double tanpsi; + double tanpsi = 0.; /// Cap mode parameters. - double sic, spc, smc, src; - double kp, km, kr; -public: + double sic = 0., spc = 0., smc = 0., src = 0.; + double kp = 0., km = 0., kr = 0.; +public: Masonry02(int n, Domain * d); - virtual ~Masonry02(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int hasMaterialModeCapability(MaterialMode mode); + void initializeFrom(InputRecord &ir) override; + bool hasMaterialModeCapability(MaterialMode mode) const override; - virtual const char *giveInputRecordName() const { return _IFT_Masonry02_Name; } - virtual const char *giveClassName() const { return "Masonry02"; } + const char *giveInputRecordName() const override { return _IFT_Masonry02_Name; } + const char *giveClassName() const override { return "Masonry02"; } - virtual void giveStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + void giveStiffnessMatrix(FloatMatrix &answer, + MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) override; - virtual int giveSizeOfFullHardeningVarsVector() { return 3; } - virtual int giveSizeOfReducedHardeningVarsVector(GaussPoint *) const { return 3; } + int giveSizeOfFullHardeningVarsVector() const override { return 3; } + int giveSizeOfReducedHardeningVarsVector(GaussPoint *) const override { return 3; } - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: - virtual int giveMaxNumberOfActiveYieldConds(GaussPoint *gp) { return 2; } + int giveMaxNumberOfActiveYieldConds(GaussPoint *gp) const override { return 2; } // // yield(YC-like functions) and loading(LC-like functions) criteria specific section // - virtual double computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars); - - virtual void computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars); - virtual void computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, - const FloatArray &stress, const FloatArray &dlambda, - const FloatArray &dplasticStrain, const IntArray &activeConditionMap); - virtual void computeKGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables); - - virtual void computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, GaussPoint *gp, const IntArray &activeConditionMap, - const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVars, - const FloatArray &gamma); - virtual void computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPoint *gp, int actSurf, - const IntArray &activeConditionMap, - const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVars, - const FloatArray &gamma); - virtual int hasHardening() { return 1; } - - virtual void computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables); - virtual void computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables); + double computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, + const FloatArray &stressSpaceHardeningVars) const override; + + void computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, + const FloatArray &stressSpaceHardeningVars) const override; + void computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, + const FloatArray &stress, const FloatArray &dlambda, + const FloatArray &dplasticStrain, const IntArray &activeConditionMap) const override; + void computeKGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, FloatArray &fullStressVector, + const FloatArray &strainSpaceHardeningVariables) const override; + + void computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, GaussPoint *gp, const IntArray &activeConditionMap, + const FloatArray &fullStressVector, + const FloatArray &strainSpaceHardeningVars, + const FloatArray &gamma) const override; + void computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPoint *gp, int actSurf, + const IntArray &activeConditionMap, + const FloatArray &fullStressVector, + const FloatArray &strainSpaceHardeningVars, + const FloatArray &gamma) const override; + int hasHardening() const override { return 1; } + + void computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, + const FloatArray &strainSpaceHardeningVariables) const override; + void computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, + const FloatArray &strainSpaceHardeningVariables) const override; void give2dInterfaceMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep); - + void computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) const override; /// Cap mode related functions. - double computeF3HardeningLaw(double k); - double computeF3HardeningGradient(double k); + double computeF3HardeningLaw(double k) const; + double computeF3HardeningGradient(double k) const; }; } // end namespace oofem #endif // masonry02_h diff --git a/src/sm/Materials/InterfaceMaterials/mat_cebfip90.C b/src/sm/Materials/InterfaceMaterials/mat_cebfip90.C index 95c43ebfa..f60840f74 100644 --- a/src/sm/Materials/InterfaceMaterials/mat_cebfip90.C +++ b/src/sm/Materials/InterfaceMaterials/mat_cebfip90.C @@ -49,20 +49,15 @@ CebFipSlip90Material :: CebFipSlip90Material(int n, Domain *d) : StructuralInter { } -CebFipSlip90Material :: ~CebFipSlip90Material() -{ } - - -void -CebFipSlip90Material :: giveEngTraction_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) +double +CebFipSlip90Material :: giveEngTraction_1d(double jump, GaussPoint *gp, TimeStep *tStep) const { CebFipSlip90MaterialStatus *status = static_cast< CebFipSlip90MaterialStatus * >( this->giveStatus(gp) ); - double f, slip, tempKappa; - - slip = jump.at(1); + double slip = jump; ///@todo This isn't slip, this is the normal displacement. This code should be rewritten to deal with a 3D jump. // compute value of loading function if strainLevel crit apply - f = fabs(slip) - status->giveKappa(); + double f = fabs(slip) - status->giveKappa(); + double tempKappa; if ( f <= 0.0 ) { // kappa do not grow tempKappa = status->giveKappa(); @@ -72,25 +67,25 @@ CebFipSlip90Material :: giveEngTraction_1d(FloatArray &answer, GaussPoint *gp, c // evaluate damage parameter } - answer.resize(1); - if ( tempKappa <= 1.e-12 ) { - answer.at(1) = 0.0; - } else { - answer.at(1) = ( this->computeBondForce(tempKappa) / tempKappa ) * slip; + double answer = 0.0; + if ( tempKappa > 1.e-12 ) { + answer = ( this->computeBondForce(tempKappa) / tempKappa ) * slip; } // update gp - status->letTempJumpBe(jump); - status->letTempTractionBe(answer); + status->letTempJumpBe({jump, 0., 0.}); + status->letTempTractionBe({answer, 0., 0.}); status->setTempKappa(tempKappa); + + return answer; } -void -CebFipSlip90Material :: give1dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<1,1> +CebFipSlip90Material :: give1dStiffnessMatrix_Eng(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { CebFipSlip90MaterialStatus *status = static_cast< CebFipSlip90MaterialStatus * >( this->giveStatus(gp) ); - answer.resize(1, 1); + FloatMatrixF<1,1> answer; if ( mode == ElasticStiffness || mode == SecantStiffness ) { double kappa = status->giveKappa(); @@ -105,6 +100,7 @@ CebFipSlip90Material :: give1dStiffnessMatrix_Eng(FloatMatrix &answer, MatRespo } else { OOFEM_ERROR("unknown MatResponseMode (%s)", __MatResponseModeToString(mode) ); } + return answer; } @@ -113,7 +109,7 @@ CebFipSlip90Material :: giveIPValue(FloatArray &answer, GaussPoint *gp, Internal { CebFipSlip90MaterialStatus *status = static_cast< CebFipSlip90MaterialStatus * >( this->giveStatus(gp) ); - if ( type == IST_DamageScalar ) { + if ( type == IST_DamageScalar ) { answer.resize(1); answer.at(1) = status->giveKappa(); return 1; @@ -123,10 +119,10 @@ CebFipSlip90Material :: giveIPValue(FloatArray &answer, GaussPoint *gp, Internal } -IRResultType -CebFipSlip90Material :: initializeFrom(InputRecord *ir) +void +CebFipSlip90Material :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralInterfaceMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, tmax, _IFT_CebFipSlip90Material_tmax); IR_GIVE_FIELD(ir, tres, _IFT_CebFipSlip90Material_tres); @@ -136,7 +132,6 @@ CebFipSlip90Material :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, s3, _IFT_CebFipSlip90Material_s3); alpha = 0.4; - return StructuralInterfaceMaterial :: initializeFrom(ir); } @@ -155,7 +150,7 @@ CebFipSlip90Material :: giveInputRecord(DynamicInputRecord &input) double -CebFipSlip90Material :: computeBondForce(double s) +CebFipSlip90Material :: computeBondForce(double s) const { if ( s <= s1 ) { return tmax *pow( ( s / s1 ), alpha ); @@ -170,7 +165,7 @@ CebFipSlip90Material :: computeBondForce(double s) double -CebFipSlip90Material :: computeBondForceStiffness(double s) +CebFipSlip90Material :: computeBondForceStiffness(double s) const { if ( s <= s1 / 1000. ) { s = s1 / 1000.; @@ -187,18 +182,12 @@ CebFipSlip90Material :: computeBondForceStiffness(double s) } -CebFipSlip90MaterialStatus :: CebFipSlip90MaterialStatus(int n, Domain *d, GaussPoint *g) : StructuralInterfaceMaterialStatus(n, d, g) -{ - kappa = tempKappa = 0.0; -} - - -CebFipSlip90MaterialStatus :: ~CebFipSlip90MaterialStatus() -{ } +CebFipSlip90MaterialStatus :: CebFipSlip90MaterialStatus(GaussPoint *g) : StructuralInterfaceMaterialStatus(g) +{} void -CebFipSlip90MaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +CebFipSlip90MaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralInterfaceMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -224,40 +213,24 @@ CebFipSlip90MaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -CebFipSlip90MaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +CebFipSlip90MaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralInterfaceMaterialStatus :: saveContext(stream, mode); - // write a raw data if ( !stream.write(kappa) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -CebFipSlip90MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +CebFipSlip90MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralInterfaceMaterialStatus :: restoreContext(stream, mode); - // read parent class status - if ( ( iores = StructuralInterfaceMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data if ( !stream.read(kappa) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/Materials/InterfaceMaterials/mat_cebfip90.h b/src/sm/Materials/InterfaceMaterials/mat_cebfip90.h index 6e47723df..bfdfd5769 100644 --- a/src/sm/Materials/InterfaceMaterials/mat_cebfip90.h +++ b/src/sm/Materials/InterfaceMaterials/mat_cebfip90.h @@ -58,33 +58,30 @@ class CebFipSlip90MaterialStatus : public StructuralInterfaceMaterialStatus { protected: /// Scalar measure of the largest slip reached in material. - double kappa; + double kappa = 0.; /// Non-equilibrated scalar of the largest slip displacement. - double tempKappa; + double tempKappa = 0.; public: /// Constructor. - CebFipSlip90MaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor. - virtual ~CebFipSlip90MaterialStatus(); + CebFipSlip90MaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; /// Returns the last equilibrated scalar measure of the largest strain level. - double giveKappa() { return kappa; } + double giveKappa() const { return kappa; } /// Returns the temp. scalar measure of the largest strain level. - double giveTempKappa() { return tempKappa; } + double giveTempKappa() const { return tempKappa; } /// Sets the temp scalar measure of the largest strain level to given value. void setTempKappa(double newKappa) { tempKappa = newKappa; } - // definition - virtual const char *giveClassName() const { return "CebFipSlip90MaterialStatus"; } + const char *giveClassName() const override { return "CebFipSlip90MaterialStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -98,52 +95,47 @@ class CebFipSlip90Material : public StructuralInterfaceMaterial { protected: /// Max force (stress). - double tmax; + double tmax = 0.; /// Slip valu at begining of yield plateau. - double s1; + double s1 = 0.; /// Slip at end of plateau. - double s2; + double s2 = 0.; /// Slip when residual force/stress activated. - double s3; + double s3 = 0.; /// Residual force/stress. - double tres; + double tres = 0.; /// Alpha coeff. - double alpha; + double alpha = 0.; public: /// Constructor CebFipSlip90Material(int n, Domain * d); - /// Destructor - virtual ~CebFipSlip90Material(); - virtual int hasNonLinearBehaviour() { return 1; } + const char *giveInputRecordName() const override { return _IFT_CebFipSlip90Material_Name; } + const char *giveClassName() const override { return "CebFipSlip90Material"; } - virtual const char *giveInputRecordName() const { return _IFT_CebFipSlip90Material_Name; } - virtual const char *giveClassName() const { return "CebFipSlip90Material"; } + double giveEngTraction_1d(double jump, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<1,1> give1dStiffnessMatrix_Eng(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveEngTraction_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); - virtual void give1dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - - virtual bool hasAnalyticalTangentStiffness() const { return true; } + bool hasAnalyticalTangentStiffness() const override { return true; } /** * Computes the value of bond force/stress, based on given value of slip value. * @param kappa Slip value. */ - double computeBondForce(double kappa); + double computeBondForce(double kappa) const; /** * Computes the value of bond force/stress stiffness, based on given value of slip value. * @param kappa Slip value. */ - double computeBondForceStiffness(double kappa); - - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + double computeBondForceStiffness(double kappa) const; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new CebFipSlip90MaterialStatus(1, domain, gp); } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new CebFipSlip90MaterialStatus(gp); } }; } // end namespace oofem #endif // mat_cebfip90_h diff --git a/src/sm/Materials/InterfaceMaterials/structuralinterfacematerial.C b/src/sm/Materials/InterfaceMaterials/structuralinterfacematerial.C index 4b9d91b7f..04902ef84 100644 --- a/src/sm/Materials/InterfaceMaterials/structuralinterfacematerial.C +++ b/src/sm/Materials/InterfaceMaterials/structuralinterfacematerial.C @@ -50,37 +50,33 @@ StructuralInterfaceMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, I StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus(gp) ); if ( type == IST_InterfaceJump ) { answer = status->giveJump(); - answer.resizeWithValues(3); // In case some model is not storing all components. return 1; } else if ( type == IST_InterfaceTraction ) { answer = status->giveTraction(); - answer.resizeWithValues(3); return 1; } else if ( type == IST_InterfaceFirstPKTraction ) { answer = status->giveFirstPKTraction(); - answer = status->giveTempFirstPKTraction(); - answer.resizeWithValues(3); return 1; } else if ( type == IST_DeformationGradientTensor ) { - answer.beVectorForm( status->giveF() ); + answer = to_voigt_form( status->giveF() ); return 1; } else if ( type == IST_InterfaceNormal ) { answer = status->giveNormal(); return 1; + } else if ( type == IST_DamageScalar ) { + answer.resize(1); + answer.at(1) = status->giveDamage(); + return 1; } else { return Material :: giveIPValue(answer, gp, type, tStep); } } -IRResultType -StructuralInterfaceMaterial :: initializeFrom(InputRecord *ir) +void +StructuralInterfaceMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_OPTIONAL_FIELD(ir, this->useNumericalTangent, _IFT_StructuralInterfaceMaterial_useNumericalTangent); - - return IRRT_OK; } @@ -91,60 +87,19 @@ StructuralInterfaceMaterial :: giveInputRecord(DynamicInputRecord &input) } -#if 0 -void -StructuralInterfaceMaterial :: giveStiffnessMatrix_dTdj_Num(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<1,1> +StructuralInterfaceMaterial :: give1dStiffnessMatrix_Eng(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - // Default implementation for computation of the numerical tangent - // Computes the material stiffness using a central difference method - - StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus(gp) ); - if ( status ) { - FloatMatrix F; - F = status->giveTempF(); - int dim = F.giveNumberOfRows(); - answer.resize(dim, dim); - answer.zero(); - const double eps = 1.0e-9; - FloatArray T, TPlus, TMinus; - - FloatArray jump, jumpPlus, jumpMinus, Kcolumn; - jump = status->giveTempJump(); - for ( int i = 1; i <= dim; i++ ) { - jumpPlus = jumpMinus = jump; - jumpPlus.at(i) += eps; - jumpMinus.at(i) -= eps; - this->giveFirstPKTraction_3d(TPlus, gp, jumpPlus, F, tStep); - this->giveFirstPKTraction_3d(TMinus, gp, jumpMinus, F, tStep); - - Kcolumn = ( TPlus - TMinus ); - answer.setColumn(Kcolumn, i); - } - answer.times( 1.0 / ( 2 * eps ) ); - this->giveFirstPKTraction_3d(T, gp, jump, F, tStep); // reset temp values by recomputing the stress - } + auto d = give3dStiffnessMatrix_Eng(mode, gp, tStep); + return {d(0,0)}; } -#endif -void -StructuralInterfaceMaterial :: give1dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<2,2> +StructuralInterfaceMaterial :: give2dStiffnessMatrix_Eng(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix answer3D; - give3dStiffnessMatrix_Eng(answer3D, mode, gp, tStep); - answer.resize(1, 1); - answer.at(1, 1) = answer3D.at(1, 1); -} - - -void -StructuralInterfaceMaterial :: give2dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - FloatMatrix answer3D; - give3dStiffnessMatrix_Eng(answer3D, mode, gp, tStep); - IntArray mask = {1, 2}; - answer.beSubMatrixOf(answer3D, mask, mask); - + auto d = give3dStiffnessMatrix_Eng(mode, gp, tStep); + return d({0,1}, {0,1}); #if 0 answer3D.printYourself("analytical tangent"); @@ -159,281 +114,223 @@ StructuralInterfaceMaterial :: give2dStiffnessMatrix_Eng(FloatMatrix &answer, Ma #endif } -void -StructuralInterfaceMaterial :: give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +StructuralInterfaceMaterial :: give3dStiffnessMatrix_Eng(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { // Default implementation. Will use large deformation dT/dj as stiffness - give3dStiffnessMatrix_dTdj(answer, mode, gp, tStep); + return give3dStiffnessMatrix_dTdj(mode, gp, tStep); } -void -StructuralInterfaceMaterial :: give1dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<1,1> +StructuralInterfaceMaterial :: give1dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - this->give3dStiffnessMatrix_dTdj_Num(answer, gp, tStep); - answer.resize(1, 1); - answer.at(1, 1) = answer.at(1, 1); + auto d = this->give3dStiffnessMatrix_dTdj_Num(gp, tStep); + return {d(0,0)}; } -void -StructuralInterfaceMaterial :: give2dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<2,2> +StructuralInterfaceMaterial :: give2dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - this->give3dStiffnessMatrix_dTdj_Num(answer, gp, tStep); - answer.resize(2, 2); -// answer.at(1, 1) = answer.at(1, 1); -// answer.at(1, 2) = answer.at(1, 3); -// answer.at(2, 1) = answer.at(3, 1); -// answer.at(2, 2) = answer.at(3, 3); + auto d = this->give3dStiffnessMatrix_dTdj_Num(gp, tStep); + return d({0,1}, {0,1}); } - -void -StructuralInterfaceMaterial :: give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +StructuralInterfaceMaterial :: give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const { - this->give3dStiffnessMatrix_dTdj_Num(answer, gp, tStep); OOFEM_WARNING("Using numerical tangent"); + return this->give3dStiffnessMatrix_dTdj_Num(gp, tStep); } -void -StructuralInterfaceMaterial :: giveFirstPKTraction_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &reducedF, TimeStep *tStep) +double +StructuralInterfaceMaterial :: giveFirstPKTraction_1d(double jump, double reducedF, GaussPoint *gp, TimeStep *tStep) const { - FloatArray traction3D; - FloatMatrix F(3, 3); - F.at(1, 1) = reducedF.at(1, 1); - F.at(2, 2) = 1.; - F.at(3, 3) = 1.; - - this->giveFirstPKTraction_3d(traction3D, gp, { jump.at(1), 0., 0. }, F, tStep); - answer = FloatArray{ traction3D.at(1) }; + return this->giveFirstPKTraction_3d({ jump, 0., 0. }, diag<3>({reducedF, 1., 1.}), gp, tStep).at(1); } -void -StructuralInterfaceMaterial :: giveFirstPKTraction_2d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &reducedF, TimeStep *tStep) +FloatArrayF<2> +StructuralInterfaceMaterial :: giveFirstPKTraction_2d(const FloatArrayF<2> &jump, const FloatMatrixF<2,2> &reducedF, GaussPoint *gp, TimeStep *tStep) const { - FloatArray traction3D; - FloatMatrix F(3, 3); -// F.at(1, 1) = reducedF.at(1, 1); -// F.at(1, 3) = reducedF.at(1, 2); -// F.at(2, 2) = 1.; -// F.at(3, 1) = reducedF.at(2, 1); -// F.at(3, 3) = reducedF.at(2, 2); - F.at(1, 1) = reducedF.at(1, 1); - F.at(1, 2) = reducedF.at(1, 2); - F.at(2, 1) = reducedF.at(2, 1); - F.at(2, 2) = reducedF.at(2, 2); - F.at(3, 3) = 1.; - - //this->giveFirstPKTraction_3d(traction3D, gp, { jump.at(1), 0., jump.at(2) }, F, tStep); - this->giveFirstPKTraction_3d(traction3D, gp, { jump.at(1), jump.at(2), 0. }, F, tStep); - answer = { traction3D.at(1), traction3D.at(2) }; + FloatMatrixF<3,3> F = { + reducedF(0,0), reducedF(1,0), 0., + reducedF(0,1), reducedF(1,1), 0., + 0., 0., 1. + }; + + auto traction3D = this->giveFirstPKTraction_3d({ jump.at(1), jump.at(2), 0. }, F, gp, tStep); + return { traction3D.at(1), traction3D.at(2) }; } -void -StructuralInterfaceMaterial :: giveEngTraction_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) +double +StructuralInterfaceMaterial :: giveEngTraction_1d(double jump, GaussPoint *gp, TimeStep *tStep) const { - FloatArray traction3D; - this->giveEngTraction_3d(traction3D, gp, { jump.at(1), 0., 0.}, tStep); - answer = FloatArray{ traction3D.at(1) }; + auto traction3D = this->giveEngTraction_3d({ jump, 0., 0.}, gp, tStep); + return traction3D.at(1); } -void -StructuralInterfaceMaterial :: giveEngTraction_2d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) +FloatArrayF<2> +StructuralInterfaceMaterial :: giveEngTraction_2d(const FloatArrayF<2> &jump, GaussPoint *gp, TimeStep *tStep) const { - FloatArray traction3D; - //this->giveEngTraction_3d(traction3D, gp, { jump.at(1), 0.0, jump.at(2) }, tStep); - this->giveEngTraction_3d(traction3D, gp, { jump.at(1), jump.at(2), 0. }, tStep); - answer = { traction3D.at(1), traction3D.at(2) }; + auto traction3D = this->giveEngTraction_3d({ jump.at(1), jump.at(2), 0. }, gp, tStep); + return { traction3D.at(1), traction3D.at(2) }; } -void -StructuralInterfaceMaterial :: giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep) +FloatArrayF<3> +StructuralInterfaceMaterial :: giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const { // Default implementation calls first PK version with F = I - FloatMatrix F(3, 3); - F.beUnitMatrix(); - giveFirstPKTraction_3d(answer, gp, jump, F, tStep); + return giveFirstPKTraction_3d(jump, eye<3>(), gp, tStep); } // Numerical tangents -void -StructuralInterfaceMaterial :: give1dStiffnessMatrix_dTdj_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<1,1> +StructuralInterfaceMaterial :: give1dStiffnessMatrix_dTdj_Num(GaussPoint *gp, TimeStep *tStep) const { // Default implementation for computation of the numerical tangent // Computes the material stiffness using a central difference method StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus( gp ) ); double eps = 1.0e-9; - const FloatMatrix &F = status->giveTempF(); - FloatArray T, TPlus, TMinus; - FloatArray jumpPlus, jumpMinus, Kcolumn; - FloatArray jump = FloatArray{status->giveTempJump().at(3)}; - int dim = jump.giveSize(); - answer.resize( dim, dim ); - - for ( int i = 1; i <= dim; i++ ) { - jumpPlus = jumpMinus = jump; - jumpPlus.at( i ) += eps; - jumpMinus.at( i ) -= eps; - this->giveFirstPKTraction_1d( TPlus, gp, jumpPlus, F, tStep ); - this->giveFirstPKTraction_1d( TMinus, gp, jumpMinus, F, tStep ); + double F = status->giveTempF().at(1,1); + double jump = status->giveTempJump().at(3); - Kcolumn.beDifferenceOf(TPlus, TMinus); - answer.setColumn( Kcolumn, i ); - } - answer.times( 1.0 / ( 2 * eps ) ); - this->giveFirstPKTraction_1d(T, gp, jump, F, tStep); // reset temp values by recomputing the stress + double tPlus = this->giveFirstPKTraction_1d( jump + eps, F, gp, tStep ); + double tMinus = this->giveFirstPKTraction_1d( jump - eps, F, gp, tStep ); + + this->giveFirstPKTraction_1d(jump, F, gp, tStep); // reset temp values by recomputing the stress + return (tPlus - tMinus) / ( 2 * eps ); } -void -StructuralInterfaceMaterial :: give2dStiffnessMatrix_dTdj_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<2,2> +StructuralInterfaceMaterial :: give2dStiffnessMatrix_dTdj_Num(GaussPoint *gp, TimeStep *tStep) const { // Default implementation for computation of the numerical tangent // Computes the material stiffness using a central difference method StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus( gp ) ); double eps = 1.0e-9; - const FloatMatrix &F = status->giveTempF(); - FloatArray T, TPlus, TMinus; - FloatArray jumpPlus, jumpMinus, Kcolumn; - FloatArray jump = {status->giveTempJump().at(1), status->giveTempJump().at(2)}; - int dim = jump.giveSize(); - answer.resize( dim, dim ); - - for ( int i = 1; i <= dim; i++ ) { - jumpPlus = jumpMinus = jump; + const auto &F3 = status->giveTempF(); + FloatMatrixF<2,2> F = {F3(0,0), F3(1,0), F3(0,1), F3(1,1)}; + FloatArrayF<2> jump = { status->giveTempJump().at(1), status->giveTempJump().at(2) }; + + FloatMatrixF<2,2> answer; + for ( int i = 1; i <= 2; i++ ) { + auto jumpPlus = jump; + auto jumpMinus = jump; jumpPlus.at( i ) += eps; jumpMinus.at( i ) -= eps; - this->giveFirstPKTraction_2d(TPlus, gp, jumpPlus, F, tStep); - this->giveFirstPKTraction_2d(TMinus, gp, jumpMinus, F, tStep); + auto TPlus = this->giveFirstPKTraction_2d(jumpPlus, F, gp, tStep); + auto TMinus = this->giveFirstPKTraction_2d(jumpMinus, F, gp, tStep); - Kcolumn.beDifferenceOf(TPlus, TMinus); + auto Kcolumn = TPlus - TMinus; answer.setColumn(Kcolumn, i); } - answer.times( 1.0 / ( 2 * eps ) ); - this->giveFirstPKTraction_2d(T, gp, jump, F, tStep); // reset temp values by recomputing the stress + answer *= 1.0 / ( 2 * eps ); + this->giveFirstPKTraction_2d(jump, F, gp, tStep); // reset temp values by recomputing the stress + return answer; } -void -StructuralInterfaceMaterial :: give3dStiffnessMatrix_dTdj_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +StructuralInterfaceMaterial :: give3dStiffnessMatrix_dTdj_Num(GaussPoint *gp, TimeStep *tStep) const { // Default implementation for computation of the numerical tangent // Computes the material stiffness using a central difference method - StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus( gp ) ); double eps = 1.0e-9; - const FloatMatrix &F = status->giveTempF(); - FloatArray T, TPlus, TMinus; - FloatArray jumpPlus, jumpMinus, Kcolumn; - const FloatArray &jump = status->giveTempJump(); - int dim = jump.giveSize(); - answer.resize( dim, dim ); - - for(int i = 1; i <= dim; i++) { - jumpPlus = jumpMinus = jump; + const auto &F = status->giveTempF(); + const auto &jump = status->giveTempJump(); + + FloatMatrixF<3,3> answer; + for(int i = 1; i <= 3; i++) { + auto jumpPlus = jump; + auto jumpMinus = jump; jumpPlus.at( i ) += eps; jumpMinus.at( i ) -= eps; - this->giveFirstPKTraction_3d( TPlus, gp, jumpPlus, F, tStep ); - this->giveFirstPKTraction_3d( TMinus, gp, jumpMinus, F, tStep ); + auto TPlus = this->giveFirstPKTraction_3d(jumpPlus, F, gp, tStep ); + auto TMinus = this->giveFirstPKTraction_3d(jumpMinus, F, gp, tStep ); - Kcolumn.beDifferenceOf(TPlus, TMinus); + auto Kcolumn = TPlus - TMinus; answer.setColumn(Kcolumn, i); } - answer.times( 1.0 / ( 2 * eps ) ); - this->giveFirstPKTraction_3d(T, gp, jump, F, tStep); // reset temp values by recomputing the stress + answer *= 1.0 / ( 2 * eps ); + this->giveFirstPKTraction_3d(jump, F, gp, tStep); // reset temp values by recomputing the stress + return answer; } -void -StructuralInterfaceMaterial :: give1dStiffnessMatrix_Eng_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<1,1> +StructuralInterfaceMaterial :: give1dStiffnessMatrix_Eng_Num(GaussPoint *gp, TimeStep *tStep) const { // Default implementation for computation of the numerical tangent d(sig)/d(jump) // Computes the material stiffness using a central difference method - StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus( gp ) ); double eps = 1.0e-9; - FloatArray t, tPlus, tMinus; - FloatArray jumpPlus, jumpMinus, Kcolumn; - FloatArray jump = FloatArray{status->giveTempJump().at(1)}; - int dim = jump.giveSize(); - answer.resize( dim, dim ); - answer.zero(); - - for(int i = 1; i <= dim; i++) { - jumpPlus = jumpMinus = jump; - jumpPlus.at( i ) += eps; - jumpMinus.at( i ) -= eps; - this->giveEngTraction_1d(tPlus, gp, jumpPlus, tStep); - this->giveEngTraction_1d(tMinus, gp, jumpMinus, tStep); + double jump = status->giveTempJump().at(1); - Kcolumn.beDifferenceOf(tPlus, tMinus); - answer.setColumn(Kcolumn, i); - } - answer.times( 1.0 / ( 2 * eps ) ); - this->giveEngTraction_1d( t, gp, jump, tStep ); // reset temp values by recomputing the stress + auto tPlus = this->giveEngTraction_1d(jump + eps, gp, tStep); + auto tMinus = this->giveEngTraction_1d(jump - eps, gp, tStep); + + this->giveEngTraction_1d( jump, gp, tStep ); // reset temp values by recomputing the stress + return (tPlus - tMinus) / ( 2 * eps ); } -void -StructuralInterfaceMaterial :: give2dStiffnessMatrix_Eng_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<2,2> +StructuralInterfaceMaterial :: give2dStiffnessMatrix_Eng_Num(GaussPoint *gp, TimeStep *tStep) const { // Default implementation for computation of the numerical tangent d(sig)/d(jump) // Computes the material stiffness using a central difference method StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus( gp ) ); double eps = 1.0e-12; - FloatArray t, tPlus, tMinus; - FloatArray tempJump, jumpPlus, jumpMinus, Kcolumn; - FloatArray jump = {status->giveTempJump().at(1), status->giveTempJump().at(2)}; - int dim = jump.giveSize(); - answer.resize(dim, dim); - answer.zero(); - - for(int i = 1; i <= dim; i++) { - jumpPlus = jumpMinus = jump; + FloatArrayF<2> jump = {status->giveTempJump().at(1), status->giveTempJump().at(2)}; + + FloatMatrixF<2,2> answer; + for(int i = 1; i <= 2; i++) { + auto jumpPlus = jump; + auto jumpMinus = jump; jumpPlus.at( i ) += eps; jumpMinus.at( i ) -= eps; - this->giveEngTraction_2d(tPlus, gp, jumpPlus, tStep); - this->giveEngTraction_2d(tMinus, gp, jumpMinus, tStep); + auto tPlus = this->giveEngTraction_2d(jumpPlus, gp, tStep); + auto tMinus = this->giveEngTraction_2d(jumpMinus, gp, tStep); - Kcolumn.beDifferenceOf(tPlus, tMinus); + auto Kcolumn = tPlus - tMinus; answer.setColumn(Kcolumn, i); } - answer.times( 1.0 / ( 2 * eps ) ); - this->giveEngTraction_2d( t, gp, jump, tStep ); // reset temp values by recomputing the stress + answer *= 1.0 / ( 2 * eps ); + this->giveEngTraction_2d( jump, gp, tStep ); // reset temp values by recomputing the stress + return answer; } -void -StructuralInterfaceMaterial :: give3dStiffnessMatrix_Eng_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +StructuralInterfaceMaterial :: give3dStiffnessMatrix_Eng_Num(GaussPoint *gp, TimeStep *tStep) const { // Default implementation for computation of the numerical tangent d(sig)/d(jump) // Computes the material stiffness using a central difference method StructuralInterfaceMaterialStatus *status = static_cast< StructuralInterfaceMaterialStatus * >( this->giveStatus( gp ) ); double eps = 1.0e-9; - FloatArray t, tPlus, tMinus; - FloatArray jumpPlus, jumpMinus, Kcolumn; - const FloatArray &jump = status->giveTempJump(); - int dim = jump.giveSize(); - answer.resize(dim, dim); - answer.zero(); - - for(int i = 1; i <= dim; i++) { - jumpPlus = jumpMinus = jump; + const auto &jump = status->giveTempJump(); + + FloatMatrixF<3,3> answer; + for(int i = 1; i <= 3; i++) { + auto jumpPlus = jump; + auto jumpMinus = jump; jumpPlus.at( i ) += eps; jumpMinus.at( i ) -= eps; - this->giveEngTraction_3d(tPlus, gp, jumpPlus, tStep); - this->giveEngTraction_3d(tMinus, gp, jumpMinus, tStep); + auto tPlus = this->giveEngTraction_3d(jumpPlus, gp, tStep); + auto tMinus = this->giveEngTraction_3d(jumpMinus, gp, tStep); - Kcolumn.beDifferenceOf(tPlus, tMinus); + auto Kcolumn = tPlus - tMinus; answer.setColumn(Kcolumn, i); } - answer.times( 1.0 / ( 2 * eps ) ); - this->giveEngTraction_3d( t, gp, jump, tStep ); // reset temp values by recomputing the stress + answer *= 1.0 / ( 2 * eps ); + this->giveEngTraction_3d(jump, gp, tStep ); // reset temp values by recomputing the stress + return answer; } } // end namespace oofem diff --git a/src/sm/Materials/InterfaceMaterials/structuralinterfacematerial.h b/src/sm/Materials/InterfaceMaterials/structuralinterfacematerial.h index d0b3c7496..1bb5e3b62 100644 --- a/src/sm/Materials/InterfaceMaterials/structuralinterfacematerial.h +++ b/src/sm/Materials/InterfaceMaterials/structuralinterfacematerial.h @@ -40,6 +40,7 @@ #include "floatmatrix.h" #include "matconst.h" #include "matstatus.h" +#include "floatarrayf.h" ///@name Input fields for StructuralInterfaceMaterial //@{ @@ -78,9 +79,6 @@ class StructuralInterfaceMaterial : public Material * @param d Domain to which new material will belong. */ StructuralInterfaceMaterial(int n, Domain * d); - /// Destructor. - virtual ~StructuralInterfaceMaterial() { } - /** * Computes the first Piola-Kirchoff traction vector for given total jump/gap and integration point. @@ -94,17 +92,14 @@ class StructuralInterfaceMaterial : public Material * @param reducedF Deformation gradient in in reduced form. * @param tStep Current time step (most models are able to respond only when tStep is current time step). */ - virtual void giveFirstPKTraction_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &reducedF, TimeStep *tStep); - virtual void giveFirstPKTraction_2d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &reducedF, TimeStep *tStep); - virtual void giveFirstPKTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, - const FloatMatrix &F, TimeStep *tStep) - { OOFEM_ERROR("not implemented "); } - - virtual void giveEngTraction_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); - virtual void giveEngTraction_2d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); - virtual void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, TimeStep *tStep); + virtual double giveFirstPKTraction_1d(double jump, double reducedF, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatArrayF<2> giveFirstPKTraction_2d(const FloatArrayF<2> &jump, const FloatMatrixF<2,2> &reducedF, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatArrayF<3> giveFirstPKTraction_3d(const FloatArrayF<3> &jump, const FloatMatrixF<3,3> &F, GaussPoint *gp, TimeStep *tStep) const + { OOFEM_ERROR("not implemented "); return FloatArrayF<3>(); } + + virtual double giveEngTraction_1d(double jump, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatArrayF<2> giveEngTraction_2d(const FloatArrayF<2> &jump, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatArrayF<3> giveEngTraction_3d(const FloatArrayF<3> &jump, GaussPoint *gp, TimeStep *tStep) const; /** * Gives the tangent: @f$ \frac{\partial T}{\partial j} @f$. @@ -114,21 +109,21 @@ class StructuralInterfaceMaterial : public Material * @param gp Gauss point. * @param tStep Time step. */ - virtual void give1dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void give2dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dStiffnessMatrix_dTdj(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + virtual FloatMatrixF<1,1> give1dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatMatrixF<2,2> give2dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatMatrixF<3,3> give3dStiffnessMatrix_dTdj(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; - virtual void give1dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void give2dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dStiffnessMatrix_Eng(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + virtual FloatMatrixF<1,1> give1dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatMatrixF<2,2> give2dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatMatrixF<3,3> give3dStiffnessMatrix_Eng(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; - void give1dStiffnessMatrix_dTdj_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - void give2dStiffnessMatrix_dTdj_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - void give3dStiffnessMatrix_dTdj_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<1,1> give1dStiffnessMatrix_dTdj_Num(GaussPoint *gp, TimeStep *tStep) const; + FloatMatrixF<2,2> give2dStiffnessMatrix_dTdj_Num(GaussPoint *gp, TimeStep *tStep) const; + FloatMatrixF<3,3> give3dStiffnessMatrix_dTdj_Num(GaussPoint *gp, TimeStep *tStep) const; - void give1dStiffnessMatrix_Eng_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - void give2dStiffnessMatrix_Eng_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); - void give3dStiffnessMatrix_Eng_Num(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<1,1> give1dStiffnessMatrix_Eng_Num(GaussPoint *gp, TimeStep *tStep) const; + FloatMatrixF<2,2> give2dStiffnessMatrix_Eng_Num(GaussPoint *gp, TimeStep *tStep) const; + FloatMatrixF<3,3> give3dStiffnessMatrix_Eng_Num(GaussPoint *gp, TimeStep *tStep) const; /** * Tells if the model has implemented analytical tangent stiffness. @@ -137,15 +132,13 @@ class StructuralInterfaceMaterial : public Material virtual bool hasAnalyticalTangentStiffness() const = 0; // identification and auxiliary functions - virtual const char *giveClassName() const { return "StructuralInterfaceMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - - virtual FloatArray giveInterfaceStrength() { return {0};} + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + virtual FloatArray giveInterfaceStrength() { return {0}; } //virtual int setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; bool useNumericalTangent; ///@todo make private }; diff --git a/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialphf.h b/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialphf.h index 5221658b6..a399b1f80 100644 --- a/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialphf.h +++ b/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialphf.h @@ -34,7 +34,8 @@ #ifndef structuralinterfacematerialphf_h #define structuralinterfacematerialphf_h -#include "Materials/InterfaceMaterials/structuralinterfacematerial.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" +#include "floatmatrixf.h" namespace oofem { class GaussPoint; @@ -45,32 +46,30 @@ class GaussPoint; */ class StructuralInterfaceMaterialPhF : public StructuralInterfaceMaterial { -public: + struct Tangents { + FloatMatrixF<3,3> jj; + FloatArrayF<3> jd; + FloatArrayF<3> dj; + double dd; + }; +public: StructuralInterfaceMaterialPhF(int n, Domain * d); - /// Destructor. - virtual ~StructuralInterfaceMaterialPhF() { } - - //virtual void giveEngTraction_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const double damage, TimeStep *tStep); - virtual void giveEngTraction_2d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const double damage, TimeStep *tStep); - virtual void giveEngTraction_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &jump, const double damage, TimeStep *tStep) + //virtual FloatArrayF<1> giveEngTraction_1d(const FloatArrayF<1> &jump, double damage, GaussPoint *gp, TimeStep *tStep); + virtual FloatArrayF<2> giveEngTraction_2d(const FloatArrayF<2> &jump, double damage, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatArrayF<3> giveEngTraction_3d(const FloatArrayF<3> &jump, double damage, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("not implemented "); }; - - virtual double giveDrivingForce(GaussPoint *gp) { OOFEM_ERROR("not implemented "); return -1;}; - virtual double giveDrivingForcePrime(GaussPoint *gp) { OOFEM_ERROR("not implemented "); return -1; }; - + virtual double giveDrivingForce(GaussPoint *gp) const { OOFEM_ERROR("not implemented "); return -1; } + virtual double giveDrivingForcePrime(GaussPoint *gp) const { OOFEM_ERROR("not implemented "); return -1; } + // Df/Dd //virtual void giveDrivingForceTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveTangents(FloatMatrix &jj, FloatMatrix &jd, FloatMatrix &dj, FloatMatrix &dd, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) + virtual void giveTangents(FloatMatrix &jj, FloatMatrix &jd, FloatMatrix &dj, FloatMatrix &dd, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("not implemented "); }; - - - - // identification and auxiliary functions - virtual const char *giveClassName() const { return "StructuralInterfaceMaterialPhF"; } - + + const char *giveClassName() const override { return "StructuralInterfaceMaterialPhF"; } }; } // end namespace oofem #endif // StructuralInterfaceMaterialPhF_h diff --git a/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.C b/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.C index ae239ce85..c690f25d3 100644 --- a/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.C +++ b/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.C @@ -36,25 +36,22 @@ #include "structuralinterfacematerial.h" #include "contextioerr.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "structuralinterfacematerialstatus.h" #include "gausspoint.h" + namespace oofem { -StructuralInterfaceMaterialStatus :: StructuralInterfaceMaterialStatus(int n, Domain *d, GaussPoint *g) : - MaterialStatus(n, d, g), jump(3), traction(3), tempTraction(3), tempJump(3), firstPKTraction(3), tempFirstPKTraction(3), F(3, 3), tempF(3, 3), - mNewlyInserted(true) + +StructuralInterfaceMaterialStatus :: StructuralInterfaceMaterialStatus(GaussPoint *g) : + MaterialStatus(g) { - this->F.beUnitMatrix(); - this->tempF.beUnitMatrix(); + F = eye<3>(); + tempF = F; } -StructuralInterfaceMaterialStatus :: ~StructuralInterfaceMaterialStatus() { } - - -void StructuralInterfaceMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +void StructuralInterfaceMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { -#if 1 MaterialStatus :: printOutputAt(file, tStep); fprintf(file, " jump "); @@ -67,12 +64,10 @@ void StructuralInterfaceMaterialStatus :: printOutputAt(FILE *file, TimeStep *tS fprintf(file, " %.4e", val ); } fprintf(file, "\n"); -#endif } void StructuralInterfaceMaterialStatus :: updateYourself(TimeStep *tStep) -// Performs end-of-step updates. { MaterialStatus :: updateYourself(tStep); @@ -84,27 +79,9 @@ void StructuralInterfaceMaterialStatus :: updateYourself(TimeStep *tStep) void StructuralInterfaceMaterialStatus :: initTempStatus() -// -// initialize record at the begining of new load step -// { MaterialStatus :: initTempStatus(); - // see if vectors describing reached equilibrium are defined - if ( this->giveJump().giveSize() == 0 ) { - - this->jump.resize( this->giveDomain()->giveNumberOfSpatialDimensions() ); - //this->jump.resize(3); - this->jump.zero(); - } - - if ( this->giveTraction().giveSize() == 0 ) { - this->traction.resize( this->giveDomain()->giveNumberOfSpatialDimensions() ); - //this->traction.resize(3); - this->traction.zero(); - } - - // reset temp vars. this->tempJump = this->jump; this->tempTraction = this->traction; this->tempFirstPKTraction = this->firstPKTraction; @@ -112,16 +89,13 @@ void StructuralInterfaceMaterialStatus :: initTempStatus() } -contextIOResultType -StructuralInterfaceMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +StructuralInterfaceMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { #if 0 - contextIOResultType iores; - - if ( ( iores = MaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + MaterialStatus :: saveContext(stream, mode); + contextIOResultType iores; if ( ( iores = strainVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -130,20 +104,16 @@ StructuralInterfaceMaterialStatus :: saveContext(DataStream &stream, ContextMode THROW_CIOERR(iores); } #endif - return CIO_OK; } -contextIOResultType -StructuralInterfaceMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +StructuralInterfaceMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { #if 0 - contextIOResultType iores; - - if ( ( iores = MaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + MaterialStatus :: restoreContext(stream, mode); + contextIOResultType iores; if ( ( iores = strainVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -152,13 +122,11 @@ StructuralInterfaceMaterialStatus :: restoreContext(DataStream &stream, ContextM THROW_CIOERR(iores); } #endif - return CIO_OK; } void StructuralInterfaceMaterialStatus :: copyStateVariables(const MaterialStatus &iStatus) { - MaterialStatus &tmpStat = const_cast< MaterialStatus & >(iStatus); - const StructuralInterfaceMaterialStatus &structStatus = dynamic_cast< StructuralInterfaceMaterialStatus & >(tmpStat); + const StructuralInterfaceMaterialStatus &structStatus = static_cast< const StructuralInterfaceMaterialStatus & >(iStatus); jump = structStatus.giveJump(); traction = structStatus.giveTraction(); diff --git a/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h b/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h index 7ee2494c7..178f64845 100644 --- a/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h +++ b/src/sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h @@ -39,11 +39,11 @@ #include "floatarray.h" #include "matstatmapperint.h" #include "floatmatrix.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" namespace oofem { class GaussPoint; -class Dictionary; -class Domain; /** * This class implements a structural interface material status information. It is attribute of @@ -54,109 +54,100 @@ class Domain; * StructuralInterfaceMaterial class. * It defines the traction, jump (discontinuity), deformation gradient and their temporary counterparts. * Functions for accessing these components are defined. - * - * Tasks: - * This is abstract class - only basic functionality is supported like: - * - maintaining and providing access to stress and strain vectors - * (including their increments) - * - storing and restoring status on tape - * - printingYourself() - * - updating Yourself after a new equilibrium state has been reached. */ class StructuralInterfaceMaterialStatus : public MaterialStatus, public MaterialStatusMapperInterface { protected: /// Equilibrated jump (discontinuity) - FloatArray jump; + FloatArrayF<3> jump; /// Equilibrated (engineering) traction vector - FloatArray traction; + FloatArrayF<3> traction; /// Temporary (engineering) traction vector - FloatArray tempTraction; + FloatArrayF<3> tempTraction; /// Temporary jump (discontinuity) - FloatArray tempJump; + FloatArrayF<3> tempJump; /// Equilibrated first Piola-Kirchhoff traction vector T - FloatArray firstPKTraction; + FloatArrayF<3> firstPKTraction; /// Temporary first Piola-Kirchhoff traction vector (to find balanced state) - FloatArray tempFirstPKTraction; + FloatArrayF<3> tempFirstPKTraction; /// Equilibrated deformation gradient in reduced form - FloatMatrix F; + FloatMatrixF<3,3> F; /// Temporary deformation gradient in reduced form (to find balanced state) - FloatMatrix tempF; + FloatMatrixF<3,3> tempF; /// Interface normal direction - FloatArray mNormalDir; + FloatArrayF<3> mNormalDir; - bool mNewlyInserted; + bool mNewlyInserted = true; - FloatArray projectedTraction; + FloatArrayF<2> projectedTraction; public: /// Constructor. Creates new StructuralInterfaceMaterialStatus with number n, belonging to domain d and IntegrationPoint g. - StructuralInterfaceMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~StructuralInterfaceMaterialStatus(); + StructuralInterfaceMaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; /// Returns the const pointer to receiver's jump. - const FloatArray &giveJump() const { return jump; } + const FloatArrayF<3> &giveJump() const { return jump; } /// Returns the const pointer to receiver's traction vector. - const FloatArray &giveTraction() const { return traction; } + const FloatArrayF<3> &giveTraction() const { return traction; } /// Returns the const pointer to receiver's first Piola-Kirchhoff traction vector. - const FloatArray &giveFirstPKTraction() const { return firstPKTraction; } + const FloatArrayF<3> &giveFirstPKTraction() const { return firstPKTraction; } /// Returns the const pointer to receiver's deformation gradient vector. - const FloatMatrix &giveF() const { return F; } + const FloatMatrixF<3,3> &giveF() const { return F; } /// Returns the const pointer to receiver's temporary jump. - const FloatArray &giveTempJump() const { return tempJump; } + const FloatArrayF<3> &giveTempJump() const { return tempJump; } /// Returns the const pointer to receiver's temporary traction vector. - const FloatArray &giveTempTraction() const { return tempTraction; } + const FloatArrayF<3> &giveTempTraction() const { return tempTraction; } /// Returns the const pointer to receiver's temporary first Piola-Kirchhoff traction vector. - const FloatArray &giveTempFirstPKTraction() const { return tempFirstPKTraction; } + const FloatArrayF<3> &giveTempFirstPKTraction() const { return tempFirstPKTraction; } /// Returns the const pointer to receiver's temporary deformation gradient vector. - const FloatMatrix &giveTempF() const { return tempF; } + const FloatMatrixF<3,3> &giveTempF() const { return tempF; } /// Returns const reference to normal vector. - const FloatArray &giveNormal() const { return mNormalDir; } + const FloatArrayF<3> &giveNormal() const { return mNormalDir; } /// Returns the projected traction. - const FloatArray &giveProjectedTraction() const { return projectedTraction; } + const FloatArrayF<2> &giveProjectedTraction() const { return projectedTraction; } /// Assigns jump to given vector v. - void letJumpBe(FloatArray v) { jump = std :: move(v); } + void letJumpBe(const FloatArrayF<3> v) { jump = v; } /// Assigns traction to given vector v. - void letTractionBe(FloatArray v) { traction = std :: move(v); } + void letTractionBe(const FloatArrayF<3> v) { traction = v; } /// Assigns firstPKTraction to given vector v. - void letFirstPKTractionBe(FloatArray v) { firstPKTraction = std :: move(v); } + void letFirstPKTractionBe(const FloatArrayF<3> v) { firstPKTraction = v; } /// Assigns FVector to given vector v. - void letFBe(FloatMatrix v) { F = std :: move(v); } + void letFBe(const FloatMatrixF<3,3> v) { F = v; } /// Assigns tempTraction to given vector v. - void letTempTractionBe(FloatArray v) { tempTraction = std :: move(v); } + void letTempTractionBe(const FloatArrayF<3> v) { tempTraction = v; } /// Assigns tempJump to given vector v - void letTempJumpBe(FloatArray v) { tempJump = std :: move(v); } + void letTempJumpBe(const FloatArrayF<3> v) { tempJump = v; } /// Assigns tempFirstPKTraction to given vector v - void letTempFirstPKTractionBe(FloatArray v) { tempFirstPKTraction = std :: move(v); } + void letTempFirstPKTractionBe(const FloatArrayF<3> v) { tempFirstPKTraction = v; } /// Assigns tempFVector to given vector v - void letTempFBe(FloatMatrix v) { tempF = std :: move(v); } + void letTempFBe(const FloatMatrixF<3,3> &v) { tempF = v; } /// Assigns normal vector - void letNormalBe(FloatArray iN) { mNormalDir = std :: move(iN); } + void letNormalBe(const FloatArrayF<3> &iN) { mNormalDir = iN; } /// Assigns projeted traction - void letProjectedTractionBe(FloatArray iProjectedTraction) { projectedTraction = std :: move(iProjectedTraction); } + void letProjectedTractionBe(const FloatArrayF<2> &iProjectedTraction) { projectedTraction = iProjectedTraction; } + ///@TODO Projected tractions are *never* set. What is it supposed to be good for? - virtual const char *giveClassName() const { return "StructuralInterfaceMaterialStatus"; } + const char *giveClassName() const override { return "StructuralInterfaceMaterialStatus"; } /// Functions for MaterialStatusMapperInterface - virtual void copyStateVariables(const MaterialStatus &iStatus); - virtual void addStateVariables(const MaterialStatus &iStatus); - - bool giveNewlyInserted() const {return mNewlyInserted;} - void setNewlyInserted(bool iNewlyInserted) {mNewlyInserted = iNewlyInserted;} - - virtual double giveDamage() { return 0.0; } // no default damage - virtual double giveTempDamage() { return 0.0; } // no default damage + void copyStateVariables(const MaterialStatus &iStatus) override; + void addStateVariables(const MaterialStatus &iStatus) override; + + bool giveNewlyInserted() const { return mNewlyInserted; } + void setNewlyInserted(bool iNewlyInserted) { mNewlyInserted = iNewlyInserted; } + + virtual double giveDamage() const { return 0.0; } // no default damage + virtual double giveTempDamage() const { return 0.0; } // no default damage }; } // end namespace oofem #endif // structuralinterfacematerialstatus_h diff --git a/tests/sm/rvesmall.out-gp1 b/src/sm/Materials/LatticeMaterials/CMakeLists.txt similarity index 100% rename from tests/sm/rvesmall.out-gp1 rename to src/sm/Materials/LatticeMaterials/CMakeLists.txt diff --git a/src/sm/Materials/LatticeMaterials/latticebondplasticity.C b/src/sm/Materials/LatticeMaterials/latticebondplasticity.C new file mode 100644 index 000000000..f41752f5e --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticebondplasticity.C @@ -0,0 +1,764 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticebondplasticity.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "engngm.h" +#include "mathfem.h" +#include +#include "latticematstatus.h" +#include "intarray.h" +#include "Elements/LatticeElements/latticestructuralelement.h" +#include "datastream.h" +#include "contextioerr.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(LatticeBondPlasticity); + + +LatticeBondPlasticity::LatticeBondPlasticity(int n, Domain *d) : LatticeLinearElastic(n, d) +{} + + +bool +LatticeBondPlasticity::hasMaterialModeCapability(MaterialMode mode) const +{ + return mode == _3dLattice; +} + +double +LatticeBondPlasticity::computeHardening(double kappa) const +{ + return exp( pow(kappa / this->ef, 2.) ); +} + +double +LatticeBondPlasticity::computeDHardeningDKappa(double kappa) const +{ + return 2. * kappa / ( pow(this->ef, 2.) ) * exp( pow(kappa / this->ef, 2.) ); +} + + +void +LatticeBondPlasticity::initializeFrom(InputRecord &ir) +{ + LatticeLinearElastic::initializeFrom(ir); + + this->yieldTol = 1.e-6; + IR_GIVE_OPTIONAL_FIELD(ir, this->yieldTol, _IFT_LatticeBondPlasticity_tol); + + newtonIter = 100; + IR_GIVE_OPTIONAL_FIELD(ir, newtonIter, _IFT_LatticeBondPlasticity_iter); + + numberOfSubIncrements = 10; + IR_GIVE_OPTIONAL_FIELD(ir, numberOfSubIncrements, _IFT_LatticeBondPlasticity_sub); + + IR_GIVE_FIELD(ir, this->fc, _IFT_LatticeBondPlasticity_fc); + + this->frictionAngleOne = 0.2; + IR_GIVE_OPTIONAL_FIELD(ir, this->frictionAngleOne, _IFT_LatticeBondPlasticity_angle1); + + this->frictionAngleTwo = this->frictionAngleOne; + + this->flowAngle = this->frictionAngleOne; + + this->ef = 0.; + IR_GIVE_OPTIONAL_FIELD(ir, this->ef, _IFT_LatticeBondPlasticity_ef); +} + +MaterialStatus * +LatticeBondPlasticity::CreateStatus(GaussPoint *gp) const +{ + return new LatticeBondPlasticityStatus(1, LatticeBondPlasticity::domain, gp); +} + +double +LatticeBondPlasticity::computeShift(const double kappa) const +{ + double hardening = computeHardening(kappa); + + double paramA = computeParamA(kappa); + + double shift = this->fc * hardening - paramA; + + return shift; +} + + +double +LatticeBondPlasticity::computeParamA(const double kappa) const +{ + double hardening = computeHardening(kappa); + + double paramA = this->frictionAngleTwo * this->frictionAngleOne * this->fc * hardening / + ( this->frictionAngleTwo * this->frictionAngleOne + + sqrt( 1. + pow(this->frictionAngleTwo, 2.) * pow(this->frictionAngleOne, 2.) ) ); + + return paramA; +} + + +double +LatticeBondPlasticity::computeDShiftDKappa(const double kappa) const +{ + double dHardeningDKappa = computeDHardeningDKappa(kappa); + + double dParamADKappa = computeDParamADKappa(kappa); + + double dShiftDKappa = this->fc * dHardeningDKappa - dParamADKappa; + + return dShiftDKappa; +} + + +double +LatticeBondPlasticity::computeDParamADKappa(const double kappa) const +{ + double dHardeningDKappa = computeDHardeningDKappa(kappa); + + double A2 = this->frictionAngleTwo * this->frictionAngleOne + sqrt( 1. + pow(this->frictionAngleTwo, 2.) * pow(this->frictionAngleOne, 2.) ); + + double dA1DKappa = this->frictionAngleTwo * this->frictionAngleOne * this->fc * dHardeningDKappa; + + double dParamADKappa = dA1DKappa / A2; + + return dParamADKappa; +} + + +FloatArrayF< 6 > +LatticeBondPlasticity::giveReducedStrain(GaussPoint *gp, TimeStep *tStep) const +{ + auto status = static_cast< LatticeBondPlasticityStatus * >( this->giveStatus(gp) ); + return status->giveReducedLatticeStrain(); +} + + +FloatArrayF< 3 > +LatticeBondPlasticity::performPlasticityReturn(GaussPoint *gp, + const FloatArrayF< 3 > &strain, + TimeStep *tStep) const +{ + auto status = static_cast< LatticeBondPlasticityStatus * >( this->giveStatus(gp) ); + + LatticeBondPlasticity_SurfaceType surfaceType = ST_Unknown; + + //Get tempKappa from the status + double tempKappa = status->giveTempKappaP(); + + /* Get plastic strain vector from status*/ + auto tempPlasticStrain = status->giveTempPlasticLatticeStrain() [ { 0, 1, 2 } ]; + + FloatArrayF< 3 >tangent = { this->eNormalMean, this->alphaOne * this->eNormalMean, this->alphaOne * this->eNormalMean }; + + /* Compute trial stress*/ + auto stress = mult(tangent, strain - tempPlasticStrain); + + //Introduce variables for subincrementation + auto oldStrain = this->giveReducedStrain(gp, tStep) [ { 0, 1, 2 } ]; + + /* Compute yield value*/ + int transitionFlag = 0; + double yieldValue = computeYieldValue(stress, tempKappa, transitionFlag, gp); + + double transition = computeTransition(tempKappa, gp); + + //If shear surface is violated then return to this surface. + //No need to check situation with ellipse + //If only ellipse is violated then try this. + if ( yieldValue < this->yieldTol && stress.at(1) < transition - this->yieldTol ) { + transitionFlag = 1; + yieldValue = computeYieldValue(stress, tempKappa, 1, gp); + } + + /* Compute yield value*/ + double error = 0.; + if ( transitionFlag == 0 ) { + error = yieldValue / fc; + } else { + error = yieldValue / pow(fc, 2.); + } + + if ( error > this->yieldTol ) { + if ( checkForVertexCase(stress, gp) ) { + performVertexReturn(stress, gp); + surfaceType = ST_Vertex; + } else { + int subIncrementFlag = 0; + double subIncrementCounter = 1; + auto convergedStrain = oldStrain; + auto tempStrain = strain; + auto deltaStrain = strain - oldStrain; + //To get into the loop + LatticeBondPlasticity_ReturnResult returnResult = RR_NotConverged; + while ( returnResult == RR_NotConverged || subIncrementFlag == 1 ) { + stress = mult(tangent, tempStrain - tempPlasticStrain); + tempKappa = performRegularReturn(stress, returnResult, surfaceType, yieldValue, transitionFlag, gp); + + if ( returnResult == RR_NotConverged ) { + subIncrementFlag = 1; + + + subIncrementCounter *= 2; + if ( subIncrementCounter >= numberOfSubIncrements ) { + OOFEM_ERROR("Subincrementation = %e did not help. Stop here with numberOfSubIncrements = %d.\n", subIncrementCounter, numberOfSubIncrements); + } + + deltaStrain *= 0.5; + tempStrain = convergedStrain + deltaStrain; + } else if ( returnResult == RR_Converged && subIncrementFlag == 1 ) { + tempPlasticStrain.at(1) = tempStrain.at(1) - stress.at(1) / eNormalMean; + tempPlasticStrain.at(2) = tempStrain.at(2) - stress.at(2) / ( this->alphaOne * eNormalMean ); + tempPlasticStrain.at(3) = tempStrain.at(3) - stress.at(3) / ( this->alphaOne * eNormalMean ); + + status->letTempPlasticLatticeStrainBe( assemble< 6 >(tempPlasticStrain, { 0, 1, 2 }) ); + + status->setTempKappaP(tempKappa); + + subIncrementCounter -= 1; + + convergedStrain = tempStrain; + deltaStrain = strain - convergedStrain; + auto deltaStrainIncrement = deltaStrain * ( 1. / subIncrementCounter ); + tempStrain = convergedStrain + deltaStrainIncrement; + if ( subIncrementCounter > 1 ) { + subIncrementFlag = 1; + } else { + subIncrementFlag = 0; + } + returnResult = RR_NotConverged; + } else if ( returnResult == RR_Elastic && subIncrementFlag == 1 ) { + convergedStrain = tempStrain; + deltaStrain = strain - convergedStrain; + auto deltaStrainIncrement = deltaStrain * ( 1. / subIncrementCounter ); + tempStrain = convergedStrain + deltaStrainIncrement; + if ( subIncrementCounter > 1 ) { + subIncrementFlag = 1; + } else { + subIncrementFlag = 0; + } + returnResult = RR_NotConverged; + } else if ( returnResult == RR_Converged && subIncrementFlag == 0 ) { + status->setTempKappaP(tempKappa); + } + } + } + } + + tempPlasticStrain.at(1) = strain.at(1) - stress.at(1) / eNormalMean; + tempPlasticStrain.at(2) = strain.at(2) - stress.at(2) / ( this->alphaOne * eNormalMean ); + tempPlasticStrain.at(3) = strain.at(3) - stress.at(3) / ( this->alphaOne * eNormalMean ); + + status->letTempPlasticLatticeStrainBe( assemble< 6 >(tempPlasticStrain, { 0, 1, 2 }) ); + status->letTempLatticeStressBe( assemble< 6 >(stress, { 0, 1, 2 }) ); + status->setSurfaceValue(surfaceType); + + return stress; +} + +int +LatticeBondPlasticity::giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) +{ + auto status = static_cast< LatticeBondPlasticityStatus * >( this->giveStatus(gp) ); + + if ( type == IST_PlasticLatticeStrain ) { + answer = status->givePlasticLatticeStrain(); + return 1; + } else { + return LatticeLinearElastic::giveIPValue(answer, gp, type, atTime); + } +} + +double +LatticeBondPlasticity::performRegularReturn(FloatArrayF< 3 > &stress, + LatticeBondPlasticity_ReturnResult &returnResult, + LatticeBondPlasticity_SurfaceType &surfaceType, + double yieldValue, + int transitionFlag, + GaussPoint *gp) const +{ + auto status = static_cast< LatticeBondPlasticityStatus * >( this->giveStatus(gp) ); + + double deltaLambda = 0.; + + auto trialStress = stress; + auto tempStress = trialStress; + + double trialShearStressNorm = norm(trialStress [ { 1, 2 } ]); + double tempShearStressNorm = trialShearStressNorm; + + auto plasticStrain = status->givePlasticLatticeStrain() [ { 0, 1, 2 } ]; + auto tempPlasticStrain = plasticStrain; + + double thetaTrial = atan2( stress.at(3), stress.at(2) ); + + // Do the same for kappa + double kappa = status->giveTempKappaP(); + double tempKappa = kappa; + + + //initialise unknowns + FloatArrayF< 4 >unknowns; + unknowns.at(1) = trialStress.at(1); + unknowns.at(2) = trialShearStressNorm; + unknowns.at(3) = tempKappa; + unknowns.at(4) = 0.; + + yieldValue = computeYieldValue(tempStress, tempKappa, transitionFlag, gp); + + //initiate residuals + FloatArrayF< 4 >residuals; + residuals.at(4) = yieldValue; + + double normOfResiduals = this->yieldTol * 2 + 1.; //just to get into the loop + + int iterationCount = 0; + while ( normOfResiduals > this->yieldTol ) { + iterationCount++; + if ( iterationCount == newtonIter ) { + returnResult = RR_NotConverged; + return kappa; + } + + FloatArrayF< 4 >residualsNorm; + residualsNorm.at(1) = residuals.at(1) / this->fc; + residualsNorm.at(2) = residuals.at(2) / this->fc; + residualsNorm.at(3) = residuals.at(3); + if ( transitionFlag == 0 ) { + residualsNorm.at(4) = residuals.at(4) / this->fc; + } else { + residualsNorm.at(4) = residuals.at(4) / pow(this->fc, 2.); + } + + normOfResiduals = norm(residualsNorm); + + if ( std::isnan(normOfResiduals) ) { + returnResult = RR_NotConverged; + return kappa; + } + + if ( normOfResiduals > this->yieldTol ) { + auto jacobian = computeJacobian(tempStress, tempKappa, deltaLambda, transitionFlag, gp); + + auto solution = solve_check(jacobian, residuals); + if ( solution.first ) { + unknowns -= solution.second; + } else { + returnResult = RR_NotConverged; + return kappa; + } + + unknowns.at(2) = max(unknowns.at(2), 0.); //Keep rho greater than zero! + unknowns.at(3) = max(unknowns.at(3), kappa); //Keep deltaKappa greater than zero! + unknowns.at(4) = max(unknowns.at(4), 0.); //Keep deltaLambda greater than zero! + + /* Update increments final values and DeltaLambda*/ + tempStress.at(1) = unknowns.at(1); + tempShearStressNorm = unknowns.at(2); + tempStress.at(2) = tempShearStressNorm * cos(thetaTrial); + tempStress.at(3) = tempShearStressNorm * sin(thetaTrial); + tempKappa = unknowns.at(3); + deltaLambda = unknowns.at(4); + + /* Compute the mVector holding the derivatives of the g function and the hardening function*/ + auto mVector = computeMVector(tempStress, tempKappa, transitionFlag, gp); + + residuals.at(1) = tempStress.at(1) - trialStress.at(1) + this->eNormalMean * deltaLambda * mVector.at(1); + residuals.at(2) = tempShearStressNorm - trialShearStressNorm + this->alphaOne * this->eNormalMean * deltaLambda * mVector.at(2); + residuals.at(3) = -tempKappa + kappa + deltaLambda * mVector.at(3); + residuals.at(4) = computeYieldValue(tempStress, tempKappa, transitionFlag, gp); + } else { + //Check transition + double transition = computeTransition(tempKappa, gp); + if ( transitionFlag == 0 ) { + //Check if the stress is on the correct side + if ( tempStress.at(1) < transition - this->yieldTol ) { + transitionFlag = 1; + tempKappa = kappa; + deltaLambda = 0.; + tempStress = trialStress; + tempShearStressNorm = norm(trialStress [ { 1, 2 } ]); + + unknowns.at(1) = trialStress.at(1); + unknowns.at(2) = trialShearStressNorm; + unknowns.at(3) = tempKappa; + unknowns.at(4) = 0.; + + residuals = zeros< 4 >(); + residuals.at(4) = computeYieldValue(tempStress, tempKappa, transitionFlag, gp); + normOfResiduals = 1; + + tempPlasticStrain = plasticStrain; + iterationCount = 0; + } else { //Accept the stress return + surfaceType = ST_Shear; + returnResult = RR_Converged; + } + } else if ( transitionFlag == 1 ) { + if ( tempStress.at(1) > transition + this->yieldTol ) { + returnResult = RR_NotConverged; + return kappa; + } else { //accept stress return + surfaceType = ST_Compression; + returnResult = RR_Converged; + } + } + } + } + + stress = tempStress; + + return tempKappa; +} + + +FloatMatrixF< 4, 4 > +LatticeBondPlasticity::computeJacobian(const FloatArrayF< 3 > &stress, + const double kappa, + const double deltaLambda, + int transitionFlag, + GaussPoint *gp) const +{ + auto dMMatrix = computeDMMatrix(stress, kappa, transitionFlag, gp); + auto mVector = computeMVector(stress, kappa, transitionFlag, gp); + auto fVector = computeFVector(stress, kappa, transitionFlag, gp); + + /* Compute matrix*/ + FloatMatrixF< 4, 4 >jacobian; + jacobian.at(1, 1) = 1. + this->eNormalMean * deltaLambda * dMMatrix.at(1, 1); + jacobian.at(1, 2) = this->eNormalMean * deltaLambda * dMMatrix.at(1, 2); + jacobian.at(1, 3) = this->eNormalMean * deltaLambda * dMMatrix.at(1, 3); + jacobian.at(1, 4) = this->eNormalMean * mVector.at(1); + /**/ + jacobian.at(2, 1) = this->alphaOne * this->eNormalMean * deltaLambda * dMMatrix.at(2, 1); + jacobian.at(2, 2) = 1. + this->alphaOne * this->eNormalMean * deltaLambda * dMMatrix.at(2, 2); + jacobian.at(2, 3) = this->alphaOne * this->eNormalMean * deltaLambda * dMMatrix.at(2, 3); + jacobian.at(2, 4) = this->alphaOne * this->eNormalMean * mVector.at(2); + /**/ + jacobian.at(3, 1) = deltaLambda * dMMatrix.at(3, 1); + jacobian.at(3, 2) = deltaLambda * dMMatrix.at(3, 2); + jacobian.at(3, 3) = deltaLambda * dMMatrix.at(3, 3) - 1.; + jacobian.at(3, 4) = mVector.at(3); + /**/ + jacobian.at(4, 1) = fVector.at(1); + jacobian.at(4, 2) = fVector.at(2); + jacobian.at(4, 3) = fVector.at(3); + jacobian.at(4, 4) = 0.; + + return jacobian; +} + + +double +LatticeBondPlasticity::computeYieldValue(const FloatArrayF< 3 > &stress, + const double kappa, + const int transitionFlag, + GaussPoint *gp) const +{ + double shift = computeShift(kappa); + double paramA = computeParamA(kappa); + + double shearNorm = norm(stress [ { 1, 2 } ]); + + if ( transitionFlag == 0 ) { //friction + return shearNorm + this->frictionAngleOne * stress.at(1); + } else { + return pow(shearNorm, 2.) + pow(stress.at(1) + shift, 2.) / pow(this->frictionAngleTwo, 2.) - pow(paramA, 2.) / pow(this->frictionAngleTwo, 2.); + } +} + + +double +LatticeBondPlasticity::computeTransition(const double kappa, + GaussPoint *gp) const +{ + double paramA = computeParamA(kappa); + + double transition = -paramA / ( this->frictionAngleTwo * this->frictionAngleOne * + sqrt( 1. + pow(this->frictionAngleTwo, 2.) * + pow(this->frictionAngleOne, 2.) ) ); + return transition; +} + + +FloatArrayF< 3 > +LatticeBondPlasticity::computeFVector(const FloatArrayF< 3 > &stress, + const double kappa, + const int transitionFlag, + GaussPoint *gp) const +{ + double shearNorm = norm(stress [ { 1, 2 } ]); + + double paramA = computeParamA(kappa); + double shift = computeShift(kappa); + + double dParamADKappa = computeDParamADKappa(kappa); + double dShiftDKappa = computeDShiftDKappa(kappa); + + FloatArrayF< 3 >f; + if ( transitionFlag == 0 ) {//line + f.at(1) = this->frictionAngleOne; + f.at(2) = 1.; + f.at(3) = 0.; + } else { //cap ellipse + f.at(1) = 2. * ( stress.at(1) + shift ) / pow(this->frictionAngleTwo, 2.); + f.at(2) = 2. * shearNorm; + f.at(3) = 2. * ( stress.at(1) + shift ) / pow(this->frictionAngleTwo, 2.) * dShiftDKappa - + 2. * paramA / pow(this->frictionAngleTwo, 2.) * dParamADKappa; + } + + return f; +} + + +FloatArrayF< 3 > +LatticeBondPlasticity::computeMVector(const FloatArrayF< 3 > &stress, + const double kappa, + const int transitionFlag, + GaussPoint *gp) const +{ + double shearNorm = norm(stress [ { 1, 2 } ]); + + double shift = computeShift(kappa); + + FloatArrayF< 3 >m; + if ( transitionFlag == 0 ) { + m.at(1) = this->flowAngle; + m.at(2) = 1.; + //No hardening for the Mohr-Coulomb + m.at(3) = 0.; + } else { + m.at(1) = 2. * ( stress.at(1) + shift ) / pow(this->frictionAngleTwo, 2.); + m.at(2) = 2. * shearNorm; + if ( stress.at(1) < -shift - this->yieldTol ) { + m.at(3) = fabs( m.at(1) ); + } else { + m.at(3) = 0; + } + } + + return m; +} + + +FloatMatrixF< 3, 3 > +LatticeBondPlasticity::computeDMMatrix(const FloatArrayF< 3 > &stress, + const double kappa, + const int transitionFlag, + GaussPoint *gp) const +{ + auto mVector = computeMVector(stress, kappa, transitionFlag, gp); + double dShiftDKappa = computeDShiftDKappa(kappa); + double shift = computeShift(kappa); + + if ( transitionFlag == 0 ) { + return FloatMatrixF< 3, 3 >(); + } else { //cap ellipse + FloatMatrixF< 3, 3 >dm; + //Derivatives of dGDSig + dm.at(1, 1) = 2. / pow(this->frictionAngleTwo, 2.); + dm.at(1, 2) = 0.; + dm.at(1, 3) = 2. * dShiftDKappa / pow(this->frictionAngleTwo, 2.); + + //Derivatives of dGDTau + dm.at(2, 1) = 0.; + dm.at(2, 2) = 2.; + dm.at(2, 3) = 0; + + //Derivates of evolution law + if ( stress.at(1) < -shift - this->yieldTol ) { + dm.at(3, 1) = 1. / mVector.at(3) * mVector.at(1) * dm.at(1, 1); + dm.at(3, 2) = 0.; + dm.at(3, 3) = 1. / mVector.at(3) * ( mVector.at(1) * dm.at(1, 3) ); + } else { + dm.at(3, 1) = dm.at(3, 2) = dm.at(3, 3) = 0.; + } + return dm; + } +} + + +FloatMatrixF< 3, 3 > +LatticeBondPlasticity::computeAMatrix(const FloatArrayF< 3 > &stress, + const double kappa, + const double deltaLambda, + const int transitionFlag, + GaussPoint *gp) const +{ + auto dMMatrix = computeDMMatrix(stress, kappa, transitionFlag, gp); + /* Compute matrix*/ + FloatMatrixF< 3, 3 >a; + a.at(1, 1) = 1 / this->eNormalMean + deltaLambda * dMMatrix.at(1, 1); + a.at(1, 2) = deltaLambda * dMMatrix.at(1, 2); + a.at(1, 3) = deltaLambda * dMMatrix.at(1, 3); + /**/ + a.at(2, 1) = deltaLambda * dMMatrix.at(2, 1); + a.at(2, 2) = 1 / ( this->alphaOne * this->eNormalMean ) + deltaLambda * dMMatrix.at(2, 2); + a.at(2, 3) = deltaLambda * dMMatrix.at(2, 3); + /**/ + a.at(3, 1) = deltaLambda * dMMatrix.at(3, 1); + a.at(3, 2) = deltaLambda * dMMatrix.at(3, 2); + a.at(3, 3) = deltaLambda * dMMatrix.at(3, 3) - 1.; + return a; +} + + +bool +LatticeBondPlasticity::checkForVertexCase(FloatArrayF< 3 > &stress, GaussPoint *gp) const +{ + double shearNorm = norm(stress [ { 1, 2 } ]); + + double ratio = 0.; + + if ( shearNorm / this->eNormalMean > 1.e-30 ) { + ratio = this->alphaOne * stress.at(1) / shearNorm; + } else { + ratio = 5. * this->flowAngle;//set to arbitrary value which is greater than flowAngle + } + if ( stress.at(1) > 0 && this->flowAngle < ratio ) { + return true; + } else { + return false; + } +} + + +void +LatticeBondPlasticity::performVertexReturn(FloatArrayF< 3 > &stress, GaussPoint *gp) const +{ + auto status = static_cast< LatticeBondPlasticityStatus * >( giveStatus(gp) ); + + double shearStressNorm = norm(stress [ { 1, 2 } ]); + //Update kappa + double kappa = status->giveKappaP(); + double deltaKappa = pow(stress.at(1) / this->eNormalMean, 2.) + pow(shearStressNorm / ( this->alphaOne * this->eNormalMean ), 2.); + + double tempKappa = kappa + deltaKappa; + + stress = zeros< 3 >(); + + status->setTempKappaP(tempKappa); +} + + +FloatArrayF< 6 > +LatticeBondPlasticity::giveLatticeStress3d(const FloatArrayF< 6 > &originalStrain, GaussPoint *gp, TimeStep *tStep) +{ + auto status = static_cast< LatticeBondPlasticityStatus * >( this->giveStatus(gp) ); + status->initTempStatus(); + + auto reducedStrain = originalStrain; + auto thermalStrain = this->computeStressIndependentStrainVector(gp, tStep, VM_Total); + if ( thermalStrain.giveSize() ) { + reducedStrain -= FloatArrayF< 6 >(thermalStrain); + } + + auto stress3 = this->performPlasticityReturn(gp, reducedStrain [ { 0, 1, 2 } ], tStep); + + auto stress = assemble< 6 >(stress3, { 0, 1, 2 }); + stress.at(4) = reducedStrain.at(4) * this->alphaTwo * this->eNormalMean; + stress.at(5) = reducedStrain.at(5) * this->alphaTwo * this->eNormalMean; + stress.at(6) = reducedStrain.at(6) * this->alphaTwo * this->eNormalMean; + + status->letTempLatticeStrainBe(originalStrain); + status->letTempReducedLatticeStrainBe(reducedStrain); + status->letTempLatticeStressBe(stress); + + return stress; +} + + +LatticeBondPlasticityStatus::LatticeBondPlasticityStatus(int n, Domain *d, GaussPoint *gp) + : LatticeMaterialStatus(gp) +{ } + + +void +LatticeBondPlasticityStatus::initTempStatus() +{ + LatticeMaterialStatus::initTempStatus(); + this->tempKappaP = this->kappaP; +} + +void +LatticeBondPlasticityStatus::printOutputAt(FILE *file, TimeStep *tStep) const +{ + LatticeMaterialStatus::printOutputAt(file, tStep); + fprintf(file, "status { "); + fprintf(file, "plasticStrains "); + for ( double s : this->plasticLatticeStrain ) { + fprintf(file, "% .8e ", s); + } + + fprintf(file, "\n \t"); + fprintf(file, " kappaP %.8e, surfaceType %d\n", this->kappaP, this->surfaceValue); + fprintf(file, "}\n"); +} + + +void +LatticeBondPlasticityStatus::updateYourself(TimeStep *atTime) +{ + LatticeMaterialStatus::updateYourself(atTime); + this->kappaP = this->tempKappaP; +} + + +void +LatticeBondPlasticityStatus::saveContext(DataStream &stream, ContextMode mode) +{ + LatticeMaterialStatus::saveContext(stream, mode); + + if ( !stream.write(& kappaP, 1) ) { + THROW_CIOERR(CIO_IOERR); + } +} + + +void +LatticeBondPlasticityStatus::restoreContext(DataStream &stream, ContextMode mode) +{ + LatticeMaterialStatus::restoreContext(stream, mode); + + if ( !stream.read(& kappaP, 1) ) { + THROW_CIOERR(CIO_IOERR); + } +} +} // end namespace oofem diff --git a/src/sm/Materials/LatticeMaterials/latticebondplasticity.h b/src/sm/Materials/LatticeMaterials/latticebondplasticity.h new file mode 100644 index 000000000..0c77641f1 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticebondplasticity.h @@ -0,0 +1,217 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticebondplasticity_h +#define latticebondplasticity_h + +#include "latticelinearelastic.h" +#include "latticematstatus.h" + +///@name Input fields for LatticePlasticityDamage +//@{ +#define _IFT_LatticeBondPlasticity_Name "latticebondplast" +#define _IFT_LatticeBondPlasticity_tol "tol" +#define _IFT_LatticeBondPlasticity_iter "iter" +#define _IFT_LatticeBondPlasticity_sub "sub" +#define _IFT_LatticeBondPlasticity_fc "fc" +#define _IFT_LatticeBondPlasticity_angle1 "angle1" +#define _IFT_LatticeBondPlasticity_ef "ef" +//@} + +namespace oofem { +/** + * This class implements associated Material Status to LatticeBondPlasticity. + */ +class LatticeBondPlasticityStatus : public LatticeMaterialStatus +{ +protected: + + double kappaP = 0.; + double tempKappaP = 0.; + + int surfaceValue = 0.; + +public: + + /// Constructor + LatticeBondPlasticityStatus(int n, Domain *d, GaussPoint *g); + + /// Returns the last equilibrated scalar measure of the largest strain level + double giveKappaP() const { return kappaP; } + /// Returns the temp. scalar measure of the largest strain level + double giveTempKappaP() const { return tempKappaP; } + /// Sets the temp scalar measure of the largest strain level to given value + void setTempKappaP(double newKappa) { tempKappaP = newKappa; } + + void setSurfaceValue(int val) + { + surfaceValue = val; + } + + int giveSurfaceValue() + { + return surfaceValue; + } + + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + const char *giveClassName() const override { return "LatticeBondPlasticityStatus"; } + + void initTempStatus() override; + + void updateYourself(TimeStep *) override; + + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; +}; + +class LatticeBondPlasticity : public LatticeLinearElastic +{ +protected: + + enum LatticeBondPlasticity_SurfaceType { ST_Unknown, ST_Vertex, ST_Shear, ST_Compression }; + + enum LatticeBondPlasticity_ReturnResult { RR_NotConverged, RR_Converged, RR_Elastic }; + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime) override; + + /// compressive strength + double fc = 0.; + + /// frictional angle of the yield surface + double frictionAngleOne = 0.; + double frictionAngleTwo = 0.; + + double flowAngle = 0.; + + /// yield tolerance + double yieldTol = 0.; + + /// maximum number of iterations for stress return + int newtonIter = 0; + + /// maximum number of subincrements + int numberOfSubIncrements = 0; + + //parameter in hardening law + double ef = 0.; + +public: + + /// Constructor + LatticeBondPlasticity(int n, Domain *d); + + const char *giveInputRecordName() const override { return _IFT_LatticeBondPlasticity_Name; } + const char *giveClassName() const override { return "LatticeBondPlasticity"; } + + double computeHardening(double kappa) const; + + double computeDHardeningDKappa(double kappa) const; + + double computeParamA(const double kappa) const; + double computeDParamADKappa(const double kappa) const; + + double computeShift(const double kappa) const; + double computeDShiftDKappa(const double kappa) const; + + + void initializeFrom(InputRecord &ir) override; + + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + + + + bool checkForVertexCase(FloatArrayF< 3 > &stress, GaussPoint *gp) const; + + void performVertexReturn(FloatArrayF< 3 > &stress, GaussPoint *gp) const; + + double computeTransition(const double kappa, GaussPoint *gp) const; + + bool hasMaterialModeCapability(MaterialMode mode) const override; + + + /* Compute the A matrix used for closest point return + */ + FloatMatrixF< 3, 3 >computeAMatrix(const FloatArrayF< 3 > &sigma, + const double tempKappa, + const double deltaLambda, + int transitionFlag, + GaussPoint *gp) const; + + FloatMatrixF< 4, 4 >computeJacobian(const FloatArrayF< 3 > &sigma, + const double tempKappa, + const double deltaLambda, + int transitionFlag, + GaussPoint *gp) const; + + FloatArrayF< 3 >computeFVector(const FloatArrayF< 3 > &sigma, + const double kappa, + int transitionFlag, + GaussPoint *gp) const; + FloatArrayF< 3 >computeMVector(const FloatArrayF< 3 > &sigma, + const double kappa, + int transitionFlag, + GaussPoint *gp) const; + FloatMatrixF< 3, 3 >computeDMMatrix(const FloatArrayF< 3 > &sigma, + const double deltaLambda, + int transitionFlag, + GaussPoint *gp) const; + + FloatArrayF< 6 >giveLatticeStress3d(const FloatArrayF< 6 > &jump, GaussPoint *gp, TimeStep *tStep) override; + + + FloatArrayF< 3 >performPlasticityReturn(GaussPoint *gp, const FloatArrayF< 3 > &totalStrain, TimeStep *) const; + + double performRegularReturn(FloatArrayF< 3 > &stress, + LatticeBondPlasticity_ReturnResult &returnResult, + LatticeBondPlasticity_SurfaceType &surfaceType, + double yieldValue, + int transitionFlag, + GaussPoint *gp) const; + + double computeYieldValue(const FloatArrayF< 3 > &sigma, + const double tempKappa, + int transitionFlag, + GaussPoint *gp) const; + + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + virtual FloatArrayF< 6 >giveReducedStrain(GaussPoint *gp, TimeStep *tStep) const; +}; +} // end namespace oofem +#endif diff --git a/src/sm/Materials/LatticeMaterials/latticedamage.C b/src/sm/Materials/LatticeMaterials/latticedamage.C new file mode 100644 index 000000000..1747fb8d2 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticedamage.C @@ -0,0 +1,659 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticedamage.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "CrossSections/latticecrosssection.h" +#include "engngm.h" +#include "mathfem.h" +#include "Elements/LatticeElements/latticestructuralelement.h" +#include "datastream.h" +#include "staggeredproblem.h" +#include "contextioerr.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(LatticeDamage); + +LatticeDamage :: LatticeDamage(int n, Domain *d) : LatticeLinearElastic(n, d) +{} + + +bool +LatticeDamage :: hasMaterialModeCapability(MaterialMode mode) const +{ + return ( mode == _3dLattice ); +} + + +void +LatticeDamage :: initializeFrom(InputRecord &ir) +{ + LatticeLinearElastic :: initializeFrom(ir); + + softeningType = 1; + IR_GIVE_OPTIONAL_FIELD(ir, softeningType, _IFT_LatticeDamage_softeningType); // Macro + + IR_GIVE_FIELD(ir, wf, _IFT_LatticeDamage_wf); // Macro + + if ( softeningType == 2 ) { //bilinear softening + wfOne = 0.15 * wf; + IR_GIVE_OPTIONAL_FIELD(ir, wfOne, _IFT_LatticeDamage_wfOne); // Macro + e0OneMean = 0.3 * e0Mean; + IR_GIVE_OPTIONAL_FIELD(ir, e0OneMean, _IFT_LatticeDamage_e0OneMean); + } + + IR_GIVE_OPTIONAL_FIELD(ir, e0Mean, _IFT_LatticeDamage_e0Mean); // Macro + + this->coh = 2.; + IR_GIVE_OPTIONAL_FIELD(ir, coh, _IFT_LatticeDamage_coh); // Macro + + this->ec = 10.; + IR_GIVE_OPTIONAL_FIELD(ir, ec, _IFT_LatticeDamage_ec); // Macro + + this->biotCoefficient = 0.; + IR_GIVE_OPTIONAL_FIELD(ir, this->biotCoefficient, _IFT_LatticeDamage_bio); + + this->biotType = 0; + IR_GIVE_OPTIONAL_FIELD(ir, this->biotType, _IFT_LatticeDamage_btype); +} + + +double +LatticeDamage :: computeEquivalentStrain(const FloatArrayF< 6 > &strain, GaussPoint *gp) const +{ + const double e0 = this->give(e0_ID, gp) * this->e0Mean; + double paramA = 0.5 * ( e0 + ec * e0 ); + double paramB = ( coh * e0 ) / sqrt(1. - pow( ( ec * e0 - e0 ) / ( e0 + ec * e0 ), 2. ) ); + double paramC = 0.5 * ( this->ec * e0 - e0 ); + + double shearNorm = norm(strain [ { 1, 2 } ]); + return norm({ this->alphaOne * shearNorm / paramB, ( strain.at(1) + paramC ) / paramA }) * paramA - paramC; +} + + +double +LatticeDamage :: computeDamageParam(double tempKappa, GaussPoint *gp) const +{ + double le = static_cast< LatticeStructuralElement * >( gp->giveElement() )->giveLength(); + const double e0 = this->give(e0_ID, gp) * this->e0Mean; + double eNormal = this->give(eNormal_ID, gp) * this->eNormalMean; + + if ( softeningType == 1 ) { //linear + if ( tempKappa >= e0 && tempKappa < this->wf / le ) { + //linear stress-crack opening relation + //check if input parameter make sense + if ( this->wf / le <= e0 ) { + OOFEM_ERROR("e0>wf/Le \n Possible solutions: Increase fracture energy or reduce element size\n"); + } + + return ( 1. - e0 / tempKappa ) / ( 1. - e0 / ( this->wf / le ) ); + } else if ( tempKappa >= this->wf / le ) { + return 1.; + } else { + return 0.; + } + } else if ( softeningType == 2 ) { //bilinear softening + //Check if input parameter make sense + if ( e0 > wfOne / le ) { + OOFEM_ERROR("parameter wf1 is too small"); + } else if ( wfOne / le > this->wf / le ) { + OOFEM_ERROR("parameter wf is too small"); + } + + if ( tempKappa > e0 ) { + double helpStrain = 0.3 * e0; + double omega = ( 1 - e0 / tempKappa ) / ( ( helpStrain - e0 ) / this->wfOne * le + 1. ); + + if ( omega * tempKappa * le > 0 && omega * tempKappa * le < this->wfOne ) { + return omega; + } else { + omega = ( 1. - helpStrain / tempKappa - helpStrain * this->wfOne / ( tempKappa * ( this->wf - this->wfOne ) ) ) / ( 1. - helpStrain * le / ( this->wf - this->wfOne ) ); + + if ( omega * tempKappa * le >= this->wfOne && omega * tempKappa * le < this->wf ) { + return omega; + } + } + + return clamp(omega, 0., 1.); + } else { + return 0.; + } + } else if ( softeningType == 3 ) { + //exponential softening + // iteration to achieve objectivity + // we are finding state, where elastic stress is equal to + // stress from crack-opening relation (wf = wf characterizes the carc opening diagram) + if ( tempKappa <= e0 ) { + return 0.0; + } else { + int nite = 0; + double R = 0., omega = 0.; + double Ft = eNormal * e0; + do { + nite++; + double help = le * omega * tempKappa / this->wf; + double Lhs = eNormal * tempKappa - Ft * exp(-help) * le * tempKappa / this->wf; + R = ( 1. - omega ) * eNormal * tempKappa - Ft * exp(-help); + omega += R / Lhs; + if ( nite > 40 ) { + OOFEM_ERROR("computeDamageParam: algorithm not converging"); + } + } while ( fabs(R) >= 1.e-4 ); + + if ( ( omega > 1.0 ) || ( omega < 0.0 ) ) { + OOFEM_ERROR("computeDamageParam: internal error\n"); + } + return omega; + } + } else { + OOFEM_ERROR("computeDamageParam: unknown softening type"); + } +} + + +MaterialStatus * +LatticeDamage :: CreateStatus(GaussPoint *gp) const +{ + return new LatticeDamageStatus(gp); +} + + +FloatMatrixF< 6, 6 > +LatticeDamage :: give3dLatticeStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto elastic = LatticeLinearElastic :: give3dLatticeStiffnessMatrix(mode, gp, tStep); + + if ( mode == ElasticStiffness ) { + return elastic; + } else if ( ( mode == SecantStiffness ) || ( mode == TangentStiffness ) ) { + auto status = static_cast< LatticeDamageStatus * >( this->giveStatus(gp) ); + + double omega = min(status->giveTempDamage(), 0.99999); + return elastic * ( 1. - omega ); + } else { + OOFEM_ERROR("Unsupported stiffness mode\n"); + return elastic; + } +} + + +FloatMatrixF< 3, 3 > +LatticeDamage :: give2dLatticeStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + + auto elastic = LatticeLinearElastic :: give2dLatticeStiffnessMatrix(mode, gp, tStep); + + if ( mode == ElasticStiffness ) { + return elastic; + } else if ( ( mode == SecantStiffness ) || ( mode == TangentStiffness ) ) { + auto status = static_cast< LatticeDamageStatus * >( this->giveStatus(gp) ); + double omega = status->giveTempDamage(); + + if ( omega > 0.99999 ) { + omega = 0.99999; + } + + return elastic * ( 1. - omega ); + } else { + OOFEM_ERROR("Unsupported stiffness mode\n"); + return elastic; + } +} + + +FloatArrayF< 6 > +LatticeDamage :: giveLatticeStress3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) +{ + auto status = static_cast< LatticeDamageStatus * >( this->giveStatus(gp) ); + + const double e0 = this->give(e0_ID, gp) * this->e0Mean; + + status->setE0(e0); + this->initTempStatus(gp); + + // substract stress independent part + auto reducedStrain = strain; + auto thermalStrain = this->computeStressIndependentStrainVector(gp, tStep, VM_Total); + if ( thermalStrain.giveSize() ) { + reducedStrain -= FloatArrayF< 6 >(thermalStrain); + } + + double omega = 0.; + this->performDamageEvaluation(gp, reducedStrain); + omega = status->giveTempDamage(); + + auto stiffnessMatrix = LatticeLinearElastic :: give3dLatticeStiffnessMatrix(ElasticStiffness, gp, tStep); + + FloatArrayF< 6 >answer; + for ( int i = 1; i <= 6; i++ ) { // only diagonal terms matter + answer.at(i) = stiffnessMatrix.at(i, i) * reducedStrain.at(i) * ( 1. - omega ); + } + + //Read in fluid pressures from structural element if this is not a slave problem + FloatArray pressures; + if ( !domain->giveEngngModel()->giveMasterEngngModel() ) { + static_cast< LatticeStructuralElement * >( gp->giveElement() )->givePressures(pressures); + } + + double waterPressure = 0.; + for ( int i = 0; i < pressures.giveSize(); i++ ) { + waterPressure += 1. / pressures.giveSize() * pressures [ i ]; + } + answer.at(1) += waterPressure; + + double tempDeltaDissipation = computeDeltaDissipation3d(omega, reducedStrain, gp, tStep); + double tempDissipation = status->giveDissipation() + tempDeltaDissipation; + + //Set all temp values + status->setTempDissipation(tempDissipation); + status->setTempDeltaDissipation(tempDeltaDissipation); + + status->letTempLatticeStrainBe(strain); + status->letTempReducedLatticeStrainBe(reducedStrain); + status->letTempLatticeStressBe(answer); + status->setTempNormalLatticeStress(answer.at(1) ); + + return answer; +} + + +void +LatticeDamage :: performDamageEvaluation(GaussPoint *gp, FloatArrayF< 6 > &reducedStrain) const +{ + auto status = static_cast< LatticeDamageStatus * >( this->giveStatus(gp) ); + // compute equivalent strain + double equivStrain = this->computeEquivalentStrain(reducedStrain, gp); + + // compute value of loading function if strainLevel crit apply + double f = equivStrain - status->giveKappa(); + + double tempKappa, omega = 0.; + if ( f <= 0.0 ) { + // damage does not grow + tempKappa = status->giveKappa(); + omega = status->giveDamage(); + if ( status->giveCrackFlag() != 0 ) { + status->setTempCrackFlag(2); + } else { + status->setTempCrackFlag(0); + } + } else { + // damage grows + tempKappa = equivStrain; + + // evaluate damage parameter + + omega = this->computeDamageParam(tempKappa, gp); + if ( omega > 0 ) { + status->setTempCrackFlag(1); + } + } + + //Create history variables for the damage strain + FloatArrayF< 6 >tempDamageLatticeStrain = omega * reducedStrain; + status->letTempDamageLatticeStrainBe(tempDamageLatticeStrain); + + //Compute crack width + double length = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveLength(); + double crackWidth = omega * norm(reducedStrain [ { 0, 1, 2 } ]) * length; + + status->setTempEquivalentStrain(equivStrain); + status->setTempKappa(tempKappa); + status->setTempDamage(omega); + status->setTempCrackWidth(crackWidth); +} + +double +LatticeDamage :: computeBiot(double omega, double kappa, double le) const +{ + if ( this->softeningType == 1 || this->softeningType == 3 ) { + if ( omega == 0 ) { + return this->biotCoefficient; + } else if ( omega * kappa * le > 0 && omega * kappa * le < this->wf ) { + return this->biotCoefficient + ( 1. - biotCoefficient ) * omega * kappa * le / this->wf; + } else { + return 1.; + } + } else { + OOFEM_ERROR("Wrong stype for btype=1. Only linear and exponential softening considered so far\n"); + return 0.; + } +} + + +double +LatticeDamage :: computeReferenceGf(GaussPoint *gp) const +{ + const double e0 = this->give(e0_ID, gp) * this->e0Mean; + const double eNormal = this->give(eNormal_ID, gp) * this->eNormalMean; + if ( softeningType == 1 ) { + return e0 * eNormal * this->wf / 2.; + } else { //This is for the exponential law. Should also implement it for the bilinear one. + return e0 * eNormal * this->wf; + } +} + + +double +LatticeDamage :: computeIntervals(double testDissipation, double referenceGf) const +{ + if ( testDissipation / ( referenceGf ) > 0.01 ) { + return 1000. * min(testDissipation / referenceGf, 1.); + } else { + return 1.; + } +} + + +double +LatticeDamage :: computeDeltaDissipation2d(double omega, + const FloatArrayF< 3 > &reducedStrain, + GaussPoint *gp, + TimeStep *tStep) const +{ + auto status = static_cast< LatticeDamageStatus * >( this->giveStatus(gp) ); + const double length = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveLength(); + const double eNormal = this->give(eNormal_ID, gp) * this->eNormalMean; + const double eShear = this->alphaOne * eNormal; + const double eTorsion = this->alphaTwo * eNormal; + const FloatArrayF< 3 >tangent = { eNormal, eShear, eTorsion }; + + const auto reducedStrainOld = status->giveReducedLatticeStrain() [ { 0, 1, 5 } ]; + const double omegaOld = status->giveDamage(); + + auto oldIntermediateStrain = reducedStrainOld; + double oldIntermediateOmega = omegaOld; + double deltaOmega = ( omega - omegaOld ); + auto testStrain = ( reducedStrain + reducedStrainOld ) * 0.5; + auto testStress = mult(tangent, testStrain); + double testDissipation = 0.5 * length * norm(testStress) * deltaOmega; + + double referenceGf = computeReferenceGf(gp); + double intervals = computeIntervals(testDissipation, referenceGf); + + double oldKappa = status->giveKappa(); + if ( deltaOmega > 0 ) { + double tempDeltaDissipation = 0.; + for ( int k = 0; k < intervals; k++ ) { + auto intermediateStrain = reducedStrainOld + ( k + 1 ) / intervals * ( reducedStrain - reducedStrainOld ); + double equivStrain = this->computeEquivalentStrain(assemble< 6 >(intermediateStrain, { 0, 1, 5 }), gp); + double f = equivStrain - oldKappa; + if ( f > 0 ) { + auto intermediateOmega = this->computeDamageParam(equivStrain, gp); + auto deltaOmega = ( intermediateOmega - oldIntermediateOmega ); + auto midStrain = ( intermediateStrain + oldIntermediateStrain ) / 2.; + auto midStress = mult(tangent, midStrain); + auto deltaTempDeltaDissipation = 0.5 * length * norm(midStress) * deltaOmega; + oldKappa = equivStrain; + oldIntermediateOmega = intermediateOmega; + tempDeltaDissipation += deltaTempDeltaDissipation; + } + + oldIntermediateStrain = intermediateStrain; + } + return max(tempDeltaDissipation, 2. * referenceGf); + } else { + return 0.; + } +} + + +double +LatticeDamage :: computeDeltaDissipation3d(double omega, + const FloatArrayF< 6 > &reducedStrain, + GaussPoint *gp, + TimeStep *atTime) const +{ + auto status = static_cast< LatticeDamageStatus * >( this->giveStatus(gp) ); + const double length = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveLength(); + const double eNormal = this->give(eNormal_ID, gp) * this->eNormalMean; + const double eShear = this->alphaOne * eNormal; + const double eTorsion = this->alphaTwo * eNormal; + const FloatArrayF< 6 >tangent = { eNormal, eShear, eShear, eTorsion, eTorsion, eTorsion }; + + const auto &reducedStrainOld = status->giveReducedLatticeStrain(); + const double omegaOld = status->giveDamage(); + + auto oldIntermediateStrain = reducedStrainOld; + double oldIntermediateOmega = omegaOld; + double deltaOmega = ( omega - omegaOld ); + auto testStrain = ( reducedStrain + reducedStrainOld ) * 0.5; + auto testStress = mult(tangent, testStrain); + double testDissipation = 0.5 * length * norm(testStress) * deltaOmega; + + double referenceGf = computeReferenceGf(gp); + double intervals = computeIntervals(testDissipation, referenceGf); + + double oldKappa = status->giveKappa(); + if ( deltaOmega > 0 ) { + double tempDeltaDissipation = 0.; + for ( int k = 0; k < intervals; k++ ) { + auto intermediateStrain = reducedStrainOld + ( k + 1 ) / intervals * ( reducedStrain - reducedStrainOld ); + double equivStrain = this->computeEquivalentStrain(intermediateStrain, gp); + double f = equivStrain - oldKappa; + if ( f > 0 ) { + auto intermediateOmega = this->computeDamageParam(equivStrain, gp); + auto deltaOmega = ( intermediateOmega - oldIntermediateOmega ); + auto midStrain = ( intermediateStrain + oldIntermediateStrain ) / 2.; + auto midStress = mult(tangent, midStrain); + auto deltaTempDeltaDissipation = 0.5 * length * norm(midStress) * deltaOmega; + oldKappa = equivStrain; + oldIntermediateOmega = intermediateOmega; + tempDeltaDissipation += deltaTempDeltaDissipation; + } + + oldIntermediateStrain = intermediateStrain; + } + return max(tempDeltaDissipation, 2. * referenceGf); + } else { + return 0.; + } +} + + +double +LatticeDamage :: give(int aProperty, GaussPoint *gp) const +{ + this->giveStatus(gp); + + double answer; + if ( RandomMaterialExtensionInterface :: give(aProperty, gp, answer) ) { + if ( answer < 0.1 ) { //Introduce cut off to avoid numerical problems + answer = 0.1; + } else if ( answer > 10 ) { + answer = 10; + } + return answer; + } else if ( aProperty == e0_ID ) { + return 1.; + } else if ( aProperty == ef_ID ) { + return 1.; + } else { + return LatticeLinearElastic :: give(aProperty, gp); + } +} + +int +LatticeDamage :: giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) +{ + LatticeDamageStatus *status = static_cast< LatticeDamageStatus * >( this->giveStatus(gp) ); + if ( type == IST_CrackedFlag ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveCrackFlag(); + return 1; + } else if ( type == IST_DamageScalar ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveDamage(); + return 1; + } else if ( type == IST_DamageTensor ) { + answer.resize(6); + answer.zero(); + answer.at(1) = answer.at(2) = answer.at(3) = status->giveDamage(); + return 1; + } else if ( type == IST_DissWork ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveDissipation(); + return 1; + } else if ( type == IST_DeltaDissWork ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveDeltaDissipation(); + return 1; + } else if ( type == IST_CrackWidth ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveCrackWidth(); + return 1; + } else if ( type == IST_NormalStress ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveNormalLatticeStress(); + return 1; + } else if ( type == IST_CharacteristicLength ) { + answer.resize(1); + answer.zero(); + answer.at(1) = static_cast< LatticeStructuralElement * >( gp->giveElement() )->giveLength(); + return 1; + } else { + return LatticeLinearElastic :: giveIPValue(answer, gp, type, atTime); + } +} + +LatticeDamageStatus :: LatticeDamageStatus(GaussPoint *g) : + LatticeMaterialStatus(g) +{ } + +void +LatticeDamageStatus :: initTempStatus() +{ + LatticeMaterialStatus :: initTempStatus(); + + this->tempKappa = this->kappa; + this->tempEquivStrain = this->equivStrain; + this->tempDamage = this->damage; +} + +void +LatticeDamageStatus :: printOutputAt(FILE *file, TimeStep *tStep) const +{ + LatticeMaterialStatus :: printOutputAt(file, tStep); + fprintf(file, "kappa %f, equivStrain %f, damage %f, dissipation %f, deltaDissipation %f, e0 %f, crackFlag %d\n", this->kappa, this->equivStrain, this->damage, this->dissipation, this->deltaDissipation, this->e0, this->crackFlag); +} + + +void +LatticeDamageStatus :: updateYourself(TimeStep *atTime) +// +// updates variables (nonTemp variables describing situation at previous equilibrium state) +// after a new equilibrium state has been reached +// temporary variables are having values corresponding to newly reached equilibrium. +// +{ + LatticeMaterialStatus :: updateYourself(atTime); + + this->kappa = this->tempKappa; + this->equivStrain = this->tempEquivStrain; + this->damage = this->tempDamage; +} + +void +LatticeDamageStatus :: saveContext(DataStream &stream, ContextMode mode) +// +// saves full information stored in this Status +// no temp variables stored +// +{ + LatticeMaterialStatus :: saveContext(stream, mode); + + if ( !stream.write(kappa) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(equivStrain) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(damage) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(e0) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(biot) ) { + THROW_CIOERR(CIO_IOERR); + } +} + +void +LatticeDamageStatus :: restoreContext(DataStream &stream, ContextMode mode) +// +// restores full information stored in stream to this Status +// +{ + LatticeMaterialStatus :: restoreContext(stream, mode); + + if ( !stream.read(kappa) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(equivStrain) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(damage) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(e0) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(biot) ) { + THROW_CIOERR(CIO_IOERR); + } +} +} // end namespace oofem diff --git a/src/sm/Materials/LatticeMaterials/latticedamage.h b/src/sm/Materials/LatticeMaterials/latticedamage.h new file mode 100644 index 000000000..891ab8a5b --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticedamage.h @@ -0,0 +1,230 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticedamage_h +#define latticedamage_h + +#include "latticelinearelastic.h" +#include "latticematstatus.h" +#include "randommaterialext.h" + +///@name Input fields for LatticeDamage +//@{ +#define _IFT_LatticeDamage_Name "latticedamage" +#define _IFT_LatticeDamage_softeningType "stype" +#define _IFT_LatticeDamage_wf "wf" +#define _IFT_LatticeDamage_wfOne "wf1" +#define _IFT_LatticeDamage_e0Mean "e0" +#define _IFT_LatticeDamage_e0OneMean "e01" +#define _IFT_LatticeDamage_coh "coh" +#define _IFT_LatticeDamage_ec "ec" +#define _IFT_LatticeDamage_bio "bio" + +#define _IFT_LatticeDamage_btype "btype" +//@} + +namespace oofem { +/** + * This class implements associated Material Status to LatticeDamage. + */ +class LatticeDamageStatus : public LatticeMaterialStatus +{ +protected: + + + /// scalar measure of the largest strain level ever reached in material + double kappa = 0.; + + /// non-equilibrated scalar measure of the largest strain level + double tempKappa = 0.; + + /// scalar measure of the largest strain level ever reached in material + double equivStrain = 0.; + + /// non-equilibrated scalar measure of the largest strain level + double tempEquivStrain = 0.; + + /// damage level of material + double damage = 0.; + + /// non-equilibrated damage level of material + double tempDamage = 0.; + + /// random material parameter stored in status, since each gp has a differnet value. + double e0 = 0.; + + /// computed biot coefficient + double biot = 0.; + +public: + LatticeDamageStatus(GaussPoint *g); + + /// Returns the last equilibrated scalar measure of the largest strain level + double giveKappa() const { return kappa; } + /// Returns the temp. scalar measure of the largest strain level + double giveTempKappa() const { return tempKappa; } + + /// Sets the temp scalar measure of the largest strain level to given value + void setTempKappa(double newKappa) { tempKappa = newKappa; } + + /// Returns the last equilibrated scalar measure of the largest strain level + double giveEquivalentStrain() const { return equivStrain; } + /// Returns the temp. scalar measure of the largest strain level + double giveTempEquivalentStrain() const { return tempEquivStrain; } + /// Sets the temp scalar measure of the largest strain level to given value + void setTempEquivalentStrain(double newEquivStrain) { tempEquivStrain = newEquivStrain; } + + + /// Returns the last equilibrated damage level + double giveDamage() const { return damage; } + /// Returns the temp. damage level + double giveTempDamage() const { return tempDamage; } + /// Sets the temp damage level to given value + void setTempDamage(double newDamage) { tempDamage = newDamage; } + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + + const char *giveClassName() const override { return "LatticeDamageStatus"; } + + void initTempStatus() override; + + void updateYourself(TimeStep *) override; + + ///Set random e0 + void setE0(double val) { e0 = val; } + + void setBiotCoefficientInStatus(double variable) { biot = variable; } + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; +}; + + +/** + * This class implements a local random damage model for quasi-brittle materials for lattice (1D, 2D and 3D) elements. + */ +class LatticeDamage : public LatticeLinearElastic +{ +protected: + + + /// max effective strain at peak + double e0Mean = 0.; + double e0OneMean = 0.; + + ///tensile strength + double ftMean = 0.; + double ftOneMean = 0.; + + /**parameter which determines the typ of the softeningFunction + * 1 = linear softening + * 2 = bilinear softening + * 3 = exponential softening + **/ + int softeningType = 0.; + + /// determines the softening -> corresponds to crack opening when tension stress vanishes + double wf = 0., wfOne = 0.; + + double ultimateFactor = 0.; + + //parameter for the elliptic equivalent strain function + double coh = 0.; + + //parameter for the elliptic equivalent strain function + double ec = 0.; + + /// flag which chooses between no distribution (0) and Gaussian distribution (1) + double localRandomType = 0.; + + /// Biot's coefficient + double biotCoefficient = 0.; + + /// Parameter specifying how the biot coefficient changes with the crack opening + int biotType = 0; + + +public: + LatticeDamage(int n, Domain *d); + + const char *giveInputRecordName() const override { return _IFT_LatticeDamage_Name; } + const char *giveClassName() const override { return "LatticeDamage"; } + + bool hasAnalyticalTangentStiffness() const override { return true; } + + void initializeFrom(InputRecord &ir) override; + + + FloatArrayF< 6 >giveLatticeStress3d(const FloatArrayF< 6 > &jump, GaussPoint *gp, TimeStep *tStep) override; + + FloatMatrixF< 6, 6 >give3dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatMatrixF< 3, 3 >give2dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + + + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + + bool hasMaterialModeCapability(MaterialMode mode) const override; + + void performDamageEvaluation(GaussPoint *gp, FloatArrayF< 6 > &reducedStrain) const; + + virtual double computeEquivalentStrain(const FloatArrayF< 6 > &strain, GaussPoint *gp) const; + + virtual double computeBiot(double omega, double kappa, double le) const; + + virtual double computeDamageParam(double kappa, GaussPoint *gp) const; + ///Compute increment of dissipation for post-processing reasons + double computeDeltaDissipation2d(double omega, const FloatArrayF< 3 > &reducedStrain, GaussPoint *gp, TimeStep *atTime) const; + + double computeDeltaDissipation3d(double omega, const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *atTime) const; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + double give(int aProperty, GaussPoint *gp) const override; + + +protected: + double computeReferenceGf(GaussPoint *gp) const; + double computeIntervals(double testDissipation, double referenceGf) const; + + int giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) override; +}; +} // end namespace oofem + +#endif diff --git a/src/sm/Materials/LatticeMaterials/latticedamageviscoelastic.C b/src/sm/Materials/LatticeMaterials/latticedamageviscoelastic.C new file mode 100644 index 000000000..d66b5aa75 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticedamageviscoelastic.C @@ -0,0 +1,304 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticedamageviscoelastic.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "Elements/LatticeElements/latticestructuralelement.h" +#include "datastream.h" +#include "contextioerr.h" +#include "classfactory.h" +#include "math.h" + + +namespace oofem { +REGISTER_Material(LatticeDamageViscoelastic); + +LatticeDamageViscoelastic :: LatticeDamageViscoelastic(int n, Domain *d) : LatticeDamage(n, d) +{} + +void +LatticeDamageViscoelastic :: initializeFrom(InputRecord &ir) +{ + LatticeDamage :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, viscoMat, _IFT_LatticeDamageViscoelastic_viscoMat); // number of slave material + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + // override elastic modulus by the one given by the compliance function + double timeFactor = 0.; + IR_GIVE_FIELD(ir, timeFactor, _IFT_LatticeDamageViscoelastic_timeFactor); // timeConversion equal to 1 day in current time units of the analysis + + double E28 = 1. / rheoMat->computeCreepFunction(timeFactor * 28.01, timeFactor * 28., NULL, NULL); // modulus of elasticity evaluated at 28 days, duration of loading 15 min + this->e0Mean *= ( this->eNormalMean / E28 ); // transform strain at peak stress accordingly + this->eNormalMean = E28; // swap elastic modulus/stiffness +} + + +MaterialStatus * +LatticeDamageViscoelastic :: CreateStatus(GaussPoint *gp) const +{ + return new LatticeDamageViscoelasticStatus(gp); +} + + +FloatArrayF< 6 > +LatticeDamageViscoelastic :: giveLatticeStress3d(const FloatArrayF< 6 > &totalStrain, + GaussPoint *gp, + TimeStep *tStep) +{ + double tol = 1.e-12; // error in order of Pascals + + auto *status = static_cast< LatticeDamageViscoelasticStatus * >( this->giveStatus(gp) ); + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + GaussPoint *rChGP = status->giveSlaveGaussPointVisco(); + // just a dummy yet essential call to create a status of viscomaterial. Otherwise initTempStatus() would fail. + rheoMat->giveStatus(rChGP); + + // the value from the status seems to be unused except for printout + status->setE0(this->give(e0_ID, gp) * this->e0Mean); + status->initTempStatus(); + + FloatArrayF< 6 >reducedStrain; + FloatArrayF< 6 >quasiReducedStrain; + + FloatArrayF< 6 >stress; + FloatArrayF< 6 >tempStress; + FloatArray viscoStress; + + FloatArray indepStrain; + + int itercount = 1; + double tolerance = 1.; + + // componentes which do not change during iterations + indepStrain = this->computeStressIndependentStrainVector(gp, tStep, VM_Total); + auto elasticStiffnessMatrix = LatticeLinearElastic :: give3dLatticeStiffnessMatrix(ElasticStiffness, gp, tStep); + + do { + if ( itercount > 100 ) { + printf("tolerance = %e and itercount = %d\n", tolerance, itercount); + OOFEM_ERROR("Algorithm not converging"); + } + + //total strain + reducedStrain = totalStrain; + + if ( indepStrain.giveSize() > 0 ) { + reducedStrain -= FloatArrayF< 6 >(indepStrain); + } + + FloatArrayF< 6 >tempDamageLatticeStrain = status->giveTempDamageLatticeStrain(); + reducedStrain -= FloatArrayF< 6 >(tempDamageLatticeStrain); + + rheoMat->giveRealStressVector(viscoStress, rChGP, reducedStrain, tStep); + tempStress = FloatArrayF< 6 >(viscoStress); + + for ( int i = 1; i <= 6; i++ ) { // only diagonal terms matter + quasiReducedStrain.at(i) = tempStress.at(i) / elasticStiffnessMatrix.at(i, i); + } + + quasiReducedStrain += tempDamageLatticeStrain; + + LatticeDamage :: performDamageEvaluation(gp, quasiReducedStrain); + double tempDamage = status->giveTempDamage(); + + for ( int i = 1; i <= 6; i++ ) { // only diagonal terms matter + stress.at(i) = elasticStiffnessMatrix.at(i, i) * quasiReducedStrain.at(i) * ( 1. - tempDamage ); + } + + tolerance = norm(stress - tempStress) / this->eNormalMean; + + itercount++; + } while ( tolerance >= tol ); + + status->letTempLatticeStrainBe(totalStrain); + status->letTempLatticeStressBe(tempStress); + status->letTempReducedLatticeStrainBe(quasiReducedStrain); + + return tempStress; +} + + + +FloatMatrixF< 6, 6 > +LatticeDamageViscoelastic :: give3dLatticeStiffnessMatrix(MatResponseMode rmode, + GaussPoint *gp, + TimeStep *tStep) const +{ + LatticeDamageViscoelasticStatus *status = static_cast< LatticeDamageViscoelasticStatus * >( this->giveStatus(gp) ); + GaussPoint *slaveGp; + + + // get status of the slave viscoelastic material + slaveGp = status->giveSlaveGaussPointVisco(); + // get viscoelastic material + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + double Eincr = rheoMat->giveEModulus(slaveGp, tStep); + + auto answer = LatticeLinearElastic :: give3dLatticeStiffnessMatrix(ElasticStiffness, gp, tStep); + + answer *= ( Eincr / this->eNormalMean ); + + return answer; +} + +FloatMatrixF< 3, 3 > +LatticeDamageViscoelastic :: give2dLatticeStiffnessMatrix(MatResponseMode rmode, + GaussPoint *gp, + TimeStep *tStep) const +{ + LatticeDamageViscoelasticStatus *status = static_cast< LatticeDamageViscoelasticStatus * >( this->giveStatus(gp) ); + GaussPoint *slaveGp; + + + // get status of the slave viscoelastic material + slaveGp = status->giveSlaveGaussPointVisco(); + // get viscoelastic material + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + double Eincr = rheoMat->giveEModulus(slaveGp, tStep); + + auto answer = LatticeLinearElastic :: give2dLatticeStiffnessMatrix(ElasticStiffness, gp, tStep); + + answer *= ( Eincr / this->eNormalMean ); + + return answer; +} + + + +int +LatticeDamageViscoelastic :: giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *tStep) +{ + if ( ( type == IST_DryingShrinkageTensor ) || + ( type == IST_AutogenousShrinkageTensor ) || + ( type == IST_TotalShrinkageTensor ) || + ( type == IST_CreepStrainTensor ) || + ( type == IST_DryingShrinkageTensor ) || + ( type == IST_ThermalStrainTensor ) ) { + LatticeDamageViscoelasticStatus *status = static_cast< LatticeDamageViscoelasticStatus * >( this->giveStatus(gp) ); + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + return rheoMat->giveIPValue(answer, status->giveSlaveGaussPointVisco(), type, tStep); + } + + return LatticeDamage :: giveIPValue(answer, gp, type, tStep); +} + + +int LatticeDamageViscoelastic :: checkConsistency() +{ + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + if ( rheoMat->giveAlphaOne() != this->alphaOne ) { + OOFEM_ERROR("a1 must be set to the same value in both master and viscoelastic slave materials"); + } + + if ( rheoMat->giveAlphaTwo() != this->alphaTwo ) { + OOFEM_ERROR("a2 must be set to the same value in both master and viscoelastic slave materials"); + } + + GaussPoint *noGP = NULL; + if ( rheoMat->give(tAlpha, noGP) != 0. ) { + OOFEM_ERROR("tAlpha must be set to 0. in slave viscoelastic material"); + } + + return FEMComponent :: checkConsistency(); +} + + +LatticeDamageViscoelasticStatus :: LatticeDamageViscoelasticStatus(GaussPoint *g) : + LatticeDamageStatus(g), slaveGpVisco(std :: make_unique< GaussPoint >(gp->giveIntegrationRule(), 0, gp->giveNaturalCoordinates(), 0., gp->giveMaterialMode() ) ) +{} + + +void +LatticeDamageViscoelasticStatus :: initTempStatus() +{ + LatticeDamageStatus :: initTempStatus(); + + // at this point rheomat :: giveStatus (viscoGP) has to be called first + RheoChainMaterialStatus *rheoStatus = static_cast< RheoChainMaterialStatus * >( this->giveSlaveGaussPointVisco()->giveMaterialStatus() ); + + rheoStatus->initTempStatus(); +} + + +void +LatticeDamageViscoelasticStatus :: printOutputAt(FILE *file, TimeStep *tStep) const +{ + LatticeDamageStatus :: printOutputAt(file, tStep); + fprintf(file, "\nViscoelastic material:"); + + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->printOutputAt(file, tStep); + + fprintf(file, "\n"); +} + + +void +LatticeDamageViscoelasticStatus :: updateYourself(TimeStep *tStep) +{ + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->updateYourself(tStep); + + LatticeDamageStatus :: updateYourself(tStep); +} + +void +LatticeDamageViscoelasticStatus :: saveContext(DataStream &stream, ContextMode mode) +{ + // save parent class status + LatticeDamageStatus :: saveContext(stream, mode); + + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->saveContext(stream, mode); +} + +void +LatticeDamageViscoelasticStatus :: restoreContext(DataStream &stream, ContextMode mode) +{ + // read parent class status + LatticeDamageStatus :: restoreContext(stream, mode); + + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->restoreContext(stream, mode); +} +} // end namespace oofem diff --git a/src/sm/Materials/LatticeMaterials/latticedamageviscoelastic.h b/src/sm/Materials/LatticeMaterials/latticedamageviscoelastic.h new file mode 100644 index 000000000..4a34217c5 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticedamageviscoelastic.h @@ -0,0 +1,136 @@ + +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticedamageviscoelastic_h +#define latticedamageviscoelastic_h + +#include "latticedamage.h" +#include "../RheoChainMaterials/rheoChM.h" + +///@name Input fields for LatticeDamage +//@{ +#define _IFT_LatticeDamageViscoelastic_Name "latticedamageviscoelastic" +#define _IFT_LatticeDamageViscoelastic_viscoMat "viscomat" +#define _IFT_LatticeDamageViscoelastic_timeFactor "timefactor" + +//@} + +namespace oofem { +/** + * This class implements associated Material Status to LatticeDamageViscoelastic. + * @author: Petr Havlasek + */ +class LatticeDamageViscoelasticStatus : public LatticeDamageStatus + +{ +protected: + std :: unique_ptr< GaussPoint >slaveGpVisco; + +public: + + /// Constructor + LatticeDamageViscoelasticStatus(GaussPoint *g); + + /// Prints the receiver state to given stream + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + + const char *giveClassName() const override { return "LatticeDamageViscoelasticStatus"; } + + void initTempStatus() override; + + void updateYourself(TimeStep *) override; // update after new equilibrium state reached + + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; + + GaussPoint *giveSlaveGaussPointVisco() const { return this->slaveGpVisco.get(); } +}; + + +/** + * This class implements a local viscoelastic model for concrete in tension for 3D lattice elements. + * @author: Petr Havlasek + */ +class LatticeDamageViscoelastic : public LatticeDamage + +{ +protected: + /// 'slave' (= viscoelastic) material model number. + int viscoMat = 0; + + +public: + + /// Constructor + LatticeDamageViscoelastic(int n, Domain *d); + + const char *giveInputRecordName() const override { return _IFT_LatticeDamageViscoelastic_Name; } + const char *giveClassName() const override { return "LatticeDamageViscoelastic"; } + + void initializeFrom(InputRecord &ir) override; + + + FloatMatrixF< 6, 6 >give3dLatticeStiffnessMatrix(MatResponseMode rmode, + GaussPoint *gp, + TimeStep *atTime) const override; + + FloatMatrixF< 3, 3 >give2dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + + + FloatArrayF< 6 >giveLatticeStress3d(const FloatArrayF< 6 > &totalStrain, + GaussPoint *gp, + TimeStep *tStep) override; + + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + RheoChainMaterial *giveViscoelasticMaterial(); + +protected: + + int giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) override; + + int checkConsistency(void) override; +}; +} // end namespace oofem + + +#endif diff --git a/src/sm/Materials/LatticeMaterials/latticeframeconcreteplastic.C b/src/sm/Materials/LatticeMaterials/latticeframeconcreteplastic.C new file mode 100644 index 000000000..6d394b898 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeframeconcreteplastic.C @@ -0,0 +1,934 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2022 Borek Patzak + * + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticeframeconcreteplastic.h" +#include "latticeframeelastic.h" +#include "latticestructuralmaterial.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "CrossSections/structuralcrosssection.h" +#include "engngm.h" +#include "mathfem.h" +#include "Elements/LatticeElements/latticestructuralelement.h" +#include "datastream.h" +#include "staggeredproblem.h" +#include "contextioerr.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(LatticeFrameConcretePlastic); + +bool LatticeFrameConcretePlastic::hasMaterialModeCapability(MaterialMode mode) const +{ + return ( mode == _3dLattice ); +} + + +void LatticeFrameConcretePlastic::initializeFrom(InputRecord &ir) +{ + LatticeStructuralMaterial::initializeFrom(ir); + + // Young's modulus of the material that the beam element is made of + IR_GIVE_FIELD(ir, this->e, _IFT_LatticeFrameConcretePlastic_e); // Macro + + // Poisson's ratio of the material that the beam element is made of + IR_GIVE_FIELD(ir, this->nu, _IFT_LatticeFrameConcretePlastic_n); // Macro + + // Nx0 + IR_GIVE_FIELD(ir, this->nx0, _IFT_LatticeFrameConcretePlastic_nx0); // Macro + + // Nx01 + IR_GIVE_FIELD(ir, this->nx01, _IFT_LatticeFrameConcretePlastic_nx01); // Macro + + // vy0 + IR_GIVE_FIELD(ir, this->vy0, _IFT_LatticeFrameConcretePlastic_vy0); // Macro + + // vy01 + IR_GIVE_FIELD(ir, this->vy01, _IFT_LatticeFrameConcretePlastic_vy01); // Macro + + // vz0 + IR_GIVE_FIELD(ir, this->vz0, _IFT_LatticeFrameConcretePlastic_vz0); // Macro + + // vz01 + IR_GIVE_FIELD(ir, this->vz01, _IFT_LatticeFrameConcretePlastic_vz01); // Macro + + // Mx0 + IR_GIVE_FIELD(ir, this->mx0, _IFT_LatticeFrameConcretePlastic_mx0); // Macro + + // Mx01 + IR_GIVE_FIELD(ir, this->mx01, _IFT_LatticeFrameConcretePlastic_mx01); // Macro + + // My0 + IR_GIVE_FIELD(ir, this->my0, _IFT_LatticeFrameConcretePlastic_my0); // Macro + + // My01 + IR_GIVE_FIELD(ir, this->my01, _IFT_LatticeFrameConcretePlastic_my01); // Macro + + // Mz0 + IR_GIVE_FIELD(ir, this->mz0, _IFT_LatticeFrameConcretePlastic_mz0); // Macro + + // Mz01 + IR_GIVE_FIELD(ir, this->mz01, _IFT_LatticeFrameConcretePlastic_mz01); // Macro + + yieldTol = 1.e-6; + IR_GIVE_FIELD(ir, this->yieldTol, _IFT_LatticeFrameConcretePlastic_tol); // Macro + + this->newtonIter = 100; + IR_GIVE_FIELD(ir, this->newtonIter, _IFT_LatticeFrameConcretePlastic_iter); // Macro + + numberOfSubIncrements = 10; + IR_GIVE_FIELD(ir, this->numberOfSubIncrements, _IFT_LatticeFrameConcretePlastic_sub); // Macro + + this->plasticFlag = 1; + IR_GIVE_OPTIONAL_FIELD(ir, plasticFlag, _IFT_LatticeFrameConcretePlastic_plastic); // Macro + + // wu + IR_GIVE_OPTIONAL_FIELD(ir, this->wu, _IFT_LatticeFrameConcretePlastic_wu); + + // wf + IR_GIVE_FIELD(ir, wf, _IFT_LatticeFrameConcretePlastic_wf); +} +MaterialStatus * +LatticeFrameConcretePlastic::CreateStatus(GaussPoint *gp) const +{ + return new LatticeFrameConcretePlasticStatus(1, LatticeFrameConcretePlastic::domain, gp); +} + +MaterialStatus * +LatticeFrameConcretePlastic::giveStatus(GaussPoint *gp) const +{ + MaterialStatus *status = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); + if ( !status ) { + // create a new one + status = this->CreateStatus(gp); + + if ( status ) { + gp->setMaterialStatus(status); + } + } + // + return status; +} +int +LatticeFrameConcretePlastic::giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) +{ + auto status = static_cast< LatticeFrameConcretePlasticStatus * >( this->giveStatus(gp) ); + + if ( type == IST_PlasticLatticeStrain ) { + answer.resize(6); + answer.zero(); + answer = status->givePlasticLatticeStrain(); + return 1; + } else if ( type == IST_DamageScalar ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveDamage(); + return 1; + } else { + return LatticeStructuralMaterial::giveIPValue(answer, gp, type, atTime); + } +} + +double +LatticeFrameConcretePlastic::computeYieldValue(const FloatArrayF< 6 > &stress, const FloatArrayF< 6 > &k, + GaussPoint *gp, + TimeStep *tStep) const +{ + double yieldValue = 0.; + double nx = stress.at(1); + double vy = stress.at(2); + double vz = stress.at(3); + double mx = stress.at(4); + double my = stress.at(5); + double mz = stress.at(6); + + double ax; + if ( k.at(1) == 1 ) { + ax = nx0; + } else { + ax = nx01; + } + double ay; + if ( k.at(2) == 1 ) { + ay = vy0; + } else { + ay = vy01; + } + double az; + if ( k.at(3) == 1 ) { + az = vz0; + } else { + az = vz01; + } + double bx; + + if ( k.at(4) == 1 ) { + bx = mx0; + } else { + bx = mx01; + } + double by; + + if ( k.at(5) == 1 ) { + by = my0; + } else { + by = my01; + } + + double bz; + + if ( k.at(6) == 1 ) { + bz = mz0; + } else { + bz = mz01; + } + + + + yieldValue = pow(nx / ax, 2.) + pow(vy / ay, 2.) + pow(vz / az, 2.) + pow(mx / bx, 2.) + pow(my / by, 2.) + pow(mz / bz, 2.) - 1.; + + + return yieldValue; +} + +FloatArrayF< 6 > +LatticeFrameConcretePlastic::computeFVector(const FloatArrayF< 6 > &stress, const FloatArrayF< 6 > &k, + GaussPoint *gp, + TimeStep *tStep) const +{ + double nx = stress.at(1); + double vy = stress.at(2); + double vz = stress.at(3); + double mx = stress.at(4); + double my = stress.at(5); + double mz = stress.at(6); + + double ax = 0.; + if ( k.at(1) == 1 ) { + ax = nx0; + } else { + ax = nx01; + } + + double ay = 0.; + if ( k.at(2) == 1 ) { + ay = vy0; + } else { + ay = vy01; + } + + double az = 0.; + if ( k.at(3) == 1 ) { + az = vz0; + } else { + az = vz01; + } + + double bx = 0.; + if ( k.at(4) == 1 ) { + bx = mx0; + } else { + bx = mx01; + } + + double by = 0.; + if ( k.at(5) == 1 ) { + by = my0; + } else { + by = my01; + } + + double bz = 0.; + if ( k.at(6) == 1 ) { + bz = mz0; + } else { + bz = mz01; + } + + FloatArrayF< 6 >f; + f.at(1) = 2. * nx / pow(ax, 2.); + f.at(2) = 2. * vy / pow(ay, 2.); + f.at(3) = 2. * vz / pow(az, 2.); + f.at(4) = 2. * mx / pow(bx, 2.); + f.at(5) = 2. * my / pow(by, 2.); + f.at(6) = 2. * mz / pow(bz, 2.); + + return f; +} + +FloatMatrixF< 6, 6 > +LatticeFrameConcretePlastic::computeDMMatrix(const FloatArrayF< 6 > &stress, const FloatArrayF< 6 > &k, GaussPoint *gp, TimeStep *tStep) const +{ + double ax = nx01; + if ( k.at(1) == 1 ) { + ax = nx0; + } + + double ay = vy01; + ; + if ( k.at(2) == 1 ) { + ay = vy0; + } + + double az = vz01; + if ( k.at(3) == 1 ) { + az = vz0; + } + + double bx = mx01; + if ( k.at(4) == 1 ) { + bx = mx0; + } + + double by = my01; + if ( k.at(5) == 1 ) { + by = my0; + } + + double bz = mz01; + ; + if ( k.at(6) == 1 ) { + bz = mz0; + } + + FloatArrayF< 6 >dm = { + 2. / pow(ax, 2.), + 2. / pow(ay, 2.), + 2. / pow(az, 2.), + 2. / pow(bx, 2.), + 2. / pow(by, 2.), + 2. / pow(bz, 2.) + }; + + return diag(dm); +} + +FloatArrayF< 6 > +LatticeFrameConcretePlastic::giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const +// returns a FloatArray(6) of initial strain vector caused by unit temperature in direction of gp (element) local axes +{ + double alpha = this->give(tAlpha, gp); + + return { + alpha, 0., 0., 0., 0., 0. + }; +} + +FloatArrayF< 6 > +LatticeFrameConcretePlastic::giveStrain(GaussPoint *gp, TimeStep *tStep) const +{ + auto status = static_cast< LatticeMaterialStatus * >( this->giveStatus(gp) ); + return status->giveLatticeStrain(); +} + +const FloatArrayF< 6 > +LatticeFrameConcretePlastic::checkTransition(const FloatArrayF< 6 > &stress, GaussPoint *gp, TimeStep *tStep) const +{ + FloatArrayF< 6 >k; + + IntArray m(6); + + if ( stress.at(1) >= 0 ) { + m.at(1) = 1; + } else { + m.at(1) = -1; + } + + if ( stress.at(2) >= 0 ) { + m.at(2) = 1; + } else { + m.at(2) = -1; + } + + if ( stress.at(3) >= 0 ) { + m.at(3) = 1; + } else { + m.at(3) = -1; + } + + if ( stress.at(4) >= 0 ) { + m.at(4) = 1; + } else { + m.at(4) = -1; + } + + if ( stress.at(5) >= 0 ) { + m.at(5) = 1; + } else { + m.at(5) = -1; + } + + if ( stress.at(6) >= 0 ) { + m.at(6) = 1; + } else { + m.at(6) = -1; + } + + int counter = 1; + for ( int xi = -1; xi < 2; xi += 2 ) { + for ( int yi = -1; yi < 2; yi += 2 ) { + for ( int zi = -1; zi < 2; zi += 2 ) { + for ( int xj = -1; xj < 2; xj += 2 ) { + for ( int yj = -1; yj < 2; yj += 2 ) { + for ( int zj = -1; zj < 2; zj += 2 ) { + if ( !( zj == 0 && yj == 0 && xj == 0 && zi == 0 && yi == 0 && xi == 0 ) ) { + if ( xi == m.at(1) && yi == m.at(2) && zi == m.at(3) && xj == m.at(4) && yj == m.at(5) && zj == m.at(6) ) { + k.at(1) = xi; + k.at(2) = yi; + k.at(3) = zi; + k.at(4) = xj; + k.at(5) = yj; + k.at(6) = zj; + } + counter++; + } + } + } + } + } + } + } + if + ( k.at(1) != m.at(1) && k.at(2) != m.at(2) && k.at(2) != m.at(2) && k.at(2) != m.at(2) && k.at(2) != m.at(2) && k.at(2) != m.at(2) ) { + OOFEM_ERROR("This case should not exist"); + } + + return k; +} + +// + +FloatArrayF< 6 > +LatticeFrameConcretePlastic::performPlasticityReturn(GaussPoint *gp, const FloatArrayF< 6 > &strain, TimeStep *tStep) const +{ + LatticeFrameConcretePlastic_ReturnResult returnResult = RR_Unknown; + int kIter = 0; + double g = this->e / ( 2. * ( 1. + this->nu ) ); + const double area = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveArea(); + const double shearareay = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaY(); + const double shearareaz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaZ(); + const double ik = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIk(); + const double iy = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIy(); + const double iz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIz(); + + auto status = static_cast< LatticeFrameConcretePlasticStatus * >( this->giveStatus(gp) ); + + + /* Get plastic strain vector from status*/ + auto tempPlasticStrain = status->givePlasticLatticeStrain(); + + FloatArrayF< 6 >tangent = { area *this->e, g *shearareay, g *shearareaz, ik *g, iy *this->e, iz *this->e }; + + /* Compute trial stress*/ + auto stress = mult(tangent, strain - tempPlasticStrain); + + + + auto oldStrain = this->giveStrain(gp, tStep); + //test + auto k = checkTransition(stress, gp, tStep); + + /* Compute yield value*/ + double yieldValue = computeYieldValue(stress, k, gp, tStep); + int subIncrementCounter = 0; + + /* Check yield condition, i.e. if the yield value is less than the yield tolerance. If yield condition is valid. Do perform regular return (closest point return)*/ + + if ( yieldValue > yieldTol ) { + int subIncrementFlag = 0; + auto convergedStrain = oldStrain; + auto tempStrain = strain; + auto deltaStrain = strain - oldStrain; + // To get into the loop + status->letTempReturnResultBe(LatticeFrameConcretePlastic::RR_NotConverged); + while ( status->giveTempReturnResult() == RR_NotConverged || subIncrementFlag == 1 ) { + stress = mult(tangent, tempStrain - tempPlasticStrain); + performRegularReturn(stress, returnResult, k, yieldValue, gp, tStep); + //if ( status->giveTempReturnResult() == RR_WrongSurface ) { + // int RestartWithNewKValue; + //} + if ( status->giveTempReturnResult() == RR_NotConverged ) { + subIncrementCounter++; + if ( subIncrementCounter > numberOfSubIncrements ) { + OOFEM_LOG_INFO( "Unstable element %d \n", gp->giveElement()->giveGlobalNumber() ); + OOFEM_LOG_INFO("Yield value %e \n", yieldValue); + OOFEM_LOG_INFO( "ConvergedStrain value %e %e %e %e\n", convergedStrain.at(1), convergedStrain.at(2), convergedStrain.at(3), convergedStrain.at(4), convergedStrain.at(5), convergedStrain.at(6) ); + OOFEM_LOG_INFO( "tempStrain value %e %e %e %e\n", tempStrain.at(1), tempStrain.at(2), tempStrain.at(3), tempStrain.at(4), tempStrain.at(5), tempStrain.at(6) ); + OOFEM_LOG_INFO( "deltaStrain value %e %e %e %e\n", deltaStrain.at(1), deltaStrain.at(2), deltaStrain.at(3), deltaStrain.at(4), deltaStrain.at(5), deltaStrain.at(6) ); + OOFEM_LOG_INFO( "targetstrain value %e %e %e %e\n", strain.at(1), strain.at(2), strain.at(3), strain.at(4), strain.at(5), strain.at(6) ); + + OOFEM_ERROR("LatticeFrameConcretePlastic :: performPlasticityReturn - Could not reach convergence with small deltaStrain, giving up."); + } + subIncrementFlag = 1; + deltaStrain *= 0.5; + tempStrain = convergedStrain + deltaStrain; + } else if ( status->giveTempReturnResult() == RR_Converged && subIncrementFlag == 1 ) { + tempPlasticStrain.at(1) = tempStrain.at(1) - stress.at(1) / ( area * this->e ); + tempPlasticStrain.at(2) = tempStrain.at(2) - stress.at(2) / ( g * shearareay ); + tempPlasticStrain.at(3) = tempStrain.at(3) - stress.at(3) / ( g * shearareaz ); + tempPlasticStrain.at(4) = tempStrain.at(4) - stress.at(4) / ( ik * g ); + tempPlasticStrain.at(5) = tempStrain.at(5) - stress.at(5) / ( iy * this->e ); + tempPlasticStrain.at(6) = tempStrain.at(6) - stress.at(6) / ( iz * this->e ); + + status->letTempPlasticLatticeStrainBe( assemble< 6 >(tempPlasticStrain, { 0, 1, 2, 3, 4, 5 }) ); + + subIncrementFlag = 0; + + status->letTempReturnResultBe(LatticeFrameConcretePlastic::RR_NotConverged); + convergedStrain = tempStrain; + deltaStrain = strain - convergedStrain; + tempStrain = strain; + subIncrementCounter = 0; + } else { //Converged + //Check the surface + FloatArrayF< 6 >kCheck = checkTransition(stress, gp, tStep); + + if ( kCheck.at(1) == k.at(1) && kCheck.at(2) == k.at(2) && kCheck.at(3) == k.at(3) && kCheck.at(4) == k.at(4) && kCheck.at(5) == k.at(5) && kCheck.at(6) == k.at(6) ) { + returnResult = RR_Converged; + } else { + //ended up in a region for which other surface should have been used. + //Try with other surface + if ( kIter == 1 ) { + OOFEM_ERROR("LatticePlasticityDamage :: performPlasticityReturn - Tried both surfaces"); + } + + k = kCheck; + returnResult = RR_NotConverged; + kIter++; + } + } + } + } + + tempPlasticStrain.at(1) = strain.at(1) - stress.at(1) / ( area * this->e ); + tempPlasticStrain.at(2) = strain.at(2) - stress.at(2) / ( g * shearareay ); + tempPlasticStrain.at(3) = strain.at(3) - stress.at(3) / ( g * shearareaz ); + tempPlasticStrain.at(4) = strain.at(4) - stress.at(4) / ( ik * g ); + tempPlasticStrain.at(5) = strain.at(5) - stress.at(5) / ( iy * this->e ); + tempPlasticStrain.at(6) = strain.at(6) - stress.at(6) / ( iz * this->e ); + + status->letTempPlasticLatticeStrainBe(tempPlasticStrain); + + return stress; +} + +Interface * +LatticeFrameConcretePlastic::giveInterface(InterfaceType type) +{ + return nullptr; +} +// +void +LatticeFrameConcretePlastic::performRegularReturn(FloatArrayF< 6 > &stress, LatticeFrameConcretePlastic_ReturnResult, const FloatArrayF< 6 > &k, + double yieldValue, + GaussPoint *gp, + TimeStep *tStep) const +{ + // Use material specific status + auto status = static_cast< LatticeFrameConcretePlasticStatus * >( this->giveStatus(gp) ); + + double deltaLambda = 0.; + + auto trialStress = stress; + auto tempStress = trialStress; + + // initialise unknowns + FloatArrayF< 7 >unknowns; + unknowns.at(1) = trialStress.at(1); + unknowns.at(2) = trialStress.at(2); + unknowns.at(3) = trialStress.at(3); + unknowns.at(4) = trialStress.at(4); + unknowns.at(5) = trialStress.at(5); + unknowns.at(6) = trialStress.at(6); + unknowns.at(7) = 0.; + + yieldValue = computeYieldValue(tempStress, k, gp, tStep); + + // initiate residuals + FloatArrayF< 7 >residuals; + residuals.at(7) = yieldValue; + double normOfResiduals = 1.; // just to get into the loop + int iterationCount = 0; + while ( normOfResiduals > yieldTol ) { + iterationCount++; + if ( iterationCount == newtonIter ) { + status->letTempReturnResultBe(LatticeFrameConcretePlasticStatus::RR_NotConverged); + return; + } + + + double ax; + if ( k.at(1) == 1 ) { + ax = nx0; + } else { + ax = nx01; + } + double ay; + if ( k.at(2) == 1 ) { + ay = vy0; + } else { + ay = vy01; + } + double az; + if ( k.at(3) == 1 ) { + az = vz0; + } else { + az = vz01; + } + double bx; + + if ( k.at(4) == 1 ) { + bx = mx0; + } else { + bx = mx01; + } + double by; + + if ( k.at(5) == 1 ) { + by = my0; + } else { + by = my01; + } + + double bz; + + if ( k.at(6) == 1 ) { + bz = mz0; + } else { + bz = mz01; + } + + FloatArrayF< 7 >residualsNorm; + residualsNorm.at(1) = residuals.at(1) / ax; + residualsNorm.at(2) = residuals.at(2) / ay; + residualsNorm.at(3) = residuals.at(3) / az; + residualsNorm.at(4) = residuals.at(4) / bx; + residualsNorm.at(5) = residuals.at(5) / by; + residualsNorm.at(6) = residuals.at(6) / bz; + residualsNorm.at(7) = residuals.at(7); + normOfResiduals = norm(residualsNorm); + // printf( "normOfResiduals=%e\n", normOfResiduals ); + if ( std::isnan(normOfResiduals) ) { + status->letTempReturnResultBe(LatticeFrameConcretePlasticStatus::RR_NotConverged); + return; + } + + if ( normOfResiduals > yieldTol ) { + auto jacobian = computeJacobian(tempStress, k, deltaLambda, gp, tStep); + + auto solution = solve_check(jacobian, residuals); + if ( solution.first ) { + unknowns -= solution.second; + } else { + status->letTempReturnResultBe(LatticeFrameConcretePlastic::RR_NotConverged); + } + unknowns.at(7) = max(unknowns.at(7), 0.); // Keep deltaLambda greater than zero! + + /* Update increments final values and DeltaLambda*/ + tempStress.at(1) = unknowns.at(1); + tempStress.at(2) = unknowns.at(2); + tempStress.at(3) = unknowns.at(3); + tempStress.at(4) = unknowns.at(4); + tempStress.at(5) = unknowns.at(5); + tempStress.at(6) = unknowns.at(6); + deltaLambda = unknowns.at(7); + + /* Compute the fVector*/ + auto FVector = computeFVector(tempStress, k, gp, tStep); + double g = this->e / ( 2. * ( 1. + this->nu ) ); + const double area = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveArea(); + const double shearareay = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaY(); + const double shearareaz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaZ(); + const double ik = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIk(); + const double iy = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIy(); + const double iz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIz(); + + residuals.at(1) = tempStress.at(1) - trialStress.at(1) + area * this->e * deltaLambda * FVector.at(1); + residuals.at(2) = tempStress.at(2) - trialStress.at(2) + shearareay * g * deltaLambda * FVector.at(2); + residuals.at(3) = tempStress.at(3) - trialStress.at(3) + shearareaz * g * deltaLambda * FVector.at(3); + residuals.at(4) = tempStress.at(4) - trialStress.at(4) + ik * g * deltaLambda * FVector.at(4); + residuals.at(5) = tempStress.at(5) - trialStress.at(5) + iy * this->e * deltaLambda * FVector.at(5); + residuals.at(6) = tempStress.at(6) - trialStress.at(6) + iz * this->e * deltaLambda * FVector.at(6); + residuals.at(7) = computeYieldValue(tempStress, k, gp, tStep); + } + } + status->letTempReturnResultBe(LatticeFrameConcretePlastic::RR_Converged); + stress = tempStress; +} + +FloatMatrixF< 7, 7 > +LatticeFrameConcretePlastic::computeJacobian(const FloatArrayF< 6 > &stress, const FloatArrayF< 6 > &k, + const double deltaLambda, + GaussPoint *gp, + TimeStep *tStep) const +{ + auto dMMatrix = computeDMMatrix(stress, k, gp, tStep); + auto fVector = computeFVector(stress, k, gp, tStep); + double g = this->e / ( 2. * ( 1. + this->nu ) ); + const double area = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveArea(); + const double shearareay = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaY(); + const double shearareaz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaZ(); + const double ik = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIk(); + const double iy = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIy(); + const double iz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIz(); + + /* Compute matrix*/ + FloatMatrixF< 7, 7 >jacobian; + jacobian.at(1, 1) = 1. + this->e * area * deltaLambda * dMMatrix.at(1, 1); + jacobian.at(1, 2) = 0.; + jacobian.at(1, 3) = 0.; + jacobian.at(1, 4) = 0.; + jacobian.at(1, 5) = 0.; + jacobian.at(1, 6) = 0.; + jacobian.at(1, 7) = this->e * area * fVector.at(1); + + jacobian.at(2, 1) = 0.; + jacobian.at(2, 2) = 1. + shearareay * g * deltaLambda * dMMatrix.at(2, 2); + jacobian.at(2, 3) = 0.; + jacobian.at(2, 4) = 0.; + jacobian.at(2, 5) = 0.; + jacobian.at(2, 6) = 0.; + jacobian.at(2, 7) = shearareay * g * fVector.at(2); + + jacobian.at(3, 1) = 0.; + jacobian.at(3, 2) = 0.; + jacobian.at(3, 3) = 1. + shearareaz * g * deltaLambda * dMMatrix.at(3, 3); + jacobian.at(3, 4) = 0.; + jacobian.at(3, 5) = 0.; + jacobian.at(3, 6) = 0.; + jacobian.at(3, 7) = shearareaz * g * fVector.at(3); + + jacobian.at(4, 1) = 0.; + jacobian.at(4, 2) = 0.; + jacobian.at(4, 3) = 0.; + jacobian.at(4, 4) = 1. + ik * g * deltaLambda * dMMatrix.at(4, 4); + jacobian.at(4, 5) = 0.; + jacobian.at(4, 6) = 0.; + jacobian.at(4, 7) = ik * g * fVector.at(4); + + jacobian.at(5, 1) = 0.; + jacobian.at(5, 2) = 0.; + jacobian.at(5, 3) = 0.; + jacobian.at(5, 4) = 0.; + jacobian.at(5, 5) = 1. + iy * this->e * deltaLambda * dMMatrix.at(5, 5); + jacobian.at(5, 6) = 0.; + jacobian.at(5, 7) = iy * this->e * fVector.at(5); + + + jacobian.at(6, 1) = 0.; + jacobian.at(6, 2) = 0.; + jacobian.at(6, 3) = 0.; + jacobian.at(6, 4) = 0.; + jacobian.at(6, 5) = 0.; + jacobian.at(6, 6) = 1. + this->e * iz * deltaLambda * dMMatrix.at(6, 6); + jacobian.at(6, 7) = this->e * iz * fVector.at(6); + + jacobian.at(7, 1) = fVector.at(1); + jacobian.at(7, 2) = fVector.at(2); + jacobian.at(7, 3) = fVector.at(3); + jacobian.at(7, 4) = fVector.at(4); + jacobian.at(7, 5) = fVector.at(5); + jacobian.at(7, 6) = fVector.at(6); + jacobian.at(7, 7) = 0.; + + return jacobian; +} + + +FloatArrayF< 6 > +LatticeFrameConcretePlastic::giveFrameForces3d(const FloatArrayF< 6 > &originalStrain, GaussPoint *gp, TimeStep *tStep) +{ + auto status = static_cast< LatticeFrameConcretePlasticStatus * >( this->giveStatus(gp) ); + auto strain = originalStrain; + auto thermalStrain = this->computeStressIndependentStrainVector(gp, tStep, VM_Total); + if ( thermalStrain.giveSize() ) { + strain -= FloatArrayF< 6 >(thermalStrain); + } + auto stress = this->performPlasticityReturn(gp, strain, tStep); + + auto tempPlasticStrain = status->giveTempPlasticLatticeStrain(); + + double le = static_cast< LatticeStructuralElement * >( gp->giveElement() )->giveLength(); + + //double equivalentStrain = sqrt(pow(tempPlasticStrain.at(1), 2) + pow(tempPlasticStrain.at(2), 2) + pow(tempPlasticStrain.at(3), 2) + + // pow(tempPlasticStrain.at(4), 2) + pow(tempPlasticStrain.at(5), 2.) + pow(tempPlasticStrain.at(6), 2) ) - wu / le; + double equivalentStrain = sqrt(pow(tempPlasticStrain.at(4), 2) + pow(tempPlasticStrain.at(5), 2.) + pow(tempPlasticStrain.at(6), 2) ) - wu / le; + // printf("equivalentStrain = %e, wu/le = %e, le = %e\n", equivalentStrain, wu/le, le); + + double tempKappaD = 0.0; + + if ( equivalentStrain > status->giveKappaD() ) { + tempKappaD = equivalentStrain; + } else { + tempKappaD = status->giveKappaD(); + } + + double omega = 0.0; + if ( tempKappaD <= 0. ) { + omega = 0.; + } else if ( tempKappaD > 0. ) { + omega = 1. - exp(-tempKappaD * le / ( wf ) ); + } else { + printf("Should not be here\n"); + } + + if ( omega > 1.0 ) { + omega = 1.; + } else if ( omega < 0.0 ) { + omega = 0.; + } + + stress *= ( 1. - omega ); + + status->letTempLatticeStrainBe(originalStrain); + status->letTempReducedLatticeStrainBe(strain); + status->letTempLatticeStressBe(stress); + status->setTempKappaD(tempKappaD); + status->setTempDamage(omega); + + return stress; +} + + +FloatMatrixF< 6, 6 > +LatticeFrameConcretePlastic::give3dFrameStiffnessMatrix(MatResponseMode rmode, GaussPoint *gp, TimeStep *atTime) const +{ + static_cast< LatticeFrameConcretePlasticStatus * >( this->giveStatus(gp) ); + + double g = this->e / ( 2. * ( 1. + this->nu ) ); + const double area = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveArea(); + const double shearareay = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaY(); + const double shearareaz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaZ(); + const double ik = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIk(); + const double iy = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIy(); + const double iz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIz(); + + + FloatArrayF< 6 >d = { + this->e * area, + g *shearareay, + g *shearareaz, + g *ik, + this->e * iy, + this->e * iz + }; + + return diag(d); +} + +LatticeFrameConcretePlasticStatus::LatticeFrameConcretePlasticStatus(int n, Domain *d, GaussPoint *g) : + LatticeMaterialStatus(g) +{} +void +LatticeFrameConcretePlasticStatus::initTempStatus() +{ + LatticeMaterialStatus::initTempStatus(); + this->tempKappaD = this->kappaD; + this->tempDamage = this->damage; +} + +void +LatticeFrameConcretePlasticStatus::updateYourself(TimeStep *atTime) +// +// updates variables (nonTemp variables describing situation at previous equilibrium state) +// after a new equilibrium state has been reached +// temporary variables are having values corresponding to newly reached equilibrium. +// +{ + LatticeMaterialStatus::updateYourself(atTime); + this->kappaD = this->tempKappaD; + this->damage = this->tempDamage; +} + +void +LatticeFrameConcretePlasticStatus::printOutputAt(FILE *file, TimeStep *tStep) const +{ + LatticeMaterialStatus::printOutputAt(file, tStep); + + fprintf(file, "plasticStrains "); + for ( double s : this->plasticLatticeStrain ) { + fprintf(file, "% .8e ", s); + } + //fprintf(file, "kappad %.8e ", this->kappaD); + // fprintf(file, "damage %.8e ", this->damage); + fprintf(file, ", kappaD %.8e, damage %.8e \n", this->kappaD, this->damage); + +} + +void +LatticeFrameConcretePlasticStatus::saveContext(DataStream &stream, ContextMode mode) +// +// saves full information stored in this Status +// no temp variables stored +// +{ + LatticeMaterialStatus::saveContext(stream, mode); + + + + if ( !stream.write(& kappaD, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(& damage, 1) ) { + THROW_CIOERR(CIO_IOERR); + } +} + + + +void +LatticeFrameConcretePlasticStatus::restoreContext(DataStream &stream, ContextMode mode) +// +// restores full information stored in stream to this Status +// +{ + LatticeMaterialStatus::restoreContext(stream, mode); + + if ( !stream.read(& kappaD, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(& damage, 1) ) { + THROW_CIOERR(CIO_IOERR); + } +} +} diff --git a/src/sm/Materials/LatticeMaterials/latticeframeconcreteplastic.h b/src/sm/Materials/LatticeMaterials/latticeframeconcreteplastic.h new file mode 100644 index 000000000..bb75de887 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeframeconcreteplastic.h @@ -0,0 +1,269 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2022 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticeframeconcreteplastic_h +#define latticeframeconcreteplastic_h + + +#include "latticestructuralmaterial.h" +#include "cltypes.h" +#include "randommaterialext.h" +#include "strainvector.h" +#include "stressvector.h" +#include "latticematstatus.h" +///@name Input fields for LatticeFrameConcretePlastic +//@{ +#define _IFT_LatticeFrameConcretePlastic_Name "LatticeFrameConcretePlastic" +#define _IFT_LatticeFrameConcretePlastic_talpha "talpha" +#define _IFT_LatticeFrameConcretePlastic_e "e" +#define _IFT_LatticeFrameConcretePlastic_n "n" +#define _IFT_LatticeFrameConcretePlastic_nx0 "nx0" +#define _IFT_LatticeFrameConcretePlastic_vy0 "vy0" +#define _IFT_LatticeFrameConcretePlastic_vz0 "vz0" +#define _IFT_LatticeFrameConcretePlastic_mx0 "mx0" +#define _IFT_LatticeFrameConcretePlastic_my0 "my0" +#define _IFT_LatticeFrameConcretePlastic_mz0 "mz0" +#define _IFT_LatticeFrameConcretePlastic_nx01 "nx01" +#define _IFT_LatticeFrameConcretePlastic_vy01 "vy01" +#define _IFT_LatticeFrameConcretePlastic_vz01 "vz01" +#define _IFT_LatticeFrameConcretePlastic_mx01 "mx01" +#define _IFT_LatticeFrameConcretePlastic_my01 "my01" +#define _IFT_LatticeFrameConcretePlastic_mz01 "mz01" +#define _IFT_LatticeFrameConcretePlastic_tol "tol" +#define _IFT_LatticeFrameConcretePlastic_iter "iter" +#define _IFT_LatticeFrameConcretePlastic_sub "sub" +#define _IFT_LatticeFrameConcretePlastic_plastic "plastic" +#define _IFT_LatticeFrameConcretePlastic_wu "wu" +#define _IFT_LatticeFrameConcretePlastic_wf "wf" +#define _IFT_LatticeFrameConcretePlastic_wftwo "wftwo" +#define _IFT_LatticeFrameConcretePlastic_qzero "qzero" +//@} + +namespace oofem { +/** + * This class implements associated Material Status to LatticeFrameConcretePlastic. + * @authors: Gumaa Abdelrhim, Peter Grassl + */ + +class LatticeFrameConcretePlasticStatus : public LatticeMaterialStatus +{ +public: + + enum state_flag_values { + LatticeFrameConcretePlastic_Elastic, + LatticeFrameConcretePlastic_Unloading, + LatticeFrameConcretePlastic_Plastic, + }; + enum LatticeFrameConcretePlastic_ReturnResult { + RR_NotConverged, + RR_Converged, + }; + +protected: + + double kappaD = 0.; + double tempKappaD = 0.; + double damage = 0.; + double tempDamage = 0.; + + + int tempReturnResult = LatticeFrameConcretePlasticStatus::RR_NotConverged; + +public: + + /// Constructor + LatticeFrameConcretePlasticStatus(int n, Domain *d, GaussPoint *g); + + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + const char *giveClassName() const override { return "LatticeFrameConcretePlasticStatus"; } + + void letTempReturnResultBe(const int result) { tempReturnResult = result; } + + int giveTempReturnResult() const { return tempReturnResult; } + + double giveKappaD() const { return this->kappaD; } + + double giveTempKappaD() const { return this->tempKappaD; } + + void setTempKappaD(double newKappa) { this->tempKappaD = newKappa; } + + double giveDamage() const { return this->damage; } + + double giveTempDamage() const { return this->tempDamage; } + + void setTempDamage(double newDamage) { this->tempDamage = newDamage; } + + void initTempStatus() override; + + void updateYourself(TimeStep *) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; +}; + + +/** + * This class implements a concrete plasticity model for concrete for frame elements. + */ +class LatticeFrameConcretePlastic : public LatticeStructuralMaterial + +{ +protected: + + + + ///Normal modulus + double e; + + ///Ratio of shear and normal modulus + double nu; + + ///maximum axial force in x-axis x-axis nx0 + double nx0; + + double vy0; + + double vz0; + + ///maximum bending moment about x-axis mx0 + double mx0; + + ///maximum bending moment about x-axis my0 + double my0; + + ///maximum bending moment about x-axis mz0 + double mz0; + + ///maximum axial force in x-axis x-axis nx01 + double nx01; + + double vy01; + + double vz01; + + ///maximum bending moment about x-axis mx01 + double mx01; + + ///maximum bending moment about x-axis my01 + double my01; + + ///maximum bending moment about x-axis mz01 + double mz01; + + /// yield tolerance + double yieldTol; + + /// maximum number of iterations for stress return + double newtonIter; + + ///number Of SubIncrements + double numberOfSubIncrements; + + ///plastic flag + double plasticFlag; + + ///wu + double wu; + + ///wf + double wf; + + ///wftwo + double wftwo; + + ///qzero + double qzero; + + + enum LatticeFrameConcretePlastic_ReturnResult { RR_NotConverged, RR_Converged, RR_Unknown, RR_known }; + + double initialYieldStress = 0.; + +public: + LatticeFrameConcretePlastic(int n, Domain *d) : LatticeStructuralMaterial(n, d) { }; + + FloatArrayF< 6 >computeFVector(const FloatArrayF< 6 > &stress, const FloatArrayF< 6 > &k, GaussPoint *gp, TimeStep *tStep) const; + + FloatMatrixF< 6, 6 >computeDMMatrix(const FloatArrayF< 6 > &stress, const FloatArrayF< 6 > &k, GaussPoint *gp, TimeStep *tStep) const; + + FloatArrayF< 6 >giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; + + FloatArrayF< 6 >giveLatticeStrain(GaussPoint *gp, TimeStep *tStep) const; + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime) override; + virtual FloatArrayF< 6 >giveStrain(GaussPoint *gp, TimeStep *tStep) const; + + FloatArrayF< 6 >performPlasticityReturn(GaussPoint *gp, const FloatArrayF< 6 > &strain, TimeStep *tStep) const; + + void performRegularReturn(FloatArrayF< 6 > &stress, LatticeFrameConcretePlastic_ReturnResult, const FloatArrayF< 6 > &k, double yieldValue, GaussPoint *gp, TimeStep *tStep) const; + + void giveSwitches(IntArray &answer, int k); + + double computeYieldValue(const FloatArrayF< 6 > &stress, const FloatArrayF< 6 > &k, GaussPoint *gp, TimeStep *tStep) const; + + FloatMatrixF< 7, 7 >computeJacobian(const FloatArrayF< 6 > &stress, const FloatArrayF< 6 > &k, const double deltaLambda, GaussPoint *gp, TimeStep *tStep) const; + + IntArray checkStatus(const FloatArrayF< 6 > &stress, IntArray &k, GaussPoint *gp, TimeStep *tStep) const; + + FloatArrayF< 6 >giveFrameForces3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) override; + + const char *giveInputRecordName() const override { return _IFT_LatticeFrameConcretePlastic_Name; } + + const char *giveClassName() const override { return "LatticeFrameConcretePlastic"; } + + void initializeFrom(InputRecord &ir) override; + + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + + Interface *giveInterface(InterfaceType) override; + + FloatMatrixF< 6, 6 >give3dFrameStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + + bool hasMaterialModeCapability(MaterialMode mode) const override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + MaterialStatus *giveStatus(GaussPoint *gp) const override; + +protected: + const FloatArray checkStatus(FloatArrayF< 6 >f, GaussPoint *pPoint, TimeStep *pStep) const; + IntArray checkStatus(const FloatArrayF< 6 > &stress, IntArray &k) const; + const FloatArrayF< 6 >checkTransition(const FloatArrayF< 6 > &stress, GaussPoint *gp, TimeStep *tStep) const; +}; +} // end namespace oofem + +#endif diff --git a/src/sm/Materials/LatticeMaterials/latticeframeelastic.C b/src/sm/Materials/LatticeMaterials/latticeframeelastic.C new file mode 100644 index 000000000..929f7cc86 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeframeelastic.C @@ -0,0 +1,164 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticeframeelastic.h" +#include "latticematstatus.h" +#include "latticestructuralmaterial.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "CrossSections/structuralcrosssection.h" +#include "engngm.h" +#include "mathfem.h" +#include "Elements/LatticeElements/latticestructuralelement.h" +#include "datastream.h" +#include "staggeredproblem.h" +#include "contextioerr.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(LatticeFrameElastic); + +bool +LatticeFrameElastic::hasMaterialModeCapability(MaterialMode mode) const +{ + return ( mode == _3dLattice ); +} + + +void +LatticeFrameElastic::initializeFrom(InputRecord &ir) +{ + LatticeStructuralMaterial::initializeFrom(ir); + + //Young's modulus of the material that the beam element is made of + IR_GIVE_FIELD(ir, this->e, _IFT_LatticeFrameElastic_e); // Macro + + //Poisson's ratio of the material that the beam element is made of + IR_GIVE_FIELD(ir, this->nu, _IFT_LatticeFrameElastic_n); // Macro +} + +MaterialStatus * +LatticeFrameElastic::CreateStatus(GaussPoint *gp) const +{ + return new LatticeMaterialStatus(gp); +} + +MaterialStatus * +LatticeFrameElastic::giveStatus(GaussPoint *gp) const +{ + MaterialStatus *status = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); + if ( !status ) { + // create a new one + status = this->CreateStatus(gp); + + if ( status ) { + gp->setMaterialStatus(status); + } + } + + return status; +} + + +FloatArrayF< 6 > +LatticeFrameElastic::giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const +// +// returns a FloatArray(6) of initial strain vector +// caused by unit temperature in direction of +// gp (element) local axes +// +{ + double alpha = this->give(tAlpha, gp); + + + return { + alpha, 0., 0., 0., 0., 0. + }; +} + + +FloatArrayF< 6 > +LatticeFrameElastic::giveFrameForces3d(const FloatArrayF< 6 > &strain, + GaussPoint *gp, + TimeStep *tStep) +{ + auto status = static_cast< LatticeMaterialStatus * >( this->giveStatus(gp) ); + + this->initTempStatus(gp); + auto stiffnessMatrix = LatticeFrameElastic::give3dFrameStiffnessMatrix(ElasticStiffness, gp, tStep); + auto stress = dot(stiffnessMatrix, strain); + status->letTempLatticeStrainBe(strain); + status->letTempLatticeStressBe(stress); + + return stress; +} + + +Interface * +LatticeFrameElastic::giveInterface(InterfaceType type) +{ + return nullptr; +} + + +FloatMatrixF< 6, 6 > +LatticeFrameElastic::give3dFrameStiffnessMatrix(MatResponseMode rmode, GaussPoint *gp, TimeStep *atTime) const +{ + static_cast< LatticeMaterialStatus * >( this->giveStatus(gp) ); + + double g = this->e / ( 2. * ( 1. + this->nu ) ); + + const double area = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveArea(); + const double iy = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIy(); + const double iz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIz(); + const double ik = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIk(); + const double shearareay = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaY(); + const double shearareaz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaZ(); + + //Peter: You need to put here the correct values. Please check this. + FloatArrayF< 6 >d = { + this->e * area, + g *shearareay, + g *shearareaz, + g *ik, + this->e * iy, + this->e * iz + }; + + return diag(d); +} +} diff --git a/src/sm/Materials/LatticeMaterials/latticeframeelastic.h b/src/sm/Materials/LatticeMaterials/latticeframeelastic.h new file mode 100644 index 000000000..58727d398 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeframeelastic.h @@ -0,0 +1,98 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticeframeelastic_h +#define latticeframeelastic_h + +#include "latticestructuralmaterial.h" +#include "cltypes.h" +#include "randommaterialext.h" +#include "strainvector.h" +#include "stressvector.h" +#include "latticematstatus.h" + +///@name Input fields for LatticeFrameElastic +//@{ +#define _IFT_LatticeFrameElastic_Name "latticeframeelastic" +#define _IFT_LatticeFrameElastic_talpha "talpha" +#define _IFT_LatticeFrameElastic_e "e" +#define _IFT_LatticeFrameElastic_n "n" +//@} + +namespace oofem { +/** + * This class implements a local random linear elastic model for lattice elements. + */ +class LatticeFrameElastic : public LatticeStructuralMaterial +{ +protected: + ///Normal modulus + double e; + + ///Ratio of shear and normal modulus + double nu; + +public: + LatticeFrameElastic(int n, Domain *d) : LatticeStructuralMaterial(n, d) { }; + + + FloatArrayF< 6 >giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; + + const char *giveInputRecordName() const override { return _IFT_LatticeFrameElastic_Name; } + + const char *giveClassName() const override { return "LatticeFrameElastic"; } + + void initializeFrom(InputRecord &ir) override; + + + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + + FloatArrayF< 6 >giveFrameForces3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) override; + + FloatMatrixF< 6, 6 >give3dFrameStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + + + bool hasMaterialModeCapability(MaterialMode mode) const override; + + Interface *giveInterface(InterfaceType) override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + MaterialStatus *giveStatus(GaussPoint *gp) const override; + +protected: +}; +} // end namespace oofem + +#endif diff --git a/src/sm/Materials/LatticeMaterials/latticeframesteelplastic.C b/src/sm/Materials/LatticeMaterials/latticeframesteelplastic.C new file mode 100644 index 000000000..02f6315a4 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeframesteelplastic.C @@ -0,0 +1,533 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticeframesteelplastic.h" +#include "latticeframeelastic.h" +#include "latticestructuralmaterial.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "CrossSections/structuralcrosssection.h" +#include "engngm.h" +#include "mathfem.h" +#include "Elements/LatticeElements/latticestructuralelement.h" +#include "datastream.h" +#include "staggeredproblem.h" +#include "contextioerr.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(LatticeFrameSteelPlastic); + +// constructor which creates a dummy material without a status and without random extension interface +// LatticeFrameSteelPlastic :: LatticeFrameSteelPlastic(int n, Domain *d) : +// LatticeStructuralMaterial(n, d) +bool +LatticeFrameSteelPlastic::hasMaterialModeCapability(MaterialMode mode) const +{ + return ( mode == _3dLattice ); +} + + +void +LatticeFrameSteelPlastic::initializeFrom(InputRecord &ir) +{ + LatticeStructuralMaterial::initializeFrom(ir); + + //Young's modulus of the material that the beam element is made of + IR_GIVE_FIELD(ir, this->e, _IFT_LatticeFrameSteelPlastic_e); // Macro + + //Poisson's ratio of the material that the beam element is made of + IR_GIVE_FIELD(ir, this->nu, _IFT_LatticeFrameSteelPlastic_n); // Macro + + //Nx0 + IR_GIVE_FIELD(ir, this->nx0, _IFT_LatticeFrameSteelPlastic_nx0); // Macro + + //Mx0 + IR_GIVE_FIELD(ir, this->mx0, _IFT_LatticeFrameSteelPlastic_mx0); // Macro + + //My0 + IR_GIVE_FIELD(ir, this->my0, _IFT_LatticeFrameSteelPlastic_my0); // Macro + + //Mz0 + IR_GIVE_FIELD(ir, this->mz0, _IFT_LatticeFrameSteelPlastic_mz0); // Macro + + yieldTol = 1.e-6; + ; + IR_GIVE_FIELD(ir, this->yieldTol, _IFT_LatticeFrameSteelPlastic_tol); // Macro + + this->newtonIter = 100; + IR_GIVE_FIELD(ir, this->newtonIter, _IFT_LatticeFrameSteelPlastic_iter); // Macro + + numberOfSubIncrements = 10; + IR_GIVE_FIELD(ir, this->numberOfSubIncrements, _IFT_LatticeFrameSteelPlastic_sub); // Macro + + this->plasticFlag = 1; + IR_GIVE_OPTIONAL_FIELD(ir, plasticFlag, _IFT_LatticeFrameSteelPlastic_plastic); // Macro +} + +MaterialStatus * +LatticeFrameSteelPlastic::CreateStatus(GaussPoint *gp) const +{ + return new LatticeFrameSteelPlasticStatus(1, LatticeFrameSteelPlastic::domain, gp); +} + +MaterialStatus * +LatticeFrameSteelPlastic::giveStatus(GaussPoint *gp) const +{ + // test + MaterialStatus *status = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); + if ( !status ) { + // create a new one + status = this->CreateStatus(gp); + + if ( status ) { + gp->setMaterialStatus(status); + } + } + + return status; +} + +int +LatticeFrameSteelPlastic::giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) +{ + auto status = static_cast< LatticeFrameSteelPlasticStatus * >( this->giveStatus(gp) ); + + if ( type == IST_PlasticLatticeStrain ) { + answer = status->givePlasticLatticeStrain(); + return 1; + } else { + return LatticeStructuralMaterial::giveIPValue(answer, gp, type, atTime); + } +} + + + +double +LatticeFrameSteelPlastic::computeYieldValue(const FloatArrayF< 4 > &stress, + GaussPoint *gp, + TimeStep *tStep) const +{ + double yieldValue = 0.; + double nx = stress.at(1); + double mx = stress.at(2); + double my = stress.at(3); + double mz = stress.at(4); + + { + yieldValue = pow(nx / this->nx0, 2.) + pow(mx / this->mx0, 2.) + pow(my / this->my0, 2.) + pow(mz / this->mz0, 2.) - 1.; + } + + return yieldValue; +} + +FloatArrayF< 4 > +LatticeFrameSteelPlastic::computeFVector(const FloatArrayF< 4 > &stress, + GaussPoint *gp, + TimeStep *tStep) const +{ + double nx = stress.at(1); + double mx = stress.at(2); + double my = stress.at(3); + double mz = stress.at(4); + + FloatArrayF< 4 >f; + + f.at(1) = 2. * nx / pow(this->nx0, 2.); + f.at(2) = 2. * mx / pow(this->mx0, 2.); + f.at(3) = 2. * my / pow(this->my0, 2.); + f.at(4) = 2. * mz / pow(this->mz0, 2.); + + return f; +} + +FloatMatrixF< 4, 4 > +LatticeFrameSteelPlastic::computeDMMatrix(const FloatArrayF< 4 > &stress, GaussPoint *gp, TimeStep *tStep) const +{ + FloatMatrixF< 4, 4 >dm; + + //Derivatives of dGDSig + dm.at(1, 1) = 2. / pow(this->nx0, 2.); + dm.at(1, 2) = 0; + dm.at(1, 3) = 0; + dm.at(1, 4) = 0; + + //Derivatives of dGDTau + dm.at(2, 1) = 0; + dm.at(2, 2) = 2. / pow(this->mx0, 2.); + dm.at(2, 3) = 0; + dm.at(2, 4) = 0; + + //Derivates of evolution law + dm.at(3, 1) = 0; + dm.at(3, 2) = 0; + dm.at(3, 3) = 2. / pow(this->my0, 2.); + dm.at(3, 4) = 0; + + //Derivates of evolution law + dm.at(4, 1) = 0; + dm.at(4, 2) = 0; + dm.at(4, 3) = 0; + dm.at(4, 4) = 2. / pow(this->mz0, 2.); + + return dm; +} + +FloatArrayF< 6 > +LatticeFrameSteelPlastic::giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const +// returns a FloatArray(6) of initial strain vector caused by unit temperature in direction of gp (element) local axes +{ + double alpha = this->give(tAlpha, gp); + + return { + alpha, 0., 0., 0., 0., 0. + }; +} + +FloatArrayF< 6 > +LatticeFrameSteelPlastic::giveReducedStrain(GaussPoint *gp, TimeStep *tStep) const +{ + auto status = static_cast< LatticeMaterialStatus * >( this->giveStatus(gp) ); + return status->giveReducedLatticeStrain(); +} + + +FloatArrayF< 6 > +LatticeFrameSteelPlastic::performPlasticityReturn(GaussPoint *gp, const FloatArrayF< 6 > &reducedStrain, TimeStep *tStep) const +{ + double g = this->e / ( 2. * ( 1. + this->nu ) ); + const double area = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveArea(); + const double iy = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIy(); + const double iz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIz(); + const double ik = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIk(); + + auto status = static_cast< LatticeFrameSteelPlasticStatus * >( this->giveStatus(gp) ); + + //Shear components are not used for plasticity return + auto strain = reducedStrain [ { 0, 3, 4, 5 } ]; + + /* Get plastic strain vector from status*/ + auto tempPlasticStrain = status->givePlasticLatticeStrain() [ { 0, 3, 4, 5 } ]; + + FloatArrayF< 4 >tangent = { area *this->e, ik *g, iy *this->e, iz *this->e }; + + /* Compute trial stress*/ + auto stress = mult(tangent, strain - tempPlasticStrain); + + auto oldStrain = this->giveReducedStrain(gp, tStep) [ { 0, 3, 4, 5 } ]; + + /* Compute yield value*/ + double yieldValue = computeYieldValue(stress, gp, tStep); + int subIncrementCounter = 0; + + /* Check yield condition, i.e. if the yield value is less than the yield tolerance. If yield condition is valid. Do perform regular return (closest point return)*/ + + if ( yieldValue > yieldTol ) { + int subIncrementFlag = 0; + auto convergedStrain = oldStrain; + auto tempStrain = strain; + auto deltaStrain = strain - oldStrain; + //To get into the loop + status->letTempReturnResultBe(LatticeFrameSteelPlastic::RR_NotConverged); + while ( status->giveTempReturnResult() == RR_NotConverged || subIncrementFlag == 1 ) { + stress = mult(tangent, tempStrain - tempPlasticStrain); + performRegularReturn(stress, yieldValue, gp, tStep); + + if ( status->giveTempReturnResult() == RR_NotConverged ) { + subIncrementCounter++; + if ( subIncrementCounter > numberOfSubIncrements ) { + OOFEM_LOG_INFO( "Unstable element %d \n", gp->giveElement()->giveGlobalNumber() ); + OOFEM_LOG_INFO("Yield value %e \n", yieldValue); + OOFEM_LOG_INFO( "ConvergedStrain value %e %e %e %e\n", convergedStrain.at(1), convergedStrain.at(2), convergedStrain.at(3), convergedStrain.at(4) ); + OOFEM_LOG_INFO( "tempStrain value %e %e %e %e\n", tempStrain.at(1), tempStrain.at(2), tempStrain.at(3), tempStrain.at(4) ); + OOFEM_LOG_INFO( "deltaStrain value %e %e %e %e\n", deltaStrain.at(1), deltaStrain.at(2), deltaStrain.at(3), deltaStrain.at(4) ); + OOFEM_LOG_INFO( "targetstrain value %e %e %e %e\n", strain.at(1), strain.at(2), strain.at(3), strain.at(4) ); + + OOFEM_ERROR("LatticeFrameSteelPlastic :: performPlasticityReturn - Could not reach convergence with small deltaStrain, giving up."); + } + subIncrementFlag = 1; + deltaStrain *= 0.5; + tempStrain = convergedStrain + deltaStrain; + } else if ( status->giveTempReturnResult() == RR_Converged && subIncrementFlag == 1 ) { + tempPlasticStrain.at(1) = tempStrain.at(1) - stress.at(1) / ( area * this->e ); + tempPlasticStrain.at(2) = tempStrain.at(2) - stress.at(2) / ( ik * g ); + tempPlasticStrain.at(3) = tempStrain.at(3) - stress.at(3) / ( iy * this->e ); + tempPlasticStrain.at(4) = tempStrain.at(4) - stress.at(4) / ( iz * this->e ); + + status->letTempPlasticLatticeStrainBe( assemble< 6 >(tempPlasticStrain, { 0, 3, 4, 5 }) ); + + subIncrementFlag = 0; + + status->letTempReturnResultBe(LatticeFrameSteelPlastic::RR_NotConverged); + convergedStrain = tempStrain; + deltaStrain = strain - convergedStrain; + tempStrain = strain; + subIncrementCounter = 0; + } + } + } + + const double shearareay = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaY(); + const double shearareaz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaZ(); + + + tempPlasticStrain.at(1) = strain.at(1) - stress.at(1) / ( area * this->e ); + tempPlasticStrain.at(2) = strain.at(2) - stress.at(2) / ( ik * g ); + tempPlasticStrain.at(3) = strain.at(3) - stress.at(3) / ( iy * this->e ); + tempPlasticStrain.at(4) = strain.at(4) - stress.at(4) / ( iz * this->e ); + + + status->letTempPlasticLatticeStrainBe( assemble< 6 >(tempPlasticStrain, { 0, 3, 4, 5 }) ); + auto answer = assemble< 6 >(stress, { 0, 3, 4, 5 }); + answer.at(2) = shearareay * g * reducedStrain.at(2); + answer.at(3) = shearareaz * g * reducedStrain.at(3); + + return answer; +} + +Interface * +LatticeFrameSteelPlastic::giveInterface(InterfaceType type) +{ + return nullptr; +} + +void +LatticeFrameSteelPlastic::performRegularReturn(FloatArrayF< 4 > &stress, + double yieldValue, + GaussPoint *gp, + TimeStep *tStep) const +{ + //Use material specific status + auto status = static_cast< LatticeFrameSteelPlasticStatus * >( this->giveStatus(gp) ); + + double deltaLambda = 0.; + + auto trialStress = stress; + auto tempStress = trialStress; + + //initialise unknowns + FloatArrayF< 5 >unknowns; + unknowns.at(1) = trialStress.at(1); + unknowns.at(2) = trialStress.at(2); + unknowns.at(3) = trialStress.at(3); + unknowns.at(4) = trialStress.at(4); + unknowns.at(5) = 0.; + + yieldValue = computeYieldValue(tempStress, gp, tStep); + + //initiate residuals + FloatArrayF< 5 >residuals; + residuals.at(5) = yieldValue; + double normOfResiduals = 1.; //just to get into the loop + int iterationCount = 0; + while ( normOfResiduals > yieldTol ) { + iterationCount++; + if ( iterationCount == newtonIter ) { + status->letTempReturnResultBe(LatticeFrameSteelPlasticStatus::RR_NotConverged); + return; + } + + FloatArrayF< 5 >residualsNorm; + residualsNorm.at(1) = residuals.at(1) / this->nx0; + residualsNorm.at(2) = residuals.at(2) / this->mx0; + residualsNorm.at(3) = residuals.at(3) / this->my0; + residualsNorm.at(4) = residuals.at(4) / this->mz0; + residualsNorm.at(5) = residuals.at(5); + + normOfResiduals = norm(residualsNorm); + + if ( std::isnan(normOfResiduals) ) { + status->letTempReturnResultBe(LatticeFrameSteelPlasticStatus::RR_NotConverged); + return; + } + + if ( normOfResiduals > yieldTol ) { + auto jacobian = computeJacobian(tempStress, deltaLambda, gp, tStep); + + auto solution = solve_check(jacobian, residuals); + if ( solution.first ) { + unknowns -= solution.second; + } else { + status->letTempReturnResultBe(LatticeFrameSteelPlastic::RR_NotConverged); + } + + unknowns.at(5) = max(unknowns.at(5), 0.); //Keep deltaLambda greater than zero! + + /* Update increments final values and DeltaLambda*/ + tempStress.at(1) = unknowns.at(1); + tempStress.at(2) = unknowns.at(2); + tempStress.at(3) = unknowns.at(3); + tempStress.at(4) = unknowns.at(4); + deltaLambda = unknowns.at(5); + + /* Compute the fVector*/ + auto FVector = computeFVector(tempStress, gp, tStep); + double g = this->e / ( 2. * ( 1. + this->nu ) ); + const double area = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveArea(); + const double ik = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIk(); + const double iy = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIy(); + const double iz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIz(); + + residuals.at(1) = tempStress.at(1) - trialStress.at(1) + area * this->e * deltaLambda * FVector.at(1); + residuals.at(2) = tempStress.at(2) - trialStress.at(2) + ik * g * deltaLambda * FVector.at(2); + residuals.at(3) = tempStress.at(3) - trialStress.at(3) + iy * this->e * deltaLambda * FVector.at(3); + residuals.at(4) = tempStress.at(4) - trialStress.at(4) + iz * this->e * deltaLambda * FVector.at(4); + residuals.at(5) = computeYieldValue(tempStress, gp, tStep); + } + } + + status->letTempReturnResultBe(LatticeFrameSteelPlastic::RR_Converged); + ; + + stress = tempStress; +} + +FloatMatrixF< 5, 5 > +LatticeFrameSteelPlastic::computeJacobian(const FloatArrayF< 4 > &stress, + const double deltaLambda, + GaussPoint *gp, + TimeStep *tStep) const +{ + auto dMMatrix = computeDMMatrix(stress, gp, tStep); + auto fVector = computeFVector(stress, gp, tStep); + double g = this->e / ( 2. * ( 1. + this->nu ) ); + const double area = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveArea(); + const double ik = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIk(); + const double iy = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIy(); + const double iz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIz(); + + + /* Compute matrix*/ + FloatMatrixF< 5, 5 >jacobian; + jacobian.at(1, 1) = 1. + this->e * area * deltaLambda * dMMatrix.at(1, 1); + jacobian.at(1, 2) = 0.; + jacobian.at(1, 3) = 0.; + jacobian.at(1, 4) = 0.; + jacobian.at(1, 5) = this->e * area * fVector.at(1); + + jacobian.at(2, 1) = 0.; + jacobian.at(2, 2) = 1. + ik * g * deltaLambda * dMMatrix.at(2, 2); + jacobian.at(2, 3) = 0.; + jacobian.at(2, 4) = 0.; + jacobian.at(2, 5) = ik * this->e * fVector.at(2); + + jacobian.at(3, 1) = 0.; + jacobian.at(3, 2) = 0.; + jacobian.at(3, 3) = 1. + iy * this->e * deltaLambda * dMMatrix.at(3, 3); + jacobian.at(3, 4) = 0.; + jacobian.at(3, 5) = iy * this->e * fVector.at(3); + + jacobian.at(4, 1) = 0.; + jacobian.at(4, 2) = 0.; + jacobian.at(4, 3) = 0.; + jacobian.at(4, 4) = 1. + iz * this->e * deltaLambda * dMMatrix.at(4, 4); + jacobian.at(4, 5) = iz * this->e * fVector.at(4); + + jacobian.at(5, 1) = fVector.at(1); + jacobian.at(5, 2) = fVector.at(2); + jacobian.at(5, 3) = fVector.at(3); + jacobian.at(5, 4) = fVector.at(4); + jacobian.at(5, 5) = 0.; + + return jacobian; +} + +FloatArrayF< 6 > +LatticeFrameSteelPlastic::giveFrameForces3d(const FloatArrayF< 6 > &originalStrain, GaussPoint *gp, TimeStep *tStep) +{ + auto status = static_cast< LatticeFrameSteelPlasticStatus * >( this->giveStatus(gp) ); + auto reducedStrain = originalStrain; + auto thermalStrain = this->computeStressIndependentStrainVector(gp, tStep, VM_Total); + if ( thermalStrain.giveSize() ) { + reducedStrain -= FloatArrayF< 6 >(thermalStrain); + } + + auto stress = this->performPlasticityReturn(gp, reducedStrain, tStep); + + status->letTempLatticeStrainBe(originalStrain); + status->letTempReducedLatticeStrainBe(reducedStrain); + status->letTempLatticeStressBe(stress); + + return stress; +} + + + +FloatMatrixF< 6, 6 > +LatticeFrameSteelPlastic::give3dFrameStiffnessMatrix(MatResponseMode rmode, GaussPoint *gp, TimeStep *atTime) const +{ + static_cast< LatticeFrameSteelPlasticStatus * >( this->giveStatus(gp) ); + + double g = this->e / ( 2. * ( 1. + this->nu ) ); + + const double area = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveArea(); + const double ik = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIk(); + const double iy = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIy(); + const double iz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveIz(); + const double shearareay = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaY(); + const double shearareaz = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveShearAreaZ(); + + FloatArrayF< 6 >d = { + this->e * area, + g *shearareay, + g *shearareaz, + g *ik, + this->e * iy, + this->e * iz + }; + + return diag(d); +} + +LatticeFrameSteelPlasticStatus::LatticeFrameSteelPlasticStatus(int n, Domain *d, GaussPoint *g) : LatticeMaterialStatus(g) +{ } + +void +LatticeFrameSteelPlasticStatus::printOutputAt(FILE *file, TimeStep *tStep) const +{ + LatticeMaterialStatus::printOutputAt(file, tStep); + + fprintf(file, "plasticStrains "); + for ( double s : this->plasticLatticeStrain ) { + fprintf(file, "% .8e ", s); + } +} +} diff --git a/src/sm/Materials/LatticeMaterials/latticeframesteelplastic.h b/src/sm/Materials/LatticeMaterials/latticeframesteelplastic.h new file mode 100644 index 000000000..a64e76456 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeframesteelplastic.h @@ -0,0 +1,197 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticeframesteelplastic_h +#define latticeframesteelplastic_h + +#include "latticestructuralmaterial.h" +#include "cltypes.h" +#include "randommaterialext.h" +#include "strainvector.h" +#include "stressvector.h" +#include "latticematstatus.h" + +///@name Input fields for LatticeFrameSteelPlastic +//@{ +#define _IFT_LatticeFrameSteelPlastic_Name "LatticeFrameSteelPlastic" +#define _IFT_LatticeFrameSteelPlastic_talpha "talpha" +#define _IFT_LatticeFrameSteelPlastic_e "e" +#define _IFT_LatticeFrameSteelPlastic_n "n" +#define _IFT_LatticeFrameSteelPlastic_nx0 "nx0" +#define _IFT_LatticeFrameSteelPlastic_mx0 "mx0" +#define _IFT_LatticeFrameSteelPlastic_my0 "my0" +#define _IFT_LatticeFrameSteelPlastic_mz0 "mz0" +#define _IFT_LatticeFrameSteelPlastic_tol "tol" +#define _IFT_LatticeFrameSteelPlastic_iter "iter" +#define _IFT_LatticeFrameSteelPlastic_sub "sub" +#define _IFT_LatticeFrameSteelPlastic_plastic "plastic" +//@} + +namespace oofem { +/** + * This class implements associated Material Status to LatticeFrameSteelPlastic. + * @authors: Gumaa Abdelrhim, Peter Grassl + */ + +class LatticeFrameSteelPlasticStatus : public LatticeMaterialStatus +{ +public: + + enum state_flag_values { + LatticeFrameSteelPlastic_Elastic, + LatticeFrameSteelPlastic_Unloading, + LatticeFrameSteelPlastic_Plastic, + }; + + + enum LatticeFrameSteelPlastic_ReturnResult { + RR_NotConverged, + RR_Converged + }; + + +protected: + + int tempReturnResult = LatticeFrameSteelPlasticStatus::RR_NotConverged; + + + +public: + + /// Constructor + LatticeFrameSteelPlasticStatus(int n, Domain *d, GaussPoint *g); + + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + const char *giveClassName() const override { return "LatticeFrameSteelPlasticStatus"; } + + void letTempReturnResultBe(const int result) { tempReturnResult = result; } + + int giveTempReturnResult() const { return tempReturnResult; } +}; + + +/** + * This class implements a local random linear elastic model for lattice elements. + */ +class LatticeFrameSteelPlastic : public LatticeStructuralMaterial +{ +protected: + + ///Normal modulus + double e; + + ///Ratio of shear and normal modulus + double nu; + + ///maximum axial force in x-axis x-axis nx0 + double nx0; + + ///maximum bending moment about x-axis mx0 + double mx0; + + ///maximum bending moment about x-axis my0 + double my0; + + ///maximum bending moment about x-axis mz0 + double mz0; + + /// yield tolerance + double yieldTol; + + /// maximum number of iterations for stress return + double newtonIter; + + ///number Of SubIncrements + double numberOfSubIncrements; + + ///plastic flag + double plasticFlag; + + enum LatticeFrameSteelPlastic_ReturnResult { RR_NotConverged, RR_Converged }; + // mutable LatticeFrameSteelPlastic_ReturnResult returnResult = RR_NotConverged; /// FIXME: This must be removed. Not thread safe. Shouldn't be stored at all. + + double initialYieldStress = 0.; + + // + +public: + LatticeFrameSteelPlastic(int n, Domain *d) : LatticeStructuralMaterial(n, d) { }; + + FloatArrayF< 4 >computeFVector(const FloatArrayF< 4 > &sigma, GaussPoint *gp, TimeStep *tStep) const; + + FloatMatrixF< 4, 4 >computeDMMatrix(const FloatArrayF< 4 > &sigma, GaussPoint *gp, TimeStep *tStep) const; + + FloatArrayF< 6 >giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; + + FloatArrayF< 6 >giveReducedLatticeStrain(GaussPoint *gp, TimeStep *tStep) const; + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime) override; + + virtual FloatArrayF< 6 >giveReducedStrain(GaussPoint *gp, TimeStep *tStep) const; + + FloatArrayF< 6 >performPlasticityReturn(GaussPoint *gp, const FloatArrayF< 6 > &reducedStrain, TimeStep *tStep) const; + + void performRegularReturn(FloatArrayF< 4 > &stress, double yieldValue, GaussPoint *gp, TimeStep *tStep) const; + + double computeYieldValue(const FloatArrayF< 4 > &sigma, GaussPoint *gp, TimeStep *tStep) const; + + FloatMatrixF< 5, 5 >computeJacobian(const FloatArrayF< 4 > &sigma, const double deltaLambda, GaussPoint *gp, TimeStep *tStep) const; + + FloatArrayF< 6 >giveFrameForces3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) override; + + const char *giveInputRecordName() const override { return _IFT_LatticeFrameSteelPlastic_Name; } + + const char *giveClassName() const override { return "LatticeFrameSteelPlastic"; } + + void initializeFrom(InputRecord &ir) override; + + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + + Interface *giveInterface(InterfaceType) override; + + FloatMatrixF< 6, 6 >give3dFrameStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + + bool hasMaterialModeCapability(MaterialMode mode) const override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + MaterialStatus *giveStatus(GaussPoint *gp) const override; + +protected: +}; +} // end namespace oofem + +#endif diff --git a/src/sm/Materials/LatticeMaterials/latticelinearelastic.C b/src/sm/Materials/LatticeMaterials/latticelinearelastic.C new file mode 100644 index 000000000..fe7e7f1b3 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticelinearelastic.C @@ -0,0 +1,261 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticelinearelastic.h" +#include "latticematstatus.h" +#include "latticestructuralmaterial.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "CrossSections/structuralcrosssection.h" +#include "engngm.h" +#include "mathfem.h" +#include "Elements/LatticeElements/latticestructuralelement.h" +#include "datastream.h" +#include "staggeredproblem.h" +#include "contextioerr.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(LatticeLinearElastic); + +// constructor which creates a dummy material without a status and without random extension interface +LatticeLinearElastic :: LatticeLinearElastic(int n, Domain *d, double e, double a1, double a2) : + LatticeStructuralMaterial(n, d), + eNormalMean(e), + alphaOne(a1), + alphaTwo(a2) +{} + + +bool +LatticeLinearElastic :: hasMaterialModeCapability(MaterialMode mode) const +{ + return ( mode == _3dLattice ); +} + + +void +LatticeLinearElastic :: initializeFrom(InputRecord &ir) +{ + LatticeStructuralMaterial :: initializeFrom(ir); + RandomMaterialExtensionInterface :: initializeFrom(ir); + + //Young's modulus of the material that the network element is made of + IR_GIVE_FIELD(ir, this->eNormalMean, _IFT_LatticeLinearElastic_e); // Macro + + //Parameter which relates the shear stiffness to the normal stiffness. Default is 1 + alphaOne = 1.; + IR_GIVE_OPTIONAL_FIELD(ir, alphaOne, _IFT_LatticeLinearElastic_a1); // Macro + + //Parameter which is used for the definition of bending stiffness. Default is 0. + alphaTwo = 0.; + IR_GIVE_OPTIONAL_FIELD(ir, alphaTwo, _IFT_LatticeLinearElastic_a2); // Macro + + localRandomType = 0; //Default: No local random field + IR_GIVE_OPTIONAL_FIELD(ir, localRandomType, _IFT_LatticeLinearElastic_localrandomtype); // Macro + if ( localRandomType == 1 ) { //Gaussian random generator + coefficientOfVariation = 0.; + IR_GIVE_FIELD(ir, coefficientOfVariation, _IFT_LatticeLinearElastic_cov); // Macro + } + + + this->cAlpha = 0; + IR_GIVE_OPTIONAL_FIELD(ir, cAlpha, _IFT_LatticeLinearElastic_calpha); +} + +MaterialStatus * +LatticeLinearElastic :: CreateStatus(GaussPoint *gp) const +{ + return new LatticeMaterialStatus(gp); +} + +MaterialStatus * +LatticeLinearElastic :: giveStatus(GaussPoint *gp) const +{ + MaterialStatus *status = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); + if ( !status ) { + // create a new one + status = this->CreateStatus(gp); + + if ( status ) { + gp->setMaterialStatus(status); + this->_generateStatusVariables(gp); + } + } + + return status; +} + + +FloatArrayF< 6 > +LatticeLinearElastic :: giveLatticeStress3d(const FloatArrayF< 6 > &strain, + GaussPoint *gp, + TimeStep *tStep) +{ + auto status = static_cast< LatticeMaterialStatus * >( this->giveStatus(gp) ); + + this->initTempStatus(gp); + + // subtract stress independent part + auto reducedStrain = strain; + FloatArray indepStrain = this->computeStressIndependentStrainVector(gp, tStep, VM_Total); + if ( indepStrain.giveSize() > 0 ) { + reducedStrain -= FloatArrayF< 6 >(indepStrain); + } + + auto stiffnessMatrix = LatticeLinearElastic :: give3dLatticeStiffnessMatrix(ElasticStiffness, gp, tStep); + auto stress = dot(stiffnessMatrix, reducedStrain); + + //Read in fluid pressures from structural element if this is not a slave problem + FloatArray pressures; + if ( !domain->giveEngngModel()->giveMasterEngngModel() ) { + static_cast< LatticeStructuralElement * >( gp->giveElement() )->givePressures(pressures); + } + + double waterPressure = 0.; + for ( int i = 0; i < pressures.giveSize(); i++ ) { + waterPressure += 1. / pressures.giveSize() * pressures [ i ]; + } + + stress.at(1) += waterPressure; + + //Set all temp values + status->letTempLatticeStrainBe(strain); + status->letTempLatticeStressBe(stress); + + return stress; +} + + +void LatticeLinearElastic :: giveRandomParameters(FloatArray ¶m) +{ + param.resize(3); + param.zero(); + param.at(1) = localRandomType; + + if ( localRandomType == 1 ) { //Gaussian + param.at(2) = coefficientOfVariation; + } else { + OOFEM_ERROR("Error: Unknown local random type:\n randomtype 1 = Gaussian\n"); + } +} + + +Interface * +LatticeLinearElastic :: giveInterface(InterfaceType type) +{ + return nullptr; +} + + +FloatMatrixF< 6, 6 > +LatticeLinearElastic :: give3dLatticeStiffnessMatrix(MatResponseMode rmode, GaussPoint *gp, TimeStep *atTime) const +{ + //Needed to make sure that status exists before random values are requested for elastic stiffness. Problem is that gp->giveMaterialStatus does not check if status exist already + static_cast< LatticeMaterialStatus * >( this->giveStatus(gp) ); + + FloatArrayF< 6 >d = { + 1., + this->alphaOne, // shear + this->alphaOne, // shear + this->alphaTwo, // torsion + this->alphaTwo, // torsion + this->alphaTwo, // torsion + }; + + return diag(d * this->give(eNormal_ID, gp) * this->eNormalMean); +} + + +FloatMatrixF< 3, 3 > +LatticeLinearElastic :: give2dLatticeStiffnessMatrix(MatResponseMode rmode, GaussPoint *gp, TimeStep *atTime) const +{ + //Needed to make sure that status exists before random values are requested for elastic stiffness. Problem is that gp->giveMaterialStatus does not check if status exist already + static_cast< LatticeMaterialStatus * >( this->giveStatus(gp) ); + + FloatArrayF< 3 >d = { + 1., + this->alphaOne, // shear + this->alphaTwo, // torsion + }; + + return diag(d * this->give(eNormal_ID, gp) * this->eNormalMean); +} + + +FloatArrayF< 6 > +LatticeLinearElastic :: giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const +// +// returns a FloatArray(6) of initial strain vector +// caused by unit temperature in direction of +// gp (element) local axes +// +{ + double alpha = this->give(tAlpha, gp); + + //Option to add a eigendisplacement instead of strain + double length = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveLength(); + alpha += this->cAlpha / length; + + return { + alpha, 0., 0., 0., 0., 0. + }; +} + + +double +LatticeLinearElastic :: give(int aProperty, GaussPoint *gp) const +{ + this->giveStatus(gp); + + double answer; + if ( RandomMaterialExtensionInterface :: give(aProperty, gp, answer) ) { + if ( answer < 0.1 ) { //Introduce cut off to avoid numerical problems + answer = 0.1; + } else if ( answer > 10 ) { + answer = 10; + } + return answer; + } else if ( aProperty == eNormal_ID ) { + return 1.; + } else if ( aProperty == 'E' ) { + return this->eNormalMean; + } else { + return LatticeStructuralMaterial :: give(aProperty, gp); + } +} +} diff --git a/src/sm/Materials/LatticeMaterials/latticelinearelastic.h b/src/sm/Materials/LatticeMaterials/latticelinearelastic.h new file mode 100644 index 000000000..44593fda3 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticelinearelastic.h @@ -0,0 +1,123 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticelinearelastic_h +#define latticelinearelastic_h + +#include "latticestructuralmaterial.h" +#include "cltypes.h" +#include "randommaterialext.h" +#include "strainvector.h" +#include "stressvector.h" +#include "latticematstatus.h" + +///@name Input fields for LatticeLinearElastic +//@{ +#define _IFT_LatticeLinearElastic_Name "latticelinearelastic" +#define _IFT_LatticeLinearElastic_talpha "talpha" +#define _IFT_LatticeLinearElastic_e "e" +#define _IFT_LatticeLinearElastic_n "n" +#define _IFT_LatticeLinearElastic_a1 "a1" +#define _IFT_LatticeLinearElastic_a2 "a2" +#define _IFT_LatticeLinearElastic_localrandomtype "randomtype" +#define _IFT_LatticeLinearElastic_cov "cov" +#define _IFT_LatticeLinearElastic_calpha "calpha" +//@} + +namespace oofem { +/** + * This class implements a local random linear elastic model for lattice elements. + */ +class LatticeLinearElastic : public LatticeStructuralMaterial, public RandomMaterialExtensionInterface +{ +protected: + ///Normal modulus + double eNormalMean = 0.; + + ///Ratio of shear and normal modulus + double alphaOne = 0.; + + ///Ratio of torsion and normal modulus + double alphaTwo = 0.; + + /// coefficient variation of the Gaussian distribution + double coefficientOfVariation = 0.; + + /// flag which chooses between no distribution (0) and Gaussian distribution (1) + double localRandomType = 0.; + + /// parameter which allows to prescribed thermal displacement + double cAlpha = 0.; + +public: + LatticeLinearElastic(int n, Domain *d) : LatticeStructuralMaterial(n, d), RandomMaterialExtensionInterface() { }; + + + LatticeLinearElastic(int n, Domain *d, double eNormalMean, double alphaOne, double alphaTwo); + + const char *giveInputRecordName() const override { return _IFT_LatticeLinearElastic_Name; } + + const char *giveClassName() const override { return "LatticeLinearElastic"; } + + void initializeFrom(InputRecord &ir) override; + + FloatArrayF< 6 >giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; + + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + + FloatArrayF< 6 >giveLatticeStress3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) override; + + FloatMatrixF< 6, 6 >give3dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatMatrixF< 3, 3 >give2dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + + + bool hasMaterialModeCapability(MaterialMode mode) const override; + + + Interface *giveInterface(InterfaceType) override; + + virtual void giveRandomParameters(FloatArray ¶m); + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + MaterialStatus *giveStatus(GaussPoint *gp) const override; + + double give(int aProperty, GaussPoint *gp) const override; + +protected: +}; +} // end namespace oofem + +#endif diff --git a/src/sm/Materials/LatticeMaterials/latticematstatus.C b/src/sm/Materials/LatticeMaterials/latticematstatus.C new file mode 100644 index 000000000..55a734652 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticematstatus.C @@ -0,0 +1,252 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "latticematstatus.h" +#include "../structuralmaterial.h" +#include "contextioerr.h" +#include "datastream.h" +#include "gausspoint.h" + +namespace oofem { +LatticeMaterialStatus :: LatticeMaterialStatus(GaussPoint *g) : MaterialStatus(g), RandomMaterialStatusExtensionInterface() +{ } + + +void +LatticeMaterialStatus :: initTempStatus() +// +// initializes temp variables according to variables form previous equlibrium state. +// builds new crackMap +// +{ + MaterialStatus :: initTempStatus(); + + this->tempLatticeStrain = this->latticeStrain; + + this->tempInternalForces = this->internalForces; + + this->tempLatticeStress = this->latticeStress; + + this->tempReducedLatticeStrain = this->reducedLatticeStrain; + + this->tempNormalLatticeStress = this->normalLatticeStress; + + this->tempPlasticLatticeStrain = this->plasticLatticeStrain; + + this->tempDissipation = this->dissipation; + this->tempDeltaDissipation = this->deltaDissipation; + this->tempCrackFlag = this->crackFlag; + this->tempCrackWidth = this->crackWidth; + + this->tempDamageLatticeStrain = this->damageLatticeStrain; + + this->updateFlag = 0; +} + + +void +LatticeMaterialStatus :: updateYourself(TimeStep *atTime) +{ + MaterialStatus :: updateYourself(atTime); + + this->internalForces = this->tempInternalForces; + + this->latticeStress = this->tempLatticeStress; + + this->latticeStrain = this->tempLatticeStrain; + + this->plasticLatticeStrain = this->tempPlasticLatticeStrain; + + this->reducedLatticeStrain = this->tempReducedLatticeStrain; + + this->damageLatticeStrain = this->tempDamageLatticeStrain; + + this->dissipation = this->tempDissipation; + + this->deltaDissipation = this->tempDeltaDissipation; + + this->crackFlag = this->tempCrackFlag; + + this->crackWidth = this->tempCrackWidth; + + this->updateFlag = 1; +} + + +void +LatticeMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const +{ + MaterialStatus :: printOutputAt(file, tStep); + + fprintf(file, " latticestrain "); + for ( double s : this->latticeStrain ) { + fprintf(file, "% .4e ", s); + } + fprintf(file, " latticestress "); + for ( double s : this->latticeStress ) { + fprintf(file, "% .4e ", s); + } + fprintf(file, " reducedlatticestrain "); + for ( double s : this->reducedLatticeStrain ) { + fprintf(file, "% .4e ", s); + } +} + + +Interface * +LatticeMaterialStatus :: giveInterface(InterfaceType type) +{ + if ( type == RandomMaterialStatusExtensionInterfaceType ) { + return ( RandomMaterialStatusExtensionInterface * ) this; + } else { + return nullptr; + } +} + + +void +LatticeMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) +// +// saves full information stored in this Status +// no temp variables stored +// +{ + MaterialStatus :: saveContext(stream, mode); + + contextIOResultType iores; + + if ( ( iores = latticeStress.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = internalForces.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = latticeStrain.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = reducedLatticeStrain.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = plasticLatticeStrain.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = damageLatticeStrain.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = internalForces.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( !stream.write(le) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(dissipation) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(deltaDissipation) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(crackFlag) ) { + THROW_CIOERR(CIO_IOERR); + } +} + + +void +LatticeMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) +// +// restores full information stored in stream to this Status +// +{ + MaterialStatus :: saveContext(stream, mode); + + contextIOResultType iores; + + if ( ( iores = damageLatticeStrain.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = internalForces.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = latticeStress.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = latticeStrain.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = reducedLatticeStrain.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = plasticLatticeStrain.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = internalForces.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + + if ( !stream.read(le) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(dissipation) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(deltaDissipation) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(crackFlag) ) { + THROW_CIOERR(CIO_IOERR); + } + + +} +} // end namespace oofem diff --git a/src/sm/Materials/LatticeMaterials/latticematstatus.h b/src/sm/Materials/LatticeMaterials/latticematstatus.h new file mode 100644 index 000000000..b5093fc4b --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticematstatus.h @@ -0,0 +1,267 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef latticematstatus_h +#define latticematstatus_h + + +#include "../structuralms.h" +#include "randommaterialext.h" +#include "floatarrayf.h" + +namespace oofem { +class GaussPoint; +class Dictionary; +class Domain; +class NonlocalMaterialStatusExtension; + +/** + * This class implements a base lattice material status. + * In this class services are defined that are used by other + * lattice material statuses. + */ +class LatticeMaterialStatus : public MaterialStatus, public RandomMaterialStatusExtensionInterface +{ +protected: + + /// Equilibriated lattice strain + FloatArrayF< 6 >latticeStrain; + + /// Non-equilibriated lattice strain + FloatArrayF< 6 >tempLatticeStrain; + + /// Equilibriated lattice stress + FloatArrayF< 6 >latticeStress; + + /// Non-equilibriated lattice stress + FloatArrayF< 6 >tempLatticeStress; + + /// Equilibriated reduced lattice strain, which is free of thermal strain + FloatArrayF< 6 >reducedLatticeStrain; + /// Non-equilibrated reduced lattice strain, which is free of thermal strain + FloatArrayF< 6 >tempReducedLatticeStrain; + /// Equilibriated plastic lattice strain + FloatArrayF< 6 >plasticLatticeStrain; + /// Non-equilibrated plastic lattice strain + FloatArrayF< 6 >tempPlasticLatticeStrain; + /// Non-equilibrated plastic lattice strain + FloatArrayF< 6 >oldPlasticLatticeStrain; + + /// Equilibrated Internal Forces + FloatArrayF< 12 >internalForces; + ///Non-equilibrated Internal Forces + FloatArrayF< 12 >tempInternalForces; + + /// Equilibriated damage lattice strain + FloatArrayF< 6 >damageLatticeStrain; + + /// Non-equilibriated damage lattice strain + FloatArrayF< 6 >tempDamageLatticeStrain; + + + /// Equilibrated normal stress + double normalLatticeStress = 0.; + + /// Non-equilibrated normal stress + double tempNormalLatticeStress = 0.; + + /// dissipation + double dissipation = 0.; + + /// Non-equilibrated increment of dissipation + double tempDissipation = 0.; + + ///Increment of dissipation + double deltaDissipation = 0.; + + // ///Internal lForces + // double internalForces=0; + + // ///temp Internal Forces + // double tempInternalForces=0; + + /// Non-equilibrated increment of dissipation + double tempDeltaDissipation = 0.; + + /// Characteristic length + double le = 0.; + + /** the crack_flag indicates if the gp is damaged (cracked): + * crack_flag = 0 gp is undamaged + * crack_flag = 1 gp is damaged and damage grows + * crack_flag = 2 gp is damaged and damage does not grow + */ + int crackFlag = 0; + + /// Non-equilibrated temp flag. + int tempCrackFlag = 0; + + /// Non-equilibrated crack width + double tempCrackWidth = 0.; + + /// Crack width + double crackWidth = 0.; + + + int updateFlag = 0; + +public: + LatticeMaterialStatus(GaussPoint *g); + + const char *giveClassName() const override { return "LatticeMaterialStatus"; } + + void initTempStatus() override; + + void updateYourself(TimeStep *) override; + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + /// Returns lattice strain. + const FloatArrayF< 6 > &giveLatticeStrain() const { return this->latticeStrain; } + + + /// Returns lattice strain. + const FloatArrayF< 6 > &giveTempLatticeStrain() const { return this->tempLatticeStrain; } + + /// Returns reduced lattice strain. + const FloatArrayF< 6 > &giveReducedLatticeStrain() const { return reducedLatticeStrain; } + + /// Returns temp reduced lattice strain. + const FloatArrayF< 6 > &giveTempReducedLatticeStrain() const { return tempReducedLatticeStrain; } + + /// Returns plastic lattice strain. + const FloatArrayF< 6 > &givePlasticLatticeStrain() const { return this->plasticLatticeStrain; } + + /// Returns temp plastic lattice strain. + const FloatArrayF< 6 > &giveTempPlasticLatticeStrain() const { return this->tempPlasticLatticeStrain; } + + /// Returns plastic lattice strain. + const FloatArrayF< 6 > &giveOldPlasticLatticeStrain() const { return this->oldPlasticLatticeStrain; } + + /// Returns lattice stress. + const FloatArrayF< 6 > &giveLatticeStress() const { return this->latticeStress; } + /// Returns temp lattice stress. + const FloatArrayF< 6 > &giveTempLatticeStress() const { return this->tempLatticeStress; } + + /// Returns temp lattice stress. + const FloatArrayF< 12 > &giveTempInternalForces() const { return this->tempInternalForces; } + + /// Returns temp damage lattice strain. + const FloatArrayF< 6 > &giveTempDamageLatticeStrain() const { return this->tempDamageLatticeStrain; } + + /// Returns temp damage lattice strain. + const FloatArrayF< 12 > &giveInternalForces() const { return this->internalForces; } + + + /// Assigns the temp value of lattice strain. + void letTempLatticeStrainBe(const FloatArrayF< 6 > &v) { this->tempLatticeStrain = v; } + + /// Assigns the temp value of lattice strain. + void letTempReducedLatticeStrainBe(const FloatArrayF< 6 > &v) { this->tempReducedLatticeStrain = v; } + + /// Assigns the temp value of lattice strain. + void letTempPlasticLatticeStrainBe(const FloatArrayF< 6 > &v) { this->tempPlasticLatticeStrain = v; } + + /// Assigns the temp value of lattice stress. + void letTempLatticeStressBe(const FloatArrayF< 6 > &v) { this->tempLatticeStress = v; } + + /// Assigns the temp value of lattice stress. + void letTempInternalForcesBe(const FloatArrayF< 12 > &v) { this->tempInternalForces = v; } + + /// Assigns the temp value of damage lattice strain. + void letTempDamageLatticeStrainBe(const FloatArrayF< 6 > &v) { this->tempDamageLatticeStrain = v; } + + + /// Sets the temp normalStress + void setTempNormalLatticeStress(double val) { this->tempNormalLatticeStress = val; } + + /// Gives the last equilibrated normal stress + double giveNormalLatticeStress() const { return this->normalLatticeStress; } + + /// Gives the last equilibrated normal stress + double giveTempNormalLatticeStress() const { return this->tempNormalLatticeStress; } + + + ///Sets the temp_crack_flag + void setTempCrackFlag(int val) { tempCrackFlag = val; } + + ///Sets the temp_crack_width + void setTempCrackWidth(double val) { tempCrackWidth = val; } + + /** + * Returns the crack flag + * @return crack flag + */ + virtual int giveCrackFlag() const { return this->crackFlag; } + + /** + * @return crack width + */ + virtual double giveCrackWidth() const { return this->crackWidth; } + + + /// Returns characteristic length stored in receiver + double giveLe() const { return le; } + + /// Sets characteristic length to given value + void setLe(double ls) { le = ls; } + + virtual int hasBeenUpdated() const { return this->updateFlag; } + + /** + * Returns the energy dissipation computed at the GaussPoint of the element. + * This function is used for the lattice specific vtk export. + * @return dissipation + */ + virtual double giveDissipation() const { return dissipation; } + double giveTempDissipation() const { return tempDissipation; } + void setTempDissipation(double newDiss) { tempDissipation = newDiss; } + + /** + * Returns the increment of dissipation computed at the GaussPoint of the element. + * This function is used for the lattice specific vtk export. + * @return increment of dissipation + */ + virtual double giveDeltaDissipation() const { return deltaDissipation; } + double giveTempDeltaDissipation() const { return tempDeltaDissipation; } + void setTempDeltaDissipation(double newDiss) { tempDeltaDissipation = newDiss; } + + Interface *giveInterface(InterfaceType) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; +}; +} // end namespace oofem +#endif // matstatus_h diff --git a/src/sm/Materials/LatticeMaterials/latticeplasticitydamage.C b/src/sm/Materials/LatticeMaterials/latticeplasticitydamage.C new file mode 100644 index 000000000..9e58af7a3 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeplasticitydamage.C @@ -0,0 +1,1136 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticeplasticitydamage.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatmatrixf.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "engngm.h" +#include "mathfem.h" +#include +#include "latticematstatus.h" +#include "intarray.h" +#include "Elements/LatticeElements/latticestructuralelement.h" +#include "datastream.h" +#include "contextioerr.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(LatticePlasticityDamage); + +LatticePlasticityDamage::LatticePlasticityDamage(int n, Domain *d) : LatticeLinearElastic(n, d) +{} + + +bool +LatticePlasticityDamage::hasMaterialModeCapability(MaterialMode mode) const +{ + return mode == _3dLattice; +} + +void +LatticePlasticityDamage::initializeFrom(InputRecord &ir) +{ + LatticeLinearElastic::initializeFrom(ir); + + yieldTol = 1.e-6; + IR_GIVE_OPTIONAL_FIELD(ir, yieldTol, _IFT_LatticePlasticityDamage_tol); + + newtonIter = 100; + IR_GIVE_OPTIONAL_FIELD(ir, newtonIter, _IFT_LatticePlasticityDamage_iter); + + numberOfSubIncrements = 10; + IR_GIVE_OPTIONAL_FIELD(ir, numberOfSubIncrements, _IFT_LatticePlasticityDamage_sub); + + IR_GIVE_FIELD(ir, this->ft, _IFT_LatticePlasticityDamage_ft); + + IR_GIVE_FIELD(ir, this->fc, _IFT_LatticePlasticityDamage_fc); + + this->frictionAngleOne = 0.23; //Based on fc = 10*ft and fq= ft + IR_GIVE_OPTIONAL_FIELD(ir, frictionAngleOne, _IFT_LatticePlasticityDamage_angle1); + if ( this->frictionAngleOne > 0.5 ) { + OOFEM_WARNING("Friction angle angle1 very large. Really intended? Default value is 0.23"); + } + + this->frictionAngleTwo = 0.5; + IR_GIVE_OPTIONAL_FIELD(ir, frictionAngleTwo, _IFT_LatticePlasticityDamage_angle2); + + this->flowAngleOne = this->frictionAngleOne; + IR_GIVE_OPTIONAL_FIELD(ir, flowAngleOne, _IFT_LatticePlasticityDamage_flow); + if ( this->flowAngleOne > this->frictionAngleOne ) { + OOFEM_WARNING("Flow angle flow exceeds friction angle angle1. Set flow equal to angle1.\n"); + this->flowAngleOne = this->frictionAngleOne; + } + + this->flowAngleTwo = this->frictionAngleTwo; + + softeningType = 0; + IR_GIVE_OPTIONAL_FIELD(ir, softeningType, _IFT_LatticePlasticityDamage_stype); + + if ( softeningType > 1 ) { + OOFEM_ERROR("Unknown softening type"); + } + + IR_GIVE_FIELD(ir, wf, _IFT_LatticePlasticityDamage_wf); + + double ftOne = 0.; + if ( softeningType == 1 ) { //bilinear softening + ftOne = 0.15 * this->ft; + IR_GIVE_OPTIONAL_FIELD(ir, ftOne, _IFT_LatticePlasticityDamage_ft1); + this->ftOneRatio = ftOne / this->ft; + this->wfOne = 0.1 * this->wf; + IR_GIVE_OPTIONAL_FIELD(ir, wfOne, _IFT_LatticePlasticityDamage_wf1); + } + + this->aHard = 0.1; + IR_GIVE_OPTIONAL_FIELD(ir, aHard, _IFT_LatticePlasticityDamage_ahard); + + this->damageFlag = 1; + IR_GIVE_OPTIONAL_FIELD(ir, damageFlag, _IFT_LatticePlasticityDamage_damage); +} + +double +LatticePlasticityDamage::computeDamageParam(double kappaDOne, double kappaDTwo, GaussPoint *gp, TimeStep *tStep) const +{ + double ftLocal = giveTensileStrength(gp, tStep); + double fcLocal = giveCompressiveStrength(gp, tStep); + + double le = static_cast< LatticeStructuralElement * >( gp->giveElement() )->giveLength(); + double strength; + if ( ftLocal == 0 ) { + strength = ( fcLocal - this->frictionAngleOne * this->frictionAngleTwo * ftLocal ) / ( 1 + this->frictionAngleOne * this->frictionAngleTwo ); + } else { + strength = ftLocal; + } + + double omega = 0.; + if ( softeningType == 0 ) { //Default: Exponential + omega = 0; + double R = 0.; + int nite = 0; + do { + nite++; + double help = le * ( kappaDOne + omega * kappaDTwo ) / this->wf; + double Lhs = le * kappaDTwo / this->wf * strength * exp(-help) - kappaDTwo * this->eNormalMean; + R = ( 1 - omega ) * kappaDTwo * this->eNormalMean - strength * exp(-help); + omega -= R / Lhs; + if ( nite > 40 ) { + OOFEM_ERROR("computeDamageParam: algorithm not converging"); + } + } while ( fabs(R) >= 1.e-6 || omega < 0.0 ); + } else if ( softeningType == 1 ) { //bilinear: Calculate all damage parameters and check which makes sense + double omegaOne = ( this->eNormalMean * kappaDTwo * this->wfOne - ftLocal * this->wfOne - ( this->ftOneRatio * ftLocal - ftLocal ) * kappaDOne * le ) / + ( this->eNormalMean * kappaDTwo * this->wfOne + ( this->ftOneRatio * ftLocal - this->ftOneRatio * ftLocal ) * le * kappaDTwo ); + double helpOne = le * kappaDOne + le * omegaOne * kappaDTwo; + + + double omegaTwo = ( this->eNormalMean * kappaDTwo * ( this->wf - this->wfOne ) - this->ftOneRatio * ftLocal * ( this->wf - this->wfOne ) + + this->ftOneRatio * ftLocal * kappaDOne * le - this->ftOneRatio * ftLocal * this->wfOne ) / + ( this->eNormalMean * kappaDTwo * ( this->wf - this->wfOne ) - this->ftOneRatio * ftLocal * le * kappaDTwo ); + double helpTwo = le * kappaDOne + le * omegaTwo * kappaDTwo; + + + if ( helpOne >= 0. && helpOne < wfOne ) { + omega = omegaOne; + } else if ( helpTwo > wfOne && helpTwo < wf ) { + omega = omegaTwo; + } else if ( helpTwo > wf ) { + omega = 0.99999; + } + } else { + OOFEM_ERROR("Unknown softening type\n"); + } + + if ( omega > 1.0 ) { + omega = 0.99999; + } else if ( omega < 0.0 ) { + omega = 0.; + } + + return omega; +} + + +MaterialStatus * +LatticePlasticityDamage::CreateStatus(GaussPoint *gp) const +{ + return new LatticePlasticityDamageStatus(1, LatticePlasticityDamage::domain, gp); +} + + +double +LatticePlasticityDamage::computeYieldValue(const FloatArrayF< 3 > &stress, + const double kappa, + const int surface, + GaussPoint *gp, + TimeStep *tStep) const +{ + double ftLocal = giveTensileStrength(gp, tStep); + double fcLocal = giveCompressiveStrength(gp, tStep); + + double yieldValue = 0; + double hardening = computeHardening(kappa, gp); + double shearNorm = norm(stress [ { 1, 2 } ]); + + if ( surface == 0 ) { //main ellipse + yieldValue = pow(shearNorm, 2.) + pow(this->frictionAngleOne, 2.) * pow(stress.at(1), 2.) + + 2. * ( fcLocal - this->frictionAngleOne * this->frictionAngleTwo * ftLocal ) * pow(this->frictionAngleOne, 2.) / ( 1. + this->frictionAngleOne * this->frictionAngleTwo ) * hardening * stress.at(1) - + ( 2. * fcLocal * ftLocal * pow(this->frictionAngleOne, 2.) + ( 1. - this->frictionAngleOne * this->frictionAngleTwo ) * pow(ftLocal, 2.) * pow(this->frictionAngleOne, 2.) ) / ( 1. + this->frictionAngleOne * this->frictionAngleTwo ) * pow(hardening, 2.); + } else { //cap ellipse + yieldValue = pow(shearNorm, 2.) + pow(stress.at(1) / this->frictionAngleTwo, 2.) + + 2. * ( fcLocal - this->frictionAngleOne * this->frictionAngleTwo * ftLocal ) / ( pow(this->frictionAngleTwo, 2.) * ( 1. + this->frictionAngleOne * this->frictionAngleTwo ) ) * hardening * stress.at(1) + + ( pow(fcLocal, 2.) * ( 1. - pow(this->frictionAngleOne * this->frictionAngleTwo, 2.) ) - + 2. * fcLocal * ftLocal * this->frictionAngleOne * this->frictionAngleTwo * ( 1. + this->frictionAngleOne * this->frictionAngleTwo ) ) / ( pow(this->frictionAngleTwo, 2.) * pow(1. + this->frictionAngleOne * this->frictionAngleTwo, 2.) ) * pow(hardening, 2.); + } + + return yieldValue; +} + +double +LatticePlasticityDamage::computeHardening(const double kappa, GaussPoint *gp) const +{ + return exp(kappa / this->aHard); +} + +double +LatticePlasticityDamage::computeDHardeningDKappa(const double kappa, GaussPoint *gp) const +{ + return 1. / this->aHard * exp(kappa / this->aHard); +} + +double +LatticePlasticityDamage::computeDDHardeningDDKappa(const double kappa, GaussPoint *gp) const +{ + return 1. / pow(this->aHard, 2.) * exp(kappa / this->aHard); +} + +FloatArrayF< 3 > +LatticePlasticityDamage::computeFVector(const FloatArrayF< 3 > &stress, + const double kappa, + const int surface, + GaussPoint *gp, + TimeStep *tStep) const +{ + double ftLocal = giveTensileStrength(gp, tStep); + double fcLocal = giveCompressiveStrength(gp, tStep); + + double hardening = computeHardening(kappa, gp); + double dHardeningDKappa = computeDHardeningDKappa(kappa, gp); + double shearNorm = norm(stress [ { 1, 2 } ]); + + FloatArrayF< 3 >f; + if ( surface == 0 ) { //main ellipse + f.at(1) = 2. * pow(this->frictionAngleOne, 2.) * stress.at(1) + 2. * ( fcLocal - this->frictionAngleOne * this->frictionAngleTwo * ftLocal ) * pow(this->frictionAngleOne, 2.) / ( 1. + this->frictionAngleOne * this->frictionAngleTwo ) * hardening; + f.at(2) = 2. * shearNorm; + f.at(3) = 2. * ( fcLocal - this->frictionAngleOne * this->frictionAngleTwo * ftLocal ) * pow(this->frictionAngleOne, 2.) / ( 1. + this->frictionAngleOne * this->frictionAngleTwo ) * stress.at(1) * dHardeningDKappa - + 2. * ( 2. * fcLocal * ftLocal * pow(this->frictionAngleOne, 2.) + ( 1. - this->frictionAngleOne * this->frictionAngleTwo ) * pow(ftLocal, 2.) * pow(this->frictionAngleOne, 2.) ) / ( 1. + this->frictionAngleOne * this->frictionAngleTwo ) * hardening * dHardeningDKappa; + } else { //cap ellipse + f.at(1) = 2. * stress.at(1) / pow(this->frictionAngleTwo, 2.) + 2. * ( fcLocal - this->frictionAngleOne * this->frictionAngleTwo * ftLocal ) / ( pow(this->frictionAngleTwo, 2.) * ( 1. + this->frictionAngleOne * this->frictionAngleTwo ) ) * hardening; + f.at(2) = 2. * shearNorm; + f.at(3) = 2. * ( fcLocal - this->frictionAngleOne * this->frictionAngleTwo * ftLocal ) / ( pow(this->frictionAngleTwo, 2.) * ( 1. + this->frictionAngleOne * this->frictionAngleTwo ) ) * stress.at(1) * dHardeningDKappa + + 2. * ( pow(fcLocal, 2.) * ( 1. - pow(this->frictionAngleOne * this->frictionAngleTwo, 2.) ) - + 2. * fcLocal * ftLocal * this->frictionAngleOne * this->frictionAngleTwo * ( 1. + this->frictionAngleOne * this->frictionAngleTwo ) ) / + ( pow(frictionAngleTwo, 2.) * pow(1. + this->frictionAngleOne * this->frictionAngleTwo, 2.) ) * hardening * dHardeningDKappa; + } + + return f; +} + +FloatArrayF< 3 > +LatticePlasticityDamage::computeMVector(const FloatArrayF< 3 > &stress, + const double kappa, + const int surface, + GaussPoint *gp, + TimeStep *tStep) const +{ + double ftLocal = giveTensileStrength(gp, tStep); + double fcLocal = giveCompressiveStrength(gp, tStep); + + double hardening = computeHardening(kappa, gp); + double shearNorm = norm(stress [ { 1, 2 } ]); + + FloatArrayF< 3 >m; + if ( surface == 0 ) { //main ellips + m.at(1) = 2. * pow(this->flowAngleOne, 2.) * stress.at(1) + 2. * ( fcLocal - this->flowAngleOne * this->flowAngleTwo * ftLocal ) * pow(this->flowAngleOne, 2.) / ( 1. + this->flowAngleOne * this->flowAngleTwo ) * hardening; + m.at(2) = 2. * shearNorm; + m.at(3) = fabs(m.at(1) ); + } else { //cap + m.at(1) = 2. * stress.at(1) / pow(this->flowAngleTwo, 2.) + 2. * ( fcLocal - this->flowAngleTwo * this->flowAngleOne * ftLocal ) / ( pow(this->flowAngleTwo, 2.) * ( 1. + this->flowAngleOne * this->flowAngleTwo ) ) * hardening; + m.at(2) = 2. * shearNorm; + m.at(3) = fabs(m.at(1) ); + } + + return m; +} + + +FloatMatrixF< 3, 3 > +LatticePlasticityDamage::computeDMMatrix(const FloatArrayF< 3 > &stress, const double kappa, const int surface, GaussPoint *gp, TimeStep *tStep) const +{ + double ftLocal = giveTensileStrength(gp, tStep); + double fcLocal = giveCompressiveStrength(gp, tStep); + + double dHardeningDKappa = computeDHardeningDKappa(kappa, gp); + + FloatMatrixF< 3, 3 >dm; + if ( surface == 0 ) { //main ellipse + //Derivatives of dGDSig + dm.at(1, 1) = 2. * pow(this->flowAngleOne, 2.); + dm.at(1, 2) = 0.; + dm.at(1, 3) = 2. * ( fcLocal - this->flowAngleOne * this->flowAngleTwo * ftLocal ) * pow(this->flowAngleOne, 2.) / ( 1. + this->flowAngleOne * this->flowAngleTwo ) * dHardeningDKappa; + + //Derivatives of dGDTau + dm.at(2, 1) = 0.; + dm.at(2, 2) = 2.; + dm.at(2, 3) = 0; + + //Derivates of evolution law + dm.at(3, 1) = dm.at(1, 1); + dm.at(3, 2) = dm.at(1, 2); + dm.at(3, 3) = dm.at(1, 3); + } else { //cap ellipse + //Derivatives of dGDSig + dm.at(1, 1) = 2. / pow(this->flowAngleTwo, 2.); + dm.at(1, 2) = 0.; + dm.at(1, 3) = 2. * ( fcLocal - this->flowAngleOne * this->flowAngleTwo * ftLocal ) / ( pow(this->flowAngleTwo, 2.) * ( 1. + this->flowAngleOne * this->flowAngleTwo ) ) * dHardeningDKappa; + + //Derivatives of dGDTau + dm.at(2, 1) = 0.; + dm.at(2, 2) = 2.; + dm.at(2, 3) = 0; + + //Derivates of evolution law + dm.at(3, 1) = -dm.at(1, 1); + dm.at(3, 2) = -dm.at(1, 2); + dm.at(3, 3) = -dm.at(1, 3); + } + return dm; +} + + +FloatArrayF< 6 > +LatticePlasticityDamage::giveReducedStrain(GaussPoint *gp, TimeStep *tStep) const +{ + auto status = static_cast< LatticePlasticityDamageStatus * >( this->giveStatus(gp) ); + return status->giveReducedLatticeStrain(); +} + + +int +LatticePlasticityDamage::checkTransition(const FloatArrayF< 3 > &sigma, const double tempKappa, GaussPoint *gp, TimeStep *tStep) const +{ + int surface = -1; + + double ftLocal = giveTensileStrength(gp, tStep); + double fcLocal = giveCompressiveStrength(gp, tStep); + + double hardening = computeHardening(tempKappa, gp); + double transition = -( fcLocal - this->frictionAngleOne * this->frictionAngleTwo * ftLocal ) / ( 1. + this->frictionAngleOne * this->frictionAngleTwo ) * hardening; + + if ( sigma.at(1) >= transition ) {//main ellipse + surface = 0; + } else if ( sigma.at(1) < transition ) {//cap ellipse + surface = 1; + } else { + OOFEM_ERROR("LatticePlasticityDamage :: check transition wrong\n"); + } + + return surface; +} + + + +FloatArrayF< 6 > +LatticePlasticityDamage::performPlasticityReturn(GaussPoint *gp, + const FloatArrayF< 6 > &reducedStrain, + TimeStep *tStep) const +{ + FloatArrayF<6> answer; + + LatticePlasticityDamage_ReturnResult returnResult = RR_Unknown; + + double fcLocal = giveCompressiveStrength(gp, tStep); + auto status = static_cast< LatticePlasticityDamageStatus * >( this->giveStatus(gp) ); + + //Get kappa from the status + double tempKappa = status->giveKappaP(); + + //Subset of reduced strain. + //Rotational components are not used for plasticity return + auto strain = reducedStrain [ { 0, 1, 2 } ]; + + /* Get plastic strain vector from status*/ + auto tempPlasticStrain = status->givePlasticLatticeStrain() [ { 0, 1, 2 } ]; + + FloatArrayF< 3 >tangent = { this->eNormalMean, this->alphaOne * this->eNormalMean, this->alphaOne * this->eNormalMean }; + + /* Compute trial stress*/ + auto stress = mult(tangent, strain - tempPlasticStrain); + + //Introduce variables for subincrementation + //Only _3dLattice is possible + + auto oldStrain = this->giveReducedStrain(gp, tStep) [ { 0, 1, 2 } ]; + + //Determine region of stress. + int surface = checkTransition(stress, tempKappa, gp, tStep); + + /* Compute yield value*/ + double yieldValue = computeYieldValue(stress, tempKappa, surface, gp, tStep); + int subIncrementCounter = 0; + + /* Check yield condition, i.e. if the yield value is less than the yield tolerance. + * If yield condition is valid. Do perform regular return (closest point return)*/ + + if ( yieldValue / pow(fcLocal, 2.) > yieldTol ) { + // introduce a subincrementation flag + int subIncrementFlag = 0; + auto convergedStrain = oldStrain; + auto tempStrain = strain; + auto deltaStrain = strain - oldStrain; + //To get into the loop + returnResult = RR_NotConverged; + while ( returnResult == RR_NotConverged || subIncrementFlag == 1 ) { + stress = mult(tangent, tempStrain - tempPlasticStrain); + + tempKappa = performRegularReturn(stress, returnResult, yieldValue, surface, gp, tStep); + + if ( returnResult == RR_NotConverged ) { + subIncrementCounter++; + if ( subIncrementCounter > numberOfSubIncrements ) { + OOFEM_LOG_INFO("Unstable element %d \n", gp->giveElement()->giveGlobalNumber() ); + OOFEM_LOG_INFO("Yield value %e \n", yieldValue); + OOFEM_LOG_INFO("ConvergedStrain value %e %e %e\n", convergedStrain.at(1), convergedStrain.at(2), convergedStrain.at(3) ); + OOFEM_LOG_INFO("tempStrain value %e %e %e\n", tempStrain.at(1), tempStrain.at(2), tempStrain.at(3) ); + OOFEM_LOG_INFO("deltaStrain value %e %e %e\n", deltaStrain.at(1), deltaStrain.at(2), deltaStrain.at(3) ); + OOFEM_LOG_INFO("targetstrain value %e %e %e\n", strain.at(1), strain.at(2), strain.at(3) ); + + OOFEM_WARNING("LatticePlasticityDamage :: performPlasticityReturn - Could not reach convergence with small deltaStrain, giving up. Delete element.\n"); + status->setTempDeletionFlag(1); + for(int k=0; k<6;k++){ + answer.at(k+1) = 0.; + } + return answer; + } + + subIncrementFlag = 1; + deltaStrain *= 0.5; + tempStrain = convergedStrain + deltaStrain; + } else if ( returnResult == RR_Converged && subIncrementFlag == 1 ) { + tempPlasticStrain.at(1) = tempStrain.at(1) - stress.at(1) / eNormalMean; + tempPlasticStrain.at(2) = tempStrain.at(2) - stress.at(2) / ( this->alphaOne * eNormalMean ); + tempPlasticStrain.at(3) = tempStrain.at(3) - stress.at(3) / ( this->alphaOne * eNormalMean ); + + status->letTempPlasticLatticeStrainBe(assemble< 6 >(tempPlasticStrain, { 0, 1, 2 }) ); + status->setTempKappaP(tempKappa); + + subIncrementFlag = 0; + returnResult = RR_NotConverged; + convergedStrain = tempStrain; + deltaStrain = strain - convergedStrain; + tempStrain = strain; + subIncrementCounter = 0; + } else {//Converged + //Check the surface + int surfaceCheck = checkTransition(stress, tempKappa, gp, tStep); + status->setTempKappaP(tempKappa); + // if ( surfaceCheck != surface ) { + // // OOFEM_WARNING("LatticePlasticityDamage::PerformPlasticityReturn Wrong surface. Try the other\n"); + // surface = surfaceCheck; + // returnResult = RR_NotConverged; + // } + } + } + } + + tempPlasticStrain.at(1) = strain.at(1) - stress.at(1) / eNormalMean; + tempPlasticStrain.at(2) = strain.at(2) - stress.at(2) / ( this->alphaOne * eNormalMean ); + tempPlasticStrain.at(3) = strain.at(3) - stress.at(3) / ( this->alphaOne * eNormalMean ); + + status->letTempPlasticLatticeStrainBe(assemble< 6 >(tempPlasticStrain, { 0, 1, 2 }) ); + + + // status->letTempLatticeStressBe(assemble< 6 >(stress, { 0, 1, 2 }) ); + + answer = assemble< 6 >(stress, { 0, 1, 2 }); + answer.at(4) = this->alphaTwo * this->eNormalMean * reducedStrain.at(4); + answer.at(5) = this->alphaTwo * this->eNormalMean * reducedStrain.at(5); + answer.at(6) = this->alphaTwo * this->eNormalMean * reducedStrain.at(6); + + return answer; +} + + +double +LatticePlasticityDamage::performRegularReturn(FloatArrayF< 3 > &stress, + LatticePlasticityDamage_ReturnResult &returnResult, + double yieldValue, + const int surface, + GaussPoint *gp, + TimeStep *tStep) const +{ + double fcLocal = giveCompressiveStrength(gp, tStep); + + auto status = static_cast< LatticePlasticityDamageStatus * >( this->giveStatus(gp) ); + + double deltaLambda = 0.; + + auto trialStress = stress; + auto tempStress = trialStress; + + double trialShearStressNorm = norm(trialStress [ { 1, 2 } ]); + + double tempShearStressNorm = trialShearStressNorm; + + double thetaTrial = atan2(stress.at(3), stress.at(2) ); + + // Do the same for kappa + double kappa = status->giveKappaP(); + double tempKappa = kappa; + + //initialise unknowns + FloatArrayF< 4 >unknowns; + unknowns.at(1) = trialStress.at(1); + unknowns.at(2) = trialShearStressNorm; + unknowns.at(3) = tempKappa; + unknowns.at(4) = 0.; + + // Look at the magnitudes of the residuals. You have to scale the yieldValue down. + yieldValue = computeYieldValue(tempStress, tempKappa, surface, gp, tStep); + + //initiate residuals + FloatArrayF< 4 >residuals; + residuals.at(4) = yieldValue; + + double normOfResiduals = 1.; //just to get into the loop + + int iterationCount = 0; + while ( normOfResiduals > yieldTol ) { + iterationCount++; + if ( iterationCount == newtonIter ) { + returnResult = RR_NotConverged; + return 0.; + } + + //Normalize residuals. Think about it more. + FloatArrayF< 4 >residualsNorm; + residualsNorm.at(1) = residuals.at(1) / fcLocal; + residualsNorm.at(2) = residuals.at(2) / fcLocal; + residualsNorm.at(3) = residuals.at(3); + residualsNorm.at(4) = residuals.at(4) / pow(fcLocal, 2.); + + normOfResiduals = norm(residualsNorm); + + //First check if return has failed + if ( std::isnan(normOfResiduals) ) { + returnResult = RR_NotConverged; + return 0.; + } + + if ( normOfResiduals > yieldTol ) { + // Test to run newton iteration using inverse of Jacobian + auto jacobian = computeJacobian(tempStress, tempKappa, deltaLambda, surface, gp, tStep); + + auto solution = solve_check(jacobian, residuals); + if ( solution.first ) { + unknowns -= solution.second; + } else { + returnResult = RR_NotConverged; + return kappa; + } + + unknowns.at(2) = max(unknowns.at(2), 0.); //Keep rho greater than zero! + unknowns.at(3) = max(unknowns.at(3), kappa); //Keep deltaKappa greater than zero! + unknowns.at(4) = max(unknowns.at(4), 0.); //Keep deltaLambda greater than zero! + + /* Update increments final values and DeltaLambda*/ + tempStress.at(1) = unknowns.at(1); + tempShearStressNorm = unknowns.at(2); + + tempStress.at(2) = tempShearStressNorm * cos(thetaTrial); + tempStress.at(3) = tempShearStressNorm * sin(thetaTrial); + + tempKappa = unknowns.at(3); + deltaLambda = unknowns.at(4); + + /* Compute the mVector holding the derivatives of the g function and the hardening function*/ + auto mVector = computeMVector(tempStress, tempKappa, surface, gp, tStep); + + residuals.at(1) = tempStress.at(1) - trialStress.at(1) + this->eNormalMean * deltaLambda * mVector.at(1); + residuals.at(2) = tempShearStressNorm - trialShearStressNorm + this->alphaOne * this->eNormalMean * deltaLambda * mVector.at(2); + residuals.at(3) = -tempKappa + kappa + deltaLambda * mVector.at(3); + residuals.at(4) = computeYieldValue(tempStress, tempKappa, surface, gp, tStep); + } + } + + returnResult = RR_Converged; + + stress = tempStress; + + return tempKappa; +} + + + +FloatMatrixF< 4, 4 > +LatticePlasticityDamage::computeJacobian(const FloatArrayF< 3 > &stress, + const double kappa, + const double deltaLambda, + const int surface, + GaussPoint *gp, + TimeStep *tStep) const +{ + auto dMMatrix = computeDMMatrix(stress, kappa, surface, gp, tStep); + auto mVector = computeMVector(stress, kappa, surface, gp, tStep); + auto fVector = computeFVector(stress, kappa, surface, gp, tStep); + + /* Compute matrix*/ + FloatMatrixF< 4, 4 >jacobian; + jacobian.at(1, 1) = 1. + this->eNormalMean * deltaLambda * dMMatrix.at(1, 1); + jacobian.at(1, 2) = this->eNormalMean * deltaLambda * dMMatrix.at(1, 2); + jacobian.at(1, 3) = this->eNormalMean * deltaLambda * dMMatrix.at(1, 3); + jacobian.at(1, 4) = this->eNormalMean * mVector.at(1); + /**/ + jacobian.at(2, 1) = this->alphaOne * this->eNormalMean * deltaLambda * dMMatrix.at(2, 1); + jacobian.at(2, 2) = 1. + this->alphaOne * this->eNormalMean * deltaLambda * dMMatrix.at(2, 2); + jacobian.at(2, 3) = this->alphaOne * this->eNormalMean * deltaLambda * dMMatrix.at(2, 3); + jacobian.at(2, 4) = this->alphaOne * this->eNormalMean * mVector.at(2); + /**/ + jacobian.at(3, 1) = deltaLambda * dMMatrix.at(3, 1); + jacobian.at(3, 2) = deltaLambda * dMMatrix.at(3, 2); + jacobian.at(3, 3) = deltaLambda * dMMatrix.at(3, 3) - 1.; + jacobian.at(3, 4) = mVector.at(3); + /**/ + jacobian.at(4, 1) = fVector.at(1); + jacobian.at(4, 2) = fVector.at(2); + jacobian.at(4, 3) = fVector.at(3); + jacobian.at(4, 4) = 0.; + + return jacobian; +} + +double +LatticePlasticityDamage::give(int aProperty, GaussPoint *gp) const +{ + this->giveStatus(gp); + + double answer; + if ( RandomMaterialExtensionInterface::give(aProperty, gp, answer) ) { + return answer; + } else if ( aProperty == fc_strength ) { + return 1.; + } else if ( aProperty == ft_strength ) { + return 1.; + } else { + return LatticeLinearElastic::give(aProperty, gp); + } +} + + +FloatArrayF< 6 > +LatticePlasticityDamage::giveLatticeStress3d(const FloatArrayF< 6 > &originalStrain, GaussPoint *gp, TimeStep *tStep) +{ + auto status = static_cast< LatticePlasticityDamageStatus * >( this->giveStatus(gp) ); + status->initTempStatus(); + + FloatArrayF<6> stress; + + if(status->giveTempDeletionFlag()==1){ + //Deal with deleted element + return stress; + + } + + + + auto reducedStrain = originalStrain; + auto thermalStrain = this->computeStressIndependentStrainVector(gp, tStep, VM_Total); + if ( thermalStrain.giveSize() ) { + reducedStrain -= FloatArrayF< 6 >(thermalStrain); + } + + auto effectiveStress = this->performPlasticityReturn(gp, reducedStrain, tStep); + + stress = effectiveStress; + + //TODO: Compute dissipation + double tempDissipation = status->giveDissipation(); + double tempTensionDissipation = status->giveTensionDissipation(); + double tempShearDissipation = status->giveShearDissipation(); + double tempCompressionDissipation = status->giveCompressionDissipation(); + double tempDeltaDissipation = 0., tempTensionDeltaDissipation = 0., tempShearDeltaDissipation = 0., tempCompressionDeltaDissipation = 0.; + + if(status->giveTempDeletionFlag()==1){ + //Deal with deleted element + return stress; + } + + double omega = 0.; + if ( damageFlag == 1 ) { + this->performDamageEvaluation(gp, reducedStrain, tStep); + omega = status->giveTempDamage(); + } + + stress *= ( 1. - omega ); + + tempDeltaDissipation = computeDeltaDissipation(omega, reducedStrain, gp, tStep); + + //Check what stress state the model is in + double tempKappaP = status->giveTempKappaP(); + auto reducedEffectiveStress = effectiveStress [ { 0, 1, 2 } ]; + int surface = checkTransition(reducedEffectiveStress, tempKappaP, gp, tStep); + + if(effectiveStress.at(1) > 0.){ + tempTensionDeltaDissipation = tempDeltaDissipation; + tempTensionDissipation +=tempDeltaDissipation; + } + else if(stress.at(1)<0 && surface == 0){ + tempShearDeltaDissipation = tempDeltaDissipation; + tempShearDissipation +=tempDeltaDissipation; + } + else{ + tempCompressionDeltaDissipation = tempDeltaDissipation; + tempCompressionDissipation +=tempDeltaDissipation; + } + + tempDissipation += tempDeltaDissipation; + + status->setTempDissipation(tempDissipation); + status->setTempTensionDissipation(tempTensionDissipation); + status->setTempShearDissipation(tempShearDissipation); + status->setTempCompressionDissipation(tempCompressionDissipation); + + status->setTempDeltaDissipation(tempDeltaDissipation); + status->setTempTensionDeltaDissipation(tempTensionDeltaDissipation); + status->setTempShearDeltaDissipation(tempShearDeltaDissipation); + status->setTempCompressionDeltaDissipation(tempCompressionDeltaDissipation); + + status->letTempLatticeStrainBe(originalStrain); + status->letTempReducedLatticeStrainBe(reducedStrain); + status->letTempLatticeStressBe(stress); + + return stress; +} + + +void +LatticePlasticityDamage::performDamageEvaluation(GaussPoint *gp, FloatArrayF< 6 > &reducedStrain, TimeStep *tStep) const +{ + double ftLocal = giveTensileStrength(gp, tStep); + double fcLocal = giveCompressiveStrength(gp, tStep); + + auto status = static_cast< LatticePlasticityDamageStatus * >( this->giveStatus(gp) ); + + double le = static_cast< LatticeStructuralElement * >( gp->giveElement() )->giveLength(); + + auto tempPlasticStrain = status->giveTempPlasticLatticeStrain(); + auto plasticStrain = status->givePlasticLatticeStrain(); + auto deltaPlasticStrain = tempPlasticStrain - plasticStrain; + + //Compute the damage history variable + double omega = status->giveDamage(); + double tempKappaDOne = status->giveKappaDOne(); + double tempKappaDTwo = status->giveKappaDTwo(); + + // Compute deltaKappaP from the plastic Strain + double tempKappaP = status->giveTempKappaP(); + double kappaP = status->giveKappaP(); + double deltaKappaP = tempKappaP - kappaP; + double hardening = computeHardening(tempKappaP, gp); + + double strength = ( fcLocal - this->frictionAngleOne * this->frictionAngleTwo * ftLocal ) / ( 1 + this->frictionAngleOne * this->frictionAngleTwo ); + + if ( deltaKappaP <= 0. ) { //unloading or reloading + tempKappaDOne = status->giveKappaDOne(); + tempKappaDTwo = status->giveKappaDTwo(); + omega = status->giveDamage(); + if ( status->giveCrackFlag() != 0 ) { + status->setTempCrackFlag(2); + } else { + status->setTempCrackFlag(0); + } + } else { //plastic loading + if ( deltaPlasticStrain.at(1) <= 0. ) { //compressive side! No damage + tempKappaDOne = status->giveKappaDOne(); + tempKappaDTwo = status->giveKappaDTwo(); + omega = status->giveDamage(); + status->setTempCrackFlag(3); + } else { + tempKappaDOne += deltaPlasticStrain.at(1); + + if ( ftLocal == 0 ) { + tempKappaDTwo = hardening * strength / this->eNormalMean; + } else { + tempKappaDTwo = hardening * ftLocal / this->eNormalMean; + } + + // evaluate damage parameter + omega = this->computeDamageParam(tempKappaDOne, tempKappaDTwo, gp, tStep); + + //threshold for crack patterns + if ( ( tempKappaDOne + omega * tempKappaDTwo ) * le > 0. ) { + status->setTempCrackFlag(1); + } else { + status->setTempCrackFlag(0); + } + } + } + + //Create history variables for the damage strain + FloatArrayF< 6 >elasticReducedStrain = reducedStrain - tempPlasticStrain; + FloatArrayF< 6 >tempDamageLatticeStrain = omega * elasticReducedStrain; + status->letTempDamageLatticeStrainBe(tempDamageLatticeStrain); + + double crackWidth = norm(tempPlasticStrain + omega * ( reducedStrain - tempPlasticStrain ) ) * le; + + status->setTempKappaDOne(tempKappaDOne); + status->setTempKappaDTwo(tempKappaDTwo); + status->setTempDamage(omega); + status->setTempCrackWidth(crackWidth); +} + +/*double LatticePlasticityDamage :: giveMaterialParameter() + * { + * return this->ft; + * }*/ + + +double +LatticePlasticityDamage :: computeDeltaDissipation(const double omega, + const FloatArray &tempReducedStrain, + GaussPoint *gp, + TimeStep *tStep) const +{ + auto status = static_cast< LatticePlasticityDamageStatus * >( this->giveStatus(gp) ); + + double length = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveLength(); + + auto plasticStrain = status->givePlasticLatticeStrain() [ { 0, 1, 2 } ]; + auto tempPlasticStrain = status->giveTempPlasticLatticeStrain() [ { 0, 1, 2 } ]; + auto deltaPlasticStrain = tempPlasticStrain-plasticStrain; + auto reducedStrain = status->giveReducedLatticeStrain(); + double omegaOld = status->giveDamage(); + double deltaOmega; + + deltaOmega = ( omega - omegaOld ); + double deltaDissPlastic = length * (1.-omega)*((tempReducedStrain.at(1)-tempPlasticStrain.at(1) + + reducedStrain.at(1)-plasticStrain.at(1))/2. + * this->eNormalMean * deltaPlasticStrain.at(1) + + (tempReducedStrain.at(2)-tempPlasticStrain.at(2) + + reducedStrain.at(2)-plasticStrain.at(2))/2. + *this->alphaOne * this->eNormalMean * deltaPlasticStrain.at(2) + + (tempReducedStrain.at(3)-tempPlasticStrain.at(3) + + reducedStrain.at(3)-plasticStrain.at(3))/2. + *this->alphaOne * this->eNormalMean * deltaPlasticStrain.at(3)); + + double deltaDissDamage = 0.5 * length * ( pow( ( tempReducedStrain.at(1)-tempPlasticStrain.at(1) + reducedStrain.at(1) - plasticStrain.at(1) ) / 2., 2. ) * this->eNormalMean + + pow( ( tempReducedStrain.at(2)-tempPlasticStrain.at(2) + reducedStrain.at(2) - plasticStrain.at(2) ) / 2., 2. ) * this->alphaOne*this->eNormalMean + + pow( ( tempReducedStrain.at(3)-tempPlasticStrain.at(3) + reducedStrain.at(3) - plasticStrain.at(3) ) / 2., 2. ) * this->alphaOne*this->eNormalMean + + pow( ( tempReducedStrain.at(4) + reducedStrain.at(4) ) / 2., 2. ) * this->alphaTwo * this->eNormalMean + + pow( ( tempReducedStrain.at(5) + reducedStrain.at(5) ) / 2., 2. ) * this->alphaTwo * this->eNormalMean + + pow( ( tempReducedStrain.at(6) + reducedStrain.at(6) ) / 2., 2. ) * this->alphaTwo* this->eNormalMean ) * deltaOmega; + + double totalDeltaDiss = deltaDissDamage + deltaDissPlastic; + + return totalDeltaDiss; +} + + +FloatMatrixF< 6, 6 > +LatticePlasticityDamage::give3dLatticeStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto elastic = LatticeLinearElastic::give3dLatticeStiffnessMatrix(mode, gp, tStep); + + if ( mode == ElasticStiffness ) { + return elastic; + } else if ( ( mode == SecantStiffness ) || ( mode == TangentStiffness ) ) { + auto status = static_cast< LatticePlasticityDamageStatus * >( this->giveStatus(gp) ); + double omega = min(status->giveTempDamage(), 0.99999); + return elastic * ( 1. - omega ); + } else { + OOFEM_ERROR("Unsupported stiffness mode\n"); + return elastic; + } +} + +int +LatticePlasticityDamage::giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) +{ + auto status = static_cast< LatticePlasticityDamageStatus * >( this->giveStatus(gp) ); + + if ( type == IST_DamageTensor ) { + answer.resize(6); + answer.zero(); + answer.at(1) = answer.at(2) = answer.at(3) = status->giveDamage(); + return 1; + } else if ( type == IST_DamageScalar ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveDamage(); + return 1; + } else if ( type == IST_CrackedFlag ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveCrackFlag(); + return 1; + } else if ( type == IST_DissWork ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveDissipation(); + return 1; + } else if ( type == IST_DeltaDissWork ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveDeltaDissipation(); + return 1; + } else if ( type == IST_CrackWidth ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveCrackWidth(); + return 1; + } else if ( type == IST_CharacteristicLength ) { + answer.resize(1); + answer.zero(); + answer.at(1) = static_cast< LatticeStructuralElement * >( gp->giveElement() )->giveLength(); + return 1; + } else if ( type == IST_PlasticLatticeStrain ) { + answer = status->givePlasticLatticeStrain(); + return 1; + } else if ( type == IST_TensileStrength ) { + answer.resize(1); + answer.at(1); + answer.at(1) = giveTensileStrength(gp, atTime); + return 1; + } else if ( type == IST_TensionDissWork ) { + answer.resize(1); + answer.at(1); + answer.at(1) = status->giveTensionDissipation(); + return 1; + } else if ( type == IST_TensionDeltaDissWork ) { + answer.resize(1); + answer.at(1); + answer.at(1) = status->giveTensionDeltaDissipation(); + return 1; + } else if ( type == IST_ShearDissWork ) { + answer.resize(1); + answer.at(1); + answer.at(1) = status->giveShearDissipation(); + return 1; + } else if ( type == IST_ShearDeltaDissWork ) { + answer.resize(1); + answer.at(1); + answer.at(1) = status->giveShearDeltaDissipation(); + return 1; + } else if ( type == IST_CompressionDissWork ) { + answer.resize(1); + answer.at(1); + answer.at(1) = status->giveCompressionDissipation(); + return 1; + } else if ( type == IST_CompressionDeltaDissWork ) { + answer.resize(1); + answer.at(1); + answer.at(1) = status->giveCompressionDeltaDissipation(); + return 1; + } + + + + else { + return LatticeLinearElastic::giveIPValue(answer, gp, type, atTime); + } +} + + +LatticePlasticityDamageStatus::LatticePlasticityDamageStatus(int n, Domain *d, GaussPoint *g) : LatticeMaterialStatus(g) +{ } + +void +LatticePlasticityDamageStatus::initTempStatus() +{ + LatticeMaterialStatus::initTempStatus(); + this->tempKappaP = this->kappaP; + this->tempKappaDOne = this->kappaDOne; + this->tempKappaDTwo = this->kappaDTwo; + this->tempDamage = this->damage; + this->tempDissipation = this->dissipation; + this->tempTensionDissipation = this->tensionDissipation; + this->tempShearDissipation = this->shearDissipation; + this->tempCompressionDissipation = this->compressionDissipation; + this->tempDeltaDissipation = 0.; + this->tempTensionDeltaDissipation = 0.; + this->tempShearDeltaDissipation = 0.; + this->tempCompressionDeltaDissipation = 0.; + this->tempDeletionFlag = this->deletionFlag; +} + +void +LatticePlasticityDamageStatus::printOutputAt(FILE *file, TimeStep *tStep) const +{ + LatticeMaterialStatus::printOutputAt(file, tStep); + + fprintf(file, "plasticStrains "); + for ( double s : this->plasticLatticeStrain ) { + fprintf(file, "% .8e ", s); + } + + fprintf(file, ", kappaP %.8e, kappaDOne %.8e, kappaDTwo %.8e, damage %.8e, deltaDissipation %.8e, dissipation %.8e, tensionDeltaDissipation %.8e, tensionDissipation %.8e, shearDeltaDissipation %.8e, shearDissipation %.8e, compressionDeltaDissipation %.8e, compressionDissipation %.8e, crackFlag %d, crackWidth %.8e \n", this->kappaP, this->kappaDOne, this->kappaDTwo, this->damage, this->deltaDissipation, this->dissipation, this->tensionDeltaDissipation, this->tensionDissipation, this->shearDeltaDissipation, this->shearDissipation, this->compressionDeltaDissipation, this->compressionDissipation, this->crackFlag, this->crackWidth); +} + + +void +LatticePlasticityDamageStatus::updateYourself(TimeStep *atTime) +// +// updates variables (nonTemp variables describing situation at previous equilibrium state) +// after a new equilibrium state has been reached +// temporary variables are having values corresponding to newly reached equilibrium. +// +{ + LatticeMaterialStatus::updateYourself(atTime); + this->kappaP = this->tempKappaP; + this->kappaDOne = this->tempKappaDOne; + this->kappaDTwo = this->tempKappaDTwo; + this->damage = this->tempDamage; + this->dissipation = this->tempDissipation; + this->tensionDissipation = this->tempTensionDissipation; + this->compressionDissipation = this->tempCompressionDissipation; + this->shearDissipation = this->tempShearDissipation; + this->deltaDissipation = this->tempDeltaDissipation; + this->tensionDeltaDissipation = this->tempTensionDeltaDissipation; + this->compressionDeltaDissipation = this->tempCompressionDeltaDissipation; + this->shearDeltaDissipation = this->tempShearDeltaDissipation; + this->deletionFlag = this->tempDeletionFlag; +} + + +void +LatticePlasticityDamageStatus::saveContext(DataStream &stream, ContextMode mode) +// +// saves full information stored in this Status +// no temp variables stored +// +{ + LatticeMaterialStatus::saveContext(stream, mode); + + if ( !stream.write(& kappaP, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(& kappaDOne, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(& kappaDTwo, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(& damage, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(& dissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(& tensionDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(& compressionDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(& shearDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(& deltaDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(& tensionDeltaDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(& compressionDeltaDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(& shearDeltaDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + +} + + +void +LatticePlasticityDamageStatus::restoreContext(DataStream &stream, ContextMode mode) +// +// restores full information stored in stream to this Status +// +{ + LatticeMaterialStatus::restoreContext(stream, mode); + + if ( !stream.read(& kappaP, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(& kappaDOne, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(& kappaDTwo, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(& damage, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(& dissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(& tensionDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(& shearDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(& compressionDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(& deltaDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(& tensionDeltaDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(& shearDeltaDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(& compressionDeltaDissipation, 1) ) { + THROW_CIOERR(CIO_IOERR); + } + +} +} // end namespace oofem diff --git a/src/sm/Materials/LatticeMaterials/latticeplasticitydamage.h b/src/sm/Materials/LatticeMaterials/latticeplasticitydamage.h new file mode 100644 index 000000000..bd550ffa0 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeplasticitydamage.h @@ -0,0 +1,365 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticeplasticitydamage_h +#define latticeplasticitydamage_h + +#include "latticelinearelastic.h" +#include "latticematstatus.h" + +///@name Input fields for LatticePlasticityDamage +//@{ +#define _IFT_LatticePlasticityDamage_Name "latticeplastdam" +#define _IFT_LatticePlasticityDamage_tol "tol" +#define _IFT_LatticePlasticityDamage_iter "iter" +#define _IFT_LatticePlasticityDamage_sub "sub" +#define _IFT_LatticePlasticityDamage_ft "ft" +#define _IFT_LatticePlasticityDamage_fc "fc" +#define _IFT_LatticePlasticityDamage_angle1 "angle1" +#define _IFT_LatticePlasticityDamage_angle2 "angle2" +#define _IFT_LatticePlasticityDamage_flow "flow" +#define _IFT_LatticePlasticityDamage_stype "stype" +#define _IFT_LatticePlasticityDamage_wf "wf" +#define _IFT_LatticePlasticityDamage_ft1 "ft1" +#define _IFT_LatticePlasticityDamage_wf1 "wf1" +#define _IFT_LatticePlasticityDamage_ahard "ahard" +#define _IFT_LatticePlasticityDamage_damage "damage" +//@} + +namespace oofem { +/** + * This class implements associated Material Status to LatticePlasticityDamage. + * @author: Peter Grassl + */ +class LatticePlasticityDamageStatus : public LatticeMaterialStatus +{ +protected: + + double kappaP = 0.; + + double tempKappaP = 0.; + + double kappaDOne = 0., kappaDTwo = 0.;//, kappaDThree; + + double tempKappaDOne = 0., tempKappaDTwo = 0.;//, tempKappaDThree; + + double damage = 0.; + + double tempDamage = 0.; + + double dissipation = 0.; + + double tempDissipation = 0.; + + double tensionDissipation = 0.; + + double tempTensionDissipation = 0.; + + double compressionDissipation = 0.; + + double tempCompressionDissipation = 0.; + + double shearDissipation = 0.; + + double tempShearDissipation = 0.; + + double deltaDissipation = 0.; + + double tempDeltaDissipation = 0.; + + double tensionDeltaDissipation = 0.; + + double tempTensionDeltaDissipation = 0.; + + double compressionDeltaDissipation = 0.; + + double tempCompressionDeltaDissipation = 0.; + + double shearDeltaDissipation = 0.; + + double tempShearDeltaDissipation = 0.; + + int deletionFlag = 0; + int tempDeletionFlag = 1.; + + //double e0 = 0.; + + int compressionFlag = 0; + + +public: + + /// Constructor + LatticePlasticityDamageStatus(int n, Domain *d, GaussPoint *g); + + double giveKappaP() const { return kappaP; } + + double giveTempKappaP() const { return tempKappaP; } + + double giveKappaDOne() const { return kappaDOne; } + double giveKappaDTwo() const { return kappaDTwo; } + + double giveTempKappaDOne() const { return tempKappaDOne; } + double giveTempKappaDTwo() const { return tempKappaDTwo; } + + void setTempKappaP(double newKappa) { tempKappaP = newKappa; } + + void setTempKappaDOne(double newKappa) { tempKappaDOne = newKappa; } + + void setTempKappaDTwo(double newKappa) { tempKappaDTwo = newKappa; } + + double giveDamage() const { return damage; } + + double giveTempDamage() const { return tempDamage; } + + void setTempDamage(double newDamage) { tempDamage = newDamage; } + + double giveDissipation() const override {return dissipation;} + double giveTensionDissipation() const {return tensionDissipation;} + double giveCompressionDissipation() const {return compressionDissipation;} + double giveShearDissipation() const {return shearDissipation;} + + double giveDeltaDissipation() const override {return deltaDissipation;} + double giveTensionDeltaDissipation() const {return tensionDeltaDissipation;} + double giveCompressionDeltaDissipation() const {return compressionDeltaDissipation;} + double giveShearDeltaDissipation() const {return shearDeltaDissipation;} + + void setTempDissipation(double newDiss) {this->tempDissipation = newDiss;} + void setTempTensionDissipation(double newDiss) {this->tempTensionDissipation = newDiss;} + void setTempCompressionDissipation(double newDiss) {this->tempCompressionDissipation = newDiss;} + void setTempShearDissipation(double newDiss) {this->tempShearDissipation = newDiss;} + + void setTempDeltaDissipation(double newDiss) {this->tempDeltaDissipation = newDiss;} + void setTempTensionDeltaDissipation(double newDiss) {this->tempTensionDeltaDissipation = newDiss;} + void setTempCompressionDeltaDissipation(double newDiss) {this->tempCompressionDeltaDissipation = newDiss;} + void setTempShearDeltaDissipation(double newDiss) {this->tempShearDeltaDissipation = newDiss;} + + void setTempDeletionFlag(int newFlag) {this->tempDeletionFlag = newFlag;} + int giveDeletionFlag() const{ return this->deletionFlag;} + int giveTempDeletionFlag() const{ return this->tempDeletionFlag;} + + int giveCompressionFlag() const { return compressionFlag; } + + void setCompressionFlag(int flag) { compressionFlag = flag; } + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + const char *giveClassName() const override { return "LatticePlasticityDamageStatus"; } + + void initTempStatus() override; + + void updateYourself(TimeStep *) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; +}; + + +/** + * This class implements a local random plasticity damage model for concrete for lattice elements. + */ +class LatticePlasticityDamage : public LatticeLinearElastic +{ +protected: + + enum LatticePlasticityDamage_ReturnResult { + RR_Unknown, + RR_NotConverged, + RR_Converged + }; + + double initialYieldStress = 0.; + + /// tensile strength + double ft = 0.; + /// compressive strength + double fc = 0.; + /// frictional angle of the yield surface + double frictionAngleOne = 0.; + /// frictional angle of the yield surface + double frictionAngleTwo = 0.; + /// frictional angle of the plastic potential + double flowAngleOne = 0.; + + /// frictional angle of the plastic potential + double flowAngleTwo = 0.; + + /// determines the softening -> corresponds to crack opening (not strain) when tension stress vanishes + double wf = 0.; + + /// softening type determines the type of softening. 0 is exponential and 1 is bilinear. + int softeningType = 0; + + /// ratio of tensile stress value for bilinear stress-crack opening curve + double ftOneRatio = 0.; + + /// crack opening value for bilinear stress-crack opening curve + double wfOne = 0.; + + ///hardening parameter + double aHard = 0.; + + /// yield tolerance + double yieldTol = 0.; + + /// maximum number of iterations for stress return + int newtonIter = 0; + int numberOfSubIncrements = 0; + + ///damageFlag + int damageFlag = 0; + + virtual double giveTensileStrength(GaussPoint *gp, TimeStep *tStep) const { return this->give(ft_strength, gp) * this->ft; } + + virtual double giveCompressiveStrength(GaussPoint *gp, TimeStep *tStep) const { return this->give(fc_strength, gp) * this->fc; } + +public: + + /// Constructor + LatticePlasticityDamage(int n, Domain *d); + + const char *giveInputRecordName() const override { return _IFT_LatticePlasticityDamage_Name; } + const char *giveClassName() const override { return "LatticePlasticityDamage"; } + + + void initializeFrom(InputRecord &ir) override; + + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + + double give(int aProperty, GaussPoint *gp) const override; + + FloatMatrixF< 6, 6 >give3dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + + bool hasMaterialModeCapability(MaterialMode mode) const override; + + + double computeDeltaDissipation(const double omega, + const FloatArray &reducedStrain, + GaussPoint *gp, + TimeStep *atTime) const; + + + FloatArrayF< 3 >computeFVector(const FloatArrayF< 3 > &sigma, + const double deltaLambda, + const int surface, + GaussPoint *gp, + TimeStep *tStep) const; + + FloatArrayF< 3 >computeMVector(const FloatArrayF< 3 > &sigma, + const double deltaLambda, + const int surface, + GaussPoint *gp, + TimeStep *tStep) const; + + FloatMatrixF< 3, 3 >computeDMMatrix(const FloatArrayF< 3 > &sigma, + const double deltaLambda, + const int surface, + GaussPoint *gp, TimeStep *tStep) const; + + int checkTransition(const FloatArrayF< 3 > &sigma, const double tempKappa, GaussPoint *gp, TimeStep *tStep) const; + + + FloatMatrixF< 4, 4 >computeJacobian(const FloatArrayF< 3 > &sigma, + const double tempKappa, + const double deltaLambda, + const int surface, + GaussPoint *gp, + TimeStep *tStep) const; + + virtual double computeDamageParam(double kappaOne, double kappaTwo, GaussPoint *gp, TimeStep *tStep) const; + + FloatArrayF< 6 >giveLatticeStress3d(const FloatArrayF< 6 > &jump, GaussPoint *gp, TimeStep *tStep) override; + + FloatArrayF< 6 >performPlasticityReturn(GaussPoint *gp, + const FloatArrayF< 6 > &reducedStrain, + TimeStep *tStep) const; + + void performDamageEvaluation(GaussPoint *gp, + FloatArrayF< 6 > &reducedStrain, + TimeStep *tStep) const; + + double performRegularReturn(FloatArrayF< 3 > &stress, + LatticePlasticityDamage_ReturnResult &returnResult, + double yieldValue, + const int surface, + GaussPoint *gp, + TimeStep *tStep) const; + + double computeYieldValue(const FloatArrayF< 3 > &sigma, + const double tempKappa, + const int surface, + GaussPoint *gp, + TimeStep *tStep) const; + + double computeHardening(const double kappa, + GaussPoint *gp) const; + + + double computeDHardeningDKappa(const double kappa, + GaussPoint *gp) const; + double computeDDHardeningDDKappa(const double kappa, + GaussPoint *gp) const; + + double computeDuctilityMeasure(FloatArray &stress, double ductilityParameter) const; + + double computeYieldStress(double kappaP, GaussPoint *gp); + const + + double computeEquivalentStress(const FloatArray &tempSigma) const; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + virtual FloatArrayF< 6 >giveReducedStrain(GaussPoint *gp, TimeStep *tStep) const; + + +protected: + + int giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) override; + + int giveIPValueSize(InternalStateType type, + GaussPoint *gp); + + int giveIntVarCompFullIndx(IntArray &answer, + InternalStateType type, + MaterialMode mmode); + + InternalStateValueType giveIPValueType(InternalStateType type); +}; +} // end namespace oofem + +#endif diff --git a/src/sm/Materials/LatticeMaterials/latticeplasticitydamageviscoelastic.C b/src/sm/Materials/LatticeMaterials/latticeplasticitydamageviscoelastic.C new file mode 100644 index 000000000..f1ad2e650 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeplasticitydamageviscoelastic.C @@ -0,0 +1,433 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticeplasticitydamageviscoelastic.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "Elements/LatticeElements/latticestructuralelement.h" +#include "datastream.h" +#include "contextioerr.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_Material(LatticePlasticityDamageViscoelastic); + +LatticePlasticityDamageViscoelastic::LatticePlasticityDamageViscoelastic(int n, Domain *d) : LatticePlasticityDamage(n, d) +{} + +void +LatticePlasticityDamageViscoelastic::initializeFrom(InputRecord &ir) +{ + LatticePlasticityDamage::initializeFrom(ir); + + IR_GIVE_FIELD(ir, viscoMat, _IFT_LatticePlasticityDamageViscoelastic_viscoMat); // number of slave material + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + // override elastic modulus by the one given by the compliance function + timeFactor = 0.; + IR_GIVE_FIELD(ir, timeFactor, _IFT_LatticePlasticityDamageViscoelastic_timeFactor); // timeConversion equal to 1 day in current time units of the analysis + + double E28 = 1. / rheoMat->computeCreepFunction(timeFactor * 28.01, timeFactor * 28., NULL, NULL); // modulus of elasticity evaluated at 28 days, duration of loading 15 min + + this->eNormalMean = E28; // swap elastic modulus/stiffness + + if ( ir.hasField(_IFT_LatticePlasticityDamageViscoelastic_timedepfracturing) ) { + this->fib = true; + IR_GIVE_FIELD(ir, fib_fcm28, _IFT_LatticePlasticityDamageViscoelastic_fcm28); + IR_GIVE_FIELD(ir, fib_s, _IFT_LatticePlasticityDamageViscoelastic_fib_s); + IR_GIVE_FIELD(ir, stiffnessFactor, _IFT_LatticePlasticityDamageViscoelastic_stiffnessFactor); + } +} + + +MaterialStatus * +LatticePlasticityDamageViscoelastic::CreateStatus(GaussPoint *gp) const +{ + return new LatticePlasticityDamageViscoelasticStatus(1, LatticePlasticityDamageViscoelastic::domain, gp); +} + + +FloatArrayF< 6 > +LatticePlasticityDamageViscoelastic::giveLatticeStress3d(const FloatArrayF< 6 > &totalStrain, + GaussPoint *gp, + TimeStep *tStep) +{ + + double tol = 1.e-12; // error in order of approx. Pascals + + auto status = static_cast< LatticePlasticityDamageViscoelasticStatus * >( this->giveStatus(gp) ); + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + GaussPoint *rChGP = status->giveSlaveGaussPointVisco(); + + // just a dummy yet essential call to create a status of viscomaterial. Otherwise initTempStatus() would fail. + rheoMat->giveStatus(rChGP); + + status->initTempStatus(); + + + FloatArrayF< 6 >viscoStress; + FloatArrayF< 6 >plastDamStress; + + if(status->giveTempDeletionFlag()==1){ + //Deal with deleted element + status->letTempLatticeStressBe(viscoStress); + return viscoStress; + } + + FloatArrayF< 6 >reducedStrainForViscoMat; + FloatArrayF< 6 >reducedStrain; + FloatArrayF< 6 >quasiReducedStrain; + + FloatArray tempStressVE; + + int itercount = 1; + + FloatArray indepStrain; + indepStrain = this->computeStressIndependentStrainVector(gp, tStep, VM_Total); + + auto elasticStiffnessMatrix = LatticeLinearElastic::give3dLatticeStiffnessMatrix(ElasticStiffness, gp, tStep); + + double tolerance = 1.; + + FloatArrayF< 6 >inelasticTrialStrain; + + double sigmaResid; + double sigmaResidPlus = this->eNormalMean; + double sigmaResidMinus = -sigmaResidPlus; + + + FloatArrayF< 6 >inelastPlus; + FloatArrayF< 6 >inelastMinus; + + bool plusFlag = false; + bool minusFlag = false; + + int iterBisection = 10; + + do { + if ( itercount > 100 ) { + OOFEM_WARNING("Algorithm not converging"); + + printf("Algorithm not converging, giving up\n"); + printf("Unable to reach equilibrium between viscoelastic and CDPM materials, Element %d\n", gp->giveElement()->giveNumber() ); + printf("tolerance = %e > %e!, stress error = %e, itercount = %d\n", tolerance, tol, sigmaResid, itercount); + + if ( plusFlag ) { + printf("inelastPlus = "); + for ( auto &val : inelastPlus ) { + printf(" %.10e", val); + } + printf(" sigmaResidPlus = %e \n", sigmaResidPlus); + } + + if ( minusFlag ) { + printf("inelastMinus = "); + for ( auto &val : inelastMinus ) { + printf(" %.10e", val); + } + printf(" sigmaResidMinus = %e \n", sigmaResidMinus); + } + + break; + } + + reducedStrainForViscoMat = totalStrain; + + if ( indepStrain.giveSize() > 0 ) { + reducedStrainForViscoMat -= FloatArrayF< 6 >(indepStrain); + } + + if ( itercount < iterBisection || ( !plusFlag || !minusFlag ) ) { + inelasticTrialStrain = status->giveTempPlasticLatticeStrain() + FloatArrayF< 6 >( status->giveTempDamageLatticeStrain() ); + } + + reducedStrainForViscoMat -= inelasticTrialStrain; + + rheoMat->giveRealStressVector(tempStressVE, rChGP, reducedStrainForViscoMat, tStep); + viscoStress = FloatArrayF< 6 >(tempStressVE); + + for ( int i = 1; i <= 6; i++ ) { + quasiReducedStrain.at(i) = viscoStress.at(i) / elasticStiffnessMatrix.at(i, i) + inelasticTrialStrain.at(i); + } + + plastDamStress = this->performPlasticityReturn(gp, quasiReducedStrain, tStep); + + if(status->giveTempDeletionFlag()==1){ + //Deal with deleted element + status->letTempLatticeStressBe(plastDamStress); + return plastDamStress; + } + + + this->performDamageEvaluation(gp, quasiReducedStrain, tStep); + double tempDamage = status->giveTempDamage(); + plastDamStress *= ( 1. - tempDamage ); + + inelasticTrialStrain = status->giveTempPlasticLatticeStrain(); + inelasticTrialStrain += FloatArrayF< 6 >(status->giveTempDamageLatticeStrain() ); + + tolerance = norm(plastDamStress - viscoStress) / this->eNormalMean; + + // try bisection method - prepare bounds, might be needed + sigmaResid = viscoStress [ 0 ] - plastDamStress [ 0 ]; + + if ( sigmaResid > 0. ) { + if ( sigmaResid < sigmaResidPlus ) { + plusFlag = true; + sigmaResidPlus = sigmaResid; + inelastPlus = inelasticTrialStrain; + } + } else { + if ( sigmaResid > sigmaResidMinus ) { + minusFlag = true; + sigmaResidMinus = sigmaResid; + inelastMinus = inelasticTrialStrain; + } + } + + if ( itercount >= iterBisection && plusFlag && minusFlag ) { + inelasticTrialStrain = ( sigmaResidPlus * inelastMinus - sigmaResidMinus * inelastPlus ) / ( sigmaResidPlus - sigmaResidMinus ); + } + + itercount++; + } while ( tolerance >= tol ); + + status->letTempLatticeStrainBe(totalStrain); + status->letTempLatticeStressBe(viscoStress); + status->letTempReducedLatticeStrainBe(quasiReducedStrain); + + return viscoStress; +} + +double +LatticePlasticityDamageViscoelastic::giveCompressiveStrength(GaussPoint *gp, TimeStep *tStep) const +{ + if ( fib ) { + double equivalentTime = this->giveEquivalentTime(gp, tStep); + double fcm = exp(this->fib_s * ( 1. - sqrt(28. * this->timeFactor / equivalentTime) ) ) * this->fib_fcm28; + return fcm / this->fib_fcm28 * LatticePlasticityDamage::giveCompressiveStrength(gp, tStep); + } else { + return LatticePlasticityDamage::giveCompressiveStrength(gp, tStep); + } +} + + +double +LatticePlasticityDamageViscoelastic::giveTensileStrength(GaussPoint *gp, TimeStep *tStep) const +{ + // check if the fracture properties are constant or time-dependent + double ftm = 1.; + double ftm28 = 1.; + + if ( fib ) { + double equivalentTime = this->giveEquivalentTime(gp, tStep); + double fcm = exp(this->fib_s * ( 1. - sqrt(28. * this->timeFactor / equivalentTime) ) ) * this->fib_fcm28; + + //Calculate the aged tensile strength + if ( fcm >= 58. ) { + ftm = 2.12 * log(1. + 0.1 * fcm) * 1.e6 / this->stiffnessFactor; + } else if ( fcm <= 20. ) { + ftm = 0.07862 * fcm * 1.e6 / this->stiffnessFactor; // 12^(2/3) * 0.3 / 20 = 0.07862 + } else { + ftm = 0.3 * pow(fcm - 8., 2. / 3.) * 1.e6 / this->stiffnessFactor; //5.1-3a + } + + //Do the same for the 28 day compressive strength + if ( this->fib_fcm28 >= 58. ) { + ftm28 = 2.12 * log(1. + 0.1 * this->fib_fcm28) * 1.e6 / this->stiffnessFactor; + } else if ( this->fib_fcm28 <= 20. ) { + ftm28 = 0.07862 * this->fib_fcm28 * 1.e6 / this->stiffnessFactor; // 12^(2/3) * 0.3 / 20 = 0.07862 + } else { + ftm28 = 0.3 * pow(this->fib_fcm28 - 8., 2. / 3.) * 1.e6 / this->stiffnessFactor; //5.1-3a + } + return ftm / ftm28 * LatticePlasticityDamage::giveTensileStrength(gp, tStep); + } else { + return LatticePlasticityDamage::giveTensileStrength(gp, tStep); + } +} + + +FloatMatrixF< 6, 6 > +LatticePlasticityDamageViscoelastic::give3dLatticeStiffnessMatrix(MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep) const +{ + LatticePlasticityDamageViscoelasticStatus *status = static_cast< LatticePlasticityDamageViscoelasticStatus * >( this->giveStatus(gp) ); + GaussPoint *slaveGp; + + // get status of the slave viscoelastic material + slaveGp = status->giveSlaveGaussPointVisco(); + + // get viscoelastic material + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + double Eincr = rheoMat->giveEModulus(slaveGp, tStep); + + auto answer = LatticeLinearElastic::give3dLatticeStiffnessMatrix(ElasticStiffness, gp, tStep); + + answer *= ( Eincr / this->eNormalMean ); + + if ( rmode == ElasticStiffness ) { + return answer; + } else if ( ( rmode == SecantStiffness ) || ( rmode == TangentStiffness ) ) { + double omega = min(status->giveTempDamage(), 0.99999); + return answer * ( 1. - omega ); + } else { + OOFEM_ERROR("Unsupported stiffness mode\n"); + return answer; + } +} + +int +LatticePlasticityDamageViscoelastic::giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *tStep) +{ + if ( ( type == IST_DryingShrinkageTensor ) || + ( type == IST_AutogenousShrinkageTensor ) || + ( type == IST_TotalShrinkageTensor ) || + ( type == IST_CreepStrainTensor ) || + ( type == IST_DryingShrinkageTensor ) || + ( type == IST_ThermalStrainTensor ) ) { + LatticePlasticityDamageViscoelasticStatus *status = static_cast< LatticePlasticityDamageViscoelasticStatus * >( this->giveStatus(gp) ); + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + return rheoMat->giveIPValue(answer, status->giveSlaveGaussPointVisco(), type, tStep); + } + + return LatticePlasticityDamage::giveIPValue(answer, gp, type, tStep); +} + + +int LatticePlasticityDamageViscoelastic::checkConsistency() +{ + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + if ( rheoMat->giveAlphaOne() != this->alphaOne ) { + OOFEM_ERROR("a1 must be set to the same value in both master and viscoelastic slave materials"); + } + + if ( rheoMat->giveAlphaTwo() != this->alphaTwo ) { + OOFEM_ERROR("a2 must be set to the same value in both master and viscoelastic slave materials"); + } + + GaussPoint *noGP = NULL; + if ( rheoMat->give(tAlpha, noGP) != 0. ) { + OOFEM_ERROR("tAlpha must be set to 0. in slave viscoelastic material"); + } + + + return FEMComponent::checkConsistency(); +} + +double +LatticePlasticityDamageViscoelastic::giveEquivalentTime(GaussPoint *gp, TimeStep *tStep) const +{ + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + LatticePlasticityDamageViscoelasticStatus *status = static_cast< LatticePlasticityDamageViscoelasticStatus * >( this->giveStatus(gp) ); + + return rheoMat->giveEquivalentTime(status->giveSlaveGaussPointVisco(), tStep); +} + + +LatticePlasticityDamageViscoelasticStatus::LatticePlasticityDamageViscoelasticStatus(int n, Domain *d, GaussPoint *gp) : + LatticePlasticityDamageStatus(n, d, gp), slaveGpVisco(std::make_unique< GaussPoint >(gp->giveIntegrationRule(), 0, gp->giveNaturalCoordinates(), 0., gp->giveMaterialMode() ) ) +{} + +void +LatticePlasticityDamageViscoelasticStatus::initTempStatus() +// +// initializes temp variables according to variables form previous equlibrium state. +{ + LatticePlasticityDamageStatus::initTempStatus(); + + // at this point rheomat :: giveStatus (viscoGP) has to be called first + RheoChainMaterialStatus *rheoStatus = static_cast< RheoChainMaterialStatus * >( this->giveSlaveGaussPointVisco()->giveMaterialStatus() ); + + rheoStatus->initTempStatus(); +} + +void +LatticePlasticityDamageViscoelasticStatus::printOutputAt(FILE *file, TimeStep *tStep) const +{ + LatticePlasticityDamageStatus::printOutputAt(file, tStep); + fprintf(file, "\nViscoelastic material:"); + + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->printOutputAt(file, tStep); + + fprintf(file, "\n"); +} + + +void +LatticePlasticityDamageViscoelasticStatus::updateYourself(TimeStep *tStep) +// +// updates variables (nonTemp variables describing situation at previous equilibrium state) +// after a new equilibrium state has been reached +// temporary variables are having values corresponding to newly reached equilibrium. +// +{ + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->updateYourself(tStep); + + LatticePlasticityDamageStatus::updateYourself(tStep); +} + +void +LatticePlasticityDamageViscoelasticStatus::saveContext(DataStream &stream, ContextMode mode) +// +// saves full information stored in this Status +// no temp variables stored +// +{ + LatticePlasticityDamageStatus::saveContext(stream, mode); + + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->saveContext(stream, mode); +} + +void +LatticePlasticityDamageViscoelasticStatus::restoreContext(DataStream &stream, ContextMode mode) +// +// restores full information stored in stream to this Status +// +{ + LatticePlasticityDamageStatus::restoreContext(stream, mode); + + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->restoreContext(stream, mode); +} +} // end namespace oofem diff --git a/src/sm/Materials/LatticeMaterials/latticeplasticitydamageviscoelastic.h b/src/sm/Materials/LatticeMaterials/latticeplasticitydamageviscoelastic.h new file mode 100644 index 000000000..b7bd7c751 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeplasticitydamageviscoelastic.h @@ -0,0 +1,147 @@ + +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticeplasticitydamageviscoelastic_h +#define latticeplasticitydamageviscoelastic_h + +#include "latticeplasticitydamage.h" +#include "../RheoChainMaterials/rheoChM.h" + +///@name Input fields for LatticePlasticityDamageViscoelastic +//@{ +#define _IFT_LatticePlasticityDamageViscoelastic_Name "latticeplasticitydamageviscoelastic" +#define _IFT_LatticePlasticityDamageViscoelastic_viscoMat "viscomat" +#define _IFT_LatticePlasticityDamageViscoelastic_timeFactor "timefactor" +#define _IFT_LatticePlasticityDamageViscoelastic_timedepfracturing "timedepfracturing" +#define _IFT_LatticePlasticityDamageViscoelastic_fcm28 "fcm28" +#define _IFT_LatticePlasticityDamageViscoelastic_fib_s "fib_s" +#define _IFT_LatticePlasticityDamageViscoelastic_stiffnessFactor "stiffnessfactor" + +//@} + +namespace oofem { +/** + * This class implements associated Material Status to LatticePlasticityDamageViscoelastic. + * @author: Petr Havalasek + */ +class LatticePlasticityDamageViscoelasticStatus : public LatticePlasticityDamageStatus + +{ +protected: + + std::unique_ptr< GaussPoint >slaveGpVisco; + +public: + + /// Constructor + LatticePlasticityDamageViscoelasticStatus(int n, Domain *d, GaussPoint *g); + + /// Prints the receiver state to given stream + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + + const char *giveClassName() const override { return "LatticePlasticityDamageViscoelasticStatus"; } + + void initTempStatus() override; + + void updateYourself(TimeStep *) override; + + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; + + GaussPoint *giveSlaveGaussPointVisco() const { return this->slaveGpVisco.get(); } +}; + + + +/** + * This class implements a local viscoelastic model for concrete in tension for 3D lattice elements. + * @author: Petr Havlasek + */ +class LatticePlasticityDamageViscoelastic : public LatticePlasticityDamage + +{ +protected: + /// 'slave' (= viscoelastic) material model number. + int viscoMat = 0; + + bool fib = false; + double fib_fcm28 = 0; + double fib_s = 0; + double timeFactor = 0; + + /* scaling factor transforming PREDICTED strength and fracture energy + * e.g. if the stiffness should be in MPa, then stiffnessFactor = 1.e6 */ + double stiffnessFactor = 0.; + +public: + + /// Constructor + LatticePlasticityDamageViscoelastic(int n, Domain *d); + + const char *giveInputRecordName() const override { return _IFT_LatticePlasticityDamageViscoelastic_Name; } + const char *giveClassName() const override { return "LatticePlasticityDamageViscoelastic"; } + + void initializeFrom(InputRecord &ir) override; + + FloatMatrixF< 6, 6 >give3dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatArrayF< 6 >giveLatticeStress3d(const FloatArrayF< 6 > &totalStrain, + GaussPoint *gp, + TimeStep *tStep) override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + +protected: + + int giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) override; + + int checkConsistency(void) override; + + /// returns equivalent time (used to compute time-dependent ft and gf) + virtual double giveEquivalentTime(GaussPoint *gp, TimeStep *tStep) const; + + double giveTensileStrength(GaussPoint *gp, TimeStep *tStep) const override; + double giveCompressiveStrength(GaussPoint *gp, TimeStep *tStep) const override; +}; +} // end namespace oofem + + +#endif diff --git a/src/sm/Materials/LatticeMaterials/latticeslip.C b/src/sm/Materials/LatticeMaterials/latticeslip.C new file mode 100644 index 000000000..dddf2fd43 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeslip.C @@ -0,0 +1,269 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticeslip.h" +#include "latticelinearelastic.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "CrossSections/structuralcrosssection.h" +#include "engngm.h" +#include "mathfem.h" +#include "floatarrayf.h" +#include "Elements/LatticeElements/latticestructuralelement.h" +#include "datastream.h" +#include "staggeredproblem.h" +#include "contextioerr.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_Material(LatticeSlip); + +LatticeSlip :: LatticeSlip(int n, Domain *d) : LatticeLinearElastic(n, d) +{} + + +bool +LatticeSlip :: hasMaterialModeCapability(MaterialMode mode) const +{ + return ( mode == _3dLattice ); +} + + +void +LatticeSlip :: initializeFrom(InputRecord &ir) +{ + LatticeLinearElastic :: initializeFrom(ir); + + //Parameter which relates the shear stiffness to the normal stiffness. Default is 1000. Reread this again, because the + alphaOne = 1000.; + IR_GIVE_OPTIONAL_FIELD(ir, alphaOne, _IFT_LatticeSlip_a1); // Macro + + //Parameter which is used for the definition of bending stiffness. Default is 1000. + alphaTwo = 1000.; + IR_GIVE_OPTIONAL_FIELD(ir, alphaTwo, _IFT_LatticeSlip_a2); // Macro + + //Parameter which limits the stress in slip direction. + IR_GIVE_FIELD(ir, tauZero, _IFT_LatticeSlip_t0); // Macro +} + + +MaterialStatus * +LatticeSlip :: CreateStatus(GaussPoint *gp) const +{ + return new LatticeSlipStatus(gp); +} + + +FloatArrayF< 6 > +LatticeSlip :: giveLatticeStress3d(const FloatArrayF< 6 > &totalStrain, GaussPoint *gp, TimeStep *atTime) +{ + auto status = static_cast< LatticeSlipStatus * >( this->giveStatus(gp) ); + status->initTempStatus(); + + auto tempPlasticStrain = status->givePlasticLatticeStrain(); + + auto stiffnessMatrix = this->give3dLatticeStiffnessMatrix(ElasticStiffness, gp, atTime); + + /*First component is the slip one for which the stress should be limited using plasiticity (frictional slip between fibre and matrix). The other components are kept elastic. */ + FloatArrayF<6> stress; + + stress.at(1) = ( totalStrain.at(1) - tempPlasticStrain.at(1) ) * stiffnessMatrix.at(1, 1); + double f = fabs(stress.at(1) ) - tauZero; + + if ( f > 0 ) {//plastic response. + //Reduced stress by increasing plastic strain. + tempPlasticStrain.at(1) = tempPlasticStrain.at(1) + sgn(stress.at(1) ) * f / stiffnessMatrix.at(1, 1); + stress.at(1) = ( totalStrain.at(1) - tempPlasticStrain.at(1) ) * stiffnessMatrix.at(1, 1); + + status->setTempCrackFlag(1); + } + + //Compute the final stress components + for ( int i = 2; i <= 6; i++ ) { + stress.at(i) = stiffnessMatrix.at(i, i) * totalStrain.at(i); + } + + //Set temp values in status needed for dissipation + status->letTempPlasticLatticeStrainBe(tempPlasticStrain); + status->letTempLatticeStrainBe(totalStrain); + status->letTempLatticeStressBe(stress); + + double tempDissipation = status->giveDissipation(); + double tempDeltaDissipation; + + tempDeltaDissipation = computeDeltaDissipation(gp, atTime); + + tempDissipation += tempDeltaDissipation; + + //Set all temp values + status->setTempDissipation(tempDissipation); + status->setTempDeltaDissipation(tempDeltaDissipation); + + return stress; +} + + +Interface * +LatticeSlip :: giveInterface(InterfaceType type) +{ + return nullptr; +} + + +LatticeSlipStatus :: LatticeSlipStatus(GaussPoint *g) : LatticeMaterialStatus(g) +{} + + +void +LatticeSlipStatus :: initTempStatus() +{ + LatticeMaterialStatus :: initTempStatus(); + this->tempPlasticLatticeStrain = this->plasticLatticeStrain; +} + + +FloatArrayF< 6 > +LatticeSlip :: giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const +// +// returns a FloatArray(6) of initial strain vector +// caused by unit temperature in direction of +// gp (element) local axes +// +{ + double alpha = this->give(tAlpha, gp); + + //Option to add a eigendisplacement instead of strain + double length = static_cast< LatticeStructuralElement * >( gp->giveElement() )->giveLength(); + alpha += this->cAlpha / length; + + return { + alpha, 0., 0., 0., 0., 0. + }; +} + +void +LatticeSlipStatus :: printOutputAt(FILE *file, TimeStep *tStep) const +{ + LatticeMaterialStatus :: printOutputAt(file, tStep); + fprintf(file, "plasticStrain %.8e, dissipation %f, deltaDissipation %f, crackFlag %d\n", this->plasticLatticeStrain.at(1), this->dissipation, this->deltaDissipation, this->crackFlag); +} + + +double +LatticeSlip :: computeDeltaDissipation(GaussPoint *gp, TimeStep *atTime) const +{ + auto status = static_cast< LatticeSlipStatus * >( this->giveStatus(gp) ); + + const auto &plasticStrain = status->givePlasticLatticeStrain(); + const auto &tempPlasticStrain = status->giveTempPlasticLatticeStrain(); + const auto &tempStress = status->giveTempLatticeStress(); + + return tempStress.at(1) * ( tempPlasticStrain.at(1) - plasticStrain.at(1) ); +} + + +void +LatticeSlipStatus :: saveContext(DataStream &stream, ContextMode mode) +// +// saves full information stored in this Status +// no temp variables stored +// +{ + contextIOResultType iores; + // save parent class status + LatticeMaterialStatus :: saveContext(stream, mode); + + if ( ( iores = this->plasticLatticeStrain.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } +} + + +void +LatticeSlipStatus :: restoreContext(DataStream &stream, ContextMode mode) +{ + contextIOResultType iores; + + LatticeMaterialStatus :: restoreContext(stream, mode); + + if ( ( iores = this->plasticLatticeStrain.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } +} + + +void +LatticeSlipStatus :: updateYourself(TimeStep *atTime) +{ + LatticeMaterialStatus :: updateYourself(atTime); + this->plasticLatticeStrain = this->tempPlasticLatticeStrain; +} + + + +int +LatticeSlip :: giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) +{ + auto status = static_cast< LatticeSlipStatus * >( this->giveStatus(gp) ); + + if ( type == IST_CrackStatuses ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveCrackFlag(); + return 1; + } else if ( type == IST_DissWork ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveDissipation(); + return 1; + } else if ( type == IST_DeltaDissWork ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveDeltaDissipation(); + return 1; + } else if ( type == IST_CharacteristicLength ) { + answer.resize(1); + answer.zero(); + answer.at(1) = static_cast< LatticeStructuralElement * >( gp->giveElement() )->giveLength(); + return 1; + } else { + return LatticeLinearElastic :: giveIPValue(answer, gp, type, atTime); + } +} +} diff --git a/src/sm/Materials/LatticeMaterials/latticeslip.h b/src/sm/Materials/LatticeMaterials/latticeslip.h new file mode 100644 index 000000000..2c022b8ca --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeslip.h @@ -0,0 +1,143 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticeslip_h +#define latticeslip_h + +#include "latticelinearelastic.h" +#include "latticematstatus.h" + +///@name Input fields for LatticeSlip +//@{ +#define _IFT_LatticeSlip_Name "latticeslip" +#define _IFT_LatticeSlip_talpha "talpha" +#define _IFT_LatticeSlip_e "e" +#define _IFT_LatticeSlip_a1 "a1" +#define _IFT_LatticeSlip_a2 "a2" +#define _IFT_LatticeSlip_t0 "t0" +//@} + +namespace oofem { +class LatticeSlipStatus : public LatticeMaterialStatus +{ +protected: + + +public: + LatticeSlipStatus(GaussPoint *g); + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + const char *giveClassName() const override { return "LatticeSlipStatus"; } + + void initTempStatus() override; + + void updateYourself(TimeStep *) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; +}; + + + +/** + * This class implements a slip model for interface elements between lattice and beam elements. + */ + +class LatticeSlip : public LatticeLinearElastic +{ +protected: + + ///Normal modulus + double eNormal = 0.; + + ///Ratio of shear and normal modulus + double alphaOne = 0.; + + ///Ratio of torsion and normal modulus + double alphaTwo = 0.; + + ///Strength for slip component + double tauZero = 0.; + + /// coefficient variation of the Gaussian distribution + double coefficientOfVariation = 0.; + + /// flag which chooses between no distribution (0) and Gaussian distribution (1) + double localRandomType = 0.; + + double cAlpha = 0.; + + double tAlphaMean = 0.; + +public: + + /// Constructor + LatticeSlip(int n, Domain *d); + + + const char *giveInputRecordName() const override { return _IFT_LatticeSlip_Name; } + const char *giveClassName() const override { return "LatticeSlip"; } + + void initializeFrom(InputRecord &ir) override; + + FloatArrayF< 6 >giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; + + + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } + + + double computeDeltaDissipation(GaussPoint *gp, TimeStep *atTime) const; + + bool hasMaterialModeCapability(MaterialMode mode) const override; + + + Interface *giveInterface(InterfaceType) override; + + FloatArrayF< 6 >giveLatticeStress3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + +protected: + + int giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) override; +}; +} // end namespace oofem + +#endif diff --git a/src/sm/Materials/LatticeMaterials/latticestructuralmaterial.C b/src/sm/Materials/LatticeMaterials/latticestructuralmaterial.C new file mode 100644 index 000000000..843172925 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticestructuralmaterial.C @@ -0,0 +1,162 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sm/Materials/LatticeMaterials/latticestructuralmaterial.h" +#include "sm/Materials/LatticeMaterials/latticematstatus.h" +#include "domain.h" +#include "verbose.h" +#include "sm/Materials/structuralms.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Elements/nlstructuralelement.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" +#include "mathfem.h" +#include "engngm.h" +#include "fieldmanager.h" +#include "dynamicinputrecord.h" + +namespace oofem { +LatticeStructuralMaterial::LatticeStructuralMaterial(int n, Domain *d) : StructuralMaterial(n, d) { } + + +bool +LatticeStructuralMaterial::hasMaterialModeCapability(MaterialMode mode) const +// +// returns whether receiver supports given mode +// +{ + return mode == _3dLattice || mode == _2dLattice || mode == _1dLattice; +} + +void +LatticeStructuralMaterial::giveStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, + GaussPoint *gp, TimeStep *tStep) +// +// Returns characteristic material stiffness matrix of the receiver +// +{ + answer = this->give3dLatticeStiffnessMatrix(rMode, gp, tStep); +} + + +int +LatticeStructuralMaterial::giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) +{ + auto status = static_cast< LatticeMaterialStatus * >( this->giveStatus(gp) ); + + if ( type == IST_LatticeStress ) { + answer = status->giveLatticeStress(); + return 1; + } else if ( type == IST_LatticeStrain ) { + answer = status->giveLatticeStrain(); + return 1; + } else { + return StructuralMaterial::giveIPValue(answer, gp, type, atTime); + } +} + + +double +LatticeStructuralMaterial::giveLatticeStress1d(double strain, GaussPoint *gp, TimeStep *tStep) +{ + FloatArrayF< 6 >tempStrain; + tempStrain [ 0 ] = strain; + auto answer = giveLatticeStress3d(tempStrain, gp, tStep); + return answer [ { 0 } ]; +} + +FloatArrayF< 3 > +LatticeStructuralMaterial::giveLatticeStress2d(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) +{ + auto answer = giveLatticeStress3d(assemble< 6 >(strain, { 0, 1, 5 }), gp, tStep); + return answer [ { 0, 1, 5 } ]; +} + +FloatArrayF< 6 > +LatticeStructuralMaterial::giveLatticeStress3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) +{ + OOFEM_ERROR("3dLattice mode not supported"); +} + +FloatArrayF< 6 > +LatticeStructuralMaterial::giveFrameForces3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) +{ + OOFEM_ERROR("3dFrame mode not supported"); +} + + + +FloatMatrixF< 1, 1 > +LatticeStructuralMaterial::give1dLatticeStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +// +// return material stiffness matrix for 1dlattice +// +{ + OOFEM_ERROR("No general implementation provided"); +} + +FloatMatrixF< 3, 3 > +LatticeStructuralMaterial::give2dLatticeStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +// +// return material stiffness matrix for 2dlattice +// +{ + OOFEM_ERROR("No general implementation provided"); +} + +FloatMatrixF< 6, 6 > +LatticeStructuralMaterial::give3dLatticeStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +// +// return material stiffness matrix for 2dlattice +// +{ + OOFEM_ERROR("No general implementation provided"); +} + +FloatMatrixF< 6, 6 > +LatticeStructuralMaterial::give3dFrameStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +// +// return material stiffness matrix for 2dlattice +// +{ + OOFEM_ERROR("No general implementation provided"); +} +} // end namespace oofem diff --git a/src/sm/Materials/LatticeMaterials/latticestructuralmaterial.h b/src/sm/Materials/LatticeMaterials/latticestructuralmaterial.h new file mode 100644 index 000000000..a78deced9 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticestructuralmaterial.h @@ -0,0 +1,109 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef latticestructuralmaterial_h +#define latticestructuralmaterial_h + +#include "../structuralmaterial.h" +#include "floatarray.h" +#include "floatmatrix.h" +#include "matconst.h" +#include "matstatus.h" +#include "valuemodetype.h" +#include + +///@name Input fields for LatticeStructuralMaterial +//@{ +#define _IFT_LatticeStructuralMaterial_referencetemperature "referencetemperature" +#define _IFT_LatticeStructuralMaterial_talpha "talpha" +//@} + +namespace oofem { +#define STRAIN_STEPS 10.0 + +class GaussPoint; +///@todo Update documentation +/** + * Abstract base class for all lattice "structural" constitutive models. It declares common services provided + * by all lattice structural material models. The implementation of these services is partly left on derived classes, + * which will implement constitutive model dependent part. + * Structural material services should not be called directly by elements. Instead, they always should + * pass their requests to corresponding cross section model. Cross section performs all necessary integration over + * its volume and invokes material model services. + * + * @author Peter Grassl + */ +class LatticeStructuralMaterial : public StructuralMaterial +{ +protected: + /// Reference temperature (temperature, when material has been built into structure). + double referenceTemperature = 0.; + +public: + + /** + * Constructor. Creates material with given number, belonging to given domain. + * @param n Material number. + * @param d Domain to which new material will belong. + */ + LatticeStructuralMaterial(int n, Domain *d); + + void giveStiffnessMatrix(FloatMatrix &answer, + MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) override; + + virtual bool hasAnalyticalTangentStiffness() const { return true; } + + bool hasMaterialModeCapability(MaterialMode mode) const override; + const char *giveClassName() const override { return "LatticeStructuralMaterial"; } + + virtual double giveLatticeStress1d(const double strain, GaussPoint *gp, TimeStep *tStep); + + virtual FloatArrayF< 3 >giveLatticeStress2d(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep); + + virtual FloatArrayF< 6 >giveLatticeStress3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep); + + virtual FloatArrayF< 6 >giveFrameForces3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep); + + virtual FloatMatrixF< 1, 1 >give1dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatMatrixF< 3, 3 >give2dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatMatrixF< 6, 6 >give3dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + + virtual FloatMatrixF< 6, 6 >give3dFrameStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime) override; +}; +} // end namespace oofem +#endif // latticestructuralmaterial_h diff --git a/src/sm/Materials/LatticeMaterials/latticeviscoelastic.C b/src/sm/Materials/LatticeMaterials/latticeviscoelastic.C new file mode 100644 index 000000000..80eba7fa4 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeviscoelastic.C @@ -0,0 +1,271 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "latticeviscoelastic.h" +#include "gausspoint.h" +#include "floatarray.h" +#include "datastream.h" +#include "contextioerr.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(LatticeViscoelastic); + +LatticeViscoelastic::LatticeViscoelastic(int n, Domain *d) : LatticeLinearElastic(n, d) +{} + + +void +LatticeViscoelastic::initializeFrom(InputRecord &ir) +{ + LatticeLinearElastic::initializeFrom(ir); + + IR_GIVE_FIELD(ir, viscoMat, _IFT_LatticeViscoelastic_viscoMat); // number of slave material + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + // fix to work at arbitrary time units! + double E28 = 1. / rheoMat->computeCreepFunction(28.01, 28., NULL, NULL); // modulus of elasticity evaluated at 28 days, duration of loading 15 min + this->eNormalMean = E28; // swap elastic modulus/stiffness +} + + +MaterialStatus * +LatticeViscoelastic::CreateStatus(GaussPoint *gp) const +{ + LatticeViscoelasticStatus *answer = new LatticeViscoelasticStatus(gp); + return answer; +} + + +FloatArrayF< 6 > +LatticeViscoelastic::giveLatticeStress3d(const FloatArrayF< 6 > &totalStrain, + GaussPoint *gp, + TimeStep *tStep) +{ + auto status = static_cast< LatticeViscoelasticStatus * >( this->giveStatus(gp) ); + + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + FloatArray viscoStress; + FloatArray partialStrain; + + GaussPoint *rChGP = status->giveSlaveGaussPointVisco(); + double Eincr = rheoMat->giveEModulus(rChGP, tStep); + this->eNormalMean = Eincr; + + FloatArrayF< 6 >reducedStrainForViscoMat; + FloatArrayF< 6 >quasiTotalStrain; + + FloatArray indepStrain; + + FloatArrayF< 6 >tempStress; + reducedStrainForViscoMat = totalStrain; + + indepStrain = this->computeStressIndependentStrainVector(gp, tStep, VM_Total); + + if ( indepStrain.giveSize() > 0 ) { + reducedStrainForViscoMat -= FloatArrayF< 6 >(indepStrain); + } + + + rheoMat->giveRealStressVector(viscoStress, rChGP, reducedStrainForViscoMat, tStep); + tempStress = FloatArrayF< 6 >(viscoStress); + + + status->letTempLatticeStrainBe(totalStrain); + status->letTempLatticeStressBe(tempStress); + + return tempStress; +} + +FloatMatrixF< 6, 6 > +LatticeViscoelastic::give3dLatticeStiffnessMatrix(MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep) const + +{ + LatticeViscoelasticStatus *status = static_cast< LatticeViscoelasticStatus * >( this->giveStatus(gp) ); + GaussPoint *slaveGp; + + // get status of the slave viscoelastic material + slaveGp = status->giveSlaveGaussPointVisco(); + // get viscoelastic material + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + auto answer = LatticeLinearElastic::give3dLatticeStiffnessMatrix(ElasticStiffness, gp, tStep); + + double Eincr = rheoMat->giveEModulus(slaveGp, tStep); + + answer *= ( Eincr / this->eNormalMean ); + + return answer; +} + +FloatMatrixF< 3, 3 > +LatticeViscoelastic::give2dLatticeStiffnessMatrix(MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep) const +{ + LatticeViscoelasticStatus *status = static_cast< LatticeViscoelasticStatus * >( this->giveStatus(gp) ); + GaussPoint *slaveGp; + + // get status of the slave viscoelastic material + slaveGp = status->giveSlaveGaussPointVisco(); + // get viscoelastic material + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + auto answer = LatticeLinearElastic::give2dLatticeStiffnessMatrix(ElasticStiffness, gp, tStep); + + double Eincr = rheoMat->giveEModulus(slaveGp, tStep); + answer *= ( Eincr / this->eNormalMean ); + + return answer; +} + + +int +LatticeViscoelastic::giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *tStep) +{ + if ( ( type == IST_DryingShrinkageTensor ) || + ( type == IST_AutogenousShrinkageTensor ) || + ( type == IST_TotalShrinkageTensor ) || + ( type == IST_CreepStrainTensor ) || + ( type == IST_DryingShrinkageTensor ) || + ( type == IST_ThermalStrainTensor ) ) { + LatticeViscoelasticStatus *status = static_cast< LatticeViscoelasticStatus * >( this->giveStatus(gp) ); + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + return rheoMat->giveIPValue(answer, status->giveSlaveGaussPointVisco(), type, tStep); + } + + return LatticeLinearElastic::giveIPValue(answer, gp, type, tStep); +} + + + +int LatticeViscoelastic::checkConsistency() +{ + RheoChainMaterial *rheoMat = static_cast< RheoChainMaterial * >( domain->giveMaterial(this->viscoMat) ); + + + if ( rheoMat->giveAlphaOne() != this->alphaOne ) { + OOFEM_ERROR("a1 must be set to the same value in both master and viscoelastic slave materials"); + } + + if ( rheoMat->giveAlphaTwo() != this->alphaTwo ) { + OOFEM_ERROR("a2 must be set to the same value in both master and viscoelastic slave materials"); + } + + + return FEMComponent::checkConsistency(); +} + + + + + +LatticeViscoelasticStatus::LatticeViscoelasticStatus(GaussPoint *gp) : + LatticeMaterialStatus(gp), + slaveGpVisco( std::make_unique< GaussPoint >( gp->giveIntegrationRule(), 0, gp->giveNaturalCoordinates(), 0., gp->giveMaterialMode() ) ) + // slaveGpVisco(std::make_unique( gp->giveIntegrationRule(), 0, gp->giveNaturalCoordinates(), 0., gp->giveMaterialMode()) ) + + +{} + +void +LatticeViscoelasticStatus::initTempStatus() +// +// initializes temp variables according to variables form previous equlibrium state. +// builds new crackMap +// +{ + LatticeMaterialStatus::initTempStatus(); + + RheoChainMaterialStatus *rheoStatus = static_cast< RheoChainMaterialStatus * >( this->giveSlaveGaussPointVisco()->giveMaterialStatus() ); + rheoStatus->initTempStatus(); +} + +void +LatticeViscoelasticStatus::printOutputAt(FILE *file, TimeStep *tStep) const +{ + // MaterialStatus *mS = this->giveViscoelasticMatStatus(); + + LatticeMaterialStatus::printOutputAt(file, tStep); + fprintf(file, "\nViscoelastic material:"); + + //this->slaveGpVisco->giveMaterialStatus()->printOutputAt(file, tStep); + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->printOutputAt(file, tStep); + + fprintf(file, "\n"); +} + +void +LatticeViscoelasticStatus::updateYourself(TimeStep *tStep) +// +// updates variables (nonTemp variables describing situation at previous equilibrium state) +// after a new equilibrium state has been reached +// temporary variables are having values corresponding to newly reached equilibrium. +// +{ + // this->slaveGpVisco->giveMaterialStatus()->updateYourself(tStep); + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->updateYourself(tStep); + + LatticeMaterialStatus::updateYourself(tStep); +} + +void +LatticeViscoelasticStatus::saveContext(DataStream &stream, ContextMode mode) +// +// saves full information stored in this Status +// no temp variables stored +// +{ + // save parent class status + LatticeMaterialStatus::saveContext(stream, mode); + + // this->slaveGpVisco->giveMaterialStatus()->saveContext(stream, mode); + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->saveContext(stream, mode); +} + +void +LatticeViscoelasticStatus::restoreContext(DataStream &stream, ContextMode mode) +// +// restores full information stored in stream to this Status +// +{ + LatticeMaterialStatus::restoreContext(stream, mode); + + // this->slaveGpVisco->giveMaterialStatus()->restoreContext(stream, mode); + this->giveSlaveGaussPointVisco()->giveMaterialStatus()->restoreContext(stream, mode); +} +} // end namespace oofem diff --git a/src/sm/Materials/LatticeMaterials/latticeviscoelastic.h b/src/sm/Materials/LatticeMaterials/latticeviscoelastic.h new file mode 100644 index 000000000..0e6569926 --- /dev/null +++ b/src/sm/Materials/LatticeMaterials/latticeviscoelastic.h @@ -0,0 +1,137 @@ + +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef latticeviscoelastic_h +#define latticeviscoelastic_h + +#include "latticelinearelastic.h" +#include "latticematstatus.h" +#include "../RheoChainMaterials/rheoChM.h" + +///@name Input fields for LatticeDamage +//@{ +#define _IFT_LatticeViscoelastic_Name "latticeviscoelastic" +#define _IFT_LatticeViscoelastic_viscoMat "viscomat" + +//@} + +namespace oofem { +/** + * This class implements associated Material Status to LatticeViscoelastic. + */ +class LatticeViscoelasticStatus : public LatticeMaterialStatus + +{ +protected: + std :: unique_ptr< GaussPoint >slaveGpVisco; + +public: + + /// Constructor + LatticeViscoelasticStatus(GaussPoint *g); + + /// Prints the receiver state to given stream + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + + const char *giveClassName() const override { return "LatticeViscoelasticStatus"; } + + void initTempStatus() override; + + void updateYourself(TimeStep *) override; + + + void saveContext(DataStream &stream, ContextMode mode) override; + + void restoreContext(DataStream &stream, ContextMode mode) override; + + GaussPoint *giveSlaveGaussPointVisco() const { return this->slaveGpVisco.get(); } +}; + + + + + +/** + * This class implements a local viscoelastic model for concrete in tension for 3D lattice elements. + */ +class LatticeViscoelastic : public LatticeLinearElastic + +{ +protected: + /// 'slave' material model number. + int viscoMat = 0; + + +public: + + /// Constructor + LatticeViscoelastic(int n, Domain *d); + + + const char *giveInputRecordName() const override { return _IFT_LatticeViscoelastic_Name; } + const char *giveClassName() const override { return "LatticeViscoelastic"; } + + void initializeFrom(InputRecord &ir) override; + + FloatMatrixF< 6, 6 >give3dLatticeStiffnessMatrix(MatResponseMode rmode, + GaussPoint *gp, + TimeStep *atTime) const override; + + FloatMatrixF< 3, 3 >give2dLatticeStiffnessMatrix(MatResponseMode rmode, + GaussPoint *gp, + TimeStep *atTime) const override; + + + FloatArrayF< 6 >giveLatticeStress3d(const FloatArrayF< 6 > &totalStrain, + GaussPoint *gp, + TimeStep *tStep) override; + + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + +protected: + + int giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *atTime) override; + + int checkConsistency(void) override; +}; +} // end namespace oofem + + +#endif diff --git a/src/sm/Materials/MixedPressure/mixedpressurematerialextensioninterface.C b/src/sm/Materials/MixedPressure/mixedpressurematerialextensioninterface.C new file mode 100644 index 000000000..b439f3e30 --- /dev/null +++ b/src/sm/Materials/MixedPressure/mixedpressurematerialextensioninterface.C @@ -0,0 +1,98 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + + +#include "domain.h" +#include "mixedpressurematerialextensioninterface.h" +#include "gausspoint.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "../sm/Materials/structuralmaterial.h" + +#include + + +namespace oofem { +// constructor +MixedPressureMaterialExtensionInterface :: MixedPressureMaterialExtensionInterface(Domain *d) : Interface() +{ + dom = d; +} + + + + +void +MixedPressureMaterialExtensionInterface :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, double pressure, TimeStep *tStep) +{ + ///@todo Move this to StructuralCrossSection ? + MaterialMode mode = gp->giveMaterialMode(); + if ( mode == _3dMat ) { + this->giveRealStressVector_3d(answer, gp, reducedStrain, pressure, tStep); + } else if ( mode == _PlaneStrain ) { + this->giveRealStressVector_PlaneStrain(answer, gp, reducedStrain, pressure, tStep); + } else { + OOFEM_ERROR("Unknown material mode for the mixed u-p formulation"); + } +} + + + +void +MixedPressureMaterialExtensionInterface :: giveDeviatoricConstitutiveMatrix(FloatMatrix &answer, MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep) +{ + ///@todo Move this to StructuralCrossSection ? + MaterialMode mode = gp->giveMaterialMode(); + if ( mode == _3dMat ) { + this->giveDeviatoric3dMaterialStiffnessMatrix(answer, rmode, gp, tStep); + } else if ( mode == _PlaneStrain ) { + this->giveDeviatoricPlaneStrainStiffMtrx(answer, rmode, gp, tStep); + } else { + OOFEM_ERROR("Unknown material mode for the mixed u-p formulation"); + } +} + + + + +void +MixedPressureMaterialExtensionInterface :: giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, double pressure, TimeStep *tStep) +{ + FloatArray vE, vS; + StructuralMaterial :: giveFullSymVectorForm(vE, reducedStrain, _PlaneStrain); + this->giveRealStressVector_3d(vS, gp, vE, pressure, tStep); + StructuralMaterial :: giveReducedSymVectorForm(answer, vS, _PlaneStrain); +} +} diff --git a/src/sm/Materials/MixedPressure/mixedpressurematerialextensioninterface.h b/src/sm/Materials/MixedPressure/mixedpressurematerialextensioninterface.h new file mode 100644 index 000000000..370ffb77e --- /dev/null +++ b/src/sm/Materials/MixedPressure/mixedpressurematerialextensioninterface.h @@ -0,0 +1,103 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef mixedpressurematerialextensioninterface_h +#define mixedpressurematerialextensioninterface_h + +#include "interface.h" +#include "matresponsemode.h" +#include "domain.h" + +///@name micromorphicmaterialextensioninterface +//@{ + +//@} + +namespace oofem { +class FloatMatrix; +class FloatArray; +class GaussPoint; +class TimeStep; + + + +/** + * Material interface for gradient material models. + */ +class MixedPressureMaterialExtensionInterface : public Interface +{ +protected: + Domain *dom = nullptr; + +public: + /** + * Constructor. Creates material with given number, belonging to given domain. + * @param d Domain to which new material will belong. + */ + MixedPressureMaterialExtensionInterface(Domain *d); + /// Destructor. + virtual ~MixedPressureMaterialExtensionInterface() { } + + + virtual void giveDeviatoric3dMaterialStiffnessMatrix(FloatMatrix &answer, + MatResponseMode, + GaussPoint *gp, + TimeStep *tStep) + { OOFEM_ERROR("not implemented "); } + + + virtual void giveDeviatoricPlaneStrainStiffMtrx(FloatMatrix &answer, + MatResponseMode, GaussPoint *gp, + TimeStep *tStep) + { OOFEM_ERROR("not implemented "); } + + + virtual void giveDeviatoricConstitutiveMatrix(FloatMatrix & answer, + MatResponseMode, GaussPoint * gp, + TimeStep * tStep); + + + virtual void giveInverseOfBulkModulus(double &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + + + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, double pressure, TimeStep *tStep); + + virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, double pressure, TimeStep *tStep) = 0; + virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, double pressure, TimeStep *tStep); + // virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, double pressure, TimeStep *tStep) = 0; + + virtual void giveFiniteStrainGeneralizedStressVectors(FloatArray &sigma, GaussPoint *gp, const FloatArray &devF, double pressure, TimeStep *tStep) {; } +}; +} +#endif diff --git a/src/sm/Materials/Obsolete/j2mplasticmaterial.C b/src/sm/Materials/Obsolete/j2mplasticmaterial.C index 7e2153496..4aa67037f 100644 --- a/src/sm/Materials/Obsolete/j2mplasticmaterial.C +++ b/src/sm/Materials/Obsolete/j2mplasticmaterial.C @@ -33,7 +33,7 @@ */ #include "j2mplasticmaterial.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" @@ -46,31 +46,18 @@ REGISTER_Material(J2MPlasticMaterial); J2MPlasticMaterial :: J2MPlasticMaterial(int n, Domain *d) : MPlasticMaterial(n, d) { - // - // constructor - // - kinematicHardeningFlag = isotropicHardeningFlag = 0; linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); this->nsurf = 1; } -J2MPlasticMaterial :: ~J2MPlasticMaterial() -{ - // - // destructor - // -} -IRResultType -J2MPlasticMaterial :: initializeFrom(InputRecord *ir) +void +J2MPlasticMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro double value; - result = MPlasticMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - result = linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) return result; + MPlasticMaterial :: initializeFrom(ir); + linearElasticMaterial->initializeFrom(ir); IR_GIVE_FIELD(ir, value, _IFT_J2MPlasticMaterial_ry); k = value / sqrt(3.0); @@ -96,20 +83,18 @@ J2MPlasticMaterial :: initializeFrom(InputRecord *ir) } else { this->rmType = mpm_CuttingPlane; } - - return IRRT_OK; } MaterialStatus * J2MPlasticMaterial :: CreateStatus(GaussPoint *gp) const { - return new MPlasticMaterialStatus(1, this->giveDomain(), gp, this->giveSizeOfReducedHardeningVarsVector(gp)); + return new MPlasticMaterialStatus(gp, this->giveSizeOfReducedHardeningVarsVector(gp)); } void J2MPlasticMaterial :: computeStressSpaceHardeningVars(FloatArray &answer, GaussPoint *gp, - const FloatArray &strainSpaceHardeningVariables) + const FloatArray &strainSpaceHardeningVariables) const { // in full stress strain space int count = 0, size = this->giveSizeOfFullHardeningVarsVector(), isize, rSize; @@ -148,7 +133,7 @@ J2MPlasticMaterial :: computeStressSpaceHardeningVars(FloatArray &answer, GaussP double J2MPlasticMaterial :: computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) + const FloatArray &stressSpaceHardeningVars) const { double f; FloatArray helpVector, backStress; @@ -176,7 +161,7 @@ J2MPlasticMaterial :: computeYieldValueAt(GaussPoint *gp, int isurf, const Float void J2MPlasticMaterial :: computeHardeningReducedModuli(FloatMatrix &answer, GaussPoint *gp, const FloatArray &strainSpaceHardeningVariables, - TimeStep *tStep) + TimeStep *tStep) const { /* computes hardening moduli in reduced stress strain space (for kinematic back-stress)*/ @@ -206,7 +191,7 @@ J2MPlasticMaterial :: computeHardeningReducedModuli(FloatMatrix &answer, GaussPo void J2MPlasticMaterial :: computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) + const FloatArray &stressSpaceHardeningVars) const { /* stress gradient of yield function in full stress - strain space */ @@ -252,7 +237,7 @@ J2MPlasticMaterial :: computeStressGradientVector(FloatArray &answer, functType void J2MPlasticMaterial :: computeStressSpaceHardeningVarsReducedGradient(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) + const FloatArray &stressSpaceHardeningVars) const { /* computes stress space hardening gradient in reduced stress-strain space */ @@ -288,7 +273,7 @@ J2MPlasticMaterial :: computeStressSpaceHardeningVarsReducedGradient(FloatArray int -J2MPlasticMaterial :: hasHardening() +J2MPlasticMaterial :: hasHardening() const { return ( this->kinematicHardeningFlag || this->isotropicHardeningFlag ); } @@ -298,7 +283,7 @@ void J2MPlasticMaterial :: computeReducedGradientMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) + const FloatArray &stressSpaceHardeningVars) const { int size; int imask, jmask; @@ -400,15 +385,15 @@ J2MPlasticMaterial :: computeReducedGradientMatrix(FloatMatrix &answer, int isur void J2MPlasticMaterial :: compute3dElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { /* Returns 3d elastic moduli */ - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, ElasticStiffness, gp, tStep); + answer = this->linearElasticMaterial->give3dMaterialStiffnessMatrix(ElasticStiffness, gp, tStep); } double -J2MPlasticMaterial :: computeJ2InvariantAt(const FloatArray &stressVector) +J2MPlasticMaterial :: computeJ2InvariantAt(const FloatArray &stressVector) const { double answer; double v1, v2, v3; @@ -429,7 +414,7 @@ J2MPlasticMaterial :: computeJ2InvariantAt(const FloatArray &stressVector) int -J2MPlasticMaterial :: giveSizeOfFullHardeningVarsVector() +J2MPlasticMaterial :: giveSizeOfFullHardeningVarsVector() const { /* Returns the size of hardening variables vector */ int size = 0; @@ -465,7 +450,7 @@ J2MPlasticMaterial :: giveSizeOfReducedHardeningVarsVector(GaussPoint *gp) const void J2MPlasticMaterial :: giveStressBackVector(FloatArray &answer, - const FloatArray &stressSpaceHardeningVars) + const FloatArray &stressSpaceHardeningVars) const { /* returns part of hardening vector corresponding to kinematic hardening */ if ( this->kinematicHardeningFlag ) { @@ -482,7 +467,7 @@ J2MPlasticMaterial :: giveStressBackVector(FloatArray &answer, double -J2MPlasticMaterial :: giveIsotropicHardeningVar(const FloatArray &stressSpaceHardeningVars) +J2MPlasticMaterial :: giveIsotropicHardeningVar(const FloatArray &stressSpaceHardeningVars) const { /* returns value in hardening vector corresponding to isotropic hardening */ if ( !isotropicHardeningFlag ) { diff --git a/src/sm/Materials/Obsolete/j2mplasticmaterial.h b/src/sm/Materials/Obsolete/j2mplasticmaterial.h index 923773eb3..32aa0751e 100644 --- a/src/sm/Materials/Obsolete/j2mplasticmaterial.h +++ b/src/sm/Materials/Obsolete/j2mplasticmaterial.h @@ -57,48 +57,46 @@ class Domain; class J2MPlasticMaterial : public MPlasticMaterial { protected: - int kinematicHardeningFlag, isotropicHardeningFlag; - double kinematicModuli, isotropicModuli; - double k; + int kinematicHardeningFlag = 0, isotropicHardeningFlag = 0; + double kinematicModuli = 0., isotropicModuli = 0.; + double k = 0.; public: J2MPlasticMaterial(int n, Domain * d); - virtual ~J2MPlasticMaterial(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveInputRecordName() const { return _IFT_J2MPlasticMaterial_Name; } - virtual const char *giveClassName() const { return "J2MPlasticMaterial"; } + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_J2MPlasticMaterial_Name; } + const char *giveClassName() const override { return "J2MPlasticMaterial"; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: - virtual void computeStressSpaceHardeningVars(FloatArray &answer, GaussPoint *gp, - const FloatArray &strainSpaceHardeningVariables); - virtual double computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars); - virtual void computeHardeningReducedModuli(FloatMatrix &answer, GaussPoint *gp, - const FloatArray &strainSpaceHardeningVariables, - TimeStep *tStep); - virtual void computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars); - virtual void computeStressSpaceHardeningVarsReducedGradient(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, - const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars); - virtual int hasHardening(); - virtual void computeReducedGradientMatrix(FloatMatrix &answer, int isurf, - GaussPoint *gp, - const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars); + void computeStressSpaceHardeningVars(FloatArray &answer, GaussPoint *gp, + const FloatArray &strainSpaceHardeningVariables) const override; + double computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, + const FloatArray &stressSpaceHardeningVars) const override; + void computeHardeningReducedModuli(FloatMatrix &answer, GaussPoint *gp, + const FloatArray &strainSpaceHardeningVariables, + TimeStep *tStep) const override; + void computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, + const FloatArray &stressSpaceHardeningVars) const override; + void computeStressSpaceHardeningVarsReducedGradient(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, + const FloatArray &stressVector, + const FloatArray &stressSpaceHardeningVars) const override; + int hasHardening() const override; + void computeReducedGradientMatrix(FloatMatrix &answer, int isurf, + GaussPoint *gp, + const FloatArray &stressVector, + const FloatArray &stressSpaceHardeningVars) const override; virtual void compute3dElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep); + TimeStep *tStep) const; // auxiliary function - double computeJ2InvariantAt(const FloatArray &stressVector); - int giveSizeOfFullHardeningVarsVector(); - int giveSizeOfReducedHardeningVarsVector(GaussPoint *gp) const; - double giveIsotropicHardeningVar(const FloatArray &stressSpaceHardeningVars); - void giveStressBackVector(FloatArray &answer, - const FloatArray &stressSpaceHardeningVars); + double computeJ2InvariantAt(const FloatArray &stressVector) const; + int giveSizeOfFullHardeningVarsVector() const override; + int giveSizeOfReducedHardeningVarsVector(GaussPoint *gp) const override; + double giveIsotropicHardeningVar(const FloatArray &stressSpaceHardeningVars) const; + void giveStressBackVector(FloatArray &answer, const FloatArray &stressSpaceHardeningVars) const; }; } // end namespace oofem #endif // j2mplasticmaterial_h diff --git a/src/sm/Materials/Obsolete/j2plasticmaterial.C b/src/sm/Materials/Obsolete/j2plasticmaterial.C index 47bdce176..d63743a04 100644 --- a/src/sm/Materials/Obsolete/j2plasticmaterial.C +++ b/src/sm/Materials/Obsolete/j2plasticmaterial.C @@ -33,7 +33,7 @@ */ #include "j2plasticmaterial.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" @@ -47,24 +47,16 @@ REGISTER_Material(J2plasticMaterial); J2plasticMaterial :: J2plasticMaterial(int n, Domain *d) : PlasticMaterial(n, d) { - kinematicHardeningFlag = isotropicHardeningFlag = 0; linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); } -J2plasticMaterial :: ~J2plasticMaterial() -{ -} - -IRResultType -J2plasticMaterial :: initializeFrom(InputRecord *ir) +void +J2plasticMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro double value; - result = PlasticMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - result = linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) return result; + PlasticMaterial :: initializeFrom(ir); + linearElasticMaterial->initializeFrom(ir); IR_GIVE_FIELD(ir, value, _IFT_J2plasticMaterial_ry); k = value / sqrt(3.0); @@ -82,8 +74,6 @@ J2plasticMaterial :: initializeFrom(InputRecord *ir) if ( fabs(isotropicModuli) > 1.e-12 ) { isotropicHardeningFlag = 1; } - - return IRRT_OK; } void J2plasticMaterial :: giveInputRecord(DynamicInputRecord &input) @@ -105,13 +95,13 @@ void J2plasticMaterial :: giveInputRecord(DynamicInputRecord &input) MaterialStatus * J2plasticMaterial :: CreateStatus(GaussPoint *gp) const { - return new PlasticMaterialStatus(1, this->giveDomain(), gp, this->giveSizeOfReducedHardeningVarsVector(gp)); + return new PlasticMaterialStatus(gp, this->giveSizeOfReducedHardeningVarsVector(gp)); } FloatArray * J2plasticMaterial :: ComputeStressSpaceHardeningVars(GaussPoint *gp, - FloatArray *strainSpaceHardeningVariables) + FloatArray *strainSpaceHardeningVariables) const { // in full stress strain space @@ -149,7 +139,7 @@ J2plasticMaterial :: ComputeStressSpaceHardeningVars(GaussPoint *gp, double J2plasticMaterial :: computeYieldValueAt(GaussPoint *gp, FloatArray *stressVector, - FloatArray *stressSpaceHardeningVars) + FloatArray *stressSpaceHardeningVars) const { double f; FloatArray helpVector, backStress; @@ -178,7 +168,7 @@ void J2plasticMaterial :: computeHardeningReducedModuli(FloatMatrix &answer, GaussPoint *gp, FloatArray *strainSpaceHardeningVariables, - TimeStep *tStep) + TimeStep *tStep) const { /* computes hardening moduli in reduced stress strain space (for kinematic back-stress)*/ int size = this->giveSizeOfReducedHardeningVarsVector(gp); @@ -208,7 +198,7 @@ J2plasticMaterial :: computeHardeningReducedModuli(FloatMatrix &answer, FloatArray * J2plasticMaterial :: ComputeStressGradient(GaussPoint *gp, FloatArray *stressVector, - FloatArray *stressSpaceHardeningVars) + FloatArray *stressSpaceHardeningVars) const { /* stress gradient of yield function in full stress - strain space */ @@ -256,7 +246,7 @@ J2plasticMaterial :: ComputeStressGradient(GaussPoint *gp, FloatArray *stressVec FloatArray * J2plasticMaterial :: ComputeStressSpaceHardeningVarsReducedGradient(GaussPoint *gp, FloatArray *stressVector, - FloatArray *stressSpaceHardeningVars) + FloatArray *stressSpaceHardeningVars) const { /* computes stress space hardening gradient in reduced stress-strain space */ @@ -297,7 +287,7 @@ J2plasticMaterial :: ComputeStressSpaceHardeningVarsReducedGradient(GaussPoint * int -J2plasticMaterial :: hasHardening() +J2plasticMaterial :: hasHardening() const { return ( this->kinematicHardeningFlag || this->isotropicHardeningFlag ); } @@ -307,7 +297,7 @@ void J2plasticMaterial :: computeReducedGradientMatrix(FloatMatrix &answer, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) + const FloatArray &stressSpaceHardeningVars) const { int size; int imask, jmask; @@ -408,13 +398,13 @@ J2plasticMaterial :: computeReducedGradientMatrix(FloatMatrix &answer, void J2plasticMaterial :: computeTrialStressIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &strainIncrement, - TimeStep *tStep) + TimeStep *tStep) const { /* Computes the full trial elastic stress vector */ FloatArray reducedAnswer; FloatMatrix reducedModuli; - this->giveLinearElasticMaterial()->giveStiffnessMatrix(reducedModuli, ElasticStiffness, + this->linearElasticMaterial->giveStiffnessMatrix(reducedModuli, ElasticStiffness, gp, tStep); reducedAnswer.beProductOf(reducedModuli, strainIncrement); @@ -425,15 +415,15 @@ J2plasticMaterial :: computeTrialStressIncrement(FloatArray &answer, GaussPoint void J2plasticMaterial :: compute3dElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { /* Returns 3d elastic moduli */ - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, ElasticStiffness, gp, tStep); + answer = this->linearElasticMaterial->give3dMaterialStiffnessMatrix(ElasticStiffness, gp, tStep); } double -J2plasticMaterial :: computeJ2InvariantAt(FloatArray *stressVector) +J2plasticMaterial :: computeJ2InvariantAt(FloatArray *stressVector) const { double answer; double v1, v2, v3; @@ -454,7 +444,7 @@ J2plasticMaterial :: computeJ2InvariantAt(FloatArray *stressVector) int -J2plasticMaterial :: giveSizeOfFullHardeningVarsVector() +J2plasticMaterial :: giveSizeOfFullHardeningVarsVector() const { /* Returns the size of hardening variables vector */ int size = 0; @@ -490,7 +480,7 @@ J2plasticMaterial :: giveSizeOfReducedHardeningVarsVector(GaussPoint *gp) const void J2plasticMaterial :: giveStressBackVector(FloatArray &answer, - const FloatArray &stressSpaceHardeningVars) + const FloatArray &stressSpaceHardeningVars) const { /* returns part of hardening vector corresponding to kinematic hardening */ if ( this->kinematicHardeningFlag ) { @@ -507,7 +497,7 @@ J2plasticMaterial :: giveStressBackVector(FloatArray &answer, double -J2plasticMaterial :: giveIsotropicHardeningVar(FloatArray *stressSpaceHardeningVars) +J2plasticMaterial :: giveIsotropicHardeningVar(FloatArray *stressSpaceHardeningVars) const { /* returns value in hardening vector corresponding to isotropic hardening */ if ( !isotropicHardeningFlag ) { diff --git a/src/sm/Materials/Obsolete/j2plasticmaterial.h b/src/sm/Materials/Obsolete/j2plasticmaterial.h index e535115e1..0a93e30d5 100644 --- a/src/sm/Materials/Obsolete/j2plasticmaterial.h +++ b/src/sm/Materials/Obsolete/j2plasticmaterial.h @@ -56,21 +56,20 @@ class Domain; class J2plasticMaterial : public PlasticMaterial { protected: - int kinematicHardeningFlag, isotropicHardeningFlag; - double kinematicModuli, isotropicModuli; - //double E, nu; // isotropic material constants - double k; + int kinematicHardeningFlag = 0, isotropicHardeningFlag = 0; + double kinematicModuli = 0., isotropicModuli = 0.; + //double E = 0., nu = 0.; // isotropic material constants + double k = 0.; public: J2plasticMaterial(int n, Domain * d); - virtual ~J2plasticMaterial(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveInputRecordName() const { return _IFT_J2plasticMaterial_Name; } - virtual const char *giveClassName() const { return "J2plasticMaterial"; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveInputRecordName() const override { return _IFT_J2plasticMaterial_Name; } + const char *giveClassName() const override { return "J2plasticMaterial"; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: @@ -78,33 +77,32 @@ class J2plasticMaterial : public PlasticMaterial // yield(YC-like functions) and loading(LC-like functions) criteria specific section // - virtual FloatArray *ComputeStressSpaceHardeningVars(GaussPoint *gp, - FloatArray *strainSpaceHardeningVariables); - virtual double computeYieldValueAt(GaussPoint *gp, FloatArray *stressVector, - FloatArray *stressSpaceHardeningVars); - virtual void computeHardeningReducedModuli(FloatMatrix &answer, GaussPoint *gp, - FloatArray *strainSpaceHardeningVariables, - TimeStep *tStep); - virtual FloatArray *ComputeStressGradient(GaussPoint *gp, FloatArray *stressVector, - FloatArray *stressSpaceHardeningVars); - virtual FloatArray *ComputeStressSpaceHardeningVarsReducedGradient(GaussPoint *gp, - FloatArray *stressVector, - FloatArray *stressSpaceHardeningVars); - virtual int hasHardening(); - virtual void computeReducedGradientMatrix(FloatMatrix &answer, GaussPoint *gp, - const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars); - virtual void computeTrialStressIncrement(FloatArray &answer, GaussPoint *gp, - const FloatArray &strainIncrement, TimeStep *tStep); - virtual void compute3dElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep); + FloatArray *ComputeStressSpaceHardeningVars(GaussPoint *gp, + FloatArray *strainSpaceHardeningVariables) const override; + double computeYieldValueAt(GaussPoint *gp, FloatArray *stressVector, + FloatArray *stressSpaceHardeningVars) const override; + void computeHardeningReducedModuli(FloatMatrix &answer, GaussPoint *gp, + FloatArray *strainSpaceHardeningVariables, + TimeStep *tStep) const override; + FloatArray *ComputeStressGradient(GaussPoint *gp, FloatArray *stressVector, + FloatArray *stressSpaceHardeningVars) const override; + FloatArray *ComputeStressSpaceHardeningVarsReducedGradient(GaussPoint *gp, + FloatArray *stressVector, + FloatArray *stressSpaceHardeningVars) const override; + int hasHardening() const override; + void computeReducedGradientMatrix(FloatMatrix &answer, GaussPoint *gp, + const FloatArray &stressVector, + const FloatArray &stressSpaceHardeningVars) const override; + void computeTrialStressIncrement(FloatArray &answer, GaussPoint *gp, + const FloatArray &strainIncrement, TimeStep *tStep) const override; + void compute3dElasticModuli(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) const override; // auxiliary function - double computeJ2InvariantAt(FloatArray *answer); - int giveSizeOfFullHardeningVarsVector(); - int giveSizeOfReducedHardeningVarsVector(GaussPoint *gp) const; - double giveIsotropicHardeningVar(FloatArray *stressSpaceHardeningVars); - void giveStressBackVector(FloatArray &answer, const FloatArray &stressSpaceHardeningVars); + double computeJ2InvariantAt(FloatArray *answer) const; + int giveSizeOfFullHardeningVarsVector() const override; + int giveSizeOfReducedHardeningVarsVector(GaussPoint *gp) const override; + double giveIsotropicHardeningVar(FloatArray *stressSpaceHardeningVars) const; + void giveStressBackVector(FloatArray &answer, const FloatArray &stressSpaceHardeningVars) const; }; } // end namespace oofem #endif // j2plasticmaterial_h diff --git a/src/sm/Materials/Obsolete/mplasticmaterial.C b/src/sm/Materials/Obsolete/mplasticmaterial.C index 9da3ab111..57694628e 100644 --- a/src/sm/Materials/Obsolete/mplasticmaterial.C +++ b/src/sm/Materials/Obsolete/mplasticmaterial.C @@ -46,27 +46,18 @@ namespace oofem { #define PLASTIC_MATERIAL_MAX_ITERATIONS 90 MPlasticMaterial :: MPlasticMaterial(int n, Domain *d) : StructuralMaterial(n, d) - // - // constructor - // { - linearElasticMaterial = NULL; - rmType = mpm_ClosestPoint; - plType = associatedPT; } MPlasticMaterial :: ~MPlasticMaterial() -// -// destructor -// { delete linearElasticMaterial; } -int -MPlasticMaterial :: hasMaterialModeCapability(MaterialMode mode) +bool +MPlasticMaterial :: hasMaterialModeCapability(MaterialMode mode) const // // returns whether receiver supports given mode // @@ -83,7 +74,7 @@ MPlasticMaterial :: hasMaterialModeCapability(MaterialMode mode) MaterialStatus * MPlasticMaterial :: CreateStatus(GaussPoint *gp) const { - return new MPlasticMaterialStatus(1, this->giveDomain(), gp, this->giveSizeOfReducedHardeningVarsVector(gp)); + return new MPlasticMaterialStatus(gp, this->giveSizeOfReducedHardeningVarsVector(gp)); } @@ -661,7 +652,7 @@ void MPlasticMaterial :: computeGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, - const FloatArray &fullStressSpaceHardeningVars) + const FloatArray &fullStressSpaceHardeningVars) const { /* * Computes gradient vector R in reduced form. @@ -674,7 +665,7 @@ MPlasticMaterial :: computeGradientVector(FloatArray &answer, functType ftype, i */ FloatArray stressGradient, stressGradientR; FloatArray stressSpaceHardVarGradient; - int i, isize, size; + int isize, size; this->computeStressGradientVector(stressGradient, ftype, isurf, gp, fullStressVector, fullStressSpaceHardeningVars); @@ -692,11 +683,11 @@ MPlasticMaterial :: computeGradientVector(FloatArray &answer, functType ftype, i } answer.resize(size); - for ( i = 1; i <= isize; i++ ) { + for ( int i = 1; i <= isize; i++ ) { answer.at(i) = stressGradientR.at(i); } - for ( i = isize + 1; i <= size; i++ ) { + for ( int i = isize + 1; i <= size; i++ ) { answer.at(i) = stressSpaceHardVarGradient.at(i - isize); } } @@ -711,7 +702,7 @@ MPlasticMaterial :: computeResidualVector(FloatArray &answer, GaussPoint *gp, co /* Computes Residual vector for closest point projection algorithm */ FloatArray oldPlasticStrainVectorR, oldStrainSpaceHardeningVariables; - int i, j, isize, size; + int isize, size; MPlasticMaterialStatus *status = static_cast< MPlasticMaterialStatus * >( this->giveStatus(gp) ); isize = plasticStrainVectorR.giveSize(); @@ -721,17 +712,17 @@ MPlasticMaterial :: computeResidualVector(FloatArray &answer, GaussPoint *gp, co oldPlasticStrainVectorR = status->givePlasticStrainVector(); oldStrainSpaceHardeningVariables = status->giveStrainSpaceHardeningVars(); - for ( i = 1; i <= isize; i++ ) { + for ( int i = 1; i <= isize; i++ ) { answer.at(i) = oldPlasticStrainVectorR.at(i) - plasticStrainVectorR.at(i); } - for ( i = isize + 1; i <= size; i++ ) { + for ( int i = isize + 1; i <= size; i++ ) { answer.at(i) = oldStrainSpaceHardeningVariables.at(i - isize) - strainSpaceHardeningVariables.at(i - isize); } - for ( i = 1; i <= this->nsurf; i++ ) { + for ( int i = 1; i <= this->nsurf; i++ ) { if ( activeConditionMap.at(i) ) { - for ( j = 1; j <= size; j++ ) { + for ( int j = 1; j <= size; j++ ) { answer.at(j) += gamma.at(i) * gradientVectorR [ i - 1 ].at(j); } } @@ -742,7 +733,7 @@ MPlasticMaterial :: computeResidualVector(FloatArray &answer, GaussPoint *gp, co void MPlasticMaterial :: computeTrialStressIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &elasticStrainVectorR, - TimeStep *tStep) + TimeStep *tStep) const { /* Computes the full trial elastic stress vector */ @@ -764,7 +755,7 @@ MPlasticMaterial :: computeAlgorithmicModuli(FloatMatrix &answer, const FloatArray &gamma, const IntArray &activeConditionMap, const FloatArray &fullStressVector, - const FloatArray &fullStressSpaceHardeningVars) + const FloatArray &fullStressSpaceHardeningVars) const { /* returns consistent moduli in reduced form. * Note: elasticModuli and hardeningModuli will be inverted @@ -828,11 +819,10 @@ MPlasticMaterial :: computeAlgorithmicModuli(FloatMatrix &answer, // ----------------------------------------------------------------------------// -void -MPlasticMaterial :: giveConsistentStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrix +MPlasticMaterial :: giveConsistentStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { // // returns receiver material matrix for given reached state @@ -867,8 +857,9 @@ MPlasticMaterial :: giveConsistentStiffnessMatrix(FloatMatrix &answer, // check for elastic cases // if ( ( status->giveTempStateFlag() == MPlasticMaterialStatus :: PM_Elastic ) || ( status->giveTempStateFlag() == MPlasticMaterialStatus :: PM_Unloading ) ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, TangentStiffness, gp, tStep); - return; + FloatMatrix answer; + this->linearElasticMaterial->giveStiffnessMatrix(answer, TangentStiffness, gp, tStep); + return answer; } // @@ -943,8 +934,10 @@ MPlasticMaterial :: giveConsistentStiffnessMatrix(FloatMatrix &answer, helpMtrx2.beProductOf(helpMtrx, nmat); + FloatMatrix answer; answer.beSubMatrixOf(consistentModuli, 1, sizeR, 1, sizeR); answer.subtract(helpMtrx2); + return answer; } else { FloatMatrix lgradMat(actSurf, size); for ( i = 1; i <= nsurf; i++ ) { @@ -968,8 +961,10 @@ MPlasticMaterial :: giveConsistentStiffnessMatrix(FloatMatrix &answer, nmat.beProductOf(gradMat, sbm1); helpMtrx2.beProductOf(helpMtrx, nmat); + FloatMatrix answer; answer.beSubMatrixOf(consistentModuli, 1, sizeR, 1, sizeR); answer.subtract(helpMtrx2); + return answer; } } @@ -978,7 +973,7 @@ void MPlasticMaterial :: giveElastoPlasticStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { // // returns receiver material matrix for given reached state @@ -1003,7 +998,7 @@ MPlasticMaterial :: giveElastoPlasticStiffnessMatrix(FloatMatrix &answer, // check for elastic cases // if ( ( status->giveTempStateFlag() == MPlasticMaterialStatus :: PM_Elastic ) || ( status->giveTempStateFlag() == MPlasticMaterialStatus :: PM_Unloading ) ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, TangentStiffness, gp, tStep); + this->linearElasticMaterial->giveStiffnessMatrix(answer, TangentStiffness, gp, tStep); return; } @@ -1109,12 +1104,12 @@ MPlasticMaterial :: giveElastoPlasticStiffnessMatrix(FloatMatrix &answer, void MPlasticMaterial :: computeDiagModuli(FloatMatrix &answer, GaussPoint *gp, FloatMatrix &elasticModuliInverse, - FloatMatrix &hardeningModuliInverse) + FloatMatrix &hardeningModuliInverse) const { // // assembles diagonal moduli from elasticModuliInverse and hardeningModuliInverse // - int size1, size2, i, j; + int size1, size2; size1 = elasticModuliInverse.giveNumberOfRows(); if ( hardeningModuliInverse.giveNumberOfRows() ) { @@ -1126,14 +1121,14 @@ MPlasticMaterial :: computeDiagModuli(FloatMatrix &answer, answer.resize(size2, size2); answer.zero(); - for ( i = 1; i <= size1; i++ ) { - for ( j = 1; j <= size1; j++ ) { + for ( int i = 1; i <= size1; i++ ) { + for ( int j = 1; j <= size1; j++ ) { answer.at(i, j) = elasticModuliInverse.at(i, j); } } - for ( i = size1 + 1; i <= size2; i++ ) { - for ( j = size1 + 1; j <= size2; j++ ) { + for ( int i = size1 + 1; i <= size2; i++ ) { + for ( int j = size1 + 1; j <= size2; j++ ) { answer.at(i, j) = hardeningModuliInverse.at(i - size1, j - size1); } } @@ -1143,21 +1138,18 @@ MPlasticMaterial :: computeDiagModuli(FloatMatrix &answer, void MPlasticMaterial :: computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { /* Returns elastic moduli in reduced stress-strain space*/ - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, - ElasticStiffness, - gp, tStep); + this->linearElasticMaterial->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); } // overloaded from structural material -void -MPlasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +MPlasticMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // // @@ -1174,11 +1166,6 @@ MPlasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, // // { - MaterialMode originalMode = gp->giveMaterialMode(); - if ( originalMode != _3dMat ) { - OOFEM_ERROR("Different stressStrain mode encountered"); - } - // we can force 3d response, and we obtain correct 3d tangent matrix, // but in fact, stress integration algorithm will not work // because in stress integration algorithm we are unable to recognize @@ -1188,20 +1175,21 @@ MPlasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, // then programming simple inteface function for you stressstrain state // calling GiveMaterailStiffenssMatrix, which imposes constrains correctly. if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->give3dMaterialStiffnessMatrix(mode, gp, tStep); } else if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { + FloatMatrix answer; this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return answer; } } -void -MPlasticMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +MPlasticMaterial :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dPlaneStressMtrx @@ -1212,20 +1200,21 @@ MPlasticMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, // this implementation should be faster. { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep); } else if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { + FloatMatrix answer; this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return answer; } } -void -MPlasticMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<4,4> +MPlasticMaterial :: givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // return receiver's 2dPlaneStrainMtrx constructed from @@ -1234,40 +1223,42 @@ MPlasticMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, // { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlaneStrainStiffMtrx(mode, gp, tStep); } else if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { + FloatMatrix answer; this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return answer; } } -void -MPlasticMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<1,1> +MPlasticMaterial :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 1dMaterialStiffnessMAtrix // (1d case ==> sigma_y = sigma_z = tau_yz = tau_zx = tau_xy = 0.) { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->give1dStressStiffMtrx(mode, gp, tStep); } else if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return answer; } } -void -MPlasticMaterial :: give2dBeamLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<2,2> +MPlasticMaterial :: give2dBeamLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dBeamLayerStiffMtrx. // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -1277,20 +1268,21 @@ MPlasticMaterial :: give2dBeamLayerStiffMtrx(FloatMatrix &answer, // this implementation should be faster. { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->give2dBeamLayerStiffMtrx(mode, gp, tStep); } else if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return answer; } } -void -MPlasticMaterial :: givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<5,5> +MPlasticMaterial :: givePlateLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dPlateLayerMtrx // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -1300,20 +1292,21 @@ MPlasticMaterial :: givePlateLayerStiffMtrx(FloatMatrix &answer, // this implementation should be faster. { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlateLayerStiffMtrx(mode, gp, tStep); } else if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return answer; } } -void -MPlasticMaterial :: giveFiberStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +MPlasticMaterial :: giveFiberStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's Fiber // (1dFiber ==> sigma_y = sigma_z = tau_yz = 0.) @@ -1323,11 +1316,13 @@ MPlasticMaterial :: giveFiberStiffMtrx(FloatMatrix &answer, // this implementation should be faster. { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->giveFiberStiffMtrx(mode, gp, tStep); } else if ( rmType == mpm_ClosestPoint ) { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } else { - this->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveElastoPlasticStiffnessMatrix(answer, mode, gp, tStep); + return answer; } } @@ -1356,22 +1351,14 @@ MPlasticMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStat } -MPlasticMaterialStatus :: MPlasticMaterialStatus(int n, Domain *d, GaussPoint *g, int statusSize) : - StructuralMaterialStatus(n, d, g), plasticStrainVector(), tempPlasticStrainVector(), - strainSpaceHardeningVarsVector(statusSize), tempStrainSpaceHardeningVarsVector(statusSize), - gamma(), - tempGamma() -{ - state_flag = temp_state_flag = MPlasticMaterialStatus :: PM_Elastic; -} - - -MPlasticMaterialStatus :: ~MPlasticMaterialStatus() -{ } +MPlasticMaterialStatus :: MPlasticMaterialStatus(GaussPoint *g, int statusSize) : + StructuralMaterialStatus(g), + strainSpaceHardeningVarsVector(statusSize), tempStrainSpaceHardeningVarsVector(statusSize) +{} void -MPlasticMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +MPlasticMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -1440,21 +1427,12 @@ MPlasticMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -MPlasticMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +MPlasticMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: saveContext(stream, mode); - // write a raw data + contextIOResultType iores; if ( ( iores = plasticStrainVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -1474,25 +1452,15 @@ MPlasticMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void if ( ( iores = activeConditionMap.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - - return CIO_OK; } -contextIOResultType -MPlasticMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +MPlasticMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: restoreContext(stream, mode); + contextIOResultType iores; if ( ( iores = plasticStrainVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -1512,8 +1480,5 @@ MPlasticMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, v if ( ( iores = activeConditionMap.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - - return CIO_OK; // return succes } } // end namespace oofem diff --git a/src/sm/Materials/Obsolete/mplasticmaterial.h b/src/sm/Materials/Obsolete/mplasticmaterial.h index d9e6e32c8..5c6ba84ef 100644 --- a/src/sm/Materials/Obsolete/mplasticmaterial.h +++ b/src/sm/Materials/Obsolete/mplasticmaterial.h @@ -35,12 +35,12 @@ #ifndef mplasticmaterial_h #define mplasticmaterial_h -#include "../sm/Materials/structuralmaterial.h" -#include "Materials/linearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/linearelasticmaterial.h" #include "intarray.h" #include "floatarray.h" #include "floatmatrix.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include @@ -76,8 +76,8 @@ class MPlasticMaterialStatus : public StructuralMaterialStatus FloatArray tempStrainSpaceHardeningVarsVector; /// Yield function status indicator. - int state_flag; - int temp_state_flag; + int state_flag = MPlasticMaterialStatus :: PM_Elastic; + int temp_state_flag = MPlasticMaterialStatus :: PM_Elastic; /// Consistency parameter values (needed for algorithmic stiffness). FloatArray gamma, tempGamma; @@ -85,16 +85,15 @@ class MPlasticMaterialStatus : public StructuralMaterialStatus IntArray activeConditionMap, tempActiveConditionMap; public: - MPlasticMaterialStatus(int n, Domain * d, GaussPoint * g, int statusSize); - virtual ~MPlasticMaterialStatus(); + MPlasticMaterialStatus(GaussPoint * g, int statusSize); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; /// Returns the equilibrated strain vector. const FloatArray &givePlasticStrainVector() const { return plasticStrainVector; } @@ -126,7 +125,7 @@ class MPlasticMaterialStatus : public StructuralMaterialStatus void setTempGamma(FloatArray v) { tempGamma = std :: move(v); } // definition - virtual const char *giveClassName() const { return "MPlasticMaterialStatus"; } + const char *giveClassName() const override { return "MPlasticMaterialStatus"; } }; /** @@ -143,23 +142,22 @@ class MPlasticMaterial : public StructuralMaterial { protected: /// Reference to bulk (undamaged) material. - LinearElasticMaterial *linearElasticMaterial; + LinearElasticMaterial *linearElasticMaterial = nullptr; /// Number of yield surfaces. - int nsurf; + int nsurf = 0; /// Protected type to determine the return mapping algorithm. - enum ReturnMappingAlgoType { mpm_ClosestPoint, mpm_CuttingPlane } rmType; + enum ReturnMappingAlgoType { mpm_ClosestPoint, mpm_CuttingPlane } rmType = mpm_ClosestPoint; /// Type that allows to distinguish between yield function and loading function. enum functType { yieldFunction, loadFunction }; - enum plastType { associatedPT, nonassociatedPT } plType; + enum plastType { associatedPT, nonassociatedPT } plType = associatedPT; public: MPlasticMaterial(int n, Domain * d); virtual ~MPlasticMaterial(); // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 1; } - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual const char *giveClassName() const { return "MPlasticMaterial"; } + bool hasMaterialModeCapability(MaterialMode mode) const override; + const char *giveClassName() const override { return "MPlasticMaterial"; } /// Returns reference to undamaged (bulk) material. LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } @@ -168,33 +166,46 @@ class MPlasticMaterial : public StructuralMaterial * Returns true if stiffness matrix of receiver is symmetric. * Default implementation returns true. */ - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return true; } - - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); - - - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *, - const FloatArray &, TimeStep *); - - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return true; } + + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + + + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &, TimeStep *tStep) override; + + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<4> giveRealStressVector_PlaneStrain(const FloatArrayF<4> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; // auxiliary functions - virtual int giveSizeOfFullHardeningVarsVector() { return 0; } + virtual int giveSizeOfFullHardeningVarsVector() const { return 0; } virtual int giveSizeOfReducedHardeningVarsVector(GaussPoint *) const { return 0; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: void closestPointReturn(FloatArray &answer, IntArray &activeConditionMap, FloatArray &gamma, @@ -208,81 +219,60 @@ class MPlasticMaterial : public StructuralMaterial FloatArray &strainSpaceHardeningVariables, TimeStep *tStep); void computeGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, - const FloatArray &fullStressSpaceHardeningVars); + const FloatArray &fullStressSpaceHardeningVars) const; void computeResidualVector(FloatArray &answer, GaussPoint *gp, const FloatArray &gamma, const IntArray &activeConditionMap, const FloatArray &plasticStrainVectorR, const FloatArray &strainSpaceHardeningVariables, std :: vector< FloatArray > &gradVec); - virtual void giveConsistentStiffnessMatrix(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); + virtual FloatMatrix giveConsistentStiffnessMatrix(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const; virtual void giveElastoPlasticStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep); + TimeStep *tStep) const; void computeAlgorithmicModuli(FloatMatrix &answer, GaussPoint *gp, const FloatMatrix &elasticModuliInverse, const FloatMatrix &hardeningModuliInverse, const FloatArray &gamma, const IntArray &activeConditionMap, const FloatArray &fullStressVector, - const FloatArray &fullStressSpaceHardeningVars); + const FloatArray &fullStressSpaceHardeningVars) const; void computeDiagModuli(FloatMatrix &answer, GaussPoint *gp, FloatMatrix &elasticModuliInverse, - FloatMatrix &hardeningModuliInverse); + FloatMatrix &hardeningModuliInverse) const ; virtual void computeStressSpaceHardeningVars(FloatArray &answer, GaussPoint *gp, - const FloatArray &strainSpaceHardeningVariables) = 0; + const FloatArray &strainSpaceHardeningVariables) const = 0; virtual double computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) = 0; + const FloatArray &stressSpaceHardeningVars) const = 0; virtual void computeHardeningReducedModuli(FloatMatrix &answer, GaussPoint *gp, const FloatArray &strainSpaceHardeningVariables, - TimeStep *tStep) = 0; + TimeStep *tStep) const = 0; virtual void computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) = 0; + const FloatArray &stressSpaceHardeningVars) const = 0; virtual void computeStressSpaceHardeningVarsReducedGradient(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) = 0; - virtual int hasHardening() { return 0; } + const FloatArray &stressSpaceHardeningVars) const = 0; + virtual int hasHardening() const { return 0; } virtual void computeReducedGradientMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) = 0; + const FloatArray &stressSpaceHardeningVars) const = 0; virtual void computeTrialStressIncrement(FloatArray &answer, GaussPoint *gp, - const FloatArray &strainIncrement, TimeStep *tStep); + const FloatArray &strainIncrement, TimeStep *tStep) const; virtual void computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep); + TimeStep *tStep) const; //virtual void compute3dElasticModuli(FloatMatrix& answer, GaussPoint *gp, // TimeStep *tStep) = 0; // next functions overloaded from structural material level - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); - virtual void give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); - virtual void give2dBeamLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); - virtual void givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void giveFiberStiffMtrx(FloatMatrix &answer, - MatResponseMode, GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<2,2> give2dBeamLayerStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<5,5> givePlateLayerStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> giveFiberStiffMtrx(MatResponseMode, GaussPoint *gp, TimeStep *tStep) const override; }; } // end namespace oofem #endif // mplasticmaterial_h diff --git a/src/sm/Materials/Obsolete/perfectlyplasticmaterial.C b/src/sm/Materials/Obsolete/perfectlyplasticmaterial.C index ea0f0dddd..115613c45 100644 --- a/src/sm/Materials/Obsolete/perfectlyplasticmaterial.C +++ b/src/sm/Materials/Obsolete/perfectlyplasticmaterial.C @@ -33,7 +33,7 @@ */ #include "perfectlyplasticmaterial.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" @@ -42,8 +42,8 @@ #include "contextioerr.h" namespace oofem { -int -PerfectlyPlasticMaterial :: hasMaterialModeCapability(MaterialMode mode) +bool +PerfectlyPlasticMaterial :: hasMaterialModeCapability(MaterialMode mode) const // // returns whether receiver supports given mode // @@ -350,11 +350,10 @@ PerfectlyPlasticMaterial :: giveMaterialStiffnessMatrix(FloatMatrix &answer, Mat } -void -PerfectlyPlasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +PerfectlyPlasticMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // // @@ -370,11 +369,6 @@ PerfectlyPlasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, // // { - MaterialMode originalMode = gp->giveMaterialMode(); - if ( originalMode != _3dMat ) { - OOFEM_ERROR("Different stressStrain mode encountered"); - } - // we can force 3d response, and we obtain correct 3d tangent matrix, // but in fact, stress integration algorithm will not work // because in stress integration algorithm we are unable to recognize @@ -385,19 +379,19 @@ PerfectlyPlasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, // calling GiveMaterailStiffenssMatrix, which imposes constrains correctly. if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->give3dMaterialStiffnessMatrix(mode, gp, tStep); } else { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } } -void -PerfectlyPlasticMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +PerfectlyPlasticMaterial :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) - + TimeStep *tStep) const // // returns receiver's 2dPlaneStressMtrx // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -406,64 +400,61 @@ PerfectlyPlasticMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, // the reduction from 3d case will not work // this implementation should be faster. { - FloatMatrix fullAnswer; if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep); } else { - this->giveMaterialStiffnessMatrix(fullAnswer, mode, gp, tStep); + FloatMatrix fullAnswer, answer; + const_cast(this)->giveMaterialStiffnessMatrix(fullAnswer, mode, gp, tStep); StructuralMaterial :: giveReducedSymMatrixForm( answer, fullAnswer, gp->giveMaterialMode() ); + return answer; } } -void -PerfectlyPlasticMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<4,4> +PerfectlyPlasticMaterial :: givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) - + TimeStep *tStep) const // // return receiver's 2dPlaneStrainMtrx constructed from // general 3dMatrialStiffnessMatrix // (2dPlaneStrain ==> eps_z = gamma_xz = gamma_yz = 0.) // { - FloatMatrix fullAnswer; if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlaneStrainStiffMtrx(mode, gp, tStep); } else { - this->giveMaterialStiffnessMatrix(fullAnswer, mode, gp, tStep); + FloatMatrix fullAnswer, answer; + const_cast(this)->giveMaterialStiffnessMatrix(fullAnswer, mode, gp, tStep); StructuralMaterial :: giveReducedSymMatrixForm( answer, fullAnswer, gp->giveMaterialMode() ); + return answer; } } -void -PerfectlyPlasticMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF<1,1> +PerfectlyPlasticMaterial :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const // // returns receiver's 1dMaterialStiffnessMAtrix // (1d case ==> sigma_y = sigma_z = tau_yz = tau_zx = tau_xy = 0.) { - FloatMatrix fullAnswer; if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->give1dStressStiffMtrx(mode, gp, tStep); } else { - this->giveMaterialStiffnessMatrix(fullAnswer, mode, gp, tStep); + FloatMatrix fullAnswer, answer; + const_cast(this)->giveMaterialStiffnessMatrix(fullAnswer, mode, gp, tStep); StructuralMaterial :: giveReducedSymMatrixForm( answer, fullAnswer, gp->giveMaterialMode() ); + return answer; } } -void -PerfectlyPlasticMaterial :: give2dBeamLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<2,2> +PerfectlyPlasticMaterial :: give2dBeamLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dBeamLayerStiffMtrx. // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -472,21 +463,21 @@ PerfectlyPlasticMaterial :: give2dBeamLayerStiffMtrx(FloatMatrix &answer, // the reduction from 3d case will not work // this implementation should be faster. { - FloatMatrix fullAnswer; if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->give2dBeamLayerStiffMtrx(mode, gp, tStep); } else { - this->giveMaterialStiffnessMatrix(fullAnswer, mode, gp, tStep); + FloatMatrix fullAnswer, answer; + const_cast(this)->giveMaterialStiffnessMatrix(fullAnswer, mode, gp, tStep); StructuralMaterial :: giveReducedSymMatrixForm( answer, fullAnswer, gp->giveMaterialMode() ); + return answer; } } -void -PerfectlyPlasticMaterial :: givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<5,5> +PerfectlyPlasticMaterial :: givePlateLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dPlateLayerMtrx // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -495,12 +486,13 @@ PerfectlyPlasticMaterial :: givePlateLayerStiffMtrx(FloatMatrix &answer, // the reduction from 3d case will not work // this implementation should be faster. { - FloatMatrix fullAnswer; if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlateLayerStiffMtrx(mode, gp, tStep); } else { - this->giveMaterialStiffnessMatrix(fullAnswer, mode, gp, tStep); + FloatMatrix fullAnswer, answer; + const_cast(this)->giveMaterialStiffnessMatrix(fullAnswer, mode, gp, tStep); StructuralMaterial :: giveReducedSymMatrixForm( answer, fullAnswer, gp->giveMaterialMode() ); + return answer; } } @@ -632,17 +624,16 @@ PerfectlyPlasticMaterial :: GiveStressCorrectionBackToYieldSurface(GaussPoint *g } -IRResultType -PerfectlyPlasticMaterial :: initializeFrom(InputRecord *ir) +void +PerfectlyPlasticMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result = Material :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - return this->giveLinearElasticMaterial()->initializeFrom(ir); + Material :: initializeFrom(ir); + this->giveLinearElasticMaterial()->initializeFrom(ir); } double -PerfectlyPlasticMaterial :: give(int aProperty, GaussPoint *gp) +PerfectlyPlasticMaterial :: give(int aProperty, GaussPoint *gp) const // Returns the value of the property aProperty (e.g. the Young's modulus // 'E') of the receiver. { @@ -668,7 +659,7 @@ PerfectlyPlasticMaterial :: CreateStatus(GaussPoint *gp) const * creates new material status corresponding to this class */ { - return new PerfectlyPlasticMaterialStatus(1, this->giveDomain(), gp); + return new PerfectlyPlasticMaterialStatus(gp); } @@ -699,71 +690,47 @@ PerfectlyPlasticMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, Inte //################################################################################################## -PerfectlyPlasticMaterialStatus :: PerfectlyPlasticMaterialStatus(int n, Domain *d, GaussPoint *g) : - StructuralMaterialStatus(n, d, g), plasticStrainVector(), plasticStrainIncrementVector() +PerfectlyPlasticMaterialStatus :: PerfectlyPlasticMaterialStatus(GaussPoint *g) : + StructuralMaterialStatus(g), plasticStrainVector(), plasticStrainIncrementVector() { temp_yield_flag = yield_flag = 0; // elastic case at beginning } -PerfectlyPlasticMaterialStatus :: ~PerfectlyPlasticMaterialStatus() -{ } - - -contextIOResultType -PerfectlyPlasticMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// +void +PerfectlyPlasticMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: saveContext(stream, mode); - // write a raw data if ( !stream.write(yield_flag) ) { THROW_CIOERR(CIO_IOERR); } + contextIOResultType iores; if ( ( iores = plasticStrainVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - // return result back - return CIO_OK; } -contextIOResultType -PerfectlyPlasticMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restore state variables from stream -// +void +PerfectlyPlasticMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: restoreContext(stream, mode); - // read raw data if ( !stream.read(yield_flag) ) { THROW_CIOERR(CIO_IOERR); } + contextIOResultType iores; if ( ( iores = plasticStrainVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - // return result back - return CIO_OK; } void -PerfectlyPlasticMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +PerfectlyPlasticMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { yield_flag %d}\n", yield_flag); diff --git a/src/sm/Materials/Obsolete/perfectlyplasticmaterial.h b/src/sm/Materials/Obsolete/perfectlyplasticmaterial.h index fb9ceb84e..743f5d8f7 100644 --- a/src/sm/Materials/Obsolete/perfectlyplasticmaterial.h +++ b/src/sm/Materials/Obsolete/perfectlyplasticmaterial.h @@ -35,11 +35,11 @@ #ifndef perfectlyplasticmaterial_h #define perfectlyplasticmaterial_h -#include "../sm/Materials/structuralmaterial.h" -#include "Materials/linearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/linearelasticmaterial.h" #include "floatarray.h" #include "floatmatrix.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" namespace oofem { /** @@ -68,28 +68,26 @@ class PerfectlyPlasticMaterialStatus : public StructuralMaterialStatus int temp_yield_flag; public: - PerfectlyPlasticMaterialStatus(int n, Domain * d, GaussPoint * g); - virtual ~PerfectlyPlasticMaterialStatus(); + PerfectlyPlasticMaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; int setTempYieldFlag(int i) { return temp_yield_flag = i; } int giveTempYieldFlag() { return temp_yield_flag; } int giveYieldFlag() { return yield_flag; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; const FloatArray &givePlasticStrainVector() const { return plasticStrainVector; } const FloatArray &givePlasticStrainIncrementVector() const { return plasticStrainIncrementVector; } void letPlasticStrainVectorBe(FloatArray v) { plasticStrainVector = std :: move(v); } void letPlasticStrainIncrementVectorBe(FloatArray v) { plasticStrainIncrementVector = std :: move(v); } - // definition - virtual const char *giveClassName() const { return "PerfectlyPlasticMaterialStatus"; } + const char *giveClassName() const override { return "PerfectlyPlasticMaterialStatus"; } }; /** @@ -115,60 +113,74 @@ class PerfectlyPlasticMaterialStatus : public StructuralMaterialStatus class PerfectlyPlasticMaterial : public StructuralMaterial { protected: - int yieldCriteria; - int loadingCriteria; - LinearElasticMaterial *linearElasticMaterial; + int yieldCriteria = 0; + int loadingCriteria = 0; + LinearElasticMaterial *linearElasticMaterial = nullptr; public: - PerfectlyPlasticMaterial(int n, Domain * d) : StructuralMaterial(n, d) - { - yieldCriteria = 0; - loadingCriteria = 0; - linearElasticMaterial = NULL; - } + PerfectlyPlasticMaterial(int n, Domain * d) : StructuralMaterial(n, d) {} virtual ~PerfectlyPlasticMaterial() { delete linearElasticMaterial; } - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); - - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_2dBeamLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlateLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; + + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<4> giveRealStressVector_PlaneStrain(const FloatArrayF<4> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<2> giveRealStressVector_2dBeamLayer(const FloatArrayF<2> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<5> giveRealStressVector_PlateLayer(const FloatArrayF<5> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } // can be moved to parent classes virtual void updateIfFailure(GaussPoint *gp, FloatArray *stressVector3d, FloatArray *PlasticStrainVector3d) { } - // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 1; } - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual const char *giveClassName() const { return "PerfectlyPlasticMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); + bool hasMaterialModeCapability(MaterialMode mode) const override; + const char *giveClassName() const override { return "PerfectlyPlasticMaterial"; } + void initializeFrom(InputRecord &ir) override; LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } - virtual double give(int aProperty, GaussPoint *gp); + double give(int aProperty, GaussPoint *gp) const override; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: // two functions used to initialize and updating temporary variables in @@ -182,26 +194,11 @@ class PerfectlyPlasticMaterial : public StructuralMaterial MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - virtual void give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - virtual void give2dBeamLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - virtual void givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<2,2> give2dBeamLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<5,5> givePlateLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; void computeTrialStressIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &strainIncrement, TimeStep *tStep); diff --git a/src/sm/Materials/Obsolete/plasticmaterial.C b/src/sm/Materials/Obsolete/plasticmaterial.C index aeb9c086b..b8a9726bc 100644 --- a/src/sm/Materials/Obsolete/plasticmaterial.C +++ b/src/sm/Materials/Obsolete/plasticmaterial.C @@ -37,7 +37,7 @@ #include "floatmatrix.h" #include "floatarray.h" #include "intarray.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "datastream.h" #include "contextioerr.h" @@ -47,28 +47,17 @@ namespace oofem { #define PLASTIC_MATERIAL_MAX_ITERATIONS 40 PlasticMaterial :: PlasticMaterial(int n, Domain *d) : StructuralMaterial(n, d) - // - // constructor - // -{ - linearElasticMaterial = NULL; -} +{} PlasticMaterial :: ~PlasticMaterial() -// -// destructor -// { delete linearElasticMaterial; } -int -PlasticMaterial :: hasMaterialModeCapability(MaterialMode mode) -// -// returns whether receiver supports given mode -// +bool +PlasticMaterial :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _3dMat || mode == _1dMat || @@ -85,7 +74,7 @@ PlasticMaterial :: hasMaterialModeCapability(MaterialMode mode) MaterialStatus * PlasticMaterial :: CreateStatus(GaussPoint *gp) const { - return new PlasticMaterialStatus(1, this->giveDomain(), gp, this->giveSizeOfReducedHardeningVarsVector(gp)); + return new PlasticMaterialStatus(gp, this->giveSizeOfReducedHardeningVarsVector(gp)); } @@ -243,7 +232,7 @@ PlasticMaterial :: giveRealStressVector(FloatArray &answer, FloatArray * PlasticMaterial :: ComputeGradientVector(GaussPoint *gp, FloatArray *fullStressVector, - FloatArray *fullStressSpaceHardeningVars) + FloatArray *fullStressSpaceHardeningVars) const { /* * Computes gradient vector R in reduced form. @@ -292,7 +281,7 @@ FloatArray * PlasticMaterial :: ComputeResidualVector(GaussPoint *gp, double Gamma, FloatArray *plasticStrainVectorR, FloatArray *strainSpaceHardeningVariables, - FloatArray *gradientVectorR) + FloatArray *gradientVectorR) const { /* Computes Residual vector for closes point projection algorithm */ @@ -323,7 +312,7 @@ PlasticMaterial :: ComputeResidualVector(GaussPoint *gp, double Gamma, void PlasticMaterial :: computeTrialStressIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &elasticStrainVectorR, - TimeStep *tStep) + TimeStep *tStep) const { /* Computes the full trial elastic stress vector */ @@ -338,7 +327,7 @@ PlasticMaterial :: computeConsistentModuli(FloatMatrix &answer, FloatMatrix &hardeningModuliInverse, double Gamma, const FloatArray &fullStressVector, - const FloatArray &fullStressSpaceHardeningVars) + const FloatArray &fullStressSpaceHardeningVars) const { /* returns consistent moduli in reduced form. * Note: elasticModuli and hardeningModuli will be inverted @@ -388,11 +377,10 @@ PlasticMaterial :: computeConsistentModuli(FloatMatrix &answer, // ----------------------------------------------------------------------------// -void -PlasticMaterial :: giveConsistentStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrix +PlasticMaterial :: giveConsistentStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { // // returns receiver material matrix for given reached state @@ -415,8 +403,7 @@ PlasticMaterial :: giveConsistentStiffnessMatrix(FloatMatrix &answer, // check for elastic cases if ( ( status->giveTempStateFlag() == PM_Elastic ) || ( status->giveTempStateFlag() == PM_Unloading ) ) { this->computeReducedElasticModuli(elasticModuli, gp, tStep); - answer = elasticModuli; - return; + return elasticModuli; } // @@ -465,13 +452,13 @@ PlasticMaterial :: giveConsistentStiffnessMatrix(FloatMatrix &answer, delete gradientVector; delete stressSpaceHardeningVars; - answer = answerR; + return answerR; } void PlasticMaterial :: computeDiagModuli(FloatMatrix &answer, GaussPoint *gp, FloatMatrix &elasticModuliInverse, - FloatMatrix &hardeningModuliInverse) + FloatMatrix &hardeningModuliInverse) const { // // assembles diagonal moduli from elasticModuliInverse and hardeningModuliInverse @@ -505,21 +492,18 @@ PlasticMaterial :: computeDiagModuli(FloatMatrix &answer, void PlasticMaterial :: computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { /* Returns elastic moduli in reduced stress-strain space*/ - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, - ElasticStiffness, - gp, tStep); + this->linearElasticMaterial->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); } // overloaded from structural material -void -PlasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +PlasticMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // // @@ -536,11 +520,6 @@ PlasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, // // { - MaterialMode originalMode = gp->giveMaterialMode(); - if ( originalMode != _3dMat ) { - OOFEM_ERROR("Different stressStrain mode encountered"); - } - // we can force 3d response, and we obtain correct 3d tangent matrix, // but in fact, stress integration algorithm will not work // because in stress integration algorithm we are unable to recognize @@ -550,19 +529,17 @@ PlasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, // then programming simple inteface function for you stressstrain state // calling GiveMaterailStiffenssMatrix, which imposes constrains correctly. if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->give3dMaterialStiffnessMatrix(mode, gp, tStep); } else { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } } -void -PlasticMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +PlasticMaterial :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) - + TimeStep *tStep) const // // returns receiver's 2dPlaneStressMtrx // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -572,18 +549,17 @@ PlasticMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, // this implementation should be faster. { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep); } else { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } } -void -PlasticMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<4,4> +PlasticMaterial :: givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // return receiver's 2dPlaneStrainMtrx constructed from @@ -592,36 +568,34 @@ PlasticMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, // { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlaneStrainStiffMtrx(mode, gp, tStep); } else { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } } -void -PlasticMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<1,1> +PlasticMaterial :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 1dMaterialStiffnessMAtrix // (1d case ==> sigma_y = sigma_z = tau_yz = tau_zx = tau_xy = 0.) { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->give1dStressStiffMtrx(mode, gp, tStep); } else { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } } -void -PlasticMaterial :: give2dBeamLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<2,2> +PlasticMaterial :: give2dBeamLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dBeamLayerStiffMtrx. // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -631,18 +605,17 @@ PlasticMaterial :: give2dBeamLayerStiffMtrx(FloatMatrix &answer, // this implementation should be faster. { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->give2dBeamLayerStiffMtrx(mode, gp, tStep); } else { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } } -void -PlasticMaterial :: givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<5,5> +PlasticMaterial :: givePlateLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dPlateLayerMtrx // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -652,18 +625,17 @@ PlasticMaterial :: givePlateLayerStiffMtrx(FloatMatrix &answer, // this implementation should be faster. { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->givePlateLayerStiffMtrx(mode, gp, tStep); } else { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } } -void -PlasticMaterial :: giveFiberStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +PlasticMaterial :: giveFiberStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's Fiber // (1dFiber ==> sigma_y = sigma_z = tau_yz = 0.) @@ -673,9 +645,9 @@ PlasticMaterial :: giveFiberStiffMtrx(FloatMatrix &answer, // this implementation should be faster. { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + return this->linearElasticMaterial->giveFiberStiffMtrx(mode, gp, tStep); } else { - this->giveConsistentStiffnessMatrix(answer, mode, gp, tStep); + return this->giveConsistentStiffnessMatrix(mode, gp, tStep); } } @@ -704,21 +676,14 @@ PlasticMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalState } -PlasticMaterialStatus :: PlasticMaterialStatus(int n, Domain *d, GaussPoint *g, int statusSize) : - StructuralMaterialStatus(n, d, g), plasticStrainVector(), tempPlasticStrainVector(), +PlasticMaterialStatus :: PlasticMaterialStatus(GaussPoint *g, int statusSize) : + StructuralMaterialStatus(g), plasticStrainVector(), tempPlasticStrainVector(), strainSpaceHardeningVarsVector(statusSize), tempStrainSpaceHardeningVarsVector(statusSize) -{ - state_flag = temp_state_flag = PM_Elastic; - gamma = temp_gamma = 0.; -} - - -PlasticMaterialStatus :: ~PlasticMaterialStatus() -{ } +{} void -PlasticMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +PlasticMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -785,21 +750,12 @@ PlasticMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -PlasticMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +PlasticMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralMaterialStatus :: saveContext(stream, mode); - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write a raw data + contextIOResultType iores; if ( ( iores = plasticStrainVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -815,24 +771,15 @@ PlasticMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void if ( !stream.write(gamma) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -PlasticMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +PlasticMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: restoreContext(stream, mode); + contextIOResultType iores; if ( ( iores = plasticStrainVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -848,16 +795,13 @@ PlasticMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, vo if ( !stream.read(gamma) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; // return success } void PlasticMaterialStatus :: copyStateVariables(const MaterialStatus &iStatus) { StructuralMaterialStatus :: copyStateVariables(iStatus); - MaterialStatus &tmpStat = const_cast< MaterialStatus & >(iStatus); - const PlasticMaterialStatus &plastStatus = dynamic_cast< PlasticMaterialStatus & >(tmpStat); + const PlasticMaterialStatus &plastStatus = static_cast< const PlasticMaterialStatus & >(iStatus); plasticStrainVector = plastStatus.givePlasticStrainVector(); tempPlasticStrainVector = plastStatus.giveTempPlasticStrainVector(); @@ -877,9 +821,4 @@ void PlasticMaterialStatus :: addStateVariables(const MaterialStatus &iStatus) printf("Entering PlasticMaterialStatus :: copyAddVariables().\n"); } -void PlasticMaterialStatus :: printYourself() -{ - printf("I am a PlasticMaterialStatus. plasticStrainVector: \n"); - plasticStrainVector.printYourself(); -} } // end namespace oofem diff --git a/src/sm/Materials/Obsolete/plasticmaterial.h b/src/sm/Materials/Obsolete/plasticmaterial.h index cecc4bc43..82b651b05 100644 --- a/src/sm/Materials/Obsolete/plasticmaterial.h +++ b/src/sm/Materials/Obsolete/plasticmaterial.h @@ -35,11 +35,11 @@ #ifndef plasticmaterial_h #define plasticmaterial_h -#include "../sm/Materials/structuralmaterial.h" -#include "Materials/linearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/linearelasticmaterial.h" #include "floatarray.h" #include "floatmatrix.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "matstatmapperint.h" namespace oofem { @@ -61,23 +61,22 @@ class PlasticMaterialStatus : public StructuralMaterialStatus FloatArray tempStrainSpaceHardeningVarsVector; /// Yield function status indicator. - int state_flag; - int temp_state_flag; + int state_flag = PM_Elastic; + int temp_state_flag = PM_Elastic; /// Plastic consistency parameter. - double gamma, temp_gamma; + double gamma = 0., temp_gamma = 0.; public: - PlasticMaterialStatus(int n, Domain * d, GaussPoint * g, int statusSize); - virtual ~PlasticMaterialStatus(); + PlasticMaterialStatus(GaussPoint * g, int statusSize); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; const FloatArray &givePlasticStrainVector() const { return plasticStrainVector; } const FloatArray &giveTempPlasticStrainVector() const { return tempPlasticStrainVector; } @@ -97,14 +96,11 @@ class PlasticMaterialStatus : public StructuralMaterialStatus void letTempStateFlagBe(int v) { temp_state_flag = v; } - // definition - virtual const char *giveClassName() const { return "PlasticMaterialStatus"; } - - virtual void printYourself(); + const char *giveClassName() const override { return "PlasticMaterialStatus"; } /// Functions for MaterialStatusMapperInterface - virtual void copyStateVariables(const MaterialStatus &iStatus); - virtual void addStateVariables(const MaterialStatus &iStatus); + void copyStateVariables(const MaterialStatus &iStatus) override; + void addStateVariables(const MaterialStatus &iStatus) override; }; /** @@ -121,137 +117,139 @@ class PlasticMaterial : public StructuralMaterial { protected: /// Reference to bulk (undamaged) material - LinearElasticMaterial *linearElasticMaterial; + LinearElasticMaterial *linearElasticMaterial = nullptr; public: PlasticMaterial(int n, Domain * d); virtual ~PlasticMaterial(); // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 1; } - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual const char *giveClassName() const { return "PlasticMaterial"; } + bool hasMaterialModeCapability(MaterialMode mode) const override; + const char *giveClassName() const override { return "PlasticMaterial"; } /// Returns reference to undamaged (bulk) material. LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - - - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); - - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_2dBeamLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlateLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_Fiber(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - - - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; + + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<4> giveRealStressVector_PlaneStrain(const FloatArrayF<4> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<2> giveRealStressVector_2dBeamLayer(const FloatArrayF<2> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<5> giveRealStressVector_PlateLayer(const FloatArrayF<5> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<3> giveRealStressVector_Fiber(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: // add here some auxiliary functions if needed FloatArray *ComputeGradientVector(GaussPoint *gp, FloatArray *fullStressVector, - FloatArray *fullStressSpaceHardeningVars); + FloatArray *fullStressSpaceHardeningVars) const; FloatArray *ComputeResidualVector(GaussPoint *gp, double Gamma, FloatArray *plasticStrainVectorR, FloatArray *strainSpaceHardeningVariables, - FloatArray *gradientVectorR); - virtual void giveConsistentStiffnessMatrix(FloatMatrix &answer, - MatResponseMode, + FloatArray *gradientVectorR) const; + virtual FloatMatrix giveConsistentStiffnessMatrix(MatResponseMode, GaussPoint *gp, - TimeStep *tStep); + TimeStep *tStep) const; void computeConsistentModuli(FloatMatrix &answer, GaussPoint *gp, FloatMatrix &elasticModuliInverse, FloatMatrix &hardeningModuliInverse, double Gamma, const FloatArray &fullStressVector, - const FloatArray &fullStressSpaceHardeningVars); + const FloatArray &fullStressSpaceHardeningVars) const; void computeDiagModuli(FloatMatrix &answer, GaussPoint *gp, FloatMatrix &elasticModuliInverse, - FloatMatrix &hardeningModuliInverse); + FloatMatrix &hardeningModuliInverse) const; virtual FloatArray *ComputeStressSpaceHardeningVars(GaussPoint *gp, - FloatArray *strainSpaceHardeningVariables) + FloatArray *strainSpaceHardeningVariables) const { return NULL; } virtual double computeYieldValueAt(GaussPoint *gp, FloatArray *stressVector, - FloatArray *stressSpaceHardeningVars) { return 0.; } + FloatArray *stressSpaceHardeningVars) const { return 0.; } virtual void computeHardeningReducedModuli(FloatMatrix &answer, GaussPoint *gp, FloatArray *strainSpaceHardeningVariables, - TimeStep *tStep) = 0; + TimeStep *tStep) const = 0; virtual FloatArray *ComputeStressGradient(GaussPoint *gp, FloatArray *stressVector, - FloatArray *stressSpaceHardeningVars) { return NULL; } + FloatArray *stressSpaceHardeningVars) const { return NULL; } virtual FloatArray *ComputeStressSpaceHardeningVarsReducedGradient(GaussPoint *gp, FloatArray *stressVector, - FloatArray *stressSpaceHardeningVars) + FloatArray *stressSpaceHardeningVars) const { return NULL; } - virtual int hasHardening() { return 0; } + virtual int hasHardening() const { return 0; } virtual void computeReducedGradientMatrix(FloatMatrix &answer, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) = 0; + const FloatArray &stressSpaceHardeningVars) const = 0; virtual void computeTrialStressIncrement(FloatArray &answer, GaussPoint *gp, - const FloatArray &strainIncrement, TimeStep *tStep); + const FloatArray &strainIncrement, TimeStep *tStep) const; virtual void computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep); + TimeStep *tStep) const; virtual void compute3dElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep) = 0; + TimeStep *tStep) const = 0; // auxiliary functions - virtual int giveSizeOfFullHardeningVarsVector() { return 0; } + virtual int giveSizeOfFullHardeningVarsVector() const { return 0; } virtual int giveSizeOfReducedHardeningVarsVector(GaussPoint *) const { return 0; } friend class PlasticMaterialStatus; + // next functions overloaded rom structural material level + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - // next functions overloaded rom structural material level - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void give2dBeamLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void giveFiberStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatMatrixF<2,2> give2dBeamLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatMatrixF<5,5> givePlateLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatMatrixF<3,3> giveFiberStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; }; } // end namespace oofem #endif // plasticmaterial_h diff --git a/src/sm/Materials/Obsolete/rankinepm.C b/src/sm/Materials/Obsolete/rankinepm.C index 73928f5d7..d0ffe9154 100644 --- a/src/sm/Materials/Obsolete/rankinepm.C +++ b/src/sm/Materials/Obsolete/rankinepm.C @@ -33,7 +33,7 @@ */ #include "rankinepm.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "floatmatrix.h" #include "floatarray.h" #include "classfactory.h" @@ -43,36 +43,25 @@ REGISTER_Material(RankinePlasticMaterial); RankinePlasticMaterial :: RankinePlasticMaterial(int n, Domain *d) : MPlasticMaterial(n, d) { - // - // constructor - // linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); this->nsurf = 3; this->rmType = mpm_CuttingPlane; } -RankinePlasticMaterial :: ~RankinePlasticMaterial() -{ } - -IRResultType -RankinePlasticMaterial :: initializeFrom(InputRecord *ir) +void +RankinePlasticMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = MPlasticMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - result = linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) return result; + MPlasticMaterial :: initializeFrom(ir); + linearElasticMaterial->initializeFrom(ir); IR_GIVE_FIELD(ir, k, _IFT_RankinePlasticMaterial_ry); - return IRRT_OK; } double RankinePlasticMaterial :: computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) + const FloatArray &stressSpaceHardeningVars) const { FloatArray princStress(3); this->computePrincipalValues(princStress, stressVector, principal_stress); @@ -82,7 +71,7 @@ RankinePlasticMaterial :: computeYieldValueAt(GaussPoint *gp, int isurf, const F void RankinePlasticMaterial :: computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) + const FloatArray &stressSpaceHardeningVars) const { FloatArray princStress(3); FloatMatrix t(3, 3); @@ -106,7 +95,7 @@ void RankinePlasticMaterial :: computeHardeningReducedModuli(FloatMatrix &answer, GaussPoint *gp, const FloatArray &strainSpaceHardeningVariables, - TimeStep *tStep) + TimeStep *tStep) const { answer.clear(); } @@ -114,7 +103,7 @@ RankinePlasticMaterial :: computeHardeningReducedModuli(FloatMatrix &answer, void RankinePlasticMaterial :: computeStressSpaceHardeningVarsReducedGradient(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) + const FloatArray &stressSpaceHardeningVars) const { answer.clear(); } @@ -124,7 +113,7 @@ void RankinePlasticMaterial :: computeReducedGradientMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars) + const FloatArray &stressSpaceHardeningVars) const { answer.clear(); } @@ -132,7 +121,7 @@ RankinePlasticMaterial :: computeReducedGradientMatrix(FloatMatrix &answer, int void RankinePlasticMaterial :: computeStressSpaceHardeningVars(FloatArray &answer, GaussPoint *gp, - const FloatArray &strainSpaceHardeningVariables) + const FloatArray &strainSpaceHardeningVariables) const { answer.clear(); } @@ -141,6 +130,6 @@ RankinePlasticMaterial :: computeStressSpaceHardeningVars(FloatArray &answer, Ga MaterialStatus * RankinePlasticMaterial :: CreateStatus(GaussPoint *gp) const { - return new MPlasticMaterialStatus(1, this->giveDomain(), gp, this->giveSizeOfReducedHardeningVarsVector(gp)); + return new MPlasticMaterialStatus(gp, this->giveSizeOfReducedHardeningVarsVector(gp)); } } // end namespace oofem diff --git a/src/sm/Materials/Obsolete/rankinepm.h b/src/sm/Materials/Obsolete/rankinepm.h index 2b054a7de..773196c70 100644 --- a/src/sm/Materials/Obsolete/rankinepm.h +++ b/src/sm/Materials/Obsolete/rankinepm.h @@ -54,18 +54,17 @@ class RankinePlasticMaterial : public MPlasticMaterial { protected: /// Yield value. - double k; + double k = 0.; public: RankinePlasticMaterial(int n, Domain * d); - virtual ~RankinePlasticMaterial(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveInputRecordName() const { return _IFT_RankinePlasticMaterial_Name; } - virtual const char *giveClassName() const { return "RankinePlasticMaterial"; } + const char *giveInputRecordName() const override { return _IFT_RankinePlasticMaterial_Name; } + const char *giveClassName() const override { return "RankinePlasticMaterial"; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: @@ -74,25 +73,25 @@ class RankinePlasticMaterial : public MPlasticMaterial // double computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars); + const FloatArray &stressSpaceHardeningVars) const override; void computeHardeningReducedModuli(FloatMatrix &answer, GaussPoint *gp, const FloatArray &strainSpaceHardeningVariables, - TimeStep *tStep); + TimeStep *tStep) const override; void computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars); + const FloatArray &stressSpaceHardeningVars) const override; void computeStressSpaceHardeningVarsReducedGradient(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars); - int hasHardening() { return 0; } + const FloatArray &stressSpaceHardeningVars) const override; + int hasHardening() const override { return 0; } void computeReducedGradientMatrix(FloatMatrix &answer, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &stressSpaceHardeningVars); + const FloatArray &stressSpaceHardeningVars) const override; void computeStressSpaceHardeningVars(FloatArray &answer, GaussPoint *gp, - const FloatArray &strainSpaceHardeningVariables); + const FloatArray &strainSpaceHardeningVariables) const override; }; } // end namespace oofem #endif // rankinepm_h diff --git a/src/sm/Materials/Obsolete/steel1.C b/src/sm/Materials/Obsolete/steel1.C index 32658c86b..ab1716b8f 100644 --- a/src/sm/Materials/Obsolete/steel1.C +++ b/src/sm/Materials/Obsolete/steel1.C @@ -33,7 +33,7 @@ */ #include "steel1.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "mathfem.h" #include "classfactory.h" @@ -41,7 +41,6 @@ namespace oofem { REGISTER_Material(Steel1); Steel1 :: Steel1(int n, Domain *d) : PerfectlyPlasticMaterial(n, d) - // constructor { linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); } @@ -173,15 +172,13 @@ Steel1 :: GiveLCPlasticStrainGradient(GaussPoint *gp, } -IRResultType -Steel1 :: initializeFrom(InputRecord *ir) +void +Steel1 :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - double value; + PerfectlyPlasticMaterial :: initializeFrom(ir); + double value; IR_GIVE_FIELD(ir, value, _IFT_Steel1_ry); propertyDictionary.add( 'k', value / sqrt(3.) ); - - return PerfectlyPlasticMaterial :: initializeFrom(ir); } } // end namespace oofem diff --git a/src/sm/Materials/Obsolete/steel1.h b/src/sm/Materials/Obsolete/steel1.h index 85f636c89..620f6c01f 100644 --- a/src/sm/Materials/Obsolete/steel1.h +++ b/src/sm/Materials/Obsolete/steel1.h @@ -36,7 +36,7 @@ #define steel1_h #include "perfectlyplasticmaterial.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" ///@name Input fields for Steel1 //@{ @@ -54,25 +54,24 @@ class Steel1 : public PerfectlyPlasticMaterial { public: Steel1(int n, Domain * d); - virtual ~Steel1() { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveInputRecordName() const { return _IFT_Steel1_Name; } - virtual const char *giveClassName() const { return "Steel1MaterialClass"; } - virtual void updateIfFailure(GaussPoint *gp, FloatArray *, FloatArray *) { } - virtual int hasCastingTimeSupport() { return 1.; } + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_Steel1_Name; } + const char *giveClassName() const override { return "Steel1MaterialClass"; } + void updateIfFailure(GaussPoint *gp, FloatArray *, FloatArray *) override { } + bool hasCastingTimeSupport() const override { return true; } protected: // // yield(YC-like functions) and loading(LC-like functions) criteria specific section // - virtual double computeYCValueAt(GaussPoint *, FloatArray *, FloatArray *); - virtual FloatArray *GiveYCStressGradient(GaussPoint *, FloatArray *, FloatArray *); - virtual FloatArray *GiveLCStressGradient(GaussPoint *, FloatArray *, FloatArray *); - virtual FloatArray *GiveYCPlasticStrainGradient(GaussPoint *, FloatArray *, FloatArray *); - virtual FloatArray *GiveLCPlasticStrainGradient(GaussPoint *, FloatArray *, FloatArray *); - virtual void updateTempYC(GaussPoint *, FloatArray *, FloatArray *) { } - virtual void updateTempLC(GaussPoint *, FloatArray *, FloatArray *) { } + double computeYCValueAt(GaussPoint *, FloatArray *, FloatArray *) override; + FloatArray *GiveYCStressGradient(GaussPoint *, FloatArray *, FloatArray *) override; + FloatArray *GiveLCStressGradient(GaussPoint *, FloatArray *, FloatArray *) override; + FloatArray *GiveYCPlasticStrainGradient(GaussPoint *, FloatArray *, FloatArray *) override; + FloatArray *GiveLCPlasticStrainGradient(GaussPoint *, FloatArray *, FloatArray *) override; + void updateTempYC(GaussPoint *, FloatArray *, FloatArray *) override { } + void updateTempLC(GaussPoint *, FloatArray *, FloatArray *) override { } // update during computation // auxiliary function diff --git a/src/sm/Materials/RheoChainMaterials/b3mat.C b/src/sm/Materials/RheoChainMaterials/b3mat.C index f66b98c52..61c527053 100644 --- a/src/sm/Materials/RheoChainMaterials/b3mat.C +++ b/src/sm/Materials/RheoChainMaterials/b3mat.C @@ -42,31 +42,28 @@ namespace oofem { REGISTER_Material(B3Material); -IRResultType -B3Material :: initializeFrom(InputRecord *ir) +void +B3Material :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = MaxwellChainMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + MaxwellChainMaterial :: initializeFrom(ir); // // NOTE // // this material model is unit dependent! - // units must be in Mpa, m, MN. + // units must be in MPa, m, MN. // // double fc = 0.0, c = 0.0, wc = 0.0, ac = 0.0, alpha1 = 0.0, alpha2 = 0.0; int mode = 0; IR_GIVE_OPTIONAL_FIELD(ir, mode, _IFT_B3Material_mode); + IR_GIVE_FIELD(ir, t0, _IFT_B3Material_t0); // age when drying begins (in days) + IR_GIVE_FIELD(ir, fc, _IFT_B3Material_fc); // 28-day standard mean cylinder compression strength in MPa //needed for E28 if ( mode == 0 ) { // default, determine raw params q1,..,q5 from composition - IR_GIVE_FIELD(ir, fc, _IFT_B3Material_fc); // 28-day standard cylinder compression strength in MPa IR_GIVE_FIELD(ir, c, _IFT_B3Material_cc); // cement content of concrete in kg m^-3. IR_GIVE_FIELD(ir, wc, _IFT_B3Material_wc); // ratio (by weight) of water to cementitious material IR_GIVE_FIELD(ir, ac, _IFT_B3Material_ac); // ratio (by weight) of aggregate to cement - IR_GIVE_FIELD(ir, t0, _IFT_B3Material_t0); // age when drying begins (in days) } else { // read raw Basic creep parameters IR_GIVE_FIELD(ir, q1, _IFT_B3Material_q1); IR_GIVE_FIELD(ir, q2, _IFT_B3Material_q2); @@ -118,8 +115,6 @@ B3Material :: initializeFrom(InputRecord *ir) if ( mode == 0 ) { this->predictParametersFrom(fc, c, wc, ac, t0, alpha1, alpha2); } - - return IRRT_OK; } void @@ -177,56 +172,55 @@ B3Material :: predictParametersFrom(double fc, double c, double wc, double ac, q5 = 7.57e5 * ( 1. / fc ) * pow(EpsSinf, -0.6); - OOFEM_LOG_DEBUG("B3mat[%d]: estimated params: q1=%lf q2=%lf q3=%lf q4=%lf q5=%lf kt=%lf EpsSinf=%lf\n", + OOFEM_LOG_DEBUG("B3mat[%d]: estimated params: q1 %lf q2 %lf q3 %lf q4 %lf q5 %lf kt %lf EpsSinf %lf\n", this->number, q1, q2, q3, q4, q5, kt, EpsSinf); } else { - OOFEM_LOG_DEBUG("B3mat[%d]: estimated params: q1=%lf q2=%lf q3=%lf q4=%lf\n", + OOFEM_LOG_DEBUG("B3mat[%d]: estimated params: q1 %lf q2 %lf q3 %lf q4 %lf\n", this->number, q1, q2, q3, q4); } } double -B3Material :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) +B3Material :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const { // computes the value of creep function at time t // when load is acting from time t_prime // t-t_prime = duration of loading - double Qf, Z, r, Q, C0, TauSh, St1, St2, H1, H2, Cd; - double n, m; - - m = 0.5; - n = 0.1; + double m = 0.5; + double n = 0.1; // basic creep - Qf = 1. / ( 0.086 * pow(t_prime, 2. / 9.) + 1.21 * pow(t_prime, 4. / 9.) ); - Z = pow(t_prime, -m) * log( 1. + pow(t - t_prime, n) ); - r = 1.7 * pow(t_prime, 0.12) + 8.0; - Q = Qf * pow( ( 1. + pow( ( Qf / Z ), r ) ), -1. / r ); - - C0 = q2 * Q + q3 *log( 1. + pow ( t - t_prime, n ) ) + q4 *log(t / t_prime); + double Qf = 1. / ( 0.086 * pow(t_prime, 2. / 9.) + 1.21 * pow(t_prime, 4. / 9.) ); + double Z = pow(t_prime, -m) * log( 1. + pow(t - t_prime, n) ); + double r = 1.7 * pow(t_prime, 0.12) + 8.0; + double Q = Qf * pow( ( 1. + pow( ( Qf / Z ), r ) ), -1. / r ); + double C0 = q2 * Q + q3 *log( 1. + pow ( t - t_prime, n ) ) + q4 *log(t / t_prime); + double Cd; if ( this->shMode == B3_AverageShrinkage ) { // Aditional creep due to drying - TauSh = kt * pow(ks * 2.0 * vs, 2.); + double TauSh = kt * pow(ks * 2.0 * vs, 2.); + double St1; if ( ( t - t0 ) >= 0 ) { St1 = tanh( pow( ( t - t0 ) / TauSh, 1. / 2. ) ); } else { St1 = 0.0; } + double St2; if ( ( t_prime - t0 ) >= 0 ) { St2 = tanh( pow( ( t_prime - t0 ) / TauSh, 1. / 2. ) ); } else { St2 = 0.0; } - H1 = 1. - ( 1. - hum ) * St1; - H2 = 1. - ( 1. - hum ) * St2; + double H1 = 1. - ( 1. - hum ) * St1; + double H2 = 1. - ( 1. - hum ) * St2; Cd = q5 * pow( ( exp(-8.0 * H1) - exp(-8.0 * H2) ), 0.5 ); } else { Cd = 0.0; @@ -241,10 +235,8 @@ void B3Material :: giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, - ValueModeType mode) + ValueModeType mode) const { - FloatArray prevAnswer; - if ( this->shMode == B3_NoShrinkage ) { answer.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); answer.zero(); @@ -259,6 +251,7 @@ B3Material :: giveShrinkageStrainVector(FloatArray &answer, this->computeTotalAverageShrinkageStrainVector(answer, gp, tStep); if ( ( mode == VM_Incremental ) && ( !tStep->isTheFirstStep() ) ) { + FloatArray prevAnswer; this->computeTotalAverageShrinkageStrainVector( prevAnswer, gp, tStep->givePreviousStep() ); answer.subtract(prevAnswer); } @@ -268,15 +261,13 @@ B3Material :: giveShrinkageStrainVector(FloatArray &answer, } void -B3Material :: computeTotalAverageShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +B3Material :: computeTotalAverageShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const { /* * returns average shrinkage strain vector of cross-section at drying */ - double TauSh, St, kh, help, E607, Et0Tau, EpsShInf, EpsSh; - double time = relMatAge + tStep->giveTargetTime() / timeFactor; + double time = this->relMatAge - this->castingTime + tStep->giveTargetTime() / timeFactor; int size; - FloatArray fullAnswer; MaterialMode mode = gp->giveMaterialMode(); if ( ( mode == _3dShell ) || ( mode == _3dBeam ) || ( mode == _2dPlate ) || ( mode == _2dBeam ) ) { @@ -285,30 +276,36 @@ B3Material :: computeTotalAverageShrinkageStrainVector(FloatArray &answer, Gauss size = 6; } - fullAnswer.resize(size); - fullAnswer.zero(); + FloatArray fullAnswer(size); // size dependence - TauSh = kt * pow(ks * 2.0 * vs, 2.); - // time curve - St = tanh( pow( ( time - t0 ) / TauSh, 1. / 2. ) ); + double TauSh = kt * pow(ks * 2.0 * vs, 2.); + // time curve, check if before t0 + double St; + if (time > t0) { + St = tanh( pow( ( time - t0 ) / TauSh, 1. / 2. ) ); + } else { + St = 0.; + } + // humidity dependence + double kh; if ( hum <= 0.98 ) { kh = 1. - pow(hum, 3); } else if ( hum == 1 ) { kh = -0.2; // swelling in water } else { // linear interpolation for 0.98 <= h <= 1. - help = 1. - pow(hum, 3); + double help = 1. - pow(hum, 3); kh = help + ( -0.2 - help ) / ( 1. - 0.98 ) * ( hum - 0.98 ); } // time dependence of ultimate shrinkage - E607 = E28 * pow(607 / ( 4. + 0.85 * 607 ), 0.5); - Et0Tau = E28 * pow( ( t0 + TauSh ) / ( 4. + 0.85 * ( t0 + TauSh ) ), 0.5 ); - EpsShInf = EpsSinf * E607 / Et0Tau; + double E607 = E28 * pow(607 / ( 4. + 0.85 * 607 ), 0.5); + double Et0Tau = E28 * pow( ( t0 + TauSh ) / ( 4. + 0.85 * ( t0 + TauSh ) ), 0.5 ); + double EpsShInf = EpsSinf * E607 / Et0Tau; // mean shrinkage in the cross section: - EpsSh = -EpsShInf * kh * St; + double EpsSh = -EpsShInf * kh * St; fullAnswer.at(1) = fullAnswer.at(2) = fullAnswer.at(3) = EpsSh * 1.e-6; @@ -316,19 +313,18 @@ B3Material :: computeTotalAverageShrinkageStrainVector(FloatArray &answer, Gauss } void -B3Material :: computeShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +B3Material :: computeShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const { // additional material parameters required: // es0 - final shrinkage at material point // r - coefficient // rprime - coefficient // at - coeff relating stress-induced thermal strain and shrinkage - double sv, sn, et0, et, wrate = 0.0, trate = 0.0, h1; - double time = relMatAge + tStep->giveTargetTime() / timeFactor; - int err, tflag = 0, wflag = 0; + double wrate = 0.0, trate = 0.0; + double time = this->relMatAge - this->castingTime + tStep->giveTargetTime() / timeFactor; + int tflag = 0, wflag = 0; MaxwellChainMaterialStatus *status = static_cast< MaxwellChainMaterialStatus * >( this->giveStatus(gp) ); int size; - FloatArray fullAnswer; MaterialMode mmode = gp->giveMaterialMode(); if ( ( mmode == _3dShell ) || ( mmode == _3dBeam ) || ( mmode == _2dPlate ) || ( mmode == _2dBeam ) ) { @@ -337,9 +333,7 @@ B3Material :: computeShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, T size = 6; } - fullAnswer.resize(size); - fullAnswer.zero(); - + FloatArray fullAnswer(size); /* ask for humidity and temperature from external sources, if provided */ FieldManager *fm = domain->giveEngngModel()->giveContext()->giveFieldManager(); @@ -349,6 +343,7 @@ B3Material :: computeShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, T if ( ( tf = fm->giveField(FT_Temperature) ) ) { // temperature field registered gp->giveElement()->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); + int err; if ( ( err = tf->evaluateAt(et2, gcoords, VM_Incremental, tStep) ) ) { OOFEM_ERROR("tf->evaluateAt failed, error value %d", err); } @@ -360,6 +355,7 @@ B3Material :: computeShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, T if ( ( tf = fm->giveField(FT_HumidityConcentration) ) ) { // temperature field registered gp->giveElement()->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); + int err; if ( ( err = tf->evaluateAt(et2, gcoords, VM_Total, tStep) ) ) { OOFEM_ERROR("tf->evaluateAt failed, error value %d", err); } @@ -380,7 +376,7 @@ B3Material :: computeShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, T // if ( status->giveStressVector().giveSize() ) { // stressVector = status->giveStressVector(); if ( status->giveViscoelasticStressVector().giveSize() ) { - stressVector = status->giveViscoelasticStressVector(); + stressVector = status->giveViscoelasticStressVector(); } else { stressVector.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); stressVector.zero(); @@ -388,16 +384,16 @@ B3Material :: computeShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, T StructuralMaterial :: giveFullSymVectorForm( fullStressVector, stressVector, gp->giveMaterialMode() ); // compute volumetric stress - sv = 0.0; + double sv = 0.0; for ( int i = 1; i <= 3; i++ ) { sv += stressVector.at(i); } - et = 1. / this->computeCreepFunction(time + 0.01, time, gp, tStep); - et0 = 1. / this->computeCreepFunction(t0 + 0.01, t0, gp, tStep); + double et = 1. / this->computeCreepFunction(time + 0.01, time, gp, tStep); + double et0 = 1. / this->computeCreepFunction(t0 + 0.01, t0, gp, tStep); - h1 = es0 * ( et0 / et ); - sn = sgn(wrate + at * trate); + double h1 = es0 * ( et0 / et ); + double sn = sgn(wrate + at * trate); // compute increment of shrinkage strain fullAnswer.at(1) = h1 * ( 1.0 + sn * ( r * fullStressVector.at(1) + rprime * sv ) ) * ( wrate + at * trate ); fullAnswer.at(2) = h1 * ( 1.0 + sn * ( r * fullStressVector.at(2) + rprime * sv ) ) * ( wrate + at * trate ); @@ -429,14 +425,11 @@ B3Material :: computeShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, T } double -B3Material :: inverse_sorption_isotherm(double w) +B3Material :: inverse_sorption_isotherm(double w) const { - // phi ... relative humidity // w_h, n, a ... constants obtained from experiments - double phi; - // relative humidity - phi = exp( a * ( 1.0 - pow( ( w_h / w ), ( n ) ) ) ); + double phi = exp( a * ( 1.0 - pow( ( w_h / w ), ( n ) ) ) ); if ( ( phi < 0.2 ) || ( phi > 0.98 ) ) { OOFEM_ERROR("Relative humidity h = %e (w=%e) is out of range", phi, w); diff --git a/src/sm/Materials/RheoChainMaterials/b3mat.h b/src/sm/Materials/RheoChainMaterials/b3mat.h index d58f22d57..032740591 100644 --- a/src/sm/Materials/RheoChainMaterials/b3mat.h +++ b/src/sm/Materials/RheoChainMaterials/b3mat.h @@ -75,45 +75,42 @@ namespace oofem { class B3Material : public MaxwellChainMaterial { protected: - double t0; ///< Age when drying begins (in days) + double t0 = 0.; ///< Age when drying begins (in days) - double w, E28; - double q1, q2, q3, q4, q5; // predicted data - enum b3ShModeType { B3_NoShrinkage, B3_AverageShrinkage, B3_PointShrinkage } shMode; + double w = 0., E28 = 0.; + double q1 = 0., q2 = 0., q3 = 0., q4 = 0., q5 = 0.; // predicted data + enum b3ShModeType { B3_NoShrinkage, B3_AverageShrinkage, B3_PointShrinkage } shMode = B3_NoShrinkage; ///@name Additional parameters for average cross section shrinkage. //@{ - double EpsSinf, kt, ks, vs, hum; + double EpsSinf = 0., kt = 0., ks = 0., vs = 0., hum = 0.; //@} ///@name Additional parameters for free shrinkage at material point. //@{ - double es0, r, rprime, at; + double es0 = 0., r = 0., rprime = 0., at = 0.; //@} ///@name Additional parameters for absorption isotherm (used to compute relative humidity from water content) //@{ - double w_h; ///< Constant water content (obtained from experiments) w_h [Pedersen, 1990] - double n; ///< Constant-exponent (obtained from experiments) n [Pedersen, 1990] - double a; ///< Constant (obtained from experiments) A [Pedersen, 1990] + double w_h = 0.; ///< Constant water content (obtained from experiments) w_h [Pedersen, 1990] + double n = 0.; ///< Constant-exponent (obtained from experiments) n [Pedersen, 1990] + double a = 0.; ///< Constant (obtained from experiments) A [Pedersen, 1990] //@} public: - B3Material(int n, Domain *d) : MaxwellChainMaterial(n, d) { - shMode = B3_NoShrinkage; - } - virtual ~B3Material() { } + B3Material(int n, Domain *d) : MaxwellChainMaterial(n, d) {} - virtual void giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + void giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; - virtual const char *giveClassName() const { return "B3Material"; } - virtual const char *giveInputRecordName() const { return _IFT_B3Material_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "B3Material"; } + const char *giveInputRecordName() const override { return _IFT_B3Material_Name; } + void initializeFrom(InputRecord &ir) override; - virtual double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep); + double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const override; protected: - virtual int hasIncrementalShrinkageFormulation() { return 1; } + bool hasIncrementalShrinkageFormulation() const override { return true; } - virtual void computeTotalAverageShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + virtual void computeTotalAverageShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const; /// Free shrinkage at material point, requires staggered analysis. - virtual void computeShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + virtual void computeShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const; void predictParametersFrom(double, double, double, double, double, double, double); /** @@ -123,7 +120,7 @@ class B3Material : public MaxwellChainMaterial * PhD-thesis, Technical University of Denmark, Lingby. * @param w Water content (kg/kg). */ - double inverse_sorption_isotherm(double w); + double inverse_sorption_isotherm(double w) const; }; } // end namespace oofem #endif // b3mat_h diff --git a/src/sm/Materials/RheoChainMaterials/b3solidmat.C b/src/sm/Materials/RheoChainMaterials/b3solidmat.C index 8db765188..9cf4e3caa 100644 --- a/src/sm/Materials/RheoChainMaterials/b3solidmat.C +++ b/src/sm/Materials/RheoChainMaterials/b3solidmat.C @@ -45,10 +45,11 @@ namespace oofem { REGISTER_Material(B3SolidMaterial); -IRResultType -B3SolidMaterial :: initializeFrom(InputRecord *ir) +void +B3SolidMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + // ph!!! + //KelvinChainMaterial :: initializeFrom(ir); // // NOTE @@ -100,7 +101,8 @@ B3SolidMaterial :: initializeFrom(InputRecord *ir) // constant c1 (=C1*R*T/M) IR_GIVE_FIELD(ir, c1, _IFT_B3SolidMaterial_c1); // t0- necessary for the initial value of microprestress = S0 (age when drying begins) - IR_GIVE_FIELD(ir, t0, _IFT_B3Material_t0); + // IR_GIVE_FIELD(ir, t0, _IFT_B3Material_t0); + this->tS0 = this->relMatAge; // microprestress-sol-theory: read data for inverse desorption isotherm IR_GIVE_FIELD(ir, w_h, _IFT_B3Material_wh); @@ -116,8 +118,7 @@ B3SolidMaterial :: initializeFrom(InputRecord *ir) if ( this->shMode == B3_PointShrinkage ) { // #2 in enumerator if ( this->MicroPrestress == 0 ) { - OOFEM_WARNING("to use B3_PointShrinkageMPS - MicroPrestress must be = 1"); //or else no external fiels would be found - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_B3SolidMaterial_microprestress, "to use B3_PointShrinkageMPS - MicroPrestress must be = 1"); //or else no external fiels would be found } kSh = -1; @@ -130,16 +131,18 @@ B3SolidMaterial :: initializeFrom(InputRecord *ir) // either kSh or initHum and finalHum must be given in input record if ( !( ( this->kSh != -1 ) || ( ( initHum != -1 ) && ( finalHum != -1 ) ) ) ) { - OOFEM_WARNING("either kSh or initHum and finalHum must be given in input record"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, "none", "either kSh or initHum and finalHum must be given in input record"); } - if ( ( ( initHum < 0.2 ) || ( initHum > 0.98 ) || ( finalHum < 0.2 ) || ( finalHum > 0.98 ) ) && ( this->kSh == -1 ) ) { - OOFEM_ERROR("initital humidity or final humidity out of range (0.2 - 0.98)"); + if ( ( initHum < 0.2 || initHum > 0.98 ) && this->kSh == -1 ) { + throw ValueInputException(ir, _IFT_B3SolidMaterial_initialhumidity, "initital humidity out of range (0.2 - 0.98)"); + } + if ( ( finalHum < 0.2 || finalHum > 0.98 ) && this->kSh == -1 ) { + throw ValueInputException(ir, _IFT_B3SolidMaterial_finalhumidity, "final humidity out of range (0.2 - 0.98)"); } - if ( this->kSh == -1 ) { // predict kSh from composition + if ( this->kSh == -1 ) { // predict kSh from composition IR_GIVE_OPTIONAL_FIELD(ir, alpha1, _IFT_B3Material_alpha1); // influence of cement type IR_GIVE_OPTIONAL_FIELD(ir, alpha2, _IFT_B3Material_alpha2); // influence of curing type this->kSh = alpha1 * alpha2 * ( 1 - pow(finalHum, 3.) ) * ( 0.019 * pow(wc * c, 2.1) * pow(fc, -0.28) + 270 ) * 1.e-6 / fabs(initHum - finalHum); @@ -175,10 +178,6 @@ B3SolidMaterial :: initializeFrom(InputRecord *ir) if ( mode == 0 ) { this->predictParametersFrom(fc, c, wc, ac, t0, alpha1, alpha2); } - - // ph!!! - //return KelvinChainMaterial :: initializeFrom(ir); - return IRRT_OK; } void @@ -241,7 +240,7 @@ B3SolidMaterial :: predictParametersFrom(double fc, double c, double wc, double double -B3SolidMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) +B3SolidMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) const { /* * This function returns the incremental modulus for the given time increment. @@ -254,15 +253,13 @@ B3SolidMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) // !!! chartime exponents are assumed to be equal to 1 !!! - double v, eta; - double t_halfstep; double chainStiffness = 0.; - v = computeSolidifiedVolume(tStep); - eta = this->computeFlowTermViscosity(gp, tStep); //evaluated in the middle of the time-step + double v = computeSolidifiedVolume(tStep); + double eta = this->computeFlowTermViscosity(gp, tStep); //evaluated in the middle of the time-step ///@todo THREAD UNSAFE! - t_halfstep = relMatAge + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor; + double t_halfstep = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor; this->updateEparModuli( t_halfstep, gp, tStep ); if ( this->EmoduliMode == 0 ) { //retardation spectrum used @@ -271,8 +268,8 @@ B3SolidMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) sum = 1. / KelvinChainMaterial :: giveEModulus(gp, tStep); // add compliance of non-aging spring sum += 1. / EspringVal; - // convert to stiffness - chainStiffness = 1. / sum; + // convert to stiffness + chainStiffness = 1. / sum; } else { //least-squares method used chainStiffness = KelvinChainMaterial :: giveEModulus(gp, tStep); @@ -283,15 +280,15 @@ B3SolidMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) void -B3SolidMaterial :: updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *tStep) +B3SolidMaterial :: updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *tStep) const { /* * Since the elastic moduli are constant in time it is necessary to update them only once * on the beginning of the computation */ - if (this->EparVal.isEmpty()) { - RheoChainMaterial :: updateEparModuli(tPrime, gp, tStep); - } + if ( this->EparVal.isEmpty() ) { + RheoChainMaterial :: updateEparModuli(tPrime, gp, tStep); + } } void @@ -341,8 +338,8 @@ B3SolidMaterial :: computeCharTimes() } -void -B3SolidMaterial :: computeCharCoefficients(FloatArray &answer, double tPrime, GaussPoint *gp, TimeStep *tStep) +FloatArray +B3SolidMaterial :: computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const { /* * If EmoduliMode == 0 then analysis of continuous retardation spectrum is used for @@ -350,51 +347,43 @@ B3SolidMaterial :: computeCharCoefficients(FloatArray &answer, double tPrime, Ga * Else least-squares method is used */ if ( this->EmoduliMode == 0 ) { - - int mu; - double tau0, tauMu; + // constant "n" is assumed to be equal to 0.1 (typical value) - // constant "n" is assumed to be equal to 0.1 (typical value) - - // modulus of elasticity of the first unit of Kelvin chain. - // (aging elastic spring with retardation time = 0) - double lambda0ToPowN = pow(lambda0, 0.1); - tau0 = pow(2 * this->giveCharTime(1) / sqrt(10.0), 0.1); - EspringVal = 1. / ( q2 * log(1.0 + tau0 / lambda0ToPowN) - q2 * tau0 / ( 10.0 * lambda0ToPowN + 10.0 * tau0 ) ); - - // evaluation of moduli of elasticity for the remaining units - // (Solidifying kelvin units with retardation times tauMu) - answer.resize(nUnits); - answer.zero(); - for ( mu = 1; mu <= this->nUnits; mu++ ) { - tauMu = pow(2 * this->giveCharTime(mu), 0.1); - answer.at(mu) = 10. * pow(1 + tauMu / lambda0ToPowN, 2) / ( log(10.0) * q2 * ( tauMu / lambda0ToPowN ) * ( 0.9 + tauMu / lambda0ToPowN ) ); - this->charTimes.at(mu) *= 1.35; - } + // modulus of elasticity of the first unit of Kelvin chain. + // (aging elastic spring with retardation time = 0) + double lambda0ToPowN = pow(lambda0, 0.1); + double tau0 = pow(2 * this->giveCharTime(1) / sqrt(10.0), 0.1); + this->EspringVal = 1. / ( q2 * log(1.0 + tau0 / lambda0ToPowN) - q2 * tau0 / ( 10.0 * lambda0ToPowN + 10.0 * tau0 ) ); + + // evaluation of moduli of elasticity for the remaining units + // (Solidifying kelvin units with retardation times tauMu) + FloatArray answer(nUnits); + for ( int mu = 1; mu <= this->nUnits; mu++ ) { + double tauMu = pow(2 * this->giveCharTime(mu), 0.1); + answer.at(mu) = 10. * pow(1 + tauMu / lambda0ToPowN, 2) / ( log(10.0) * q2 * ( tauMu / lambda0ToPowN ) * ( 0.9 + tauMu / lambda0ToPowN ) ); + this->charTimes.at(mu) *= 1.35; + } - answer.at(nUnits) /= 1.2; // modulus of the last unit is reduced + answer.at(nUnits) /= 1.2; // modulus of the last unit is reduced + return answer; } else { // moduli computed using the least-squares method - KelvinChainMaterial :: computeCharCoefficients(answer, tPrime, gp, tStep); + return KelvinChainMaterial :: computeCharCoefficients(tPrime, gp, tStep); } } double -B3SolidMaterial :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) +B3SolidMaterial :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const // compute the value of the creep function of the non-aging solidifying constituent // corresponding to the given load duration (in days) // t-t_prime = duration of loading { - double Phi; //return value //double lambda0 = 1.0; // standard value [day] double n = 0.1; // standard value - - Phi = q2 * log( 1 + pow( (t-t_prime) / lambda0, n) ); - - return Phi; + return q2 * log( 1 + pow( (t-t_prime) / lambda0, n) ); } @@ -402,7 +391,7 @@ void B3SolidMaterial :: giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, - ValueModeType mode) + ValueModeType mode) const { FloatArray prevAnswer; @@ -429,14 +418,14 @@ B3SolidMaterial :: giveShrinkageStrainVector(FloatArray &answer, } void -B3SolidMaterial :: computeTotalAverageShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +B3SolidMaterial :: computeTotalAverageShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const { /* * returns average shrinkage strain vector of cross section at drying */ double TauSh, St, kh, help, E607, Et0Tau, EpsShInf, EpsSh; - double time = relMatAge + tStep->giveTargetTime() / timeFactor; + double time = this->relMatAge - this->castingTime + tStep->giveTargetTime() / timeFactor; int size; FloatArray fullAnswer; MaterialMode mode = gp->giveMaterialMode(); @@ -480,7 +469,7 @@ B3SolidMaterial :: computeTotalAverageShrinkageStrainVector(FloatArray &answer, void -B3SolidMaterial :: computePointShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +B3SolidMaterial :: computePointShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const { /* dEpsSh/dt = kSh * dh/dt (h = humidity) * ->> EpsSh = kSh * h_difference @@ -508,7 +497,7 @@ B3SolidMaterial :: computePointShrinkageStrainVector(FloatArray &answer, GaussPo double -B3SolidMaterial :: computeSolidifiedVolume(TimeStep *tStep) +B3SolidMaterial :: computeSolidifiedVolume(TimeStep *tStep) const // compute the relative volume of the solidified material at given age (in days) { double m, alpha; @@ -520,7 +509,7 @@ B3SolidMaterial :: computeSolidifiedVolume(TimeStep *tStep) //lambda0 = 1; //[day] alpha = q3 / q2; - atAge = relMatAge + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor; + atAge = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor; v = 1 / ( alpha + pow(lambda0 / atAge, m) ); return v; @@ -528,49 +517,44 @@ B3SolidMaterial :: computeSolidifiedVolume(TimeStep *tStep) double -B3SolidMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) +B3SolidMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) const //used for evaluation of the flow term viscosity (term containing q4) { - double eta, S, tHalfStep; - if ( this->MicroPrestress == 1 ) { - S = this->computeMicroPrestress(gp, tStep, 0); //microprestress in the middle of the time-step - eta = 1. / ( q4 * c0 * S ); + double S = this->computeMicroPrestress(gp, tStep, 0); //microprestress in the middle of the time-step + return 1. / ( q4 * c0 * S ); //static_cast< B3SolidMaterialStatus* >( gp->giveMaterialStatus() )->setMPS(S); } else if ( this->MicroPrestress == 0 ) { - tHalfStep = relMatAge + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor; - eta = 1. * tHalfStep / q4; + double tHalfStep = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor; + return 1. * tHalfStep / q4; } else { OOFEM_ERROR("mode is not supported"); - eta = 0.; + return 0.; } - - return eta; } void -B3SolidMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +B3SolidMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const // // computes the strain due to creep at constant stress during the increment // (in fact, the INCREMENT of creep strain is computed for mode == VM_Incremental) // { - double v, eta; - FloatArray help, reducedAnswer, sigma; - FloatMatrix C; - KelvinChainMaterialStatus *status = static_cast< KelvinChainMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< KelvinChainMaterialStatus * >( this->giveStatus(gp) ); // !!! chartime exponents are assumed to be equal to 1 !!! if ( mode == VM_Incremental ) { - v = computeSolidifiedVolume(tStep); - eta = this->computeFlowTermViscosity(gp, tStep); //evaluated too in the middle of the time-step + double v = computeSolidifiedVolume(tStep); + double eta = this->computeFlowTermViscosity(gp, tStep); //evaluated too in the middle of the time-step - // sigma = status->giveStressVector(); //stress vector at the beginning of time-step - sigma = status->giveViscoelasticStressVector(); //stress vector at the beginning of time-step + FloatArray help, reducedAnswer; + // sigma = status->giveStressVector(); //stress vector at the beginning of time-step + auto sigma = status->giveViscoelasticStressVector(); //stress vector at the beginning of time-step + FloatMatrix C; this->giveUnitComplianceMatrix(C, gp, tStep); reducedAnswer.resize( C.giveNumberOfRows() ); - reducedAnswer.zero(); + reducedAnswer.zero(); reducedAnswer.beProductOf(C, sigma); reducedAnswer.times( tStep->giveTimeIncrement() / ( timeFactor * eta ) ); @@ -590,7 +574,7 @@ B3SolidMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, Tim double -B3SolidMaterial :: inverse_sorption_isotherm(double w) +B3SolidMaterial :: inverse_sorption_isotherm(double w) const // Function calculates relative humidity from water content (inverse relation form sorption isotherm). // Relative humidity (phi) is from range 0.2 - 0.98 !!! // sorption isotherm by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, @@ -599,10 +583,8 @@ B3SolidMaterial :: inverse_sorption_isotherm(double w) // phi ... relative humidity // w_h, n, a ... constants obtained from experiments { - double phi; - // relative humidity - phi = exp( a * ( 1.0 - pow( ( w_h / w ), ( n ) ) ) ); + double phi = exp( a * ( 1.0 - pow( ( w_h / w ), ( n ) ) ) ); /* * if ( ( phi < 0.2 ) || ( phi > 0.98 ) ) { @@ -615,7 +597,7 @@ B3SolidMaterial :: inverse_sorption_isotherm(double w) double -B3SolidMaterial :: computeMicroPrestress(GaussPoint *gp, TimeStep *tStep, int option) +B3SolidMaterial :: computeMicroPrestress(GaussPoint *gp, TimeStep *tStep, int option) const { //return 1.;//!!!!!!!!!!!!!!!!!!!!!!!!!! /* numerically solves non-linear differential equation in form: @@ -709,58 +691,49 @@ B3SolidMaterial :: computeMicroPrestress(GaussPoint *gp, TimeStep *tStep, int op double -B3SolidMaterial :: giveInitMicroPrestress() +B3SolidMaterial :: giveInitMicroPrestress() const { - double S0; - S0 = 1 / ( c0 * tS0 ); - return S0; + return 1 / ( c0 * tS0 ); } double -B3SolidMaterial :: giveHumidity(GaussPoint *gp, TimeStep *tStep) //computes humidity at given TimeStep +B3SolidMaterial :: giveHumidity(GaussPoint *gp, TimeStep *tStep) const //computes humidity at given TimeStep { - double humidity = 0.; - int err, wflag = 0; - /* ask for humidity from external sources, if provided */ FieldManager *fm = domain->giveEngngModel()->giveContext()->giveFieldManager(); FieldPtr tf; - FloatArray gcoords, et2; if ( ( tf = fm->giveField(FT_HumidityConcentration) ) ) { // humidity field registered + FloatArray gcoords, et2; + int err; gp->giveElement()->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); if ( ( err = tf->evaluateAt(et2, gcoords, VM_Total, tStep) ) ) { OOFEM_ERROR("tf->evaluateAt failed, error value %d", err); } // convert water mass to relative humidity - humidity = this->inverse_sorption_isotherm( et2.at(1) ); - wflag = 1; - } - - if ( wflag == 0 ) { + return this->inverse_sorption_isotherm( et2.at(1) ); + } else { OOFEM_ERROR("external fields not found"); + return 0.; } - return humidity; } double -B3SolidMaterial :: giveHumidityIncrement(GaussPoint *gp, TimeStep *tStep) //computes humidity increment at given TimeStep +B3SolidMaterial :: giveHumidityIncrement(GaussPoint *gp, TimeStep *tStep) const //computes humidity increment at given TimeStep { - double humIncrement = 0.; - int err, wflag = 0; - /* ask for humidity from external sources, if provided */ FieldManager *fm = domain->giveEngngModel()->giveContext()->giveFieldManager(); FieldPtr tf; - FloatArray gcoords, et2, ei2; if ( ( tf = fm->giveField(FT_HumidityConcentration) ) ) { // humidity field registered + FloatArray gcoords, et2, ei2; + int err; gp->giveElement()->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); if ( ( err = tf->evaluateAt(et2, gcoords, VM_Total, tStep) ) ) { OOFEM_ERROR("tf->evaluateAt failed, error value %d", err); @@ -771,15 +744,11 @@ B3SolidMaterial :: giveHumidityIncrement(GaussPoint *gp, TimeStep *tStep) //comp } // convert water mass to relative humidity - humIncrement = this->inverse_sorption_isotherm( et2.at(1) ) - this->inverse_sorption_isotherm( et2.at(1) - ei2.at(1) ); - wflag = 1; - } - - if ( wflag == 0 ) { + return this->inverse_sorption_isotherm( et2.at(1) ) - this->inverse_sorption_isotherm( et2.at(1) - ei2.at(1) ); + } else { OOFEM_ERROR("external fields not found"); + return 0.; } - - return humIncrement; } @@ -789,7 +758,7 @@ B3SolidMaterial :: CreateStatus(GaussPoint *gp) const * creates a new material status corresponding to this class */ { - return new B3SolidMaterialStatus(1, this->giveDomain(), gp, nUnits); + return new B3SolidMaterialStatus(gp, nUnits); } @@ -809,8 +778,8 @@ B3SolidMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, cons /********** B3SolidMaterialStatus - HUMIDITY ****************************************/ -B3SolidMaterialStatus :: B3SolidMaterialStatus(int n, Domain *d, GaussPoint *g, int nunits) : - KelvinChainMaterialStatus(n, d, g, nunits) { } +B3SolidMaterialStatus :: B3SolidMaterialStatus(GaussPoint *g, int nunits) : + KelvinChainMaterialStatus(g, nunits) { } void B3SolidMaterialStatus :: updateYourself(TimeStep *tStep) @@ -822,42 +791,23 @@ B3SolidMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -B3SolidMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// +void +B3SolidMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + KelvinChainMaterialStatus :: saveContext(stream, mode); - if ( ( iores = KelvinChainMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write microprestress value if ( !stream.write(microprestress_old) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -B3SolidMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restore the state variables from a stream -// +void +B3SolidMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = KelvinChainMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + KelvinChainMaterialStatus :: restoreContext(stream, mode); - // read microprestress value if ( !stream.read(microprestress_old) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/Materials/RheoChainMaterials/b3solidmat.h b/src/sm/Materials/RheoChainMaterials/b3solidmat.h index a6b1c7e8d..6809f6d62 100644 --- a/src/sm/Materials/RheoChainMaterials/b3solidmat.h +++ b/src/sm/Materials/RheoChainMaterials/b3solidmat.h @@ -58,23 +58,22 @@ class B3SolidMaterialStatus : public KelvinChainMaterialStatus { protected: /// Microprestresses - double microprestress_old; - double microprestress_new; + double microprestress_old = 0.; + double microprestress_new = 0.; public: - B3SolidMaterialStatus(int n, Domain *d, GaussPoint *g, int nunits); - virtual ~B3SolidMaterialStatus() { } + B3SolidMaterialStatus(GaussPoint *g, int nunits); - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; double giveMPS() const { return microprestress_old; } void setMPS(double src) { microprestress_new = src; } // definition - virtual const char *giveClassName() const { return "B3SolidMaterialStatus"; } + const char *giveClassName() const override { return "B3SolidMaterialStatus"; } }; @@ -86,88 +85,84 @@ class B3SolidMaterialStatus : public KelvinChainMaterialStatus class B3SolidMaterial : public KelvinChainMaterial { protected: - double t0; - double w, E28, q1, q2, q3, q4, q5; // predicted data + double t0 = 0.; + double w = 0., E28 = 0., q1 = 0., q2 = 0., q3 = 0., q4 = 0., q5 = 0.; // predicted data /// constant equal to one day in time units of analysis (eg. 86400 if the analysis runs in seconds) - double lambda0; + double lambda0 = 0.; - enum b3ShModeType { B3_NoShrinkage, B3_AverageShrinkage, B3_PointShrinkage } shMode; + enum b3ShModeType { B3_NoShrinkage, B3_AverageShrinkage, B3_PointShrinkage } shMode = B3_NoShrinkage; /// Additional parameters for average cross section shrinkage - double EpsSinf, kt, ks, vs, hum; + double EpsSinf = 0., kt = 0., ks = 0., vs = 0., hum = 0.; /// Additional parameters for free shrinkage at material point - double es0, r, rprime, at; + double es0 = 0., r = 0., rprime = 0., at = 0.; // Additional parameters for sorption isotherm (used to compute relative humidity from water content) - double w_h; ///< Constant water content (obtained from experiments) w_h [Pedersen, 1990] - double n; ///< Constant-exponent (obtained from experiments) n [Pedersen, 1990] - double a; ///< Constant (obtained from experiments) A [Pedersen, 1990] - double EspringVal; ///< elastic modulus of the aging spring (first member of Kelvin chain if retardation spectrum is used) + double w_h = 0.; ///< Constant water content (obtained from experiments) w_h [Pedersen, 1990] + double n = 0.; ///< Constant-exponent (obtained from experiments) n [Pedersen, 1990] + double a = 0.; ///< Constant (obtained from experiments) A [Pedersen, 1990] + mutable double EspringVal = 0.; ///< elastic modulus of the aging spring (first member of Kelvin chain if retardation spectrum is used) /** * If 0, analysis of retardation spectrum is used for evaluation of Kelvin units moduli (default). * If 1, least-squares method is used for evaluation of Kelvin units moduli. */ - int EmoduliMode; + int EmoduliMode = 0; /** * If 1, computation exploiting Microprestress solidification theory is done. * Default value is 0 = without external fields it can be used for basic creep. */ - int MicroPrestress; - double c0; ///< MPS constant c0 [MPa^-1 * day^-1] - double c1; ///< MPS constant c1 (=C1*R*T/M) - double tS0; ///< MPS tS0 - necessary for the initial value of microprestress (age when the load is applied) - double kSh; ///< MPS shrinkage parameter. Either this or inithum and finalhum must be given in input record + int MicroPrestress = 0; + double c0 = 0.; ///< MPS constant c0 [MPa^-1 * day^-1] + double c1 = 0.; ///< MPS constant c1 (=C1*R*T/M) + double tS0 = 0.; ///< MPS tS0 - necessary for the initial value of microprestress (age when the load is applied) + double kSh = 0.; ///< MPS shrinkage parameter. Either this or inithum and finalhum must be given in input record public: - B3SolidMaterial(int n, Domain *d) : KelvinChainMaterial(n, d) { - shMode = B3_NoShrinkage; - } - virtual ~B3SolidMaterial() { } + B3SolidMaterial(int n, Domain *d) : KelvinChainMaterial(n, d) {} - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); - //virtual void updateYourself(GaussPoint *gp, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; - virtual void giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + void giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; - virtual const char *giveClassName() const { return "B3SolidMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_B3SolidMaterial_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "B3SolidMaterial"; } + const char *giveInputRecordName() const override { return _IFT_B3SolidMaterial_Name; } + void initializeFrom(InputRecord &ir) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; /// Evaluation of the compliance function of the non-aging solidifying constituent. - virtual double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep); + double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const override; protected: - virtual int hasIncrementalShrinkageFormulation() { return 1; } + bool hasIncrementalShrinkageFormulation() const override { return true; } - void computeTotalAverageShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeTotalAverageShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const; /// Evaluation of the shrinkageStrainVector. Shrinkage is fully dependent on humidity rate in given GP - void computePointShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computePointShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const; void predictParametersFrom(double, double, double, double, double, double, double); /// Evaluation of the relative volume of the solidified material. - double computeSolidifiedVolume(TimeStep *tStep); + double computeSolidifiedVolume(TimeStep *tStep) const; /// Evaluation of the flow term viscosity. - double computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep); + double computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) const; - double inverse_sorption_isotherm(double w); + double inverse_sorption_isotherm(double w) const; /// Evaluation of characteristic moduli of the non-aging Kelvin chain. - virtual void computeCharCoefficients(FloatArray &answer, double tPrime, GaussPoint *gp, TimeStep *tStep); + FloatArray computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const override; /// Update of partial moduli of individual chain units - virtual void updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *tStep); + void updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *tStep) const override; - virtual void computeCharTimes(); + void computeCharTimes() override; - virtual double giveEModulus(GaussPoint *gp, TimeStep *tStep); + double giveEModulus(GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + void giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; /** * Computes microprestress at given time step and GP. @@ -176,16 +171,16 @@ class B3SolidMaterial : public KelvinChainMaterial * @param option If 0, microprestress is evaluated in the middle of the time step (used for stiffnesses). * If 1, MPS is evaluated at the end of the time step. (Used for updating). */ - double computeMicroPrestress(GaussPoint *gp, TimeStep *tStep, int option); + double computeMicroPrestress(GaussPoint *gp, TimeStep *tStep, int option) const; /// Computes initial value of the MicroPrestress - double giveInitMicroPrestress(void); + double giveInitMicroPrestress() const; /// Computes relative humidity at given time step and GP - double giveHumidity(GaussPoint *gp, TimeStep *tStep); + double giveHumidity(GaussPoint *gp, TimeStep *tStep) const; /// Computes relative humidity increment at given time step and GP - double giveHumidityIncrement(GaussPoint *gp, TimeStep *tStep); + double giveHumidityIncrement(GaussPoint *gp, TimeStep *tStep) const; }; } // end namespace oofem #endif // b3solidmat_h diff --git a/src/sm/Materials/RheoChainMaterials/cebfip78.C b/src/sm/Materials/RheoChainMaterials/cebfip78.C index 2624c4862..09a99bad4 100644 --- a/src/sm/Materials/RheoChainMaterials/cebfip78.C +++ b/src/sm/Materials/RheoChainMaterials/cebfip78.C @@ -40,10 +40,10 @@ namespace oofem { REGISTER_Material(CebFip78Material); -IRResultType -CebFip78Material :: initializeFrom(InputRecord *ir) +void +CebFip78Material :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + MaxwellChainMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, E28, _IFT_CebFip78Material_e28); IR_GIVE_FIELD(ir, fibf, _IFT_CebFip78Material_fibf); @@ -51,53 +51,46 @@ CebFip78Material :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, kap_c, _IFT_CebFip78Material_kap_c); IR_GIVE_FIELD(ir, kap_tt, _IFT_CebFip78Material_kap_tt); IR_GIVE_FIELD(ir, u, _IFT_CebFip78Material_u); - - return MaxwellChainMaterial :: initializeFrom(ir); } double -CebFip78Material :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) +CebFip78Material :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const { // computes the value of creep function at time t // when load is acting from time t_prime // t-t_prime = duration of loading - double e0; - double fi, fi0, firv, fiir, hd, alpha, beta; - double tt, t0; - - t0 = this->kap_tt * this->kap_c * t_prime; - tt = this->kap_tt * this->kap_c * t; + double t0 = this->kap_tt * this->kap_c * t_prime; + double tt = this->kap_tt * this->kap_c * t; - e0 = E28 * sqrt( 1.36 * t0 / ( t0 + 10. ) ); + double e0 = E28 * sqrt( 1.36 * t0 / ( t0 + 10. ) ); - fi0 = 0.95 * pow(t0, -0.3) - 0.1; + double fi0 = 0.95 * pow(t0, -0.3) - 0.1; if ( fi0 < 0. ) { fi0 = 0.; } - firv = 0.11 + 0.2 * atan( 0.05 * pow( ( tt - t0 ), 2. / 3. ) ); + double firv = 0.11 + 0.2 * atan( 0.05 * pow( ( tt - t0 ), 2. / 3. ) ); if ( firv < 0.4 ) { firv = 0.4; } - hd = this->kap_a_per_area * 1000. * 1000. / this->u; + double hd = this->kap_a_per_area * 1000. * 1000. / this->u; if ( hd < 50. ) { hd = 50.; } - if ( hd > 1500. ) { hd = 1500.; } - alpha = 0.078 * exp( -1.20 * log10(hd) ); - beta = 0.530 * exp( -0.13 * log10(hd) ); + double alpha = 0.078 * exp( -1.20 * log10(hd) ); + double beta = 0.530 * exp( -0.13 * log10(hd) ); - fiir = 0.25 * ( 5.4 - log10(hd) ) * ( exp( -pow(alpha * t0, beta) ) - exp( -pow(alpha * tt, beta) ) ); - fiir = fibf * fiir; + double fiir = 0.25 * ( 5.4 - log10(hd) ) * ( exp( -pow(alpha * t0, beta) ) - exp( -pow(alpha * tt, beta) ) ); + fiir *= fibf; - fi = fi0 + firv + fiir; + double fi = fi0 + firv + fiir; return ( 1. / e0 ) + fi / E28; } diff --git a/src/sm/Materials/RheoChainMaterials/cebfip78.h b/src/sm/Materials/RheoChainMaterials/cebfip78.h index 22f019945..e33748ce7 100644 --- a/src/sm/Materials/RheoChainMaterials/cebfip78.h +++ b/src/sm/Materials/RheoChainMaterials/cebfip78.h @@ -56,24 +56,21 @@ namespace oofem { class CebFip78Material : public MaxwellChainMaterial { protected: - double E28; ///< Young modulus at age of 28 days [MPa]. - double fibf; ///< Basic creep coefficient. - double kap_a_per_area; ///< Coefficient of hydrometric conditions. - double kap_c; ///< Coefficient of type of cement. - double kap_tt; ///< Coefficient of temperature effects. - double u; ///< Surface imposed to environment [mm^2]; temporary here ; should be in crosssection level. + double E28 = 0.; ///< Young modulus at age of 28 days [MPa]. + double fibf = 0.; ///< Basic creep coefficient. + double kap_a_per_area = 0.; ///< Coefficient of hydrometric conditions. + double kap_c = 0.; ///< Coefficient of type of cement. + double kap_tt = 0.; ///< Coefficient of temperature effects. + double u = 0.; ///< Surface imposed to environment [mm^2]; temporary here ; should be in crosssection level. public: CebFip78Material(int n, Domain *d) : MaxwellChainMaterial(n, d) { } - virtual ~CebFip78Material() { } - virtual const char *giveClassName() const { return "CebFip78Material"; } - virtual const char *giveInputRecordName() const { return _IFT_CebFip78Material_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "CebFip78Material"; } + const char *giveInputRecordName() const override { return _IFT_CebFip78Material_Name; } + void initializeFrom(InputRecord &ir) override; - virtual double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep); - -protected: + double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const override; }; } // end namespace oofem #endif // cebfip78_h diff --git a/src/sm/Materials/RheoChainMaterials/doublepowerlaw.C b/src/sm/Materials/RheoChainMaterials/doublepowerlaw.C index a6d5cbce7..2a3a1e0f7 100644 --- a/src/sm/Materials/RheoChainMaterials/doublepowerlaw.C +++ b/src/sm/Materials/RheoChainMaterials/doublepowerlaw.C @@ -39,37 +39,31 @@ namespace oofem { REGISTER_Material(DoublePowerLawMaterial); -IRResultType -DoublePowerLawMaterial :: initializeFrom(InputRecord *ir) +void +DoublePowerLawMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + MaxwellChainMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, E28, _IFT_DoublePowerLawMaterial_e28); IR_GIVE_FIELD(ir, fi1, _IFT_DoublePowerLawMaterial_fi1); IR_GIVE_FIELD(ir, m, _IFT_DoublePowerLawMaterial_m); IR_GIVE_FIELD(ir, n, _IFT_DoublePowerLawMaterial_n); IR_GIVE_FIELD(ir, alpha, _IFT_DoublePowerLawMaterial_alpha); - - return MaxwellChainMaterial :: initializeFrom(ir); } double -DoublePowerLawMaterial :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) +DoublePowerLawMaterial :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const { - // computes the value of creep function at time t // when load is acting from time t_prime // t-t_prime = duration of loading - double e0; - double h1, h2, h3; - - e0 = 1.50 * E28; + double e0 = 1.50 * E28; - h1 = pow(t - t_prime, n); - h2 = pow(t_prime, -m) + alpha; - h3 = fi1 / e0; + double h1 = pow(t - t_prime, n); + double h2 = pow(t_prime, -m) + alpha; + double h3 = fi1 / e0; return 1. / e0 + h1 * h2 * h3; } diff --git a/src/sm/Materials/RheoChainMaterials/doublepowerlaw.h b/src/sm/Materials/RheoChainMaterials/doublepowerlaw.h index 5ef2651a4..a88ad413c 100644 --- a/src/sm/Materials/RheoChainMaterials/doublepowerlaw.h +++ b/src/sm/Materials/RheoChainMaterials/doublepowerlaw.h @@ -54,22 +54,19 @@ namespace oofem { class DoublePowerLawMaterial : public MaxwellChainMaterial { protected: - double E28; ///< Young modulus at age of 28 days [MPa]. - double fi1; ///< Basic creep coefficient. - double m, n; - double alpha; + double E28 = 0.; ///< Young modulus at age of 28 days [MPa]. + double fi1 = 0.; ///< Basic creep coefficient. + double m = 0., n = 0.; + double alpha = 0.; public: DoublePowerLawMaterial(int n, Domain *d) : MaxwellChainMaterial(n, d) { } - virtual ~DoublePowerLawMaterial() { } - virtual const char *giveClassName() const { return "DoublePowerLawMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_DoublePowerLawMaterial_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "DoublePowerLawMaterial"; } + const char *giveInputRecordName() const override { return _IFT_DoublePowerLawMaterial_Name; } + void initializeFrom(InputRecord &ir) override; - virtual double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep); - -protected: + double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const override; }; } // end namespace oofem #endif // doublepowerlaw_h diff --git a/src/sm/Materials/RheoChainMaterials/eurocode2creep.C b/src/sm/Materials/RheoChainMaterials/eurocode2creep.C index d8dfc2edd..07f059873 100644 --- a/src/sm/Materials/RheoChainMaterials/eurocode2creep.C +++ b/src/sm/Materials/RheoChainMaterials/eurocode2creep.C @@ -44,11 +44,9 @@ namespace oofem { REGISTER_Material(Eurocode2CreepMaterial); -IRResultType -Eurocode2CreepMaterial :: initializeFrom(InputRecord *ir) +void +Eurocode2CreepMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, fcm28, _IFT_Eurocode2CreepMaterial_fcm28); /* scaling factor transforming PREDICTED stiffness Ecm @@ -61,12 +59,12 @@ Eurocode2CreepMaterial :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, h0, _IFT_Eurocode2CreepMaterial_h0); // equivalent thickness, in mm !!! this->retardationSpectrumApproximation = false; - if ( ir->hasField(_IFT_Eurocode2CreepMaterial_spectrum) ) { + if ( ir.hasField(_IFT_Eurocode2CreepMaterial_spectrum) ) { this->retardationSpectrumApproximation = true; } this->temperatureDependent = false; - if ( ir->hasField(_IFT_Eurocode2CreepMaterial_temperatureDependent) ) { + if ( ir.hasField(_IFT_Eurocode2CreepMaterial_temperatureDependent) ) { this->temperatureDependent = true; } @@ -95,8 +93,6 @@ Eurocode2CreepMaterial :: initializeFrom(InputRecord *ir) // spectrum switch is initialized here) // initialize Kelvin chain aging material KelvinChainMaterial :: initializeFrom(ir); - - return IRRT_OK; } @@ -231,7 +227,7 @@ Eurocode2CreepMaterial :: computeCreepParams(int cemType, double henv) double -Eurocode2CreepMaterial :: computeConcreteStrengthAtAge(double age) +Eurocode2CreepMaterial :: computeConcreteStrengthAtAge(double age) const { double beta = exp( this->s * ( 1. - sqrt( 28. / ( age / this->timeFactor ) ) ) ); @@ -239,7 +235,7 @@ Eurocode2CreepMaterial :: computeConcreteStrengthAtAge(double age) } double -Eurocode2CreepMaterial :: computeMeanElasticModulusAtAge(double age) +Eurocode2CreepMaterial :: computeMeanElasticModulusAtAge(double age) const { double fcm_at_age; double Ecm_at_age; @@ -251,62 +247,46 @@ Eurocode2CreepMaterial :: computeMeanElasticModulusAtAge(double age) } double -Eurocode2CreepMaterial :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) +Eurocode2CreepMaterial :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const // compute the value of the creep function of concrete // corresponding to the given load duration (in days) // t-t_prime = duration of loading { - double J; //return value - - // elastic modulus isn not temperature adjusted too - J = 1. / this->computeMeanElasticModulusAtAge(t_prime); - - J += this->computeCreepCoefficient(t, t_prime, gp, tStep) / ( 1.05 * this->Ecm28 ); - + double J = 1. / this->computeMeanElasticModulusAtAge(t_prime) + + this->computeCreepCoefficient(t, t_prime, gp, tStep) / ( 1.05 * this->Ecm28 ); return J; } double -Eurocode2CreepMaterial :: computeCreepCoefficient(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) +Eurocode2CreepMaterial :: computeCreepCoefficient(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const // compute the value of the creep coefficient // corresponding to the given load duration (in days) // t-t_prime = duration of loading { - double phi; //return value - - double beta_t0, beta_c; - double t_prime_equiv; - - if ( temperatureDependent ) { - t_prime_equiv = this->computeEquivalentAge(gp, tStep); - } else { - t_prime_equiv = t_prime; - } + double t_prime_equiv = temperatureDependent ? this->computeEquivalentAge(gp, tStep) : t_prime; // B.5 - beta_t0 = 1. / ( 0.1 + pow(t_prime_equiv / this->timeFactor, 0.2) ); + double beta_t0 = 1. / ( 0.1 + pow(t_prime_equiv / this->timeFactor, 0.2) ); // B.7 - beta_c = pow( ( ( t - t_prime ) / ( this->beta_H * this->timeFactor + t - t_prime ) ), 0.3 ); + double beta_c = pow( ( ( t - t_prime ) / ( this->beta_H * this->timeFactor + t - t_prime ) ), 0.3 ); // t-t'_prime should not be temperature-adjusted (so says the EC) // B.1 + B.2 - phi = this->phi_RH * this->beta_fcm * beta_t0 * beta_c; - - - return phi; + return this->phi_RH * this->beta_fcm * beta_t0 * beta_c; } // implements B.10 double -Eurocode2CreepMaterial :: computeEquivalentMaturity(GaussPoint *gp, TimeStep *tStep) { +Eurocode2CreepMaterial :: computeEquivalentMaturity(GaussPoint *gp, TimeStep *tStep) const +{ Eurocode2CreepMaterialStatus *status = static_cast< Eurocode2CreepMaterialStatus * >( this->giveStatus(gp) ); FloatArray et; @@ -319,7 +299,7 @@ Eurocode2CreepMaterial :: computeEquivalentMaturity(GaussPoint *gp, TimeStep *tS selem->computeResultingIPTemperatureAt(et, tStep, gp, VM_Total); - if ( tStep->isTheFirstStep() || ( tStep->giveIntrinsicTime() - tStep->giveTimeIncrement() - this->castingTime ) < 0. ) { + if ( tStep->isTheFirstStep() || ( ! Material :: isActivated( tStep->givePreviousStep() ) ) ) { initMaturity = this->relMatAge; averageTemperature = et.at(1); } else { @@ -342,23 +322,18 @@ Eurocode2CreepMaterial :: computeEquivalentMaturity(GaussPoint *gp, TimeStep *tS // implements B.9 double -Eurocode2CreepMaterial :: computeEquivalentAge(GaussPoint *gp, TimeStep *tStep) +Eurocode2CreepMaterial :: computeEquivalentAge(GaussPoint *gp, TimeStep *tStep) const { - double maturity; - double age; - - maturity = this->computeEquivalentMaturity(gp, tStep); + double maturity = this->computeEquivalentMaturity(gp, tStep); - age = maturity * pow( ( 9. / ( 2. + pow(maturity, 1.2) ) + 1. ), this->alpha_T_cement ); - age = max(age, 0.5); - - return age; + double age = maturity * pow( ( 9. / ( 2. + pow(maturity, 1.2) ) + 1. ), this->alpha_T_cement ); + return max(age, 0.5); } double -Eurocode2CreepMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) +Eurocode2CreepMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) const { /* * This function returns the incremental modulus for the given time increment. @@ -373,7 +348,7 @@ Eurocode2CreepMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) double chainStiffness = 0.; - if ( !this->isActivated(tStep) ) { + if ( !Material :: isActivated(tStep) ) { return 1.; // stresses are cancelled in giveRealStressVector; } @@ -388,7 +363,7 @@ Eurocode2CreepMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) sum += 1 / this->EspringVal; // add zeroth unit - t_halfstep = this->relMatAge + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ); + t_halfstep = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ); if ( t_halfstep <= 0. ) { OOFEM_ERROR("attempt to evaluate material stiffness at negative age"); @@ -473,7 +448,7 @@ Eurocode2CreepMaterial :: computeCharTimes() double -Eurocode2CreepMaterial :: computeRetardationTimeCorrection(int mu) +Eurocode2CreepMaterial :: computeRetardationTimeCorrection(int mu) const { return 1. + 0.555 * exp( -4. * pow( ( this->tau1 * pow( 10., double( mu - 1 ) ) / ( this->beta_H * this->timeFactor ) ), 2. ) ); @@ -483,33 +458,28 @@ Eurocode2CreepMaterial :: computeRetardationTimeCorrection(int mu) double -Eurocode2CreepMaterial :: evaluateSpectrumAt(double tau) +Eurocode2CreepMaterial :: evaluateSpectrumAt(double tau) const { // second-order approximation of the retardation spectrum - double L; - double t = 2 * tau; double n = 0.3; // exponent in the model - double f, df, ddf; // function "t/(beta+t)" and its derivatives - double ddPhi; // second derivative of (f(t))^n + // function "t/(beta+t)" and its derivatives + double f = t / ( this->beta_H * this->timeFactor + t ); - f = t / ( this->beta_H * this->timeFactor + t ); + double df = this->beta_H * this->timeFactor / ( ( this->beta_H * this->timeFactor + t ) * ( this->beta_H * this->timeFactor + t ) ); - df = this->beta_H * this->timeFactor / ( ( this->beta_H * this->timeFactor + t ) * ( this->beta_H * this->timeFactor + t ) ); + double ddf = -2. * this->beta_H * this->timeFactor / ( ( this->beta_H * this->timeFactor + t ) * ( this->beta_H * this->timeFactor + t ) * ( this->beta_H * this->timeFactor + t ) ); - ddf = -2. * this->beta_H * this->timeFactor / ( ( this->beta_H * this->timeFactor + t ) * ( this->beta_H * this->timeFactor + t ) * ( this->beta_H * this->timeFactor + t ) ); + // second derivative of (f(t))^n + double ddPhi = n * ( n - 1. ) * pow( f, ( n - 2. ) ) * df * df + n *pow( f, ( n - 1. ) ) * ddf; - ddPhi = n * ( n - 1. ) * pow( f, ( n - 2. ) ) * df * df + n *pow( f, ( n - 1. ) ) * ddf; - - L = -4. * tau * tau * ddPhi; - - return L; + return -4. * tau * tau * ddPhi; } -void -Eurocode2CreepMaterial :: computeCharCoefficients(FloatArray &answer, double atTime, GaussPoint *gp, TimeStep *tStep) +FloatArray +Eurocode2CreepMaterial :: computeCharCoefficients(double atTime, GaussPoint *gp, TimeStep *tStep) const { /* * If retardationSpectrumApproximation == true then analysis of continuous retardation spectrum is used for @@ -519,16 +489,9 @@ Eurocode2CreepMaterial :: computeCharCoefficients(FloatArray &answer, double atT if ( retardationSpectrumApproximation ) { // all moduli must be multiplied by g(t') / c - see equation (46) in Jirasek's retardation spectrum paper - double coefficient; - double equivalentAge; - - if ( temperatureDependent ) { - equivalentAge = this->computeEquivalentAge(gp, tStep); - } else { - equivalentAge = atTime; - } + const double equivalentAge = temperatureDependent ? this->computeEquivalentAge(gp, tStep) : atTime; - coefficient = 1.05 * this->Ecm28 * ( 0.1 + pow(equivalentAge / this->timeFactor, 0.2) ) / ( this->phi_RH * this->beta_fcm ); + const double coefficient = 1.05 * this->Ecm28 * ( 0.1 + pow(equivalentAge / this->timeFactor, 0.2) ) / ( this->phi_RH * this->beta_fcm ); // evaluate stiffness of the zero-th unit of the Kelvin chain @@ -536,7 +499,7 @@ Eurocode2CreepMaterial :: computeCharCoefficients(FloatArray &answer, double atT // this is done employing Simpson's rule. the begOfTimeOfInterest cannot exceed 0.1 day // E0 = EspringVal = int( L, 0, tau1/sqrt(10) ) - double tau0 = this->tau1 / sqrt(10.0); // upper bound of the integral + const double tau0 = this->tau1 / sqrt(10.0); // upper bound of the integral this->EspringVal = 1. / ( ( log(10.) / 3. ) * ( this->evaluateSpectrumAt(tau0 * 1.e-8) + 4. * this->evaluateSpectrumAt(tau0 * 1.e-7) + @@ -548,20 +511,18 @@ Eurocode2CreepMaterial :: computeCharCoefficients(FloatArray &answer, double atT this->EspringVal *= coefficient; // process remaining units - answer.resize(nUnits); - answer.zero(); - - double tauMu; + FloatArray answer(nUnits); for ( int mu = 1; mu <= this->nUnits; mu++ ) { - tauMu = this->tau1 * pow( 10., double( mu - 1 ) ); + double tauMu = this->tau1 * pow( 10., double( mu - 1 ) ); answer.at(mu) = 2. / ( log(10.) * ( this->evaluateSpectrumAt( tauMu * pow(10., -sqrt(3.) / 6.) ) + this->evaluateSpectrumAt( tauMu * pow(10., sqrt(3.) / 6.) ) ) ); } answer.times(coefficient); + return answer; } else { // moduli computed using the least-squares method - KelvinChainMaterial :: computeCharCoefficients(answer, atTime, gp, tStep); + return KelvinChainMaterial :: computeCharCoefficients(atTime, gp, tStep); } } @@ -570,7 +531,7 @@ void Eurocode2CreepMaterial :: giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, - ValueModeType mode) + ValueModeType mode) const { answer.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); answer.zero(); @@ -586,22 +547,22 @@ Eurocode2CreepMaterial :: giveShrinkageStrainVector(FloatArray &answer, FloatArray eps_sh; // the relative matereial age can be negative to properly reflect the casting time - double dryingTimeNow = ( tStep->giveTargetTime() + this->relMatAge - this->t0 ) / timeFactor; - double autoShrTimeNow = ( this->relMatAge + tStep->giveTargetTime() ) / this->timeFactor; + double dryingTimeNow = ( this->relMatAge - this->castingTime - this->t0 + tStep->giveTargetTime() ) / timeFactor; + double autoShrTimeNow = ( this->relMatAge - this->castingTime + tStep->giveTargetTime() ) / this->timeFactor; if ( mode == VM_Incremental ) { double dt = tStep->giveTimeIncrement() / this->timeFactor; if ( dryingTimeNow > 0. ) { if ( ( this->shType == EC2_TotalShrinkage ) || ( this->shType == EC2_DryingShrinkage ) ) { - this->computeIncrementOfDryingShrinkageVector(eps_sh, gp, dryingTimeNow, dryingTimeNow - dt); + this->computeIncrementOfDryingShrinkageVector(eps_sh, gp, dryingTimeNow, max(dryingTimeNow - dt, 0.)); answer.add(eps_sh); } } - if ( autoShrTimeNow > ( this->castingTime + this->relMatAge ) ) { + if ( autoShrTimeNow > 0. ) { if ( ( this->shType == EC2_TotalShrinkage ) || ( this->shType == EC2_AutogenousShrinkage ) ) { - this->computeIncrementOfAutogenousShrinkageVector(eps_sh, gp, autoShrTimeNow, autoShrTimeNow - dt); + this->computeIncrementOfAutogenousShrinkageVector(eps_sh, gp, autoShrTimeNow, max(autoShrTimeNow - dt, 0.)); answer.add(eps_sh); } } @@ -613,13 +574,9 @@ Eurocode2CreepMaterial :: giveShrinkageStrainVector(FloatArray &answer, } } - if ( autoShrTimeNow > ( this->castingTime + this->relMatAge ) ) { + if ( autoShrTimeNow > this->relMatAge ) { if ( ( this->shType == EC2_TotalShrinkage ) || ( this->shType == EC2_AutogenousShrinkage ) ) { - if (this->castingTime > 0.) { - this->computeIncrementOfAutogenousShrinkageVector(eps_sh, gp, autoShrTimeNow, (this->relMatAge+this->castingTime) / this->timeFactor); - } else { - this->computeIncrementOfAutogenousShrinkageVector(eps_sh, gp, autoShrTimeNow, (this->relMatAge) / this->timeFactor); - } + this->computeIncrementOfAutogenousShrinkageVector(eps_sh, gp, autoShrTimeNow, this->relMatAge / this->timeFactor); answer.add(eps_sh); } } @@ -631,10 +588,9 @@ Eurocode2CreepMaterial :: giveShrinkageStrainVector(FloatArray &answer, } void -Eurocode2CreepMaterial :: computeIncrementOfDryingShrinkageVector(FloatArray &answer, GaussPoint *gp, double tNow, double tThen) +Eurocode2CreepMaterial :: computeIncrementOfDryingShrinkageVector(FloatArray &answer, GaussPoint *gp, double tNow, double tThen) const { int size; - FloatArray fullAnswer; MaterialMode mode = gp->giveMaterialMode(); if ( ( mode == _3dShell ) || ( mode == _3dBeam ) || ( mode == _2dPlate ) || ( mode == _2dBeam ) ) { @@ -643,19 +599,14 @@ Eurocode2CreepMaterial :: computeIncrementOfDryingShrinkageVector(FloatArray &an size = 6; } - fullAnswer.resize(size); - fullAnswer.zero(); + FloatArray fullAnswer(size); if ( tNow > tThen ) { - double dEpsSh; - // B.10 - double beta_ds_now, beta_ds_then; - - beta_ds_now = tNow / ( tNow + 0.04 * pow(this->h0, 3. / 2.) ); - beta_ds_then = tThen / ( tThen + 0.04 * pow(this->h0, 3. / 2.) ); + double beta_ds_now = tNow / ( tNow + 0.04 * pow(this->h0, 3. / 2.) ); + double beta_ds_then = tThen / ( tThen + 0.04 * pow(this->h0, 3. / 2.) ); - dEpsSh = ( beta_ds_now - beta_ds_then ) * this->kh * this->eps_cd_0; + double dEpsSh = ( beta_ds_now - beta_ds_then ) * this->kh * this->eps_cd_0; fullAnswer.at(1) = fullAnswer.at(2) = fullAnswer.at(3) = dEpsSh; } @@ -665,10 +616,9 @@ Eurocode2CreepMaterial :: computeIncrementOfDryingShrinkageVector(FloatArray &an void -Eurocode2CreepMaterial :: computeIncrementOfAutogenousShrinkageVector(FloatArray &answer, GaussPoint *gp, double tNow, double tThen) +Eurocode2CreepMaterial :: computeIncrementOfAutogenousShrinkageVector(FloatArray &answer, GaussPoint *gp, double tNow, double tThen) const { int size; - FloatArray fullAnswer; MaterialMode mode = gp->giveMaterialMode(); if ( ( mode == _3dShell ) || ( mode == _3dBeam ) || ( mode == _2dPlate ) || ( mode == _2dBeam ) ) { @@ -677,20 +627,14 @@ Eurocode2CreepMaterial :: computeIncrementOfAutogenousShrinkageVector(FloatArray size = 6; } - fullAnswer.resize(size); - fullAnswer.zero(); - + FloatArray fullAnswer(size); if ( tNow > tThen ) { - double dEpsAu; - // B.13 - double beta_as_now, beta_as_then; - - beta_as_now = 1. - exp( -0.2 * sqrt(tNow) ); - beta_as_then = 1. - exp( -0.2 * sqrt(tThen) ); + double beta_as_now = 1. - exp( -0.2 * sqrt(tNow) ); + double beta_as_then = 1. - exp( -0.2 * sqrt(tThen) ); - dEpsAu = ( beta_as_now - beta_as_then ) * this->eps_ca_infty; + double dEpsAu = ( beta_as_now - beta_as_then ) * this->eps_ca_infty; fullAnswer.at(1) = fullAnswer.at(2) = fullAnswer.at(3) = dEpsAu; } @@ -702,7 +646,7 @@ Eurocode2CreepMaterial :: computeIncrementOfAutogenousShrinkageVector(FloatArray MaterialStatus * Eurocode2CreepMaterial :: CreateStatus(GaussPoint *gp) const { - return new Eurocode2CreepMaterialStatus(1, this->giveDomain(), gp, nUnits); + return new Eurocode2CreepMaterialStatus(gp, nUnits); } @@ -720,16 +664,6 @@ Eurocode2CreepMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *g /****************************************************************************************/ /********** Eurocode2CreepMaterialStatus - HUMIDITY ****************************************/ - -Eurocode2CreepMaterialStatus :: Eurocode2CreepMaterialStatus(int n, Domain *d, GaussPoint *g, int nunits) : - KelvinChainMaterialStatus(n, d, g, nunits) { - tempMaturity = 0.; - maturity = tempMaturity; - - tempTemperature = 0.; - temperature = tempTemperature; -} - void Eurocode2CreepMaterialStatus :: updateYourself(TimeStep *tStep) { @@ -743,53 +677,31 @@ Eurocode2CreepMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -Eurocode2CreepMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// +void +Eurocode2CreepMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + KelvinChainMaterialStatus :: saveContext(stream, mode); - if ( ( iores = KelvinChainMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write maturity value if ( !stream.write(maturity) ) { THROW_CIOERR(CIO_IOERR); } - // write temperature value if ( !stream.write(temperature) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -Eurocode2CreepMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restore the state variables from a stream -// +void +Eurocode2CreepMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = KelvinChainMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + KelvinChainMaterialStatus :: restoreContext(stream, mode); - // read maturity value if ( !stream.read(maturity) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } - // read temperature value if ( !stream.read(temperature) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } - - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/Materials/RheoChainMaterials/eurocode2creep.h b/src/sm/Materials/RheoChainMaterials/eurocode2creep.h index 6433744ef..a9f6bd0fd 100644 --- a/src/sm/Materials/RheoChainMaterials/eurocode2creep.h +++ b/src/sm/Materials/RheoChainMaterials/eurocode2creep.h @@ -59,22 +59,21 @@ class Eurocode2CreepMaterialStatus : public KelvinChainMaterialStatus { protected: /// temperature-dependent equivalent age, maturity (equilibrated value) - double maturity; + double maturity = 0.; /// temperature-dependent equivalent age, maturity (temporary value) - double tempMaturity; + double tempMaturity = 0.; /// temperature (equilibrated value) - double temperature; + double temperature = 0.; /// temperature (temporary value) - double tempTemperature; + double tempTemperature = 0.; public: - Eurocode2CreepMaterialStatus(int n, Domain *d, GaussPoint *g, int nunits); - virtual ~Eurocode2CreepMaterialStatus() { } + Eurocode2CreepMaterialStatus(GaussPoint *g, int nunits): KelvinChainMaterialStatus(g, nunits) {} - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; double giveConcreteMaturity() const { return maturity; } void setTempConcreteMaturity(double src) { tempMaturity = src; } @@ -84,7 +83,7 @@ class Eurocode2CreepMaterialStatus : public KelvinChainMaterialStatus // definition - virtual const char *giveClassName() const { return "Eurocode2CreepMaterialStatus"; } + const char *giveClassName() const override { return "Eurocode2CreepMaterialStatus"; } }; @@ -104,113 +103,110 @@ class Eurocode2CreepMaterial : public KelvinChainMaterial /// fixed retardation time of the first unit // the reason it is introduced is the application of the correction factors // to achieve a better approximation of the compliance function by the retardation spectrum - double tau1; + double tau1 = 0.; /// stiffness of the zeroth Kelvin unit - double EspringVal; + mutable double EspringVal = 0.; // ELASTICITY + SHORT TERM + STRENGTH /// mean compressive strength at 28 days default - to be specified in units of the analysis (e.g. 30.e6 + stiffnessFacotr 1. or 30. + stiffnessFactor 1.e6) - double fcm28; + double fcm28 = 0.; /// Young's modulus at 28 days default [MPa] - double Ecm28; + double Ecm28 = 0.; /// factor unifying stiffnesses (Ecm is predicted from fcm...) - double stiffnessFactor; + double stiffnessFactor = 0.; /// parameter determined by cement type - double s; + double s = 0.; // CREEP /// drying creep coefficient - double phi_RH; + double phi_RH = 0.; /// drying creep coefficient - double beta_fcm; + double beta_fcm = 0.; /// drying creep coefficient - double beta_H; + double beta_H = 0.; /// effective thickness [mm] - double h0; + double h0 = 0.; /// influence of cement type on concrete equivalent age, B.9 in EC2 - double alpha_T_cement; + double alpha_T_cement = 0.; // DRYING SHRINKAGE /// duration of curing [day, sec, ...] - double t0; + double t0 = 0.; /// age (absolute) when concrete started drying, must be in days! - double begOfDrying; + double begOfDrying = 0.; /// drying shrinkage coefficient - double kh; + double kh = 0.; /// asymptotic value of drying shrinkage at zero relative humidity, B.11 in EC2 - double eps_cd_0; + double eps_cd_0 = 0.; // AUTEGENOUS SHRINKAGE /// asymptotic value of autogenous shrinakge, 3.12 in EC2 - double eps_ca_infty; + double eps_ca_infty = 0.; /// shrinkage option - enum ec2ShrinkageType { EC2_NoShrinkage, EC2_TotalShrinkage, EC2_DryingShrinkage, EC2_AutogenousShrinkage } shType; + enum ec2ShrinkageType { EC2_NoShrinkage, EC2_TotalShrinkage, EC2_DryingShrinkage, EC2_AutogenousShrinkage } shType = EC2_NoShrinkage; /** * If true, analysis of retardation spectrum is used for evaluation of Kelvin units moduli * If false, least-squares method is used for evaluation of Kelvin units moduli (default) */ - bool retardationSpectrumApproximation; + bool retardationSpectrumApproximation = 0.; /// switch for temperature dependence of concrete maturity (default option is off) - bool temperatureDependent; + bool temperatureDependent = 0.; public: - Eurocode2CreepMaterial(int n, Domain *d) : KelvinChainMaterial(n, d) { - shType = EC2_NoShrinkage; - } - virtual ~Eurocode2CreepMaterial() { } + Eurocode2CreepMaterial(int n, Domain *d) : KelvinChainMaterial(n, d) {} - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; - virtual void giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + void giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; - virtual const char *giveClassName() const { return "Eurocode2CreepMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_Eurocode2CreepMaterial_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "Eurocode2CreepMaterial"; } + const char *giveInputRecordName() const override { return _IFT_Eurocode2CreepMaterial_Name; } + void initializeFrom(InputRecord &ir) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; /// evaluates concrete strength at given age - virtual double computeConcreteStrengthAtAge(double age); + virtual double computeConcreteStrengthAtAge(double age) const; /// evaluates concrete mean elastic modulus at given age - virtual double computeMeanElasticModulusAtAge(double age); + virtual double computeMeanElasticModulusAtAge(double age) const; /// Evaluation of the compliance function - virtual double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep); + double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const override; /// Evaluation of the compliance function (according to appendix B from the EC) - virtual double computeCreepCoefficient(double t, double t_prime, GaussPoint *gp, TimeStep *tStep); + virtual double computeCreepCoefficient(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const; protected: - virtual int hasIncrementalShrinkageFormulation() { return 1; } + bool hasIncrementalShrinkageFormulation() const override { return true; } - virtual double giveEModulus(GaussPoint *gp, TimeStep *tStep); + double giveEModulus(GaussPoint *gp, TimeStep *tStep) const override; /// implements B.9 - virtual double computeEquivalentAge(GaussPoint *gp, TimeStep *tStep); + virtual double computeEquivalentAge(GaussPoint *gp, TimeStep *tStep) const; /// implements B.10 - virtual double computeEquivalentMaturity(GaussPoint *gp, TimeStep *tStep); + virtual double computeEquivalentMaturity(GaussPoint *gp, TimeStep *tStep) const; /// sets parameters for elasticity and strength according to formulas from EC @@ -223,22 +219,22 @@ class Eurocode2CreepMaterial : public KelvinChainMaterial void computeCreepParams(int, double); /// computes retardation times of the aging Kelvin chain - virtual void computeCharTimes(); + void computeCharTimes() override; /// computes correction factor which multiplies the retardation times - double computeRetardationTimeCorrection(int mu); + double computeRetardationTimeCorrection(int mu) const; /// evaluates retardation spectrum at given time (t-t') - double evaluateSpectrumAt(double tau); + double evaluateSpectrumAt(double tau) const; /// Evaluation of characteristic moduli of the Kelvin chain. - virtual void computeCharCoefficients(FloatArray &answer, double tPrime, GaussPoint *gp, TimeStep *tStep); + FloatArray computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const override; /// computes increment of drying shrinkage - the shrinkage strain is isotropic - void computeIncrementOfDryingShrinkageVector(FloatArray &answer, GaussPoint *gp, double tNow, double tThen); + void computeIncrementOfDryingShrinkageVector(FloatArray &answer, GaussPoint *gp, double tNow, double tThen) const; /// computes increment of autogenous shrinkage - the shrinkage strain is isotropic - void computeIncrementOfAutogenousShrinkageVector(FloatArray &answer, GaussPoint *gp, double tNow, double tThen); + void computeIncrementOfAutogenousShrinkageVector(FloatArray &answer, GaussPoint *gp, double tNow, double tThen) const; }; } // end namespace oofem #endif // eurocode2creep_h diff --git a/src/sm/Materials/RheoChainMaterials/kelvinChM.C b/src/sm/Materials/RheoChainMaterials/kelvinChM.C index b09066304..8e4aa962c 100644 --- a/src/sm/Materials/RheoChainMaterials/kelvinChM.C +++ b/src/sm/Materials/RheoChainMaterials/kelvinChM.C @@ -44,8 +44,8 @@ namespace oofem { KelvinChainMaterial :: KelvinChainMaterial(int n, Domain *d) : RheoChainMaterial(n, d) { } -void -KelvinChainMaterial :: computeCharCoefficients(FloatArray &answer, double tPrime, GaussPoint *gp, TimeStep *tStep ) +FloatArray +KelvinChainMaterial :: computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const { /* * This function computes the moduli of individual Kelvin units @@ -101,16 +101,18 @@ KelvinChainMaterial :: computeCharCoefficients(FloatArray &answer, double tPrime } // solve the linear system + FloatArray answer; A.solveForRhs(rhs, answer); // convert compliances into moduli for ( int i = 1; i <= this->nUnits; i++ ) { answer.at(i) = 1. / answer.at(i); } + return answer; } double -KelvinChainMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) +KelvinChainMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) const { /* * This function returns the incremental modulus for the given time increment. @@ -122,12 +124,13 @@ KelvinChainMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) double sum = 0.0; // return value - if ( (tStep->giveIntrinsicTime() < this->castingTime) ) { + // the viscoelastic material does not exist yet + if ( ! Material :: isActivated( tStep ) ) { OOFEM_ERROR("Attempted to evaluate E modulus at time lower than casting time"); } ///@warning THREAD UNSAFE! - double tPrime = relMatAge + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ); + double tPrime = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ); this->updateEparModuli(tPrime, gp, tStep); double deltaT = tStep->giveTimeIncrement(); @@ -155,17 +158,17 @@ KelvinChainMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) } void -KelvinChainMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +KelvinChainMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const // // computes the strain due to creep at constant stress during the increment // (in fact, the INCREMENT of creep strain is computed for mode == VM_Incremental) // { - KelvinChainMaterialStatus *status = static_cast< KelvinChainMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< KelvinChainMaterialStatus * >( this->giveStatus(gp) ); // !!! chartime exponents are assumed to be equal to 1 !!! - if ( tStep->giveIntrinsicTime() < this->castingTime ) { + if ( ! Material :: isActivated( tStep ) ) { OOFEM_ERROR("Attempted to evaluate creep strain for time lower than casting time"); } @@ -211,11 +214,11 @@ KelvinChainMaterial :: computeHiddenVars(GaussPoint *gp, TimeStep *tStep) // !!! chartime exponents are assumed to be equal to 1 !!! - FloatArray help, deltaEps0, delta_sigma; + FloatArray help, delta_sigma; KelvinChainMaterialStatus *status = static_cast< KelvinChainMaterialStatus * >( this->giveStatus(gp) ); - // if ( !this->isActivated(tStep) ) { - if ( tStep->giveIntrinsicTime() < this->castingTime ) { + // goes there if the viscoelastic material does not exist yet + if ( ! Material :: isActivated( tStep ) ) { help.resize(StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); help.zero(); for ( int mu = 1; mu <= nUnits; mu++ ) { @@ -228,7 +231,7 @@ KelvinChainMaterial :: computeHiddenVars(GaussPoint *gp, TimeStep *tStep) delta_sigma.subtract( status->giveStrainVector() ); // strain increment in current time-step // Subtract the stress-independent part of strain - this->computeStressIndependentStrainVector(deltaEps0, gp, tStep, VM_Incremental); + auto deltaEps0 = this->computeStressIndependentStrainVector(gp, tStep, VM_Incremental); if ( deltaEps0.giveSize() ) { delta_sigma.subtract(deltaEps0); // should be equal to zero if there is no stress change during the time-step } @@ -272,27 +275,23 @@ KelvinChainMaterial :: computeHiddenVars(GaussPoint *gp, TimeStep *tStep) MaterialStatus * KelvinChainMaterial :: CreateStatus(GaussPoint *gp) const { - return new KelvinChainMaterialStatus(1, this->giveDomain(), gp, nUnits); + return new KelvinChainMaterialStatus(gp, nUnits); } -IRResultType -KelvinChainMaterial :: initializeFrom(InputRecord *ir) +void +KelvinChainMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result = RheoChainMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - + RheoChainMaterial :: initializeFrom(ir); this->giveDiscreteTimes(); // Makes sure the new discrete times are evaluated. - return IRRT_OK; } /****************************************************************************************/ -KelvinChainMaterialStatus :: KelvinChainMaterialStatus(int n, Domain *d, - GaussPoint *g, int nunits) : - RheoChainMaterialStatus(n, d, g, nunits) { } +KelvinChainMaterialStatus :: KelvinChainMaterialStatus(GaussPoint *g, int nunits) : + RheoChainMaterialStatus(g, nunits) { } void -KelvinChainMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +KelvinChainMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { RheoChainMaterialStatus :: printOutputAt(file, tStep); } @@ -310,28 +309,15 @@ KelvinChainMaterialStatus :: initTempStatus() RheoChainMaterialStatus :: initTempStatus(); } -contextIOResultType -KelvinChainMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +KelvinChainMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = RheoChainMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + RheoChainMaterialStatus :: saveContext(stream, mode); } - -contextIOResultType -KelvinChainMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +KelvinChainMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = RheoChainMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + RheoChainMaterialStatus :: restoreContext(stream, mode); } } // end namespace oofem diff --git a/src/sm/Materials/RheoChainMaterials/kelvinChM.h b/src/sm/Materials/RheoChainMaterials/kelvinChM.h index c722f3569..bcc066643 100644 --- a/src/sm/Materials/RheoChainMaterials/kelvinChM.h +++ b/src/sm/Materials/RheoChainMaterials/kelvinChM.h @@ -44,19 +44,18 @@ namespace oofem { class KelvinChainMaterialStatus : public RheoChainMaterialStatus { public: - KelvinChainMaterialStatus(int n, Domain * d, GaussPoint * g, int nunits); - virtual ~KelvinChainMaterialStatus() { } + KelvinChainMaterialStatus(GaussPoint *g, int nunits); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; // definition - virtual const char *giveClassName() const { return "KelvinChainMaterialStatus"; } + const char *giveClassName() const override { return "KelvinChainMaterialStatus"; } }; @@ -67,37 +66,35 @@ class KelvinChainMaterialStatus : public RheoChainMaterialStatus class KelvinChainMaterial : public RheoChainMaterial { public: - KelvinChainMaterial(int n, Domain * d); - virtual ~KelvinChainMaterial() { } + KelvinChainMaterial(int n, Domain *d); // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 0; } - virtual const char *giveClassName() const { return "KelvinChainMaterial"; } + const char *giveClassName() const override { return "KelvinChainMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void giveShrinkageStrainVector(FloatArray &answer, - GaussPoint *gp, - TimeStep *tStep, - ValueModeType mode) + void giveShrinkageStrainVector(FloatArray &answer, + GaussPoint *gp, + TimeStep *tStep, + ValueModeType mode) const override { answer.clear(); } - virtual void giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + void giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) override; void computeHiddenVars(GaussPoint *gp, TimeStep *tStep); protected: - virtual int hasIncrementalShrinkageFormulation() { return 0; } + bool hasIncrementalShrinkageFormulation() const override { return false; } - virtual void computeCharCoefficients(FloatArray &answer, double tPrime, GaussPoint *gp, TimeStep *tStep); + FloatArray computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const override; - virtual double giveEModulus(GaussPoint *gp, TimeStep *tStep); + double giveEModulus(GaussPoint *gp, TimeStep *tStep) const override; - LinearElasticMaterial *giveLinearElasticMaterial(); + // LinearElasticMaterial *giveLinearElasticMaterial(); }; } // end namespace oofem #endif // kelvinchm_h diff --git a/src/sm/Materials/RheoChainMaterials/kelvinChSolM.C b/src/sm/Materials/RheoChainMaterials/kelvinChSolM.C index 05af7a8b6..c325e3ec9 100644 --- a/src/sm/Materials/RheoChainMaterials/kelvinChSolM.C +++ b/src/sm/Materials/RheoChainMaterials/kelvinChSolM.C @@ -45,7 +45,7 @@ KelvinChainSolidMaterial :: KelvinChainSolidMaterial(int n, Domain *d) : RheoCha { } double -KelvinChainSolidMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) +KelvinChainSolidMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) const { /* * This function returns the incremental modulus for the given time increment. @@ -57,71 +57,59 @@ KelvinChainSolidMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) * Note: time -1 refers to the previous time. */ - int mu; - double v; - double lambdaMu, Emu; - double sum = 0.0; - - if ( (tStep->giveIntrinsicTime() < this->castingTime) ) { - OOFEM_ERROR("Attempted to evaluate E modulus at time lower than casting time"); + if ( ! Material :: isActivated( tStep ) ) { + OOFEM_ERROR("Attempted to evaluate E modulus at time lower than casting time"); } if ( this->EparVal.isEmpty() ) { - this->updateEparModuli(0., gp, tStep); // stiffnesses are time independent (evaluated at time t = 0.) + this->updateEparModuli(0., gp, tStep); // stiffnesses are time independent (evaluated at time t = 0.) } - - for ( mu = 1; mu <= nUnits; mu++ ) { - lambdaMu = this->computeLambdaMu(gp, tStep, mu); - Emu = this->giveEparModulus(mu); + double sum = 0.0; + for ( int mu = 1; mu <= nUnits; mu++ ) { + double lambdaMu = this->computeLambdaMu(gp, tStep, mu); + double Emu = this->giveEparModulus(mu); sum += ( 1 - lambdaMu ) / Emu; } - v = this->computeSolidifiedVolume(gp, tStep); + double v = this->computeSolidifiedVolume(gp, tStep); return sum / v; } void -KelvinChainSolidMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +KelvinChainSolidMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const // // computes the strain due to creep at constant stress during the increment // (in fact, the INCREMENT of creep strain is computed for mode == VM_Incremental) // { - int mu; - double betaMu; - double v; - FloatArray *sigmaVMu = NULL, reducedAnswer, help; - FloatMatrix C; KelvinChainSolidMaterialStatus *status = static_cast< KelvinChainSolidMaterialStatus * >( this->giveStatus(gp) ); - if ( (tStep->giveIntrinsicTime() < this->castingTime) ) { - OOFEM_ERROR("Attempted to evaluate creep strain for time lower than casting time"); + if ( ! Material :: isActivated( tStep ) ) { + OOFEM_ERROR("Attempted to evaluate creep strain for time lower than casting time"); } if ( this->EparVal.isEmpty() ) { - this->updateEparModuli(0., gp, tStep); // stiffnesses are time independent (evaluated at time t = 0.) + this->updateEparModuli(0., gp, tStep); // stiffnesses are time independent (evaluated at time t = 0.) } - if ( mode == VM_Incremental ) { - for ( mu = 1; mu <= nUnits; mu++ ) { - betaMu = this->computeBetaMu(gp, tStep, mu); - sigmaVMu = & status->giveHiddenVarsVector(mu); // JB + FloatArray *sigmaVMu = nullptr, reducedAnswer; + for ( int mu = 1; mu <= nUnits; mu++ ) { + double betaMu = this->computeBetaMu(gp, tStep, mu); + sigmaVMu = & status->giveHiddenVarsVector(mu); // JB if ( sigmaVMu->isNotEmpty() ) { - help.zero(); - help.add(* sigmaVMu); - help.times( ( 1.0 - betaMu ) / this->giveEparModulus(mu) ); - reducedAnswer.add(help); + reducedAnswer.add(( 1.0 - betaMu ) / this->giveEparModulus(mu), * sigmaVMu); } } if ( sigmaVMu->isNotEmpty() ) { - help = reducedAnswer; + FloatMatrix C; + FloatArray help = reducedAnswer; this->giveUnitComplianceMatrix(C, gp, tStep); reducedAnswer.beProductOf(C, help); - v = this->computeSolidifiedVolume(gp, tStep); + double v = this->computeSolidifiedVolume(gp, tStep); reducedAnswer.times(1. / v); } @@ -133,43 +121,31 @@ KelvinChainSolidMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint } double -KelvinChainSolidMaterial :: computeBetaMu(GaussPoint *gp, TimeStep *tStep, int Mu) +KelvinChainSolidMaterial :: computeBetaMu(GaussPoint *gp, TimeStep *tStep, int Mu) const { - double betaMu; - double deltaT; - double tauMu; - - deltaT = tStep->giveTimeIncrement(); - tauMu = this->giveCharTime(Mu); + double deltaT = tStep->giveTimeIncrement(); + double tauMu = this->giveCharTime(Mu); if ( deltaT / tauMu > 30 ) { - betaMu = 0; + return 0; } else { - betaMu = exp(-( deltaT ) / tauMu); + return exp(-( deltaT ) / tauMu); } - - return betaMu; } double -KelvinChainSolidMaterial :: computeLambdaMu(GaussPoint *gp, TimeStep *tStep, int Mu) +KelvinChainSolidMaterial :: computeLambdaMu(GaussPoint *gp, TimeStep *tStep, int Mu) const { - double lambdaMu; - double deltaT; - double tauMu; - - deltaT = tStep->giveTimeIncrement(); - tauMu = this->giveCharTime(Mu); + double deltaT = tStep->giveTimeIncrement(); + double tauMu = this->giveCharTime(Mu); if ( deltaT / tauMu < 1.e-5 ) { - lambdaMu = 1 - 0.5 * ( deltaT / tauMu ) + 1 / 6 * ( pow(deltaT / tauMu, 2) ) - 1 / 24 * ( pow(deltaT / tauMu, 3) ); + return 1 - 0.5 * ( deltaT / tauMu ) + 1 / 6 * ( pow(deltaT / tauMu, 2) ) - 1 / 24 * ( pow(deltaT / tauMu, 3) ); } else if ( deltaT / tauMu > 30 ) { - lambdaMu = tauMu / deltaT; + return tauMu / deltaT; } else { - lambdaMu = ( 1.0 - exp(-( deltaT ) / tauMu) ) * tauMu / deltaT; + return ( 1.0 - exp(-( deltaT ) / tauMu) ) * tauMu / deltaT; } - - return lambdaMu; } @@ -190,27 +166,27 @@ KelvinChainSolidMaterial :: computeHiddenVars(GaussPoint *gp, TimeStep *tStep) * Updates hidden variables used to effectively trace the load history */ - double betaMu; - double lambdaMu; - - FloatArray help, SigmaVMu, deltaEps0, deltaSigma; + FloatArray help, SigmaVMu, deltaSigma; FloatMatrix D; KelvinChainSolidMaterialStatus *status = static_cast< KelvinChainSolidMaterialStatus * >( this->giveStatus(gp) ); - if ( ( !this->isActivated(tStep) ) || ( tStep->giveIntrinsicTime() < this->castingTime ) ) { - help.resize(StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); - help.zero(); - for ( int mu = 1; mu <= nUnits; mu++ ) { - status->letTempHiddenVarsVectorBe(mu, help); - } - return; + // goes there if the viscoelastic material does not exist and at the same time the precastingtime mat is not provided + // if ( ! this->isActivated( tStep ) ) { + // goes there if the viscoelastic material does not exist yet + if ( ! Material :: isActivated( tStep ) ) { + help.resize(StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + help.zero(); + for ( int mu = 1; mu <= nUnits; mu++ ) { + status->letTempHiddenVarsVectorBe(mu, help); + } + return; } help = status->giveTempStrainVector(); // gives updated strain vector (at the end of time-step) help.subtract( status->giveStrainVector() ); // strain increment in current time-step // Subtract the stress-independent part of strain - this->computeStressIndependentStrainVector(deltaEps0, gp, tStep, VM_Incremental); + auto deltaEps0 = this->computeStressIndependentStrainVector(gp, tStep, VM_Incremental); if ( deltaEps0.giveSize() ) { help.subtract(deltaEps0); // should be equal to zero if there is no stress change during the time-step } @@ -222,8 +198,8 @@ KelvinChainSolidMaterial :: computeHiddenVars(GaussPoint *gp, TimeStep *tStep) deltaSigma.beProductOf(D, help); for ( int mu = 1; mu <= nUnits; mu++ ) { - betaMu = this->computeBetaMu(gp, tStep, mu); - lambdaMu = this->computeLambdaMu(gp, tStep, mu); + double betaMu = this->computeBetaMu(gp, tStep, mu); + double lambdaMu = this->computeLambdaMu(gp, tStep, mu); help = deltaSigma; help.times(lambdaMu); @@ -247,18 +223,18 @@ KelvinChainSolidMaterial :: CreateStatus(GaussPoint *gp) const * creates a new material status corresponding to this class */ { - return new KelvinChainSolidMaterialStatus(1, this->giveDomain(), gp, nUnits); + return new KelvinChainSolidMaterialStatus(gp, nUnits); } -IRResultType -KelvinChainSolidMaterial :: initializeFrom(InputRecord *ir) +void +KelvinChainSolidMaterial :: initializeFrom(InputRecord &ir) { - return RheoChainMaterial :: initializeFrom(ir); + RheoChainMaterial :: initializeFrom(ir); } // useless here double -KelvinChainSolidMaterial :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) +KelvinChainSolidMaterial :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("function has not been yet implemented to KelvinChainSolidMaterialStatus.C"); return 0.; @@ -267,12 +243,11 @@ KelvinChainSolidMaterial :: computeCreepFunction(double t, double t_prime, Gauss /****************************************************************************************/ -KelvinChainSolidMaterialStatus :: KelvinChainSolidMaterialStatus(int n, Domain *d, - GaussPoint *g, int nunits) : - RheoChainMaterialStatus(n, d, g, nunits) { } +KelvinChainSolidMaterialStatus :: KelvinChainSolidMaterialStatus(GaussPoint *g, int nunits) : + RheoChainMaterialStatus(g, nunits) { } void -KelvinChainSolidMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +KelvinChainSolidMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { RheoChainMaterialStatus :: printOutputAt(file, tStep); } @@ -290,28 +265,15 @@ KelvinChainSolidMaterialStatus :: initTempStatus() RheoChainMaterialStatus :: initTempStatus(); } -contextIOResultType -KelvinChainSolidMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +KelvinChainSolidMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = RheoChainMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + RheoChainMaterialStatus :: saveContext(stream, mode); } - -contextIOResultType -KelvinChainSolidMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +KelvinChainSolidMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = RheoChainMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + RheoChainMaterialStatus :: restoreContext(stream, mode); } } // end namespace oofem diff --git a/src/sm/Materials/RheoChainMaterials/kelvinChSolM.h b/src/sm/Materials/RheoChainMaterials/kelvinChSolM.h index d9de7cdb6..95dea1ad9 100644 --- a/src/sm/Materials/RheoChainMaterials/kelvinChSolM.h +++ b/src/sm/Materials/RheoChainMaterials/kelvinChSolM.h @@ -45,18 +45,18 @@ namespace oofem { class KelvinChainSolidMaterialStatus : public RheoChainMaterialStatus { public: - KelvinChainSolidMaterialStatus(int n, Domain * d, GaussPoint * g, int nunits); - virtual ~KelvinChainSolidMaterialStatus() { } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + KelvinChainSolidMaterialStatus(GaussPoint * g, int nunits); - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; // definition - virtual const char *giveClassName() const { return "KelvinChainSolidMaterialStatus"; } + const char *giveClassName() const override { return "KelvinChainSolidMaterialStatus"; } }; @@ -68,41 +68,38 @@ class KelvinChainSolidMaterial : public RheoChainMaterial { public: KelvinChainSolidMaterial(int n, Domain * d); - virtual ~KelvinChainSolidMaterial() { } - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) override; void computeHiddenVars(GaussPoint *gp, TimeStep *tStep); // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 0; } - virtual const char *giveClassName() const { return "KelvinChainSolidMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual void giveShrinkageStrainVector(FloatArray &answer, - GaussPoint *gp, - TimeStep *tStep, - ValueModeType mode) + const char *giveClassName() const override { return "KelvinChainSolidMaterial"; } + void initializeFrom(InputRecord &ir) override; + + void giveShrinkageStrainVector(FloatArray &answer, + GaussPoint *gp, + TimeStep *tStep, + ValueModeType mode) const override { answer.clear(); } - virtual void giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + void giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; /// Evaluation of the creep compliance function - function useless here - virtual double computeCreepFunction(double ofAge, double tPrime, GaussPoint *gp, TimeStep *tStep); + double computeCreepFunction(double ofAge, double tPrime, GaussPoint *gp, TimeStep *tStep) const override; protected: - virtual int hasIncrementalShrinkageFormulation() { return 0; } + bool hasIncrementalShrinkageFormulation() const override { return false; } - virtual double giveEModulus(GaussPoint *gp, TimeStep *tStep); + double giveEModulus(GaussPoint *gp, TimeStep *tStep) const override; /// Evaluation of the relative volume of the solidified material - virtual double computeSolidifiedVolume(GaussPoint *gp, TimeStep *tStep) = 0; + virtual double computeSolidifiedVolume(GaussPoint *gp, TimeStep *tStep) const = 0; /// factors for exponential algorithm - virtual double computeBetaMu(GaussPoint *gp, TimeStep *tStep, int Mu); - virtual double computeLambdaMu(GaussPoint *gp, TimeStep *tStep, int Mu); - + virtual double computeBetaMu(GaussPoint *gp, TimeStep *tStep, int Mu) const; + virtual double computeLambdaMu(GaussPoint *gp, TimeStep *tStep, int Mu) const; }; } // end namespace oofem #endif // kelvinchsol_h diff --git a/src/sm/Materials/RheoChainMaterials/maxwellChM.C b/src/sm/Materials/RheoChainMaterials/maxwellChM.C index a9d80ea05..f00c8625a 100644 --- a/src/sm/Materials/RheoChainMaterials/maxwellChM.C +++ b/src/sm/Materials/RheoChainMaterials/maxwellChM.C @@ -45,15 +45,14 @@ MaxwellChainMaterial :: MaxwellChainMaterial(int n, Domain *d) : RheoChainMateri { } -void -MaxwellChainMaterial :: computeCharCoefficients(FloatArray &answer, double tPrime, GaussPoint *gp, TimeStep *tStep) +FloatArray +MaxwellChainMaterial :: computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const { - int rSize; FloatArray rhs(this->nUnits), discreteRelaxFunctionVal; FloatMatrix A(this->nUnits, this->nUnits); const FloatArray &rTimes = this->giveDiscreteTimes(); - rSize = rTimes.giveSize(); + int rSize = rTimes.giveSize(); // compute discrete values of the relaxation function at times rTimes // from the creep function (by numerically solving integral equations) @@ -96,13 +95,15 @@ MaxwellChainMaterial :: computeCharCoefficients(FloatArray &answer, double tPrim } // solve the linear system + FloatArray answer; A.solveForRhs(rhs, answer); + return answer; } double -MaxwellChainMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) +MaxwellChainMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) const { /* * This function returns the incremental modulus for the given time increment. @@ -114,11 +115,12 @@ MaxwellChainMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) ///@warning THREAD UNSAFE! - if ( (tStep->giveIntrinsicTime() < this->castingTime) ) { + // the viscoelastic material does not exist yet + if ( ! Material :: isActivated( tStep ) ) { OOFEM_ERROR("Attempted to evaluate E modulus at time lower than casting time"); } - double tPrime = relMatAge + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor; + double tPrime = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor; this->updateEparModuli(tPrime, gp, tStep); for ( int mu = 1; mu <= nUnits; mu++ ) { @@ -142,7 +144,7 @@ MaxwellChainMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) void MaxwellChainMaterial :: giveEigenStrainVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep, ValueModeType mode) + GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const // // computes the strain due to creep at constant stress during the increment // (in fact, the INCREMENT of creep strain is computed for mode == VM_Incremental) @@ -153,7 +155,7 @@ MaxwellChainMaterial :: giveEigenStrainVector(FloatArray &answer, FloatMatrix B; MaxwellChainMaterialStatus *status = static_cast< MaxwellChainMaterialStatus * >( this->giveStatus(gp) ); - if ( (tStep->giveIntrinsicTime() < this->castingTime) ) { + if ( ! Material :: isActivated( tStep ) ) { OOFEM_ERROR("Attempted to evaluate creep strain for time lower than casting time"); } @@ -210,6 +212,17 @@ MaxwellChainMaterial :: computeHiddenVars(GaussPoint *gp, TimeStep *tStep) MaxwellChainMaterialStatus *status = static_cast< MaxwellChainMaterialStatus * >( this->giveStatus(gp) ); + + // goes there if the viscoelastic material does not exist yet + if ( ! Material :: isActivated( tStep ) ) { + help.resize(StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + help.zero(); + for ( int mu = 1; mu <= nUnits; mu++ ) { + status->letTempHiddenVarsVectorBe(mu, help); + } + return; + } + this->giveUnitStiffnessMatrix(Binv, gp, tStep); help = status->giveTempStrainVector(); help.subtract( status->giveStrainVector() ); @@ -223,8 +236,9 @@ MaxwellChainMaterial :: computeHiddenVars(GaussPoint *gp, TimeStep *tStep) help1.beProductOf(Binv, help); ///@warning THREAD UNSAFE! - double tPrime = relMatAge + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor; - this->updateEparModuli(tPrime, gp, tStep); + // redundant two subsequent lines? + // double tPrime = relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ) / timeFactor; + // this->updateEparModuli(tPrime, gp, tStep); for ( int mu = 1; mu <= nUnits; mu++ ) { double deltaYmu = tStep->giveTimeIncrement() / timeFactor / this->giveCharTime(mu); @@ -250,25 +264,24 @@ MaxwellChainMaterial :: computeHiddenVars(GaussPoint *gp, TimeStep *tStep) MaterialStatus * MaxwellChainMaterial :: CreateStatus(GaussPoint *gp) const { - return new MaxwellChainMaterialStatus(1, this->giveDomain(), gp, nUnits); + return new MaxwellChainMaterialStatus(gp, nUnits); } -IRResultType -MaxwellChainMaterial :: initializeFrom(InputRecord *ir) +void +MaxwellChainMaterial :: initializeFrom(InputRecord &ir) { - return RheoChainMaterial :: initializeFrom(ir); + RheoChainMaterial :: initializeFrom(ir); } /****************************************************************************************/ -MaxwellChainMaterialStatus :: MaxwellChainMaterialStatus(int n, Domain *d, - GaussPoint *g, int nunits) : - RheoChainMaterialStatus(n, d, g, nunits) { } +MaxwellChainMaterialStatus :: MaxwellChainMaterialStatus(GaussPoint *g, int nunits) : + RheoChainMaterialStatus(g, nunits) { } void -MaxwellChainMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +MaxwellChainMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { RheoChainMaterialStatus :: printOutputAt(file, tStep); } @@ -286,28 +299,15 @@ MaxwellChainMaterialStatus :: initTempStatus() RheoChainMaterialStatus :: initTempStatus(); } -contextIOResultType -MaxwellChainMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +MaxwellChainMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = RheoChainMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + RheoChainMaterialStatus :: saveContext(stream, mode); } - -contextIOResultType -MaxwellChainMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +MaxwellChainMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores = RheoChainMaterialStatus :: restoreContext(stream, mode, obj); - - if ( iores != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + RheoChainMaterialStatus :: restoreContext(stream, mode); } } // end namespace oofem diff --git a/src/sm/Materials/RheoChainMaterials/maxwellChM.h b/src/sm/Materials/RheoChainMaterials/maxwellChM.h index fe4eb3896..15717b451 100644 --- a/src/sm/Materials/RheoChainMaterials/maxwellChM.h +++ b/src/sm/Materials/RheoChainMaterials/maxwellChM.h @@ -44,19 +44,18 @@ namespace oofem { class MaxwellChainMaterialStatus : public RheoChainMaterialStatus { public: - MaxwellChainMaterialStatus(int n, Domain * d, GaussPoint * g, int nunits); - virtual ~MaxwellChainMaterialStatus() { } + MaxwellChainMaterialStatus(GaussPoint *g, int nunits); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; // definition - virtual const char *giveClassName() const { return "MaxwellChainMaterialStatus"; } + const char *giveClassName() const override { return "MaxwellChainMaterialStatus"; } }; @@ -68,31 +67,29 @@ class MaxwellChainMaterialStatus : public RheoChainMaterialStatus class MaxwellChainMaterial : public RheoChainMaterial { public: - MaxwellChainMaterial(int n, Domain * d); - virtual ~MaxwellChainMaterial() { } + MaxwellChainMaterial(int n, Domain *d); // overload thesse function such that computation of hidden vars can be done after the computation of stress - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) override; void computeHiddenVars(GaussPoint *gp, TimeStep *tStep); // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 0; } - virtual const char *giveClassName() const { return "MaxwellChainMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual void giveShrinkageStrainVector(FloatArray &answer, - GaussPoint *gp, - TimeStep *tStep, - ValueModeType mode) + const char *giveClassName() const override { return "MaxwellChainMaterial"; } + void initializeFrom(InputRecord &ir) override; + + void giveShrinkageStrainVector(FloatArray &answer, + GaussPoint *gp, + TimeStep *tStep, + ValueModeType mode) const override { answer.clear(); } - virtual void giveEigenStrainVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + void giveEigenStrainVector(FloatArray &answer, + GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: - virtual int hasIncrementalShrinkageFormulation() { return 0; } + bool hasIncrementalShrinkageFormulation() const override { return false; } /** * This function computes the moduli of individual Maxwell units * such that the corresponding Dirichlet series gives the best @@ -107,10 +104,10 @@ class MaxwellChainMaterial : public RheoChainMaterial * @param[out] answer Array with coefficients * @param tStep Age of material when load is applied ??? */ - virtual void computeCharCoefficients(FloatArray &answer, double tPrime, GaussPoint *gp, TimeStep *tStep); + FloatArray computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const override; - virtual double giveEModulus(GaussPoint *gp, TimeStep *tStep); - LinearElasticMaterial *giveLinearElasticMaterial(); + double giveEModulus(GaussPoint *gp, TimeStep *tStep) const override; + // LinearElasticMaterial *giveLinearElasticMaterial(); }; } // end namespace oofem #endif // maxwellchm_h diff --git a/src/sm/Materials/RheoChainMaterials/mps.C b/src/sm/Materials/RheoChainMaterials/mps.C index f7d629ac9..e14c83cf8 100644 --- a/src/sm/Materials/RheoChainMaterials/mps.C +++ b/src/sm/Materials/RheoChainMaterials/mps.C @@ -40,6 +40,7 @@ #include "contextioerr.h" #include "datastream.h" #include "classfactory.h" +#include "function.h" namespace oofem { REGISTER_Material(MPSMaterial); @@ -50,35 +51,18 @@ REGISTER_Material(MPSMaterial); -MPSMaterialStatus :: MPSMaterialStatus(int n, Domain *d, GaussPoint *gp, int nunits) : - KelvinChainSolidMaterialStatus(n, d, gp, nunits) +MPSMaterialStatus::MPSMaterialStatus(GaussPoint *gp, int nunits) : + KelvinChainSolidMaterialStatus(gp, nunits) { - hum = -1.; - hum_increment = -1.; - T = -1.; - T_increment = -1.; - storedEmodulusFlag = false; - storedEmodulus = -1.; - equivalentTime = 0.; - equivalentTimeTemp = 0.; - flowTermViscosityTemp = -1.; - #ifdef keep_track_of_strains - dryingShrinkageStrain = 0.; - tempDryingShrinkageStrain = 0.; - autogenousShrinkageStrain = 0.; - tempAutogenousShrinkageStrain = 0.; - - int rsize = StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ); + int rsize = StructuralMaterial::giveSizeOfVoigtSymVector( gp->giveMaterialMode() ); creepStrain.resize(rsize); - creepStrain.zero(); creepStrainIncrement.resize(rsize); - creepStrainIncrement.zero(); #endif } void -MPSMaterialStatus :: updateYourself(TimeStep *tStep) +MPSMaterialStatus::updateYourself(TimeStep *tStep) { equivalentTime = equivalentTimeTemp; equivalentTimeTemp = 0.; @@ -95,6 +79,9 @@ MPSMaterialStatus :: updateYourself(TimeStep *tStep) T = -1.; T_increment = -1.; + humNano = humNanoTemp; + humNanoTemp = -1.; + #ifdef keep_track_of_strains dryingShrinkageStrain = tempDryingShrinkageStrain; tempDryingShrinkageStrain = 0.; @@ -106,14 +93,14 @@ MPSMaterialStatus :: updateYourself(TimeStep *tStep) tempAutogenousShrinkageStrain = 0.; #endif - KelvinChainSolidMaterialStatus :: updateYourself(tStep); + KelvinChainSolidMaterialStatus::updateYourself(tStep); } void -MPSMaterialStatus :: initTempStatus() +MPSMaterialStatus::initTempStatus() { - KelvinChainSolidMaterialStatus :: initTempStatus(); + KelvinChainSolidMaterialStatus::initTempStatus(); equivalentTimeTemp = 0.; @@ -128,58 +115,66 @@ MPSMaterialStatus :: initTempStatus() T = -1.; T_increment = -1.; + humNanoTemp = -1.; + #ifdef keep_track_of_strains tempDryingShrinkageStrain = 0.; creepStrainIncrement.zero(); tempAutogenousShrinkageStrain = 0.; #endif - } -contextIOResultType -MPSMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// +void +MPSMaterialStatus::saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + KelvinChainSolidMaterialStatus::saveContext(stream, mode); - if ( ( iores = KelvinChainSolidMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); + if ( !stream.write(T_max) ) { + THROW_CIOERR(CIO_IOERR); } + if ( !stream.write(h_min) ) { + THROW_CIOERR(CIO_IOERR); + } if ( !stream.write(equivalentTime) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } if ( !stream.write(flowTermViscosity) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } - return CIO_OK; + if ( !stream.write(humNano) ) { + THROW_CIOERR(CIO_IOERR); + } } -contextIOResultType -MPSMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restore the state variables from a stream -// +void +MPSMaterialStatus::restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = KelvinChainSolidMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); + KelvinChainSolidMaterialStatus::restoreContext(stream, mode); + + + if ( !stream.read(T_max) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(h_min) ) { + THROW_CIOERR(CIO_IOERR); } if ( !stream.read(equivalentTime) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } if ( !stream.read(flowTermViscosity) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } - return CIO_OK; + if ( !stream.read(humNano) ) { + THROW_CIOERR(CIO_IOERR); + } } // ********************************************************************************************** @@ -188,11 +183,9 @@ MPSMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void * // ********************************************************************************************** -IRResultType -MPSMaterial :: initializeFrom(InputRecord *ir) +void +MPSMaterial::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - double fc, c, wc, ac; /* scaling factor transforming PREDICTED stiffnesses q1, q2, q3 and q4 to desired @@ -201,37 +194,40 @@ MPSMaterial :: initializeFrom(InputRecord *ir) this->stiffnessFactor = 1.e6; IR_GIVE_OPTIONAL_FIELD(ir, stiffnessFactor, _IFT_MPSMaterial_stiffnessfactor); - result = KelvinChainSolidMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + KelvinChainSolidMaterial::initializeFrom(ir); - // checking timefactor - for MPS material must be equal to 1. + // checking timefactor - for MPS material must be equal to 1. (in seconds) double tf; IR_GIVE_FIELD(ir, tf, _IFT_RheoChainMaterial_timefactor); if ( tf != 1. ) { - OOFEM_WARNING("for MPS material timefactor must be equal to 1."); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_RheoChainMaterial_timefactor, "for MPS material timefactor must be equal to 1."); } // initialize exponent p or p_tilde of the governing equation - if ( ir->hasField(_IFT_MPSMaterial_p_tilde) && ir->hasField(_IFT_MPSMaterial_p) ) { - OOFEM_ERROR("for MPS p and p_tilde cannot be defined at the same time"); + if ( ir.hasField(_IFT_MPSMaterial_p_tilde) && ir.hasField(_IFT_MPSMaterial_p) ) { + throw ValueInputException(ir, _IFT_MPSMaterial_p_tilde, "for MPS p and p_tilde cannot be defined at the same time"); } double p_tilde = 2.; IR_GIVE_OPTIONAL_FIELD(ir, p_tilde, _IFT_MPSMaterial_p_tilde); - p = p_tilde / ( p_tilde - 1. ); + if (p_tilde == 1.) { + p = 100.; + } else { + p = p_tilde / ( p_tilde - 1. ); + } + IR_GIVE_OPTIONAL_FIELD(ir, p, _IFT_MPSMaterial_p); if ( p > 100. ) { p = 100.; } + IR_GIVE_FIELD(ir, lambda0, _IFT_MPSMaterial_lambda0); + int mode = 0; IR_GIVE_OPTIONAL_FIELD(ir, mode, _IFT_MPSMaterial_mode); - - if ( mode == 0 ) { // default - estimate model parameters q1,..,q4 from composition IR_GIVE_FIELD(ir, fc, _IFT_MPSMaterial_fc); // 28-day standard cylinder compression strength [MPa] IR_GIVE_FIELD(ir, c, _IFT_MPSMaterial_cc); // cement content of concrete [kg/m^3] @@ -246,13 +242,10 @@ MPSMaterial :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, q4, _IFT_MPSMaterial_q4); } - IR_GIVE_FIELD(ir, lambda0, _IFT_MPSMaterial_lambda0); - int type = 1; IR_GIVE_OPTIONAL_FIELD(ir, type, _IFT_MPSMaterial_coupledanalysistype); if ( type >= 4 ) { - OOFEM_WARNING("CoupledAnalysisType must be equal to 0, 1, 2 or 3"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_MPSMaterial_coupledanalysistype, "must be 0, 1, 2 or 3"); } this->CoupledAnalysis = ( coupledAnalysisType ) type; @@ -260,7 +253,9 @@ MPSMaterial :: initializeFrom(InputRecord *ir) if ( ( this->CoupledAnalysis == MPS_full ) || ( this->CoupledAnalysis == MPS_humidity ) || ( this->CoupledAnalysis == MPS_temperature ) ) { // age when drying or thermal changes begin [days] - necessary to determine initial viscosity - IR_GIVE_FIELD(ir, t0, _IFT_MPSMaterial_t0); + // time t0 is equal to relMatAge + // IR_GIVE_FIELD(ir, t0, _IFT_MPSMaterial_t0); + this->t0 = this->relMatAge; if ( this->p < 100. ) { // muS- the only parameter necessary for evaluation of the flow-term viscosity @@ -284,6 +279,20 @@ MPSMaterial :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, sh_hC, _IFT_MPSMaterial_sh_hC); IR_GIVE_OPTIONAL_FIELD(ir, sh_n, _IFT_MPSMaterial_sh_n); + + if ( ir.hasField(_IFT_MPSMaterial_factor_ksh_h) && ir.hasField(_IFT_MPSMaterial_factor_ksh_fh) ) { + IR_GIVE_FIELD(ir, ksh_h, _IFT_MPSMaterial_factor_ksh_h); + IR_GIVE_FIELD(ir, ksh_fh, _IFT_MPSMaterial_factor_ksh_fh); + + if ( ksh_h.giveSize() != ksh_fh.giveSize() ) { + throw ValueInputException(ir, _IFT_MPSMaterial_factor_ksh_h, "the size of 'ksh_h' and 'ksh_f(h)' must be the same"); + } + } + + if ( ir.hasField(_IFT_MPSMaterial_timedependent_ksh) ) { + this->timeDependent_ksh = true; + } + this->alphaE = 10.; // according to Bazant 1995 IR_GIVE_OPTIONAL_FIELD(ir, alphaE, _IFT_MPSMaterial_alphae); this->alphaR = 0.1; // according to Bazant 1995 @@ -291,6 +300,14 @@ MPSMaterial :: initializeFrom(InputRecord *ir) this->alphaS = 0.1; // according to Bazant 1995 IR_GIVE_OPTIONAL_FIELD(ir, alphaS, _IFT_MPSMaterial_alphas); + IR_GIVE_OPTIONAL_FIELD(ir, tau_nano, _IFT_MPSMaterial_tau_nano); + + this->khc = 1.0; + IR_GIVE_OPTIONAL_FIELD(ir, khc, _IFT_MPSMaterial_khc); + if ( ( this->khc > 1. ) || ( this->khc < 0. ) ) { + throw ValueInputException(ir, _IFT_MPSMaterial_khc, "Allowed value for khc is in the range <0., 1.>"); + } + /// if sortion parameters are provided then it is assumed that the transport analysis uses moisture content/ratio; if not then it exports relative humidity // Parameters for desorption isotherm @@ -316,7 +333,7 @@ MPSMaterial :: initializeFrom(InputRecord *ir) /// flag - if true, external fields and reference temperature are in Celsius this->temperScaleDifference = 0.; - if ( ir->hasField(_IFT_MPSMaterial_temperInCelsius) ) { + if ( ir.hasField(_IFT_MPSMaterial_temperInCelsius) ) { this->temperScaleDifference = 273.15; } @@ -337,7 +354,7 @@ MPSMaterial :: initializeFrom(InputRecord *ir) this->eps_cas0 = 0.; IR_GIVE_OPTIONAL_FIELD(ir, eps_cas0, _IFT_MPSMaterial_eps_cas0); - if ( ir->hasField(_IFT_MPSMaterial_alpha_as) && ir->hasField(_IFT_MPSMaterial_fc) ) { + if ( ir.hasField(_IFT_MPSMaterial_alpha_as) && ir.hasField(_IFT_MPSMaterial_fc) ) { double alpha_as; // table 5.1-13 from fib2010 // alpha_as = 800 for cem 32.5N @@ -348,7 +365,7 @@ MPSMaterial :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, fc, _IFT_MPSMaterial_fc); // fib2010 equations 5.1-78 - eps_cas0 = -alpha_as *pow( ( fc / 10. ) / ( 6. + fc / 10. ), 2.5 ) * 1e-6; + eps_cas0 = -alpha_as *pow( ( fc / 10. ) / ( 6. + fc / 10. ), 2.5) * 1e-6; } // autogenous shrinkage according to B4 @@ -356,8 +373,8 @@ MPSMaterial :: initializeFrom(InputRecord *ir) b4_tau_au = 0.; b4_alpha = 0.; b4_r_t = 0.; - - if ( ir->hasField(_IFT_MPSMaterial_B4_cem_type) ) { + + if ( ir.hasField(_IFT_MPSMaterial_B4_cem_type) ) { /// auxiliary parameters for autogenous shrinkage according to B4 model double b4_r_alpha = 0., b4_eps_au_cem = 0., b4_tau_au_cem = 0., b4_r_ea, b4_r_ew, b4_r_tw; int b4_cem_type; @@ -389,29 +406,31 @@ MPSMaterial :: initializeFrom(InputRecord *ir) b4_r_ea = -0.75; b4_r_ew = -3.5; } else { - OOFEM_ERROR("Unknown cement type (b4_cem_type)"); + throw ValueInputException(ir, _IFT_MPSMaterial_B4_cem_type, "Unknown cement type"); } - IR_GIVE_FIELD(ir, wc, _IFT_MPSMaterial_wc); - IR_GIVE_FIELD(ir, ac, _IFT_MPSMaterial_ac); - if ( ir->hasField( _IFT_MPSMaterial_B4_eps_au_infty) ) { - IR_GIVE_FIELD(ir, b4_eps_au_infty, _IFT_MPSMaterial_B4_eps_au_infty); - } else { - b4_eps_au_infty = -b4_eps_au_cem *pow(ac / 6., b4_r_ea) * pow(wc / 0.38, b4_r_ew); + if ( ir.hasField(_IFT_MPSMaterial_B4_eps_au_infty) ) { + IR_GIVE_FIELD(ir, b4_eps_au_infty, _IFT_MPSMaterial_B4_eps_au_infty); + } else { + IR_GIVE_FIELD(ir, wc, _IFT_MPSMaterial_wc); + IR_GIVE_FIELD(ir, ac, _IFT_MPSMaterial_ac); + b4_eps_au_infty = -b4_eps_au_cem *pow(ac / 6., b4_r_ea) * pow(wc / 0.38, b4_r_ew); } - if ( ir->hasField( _IFT_MPSMaterial_B4_tau_au) ) { - IR_GIVE_FIELD(ir, b4_tau_au, _IFT_MPSMaterial_B4_tau_au); // must be in units of the analysis + if ( ir.hasField(_IFT_MPSMaterial_B4_tau_au) ) { + IR_GIVE_FIELD(ir, b4_tau_au, _IFT_MPSMaterial_B4_tau_au); // must be in units of the analysis } else { - b4_tau_au = b4_tau_au_cem * pow(wc / 0.38, b4_r_tw); - b4_tau_au *= lambda0; // converted to desired time unit + IR_GIVE_FIELD(ir, wc, _IFT_MPSMaterial_wc); + b4_tau_au = b4_tau_au_cem * pow(wc / 0.38, b4_r_tw); + b4_tau_au *= lambda0; // converted to desired time unit } - if ( ir->hasField( _IFT_MPSMaterial_B4_alpha) ) { - IR_GIVE_FIELD(ir, b4_alpha, _IFT_MPSMaterial_B4_alpha); + if ( ir.hasField(_IFT_MPSMaterial_B4_alpha) ) { + IR_GIVE_FIELD(ir, b4_alpha, _IFT_MPSMaterial_B4_alpha); } else { - b4_alpha = b4_r_alpha * wc / 0.38; + IR_GIVE_FIELD(ir, wc, _IFT_MPSMaterial_wc); + b4_alpha = b4_r_alpha * wc / 0.38; } // possibility to overwrite default value of exponent r_t @@ -419,35 +438,39 @@ MPSMaterial :: initializeFrom(InputRecord *ir) } if ( ( eps_cas0 != 0. ) && ( b4_eps_au_infty != 0. ) ) { - OOFEM_ERROR("autogenous shrinkage cannot be described according to fib and B4 simultaneously"); + throw ValueInputException(ir, _IFT_MPSMaterial_B4_eps_au_infty, + "autogenous shrinkage cannot be described according to fib and B4 simultaneously"); } - return IRRT_OK; + + hydrationTimescaleTF = 0; + IR_GIVE_OPTIONAL_FIELD(ir, hydrationTimescaleTF, _IFT_MPSMaterial_hydrationTimescaleTF); + + autoShrinkageTF = 0; + IR_GIVE_OPTIONAL_FIELD(ir, autoShrinkageTF, _IFT_MPSMaterial_autoShrinkageTF); } void -MPSMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +MPSMaterial::giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) { - KelvinChainSolidMaterial :: giveRealStressVector(answer, gp, reducedStrain, tStep); + KelvinChainSolidMaterial::giveRealStressVector(answer, gp, reducedStrain, tStep); - if ( !this->isActivated(tStep) ) { + if ( !Material::isActivated(tStep) ) { return; } MPSMaterialStatus *status = static_cast< MPSMaterialStatus * >( this->giveStatus(gp) ); - if ( ( this->CoupledAnalysis == MPS_full ) || ( this->CoupledAnalysis == MPS_humidity ) || ( this->CoupledAnalysis == MPS_temperature ) ) { - status->setEquivalentTimeTemp( this->computeEquivalentTime(gp, tStep, 1) ); - } + status->setEquivalentTimeTemp( this->computeEquivalentTime(gp, tStep, 1) ); } void -MPSMaterial :: giveShrinkageStrainVector(FloatArray &answer, - GaussPoint *gp, - TimeStep *tStep, - ValueModeType mode) +MPSMaterial::giveShrinkageStrainVector(FloatArray &answer, + GaussPoint *gp, + TimeStep *tStep, + ValueModeType mode) const { if ( ( mode != VM_Total ) && ( mode != VM_Incremental ) ) { OOFEM_ERROR("unsupported mode"); @@ -467,10 +490,10 @@ MPSMaterial :: giveShrinkageStrainVector(FloatArray &answer, double dryShrIncr = 0.; double autoShrIncr = 0.; - answer.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + answer.resize( StructuralMaterial::giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); answer.zero(); - if ( ( this->CoupledAnalysis == Basic ) || ( this->CoupledAnalysis == MPS_temperature ) || ( !this->isActivated(tStep) ) ) { + if ( ( this->CoupledAnalysis == Basic ) || ( this->CoupledAnalysis == MPS_temperature ) || ( !Material::isActivated(tStep) ) ) { ; } else { // compute drying shrinkage this->computePointShrinkageStrainVector(dry_shr, gp, tStep); @@ -484,11 +507,13 @@ MPSMaterial :: giveShrinkageStrainVector(FloatArray &answer, } #endif - if ( ( this->eps_cas0 != 0. ) || ( this->b4_eps_au_infty != 0. ) ) { + if ( ( this->eps_cas0 != 0. ) || ( this->b4_eps_au_infty != 0. ) || ( this->autoShrinkageTF ) ) { if ( this->eps_cas0 != 0. ) { this->computeFibAutogenousShrinkageStrainVector(eps_as, gp, tStep); } else if ( this->b4_eps_au_infty != 0. ) { this->computeB4AutogenousShrinkageStrainVector(eps_as, gp, tStep); + } else if ( this->autoShrinkageTF ) { + this->computeAutogenousShrinkageDefinedByTF(eps_as, gp, tStep); } #ifdef keep_track_of_strains @@ -526,24 +551,24 @@ MPSMaterial :: giveShrinkageStrainVector(FloatArray &answer, fullAnswer.at(1) = fullAnswer.at(2) = fullAnswer.at(3) = status->giveAutogenousShrinkageStrain() + autoShrIncr + status->giveDryingShrinkageStrain() + dryShrIncr; } - StructuralMaterial :: giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() ); + StructuralMaterial::giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() ); } return; } MaterialStatus * -MPSMaterial :: CreateStatus(GaussPoint *gp) const +MPSMaterial::CreateStatus(GaussPoint *gp) const /* * creates a new material status corresponding to this class */ { - return new MPSMaterialStatus(1, this->giveDomain(), gp, nUnits); + return new MPSMaterialStatus(gp, nUnits); } void -MPSMaterial :: predictParametersFrom(double fc, double c, double wc, double ac) +MPSMaterial::predictParametersFrom(double fc, double c, double wc, double ac) { /* * Prediction of model parameters - estimation from concrete composition @@ -571,42 +596,46 @@ MPSMaterial :: predictParametersFrom(double fc, double c, double wc, double ac) q3 = 0.29 * pow(wc, 4.) * q2; q4 = 1.e-12 * this->stiffnessFactor * 20.3 * pow(ac, -0.7); - char buff [ 1024 ]; + char buff[ 1024 ]; sprintf(buff, "q1=%lf q2=%lf q3=%lf q4=%lf", q1, q2, q3, q4); OOFEM_LOG_DEBUG("MPS[%d]: estimated params: %s\n", this->number, buff); + OOFEM_LOG_DEBUG( "E28: %f\n", 1. / computeCreepFunction(this->lambda0 * ( 28. + 0.01 ), this->lambda0 * 28., NULL, NULL) ); } - double -MPSMaterial :: computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) +MPSMaterial::computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const { // computes the value of creep function at time t // when load is acting from time t_prime // t-t_prime = duration of loading - double Qf, Z, r, Q, C0; - double n, m; + // standard expressions which work with days - need to incorporate lambda0 to work in general - m = 0.5; - n = 0.1; + double m = 0.5; + double n = 0.1; // basic creep + double Qf = 1. / ( 0.086 * pow(t_prime / this->lambda0, 2. / 9.) + 1.21 * pow(t_prime / this->lambda0, 4. / 9.) ); + double Z = pow(t_prime / this->lambda0, -m) * log( 1. + pow(t / this->lambda0 - t_prime / this->lambda0, n) ); + double r = 1.7 * pow(t_prime / this->lambda0, 0.12) + 8.0; + double Q = Qf * pow( ( 1. + pow( ( Qf / Z ), r) ), -1. / r); - Qf = 1. / ( 0.086 * pow(t_prime, 2. / 9.) + 1.21 * pow(t_prime, 4. / 9.) ); - Z = pow(t_prime, -m) * log( 1. + pow(t - t_prime, n) ); - r = 1.7 * pow(t_prime, 0.12) + 8.0; - Q = Qf * pow( ( 1. + pow( ( Qf / Z ), r ) ), -1. / r ); - - C0 = q2 * Q + q3 *log( 1. + pow(t - t_prime, n) ) + q4 *log(t / t_prime); + double C0 = q2 * Q + q3 * log( 1. + pow(t / this->lambda0 - t_prime / this->lambda0, n) ) + q4 * log(t / t_prime); - return ( q1 + C0 ); + return q1 + C0; } +double +MPSMaterial::giveEquivalentTime(GaussPoint *gp, TimeStep *tStep) const +{ + return this->computeEquivalentTime(gp, tStep, 0); +} + void -MPSMaterial :: computeCharTimes() +MPSMaterial::computeCharTimes() { /* * This function generates discrete characteristic times @@ -614,11 +643,6 @@ MPSMaterial :: computeCharTimes() * of the relaxation or creep function by the Dirichlet series */ - int mu; - double Tau1; - int j; - - if ( this->begOfTimeOfInterest == -1. ) { this->begOfTimeOfInterest = 0.01 * lambda0; } @@ -628,12 +652,12 @@ MPSMaterial :: computeCharTimes() } //first retardation time found in given by formula 0.3 * begOfTimeOfInterest - Tau1 = 0.3 * this->begOfTimeOfInterest; + double Tau1 = 0.3 * this->begOfTimeOfInterest; //last retardation time has to be bigger than 0.5 * endOfTimeOfInterest - this->endOfTimeOfInterest = RheoChainMaterial :: giveEndOfTimeOfInterest(); + this->endOfTimeOfInterest = RheoChainMaterial::giveEndOfTimeOfInterest(); - j = 1; + int j = 1; while ( 0.5 * this->endOfTimeOfInterest >= Tau1 * pow( 10.0, ( double ) ( j - 1 ) ) ) { j++; } @@ -643,42 +667,39 @@ MPSMaterial :: computeCharTimes() this->charTimes.resize(this->nUnits); this->charTimes.zero(); - for ( mu = 1; mu <= this->nUnits; mu++ ) { + for ( int mu = 1; mu <= this->nUnits; mu++ ) { charTimes.at(mu) = Tau1 * pow(10., mu - 1); } } -void -MPSMaterial :: computeCharCoefficients(FloatArray &answer, double tPrime, GaussPoint *gp, TimeStep *tStep) +FloatArray +MPSMaterial::computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const { - int mu; - double tau0, tauMu; - // constant "n" is assumed to be equal to 0.1 (typical value) // modulus of elasticity of the first unit of Kelvin chain. // (aging elastic spring with retardation time = 0) double lambda0ToPowN = pow(lambda0, 0.1); - tau0 = pow(2 * this->giveCharTime(1) / sqrt(10.0), 0.1); + double tau0 = pow(2 * this->giveCharTime(1) / sqrt(10.0), 0.1); EspringVal = 1. / ( q2 * log(1.0 + tau0 / lambda0ToPowN) - q2 * tau0 / ( 10.0 * lambda0ToPowN + 10.0 * tau0 ) ); // evaluation of moduli of elasticity for the remaining units // (Solidifying kelvin units with retardation times tauMu) - answer.resize(nUnits); - answer.zero(); - for ( mu = 1; mu <= this->nUnits; mu++ ) { - tauMu = pow(2 * this->giveCharTime(mu), 0.1); + FloatArray answer(nUnits); + for ( int mu = 1; mu <= this->nUnits; mu++ ) { + double tauMu = pow(2 * this->giveCharTime(mu), 0.1); answer.at(mu) = 10. * pow(1 + tauMu / lambda0ToPowN, 2) / ( log(10.0) * q2 * ( tauMu / lambda0ToPowN ) * ( 0.9 + tauMu / lambda0ToPowN ) ); this->charTimes.at(mu) *= 1.35; } answer.at(nUnits) /= 1.2; // modulus of the last unit is reduced + return answer; } double -MPSMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) +MPSMaterial::giveEModulus(GaussPoint *gp, TimeStep *tStep) const { /* * This function returns the incremental modulus for the given time increment. @@ -699,19 +720,28 @@ MPSMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) double Emodulus; MPSMaterialStatus *status = static_cast< MPSMaterialStatus * >( this->giveStatus(gp) ); - if ( !this->isActivated(tStep) ) { + if ( !Material::isActivated(tStep) ) { return 1.; // stresses are cancelled in giveRealStressVector; } + // check if the material AGE is positive in the middle of the time step + if ( tStep->isTheFirstStep() || ( !Material::isActivated( tStep->givePreviousStep() ) ) ) { + double atAge = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ); + if ( atAge <= 0. ) { + OOFEM_ERROR("Attempting to evaluate stiffness at negative age: %f. Refine time steps or change material definition!\n", atAge); + } + } + + if ( status->giveStoredEmodulusFlag() ) { Emodulus = status->giveStoredEmodulus(); } else { if ( EparVal.giveSize() == 0 ) { - this->updateEparModuli(0., gp, tStep); // stiffnesses are time independent (evaluated at time t = 0.) + this->updateEparModuli(0., gp, tStep); // stiffnesses are time independent (evaluated at time t = 0.) } // contribution of the solidifying Kelving chain - sum = KelvinChainSolidMaterial :: giveEModulus(gp, tStep); + sum = KelvinChainSolidMaterial::giveEModulus(gp, tStep); v = computeSolidifiedVolume(gp, tStep); @@ -727,7 +757,7 @@ MPSMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) // TRAPEZOIDAL INTEGRATION RULE // is the first time step or the material has been just activated (i.e. the previous time was less than casting time) - if ( tStep->isTheFirstStep() || ( tStep->giveIntrinsicTime() - tStep->giveTimeIncrement() - this->castingTime < 0. ) ) { + if ( tStep->isTheFirstStep() || ( !Material::isActivated( tStep->givePreviousStep() ) ) ) { // if ( tStep->isTheFirstStep() ) { etaR = this->giveInitViscosity(tStep) / this->computePsiR(gp, tStep, 0); } else { @@ -769,19 +799,17 @@ MPSMaterial :: giveEModulus(GaussPoint *gp, TimeStep *tStep) double -MPSMaterial :: computeSolidifiedVolume(GaussPoint *gp, TimeStep *tStep) +MPSMaterial::computeSolidifiedVolume(GaussPoint *gp, TimeStep *tStep) const // compute the relative volume of the solidified material at given age (in days) { - double m, alpha; - double atAge; // (equivalent age) - // standard values of exponents - empirical constants - m = 0.5; + double m = 0.5; - alpha = q3 / q2; + double alpha = q3 / q2; + double atAge; // (equivalent age) if ( this->CoupledAnalysis == Basic ) { - atAge = relMatAge + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ); + atAge = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ); } else { atAge = computeEquivalentTime(gp, tStep, 0); } @@ -791,57 +819,45 @@ MPSMaterial :: computeSolidifiedVolume(GaussPoint *gp, TimeStep *tStep) double -MPSMaterial :: computeBetaMu(GaussPoint *gp, TimeStep *tStep, int Mu) +MPSMaterial::computeBetaMu(GaussPoint *gp, TimeStep *tStep, int Mu) const { - double betaMu; - double deltaT; - double tauMu; - - deltaT = tStep->giveTimeIncrement(); + double deltaT = tStep->giveTimeIncrement(); if ( ( this->CoupledAnalysis == MPS_full ) || ( this->CoupledAnalysis == MPS_humidity ) || ( this->CoupledAnalysis == MPS_temperature ) ) { deltaT *= 0.5 * ( this->computePsiR(gp, tStep, 0) + this->computePsiR(gp, tStep, 1) ); } - tauMu = this->giveCharTime(Mu); + double tauMu = this->giveCharTime(Mu); if ( deltaT / tauMu > 30 ) { - betaMu = 0; + return 0; } else { - betaMu = exp(-( deltaT ) / tauMu); + return exp(-( deltaT ) / tauMu); } - - return betaMu; } double -MPSMaterial :: computeLambdaMu(GaussPoint *gp, TimeStep *tStep, int Mu) +MPSMaterial::computeLambdaMu(GaussPoint *gp, TimeStep *tStep, int Mu) const { - double lambdaMu; - double deltaT; - double tauMu; - - deltaT = tStep->giveTimeIncrement(); + double deltaT = tStep->giveTimeIncrement(); if ( ( this->CoupledAnalysis == MPS_full ) || ( this->CoupledAnalysis == MPS_humidity ) || ( this->CoupledAnalysis == MPS_temperature ) ) { deltaT *= 0.5 * ( this->computePsiR(gp, tStep, 0) + this->computePsiR(gp, tStep, 1) ); } - tauMu = this->giveCharTime(Mu); + double tauMu = this->giveCharTime(Mu); if ( deltaT / tauMu < 1.e-5 ) { - lambdaMu = 1 - 0.5 * ( deltaT / tauMu ) + 1 / 6 * ( pow(deltaT / tauMu, 2) ) - 1 / 24 * ( pow(deltaT / tauMu, 3) ); + return 1 - 0.5 * ( deltaT / tauMu ) + 1 / 6 * ( pow(deltaT / tauMu, 2) ) - 1 / 24 * ( pow(deltaT / tauMu, 3) ); } else if ( deltaT / tauMu > 30 ) { - lambdaMu = tauMu / deltaT; + return tauMu / deltaT; } else { - lambdaMu = ( 1.0 - exp(-( deltaT ) / tauMu) ) * tauMu / deltaT; + return ( 1.0 - exp(-( deltaT ) / tauMu) ) * tauMu / deltaT; } - - return lambdaMu; } double -MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) +MPSMaterial::computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) const { double eta = 0., tHalfStep; @@ -849,6 +865,7 @@ MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) double A = 0., B = 0.; double T_new = 0., T_old = 0., H_new = 0., H_old = 0.; double kT = 0.; + double kh = 0.; /* double eta, tHalfStep; @@ -860,7 +877,7 @@ MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) */ if ( this->CoupledAnalysis == Basic ) { - tHalfStep = relMatAge + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ); + tHalfStep = this->relMatAge - this->castingTime + ( tStep->giveTargetTime() - 0.5 * tStep->giveTimeIncrement() ); eta = tHalfStep / q4; } else if ( ( this->CoupledAnalysis == MPS_full ) || ( this->CoupledAnalysis == MPS_humidity ) || ( this->CoupledAnalysis == MPS_temperature ) ) { MPSMaterialStatus *status = static_cast< MPSMaterialStatus * >( this->giveStatus(gp) ); @@ -873,7 +890,7 @@ MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) } else { // the first time step or the material has been just activated (i.e. the previous time was less than casting time) // ask for an initial value of viscosity - if ( tStep->isTheFirstStep() || ( tStep->giveIntrinsicTime() - tStep->giveTimeIncrement() - this->castingTime < 0. ) ) { + if ( tStep->isTheFirstStep() || ( !Material::isActivated( tStep->givePreviousStep() ) ) ) { prevEta = this->giveInitViscosity(tStep); } else { // asks for the value of viscosity from the end of the last time-step @@ -884,15 +901,27 @@ MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) PsiS = this->computePsiS(gp, tStep); // evaluated in the middle of the time step if ( ( this->CoupledAnalysis == MPS_full ) || ( this->CoupledAnalysis == MPS_humidity ) ) { - H_new = this->giveHumidity(gp, tStep, 1); - H_old = this->giveHumidity(gp, tStep, 0); + if ( this->tau_nano > 0. ) { + H_new = this->giveHumidityNano(gp, tStep, 1); + H_old = this->giveHumidityNano(gp, tStep, 0); + } else { + H_new = this->giveHumidity(gp, tStep, 1); + H_old = this->giveHumidity(gp, tStep, 0); + } + + if ( ( status->giveHumMin() - H_new >= 0. ) || tStep->isTheFirstStep() || ( !Material::isActivated( tStep->givePreviousStep() ) ) ) { + status->setHumMin(H_new); + kh = 1.0; + } else { + kh = this->khc; + } } if ( ( this->CoupledAnalysis == MPS_full ) || ( this->CoupledAnalysis == MPS_temperature ) ) { T_new = this->giveTemperature(gp, tStep, 1); T_old = this->giveTemperature(gp, tStep, 0); - if ( ( status->giveTmax() - T_new <= 0. ) || tStep->isTheFirstStep() || ( tStep->giveIntrinsicTime() - tStep->giveTimeIncrement() - this->castingTime < 0. ) ) { + if ( ( status->giveTmax() - T_new <= 0. ) || tStep->isTheFirstStep() || ( !Material::isActivated( tStep->givePreviousStep() ) ) ) { status->setTmax(T_new); kT = kTm; } else { @@ -906,14 +935,14 @@ MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) if ( this->CoupledAnalysis == MPS_full ) { if ( kTm == -1. ) { - A = sqrt( muS * fabs( ( T_new + T_old ) * ( H_new - H_old ) / ( H_new + H_old ) + log( ( H_new + H_old ) / 2. ) * ( T_new - T_old ) ) / ( dt * this->roomTemperature ) ); + A = sqrt( muS * fabs( ( T_new + T_old ) * kh * ( H_new - H_old ) / ( H_new + H_old ) + log( ( H_new + H_old ) / 2.) * ( T_new - T_old ) ) / ( dt * this->roomTemperature ) ); } else { - A = sqrt( muS * fabs( ( T_new + T_old ) * ( H_new - H_old ) / ( H_new + H_old ) - kT * ( T_new - T_old ) ) / ( dt * this->roomTemperature ) ); + A = sqrt( muS * fabs( ( T_new + T_old ) * kh * ( H_new - H_old ) / ( H_new + H_old ) - kT * ( T_new - T_old ) ) / ( dt * this->roomTemperature ) ); } B = sqrt(PsiS / this->q4); } else if ( this->CoupledAnalysis == MPS_humidity ) { // original version of the RHS for constant && room temperature - A = sqrt(muS * ( fabs( log(H_new) - log(H_old) ) ) / dt); + A = sqrt(muS * ( kh * fabs( log(H_new) - log(H_old) ) ) / dt); B = sqrt(PsiS / this->q4); } else if ( this->CoupledAnalysis == MPS_temperature ) { A = sqrt( muS * fabs( kT * ( T_new - T_old ) ) / ( dt * this->roomTemperature ) ); @@ -937,13 +966,13 @@ MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) if ( this->CoupledAnalysis == MPS_full ) { if ( kTm == -1. ) { - A = pow( muS, 1. / ( p - 1. ) ) * fabs( ( T_new + T_old ) * ( H_new - H_old ) / ( H_new + H_old ) + log( ( H_new + H_old ) / 2. ) * ( T_new - T_old ) ) / ( dt * this->roomTemperature ); + A = pow( muS, 1. / ( p - 1. ) ) * fabs( ( T_new + T_old ) * kh * ( H_new - H_old ) / ( H_new + H_old ) + log( ( H_new + H_old ) / 2.) * ( T_new - T_old ) ) / ( dt * this->roomTemperature ); } else { - A = pow( muS, 1. / ( p - 1. ) ) * fabs( ( T_new + T_old ) * ( H_new - H_old ) / ( H_new + H_old ) - kT * ( T_new - T_old ) ) / ( dt * this->roomTemperature ); + A = pow( muS, 1. / ( p - 1. ) ) * fabs( ( T_new + T_old ) * kh * ( H_new - H_old ) / ( H_new + H_old ) - kT * ( T_new - T_old ) ) / ( dt * this->roomTemperature ); } B = PsiS / this->q4; } else if ( this->CoupledAnalysis == MPS_humidity ) { - A = pow( muS, 1. / ( p - 1. ) ) * ( fabs( log(H_new) - log(H_old) ) ) / dt; + A = pow( muS, 1. / ( p - 1. ) ) * ( kh * fabs( log(H_new) - log(H_old) ) ) / dt; B = PsiS / this->q4; } else if ( this->CoupledAnalysis == MPS_temperature ) { A = pow( muS, 1. / ( p - 1. ) ) * fabs( kT * ( T_new - T_old ) ) / ( dt * this->roomTemperature ); @@ -958,8 +987,8 @@ MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) double relError = 1.; while ( relError > iterTol ) { - f = deltaEta / dt + A *pow( prevEta + 0.5 *deltaEta, p / ( p - 1. ) ) - B; - df = 1 / dt + A *p *pow( prevEta + 0.5 *deltaEta, 1. / ( p - 1. ) ) / ( 2. * ( p - 1. ) ); + f = deltaEta / dt + A * pow( prevEta + 0.5 * deltaEta, p / ( p - 1. ) ) - B; + df = 1 / dt + A * p * pow( prevEta + 0.5 * deltaEta, 1. / ( p - 1. ) ) / ( 2. * ( p - 1. ) ); deltaDeltaEta = -f / df; deltaEta += deltaDeltaEta; @@ -982,14 +1011,18 @@ MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) if ( this->CoupledAnalysis == MPS_full ) { if ( kTm == -1. ) { - A = pow( muS, 1. / ( p - 1. ) ) * fabs( T_new * log(H_new) - T_old * log(H_old) ) / ( dt * this->roomTemperature ); + if ( kh < 1. ) { + A = ( fabs(log( ( H_new + H_old ) / 2.) ) * fabs(T_new - T_old) + 0.5 * ( T_new + T_old ) * kh * fabs( log(H_new) - log(H_old) ) ) * pow( muS, 1. / ( p - 1. ) ) / ( dt * this->roomTemperature ); + } else { // kh == 1 + A = pow( muS, 1. / ( p - 1. ) ) * fabs( T_new * log(H_new) - T_old * log(H_old) ) / ( dt * this->roomTemperature ); + } } else { - A = ( kT * fabs(T_new - T_old) + 0.5 * ( T_new + T_old ) * fabs( log(H_new) - log(H_old) ) ) * pow( muS, 1. / ( p - 1. ) ) / ( dt * this->roomTemperature ); + A = ( kT * fabs(T_new - T_old) + 0.5 * ( T_new + T_old ) * kh * fabs( log(H_new) - log(H_old) ) ) * pow( muS, 1. / ( p - 1. ) ) / ( dt * this->roomTemperature ); } B = PsiS / this->q4; } else if ( this->CoupledAnalysis == MPS_humidity ) { - A = ( fabs( log(H_new) - log(H_old) ) ) * pow( muS, 1. / ( p - 1. ) ) / dt; + A = ( kh * fabs( log(H_new) - log(H_old) ) ) * pow( muS, 1. / ( p - 1. ) ) / dt; B = PsiS / this->q4; } else if ( this->CoupledAnalysis == MPS_temperature ) { A = kT * fabs(T_new - T_old) * pow( muS, 1. / ( p - 1. ) ) / ( dt * this->roomTemperature ); @@ -1005,8 +1038,8 @@ MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) double minEta = 1.e-6; while ( relError > iterTol ) { - f = deltaEta / dt + A *pow( prevEta + deltaEta, p / ( p - 1. ) ) - B; - df = 1 / dt + A *pow( prevEta + deltaEta, 1. / ( p - 1. ) ) * p / ( p - 1. ); + f = deltaEta / dt + A * pow( prevEta + deltaEta, p / ( p - 1. ) ) - B; + df = 1 / dt + A * pow( prevEta + deltaEta, 1. / ( p - 1. ) ) * p / ( p - 1. ); deltaDeltaEta = -f / df; deltaEta += deltaDeltaEta; @@ -1030,16 +1063,20 @@ MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) if ( this->CoupledAnalysis == MPS_full ) { // original version of the RHS for variable/elevated temperature if ( kTm == -1. ) { - A = k3 * fabs( T_new * log(H_new) - T_old * log(H_old) ) / ( dt * this->roomTemperature ); + if ( kh < 1. ) { + A = k3 * ( fabs(log( ( H_new + H_old ) / 2.) ) * fabs(T_new - T_old) + 0.5 * ( T_new + T_old ) * kh * fabs( log(H_new) - log(H_old) ) ) / ( dt * this->roomTemperature ); + } else { // kh == 1 + A = k3 * fabs( T_new * log(H_new) - T_old * log(H_old) ) / ( dt * this->roomTemperature ); + } } else { - A = k3 * ( kT * fabs(T_new - T_old) + 0.5 * ( T_new + T_old ) * fabs( log(H_new) - log(H_old) ) ) / ( dt * this->roomTemperature ); + A = k3 * ( kT * fabs(T_new - T_old) + 0.5 * ( T_new + T_old ) * kh * fabs( log(H_new) - log(H_old) ) ) / ( dt * this->roomTemperature ); } B = PsiS / this->q4; } else if ( this->CoupledAnalysis == MPS_humidity ) { // original version of the RHS for constant && room temperature // compiler warning: - A = k3 * ( fabs( log(H_new) - log(H_old) ) ) / dt; + A = k3 * ( kh * fabs( log(H_new) - log(H_old) ) ) / dt; B = PsiS / this->q4; } else if ( this->CoupledAnalysis == MPS_temperature ) { A = k3 * kT * fabs(T_new - T_old) / ( dt * this->roomTemperature ); @@ -1081,7 +1118,7 @@ MPSMaterial :: computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) // returns initial value of the flow term viscosity double -MPSMaterial :: giveInitViscosity(TimeStep *tStep) +MPSMaterial::giveInitViscosity(TimeStep *tStep) const { if ( ( t0 - tStep->giveTimeIncrement() ) <= 0. ) { OOFEM_ERROR("length of the first time step increment %e must be smaller than t0 %e", tStep->giveTimeIncrement(), t0); @@ -1092,7 +1129,7 @@ MPSMaterial :: giveInitViscosity(TimeStep *tStep) void -MPSMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +MPSMaterial::giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const // // computes the strain due to creep at constant stress during the increment // (in fact, the INCREMENT of creep strain is computed for mode == VM_Incremental) @@ -1123,7 +1160,7 @@ MPSMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeSte // TRAPEZOIDAL INTEGRATION RULE // if ( tStep->isTheFirstStep() ) { // is the first time step or the material has been just activated (i.e. the previous time was less than casting time) - if ( tStep->isTheFirstStep() || ( tStep->giveIntrinsicTime() - tStep->giveTimeIncrement() - this->castingTime < 0. ) ) { + if ( tStep->isTheFirstStep() || ( !Material::isActivated( tStep->givePreviousStep() ) ) ) { etaR = this->giveInitViscosity(tStep) / this->computePsiR(gp, tStep, 0); } else { etaR = status->giveFlowTermViscosity() / this->computePsiR(gp, tStep, 0); @@ -1152,7 +1189,7 @@ MPSMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeSte } //computes creep component of the Kelvin Chain - KelvinChainSolidMaterial :: giveEigenStrainVector(KelvinEigenStrain, gp, tStep, mode); + KelvinChainSolidMaterial::giveEigenStrainVector(KelvinEigenStrain, gp, tStep, mode); reducedAnswer.add(KelvinEigenStrain); answer = reducedAnswer; @@ -1160,25 +1197,28 @@ MPSMaterial :: giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeSte #ifdef keep_track_of_strains status->setCreepStrainIncrement(answer); #endif - } else { - /* error - total mode not implemented yet */ - OOFEM_ERROR("mode is not supported"); +#ifndef keep_track_of_strains + OOFEM_ERROR("for total formulation of shrinkage strains need to define keep_track_of_strains"); +#else + answer = status->giveCreepStrain(); + this->giveEigenStrainVector(reducedAnswer, gp, tStep, VM_Incremental); + answer.add(reducedAnswer); + return; + +#endif } } void -MPSMaterial :: computePointShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +MPSMaterial::computePointShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const { /* dEpsSh/dt = kSh * dh/dt (h = humidity) * ->> EpsSh = kSh * h_difference */ - double humDiff, EpsSh; int size; - FloatArray fullAnswer; MaterialMode mMode = gp->giveMaterialMode(); - double h, kShFactor; if ( ( mMode == _3dShell ) || ( mMode == _3dBeam ) || ( mMode == _2dPlate ) || ( mMode == _2dBeam ) ) { size = 12; @@ -1186,19 +1226,34 @@ MPSMaterial :: computePointShrinkageStrainVector(FloatArray &answer, GaussPoint size = 6; } + double kShFactor = 1.; if ( this->sh_a != 1. ) { - h = this->giveHumidity(gp, tStep, 2); - kShFactor = sh_a + ( 1. - sh_a ) / ( 1. + pow( ( 1. - h ) / ( 1. - sh_hC ), sh_n ) ); - } else { - kShFactor = 1.; + double h = this->giveHumidity(gp, tStep, 2); + kShFactor = sh_a + ( 1. - sh_a ) / ( 1. + pow( ( 1. - h ) / ( 1. - sh_hC ), sh_n) ); + } + + + if ( ksh_h.giveSize() >= 2 ) { + double h = this->giveHumidity(gp, tStep, 2); + double tol = 1.e-10; + for ( int i = 2; i <= ksh_h.giveSize(); i++ ) { + if ( ( h - ksh_h.at(i) ) < tol ) { + kShFactor *= ksh_fh.at(i - 1) + ( h - ksh_h.at(i - 1) ) * ( ksh_fh.at(i) - ksh_fh.at(i - 1) ) / ( ksh_h.at(i) - ksh_h.at(i - 1) ); + break; + } + } } - humDiff = this->giveHumidity(gp, tStep, 3); + if ( this->timeDependent_ksh ) { + double te = this->computeEquivalentTime(gp, tStep, 0); + kShFactor *= MPSMaterial::computeCreepFunction(te + 0.01 * this->lambda0, te, gp, tStep) / MPSMaterial::computeCreepFunction(28.01 * this->lambda0, 28. * this->lambda0, gp, tStep); + } + + double humDiff = this->giveHumidity(gp, tStep, 3); - EpsSh = humDiff * kSh * kShFactor; + double EpsSh = humDiff * kSh * kShFactor; - fullAnswer.resize(size); - fullAnswer.zero(); + FloatArray fullAnswer(size); if ( ( mMode == _2dLattice ) || ( mMode == _3dLattice ) ) { fullAnswer.at(1) = EpsSh; @@ -1206,11 +1261,11 @@ MPSMaterial :: computePointShrinkageStrainVector(FloatArray &answer, GaussPoint fullAnswer.at(1) = fullAnswer.at(2) = fullAnswer.at(3) = EpsSh; } - StructuralMaterial :: giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() ); + StructuralMaterial::giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() ); } void -MPSMaterial :: computeFibAutogenousShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +MPSMaterial::computeFibAutogenousShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const { /* from fib MC 2010: equations 5.1-76, 5.1-79 * eps_cas(t) = eps_cas0 * beta_as(t) @@ -1219,26 +1274,20 @@ MPSMaterial :: computeFibAutogenousShrinkageStrainVector(FloatArray &answer, Gau * ->> d_eps_cas(t) = eps_cas0 * [ -exp(-0.2 * sqrt(t_e_n+1) ) + exp(-0.2 * sqrt(t_e_n) ) ] */ - double eps_cas; - int size; - FloatArray fullAnswer; MaterialMode mMode = gp->giveMaterialMode(); - double t_equiv_beg, t_equiv_end; - - if ( ( mMode == _3dShell ) || ( mMode == _3dBeam ) || ( mMode == _2dPlate ) || ( mMode == _2dBeam ) ) { size = 12; } else { size = 6; } - + double t_equiv_beg, t_equiv_end; // if ( tStep->isTheFirstStep() ) { // is the first time step or the material has been just activated (i.e. the previous time was less than casting time) - if ( tStep->isTheFirstStep() || ( tStep->giveIntrinsicTime() - tStep->giveTimeIncrement() - this->castingTime < 0. ) ) { - t_equiv_beg = relMatAge - tStep->giveTimeIncrement(); + if ( tStep->isTheFirstStep() || ( !Material::isActivated( tStep->givePreviousStep() ) ) ) { + t_equiv_beg = this->relMatAge - tStep->giveTimeIncrement(); } else { MPSMaterialStatus *status = static_cast< MPSMaterialStatus * >( this->giveStatus(gp) ); t_equiv_beg = status->giveEquivalentTime(); @@ -1250,10 +1299,9 @@ MPSMaterial :: computeFibAutogenousShrinkageStrainVector(FloatArray &answer, Gau // time must be converted into days t_equiv_end /= this->lambda0; - eps_cas = eps_cas0 * ( -exp( -0.2 * sqrt(t_equiv_end) ) + exp( -0.2 * sqrt(t_equiv_beg) ) ); + double eps_cas = eps_cas0 * ( -exp( -0.2 * sqrt(t_equiv_end) ) + exp( -0.2 * sqrt(t_equiv_beg) ) ); - fullAnswer.resize(size); - fullAnswer.zero(); + FloatArray fullAnswer(size); if ( ( mMode == _2dLattice ) || ( mMode == _3dLattice ) ) { fullAnswer.at(1) = eps_cas; @@ -1261,13 +1309,12 @@ MPSMaterial :: computeFibAutogenousShrinkageStrainVector(FloatArray &answer, Gau fullAnswer.at(1) = fullAnswer.at(2) = fullAnswer.at(3) = eps_cas; } - - StructuralMaterial :: giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() ); + StructuralMaterial::giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() ); } void -MPSMaterial :: computeB4AutogenousShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +MPSMaterial::computeB4AutogenousShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const { /* from Bazant's B4 model (ver. Dec 2014): equations 23-25 and Table 2 * eps_au(t) = eps_au_infty * [ 1 + (tau_au / t_eq)^alpha ]^r_t @@ -1275,26 +1322,19 @@ MPSMaterial :: computeB4AutogenousShrinkageStrainVector(FloatArray &answer, Gaus * eps_au_infty = -eps_au_cem * (ac/6)^r_ea * (wc/0.38)^r_ew * tau_au = tau_au_cem * (wc/0.38)^r_tw */ - - double eps_au; - int size; - FloatArray fullAnswer; MaterialMode mMode = gp->giveMaterialMode(); - double t_equiv_beg, t_equiv_end; - if ( ( mMode == _3dShell ) || ( mMode == _3dBeam ) || ( mMode == _2dPlate ) || ( mMode == _2dBeam ) ) { size = 12; } else { size = 6; } - // if ( tStep->isTheFirstStep() ) { - // is the first time step or the material has been just activated (i.e. the previous time was less than casting time) - if ( tStep->isTheFirstStep() || ( tStep->giveIntrinsicTime() - tStep->giveTimeIncrement() - this->castingTime < 0. ) ) { - t_equiv_beg = relMatAge - tStep->giveTimeIncrement(); + double t_equiv_beg, t_equiv_end; + if ( tStep->isTheFirstStep() || ( !Material::isActivated( tStep->givePreviousStep() ) ) ) { + t_equiv_beg = this->relMatAge - tStep->giveTimeIncrement(); } else { MPSMaterialStatus *status = static_cast< MPSMaterialStatus * >( this->giveStatus(gp) ); t_equiv_beg = status->giveEquivalentTime(); @@ -1302,10 +1342,9 @@ MPSMaterial :: computeB4AutogenousShrinkageStrainVector(FloatArray &answer, Gaus t_equiv_end = this->computeEquivalentTime(gp, tStep, 1); // t_equiv_beg, t_equiv_end and b4_tau_au are in time-units of the analysis - eps_au = b4_eps_au_infty * ( pow(1. + pow(b4_tau_au / t_equiv_end, b4_alpha), b4_r_t) - pow(1. + pow(b4_tau_au / t_equiv_beg, b4_alpha), b4_r_t) ); + double eps_au = b4_eps_au_infty * ( pow(1. + pow(b4_tau_au / t_equiv_end, b4_alpha), b4_r_t) - pow(1. + pow(b4_tau_au / t_equiv_beg, b4_alpha), b4_r_t) ); - fullAnswer.resize(size); - fullAnswer.zero(); + FloatArray fullAnswer(size); if ( ( mMode == _2dLattice ) || ( mMode == _3dLattice ) ) { fullAnswer.at(1) = eps_au; @@ -1313,13 +1352,50 @@ MPSMaterial :: computeB4AutogenousShrinkageStrainVector(FloatArray &answer, Gaus fullAnswer.at(1) = fullAnswer.at(2) = fullAnswer.at(3) = eps_au; } + StructuralMaterial::giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() ); +} + +void +MPSMaterial::computeAutogenousShrinkageDefinedByTF(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const +{ + int size; + MaterialMode mMode = gp->giveMaterialMode(); + + if ( ( mMode == _3dShell ) || ( mMode == _3dBeam ) || ( mMode == _2dPlate ) || ( mMode == _2dBeam ) ) { + size = 12; + } else { + size = 6; + } + + // is the first time step or the material has been just activated (i.e. the previous time was less than casting time) + double t_equiv_beg, t_equiv_end; + if ( tStep->isTheFirstStep() || ( !Material::isActivated( tStep->givePreviousStep() ) ) ) { + t_equiv_beg = this->relMatAge - tStep->giveTimeIncrement(); + } else { + MPSMaterialStatus *status = static_cast< MPSMaterialStatus * >( this->giveStatus(gp) ); + t_equiv_beg = status->giveEquivalentTime(); + } + + t_equiv_end = this->computeEquivalentTime(gp, tStep, 1); + + double eps_au = domain->giveFunction(this->autoShrinkageTF)->evaluateAtTime(t_equiv_end); + eps_au -= domain->giveFunction(this->autoShrinkageTF)->evaluateAtTime(t_equiv_beg); - StructuralMaterial :: giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() ); + FloatArray fullAnswer(size); + + if ( ( mMode == _2dLattice ) || ( mMode == _3dLattice ) ) { + fullAnswer.at(1) = eps_au; + } else { + fullAnswer.at(1) = fullAnswer.at(2) = fullAnswer.at(3) = eps_au; + } + + StructuralMaterial::giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() ); } -// double -// MPSMaterial :: inverse_sorption_isotherm(double w) +#if 0 +double +MPSMaterial::inverse_sorption_isotherm const // Function calculates relative humidity from water content (inverse relation form sorption isotherm). // Relative humidity (phi) is from range 0.2 - 0.98 !!! // sorption isotherm by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, @@ -1327,21 +1403,22 @@ MPSMaterial :: computeB4AutogenousShrinkageStrainVector(FloatArray &answer, Gaus // w (kg/kg) ... water content // phi ... relative humidity // w_h, n, a ... constants obtained from experiments -//{ -// relative humidity -// double phi = exp( a * ( 1.0 - pow( ( w_h / w ), ( n ) ) ) ); -// -// /*if ( ( phi < 0.2 ) || ( phi > 0.98 ) ) { -// * OOFEM_ERROR("Relative humidity h = %e (w=%e) is out of range", phi, w); -// * }*/ -// //if ( phi < 0.20 ){ phi = 0.2;} -// //if ( phi > 0.98 ){ phi = 0.98;} -// -// return phi; -//} +{ + //relative humidity + double phi = exp( a * ( 1.0 - pow( ( w_h / w ), ( n ) ) ) ); + + /*if ( ( phi < 0.2 ) || ( phi > 0.98 ) ) { + * OOFEM_ERROR("Relative humidity h = %e (w=%e) is out of range", phi, w); + * }*/ + //if ( phi < 0.20 ){ phi = 0.2;} + //if ( phi > 0.98 ){ phi = 0.98;} + + return phi; +} +#endif double -MPSMaterial :: giveHumidity(GaussPoint *gp, TimeStep *tStep, int option) +MPSMaterial::giveHumidity(GaussPoint *gp, TimeStep *tStep, int option) const { double H_tot = 0.0, H_inc = 0.0; @@ -1401,8 +1478,62 @@ MPSMaterial :: giveHumidity(GaussPoint *gp, TimeStep *tStep, int option) return 0.; // happy compiler } + double -MPSMaterial :: giveTemperature(GaussPoint *gp, TimeStep *tStep, int option) +MPSMaterial::giveHumidityNano(GaussPoint *gp, TimeStep *tStep, int option) const +{ + MPSMaterialStatus *status = static_cast< MPSMaterialStatus * >( this->giveStatus(gp) ); + + double h_nano_beg, h_nano_end; + + double h_beg = this->giveHumidity(gp, tStep, 0); + double h_end = this->giveHumidity(gp, tStep, 1); + + // is the first time step or the material has been just activated (i.e. the previous time was less than casting time) + if ( tStep->isTheFirstStep() || ( !Material::isActivated( tStep->givePreviousStep() ) ) ) { + h_nano_beg = h_beg; + } else { + h_nano_beg = status->giveHumNano(); + } + + double deltaT = tStep->giveTimeIncrement(); + double beta, lambda; + + if ( deltaT / this->tau_nano > 30 ) { + beta = 0.; + } else { + beta = exp(-( deltaT ) / this->tau_nano); + } + + if ( deltaT / this->tau_nano < 1.e-5 ) { + lambda = 1. - 0.5 * ( deltaT / this->tau_nano ) + 1. / 6. * ( pow(deltaT / this->tau_nano, 2) ) - 1. / 24. * ( pow(deltaT / this->tau_nano, 3) ); + } else if ( deltaT / this->tau_nano > 30. ) { + lambda = this->tau_nano / deltaT; + } else { + lambda = ( 1.0 - beta ) * this->tau_nano / deltaT; + } + + h_nano_end = h_nano_beg + ( 1. - lambda ) * ( h_end - h_beg ) + ( 1. - beta ) * ( h_beg - h_nano_beg ); + + status->setHumNanoTemp(h_nano_end); + + switch ( option ) { + case 0: return h_nano_beg; // returns relative humidity IN THE NANOPORES on the BEGINNING of the time step + + case 1: return h_nano_end; // returns relative humidity IN THE NANOPORES in the END of the time step + + case 2: return 0.5 * ( h_nano_beg + h_nano_end ); // returns relative humidity IN THE NANOPORES in the middle of the time step = AVERAGE + + case 3: return ( h_nano_end - h_nano_beg ); // returns relative humidity IN THE NANOPORES INCREMENT + + default: OOFEM_ERROR("option %d not supported", option); + } + + return 0.; // happy compiler +} + +double +MPSMaterial::giveTemperature(GaussPoint *gp, TimeStep *tStep, int option) const { double T_tot = 0.0, T_inc = 0.0; MPSMaterialStatus *status = static_cast< MPSMaterialStatus * >( this->giveStatus(gp) ); @@ -1460,24 +1591,31 @@ MPSMaterial :: giveTemperature(GaussPoint *gp, TimeStep *tStep, int option) } double -MPSMaterial :: computePsiR(GaussPoint *gp, TimeStep *tStep, int option) +MPSMaterial::computePsiR(GaussPoint *gp, TimeStep *tStep, int option) const { - double H, T; - double betaRH, betaRT; - if ( this->CoupledAnalysis == MPS_humidity ) { - H = this->giveHumidity(gp, tStep, option); - betaRH = alphaR + ( 1. - alphaR ) * H * H; + double H = 0.; + if ( this->tau_nano > 0. ) { + H = this->giveHumidityNano(gp, tStep, option); + } else { + H = this->giveHumidity(gp, tStep, option); + } + double betaRH = alphaR + ( 1. - alphaR ) * H * H; return betaRH; } else if ( this->CoupledAnalysis == MPS_temperature ) { - T = this->giveTemperature(gp, tStep, option); - betaRT = exp( QRtoR * ( 1. / this->roomTemperature - 1. / T ) ); + double T = this->giveTemperature(gp, tStep, option); + double betaRT = exp( QRtoR * ( 1. / this->roomTemperature - 1. / T ) ); return betaRT; } else if ( this->CoupledAnalysis == MPS_full ) { - H = this->giveHumidity(gp, tStep, option); - T = this->giveTemperature(gp, tStep, option); - betaRH = alphaR + ( 1. - alphaR ) * H * H; - betaRT = exp( QRtoR * ( 1. / this->roomTemperature - 1. / T ) ); + double H = 0.; + if ( this->tau_nano > 0. ) { + H = this->giveHumidityNano(gp, tStep, option); + } else { + H = this->giveHumidity(gp, tStep, option); + } + double T = this->giveTemperature(gp, tStep, option); + double betaRH = alphaR + ( 1. - alphaR ) * H * H; + double betaRT = exp( QRtoR * ( 1. / this->roomTemperature - 1. / T ) ); return betaRH * betaRT; } else { OOFEM_ERROR("mode is not supported"); @@ -1486,24 +1624,32 @@ MPSMaterial :: computePsiR(GaussPoint *gp, TimeStep *tStep, int option) } double -MPSMaterial :: computePsiS(GaussPoint *gp, TimeStep *tStep) +MPSMaterial::computePsiS(GaussPoint *gp, TimeStep *tStep) const { - double AverageHum, AverageTemp; - double betaSH, betaST; - if ( this->CoupledAnalysis == MPS_humidity ) { - AverageHum = this->giveHumidity(gp, tStep, 2); - betaSH = alphaS + ( 1. - alphaS ) * AverageHum * AverageHum; + double AverageHum = 0.; + if ( this->tau_nano > 0. ) { + AverageHum = this->giveHumidityNano(gp, tStep, 2); + } else { + AverageHum = this->giveHumidity(gp, tStep, 2); + } + double betaSH = alphaS + ( 1. - alphaS ) * AverageHum * AverageHum; return betaSH; } else if ( this->CoupledAnalysis == MPS_temperature ) { - AverageTemp = this->giveTemperature(gp, tStep, 2); - betaST = exp( QStoR * ( 1. / this->roomTemperature - 1. / AverageTemp ) ); + double AverageTemp = this->giveTemperature(gp, tStep, 2); + double betaST = exp( QStoR * ( 1. / this->roomTemperature - 1. / AverageTemp ) ); return betaST; } else if ( this->CoupledAnalysis == MPS_full ) { - AverageHum = this->giveHumidity(gp, tStep, 2); - AverageTemp = this->giveTemperature(gp, tStep, 2); - betaSH = alphaS + ( 1. - alphaS ) * AverageHum * AverageHum; - betaST = exp( QStoR * ( 1. / this->roomTemperature - 1. / AverageTemp ) ); + double AverageHum = 0.; + if ( this->tau_nano > 0. ) { + AverageHum = this->giveHumidityNano(gp, tStep, 2); + } else { + AverageHum = this->giveHumidity(gp, tStep, 2); + } + + double AverageTemp = this->giveTemperature(gp, tStep, 2); + double betaSH = alphaS + ( 1. - alphaS ) * AverageHum * AverageHum; + double betaST = exp( QStoR * ( 1. / this->roomTemperature - 1. / AverageTemp ) ); return betaSH * betaST; } else { OOFEM_ERROR("mode is not supported"); @@ -1511,26 +1657,29 @@ MPSMaterial :: computePsiS(GaussPoint *gp, TimeStep *tStep) } } +//for equivalent time double -MPSMaterial :: computePsiE(GaussPoint *gp, TimeStep *tStep) +MPSMaterial::computePsiE(GaussPoint *gp, TimeStep *tStep) const { - double AverageHum, AverageTemp; - double betaEH, betaET; + double hydrationTimescale = 1.; + if ( hydrationTimescaleTF ) { + hydrationTimescale = domain->giveFunction(hydrationTimescaleTF)->evaluateAtTime(tStep->giveIntrinsicTime() ); + } if ( this->CoupledAnalysis == MPS_humidity ) { - AverageHum = this->giveHumidity(gp, tStep, 2); - betaEH = 1. / ( 1. + pow( ( alphaE * ( 1. - AverageHum ) ), 4. ) ); - return betaEH; + double AverageHum = this->giveHumidity(gp, tStep, 2); + double betaEH = 1. / ( 1. + pow( ( alphaE * ( 1. - AverageHum ) ), 4.) ); + return hydrationTimescale * betaEH; } else if ( this->CoupledAnalysis == MPS_temperature ) { - AverageTemp = this->giveTemperature(gp, tStep, 2); - betaET = exp( QEtoR * ( 1. / this->roomTemperature - 1. / AverageTemp ) ); - return betaET; + double AverageTemp = this->giveTemperature(gp, tStep, 2); + double betaET = exp( QEtoR * ( 1. / this->roomTemperature - 1. / AverageTemp ) ); + return hydrationTimescale * betaET; } else if ( this->CoupledAnalysis == MPS_full ) { - AverageHum = this->giveHumidity(gp, tStep, 2); - AverageTemp = this->giveTemperature(gp, tStep, 2); - betaEH = 1. / ( 1. + pow( ( alphaE * ( 1. - AverageHum ) ), 4. ) ); - betaET = exp( QEtoR * ( 1. / this->roomTemperature - 1. / AverageTemp ) ); - return betaEH * betaET; + double AverageHum = this->giveHumidity(gp, tStep, 2); + double AverageTemp = this->giveTemperature(gp, tStep, 2); + double betaEH = 1. / ( 1. + pow( ( alphaE * ( 1. - AverageHum ) ), 4.) ); + double betaET = exp( QEtoR * ( 1. / this->roomTemperature - 1. / AverageTemp ) ); + return hydrationTimescale * betaEH * betaET; } else { OOFEM_ERROR(" mode is not supported"); return 0.; @@ -1539,42 +1688,44 @@ MPSMaterial :: computePsiE(GaussPoint *gp, TimeStep *tStep) double -MPSMaterial :: computeEquivalentTime(GaussPoint *gp, TimeStep *tStep, int option) +MPSMaterial::computeEquivalentTime(GaussPoint *gp, TimeStep *tStep, int option) const { - double tEquiv = 0.; - double PsiE; + double PsiE = 1.; - PsiE = computePsiE(gp, tStep); + if ( ( this->CoupledAnalysis == MPS_full ) || ( this->CoupledAnalysis == MPS_humidity ) || + ( this->CoupledAnalysis == MPS_temperature ) ) { + PsiE = computePsiE(gp, tStep); + } // is the first time step or the material has been just activated (i.e. the previous time was less than casting time) - if ( tStep->isTheFirstStep() || ( tStep->giveIntrinsicTime() - tStep->giveTimeIncrement() - this->castingTime < 0. ) ) { + if ( tStep->isTheFirstStep() || ( !Material::isActivated( tStep->givePreviousStep() ) ) ) { if ( option == 0 ) { // gives time in the middle of the timestep - return relMatAge - tStep->giveTimeIncrement() + PsiE * ( 0.5 * tStep->giveTimeIncrement() ); + return this->relMatAge - tStep->giveTimeIncrement() + PsiE * ( 0.5 * tStep->giveTimeIncrement() ); } else if ( option == 1 ) { // gives time in the end of the timestep - for UPDATING - return relMatAge - tStep->giveTimeIncrement() + PsiE *tStep->giveTimeIncrement(); + return this->relMatAge - tStep->giveTimeIncrement() + PsiE * tStep->giveTimeIncrement(); } else { - OOFEM_ERROR("mode is not supported") + OOFEM_ERROR("mode is not supported"); + return 0.; } } else { MPSMaterialStatus *status = static_cast< MPSMaterialStatus * >( this->giveStatus(gp) ); - tEquiv = status->giveEquivalentTime(); + double tEquiv = status->giveEquivalentTime(); if ( option == 0 ) { // gives time in the middle of the timestep - tEquiv = tEquiv + PsiE * 0.5 * tStep->giveTimeIncrement(); + tEquiv += PsiE * 0.5 * tStep->giveTimeIncrement(); } else if ( option == 1 ) { // gives time on the end of the timestep - for UPDATING - tEquiv = tEquiv + PsiE *tStep->giveTimeIncrement(); + tEquiv += PsiE * tStep->giveTimeIncrement(); } else { OOFEM_ERROR("mode is not supported") } return tEquiv; } - return tEquiv; // happy compiler } int -MPSMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +MPSMaterial::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { MPSMaterialStatus *status = static_cast< MPSMaterialStatus * >( this->giveStatus(gp) ); if ( type == IST_DryingShrinkageTensor ) { @@ -1593,13 +1744,22 @@ MPSMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType answer.at(1) = answer.at(2) = answer.at(3) = status->giveAutogenousShrinkageStrain() + status->giveDryingShrinkageStrain(); return 1; } else if ( type == IST_CreepStrainTensor ) { - StructuralMaterial :: giveFullSymVectorForm( answer, status->giveCreepStrain(), gp->giveMaterialMode() ); - + StructuralMaterial::giveFullSymVectorForm( answer, status->giveCreepStrain(), gp->giveMaterialMode() ); + return 1; + } else if ( type == IST_IncrementCreepModulus ) { + answer.resize(1); + answer.zero(); + answer.at(1) = giveEModulus(gp, tStep); + status->giveStoredEmodulus(); + return 1; + } else if ( type == IST_EquivalentTime ) { + answer.resize(1); + answer.zero(); + answer.at(1) = status->giveEquivalentTime(); return 1; } else { - return RheoChainMaterial :: giveIPValue(answer, gp, type, tStep); + return RheoChainMaterial::giveIPValue(answer, gp, type, tStep); } - - return 1; // to make the compiler happy + return 0; // to make the compiler happy } } // end namespace oofem diff --git a/src/sm/Materials/RheoChainMaterials/mps.h b/src/sm/Materials/RheoChainMaterials/mps.h index 7056214ca..c31d1d5d6 100644 --- a/src/sm/Materials/RheoChainMaterials/mps.h +++ b/src/sm/Materials/RheoChainMaterials/mps.h @@ -55,11 +55,9 @@ #define _IFT_MPSMaterial_q3 "q3" #define _IFT_MPSMaterial_q4 "q4" #define _IFT_MPSMaterial_lambda0 "lambda0" -#define _IFT_MPSMaterial_t0 "t0" +// in input record t0 replaced by relMatAge +//#define _IFT_MPSMaterial_t0 "t0" #define _IFT_MPSMaterial_ksh "ksh" -//#define _IFT_MPSMaterial_wh "w_h" -//#define _IFT_MPSMaterial_ncoeff "ncoeff" -//#define _IFT_MPSMaterial_a "a" #define _IFT_MPSMaterial_qetor "qetor" #define _IFT_MPSMaterial_qrtor "qrtor" #define _IFT_MPSMaterial_qstor "qstor" @@ -69,6 +67,7 @@ #define _IFT_MPSMaterial_mus "mus" #define _IFT_MPSMaterial_ktm "ktm" #define _IFT_MPSMaterial_ktc "ktc" +#define _IFT_MPSMaterial_khc "khc" #define _IFT_MPSMaterial_stiffnessfactor "stiffnessfactor" #define _IFT_MPSMaterial_p "p" #define _IFT_MPSMaterial_p_tilde "p_tilde" @@ -76,6 +75,9 @@ #define _IFT_MPSMaterial_sh_a "sh_a" #define _IFT_MPSMaterial_sh_hC "sh_hc" #define _IFT_MPSMaterial_sh_n "sh_n" +#define _IFT_MPSMaterial_factor_ksh_h "factor_ksh_h" +#define _IFT_MPSMaterial_factor_ksh_fh "factor_ksh_f(h)" +#define _IFT_MPSMaterial_timedependent_ksh "timedependent_ksh" #define _IFT_MPSMaterial_alpha_as "alpha_as" #define _IFT_MPSMaterial_eps_cas0 "eps_cas0" #define _IFT_MPSMaterial_B4_eps_au_infty "b4_eps_au_infty" @@ -84,6 +86,9 @@ #define _IFT_MPSMaterial_B4_r_t "b4_r_t" #define _IFT_MPSMaterial_B4_cem_type "b4_cem_type" #define _IFT_MPSMaterial_temperInCelsius "temperincelsius" +#define _IFT_MPSMaterial_hydrationTimescaleTF "hydrationtimescaletf" +#define _IFT_MPSMaterial_autoShrinkageTF "autoshrinkagetf" +#define _IFT_MPSMaterial_tau_nano "tau_nano" //@} namespace oofem { @@ -97,40 +102,44 @@ namespace oofem { class MPSMaterialStatus : public KelvinChainSolidMaterialStatus { protected: - /// Values of humidity and temperature in a particular GP and their increment - double hum; - double hum_increment; - double T; - double T_increment; - double T_max; + /// Values of humidity and temperature in a particular GP, their increment, and maximum/minimum to treat cyclic ambient conditions + double hum = -1.; + double hum_increment = -1.; + double h_min = 1.; + double T = -1.; + double T_increment = -1.; + double T_max = 0.; /// Hidden variable - equivalent time: necessary to compute solidified volume - double equivalentTime; - double equivalentTimeTemp; - double flowTermViscosity; - double flowTermViscosityTemp; + double equivalentTime = 0.; + double equivalentTimeTemp = 0.; + double flowTermViscosity = 0.; + double flowTermViscosityTemp = -1.; /// flag for Emodulus - true if modulus has been already computed in the current time step - bool storedEmodulusFlag; - double storedEmodulus; + bool storedEmodulusFlag = false; + double storedEmodulus = -1.; + + /// value of relative humidity in the nanopores + double humNano = -1.; + double humNanoTemp = -1.; #ifdef keep_track_of_strains - double dryingShrinkageStrain; - double tempDryingShrinkageStrain; - double autogenousShrinkageStrain; - double tempAutogenousShrinkageStrain; + double dryingShrinkageStrain = 0.; + double tempDryingShrinkageStrain = 0.; + double autogenousShrinkageStrain = 0.; + double tempAutogenousShrinkageStrain = 0.; FloatArray creepStrain; FloatArray creepStrainIncrement; #endif public: - MPSMaterialStatus(int n, Domain *d, GaussPoint *g, int nunits); - virtual ~MPSMaterialStatus() { } + MPSMaterialStatus(GaussPoint *g, int nunits); - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; /// Returns relative humidity double giveHum() { return hum; } @@ -141,6 +150,18 @@ class MPSMaterialStatus : public KelvinChainSolidMaterialStatus /// Stores relative humidity increment void setHumIncrement(double src) { hum_increment = src; } + + /// Returns relative humidity (nanopores) + double giveHumNano() { return humNano; } + /// Stores relative humidity (nanopores) + void setHumNanoTemp(double src) { humNanoTemp = src; } + + /// Returns previously minimum previously reached humidity - treatment of cyclic ambient coditions + double giveHumMin() { return h_min; } + /// Stores minimum reached humidity + void setHumMin(double src) { h_min = src; } + + /// Returns temperature double giveT() { return T; } /// Stores temperature @@ -182,12 +203,12 @@ class MPSMaterialStatus : public KelvinChainSolidMaterialStatus double giveTempAutogenousShrinkageStrain(void) { return tempAutogenousShrinkageStrain; } double giveAutogenousShrinkageStrain(void) { return autogenousShrinkageStrain; } - void setCreepStrainIncrement(FloatArray src) { creepStrainIncrement = std :: move(src); } + void setCreepStrainIncrement(FloatArray src) { creepStrainIncrement = std::move(src); } const FloatArray &giveCreepStrain() const { return creepStrain; } #endif // definition - virtual const char *giveClassName() const { return "MPSMaterialStatus"; } + const char *giveClassName() const override { return "MPSMaterialStatus"; } }; @@ -204,146 +225,182 @@ class MPSMaterialStatus : public KelvinChainSolidMaterialStatus class MPSMaterial : public KelvinChainSolidMaterial { protected: - - /// age when temperature or humidity starts to change - double t0; + double t0 = 0.; /// compliances of the B3 model - double q1, q2, q3, q4; + double q1 = 0., q2 = 0., q3 = 0., q4 = 0.; /// constant equal to one day in time units of analysis (eg. 86400 if the analysis runs in seconds) - double lambda0; + double lambda0 = 0.; enum coupledAnalysisType { Basic, MPS_full, MPS_humidity, MPS_temperature } CoupledAnalysis; - double EspringVal; // elastic modulus of the aging spring (first member of Kelvin chain if retardation spectrum is used) + mutable double EspringVal = 0.; // elastic modulus of the aging spring (first member of Kelvin chain if retardation spectrum is used) /// additional parameters for sorption isotherm (used to compute relative humidity from water content) //double w_h, n, a; //constant (obtained from experiments) A [Pedersen, 1990] // MPS theory parameters /// proportionality parameter between change of humidity and shrinkage - double kSh; + double kSh = 0.; /// fluidity parameter used in viscosity evolution equation - double muS, k3; + double muS = 0., k3 = 0.; /// kTm replaces ln(h) on RHS of the differential equation describing evolution of MPS - double kTm; + double kTm = 0.; /// parameter reducing creep effects of thermal cycling (replaces kTm in such case) - double kTc; + double kTc = 0.; + /// parameter reducing creep effects of hygral cycling (0 = complete reduction, 1 = no reduction, default value) + double khc = 0.; /// parameter reducing creep effects of thermal cycling - double ct; + // commented - unused parameter? PH + //double ct = 0.; /// reference room temperature for MPS algorithm [K] - double roomTemperature; + double roomTemperature = 0.; /// activation energies - double QEtoR, QRtoR, QStoR; //[K] + double QEtoR = 0., QRtoR = 0., QStoR = 0.; //[K] /// parameters that control the effect of humidity on rates of hydration, creep and microprestress relaxation - double alphaE, alphaR, alphaS; //[-] + double alphaE = 0., alphaR = 0., alphaS = 0.; //[-] /// exponent in the microprestress/viscosity governing equation - double p; + double p = 0.; /// parameters for nonlinear shrinkage function - double sh_a, sh_hC, sh_n; + double sh_a = 0., sh_hC = 0., sh_n = 0.; + /// flag activating equivalent-time-dependence of shrinkage coefficient + bool timeDependent_ksh = false; + /// nonlinear shrinkage function - user-defined piecewise-linear function + FloatArray ksh_h, ksh_fh; /// parameter for autogenous shrinkage according to fib MC 2010 - double eps_cas0; + double eps_cas0 = 0.; /// parameters for autogenous shrinkage according to B4 model - double b4_eps_au_infty, b4_tau_au, b4_alpha, b4_r_t; + double b4_eps_au_infty = 0., b4_tau_au = 0., b4_alpha = 0., b4_r_t = 0.; /// scaling factor 1. for Pa, 1.e6 for MPa - only for empirical formulas - q1-q4 and ft and gf - double stiffnessFactor; + double stiffnessFactor = 0.; /// 0 for Kelvin, 273.15 for Celsius - double temperScaleDifference; + double temperScaleDifference = 0.; + /** + * Further scaling of creep, shrinkage, tensile strength etc. with regards to this time function. + * Let us assume two hydrating cements with different kinetics. If the fast cement is a reference one, + * the simulation of the slow one is carried out on the reference cement and scaling by + * this time function, which is then ≤1. Results from isothermal calorimetry are typically used for + * defining this function. + */ + int hydrationTimescaleTF; -public: - MPSMaterial(int n, Domain *d) : KelvinChainSolidMaterial(n, d) { } - virtual ~MPSMaterial() { } + /** + * Possibility to prescribe the evolution of autogenous shrinkage strain by an auxiliary time function, the function is evaluated according to the current value of the equivalenet age, i.e. maturity. + */ + int autoShrinkageTF; - virtual const char *giveInputRecordName() const { return _IFT_MPSMaterial_Name; } - virtual const char *giveClassName() const { return "MPSMaterial"; } + /** characteristic time defining delay of relative humidity in the nanopores behind the capillary pores + * alternative approach might initiate shrinakge cracking before the stresses relax + * hum_nano + tau_nano * d_hum_nano / d_t = hum + * hum_nano is obtained using second-order exponential algorithm originally developed for creep of Kelvin unit + */ + double tau_nano = 0.; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - //virtual void updateYourself(GaussPoint *gp, TimeStep *tStep); +public: + MPSMaterial(int n, Domain *d) : KelvinChainSolidMaterial(n, d) { } + const char *giveInputRecordName() const override { return _IFT_MPSMaterial_Name; } + const char *giveClassName() const override { return "MPSMaterial"; } + void initializeFrom(InputRecord &ir) override; - virtual void giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) override; + //void updateYourself(GaussPoint *gp, TimeStep *tStep) override; + + void giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; /// Evaluation of the basic creep compliance function - can be used to compute elastic modulus in derived damage material - virtual double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep); + double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const override; + + double giveEquivalentTime(GaussPoint *gp, TimeStep *tStep) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: void predictParametersFrom(double, double, double, double); - virtual void computeCharTimes(); + void computeCharTimes() override; /// Evaluation of characteristic moduli of the non-aging Kelvin chain - virtual void computeCharCoefficients(FloatArray &answer, double, GaussPoint *gp, TimeStep *tStep); + FloatArray computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const override; - virtual double giveEModulus(GaussPoint *gp, TimeStep *tStep); + double giveEModulus(GaussPoint *gp, TimeStep *tStep) const override; - virtual double computeSolidifiedVolume(GaussPoint *gp, TimeStep *tStep); + double computeSolidifiedVolume(GaussPoint *gp, TimeStep *tStep) const override; - virtual double computeBetaMu(GaussPoint *gp, TimeStep *tStep, int Mu); - virtual double computeLambdaMu(GaussPoint *gp, TimeStep *tStep, int Mu); + double computeBetaMu(GaussPoint *gp, TimeStep *tStep, int Mu) const override; + double computeLambdaMu(GaussPoint *gp, TimeStep *tStep, int Mu) const override; /// Evaluation of the flow term viscosity - double computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep); + double computeFlowTermViscosity(GaussPoint *gp, TimeStep *tStep) const; /// Returns initial value of the flow term viscosity - double giveInitViscosity(TimeStep *tStep); + double giveInitViscosity(TimeStep *tStep) const; - virtual void giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); - - virtual int hasIncrementalShrinkageFormulation() { return 1; } + void giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; + bool hasIncrementalShrinkageFormulation() const override { return true; } /// Evaluation of the shrinkageStrainVector - shrinkage is fully dependent on humidity rate in given GP - void computePointShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computePointShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const; /// Evaluation of the autogenousShrinkageStrainVector according to fib MC 2010 - autogenous shrinkage is fully dependent on the equivalent age at given GP - void computeFibAutogenousShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeFibAutogenousShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const; /// Evaluation of the autogenousShrinkageStrainVector according to Bazant's B4 model. In the model the evolution depends on temperature adjusted age, here on equivalent age (additional humidity influence) - void computeB4AutogenousShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + void computeB4AutogenousShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const; + + /// Evaluation of the autogenousShrinkageStrainVector given by an auxiliary time function (autoShrinkageTF parameter). The time scale in that time function corresponds to the equivalent material age. + void computeAutogenousShrinkageDefinedByTF(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) const; - //double inverse_sorption_isotherm(double w); + //double inverse_sorption_isotherm(double w) const; /// Gives value of humidity at given GP and timestep /// option = 0 ... beginning of the time step /// option = 1 ... end of the time step /// option = 2 ... average values /// option = 3 ... incremental values - double giveHumidity(GaussPoint *gp, TimeStep *tStep, int option); + double giveHumidity(GaussPoint *gp, TimeStep *tStep, int option) const; + + /// Gives value of humidity in the nanopores at given GP and timestep + /// for default value tau_nano = 0 hum_nano coincides with conventional pore humidity + /// option = 0 ... beginning of the time step + /// option = 1 ... end of the time step + /// option = 2 ... average values + /// option = 3 ... incremental values + double giveHumidityNano(GaussPoint *gp, TimeStep *tStep, int option) const; /// Gives value of temperature at given GP and timestep /// option = 0 ... beginning of the time step /// option = 1 ... end of the time step /// option = 2 ... average values /// option = 3 ... incremental values - double giveTemperature(GaussPoint *gp, TimeStep *tStep, int option); + double giveTemperature(GaussPoint *gp, TimeStep *tStep, int option) const; /// Evaluation of the factor transforming real time to reduced time (effect on the flow term) /// option = 0 ... beginning of the time step /// option = 1 ... end of the time step /// option = 2 ... average value - double computePsiR(GaussPoint *gp, TimeStep *tStep, int option); + double computePsiR(GaussPoint *gp, TimeStep *tStep, int option) const; /// Evaluation of the factor transforming real time to reduced time (effect on the evolution of microprestress) - double computePsiS(GaussPoint *gp, TimeStep *tStep); + double computePsiS(GaussPoint *gp, TimeStep *tStep) const; /// Evaluation of the factor transforming real time to equivalent time (effect on the solidified volume) - double computePsiE(GaussPoint *gp, TimeStep *tStep); + double computePsiE(GaussPoint *gp, TimeStep *tStep) const; /// Computes equivalent time at given time step and GP. /// If option == 0, equivalentTime is evaluated in the middle of the time step (to determine solidified ratio). /// If option == 1, equivalentTime is evaluated at the end of the time step. (for updating). - double computeEquivalentTime(GaussPoint *gp, TimeStep *tStep, int option); + double computeEquivalentTime(GaussPoint *gp, TimeStep *tStep, int option) const; friend class RankineMPSmat; }; diff --git a/src/sm/Materials/RheoChainMaterials/mpsdammat.C b/src/sm/Materials/RheoChainMaterials/mpsdammat.C index ba23c34e2..dabad69a1 100644 --- a/src/sm/Materials/RheoChainMaterials/mpsdammat.C +++ b/src/sm/Materials/RheoChainMaterials/mpsdammat.C @@ -51,26 +51,13 @@ REGISTER_Material(MPSDamMaterial); -MPSDamMaterialStatus :: MPSDamMaterialStatus(int n, Domain *d, GaussPoint *g, int nunits) : - MPSMaterialStatus(n, d, g, nunits), effectiveStressVector(), tempEffectiveStressVector() +MPSDamMaterialStatus :: MPSDamMaterialStatus(GaussPoint *g, int nunits) : + MPSMaterialStatus(g, nunits), + crackVector(3) { - kappa = tempKappa = 0.0; - damage = tempDamage = 0.0; - charLength = 0.0; - crackVector.resize(3); - crackVector.zero(); - - var_e0 = var_gf = 0.; - - int rsize = StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ); + int rsize = StructuralMaterial :: giveSizeOfVoigtSymVector( g->giveMaterialMode() ); effectiveStressVector.resize(rsize); - effectiveStressVector.zero(); tempEffectiveStressVector = effectiveStressVector; - -#ifdef supplementary_info - crackWidth = 0.; - residTensileStrength = 0.; -#endif } @@ -89,6 +76,7 @@ MPSDamMaterialStatus :: initTempStatus() } } + void MPSDamMaterialStatus :: updateYourself(TimeStep *tStep) { @@ -104,16 +92,16 @@ MPSDamMaterialStatus :: updateYourself(TimeStep *tStep) } } + void -MPSDamMaterialStatus :: giveCrackVector(FloatArray &answer) +MPSDamMaterialStatus :: giveCrackVector(FloatArray &answer) const { - answer = crackVector; - answer.times(damage); + answer.beScaled(damage, crackVector); } void -MPSDamMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +MPSDamMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { MPSMaterialStatus :: printOutputAt(file, tStep); @@ -127,18 +115,10 @@ MPSDamMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) } - -contextIOResultType -MPSDamMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// +void +MPSDamMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = MPSMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + MPSMaterialStatus :: saveContext(stream, mode); if ( !stream.write(kappa) ) { THROW_CIOERR(CIO_IOERR); @@ -152,6 +132,7 @@ MPSDamMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void * THROW_CIOERR(CIO_IOERR); } + contextIOResultType iores; if ( ( iores = crackVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -167,51 +148,41 @@ MPSDamMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void * if ( ( iores = effectiveStressVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -MPSDamMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restore the state variables from a stream -// +void +MPSDamMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = MPSMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + MPSMaterialStatus :: restoreContext(stream, mode); if ( !stream.read(kappa) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } if ( !stream.read(damage) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } if ( !stream.read(charLength) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } + contextIOResultType iores; if ( ( iores = crackVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } if ( !stream.read(var_e0) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } if ( !stream.read(var_gf) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } if ( ( iores = effectiveStressVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - - return CIO_OK; } // *********************************************************************************** @@ -220,41 +191,23 @@ MPSDamMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, voi MPSDamMaterial :: MPSDamMaterial(int n, Domain *d) : MPSMaterial(n, d) +{} -{ - maxOmega = 0.999999; - - softType = ST_Exponential_Cohesive_Crack; - ecsMethod = ECSM_Projection; - // const_e0 = 0.; - const_gf = 0.; - checkSnapBack = 1; //snapback check by default - E = -1.; - -} - - -int -MPSDamMaterial :: hasMaterialModeCapability(MaterialMode mode) -// -// returns whether receiver supports given mode -// +bool +MPSDamMaterial :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _3dMat || mode == _PlaneStress || mode == _PlaneStrain || mode == _1dMat; } - -IRResultType -MPSDamMaterial :: initializeFrom(InputRecord *ir) +void +MPSDamMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - MPSMaterial :: initializeFrom(ir); this->isotropic = false; - if ( ir->hasField(_IFT_MPSDamMaterial_isotropic) ) { + if ( ir.hasField(_IFT_MPSDamMaterial_isotropic) ) { this->isotropic = true; } @@ -263,7 +216,7 @@ MPSDamMaterial :: initializeFrom(InputRecord *ir) this->timeDepFracturing = false; - if ( ir->hasField(_IFT_MPSDamMaterial_timedepfracturing) ) { + if ( ir.hasField(_IFT_MPSDamMaterial_timedepfracturing) ) { this->timeDepFracturing = true; // IR_GIVE_FIELD(ir, fib_s, _IFT_MPSDamMaterial_fib_s); @@ -272,7 +225,7 @@ MPSDamMaterial :: initializeFrom(InputRecord *ir) this->gf28 = 0.; this->ft28 = 0.; - if ( ( ir->hasField(_IFT_MPSDamMaterial_ft28) ) && ( ir->hasField(_IFT_MPSDamMaterial_gf28) ) ) { + if ( ( ir.hasField(_IFT_MPSDamMaterial_ft28) ) && ( ir.hasField(_IFT_MPSDamMaterial_gf28) ) ) { IR_GIVE_FIELD(ir, gf28, _IFT_MPSDamMaterial_gf28); if (gf28 < 0.) { @@ -317,20 +270,17 @@ MPSDamMaterial :: initializeFrom(InputRecord *ir) } IR_GIVE_OPTIONAL_FIELD(ir, checkSnapBack, _IFT_MPSDamMaterial_checkSnapBack); - - return IRRT_OK; } void MPSDamMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep) { - - if (this->E < 0.) { // initialize dummy elastic modulus E - this->E = 1. / MPSMaterial :: computeCreepFunction(28.01, 28., gp, tStep); - } + if ( this->E < 0. ) { // initialize dummy elastic modulus E + this->E = 1. / MPSMaterial :: computeCreepFunction(28.01*this->lambda0, 28.*this->lambda0, gp, tStep); + } - MPSDamMaterialStatus *status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); + MPSDamMaterialStatus *status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); MaterialMode mode = gp->giveMaterialMode(); @@ -361,6 +311,7 @@ MPSDamMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const status->setTempDamage(0.); #endif + answer = tempEffectiveStress; return; } @@ -429,7 +380,7 @@ MPSDamMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const crackPlaneNormal.at(i) = principalDir.at(i, 1); } this->initDamaged(tempKappa, crackPlaneNormal, gp, tStep); - this->computeDamage(omega, tempKappa, gp); + omega = this->computeDamage(tempKappa, gp); } answer.zero(); @@ -455,10 +406,10 @@ MPSDamMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const if ( mode == _PlaneStress ) { principalStress.resizeWithValues(3); - givePlaneStressVectorTranformationMtrx(Tstress, principalDir, true); + Tstress = givePlaneStressVectorTranformationMtrx(principalDir, true); } else { principalStress.resizeWithValues(6); - giveStressVectorTranformationMtrx(Tstress, principalDir, true); + Tstress = giveStressVectorTranformationMtrx(principalDir, true); } principalStress.rotatedWith(Tstress, 'n'); @@ -514,13 +465,10 @@ MPSDamMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const void MPSDamMaterial :: initDamagedFib(GaussPoint *gp, TimeStep *tStep) { - MPSDamMaterialStatus *status = ( MPSDamMaterialStatus * ) this->giveStatus(gp); + auto status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); if ( status->giveDamage() == 0. ) { - double tequiv; - - tequiv = this->computeEquivalentTime(gp, tStep, 0); - + double tequiv = this->computeEquivalentTime(gp, tStep, 0); double e0 = this->computeTensileStrength(tequiv) / this->E; double gf = this->computeFractureEnergy(tequiv); @@ -530,21 +478,22 @@ MPSDamMaterial :: initDamagedFib(GaussPoint *gp, TimeStep *tStep) } double -MPSDamMaterial :: givee0(GaussPoint *gp) +MPSDamMaterial :: givee0(GaussPoint *gp) const { if ( this->timeDepFracturing ) { - MPSDamMaterialStatus *status = ( MPSDamMaterialStatus * ) this->giveStatus(gp); + auto status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); return status->givee0(); } else { return this->ft / this->E; } } + double -MPSDamMaterial :: givegf(GaussPoint *gp) +MPSDamMaterial :: givegf(GaussPoint *gp) const { if ( this->timeDepFracturing ) { - MPSDamMaterialStatus *status = ( MPSDamMaterialStatus * ) this->giveStatus(gp); + auto status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); return status->givegf(); } else { return this->const_gf; @@ -553,12 +502,8 @@ MPSDamMaterial :: givegf(GaussPoint *gp) double -MPSDamMaterial :: computeFractureEnergy(double equivalentTime) +MPSDamMaterial :: computeFractureEnergy(double equivalentTime) const { - - double fractureEnergy, fractureEnergy28; - double ftm, ftm28; - // the fracture energy has the same time evolution as the tensile strength, // the direct relation to the mean value of compressive strength according to Model Code // highly overestimates the initial (early age) value of the fracture energy @@ -581,48 +526,45 @@ MPSDamMaterial :: computeFractureEnergy(double equivalentTime) // 1) read or estimate the 28-day value of fracture energy - if (this->gf28 > 0.) { - fractureEnergy28 = this->gf28; + double fractureEnergy28; + if ( this->gf28 > 0. ) { + fractureEnergy28 = this->gf28; } else { - fractureEnergy28 = 73. * pow(fib_fcm28, 0.18) / MPSMaterial :: stiffnessFactor; + fractureEnergy28 = 73. * pow(fib_fcm28, 0.18) / MPSMaterial :: stiffnessFactor; } // 2) compute the tensile strengh according to provided equivalent time - ftm = this->computeTensileStrength(equivalentTime); - ftm28 = this->computeTensileStrength(28. * MPSMaterial :: lambda0); + double ftm = this->computeTensileStrength(equivalentTime); + double ftm28 = this->computeTensileStrength(28. * MPSMaterial :: lambda0); // 3) calculate the resulting fracture energy as gf28 * ft/ft28 - fractureEnergy = fractureEnergy28 * ftm / ftm28; - - return fractureEnergy; + return fractureEnergy28 * ftm / ftm28; } double -MPSDamMaterial :: computeTensileStrength(double equivalentTime) +MPSDamMaterial :: computeTensileStrength(double equivalentTime) const { double fcm, ftm; - - if (this->ft28 > 0.) { - double fcm28mod; - fcm28mod = pow ( this->ft28 * MPSMaterial :: stiffnessFactor / 0.3e6, 3./2. ) + 8.; - fcm = exp( fib_s * ( 1. - sqrt(28. * MPSMaterial :: lambda0 / equivalentTime) ) ) * fcm28mod; + if ( this->ft28 > 0. ) { + double fcm28mod = pow ( this->ft28 * MPSMaterial :: stiffnessFactor / 0.3e6, 3./2. ) + 8.; + fcm = exp( fib_s * ( 1. - sqrt(28. * MPSMaterial :: lambda0 / equivalentTime) ) ) * fcm28mod; } else { - // returns fcm in MPa - formula 5.1-51, Table 5.1-9 - fcm = exp( fib_s * ( 1. - sqrt(28. * MPSMaterial :: lambda0 / equivalentTime) ) ) * fib_fcm28; + // returns fcm in MPa - formula 5.1-51, Table 5.1-9 + fcm = exp( fib_s * ( 1. - sqrt(28. * MPSMaterial :: lambda0 / equivalentTime) ) ) * fib_fcm28; } // ftm adjusted according to the stiffnessFactor (MPa by default) if ( fcm >= 58. ) { - ftm = 2.12 * log ( 1. + 0.1 * fcm ) * 1.e6 / MPSMaterial :: stiffnessFactor; + ftm = 2.12 * log ( 1. + 0.1 * fcm ) * 1.e6 / MPSMaterial :: stiffnessFactor; } else if ( fcm <= 20. ) { - ftm = 0.07862 * fcm * 1.e6 / MPSMaterial :: stiffnessFactor; // 12^(2/3) * 0.3 / 20 = 0.07862 + ftm = 0.07862 * fcm * 1.e6 / MPSMaterial :: stiffnessFactor; // 12^(2/3) * 0.3 / 20 = 0.07862 } else { - ftm = 0.3 * pow(fcm - 8., 2. / 3.) * 1.e6 / MPSMaterial :: stiffnessFactor; //5.1-3a + ftm = 0.3 * pow(fcm - 8., 2. / 3.) * 1.e6 / MPSMaterial :: stiffnessFactor; //5.1-3a } /* @@ -640,29 +582,26 @@ MPSDamMaterial :: computeTensileStrength(double equivalentTime) } -void -MPSDamMaterial :: computeDamage(double &omega, double kappa, GaussPoint *gp) +double +MPSDamMaterial :: computeDamage(double kappa, GaussPoint *gp) const { if ( this->softType == ST_Disable_Damage ) { //dummy material with no damage - omega = 0.; + return 0.; } else { - computeDamageForCohesiveCrack(omega, kappa, gp); + return computeDamageForCohesiveCrack(kappa, gp); } } -void -MPSDamMaterial :: computeDamageForCohesiveCrack(double &omega, double kappa, GaussPoint *gp) +double +MPSDamMaterial :: computeDamageForCohesiveCrack(double kappa, GaussPoint *gp) const { - MPSDamMaterialStatus *status = NULL; + auto status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); - omega = 0.0; + double omega = 0.0; double e0 = this->givee0(gp); - double ef = 0.; - if ( kappa > e0 ) { double gf = this->givegf(gp); - double Le; double wf = 0.; if ( softType == ST_Exponential_Cohesive_Crack ) { // exponential softening wf = gf / this->E / e0; // wf is the crack opening @@ -672,14 +611,11 @@ MPSDamMaterial :: computeDamageForCohesiveCrack(double &omega, double kappa, Gau OOFEM_ERROR("Gf unsupported for softening type softType = %d", softType); } - // MPSDamMaterialStatus *status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); - status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); - - Le = status->giveCharLength(); - ef = wf / Le; //ef is the fracturing strain + double Le = status->giveCharLength(); + double ef = wf / Le; //ef is the fracturing strain if ( ef < e0 ) { //check that no snapback occurs double minGf = 0.; - OOFEM_WARNING("ef %e < e0 %e, this leads to material snapback in element %d, characteristic length %f", ef, e0, gp->giveElement()->giveNumber(), Le); + OOFEM_WARNING("ef %e < e0 %e, this leads to material snapback in element %d, characteristic length %f", ef, e0, gp->giveElement()->giveGlobalNumber(), Le); if ( softType == ST_Exponential_Cohesive_Crack ) { //exponential softening minGf = this->E * e0 * e0 * Le; @@ -703,7 +639,7 @@ MPSDamMaterial :: computeDamageForCohesiveCrack(double &omega, double kappa, Gau } } else if ( this->softType == ST_Exponential_Cohesive_Crack ) { // exponential cohesive crack - iteration needed - double R, Lhs, help; + double R = 0.; int nite = 0; // iteration to achieve objectivity // we are looking for a state in which the elastic stress is equal to @@ -711,9 +647,9 @@ MPSDamMaterial :: computeDamageForCohesiveCrack(double &omega, double kappa, Gau // ef has now the meaning of strain do { nite++; - help = omega * kappa / ef; + double help = omega * kappa / ef; R = ( 1. - omega ) * kappa - e0 *exp(-help); //residuum - Lhs = kappa - e0 *exp(-help) * kappa / ef; //- dR / (d omega) + double Lhs = kappa - e0 *exp(-help) * kappa / ef; //- dR / (d omega) omega += R / Lhs; if ( nite > 40 ) { OOFEM_ERROR("algorithm not converging"); @@ -735,38 +671,33 @@ MPSDamMaterial :: computeDamageForCohesiveCrack(double &omega, double kappa, Gau } } - } - #ifdef supplementary_info - double residualStrength = 0.; + double residualStrength = 0.; - if ( omega == 0. ) { - residualStrength = E * e0; // undamaged material - status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); - } else { - if ( this->softType == ST_Linear_Cohesive_Crack ) { - residualStrength = E * e0 * ( ef - kappa ) / ( ef - e0 ); - } else if ( this->softType == ST_Exponential_Cohesive_Crack ) { - residualStrength = E * e0 * exp(-1. * ( kappa - e0 ) / ef); + if ( omega == 0. ) { + residualStrength = E * e0; // undamaged material } else { - OOFEM_ERROR("Unknown softening type for cohesive crack model."); + if ( this->softType == ST_Linear_Cohesive_Crack ) { + residualStrength = E * e0 * ( ef - kappa ) / ( ef - e0 ); + } else if ( this->softType == ST_Exponential_Cohesive_Crack ) { + residualStrength = E * e0 * exp(-1. * ( kappa - e0 ) / ef); + } else { + OOFEM_ERROR("Unknown softening type for cohesive crack model."); + } } - } - if ( status ) { status->setResidualTensileStrength(residualStrength); +#endif } -#endif + return omega; } void MPSDamMaterial :: initDamaged(double kappa, FloatArray &principalDirection, GaussPoint *gp, TimeStep *tStep) { - double le = 0.; - - MPSDamMaterialStatus *status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); if ( this->timeDepFracturing ) { this->initDamagedFib(gp, tStep); @@ -789,7 +720,7 @@ MPSDamMaterial :: initDamaged(double kappa, FloatArray &principalDirection, Gaus if ( ( kappa > e0 ) && ( status->giveDamage() == 0. ) ) { status->setCrackVector(principalDirection); - le = gp->giveElement()->giveCharacteristicSize(gp, principalDirection, ecsMethod); + double le = gp->giveElement()->giveCharacteristicSize(gp, principalDirection, ecsMethod); status->setCharLength(le); if ( gf != 0. && e0 >= ( wf / le ) ) { // case for a given fracture energy @@ -809,89 +740,82 @@ MPSDamMaterial :: CreateStatus(GaussPoint *gp) const * creates a new material status corresponding to this class */ { - return new MPSDamMaterialStatus(1, this->giveDomain(), gp, nUnits); + return new MPSDamMaterialStatus(gp, nUnits); } -void -MPSDamMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +MPSDamMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - RheoChainMaterial :: give3dMaterialStiffnessMatrix(answer, ElasticStiffness, gp, tStep); + auto d = RheoChainMaterial :: give3dMaterialStiffnessMatrix(ElasticStiffness, gp, tStep); if ( mode == ElasticStiffness || ( mode == SecantStiffness && !this->isotropic ) ) { - return; + return d; } - double tempDamage; - MPSDamMaterialStatus *status = ( MPSDamMaterialStatus * ) this->giveStatus(gp); - tempDamage = min(status->giveTempDamage(), this->maxOmega); - answer.times(1.0 - tempDamage); + auto status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); + double tempDamage = min(status->giveTempDamage(), this->maxOmega); + return d * (1.0 - tempDamage); } -void -MPSDamMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +MPSDamMaterial :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - RheoChainMaterial :: givePlaneStressStiffMtrx(answer, ElasticStiffness, gp, tStep); + auto d = RheoChainMaterial :: givePlaneStressStiffMtrx(ElasticStiffness, gp, tStep); if ( mode == ElasticStiffness || ( mode == SecantStiffness && !this->isotropic ) ) { - return; + return d; } - double tempDamage; - MPSDamMaterialStatus *status = ( MPSDamMaterialStatus * ) this->giveStatus(gp); - tempDamage = min(status->giveTempDamage(), this->maxOmega); - answer.times(1.0 - tempDamage); + auto status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); + double tempDamage = min(status->giveTempDamage(), this->maxOmega); + return d * (1.0 - tempDamage); } -void -MPSDamMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, + +FloatMatrixF<4,4> +MPSDamMaterial :: givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - RheoChainMaterial :: givePlaneStrainStiffMtrx(answer, ElasticStiffness, gp, tStep); + auto d = RheoChainMaterial :: givePlaneStrainStiffMtrx(ElasticStiffness, gp, tStep); if ( mode == ElasticStiffness || ( mode == SecantStiffness && !this->isotropic ) ) { - return; + return d; } - double tempDamage; - MPSDamMaterialStatus *status = ( MPSDamMaterialStatus * ) this->giveStatus(gp); - tempDamage = min(status->giveTempDamage(), this->maxOmega); - answer.times(1.0 - tempDamage); + auto status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); + double tempDamage = min(status->giveTempDamage(), this->maxOmega); + return d * (1.0 - tempDamage); } -void -MPSDamMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<1,1> +MPSDamMaterial :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - RheoChainMaterial :: give1dStressStiffMtrx(answer, ElasticStiffness, gp, tStep); + auto d = RheoChainMaterial :: give1dStressStiffMtrx(ElasticStiffness, gp, tStep); if ( mode == ElasticStiffness || ( mode == SecantStiffness && !this->isotropic ) ) { - return; + return d; } - double tempDamage; - MPSDamMaterialStatus *status = ( MPSDamMaterialStatus * ) this->giveStatus(gp); - tempDamage = min(status->giveTempDamage(), this->maxOmega); - answer.times(1.0 - tempDamage); + auto status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); + double tempDamage = min(status->giveTempDamage(), this->maxOmega); + return d * (1.0 - tempDamage); } int MPSDamMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - MPSDamMaterialStatus *status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); if ( type == IST_DamageScalar ) { answer.resize(1); answer.zero(); @@ -938,18 +862,15 @@ MPSDamMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateT answer.at(1) = status->giveResidualTensileStrength(); return 1; } else if ( type == IST_TensileStrength ) { - MPSDamMaterialStatus *status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); double tequiv = status->giveEquivalentTime(); answer.resize(1); answer.zero(); - if (tequiv >= this->castingTime) { + if (tequiv >= 0.) { answer.at(1) = this->computeTensileStrength(tequiv); } return 1; } else if ( type == IST_CrackIndex ) { //ratio of real principal stress / strength. 1 if damage already occured. - FloatArray principalStress; - MPSDamMaterialStatus *status = static_cast< MPSDamMaterialStatus * >( this->giveStatus(gp) ); answer.resize(1); answer.zero(); if ( status->giveDamage()>0. ){ @@ -958,13 +879,14 @@ MPSDamMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateT } //FloatArray effectiveStress = status->giveTempViscoelasticStressVector(); //StructuralMaterial :: computePrincipalValues(principalStress, effectiveStress, principal_stress); + FloatArray principalStress; StructuralMaterial :: giveIPValue(principalStress, gp, IST_PrincipalStressTensor, tStep); double tequiv = status->giveEquivalentTime(); - if (tequiv >= this->castingTime) { - double ft = this->computeTensileStrength(tequiv); - if (ft > 1.e-20 && principalStress.at(1)>1.e-20){ + if ( tequiv >= 0. ) { + double ft = this->computeTensileStrength(tequiv); + if ( ft > 1.e-20 && principalStress.at(1)>1.e-20 ) { answer.at(1) = principalStress.at(1)/ft; - } + } } return 1; } else { diff --git a/src/sm/Materials/RheoChainMaterials/mpsdammat.h b/src/sm/Materials/RheoChainMaterials/mpsdammat.h index 5e6ee19b2..af361541a 100644 --- a/src/sm/Materials/RheoChainMaterials/mpsdammat.h +++ b/src/sm/Materials/RheoChainMaterials/mpsdammat.h @@ -77,68 +77,67 @@ class MPSDamMaterialStatus : public MPSMaterialStatus /// Temporary stress vector in reduced form (increments are used mainly in nonlinear analysis) FloatArray tempEffectiveStressVector; /// Scalar measure of the largest strain level ever reached in material. - double kappa; + double kappa = 0.; /// Non-equilibrated scalar measure of the largest strain level. - double tempKappa; + double tempKappa = 0.; /// Damage level of material. - double damage; + double damage = 0.; /// Non-equilibrated damage level of material. - double tempDamage; + double tempDamage = 0.; /// Characteristic length - double charLength; + double charLength = 0.; /// Crack orientation normalized to damage magnitude. This is useful for plotting cracks as a vector field (paraview etc.). FloatArray crackVector; /// hydration-degree dependent equivalent strain at stress peak - double var_e0; + double var_e0 = 0.; /// hydration-degree dependent fracture energy - double var_gf; + double var_gf = 0.; #ifdef supplementary_info - double crackWidth; - double residTensileStrength; + double crackWidth = 0.; + double residTensileStrength = 0.; #endif public: - MPSDamMaterialStatus(int n, Domain *d, GaussPoint *g, int nunits); - virtual ~MPSDamMaterialStatus() { } + MPSDamMaterialStatus(GaussPoint *g, int nunits); - virtual const FloatArray &giveViscoelasticStressVector() const { return effectiveStressVector; } + const FloatArray &giveViscoelasticStressVector() const override { return effectiveStressVector; } /// Assigns tempStressVector to given vector v. void letTempViscoelasticStressVectorBe(FloatArray v) { tempEffectiveStressVector = std :: move(v); } virtual const FloatArray &giveTempViscoelasticStressVector() const { return tempEffectiveStressVector; } /// Returns the last equilibrated scalar measure of the largest strain level. - double giveKappa() { return kappa; } + double giveKappa() const { return kappa; } /// Returns the temp. scalar measure of the largest strain level. - double giveTempKappa() { return tempKappa; } + double giveTempKappa() const { return tempKappa; } /// Sets the temp scalar measure of the largest strain level to given value. void setTempKappa(double newKappa) { tempKappa = newKappa; } /// Returns the last equilibrated damage level. - double giveDamage() { return damage; } + double giveDamage() const { return damage; } /// Returns the temp. damage level. - double giveTempDamage() { return tempDamage; } + double giveTempDamage() const { return tempDamage; } /// Sets the temp damage level to given value. void setTempDamage(double newDamage) { tempDamage = newDamage; } /// Returns characteristic length stored in receiver. - double giveCharLength() { return charLength; } + double giveCharLength() const { return charLength; } /// Sets characteristic length to given value. void setCharLength(double length) { charLength = length; } /// Returns crack vector stored in receiver. This is useful for plotting cracks as a vector field (paraview etc.). - void giveCrackVector(FloatArray &answer); + void giveCrackVector(FloatArray &answer) const; /// Sets crack vector to given value. This is useful for plotting cracks as a vector field (paraview etc.). void setCrackVector(FloatArray cv) { crackVector = cv; } void sete0(double e0) { var_e0 = e0; } void setgf(double gf) { var_gf = gf; } - double givee0() { return var_e0; } - double givegf() { return var_gf; } + double givee0() const { return var_e0; } + double givegf() const { return var_gf; } - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; #ifdef supplementary_info void setCrackWidth(double src) { crackWidth = src; } @@ -147,12 +146,11 @@ class MPSDamMaterialStatus : public MPSMaterialStatus double giveResidualTensileStrength(void) { return residTensileStrength; } #endif - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; // definition - virtual const char *giveClassName() const { return "MPSDamMaterialStatus"; } + const char *giveClassName() const override { return "MPSDamMaterialStatus"; } protected: /** @@ -183,22 +181,22 @@ class MPSDamMaterial : public MPSMaterial { protected: - bool timeDepFracturing; - double fib_s; - double fib_fcm28; - bool isotropic; + bool timeDepFracturing = false; + double fib_s = 0.; + double fib_fcm28 = 0.; + bool isotropic = false; /// dummy Young's modulus - double E; + double E = -1.; /// Maximum limit on omega. The purpose is elimination of a too compliant material which may cause convergence problems. Set to something like 0.99 if needed. - double maxOmega; + double maxOmega = 0.999999; /// Equivalent strain at stress peak (or a similar parameter). //double const_e0; /// constant tensile strength - double ft; + double ft = 0.; /** * Determines the softening -> corresponds to the initial fracture energy. For a linear law, it is the area @@ -206,46 +204,42 @@ class MPSDamMaterial : public MPSMaterial * and a tangent to the softening part of the curve at the peak stress. For a bilinear law, * gf corresponds to area bounded by elasticity and the first linear softening line projected to zero stress. */ - double const_gf; + double const_gf = 0.; + + /// Check possible snap back flag + int checkSnapBack = 1; /** Type characterizing the formula for the damage law. For example, linear softening can be specified * with fracturing strain or crack opening. */ enum SofteningType { ST_Exponential_Cohesive_Crack, ST_Linear_Cohesive_Crack, ST_Disable_Damage }; - - /// Check possible snap back flag - int checkSnapBack; - /// Parameter specifying the type of softening (damage law). - SofteningType softType; + SofteningType softType = ST_Exponential_Cohesive_Crack; /// Method used for evaluation of characteristic element size - ElementCharSizeMethod ecsMethod; + ElementCharSizeMethod ecsMethod = ECSM_Projection; /// 28-day value of tensile strength. Used only with "timedepfracturing" - double ft28; + double ft28 = 0.; /// 28-day value of fracture energy. Used only with "timedepfracturing" - double gf28; + double gf28 = 0.; public: MPSDamMaterial(int n, Domain *d); - virtual ~MPSDamMaterial() { } - virtual int hasNonLinearBehaviour() { return 1; } + bool hasMaterialModeCapability(MaterialMode mode) const override; - virtual int hasMaterialModeCapability(MaterialMode mode); + const char *giveInputRecordName() const override { return _IFT_MPSDamMaterial_Name; } + const char *giveClassName() const override { return "MPSDamMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_MPSDamMaterial_Name; } - virtual const char *giveClassName() const { return "MPSDamMaterial"; } + void initializeFrom(InputRecord &ir) override; - virtual IRResultType initializeFrom(InputRecord *ir); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) override; - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - - double givee0(GaussPoint *gp); - double givegf(GaussPoint *gp); + double givee0(GaussPoint *gp) const; + double givegf(GaussPoint *gp) const; /** * Abstract service allowing to perform some initialization, when damage first appear. @@ -261,54 +255,41 @@ class MPSDamMaterial : public MPSMaterial /** * Computes the value of damage omega, based on given value of equivalent strain. - * @param[out] omega Contains result. * @param kappa Equivalent strain measure. * @param strain Total strain in full form. * @param gp Integration point. + * @return Damage. */ - void computeDamage(double &omega, double kappa, GaussPoint *gp); + double computeDamage(double kappa, GaussPoint *gp) const; /** * computes the value of damage parameter omega, * based on a given value of equivalent strain, * using iterations to achieve objectivity, * based on the crack band concept (effective element size used) - * @param[out] omega Contains the resulting damage. * @param kappa Equivalent strain measure. * @param gp Integration point. + * @return Damage. */ - void computeDamageForCohesiveCrack(double &omega, double kappa, GaussPoint *gp); - - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; - + double computeDamageForCohesiveCrack(double kappa, GaussPoint *gp) const; - virtual double computeTensileStrength(double equivalentTime); - virtual double computeFractureEnergy(double equivalentTime); + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + virtual double computeTensileStrength(double equivalentTime) const; + virtual double computeFractureEnergy(double equivalentTime) const; - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, + TimeStep *tStep) const override; - virtual void give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, + TimeStep *tStep) const override; + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, + TimeStep *tStep) const override; -protected: - - //virtual double giveEModulus(GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, + TimeStep *tStep) const override; }; } // end namespace oofem #endif // mpsdammat_h diff --git a/src/sm/Materials/RheoChainMaterials/rheoChM.C b/src/sm/Materials/RheoChainMaterials/rheoChM.C index d827816cd..dea00adf2 100644 --- a/src/sm/Materials/RheoChainMaterials/rheoChM.C +++ b/src/sm/Materials/RheoChainMaterials/rheoChM.C @@ -35,25 +35,18 @@ #include "mathfem.h" #include "rheoChM.h" #include "material.h" -#include "Materials/isolinearelasticmaterial.h" -//#include "Materials/latticelinearelastic.h" +#include "sm/Materials/isolinearelasticmaterial.h" +#include "sm/Materials/LatticeMaterials/latticelinearelastic.h" #include "floatarray.h" #include "floatmatrix.h" #include "gausspoint.h" #include "engngm.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "contextioerr.h" namespace oofem { -RheoChainMaterial :: RheoChainMaterial(int n, Domain *d) : StructuralMaterial(n, d), - EparVal(), charTimes(), discreteTimeScale() -{ - nUnits = 0; - relMatAge = 0.0; - linearElasticMaterial = NULL; - EparValTime = -1.0; - preCastingTimeMat = 0; -} +RheoChainMaterial :: RheoChainMaterial(int n, Domain *d) : StructuralMaterial(n, d) +{} RheoChainMaterial :: ~RheoChainMaterial() @@ -64,16 +57,14 @@ RheoChainMaterial :: ~RheoChainMaterial() } -int -RheoChainMaterial :: hasMaterialModeCapability(MaterialMode mode) -// -// returns whether the receiver supports the given mode -// +bool +RheoChainMaterial :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _3dMat || mode == _PlaneStress || mode == _PlaneStrain || mode == _1dMat || mode == _PlateLayer || mode == _2dBeamLayer || - mode == _2dLattice || mode == _3dLattice; + mode == _1dLattice || mode == _2dLattice || + mode == _3dLattice; } @@ -94,12 +85,23 @@ RheoChainMaterial :: giveRealStressVector(FloatArray &answer, double Emodulus; RheoChainMaterialStatus *status = static_cast< RheoChainMaterialStatus * >( this->giveStatus(gp) ); - // initialize the temporary material status and the Gauss point - this->initTempStatus(gp); + // Initialize the temporary material status and the Gauss point + // Do not initialize if the the actual time is the same as before + // this has to be introduced when the time-stepping is variable and + // some time steps can be run several times + // It is vital to erase some temporary variables if the time is changed and + // the time step is still the same + // In order to guarantee a reasonable performance the temporary status is not + // initialized in subsequent iterations of the same time step + + if ( status->giveCurrentTime() != tStep->giveTargetTime() ) { + status->setCurrentTime(tStep->giveTargetTime() ); + this->initTempStatus(gp); + } if ( !this->isActivated(tStep) ) { FloatArray zeros; - zeros.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + zeros.resize(StructuralMaterial :: giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ); zeros.zero(); status->letTempStrainVectorBe(zeros); status->letTempStressVectorBe(zeros); @@ -117,7 +119,7 @@ RheoChainMaterial :: giveRealStressVector(FloatArray &answer, tStep, VM_Incremental); // subtract the initial strain to get the "net" strain increment, // which is related to the stress increment - strainIncrement.beDifferenceOf( reducedStrain, status->giveStrainVector() ); + strainIncrement.beDifferenceOf(reducedStrain, status->giveStrainVector() ); // get the initial stress, or set it to zero if not available (first step) //if ( status->giveStressVector().giveSize() ) { @@ -125,15 +127,14 @@ RheoChainMaterial :: giveRealStressVector(FloatArray &answer, if ( status->giveViscoelasticStressVector().giveSize() ) { stressVector = status->giveViscoelasticStressVector(); } else { - stressVector.resize( strainIncrement.giveSize() ); + stressVector.resize(strainIncrement.giveSize() ); stressVector.zero(); } - if ( tStep->giveIntrinsicTime() < this->castingTime && preCastingTimeMat > 0 ) { + if ( ( !Material :: isActivated(tStep) ) && ( preCastingTimeMat > 0 ) ) { StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); sMat->giveStiffnessMatrix(Binv, ElasticStiffness, gp, tStep); - } else { // evaluate the incremental modulus Emodulus = this->giveEModulus(gp, tStep); @@ -141,7 +142,6 @@ RheoChainMaterial :: giveRealStressVector(FloatArray &answer, this->giveUnitStiffnessMatrix(Binv, gp, tStep); // multiply the "net" strain increment by unit stiffness and by the incremental modulus Binv.times(Emodulus); - } stressIncrement.beProductOf(Binv, strainIncrement); @@ -154,20 +154,21 @@ RheoChainMaterial :: giveRealStressVector(FloatArray &answer, status->letTempStrainVectorBe(totalStrain); status->letTempStressVectorBe(stressVector); - // update the shrinkage strain if needed - if ( this->hasIncrementalShrinkageFormulation() ) { - FloatArray shv; - this->giveShrinkageStrainVector(shv, gp, tStep, VM_Total); - status->setShrinkageStrainVector(shv); + if ( Material :: isActivated(tStep) ) { + // update the shrinkage strain if needed + if ( this->hasIncrementalShrinkageFormulation() ) { + FloatArray shv; + this->giveShrinkageStrainVector(shv, gp, tStep, VM_Total); + status->setShrinkageStrainVector(shv); + } } answer = stressVector; } -void -RheoChainMaterial :: giveThermalDilatationVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep) +FloatArrayF< 6 > +RheoChainMaterial :: giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const // // returns a FloatArray(6) of initial strain vector // eps_0 = {exx_0, eyy_0, ezz_0, gyz_0, gxz_0, gxy_0}^T @@ -176,45 +177,44 @@ RheoChainMaterial :: giveThermalDilatationVector(FloatArray &answer, // { MaterialMode mMode = gp->giveMaterialMode(); - - answer.resize(6); - answer.zero(); - - if ( mMode == _2dLattice || mMode == _3dLattice ) { - answer.at(1) = ( this->talpha ); + if ( mMode == _1dLattice || mMode == _2dLattice || mMode == _3dLattice ) { + return { + this->talpha, 0., 0., 0., 0., 0. + }; } else { - answer.at(1) = ( this->talpha ); - answer.at(2) = ( this->talpha ); - answer.at(3) = ( this->talpha ); + return { + talpha, + talpha, + talpha, + 0., + 0., + 0., + }; } } void RheoChainMaterial :: computeDiscreteRelaxationFunction(FloatArray &answer, const FloatArray &tSteps, - double t0, double tr, - GaussPoint *gp, TimeStep *tStep) + double t0, double tr, + GaussPoint *gp, TimeStep *tStep) const { - int size, nsteps, si; - double taui, tauk, Jtrt0, totalDeltaSigma; - double sig0; - double sum; - - size = tSteps.giveSize(); - nsteps = size; + int size = tSteps.giveSize(); + int nsteps = size; FloatArray deltaSigma(size); answer.resize(size); answer.zero(); - Jtrt0 = this->computeCreepFunction(t0 + tSteps.at(1), t0, gp, tStep); - sig0 = 1. / Jtrt0; + double Jtrt0 = this->computeCreepFunction(t0 + tSteps.at(1), t0, gp, tStep); + double sig0 = 1. / Jtrt0; answer.at(1) = sig0; - si = 2; + int si = 2; - totalDeltaSigma = 0.; + double totalDeltaSigma = 0.; for ( int k = si; k <= nsteps; k++ ) { - sum = 0.; + double sum = 0.; for ( int i = si; i <= k - 1; i++ ) { + double taui; if ( i == 1 ) { // ??? it seems that tr plays no role because si=2 and the case // i=1 or k=1 can never occur @@ -226,6 +226,7 @@ RheoChainMaterial :: computeDiscreteRelaxationFunction(FloatArray &answer, sum += deltaSigma.at(i) * this->computeCreepFunction(t0 + tSteps.at(k), taui, gp, tStep); } + double tauk; if ( k == 1 ) { // ??? it seems that tr plays no role because si=2 and the case // i=1 or k=1 can never occur @@ -243,21 +244,20 @@ RheoChainMaterial :: computeDiscreteRelaxationFunction(FloatArray &answer, } -void -RheoChainMaterial :: generateLogTimeScale(FloatArray &answer, double from, double to, int nsteps) +FloatArray +RheoChainMaterial :: generateLogTimeScale(double from, double to, int nsteps) { - answer.resize(nsteps); - answer.zero(); - + FloatArray answer(nsteps); double help = log(to / from) / nsteps; for ( int i = 1; i <= nsteps; i++ ) { answer.at(i) = exp(i * help) * from; } + return answer; } const FloatArray & -RheoChainMaterial :: giveDiscreteTimes() +RheoChainMaterial :: giveDiscreteTimes() const { return discreteTimeScale; } @@ -266,7 +266,7 @@ RheoChainMaterial :: giveDiscreteTimes() void RheoChainMaterial :: giveUnitStiffnessMatrix(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { /* * Returns the stiffness matrix of an isotropic linear elastic material @@ -279,13 +279,13 @@ RheoChainMaterial :: giveUnitStiffnessMatrix(FloatMatrix &answer, * defined by stressStrain mode in gp, which may be of a type suported * at the crosssection level). */ - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); + this->linearElasticMaterial->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); } void RheoChainMaterial :: giveUnitComplianceMatrix(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const /* * Returns the compliance matrix of an isotropic linear elastic material * with the given Poisson ratio (assumed to be unaffected by creep) @@ -293,14 +293,14 @@ RheoChainMaterial :: giveUnitComplianceMatrix(FloatMatrix &answer, */ { FloatMatrix tangent; - this->giveLinearElasticMaterial()->giveStiffnessMatrix(tangent, ElasticStiffness, gp, tStep); + this->linearElasticMaterial->giveStiffnessMatrix(tangent, ElasticStiffness, gp, tStep); answer.beInverseOf(tangent); } double -RheoChainMaterial :: giveEparModulus(int iChain) +RheoChainMaterial :: giveEparModulus(int iChain) const { /* returns the modulus of unit number iChain, * previously computed by updateEparModuli() function @@ -310,7 +310,7 @@ RheoChainMaterial :: giveEparModulus(int iChain) void -RheoChainMaterial :: updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *tStep) +RheoChainMaterial :: updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *tStep) const { /* * Computes moduli of individual units in the chain that provide @@ -329,47 +329,45 @@ RheoChainMaterial :: updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *t * */ // compute new values and store them in a temporary array for further use - if ( fabs(tPrime - EparValTime) > TIME_DIFF ) { - if ( tPrime < 0 ) { - this->computeCharCoefficients(EparVal, 1.e-3, gp, tStep); - } else { - this->computeCharCoefficients(EparVal, tPrime, gp, tStep); - } - EparValTime = tPrime; + if ( fabs(tPrime - this->EparValTime) > TIME_DIFF ) { + this->EparVal = this->computeCharCoefficients(tPrime < 0 ? 1.e-3 : tPrime, gp, tStep); + this->EparValTime = tPrime; } } void RheoChainMaterial :: computeTrueStressIndependentStrainVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep, ValueModeType mode) + GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const // // computes the strain due to temperature and shrinkage effects // (it is called "true" because the "stress-independent strain" // will also contain the effect of creep) // { - FloatArray e0; + if ( !Material :: isActivated(tStep) ) { + answer.zero(); + return; + } // shrinkage strain this->giveShrinkageStrainVector(answer, gp, tStep, mode); // thermally induced strain - StructuralMaterial :: computeStressIndependentStrainVector(e0, gp, tStep, mode); + auto e0 = StructuralMaterial :: computeStressIndependentStrainVector(gp, tStep, mode); answer.add(e0); if ( e0.giveSize() ) { #ifdef keep_track_of_strains RheoChainMaterialStatus *status = static_cast< RheoChainMaterialStatus * >( this->giveStatus(gp) ); - status->setTempThermalStrain( status->giveThermalStrain() + e0.at(1) ); + status->setTempThermalStrain(status->giveThermalStrain() + e0.at(1) ); #endif } } -void -RheoChainMaterial :: computeStressIndependentStrainVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +FloatArray +RheoChainMaterial :: computeStressIndependentStrainVector(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const // // computes the strain due to temperature, shrinkage and creep effects // (it is the strain which would occur at the end of the step if the stress @@ -379,17 +377,18 @@ RheoChainMaterial :: computeStressIndependentStrainVector(FloatArray &answer, // takes into account the form of the load vector assumed by engngModel (Incremental or Total Load form) // { - FloatArray e0; - // strain due to temperature changes and shrinkage + FloatArray answer; this->computeTrueStressIndependentStrainVector(answer, gp, tStep, mode); // strain due to creep - if ( tStep->giveIntrinsicTime() >= this->castingTime ) { + if ( Material :: isActivated(tStep) ) { + FloatArray e0; this->giveEigenStrainVector(e0, gp, tStep, mode); if ( e0.giveSize() ) { answer.add(e0); } } + return answer; } @@ -430,7 +429,7 @@ RheoChainMaterial :: computeCharTimes() this->begOfTimeOfInterest = 0.1; //default value } - Tau1 = begOfTimeOfInterest; + Tau1 = begOfTimeOfInterest; if ( Tau1 <= 0 ) { OOFEM_ERROR("begOfTimeOfInterest must be a positive number"); @@ -454,12 +453,37 @@ RheoChainMaterial :: computeCharTimes() } } +/* + * void + * RheoChainMaterial :: giveStiffnessMatrix(FloatMatrix &answer, + * MatResponseMode rMode, + * GaussPoint *gp, TimeStep *tStep) + * { + * // + * // Returns the incremental material stiffness matrix of the receiver + * // PH: the "giveEModulus must be called before any method on elastic material + * // otherwise the status would refer to the elastic material and not to the + * // viscoelastic one + * // in my opinion ElasticStiffness should return incremental stiffness and not unit stiffness + * // for this purpose use giveUnitStiffnessMatrix + * // + * this->giveStatus(gp); // Ensures correct status creation + * if ( ( !Material :: isActivated(tStep) ) && ( preCastingTimeMat > 0 ) ) { + * auto sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); + * sMat->giveStiffnessMatrix(answer, rMode, gp, tStep); + * // return sMat->give3dMaterialStiffnessMatrix(mode, gp, tStep); + * } else { + * this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, rMode, gp, tStep); + * double incrStiffness = this->giveEModulus(gp, tStep); + * answer.times(incrStiffness); + * //return incrStiffness * this->linearElasticMaterial->give3dMaterialStiffnessMatrix(mode, gp, tStep); + * } + * } + */ -void -RheoChainMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) + +FloatMatrixF< 6, 6 > +RheoChainMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { // // Returns the incremental material stiffness matrix of the receiver @@ -469,131 +493,89 @@ RheoChainMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, // in my opinion ElasticStiffness should return incremental stiffness and not unit stiffness // for this purpose use giveUnitStiffnessMatrix // - this->giveStatus(gp); // Ensures correct status creation - if ( tStep->giveIntrinsicTime() < this->castingTime && preCastingTimeMat > 0 ) { - StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); - sMat->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + if ( ( !Material :: isActivated(tStep) ) && ( preCastingTimeMat > 0 ) ) { + auto sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); + return sMat->give3dMaterialStiffnessMatrix(mode, gp, tStep); } else { double incrStiffness = this->giveEModulus(gp, tStep); - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); - answer.times(incrStiffness); + return incrStiffness * this->linearElasticMaterial->give3dMaterialStiffnessMatrix(mode, gp, tStep); } } -void -RheoChainMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -{ - this->giveStatus(gp); // Ensures correct status creation - if ( tStep->giveIntrinsicTime() < this->castingTime && preCastingTimeMat > 0 ) { - StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); - sMat->givePlaneStressStiffMtrx(answer, mode, gp, tStep); - } else { - double incrStiffness = this->giveEModulus(gp, tStep); - this->giveLinearElasticMaterial()->givePlaneStressStiffMtrx(answer, mode, gp, tStep); - answer.times(incrStiffness); - } -} -void -RheoChainMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF< 3, 3 > +RheoChainMaterial :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { this->giveStatus(gp); // Ensures correct status creation - if ( tStep->giveIntrinsicTime() < this->castingTime && preCastingTimeMat > 0 ) { - StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); - sMat->givePlaneStrainStiffMtrx(answer, mode, gp, tStep); + if ( ( !Material :: isActivated(tStep) ) && ( preCastingTimeMat > 0 ) ) { + auto sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); + return sMat->givePlaneStressStiffMtrx(mode, gp, tStep); } else { double incrStiffness = this->giveEModulus(gp, tStep); - this->giveLinearElasticMaterial()->givePlaneStrainStiffMtrx(answer, mode, gp, tStep); - answer.times(incrStiffness); + return incrStiffness * this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep); } } -void -RheoChainMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -{ - this->giveStatus(gp); // Ensures correct status creation - if ( tStep->giveIntrinsicTime() < this->castingTime && preCastingTimeMat > 0 ) { - StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); - sMat->give1dStressStiffMtrx(answer, mode, gp, tStep); - } else { - double incrStiffness = this->giveEModulus(gp, tStep); - this->giveLinearElasticMaterial()->give1dStressStiffMtrx(answer, mode, gp, tStep); - answer.times(incrStiffness); - } -} -void -RheoChainMaterial :: give2dLatticeStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF< 4, 4 > +RheoChainMaterial :: givePlaneStrainStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const { - this->giveStatus(gp); // Ensures correct status creation - if ( tStep->giveIntrinsicTime() < this->castingTime && preCastingTimeMat > 0 ) { - StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); - sMat->give2dLatticeStiffMtrx(answer, mode, gp, tStep); + if ( ( !Material :: isActivated(tStep) ) && ( preCastingTimeMat > 0 ) ) { + auto sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); + return sMat->givePlaneStrainStiffMtrx(mode, gp, tStep); } else { double incrStiffness = this->giveEModulus(gp, tStep); - this->giveLinearElasticMaterial()->give2dLatticeStiffMtrx(answer, mode, gp, tStep); - answer.times(incrStiffness); + return incrStiffness * this->linearElasticMaterial->givePlaneStrainStiffMtrx(mode, gp, tStep); } } -void -RheoChainMaterial :: give3dLatticeStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) + +FloatMatrixF< 1, 1 > +RheoChainMaterial :: give1dStressStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const { this->giveStatus(gp); // Ensures correct status creation - if ( tStep->giveIntrinsicTime() < this->castingTime && preCastingTimeMat > 0 ) { - StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); - sMat->give3dLatticeStiffMtrx(answer, mode, gp, tStep); + if ( ( !Material :: isActivated(tStep) ) && ( preCastingTimeMat > 0 ) ) { + auto sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(preCastingTimeMat) ); + return sMat->give1dStressStiffMtrx(mode, gp, tStep); } else { double incrStiffness = this->giveEModulus(gp, tStep); - this->giveLinearElasticMaterial()->give3dLatticeStiffMtrx(answer, mode, gp, tStep); - answer.times(incrStiffness); + return incrStiffness * this->linearElasticMaterial->give1dStressStiffMtrx(mode, gp, tStep); } } - - MaterialStatus * RheoChainMaterial :: CreateStatus(GaussPoint *gp) const { - return new RheoChainMaterialStatus(1, this->giveDomain(), gp, nUnits); + return new RheoChainMaterialStatus(gp, nUnits); } -IRResultType -RheoChainMaterial :: initializeFrom(InputRecord *ir) +void +RheoChainMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralMaterial :: initializeFrom(ir); - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + // if the casting time is not defined, we set it to zero such that it concides + // with the beginning of the computational time + if ( !ir.hasField(_IFT_Material_castingtime) ) { + this->castingTime = 0.; + } this->talpha = 0.; IR_GIVE_OPTIONAL_FIELD(ir, talpha, _IFT_RheoChainMaterial_talpha); - // "slave" material for time < castingTime - IR_GIVE_OPTIONAL_FIELD(ir, preCastingTimeMat, _IFT_RheoChainMaterial_preCastingTimeMat); - - if ( ir->hasField(_IFT_RheoChainMaterial_lattice) ) { + if ( ir.hasField(_IFT_RheoChainMaterial_lattice) ) { lattice = true; this->alphaOne = 1.; this->alphaTwo = 1.; @@ -616,23 +598,23 @@ RheoChainMaterial :: initializeFrom(InputRecord *ir) // sets up discrete times double endTime = this->giveEndOfTimeOfInterest(); - this->generateLogTimeScale(discreteTimeScale, this->begOfTimeOfInterest, endTime, MNC_NPOINTS - 1); + this->discreteTimeScale = this->generateLogTimeScale(this->begOfTimeOfInterest, endTime, MNC_NPOINTS - 1); + this->giveLinearElasticMaterial(); ///@warning Stiffness is time dependant, so the variable changes with time. //ph !!! why was it put here? //this->updateEparModuli(0.); // stiffnesses are time independent (evaluated at time t = 0.) - - return IRRT_OK; } -LinearElasticMaterial * +//LinearElasticMaterial * +StructuralMaterial * RheoChainMaterial :: giveLinearElasticMaterial() { if ( linearElasticMaterial == NULL ) { if ( this->lattice ) { - /* linearElasticMaterial = new LatticeLinearElastic(this->giveNumber(), + linearElasticMaterial = new LatticeLinearElastic(this->giveNumber(), this->giveDomain(), - 1.0, this->alphaOne, this->alphaTwo);*/ + 1.0, this->alphaOne, this->alphaTwo); } else { linearElasticMaterial = new IsotropicLinearElasticMaterial(this->giveNumber(), this->giveDomain(), @@ -655,45 +637,19 @@ RheoChainMaterial :: giveEndOfTimeOfInterest() return this->endOfTimeOfInterest; } -contextIOResultType +void RheoChainMaterial :: saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -// -// saves full status for this material, also invokes saving -// for sub-objects of this { - contextIOResultType iores; - - if ( ( iores = Material :: saveIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = giveLinearElasticMaterial()->saveIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + Material :: saveIPContext(stream, mode, gp); + giveLinearElasticMaterial()->saveIPContext(stream, mode, gp); } - -contextIOResultType +void RheoChainMaterial :: restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -// -// reads full status for this material, also invokes reading -// of sub-objects of this -// { - contextIOResultType iores; - - if ( ( iores = Material :: restoreIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - + Material :: restoreIPContext(stream, mode, gp); // invoke possible restoring of statuses for submaterials - if ( ( iores = giveLinearElasticMaterial()->restoreIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + giveLinearElasticMaterial()->restoreIPContext(stream, mode, gp); } @@ -715,24 +671,12 @@ RheoChainMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalSta /****************************************************************************************/ -RheoChainMaterialStatus :: RheoChainMaterialStatus(int n, Domain *d, - GaussPoint *g, int nunits) : - StructuralMaterialStatus(n, d, g), +RheoChainMaterialStatus :: RheoChainMaterialStatus(GaussPoint *g, int nunits) : + StructuralMaterialStatus(g), nUnits(nunits), hiddenVars(nUnits), - tempHiddenVars(nUnits), - shrinkageStrain() -{ - - -#ifdef keep_track_of_strains - thermalStrain = 0.; - tempThermalStrain = 0.; -#endif -} - - -RheoChainMaterialStatus :: ~RheoChainMaterialStatus() { } + tempHiddenVars(nUnits) +{} void @@ -748,7 +692,7 @@ RheoChainMaterialStatus :: letTempHiddenVarsVectorBe(int i, FloatArray &valueArr } void -RheoChainMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +RheoChainMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { // printing of hidden variables @@ -757,8 +701,8 @@ RheoChainMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) fprintf(file, "{hidden variables: "); for ( int i = 0; i < nUnits; i++ ) { fprintf(file, "{ "); - for ( auto &val : hiddenVars[i] ) { - fprintf( file, "%f ", val ); + for ( auto &val : hiddenVars [ i ] ) { + fprintf(file, "%f ", val); } fprintf(file, "} "); @@ -767,7 +711,7 @@ RheoChainMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) if ( shrinkageStrain.isNotEmpty() ) { fprintf(file, "shrinkageStrain: {"); for ( auto &val : shrinkageStrain ) { - fprintf( file, "%f ", val ); + fprintf(file, "%f ", val); } fprintf(file, "} "); @@ -786,6 +730,8 @@ RheoChainMaterialStatus :: updateYourself(TimeStep *tStep) this->hiddenVars [ i ] = this->tempHiddenVars [ i ]; } + currentTime = -1.e20; + #ifdef keep_track_of_strains thermalStrain = tempThermalStrain; tempThermalStrain = 0.; @@ -796,21 +742,18 @@ void RheoChainMaterialStatus :: initTempStatus() { StructuralMaterialStatus :: initTempStatus(); + +#ifdef keep_track_of_strains + tempThermalStrain = 0.; +#endif } -contextIOResultType -RheoChainMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// +void +RheoChainMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralMaterialStatus :: saveContext(stream, mode); - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write raw data + contextIOResultType iores; for ( int i = 0; i < nUnits; i++ ) { if ( ( iores = hiddenVars [ i ].storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); @@ -820,24 +763,15 @@ RheoChainMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, voi if ( ( iores = shrinkageStrain.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -RheoChainMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restore the state variables from a stream -// +void +RheoChainMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralMaterialStatus :: restoreContext(stream, mode); - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data + contextIOResultType iores; for ( int i = 0; i < nUnits; i++ ) { if ( ( iores = hiddenVars [ i ].restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); @@ -847,7 +781,5 @@ RheoChainMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, if ( ( iores = shrinkageStrain.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } } // end namespace oofem diff --git a/src/sm/Materials/RheoChainMaterials/rheoChM.h b/src/sm/Materials/RheoChainMaterials/rheoChM.h index 506ddc41d..15846a44f 100644 --- a/src/sm/Materials/RheoChainMaterials/rheoChM.h +++ b/src/sm/Materials/RheoChainMaterials/rheoChM.h @@ -38,14 +38,14 @@ /// thermal, shrinkage (drying & autogenous) and creep strains are stored for export #define keep_track_of_strains -#include "../sm/Materials/structuralmaterial.h" -#include "Materials/linearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +//#include "sm/Materials/linearelasticmaterial.h" #include "floatarray.h" #include "floatmatrix.h" #include "matconst.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Materials/structuralms.h" ///@name Input fields for RheoChainMaterial //@{ @@ -58,7 +58,6 @@ #define _IFT_RheoChainMaterial_endoftimeofinterest "endoftimeofinterest" #define _IFT_RheoChainMaterial_timefactor "timefactor" #define _IFT_RheoChainMaterial_talpha "talpha" -#define _IFT_RheoChainMaterial_preCastingTimeMat "precastingtimemat" //@} namespace oofem { @@ -72,7 +71,7 @@ class RheoChainMaterialStatus : public StructuralMaterialStatus { protected: /// Number of units in the chain. - int nUnits; + int nUnits = 0; /// Hidden (internal) variables, the meaning of which depends on the type of chain. std :: vector< FloatArray >hiddenVars; std :: vector< FloatArray >tempHiddenVars; @@ -83,16 +82,21 @@ class RheoChainMaterialStatus : public StructuralMaterialStatus */ FloatArray shrinkageStrain; + /** Internal variable with the meaning of the solution time + * essential when giveRealStressVector of the viscoelastic material is called + * more than once in one time step and at one time step. + */ + double currentTime = 0.; + #ifdef keep_track_of_strains - double thermalStrain; - double tempThermalStrain; + double thermalStrain = 0.; + double tempThermalStrain = 0.; #endif public: - RheoChainMaterialStatus(int n, Domain *d, GaussPoint *g, int nunits); - virtual ~RheoChainMaterialStatus(); + RheoChainMaterialStatus(GaussPoint *g, int nunits); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; virtual const FloatArray &giveViscoelasticStressVector() const { return stressVector; } @@ -104,11 +108,16 @@ class RheoChainMaterialStatus : public StructuralMaterialStatus FloatArray *giveShrinkageStrainVector() { return & shrinkageStrain; } void setShrinkageStrainVector(FloatArray src) { shrinkageStrain = std :: move(src); } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + /// Returns current time - see explanation near initTempStatus in giveRealStressVector + double giveCurrentTime() { return currentTime; } + /// Stores current time + void setCurrentTime(double src) { currentTime = src; } + + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; #ifdef keep_track_of_strains @@ -118,7 +127,7 @@ class RheoChainMaterialStatus : public StructuralMaterialStatus #endif // definition - virtual const char *giveClassName() const { return "RheoChainMaterialStatus"; } + const char *giveClassName() const override { return "RheoChainMaterialStatus"; } }; @@ -131,31 +140,33 @@ class RheoChainMaterial : public StructuralMaterial { protected: /// thermal dilatation coeff. - double talpha; + double talpha = 0.; /// Number of (Maxwell or Kelvin) units in the rheologic chain. - int nUnits; + int nUnits = 0.; /// Physical age of the material at castingTime - double relMatAge; + double relMatAge = 0.; - bool lattice; + bool lattice = false; /// Poisson's ratio (assumed to be constant, unaffected by creep). - double nu; + double nu = 0.; /// Parameters for the lattice model - double alphaOne, alphaTwo; + double alphaOne = 0., alphaTwo = 0.; /// Time for which the partial moduli of individual units have been evaluated. - double EparValTime; + mutable double EparValTime = -1.; /// Time from which the model should give a good approximation. Optional field. Default value is 0.1 [day]. - double begOfTimeOfInterest; // local one or taken from e-model + double begOfTimeOfInterest = 0.; // local one or taken from e-model /// Time (age???) up to which the model should give a good approximation. - double endOfTimeOfInterest; // local one or taken from e-model + double endOfTimeOfInterest = 0.; // local one or taken from e-model /// Associated linearElasticMaterial, with E = 1. - LinearElasticMaterial *linearElasticMaterial; + // LinearElasticMaterial *linearElasticMaterial = nullptr; + StructuralMaterial *linearElasticMaterial = nullptr; + /// Partial moduli of individual units. - FloatArray EparVal; + mutable FloatArray EparVal; //FloatArray relaxationTimes; /// Characteristic times of individual units (relaxation or retardation times). - FloatArray charTimes; + mutable FloatArray charTimes; /// Times at which the errors are evaluated if the least-square method is used. FloatArray discreteTimeScale; @@ -164,40 +175,59 @@ class RheoChainMaterial : public StructuralMaterial * (gives the number of simulation time units in one day, * e.g. 86400 if the simulation works with seconds as the time units) */ - double timeFactor; - - /// Stiffness at time less than casting time - optional parameter, negative by default - //double zeroStiffness; - - int preCastingTimeMat; + double timeFactor = 0.; public: RheoChainMaterial(int n, Domain *d); virtual ~RheoChainMaterial(); - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_2dBeamLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlateLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } + FloatArrayF< 6 >giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast< RheoChainMaterial * >( this )->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF< 4 >giveRealStressVector_PlaneStrain(const FloatArrayF< 4 > &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast< RheoChainMaterial * >( this )->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF< 3 >giveRealStressVector_PlaneStress(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast< RheoChainMaterial * >( this )->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF< 1 >giveRealStressVector_1d(const FloatArrayF< 1 > &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast< RheoChainMaterial * >( this )->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF< 2 >giveRealStressVector_2dBeamLayer(const FloatArrayF< 2 > &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast< RheoChainMaterial * >( this )->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF< 5 >giveRealStressVector_PlateLayer(const FloatArrayF< 5 > &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast< RheoChainMaterial * >( this )->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + FloatArrayF< 6 >giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; /* virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) * { answer.clear(); }*/ /// Evaluation of the incremental modulus. - virtual double giveEModulus(GaussPoint *gp, TimeStep *tStep) = 0; + virtual double giveEModulus(GaussPoint *gp, TimeStep *tStep) const = 0; /* virtual double giveIncrementalModulus(GaussPoint *gp, TimeStep *tStep) { * if ( (tStep->giveIntrinsicTime() < this->castingTime) && ( this->zeroStiffness > 0. ) ) { @@ -208,53 +238,48 @@ class RheoChainMaterial : public StructuralMaterial * }*/ /// Evaluation of the moduli of individual units. - virtual void computeCharCoefficients(FloatArray &answer, double tPrime, GaussPoint *gp, TimeStep *tStep) = 0; + virtual FloatArray computeCharCoefficients(double tPrime, GaussPoint *gp, TimeStep *tStep) const = 0; // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 0; } - virtual int hasMaterialModeCapability(MaterialMode mode); + bool hasMaterialModeCapability(MaterialMode mode) const override; - virtual int hasCastingTimeSupport() { return 1; } + bool hasCastingTimeSupport() const override { return true; } - virtual const char *giveClassName() const { return "RheoChainMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "RheoChainMaterial"; } + void initializeFrom(InputRecord &ir) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; // store & restore context functions - virtual contextIOResultType saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); - virtual contextIOResultType restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); - - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - virtual void give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void give2dLatticeStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void give3dLatticeStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void computeStressIndependentStrainVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + void saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override; + void restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override; + + /** + * Computes the stiffness matrix for giveRealStressVector of receiver in given integration point, respecting its history. + * The algorithm should use temporary or equilibrium history variables stored in integration point status + * to compute and return required result. + * @param answer Contains result. + * @param mode Material response mode. + * @param gp Integration point. + * @param tStep Time step (most models are able to respond only when tStep is current time step). + */ + /* void giveStiffnessMatrix(FloatMatrix &answer, + * MatResponseMode mode, + * GaussPoint *gp, + * TimeStep *tStep) override; + */ + + FloatMatrixF< 6, 6 >give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 3, 3 >givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 4, 4 >givePlaneStrainStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF< 1, 1 >give1dStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + + // maybe not needed afterall? + // FloatMatrixF< 3, 3 >give2dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + + // FloatMatrixF< 6, 6 >give3dLatticeStiffnessMatrix(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) const; + + FloatArray computeStressIndependentStrainVector(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; /** * Computes, for the given integration point, @@ -267,7 +292,7 @@ class RheoChainMaterial : public StructuralMaterial virtual void giveShrinkageStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, - ValueModeType mode) + ValueModeType mode) const { answer.clear(); } // Note: must take LoadResponseMode into account @@ -279,17 +304,21 @@ class RheoChainMaterial : public StructuralMaterial * @param tStep Time step (most models are able to respond only when tStep is the current time step). * @param mode Determines response mode. */ - virtual void giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) { } + virtual void giveEigenStrainVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const { } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; double giveAlphaOne() const { return this->alphaOne; } double giveAlphaTwo() const { return this->alphaTwo; } + /// Returns Poisson's ratio. + double givePoissonsRatio() const { return nu; } + /// Evaluation of the creep compliance function at time t when loading is acting from time t_prime - virtual double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) = 0; + virtual double computeCreepFunction(double t, double t_prime, GaussPoint *gp, TimeStep *tStep) const = 0; - virtual bool isActivated(TimeStep *tStep) { + /// Extended meaning: returns true if the material is cast (target time > casting time) or the precasing time mat is defined + bool isActivated(TimeStep *tStep) const override { if ( this->preCastingTimeMat > 0 ) { return true; } else { @@ -297,26 +326,30 @@ class RheoChainMaterial : public StructuralMaterial } } + /// By default returns equivalent time in the middle of the time step + virtual double giveEquivalentTime(GaussPoint *gp, TimeStep *tStep) const + { return ( tStep->giveTargetTime() - tStep->giveTimeIncrement() / 2 ); } + protected: /** * If only incremental shrinkage strain formulation is provided, then total shrinkage strain must be tracked * in status in order to be able to compute total value. */ - virtual int hasIncrementalShrinkageFormulation() { return 0; } + virtual bool hasIncrementalShrinkageFormulation() const { return false; } /** * Generates discrete times starting from time "from" to time "to" * uniformly distributed in log time scale. * The time interval (to-from) is divided to nsteps intervals. * We return times starting from ("from" + first increment) - * @param answer Resulting array of discrete times. * @param from Starting time * @param to End time * @param nsteps Number of discrete steps. + * @return Resulting array of discrete times. */ - static void generateLogTimeScale(FloatArray &answer, double from, double to, int nsteps); - const FloatArray &giveDiscreteTimes(); + static FloatArray generateLogTimeScale(double from, double to, int nsteps); + const FloatArray &giveDiscreteTimes() const; /** * Evaluation of the relaxation function at given times. @@ -333,18 +366,18 @@ class RheoChainMaterial : public StructuralMaterial * @param tSteps At which times the relaxation function will be evaluated. * @warning tSteps should be uniformly distributed in log time scale and relatively dense (100 intervals) in order to achieve a reasonable accuracy. */ - void computeDiscreteRelaxationFunction(FloatArray &answer, const FloatArray &tSteps, double t0, double tr, GaussPoint *gp, TimeStep *tSte); + void computeDiscreteRelaxationFunction(FloatArray &answer, const FloatArray &tSteps, double t0, double tr, GaussPoint *gp, TimeStep *tStep) const; /// Evaluation of elastic compliance matrix for unit Young's modulus. - void giveUnitComplianceMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); + void giveUnitComplianceMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) const; /// Evaluation of elastic stiffness matrix for unit Young's modulus. - void giveUnitStiffnessMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); + void giveUnitStiffnessMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) const; /// Update of partial moduli of individual chain units - virtual void updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *tStep); + virtual void updateEparModuli(double tPrime, GaussPoint *gp, TimeStep *tStep) const; /// Access to partial modulus of a given unit - double giveEparModulus(int iChain); + double giveEparModulus(int iChain) const; /// Evaluation of characteristic times virtual void computeCharTimes(); @@ -353,17 +386,17 @@ class RheoChainMaterial : public StructuralMaterial double giveCharTime(int) const; /// Exponent to be used with the char time of a given unit, usually = 1.0 - virtual double giveCharTimeExponent(int i) { return 1.0; } + virtual double giveCharTimeExponent(int i) const { return 1.0; } /// Access to the underlying linear elastic material with unit Young's modulus - LinearElasticMaterial *giveLinearElasticMaterial(); + // LinearElasticMaterial *giveLinearElasticMaterial(); + StructuralMaterial *giveLinearElasticMaterial(); /// Access to the time up to which the response should be accurate double giveEndOfTimeOfInterest(); /** * Computes, for the given integration point, - * the strain vector induced by stress-independent * internal processes in the material. * Takes into account only temperature and shrinkage-induced strains. * @param answer Returned strain vector. @@ -372,7 +405,7 @@ class RheoChainMaterial : public StructuralMaterial * @param mode Determines response mode (Total or incremental). */ void computeTrueStressIndependentStrainVector(FloatArray &answer, GaussPoint *gp, - TimeStep *tStep, ValueModeType mode); + TimeStep *tStep, ValueModeType mode) const; }; } // end namespace oofem #endif // rheochm_h diff --git a/src/sm/Materials/abaqususermaterial.C b/src/sm/Materials/abaqususermaterial.C index 8b66cdb1f..b40f1c9d6 100644 --- a/src/sm/Materials/abaqususermaterial.C +++ b/src/sm/Materials/abaqususermaterial.C @@ -34,6 +34,8 @@ #include "abaqususermaterial.h" #include "gausspoint.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "classfactory.h" #include "dynamicinputrecord.h" @@ -48,21 +50,18 @@ namespace oofem { REGISTER_Material(AbaqusUserMaterial); -int AbaqusUserMaterial :: n = 1; +int const AbaqusUserMaterial::abq2oo9[ 9 ] = { 0, 1, 2, 5, 4, 3, 6, 8, 7 }; +int const AbaqusUserMaterial::abq2oo6[ 6 ] = { 0, 1, 2, 5, 4, 3 }; -AbaqusUserMaterial :: AbaqusUserMaterial(int n, Domain *d) : - StructuralMaterial(n, d), - umatobj(NULL), umat(NULL), - mStressInterpretation(0), - mUseNumericalTangent(false), - mPerturbation(1.0e-7) +AbaqusUserMaterial::AbaqusUserMaterial(int n, Domain *d) : + StructuralMaterial(n, d) { } -AbaqusUserMaterial :: ~AbaqusUserMaterial() +AbaqusUserMaterial::~AbaqusUserMaterial() { #ifdef _WIN32 if ( this->umatobj ) { - FreeLibrary( ( HMODULE ) this->umatobj ); + FreeLibrary( ( HMODULE ) this->umatobj); } #else if ( this->umatobj ) { @@ -72,32 +71,33 @@ AbaqusUserMaterial :: ~AbaqusUserMaterial() #endif } -IRResultType AbaqusUserMaterial :: initializeFrom(InputRecord *ir) +void AbaqusUserMaterial::initializeFrom(InputRecord &ir) { - IRResultType result; - std :: string umatname; + std::string umatname; - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + StructuralMaterial::initializeFrom(ir); IR_GIVE_FIELD(ir, this->numState, _IFT_AbaqusUserMaterial_numState); IR_GIVE_FIELD(ir, this->properties, _IFT_AbaqusUserMaterial_properties); IR_GIVE_FIELD(ir, this->filename, _IFT_AbaqusUserMaterial_userMaterial); umatname = "umat"; IR_GIVE_OPTIONAL_FIELD(ir, umatname, _IFT_AbaqusUserMaterial_name); - strncpy(this->cmname, umatname.c_str(), 80); - IR_GIVE_OPTIONAL_FIELD(ir, this->initialStress, _IFT_AbaqusUserMaterial_initialStress); + strncpy(this->cmname, umatname.c_str(), 79); + + FloatArray s(6); + IR_GIVE_OPTIONAL_FIELD(ir, s, _IFT_AbaqusUserMaterial_initialStress); + this->initialStress = s; #ifdef _WIN32 ///@todo Check all the windows support. - this->umatobj = ( void * ) LoadLibrary( filename.c_str() ); + this->umatobj = ( void * ) LoadLibrary(filename.c_str() ); if ( !this->umatobj ) { DWORD dlresult = GetLastError(); //works for MinGW 32bit and MSVC OOFEM_ERROR("Couldn't load \"%s\",\nerror code = %d", filename.c_str(), dlresult); } // * ( void ** )( & this->umat ) = GetProcAddress( ( HMODULE ) this->umatobj, "umat_" ); - * ( FARPROC * ) ( & this->umat ) = GetProcAddress( ( HMODULE ) this->umatobj, "umat_" ); //works for MinGW 32bit + * ( FARPROC * ) ( & this->umat ) = GetProcAddress( ( HMODULE ) this->umatobj, "umat_"); //works for MinGW 32bit if ( !this->umat ) { // char *dlresult = GetLastError(); DWORD dlresult = GetLastError(); //works for MinGW 32bit @@ -107,7 +107,7 @@ IRResultType AbaqusUserMaterial :: initializeFrom(InputRecord *ir) #else this->umatobj = dlopen(filename.c_str(), RTLD_NOW); if ( !this->umatobj ) { - OOFEM_ERROR("couldn't load \"%s\",\ndlerror: %s", filename.c_str(), dlerror() ); + OOFEM_ERROR( "couldn't load \"%s\",\ndlerror: %s", filename.c_str(), dlerror() ); } * ( void ** ) ( & this->umat ) = dlsym(this->umatobj, "umat_"); @@ -119,21 +119,19 @@ IRResultType AbaqusUserMaterial :: initializeFrom(InputRecord *ir) #endif - if ( ir->hasField(_IFT_AbaqusUserMaterial_numericalTangent) ) { + if ( ir.hasField(_IFT_AbaqusUserMaterial_numericalTangent) ) { mUseNumericalTangent = true; } - if ( ir->hasField(_IFT_AbaqusUserMaterial_numericalTangentPerturbation) ) { + if ( ir.hasField(_IFT_AbaqusUserMaterial_numericalTangentPerturbation) ) { IR_GIVE_OPTIONAL_FIELD(ir, mPerturbation, _IFT_AbaqusUserMaterial_numericalTangentPerturbation); printf("mPerturbation: %e\n", mPerturbation); } - - return IRRT_OK; } -void AbaqusUserMaterial :: giveInputRecord(DynamicInputRecord &input) +void AbaqusUserMaterial::giveInputRecord(DynamicInputRecord &input) { - StructuralMaterial :: giveInputRecord(input); + StructuralMaterial::giveInputRecord(input); input.setField(this->numState, _IFT_AbaqusUserMaterial_numState); input.setField(this->properties, _IFT_AbaqusUserMaterial_properties); @@ -141,31 +139,29 @@ void AbaqusUserMaterial :: giveInputRecord(DynamicInputRecord &input) input.setField(std::string(this->cmname), _IFT_AbaqusUserMaterial_name); } -MaterialStatus *AbaqusUserMaterial :: CreateStatus(GaussPoint *gp) const +MaterialStatus *AbaqusUserMaterial::CreateStatus(GaussPoint *gp) const { - return new AbaqusUserMaterialStatus(n++, this->giveDomain(), gp, this->numState); + return new AbaqusUserMaterialStatus(gp, this->numState); } -void AbaqusUserMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 6, 6 > +AbaqusUserMaterial::give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - AbaqusUserMaterialStatus *ms = dynamic_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) ); + auto ms = dynamic_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) ); if ( !ms->hasTangent() ) { ///@todo Make this hack fit more nicely into OOFEM in general; // Evaluating the function once, so that the tangent can be obtained. - FloatArray stress(6), strain(6); - strain.zero(); - this->giveRealStressVector_3d(stress, gp, strain, tStep); + const_cast< AbaqusUserMaterial * >( this )->giveRealStressVector_3d(zeros< 6 >(), gp, tStep); } - answer = ms->giveTempTangent(); + return ms->giveTempTangent(); #if 0 double h = 1e-7; FloatArray strain, strainh, stress, stressh; strain = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveTempStrainVector(); stress = static_cast< StructuralMaterialStatus * >( gp->giveMaterialStatus() )->giveTempStressVector(); - FloatMatrix En( strain.giveSize(), strain.giveSize() ); + FloatMatrix En(strain.giveSize(), strain.giveSize() ); for ( int i = 1; i <= strain.giveSize(); ++i ) { strainh = strain; strainh.at(i) += h; @@ -184,20 +180,19 @@ void AbaqusUserMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, } -void AbaqusUserMaterial :: give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 9, 9 > +AbaqusUserMaterial::give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - AbaqusUserMaterialStatus *ms = dynamic_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) ); + auto ms = dynamic_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) ); if ( !ms->hasTangent() ) { ///@todo Make this hack fit more nicely into OOFEM in general; // Evaluating the function once, so that the tangent can be obtained. - FloatArray stress, vF; - vF = ms->giveTempFVector(); - this->giveFirstPKStressVector_3d(stress, gp, vF, tStep); + const auto &vF = ms->giveTempFVector(); + this->giveFirstPKStressVector_3d(vF, gp, tStep); } if ( !mUseNumericalTangent ) { // if(mStressInterpretation == 0) { - answer = ms->giveTempTangent(); + return ms->giveTempTangent(); /* * } * else { @@ -208,23 +203,21 @@ void AbaqusUserMaterial :: give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answe * this->give_dPdF_from(dSdE, answer, gp); * } */ - } else { + } else { double h = mPerturbation; - FloatArray vF, vF_h, stress, stressh; - vF = ms->giveTempFVector(); - stress = ( ( StructuralMaterialStatus * ) gp->giveMaterialStatus() )->giveTempPVector(); - FloatMatrix En(9, 9); + auto const &vF = ms->giveTempFVector(); + auto const &stress = ms->giveTempPVector(); + FloatMatrixF< 9, 9 >En; for ( int i = 1; i <= 9; ++i ) { - vF_h = vF; + auto vF_h = vF; vF_h.at(i) += h; - this->giveFirstPKStressVector_3d(stressh, gp, vF_h, tStep); - stressh.subtract(stress); - stressh.times(1.0 / h); - En.setColumn(stressh, i); + auto stressh = this->giveFirstPKStressVector_3d(vF_h, gp, tStep); + auto ds = ( stressh - stress ) * ( 1. / h ); + En.setColumn(ds, i); } // Reset - this->giveFirstPKStressVector_3d(stressh, gp, vF, tStep); + this->giveFirstPKStressVector_3d(vF, gp, tStep); /* * printf("En = "); @@ -239,23 +232,23 @@ void AbaqusUserMaterial :: give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answe * printf("diff: "); diff.printYourself(); */ - answer = En; + return En; } } -void AbaqusUserMaterial :: givePlaneStrainStiffMtrx_dPdF(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF< 5, 5 > +AbaqusUserMaterial::givePlaneStrainStiffnessMatrix_dPdF(MatResponseMode mmode, GaussPoint *gp, + TimeStep *tStep) const { - FloatMatrix dPdF3d; - this->give3dMaterialStiffnessMatrix_dPdF(dPdF3d, mmode, gp, tStep); - StructuralMaterial :: giveReducedMatrixForm(answer, dPdF3d, _PlaneStrain); + auto dPdF3D = this->give3dMaterialStiffnessMatrix_dPdF(mmode, gp, tStep); + return dPdF3D({ 0, 1, 2, 5, 8 }, { 0, 1, 2, 5, 8 }); } -void AbaqusUserMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF< 6 > +AbaqusUserMaterial::giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, + TimeStep *tStep) const { - AbaqusUserMaterialStatus *ms = static_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) ); /* User-defined material name, left justified. Some internal material models are given names starting with * the “ABQ_†character string. To avoid conflict, you should not use “ABQ_†as the leading string for * CMNAME. */ @@ -266,14 +259,11 @@ void AbaqusUserMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoin int nshr = 3; int ntens = ndi + nshr; - FloatArray strain = ms->giveStrainVector(); - FloatArray stress = ms->giveStressVector(); - // adding the initial stress - stress.add(initialStress); - FloatArray strainIncrement; - strainIncrement.beDifferenceOf(reducedStrain, strain); - FloatArray state = ms->giveStateVector(); - FloatMatrix jacobian(ntens, ntens); + FloatArrayF< 6 >old_strain = ms->giveStrainVector(); + FloatArrayF< 6 >old_stress = initialStress + ms->giveStressVector(); + auto strainIncrement = strain - old_strain; + auto state = ms->giveStateVector(); + FloatMatrixF< 6, 6 >abq_jacobian; int numProperties = this->properties.giveSize(); // Temperature and increment @@ -282,7 +272,7 @@ void AbaqusUserMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoin // Times and increment double dtime = tStep->giveTimeIncrement(); ///@todo Check this. I'm just guessing. Maybe intrinsic time instead? - double time [ 2 ] = { + double time[ 2 ] = { tStep->giveTargetTime() - dtime, tStep->giveTargetTime() }; double pnewdt = 1.0; ///@todo Right default value? umat routines may change this (although we ignore it) @@ -295,15 +285,15 @@ void AbaqusUserMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoin // Outputs only in a fully coupled thermal-stress analysis: double rpl = 0.0; // Volumetric heat generation per unit time at the end of the increment caused by mechanical working of the material. - FloatArray ddsddt(ntens); // Variation of the stress increments with respect to the temperature. - FloatArray drplde(ntens); // Variation of RPL with respect to the strain increments. + FloatArrayF< 6 >ddsddt; // Variation of the stress increments with respect to the temperature. + FloatArrayF< 6 >drplde; // Variation of RPL with respect to the strain increments. double drpldt = 0.0; // Variation of RPL with respect to the temperature. /* An array containing the coordinates of this point. These are the current coordinates if geometric * nonlinearity is accounted for during the step (see “Procedures: overview,†Section 6.1.1); otherwise, * the array contains the original coordinates of the point */ FloatArray coords; - gp->giveElement()->computeGlobalCoordinates( coords, gp->giveNaturalCoordinates() ); + gp->giveElement()->computeGlobalCoordinates(coords, gp->giveNaturalCoordinates() ); /* Rotation increment matrix. This matrix represents the increment of rigid body rotation of the basis * system in which the components of stress (STRESS) and strain (STRAN) are stored. It is provided so @@ -311,8 +301,7 @@ void AbaqusUserMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoin * strain components are already rotated by this amount before UMAT is called. This matrix is passed in * as a unit matrix for small-displacement analysis and for large-displacement analysis if the basis system * for the material point rotates with the material (as in a shell element or when a local orientation is used).*/ - FloatMatrix drot(3, 3); - drot.beUnitMatrix(); + auto drot = eye< 3 >(); /* Characteristic element length, which is a typical length of a line across an element for a first-order * element; it is half of the same typical length for a second-order element. For beams and trusses it is a @@ -324,14 +313,12 @@ void AbaqusUserMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoin /* Array containing the deformation gradient at the beginning of the increment. See the discussion * regarding the availability of the deformation gradient for various element types. */ - FloatMatrix dfgrd0(3, 3); - dfgrd0.beUnitMatrix(); + auto dfgrd0 = eye< 3 >(); /* Array containing the deformation gradient at the end of the increment. The components of this array * are set to zero if nonlinear geometric effects are not included in the step definition associated with * this increment. See the discussion regarding the availability of the deformation gradient for various * element types. */ - FloatMatrix dfgrd1(3, 3); - dfgrd1.beUnitMatrix(); + auto dfgrd1 = eye< 3 >(); int noel = gp->giveElement()->giveNumber(); // Element number. int npt = 0; // Integration point number. @@ -346,16 +333,16 @@ void AbaqusUserMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoin double dpred; // Change to Abaqus's component order - stress.changeComponentOrder(); - strain.changeComponentOrder(); - strainIncrement.changeComponentOrder(); + auto abq_stress = old_stress [ abq2oo6 ]; + auto abq_old_strain = old_strain [ abq2oo6 ]; + auto abq_strainIncrement = strainIncrement [ abq2oo6 ]; // printf("stress oofem: "); stress.printYourself(); OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector_3d - Calling subroutine"); - this->umat(stress.givePointer(), // STRESS + this->umat(abq_stress.givePointer(), // STRESS state.givePointer(), // STATEV - jacobian.givePointer(), // DDSDDE + abq_jacobian.givePointer(), // DDSDDE & sse, // SSE & spd, // SPD & scd, // SCD @@ -363,20 +350,20 @@ void AbaqusUserMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoin ddsddt.givePointer(), // DDSDDT drplde.givePointer(), // DRPLDE & drpldt, // DRPLDT - strain.givePointer(), // STRAN - strainIncrement.givePointer(), // DSTRAN + abq_old_strain.givePointer(), // STRAN + abq_strainIncrement.givePointer(), // DSTRAN time, // TIME & dtime, // DTIME & temp, // TEMP & dtemp, // DTEMP & predef, // PREDEF & dpred, // DPRED - this->cmname, // CMNAME + const_cast< AbaqusUserMaterial * >( this )->cmname, // CMNAME & ndi, // NDI & nshr, // NSHR & ntens, // NTENS - & numState, // NSTATV - properties.givePointer(), // PROPS + const_cast< int * >( & numState ), // NSTATV + const_cast< AbaqusUserMaterial * >( this )->properties.givePointer(), // PROPS & numProperties, // NPROPS coords.givePointer(), // COORDS drot.givePointer(), // DROT @@ -392,27 +379,23 @@ void AbaqusUserMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoin & kinc); // KINC // Change to OOFEM's component order - stress.changeComponentOrder(); + auto jacobian = abq_jacobian(abq2oo6, abq2oo6); // subtracking the initial stress - stress.subtract(initialStress); - strain.changeComponentOrder(); - strainIncrement.changeComponentOrder(); - jacobian.changeComponentOrder(); + auto stress = abq_stress [ abq2oo6 ] - initialStress; - ms->letTempStrainVectorBe(reducedStrain); + ms->letTempStrainVectorBe(strain); ms->letTempStressVectorBe(stress); ms->letTempStateVectorBe(state); ms->letTempTangentBe(jacobian); - answer = stress; - - OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector - Calling subroutine was successful"); + return stress; } -void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &vF, TimeStep *tStep) +FloatArrayF< 9 > +AbaqusUserMaterial::giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, + TimeStep *tStep) const { - AbaqusUserMaterialStatus *ms = static_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) ); /* User-defined material name, left justified. Some internal material models are given names starting with * the “ABQ_†character string. To avoid conflict, you should not use “ABQ_†as the leading string for * CMNAME. */ @@ -423,24 +406,16 @@ void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussP int nshr = 3; int ntens = ndi + nshr; - FloatArray stress(9); // PK1 - FloatArray strainIncrement; + FloatArrayF< 9 >abq_stress; // PK1 or cauchy // compute Green-Lagrange strain - FloatArray strain; - FloatArray vS; - FloatMatrix F, E; - F.beMatrixForm(vF); - E.beTProductOf(F, F); - E.at(1, 1) -= 1.0; - E.at(2, 2) -= 1.0; - E.at(3, 3) -= 1.0; - E.times(0.5); - strain.beSymVectorFormOfStrain(E); - - strainIncrement.beDifferenceOf(strain, ms->giveStrainVector()); + auto F = from_voigt_form(vF); + auto E = 0.5 * ( Tdot(F, F) - eye< 3 >() ); + auto strain = to_voigt_strain(E); + + auto strainIncrement = strain - FloatArrayF< 6 >( ms->giveStrainVector() ); FloatArray state = ms->giveStateVector(); - FloatMatrix jacobian(9, 9); // dPdF + FloatMatrixF< 9, 9 >abq_jacobian; // dPdF int numProperties = this->properties.giveSize(); // Temperature and increment @@ -449,7 +424,7 @@ void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussP // Times and increment double dtime = tStep->giveTimeIncrement(); ///@todo Check this. I'm just guessing. Maybe intrinsic time instead? - double time [ 2 ] = { + double time[ 2 ] = { tStep->giveTargetTime() - dtime, tStep->giveTargetTime() }; double pnewdt = 1.0; ///@todo Right default value? umat routines may change this (although we ignore it) @@ -470,7 +445,7 @@ void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussP * nonlinearity is accounted for during the step (see “Procedures: overview,†Section 6.1.1); otherwise, * the array contains the original coordinates of the point */ FloatArray coords; - gp->giveElement()->computeGlobalCoordinates( coords, gp->giveNaturalCoordinates() ); ///@todo Large deformations? + gp->giveElement()->computeGlobalCoordinates(coords, gp->giveNaturalCoordinates() ); ///@todo Large deformations? /* Rotation increment matrix. This matrix represents the increment of rigid body rotation of the basis * system in which the components of stress (STRESS) and strain (STRAN) are stored. It is provided so @@ -478,8 +453,7 @@ void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussP * strain components are already rotated by this amount before UMAT is called. This matrix is passed in * as a unit matrix for small-displacement analysis and for large-displacement analysis if the basis system * for the material point rotates with the material (as in a shell element or when a local orientation is used).*/ - FloatMatrix drot(3, 3); - drot.beUnitMatrix(); + auto drot = eye< 3 >(); /* Characteristic element length, which is a typical length of a line across an element for a first-order * element; it is half of the same typical length for a second-order element. For beams and trusses it is a @@ -491,15 +465,12 @@ void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussP /* Array containing the deformation gradient at the beginning of the increment. See the discussion * regarding the availability of the deformation gradient for various element types. */ - FloatMatrix dfgrd0(3, 3); + auto dfgrd0 = from_voigt_form(ms->giveFVector() ); /* Array containing the deformation gradient at the end of the increment. The components of this array * are set to zero if nonlinear geometric effects are not included in the step definition associated with * this increment. See the discussion regarding the availability of the deformation gradient for various * element types. */ - FloatMatrix dfgrd1(3, 3); - - dfgrd0.beMatrixForm( ms->giveFVector() ); - dfgrd1.beMatrixForm(vF); + auto dfgrd1 = from_voigt_form(vF); int noel = gp->giveElement()->giveNumber(); // Element number. int npt = 0; // Integration point number. @@ -515,14 +486,13 @@ void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussP double dpred; // Change to Abaqus's component order - stress.changeComponentOrder(); - strain.changeComponentOrder(); - strainIncrement.changeComponentOrder(); + auto abq_strain = strain [ abq2oo6 ]; + auto abq_strainIncrement = strainIncrement [ abq2oo6 ]; OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector - Calling subroutine"); - this->umat(stress.givePointer(), // STRESS + this->umat(abq_stress.givePointer(), // STRESS state.givePointer(), // STATEV - jacobian.givePointer(), // DDSDDE + abq_jacobian.givePointer(), // DDSDDE & sse, // SSE & spd, // SPD & scd, // SCD @@ -530,20 +500,20 @@ void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussP ddsddt.givePointer(), // DDSDDT drplde.givePointer(), // DRPLDE & drpldt, // DRPLDT - strain.givePointer(), // STRAN - strainIncrement.givePointer(), // DSTRAN + abq_strain.givePointer(), // STRAN + abq_strainIncrement.givePointer(), // DSTRAN time, // TIME & dtime, // DTIME & temp, // TEMP & dtemp, // DTEMP & predef, // PREDEF & dpred, // DPRED - this->cmname, // CMNAME + const_cast< char * >( this->cmname ), // CMNAME & ndi, // NDI & nshr, // NSHR & ntens, // NTENS - & numState, // NSTATV - properties.givePointer(), // PROPS + const_cast< int * >( & numState ), // NSTATV + const_cast< double * >( properties.givePointer() ), // PROPS & numProperties, // NPROPS coords.givePointer(), // COORDS drot.givePointer(), // DROT @@ -560,24 +530,15 @@ void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussP // Change to OOFEM's component order - stress.changeComponentOrder(); - strain.changeComponentOrder(); - strainIncrement.changeComponentOrder(); - jacobian.changeComponentOrder(); - + auto jacobian = abq_jacobian(abq2oo9, abq2oo9); if ( mStressInterpretation == 0 ) { - FloatMatrix P, cauchyStress; - P.beMatrixForm(stress); - - FloatArray vP; - vP.beVectorForm(P); - - cauchyStress.beProductTOf(P, F); - cauchyStress.times( 1.0 / F.giveDeterminant() ); + auto stress = abq_stress [ abq2oo9 ]; + auto P = from_voigt_form(stress); + auto vP = to_voigt_form(P); - FloatArray vCauchyStress; - vCauchyStress.beSymVectorForm(cauchyStress); + auto cauchyStress = dotT(P, F) * ( 1. / det(F) ); + auto vCauchyStress = to_voigt_stress(cauchyStress); ms->letTempStrainVectorBe(strain); ms->letTempStressVectorBe(vCauchyStress); @@ -586,21 +547,18 @@ void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussP ms->letTempPVectorBe(vP); ms->letTempFVectorBe(vF); - answer = vP; - } else { - FloatArray vP; - FloatMatrix P, sigma, F_inv; - F_inv.beInverseOf(F); + return vP; + } else { + auto vsigma = abq_stress [ abq2oo6 ]; + auto sigma = from_voigt_stress(vsigma); - sigma.beMatrixForm(stress); - P.beProductOf(F, sigma); - vP.beVectorForm(P); - answer = vP; + auto P = dot(F, sigma); + auto vP = to_voigt_form(P); // Convert from sigma to S - FloatMatrix S; - S.beProductOf(F_inv, P); - vS.beSymVectorForm(S); + auto F_inv = inv(F); + auto S = dot(F_inv, P); + auto vS = to_voigt_stress(S); // @todo Should convert from dsigmadE to dSdE here // L2=detF*matmul( matmul ( inv(op_a_V9(F,F), cm-op_a_V9(ident,Tau)-op_b_V9(Tau,ident) ), inv(op_a_V9(Ft,Ft))) @@ -611,15 +569,15 @@ void AbaqusUserMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussP ms->letTempTangentBe(jacobian); ms->letTempPVectorBe(vP); ms->letTempFVectorBe(vF); - } - OOFEM_LOG_DEBUG("AbaqusUserMaterial :: giveRealStressVector_3d - Calling subroutine was successful"); + return vP; + } } -int AbaqusUserMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +int AbaqusUserMaterial::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - AbaqusUserMaterialStatus *ms = static_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< AbaqusUserMaterialStatus * >( this->giveStatus(gp) ); if ( type == IST_Undefined || type == IST_AbaqusStateVector ) { // The undefined value is used to just dump the entire state vector. answer = ms->giveStateVector(); @@ -629,46 +587,42 @@ int AbaqusUserMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, Intern answer.add(initialStress); return 1; } else { - return StructuralMaterial :: giveIPValue(answer, gp, type, tStep); + return StructuralMaterial::giveIPValue(answer, gp, type, tStep); } } -void AbaqusUserMaterialStatus :: initTempStatus() +void AbaqusUserMaterialStatus::initTempStatus() { - StructuralMaterialStatus :: initTempStatus(); + StructuralMaterialStatus::initTempStatus(); tempStateVector = stateVector; } -AbaqusUserMaterialStatus :: AbaqusUserMaterialStatus(int n, Domain *d, GaussPoint *gp, int numState) : - StructuralMaterialStatus(n, d, gp), +AbaqusUserMaterialStatus::AbaqusUserMaterialStatus(GaussPoint *gp, int numState) : + StructuralMaterialStatus(gp), numState(numState), stateVector(numState), tempStateVector(numState), hasTangentFlag(false) { strainVector.resize(6); strainVector.zero(); } -void AbaqusUserMaterialStatus :: updateYourself(TimeStep *tStep) +void AbaqusUserMaterialStatus::updateYourself(TimeStep *tStep) { - StructuralMaterialStatus :: updateYourself(tStep); + StructuralMaterialStatus::updateYourself(tStep); stateVector = tempStateVector; } -void AbaqusUserMaterialStatus :: printOutputAt(FILE *File, TimeStep *tStep) -// Prints the strains and stresses on the data file. +void AbaqusUserMaterialStatus::printOutputAt(FILE *File, TimeStep *tStep) const { - StructuralMaterialStatus :: printOutputAt(File, tStep); + StructuralMaterialStatus::printOutputAt(File, tStep); fprintf(File, " stateVector "); FloatArray state = this->giveStateVector(); for ( auto &var : state ) { - fprintf( File, " % .4e", var ); + fprintf(File, " % .4e", var); } fprintf(File, "\n"); } - - - } // end namespace oofem diff --git a/src/sm/Materials/abaqususermaterial.h b/src/sm/Materials/abaqususermaterial.h index 3e73bab0a..bc442e20c 100644 --- a/src/sm/Materials/abaqususermaterial.h +++ b/src/sm/Materials/abaqususermaterial.h @@ -35,9 +35,10 @@ #ifndef abaqususermaterial_h #define abaqususermaterial_h -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "floatarray.h" +#include "floatarrayf.h" #include "floatmatrix.h" ///@name Input fields for AbaqusUserMaterial @@ -80,49 +81,51 @@ namespace oofem { class AbaqusUserMaterial : public StructuralMaterial { private: - /// Gausspoint counter - static int n; /// Dynamically loaded umat. - void *umatobj; + void *umatobj = nullptr; /// Pointer to the dynamically loaded umat-function (translated to C) - void ( * umat )(double *stress, double *statev, double *ddsdde, double *sse, double *spd, // 5 - double *scd, double *rpl, double *ddsddt, double *drplde, double *drpldt, // 5 - double *stran, double *dstran, double time [ 2 ], double *dtime, double *temp, // 4 - double *dtemp, double predef [ 1 ], double dpred [ 1 ], char cmname [ 80 ], int *ndi, // 5 - int *nshr, int *ntens, int *nstatv, double *props, int *nprops, double coords [ 3 ], // 6 - double *drot, double *pnewdt, double *celent, double *dfgrd0, double *dfgrd1, // 5 - int *noel, int *npt, int *layer, int *kspt, int *kstep, int *kinc); // 6 + void ( *umat )(double *stress, double *statev, double *ddsdde, double *sse, double *spd, // 5 + double *scd, double *rpl, double *ddsddt, double *drplde, double *drpldt, // 5 + double *stran, double *dstran, double time[ 2 ], double *dtime, double *temp, // 4 + double *dtemp, double predef[ 1 ], double dpred[ 1 ], char cmname[ 80 ], int *ndi, // 5 + int *nshr, int *ntens, int *nstatv, double *props, int *nprops, double coords[ 3 ], // 6 + double *drot, double *pnewdt, double *celent, double *dfgrd0, double *dfgrd1, // 5 + int *noel, int *npt, int *layer, int *kspt, int *kstep, int *kinc) = nullptr; // 6 /// Name for material routine. - char cmname [ 80 ]; + char cmname[ 80 ]; /// Size of the state vector. - int numState; + int numState = 0; + /// Material properties. FloatArray properties; /// Initial stress. - FloatArray initialStress; + FloatArrayF< 6 >initialStress; /** * Flag to determine how the stress and Jacobian are interpreted. * 0 implies that the P and dPdF are returned from the umat routine. */ - int mStressInterpretation; + int mStressInterpretation = 0; /** * Flag to determine if numerical tangent should be used. */ - bool mUseNumericalTangent; + bool mUseNumericalTangent = false; /** * Size of perturbation if numerical tangent is used. */ - double mPerturbation; + double mPerturbation = 1e-7; /// Name of the file that contains the umat function - std :: string filename; + std::string filename; + + static int const abq2oo9[ 9 ]; + static int const abq2oo6[ 6 ]; public: /// Constructor. - AbaqusUserMaterial(int n, Domain * d); + AbaqusUserMaterial(int n, Domain *d); /// Destructor. virtual ~AbaqusUserMaterial(); @@ -133,34 +136,30 @@ class AbaqusUserMaterial : public StructuralMaterial * - umat (required, string): Filename of umat file dynamically library. * - name (optional, string, default "umat"): Name of material model (used for input to umat routine). */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF< 6, 6 >give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF< 9, 9 >give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const override; - virtual void givePlaneStrainStiffMtrx_dPdF(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF< 5, 5 >givePlaneStrainStiffnessMatrix_dPdF(MatResponseMode mmode, GaussPoint *gp, + TimeStep *tStep) const override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + FloatArrayF< 6 >giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, + TimeStep *tStep) const override; - virtual void giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedF, TimeStep *tStep); + FloatArrayF< 9 >giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, + TimeStep *tStep) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual int hasNonLinearBehaviour() { return true; } - virtual const char *giveClassName() const { return "AbaqusUserMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_AbaqusUserMaterial_Name; } + const char *giveClassName() const override { return "AbaqusUserMaterial"; } + const char *giveInputRecordName() const override { return _IFT_AbaqusUserMaterial_Name; } }; class AbaqusUserMaterialStatus : public StructuralMaterialStatus @@ -180,12 +179,10 @@ class AbaqusUserMaterialStatus : public StructuralMaterialStatus public: /// Constructor. - AbaqusUserMaterialStatus(int n, Domain * d, GaussPoint * gp, int numState); - /// Destructor. - virtual ~AbaqusUserMaterialStatus() { } + AbaqusUserMaterialStatus(GaussPoint *gp, int numState); - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; bool hasTangent() const { return hasTangentFlag; } @@ -195,15 +192,13 @@ class AbaqusUserMaterialStatus : public StructuralMaterialStatus FloatArray &letTempStateVectorBe(FloatArray &s) { return tempStateVector = s; } const FloatMatrix &giveTempTangent() { return tempTangent; } void letTempTangentBe(FloatMatrix t) { - tempTangent = std :: move(t); + tempTangent = std::move(t); hasTangentFlag = true; } - - - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual const char *giveClassName() const { return "AbaqusUserMaterialStatus"; } + const char *giveClassName() const override { return "AbaqusUserMaterialStatus"; } }; } // end namespace oofem #endif // abaqususermaterial_h diff --git a/src/sm/Materials/anisodamagemodel.C b/src/sm/Materials/anisodamagemodel.C index 7add6fb96..bcdebeeed 100644 --- a/src/sm/Materials/anisodamagemodel.C +++ b/src/sm/Materials/anisodamagemodel.C @@ -37,7 +37,7 @@ // published in Engineering Fracture Mechanics 74 (2007) 1539-1560. #include "anisodamagemodel.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "floatmatrix.h" #include "floatarray.h" #include "mathfem.h" @@ -50,34 +50,13 @@ namespace oofem { REGISTER_Material(AnisotropicDamageMaterial); -AnisotropicDamageMaterial :: AnisotropicDamageMaterial(int n, Domain *d) : StructuralMaterial(n, d) - // - // constructor - // -{ - linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); - E = 0.; - nu = 0.; - equivStrainType = EST_Unknown; - damageLawType = DLT_Unknown; - kappa0 = 0.; - kappaf = 0.; - aA = 0.; -} +AnisotropicDamageMaterial :: AnisotropicDamageMaterial(int n, Domain *d) : StructuralMaterial(n, d), + linearElasticMaterial(n, d) +{} -AnisotropicDamageMaterial :: ~AnisotropicDamageMaterial() -// -// destructor -// -{ - delete linearElasticMaterial; -} -int -AnisotropicDamageMaterial :: hasMaterialModeCapability(MaterialMode mode) -// -// returns whether receiver supports the given mode -// +bool +AnisotropicDamageMaterial :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _3dMat || mode == _PlaneStress; //return mode == _3dMat || mode == _PlaneStress || mode == _PlaneStrain || mode == _1dMat; @@ -88,9 +67,8 @@ AnisotropicDamageMaterial :: hasMaterialModeCapability(MaterialMode mode) // plane stress implementation by Milan Jirasek //******************************************************** -void -AnisotropicDamageMaterial :: giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, - const FloatArray &totalStrain, TimeStep *atTime) +FloatArrayF<3> +AnisotropicDamageMaterial :: giveRealStressVector_PlaneStress(const FloatArrayF<3> &totalStrain, GaussPoint *gp, TimeStep *atTime) const // // special version of the stress-evaluation algorithm applicable under plane stress // based on the report by Jirasek & Suarez, 25 April 2014 @@ -191,6 +169,7 @@ AnisotropicDamageMaterial :: giveRealStressVector_PlaneStress(FloatArray &answer status->setTempKappa(kappa); } // formulae (93)-(100) + FloatArray answer; computeInplaneStress(answer, eps, ez1, tempDamage); //this->correctBigValues(stressTensor); // ??? status->setTempDamage(tempDamage); @@ -199,10 +178,11 @@ AnisotropicDamageMaterial :: giveRealStressVector_PlaneStress(FloatArray &answer #ifdef keep_track_of_dissipated_energy status->computeWork(gp); #endif + return answer; } void -AnisotropicDamageMaterial :: computePrincValDir2D(double &D1, double &D2, double &c, double &s, double Dx, double Dy, double Dxy) +AnisotropicDamageMaterial :: computePrincValDir2D(double &D1, double &D2, double &c, double &s, double Dx, double Dy, double Dxy) const // // computes the principal values and directions of a symmetric second-order tensor in 2D // input: Dx, Dy, Dxy ... components of the tensor wrt global coordinates @@ -231,7 +211,7 @@ AnisotropicDamageMaterial :: computePrincValDir2D(double &D1, double &D2, double } bool -AnisotropicDamageMaterial :: checkPrincVal2D(double Dx, double Dy, double Dxy) +AnisotropicDamageMaterial :: checkPrincVal2D(double Dx, double Dy, double Dxy) const // // checks whether both eigenvalues of a symmetric second-order tensor in 2D are <= 1 // @@ -246,7 +226,7 @@ AnisotropicDamageMaterial :: checkPrincVal2D(double Dx, double Dy, double Dxy) } void -AnisotropicDamageMaterial :: computeDamage(FloatMatrix &tempDamage, const FloatMatrix &damage, double kappa, double eps1, double eps2, double ceps, double seps, double epsZ) +AnisotropicDamageMaterial :: computeDamage(FloatMatrix &tempDamage, const FloatMatrix &damage, double kappa, double eps1, double eps2, double ceps, double seps, double epsZ) const // // evaluates the final damage "tempDamage" from the initial damage "damage", initial history variable "kappa" // and the final in-plane strain @@ -325,7 +305,7 @@ AnisotropicDamageMaterial :: computeDamage(FloatMatrix &tempDamage, const FloatM } double -AnisotropicDamageMaterial :: computeTraceD(double equivStrain) +AnisotropicDamageMaterial :: computeTraceD(double equivStrain) const { double knu, aux; double answer = 0.; @@ -354,7 +334,7 @@ AnisotropicDamageMaterial :: computeTraceD(double equivStrain) } double -AnisotropicDamageMaterial :: computeOutOfPlaneStrain(const FloatArray &inplaneStrain, const FloatMatrix &dam, bool tens_flag) +AnisotropicDamageMaterial :: computeOutOfPlaneStrain(const FloatArray &inplaneStrain, const FloatMatrix &dam, bool tens_flag) const // // evaluate the out-of-plane strain from the condition of zero out-of-plane stress for the given damage // based on formula (79) from the report by Jirasek & Suarez, 25 April 2014 @@ -390,7 +370,7 @@ AnisotropicDamageMaterial :: computeOutOfPlaneStrain(const FloatArray &inplaneSt } double -AnisotropicDamageMaterial :: computeDimensionlessOutOfPlaneStress(const FloatArray &inplaneStrain, double epsZ, const FloatMatrix &dam) +AnisotropicDamageMaterial :: computeDimensionlessOutOfPlaneStress(const FloatArray &inplaneStrain, double epsZ, const FloatMatrix &dam) const // // evaluate the dimensionless out-of-plane stress (i.e., stress divided by E and multiplied by 3*B*(1+nu)*(1-2*nu)) // for the given final in-plane strain, out-of-plane strain and damage (which is already updated for this strain) @@ -427,7 +407,7 @@ AnisotropicDamageMaterial :: computeDimensionlessOutOfPlaneStress(const FloatArr } void -AnisotropicDamageMaterial :: computeInplaneStress(FloatArray &inplaneStress, const FloatArray &inplaneStrain, double epsZ, const FloatMatrix &dam) +AnisotropicDamageMaterial :: computeInplaneStress(FloatArray &inplaneStress, const FloatArray &inplaneStrain, double epsZ, const FloatMatrix &dam) const // // evaluate the in-plane stress components // for the given final in-plane strain, out-of-plane strain and damage (which is already updated for this strain) @@ -522,7 +502,7 @@ AnisotropicDamageMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint // evaluate stress under general triaxial stress conditions AnisotropicDamageMaterialStatus *status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); - IsotropicLinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); + IsotropicLinearElasticMaterial &lmat = linearElasticMaterial; FloatMatrix de, tempDamage; double equivStrain, kappa = 0.0, tempKappa = 0.0, traceTempD; FloatArray eVals, effectiveStressVector, fullEffectiveStressVector, stressVector; @@ -540,7 +520,7 @@ AnisotropicDamageMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint } if ( ( equivStrain <= kappa ) && ( kappa <= this->kappa0 ) ) { // elastic behavior - lmat->giveStiffnessMatrix(de, ElasticStiffness, gp, atTime); + lmat.giveStiffnessMatrix(de, ElasticStiffness, gp, atTime); effectiveStressVector.beProductOf(de, reducedTotalStrainVector); answer = effectiveStressVector; } else { @@ -568,12 +548,12 @@ AnisotropicDamageMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint strainTensor.at(2, 3) = strainTensor.at(3, 2) = reducedTotalStrainVector.at(4) / 2.0; strainTensor.at(1, 3) = strainTensor.at(3, 1) = reducedTotalStrainVector.at(5) / 2.0; strainTensor.at(1, 2) = strainTensor.at(2, 1) = reducedTotalStrainVector.at(6) / 2.0; - lmat->giveStiffnessMatrix(de, ElasticStiffness, gp, atTime); + lmat.giveStiffnessMatrix(de, ElasticStiffness, gp, atTime); effectiveStressVector.beProductOf(de, reducedTotalStrainVector); StructuralMaterial :: giveFullSymVectorForm(fullEffectiveStressVector, effectiveStressVector, mode); effectiveStressTensor.beMatrixForm(fullEffectiveStressVector); } - /* lmat->giveStiffnessMatrix(de, ElasticStiffness, gp, atTime); + /* lmat.giveStiffnessMatrix(de, ElasticStiffness, gp, atTime); * effectiveStressVector.beProductOf(de, reducedTotalStrainVector); * StructuralMaterial :: giveFullSymVectorForm(fullEffectiveStressVector, effectiveStressVector, mode); * effectiveStressTensor.beMatrixForm(fullEffectiveStressVector);*/ @@ -667,9 +647,9 @@ AnisotropicDamageMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint } void -AnisotropicDamageMaterial :: computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *atTime) +AnisotropicDamageMaterial :: computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *atTime) const { - AnisotropicDamageMaterialStatus *status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); if ( strain.isEmpty() ) { kappa = 0.; @@ -734,7 +714,7 @@ AnisotropicDamageMaterial :: computeEquivalentStrain(double &kappa, const FloatA * FloatArray stress, fullStress, principalStress; * FloatMatrix de; * - * lmat->giveStiffnessMatrix(de, SecantStiffness, gp, atTime); + * lmat.giveStiffnessMatrix(de, SecantStiffness, gp, atTime); * stress.beProductOf(de, strain); * StructuralMaterial :: giveFullSymVectorForm( fullStress, stress, gp->giveMaterialMode() ); * this->computePrincipalValues(principalStress, fullStress, principal_stress); @@ -754,14 +734,14 @@ AnisotropicDamageMaterial :: computeEquivalentStrain(double &kappa, const FloatA * sum = sqrt(sum); * } * - * kappa = sum / lmat->give('E', gp); + * kappa = sum / lmat.give('E', gp); * } else if ( ( this->equivStrainType == EST_ElasticEnergy ) || ( this->equivStrainType == EST_ElasticEnergyPositiveStress ) || ( this->equivStrainType == EST_ElasticEnergyPositiveStrain ) ) { * // equivalent strain expressions based on elastic energy * FloatMatrix de; * FloatArray stress; * double sum; * - * lmat->giveStiffnessMatrix(de, SecantStiffness, gp, atTime); + * lmat.giveStiffnessMatrix(de, SecantStiffness, gp, atTime); * if ( this->equivStrainType == EST_ElasticEnergy ) { * // standard elastic energy * stress.beProductOf(de, strain); @@ -781,13 +761,13 @@ AnisotropicDamageMaterial :: computeEquivalentStrain(double &kappa, const FloatA * OOFEM_ERROR("Elastic energy corresponding to positive part of strain not finished"); * } * - * kappa = sqrt( sum / lmat->give('E', gp) ); + * kappa = sqrt( sum / lmat.give('E', gp) ); * } else if ( this->equivStrainType == EST_Griffith ) { * double sum = 0.; * FloatArray stress, fullStress, principalStress; * FloatMatrix de; * - * lmat->giveStiffnessMatrix(de, SecantStiffness, gp, atTime); + * lmat.giveStiffnessMatrix(de, SecantStiffness, gp, atTime); * stress.beProductOf(de, strain); * StructuralMaterial :: giveFullSymVectorForm( fullStress, stress, gp->giveMaterialMode() ); * this->computePrincipalValues(principalStress, fullStress, principal_stress); @@ -802,7 +782,7 @@ AnisotropicDamageMaterial :: computeEquivalentStrain(double &kappa, const FloatA * sum = -pow(principalStress.at(1)-principalStress.at(3),2.)/8./(principalStress.at(1)+principalStress.at(3)); * } * sum = max(sum,0.); - * kappa = sum / lmat->give('E', gp); + * kappa = sum / lmat.give('E', gp); * } else { * OOFEM_ERROR("computeEquivalentStrain: unknown EquivStrainType"); * } @@ -823,7 +803,7 @@ AnisotropicDamageMaterial :: computeKappa(FloatMatrix damageTensor) // To do this, the middle point algorithm is used. // @TODO: this algorithm is not particularly efficient and another algorithm could be implemented. double -AnisotropicDamageMaterial :: obtainAlpha1(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, double damageThreshold) +AnisotropicDamageMaterial :: obtainAlpha1(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, double damageThreshold) const { double alpha_a, alpha_b, newAlpha, eps, maxDamage, size; FloatMatrix deltaD, positiveStrainTensorSquared, resultingDamageTensor, eVecs; @@ -903,7 +883,7 @@ AnisotropicDamageMaterial :: obtainAlpha1(FloatMatrix tempDamageTensor, double d // To do this, the middle point algorithm is used. // @TODO: this algorithm is not particularly efficient and another algorithm could be implemented. double -AnisotropicDamageMaterial :: obtainAlpha2(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, FloatMatrix projPosStrainTensor, double damageThreshold) +AnisotropicDamageMaterial :: obtainAlpha2(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, FloatMatrix projPosStrainTensor, double damageThreshold) const { double alpha_a, alpha_b, newAlpha, eps, maxDamage, size, minVal; FloatMatrix deltaD, resultingDamageTensor, eVecs; @@ -986,7 +966,7 @@ AnisotropicDamageMaterial :: obtainAlpha2(FloatMatrix tempDamageTensor, double d // To do this, the middle point algorithm is used. // @TODO: this algorithm is not particularly efficient and another algorithm could be implemented. double -AnisotropicDamageMaterial :: obtainAlpha3(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, FloatArray vec3, double damageThreshold) +AnisotropicDamageMaterial :: obtainAlpha3(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, FloatArray vec3, double damageThreshold) const { double alpha_a, alpha_b, newAlpha, eps, aux = 0; FloatMatrix deltaD, positiveStrainTensorSquared, resultingDamageTensor, eVecs; @@ -1045,7 +1025,7 @@ AnisotropicDamageMaterial :: obtainAlpha3(FloatMatrix tempDamageTensor, double d } //To check symmetry: delete this function when everything works fine double -AnisotropicDamageMaterial :: checkSymmetry(FloatMatrix matrix) +AnisotropicDamageMaterial :: checkSymmetry(FloatMatrix matrix) const { int a = 0; int nRows = matrix.giveNumberOfRows(); @@ -1065,7 +1045,7 @@ AnisotropicDamageMaterial :: checkSymmetry(FloatMatrix matrix) } void -AnisotropicDamageMaterial :: correctBigValues(FloatMatrix &matrix) +AnisotropicDamageMaterial :: correctBigValues(FloatMatrix &matrix) const { int nRows = matrix.giveNumberOfRows(); for ( int i = 1; i <= nRows; i++ ) { @@ -1080,9 +1060,9 @@ AnisotropicDamageMaterial :: correctBigValues(FloatMatrix &matrix) } double -AnisotropicDamageMaterial :: computeTraceD(FloatMatrix tempDamageTensor, FloatMatrix strainTensor, GaussPoint *gp) +AnisotropicDamageMaterial :: computeTraceD(FloatMatrix tempDamageTensor, FloatMatrix strainTensor, GaussPoint *gp) const { - AnisotropicDamageMaterialStatus *status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); int flag = status->giveFlag(); //int tempFlag=status->giveTempFlag(); double Dc = 1.00, trD = 0; @@ -1113,11 +1093,11 @@ AnisotropicDamageMaterial :: computeTraceD(FloatMatrix tempDamageTensor, FloatMa } double -AnisotropicDamageMaterial :: computeCorrectionFactor(FloatMatrix tempDamageTensor, FloatMatrix strainTensor, GaussPoint *gp) +AnisotropicDamageMaterial :: computeCorrectionFactor(FloatMatrix tempDamageTensor, FloatMatrix strainTensor, GaussPoint *gp) const { // In the case that the material has experimented some damaged under compression, this must affect the material behaviour when it is // under tension in the future - AnisotropicDamageMaterialStatus *status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); int tempFlag = status->giveFlag(); double tempStoredFactor = status->giveStoredFactor(); double Dc = 1.00, trD = 0; @@ -1152,27 +1132,24 @@ AnisotropicDamageMaterial :: computeCorrectionFactor(FloatMatrix tempDamageTenso return factor; } -void -AnisotropicDamageMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +AnisotropicDamageMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *atTime) + TimeStep *atTime) const // // Implementation of the 3D stiffness matrix, according to the equations 56 and 57 of the reference paper. { - AnisotropicDamageMaterialStatus *status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, atTime); + return linearElasticMaterial.give3dMaterialStiffnessMatrix(mode, gp, atTime); } else { const FloatArray &totalStrain = status->giveTempStrainVector(); FloatArray reducedTotalStrainVector; this->giveStressDependentPartOfStrainVector(reducedTotalStrainVector, gp, totalStrain, atTime, VM_Total); //FloatArray totalStrain; - FloatMatrix damageTensor, strainTensor; // The strain vector is turned into a tensor; for that, the elements that are out of the diagonal // must be divided by 2 - strainTensor.resize(3, 3); - strainTensor.zero(); + FloatMatrix strainTensor(3,3); strainTensor.at(1, 1) = reducedTotalStrainVector.at(1); strainTensor.at(2, 2) = reducedTotalStrainVector.at(2); strainTensor.at(3, 3) = reducedTotalStrainVector.at(3); @@ -1183,23 +1160,25 @@ AnisotropicDamageMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, strainTensor.at(1, 2) = reducedTotalStrainVector.at(6) / 2.0; strainTensor.at(2, 1) = reducedTotalStrainVector.at(6) / 2.0; // The damage tensor is read - damageTensor = status->giveTempDamage(); + FloatMatrix answer; + FloatMatrix damageTensor = status->giveTempDamage(); AnisotropicDamageMaterial :: computeSecantOperator(answer, strainTensor, damageTensor, gp); for ( int j = 4; j <= 6; j++ ) { for ( int i = 1; i <= 6; i++ ) { answer.at(i, j) = answer.at(i, j) / 2.0; } } + return answer; } } -void AnisotropicDamageMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, - GaussPoint *gp, TimeStep *atTime) +FloatMatrixF<3,3> +AnisotropicDamageMaterial :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) const { - AnisotropicDamageMaterialStatus *status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, atTime); + return linearElasticMaterial.givePlaneStressStiffMtrx(mode, gp, atTime); } else { FloatArray totalStrain = status->giveTempStrainVector(); FloatArray reducedTotalStrainVector; @@ -1243,7 +1222,7 @@ void AnisotropicDamageMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, //q = -nu/E; r = 1. / ( 1. - C13 * q ); s = 1. / ( 1. - q * C23 - C23 * q * q * r * C13 ); - answer.resize(3, 3); + FloatMatrixF<3,3> answer; answer.at(2, 1) = s * ( C21 + C11 * C23 * q * r ); answer.at(2, 2) = s * ( C22 + C12 * C23 * q * r ); answer.at(2, 3) = s * ( C26 + C16 * C23 * q * r ) * 1. / 2.; @@ -1253,33 +1232,32 @@ void AnisotropicDamageMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, answer.at(3, 1) = C61 + C63 * q * ( answer.at(1, 1) + answer.at(2, 1) ); answer.at(3, 2) = C62 + C63 * q * ( answer.at(1, 2) + answer.at(2, 2) ); answer.at(3, 3) = ( C66 + C63 * q * ( answer.at(1, 3) + answer.at(2, 3) ) ) * 1. / 2.; + return answer; } } -void AnisotropicDamageMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mode, - GaussPoint *gp, TimeStep *atTime) -{} -void AnisotropicDamageMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, - GaussPoint *gp, TimeStep *atTime) +FloatMatrixF<1,1> AnisotropicDamageMaterial :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) const { // Implementation of the 3D stiffness matrix - AnisotropicDamageMaterialStatus *status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, atTime); + return linearElasticMaterial.give1dStressStiffMtrx(mode, gp, atTime); } else { + auto status = static_cast< AnisotropicDamageMaterialStatus * >( this->giveStatus(gp) ); FloatArray strain = status->giveTempStrainVector(); if ( ( strain.at(1) + strain.at(2) + strain.at(3) ) > 0 ) { //@todo eq 56 } else { //@todo eq 57 } + OOFEM_ERROR("not implemented"); + return {0.}; } } void AnisotropicDamageMaterial :: computePlaneStressStrain(FloatMatrix &answer, FloatMatrix damageTensor, FloatArray reducedTotalStrainVector, GaussPoint *gp, - TimeStep *atTime) + TimeStep *atTime) const // { FloatMatrix inPlaneStrain, B, eVecs; @@ -1362,7 +1340,7 @@ AnisotropicDamageMaterial :: computePlaneStressStrain(FloatMatrix &answer, Float void AnisotropicDamageMaterial :: computePlaneStressSigmaZ(double &answer, FloatMatrix damageTensor, FloatArray reducedTotalStrainVector, - double epsilonZ, GaussPoint *gp, TimeStep *atTime) + double epsilonZ, GaussPoint *gp, TimeStep *atTime) const // { FloatMatrix Auxiliar, inPlaneStrain; @@ -1750,7 +1728,7 @@ AnisotropicDamageMaterial :: computeDamageTensor(FloatMatrix &answer, GaussPoint } void -AnisotropicDamageMaterial :: computeSecantOperator(FloatMatrix &answer, FloatMatrix strainTensor, FloatMatrix damageTensor, GaussPoint *gp) +AnisotropicDamageMaterial :: computeSecantOperator(FloatMatrix &answer, FloatMatrix strainTensor, FloatMatrix damageTensor, GaussPoint *gp) const // // Implementation of the 3D stiffness matrix, according to the equations 56 and 57 of the reference paper. { @@ -2021,14 +1999,13 @@ AnisotropicDamageMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, Int } -IRResultType -AnisotropicDamageMaterial :: initializeFrom(InputRecord *ir) +void +AnisotropicDamageMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - linearElasticMaterial->initializeFrom(ir); - E = linearElasticMaterial->giveYoungsModulus(); - nu = linearElasticMaterial->givePoissonsRatio(); + StructuralMaterial :: initializeFrom(ir); + linearElasticMaterial.initializeFrom(ir); + E = linearElasticMaterial.giveYoungsModulus(); + nu = linearElasticMaterial.givePoissonsRatio(); int eqStrain = 0; // specify the type of formula for equivalent strain // currently only the Mazars formula is allowed !!! (this should be generalized later) @@ -2074,8 +2051,6 @@ AnisotropicDamageMaterial :: initializeFrom(InputRecord *ir) if ( damageLawType == DLT_Desmorat2 ) { IR_GIVE_FIELD(ir, aA, _IFT_AnisotropicDamageMaterial_aA); } - - return StructuralMaterial :: initializeFrom(ir); } void @@ -2086,29 +2061,12 @@ AnisotropicDamageMaterial :: giveInputRecord(DynamicInputRecord &input) } -AnisotropicDamageMaterialStatus :: AnisotropicDamageMaterialStatus(int n, Domain *d, GaussPoint *g) : StructuralMaterialStatus(n, d, g) -{ - kappa = tempKappa = 0.0; - damage.resize(3, 3); - damage.zero(); - tempDamage.resize(3, 3); - tempDamage.zero(); - strainZ = tempStrainZ = 0.0; - flag = tempFlag = 0; - storedFactor = 1.0; - tempStoredFactor = 1.0; - -#ifdef keep_track_of_dissipated_energy - stressWork = tempStressWork = 0.0; - dissWork = tempDissWork = 0.0; -#endif -} - -AnisotropicDamageMaterialStatus :: ~AnisotropicDamageMaterialStatus() -{ } +AnisotropicDamageMaterialStatus :: AnisotropicDamageMaterialStatus(GaussPoint *g) : StructuralMaterialStatus(g), + damage(3, 3), tempDamage(3, 3) +{} void -AnisotropicDamageMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +AnisotropicDamageMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { MaterialMode mode = gp->giveMaterialMode(); if ( mode == _PlaneStress ) { // special treatment of the out-of-plane strain @@ -2183,50 +2141,36 @@ AnisotropicDamageMaterialStatus :: updateYourself(TimeStep *atTime) } -contextIOResultType -AnisotropicDamageMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +AnisotropicDamageMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - /* contextIOResultType iores; - * - * // save parent class status - * if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - * THROW_CIOERR(iores); - * } - * - * // write raw data - * if ( !stream.write(kappa) ) { - * THROW_CIOERR(CIO_IOERR); - * } - * - * if ( !stream.write(damage) ) { - * THROW_CIOERR(CIO_IOERR); - * } - * - * #ifdef keep_track_of_dissipated_energy - * if ( !stream.write(stressWork) ) { - * THROW_CIOERR(CIO_IOERR); - * } - * - * if ( !stream.write(dissWork) ) { - * THROW_CIOERR(CIO_IOERR); - * } - * - * #endif - */ - contextIOResultType iores; + StructuralMaterialStatus :: saveContext(stream, mode); - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } +#if 0 + if ( !stream.write(kappa) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(damage) ) { + THROW_CIOERR(CIO_IOERR); + } + +#ifdef keep_track_of_dissipated_energy + if ( !stream.write(stressWork) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.write(dissWork) ) { + THROW_CIOERR(CIO_IOERR); + } +#endif +#endif - // write raw data if ( !stream.write(kappa) ) { THROW_CIOERR(CIO_IOERR); } - - // write damage (vector) + contextIOResultType iores; if ( ( iores = damage.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -2239,60 +2183,41 @@ AnisotropicDamageMaterialStatus :: saveContext(DataStream &stream, ContextMode m if ( !stream.write(dissWork) ) { THROW_CIOERR(CIO_IOERR); } - - #endif - - return CIO_OK; } -contextIOResultType -AnisotropicDamageMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +AnisotropicDamageMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - /* contextIOResultType iores; - * - * // read parent class status - * if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - * THROW_CIOERR(iores); - * } - * - * // read raw data - * if ( !stream.read(kappa) ) { - * THROW_CIOERR(CIO_IOERR); - * } - * - * if ( !stream.read(damage) ) { - * THROW_CIOERR(CIO_IOERR); - * } - * - * #ifdef keep_track_of_dissipated_energy - * if ( !stream.read(stressWork) ) { - * THROW_CIOERR(CIO_IOERR); - * } - * - * if ( !stream.read(dissWork) ) { - * THROW_CIOERR(CIO_IOERR); - * } - * - * #endif - */ + StructuralMaterialStatus :: restoreContext(stream, mode); - contextIOResultType iores; +#if 0 + if ( !stream.read(kappa) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(damage) ) { + THROW_CIOERR(CIO_IOERR); + } - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } +#ifdef keep_track_of_dissipated_energy + if ( !stream.read(stressWork) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( !stream.read(dissWork) ) { + THROW_CIOERR(CIO_IOERR); + } + +#endif +#endif - // read raw data if ( !stream.read(kappa) ) { THROW_CIOERR(CIO_IOERR); } - - // read damage (vector) + contextIOResultType iores; if ( ( iores = damage.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -2305,11 +2230,7 @@ AnisotropicDamageMaterialStatus :: restoreContext(DataStream &stream, ContextMod if ( !stream.read(dissWork) ) { THROW_CIOERR(CIO_IOERR); } - #endif - - - return CIO_OK; } #ifdef keep_track_of_dissipated_energy diff --git a/src/sm/Materials/anisodamagemodel.h b/src/sm/Materials/anisodamagemodel.h index af27ac2cf..6d7008978 100644 --- a/src/sm/Materials/anisodamagemodel.h +++ b/src/sm/Materials/anisodamagemodel.h @@ -41,10 +41,10 @@ #define keep_track_of_dissipated_energy #include "material.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "isolinearelasticmaterial.h" -#include "../sm/Materials/structuralms.h" -#include "Materials/ConcreteMaterials/idm1.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/ConcreteMaterials/idm1.h" ///@name Input fields for AnisotropicDamageMaterial //@{ @@ -68,41 +68,39 @@ class AnisotropicDamageMaterialStatus : public StructuralMaterialStatus { protected: /// Scalar measure of the largest strain level ever reached in material. - double kappa; + double kappa = 0.; /// Non-equilibrated scalar measure of the largest strain level. - double tempKappa; + double tempKappa = 0.; /// Second order damage tensor FloatMatrix damage; /// Non-equilibrated second order damage tensor FloatMatrix tempDamage; /// Out-of-plane value for 2dPlaneStress mode - double tempStrainZ; + double strainZ = 0.; /// Non-equilibrated out-of-plane value for 2dPlaneStress mode - double strainZ; + double tempStrainZ = 0.; /// This flag turns into 1 and remains 1 when the trace of the damage tensor is >1 in compression (tr(strainTensor)<0) - int flag; - int tempFlag; - double storedFactor; - double tempStoredFactor; + int flag = 0; + int tempFlag = 0; + double storedFactor = 1.; + double tempStoredFactor = 1.; #ifdef keep_track_of_dissipated_energy /// Density of total work done by stresses on strain increments. - double stressWork; + double stressWork = 0.; /// Non-equilibrated density of total work done by stresses on strain increments. - double tempStressWork; + double tempStressWork = 0.; /// Density of dissipated work. - double dissWork; + double dissWork = 0.; /// Non-equilibrated density of dissipated work. - double tempDissWork; + double tempDissWork = 0.; #endif public: /// Constructor - AnisotropicDamageMaterialStatus(int n, Domain *d, GaussPoint *g); - /// Destructor - virtual ~AnisotropicDamageMaterialStatus(); + AnisotropicDamageMaterialStatus(GaussPoint *g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; /// Returns the last equilibrated scalar measure of the largest strain level. double giveKappa() { return kappa; } @@ -157,13 +155,13 @@ class AnisotropicDamageMaterialStatus : public StructuralMaterialStatus #endif // definition - virtual const char *giveClassName() const { return "AnisotropicDamageMaterialModelStatus"; } + const char *giveClassName() const override { return "AnisotropicDamageMaterialModelStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -179,91 +177,96 @@ class AnisotropicDamageMaterialStatus : public StructuralMaterialStatus class AnisotropicDamageMaterial : public StructuralMaterial { protected: - /// Reference to bulk (undamaged) material - IsotropicLinearElasticMaterial *linearElasticMaterial; + IsotropicLinearElasticMaterial linearElasticMaterial; /// Young's modulus - double E; + double E = 0.; /// Poisson's ratio - double nu; + double nu = 0.; /// Damage threshold kappa0, as defined in the paper mentioned above. - double kappa0; + double kappa0 = 0.; /// Damage parameter kappa_f (in the paper denoted as "a") - double kappaf; + double kappaf = 0.; /// Damage parameter a*A, needed to obtain Kappa(trD), according to eq. 33 in the paper mentioned above. - double aA; + double aA = 0.; /// Type characterizing the algorithm used to compute equivalent strain measure. enum EquivStrainType { EST_Unknown, EST_Mazars, EST_Rankine_Smooth, EST_Rankine_Standard, EST_ElasticEnergy, EST_ElasticEnergyPositiveStress, EST_ElasticEnergyPositiveStrain, EST_Mises, EST_Griffith }; /// Parameter specifying the definition of equivalent strain. - EquivStrainType equivStrainType; + EquivStrainType equivStrainType = EST_Unknown; /// Type characterizing the damage law. enum DamLawType { DLT_Unknown, DLT_Desmorat1, DLT_Desmorat2, DLT_Linear, DLT_Exponential }; /// Parameter specifying the damage law. - DamLawType damageLawType; + DamLawType damageLawType = DLT_Unknown; public: /// Constructor AnisotropicDamageMaterial(int n, Domain *d); - /// Destructor - virtual ~AnisotropicDamageMaterial(); - - virtual int hasNonLinearBehaviour() { return 1; } - virtual int hasMaterialModeCapability(MaterialMode mode); - // identification and auxiliary functions - virtual const char *giveClassName() const { return "AnisotropicDamageMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_AnisotropicDamageMaterial_Name; } + bool hasMaterialModeCapability(MaterialMode mode) const override; - /// Returns reference to undamaged (bulk) material - IsotropicLinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } + const char *giveClassName() const override { return "AnisotropicDamageMaterial"; } + const char *giveInputRecordName() const override { return _IFT_AnisotropicDamageMaterial_Name; } /// Plane-stress version of the stress evaluation algorithm - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - void computePrincValDir2D(double &D1, double &D2, double &c, double &s, double Dx, double Dy, double Dxy); - bool checkPrincVal2D(double Dx, double Dy, double Dxy); - void computeDamage(FloatMatrix &tempDamage, const FloatMatrix &damage, double kappa, double eps1, double eps2, double ceps, double seps, double epsZ); - double computeTraceD(double equivStrain); - double computeOutOfPlaneStrain(const FloatArray &inplaneStrain, const FloatMatrix &dam, bool tens_flag); - double computeDimensionlessOutOfPlaneStress(const FloatArray &inplaneStrain, double epsZ, const FloatMatrix &dam); - void computeInplaneStress(FloatArray &inplaneStress, const FloatArray &inplaneStrain, double epsZ, const FloatMatrix &dam); + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &reducedE, GaussPoint *gp, TimeStep *tStep) const override; + void computePrincValDir2D(double &D1, double &D2, double &c, double &s, double Dx, double Dy, double Dxy) const; + bool checkPrincVal2D(double Dx, double Dy, double Dxy) const; + void computeDamage(FloatMatrix &tempDamage, const FloatMatrix &damage, double kappa, double eps1, double eps2, double ceps, double seps, double epsZ) const; + double computeTraceD(double equivStrain) const; + double computeOutOfPlaneStrain(const FloatArray &inplaneStrain, const FloatMatrix &dam, bool tens_flag) const; + double computeDimensionlessOutOfPlaneStress(const FloatArray &inplaneStrain, double epsZ, const FloatMatrix &dam) const; + void computeInplaneStress(FloatArray &inplaneStress, const FloatArray &inplaneStrain, double epsZ, const FloatMatrix &dam) const; /// Obtains the proportion of the damage tensor that is needed to get the first eigenvalue equal to the damage threshold - double obtainAlpha1(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, double damageThreshold); + double obtainAlpha1(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, double damageThreshold) const; /// Obtains the proportion of the damage tensor that is needed to get the second eigenvalue equal to the damage threshold - double obtainAlpha2(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, FloatMatrix ProjMatrix, double damageThreshold); + double obtainAlpha2(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, FloatMatrix ProjMatrix, double damageThreshold) const; /// Obtains the proportion of the damage tensor that is needed to get the third eigenvalue equal to the damage threshold - double obtainAlpha3(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, FloatArray vec3, double damageThreshold); - - double checkSymmetry(FloatMatrix matrix); - - void correctBigValues(FloatMatrix &matrix); - - double computeTraceD(FloatMatrix tempDamageTensor, FloatMatrix strainTensor, GaussPoint *gp); - - double computeCorrectionFactor(FloatMatrix tempDamageTensor, FloatMatrix strainTensor, GaussPoint *gp); - - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); - - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_StressControl(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, const IntArray &strainControl, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime); - - // virtual InternalStateValueType giveIPValueType(InternalStateType type); - //virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *, TimeStep *); + double obtainAlpha3(FloatMatrix tempDamageTensor, double deltaLambda, FloatMatrix positiveStrainTensor, FloatArray vec3, double damageThreshold) const; + + double checkSymmetry(FloatMatrix matrix) const; + + void correctBigValues(FloatMatrix &matrix) const; + + double computeTraceD(FloatMatrix tempDamageTensor, FloatMatrix strainTensor, GaussPoint *gp) const; + + double computeCorrectionFactor(FloatMatrix tempDamageTensor, FloatMatrix strainTensor, GaussPoint *gp) const; + + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; + + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<4> giveRealStressVector_PlaneStrain(const FloatArrayF<4> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArray giveRealStressVector_StressControl(const FloatArray &strain, const IntArray &strainControl, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime) override; + + //InternalStateValueType giveIPValueType(InternalStateType type) override; + //FloatArrayF<6> giveThermalDilatationVector(GaussPoint *, TimeStep *) const override; /** * Computes the equivalent strain measure from given strain vector (full form). @@ -272,42 +275,32 @@ class AnisotropicDamageMaterial : public StructuralMaterial * @param gp Integration point. * @param tStep Time step. */ - virtual void computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); + void computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void computeDamageTensor(FloatMatrix &answer, GaussPoint *gp, - const FloatArray &totalStrain, double equivStrain, - TimeStep *atTime); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void computeDamageTensor(FloatMatrix &answer, GaussPoint *gp, const FloatArray &totalStrain, double equivStrain, TimeStep *atTime); - MaterialStatus *CreateStatus(GaussPoint *gp) const { return new AnisotropicDamageMaterialStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new AnisotropicDamageMaterialStatus(gp); } protected: + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + void computePlaneStressStrain(FloatMatrix &answer, FloatMatrix damageTensor, FloatArray totalStrain, GaussPoint *gp, + TimeStep *atTime) const; + void computePlaneStressSigmaZ(double &answer, FloatMatrix damageTensor, FloatArray reducedTotalStrainVector, + double epsZ, GaussPoint *gp, TimeStep *atTime) const; - virtual void give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - virtual void computePlaneStressStrain(FloatMatrix &answer, FloatMatrix damageTensor, FloatArray totalStrain, GaussPoint *gp, - TimeStep *atTime); - virtual void computePlaneStressSigmaZ(double &answer, FloatMatrix damageTensor, FloatArray reducedTotalStrainVector, - double epsZ, GaussPoint *gp, TimeStep *atTime); - - /* virtual void computeDamageTensor(FloatMatrix &answer, GaussPoint *gp, - * const FloatArray &totalStrain, double equivStrain, - * TimeStep *atTime); - */ +#if 0 + void computeDamageTensor(FloatMatrix &answer, GaussPoint *gp, + const FloatArray &totalStrain, double equivStrain, + TimeStep *atTime) override; +#endif virtual void computeSecantOperator(FloatMatrix &answer, FloatMatrix strainTensor, - FloatMatrix damageTensor, GaussPoint *gp); + FloatMatrix damageTensor, GaussPoint *gp) const; double computeK(GaussPoint *gp); diff --git a/src/sm/Materials/anisolinearelasticmaterial.C b/src/sm/Materials/anisolinearelasticmaterial.C index eea31186b..d137c6985 100644 --- a/src/sm/Materials/anisolinearelasticmaterial.C +++ b/src/sm/Materials/anisolinearelasticmaterial.C @@ -42,10 +42,10 @@ namespace oofem { REGISTER_Material(AnisotropicLinearElasticMaterial); -IRResultType -AnisotropicLinearElasticMaterial :: initializeFrom(InputRecord *ir) +void +AnisotropicLinearElasticMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + LinearElasticMaterial :: initializeFrom(ir); // read the stiffness coefficients arranged by rows from the diagonal to the right (21 values) FloatArray stiffness; @@ -55,24 +55,20 @@ AnisotropicLinearElasticMaterial :: initializeFrom(InputRecord *ir) } // put the stiffness coefficients into a 6x6 matrix - int k = 1; - for ( int i = 1; i <= 6; i++ ) { - stiffmat.at(i, i) = stiffness.at(k++); + for ( int k = 1, i = 1; i <= 6; i++ ) { + tangent.at(i, i) = stiffness.at(k++); for ( int j = i + 1; j <= 6; j++ ) { - stiffmat.at(i, j) = stiffmat.at(j, i) = stiffness.at(k++); + tangent.at(i, j) = tangent.at(j, i) = stiffness.at(k++); } } + this->computesSubTangents(); - // read the thermal expansion coefficients (3 values) - IR_GIVE_FIELD(ir, alpha, _IFT_AnisotropicLinearElasticMaterial_talpha); - if ( alpha.giveSize() == 0 ) { - alpha.resize(6); - alpha.zero(); - } else if ( alpha.giveSize() != 6 ) { - OOFEM_ERROR( "Incorrect size of talpha - should be 0 or 6, is %d\n", alpha.giveSize() ); + FloatArray alpha_input(6); + IR_GIVE_FIELD(ir, alpha_input, _IFT_AnisotropicLinearElasticMaterial_talpha); + if ( alpha_input.giveSize() != 6 ) { + OOFEM_ERROR( "Incorrect size of talpha - should be 6, is %d\n", alpha.giveSize() ); } - - return LinearElasticMaterial :: initializeFrom(ir); + alpha = alpha_input; } @@ -81,10 +77,9 @@ AnisotropicLinearElasticMaterial :: giveInputRecord(DynamicInputRecord &input) { Material :: giveInputRecord(input); FloatArray stiffness(21); - int k = 1; - for ( int i = 1; i <= 6; i++ ) { + for ( int k = 1, i = 1; i <= 6; i++ ) { for ( int j = i; j <= 6; j++ ) { - stiffness.at(k++) = stiffmat.at(i, j); + stiffness.at(k++) = tangent.at(i, j); } } input.setField(stiffness, _IFT_AnisotropicLinearElasticMaterial_stiff); @@ -92,35 +87,4 @@ AnisotropicLinearElasticMaterial :: giveInputRecord(DynamicInputRecord &input) input.setField(alpha, _IFT_AnisotropicLinearElasticMaterial_talpha); } - -void -AnisotropicLinearElasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -{ - answer = stiffmat; - - if ( ( tStep->giveIntrinsicTime() < this->castingTime ) ) { - answer.times(1. - this->preCastStiffnessReduction); - } -} - - -void -AnisotropicLinearElasticMaterial :: giveThermalDilatationVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep) -{ - answer = alpha; -} - - -MaterialStatus * -AnisotropicLinearElasticMaterial :: CreateStatus(GaussPoint *gp) const -/* - * creates new material status corresponding to this class - */ -{ - return new StructuralMaterialStatus(1, this->giveDomain(), gp); -} } // end namespace oofem diff --git a/src/sm/Materials/anisolinearelasticmaterial.h b/src/sm/Materials/anisolinearelasticmaterial.h index 257d51fc8..a397577eb 100644 --- a/src/sm/Materials/anisolinearelasticmaterial.h +++ b/src/sm/Materials/anisolinearelasticmaterial.h @@ -45,7 +45,9 @@ ///@name Input fields for AnisotropicLinearElasticMaterial //@{ #define _IFT_AnisotropicLinearElasticMaterial_Name "anisole" +/// Stiffness coefficients arranged by rows from the diagonal to the right (21 values) #define _IFT_AnisotropicLinearElasticMaterial_stiff "stiff" +/// Thermal expansion, 6 components in strain-Voigt order, #define _IFT_AnisotropicLinearElasticMaterial_talpha "talpha" //@} @@ -55,43 +57,17 @@ class GaussPoint; /** * This class implements a general anisotropic linear elastic material in a finite * element problem. - * - * Tasks: - * - Returning standard material stiffness matrix for 3d-case. - * according to current state determined by using data stored - * in Gausspoint, and local coordinate system defined in gp. - * - Returning real stress state vector(tensor) at gauss point for 3d - case. */ class AnisotropicLinearElasticMaterial : public LinearElasticMaterial { -protected: - FloatMatrix stiffmat; - FloatArray alpha; - public: + AnisotropicLinearElasticMaterial(int n, Domain *d) : LinearElasticMaterial(n, d) {} - AnisotropicLinearElasticMaterial(int n, Domain *d) : LinearElasticMaterial(n, d), stiffmat(6,6), alpha(3) - {} - virtual ~AnisotropicLinearElasticMaterial() - {} - - // identification and auxiliary functions - virtual const char *giveInputRecordName() const { return _IFT_AnisotropicLinearElasticMaterial_Name; } - virtual const char *giveClassName() const { return "AnisotropicLinearElasticMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); - void giveInputRecord(DynamicInputRecord &input); - - // important functions - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep); - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); - - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; - -protected: + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - friend class CrossSection; + const char *giveInputRecordName() const override { return _IFT_AnisotropicLinearElasticMaterial_Name; } + const char *giveClassName() const override { return "AnisotropicLinearElasticMaterial"; } }; } // end namespace oofem #endif // anisolinearelasticmaterial_h diff --git a/src/sm/Materials/deformationtheorymaterial.h b/src/sm/Materials/deformationtheorymaterial.h index a2af14fc1..81b688437 100644 --- a/src/sm/Materials/deformationtheorymaterial.h +++ b/src/sm/Materials/deformationtheorymaterial.h @@ -35,7 +35,7 @@ #ifndef deformationtheorymaterial_h #define deformationtheorymaterial_h -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" namespace oofem { /** @@ -46,11 +46,8 @@ class DeformationTheoryMaterial : public StructuralMaterial { public: DeformationTheoryMaterial(int n, Domain * d) : StructuralMaterial(n, d) { } - virtual ~DeformationTheoryMaterial() { } - // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 1; } - virtual const char *giveClassName() const { return "DeformationTheoryMaterial"; } + const char *giveClassName() const override { return "DeformationTheoryMaterial"; } }; } // end namespace oofem #endif // deformationtheorymaterial_h diff --git a/src/sm/Materials/druckerPragerPlasticitySM.C b/src/sm/Materials/druckerPragerPlasticitySM.C index a4bc475fd..b245dcb9f 100644 --- a/src/sm/Materials/druckerPragerPlasticitySM.C +++ b/src/sm/Materials/druckerPragerPlasticitySM.C @@ -36,11 +36,11 @@ #include "floatarray.h" #include "floatmatrix.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "gausspoint.h" #include "intarray.h" -#include "../sm/Materials/structuralmaterial.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "datastream.h" #include "contextioerr.h" #include "mathfem.h" @@ -49,24 +49,15 @@ namespace oofem { REGISTER_Material(DruckerPragerPlasticitySM); -DruckerPragerPlasticitySMStatus :: DruckerPragerPlasticitySMStatus(int n, Domain *d, GaussPoint *gp) : - StructuralMaterialStatus(n, d, gp), - plasticStrainDeviator( 6 ), - tempPlasticStrainDeviator( 6 ) +DruckerPragerPlasticitySMStatus :: DruckerPragerPlasticitySMStatus(GaussPoint *gp) : + StructuralMaterialStatus(gp) { stressVector.resize(6); strainVector.resize(6); tempStressVector = stressVector; tempStrainVector = strainVector; - - kappa = tempKappa = 0.; - state_flag = temp_state_flag = DruckerPragerPlasticitySMStatus :: DP_Elastic; - volumetricPlasticStrain = tempVolumetricPlasticStrain = 0.; } -DruckerPragerPlasticitySMStatus :: ~DruckerPragerPlasticitySMStatus() -{ } - void DruckerPragerPlasticitySMStatus :: initTempStatus() { @@ -93,7 +84,7 @@ DruckerPragerPlasticitySMStatus :: updateYourself(TimeStep *tStep) } void -DruckerPragerPlasticitySMStatus :: printOutputAt(FILE *file, TimeStep *tStep) +DruckerPragerPlasticitySMStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { // Call corresponding function of the parent class to print variables defined there. StructuralMaterialStatus :: printOutputAt(file, tStep); @@ -117,8 +108,7 @@ DruckerPragerPlasticitySMStatus :: printOutputAt(FILE *file, TimeStep *tStep) } // print plastic strain vector - FloatArray plasticStrainVector; - givePlasticStrainVector(plasticStrainVector); + auto plasticStrainVector = givePlasticStrainVector(); fprintf(file, "plasticStrains "); for ( auto &val : plasticStrainVector ) { @@ -132,17 +122,12 @@ DruckerPragerPlasticitySMStatus :: printOutputAt(FILE *file, TimeStep *tStep) fprintf(file, " %.4e\n", kappa); } -contextIOResultType -DruckerPragerPlasticitySMStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +DruckerPragerPlasticitySMStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralMaterialStatus :: saveContext(stream, mode); - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write raw data + contextIOResultType iores; if ( ( iores = plasticStrainDeviator.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -158,22 +143,15 @@ DruckerPragerPlasticitySMStatus :: saveContext(DataStream &stream, ContextMode m if ( !stream.write(temp_state_flag) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } -contextIOResultType -DruckerPragerPlasticitySMStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +DruckerPragerPlasticitySMStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralMaterialStatus :: restoreContext(stream, mode); - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data + contextIOResultType iores; if ( ( iores = plasticStrainDeviator.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -189,8 +167,6 @@ DruckerPragerPlasticitySMStatus :: restoreContext(DataStream &stream, ContextMod if ( !stream.read(temp_state_flag) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } // ************************************************************* @@ -199,35 +175,22 @@ DruckerPragerPlasticitySMStatus :: restoreContext(DataStream &stream, ContextMod DruckerPragerPlasticitySM :: DruckerPragerPlasticitySM(int n, Domain *d) : - StructuralMaterial(n, d) -{ - LEMaterial = new IsotropicLinearElasticMaterial(n, d); - kFactor = 0.; - yieldTol = 0.; - newtonIter = 0; -} + StructuralMaterial(n, d), + LEMaterial(n, d) +{} -DruckerPragerPlasticitySM :: ~DruckerPragerPlasticitySM() -{ - delete LEMaterial; -} -IRResultType -DruckerPragerPlasticitySM :: initializeFrom(InputRecord *ir) +void +DruckerPragerPlasticitySM :: initializeFrom(InputRecord &ir) { - // Required by IR_GIVE_FIELD macro - IRResultType result; // call the corresponding service of structural material - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - + StructuralMaterial :: initializeFrom(ir); // call the corresponding service for the linear elastic material - result = LEMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) return result; + LEMaterial.initializeFrom(ir); // initialize elastic constants - //eM = LEMaterial->give(Ex,gp); - //nu = LEMaterial->give(NYxz,gp); + //eM = LEMaterial.give(Ex,gp); + //nu = LEMaterial.give(NYxz,gp); //gM = eM / ( 2. * ( 1. + nu ) ); //kM = eM / ( 3. * ( 1. - 2. * nu ) ); @@ -249,77 +212,66 @@ DruckerPragerPlasticitySM :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, limitYieldStress, _IFT_DruckerPragerPlasticitySM_lys); break; default: - OOFEM_WARNING("Choose hardeningType 1 (linear hardening/softening), 2 (exponential hardening/softening) in input file!"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_DruckerPragerPlasticitySM_ht, + "must be 1 (linear hardening/softening) or 2 (exponential hardening/softening)"); } yieldTol = 1.e-14; IR_GIVE_OPTIONAL_FIELD(ir, yieldTol, _IFT_DruckerPragerPlasticitySM_yieldtol); newtonIter = 30; IR_GIVE_OPTIONAL_FIELD(ir, newtonIter, _IFT_DruckerPragerPlasticitySM_newtoniter); - - return IRRT_OK; } -void -DruckerPragerPlasticitySM :: giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) +FloatArrayF<6> +DruckerPragerPlasticitySM :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, + TimeStep *tStep) const { - FloatArray strainVectorR; - - DruckerPragerPlasticitySMStatus *status = - static_cast< DruckerPragerPlasticitySMStatus * >( this->giveStatus(gp) ); + auto status = static_cast< DruckerPragerPlasticitySMStatus * >( this->giveStatus(gp) ); // Initialize temp variables for this gauss point - initTempStatus(gp); + const_cast(this)->initTempStatus(gp); // subtract stress independent part // note: eigenStrains (temperature) is not contained in mechanical strain stored in gp // therefore it is necessary to subtract always the total eigen strain value - this->giveStressDependentPartOfStrainVector_3d(strainVectorR, gp, totalStrain, - tStep, VM_Total); + auto thermalStrain = this->computeStressIndependentStrainVector_3d(gp, tStep, VM_Total); + auto strainVectorR = strain - thermalStrain; // perform the local stress return and update the history variables performLocalStressReturn(gp, strainVectorR); // copy total strain vector to the temp status - status->letTempStrainVectorBe(totalStrain); + status->letTempStrainVectorBe(strain); // give back correct form of stressVector to giveRealStressVector - answer = status->giveTempStressVector(); + return status->giveTempStressVector(); } void -DruckerPragerPlasticitySM :: performLocalStressReturn(GaussPoint *gp, - const FloatArray &strain) +DruckerPragerPlasticitySM :: performLocalStressReturn(GaussPoint *gp, const FloatArrayF<6> &strain) const { - DruckerPragerPlasticitySMStatus *status = - static_cast< DruckerPragerPlasticitySMStatus * >( giveStatus(gp) ); + auto status = static_cast< DruckerPragerPlasticitySMStatus * >( giveStatus(gp) ); // split total strains in volumetric and deviatoric part - FloatArray strainDeviator; - double volumetricStrain; // elastic constants - double eM = LEMaterial->give(Ex, gp); - double nu = LEMaterial->give(NYxz, gp); + double eM = LEMaterial.give(Ex, gp); + double nu = LEMaterial.give(NYxz, gp); double gM = eM / ( 2. * ( 1. + nu ) ); double kM = eM / ( 3. * ( 1. - 2. * nu ) ); - volumetricStrain = computeDeviatoricVolumetricSplit(strainDeviator, strain); + //auto [strainDeviator, volumetricStrain] = computeDeviatoricVolumetricSplit(strain); // c++17 + auto tmp = computeDeviatoricVolumetricSplit(strain); + auto strainDeviator = tmp.first; + auto volumetricStrain = tmp.second; // compute trial elastic strains - double volumetricElasticTrialStrain = - volumetricStrain - status->giveVolumetricPlasticStrain(); - FloatArray plasticStrainDeviator = status->givePlasticStrainDeviator(); - FloatArray elasticStrainDeviator = strainDeviator; - elasticStrainDeviator.subtract(plasticStrainDeviator); + double volumetricElasticTrialStrain = volumetricStrain - status->giveVolumetricPlasticStrain(); + auto plasticStrainDeviator = status->givePlasticStrainDeviator(); + auto elasticStrainDeviator = strainDeviator - plasticStrainDeviator; // compute trial stresses - FloatArray stressDeviator; double volumetricStress = 3. * kM * volumetricElasticTrialStrain; - applyDeviatoricElasticStiffness(stressDeviator, elasticStrainDeviator, gM); + auto stressDeviator = applyDeviatoricElasticStiffness(elasticStrainDeviator, gM); // norm of trial stress deviator double trialStressJTwo = computeSecondStressInvariant(stressDeviator); @@ -352,20 +304,18 @@ DruckerPragerPlasticitySM :: performLocalStressReturn(GaussPoint *gp, status->letTempKappaBe(tempKappa); // compute full stresses from deviatoric and volumetric part and store them - FloatArray stress; - computeDeviatoricVolumetricSum(stress, stressDeviator, volumetricStress); + auto stress = computeDeviatoricVolumetricSum(stressDeviator, volumetricStress); status->letTempStressVectorBe(stress); // compute and update plastic strains, volumetric and deviatoric part - applyDeviatoricElasticCompliance(elasticStrainDeviator, stressDeviator, gM); - plasticStrainDeviator = strainDeviator; - plasticStrainDeviator.subtract(elasticStrainDeviator); + elasticStrainDeviator = applyDeviatoricElasticCompliance(stressDeviator, gM); + plasticStrainDeviator = strainDeviator - elasticStrainDeviator; status->letTempPlasticStrainDeviatorBe(plasticStrainDeviator); status->letTempVolumetricPlasticStrainBe(volumetricStrain - volumetricStress / 3. / kM); } bool -DruckerPragerPlasticitySM :: checkForVertexCase(double eM, double gM, double kM, double trialStressJTwo, double volumetricStress, double tempKappa) +DruckerPragerPlasticitySM :: checkForVertexCase(double eM, double gM, double kM, double trialStressJTwo, double volumetricStress, double tempKappa) const { // delta lambda max corresponds to the maximum value // of the rate of the plastic multiplier for regular plastic flow @@ -387,7 +337,7 @@ DruckerPragerPlasticitySM :: checkForVertexCase(double eM, double gM, double kM, } void -DruckerPragerPlasticitySM :: performRegularReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArray &stressDeviator, double &volumetricStress, double &tempKappa) +DruckerPragerPlasticitySM :: performRegularReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArrayF<6> &stressDeviator, double &volumetricStress, double &tempKappa) const { // delta lambda max controls the maximum plastic flow, see below double deltaLambdaMax = sqrt(trialStressJTwo) / gM; @@ -398,16 +348,9 @@ DruckerPragerPlasticitySM :: performRegularReturn(double eM, double gM, double k // yield value prime is derivative of yield value with respect to deltaLambda double yieldValuePrimeZero = -9. * alpha * alphaPsi * kM - gM; - FloatArray flowDir = stressDeviator; - flowDir.times( 1. / sqrt(2. * trialStressJTwo) ); - - - // some variables needed for iteration - double yieldValuePrime; - FloatArray plasticFlow; + auto flowDir = stressDeviator * ( 1. / sqrt(2. * trialStressJTwo) ); // initialize Newton iteration - double tempJTwo; int iterationCount = 0; double deltaLambda = 0.; double deltaLambdaIncrement = 0.; @@ -420,7 +363,7 @@ DruckerPragerPlasticitySM :: performRegularReturn(double eM, double gM, double k OOFEM_ERROR("Newton iteration for deltaLambda (regular stress return) did not converge after newtonIter iterations. You might want to try increasing the optional parameter newtoniter or yieldtol in the material record of your input file."); } - yieldValuePrime = yieldValuePrimeZero - kFactor *computeYieldStressPrime(tempKappa, eM); + double yieldValuePrime = yieldValuePrimeZero - kFactor *computeYieldStressPrime(tempKappa, eM); deltaLambdaIncrement = -yieldValue / yieldValuePrime; // deltaLambdaMax may be exceeded if the yield stress has almost vanished @@ -436,12 +379,11 @@ DruckerPragerPlasticitySM :: performRegularReturn(double eM, double gM, double k tempKappa += kFactor * deltaLambdaIncrement; volumetricStress -= volConstant * deltaLambdaIncrement; - // plasticFlow = flowDir ; - //plasticFlow.times( devConstant * deltaLambdaIncrement ) ; - //stressDeviator.subtract( plasticFlow ) ; + // auto plasticFlow = flowDir * (devConstant * deltaLambdaIncrement) + //stressDeviator -= plasticFlow; - stressDeviator.add(-devConstant * deltaLambdaIncrement, flowDir); - tempJTwo = computeSecondStressInvariant(stressDeviator); + stressDeviator += (-devConstant * deltaLambdaIncrement) * flowDir; + double tempJTwo = computeSecondStressInvariant(stressDeviator); yieldValue = computeYieldValue(volumetricStress, tempJTwo, tempKappa, eM); newtonError = fabs(yieldValue / eM); //printf("newtonError = %e\n", newtonError) ; @@ -455,7 +397,7 @@ DruckerPragerPlasticitySM :: performRegularReturn(double eM, double gM, double k } void -DruckerPragerPlasticitySM :: performVertexReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArray &stressDeviator, double &volumetricStress, double &tempKappa, double volumetricElasticTrialStrain, double kappa) +DruckerPragerPlasticitySM :: performVertexReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArrayF<6> &stressDeviator, double &volumetricStress, double &tempKappa, double volumetricElasticTrialStrain, double kappa) const { // declare some constants for faster use // yield value prime is derivative of yield value with respect to deltaLambda @@ -463,12 +405,9 @@ DruckerPragerPlasticitySM :: performVertexReturn(double eM, double gM, double kM // contribution of deviatoric strain to hardening double deviatorContribution = trialStressJTwo / 3. / gM / gM; // in the vertex case, deviatoric stresses are zero - stressDeviator.zero(); + stressDeviator = zeros<6>(); volumetricStress = 3. * kM * volumetricElasticTrialStrain; - // needed for iteration - double yieldValuePrime; - // initialize Newton iteration int iterationCount = 0; double deltaVolumetricStress = 0.; @@ -485,6 +424,7 @@ DruckerPragerPlasticitySM :: performVertexReturn(double eM, double gM, double kM } // exclude division by zero + double yieldValuePrime; if ( deltaKappa == 0. ) { yieldValuePrime = yieldValuePrimeZero - sqrt(2.) / 3. / kM *computeYieldStressPrime(tempKappa, eM); @@ -532,21 +472,14 @@ DruckerPragerPlasticitySM :: computeYieldStressInShear(double kappa, double eM) yieldStress = 0.; //printf("Yield stress zero reached in computeYieldStressInShear.\n") ; } - - break; + return yieldStress; case 2: // exponential hardening - yieldStress = - limitYieldStress - ( limitYieldStress - initialYieldStress ) * exp(-kappa / kappaC); - break; + return limitYieldStress - ( limitYieldStress - initialYieldStress ) * exp(-kappa / kappaC); default: //StructuralMaterial :: OOFEM_ERROR( "Case failed: choose linear hardening/softening (1), exponential hardening/softening (2) in input file.") ; OOFEM_ERROR("Case failed: choose linear hardening/softening (1), exponential hardening/softening (2) in input file."); return 0.; - - break; } - - return yieldStress; } double @@ -560,57 +493,44 @@ DruckerPragerPlasticitySM :: computeYieldStressPrime(double kappa, double eM) co } else { return eM * hardeningModulus; } - - break; case 2: // exponential hardening return ( limitYieldStress - initialYieldStress ) / kappaC *exp(-kappa / kappaC); - - break; default: //StructuralMaterial :: OOFEM_ERROR( "Case failed: choose linear hardening/softening (1), exponential hardening/softening (2) in input file.") ; OOFEM_ERROR("Case failed: choose linear hardening/softening (1), exponential hardening/softening (2) in input file."); return 0.; - - break; } } -void -DruckerPragerPlasticitySM :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, + +FloatMatrixF<6,6> +DruckerPragerPlasticitySM :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { switch ( mode ) { case ElasticStiffness: - LEMaterial->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); - break; + return LEMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep); case SecantStiffness: - LEMaterial->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); - break; - + return LEMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep); case TangentStiffness: switch ( ( static_cast< DruckerPragerPlasticitySMStatus * >( this->giveStatus(gp) ) ) ->giveTempStateFlag() ) { case DruckerPragerPlasticitySMStatus :: DP_Elastic: // elastic stiffness case DruckerPragerPlasticitySMStatus :: DP_Unloading: // elastic stiffness - LEMaterial->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); - break; + return LEMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep); case DruckerPragerPlasticitySMStatus :: DP_Yielding: // elasto-plastic stiffness for regular case //printf("\nAssembling regular algorithmic stiffness matrix.") ; - giveRegAlgorithmicStiffMatrix(answer, mode, gp, tStep); - break; + return giveRegAlgorithmicStiffMatrix(mode, gp, tStep); case DruckerPragerPlasticitySMStatus :: DP_Vertex: // elasto-plastic stiffness for vertex case //printf("\nAssembling vertex case algorithmic stiffness matrix.") ; - giveVertexAlgorithmicStiffMatrix(answer, mode, gp, tStep); - break; + return giveVertexAlgorithmicStiffMatrix(mode, gp, tStep); default: OOFEM_ERROR("Case did not match."); - break; } break; @@ -619,32 +539,28 @@ DruckerPragerPlasticitySM :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, OOFEM_ERROR("Switch failed: Only elastic and tangent stiffness are supported."); break; } + return FloatMatrixF<6,6>(); } -void -DruckerPragerPlasticitySM :: giveRegAlgorithmicStiffMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +DruckerPragerPlasticitySM :: giveRegAlgorithmicStiffMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - int i, j; - DruckerPragerPlasticitySMStatus *status = - static_cast< DruckerPragerPlasticitySMStatus * >( this->giveStatus(gp) ); + auto status = static_cast< DruckerPragerPlasticitySMStatus * >( this->giveStatus(gp) ); + + const auto &stressVector = status->giveTempStressVector(); - const FloatArray &stressVector = status->giveTempStressVector(); - FloatArray deviatoricStress; - computeDeviatoricVolumetricSplit(deviatoricStress, stressVector); + auto deviatoricStress = computeDeviator(stressVector); + double normOfStress = sqrt( 2. * computeSecondStressInvariant(deviatoricStress) ); // elastic constants - double eM = LEMaterial->give(Ex, gp); - double nu = LEMaterial->give(NYxz, gp); + double eM = LEMaterial.give(Ex, gp); + double nu = LEMaterial.give(NYxz, gp); double gM = eM / ( 2. * ( 1. + nu ) ); double kM = eM / ( 3. * ( 1. - 2. * nu ) ); - - - FloatArray flowDir = deviatoricStress; - flowDir.times(1. / normOfStress); + auto flowDir = deviatoricStress / normOfStress; double kappa = status->giveKappa(); double tempKappa = status->giveTempKappa(); @@ -663,73 +579,71 @@ DruckerPragerPlasticitySM :: giveRegAlgorithmicStiffMatrix(FloatMatrix &answer, double d_const = sqrt(2.) * alpha * gM / hStar; double e_const = gM / hStar - deltaLambdaStar; - FloatMatrix A_Matrix(6, 6); - A_Matrix.zero(); - for ( i = 1; i < 7; i++ ) { + FloatMatrixF<6,6> A_Matrix; + + for ( int i = 1; i < 7; i++ ) { A_Matrix.at(i, i) = a_const; } - for ( i = 1; i < 4; i++ ) { - for ( j = 1; j < 4; j++ ) { + for ( int i = 1; i < 4; i++ ) { + for ( int j = 1; j < 4; j++ ) { A_Matrix.at(i, j) += b_const; } } - for ( i = 1; i < 4; i++ ) { - for ( j = 1; j < 4; j++ ) { + for ( int i = 1; i < 4; i++ ) { + for ( int j = 1; j < 4; j++ ) { A_Matrix.at(i, j) += c_const * flowDir.at(j); } - for ( j = 4; j < 7; j++ ) { + for ( int j = 4; j < 7; j++ ) { A_Matrix.at(i, j) += 2. *c_const *flowDir.at(j); } } - for ( i = 1; i < 7; i++ ) { - for ( j = 1; j < 4; j++ ) { + for ( int i = 1; i < 7; i++ ) { + for ( int j = 1; j < 4; j++ ) { A_Matrix.at(i, j) += d_const * flowDir.at(i); } } - for ( i = 1; i < 7; i++ ) { - for ( j = 1; j < 4; j++ ) { + for ( int i = 1; i < 7; i++ ) { + for ( int j = 1; j < 4; j++ ) { A_Matrix.at(i, j) += e_const * flowDir.at(i) * flowDir.at(j); } // account for engineering notation - for ( j = 4; j < 7; j++ ) { + for ( int j = 4; j < 7; j++ ) { A_Matrix.at(i, j) += 2. *e_const *flowDir.at(i) * flowDir.at(j); } } - FloatMatrix De; - LEMaterial->give3dMaterialStiffnessMatrix(De, mode, gp, tStep); + auto De = LEMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep); // answer is A_Matrix^-1 * De - A_Matrix.solveForRhs(De, answer); + return dot(inv(A_Matrix), De); } -void -DruckerPragerPlasticitySM :: giveVertexAlgorithmicStiffMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +DruckerPragerPlasticitySM :: giveVertexAlgorithmicStiffMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - DruckerPragerPlasticitySMStatus *status = - static_cast< DruckerPragerPlasticitySMStatus * >( this->giveStatus(gp) ); + auto status = static_cast< DruckerPragerPlasticitySMStatus * >( this->giveStatus(gp) ); double tempKappa = status->giveTempKappa(); double deltaKappa = tempKappa - status->giveKappa(); // elastic constants - double eM = LEMaterial->give(Ex, gp); - double nu = LEMaterial->give(NYxz, gp); + double eM = LEMaterial.give(Ex, gp); + double nu = LEMaterial.give(NYxz, gp); //double gM = eM / ( 2. * ( 1. + nu ) ); double kM = eM / ( 3. * ( 1. - 2. * nu ) ); if ( deltaKappa <= 0. ) { // This case occurs in the first iteration of a step. // printf("deltaKappa<=0. for vertex case algorithmic stiffness, i.e. continuum tangent stiffness. Since the continuum tangent stiffness does not exist at the vertex, elastic stiffness is used instead. This will cause the loss of quadratic convergence.\n") ; - LEMaterial->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + return LEMaterial.give3dMaterialStiffnessMatrix( mode, gp, tStep); + } double deltaVolumetricPlasticStrain = @@ -737,11 +651,9 @@ DruckerPragerPlasticitySM :: giveVertexAlgorithmicStiffMatrix(FloatMatrix &answe double HBar = computeYieldStressPrime(tempKappa, eM); // compute elastic trial strain deviator of latest temp-state - FloatArray strainDeviator; - computeDeviatoricVolumetricSplit(strainDeviator, status->giveTempStrainVector()); + auto strainDeviator = computeDeviator(status->giveTempStrainVector()); - FloatArray elasticStrainDeviator = strainDeviator; - elasticStrainDeviator.subtract( status->givePlasticStrainDeviator() ); + auto elasticStrainDeviator = strainDeviator - FloatArrayF<6>(status->givePlasticStrainDeviator()); double a_const = kM * HBar / ( HBar * deltaVolumetricPlasticStrain + 9. / 2. * alpha * kM * deltaKappa ); @@ -751,8 +663,8 @@ DruckerPragerPlasticitySM :: giveVertexAlgorithmicStiffMatrix(FloatMatrix &answe } // compute the algorithmic tangent stiffness - answer.resize(6, 6); - answer.zero(); + + FloatMatrixF<6,6> answer; for ( int i = 1; i < 4; i++ ) { for ( int j = 1; j < 4; j++ ) { answer.at(i, j) = deltaVolumetricPlasticStrain; @@ -769,7 +681,7 @@ DruckerPragerPlasticitySM :: giveVertexAlgorithmicStiffMatrix(FloatMatrix &answe } } - answer.times(a_const); + return a_const * answer; } int @@ -778,12 +690,11 @@ DruckerPragerPlasticitySM :: giveIPValue(FloatArray &answer, InternalStateType type, TimeStep *tStep) { - const DruckerPragerPlasticitySMStatus *status = - static_cast< DruckerPragerPlasticitySMStatus * >( giveStatus(gp) ); + const auto status = static_cast< DruckerPragerPlasticitySMStatus * >( giveStatus(gp) ); switch ( type ) { case IST_PlasticStrainTensor: - status->givePlasticStrainVector(answer); + answer = status->givePlasticStrainVector(); return 1; case IST_DamageTensor: @@ -800,15 +711,14 @@ DruckerPragerPlasticitySM :: giveIPValue(FloatArray &answer, MaterialStatus * DruckerPragerPlasticitySM :: CreateStatus(GaussPoint *gp) const { - return new DruckerPragerPlasticitySMStatus(1, StructuralMaterial :: giveDomain(), gp); + return new DruckerPragerPlasticitySMStatus(gp); } double DruckerPragerPlasticitySM :: predictRelativeComputationalCost(GaussPoint *gp) { - DruckerPragerPlasticitySMStatus *status = - static_cast< DruckerPragerPlasticitySMStatus * >( giveStatus(gp) ); + auto status = static_cast< DruckerPragerPlasticitySMStatus * >( giveStatus(gp) ); int state_flag = status->giveStateFlag(); if ( ( state_flag == DruckerPragerPlasticitySMStatus :: DP_Vertex ) || diff --git a/src/sm/Materials/druckerPragerPlasticitySM.h b/src/sm/Materials/druckerPragerPlasticitySM.h index 3d31ee780..507660bb1 100644 --- a/src/sm/Materials/druckerPragerPlasticitySM.h +++ b/src/sm/Materials/druckerPragerPlasticitySM.h @@ -38,9 +38,9 @@ #include "floatarray.h" #include "floatmatrix.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/Materials/structuralmaterial.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" ///@name Input fields for DruckerPragerPlasticitySM //@{ @@ -70,53 +70,51 @@ class DruckerPragerPlasticitySMStatus : public StructuralMaterialStatus protected: /// Volumetric plastic strain. - double volumetricPlasticStrain; - double tempVolumetricPlasticStrain; + double volumetricPlasticStrain = 0.; + double tempVolumetricPlasticStrain = 0.; /// Deviatoric of plastic strain. - FloatArray plasticStrainDeviator; - FloatArray tempPlasticStrainDeviator; + FloatArrayF<6> plasticStrainDeviator; + FloatArrayF<6> tempPlasticStrainDeviator; /// Hardening variable. - double kappa; - double tempKappa; + double kappa = 0.; + double tempKappa = 0.; /// Indicates the state (i.e. elastic, yielding, vertex, unloading) of the Gauss point - int state_flag; - int temp_state_flag; + int state_flag = DruckerPragerPlasticitySMStatus :: DP_Elastic; + int temp_state_flag = DruckerPragerPlasticitySMStatus :: DP_Elastic; public: /// Constructor - DruckerPragerPlasticitySMStatus(int n, Domain * d, GaussPoint * gp); + DruckerPragerPlasticitySMStatus(GaussPoint * gp); - /// Destructor - virtual ~DruckerPragerPlasticitySMStatus(); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - - virtual const char *giveClassName() const { return "DruckerPragerPlasticitySMStatus"; } + const char *giveClassName() const override { return "DruckerPragerPlasticitySMStatus"; } /** * Get the full plastic strain vector from the material status. * @param answer Plastic strain vector. */ - void givePlasticStrainVector(FloatArray &answer) const + FloatArrayF<6> givePlasticStrainVector() const { - answer = plasticStrainDeviator; - answer[0] += volumetricPlasticStrain; - answer[1] += volumetricPlasticStrain; - answer[2] += volumetricPlasticStrain; + auto plasticStrain = plasticStrainDeviator; + plasticStrain[0] += volumetricPlasticStrain; + plasticStrain[1] += volumetricPlasticStrain; + plasticStrain[2] += volumetricPlasticStrain; + return plasticStrain; } /** * Get the plastic strain deviator from the material status. * @return Plastic strain deviator. */ - const FloatArray &givePlasticStrainDeviator() const { return plasticStrainDeviator; } + const FloatArrayF<6> &givePlasticStrainDeviator() const { return plasticStrainDeviator; } /** * Get the volumetric plastic strain from the material status. * @return Volumetric plastic strain. @@ -137,18 +135,19 @@ class DruckerPragerPlasticitySMStatus : public StructuralMaterialStatus * Get the temp value of the full plastic strain vector from the material status. * @param answer Temp value of plastic strain vector. */ - void giveTempPlasticStrainVector(FloatArray &answer) const + FloatArrayF<6> giveTempPlasticStrainVector() const { - answer = tempPlasticStrainDeviator; - answer[0] += tempVolumetricPlasticStrain; - answer[1] += tempVolumetricPlasticStrain; - answer[2] += tempVolumetricPlasticStrain; + auto plasticStrain = tempPlasticStrainDeviator; + plasticStrain[0] += tempVolumetricPlasticStrain; + plasticStrain[1] += tempVolumetricPlasticStrain; + plasticStrain[2] += tempVolumetricPlasticStrain; + return plasticStrain; } /** * Get the temp value of the plastic strain deviator from the material status. * @param answer Temp value of plastic strain deviator. */ - const FloatArray &giveTempPlasticStrainDeviator() const { return tempPlasticStrainDeviator; } + const FloatArrayF<6> &giveTempPlasticStrainDeviator() const { return tempPlasticStrainDeviator; } /** * Get the temp value of the volumetric strain deviator from the material status. * @return Temp value of volumetric plastic strain @@ -169,7 +168,7 @@ class DruckerPragerPlasticitySMStatus : public StructuralMaterialStatus * Assign the temp value of deviatoric plastic strain. * @param v New temp value of deviatoric plastic strain. */ - void letTempPlasticStrainDeviatorBe(const FloatArray &v) { tempPlasticStrainDeviator = v; } + void letTempPlasticStrainDeviatorBe(const FloatArrayF<6> &v) { tempPlasticStrainDeviator = v; } /** * Assign the temp value of volumetric plastic strain. * @param v New temp value of volumetric plastic strain. @@ -203,48 +202,43 @@ class DruckerPragerPlasticitySM : public StructuralMaterial * 1: linear hardening/softening with cutoff at zero stress. * 2: exponential hardening/softening to limitYieldStress. */ - int hardeningType; + int hardeningType = 1; /// Parameter of the exponential laws. - double kappaC; + double kappaC = 0.; /// Hardening modulus normalized with the elastic modulus, parameter of the linear hardening/softening law. - double hardeningModulus; + double hardeningModulus = 0.; /// Parameter of the exponential hardening law. - double limitYieldStress; + double limitYieldStress = 0.; /// Parameter of all three laws, this is the initial value of the yield stress in pure shear. - double initialYieldStress; + double initialYieldStress = 0.; /// Friction coefficient, parameter of the yield criterion. - double alpha; + double alpha = 0.; /// Dilatancy coefficient, parameter of the flow rule. - double alphaPsi; + double alphaPsi = 0.; /// Scalar factor between rate of plastic multiplier and rate of hardening variable. - double kFactor; + double kFactor = 0.; /// Associated linear elastic material. - IsotropicLinearElasticMaterial *LEMaterial; + IsotropicLinearElasticMaterial LEMaterial; /// Yield tolerance. - double yieldTol; + double yieldTol = 0.; /// Maximum number of iterations for stress return. - int newtonIter; + int newtonIter = 0; public: /// Constructor DruckerPragerPlasticitySM(int n, Domain * d); - /// Destructor - virtual ~DruckerPragerPlasticitySM(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveClassName() const { return "DruckerPragerPlasticitySM"; } - virtual const char *giveInputRecordName() const { return _IFT_DruckerPragerPlasticitySM_Name; } + const char *giveClassName() const override { return "DruckerPragerPlasticitySM"; } + const char *giveInputRecordName() const override { return _IFT_DruckerPragerPlasticitySM_Name; } - virtual void giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &strainVector, - TimeStep *tStep); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, + TimeStep *tStep) const override; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; /** * Perform a standard local stress return using the function computeYieldValue at the specified Gauss point. @@ -252,7 +246,7 @@ class DruckerPragerPlasticitySM : public StructuralMaterial * @param gp Gauss point. * @param strain Strain vector of this Gauss point. */ - void performLocalStressReturn(GaussPoint *gp, const FloatArray &strain); + void performLocalStressReturn(GaussPoint *gp, const FloatArrayF<6> &strain) const; /** * Check if the trial stress state falls within the vertex region. * @param eM Elasticity modulus. @@ -260,21 +254,21 @@ class DruckerPragerPlasticitySM : public StructuralMaterial * @param kM Bulk modulus. * @return True for vertex case and false if regular stress return has to be used. */ - bool checkForVertexCase(double eM, double gM, double kM, double trialStressJTwo, double volumetricStress, double tempKappa); + bool checkForVertexCase(double eM, double gM, double kM, double trialStressJTwo, double volumetricStress, double tempKappa) const; /** * Perform stress return for regular case, i.e. if the trial stress state does not lie within the vertex region. * @param eM Elasticity modulus. * @param gM Shear modulus. * @param kM Bulk modulus. */ - void performRegularReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArray &stressDeviator, double &volumetricStress, double &tempKappa); + void performRegularReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArrayF<6> &stressDeviator, double &volumetricStress, double &tempKappa) const; /** * Perform stress return for vertex case, i.e. if the trial stress state lies within the vertex region. * @param eM Elasticity modulus. * @param gM Shear modulus. * @param kM Bulk modulus. */ - void performVertexReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArray &stressDeviator, double &volumetricStress, double &tempKappa, double volumetricElasticTrialStrain, double kappa); + void performVertexReturn(double eM, double gM, double kM, double trialStressJTwo, FloatArrayF<6> &stressDeviator, double &volumetricStress, double &tempKappa, double volumetricElasticTrialStrain, double kappa) const; /** * Compute the yield value based on stress and hardening variable. * @param meanStress 1/3 of trace of sigma. @@ -305,43 +299,37 @@ class DruckerPragerPlasticitySM : public StructuralMaterial /** * Compute and give back algorithmic stiffness matrix for the regular case (no vertex). - * @param answer Consistent stiffness matrix. * @param mode Material reponse mode. * @param gp Gauss point. * @param tStep Time step. + * @return Consistent stiffness matrix. */ - void giveRegAlgorithmicStiffMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> giveRegAlgorithmicStiffMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; /** * Compute consistent stiffness matrix for the vertex case. - * @param answer Consistent stiffness matrix. * @param mode Material reponse mode. * @param gp Gauss point. * @param tStep Time step. + * @return Consistent stiffness matrix. */ - void giveVertexAlgorithmicStiffMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> giveVertexAlgorithmicStiffMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; - virtual int giveIPValue(FloatArray &answer, - GaussPoint *gp, - InternalStateType type, - TimeStep *tStep); + int giveIPValue(FloatArray &answer, + GaussPoint *gp, + InternalStateType type, + TimeStep *tStep) override; - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) + FloatArrayF<6> giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override { - LEMaterial->giveThermalDilatationVector(answer, gp, tStep); + return LEMaterial.giveThermalDilatationVector(gp, tStep); } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual double predictRelativeComputationalCost(GaussPoint *gp); - virtual double predictRelativeRedistributionCost(GaussPoint *gp) { return 1.0; } + double predictRelativeComputationalCost(GaussPoint *gp) override; + double predictRelativeRedistributionCost(GaussPoint *gp) override { return 1.0; } }; } // end namespace oofem #endif // druckerpragerplasticitysm_h diff --git a/src/sm/Materials/druckerpragercutmat.C b/src/sm/Materials/druckerpragercutmat.C index 75da12070..a7978036f 100644 --- a/src/sm/Materials/druckerpragercutmat.C +++ b/src/sm/Materials/druckerpragercutmat.C @@ -33,7 +33,7 @@ */ #include "druckerpragercutmat.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "floatmatrix.h" #include "floatarray.h" #include "gausspoint.h" @@ -54,38 +54,20 @@ DruckerPragerCutMat :: DruckerPragerCutMat(int n, Domain *d) : MPlasticMaterial2 // this->rmType = mpm_ClosestPoint; this->plType = nonassociatedPT; // Rankine associated, DP nonassociated - - sigT = 0.; - H = 0.; - omegaCrit = 0.; - a = 0.; - yieldTol = 0.; - newtonIter = 30; - G = 0.; - K = 0.; } -// destructor -DruckerPragerCutMat :: ~DruckerPragerCutMat() -{ } - -// specifies whether a given material mode is supported by this model -int -DruckerPragerCutMat :: hasMaterialModeCapability(MaterialMode mode) +bool +DruckerPragerCutMat :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _3dMat || mode == _PlaneStrain; } // reads the model parameters from the input file -IRResultType -DruckerPragerCutMat :: initializeFrom(InputRecord *ir) +void +DruckerPragerCutMat :: initializeFrom(InputRecord &ir) { - IRResultType result; // required by IR_GIVE_FIELD macro - - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - result = linearElasticMaterial->initializeFrom(ir); // takes care of elastic constants - if ( result != IRRT_OK ) return result; + StructuralMaterial :: initializeFrom(ir); + linearElasticMaterial->initializeFrom(ir); // takes care of elastic constants G = static_cast< IsotropicLinearElasticMaterial * >(linearElasticMaterial)->giveShearModulus(); K = static_cast< IsotropicLinearElasticMaterial * >(linearElasticMaterial)->giveBulkModulus(); @@ -100,19 +82,17 @@ DruckerPragerCutMat :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, a, _IFT_DruckerPragerCutMat_a); // exponent in damage law IR_GIVE_OPTIONAL_FIELD(ir, yieldTol, _IFT_DruckerPragerCutMat_yieldTol); //tolerance of the error in the yield criterion IR_GIVE_OPTIONAL_FIELD(ir, newtonIter, _IFT_DruckerPragerCutMat_newtonIter); //Maximum number of iterations in lambda search - - return IRRT_OK; } MaterialStatus * DruckerPragerCutMat :: CreateStatus(GaussPoint *gp) const { - return new MPlasticMaterial2Status(1, this->giveDomain(), gp, this->giveSizeOfReducedHardeningVarsVector(gp)); + return new MPlasticMaterial2Status(gp, this->giveSizeOfReducedHardeningVarsVector(gp)); } double -DruckerPragerCutMat :: computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, const FloatArray &strainSpaceHardeningVariables) +DruckerPragerCutMat :: computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, const FloatArray &strainSpaceHardeningVariables) const { //strainSpaceHardeningVariables = kappa if ( isurf <= 3 ) { //Rankine, surfaces 1,2,3 @@ -120,20 +100,19 @@ DruckerPragerCutMat :: computeYieldValueAt(GaussPoint *gp, int isurf, const Floa this->computePrincipalValues(princStress, stressVector, principal_stress); return princStress.at(isurf) - this->sigT; } else { //Drucker-Prager, surface 4 - double volumetricStress; double DPYieldStressInShear = tau0 + H *strainSpaceHardeningVariables.at(4); - double JTwo; - FloatArray deviatoricStress; - - volumetricStress = this->computeDeviatoricVolumetricSplit(deviatoricStress, stressVector); - JTwo = computeSecondStressInvariant(deviatoricStress); + //auto [deviatoricStress, volumetricStress] = this->computeDeviatoricVolumetricSplit(stressVector); // c++17 + auto tmp = this->computeDeviatoricVolumetricSplit(stressVector); // c++17 + auto deviatoricStress = tmp.first; + auto volumetricStress = tmp.second; + auto JTwo = computeSecondStressInvariant(deviatoricStress); return 3. * alpha * volumetricStress + sqrt(JTwo) - DPYieldStressInShear; } } //associated and nonassociated flow rule void -DruckerPragerCutMat :: computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, const FloatArray &stressSpaceHardeningVars) +DruckerPragerCutMat :: computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, const FloatArray &stressSpaceHardeningVars) const { FloatArray princStress(3); FloatMatrix t(3, 3); @@ -151,11 +130,9 @@ DruckerPragerCutMat :: computeStressGradientVector(FloatArray &answer, functType answer.at(5) = t.at(1, isurf) * t.at(3, isurf); //xz = 13 answer.at(6) = t.at(1, isurf) * t.at(2, isurf); //xy = 12 } else { //DP nonassociated - double sqrtJTwo; - FloatArray deviatoricStress; - this->computeDeviatoricVolumetricSplit(deviatoricStress, stressVector); - sqrtJTwo = sqrt( computeSecondStressInvariant(deviatoricStress) ); + auto deviatoricStress = this->computeDeviator(stressVector); + auto sqrtJTwo = sqrt( computeSecondStressInvariant(deviatoricStress) ); answer.at(1) = alphaPsi + deviatoricStress.at(1) / 2. / sqrtJTwo; answer.at(2) = alphaPsi + deviatoricStress.at(2) / 2. / sqrtJTwo; @@ -169,7 +146,7 @@ DruckerPragerCutMat :: computeStressGradientVector(FloatArray &answer, functType //necesarry only for mpm_ClosestPoint, see Jirasek: Inelastic analysis of structures, pp. 411. //Hessian matrix void -DruckerPragerCutMat :: computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables) +DruckerPragerCutMat :: computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables) const { switch ( gp->giveMaterialMode() ) { case _3dMat: @@ -186,10 +163,9 @@ DruckerPragerCutMat :: computeReducedSSGradientMatrix(FloatMatrix &gradientMatri if ( isurf == 4 ) { double c1 = 0.; - FloatArray deviatoricStress; double JTwo, sqrtJTwo; - computeDeviatoricVolumetricSplit(deviatoricStress, fullStressVector); + auto deviatoricStress = computeDeviator(fullStressVector); JTwo = computeSecondStressInvariant(deviatoricStress); sqrtJTwo = sqrt(JTwo); @@ -235,13 +211,13 @@ DruckerPragerCutMat :: computeReducedSSGradientMatrix(FloatMatrix &gradientMatri void DruckerPragerCutMat :: computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { /* Returns elastic moduli in reduced stress-strain space*/ - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); + this->linearElasticMaterial->giveStiffnessMatrix(answer, ElasticStiffness, gp, tStep); } //answer is dkappa (cumulative plastic strain), flow rule -void DruckerPragerCutMat :: computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &stress, const FloatArray &dlambda, const FloatArray &dplasticStrain, const IntArray &activeConditionMap) +void DruckerPragerCutMat :: computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &stress, const FloatArray &dlambda, const FloatArray &dplasticStrain, const IntArray &activeConditionMap) const { answer.resize(4); answer.zero(); @@ -252,7 +228,7 @@ void DruckerPragerCutMat :: computeStrainHardeningVarsIncrement(FloatArray &answ } // Computes the derivative of yield/loading function with respect to kappa_1, kappa_2 etc. -void DruckerPragerCutMat :: computeKGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables) +void DruckerPragerCutMat :: computeKGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables) const { answer.resize(1); //1 hardening variable for DP model - kappa answer.zero(); @@ -264,7 +240,7 @@ void DruckerPragerCutMat :: computeKGradientVector(FloatArray &answer, functType //necesarry only for mpm_ClosestPoint //Computes second mixed derivative of loading function with respect to stress and hardening vars. -void DruckerPragerCutMat :: computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables) +void DruckerPragerCutMat :: computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables) const { int size = StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ); gradientMatrix.resize(size, 1); //six stresses in 3D and one kappa @@ -272,7 +248,7 @@ void DruckerPragerCutMat :: computeReducedSKGradientMatrix(FloatMatrix &gradient } // computes dKappa_i/dsig_j gradient matrix -void DruckerPragerCutMat :: computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, GaussPoint *gp, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, const FloatArray &dlambda) +void DruckerPragerCutMat :: computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, GaussPoint *gp, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, const FloatArray &dlambda) const { int size = StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ); answer.resize(1, size); @@ -280,7 +256,7 @@ void DruckerPragerCutMat :: computeReducedHardeningVarsSigmaGradient(FloatMatrix } // computes dKappa_i/dLambda_j for one surface -void DruckerPragerCutMat :: computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPoint *gp, int actSurf, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, const FloatArray &dlambda) +void DruckerPragerCutMat :: computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPoint *gp, int actSurf, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, const FloatArray &dlambda) const { int indx; answer.resize(1, actSurf); //actSurf = number of active surfaces diff --git a/src/sm/Materials/druckerpragercutmat.h b/src/sm/Materials/druckerpragercutmat.h index 6e0f33be9..a2bdff61f 100644 --- a/src/sm/Materials/druckerpragercutmat.h +++ b/src/sm/Materials/druckerpragercutmat.h @@ -35,7 +35,7 @@ #ifndef druckerpragercatmat_h #define druckerpragercatmat_h -#include "Materials/ConcreteMaterials/mplasticmaterial2.h" +#include "sm/Materials/ConcreteMaterials/mplasticmaterial2.h" ///@name Input fields for DruckerPragerCutMat //@{ @@ -67,91 +67,91 @@ class DruckerPragerCutMat : public MPlasticMaterial2 //LinearElasticMaterial *linearElasticMaterial; /// Elastic shear modulus. - double G; + double G = 0.; /// Elastic bulk modulus. - double K; + double K = 0.; /// Hardening modulus. - double H; + double H = 0.; /// Uniaxial tensile strength for cut-off. - double sigT; + double sigT = 0.; /// Initial yield stress under pure shear. - double tau0; + double tau0 = 0.; /// Friction coefficient. - double alpha; + double alpha = 0.; ///Dilatancy coefficient (allowing non-associated plasticity). - double alphaPsi; + double alphaPsi = 0.; /// Tolerance of the error in the yield criterion. - double yieldTol; + double yieldTol = 0.; /// Maximum number of iterations in lambda search. - int newtonIter; + int newtonIter = 30; /// Maximum damage value. - double omegaCrit; + double omegaCrit = 0.; /// Parameter for damage computation from cumulative plastic strain - double a; + double a = 0.; public: DruckerPragerCutMat(int n, Domain * d); - virtual ~DruckerPragerCutMat(); - virtual int hasMaterialModeCapability(MaterialMode mode); + bool hasMaterialModeCapability(MaterialMode mode) const override; + + bool hasCastingTimeSupport() const override { return true; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual int hasNonLinearBehaviour() { return 1; } - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } - virtual const char *giveClassName() const { return "DruckerPragerCutMat"; } - virtual const char *giveInputRecordName() const { return _IFT_DruckerPragerCutMat_Name; } + const char *giveClassName() const override { return "DruckerPragerCutMat"; } + const char *giveInputRecordName() const override { return _IFT_DruckerPragerCutMat_Name; } /// Returns a reference to the basic elastic material. LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } - virtual int giveSizeOfFullHardeningVarsVector() { return 4; } - virtual int giveSizeOfReducedHardeningVarsVector(GaussPoint *) const { return 4; } //cummulative strain = one per each surface + int giveSizeOfFullHardeningVarsVector() const override { return 4; } + int giveSizeOfReducedHardeningVarsVector(GaussPoint *) const override { return 4; } //cummulative strain = one per each surface protected: - virtual int giveMaxNumberOfActiveYieldConds(GaussPoint *gp) { return 3; } //normally one less than number of all conditions + int giveMaxNumberOfActiveYieldConds(GaussPoint *gp) const override { return 3; } //normally one less than number of all conditions - virtual double computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, const FloatArray &strainSpaceHardeningVariables); + double computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, const FloatArray &strainSpaceHardeningVariables) const override; - virtual void computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, const FloatArray &stressSpaceHardeningVars); + void computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, const FloatArray &stressSpaceHardeningVars) const override; /// Computes second derivative of yield/loading function with respect to stress - virtual void computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables); + void computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables) const override; - virtual void computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep); + void computeReducedElasticModuli(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) const override; /// Functions related to hardening - virtual int hasHardening() { return 1; } + int hasHardening() const override { return 1; } /// Compute dot(kappa_1), dot(kappa_2) etc. - virtual void computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &stress, const FloatArray &dlambda, const FloatArray &dplasticStrain, const IntArray &activeConditionMap); + void computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &stress, const FloatArray &dlambda, const FloatArray &dplasticStrain, const IntArray &activeConditionMap) const override; /// Computes the derivative of yield/loading function with respect to kappa_1, kappa_2 etc. - virtual void computeKGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables); + void computeKGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables) const override; /// computes mixed derivative of load function with respect to stress and hardening variables - virtual void computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables); + void computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVariables) const override; /// computes dk(i)/dsig(j) gradient matrix - virtual void computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, GaussPoint *gp, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, const FloatArray &dlambda); + void computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, GaussPoint *gp, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, const FloatArray &dlambda) const override; /// computes dKappa_i/dLambda_j - virtual void computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPoint *gp, int actSurf, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, const FloatArray &dlambda); + void computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPoint *gp, int actSurf, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, const FloatArray &dlambda) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; }; } // end namespace oofem #endif // druckerpragercatmat_h diff --git a/src/sm/Materials/dustmat.C b/src/sm/Materials/dustmat.C index 939fcd588..7228efd0d 100644 --- a/src/sm/Materials/dustmat.C +++ b/src/sm/Materials/dustmat.C @@ -36,11 +36,11 @@ #include "floatarray.h" #include "floatmatrix.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "gausspoint.h" #include "intarray.h" -#include "../sm/Materials/structuralmaterial.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "datastream.h" #include "contextioerr.h" #include "mathfem.h" @@ -49,10 +49,8 @@ namespace oofem { REGISTER_Material(DustMaterial); -DustMaterialStatus :: DustMaterialStatus(int n, Domain *d, GaussPoint *gp, double q0) : - StructuralMaterialStatus(n, d, gp), - plasticStrain( 6 ), - tempPlasticStrain( 6 ) +DustMaterialStatus :: DustMaterialStatus(GaussPoint *gp, double q0) : + StructuralMaterialStatus(gp) { stressVector.resize(6); strainVector.resize(6); @@ -61,8 +59,6 @@ DustMaterialStatus :: DustMaterialStatus(int n, Domain *d, GaussPoint *gp, doubl q = q0; } -DustMaterialStatus :: ~DustMaterialStatus() -{ } void DustMaterialStatus :: initTempStatus() @@ -85,7 +81,7 @@ DustMaterialStatus :: updateYourself(TimeStep *tStep) } void -DustMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +DustMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { // Call the corresponding function of the parent class to print variables defined there. StructuralMaterialStatus :: printOutputAt(file, tStep); @@ -121,31 +117,17 @@ DustMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) fprintf(file, "}\n"); } -contextIOResultType -DustMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +DustMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + StructuralMaterialStatus :: saveContext(stream, mode); } -contextIOResultType -DustMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +DustMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + StructuralMaterialStatus :: restoreContext(stream, mode); } @@ -155,28 +137,19 @@ DustMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void // ************************************************************* -DustMaterial :: DustMaterial(int n, Domain *d) : StructuralMaterial(n, d) +DustMaterial :: DustMaterial(int n, Domain *d) : StructuralMaterial(n, d), + LEMaterial(n, d) { - LEMaterial = new IsotropicLinearElasticMaterial(n, d); } -DustMaterial :: ~DustMaterial() -{ - delete LEMaterial; -} -IRResultType -DustMaterial :: initializeFrom(InputRecord *ir) +void +DustMaterial :: initializeFrom(InputRecord &ir) { - // Required by IR_GIVE_FIELD macro - IRResultType result; // call the corresponding service of structural material - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - + StructuralMaterial :: initializeFrom(ir); // call the corresponding service for the linear elastic material - result = this->LEMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) return result; + this->LEMaterial.initializeFrom(ir); // instanciate the variables defined in DustMaterial ft = 3e6; @@ -207,38 +180,31 @@ DustMaterial :: initializeFrom(InputRecord *ir) // check parameters admissibility if ( ft < 0 ) { - OOFEM_WARNING("parameter 'ft' must be positive"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_DustMaterial_ft, "must be positive"); } if ( x0 < 0 ) { - OOFEM_WARNING("parameter 'x0' must be positive"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_DustMaterial_x0, "must be positive"); } if ( rEll < 0 ) { - OOFEM_WARNING("parameter 'rEll' must be positive"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_DustMaterial_rEll, "must be positive"); } if ( theta < 0 ) { - OOFEM_WARNING("parameter 'theta' must be positive"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_DustMaterial_theta, "must be positive"); } if ( beta < 0 ) { - OOFEM_WARNING("parameter 'beta' must be positive"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_DustMaterial_beta, "must be positive"); } if ( lambda < 0 ) { - OOFEM_WARNING("parameter 'lambda' must be positive"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_DustMaterial_lambda, "must be positive"); } if ( alpha < lambda ) { - OOFEM_WARNING("parameter 'alpha' must be greater than parameter 'lambda'"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_DustMaterial_alpha, "must be greater than lambda"); } x0 = -x0; // compressive strength is negative, although on input it is a positive number @@ -248,62 +214,60 @@ DustMaterial :: initializeFrom(InputRecord *ir) q0 = x0; solveQ0(q0); - - return IRRT_OK; } -void -DustMaterial :: giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) +FloatArrayF<6> +DustMaterial :: giveRealStressVector_3d(const FloatArrayF<6> &strain, + GaussPoint *gp, TimeStep *tStep) const { - FloatArray strainVectorR; - - DustMaterialStatus *status = static_cast< DustMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< DustMaterialStatus * >( this->giveStatus(gp) ); // Initialize temp variables for this Gauss point this->initTempStatus(gp); // subtract stress-independent part of strain - this->giveStressDependentPartOfStrainVector_3d(strainVectorR, gp, totalStrain, tStep, VM_Total); + auto thermalStrain = this->computeStressIndependentStrainVector_3d(gp, tStep, VM_Total); + auto strainVectorR = strain - thermalStrain; // perform the local stress return and update the history variables performStressReturn(gp, strainVectorR); // copy total strain vector to the temp status - status->letTempStrainVectorBe(totalStrain); + status->letTempStrainVectorBe(strain); // pass the correct form of stressVector to giveRealStressVector - answer = status->giveTempStressVector(); + return status->giveTempStressVector(); } void -DustMaterial :: performStressReturn(GaussPoint *gp, const FloatArray &strain) +DustMaterial :: performStressReturn(GaussPoint *gp, const FloatArrayF<6> &strain) const { - DustMaterialStatus *status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); + auto status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); // compute total strain components - FloatArray strainDeviator; - double volumetricStrain; - volumetricStrain = computeDeviatoricVolumetricSplit(strainDeviator, strain); + //auto [strainDeviator, volumetricStrain] = computeDeviatoricVolumetricSplit(strain); // c++17 + auto tmp = computeDeviatoricVolumetricSplit(strain); + auto strainDeviator = tmp.first; + auto volumetricStrain = tmp.second; // compute trial elastic strains - FloatArray plasticStrain = status->givePlasticStrain(); - double volumetricPlasticStrain; - FloatArray plasticStrainDeviator; - volumetricPlasticStrain = computeDeviatoricVolumetricSplit(plasticStrainDeviator, plasticStrain); + auto plasticStrain = status->givePlasticStrain(); + + //auto [plasticStrainDeviator, volumetricPlasticStrain] = computeDeviatoricVolumetricSplit(plasticStrain); // c++17 + auto tmp2 = computeDeviatoricVolumetricSplit(plasticStrain); + auto plasticStrainDeviator = tmp2.first; + auto volumetricPlasticStrain = tmp2.second; + double volumetricElasticStrain = volumetricStrain - volumetricPlasticStrain; - FloatArray elasticStrainDeviator = strainDeviator; - elasticStrainDeviator.subtract(plasticStrainDeviator); + auto elasticStrainDeviator = strainDeviator - plasticStrainDeviator; // compute trial stresses double bulkModulus, shearModulus; computeAndSetBulkAndShearModuli(bulkModulus, shearModulus, gp); double volumetricStress = 3. * bulkModulus * volumetricElasticStrain; - FloatArray stressDeviator = {2 * elasticStrainDeviator[0], 2 * elasticStrainDeviator[1], 2 * elasticStrainDeviator[2], + FloatArrayF<6> stressDeviator = {2 * elasticStrainDeviator[0], 2 * elasticStrainDeviator[1], 2 * elasticStrainDeviator[2], elasticStrainDeviator[3], elasticStrainDeviator[4], elasticStrainDeviator[5]}; - stressDeviator.times(shearModulus); + stressDeviator *= shearModulus; // norm of trial stress deviator double rho = computeSecondCoordinate(stressDeviator); @@ -316,7 +280,7 @@ DustMaterial :: performStressReturn(GaussPoint *gp, const FloatArray &strain) // actual stress return double lambda = 0.; - FloatArray m(6); + FloatArrayF<6> m; double feft = functionFe(ft); double auxModulus = 2 * shearModulus / ( 9 * bulkModulus ); double temp = feft - auxModulus * ( i1 - ft ) / functionFeDI1(ft); @@ -326,13 +290,13 @@ DustMaterial :: performStressReturn(GaussPoint *gp, const FloatArray &strain) performF1return(i1, rho, gp); tempQ = status->giveTempQ(); lambda = ( rho - functionFe( functionI1(q, tempQ, i1, bulkModulus) ) ) / ( 2 * shearModulus ); - computePlastStrainDirM1(m, stressDeviator, rho, i1, q); + m = computePlastStrainDirM1(stressDeviator, rho, i1, q); } else if ( f2 > 0 && i1 < q ) { // yield function 2 status->letTempStateFlagBe(DustMaterialStatus :: DM_Yielding2); performF2return(i1, rho, gp); tempQ = status->giveTempQ(); lambda = computeDeltaGamma2(tempQ, q, i1, bulkModulus); - computePlastStrainDirM2(m, stressDeviator, rho, i1, tempQ); + m = computePlastStrainDirM2(stressDeviator, rho, i1, tempQ); } else if ( f3 > 0 && rho < temp ) { // yield function 3 status->letTempStateFlagBe(DustMaterialStatus :: DM_Yielding3); double fFeFt = functionFe(ft); @@ -350,7 +314,7 @@ DustMaterial :: performStressReturn(GaussPoint *gp, const FloatArray &strain) } status->letTempQBe(tempQ); - computePlastStrainDirM3(m, stressDeviator, rho, i1, tempQ); + m = computePlastStrainDirM3(stressDeviator, rho, i1, tempQ); } else { // elastic case int stateFlag = status->giveStateFlag(); if ( ( stateFlag == DustMaterialStatus :: DM_Unloading ) || ( stateFlag == DustMaterialStatus :: DM_Elastic ) ) { @@ -365,21 +329,21 @@ DustMaterial :: performStressReturn(GaussPoint *gp, const FloatArray &strain) } // compute correct stress - m.times(lambda); - plasticStrain.add(m); - double mVol; - FloatArray mDeviator; - mVol = computeDeviatoricVolumetricSplit(mDeviator, m); + m *= lambda; + plasticStrain += m; + + //auto [mDeviator, mVol] = computeDeviatoricVolumetricSplit(m); // c++17 + auto tmp3 = computeDeviatoricVolumetricSplit(m); + auto mDeviator = tmp3.first; + auto mVol = tmp3.second; + i1 -= 3 * bulkModulus * mVol; volumetricStress = i1 / 3.; - mDeviator.times(-2 * shearModulus); - stressDeviator.add(mDeviator); + stressDeviator += (-2 * shearModulus) * mDeviator; // compute full stresses from deviatoric and volumetric part and store them - FloatArray stress = stressDeviator; - stress.at(1) += volumetricStress; - stress.at(2) += volumetricStress; - stress.at(3) += volumetricStress; + auto stress = computeDeviatoricVolumetricSum(stressDeviator, volumetricStress); + status->letTempStressVectorBe(stress); // compute and update plastic strain and q @@ -387,30 +351,28 @@ DustMaterial :: performStressReturn(GaussPoint *gp, const FloatArray &strain) } void -DustMaterial :: performF1return(double i1, double rho, GaussPoint *gp) +DustMaterial :: performF1return(double i1, double rho, GaussPoint *gp) const { - DustMaterialStatus *status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); + auto status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); double bulkModulus = status->giveBulkModulus(); double shearModulus = status->giveShearModulus(); double q = status->giveQ(); double tempQ = status->giveTempQ(); - double fx, dfx; double m = 9 * bulkModulus / ( 2 * shearModulus ); - double vfI1, vfI1DQ, a, b, c, d, da, db, dc; int positiveFlag = 0; for ( int i = 0; i < newtonIter; i++ ) { - vfI1 = functionI1(q, tempQ, i1, bulkModulus); - vfI1DQ = functionI1DQ(tempQ, bulkModulus); - a = ( vfI1 - tempQ ) / ( ft - tempQ ); - b = functionFeDI1(vfI1); - c = rho - functionFe(vfI1); - da = ( ( vfI1DQ - 1 ) * ( ft - tempQ ) + ( vfI1 - tempQ ) ) / ( ( ft - tempQ ) * ( ft - tempQ ) ); - db = functionFeDI1DI1(vfI1) * vfI1DQ; - dc = -functionFeDI1(vfI1) * vfI1DQ; - d = da * b * c + a * db * c + a * b * dc; - fx = -3 *bulkModulus *functionH(q, tempQ) - m * a * b * c; - dfx = -3 *bulkModulus *functionHDQ(tempQ) - m * d; + double vfI1 = functionI1(q, tempQ, i1, bulkModulus); + double vfI1DQ = functionI1DQ(tempQ, bulkModulus); + double a = ( vfI1 - tempQ ) / ( ft - tempQ ); + double b = functionFeDI1(vfI1); + double c = rho - functionFe(vfI1); + double da = ( ( vfI1DQ - 1 ) * ( ft - tempQ ) + ( vfI1 - tempQ ) ) / ( ( ft - tempQ ) * ( ft - tempQ ) ); + double db = functionFeDI1DI1(vfI1) * vfI1DQ; + double dc = -functionFeDI1(vfI1) * vfI1DQ; + double d = da * b * c + a * db * c + a * b * dc; + double fx = -3 *bulkModulus *functionH(q, tempQ) - m * a * b * c; + double dfx = -3 *bulkModulus *functionHDQ(tempQ) - m * d; tempQ -= fx / dfx; if ( tempQ >= 0 ) { if ( positiveFlag >= 1 ) { @@ -433,20 +395,18 @@ DustMaterial :: performF1return(double i1, double rho, GaussPoint *gp) } void -DustMaterial :: performF2return(double i1, double rho, GaussPoint *gp) +DustMaterial :: performF2return(double i1, double rho, GaussPoint *gp) const { - DustMaterialStatus *status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); + auto status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); double bulkModulus = status->giveBulkModulus(); double shearModulus = status->giveShearModulus(); double q = status->giveQ(); double qRight = q; double qLeft = q; double tempQ = .5 * ( qLeft + qRight ); - double fq; - double fx, dfx; for ( int i = 0; i < newtonIter; i++ ) { - fx = i1 - 3 *bulkModulus *functionH(q, qLeft) - qLeft; - dfx = -3 *bulkModulus *functionHDQ(qLeft) - 1; + double fx = i1 - 3 *bulkModulus *functionH(q, qLeft) - qLeft; + double dfx = -3 *bulkModulus *functionHDQ(qLeft) - 1; qLeft -= fx / dfx; if ( fabs(fx / dfx / q0) < newtonTol ) { break; @@ -454,7 +414,7 @@ DustMaterial :: performF2return(double i1, double rho, GaussPoint *gp) } for ( int i = 0; i < newtonIter; i++ ) { - fq = fTempR2(tempQ, q, i1, rho, bulkModulus, shearModulus); + double fq = fTempR2(tempQ, q, i1, rho, bulkModulus, shearModulus); if ( fabs( ( qRight - qLeft ) / qRight ) < newtonTol ) { status->letTempQBe(tempQ); return; @@ -473,17 +433,16 @@ DustMaterial :: performF2return(double i1, double rho, GaussPoint *gp) } void -DustMaterial :: computeQFromPlastVolEps(double &answer, double q, double deltaVolumetricPlasticStrain) +DustMaterial :: computeQFromPlastVolEps(double &answer, double q, double deltaVolumetricPlasticStrain) const { if ( q >= 0. ) { answer = 0.; return; } - double fx, dfx; for ( int i = 0; i <= newtonIter; i++ ) { - fx = functionH(q, answer) - deltaVolumetricPlasticStrain; - dfx = functionHDQ(answer); + double fx = functionH(q, answer) - deltaVolumetricPlasticStrain; + double dfx = functionHDQ(answer); answer -= fx / dfx; if ( fabs(fx / dfx / answer) < newtonTol ) { if ( answer > 0 ) { @@ -498,21 +457,19 @@ DustMaterial :: computeQFromPlastVolEps(double &answer, double q, double deltaVo OOFEM_ERROR("Newton's method did not converge"); } -void -DustMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +DustMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - DustMaterialStatus *status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); - double ym0 = LEMaterial->giveYoungsModulus(); + auto status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); + double ym0 = LEMaterial.giveYoungsModulus(); double ym = status->giveYoungsModulus(); double coeff = status->giveVolumetricPlasticStrain() < 0 ? ym / ym0 : 1.0; if ( mode == ElasticStiffness ) { - LEMaterial->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + return LEMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep); } else if ( mode == SecantStiffness || mode == TangentStiffness ) { - LEMaterial->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); - answer.times(coeff); + return coeff * LEMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep); } else { OOFEM_ERROR("Unsupported MatResponseMode"); } @@ -521,7 +478,7 @@ DustMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, int DustMaterial :: setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type) { - DustMaterialStatus *status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); + auto status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); if ( type == IST_PlasticStrainTensor ) { status->letPlasticStrainBe(value); return 1; @@ -539,7 +496,7 @@ DustMaterial :: giveIPValue(FloatArray &answer, InternalStateType type, TimeStep *tStep) { - const DustMaterialStatus *status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); + const auto status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); if ( type == IST_PlasticStrainTensor ) { answer = status->givePlasticStrain(); return 1; @@ -564,70 +521,69 @@ DustMaterial :: giveIPValue(FloatArray &answer, MaterialStatus * DustMaterial :: CreateStatus(GaussPoint *gp) const { - return new DustMaterialStatus( 1, StructuralMaterial :: giveDomain(), gp, this->giveQ0() ); + return new DustMaterialStatus(gp, this->giveQ0() ); } double -DustMaterial :: functionFe(double i1) +DustMaterial :: functionFe(double i1) const { return alpha - lambda *exp(beta *i1) - theta * i1; } double -DustMaterial :: functionFeDI1(double i1) +DustMaterial :: functionFeDI1(double i1) const { return -lambda *beta *exp(beta *i1) - theta; } double -DustMaterial :: functionFeDI1DI1(double i1) +DustMaterial :: functionFeDI1DI1(double i1) const { return -lambda *beta *beta *exp(beta *i1); } double -DustMaterial :: functionFc(double rho, double i1, double q) +DustMaterial :: functionFc(double rho, double i1, double q) const { return sqrt( rho * rho + 1 / rEll / rEll * ( q - i1 ) * ( q - i1 ) ); } double -DustMaterial :: yieldFunction1(double rho, double i1) +DustMaterial :: yieldFunction1(double rho, double i1) const { return rho - functionFe(i1); } double -DustMaterial :: yieldFunction2(double rho, double i1, double q) +DustMaterial :: yieldFunction2(double rho, double i1, double q) const { return functionFc(rho, i1, q) - functionFe(q); } double -DustMaterial :: yieldFunction3(double i1) +DustMaterial :: yieldFunction3(double i1) const { return i1 - ft; } double -DustMaterial :: functionX(double q) +DustMaterial :: functionX(double q) const { return q - rEll * ( alpha - lambda * exp(beta * q) - theta * q ); } double -DustMaterial :: functionXDQ(double q) +DustMaterial :: functionXDQ(double q) const { return 1 - rEll * ( -lambda * beta * exp(beta * q) - theta ); } void -DustMaterial :: solveQ0(double &answer) +DustMaterial :: solveQ0(double &answer) const { - double fx, dfx; for ( int i = 0; i < newtonIter; i++ ) { - fx = -x0 + answer - rEll * ( alpha - lambda * exp(beta * answer) - theta * answer ); - dfx = 1 - rEll * ( -beta * lambda * exp(beta * answer) - theta ); + double fx = -x0 + answer - rEll * ( alpha - lambda * exp(beta * answer) - theta * answer ); + double dfx = 1 - rEll * ( -beta * lambda * exp(beta * answer) - theta ); answer -= fx / dfx; if ( fabs(fx / dfx / answer) < newtonTol ) { if ( answer >= 0 ) { @@ -642,11 +598,11 @@ DustMaterial :: solveQ0(double &answer) } void -DustMaterial :: computeAndSetBulkAndShearModuli(double &bulkModulus, double &shearModulus, GaussPoint *gp) +DustMaterial :: computeAndSetBulkAndShearModuli(double &bulkModulus, double &shearModulus, GaussPoint *gp) const { - DustMaterialStatus *status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); - double ym = LEMaterial->giveYoungsModulus(); - double nu = LEMaterial->givePoissonsRatio(); + auto status = static_cast< DustMaterialStatus * >( giveStatus(gp) ); + double ym = LEMaterial.giveYoungsModulus(); + double nu = LEMaterial.givePoissonsRatio(); double volumetricPlasticStrain = status->giveVolumetricPlasticStrain(); if ( volumetricPlasticStrain < 0. ) { ym -= mStiff * volumetricPlasticStrain; @@ -659,44 +615,35 @@ DustMaterial :: computeAndSetBulkAndShearModuli(double &bulkModulus, double &she status->setYoungsModulus(ym); } -void -DustMaterial :: computePlastStrainDirM1(FloatArray &answer, const FloatArray &stressDeviator, double rho, double i1, double q) +FloatArrayF<6> +DustMaterial :: computePlastStrainDirM1(const FloatArrayF<6> &stressDeviator, double rho, double i1, double q) const { - answer.beScaled(1./rho, stressDeviator); - double temp = ( lambda * beta * exp(beta * i1) + theta ) * ( i1 - q ) / ( ft - q ); - answer.at(1) += temp; - answer.at(2) += temp; - answer.at(3) += temp; + + return computeDeviatoricVolumetricSum((1./rho) * stressDeviator, temp); } -void -DustMaterial :: computePlastStrainDirM2(FloatArray &answer, const FloatArray &stressDeviator, double rho, double i1, double q) +FloatArrayF<6> +DustMaterial :: computePlastStrainDirM2(const FloatArrayF<6> &stressDeviator, double rho, double i1, double q) const { double fc = functionFc(rho, i1, q); - answer.beScaled(1./fc, stressDeviator); - double temp = ( q - i1 ) / ( rEll * rEll * fc ); - answer.at(1) -= temp; - answer.at(2) -= temp; - answer.at(3) -= temp; + + return computeDeviatoricVolumetricSum((1./fc) * stressDeviator, -temp); } -void -DustMaterial :: computePlastStrainDirM3(FloatArray &answer, const FloatArray &stressDeviator, double rho, double i1, double q) +FloatArrayF<6> +DustMaterial :: computePlastStrainDirM3(const FloatArrayF<6> &stressDeviator, double rho, double i1, double q) const { double feft = functionFe(ft); - answer.beScaled(1./feft, stressDeviator); - double dfeft = functionFeDI1(ft); double temp = 1 - ( 1 + dfeft ) * rho / feft; - answer.at(1) += temp; - answer.at(2) += temp; - answer.at(3) += temp; + + return computeDeviatoricVolumetricSum((1./feft) * stressDeviator, temp); } double -DustMaterial :: functionH(double q, double tempQ) +DustMaterial :: functionH(double q, double tempQ) const { double xq = functionX(q); double xtq = functionX(tempQ); @@ -710,7 +657,7 @@ DustMaterial :: functionH(double q, double tempQ) } double -DustMaterial :: functionHDQ(double tempQ) +DustMaterial :: functionHDQ(double tempQ) const { double xtq = functionX(tempQ); double dxtq = functionXDQ(tempQ); @@ -724,26 +671,26 @@ DustMaterial :: functionHDQ(double tempQ) } double -DustMaterial :: functionI1(double q, double tempQ, double i1, double bulkModulus) +DustMaterial :: functionI1(double q, double tempQ, double i1, double bulkModulus) const { return i1 - 3 *bulkModulus *functionH(q, tempQ); } double -DustMaterial :: functionI1DQ(double tempQ, double bulkModulus) +DustMaterial :: functionI1DQ(double tempQ, double bulkModulus) const { return -3 *bulkModulus *functionHDQ(tempQ); } double -DustMaterial :: computeDeltaGamma2(double tempQ, double q, double i1, double bulkModulus) +DustMaterial :: computeDeltaGamma2(double tempQ, double q, double i1, double bulkModulus) const { double vfH = functionH(q, tempQ); return rEll *rEll *functionFe(tempQ) * vfH / ( 3 * ( i1 - 3 * bulkModulus * vfH - tempQ ) ); } double -DustMaterial :: computeDeltaGamma2DQ(double tempQ, double q, double i1, double bulkModulus) +DustMaterial :: computeDeltaGamma2DQ(double tempQ, double q, double i1, double bulkModulus) const { double vfH = functionH(q, tempQ); double vdfH = functionHDQ(tempQ); @@ -757,7 +704,7 @@ DustMaterial :: computeDeltaGamma2DQ(double tempQ, double q, double i1, double b } double -DustMaterial :: fTempR2(double tempQ, double q, double i1, double rho, double bulkModulus, double shearModulus) +DustMaterial :: fTempR2(double tempQ, double q, double i1, double rho, double bulkModulus, double shearModulus) const { double vfEq = functionFe(tempQ); double dgq = computeDeltaGamma2(tempQ, q, i1, bulkModulus); diff --git a/src/sm/Materials/dustmat.h b/src/sm/Materials/dustmat.h index 4595ebb29..06d4664db 100644 --- a/src/sm/Materials/dustmat.h +++ b/src/sm/Materials/dustmat.h @@ -37,9 +37,9 @@ #include "floatarray.h" #include "floatmatrix.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/Materials/structuralmaterial.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" ///@name Input fields for DustMaterial //@{ @@ -79,45 +79,42 @@ class DustMaterialStatus : public StructuralMaterialStatus protected: /// Plastic strain - FloatArray plasticStrain; - FloatArray tempPlasticStrain; + FloatArrayF<6> plasticStrain; + FloatArrayF<6> tempPlasticStrain; /// Hardening parameter q - double q; - double tempQ; + double q = 0; + double tempQ = 0; /// Current bulk modulus - double bulkModulus; + double bulkModulus = 0; /// Current shear modulus - double shearModulus; + double shearModulus = 0; /// Current Young's modulus - double youngsModulus; + double youngsModulus = 0; /// Indicates the state (i.e. elastic, yielding, unloading) of the Gauss point - int stateFlag; - int tempStateFlag; + int stateFlag = 0; + int tempStateFlag = 0; public: /// Constructor - DustMaterialStatus(int n, Domain * d, GaussPoint * gp, double q0); + DustMaterialStatus(GaussPoint * gp, double q0); - /// Destructor - virtual ~DustMaterialStatus(); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - - virtual const char *giveClassName() const { return "DustMaterialStatus"; } + const char *giveClassName() const override { return "DustMaterialStatus"; } /** * Get the full plastic strain vector from the material status. * @return Plastic strain. */ - const FloatArray &givePlasticStrain() const { return plasticStrain; } + const FloatArrayF<6> &givePlasticStrain() const { return plasticStrain; } /** * Get the full plastic strain vector from the material status. * @return Volumetric part of plastic strain. @@ -138,7 +135,7 @@ class DustMaterialStatus : public StructuralMaterialStatus * Get the temp value of the full plastic strain vector from the material status. * @return Temp value of plastic strain vector. */ - const FloatArray &giveTempPlasticStrain() const { return tempPlasticStrain; } + const FloatArrayF<6> &giveTempPlasticStrain() const { return tempPlasticStrain; } /** * Get the temp value of the hardening variable q from the material status. * @return Temp value of hardening variable kappaP. @@ -170,7 +167,7 @@ class DustMaterialStatus : public StructuralMaterialStatus * Assign the value of plastic strain. * @param v New value of plastic strain. */ - void letPlasticStrainBe(const FloatArray &v) { plasticStrain = v; } + void letPlasticStrainBe(const FloatArrayF<6> &v) { plasticStrain = v; } /** * Assign the value of variable q * @param v New value of variable q @@ -196,17 +193,17 @@ class DustMaterialStatus : public StructuralMaterialStatus * Get the value of actual bulk modulus of the status * @return Value of bulk modulus */ - double giveBulkModulus() { return bulkModulus; } + double giveBulkModulus() const { return bulkModulus; } /** * Get the value of actual shear modulus of the status * @return Value of shear modulus */ - double giveShearModulus() { return shearModulus; } + double giveShearModulus() const { return shearModulus; } /** * Get the value of actual Young's modulus of the status * @return Value of Young's modulus */ - double giveYoungsModulus() { return youngsModulus; } + double giveYoungsModulus() const { return youngsModulus; } }; /** @@ -234,55 +231,55 @@ class DustMaterial : public StructuralMaterial { protected: /// Pointer for linear elastic material - IsotropicLinearElasticMaterial *LEMaterial; + IsotropicLinearElasticMaterial LEMaterial; /// Parameter determining shape of yield surface - double alpha; + double alpha = 0.; /// Parameter determining shape of yield surface - double beta; + double beta = 0.; /// Parameter determining shape of yield surface - double lambda; + double lambda = 0.; /// Parameter determining shape of yield surface - double theta; + double theta = 0.; /// Parameter determining shape of yield surface (param T in original publication) - double ft; + double ft = 0.; /// Parameter determining shape of yield surface (param R in original publication) - double rEll; + double rEll = 0.; /// Parameter determining hardening type - int hardeningType; + int hardeningType = 0; /// Parameter increasing stiffness (parameter M in original publication) - double mStiff; + double mStiff = 0.; /// Parameter determining shape of yield surface (param X0 in original publication) - double x0; + double x0 = 0.; /// Parameter determining shape of yield surface - double q0; + double q0 = 0.; /// Parameter determining hardening law (parameter W in original publication) - double wHard; + double wHard = 0.; /// Parameter determining hardening law (parameter D in original publication) - double dHard; + double dHard = 0.; /// Tollerance for iterative methods - double newtonTol; + double newtonTol = 0.; /// Maximum number of iterations for iterative methods - int newtonIter; + int newtonIter = 0; /** * Auxiliary equation Fe (7.8) * @param i1 Trace of stress tensor * @return Fe */ - double functionFe(double i1); + double functionFe(double i1) const; /** * Derivative by i1 of auxiliary equation (7.8) * @param i1 Trace of stress tensor * @return @f$ \frac{\partial Fe}{\partial i_1 } @f$ */ - double functionFeDI1(double i1); + double functionFeDI1(double i1) const; /** * Second derivative by i1 of auxiliary equation (7.8) * @param i1 Trace of stress tensor * @return @f$ \frac{\partial^2 Fe}{\partial i1^2 } @f$ */ - double functionFeDI1DI1(double i1); + double functionFeDI1DI1(double i1) const; /** * Auxiliary equation Fc (7.9) * @param i1 Trace of stress tensor @@ -290,26 +287,26 @@ class DustMaterial : public StructuralMaterial * @param q Parameter q * @return Fc */ - double functionFc(double rho, double i1, double q); + double functionFc(double rho, double i1, double q) const; /** * Auxiliary equation X (7.11) * @param q Parameter q * @return X */ - double functionX(double q); + double functionX(double q) const; /** * Derivative by q of auxiliary equation X (7.11) * @param q Parameter q * @return @f$ \frac{\partial X }{\partial q} @f$ */ - double functionXDQ(double q); + double functionXDQ(double q) const; /** * Yield function 1 (shear dominant), equation 7.5 * @param rho Second Haigh-Westergaard coordinate * @param i1 Trace of stress tensor * @return Value */ - double yieldFunction1(double rho, double i1); + double yieldFunction1(double rho, double i1) const; /** * Yield function 2 (compression dominant), equation 7.6 * @param rho Second Haigh-Westergaard coordinate @@ -317,71 +314,71 @@ class DustMaterial : public StructuralMaterial * @param q Parameter q * @return value */ - double yieldFunction2(double rho, double i1, double q); + double yieldFunction2(double rho, double i1, double q) const; /** * Yield function 3 (tension dominant), equation 7.7 * @param i1 Trace of stress tensor * @return value */ - double yieldFunction3(double i1); + double yieldFunction3(double i1) const; /** * Solves q0 according to given parameters, equation 7.12 * @param answer Result */ - void solveQ0(double &answer); + void solveQ0(double &answer) const; /** * Computes and sets all elastic moduli, with possible stiffening. Equation 7.4 * @param bulkModulus Bulk modulus * @param shearModulus Shear modulus * @param gp Gauss point */ - void computeAndSetBulkAndShearModuli(double &bulkModulus, double &shearModulus, GaussPoint *gp); + void computeAndSetBulkAndShearModuli(double &bulkModulus, double &shearModulus, GaussPoint *gp) const; /** * Perform stress return and update all internal variables * @param gp Gauss point * @param strain Strain */ - void performStressReturn(GaussPoint *gp, const FloatArray &strain); + void performStressReturn(GaussPoint *gp, const FloatArrayF<6> &strain) const; /** * Computes direction of plastic yielding m1, equation 7.17 - * @param answer Result * @param stressDeviator Deviator of stress tensor * @param rho Second Haigh-Westergaard coordinate * @param i1 Trace of stress tensor * @param q Parameter q + * @param return Result */ - void computePlastStrainDirM1(FloatArray &answer, const FloatArray &stressDeviator, double rho, double i1, double q); + FloatArrayF<6> computePlastStrainDirM1(const FloatArrayF<6> &stressDeviator, double rho, double i1, double q) const; /** * Computes direction of plastic yielding m2, equation 7.19 - * @param answer Result * @param stressDeviator Deviator of stress tensor * @param rho Second Haigh-Westergaard coordinate * @param i1 Trace of stress tensor * @param q Parameter q + * @param return Result */ - void computePlastStrainDirM2(FloatArray &answer, const FloatArray &stressDeviator, double rho, double i1, double q); + FloatArrayF<6> computePlastStrainDirM2(const FloatArrayF<6> &stressDeviator, double rho, double i1, double q) const; /** * Computes direction of plastic yielding m2, equation 7.18 - * @param answer Result * @param stressDeviator Deviator of stress tensor * @param rho Second Haigh-Westergaard coordinate * @param i1 Trace of stress tensor * @param q Parameter q + * @param return Result */ - void computePlastStrainDirM3(FloatArray &answer, const FloatArray &stressDeviator, double rho, double i1, double q); + FloatArrayF<6> computePlastStrainDirM3(const FloatArrayF<6> &stressDeviator, double rho, double i1, double q) const; /** * Auxiliary equation H (7.33 or 7.34) * @param q Parameter q from previous step * @param tempQ Parameter tempQ * @return H */ - double functionH(double q, double tempQ); + double functionH(double q, double tempQ) const; /** * Derivative by tempQ of auxiliary equation H (7.33 or 7.34) * @param tempQ Parameter tempQ * @return @f$ \frac{\partial X}{\partial tempQ} @f$ */ - double functionHDQ(double tempQ); + double functionHDQ(double tempQ) const; /** * Auxiliary equation I1 (7.32) * @param q Parameter q from previous step @@ -390,35 +387,35 @@ class DustMaterial : public StructuralMaterial * @param bulkModulus Bulk modulus * @return I1 */ - double functionI1(double q, double tempQ, double i1, double bulkModulus); + double functionI1(double q, double tempQ, double i1, double bulkModulus) const; /** * Derivative by tempQ of auxiliary equation I1 (7.32) * @param tempQ Parameter tempQ * @param bulkModulus Bulk modulus * @return @f$ \frac{\partial I1}{\partial tempQ} @f$ */ - double functionI1DQ(double tempQ, double bulkModulus); + double functionI1DQ(double tempQ, double bulkModulus) const; /** * Performs stress return of case of yield function F1, computes new value of tempQ and sets it to status. Equation 7.31 * @param i1 Trace of stress tensor * @param rho Second Haigh-Westergaard coordinate * @param gp Gauss point */ - void performF1return(double i1, double rho, GaussPoint *gp); + void performF1return(double i1, double rho, GaussPoint *gp) const; /** * Performs stress return of case of yield function F2, computes new value of tempQ and sets it to status. Equation 7.38 * @param i1 Trace of stress tensor * @param rho Second Haigh-Westergaard coordinate * @param gp Gauss point */ - void performF2return(double i1, double rho, GaussPoint *gp); + void performF2return(double i1, double rho, GaussPoint *gp) const; /** * Computes tempQ from volumetric plastic strain increment, equation 7.44 * @param answer Result tempQ * @param q Parameter q from previous step * @param deltaVolumetricPlasticStrain Volumetric plastic strain increment */ - void computeQFromPlastVolEps(double &answer, double q, double deltaVolumetricPlasticStrain); + void computeQFromPlastVolEps(double &answer, double q, double deltaVolumetricPlasticStrain) const; /** * Computed value of plastic multiplier for F2 yield function, equation 7.39 * @param tempQ Parameter tempQ @@ -426,7 +423,7 @@ class DustMaterial : public StructuralMaterial * @param i1 Trace of stress tensor * @param bulkModulus Bulk modulus */ - double computeDeltaGamma2(double tempQ, double q, double i1, double bulkModulus); + double computeDeltaGamma2(double tempQ, double q, double i1, double bulkModulus) const; /** * Computed derivative by tempQ of equation 7.39 * @param tempQ Parameter tempQ @@ -434,7 +431,7 @@ class DustMaterial : public StructuralMaterial * @param i1 Trace of stress tensor * @param bulkModulus Bulk modulus */ - double computeDeltaGamma2DQ(double tempQ, double q, double i1, double bulkModulus); + double computeDeltaGamma2DQ(double tempQ, double q, double i1, double bulkModulus) const; /** * Equation 7.38 * @param tempQ Parameter tempQ @@ -444,41 +441,33 @@ class DustMaterial : public StructuralMaterial * @param bulkModulus Bulk modulus * @param shearModulus Shear modulus */ - double fTempR2(double tempQ, double q, double i1, double rho, double bulkModulus, double shearModulus); + double fTempR2(double tempQ, double q, double i1, double rho, double bulkModulus, double shearModulus) const; public: /// Constructor DustMaterial(int n, Domain * d); - /// Destructor - virtual ~DustMaterial(); - - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "DustMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_DustMaterial_Name; } + void initializeFrom(InputRecord &ir) override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &strainVector, TimeStep *tStep); + const char *giveClassName() const override { return "DustMaterial"; } + const char *giveInputRecordName() const override { return _IFT_DustMaterial_Name; } + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; - virtual int setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type); + int setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type) override; - virtual int giveIPValue(FloatArray &answer, - GaussPoint *gp, - InternalStateType type, - TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) + FloatArrayF<6> giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override { - LEMaterial->giveThermalDilatationVector(answer, gp, tStep); + return LEMaterial.giveThermalDilatationVector(gp, tStep); } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; double giveQ0() const { return q0; } }; diff --git a/src/sm/Materials/fcm.C b/src/sm/Materials/fcm.C index d7c163c06..dc9874b98 100644 --- a/src/sm/Materials/fcm.C +++ b/src/sm/Materials/fcm.C @@ -43,31 +43,19 @@ #include namespace oofem { -FCMMaterial :: FCMMaterial(int n, Domain *d) : StructuralMaterial(n, d) - // - // constructor - // -{ - ecsMethod = ECSM_Unknown; - linearElasticMaterial = NULL; -} - - -FCMMaterial :: ~FCMMaterial() -// -// destructor -// +FCMMaterial :: FCMMaterial(int n, Domain *d) : StructuralMaterial(n, d), + linearElasticMaterial(n, d), + ecsMethod(ECSM_Unknown) {} -int -FCMMaterial :: hasMaterialModeCapability(MaterialMode mode) -// -// returns whether receiver supports given mode -// + +bool +FCMMaterial :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _3dMat || mode == _PlaneStress || mode == _PlaneStrain; } + void FCMMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, @@ -80,18 +68,20 @@ FCMMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, { // g = global direction // l = local (crack) direction + // normal = normal components only (in direction of crack planes, "l") // stress and strain transformation matrices - FloatMatrix epsG2L, sigmaL2G; + FloatMatrix epsG2L, sigmaL2G, sigmaG2L; // stiffness matrices (total, elastic, cracking) - FloatMatrix D, De, Dcr; + FloatMatrix D, De, Dcr, DeRed; FloatMatrix principalDirs; // STRESSES - FloatArray stressIncrement_l, stressVector_g, trialStress_g, trialStress_l, sigmaResid, sigmaElast_l, sigmaCrack_l; - + FloatArray stressIncrement_l, stressVector_g, trialStress_g, trialStress_l, sigmaResid, sigmaElast_l, sigmaCrack_l, sigmaResid_old; + FloatArray stressVector_l; + // STRAINS - FloatArray reducedStrain_g, reducedStrain_l, strainIncrement_g, strainIncrement_l, crackStrain, crackStrainIncrement, elasticStrain_l; + FloatArray reducedStrain_g, strainIncrement_g, strainIncrement_l, crackStrain, crackStrainIncrement, elasticStrain_l, elasticStrainIncrement_l; // FloatArray reducedStrain_l FCMMaterialStatus *status = static_cast< FCMMaterialStatus * >( this->giveStatus(gp) ); MaterialMode mMode = gp->giveMaterialMode(); @@ -99,34 +89,83 @@ FCMMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, int nCr = status->giveNumberOfCracks(); int nMaxCr = status->giveMaxNumberOfCracks(gp); - double maxErr; - int iterLimit; - double maxTau; + double maxErr = 0.; + double maxTau = 0.; + + double G; + + double DII; + + double gamma_cr, d_gamma_cr; + double tau_el, tau_cr; + double d_tau; + double d_tau_old = 0.; + bool illinoisFlag = false; + + int iterLimitGlobal = 20; + int iterLimitGradient = 20; + int iterLimitNormal = 100; + int iterLimitShear = 100; + int indexLimit = 10; + + FloatArray tempNormalCrackStrain, normalCrackStrain; + // FloatArray normalStrainVector_l; + FloatArray normalStrainIncrement_l; + FloatArray normalStressVector_l; + FloatArray normalCrackStrainIncrement; + FloatArray normalElasticStrainIncrement_l; + FloatArray normalElasticStrain_l; + // for the bisection method: - int index, indexCount; - bool exitWhileCond = false; - bool cancelledStrainFlag = false; + int index, indexOld, indexCount; + + bool changeIndexFlag = false; bool plus, minus; FloatArray crackStrainPlus, crackStrainMinus, residPlus, residMinus; //local - index = indexCount = 0; + FloatArray helpRF; + + int iterN; + + plus = false; + minus = false; + + sigmaResid_old.resize(nMaxCr); + + index = indexOld = indexCount = 0; + this->initTempStatus(gp); + if ( !this->isActivated(tStep) ) { + FloatArray zeros; + zeros.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + zeros.zero(); + status->letTempStrainVectorBe(zeros); + status->letTempStressVectorBe(zeros); + answer = zeros; + return; + } + // get elastic stiffness matrix this->giveStiffnessMatrix(De, ElasticStiffness, gp, tStep); + // equilibrated global stress + stressVector_g = status->giveStressVector(); - // NOW INDEPENDENTLY OF THE HISTORY GET PRINCIPAL STRESSES / STRESSES IN THE CRACK DIRS + this->giveStressDependentPartOfStrainVector(reducedStrain_g, gp, totalStrain, tStep, VM_Incremental); + strainIncrement_g.beDifferenceOf( reducedStrain_g, status->giveStrainVector() ); + + trialStress_g.beProductOf(De, strainIncrement_g); + trialStress_g.add(stressVector_g); + // ELASTIC CASE - NO CRACKING SO FAR (in prevs steps) if ( nCr == 0 ) { - this->giveStressDependentPartOfStrainVector(reducedStrain_g, gp, totalStrain, tStep, VM_Total); - trialStress_g.beProductOf(De, reducedStrain_g); - this->computePrincipalValDir(trialStress_l, principalDirs, trialStress_g, principal_stress); + this->computePrincipalValDir(trialStress_l, principalDirs, trialStress_g, principal_stress); // REMAINS ELASTIC or element cracking is prevented from above if ( !this->isStrengthExceeded( principalDirs, gp, tStep, 1, trialStress_l.at(1) ) ) { @@ -137,11 +176,11 @@ FCMMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, // STARTS CRACKING - 1st crack } else { - this->initializeCrack(gp, principalDirs, 1); + this->initializeCrack(gp, tStep, principalDirs, 1); for ( int iCrack = 2; iCrack <= min(nMaxCr, this->nAllowedCracks); iCrack++ ) { if ( this->isStrengthExceeded( principalDirs, gp, tStep, iCrack, trialStress_l.at(iCrack) ) ) { // for "nonlocal model" - this->initializeCrack(gp, principalDirs, iCrack); + this->initializeCrack(gp, tStep, principalDirs, iCrack); } } } @@ -150,15 +189,6 @@ FCMMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, } else { // check other principal directions - if strength is not exceeded, take transformation matrices from previous analysi if ( nCr < nMaxCr ) { - // equilibrated global stress - stressVector_g = status->giveStressVector(); - // get strain increment - this->giveStressDependentPartOfStrainVector(reducedStrain_g, gp, totalStrain, tStep, VM_Incremental); - strainIncrement_g.beDifferenceOf( reducedStrain_g, status->giveStrainVector() ); - - // stress increment in crack direction - trialStress_g.beProductOf(De, strainIncrement_g); - trialStress_g.add(stressVector_g); principalDirs = status->giveCrackDirs(); @@ -170,428 +200,724 @@ FCMMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, if ( !this->checkStrengthCriterion(principalDirs, trialStress_g, gp, tStep, iCrack) ) { // = strength of composite // second and third crack is now initialized - this->initializeCrack(gp, principalDirs, iCrack); + this->initializeCrack(gp, tStep, principalDirs, iCrack); } } // end for } // end nMaxCr } // cracking in previous steps - sigmaL2G = status->giveL2GStressVectorTransformationMtrx(); + epsG2L = status->giveG2LStrainVectorTransformationMtrx(); + sigmaG2L = status->giveG2LStressVectorTransformationMtrx(); + sigmaL2G = status->giveL2GStressVectorTransformationMtrx(); // PREPARE STRAIN AND STRESS INCREMENT IN CRACK DIRECTIONS - if ( ( nCr == 0 ) || ( nCr == nMaxCr ) ) { // not to do the same job twice - // get strain increment - this->giveStressDependentPartOfStrainVector(reducedStrain_g, gp, totalStrain, tStep, VM_Incremental); - strainIncrement_g.beDifferenceOf( reducedStrain_g, status->giveStrainVector() ); - } - - // strain and strain increment in crack direction - strainIncrement_l = strainIncrement_g; - strainIncrement_l.rotatedWith(epsG2L, 'n'); // from global to local - - reducedStrain_l = reducedStrain_g; - reducedStrain_l.rotatedWith(epsG2L, 'n'); // from global to local - + strainIncrement_l.beProductOf(epsG2L, strainIncrement_g); // from global to local + // stress increment in crack direction stressIncrement_l.beProductOf(De, strainIncrement_l); + // (equilibrated) stress in crack direction + + stressVector_l.beProductOf(sigmaG2L, status->giveStressVector() ); + // SIMILARLY TO RCM2: THE STRESS INCREMENT IN ELASTIC // AND CRACKING UNIT MUST BE EQUAL - ITERATE + // average shear modulus + G = computeOverallElasticShearModulus(gp, tStep); + + DeRed = De; + DeRed.resizeWithData(nMaxCr,nMaxCr); + crackStrain = status->giveCrackStrainVector(); - - iterLimit = 20; - - for ( int iter = 1; iter <= iterLimit; iter++ ) { - this->giveLocalCrackedStiffnessMatrix(Dcr, TangentStiffness, gp, tStep); - - if ( iter == 1 ) { - // residuum - sigmaResid = stressIncrement_l; - } - - D = De; - D.add(Dcr); - - D.solveForRhs(sigmaResid, crackStrainIncrement); - - // update and store cracking strain - crackStrain.add(crackStrainIncrement); - - status->setTempCrackStrainVector(crackStrain); - - // update statuses - this->updateCrackStatus(gp); - - // compute and compare stress in elastic and cracking unit: - // EL - elasticStrain_l = reducedStrain_l; - elasticStrain_l.subtract(crackStrain); - sigmaElast_l.beProductOf(De, elasticStrain_l); - // CR - this->giveLocalCrackedStiffnessMatrix(Dcr, SecantStiffness, gp, tStep); - // sigmaCrack_l.beProductOf(Dr, crackStrain); // matrix is diagonal - sigmaCrack_l.resize( crackStrain.giveSize() ); - for ( int i = 1; i <= crackStrain.giveSize(); i++ ) { - sigmaCrack_l.at(i) = Dcr.at(i, i) * crackStrain.at(i); - - switch ( mMode ) { - case _PlaneStress: - - if ( i == 3 ) { - maxTau = this->maxShearStress(gp, 6); - - if ( sigmaCrack_l.at(i) > maxTau ) { - sigmaCrack_l.at(i) = maxTau; - } - } - break; - - case _3dMat: - - if ( i >= 4 ) { - maxTau = this->maxShearStress(gp, i); - - if ( sigmaCrack_l.at(i) > maxTau ) { - sigmaCrack_l.at(i) = maxTau; - } - } - break; - - case _PlaneStrain: // check - - if ( i == 4 ) { - maxTau = this->maxShearStress(gp, 6); - - if ( sigmaCrack_l.at(i) > maxTau ) { - sigmaCrack_l.at(i) = maxTau; - } - } - break; - - default: - OOFEM_ERROR( "Material mode %s not supported", __MaterialModeToString(mMode) ); - } - } - - // residuum - sigmaResid = sigmaElast_l; - sigmaResid.subtract(sigmaCrack_l); - - - maxErr = 0.; - for ( int i = 1; i <= sigmaResid.giveSize(); i++ ) { - if ( fabs( sigmaResid.at(i) ) > maxErr ) { - maxErr = fabs( sigmaResid.at(i) ); - } - } - - - if ( maxErr < fcm_TOLERANCE * this->giveTensileStrength(gp) ) { - break; - } - } - - - // modified iteration method - first gradient and then bisection method - - while ( maxErr > fcm_TOLERANCE * this->giveTensileStrength(gp) ) { - for ( int i = 1; i <= sigmaResid.giveSize(); i++ ) { - if ( fabs( sigmaResid.at(i) ) == maxErr ) { - // found the same index as before -> do not do the same job over, exit while - if ( index == i ) { - exitWhileCond = true; - break; - } else { - // the crack strain index is not the same as before - clear the following flag - cancelledStrainFlag = false; - } - - index = i; - - break; - } - } - - if ( exitWhileCond ) { - break; - } - - iterLimit = 100; - - plus = false; - minus = false; - - crackStrainPlus.zero(); - crackStrainMinus.zero(); - residPlus.zero(); - residMinus.zero(); - - indexCount++; - - if ( indexCount > 10 ) { - OOFEM_WARNING("Fixed crack model: Local equilibrium not reached!, max. stress error %f", maxErr); - break; - } - - - for ( int iter = 1; iter <= iterLimit; iter++ ) { - if ( iter == iterLimit ) { - OOFEM_WARNING("Fixed crack model: Local equilibrium not reached!, max. stress error %f", maxErr); - } - - - if ( ( iter == 1 ) && ( indexCount == 1 ) ) { - crackStrain.zero(); - crackStrain.add( status->giveCrackStrainVector() ); - status->setTempCrackStrainVector(crackStrain); - //sigmaResid.zero(); - sigmaResid = stressIncrement_l; - this->updateCrackStatus(gp); - } - - // DO THE FOLLOWING SECTION ONLY UNTIL "PLUS" AND "MINUS" CRACK STRAIN IS FOUND - - if ( ( !plus ) || ( !minus ) ) { - this->giveLocalCrackedStiffnessMatrix(Dcr, TangentStiffness, gp, tStep); - - D = De; - D.add(Dcr); - - D.solveForRhs(sigmaResid, crackStrainIncrement); - - // update and store cracking strain - crackStrain.add(crackStrainIncrement); - - status->setTempCrackStrainVector(crackStrain); - - // update statuses - this->updateCrackStatus(gp); - - // compute and compare stress in elastic and cracking unit: - // EL - elasticStrain_l = reducedStrain_l; - elasticStrain_l.subtract(crackStrain); - sigmaElast_l.beProductOf(De, elasticStrain_l); - // CR - this->giveLocalCrackedStiffnessMatrix(Dcr, SecantStiffness, gp, tStep); - // sigmaCrack_l.beProductOf(Dr, crackStrain); // matrix is diagonal - sigmaCrack_l.resize( crackStrain.giveSize() ); - for ( int i = 1; i <= crackStrain.giveSize(); i++ ) { - sigmaCrack_l.at(i) = Dcr.at(i, i) * crackStrain.at(i); - - switch ( mMode ) { - case _PlaneStress: - - if ( i == 3 ) { - maxTau = this->maxShearStress(gp, 6); - - if ( sigmaCrack_l.at(i) > maxTau ) { - sigmaCrack_l.at(i) = maxTau; - } - } - break; - - case _3dMat: - - if ( i >= 4 ) { - maxTau = this->maxShearStress(gp, i); - - if ( sigmaCrack_l.at(i) > maxTau ) { - sigmaCrack_l.at(i) = maxTau; - } - } - break; - - case _PlaneStrain: // check - - if ( i == 4 ) { - maxTau = this->maxShearStress(gp, 6); - - if ( sigmaCrack_l.at(i) > maxTau ) { - sigmaCrack_l.at(i) = maxTau; - } - } - break; - - default: - OOFEM_ERROR( "Material mode %s not supported", __MaterialModeToString(mMode) ); - } - } - - // residuum - sigmaResid = sigmaElast_l; - sigmaResid.subtract(sigmaCrack_l); - - if ( sigmaResid.at(index) > 0 ) { - if ( !plus ) { // first positive sigma resid - residPlus = sigmaResid; - } else { - if ( sigmaResid.at(index) < residPlus.at(index) ) { // smaller error - residPlus = sigmaResid; - } - } - - crackStrainPlus = crackStrain; - plus = true; - } else { // sigmaResid < 0 - if ( !minus ) { // first negative sigma resid - residMinus = sigmaResid; - } else { - if ( sigmaResid.at(index) > residMinus.at(index) ) { // smaller error - residMinus = sigmaResid; - } - } - - crackStrainMinus = crackStrain; - minus = true; - } - - - maxErr = 0.; - for ( int i = 1; i <= sigmaResid.giveSize(); i++ ) { - if ( fabs( sigmaResid.at(i) ) > maxErr ) { - maxErr = fabs( sigmaResid.at(i) ); - } - } - - - if ( fabs( sigmaResid.at(index) ) < fcm_TOLERANCE * this->giveTensileStrength(gp) ) { - break; - } - } else { // we have "plus" and "minus" cracking and the bisection method can start - crackStrain.zero(); - crackStrain.add(crackStrainMinus); - crackStrain.add(crackStrainPlus); - crackStrain.times(0.5); - - status->setTempCrackStrainVector(crackStrain); - // update statuses - to have correct stiffnesses (unlo-relo vs. softening) - this->updateCrackStatus(gp); - - - - // compute and compare stress in elastic and cracking unit: - // EL - elasticStrain_l = reducedStrain_l; - elasticStrain_l.subtract(crackStrain); - sigmaElast_l.beProductOf(De, elasticStrain_l); - // CR - this->giveLocalCrackedStiffnessMatrix(Dcr, SecantStiffness, gp, tStep); - // sigmaCrack_l.beProductOf(Dr, crackStrain); // matrix is diagonal - sigmaCrack_l.resize( crackStrain.giveSize() ); - for ( int i = 1; i <= crackStrain.giveSize(); i++ ) { - sigmaCrack_l.at(i) = Dcr.at(i, i) * crackStrain.at(i); - - switch ( mMode ) { - case _PlaneStress: - - if ( i == 3 ) { - maxTau = this->maxShearStress(gp, 6); - - if ( sigmaCrack_l.at(i) > maxTau ) { - sigmaCrack_l.at(i) = maxTau; - } - } - break; - - case _3dMat: - - if ( i >= 4 ) { - maxTau = this->maxShearStress(gp, i); - - if ( sigmaCrack_l.at(i) > maxTau ) { - sigmaCrack_l.at(i) = maxTau; - } - } - break; - - case _PlaneStrain: // check - - if ( i == 4 ) { - maxTau = this->maxShearStress(gp, 6); - - if ( sigmaCrack_l.at(i) > maxTau ) { - sigmaCrack_l.at(i) = maxTau; - } - } - break; - - default: - OOFEM_ERROR( "Material mode %s not supported", __MaterialModeToString(mMode) ); - } - } - - // residuum - sigmaResid = sigmaElast_l; - sigmaResid.subtract(sigmaCrack_l); - - - maxErr = 0.; - for ( int i = 1; i <= sigmaResid.giveSize(); i++ ) { - if ( fabs( sigmaResid.at(i) ) > maxErr ) { - maxErr = fabs( sigmaResid.at(i) ); - } - } - - // condition for the given stress component - if ( fabs( sigmaResid.at(index) ) < fcm_TOLERANCE * this->giveTensileStrength(gp) ) { - break; - } - - - if ( sigmaResid.at(index) > 0 ) { - if ( sigmaResid.at(index) < residPlus.at(index) ) { // smaller error - residPlus = sigmaResid; - } - - crackStrainPlus = crackStrain; - } else { // sigmaResid < 0 - if ( sigmaResid.at(index) > residMinus.at(index) ) { // smaller error - residMinus = sigmaResid; - } - - crackStrainMinus = crackStrain; - } - - - if ( fabs( crackStrainMinus.at(index) - crackStrainPlus.at(index) ) < 1.e-18 ) { - crackStrain.zero(); - crackStrain.add(crackStrainMinus); - crackStrain.add(crackStrainPlus); - crackStrain.times(0.5); - - // if ( fabs (crackStrain.at(index) < 1.e-18 ) ) { - crackStrain.at(index) = 0.; - cancelledStrainFlag = true; - // } - -#if DEBUG - if ( cancelledStrainFlag ) { - OOFEM_WARNING("Fixed crack model: cracking strain component %d set to zero", index); - } + + tempNormalCrackStrain = status->giveCrackStrainVector(); + tempNormalCrackStrain.resize(nMaxCr); + + normalCrackStrain = tempNormalCrackStrain; + + + normalStressVector_l = stressVector_l; + normalStressVector_l.resize(nMaxCr); + + normalStrainIncrement_l = strainIncrement_l; + normalStrainIncrement_l.resizeWithValues(nMaxCr); + + for ( int iterG = 1; iterG <= iterLimitGlobal; iterG++ ) { + + if ( iterG == 1 ) { + // residuum + sigmaResid = stressIncrement_l; + } + + for ( int indexCount = 1; indexCount <= indexLimit; indexCount++ ) { + + if (indexCount > 1 ) { + if ( !changeIndexFlag ) {// same index as before - do not even try to fix it + OOFEM_WARNING("FCM: maximum error on the same component, max. stress error %f, index %d, indexCount %d, element %d\n", maxErr, index, indexCount, gp->giveElement()->giveNumber() ); + + break; + } + } + + minus = plus = false; + illinoisFlag = false; + changeIndexFlag = false; + iterN = 0; + sigmaResid_old.zero(); + + + do { // find convergence in the crack directions + + iterN++; + + if ( (iterN == 1) && (indexCount == 1) ) { + // shrink the total residuum + sigmaResid.resizeWithValues(nMaxCr); + } + + this->giveNormalLocalCrackedStiffnessMatrix(Dcr, TangentStiffness, gp, tStep); + + D = DeRed; + D.add(Dcr); + + D.solveForRhs(sigmaResid, normalCrackStrainIncrement); + + // update and store cracking strain + tempNormalCrackStrain.add(normalCrackStrainIncrement); + status->setTempNormalCrackStrainVector(tempNormalCrackStrain); + + // update statuses + this->updateCrackStatus(gp); + + // compute and compare stress in elastic and cracking unit: + // CR + this->giveNormalLocalCrackedStiffnessMatrix(Dcr, SecantStiffness, gp, tStep); + + sigmaCrack_l.resize( nMaxCr ); + for ( int i = 1; i <= nMaxCr; i++ ) { + sigmaCrack_l.at(i) = Dcr.at(i, i) * tempNormalCrackStrain.at(i); + } + + // compute and compare stress in elastic and cracking unit: + // increment of elastic strain + // d_eps_el = d_eps - d_eps_cr + // d_eps_cr = eps_cr_n - eps_cr_n-1 + normalElasticStrainIncrement_l = normalStrainIncrement_l; + normalElasticStrainIncrement_l.subtract(tempNormalCrackStrain); + normalElasticStrainIncrement_l.add(normalCrackStrain); + + // d_sigma = Del * d_eps_el + sigmaElast_l.beProductOf(DeRed, normalElasticStrainIncrement_l); + + // sigma_n = sigma_n-1 + d_sigma + sigmaElast_l.add(normalStressVector_l); + + // residuum + sigmaResid = sigmaElast_l; + sigmaResid.subtract(sigmaCrack_l); + + maxErr = 0.; + indexOld = index; + + for ( int i = 1; i <= sigmaResid.giveSize(); i++ ) { + if ( fabs( sigmaResid.at(i) ) > maxErr ) { + maxErr = fabs( sigmaResid.at(i) ); + + // if (indexCount == 1) { + index = i; + // } + } + } + + + + if ( maxErr <= fcm_TOLERANCE * this->giveTensileStrength(gp, tStep) ) { + break; // convergence criteria satisfied + } + + // try only gradient method and do not slow down with the preparation for the bisection method + if ( indexCount == 1 ) { + + if (iterN < iterLimitGradient/2.) { + continue; + + } + } + // identify the biggest error only in the first run of the gradient method + //} else { + + if (index != indexOld) { + minus = plus = false; + // crackStrainPlus.resize(nMaxCr); + /*crackStrainPlus.zero(); + //crackStrainMinus.resize(nMaxCr); + crackStrainMinus.zero(); + // residPlus.resize(nMaxCr); + residPlus.zero(); + //residMinus.resize(nMaxCr); + residMinus.zero();*/ + } + + + + if ( sigmaResid.at(index) > 0 ) { + if ( !plus) { // first positive error + plus = true; + residPlus = sigmaResid; + crackStrainPlus = tempNormalCrackStrain; + } else if ( fabs(sigmaResid.at(index)) < fabs(residPlus.at(index)) ) { // smaller error + residPlus = sigmaResid; + crackStrainPlus = tempNormalCrackStrain; + } + + } else { + if ( !minus) { // first negative error + minus = true; + residMinus = sigmaResid; + crackStrainMinus = tempNormalCrackStrain; + } + + else if ( fabs(sigmaResid.at(index)) < fabs(residMinus.at(index)) ) { // smaller error + residMinus = sigmaResid; + crackStrainMinus = tempNormalCrackStrain; + } + } + + + // if ( (! plus) || (! minus) ) { + + if ( ( plus) && ( minus) ) { + if ( ( indexCount == 1 ) && ( iterN < iterLimitGradient ) ) { + continue; + } + + + + //( iterN < iterLimitGradient ) || (! plus) || (! minus) ) { + + } else { + continue; + } + + do { // perform bisection method + + // check if the cracking strain at index is negative and try to fix it + tempNormalCrackStrain.zero(); + + if( (crackStrainMinus.at(index) < 0.) || (crackStrainPlus.at(index) < 0.) ) { + tempNormalCrackStrain.add(crackStrainMinus); + tempNormalCrackStrain.add(crackStrainPlus); + tempNormalCrackStrain.times(0.5); + + } else { + // OOFEM_WARNING("Trying regula-falsi iterations\n"); + + // try regula-falsi + // eps_cr_new = (eps_cr_min * resid_plus - eps_cr_plus * resid_minus) / (resid_plus - resid_minus) + // https://en.wikipedia.org/wiki/False_position_method#The_Regula_Falsi_.28False_Position.29_Method + + if (illinoisFlag) { // same sign of the error (at least) twice in a row + + if ( sigmaResid.at(index) == residPlus.at(index) ) { // error is positive + + tempNormalCrackStrain.add(crackStrainMinus); + tempNormalCrackStrain.times(residPlus.at(index) ); + + helpRF = crackStrainPlus; + helpRF.times( 0.5 * residMinus.at(index) ); + + tempNormalCrackStrain.subtract(helpRF); + tempNormalCrackStrain.times( 1. / ( residPlus.at(index) - 0.5 * residMinus.at(index) ) ); + + } else { // error is negative + + tempNormalCrackStrain.add(crackStrainMinus); + tempNormalCrackStrain.times( 0.5 * residPlus.at(index) ); + + helpRF = crackStrainPlus; + helpRF.times( residMinus.at(index) ); + + tempNormalCrackStrain.subtract(helpRF); + tempNormalCrackStrain.times( 1. / ( 0.5 * residPlus.at(index) - residMinus.at(index) ) ); + + } + + } else { // different sign of the error (consecutive errors) + // perform standard regula-falsi + + tempNormalCrackStrain.add(crackStrainMinus); + tempNormalCrackStrain.times(residPlus.at(index) ); + + helpRF = crackStrainPlus; + helpRF.times(residMinus.at(index) ); + + tempNormalCrackStrain.subtract(helpRF); + tempNormalCrackStrain.times( 1. / ( residPlus.at(index) - residMinus.at(index) ) ); + } + } + + + // too small strain and the crack has not existed before + if ( ( fabs (crackStrainMinus.at(index) ) <= fcm_THRESHOLD_CRACK_STRAIN ) && + ( fabs (crackStrainPlus.at(index) ) <= fcm_THRESHOLD_CRACK_STRAIN ) && + ( status->giveCrackStatus(index) == 0 ) ) { + tempNormalCrackStrain.at(index) = 0.; + } + + // replace negative cracking strain by a zero strain + if (tempNormalCrackStrain.at(index) < 0.) { + tempNormalCrackStrain.at(index) = 0.; + } + + status->setTempNormalCrackStrainVector(tempNormalCrackStrain); + // update statuses - to have correct stiffnesses (unlo-relo vs. softening) + this->updateCrackStatus(gp); + + // compute and compare stress in elastic and cracking unit: + // CR + this->giveNormalLocalCrackedStiffnessMatrix(Dcr, SecantStiffness, gp, tStep); + sigmaCrack_l.resize( nMaxCr ); + for ( int i = 1; i <= nMaxCr; i++ ) { + sigmaCrack_l.at(i) = Dcr.at(i, i) * tempNormalCrackStrain.at(i); + } + + // increment of elastic strain + // d_eps_el = d_eps - d_eps_cr + // d_eps_cr = eps_cr_n - eps_cr_n-1 + normalElasticStrainIncrement_l = normalStrainIncrement_l; + normalElasticStrainIncrement_l.subtract(tempNormalCrackStrain); + normalElasticStrainIncrement_l.add(normalCrackStrain); + + // d_sigma = Del * d_eps_el + sigmaElast_l.beProductOf(DeRed, normalElasticStrainIncrement_l); + + // sigma_n = sigma_n-1 + d_sigma + sigmaElast_l.add(normalStressVector_l); + + // residuum + sigmaResid = sigmaElast_l; + sigmaResid.subtract(sigmaCrack_l); + + + /* if ( (status->giveTempCrackStatus(index) == 4) && (tempNormalCrackStrain.at(index) < fcm_SMALL_STRAIN) ) { + sigmaResid.at(index) = 0.; + }*/ + + + + // adjust residuum if the crack does not exist + /* if ( status->giveTempCrackStatus(index) == 0 ) { + sigmaResid.at(index) = 0.; + }*/ + + // condition for the given stress component + if ( fabs( sigmaResid.at(index) ) < fcm_TOLERANCE * this->giveTensileStrength(gp, tStep) ) { + changeIndexFlag = true; + break; + } + + + if ( (sigmaResid.at(index) >= 0.) && ( sigmaResid.at(index) < residPlus.at(index) ) ) { + residPlus = sigmaResid; + crackStrainPlus = tempNormalCrackStrain; + + } else if ( (sigmaResid.at(index) <= 0.) && ( fabs(sigmaResid.at(index)) < fabs(residMinus.at(index) ) ) ) { + + residMinus = sigmaResid; + crackStrainMinus = tempNormalCrackStrain; + + } else { // error is increasing -> change index + changeIndexFlag = true; + } + + + // cracking strain at index component is close to zero + if ( ( ( fabs( crackStrainMinus.at(index) - crackStrainPlus.at(index) ) < 1.e-16 ) && + ( max( fabs( crackStrainMinus.at(index) ), fabs( crackStrainPlus.at(index) ) ) < 1.e-14 ) ) || + ( status->giveTempCrackStatus(index) == pscm_NONE ) ) { + tempNormalCrackStrain.zero(); + tempNormalCrackStrain.add(crackStrainMinus); + tempNormalCrackStrain.add(crackStrainPlus); + tempNormalCrackStrain.times(0.5); + + tempNormalCrackStrain.at(index) = 0.; + +#if DEBUG + // OOFEM_WARNING("Fixed crack model: cracking strain component %d set to zero", index); +#endif + + + status->setTempNormalCrackStrainVector(tempNormalCrackStrain); + + // update statuses + this->updateCrackStatus(gp); + + // compute and compare stress in elastic and cracking unit: + for ( int i_count = 1; i_count <= 2; i_count++ ) { + + // EL + // increment of elastic strain + // d_eps_el = d_eps - d_eps_cr + // d_eps_cr = eps_cr_n - eps_cr_n-1 + normalElasticStrainIncrement_l = normalStrainIncrement_l; + normalElasticStrainIncrement_l.subtract(tempNormalCrackStrain); + normalElasticStrainIncrement_l.add(normalCrackStrain); + // d_sigma = Del * d_eps_el + sigmaElast_l.beProductOf(DeRed, normalElasticStrainIncrement_l); + + // eliminating stress error at index component + tempNormalCrackStrain.at(index) = sigmaElast_l.at(index) / this->giveCrackingModulus(SecantStiffness, gp, tStep, index); + status->setTempNormalCrackStrainVector(tempNormalCrackStrain); + + // update statuses + this->updateCrackStatus(gp); + } + + // stress in cracking unit + this->giveNormalLocalCrackedStiffnessMatrix(Dcr, SecantStiffness, gp, tStep); + sigmaCrack_l.resize( nMaxCr ); + for ( int i = 1; i <= nMaxCr; i++ ) { + sigmaCrack_l.at(i) = Dcr.at(i, i) * tempNormalCrackStrain.at(i); + } + + // reevaluate the residuum + sigmaResid = sigmaElast_l; + sigmaResid.subtract(sigmaCrack_l); + + } // end - crack strain is close to zero + + // evaluate maximum error + indexOld = index; + + maxErr = 0.; + for ( int i = 1; i <= sigmaResid.giveSize(); i++ ) { + if ( fabs( sigmaResid.at(i) ) > maxErr ) { + maxErr = fabs( sigmaResid.at(i) ); + index = i; + } + } + + // biggest error on different index + if (indexOld != index) { + changeIndexFlag = true; + illinoisFlag = false; + + } else { // evaluate + + if ( sgn(sigmaResid.at(index) ) == sgn(sigmaResid_old.at(index) ) ) { + illinoisFlag = true; + } else { + illinoisFlag = false; + } + + sigmaResid_old = sigmaResid; + + } + + + // end loop bisection method + } while ( (!changeIndexFlag) && (iterN <= iterLimitNormal) && ( fabs( sigmaResid.at(index) ) < fcm_TOLERANCE * this->giveTensileStrength(gp, tStep) ) ); + + + // end normal loop + } while ( ( !changeIndexFlag ) && ( maxErr > fcm_TOLERANCE * this->giveTensileStrength(gp, tStep) ) && (iterN <= iterLimitNormal) ); + + if ( maxErr <= fcm_TOLERANCE * this->giveTensileStrength(gp, tStep) ) { + break; // break index loop + } + + if ( indexCount >= indexLimit/2.) { + OOFEM_WARNING("FCM: slowly converging equilibrium in crack direction!, max. stress error %f, index %d, indexCount %d, element %d\n", maxErr, index, indexCount, gp->giveElement()->giveNumber() ); + } + + if ( indexCount >= indexLimit ) { + OOFEM_WARNING("FCM: slowly converging equilibrium in crack direction!, max. stress error %f, index %d, indexCount %d, element %d\n", maxErr, index, indexCount, gp->giveElement()->giveNumber() ); + break; + } + + + } // end index loop in normal direction + + // FIND EQUILIBRIUM FOR SHEAR + tau_cr = 0.; + DII = 0.; + + + double d_gamma_el; + + for ( int i = nMaxCr+1; i <= crackStrain.giveSize(); i++ ) { + + plus = false; + minus = false; + + crackStrainPlus.resize(1); + crackStrainPlus.zero(); + crackStrainMinus.resize(1); + crackStrainMinus.zero(); + residPlus.resize(1); + residPlus.zero(); + residMinus.resize(1); + residMinus.zero(); + + + d_tau = G * strainIncrement_l.at(i); + gamma_cr = status->giveCrackStrain(i); + + for ( int iterS = 1; iterS <= iterLimitShear; iterS++ ) { + + switch ( mMode ) { + case _PlaneStress: + + DII = computeTotalD2Modulus(gp, tStep, 6); + break; + + case _PlaneStrain: // check + DII = computeTotalD2Modulus(gp, tStep, 6); + break; + + case _3dMat: + DII = computeTotalD2Modulus(gp, tStep, i); + break; + + default: + OOFEM_ERROR( "Material mode %s not supported", __MaterialModeToString(mMode) ); + } + + + if ( ( !plus ) || ( !minus ) ) { + + if (iterS == 1) { + d_gamma_cr = ( stressVector_l.at(i) - DII * status->giveCrackStrain(i) + d_tau ) / ( G + DII ); + } else { + d_gamma_cr = ( d_tau ) / ( G + DII ); + } + + gamma_cr += d_gamma_cr; + } else { + // same sign of the cracking strain + if (sgn( crackStrainMinus.at(1) ) == sgn( crackStrainPlus.at(1) ) ) { + + if (illinoisFlag) { // same sign of the error (at least) twice in a row + + if (d_tau == residPlus.at(1) ) { // error is positive + gamma_cr = ( crackStrainMinus.at(1) * residPlus.at(1) - 0.5 * crackStrainPlus.at(1) * residMinus.at(1) ) / ( residPlus.at(1) - 0.5 * residMinus.at(1) ); + + } else { + gamma_cr = ( 0.5 * crackStrainMinus.at(1) * residPlus.at(1) - crackStrainPlus.at(1) * residMinus.at(1) ) / ( 0.5 * residPlus.at(1) - residMinus.at(1) ); + } + + // different sign of the error (consecutive errors) + } else { + gamma_cr = ( crackStrainMinus.at(1) * residPlus.at(1) - crackStrainPlus.at(1) * residMinus.at(1) ) / ( residPlus.at(1) - residMinus.at(1) ); + } + } else { // different sign of the cracking strain + gamma_cr = ( crackStrainMinus.at(1) + crackStrainPlus.at(1) ) / 2.; + } + } + + + status->setTempCrackStrain(i, gamma_cr); + this->updateCrackStatus(gp); + + switch ( mMode ) { + case _PlaneStress: + + maxTau = this->maxShearStress(gp, tStep, 6); + tau_cr = computeTotalD2Modulus(gp, tStep, 6) * gamma_cr; + break; + + case _PlaneStrain: // check + + maxTau = this->maxShearStress(gp, tStep, 6); + tau_cr = computeTotalD2Modulus(gp, tStep, 6) * gamma_cr; + break; + + case _3dMat: + + maxTau = this->maxShearStress(gp, tStep, i); + tau_cr = computeTotalD2Modulus(gp, tStep, i) * gamma_cr; + break; + + default: + OOFEM_ERROR( "Material mode %s not supported", __MaterialModeToString(mMode) ); + } + + if( fabs(tau_cr) > maxTau) { + + if ( ( !plus ) || ( !minus ) ) { + + // d_eps_el = (tau_max - tau_n-1)/G + d_gamma_el = ( sgn(tau_cr)* maxTau - stressVector_l.at(i) ) / G; + + // eps_cr_n = eps_cr_n-1 + d_eps - d_eps_el + gamma_cr = status->giveCrackStrain(i) + strainIncrement_l.at(i) - d_gamma_el; + + // maxTau can be dependent on the actual cracking strain + // (such as in the case of FRC) + + } else { + d_gamma_el = strainIncrement_l.at(i) - (gamma_cr - status->giveCrackStrain(i) ); + } + + status->setTempCrackStrain(i, gamma_cr); + this->updateCrackStatus(gp); + + // reevaluate TauMax + switch ( mMode ) { + case _PlaneStress: + + maxTau = this->maxShearStress(gp, tStep, 6); + break; + + case _PlaneStrain: // check + + maxTau = this->maxShearStress(gp, tStep, 6); + break; + + case _3dMat: + + maxTau = this->maxShearStress(gp, tStep, i); + break; + + default: + OOFEM_ERROR( "Material mode %s not supported", __MaterialModeToString(mMode) ); + } + + tau_el = stressVector_l.at(i) + d_gamma_el * G; + + tau_cr = min( maxTau, DII * fabs(gamma_cr) ); + tau_cr *= sgn(gamma_cr); + + } else { // tau is smaller than tau_max + + // old shear stress + tau_el = stressVector_l.at(i); + // shear stress increment + tau_el += G * ( strainIncrement_l.at(i) - gamma_cr + status->giveCrackStrain(i) ); + } + + // compute residuum = sig_el - sig_cr + d_tau = tau_el - tau_cr; + + if ( fabs( d_tau ) < fcm_TOLERANCE * this->giveTensileStrength(gp, tStep) ) { + break; + + } else { + + if (d_tau < 0.) { + minus = true; + + residMinus.at(1) = d_tau; + crackStrainMinus.at(1) = gamma_cr; + + } else { + plus = true; + + residPlus.at(1) = d_tau; + crackStrainPlus.at(1) = gamma_cr; + } + + // compare signs of the error + if (sgn(d_tau_old) == sgn(d_tau) ) { // same sign of the error as before + illinoisFlag = true; + + } else { + illinoisFlag = false; + } + + d_tau_old = d_tau; + + } + +#if DEBUG + if ( iterS > iterLimitShear*0.3) { + OOFEM_WARNING("Fixed crack model: Local equilibrium in shear not converging!, max. stress error %f, index %d, iter %d, element %d\n", fabs(d_tau), i, iterS, gp->giveElement()->giveNumber() ); + } #endif - break; - } - } // plus-minus condition - } // iter looop - } // maxErr exceeded - - - if ( ( maxErr >= fcm_TOLERANCE * this->giveTensileStrength(gp) ) && ( !cancelledStrainFlag ) ) { - OOFEM_WARNING("Fixed crack model: Local equilibrium not reached!, max. stress error %f", maxErr); - } - - // set the final-equilibrated crack strain and store the correct corresponding statuses - status->setTempCrackStrainVector(crackStrain); - // update statuses - to have correct stiffnesses - this->updateCrackStatus(gp); + + if ( iterS == iterLimitShear ) { + OOFEM_WARNING("Fixed crack model: Local equilibrium in shear direction(s) not reached!, max. stress error %f, element %d\n", fabs(d_tau), gp->giveElement()->giveNumber() ); + } + + } // i-th shear component equlibrium loop + + } // shear components loop + + // compute final stress residuum + crackStrain = status->giveTempCrackStrainVector(); + + // el + elasticStrainIncrement_l = strainIncrement_l; + elasticStrainIncrement_l.subtract(crackStrain); + elasticStrainIncrement_l.add(status->giveCrackStrainVector() ); + + sigmaElast_l.beProductOf(De, elasticStrainIncrement_l); + sigmaElast_l.add(stressVector_l); + + this->giveTotalLocalCrackedStiffnessMatrix(Dcr, SecantStiffness, gp, tStep); + + sigmaCrack_l.resize( crackStrain.giveSize() ); + + for ( int i = 1; i <= crackStrain.giveSize(); i++ ) { + sigmaCrack_l.at(i) = Dcr.at(i, i) * crackStrain.at(i); + + if (this->isThisShearComponent(gp, i) ) { + + switch ( mMode ) { + case _PlaneStress: + maxTau = this->maxShearStress(gp, tStep, 6); + break; + + case _PlaneStrain: + maxTau = this->maxShearStress(gp, tStep, 6); + break; + + case _3dMat: + maxTau = this->maxShearStress(gp, tStep, i); + break; + + default: + OOFEM_ERROR( "Material mode %s not supported", __MaterialModeToString(mMode) ); + } + + + if ( fabs( sigmaCrack_l.at(i) ) > maxTau ) { + sigmaCrack_l.at(i) = sgn(sigmaCrack_l.at(i)) * maxTau; + } + } + } + + // residuum + sigmaResid = sigmaElast_l; + sigmaResid.subtract(sigmaCrack_l); + + maxErr = 0.; + for ( int i = 1; i <= sigmaResid.giveSize(); i++ ) { + if ( fabs( sigmaResid.at(i) ) > maxErr ) { + maxErr = fabs( sigmaResid.at(i) ); + } + } + + if ( maxErr < fcm_TOLERANCE * this->giveTensileStrength(gp, tStep) ) { + break; + } + + if ( iterG == iterLimitGlobal ) { + OOFEM_WARNING("Fixed crack model: Local equilibrium not reached!, max. stress error %f, element %d\n", maxErr, gp->giveElement()->giveNumber() ); + } + + if ( iterG > iterLimitGlobal/3 ) { + OOFEM_WARNING("Slowly converning (normal vs. shear interaction)!, iter %d/ iter limit %d, max. stress error %f, element %d\n", iterG, iterLimitGlobal, maxErr, gp->giveElement()->giveNumber() ); + } + + } // global loop // correct non-zeros, statuses, etc... @@ -634,20 +960,17 @@ FCMMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, status->setTempCrackStrain(3, 0.); } - - // convert from local to global coordinates - sigmaElast_l.rotatedWith(sigmaL2G, 'n'); - - answer = sigmaElast_l; + // convert from local to global coordinates + answer.beProductOf(sigmaL2G, sigmaElast_l); status->letTempStrainVectorBe(totalStrain); - status->letTempStressVectorBe(sigmaElast_l); + status->letTempStressVectorBe(answer); return; } - + void -FCMMaterial :: initializeCrack(GaussPoint *gp, FloatMatrix &base, int nCrack) +FCMMaterial :: initializeCrack(GaussPoint *gp, TimeStep *tStep, FloatMatrix &base, int nCrack) { MaterialMode mMode = gp->giveMaterialMode(); FCMMaterialStatus *status = static_cast< FCMMaterialStatus * >( this->giveStatus(gp) ); @@ -667,7 +990,7 @@ FCMMaterial :: initializeCrack(GaussPoint *gp, FloatMatrix &base, int nCrack) Le = this->giveCharacteristicElementLength(gp, crackVector); status->setCharLength(nCrack, Le); - this->checkSnapBack(gp, nCrack); + this->checkSnapBack(gp, tStep, nCrack); status->setTempCrackStatus(nCrack, pscm_JUST_INIT); //status->setTempCrackStatus(nCrack, pscm_SOFTENING); @@ -694,17 +1017,17 @@ FCMMaterial :: initializeCrack(GaussPoint *gp, FloatMatrix &base, int nCrack) status->setCrackDirs(base); if ( mMode == _PlaneStress ) { - this->givePlaneStressVectorTranformationMtrx(sigmaG2L, base, 0); - this->give2DStrainVectorTranformationMtrx(epsG2L, base, 0); + sigmaG2L = this->givePlaneStressVectorTranformationMtrx(base, 0); + epsG2L = this->give2DStrainVectorTranformationMtrx(base, 0); - this->givePlaneStressVectorTranformationMtrx(sigmaL2G, base, 1); - this->give2DStrainVectorTranformationMtrx(epsL2G, base, 1); + sigmaL2G = this->givePlaneStressVectorTranformationMtrx(base, 1); + epsL2G = this->give2DStrainVectorTranformationMtrx(base, 1); } else { - this->giveStressVectorTranformationMtrx(sigmaG2L, base, 0); - this->giveStrainVectorTranformationMtrx(epsG2L, base, 0); + sigmaG2L = this->giveStressVectorTranformationMtrx(base, 0); + epsG2L = this->giveStrainVectorTranformationMtrx(base, 0); - this->giveStressVectorTranformationMtrx(sigmaL2G, base, 1); - this->giveStrainVectorTranformationMtrx(epsL2G, base, 1); + sigmaL2G = this->giveStressVectorTranformationMtrx(base, 1); + epsL2G = this->giveStrainVectorTranformationMtrx(base, 1); } status->setG2LStressVectorTransformationMtrx(sigmaG2L); @@ -724,16 +1047,16 @@ FCMMaterial :: isIntact(GaussPoint *gp, int icrack) { OOFEM_ERROR("Unexpected crack number"); } - if ( ( status->giveTempCrackStatus(icrack) != pscm_NONE ) && ( status->giveTempCrackStatus(icrack) != pscm_CLOSED ) ) { - return false; + if ( status->giveCrackStatus(icrack) != pscm_NONE ) { + return false; + } else if ( ( status->giveTempCrackStatus(icrack) != pscm_NONE ) && ( status->giveTempCrackStatus(icrack) != pscm_CLOSED ) ) { + return false; } else { - return true; + return true; } } - - bool FCMMaterial :: isIntactForShear(GaussPoint *gp, int i) { FCMMaterialStatus *status = static_cast< FCMMaterialStatus * >( this->giveStatus(gp) ); @@ -754,10 +1077,14 @@ FCMMaterial :: isIntactForShear(GaussPoint *gp, int i) { normal_1 = normal_2 = 0; } - if ( ( status->giveTempCrackStatus(normal_1) != pscm_NONE ) && ( status->giveTempCrackStatus(normal_1) != pscm_CLOSED ) ) { - return false; - } else if ( ( status->giveTempCrackStatus(normal_2) != pscm_NONE ) && ( status->giveTempCrackStatus(normal_2) != pscm_CLOSED ) ) { + // any crack had existed in previous steps - newly inserted condition + if ( (status->giveCrackStatus(normal_1) != pscm_NONE ) || (status->giveCrackStatus(normal_2) != pscm_NONE ) ) { return false; + + // } else if ( ( status->giveTempCrackStatus(normal_1) != pscm_NONE ) && ( status->giveTempCrackStatus(normal_1) != pscm_CLOSED ) ) { + // return false; + // } else if ( ( status->giveTempCrackStatus(normal_2) != pscm_NONE ) && ( status->giveTempCrackStatus(normal_2) != pscm_CLOSED ) ) { + // return false; } else { return true; } @@ -765,6 +1092,42 @@ FCMMaterial :: isIntactForShear(GaussPoint *gp, int i) { +bool +FCMMaterial :: isThisShearComponent(GaussPoint *gp, int component) { + + MaterialMode mMode = gp->giveMaterialMode(); + + switch ( mMode ) { + + case _PlaneStress: + if (component == 3) { + return true; + } + break; + + case _PlaneStrain: + if (component == 4) { + return true; + } + break; + + case _3dMat: + + if (component >=4 ) { + return true; + } + break; + + default: + OOFEM_ERROR("Unsupported material mode"); + } + + return false; +} + + + + double FCMMaterial :: computeNormalCrackOpening(GaussPoint *gp, int i) { FCMMaterialStatus *status = static_cast< FCMMaterialStatus * >( this->giveStatus(gp) ); @@ -785,7 +1148,7 @@ FCMMaterial :: computeNormalCrackOpening(GaussPoint *gp, int i) { double -FCMMaterial :: computeMaxNormalCrackOpening(GaussPoint *gp, int i) { +FCMMaterial :: computeMaxNormalCrackOpening(GaussPoint *gp, TimeStep *tStep, int i) { FCMMaterialStatus *status = static_cast< FCMMaterialStatus * >( this->giveStatus(gp) ); double crackOpening, N; @@ -804,7 +1167,7 @@ FCMMaterial :: computeMaxNormalCrackOpening(GaussPoint *gp, int i) { double -FCMMaterial :: computeShearSlipOnCrack(GaussPoint *gp, int icrack) { +FCMMaterial :: computeShearSlipOnCrack(GaussPoint *gp, TimeStep *tStep, int icrack) { MaterialMode mMode = gp->giveMaterialMode(); FCMMaterialStatus *status = static_cast< FCMMaterialStatus * >( this->giveStatus(gp) ); @@ -858,7 +1221,7 @@ FCMMaterial :: computeShearSlipOnCrack(GaussPoint *gp, int icrack) { // well this is quite unfortunate. The problem is that the shear slip should be redistributed according to the D2 moduli for the individual crack. In reality this is a big problem for the FRC-FCM problem beacuse it would have led to recursive calling (D2 modulus evaluates damage and damage is computed from shear slip etc. - factor_ij = this->computeShearStiffnessRedistributionFactor(gp, icrack, dir_j); + factor_ij = this->computeShearStiffnessRedistributionFactor(gp, tStep, icrack, dir_j); } slip = factor_ij * fabs(gamma_cr_ij) * status->giveCharLength(icrack) / nCracks; @@ -890,11 +1253,11 @@ FCMMaterial :: computeShearSlipOnCrack(GaussPoint *gp, int icrack) { if ( ( status->giveTempCrackStatus(dir_j) != pscm_NONE ) || ( status->giveTempCrackStatus(dir_k) != pscm_NONE ) ) { if ( status->giveTempCrackStatus(dir_j) != pscm_NONE ) { - factor_ij = this->computeShearStiffnessRedistributionFactor(gp, icrack, dir_j); + factor_ij = this->computeShearStiffnessRedistributionFactor(gp, tStep, icrack, dir_j); } if ( status->giveTempCrackStatus(dir_k) != pscm_NONE ) { - factor_ik = this->computeShearStiffnessRedistributionFactor(gp, icrack, dir_k); + factor_ik = this->computeShearStiffnessRedistributionFactor(gp, tStep, icrack, dir_k); } } @@ -912,7 +1275,7 @@ FCMMaterial :: computeShearSlipOnCrack(GaussPoint *gp, int icrack) { bool FCMMaterial :: isStrengthExceeded(const FloatMatrix &base, GaussPoint *gp, TimeStep *tStep, int iCrack, double trialStress) { - if ( trialStress > this->giveTensileStrength(gp) ) { + if ( trialStress > this->giveTensileStrength(gp, tStep) ) { return true; } else { return false; @@ -923,12 +1286,12 @@ FCMMaterial :: isStrengthExceeded(const FloatMatrix &base, GaussPoint *gp, TimeS double -FCMMaterial :: computeShearStiffnessRedistributionFactor(GaussPoint *gp, int ithCrackPlane, int jthCrackDirection) { +FCMMaterial :: computeShearStiffnessRedistributionFactor(GaussPoint *gp, TimeStep *tStep, int ithCrackPlane, int jthCrackDirection) { double factor_ij; double D2_i, D2_j; - D2_i = this->computeD2ModulusForCrack(gp, ithCrackPlane); - D2_j = this->computeD2ModulusForCrack(gp, jthCrackDirection); + D2_i = this->computeD2ModulusForCrack(gp, tStep, ithCrackPlane); + D2_j = this->computeD2ModulusForCrack(gp, tStep, jthCrackDirection); factor_ij = D2_j / ( D2_i + D2_j ); @@ -946,10 +1309,10 @@ FCMMaterial :: checkStrengthCriterion(FloatMatrix &newBase, const FloatArray &gl sigmaG2L = status->giveG2LStressVectorTransformationMtrx(); - trialStress = globalStress; - // rotate stress to local coordinates - trialStress.rotatedWith(sigmaG2L, 'n'); + // trialStress = globalStress; + // trialStress.rotatedWith(sigmaG2L, 'n'); + trialStress.beProductOf(sigmaG2L, globalStress); if ( status->giveMaxNumberOfCracks(gp) < 3 ) { // plane stress // test material strength but keep crack coordinates @@ -1184,21 +1547,34 @@ FCMMaterial :: updateCrackStatus(GaussPoint *gp) // closed previously } else if ( crackStrain.at(i) <= 0. ) { + + if (status->giveCrackStatus(i) != pscm_NONE ) { status->setTempCrackStatus(i, pscm_CLOSED); + } else { + status->setTempCrackStatus(i, pscm_NONE); + status->setTempMaxCrackStrain(i, 0.); + } - if ( status->giveMaxCrackStrain(i) == 0. ) { //not existing crack in previous step that wants to close? - status->setTempMaxCrackStrain(i, 0.); + + // if ( status->giveMaxCrackStrain(i) == 0. ) { //not existing crack in previous step that wants to close? + + + + // status->setTempMaxCrackStrain(i, 0.); + + // status->setTempCrackStatus(i, pscm_NONE); + // status->setTempCrackStatus(i, pscm_NONE); // CLOSED status should have similar behavior and it is safer. The status can be changed within one iteration loop on the local scale // the crack can be changed from CLOSED to NONE during overall updating // status->setTempCrackStatus(i, pscm_CLOSED); - } + //} // unloading--reloading } else if ( crackStrain.at(i) < maxCrackStrain.at(i) ) { status->setTempCrackStatus(i, pscm_UNLO_RELO); } else { - OOFEM_ERROR("Unexpected value of cracking strain"); + OOFEM_ERROR("Unexpected value of %d-th cracking strain %f ", i, crackStrain.at(i) ); } } } @@ -1216,7 +1592,7 @@ FCMMaterial :: updateCrackStatus(GaussPoint *gp) void -FCMMaterial :: giveLocalCrackedStiffnessMatrix(FloatMatrix &answer, +FCMMaterial :: giveTotalLocalCrackedStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { @@ -1233,9 +1609,9 @@ FCMMaterial :: giveLocalCrackedStiffnessMatrix(FloatMatrix &answer, j = indx.at(i); if ( j <= 3 ) { - Dcr.at(i, i) = this->giveCrackingModulus(rMode, gp, j); + Dcr.at(i, i) = this->giveCrackingModulus(rMode, gp, tStep, j); } else { - Dcr.at(i, i) = this->computeTotalD2Modulus(gp, j); + Dcr.at(i, i) = this->computeTotalD2Modulus(gp, tStep, j); } } @@ -1243,6 +1619,25 @@ FCMMaterial :: giveLocalCrackedStiffnessMatrix(FloatMatrix &answer, } + +void +FCMMaterial :: giveNormalLocalCrackedStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, GaussPoint *gp, + TimeStep *tStep) +{ + + FloatMatrix Dcr; + FCMMaterialStatus *status = static_cast< FCMMaterialStatus * >( this->giveStatus(gp) ); + int nMaxCr = status->giveMaxNumberOfCracks(gp); + + Dcr.resize(nMaxCr, nMaxCr); + + for ( int i = 1; i <= nMaxCr; i++ ) { + Dcr.at(i, i) = this->giveCrackingModulus(rMode, gp, tStep, i); + } + + answer = Dcr; +} @@ -1257,85 +1652,170 @@ FCMMaterial :: giveMaterialStiffnessMatrix(FloatMatrix &answer, // { FCMMaterialStatus *status = static_cast< FCMMaterialStatus * >( this->giveStatus(gp) ); - StructuralMaterial *lMat = static_cast< StructuralMaterial * >( this->giveLinearElasticMaterial() ); + // StructuralMaterial *lMat = static_cast< StructuralMaterial * >( this->giveLinearElasticMaterial() ); MaterialMode mMode = gp->giveMaterialMode(); int numberOfActiveCracks, nMaxCracks; double overallElasticStiffness; + double G = this->computeOverallElasticShearModulus(gp, tStep); + + FloatMatrix D, De, C, stiffnessL2G; - FloatMatrix D, De, DeHelp, Dcr, DcrHelp, DcrHelp2, inv, stiffnessL2G; + FloatMatrix DeHelp, Dcr, DcrHelp, DcrHelp2; numberOfActiveCracks = status->giveNumberOfTempCracks(); // ELASTIC MATRIX - if ( ( rMode == ElasticStiffness ) || ( numberOfActiveCracks == 0 ) ) { - lMat->giveStiffnessMatrix(D, rMode, gp, tStep); - - overallElasticStiffness = this->computeOverallElasticStiffness(); - if ( overallElasticStiffness != ( this->give('E', gp) ) ) { - D.times( overallElasticStiffness / ( this->give('E', gp) ) ); - } + linearElasticMaterial.giveStiffnessMatrix(De, rMode, gp, tStep); + // lMat->giveStiffnessMatrix(De, rMode, gp, tStep); + + overallElasticStiffness = this->computeOverallElasticStiffness(gp, tStep); + if ( overallElasticStiffness != ( this->give('E', gp) ) ) { + De.times( overallElasticStiffness / ( this->give('E', gp) ) ); + } - answer = D; + if ( ( rMode == ElasticStiffness ) || ( numberOfActiveCracks == 0 ) ) { + answer = De; return; } // SECANT OR TANGENT MATRIX - first in local direction nMaxCracks = status->giveMaxNumberOfCracks(gp); - lMat->giveStiffnessMatrix(De, rMode, gp, tStep); - - overallElasticStiffness = this->computeOverallElasticStiffness(); - if ( overallElasticStiffness != ( this->give('E', gp) ) ) { - De.times( overallElasticStiffness / ( this->give('E', gp) ) ); + De.resizeWithData(nMaxCracks,nMaxCracks); + + + double E_crack; + + if ( rMode == SecantStiffness ) { + + C.beInverseOf(De); + + for ( int i = 1; i <= numberOfActiveCracks; i++ ) { + + E_crack = this->giveCrackingModulus(rMode, gp, tStep, i); + + C.at(i, i) += 1. / E_crack; + + } + + + D.beInverseOf(C); + + } else if ( rMode == TangentStiffness ) { + + // if ( ( rMode == SecantStiffness ) || ( rMode == TangentStiffness ) ) { + + // shrink to square matrix number of cracks x number of cracks + DeHelp = De; + DeHelp.resizeWithData(numberOfActiveCracks, numberOfActiveCracks); + + Dcr.resize(numberOfActiveCracks, numberOfActiveCracks); + Dcr.zero(); + + for ( int i = 1; i <= numberOfActiveCracks; i++ ) { + if ( status->giveTempCrackStrain(i) > fcm_THRESHOLD_CRACK_STRAIN ) { + Dcr.at(i, i) = this->giveCrackingModulus(rMode, gp, tStep, i); + } else { + Dcr.at(i, i) = fcm_BIGNUMBER * overallElasticStiffness; + } + } + + Dcr.add(DeHelp); + C.beInverseOf(Dcr); + C.resizeWithData(nMaxCracks, nMaxCracks); + + DcrHelp.beProductOf(De, C); // De (De + Dcr)^-1 + DcrHelp2.beProductOf(DcrHelp, De); // De (De + Dcr)^-1 De + + D.zero(); + D.resize(nMaxCracks, nMaxCracks); + D.add(De); + D.subtract(DcrHelp2); // De - De (De + Dcr)^-1 De } - // extract 1x1 / 2x2 / 3x3 submatrix - De.resizeWithData(nMaxCracks, nMaxCracks); - - // shrink to square matrix number of cracks x number of cracks - DeHelp = De; - DeHelp.resizeWithData(numberOfActiveCracks, numberOfActiveCracks); - Dcr.resize(numberOfActiveCracks, numberOfActiveCracks); - Dcr.zero(); - - for ( int i = 1; i <= numberOfActiveCracks; i++ ) { - Dcr.at(i, i) = this->giveCrackingModulus(rMode, gp, i); + if ( this->normalCoeffNumer > 0. ) { + // apply minimum stiffness + double nu = this->givePoissonsRatio(); + + for ( int i = 1; i <= nMaxCracks; i++ ) { + for ( int j = 1; j <= nMaxCracks; j++ ) { + if (i == j) { // diagonal terms + D.at(i, j) = max( D.at(i,j), this->normalCoeffNumer * overallElasticStiffness ); + } else { + D.at(i, j) = max( D.at(i,j), this->normalCoeffNumer * overallElasticStiffness * nu/(1-nu) ); + } + } + } } - Dcr.add(DeHelp); - inv.beInverseOf(Dcr); - inv.resizeWithData(nMaxCracks, nMaxCracks); - - - DcrHelp.beProductOf(De, inv); // De (De + Dcr)^-1 - DcrHelp2.beProductOf(DcrHelp, De); // De (De + Dcr)^-1 De - D.zero(); - D.resize(nMaxCracks, nMaxCracks); - D.add(De); - D.subtract(DcrHelp2); // De - De (De + Dcr)^-1 De + // resize add shear moduli on diagonal switch ( mMode ) { case _PlaneStress: D.resizeWithData(3, 3); - D.at(3, 3) = this->computeEffectiveShearModulus(gp, 6); + + if ( max( status->giveCrackStrain(1), status->giveCrackStrain(2) ) > fcm_THRESHOLD_CRACK_STRAIN ) { + D.at(3, 3) = this->computeEffectiveShearModulus(gp, tStep, 6); + D.at(3, 3) = max( D.at(3,3), this->shearCoeffNumer * G ); + } else { + D.at(3, 3) = G; + } + + // debug: + /*double help; + help = this->shearCoeffNumer * G; + if (help > D.at(3, 3) ) { + D.at(3, 3) = help; + }*/ break; case _3dMat: D.resizeWithData(6, 6); for ( int i = 4; i <= 6; i++ ) { - D.at(i, i) = this->computeEffectiveShearModulus(gp, i); - } + if (i == 4) { + if ( max( status->giveCrackStrain(2), status->giveCrackStrain(3) ) > fcm_THRESHOLD_CRACK_STRAIN ) { + D.at(i, i) = this->computeEffectiveShearModulus(gp, tStep, i); + D.at(i, i) = max( D.at(i,i), this->shearCoeffNumer * G ); + } else { + D.at(i, i) = G; + } + + } else if ( i == 5 ) { + if ( max( status->giveCrackStrain(1), status->giveCrackStrain(3) ) > fcm_THRESHOLD_CRACK_STRAIN ) { + D.at(i, i) = this->computeEffectiveShearModulus(gp, tStep, i); + D.at(i, i) = max( D.at(i,i), this->shearCoeffNumer * G ); + } else { + D.at(i, i) = G; + } + + } else { // i == 6 + if ( max( status->giveCrackStrain(1), status->giveCrackStrain(2) ) > fcm_THRESHOLD_CRACK_STRAIN ) { + D.at(i, i) = this->computeEffectiveShearModulus(gp, tStep, i); + D.at(i, i) = max( D.at(i,i), this->shearCoeffNumer * G ); + } else { + D.at(i, i) = G; + } + } + } // end for + break; case _PlaneStrain: D.resizeWithData(6, 6); - D.at(6, 6) = this->computeEffectiveShearModulus(gp, 6); + + if ( max( status->giveCrackStrain(1), status->giveCrackStrain(2) ) > fcm_THRESHOLD_CRACK_STRAIN ) { + D.at(6, 6) = this->computeEffectiveShearModulus(gp, tStep, 6); + D.at(6, 6) = max( D.at(6,6), this->shearCoeffNumer * G ); + } else { + D.at(6, 6) = G; + } + break; default: @@ -1375,14 +1855,14 @@ FCMMaterial :: giveMaterialStiffnessMatrix(FloatMatrix &answer, double -FCMMaterial :: computeTotalD2Modulus(GaussPoint *gp, int shearDirection) +FCMMaterial :: computeTotalD2Modulus(GaussPoint *gp, TimeStep *tStep, int shearDirection) { double D2 = 0.; int crackA, crackB; double D2_1, D2_2; if ( this->isIntactForShear(gp, shearDirection) ) { - D2 = this->computeOverallElasticStiffness() * fcm_BIGNUMBER; + D2 = this->computeOverallElasticStiffness(gp, tStep) * fcm_BIGNUMBER; } else { if ( shearDirection == 4 ) { crackA = 2; @@ -1400,13 +1880,13 @@ FCMMaterial :: computeTotalD2Modulus(GaussPoint *gp, int shearDirection) if ( ( this->isIntact(gp, crackA) ) || ( this->isIntact(gp, crackB) ) ) { if ( this->isIntact(gp, crackA) ) { - D2 = this->computeD2ModulusForCrack(gp, crackB); + D2 = this->computeD2ModulusForCrack(gp, tStep, crackB); } else { - D2 = this->computeD2ModulusForCrack(gp, crackA); + D2 = this->computeD2ModulusForCrack(gp, tStep, crackA); } } else { - D2_1 = this->computeD2ModulusForCrack(gp, crackA); - D2_2 = this->computeD2ModulusForCrack(gp, crackB); + D2_1 = this->computeD2ModulusForCrack(gp, tStep, crackA); + D2_2 = this->computeD2ModulusForCrack(gp, tStep, crackB); if ( multipleCrackShear ) { // serial coupling of stiffnesses 1/D = 1/D1 + 1/D2 @@ -1415,32 +1895,102 @@ FCMMaterial :: computeTotalD2Modulus(GaussPoint *gp, int shearDirection) D2 = min(D2_1, D2_2); } } + + // adjust stiffness according to the maximum allowable stress + /*FCMMaterialStatus *status = static_cast< FCMMaterialStatus * >( this->giveStatus(gp) ); + MaterialMode mMode = gp->giveMaterialMode(); + double D2_help, gamma_max; + switch ( mMode ) { + case _PlaneStress: + + gamma_max = status->giveMaxCrackStrain(3); + break; + + case _PlaneStrain: // check + gamma_max = status->giveMaxCrackStrain(3); + break; + + case _3dMat: + gamma_max = status->giveMaxCrackStrain(shearDirection); + break; + + default: + OOFEM_ERROR( "Material mode %s not supported", __MaterialModeToString(mMode) ); + } + D2_help = this->maxShearStress(gp, tStep, shearDirection) / gamma_max; + D2 = min(D2, D2_help); + */ } return D2; } -IRResultType -FCMMaterial :: initializeFrom(InputRecord *ir) + +double +FCMMaterial :: computeNumerD2Modulus(GaussPoint *gp, TimeStep *tStep, int shearDirection) { - IRResultType result; // Required by IR_GIVE_FIELD macro + double D2 = 0.; + int crackA, crackB; + double D2_1, D2_2; - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; + if ( this->isIntactForShear(gp, shearDirection) ) { + D2 = this->computeOverallElasticStiffness(gp, tStep) * fcm_BIGNUMBER; + } else { + if ( shearDirection == 4 ) { + crackA = 2; + crackB = 3; + } else if ( shearDirection == 5 ) { + crackA = 1; + crackB = 3; + } else if ( shearDirection == 6 ) { + crackA = 1; + crackB = 2; + } else { + OOFEM_ERROR("Unexpected value of index i (4, 5, 6 permitted only)"); + crackA = crackB = 0; + } + + if ( ( this->isIntact(gp, crackA) ) || ( this->isIntact(gp, crackB) ) ) { + if ( this->isIntact(gp, crackA) ) { + D2 = this->computeNumerD2ModulusForCrack(gp, tStep, crackB); + } else { + D2 = this->computeNumerD2ModulusForCrack(gp, tStep, crackA); + } + } else { + D2_1 = this->computeNumerD2ModulusForCrack(gp, tStep, crackA); + D2_2 = this->computeNumerD2ModulusForCrack(gp, tStep, crackB); + + if ( multipleCrackShear ) { + // serial coupling of stiffnesses 1/D = 1/D1 + 1/D2 + D2 = D2_1 * D2_2 / ( D2_1 + D2_2 ); + } else { + D2 = min(D2_1, D2_2); + } + } } + return D2; +} + + + +void +FCMMaterial :: initializeFrom(InputRecord &ir) +{ + StructuralMaterial :: initializeFrom(ir); + linearElasticMaterial.initializeFrom(ir); + this->nAllowedCracks = 3; IR_GIVE_OPTIONAL_FIELD(ir, nAllowedCracks, _IFT_FCM_nAllowedCracks); this->crackSpacing = -1.; - if ( ir->hasField(_IFT_FCM_crackSpacing) ) { + if ( ir.hasField(_IFT_FCM_crackSpacing) ) { IR_GIVE_FIELD(ir, crackSpacing, _IFT_FCM_crackSpacing); } this->multipleCrackShear = false; - if ( ir->hasField(_IFT_FCM_multipleCrackShear) ) { + if ( ir.hasField(_IFT_FCM_multipleCrackShear) ) { this->multipleCrackShear = true; } @@ -1458,15 +2008,17 @@ FCMMaterial :: initializeFrom(InputRecord *ir) default: ecsMethod = ECSM_Projection; } - - return IRRT_OK; + this->shearCoeffNumer = -1.; + IR_GIVE_OPTIONAL_FIELD(ir, shearCoeffNumer, _IFT_FCM_shearCoeffNumer); + this->normalCoeffNumer = -1. * fcm_BIGNUMBER; + IR_GIVE_OPTIONAL_FIELD(ir, normalCoeffNumer, _IFT_FCM_normalCoeffNumer); } double -FCMMaterial :: give(int aProperty, GaussPoint *gp) +FCMMaterial :: give(int aProperty, GaussPoint *gp) const { - return linearElasticMaterial->give(aProperty, gp); + return linearElasticMaterial.give(aProperty, gp); } @@ -1665,62 +2217,91 @@ FCMMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType } return 1; + } else if ( type == IST_CrackStatuses ) { - const IntArray &crackStatus = status->giveCrackStatus(); answer.resize(3); - for ( int i = 1; i <= 3; i++ ) { - answer.at(i) = crackStatus.at(i); + answer.zero(); + for ( int i = 1; i <= status->giveNumberOfCracks(); i++ ) { + answer.at(i) = status->giveCrackStatus(i); } + return 1; + } else if ( type == IST_CrackStatusesTemp ) { + answer.resize(3); + answer.zero(); + for ( int i = 1; i <= status->giveNumberOfTempCracks(); i++ ) { + answer.at(i) = status->giveTempCrackStatus(i); + } return 1; + } else if ( type == IST_CrackStrainTensor ) { - FloatArray crackStrain = status->giveCrackStrainVector(); + // FloatArray crackStrain = status->giveCrackStrainVector(); + FloatArray crackStrain; FloatMatrix epsL2G = status->giveL2GStrainVectorTransformationMtrx(); // from local to global - crackStrain.rotatedWith(epsL2G, 'n'); + // crackStrain.rotatedWith(epsL2G, 'n'); + crackStrain.beProductOf(epsL2G, status->giveCrackStrainVector() ); StructuralMaterial :: giveFullSymVectorForm( answer, crackStrain, gp->giveMaterialMode() ); return 1; + + } else if ( type == IST_CrackSlip ) { + answer.resize(1); + answer.zero(); + + /* if ( ( mMode == _PlaneStress ) || ( mMode == _PlaneStrain ) ) { + answer = this->computeShearSlipOnCrack(gp, tStep, 1); + } else {*/ + + int nMaxCracks = status->giveNumberOfTempCracks(); + for ( int i = 1; i <= nMaxCracks; i++ ) { + answer.at(1) = max(answer.at(1), this->computeShearSlipOnCrack(gp, tStep, i) ); + } + // } + return 1; + } else { return StructuralMaterial :: giveIPValue(answer, gp, type, tStep); } } -void -FCMMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +FCMMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } -void -FCMMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +FCMMaterial :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) - + TimeStep *tStep) const { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } -void -FCMMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<4,4> +FCMMaterial :: givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } -FCMMaterialStatus :: FCMMaterialStatus(int n, Domain *d, GaussPoint *gp) : - StructuralMaterialStatus(n, d, gp), +FCMMaterialStatus :: FCMMaterialStatus(GaussPoint *gp) : + StructuralMaterialStatus(gp), crackStatuses(), tempCrackStatuses(), maxCrackStrains(), tempMaxCrackStrains(), crackStrainVector(), tempCrackStrainVector(), @@ -1730,7 +2311,6 @@ FCMMaterialStatus :: FCMMaterialStatus(int n, Domain *d, GaussPoint *gp) : transMatrix_L2Gstress(), transMatrix_L2Gstrain() { // resize in constructor according to stress-state - this->nMaxCracks = 0; this->nMaxCracks = giveMaxNumberOfCracks(gp); crackStatuses.resize(this->nMaxCracks); @@ -1775,21 +2355,15 @@ FCMMaterialStatus :: FCMMaterialStatus(int n, Domain *d, GaussPoint *gp) : } -FCMMaterialStatus :: ~FCMMaterialStatus() -{ } - - - void -FCMMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +FCMMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { - int i; char s [ 11 ]; StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); if ( this->giveNumberOfCracks() > 0 ) { - for ( i = 1; i <= crackDirs.giveNumberOfColumns(); i++ ) { + for ( int i = 1; i <= crackDirs.giveNumberOfColumns(); i++ ) { switch ( crackStatuses.at(i) ) { case pscm_NONE: strcpy(s, "NONE"); @@ -1817,8 +2391,11 @@ FCMMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) fprintf( file, "%f ", crackDirs.at(j, i) ); } - fprintf(file, "}}"); - ; + fprintf(file, "} "); + + fprintf(file, "crack_width %.4e", this->giveCharLength(i) * this->giveCrackStrain(i) ); + + fprintf(file, " } "); } } @@ -1885,6 +2462,18 @@ FCMMaterialStatus :: giveMaxNumberOfCracks(GaussPoint *gp) } +void +FCMMaterialStatus :: setTempNormalCrackStrainVector(FloatArray tempNormalCrackStrain) +// +// return number of maximum allowable cracks +// +{ + + for ( int i = 1; i <= tempNormalCrackStrain.giveSize(); i++ ) { + tempCrackStrainVector.at(i) = tempNormalCrackStrain.at(i); + } + +} void @@ -1916,7 +2505,8 @@ FCMMaterialStatus :: updateYourself(TimeStep *tStep) maxCrackStrains = tempMaxCrackStrains; crackStrainVector = tempCrackStrainVector; - for ( int i = 1; i <= crackStrainVector.giveSize(); i++ ) { + // for ( int i = 1; i <= crackStrainVector.giveSize(); i++ ) { + for ( int i = 1; i <= this->nMaxCracks; i++ ) { // loop only in normal directions! if ( crackStrainVector.at(i) < 0. ) { crackStrainVector.at(i) = 0.; } @@ -1947,22 +2537,12 @@ FCMMaterialStatus :: updateYourself(TimeStep *tStep) -contextIOResultType -FCMMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +FCMMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write a raw data + StructuralMaterialStatus :: saveContext(stream, mode); + contextIOResultType iores; if ( ( iores = crackStatuses.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -2002,25 +2582,14 @@ FCMMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj if ( ( iores = transMatrix_L2Gstress.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -FCMMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +FCMMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data + StructuralMaterialStatus :: restoreContext(stream, mode); + contextIOResultType iores; if ( ( iores = crackStatuses.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -2056,7 +2625,5 @@ FCMMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void * if ( ( iores = transMatrix_L2Gstress.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; // return succes } } // end namespace oofem diff --git a/src/sm/Materials/fcm.h b/src/sm/Materials/fcm.h index 3b9cce407..d746b22c2 100644 --- a/src/sm/Materials/fcm.h +++ b/src/sm/Materials/fcm.h @@ -47,6 +47,8 @@ #define _IFT_FCM_crackSpacing "crackspacing" #define _IFT_FCM_multipleCrackShear "multiplecrackshear" #define _IFT_FCM_ecsm "ecsm" +#define _IFT_FCM_shearCoeffNumer "shearcoeffnumer" +#define _IFT_FCM_normalCoeffNumer "normalcoeffnumer" //@} namespace oofem { @@ -60,6 +62,7 @@ namespace oofem { #define fcm_SMALL_STRAIN 1.e-12 #define fcm_BIGNUMBER 1.e6 #define fcm_TOLERANCE 1.e-6 +#define fcm_THRESHOLD_CRACK_STRAIN 1.e-8 /** @@ -68,7 +71,7 @@ namespace oofem { class FCMMaterialStatus : public StructuralMaterialStatus { protected: - /// crack statuses (none, just initialized, softenin, unlo-relo, closed) + /// crack statuses (none, just initialized, softening, unload-reload, closed) IntArray crackStatuses, tempCrackStatuses; /// Max. crack strain reached in the entire previous history FloatArray maxCrackStrains, tempMaxCrackStrains; @@ -89,13 +92,12 @@ class FCMMaterialStatus : public StructuralMaterialStatus FloatMatrix transMatrix_L2Gstrain; /// number of maximum possible cracks (optional parameter) - int nMaxCracks; + int nMaxCracks = 0; public: - FCMMaterialStatus(int n, Domain *d, GaussPoint *g); - virtual ~FCMMaterialStatus(); - /// prints the output into the output file - virtual void printOutputAt(FILE *file, TimeStep *tStep); + FCMMaterialStatus(GaussPoint *g); + + void printOutputAt(FILE *file, TimeStep *tStep) const override; /// returns number of cracks from the previous time step (equilibrated value) virtual int giveNumberOfCracks() const; /// returns temporary number of cracks @@ -130,8 +132,10 @@ class FCMMaterialStatus : public StructuralMaterialStatus double giveCrackStrain(int icrack) const { return crackStrainVector.at(icrack); } /// returns i-th component of the crack strain vector (temporary) double giveTempCrackStrain(int icrack) const { return tempCrackStrainVector.at(icrack); } - /// sets temporary vector of cracking strains (max 6 components) + /// sets temporary vector of cracking strains (max 6 components) void setTempCrackStrainVector(FloatArray a) { tempCrackStrainVector = std :: move(a); } + /// sets temporary vector of cracking strains (normal components) + void setTempNormalCrackStrainVector(FloatArray a); /// sets temporary value of i-th cracking strain (max 6 components) void setTempCrackStrain(int icrack, double val) { tempCrackStrainVector.at(icrack) = val; } /// sets equilibrated vector of cracking strains (max 6 components) @@ -173,18 +177,13 @@ class FCMMaterialStatus : public StructuralMaterialStatus /// returns maximum number of cracks associated with current mode virtual int giveMaxNumberOfCracks(GaussPoint *gp); - // definition - virtual const char *giveClassName() const { return "FCMMaterialStatus"; } + const char *giveClassName() const override { return "FCMMaterialStatus"; } - /// initializes temporary status - virtual void initTempStatus(); - /// replaces equilibrated values with temporary values - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - /// saves current context(state) into stream - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - /// restores context(state) from stream - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; /** @@ -192,79 +191,87 @@ class FCMMaterialStatus : public StructuralMaterialStatus * After the onset of cracking, the cracks can still transfer tractions (i.e. cohesive crack approach) in * both normal and shear directions. Cracks can develop only in mutually perpendicular directions. * In elastic state this model is isotropic. - * This is class is purely abstract, it can be used only in the derived classes (e.g. ConcreteFCM) + * This class is purely abstract, it can be used only in the derived classes (e.g. ConcreteFCM) */ class FCMMaterial : public StructuralMaterial { protected: - IsotropicLinearElasticMaterial *linearElasticMaterial; + IsotropicLinearElasticMaterial linearElasticMaterial; public: FCMMaterial(int n, Domain *d); - virtual ~FCMMaterial(); - - // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 1; } - virtual int hasMaterialModeCapability(MaterialMode mode); - - virtual const char *giveClassName() const { return "FCMMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); + bool hasMaterialModeCapability(MaterialMode mode) const override; - virtual double give(int aProperty, GaussPoint *gp); + const char *giveClassName() const override { return "FCMMaterial"; } - IsotropicLinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } + void initializeFrom(InputRecord &ir) override; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + double give(int aProperty, GaussPoint *gp) const override; + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; - virtual void initializeCrack(GaussPoint *gp, FloatMatrix &base, int nCrack); - - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_2dBeamLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlateLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } + virtual void initializeCrack(GaussPoint *gp, TimeStep *tStep, FloatMatrix &base, int nCrack); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<4> giveRealStressVector_PlaneStrain(const FloatArrayF<4> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<2> giveRealStressVector_2dBeamLayer(const FloatArrayF<2> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<5> giveRealStressVector_PlateLayer(const FloatArrayF<5> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; /// uses temporary cracking strain and characteristic length to obtain the crack opening virtual double computeNormalCrackOpening(GaussPoint *gp, int i); /// uses maximum equilibrated cracking strain and characteristic length to obtain the maximum reached crack opening - virtual double computeMaxNormalCrackOpening(GaussPoint *gp, int i); + virtual double computeMaxNormalCrackOpening(GaussPoint *gp, TimeStep *tStep, int i); /// computes total shear slip on a given crack plane (i = 1, 2, 3); the slip is computed from the temporary cracking strain - virtual double computeShearSlipOnCrack(GaussPoint *gp, int i); + virtual double computeShearSlipOnCrack(GaussPoint *gp, TimeStep *tStep, int i); - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new FCMMaterialStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new FCMMaterialStatus(gp); } protected: - /// allowed number of cracks (user-defined) + /// allowed number of cracks (user-defined) int nAllowedCracks; /// Method used for evaluation of characteristic element size @@ -274,34 +281,43 @@ class FCMMaterial : public StructuralMaterial bool multipleCrackShear; /// comutes tensile strength - virtual double giveTensileStrength(GaussPoint *gp) = 0; + virtual double giveTensileStrength(GaussPoint *gp, TimeStep *tStep) = 0; /// checks possible snap-back - virtual void checkSnapBack(GaussPoint *gp, int crack) = 0; + virtual void checkSnapBack(GaussPoint *gp, TimeStep *tStep, int crack) = 0; /// updates crack statuses virtual void updateCrackStatus(GaussPoint *gp); /// computes normal stress associated with i-th crack direction - virtual double giveNormalCrackingStress(GaussPoint *gp, double eps_cr, int i) = 0; + virtual double giveNormalCrackingStress(GaussPoint *gp, TimeStep *tStep, double eps_cr, int i) = 0; /// returns characteristic element length in given direction virtual double giveCharacteristicElementLength(GaussPoint *gp, const FloatArray &crackPlaneNormal); /// returns stiffness in the normal direction of the i-th crack - virtual double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, int i) = 0; + virtual double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep, int i) = 0; + /// returns stiffness in the normal direction of the i-th crack + virtual double giveCrackingModulusInTension(MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep, int i) = 0; + /// returns Geff which is necessary in the global stiffness matrix - virtual double computeEffectiveShearModulus(GaussPoint *gp, int i) = 0; + virtual double computeEffectiveShearModulus(GaussPoint *gp, TimeStep *tStep, int i) = 0; /// shear modulus for a given shear direction (4, 5, 6) - virtual double computeTotalD2Modulus(GaussPoint *gp, int i); + virtual double computeTotalD2Modulus(GaussPoint *gp, TimeStep *tStep, int i); + + /// shear modulus in a STIFFNESS MATRIX for a given shear direction (4, 5, 6) + virtual double computeNumerD2Modulus(GaussPoint *gp, TimeStep *tStep, int i); /// shear modulus for a given crack plane (1, 2, 3) - virtual double computeD2ModulusForCrack(GaussPoint *gp, int icrack) = 0; + virtual double computeD2ModulusForCrack(GaussPoint *gp, TimeStep *tStep, int icrack) = 0; + /// shear modulus for numerical purpose (stiffness matrix) for a given crack plane (1, 2, 3) + virtual double computeNumerD2ModulusForCrack(GaussPoint *gp, TimeStep *tStep, int icrack) = 0; + /// computes the maximum value of the shear stress; if the shear stress exceeds this value, it is cropped - virtual double maxShearStress(GaussPoint *gp, int i) = 0; + virtual double maxShearStress(GaussPoint *gp, TimeStep *tStep, int i) = 0; /// returns true for closed or no cracks associated to given shear direction (i = 4, 5, 6) virtual bool isIntactForShear(GaussPoint *gp, int i); @@ -309,6 +325,9 @@ class FCMMaterial : public StructuralMaterial /// returns true for closed or no crack (i = 1, 2, 3) virtual bool isIntact(GaussPoint *gp, int icrack); + /// returns true if current component is associated with shear + virtual bool isThisShearComponent(GaussPoint *gp, int component); + /// checks if the globalStress does not exceed strength in the direction of newBase for n-th crack virtual bool checkStrengthCriterion(FloatMatrix &newBase, const FloatArray &globalStress, GaussPoint *gp, TimeStep *tStep, int nCrack); @@ -316,11 +335,18 @@ class FCMMaterial : public StructuralMaterial virtual bool isStrengthExceeded(const FloatMatrix &base, GaussPoint *gp, TimeStep *tStep, int iCrack, double trialStress); /// function calculating ratio used to split shear slips on two crack planes - virtual double computeShearStiffnessRedistributionFactor(GaussPoint *gp, int ithCrackPlane, int jthCrackDirection); + virtual double computeShearStiffnessRedistributionFactor(GaussPoint *gp, TimeStep *tStep, int ithCrackPlane, int jthCrackDirection); /// value of crack spacing (allows to "have" more parallel cracks in one direction if the element size exceeds user-defined or computed crack spacing). double crackSpacing; + /// minimum ratio of effective shear modulus vs. shear modulus - just for numerical purpose + double shearCoeffNumer; + + /// minimum ratio of effective normal stiffness vs. overall modulus - just for numerical purpose + double normalCoeffNumer; + + /// returns either user-provided value of crack spacing or a value computed from composition virtual double giveCrackSpacing(void); @@ -335,16 +361,27 @@ class FCMMaterial : public StructuralMaterial GaussPoint * gp, TimeStep * tStep); - /// returns local stiffness matrix of the crack - virtual void giveLocalCrackedStiffnessMatrix(FloatMatrix &answer, + /// returns local stiffness matrix in the cracks' direction (total according to the material mode) + virtual void giveTotalLocalCrackedStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, + GaussPoint *gp, TimeStep *tStep); + + /// returns local stiffness matrix in the cracks' direction (only normal components) + virtual void giveNormalLocalCrackedStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); /// returns overall Young's modulus - virtual double computeOverallElasticStiffness(void) { return linearElasticMaterial->giveYoungsModulus(); } + virtual double computeOverallElasticStiffness(GaussPoint *gp, TimeStep *tStep) { return linearElasticMaterial.giveYoungsModulus(); } /// returns overall shear modulus - virtual double computeOverallElasticShearModulus(void) { return linearElasticMaterial->giveShearModulus(); } + virtual double computeOverallElasticShearModulus(GaussPoint *gp, TimeStep *tStep) { return linearElasticMaterial.giveShearModulus(); } + + /// returns Poisson's ratio + virtual double givePoissonsRatio() { return linearElasticMaterial.givePoissonsRatio(); } + + + }; } // end namespace oofem #endif // fcm_h diff --git a/src/sm/Materials/graddamagematerialextensioninterface.C b/src/sm/Materials/graddamagematerialextensioninterface.C new file mode 100644 index 000000000..e21ac0d2a --- /dev/null +++ b/src/sm/Materials/graddamagematerialextensioninterface.C @@ -0,0 +1,93 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "domain.h" +#include "nonlocalbarrier.h" +#include "graddamagematerialextensioninterface.h" +#include "inputrecord.h" +#include "floatmatrix.h" + +#include + + +namespace oofem { +// constructor +GradientDamageMaterialExtensionInterface :: GradientDamageMaterialExtensionInterface(Domain *d) : + Interface(), + dom(d) +{ +} + +void +GradientDamageMaterialExtensionInterface :: giveGradientDamageStiffnessMatrix_dd_NN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + answer.clear(); +} + +void +GradientDamageMaterialExtensionInterface :: giveGradientDamageStiffnessMatrix_dd_BN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + answer.clear(); +} + + +void +GradientDamageMaterialExtensionInterface :: initializeFrom(InputRecord &ir) +{ + // read the characteristic length + IR_GIVE_FIELD(ir, internalLength, _IFT_GradientDamageMaterialExtensionInterface_l); +} + +GradientDamageMaterialStatusExtensionInterface :: GradientDamageMaterialStatusExtensionInterface() : Interface() +{ +} + + +void +GradientDamageMaterialStatusExtensionInterface :: initTempStatus() +{ + tempLocalDamageDrivingVariable = localDamageDrivingVariable; + tempNonlocalDamageDrivingVariable = nonlocalDamageDrivingVariable; + tempNonlocalDamageDrivingVariableGrad = nonlocalDamageDrivingVariableGrad; +} + + +void +GradientDamageMaterialStatusExtensionInterface :: updateYourself(TimeStep *tStep) +{ + localDamageDrivingVariable = tempLocalDamageDrivingVariable; + nonlocalDamageDrivingVariable = tempNonlocalDamageDrivingVariable; + nonlocalDamageDrivingVariableGrad = tempNonlocalDamageDrivingVariableGrad; +} +} // end namespace oofem diff --git a/src/sm/Materials/graddamagematerialextensioninterface.h b/src/sm/Materials/graddamagematerialextensioninterface.h new file mode 100644 index 000000000..32e284a9c --- /dev/null +++ b/src/sm/Materials/graddamagematerialextensioninterface.h @@ -0,0 +1,142 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef gradientdamagematerialextensioninterface_h +#define gradientdamagematerialextensioninterface_h + +#include "interface.h" +#include "matresponsemode.h" +#include "floatarray.h" + +///@name graddpdmaterialextensioninterface +//@{ +#define _IFT_GradientDamageMaterialExtensionInterface_l "l" +//@} + +namespace oofem { +class GaussPoint; +class TimeStep; +class FloatArray; +class FloatMatrix; + + + + +/** + * Material interface for gradient material models. + */ +class GradientDamageMaterialExtensionInterface : public Interface +{ +protected: + Domain *dom = nullptr; + + /** + * Initial(user defined) characteristic length of the nonlocal model + */ + double internalLength = 0.; + + + +public: + /** + * Constructor. Creates material with given number, belonging to given domain. + * @param d Domain to which new material will belong. + */ + GradientDamageMaterialExtensionInterface(Domain *d); + /// Destructor. + virtual ~GradientDamageMaterialExtensionInterface() { } + /// Left upper block + virtual void giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + /// Left lower block + virtual void giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + /// Right upper block + virtual void giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + /// Right lower block + virtual void giveGradientDamageStiffnessMatrix_dd_NN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + virtual void giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; + virtual void giveGradientDamageStiffnessMatrix_dd_BN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + /// gradient - based giveRealStressVector + virtual void giveRealStressVectorGradientDamage(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalDamageDrivningVariable, TimeStep *tStep) { OOFEM_ERROR("not implemented") } + virtual void giveFirstPKStressVectorGradientDamage(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalDamageDrivningVariable, TimeStep *tStep) { OOFEM_ERROR("not implemented") } + virtual void giveCauchyStressVectorGradientDamage(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalDamageDrivningVariable, TimeStep *tStep) { OOFEM_ERROR("not implemented") } + + virtual void computeInternalForcesRegularizationTerm(double &answer, GaussPoint *gp, TimeStep *tStep) + { answer = 0.; } + virtual void computeStiffnessRegularizationTerm(double &answer, GaussPoint *gp, TimeStep *tStep) + { answer = 0.; } + + + virtual void computeLocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep) = 0; + virtual void giveNonlocalInternalForces_N_factor(double &answer, double nlddv, GaussPoint *gp, TimeStep *tStep) = 0; + virtual void giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlddv, GaussPoint *gp, TimeStep *tStep) = 0; + + virtual void initializeFrom(InputRecord &ir); +}; + +class GradientDamageMaterialStatusExtensionInterface : public Interface +{ +public: + GradientDamageMaterialStatusExtensionInterface(); + /// Destructor. + virtual ~GradientDamageMaterialStatusExtensionInterface() { } + +protected: + double nonlocalDamageDrivingVariable = 0.; + double localDamageDrivingVariable = 0.; + double tempNonlocalDamageDrivingVariable = 0.; + double tempLocalDamageDrivingVariable = 0.; + + FloatArray nonlocalDamageDrivingVariableGrad; + FloatArray tempNonlocalDamageDrivingVariableGrad; + +public: + virtual double giveLocalDamageDrivingVariable() { return localDamageDrivingVariable; } + virtual double giveNonlocalDamageDrivingVariable() { return nonlocalDamageDrivingVariable; } + virtual double giveTempLocalDamageDrivingVariable() { return tempLocalDamageDrivingVariable; } + virtual double giveTempNonlocalDamageDrivingVariable() { return tempNonlocalDamageDrivingVariable; } + const FloatArray &giveTempNonlocalDamageDrivingVariableGrad() const { return tempNonlocalDamageDrivingVariableGrad; } + + + + virtual void setLocalDamageDrivingVariable(double localDamageDrivingVariable) { this->localDamageDrivingVariable = localDamageDrivingVariable; } + virtual void setNonlocalDamageDrivingVariable(double nonlocalDamageDrivingVariable) { this->nonlocalDamageDrivingVariable = nonlocalDamageDrivingVariable; } + virtual void setTempLocalDamageDrivingVariable(double localDamageDrivingVariable) { this->tempLocalDamageDrivingVariable = localDamageDrivingVariable; } + virtual void setTempNonlocalDamageDrivingVariable(double nonlocalDamageDrivingVariable) { this->tempNonlocalDamageDrivingVariable = nonlocalDamageDrivingVariable; } + virtual void letTempNonlocalDamageDrivingVariableGradBe(const FloatArray &nonlocalDamageDrivingVariableGrad) { this->tempNonlocalDamageDrivingVariableGrad = nonlocalDamageDrivingVariableGrad; } + + virtual void initTempStatus(); + virtual void updateYourself(TimeStep *tStep); +}; +} +#endif diff --git a/src/sm/Materials/graddpmaterialextensioninterface.C b/src/sm/Materials/graddpmaterialextensioninterface.C deleted file mode 100644 index d9eb39e12..000000000 --- a/src/sm/Materials/graddpmaterialextensioninterface.C +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "domain.h" -#include "nonlocalbarrier.h" -#include "graddpmaterialextensioninterface.h" -#include "inputrecord.h" - -#include - - -namespace oofem { -// flag forcing the inclusion of all elements with volume inside support of weight function. -// This forces inclusion of all integration points of these elements, even if weight is zero -// If not defined (default) only integration points with nonzero weight are included. -// #define NMEI_USE_ALL_ELEMENTS_IN_SUPPORT - - -// constructor -GradDpMaterialExtensionInterface :: GradDpMaterialExtensionInterface(Domain *d) : Interface() -{ - dom = d; - - cl = 0.; - cl0 = 0.; - averType = 0; - beta = 0.; - zeta = 0.; -} - - - - -IRResultType -GradDpMaterialExtensionInterface :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - - // read the characteristic length - IR_GIVE_FIELD(ir, cl, _IFT_GradDpMaterialExtensionInterface_cl); - if ( cl < 0.0 ) { - cl = 0.0; - } - - cl0 = cl; - // special averaging - // averType = 0 ... classical - // averType = 1 ... distance-based - // averType = 1 ... stress-based - averType = 0; - - IR_GIVE_OPTIONAL_FIELD(ir, averType, _IFT_GradDpMaterialExtensionInterface_averagingtype); - if ( averType == 1 ) { - IR_GIVE_FIELD(ir, beta, _IFT_GradDpMaterialExtensionInterface_beta); - IR_GIVE_FIELD(ir, zeta, _IFT_GradDpMaterialExtensionInterface_zeta); - } else if ( averType == 2 ) { - IR_GIVE_FIELD(ir, beta, _IFT_GradDpMaterialExtensionInterface_beta); - } - - return IRRT_OK; -} - - - - - -void -GradDpMaterialExtensionInterface :: giveDistanceBasedCharacteristicLength(const FloatArray &gpCoords) -{ - double distance = 1.e20; // Initially distance from the boundary is set to the maximum value - double temp; - int ib, nbarrier = dom->giveNumberOfNonlocalBarriers(); - for ( ib = 1; ib <= nbarrier; ib++ ) { //Loop over all the nonlocal barriers to find minimum distance from the boundary - temp = dom->giveNonlocalBarrier(ib)->calculateMinimumDistanceFromBoundary(gpCoords); - if ( distance > temp ) { //Check to find minimum distance from boundary from all nonlocal boundaries - distance = temp; - } - } - - //Calculate interaction radius based on the minimum distance from the nonlocal boundaries - if ( distance < zeta * cl0 ) { - cl = ( ( 1 - beta ) / ( zeta * cl0 ) * distance + beta ) * cl0; - } else { - cl = cl0; - } -} -//////////////////////////////////////////////////////////////////////////////////////////////////// -} // end namespace oofem diff --git a/src/sm/Materials/graddpmaterialextensioninterface.h b/src/sm/Materials/graddpmaterialextensioninterface.h deleted file mode 100644 index baa040363..000000000 --- a/src/sm/Materials/graddpmaterialextensioninterface.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef graddpmaterialextensioninterface_h -#define graddpmaterialextensioninterface_h - -#include "interface.h" -#include "matresponsemode.h" - -///@name graddpdmaterialextensioninterface -//@{ -#define _IFT_GradDpMaterialExtensionInterface_averagingtype "averagingType" -#define _IFT_GradDpMaterialExtensionInterface_cl "cl" -#define _IFT_GradDpMaterialExtensionInterface_beta "beta" -#define _IFT_GradDpMaterialExtensionInterface_zeta "zeta" -//@} - -namespace oofem { -class FloatMatrix; -class GaussPoint; -class TimeStep; - - - -/** - * Material interface for gradient material models. - */ -class GradDpMaterialExtensionInterface : public Interface -{ -protected: - Domain *dom; - - /** - * Initial(user defined) characteristic length of the nonlocal model - * (its interpretation depends on the weight function) - * Is different to cl when a Stress-based or a Distance-based - * nonlocal variation is applied - */ - double cl0; - - - /** - * Parameter which defines the averaging type - * When averType is equal to zereo classical approach is used - * for averType equal to one, distance-based apprach is used - * and avetType equal to two corresponds to stress-based averaging - */ - int averType; - - /** - * Parameter which multiplied with the interaction radius cl0 - * gives its minimum allowed value. It is used when a Stress-based - * or a Distance-based nonlocal variation is applied - */ - double beta; - /** - * Parameter used when Distance-based nonlocal variation is applied - * When it is multiplied with the interaction radius cl gives the maxinmum - * distance of the Gauss Point from the boundary. If the Gauss Point's distance - * from the boundary is larger than this value the interaction radius cl is set - * to cl0 - */ - double zeta; - - /** - * Characteristic length of the nonlocal model - * (its interpretation depends on the type of weight function). - */ - double cl; - - /** - * Provides the distance based interaction radius - * This function is called when averType is set to 1. - * The function loops over all user defined nonlocal boundaries - * to find minimum distance from the GP. Then calculates interaction radius - * @param gpCoords The Gauss points' coordinates, whose interaction radius is calculated based on the distance-based averaging approach. - */ - void giveDistanceBasedCharacteristicLength(const FloatArray &gpCoords); -public: - /** - * Constructor. Creates material with given number, belonging to given domain. - * @param d Domain to which new material will belong. - */ - GradDpMaterialExtensionInterface(Domain * d); - /// Destructor. - virtual ~GradDpMaterialExtensionInterface() { } - /// Left upper block - virtual void givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; - /// Left lower block - virtual void givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; - /// Right upper block - virtual void givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; - /// Right lower block - virtual void givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; - /// Stress-based averaging - virtual void givePDGradMatrix_LD(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) = 0; - /// gradient - based giveRealStressVector - virtual void giveRealStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalDamageDrivningVariable, TimeStep *tStep) { OOFEM_ERROR("not implemented") } - virtual void giveFirstPKStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalDamageDrivningVariable, TimeStep *tStep) { OOFEM_ERROR("not implemented") } - virtual void giveCauchyStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalDamageDrivningVariable, TimeStep *tStep) { OOFEM_ERROR("not implemented") } - - virtual IRResultType initializeFrom(InputRecord *ir); - int giveAveragingType() { return averType; } -}; - -class GradDpMaterialStatusExtensionInterface : public Interface -{ -protected: - double nonlocalCumulatedStrain; -public: - virtual double giveNonlocalCumulatedStrain() = 0; - virtual void setNonlocalCumulatedStrain(double nonlocalCumulatedStrain) = 0; -}; -} -#endif diff --git a/src/sm/Materials/hyperelasticmaterial.C b/src/sm/Materials/hyperelasticmaterial.C deleted file mode 100644 index 2ab4490e7..000000000 --- a/src/sm/Materials/hyperelasticmaterial.C +++ /dev/null @@ -1,157 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "hyperelasticmaterial.h" -#include "floatmatrix.h" -#include "floatarray.h" -#include "classfactory.h" - -namespace oofem { -REGISTER_Material(HyperElasticMaterial); - -HyperElasticMaterial :: HyperElasticMaterial(int n, Domain *d) : StructuralMaterial(n, d) -{ } - - -void -HyperElasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode, GaussPoint *gp, TimeStep *tStep) -{ - double J2, c11, c22, c33, c12, c13, c23, A, B; - FloatMatrix C(3, 3); - FloatMatrix invC; - - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - - C.at(1, 1) = 1. + 2. * status->giveTempStrainVector().at(1); - C.at(2, 2) = 1. + 2. * status->giveTempStrainVector().at(2); - C.at(3, 3) = 1. + 2. * status->giveTempStrainVector().at(3); - C.at(2, 3) = C.at(3, 2) = status->giveTempStrainVector().at(4); - C.at(1, 3) = C.at(3, 1) = status->giveTempStrainVector().at(5); - C.at(1, 2) = C.at(2, 1) = status->giveTempStrainVector().at(6); - - invC.beInverseOf(C); - J2 = C.giveDeterminant(); - - c11 = invC.at(1, 1); - c22 = invC.at(2, 2); - c33 = invC.at(3, 3); - c12 = invC.at(1, 2); - c13 = invC.at(1, 3); - c23 = invC.at(2, 3); - - A = ( K - 2. / 3. * G ) * J2; - B = -( K - 2. / 3. * G ) * ( J2 - 1. ) + 2. * G; - - answer.resize(6, 6); - - answer.at(1, 1) = ( A + B ) * c11 * c11; - answer.at(2, 2) = ( A + B ) * c22 * c22; - answer.at(3, 3) = ( A + B ) * c33 * c33; - answer.at(4, 4) = A * c23 * c23 + B / 2. * ( c22 * c33 + c23 * c23 ); - answer.at(5, 5) = A * c13 * c13 + B / 2. * ( c11 * c33 + c13 * c13 ); - answer.at(6, 6) = A * c12 * c12 + B / 2. * ( c11 * c22 + c12 * c12 ); - answer.at(1, 2) = answer.at(2, 1) = A * c11 * c22 + B * c12 * c12; - answer.at(1, 3) = answer.at(3, 1) = A * c11 * c33 + B * c13 * c13; - answer.at(1, 4) = answer.at(4, 1) = A * c11 * c23 + B * c12 * c13; - answer.at(1, 5) = answer.at(5, 1) = A * c11 * c13 + B * c11 * c13; - answer.at(1, 6) = answer.at(6, 1) = A * c11 * c12 + B * c11 * c12; - answer.at(2, 3) = answer.at(3, 2) = A * c22 * c33 + B * c23 * c23; - answer.at(2, 4) = answer.at(4, 2) = A * c22 * c23 + B * c22 * c23; - answer.at(2, 5) = answer.at(5, 2) = A * c22 * c13 + B * c12 * c23; - answer.at(2, 6) = answer.at(6, 2) = A * c22 * c12 + B * c22 * c12; - answer.at(3, 4) = answer.at(4, 3) = A * c33 * c23 + B * c33 * c23; - answer.at(3, 5) = answer.at(5, 3) = A * c33 * c13 + B * c33 * c13; - answer.at(3, 6) = answer.at(6, 3) = A * c33 * c12 + B * c13 * c23; - answer.at(4, 5) = answer.at(5, 4) = A * c23 * c13 + B / 2. * ( c12 * c33 + c13 * c23 ); - answer.at(4, 6) = answer.at(6, 4) = A * c23 * c12 + B / 2. * ( c12 * c23 + c22 * c13 ); - answer.at(5, 6) = answer.at(6, 5) = A * c13 * c12 + B / 2. * ( c11 * c23 + c12 * c13 ); -} - - -void -HyperElasticMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep) -{ - double J2; - FloatMatrix C(3, 3); - FloatMatrix invC; - FloatArray strainVector; - - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - this->giveStressDependentPartOfStrainVector_3d(strainVector, gp, - totalStrain, - tStep, VM_Total); - - C.at(1, 1) = 1. + 2. * strainVector.at(1); - C.at(2, 2) = 1. + 2. * strainVector.at(2); - C.at(3, 3) = 1. + 2. * strainVector.at(3); - C.at(1, 2) = C.at(2, 1) = strainVector.at(6); - C.at(1, 3) = C.at(3, 1) = strainVector.at(5); - C.at(2, 3) = C.at(3, 2) = strainVector.at(4); - invC.beInverseOf(C); - J2 = C.giveDeterminant(); - - answer.resize(6); - double aux = ( K - 2. / 3. * G ) * ( J2 - 1. ) / 2. - G; - answer.at(1) = aux * invC.at(1, 1) + G; - answer.at(2) = aux * invC.at(2, 2) + G; - answer.at(3) = aux * invC.at(3, 3) + G; - answer.at(4) = aux * invC.at(2, 3); - answer.at(5) = aux * invC.at(1, 3); - answer.at(6) = aux * invC.at(1, 2); - - // update gp - status->letTempStrainVectorBe(totalStrain); - status->letTempStressVectorBe(answer); -} - - -MaterialStatus * -HyperElasticMaterial :: CreateStatus(GaussPoint *gp) const -{ - return new StructuralMaterialStatus(1, this->giveDomain(), gp); -} - - -IRResultType -HyperElasticMaterial :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - IR_GIVE_FIELD(ir, K, _IFT_HyperElasticMaterial_k); - IR_GIVE_FIELD(ir, G, _IFT_HyperElasticMaterial_g); - - return StructuralMaterial :: initializeFrom(ir); -} - -} // end namespace oofem diff --git a/src/sm/Materials/isodamagemodel.C b/src/sm/Materials/isodamagemodel.C index 514e75ee8..414c1fb10 100644 --- a/src/sm/Materials/isodamagemodel.C +++ b/src/sm/Materials/isodamagemodel.C @@ -39,48 +39,35 @@ #include "datastream.h" #include "contextioerr.h" #include "dynamicinputrecord.h" +#include "gausspoint.h" namespace oofem { IsotropicDamageMaterial :: IsotropicDamageMaterial(int n, Domain *d) : StructuralMaterial(n, d) - // - // constructor - // { - linearElasticMaterial = NULL; - llcriteria = idm_strainLevelCR; - maxOmega = 0.999999; - permStrain = 0; } IsotropicDamageMaterial :: ~IsotropicDamageMaterial() -// -// destructor -// { delete linearElasticMaterial; } -int -IsotropicDamageMaterial :: hasMaterialModeCapability(MaterialMode mode) -// -// returns whether receiver supports given mode -// +bool +IsotropicDamageMaterial :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _3dMat || mode == _PlaneStress || mode == _PlaneStrain || mode == _1dMat; } -void -IsotropicDamageMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +IsotropicDamageMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // computes full constitutive matrix for case of gp stress-strain state. // { - IsotropicDamageMaterialStatus *status = static_cast< IsotropicDamageMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< IsotropicDamageMaterialStatus * >( this->giveStatus(gp) ); double tempDamage; if ( mode == ElasticStiffness ) { tempDamage = 0.0; @@ -89,8 +76,8 @@ IsotropicDamageMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, tempDamage = min(tempDamage, maxOmega); } - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); - answer.times(1.0 - tempDamage); + auto d = this->linearElasticMaterial->give3dMaterialStiffnessMatrix(mode, gp, tStep); + return d * (1.0 - tempDamage); //TODO - correction for tangent mode } @@ -122,8 +109,8 @@ IsotropicDamageMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint * //crossSection->giveFullCharacteristicVector(totalStrainVector, gp, reducedTotalStrainVector); // compute equivalent strain - this->computeEquivalentStrain(equivStrain, reducedTotalStrainVector, gp, tStep); - + equivStrain = this->computeEquivalentStrain(reducedTotalStrainVector, gp, tStep); + if ( llcriteria == idm_strainLevelCR ) { // compute value of loading function if strainLevel crit apply f = equivStrain - status->giveKappa(); @@ -137,13 +124,13 @@ IsotropicDamageMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint * tempKappa = equivStrain; this->initDamaged(tempKappa, reducedTotalStrainVector, gp); // evaluate damage parameter - this->computeDamageParam(omega, tempKappa, reducedTotalStrainVector, gp); + omega = this->computeDamageParam(tempKappa, reducedTotalStrainVector, gp); } } else if ( llcriteria == idm_damageLevelCR ) { // evaluate damage parameter first tempKappa = equivStrain; this->initDamaged(tempKappa, reducedTotalStrainVector, gp); - this->computeDamageParam(omega, tempKappa, reducedTotalStrainVector, gp); + omega = this->computeDamageParam(tempKappa, reducedTotalStrainVector, gp); if ( omega < status->giveDamage() ) { // unloading takes place omega = status->giveDamage(); @@ -179,10 +166,10 @@ IsotropicDamageMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint * } -void IsotropicDamageMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +IsotropicDamageMaterial :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - IsotropicDamageMaterialStatus *status = static_cast< IsotropicDamageMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< IsotropicDamageMaterialStatus * >( this->giveStatus(gp) ); double tempDamage; if ( mode == ElasticStiffness ) { tempDamage = 0.0; @@ -191,8 +178,8 @@ void IsotropicDamageMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, Ma tempDamage = min(tempDamage, maxOmega); } - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); - answer.times(1.0 - tempDamage); + auto d = this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep); + d *= 1.0 - tempDamage; if ( mode == TangentStiffness ) { double damage = status->giveDamage(); if ( tempDamage > damage ) { @@ -213,16 +200,17 @@ void IsotropicDamageMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, Ma // times minus derivative of damage function correctionTerm.times(-damagePrime); // add to secant stiffness - answer.add(correctionTerm); + d += FloatMatrixF<3,3>(correctionTerm); } } + return d; } -void IsotropicDamageMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<4,4> +IsotropicDamageMaterial :: givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - IsotropicDamageMaterialStatus *status = static_cast< IsotropicDamageMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< IsotropicDamageMaterialStatus * >( this->giveStatus(gp) ); double tempDamage; if ( mode == ElasticStiffness ) { tempDamage = 0.0; @@ -231,16 +219,15 @@ void IsotropicDamageMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, Ma tempDamage = min(tempDamage, maxOmega); } - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); - answer.times(1.0 - tempDamage); + return (1.0 - tempDamage) * this->linearElasticMaterial->givePlaneStrainStiffMtrx(mode, gp, tStep); //TODO - correction for tangent mode } -void IsotropicDamageMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<1,1> +IsotropicDamageMaterial :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - IsotropicDamageMaterialStatus *status = static_cast< IsotropicDamageMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< IsotropicDamageMaterialStatus * >( this->giveStatus(gp) ); double tempDamage; if ( mode == ElasticStiffness ) { tempDamage = 0.0; @@ -249,8 +236,33 @@ void IsotropicDamageMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, MatRe tempDamage = min(tempDamage, maxOmega); } - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); - answer.times(1.0 - tempDamage); + auto answer = this->linearElasticMaterial->give1dStressStiffMtrx(mode, gp, tStep); + answer *= 1.0 - tempDamage; + + if ( mode == TangentStiffness ) { + double damage = status->giveDamage(); + if ( tempDamage > damage ) { + double tempKappa; + FloatArray stress, strain, eta; + FloatMatrix correctionTerm; + stress = status->giveTempStressVector(); + strain = status->giveTempStrainVector(); + tempKappa = status->giveTempKappa(); + // effective stress + stress.times( 1. / ( 1 - tempDamage ) ); + //Computes derivative of the equivalent strain with regards to strain + this->computeEta(eta, strain, gp, tStep); + //compute derivative of damage function + double damagePrime = damageFunctionPrime(tempKappa, gp); + // dyadic product of eff stress and eta + correctionTerm.beDyadicProductOf(stress, eta); + // times minus derivative of damage function + correctionTerm.times(-damagePrime); + // add to secant stiffness + answer += FloatMatrixF<1,1>(correctionTerm); + } + } + return answer; //TODO - correction for tangent mode } @@ -295,7 +307,7 @@ IsotropicDamageMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, Inter answer.resize(1); answer.at(1) = status->giveLe(); return 1; - } else if (type == IST_CrackWidth) { + } else if ( type == IST_CrackWidth ) { answer.resize(1); FloatArray reducedTotalStrainVector; this->giveStressDependentPartOfStrainVector(reducedTotalStrainVector, gp, status->giveStrainVector(), tStep, VM_Total); @@ -306,9 +318,13 @@ IsotropicDamageMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, Inter answer.at(1) = status->giveCrackAngle(); return 1; } else if ( type == IST_CrackVector ) { - status->giveCrackVector(answer); + answer = status->giveCrackVector(); + return 1; + } else if ( type == IST_CumPlasticStrain ) { + if ( permStrain ) { + answer.at(1) = evaluatePermanentStrain(status->giveKappa(), status->giveDamage()); + } return 1; - #ifdef keep_track_of_dissipated_energy } else if ( type == IST_StressWorkDensity ) { answer.resize(1); @@ -331,9 +347,8 @@ IsotropicDamageMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, Inter } -void -IsotropicDamageMaterial :: giveThermalDilatationVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep) +FloatArrayF<6> +IsotropicDamageMaterial :: giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const // // returns a FloatArray(6) of initial strain vector // eps_0 = {exx_0, eyy_0, ezz_0, gyz_0, gxz_0, gxy_0}^T @@ -341,22 +356,23 @@ IsotropicDamageMaterial :: giveThermalDilatationVector(FloatArray &answer, // gp (element) local axes // { - answer.resize(6); - answer.zero(); - answer.at(1) = this->tempDillatCoeff; - answer.at(2) = this->tempDillatCoeff; - answer.at(3) = this->tempDillatCoeff; + return { + this->tempDillatCoeff, + this->tempDillatCoeff, + this->tempDillatCoeff, + 0., 0., 0., + }; } -double IsotropicDamageMaterial :: give(int aProperty, GaussPoint *gp) +double IsotropicDamageMaterial :: give(int aProperty, GaussPoint *gp) const { return linearElasticMaterial->give(aProperty, gp); } -IRResultType -IsotropicDamageMaterial :: initializeFrom(InputRecord *ir) +void +IsotropicDamageMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralMaterial :: initializeFrom(ir); //Set limit on the maximum isotropic damage parameter if needed IR_GIVE_OPTIONAL_FIELD(ir, maxOmega, _IFT_IsotropicDamageMaterial_maxOmega); @@ -367,7 +383,6 @@ IsotropicDamageMaterial :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, permStrain, _IFT_IsotropicDamageMaterial_permstrain); IR_GIVE_FIELD(ir, tempDillatCoeff, _IFT_IsotropicDamageMaterial_talpha); - return StructuralMaterial :: initializeFrom(ir); } @@ -380,28 +395,33 @@ IsotropicDamageMaterial :: giveInputRecord(DynamicInputRecord &input) } +void +IsotropicDamageMaterial::saveContext(DataStream &stream, ContextMode mode) +{ + StructuralMaterial::saveContext(stream, mode); + if ( ( mode & CM_Definition ) ) { + linearElasticMaterial->saveContext(stream, mode); + } +} -IsotropicDamageMaterialStatus :: IsotropicDamageMaterialStatus(int n, Domain *d, GaussPoint *g) : StructuralMaterialStatus(n, d, g) + +void +IsotropicDamageMaterial::restoreContext(DataStream &stream, ContextMode mode) { - kappa = tempKappa = 0.0; - damage = tempDamage = 0.0; - le = 0.0; - crack_angle = -1000.0; - crackVector.resize(3); - crackVector.zero(); -#ifdef keep_track_of_dissipated_energy - stressWork = tempStressWork = 0.0; - dissWork = tempDissWork = 0.0; -#endif + StructuralMaterial::restoreContext(stream, mode); + if ( ( mode & CM_Definition ) ) { + linearElasticMaterial->saveContext(stream, mode); + } } -IsotropicDamageMaterialStatus :: ~IsotropicDamageMaterialStatus() -{ } +IsotropicDamageMaterialStatus :: IsotropicDamageMaterialStatus(GaussPoint *g) : StructuralMaterialStatus(g) +{ +} void -IsotropicDamageMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +IsotropicDamageMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -427,7 +447,7 @@ IsotropicDamageMaterialStatus :: initTempStatus() StructuralMaterialStatus :: initTempStatus(); this->tempKappa = this->kappa; //mj 14 July 2010 - should be discussed with Borek !!! - //this->tempDamage = this->damage; + this->tempDamage = this->damage; #ifdef keep_track_of_dissipated_energy this->tempStressWork = this->stressWork; this->tempDissWork = this->dissWork; @@ -447,25 +467,12 @@ IsotropicDamageMaterialStatus :: updateYourself(TimeStep *tStep) #endif } -void -IsotropicDamageMaterialStatus :: giveCrackVector(FloatArray &answer) -{ - answer = crackVector; - answer.times(damage); -} - -contextIOResultType -IsotropicDamageMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +IsotropicDamageMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralMaterialStatus :: saveContext(stream, mode); - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write raw data if ( !stream.write(kappa) ) { THROW_CIOERR(CIO_IOERR); } @@ -484,21 +491,13 @@ IsotropicDamageMaterialStatus :: saveContext(DataStream &stream, ContextMode mod } #endif - - return CIO_OK; } -contextIOResultType -IsotropicDamageMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +IsotropicDamageMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralMaterialStatus :: restoreContext(stream, mode); - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data if ( !stream.read(kappa) ) { THROW_CIOERR(CIO_IOERR); } @@ -517,8 +516,6 @@ IsotropicDamageMaterialStatus :: restoreContext(DataStream &stream, ContextMode } #endif - - return CIO_OK; } #ifdef keep_track_of_dissipated_energy diff --git a/src/sm/Materials/isodamagemodel.h b/src/sm/Materials/isodamagemodel.h index 07026fcc9..04bcf95b1 100644 --- a/src/sm/Materials/isodamagemodel.h +++ b/src/sm/Materials/isodamagemodel.h @@ -41,9 +41,9 @@ #define keep_track_of_dissipated_energy #include "material.h" -#include "Materials/linearelasticmaterial.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/linearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" ///@name Input fields for IsotropicDamageMaterial //@{ @@ -63,94 +63,91 @@ class IsotropicDamageMaterialStatus : public StructuralMaterialStatus { protected: /// Scalar measure of the largest strain level ever reached in material. - double kappa; + double kappa = 0.; /// Non-equilibrated scalar measure of the largest strain level. - double tempKappa; + double tempKappa = 0.; /// Damage level of material. - double damage; + double damage = 0.; /// Non-equilibrated damage level of material. - double tempDamage; + double tempDamage = 0.; /** * Characteristic element length, * computed when damage initialized from direction of * maximum positive principal strain. Fixed during further loading. */ - double le; + double le = 0.; /// Angle characterizing the crack direction. - double crack_angle; + double crack_angle = -1000.0; /// Crack orientation normalized to damage magnitude. This is useful for plotting cracks as a vector field (paraview etc.). - FloatArray crackVector; + FloatArrayF<3> crackVector; #ifdef keep_track_of_dissipated_energy /// Density of total work done by stresses on strain increments. - double stressWork; + double stressWork = 0.; /// Non-equilibrated density of total work done by stresses on strain increments. - double tempStressWork; + double tempStressWork = 0.; /// Density of dissipated work. - double dissWork; + double dissWork = 0.; /// Non-equilibrated density of dissipated work. - double tempDissWork; + double tempDissWork = 0.; #endif public: /// Constructor - IsotropicDamageMaterialStatus(int n, Domain *d, GaussPoint *g); - /// Destructor - virtual ~IsotropicDamageMaterialStatus(); + IsotropicDamageMaterialStatus(GaussPoint *g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; /// Returns the last equilibrated scalar measure of the largest strain level. - double giveKappa() { return kappa; } + double giveKappa() const { return kappa; } /// Returns the temp. scalar measure of the largest strain level. - double giveTempKappa() { return tempKappa; } + double giveTempKappa() const { return tempKappa; } /// Sets the temp scalar measure of the largest strain level to given value. void setTempKappa(double newKappa) { tempKappa = newKappa; } /// Returns the last equilibrated damage level. - double giveDamage() { return damage; } + double giveDamage() const { return damage; } /// Returns the temp. damage level. - double giveTempDamage() { return tempDamage; } + double giveTempDamage() const { return tempDamage; } /// Sets the temp damage level to given value. void setTempDamage(double newDamage) { tempDamage = newDamage; } /// Returns characteristic length stored in receiver. - double giveLe() { return le; } + double giveLe() const { return le; } /// Sets characteristic length to given value. void setLe(double ls) { le = ls; } /// Returns crack angle stored in receiver. - double giveCrackAngle() { return crack_angle; } + double giveCrackAngle() const { return crack_angle; } /// Sets crack angle to given value. void setCrackAngle(double ca) { crack_angle = ca; } /// Returns crack vector stored in receiver. This is useful for plotting cracks as a vector field (paraview etc.). - void giveCrackVector(FloatArray &answer); + FloatArrayF<3> giveCrackVector() const { return crackVector * damage; } /// Sets crack vector to given value. This is useful for plotting cracks as a vector field (paraview etc.). - void setCrackVector(FloatArray cv) { crackVector = cv; } + void setCrackVector(const FloatArrayF<3> &cv) { crackVector = cv; } #ifdef keep_track_of_dissipated_energy /// Returns the density of total work of stress on strain increments. - double giveStressWork() { return stressWork; } + double giveStressWork() const { return stressWork; } /// Returns the temp density of total work of stress on strain increments. - double giveTempStressWork() { return tempStressWork; } + double giveTempStressWork() const { return tempStressWork; } /// Sets the density of total work of stress on strain increments to given value. void setTempStressWork(double w) { tempStressWork = w; } /// Returns the density of dissipated work. - double giveDissWork() { return dissWork; } + double giveDissWork() const { return dissWork; } /// Returns the density of temp dissipated work. - double giveTempDissWork() { return tempDissWork; } + double giveTempDissWork() const { return tempDissWork; } /// Sets the density of dissipated work to given value. void setTempDissWork(double w) { tempDissWork = w; } /// Computes the increment of total stress work and of dissipated work. void computeWork(GaussPoint *gp); #endif - // definition - virtual const char *giveClassName() const { return "IsotropicDamageMaterialModelStatus"; } + const char *giveClassName() const override { return "IsotropicDamageMaterialModelStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -164,23 +161,23 @@ class IsotropicDamageMaterial : public StructuralMaterial { protected: /// Coefficient of thermal dilatation. - double tempDillatCoeff; + double tempDillatCoeff = 0.; /// Maximum limit on omega. The purpose is elimination of a too compliant material which may cause convergence problems. Set to something like 0.99 if needed. - double maxOmega; + double maxOmega = 0.999999; /// Indicator of the type of permanent strain formulation (0 = standard damage with no permanent strain) - int permStrain; + int permStrain = 0; /// Reference to bulk (undamaged) material - LinearElasticMaterial *linearElasticMaterial; + LinearElasticMaterial *linearElasticMaterial = nullptr; /** * Variable controlling type of loading/unloading law, default set to idm_strainLevel * defines the two two possibilities: * - idm_strainLevelCR the unloading takes place, when strain level is smaller than the largest level ever reached; * - idm_damageLevelCR the unloading takes place, when damage level is smaller than the largest damage ever reached; */ - enum loaUnloCriterium { idm_strainLevelCR, idm_damageLevelCR } llcriteria; + enum loaUnloCriterium { idm_strainLevelCR, idm_damageLevelCR } llcriteria = idm_strainLevelCR; public: /// Constructor @@ -188,37 +185,52 @@ class IsotropicDamageMaterial : public StructuralMaterial /// Destructor virtual ~IsotropicDamageMaterial(); - virtual int hasNonLinearBehaviour() { return 1; } - - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual const char *giveClassName() const { return "IsotropicDamageMaterial"; } + bool hasMaterialModeCapability(MaterialMode mode) const override; + const char *giveClassName() const override { return "IsotropicDamageMaterial"; } /// Returns reference to undamaged (bulk) material LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_StressControl(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, const IntArray &strainControl, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<4> giveRealStressVector_PlaneStrain( const FloatArrayF<4> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArray giveRealStressVector_StressControl(const FloatArray &strain, const IntArray &strainControl, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *, TimeStep *); - virtual double evaluatePermanentStrain(double kappa, double omega) { return 0.; } + FloatArrayF<6> giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; + virtual double evaluatePermanentStrain(double kappa, double omega) const { return 0.; } /** * Returns the value of material property 'aProperty'. Property must be identified @@ -228,7 +240,7 @@ class IsotropicDamageMaterial : public StructuralMaterial * @param gp Integration point, * @return Property value. */ - virtual double give(int aProperty, GaussPoint *gp); + double give(int aProperty, GaussPoint *gp) const override; /** * Computes the equivalent strain measure from given strain vector (full form). * @param[out] kappa Return parameter, containing the corresponding equivalent strain. @@ -236,14 +248,14 @@ class IsotropicDamageMaterial : public StructuralMaterial * @param gp Integration point. * @param tStep Time step. */ - virtual void computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) = 0; + virtual double computeEquivalentStrain(const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const = 0; /**Computes derivative of the equivalent strain with regards to strain * @param[out] answer Contains the resulting derivative. * @param strain Strain vector. * @param gp Integration point. * @param tStep Time step. */ - virtual void computeEta(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { OOFEM_ERROR("not implemented"); } + virtual void computeEta(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("not implemented"); } /** * Computes the value of damage parameter omega, based on given value of equivalent strain. * @param[out] omega Contains result. @@ -251,13 +263,19 @@ class IsotropicDamageMaterial : public StructuralMaterial * @param strain Total strain in full form. * @param gp Integration point. */ - virtual void computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *gp) = 0; + virtual double computeDamageParam(double kappa, const FloatArray &strain, GaussPoint *gp) const = 0; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - MaterialStatus *CreateStatus(GaussPoint *gp) const { return new IsotropicDamageMaterialStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new IsotropicDamageMaterialStatus(gp); } + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, + TimeStep *tStep) const override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + protected: /** * Abstract service allowing to perform some initialization, when damage first appear. @@ -265,7 +283,7 @@ class IsotropicDamageMaterial : public StructuralMaterial * @param totalStrainVector Current total strain vector. * @param gp Integration point. */ - virtual void initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) { } + virtual void initDamaged(double kappa, FloatArray &totalStrainVector, GaussPoint *gp) const { } /** * Returns the value of derivative of damage function @@ -275,22 +293,14 @@ class IsotropicDamageMaterial : public StructuralMaterial * @param kappa Equivalent strain measure. * @param gp Integration point. */ - virtual double damageFunctionPrime(double kappa, GaussPoint *gp) { + virtual double damageFunctionPrime(double kappa, GaussPoint *gp) const { OOFEM_ERROR("not implemented"); return 0; } - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp,TimeStep *tStep) const override; + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); }; } // end namespace oofem #endif // isodamagemodel_h diff --git a/src/sm/Materials/isolinearelasticmaterial.C b/src/sm/Materials/isolinearelasticmaterial.C index 4744c95c9..7cffef714 100644 --- a/src/sm/Materials/isolinearelasticmaterial.C +++ b/src/sm/Materials/isolinearelasticmaterial.C @@ -34,49 +34,59 @@ #include "linearelasticmaterial.h" #include "isolinearelasticmaterial.h" -#include "../sm/CrossSections/simplecrosssection.h" -#include "../sm/Materials/structuralms.h" +#include "sm/CrossSections/simplecrosssection.h" +#include "sm/Materials/structuralms.h" #include "floatmatrix.h" #include "gausspoint.h" #include "classfactory.h" #include "dynamicinputrecord.h" +#include "contextioerr.h" namespace oofem { REGISTER_Material(IsotropicLinearElasticMaterial); +IsotropicLinearElasticMaterial :: IsotropicLinearElasticMaterial(int n, Domain *d) : + LinearElasticMaterial(n, d), MixedPressureMaterialExtensionInterface(d) +{ } + IsotropicLinearElasticMaterial :: IsotropicLinearElasticMaterial(int n, Domain *d, double _E, double _nu) : - LinearElasticMaterial(n, d) + LinearElasticMaterial(n, d), MixedPressureMaterialExtensionInterface(d), + E(_E), + nu(_nu), + G( E / ( 2.0 * ( 1. + nu ) ) ), + a(0.) { - E = _E; - nu = _nu; - - // compute value of shear modulus - G = E / ( 2.0 * ( 1. + nu ) ); + this->initTangents(); } -IRResultType -IsotropicLinearElasticMaterial :: initializeFrom(InputRecord *ir) +void +IsotropicLinearElasticMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - double value; - // we use rather object's member data than to store data into slow - // key-val dictionary with lot of memory allocations + LinearElasticMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, E, _IFT_IsotropicLinearElasticMaterial_e); IR_GIVE_FIELD(ir, nu, _IFT_IsotropicLinearElasticMaterial_n); - IR_GIVE_FIELD(ir, value, _IFT_IsotropicLinearElasticMaterial_talpha); - propertyDictionary.add(tAlpha, value); + IR_GIVE_FIELD(ir, a, _IFT_IsotropicLinearElasticMaterial_talpha); + // propertyDictionary.add(tAlpha, a); // compute value of shear modulus G = E / ( 2.0 * ( 1. + nu ) ); + this->initTangents(); +} - return LinearElasticMaterial :: initializeFrom(ir); - ; +void +IsotropicLinearElasticMaterial :: initTangents() +{ + double K = E / ( 3.0 * ( 1. - 2. * nu ) ); + this->tangent = 2 * G * I_dev6 + K * I6_I6; + this->computesSubTangents(); + this->alpha = { + a, a, a, 0., 0., 0. + }; } - void IsotropicLinearElasticMaterial :: giveInputRecord(DynamicInputRecord &input) { @@ -85,17 +95,51 @@ IsotropicLinearElasticMaterial :: giveInputRecord(DynamicInputRecord &input) input.setField(this->E, _IFT_IsotropicLinearElasticMaterial_e); input.setField(this->nu, _IFT_IsotropicLinearElasticMaterial_n); - input.setField(this->propertyDictionary.at(tAlpha), _IFT_IsotropicLinearElasticMaterial_talpha); + input.setField(this->a, _IFT_IsotropicLinearElasticMaterial_talpha); +} + + +void IsotropicLinearElasticMaterial :: saveContext(DataStream &stream, ContextMode mode) +{ + LinearElasticMaterial :: saveContext(stream, mode); + + if ( ( mode & CM_Definition ) ) { + if ( !stream.write(E) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(nu) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.write(a) ) { + THROW_CIOERR(CIO_IOERR); + } + } +} + + +void IsotropicLinearElasticMaterial :: restoreContext(DataStream &stream, ContextMode mode) +{ + LinearElasticMaterial :: restoreContext(stream, mode); + + if ( mode & CM_Definition ) { + if ( !stream.read(E) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(nu) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( !stream.read(a) ) { + THROW_CIOERR(CIO_IOERR); + } + } + G = E / ( 2.0 * ( 1. + nu ) ); + this->initTangents(); } double -IsotropicLinearElasticMaterial :: give(int aProperty, GaussPoint *gp) -// -// Returns the value of the property aProperty (e.g. the Young's modulus -// 'E') of the receiver. -// +IsotropicLinearElasticMaterial :: give(int aProperty, GaussPoint *gp) const { if ( ( aProperty == NYxy ) || ( aProperty == NYxz ) || ( aProperty == NYyz ) ) { return nu; @@ -120,138 +164,140 @@ IsotropicLinearElasticMaterial :: give(int aProperty, GaussPoint *gp) } +FloatMatrixF<3,3> +IsotropicLinearElasticMaterial :: givePlaneStressStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const +{ + if ( ( tStep->giveIntrinsicTime() < this->castingTime ) ) { + return tangentPlaneStress * (1. - this->preCastStiffnessReduction); + } else { + return tangentPlaneStress; + } +} + + +FloatMatrixF<4,4> +IsotropicLinearElasticMaterial :: givePlaneStrainStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const +{ + if ( ( tStep->giveIntrinsicTime() < this->castingTime ) ) { + return tangentPlaneStrain * (1. - this->preCastStiffnessReduction); + } else { + return tangentPlaneStrain; + } +} + + +FloatMatrixF<1,1> +IsotropicLinearElasticMaterial :: give1dStressStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const +{ + double e = this->E; + if ( tStep->giveIntrinsicTime() < this->castingTime ) { + e *= 1. - this->preCastStiffnessReduction; + } + return {e}; +} + + + + + + + + void -IsotropicLinearElasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) +IsotropicLinearElasticMaterial :: giveDeviatoric3dMaterialStiffnessMatrix(FloatMatrix &answer, + MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) // // forceElasticResponse ignored - always elastic // { - double e, nu, ee; + double mu = this->E / 2 / ( 1. + this->nu ); - e = this->E; - nu = this->nu; - ee = e / ( ( 1. + nu ) * ( 1. - 2. * nu ) ); answer.resize(6, 6); answer.zero(); - answer.at(1, 1) = 1. - nu; - answer.at(1, 2) = nu; - answer.at(1, 3) = nu; - answer.at(2, 1) = nu; - answer.at(2, 2) = 1. - nu; - answer.at(2, 3) = nu; - answer.at(3, 1) = nu; - answer.at(3, 2) = nu; - answer.at(3, 3) = 1. - nu; - - answer.at(4, 4) = ( 1. - 2. * nu ) * 0.5; - answer.at(5, 5) = ( 1. - 2. * nu ) * 0.5; - answer.at(6, 6) = ( 1. - 2. * nu ) * 0.5; + answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = 4. / 3.; + answer.at(1, 2) = answer.at(1, 3) = -2. / 3.; + answer.at(2, 1) = answer.at(2, 3) = -2. / 3.; + answer.at(3, 1) = answer.at(3, 2) = -2. / 3.; - answer.times(ee); + answer.at(4, 4) = answer.at(5, 5) = answer.at(6, 6) = 1.0; - if ( ( tStep->giveIntrinsicTime() < this->castingTime ) ) { - answer.times(1. - this->preCastStiffnessReduction); - } + answer.times(mu); } void -IsotropicLinearElasticMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) +IsotropicLinearElasticMaterial :: giveDeviatoricPlaneStrainStiffMtrx(FloatMatrix &answer, + MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) { - this->giveStatus(gp); - double e, nu, ee, shear; + answer.resize(4, 4); - e = this->E; - nu = this->nu; - ee = e / ( 1. - nu * nu ); - shear = this->G; + double mu = this->E / 2 / ( 1. + this->nu ); - answer.resize(3, 3); answer.zero(); + answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = 4. / 3.; + answer.at(1, 2) = answer.at(1, 3) = -2. / 3.; + answer.at(2, 1) = answer.at(2, 3) = -2. / 3.; + answer.at(3, 1) = answer.at(3, 2) = -2. / 3.; - answer.at(1, 1) = ee; - answer.at(1, 2) = nu * ee; - answer.at(2, 1) = nu * ee; - answer.at(2, 2) = ee; - answer.at(3, 3) = shear; + answer.at(4, 4) = 1.0; - if ( ( tStep->giveIntrinsicTime() < this->castingTime ) ) { - answer.times(1. - this->preCastStiffnessReduction); - } + answer.times(mu); } + void -IsotropicLinearElasticMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) +IsotropicLinearElasticMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, double pressure, TimeStep *tStep) { - double e, nu, ee, shear; - - e = this->E; - nu = this->nu; - ee = e / ( 1.0 + nu ) / ( 1. - 2.0 * nu ); - shear = this->G; + FloatArray strainVector; + FloatMatrix d; + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - answer.resize(4, 4); - answer.zero(); + this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Total); - answer.at(1, 1) = ee * ( 1.0 - nu ); - answer.at(1, 2) = nu * ee; - answer.at(1, 3) = nu * ee; - answer.at(2, 1) = nu * ee; - answer.at(2, 2) = ee * ( 1.0 - nu ); - answer.at(2, 3) = nu * ee; - answer.at(3, 1) = ee * nu; - answer.at(3, 2) = ee * nu; - answer.at(3, 3) = ee * ( 1.0 - nu ); - answer.at(4, 4) = shear; + this->giveDeviatoric3dMaterialStiffnessMatrix(d, TangentStiffness, gp, tStep); + answer.beProductOf(d, strainVector); + answer.at(1) -= pressure; + answer.at(2) -= pressure; + answer.at(3) -= pressure; - if ( ( tStep->giveIntrinsicTime() < this->castingTime ) ) { - answer.times(1. - this->preCastStiffnessReduction); - } + // update gp + status->letTempStrainVectorBe(reducedStrain); + status->letTempStressVectorBe(answer); } + void -IsotropicLinearElasticMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) +IsotropicLinearElasticMaterial :: giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, double pressure, TimeStep *tStep) { - answer.resize(1, 1); - answer.at(1, 1) = this->E; + FloatArray strainVector; + FloatMatrix d; + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - if ( ( tStep->giveIntrinsicTime() < this->castingTime ) ) { - answer.times(1. - this->preCastStiffnessReduction); - } -} + this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Total); + this->giveDeviatoricPlaneStrainStiffMtrx(d, TangentStiffness, gp, tStep); + answer.beProductOf(d, strainVector); + answer.at(1) -= pressure; + answer.at(2) -= pressure; + answer.at(3) -= pressure; -void -IsotropicLinearElasticMaterial :: giveThermalDilatationVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep) -// -// returns a FloatArray(6) of initial strain vector -// eps_0 = {exx_0, eyy_0, ezz_0, gyz_0, gxz_0, gxy_0}^T -// caused by unit temperature in direction of -// gp (element) local axes -// -{ - double alpha = this->give(tAlpha, gp); - answer.resize(6); - answer.zero(); - answer.at(1) = alpha; - answer.at(2) = alpha; - answer.at(3) = alpha; + + // update gp + status->letTempStrainVectorBe(reducedStrain); + status->letTempStressVectorBe(answer); } } // end namespace oofem diff --git a/src/sm/Materials/isolinearelasticmaterial.h b/src/sm/Materials/isolinearelasticmaterial.h index 9b72d4a34..791384f08 100644 --- a/src/sm/Materials/isolinearelasticmaterial.h +++ b/src/sm/Materials/isolinearelasticmaterial.h @@ -39,9 +39,13 @@ #include "dictionary.h" #include "floatarray.h" #include "floatmatrix.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" #include "qcmaterialextensioninterface.h" +#include "MixedPressure/mixedpressurematerialextensioninterface.h" + ///@name Input fields for IsotropicLinearElasticMaterial //@{ #define _IFT_IsotropicLinearElasticMaterial_Name "isole" @@ -67,15 +71,17 @@ class GaussPoint; * - Returning a material property (method 'give'). Only for non-standard elements. * - Returning real stress state vector(tensor) at gauss point for 3d - case. */ - class IsotropicLinearElasticMaterial : public LinearElasticMaterial, public QCMaterialExtensionInterface +class IsotropicLinearElasticMaterial : public LinearElasticMaterial, public QCMaterialExtensionInterface, public MixedPressureMaterialExtensionInterface { protected: /// Young's modulus. - double E; + double E = 0; /// Poisson's ratio. - double nu; + double nu = 0; /// Shear modulus. - double G; + double G = 0; + /// Alpha + double a = 0; public: /** @@ -84,7 +90,7 @@ class GaussPoint; * @param n material model number in domain * @param d domain which receiver belongs to */ - IsotropicLinearElasticMaterial(int n, Domain *d) : LinearElasticMaterial(n, d) { } + IsotropicLinearElasticMaterial(int n, Domain *d); /** * Creates a new IsotropicLinearElasticMaterial class instance * with given number belonging to domain d. @@ -94,60 +100,46 @@ class GaussPoint; * @param nu Poisson ratio. */ IsotropicLinearElasticMaterial(int n, Domain *d, double E, double nu); - /// Destructor. - virtual ~IsotropicLinearElasticMaterial() { } - /** - * Returns a vector of coefficients of thermal dilatation in direction - * of each material principal (local) axis. - * @param answer Vector of thermal dilatation coefficients. - * @param gp Integration point. - * @param tStep Time step (most models are able to respond only when tStep is current time step). - */ - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); - - // identification and auxiliary functions - virtual const char *giveClassName() const { return "IsotropicLinearElasticMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_IsotropicLinearElasticMaterial_Name; } + const char *giveClassName() const override { return "IsotropicLinearElasticMaterial"; } + const char *giveInputRecordName() const override { return _IFT_IsotropicLinearElasticMaterial_Name; } /** * Initializes receiver according to object description stored in input record. * The E modulus (keyword "E"), Poisson ratio ("nu") and coefficient of thermal dilatation * alpha ("talpha") are read. The parent class instanciateFrom method is called. */ - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual double give(int aProperty, GaussPoint *gp); + /// Initialized fixed size tangents. Called by ctor and initializeFrom. + void initTangents(); + + double give(int aProperty, GaussPoint *gp) const override; /// Returns Young's modulus. - double giveYoungsModulus() { return E; } + double giveYoungsModulus() const { return E; } /// Returns Poisson's ratio. - double givePoissonsRatio() { return nu; } + double givePoissonsRatio() const { return nu; } /// Returns the shear elastic modulus @f$ G = \frac{E}{2(1+\nu)} @f$. - double giveShearModulus() { return G; } + double giveShearModulus() const override { return G; } /// Returns the bulk elastic modulus @f$ K = \frac{E}{3(1-2\nu)} @f$. - double giveBulkModulus() { return E / ( 3. * ( 1. - 2. * nu ) ); } - - virtual void give3dMaterialStiffnessMatrix(FloatMatrix & answer, - MatResponseMode, - GaussPoint * gp, - TimeStep * tStep); + double giveBulkModulus() const { return E / ( 3. * ( 1. - 2. * nu ) ); } - virtual void givePlaneStressStiffMtrx(FloatMatrix & answer, - MatResponseMode, GaussPoint * gp, - TimeStep * tStep); + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode, GaussPoint * gp, + TimeStep * tStep) const override; - virtual void givePlaneStrainStiffMtrx(FloatMatrix & answer, - MatResponseMode, GaussPoint * gp, - TimeStep * tStep); + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode, GaussPoint * gp, + TimeStep * tStep) const override; - virtual void give1dStressStiffMtrx(FloatMatrix & answer, - MatResponseMode, GaussPoint * gp, - TimeStep * tStep); + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode, GaussPoint * gp, + TimeStep * tStep) const override; /** * Computes bulk modulus from given Young's modulus and Poisson's ratio. @@ -171,20 +163,41 @@ class GaussPoint; return young / ( 2. * ( 1. + nu ) ); } + double giveQcElasticParamneter() override { return E; } + double giveQcPlasticParamneter() override { return std :: numeric_limits< float > :: infinity(); } - virtual double giveQcElasticParamneter(){return E;} - virtual double giveQcPlasticParamneter(){return std::numeric_limits::infinity();} - - virtual Interface *giveInterface(InterfaceType t) { + Interface *giveInterface(InterfaceType t) override { if ( t == QCMaterialExtensionInterfaceType ) { - // return static_cast< QCMaterialExtensionInterface * >(this); - return this; + return static_cast< QCMaterialExtensionInterface * >(this); + } else if ( t == MixedPressureMaterialExtensionInterfaceType ) { + return static_cast< MixedPressureMaterialExtensionInterface * >( this ); } else { - return NULL; + return nullptr; } } - + + /** + ** support for mixed u-p formulation + ** + */ + + void giveDeviatoric3dMaterialStiffnessMatrix(FloatMatrix & answer, + MatResponseMode, + GaussPoint * gp, + TimeStep * tStep) override; + + + void giveDeviatoricPlaneStrainStiffMtrx(FloatMatrix & answer, + MatResponseMode, GaussPoint * gp, + TimeStep * tStep) override; + + + void giveInverseOfBulkModulus(double &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override { answer = 3. * ( 1. - 2. * nu ) / E; } + + void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, double pressure, TimeStep *tStep) override; + void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, double pressure, TimeStep *tStep) override; + }; } // end namespace oofem #endif // isolinearelasticmaterial_h diff --git a/src/sm/Materials/j2mat.C b/src/sm/Materials/j2mat.C index f0469c3bf..189cf11f5 100644 --- a/src/sm/Materials/j2mat.C +++ b/src/sm/Materials/j2mat.C @@ -46,28 +46,17 @@ REGISTER_Material(J2Mat); J2Mat :: J2Mat(int n, Domain *d) : MPlasticMaterial2(n, d) { - // - // constructor - // - kinematicHardeningFlag = isotropicHardeningFlag = 0; linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); this->nsurf = 1; } -J2Mat :: ~J2Mat() -{ } - -IRResultType -J2Mat :: initializeFrom(InputRecord *ir) +void +J2Mat :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro double value; - result = MPlasticMaterial2 :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - - result = linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) return result; + MPlasticMaterial2 :: initializeFrom(ir); + linearElasticMaterial->initializeFrom(ir); IR_GIVE_FIELD(ir, value, _IFT_J2Mat_ry); k = value / sqrt(3.0); @@ -93,20 +82,17 @@ J2Mat :: initializeFrom(InputRecord *ir) } else { this->rmType = mpm_CuttingPlane; } - - - return IRRT_OK; } MaterialStatus * J2Mat :: CreateStatus(GaussPoint *gp) const { - return new MPlasticMaterial2Status(1, this->giveDomain(), gp, this->giveSizeOfReducedHardeningVarsVector(gp)); + return new MPlasticMaterial2Status(gp, this->giveSizeOfReducedHardeningVarsVector(gp)); } int -J2Mat :: giveSizeOfFullHardeningVarsVector() +J2Mat :: giveSizeOfFullHardeningVarsVector() const { /* Returns the size of hardening variables vector */ int size = 0; @@ -142,7 +128,7 @@ J2Mat :: giveSizeOfReducedHardeningVarsVector(GaussPoint *gp) const double J2Mat :: computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, - const FloatArray &strainSpaceHardeningVars) + const FloatArray &strainSpaceHardeningVars) const { double f; FloatArray helpVector, backStress; @@ -166,7 +152,7 @@ J2Mat :: computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stress void J2Mat :: computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, const FloatArray &stressVector, - const FloatArray &strainSpaceHardeningVars) + const FloatArray &strainSpaceHardeningVars) const { /* stress gradient of yield function in full stress - strain space */ @@ -213,7 +199,7 @@ J2Mat :: computeStressGradientVector(FloatArray &answer, functType ftype, int is void J2Mat :: computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, const FloatArray &stress, const FloatArray &dlambda, - const FloatArray &dplasticStrain, const IntArray &activeConditionMap) + const FloatArray &dplasticStrain, const IntArray &activeConditionMap) const { int size = this->giveSizeOfReducedHardeningVarsVector(gp); answer.resize(size); @@ -234,7 +220,7 @@ J2Mat :: computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, void J2Mat :: computeKGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables) + const FloatArray &strainSpaceHardeningVariables) const { int kcount = 0, size = this->giveSizeOfReducedHardeningVarsVector(gp); FloatArray reducedKinematicGrad; @@ -264,7 +250,7 @@ void J2Mat :: computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, GaussPoint *gp, const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, - const FloatArray &gamma) + const FloatArray &gamma) const { int rsize = StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ); answer.resize(giveSizeOfReducedHardeningVarsVector(gp), rsize); @@ -288,7 +274,7 @@ J2Mat :: computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPoint const IntArray &activeConditionMap, const FloatArray &fullStressVector, const FloatArray &strainSpaceHardeningVars, - const FloatArray &gamma) + const FloatArray &gamma) const { int size = this->giveSizeOfReducedHardeningVarsVector(gp); answer.resize(size, 1); @@ -314,7 +300,7 @@ J2Mat :: computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPoint void J2Mat :: computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int isurf, GaussPoint *gp, const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVars) + const FloatArray &strainSpaceHardeningVars) const { int size; int imask, jmask; @@ -412,7 +398,7 @@ J2Mat :: computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int isurf, void J2Mat :: computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables) + const FloatArray &strainSpaceHardeningVariables) const { // something will be here for k1 vector int size = giveSizeOfReducedHardeningVarsVector(gp); @@ -435,7 +421,7 @@ J2Mat :: computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int i, Gau int -J2Mat :: hasHardening() +J2Mat :: hasHardening() const { return ( this->kinematicHardeningFlag || this->isotropicHardeningFlag ); } @@ -464,7 +450,7 @@ J2Mat :: computeJ2InvariantAt(const FloatArray &stressVector) void J2Mat :: giveStressBackVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &strainSpaceHardeningVars) + const FloatArray &strainSpaceHardeningVars) const { /* returns part of hardening vector corresponding to kinematic hardening */ if ( this->kinematicHardeningFlag ) { @@ -488,7 +474,7 @@ J2Mat :: giveStressBackVector(FloatArray &answer, GaussPoint *gp, double -J2Mat :: giveIsotropicHardeningVar(GaussPoint *gp, const FloatArray &strainSpaceHardeningVars) +J2Mat :: giveIsotropicHardeningVar(GaussPoint *gp, const FloatArray &strainSpaceHardeningVars) const { /* returns value in hardening vector corresponding to isotropic hardening */ if ( !isotropicHardeningFlag ) { diff --git a/src/sm/Materials/j2mat.h b/src/sm/Materials/j2mat.h index 58c13c8e4..085e635f1 100644 --- a/src/sm/Materials/j2mat.h +++ b/src/sm/Materials/j2mat.h @@ -35,7 +35,7 @@ #ifndef j2mat_h #define j2mat_h -#include "Materials/ConcreteMaterials/mplasticmaterial2.h" +#include "sm/Materials/ConcreteMaterials/mplasticmaterial2.h" ///@name Input fields for J2Mat //@{ @@ -57,62 +57,58 @@ class Domain; class J2Mat : public MPlasticMaterial2 { protected: - int kinematicHardeningFlag, isotropicHardeningFlag; - double kinematicModuli, isotropicModuli; - double k; + int kinematicHardeningFlag = 0, isotropicHardeningFlag = 0; + double kinematicModuli = 0., isotropicModuli = 0.; + double k = 0.; public: J2Mat(int n, Domain * d); - virtual ~J2Mat(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveInputRecordName() const { return _IFT_J2Mat_Name; } - virtual const char *giveClassName() const { return "J2Mat"; } + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_J2Mat_Name; } + const char *giveClassName() const override { return "J2Mat"; } - virtual int giveSizeOfFullHardeningVarsVector(); - virtual int giveSizeOfReducedHardeningVarsVector(GaussPoint *gp) const; - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } + int giveSizeOfFullHardeningVarsVector() const override; + int giveSizeOfReducedHardeningVarsVector(GaussPoint *gp) const override; + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: - virtual int giveMaxNumberOfActiveYieldConds(GaussPoint *gp) { return 2; } - - virtual double computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, - const FloatArray &strainSpaceHardeningVars); - - virtual void computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, - const FloatArray &stressVector, const FloatArray &strainSpaceHardeningVars); - - virtual void computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, - const FloatArray &stress, const FloatArray &dlambda, - const FloatArray &dplasticStrain, const IntArray &activeConditionMap); - virtual void computeKGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables); - - virtual void computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, GaussPoint *gp, const IntArray &activeConditionMap, - const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVars, - const FloatArray &gamma); - virtual void computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPoint *gp, int actSurf, - const IntArray &activeConditionMap, - const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVars, - const FloatArray &gamma); - virtual int hasHardening(); - /* virtual void computeReducedGradientMatrix (FloatMatrix& answer, int isurf, - * GaussPoint *gp, - * const FloatArray& stressVector, - * const FloatArray& stressSpaceHardeningVars) = 0;*/ - virtual void computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables); - virtual void computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, - const FloatArray &strainSpaceHardeningVariables); + int giveMaxNumberOfActiveYieldConds(GaussPoint *gp) const override { return 2; } + + double computeYieldValueAt(GaussPoint *gp, int isurf, const FloatArray &stressVector, + const FloatArray &strainSpaceHardeningVars) const override; + + void computeStressGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, + const FloatArray &stressVector, const FloatArray &strainSpaceHardeningVars) const override; + + void computeStrainHardeningVarsIncrement(FloatArray &answer, GaussPoint *gp, + const FloatArray &stress, const FloatArray &dlambda, + const FloatArray &dplasticStrain, const IntArray &activeConditionMap) const override; + void computeKGradientVector(FloatArray &answer, functType ftype, int isurf, GaussPoint *gp, FloatArray &fullStressVector, + const FloatArray &strainSpaceHardeningVariables) const override; + + void computeReducedHardeningVarsSigmaGradient(FloatMatrix &answer, GaussPoint *gp, const IntArray &activeConditionMap, + const FloatArray &fullStressVector, + const FloatArray &strainSpaceHardeningVars, + const FloatArray &gamma) const override; + void computeReducedHardeningVarsLamGradient(FloatMatrix &answer, GaussPoint *gp, int actSurf, + const IntArray &activeConditionMap, + const FloatArray &fullStressVector, + const FloatArray &strainSpaceHardeningVars, + const FloatArray &gamma) const override; + int hasHardening() const override; + + void computeReducedSSGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, + const FloatArray &strainSpaceHardeningVariables) const override; + void computeReducedSKGradientMatrix(FloatMatrix &gradientMatrix, int i, GaussPoint *gp, const FloatArray &fullStressVector, + const FloatArray &strainSpaceHardeningVariables) const override; // auxiliary function static double computeJ2InvariantAt(const FloatArray &stressVector); - double giveIsotropicHardeningVar(GaussPoint *gp, const FloatArray &strainSpaceHardeningVars); - void giveStressBackVector(FloatArray &answer, GaussPoint *gp, const FloatArray &strainSpaceHardeningVars); + double giveIsotropicHardeningVar(GaussPoint *gp, const FloatArray &strainSpaceHardeningVars) const; + void giveStressBackVector(FloatArray &answer, GaussPoint *gp, const FloatArray &strainSpaceHardeningVars) const; }; } // end namespace oofem #endif // j2mat_h diff --git a/src/sm/Materials/latticedamage2d.C b/src/sm/Materials/latticedamage2d.C deleted file mode 100644 index f574a3461..000000000 --- a/src/sm/Materials/latticedamage2d.C +++ /dev/null @@ -1,953 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "latticedamage2d.h" -#include "gausspoint.h" -#include "floatmatrix.h" -#include "floatarray.h" -#include "datastream.h" -#include "contextioerr.h" -#include "mathfem.h" -#include "Elements/latticestructuralelement.h" -#include "Materials/isolinearelasticmaterial.h" -#include "staggeredproblem.h" -#include "classfactory.h" -#ifdef __TM_MODULE - #include "../tm/latticetransportelement.h" -#endif - -#include - -namespace oofem { -REGISTER_Material(LatticeDamage2d); - -LatticeDamage2d :: LatticeDamage2d(int n, Domain *d) : StructuralMaterial(n, d), RandomMaterialExtensionInterface() -{ } - - -LatticeDamage2d :: ~LatticeDamage2d() -{ } - -int -LatticeDamage2d :: hasMaterialModeCapability(MaterialMode mode) -{ - return mode == _2dLattice; -} - - -IRResultType -LatticeDamage2d :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - - result = RandomMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - - double value = 0.; - IR_GIVE_FIELD(ir, value, _IFT_IsotropicLinearElasticMaterial_talpha); - propertyDictionary.add(tAlpha, value); - - IR_GIVE_FIELD(ir, eNormal, _IFT_LatticeDamage2d_eNormal); - - cAlpha = 0; - IR_GIVE_OPTIONAL_FIELD(ir, cAlpha, _IFT_LatticeDamage2d_calpha); - - - //factor which relates the shear stiffness to the normal stiffness. Default is 1 - alphaOne = 1.; - IR_GIVE_OPTIONAL_FIELD(ir, alphaOne, _IFT_LatticeDamage2d_alphaOne); - eShear = alphaOne * eNormal; - - //Parameter which is used for the definition of the moment. - alphaTwo = 1.; - IR_GIVE_OPTIONAL_FIELD(ir, alphaTwo, _IFT_LatticeDamage2d_alphaTwo); - - eTorsion = alphaTwo * eNormal; - - localRandomType = 0; //Default: No local random field - IR_GIVE_OPTIONAL_FIELD(ir, localRandomType, _IFT_LatticeDamage2d_localrandomtype); - if ( localRandomType == 1 ) { //Gaussian random generator - coefficientOfVariation = 0.; - IR_GIVE_FIELD(ir, coefficientOfVariation, _IFT_LatticeDamage2d_coefficientOfVariation); - } - - e0Mean = 0; - IR_GIVE_FIELD(ir, e0Mean, _IFT_LatticeDamage2d_e0Mean); - - IR_GIVE_FIELD(ir, coh, _IFT_LatticeDamage2d_coh); - IR_GIVE_FIELD(ir, ec, _IFT_LatticeDamage2d_ec); - - softeningType = 0; - IR_GIVE_FIELD(ir, softeningType, _IFT_LatticeDamage2d_softeningType); - - if ( softeningType == 1 || softeningType == 3 ) { //linear or exponential softening - IR_GIVE_FIELD(ir, wf, _IFT_LatticeDamage2d_wf); - } else if ( softeningType == 2 ) { //bilinear softening - IR_GIVE_FIELD(ir, wf, _IFT_LatticeDamage2d_wf); - wfOne = 0.15 * wf; - IR_GIVE_OPTIONAL_FIELD(ir, wfOne, _IFT_LatticeDamage2d_wfOne); - e0OneMean = 0.3 * e0Mean; - IR_GIVE_OPTIONAL_FIELD(ir, e0OneMean, _IFT_LatticeDamage2d_e0OneMean); - } else { - OOFEM_WARNING("Unknown softening type"); - return IRRT_BAD_FORMAT; - } - - this->biotCoefficient = 0.; - IR_GIVE_OPTIONAL_FIELD(ir, this->biotCoefficient, _IFT_LatticeDamage2d_bio); - - this->biotType = 0; - IR_GIVE_OPTIONAL_FIELD(ir, this->biotType, _IFT_LatticeDamage2d_btype); - - return IRRT_OK; -} - -void -LatticeDamage2d :: computeEquivalentStrain(double &tempEquivStrain, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) -{ - if ( strain.isEmpty() ) { - tempEquivStrain = 0.; - return; - } - - //LatticeDamage2dStatus *status = static_cast< LatticeDamage2dStatus * >( this->giveStatus(gp) ); - const double e0 = this->give(e0_ID, gp) * this->e0Mean; - - double paramA, paramB, paramC; - - paramA = 0.5 * ( e0 + ec * e0 ); - paramB = ( coh * e0 ) / sqrt( 1. - pow( ( ec * e0 - e0 ) / ( e0 + ec * e0 ), 2. ) ); - paramC = 0.5 * ( this->ec * e0 - e0 ); - - //double equivStrain = status->giveEquivalentStrain(); - tempEquivStrain = sqrt( pow(this->alphaOne * strain.at(2) / paramB, 2.) + pow( ( strain.at(1) + paramC ) / paramA, 2. ) ) * paramA - paramC; -} - -void -LatticeDamage2d :: computeDamageParam(double &omega, double tempKappa, const FloatArray &strain, GaussPoint *gp) -{ - double le = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveLength(); - const double e0 = this->give(e0_ID, gp) * this->e0Mean; - omega = 0.0; - - int nite = 0; - double R, Lhs, Ft, help; - - if ( softeningType == 1 ) { //linear - if ( tempKappa >= e0 && tempKappa < this->wf / le ) { - //linear stress-crack opening relation - //check if input parameter make sense - if ( this->wf / le <= e0 ) { - OOFEM_ERROR("e0>wf/Le \n Possible solutions: Increase fracture energy or reduce element size"); - } - - omega = ( 1. - e0 / tempKappa ) / ( 1. - e0 / ( this->wf / le ) ); - } else if ( tempKappa >= this->wf / le ) { - omega = 1.; - } else { - omega = 0.; - } - } else if ( softeningType == 2 ) { //bilinear softening - double helpStrain = 0.3 * e0; - - //Check if input parameter make sense - if ( e0 > wfOne / le ) { - OOFEM_ERROR("parameter wf1 is too small"); - } else if ( wfOne / le > this->wf / le ) { - OOFEM_ERROR("parameter wf is too small"); - } - - // - if ( tempKappa > e0 ) { - omega = ( 1 - e0 / tempKappa ) / ( ( helpStrain - e0 ) / this->wfOne * le + 1. ); - - if ( omega * tempKappa * le > 0 && omega * tempKappa * le < this->wfOne ) { - return; - } else { - omega = ( 1. - helpStrain / tempKappa - helpStrain * this->wfOne / ( tempKappa * ( this->wf - this->wfOne ) ) ) / ( 1. - helpStrain * le / ( this->wf - this->wfOne ) ); - - if ( omega * tempKappa * le >= this->wfOne && omega * tempKappa * le < this->wf ) { - return; - } - } - - if ( omega > 1. ) { - omega = 1.; - } else if ( omega < 0 ) { - omega = 0; - } - } else { - omega = 0.; - } - } else if ( softeningType == 3 ) { //exponential softening - // iteration to achieve objectivity - // we are finding state, where elastic stress is equal to - // stress from crack-opening relation (wf = wf characterizes the carc opening diagram) - - if ( tempKappa <= e0 ) { - omega = 0.0; - } else { - omega = 0.0; - Ft = this->eNormal * e0; - do { - nite++; - help = le * omega * tempKappa / this->wf; - R = ( 1. - omega ) * eNormal * tempKappa - Ft *exp(-help); - Lhs = eNormal * tempKappa - Ft *exp(-help) * le * tempKappa / this->wf; - omega += R / Lhs; - if ( nite > 40 ) { - OOFEM_ERROR("algorithm not converging"); - } - } while ( fabs(R) >= 1.e-4 ); - - if ( ( omega > 1.0 ) || ( omega < 0.0 ) ) { - OOFEM_ERROR("internal error"); - } - } - } else { - OOFEM_ERROR("Unknown softening type"); - } -} - - -void -LatticeDamage2d :: computeStressIndependentStrainVector(FloatArray &answer, - GaussPoint *gp, - TimeStep *tStep, - ValueModeType mode) -{ - FloatArray et; - LatticeStructuralElement *lselem = static_cast< LatticeStructuralElement * >( gp->giveElement() ); - - answer.resize(3); - answer.zero(); - - if ( tStep->giveIntrinsicTime() < this->castingTime ) { - return; - } - - if ( lselem ) { - lselem->computeResultingIPTemperatureAt(et, tStep, gp, mode); - } - - if ( et.giveSize() == 0 ) { - answer.clear(); - return; - } - - if ( et.giveSize() < 1 ) { - OOFEM_ERROR("Bad format of TemperatureLoad"); - exit(1); - } - - if ( mode == VM_Total ) { - // compute temperature difference - double deltaTemperature = et.at(1) - this->referenceTemperature; - answer.at(1) = this->give(tAlpha, gp) * deltaTemperature; - } else { - answer.at(1) = this->give(tAlpha, gp) * et.at(1); - } - - double length = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveLength(); - - answer.at(1) += this->cAlpha * et.at(1) / length; - return; -} - -MaterialStatus * -LatticeDamage2d :: CreateStatus(GaussPoint *gp) const -{ - return new LatticeDamage2dStatus(1, LatticeDamage2d :: domain, gp); -} - -MaterialStatus * -LatticeDamage2d :: giveStatus(GaussPoint *gp) const -{ - MaterialStatus *status = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); - if ( status == NULL ) { - // create a new one - status = this->CreateStatus(gp); - - if ( status != NULL ) { - gp->setMaterialStatus( status, this->giveNumber() ); - this->_generateStatusVariables(gp); - } - } - - return status; -} - - -void -LatticeDamage2d :: giveRealStressVector(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) -// -// returns real stress vector in 3d stress space of receiver according to -// previous level of stress and current -// strain increment, the only way, how to correctly update gp records -// -{ - LatticeDamage2dStatus *status = static_cast< LatticeDamage2dStatus * >( this->giveStatus(gp) ); - - const double e0 = this->give(e0_ID, gp) * this->e0Mean; - status->setE0(e0); - - FloatArray reducedStrain; - - double f, equivStrain, tempKappa, omega = 0.; - - this->initTempStatus(gp); - reducedStrain = totalStrain; - - // subtract stress independent part - this->giveStressDependentPartOfStrainVector(reducedStrain, gp, totalStrain, tStep, VM_Total); - - // compute equivalent strain - this->computeEquivalentStrain(equivStrain, reducedStrain, gp, tStep); - - - // compute value of loading function if strainLevel crit apply - f = equivStrain - status->giveKappa(); - - - if ( f <= 0.0 ) { - // damage does not grow - tempKappa = status->giveKappa(); - omega = status->giveDamage(); - if ( status->giveCrackFlag() != 0 ) { - status->setTempCrackFlag(2); - } else { - status->setTempCrackFlag(0); - } - } else { - // damage grows - tempKappa = equivStrain; - - // evaluate damage parameter - this->computeDamageParam(omega, tempKappa, reducedStrain, gp); - if ( omega > 0 ) { - status->setTempCrackFlag(1); - } - } - - //Compute the stress - answer.resize(3); - answer.zero(); - answer.at(1) = ( 1. - omega ) * eNormal * reducedStrain.at(1); - answer.at(2) = ( 1. - omega ) * eShear * reducedStrain.at(2); - answer.at(3) = ( 1. - omega ) * eTorsion * reducedStrain.at(3); - - //Add the water pressure to the normal component of the stress - IntArray coupledModels; - double waterPressure = 0.; - -#ifdef __TM_MODULE - if ( domain->giveEngngModel()->giveMasterEngngModel() ) { - ( static_cast< StaggeredProblem * >( domain->giveEngngModel()->giveMasterEngngModel() ) )->giveCoupledModels(coupledModels); - int couplingFlag = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveCouplingFlag(); - - if ( couplingFlag == 1 && coupledModels.at(2) != 0 && !tStep->isTheFirstStep() ) { - IntArray couplingNumbers; - - static_cast< LatticeStructuralElement * >( gp->giveElement() ) ->giveCouplingNumbers(couplingNumbers); - LatticeTransportElement *coupledElement; - coupledElement = static_cast< LatticeTransportElement * >(domain->giveEngngModel()->giveMasterEngngModel()->giveSlaveProblem( coupledModels.at(2) )->giveDomain(1)->giveElement(couplingNumbers.at(1)) ); - waterPressure = coupledElement->givePressure(); - } - } -#endif - - //Compute dissipation - double tempDissipation = status->giveDissipation(); - double tempDeltaDissipation = computeDeltaDissipation(omega, reducedStrain, gp, tStep); - - tempDissipation += tempDeltaDissipation; - - //Compute crack width - double le = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveLength(); - double crackWidth = omega * sqrt( pow(reducedStrain.at(1), 2.) + pow(reducedStrain.at(2), 2.) ) * le; - - //Calculate the the bio coefficient; - double biot = 0.; - if ( this->biotType == 0 ) { - biot = this->biotCoefficient; - } else if ( this->biotType == 1 ) { - biot = computeBiot(omega, tempKappa, le); - } else { - OOFEM_ERROR("Unknown biot type\n"); - } - - answer.at(1) = answer.at(1) + biot * waterPressure; - - - //Set all temp values - status->setTempDissipation(tempDissipation); - status->setTempDeltaDissipation(tempDeltaDissipation); - - status->setTempEquivalentStrain(equivStrain); - status->letTempStrainVectorBe(totalStrain); - status->letTempReducedStrainBe(reducedStrain); - status->letTempStressVectorBe(answer); - status->setTempKappa(tempKappa); - status->setTempDamage(omega); - - status->setTempNormalStress( answer.at(1) ); - status->setTempCrackWidth(crackWidth); - - status->setBiotCoefficientInStatus(biot); -} - -double -LatticeDamage2d :: computeBiot(double omega, - double kappa, - double le) -{ - - double biot = 0.; - - if ( this->softeningType == 1 || this->softeningType == 3 ) { - if ( omega == 0 ) { - biot = this->biotCoefficient; - } else if ( omega*kappa*le > 0 && omega*kappa*le < this->wf ) { - biot = this->biotCoefficient + (1.-biotCoefficient)*omega*kappa*le/this->wf; - } else { - biot = 1.; - } - } else { - OOFEM_ERROR("Wrong stype for btype=1. Only linear and exponential softening considered so far\n"); - } - - return biot; -} - - -double -LatticeDamage2d :: computeDeltaDissipation(double omega, - FloatArray &reducedStrain, - GaussPoint *gp, - TimeStep *tStep) -{ - LatticeDamage2dStatus *status = static_cast< LatticeDamage2dStatus * >( this->giveStatus(gp) ); - double length = ( static_cast< LatticeStructuralElement * >( gp->giveElement() ) )->giveLength(); - const double e0 = this->give(e0_ID, gp) * this->e0Mean; - - FloatArray reducedStrainOld; - - reducedStrainOld = status->giveReducedStrain(); - double omegaOld = status->giveDamage(); - double deltaOmega; - - FloatArray crackOpeningOld(3); - crackOpeningOld.times(omegaOld); - crackOpeningOld.times(length); - FloatArray intermediateStrain(3); - - double tempDeltaDissipation = 0.; - double deltaTempDeltaDissipation = 0.; - - double intermediateOmega = 0; - FloatArray oldIntermediateStrain(3); - oldIntermediateStrain = reducedStrainOld; - double oldIntermediateOmega = omegaOld; - deltaOmega = ( omega - omegaOld ); - double testDissipation = - 0.5 * length * ( pow( ( reducedStrain(0) + reducedStrainOld(0) ) / 2., 2. ) * eNormal + - pow( ( reducedStrain(1) + reducedStrainOld(1) ) / 2., 2. ) * eShear + - pow( ( reducedStrain(2) + reducedStrainOld(2) ) / 2., 2. ) * eTorsion ) * deltaOmega; - - - double intervals = 0.; - - double referenceGf = 0; - - if ( softeningType == 1 ) { - referenceGf = e0 * eNormal * this->wf / 2.; - } else { //This is for the exponential law. Should also implement it for the bilinear one. - referenceGf = e0 * eNormal * this->wf; - } - - if ( testDissipation / ( referenceGf ) > 0.01 ) { - intervals = 1000. * testDissipation / referenceGf; - } else { - intervals = 1.; - } - - if ( intervals > 1000. ) { - intervals = 1000.; - } - - double oldKappa = status->giveKappa(); - double f, equivStrain; - if ( deltaOmega > 0 ) { - for ( int k = 0; k < intervals; k++ ) { - intermediateStrain(0) = reducedStrainOld(0) + ( k + 1 ) / intervals * ( reducedStrain(0) - reducedStrainOld(0) ); - intermediateStrain(1) = reducedStrainOld(1) + ( k + 1 ) / intervals * ( reducedStrain(1) - reducedStrainOld(1) ); - intermediateStrain(2) = reducedStrainOld(2) + ( k + 1 ) / intervals * ( reducedStrain(2) - reducedStrainOld(2) ); - this->computeEquivalentStrain(equivStrain, intermediateStrain, gp, tStep); - f = equivStrain - oldKappa; - if ( f > 0 ) { - this->computeDamageParam(intermediateOmega, equivStrain, intermediateStrain, gp); - deltaOmega = ( intermediateOmega - oldIntermediateOmega ); - deltaTempDeltaDissipation = - 0.5 * length * ( pow( ( intermediateStrain(0) + oldIntermediateStrain(0) ) / 2., 2. ) * eNormal + - pow( ( intermediateStrain(1) + oldIntermediateStrain(1) ) / 2., 2. ) * eShear + - pow( ( intermediateStrain(2) + oldIntermediateStrain(2) ) / 2., 2. ) * eTorsion ) * deltaOmega; - - oldKappa = equivStrain; - oldIntermediateOmega = intermediateOmega; - } else { - deltaTempDeltaDissipation = 0.; - } - - tempDeltaDissipation += deltaTempDeltaDissipation; - oldIntermediateStrain = intermediateStrain; - } - } else { - tempDeltaDissipation = 0.; - } - - if ( tempDeltaDissipation >= 2. * referenceGf ) { - tempDeltaDissipation = 2. * referenceGf; - } - - return tempDeltaDissipation; -} - - -void LatticeDamage2d :: giveRandomParameters(FloatArray ¶m) -{ - param.resize(3); - param.at(1) = localRandomType; - - if ( localRandomType == 1 ) { //Gaussian - param.at(2) = coefficientOfVariation; - } else { - OOFEM_ERROR("Unknown local random type:\n randomtype 1 = Gaussian"); - } -} - - -Interface * -LatticeDamage2d :: giveInterface(InterfaceType type) -{ - return NULL; -} - - -void -LatticeDamage2d :: giveStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep) -{ - MaterialMode mMode = gp->giveMaterialMode(); - switch ( mMode ) { - case _2dLattice: - - if ( rMode == ElasticStiffness ) { - this->giveElasticStiffnessMatrix(answer, gp, tStep); - } else if ( rMode == SecantStiffness ) { - this->giveSecantStiffnessMatrix(answer, gp, tStep); - } else if ( rMode == TangentStiffness ) { - this->giveSecantStiffnessMatrix(answer, gp, tStep); - } else { - OOFEM_ERROR("Unsupported stiffness mode"); - } - - break; - default: - OOFEM_ERROR("unknown material mode"); - } -} - - -void -LatticeDamage2d :: giveSecantStiffnessMatrix(FloatMatrix &answer, - GaussPoint *gp, - TimeStep *tStep) -{ - LatticeDamage2dStatus *status = static_cast< LatticeDamage2dStatus * >( this->giveStatus(gp) ); - - double omega = status->giveTempDamage(); - - if ( omega > 1. - 1.e-9 ) { //To avoid convergence problems - omega = 1. - 1.e-9; - } - - /* Returns elastic moduli in reduced stress-strain space*/ - answer.resize(3, 3); - answer.zero(); - answer.at(1, 1) = ( 1 - omega ) * eNormal; - answer.at(2, 2) = ( 1 - omega ) * eShear; - answer.at(3, 3) = ( 1 - omega ) * eTorsion; -} - -void -LatticeDamage2d :: giveElasticStiffnessMatrix(FloatMatrix &answer, - GaussPoint *gp, - TimeStep *tStep) -{ - /* Returns elastic moduli in reduced stress-strain space*/ - answer.resize(3, 3); - answer.zero(); - answer.at(1, 1) = eNormal; - answer.at(2, 2) = eShear; - answer.at(3, 3) = eTorsion; -} - - -void -LatticeDamage2d :: giveThermalDilatationVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep) -{ - answer.resize(3); - answer.zero(); - answer.at(1) = this->give(tAlpha, gp); -} - - -double -LatticeDamage2d :: give(int aProperty, GaussPoint *gp) -{ - double answer; - if ( static_cast< LatticeDamage2dStatus * >( this->giveStatus(gp) )->_giveProperty(aProperty, answer) ) { - return answer; - } else if ( aProperty == e0_ID ) { - return 1.; - } else if ( aProperty == ef_ID ) { - return 1.; - } else { - return StructuralMaterial :: give(aProperty, gp); - } -} - - -int -LatticeDamage2d :: giveIPValue(FloatArray &answer, - GaussPoint *gp, - InternalStateType type, - TimeStep *tStep) -{ - LatticeDamage2dStatus *status = static_cast< LatticeDamage2dStatus * >( this->giveStatus(gp) ); - if ( type == IST_CrackStatuses ) { - answer.resize(1); - answer.at(1) = status->giveCrackFlag(); - return 1; - } else if ( type == IST_DamageScalar ) { - answer.resize(1); - answer.at(1) = status->giveDamage(); - return 1; - } else if ( type == IST_DamageTensor ) { - answer.resize(6); - answer.at(1) = answer.at(2) = answer.at(3) = status->giveDamage(); - return 1; - } else if ( type == IST_DissWork ) { - answer.resize(1); - answer.at(1) = status->giveDissipation(); - return 1; - } else if ( type == IST_DeltaDissWork ) { - answer.resize(1); - answer.at(1) = status->giveDeltaDissipation(); - return 1; - } else if ( type == IST_CrackWidth ) { - answer.resize(1); - answer.at(1) = status->giveCrackWidth(); - return 1; - } else { - return StructuralMaterial :: giveIPValue(answer, gp, type, tStep); - } -} - -LatticeDamage2dStatus :: LatticeDamage2dStatus(int n, Domain *d, GaussPoint *g) : - LatticeMaterialStatus(n, d, g), RandomMaterialStatusExtensionInterface(), reducedStrain(3), tempReducedStrain(3) -{ - le = 0.0; - crack_flag = temp_crack_flag = 0; - crackWidth = tempCrackWidth = 0; - normalStress = tempNormalStress = 0; - oldNormalStress = 0; - e0 = 0.; - damage = tempDamage = 0.; - equivStrain = tempEquivStrain = 0.; - kappa = tempKappa = 0.; - dissipation = tempDissipation = 0.; - deltaDissipation = tempDeltaDissipation = 0.; - biot = 0.; -} - -void -LatticeDamage2dStatus :: initTempStatus() -// -// initializes temp variables according to variables form previous equlibrium state. -// builds new crackMap -// -{ - StructuralMaterialStatus :: initTempStatus(); - this->tempReducedStrain = this->reducedStrain; - this->tempKappa = this->kappa; - this->tempEquivStrain = this->equivStrain; - this->tempDamage = this->damage; - this->tempDissipation = this->dissipation; - this->tempDeltaDissipation = this->deltaDissipation; - this->temp_crack_flag = this->crack_flag; - this->tempCrackWidth = this->crackWidth; - this->tempNormalStress = this->normalStress; - this->updateFlag = 0; -} - -void -LatticeDamage2dStatus :: printOutputAt(FILE *file, TimeStep *tStep) -{ - StructuralMaterialStatus :: printOutputAt(file, tStep); - fprintf(file, "status { "); - fprintf(file, "reduced strains "); - for ( auto &val : reducedStrain ) { - fprintf( file, "%.4e ", val ); - } - - fprintf(file, "kappa %f, equivStrain %f, damage %f, dissipation %f, deltaDissipation %f, e0 %f, crack_flag %d, crackWidth %.8e, biotCoeff %f", this->kappa, this->equivStrain, this->damage, this->dissipation, this->deltaDissipation, this->e0, this->crack_flag, this->crackWidth, this->biot); - fprintf(file, "}\n"); -} - - -void -LatticeDamage2dStatus :: updateYourself(TimeStep *tStep) -{ - StructuralMaterialStatus :: updateYourself(tStep); - - this->reducedStrain = this->tempReducedStrain; - this->kappa = this->tempKappa; - this->equivStrain = this->tempEquivStrain; - this->damage = this->tempDamage; - this->dissipation = this->tempDissipation; - this->deltaDissipation = this->tempDeltaDissipation; - this->crack_flag = this->temp_crack_flag; - this->crackWidth = this->tempCrackWidth; - //Need to preserve oldValues for coupling; - this->oldNormalStress = this->normalStress; - this->normalStress = this->tempNormalStress; - //set updateflag - this->updateFlag = 1; -} - -Interface * -LatticeDamage2dStatus :: giveInterface(InterfaceType type) -{ - if ( type == RandomMaterialStatusExtensionInterfaceType ) { - return static_cast< RandomMaterialStatusExtensionInterface * >(this); - } else { - return NULL; - } -} - -void -LatticeDamage2dStatus :: setTempNormalStress(double val) -{ - tempNormalStress = val; -} - -void -LatticeDamage2dStatus :: setOldNormalStress(double val) -{ - oldNormalStress = val; -} - - -contextIOResultType -LatticeDamage2dStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// -{ - contextIOResultType iores; - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - - - // write a raw data - if ( ( iores = reducedStrain.storeYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write a raw data - if ( !stream.write(kappa) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.write(equivStrain) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.write(damage) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.write(le) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.write(dissipation) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.write(deltaDissipation) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.write(crack_flag) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.write(crackWidth) ) { - THROW_CIOERR(CIO_IOERR); - } - - - if ( !stream.write(e0) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.write(biot) ) { - THROW_CIOERR(CIO_IOERR); - } - - return CIO_OK; -} - -void -LatticeDamage2dStatus :: setTempCrackFlag(int val) -{ - temp_crack_flag = val; -} - - - -void -LatticeDamage2dStatus :: setTempCrackWidth(double val) -{ - tempCrackWidth = val; -} - - -void -LatticeDamage2dStatus :: setVariableInStatus(double variable) -{ - e0 = variable; -} - - -void -LatticeDamage2dStatus :: setBiotCoefficientInStatus(double variable) -{ - biot = variable; -} - -int -LatticeDamage2dStatus :: giveCrackFlag() -{ - if ( crack_flag != 0 ) { } - - return crack_flag; -} - - -contextIOResultType -LatticeDamage2dStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// -{ - contextIOResultType iores; - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = reducedStrain.restoreYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data - if ( !stream.read(kappa) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.read(equivStrain) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.read(damage) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.read(le) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.read(dissipation) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.read(deltaDissipation) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.read(crack_flag) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.read(crackWidth) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.read(e0) ) { - THROW_CIOERR(CIO_IOERR); - } - - if ( !stream.read(biot) ) { - THROW_CIOERR(CIO_IOERR); - } - - - return CIO_OK; -} -} // end namespace oofem diff --git a/src/sm/Materials/latticedamage2d.h b/src/sm/Materials/latticedamage2d.h deleted file mode 100644 index 5ba647122..000000000 --- a/src/sm/Materials/latticedamage2d.h +++ /dev/null @@ -1,383 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef latticedamage2d_h -#define latticedamage2d_h - -#include "material.h" -#include "Materials/linearelasticmaterial.h" -#include "latticematstatus.h" -#include "cltypes.h" -#include "../sm/Materials/structuralmaterial.h" -#include "randommaterialext.h" -#include "strainvector.h" -#include "stressvector.h" - -///@name Input fields for LatticeDamage2d -//@{ -#define _IFT_LatticeDamage2d_Name "latticedamage2d" -#define _IFT_LatticeDamage2d_eNormal "e" -#define _IFT_LatticeDamage2d_alphaOne "a1" -#define _IFT_LatticeDamage2d_alphaTwo "a2" -#define _IFT_LatticeDamage2d_softeningType "stype" -#define _IFT_LatticeDamage2d_wf "wf" -#define _IFT_LatticeDamage2d_wfOne "wf1" -#define _IFT_LatticeDamage2d_localrandomtype "randomtype" -#define _IFT_LatticeDamage2d_coefficientOfVariation "cov" -#define _IFT_LatticeDamage2d_e0Mean "e0" -#define _IFT_LatticeDamage2d_e0OneMean "e01" -#define _IFT_LatticeDamage2d_coh "coh" -#define _IFT_LatticeDamage2d_ec "ec" -#define _IFT_LatticeDamage2d_calpha "calpha" -#define _IFT_LatticeDamage2d_bio "bio" -#define _IFT_LatticeDamage2d_btype "btype" -//@} - -namespace oofem { -/** - * This class implements associated Material Status to LatticeDamage2d. - */ -class LatticeDamage2dStatus : public LatticeMaterialStatus, public RandomMaterialStatusExtensionInterface -{ -protected: - /// Scalar measure of the largest strain level ever reached in material. - double kappa; - /// Non-equilibrated scalar measure of the largest strain level. - double tempKappa; - - /// Scalar measure of the strain. - double equivStrain; - /// Non-equilibrated scalar measure of the strain. - double tempEquivStrain; - - /// Damage level of material. - double damage; - /// Non-equilibrated damage level of material. - double tempDamage; - - /// Dissipation. - double dissipation; - /// Non-equilibrated dissipation.. - double tempDissipation; - - /// Increment of dissipation. - double deltaDissipation; - /// Non-equilibrated increment of dissipation. - double tempDeltaDissipation; - - /// Characteristic length. - double le; - - /// Random material parameter stored in status, since each gp has a different value. - double e0; - - /// Set biot coefficient - double biot; - - /** - * The crack_flag indicates if the gp is cracked: - * crack_flag = 0 gp is uncracked - * crack_flag = 1 gp is cracked and damage grows - * crack_flag = 2 gp is cracked and damage does not grow - */ - int crack_flag; - - /// Non-equilibrated temp flag. - int temp_crack_flag; - - /// Crack width. - double crackWidth; - - /// Old crack width - double oldCrackWidth; - - /// Non-equilibrated crack width. - double tempCrackWidth; - - /// equilibrated normal stress - double normalStress; - - /// old normal stress - double oldNormalStress; - - /// nonequilibrated normal stress - double tempNormalStress; - - /// Reduced strain. - FloatArray reducedStrain; - - /// Non-equilibrated reduced strain. - FloatArray tempReducedStrain; - - int updateFlag; - -public: - - /// Constructor - LatticeDamage2dStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~LatticeDamage2dStatus() { } - - - /// Returns the last equilibrated scalar measure of the largest strain level - double giveKappa() { return kappa; } - /// Returns the temp. scalar measure of the largest strain level - double giveTempKappa() { return tempKappa; } - /// Sets the temp scalar measure of the largest strain level to given value - void setTempKappa(double newKappa) { tempKappa = newKappa; } - - /// Returns the last equilibrated scalar measure of the largest strain level - double giveEquivalentStrain() { return equivStrain; } - /// Returns the temp. scalar measure of the largest strain level - double giveTempEquivalentStrain() { return tempEquivStrain; } - /// Sets the temp scalar measure of the largest strain level to given value - void setTempEquivalentStrain(double newEquivStrain) { tempEquivStrain = newEquivStrain; } - - /// Returns the last equilibrated dissipation - double giveDissipation() { return dissipation; } - /// Returns the temp. dissipation - double giveTempDissipation() { return tempDissipation; } - /// Sets the temp dissipation - void setTempDissipation(double newDiss) { tempDissipation = newDiss; } - - /// Returns the last equilibrated increment of dissipation - double giveDeltaDissipation() { return deltaDissipation; } - /// Returns the temp. increment dissipation - double giveTempDeltaDissipation() { return tempDeltaDissipation; } - /// Sets the temp. increment dissipation - void setTempDeltaDissipation(double newDiss) { tempDeltaDissipation = newDiss; } - - - /// Returns the last equilibrated damage level - double giveDamage() { return damage; } - /// Returns the temp. damage level - double giveTempDamage() { return tempDamage; } - /// Sets the temp damage level to given value - void setTempDamage(double newDamage) { tempDamage = newDamage; } - - /// Gives the temp value of plastic strain. - const FloatArray &giveTempReducedStrain() const { return tempReducedStrain; } - /// Gives the old equilibrated value of plastic strain. - const FloatArray &giveReducedStrain() const { return reducedStrain; } - - /** - * Assign the temp value of plastic strain. - * @param v New temp value of plastic strain. - */ - void letTempReducedStrainBe(FloatArray v) { tempReducedStrain = std :: move(v); } - - /// Prints the receiver state to given stream - void printOutputAt(FILE *file, TimeStep *tStep); - - /// Returns characteristic length stored in receiver - double giveLe() { return le; } - - /// Sets characteristic length to given value - void setLe(double ls) { le = ls; } - - ///Sets the temp_crack_flag - void setTempCrackFlag(int val); - - /// Returns the crack_flag - int giveCrackFlag(); - - /// Set random e0 - void setE0(double val) { e0 = val; } - - /// Sets the temp crack width - void setTempCrackWidth(double val); - - /// Gives the last equilibrated crack width - double giveCrackWidth() { return this->crackWidth; } - - - virtual double giveNormalStress() { return this->normalStress; } - - virtual double giveOldNormalStress() { return this->oldNormalStress; } - - virtual int hasBeenUpdated() { return this->updateFlag; } - - - /// Sets the temp normalStress - void setTempNormalStress(double val); - - /// Sets the old normalStress - void setOldNormalStress(double val); - - // definition - virtual const char *giveClassName() const { return "LatticeDamage2dStatus"; } - - virtual void initTempStatus(); - - virtual void updateYourself(TimeStep *); - - virtual Interface *giveInterface(InterfaceType); - - virtual void setVariableInStatus(double variable); - - void setBiotCoefficientInStatus(double variable); - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); -}; - - -/** - * This class implements a local random isotropic damage model for concrete in tension for 2D lattice elements. - */ -class LatticeDamage2d : public StructuralMaterial, public RandomMaterialExtensionInterface -{ -protected: - - /// Normal modulus - double eNormal; - /// Shear modulus - double eShear; - /// Torsion modulus - double eTorsion; - /// Ratio of shear and normal modulus - double alphaOne; - /// Ratio of torsion and normal modulus - double alphaTwo; - - /// Mean effective strain at peak - double e0Mean; - - /// Mean effective strain at sigma1 - double e0OneMean; - - ///coefficient used for modelling eigendisplacements - double cAlpha; - - /** - * Parameter which determines the typ of the softeningFunction - * 1 = linear softening - * 2 = bilinear softening - * 3 = exponential softening - */ - int softeningType; - - /// Determines the softening -> corresponds to threshold of crack opening (not strain) - double wf, wfOne; - - /// Parameter for the elliptic equivalent strain function - double ec; - - /// Parameter setting ratio of shear and tensile strength - double coh; - - /// Parameter controlling the amount of fluid pressure added to the mechanical stress (Biot's coefficient) - double biotCoefficient; - - /// Parameter specifying how the biot coefficient changes with the crack opening - int biotType; - - /// Coefficient variation of the Gaussian distribution - double coefficientOfVariation; - - /// Flag which chooses between no distribution (0) and Gaussian distribution (1) - double localRandomType; - -public: - - /// Constructor - LatticeDamage2d(int n, Domain * d); - /// Destructor - virtual ~LatticeDamage2d(); - - virtual const char *giveInputRecordName() const { return _IFT_LatticeDamage2d_Name; } - virtual const char *giveClassName() const { return "LatticeDamage2d"; } - - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } - - virtual void giveStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - - virtual void computeStressIndependentStrainVector(FloatArray &answer, - GaussPoint *gp, - TimeStep *tStep, - ValueModeType mode); - - virtual void giveSecantStiffnessMatrix(FloatMatrix &answer, - GaussPoint *gp, - TimeStep *tStep); - - - virtual void giveElasticStiffnessMatrix(FloatMatrix &answer, - GaussPoint *gp, - TimeStep *tStep); - - virtual int hasMaterialModeCapability(MaterialMode mode); - - virtual void computeEquivalentStrain(double &kappa, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - - virtual void computeDamageParam(double &omega, double kappa, const FloatArray &strain, GaussPoint *gp); - - virtual double computeBiot(double omega, double kappa, double le); - - virtual Interface *giveInterface(InterfaceType); - - - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *, - const FloatArray &, TimeStep *); - - virtual void giveRandomParameters(FloatArray ¶m); - - - ///Compute increment of dissipation for post-processing reasons - double computeDeltaDissipation(double omega, FloatArray &reducedStrain, GaussPoint *gp, TimeStep *tStep); - - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); - - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; - - virtual MaterialStatus *giveStatus(GaussPoint *gp) const; - - virtual double give(int aProperty, GaussPoint *gp); - - -protected: - - virtual int giveIPValue(FloatArray &answer, - GaussPoint *gp, - InternalStateType type, - TimeStep *tStep); -}; -} // end namespace oofem -#endif diff --git a/src/sm/Materials/latticematstatus.h b/src/sm/Materials/latticematstatus.h deleted file mode 100644 index 1dec494d8..000000000 --- a/src/sm/Materials/latticematstatus.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef latticematstatus_h -#define latticematstatus_h - -#include "../sm/Materials/structuralms.h" - -namespace oofem { -class GaussPoint; -class Dictionary; -class Domain; -class NonlocalMaterialStatusExtension; - -/** - * This class implements a base lattice material status. - * In this class services are defined that are used by other - * lattice material statuses. - */ -class LatticeMaterialStatus : public StructuralMaterialStatus -{ -public: - LatticeMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor. - virtual ~LatticeMaterialStatus() { } - - virtual void printOutputAt(FILE *, TimeStep *) { } - - virtual void initTempStatus() { } - - virtual void updateYourself(TimeStep *) { } - - /// Gives the last equilibrated normal stress - virtual double giveNormalStress() { return 0; } - - /// Gives the last equilibrated normal stress - virtual double giveOldNormalStress(){return 0;} - - /// Gives the last equilibrated normal stress - virtual int hasBeenUpdated(){return 0;} - - - virtual const char *giveClassName() const { return "LatticeMaterialStatus"; } - - ///Sets the temp_crack_flag - virtual void setTempCrackFlag(int val) = 0; - - /** - * Returns the crack flag - * @return crack flag - */ - virtual int giveCrackFlag() { return 0; } - - /** - * @return crack width - */ - virtual double giveCrackWidth() { return 0; } - - - /** - * @return old crack width - */ - virtual double giveOldCrackWidth() { return 0; } - - - /** - * Returns the energy dissipation computed at the GaussPoint of the element. - * This function is used for the lattice specific vtk export. - * @return dissipation - */ - virtual double giveDissipation() { return 0; } - - /** - * Returns the increment of dissipation computed at the GaussPoint of the element. - * This function is used for the lattice specific vtk export. - * @return increment of dissipation - */ - virtual double giveDeltaDissipation() { return 0; } - - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } -}; -} // end namespace oofem -#endif // matstatus_h diff --git a/src/sm/Materials/linearelasticmaterial.C b/src/sm/Materials/linearelasticmaterial.C index cd2fa3c55..1fc95034c 100644 --- a/src/sm/Materials/linearelasticmaterial.C +++ b/src/sm/Materials/linearelasticmaterial.C @@ -34,20 +34,20 @@ #include "linearelasticmaterial.h" #include "gausspoint.h" -#include "../sm/CrossSections/simplecrosssection.h" -#include "../sm/Materials/structuralms.h" +#include "sm/CrossSections/simplecrosssection.h" +#include "sm/Materials/structuralms.h" #include "dynamicinputrecord.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" namespace oofem { -IRResultType -LinearElasticMaterial :: initializeFrom(InputRecord *ir) +void +LinearElasticMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralMaterial :: initializeFrom(ir); preCastStiffnessReduction = 0.99999999; IR_GIVE_OPTIONAL_FIELD(ir, preCastStiffnessReduction, _IFT_LinearElasticMaterial_preCastStiffRed); - - return StructuralMaterial :: initializeFrom(ir); } @@ -58,42 +58,78 @@ LinearElasticMaterial :: giveInputRecord(DynamicInputRecord &input) input.setField(this->preCastStiffnessReduction, _IFT_LinearElasticMaterial_preCastStiffRed); } - void -LinearElasticMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +LinearElasticMaterial :: computesSubTangents() { - FloatArray strainVector, strainIncrement; - FloatMatrix d; - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + tangentPlaneStrain = { + tangent(0, 0), tangent(1, 0), tangent(2, 0), tangent(3, 0), + tangent(0, 1), tangent(1, 1), tangent(2, 1), tangent(3, 1), + tangent(0, 2), tangent(1, 2), tangent(2, 2), tangent(3, 2), + tangent(0, 3), tangent(1, 3), tangent(2, 3), tangent(3, 3), + }; + + auto c = inv(tangent); + FloatMatrixF<3,3> reduced = { + c(0,0), c(0,1), c(0,5), + c(1,0), c(1,1), c(1,5), + c(5,0), c(5,1), c(5,5), + }; + tangentPlaneStress = inv(reduced); +} - this->give3dMaterialStiffnessMatrix(d, TangentStiffness, gp, tStep); +FloatMatrixF<6,6> +LinearElasticMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const +{ + if ( tStep->giveIntrinsicTime() < this->castingTime ) { + return tangent * (1. - this->preCastStiffnessReduction); + } else { + return tangent; + } +} + + +FloatArrayF<6> +LinearElasticMaterial :: giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const +{ + return alpha; +} + + +FloatArrayF<6> +LinearElasticMaterial :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const +{ + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + + auto d = this->give3dMaterialStiffnessMatrix(TangentStiffness, gp, tStep); + + FloatArrayF<6> stress; if ( this->castingTime < 0. ) { // no changes in material stiffness ->> total formulation - this->giveStressDependentPartOfStrainVector_3d(strainVector, gp, reducedStrain, tStep, VM_Total); - answer.beProductOf(d, strainVector); + auto thermalStrain = this->computeStressIndependentStrainVector_3d(gp, tStep, VM_Total); + auto strainVector = strain - thermalStrain; + stress = dot(d, strainVector); } else { // changes in material stiffness ->> incremental formulation - this->giveStressDependentPartOfStrainVector_3d(strainVector, gp, reducedStrain, tStep, VM_Incremental); - strainIncrement.beDifferenceOf( strainVector, status->giveStrainVector() ); + auto thermalStrain = this->computeStressIndependentStrainVector_3d(gp, tStep, VM_Incremental); + auto strainIncrement = strain - thermalStrain - FloatArrayF<6>(status->giveStrainVector()); - answer.beProductOf(d, strainIncrement); - answer.add( status->giveStressVector() ); + stress = dot(d, strainIncrement) + status->giveStressVector(); } // update gp - status->letTempStrainVectorBe(reducedStrain); - status->letTempStressVectorBe(answer); + status->letTempStrainVectorBe(strain); + status->letTempStressVectorBe(stress); + return stress; } - -void -LinearElasticMaterial :: giveRealStressVector_3dDegeneratedShell(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF<6> +LinearElasticMaterial :: giveRealStressVector_3dDegeneratedShell(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const { - FloatArray strainVector, strainIncrement; - FloatMatrix d; - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - this->give3dMaterialStiffnessMatrix(d, TangentStiffness, gp, tStep); + auto d = this->give3dMaterialStiffnessMatrix(TangentStiffness, gp, tStep); d.at(1, 1) -= d.at(1, 3) * d.at(3, 1) / d.at(3, 3); d.at(2, 1) -= d.at(2, 3) * d.at(3, 1) / d.at(3, 3); @@ -106,66 +142,42 @@ LinearElasticMaterial :: giveRealStressVector_3dDegeneratedShell(FloatArray &ans d.at(2, 3) = 0.0; d.at(1, 3) = 0.0; - + FloatArrayF<6> stress, strainVector; if ( this->castingTime < 0. ) { // no changes in material stiffness ->> total formulation - this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Total); - answer.beProductOf(d, strainVector); + auto thermalStrain = this->computeStressIndependentStrainVector_3d(gp, tStep, VM_Total); + strainVector = strain - thermalStrain; + stress = dot(d, strainVector); } else { // changes in material stiffness ->> incremental formulation - this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Incremental); - strainIncrement.beDifferenceOf( strainVector, status->giveStrainVector() ); + auto thermalStrain = this->computeStressIndependentStrainVector_3d(gp, tStep, VM_Incremental); + auto strainIncrement = strain - thermalStrain - FloatArrayF<6>(status->giveStrainVector()); - answer.beProductOf(d, strainIncrement); - answer.add( status->giveStressVector() ); + stress = dot(d, strainIncrement) + status->giveStressVector(); } - answer.beProductOf(d, strainVector); - - // update gp - status->letTempStrainVectorBe(reducedStrain); - status->letTempStressVectorBe(answer); -} - -void -LinearElasticMaterial :: giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) -{ - FloatArray strainVector, strainIncrement; - FloatMatrix d; - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - - this->givePlaneStrainStiffMtrx(d, TangentStiffness, gp, tStep); - - if ( this->castingTime < 0. ) { // no changes in material stiffness ->> total formulation - this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Total); - answer.beProductOf(d, strainVector); - } else { // changes in material stiffness ->> incremental formulation - this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Incremental); - strainIncrement.beDifferenceOf( strainVector, status->giveStrainVector() ); - - answer.beProductOf(d, strainIncrement); - answer.add( status->giveStressVector() ); - } + stress = dot(d, strainVector); // update gp - status->letTempStrainVectorBe(reducedStrain); - status->letTempStressVectorBe(answer); + status->letTempStrainVectorBe(strain); + status->letTempStressVectorBe(stress); + return stress; } -void -LinearElasticMaterial :: giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF<3> +LinearElasticMaterial :: giveRealStressVector_PlaneStress(const FloatArrayF<3> &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { - FloatArray strainVector, strainIncrement; - FloatMatrix d; - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - this->givePlaneStressStiffMtrx(d, TangentStiffness, gp, tStep); + auto d = this->givePlaneStressStiffMtrx(TangentStiffness, gp, tStep); + FloatArray answer; + FloatArray strainVector; if ( this->castingTime < 0. ) { // no changes in material stiffness ->> total formulation this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Total); answer.beProductOf(d, strainVector); } else { // changes in material stiffness ->> incremental formulation this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Incremental); - strainIncrement.beDifferenceOf( strainVector, status->giveStrainVector() ); + auto strainIncrement = strainVector - status->giveStrainVector(); answer.beProductOf(d, strainIncrement); answer.add( status->giveStressVector() ); @@ -174,24 +186,24 @@ LinearElasticMaterial :: giveRealStressVector_PlaneStress(FloatArray &answer, Ga // update gp status->letTempStrainVectorBe(reducedStrain); status->letTempStressVectorBe(answer); + return answer; } -void -LinearElasticMaterial :: giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF<1> +LinearElasticMaterial :: giveRealStressVector_1d(const FloatArrayF<1> &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { - FloatArray strainVector, strainIncrement; - FloatMatrix d; - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - - this->give1dStressStiffMtrx(d, TangentStiffness, gp, tStep); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto d = this->give1dStressStiffMtrx(TangentStiffness, gp, tStep); + FloatArray answer; + FloatArray strainVector; if ( this->castingTime < 0. ) { // no changes in material stiffness ->> total formulation this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Total); answer.beProductOf(d, strainVector); } else { // changes in material stiffness ->> incremental formulation this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Incremental); - strainIncrement.beDifferenceOf( strainVector, status->giveStrainVector() ); + auto strainIncrement = strainVector - status->giveStrainVector(); answer.beProductOf(d, strainIncrement); answer.add( status->giveStressVector() ); @@ -200,59 +212,64 @@ LinearElasticMaterial :: giveRealStressVector_1d(FloatArray &answer, GaussPoint // update gp status->letTempStrainVectorBe(reducedStrain); status->letTempStressVectorBe(answer); + return answer; } -void -LinearElasticMaterial :: giveRealStressVector_Warping(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF<2> +LinearElasticMaterial :: giveRealStressVector_Warping(const FloatArrayF<2> &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { // reducedStrain contains the stress components tau_zy and tau_zx, computed as // tau_zy = G * theta * ( x + dPsi/dy ) // tau_zx = G * theta * (-y + dPsi/dx ) // where x and y are the global coordinates of the Gauss point (the origin must be at the centroid of the cross section) // G is the shear modulus of elasticity and theta is the relative twist (dPhi_z/dz) + + ///@todo Why is this warping method implemented here? It seems to assume isotropic linear elastic material, so it should be implemented in the subclass instead of relying on "giveShearModulus" which is only implemented there anyway. + + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + double G = this->giveShearModulus(); FloatArray gcoords; Element *elem = gp->giveElement(); - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - double G = this->giveShearModulus(); elem->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); - answer.resize(2); + FloatArrayF<2> answer; if ( this->castingTime < 0. ) { // no changes in material stiffness ->> total formulation answer.at(1) = reducedStrain.at(1); answer.at(2) = reducedStrain.at(2); - answer.times(G); + answer *= G; } else { // changes in material stiffness ->> incremental formulation FloatArray strainIncrement; strainIncrement.beDifferenceOf( reducedStrain, status->giveStrainVector() ); answer.at(1) = strainIncrement.at(1); answer.at(2) = strainIncrement.at(2); - answer.times(G); + answer *= G; if ( ( tStep->giveIntrinsicTime() < this->castingTime ) ) { - answer.times(1. - this->preCastStiffnessReduction); + answer *= (1. - this->preCastStiffnessReduction); } - answer.add( status->giveStressVector() ); + answer += FloatArrayF<2>(status->giveStressVector()); } // update gp status->letTempStrainVectorBe(reducedStrain); status->letTempStressVectorBe(answer); + return answer; } -void -LinearElasticMaterial :: giveRealStressVector_2dBeamLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF<2> +LinearElasticMaterial :: giveRealStressVector_2dBeamLayer(const FloatArrayF<2> &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { - FloatArray strainVector, strainIncrement; - FloatMatrix d; - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - this->give2dBeamLayerStiffMtrx(d, TangentStiffness, gp, tStep); + auto d = this->give2dBeamLayerStiffMtrx(TangentStiffness, gp, tStep); + FloatArray answer; + FloatArray strainVector, strainIncrement; if ( this->castingTime < 0. ) { // no changes in material stiffness ->> total formulation this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Total); answer.beProductOf(d, strainVector); @@ -267,18 +284,19 @@ LinearElasticMaterial :: giveRealStressVector_2dBeamLayer(FloatArray &answer, Ga // update gp status->letTempStrainVectorBe(reducedStrain); status->letTempStressVectorBe(answer); + return answer; } -void -LinearElasticMaterial :: giveRealStressVector_PlateLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF<5> +LinearElasticMaterial :: giveRealStressVector_PlateLayer(const FloatArrayF<5> &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { - FloatArray strainVector, strainIncrement; - FloatMatrix d; - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - this->givePlateLayerStiffMtrx(d, TangentStiffness, gp, tStep); + auto d = this->givePlateLayerStiffMtrx(TangentStiffness, gp, tStep); + FloatArray answer; + FloatArray strainVector, strainIncrement; if ( this->castingTime < 0. ) { // no changes in material stiffness ->> total formulation this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Total); answer.beProductOf(d, strainVector); @@ -293,24 +311,25 @@ LinearElasticMaterial :: giveRealStressVector_PlateLayer(FloatArray &answer, Gau // update gp status->letTempStrainVectorBe(reducedStrain); status->letTempStressVectorBe(answer); + return answer; } -void -LinearElasticMaterial :: giveRealStressVector_Fiber(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF<3> +LinearElasticMaterial :: giveRealStressVector_Fiber(const FloatArrayF<3> &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { - FloatArray strainVector, strainIncrement; - FloatMatrix d; - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - this->giveFiberStiffMtrx(d, TangentStiffness, gp, tStep); + auto d = this->giveFiberStiffMtrx(TangentStiffness, gp, tStep); + FloatArray answer; + FloatArray strainVector; if ( this->castingTime < 0. ) { // no changes in material stiffness ->> total formulation this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Total); answer.beProductOf(d, strainVector); } else { // changes in material stiffness ->> incremental formulation this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Incremental); - strainIncrement.beDifferenceOf( strainVector, status->giveStrainVector() ); + auto strainIncrement = strainVector - status->giveStrainVector(); answer.beProductOf(d, strainIncrement); answer.add( status->giveStressVector() ); @@ -319,6 +338,7 @@ LinearElasticMaterial :: giveRealStressVector_Fiber(FloatArray &answer, GaussPoi // update gp status->letTempStrainVectorBe(reducedStrain); status->letTempStressVectorBe(answer); + return answer; } void @@ -372,10 +392,33 @@ LinearElasticMaterial :: giveEnergyDensity(GaussPoint *gp, TimeStep *tStep) return 0.5 * stress.dotProduct(strain); } +int +LinearElasticMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +{ + StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + if ( type == IST_ElasticStrainTensor ) { + this->giveStressDependentPartOfStrainVector(answer, gp, status->giveStrainVector(), tStep, VM_Total); + return 1; + } else if ( type == IST_ThermalStrainTensor ) { + answer = this->computeStressIndependentStrainVector_3d(gp, tStep, VM_Total); + return 1; + } else if ( type == IST_CreepStrainTensor ) { + answer.resize(6); + answer.zero(); + return 1; + } else if ( type == IST_FreeEnergyDensity ) { + answer.resize(1); + answer.at(1) = this->giveEnergyDensity(gp,tStep); + return 1; + } else { + return StructuralMaterial :: giveIPValue(answer, gp, type, tStep); + } +} + MaterialStatus * LinearElasticMaterial :: CreateStatus(GaussPoint *gp) const { - return new StructuralMaterialStatus(1, this->giveDomain(), gp); + return new StructuralMaterialStatus(gp); } } // end namespace oofem diff --git a/src/sm/Materials/linearelasticmaterial.h b/src/sm/Materials/linearelasticmaterial.h index 513386bf3..e0bb246dd 100644 --- a/src/sm/Materials/linearelasticmaterial.h +++ b/src/sm/Materials/linearelasticmaterial.h @@ -35,7 +35,9 @@ #ifndef linearelasticmaterial_h #define linearelasticmaterial_h -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" ///@name Input fields for LinearElasticMaterial //@{ @@ -64,36 +66,54 @@ class LinearElasticMaterial : public StructuralMaterial { protected: /// artificial isotropic damage to reflect reduction in stiffness for time < castingTime. - double preCastStiffnessReduction; + double preCastStiffnessReduction = 0.; + + /// Preconstructed 3d tangent + FloatMatrixF<6,6> tangent; + FloatMatrixF<4,4> tangentPlaneStrain; + FloatMatrixF<3,3> tangentPlaneStress; + + /// Thermal expansion + FloatArrayF<6> alpha; public: /// Constructor. LinearElasticMaterial(int n, Domain *d) : StructuralMaterial(n, d) { } - /// Destructor. - virtual ~LinearElasticMaterial() { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + + const FloatMatrixF<6,6> &giveTangent() const { return tangent; } + const FloatArrayF<6> &giveAlpha() const { return alpha; } + + /** + * Computes the plane strain and plane stress tangents from the 3D tangent. + */ + void computesSubTangents(); + + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<6> giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep); - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStressVector_3dDegeneratedShell(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedF, TimeStep *tStep); - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStressVector_Warping(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveRealStressVector_2dBeamLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - virtual void giveRealStressVector_PlateLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - virtual void giveRealStressVector_Fiber(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; + ///@todo Should this be virtual? It's never used. It's not part of the base class. + virtual FloatArrayF<6> giveRealStressVector_3dDegeneratedShell(const FloatArrayF<6> &reducedF, GaussPoint *gp, TimeStep *tStep) const; + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<2> giveRealStressVector_Warping(const FloatArrayF<2> &reducedStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<2> giveRealStressVector_2dBeamLayer(const FloatArrayF<2> &reducedE, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<5> giveRealStressVector_PlateLayer(const FloatArrayF<5> &reducedE, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<3> giveRealStressVector_Fiber(const FloatArrayF<3> &reducedE, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveEshelbyStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedF, TimeStep *tStep); + void giveEshelbyStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedF, TimeStep *tStep) override; double giveEnergyDensity(GaussPoint *gp, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual double giveShearModulus() { return 1.; } - virtual int hasNonLinearBehaviour() { return 0; } - virtual int hasCastingTimeSupport() { return 1.; } - virtual const char *giveClassName() const { return "LinearElasticMaterial"; } + ///@todo This makes no sense in this base class, it should belong to isotropiclinearelastic material. + virtual double giveShearModulus() const { return 1.; } + bool hasCastingTimeSupport() const override { return true; } + const char *giveClassName() const override { return "LinearElasticMaterial"; } }; } // end namespace oofem #endif // linearelasticmaterial_h diff --git a/src/sm/Materials/lsmastermat.C b/src/sm/Materials/lsmastermat.C index 297ca5539..75637ed2f 100644 --- a/src/sm/Materials/lsmastermat.C +++ b/src/sm/Materials/lsmastermat.C @@ -33,10 +33,12 @@ */ #include "lsmastermat.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" #include "intarray.h" #include "stressvector.h" #include "strainvector.h" @@ -48,58 +50,46 @@ namespace oofem { REGISTER_Material(LargeStrainMasterMaterial); -// constructor LargeStrainMasterMaterial :: LargeStrainMasterMaterial(int n, Domain *d) : StructuralMaterial(n, d) { - slaveMat = 0; } -// destructor -LargeStrainMasterMaterial :: ~LargeStrainMasterMaterial() -{ } - -// reads the model parameters from the input file -IRResultType -LargeStrainMasterMaterial :: initializeFrom(InputRecord *ir) +void +LargeStrainMasterMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // required by IR_GIVE_FIELD macro - IR_GIVE_OPTIONAL_FIELD(ir, slaveMat, _IFT_LargeStrainMasterMaterial_slaveMat); // number of slave material IR_GIVE_OPTIONAL_FIELD(ir, m, _IFT_LargeStrainMasterMaterial_m); // type of Set-Hill strain tensor - - return IRRT_OK; } -// creates a new material status corresponding to this class MaterialStatus * LargeStrainMasterMaterial :: CreateStatus(GaussPoint *gp) const { - return new LargeStrainMasterMaterialStatus(1, this->giveDomain(), gp, slaveMat); + return new LargeStrainMasterMaterialStatus(gp, domain, slaveMat); } -void -LargeStrainMasterMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &vF, TimeStep *tStep) +FloatArrayF<9> +LargeStrainMasterMaterial :: giveFirstPKStressVector_3d(const FloatArrayF<9> &vF, GaussPoint *gp, TimeStep *tStep) const { - LargeStrainMasterMaterialStatus *status = static_cast< LargeStrainMasterMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< LargeStrainMasterMaterialStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); - StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); + auto sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); - double lambda1, lambda2, lambda3, E1, E2, E3; - FloatArray eVals, SethHillStrainVector, stressVector, stressM; - FloatMatrix F, Ft, C, eVecs, SethHillStrain; - FloatMatrix L1, L2, T; //store of deformation gradient into 3x3 matrix - F.beMatrixForm(vF); + auto F = from_voigt_form(vF); //compute right Cauchy-Green tensor(C), its eigenvalues and eigenvectors - C.beTProductOf(F, F); + auto C = Tdot(F, F); // compute eigen values and eigen vectors of C - C.jaco_(eVals, eVecs, 15); + FloatArray eVals; + FloatMatrix eVecs; + FloatMatrix(C).jaco_(eVals, eVecs, 15); + // compute Seth - Hill's strain measure, it depends on mParameter - lambda1 = eVals.at(1); - lambda2 = eVals.at(2); - lambda3 = eVals.at(3); + double lambda1 = eVals.at(1); + double lambda2 = eVals.at(2); + double lambda3 = eVals.at(3); + double E1, E2, E3; if ( m == 0 ) { E1 = 1. / 2. * log(lambda1); E2 = 1. / 2. * log(lambda2); @@ -110,52 +100,53 @@ LargeStrainMasterMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, Gaus E3 = 1. / ( 2. * m ) * ( pow(lambda3, m) - 1. ); } - SethHillStrain.resize(3, 3); + FloatMatrixF<3,3> SethHillStrain; for ( int i = 1; i < 4; i++ ) { for ( int j = 1; j < 4; j++ ) { SethHillStrain.at(i, j) = E1 * eVecs.at(i, 1) * eVecs.at(j, 1) + E2 *eVecs.at(i, 2) * eVecs.at(j, 2) + E3 *eVecs.at(i, 3) * eVecs.at(j, 3); } } - SethHillStrainVector.beSymVectorFormOfStrain(SethHillStrain); - sMat->giveRealStressVector_3d(stressVector, gp, SethHillStrainVector, tStep); - this->constructTransformationMatrix(T, eVecs); + auto SethHillStrainVector = to_voigt_strain(SethHillStrain); + auto stressVector = sMat->giveRealStressVector_3d(SethHillStrainVector, gp, tStep); - stressVector.at(4) = 2 * stressVector.at(4); - stressVector.at(5) = 2 * stressVector.at(5); - stressVector.at(6) = 2 * stressVector.at(6); + auto T = this->constructTransformationMatrix(eVecs); + stressVector.at(4) = 2; + stressVector.at(5) = 2; + stressVector.at(6) = 2; + auto stressM = dot(T, FloatArrayF<6>(stressVector)); + stressM.at(4) *= 1. / 2.; + stressM.at(5) *= 1. / 2.; + stressM.at(6) *= 1. / 2.; - stressM.beProductOf(T, stressVector); - stressM.at(4) = 1. / 2. * stressM.at(4); - stressM.at(5) = 1. / 2. * stressM.at(5); - stressM.at(6) = 1. / 2. * stressM.at(6); + //auto [L1, L2] = this->constructL1L2TransformationMatrices(eVals, stressM, E1, E2, E3); // c++17 + auto tmp = this->constructL1L2TransformationMatrices(eVals, stressM, E1, E2, E3); + auto L1 = tmp.first; + auto L2 = tmp.second; - this->constructL1L2TransformationMatrices(L1, L2, eVals, stressM, E1, E2, E3); + auto P = Tdot(T, dot(L1, T)); - FloatMatrix junk, P, TL; - FloatArray secondPK; - junk.beProductOf(L1, T); - P.beTProductOf(T, junk); //transformation of the stress to the 2PK stress and then to 1PK - stressVector.at(4) = 0.5 * stressVector.at(4); - stressVector.at(5) = 0.5 * stressVector.at(5); - stressVector.at(6) = 0.5 * stressVector.at(6); - secondPK.beProductOf(P, stressVector); - answer.beProductOf(F, secondPK); // P = F*S - junk.zero(); - junk.beProductOf(L2, T); - TL.beTProductOf(T, junk); + stressVector.at(4) *= 0.5; + stressVector.at(5) *= 0.5; + stressVector.at(6) *= 0.5; + auto secondPK = dot(P, FloatArrayF<6>(stressVector)); + + auto firstPK = dot(F, from_voigt_stress(secondPK)); // P = F*S + auto firstPKv = to_voigt_form(firstPK); + auto TL = Tdot(T, dot(L2, T)); status->setPmatrix(P); status->setTLmatrix(TL); - status->letTempStressVectorBe(answer); + status->letTempStressVectorBe(firstPKv); + return firstPKv; } -void -LargeStrainMasterMaterial :: constructTransformationMatrix(FloatMatrix &answer, const FloatMatrix &eVecs) +FloatMatrixF<6,6> +LargeStrainMasterMaterial :: constructTransformationMatrix(const FloatMatrixF<3,3> &eVecs) const { - answer.resize(6, 6); + FloatMatrixF<6,6> answer; answer.at(1, 1) = eVecs.at(1, 1) * eVecs.at(1, 1); answer.at(1, 2) = eVecs.at(2, 1) * eVecs.at(2, 1); answer.at(1, 3) = eVecs.at(3, 1) * eVecs.at(3, 1); @@ -197,12 +188,14 @@ LargeStrainMasterMaterial :: constructTransformationMatrix(FloatMatrix &answer, answer.at(6, 4) = eVecs.at(2, 1) * eVecs.at(3, 2) + eVecs.at(3, 1) * eVecs.at(2, 2); answer.at(6, 5) = eVecs.at(1, 1) * eVecs.at(3, 2) + eVecs.at(3, 1) * eVecs.at(1, 2); answer.at(6, 6) = eVecs.at(1, 1) * eVecs.at(2, 2) + eVecs.at(2, 1) * eVecs.at(1, 2); + return answer; } -void -LargeStrainMasterMaterial :: constructL1L2TransformationMatrices(FloatMatrix &answer1, FloatMatrix &answer2, const FloatArray &eigenValues, FloatArray &stressM, double E1, double E2, double E3) +std::pair, FloatMatrixF<6,6>> +LargeStrainMasterMaterial :: constructL1L2TransformationMatrices(const FloatArrayF<3> &eigenValues, const FloatArrayF<6> &stressM, double E1, double E2, double E3) const { + FloatMatrixF<6,6> answer1, answer2; double gamma12, gamma13, gamma23, gamma112, gamma221, gamma113, gamma331, gamma223, gamma332, gamma; double lambda1 = eigenValues.at(1); double lambda2 = eigenValues.at(2); @@ -343,17 +336,16 @@ LargeStrainMasterMaterial :: constructL1L2TransformationMatrices(FloatMatrix &an answer1.at(4, 4) = gamma23; answer1.at(5, 5) = gamma13; answer1.at(6, 6) = gamma12; + return {answer1, answer2}; } -void -LargeStrainMasterMaterial :: give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<9,9> +LargeStrainMasterMaterial :: give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - LargeStrainMasterMaterialStatus *status = static_cast< LargeStrainMasterMaterialStatus * >( this->giveStatus(gp) ); - StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); - FloatMatrix stiffness; + auto status = static_cast< LargeStrainMasterMaterialStatus * >( this->giveStatus(gp) ); + auto sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); - sMat->give3dMaterialStiffnessMatrix(stiffness, mode, gp, tStep); - FloatMatrix junk; + auto stiffness = sMat->give3dMaterialStiffnessMatrix(mode, gp, tStep); /////////////////////////////////////////////////////////// stiffness.at(1, 4) = 2. * stiffness.at(1, 4); stiffness.at(4, 1) = 2. * stiffness.at(4, 1); @@ -383,18 +375,17 @@ LargeStrainMasterMaterial :: give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &ans stiffness.at(6, 5) = 4. * stiffness.at(6, 5); stiffness.at(6, 6) = 4. * stiffness.at(6, 6); ///////////////////////////////////////////////////////////// - junk.beProductOf( stiffness, status->givePmatrix() ); - stiffness.beProductOf(status->givePmatrix(), junk); - stiffness.add( status->giveTLmatrix() ); + auto junk = dot(FloatMatrixF<6,6>(stiffness), status->givePmatrix()); + auto stiffness2 = dot(status->givePmatrix(), junk) + status->giveTLmatrix(); - this->convert_dSdE_2_dPdF(answer, stiffness, status->giveTempStressVector(), status->giveTempFVector(), _3dMat); + return convert_dSdE_2_dPdF_3D(stiffness2, status->giveTempStressVector(), status->giveTempFVector()); } int LargeStrainMasterMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - LargeStrainMasterMaterialStatus *status = static_cast< LargeStrainMasterMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< LargeStrainMasterMaterialStatus * >( this->giveStatus(gp) ); if ( type == IST_StressTensor ) { answer = status->giveStressVector(); @@ -411,25 +402,20 @@ LargeStrainMasterMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, Int //============================================================================= -LargeStrainMasterMaterialStatus :: LargeStrainMasterMaterialStatus(int n, Domain *d, GaussPoint *g, int s) : StructuralMaterialStatus(n, d, g), - Pmatrix(6, 6), - TLmatrix(6, 6), - transformationMatrix(6, 6), +LargeStrainMasterMaterialStatus :: LargeStrainMasterMaterialStatus(GaussPoint *g, Domain *d, int s) : + StructuralMaterialStatus(g), + domain(d), slaveMat(s) { - Pmatrix.beUnitMatrix(); + Pmatrix = eye<6>(); } -LargeStrainMasterMaterialStatus :: ~LargeStrainMasterMaterialStatus() -{ } - - void -LargeStrainMasterMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +LargeStrainMasterMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { - StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); - MaterialStatus *mS = sMat->giveStatus(gp); + auto sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); + auto mS = sMat->giveStatus(gp); mS->printOutputAt(file, tStep); // StructuralMaterialStatus :: printOutputAt(file, tStep); @@ -439,8 +425,8 @@ LargeStrainMasterMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) // initializes temporary variables based on their values at the previous equlibrium state void LargeStrainMasterMaterialStatus :: initTempStatus() { - StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); - MaterialStatus *mS = sMat->giveStatus(gp); + auto sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); + auto mS = sMat->giveStatus(gp); mS->initTempStatus(); //StructuralMaterialStatus :: initTempStatus(); } @@ -450,45 +436,26 @@ void LargeStrainMasterMaterialStatus :: initTempStatus() void LargeStrainMasterMaterialStatus :: updateYourself(TimeStep *tStep) { - StructuralMaterial *sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); - MaterialStatus *mS = sMat->giveStatus(gp); + auto sMat = static_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); + auto mS = sMat->giveStatus(gp); mS->updateYourself(tStep); // StructuralMaterialStatus :: updateYourself(tStep); } -// saves full information stored in this status -// temporary variables are NOT stored -contextIOResultType -LargeStrainMasterMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +LargeStrainMasterMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - StructuralMaterial *sMat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); - MaterialStatus *mS = sMat->giveStatus(gp); + auto sMat = dynamic_cast< StructuralMaterial * >( domain->giveMaterial(slaveMat) ); + auto mS = sMat->giveStatus(gp); // save parent class status - if ( ( iores = mS->saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write raw data - - return CIO_OK; + mS->saveContext(stream, mode); } -contextIOResultType -LargeStrainMasterMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +LargeStrainMasterMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; // return succes + StructuralMaterialStatus :: restoreContext(stream, mode); } } // end namespace oofem diff --git a/src/sm/Materials/lsmastermat.h b/src/sm/Materials/lsmastermat.h index 5f70c1006..5d4e91579 100644 --- a/src/sm/Materials/lsmastermat.h +++ b/src/sm/Materials/lsmastermat.h @@ -35,9 +35,9 @@ #ifndef lsmastermat_h #define lsmastermat_h -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" -#include "Materials/linearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/linearelasticmaterial.h" #include "dictionary.h" #include "floatarray.h" #include "floatmatrix.h" @@ -64,44 +64,40 @@ class LargeStrainMasterMaterial : public StructuralMaterial { protected: /// Reference to the basic elastic material. - LinearElasticMaterial *linearElasticMaterial; + LinearElasticMaterial *linearElasticMaterial = nullptr; /// 'slave' material model number. - int slaveMat; + int slaveMat = 0; /// Specifies the strain tensor. - double m; - + double m = 0.; public: LargeStrainMasterMaterial(int n, Domain *d); - virtual ~LargeStrainMasterMaterial(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual int hasNonLinearBehaviour() { return 1; } - virtual const char *giveInputRecordName() const { return _IFT_LargeStrainMasterMaterial_Name; } - virtual const char *giveClassName() const { return "LargeStrainMasterMaterial"; } + const char *giveInputRecordName() const override { return _IFT_LargeStrainMasterMaterial_Name; } + const char *giveClassName() const override { return "LargeStrainMasterMaterial"; } LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual void give3dMaterialStiffnessMatrix_dPdF(FloatMatrix & answer, - MatResponseMode, - GaussPoint * gp, - TimeStep * tStep); + FloatMatrixF<9,9> give3dMaterialStiffnessMatrix_dPdF(MatResponseMode, + GaussPoint * gp, + TimeStep * tStep) const override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *, const FloatArray &, TimeStep *) - { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } - virtual void giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &vF, TimeStep *tStep); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &, GaussPoint *, TimeStep *) const override + { OOFEM_ERROR("not implemented, this material is designed for large strains only"); return zeros<6>(); } + FloatArrayF<9> giveFirstPKStressVector_3d(const FloatArrayF<9> &vF, GaussPoint *gp, TimeStep *tStep) const override; /// transformation matrices - void constructTransformationMatrix(FloatMatrix &answer, const FloatMatrix &eigenVectors); - void constructL1L2TransformationMatrices(FloatMatrix &answer1, FloatMatrix &answer2, const FloatArray &eigenValues, FloatArray &stress, double E1, double E2, double E3); + FloatMatrixF<6,6> constructTransformationMatrix(const FloatMatrixF<3,3> &eigenVectors) const; + std::pair, FloatMatrixF<6,6>> constructL1L2TransformationMatrices(const FloatArrayF<3> &eigenValues, const FloatArrayF<6> &stress, double E1, double E2, double E3) const; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; }; //============================================================================= @@ -110,33 +106,30 @@ class LargeStrainMasterMaterial : public StructuralMaterial class LargeStrainMasterMaterialStatus : public StructuralMaterialStatus { protected: - FloatMatrix Pmatrix, TLmatrix, transformationMatrix; - int slaveMat; + FloatMatrixF<6,6> Pmatrix = eye<6>(); + FloatMatrixF<6,6> TLmatrix, transformationMatrix; + Domain *domain = nullptr; + int slaveMat = 0.; public: - LargeStrainMasterMaterialStatus(int n, Domain *d, GaussPoint *g, int s); - virtual ~LargeStrainMasterMaterialStatus(); - - - const FloatMatrix &givePmatrix() { return Pmatrix; } - const FloatMatrix &giveTLmatrix() { return TLmatrix; } - const FloatMatrix &giveTransformationMatrix() { return transformationMatrix; } - - void setPmatrix(const FloatMatrix &values) { Pmatrix = values; } - void setTLmatrix(const FloatMatrix &values) { TLmatrix = values; } - void setTransformationMatrix(const FloatMatrix &values) { transformationMatrix = values; } - - virtual void printOutputAt(FILE *file, TimeStep *tStep); + LargeStrainMasterMaterialStatus(GaussPoint *g, Domain *d, int s); - virtual void initTempStatus(); + const FloatMatrixF<6,6> &givePmatrix() const { return Pmatrix; } + const FloatMatrixF<6,6> &giveTLmatrix() const { return TLmatrix; } + const FloatMatrixF<6,6> &giveTransformationMatrix() const { return transformationMatrix; } - virtual void updateYourself(TimeStep *); + void setPmatrix(const FloatMatrixF<6,6> &values) { Pmatrix = values; } + void setTLmatrix(const FloatMatrixF<6,6> &values) { TLmatrix = values; } + void setTransformationMatrix(const FloatMatrixF<6,6> &values) { transformationMatrix = values; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void printOutputAt(FILE *file, TimeStep *tStep) const override; + void initTempStatus() override; + void updateYourself(TimeStep *) override; - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual const char *giveClassName() const { return "LargeStrainMasterMaterialStatus"; } + const char *giveClassName() const override { return "LargeStrainMasterMaterialStatus"; } }; } // end namespace oofem #endif // misesmat_h diff --git a/src/sm/Materials/lsmastermatgrad.C b/src/sm/Materials/lsmastermatgrad.C index 3b877d8bb..7c1aef2de 100644 --- a/src/sm/Materials/lsmastermatgrad.C +++ b/src/sm/Materials/lsmastermatgrad.C @@ -46,21 +46,17 @@ #include "classfactory.h" namespace oofem { -REGISTER_Material(LargeStrainMasterMaterial); +REGISTER_Material(LargeStrainMasterMaterialGrad); // constructor -LargeStrainMasterMaterialGrad :: LargeStrainMasterMaterialGrad(int n, Domain *d) : LargeStrainMasterMaterial(n, d), GradDpMaterialExtensionInterface(d) +LargeStrainMasterMaterialGrad :: LargeStrainMasterMaterialGrad(int n, Domain *d) : LargeStrainMasterMaterial(n, d), GradientDamageMaterialExtensionInterface(d) { - slaveMat = 0; } -// destructor -LargeStrainMasterMaterialGrad :: ~LargeStrainMasterMaterialGrad() -{ } // specifies whether a given material mode is supported by this model -int -LargeStrainMasterMaterialGrad :: hasMaterialModeCapability(MaterialMode mode) +bool +LargeStrainMasterMaterialGrad :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _3dMat; } @@ -69,7 +65,7 @@ LargeStrainMasterMaterialGrad :: hasMaterialModeCapability(MaterialMode mode) MaterialStatus * LargeStrainMasterMaterialGrad :: CreateStatus(GaussPoint *gp) const { - return new LargeStrainMasterMaterialStatus(1, this->giveDomain(), gp, slaveMat); + return new LargeStrainMasterMaterialStatus(gp, this->giveDomain(), slaveMat); } @@ -84,12 +80,12 @@ LargeStrainMasterMaterialGrad :: giveStiffnessMatrix(FloatMatrix &answer, MatRes void -LargeStrainMasterMaterialGrad :: givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +LargeStrainMasterMaterialGrad :: giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { case _3dMat: - LargeStrainMasterMaterial :: give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + answer = LargeStrainMasterMaterial :: give3dMaterialStiffnessMatrix(mode, gp, tStep); break; default: OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mMode) ); @@ -97,7 +93,7 @@ LargeStrainMasterMaterialGrad :: givePDGradMatrix_uu(FloatMatrix &answer, MatRes } void -LargeStrainMasterMaterialGrad :: givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +LargeStrainMasterMaterialGrad :: giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { @@ -110,7 +106,7 @@ LargeStrainMasterMaterialGrad :: givePDGradMatrix_ku(FloatMatrix &answer, MatRes } void -LargeStrainMasterMaterialGrad :: givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +LargeStrainMasterMaterialGrad :: giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { @@ -122,39 +118,11 @@ LargeStrainMasterMaterialGrad :: givePDGradMatrix_uk(FloatMatrix &answer, MatRes } } -void -LargeStrainMasterMaterialGrad :: givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - MaterialMode mMode = gp->giveMaterialMode(); - switch ( mMode ) { - case _3dMat: - giveInternalLength(answer, mode, gp, tStep); - break; - default: - OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mMode) ); - } -} void -LargeStrainMasterMaterialGrad :: givePDGradMatrix_LD(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - MaterialMode mMode = gp->giveMaterialMode(); - OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mMode) ); -} - - -void -LargeStrainMasterMaterialGrad :: giveInternalLength(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - this->initTempStatus(gp); - GradDpMaterialExtensionInterface *graddpmat = dynamic_cast< GradDpMaterialExtensionInterface * >( domain->giveMaterial(slaveMat)->giveInterface(GradDpMaterialExtensionInterfaceType) ); - if ( graddpmat == NULL ) { - OOFEM_WARNING("material %d has no Structural support", slaveMat); - return; - } +LargeStrainMasterMaterialGrad :: giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{} - graddpmat->givePDGradMatrix_kk(answer, mode, gp, tStep); -} void LargeStrainMasterMaterialGrad :: give3dGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) @@ -162,13 +130,13 @@ LargeStrainMasterMaterialGrad :: give3dGprime(FloatMatrix &answer, MatResponseMo LargeStrainMasterMaterialStatus *status = static_cast< LargeStrainMasterMaterialStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); FloatMatrix gPrime; - GradDpMaterialExtensionInterface *graddpmat = dynamic_cast< GradDpMaterialExtensionInterface * >( domain->giveMaterial(slaveMat)->giveInterface(GradDpMaterialExtensionInterfaceType) ); + GradientDamageMaterialExtensionInterface *graddpmat = dynamic_cast< GradientDamageMaterialExtensionInterface * >( domain->giveMaterial(slaveMat)->giveInterface(GradientDamageMaterialExtensionInterfaceType) ); if ( graddpmat == NULL ) { OOFEM_WARNING("material %d has no Structural support", slaveMat); return; } - graddpmat->givePDGradMatrix_uk(gPrime, mode, gp, tStep); + graddpmat->giveGradientDamageStiffnessMatrix_ud(gPrime, mode, gp, tStep); gPrime.at(4, 1) = 2. * gPrime.at(4, 1); gPrime.at(5, 1) = 2. * gPrime.at(5, 1); gPrime.at(6, 1) = 2. * gPrime.at(6, 1); @@ -182,13 +150,13 @@ LargeStrainMasterMaterialGrad :: give3dKappaMatrix(FloatMatrix &answer, MatRespo LargeStrainMasterMaterialStatus *status = static_cast< LargeStrainMasterMaterialStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); FloatMatrix kappaMatrix; - GradDpMaterialExtensionInterface *graddpmat = dynamic_cast< GradDpMaterialExtensionInterface * >( domain->giveMaterial(slaveMat)->giveInterface(GradDpMaterialExtensionInterfaceType) ); + GradientDamageMaterialExtensionInterface *graddpmat = dynamic_cast< GradientDamageMaterialExtensionInterface * >( domain->giveMaterial(slaveMat)->giveInterface(GradientDamageMaterialExtensionInterfaceType) ); if ( graddpmat == NULL ) { OOFEM_WARNING("material %d has no Structural support", slaveMat); return; } - graddpmat->givePDGradMatrix_ku(kappaMatrix, mode, gp, tStep); + graddpmat->giveGradientDamageStiffnessMatrix_du(kappaMatrix, mode, gp, tStep); kappaMatrix.at(1, 4) = 2. * kappaMatrix.at(1, 4); kappaMatrix.at(1, 5) = 2. * kappaMatrix.at(1, 5); kappaMatrix.at(1, 6) = 2. * kappaMatrix.at(1, 6); @@ -197,6 +165,30 @@ LargeStrainMasterMaterialGrad :: give3dKappaMatrix(FloatMatrix &answer, MatRespo + +void +LargeStrainMasterMaterialGrad :: giveNonlocalInternalForces_N_factor(double &answer, double nlDamageDrivingVariable, GaussPoint *gp, TimeStep *tStep) +{ + answer = nlDamageDrivingVariable; +} + +void +LargeStrainMasterMaterialGrad :: giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlDamageDrivingVariable_grad, GaussPoint *gp, TimeStep *tStep) +{ + answer = nlDamageDrivingVariable_grad; + answer.times(internalLength * internalLength); +} + + +void +LargeStrainMasterMaterialGrad :: computeLocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep) +{ + // LargeStrainMasterMaterialStatus *status = static_cast< LargeStrainMasterMaterialStatus * >( this->giveStatus(gp) ); + // @todo: solve this + // answer = status->giveTempKappa();w + answer = 1; +} + void LargeStrainMasterMaterialGrad :: giveFirstPKStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &vF, double nonlocalCumulatedStrain, TimeStep *tStep) { @@ -213,7 +205,7 @@ LargeStrainMasterMaterialGrad :: giveFirstPKStressVectorGrad(FloatArray &answer1 return; } - GradDpMaterialExtensionInterface *dpmat = static_cast< GradDpMaterialExtensionInterface * >( sMat->giveInterface(GradDpMaterialExtensionInterfaceType) ); + GradientDamageMaterialExtensionInterface *dpmat = static_cast< GradientDamageMaterialExtensionInterface * >( sMat->giveInterface(GradientDamageMaterialExtensionInterfaceType) ); if ( !dpmat ) { OOFEM_ERROR("Material doesn't implement the required DpGrad interface!"); } @@ -253,8 +245,8 @@ LargeStrainMasterMaterialGrad :: giveFirstPKStressVectorGrad(FloatArray &answer1 SethHillStrainVector.beSymVectorFormOfStrain(SethHillStrain); - dpmat->giveRealStressVectorGrad(stressVector, answer2, gp, SethHillStrainVector, nonlocalCumulatedStrain, tStep); - this->constructTransformationMatrix(T, eVecs); + dpmat->giveRealStressVectorGradientDamage(stressVector, answer2, gp, SethHillStrainVector, nonlocalCumulatedStrain, tStep); + // this->constructTransformationMatrix(T, eVecs); stressVector.at(4) = 2 * stressVector.at(4); stressVector.at(5) = 2 * stressVector.at(5); @@ -266,7 +258,7 @@ LargeStrainMasterMaterialGrad :: giveFirstPKStressVectorGrad(FloatArray &answer1 stressM.at(5) = 1. / 2. * stressM.at(5); stressM.at(6) = 1. / 2. * stressM.at(6); - this->constructL1L2TransformationMatrices(L1, L2, eVals, stressM, E1, E2, E3); + // this->constructL1L2TransformationMatrices(L1, L2, eVals, stressM, E1, E2, E3); FloatMatrix junk, P, TL; FloatArray secondPK; @@ -291,9 +283,9 @@ LargeStrainMasterMaterialGrad :: giveFirstPKStressVectorGrad(FloatArray &answer1 } -IRResultType -LargeStrainMasterMaterialGrad :: initializeFrom(InputRecord *ir) +void +LargeStrainMasterMaterialGrad :: initializeFrom(InputRecord &ir) { - return LargeStrainMasterMaterial :: initializeFrom(ir); + LargeStrainMasterMaterial :: initializeFrom(ir); } } // end namespace oofem diff --git a/src/sm/Materials/lsmastermatgrad.h b/src/sm/Materials/lsmastermatgrad.h index 98bb0f537..433ce1a22 100644 --- a/src/sm/Materials/lsmastermatgrad.h +++ b/src/sm/Materials/lsmastermatgrad.h @@ -42,48 +42,53 @@ #include "dictionary.h" #include "floatarray.h" #include "floatmatrix.h" -#include "graddpmaterialextensioninterface.h" +#include "graddamagematerialextensioninterface.h" namespace oofem { class GaussPoint; class Domain; + +#define _IFT_LargeStrainMasterMaterialGrad_Name "lsmastermatgrad" + + /** * This class implements an gradient version of LargeStrainMasterMaterial */ -class LargeStrainMasterMaterialGrad : public LargeStrainMasterMaterial, GradDpMaterialExtensionInterface +class LargeStrainMasterMaterialGrad : public LargeStrainMasterMaterial, GradientDamageMaterialExtensionInterface { public: - LargeStrainMasterMaterialGrad(int n, Domain * d); - virtual ~LargeStrainMasterMaterialGrad(); + LargeStrainMasterMaterialGrad(int n, Domain *d); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual Interface *giveInterface(InterfaceType t) { - if ( t == GradDpMaterialExtensionInterfaceType ) { - return static_cast< GradDpMaterialExtensionInterface * >(this); + void initializeFrom(InputRecord &ir) override; + bool hasMaterialModeCapability(MaterialMode mode) const override; + Interface *giveInterface(InterfaceType t) override { + if ( t == GradientDamageMaterialExtensionInterfaceType ) { + return static_cast< GradientDamageMaterialExtensionInterface * >( this ); } else { - return NULL; + return nullptr; } } - virtual void giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; - virtual void givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_LD(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + void giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + + void computeLocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep) override; + void giveNonlocalInternalForces_N_factor(double &answer, double nlddv, GaussPoint *gp, TimeStep *tStep) override; + void giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlddv, GaussPoint *gp, TimeStep *tStep) override; void give3dKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); void give3dGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); void giveInternalLength(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual const char *giveClassName() const { return "LargeStrainMasterMaterialGrad"; } + const char *giveClassName() const override { return "LargeStrainMasterMaterialGrad"; } - MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; virtual void giveFirstPKStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalDamageDrivningVariable, TimeStep *tStep); }; - } // end namespace oofem #endif // misesmat_h diff --git a/src/sm/Materials/m4.C b/src/sm/Materials/m4.C index 16317eccc..675a46395 100644 --- a/src/sm/Materials/m4.C +++ b/src/sm/Materials/m4.C @@ -33,7 +33,6 @@ */ #include "m4.h" -#include "microplane.h" #include "floatmatrix.h" #include "floatarray.h" #include "mathfem.h" @@ -46,13 +45,6 @@ M4Material :: M4Material(int n, Domain *d) : MicroplaneMaterial_Bazant(n, d) { } - -inline double -M4Material :: macbra(double x) /* Macauley bracket = positive part of x */ -{ - return ( max(x, 0.0) ); -} - inline double M4Material :: FVplus(double ev, double k1, double c13, double c14, double c15, double Ev) /*positive volumetric boundary */ @@ -109,51 +101,28 @@ M4Material :: FT(double sn, double ev, double k1, double k2, double c10, } -void -M4Material :: giveRealMicroplaneStressVector(FloatArray &answer, - Microplane *mplane, - const FloatArray &strain, - TimeStep *tStep) +MicroplaneState +M4Material :: giveRealMicroplaneStressVector(GaussPoint *gp, int mnumber, + const MicroplaneState &strain, + TimeStep *tStep) const { - M4MaterialStatus *status = static_cast< M4MaterialStatus * >( this->giveMicroplaneStatus(mplane) ); - FloatArray previousStress; - FloatArray strainIncrement; - double EpsN, DEpsN, DEpsL, DEpsM; - double EpsV, DEpsV; - double SEV, SVdash, EpsD, DEpsD, SED, SEM, SEL, SD; + M4MaterialStatus *status = static_cast< M4MaterialStatus * >( this->giveStatus(gp) ); + double SEV, SVdash, SED, SEM, SEL, SD; double SNdash, F; double CV, CD; - - // size answer - answer.resize(4); - answer.zero(); - // ask status for tempVH parameter - previousStress = status->giveStressVector(); - strainIncrement.beDifferenceOf( strain, status->giveStrainVector() ); - if ( !previousStress.isNotEmpty() ) { - previousStress.resize(4); - previousStress.zero(); - } - - EpsV = strain.at(1); - EpsN = strain.at(2); - DEpsV = strainIncrement.at(1); - DEpsN = strainIncrement.at(2); - DEpsL = strainIncrement.at(3); - DEpsM = strainIncrement.at(4); - EpsD = EpsN - EpsV; - DEpsD = DEpsN - DEpsV; - - /* previousStress.at(i)...Vector of history parameters - * (1)...previous volumetric stress - * (2)..previous normal stress for microplane - * (3)..previous l-shear stress for microplane - * (4)..previous m-shear stress for microplane - * - */ - + auto &prevStrain = status->giveMicroplaneStrain(mnumber); + auto &previousStress = status->giveMicroplaneStress(mnumber); + + double EpsV = strain.v; + double EpsN = strain.n; + double DEpsV = strain.v - prevStrain.v; + double DEpsN = strain.n - prevStrain.n; + double DEpsL = strain.l - prevStrain.l; + double DEpsM = strain.m - prevStrain.m; + double EpsD = EpsN - EpsV; + double DEpsD = DEpsN - DEpsV; // SVsum=0.0; // novy koncept s odtizenim @@ -171,59 +140,57 @@ M4Material :: giveRealMicroplaneStressVector(FloatArray &answer, * // if (SigD0*DEpsD<0.0) CD = fabs(SigD0/EpsD0); */ - SEV = previousStress.at(1) + CV * DEpsV; + MicroplaneState answer; + + SEV = previousStress.v + CV * DEpsV; SVdash = min( max( SEV, this->FVminus(EpsV, k1, k3, k4, E) ), this->FVplus(EpsV, k1, c13, c14, c15, EV) ); - SED = previousStress.at(2) - previousStress.at(1) + CD * DEpsD; + SED = previousStress.n - previousStress.v + CD * DEpsD; SD = min( max( SED, this->FDminus(EpsD, k1, c7, c8, c9, E) ), this->FDplus(EpsD, k1, c5, c6, c7, c20, E) ); SNdash = SVdash + SD; - answer.at(2) = min( SNdash, this->FN(EpsN, previousStress.at(1), k1, c1, c2, c3, c4, E, EV) ); + answer.n = min( SNdash, this->FN(EpsN, previousStress.v, k1, c1, c2, c3, c4, E, EV) ); - SEM = previousStress.at(4) + ET * DEpsM; - SEL = previousStress.at(3) + ET * DEpsL; + SEM = previousStress.m + ET * DEpsM; + SEL = previousStress.l + ET * DEpsL; - F = this->FT(answer.at(2), EpsV, k1, k2, c10, c11, c12, ET); + F = this->FT(answer.n, EpsV, k1, k2, c10, c11, c12, ET); if ( SEL > F ) { - answer.at(3) = F; + answer.l = F; } else if ( SEL < -F ) { - answer.at(3) = -F; + answer.l = -F; } else { - answer.at(3) = SEL; + answer.l = SEL; } if ( SEM > F ) { - answer.at(4) = F; + answer.m = F; } else if ( SEM < -F ) { - answer.at(4) = -F; + answer.m = -F; } else { - answer.at(4) = SEM; + answer.m = SEM; } - answer.at(1) = SVdash; + answer.v = SVdash; // uncomment this //stressIncrement = answer; //stressIncrement.subtract (previousStress); - //status->letStressIncrementVectorBe (stressIncrement); - //status->letStrainIncrementVectorBe (strainIncrement); // update gp - status->letTempStrainVectorBe(strain); - status->letTempStressVectorBe(answer); + status->letTempMicroplaneStrainBe(mnumber, strain); + status->letTempMicroplaneStressBe(mnumber, answer); + return answer; } -IRResultType -M4Material :: initializeFrom(InputRecord *ir) +void +M4Material :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = MicroplaneMaterial_Bazant :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + MicroplaneMaterial_Bazant :: initializeFrom(ir); c1 = 6.20e-1; c2 = 2.76; @@ -258,29 +225,25 @@ M4Material :: initializeFrom(InputRecord *ir) EV = E / ( 1 - 2 * nu ); ED = 5 * E / ( 2 + 3 * mu ) / ( 1 + nu ); ET = mu * ED; - - return IRRT_OK; } void -M4Material :: updateVolumetricStressTo(Microplane *mPlane, double sigv) +M4Material :: updateVolumetricStressTo(GaussPoint *gp, int mnumber, double sigv) const { //FloatArray stressIncrement; - FloatArray stress; - M4MaterialStatus *status = static_cast< M4MaterialStatus * >( this->giveStatus(mPlane) ); + M4MaterialStatus *status = static_cast< M4MaterialStatus * >( this->giveStatus(gp) ); //stressIncrement = status->giveStressIncrementVector(); //stressIncrement.at(1) = sigv - status->giveStressVector().at(1); //status->letStressIncrementVectorBe (stressIncrement); - stress = status->giveTempStressVector(); - stress.at(1) = sigv; - status->letTempStressVectorBe(stress); + auto stress = status->giveTempMicroplaneStress(mnumber); + stress.v = sigv; + status->letTempMicroplaneStressBe(mnumber, stress); } -void -M4Material :: giveThermalDilatationVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep) +FloatArrayF<6> +M4Material :: giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const // // returns a FloatArray(6) of initial strain vector // eps_0 = {exx_0, eyy_0, ezz_0, gyz_0, gxz_0, gxy_0}^T @@ -288,24 +251,26 @@ M4Material :: giveThermalDilatationVector(FloatArray &answer, // gp (element) local axes // { - answer.resize(6); - answer.zero(); - answer.at(1) = talpha; - answer.at(2) = talpha; - answer.at(3) = talpha; + return { + talpha, + talpha, + talpha, + 0., + 0., + 0., + }; } //////////////////////////////////////////////////////////////////////////// -M4MaterialStatus :: M4MaterialStatus(int n, Domain *d, GaussPoint *g) : - StructuralMaterialStatus(n, d, g) +M4MaterialStatus :: M4MaterialStatus(GaussPoint *g, int nplanes) : + StructuralMaterialStatus(g), + microplaneStrain(nplanes), tempMicroplaneStrain(nplanes), + microplaneStress(nplanes), tempMicroplaneStress(nplanes) { } -M4MaterialStatus :: ~M4MaterialStatus() -{ } - void M4MaterialStatus :: initTempStatus() { @@ -316,17 +281,21 @@ void M4MaterialStatus :: updateYourself(TimeStep *tStep) { StructuralMaterialStatus :: updateYourself(tStep); + microplaneStrain = tempMicroplaneStrain; + microplaneStress = tempMicroplaneStress; } -contextIOResultType -M4MaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +M4MaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - return StructuralMaterialStatus :: saveContext(stream, mode, obj); + StructuralMaterialStatus :: saveContext(stream, mode); + /// @todo, save microplanestress etc. } -contextIOResultType -M4MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +M4MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - return StructuralMaterialStatus :: restoreContext(stream, mode, obj); + StructuralMaterialStatus :: restoreContext(stream, mode); + /// @todo, save microplanestress etc. } } // end namespace oofem diff --git a/src/sm/Materials/m4.h b/src/sm/Materials/m4.h index 63e8bbd0f..592f9e0a1 100644 --- a/src/sm/Materials/m4.h +++ b/src/sm/Materials/m4.h @@ -36,7 +36,7 @@ #define m4_h #include "microplanematerial_bazant.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" ///@name Input fields for M4Material //@{ @@ -59,18 +59,28 @@ namespace oofem { */ class M4MaterialStatus : public StructuralMaterialStatus { +protected: + std::vector microplaneStrain, tempMicroplaneStrain; + std::vector microplaneStress, tempMicroplaneStress; + public: - M4MaterialStatus(int n, Domain *d, GaussPoint *g); - virtual ~M4MaterialStatus(); + M4MaterialStatus(GaussPoint *g, int nplanes); + + const char *giveClassName() const override { return "M4MaterialStatus"; } - // definition - virtual const char *giveClassName() const { return "M4MaterialStatus"; } + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + const MicroplaneState &giveMicroplaneStrain(int mnumber) const { return microplaneStrain[mnumber-1]; } + const MicroplaneState &giveMicroplaneStress(int mnumber) const { return microplaneStress[mnumber-1]; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + const MicroplaneState &giveTempMicroplaneStress(int mnumber) const { return tempMicroplaneStress[mnumber-1]; } + + void letTempMicroplaneStrainBe(int mnumber, const MicroplaneState &state) { tempMicroplaneStrain[mnumber-1] = state; } + void letTempMicroplaneStressBe(int mnumber, const MicroplaneState &state) { tempMicroplaneStress[mnumber-1] = state; } + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -81,12 +91,13 @@ class M4MaterialStatus : public StructuralMaterialStatus class M4Material : public MicroplaneMaterial_Bazant { protected: - - double c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12; - double c13, c14, c15, c16, c17, c18, c19, c20; /*c... fixed empirical constants*/ - double k1, k2, k3, k4, k5, mu; - double EV, ED, ET; - double talpha; + double c1 = 0., c2 = 0., c3 = 0., c4 = 0., c5 = 0.; + double c6 = 0., c7 = 0., c8 = 0., c9 = 0., c10 = 0.; + double c11 = 0., c12 = 0., c13 = 0., c14 = 0., c15 = 0.; + double c16 = 0., c17 = 0., c18 = 0., c19 = 0., c20 = 0.; /*c... fixed empirical constants*/ + double k1 = 0., k2 = 0., k3 = 0., k4 = 0., k5 = 0., mu = 0.; + double EV = 0., ED = 0., ET = 0.; + double talpha = 0.; public: /** @@ -96,31 +107,28 @@ class M4Material : public MicroplaneMaterial_Bazant * @param d Domain to which newly created material belongs. */ M4Material(int n, Domain *d); - /// Destructor. - virtual ~M4Material() { } - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + FloatArrayF<6> giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealMicroplaneStressVector(FloatArray &answer, Microplane *mplane, const FloatArray &strain, TimeStep *tStep); + MicroplaneState giveRealMicroplaneStressVector(GaussPoint *gp, int mnumber, const MicroplaneState &strain, TimeStep *tStep) const override; - double macbra(double x); - double FVplus(double ev, double k1, double c13, double c14, double c15, double Ev); - double FVminus(double ev, double k1, double k3, double k4, double E); - double FDminus(double ed, double k1, double c7, double c8, double c9, double E); - double FDplus(double ed, double k1, double c5, double c6, double c7, double c20, double E); - double FN(double en, double sv, double k1, double c1, double c2, double c3, double c4, + static double FVplus(double ev, double k1, double c13, double c14, double c15, double Ev); + static double FVminus(double ev, double k1, double k3, double k4, double E); + static double FDminus(double ed, double k1, double c7, double c8, double c9, double E); + static double FDplus(double ed, double k1, double c5, double c6, double c7, double c20, double E); + static double FN(double en, double sv, double k1, double c1, double c2, double c3, double c4, double E, double Ev); - double FT(double sn, double ev, double k1, double k2, double c10, + static double FT(double sn, double ev, double k1, double k2, double c10, double c11, double c12, double Et); - virtual void updateVolumetricStressTo(Microplane *mPlane, double sigv); + void updateVolumetricStressTo(GaussPoint *gp, int mnumber, double sigv) const override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveInputRecordName() const { return _IFT_M4Material_Name; } - virtual const char *giveClassName() const { return "M4Material"; } + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_M4Material_Name; } + const char *giveClassName() const override { return "M4Material"; } protected: - MaterialStatus *CreateMicroplaneStatus(GaussPoint *gp) { return new M4MaterialStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new M4MaterialStatus(gp, numberOfMicroplanes); } }; } // end namespace oofem #endif // m4_h diff --git a/src/sm/Materials/mdm.C b/src/sm/Materials/mdm.C index 4307c9253..52163e846 100644 --- a/src/sm/Materials/mdm.C +++ b/src/sm/Materials/mdm.C @@ -37,10 +37,9 @@ #include "floatmatrix.h" #include "floatarray.h" #include "mathfem.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "mmaclosestiptransfer.h" #include "nonlocalmaterialext.h" -#include "microplane.h" #include "contextioerr.h" #include "classfactory.h" #include "dynamicinputrecord.h" @@ -74,19 +73,12 @@ MMAClosestIPTransfer MDM :: mapper2; MaterialStatus * MDM :: CreateStatus(GaussPoint *gp) const { - if ( dynamic_cast< Microplane * >(gp) ) { - return NULL; - } else { - return new MDMStatus(1, this->nsd, this->numberOfMicroplanes, MicroplaneMaterial :: giveDomain(), gp); - } + return new MDMStatus(gp, this->nsd, this->numberOfMicroplanes); } -int -MDM :: hasMaterialModeCapability(MaterialMode mode) -// -// returns whether receiver supports given mode -// +bool +MDM :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _3dMat || mode == _PlaneStress || mode == _PlaneStrain; } @@ -159,7 +151,7 @@ MDM :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, void MDM :: computeDamageTensor(FloatMatrix &damageTensor, const FloatArray &totalStrain, - GaussPoint *gp, TimeStep *tStep) + GaussPoint *gp, TimeStep *tStep) const { // local or nonlocal if ( nonlocal ) { @@ -204,22 +196,17 @@ MDM :: computeDamageTensor(FloatMatrix &damageTensor, const FloatArray &totalStr void MDM :: computeLocalDamageTensor(FloatMatrix &damageTensor, const FloatArray &totalStrain, - GaussPoint *gp, TimeStep *tStep) + GaussPoint *gp, TimeStep *tStep) const { - int im1; - double PsiOld, Psi; FloatArray damageVector(6); - Microplane *mPlane; MDMStatus *status = static_cast< MDMStatus * >( this->giveStatus(gp) ); // Loop over microplanes. for ( int im = 0; im < numberOfMicroplanes; im++ ) { - mPlane = this->giveMicroplane(im, gp); - im1 = im + 1; - - Psi = computeDamageOnPlane(gp, mPlane, totalStrain); + int im1 = im + 1; - PsiOld = status->giveMicroplaneDamage(im1); + double Psi = computeDamageOnPlane(gp, im1, totalStrain); + double PsiOld = status->giveMicroplaneDamage(im1); if ( PsiOld > Psi ) { Psi = PsiOld; } @@ -274,7 +261,7 @@ MDM :: computeLocalDamageTensor(FloatMatrix &damageTensor, const FloatArray &tot #define HUGE_RELATIVE_COMPLIANCE 1.e20 double -MDM :: computeDamageOnPlane(GaussPoint *gp, Microplane *mplane, const FloatArray &strain) +MDM :: computeDamageOnPlane(GaussPoint *gp, int mnumber, const FloatArray &strain) const { double en, em, el, Ep, Efp, ParEpp; double Enorm = 0.0, sv = 0.0, answer = 0.0; @@ -284,9 +271,9 @@ MDM :: computeDamageOnPlane(GaussPoint *gp, Microplane *mplane, const FloatArray StructuralMaterial :: giveInvertedVoigtVectorMask( mask, gp->giveMaterialMode() ); StructuralMaterial :: giveFullSymVectorForm( fullStrain, strain, gp->giveMaterialMode() ); - en = this->computeNormalStrainComponent(mplane, fullStrain); - em = this->computeShearMStrainComponent(mplane, fullStrain); - el = this->computeShearLStrainComponent(mplane, fullStrain); + en = this->computeNormalStrainComponent(mnumber, fullStrain); + em = this->computeShearMStrainComponent(mnumber, fullStrain); + el = this->computeShearLStrainComponent(mnumber, fullStrain); // request raw parameters @@ -302,7 +289,7 @@ MDM :: computeDamageOnPlane(GaussPoint *gp, Microplane *mplane, const FloatArray } ParEpp = Ep / ( 1. - ParMd ); // 1d sv reduction - fmicroplane = linearElasticMaterial->give('E', gp) * ParEpp; + fmicroplane = linearElasticMaterial.give('E', gp) * ParEpp; // en /= (1.-ParMd*sv); en /= ( 1. - ParMd * sv / ( fmicroplane ) ); // suggested by P.Grassl (ParMd is unit dependent) @@ -347,7 +334,7 @@ MDM :: computeDamageOnPlane(GaussPoint *gp, Microplane *mplane, const FloatArray void MDM :: computePDC(FloatMatrix &tempDamageTensor, FloatArray &tempDamageTensorEigenVals, - FloatMatrix &tempDamageTensorEigenVec) + FloatMatrix &tempDamageTensorEigenVec) const { FloatMatrix help = tempDamageTensor; @@ -369,7 +356,7 @@ MDM :: computePDC(FloatMatrix &tempDamageTensor, FloatArray &tempDamageTensorEig void MDM :: transformStrainToPDC(FloatArray &answer, FloatArray &strain, - FloatMatrix &t, GaussPoint *gp) + FloatMatrix &t, GaussPoint *gp) const { FloatArray fullStrain; @@ -413,7 +400,7 @@ MDM :: transformStrainToPDC(FloatArray &answer, FloatArray &strain, } void -MDM :: applyDamageTranformation(FloatArray &strainPDC, const FloatArray &tempDamageTensorEigenVals) +MDM :: applyDamageTranformation(FloatArray &strainPDC, const FloatArray &tempDamageTensorEigenVals) const { if ( mdmMode == mdm_3d ) { double psi1 = tempDamageTensorEigenVals.at(1); @@ -464,12 +451,13 @@ MDM :: applyDamageTranformation(FloatArray &strainPDC, const FloatArray &tempDam void MDM :: computeEffectiveStress(FloatArray &stressPDC, const FloatArray &strainPDC, GaussPoint *gp, TimeStep *tStep) { + //FloatMatrixF<6,6> de; FloatMatrix de; if ( mdmMode == mdm_3d ) { // PDC components in 3d mode are in full 3d format, even in planeStrain situation - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(de, TangentStiffness, gp, tStep); + de = linearElasticMaterial.give3dMaterialStiffnessMatrix(TangentStiffness, gp, tStep); } else { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(de, TangentStiffness, gp, tStep); + linearElasticMaterial.giveStiffnessMatrix(de, TangentStiffness, gp, tStep); } stressPDC.beProductOf(de, strainPDC); @@ -481,7 +469,7 @@ MDM :: computeEffectiveStress(FloatArray &stressPDC, const FloatArray &strainPDC #define S(p) stressPDC.at(p) void -MDM :: transformStressFromPDC(FloatArray &answer, const FloatArray &stressPDC, const FloatMatrix &t, GaussPoint *gp) +MDM :: transformStressFromPDC(FloatArray &answer, const FloatArray &stressPDC, const FloatMatrix &t, GaussPoint *gp) const { if ( mdmMode == mdm_3d ) { FloatArray fullAnswer(6); @@ -525,11 +513,12 @@ void MDM :: giveMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - MDMStatus *status = static_cast< MDMStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MDMStatus * >( this->giveStatus(gp) ); - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, TangentStiffness, gp, tStep); + /// FIXME: ask for 3d stiffness? + const_cast(this)->linearElasticMaterial.giveStiffnessMatrix(answer, TangentStiffness, gp, tStep); //answer = de; //return; // if (isVirgin()) return ; @@ -546,7 +535,7 @@ MDM :: giveMaterialStiffnessMatrix(FloatMatrix &answer, #define MAX_REL_COMPL_TRESHOLD 1.e6 void -MDM :: applyDamageToStiffness(FloatMatrix &d, GaussPoint *gp) +MDM :: applyDamageToStiffness(FloatMatrix &d, GaussPoint *gp) const { MDMStatus *status = static_cast< MDMStatus * >( this->giveStatus(gp) ); @@ -631,38 +620,41 @@ MDM :: applyDamageToStiffness(FloatMatrix &d, GaussPoint *gp) void -MDM :: transformStiffnessfromPDC(FloatMatrix &de, const FloatMatrix &t) +MDM :: transformStiffnessfromPDC(FloatMatrix &de, const FloatMatrix &t) const { this->rotateTensor4(de, t); } -void -MDM :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +MDM :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } -void -MDM :: givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) + +FloatMatrixF<3,3> +MDM :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } -void -MDM :: givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<4,4> +MDM :: givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } - int MDM :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { @@ -767,26 +759,24 @@ MDM :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, T } } -void -MDM :: giveThermalDilatationVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep) +FloatArrayF<6> +MDM :: giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const { - answer.resize(6); - answer.zero(); - answer.at(1) = this->tempDillatCoeff; - answer.at(2) = this->tempDillatCoeff; - answer.at(3) = this->tempDillatCoeff; + return { + this->tempDillatCoeff, + this->tempDillatCoeff, + this->tempDillatCoeff, + 0., 0., 0. + }; } -IRResultType -MDM :: initializeFrom(InputRecord *ir) +void +MDM :: initializeFrom(InputRecord &ir) // // initializes according to string // { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, this->tempDillatCoeff, _IFT_MDM_talpha); IR_GIVE_FIELD(ir, this->ParMd, _IFT_MDM_parmd); IR_GIVE_FIELD(ir, this->nonlocal, _IFT_MDM_nonloc); @@ -797,28 +787,26 @@ MDM :: initializeFrom(InputRecord *ir) R = 0.0; } - if ( ( ir->hasField(_IFT_MDM_efp) ) && ( ir->hasField(_IFT_MDM_ep) ) ) { + if ( ir.hasField(_IFT_MDM_efp) && ir.hasField(_IFT_MDM_ep) ) { // read raw_params if available IR_GIVE_FIELD(ir, this->mdm_Efp, _IFT_MDM_efp); IR_GIVE_FIELD(ir, this->mdm_Ep, _IFT_MDM_ep); - } else if ( ( ir->hasField(_IFT_MDM_gf) ) && ( ir->hasField(_IFT_MDM_ft) ) ) { + } else if ( ir.hasField(_IFT_MDM_gf) && ir.hasField(_IFT_MDM_ft) ) { IR_GIVE_FIELD(ir, this->Gf, _IFT_MDM_gf); IR_GIVE_FIELD(ir, this->Ft, _IFT_MDM_ft); } else { - OOFEM_WARNING("unknown set of parameters"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_MDM_nonloc, "unknown set of parameters"); } } else { // local case - if ( ( ir->hasField(_IFT_MDM_efp) ) && ( ir->hasField(_IFT_MDM_ep) ) ) { + if ( ir.hasField(_IFT_MDM_efp) && ir.hasField(_IFT_MDM_ep) ) { // read raw_params if available IR_GIVE_FIELD(ir, this->mdm_Efp, _IFT_MDM_efp); IR_GIVE_FIELD(ir, this->mdm_Ep, _IFT_MDM_ep); - } else if ( ( ir->hasField(_IFT_MDM_gf) ) && ( ir->hasField(_IFT_MDM_ep) ) ) { + } else if ( ir.hasField(_IFT_MDM_gf) && ir.hasField(_IFT_MDM_ep) ) { IR_GIVE_FIELD(ir, this->Gf, _IFT_MDM_gf); IR_GIVE_FIELD(ir, this->mdm_Ep, _IFT_MDM_ep); } else { - OOFEM_WARNING("unknown set of parameters"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_MDM_nonloc, "unknown set of parameters"); } } @@ -846,37 +834,27 @@ MDM :: initializeFrom(InputRecord *ir) OOFEM_LOG_INFO("MDM: using optional mapper %d\n", mapperType); #endif - result = MicroplaneMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + MicroplaneMaterial :: initializeFrom(ir); if ( this->nonlocal ) { - result = StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); } - linearElasticMaterial = new IsotropicLinearElasticMaterial( 1, MicroplaneMaterial :: giveDomain() ); - result = linearElasticMaterial->initializeFrom(ir); - if ( result != IRRT_OK ) return result; + linearElasticMaterial.initializeFrom(ir); #ifdef MDM_MAPPING_DEBUG - result = mapperSFT.initializeFrom(ir); - if ( result != IRRT_OK ) return result; - result = mapperLST.initializeFrom(ir); - if ( result != IRRT_OK ) return result; + mapperSFT.initializeFrom(ir); + mapperLST.initializeFrom(ir); #else - result = mapper.initializeFrom(ir); - if ( result != IRRT_OK ) return result; + mapper.initializeFrom(ir); #endif - result = mapper2.initializeFrom(ir); - if ( result != IRRT_OK ) return result; - - return IRRT_OK; + mapper2.initializeFrom(ir); } void MDM :: giveInputRecord(DynamicInputRecord &input) { - linearElasticMaterial->giveInputRecord(input); + linearElasticMaterial.giveInputRecord(input); MicroplaneMaterial :: giveInputRecord(input); StructuralNonlocalMaterialExtensionInterface :: giveInputRecord(input); #ifdef MDM_MAPPING_DEBUG @@ -920,7 +898,7 @@ void MDM :: giveInputRecord(DynamicInputRecord &input) void -MDM :: rotateTensor4(FloatMatrix &Dlocal, const FloatMatrix &t) +MDM :: rotateTensor4(FloatMatrix &Dlocal, const FloatMatrix &t) const // // Interpreting "t" as the rotation matrix containing in its // columns the local base vectors, transform a fourth-order tensor @@ -940,7 +918,7 @@ MDM :: rotateTensor4(FloatMatrix &Dlocal, const FloatMatrix &t) void -MDM :: formTransformationMatrix(FloatMatrix &answer, const FloatMatrix &t, int n) +MDM :: formTransformationMatrix(FloatMatrix &answer, const FloatMatrix &t, int n) const // // Interpreting "t" as the rotation matrix containing in its // columns the local base vectors, form the transformation matrix @@ -991,7 +969,7 @@ MDM :: formTransformationMatrix(FloatMatrix &answer, const FloatMatrix &t, int n } void -MDM :: giveRawMDMParameters(double &Efp, double &Ep, const FloatArray &reducedStrain, GaussPoint *gp) +MDM :: giveRawMDMParameters(double &Efp, double &Ep, const FloatArray &reducedStrain, GaussPoint *gp) const { // test if raw parameters are given if ( this->mdm_Efp > 0.0 ) { @@ -1003,7 +981,7 @@ MDM :: giveRawMDMParameters(double &Efp, double &Ep, const FloatArray &reducedSt // determine params from macroscopic ones if ( nonlocal ) { // formulas derived for 3d case - double EModulus = linearElasticMaterial->give('E', gp); + double EModulus = linearElasticMaterial.give('E', gp); double gammaf = ( EModulus * this->Gf ) / ( this->R * this->Ft * this->Ft ); double gamma = gammaf / ( 1.47 - 0.0014 * gammaf ); double f = this->Ft / ( 1.56 + 0.006 * gamma ); // microplane tensile strength @@ -1038,7 +1016,7 @@ MDM :: giveRawMDMParameters(double &Efp, double &Ep, const FloatArray &reducedSt dir.at(3) = dirs.at(3, indx); h = gp->giveElement()->giveCharacteristicLength(dir); - double E = this->giveLinearElasticMaterial()->give(Ex, gp); + double E = linearElasticMaterial.give(Ex, gp); Ep = this->mdm_Ep; if ( nsd == 2 ) { Efp = ( Gf / ( h * E * Ep ) + 1.2 * Ep ) / 1.75 - Ep; @@ -1112,14 +1090,18 @@ MDM :: initializeData(int numberOfMicroplanes) OOFEM_ERROR("required number of microplanes too big"); } - int iplane; - int i, ii, jj; double alpha = M_PI / numberOfMicroplanes; FloatArray n(3), m(3), l(3); int ij [ 6 ] [ 2 ] = { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 2, 3 }, { 3, 1 }, { 1, 2 } }; - - for ( iplane = 0; iplane < numberOfMicroplanes; iplane++ ) { + + microplaneNormals.resize(numberOfMicroplanes); + microplaneWeights.resize(numberOfMicroplanes); + M.resize(numberOfMicroplanes); + N.resize(numberOfMicroplanes); + L.resize(numberOfMicroplanes); + + for ( int iplane = 0; iplane < numberOfMicroplanes; iplane++ ) { microplaneWeights [ iplane ] = alpha; n.at(1) = microplaneNormals [ iplane ] [ 0 ] = cos(iplane * alpha); @@ -1135,9 +1117,9 @@ MDM :: initializeData(int numberOfMicroplanes) l.at(2) = 0.0; l.at(3) = 1.0; - for ( i = 0; i < 6; i++ ) { - ii = ij [ i ] [ 0 ]; - jj = ij [ i ] [ 1 ]; + for ( int i = 0; i < 6; i++ ) { + int ii = ij [ i ] [ 0 ]; + int jj = ij [ i ] [ 1 ]; N [ iplane ] [ i ] = n.at(ii) * n.at(jj); M [ iplane ] [ i ] = 0.5 * ( m.at(ii) * n.at(jj) + m.at(jj) * n.at(ii) ); @@ -1153,7 +1135,7 @@ MDM :: initializeData(int numberOfMicroplanes) void -MDM :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) +MDM :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const { /* Implements the service updating local variables in given integration points, * which take part in nonlocal average process. @@ -1161,20 +1143,19 @@ MDM :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, * corresponding status variable. * This service is declared at StructuralNonlocalMaterial level. */ - MDMStatus *status = static_cast< MDMStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MDMStatus * >( this->giveStatus(gp) ); FloatMatrix tempDamageTensor; - this->computeLocalDamageTensor(tempDamageTensor, strainVector, gp, tStep); status->setLocalDamageTensorForAverage(tempDamageTensor); } double -MDM :: computeWeightFunction(const FloatArray &src, const FloatArray &coord) +MDM :: computeWeightFunction(const double R, const FloatArray &src, const FloatArray &coord) const { // Bell shaped function decaying with the distance. - double dist = src.distance(coord); + double dist = distance(src, coord); if ( ( dist >= 0. ) && ( dist <= this->R ) ) { double help = ( 1. - dist * dist / ( R * R ) ); @@ -1196,8 +1177,8 @@ MDM :: MMI_map(GaussPoint *gp, Domain *oldd, TimeStep *tStep) toMap.at(1) = ( int ) IST_MicroplaneDamageValues; // Set up source element set if not set up by user - if ( sourceElemSet == NULL ) { - sourceElemSet = new Set(0, oldd); + if ( !sourceElemSet ) { + sourceElemSet = std::make_unique(0, oldd); IntArray el; // compile source list to contain all elements on old odmain with the same material id for ( int i = 1; i <= oldd->giveNumberOfElements(); i++ ) { @@ -1383,7 +1364,7 @@ MDM :: predictRelativeComputationalCost(GaussPoint *gp) -MDMStatus :: MDMStatus(int n, int nsd, int nmplanes, Domain *d, GaussPoint *g) : StructuralMaterialStatus(n, d, g), StructuralNonlocalMaterialStatusExtensionInterface(), Psi(nmplanes), PsiTemp(nmplanes), DamageTensor(nsd, nsd), DamageTensorTemp(nsd, nsd), tempDamageTensorEigenValues(nsd), damageTensorEigenValues(nsd), tempDamageTensorEigenVectors(nsd, nsd), damageTensorEigenVectors(nsd, nsd) +MDMStatus :: MDMStatus(GaussPoint *g, int nsd, int nmplanes) : StructuralMaterialStatus(g), StructuralNonlocalMaterialStatusExtensionInterface(), Psi(nmplanes), PsiTemp(nmplanes), DamageTensor(nsd, nsd), DamageTensorTemp(nsd, nsd), tempDamageTensorEigenValues(nsd), damageTensorEigenValues(nsd), tempDamageTensorEigenVectors(nsd, nsd), damageTensorEigenVectors(nsd, nsd) { for ( int i = 1; i <= nsd; i++ ) { damageTensorEigenValues.at(i) = tempDamageTensorEigenValues.at(i) = 1.0; @@ -1392,18 +1373,12 @@ MDMStatus :: MDMStatus(int n, int nsd, int nmplanes, Domain *d, GaussPoint *g) : } -MDMStatus :: ~MDMStatus() { } - -contextIOResultType -MDMStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +MDMStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: saveContext(stream, mode); + contextIOResultType iores; if ( ( iores = Psi.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -1419,21 +1394,15 @@ MDMStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) if ( ( iores = damageTensorEigenVectors.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -MDMStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +MDMStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: restoreContext(stream, mode); + contextIOResultType iores; if ( ( iores = Psi.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -1449,8 +1418,6 @@ MDMStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) if ( ( iores = damageTensorEigenVectors.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } void @@ -1476,7 +1443,7 @@ MDMStatus :: initTempStatus() } void -MDMStatus :: printOutputAt(FILE *file, TimeStep *tStep) +MDMStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -1512,7 +1479,7 @@ MDMStatus :: giveInterface(InterfaceType type) if ( type == NonlocalMaterialStatusExtensionInterfaceType ) { return this; } else { - return NULL; + return nullptr; } } } // end namespace oofem diff --git a/src/sm/Materials/mdm.h b/src/sm/Materials/mdm.h index e5b716e2e..d6b0d19c9 100644 --- a/src/sm/Materials/mdm.h +++ b/src/sm/Materials/mdm.h @@ -50,7 +50,8 @@ #include "microplanematerial.h" #include "structuralnonlocalmaterialext.h" #include "matconst.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/isolinearelasticmaterial.h" +#include "sm/Materials/structuralms.h" #include "materialmapperinterface.h" #include "mmaclosestiptransfer.h" @@ -89,7 +90,6 @@ //@} namespace oofem { -class Microplane; /** * Material status class MDMStatus associated to MDM matarial @@ -106,8 +106,7 @@ class MDMStatus : public StructuralMaterialStatus, public StructuralNonlocalMate FloatMatrix tempDamageTensorEigenVectors, damageTensorEigenVectors; public: - MDMStatus(int n, int nsd, int nmplanes, Domain * d, GaussPoint * g); - virtual ~MDMStatus(); + MDMStatus(GaussPoint * g, int nsd, int nmplanes); void setTempDamageTensorEigenVals(FloatArray src) { tempDamageTensorEigenValues = std :: move(src); } void setTempDamageTensorEigenVec(FloatMatrix src) { tempDamageTensorEigenVectors = std :: move(src); } @@ -129,17 +128,15 @@ class MDMStatus : public StructuralMaterialStatus, public StructuralNonlocalMate const FloatMatrix &giveLocalDamageTensorForAverage() { return localDamageTensor; } const FloatMatrix *giveLocalDamageTensorForAveragePtr() { return & localDamageTensor; } + const char *giveClassName() const override { return "MDMStatus"; } - // definition - virtual const char *giveClassName() const { return "MDMStatus"; } + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; /** * Interface requesting service. In the case of nonlocal constitutive models, @@ -151,7 +148,7 @@ class MDMStatus : public StructuralMaterialStatus, public StructuralNonlocalMate * returning adress of component or using pointer conversion from receiver to base class * NonlocalMaterialStatusExtension. If no nonlocal extension exists, NULL pointer is returned. */ - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; }; @@ -165,36 +162,36 @@ class MDM : public MicroplaneMaterial, public StructuralNonlocalMaterialExtensio enum MDMModeType { mdm_3d, mdm_2d }; protected: - int ndc; ///< Number of damage components. - int nsd; ///< Number of spatial dimensions. - int type_dam; - int type_soft; + int ndc = 0; ///< Number of damage components. + int nsd = 0; ///< Number of spatial dimensions. + int type_dam = 0; + int type_soft = 0; /// Parameter controlling the elastic limit. - double mdm_Ep; + mutable double mdm_Ep = 0.; /// Prescribed value of ef-ep. - double mdm_Efp; - double ParMd; ///< (m/E*Ep) - double tempDillatCoeff; ///< Temperature dilatation coeff. + mutable double mdm_Efp = 0.; /// THREAD UNSAFE. These are modified when evaluating the material. Why? This must be avoided at all cost. + double ParMd = 0.; ///< (m/E*Ep) + double tempDillatCoeff = 0.; ///< Temperature dilatation coeff. /// Fracture energy (necessary to determine Ep and Efp if not given). - double Gf; + double Gf = 0.; /// Macroscopic tensile strength (necessary to determine Ep and Efp if not given). - double Ft; + double Ft = 0.; - MDMFormulatrionType formulation; - MDMModeType mdmMode; + MDMFormulatrionType formulation = COMPLIANCE_DAMAGE; + MDMModeType mdmMode = mdm_3d; /// Reference to bulk (undamaged) material. - StructuralMaterial *linearElasticMaterial; + IsotropicLinearElasticMaterial linearElasticMaterial; /// Flag indicating local or nonlocal mode. - int nonlocal; + int nonlocal = 0; /// Interaction radius, related to the nonlocal characteristic length of material. - double R; + double R = 0.; ///cached source element set used to map internal variables (adaptivity), created on demand - Set *sourceElemSet; + std::unique_ptr sourceElemSet; #ifdef MDM_MAPPING_DEBUG /// Mapper used to map internal variables in adaptivity. @@ -203,7 +200,7 @@ class MDM : public MicroplaneMaterial, public StructuralNonlocalMaterialExtensio // determines the mapping algorithm to be used enum MDMMapperType { mdm_cpt=0, mdm_sft=1, mdm_lst=2 }; - MDMMapperType mapperType; + MDMMapperType mapperType = mdm_cpt; #else #ifdef MDM_USE_MMAClosestIPTransfer @@ -229,121 +226,105 @@ class MDM : public MicroplaneMaterial, public StructuralNonlocalMaterialExtensio * @param n Material number. * @param d Domain to which newly created material belongs. */ - MDM(int n, Domain * d) : MicroplaneMaterial(n, d), StructuralNonlocalMaterialExtensionInterface(d), MaterialModelMapperInterface() + MDM(int n, Domain * d) : MicroplaneMaterial(n, d), + StructuralNonlocalMaterialExtensionInterface(d), + MaterialModelMapperInterface(), + linearElasticMaterial(n, d) { - linearElasticMaterial = NULL; - nonlocal = 0; - type_dam = 0; - type_soft = 0; mdm_Ep = mdm_Efp = -1.0; - sourceElemSet = NULL; - } - /// Destructor. - virtual ~MDM() { - if ( linearElasticMaterial ) { - delete linearElasticMaterial; - } - if ( sourceElemSet ) { - delete sourceElemSet; - } } - virtual int hasMaterialModeCapability(MaterialMode mode); - - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + bool hasMaterialModeCapability(MaterialMode mode) const override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<4> giveRealStressVector_PlaneStrain(const FloatArrayF<4> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + FloatArrayF<6> giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; - // identification and auxiliary functions - virtual const char *giveInputRecordName() const { return _IFT_MDM_Name; } - virtual const char *giveClassName() const { return "MDM"; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual void giveRealMicroplaneStressVector(FloatArray &answer, Microplane *mplane, - const FloatArray &strain, TimeStep *tStep) { } + const char *giveInputRecordName() const override { return _IFT_MDM_Name; } + const char *giveClassName() const override { return "MDM"; } - virtual void initializeData(int numberOfMicroplanes); + void initializeData(int numberOfMicroplanes) override; - virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep); + void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const override; - virtual double computeWeightFunction(const FloatArray &src, const FloatArray &coord); + double computeWeightFunction(const double cl, const FloatArray &src, const FloatArray &coord) const override; - virtual int hasBoundedSupport() { return 1; } + int hasBoundedSupport() const override { return 1; } /** * Determines the width (radius) of limited support of weighting function. */ virtual void giveSupportRadius(double &radius) { radius = this->R; } - virtual Interface *giveInterface(InterfaceType it); + Interface *giveInterface(InterfaceType it) override; - virtual int MMI_map(GaussPoint *gp, Domain *oldd, TimeStep *tStep); - virtual int MMI_update(GaussPoint *gp, TimeStep *tStep, FloatArray *estrain = NULL); - virtual int MMI_finish(TimeStep *tStep); + int MMI_map(GaussPoint *gp, Domain *oldd, TimeStep *tStep) override; + int MMI_update(GaussPoint *gp, TimeStep *tStep, FloatArray *estrain = nullptr) override; + int MMI_finish(TimeStep *tStep) override; - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int estimatePackSize(DataStream &buff, GaussPoint *ip); - virtual double predictRelativeComputationalCost(GaussPoint *gp); - virtual double predictRelativeRedistributionCost(GaussPoint *gp) { return 1.0; } + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int estimatePackSize(DataStream &buff, GaussPoint *ip) override; + double predictRelativeComputationalCost(GaussPoint *gp) override; + double predictRelativeRedistributionCost(GaussPoint *gp) override { return 1.0; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; protected: - /// Returns reference to undamaged (bulk) material. - StructuralMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } - - virtual MaterialStatus *CreateMicroplaneStatus(GaussPoint *gp) - { return NULL; } void computeDamageTensor(FloatMatrix &tempDamageTensor, const FloatArray &totalStrain, - GaussPoint *gp, TimeStep *tStep); + GaussPoint *gp, TimeStep *tStep) const; void computeLocalDamageTensor(FloatMatrix &tempDamageTensor, const FloatArray &totalStrain, - GaussPoint *gp, TimeStep *tStep); - double computeDamageOnPlane(GaussPoint *gp, Microplane *mplane, const FloatArray &strain); + GaussPoint *gp, TimeStep *tStep) const; + double computeDamageOnPlane(GaussPoint *gp, int mnumber, const FloatArray &strain) const; void computePDC(FloatMatrix &tempDamageTensor, FloatArray &tempDamageTensorEigenVals, - FloatMatrix &tempDamageTensorEigenVec); + FloatMatrix &tempDamageTensorEigenVec) const; void transformStrainToPDC(FloatArray &answer, FloatArray &strain, - FloatMatrix &t, GaussPoint *gp); - void applyDamageTranformation(FloatArray &strainPDC, const FloatArray &tempDamageTensorEigenVals); - void transformStressFromPDC(FloatArray &answer, const FloatArray &stressPDC, const FloatMatrix &t, GaussPoint *gp); + FloatMatrix &t, GaussPoint *gp) const; + void applyDamageTranformation(FloatArray &strainPDC, const FloatArray &tempDamageTensorEigenVals) const; + void transformStressFromPDC(FloatArray &answer, const FloatArray &stressPDC, const FloatMatrix &t, GaussPoint *gp) const; void computeEffectiveStress(FloatArray &stressPDC, const FloatArray &strainPDC, - GaussPoint *gp, TimeStep *tStep); + GaussPoint *gp, TimeStep *tStep) ; void giveMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep); - void applyDamageToStiffness(FloatMatrix &d, GaussPoint *gp); - void transformStiffnessfromPDC(FloatMatrix &de, const FloatMatrix &t); + TimeStep *tStep) const; + void applyDamageToStiffness(FloatMatrix &d, GaussPoint *gp) const; + void transformStiffnessfromPDC(FloatMatrix &de, const FloatMatrix &t) const; - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; - void rotateTensor4(FloatMatrix &Dlocal, const FloatMatrix &t); - void formTransformationMatrix(FloatMatrix &answer, const FloatMatrix &t, int n); + void rotateTensor4(FloatMatrix &Dlocal, const FloatMatrix &t) const; + void formTransformationMatrix(FloatMatrix &answer, const FloatMatrix &t, int n) const; //double giveParameterEfp(const FloatArray &reducedStrain, GaussPoint *gp); - void giveRawMDMParameters(double &Efp, double &Ep, const FloatArray &reducedStrain, GaussPoint *gp); + void giveRawMDMParameters(double &Efp, double &Ep, const FloatArray &reducedStrain, GaussPoint *gp) const; }; } // end namespace oofem #endif // mdm_h diff --git a/src/sm/Materials/mfrontusermaterial.C b/src/sm/Materials/mfrontusermaterial.C new file mode 100644 index 000000000..c5e7a05b3 --- /dev/null +++ b/src/sm/Materials/mfrontusermaterial.C @@ -0,0 +1,322 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// Use the following flags and specify location of the cmake files. +// cmake -DUSE_MFRONT=ON -DMFrontGenericInterface_DIR=/usr/local/share/mgis/cmake/ .. + +#include "mfrontusermaterial.h" +#include "gausspoint.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" +#include "classfactory.h" +#include "dynamicinputrecord.h" + +#ifdef _WIN32 //_MSC_VER and __MINGW32__ included + #include +#else + #include +#endif + +#include + +namespace oofem { +REGISTER_Material(MFrontUserMaterial); + +// eventual reindexing +int const MFrontUserMaterial :: mfront2oo9[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; +int const MFrontUserMaterial :: mfront2oo6[6] = {0, 1, 2, 3, 4, 5}; + +MFrontUserMaterial :: MFrontUserMaterial(int n, Domain *d) : StructuralMaterial(n, d) {} + +MFrontUserMaterial :: ~MFrontUserMaterial() +{ + +} + +void MFrontUserMaterial :: initializeFrom(InputRecord &ir) +{ + using namespace mgis::behaviour; + + StructuralMaterial :: initializeFrom(ir); + + + FloatArray s(6); + this->initialStress = s; + + std :: string libname; + std :: string modelname; + IR_GIVE_FIELD(ir, libname, _IFT_MFrontUserMaterial_libpath); + IR_GIVE_FIELD(ir, modelname, _IFT_MFrontUserMaterial_modelname); + strncpy(this->libname, libname.c_str(), 199); + strncpy(this->modelname, modelname.c_str(), 199); + // loading the MFront library using MGIS + this->behaviour = std::make_unique(load(this->libname, this->modelname, Hypothesis::TRIDIMENSIONAL)); + // initialize material properties from user data + IR_GIVE_FIELD(ir, this->properties, _IFT_MFrontUserMaterial_properties); + // check that the number of material properties given by the user is correct + const auto nprops = mgis::behaviour::getArraySize(this->behaviour->mps, this->behaviour->hypothesis); + if (this->properties.giveSize() != nprops) { + throw(std::runtime_error("wrong number of material properties")); + } + // treating the case for external state variables + const auto nesvs = mgis::behaviour::getArraySize(this->behaviour->esvs, this->behaviour->hypothesis); + if (nesvs != 1) { + throw(std::runtime_error("wrong number of external state variables")); + } + if (this->behaviour->esvs[0].name != "Temperature") { + throw(std::runtime_error("the temperature is the only external state variable supported so far")); + } + +} + +void MFrontUserMaterial :: giveInputRecord(DynamicInputRecord &input) +{ + StructuralMaterial :: giveInputRecord(input); +} + +MaterialStatus *MFrontUserMaterial :: CreateStatus(GaussPoint *gp) const +{ + return new MFrontUserMaterialStatus(gp, *(this->behaviour)); +} + + +FloatMatrixF<6,6> +MFrontUserMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto ms = dynamic_cast< MFrontUserMaterialStatus * >( this->giveStatus(gp) ); + if (!ms->hasTangent()) { + // Evaluating the function once, so that the tangent can be obtained. + const_cast(this)->giveRealStressVector_3d(zeros<6>(), gp, tStep); + } + + double h = mPerturbation; + FloatArray strain, strainh, stress, stressh; + strain = static_cast(gp->giveMaterialStatus())->giveTempStrainVector(); + stress = static_cast(gp->giveMaterialStatus())->giveTempStressVector(); + FloatMatrix En(strain.giveSize(), strain.giveSize()); + for (int i = 1; i <= strain.giveSize(); ++i) { + strainh = strain; + strainh.at(i) += h; + stressh = this->giveRealStressVector_3d(strainh, gp, tStep); + stressh.subtract(stress); + stressh.times(1.0 / h); + En.setColumn(stressh, i); + } + stress = this->giveRealStressVector_3d(strain, gp, tStep); + + return En; +} + + +FloatMatrixF<9,9> +MFrontUserMaterial :: give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto ms = dynamic_cast(this->giveStatus(gp)); + if (!ms->hasTangent()) { + // Evaluating the function once, so that the tangent can be obtained. + const auto &vF = ms->giveTempFVector(); + this->giveFirstPKStressVector_3d(vF, gp, tStep); + } + + double h = mPerturbation; + auto const &vF = ms->giveTempFVector(); + auto const &stress = ms->giveTempPVector(); + FloatMatrixF<9,9> En; + for ( int i = 1; i <= 9; ++i ) { + auto vF_h = vF; + vF_h.at(i) += h; + auto stressh = this->giveFirstPKStressVector_3d(vF_h, gp, tStep); + auto ds = (stressh - stress) * (1. / h); + En.setColumn(ds, i); + } + + // Reset + this->giveFirstPKStressVector_3d(vF, gp, tStep); + + return En; +} + +FloatMatrixF<5,5> +MFrontUserMaterial :: givePlaneStrainStiffMtrx_dPdF(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const +{ + auto dPdF3D = this->give3dMaterialStiffnessMatrix_dPdF(mmode, gp, tStep); + return dPdF3D({0, 1, 2, 5, 8}, {0, 1, 2, 5, 8}); +} + + +FloatArrayF<6> +MFrontUserMaterial :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const +{ + auto ms = static_cast< MFrontUserMaterialStatus * >( this->giveStatus(gp) ); + + FloatArrayF<6> old_strain = ms->giveStrainVector(); + FloatArrayF<6> old_stress = initialStress + ms->giveStressVector(); + + auto old_state = ms->giveStateVector(); + auto new_state = old_state; + FloatMatrixF<6,6> mfront_jacobian; + + // Times and increment + double dtime = tStep->giveTimeIncrement(); + + // Change the component order + auto mfront_stress = old_stress[mfront2oo6]; + auto mfront_old_strain = old_strain[mfront2oo6]; + auto mfront_new_strain = strain[mfront2oo6]; + + // Beware of MFront conventions here !!!! + mfront_stress[3] *= 2.; + mfront_stress[4] *= 2.; + mfront_stress[5] *= 2.; + mfront_old_strain[3] /= 2.; + mfront_old_strain[4] /= 2.; + mfront_old_strain[5] /= 2.; + mfront_new_strain[3] /= 2.; + mfront_new_strain[4] /= 2.; + mfront_new_strain[5] /= 2.; + + // + double externalStateVariables[1] = {293.15}; + double stored_energy = 0; + double dissipated_energy = 0; + + mgis::behaviour::BehaviourDataView v; + v.dt = dtime; + +// modifications du to API changes in MGIS +#ifdef MGIS_BEHAVIOUR_API_VERSION +#if MGIS_BEHAVIOUR_API_VERSION == 1 + auto rdt = double{}; + v.rdt = &rdt; + v.speed_of_sound = nullptr; +#else /* MGIS_BEHAVIOUR_API_VERSION == 1 */ +#error "Unsupported MGIS' behaviour API" +#endif /* MGIS_BEHAVIOUR_API_VERSION == 1 */ +#else /* MGIS_BEHAVIOUR_API_VERSION */ + v.rdt = 1; +#endif /* MGIS_BEHAVIOUR_API_VERSION */ + + v.K = &mfront_jacobian(0, 0); + // perform an integration with computation of the consistent tangent operator + v.K[0] = 4; + // setting the initial state + v.s0.gradients = &mfront_old_strain[0]; + v.s0.thermodynamic_forces = &old_stress[0]; + v.s0.material_properties = nullptr; // &(this->properties[0]) + v.s0.internal_state_variables = &old_state[0]; // shall be null if numState==0 + v.s0.external_state_variables = externalStateVariables; + v.s0.stored_energy = &stored_energy; + v.s0.dissipated_energy = &dissipated_energy; + // setting the state at the end of the time step + v.s1.gradients = &mfront_new_strain[0]; + v.s1.thermodynamic_forces = &mfront_stress[0]; + v.s1.material_properties = nullptr; // &(this->properties[0]) + v.s1.internal_state_variables = &new_state[0]; // shall be null if numState==0 + v.s1.external_state_variables = externalStateVariables; + v.s1.stored_energy = &stored_energy; + v.s1.dissipated_energy = &dissipated_energy; + + integrate(v, *(this->behaviour)); + + // Change to OOFEM's component order + auto jacobian = mfront_jacobian(mfront2oo6, mfront2oo6); + // subtracking the initial stress + auto stress = mfront_stress[mfront2oo6] - initialStress; + // Here MFront->OOFEM conventions for the strain **and** the jacobian + // + + ms->letTempStrainVectorBe(strain); + ms->letTempStressVectorBe(stress); + ms->letTempStateVectorBe(new_state); + ms->letTempTangentBe(jacobian); + return stress; +} + + +int MFrontUserMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +{ + auto ms = static_cast(this->giveStatus(gp)); + if ( type == IST_Undefined || type == IST_AbaqusStateVector ) { + // The undefined value is used to just dump the entire state vector. + answer = ms->giveStateVector(); + return 1; + } else if (type == IST_StressTensor) { + answer = ms->giveStressVector(); + answer.add(initialStress); + return 1; + } else { + return StructuralMaterial :: giveIPValue(answer, gp, type, tStep); + } +} + +void MFrontUserMaterialStatus :: initTempStatus() +{ + StructuralMaterialStatus :: initTempStatus(); + tempStateVector = stateVector; +} + +MFrontUserMaterialStatus :: MFrontUserMaterialStatus(GaussPoint *gp, const mgis::behaviour::Behaviour &b) : + StructuralMaterialStatus(gp), hasTangentFlag(false) +{ + strainVector.resize(6); + strainVector.zero(); + // getting number of state variables + const auto numState = mgis::behaviour::getArraySize(b.isvs, b.hypothesis); + // allocating number of state variables + this->stateVector.resize(numState); + this->tempStateVector.resize(numState); + this->stateVector.zero(); // ?? + this->tempStateVector.zero(); // ?? +} + +void MFrontUserMaterialStatus :: updateYourself(TimeStep *tStep) +{ + StructuralMaterialStatus :: updateYourself(tStep); + stateVector = tempStateVector; +} + +void MFrontUserMaterialStatus :: printOutputAt(FILE *File, TimeStep *tStep) const +{ + StructuralMaterialStatus :: printOutputAt(File, tStep); + + fprintf(File, " stateVector "); + FloatArray state = this->giveStateVector(); + for ( auto &var : state ) { + fprintf( File, " % .4e", var ); + } + + fprintf(File, "\n"); +} + +} // end namespace oofem diff --git a/src/sm/Materials/mfrontusermaterial.h b/src/sm/Materials/mfrontusermaterial.h new file mode 100644 index 000000000..98d71ff85 --- /dev/null +++ b/src/sm/Materials/mfrontusermaterial.h @@ -0,0 +1,166 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef mfrontusermaterial_h +#define mfrontusermaterial_h + +#include + +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrix.h" + +#include "MGIS/Behaviour/State.hxx" +#include "MGIS/Behaviour/Behaviour.hxx" +#include "MGIS/Behaviour/BehaviourData.hxx" +#include "MGIS/Behaviour/Integrate.hxx" +#include "MGIS/ThreadPool.hxx" +#include "MGIS/Behaviour/MaterialDataManager.hxx" + +///@name Input fields for MFrontUserMaterial +//@{ +#define _IFT_MFrontUserMaterial_Name "mfrontusermaterial" +#define _IFT_MFrontUserMaterial_numState "numstate" +#define _IFT_MFrontUserMaterial_properties "properties" +#define _IFT_MFrontUserMaterial_initialStress "initialstress" +#define _IFT_MFrontUserMaterial_userMaterial "umat" +#define _IFT_MFrontUserMaterial_name "name" +#define _IFT_MFrontUserMaterial_numericalTangent "numericaltangent" +#define _IFT_MFrontUserMaterial_numericalTangentPerturbation "perturbation" +#define _IFT_MFrontUserMaterial_libpath "libpath" +#define _IFT_MFrontUserMaterial_modelname "modelname" +//@} + + +namespace oofem { + + +using namespace mgis; +using namespace mgis::behaviour; + + +class MFrontUserMaterial : public StructuralMaterial +{ +private: + + char libname[200]; + char modelname[200]; + + /// Material properties. + FloatArray properties; + /// Initial stress. + FloatArrayF<6> initialStress; + + int mStressInterpretation = 0; + + bool mUseNumericalTangent = false; + + /** + * Size of perturbation for numerical tangent. + */ + double mPerturbation = 1e-7; + + std :: string filename; + + static int const mfront2oo9[9]; + static int const mfront2oo6[6]; + + //! \brief pointer to the MGIS behaviour + std::unique_ptr behaviour; + +public: + /// Constructor. + MFrontUserMaterial(int n, Domain *d); + /// Destructor. + virtual ~MFrontUserMaterial(); + + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatMatrixF<9,9> give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatMatrixF<5,5> givePlaneStrainStiffMtrx_dPdF(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + + const char *giveClassName() const override { return "MFrontUserMaterial"; } + const char *giveInputRecordName() const override { return _IFT_MFrontUserMaterial_Name; } +}; + +class MFrontUserMaterialStatus : public StructuralMaterialStatus +{ +protected: + /// General state vector. + FloatArray stateVector; + /// Temporary state vector. + FloatArray tempStateVector; + /// Temporary elastic tangent. + FloatMatrix tempTangent; + + /// Checker to see if tangent has been computed. + bool hasTangentFlag; + +public: + /// Constructor. + MFrontUserMaterialStatus(GaussPoint *gp, const mgis::behaviour::Behaviour &b); + + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + + bool hasTangent() const { return hasTangentFlag; } + + const FloatArray &giveStateVector() const { return stateVector; } + FloatArray &letStateVectorBe(FloatArray &s) { return stateVector = s; } + const FloatArray &giveTempStateVector() const { return tempStateVector; } + FloatArray &letTempStateVectorBe(FloatArray &s) { return tempStateVector = s; } + const FloatMatrix &giveTempTangent() { return tempTangent; } + void letTempTangentBe(FloatMatrix t) { + tempTangent = std::move(t); + hasTangentFlag = true; + } + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + const char *giveClassName() const override { return "MFrontUserMaterialStatus"; } +}; +} // end namespace oofem +#endif // mfrontusermaterial_h diff --git a/src/sm/Materials/micromaterial.C b/src/sm/Materials/micromaterial.C index 975e7c3c0..1e596d132 100644 --- a/src/sm/Materials/micromaterial.C +++ b/src/sm/Materials/micromaterial.C @@ -33,8 +33,8 @@ */ #include "micromaterial.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "domain.h" #include "dofmanager.h" #include "classfactory.h" @@ -64,9 +64,8 @@ REGISTER_Material(MicroMaterial); // constructor //strainVector, tempStrainVector, stressVector, tempStressVector are defined on StructuralMaterialStatus -MicroMaterialStatus :: MicroMaterialStatus(int n, Domain *d, GaussPoint *gp) : StructuralMaterialStatus(n, d, gp) { } +MicroMaterialStatus :: MicroMaterialStatus(GaussPoint *gp) : StructuralMaterialStatus(gp) { } -MicroMaterialStatus :: ~MicroMaterialStatus() { } void MicroMaterialStatus :: initTempStatus() { @@ -78,88 +77,37 @@ void MicroMaterialStatus :: updateYourself(TimeStep *tStep) StructuralMaterialStatus :: updateYourself(tStep); } -void MicroMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +void MicroMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { } -contextIOResultType MicroMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void MicroMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - return CIO_OK; } -contextIOResultType MicroMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void MicroMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - return CIO_OK; } MicroMaterial :: MicroMaterial(int n, Domain *d) : StructuralMaterial(n, d), UnknownNumberingScheme() -{ - this->problemMicro = NULL; - this->isDefaultNumbering = true; - this->DofEquationNumbering = AllNodes; - this->microBoundaryDofs = NULL; - this->microInternalDofs = NULL; - this->microDefaultDofs = NULL; - this->microBoundaryDofsArr.clear(); - this->microInternalDofsArr.clear(); - this->microMatIsUsed = false; -} - -MicroMaterial :: ~MicroMaterial() -{ - if ( this->problemMicro ) { - delete this->problemMicro; - } +{} - for ( int i = 0; i < this->NumberOfDofManagers; i++ ) { - if ( this->microBoundaryDofs ) { - delete [] microBoundaryDofs [ i ]; - } - - if ( this->microInternalDofs ) { - delete [] microInternalDofs [ i ]; - } - - if ( this->microDefaultDofs ) { - delete [] microDefaultDofs [ i ]; - } - } - - if ( this->microBoundaryDofs ) { - delete [] microBoundaryDofs; - } - - if ( this->microInternalDofs ) { - delete [] microInternalDofs; - } - - if ( this->microDefaultDofs ) { - delete [] microDefaultDofs; - } -} -IRResultType MicroMaterial :: initializeFrom(InputRecord *ir) +void MicroMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - IR_GIVE_FIELD(ir, this->inputFileNameMicro, _IFT_MicroMaterial_fileName); OOFEM_LOG_INFO( "** Instanciating microproblem with BC from file %s\n", inputFileNameMicro.c_str() ); OOFEMTXTDataReader drMicro( inputFileNameMicro.c_str() ); - this->problemMicro = InstanciateProblem(& drMicro, _processor, 0); //0=contextFlag-store/resore + this->problemMicro = InstanciateProblem(drMicro, _processor, 0); //0=contextFlag-store/resore drMicro.finish(); - OOFEM_LOG_INFO("** Microproblem %p instanciated\n\n", problemMicro); - - return IRRT_OK; + OOFEM_LOG_INFO("Microproblem instanciated\n"); } - - //original pure virtual function has to be declared here //this function should not be used, internal forces are calculated based on reactions not stresses in GPs -void MicroMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep) +FloatArrayF<6> MicroMaterial :: giveRealStressVector_3d(const FloatArrayF<6> &totalStrain, GaussPoint *gp, TimeStep *tStep) const { //perform average over microproblem // int index; @@ -172,6 +120,7 @@ void MicroMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp // StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); OOFEM_ERROR("Should not be called, use giveInternalForcesVector instead"); + return zeros<6>(); // int nelem = microDomain->giveNumberOfElements(); // //int nnodes = microDomain->giveNumberOfDofManagers(); @@ -226,8 +175,7 @@ void MicroMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp MaterialStatus * MicroMaterial :: CreateStatus(GaussPoint *gp) const { - MicroMaterialStatus *status = new MicroMaterialStatus(1, StructuralMaterial :: giveDomain(), gp); - return status; + return new MicroMaterialStatus(gp); } @@ -242,15 +190,15 @@ void MicroMaterial :: giveMacroStiffnessMatrix(FloatMatrix &answer, TimeStep *tS Dof *dof; FloatMatrix Kbb; //contains reduced problem with boundary nodes and without interior nodes - FloatMatrix *Kbi = NULL; //can be zero size if no internal DOFs - FloatMatrix *Kii1KbiT = NULL; //can be zero size if no internal DOFs - FloatMatrix *Kbb_1 = NULL; //help matrix + FloatMatrix Kbi; //can be zero size if no internal DOFs + FloatMatrix Kii1KbiT; //can be zero size if no internal DOFs + FloatMatrix Kbb_1; //help matrix FloatMatrix slaveMasterOnBoundary; //transformation matrix representing displacements on boundary tied to master nodes SparseMtrxType sparseMtrxType = ( SparseMtrxType ) 0; //SMT_Skyline symmetric skyline - SparseMtrx *stiffnessMatrixMicro = NULL; //full stiffness matrix without any constraint - SparseMtrx *Kii = NULL; //submatrix of internal DOFs + std::unique_ptr stiffnessMatrixMicro; //full stiffness matrix without any constraint + std::unique_ptr Kii; //submatrix of internal DOFs Kbb.resize(totalBoundaryDofs, totalBoundaryDofs); Kbb.zero(); @@ -264,13 +212,12 @@ void MicroMaterial :: giveMacroStiffnessMatrix(FloatMatrix &answer, TimeStep *tS printf( "Internal DOFs %d\n", this->giveRequiredNumberOfDomainEquation() ); this->DofEquationNumbering = InteriorNodes; if ( totalInternalDofs ) { - Kbi = new FloatMatrix(totalBoundaryDofs, totalInternalDofs); - Kbi->zero(); - Kii1KbiT = new FloatMatrix(totalInternalDofs, totalBoundaryDofs); - Kii1KbiT->zero(); + Kbi.resize(totalBoundaryDofs, totalInternalDofs); + Kbi.zero(); + Kii1KbiT.resize(totalInternalDofs, totalBoundaryDofs); + Kii1KbiT.zero(); Kii = classFactory.createSparseMtrx(sparseMtrxType); Kii->buildInternalStructure(microEngngModel, 1, * this); - Kii->zero(); microEngngModel->assemble(*Kii, tStep, TangentAssembler(rMode), * this, microDomain); } @@ -281,9 +228,7 @@ void MicroMaterial :: giveMacroStiffnessMatrix(FloatMatrix &answer, TimeStep *tS this->DofEquationNumbering = AllNodes; stiffnessMatrixMicro = classFactory.createSparseMtrx(sparseMtrxType); - stiffnessMatrixMicro->zero(); stiffnessMatrixMicro->buildInternalStructure(microEngngModel, 1, * this); - stiffnessMatrixMicro->zero(); microEngngModel->assemble(*stiffnessMatrixMicro, tStep, TangentAssembler(rMode), * this, microDomain); @@ -301,7 +246,7 @@ void MicroMaterial :: giveMacroStiffnessMatrix(FloatMatrix &answer, TimeStep *tS row = microBoundaryDofsArr.at(i); col = microInternalDofsArr.at(j); if ( stiffnessMatrixMicro->isAllocatedAt(row, col) ) { - Kbi->at(i, j) = stiffnessMatrixMicro->at(row, col); + Kbi.at(i, j) = stiffnessMatrixMicro->at(row, col); } } } @@ -321,10 +266,10 @@ void MicroMaterial :: giveMacroStiffnessMatrix(FloatMatrix &answer, TimeStep *tS for ( int b = 1; b <= totalBoundaryDofs; b++ ) { //do not store Kii^-1, it is a dense matrix, compute multiplication directly tmpDouble = 0.; for ( int j = 1; j <= totalInternalDofs; j++ ) { - tmpDouble += xVector.at(j) * Kbi->at(b, j); + tmpDouble += xVector.at(j) * Kbi.at(b, j); } - Kii1KbiT->at(i, b) = tmpDouble; + Kii1KbiT.at(i, b) = tmpDouble; } //OOFEM_LOG_INFO("%d ", i); @@ -332,40 +277,19 @@ void MicroMaterial :: giveMacroStiffnessMatrix(FloatMatrix &answer, TimeStep *tS OOFEM_LOG_INFO("\n"); - Kbb_1 = new FloatMatrix(); - Kbb_1->beProductOf( ( FloatMatrix const & ) * Kbi, ( FloatMatrix const & ) * Kii1KbiT ); + Kbb_1.beProductOf( Kbi, Kii1KbiT ); for ( int i = 1; i <= totalBoundaryDofs; i++ ) { for ( int j = 1; j <= totalBoundaryDofs; j++ ) { - Kbb.at(i, j) -= Kbb_1->at(i, j); + Kbb.at(i, j) -= Kbb_1.at(i, j); } } } - if ( Kbi ) { - delete Kbi; - } - - if ( Kii1KbiT ) { - delete Kii1KbiT; - } - - if ( Kbb_1 ) { - delete Kbb_1; - } - - //Kbb_1->printYourself(); + //Kbb_1-printYourself(); //OOFEM_ERROR("Stop"); this->isDefaultNumbering = true; //switch back to default numbering this->DofEquationNumbering = AllNodes; - if ( Kii ) { - delete Kii; - } - - if ( stiffnessMatrixMicro ) { - delete stiffnessMatrixMicro; - } - // IntArray interiorDofNode; //equation numbers to be condensed out, sorted // IntArray boundaryDofNode;//equation numbers in rows (or columns) of stiffness matrix without interior nodes, sorted // interiorDofNode.clear(); @@ -455,7 +379,7 @@ void MicroMaterial :: giveMacroStiffnessMatrix(FloatMatrix &answer, TimeStep *tS OOFEM_ERROR("Not found equation number %d in reduced stiffness matrix of node %d\n", giveDofEquationNumber(dof), DofMan->giveGlobalNumber() ); } - this->macroLSpaceElement->evalInterpolation( n, this->microMasterCoords, * DofMan->giveCoordinates() ); + this->macroLSpaceElement->evalInterpolation( n, this->microMasterCoords, DofMan->giveCoordinates() ); //construct transformation matrix relating displacement of slave boundary nodes to macroelement nodes //the answer is returned to macroelement so the columns correspond to x,y,z DOFs of each macroelement node @@ -524,26 +448,25 @@ void MicroMaterial :: setMacroProperties(Domain *macroDomain, MacroLSpace *macro this->microMasterCoords.clear(); this->microMasterCoords.reserve(microMasterNodes.giveSize()); for ( int nodeNum: microMasterNodes ) { //8 nodes - this->microMasterCoords.push_back( * microDomain->giveNode( nodeNum )->giveCoordinates() ); + this->microMasterCoords.push_back( microDomain->giveNode( nodeNum )->giveCoordinates() ); } microEngngModel->giveNextStep(); //set the first time step mstep = microEngngModel->giveCurrentMetaStep(); mstep->setNumberOfSteps(this->macroDomain->giveEngngModel()->giveMetaStep(1)->giveNumberOfSteps() + 1); - //separate DOFs into boundary and internal this->NumberOfDofManagers = microDomain->giveNumberOfDofManagers(); - microBoundaryDofs = new int * [ this->NumberOfDofManagers ]; - microInternalDofs = new int * [ this->NumberOfDofManagers ]; - microDefaultDofs = new int * [ this->NumberOfDofManagers ]; + microBoundaryDofs.resize( this->NumberOfDofManagers ); + microInternalDofs.resize( this->NumberOfDofManagers ); + microDefaultDofs.resize( this->NumberOfDofManagers ); for ( int i = 0; i < this->NumberOfDofManagers; i++ ) { - microBoundaryDofs [ i ] = new int [ 3 ]; - microInternalDofs [ i ] = new int [ 3 ]; - microDefaultDofs [ i ] = new int [ 3 ]; - microBoundaryDofs [ i ] [ 0 ] = microBoundaryDofs [ i ] [ 1 ] = microBoundaryDofs [ i ] [ 2 ] = 0; - microInternalDofs [ i ] [ 0 ] = microInternalDofs [ i ] [ 1 ] = microInternalDofs [ i ] [ 2 ] = 0; - microDefaultDofs [ i ] [ 0 ] = microDefaultDofs [ i ] [ 1 ] = microDefaultDofs [ i ] [ 2 ] = 0; + microBoundaryDofs [ i ].resize(3); + microInternalDofs [ i ].resize(3); + microDefaultDofs [ i ].resize(3); + microBoundaryDofs [ i ].zero(); + microInternalDofs [ i ].zero(); + microDefaultDofs [ i ].zero(); } for ( int i = 0; i < this->NumberOfDofManagers; i++ ) { @@ -607,30 +530,24 @@ void MicroMaterial :: init(void) //Each node has three dofs (x,y,z direction) int MicroMaterial :: giveDofEquationNumber(Dof *dof) const { - int answer; - int numDofMan, numDof; - - numDofMan = dof->giveDofManNumber(); - numDof = dof->giveDofID(); // Note: Relieas on D_u, D_v, D_w being 1, 2, 3 + int numDofMan = dof->giveDofManNumber(); + int numDof = dof->giveDofID(); // Note: Relieas on D_u, D_v, D_w being 1, 2, 3 //depending on the assembly of submatrix, swith to equation numbering switch ( DofEquationNumbering ) { case AllNodes: //the default - answer = microDefaultDofs [ numDofMan - 1 ] [ numDof - 1 ]; + return microDefaultDofs [ numDofMan - 1 ] [ numDof - 1 ]; break; case BoundaryNodes: - answer = microBoundaryDofs [ numDofMan - 1 ] [ numDof - 1 ]; + return microBoundaryDofs [ numDofMan - 1 ] [ numDof - 1 ]; break; case InteriorNodes: - answer = microInternalDofs [ numDofMan - 1 ] [ numDof - 1 ]; + return microInternalDofs [ numDofMan - 1 ] [ numDof - 1 ]; break; default: - answer = 0; OOFEM_ERROR("Node numbering undefined"); + return 0; } - - // answer = 3 * ( dof->giveDofManNumber() - 1 ) + dof->giveNumber(); - return answer; } //from class UnknownNumberingScheme diff --git a/src/sm/Materials/micromaterial.h b/src/sm/Materials/micromaterial.h index e25e3eedc..c4f1a2c7b 100644 --- a/src/sm/Materials/micromaterial.h +++ b/src/sm/Materials/micromaterial.h @@ -36,7 +36,7 @@ #define micromaterial_h #include "structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "dictionary.h" #include "floatarray.h" #include "floatmatrix.h" @@ -45,7 +45,7 @@ #include "contextioerr.h" #include "unknownnumberingscheme.h" #include "boundarycondition.h" -#include "Elements/3D/macrolspace.h" +#include "sm/Elements/3D/macrolspace.h" #include "error.h" ///@name Input fields for MicroMaterial @@ -63,19 +63,16 @@ class MicroMaterialStatus : public StructuralMaterialStatus { public: /// Constructor - MicroMaterialStatus(int, Domain * d, GaussPoint * gp); + MicroMaterialStatus(GaussPoint * gp); - /// Destructor - virtual ~MicroMaterialStatus(); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + const char *giveClassName() const override { return "MicroMaterialStatus"; } - virtual const char *giveClassName() const { return "MicroMaterialStatus"; } - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -91,68 +88,66 @@ class MicroMaterial : public StructuralMaterial, public UnknownNumberingScheme public: /// Constructor MicroMaterial(int n, Domain * d); - /// Destructor - virtual ~MicroMaterial(); std :: string inputFileNameMicro; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveInputRecordName() const { return _IFT_MicroMaterial_Name; } - virtual const char *giveClassName() const { return "MicroMaterial"; } + const char *giveInputRecordName() const override { return _IFT_MicroMaterial_Name; } + const char *giveClassName() const override { return "MicroMaterial"; } - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *, const FloatArray &, TimeStep *); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; void giveMacroStiffnessMatrix(FloatMatrix &answer, TimeStep *tStep, MatResponseMode rMode, const IntArray µMasterNodes, const IntArray µBoundaryNodes); void setMacroProperties(Domain *macroDomain, MacroLSpace *macroLSpaceElement, const IntArray µMasterNodes, const IntArray µBoundaryNodes); /// Pointer to the underlying micro problem. - EngngModel *problemMicro; + std::unique_ptr problemMicro; /// Pointer to the macroscale domain. - Domain *macroDomain; + Domain *macroDomain = nullptr; /// Pointer to the macroscale element. - MacroLSpace *macroLSpaceElement; + MacroLSpace *macroLSpaceElement = nullptr; /// Related to numbering scheme. - void init(void); - int giveDofEquationNumber(Dof *dof) const; - virtual bool isDefault() const { return isDefaultNumbering; } - virtual int giveRequiredNumberOfDomainEquation() const; + void init(void) override; + int giveDofEquationNumber(Dof *dof) const override; + bool isDefault() const override { return isDefaultNumbering; } + int giveRequiredNumberOfDomainEquation() const override; //friend class EngngModel;-not here but define in EngngModel class /// Array containing coordinates of 8 master nodes of microproblem. std::vector< FloatArray >microMasterCoords; /// Array containing equation numbers for boundary nodes [DofManagerNumber][DOF]. - int **microBoundaryDofs; + std::vector microBoundaryDofs; /// Array of equation numbers associated to boundary nodes. IntArray microBoundaryDofsArr; /// Array containing equation numbers for internal nodes to be condensed out [DofManagerNumber][DOF]. - int **microInternalDofs; + std::vector microInternalDofs; /// Array of equation numbers associated to internal nodes. IntArray microInternalDofsArr; /// Array containing default equation numbers for all nodes [DofManagerNumber][DOF]. - int **microDefaultDofs; + std::vector microDefaultDofs; /// Flag signalizing whether micromaterial is used by other element. - bool microMatIsUsed; + bool microMatIsUsed = false; protected: - bool isDefaultNumbering; + bool isDefaultNumbering = true; /// The maximum DOFs corresponding to released all of the boundary conditions. - int maxNumberOfDomainEquation; + int maxNumberOfDomainEquation = 0; /// Required number of domain equations. - int reqNumberOfDomainEquation; + int reqNumberOfDomainEquation = 0; /// Number of DOF Managers. - int NumberOfDofManagers; + int NumberOfDofManagers = 0; enum EquationNumbering { AllNodes, BoundaryNodes, InteriorNodes }; - EquationNumbering DofEquationNumbering; + EquationNumbering DofEquationNumbering = AllNodes; /// Number of equations associated with boundary nodes. - int totalBoundaryDofs; + int totalBoundaryDofs = 0; /// Number of equations associated with boundary nodes. - int totalInternalDofs; + int totalInternalDofs = 0; }; } // end namespace oofem #endif // micromaterial_h diff --git a/src/sm/Materials/microplane_m1.C b/src/sm/Materials/microplane_m1.C index 58ec6b83a..26e37df66 100644 --- a/src/sm/Materials/microplane_m1.C +++ b/src/sm/Materials/microplane_m1.C @@ -44,15 +44,13 @@ REGISTER_Material(M1Material); #ifdef microplane_m1_new_implementation // ========================= new implementation ========================= M1Material :: M1Material(int n, Domain *d) : MicroplaneMaterial(n, d) -{ E = 0.; nu = 0.; EN = 0.; s0 = 0.; HN = 0.; } +{ } -IRResultType -M1Material :: initializeFrom(InputRecord *ir) +void +M1Material :: initializeFrom(InputRecord &ir) { MicroplaneMaterial :: initializeFrom(ir); - IRResultType result; // Required by IR_GIVE_FIELD macro - if ( nu != 0.25 ) { OOFEM_WARNING("Poisson ratio of microplane model M1 must be set to 0.25"); } @@ -62,21 +60,15 @@ M1Material :: initializeFrom(InputRecord *ir) HN = 0.; IR_GIVE_OPTIONAL_FIELD(ir, HN, _IFT_M1Material_hn); ENtan = EN * HN / ( EN + HN ); - - return IRRT_OK; } -void -M1Material :: giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) +FloatArrayF<6> +M1Material :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, + TimeStep *tStep) const { - answer.resize(6); - answer.zero(); + auto status = static_cast< M1MaterialStatus * >( this->giveStatus(gp) ); // get the status at the beginning - M1MaterialStatus *status = static_cast< M1MaterialStatus * >( this->giveStatus(gp) ); // prepare status at the end this->initTempStatus(gp); // get the initial values of plastic strains on microplanes (set to zero in the first step) @@ -86,13 +78,13 @@ M1Material :: giveRealStressVector_3d(FloatArray &answer, epspN.zero(); } + FloatArrayF<6> stress; + // loop over microplanes FloatArray sigN(numberOfMicroplanes); IntArray plState(numberOfMicroplanes); for ( int imp = 1; imp <= numberOfMicroplanes; imp++ ) { - Microplane *mPlane = this->giveMicroplane(imp - 1, gp); - //IntegrationPointStatus *mPlaneStatus = this->giveMicroplaneStatus(mPlane); - double epsN = computeNormalStrainComponent(mPlane, totalStrain); + double epsN = computeNormalStrainComponent(imp, strain); // evaluate trial stress on the microplane double sigTrial = EN * ( epsN - epspN.at(imp) ); // evaluate the yield stress (from total microplane strain, not from its plastic part) @@ -111,39 +103,35 @@ M1Material :: giveRealStressVector_3d(FloatArray &answer, } // add the contribution of the microplane to macroscopic stresses for ( int i = 1; i <= 6; i++ ) { - answer.at(i) += N [ imp - 1 ] [ i - 1 ] * sigN.at(imp) * microplaneWeights [ imp - 1 ]; + stress.at(i) += N [ imp - 1 ] [ i - 1 ] * sigN.at(imp) * microplaneWeights [ imp - 1 ]; } } // multiply the integral over unit hemisphere by 6 - answer.times(6); + stress *= 6; // update status - status->letTempStrainVectorBe(totalStrain); - status->letTempStressVectorBe(answer); + status->letTempStrainVectorBe(strain); + status->letTempStressVectorBe(stress); status->letTempNormalMplaneStressesBe(sigN); status->letTempNormalMplanePlasticStrainsBe(epspN); status->letPlasticStateIndicatorsBe(plState); + return stress; } -void -M1Material :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +M1Material :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - answer.resize(6, 6); - answer.zero(); // elastic stiffness matrix if ( mode == ElasticStiffness ) { - MicroplaneMaterial :: give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); - return; + return MicroplaneMaterial :: give3dMaterialStiffnessMatrix(mode, gp, tStep); } M1MaterialStatus *status = static_cast< M1MaterialStatus * >( this->giveStatus(gp) ); IntArray plasticState = status->givePlasticStateIndicators(); if ( plasticState.giveSize() != numberOfMicroplanes ) { - MicroplaneMaterial :: give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); - return; + return MicroplaneMaterial :: give3dMaterialStiffnessMatrix(mode, gp, tStep); } // tangent stiffness matrix double aux, D11 = 0., D12 = 0., D13 = 0., D14 = 0., D15 = 0., D16 = 0., D22 = 0., D23 = 0., D24 = 0., D25 = 0., D26 = 0., D33 = 0., D34 = 0., D35 = 0., D36 = 0.; @@ -172,6 +160,7 @@ M1Material :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, D35 += aux * N [ im ] [ 2 ] * N [ im ] [ 4 ]; D36 += aux * N [ im ] [ 2 ] * N [ im ] [ 5 ]; } + FloatMatrixF<6,6> answer; answer.at(1, 1) = D11; answer.at(1, 2) = answer.at(2, 1) = answer.at(6, 6) = D12; answer.at(1, 3) = answer.at(3, 1) = answer.at(5, 5) = D13; @@ -189,8 +178,9 @@ M1Material :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, answer.at(3, 4) = answer.at(4, 3) = D34; answer.at(3, 5) = answer.at(5, 3) = D35; answer.at(3, 6) = answer.at(6, 3) = answer.at(4, 5) = answer.at(5, 4) = D36; + answer *= 6.; - answer.times(6.); + return answer; } int @@ -217,14 +207,11 @@ M1Material :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType } //////////////////////////////////////////////////////////////////////////// -M1MaterialStatus :: M1MaterialStatus(int n, Domain *d, GaussPoint *g) : - StructuralMaterialStatus(n, d, g), sigN(0), epspN(0), plasticState(0) +M1MaterialStatus :: M1MaterialStatus(GaussPoint *g) : + StructuralMaterialStatus(g), sigN(0), epspN(0), plasticState(0) {} -M1MaterialStatus :: ~M1MaterialStatus() -{ } - void M1MaterialStatus :: initTempStatus() { @@ -232,21 +219,20 @@ M1MaterialStatus :: initTempStatus() } void -M1MaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +M1MaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { sigN "); - int nm = sigN.giveSize(); - for ( int imp = 1; imp <= nm; imp++ ) { - fprintf( file, " %g ", sigN.at(imp) ); + for ( auto v : sigN ) { + fprintf( file, " %g ", v ); } fprintf(file, " epspN "); - for ( int imp = 1; imp <= nm; imp++ ) { - fprintf( file, " %g ", epspN.at(imp) ); + for ( auto v : epspN ) { + fprintf( file, " %g ", v ); } fprintf(file, " plast "); - for ( int imp = 1; imp <= nm; imp++ ) { - fprintf( file, " %d ", plasticState.at(imp) ); + for ( auto v : plasticState ) { + fprintf( file, " %d ", v ); } fprintf(file, "}\n"); } @@ -259,16 +245,18 @@ M1MaterialStatus :: updateYourself(TimeStep *tStep) StructuralMaterialStatus :: updateYourself(tStep); } -contextIOResultType -M1MaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +M1MaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - return StructuralMaterialStatus :: saveContext(stream, mode, obj); + StructuralMaterialStatus :: saveContext(stream, mode); + ///@todo All fields } -contextIOResultType -M1MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +M1MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - return StructuralMaterialStatus :: restoreContext(stream, mode, obj); + StructuralMaterialStatus :: restoreContext(stream, mode); + ///@todo All fields } #else @@ -377,13 +365,10 @@ M1Material :: givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode rMod } -IRResultType -M1Material :: initializeFrom(InputRecord *ir) +void +M1Material :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + StructuralMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, E, _IFT_M1Material_e); EN = 1.5 * E; @@ -414,12 +399,10 @@ M1Material :: initializeFrom(InputRecord *ir) NN.at(imp, 5) = s * s * s * s; mw.at(imp) = 2. / nmp; } - - return IRRT_OK; } -int -M1Material :: hasMaterialModeCapability(MaterialMode mode) +bool +M1Material :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _PlaneStress; } @@ -460,8 +443,8 @@ M1Material :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType //////////////////////////////////////////////////////////////////////////// -M1MaterialStatus :: M1MaterialStatus(int n, Domain *d, GaussPoint *g) : - StructuralMaterialStatus(n, d, g), sigN(0) +M1MaterialStatus :: M1MaterialStatus(GaussPoint *g) : + StructuralMaterialStatus(g), sigN(0) {} @@ -493,16 +476,16 @@ M1MaterialStatus :: updateYourself(TimeStep *tStep) StructuralMaterialStatus :: updateYourself(tStep); } -contextIOResultType -M1MaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +M1MaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - return StructuralMaterialStatus :: saveContext(stream, mode, obj); + StructuralMaterialStatus :: saveContext(stream, mode); } -contextIOResultType -M1MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +M1MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - return StructuralMaterialStatus :: restoreContext(stream, mode, obj); + StructuralMaterialStatus :: restoreContext(stream, mode); } #endif // end of old implementation diff --git a/src/sm/Materials/microplane_m1.h b/src/sm/Materials/microplane_m1.h index d8666c9d7..1edd86f16 100644 --- a/src/sm/Materials/microplane_m1.h +++ b/src/sm/Materials/microplane_m1.h @@ -61,11 +61,9 @@ class M1MaterialStatus : public StructuralMaterialStatus IntArray plasticState; public: - M1MaterialStatus(int n, Domain *d, GaussPoint *g); - virtual ~M1MaterialStatus(); + M1MaterialStatus(GaussPoint *g); - // definition - virtual const char *giveClassName() const { return "M1MaterialStatus"; } + const char *giveClassName() const override { return "M1MaterialStatus"; } void letTempNormalMplaneStressesBe(FloatArray sigmaN) { tempSigN = std :: move(sigmaN); } void letTempNormalMplanePlasticStrainsBe(FloatArray epsilonpN) { tempEpspN = std :: move(epsilonpN); } void letPlasticStateIndicatorsBe(IntArray plSt) { plasticState = std :: move(plSt); } @@ -74,12 +72,12 @@ class M1MaterialStatus : public StructuralMaterialStatus const FloatArray &giveNormalMplanePlasticStrains() { return epspN; } const FloatArray &giveTempNormalMplanePlasticStrains() { return tempEpspN; } const IntArray &givePlasticStateIndicators() { return plasticState; } - virtual void initTempStatus(); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void printOutputAt(FILE *file, TimeStep *tStep) const override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; /** @@ -88,11 +86,10 @@ class M1MaterialStatus : public StructuralMaterialStatus class M1Material : public MicroplaneMaterial { protected: - - double EN; // normal microplane elastic modulus - double ENtan; // normal microplane tangent (elastoplastic) modulus - double HN; // normal microplane hardening/softening modulus - double s0; // normal microplane initial yield stress + double EN = 0.; // normal microplane elastic modulus + double ENtan = 0.; // normal microplane tangent (elastoplastic) modulus + double HN = 0.; // normal microplane hardening/softening modulus + double s0 = 0.; // normal microplane initial yield stress public: /** @@ -101,26 +98,17 @@ class M1Material : public MicroplaneMaterial * @param d Domain to which newly created material belongs. */ M1Material(int n, Domain *d); - /// Destructor. - virtual ~M1Material() { } - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - virtual void giveRealMicroplaneStressVector(FloatArray &answer, Microplane *mplane, const FloatArray &strain, TimeStep *tStep) {}; + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual const char *giveClassName() const { return "M1Material"; } - virtual const char *giveInputRecordName() const { return _IFT_M1Material_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "M1Material"; } + const char *giveInputRecordName() const override { return _IFT_M1Material_Name; } + void initializeFrom(InputRecord &ir) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new M1MaterialStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new M1MaterialStatus(gp); } -protected: - MaterialStatus *CreateMicroplaneStatus(GaussPoint *gp) { return new M1MaterialStatus(1, domain, gp); } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; }; } // end namespace oofem @@ -152,22 +140,21 @@ class M1MaterialStatus : public StructuralMaterialStatus FloatArray sigN, tempSigN, sigNyield; public: - M1MaterialStatus(int n, Domain *d, GaussPoint *g); - virtual ~M1MaterialStatus(); + M1MaterialStatus(GaussPoint *g); // definition - virtual const char *giveClassName() const { return "M1MaterialStatus"; } + const char *giveClassName() const override { return "M1MaterialStatus"; } void letTempNormalMplaneStressesBe(FloatArray sigmaN) { tempSigN = std :: move(sigmaN); } void letNormalMplaneYieldStressesBe(FloatArray sigmaNyield) { sigNyield = std :: move(sigmaNyield); } const FloatArray &giveNormalMplaneStresses() { return sigN; } const FloatArray &giveTempNormalMplaneStresses() { return tempSigN; } const FloatArray &giveNormalMplaneYieldStresses() { return sigNyield; } - virtual void initTempStatus(); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void printOutputAt(FILE *file, TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -177,13 +164,12 @@ class M1MaterialStatus : public StructuralMaterialStatus class M1Material : public StructuralMaterial { protected: - - double E; // Young's modulus - double nu; // Poisson ratio - double EN; // normal microplane elastic modulus - double HN; // normal microplane hardening/softening modulus - double s0; // normal microplane initial yield stress - int nmp; // number of microplanes + double E = 0.; // Young's modulus + double nu = 0.; // Poisson ratio + double EN = 0.; // normal microplane elastic modulus + double HN = 0.; // normal microplane hardening/softening modulus + double s0 = 0.; // normal microplane initial yield stress + int nmp = 0; // number of microplanes FloatMatrix n; // microplane normals FloatMatrix N; // N = n x n in Voigt notation FloatMatrix NN; // NN = n x n x n x n in special notation @@ -196,22 +182,19 @@ class M1Material : public StructuralMaterial * @param d Domain to which newly created material belongs. */ M1Material(int n, Domain *d); - /// Destructor. - virtual ~M1Material() { } - - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); - virtual void giveElasticPlaneStressStiffMtrx(FloatMatrix &answer); - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); - virtual const char *giveClassName() const { return "M1Material"; } - virtual const char *giveInputRecordName() const { return _IFT_M1Material_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new M1MaterialStatus(1, domain, gp); } + + void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; + void giveElasticPlaneStressStiffMtrx(FloatMatrix &answer) override; + void givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; + const char *giveClassName() const override { return "M1Material"; } + const char *giveInputRecordName() const override { return _IFT_M1Material_Name; } + void initializeFrom(InputRecord &ir) override; + bool hasMaterialModeCapability(MaterialMode mode) const override; + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new M1MaterialStatus(gp); } protected: - MaterialStatus *CreateMicroplaneStatus(GaussPoint *gp) { return new M1MaterialStatus(1, domain, gp); } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; }; } // end namespace oofem #endif // end of old implementation diff --git a/src/sm/Materials/microplanematerial.C b/src/sm/Materials/microplanematerial.C index b28d4fdbb..5cdf4791b 100644 --- a/src/sm/Materials/microplanematerial.C +++ b/src/sm/Materials/microplanematerial.C @@ -33,7 +33,6 @@ */ #include "microplanematerial.h" -#include "microplane.h" #include "gausspoint.h" #include "floatarray.h" #include "contextioerr.h" @@ -41,264 +40,99 @@ #include "dynamicinputrecord.h" namespace oofem { -Microplane * -MicroplaneMaterial :: giveMicroplane(int i, GaussPoint *masterGp) -{ - // - // return the i-th slave integration point (microplane) of master gp - // if slaves of gp don't exists - create them - - // - GaussPoint *slave = masterGp->giveSlaveGaussPoint(i); - if ( slave == NULL ) { - // check for proper dimensions - slave can be NULL if index too high or if not - // slaves previously defined - if ( ( i < 0 ) || ( i > ( this->numberOfMicroplanes - 1 ) ) ) { - OOFEM_ERROR("no such microplane defined"); - } - - // create new slave record in masterGp - // (requires that this is friend of gp) - - MaterialMode slaveMode, masterMode = masterGp->giveMaterialMode(); - slaveMode = this->giveCorrespondingSlaveMaterialMode(masterMode); - - masterGp->gaussPoints.resize(this->numberOfMicroplanes); - for ( int j = 0; j < numberOfMicroplanes; j++ ) { - masterGp->gaussPoints [ j ] = new Microplane(masterGp->giveIntegrationRule(), j + 1, slaveMode); - } - - slave = masterGp->gaussPoints [ i ]; - } - - return static_cast< Microplane * >(slave); -} - - -MaterialMode -MicroplaneMaterial :: giveCorrespondingSlaveMaterialMode(MaterialMode masterMode) -{ - return _3dMicroplane; -} - -IntegrationPointStatus * -MicroplaneMaterial :: giveMicroplaneStatus(GaussPoint *gp) -/* - * returns material status in gp corresponding to specific material class - */ -{ - IntegrationPointStatus *status = gp->giveMaterialStatus(); - if ( status == NULL ) { - // create a new one - status = this->CreateMicroplaneStatus(gp); - // if newly created status is null - // don't include it. specific instance - // does not have status. - if ( status != NULL ) { - gp->setMaterialStatus( status, this->giveNumber() ); - } - } - - return status; -} - -void -MicroplaneMaterial :: initTempStatus(GaussPoint *gp) -{ - // init master - this->giveStatus(gp)->initTempStatus(); - - // init master microplanes - for ( int mPlaneIndex = 0; mPlaneIndex < numberOfMicroplanes; mPlaneIndex++ ) { - Microplane *mPlane = this->giveMicroplane(mPlaneIndex, gp); - MaterialStatus *status = dynamic_cast< MaterialStatus * >( this->giveMicroplaneStatus(mPlane) ); - if ( status ) { - status->initTempStatus(); - } - } -} - -contextIOResultType -MicroplaneMaterial :: saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -{ - contextIOResultType iores; - - if ( gp == NULL ) { - THROW_CIOERR(CIO_BADOBJ); - } - - // save master - if ( ( iores = StructuralMaterial :: saveIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // save microplanes - for ( int mPlaneIndex = 0; mPlaneIndex < numberOfMicroplanes; mPlaneIndex++ ) { - Microplane *mPlane = this->giveMicroplane(mPlaneIndex, gp); - IntegrationPointStatus *status = this->giveMicroplaneStatus(mPlane); - if ( status ) { - if ( ( iores = status->saveContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - } - } - - return CIO_OK; -} - -contextIOResultType -MicroplaneMaterial :: restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -{ - contextIOResultType iores; - - // corresponding gp is passed in obj - if ( gp == NULL ) { - THROW_CIOERR(CIO_BADOBJ); - } - - // save master - if ( ( iores = StructuralMaterial :: restoreIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // save microplanes - for ( int mPlaneIndex = 0; mPlaneIndex < numberOfMicroplanes; mPlaneIndex++ ) { - Microplane *mPlane = this->giveMicroplane(mPlaneIndex, gp); - IntegrationPointStatus *status = this->giveMicroplaneStatus(mPlane); - if ( status ) { - if ( ( iores = status->restoreContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - } - } - - return CIO_OK; -} - - - - -void -MicroplaneMaterial :: giveMicroplaneNormal(FloatArray &answer, Microplane *mplane) -{ - int mnumber = mplane->giveNumber(); - answer.resize(3); - - answer.at(1) = microplaneNormals [ mnumber - 1 ] [ 0 ]; - answer.at(2) = microplaneNormals [ mnumber - 1 ] [ 1 ]; - answer.at(3) = microplaneNormals [ mnumber - 1 ] [ 2 ]; -} double -MicroplaneMaterial :: giveMicroplaneIntegrationWeight(Microplane *mplane) +MicroplaneMaterial :: giveMicroplaneIntegrationWeight(int mnumber) const { - int mnumber = mplane->giveNumber(); - return microplaneWeights [ mnumber - 1 ]; } double -MicroplaneMaterial :: computeNormalStrainComponent(Microplane *mplane, - const FloatArray ¯oStrain) +MicroplaneMaterial :: computeNormalStrainComponent(int mnumber, + const FloatArray ¯oStrain) const { - int mnumber = mplane->giveNumber(); double en = 0.0; - for ( int i = 0; i < 6; i++ ) { - en += N [ mnumber - 1 ] [ i ] * macroStrain.at(i + 1); + en += N [ mnumber - 1 ] [ i ] * macroStrain[ i ]; } return en; } double -MicroplaneMaterial :: computeNormalVolumetricStrainComponent(Microplane *mplane, - const FloatArray ¯oStrain) +MicroplaneMaterial :: computeNormalVolumetricStrainComponent(const FloatArray ¯oStrain) const { return ( macroStrain.at(1) + macroStrain.at(2) + macroStrain.at(3) ) / 3.0; } double -MicroplaneMaterial :: computeNormalDeviatoricStrainComponent(Microplane *mplane, - const FloatArray ¯oStrain) +MicroplaneMaterial :: computeNormalDeviatoricStrainComponent(int mnumber, + const FloatArray ¯oStrain) const { - return this->computeNormalStrainComponent(mplane, macroStrain) - - this->computeNormalVolumetricStrainComponent(mplane, macroStrain); + return this->computeNormalStrainComponent(mnumber, macroStrain) - + this->computeNormalVolumetricStrainComponent(macroStrain); } double -MicroplaneMaterial :: computeShearMStrainComponent(Microplane *mplane, - const FloatArray ¯oStrain) +MicroplaneMaterial :: computeShearMStrainComponent(int mnumber, + const FloatArray ¯oStrain) const { - int mnumber = mplane->giveNumber(); double em = 0.0; - for ( int i = 0; i < 6; i++ ) { - em += M [ mnumber - 1 ] [ i ] * macroStrain.at(i + 1); + em += M [ mnumber - 1 ] [ i ] * macroStrain[ i ]; } return em; } double -MicroplaneMaterial :: computeShearLStrainComponent(Microplane *mplane, - const FloatArray ¯oStrain) +MicroplaneMaterial :: computeShearLStrainComponent(int mnumber, + const FloatArray ¯oStrain) const { - int mnumber = mplane->giveNumber(); double el = 0.0; for ( int i = 0; i < 6; i++ ) { - el += L [ mnumber - 1 ] [ i ] * macroStrain.at(i + 1); + el += L [ mnumber - 1 ] [ i ] * macroStrain[ i ]; } return el; } -void -MicroplaneMaterial :: computeStrainVectorComponents(FloatArray &answer, Microplane *mplane, - const FloatArray ¯oStrain) +MicroplaneState +MicroplaneMaterial :: computeStrainVectorComponents(int mnumber, + const FloatArray ¯oStrain) const { - int mnumber = mplane->giveNumber(); - double en = 0., ev = 0., em = 0., el = 0.; + MicroplaneState e; for ( int i = 0; i < 6; i++ ) { - en += N [ mnumber - 1 ] [ i ] * macroStrain.at(i + 1); - em += M [ mnumber - 1 ] [ i ] * macroStrain.at(i + 1); - el += L [ mnumber - 1 ] [ i ] * macroStrain.at(i + 1); + e.n += N [ mnumber - 1 ] [ i ] * macroStrain [ i ]; + e.m += M [ mnumber - 1 ] [ i ] * macroStrain [ i ]; + e.l += L [ mnumber - 1 ] [ i ] * macroStrain [ i ]; } - ev = ( macroStrain.at(1) + macroStrain.at(2) + macroStrain.at(3) ) / 3.0; - - answer.resize(4); - answer.zero(); - answer.at(1) = ev; - answer.at(2) = en; - answer.at(3) = el; - answer.at(4) = em; + e.v = ( macroStrain.at(1) + macroStrain.at(2) + macroStrain.at(3) ) / 3.0; + return e; } -void -MicroplaneMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, + +FloatMatrixF<6,6> +MicroplaneMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - answer.resize(6, 6); - answer.zero(); + FloatMatrixF<6,6> answer; // elastic stiffness matrix answer.at(4, 4) = answer.at(5, 5) = answer.at(6, 6) = E / ( 2. + 2. * nu ); answer.at(1, 1) = answer.at(2, 2) = answer.at(3, 3) = E * ( 1. - nu ) / ( ( 1. + nu ) * ( 1. - 2. * nu ) ); answer.at(1, 2) = answer.at(2, 1) = answer.at(1, 3) = answer.at(3, 1) = - answer.at(2, 3) = answer.at(3, 2) = E * nu / ( ( 1. + nu ) * ( 1. - 2. * nu ) ); + answer.at(2, 3) = answer.at(3, 2) = E * nu / ( ( 1. + nu ) * ( 1. - 2. * nu ) ); + return answer; } -IRResultType -MicroplaneMaterial :: initializeFrom(InputRecord *ir) +void +MicroplaneMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + StructuralMaterial :: initializeFrom(ir); // elastic constants IR_GIVE_FIELD(ir, E, _IFT_MicroplaneMaterial_e); @@ -306,7 +140,6 @@ MicroplaneMaterial :: initializeFrom(InputRecord *ir) // number of microplanes IR_GIVE_FIELD(ir, numberOfMicroplanes, _IFT_MicroplaneMaterial_nmp); this->initializeData(numberOfMicroplanes); - return IRRT_OK; } @@ -321,7 +154,6 @@ MicroplaneMaterial :: giveInputRecord(DynamicInputRecord &input) void MicroplaneMaterial :: initializeData(int numberOfMicroplanes) { - int i, i4, mPlane; int ij [ 6 ] [ 2 ] = { { 1, 1 }, { 2, 2 }, { 3, 3 }, { 2, 3 }, { 3, 1 }, { 1, 2 } }; // kronecker delta @@ -333,9 +165,14 @@ MicroplaneMaterial :: initializeData(int numberOfMicroplanes) Kronecker [ 5 ] = 0.; // definition of intergation points and weights + microplaneNormals.resize(numberOfMicroplanes); + microplaneWeights.resize(numberOfMicroplanes); + M.resize(numberOfMicroplanes); + N.resize(numberOfMicroplanes); + L.resize(numberOfMicroplanes); if ( numberOfMicroplanes == 28 ) { - for ( i = 0; i < 4; i++ ) { + for ( int i = 0; i < 4; i++ ) { microplaneWeights [ i ] = 0.0160714276E0; microplaneWeights [ i + 4 ] = 0.0204744730E0; microplaneWeights [ i + 8 ] = 0.0204744730E0; @@ -351,8 +188,8 @@ MicroplaneMaterial :: initializeData(int numberOfMicroplanes) { .186156720E0, .694746614E0, .694746614E0 }, { .694746614E0, .186156720E0, .694746614E0 }, { .694746614E0, .694746614E0, .186156720E0 } }; - for ( i = 0; i < 7; i++ ) { - i4 = i * 4; + for ( int i = 0; i < 7; i++ ) { + int i4 = i * 4; microplaneNormals [ i4 ] [ 0 ] = help [ i ] [ 0 ]; microplaneNormals [ i4 ] [ 1 ] = help [ i ] [ 1 ]; microplaneNormals [ i4 ] [ 2 ] = help [ i ] [ 2 ]; @@ -399,7 +236,7 @@ MicroplaneMaterial :: initializeData(int numberOfMicroplanes) * * l.beVectorProductOf (m,n); * - * for (i=0; i<6; i++) { + * for (int i=0; i<6; i++) { * ii = ij[i][0]; * jj = ij[i][1]; * N[mPlane][i] = n.at(ii)*n.at(jj); @@ -410,15 +247,15 @@ MicroplaneMaterial :: initializeData(int numberOfMicroplanes) * * } */ } else if ( numberOfMicroplanes == 21 ) { - for ( i = 0; i < 3; i++ ) { + for ( int i = 0; i < 3; i++ ) { microplaneWeights [ i ] = 0.02652141274; } - for ( i = 3; i < 9; i++ ) { + for ( int i = 3; i < 9; i++ ) { microplaneWeights [ i ] = 0.01993014153; } - for ( i = 9; i < 21; i++ ) { + for ( int i = 9; i < 21; i++ ) { microplaneWeights [ i ] = 0.02507124272; } @@ -440,8 +277,8 @@ MicroplaneMaterial :: initializeData(int numberOfMicroplanes) { 0.3879072746, 0.8360956240, 0.3879072746 }, { 0.8360956240, 0.3879072746, 0.3879072746 } }; - for ( i = 0; i < 3; i++ ) { - i4 = i * 4; + for ( int i = 0; i < 3; i++ ) { + int i4 = i * 4; microplaneNormals [ 9 + i4 ] [ 0 ] = help [ i ] [ 0 ]; microplaneNormals [ 9 + i4 ] [ 1 ] = help [ i ] [ 1 ]; microplaneNormals [ 9 + i4 ] [ 2 ] = help [ i ] [ 2 ]; @@ -590,7 +427,7 @@ MicroplaneMaterial :: initializeData(int numberOfMicroplanes) { 0.274960591212, -0.304743149777, 0.911881728046, 0.00690477957966 } }; - for ( i = 0; i < numberOfMicroplanes; i++ ) { + for ( int i = 0; i < numberOfMicroplanes; i++ ) { microplaneNormals [ i ] [ 0 ] = help [ i ] [ 0 ]; microplaneNormals [ i ] [ 1 ] = help [ i ] [ 1 ]; microplaneNormals [ i ] [ 2 ] = help [ i ] [ 2 ]; @@ -603,7 +440,7 @@ MicroplaneMaterial :: initializeData(int numberOfMicroplanes) * FloatArray n(3), m(3), l(3); * double aux; * - * for (mPlane=0; mPlane < numberOfMicroplanes; mPlane++) { + * for (int mPlane=0; mPlane < numberOfMicroplanes; mPlane++) { * n.at(1) = microplaneNormals[mPlane][0]; * n.at(2) = microplaneNormals[mPlane][1]; * n.at(3) = microplaneNormals[mPlane][2]; @@ -645,17 +482,13 @@ MicroplaneMaterial :: initializeData(int numberOfMicroplanes) } // compute projection tensors for each microplane - int ii, jj; - FloatArray n(3), m(3), l(3); - double aux; + FloatArray m(3), l(3); - for ( mPlane = 0; mPlane < numberOfMicroplanes; mPlane++ ) { - n.at(1) = microplaneNormals [ mPlane ] [ 0 ]; - n.at(2) = microplaneNormals [ mPlane ] [ 1 ]; - n.at(3) = microplaneNormals [ mPlane ] [ 2 ]; + for ( int mPlane = 0; mPlane < numberOfMicroplanes; mPlane++ ) { + auto n = microplaneNormals [ mPlane ]; if ( ( mPlane + 1 ) % 3 == 0 ) { - aux = sqrt( n.at(1) * n.at(1) + n.at(2) * n.at(2) ); + double aux = sqrt( n.at(1) * n.at(1) + n.at(2) * n.at(2) ); if ( fabs(aux) > 1.0e-12 ) { m.at(1) = n.at(2) / aux; m.at(2) = -n.at(1) / aux; @@ -666,7 +499,7 @@ MicroplaneMaterial :: initializeData(int numberOfMicroplanes) m.at(3) = 0.0; } } else if ( ( mPlane + 1 ) % 3 == 1 ) { - aux = sqrt( n.at(2) * n.at(2) + n.at(3) * n.at(3) ); + double aux = sqrt( n.at(2) * n.at(2) + n.at(3) * n.at(3) ); if ( fabs(aux) > 1.0e-12 ) { m.at(1) = 0.0; m.at(2) = n.at(3) / aux; @@ -677,7 +510,7 @@ MicroplaneMaterial :: initializeData(int numberOfMicroplanes) m.at(3) = 0.0; } } else { - aux = sqrt( n.at(1) * n.at(1) + n.at(3) * n.at(3) ); + double aux = sqrt( n.at(1) * n.at(1) + n.at(3) * n.at(3) ); if ( fabs(aux) > 1.0e-12 ) { m.at(1) = n.at(3) / aux; m.at(2) = 0.0; @@ -692,9 +525,9 @@ MicroplaneMaterial :: initializeData(int numberOfMicroplanes) l.beVectorProductOf(m, n); - for ( i = 0; i < 6; i++ ) { - ii = ij [ i ] [ 0 ]; - jj = ij [ i ] [ 1 ]; + for ( int i = 0; i < 6; i++ ) { + int ii = ij [ i ] [ 0 ]; + int jj = ij [ i ] [ 1 ]; N [ mPlane ] [ i ] = n.at(ii) * n.at(jj); M [ mPlane ] [ i ] = 0.5 * ( m.at(ii) * n.at(jj) + m.at(jj) * n.at(ii) ); diff --git a/src/sm/Materials/microplanematerial.h b/src/sm/Materials/microplanematerial.h index cf267c854..814dcc37f 100644 --- a/src/sm/Materials/microplanematerial.h +++ b/src/sm/Materials/microplanematerial.h @@ -35,8 +35,9 @@ #ifndef microplanematerial_h #define microplanematerial_h -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "matconst.h" +#include "floatarrayf.h" ///@name Input fields for MicroplaneMaterial //@{ @@ -46,10 +47,19 @@ //@} namespace oofem { -class Microplane; #define MAX_NUMBER_OF_MICROPLANES 61 +/// Defines the stress or strain state in a micro plane +struct MicroplaneState +{ + double n = 0.; + double v = 0.; + double m = 0.; + double l = 0.; +}; + + /** * Abstract base class for all microplane models. * @@ -63,37 +73,37 @@ class MicroplaneMaterial : public StructuralMaterial { protected: /// Number of microplanes. - int numberOfMicroplanes; + int numberOfMicroplanes = 0; /// Integration weights of microplanes. - double microplaneWeights [ MAX_NUMBER_OF_MICROPLANES ]; + FloatArray microplaneWeights; /// Normals of microplanes. - double microplaneNormals [ MAX_NUMBER_OF_MICROPLANES ] [ 3 ]; + std::vector> microplaneNormals; /// Kronecker's delta. - double Kronecker [ 6 ]; + FloatArrayF<6> Kronecker; /** * Normal projection tensors for all microplanes. * Due to symmetry, compressed form is stored. */ - double N [ MAX_NUMBER_OF_MICROPLANES ] [ 6 ]; + std::vector> N; /** * Shear projection tensors (m direction) for all microplanes. * Due to symmetry, compressed form is stored. */ - double M [ MAX_NUMBER_OF_MICROPLANES ] [ 6 ]; + std::vector> M; /** * Shear projection tensors (l direction) for all microplanes. * Due to symmetry, compressed form is stored. */ - double L [ MAX_NUMBER_OF_MICROPLANES ] [ 6 ]; + std::vector> L; /// Young's modulus - double E; + double E = 0.; /// Poisson's ratio - double nu; + double nu = 0.; public: @@ -102,66 +112,41 @@ class MicroplaneMaterial : public StructuralMaterial * @param n Material number. * @param d Domain to which newly created material belongs. */ - MicroplaneMaterial(int n, Domain *d) : StructuralMaterial(n, d), numberOfMicroplanes(0) { } - /// Destructor. - virtual ~MicroplaneMaterial() { } - - /** - * Computes real stress vector on given microplane - * (the meaning of values depends on particular implementation, - * e.g, can contain volumetric, deviatoric normal stresses and shear stresses on microplane) - * for given increment of microplane strains. - * @param answer Computed result. - * @param mplane Pointer to microplane object, for which response is computed. - * @param strain Strain vector. - * @param tStep Time step. - */ - virtual void giveRealMicroplaneStressVector(FloatArray &answer, Microplane *mplane, - const FloatArray &strain, TimeStep *tStep) = 0; + MicroplaneMaterial(int n, Domain *d) : StructuralMaterial(n, d) { } /** * Computes the length of normal strain vector on given microplane. */ - double computeNormalStrainComponent(Microplane *mplane, const FloatArray ¯oStrain); + double computeNormalStrainComponent(int mnumber, const FloatArray ¯oStrain) const; /** * Computes the normal volumetric component of macro strain on given microplane. */ - double computeNormalVolumetricStrainComponent(Microplane *mplane, const FloatArray ¯oStrain); + double computeNormalVolumetricStrainComponent(const FloatArray ¯oStrain) const; /** * Computes the normal deviatoric component of macro strain on given microplane. */ - double computeNormalDeviatoricStrainComponent(Microplane *mplane, const FloatArray ¯oStrain); + double computeNormalDeviatoricStrainComponent(int mnumber, const FloatArray ¯oStrain) const; /** * Computes the shear component (in m direction) of macro strain on given microplane. */ - double computeShearMStrainComponent(Microplane *mplane, const FloatArray ¯oStrain); + double computeShearMStrainComponent(int mnumber, const FloatArray ¯oStrain) const; /** * Computes the shear component (in l direction) of macro strain on given microplane. */ - double computeShearLStrainComponent(Microplane *mplane, const FloatArray ¯oStrain); + double computeShearLStrainComponent(int mnumber, const FloatArray ¯oStrain) const; /** * Computes the vector of all micro stress components (Ev, En, Em, El) of macro strain * vector on given microplane. */ - void computeStrainVectorComponents(FloatArray &answer, Microplane *mplane, - const FloatArray ¯oStrain); + MicroplaneState computeStrainVectorComponents(int mnumber, const FloatArray ¯oStrain) const; - /** - * Computes normal of given microplane. - * @param answer Normal of given microplane. - * @param mplane Microplane, which normal will be computed. - */ - virtual void giveMicroplaneNormal(FloatArray &answer, Microplane *mplane); /** * Returns microplane integration weight. * @param mplane Microplane. * @return Integration weight of given microplane. */ - virtual double giveMicroplaneIntegrationWeight(Microplane *mplane); - - /// Returns i-th microplane belonging to master-macro-integration point. )-based indexing. - Microplane *giveMicroplane(int i, GaussPoint *masterGp); + double giveMicroplaneIntegrationWeight(int mnumber) const; /** * Initializes internal data (integration weights, @@ -170,27 +155,10 @@ class MicroplaneMaterial : public StructuralMaterial */ virtual void initializeData(int numberOfMicroplanes); - /** - * Returns corresponding material mode for microplane according to macro integration mode - */ - virtual MaterialMode giveCorrespondingSlaveMaterialMode(MaterialMode masterMode); - - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual contextIOResultType saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); - virtual contextIOResultType restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); - - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - - virtual IntegrationPointStatus *giveMicroplaneStatus(GaussPoint *gp); - -protected: - virtual MaterialStatus *CreateMicroplaneStatus(GaussPoint *gp) = 0; - virtual void initTempStatus(GaussPoint *gp); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; }; } // end namespace oofem #endif // microplanematerial_h diff --git a/src/sm/Materials/microplanematerial_bazant.C b/src/sm/Materials/microplanematerial_bazant.C index cc7250243..af210f786 100644 --- a/src/sm/Materials/microplanematerial_bazant.C +++ b/src/sm/Materials/microplanematerial_bazant.C @@ -33,7 +33,6 @@ */ #include "microplanematerial_bazant.h" -#include "microplane.h" #include "floatarray.h" namespace oofem { @@ -41,44 +40,40 @@ MicroplaneMaterial_Bazant :: MicroplaneMaterial_Bazant(int n, Domain *d) : Micro { } -void -MicroplaneMaterial_Bazant :: giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) +FloatArrayF<6> +MicroplaneMaterial_Bazant :: giveRealStressVector_3d(const FloatArrayF<6> &strain, + GaussPoint *gp, TimeStep *tStep) const { - double SvDash, SvSum = 0.; - double SD; + double SvDash = 0., SvSum = 0.; FloatArray mPlaneNormalStress(numberOfMicroplanes), mPlaneShear_L_Stress(numberOfMicroplanes), mPlaneShear_M_Stress(numberOfMicroplanes); - double mPlaneIntegrationWeight; - FloatArray mPlaneStressCmpns, mPlaneStrainCmpns; - - answer.resize(6); - answer.zero(); - - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); + FloatArrayF<6> answer; for ( int mPlaneIndex = 0; mPlaneIndex < numberOfMicroplanes; mPlaneIndex++ ) { - Microplane *mPlane = this->giveMicroplane(mPlaneIndex, gp); int mPlaneIndex1 = mPlaneIndex + 1; // compute strain projections on mPlaneIndex-th microplane - computeStrainVectorComponents(mPlaneStrainCmpns, mPlane, totalStrain); + auto mPlaneStrainCmpns = computeStrainVectorComponents(mPlaneIndex1, strain); // compute real stresses on this microplane - giveRealMicroplaneStressVector(mPlaneStressCmpns, mPlane, mPlaneStrainCmpns, tStep); + auto mPlaneStressCmpns = giveRealMicroplaneStressVector(gp, mPlaneIndex1, mPlaneStrainCmpns, tStep); - mPlaneNormalStress.at(mPlaneIndex1) = mPlaneStressCmpns.at(2); - mPlaneShear_L_Stress.at(mPlaneIndex1) = mPlaneStressCmpns.at(3); - mPlaneShear_M_Stress.at(mPlaneIndex1) = mPlaneStressCmpns.at(4); - mPlaneIntegrationWeight = this->giveMicroplaneIntegrationWeight(mPlane); + mPlaneNormalStress.at(mPlaneIndex1) = mPlaneStressCmpns.n; + mPlaneShear_L_Stress.at(mPlaneIndex1) = mPlaneStressCmpns.l; + mPlaneShear_M_Stress.at(mPlaneIndex1) = mPlaneStressCmpns.m; + double mPlaneIntegrationWeight = this->giveMicroplaneIntegrationWeight(mPlaneIndex1); SvSum += mPlaneNormalStress.at(mPlaneIndex1) * mPlaneIntegrationWeight; - SD = mPlaneNormalStress.at(mPlaneIndex1) - mPlaneStressCmpns.at(1); + double SD = mPlaneNormalStress.at(mPlaneIndex1) - mPlaneStressCmpns.v; //SDSum += SD* mPlaneIntegrationWeight; + SvDash = mPlaneStressCmpns.v; + //volumetric stress is the same for all mplanes + //and does not need to be homogenized . + //Only updating accordinging to mean normal stress must be done. + //Use updateVolumetricStressTo() if necessary // perform homogenization // mPlaneStressCmpns.at(1) je SVdash @@ -95,29 +90,22 @@ MicroplaneMaterial_Bazant :: giveRealStressVector_3d(FloatArray &answer, } } - SvSum = SvSum * 6.; + SvSum *= 6.; //nakonec answer take *6 - SvDash = mPlaneStressCmpns.at(1); - //volumetric stress is the same for all mplanes - //and does not need to be homogenized . - //Only updating accordinging to mean normal stress must be done. - //Use updateVolumetricStressTo() if necessary - // sv=min(integr(sn)/2PI,SvDash) if ( SvDash > SvSum / 3. ) { SvDash = SvSum / 3.; - answer.zero(); + answer = zeros<6>(); for ( int mPlaneIndex = 0; mPlaneIndex < numberOfMicroplanes; mPlaneIndex++ ) { - Microplane *mPlane = this->giveMicroplane(mPlaneIndex, gp); int mPlaneIndex1 = mPlaneIndex + 1; - updateVolumetricStressTo(mPlane, SvDash); + updateVolumetricStressTo(gp, mPlaneIndex1, SvDash); - SD = mPlaneNormalStress.at(mPlaneIndex1) - SvDash; - mPlaneIntegrationWeight = this->giveMicroplaneIntegrationWeight(mPlane); + double SD = mPlaneNormalStress.at(mPlaneIndex1) - SvDash; + double mPlaneIntegrationWeight = this->giveMicroplaneIntegrationWeight(mPlaneIndex1); for ( int i = 0; i < 6; i++ ) { answer.at(i + 1) += ( ( N [ mPlaneIndex ] [ i ] - Kronecker [ i ] / 3. ) * SD + @@ -128,14 +116,15 @@ MicroplaneMaterial_Bazant :: giveRealStressVector_3d(FloatArray &answer, } } - answer.times(6.0); + answer *= 6.0; //2nd constraint, addition of volumetric part answer.at(1) += SvDash; answer.at(2) += SvDash; answer.at(3) += SvDash; - status->letTempStrainVectorBe(totalStrain); + status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(answer); + return answer; } } // end namespace oofem diff --git a/src/sm/Materials/microplanematerial_bazant.h b/src/sm/Materials/microplanematerial_bazant.h index 3bef27fb1..6693812c1 100644 --- a/src/sm/Materials/microplanematerial_bazant.h +++ b/src/sm/Materials/microplanematerial_bazant.h @@ -35,7 +35,7 @@ #ifndef microplanematerial_bazant_h #define microplanematerial_bazant_h -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "microplanematerial.h" @@ -56,21 +56,21 @@ class MicroplaneMaterial_Bazant : public MicroplaneMaterial * @param d Domain to which newly created material belongs. */ MicroplaneMaterial_Bazant(int n, Domain * d); - /// Destructor. - virtual ~MicroplaneMaterial_Bazant() { } - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, + TimeStep *tStep) const override; + /** + * Computes stress on given microplane (volumetric, deviatoric normal stresses and shead stresses) + */ + virtual MicroplaneState giveRealMicroplaneStressVector(GaussPoint *gp, int mnumber, const MicroplaneState &strain, TimeStep *tStep) const = 0; /** * Updates the volumetric stress component after computing real stress microplane vectors. */ - virtual void updateVolumetricStressTo(Microplane *mPlane, double sigv) = 0; - - virtual const char *giveClassName() const { return "MicroplaneMaterial_Bazant"; } + virtual void updateVolumetricStressTo(GaussPoint *gp, int mnumber, double sigv) const = 0; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new StructuralMaterialStatus(1, domain, gp); } + const char *giveClassName() const override { return "MicroplaneMaterial_Bazant"; } }; } // end namespace oofem #endif // microplanematerial_bazant_h diff --git a/src/sm/Materials/misesmat.C b/src/sm/Materials/misesmat.C index 0eb55e378..35873ced9 100644 --- a/src/sm/Materials/misesmat.C +++ b/src/sm/Materials/misesmat.C @@ -10,7 +10,7 @@ * * OOFEM : Object Oriented Finite Element Code * - * Copyright (C) 1993 - 2013 Borek Patzak + * Copyright (C) 1993 - 2019 Borek Patzak * * * @@ -33,7 +33,7 @@ */ #include "misesmat.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" @@ -44,256 +44,143 @@ #include "datastream.h" #include "classfactory.h" #include "fieldmanager.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "engngm.h" namespace oofem { REGISTER_Material(MisesMat); -// constructor -MisesMat :: MisesMat(int n, Domain *d) : StructuralMaterial(n, d) -{ - linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); - H = 0.; - //sig0 = 0.; - G = 0.; - K = 0.; -} -// destructor -MisesMat :: ~MisesMat() -{ - delete linearElasticMaterial; -} +MisesMat::MisesMat(int n, Domain *d) : StructuralMaterial(n, d), + linearElasticMaterial(n, d) +{} + -// reads the model parameters from the input file -IRResultType -MisesMat :: initializeFrom(InputRecord *ir) +void +MisesMat::initializeFrom(InputRecord &ir) { - IRResultType result; // required by IR_GIVE_FIELD macro + StructuralMaterial::initializeFrom(ir); + linearElasticMaterial.initializeFrom(ir); // takes care of elastic constants - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + G = linearElasticMaterial.giveShearModulus(); + K = linearElasticMaterial.giveBulkModulus(); - result = linearElasticMaterial->initializeFrom(ir); // takes care of elastic constants - if ( result != IRRT_OK ) return result; - G = static_cast< IsotropicLinearElasticMaterial * >(linearElasticMaterial)->giveShearModulus(); - K = static_cast< IsotropicLinearElasticMaterial * >(linearElasticMaterial)->giveBulkModulus(); + hType = 0; + IR_GIVE_OPTIONAL_FIELD(ir, hType, _IFT_MisesMat_htype); //hardening type - IR_GIVE_FIELD(ir, sig0, _IFT_MisesMat_sig0); // uniaxial yield stress + if ( hType == 0 ) { + IR_GIVE_FIELD(ir, sig0, _IFT_MisesMat_sig0); // uniaxial yield stress + H = 0.; + IR_GIVE_OPTIONAL_FIELD(ir, H, _IFT_MisesMat_h); // hardening modulus + } else if ( hType == 1 ) { //user defined hardening function + IR_GIVE_FIELD(ir, h_eps, _IFT_MisesMat_h_eps); + IR_GIVE_FIELD(ir, h_function_eps, _IFT_MisesMat_h_function_eps); + + if ( h_eps.at(1) != 0. ) { + throw ValueInputException(ir, _IFT_MisesMat_h_eps, "The first entry in h_eps must be 0."); + } + + if ( h_eps.giveSize() != h_function_eps.giveSize() ) { + throw ValueInputException(ir, _IFT_MisesMat_h_function_eps, "the size of 'h_eps' and 'h(eps)' must be the same"); + } + } else { + throw ValueInputException(ir, _IFT_MisesMat_htype, "Unknown htype. Should be either 0 or 1.\n"); + } - H = 0.; - IR_GIVE_OPTIONAL_FIELD(ir, H, _IFT_MisesMat_h); // hardening modulus - /*********************************************************************************************************/ omega_crit = 0; IR_GIVE_OPTIONAL_FIELD(ir, omega_crit, _IFT_MisesMat_omega_crit); // critical damage a = 0; IR_GIVE_OPTIONAL_FIELD(ir, a, _IFT_MisesMat_a); // exponent in damage law - /********************************************************************************************************/ - return IRRT_OK; + yieldTol = 1.e-6; + IR_GIVE_OPTIONAL_FIELD(ir, yieldTol, _IFT_MisesMat_yieldTol); // tolerance in the yield condition } // creates a new material status corresponding to this class MaterialStatus * -MisesMat :: CreateStatus(GaussPoint *gp) const +MisesMat::CreateStatus(GaussPoint *gp) const { - return new MisesMatStatus(1, this->giveDomain(), gp); + return new MisesMatStatus(gp); } -void -MisesMat :: giveRealStressVector_1d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) +FloatArrayF< 1 > +MisesMat::giveRealStressVector_1d(const FloatArrayF< 1 > &totalStrain, + GaussPoint *gp, + TimeStep *tStep) const { /// @note: One should obtain the same answer using the iterations in the default implementation (this is verified for this model). #if 1 - MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); - FloatArray strainR; - + auto status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); + // subtract stress independent part - this->giveStressDependentPartOfStrainVector(strainR, gp, totalStrain, - tStep, VM_Total); - this->performPlasticityReturn(gp, strainR, tStep); + FloatArray strainR; + this->giveStressDependentPartOfStrainVector(strainR, gp, totalStrain, tStep, VM_Total); + this->performPlasticityReturn(strainR, gp, tStep); double omega = computeDamage(gp, tStep); - answer = status->giveTempEffectiveStress(); - answer.times(1 - omega); + FloatArrayF< 6 >stress = status->giveTempEffectiveStress() * ( 1 - omega ); // Compute the other components of the strain: - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); - double E = lmat->give('E', gp), nu = lmat->give('n', gp); + double E = linearElasticMaterial.give('E', gp), nu = linearElasticMaterial.give('n', gp); - FloatArray strain = status->getTempPlasticStrain(); - strain[0] = totalStrain[0]; - strain[1] -= nu / E * status->giveTempEffectiveStress()[0]; - strain[2] -= nu / E * status->giveTempEffectiveStress()[0]; + auto strain = status->getTempPlasticStrain(); + strain [ 0 ] = totalStrain [ 0 ]; + strain [ 1 ] -= nu / E * status->giveTempEffectiveStress() [ 0 ]; + strain [ 2 ] -= nu / E * status->giveTempEffectiveStress() [ 0 ]; status->letTempStrainVectorBe(strain); status->setTempDamage(omega); - status->letTempStressVectorBe(answer); + status->letTempStressVectorBe(stress); + return stress [ { 0 } ]; + #else - StructuralMaterial :: giveRealStressVector_1d(answer, gp, totalStrain, tStep); + return StructuralMaterial::giveRealStressVector_1d(totalStrain, gp, tStep); + #endif } -void -MisesMat :: giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) -{ - MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); - // subtract stress independent part - FloatArray strainR(6); - this->giveStressDependentPartOfStrainVector(strainR, gp, totalStrain, - tStep, VM_Total); - this->performPlasticityReturn(gp, strainR, tStep); +FloatArrayF< 3 > +MisesMat::giveRealStressVector_PlaneStress(const FloatArrayF< 3 > &totalStrain, + GaussPoint *gp, TimeStep *tStep) const +{ + auto status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); + // initialization + const_cast< MisesMat * >( this )->initTempStatus(gp); + this->performPlasticityReturn_PlaneStress(totalStrain, gp, tStep); double omega = computeDamage(gp, tStep); - answer = status->giveTempEffectiveStress(); - answer.times(1 - omega); + FloatArrayF< 3 >stress = status->giveTempEffectiveStress() * ( 1 - omega ); status->setTempDamage(omega); status->letTempStrainVectorBe(totalStrain); - status->letTempStressVectorBe(answer); + status->letTempStressVectorBe(stress); + return stress; } -void -MisesMat :: giveFirstPKStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalDefGradOOFEM, - TimeStep *tStep) +FloatArrayF< 6 > +MisesMat::giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, + TimeStep *tStep) const { - MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); - - double kappa, dKappa, yieldValue, mi; - FloatMatrix F, oldF, invOldF; - FloatArray s; - F.beMatrixForm(totalDefGradOOFEM); //(method assumes full 3D) - - kappa = status->giveCumulativePlasticStrain(); - oldF.beMatrixForm( status->giveFVector() ); - invOldF.beInverseOf(oldF); - //relative deformation radient - FloatMatrix f; - f.beProductOf(F, invOldF); - //compute elastic predictor - FloatMatrix trialLeftCauchyGreen, help; - - f.times( 1./cbrt(f.giveDeterminant()) ); - - help.beProductOf(f, status->giveTempLeftCauchyGreen()); - trialLeftCauchyGreen.beProductTOf(help, f); - FloatMatrix E; - E.beTProductOf(F, F); - E.at(1, 1) -= 1.0; - E.at(2, 2) -= 1.0; - E.at(3, 3) -= 1.0; - E.times(0.5); - - FloatArray e; - e.beSymVectorFormOfStrain(E); - - FloatArray leftCauchyGreen; - FloatArray leftCauchyGreenDev; - double leftCauchyGreenVol; - - leftCauchyGreen.beSymVectorFormOfStrain(trialLeftCauchyGreen); - - leftCauchyGreenVol = computeDeviatoricVolumetricSplit(leftCauchyGreenDev, leftCauchyGreen); - FloatArray trialStressDev; - applyDeviatoricElasticStiffness(trialStressDev, leftCauchyGreenDev, G / 2.); - s = trialStressDev; - - //check for plastic loading - double trialS = computeStressNorm(trialStressDev); - double sigmaY = this->give('s', gp, tStep) + H * kappa; - //yieldValue = sqrt(3./2.)*trialS-sigmaY; - yieldValue = trialS - sqrt(2. / 3.) * sigmaY; - - - //store deviatoric trial stress(reused by algorithmic stiffness) - status->letTrialStressDevBe(trialStressDev); - //the return-mapping algorithm - double J = F.giveDeterminant(); - mi = leftCauchyGreenVol * G; - if ( yieldValue > 0 ) { - //dKappa =sqrt(3./2.)* yieldValue/(H + 3.*mi); - //kappa = kappa + dKappa; - //trialStressDev.times(1-sqrt(6.)*mi*dKappa/trialS); - dKappa = ( yieldValue / ( 2 * mi ) ) / ( 1 + H / ( 3 * mi ) ); - FloatArray n = trialStressDev; - n.times(2 * mi * dKappa / trialS); - ////return map - s.beDifferenceOf(trialStressDev, n); - kappa += sqrt(2. / 3.) * dKappa; - - - //update of intermediate configuration - trialLeftCauchyGreen.beMatrixForm(s); - trialLeftCauchyGreen.times(1.0 / G); - trialLeftCauchyGreen.at(1, 1) += leftCauchyGreenVol; - trialLeftCauchyGreen.at(2, 2) += leftCauchyGreenVol; - trialLeftCauchyGreen.at(2, 2) += leftCauchyGreenVol; - trialLeftCauchyGreen.times(J * J); - } - - //addition of the elastic mean stress - FloatMatrix kirchhoffStress; - kirchhoffStress.beMatrixForm(s); - kirchhoffStress.at(1, 1) += 1. / 2. * K * ( J * J - 1 ); - kirchhoffStress.at(2, 2) += 1. / 2. * K * ( J * J - 1 ); - kirchhoffStress.at(3, 3) += 1. / 2. * K * ( J * J - 1 ); - - - FloatMatrix iF, Ep(3, 3), S; - FloatArray vF, vS, ep; - - //transform Kirchhoff stress into Second Piola - Kirchhoff stress - iF.beInverseOf(F); - help.beProductOf(iF, kirchhoffStress); - S.beProductTOf(help, iF); - - this->computeGLPlasticStrain(F, Ep, trialLeftCauchyGreen, J); - - ep.beSymVectorFormOfStrain(Ep); - vS.beSymVectorForm(S); - vF.beVectorForm(F); - answer.beVectorForm(kirchhoffStress); - - status->setTrialStressVol(mi); - status->letTempLeftCauchyGreenBe(trialLeftCauchyGreen); - status->setTempCumulativePlasticStrain(kappa); - status->letTempStressVectorBe(answer); - status->letTempStrainVectorBe(e); - status->letTempPlasticStrainBe(ep); - status->letTempPVectorBe(answer); - status->letTempFVectorBe(vF); -} - + auto status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); + // subtract stress independent part + FloatArray strainR(6); + this->giveStressDependentPartOfStrainVector(strainR, gp, strain, tStep, VM_Total); -void -MisesMat :: computeGLPlasticStrain(const FloatMatrix &F, FloatMatrix &Ep, FloatMatrix b, double J) -{ - FloatMatrix I, invB, help; - I.resize(3, 3); - I.beUnitMatrix(); - invB.beInverseOf(b); - help.beTProductOf(F, invB); - Ep.beProductOf(help, F); - Ep.times( pow(J, -2. / 3.) ); - Ep.subtract(I); - Ep.times(1. / 2.); + this->performPlasticityReturn(strainR, gp, tStep); + double omega = computeDamage(gp, tStep); + auto stress = status->giveTempEffectiveStress() * ( 1 - omega ); + status->setTempDamage(omega); + status->letTempStrainVectorBe(strain); + status->letTempStressVectorBe(stress); + return stress; } void -MisesMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep) +MisesMat::performPlasticityReturn(const FloatArray &totalStrain, GaussPoint *gp, TimeStep *tStep) const { - MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); double kappa; FloatArray plStrain; FloatArray fullStress; @@ -301,34 +188,45 @@ MisesMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrai plStrain = status->givePlasticStrain(); kappa = status->giveCumulativePlasticStrain(); + double dKappa = 0.; // === radial return algorithm === if ( totalStrain.giveSize() == 1 ) { - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); - double E = lmat->give('E', gp); + double E = linearElasticMaterial.give('E', gp); /*trial stress*/ fullStress.resize(6); fullStress.at(1) = E * ( totalStrain.at(1) - plStrain.at(1) ); - double trialS = fabs(fullStress.at(1)); + double trialS = fabs(fullStress.at(1) ); /*yield function*/ - double yieldValue = trialS - (this->give('s', gp, tStep) + H * kappa); + double yieldValue = trialS - computeYieldStress(kappa, gp, tStep); // === radial return algorithm === if ( yieldValue > 0 ) { - double dKappa = yieldValue / ( H + E ); + if ( hType == 0 ) { + dKappa = yieldValue / ( computeYieldStressPrime(kappa) + E ); + } + if ( hType == 1 ) { + dKappa += yieldValue / ( computeYieldStressPrime(kappa) + E ); + yieldValue = trialS - checkYieldStress(dKappa, kappa, gp, tStep); + yieldValue -= E * dKappa; + if ( yieldValue > 1.e-10 ) { + dKappa += yieldValue / ( computeYieldStressPrime(kappa + dKappa) + E ); + } + } + kappa += dKappa; - plStrain.at(1) += dKappa * signum( fullStress.at(1) ); - plStrain.at(2) -= 0.5 * dKappa * signum( fullStress.at(1) ); - plStrain.at(3) -= 0.5 * dKappa * signum( fullStress.at(1) ); - fullStress.at(1) -= dKappa * E * signum( fullStress.at(1) ); + plStrain.at(1) += dKappa * signum(fullStress.at(1) ); + plStrain.at(2) -= 0.5 * dKappa * signum(fullStress.at(1) ); + plStrain.at(3) -= 0.5 * dKappa * signum(fullStress.at(1) ); + fullStress.at(1) -= dKappa * E * signum(fullStress.at(1) ); } } else { // elastic predictor FloatArray elStrain = totalStrain; elStrain.subtract(plStrain); - FloatArray elStrainDev; - double elStrainVol; - elStrainVol = computeDeviatoricVolumetricSplit(elStrainDev, elStrain); - FloatArray trialStressDev; - applyDeviatoricElasticStiffness(trialStressDev, elStrainDev, G); + //auto [elStrainDev, elStrainVol] = computeDeviatoricVolumetricSplit(elStrain); // c++17 + auto tmp = computeDeviatoricVolumetricSplit(elStrain); + auto elStrainDev = tmp.first; + auto elStrainVol = tmp.second; + FloatArray trialStressDev = applyDeviatoricElasticStiffness(elStrainDev, G); /**************************************************************/ double trialStressVol = 3 * K * elStrainVol; /**************************************************************/ @@ -338,14 +236,13 @@ MisesMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrai status->setTrialStressVol(trialStressVol); // check the yield condition at the trial state double trialS = computeStressNorm(trialStressDev); - double yieldValue = sqrt(3./2.) * trialS - (this->give('s', gp, tStep) + H * kappa); + double yieldValue = sqrt(3. / 2.) * trialS - ( computeYieldStress(kappa, gp, tStep) ); if ( yieldValue > 0. ) { // increment of cumulative plastic strain - double dKappa = yieldValue / ( H + 3. * G ); + double dKappa = yieldValue / ( computeYieldStressPrime(kappa) + 3. * G ); kappa += dKappa; - FloatArray dPlStrain; // the following line is equivalent to multiplication by scaling matrix P - applyDeviatoricElasticCompliance(dPlStrain, trialStressDev, 0.5); + FloatArray dPlStrain = applyDeviatoricElasticCompliance(trialStressDev, 0.5); // increment of plastic strain plStrain.add(sqrt(3. / 2.) * dKappa / trialS, dPlStrain); // scaling of deviatoric trial stress @@ -355,7 +252,7 @@ MisesMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrai // assemble the stress from the elastically computed volumetric part // and scaled deviatoric part - computeDeviatoricVolumetricSum(fullStress, trialStressDev, trialStressVol); + fullStress = computeDeviatoricVolumetricSum(trialStressDev, trialStressVol); } // store the effective stress in status @@ -365,8 +262,190 @@ MisesMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrai status->setTempCumulativePlasticStrain(kappa); } +void +MisesMat::performPlasticityReturn_PlaneStress(const FloatArrayF< 3 > &totalStrain, GaussPoint *gp, TimeStep *tStep) const +{ + double E = linearElasticMaterial.give('E', gp); + double nu = linearElasticMaterial.give('n', gp); + MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); + double kappa; + FloatArray plStrain, redPlStrain; + FloatArray fullStress; + // get the initial plastic strain and initial kappa from the status + plStrain = status->givePlasticStrain(); + StructuralMaterial::giveReducedSymVectorForm(redPlStrain, plStrain, _PlaneStress); + kappa = status->giveCumulativePlasticStrain(); + FloatMatrix Ps, Pe; + + FloatArray elStrain = totalStrain; + elStrain.subtract(redPlStrain); + FloatArray elStrainDev; + double elStrainVol; + // Elastic predictor: Compute elastic trial state + // Volumetric strain + double factor = 2. * G / ( K + 4. / 3. * G ); + elStrainVol = ( elStrain.at(1) + elStrain.at(2) ) * factor; + //Elastic trial deviatoric strain + elStrainDev = elStrain; + elStrainDev.at(1) -= elStrainVol / 3.; + elStrainDev.at(2) -= elStrainVol / 3.; + // Elastic trial stress components + FloatArray trialStressDev; + trialStressDev = elStrainDev; + trialStressDev.times(2. * G); + trialStressDev.at(3) /= 2.; + //applyDeviatoricElasticStiffness(trialStressDev, elStrainDev, G); + double trialStressVol = 3 * K * elStrainVol; + FloatArray trialStress(trialStressDev); + trialStress.at(1) += trialStressVol / 3.; + trialStress.at(2) += trialStressVol / 3.; + // Compute yield function value at trial state + double a1 = ( trialStress.at(1) + trialStress.at(2) ) * ( trialStress.at(1) + trialStress.at(2) ); + double a2 = ( trialStress.at(2) - trialStress.at(1) ) * ( trialStress.at(2) - trialStress.at(1) ); + double a3 = trialStress.at(3) * trialStress.at(3); + double sigmaY = this->computeYieldStress(kappa, gp, tStep); + double xi = 1. / 6. * a1 + 0.5 * a2 + 2. * a3; + //Yield function + double yieldValue = 0.5 * xi - 1. / 3. * sigmaY * sigmaY; + // double dGamma ; // not used + // Check for plastic admissibility + if ( yieldValue / sigmaY > yieldTol ) { + // Plastic step: Apply return mapping - use Newton-Raphson algorithm + // to solve the plane stress-projected return mapping + // equation for the plastic multiplier (Box 9.5) + double dKappa = 0; + int iter = 0; + double f = yieldValue; + double denom1 = 1.; + double denom2 = 1.; + while ( true ) { + double HiP = this->computeYieldStressPrime(kappa + dKappa * sqrt(2. * xi / 3.) ); + double dXi = -a1 * E / ( 1. - nu ) / 9. / denom1 / denom1 / denom1 - 2. * G * ( a2 + 4. * a3 ) / denom2 / denom2 / denom2; + double Hbar = 2. * sigmaY * HiP * sqrt(2. / 3.) * ( sqrt(xi) + dKappa * dXi / ( 2. * sqrt(xi) ) ); + double df = 0.5 * dXi - 1. / 3. * Hbar; + dKappa -= f / df; + // Compute new residual (yield function value) + denom1 = ( 1. + E * dKappa / 3. / ( 1. - nu ) ); + denom2 = ( 1 + 2. * G * dKappa ); + xi = a1 / 6. / denom1 / denom1 + ( 0.5 * a2 + 2. * a3 ) / denom2 / denom2; + sigmaY = this->computeYieldStress(kappa + sqrt(2. * xi / 3.) * dKappa, gp, tStep); + + f = 1. / 2. * xi - 1. / 3. * sigmaY * sigmaY; + + if ( fabs(f / sigmaY) < yieldTol ) { + break; + } + iter++; + if ( iter > 400 ) { + OOFEM_WARNING("No convergence of the stress return algorithm in MisesMat :: performPlasticityReturn_PlaneStress\n"); + break; + } + } + // update accumulated plastic strain + // dGamma = dKappa; + kappa += sqrt(2. * xi / 3.) * dKappa; + // update stress components: sigma := A sigma^trial + double As1 = 3. * ( 1. - nu ) / ( 3 * ( 1 - nu ) + E * dKappa ); + double As2 = 1. / ( 1. + 2. * G * dKappa ); + FloatMatrix A(3, 3); + A.at(1, 1) = 0.5 * ( As1 + As2 ); + A.at(2, 2) = A.at(1, 1); + A.at(1, 2) = 0.5 * ( As1 - As2 ); + A.at(2, 1) = A.at(1, 2); + A.at(3, 3) = As2; + fullStress.beProductOf(A, trialStress); + elStrainVol = ( fullStress.at(1) + fullStress.at(2) ) / 3. / K; + // compute corresponding elastic (engineering) strain components + redPlStrain.at(1) = totalStrain.at(1) - ( 2. / 3. * fullStress.at(1) - 1. / 3. * fullStress.at(2) ) / 2. / G - elStrainVol / 3; + redPlStrain.at(2) = totalStrain.at(2) - ( 2. / 3. * fullStress.at(2) - 1. / 3. * fullStress.at(1) ) / 2. / G - elStrainVol / 3; + redPlStrain.at(3) = totalStrain.at(3) - fullStress.at(3) / G; + StructuralMaterial::giveFullSymVectorForm(plStrain, redPlStrain, _PlaneStress); + // incompresibility condition + plStrain.at(3) = -( plStrain.at(1) + plStrain.at(2) ); + // store the plastic strain and cumulative plastic strain + } else { + fullStress = trialStress; + } + + + // storing into the status + status->letTempPlasticStrainBe(plStrain); + status->setTempCumulativePlasticStrain(kappa); + status->letTempEffectiveStressBe(fullStress); +} + + +double +MisesMat::checkYieldStress(double &dKappa, double kappa, GaussPoint *gp, TimeStep *tStep) const +{ + double yieldStress = 0.; + if ( hType == 1 ) { + if ( kappa + dKappa > h_eps.at(h_eps.giveSize() ) ) { + OOFEM_ERROR("kappa outside range of specified hardening law/n"); + } + + for ( int i = 1; i < h_eps.giveSize(); i++ ) { + if ( kappa + dKappa >= h_eps.at(i) && kappa + dKappa < h_eps.at(i + 1) && kappa < h_eps.at(i) ) { + yieldStress = h_function_eps.at(i); + dKappa = h_eps.at(i) - kappa; + return yieldStress; + } else if ( kappa >= h_eps.at(i) && kappa < h_eps.at(i + 1) && kappa + dKappa >= h_eps.at(i) && kappa + dKappa < h_eps.at(i + 1) ) { + yieldStress = h_function_eps.at(i) + ( kappa + dKappa - h_eps.at(i) ) / ( h_eps.at(i + 1) - h_eps.at(i) ) * ( h_function_eps.at(i + 1) - h_function_eps.at(i) ); + return yieldStress; + } + } + } else { + OOFEM_ERROR("MisesMat: Should not check yield stress for htype = 0\n"); + } +} + +double +MisesMat::computeYieldStress(double kappa, GaussPoint *gp, TimeStep *tStep) const +{ + double yieldStress = 0.; + if ( hType == 0 ) { + return this->give('s', gp, tStep) + this->H * kappa; // + ( this->sigInf - this->sig0 ) * (1. - exp(-expD*kappa)); + } else { + if ( kappa > h_eps.at(h_eps.giveSize() ) ) { + OOFEM_ERROR("kappa outside range of specified hardening law/n"); + } + + for ( int i = 1; i < h_eps.giveSize(); i++ ) { + if ( kappa >= h_eps.at(i) && kappa < h_eps.at(i + 1) ) { + yieldStress = h_function_eps.at(i) + ( kappa - h_eps.at(i) ) / ( h_eps.at(i + 1) - h_eps.at(i) ) * ( h_function_eps.at(i + 1) - h_function_eps.at(i) ); + return yieldStress; + } + } + } +} + + +double +MisesMat::computeYieldStressPrime(double kappa) const +{ + double yieldStressPrime; + if ( hType == 0 ) { + yieldStressPrime = this->H; + return yieldStressPrime; + } else { + if ( kappa > h_eps.at(h_eps.giveSize() ) ) { + OOFEM_ERROR("kappa outside range of specified hardening law/n"); + } + + + for ( int i = 1; i < h_eps.giveSize(); i++ ) { + if ( kappa >= h_eps.at(i) && kappa < h_eps.at(i + 1) ) { + yieldStressPrime = ( h_function_eps.at(i + 1) - h_function_eps.at(i) ) / ( h_eps.at(i + 1) - h_eps.at(i) ); + return yieldStressPrime; + } + } + } +} + + + double -MisesMat :: computeDamageParam(double tempKappa) +MisesMat::computeDamageParam(double tempKappa) const { if ( tempKappa > 0. ) { return omega_crit * ( 1.0 - exp(-a * tempKappa) ); @@ -376,7 +455,7 @@ MisesMat :: computeDamageParam(double tempKappa) } double -MisesMat :: computeDamageParamPrime(double tempKappa) +MisesMat::computeDamageParamPrime(double tempKappa) const { if ( tempKappa >= 0. ) { return omega_crit * a * exp(-a * tempKappa); @@ -386,14 +465,12 @@ MisesMat :: computeDamageParamPrime(double tempKappa) } - double -MisesMat :: computeDamage(GaussPoint *gp, TimeStep *tStep) +MisesMat::computeDamage(GaussPoint *gp, TimeStep *tStep) const { - double tempKappa, dam; - MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); - dam = status->giveDamage(); - computeCumPlastStrain(tempKappa, gp, tStep); + auto status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); + double dam = status->giveDamage(); + double tempKappa = computeCumPlastStrain(gp, tStep); double tempDam = computeDamageParam(tempKappa); if ( dam > tempDam ) { tempDam = dam; @@ -403,293 +480,168 @@ MisesMat :: computeDamage(GaussPoint *gp, TimeStep *tStep) } -void MisesMat :: computeCumPlastStrain(double &tempKappa, GaussPoint *gp, TimeStep *tStep) +double MisesMat::computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const { - MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); - tempKappa = status->giveTempCumulativePlasticStrain(); + auto status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); + return status->giveTempCumulativePlasticStrain(); } -void -MisesMat :: give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - ///@todo Directly compute dPdF instead. - FloatMatrix dSdE; - this->give3dLSMaterialStiffnessMatrix(dSdE, mode, gp, tStep); - this->give_dPdF_from(dSdE, answer, gp); -} // returns the consistent (algorithmic) tangent stiffness matrix -void -MisesMat :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF< 6, 6 > +MisesMat::give3dMaterialStiffnessMatrix(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const { // start from the elastic stiffness - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + auto d = this->linearElasticMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep); if ( mode != TangentStiffness ) { - return; + return d; } - MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); double kappa = status->giveCumulativePlasticStrain(); double tempKappa = status->giveTempCumulativePlasticStrain(); // increment of cumulative plastic strain as an indicator of plastic loading double dKappa = tempKappa - kappa; if ( dKappa <= 0.0 ) { // elastic loading - elastic stiffness plays the role of tangent stiffness - return; + return d; } // === plastic loading === // yield stress at the beginning of the step - double sigmaY = this->give('s', gp, tStep) + H * kappa; + double sigmaY = computeYieldStress(kappa, gp, tStep); // trial deviatoric stress and its norm - const FloatArray &trialStressDev = status->giveTrialStressDev(); + const FloatArrayF< 6 >trialStressDev = status->giveTrialStressDev(); //double trialStressVol = status->giveTrialStressVol(); double trialS = computeStressNorm(trialStressDev); // one correction term - FloatMatrix stiffnessCorrection; - stiffnessCorrection.beDyadicProductOf(trialStressDev, trialStressDev); double factor = -2. * sqrt(6.) * G * G / trialS; - double factor1 = factor * sigmaY / ( ( H + 3. * G ) * trialS * trialS ); - answer.add(factor1, stiffnessCorrection); + double factor1 = factor * sigmaY / ( ( computeYieldStressPrime(kappa) + 3. * G ) * trialS * trialS ); + d += factor1 * dyad(trialStressDev, trialStressDev); // another correction term - stiffnessCorrection.bePinvID(); double factor2 = factor * dKappa; - answer.add(factor2, stiffnessCorrection); + d += factor2 * I_dev6; //influence of damage // double omega = computeDamageParam(tempKappa); double omega = status->giveTempDamage(); - answer.times(1. - omega); - const FloatArray &effStress = status->giveTempEffectiveStress(); + d *= 1. - omega; + const FloatArrayF< 6 >effStress = status->giveTempEffectiveStress(); double omegaPrime = computeDamageParamPrime(tempKappa); - double scalar = -omegaPrime *sqrt(6.) * G / ( 3. * G + H ) / trialS; - stiffnessCorrection.beDyadicProductOf(effStress, trialStressDev); - stiffnessCorrection.times(scalar); - answer.add(stiffnessCorrection); + double scalar = -omegaPrime *sqrt(6.) * G / ( 3. * G + computeYieldStressPrime(kappa) ) / trialS; + d += scalar * dyad(effStress, trialStressDev); + return d; } -void -MisesMat :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -{ - this->giveLinearElasticMaterial()->give1dStressStiffMtrx(answer, mode, gp, tStep); - MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); - double kappa = status->giveCumulativePlasticStrain(); - // increment of cumulative plastic strain as an indicator of plastic loading - double tempKappa = status->giveTempCumulativePlasticStrain(); - double omega = status->giveTempDamage(); - double E = answer.at(1, 1); - if ( mode != TangentStiffness ) { - return; - } - - if ( tempKappa <= kappa ) { // elastic loading - elastic stiffness plays the role of tangent stiffness - answer.times(1 - omega); - return; - } - - - // === plastic loading === - const FloatArray &stressVector = status->giveTempEffectiveStress(); - double stress = stressVector.at(1); - answer.resize(1, 1); - answer.at(1, 1) = ( 1 - omega ) * E * H / ( E + H ) - computeDamageParamPrime(tempKappa) * E / ( E + H ) * stress * signum(stress); -} - -void -MisesMat :: give3dLSMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 3, 3 > +MisesMat::givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const { - MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); // start from the elastic stiffness - - FloatMatrix I(6, 6); - I.at(1, 1) = I.at(2, 2) = I.at(3, 3) = 1; - I.at(4, 4) = I.at(5, 5) = I.at(6, 6) = 0.5; - FloatArray delta(6); - delta.at(1) = delta.at(2) = delta.at(3) = 1; - - FloatMatrix F; - F.beMatrixForm( status->giveTempFVector() ); - double J = F.giveDeterminant(); - - const FloatArray &trialStressDev = status->giveTrialStressDev(); - double trialStressVol = status->giveTrialStressVol(); - double trialS = computeStressNorm(trialStressDev); - FloatArray n = trialStressDev; - if ( trialS == 0 ) { - n.resize(6); - } else { - n.times(1 / trialS); + auto d = linearElasticMaterial.givePlaneStressStiffMtrx(mmode, gp, tStep); + if ( mmode != TangentStiffness ) { + double omega = status->giveTempDamage(); + return d * ( 1. - omega ); } - - FloatMatrix C; - FloatMatrix help; - help.beDyadicProductOf(delta, delta); - C = help; - help.times(-1. / 3.); - FloatMatrix C1 = I; - C1.add(help); - C1.times(2 * trialStressVol); - - FloatMatrix n1, n2; - n1.beDyadicProductOf(n, delta); - n2.beDyadicProductOf(delta, n); - help = n1; - help.add(n2); - C1.add(-2. / 3. * trialS, help); - C.times(K * J * J); - - C.add(-K * ( J * J - 1 ), I); - C.add(C1); - ////////////////////////////////////////////////////////////////////////////////////////////////////////// - - FloatMatrix invF; - FloatMatrix T(6, 6); - - invF.beInverseOf(F); - ////////////////////////////////////////////////// - //first row of pull back transformation matrix - T.at(1, 1) = invF.at(1, 1) * invF.at(1, 1); - T.at(1, 2) = invF.at(1, 2) * invF.at(1, 2); - T.at(1, 3) = invF.at(1, 3) * invF.at(1, 3); - T.at(1, 4) = 2. * invF.at(1, 2) * invF.at(1, 3); - T.at(1, 5) = 2. * invF.at(1, 1) * invF.at(1, 3); - T.at(1, 6) = 2. * invF.at(1, 1) * invF.at(1, 2); - //second row of pull back transformation matrix - T.at(2, 1) = invF.at(2, 1) * invF.at(2, 1); - T.at(2, 2) = invF.at(2, 2) * invF.at(2, 2); - T.at(2, 3) = invF.at(2, 3) * invF.at(2, 3); - T.at(2, 4) = 2. * invF.at(2, 2) * invF.at(2, 3); - T.at(2, 5) = 2. * invF.at(2, 1) * invF.at(2, 3); - T.at(2, 6) = 2. * invF.at(2, 1) * invF.at(2, 2); - //third row of pull back transformation matrix - T.at(3, 1) = invF.at(3, 1) * invF.at(3, 1); - T.at(3, 2) = invF.at(3, 2) * invF.at(3, 2); - T.at(3, 3) = invF.at(3, 3) * invF.at(3, 3); - T.at(3, 4) = 2. * invF.at(3, 2) * invF.at(3, 3); - T.at(3, 5) = 2. * invF.at(3, 1) * invF.at(3, 3); - T.at(3, 6) = 2. * invF.at(3, 1) * invF.at(3, 2); - //fourth row of pull back transformation matrix - T.at(4, 1) = invF.at(2, 1) * invF.at(3, 1); - T.at(4, 2) = invF.at(2, 2) * invF.at(3, 2); - T.at(4, 3) = invF.at(2, 3) * invF.at(3, 3); - T.at(4, 4) = ( invF.at(2, 2) * invF.at(3, 3) + invF.at(2, 3) * invF.at(3, 2) ); - T.at(4, 5) = ( invF.at(2, 1) * invF.at(3, 3) + invF.at(2, 3) * invF.at(3, 1) ); - T.at(4, 6) = ( invF.at(2, 1) * invF.at(3, 2) + invF.at(2, 2) * invF.at(3, 1) ); - //fifth row of pull back transformation matrix - T.at(5, 1) = invF.at(1, 1) * invF.at(3, 1); - T.at(5, 2) = invF.at(1, 2) * invF.at(3, 2); - T.at(5, 3) = invF.at(1, 3) * invF.at(3, 3); - T.at(5, 4) = ( invF.at(1, 2) * invF.at(3, 3) + invF.at(1, 3) * invF.at(3, 2) ); - T.at(5, 5) = ( invF.at(1, 1) * invF.at(3, 3) + invF.at(1, 3) * invF.at(3, 1) ); - T.at(5, 6) = ( invF.at(1, 1) * invF.at(3, 2) + invF.at(1, 2) * invF.at(3, 1) ); - //sixth row of pull back transformation matrix - T.at(6, 1) = invF.at(1, 1) * invF.at(2, 1); - T.at(6, 2) = invF.at(1, 2) * invF.at(2, 2); - T.at(6, 3) = invF.at(1, 3) * invF.at(2, 3); - T.at(6, 4) = ( invF.at(1, 2) * invF.at(2, 3) + invF.at(1, 3) * invF.at(2, 2) ); - T.at(6, 5) = ( invF.at(1, 1) * invF.at(2, 3) + invF.at(1, 3) * invF.at(2, 1) ); - T.at(6, 6) = ( invF.at(1, 1) * invF.at(2, 2) + invF.at(1, 2) * invF.at(2, 1) ); - /////////////////////////////////////////// - - if ( mode != TangentStiffness ) { - help.beProductTOf(C, T); - answer.beProductOf(T, help); - return; - } - - double kappa = status->giveCumulativePlasticStrain(); + double tempKappa = status->giveTempCumulativePlasticStrain(); // increment of cumulative plastic strain as an indicator of plastic loading - double dKappa = sqrt(3. / 2.) * ( status->giveTempCumulativePlasticStrain() - kappa ); - //double dKappa = ( status->giveTempCumulativePlasticStrain() - kappa); + double dKappa = tempKappa - kappa; if ( dKappa <= 0.0 ) { // elastic loading - elastic stiffness plays the role of tangent stiffness - help.beProductTOf(C, T); - answer.beProductOf(T, help); - return; + return d; } - - // === plastic loading === - //dKappa = dKappa*sqrt(3./2.); - // trial deviatoric stress and its norm + // Compute elastoplastic consistent tangent (Box 9.6) + FloatArray stress, fullStress; + fullStress = status->giveTempStressVector(); + StructuralMaterial::giveReducedSymVectorForm(stress, fullStress, _PlaneStress); + // Compute xi + double xi = 2. / 3. * ( stress.at(1) * stress.at(1) + stress.at(2) * stress.at(2) - stress.at(1) * stress.at(2) ) + 2. * stress.at(3) * stress.at(3); + // compute dGamma + double dGamma = dKappa * sqrt(3. / 2. / xi); + // Hardening slope + double HiP = this->computeYieldStressPrime(tempKappa); + // Matrix E components + + double E = linearElasticMaterial.give('E', gp); + double nu = linearElasticMaterial.give('n', gp); + double Es1 = 3. * E / ( 3. * ( 1. - nu ) + E * dGamma ); + double Es2 = 2. * G / ( 1. + 2. * G * dGamma ); + double Es3 = Es2 / 2.; + // Components of the matrix product EP + double EPs1 = 1. / 3. * Es1; + double EPs2 = Es2; + double EPs3 = EPs2; + FloatMatrix EP(3, 3); + EP.at(1, 1) = 0.5 * ( EPs1 + EPs2 ); + EP.at(2, 2) = EP.at(1, 1); + EP.at(1, 2) = 0.5 * ( EPs1 - EPs2 ); + EP.at(2, 1) = EP.at(1, 2); + EP.at(3, 3) = EPs3; + // Vector n + FloatArray n(3); + n.beProductOf(EP, stress); + // Scalar alpha + double denom1 = stress.at(1) * ( 2. / 3. * n.at(1) - 1. / 3. * n.at(2) ) + stress.at(2) * ( 2. / 3. * n.at(2) - 1. / 3. * n.at(1) ) + 2. * stress.at(3) * n.at(3); + double denom2 = 2. * xi * HiP / ( 3. - 2. * HiP * dGamma ); + double alpha = 1. / ( denom1 + denom2 ); + FloatMatrix correction; + correction.beDyadicProductOf(n, n); + correction.times(alpha); + + FloatMatrixF< 3, 3 >answer; + answer.at(1, 1) = 0.5 * ( Es1 + Es2 ); + answer.at(2, 2) = answer.at(1, 1); + answer.at(1, 2) = 0.5 * ( Es1 - Es2 ); + answer.at(2, 1) = answer.at(1, 2); + answer.at(3, 3) = Es3; + answer -= FloatMatrixF< 3, 3 >(correction); + //@todo: add damage part of the stiffness + return answer; +} - double beta1, beta3, beta4; - if ( trialS == 0 ) { - beta1 = 0; - } else { - beta1 = 2 * trialStressVol * dKappa / trialS; +FloatMatrixF< 1, 1 > +MisesMat::give1dStressStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const +{ + MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); + double kappa = status->giveCumulativePlasticStrain(); + // increment of cumulative plastic strain as an indicator of plastic loading + double tempKappa = status->giveTempCumulativePlasticStrain(); + double omega = status->giveTempDamage(); + auto elastic = this->linearElasticMaterial.give1dStressStiffMtrx(mode, gp, tStep); + double E = elastic.at(1, 1); + if ( mode != TangentStiffness ) { + return elastic; } - if ( trialStressVol == 0 ) { - beta3 = beta1; - beta4 = 0; - } else { - double beta0 = 1 + H / 3 / trialStressVol; - double beta2 = ( 1 - 1 / beta0 ) * 2. / 3. * trialS * dKappa / trialStressVol; - beta3 = 1 / beta0 - beta1 + beta2; - beta4 = ( 1 / beta0 - beta1 ) * trialS / trialStressVol; + if ( tempKappa <= kappa ) { // elastic loading - elastic stiffness plays the role of tangent stiffness + return elastic * ( 1 - omega ); } - FloatMatrix N; - N.beDyadicProductOf(n, n); - N.times(-2 * trialStressVol * beta3); - - C1.times(-beta1); - FloatMatrix mN(3, 3); - mN.at(1, 1) = n.at(1); - mN.at(1, 2) = n.at(6); - mN.at(1, 3) = n.at(5); - mN.at(2, 1) = n.at(6); - mN.at(2, 2) = n.at(2); - mN.at(2, 3) = n.at(4); - mN.at(3, 1) = n.at(5); - mN.at(3, 2) = n.at(4); - mN.at(3, 3) = n.at(3); - FloatMatrix mN2; - mN2.beProductOf(mN, mN); - - double volN2 = 1. / 3. * ( mN2.at(1, 1) + mN2.at(2, 2) + mN2.at(3, 3) ); - FloatArray devN2(6); - devN2.at(1) = mN2.at(1, 1) - volN2; - devN2.at(2) = mN2.at(2, 2) - volN2; - - devN2.at(3) = mN2.at(3, 3) - volN2; - devN2.at(4) = mN2.at(2, 3); - devN2.at(5) = mN2.at(1, 3); - devN2.at(6) = mN2.at(1, 2); - FloatMatrix nonSymPart; - nonSymPart.beDyadicProductOf(n, devN2); - //symP.beTranspositionOf(nonSymPart); - //symP.add(nonSymPart); - //symP.times(1./2.); - nonSymPart.times(-2 * trialStressVol * beta4); - - C.add(C1); - C.add(N); - C.add(nonSymPart); - help.beProductTOf(C, T); - answer.beProductOf(T, help); + // === plastic loading === + const FloatArray &stressVector = status->giveTempEffectiveStress(); + double stress = stressVector.at(1); + return { + ( 1 - omega ) * E * computeYieldStressPrime(kappa) / ( E + computeYieldStressPrime(kappa) ) - computeDamageParamPrime(tempKappa) * E / ( E + computeYieldStressPrime(kappa) ) * stress * signum(stress) + }; } - #ifdef __OOFEG #endif int -MisesMat :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +MisesMat::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { MisesMatStatus *status = static_cast< MisesMatStatus * >( this->giveStatus(gp) ); if ( type == IST_PlasticStrainTensor ) { @@ -708,33 +660,26 @@ MisesMat :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType ty answer.at(1) = this->give('s', gp, tStep); return 1; } else { - return StructuralMaterial :: giveIPValue(answer, gp, type, tStep); + return StructuralMaterial::giveIPValue(answer, gp, type, tStep); } } //============================================================================= -MisesMatStatus :: MisesMatStatus(int n, Domain *d, GaussPoint *g) : - StructuralMaterialStatus(n, d, g), plasticStrain(6), tempPlasticStrain(), trialStressD() +MisesMatStatus::MisesMatStatus(GaussPoint *g) : + StructuralMaterialStatus(g), plasticStrain(6), tempPlasticStrain(), trialStressD() { stressVector.resize(6); strainVector.resize(6); - - damage = tempDamage = 0.; - kappa = tempKappa = 0.; effStress.resize(6); tempEffStress.resize(6); - leftCauchyGreen.resize(3, 3); - leftCauchyGreen.at(1, 1) = leftCauchyGreen.at(2, 2) = leftCauchyGreen.at(3, 3) = 1; } -MisesMatStatus :: ~MisesMatStatus() -{ } void -MisesMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) +MisesMatStatus::printOutputAt(FILE *file, TimeStep *tStep) const { - StructuralMaterialStatus :: printOutputAt(file, tStep); + StructuralMaterialStatus::printOutputAt(file, tStep); fprintf(file, " plastic "); for ( auto &val : this->plasticStrain ) { @@ -743,101 +688,56 @@ MisesMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) fprintf(file, "\n"); fprintf(file, "status { "); - /* - * // this would not be correct, since the status is already updated and kappa is now the "final" value - * if ( tempKappa > kappa ) { - * fprintf(file, " Yielding, "); - * } else { - * fprintf(file, " Unloading, "); - * } - */ - - /*********************************************************************************/ - + // print damage fprintf(file, "damage %.4e", tempDamage); - - /********************************************************************************/ - /* - * // print the plastic strain - * n = plasticStrain.giveSize(); - * fprintf(file, " plastic_strains "); - * for ( i = 1; i <= n; i++ ) { - * fprintf( file, " %.4e", plasticStrain.at(i) ); - * } - */ // print the cumulative plastic strain fprintf(file, ", kappa "); fprintf(file, " %.4e", kappa); fprintf(file, "}\n"); - /* - * //print Left Cauchy - Green deformation tensor - * fprintf(file," left Cauchy Green"); - * fprintf( file, " %.4e",tempLeftCauchyGreen.at(1,1) ); - * fprintf( file, " %.4e",tempLeftCauchyGreen.at(2,2) ); - * fprintf( file, " %.4e",tempLeftCauchyGreen.at(3,3) ); - * fprintf( file, " %.4e",tempLeftCauchyGreen.at(2,3) ); - * fprintf( file, " %.4e",tempLeftCauchyGreen.at(1,3) ); - * fprintf( file, " %.4e",tempLeftCauchyGreen.at(1,2) ); - * - * //print deformation gradient - * fprintf(file," Deformation Gradient"); - * fprintf( file, " %.4e",tempDefGrad.at(1,1) ); - * fprintf( file, " %.4e",tempDefGrad.at(1,2) ); - * fprintf( file, " %.4e",tempDefGrad.at(1,3) ); - * fprintf( file, " %.4e",tempDefGrad.at(2,1) ); - * fprintf( file, " %.4e",tempDefGrad.at(2,2) ); - * fprintf( file, " %.4e",tempDefGrad.at(2,3) ); - * fprintf( file, " %.4e",tempDefGrad.at(3,1) ); - * fprintf( file, " %.4e",tempDefGrad.at(3,2) ); - * fprintf( file, " %.4e",tempDefGrad.at(3,3) ); - */ fprintf(file, "}\n"); } // initializes temporary variables based on their values at the previous equlibrium state -void MisesMatStatus :: initTempStatus() +void MisesMatStatus::initTempStatus() { - StructuralMaterialStatus :: initTempStatus(); + StructuralMaterialStatus::initTempStatus(); tempDamage = damage; tempPlasticStrain = plasticStrain; tempKappa = kappa; trialStressD.clear(); // to indicate that it is not defined yet - tempLeftCauchyGreen = leftCauchyGreen; } // updates internal variables when equilibrium is reached void -MisesMatStatus :: updateYourself(TimeStep *tStep) +MisesMatStatus::updateYourself(TimeStep *tStep) { - StructuralMaterialStatus :: updateYourself(tStep); + StructuralMaterialStatus::updateYourself(tStep); plasticStrain = tempPlasticStrain; kappa = tempKappa; damage = tempDamage; trialStressD.clear(); // to indicate that it is not defined any more - leftCauchyGreen = tempLeftCauchyGreen; } double -MisesMat :: give(int aProperty, GaussPoint *gp, TimeStep *tStep) -// -// Returns the value of the property aProperty. -// +MisesMat::give(int aProperty, GaussPoint *gp, TimeStep *tStep) const { if ( aProperty == 's' ) { - return sig0.eval( { { "te", giveTemperature(gp, tStep) }, { "t", tStep->giveIntrinsicTime() } }, this->giveDomain(), gp, giveTemperature(gp, tStep) ); + ///FIXME: const cast workaround, until all methods have been properly marked const properly: + + return sig0.eval({ { "te", giveTemperature(gp, tStep) }, { "t", tStep->giveIntrinsicTime() } }, this->giveDomain(), gp, giveTemperature(gp, tStep) ); } - return this->Material :: give(aProperty, gp); + return Material::give(aProperty, gp); } -double MisesMat :: giveTemperature(GaussPoint *gp, TimeStep *tStep) +double MisesMat::giveTemperature(GaussPoint *gp, TimeStep *tStep) const { FieldManager *fm = this->domain->giveEngngModel()->giveContext()->giveFieldManager(); FieldPtr tf; @@ -845,7 +745,7 @@ double MisesMat :: giveTemperature(GaussPoint *gp, TimeStep *tStep) if ( ( tf = fm->giveField(FT_Temperature) ) ) { // temperature field registered FloatArray gcoords, answer; - static_cast< StructuralElement * >( gp->giveElement() )->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); + static_cast< StructuralElement * >( gp->giveElement() )->computeGlobalCoordinates(gcoords, gp->giveNaturalCoordinates() ); if ( ( err = tf->evaluateAt(answer, gcoords, VM_Total, tStep) ) ) { OOFEM_ERROR("tf->evaluateAt failed, element %d, error code %d", gp->giveElement()->giveNumber(), err); } @@ -855,68 +755,42 @@ double MisesMat :: giveTemperature(GaussPoint *gp, TimeStep *tStep) } -// saves full information stored in this status -// temporary variables are NOT stored -contextIOResultType -MisesMatStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +MisesMatStatus::saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus::saveContext(stream, mode); - // write raw data - - // write plastic strain (vector) + contextIOResultType iores; if ( ( iores = plasticStrain.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - // write cumulative plastic strain (scalar) if ( !stream.write(kappa) ) { THROW_CIOERR(CIO_IOERR); } - // write damage (scalar) if ( !stream.write(damage) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } - -contextIOResultType -MisesMatStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +MisesMatStatus::restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralMaterialStatus::restoreContext(stream, mode); - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read plastic strain (vector) + contextIOResultType iores; if ( ( iores = plasticStrain.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - // read cumulative plastic strain (scalar) if ( !stream.read(kappa) ) { THROW_CIOERR(CIO_IOERR); } - // read damage (scalar) if ( !stream.read(damage) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; // return succes } } // end namespace oofem diff --git a/src/sm/Materials/misesmat.h b/src/sm/Materials/misesmat.h index 59d6c3e00..905639c3c 100644 --- a/src/sm/Materials/misesmat.h +++ b/src/sm/Materials/misesmat.h @@ -35,9 +35,9 @@ #ifndef misesmat_h #define misesmat_h -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" -#include "Materials/linearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "dictionary.h" #include "floatarray.h" #include "floatmatrix.h" @@ -48,8 +48,12 @@ #define _IFT_MisesMat_Name "misesmat" #define _IFT_MisesMat_sig0 "sig0" #define _IFT_MisesMat_h "h" +#define _IFT_MisesMat_htype "htype" +#define _IFT_MisesMat_h_eps "h_eps" +#define _IFT_MisesMat_h_function_eps "h(eps)" #define _IFT_MisesMat_omega_crit "omega_crit" #define _IFT_MisesMat_a "a" +#define _IFT_MisesMat_yieldTol "yieldtol" //@} namespace oofem { @@ -65,82 +69,86 @@ class Domain; * by implementation - here we use the radial return, which * is the most efficient algorithm for this specific model. * Also, an extension to large strain will be available. - * - * The model also exemplifies how to implement non-3d material modes, in this case 1D, + * + * The model also exemplifies how to implement non-3d material modes, in this case 1D, * by overloading the default implementations that iterates over the 3D method. */ class MisesMat : public StructuralMaterial { protected: /// Reference to the basic elastic material. - LinearElasticMaterial *linearElasticMaterial; + IsotropicLinearElasticMaterial linearElasticMaterial; /// Elastic shear modulus. - double G; + double G = 0.; /// Elastic bulk modulus. - double K; + double K = 0.; /// Hardening modulus. - double H; + double H = 0.; /// Initial (uniaxial) yield stress. ScalarFunction sig0; - double omega_crit; - double a; + /// type of hardening function + int hType; + + /// user-defined hardening (yield stress - kappa) + FloatArray h_eps, h_function_eps; + + /// critical(maximal) damage. + double omega_crit = 0.; + /// exponent in damage function. + double a = 0.; + + /// tolerance for the yield function in RRM algorithm. + double yieldTol = 0.; public: - MisesMat(int n, Domain * d); - virtual ~MisesMat(); + MisesMat(int n, Domain *d); + + void performPlasticityReturn(const FloatArray &totalStrain, GaussPoint *gp, TimeStep *tStep) const; + void performPlasticityReturn_PlaneStress(const FloatArrayF< 3 > &totalStrain, GaussPoint *gp, TimeStep *tStep) const; + + double checkYieldStress(double &dKappa, double kappa, GaussPoint *gp, TimeStep *tStep) const; + double computeYieldStress(double kappa, GaussPoint *gp, TimeStep *tStep) const; + double computeYieldStressPrime(double kappa) const; + + double computeDamage(GaussPoint *gp, TimeStep *tStep) const; + double computeDamageParam(double tempKappa) const; + double computeDamageParamPrime(double tempKappa) const; + virtual double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const; - void performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep); - double computeDamage(GaussPoint *gp, TimeStep *tStep); - double computeDamageParam(double tempKappa); - double computeDamageParamPrime(double tempKappa); - virtual void computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *tStep); + void initializeFrom(InputRecord &ir) override; - virtual IRResultType initializeFrom(InputRecord *ir); + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return false; } - virtual int hasNonLinearBehaviour() { return 1; } - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return false; } + const char *giveInputRecordName() const override { return _IFT_MisesMat_Name; } + const char *giveClassName() const override { return "MisesMat"; } - virtual const char *giveInputRecordName() const { return _IFT_MisesMat_Name; } - virtual const char *giveClassName() const { return "MisesMat"; } + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - /// Returns a reference to the basic elastic material. - LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } + FloatMatrixF< 6, 6 >give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + FloatMatrixF< 3, 3 >givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF< 1, 1 >give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatArrayF< 6 >giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); + FloatArrayF< 3 >giveRealStressVector_PlaneStress(const FloatArrayF< 3 > &totalStrain, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &vF, TimeStep *tStep); + FloatArrayF< 1 >giveRealStressVector_1d(const FloatArrayF< 1 > &reducedE, GaussPoint *gp, TimeStep *tStep) const override; - virtual double give(int aProperty, GaussPoint *gp, TimeStep *tStep); - double giveTemperature(GaussPoint *gp, TimeStep *tStep); + double give(int aProperty, GaussPoint *gp, TimeStep *tStep) const; + double giveTemperature(GaussPoint *gp, TimeStep *tStep) const; protected: void computeGLPlasticStrain(const FloatMatrix &F, FloatMatrix &Ep, FloatMatrix b, double J); - virtual void give3dLSMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; }; //============================================================================= @@ -158,50 +166,42 @@ class MisesMatStatus : public StructuralMaterialStatus /// Deviatoric trial stress - needed for tangent stiffness. FloatArray trialStressD; - /**************************************************/ - double trialStressV; - /**************************************************/ + /// volumetric trial stress - needed for tangent stiffness. + double trialStressV = 0.; FloatArray effStress; FloatArray tempEffStress; /// Cumulative plastic strain (initial). - double kappa; + double kappa = 0.; /// Cumulative plastic strain (final). - double tempKappa; + double tempKappa = 0.; - /************************/ - double tempDamage, damage; - /******************************/ + /// damage variable (initial). + double damage = 0.; + + /// damage variable (final). + double tempDamage = 0.; - /// Left Cauchy-Green deformation gradient (initial). - FloatMatrix leftCauchyGreen; - /// Left Cauchy-Green deformation gradient (final). - FloatMatrix tempLeftCauchyGreen; public: - MisesMatStatus(int n, Domain * d, GaussPoint * g); - virtual ~MisesMatStatus(); + MisesMatStatus(GaussPoint *g); - const FloatArray &givePlasticStrain() { return plasticStrain; } + const FloatArray &givePlasticStrain() const { return plasticStrain; } - const FloatArray &giveTrialStressDev() { return trialStressD; } + const FloatArray &giveTrialStressDev() const { return trialStressD; } - /*******************************************/ - double giveTrialStressVol() { return trialStressV; } - /*******************************************/ - double giveDamage() { return damage; } - double giveTempDamage() { return tempDamage; } + double giveTrialStressVol() const { return trialStressV; } - double giveCumulativePlasticStrain() { return kappa; } - double giveTempCumulativePlasticStrain() { return tempKappa; } + double giveDamage() const { return damage; } + double giveTempDamage() const { return tempDamage; } - const FloatMatrix & giveTempLeftCauchyGreen() { return tempLeftCauchyGreen; } - const FloatMatrix & giveLeftCauchyGreen() { return leftCauchyGreen; } + double giveCumulativePlasticStrain() const { return kappa; } + double giveTempCumulativePlasticStrain() const { return tempKappa; } - const FloatArray & giveTempEffectiveStress() { return tempEffStress; } - const FloatArray & giveEffectiveStress() { return effStress; } + const FloatArray &giveTempEffectiveStress() const { return tempEffStress; } + const FloatArray &giveEffectiveStress() const { return effStress; } void letTempPlasticStrainBe(const FloatArray &values) { tempPlasticStrain = values; } const FloatArray &getTempPlasticStrain() const { return tempPlasticStrain; } @@ -215,26 +215,25 @@ class MisesMatStatus : public StructuralMaterialStatus void setTrialStressVol(double value) { trialStressV = value; } + + + void setTempCumulativePlasticStrain(double value) { tempKappa = value; } - /****************************************/ - void setTempDamage(double value) { tempDamage = value; } - /************************************************/ - void letTempLeftCauchyGreenBe(const FloatMatrix &values) { tempLeftCauchyGreen = values; } - void letLeftCauchyGreenBe(const FloatMatrix &values) { leftCauchyGreen = values; } + void setTempDamage(double value) { tempDamage = value; } const FloatArray &givePlasDef() { return plasticStrain; } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); + void initTempStatus() override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual const char *giveClassName() const { return "MisesMatStatus"; } + const char *giveClassName() const override { return "MisesMatStatus"; } }; } // end namespace oofem #endif // misesmat_h diff --git a/src/sm/Materials/misesmatgrad.C b/src/sm/Materials/misesmatgrad.C index be71061d3..8c2ad0c53 100644 --- a/src/sm/Materials/misesmatgrad.C +++ b/src/sm/Materials/misesmatgrad.C @@ -49,17 +49,12 @@ REGISTER_Material(MisesMatGrad); //gradient regularization of Mises plasticity coupled with isotropic damage ///////////////////////////////////////////////////////////////// -MisesMatGrad :: MisesMatGrad(int n, Domain *d) : MisesMat(n, d), GradDpMaterialExtensionInterface(d) -{ - L = 0.; -} - -MisesMatGrad :: ~MisesMatGrad() -{ } +MisesMatGrad :: MisesMatGrad(int n, Domain *d) : MisesMat(n, d), GradientDamageMaterialExtensionInterface(d) +{} -int -MisesMatGrad :: hasMaterialModeCapability(MaterialMode mode) +bool +MisesMatGrad :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _1dMat || mode == _PlaneStrain || mode == _3dMat; } @@ -77,26 +72,26 @@ MisesMatGrad :: giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, void -MisesMatGrad :: givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +MisesMatGrad :: giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { case _1dMat: - give1dStressStiffMtrx(answer, mode, gp, tStep); + answer = give1dStressStiffMtrx(mode, gp, tStep); break; case _PlaneStrain: - givePlaneStrainStiffMtrx(answer, mode, gp, tStep); + answer = givePlaneStrainStiffMtrx(mode, gp, tStep); break; case _3dMat: - give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + answer = give3dMaterialStiffnessMatrix(mode, gp, tStep); break; default: - OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mMode) ); + OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mMode) ); } } void -MisesMatGrad :: givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +MisesMatGrad :: giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { @@ -110,12 +105,12 @@ MisesMatGrad :: givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, G give3dKappaMatrix(answer, mode, gp, tStep); break; default: - OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mMode) ); + OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mMode) ); } } void -MisesMatGrad :: givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +MisesMatGrad :: giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { @@ -129,12 +124,12 @@ MisesMatGrad :: givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, G give3dGprime(answer, mode, gp, tStep); break; default: - OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mMode) ); + OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mMode) ); } } void -MisesMatGrad :: givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +MisesMatGrad :: giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { @@ -148,27 +143,18 @@ MisesMatGrad :: givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, G giveInternalLength(answer, mode, gp, tStep); break; default: - OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mMode) ); + OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mMode) ); } } -void -MisesMatGrad :: givePDGradMatrix_LD(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - MaterialMode mMode = gp->giveMaterialMode(); - OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mMode) ); -} -void -MisesMatGrad :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<1,1> +MisesMatGrad :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - answer.resize(1, 1); - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); - double E = lmat->give('E', gp); - answer.at(1, 1) = E; + double E = this->linearElasticMaterial.give('E', gp); if ( mode != TangentStiffness ) { - return; + return {E}; } MisesMatGradStatus *status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); @@ -182,8 +168,7 @@ MisesMatGrad :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, double nlKappa = status->giveNonlocalCumulatedStrain(); double kappa = mParam * nlKappa + ( 1. - mParam ) * tempKappa; if ( dKappa <= 0.0 ) { - answer.at(1, 1) = ( 1. - tempDamage ) * E; - return; + return {( 1. - tempDamage ) * E}; } @@ -191,19 +176,20 @@ MisesMatGrad :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, const FloatArray &stressVector = status->giveTempEffectiveStress(); double stress = stressVector.at(1); - answer.at(1, 1) = ( 1. - tempDamage ) * E * H / ( E + H ); - if ( ( tempDamage - damage ) > 0 ) { - answer.at(1, 1) = answer.at(1, 1) - ( 1. - mParam ) * computeDamageParamPrime(kappa) * E / ( E + H ) * signum(stress) * stress; + auto tangent = ( 1. - tempDamage ) * E * H / ( E + H ); + if ( tempDamage > damage ) { + tangent -= ( 1. - mParam ) * computeDamageParamPrime(kappa) * E / ( E + H ) * signum(stress) * stress; } + return {tangent}; } -void -MisesMatGrad :: givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<4,4> +MisesMatGrad :: givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + auto d = this->linearElasticMaterial.givePlaneStrainStiffMtrx(mode, gp, tStep); if ( mode != TangentStiffness ) { - return; + return d; } MisesMatGradStatus *status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); @@ -214,7 +200,7 @@ MisesMatGrad :: givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mo double damage = status->giveDamage(); if ( dKappa <= 0.0 ) { // elastic loading - elastic stiffness plays the role of tangent stiffness - return; + return d; } // === plastic loading === @@ -231,7 +217,7 @@ MisesMatGrad :: givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mo double factor = -2. * sqrt(6.) * G * G / trialS; double factor1 = factor * sigmaY / ( ( H + 3. * G ) * trialS * trialS ); stiffnessCorrection.times(factor1); - answer.add(stiffnessCorrection); + d += FloatMatrixF<4,4>(stiffnessCorrection); // another correction term stiffnessCorrection.zero(); stiffnessCorrection.at(1, 1) = stiffnessCorrection.at(2, 2) = stiffnessCorrection.at(3, 3) = 2. / 3.; @@ -240,9 +226,9 @@ MisesMatGrad :: givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mo stiffnessCorrection.at(4, 4) = 0.5; double factor2 = factor * dKappa; stiffnessCorrection.times(factor2); - answer.add(stiffnessCorrection); + d += FloatMatrixF<4,4>(stiffnessCorrection); //influence of damage - answer.times(1 - tempDamage); + d *= 1 - tempDamage; if ( tempDamage > damage ) { const FloatArray &effStress = status->giveTempEffectiveStress(); double nlKappa = status->giveNonlocalCumulatedStrain(); @@ -251,19 +237,20 @@ MisesMatGrad :: givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mo double scalar = -omegaPrime *sqrt(6.) * G / ( 3. * G + H ) / trialS; stiffnessCorrection.beDyadicProductOf(effStress, trialStressDev); stiffnessCorrection.times( scalar * ( 1. - mParam ) ); - answer.add(stiffnessCorrection); + d += FloatMatrixF<4,4>(stiffnessCorrection); } + return d; } -void -MisesMatGrad :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<6,6> +MisesMatGrad :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - MisesMatGradStatus *status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); - this->giveLinearElasticMaterial()->give3dMaterialStiffnessMatrix(answer, mode, gp, tStep); + auto status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); + auto d = this->linearElasticMaterial.give3dMaterialStiffnessMatrix(mode, gp, tStep); // start from the elastic stiffness if ( mode != TangentStiffness ) { - return; + return d; } double tempKappa = status->giveTempCumulativePlasticStrain(); @@ -275,36 +262,29 @@ MisesMatGrad :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMo double damage = status->giveDamage(); double sigmaY = this->give('s', gp, tStep) + H * kappa; // trial deviatoric stress and its norm - const FloatArray &trialStressDev = status->giveTrialStressDev(); + const FloatArrayF<6> trialStressDev = status->giveTrialStressDev(); /*****************************************************/ //double trialStressVol = status->giveTrialStressVol(); /****************************************************/ double trialS = computeStressNorm(trialStressDev); // one correction term - FloatMatrix stiffnessCorrection(6, 6); - stiffnessCorrection.beDyadicProductOf(trialStressDev, trialStressDev); double factor = -2. * sqrt(6.) * G * G / trialS; double factor1 = factor * sigmaY / ( ( H + 3. * G ) * trialS * trialS ); - stiffnessCorrection.times(factor1); - answer.add(stiffnessCorrection); + d += factor1 * dyad(trialStressDev, trialStressDev); // another correction term - stiffnessCorrection.bePinvID(); - double factor2 = factor * dKappa; - stiffnessCorrection.times(factor2); - answer.add(stiffnessCorrection); + d += factor * dKappa * I_dev6; //influence of damage - answer.times(1. - tempDamage); + d *= (1. - tempDamage); if ( tempDamage > damage ) { - const FloatArray &effStress = status->giveTempEffectiveStress(); - double nlKappa = status->giveNonlocalCumulatedStrain(); + const FloatArrayF<6> effStress = status->giveTempEffectiveStress(); + double nlKappa = status->giveNonlocalCumulatedStrain(); kappa = mParam * nlKappa + ( 1. - mParam ) * tempKappa; double omegaPrime = computeDamageParamPrime(kappa); double scalar = -omegaPrime *sqrt(6.) * G / ( 3. * G + H ) / trialS; - stiffnessCorrection.beDyadicProductOf(effStress, trialStressDev); - stiffnessCorrection.times( scalar * ( 1. - mParam ) ); - answer.add(stiffnessCorrection); + d += scalar * ( 1. - mParam ) * dyad(effStress, trialStressDev); } } + return d; } @@ -313,8 +293,7 @@ MisesMatGrad :: give1dKappaMatrix(FloatMatrix &answer, MatResponseMode mode, Gau { answer.resize(1, 1); answer.zero(); - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); - double E = lmat->give('E', gp); + double E = linearElasticMaterial.give('E', gp); MisesMatGradStatus *status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); double tempKappa = status->giveTempCumulativePlasticStrain(); double dKappa = tempKappa - status->giveCumulativePlasticStrain(); @@ -455,19 +434,19 @@ MisesMatGrad :: giveInternalLength(FloatMatrix &answer, MatResponseMode mode, Ga } + + void -MisesMatGrad :: giveRealStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) +MisesMatGrad :: giveRealStressVectorGradientDamage(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) { - MisesMatGradStatus *status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); - double tempDamage; - - MisesMat :: performPlasticityReturn(gp, totalStrain, tStep); + MisesMat :: performPlasticityReturn(totalStrain, gp, tStep); status->letTempStrainVectorBe(totalStrain); - tempDamage = computeDamage(gp, tStep); - const FloatArray &tempEffStress = status->giveTempEffectiveStress(); + double tempDamage = computeDamage(gp, tStep); + const auto &tempEffStress = status->giveTempEffectiveStress(); answer1.beScaled(1.0 - tempDamage, tempEffStress); answer2 = status->giveTempCumulativePlasticStrain(); @@ -478,21 +457,46 @@ MisesMatGrad :: giveRealStressVectorGrad(FloatArray &answer1, double &answer2, G } -void -MisesMatGrad :: computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *tStep) +double +MisesMatGrad :: computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const { - MisesMatGradStatus *status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); double localCumPlastStrain = status->giveTempCumulativePlasticStrain(); double nlCumPlastStrain = status->giveNonlocalCumulatedStrain(); - kappa = mParam * nlCumPlastStrain + ( 1 - mParam ) * localCumPlastStrain; + return mParam * nlCumPlastStrain + ( 1 - mParam ) * localCumPlastStrain; +} + + +void +MisesMatGrad :: giveNonlocalInternalForces_N_factor(double &answer, double nlDamageDrivingVariable, GaussPoint *gp, TimeStep *tStep) +{ + answer = nlDamageDrivingVariable; +} + +void +MisesMatGrad :: giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlDamageDrivingVariable_grad, GaussPoint *gp, TimeStep *tStep) +{ + answer = nlDamageDrivingVariable_grad; + answer.times(internalLength * internalLength); +} + + + + +void +MisesMatGrad :: computeLocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep) +{ + MisesMatGradStatus *status = static_cast< MisesMatGradStatus * >( this->giveStatus(gp) ); + answer = status->giveTempCumulativePlasticStrain(); } -IRResultType -MisesMatGrad :: initializeFrom(InputRecord *ir) + +void +MisesMatGrad :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + MisesMat :: initializeFrom(ir); IR_GIVE_FIELD(ir, L, _IFT_MisesMatGrad_l); if ( L < 0.0 ) { @@ -501,24 +505,16 @@ MisesMatGrad :: initializeFrom(InputRecord *ir) mParam = 2.; IR_GIVE_OPTIONAL_FIELD(ir, mParam, _IFT_MisesMatGrad_m); - - return MisesMat :: initializeFrom(ir); -} - - -MisesMatGradStatus :: MisesMatGradStatus(int n, Domain *d, GaussPoint *g) : - MisesMatStatus(n, d, g) -{ - nonlocalCumulatedStrain = 0; } -MisesMatGradStatus :: ~MisesMatGradStatus() -{ } +MisesMatGradStatus :: MisesMatGradStatus(GaussPoint *g) : + MisesMatStatus(g) +{} void -MisesMatGradStatus :: printOutputAt(FILE *file, TimeStep *tStep) +MisesMatGradStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status {"); @@ -550,7 +546,6 @@ MisesMatGradStatus :: initTempStatus() tempDamage = damage; tempPlasticStrain = plasticStrain; tempKappa = kappa; - tempLeftCauchyGreen = leftCauchyGreen; trialStressD.clear(); } diff --git a/src/sm/Materials/misesmatgrad.h b/src/sm/Materials/misesmatgrad.h index 5df0991c6..f0d0d5b8c 100644 --- a/src/sm/Materials/misesmatgrad.h +++ b/src/sm/Materials/misesmatgrad.h @@ -35,7 +35,7 @@ #ifndef MisesMatGrad_h #include "Materials/misesmat.h" -#include "graddpmaterialextensioninterface.h" +#include "graddamagematerialextensioninterface.h" #include "cltypes.h" ///@name Input fields for MisesMatGrad @@ -49,68 +49,65 @@ namespace oofem { /** * Gradient Mises maaterial status. */ -class MisesMatGradStatus : public MisesMatStatus, GradDpMaterialStatusExtensionInterface +class MisesMatGradStatus : public MisesMatStatus, GradientDamageMaterialStatusExtensionInterface { protected: - double localCumPlastStrainForAverage; + double localCumPlastStrainForAverage = 0.; public: - MisesMatGradStatus(int n, Domain * d, GaussPoint * g); - virtual ~MisesMatGradStatus(); + MisesMatGradStatus(GaussPoint *g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; // definition - virtual const char *giveClassName() const { return "MisesMatGradStatus"; } + const char *giveClassName() const override { return "MisesMatGradStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual double giveNonlocalCumulatedStrain() { return nonlocalCumulatedStrain; } - virtual void setNonlocalCumulatedStrain(double nonlocalCumulatedStrain) { this->nonlocalCumulatedStrain = nonlocalCumulatedStrain; } + double giveNonlocalCumulatedStrain() const { return nonlocalDamageDrivingVariable; } + void setNonlocalCumulatedStrain(double nonlocalCumulatedStrain) { this->nonlocalDamageDrivingVariable = nonlocalCumulatedStrain; } }; /** * Gradient Mises material. */ -class MisesMatGrad : public MisesMat, GradDpMaterialExtensionInterface +class MisesMatGrad : public MisesMat, GradientDamageMaterialExtensionInterface { protected: - double L; - double mParam; + double L = 0.; + double mParam = 0.; public: - MisesMatGrad(int n, Domain * d); - virtual ~MisesMatGrad(); + MisesMatGrad(int n, Domain *d); // definition - virtual const char *giveInputRecordName() const { return _IFT_MisesMatGrad_Name; } - virtual const char *giveClassName() const { return "MisesMatGrad"; } + const char *giveInputRecordName() const override { return _IFT_MisesMatGrad_Name; } + const char *giveClassName() const override { return "MisesMatGrad"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int hasMaterialModeCapability(MaterialMode mode); + void initializeFrom(InputRecord &ir) override; + bool hasMaterialModeCapability(MaterialMode mode) const override; - virtual Interface *giveInterface(InterfaceType t) { - if ( t == GradDpMaterialExtensionInterfaceType ) { - return static_cast< GradDpMaterialExtensionInterface * >(this); + Interface *giveInterface(InterfaceType t) override { + if ( t == GradientDamageMaterialExtensionInterfaceType ) { + return static_cast< GradientDamageMaterialExtensionInterface * >( this ); } else { - return NULL; + return nullptr; } } - virtual void giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; - virtual void give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode, GaussPoint *gp, TimeStep *tStep); - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode, GaussPoint * gp, TimeStep * tStep) const override; + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode, GaussPoint * gp, TimeStep * tStep) const override; + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode, GaussPoint * gp, TimeStep * tStep) const override; - virtual void givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_LD(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveRealStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep); + void giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveRealStressVectorGradientDamage(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) override; void give1dKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); @@ -124,12 +121,16 @@ class MisesMatGrad : public MisesMat, GradDpMaterialExtensionInterface void giveInternalLength(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *tStep); + void computeLocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep) override; + void giveNonlocalInternalForces_N_factor(double &answer, double nlddv, GaussPoint *gp, TimeStep *tStep) override; + void giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlddv, GaussPoint *gp, TimeStep *tStep) override; + + double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const override; void performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain); - LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } + // LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } protected: - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new MisesMatGradStatus(1, MisesMat :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new MisesMatGradStatus(gp); } }; } // end namespace oofem #define MisesMatGrad_h diff --git a/src/sm/Materials/misesmatnl.C b/src/sm/Materials/misesmatnl.C index 1476c0d2a..c158e2f70 100644 --- a/src/sm/Materials/misesmatnl.C +++ b/src/sm/Materials/misesmatnl.C @@ -33,7 +33,7 @@ */ #include "misesmatnl.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" @@ -50,74 +50,65 @@ REGISTER_Material(MisesMatNl); MisesMatNl :: MisesMatNl(int n, Domain *d) : MisesMat(n, d), StructuralNonlocalMaterialExtensionInterface(d), NonlocalMaterialStiffnessInterface() { - Rf = 0.; - exponent = 1.; - averType = 0; } -MisesMatNl :: ~MisesMatNl() -{ } - - -void -MisesMatNl :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &totalStrain, TimeStep *tStep) +FloatArrayF<6> +MisesMatNl :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("3D mode not supported"); + return zeros<6>(); } -void -MisesMatNl :: giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, - const FloatArray &totalStrain, TimeStep *tStep) +FloatArrayF<1> +MisesMatNl :: giveRealStressVector_1d(const FloatArrayF<1> &totalStrain, GaussPoint *gp, TimeStep *tStep) const { - MisesMatNlStatus *nlStatus = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); + auto nlStatus = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); - double tempDam; - performPlasticityReturn(gp, totalStrain, tStep); - tempDam = this->computeDamage(gp, tStep); - answer.beScaled(1.0 - tempDam, nlStatus->giveTempEffectiveStress()); + performPlasticityReturn(totalStrain, gp, tStep); + double tempDam = this->computeDamage(gp, tStep); + FloatArrayF<6> stress = (1.0 - tempDam) * nlStatus->giveTempEffectiveStress(); nlStatus->setTempDamage(tempDam); nlStatus->letTempStrainVectorBe(totalStrain); - nlStatus->letTempStressVectorBe(answer); + nlStatus->letTempStressVectorBe(stress); + return stress[{0}]; } -void -MisesMatNl :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<1,1> +MisesMatNl :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - answer.resize(1, 1); - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); - double E = lmat->give('E', gp); - MisesMatNlStatus *status = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); + double E = linearElasticMaterial.give('E', gp); double kappa = status->giveCumulativePlasticStrain(); double tempKappa = status->giveTempCumulativePlasticStrain(); double tempDamage = status->giveTempDamage(); double damage = status->giveDamage(); - answer.at(1, 1) = ( 1 - tempDamage ) * E; + + auto tangent = ( 1 - tempDamage ) * E; if ( mode != TangentStiffness ) { - return; + return {tangent}; } if ( tempKappa <= kappa ) { // elastic loading - elastic stiffness plays the role of tangent stiffness - return; + return {tangent}; } // === plastic loading === - const FloatArray &stressVector = status->giveTempEffectiveStress(); + const auto &stressVector = status->giveTempEffectiveStress(); double stress = stressVector.at(1); - answer.at(1, 1) = ( 1. - tempDamage ) * E * H / ( E + H ); + tangent = ( 1. - tempDamage ) * E * H / ( E + H ); if ( tempDamage > damage ) { - double nlKappa; - this->computeCumPlasticStrain(nlKappa, gp, tStep); - answer.at(1, 1) -= ( 1 - mm ) * computeDamageParamPrime(nlKappa) * E / ( E + H ) * stress * sgn(stress); + double nlKappa = this->computeCumPlasticStrain(gp, tStep); + tangent -= ( 1 - mm ) * computeDamageParamPrime(nlKappa) * E / ( E + H ) * stress * sgn(stress); } + return {tangent}; } void -MisesMatNl :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) +MisesMatNl :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const { /* Implements the service updating local variables in given integration points, * which take part in nonlocal average process. Actually, no update is necessary, @@ -126,12 +117,11 @@ MisesMatNl :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoi * This service is declared at StructuralNonlocalMaterial level. */ - double cumPlasticStrain; - MisesMatNlStatus *nlstatus = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); + auto nlstatus = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); - this->performPlasticityReturn(gp, strainVector, tStep); - this->computeLocalCumPlasticStrain(cumPlasticStrain, gp, tStep); + this->performPlasticityReturn(strainVector, gp, tStep); + double cumPlasticStrain = this->computeLocalCumPlasticStrain(gp, tStep); // standard formulation based on averaging of equivalent strain nlstatus->setLocalCumPlasticStrainForAverage(cumPlasticStrain); @@ -143,7 +133,7 @@ MisesMatNl :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoi void -MisesMatNl :: modifyNonlocalWeightFunctionAround(GaussPoint *gp) +MisesMatNl :: modifyNonlocalWeightFunctionAround(GaussPoint *gp) const { MisesMatNlStatus *nonlocStatus, *status = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); auto list = this->giveIPIntegrationList(gp); @@ -177,7 +167,7 @@ MisesMatNl :: modifyNonlocalWeightFunctionAround(GaussPoint *gp) distance += ( x - xprev ) * 0.5 * ( computeDistanceModifier(damage) + computeDistanceModifier(damageprev) ); } - w = computeWeightFunction(distance) * nearElem->computeVolumeAround(pos->nearGp); + w = computeWeightFunction(this->cl, distance) * nearElem->computeVolumeAround(pos->nearGp); pos->weight = w; wsum += w; xprev = x; @@ -194,7 +184,7 @@ MisesMatNl :: modifyNonlocalWeightFunctionAround(GaussPoint *gp) damage = nonlocStatus->giveTempDamage(); if ( pos != postarget ) { distance += ( xprev - x ) * 0.5 * ( computeDistanceModifier(damage) + computeDistanceModifier(damageprev) ); - w = computeWeightFunction(distance) * nearElem->computeVolumeAround(pos->nearGp); + w = computeWeightFunction(this->cl, distance) * nearElem->computeVolumeAround(pos->nearGp); pos->weight = w; wsum += w; } @@ -212,7 +202,7 @@ MisesMatNl :: modifyNonlocalWeightFunctionAround(GaussPoint *gp) nonlocStatus = static_cast< MisesMatNlStatus * >( this->giveStatus(pos->nearGp) ); damage = nonlocStatus->giveTempDamage(); distance += ( xprev - x ) * 0.5 * ( computeDistanceModifier(damage) + computeDistanceModifier(damageprev) ); - w = computeWeightFunction(distance) * nearElem->computeVolumeAround(pos->nearGp); + w = computeWeightFunction(this->cl, distance) * nearElem->computeVolumeAround(pos->nearGp); pos->weight = w; wsum += w; } @@ -221,7 +211,7 @@ MisesMatNl :: modifyNonlocalWeightFunctionAround(GaussPoint *gp) } double -MisesMatNl :: computeDistanceModifier(double damage) +MisesMatNl :: computeDistanceModifier(double damage) const { switch ( averType ) { case 2: return 1. / ( Rf / cl + ( 1. - Rf / cl ) * pow(1. - damage, exponent) ); @@ -240,11 +230,10 @@ MisesMatNl :: computeDistanceModifier(double damage) } } -void -MisesMatNl :: computeCumPlasticStrain(double &kappa, GaussPoint *gp, TimeStep *tStep) +double +MisesMatNl :: computeCumPlasticStrain(GaussPoint *gp, TimeStep *tStep) const { - double nonlocalContribution, nonlocalCumPlasticStrain = 0.0; - MisesMatNlStatus *nonlocStatus, *status = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); + auto status = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); this->buildNonlocalPointTable(gp); this->updateDomainBeforeNonlocAverage(tStep); @@ -252,9 +241,10 @@ MisesMatNl :: computeCumPlasticStrain(double &kappa, GaussPoint *gp, TimeStep *t // compute nonlocal cumulative plastic strain auto list = this->giveIPIntegrationList(gp); + double nonlocalCumPlasticStrain = 0.0; for ( auto &lir: *list ) { - nonlocStatus = static_cast< MisesMatNlStatus * >( this->giveStatus(lir.nearGp) ); - nonlocalContribution = nonlocStatus->giveLocalCumPlasticStrainForAverage(); + auto nonlocStatus = static_cast< MisesMatNlStatus * >( this->giveStatus(lir.nearGp) ); + auto nonlocalContribution = nonlocStatus->giveLocalCumPlasticStrainForAverage(); if ( nonlocalContribution > 0 ) { nonlocalContribution *= lir.weight; } @@ -273,7 +263,7 @@ MisesMatNl :: computeCumPlasticStrain(double &kappa, GaussPoint *gp, TimeStep *t } } - kappa = mm * nonlocalCumPlasticStrain + ( 1. - mm ) * localCumPlasticStrain; + return mm * nonlocalCumPlasticStrain + ( 1. - mm ) * localCumPlasticStrain; } Interface * @@ -289,15 +279,11 @@ MisesMatNl :: giveInterface(InterfaceType type) } -IRResultType -MisesMatNl :: initializeFrom(InputRecord *ir) +void +MisesMatNl :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = MisesMat :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - result = StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + MisesMat :: initializeFrom(ir); + StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); averType = 0; IR_GIVE_OPTIONAL_FIELD(ir, averType, _IFT_MisesMatNl_averagingtype); @@ -316,8 +302,6 @@ MisesMatNl :: initializeFrom(InputRecord *ir) if ( averType >= 2 && averType <= 5 ) { IR_GIVE_OPTIONAL_FIELD(ir, Rf, _IFT_MisesMatNl_rf); } - - return IRRT_OK; } @@ -340,14 +324,12 @@ MisesMatNl :: giveInputRecord(DynamicInputRecord &input) double -MisesMatNl :: computeDamage(GaussPoint *gp, TimeStep *tStep) +MisesMatNl :: computeDamage(GaussPoint *gp, TimeStep *tStep) const { - MisesMatNlStatus *nlStatus = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); - double nlKappa; - this->computeCumPlasticStrain(nlKappa, gp, tStep); - double dam, tempDam; - dam = nlStatus->giveDamage(); - tempDam = this->computeDamageParam(nlKappa); + auto nlStatus = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); + double nlKappa = this->computeCumPlasticStrain(gp, tStep); + double dam = nlStatus->giveDamage(); + double tempDam = this->computeDamageParam(nlKappa); if ( tempDam < dam ) { tempDam = dam; } @@ -400,19 +382,18 @@ int MisesMatNl :: giveLocalNonlocalStiffnessContribution(GaussPoint *gp, IntArray &loc, const UnknownNumberingScheme &s, FloatArray &lcontrib, TimeStep *tStep) { - double nlKappa, damage, tempDamage, dDamF; - MisesMatNlStatus *status = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); - StructuralElement *elem = static_cast< StructuralElement * >( gp->giveElement() ); + auto status = static_cast< MisesMatNlStatus * >( this->giveStatus(gp) ); + auto elem = static_cast< StructuralElement * >( gp->giveElement() ); FloatMatrix b; - this->computeCumPlasticStrain(nlKappa, gp, tStep); - damage = status->giveDamage(); - tempDamage = status->giveTempDamage(); + double nlKappa = this->computeCumPlasticStrain(gp, tStep); + double damage = status->giveDamage(); + double tempDamage = status->giveTempDamage(); if ( ( tempDamage - damage ) > 0 ) { const FloatArray &stress = status->giveTempEffectiveStress(); elem->giveLocationArray(loc, s); elem->computeBmatrixAt(gp, b); - dDamF = computeDamageParamPrime(nlKappa); + double dDamF = computeDamageParamPrime(nlKappa); lcontrib.clear(); lcontrib.plusProduct(b, stress, mm * dDamF); } @@ -437,8 +418,7 @@ MisesMatNl :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray & rcontrib.clear(); if ( ( tempKappa - kappa ) > 0 ) { - LinearElasticMaterial *lmat = this->giveLinearElasticMaterial(); - double E = lmat->give('E', gp); + double E = linearElasticMaterial.give('E', gp); const FloatArray &stress = status->giveTempEffectiveStress(); if ( gp->giveMaterialMode() == _1dMat ) { double coeff = sgn( stress.at(1) ) * E / ( E + H ); @@ -453,19 +433,13 @@ MisesMatNl :: giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray & /*********************************************status**************************************************************/ -MisesMatNlStatus :: MisesMatNlStatus(int n, Domain *d, GaussPoint *g) : - MisesMatStatus(n, d, g), StructuralNonlocalMaterialStatusExtensionInterface() -{ - localCumPlasticStrainForAverage = 0.0; -} - - -MisesMatNlStatus :: ~MisesMatNlStatus() -{ } +MisesMatNlStatus :: MisesMatNlStatus(GaussPoint *g) : + MisesMatStatus(g), StructuralNonlocalMaterialStatusExtensionInterface() +{} void -MisesMatNlStatus :: printOutputAt(FILE *file, TimeStep *tStep) +MisesMatNlStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -497,40 +471,19 @@ MisesMatNlStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -MisesMatNlStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +MisesMatNlStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // save parent class status - if ( ( iores = MisesMatStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - //if (!stream.write(&localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); - return CIO_OK; + MisesMatStatus :: saveContext(stream, mode); + //if (!stream.write(localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); } -contextIOResultType -MisesMatNlStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +MisesMatNlStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // read parent class status - if ( ( iores = MisesMatStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data - //if (!stream.read (&localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); - - return CIO_OK; + MisesMatStatus :: restoreContext(stream, mode); + //if (!stream.read(localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); } diff --git a/src/sm/Materials/misesmatnl.h b/src/sm/Materials/misesmatnl.h index e05d23740..c5dbd6f52 100644 --- a/src/sm/Materials/misesmatnl.h +++ b/src/sm/Materials/misesmatnl.h @@ -34,8 +34,8 @@ #ifndef misesmatnl_h -#include "Materials/misesmat.h" -#include "Materials/structuralnonlocalmaterialext.h" +#include "sm/Materials/misesmat.h" +#include "sm/Materials/structuralnonlocalmaterialext.h" #include "nonlocmatstiffinterface.h" #include "cltypes.h" @@ -57,30 +57,27 @@ class MisesMatNlStatus : public MisesMatStatus, public StructuralNonlocalMateria protected: // STATE VARIABLE DECLARATION // Equivalent strain for avaraging - double localCumPlasticStrainForAverage; + double localCumPlasticStrainForAverage = 0.; public: - MisesMatNlStatus(int n, Domain * d, GaussPoint * g); - virtual ~MisesMatNlStatus(); + MisesMatNlStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; // STATE VARIABLE // declare state variable access and modification methods double giveLocalCumPlasticStrainForAverage() { return localCumPlasticStrainForAverage; } - const FloatArray *giveLTangentContrib(); void setLocalCumPlasticStrainForAverage(double ls) { localCumPlasticStrainForAverage = ls; } - // DEFINITION - virtual const char *giveClassName() const { return "MisesMatNlStatus"; } + const char *giveClassName() const override { return "MisesMatNlStatus"; } - virtual void initTempStatus(); + void initTempStatus() override; - virtual void updateYourself(TimeStep *tStep); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void updateYourself(TimeStep *tStep) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; }; @@ -92,21 +89,20 @@ class MisesMatNl : public MisesMat, public StructuralNonlocalMaterialExtensionIn public NonlocalMaterialStiffnessInterface { protected: - double Rf; - double exponent; - int averType; + double Rf = 0.; + double exponent = 1.; + int averType = 0; public: MisesMatNl(int n, Domain * d); - virtual ~MisesMatNl(); - virtual const char *giveClassName() const { return "MisesMatNl"; } - virtual const char *giveInputRecordName() const { return _IFT_MisesMatNl_Name; } + const char *giveClassName() const override { return "MisesMatNl"; } + const char *giveInputRecordName() const override { return _IFT_MisesMatNl_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; /** * Computes the nonlocal cumulated plastic strain from its local form. @@ -114,23 +110,23 @@ public NonlocalMaterialStiffnessInterface * @param gp Integration point. * @param tStep Time step. */ - virtual void computeCumPlasticStrain(double &kappa, GaussPoint *gp, TimeStep *tStep); - double computeDamage(GaussPoint *gp, TimeStep *tStep); - void modifyNonlocalWeightFunctionAround(GaussPoint *gp); - double computeDistanceModifier(double damage); - void computeLocalCumPlasticStrain(double &kappa, GaussPoint *gp, TimeStep *tStep) + virtual double computeCumPlasticStrain(GaussPoint *gp, TimeStep *tStep) const; + double computeDamage(GaussPoint *gp, TimeStep *tStep) const; + void modifyNonlocalWeightFunctionAround(GaussPoint *gp) const; + double computeDistanceModifier(double damage) const; + double computeLocalCumPlasticStrain(GaussPoint *gp, TimeStep *tStep) const { - MisesMat :: computeCumPlastStrain(kappa, gp, tStep); + return MisesMat :: computeCumPlastStrain(gp, tStep); } - virtual void give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep); - //virtual void givePlaneStrainStiffMtrx(FloatMatrix& answer, MatResponseMode, GaussPoint *gp,TimeStep *tStep); - //virtual void give3dMaterialStiffnessMatrix(FloatMatrix& answer, MatResponseMode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + //void givePlaneStrainStiffMtrx(FloatMatrix& answer, MatResponseMode, GaussPoint *gp,TimeStep *tStep) override; + //void give3dMaterialStiffnessMatrix(FloatMatrix& answer, MatResponseMode, GaussPoint *gp, TimeStep *tStep) override; - virtual void NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx &dest, const UnknownNumberingScheme &s, - GaussPoint *gp, TimeStep *tStep); + void NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx &dest, const UnknownNumberingScheme &s, + GaussPoint *gp, TimeStep *tStep) override; - virtual std :: vector< localIntegrationRecord > *NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(GaussPoint *gp); + std :: vector< localIntegrationRecord > *NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(GaussPoint *gp) override; /** * Computes the "local" part of nonlocal stiffness contribution assembled for given integration point. @@ -155,20 +151,19 @@ public NonlocalMaterialStiffnessInterface void giveRemoteNonlocalStiffnessContribution(GaussPoint *gp, IntArray &rloc, const UnknownNumberingScheme &s, FloatArray &rcontrib, TimeStep *tStep); - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strainVector, TimeStep *tStep); - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &strainVector, TimeStep *tStep); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strainVector, GaussPoint *gp, TimeStep *tStep) const override; - virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep); + void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const override; - virtual int hasBoundedSupport() { return 1; } + int hasBoundedSupport() const override { return 1; } - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int estimatePackSize(DataStream &buff, GaussPoint *ip); + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int estimatePackSize(DataStream &buff, GaussPoint *ip) override; protected: - // Creates the corresponding material status - MaterialStatus *CreateStatus(GaussPoint *gp) const { return new MisesMatNlStatus(1, MisesMat :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new MisesMatNlStatus(gp); } }; } // end namespace oofem #define misesmatnl_h diff --git a/src/sm/Materials/mooneyrivlin.C b/src/sm/Materials/mooneyrivlin.C deleted file mode 100644 index fc11ecadf..000000000 --- a/src/sm/Materials/mooneyrivlin.C +++ /dev/null @@ -1,680 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2014 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mooneyrivlin.h" -#include "floatmatrix.h" -#include "floatarray.h" -#include "classfactory.h" -#include "mathfem.h" - -namespace oofem { -REGISTER_Material(MooneyRivlinMaterial); - -MooneyRivlinMaterial :: MooneyRivlinMaterial(int n, Domain *d) : StructuralMaterial(n, d) -{ } - - -void -MooneyRivlinMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &vF, TimeStep *tStep) -// returns 9 components of the first piola kirchhoff stress corresponding to the given deformation gradinet - -{ - double J, I1, I2, barI1, barI2; - FloatMatrix F, C, Cpow2, invFt, FC, invF; - - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - - //store deformation gradient into matrix - F.beMatrixForm(vF); - invF.beInverseOf(F); - invFt.beTranspositionOf(invF); - // compute jacobian - J = F.giveDeterminant(); - // compute right Cauchy-Green tensor - C.beTProductOf(F, F); - // compute C*C - Cpow2.beProductOf(C, C); - // compute F*C - FC.beProductOf(F, C); - //compute first invariant of deviatoric part of C; - I1 = ( C.at(1, 1) + C.at(2, 2) + C.at(3, 3) ); - I2 = 1. / 2. * ( I1 * I1 - Cpow2.at(1, 1) - Cpow2.at(2, 2) - Cpow2.at(3, 3) ); - barI1 = I1 * pow(J, -2. / 3.); - barI2 = I2 * pow(J, -4. / 3.); - - - FloatMatrix P; - //first part of stress tensor : C1 * \frac{\partial \bar{I}_1}{\partial F_ij} - P.add(2 * C1 / pow(J, 2 / 3.), F); - P.add(-2. / 3. * C1 * barI1, invFt); - // second part of stress tensor : C2 * \frac{\partial \bar{I}_2}{\partial F_ij} - P.add( 2. * C2 * barI1 / pow(J, 2. / 3.), F ); - P.add(-4. / 3. * C2 * barI2, invFt); - P.add(-2. * C2 / pow(J, 4. / 3.), FC ); - // third part of stress tensor : K * \frac{\partial ln J }{F_ij} - P.add(K, invFt); - - answer.beVectorForm(P); - - // update gp - status->letTempFVectorBe(vF); - status->letTempPVectorBe(answer); -} - -void -MooneyRivlinMaterial :: giveFirstPKStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep) -// returns 4 components of the First PK Stress corresponding to the given deformation gradient - -{ - double J, I1, I2, barI1, barI2; - FloatArray vF, vP; - FloatMatrix F, C, CC, invFt, FC, invF; - - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - vF = { - reducedvF.at(1), reducedvF.at(2), reducedvF.at(3), 0, 0, reducedvF.at(4), 0, 0, reducedvF.at(5) - }; - //store deformation gradient into matrix - F.beMatrixForm(vF); - invF.beInverseOf(F); - invFt.beTranspositionOf(invF); - // compute jacobian and its log - J = F.giveDeterminant(); - // compute right Cauchy-Green tensor - C.beTProductOf(F, F); - // compute C*C - CC.beProductOf(C, C); - // compute F*C - FC.beProductOf(F, C); - //compute first invariant of deviatoric part of C; - I1 = ( C.at(1, 1) + C.at(2, 2) + C.at(3, 3) ); - I2 = 1. / 2. * ( I1 * I1 - CC.at(1, 1) - CC.at(2, 2) - CC.at(3, 3) ); - barI1 = I1 * pow(J, -2. / 3.); - barI2 = I2 * pow(J, -4. / 3.); - - - FloatMatrix P; - //first part of stress tensor : C1 * \frac{\partial \bar{I}_1}{\partial F_ij} - P.add( 2 * C1 / pow(J, 2 / 3.), F ); - P.add(-2. / 3. * C1 * barI1, invFt); - // second part of stress tensor : C2 * \frac{\partial \bar{I}_2}{\partial F_ij} - P.add( 2. * C2 * barI1 / pow(J, 2. / 3.), F ); - P.add(-4. / 3. * C2 * barI2, invFt); - P.add(-2. * C2 / pow(J, 4. / 3.), FC); - // third part of stress tensor : K * \frac{\partial ln J }{F_ij} - P.add(K, invFt); - vP.beVectorForm(P); - StructuralMaterial :: giveReducedVectorForm(answer, vP, _PlaneStrain); - answer.beVectorForm(P); - - // update gp - status->letTempFVectorBe(reducedvF); - status->letTempPVectorBe(answer); -} - - -void -MooneyRivlinMaterial :: give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) -// returns the 9x9 tangent stiffness matrix - dP/dF -{ - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - - double I1, I2, J, lnJ; - FloatMatrix C, CC, invF, FC, B; - - - FloatArray vF = status->giveTempFVector(); - FloatMatrix F = { { vF.at(1), vF.at(6), vF.at(5) }, { vF.at(9), vF.at(2), vF.at(4) }, { vF.at(8), vF.at(7), vF.at(3) } }; - C.beTProductOf(F, F); - CC.beProductOf(C, C); - B.beProductTOf(F, F); - invF.beInverseOf(F); - FC.beProductOf(F, C); - - J = F.giveDeterminant(); - lnJ = log(J); - I1 = C.at(1, 1) + C.at(2, 2) + C.at(3, 3); - - I2 = 0.5 * ( I1 * I1 - CC.at(1, 1) - CC.at(2, 2) - CC.at(3, 3) ); - - - answer.at(1, 1) = ( 2. * C1 * ( 5. * I1 * invF.at(1, 1) * invF.at(1, 1) - 12. * F.at(1, 1) * invF.at(1, 1) + 9. ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 2) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(2, 2) - 3. * I1 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 3) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(3, 3) - 3. * I1 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 4) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(3, 2) + 6. * F.at(2, 3) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(3, 2) - 3. * I1 * invF.at(1, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 5) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(3, 1) + 6. * F.at(1, 3) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 6) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(2, 1) + 6. * F.at(1, 2) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 7) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(2, 3) - 3. * I1 * invF.at(2, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 8) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 9) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(1, 2) + 6. * F.at(2, 1) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(1, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - - - - - answer.at(2, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(2, 2) - 3. * I1 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 2) = ( 2. * C1 * ( 5. * I1 * invF.at(2, 2) * invF.at(2, 2) - 12. * F.at(2, 2) * invF.at(2, 2) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 3) = -( 2. * C1 * ( 6. * F.at(2, 2) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(2, 2) - 2. * I1 * invF.at(2, 2) * invF.at(3, 3) - 3. * I1 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 4) = -( 2. * C1 * ( 6. * F.at(2, 2) * invF.at(3, 2) + 6. * F.at(2, 3) * invF.at(2, 2) - 5. * I1 * invF.at(2, 2) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 5) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(3, 1) - 3. * I1 * invF.at(2, 1) * invF.at(3, 2) - 2. * I1 * invF.at(2, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 6) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(2, 1) - 5. * I1 * invF.at(2, 1) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 7) = -( 2. * C1 * ( 6. * F.at(2, 2) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(2, 2) - 5. * I1 * invF.at(2, 2) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 8) = -( 2. * C1 * ( 6. * F.at(2, 2) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(2, 2) - 3. * I1 * invF.at(1, 2) * invF.at(2, 3) - 2. * I1 * invF.at(1, 3) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 9) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(1, 2) - 5. * I1 * invF.at(1, 2) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - - - answer.at(3, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(3, 3) - 3. * I1 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 2) = -( 2. * C1 * ( 6. * F.at(2, 2) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(2, 2) - 2. * I1 * invF.at(2, 2) * invF.at(3, 3) - 3. * I1 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 3) = ( 2. * C1 * ( 5. * I1 * invF.at(3, 3) * invF.at(3, 3) - 12. * F.at(3, 3) * invF.at(3, 3) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 4) = -( 2. * C1 * ( 6. * F.at(2, 3) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(3, 2) - 5. * I1 * invF.at(3, 2) * invF.at(3, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 5) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(3, 1) - 5. * I1 * invF.at(3, 1) * invF.at(3, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 6) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(2, 1) - 2. * I1 * invF.at(2, 1) * invF.at(3, 3) - 3. * I1 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 7) = -( 2. * C1 * ( 6. * F.at(3, 2) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(2, 3) - 5. * I1 * invF.at(2, 3) * invF.at(3, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 8) = -( 2. * C1 * ( 6. * F.at(3, 1) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(1, 3) - 5. * I1 * invF.at(1, 3) * invF.at(3, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 9) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(1, 2) - 2. * I1 * invF.at(1, 2) * invF.at(3, 3) - 3. * I1 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - - - - - answer.at(4, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(3, 2) + 6. * F.at(2, 3) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(3, 2) - 3. * I1 * invF.at(1, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 2) = -( 2. * C1 * ( 6. * F.at(2, 2) * invF.at(3, 2) + 6. * F.at(2, 3) * invF.at(2, 2) - 5. * I1 * invF.at(2, 2) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 3) = -( 2. * C1 * ( 6. * F.at(2, 3) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(3, 2) - 5. * I1 * invF.at(3, 2) * invF.at(3, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 4) = ( 2. * C1 * ( 5. * I1 * invF.at(3, 2) * invF.at(3, 2) - 12. * F.at(2, 3) * invF.at(3, 2) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 5) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(3, 2) + 6. * F.at(2, 3) * invF.at(3, 1) - 5. * I1 * invF.at(3, 1) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 6) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(3, 2) + 6. * F.at(2, 3) * invF.at(2, 1) - 2. * I1 * invF.at(2, 1) * invF.at(3, 2) - 3. * I1 * invF.at(2, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 7) = -( 2. * C1 * ( 6. * F.at(2, 3) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(3, 2) - 3. * I1 * invF.at(2, 2) * invF.at(3, 3) - 2. * I1 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 8) = -( 2. * C1 * ( 6. * F.at(2, 3) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(3, 2) - 3. * I1 * invF.at(1, 2) * invF.at(3, 3) - 2. * I1 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 9) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(3, 2) + 6. * F.at(2, 3) * invF.at(1, 2) - 5. * I1 * invF.at(1, 2) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - - - - answer.at(5, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(3, 1) + 6. * F.at(1, 3) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 2) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(3, 1) - 3. * I1 * invF.at(2, 1) * invF.at(3, 2) - 2. * I1 * invF.at(2, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 3) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(3, 1) - 5. * I1 * invF.at(3, 1) * invF.at(3, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 4) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(3, 2) + 6. * F.at(2, 3) * invF.at(3, 1) - 5. * I1 * invF.at(3, 1) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 5) = ( 2. * C1 * ( 5. * I1 * invF.at(3, 1) * invF.at(3, 1) - 12. * F.at(1, 3) * invF.at(3, 1) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 6) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(3, 1) + 6. * F.at(1, 3) * invF.at(2, 1) - 5. * I1 * invF.at(2, 1) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 7) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(3, 1) - 3. * I1 * invF.at(2, 1) * invF.at(3, 3) - 2. * I1 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 8) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(3, 1) - 3. * I1 * invF.at(1, 1) * invF.at(3, 3) - 2. * I1 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 9) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(1, 2) + 6. * F.at(2, 1) * invF.at(3, 1) - 3. * I1 * invF.at(1, 1) * invF.at(3, 2) - 2. * I1 * invF.at(1, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - - - - answer.at(6, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(2, 1) + 6. * F.at(1, 2) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(6, 2) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(2, 1) - 5. * I1 * invF.at(2, 1) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(6, 3) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(2, 1) - 2. * I1 * invF.at(2, 1) * invF.at(3, 3) - 3. * I1 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(6, 4) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(3, 2) + 6. * F.at(2, 3) * invF.at(2, 1) - 2. * I1 * invF.at(2, 1) * invF.at(3, 2) - 3. * I1 * invF.at(2, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(6, 5) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(3, 1) + 6. * F.at(1, 3) * invF.at(2, 1) - 5. * I1 * invF.at(2, 1) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(6, 6) = ( 2. * C1 * ( 5. * I1 * invF.at(2, 1) * invF.at(2, 1) - 12. * F.at(1, 2) * invF.at(2, 1) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(6, 7) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(2, 1) - 5. * I1 * invF.at(2, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(6, 8) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(2, 1) - 3. * I1 * invF.at(1, 1) * invF.at(2, 3) - 2. * I1 * invF.at(2, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(6, 9) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(1, 2) + 6. * F.at(2, 1) * invF.at(2, 1) - 3. * I1 * invF.at(1, 1) * invF.at(2, 2) - 2. * I1 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - - - - - answer.at(7, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(2, 3) - 3. * I1 * invF.at(2, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(7, 2) = -( 2. * C1 * ( 6. * F.at(2, 2) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(2, 2) - 5. * I1 * invF.at(2, 2) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(7, 3) = -( 2. * C1 * ( 6. * F.at(3, 2) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(2, 3) - 5. * I1 * invF.at(2, 3) * invF.at(3, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(7, 4) = -( 2. * C1 * ( 6. * F.at(2, 3) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(3, 2) - 3. * I1 * invF.at(2, 2) * invF.at(3, 3) - 2. * I1 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(7, 5) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(3, 1) - 3. * I1 * invF.at(2, 1) * invF.at(3, 3) - 2. * I1 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(7, 6) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(2, 1) - 5. * I1 * invF.at(2, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(7, 7) = ( 2. * C1 * ( 5. * I1 * invF.at(2, 3) * invF.at(2, 3) - 12. * F.at(3, 2) * invF.at(2, 3) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(7, 8) = -( 2. * C1 * ( 6. * F.at(3, 1) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(1, 3) - 5. * I1 * invF.at(1, 3) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(7, 9) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(1, 2) - 2. * I1 * invF.at(1, 2) * invF.at(2, 3) - 3. * I1 * invF.at(1, 3) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - - - - - - answer.at(8, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(8, 2) = -( 2. * C1 * ( 6. * F.at(2, 2) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(2, 2) - 3. * I1 * invF.at(1, 2) * invF.at(2, 3) - 2. * I1 * invF.at(1, 3) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(8, 3) = -( 2. * C1 * ( 6. * F.at(3, 1) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(1, 3) - 5. * I1 * invF.at(1, 3) * invF.at(3, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(8, 4) = -( 2. * C1 * ( 6. * F.at(2, 3) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(3, 2) - 3. * I1 * invF.at(1, 2) * invF.at(3, 3) - 2. * I1 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(8, 5) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(3, 1) - 3. * I1 * invF.at(1, 1) * invF.at(3, 3) - 2. * I1 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(8, 6) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(2, 1) - 3. * I1 * invF.at(1, 1) * invF.at(2, 3) - 2. * I1 * invF.at(2, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(8, 7) = -( 2. * C1 * ( 6. * F.at(3, 1) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(1, 3) - 5. * I1 * invF.at(1, 3) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(8, 8) = ( 2. * C1 * ( 5. * I1 * invF.at(1, 3) * invF.at(1, 3) - 12. * F.at(3, 1) * invF.at(1, 3) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(8, 9) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(1, 2) - 5. * I1 * invF.at(1, 2) * invF.at(1, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - - - - - - answer.at(9, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(1, 2) + 6. * F.at(2, 1) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(1, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(9, 2) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(1, 2) - 5. * I1 * invF.at(1, 2) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(9, 3) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(1, 2) - 2. * I1 * invF.at(1, 2) * invF.at(3, 3) - 3. * I1 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(9, 4) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(3, 2) + 6. * F.at(2, 3) * invF.at(1, 2) - 5. * I1 * invF.at(1, 2) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(9, 5) = -( 2. * C1 * ( 6. * F.at(1, 3) * invF.at(1, 2) + 6. * F.at(2, 1) * invF.at(3, 1) - 3. * I1 * invF.at(1, 1) * invF.at(3, 2) - 2. * I1 * invF.at(1, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(9, 6) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(1, 2) + 6. * F.at(2, 1) * invF.at(2, 1) - 3. * I1 * invF.at(1, 1) * invF.at(2, 2) - 2. * I1 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(9, 7) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(2, 3) + 6. * F.at(3, 2) * invF.at(1, 2) - 2. * I1 * invF.at(1, 2) * invF.at(2, 3) - 3. * I1 * invF.at(1, 3) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(9, 8) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(1, 3) + 6. * F.at(3, 1) * invF.at(1, 2) - 5. * I1 * invF.at(1, 2) * invF.at(1, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(9, 9) = ( 2. * C1 * ( 5. * I1 * invF.at(1, 2) * invF.at(1, 2) - 12. * F.at(2, 1) * invF.at(1, 2) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - - - - /////////////////////////////////////////////////////////////////////////// - - - answer.at(1, 1) = answer.at(1, 1) + ( 2. * C2 * ( 9. * F.at(1, 1) * F.at(1, 1) - 24. * I1 * F.at(1, 1) * invF.at(1, 1) - 2. * I2 * invF.at(1, 1) * invF.at(1, 1) + 24. * FC.at(1, 1) * invF.at(1, 1) + 9. * B.at(1, 1) - 9. * C.at(1, 1) + 9. * I1 ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 2) = answer.at(1, 2) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(2, 2) + 12. * FC.at(2, 2) * invF.at(1, 1) + 18. * F.at(1, 1) * F.at(2, 2) - 9. * F.at(1, 2) * F.at(2, 1) - 12. * F.at(1, 1) * I1 * invF.at(2, 2) - 12. * F.at(2, 2) * I1 * invF.at(1, 1) - 8. * I2 * invF.at(1, 1) * invF.at(2, 2) + 6. * I2 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 3) = answer.at(1, 3) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(1, 1) + 18 * F.at(1, 1) * F.at(3, 3) - 9. * F.at(1, 3) * F.at(3, 1) - 12. * F.at(1, 1) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(1, 1) - 8. * I2 * invF.at(1, 1) * invF.at(3, 3) + 6 * I2 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 4) = answer.at(1, 4) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(2, 3) + 12. * FC.at(2, 3) * invF.at(1, 1) + 18 * F.at(1, 1) * F.at(2, 3) - 9. * F.at(1, 3) * F.at(2, 1) - 12. * F.at(1, 1) * I1 * invF.at(3, 2) - 12. * F.at(2, 3) * I1 * invF.at(1, 1) - 8. * I2 * invF.at(1, 1) * invF.at(3, 2) + 6 * I2 * invF.at(1, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 5) = answer.at(1, 5) - ( 2. * C2 * ( 9. * C.at(3, 1) - 12. * FC.at(1, 1) * invF.at(1, 3) - 12. * FC.at(1, 3) * invF.at(1, 1) - 9. * F.at(1, 1) * F.at(1, 3) + 12. * F.at(1, 1) * I1 * invF.at(3, 1) + 12. * F.at(1, 3) * I1 * invF.at(1, 1) + 2. * I2 * invF.at(1, 1) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 6) = answer.at(1, 6) - ( 2. * C2 * ( 9. * C.at(2, 1) - 12. * FC.at(1, 1) * invF.at(1, 2) - 12. * FC.at(1, 2) * invF.at(1, 1) - 9. * F.at(1, 1) * F.at(1, 2) + 12. * F.at(1, 1) * I1 * invF.at(2, 1) + 12. * F.at(1, 2) * I1 * invF.at(1, 1) + 2. * I2 * invF.at(1, 1) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 7) = answer.at(1, 7) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(3, 2) + 12. * FC.at(3, 2) * invF.at(1, 1) + 18 * F.at(1, 1) * F.at(3, 2) - 9. * F.at(1, 2) * F.at(3, 1) - 12. * F.at(1, 1) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(1, 1) - 8 * I2 * invF.at(1, 1) * invF.at(2, 3) + 6 * I2 * invF.at(2, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 8) = answer.at(1, 8) + ( 2. * C2 * ( 9. * B.at(1, 3) + 12. * FC.at(1, 1) * invF.at(3, 1) + 12. * FC.at(3, 1) * invF.at(1, 1) + 9. * F.at(1, 1) * F.at(3, 1) - 12. * F.at(1, 1) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(1, 1) - 2. * I2 * invF.at(1, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 9) = answer.at(1, 9) + ( 2. * C2 * ( 9. * B.at(1, 2) + 12. * FC.at(1, 1) * invF.at(2, 1) + 12. * FC.at(2, 1) * invF.at(1, 1) + 9. * F.at(1, 1) * F.at(2, 1) - 12. * F.at(1, 1) * I1 * invF.at(1, 2) - 12. * F.at(2, 1) * I1 * invF.at(1, 1) - 2. * I2 * invF.at(1, 1) * invF.at(1, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - - - - - - answer.at(2, 1) = answer.at(2, 1) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(2, 2) + 12. * FC.at(2, 2) * invF.at(1, 1) + 18 * F.at(1, 1) * F.at(2, 2) - 9. * F.at(1, 2) * F.at(2, 1) - 12. * F.at(1, 1) * I1 * invF.at(2, 2) - 12. * F.at(2, 2) * I1 * invF.at(1, 1) - 8 * I2 * invF.at(1, 1) * invF.at(2, 2) + 6 * I2 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 2) = answer.at(2, 2) + ( 2. * C2 * ( 9. * F.at(2, 2) * F.at(2, 2) - 24. * I1 * F.at(2, 2) * invF.at(2, 2) - 2. * I2 * invF.at(2, 2) * invF.at(2, 2) + 24. * FC.at(2, 2) * invF.at(2, 2) + 9. * B.at(2, 2) - 9. * C.at(2, 2) + 9. * I1 ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 3) = answer.at(2, 3) + ( 2. * C2 * ( 12. * FC.at(2, 2) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(2, 2) + 18 * F.at(2, 2) * F.at(3, 3) - 9. * F.at(2, 3) * F.at(3, 2) - 12. * F.at(2, 2) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(2, 2) - 8 * I2 * invF.at(2, 2) * invF.at(3, 3) + 6 * I2 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 4) = answer.at(2, 4) - ( 2. * C2 * ( 9. * C.at(3, 2) - 12. * FC.at(2, 2) * invF.at(2, 3) - 12. * FC.at(2, 3) * invF.at(2, 2) - 9. * F.at(2, 2) * F.at(2, 3) + 12. * F.at(2, 2) * I1 * invF.at(3, 2) + 12. * F.at(2, 3) * I1 * invF.at(2, 2) + 2. * I2 * invF.at(2, 2) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 5) = answer.at(2, 5) + ( 2. * C2 * ( 12. * FC.at(1, 3) * invF.at(2, 2) + 12. * FC.at(2, 2) * invF.at(1, 3) - 9. * F.at(1, 2) * F.at(2, 3) + 18 * F.at(1, 3) * F.at(2, 2) - 12. * F.at(1, 3) * I1 * invF.at(2, 2) - 12. * F.at(2, 2) * I1 * invF.at(3, 1) + 6 * I2 * invF.at(2, 1) * invF.at(3, 2) - 8 * I2 * invF.at(2, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 6) = answer.at(2, 6) + ( 2. * C2 * ( 9. * B.at(2, 1) + 12. * FC.at(1, 2) * invF.at(2, 2) + 12. * FC.at(2, 2) * invF.at(1, 2) + 9. * F.at(1, 2) * F.at(2, 2) - 12. * F.at(1, 2) * I1 * invF.at(2, 2) - 12. * F.at(2, 2) * I1 * invF.at(2, 1) - 2. * I2 * invF.at(2, 1) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 7) = answer.at(2, 7) + ( 2. * C2 * ( 9. * B.at(2, 3) + 12. * FC.at(2, 2) * invF.at(3, 2) + 12. * FC.at(3, 2) * invF.at(2, 2) + 9. * F.at(2, 2) * F.at(3, 2) - 12. * F.at(2, 2) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(2, 2) - 2. * I2 * invF.at(2, 2) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 8) = answer.at(2, 8) + ( 2. * C2 * ( 12. * FC.at(2, 2) * invF.at(3, 1) + 12. * FC.at(3, 1) * invF.at(2, 2) - 9. * F.at(2, 1) * F.at(3, 2) + 18 * F.at(2, 2) * F.at(3, 1) - 12. * F.at(2, 2) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(2, 2) + 6 * I2 * invF.at(1, 2) * invF.at(2, 3) - 8 * I2 * invF.at(1, 3) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 9) = answer.at(2, 9) - ( 2. * C2 * ( 9. * C.at(1, 2) - 12. * FC.at(2, 1) * invF.at(2, 2) - 12. * FC.at(2, 2) * invF.at(2, 1) - 9. * F.at(2, 1) * F.at(2, 2) + 12. * F.at(2, 1) * I1 * invF.at(2, 2) + 12. * F.at(2, 2) * I1 * invF.at(1, 2) + 2. * I2 * invF.at(1, 2) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - - - - - - answer.at(3, 1) = answer.at(3, 1) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(1, 1) + 18 * F.at(1, 1) * F.at(3, 3) - 9. * F.at(1, 3) * F.at(3, 1) - 12. * F.at(1, 1) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(1, 1) - 8 * I2 * invF.at(1, 1) * invF.at(3, 3) + 6 * I2 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 2) = answer.at(3, 2) + ( 2. * C2 * ( 12. * FC.at(2, 2) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(2, 2) + 18 * F.at(2, 2) * F.at(3, 3) - 9. * F.at(2, 3) * F.at(3, 2) - 12. * F.at(2, 2) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(2, 2) - 8 * I2 * invF.at(2, 2) * invF.at(3, 3) + 6 * I2 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 3) = answer.at(3, 3) + ( 2. * C2 * ( 9. * F.at(3, 3) * F.at(3, 3) - 24. * I1 * F.at(3, 3) * invF.at(3, 3) - 2. * I2 * invF.at(3, 3) * invF.at(3, 3) + 24. * FC.at(3, 3) * invF.at(3, 3) + 9. * B.at(3, 3) - 9. * C.at(3, 3) + 9. * I1 ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 4) = answer.at(3, 4) + ( 2. * C2 * ( 9. * B.at(3, 2) + 12. * FC.at(2, 3) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(2, 3) + 9. * F.at(2, 3) * F.at(3, 3) - 12. * F.at(2, 3) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(3, 2) - 2. * I2 * invF.at(3, 2) * invF.at(3, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 5) = answer.at(3, 5) + ( 2. * C2 * ( 9. * B.at(3, 1) + 12. * FC.at(1, 3) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(1, 3) + 9. * F.at(1, 3) * F.at(3, 3) - 12. * F.at(1, 3) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(3, 1) - 2. * I2 * invF.at(3, 1) * invF.at(3, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 6) = answer.at(3, 6) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(1, 2) + 18 * F.at(1, 2) * F.at(3, 3) - 9. * F.at(1, 3) * F.at(3, 2) - 12. * F.at(1, 2) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(2, 1) - 8 * I2 * invF.at(2, 1) * invF.at(3, 3) + 6 * I2 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 7) = answer.at(3, 7) - ( 2. * C2 * ( 9. * C.at(2, 3) - 12. * FC.at(3, 2) * invF.at(3, 3) - 12. * FC.at(3, 3) * invF.at(3, 2) - 9. * F.at(3, 2) * F.at(3, 3) + 12. * F.at(3, 2) * I1 * invF.at(3, 3) + 12. * F.at(3, 3) * I1 * invF.at(2, 3) + 2. * I2 * invF.at(2, 3) * invF.at(3, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 8) = answer.at(3, 8) - ( 2. * C2 * ( 9. * C.at(1, 3) - 12. * FC.at(3, 1) * invF.at(3, 3) - 12. * FC.at(3, 3) * invF.at(3, 1) - 9. * F.at(3, 1) * F.at(3, 3) + 12. * F.at(3, 1) * I1 * invF.at(3, 3) + 12. * F.at(3, 3) * I1 * invF.at(1, 3) + 2. * I2 * invF.at(1, 3) * invF.at(3, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 9) = answer.at(3, 9) + ( 2. * C2 * ( 12. * FC.at(2, 1) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(2, 1) + 18 * F.at(2, 1) * F.at(3, 3) - 9. * F.at(2, 3) * F.at(3, 1) - 12. * F.at(2, 1) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(1, 2) - 8 * I2 * invF.at(1, 2) * invF.at(3, 3) + 6 * I2 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - - - - answer.at(4, 1) = answer.at(4, 1) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(3, 2) + 12. * FC.at(2, 3) * invF.at(1, 1) + 18 * F.at(1, 1) * F.at(2, 3) - 9. * F.at(1, 3) * F.at(2, 1) - 12. * F.at(1, 1) * I1 * invF.at(3, 2) - 12. * F.at(2, 3) * I1 * invF.at(1, 1) - 8 * I2 * invF.at(1, 1) * invF.at(3, 2) + 6 * I2 * invF.at(1, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 2) = answer.at(4, 2) - ( 2. * C2 * ( 9. * C.at(2, 3) - 12. * FC.at(2, 2) * invF.at(3, 2) - 12. * FC.at(2, 3) * invF.at(2, 2) - 9. * F.at(2, 2) * F.at(2, 3) + 12. * F.at(2, 2) * I1 * invF.at(3, 2) + 12. * F.at(2, 3) * I1 * invF.at(2, 2) + 2. * I2 * invF.at(2, 2) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 3) = answer.at(4, 3) + ( 2. * C2 * ( 9. * B.at(2, 3) + 12. * FC.at(2, 3) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(3, 2) + 9. * F.at(2, 3) * F.at(3, 3) - 12. * F.at(2, 3) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(3, 2) - 2. * I2 * invF.at(3, 2) * invF.at(3, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 4) = answer.at(4, 4) + ( 2. * C2 * ( 9. * F.at(2, 3) * F.at(2, 3) - 24. * I1 * F.at(2, 3) * invF.at(3, 2) - 2. * I2 * invF.at(3, 2) * invF.at(3, 2) + 12. * FC.at(2, 3) * invF.at(3, 2) + 9. * B.at(2, 2) - 9. * C.at(3, 3) + 9. * I1 + 12. * FC.at(2, 3) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 5) = answer.at(4, 5) + ( 2. * C2 * ( 9. * B.at(2, 1) + 12. * FC.at(1, 3) * invF.at(3, 2) + 12. * FC.at(2, 3) * invF.at(1, 3) + 9. * F.at(1, 3) * F.at(2, 3) - 12. * F.at(1, 3) * I1 * invF.at(3, 2) - 12. * F.at(2, 3) * I1 * invF.at(3, 1) - 2. * I2 * invF.at(3, 1) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 6) = answer.at(4, 6) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(3, 2) + 12. * FC.at(2, 3) * invF.at(1, 2) + 18 * F.at(1, 2) * F.at(2, 3) - 9. * F.at(1, 3) * F.at(2, 2) - 12. * F.at(1, 2) * I1 * invF.at(3, 2) - 12. * F.at(2, 3) * I1 * invF.at(2, 1) - 8 * I2 * invF.at(2, 1) * invF.at(3, 2) + 6 * I2 * invF.at(2, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 7) = answer.at(4, 7) + ( 2. * C2 * ( 12. * FC.at(2, 3) * invF.at(3, 2) + 12. * FC.at(3, 2) * invF.at(3, 2) - 9. * F.at(2, 2) * F.at(3, 3) + 18 * F.at(2, 3) * F.at(3, 2) - 12. * F.at(2, 3) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(3, 2) + 6 * I2 * invF.at(2, 2) * invF.at(3, 3) - 8 * I2 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 8) = answer.at(4, 8) + ( 2. * C2 * ( 12. * FC.at(2, 3) * invF.at(3, 1) + 12. * FC.at(3, 1) * invF.at(3, 2) - 9. * F.at(2, 1) * F.at(3, 3) + 18 * F.at(2, 3) * F.at(3, 1) - 12. * F.at(2, 3) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(3, 2) + 6 * I2 * invF.at(1, 2) * invF.at(3, 3) - 8 * I2 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 9) = answer.at(4, 9) - ( 2. * C2 * ( 9. * C.at(1, 3) - 12. * FC.at(2, 1) * invF.at(3, 2) - 12. * FC.at(2, 3) * invF.at(2, 1) - 9. * F.at(2, 1) * F.at(2, 3) + 12. * F.at(2, 1) * I1 * invF.at(3, 2) + 12. * F.at(2, 3) * I1 * invF.at(1, 2) + 2. * I2 * invF.at(1, 2) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - - - answer.at(5, 1) = answer.at(5, 1) - ( 2. * C2 * ( 9. * C.at(1, 3) - 12. * FC.at(1, 1) * invF.at(3, 1) - 12. * FC.at(1, 3) * invF.at(1, 1) - 9. * F.at(1, 1) * F.at(1, 3) + 12. * F.at(1, 1) * I1 * invF.at(3, 1) + 12. * F.at(1, 3) * I1 * invF.at(1, 1) + 2. * I2 * invF.at(1, 1) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 2) = answer.at(5, 2) + ( 2. * C2 * ( 12. * FC.at(1, 3) * invF.at(2, 2) + 12. * FC.at(2, 2) * invF.at(3, 1) - 9. * F.at(1, 2) * F.at(2, 3) + 18 * F.at(1, 3) * F.at(2, 2) - 12. * F.at(1, 3) * I1 * invF.at(2, 2) - 12. * F.at(2, 2) * I1 * invF.at(3, 1) + 6 * I2 * invF.at(2, 1) * invF.at(3, 2) - 8 * I2 * invF.at(2, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 3) = answer.at(5, 3) + ( 2. * C2 * ( 9. * B.at(1, 3) + 12. * FC.at(1, 3) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(3, 1) + 9. * F.at(1, 3) * F.at(3, 3) - 12. * F.at(1, 3) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(3, 1) - 2. * I2 * invF.at(3, 1) * invF.at(3, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 4) = answer.at(5, 4) + ( 2. * C2 * ( 9. * B.at(1, 2) + 12. * FC.at(1, 3) * invF.at(2, 3) + 12. * FC.at(2, 3) * invF.at(3, 1) + 9. * F.at(1, 3) * F.at(2, 3) - 12. * F.at(1, 3) * I1 * invF.at(3, 2) - 12. * F.at(2, 3) * I1 * invF.at(3, 1) - 2. * I2 * invF.at(3, 1) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 5) = answer.at(5, 5) + ( 2. * C2 * ( 9. * F.at(1, 3) * F.at(1, 3) - 24. * I1 * F.at(1, 3) * invF.at(3, 1) - 2. * I2 * invF.at(3, 1) * invF.at(3, 1) + 12. * FC.at(1, 3) * invF.at(3, 1) + 9. * B.at(1, 1) - 9. * C.at(3, 3) + 9. * I1 + 12. * FC.at(1, 3) * invF.at(1, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 6) = answer.at(5, 6) - ( 2. * C2 * ( 9. * C.at(2, 3) - 12. * FC.at(1, 2) * invF.at(3, 1) - 12. * FC.at(1, 3) * invF.at(1, 2) - 9. * F.at(1, 2) * F.at(1, 3) + 12. * F.at(1, 2) * I1 * invF.at(3, 1) + 12. * F.at(1, 3) * I1 * invF.at(2, 1) + 2. * I2 * invF.at(2, 1) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 7) = answer.at(5, 7) + ( 2. * C2 * ( 12. * FC.at(1, 3) * invF.at(3, 2) + 12. * FC.at(3, 2) * invF.at(3, 1) - 9. * F.at(1, 2) * F.at(3, 3) + 18 * F.at(1, 3) * F.at(3, 2) - 12. * F.at(1, 3) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(3, 1) + 6 * I2 * invF.at(2, 1) * invF.at(3, 3) - 8 * I2 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 8) = answer.at(5, 8) + ( 2. * C2 * ( 12. * FC.at(1, 3) * invF.at(3, 1) + 12. * FC.at(3, 1) * invF.at(3, 1) - 9. * F.at(1, 1) * F.at(3, 3) + 18 * F.at(1, 3) * F.at(3, 1) - 12. * F.at(1, 3) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(3, 1) + 6 * I2 * invF.at(1, 1) * invF.at(3, 3) - 8 * I2 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 9) = answer.at(5, 9) + ( 2. * C2 * ( 12. * FC.at(1, 3) * invF.at(2, 1) + 12. * FC.at(2, 1) * invF.at(3, 1) - 9. * F.at(1, 1) * F.at(2, 3) + 18 * F.at(1, 3) * F.at(2, 1) - 12. * F.at(1, 3) * I1 * invF.at(1, 2) - 12. * F.at(2, 1) * I1 * invF.at(3, 1) + 6 * I2 * invF.at(1, 1) * invF.at(3, 2) - 8 * I2 * invF.at(1, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - - - - answer.at(6, 1) = answer.at(6, 1) - ( 2. * C2 * ( 9. * C.at(1, 2) - 12. * FC.at(1, 1) * invF.at(2, 1) - 12. * FC.at(1, 2) * invF.at(1, 1) - 9. * F.at(1, 1) * F.at(1, 2) + 12. * F.at(1, 1) * I1 * invF.at(2, 1) + 12. * F.at(1, 2) * I1 * invF.at(1, 1) + 2. * I2 * invF.at(1, 1) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(6, 2) = answer.at(6, 2) + ( 2. * C2 * ( 9. * B.at(1, 2) + 12. * FC.at(1, 2) * invF.at(2, 2) + 12. * FC.at(2, 2) * invF.at(2, 1) + 9. * F.at(1, 2) * F.at(2, 2) - 12. * F.at(1, 2) * I1 * invF.at(2, 2) - 12. * F.at(2, 2) * I1 * invF.at(2, 1) - 2. * I2 * invF.at(2, 1) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(6, 3) = answer.at(6, 3) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(2, 1) + 18 * F.at(1, 2) * F.at(3, 3) - 9. * F.at(1, 3) * F.at(3, 2) - 12. * F.at(1, 2) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(2, 1) - 8 * I2 * invF.at(2, 1) * invF.at(3, 3) + 6 * I2 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(6, 4) = answer.at(6, 4) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(2, 3) + 12. * FC.at(2, 3) * invF.at(2, 1) + 18 * F.at(1, 2) * F.at(2, 3) - 9. * F.at(1, 3) * F.at(2, 2) - 12. * F.at(1, 2) * I1 * invF.at(3, 2) - 12. * F.at(2, 3) * I1 * invF.at(2, 1) - 8 * I2 * invF.at(2, 1) * invF.at(3, 2) + 6 * I2 * invF.at(2, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(6, 5) = answer.at(6, 5) - ( 2. * C2 * ( 9. * C.at(3, 2) - 12. * FC.at(1, 2) * invF.at(1, 3) - 12. * FC.at(1, 3) * invF.at(2, 1) - 9. * F.at(1, 2) * F.at(1, 3) + 12. * F.at(1, 2) * I1 * invF.at(3, 1) + 12. * F.at(1, 3) * I1 * invF.at(2, 1) + 2. * I2 * invF.at(2, 1) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(6, 6) = answer.at(6, 6) + ( 2. * C2 * ( 9. * F.at(1, 2) * F.at(1, 2) - 24. * I1 * F.at(1, 2) * invF.at(2, 1) - 2. * I2 * invF.at(2, 1) * invF.at(2, 1) + 12. * FC.at(1, 2) * invF.at(2, 1) + 9. * B.at(1, 1) - 9. * C.at(2, 2) + 9. * I1 + 12. * FC.at(1, 2) * invF.at(1, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(6, 7) = answer.at(6, 7) + ( 2. * C2 * ( 9. * B.at(1, 3) + 12. * FC.at(1, 2) * invF.at(3, 2) + 12. * FC.at(3, 2) * invF.at(2, 1) + 9. * F.at(1, 2) * F.at(3, 2) - 12. * F.at(1, 2) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(2, 1) - 2. * I2 * invF.at(2, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(6, 8) = answer.at(6, 8) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(3, 1) + 12. * FC.at(3, 1) * invF.at(2, 1) - 9. * F.at(1, 1) * F.at(3, 2) + 18 * F.at(1, 2) * F.at(3, 1) - 12. * F.at(1, 2) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(2, 1) + 6 * I2 * invF.at(1, 1) * invF.at(2, 3) - 8 * I2 * invF.at(2, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(6, 9) = answer.at(6, 9) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(2, 1) + 12. * FC.at(2, 1) * invF.at(2, 1) - 9. * F.at(1, 1) * F.at(2, 2) + 18 * F.at(1, 2) * F.at(2, 1) - 12. * F.at(1, 2) * I1 * invF.at(1, 2) - 12. * F.at(2, 1) * I1 * invF.at(2, 1) + 6 * I2 * invF.at(1, 1) * invF.at(2, 2) - 8 * I2 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - - - - - answer.at(7, 1) = answer.at(7, 1) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(2, 3) + 12. * FC.at(3, 2) * invF.at(1, 1) + 18 * F.at(1, 1) * F.at(3, 2) - 9. * F.at(1, 2) * F.at(3, 1) - 12. * F.at(1, 1) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(1, 1) - 8 * I2 * invF.at(1, 1) * invF.at(2, 3) + 6 * I2 * invF.at(2, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(7, 2) = answer.at(7, 2) + ( 2. * C2 * ( 9. * B.at(3, 2) + 12. * FC.at(2, 2) * invF.at(2, 3) + 12. * FC.at(3, 2) * invF.at(2, 2) + 9. * F.at(2, 2) * F.at(3, 2) - 12. * F.at(2, 2) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(2, 2) - 2. * I2 * invF.at(2, 2) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(7, 3) = answer.at(7, 3) - ( 2. * C2 * ( 9. * C.at(3, 2) - 12. * FC.at(3, 2) * invF.at(3, 3) - 12. * FC.at(3, 3) * invF.at(2, 3) - 9. * F.at(3, 2) * F.at(3, 3) + 12. * F.at(3, 2) * I1 * invF.at(3, 3) + 12. * F.at(3, 3) * I1 * invF.at(2, 3) + 2. * I2 * invF.at(2, 3) * invF.at(3, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(7, 4) = answer.at(7, 4) + ( 2. * C2 * ( 12. * FC.at(2, 3) * invF.at(2, 3) + 12. * FC.at(3, 2) * invF.at(2, 3) - 9. * F.at(2, 2) * F.at(3, 3) + 18 * F.at(2, 3) * F.at(3, 2) - 12. * F.at(2, 3) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(3, 2) + 6 * I2 * invF.at(2, 2) * invF.at(3, 3) - 8 * I2 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(7, 5) = answer.at(7, 5) + ( 2. * C2 * ( 12. * FC.at(1, 3) * invF.at(2, 3) + 12. * FC.at(3, 2) * invF.at(1, 3) - 9. * F.at(1, 2) * F.at(3, 3) + 18 * F.at(1, 3) * F.at(3, 2) - 12. * F.at(1, 3) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(3, 1) + 6 * I2 * invF.at(2, 1) * invF.at(3, 3) - 8 * I2 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(7, 6) = answer.at(7, 6) + ( 2. * C2 * ( 9. * B.at(3, 1) + 12. * FC.at(1, 2) * invF.at(2, 3) + 12. * FC.at(3, 2) * invF.at(1, 2) + 9. * F.at(1, 2) * F.at(3, 2) - 12. * F.at(1, 2) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(2, 1) - 2. * I2 * invF.at(2, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(7, 7) = answer.at(7, 7) + ( 2. * C2 * ( 9. * F.at(3, 2) * F.at(3, 2) - 24. * I1 * F.at(3, 2) * invF.at(2, 3) - 2. * I2 * invF.at(2, 3) * invF.at(2, 3) + 12. * FC.at(3, 2) * invF.at(2, 3) + 9. * B.at(3, 3) - 9. * C.at(2, 2) + 9. * I1 + 12. * FC.at(3, 2) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(7, 8) = answer.at(7, 8) - ( 2. * C2 * ( 9. * C.at(1, 2) - 12. * FC.at(3, 1) * invF.at(2, 3) - 12. * FC.at(3, 2) * invF.at(3, 1) - 9. * F.at(3, 1) * F.at(3, 2) + 12. * F.at(3, 1) * I1 * invF.at(2, 3) + 12. * F.at(3, 2) * I1 * invF.at(1, 3) + 2. * I2 * invF.at(1, 3) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(7, 9) = answer.at(7, 9) + ( 2. * C2 * ( 12. * FC.at(2, 1) * invF.at(2, 3) + 12. * FC.at(3, 2) * invF.at(2, 1) + 18 * F.at(2, 1) * F.at(3, 2) - 9. * F.at(2, 2) * F.at(3, 1) - 12. * F.at(2, 1) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(1, 2) - 8 * I2 * invF.at(1, 2) * invF.at(2, 3) + 6 * I2 * invF.at(1, 3) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - - - - answer.at(8, 1) = answer.at(8, 1) + ( 2. * C2 * ( 9. * B.at(3, 1) + 12. * FC.at(1, 1) * invF.at(1, 3) + 12. * FC.at(3, 1) * invF.at(1, 1) + 9. * F.at(1, 1) * F.at(3, 1) - 12. * F.at(1, 1) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(1, 1) - 2. * I2 * invF.at(1, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(8, 2) = answer.at(8, 2) + ( 2. * C2 * ( 12. * FC.at(2, 2) * invF.at(1, 3) + 12. * FC.at(3, 1) * invF.at(2, 2) - 9. * F.at(2, 1) * F.at(3, 2) + 18 * F.at(2, 2) * F.at(3, 1) - 12. * F.at(2, 2) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(2, 2) + 6 * I2 * invF.at(1, 2) * invF.at(2, 3) - 8 * I2 * invF.at(1, 3) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(8, 3) = answer.at(8, 3) - ( 2. * C2 * ( 9. * C.at(3, 1) - 12. * FC.at(3, 1) * invF.at(3, 3) - 12. * FC.at(3, 3) * invF.at(1, 3) - 9. * F.at(3, 1) * F.at(3, 3) + 12. * F.at(3, 1) * I1 * invF.at(3, 3) + 12. * F.at(3, 3) * I1 * invF.at(1, 3) + 2. * I2 * invF.at(1, 3) * invF.at(3, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(8, 4) = answer.at(8, 4) + ( 2. * C2 * ( 12. * FC.at(2, 3) * invF.at(1, 3) + 12. * FC.at(3, 1) * invF.at(2, 3) - 9. * F.at(2, 1) * F.at(3, 3) + 18 * F.at(2, 3) * F.at(3, 1) - 12. * F.at(2, 3) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(3, 2) + 6 * I2 * invF.at(1, 2) * invF.at(3, 3) - 8 * I2 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(8, 5) = answer.at(8, 5) + ( 2. * C2 * ( 12. * FC.at(1, 3) * invF.at(1, 3) + 12. * FC.at(3, 1) * invF.at(1, 3) - 9. * F.at(1, 1) * F.at(3, 3) + 18 * F.at(1, 3) * F.at(3, 1) - 12. * F.at(1, 3) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(3, 1) + 6 * I2 * invF.at(1, 1) * invF.at(3, 3) - 8 * I2 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(8, 6) = answer.at(8, 6) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(1, 3) + 12. * FC.at(3, 1) * invF.at(1, 2) - 9. * F.at(1, 1) * F.at(3, 2) + 18 * F.at(1, 2) * F.at(3, 1) - 12. * F.at(1, 2) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(2, 1) + 6 * I2 * invF.at(1, 1) * invF.at(2, 3) - 8 * I2 * invF.at(2, 1) * invF.at(1, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(8, 7) = answer.at(8, 7) - ( 2. * C2 * ( 9. * C.at(2, 1) - 12. * FC.at(3, 1) * invF.at(3, 2) - 12. * FC.at(3, 2) * invF.at(1, 3) - 9. * F.at(3, 1) * F.at(3, 2) + 12. * F.at(3, 1) * I1 * invF.at(2, 3) + 12. * F.at(3, 2) * I1 * invF.at(1, 3) + 2. * I2 * invF.at(1, 3) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(8, 8) = answer.at(8, 8) + ( 2. * C2 * ( 9. * F.at(3, 1) * F.at(3, 1) - 24. * I1 * F.at(3, 1) * invF.at(1, 3) - 2. * I2 * invF.at(1, 3) * invF.at(1, 3) + 12. * FC.at(3, 1) * invF.at(1, 3) + 9. * B.at(3, 3) - 9. * C.at(1, 1) + 9. * I1 + 12. * FC.at(3, 1) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(8, 9) = answer.at(8, 9) + ( 2. * C2 * ( 9. * B.at(3, 2) + 12. * FC.at(2, 1) * invF.at(1, 3) + 12. * FC.at(3, 1) * invF.at(2, 1) + 9. * F.at(2, 1) * F.at(3, 1) - 12. * F.at(2, 1) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(1, 2) - 2. * I2 * invF.at(1, 2) * invF.at(1, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - - - - - answer.at(9, 1) = answer.at(9, 1) + ( 2. * C2 * ( 9. * B.at(2, 1) + 12. * FC.at(1, 1) * invF.at(1, 2) + 12. * FC.at(2, 1) * invF.at(1, 1) + 9. * F.at(1, 1) * F.at(2, 1) - 12. * F.at(1, 1) * I1 * invF.at(1, 2) - 12. * F.at(2, 1) * I1 * invF.at(1, 1) - 2. * I2 * invF.at(1, 1) * invF.at(1, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(9, 2) = answer.at(9, 2) - ( 2. * C2 * ( 9. * C.at(2, 1) - 12. * FC.at(2, 1) * invF.at(2, 2) - 12. * FC.at(2, 2) * invF.at(1, 2) - 9. * F.at(2, 1) * F.at(2, 2) + 12. * F.at(2, 1) * I1 * invF.at(2, 2) + 12. * F.at(2, 2) * I1 * invF.at(1, 2) + 2. * I2 * invF.at(1, 2) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(9, 3) = answer.at(9, 3) + ( 2. * C2 * ( 12. * FC.at(2, 1) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(1, 2) + 18 * F.at(2, 1) * F.at(3, 3) - 9. * F.at(2, 3) * F.at(3, 1) - 12. * F.at(2, 1) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(1, 2) - 8 * I2 * invF.at(1, 2) * invF.at(3, 3) + 6 * I2 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(9, 4) = answer.at(9, 4) - ( 2. * C2 * ( 9. * C.at(3, 1) - 12. * FC.at(2, 1) * invF.at(2, 3) - 12. * FC.at(2, 3) * invF.at(1, 2) - 9. * F.at(2, 1) * F.at(2, 3) + 12. * F.at(2, 1) * I1 * invF.at(3, 2) + 12. * F.at(2, 3) * I1 * invF.at(1, 2) + 2. * I2 * invF.at(1, 2) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(9, 5) = answer.at(9, 5) + ( 2. * C2 * ( 12. * FC.at(1, 3) * invF.at(1, 2) + 12. * FC.at(2, 1) * invF.at(1, 3) - 9. * F.at(1, 1) * F.at(2, 3) + 18 * F.at(1, 3) * F.at(2, 1) - 12. * F.at(1, 3) * I1 * invF.at(1, 2) - 12. * F.at(2, 1) * I1 * invF.at(3, 1) + 6 * I2 * invF.at(1, 1) * invF.at(3, 2) - 8 * I2 * invF.at(1, 2) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(9, 6) = answer.at(9, 6) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(1, 2) + 12. * FC.at(2, 1) * invF.at(1, 2) - 9. * F.at(1, 1) * F.at(2, 2) + 18 * F.at(1, 2) * F.at(2, 1) - 12. * F.at(1, 2) * I1 * invF.at(1, 2) - 12. * F.at(2, 1) * I1 * invF.at(2, 1) + 6 * I2 * invF.at(1, 1) * invF.at(2, 2) - 8 * I2 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(9, 7) = answer.at(9, 7) + ( 2. * C2 * ( 12. * FC.at(2, 1) * invF.at(3, 2) + 12. * FC.at(3, 2) * invF.at(1, 2) + 18 * F.at(2, 1) * F.at(3, 2) - 9. * F.at(2, 2) * F.at(3, 1) - 12. * F.at(2, 1) * I1 * invF.at(2, 3) - 12. * F.at(3, 2) * I1 * invF.at(1, 2) - 8 * I2 * invF.at(1, 2) * invF.at(2, 3) + 6 * I2 * invF.at(1, 3) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(9, 8) = answer.at(9, 8) + ( 2. * C2 * ( 9. * B.at(2, 3) + 12. * FC.at(2, 1) * invF.at(3, 1) + 12. * FC.at(3, 1) * invF.at(1, 2) + 9. * F.at(2, 1) * F.at(3, 1) - 12. * F.at(2, 1) * I1 * invF.at(1, 3) - 12. * F.at(3, 1) * I1 * invF.at(1, 2) - 2. * I2 * invF.at(1, 2) * invF.at(1, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(9, 9) = answer.at(9, 9) + ( 2. * C2 * ( 9. * F.at(2, 1) * F.at(2, 1) - 24. * I1 * F.at(2, 1) * invF.at(1, 2) - 2. * I2 * invF.at(1, 2) * invF.at(1, 2) + 12. * FC.at(2, 1) * invF.at(1, 2) + 9. * B.at(2, 2) - 9. * C.at(1, 1) + 9. * I1 + 12. * FC.at(2, 1) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - - /////////////////////////////////////////////////////////////////////////////////////////////////// - - - - - - answer.at(1, 1) = answer.at(1, 1) - K *invF.at(1, 1) * invF.at(1, 1) * ( lnJ - 1. ); - answer.at(1, 2) = answer.at(1, 2) + K * ( invF.at(1, 1) * invF.at(2, 2) - invF.at(1, 2) * invF.at(2, 1) * lnJ ); - answer.at(1, 3) = answer.at(1, 3) + K * ( invF.at(1, 1) * invF.at(3, 3) - invF.at(1, 3) * invF.at(3, 1) * lnJ ); - answer.at(1, 4) = answer.at(1, 4) + K * ( invF.at(1, 1) * invF.at(3, 2) - invF.at(1, 2) * invF.at(3, 1) * lnJ ); - answer.at(1, 5) = answer.at(1, 5) - K *invF.at(1, 1) * invF.at(3, 1) * ( lnJ - 1. ); - answer.at(1, 6) = answer.at(1, 6) - K *invF.at(1, 1) * invF.at(2, 1) * ( lnJ - 1. ); - answer.at(1, 7) = answer.at(1, 7) + K * ( invF.at(1, 1) * invF.at(2, 3) - invF.at(2, 1) * invF.at(1, 3) * lnJ ); - answer.at(1, 8) = answer.at(1, 8) - K *invF.at(1, 1) * invF.at(1, 3) * ( lnJ - 1. ); - answer.at(1, 9) = answer.at(1, 9) - K *invF.at(1, 1) * invF.at(1, 2) * ( lnJ - 1. ); - - - - - answer.at(2, 1) = answer.at(2, 1) + K * ( invF.at(1, 1) * invF.at(2, 2) - invF.at(1, 2) * invF.at(2, 1) * lnJ ); - answer.at(2, 2) = answer.at(2, 2) - K *invF.at(2, 2) * invF.at(2, 2) * ( lnJ - 1. ); - answer.at(2, 3) = answer.at(2, 3) + K * ( invF.at(2, 2) * invF.at(3, 3) - invF.at(2, 3) * invF.at(3, 2) * lnJ ); - answer.at(2, 4) = answer.at(2, 4) - K *invF.at(2, 2) * invF.at(3, 2) * ( lnJ - 1. ); - answer.at(2, 5) = answer.at(2, 5) + K * ( invF.at(2, 2) * invF.at(3, 1) - invF.at(2, 1) * invF.at(3, 2) * lnJ ); - answer.at(2, 6) = answer.at(2, 6) - K *invF.at(2, 1) * invF.at(2, 2) * ( lnJ - 1. ); - answer.at(2, 7) = answer.at(2, 7) - K *invF.at(2, 2) * invF.at(2, 3) * ( lnJ - 1. ); - answer.at(2, 8) = answer.at(2, 8) + K * ( invF.at(1, 3) * invF.at(2, 2) - invF.at(1, 2) * invF.at(2, 3) * lnJ ); - answer.at(2, 9) = answer.at(2, 9) - K *invF.at(1, 2) * invF.at(2, 2) * ( lnJ - 1. ); - - - - - answer.at(3, 1) = answer.at(3, 1) + K * ( invF.at(1, 1) * invF.at(3, 3) - invF.at(1, 3) * invF.at(3, 1) * lnJ ); - answer.at(3, 2) = answer.at(3, 2) + K * ( invF.at(2, 2) * invF.at(3, 3) - invF.at(2, 3) * invF.at(3, 2) * lnJ ); - answer.at(3, 3) = answer.at(3, 3) - K *invF.at(3, 3) * invF.at(3, 3) * ( lnJ - 1. ); - answer.at(3, 4) = answer.at(3, 4) - K *invF.at(3, 2) * invF.at(3, 3) * ( lnJ - 1. ); - answer.at(3, 5) = answer.at(3, 5) - K *invF.at(3, 1) * invF.at(3, 3) * ( lnJ - 1. ); - answer.at(3, 6) = answer.at(3, 6) + K * ( invF.at(2, 1) * invF.at(3, 3) - invF.at(3, 1) * invF.at(2, 3) * lnJ ); - answer.at(3, 7) = answer.at(3, 7) - K *invF.at(2, 3) * invF.at(3, 3) * ( lnJ - 1. ); - answer.at(3, 8) = answer.at(3, 8) - K *invF.at(1, 3) * invF.at(3, 3) * ( lnJ - 1. ); - answer.at(3, 9) = answer.at(3, 9) + K * ( invF.at(1, 2) * invF.at(3, 3) - invF.at(1, 3) * invF.at(3, 2) * lnJ ); - - - - - answer.at(4, 1) = answer.at(4, 1) + K * ( invF.at(1, 1) * invF.at(3, 2) - invF.at(1, 2) * invF.at(3, 1) * lnJ ); - answer.at(4, 2) = answer.at(4, 2) - K *invF.at(2, 2) * invF.at(3, 2) * ( lnJ - 1. ); - answer.at(4, 3) = answer.at(4, 3) - K *invF.at(3, 2) * invF.at(3, 3) * ( lnJ - 1. ); - answer.at(4, 4) = answer.at(4, 4) - K *invF.at(3, 2) * invF.at(3, 2) * ( lnJ - 1. ); - answer.at(4, 5) = answer.at(4, 5) - K *invF.at(3, 1) * invF.at(3, 2) * ( lnJ - 1. ); - answer.at(4, 6) = answer.at(4, 6) + K * ( invF.at(2, 1) * invF.at(3, 2) - invF.at(2, 2) * invF.at(3, 1) * lnJ ); - answer.at(4, 7) = answer.at(4, 7) + K * ( invF.at(2, 3) * invF.at(3, 2) - invF.at(2, 2) * invF.at(3, 3) * lnJ ); - answer.at(4, 8) = answer.at(4, 8) + K * ( invF.at(1, 3) * invF.at(3, 2) - invF.at(1, 2) * invF.at(3, 3) * lnJ ); - answer.at(4, 9) = answer.at(4, 9) - K *invF.at(1, 2) * invF.at(3, 2) * ( lnJ - 1. ); - - - - answer.at(5, 1) = answer.at(5, 1) - K *invF.at(1, 1) * invF.at(3, 1) * ( lnJ - 1. ); - answer.at(5, 2) = answer.at(5, 2) + K * ( invF.at(2, 2) * invF.at(3, 1) - invF.at(2, 1) * invF.at(3, 2) * lnJ ); - answer.at(5, 3) = answer.at(5, 3) - K *invF.at(3, 1) * invF.at(3, 3) * ( lnJ - 1. ); - answer.at(5, 4) = answer.at(5, 4) - K *invF.at(3, 1) * invF.at(3, 2) * ( lnJ - 1. ); - answer.at(5, 5) = answer.at(5, 5) - K *invF.at(3, 1) * invF.at(3, 1) * ( lnJ - 1. ); - answer.at(5, 6) = answer.at(5, 6) - K *invF.at(2, 1) * invF.at(3, 1) * ( lnJ - 1. ); - answer.at(5, 7) = answer.at(5, 7) + K * ( invF.at(3, 1) * invF.at(2, 3) - invF.at(2, 1) * invF.at(3, 3) * lnJ ); - answer.at(5, 8) = answer.at(5, 8) + K * ( invF.at(1, 3) * invF.at(3, 1) - invF.at(1, 1) * invF.at(3, 3) * lnJ ); - answer.at(5, 9) = answer.at(5, 9) + K * ( invF.at(1, 2) * invF.at(3, 1) - invF.at(1, 1) * invF.at(3, 2) * lnJ ); - - - - - answer.at(6, 1) = answer.at(6, 1) - K *invF.at(1, 1) * invF.at(2, 1) * ( lnJ - 1. ); - answer.at(6, 2) = answer.at(6, 2) - K *invF.at(2, 1) * invF.at(2, 2) * ( lnJ - 1. ); - answer.at(6, 3) = answer.at(6, 3) + K * ( invF.at(2, 1) * invF.at(3, 3) - invF.at(3, 1) * invF.at(2, 3) * lnJ ); - answer.at(6, 4) = answer.at(6, 4) + K * ( invF.at(2, 1) * invF.at(3, 2) - invF.at(2, 2) * invF.at(3, 1) * lnJ ); - answer.at(6, 5) = answer.at(6, 5) - K *invF.at(2, 1) * invF.at(3, 1) * ( lnJ - 1. ); - answer.at(6, 6) = answer.at(6, 6) - K *invF.at(2, 1) * invF.at(2, 1) * ( lnJ - 1. ); - answer.at(6, 7) = answer.at(6, 7) - K *invF.at(2, 1) * invF.at(2, 3) * ( lnJ - 1. ); - answer.at(6, 8) = answer.at(6, 8) + K * ( invF.at(2, 1) * invF.at(1, 3) - invF.at(1, 1) * invF.at(2, 3) * lnJ ); - answer.at(6, 9) = answer.at(6, 9) + K * ( invF.at(1, 2) * invF.at(2, 1) - invF.at(1, 1) * invF.at(2, 2) * lnJ ); - - - - - - answer.at(7, 1) = answer.at(7, 1) + K * ( invF.at(1, 1) * invF.at(2, 3) - invF.at(2, 1) * invF.at(1, 3) * lnJ ); - answer.at(7, 2) = answer.at(7, 2) - K *invF.at(2, 2) * invF.at(2, 3) * ( lnJ - 1. ); - answer.at(7, 3) = answer.at(7, 3) - K *invF.at(2, 3) * invF.at(3, 3) * ( lnJ - 1. ); - answer.at(7, 4) = answer.at(7, 4) + K * ( invF.at(2, 3) * invF.at(3, 2) - invF.at(2, 2) * invF.at(3, 3) * lnJ ); - answer.at(7, 5) = answer.at(7, 5) + K * ( invF.at(3, 1) * invF.at(2, 3) - invF.at(2, 1) * invF.at(3, 3) * lnJ ); - answer.at(7, 6) = answer.at(7, 6) - K *invF.at(2, 1) * invF.at(2, 3) * ( lnJ - 1. ); - answer.at(7, 7) = answer.at(7, 7) - K *invF.at(2, 3) * invF.at(2, 3) * ( lnJ - 1. ); - answer.at(7, 8) = answer.at(7, 8) - K *invF.at(1, 3) * invF.at(2, 3) * ( lnJ - 1. ); - answer.at(7, 9) = answer.at(7, 9) + K * ( invF.at(1, 2) * invF.at(2, 3) - invF.at(1, 3) * invF.at(2, 2) * lnJ ); - - - - - answer.at(8, 1) = answer.at(8, 1) - K *invF.at(1, 1) * invF.at(1, 3) * ( lnJ - 1. ); - answer.at(8, 2) = answer.at(8, 2) + K * ( invF.at(1, 3) * invF.at(2, 2) - invF.at(1, 2) * invF.at(2, 3) * lnJ ); - answer.at(8, 3) = answer.at(8, 3) - K *invF.at(1, 3) * invF.at(3, 3) * ( lnJ - 1. ); - answer.at(8, 4) = answer.at(8, 4) + K * ( invF.at(1, 3) * invF.at(3, 2) - invF.at(1, 2) * invF.at(3, 3) * lnJ ); - answer.at(8, 5) = answer.at(8, 5) + K * ( invF.at(1, 3) * invF.at(3, 1) - invF.at(1, 1) * invF.at(3, 3) * lnJ ); - answer.at(8, 6) = answer.at(8, 6) + K * ( invF.at(2, 1) * invF.at(1, 3) - invF.at(1, 1) * invF.at(2, 3) * lnJ ); - answer.at(8, 7) = answer.at(8, 7) - K *invF.at(1, 3) * invF.at(2, 3) * ( lnJ - 1. ); - answer.at(8, 8) = answer.at(8, 8) - K *invF.at(1, 3) * invF.at(1, 3) * ( lnJ - 1. ); - answer.at(8, 9) = answer.at(8, 9) - K *invF.at(1, 2) * invF.at(1, 3) * ( lnJ - 1. ); - - - - - - answer.at(9, 1) = answer.at(9, 1) - K *invF.at(1, 1) * invF.at(1, 2) * ( lnJ - 1. ); - answer.at(9, 2) = answer.at(9, 2) - K *invF.at(1, 2) * invF.at(2, 2) * ( lnJ - 1. ); - answer.at(9, 3) = answer.at(9, 3) + K * ( invF.at(1, 2) * invF.at(3, 3) - invF.at(1, 3) * invF.at(3, 2) * lnJ ); - answer.at(9, 4) = answer.at(9, 4) - K *invF.at(1, 2) * invF.at(3, 2) * ( lnJ - 1. ); - answer.at(9, 5) = answer.at(9, 5) + K * ( invF.at(1, 2) * invF.at(3, 1) - invF.at(1, 1) * invF.at(3, 2) * lnJ ); - answer.at(9, 6) = answer.at(9, 6) + K * ( invF.at(1, 2) * invF.at(2, 1) - invF.at(1, 1) * invF.at(2, 2) * lnJ ); - answer.at(9, 7) = answer.at(9, 7) + K * ( invF.at(1, 2) * invF.at(2, 3) - invF.at(1, 3) * invF.at(2, 2) * lnJ ); - answer.at(9, 8) = answer.at(9, 8) - K *invF.at(1, 2) * invF.at(1, 3) * ( lnJ - 1. ); - answer.at(9, 9) = answer.at(9, 9) - K *invF.at(1, 2) * invF.at(1, 2) * ( lnJ - 1. ); -} - - - -void -MooneyRivlinMaterial :: givePlaneStrainStiffMtrx_dPdF(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) -{ - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - - double I1, I2, J, lnJ; - FloatMatrix C, CC, invF, FC, B; - - - FloatArray vF = status->giveTempFVector(); - FloatMatrix F = { { vF.at(1), vF.at(5), 0 }, { vF.at(4), vF.at(2), 0 }, { 0, 0, vF.at(3) } }; - C.beTProductOf(F, F); - CC.beProductOf(C, C); - B.beProductTOf(F, F); - invF.beInverseOf(F); - FC.beProductOf(F, C); - - J = F.giveDeterminant(); - lnJ = log(J); - I1 = C.at(1, 1) + C.at(2, 2) + C.at(3, 3); - - I2 = 0.5 * ( I1 * I1 - CC.at(1, 1) - CC.at(2, 2) - CC.at(3, 3) ); - - answer.resize(5, 5); - - answer.at(1, 1) = ( 2. * C1 * ( 5. * I1 * invF.at(1, 1) * invF.at(1, 1) - 12. * F.at(1, 1) * invF.at(1, 1) + 9. ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 2) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(2, 2) - 3. * I1 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 3) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(3, 3) - 3. * I1 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 4) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(2, 1) + 6. * F.at(1, 2) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(1, 5) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(1, 2) + 6. * F.at(2, 1) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(1, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - - answer.at(2, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(2, 2) - 3. * I1 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 2) = ( 2. * C1 * ( 5. * I1 * invF.at(2, 2) * invF.at(2, 2) - 12. * F.at(2, 2) * invF.at(2, 2) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 3) = -( 2. * C1 * ( 6. * F.at(2, 2) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(2, 2) - 2. * I1 * invF.at(2, 2) * invF.at(3, 3) - 3. * I1 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 4) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(2, 1) - 5. * I1 * invF.at(2, 1) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(2, 5) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(1, 2) - 5. * I1 * invF.at(1, 2) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - - - answer.at(3, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(1, 1) - 2. * I1 * invF.at(1, 1) * invF.at(3, 3) - 3. * I1 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 2) = -( 2. * C1 * ( 6. * F.at(2, 2) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(2, 2) - 2. * I1 * invF.at(2, 2) * invF.at(3, 3) - 3. * I1 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 3) = ( 2. * C1 * ( 5. * I1 * invF.at(3, 3) * invF.at(3, 3) - 12. * F.at(3, 3) * invF.at(3, 3) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 4) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(2, 1) - 2. * I1 * invF.at(2, 1) * invF.at(3, 3) - 3. * I1 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(3, 5) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(1, 2) - 2. * I1 * invF.at(1, 2) * invF.at(3, 3) - 3. * I1 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - - answer.at(4, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(2, 1) + 6. * F.at(1, 2) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 2) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(2, 1) - 5. * I1 * invF.at(2, 1) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 3) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(2, 1) - 2. * I1 * invF.at(2, 1) * invF.at(3, 3) - 3. * I1 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 4) = ( 2. * C1 * ( 5. * I1 * invF.at(2, 1) * invF.at(2, 1) - 12. * F.at(1, 2) * invF.at(2, 1) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(4, 5) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(1, 2) + 6. * F.at(2, 1) * invF.at(2, 1) - 3. * I1 * invF.at(1, 1) * invF.at(2, 2) - 2. * I1 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - - - answer.at(5, 1) = -( 2. * C1 * ( 6. * F.at(1, 1) * invF.at(1, 2) + 6. * F.at(2, 1) * invF.at(1, 1) - 5. * I1 * invF.at(1, 1) * invF.at(1, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 2) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(2, 2) + 6. * F.at(2, 2) * invF.at(1, 2) - 5. * I1 * invF.at(1, 2) * invF.at(2, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 3) = -( 2. * C1 * ( 6. * F.at(2, 1) * invF.at(3, 3) + 6. * F.at(3, 3) * invF.at(1, 2) - 2. * I1 * invF.at(1, 2) * invF.at(3, 3) - 3. * I1 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 4) = -( 2. * C1 * ( 6. * F.at(1, 2) * invF.at(1, 2) + 6. * F.at(2, 1) * invF.at(2, 1) - 3. * I1 * invF.at(1, 1) * invF.at(2, 2) - 2. * I1 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 2. / 3.) ); - answer.at(5, 5) = ( 2. * C1 * ( 5. * I1 * invF.at(1, 2) * invF.at(1, 2) - 12. * F.at(2, 1) * invF.at(1, 2) + 9 ) ) / ( 9. * pow(J, 2. / 3.) ); - - - - /////////////////////////////////////////////////////////////////////////// - - - answer.at(1, 1) = answer.at(1, 1) + ( 2. * C2 * ( 9. * F.at(1, 1) * F.at(1, 1) - 24. * I1 * F.at(1, 1) * invF.at(1, 1) - 2. * I2 * invF.at(1, 1) * invF.at(1, 1) + 24. * FC.at(1, 1) * invF.at(1, 1) + 9. * B.at(1, 1) - 9. * C.at(1, 1) + 9. * I1 ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 2) = answer.at(1, 2) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(2, 2) + 12. * FC.at(2, 2) * invF.at(1, 1) + 18. * F.at(1, 1) * F.at(2, 2) - 9. * F.at(1, 2) * F.at(2, 1) - 12. * F.at(1, 1) * I1 * invF.at(2, 2) - 12. * F.at(2, 2) * I1 * invF.at(1, 1) - 8. * I2 * invF.at(1, 1) * invF.at(2, 2) + 6. * I2 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 3) = answer.at(1, 3) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(1, 1) + 18 * F.at(1, 1) * F.at(3, 3) - 9. * F.at(1, 3) * F.at(3, 1) - 12. * F.at(1, 1) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(1, 1) - 8. * I2 * invF.at(1, 1) * invF.at(3, 3) + 6 * I2 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 4) = answer.at(1, 4) - ( 2. * C2 * ( 9. * C.at(2, 1) - 12. * FC.at(1, 1) * invF.at(1, 2) - 12. * FC.at(1, 2) * invF.at(1, 1) - 9. * F.at(1, 1) * F.at(1, 2) + 12. * F.at(1, 1) * I1 * invF.at(2, 1) + 12. * F.at(1, 2) * I1 * invF.at(1, 1) + 2. * I2 * invF.at(1, 1) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(1, 5) = answer.at(1, 5) + ( 2. * C2 * ( 9. * B.at(1, 2) + 12. * FC.at(1, 1) * invF.at(2, 1) + 12. * FC.at(2, 1) * invF.at(1, 1) + 9. * F.at(1, 1) * F.at(2, 1) - 12. * F.at(1, 1) * I1 * invF.at(1, 2) - 12. * F.at(2, 1) * I1 * invF.at(1, 1) - 2. * I2 * invF.at(1, 1) * invF.at(1, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - - answer.at(2, 1) = answer.at(2, 1) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(2, 2) + 12. * FC.at(2, 2) * invF.at(1, 1) + 18 * F.at(1, 1) * F.at(2, 2) - 9. * F.at(1, 2) * F.at(2, 1) - 12. * F.at(1, 1) * I1 * invF.at(2, 2) - 12. * F.at(2, 2) * I1 * invF.at(1, 1) - 8 * I2 * invF.at(1, 1) * invF.at(2, 2) + 6 * I2 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 2) = answer.at(2, 2) + ( 2. * C2 * ( 9. * F.at(2, 2) * F.at(2, 2) - 24. * I1 * F.at(2, 2) * invF.at(2, 2) - 2. * I2 * invF.at(2, 2) * invF.at(2, 2) + 24. * FC.at(2, 2) * invF.at(2, 2) + 9. * B.at(2, 2) - 9. * C.at(2, 2) + 9. * I1 ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 3) = answer.at(2, 3) + ( 2. * C2 * ( 12. * FC.at(2, 2) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(2, 2) + 18 * F.at(2, 2) * F.at(3, 3) - 9. * F.at(2, 3) * F.at(3, 2) - 12. * F.at(2, 2) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(2, 2) - 8 * I2 * invF.at(2, 2) * invF.at(3, 3) + 6 * I2 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 4) = answer.at(2, 4) + ( 2. * C2 * ( 9. * B.at(2, 1) + 12. * FC.at(1, 2) * invF.at(2, 2) + 12. * FC.at(2, 2) * invF.at(1, 2) + 9. * F.at(1, 2) * F.at(2, 2) - 12. * F.at(1, 2) * I1 * invF.at(2, 2) - 12. * F.at(2, 2) * I1 * invF.at(2, 1) - 2. * I2 * invF.at(2, 1) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(2, 5) = answer.at(2, 5) - ( 2. * C2 * ( 9. * C.at(1, 2) - 12. * FC.at(2, 1) * invF.at(2, 2) - 12. * FC.at(2, 2) * invF.at(2, 1) - 9. * F.at(2, 1) * F.at(2, 2) + 12. * F.at(2, 1) * I1 * invF.at(2, 2) + 12. * F.at(2, 2) * I1 * invF.at(1, 2) + 2. * I2 * invF.at(1, 2) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - - answer.at(3, 1) = answer.at(3, 1) + ( 2. * C2 * ( 12. * FC.at(1, 1) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(1, 1) + 18 * F.at(1, 1) * F.at(3, 3) - 9. * F.at(1, 3) * F.at(3, 1) - 12. * F.at(1, 1) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(1, 1) - 8 * I2 * invF.at(1, 1) * invF.at(3, 3) + 6 * I2 * invF.at(1, 3) * invF.at(3, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 2) = answer.at(3, 2) + ( 2. * C2 * ( 12. * FC.at(2, 2) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(2, 2) + 18 * F.at(2, 2) * F.at(3, 3) - 9. * F.at(2, 3) * F.at(3, 2) - 12. * F.at(2, 2) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(2, 2) - 8 * I2 * invF.at(2, 2) * invF.at(3, 3) + 6 * I2 * invF.at(2, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 3) = answer.at(3, 3) + ( 2. * C2 * ( 9. * F.at(3, 3) * F.at(3, 3) - 24. * I1 * F.at(3, 3) * invF.at(3, 3) - 2. * I2 * invF.at(3, 3) * invF.at(3, 3) + 24. * FC.at(3, 3) * invF.at(3, 3) + 9. * B.at(3, 3) - 9. * C.at(3, 3) + 9. * I1 ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 4) = answer.at(3, 4) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(1, 2) + 18 * F.at(1, 2) * F.at(3, 3) - 9. * F.at(1, 3) * F.at(3, 2) - 12. * F.at(1, 2) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(2, 1) - 8 * I2 * invF.at(2, 1) * invF.at(3, 3) + 6 * I2 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(3, 5) = answer.at(3, 5) + ( 2. * C2 * ( 12. * FC.at(2, 1) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(2, 1) + 18 * F.at(2, 1) * F.at(3, 3) - 9. * F.at(2, 3) * F.at(3, 1) - 12. * F.at(2, 1) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(1, 2) - 8 * I2 * invF.at(1, 2) * invF.at(3, 3) + 6 * I2 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - - - answer.at(4, 1) = answer.at(4, 1) - ( 2. * C2 * ( 9. * C.at(1, 2) - 12. * FC.at(1, 1) * invF.at(2, 1) - 12. * FC.at(1, 2) * invF.at(1, 1) - 9. * F.at(1, 1) * F.at(1, 2) + 12. * F.at(1, 1) * I1 * invF.at(2, 1) + 12. * F.at(1, 2) * I1 * invF.at(1, 1) + 2. * I2 * invF.at(1, 1) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 2) = answer.at(4, 2) + ( 2. * C2 * ( 9. * B.at(1, 2) + 12. * FC.at(1, 2) * invF.at(2, 2) + 12. * FC.at(2, 2) * invF.at(2, 1) + 9. * F.at(1, 2) * F.at(2, 2) - 12. * F.at(1, 2) * I1 * invF.at(2, 2) - 12. * F.at(2, 2) * I1 * invF.at(2, 1) - 2. * I2 * invF.at(2, 1) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 3) = answer.at(4, 3) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(2, 1) + 18 * F.at(1, 2) * F.at(3, 3) - 9. * F.at(1, 3) * F.at(3, 2) - 12. * F.at(1, 2) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(2, 1) - 8 * I2 * invF.at(2, 1) * invF.at(3, 3) + 6 * I2 * invF.at(3, 1) * invF.at(2, 3) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 4) = answer.at(4, 4) + ( 2. * C2 * ( 9. * F.at(1, 2) * F.at(1, 2) - 24. * I1 * F.at(1, 2) * invF.at(2, 1) - 2. * I2 * invF.at(2, 1) * invF.at(2, 1) + 12. * FC.at(1, 2) * invF.at(2, 1) + 9. * B.at(1, 1) - 9. * C.at(2, 2) + 9. * I1 + 12. * FC.at(1, 2) * invF.at(1, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(4, 5) = answer.at(4, 5) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(2, 1) + 12. * FC.at(2, 1) * invF.at(2, 1) - 9. * F.at(1, 1) * F.at(2, 2) + 18 * F.at(1, 2) * F.at(2, 1) - 12. * F.at(1, 2) * I1 * invF.at(1, 2) - 12. * F.at(2, 1) * I1 * invF.at(2, 1) + 6 * I2 * invF.at(1, 1) * invF.at(2, 2) - 8 * I2 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - - - - answer.at(5, 1) = answer.at(5, 1) + ( 2. * C2 * ( 9. * B.at(2, 1) + 12. * FC.at(1, 1) * invF.at(1, 2) + 12. * FC.at(2, 1) * invF.at(1, 1) + 9. * F.at(1, 1) * F.at(2, 1) - 12. * F.at(1, 1) * I1 * invF.at(1, 2) - 12. * F.at(2, 1) * I1 * invF.at(1, 1) - 2. * I2 * invF.at(1, 1) * invF.at(1, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 2) = answer.at(5, 2) - ( 2. * C2 * ( 9. * C.at(2, 1) - 12. * FC.at(2, 1) * invF.at(2, 2) - 12. * FC.at(2, 2) * invF.at(1, 2) - 9. * F.at(2, 1) * F.at(2, 2) + 12. * F.at(2, 1) * I1 * invF.at(2, 2) + 12. * F.at(2, 2) * I1 * invF.at(1, 2) + 2. * I2 * invF.at(1, 2) * invF.at(2, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 3) = answer.at(5, 3) + ( 2. * C2 * ( 12. * FC.at(2, 1) * invF.at(3, 3) + 12. * FC.at(3, 3) * invF.at(1, 2) + 18 * F.at(2, 1) * F.at(3, 3) - 9. * F.at(2, 3) * F.at(3, 1) - 12. * F.at(2, 1) * I1 * invF.at(3, 3) - 12. * F.at(3, 3) * I1 * invF.at(1, 2) - 8 * I2 * invF.at(1, 2) * invF.at(3, 3) + 6 * I2 * invF.at(1, 3) * invF.at(3, 2) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 4) = answer.at(5, 4) + ( 2. * C2 * ( 12. * FC.at(1, 2) * invF.at(1, 2) + 12. * FC.at(2, 1) * invF.at(1, 2) - 9. * F.at(1, 1) * F.at(2, 2) + 18 * F.at(1, 2) * F.at(2, 1) - 12. * F.at(1, 2) * I1 * invF.at(1, 2) - 12. * F.at(2, 1) * I1 * invF.at(2, 1) + 6 * I2 * invF.at(1, 1) * invF.at(2, 2) - 8 * I2 * invF.at(1, 2) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - answer.at(5, 5) = answer.at(5, 5) + ( 2. * C2 * ( 9. * F.at(2, 1) * F.at(2, 1) - 24. * I1 * F.at(2, 1) * invF.at(1, 2) - 2. * I2 * invF.at(1, 2) * invF.at(1, 2) + 12. * FC.at(2, 1) * invF.at(1, 2) + 9. * B.at(2, 2) - 9. * C.at(1, 1) + 9. * I1 + 12. * FC.at(2, 1) * invF.at(2, 1) ) ) / ( 9. * pow(J, 4. / 3.) ); - - /////////////////////////////////////////////////////////////////////////////////////////////////// - answer.at(1, 1) = answer.at(1, 1) - K *invF.at(1, 1) * invF.at(1, 1) * ( lnJ - 1. ); - answer.at(1, 2) = answer.at(1, 2) + K * ( invF.at(1, 1) * invF.at(2, 2) - invF.at(1, 2) * invF.at(2, 1) * lnJ ); - answer.at(1, 3) = answer.at(1, 3) + K * ( invF.at(1, 1) * invF.at(3, 3) - invF.at(1, 3) * invF.at(3, 1) * lnJ ); - answer.at(1, 4) = answer.at(1, 4) - K *invF.at(1, 1) * invF.at(2, 1) * ( lnJ - 1. ); - answer.at(1, 5) = answer.at(1, 5) - K *invF.at(1, 1) * invF.at(1, 2) * ( lnJ - 1. ); - - answer.at(2, 1) = answer.at(2, 1) + K * ( invF.at(1, 1) * invF.at(2, 2) - invF.at(1, 2) * invF.at(2, 1) * lnJ ); - answer.at(2, 2) = answer.at(2, 2) - K *invF.at(2, 2) * invF.at(2, 2) * ( lnJ - 1. ); - answer.at(2, 3) = answer.at(2, 3) + K * ( invF.at(2, 2) * invF.at(3, 3) - invF.at(2, 3) * invF.at(3, 2) * lnJ ); - answer.at(2, 4) = answer.at(2, 4) - K *invF.at(2, 1) * invF.at(2, 2) * ( lnJ - 1. ); - answer.at(2, 5) = answer.at(2, 5) - K *invF.at(1, 2) * invF.at(2, 2) * ( lnJ - 1. ); - - answer.at(3, 1) = answer.at(3, 1) + K * ( invF.at(1, 1) * invF.at(3, 3) - invF.at(1, 3) * invF.at(3, 1) * lnJ ); - answer.at(3, 2) = answer.at(3, 2) + K * ( invF.at(2, 2) * invF.at(3, 3) - invF.at(2, 3) * invF.at(3, 2) * lnJ ); - answer.at(3, 3) = answer.at(3, 3) - K *invF.at(3, 3) * invF.at(3, 3) * ( lnJ - 1. ); - answer.at(3, 4) = answer.at(3, 4) + K * ( invF.at(2, 1) * invF.at(3, 3) - invF.at(3, 1) * invF.at(2, 3) * lnJ ); - answer.at(3, 5) = answer.at(3, 5) + K * ( invF.at(1, 2) * invF.at(3, 3) - invF.at(1, 3) * invF.at(3, 2) * lnJ ); - - answer.at(4, 1) = answer.at(4, 1) - K *invF.at(1, 1) * invF.at(2, 1) * ( lnJ - 1. ); - answer.at(4, 2) = answer.at(4, 2) - K *invF.at(2, 1) * invF.at(2, 2) * ( lnJ - 1. ); - answer.at(4, 3) = answer.at(4, 3) + K * ( invF.at(2, 1) * invF.at(3, 3) - invF.at(3, 1) * invF.at(2, 3) * lnJ ); - answer.at(4, 4) = answer.at(4, 4) - K *invF.at(2, 1) * invF.at(2, 1) * ( lnJ - 1. ); - answer.at(4, 5) = answer.at(4, 5) + K * ( invF.at(1, 2) * invF.at(2, 1) - invF.at(1, 1) * invF.at(2, 2) * lnJ ); - - answer.at(5, 1) = answer.at(5, 1) - K *invF.at(1, 1) * invF.at(1, 2) * ( lnJ - 1. ); - answer.at(5, 2) = answer.at(5, 2) - K *invF.at(1, 2) * invF.at(2, 2) * ( lnJ - 1. ); - answer.at(5, 3) = answer.at(5, 3) + K * ( invF.at(1, 2) * invF.at(3, 3) - invF.at(1, 3) * invF.at(3, 2) * lnJ ); - answer.at(5, 4) = answer.at(5, 4) + K * ( invF.at(1, 2) * invF.at(2, 1) - invF.at(1, 1) * invF.at(2, 2) * lnJ ); - answer.at(5, 5) = answer.at(5, 5) - K *invF.at(1, 2) * invF.at(1, 2) * ( lnJ - 1. ); -} - - - -MaterialStatus * -MooneyRivlinMaterial :: CreateStatus(GaussPoint *gp) const -{ - return new StructuralMaterialStatus(1, this->giveDomain(), gp); -} - - -IRResultType -MooneyRivlinMaterial :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - - IR_GIVE_FIELD(ir, K, _IFT_MooneyRivlinMaterial_k); - IR_GIVE_FIELD(ir, C1, _IFT_MooneyRivlinMaterial_c1); - IR_GIVE_FIELD(ir, C2, _IFT_MooneyRivlinMaterial_c2); - - return IRRT_OK; -} - -} // end namespace oofem diff --git a/src/sm/Materials/mooneyrivlin.h b/src/sm/Materials/mooneyrivlin.h deleted file mode 100644 index f5feb377f..000000000 --- a/src/sm/Materials/mooneyrivlin.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2014 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef mooneyrivlinmaterial_h -#define mooneyrivlinmaterial_h - -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" - -///@name Input fields for MooneyRivlinMaterial -//@{ -#define _IFT_MooneyRivlinMaterial_Name "mooneyrivlin" -#define _IFT_MooneyRivlinMaterial_c1 "c1" -#define _IFT_MooneyRivlinMaterial_c2 "c2" -#define _IFT_MooneyRivlinMaterial_k "k" -//@} - -namespace oofem { -/** - * This class implements Compressible Mooney - Rivlin material. - * - * @author Martin Horák, nitramkaroh@seznam.cz - * - * References: R.W. Ogden: Non-Linear Elastic Deformations, - * de Souza Neto, Peric, Owen: Computational Methods for Plasticity: Theory and Applications - * - * Free energy is considered as: - * @f[ - * \rho_0 \psi = C_1(\bar{I}_1 - 3) + C_2(\bar{I}_2-3) + \frac{1}{2} K[ln(J)]^2 - * @f] - * @f$ C_1 @f$, @f$ C_2 @f$, and @f$K@f$ are material parameters. - * - * @f$ \bar{I}_1 = J^{-2/3}I_1 @f$, where @f$I_1@f$ is the first invariant of @f$ \boldsymbol{C} @f$. - * - * @f$ \bar{I}_2 = J^{-4/3}I_2 @f$, where @f$I_2@f$ is the second invariant of @f$ \boldsymbol{C} @f$. - * - * Compressible Neo-Hookean model is obtained by setting @f$C_2 = 0@f$ - */ -class MooneyRivlinMaterial : public StructuralMaterial -{ -protected: - // Material parameters - double C1; - double C2; - double K; - - -public: - MooneyRivlinMaterial(int n, Domain *d); - - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } - - - virtual void givePlaneStrainStiffMtrx_dPdF(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep); - - - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) { OOFEM_ERROR("not implemented, this material is designed for large strains only"); } - virtual void giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &vF, TimeStep *tStep); - void giveFirstPKStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep); - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; - - virtual const char *giveInputRecordName() const { return _IFT_MooneyRivlinMaterial_Name; } - virtual const char *giveClassName() const { return "MooneyRivlinMaterial"; } -}; - -} // end namespace oofem -#endif diff --git a/src/sm/Materials/ortholinearelasticmaterial.C b/src/sm/Materials/ortholinearelasticmaterial.C index 5e2fec8f2..ca0a13ef3 100644 --- a/src/sm/Materials/ortholinearelasticmaterial.C +++ b/src/sm/Materials/ortholinearelasticmaterial.C @@ -32,12 +32,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "Materials/linearelasticmaterial.h" -#include "Materials/ortholinearelasticmaterial.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/Materials/linearelasticmaterial.h" +#include "sm/Materials/ortholinearelasticmaterial.h" +#include "sm/Elements/structuralelement.h" #include "material.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "floatmatrix.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "gausspoint.h" #include "mathfem.h" #include "classfactory.h" @@ -48,20 +50,14 @@ namespace oofem { REGISTER_Material(OrthotropicLinearElasticMaterial); -IRResultType -OrthotropicLinearElasticMaterial :: initializeFrom(InputRecord *ir) +void +OrthotropicLinearElasticMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - double value; int size; FloatArray triplets; - - result = LinearElasticMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } + LinearElasticMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, value, _IFT_OrthotropicLinearElasticMaterial_ex); propertyDictionary.add(Ex, value); @@ -134,31 +130,31 @@ OrthotropicLinearElasticMaterial :: initializeFrom(InputRecord *ir) cs_type = localCS; double n1 = 0.0, n2 = 0.0; - localCoordinateSystem = new FloatMatrix(3, 3); + localCoordinateSystem = FloatMatrixF<3,3>(); for ( int j = 1; j <= 3; j++ ) { - localCoordinateSystem->at(j, 1) = triplets.at(j); + localCoordinateSystem.at(j, 1) = triplets.at(j); n1 += triplets.at(j) * triplets.at(j); - localCoordinateSystem->at(j, 2) = triplets.at(j + 3); + localCoordinateSystem.at(j, 2) = triplets.at(j + 3); n2 += triplets.at(j + 3) * triplets.at(j + 3); } n1 = sqrt(n1); n2 = sqrt(n2); for ( int j = 1; j <= 3; j++ ) { // normalize e1' e2' - localCoordinateSystem->at(j, 1) /= n1; - localCoordinateSystem->at(j, 2) /= n2; + localCoordinateSystem.at(j, 1) /= n1; + localCoordinateSystem.at(j, 2) /= n2; } // vector e3' computed from vector product of e1', e2' - localCoordinateSystem->at(1, 3) = - ( localCoordinateSystem->at(2, 1) * localCoordinateSystem->at(3, 2) - - localCoordinateSystem->at(3, 1) * localCoordinateSystem->at(2, 2) ); - localCoordinateSystem->at(2, 3) = - ( localCoordinateSystem->at(3, 1) * localCoordinateSystem->at(1, 2) - - localCoordinateSystem->at(1, 1) * localCoordinateSystem->at(3, 2) ); - localCoordinateSystem->at(3, 3) = - ( localCoordinateSystem->at(1, 1) * localCoordinateSystem->at(2, 2) - - localCoordinateSystem->at(2, 1) * localCoordinateSystem->at(1, 2) ); + localCoordinateSystem.at(1, 3) = + ( localCoordinateSystem.at(2, 1) * localCoordinateSystem.at(3, 2) - + localCoordinateSystem.at(3, 1) * localCoordinateSystem.at(2, 2) ); + localCoordinateSystem.at(2, 3) = + ( localCoordinateSystem.at(3, 1) * localCoordinateSystem.at(1, 2) - + localCoordinateSystem.at(1, 1) * localCoordinateSystem.at(3, 2) ); + localCoordinateSystem.at(3, 3) = + ( localCoordinateSystem.at(1, 1) * localCoordinateSystem.at(2, 2) - + localCoordinateSystem.at(2, 1) * localCoordinateSystem.at(1, 2) ); } // try to read ElementCS section @@ -183,7 +179,7 @@ OrthotropicLinearElasticMaterial :: initializeFrom(InputRecord *ir) if ( size == 3 ) { cs_type = shellCS; triplets.normalize(); - helpPlaneNormal = new FloatArray(triplets); + helpPlaneNormal = triplets; // // store normal defining help plane into row matrix @@ -197,11 +193,36 @@ OrthotropicLinearElasticMaterial :: initializeFrom(InputRecord *ir) // if no cs defined assume global one // cs_type = localCS; - localCoordinateSystem = new FloatMatrix(3, 3); - localCoordinateSystem->beUnitMatrix(); + localCoordinateSystem = eye<3>(); } - return IRRT_OK; + { + double ex = propertyDictionary.at(Ex); + double ey = propertyDictionary.at(Ey); + double ez = propertyDictionary.at(Ez); + double nxz = propertyDictionary.at(NYxz); + double nyz = propertyDictionary.at(NYyz); + double nxy = propertyDictionary.at(NYxy); + double nzx = nxz * ez / ex; + double nzy = nyz * ez / ey; + double nyx = nxy * ey / ex; + double eksi = 1. - ( nxy * nyx + nyz * nzy + nzx * nxz ) - ( nxy * nyz * nzx + nyx * nzy * nxz ); + + tangent = FloatMatrixF<6,6>(); + tangent.at(1, 1) = ex * ( 1. - nyz * nzy ) / eksi; + tangent.at(1, 2) = ey * ( nxy + nxz * nzy ) / eksi; + tangent.at(1, 3) = ez * ( nxz + nyz * nxy ) / eksi; + tangent.at(2, 2) = ey * ( 1. - nxz * nzx ) / eksi; + tangent.at(2, 3) = ez * ( nyz + nyx * nxz ) / eksi; + tangent.at(3, 3) = ez * ( 1. - nyx * nxy ) / eksi; + tangent.at(4, 4) = propertyDictionary.at(Gyz); + tangent.at(5, 5) = propertyDictionary.at(Gxz); + tangent.at(6, 6) = propertyDictionary.at(Gxy); + tangent.symmetrized(); + this->computesSubTangents(); + + alpha = {propertyDictionary.at(tAlphax), propertyDictionary.at(tAlphay), propertyDictionary.at(tAlphaz), 0., 0., 0.}; + } } @@ -234,7 +255,7 @@ OrthotropicLinearElasticMaterial :: giveInputRecord(DynamicInputRecord &input) } double -OrthotropicLinearElasticMaterial :: give(int aProperty, GaussPoint *gp) +OrthotropicLinearElasticMaterial :: give(int aProperty, GaussPoint *gp) const { if ( aProperty == NYzx ) { return this->give(NYxz, gp) * this->give(Ez, gp) / this->give(Ex, gp); @@ -252,83 +273,39 @@ OrthotropicLinearElasticMaterial :: give(int aProperty, GaussPoint *gp) } -void -OrthotropicLinearElasticMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +OrthotropicLinearElasticMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) -{ - FloatMatrix rotationMatrix; - - this->give3dLocalMaterialStiffnessMatrix(answer, mode, gp, tStep); - - this->giveRotationMatrix(rotationMatrix, gp); - answer.rotatedWith(rotationMatrix); -} - - -void -OrthotropicLinearElasticMaterial :: give3dLocalMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - double eksi, nxz, nyz, nxy, nzx, nzy, nyx; - - nxz = this->give(NYxz, gp); - nyz = this->give(NYyz, gp); - nxy = this->give(NYxy, gp); - nzx = this->give(NYzx, gp); - nzy = this->give(NYzy, gp); - nyx = this->give(NYyx, gp); - - eksi = 1. - ( nxy * nyx + nyz * nzy + nzx * nxz ) - ( nxy * nyz * nzx + nyx * nzy * nxz ); - - answer.resize(6, 6); - answer.zero(); - // switched letters from original oofem -> now produces same material stiffness matrix as Abaqus method - answer.at(1, 1) = this->give(Ex, gp) * ( 1. - nyz * nzy ) / eksi; - answer.at(1, 2) = this->give(Ey, gp) * ( nxy + nxz * nzy ) / eksi; - answer.at(1, 3) = this->give(Ez, gp) * ( nxz + nyz * nxy ) / eksi; - answer.at(2, 2) = this->give(Ey, gp) * ( 1. - nxz * nzx ) / eksi; - answer.at(2, 3) = this->give(Ez, gp) * ( nyz + nyx * nxz ) / eksi; - answer.at(3, 3) = this->give(Ez, gp) * ( 1. - nyx * nxy ) / eksi; - - // define the lower triangle - for ( int i = 1; i < 4; i++ ) { - for ( int j = 1; j < i; j++ ) { - answer.at(i, j) = answer.at(j, i); - } - } - - answer.at(4, 4) = this->give(Gyz, gp); - answer.at(5, 5) = this->give(Gxz, gp); - answer.at(6, 6) = this->give(Gxy, gp); - + auto t = tangent; if ( ( tStep->giveIntrinsicTime() < this->castingTime ) ) { - answer.times(1. - this->preCastStiffnessReduction); + t *= 1. - this->preCastStiffnessReduction; } + + auto rotationMatrix = this->giveRotationMatrix(gp); + return rotate(t, rotationMatrix); } -void -OrthotropicLinearElasticMaterial :: giveTensorRotationMatrix(FloatMatrix &answer, GaussPoint *gp) +FloatMatrixF<3,3> +OrthotropicLinearElasticMaterial :: giveTensorRotationMatrix(GaussPoint *gp) const // // returns [3,3] rotation matrix from local principal axes of material // to local axes used at gp (element) level // { - int elementCsFlag; - FloatMatrix elementCs; - StructuralElement *element = static_cast< StructuralElement * >( gp->giveElement() ); - if ( gp->giveMaterialMode() == _1dMat ) { //do not rotate 1D materials on trusses and beams - answer.resize(3, 3); - answer.beUnitMatrix(); - return; + return eye<3>(); } - elementCsFlag = element->giveLocalCoordinateSystem(elementCs); + auto element = static_cast< StructuralElement * >( gp->giveElement() ); + FloatMatrix elementCs_; + int elementCsFlag = element->giveLocalCoordinateSystem(elementCs_); + FloatMatrixF<3,3> elementCs; + if (elementCsFlag) { + elementCs = elementCs_; + } // // in localCoordinateSystem the directional cosines are stored columwise (exception) // in elementCs rowwise. @@ -338,27 +315,26 @@ OrthotropicLinearElasticMaterial :: giveTensorRotationMatrix(FloatMatrix &answer // in localCoordinateSystem are stored directional cosines // if ( elementCsFlag ) { - answer.beProductOf(elementCs, * this->localCoordinateSystem); + return dot(elementCs, this->localCoordinateSystem); } else { - answer = * this->localCoordinateSystem; + return this->localCoordinateSystem; } } else if ( this->cs_type == shellCS ) { - FloatArray elementNormal, helpx, helpy; - localCoordinateSystem = new FloatMatrix(3, 3); - + FloatArray elementNormal; element->computeMidPlaneNormal(elementNormal, gp); - helpx.beVectorProductOf(* ( this->helpPlaneNormal ), elementNormal); + auto helpx = cross(this->helpPlaneNormal, elementNormal); // test if localCoordinateSystem is uniquely // defined by elementNormal and helpPlaneNormal - if ( helpx.computeNorm() < ZERO_LENGTH ) { + if ( norm(helpx) < ZERO_LENGTH ) { OOFEM_ERROR("element normal parallel to plane normal encountered"); } - helpy.beVectorProductOf(elementNormal, helpx); + auto helpy = cross(elementNormal, helpx); + FloatMatrixF<3,3> cs; for ( int i = 1; i < 4; i++ ) { - localCoordinateSystem->at(i, 1) = helpx.at(i); - localCoordinateSystem->at(i, 2) = helpy.at(i); - localCoordinateSystem->at(i, 3) = elementNormal.at(i); + cs.at(i, 1) = helpx.at(i); + cs.at(i, 2) = helpy.at(i); + cs.at(i, 3) = elementNormal.at(i); } // @@ -371,26 +347,23 @@ OrthotropicLinearElasticMaterial :: giveTensorRotationMatrix(FloatMatrix &answer * // * zRotMtrx = GiveZRotationMtrx (rotAngle); // rotAngle supplied by user * rotatedLocalCoordinateSystem = localCoordinateSystem->Times (zRotMtrx); - * delete localCoordinateSystem; * localCoordinateSystem = rotatedLocalCoordinateSystem; */ if ( elementCsFlag ) { - answer.beProductOf(elementCs, * this->localCoordinateSystem); + return dot(elementCs, cs); } else { - answer = * this->localCoordinateSystem; + return cs; } - - delete localCoordinateSystem; - localCoordinateSystem = NULL; } else { OOFEM_ERROR("internal error no cs defined"); + return eye<3>(); } // t at (i,j) contains cosine of angle between elementAxis(i) and localMaterialAxis(j). } -void -OrthotropicLinearElasticMaterial :: giveRotationMatrix(FloatMatrix &answer, GaussPoint *gp) +FloatMatrixF<6,6> +OrthotropicLinearElasticMaterial :: giveRotationMatrix(GaussPoint *gp) const // // returns [6,6] rotation matrix from local principal axes of material // to local axes used at the gp (element) level for beams and trusses @@ -398,27 +371,15 @@ OrthotropicLinearElasticMaterial :: giveRotationMatrix(FloatMatrix &answer, Gaus // // { - FloatMatrix t; - this->giveTensorRotationMatrix(t, gp); - this->giveStrainVectorTranformationMtrx(answer, t); + auto t = this->giveTensorRotationMatrix(gp); + return this->giveStrainVectorTranformationMtrx(t); } -void -OrthotropicLinearElasticMaterial :: giveThermalDilatationVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep) -// -// returns a FloatArray(3) of coefficients of thermal dilatation in direction -// of each (local) axis given by element lcs. -// +FloatArrayF<6> +OrthotropicLinearElasticMaterial :: giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix transf; - FloatArray help(6); - help.at(1) = this->give(tAlphax, gp); - help.at(2) = this->give(tAlphay, gp); - help.at(3) = this->give(tAlphaz, gp); - - this->giveRotationMatrix(transf, gp); - answer.beProductOf(transf, help); + auto transf = this->giveRotationMatrix(gp); + return dot(transf, alpha); } } // end namespace oofem diff --git a/src/sm/Materials/ortholinearelasticmaterial.h b/src/sm/Materials/ortholinearelasticmaterial.h index f6e6e39f5..a0e56535d 100644 --- a/src/sm/Materials/ortholinearelasticmaterial.h +++ b/src/sm/Materials/ortholinearelasticmaterial.h @@ -35,13 +35,15 @@ #ifndef ortholinearelasticmaterial_h #define ortholinearelasticmaterial_h -#include "Materials/linearelasticmaterial.h" +#include "sm/Materials/linearelasticmaterial.h" #include "dictionary.h" #include "floatarray.h" #include "floatmatrix.h" #include "matconst.h" #include "element.h" +#include + ///@name Input fields for OrthotropicLinearElasticMaterial //@{ #define _IFT_OrthotropicLinearElasticMaterial_Name "orthole" @@ -101,52 +103,31 @@ class OrthotropicLinearElasticMaterial : public LinearElasticMaterial { protected: CS_type cs_type; - FloatMatrix *localCoordinateSystem; - FloatArray *helpPlaneNormal; + FloatMatrixF<3,3> localCoordinateSystem; + FloatArrayF<3> helpPlaneNormal; // in localCoordinateSystem the unity vectors are stored // COLUMWISE (this is exception, but allows faster numerical // implementation) public: - OrthotropicLinearElasticMaterial(int n, Domain * d) : LinearElasticMaterial(n, d) - { - localCoordinateSystem = NULL; - helpPlaneNormal = NULL; - cs_type = unknownCS; - } - virtual ~OrthotropicLinearElasticMaterial() - { - if ( localCoordinateSystem ) { - delete localCoordinateSystem; - } - - if ( helpPlaneNormal ) { - delete helpPlaneNormal; - } - } - - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + OrthotropicLinearElasticMaterial(int n, Domain * d) : LinearElasticMaterial(n, d), + cs_type(unknownCS) + { } - // identification and auxiliary functions - virtual const char *giveInputRecordName() const { return _IFT_OrthotropicLinearElasticMaterial_Name; } - virtual const char *giveClassName() const { return "OrthotropicLinearElasticMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); - void giveInputRecord(DynamicInputRecord &input); - virtual double give(int aProperty, GaussPoint *gp); + FloatArrayF<6> giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep); + const char *giveInputRecordName() const override { return _IFT_OrthotropicLinearElasticMaterial_Name; } + const char *giveClassName() const override { return "OrthotropicLinearElasticMaterial"; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + double give(int aProperty, GaussPoint *gp) const override; - /// Computes local 3d stiffness matrix of the receiver. - virtual void give3dLocalMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; protected: - void giveTensorRotationMatrix(FloatMatrix &answer, GaussPoint *gp); - void giveRotationMatrix(FloatMatrix &answer, GaussPoint *gp); + FloatMatrixF<3,3> giveTensorRotationMatrix(GaussPoint *gp) const; + FloatMatrixF<6,6> giveRotationMatrix(GaussPoint *gp) const; friend class CrossSection; }; diff --git a/src/sm/Materials/qcmaterialextensioninterface.h b/src/sm/Materials/qcmaterialextensioninterface.h index 9c83a4d68..1298b4ffe 100644 --- a/src/sm/Materials/qcmaterialextensioninterface.h +++ b/src/sm/Materials/qcmaterialextensioninterface.h @@ -50,7 +50,6 @@ class TimeStep; */ class QCMaterialExtensionInterface : public Interface { -protected: public: /** * Constructor. Creates material with given number, belonging to given domain. diff --git a/src/sm/Materials/rankinemat.C b/src/sm/Materials/rankinemat.C index fa9bb779d..639384fd8 100644 --- a/src/sm/Materials/rankinemat.C +++ b/src/sm/Materials/rankinemat.C @@ -52,41 +52,23 @@ REGISTER_Material(RankineMat); RankineMat :: RankineMat(int n, Domain *d) : StructuralMaterial(n, d) { linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); - E = 0.; - nu = 0.; - H0 = 0.; - sig0 = 0.; - delSigY = 0.; - ep = 0.; - md = 0.; - damlaw = 1; - param1 = 0.; - param2 = 0.; - param3 = 0.; - param4 = 0.; - param5 = 0.; } // specifies whether a given material mode is supported by this model -int -RankineMat :: hasMaterialModeCapability(MaterialMode mode) +bool +RankineMat :: hasMaterialModeCapability(MaterialMode mode) const { - return ( ( mode == _PlaneStress ) || ( mode == _1dMat ) ); + return mode == _PlaneStress || mode == _1dMat; } // reads the model parameters from the input file -IRResultType -RankineMat :: initializeFrom(InputRecord *ir) +void +RankineMat :: initializeFrom(InputRecord &ir) { - IRResultType result; // required by IR_GIVE_FIELD macro - - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - - result = linearElasticMaterial->initializeFrom(ir); // takes care of elastic constants - if ( result != IRRT_OK ) return result; + StructuralMaterial :: initializeFrom(ir); + linearElasticMaterial->initializeFrom(ir); // takes care of elastic constants E = static_cast< IsotropicLinearElasticMaterial * >(linearElasticMaterial)->giveYoungsModulus(); nu = static_cast< IsotropicLinearElasticMaterial * >(linearElasticMaterial)->givePoissonsRatio(); @@ -109,8 +91,7 @@ RankineMat :: initializeFrom(InputRecord *ir) ep = ep - sig0 / E; // user input is strain at peak stress sig0 and is converted to plastic strain at peak stress sig0 md = 1. / log(50. * E * ep / sig0); // exponent used on the 1st plasticity branch } else { - OOFEM_WARNING("Plasticity hardening type number %d is unknown", plasthardtype); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_RankineMat_plasthardtype, "Plasticity hardening type is unknown"); } yieldtol = 1.e-10; @@ -131,17 +112,19 @@ RankineMat :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, param3, _IFT_RankineMat_param3); IR_GIVE_FIELD(ir, param4, _IFT_RankineMat_param4); IR_GIVE_FIELD(ir, param5, _IFT_RankineMat_param5); + } else if ( damlaw == 3 ) { + IR_GIVE_FIELD(ir, param1, _IFT_RankineMat_param1); // coefficients in damage law + IR_GIVE_FIELD(ir, param2, _IFT_RankineMat_param2); + IR_GIVE_FIELD(ir, param3, _IFT_RankineMat_param3); } else { - OOFEM_WARNING("Damage law number %d is unknown", damlaw); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_RankineMat_damlaw, "Damage law is unknown"); } double gf = 0.; IR_GIVE_OPTIONAL_FIELD(ir, gf, _IFT_RankineMat_gf); // dissipated energy per unit VOLUME if ( ( a != 0. ) && ( gf != 0 ) ) { - OOFEM_WARNING("parameters a and gf cannot be prescribed simultaneously"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_RankineMat_gf, "parameters a and gf cannot be prescribed simultaneously"); } if ( gf > 0. ) { @@ -156,26 +139,21 @@ RankineMat :: initializeFrom(InputRecord *ir) double kappaf = ( -B + sqrt(B * B - 4. * A * C) ) / ( 2. * A ); a = 1. / kappaf; } - - return IRRT_OK; } -// creates a new material status corresponding to this class MaterialStatus * RankineMat :: CreateStatus(GaussPoint *gp) const { - RankineMatStatus *status; - status = new RankineMatStatus(1, this->giveDomain(), gp); - return status; + return new RankineMatStatus(gp); } // computes the stress vector corresponding to given (final) strain -void -RankineMat :: giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep) +FloatArrayF<1> +RankineMat :: giveRealStressVector_1d(const FloatArrayF<1> &totalStrain, GaussPoint *gp, TimeStep *tStep) const { - RankineMatStatus *status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); // initialization this->initTempStatus(gp); @@ -185,6 +163,7 @@ RankineMat :: giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const // damage double omega = computeDamage(gp, tStep); + FloatArray answer; answer.beScaled(1. - omega, status->giveTempEffectiveStress()); // store variables in status @@ -195,16 +174,15 @@ RankineMat :: giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const double gf = sig0 * sig0 / E; // only estimated, but OK for this purpose status->computeWork_1d(gp, gf); #endif + return answer; } -void -RankineMat :: giveRealStressVector_PlaneStress(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) +FloatArrayF<3> +RankineMat :: giveRealStressVector_PlaneStress(const FloatArrayF<3> &totalStrain, + GaussPoint *gp, TimeStep *tStep) const { - RankineMatStatus *status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); // initialization this->initTempStatus(gp); @@ -214,6 +192,7 @@ RankineMat :: giveRealStressVector_PlaneStress(FloatArray &answer, // damage double omega = computeDamage(gp, tStep); + FloatArray answer; answer.beScaled(1. - omega, status->giveTempEffectiveStress()); // store variables in status @@ -224,18 +203,19 @@ RankineMat :: giveRealStressVector_PlaneStress(FloatArray &answer, double gf = sig0 * sig0 / E; // only estimated, but OK for this purpose status->computeWork_PlaneStress(gp, gf); #endif + return answer; } double -RankineMat :: evalYieldFunction(const FloatArray &sigPrinc, const double kappa) +RankineMat :: evalYieldFunction(const FloatArray &sigPrinc, const double kappa) const { return sigPrinc.at(1) - evalYieldStress(kappa); } double -RankineMat :: evalYieldStress(const double kappa) +RankineMat :: evalYieldStress(const double kappa) const { double yieldStress = 0.; if ( plasthardtype == 0 ) { // linear hardening @@ -258,7 +238,7 @@ RankineMat :: evalYieldStress(const double kappa) } double -RankineMat :: evalPlasticModulus(const double kappa) +RankineMat :: evalPlasticModulus(const double kappa) const { double plasticModulus = 0.; if ( plasthardtype == 0 ) { // linear hardening @@ -280,7 +260,7 @@ RankineMat :: evalPlasticModulus(const double kappa) // computes the stress according to elastoplasticity // (return of trial stress to the yield surface) void -RankineMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain) +RankineMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain) const { double kappa, tempKappa, H; RankineMatStatus *status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); @@ -433,7 +413,7 @@ RankineMat :: performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStr } double -RankineMat :: computeDamageParam(double tempKappa) +RankineMat :: computeDamageParam(double tempKappa) const { double tempDam = 0.; if ( tempKappa > 0. ) { @@ -443,6 +423,8 @@ RankineMat :: computeDamageParam(double tempKappa) tempDam = 1.0 - exp( -param1 * pow( ( tempKappa - ep ) / ep, param2 ) ); } else if ( damlaw == 2 && tempKappa > ep ) { tempDam = 1.0 - param5 *exp( -param1 *pow ( ( tempKappa - ep ) / ep, param2 ) ) - ( 1. - param5 ) * exp( -param3 * pow( ( tempKappa - ep ) / ep, param4 ) ); + } else if ( damlaw == 3 ) { + tempDam = 1.0 - (sig0 / (sig0+H0*tempKappa)) * ( (1.-param3)*exp(-param1*tempKappa) + param3*exp(-param2*tempKappa) ); } } @@ -450,7 +432,7 @@ RankineMat :: computeDamageParam(double tempKappa) } double -RankineMat :: computeDamageParamPrime(double tempKappa) +RankineMat :: computeDamageParamPrime(double tempKappa) const { double tempDam = 0.; if ( tempKappa >= 0. ) { @@ -460,6 +442,8 @@ RankineMat :: computeDamageParamPrime(double tempKappa) tempDam = param1 * param2 * pow( ( tempKappa - ep ) / ep, param2 - 1 ) / ep *exp( -param1 *pow ( ( tempKappa - ep ) / ep, param2 ) ); } else if ( damlaw == 2 && tempKappa >= ep ) { tempDam = param5 * param1 * param2 * pow( ( tempKappa - ep ) / ep, param2 - 1 ) / ep *exp( -param1 *pow ( ( tempKappa - ep ) / ep, param2 ) ) + ( 1. - param5 ) * param3 * param4 * pow( ( tempKappa - ep ) / ep, param4 - 1 ) / ep *exp( -param3 *pow ( ( tempKappa - ep ) / ep, param4 ) ); + } else if ( damlaw == 3 ) { + tempDam = (sig0 / (sig0+H0*tempKappa)) * ( (1.-param3)*param1*exp(-param1*tempKappa) + param3*param2*exp(-param2*tempKappa) ) + (sig0*H0 / (sig0+H0*tempKappa)*(sig0+H0*tempKappa)) * ( (1.-param3)*exp(-param1*tempKappa) + param3*exp(-param2*tempKappa) ); } } @@ -467,12 +451,11 @@ RankineMat :: computeDamageParamPrime(double tempKappa) } double -RankineMat :: computeDamage(GaussPoint *gp, TimeStep *tStep) +RankineMat :: computeDamage(GaussPoint *gp, TimeStep *tStep) const { - double tempKappa, dam; - RankineMatStatus *status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); - dam = status->giveDamage(); - computeCumPlastStrain(tempKappa, gp, tStep); + auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); + double dam = status->giveDamage(); + double tempKappa = computeCumPlastStrain(gp, tStep); double tempDam = computeDamageParam(tempKappa); if ( dam > tempDam ) { tempDam = dam; @@ -481,76 +464,71 @@ RankineMat :: computeDamage(GaussPoint *gp, TimeStep *tStep) return tempDam; } -void RankineMat :: computeCumPlastStrain(double &tempKappa, GaussPoint *gp, TimeStep *tStep) +double RankineMat :: computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const { RankineMatStatus *status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); - tempKappa = status->giveTempCumulativePlasticStrain(); + return status->giveTempCumulativePlasticStrain(); } // returns the consistent (algorithmic) stiffness matrix -void -RankineMat :: givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +RankineMat :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - RankineMatStatus *status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); double tempKappa = status->giveTempCumulativePlasticStrain(); double gprime = computeDamageParamPrime(tempKappa); - evaluatePlaneStressStiffMtrx(answer, mode, gp, tStep, gprime); + return evaluatePlaneStressStiffMtrx(mode, gp, tStep, gprime); } -void -RankineMat :: give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<1,1> +RankineMat :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - RankineMatStatus *status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); - answer.resize(1, 1); - answer.at(1, 1) = this->E; if ( mode == ElasticStiffness ) { + return {E}; } else if ( mode == SecantStiffness ) { + auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); double om = status->giveTempDamage(); - answer.times(1.0 - om); + return {E * (1.0 - om)}; } else { OOFEM_ERROR("unknown type of stiffness (secant stiffness not implemented for 1d)"); + return {0.}; } } // this method is also used by the gradient version, // with gprime replaced by gprime*m and evaluated for kappa hat -void -RankineMat :: evaluatePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +RankineMat :: evaluatePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep, double gprime) + TimeStep *tStep, double gprime) const { - RankineMatStatus *status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RankineMatStatus * >( this->giveStatus(gp) ); if ( mode == ElasticStiffness || mode == SecantStiffness ) { // start from the elastic stiffness - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + auto d = this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep); if ( mode == SecantStiffness ) { // transform to secant stiffness double damage = status->giveTempDamage(); - answer.times(1. - damage); + d *= 1. - damage; } - - return; + return d; } // check the unloading condition double kappa = status->giveCumulativePlasticStrain(); double tempKappa = status->giveTempCumulativePlasticStrain(); if ( tempKappa <= kappa ) { // tangent matrix requested, but unloading takes place - use secant - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + auto d = this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep); double damage = status->giveTempDamage(); - answer.times(1. - damage); - return; + return d * (1. - damage); } // tangent stiffness requested, loading // elastoplastic tangent matrix in principal stress coordinates - answer.resize(3, 3); - answer.zero(); // just to be sure (components 13,23,31,32 must be zero) + FloatMatrixF<3,3> answer; double eta1, eta2, dkap2; double dkap1 = status->giveDKappa(1); @@ -583,7 +561,7 @@ RankineMat :: evaluatePlaneStressStiffMtrx(FloatMatrix &answer, // now add the effect of damage double damage = status->giveTempDamage(); - answer.times(1. - damage); + answer *= 1. - damage; FloatArray sigPrinc(2); FloatMatrix nPrinc(2, 2); @@ -591,20 +569,18 @@ RankineMat :: evaluatePlaneStressStiffMtrx(FloatMatrix &answer, effStress.computePrincipalValDir(sigPrinc, nPrinc); // sometimes the method is called with gprime=0., then we can save some work if ( gprime != 0. ) { - FloatMatrix correction(3, 3); - correction.zero(); + FloatMatrixF<3,3> correction; correction.at(1, 1) = sigPrinc.at(1) * eta1; correction.at(1, 2) = sigPrinc.at(1) * eta2; correction.at(2, 1) = sigPrinc.at(2) * eta1; correction.at(2, 2) = sigPrinc.at(2) * eta2; - correction.times(gprime); // input parameter gprime used here - answer.subtract(correction); + correction *= gprime; // input parameter gprime used here + answer -= correction; } // transform to global coordinates - FloatMatrix T; - givePlaneStressVectorTranformationMtrx(T, nPrinc, true); - answer.rotatedWith(T, 't'); + auto T = givePlaneStressVectorTranformationMtrx(nPrinc, true); + return unrotate(answer, T); } // derivatives of final kappa with respect to final strain @@ -641,8 +617,7 @@ RankineMat :: computeEta(FloatArray &answer, RankineMatStatus *status) StressVector effStress(status->giveTempEffectiveStress(), _PlaneStress); effStress.computePrincipalValDir(sigPrinc, nPrinc); - FloatMatrix T(3, 3); - givePlaneStressVectorTranformationMtrx(T, nPrinc, true); + FloatMatrix T = givePlaneStressVectorTranformationMtrx(nPrinc, true); answer.beProductOf(T, eta); } @@ -699,8 +674,8 @@ RankineMat :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType // RANKINE MATERIAL STATUS //============================================================================= -RankineMatStatus :: RankineMatStatus(int n, Domain *d, GaussPoint *g) : - StructuralMaterialStatus(n, d, g), plasticStrain(), tempPlasticStrain() +RankineMatStatus :: RankineMatStatus(GaussPoint *g) : + StructuralMaterialStatus(g), plasticStrain(), tempPlasticStrain() { damage = tempDamage = 0.; kappa = tempKappa = 0.; @@ -715,15 +690,9 @@ RankineMatStatus :: RankineMatStatus(int n, Domain *d, GaussPoint *g) : } -RankineMatStatus :: ~RankineMatStatus() -{ } - - void -RankineMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) +RankineMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { - //int i, n; - StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -787,31 +756,20 @@ RankineMatStatus :: updateYourself(TimeStep *tStep) } -// saves full information stored in this status -// temporary variables are NOT stored -contextIOResultType -RankineMatStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +RankineMatStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + StructuralMaterialStatus :: saveContext(stream, mode); - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write raw data - - // write plastic strain (vector) + contextIOResultType iores; if ( ( iores = plasticStrain.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - // write cumulative plastic strain (scalar) if ( !stream.write(kappa) ) { THROW_CIOERR(CIO_IOERR); } - // write damage (scalar) if ( !stream.write(damage) ) { THROW_CIOERR(CIO_IOERR); } @@ -824,37 +782,24 @@ RankineMatStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) if ( !stream.write(dissWork) ) { THROW_CIOERR(CIO_IOERR); } - #endif - - return CIO_OK; } -contextIOResultType -RankineMatStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +RankineMatStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus :: restoreContext(stream, mode); - // read plastic strain (vector) + contextIOResultType iores; if ( ( iores = plasticStrain.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - // read cumulative plastic strain (scalar) if ( !stream.read(kappa) ) { THROW_CIOERR(CIO_IOERR); } - // read damage (scalar) if ( !stream.read(damage) ) { THROW_CIOERR(CIO_IOERR); } @@ -867,10 +812,7 @@ RankineMatStatus :: restoreContext(DataStream &stream, ContextMode mode, void *o if ( !stream.read(dissWork) ) { THROW_CIOERR(CIO_IOERR); } - #endif - - return CIO_OK; // return success } diff --git a/src/sm/Materials/rankinemat.h b/src/sm/Materials/rankinemat.h index 69facba37..26cee4cbf 100644 --- a/src/sm/Materials/rankinemat.h +++ b/src/sm/Materials/rankinemat.h @@ -35,8 +35,8 @@ #ifndef rankinemat_h #define rankinemat_h -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "linearelasticmaterial.h" #include "dictionary.h" #include "floatarray.h" @@ -86,108 +86,102 @@ class RankineMat : public StructuralMaterial { protected: /// Reference to the basic elastic material. - LinearElasticMaterial *linearElasticMaterial; + LinearElasticMaterial *linearElasticMaterial = nullptr; /// Young's modulus. - double E; + double E = 0.; /// Poisson's ratio. - double nu; + double nu = 0.; /// Initial hardening modulus. - double H0; + double H0 = 0.; /// Type of plastic hardening (0=linear, 1=exponential) - int plasthardtype; + int plasthardtype = 0; /// Final increment of yield stress (at infinite cumulative plastic strain) - double delSigY; + double delSigY = 0.; /// Initial (uniaxial) yield stress. - double sig0; + double sig0 = 0.; /// Relative tolerance in yield condition - double yieldtol; + double yieldtol = 0.; /// Parameter that controls damage evolution (a=0 turns damage off). - double a; + double a = 0.; /// Total strain at peak stress sig0--Used only if plasthardtype=2 - double ep; + double ep = 0.; /// Exponent in hardening law--Used only if plasthardtype=2 - double md; + double md = 0.; /// type of damage law (0=exponential, 1=exponential and damage starts after peak stress sig0) - int damlaw; + int damlaw = 1; /// coefficient required when damlaw=1 or 2 - double param1; + double param1 = 0.; /// coefficient required when damlaw=1 or 2 - double param2; + double param2 = 0.; /// coefficient required when damlaw=2 - double param3; + double param3 = 0.; /// coefficient required when damlaw=2 - double param4; + double param4 = 0.; /// coefficient required when damlaw=2 - double param5; + double param5 = 0.; public: RankineMat(int n, Domain * d); - virtual ~RankineMat() { } - double evalYieldFunction(const FloatArray &sigPrinc, const double kappa); - double evalYieldStress(const double kappa); - double evalPlasticModulus(const double kappa); - void performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain); - double computeDamage(GaussPoint *gp, TimeStep *tStep); - double computeDamageParam(double tempKappa); - double computeDamageParamPrime(double tempKappa); - virtual void computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *tStep); + double evalYieldFunction(const FloatArray &sigPrinc, const double kappa) const; + double evalYieldStress(const double kappa) const; + double evalPlasticModulus(const double kappa) const; + void performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain) const; + double computeDamage(GaussPoint *gp, TimeStep *tStep) const; + double computeDamageParam(double tempKappa) const; + double computeDamageParamPrime(double tempKappa) const; + virtual double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const; - virtual int hasMaterialModeCapability(MaterialMode mode); + bool hasMaterialModeCapability(MaterialMode mode) const override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 1; } - virtual const char *giveInputRecordName() const { return _IFT_RankineMat_Name; } - virtual const char *giveClassName() const { return "RankineMat"; } + const char *giveInputRecordName() const override { return _IFT_RankineMat_Name; } + const char *giveClassName() const override { return "RankineMat"; } /// Returns a reference to the basic elastic material. LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return ( a == 0. ); } + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return ( a == 0. ); } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &reducesStrain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &totalStrain, GaussPoint *gp, TimeStep *tStep) const override; + + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducesStrain, TimeStep *tStep); - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep); protected: - virtual void give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); /** * Executive method used by local and gradient version. * (with different parameters gprime) */ - void evaluatePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep, double gprime); + FloatMatrixF<3,3> evaluatePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, + TimeStep *tStep, double gprime) const; /// Computes derivatives of final kappa with respect to final strain. void computeEta(FloatArray &answer, RankineMatStatus *status); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; }; //============================================================================= @@ -209,51 +203,50 @@ class RankineMatStatus : public StructuralMaterialStatus FloatArray tempEffStress; /// Cumulative plastic strain (initial). - double kappa; + double kappa = 0.; /// Cumulative plastic strain (final). - double tempKappa; + double tempKappa = 0.; /** * Increments of cumulative plastic strain * associated with the first and secomnd principal stress * (used in the case of vertex return, needed for stiffness) */ - double dKappa1, dKappa2; + double dKappa1 = 0., dKappa2 = 0.; /// Damage (initial). - double damage; + double damage = 0.; /// Damage (final). - double tempDamage; + double tempDamage = 0.; /// Tangent shear stiffness (needed for tangent matrix). - double tanG; + double tanG = 0.; #ifdef keep_track_of_dissipated_energy /// Density of total work done by stresses on strain increments. - double stressWork; + double stressWork = 0.; /// Non-equilibrated density of total work done by stresses on strain increments. - double tempStressWork; + double tempStressWork = 0.; /// Density of dissipated work. - double dissWork; + double dissWork = 0.; /// Non-equilibrated density of dissipated work. - double tempDissWork; + double tempDissWork = 0.; #endif public: - RankineMatStatus(int n, Domain * d, GaussPoint * g); - virtual ~RankineMatStatus(); + RankineMatStatus(GaussPoint * g); const FloatArray & givePlasticStrain() const { return plasticStrain; } - double giveDamage() { return damage; } - double giveTempDamage() { return tempDamage; } + double giveDamage() const { return damage; } + double giveTempDamage() const { return tempDamage; } - double giveCumulativePlasticStrain() { return kappa; } - double giveTempCumulativePlasticStrain() { return tempKappa; } + double giveCumulativePlasticStrain() const { return kappa; } + double giveTempCumulativePlasticStrain() const { return tempKappa; } - double giveDKappa(int i) + double giveDKappa(int i) const { if ( i == 1 ) { return dKappa1; @@ -287,13 +280,13 @@ class RankineMatStatus : public StructuralMaterialStatus const FloatArray &givePlasDef() { return plasticStrain; } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; #ifdef keep_track_of_dissipated_energy /// Returns the density of total work of stress on strain increments. @@ -319,7 +312,7 @@ class RankineMatStatus : public StructuralMaterialStatus void computeWork_1d(GaussPoint *gp, double gf); #endif - virtual const char *giveClassName() const { return "RankineMatStatus"; } + const char *giveClassName() const override { return "RankineMatStatus"; } }; } // end namespace oofem #endif // rankinemat_h diff --git a/src/sm/Materials/rankinematgrad.C b/src/sm/Materials/rankinematgrad.C index 116878f3a..cb7d036e2 100644 --- a/src/sm/Materials/rankinematgrad.C +++ b/src/sm/Materials/rankinematgrad.C @@ -48,15 +48,41 @@ namespace oofem { REGISTER_Material(RankineMatGrad); -// constructor -RankineMatGrad :: RankineMatGrad(int n, Domain *d) : RankineMat(n, d), GradDpMaterialExtensionInterface(d) +RankineMatGrad :: RankineMatGrad(int n, Domain *d) : RankineMat(n, d), GradientDamageMaterialExtensionInterface(d) +{} + +///////////////////////////////////////////////////////////////////////////// +void +RankineMatGrad :: initializeFrom(InputRecord &ir) { - L = 0.; + RankineMat :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, L, _IFT_RankineMatGrad_L); + if ( L < 0.0 ) { + L = 0.0; + } + + mParam = 2.; + IR_GIVE_OPTIONAL_FIELD(ir, mParam, _IFT_RankineMatGrad_m); + negligible_damage = 0.; + IR_GIVE_OPTIONAL_FIELD(ir, negligible_damage, _IFT_RankineMatGrad_negligibleDamage); + + + int formulationType = 0; + IR_GIVE_OPTIONAL_FIELD(ir, formulationType, _IFT_RankineMatGrad_formulationType); + if ( formulationType == 0 ) { + this->gradientDamageFormulationType = GDFT_Standard; + } else if ( formulationType == 2 ) { + this->gradientDamageFormulationType = GDFT_Eikonal; + } else { + throw ValueInputException(ir, _IFT_RankineMatGrad_formulationType, "Unknown gradient damage formulation"); + } } +///////////////////////////////////////////////////////////////////////////// -int -RankineMatGrad :: hasMaterialModeCapability(MaterialMode mode) +bool +RankineMatGrad :: hasMaterialModeCapability(MaterialMode mode) const { return mode == _PlaneStress; } @@ -71,12 +97,39 @@ RankineMatGrad :: giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode } void -RankineMatGrad :: givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +RankineMatGrad :: giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { case _PlaneStress: - givePlaneStressStiffMtrx(answer, mode, gp, tStep); + if ( mode == ElasticStiffness ) { + this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + } else { + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + double tempDamage = status->giveTempDamage(); + double damage = status->giveDamage(); + double gprime; + // Note: + // The approximate solution of Helmholtz equation can lead + // to very small but nonzero nonlocal kappa at some points that + // are actually elastic. If such small values are positive, + // they lead to a very small but nonzero damage. If this is + // interpreted as "loading", the tangent terms are activated, + // but damage will not actually grow at such points and the + // convergence rate is slowed down. It is better to consider + // such points as elastic. + if ( tempDamage - damage <= negligible_damage ) { + gprime = 0.; + } else { + double nonlocalCumulatedStrain = status->giveNonlocalCumulatedStrain(); + double tempLocalCumulatedStrain = status->giveTempCumulativePlasticStrain(); + double overNonlocalCumulatedStrain = mParam * nonlocalCumulatedStrain + ( 1. - mParam ) * tempLocalCumulatedStrain; + gprime = computeDamageParamPrime(overNonlocalCumulatedStrain); + gprime *= ( 1. - mParam ); + } + + answer = evaluatePlaneStressStiffMtrx(mode, gp, tStep, gprime); + } break; default: OOFEM_ERROR("mMode = %d not supported\n", mMode); @@ -84,40 +137,297 @@ RankineMatGrad :: givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, } void -RankineMatGrad :: givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +RankineMatGrad :: giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { case _PlaneStress: - givePlaneStressGprime(answer, mode, gp, tStep); - break; + { + answer.resize(3, 1); + answer.zero(); + if ( mode != TangentStiffness ) { + return; + } + + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + double damage = status->giveDamage(); + double tempDamage = status->giveTempDamage(); + if ( tempDamage - damage <= negligible_damage ) { + return; + } + + double nonlocalCumulatedStrain = status->giveNonlocalCumulatedStrain(); + double tempCumulatedStrain = status->giveTempCumulativePlasticStrain(); + double overNonlocalCumulatedStrain = mParam * nonlocalCumulatedStrain + ( 1. - mParam ) * tempCumulatedStrain; + const FloatArray &tempEffStress = status->giveTempEffectiveStress(); + answer.at(1, 1) = tempEffStress.at(1); + answer.at(2, 1) = tempEffStress.at(2); + answer.at(3, 1) = tempEffStress.at(3); + double gPrime = computeDamageParamPrime(overNonlocalCumulatedStrain); + answer.times(-1. * gPrime * mParam); + } + break; default: OOFEM_ERROR("mMode = %d not supported\n", mMode); } } void -RankineMatGrad :: givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +RankineMatGrad :: giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { case _PlaneStress: - givePlaneStressKappaMatrix(answer, mode, gp, tStep); - break; + { + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + answer.resize(1, 3); + answer.zero(); + if ( mode != TangentStiffness ) { + return; + } + + double tempKappa = status->giveTempCumulativePlasticStrain(); + double dKappa = tempKappa - status->giveCumulativePlasticStrain(); + if ( dKappa <= 0. ) { + return; + } + + FloatArray eta(3); + double dkap1 = status->giveDKappa(1); + double H = evalPlasticModulus(tempKappa); + + // evaluate in principal coordinates + + if ( dkap1 == 0. ) { + // regular case + double Estar = E / ( 1. - nu * nu ); + double aux = Estar / ( H + Estar ); + eta.at(1) = aux; + eta.at(2) = nu * aux; + eta.at(3) = 0.; + } else { + // vertex case + double dkap2 = status->giveDKappa(2); + double denom = E * dkap1 + H * ( 1. - nu ) * ( dkap1 + dkap2 ); + eta.at(1) = E * dkap1 / denom; + eta.at(2) = E * dkap2 / denom; + eta.at(3) = 0.; + } + + // transform to global coordinates + + FloatArray sigPrinc(2); + FloatMatrix nPrinc(2, 2); + StressVector effStress(status->giveTempEffectiveStress(), _PlaneStress); + effStress.computePrincipalValDir(sigPrinc, nPrinc); + + FloatMatrix T = givePlaneStressVectorTranformationMtrx(nPrinc, true); + FloatArray etaglob(3); + etaglob.beProductOf(T, eta); + + answer.at(1, 1) = etaglob.at(1); + answer.at(1, 2) = etaglob.at(2); + answer.at(1, 3) = etaglob.at(3); + + if ( gradientDamageFormulationType == GDFT_Standard ) { + answer.times(1.); + } else if ( gradientDamageFormulationType == GDFT_Eikonal ) { + double iA = this->computeEikonalInternalLength_a(gp); + if ( iA != 0 ) { + answer.times(1. / iA); + } + } else { + OOFEM_WARNING("Unknown internalLengthDependenceType"); + } + } + break; default: OOFEM_ERROR("mMode = %d not supported\n", mMode); } } +void +RankineMatGrad :: giveGradientDamageStiffnessMatrix_du_NB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + if ( gradientDamageFormulationType == GDFT_Standard ) { + answer.clear(); + } else if ( gradientDamageFormulationType == GDFT_Eikonal ) { + MaterialMode mMode = gp->giveMaterialMode(); + switch ( mMode ) { + case _PlaneStress: + { + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + answer.resize(1, 3); + answer.zero(); + if ( mode != TangentStiffness ) { + return; + } + + double tempKappa = status->giveTempCumulativePlasticStrain(); + double dKappa = tempKappa - status->giveCumulativePlasticStrain(); + if ( dKappa <= 0. ) { + return; + } + + FloatArray eta(3); + double dkap1 = status->giveDKappa(1); + double H = evalPlasticModulus(tempKappa); + + // evaluate in principal coordinates + + if ( dkap1 == 0. ) { + // regular case + double Estar = E / ( 1. - nu * nu ); + double aux = Estar / ( H + Estar ); + eta.at(1) = aux; + eta.at(2) = nu * aux; + eta.at(3) = 0.; + } else { + // vertex case + double dkap2 = status->giveDKappa(2); + double denom = E * dkap1 + H * ( 1. - nu ) * ( dkap1 + dkap2 ); + eta.at(1) = E * dkap1 / denom; + eta.at(2) = E * dkap2 / denom; + eta.at(3) = 0.; + } + + // transform to global coordinates + + FloatArray sigPrinc(2); + FloatMatrix nPrinc(2, 2); + StressVector effStress(status->giveTempEffectiveStress(), _PlaneStress); + effStress.computePrincipalValDir(sigPrinc, nPrinc); + + FloatMatrix T = givePlaneStressVectorTranformationMtrx(nPrinc, true); + FloatArray etaglob(3); + etaglob.beProductOf(T, eta); + + answer.at(1, 1) = etaglob.at(1); + answer.at(1, 2) = etaglob.at(2); + answer.at(1, 3) = etaglob.at(3); + + double LocalCumulatedStrain = status->giveTempLocalDamageDrivingVariable(); + double NonLocalCumulatedStrain = status->giveTempNonlocalDamageDrivingVariable(); + answer.times(LocalCumulatedStrain - NonLocalCumulatedStrain); + double iA = this->computeEikonalInternalLength_a(gp); + if ( iA != 0 ) { + answer.times( 1. / ( iA * iA ) ); + } + double iAPrime = this->computeEikonalInternalLength_aPrime(gp); + double gPrime = this->computeDamageParamPrime(tempKappa); + answer.times(iAPrime * gPrime); + answer.times(1. - mParam); + } + break; + default: + OOFEM_ERROR("mMode = %d not supported\n", mMode); + } + } else { + OOFEM_WARNING("Unknown internalLengthDependenceType"); + } +} +void +RankineMatGrad :: giveGradientDamageStiffnessMatrix_du_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + if ( gradientDamageFormulationType == GDFT_Standard ) { + answer.clear(); + } else if ( gradientDamageFormulationType == GDFT_Eikonal ) { + MaterialMode mMode = gp->giveMaterialMode(); + switch ( mMode ) { + case _PlaneStress: + { + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + answer.resize(1, 3); + answer.zero(); + if ( mode != TangentStiffness ) { + return; + } + + double tempKappa = status->giveTempCumulativePlasticStrain(); + double dKappa = tempKappa - status->giveCumulativePlasticStrain(); + if ( dKappa <= 0. ) { + return; + } + + FloatArray eta(3); + double dkap1 = status->giveDKappa(1); + double H = evalPlasticModulus(tempKappa); + + // evaluate in principal coordinates + + if ( dkap1 == 0. ) { + // regular case + double Estar = E / ( 1. - nu * nu ); + double aux = Estar / ( H + Estar ); + eta.at(1) = aux; + eta.at(2) = nu * aux; + eta.at(3) = 0.; + } else { + // vertex case + double dkap2 = status->giveDKappa(2); + double denom = E * dkap1 + H * ( 1. - nu ) * ( dkap1 + dkap2 ); + eta.at(1) = E * dkap1 / denom; + eta.at(2) = E * dkap2 / denom; + eta.at(3) = 0.; + } + + // transform to global coordinates + + FloatArray sigPrinc(2); + FloatMatrix nPrinc(2, 2); + StressVector effStress(status->giveTempEffectiveStress(), _PlaneStress); + effStress.computePrincipalValDir(sigPrinc, nPrinc); + + FloatMatrix T = givePlaneStressVectorTranformationMtrx(nPrinc, true); + FloatArray etaglob(3); + etaglob.beProductOf(T, eta); + + FloatArray GradP = status->giveTempNonlocalDamageDrivingVariableGrad(); + answer.beDyadicProductOf(GradP, etaglob); + double iBPrime = this->computeEikonalInternalLength_bPrime(gp); + double gPrime = this->computeDamageParamPrime(tempKappa); + answer.times( iBPrime * gPrime * ( 1. - mParam ) ); + } + break; + default: + OOFEM_ERROR("mMode = %d not supported\n", mMode); + } + } else { + OOFEM_WARNING("Unknown internalLengthDependenceType"); + } +} void -RankineMatGrad :: givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +RankineMatGrad :: giveGradientDamageStiffnessMatrix_dd_NN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { case _PlaneStress: - giveInternalLength(answer, mode, gp, tStep); + if ( gradientDamageFormulationType == GDFT_Standard ) { + answer.clear(); + } else if ( gradientDamageFormulationType == GDFT_Eikonal ) { + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + answer.resize(1, 1); + answer.zero(); + double iA = this->computeEikonalInternalLength_a(gp); + + if ( iA != 0 ) { + answer.at(1, 1) += 1. / iA; + } + if ( mode == TangentStiffness ) { + double tempKappa = status->giveTempCumulativePlasticStrain(); + if ( tempKappa > status->giveCumulativePlasticStrain() && iA != 0 ) { + double iAPrime = this->computeEikonalInternalLength_aPrime(gp); + double gPrime = this->computeDamageParamPrime(tempKappa); + double LocalCumulatedStrain = status->giveTempLocalDamageDrivingVariable(); + double NonLocalCumulatedStrain = status->giveTempNonlocalDamageDrivingVariable(); + answer.at(1, 1) += iAPrime / iA / iA * gPrime * mParam * ( LocalCumulatedStrain - NonLocalCumulatedStrain ); + } + } + } else { + OOFEM_WARNING("Unknown internalLengthDependenceType"); + } break; default: OOFEM_ERROR("mMode = %d not supported\n", mMode); @@ -125,14 +435,59 @@ RankineMatGrad :: givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, } void -RankineMatGrad :: givePDGradMatrix_LD(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +RankineMatGrad :: giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { MaterialMode mMode = gp->giveMaterialMode(); - OOFEM_ERROR("mMode = %d not supported\n", mMode); + switch ( mMode ) { + case _PlaneStress: + { + int n = this->giveDimension(gp); + answer.resize(n, n); + answer.beUnitMatrix(); + if ( gradientDamageFormulationType == GDFT_Standard ) { + answer.times(internalLength * internalLength); + } else if ( gradientDamageFormulationType == GDFT_Eikonal ) { + double iB = this->computeEikonalInternalLength_b(gp); + answer.times(iB); + } else { + OOFEM_WARNING("Unknown internalLengthDependenceType"); + } + break; + } + default: + OOFEM_ERROR("mMode = %d not supported\n", mMode); + } } void -RankineMatGrad :: givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +RankineMatGrad :: giveGradientDamageStiffnessMatrix_dd_BN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +{ + if ( gradientDamageFormulationType == GDFT_Standard ) { + answer.clear(); + } else if ( gradientDamageFormulationType == GDFT_Eikonal ) { + MaterialMode mMode = gp->giveMaterialMode(); + switch ( mMode ) { + case _PlaneStress: + { + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + FloatArray GradP = status->giveTempNonlocalDamageDrivingVariableGrad(); + answer = GradP; + double iBPrime = this->computeEikonalInternalLength_bPrime(gp); + double tempKappa = status->giveTempCumulativePlasticStrain(); + double gPrime = this->computeDamageParamPrime(tempKappa); + answer.times(iBPrime * gPrime * mParam); + break; + } + default: + OOFEM_ERROR("mMode = %d not supported\n", mMode); + } + } else { + OOFEM_WARNING("Unknown internalLengthDependenceType"); + } +} + +FloatMatrixF<3,3> +RankineMatGrad :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); double tempDamage = status->giveTempDamage(); @@ -157,102 +512,53 @@ RankineMatGrad :: givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode gprime *= ( 1. - mParam ); } - evaluatePlaneStressStiffMtrx(answer, mode, gp, tStep, gprime); + return evaluatePlaneStressStiffMtrx(mode, gp, tStep, gprime); } -// derivative of kappa (result of stress return) wrt final strain void -RankineMatGrad :: givePlaneStressKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +RankineMatGrad :: giveInternalLength(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { - RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); - answer.resize(1, 3); - answer.zero(); - if ( mode != TangentStiffness ) { - return; - } - - double tempKappa = status->giveTempCumulativePlasticStrain(); - double dKappa = tempKappa - status->giveCumulativePlasticStrain(); - if ( dKappa <= 0. ) { - return; - } - - FloatArray eta(3); - double dkap1 = status->giveDKappa(1); - double H = evalPlasticModulus(tempKappa); - - // evaluate in principal coordinates - - if ( dkap1 == 0. ) { - // regular case - double Estar = E / ( 1. - nu * nu ); - double aux = Estar / ( H + Estar ); - eta.at(1) = aux; - eta.at(2) = nu * aux; - eta.at(3) = 0.; - } else { - // vertex case - double dkap2 = status->giveDKappa(2); - double denom = E * dkap1 + H * ( 1. - nu ) * ( dkap1 + dkap2 ); - eta.at(1) = E * dkap1 / denom; - eta.at(2) = E * dkap2 / denom; - eta.at(3) = 0.; - } - - // transform to global coordinates - - FloatArray sigPrinc(2); - FloatMatrix nPrinc(2, 2); - StressVector effStress(status->giveTempEffectiveStress(), _PlaneStress); - effStress.computePrincipalValDir(sigPrinc, nPrinc); - - FloatMatrix T(3, 3); - givePlaneStressVectorTranformationMtrx(T, nPrinc, true); - FloatArray etaglob(3); - etaglob.beProductOf(T, eta); - - answer.at(1, 1) = etaglob.at(1); - answer.at(1, 2) = etaglob.at(2); - answer.at(1, 3) = etaglob.at(3); + answer.resize(1, 1); + answer.at(1, 1) = L; } -// minus derivative of total stress wrt nonlocal kappa void -RankineMatGrad :: givePlaneStressGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +RankineMatGrad :: giveNonlocalInternalForces_N_factor(double &answer, double nlDamageDrivingVariable, GaussPoint *gp, TimeStep *tStep) { - answer.resize(3, 1); - answer.zero(); - if ( mode != TangentStiffness ) { - return; - } - + // I modified this one to put pnl -p instead of just pnl RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); - double damage = status->giveDamage(); - double tempDamage = status->giveTempDamage(); - if ( tempDamage - damage <= negligible_damage ) { - return; + double LocalCumulatedStrain = status->giveTempLocalDamageDrivingVariable(); + double NonLocalCumulatedStrain = status->giveTempNonlocalDamageDrivingVariable(); + answer = NonLocalCumulatedStrain - LocalCumulatedStrain; + if ( gradientDamageFormulationType == GDFT_Eikonal ) { + double iA = this->computeEikonalInternalLength_a(gp); + if ( iA != 0 ) { + answer = answer / iA; + } } +} - double nonlocalCumulatedStrain = status->giveNonlocalCumulatedStrain(); - double tempCumulatedStrain = status->giveTempCumulativePlasticStrain(); - double overNonlocalCumulatedStrain = mParam * nonlocalCumulatedStrain + ( 1. - mParam ) * tempCumulatedStrain; - const FloatArray &tempEffStress = status->giveTempEffectiveStress(); - answer.at(1, 1) = tempEffStress.at(1); - answer.at(2, 1) = tempEffStress.at(2); - answer.at(3, 1) = tempEffStress.at(3); - double gPrime = computeDamageParamPrime(overNonlocalCumulatedStrain); - answer.times(gPrime * mParam); +void +RankineMatGrad :: giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlDamageDrivingVariable_grad, GaussPoint *gp, TimeStep *tStep) +{ + answer = nlDamageDrivingVariable_grad; + if ( gradientDamageFormulationType == GDFT_Eikonal ) { + double iB = this->computeEikonalInternalLength_b(gp); + answer.times(iB); + } else { + answer.times(internalLength * internalLength); + } } void -RankineMatGrad :: giveInternalLength(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +RankineMatGrad :: computeLocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep) { - answer.resize(1, 1); - answer.at(1, 1) = L; + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + answer = status->giveTempCumulativePlasticStrain(); } void -RankineMatGrad :: giveRealStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) +RankineMatGrad :: giveRealStressVectorGradientDamage(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) { RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); @@ -281,42 +587,22 @@ RankineMatGrad :: giveRealStressVectorGrad(FloatArray &answer1, double &answer2, status->setKappa_hat(khat); } - -void -RankineMatGrad :: computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *tStep) +double +RankineMatGrad :: computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const { - RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); double localCumPlastStrain = status->giveTempCumulativePlasticStrain(); double nlCumPlastStrain = status->giveNonlocalCumulatedStrain(); - kappa = mParam * nlCumPlastStrain + ( 1. - mParam ) * localCumPlastStrain; + return mParam * nlCumPlastStrain + ( 1. - mParam ) * localCumPlastStrain; } double RankineMatGrad :: giveNonlocalCumPlasticStrain(GaussPoint *gp) { - RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); return status->giveNonlocalCumulatedStrain(); } -IRResultType -RankineMatGrad :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - IR_GIVE_FIELD(ir, L, _IFT_RankineMatGrad_L); - if ( L < 0.0 ) { - L = 0.0; - } - - mParam = 2.; - IR_GIVE_OPTIONAL_FIELD(ir, mParam, _IFT_RankineMatGrad_m); - - negligible_damage = 0.; - IR_GIVE_OPTIONAL_FIELD(ir, negligible_damage, _IFT_RankineMatGrad_negligibleDamage); - - return RankineMat :: initializeFrom(ir); -} - int RankineMatGrad :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) @@ -327,26 +613,80 @@ RankineMatGrad :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateT return 1; } else if ( type == IST_MaxEquivalentStrainLevel ) { answer.resize(1); - computeCumPlastStrain(answer.at(1), gp, tStep); + answer.at(1) = computeCumPlastStrain(gp, tStep); return 1; } else { return RankineMat :: giveIPValue(answer, gp, type, tStep); } } + +double +RankineMatGrad :: computeEikonalInternalLength_a(GaussPoint *gp) +{ + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + + double damage = status->giveTempDamage(); + return sqrt(1. - damage) * internalLength; +} + +double +RankineMatGrad :: computeEikonalInternalLength_b(GaussPoint *gp) +{ + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + + double damage = status->giveTempDamage(); + return sqrt(1. - damage) * internalLength; +} + + +double +RankineMatGrad :: computeEikonalInternalLength_aPrime(GaussPoint *gp) +{ + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + + double damage = status->giveTempDamage(); + return -0.5 / sqrt(1. - damage) * internalLength; +} + +double +RankineMatGrad :: computeEikonalInternalLength_bPrime(GaussPoint *gp) +{ + RankineMatGradStatus *status = static_cast< RankineMatGradStatus * >( this->giveStatus(gp) ); + + double damage = status->giveTempDamage(); + return -0.5 / sqrt(1. - damage) * internalLength; +} + +int +RankineMatGrad :: giveDimension(GaussPoint *gp) +{ + if ( gp->giveMaterialMode() == _1dMat ) { + return 1; + } else if ( gp->giveMaterialMode() == _PlaneStress ) { + return 2; + } else if ( gp->giveMaterialMode() == _PlaneStrain ) { + return 3; + } else if ( gp->giveMaterialMode() == _3dMat ) { + return 3; + } else { + return 0; + } +} + + + //============================================================================= // GRADIENT RANKINE MATERIAL STATUS //============================================================================= -RankineMatGradStatus :: RankineMatGradStatus(int n, Domain *d, GaussPoint *g) : - RankineMatStatus(n, d, g) -{ - nonlocalCumulatedStrain = 0; -} +RankineMatGradStatus :: RankineMatGradStatus(GaussPoint *g) : + RankineMatStatus(g) +{} void -RankineMatGradStatus :: printOutputAt(FILE *file, TimeStep *tStep) +RankineMatGradStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); diff --git a/src/sm/Materials/rankinematgrad.h b/src/sm/Materials/rankinematgrad.h index 42a758e88..5458cbd98 100644 --- a/src/sm/Materials/rankinematgrad.h +++ b/src/sm/Materials/rankinematgrad.h @@ -37,7 +37,7 @@ #include "rankinemat.h" #include "structuralnonlocalmaterialext.h" #include "nonlocmatstiffinterface.h" -#include "graddpmaterialextensioninterface.h" +#include "graddamagematerialextensioninterface.h" #include "cltypes.h" ///@name Input fields for RankineMatGrad @@ -46,90 +46,123 @@ #define _IFT_RankineMatGrad_L "l" #define _IFT_RankineMatGrad_m "m" #define _IFT_RankineMatGrad_negligibleDamage "negligible_damage" +#define _IFT_RankineMatGrad_formulationType "formtype" //@} namespace oofem { /** * Gradient rankine material status. */ -class RankineMatGradStatus : public RankineMatStatus, public GradDpMaterialStatusExtensionInterface +class RankineMatGradStatus : public RankineMatStatus, public GradientDamageMaterialStatusExtensionInterface { protected: - double kappa_nl; - double kappa_hat; + + /** Type characterizing the dependence of the internal lenght on variable of the state + * Note that the assigned numbers to enum values have to correspond to values + * used in initializeFrom to resolve internalLenghtDependence. If not, the consistency + * between initializeFrom and giveInputRecord methods is lost. + */ + + double kappa_nl = 0.; + double kappa_hat = 0.; public: - RankineMatGradStatus(int n, Domain * d, GaussPoint * g); - virtual ~RankineMatGradStatus() { } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + RankineMatGradStatus(GaussPoint *g); + + void printOutputAt(FILE *file, TimeStep *tStep) const override; // definition - virtual const char *giveClassName() const { return "RankineMatGradStatus"; } + const char *giveClassName() const override { return "RankineMatGradStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; void setKappa_nl(double kap) { kappa_nl = kap; } void setKappa_hat(double kap) { kappa_hat = kap; } double giveKappa_nl() { return kappa_nl; } double giveKappa_hat() { return kappa_hat; } - virtual double giveNonlocalCumulatedStrain() { return nonlocalCumulatedStrain; } - virtual void setNonlocalCumulatedStrain(double nonlocalCumulatedStrain) { this->nonlocalCumulatedStrain = nonlocalCumulatedStrain; } + virtual double giveNonlocalCumulatedStrain() { return nonlocalDamageDrivingVariable; } + virtual void setNonlocalCumulatedStrain(double nonlocalCumulatedStrain) { this->nonlocalDamageDrivingVariable = nonlocalCumulatedStrain; } }; /** * Gradient Rankine material. */ -class RankineMatGrad : public RankineMat, GradDpMaterialExtensionInterface +class RankineMatGrad : public RankineMat, GradientDamageMaterialExtensionInterface { protected: - double L; - double mParam; - double negligible_damage; + double L = 0.; + double mParam = 0.; + double negligible_damage = 0.; + + enum GradientDamageFormulationType { + GDFT_Standard = 0, + GDFT_Eikonal = 2 + }; + + GradientDamageFormulationType gradientDamageFormulationType = GDFT_Standard; + public: - RankineMatGrad(int n, Domain * d); - virtual ~RankineMatGrad() { } + RankineMatGrad(int n, Domain *d); - virtual const char *giveClassName() const { return "RankineMatGrad"; } - virtual const char *giveInputRecordName() const { return _IFT_RankineMatGrad_Name; } + const char *giveClassName() const override { return "RankineMatGrad"; } + const char *giveInputRecordName() const override { return _IFT_RankineMatGrad_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual Interface *giveInterface(InterfaceType t) { - if ( t == GradDpMaterialExtensionInterfaceType ) { - return static_cast< GradDpMaterialExtensionInterface * >(this); + void initializeFrom(InputRecord &ir) override; + bool hasMaterialModeCapability(MaterialMode mode) const override; + Interface *giveInterface(InterfaceType t) override { + if ( t == GradientDamageMaterialExtensionInterfaceType ) { + return static_cast< GradientDamageMaterialExtensionInterface * >( this ); } else { - return NULL; + return nullptr; } } - virtual void giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); + void giveStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override; - virtual void givePDGradMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_uk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_ku(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_kk(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void givePDGradMatrix_LD(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void giveRealStressVectorGrad(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep); + void giveGradientDamageStiffnessMatrix_uu(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_ud(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_du(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_du_NB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + void giveGradientDamageStiffnessMatrix_du_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + void giveGradientDamageStiffnessMatrix_dd_NN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_dd_BB(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; + void giveGradientDamageStiffnessMatrix_dd_BN(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) override; - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode, GaussPoint *gp, TimeStep *tStep); + void computeLocalDamageDrivingVariable(double &answer, GaussPoint *gp, TimeStep *tStep) override; + + void giveNonlocalInternalForces_N_factor(double &answer, double nlddv, GaussPoint *gp, TimeStep *tStep) override; + void giveNonlocalInternalForces_B_factor(FloatArray &answer, const FloatArray &nlddv, GaussPoint *gp, TimeStep *tStep) override; + + + void giveRealStressVectorGradientDamage(FloatArray &answer1, double &answer2, GaussPoint *gp, const FloatArray &totalStrain, double nonlocalCumulatedStrain, TimeStep *tStep) override; + + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode, GaussPoint * gp, TimeStep * tStep) const override; void givePlaneStressGprime(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); void givePlaneStressKappaMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); void giveInternalLength(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - virtual void computeCumPlastStrain(double &kappa, GaussPoint *gp, TimeStep *tStep); + double computeCumPlastStrain(GaussPoint *gp, TimeStep *tStep) const override; double giveNonlocalCumPlasticStrain(GaussPoint *gp); void performPlasticityReturn(GaussPoint *gp, const FloatArray &totalStrain); LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; protected: - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new RankineMatGradStatus(1, RankineMat :: domain, gp); } + double computeInternalLength(GaussPoint *gp); + int giveDimension(GaussPoint *gp); + + double computeEikonalInternalLength_a(GaussPoint *gp); + double computeEikonalInternalLength_b(GaussPoint *gp); + double computeEikonalInternalLength_aPrime(GaussPoint *gp); + double computeEikonalInternalLength_bPrime(GaussPoint *gp); + + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new RankineMatGradStatus(gp); } }; } // end namespace oofem #define RankineMatGrad_h diff --git a/src/sm/Materials/rankinematnl.C b/src/sm/Materials/rankinematnl.C index 504ce07ce..424107172 100644 --- a/src/sm/Materials/rankinematnl.C +++ b/src/sm/Materials/rankinematnl.C @@ -33,7 +33,7 @@ */ #include "rankinematnl.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" @@ -48,71 +48,64 @@ namespace oofem { REGISTER_Material(RankineMatNl); RankineMatNl :: RankineMatNl(int n, Domain *d) : RankineMat(n, d), StructuralNonlocalMaterialExtensionInterface(d), NonlocalMaterialStiffnessInterface() - // - // constructor - // { } -void -RankineMatNl :: giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, - const FloatArray &totalStrain, TimeStep *tStep) +FloatArrayF<3> +RankineMatNl :: giveRealStressVector_PlaneStress(const FloatArrayF<3> &totalStrain, GaussPoint *gp, TimeStep *tStep) const { - RankineMatNlStatus *nlStatus = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); + auto nlStatus = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); - double tempDam; //mj performPlasticityReturn(gp, totalStrain, mode); // nonlocal method "computeDamage" performs the plastic return // for all Gauss points when it is called for the first time // in the iteration - tempDam = this->computeDamage(gp, tStep); - answer.beScaled(1.0 - tempDam, nlStatus->giveTempEffectiveStress()); + double tempDam = this->computeDamage(gp, tStep); + FloatArrayF<6> stress = (1.0 - tempDam) * nlStatus->giveTempEffectiveStress(); nlStatus->setTempDamage(tempDam); nlStatus->letTempStrainVectorBe(totalStrain); - nlStatus->letTempStressVectorBe(answer); + nlStatus->letTempStressVectorBe(stress); #ifdef keep_track_of_dissipated_energy double gf = sig0 * sig0 / E; // only estimated, but OK for this purpose nlStatus->computeWork_PlaneStress(gp, gf); #endif + return stress[{0, 1, 5}]; } -void -RankineMatNl :: giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, - const FloatArray &totalStrain, TimeStep *tStep) +FloatArrayF<1> +RankineMatNl :: giveRealStressVector_1d(const FloatArrayF<1> &totalStrain, GaussPoint *gp, TimeStep *tStep) const { - RankineMatNlStatus *nlStatus = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); + auto nlStatus = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); - double tempDam; //mj performPlasticityReturn(gp, totalStrain, mode); // nonlocal method "computeDamage" performs the plastic return // for all Gauss points when it is called for the first time // in the iteration - tempDam = this->computeDamage(gp, tStep); - answer.beScaled(1.0 - tempDam, nlStatus->giveTempEffectiveStress()); + double tempDam = this->computeDamage(gp, tStep); + FloatArrayF<6> stress = (1.0 - tempDam) * nlStatus->giveTempEffectiveStress(); nlStatus->setTempDamage(tempDam); nlStatus->letTempStrainVectorBe(totalStrain); - nlStatus->letTempStressVectorBe(answer); + nlStatus->letTempStressVectorBe(stress); #ifdef keep_track_of_dissipated_energy double gf = sig0 * sig0 / E; // only estimated, but OK for this purpose nlStatus->computeWork_1d(gp, gf); #endif + return stress[{0}]; } -void -RankineMatNl :: givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +RankineMatNl :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { if ( mode == ElasticStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); - return; + return this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep); } - RankineMatNlStatus *status = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); if ( mode == SecantStiffness ) { - this->giveLinearElasticMaterial()->giveStiffnessMatrix(answer, mode, gp, tStep); + auto d = this->linearElasticMaterial->givePlaneStressStiffMtrx(mode, gp, tStep); double damage = status->giveTempDamage(); - answer.times(1. - damage); - return; + return d * (1. - damage); } if ( mode == TangentStiffness ) { @@ -122,21 +115,19 @@ RankineMatNl :: givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mo if ( tempDamage <= damage ) { // unloading gprime = 0.; } else { // loading - double kappa; - computeCumPlasticStrain(kappa, gp, tStep); + double kappa = computeCumPlasticStrain(gp, tStep); gprime = computeDamageParamPrime(kappa); gprime *= ( 1. - mm ); } - evaluatePlaneStressStiffMtrx(answer, mode, gp, tStep, gprime); - return; + return evaluatePlaneStressStiffMtrx(mode, gp, tStep, gprime); } OOFEM_ERROR("unknown type of stiffness"); } void -RankineMatNl :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) +RankineMatNl :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const { /* Implements the service updating local variables in given integration points, * which take part in nonlocal average process. Actually, no update is necessary, @@ -144,23 +135,36 @@ RankineMatNl :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussP * computation. It is therefore necessary only to store local strain in corresponding status. * This service is declared at StructuralNonlocalMaterial level. */ - - double cumPlasticStrain; - RankineMatNlStatus *nlstatus = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); + auto nlstatus = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); this->performPlasticityReturn(gp, strainVector); - this->computeLocalCumPlasticStrain(cumPlasticStrain, gp, tStep); + double cumPlasticStrain = this->computeLocalCumPlasticStrain(gp, tStep); // standard formulation based on averaging of equivalent strain nlstatus->setLocalCumPlasticStrainForAverage(cumPlasticStrain); + // influence of damage on weight function + if ( averType >= 2 && averType <= 6 ) { + this->modifyNonlocalWeightFunctionAround(gp); + } +} + +double +RankineMatNl :: giveNonlocalMetricModifierAt(GaussPoint *gp) const +{ + auto status = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); + double damage = status->giveTempDamage(); + if ( damage == 0. ) { + damage = status->giveDamage(); + } + return damage; } // returns in "kappa" the value of kappa_hat = m*kappa_nonlocal + (1-m)*kappa_local -void -RankineMatNl :: computeCumPlasticStrain(double &kappa, GaussPoint *gp, TimeStep *tStep) +double +RankineMatNl :: computeCumPlasticStrain(GaussPoint *gp, TimeStep *tStep) const { - double nonlocalContribution, nonlocalCumPlasticStrain = 0.0; - RankineMatNlStatus *nonlocStatus, *status = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); + double nonlocalCumPlasticStrain = 0.0; this->buildNonlocalPointTable(gp); this->updateDomainBeforeNonlocAverage(tStep); @@ -169,8 +173,8 @@ RankineMatNl :: computeCumPlasticStrain(double &kappa, GaussPoint *gp, TimeStep auto list = this->giveIPIntegrationList(gp); for ( auto &lir: *list ) { - nonlocStatus = static_cast< RankineMatNlStatus * >( this->giveStatus(lir.nearGp) ); - nonlocalContribution = nonlocStatus->giveLocalCumPlasticStrainForAverage(); + auto nonlocStatus = static_cast< RankineMatNlStatus * >( this->giveStatus(lir.nearGp) ); + double nonlocalContribution = nonlocStatus->giveLocalCumPlasticStrainForAverage(); if ( nonlocalContribution > 0 ) { nonlocalContribution *= lir.weight; } @@ -189,9 +193,10 @@ RankineMatNl :: computeCumPlasticStrain(double &kappa, GaussPoint *gp, TimeStep } } - kappa = mm * nonlocalCumPlasticStrain + ( 1. - mm ) * localCumPlasticStrain; + double kappa = mm * nonlocalCumPlasticStrain + ( 1. - mm ) * localCumPlasticStrain; status->setKappa_nl(nonlocalCumPlasticStrain); status->setKappa_hat(kappa); + return kappa; } Interface * @@ -202,20 +207,16 @@ RankineMatNl :: giveInterface(InterfaceType type) } else if ( type == NonlocalMaterialStiffnessInterfaceType ) { return static_cast< NonlocalMaterialStiffnessInterface * >(this); } else { - return NULL; + return nullptr; } } -IRResultType -RankineMatNl :: initializeFrom(InputRecord *ir) +void +RankineMatNl :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - - return RankineMat :: initializeFrom(ir); + RankineMat :: initializeFrom(ir); + StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); } @@ -229,14 +230,12 @@ RankineMatNl :: giveInputRecord(DynamicInputRecord &input) double -RankineMatNl :: computeDamage(GaussPoint *gp, TimeStep *tStep) +RankineMatNl :: computeDamage(GaussPoint *gp, TimeStep *tStep) const { - RankineMatNlStatus *nlStatus = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); - double nlKappa; - this->computeCumPlasticStrain(nlKappa, gp, tStep); - double dam, tempDam; - dam = nlStatus->giveDamage(); - tempDam = this->computeDamageParam(nlKappa); + auto nlStatus = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); + double nlKappa = this->computeCumPlasticStrain(gp, tStep); + double dam = nlStatus->giveDamage(); + double tempDam = this->computeDamageParam(nlKappa); if ( tempDam < dam ) { tempDam = dam; } @@ -257,10 +256,8 @@ void RankineMatNl :: NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx &dest, const UnknownNumberingScheme &s, GaussPoint *gp, TimeStep *tStep) { - double coeff; - RankineMatNlStatus *status = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); auto list = status->giveIntegrationDomainList(); - RankineMatNl *rmat; FloatArray rcontrib, lcontrib; IntArray loc, rloc; @@ -271,10 +268,10 @@ RankineMatNl :: NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx } for ( auto &lir: *list ) { - rmat = dynamic_cast< RankineMatNl * >( lir.nearGp->giveMaterial() ); + auto rmat = dynamic_cast< RankineMatNl * >( lir.nearGp->giveMaterial() ); if ( rmat ) { rmat->giveRemoteNonlocalStiffnessContribution(lir.nearGp, rloc, s, rcontrib, tStep); - coeff = gp->giveElement()->computeVolumeAround(gp) * lir.weight / status->giveIntegrationScale(); + double coeff = gp->giveElement()->computeVolumeAround(gp) * lir.weight / status->giveIntegrationScale(); contrib.clear(); contrib.plusDyadUnsym(lcontrib, rcontrib, - 1.0 * coeff); @@ -286,7 +283,7 @@ RankineMatNl :: NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx std :: vector< localIntegrationRecord > * RankineMatNl :: NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(GaussPoint *gp) { - RankineMatNlStatus *status = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); this->buildNonlocalPointTable(gp); return status->giveIntegrationDomainList(); } @@ -300,7 +297,7 @@ RankineMatNl :: giveLocalNonlocalStiffnessContribution(GaussPoint *gp, IntArray FloatArray &lcontrib, TimeStep *tStep) { int nrows, nsize; - double sum, nlKappa, damage, tempDamage; + double sum, damage, tempDamage; RankineMatNlStatus *status = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); StructuralElement *elem = static_cast< StructuralElement * >( gp->giveElement() ); FloatMatrix b; @@ -314,7 +311,7 @@ RankineMatNl :: giveLocalNonlocalStiffnessContribution(GaussPoint *gp, IntArray elem->giveLocationArray(loc, s); const FloatArray &stress = status->giveTempEffectiveStress(); elem->computeBmatrixAt(gp, b); - this->computeCumPlasticStrain(nlKappa, gp, tStep); + double nlKappa = this->computeCumPlasticStrain(gp, tStep); double factor = computeDamageParamPrime(nlKappa); factor *= mm; // this factor is m*gprime nrows = b.giveNumberOfColumns(); @@ -374,15 +371,14 @@ RankineMatNl :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateTyp { if ( type == IST_CumPlasticStrain_2 ) { answer.resize(1); - double dummy; // this method also stores the nonlocal kappa in status ... kappa_nl - computeCumPlasticStrain(dummy, gp, tStep); + computeCumPlasticStrain(gp, tStep); RankineMatNlStatus *status = static_cast< RankineMatNlStatus * >( this->giveStatus(gp) ); answer.at(1) = status->giveKappa_nl(); return 1; } else if ( type == IST_MaxEquivalentStrainLevel ) { answer.resize(1); - computeCumPlasticStrain(answer.at(1), gp, tStep); + answer.at(1) = computeCumPlasticStrain(gp, tStep); return 1; } else { return RankineMat :: giveIPValue(answer, gp, type, tStep); @@ -394,19 +390,13 @@ RankineMatNl :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateTyp //*************status************ //******************************* -RankineMatNlStatus :: RankineMatNlStatus(int n, Domain *d, GaussPoint *g) : - RankineMatStatus(n, d, g), StructuralNonlocalMaterialStatusExtensionInterface() -{ - localCumPlasticStrainForAverage = 0.0; -} - - -RankineMatNlStatus :: ~RankineMatNlStatus() -{ } +RankineMatNlStatus :: RankineMatNlStatus(GaussPoint *g) : + RankineMatStatus(g), StructuralNonlocalMaterialStatusExtensionInterface() +{} void -RankineMatNlStatus :: printOutputAt(FILE *file, TimeStep *tStep) +RankineMatNlStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); @@ -440,39 +430,18 @@ RankineMatNlStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -RankineMatNlStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +RankineMatNlStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // save parent class status - if ( ( iores = RankineMatStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - //if (!stream.write(&localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); - return CIO_OK; + RankineMatStatus :: saveContext(stream, mode); + //if (!stream.write(localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); } -contextIOResultType -RankineMatNlStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +RankineMatNlStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - // read parent class status - if ( ( iores = RankineMatStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data - //if (!stream.read (&localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); - - return CIO_OK; + RankineMatStatus :: restoreContext(stream, mode); + //if (!stream.read(localEquivalentStrainForAverage,1)) THROW_CIOERR(CIO_IOERR); } Interface * diff --git a/src/sm/Materials/rankinematnl.h b/src/sm/Materials/rankinematnl.h index 9cf89eb3e..202d258e4 100644 --- a/src/sm/Materials/rankinematnl.h +++ b/src/sm/Materials/rankinematnl.h @@ -38,6 +38,7 @@ #include "rankinemat.h" #include "structuralnonlocalmaterialext.h" #include "nonlocmatstiffinterface.h" +#include "nonlocalmaterialext.h" #include "cltypes.h" #define _IFT_RankineMatNl_Name "rankmatnl" @@ -50,37 +51,35 @@ class RankineMatNlStatus : public RankineMatStatus, public StructuralNonlocalMat { protected: /// Equivalent strain for averaging. - double localCumPlasticStrainForAverage; + double localCumPlasticStrainForAverage = 0.; /// For printing only - double kappa_nl; - double kappa_hat; + double kappa_nl = 0.; + double kappa_hat = 0.; public: - RankineMatNlStatus(int n, Domain * d, GaussPoint * g); - virtual ~RankineMatNlStatus(); + RankineMatNlStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - double giveLocalCumPlasticStrainForAverage() { return localCumPlasticStrainForAverage; } - const FloatArray *giveLTangentContrib(); + double giveLocalCumPlasticStrainForAverage() const { return localCumPlasticStrainForAverage; } void setLocalCumPlasticStrainForAverage(double ls) { localCumPlasticStrainForAverage = ls; } - virtual const char *giveClassName() const { return "RankineMatNlStatus"; } + const char *giveClassName() const override { return "RankineMatNlStatus"; } - virtual void initTempStatus(); + void initTempStatus() override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; void setKappa_nl(double kap) { kappa_nl = kap; } void setKappa_hat(double kap) { kappa_hat = kap; } - double giveKappa_nl() { return kappa_nl; } - double giveKappa_hat() { return kappa_hat; } + double giveKappa_nl() const { return kappa_nl; } + double giveKappa_hat() const { return kappa_hat; } - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; }; @@ -92,17 +91,14 @@ public NonlocalMaterialStiffnessInterface { public: RankineMatNl(int n, Domain * d); - virtual ~RankineMatNl() { - ; - } - virtual const char *giveClassName() const { return "RankineMatNl"; } - virtual const char *giveInputRecordName() const { return _IFT_RankineMatNl_Name; } + const char *giveClassName() const override { return "RankineMatNl"; } + const char *giveInputRecordName() const override { return _IFT_RankineMatNl_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; /** * Computes the nonlocal cumulated plastic strain from its local form. @@ -110,29 +106,29 @@ public NonlocalMaterialStiffnessInterface * @param gp integration point. * @param tStep time step. */ - virtual void computeCumPlasticStrain(double &kappa, GaussPoint *gp, TimeStep *tStep); - double computeDamage(GaussPoint *gp, TimeStep *tStep); - void modifyNonlocalWeightFunctionAround(GaussPoint *gp); - double computeDistanceModifier(double damage); - void computeLocalCumPlasticStrain(double &kappa, GaussPoint *gp, TimeStep *tStep) + virtual double computeCumPlasticStrain(GaussPoint *gp, TimeStep *tStep) const; + double computeDamage(GaussPoint *gp, TimeStep *tStep) const; + //void modifyNonlocalWeightFunctionAround(GaussPoint *gp); + double computeDistanceModifier(double damage) const; + double computeLocalCumPlasticStrain(GaussPoint *gp, TimeStep *tStep) const { - RankineMat :: computeCumPlastStrain(kappa, gp, tStep); + return RankineMat :: computeCumPlastStrain(gp, tStep); } - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep); - //virtual void givePlaneStrainStiffMtrx(FloatMatrix& answer, MatResponseMode,GaussPoint * gp,TimeStep * tStep); - //virtual void give3dMaterialStiffnessMatrix(FloatMatrix& answer, MatResponseMode,GaussPoint* gp, TimeStep* tStep); + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + //void givePlaneStrainStiffMtrx(FloatMatrix& answer, MatResponseMode,GaussPoint * gp,TimeStep * tStep) override; + //void give3dMaterialStiffnessMatrix(FloatMatrix& answer, MatResponseMode,GaussPoint* gp, TimeStep* tStep) override; #ifdef __OOFEG // Plots the sparse structure of stiffness contribution. - //virtual void NonlocalMaterialStiffnessInterface_showSparseMtrxStructure(GaussPoint *gp, oofegGraphicContext &gc, TimeStep *tStep); + //void NonlocalMaterialStiffnessInterface_showSparseMtrxStructure(GaussPoint *gp, oofegGraphicContext &gc, TimeStep *tStep) override; #endif - virtual void NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx &dest, const UnknownNumberingScheme &s, - GaussPoint *gp, TimeStep *tStep); + void NonlocalMaterialStiffnessInterface_addIPContribution(SparseMtrx &dest, const UnknownNumberingScheme &s, + GaussPoint *gp, TimeStep *tStep) override; - virtual std :: vector< localIntegrationRecord > *NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(GaussPoint *gp); + std :: vector< localIntegrationRecord > *NonlocalMaterialStiffnessInterface_giveIntegrationDomainList(GaussPoint *gp) override; /** * Computes the "local" part of nonlocal stiffness contribution assembled for given integration point. @@ -164,23 +160,26 @@ public NonlocalMaterialStiffnessInterface // @param tStep time step // void giveNormalElasticStiffnessMatrix (FloatMatrix& answer, MatResponseMode rMode, GaussPoint*gp, TimeStep* tStep) ; - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &strainVector, TimeStep *tStep); + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const override; // Computes 1D stress - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &strainVector, TimeStep *tStep); + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strain, GaussPoint *gp, TimeStep *tStep) const override; + + void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const override; - virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep); + /// Compute the factor that specifies how the interaction length should be modified (by eikonal nonlocal damage models) + double giveNonlocalMetricModifierAt(GaussPoint *gp) const override; - virtual int hasBoundedSupport() { return 1; } + int hasBoundedSupport() const override { return 1; } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int estimatePackSize(DataStream &buff, GaussPoint *ip); + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int estimatePackSize(DataStream &buff, GaussPoint *ip) override; protected: - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new RankineMatNlStatus(1, RankineMat :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new RankineMatNlStatus(gp); } }; } // end namespace oofem #endif diff --git a/src/sm/Materials/rcm2.C b/src/sm/Materials/rcm2.C index 80ca0bcbe..3dfa04a87 100644 --- a/src/sm/Materials/rcm2.C +++ b/src/sm/Materials/rcm2.C @@ -46,25 +46,12 @@ namespace oofem { #define rcm_RESIDUALSTIFFFACTOR 1.e-3 RCM2Material :: RCM2Material(int n, Domain *d) : StructuralMaterial(n, d) - // - // constructor - // { - linearElasticMaterial = NULL; - Gf = Ft = 0.; } -RCM2Material :: ~RCM2Material() -// -// destructor -// -{ - //delete linearElasticMaterial; -} - -int -RCM2Material :: hasMaterialModeCapability(MaterialMode mode) +bool +RCM2Material :: hasMaterialModeCapability(MaterialMode mode) const // // returns whether receiver supports given mode // @@ -147,7 +134,7 @@ RCM2Material :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, princStress.resizeWithValues(6); tempCrackDirs = status->giveTempCrackDirs(); - this->transformStressVectorTo(answer, tempCrackDirs, princStress, 1); + answer = this->transformStressVectorTo(tempCrackDirs, princStress, 1); status->letTempStrainVectorBe(totalStrain); StructuralMaterial :: giveReducedSymVectorForm( reducedStressVector, answer, gp->giveMaterialMode() ); @@ -206,8 +193,8 @@ RCM2Material :: giveRealPrincipalStressVector3d(FloatArray &answer, GaussPoint * // keep old principal values status->letTempCrackDirsBe(crackDirs); } else { - this->sortPrincDirAndValCloseTo(& principalStrain, - & tempCrackDirs, & crackDirs); + this->sortPrincDirAndValCloseTo(principalStrain, + tempCrackDirs, crackDirs); status->letTempCrackDirsBe(tempCrackDirs); } @@ -708,7 +695,7 @@ RCM2Material :: giveEffectiveMaterialStiffnessMatrix(FloatMatrix &answer, // final step - transform stiffnes to global c.s // - this->giveStressVectorTranformationMtrx(t, tempCrackDirs, 1); + t = this->giveStressVectorTranformationMtrx(tempCrackDirs, 1); df.rotatedWith(t, 't'); StructuralMaterial :: giveReducedSymMatrixForm( answer, df, gp->giveMaterialMode() ); @@ -792,11 +779,9 @@ RCM2Material :: updateActiveCrackMap(GaussPoint *gp, const IntArray *activatedCr } -IRResultType -RCM2Material :: initializeFrom(InputRecord *ir) +void +RCM2Material :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, Gf, _IFT_RCM2Material_gf); IR_GIVE_FIELD(ir, Ft, _IFT_RCM2Material_ft); @@ -804,7 +789,7 @@ RCM2Material :: initializeFrom(InputRecord *ir) } double -RCM2Material :: give(int aProperty, GaussPoint *gp) +RCM2Material :: give(int aProperty, GaussPoint *gp) const // Returns the value of the property aProperty (e.g. the Young's modulus // 'E') of the receiver. { @@ -867,30 +852,40 @@ RCM2Material :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateTyp } return 1; + + } else if ( type == IST_CrackWidth ) { + double width; + answer.resize(1); + answer.zero(); + + // MAX WIDTH + width = 0.; + for ( int i = 1; i <= status->giveNumberOfActiveCracks(); i++ ) { + width = max( width, status->giveCharLength(i) * status->giveCrackStrain(i) ); + } + answer.at(1) = width; + return 1; + } else { return StructuralMaterial :: giveIPValue(answer, gp, type, tStep); } } -void -RCM2Material :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<6,6> +RCM2Material :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - // - // returns receiver 3d material matrix - // - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } -void -RCM2Material :: givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<3,3> +RCM2Material :: givePlaneStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) - + TimeStep *tStep) const // // returns receiver's 2dPlaneStressMtrx // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -899,15 +894,16 @@ RCM2Material :: givePlaneStressStiffMtrx(FloatMatrix &answer, // the reduction from 3d case will not work // this implementation should be faster. { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } -void -RCM2Material :: givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<4,4> +RCM2Material :: givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // return receiver's 2dPlaneStrainMtrx constructed from @@ -915,29 +911,33 @@ RCM2Material :: givePlaneStrainStiffMtrx(FloatMatrix &answer, // (2dPlaneStrain ==> eps_z = gamma_xz = gamma_yz = 0.) // { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + /// FIXME: Temporary const-cast until other routines have been made const. + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } -void -RCM2Material :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<1,1> +RCM2Material :: give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 1dMaterialStiffnessMAtrix // (1d case ==> sigma_y = sigma_z = tau_yz = tau_zx = tau_xy = 0.) { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + /// FIXME: Temporary const-cast until other routines have been made const. + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } -void -RCM2Material :: give2dBeamLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<2,2> +RCM2Material :: give2dBeamLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dBeamLayerStiffMtrx. // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -946,15 +946,17 @@ RCM2Material :: give2dBeamLayerStiffMtrx(FloatMatrix &answer, // the reduction from 3d case will not work // this implementation should be faster. { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + /// FIXME: Temporary const-cast until other routines have been made const. + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } -void -RCM2Material :: givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, +FloatMatrixF<5,5> +RCM2Material :: givePlateLayerStiffMtrx(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const // // returns receiver's 2dPlateLayerMtrx // (2dPlaneStres ==> sigma_z = tau_xz = tau_yz = 0.) @@ -963,14 +965,17 @@ RCM2Material :: givePlateLayerStiffMtrx(FloatMatrix &answer, // the reduction from 3d case will not work // this implementation should be faster. { - this->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + /// FIXME: Temporary const-cast until other routines have been made const. + FloatMatrix answer; + const_cast(this)->giveMaterialStiffnessMatrix(answer, mode, gp, tStep); + return answer; } -RCM2MaterialStatus :: RCM2MaterialStatus(int n, Domain *d, GaussPoint *g) : - StructuralMaterialStatus(n, d, g), crackStatuses(3), tempCrackStatuses(3), +RCM2MaterialStatus :: RCM2MaterialStatus(GaussPoint *g) : + StructuralMaterialStatus(g), crackStatuses(3), tempCrackStatuses(3), maxCrackStrains(3), tempMaxCrackStrains(3), crackStrainVector(3), oldCrackStrainVector(3), crackDirs(3, 3), tempCrackDirs(3, 3), charLengths(3), //minEffStrainsForFullyOpenCrack(3), @@ -983,11 +988,6 @@ RCM2MaterialStatus :: RCM2MaterialStatus(int n, Domain *d, GaussPoint *g) : } -RCM2MaterialStatus :: ~RCM2MaterialStatus() -{ } - - - int RCM2MaterialStatus :: isCrackActive(int i) const // @@ -1007,15 +1007,14 @@ RCM2MaterialStatus :: isCrackActive(int i) const } void -RCM2MaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +RCM2MaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { - int i; char s [ 11 ]; StructuralMaterialStatus :: printOutputAt(file, tStep); fprintf(file, "status { "); if ( this->giveTempAlreadyCrack() ) { - for ( i = 1; i <= 3; i++ ) { + for ( int i = 1; i <= 3; i++ ) { switch ( crackStatuses.at(i) ) { case pscm_NONE: strcpy(s, "NONE"); @@ -1127,22 +1126,12 @@ RCM2MaterialStatus :: updateYourself(TimeStep *tStep) -contextIOResultType -RCM2MaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +RCM2MaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write a raw data + StructuralMaterialStatus :: saveContext(stream, mode); + contextIOResultType iores; if ( ( iores = crackStatuses.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -1187,25 +1176,14 @@ RCM2MaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *ob if ( ( iores = crackMap.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -RCM2MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +RCM2MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data + StructuralMaterialStatus :: restoreContext(stream, mode); + contextIOResultType iores; if ( ( iores = crackStatuses.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -1250,7 +1228,5 @@ RCM2MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void if ( ( iores = crackMap.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; // return succes } } // end namespace oofem diff --git a/src/sm/Materials/rcm2.h b/src/sm/Materials/rcm2.h index d5b7bf900..7f5b53dcf 100644 --- a/src/sm/Materials/rcm2.h +++ b/src/sm/Materials/rcm2.h @@ -36,9 +36,9 @@ #define rcm2_h #include "material.h" -#include "Materials/linearelasticmaterial.h" -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/linearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "intarray.h" ///@name Input fields for RCM2Material @@ -101,10 +101,9 @@ class RCM2MaterialStatus : public StructuralMaterialStatus IntArray crackMap; public: - RCM2MaterialStatus(int n, Domain * d, GaussPoint * g); - virtual ~RCM2MaterialStatus(); + RCM2MaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; const FloatArray &getPrincipalStrainVector() const { return principalStrain; } const FloatArray &getPrincipalStressVector() const { return principalStress; } @@ -152,15 +151,13 @@ class RCM2MaterialStatus : public StructuralMaterialStatus const IntArray &giveCrackStatus() { return crackStatuses; } int giveAlreadyCrack() const { return this->giveNumberOfActiveCracks(); } - // definition - virtual const char *giveClassName() const { return "RCM2MaterialStatus"; } + const char *giveClassName() const override { return "RCM2MaterialStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - // saves current context(state) into stream - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; /** @@ -178,53 +175,71 @@ class RCM2MaterialStatus : public StructuralMaterialStatus class RCM2Material : public StructuralMaterial { protected: - LinearElasticMaterial *linearElasticMaterial; - double Gf, Ft; - //double beta; + LinearElasticMaterial *linearElasticMaterial = nullptr; + double Gf = 0., Ft = 0.; + //double beta = 0.; public: RCM2Material(int n, Domain * d); - virtual ~RCM2Material(); - // identification and auxiliary functions - virtual int hasNonLinearBehaviour() { return 1; } - virtual int hasMaterialModeCapability(MaterialMode mode); + bool hasMaterialModeCapability(MaterialMode mode) const override; - virtual const char *giveClassName() const { return "RCM2Material"; } + const char *giveClassName() const override { return "RCM2Material"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual double give(int aProperty, GaussPoint *gp); + double give(int aProperty, GaussPoint *gp) const override; LinearElasticMaterial *giveLinearElasticMaterial() { return linearElasticMaterial; } - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); - - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_2dBeamLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } - virtual void giveRealStressVector_PlateLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep) override; + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<4> giveRealStressVector_PlaneStrain(const FloatArrayF<4> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<1> giveRealStressVector_1d(const FloatArrayF<1> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<2> giveRealStressVector_2dBeamLayer(const FloatArrayF<2> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } + FloatArrayF<5> giveRealStressVector_PlateLayer(const FloatArrayF<5> &strain, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast(this)->giveRealStressVector(answer, gp, strain, tStep); + return answer; + } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new RCM2MaterialStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new RCM2MaterialStatus(gp); } - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) { linearElasticMaterial->giveThermalDilatationVector(answer, gp, tStep); } + FloatArrayF<6> giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override + { return linearElasticMaterial->giveThermalDilatationVector(gp, tStep); } protected: @@ -233,7 +248,7 @@ class RCM2Material : public StructuralMaterial virtual void updateCrackStatus(GaussPoint *gp, const FloatArray &crackStrain); virtual void checkIfClosedCracks(GaussPoint *gp, FloatArray &crackStrainVector, IntArray &); - virtual int checkSizeLimit(GaussPoint *gp, double) { return 0; } + virtual int checkSizeLimit(GaussPoint *gp, double) { return 0; } virtual double giveNormalCrackingStress(GaussPoint *gp, double eps_cr, int i) = 0; virtual double giveMinCrackStrainsForFullyOpenCrack(GaussPoint *gp, int i) = 0; virtual double computeStrength(GaussPoint *gp, double) = 0; @@ -254,7 +269,6 @@ class RCM2Material : public StructuralMaterial * void computeTrialStressIncrement (FloatArray& answer, GaussPoint *gp, * const FloatArray& strainIncrement, TimeStep* tStep); */ - FloatMatrix *GiveCrackTransformationMtrx(GaussPoint *gp, int i); virtual void giveEffectiveMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep); @@ -271,21 +285,11 @@ class RCM2Material : public StructuralMaterial double giveResidualStrength() { return 0.01 * this->Ft; } - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - virtual void give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - virtual void give2dBeamLayerStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); - virtual void givePlateLayerStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<1,1> give1dStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<2,2> give2dBeamLayerStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<5,5> givePlateLayerStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; }; } // end namespace oofem #endif // rcm2_h diff --git a/src/sm/Materials/rcsd.C b/src/sm/Materials/rcsd.C index 60fa2b4ac..e404f4d5d 100644 --- a/src/sm/Materials/rcsd.C +++ b/src/sm/Materials/rcsd.C @@ -37,7 +37,7 @@ #include "floatmatrix.h" #include "floatarray.h" #include "mathfem.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "datastream.h" #include "contextioerr.h" #include "classfactory.h" @@ -48,18 +48,12 @@ namespace oofem { REGISTER_Material(RCSDMaterial); RCSDMaterial :: RCSDMaterial(int n, Domain *d) : RCM2Material(n, d) - // - // constructor - // { linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); } RCSDMaterial :: ~RCSDMaterial() -// -// destructor -// { delete linearElasticMaterial; } @@ -105,7 +99,7 @@ RCSDMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, this->giveRealPrincipalStressVector3d(princStress, gp, principalStrain, tempCrackDirs, tStep); princStress.resize(6); tempCrackDirs = status->giveTempCrackDirs(); - this->transformStressVectorTo(answer, tempCrackDirs, princStress, 1); + answer = this->transformStressVectorTo(tempCrackDirs, princStress, 1); StructuralMaterial :: giveReducedSymVectorForm( reducedSpaceStressVector, answer, gp->giveMaterialMode() ); status->letTempStressVectorBe(reducedSpaceStressVector); @@ -252,19 +246,16 @@ RCSDMaterial :: computeCurrEquivStrain(GaussPoint *gp, const FloatArray &reduced } -IRResultType -RCSDMaterial :: initializeFrom(InputRecord *ir) +void +RCSDMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - + RCM2Material :: initializeFrom(ir); IR_GIVE_FIELD(ir, SDTransitionCoeff, _IFT_RCSDMaterial_sdtransitioncoeff); - - return RCM2Material :: initializeFrom(ir); } double -RCSDMaterial :: give(int aProperty, GaussPoint *gp) +RCSDMaterial :: give(int aProperty, GaussPoint *gp) const // Returns the value of the property aProperty (e.g. the Young's modulus // 'E') of the receiver. { @@ -470,24 +461,14 @@ RCSDMaterial :: giveNormalCrackingStress(GaussPoint *gp, double crackStrain, int -RCSDMaterialStatus :: RCSDMaterialStatus(int n, Domain *d, GaussPoint *g) : - RCM2MaterialStatus(n, d, g), Ds0() -{ - maxEquivStrain = tempMaxEquivStrain = 0.0; - damageCoeff = tempDamageCoeff = 1.0; - damageStiffCoeff = depsf = depsp = 0.0; - mode = tempMode = rcMode; -} - - -RCSDMaterialStatus :: ~RCSDMaterialStatus() -{ } +RCSDMaterialStatus :: RCSDMaterialStatus(GaussPoint *g) : + RCM2MaterialStatus(g) +{} void -RCSDMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +RCSDMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { - int i; char s [ 11 ]; StructuralMaterialStatus :: printOutputAt(file, tStep); @@ -496,7 +477,7 @@ RCSDMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) fprintf(file, "mode :rc "); if ( this->giveTempAlreadyCrack() ) { - for ( i = 1; i <= 3; i++ ) { + for ( int i = 1; i <= 3; i++ ) { switch ( crackStatuses.at(i) ) { case pscm_NONE: strcpy(s, "NONE"); @@ -562,21 +543,11 @@ RCSDMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -RCSDMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +RCSDMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + RCM2MaterialStatus :: saveContext(stream, mode); - // save parent class status - if ( ( iores = RCM2MaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write a raw data if ( !stream.write(maxEquivStrain) ) { THROW_CIOERR(CIO_IOERR); } @@ -589,28 +560,19 @@ RCSDMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *ob THROW_CIOERR(CIO_IOERR); } + contextIOResultType iores; if ( ( iores = Ds0.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -RCSDMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +RCSDMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + RCM2MaterialStatus :: restoreContext(stream, mode); - // read parent class status - if ( ( iores = RCM2MaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data + contextIOResultType iores; if ( !stream.read(maxEquivStrain) ) { THROW_CIOERR(CIO_IOERR); } @@ -626,7 +588,5 @@ RCSDMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void if ( ( iores = Ds0.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; // return succes } } // end namespace oofem diff --git a/src/sm/Materials/rcsd.h b/src/sm/Materials/rcsd.h index 091e04042..2601d09db 100644 --- a/src/sm/Materials/rcsd.h +++ b/src/sm/Materials/rcsd.h @@ -63,49 +63,46 @@ class RCSDMaterialStatus : public RCM2MaterialStatus enum rcsdMode { rcMode, sdMode }; protected: - double maxEquivStrain, tempMaxEquivStrain; - double damageCoeff, tempDamageCoeff; + double maxEquivStrain = 0., tempMaxEquivStrain = 0.; + double damageCoeff = 1., tempDamageCoeff = 1.; FloatMatrix Ds0; - double damageStiffCoeff, depsf, depsp; - rcsdMode mode, tempMode; + double damageStiffCoeff = 0., depsf = 0., depsp = 0.; + rcsdMode mode = rcMode, tempMode = rcMode; public: - RCSDMaterialStatus(int n, Domain * d, GaussPoint * g); - virtual ~RCSDMaterialStatus(); + RCSDMaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - double giveTempMaxEquivStrain() { return tempMaxEquivStrain; } + double giveTempMaxEquivStrain() const { return tempMaxEquivStrain; } void setTempMaxEquivStrain(double val) { tempMaxEquivStrain = val; } - double giveDamageStiffCoeff() { return damageStiffCoeff; } + double giveDamageStiffCoeff() const { return damageStiffCoeff; } void setDamageStiffCoeff(double val) { damageStiffCoeff = val; } - double giveTempDamageCoeff() { return tempDamageCoeff; } + double giveTempDamageCoeff() const { return tempDamageCoeff; } void setTempDamageCoeff(double val) { tempDamageCoeff = val; } const FloatMatrix *giveDs0Matrix() { return & Ds0; } void setDs0Matrix(FloatMatrix &mtrx) { Ds0 = mtrx; } - double giveDamageEpsfCoeff() { return depsf; } + double giveDamageEpsfCoeff() const { return depsf; } void setDamageEpsfCoeff(double val) { depsf = val; } - double giveDamageEpspCoeff() { return depsp; } + double giveDamageEpspCoeff() const { return depsp; } void setDamageEpspCoeff(double val) { depsp = val; } - rcsdMode giveTempMode() { return tempMode; } + rcsdMode giveTempMode() const { return tempMode; } void setTempMode(rcsdMode mode) { tempMode = mode; } // query for non-tem variables (usefull for postprocessing) - double giveMaxEquivStrain() { return maxEquivStrain; } - double giveDamageCoeff() { return damageCoeff; } + double giveMaxEquivStrain() const { return maxEquivStrain; } + double giveDamageCoeff() const { return damageCoeff; } - rcsdMode giveMode() { return mode; } + rcsdMode giveMode() const { return mode; } - // definition - virtual const char *giveClassName() const { return "RCSDMaterialStatus"; } + const char *giveClassName() const override { return "RCSDMaterialStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - // saves current context(state) into stream - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -119,27 +116,23 @@ class RCSDMaterialStatus : public RCM2MaterialStatus class RCSDMaterial : public RCM2Material { protected: - double SDTransitionCoeff; + double SDTransitionCoeff = 0.; public: RCSDMaterial(int n, Domain * d); virtual ~RCSDMaterial(); - // identification and auxiliary functions - virtual const char *giveInputRecordName() const { return _IFT_RCSDMaterial_Name; } - virtual const char *giveClassName() const { return "RCSDMaterial"; } + const char *giveInputRecordName() const override { return _IFT_RCSDMaterial_Name; } + const char *giveClassName() const override { return "RCSDMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual double give(int aProperty, GaussPoint *gp); + double give(int aProperty, GaussPoint *gp) const override; - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *, - const FloatArray &, TimeStep *); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &, TimeStep *tStep) override; -#ifdef __OOFEG -#endif - - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new RCSDMaterialStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new RCSDMaterialStatus(gp); } protected: double computeCurrEquivStrain(GaussPoint *, const FloatArray &, double, TimeStep *); @@ -147,20 +140,19 @@ class RCSDMaterial : public RCM2Material // gp's status. These variables are used to control process, when // we try to find equilibrium state. - virtual void giveEffectiveMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep); + void giveEffectiveMaterialStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, + GaussPoint *gp, TimeStep *tStep) override; double computeDamageCoeff(double, double, double, double); - virtual double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, - double crackStrain, int i); - //virtual double giveShearRetentionFactor(GaussPoint* gp, double eps_cr, int i); - virtual double giveNormalCrackingStress(GaussPoint *gp, double eps_cr, int i); - virtual double giveMinCrackStrainsForFullyOpenCrack(GaussPoint *gp, int i); - //virtual void updateStatusForNewCrack( GaussPoint*, int, double); - virtual double computeStrength(GaussPoint *, double); - virtual int checkSizeLimit(GaussPoint *gp, double); - //// + double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, + double crackStrain, int i) override; + //double giveShearRetentionFactor(GaussPoint* gp, double eps_cr, int i) override; + double giveNormalCrackingStress(GaussPoint *gp, double eps_cr, int i) override; + double giveMinCrackStrainsForFullyOpenCrack(GaussPoint *gp, int i) override; + //void updateStatusForNewCrack( GaussPoint*, int, double) override; + double computeStrength(GaussPoint *gp, double) override; + int checkSizeLimit(GaussPoint *gp, double) override; }; } // end namespace oofem #endif // rcsd_h diff --git a/src/sm/Materials/rcsde.C b/src/sm/Materials/rcsde.C index a580e7bb1..f7766f3f5 100644 --- a/src/sm/Materials/rcsde.C +++ b/src/sm/Materials/rcsde.C @@ -37,7 +37,7 @@ #include "floatmatrix.h" #include "floatarray.h" #include "mathfem.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" #include "datastream.h" #include "contextioerr.h" #include "classfactory.h" @@ -47,18 +47,12 @@ namespace oofem { REGISTER_Material(RCSDEMaterial); RCSDEMaterial :: RCSDEMaterial(int n, Domain *d) : RCM2Material(n, d) - // - // constructor - // { linearElasticMaterial = new IsotropicLinearElasticMaterial(n, d); } RCSDEMaterial :: ~RCSDEMaterial() -// -// destructor -// { delete linearElasticMaterial; } @@ -104,7 +98,7 @@ RCSDEMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, this->giveRealPrincipalStressVector3d(princStress, gp, principalStrain, tempCrackDirs, tStep); princStress.resize(6); tempCrackDirs = status->giveTempCrackDirs(); - this->transformStressVectorTo(answer, tempCrackDirs, princStress, 1); + answer = this->transformStressVectorTo(tempCrackDirs, princStress, 1); StructuralMaterial :: giveReducedSymVectorForm( reducedSpaceStressVector, answer, gp->giveMaterialMode() ); status->letTempStressVectorBe(reducedSpaceStressVector); @@ -257,18 +251,16 @@ RCSDEMaterial :: computeCurrEquivStrain(GaussPoint *gp, const FloatArray &reduce } -IRResultType -RCSDEMaterial :: initializeFrom(InputRecord *ir) +void +RCSDEMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - + RCM2Material :: initializeFrom(ir); IR_GIVE_FIELD(ir, SDTransitionCoeff, _IFT_RCSDEMaterial_sdtransitioncoeff); - return RCM2Material :: initializeFrom(ir); } double -RCSDEMaterial :: give(int aProperty, GaussPoint *gp) +RCSDEMaterial :: give(int aProperty, GaussPoint *gp) const // Returns the value of the property aProperty (e.g. the Young's modulus // 'E') of the receiver. { @@ -453,22 +445,13 @@ RCSDEMaterial :: giveNormalCrackingStress(GaussPoint *gp, double crackStrain, in -RCSDEMaterialStatus :: RCSDEMaterialStatus(int n, Domain *d, GaussPoint *g) : - RCM2MaterialStatus(n, d, g), Ds0() -{ - maxEquivStrain = tempMaxEquivStrain = 0.0; - damageCoeff = tempDamageCoeff = 1.0; - transitionEps = epsF2 = 0.0; - rcsdMode = tempRcsdMode = rcMode; -} - - -RCSDEMaterialStatus :: ~RCSDEMaterialStatus() -{ } +RCSDEMaterialStatus :: RCSDEMaterialStatus(GaussPoint *g) : + RCM2MaterialStatus(g) +{} void -RCSDEMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +RCSDEMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { char s [ 11 ]; @@ -544,21 +527,10 @@ RCSDEMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -RCSDEMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +RCSDEMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = RCM2MaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // write a raw data + RCM2MaterialStatus :: saveContext(stream, mode); if ( !stream.write(maxEquivStrain) ) { THROW_CIOERR(CIO_IOERR); @@ -581,28 +553,18 @@ RCSDEMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *o THROW_CIOERR(CIO_IOERR); } + contextIOResultType iores; if ( ( iores = Ds0.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -RCSDEMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +RCSDEMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; + RCM2MaterialStatus :: restoreContext(stream, mode); - // read parent class status - if ( ( iores = RCM2MaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data if ( !stream.read(maxEquivStrain) ) { THROW_CIOERR(CIO_IOERR); } @@ -625,10 +587,9 @@ RCSDEMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void THROW_CIOERR(CIO_IOERR); } + contextIOResultType iores; if ( ( iores = Ds0.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; // return succes } } // end namespace oofem diff --git a/src/sm/Materials/rcsde.h b/src/sm/Materials/rcsde.h index 24172de68..68c1f72a1 100644 --- a/src/sm/Materials/rcsde.h +++ b/src/sm/Materials/rcsde.h @@ -61,50 +61,47 @@ class RCSDEMaterialStatus : public RCM2MaterialStatus enum __rcsdModeType { rcMode, sdMode }; protected: - - double maxEquivStrain, tempMaxEquivStrain; - double damageCoeff, tempDamageCoeff; + double maxEquivStrain = 0., tempMaxEquivStrain = 0.; + double damageCoeff = 1., tempDamageCoeff = 1.; FloatMatrix Ds0; - double transitionEps, epsF2; - __rcsdModeType rcsdMode, tempRcsdMode; -public: + double transitionEps = 0., epsF2 = 0.; + __rcsdModeType rcsdMode = rcMode, tempRcsdMode = rcMode; - RCSDEMaterialStatus(int n, Domain * d, GaussPoint * g); - virtual ~RCSDEMaterialStatus(); +public: + RCSDEMaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - double giveTempMaxEquivStrain() { return tempMaxEquivStrain; } + double giveTempMaxEquivStrain() const { return tempMaxEquivStrain; } void setTempMaxEquivStrain(double val) { tempMaxEquivStrain = val; } // double giveDamageStiffCoeff () {return damageStiffCoeff;} // void setDamageStiffCoeff (double val) {damageStiffCoeff = val;} - double giveTempDamageCoeff() { return tempDamageCoeff; } + double giveTempDamageCoeff() const { return tempDamageCoeff; } void setTempDamageCoeff(double val) { tempDamageCoeff = val; } const FloatMatrix *giveDs0Matrix() { return & Ds0; } void setDs0Matrix(FloatMatrix &mtrx) { Ds0 = mtrx; } - double giveTransitionEpsCoeff() { return transitionEps; } + double giveTransitionEpsCoeff() const { return transitionEps; } void setTransitionEpsCoeff(double val) { transitionEps = val; } - double giveEpsF2Coeff() { return epsF2; } + double giveEpsF2Coeff() const { return epsF2; } void setEpsF2Coeff(double val) { epsF2 = val; } - __rcsdModeType giveTempMode() { return tempRcsdMode; } - void setTempMode(__rcsdModeType mode) { tempRcsdMode = mode; } + __rcsdModeType giveTempMode() const { return tempRcsdMode; } + void setTempMode(__rcsdModeType mode) { tempRcsdMode = mode; } // query for non-tem variables (usefull for postprocessing) - double giveMaxEquivStrain() { return maxEquivStrain; } - double giveDamageCoeff() { return damageCoeff; } + double giveMaxEquivStrain() const { return maxEquivStrain; } + double giveDamageCoeff() const { return damageCoeff; } - __rcsdModeType giveMode() { return rcsdMode; } - // definition - virtual const char *giveClassName() const { return "RCSDEMaterialStatus"; } + __rcsdModeType giveMode() const { return rcsdMode; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + const char *giveClassName() const override { return "RCSDEMaterialStatus"; } - // saves current context(state) into stream - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; }; @@ -118,48 +115,42 @@ class RCSDEMaterialStatus : public RCM2MaterialStatus class RCSDEMaterial : public RCM2Material { protected: - double SDTransitionCoeff; + double SDTransitionCoeff = 0.; public: RCSDEMaterial(int n, Domain * d); virtual ~RCSDEMaterial(); - // identification and auxiliary functions - virtual const char *giveInputRecordName() const { return _IFT_RCSDEMaterial_Name; } - virtual const char *giveClassName() const { return "RCSDEMaterial"; } - - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_RCSDEMaterial_Name; } + const char *giveClassName() const override { return "RCSDEMaterial"; } - virtual double give(int aProperty, GaussPoint *gp); + void initializeFrom(InputRecord &ir) override; - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *, - const FloatArray &, TimeStep *); + double give(int aProperty, GaussPoint *gp) const override; -#ifdef __OOFEG -#endif + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &, TimeStep *) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new RCSDEMaterialStatus(1, domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new RCSDEMaterialStatus(gp); } protected: - double computeCurrEquivStrain(GaussPoint *, const FloatArray &, double, TimeStep *); + double computeCurrEquivStrain(GaussPoint *, const FloatArray &, double, TimeStep *tStep); // two functions used to initialize and updating temporary variables in // gp's status. These variables are used to control process, when // we try to find equlibrium state. - virtual void giveEffectiveMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep); + void giveEffectiveMaterialStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, + GaussPoint *gp, TimeStep *tStep) override; double computeDamageCoeff(double, double, double); - virtual double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, - double crackStrain, int i); - //virtual double giveShearRetentionFactor(GaussPoint* gp, double eps_cr, int i); - virtual double giveNormalCrackingStress(GaussPoint *gp, double eps_cr, int i); - virtual double giveMinCrackStrainsForFullyOpenCrack(GaussPoint *gp, int i); - //virtual void updateStatusForNewCrack( GaussPoint*, int, double); - virtual double computeStrength(GaussPoint *, double); - virtual int checkSizeLimit(GaussPoint *gp, double); - //// + double giveCrackingModulus(MatResponseMode rMode, GaussPoint *gp, + double crackStrain, int i) override; + //double giveShearRetentionFactor(GaussPoint* gp, double eps_cr, int i) override; + double giveNormalCrackingStress(GaussPoint *gp, double eps_cr, int i) override; + double giveMinCrackStrainsForFullyOpenCrack(GaussPoint *gp, int i) override; + //void updateStatusForNewCrack(GaussPoint *gp, int, double) override; + double computeStrength(GaussPoint *gp, double) override; + int checkSizeLimit(GaussPoint *gp, double) override; }; } // end namespace oofem #endif // rcsde_h diff --git a/src/sm/Materials/rcsdnl.C b/src/sm/Materials/rcsdnl.C index 0fe18a5d5..410dbf30d 100644 --- a/src/sm/Materials/rcsdnl.C +++ b/src/sm/Materials/rcsdnl.C @@ -46,17 +46,8 @@ namespace oofem { REGISTER_Material(RCSDNLMaterial); RCSDNLMaterial :: RCSDNLMaterial(int n, Domain *d) : RCSDEMaterial(n, d), StructuralNonlocalMaterialExtensionInterface(d) -{ - //linearElasticMaterial = new IsotropicLinearElasticMaterial (n,d); - SDTransitionCoeff2 = 0.; - R = 0.; -} - +{} -RCSDNLMaterial :: ~RCSDNLMaterial() -{ - //delete linearElasticMaterial; -} Interface * RCSDNLMaterial :: giveInterface(InterfaceType type) @@ -64,13 +55,13 @@ RCSDNLMaterial :: giveInterface(InterfaceType type) if ( type == NonlocalMaterialExtensionInterfaceType ) { return static_cast< StructuralNonlocalMaterialExtensionInterface * >(this); } else { - return NULL; + return nullptr; } } void -RCSDNLMaterial :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) +RCSDNLMaterial :: updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const { /* Implements the service updating local variables in given integration points, * which take part in nonlocal average process. Actually, no update is necessary, @@ -78,7 +69,7 @@ RCSDNLMaterial :: updateBeforeNonlocAverage(const FloatArray &strainVector, Gaus * computation. It is therefore necessary only to store local strain in corresponding status. * This service is declared at StructuralNonlocalMaterial level. */ - RCSDNLMaterialStatus *status = static_cast< RCSDNLMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RCSDNLMaterialStatus * >( this->giveStatus(gp) ); this->initTempStatus(gp); @@ -346,17 +337,12 @@ RCSDNLMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, } -IRResultType -RCSDNLMaterial :: initializeFrom(InputRecord *ir) +void +RCSDNLMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - //RCSDEMaterial::instanciateFrom (ir); - result = this->giveLinearElasticMaterial()->initializeFrom(ir); - if ( result != IRRT_OK ) return result; - - result = StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + this->giveLinearElasticMaterial()->initializeFrom(ir); + StructuralNonlocalMaterialExtensionInterface :: initializeFrom(ir); IR_GIVE_FIELD(ir, Ft, _IFT_RCSDNLMaterial_ft); IR_GIVE_FIELD(ir, SDTransitionCoeff, _IFT_RCSDNLMaterial_sdtransitioncoeff); @@ -374,18 +360,15 @@ RCSDNLMaterial :: initializeFrom(InputRecord *ir) R = 0.0; } - if ( ir->hasField(_IFT_RCSDNLMaterial_ef) ) { // if ef is specified, Gf is computed acordingly + if ( ir.hasField(_IFT_RCSDNLMaterial_ef) ) { // if ef is specified, Gf is computed acordingly IR_GIVE_FIELD(ir, this->ef, _IFT_RCSDNLMaterial_ef); this->Gf = this->Ft * this->ef; - } else if ( ir->hasField(_IFT_RCSDNLMaterial_gf) ) { // otherwise if Gf is specified, ef is computed acordingly + } else if ( ir.hasField(_IFT_RCSDNLMaterial_gf) ) { // otherwise if Gf is specified, ef is computed acordingly IR_GIVE_FIELD(ir, this->Gf, _IFT_RCSDNLMaterial_gf); this->ef = this->Gf / this->Ft; } else { - OOFEM_WARNING("cannot determine Gf and ef from input data"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, "none", "cannot determine Gf and ef from input data"); } - - return IRRT_OK; } @@ -397,11 +380,11 @@ RCSDNLMaterial :: giveMinCrackStrainsForFullyOpenCrack(GaussPoint *gp, int i) double -RCSDNLMaterial :: computeWeightFunction(const FloatArray &src, const FloatArray &coord) +RCSDNLMaterial :: computeWeightFunction(const double R, const FloatArray &src, const FloatArray &coord) const { // Bell shaped function decaying with the distance. - double dist = src.distance(coord); + double dist = distance(src, coord); if ( ( dist >= 0. ) && ( dist <= this->R ) ) { double help = ( 1. - dist * dist / ( R * R ) ); @@ -436,22 +419,18 @@ RCSDNLMaterial :: computeWeightFunction(const FloatArray &src, const FloatArray -RCSDNLMaterialStatus :: RCSDNLMaterialStatus(int n, Domain *d, GaussPoint *g) : - RCSDEMaterialStatus(n, d, g), StructuralNonlocalMaterialStatusExtensionInterface(), nonlocalStrainVector(), +RCSDNLMaterialStatus :: RCSDNLMaterialStatus(GaussPoint *g) : + RCSDEMaterialStatus(g), StructuralNonlocalMaterialStatusExtensionInterface(), nonlocalStrainVector(), tempNonlocalStrainVector(), localStrainVectorForAverage() { - nonlocalStrainVector.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + nonlocalStrainVector.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( g->giveMaterialMode() ) ); - localStrainVectorForAverage.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); + localStrainVectorForAverage.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( g->giveMaterialMode() ) ); } -RCSDNLMaterialStatus :: ~RCSDNLMaterialStatus() -{ } - - void -RCSDNLMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +RCSDNLMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { FloatArray helpVec; @@ -477,14 +456,6 @@ RCSDNLMaterialStatus :: initTempStatus() { RCSDEMaterialStatus :: initTempStatus(); - if ( nonlocalStrainVector.giveSize() == 0 ) { - nonlocalStrainVector.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); - } - - if ( localStrainVectorForAverage.giveSize() == 0 ) { - localStrainVectorForAverage.resize( StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ) ); - } - tempNonlocalStrainVector = nonlocalStrainVector; } @@ -502,49 +473,27 @@ RCSDNLMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -RCSDNLMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full information stored in this Status -// no temp variables stored -// +void +RCSDNLMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = RCSDEMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + RCSDEMaterialStatus :: saveContext(stream, mode); - // write a raw data + contextIOResultType iores; if ( ( iores = nonlocalStrainVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -RCSDNLMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +RCSDNLMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = RCSDEMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - // read raw data + RCSDEMaterialStatus :: restoreContext(stream, mode); + contextIOResultType iores; if ( ( iores = nonlocalStrainVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; // return success } @@ -554,7 +503,7 @@ RCSDNLMaterialStatus :: giveInterface(InterfaceType type) if ( type == NonlocalMaterialStatusExtensionInterfaceType ) { return this; } else { - return NULL; + return nullptr; } } diff --git a/src/sm/Materials/rcsdnl.h b/src/sm/Materials/rcsdnl.h index c800fabde..5ac8f6c7b 100644 --- a/src/sm/Materials/rcsdnl.h +++ b/src/sm/Materials/rcsdnl.h @@ -40,8 +40,8 @@ #define rcsdnl_h #include "rcsde.h" -#include "Materials/structuralnonlocalmaterialext.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralnonlocalmaterialext.h" +#include "sm/Materials/structuralmaterial.h" ///@name Input fields for RCSDNLMaterial //@{ #define _IFT_RCSDNLMaterial_Name "rcsdnl" @@ -63,10 +63,9 @@ class RCSDNLMaterialStatus : public RCSDEMaterialStatus, public StructuralNonloc FloatArray nonlocalStrainVector, tempNonlocalStrainVector, localStrainVectorForAverage; public: - RCSDNLMaterialStatus(int n, Domain * d, GaussPoint * g); - virtual ~RCSDNLMaterialStatus(); + RCSDNLMaterialStatus(GaussPoint *gp); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; const FloatArray &giveNonlocalStrainVector() { return nonlocalStrainVector; } const FloatArray &giveTempNonlocalStrainVector() { return tempNonlocalStrainVector; } @@ -75,18 +74,15 @@ class RCSDNLMaterialStatus : public RCSDEMaterialStatus, public StructuralNonloc const FloatArray &giveLocalStrainVectorForAverage() { return localStrainVectorForAverage; } void setLocalStrainVectorForAverage(FloatArray ls) { localStrainVectorForAverage = std :: move(ls); } - // definition - virtual const char *giveInputRecordName() const { return _IFT_RCSDNLMaterial_Name; } - virtual const char *giveClassName() const { return "RCSDNLMaterialStatus"; } + const char *giveClassName() const override { return "RCSDNLMaterialStatus"; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - // saves current context(state) into stream - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual Interface *giveInterface(InterfaceType); + Interface *giveInterface(InterfaceType) override; }; @@ -103,30 +99,28 @@ class RCSDNLMaterial : public RCSDEMaterial, public StructuralNonlocalMaterialEx * Nondimensional parameter controlling the transition between rc and sd model, * with respect to shear stifness degradation. */ - double SDTransitionCoeff2; + double SDTransitionCoeff2 = 0.; /** * Interaction radius, related to the nonlocal characteristic length of material. */ - double R; + double R = 0.; /** * Strain at complete failure. For exponential law, ef is the strain at the intersection * of the horizontal axis with the tangent to the softening curve at peak stress. */ - double ef; + double ef = 0.; public: RCSDNLMaterial(int n, Domain * d); - virtual ~RCSDNLMaterial(); - // identification and auxiliary functions - virtual const char *giveClassName() const { return "RCSDNLMaterial"; } + const char *giveClassName() const override { return "RCSDNLMaterial"; } - virtual Interface *giveInterface(InterfaceType t); + Interface *giveInterface(InterfaceType t) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *, - const FloatArray &, TimeStep *); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &, TimeStep *tStep) override; /** * Implements the service updating local variables in given integration points, @@ -138,25 +132,25 @@ class RCSDNLMaterial : public RCSDEMaterial, public StructuralNonlocalMaterialEx * @param gp integration point to update. * @param tStep solution step indicating time of update. */ - virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep); + void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const override; - virtual double computeWeightFunction(const FloatArray &src, const FloatArray &coord); - virtual int hasBoundedSupport() { return 1; } + double computeWeightFunction(const double cl, const FloatArray &src, const FloatArray &coord) const override; + int hasBoundedSupport() const override { return 1; } /** * Determines the width (radius) of limited support of weighting function */ - virtual void giveSupportRadius(double &radius) { radius = this->R; } + void giveSupportRadius(double &radius) { radius = this->R; } - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip); - virtual int estimatePackSize(DataStream &buff, GaussPoint *ip); + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *ip) override; + int estimatePackSize(DataStream &buff, GaussPoint *ip) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new RCSDNLMaterialStatus(1, RCSDEMaterial :: domain, gp); } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new RCSDNLMaterialStatus(gp); } protected: - virtual double giveCharacteristicElementLength(GaussPoint *gp, const FloatArray &) { return 1.0; } - virtual double giveMinCrackStrainsForFullyOpenCrack(GaussPoint *gp, int i); - virtual double computeStrength(GaussPoint *, double) { return this->Ft; } + double giveCharacteristicElementLength(GaussPoint *gp, const FloatArray &) override { return 1.0; } + double giveMinCrackStrainsForFullyOpenCrack(GaussPoint *gp, int i) override; + double computeStrength(GaussPoint *, double) override { return this->Ft; } }; } // end namespace oofem #endif // rcsdnl_h diff --git a/src/sm/Materials/simplevitrificationmaterial.C b/src/sm/Materials/simplevitrificationmaterial.C index 74b3834ca..39e9b17df 100644 --- a/src/sm/Materials/simplevitrificationmaterial.C +++ b/src/sm/Materials/simplevitrificationmaterial.C @@ -34,18 +34,18 @@ #include "simplevitrificationmaterial.h" #include "gausspoint.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "dynamicinputrecord.h" #include "classfactory.h" namespace oofem { REGISTER_Material(SimpleVitrificationMaterial); -SimpleVitrificationMaterial :: ~SimpleVitrificationMaterial() { } - -IRResultType SimpleVitrificationMaterial :: initializeFrom(InputRecord *ir) +void SimpleVitrificationMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; + StructuralMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->vitrTime, _IFT_SimpleVitrificationMaterial_vitrificationTime); @@ -58,8 +58,6 @@ IRResultType SimpleVitrificationMaterial :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, this->nu_r, _IFT_SimpleVitrificationMaterial_nu_r); IR_GIVE_FIELD(ir, this->G_r, _IFT_SimpleVitrificationMaterial_G_r); IR_GIVE_FIELD(ir, this->alpha_r, _IFT_SimpleVitrificationMaterial_alpha_r); - - return StructuralMaterial :: initializeFrom(ir); } @@ -87,85 +85,96 @@ int SimpleVitrificationMaterial :: checkConsistency() } - -void SimpleVitrificationMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<6,6> +SimpleVitrificationMaterial :: computeTangent(bool vitr) const { - double eksi, nxz, nyz, nxy, nzx, nzy, nyx; - bool vitr = tStep->giveIntrinsicTime() < this->vitrTime; - const FloatArray &activeNu = vitr ? this->nu_r : this->nu; - const FloatArray &activeE = vitr ? this->E_r : this->E; - const FloatArray &activeG = vitr ? this->G_r : this->G; + const auto &activeNu = vitr ? this->nu_r : this->nu; + const auto &activeE = vitr ? this->E_r : this->E; + const auto &activeG = vitr ? this->G_r : this->G; + + //double [nyz, nxz, nxy] = activeNu; // c++17 + //double [nzy, nzx, nyx] = activeNu; + + double nyz = activeNu.at(1); + double nxz = activeNu.at(2); + double nxy = activeNu.at(3); - nyz = nzy = activeNu.at(1); - nxz = nzx = activeNu.at(2); - nxy = nyx = activeNu.at(3); + double nzy = activeNu.at(1); + double nzx = activeNu.at(2); + double nyx = activeNu.at(3); - eksi = 1. - ( nxy * nyx + nyz * nzy + nzx * nxz ) - ( nxy * nyz * nzx + nyx * nzy * nxz ); + double eksi = 1. - ( nxy * nyx + nyz * nzy + nzx * nxz ) - ( nxy * nyz * nzx + nyx * nzy * nxz ); - answer.resize(6, 6); - answer.zero(); + FloatMatrixF<6,6> tangent; // switched letters from original oofem -> now produces same material stiffness matrix as Abaqus method - answer.at(1, 1) = activeE.at(1) * ( 1. - nyz * nzy ) / eksi; - answer.at(1, 2) = activeE.at(2) * ( nxy + nxz * nzy ) / eksi; - answer.at(1, 3) = activeE.at(3) * ( nxz + nyz * nxy ) / eksi; - answer.at(2, 2) = activeE.at(2) * ( 1. - nxz * nzx ) / eksi; - answer.at(2, 3) = activeE.at(3) * ( nyz + nyx * nxz ) / eksi; - answer.at(3, 3) = activeE.at(3) * ( 1. - nyx * nxy ) / eksi; + tangent.at(1, 1) = activeE.at(1) * ( 1. - nyz * nzy ) / eksi; + tangent.at(1, 2) = activeE.at(2) * ( nxy + nxz * nzy ) / eksi; + tangent.at(1, 3) = activeE.at(3) * ( nxz + nyz * nxy ) / eksi; + tangent.at(2, 2) = activeE.at(2) * ( 1. - nxz * nzx ) / eksi; + tangent.at(2, 3) = activeE.at(3) * ( nyz + nyx * nxz ) / eksi; + tangent.at(3, 3) = activeE.at(3) * ( 1. - nyx * nxy ) / eksi; // define the lower triangle for ( int i = 1; i < 4; i++ ) { for ( int j = 1; j < i; j++ ) { - answer.at(i, j) = answer.at(j, i); + tangent.at(i, j) = tangent.at(j, i); } } - answer.at(4, 4) = activeG.at(1); - answer.at(5, 5) = activeG.at(2); - answer.at(6, 6) = activeG.at(3); + tangent.at(4, 4) = activeG.at(1); + tangent.at(5, 5) = activeG.at(2); + tangent.at(6, 6) = activeG.at(3); + + return tangent; } -void SimpleVitrificationMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep) -{ - FloatArray strainVector; - FloatMatrix d; - FloatArray deltaStrain; - StructuralMaterialStatus *status = dynamic_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); +FloatMatrixF<6,6> +SimpleVitrificationMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + bool vitr = tStep->giveIntrinsicTime() < this->vitrTime; + return this->computeTangent(vitr); +} - this->giveStressDependentPartOfStrainVector(strainVector, gp, reducedStrain, tStep, VM_Total); - deltaStrain.beDifferenceOf( strainVector, status->giveStrainVector() ); +FloatArrayF<6> +SimpleVitrificationMaterial :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const +{ + auto status = dynamic_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + + auto thermalStrain = computeStressIndependentStrainVector_3d(gp, tStep, VM_Total); + auto deltaStrain = strain - thermalStrain - FloatArrayF<6>(status->giveStrainVector()); - this->give3dMaterialStiffnessMatrix(d, TangentStiffness, gp, tStep); + bool vitr = tStep->giveIntrinsicTime() < this->vitrTime; + auto d = this->computeTangent(vitr); - FloatArray deltaStress; - deltaStress.beProductOf(d, deltaStrain); + auto deltaStress = dot(d, deltaStrain); - answer = status->giveStressVector(); - answer.add(deltaStress); + auto stress = status->giveStressVector() + deltaStress; // update gp - status->letTempStrainVectorBe(reducedStrain); - status->letTempStressVectorBe(answer); + status->letTempStrainVectorBe(strain); + status->letTempStressVectorBe(stress); + + return stress; } -void SimpleVitrificationMaterial :: giveThermalDilatationVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep) +FloatArrayF<6> SimpleVitrificationMaterial :: giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const { bool vitr = tStep->giveIntrinsicTime() < this->vitrTime; - answer.resize(6); - answer.at(1) = vitr ? this->alpha_r.at(1) : this->alpha.at(1); - answer.at(2) = vitr ? this->alpha_r.at(2) : this->alpha.at(2); - answer.at(3) = vitr ? this->alpha_r.at(3) : this->alpha.at(3); + return { + vitr ? this->alpha_r.at(1) : this->alpha.at(1), + vitr ? this->alpha_r.at(2) : this->alpha.at(2), + vitr ? this->alpha_r.at(3) : this->alpha.at(3), + 0., 0., 0., + }; } MaterialStatus *SimpleVitrificationMaterial :: CreateStatus(GaussPoint *gp) const { - return new StructuralMaterialStatus(1, domain, gp); + return new StructuralMaterialStatus(gp); } } // end namespace oofem diff --git a/src/sm/Materials/simplevitrificationmaterial.h b/src/sm/Materials/simplevitrificationmaterial.h index 56358e2fa..e074a1bec 100644 --- a/src/sm/Materials/simplevitrificationmaterial.h +++ b/src/sm/Materials/simplevitrificationmaterial.h @@ -35,8 +35,8 @@ #ifndef simplevitrificationmaterial_h #define simplevitrificationmaterial_h -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "floatarray.h" ///@name Input fields for SimpleVitrificationMaterial @@ -65,7 +65,7 @@ class SimpleVitrificationMaterial : public StructuralMaterial { private: /// Vitrification time (when equal or larger than this time the material changes response). - double vitrTime; + double vitrTime = 0.; /// Material parameters for the glassy part of the model (after vitrification). FloatArray E, nu, G, alpha; /// Material parameters for the rubbery part of the model (before vitrification). @@ -74,26 +74,23 @@ class SimpleVitrificationMaterial : public StructuralMaterial public: /// Constructor. SimpleVitrificationMaterial(int n, Domain * d) : StructuralMaterial(n, d) { } - /// Destructor. - virtual ~SimpleVitrificationMaterial(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual int checkConsistency(); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + int checkConsistency() override; - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<6,6> computeTangent(bool vitr) const; + + FloatArrayF<6> giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual int hasNonLinearBehaviour() { return true; } - virtual const char *giveClassName() const { return "SimpleVitrificationMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_SimpleVitrificationMaterial_Name; } + const char *giveClassName() const override { return "SimpleVitrificationMaterial"; } + const char *giveInputRecordName() const override { return _IFT_SimpleVitrificationMaterial_Name; } }; } // end namespace oofem #endif // simplevitrificationmaterial_h diff --git a/src/sm/Materials/steelrelaxmat.C b/src/sm/Materials/steelrelaxmat.C index c10e06b7c..7092289fa 100644 --- a/src/sm/Materials/steelrelaxmat.C +++ b/src/sm/Materials/steelrelaxmat.C @@ -45,46 +45,21 @@ namespace oofem { REGISTER_Material(SteelRelaxMat); -// constructor -SteelRelaxMat :: SteelRelaxMat(int n, Domain *d) : StructuralMaterial(n, d) -{ - E = 0.; - k1 = 0.; - k2 = 0.; - rho1000 = 0.; - mu = 0.; - timeFactor = 0.; - //stiffnessFactor = 1.e6; - // prestress = 0.; -} - -// destructor -SteelRelaxMat :: ~SteelRelaxMat() +SteelRelaxMat::SteelRelaxMat(int n, Domain *d) : StructuralMaterial(n, d) {} -int -SteelRelaxMat :: hasMaterialModeCapability(MaterialMode mode) -// -// returns whether the receiver supports the given mode -// +bool +SteelRelaxMat::hasMaterialModeCapability(MaterialMode mode) const { return mode == _1dMat; } - - // reads the model parameters from the input file -IRResultType -SteelRelaxMat :: initializeFrom(InputRecord *ir) +void +SteelRelaxMat::initializeFrom(InputRecord &ir) { - IRResultType result; // required by IR_GIVE_FIELD macro - - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) { - return result; - } - + StructuralMaterial::initializeFrom(ir); IR_GIVE_FIELD(ir, this->E, _IFT_SteelRelaxMat_E); // Young's modulus @@ -113,12 +88,8 @@ SteelRelaxMat :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, this->k2, _IFT_SteelRelaxMat_k2); IR_GIVE_OPTIONAL_FIELD(ir, this->rho1000, _IFT_SteelRelaxMat_rho1000); - //IR_GIVE_OPTIONAL_FIELD(ir, this->stiffnessFactor, _IFT_SteelRelaxMat_stiffnessFactor); - IR_GIVE_FIELD(ir, this->timeFactor, _IFT_SteelRelaxMat_timeFactor); - // IR_GIVE_OPTIONAL_FIELD(ir, this->prestress, _IFT_SteelRelaxMat_prestress); - IR_GIVE_FIELD(ir, this->charStrength, _IFT_SteelRelaxMat_charStrength); this->relRelaxBound = 0.; @@ -133,26 +104,22 @@ SteelRelaxMat :: initializeFrom(InputRecord *ir) // tolerance = 1 Pa // MPa -> SF = 1e6 -> tol = 1 // Pa -> SF = 1 -> tol = 1 - //this->tolerance = 1. / this->stiffnessFactor; this->tolerance = 1. / 1.e6; IR_GIVE_OPTIONAL_FIELD(ir, this->tolerance, _IFT_SteelRelaxMat_tolerance); - - - return IRRT_OK; } // creates a new material status corresponding to this class MaterialStatus * -SteelRelaxMat :: CreateStatus(GaussPoint *gp) const +SteelRelaxMat::CreateStatus(GaussPoint *gp) const { - return new SteelRelaxMatStatus(1, this->giveDomain(), gp); + return new SteelRelaxMatStatus(gp); } void -SteelRelaxMat :: giveRealStressVector(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *tStep) +SteelRelaxMat::giveRealStressVector(FloatArray &answer, + GaussPoint *gp, + const FloatArray &totalStrain, + TimeStep *tStep) { FloatArray reducedStrain, strainIncrement, stressVector; double stressIncrement; @@ -174,14 +141,6 @@ SteelRelaxMat :: giveRealStressVector(FloatArray &answer, if ( this->Approach == EquivTime_EC2 ) { double lossIncrement; - StructuralMaterial :: giveStressDependentPartOfStrainVector(reducedStrain, gp, totalStrain, tStep, VM_Incremental); - - strainIncrement.beDifferenceOf( reducedStrain, status->giveStrainVector() ); - stressIncrement = strainIncrement.at(1) * this->E; - - // subtract stress increment due to prestress losses in the current time step - - if ( status->giveStressVector().giveSize() ) { stressVector = status->giveStressVector(); } else { @@ -189,10 +148,15 @@ SteelRelaxMat :: giveRealStressVector(FloatArray &answer, stressVector.zero(); } + StructuralMaterial::giveStressDependentPartOfStrainVector(reducedStrain, gp, totalStrain, tStep, VM_Incremental); + + strainIncrement.beDifferenceOf(reducedStrain, status->giveStrainVector() ); + stressIncrement = strainIncrement.at(1) * this->E; + stressVector.at(1) += stressIncrement; if ( stressVector.at(1) > 0. ) { - this->computeIncrOfPrestressLossAtVarStrain( lossIncrement, gp, tStep, stressVector.at(1) ); + this->computeIncrOfPrestressLossAtVarStrain(lossIncrement, gp, tStep, stressVector.at(1) ); stressVector.at(1) -= lossIncrement; } @@ -212,10 +176,10 @@ SteelRelaxMat :: giveRealStressVector(FloatArray &answer, stressVector.zero(); } - // subtracts both thermal strain increment and strain due to cable relaxation + // get strain increment without strain due to cable relaxation and thermal strain this->giveStressDependentPartOfStrainVector(reducedStrain, gp, totalStrain, tStep, VM_Incremental); - strainIncrement.beDifferenceOf( reducedStrain, status->giveStrainVector() ); + strainIncrement.beDifferenceOf(reducedStrain, status->giveStrainVector() ); stressIncrement = strainIncrement.at(1) * this->E; stressVector.at(1) += stressIncrement; @@ -230,16 +194,16 @@ SteelRelaxMat :: giveRealStressVector(FloatArray &answer, if ( i > 1000 ) { OOFEM_ERROR("Algorithm not converging"); } - } while ( fabs( prevIterTempStress - status->giveTempStressVector().at(1) ) >= this->tolerance ); + } while ( fabs(prevIterTempStress - status->giveTempStressVector().at(1) ) >= this->tolerance ); - if ( i > 30 ) { + if ( i > 50 ) { OOFEM_WARNING("Criterion of the algorithm reached in %d iterations, consider increasing tolerance", i); } } if ( stressVector.at(1) > this->charStrength ) { - OOFEM_ERROR( "Stress %f exeeds the characteristic strength of the material!", stressVector.at(1) ); + OOFEM_ERROR("Stress %f exeeds the characteristic strength of the material!", stressVector.at(1) ); } answer.resize(1); @@ -247,43 +211,38 @@ SteelRelaxMat :: giveRealStressVector(FloatArray &answer, } -void -SteelRelaxMat :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF< 1, 1 > +SteelRelaxMat::give1dStressStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const { - answer.resize(1, 1); - answer.zero(); if ( this->isActivated(tStep) ) { - answer.at(1, 1) = this->E; + return { this->E }; + } else { + return { 0. }; } } - - void -SteelRelaxMat :: giveStressDependentPartOfStrainVector(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep, ValueModeType mode) +SteelRelaxMat::giveStressDependentPartOfStrainVector(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep, ValueModeType mode) { FloatArray temperatureFreeStrain; FloatArray relaxationStrain; // subtracts temperature strain - StructuralMaterial :: giveStressDependentPartOfStrainVector(temperatureFreeStrain, gp, totalStrain, tStep, mode); + StructuralMaterial::giveStressDependentPartOfStrainVector(temperatureFreeStrain, gp, totalStrain, tStep, mode); // strains due to relaxation this->computeStressRelaxationStrainVector(relaxationStrain, gp, totalStrain, tStep, mode); answer = temperatureFreeStrain; answer.subtract(relaxationStrain); - - return; } void -SteelRelaxMat :: evalStressRelaxationAtConstStrain(double &answer, GaussPoint *gp, double dt) +SteelRelaxMat::evalStressRelaxationAtConstStrain(double &answer, GaussPoint *gp, double dt) { double rho; double k; @@ -292,6 +251,7 @@ SteelRelaxMat :: evalStressRelaxationAtConstStrain(double &answer, GaussPoint *g double prestress; SteelRelaxMatStatus *status = static_cast< SteelRelaxMatStatus * >( this->giveStatus(gp) ); + // prestress loss is not calculated in the time step when prestressing is applied prestress = status->givePrestress(); answer = 0.; @@ -303,13 +263,13 @@ SteelRelaxMat :: evalStressRelaxationAtConstStrain(double &answer, GaussPoint *g k = 0.75 * ( 1. - mu ); lambda = 1000. * this->timeFactor / 24.; - answer = prestress * rho * pow( ( dt / lambda ), k ); + answer = prestress * rho * pow( ( dt / lambda ), k); } } - +// this method is active only in the case of EC2 approach void -SteelRelaxMat :: computeIncrOfPrestressLossAtVarStrain(double &answer, GaussPoint *gp, TimeStep *tStep, double stress) +SteelRelaxMat::computeIncrOfPrestressLossAtVarStrain(double &answer, GaussPoint *gp, TimeStep *tStep, double stress) { double rho; double k; @@ -324,7 +284,7 @@ SteelRelaxMat :: computeIncrOfPrestressLossAtVarStrain(double &answer, GaussPoin // "initial" value of prestress is the sum of the current stress plus the cumulative subsequent relaxation prestress = stress + lossesUpTillNow; - status->setPrestress(prestress); + status->setTempPrestress(prestress); answer = 0.; @@ -334,96 +294,67 @@ SteelRelaxMat :: computeIncrOfPrestressLossAtVarStrain(double &answer, GaussPoin k = 0.75 * ( 1. - mu ); lambda = 1000. * this->timeFactor / 24.; - // compute total loss for updated prestress and time equiv double t_equiv; t_equiv = pow( ( lossesUpTillNow / ( prestress * rho ) ), ( 1. / k ) ) * lambda; - this->evalStressRelaxationAtConstStrain( loss, gp, t_equiv + tStep->giveTimeIncrement() ); - + this->evalStressRelaxationAtConstStrain(loss, gp, t_equiv + tStep->giveTimeIncrement() ); // set temporary sum of losses status->setTempRelaxIntVariable(loss); // subtract the preceding sum of losses to get the increment - loss -= lossesUpTillNow; - - answer = loss; + answer = loss - lossesUpTillNow; } } - - - - void -SteelRelaxMat :: computeStressRelaxationStrainVector(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep, ValueModeType mode) +SteelRelaxMat::computeStressRelaxationStrainVector(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, TimeStep *tStep, ValueModeType mode) { - // here we deal with total strain vector with subtracted tempreature - SteelRelaxMatStatus *status = static_cast< SteelRelaxMatStatus * >( this->giveStatus(gp) ); - double averageStress = 0.; - int n = 0; double mu = 0.; - double k, rho, lambda; - double dt = tStep->giveTimeIncrement(); - FloatArray temperFreeStrain, temperFreeStrainIncrement; - StructuralMaterial :: giveStressDependentPartOfStrainVector(temperFreeStrain, gp, totalStrain, tStep, VM_Total); - - double averageMechStrain = temperFreeStrain.at(1); - - double prestress; - prestress = status->givePrestress(); + // get average strain due to stress relaxation + double averageRelaxationStrain = 0.5 * ( status->giveTempRelaxIntVariable() + status->giveRelaxIntVariable() ); - if ( prestress > 0. ) { - temperFreeStrainIncrement = totalStrain; // result = eps i+1 tot - temperFreeStrainIncrement.subtract( status->giveStrainVector() ); // result = delta eps tot + // get average stress + int n = 0; + if ( status->giveStressVector().at(1) > 0. ) { + averageStress += status->giveStressVector().at(1); + n++; + } - // epsilon temperature increment - FloatArray deltaEpsTemperature; - this->computeStressIndependentStrainVector(deltaEpsTemperature, gp, tStep, VM_Incremental); + if ( status->giveTempStressVector().at(1) > 0 ) { + averageStress += status->giveTempStressVector().at(1); + n++; + } - temperFreeStrainIncrement.subtract(deltaEpsTemperature); // results = delta epsilon stress + if ( n > 0 ) { + averageStress /= n; + } - averageMechStrain -= 0.5 * temperFreeStrainIncrement.at(1); + if ( !status->givePrestress() ) { + status->setTempPrestress(averageStress); } - double F = averageMechStrain * this->E; + double averageMechStrain = averageRelaxationStrain + averageStress / this->E; - if ( prestress == 0. ) { - prestress = F; - status->setPrestress(prestress); - } + double F = averageMechStrain * this->E; double relaxStrainIncrement; - - // different approach for the first step and for the following steps + // different approach for the first step after prestressing and for the following steps + // when the prestressing is applied, the losses are assumed as zero if ( status->giveRelaxIntVariable() == 0. ) { - // assume that the strain is constant and equal to zero - eval from Eurocode function + // use Eurocode function for the first prestress loss this->evalStressRelaxationAtConstStrain(relaxStrainIncrement, gp, dt); // convert into strain relaxStrainIncrement /= this->E; } else { - if ( status->giveStressVector().giveSize() ) { - averageStress += status->giveStressVector().at(1); - n++; - } - - if ( status->giveTempStressVector().giveSize() ) { - averageStress += status->giveTempStressVector().at(1); - n++; - } - - if ( n > 0 ) { - averageStress /= n; - } - // governing equations 3.28-3.30 rewritten to the following form // // original: @@ -439,6 +370,8 @@ SteelRelaxMat :: computeStressRelaxationStrainVector(FloatArray &answer, GaussPo // ... timeFactor = 1 for day / 24 for hour / 86400 for sec, etc. relaxStrainIncrement = 0.; + double prestress = status->giveTempPrestress(); + if ( averageStress > this->relRelaxBound * this->charStrength ) { mu = prestress / this->charStrength; @@ -446,11 +379,11 @@ SteelRelaxMat :: computeStressRelaxationStrainVector(FloatArray &answer, GaussPo k = 0.75 * ( 1. - mu ); lambda = 1000. * this->timeFactor / 24.; relaxStrainIncrement = k * pow(rho, 1. / k) * F * dt; - relaxStrainIncrement /= this->E * lambda * pow( ( 1. - averageStress / F ), 1. / k - 1. ); + relaxStrainIncrement /= this->E * lambda * pow( ( 1. - averageStress / F ), 1. / k - 1.); } } - status->setTempRelaxIntVariable( relaxStrainIncrement + status->giveRelaxIntVariable() ); + status->setTempRelaxIntVariable(relaxStrainIncrement + status->giveRelaxIntVariable() ); answer.resize(1); @@ -465,99 +398,83 @@ SteelRelaxMat :: computeStressRelaxationStrainVector(FloatArray &answer, GaussPo int -SteelRelaxMat :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +SteelRelaxMat::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - return StructuralMaterial :: giveIPValue(answer, gp, type, tStep); + return StructuralMaterial::giveIPValue(answer, gp, type, tStep); } //============================================================================= -SteelRelaxMatStatus :: SteelRelaxMatStatus(int n, Domain *d, GaussPoint *g) : StructuralMaterialStatus(n, d, g) -{ - relaxIntVariable = tempRelaxIntVariable = 0.; - prestress = 0.; -} +SteelRelaxMatStatus::SteelRelaxMatStatus(GaussPoint *g) : StructuralMaterialStatus(g) +{} -SteelRelaxMatStatus :: ~SteelRelaxMatStatus() -{ } void -SteelRelaxMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) +SteelRelaxMatStatus::printOutputAt(FILE *file, TimeStep *tStep) const { - StructuralMaterialStatus :: printOutputAt(file, tStep); + StructuralMaterialStatus::printOutputAt(file, tStep); fprintf(file, " relaxationInternalVariable "); fprintf(file, "%.4e ", relaxIntVariable); fprintf(file, "\n"); - fprintf(file, " initialPrestress "); + fprintf(file, " prestress "); fprintf(file, "%.4e ", prestress); fprintf(file, "\n"); } // initializes temporary variables based on their values at the previous equlibrium state -void SteelRelaxMatStatus :: initTempStatus() +void SteelRelaxMatStatus::initTempStatus() { - StructuralMaterialStatus :: initTempStatus(); + StructuralMaterialStatus::initTempStatus(); tempRelaxIntVariable = relaxIntVariable; + tempPrestress = prestress; } // updates internal variables when equilibrium is reached void -SteelRelaxMatStatus :: updateYourself(TimeStep *tStep) +SteelRelaxMatStatus::updateYourself(TimeStep *tStep) { - StructuralMaterialStatus :: updateYourself(tStep); + StructuralMaterialStatus::updateYourself(tStep); relaxIntVariable = tempRelaxIntVariable; + + prestress = tempPrestress; + + // if ( this->prestress > 0.) { + // prestressFlag = true } -// saves full information stored in this status -// temporary variables are NOT stored -contextIOResultType -SteelRelaxMatStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +SteelRelaxMatStatus::saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // save parent class status - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus::saveContext(stream, mode); - // write raw data if ( !stream.write(relaxIntVariable) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } if ( !stream.write(prestress) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } - -contextIOResultType -SteelRelaxMatStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full information stored in stream to this Status -// +void +SteelRelaxMatStatus::restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - // read parent class status - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + StructuralMaterialStatus::restoreContext(stream, mode); if ( !stream.read(relaxIntVariable) ) { - return CIO_IOERR; + THROW_CIOERR(CIO_IOERR); } - return CIO_OK; // return succes + if ( !stream.read(prestress) ) { + THROW_CIOERR(CIO_IOERR); + } } } // end namespace oofem diff --git a/src/sm/Materials/steelrelaxmat.h b/src/sm/Materials/steelrelaxmat.h index dc4e0e1ac..7d09ba629 100644 --- a/src/sm/Materials/steelrelaxmat.h +++ b/src/sm/Materials/steelrelaxmat.h @@ -35,8 +35,8 @@ #ifndef steelrelaxmat_h #define steelrelaxmat_h -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include "dictionary.h" #include "floatarray.h" #include "floatmatrix.h" @@ -61,10 +61,10 @@ class GaussPoint; class Domain; /** - * Implementation of the material model for steel relaxation given in Eurocode 2 + * Implementation of the material model for steel relaxation given in Eurocode 2 * (the same as in Model Code 2010) and in Ba\v{z}ant and Yu (J. of Eng. Mech, 2013) - * which reduces to the first model under constant strain. At variable strain history - * the first model uses the approach employing the so-called {\sl{equivalent time}} + * which reduces to the first model under constant strain. At variable strain history + * the first model uses the approach employing the so-called {\sl{equivalent time}} * approach described in Annex D in the Eurocode 2. * The current implementation takes into account only prestress losses * due to steel relaxation, other losses (e.g. slip at anchorage, @@ -74,76 +74,74 @@ class Domain; * losses due to sequential prestressing, elastic deformation and both * short-time and long-time creep and shrinkage are taken into account * automatically provided that a suitable material model is chosen for - * concrete. + * concrete. * See material manual and the above-mentioned documents for details. */ class SteelRelaxMat : public StructuralMaterial { protected: - /// Young's modulus - double E; + double E = 0.; /// constant depending on the reinforcement class - double k1; + double k1 = 0.; /// constant depending on the reinforcement class - double k2; + double k2 = 0.; /// constant depending on the reinforcement class - double rho1000; + double rho1000 = 0.; /// ratio of prestress vs. characteristic strength - double mu; + double mu = 0.; /** * Scaling factor transforming the actual time into * appropriate units needed by the formulae of the eurocode. For analysis * in days timeFactor = 1, for analysis in seconds timeFactor = 86,400. */ - double timeFactor; + double timeFactor = 0.; //double stiffnessFactor; /// characteristic strength of prestressing steel in appropriate units (not necessarily MPa) - double charStrength; + double charStrength = 0.; /// tolerance specifying the residual in the stress evaluation algorithm, default value is $10^{-6}$ - double tolerance; + double tolerance = 0.; /** * Ratio of stress to characteristic strength * under which the relaxation is zero (typically 0.4--0.5); default * value is zero. */ - double relRelaxBound; + double relRelaxBound = 0.; /** - * 0 = approach according to Ba\v{z}ant and Yu, + * 0 = approach according to Ba\v{z}ant and Yu, * 1 = equivalent time approach according to Eurocode 2 and {\sl{fib}} Model Code 2010 */ - enum approachType { Bazant_EC2, EquivTime_EC2 } Approach; - - + enum approachType { Bazant_EC2, EquivTime_EC2 } Approach = Bazant_EC2; public: SteelRelaxMat(int n, Domain *d); - virtual ~SteelRelaxMat(); - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) - { this->giveRealStressVector(answer, gp, reducedE, tStep); } + FloatArrayF< 1 >giveRealStressVector_1d(const FloatArrayF< 1 > &reducedE, GaussPoint *gp, TimeStep *tStep) const override + { + FloatArray answer; + const_cast< SteelRelaxMat * >( this )->giveRealStressVector(answer, gp, reducedE, tStep); + return answer; + } - virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); - - virtual void give1dStressStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) override; + FloatMatrixF< 1, 1 >give1dStressStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; /** * evaluates stress-related strain - subtracts not only temperature strains but also strains caused by steel relaxation */ - virtual void giveStressDependentPartOfStrainVector(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, - TimeStep *tStep, ValueModeType mode); + void giveStressDependentPartOfStrainVector(FloatArray &answer, GaussPoint *gp, const FloatArray &totalStrain, + TimeStep *tStep, ValueModeType mode); /** * evaluates eigenstrain due to steel relaxation */ @@ -160,20 +158,20 @@ class SteelRelaxMat : public StructuralMaterial */ void computeIncrOfPrestressLossAtVarStrain(double &answer, GaussPoint *gp, TimeStep *tStep, double stress); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual int hasNonLinearBehaviour() { return 1; } + bool hasMaterialModeCapability(MaterialMode mode) const override; - virtual int hasMaterialModeCapability(MaterialMode mode); + bool hasCastingTimeSupport() const override { return true; } - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return true; } + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return true; } - virtual const char *giveInputRecordName() const { return _IFT_SteelRelaxMat_Name; } - virtual const char *giveClassName() const { return "SteelRelaxMat"; } + const char *giveInputRecordName() const override { return _IFT_SteelRelaxMat_Name; } + const char *giveClassName() const override { return "SteelRelaxMat"; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; }; //============================================================================= @@ -183,39 +181,39 @@ class SteelRelaxMatStatus : public StructuralMaterialStatus { protected: - /** - * For Bazant's approach this internal variable is a cumulative viscous strain - * while for Eurocode approach (equivalent time) it is a cumulative prestress loss - */ - double relaxIntVariable; - double tempRelaxIntVariable; + /** + * For Bazant's approach this internal variable is a cumulative viscous strain + * while for Eurocode approach (equivalent time) it is a cumulative prestress loss + */ + double relaxIntVariable = 0.; + double tempRelaxIntVariable = 0.; - double prestress; + double prestress = 0.; + double tempPrestress = 0.; + // becomes activated at the end of the time step when the material becomes prestressed + // bool prestressedFlag = false; public: - SteelRelaxMatStatus(int n, Domain *d, GaussPoint *g); - virtual ~SteelRelaxMatStatus(); - - + SteelRelaxMatStatus(GaussPoint *g); void setTempRelaxIntVariable(double src) { tempRelaxIntVariable = src; } - double giveTempRelaxIntVariable(void) { return tempRelaxIntVariable; } - double giveRelaxIntVariable(void) { return relaxIntVariable; } - - void setPrestress(double src) { prestress = src; } - double givePrestress(void) { return prestress; } + double giveTempRelaxIntVariable() const { return tempRelaxIntVariable; } + double giveRelaxIntVariable() const { return relaxIntVariable; } + void setTempPrestress(double src) { tempPrestress = src; } + double giveTempPrestress() const { return tempPrestress; } + double givePrestress() const { return prestress; } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); + void initTempStatus() override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual const char *giveClassName() const { return "SteelRelaxMatStatus"; } + const char *giveClassName() const override { return "SteelRelaxMatStatus"; } }; } // end namespace oofem #endif // steelrelaxmat_h diff --git a/src/sm/Materials/structmatsettable.C b/src/sm/Materials/structmatsettable.C index 957512d25..28e7a22ff 100644 --- a/src/sm/Materials/structmatsettable.C +++ b/src/sm/Materials/structmatsettable.C @@ -37,7 +37,7 @@ #include "floatarray.h" #include "floatmatrix.h" #include "gausspoint.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "datastream.h" #include "contextioerr.h" #include "mathfem.h" @@ -48,55 +48,44 @@ namespace oofem { REGISTER_Material( StructuralMaterialSettable ); StructuralMaterialSettable :: StructuralMaterialSettable(int n, Domain *d) : - StructuralMaterial(n, d) -{ - isoLE = new IsotropicLinearElasticMaterial(n,d); -} + StructuralMaterial(n, d), + isoLE(n,d) +{} -StructuralMaterialSettable :: ~StructuralMaterialSettable() -{ - delete isoLE; -} -IRResultType -StructuralMaterialSettable :: initializeFrom(InputRecord *ir) +void +StructuralMaterialSettable :: initializeFrom(InputRecord &ir) { - //IRResultType result; // Required by IR_GIVE_FIELD macro StructuralMaterial :: initializeFrom(ir); - return isoLE->initializeFrom(ir); + isoLE.initializeFrom(ir); } -void -StructuralMaterialSettable :: giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &totalStrain, - TimeStep *atTime) -{ - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - const FloatArray& stressVector = status->giveStressVector(); +FloatArrayF<6> +StructuralMaterialSettable :: giveRealStressVector_3d(const FloatArrayF<6> &strain,GaussPoint *gp, + TimeStep *atTime) const +{ + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + const auto &stressVector = status->giveStressVector(); - status->letTempStrainVectorBe(totalStrain); + status->letTempStrainVectorBe(strain); status->letTempStressVectorBe(stressVector); - answer = stressVector; - return; + return stressVector; } // TODO -void -StructuralMaterialSettable :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *atTime) +FloatMatrixF<6,6> +StructuralMaterialSettable :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, + TimeStep *atTime) const { - isoLE->give3dMaterialStiffnessMatrix(answer,mode,gp,atTime); + return isoLE.give3dMaterialStiffnessMatrix(mode, gp, atTime); } MaterialStatus * StructuralMaterialSettable :: CreateStatus(GaussPoint *gp) const { - return new StructuralMaterialStatus(1, StructuralMaterial :: giveDomain(), gp); + return new StructuralMaterialStatus(gp); } diff --git a/src/sm/Materials/structmatsettable.h b/src/sm/Materials/structmatsettable.h index 79916f150..a5888ec8f 100644 --- a/src/sm/Materials/structmatsettable.h +++ b/src/sm/Materials/structmatsettable.h @@ -37,10 +37,9 @@ #include "floatarray.h" #include "floatmatrix.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/Materials/structuralmaterial.h" - -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/isolinearelasticmaterial.h" ///@name Input fields for StructuralMaterialSettable //@{ @@ -57,31 +56,22 @@ namespace oofem { class StructuralMaterialSettable : public StructuralMaterial { private: - IsotropicLinearElasticMaterial *isoLE; + IsotropicLinearElasticMaterial isoLE; public: /// Constructor StructuralMaterialSettable(int n, Domain *d); - /// Destructor - virtual ~StructuralMaterialSettable(); - - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveClassName() const { return "StructuralMaterialSettable"; } - virtual const char *giveInputRecordName() const { return _IFT_StructuralMaterialSettable_Name; } + void initializeFrom(InputRecord &ir) override; - virtual void giveRealStressVector_3d(FloatArray &answer, - GaussPoint *gp, - const FloatArray &strainVector, - TimeStep *atTime); + const char *giveClassName() const override { return "StructuralMaterialSettable"; } + const char *giveInputRecordName() const override { return _IFT_StructuralMaterialSettable_Name; } - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *atTime); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; }; } // end namespace oofem #endif // structmatsettable_h diff --git a/src/sm/Materials/structuralfe2material.C b/src/sm/Materials/structuralfe2material.C index 1792fe1aa..81cad3304 100644 --- a/src/sm/Materials/structuralfe2material.C +++ b/src/sm/Materials/structuralfe2material.C @@ -10,7 +10,7 @@ * * OOFEM : Object Oriented Finite Element Code * - * Copyright (C) 1993 - 2013 Borek Patzak + * Copyright (C) 1993 - 2021 Borek Patzak * * * @@ -47,8 +47,8 @@ #include "exportmodulemanager.h" #include "vtkxmlexportmodule.h" #include "nummet.h" -#include "EngineeringModels/xfemsolverinterface.h" -#include "EngineeringModels/staticstructural.h" +#include "sm/EngineeringModels/xfemsolverinterface.h" +#include "sm/EngineeringModels/staticstructural.h" #include "unknownnumberingscheme.h" #include "xfem/xfemstructuremanager.h" #include "mathfem.h" @@ -62,23 +62,17 @@ REGISTER_Material(StructuralFE2Material); int StructuralFE2Material :: n = 1; -StructuralFE2Material :: StructuralFE2Material(int n, Domain *d) : StructuralMaterial(n, d), -useNumTangent(true) -{} - -StructuralFE2Material :: ~StructuralFE2Material() +StructuralFE2Material :: StructuralFE2Material(int n, Domain *d) : StructuralMaterial(n, d) {} -IRResultType -StructuralFE2Material :: initializeFrom(InputRecord *ir) +void +StructuralFE2Material :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->inputfile, _IFT_StructuralFE2Material_fileName); - useNumTangent = ir->hasField(_IFT_StructuralFE2Material_useNumericalTangent); - - return StructuralMaterial :: initializeFrom(ir); + useNumTangent = ir.hasField(_IFT_StructuralFE2Material_useNumericalTangent); } @@ -97,93 +91,88 @@ StructuralFE2Material :: giveInputRecord(DynamicInputRecord &input) MaterialStatus * StructuralFE2Material :: CreateStatus(GaussPoint *gp) const { - return new StructuralFE2MaterialStatus(1, this->giveDomain(), gp, this->inputfile); + int rank = -1; + auto emodel = this->domain->giveEngngModel(); + if ( emodel->isParallel() && emodel->giveNumberOfProcesses() > 1 ) { + rank = emodel->giveRank(); + } + return new StructuralFE2MaterialStatus(rank, gp, this->inputfile); } -void -StructuralFE2Material :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &totalStrain, TimeStep *tStep) +FloatArrayF<6> +StructuralFE2Material :: giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const { - FloatArray stress; - StructuralFE2MaterialStatus *ms = static_cast< StructuralFE2MaterialStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< StructuralFE2MaterialStatus * >( this->giveStatus(gp) ); #if 0 - XfemStructureManager *xMan = dynamic_cast( ms->giveRVE()->giveDomain(1)->giveXfemManager() ); - if(xMan) { - printf("Total crack length in RVE: %e\n", xMan->computeTotalCrackLength() ); - } + XfemStructureManager *xMan = dynamic_cast( ms->giveRVE()->giveDomain(1)->giveXfemManager() ); + if(xMan) { + printf("Total crack length in RVE: %e\n", xMan->computeTotalCrackLength() ); + } #endif ms->setTimeStep(tStep); // Set input - ms->giveBC()->setPrescribedGradientVoigt(totalStrain); + ms->giveBC()->setPrescribedGradientVoigt(strain); // Solve subscale problem ms->giveRVE()->solveYourselfAt(tStep); // Post-process the stress + FloatArray stress; ms->giveBC()->computeField(stress, tStep); + FloatArrayF<6> answer; if ( stress.giveSize() == 6 ) { answer = stress; - } if ( stress.giveSize() == 9 ) { + } else if ( stress.giveSize() == 9 ) { answer = {stress[0], stress[1], stress[2], 0.5*(stress[3]+stress[6]), 0.5*(stress[4]+stress[7]), 0.5*(stress[5]+stress[8])}; + } else if ( stress.giveSize() == 4 ) { + // 2D mode is a bit wonky in FE2 code right now. It doesn't actually deal with plane strain out-of-plane component correctly. + // Instead gives just the 2D state, non-symmetrically. + // This needs to be cleared up and made consistent, to take out the guesswork on what computeField() actually computes. + answer = {stress[0], stress[1], 0., 0., 0., 0.5*(stress[2]+stress[3])}; } else { - StructuralMaterial::giveFullSymVectorForm(answer, stress, gp->giveMaterialMode() ); + answer = {stress[0], 0., 0., 0., 0., 0.}; } // Update the material status variables ms->letTempStressVectorBe(answer); - ms->letTempStrainVectorBe(totalStrain); + ms->letTempStrainVectorBe(strain); ms->markOldTangent(); // Mark this so that tangent is reevaluated if they are needed. + return answer; } -void -StructuralFE2Material :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<6,6> +StructuralFE2Material :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { + auto status = static_cast( this->giveStatus( gp ) ); if ( useNumTangent ) { // Numerical tangent - StructuralFE2MaterialStatus *status = static_cast( this->giveStatus( gp ) ); double h = 1.0e-9; - const FloatArray &epsRed = status->giveTempStrainVector(); - FloatArray eps; - StructuralMaterial::giveFullSymVectorForm(eps, epsRed, gp->giveMaterialMode() ); + FloatArrayF<6> eps = status->giveTempStrainVector(); + FloatArrayF<6> sig = status->giveTempStressVector(); - - int dim = eps.giveSize(); - answer.resize(dim, dim); - answer.zero(); - - FloatArray sig, sigPert, epsPert; - - for(int i = 1; i <= dim; i++) { + FloatMatrixF<6,6> answer; + for(int i = 0; i < 6; i++) { // Add a small perturbation to the strain - epsPert = eps; - epsPert.at(i) += h; + auto epsPert = eps; + epsPert[i] += h; - giveRealStressVector_3d(sigPert, gp, epsPert, tStep); - answer.setColumn(sigPert, i); - } - - giveRealStressVector_3d(sig, gp, eps, tStep); - - for(int i = 1; i <= dim; i++) { - for(int j = 1; j <= dim; j++) { - answer.at(j,i) -= sig.at(j); - answer.at(j,i) /= h; - } + auto sigPert = const_cast(this)->giveRealStressVector_3d(epsPert, gp, tStep); + answer.setColumn((sigPert - sig) / h, i); } + const_cast(this)->giveRealStressVector_3d(eps, gp, tStep); + return answer; } else { - - StructuralFE2MaterialStatus *ms = static_cast< StructuralFE2MaterialStatus * >( this->giveStatus(gp) ); - ms->computeTangent(tStep); - const FloatMatrix &ans9 = ms->giveTangent(); - + status->computeTangent(tStep); + const auto &ans9 = status->giveTangent(); + FloatMatrix answer; StructuralMaterial::giveReducedSymMatrixForm(answer, ans9, _3dMat); + return answer; -// const FloatMatrix &ans9 = ms->giveTangent(); // printf("ans9: "); ans9.printYourself(); // // // Compute the (minor) symmetrized tangent: @@ -245,49 +234,146 @@ StructuralFE2Material :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatR } } +FloatMatrixF<4,4> +StructuralFE2Material :: givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + /// The plane-strain version of the tangent is overloaded primarily for performance when using the numerical tangent. + auto status = static_cast( this->giveStatus( gp ) ); + if ( useNumTangent ) { + // Numerical tangent + double h = 1.0e-9; -//============================================================================= + auto eps = FloatArrayF<6>(status->giveTempStrainVector())[{0, 1, 2, 5}]; + auto sig = FloatArrayF<6>(status->giveTempStressVector())[{0, 1, 2, 5}]; + + FloatMatrixF<4,4> answer; + for(int i = 0; i < 4; i++) { + // Add a small perturbation to the strain + auto epsPert = eps; + epsPert[i] += h; + + auto sigPert = this->giveRealStressVector_PlaneStrain(epsPert, gp, tStep); + answer.setColumn((sigPert - sig) / h, i); + } + this->giveRealStressVector_PlaneStrain(eps, gp, tStep); + return answer; -StructuralFE2MaterialStatus :: StructuralFE2MaterialStatus(int n, Domain * d, GaussPoint * g, const std :: string & inputfile) : -StructuralMaterialStatus(n, d, g), -mNewlyInitialized(true) + } else { + status->computeTangent(tStep); + return status->giveTangent(); + } +} + +FloatArrayF<3> +StructuralFE2Material::giveRealStressVector_PlaneStress( const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep ) const { - mInputFile = inputfile; + auto ms = static_cast( this->giveStatus(gp) ); - this->oldTangent = true; + ms->setTimeStep(tStep); + // Set input + ms->giveBC()->setPrescribedGradientVoigt(strain); + // Solve subscale problem + ms->giveRVE()->solveYourselfAt(tStep); + // Post-process the stress + FloatArray stress; + ms->giveBC()->computeField(stress, tStep); - if ( !this->createRVE(n, gp, inputfile) ) { - OOFEM_ERROR("Couldn't create RVE"); + FloatArrayF<6> updateStress; + updateStress = {stress[0], stress[1], 0., 0., 0., 0.5*(stress[2]+stress[3])}; + + FloatArrayF<6> updateStrain; + updateStrain = {strain[0], strain[1], 0., 0., 0., strain[2]}; + + FloatArrayF<3> answer; + answer = {stress[0], stress[1], 0.5*(stress[2]+stress[3])}; + + // Update the material status variables + ms->letTempStressVectorBe(updateStress); + ms->letTempStrainVectorBe(updateStrain); + ms->markOldTangent(); // Mark this so that tangent is reevaluated if they are needed. + + return answer; + +} + +FloatMatrixF<3, 3> +StructuralFE2Material::givePlaneStressStiffMtrx( MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep ) const +{ + if (useNumTangent) { + //Numerical tangent + auto status = static_cast(this->giveStatus(gp)); + double h = 1.0e-9; + + FloatArrayF<6> eps = status->giveTempStrainVector(); + FloatArrayF<6> sig = status->giveTempStressVector(); + + FloatArrayF<3> epsRed = {eps[0], eps[1], eps[5]}; + FloatArrayF<3> sigRed = {sig[0], sig[1], sig[5]}; + + FloatMatrixF<3,3> answer; + for (int i=0; i < 3; i++) { + //Add a small perturbation to the strain + auto epsPert = epsRed; + epsPert[i] += h; + + auto sigPert = const_cast(this)->giveRealStressVector_PlaneStress(epsPert, gp, tStep); + answer.setColumn((sigPert - sigRed) / h, i); + } + const_cast(this)->giveRealStressVector_PlaneStress(epsRed, gp, tStep); + return answer; + } else { + auto status = static_cast(this->giveStatus(gp)); + FloatMatrix tangent; + status->computeTangent(tStep); //implemented by BC + tangent.beSubMatrixOf(status->giveTangent(), {1,2,3}, {1,2,3}); + FloatMatrixF<3,3> answer; + answer = tangent; + return answer; } } + +//============================================================================= + + +StructuralFE2MaterialStatus :: StructuralFE2MaterialStatus(int rank, GaussPoint * g, const std :: string & inputfile) : + StructuralMaterialStatus(g), + mInputFile(inputfile) +{ + if ( !this->createRVE(1, inputfile, rank) ) { ///@TODO FIXME createRVE + OOFEM_ERROR("Couldn't create RVE"); + } + stressVector.resize(6); + strainVector.resize(6); + tempStressVector.resize(6); + tempStrainVector.resize(6); +} + PrescribedGradientHomogenization* StructuralFE2MaterialStatus::giveBC() { - this->bc = dynamic_cast< PrescribedGradientHomogenization * >( this->rve->giveDomain(1)->giveBc(1) ); - return this->bc; + this->bc = dynamic_cast< PrescribedGradientHomogenization * >( this->rve->giveDomain(1)->giveBc(1) ); + return this->bc; } bool -StructuralFE2MaterialStatus :: createRVE(int n, GaussPoint *gp, const std :: string &inputfile) +StructuralFE2MaterialStatus :: createRVE(int n, const std :: string &inputfile, int rank) { OOFEMTXTDataReader dr( inputfile.c_str() ); - EngngModel *em = InstanciateProblem(& dr, _processor, 0); // Everything but nrsolver is updated. + this->rve = InstanciateProblem(dr, _processor, 0); // Everything but nrsolver is updated. dr.finish(); - em->setProblemScale(microScale); - em->checkProblemConsistency(); - em->initMetaStepAttributes( em->giveMetaStep(1) ); - em->giveNextStep(); // Makes sure there is a timestep (which we will modify before solving a step) - em->init(); - - this->rve.reset( em ); + this->rve->setProblemScale(microScale); + this->rve->checkProblemConsistency(); + this->rve->initMetaStepAttributes( this->rve->giveMetaStep(1) ); + this->rve->giveNextStep(); // Makes sure there is a timestep (which we will modify before solving a step) + this->rve->init(); std :: ostringstream name; name << this->rve->giveOutputBaseFileName() << "-gp" << n; - if ( this->domain->giveEngngModel()->isParallel() && this->domain->giveEngngModel()->giveNumberOfProcesses() > 1 ) { - name << "." << this->domain->giveEngngModel()->giveRank(); + if ( rank >= 0 ) { + name << "." << rank; } this->rve->letOutputBaseFileNameBe( name.str() ); @@ -343,39 +429,30 @@ StructuralFE2MaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -StructuralFE2MaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +StructuralFE2MaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = StructuralMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return this->rve->saveContext(stream, mode); + StructuralMaterialStatus :: saveContext(stream, mode); + this->rve->saveContext(stream, mode); } -contextIOResultType -StructuralFE2MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +StructuralFE2MaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - if ( ( iores = StructuralMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return this->rve->restoreContext(&stream, mode, obj); + StructuralMaterialStatus :: restoreContext(stream, mode); + this->rve->restoreContext(stream, mode); } double StructuralFE2MaterialStatus :: giveRveLength() { - double rveLength = sqrt( bc->domainSize() ); - return rveLength; + return sqrt( bc->domainSize() ); } void StructuralFE2MaterialStatus :: copyStateVariables(const MaterialStatus &iStatus) { -// static int num = 0; -// printf("Entering StructuralFE2MaterialStatus :: copyStateVariables.\n"); + //static int num = 0; + //printf("Entering StructuralFE2MaterialStatus :: copyStateVariables.\n"); this->oldTangent = true; @@ -384,91 +461,85 @@ void StructuralFE2MaterialStatus :: copyStateVariables(const MaterialStatus &iSt // } - StructuralMaterialStatus::copyStateVariables(iStatus); - + StructuralMaterialStatus :: copyStateVariables(iStatus); - ////////////////////////////// - MaterialStatus &tmpStat = const_cast< MaterialStatus & >(iStatus); - StructuralFE2MaterialStatus *fe2ms = dynamic_cast(&tmpStat); - if(!fe2ms) { - OOFEM_ERROR("Failed to cast StructuralFE2MaterialStatus.") - } + ////////////////////////////// + const StructuralFE2MaterialStatus *fe2ms = dynamic_cast(&iStatus); + if ( !fe2ms ) { + OOFEM_ERROR("Failed to cast StructuralFE2MaterialStatus.") + } - this->mNewlyInitialized = fe2ms->mNewlyInitialized; - // The proper way to do this would be to clone the RVE from iStatus. - // However, this is a mess due to all pointers that need to be tracked. - // Therefore, we consider a simplified version: copy only the enrichment items. + this->mNewlyInitialized = fe2ms->mNewlyInitialized; - Domain *ext_domain = fe2ms->giveRVE()->giveDomain(1); - if( ext_domain->hasXfemManager() ) { + // The proper way to do this would be to clone the RVE from iStatus. + // However, this is a mess due to all pointers that need to be tracked. + // Therefore, we consider a simplified version: copy only the enrichment items. - Domain *rve_domain = rve->giveDomain(1); + Domain *ext_domain = fe2ms->giveRVE()->giveDomain(1); + if ( ext_domain->hasXfemManager() ) { - XfemManager *ext_xMan = ext_domain->giveXfemManager(); - XfemManager *this_xMan = rve->giveDomain(1)->giveXfemManager(); - DynamicDataReader dataReader; - if ( ext_xMan != NULL ) { + Domain *rve_domain = rve->giveDomain(1); - IRResultType result; // Required by IR_GIVE_FIELD macro - std::vector> eiList; + XfemManager *ext_xMan = ext_domain->giveXfemManager(); + XfemManager *this_xMan = rve->giveDomain(1)->giveXfemManager(); + DynamicDataReader dataReader("fe2"); + if ( ext_xMan != NULL ) { -// DynamicInputRecord *xmanRec = new DynamicInputRecord(); -// ext_xMan->giveInputRecord(* xmanRec); -// dataReader.insertInputRecord(DataReader :: IR_xfemManRec, xmanRec); + std::vector> eiList; - // Enrichment items - int nEI = ext_xMan->giveNumberOfEnrichmentItems(); - for ( int i = 1; i <= nEI; i++ ) { - EnrichmentItem *ext_ei = ext_xMan->giveEnrichmentItem(i); - ext_ei->appendInputRecords(dataReader); + //auto &xmanRec = std::make_unique(); + //ext_xMan->giveInputRecord(* xmanRec); + //dataReader.insertInputRecord(DataReader :: IR_xfemManRec, xmanRec); + // Enrichment items + int nEI = ext_xMan->giveNumberOfEnrichmentItems(); + for ( int i = 1; i <= nEI; i++ ) { + EnrichmentItem *ext_ei = ext_xMan->giveEnrichmentItem(i); + ext_ei->appendInputRecords(dataReader); - InputRecord *mir = dataReader.giveInputRecord(DataReader :: IR_enrichItemRec, i); - std :: string name; - result = mir->giveRecordKeywordField(name); - if ( result != IRRT_OK ) { - mir->report_error(this->giveClassName(), __func__, "", result, __FILE__, __LINE__); - } + auto &mir = dataReader.giveInputRecord(DataReader :: IR_enrichItemRec, i); + std :: string name; + mir.giveRecordKeywordField(name); - std :: unique_ptr< EnrichmentItem >ei( classFactory.createEnrichmentItem( name.c_str(), i, this_xMan, rve_domain ) ); - if ( ei.get() == NULL ) { - OOFEM_ERROR( "unknown enrichment item (%s)", name.c_str() ); - } + std :: unique_ptr< EnrichmentItem >ei( classFactory.createEnrichmentItem( name.c_str(), i, this_xMan, rve_domain ) ); + if ( ei.get() == NULL ) { + OOFEM_ERROR( "unknown enrichment item (%s)", name.c_str() ); + } - ei->initializeFrom(mir); - ei->instanciateYourself(&dataReader); - eiList.push_back( std :: move(ei) ); + ei->initializeFrom(mir); + ei->instanciateYourself(dataReader); + eiList.push_back( std :: move(ei) ); - } + } - this_xMan->clearEnrichmentItems(); - this_xMan->appendEnrichmentItems(eiList); + this_xMan->clearEnrichmentItems(); + this_xMan->appendEnrichmentItems(eiList); - rve_domain->postInitialize(); - rve->forceEquationNumbering(); - } + rve_domain->postInitialize(); + rve->forceEquationNumbering(); + } - } + } -// printf("done.\n"); + //printf("done.\n"); #if 0 - Domain *newDomain = fe2ms->giveRVE()->giveDomain(1)->Clone(); - newDomain->SetEngngModel(rve.get()); - bool deallocateOld = true; - rve->setDomain(1, newDomain, deallocateOld); + Domain *newDomain = fe2ms->giveRVE()->giveDomain(1)->Clone(); + newDomain->SetEngngModel(rve.get()); + bool deallocateOld = true; + rve->setDomain(1, newDomain, deallocateOld); -// rve->giveDomain(1)->postInitialize(); - rve->giveNumericalMethod(NULL)->setDomain(newDomain); + //rve->giveDomain(1)->postInitialize(); + rve->giveNumericalMethod(NULL)->setDomain(newDomain); - rve->postInitialize(); -// rve->forceEquationNumbering(); + rve->postInitialize(); + //rve->forceEquationNumbering(); - rve->initMetaStepAttributes( rve->giveMetaStep(1) ); + rve->initMetaStepAttributes( rve->giveMetaStep(1) ); rve->giveNextStep(); // Makes sure there is a timestep (which we will modify before solving a step) rve->init(); @@ -480,8 +551,8 @@ void StructuralFE2MaterialStatus :: copyStateVariables(const MaterialStatus &iSt double crackLength = 0.0; XfemStructureManager *xMan = dynamic_cast( rve->giveDomain(1)->giveXfemManager() ); - if(xMan) { - crackLength = xMan->computeTotalCrackLength(); + if ( xMan ) { + crackLength = xMan->computeTotalCrackLength(); } std :: ostringstream name; @@ -495,29 +566,29 @@ void StructuralFE2MaterialStatus :: copyStateVariables(const MaterialStatus &iSt this->rve->letOutputBaseFileNameBe( name.str() ); - // Update BC - this->bc = dynamic_cast< PrescribedGradientHomogenization * >( this->rve->giveDomain(1)->giveBc(1) ); + // Update BC + this->bc = dynamic_cast< PrescribedGradientHomogenization * >( this->rve->giveDomain(1)->giveBc(1) ); #if 1 XfemSolverInterface *xfemSolInt = dynamic_cast(rve.get()); StaticStructural *statStruct = dynamic_cast(rve.get()); - if(xfemSolInt && statStruct) { -// printf("Successfully casted to XfemSolverInterface.\n"); + if ( xfemSolInt && statStruct ) { + //printf("Successfully casted to XfemSolverInterface.\n"); - TimeStep *tStep = rve->giveCurrentStep(); + TimeStep *tStep = rve->giveCurrentStep(); - EModelDefaultEquationNumbering num; - int numDofsNew = rve->giveNumberOfDomainEquations( 1, num ); - FloatArray u; - u.resize(numDofsNew); - u.zero(); + EModelDefaultEquationNumbering num; + int numDofsNew = rve->giveNumberOfDomainEquations( 1, num ); + FloatArray u; + u.resize(numDofsNew); + u.zero(); - xfemSolInt->xfemUpdatePrimaryField(*statStruct, tStep, u); + xfemSolInt->xfemUpdatePrimaryField(*statStruct, tStep, u); - // Set domain pointer to various components ... - rve->giveNumericalMethod(NULL)->setDomain(newDomain); - // ioEngngModel.nMethod->setDomain(domain); + // Set domain pointer to various components ... + rve->giveNumericalMethod(NULL)->setDomain(newDomain); + //ioEngngModel.nMethod->setDomain(domain); } @@ -526,7 +597,6 @@ void StructuralFE2MaterialStatus :: copyStateVariables(const MaterialStatus &iSt // rve->solveYourselfAt(tStep); - int numExpModules = rve->giveExportModuleManager()->giveNumberOfModules(); for ( int i = 1; i <= numExpModules; i++ ) { // ... by diving deep into the hierarchies ... :-/ diff --git a/src/sm/Materials/structuralfe2material.h b/src/sm/Materials/structuralfe2material.h index 2db305bca..06504dd1e 100644 --- a/src/sm/Materials/structuralfe2material.h +++ b/src/sm/Materials/structuralfe2material.h @@ -35,8 +35,8 @@ #ifndef structuralfe2material_h #define structuralfe2material_h -#include "Materials/structuralmaterial.h" -#include "Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" #include @@ -57,44 +57,41 @@ class StructuralFE2MaterialStatus : public StructuralMaterialStatus /// The RVE std :: unique_ptr< EngngModel > rve; /// Boundary condition in RVE that performs the computational homogenization. - PrescribedGradientHomogenization *bc; + PrescribedGradientHomogenization *bc = nullptr; FloatMatrix tangent; - bool oldTangent; + bool oldTangent = true; /// Interface normal direction FloatArray mNormalDir; std :: string mInputFile; - - public: - StructuralFE2MaterialStatus(int n, Domain * d, GaussPoint * g, const std :: string & inputfile); - virtual ~StructuralFE2MaterialStatus() {} + StructuralFE2MaterialStatus(int rank, GaussPoint * g, const std :: string & inputfile); - EngngModel *giveRVE() { return this->rve.get(); } + EngngModel *giveRVE() const { return this->rve.get(); } PrescribedGradientHomogenization *giveBC();// { return this->bc; } void markOldTangent(); void computeTangent(TimeStep *tStep); /// Creates/Initiates the RVE problem. - bool createRVE(int n, GaussPoint *gp, const std :: string &inputfile); + bool createRVE(int n, const std :: string &inputfile, int rank); /// Copies time step data to RVE. void setTimeStep(TimeStep *tStep); FloatMatrix &giveTangent() { return tangent; } - - virtual const char *giveClassName() const { return "StructuralFE2MaterialStatus"; } - - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + const char *giveClassName() const override { return "StructuralFE2MaterialStatus"; } + + void initTempStatus() override; + + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; const FloatArray &giveNormal() const { return mNormalDir; } void letNormalBe(FloatArray iN) { mNormalDir = std :: move(iN); } @@ -102,15 +99,14 @@ class StructuralFE2MaterialStatus : public StructuralMaterialStatus double giveRveLength(); /// Functions for MaterialStatusMapperInterface - virtual void copyStateVariables(const MaterialStatus &iStatus); - virtual void addStateVariables(const MaterialStatus &iStatus) {OOFEM_ERROR("Not implemented.")}; + void copyStateVariables(const MaterialStatus &iStatus) override; + void addStateVariables(const MaterialStatus &iStatus) override { OOFEM_ERROR("Not implemented."); } // For debugging only - bool mNewlyInitialized; - + bool mNewlyInitialized = true; }; - + /** * Multiscale constitutive model for subscale structural problems. * @@ -126,23 +122,23 @@ class StructuralFE2Material : public StructuralMaterial protected: std :: string inputfile; static int n; - bool useNumTangent; + bool useNumTangent = false; public: StructuralFE2Material(int n, Domain * d); - virtual ~StructuralFE2Material(); - - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual const char *giveInputRecordName() const { return _IFT_StructuralFE2Material_Name; } - virtual const char *giveClassName() const { return "StructuralFE2Material"; } - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return true; } - - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; - // stress computation methods - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveInputRecordName() const override { return _IFT_StructuralFE2Material_Name; } + const char *giveClassName() const override { return "StructuralFE2Material"; } + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return true; } + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<4,4> givePlaneStrainStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; }; } // end namespace oofem diff --git a/src/sm/Materials/structuralmaterial.C b/src/sm/Materials/structuralmaterial.C index fdbccbf54..c4358b5d1 100644 --- a/src/sm/Materials/structuralmaterial.C +++ b/src/sm/Materials/structuralmaterial.C @@ -32,40 +32,41 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "domain.h" #include "verbose.h" -#include "../sm/Materials/structuralms.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Materials/structuralms.h" +#include "sm/Elements/structuralelement.h" +#include "sm/Elements/nlstructuralelement.h" #include "gausspoint.h" #include "floatmatrix.h" #include "floatarray.h" +#include "floatmatrixf.h" +#include "floatarrayf.h" #include "mathfem.h" #include "engngm.h" #include "fieldmanager.h" #include "dynamicinputrecord.h" namespace oofem { - -std::vector< std::vector > StructuralMaterial :: vIindex = { - { 1, 6, 5 }, - { 9, 2, 4 }, - { 8, 7, 3 } +std::array< std::array< int, 3 >, 3 >StructuralMaterial::vIindex = { + 1, 6, 5, + 9, 2, 4, + 8, 7, 3 }; -std::vector< std::vector > StructuralMaterial :: svIndex = { - { 1, 6, 5 }, - { 6, 2, 4 }, - { 5, 4, 3 } +std::array< std::array< int, 3 >, 3 >StructuralMaterial::svIndex = { + 1, 6, 5, + 6, 2, 4, + 5, 4, 3 }; -StructuralMaterial :: StructuralMaterial(int n, Domain * d) : Material(n, d) { } +StructuralMaterial::StructuralMaterial(int n, Domain *d) : Material(n, d) { } -int -StructuralMaterial :: hasMaterialModeCapability(MaterialMode mode) +bool +StructuralMaterial::hasMaterialModeCapability(MaterialMode mode) const // // returns whether receiver supports given mode // @@ -76,66 +77,60 @@ StructuralMaterial :: hasMaterialModeCapability(MaterialMode mode) void -StructuralMaterial :: giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +StructuralMaterial::giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) { ///@todo Move this to StructuralCrossSection ? MaterialMode mode = gp->giveMaterialMode(); if ( mode == _3dMat ) { - this->giveRealStressVector_3d(answer, gp, reducedStrain, tStep); + answer = this->giveRealStressVector_3d(reducedStrain, gp, tStep); } else if ( mode == _3dDegeneratedShell ) { - this->giveRealStressVector_3d(answer, gp, reducedStrain, tStep); + answer = this->giveRealStressVector_3d(reducedStrain, gp, tStep); } else if ( mode == _PlaneStrain ) { - this->giveRealStressVector_PlaneStrain(answer, gp, reducedStrain, tStep); + answer = this->giveRealStressVector_PlaneStrain(reducedStrain, gp, tStep); } else if ( mode == _PlaneStress ) { - this->giveRealStressVector_PlaneStress(answer, gp, reducedStrain, tStep); + answer = this->giveRealStressVector_PlaneStress(reducedStrain, gp, tStep); } else if ( mode == _1dMat ) { - this->giveRealStressVector_1d(answer, gp, reducedStrain, tStep); + answer = this->giveRealStressVector_1d(reducedStrain, gp, tStep); } else if ( mode == _2dBeamLayer ) { - this->giveRealStressVector_2dBeamLayer(answer, gp, reducedStrain, tStep); + answer = this->giveRealStressVector_2dBeamLayer(reducedStrain, gp, tStep); } else if ( mode == _PlateLayer ) { - this->giveRealStressVector_PlateLayer(answer, gp, reducedStrain, tStep); + answer = this->giveRealStressVector_PlateLayer(reducedStrain, gp, tStep); } else if ( mode == _Fiber ) { - this->giveRealStressVector_Fiber(answer, gp, reducedStrain, tStep); - } else if ( mode == _2dLattice ) { - this->giveRealStressVector_Lattice2d(answer, gp, reducedStrain, tStep); - } else if ( mode == _3dLattice ) { - this->giveRealStressVector_Lattice3d(answer, gp, reducedStrain, tStep); + answer = this->giveRealStressVector_Fiber(reducedStrain, gp, tStep); } else if ( mode == _2dPlateSubSoil ) { - this->giveRealStressVector_2dPlateSubSoil(answer, gp, reducedStrain, tStep); + answer = this->giveRealStressVector_2dPlateSubSoil(reducedStrain, gp, tStep); } else if ( mode == _3dBeamSubSoil ) { - this->giveRealStressVector_3dBeamSubSoil(answer, gp, reducedStrain, tStep); + answer = this->giveRealStressVector_3dBeamSubSoil(reducedStrain, gp, tStep); } } -void -StructuralMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF< 6 > +StructuralMaterial::giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("3d mode not supported"); } -void -StructuralMaterial :: giveRealStressVector_Warping(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF< 2 > +StructuralMaterial::giveRealStressVector_Warping(const FloatArrayF< 2 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("Warping mode not supported"); } -void -StructuralMaterial :: giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF< 4 > +StructuralMaterial::giveRealStressVector_PlaneStrain(const FloatArrayF< 4 > &strain, GaussPoint *gp, TimeStep *tStep) const { - FloatArray vE, vS; - StructuralMaterial :: giveFullSymVectorForm(vE, reducedStrain, _PlaneStrain); - this->giveRealStressVector_3d(vS, gp, vE, tStep); - StructuralMaterial :: giveReducedSymVectorForm(answer, vS, _PlaneStrain); + auto vS = this->giveRealStressVector_3d(assemble< 6 >(strain, { 0, 1, 2, 5 }), gp, tStep); + return vS [ { 0, 1, 2, 5 } ]; } -void -StructuralMaterial :: giveRealStressVector_StressControl(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, const IntArray &strainControl, TimeStep *tStep) +FloatArray +StructuralMaterial::giveRealStressVector_StressControl(const FloatArray &reducedStrain, const IntArray &strainControl, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); IntArray stressControl; FloatArray vE, increment_vE, vS, reducedvS; @@ -143,7 +138,7 @@ StructuralMaterial :: giveRealStressVector_StressControl(FloatArray &answer, Gau // Iterate to find full vE. // Compute the negated the array of control since we need stressControl as well; - stressControl.resize( 6 - strainControl.giveSize() ); + stressControl.resize(6 - strainControl.giveSize() ); for ( int i = 1, j = 1; i <= 6; i++ ) { if ( !strainControl.contains(i) ) { stressControl.at(j++) = i; @@ -153,44 +148,60 @@ StructuralMaterial :: giveRealStressVector_StressControl(FloatArray &answer, Gau // Initial guess; vE = status->giveStrainVector(); for ( int i = 1; i <= strainControl.giveSize(); ++i ) { - vE.at( strainControl.at(i) ) = reducedStrain.at(i); + vE.at(strainControl.at(i) ) = reducedStrain.at(i); } // Iterate to find full vE. - for ( int k = 0; k < 10; k++ ) { // Allow for a generous 100 iterations. - this->giveRealStressVector_3d(vS, gp, vE, tStep); + FloatArray answer; + int SCManrSteps = 10; + FloatMatrix reducedTangentInverse; + for ( int k = 0; k < SCMaxiter; k++ ) { // Allow for a generous 100000 iterations. + vS = this->giveRealStressVector_3d(vE, gp, tStep); // For debugging the iterations: //vE.printYourself("vE"); //vS.printYourself("vS"); reducedvS.beSubArrayOf(vS, stressControl); + //printf("%3d: %e\n", k, reducedvS.computeNorm()); // Pick out the (response) stresses for the controlled strains answer.beSubArrayOf(vS, strainControl); - if ( reducedvS.computeNorm() <= 1e0 && k >= 5 ) { // Absolute tolerance right now (with at least one iteration) + if ( ( reducedvS.computeNorm() <= this->SCRelTol * vS.computeNorm() && k >= 1 ) || ( reducedvS.computeNorm() < this->SCAbsTol ) ) { // Absolute tolerance right now (with at least one iteration) ///@todo We need a relative tolerance here! /// A relative tolerance like this could work, but if a really small increment is performed it won't work /// (it will be limited by machine precision) - //if ( reducedvS.computeNorm() <= 1e-6 * answer.computeNorm() ) { - return; + //if ( reducedvS.computeNorm() <= 1e-6 * answer.computeNorm() ) { + return answer; } - this->give3dMaterialStiffnessMatrix(tangent, TangentStiffness, gp, tStep); - reducedTangent.beSubMatrixOf(tangent, stressControl, stressControl); - reducedTangent.solveForRhs(reducedvS, increment_vE); + if ( ( k == 0 ) || ( ( ( this->SCStiffMode == TangentStiffness ) || ( this->SCStiffMode == SecantStiffness ) ) && ( k % SCManrSteps == 0 ) ) ) { + tangent = this->give3dMaterialStiffnessMatrix(this->SCStiffMode, gp, tStep); + reducedTangent.beSubMatrixOf(tangent, stressControl, stressControl); + if ( reducedTangentInverse.beInverseOf(reducedTangent) == false ) { + // in case of singularity revert to safe elastic stiffness + tangent = this->give3dMaterialStiffnessMatrix(ElasticStiffness, gp, tStep); + reducedTangent.beSubMatrixOf(tangent, stressControl, stressControl); + reducedTangentInverse.beInverseOf(reducedTangent); + } + } + //reducedTangent.printYourself(); + //reducedTangent.solveForRhs(reducedvS, increment_vE); + increment_vE.beProductOf(reducedTangentInverse, reducedvS); increment_vE.negated(); vE.assemble(increment_vE, stressControl); + //vE.printYourself("vE"); } - OOFEM_WARNING("Iteration did not converge"); - answer.clear(); + OOFEM_ERROR("Iteration did not converge after 100000 iterations\nS.norm=%e, err=%e, relErr=%e", vS.computeNorm(), reducedvS.computeNorm(), reducedvS.computeNorm() / vS.computeNorm() ); + + return FloatArray(); } -void -StructuralMaterial :: giveRealStressVector_ShellStressControl(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, const IntArray &strainControl, TimeStep *tStep) +FloatArray +StructuralMaterial::giveRealStressVector_ShellStressControl(const FloatArray &strain, const IntArray &strainControl, GaussPoint *gp, TimeStep *tStep) const // calculates stress vector (6 components) with assumption of sigma_z = 0 // used by MITC4Shell { - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); IntArray stressControl; FloatArray vE, increment_vE, vS, reducedvS; @@ -198,7 +209,7 @@ StructuralMaterial :: giveRealStressVector_ShellStressControl(FloatArray &answer // Iterate to find full vE. // Compute the negated the array of control since we need stressControl as well; - stressControl.resize( 6 - strainControl.giveSize() ); + stressControl.resize(6 - strainControl.giveSize() ); for ( int i = 1, j = 1; i <= 6; i++ ) { if ( !strainControl.contains(i) ) { stressControl.at(j++) = i; @@ -212,154 +223,138 @@ StructuralMaterial :: giveRealStressVector_ShellStressControl(FloatArray &answer // step n: vE = {., ., sum(ve(n)), ., ., .} // Iterate to find full vE. - for ( int k = 0; k < 100; k++ ) { // Allow for a generous 100 iterations. - this->giveRealStressVector_3d(answer, gp, vE, tStep); + //vE.printYourself("vE"); + FloatArray answer; + for ( int k = 0; k < SCMaxiter; k++ ) { // Allow for a generous 100 iterations. + answer = this->giveRealStressVector_3d(vE, gp, tStep); // step 0: answer = full stress vector // step n: answer = {., ., ->0, ., ., .} reducedvS.beSubArrayOf(answer, stressControl); - if ( reducedvS.computeNorm() < 1e-6 ) { - return; + if ( ( reducedvS.computeNorm() <= this->SCRelTol * answer.computeNorm() && k >= 1 ) || ( reducedvS.computeNorm() < this->SCAbsTol ) ) { // Absolute tolerance right now (with at least one iteration) + return answer; } - - this->give3dMaterialStiffnessMatrix(tangent, TangentStiffness, gp, tStep); + //reducedvS.printYourself("Vs"); + tangent = this->give3dMaterialStiffnessMatrix(this->SCStiffMode, gp, tStep); reducedTangent.beSubMatrixOf(tangent, stressControl, stressControl); + //reducedTangent.printYourself("d"); reducedTangent.solveForRhs(reducedvS, increment_vE); increment_vE.negated(); + //increment_vE.printYourself("iVe"); vE.assemble(increment_vE, stressControl); + //vE.printYourself("vE"); } OOFEM_WARNING("Iteration did not converge"); - answer.clear(); + return FloatArray(); } -void -StructuralMaterial :: giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF< 3 > +StructuralMaterial::giveRealStressVector_PlaneStress(const FloatArrayF< 3 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { IntArray strainControl; - StructuralMaterial :: giveVoigtSymVectorMask(strainControl, _PlaneStress); - this->giveRealStressVector_StressControl(answer, gp, reducedStrain, strainControl, tStep); + StructuralMaterial::giveVoigtSymVectorMask(strainControl, _PlaneStress); + return this->giveRealStressVector_StressControl(reducedStrain, strainControl, gp, tStep); } -void -StructuralMaterial :: giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF< 1 > +StructuralMaterial::giveRealStressVector_1d(const FloatArrayF< 1 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { IntArray strainControl; - StructuralMaterial :: giveVoigtSymVectorMask(strainControl, _1dMat); - this->giveRealStressVector_StressControl(answer, gp, reducedStrain, strainControl, tStep); + StructuralMaterial::giveVoigtSymVectorMask(strainControl, _1dMat); + return this->giveRealStressVector_StressControl(reducedStrain, strainControl, gp, tStep); } -void -StructuralMaterial :: giveRealStressVector_2dBeamLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF< 2 > +StructuralMaterial::giveRealStressVector_2dBeamLayer(const FloatArrayF< 2 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { IntArray strainControl; - StructuralMaterial :: giveVoigtSymVectorMask(strainControl, _2dBeamLayer); - this->giveRealStressVector_StressControl(answer, gp, reducedStrain, strainControl, tStep); + StructuralMaterial::giveVoigtSymVectorMask(strainControl, _2dBeamLayer); + return this->giveRealStressVector_StressControl(reducedStrain, strainControl, gp, tStep); } -void -StructuralMaterial :: giveRealStressVector_PlateLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF< 5 > +StructuralMaterial::giveRealStressVector_PlateLayer(const FloatArrayF< 5 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { IntArray strainControl; - StructuralMaterial :: giveVoigtSymVectorMask(strainControl, _PlateLayer); - this->giveRealStressVector_StressControl(answer, gp, reducedStrain, strainControl, tStep); + StructuralMaterial::giveVoigtSymVectorMask(strainControl, _PlateLayer); + return this->giveRealStressVector_StressControl(reducedStrain, strainControl, gp, tStep); } -void -StructuralMaterial :: giveRealStressVector_Fiber(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF< 3 > +StructuralMaterial::giveRealStressVector_Fiber(const FloatArrayF< 3 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { IntArray strainControl; - StructuralMaterial :: giveVoigtSymVectorMask(strainControl, _Fiber); - this->giveRealStressVector_StressControl(answer, gp, reducedStrain, strainControl, tStep); -} - - -void -StructuralMaterial :: giveRealStressVector_Lattice2d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) -{ - OOFEM_ERROR("2dLattice mode not supported"); + StructuralMaterial::giveVoigtSymVectorMask(strainControl, _Fiber); + return this->giveRealStressVector_StressControl(reducedStrain, strainControl, gp, tStep); } -void -StructuralMaterial :: giveRealStressVector_Lattice3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) -{ - OOFEM_ERROR("3dLattice mode not supported"); -} - -void -StructuralMaterial :: giveRealStressVector_2dPlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF< 3 > +StructuralMaterial::giveRealStressVector_2dPlateSubSoil(const FloatArrayF< 3 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("2dPlateSubSoil mode not supported"); } -void -StructuralMaterial :: giveRealStressVector_3dBeamSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep) +FloatArrayF< 6 > +StructuralMaterial::giveRealStressVector_3dBeamSubSoil(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("3dBeamSubSoil mode not supported"); } -void -StructuralMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &vF, TimeStep *tStep) +FloatArrayF< 9 > +StructuralMaterial::giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const { // Default implementation used if this method is not overloaded by the particular material model. // 1) Compute Green-Lagrange strain and call standard method for small strains. // 2) Treat stress as second Piola-Kirchhoff stress and convert to first Piola-Kirchhoff stress. // 3) Set state variables F, P - FloatArray vE, vS; - FloatMatrix F, E; - F.beMatrixForm(vF); - E.beTProductOf(F, F); - E.at(1, 1) -= 1.0; - E.at(2, 2) -= 1.0; - E.at(3, 3) -= 1.0; - E.times(0.5); - vE.beSymVectorFormOfStrain(E); // 6 - - ///@todo Have this function: - this->giveRealStressVector_3d(vS, gp, vE, tStep); - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto F = from_voigt_form(vF); + auto E = 0.5 * ( Tdot(F, F) - eye< 3 >() ); + auto vE = to_voigt_strain(E); + auto vS = this->giveRealStressVector_3d(vE, gp, tStep); // Compute first PK stress from second PK stress - FloatMatrix P, S; - S.beMatrixForm(vS); - P.beProductOf(F, S); - answer.beVectorForm(P); - - status->letTempPVectorBe(answer); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto S = from_voigt_stress(vS); + auto P = dot(F, S); + auto vP = to_voigt_form(P); + status->letTempPVectorBe(vP); status->letTempFVectorBe(vF); + + return vP; } -void -StructuralMaterial :: giveFirstPKStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep) +FloatArrayF< 5 > +StructuralMaterial::giveFirstPKStressVector_PlaneStrain(const FloatArrayF< 5 > &vF, GaussPoint *gp, TimeStep *tStep) const { - FloatArray vF, vP; - StructuralMaterial :: giveFullVectorFormF(vF, reducedvF, _PlaneStrain); - this->giveFirstPKStressVector_3d(vP, gp, vF, tStep); - StructuralMaterial :: giveReducedVectorForm(answer, vP, _PlaneStrain); + auto vP = this->giveFirstPKStressVector_3d(assemble< 9 >(vF, { 0, 1, 2, 5, 8 }), gp, tStep); + return vP [ { 0, 1, 2, 5, 8 } ]; } -void -StructuralMaterial :: giveFirstPKStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep) + + + +FloatArray +StructuralMaterial::giveFirstPKStressVector_StressControl(const FloatArray &reducedvF, const IntArray &F_control, GaussPoint *gp, TimeStep *tStep) const { - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - IntArray F_control, P_control; // Determines which components are controlled by F and P resp. - FloatArray vF, increment_vF, vP, vP_control; - FloatMatrix tangent, tangent_Pcontrol; + IntArray P_control; + FloatArray vF, increment_vF, vP, reducedvP; + FloatMatrix tangent, reducedTangent; // Iterate to find full vF. - StructuralMaterial :: giveVoigtVectorMask(F_control, _PlaneStress); - // Compute the negated the array of control since we need P_control as well; + // Compute the negated the array of control since we need stressControl as well; P_control.resize( 9 - F_control.giveSize() ); for ( int i = 1, j = 1; i <= 9; i++ ) { if ( !F_control.contains(i) ) { @@ -374,270 +369,244 @@ StructuralMaterial :: giveFirstPKStressVector_PlaneStress(FloatArray &answer, Ga } // Iterate to find full vF. - for ( int k = 0; k < 100; k++ ) { // Allow for a generous 100 iterations. - this->giveFirstPKStressVector_3d(vP, gp, vF, tStep); - vP_control.beSubArrayOf(vP, P_control); - if ( vP_control.computeNorm() < 1e-6 ) { ///@todo We need a tolerance here! - StructuralMaterial :: giveReducedVectorForm(answer, vP, _1dMat); - return; + FloatArray answer; + for ( int k = 0; k < SCMaxiter; k++ ) { // Allow for a generous 100 iterations. + vP = this->giveFirstPKStressVector_3d(vF, gp, tStep); + reducedvP.beSubArrayOf(vP, P_control); + // Pick out the (response) stresses for the controlled strains + answer.beSubArrayOf(vP, F_control); + if ( reducedvP.computeNorm() <= 1e-6 * answer.computeNorm() && k >= 1 ) { + return answer; } - this->give3dMaterialStiffnessMatrix_dPdF(tangent, TangentStiffness, gp, tStep); - tangent_Pcontrol.beSubMatrixOf(tangent, P_control, P_control); - tangent_Pcontrol.solveForRhs(vP_control, increment_vF); + tangent = this->give3dMaterialStiffnessMatrix_dPdF(TangentStiffness, gp, tStep); + reducedTangent.beSubMatrixOf(tangent, P_control, P_control); + reducedTangent.solveForRhs(reducedvP, increment_vF); + increment_vF.negated(); vF.assemble(increment_vF, P_control); } - OOFEM_WARNING("Iteration did not converge"); - answer.clear(); + OOFEM_ERROR("Iteration did not converge"); + return FloatArray(); } -void -StructuralMaterial :: giveFirstPKStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedvF, TimeStep *tStep) -{ - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - IntArray P_control; // Determines which components are controlled by P resp. - FloatArray vF, increment_vF, vP, vP_control; - FloatMatrix tangent, tangent_Pcontrol; - // Compute the negated the array of control since we need P_control as well; - P_control.resize(8); - for ( int i = 1; i <= 8; i++ ) { - P_control.at(i) = i + 1; - } - // Initial guess; - vF = status->giveFVector(); - vF.at(1) = reducedvF.at(1); - // Iterate to find full vF. - for ( int k = 0; k < 100; k++ ) { // Allow for a generous 100 iterations. - this->giveFirstPKStressVector_3d(vP, gp, vF, tStep); - vP_control.beSubArrayOf(vP, P_control); - if ( vP_control.computeNorm() < 1e-6 ) { ///@todo We need a tolerance here! - StructuralMaterial :: giveReducedVectorForm(answer, vP, _1dMat); - return; - } +FloatArrayF< 4 > +StructuralMaterial::giveFirstPKStressVector_PlaneStress(const FloatArrayF< 4 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const +{ + IntArray FControl; + StructuralMaterial::giveVoigtVectorMask(FControl, _PlaneStress); + return this->giveRealStressVector_StressControl(reducedvF, FControl, gp, tStep); +} - this->give3dMaterialStiffnessMatrix_dPdF(tangent, TangentStiffness, gp, tStep); - tangent_Pcontrol.beSubMatrixOf(tangent, P_control, P_control); - tangent_Pcontrol.solveForRhs(vP_control, increment_vF); - vF.assemble(increment_vF, P_control); - } - OOFEM_WARNING("Iteration did not converge"); - answer.clear(); +FloatArrayF< 1 > +StructuralMaterial::giveFirstPKStressVector_1d(const FloatArrayF< 1 > &reducedvF, GaussPoint *gp, TimeStep *tStep) const +{ + IntArray FControl; + StructuralMaterial::giveVoigtVectorMask(FControl, _PlaneStress); + return this->giveRealStressVector_StressControl(reducedvF, FControl, gp, tStep); } -void -StructuralMaterial :: convert_dSdE_2_dPdF(FloatMatrix &answer, const FloatMatrix &C, const FloatArray &S, const FloatArray &F, MaterialMode matMode) +FloatMatrixF< 9, 9 > +StructuralMaterial::convert_dSdE_2_dPdF_3D(const FloatMatrixF< 6, 6 > &C, const FloatArrayF< 6 > &S, const FloatArrayF< 9 > &F) { // Converts the reduced dSdE-stiffness to reduced dPdF-sitiffness for different MaterialModes // Performs the following operation dPdF = I_ik * S_jl + F_im F_kn C_mjnl, // See for example: G.A. Holzapfel, Nonlinear Solid Mechanics: A Continuum Approach for // Engineering, 2000, ISBN-10: 0471823198. - if ( matMode == _3dMat ) { - //Save terms associated with H = [du/dx, dv/dy, dw/dz, dv/dz, du/dz, du/dy, dw/dy, dw/dx, dv/dx] + //Save terms associated with H = [du/dx, dv/dy, dw/dz, dv/dz, du/dz, du/dy, dw/dy, dw/dx, dv/dx] + FloatMatrixF< 9, 9 >answer; #if 1 - - answer.resize(9, 9); - answer(0, 0) = F(0) * C(0, 0) * F(0) + F(0) * C(0, 5) * F(5) + F(0) * C(0, 4) * F(4) + F(5) * C(5, 0) * F(0) + F(5) * C(5, 5) * F(5) + F(5) * C(5, 4) * F(4) + F(4) * C(4, 0) * F(0) + F(4) * C(4, 5) * F(5) + F(4) * C(4, 4) * F(4) + S(0); - answer(0, 1) = F(0) * C(0, 5) * F(8) + F(0) * C(0, 1) * F(1) + F(0) * C(0, 3) * F(3) + F(5) * C(5, 5) * F(8) + F(5) * C(5, 1) * F(1) + F(5) * C(5, 3) * F(3) + F(4) * C(4, 5) * F(8) + F(4) * C(4, 1) * F(1) + F(4) * C(4, 3) * F(3) + 0.0; - answer(0, 2) = F(0) * C(0, 4) * F(7) + F(0) * C(0, 3) * F(6) + F(0) * C(0, 2) * F(2) + F(5) * C(5, 4) * F(7) + F(5) * C(5, 3) * F(6) + F(5) * C(5, 2) * F(2) + F(4) * C(4, 4) * F(7) + F(4) * C(4, 3) * F(6) + F(4) * C(4, 2) * F(2) + 0.0; - answer(0, 3) = F(0) * C(0, 4) * F(8) + F(0) * C(0, 3) * F(1) + F(0) * C(0, 2) * F(3) + F(5) * C(5, 4) * F(8) + F(5) * C(5, 3) * F(1) + F(5) * C(5, 2) * F(3) + F(4) * C(4, 4) * F(8) + F(4) * C(4, 3) * F(1) + F(4) * C(4, 2) * F(3) + 0.0; - answer(0, 4) = F(0) * C(0, 4) * F(0) + F(0) * C(0, 3) * F(5) + F(0) * C(0, 2) * F(4) + F(5) * C(5, 4) * F(0) + F(5) * C(5, 3) * F(5) + F(5) * C(5, 2) * F(4) + F(4) * C(4, 4) * F(0) + F(4) * C(4, 3) * F(5) + F(4) * C(4, 2) * F(4) + S(4); - answer(0, 5) = F(0) * C(0, 5) * F(0) + F(0) * C(0, 1) * F(5) + F(0) * C(0, 3) * F(4) + F(5) * C(5, 5) * F(0) + F(5) * C(5, 1) * F(5) + F(5) * C(5, 3) * F(4) + F(4) * C(4, 5) * F(0) + F(4) * C(4, 1) * F(5) + F(4) * C(4, 3) * F(4) + S(5); - answer(0, 6) = F(0) * C(0, 5) * F(7) + F(0) * C(0, 1) * F(6) + F(0) * C(0, 3) * F(2) + F(5) * C(5, 5) * F(7) + F(5) * C(5, 1) * F(6) + F(5) * C(5, 3) * F(2) + F(4) * C(4, 5) * F(7) + F(4) * C(4, 1) * F(6) + F(4) * C(4, 3) * F(2) + 0.0; - answer(0, 7) = F(0) * C(0, 0) * F(7) + F(0) * C(0, 5) * F(6) + F(0) * C(0, 4) * F(2) + F(5) * C(5, 0) * F(7) + F(5) * C(5, 5) * F(6) + F(5) * C(5, 4) * F(2) + F(4) * C(4, 0) * F(7) + F(4) * C(4, 5) * F(6) + F(4) * C(4, 4) * F(2) + 0.0; - answer(0, 8) = F(0) * C(0, 0) * F(8) + F(0) * C(0, 5) * F(1) + F(0) * C(0, 4) * F(3) + F(5) * C(5, 0) * F(8) + F(5) * C(5, 5) * F(1) + F(5) * C(5, 4) * F(3) + F(4) * C(4, 0) * F(8) + F(4) * C(4, 5) * F(1) + F(4) * C(4, 4) * F(3) + 0.0; - answer(1, 0) = F(8) * C(5, 0) * F(0) + F(8) * C(5, 5) * F(5) + F(8) * C(5, 4) * F(4) + F(1) * C(1, 0) * F(0) + F(1) * C(1, 5) * F(5) + F(1) * C(1, 4) * F(4) + F(3) * C(3, 0) * F(0) + F(3) * C(3, 5) * F(5) + F(3) * C(3, 4) * F(4) + 0.0; - answer(1, 1) = F(8) * C(5, 5) * F(8) + F(8) * C(5, 1) * F(1) + F(8) * C(5, 3) * F(3) + F(1) * C(1, 5) * F(8) + F(1) * C(1, 1) * F(1) + F(1) * C(1, 3) * F(3) + F(3) * C(3, 5) * F(8) + F(3) * C(3, 1) * F(1) + F(3) * C(3, 3) * F(3) + S(1); - answer(1, 2) = F(8) * C(5, 4) * F(7) + F(8) * C(5, 3) * F(6) + F(8) * C(5, 2) * F(2) + F(1) * C(1, 4) * F(7) + F(1) * C(1, 3) * F(6) + F(1) * C(1, 2) * F(2) + F(3) * C(3, 4) * F(7) + F(3) * C(3, 3) * F(6) + F(3) * C(3, 2) * F(2) + 0.0; - answer(1, 3) = F(8) * C(5, 4) * F(8) + F(8) * C(5, 3) * F(1) + F(8) * C(5, 2) * F(3) + F(1) * C(1, 4) * F(8) + F(1) * C(1, 3) * F(1) + F(1) * C(1, 2) * F(3) + F(3) * C(3, 4) * F(8) + F(3) * C(3, 3) * F(1) + F(3) * C(3, 2) * F(3) + S(3); - answer(1, 4) = F(8) * C(5, 4) * F(0) + F(8) * C(5, 3) * F(5) + F(8) * C(5, 2) * F(4) + F(1) * C(1, 4) * F(0) + F(1) * C(1, 3) * F(5) + F(1) * C(1, 2) * F(4) + F(3) * C(3, 4) * F(0) + F(3) * C(3, 3) * F(5) + F(3) * C(3, 2) * F(4) + 0.0; - answer(1, 5) = F(8) * C(5, 5) * F(0) + F(8) * C(5, 1) * F(5) + F(8) * C(5, 3) * F(4) + F(1) * C(1, 5) * F(0) + F(1) * C(1, 1) * F(5) + F(1) * C(1, 3) * F(4) + F(3) * C(3, 5) * F(0) + F(3) * C(3, 1) * F(5) + F(3) * C(3, 3) * F(4) + 0.0; - answer(1, 6) = F(8) * C(5, 5) * F(7) + F(8) * C(5, 1) * F(6) + F(8) * C(5, 3) * F(2) + F(1) * C(1, 5) * F(7) + F(1) * C(1, 1) * F(6) + F(1) * C(1, 3) * F(2) + F(3) * C(3, 5) * F(7) + F(3) * C(3, 1) * F(6) + F(3) * C(3, 3) * F(2) + 0.0; - answer(1, 7) = F(8) * C(5, 0) * F(7) + F(8) * C(5, 5) * F(6) + F(8) * C(5, 4) * F(2) + F(1) * C(1, 0) * F(7) + F(1) * C(1, 5) * F(6) + F(1) * C(1, 4) * F(2) + F(3) * C(3, 0) * F(7) + F(3) * C(3, 5) * F(6) + F(3) * C(3, 4) * F(2) + 0.0; - answer(1, 8) = F(8) * C(5, 0) * F(8) + F(8) * C(5, 5) * F(1) + F(8) * C(5, 4) * F(3) + F(1) * C(1, 0) * F(8) + F(1) * C(1, 5) * F(1) + F(1) * C(1, 4) * F(3) + F(3) * C(3, 0) * F(8) + F(3) * C(3, 5) * F(1) + F(3) * C(3, 4) * F(3) + S(5); - answer(2, 0) = F(7) * C(4, 0) * F(0) + F(7) * C(4, 5) * F(5) + F(7) * C(4, 4) * F(4) + F(6) * C(3, 0) * F(0) + F(6) * C(3, 5) * F(5) + F(6) * C(3, 4) * F(4) + F(2) * C(2, 0) * F(0) + F(2) * C(2, 5) * F(5) + F(2) * C(2, 4) * F(4) + 0.0; - answer(2, 1) = F(7) * C(4, 5) * F(8) + F(7) * C(4, 1) * F(1) + F(7) * C(4, 3) * F(3) + F(6) * C(3, 5) * F(8) + F(6) * C(3, 1) * F(1) + F(6) * C(3, 3) * F(3) + F(2) * C(2, 5) * F(8) + F(2) * C(2, 1) * F(1) + F(2) * C(2, 3) * F(3) + 0.0; - answer(2, 2) = F(7) * C(4, 4) * F(7) + F(7) * C(4, 3) * F(6) + F(7) * C(4, 2) * F(2) + F(6) * C(3, 4) * F(7) + F(6) * C(3, 3) * F(6) + F(6) * C(3, 2) * F(2) + F(2) * C(2, 4) * F(7) + F(2) * C(2, 3) * F(6) + F(2) * C(2, 2) * F(2) + S(2); - answer(2, 3) = F(7) * C(4, 4) * F(8) + F(7) * C(4, 3) * F(1) + F(7) * C(4, 2) * F(3) + F(6) * C(3, 4) * F(8) + F(6) * C(3, 3) * F(1) + F(6) * C(3, 2) * F(3) + F(2) * C(2, 4) * F(8) + F(2) * C(2, 3) * F(1) + F(2) * C(2, 2) * F(3) + 0.0; - answer(2, 4) = F(7) * C(4, 4) * F(0) + F(7) * C(4, 3) * F(5) + F(7) * C(4, 2) * F(4) + F(6) * C(3, 4) * F(0) + F(6) * C(3, 3) * F(5) + F(6) * C(3, 2) * F(4) + F(2) * C(2, 4) * F(0) + F(2) * C(2, 3) * F(5) + F(2) * C(2, 2) * F(4) + 0.0; - answer(2, 5) = F(7) * C(4, 5) * F(0) + F(7) * C(4, 1) * F(5) + F(7) * C(4, 3) * F(4) + F(6) * C(3, 5) * F(0) + F(6) * C(3, 1) * F(5) + F(6) * C(3, 3) * F(4) + F(2) * C(2, 5) * F(0) + F(2) * C(2, 1) * F(5) + F(2) * C(2, 3) * F(4) + 0.0; - answer(2, 6) = F(7) * C(4, 5) * F(7) + F(7) * C(4, 1) * F(6) + F(7) * C(4, 3) * F(2) + F(6) * C(3, 5) * F(7) + F(6) * C(3, 1) * F(6) + F(6) * C(3, 3) * F(2) + F(2) * C(2, 5) * F(7) + F(2) * C(2, 1) * F(6) + F(2) * C(2, 3) * F(2) + S(3); - answer(2, 7) = F(7) * C(4, 0) * F(7) + F(7) * C(4, 5) * F(6) + F(7) * C(4, 4) * F(2) + F(6) * C(3, 0) * F(7) + F(6) * C(3, 5) * F(6) + F(6) * C(3, 4) * F(2) + F(2) * C(2, 0) * F(7) + F(2) * C(2, 5) * F(6) + F(2) * C(2, 4) * F(2) + S(4); - answer(2, 8) = F(7) * C(4, 0) * F(8) + F(7) * C(4, 5) * F(1) + F(7) * C(4, 4) * F(3) + F(6) * C(3, 0) * F(8) + F(6) * C(3, 5) * F(1) + F(6) * C(3, 4) * F(3) + F(2) * C(2, 0) * F(8) + F(2) * C(2, 5) * F(1) + F(2) * C(2, 4) * F(3) + 0.0; - answer(3, 0) = F(8) * C(4, 0) * F(0) + F(8) * C(4, 5) * F(5) + F(8) * C(4, 4) * F(4) + F(1) * C(3, 0) * F(0) + F(1) * C(3, 5) * F(5) + F(1) * C(3, 4) * F(4) + F(3) * C(2, 0) * F(0) + F(3) * C(2, 5) * F(5) + F(3) * C(2, 4) * F(4) + 0.0; - answer(3, 1) = F(8) * C(4, 5) * F(8) + F(8) * C(4, 1) * F(1) + F(8) * C(4, 3) * F(3) + F(1) * C(3, 5) * F(8) + F(1) * C(3, 1) * F(1) + F(1) * C(3, 3) * F(3) + F(3) * C(2, 5) * F(8) + F(3) * C(2, 1) * F(1) + F(3) * C(2, 3) * F(3) + S(3); - answer(3, 2) = F(8) * C(4, 4) * F(7) + F(8) * C(4, 3) * F(6) + F(8) * C(4, 2) * F(2) + F(1) * C(3, 4) * F(7) + F(1) * C(3, 3) * F(6) + F(1) * C(3, 2) * F(2) + F(3) * C(2, 4) * F(7) + F(3) * C(2, 3) * F(6) + F(3) * C(2, 2) * F(2) + 0.0; - answer(3, 3) = F(8) * C(4, 4) * F(8) + F(8) * C(4, 3) * F(1) + F(8) * C(4, 2) * F(3) + F(1) * C(3, 4) * F(8) + F(1) * C(3, 3) * F(1) + F(1) * C(3, 2) * F(3) + F(3) * C(2, 4) * F(8) + F(3) * C(2, 3) * F(1) + F(3) * C(2, 2) * F(3) + S(2); - answer(3, 4) = F(8) * C(4, 4) * F(0) + F(8) * C(4, 3) * F(5) + F(8) * C(4, 2) * F(4) + F(1) * C(3, 4) * F(0) + F(1) * C(3, 3) * F(5) + F(1) * C(3, 2) * F(4) + F(3) * C(2, 4) * F(0) + F(3) * C(2, 3) * F(5) + F(3) * C(2, 2) * F(4) + 0.0; - answer(3, 5) = F(8) * C(4, 5) * F(0) + F(8) * C(4, 1) * F(5) + F(8) * C(4, 3) * F(4) + F(1) * C(3, 5) * F(0) + F(1) * C(3, 1) * F(5) + F(1) * C(3, 3) * F(4) + F(3) * C(2, 5) * F(0) + F(3) * C(2, 1) * F(5) + F(3) * C(2, 3) * F(4) + 0.0; - answer(3, 6) = F(8) * C(4, 5) * F(7) + F(8) * C(4, 1) * F(6) + F(8) * C(4, 3) * F(2) + F(1) * C(3, 5) * F(7) + F(1) * C(3, 1) * F(6) + F(1) * C(3, 3) * F(2) + F(3) * C(2, 5) * F(7) + F(3) * C(2, 1) * F(6) + F(3) * C(2, 3) * F(2) + 0.0; - answer(3, 7) = F(8) * C(4, 0) * F(7) + F(8) * C(4, 5) * F(6) + F(8) * C(4, 4) * F(2) + F(1) * C(3, 0) * F(7) + F(1) * C(3, 5) * F(6) + F(1) * C(3, 4) * F(2) + F(3) * C(2, 0) * F(7) + F(3) * C(2, 5) * F(6) + F(3) * C(2, 4) * F(2) + 0.0; - answer(3, 8) = F(8) * C(4, 0) * F(8) + F(8) * C(4, 5) * F(1) + F(8) * C(4, 4) * F(3) + F(1) * C(3, 0) * F(8) + F(1) * C(3, 5) * F(1) + F(1) * C(3, 4) * F(3) + F(3) * C(2, 0) * F(8) + F(3) * C(2, 5) * F(1) + F(3) * C(2, 4) * F(3) + S(4); - answer(4, 0) = F(0) * C(4, 0) * F(0) + F(0) * C(4, 5) * F(5) + F(0) * C(4, 4) * F(4) + F(5) * C(3, 0) * F(0) + F(5) * C(3, 5) * F(5) + F(5) * C(3, 4) * F(4) + F(4) * C(2, 0) * F(0) + F(4) * C(2, 5) * F(5) + F(4) * C(2, 4) * F(4) + S(4); - answer(4, 1) = F(0) * C(4, 5) * F(8) + F(0) * C(4, 1) * F(1) + F(0) * C(4, 3) * F(3) + F(5) * C(3, 5) * F(8) + F(5) * C(3, 1) * F(1) + F(5) * C(3, 3) * F(3) + F(4) * C(2, 5) * F(8) + F(4) * C(2, 1) * F(1) + F(4) * C(2, 3) * F(3) + 0.0; - answer(4, 2) = F(0) * C(4, 4) * F(7) + F(0) * C(4, 3) * F(6) + F(0) * C(4, 2) * F(2) + F(5) * C(3, 4) * F(7) + F(5) * C(3, 3) * F(6) + F(5) * C(3, 2) * F(2) + F(4) * C(2, 4) * F(7) + F(4) * C(2, 3) * F(6) + F(4) * C(2, 2) * F(2) + 0.0; - answer(4, 3) = F(0) * C(4, 4) * F(8) + F(0) * C(4, 3) * F(1) + F(0) * C(4, 2) * F(3) + F(5) * C(3, 4) * F(8) + F(5) * C(3, 3) * F(1) + F(5) * C(3, 2) * F(3) + F(4) * C(2, 4) * F(8) + F(4) * C(2, 3) * F(1) + F(4) * C(2, 2) * F(3) + 0.0; - answer(4, 4) = F(0) * C(4, 4) * F(0) + F(0) * C(4, 3) * F(5) + F(0) * C(4, 2) * F(4) + F(5) * C(3, 4) * F(0) + F(5) * C(3, 3) * F(5) + F(5) * C(3, 2) * F(4) + F(4) * C(2, 4) * F(0) + F(4) * C(2, 3) * F(5) + F(4) * C(2, 2) * F(4) + S(2); - answer(4, 5) = F(0) * C(4, 5) * F(0) + F(0) * C(4, 1) * F(5) + F(0) * C(4, 3) * F(4) + F(5) * C(3, 5) * F(0) + F(5) * C(3, 1) * F(5) + F(5) * C(3, 3) * F(4) + F(4) * C(2, 5) * F(0) + F(4) * C(2, 1) * F(5) + F(4) * C(2, 3) * F(4) + S(3); - answer(4, 6) = F(0) * C(4, 5) * F(7) + F(0) * C(4, 1) * F(6) + F(0) * C(4, 3) * F(2) + F(5) * C(3, 5) * F(7) + F(5) * C(3, 1) * F(6) + F(5) * C(3, 3) * F(2) + F(4) * C(2, 5) * F(7) + F(4) * C(2, 1) * F(6) + F(4) * C(2, 3) * F(2) + 0.0; - answer(4, 7) = F(0) * C(4, 0) * F(7) + F(0) * C(4, 5) * F(6) + F(0) * C(4, 4) * F(2) + F(5) * C(3, 0) * F(7) + F(5) * C(3, 5) * F(6) + F(5) * C(3, 4) * F(2) + F(4) * C(2, 0) * F(7) + F(4) * C(2, 5) * F(6) + F(4) * C(2, 4) * F(2) + 0.0; - answer(4, 8) = F(0) * C(4, 0) * F(8) + F(0) * C(4, 5) * F(1) + F(0) * C(4, 4) * F(3) + F(5) * C(3, 0) * F(8) + F(5) * C(3, 5) * F(1) + F(5) * C(3, 4) * F(3) + F(4) * C(2, 0) * F(8) + F(4) * C(2, 5) * F(1) + F(4) * C(2, 4) * F(3) + 0.0; - answer(5, 0) = F(0) * C(5, 0) * F(0) + F(0) * C(5, 5) * F(5) + F(0) * C(5, 4) * F(4) + F(5) * C(1, 0) * F(0) + F(5) * C(1, 5) * F(5) + F(5) * C(1, 4) * F(4) + F(4) * C(3, 0) * F(0) + F(4) * C(3, 5) * F(5) + F(4) * C(3, 4) * F(4) + S(5); - answer(5, 1) = F(0) * C(5, 5) * F(8) + F(0) * C(5, 1) * F(1) + F(0) * C(5, 3) * F(3) + F(5) * C(1, 5) * F(8) + F(5) * C(1, 1) * F(1) + F(5) * C(1, 3) * F(3) + F(4) * C(3, 5) * F(8) + F(4) * C(3, 1) * F(1) + F(4) * C(3, 3) * F(3) + 0.0; - answer(5, 2) = F(0) * C(5, 4) * F(7) + F(0) * C(5, 3) * F(6) + F(0) * C(5, 2) * F(2) + F(5) * C(1, 4) * F(7) + F(5) * C(1, 3) * F(6) + F(5) * C(1, 2) * F(2) + F(4) * C(3, 4) * F(7) + F(4) * C(3, 3) * F(6) + F(4) * C(3, 2) * F(2) + 0.0; - answer(5, 3) = F(0) * C(5, 4) * F(8) + F(0) * C(5, 3) * F(1) + F(0) * C(5, 2) * F(3) + F(5) * C(1, 4) * F(8) + F(5) * C(1, 3) * F(1) + F(5) * C(1, 2) * F(3) + F(4) * C(3, 4) * F(8) + F(4) * C(3, 3) * F(1) + F(4) * C(3, 2) * F(3) + 0.0; - answer(5, 4) = F(0) * C(5, 4) * F(0) + F(0) * C(5, 3) * F(5) + F(0) * C(5, 2) * F(4) + F(5) * C(1, 4) * F(0) + F(5) * C(1, 3) * F(5) + F(5) * C(1, 2) * F(4) + F(4) * C(3, 4) * F(0) + F(4) * C(3, 3) * F(5) + F(4) * C(3, 2) * F(4) + S(3); - answer(5, 5) = F(0) * C(5, 5) * F(0) + F(0) * C(5, 1) * F(5) + F(0) * C(5, 3) * F(4) + F(5) * C(1, 5) * F(0) + F(5) * C(1, 1) * F(5) + F(5) * C(1, 3) * F(4) + F(4) * C(3, 5) * F(0) + F(4) * C(3, 1) * F(5) + F(4) * C(3, 3) * F(4) + S(1); - answer(5, 6) = F(0) * C(5, 5) * F(7) + F(0) * C(5, 1) * F(6) + F(0) * C(5, 3) * F(2) + F(5) * C(1, 5) * F(7) + F(5) * C(1, 1) * F(6) + F(5) * C(1, 3) * F(2) + F(4) * C(3, 5) * F(7) + F(4) * C(3, 1) * F(6) + F(4) * C(3, 3) * F(2) + 0.0; - answer(5, 7) = F(0) * C(5, 0) * F(7) + F(0) * C(5, 5) * F(6) + F(0) * C(5, 4) * F(2) + F(5) * C(1, 0) * F(7) + F(5) * C(1, 5) * F(6) + F(5) * C(1, 4) * F(2) + F(4) * C(3, 0) * F(7) + F(4) * C(3, 5) * F(6) + F(4) * C(3, 4) * F(2) + 0.0; - answer(5, 8) = F(0) * C(5, 0) * F(8) + F(0) * C(5, 5) * F(1) + F(0) * C(5, 4) * F(3) + F(5) * C(1, 0) * F(8) + F(5) * C(1, 5) * F(1) + F(5) * C(1, 4) * F(3) + F(4) * C(3, 0) * F(8) + F(4) * C(3, 5) * F(1) + F(4) * C(3, 4) * F(3) + 0.0; - answer(6, 0) = F(7) * C(5, 0) * F(0) + F(7) * C(5, 5) * F(5) + F(7) * C(5, 4) * F(4) + F(6) * C(1, 0) * F(0) + F(6) * C(1, 5) * F(5) + F(6) * C(1, 4) * F(4) + F(2) * C(3, 0) * F(0) + F(2) * C(3, 5) * F(5) + F(2) * C(3, 4) * F(4) + 0.0; - answer(6, 1) = F(7) * C(5, 5) * F(8) + F(7) * C(5, 1) * F(1) + F(7) * C(5, 3) * F(3) + F(6) * C(1, 5) * F(8) + F(6) * C(1, 1) * F(1) + F(6) * C(1, 3) * F(3) + F(2) * C(3, 5) * F(8) + F(2) * C(3, 1) * F(1) + F(2) * C(3, 3) * F(3) + 0.0; - answer(6, 2) = F(7) * C(5, 4) * F(7) + F(7) * C(5, 3) * F(6) + F(7) * C(5, 2) * F(2) + F(6) * C(1, 4) * F(7) + F(6) * C(1, 3) * F(6) + F(6) * C(1, 2) * F(2) + F(2) * C(3, 4) * F(7) + F(2) * C(3, 3) * F(6) + F(2) * C(3, 2) * F(2) + S(3); - answer(6, 3) = F(7) * C(5, 4) * F(8) + F(7) * C(5, 3) * F(1) + F(7) * C(5, 2) * F(3) + F(6) * C(1, 4) * F(8) + F(6) * C(1, 3) * F(1) + F(6) * C(1, 2) * F(3) + F(2) * C(3, 4) * F(8) + F(2) * C(3, 3) * F(1) + F(2) * C(3, 2) * F(3) + 0.0; - answer(6, 4) = F(7) * C(5, 4) * F(0) + F(7) * C(5, 3) * F(5) + F(7) * C(5, 2) * F(4) + F(6) * C(1, 4) * F(0) + F(6) * C(1, 3) * F(5) + F(6) * C(1, 2) * F(4) + F(2) * C(3, 4) * F(0) + F(2) * C(3, 3) * F(5) + F(2) * C(3, 2) * F(4) + 0.0; - answer(6, 5) = F(7) * C(5, 5) * F(0) + F(7) * C(5, 1) * F(5) + F(7) * C(5, 3) * F(4) + F(6) * C(1, 5) * F(0) + F(6) * C(1, 1) * F(5) + F(6) * C(1, 3) * F(4) + F(2) * C(3, 5) * F(0) + F(2) * C(3, 1) * F(5) + F(2) * C(3, 3) * F(4) + 0.0; - answer(6, 6) = F(7) * C(5, 5) * F(7) + F(7) * C(5, 1) * F(6) + F(7) * C(5, 3) * F(2) + F(6) * C(1, 5) * F(7) + F(6) * C(1, 1) * F(6) + F(6) * C(1, 3) * F(2) + F(2) * C(3, 5) * F(7) + F(2) * C(3, 1) * F(6) + F(2) * C(3, 3) * F(2) + S(1); - answer(6, 7) = F(7) * C(5, 0) * F(7) + F(7) * C(5, 5) * F(6) + F(7) * C(5, 4) * F(2) + F(6) * C(1, 0) * F(7) + F(6) * C(1, 5) * F(6) + F(6) * C(1, 4) * F(2) + F(2) * C(3, 0) * F(7) + F(2) * C(3, 5) * F(6) + F(2) * C(3, 4) * F(2) + S(5); - answer(6, 8) = F(7) * C(5, 0) * F(8) + F(7) * C(5, 5) * F(1) + F(7) * C(5, 4) * F(3) + F(6) * C(1, 0) * F(8) + F(6) * C(1, 5) * F(1) + F(6) * C(1, 4) * F(3) + F(2) * C(3, 0) * F(8) + F(2) * C(3, 5) * F(1) + F(2) * C(3, 4) * F(3) + 0.0; - answer(7, 0) = F(7) * C(0, 0) * F(0) + F(7) * C(0, 5) * F(5) + F(7) * C(0, 4) * F(4) + F(6) * C(5, 0) * F(0) + F(6) * C(5, 5) * F(5) + F(6) * C(5, 4) * F(4) + F(2) * C(4, 0) * F(0) + F(2) * C(4, 5) * F(5) + F(2) * C(4, 4) * F(4) + 0.0; - answer(7, 1) = F(7) * C(0, 5) * F(8) + F(7) * C(0, 1) * F(1) + F(7) * C(0, 3) * F(3) + F(6) * C(5, 5) * F(8) + F(6) * C(5, 1) * F(1) + F(6) * C(5, 3) * F(3) + F(2) * C(4, 5) * F(8) + F(2) * C(4, 1) * F(1) + F(2) * C(4, 3) * F(3) + 0.0; - answer(7, 2) = F(7) * C(0, 4) * F(7) + F(7) * C(0, 3) * F(6) + F(7) * C(0, 2) * F(2) + F(6) * C(5, 4) * F(7) + F(6) * C(5, 3) * F(6) + F(6) * C(5, 2) * F(2) + F(2) * C(4, 4) * F(7) + F(2) * C(4, 3) * F(6) + F(2) * C(4, 2) * F(2) + S(4); - answer(7, 3) = F(7) * C(0, 4) * F(8) + F(7) * C(0, 3) * F(1) + F(7) * C(0, 2) * F(3) + F(6) * C(5, 4) * F(8) + F(6) * C(5, 3) * F(1) + F(6) * C(5, 2) * F(3) + F(2) * C(4, 4) * F(8) + F(2) * C(4, 3) * F(1) + F(2) * C(4, 2) * F(3) + 0.0; - answer(7, 4) = F(7) * C(0, 4) * F(0) + F(7) * C(0, 3) * F(5) + F(7) * C(0, 2) * F(4) + F(6) * C(5, 4) * F(0) + F(6) * C(5, 3) * F(5) + F(6) * C(5, 2) * F(4) + F(2) * C(4, 4) * F(0) + F(2) * C(4, 3) * F(5) + F(2) * C(4, 2) * F(4) + 0.0; - answer(7, 5) = F(7) * C(0, 5) * F(0) + F(7) * C(0, 1) * F(5) + F(7) * C(0, 3) * F(4) + F(6) * C(5, 5) * F(0) + F(6) * C(5, 1) * F(5) + F(6) * C(5, 3) * F(4) + F(2) * C(4, 5) * F(0) + F(2) * C(4, 1) * F(5) + F(2) * C(4, 3) * F(4) + 0.0; - answer(7, 6) = F(7) * C(0, 5) * F(7) + F(7) * C(0, 1) * F(6) + F(7) * C(0, 3) * F(2) + F(6) * C(5, 5) * F(7) + F(6) * C(5, 1) * F(6) + F(6) * C(5, 3) * F(2) + F(2) * C(4, 5) * F(7) + F(2) * C(4, 1) * F(6) + F(2) * C(4, 3) * F(2) + S(5); - answer(7, 7) = F(7) * C(0, 0) * F(7) + F(7) * C(0, 5) * F(6) + F(7) * C(0, 4) * F(2) + F(6) * C(5, 0) * F(7) + F(6) * C(5, 5) * F(6) + F(6) * C(5, 4) * F(2) + F(2) * C(4, 0) * F(7) + F(2) * C(4, 5) * F(6) + F(2) * C(4, 4) * F(2) + S(0); - answer(7, 8) = F(7) * C(0, 0) * F(8) + F(7) * C(0, 5) * F(1) + F(7) * C(0, 4) * F(3) + F(6) * C(5, 0) * F(8) + F(6) * C(5, 5) * F(1) + F(6) * C(5, 4) * F(3) + F(2) * C(4, 0) * F(8) + F(2) * C(4, 5) * F(1) + F(2) * C(4, 4) * F(3) + 0.0; - answer(8, 0) = F(8) * C(0, 0) * F(0) + F(8) * C(0, 5) * F(5) + F(8) * C(0, 4) * F(4) + F(1) * C(5, 0) * F(0) + F(1) * C(5, 5) * F(5) + F(1) * C(5, 4) * F(4) + F(3) * C(4, 0) * F(0) + F(3) * C(4, 5) * F(5) + F(3) * C(4, 4) * F(4) + 0.0; - answer(8, 1) = F(8) * C(0, 5) * F(8) + F(8) * C(0, 1) * F(1) + F(8) * C(0, 3) * F(3) + F(1) * C(5, 5) * F(8) + F(1) * C(5, 1) * F(1) + F(1) * C(5, 3) * F(3) + F(3) * C(4, 5) * F(8) + F(3) * C(4, 1) * F(1) + F(3) * C(4, 3) * F(3) + S(5); - answer(8, 2) = F(8) * C(0, 4) * F(7) + F(8) * C(0, 3) * F(6) + F(8) * C(0, 2) * F(2) + F(1) * C(5, 4) * F(7) + F(1) * C(5, 3) * F(6) + F(1) * C(5, 2) * F(2) + F(3) * C(4, 4) * F(7) + F(3) * C(4, 3) * F(6) + F(3) * C(4, 2) * F(2) + 0.0; - answer(8, 3) = F(8) * C(0, 4) * F(8) + F(8) * C(0, 3) * F(1) + F(8) * C(0, 2) * F(3) + F(1) * C(5, 4) * F(8) + F(1) * C(5, 3) * F(1) + F(1) * C(5, 2) * F(3) + F(3) * C(4, 4) * F(8) + F(3) * C(4, 3) * F(1) + F(3) * C(4, 2) * F(3) + S(4); - answer(8, 4) = F(8) * C(0, 4) * F(0) + F(8) * C(0, 3) * F(5) + F(8) * C(0, 2) * F(4) + F(1) * C(5, 4) * F(0) + F(1) * C(5, 3) * F(5) + F(1) * C(5, 2) * F(4) + F(3) * C(4, 4) * F(0) + F(3) * C(4, 3) * F(5) + F(3) * C(4, 2) * F(4) + 0.0; - answer(8, 5) = F(8) * C(0, 5) * F(0) + F(8) * C(0, 1) * F(5) + F(8) * C(0, 3) * F(4) + F(1) * C(5, 5) * F(0) + F(1) * C(5, 1) * F(5) + F(1) * C(5, 3) * F(4) + F(3) * C(4, 5) * F(0) + F(3) * C(4, 1) * F(5) + F(3) * C(4, 3) * F(4) + 0.0; - answer(8, 6) = F(8) * C(0, 5) * F(7) + F(8) * C(0, 1) * F(6) + F(8) * C(0, 3) * F(2) + F(1) * C(5, 5) * F(7) + F(1) * C(5, 1) * F(6) + F(1) * C(5, 3) * F(2) + F(3) * C(4, 5) * F(7) + F(3) * C(4, 1) * F(6) + F(3) * C(4, 3) * F(2) + 0.0; - answer(8, 7) = F(8) * C(0, 0) * F(7) + F(8) * C(0, 5) * F(6) + F(8) * C(0, 4) * F(2) + F(1) * C(5, 0) * F(7) + F(1) * C(5, 5) * F(6) + F(1) * C(5, 4) * F(2) + F(3) * C(4, 0) * F(7) + F(3) * C(4, 5) * F(6) + F(3) * C(4, 4) * F(2) + 0.0; - answer(8, 8) = F(8) * C(0, 0) * F(8) + F(8) * C(0, 5) * F(1) + F(8) * C(0, 4) * F(3) + F(1) * C(5, 0) * F(8) + F(1) * C(5, 5) * F(1) + F(1) * C(5, 4) * F(3) + F(3) * C(4, 0) * F(8) + F(3) * C(4, 5) * F(1) + F(3) * C(4, 4) * F(3) + S(0); + answer(0, 0) = F [ 0 ] * C(0, 0) * F [ 0 ] + F [ 0 ] * C(0, 5) * F [ 5 ] + F [ 0 ] * C(0, 4) * F [ 4 ] + F [ 5 ] * C(5, 0) * F [ 0 ] + F [ 5 ] * C(5, 5) * F [ 5 ] + F [ 5 ] * C(5, 4) * F [ 4 ] + F [ 4 ] * C(4, 0) * F [ 0 ] + F [ 4 ] * C(4, 5) * F [ 5 ] + F [ 4 ] * C(4, 4) * F [ 4 ] + S [ 0 ]; + answer(0, 1) = F [ 0 ] * C(0, 5) * F [ 8 ] + F [ 0 ] * C(0, 1) * F [ 1 ] + F [ 0 ] * C(0, 3) * F [ 3 ] + F [ 5 ] * C(5, 5) * F [ 8 ] + F [ 5 ] * C(5, 1) * F [ 1 ] + F [ 5 ] * C(5, 3) * F [ 3 ] + F [ 4 ] * C(4, 5) * F [ 8 ] + F [ 4 ] * C(4, 1) * F [ 1 ] + F [ 4 ] * C(4, 3) * F [ 3 ] + 0.0; + answer(0, 2) = F [ 0 ] * C(0, 4) * F [ 7 ] + F [ 0 ] * C(0, 3) * F [ 6 ] + F [ 0 ] * C(0, 2) * F [ 2 ] + F [ 5 ] * C(5, 4) * F [ 7 ] + F [ 5 ] * C(5, 3) * F [ 6 ] + F [ 5 ] * C(5, 2) * F [ 2 ] + F [ 4 ] * C(4, 4) * F [ 7 ] + F [ 4 ] * C(4, 3) * F [ 6 ] + F [ 4 ] * C(4, 2) * F [ 2 ] + 0.0; + answer(0, 3) = F [ 0 ] * C(0, 4) * F [ 8 ] + F [ 0 ] * C(0, 3) * F [ 1 ] + F [ 0 ] * C(0, 2) * F [ 3 ] + F [ 5 ] * C(5, 4) * F [ 8 ] + F [ 5 ] * C(5, 3) * F [ 1 ] + F [ 5 ] * C(5, 2) * F [ 3 ] + F [ 4 ] * C(4, 4) * F [ 8 ] + F [ 4 ] * C(4, 3) * F [ 1 ] + F [ 4 ] * C(4, 2) * F [ 3 ] + 0.0; + answer(0, 4) = F [ 0 ] * C(0, 4) * F [ 0 ] + F [ 0 ] * C(0, 3) * F [ 5 ] + F [ 0 ] * C(0, 2) * F [ 4 ] + F [ 5 ] * C(5, 4) * F [ 0 ] + F [ 5 ] * C(5, 3) * F [ 5 ] + F [ 5 ] * C(5, 2) * F [ 4 ] + F [ 4 ] * C(4, 4) * F [ 0 ] + F [ 4 ] * C(4, 3) * F [ 5 ] + F [ 4 ] * C(4, 2) * F [ 4 ] + S [ 4 ]; + answer(0, 5) = F [ 0 ] * C(0, 5) * F [ 0 ] + F [ 0 ] * C(0, 1) * F [ 5 ] + F [ 0 ] * C(0, 3) * F [ 4 ] + F [ 5 ] * C(5, 5) * F [ 0 ] + F [ 5 ] * C(5, 1) * F [ 5 ] + F [ 5 ] * C(5, 3) * F [ 4 ] + F [ 4 ] * C(4, 5) * F [ 0 ] + F [ 4 ] * C(4, 1) * F [ 5 ] + F [ 4 ] * C(4, 3) * F [ 4 ] + S [ 5 ]; + answer(0, 6) = F [ 0 ] * C(0, 5) * F [ 7 ] + F [ 0 ] * C(0, 1) * F [ 6 ] + F [ 0 ] * C(0, 3) * F [ 2 ] + F [ 5 ] * C(5, 5) * F [ 7 ] + F [ 5 ] * C(5, 1) * F [ 6 ] + F [ 5 ] * C(5, 3) * F [ 2 ] + F [ 4 ] * C(4, 5) * F [ 7 ] + F [ 4 ] * C(4, 1) * F [ 6 ] + F [ 4 ] * C(4, 3) * F [ 2 ] + 0.0; + answer(0, 7) = F [ 0 ] * C(0, 0) * F [ 7 ] + F [ 0 ] * C(0, 5) * F [ 6 ] + F [ 0 ] * C(0, 4) * F [ 2 ] + F [ 5 ] * C(5, 0) * F [ 7 ] + F [ 5 ] * C(5, 5) * F [ 6 ] + F [ 5 ] * C(5, 4) * F [ 2 ] + F [ 4 ] * C(4, 0) * F [ 7 ] + F [ 4 ] * C(4, 5) * F [ 6 ] + F [ 4 ] * C(4, 4) * F [ 2 ] + 0.0; + answer(0, 8) = F [ 0 ] * C(0, 0) * F [ 8 ] + F [ 0 ] * C(0, 5) * F [ 1 ] + F [ 0 ] * C(0, 4) * F [ 3 ] + F [ 5 ] * C(5, 0) * F [ 8 ] + F [ 5 ] * C(5, 5) * F [ 1 ] + F [ 5 ] * C(5, 4) * F [ 3 ] + F [ 4 ] * C(4, 0) * F [ 8 ] + F [ 4 ] * C(4, 5) * F [ 1 ] + F [ 4 ] * C(4, 4) * F [ 3 ] + 0.0; + answer(1, 0) = F [ 8 ] * C(5, 0) * F [ 0 ] + F [ 8 ] * C(5, 5) * F [ 5 ] + F [ 8 ] * C(5, 4) * F [ 4 ] + F [ 1 ] * C(1, 0) * F [ 0 ] + F [ 1 ] * C(1, 5) * F [ 5 ] + F [ 1 ] * C(1, 4) * F [ 4 ] + F [ 3 ] * C(3, 0) * F [ 0 ] + F [ 3 ] * C(3, 5) * F [ 5 ] + F [ 3 ] * C(3, 4) * F [ 4 ] + 0.0; + answer(1, 1) = F [ 8 ] * C(5, 5) * F [ 8 ] + F [ 8 ] * C(5, 1) * F [ 1 ] + F [ 8 ] * C(5, 3) * F [ 3 ] + F [ 1 ] * C(1, 5) * F [ 8 ] + F [ 1 ] * C(1, 1) * F [ 1 ] + F [ 1 ] * C(1, 3) * F [ 3 ] + F [ 3 ] * C(3, 5) * F [ 8 ] + F [ 3 ] * C(3, 1) * F [ 1 ] + F [ 3 ] * C(3, 3) * F [ 3 ] + S [ 1 ]; + answer(1, 2) = F [ 8 ] * C(5, 4) * F [ 7 ] + F [ 8 ] * C(5, 3) * F [ 6 ] + F [ 8 ] * C(5, 2) * F [ 2 ] + F [ 1 ] * C(1, 4) * F [ 7 ] + F [ 1 ] * C(1, 3) * F [ 6 ] + F [ 1 ] * C(1, 2) * F [ 2 ] + F [ 3 ] * C(3, 4) * F [ 7 ] + F [ 3 ] * C(3, 3) * F [ 6 ] + F [ 3 ] * C(3, 2) * F [ 2 ] + 0.0; + answer(1, 3) = F [ 8 ] * C(5, 4) * F [ 8 ] + F [ 8 ] * C(5, 3) * F [ 1 ] + F [ 8 ] * C(5, 2) * F [ 3 ] + F [ 1 ] * C(1, 4) * F [ 8 ] + F [ 1 ] * C(1, 3) * F [ 1 ] + F [ 1 ] * C(1, 2) * F [ 3 ] + F [ 3 ] * C(3, 4) * F [ 8 ] + F [ 3 ] * C(3, 3) * F [ 1 ] + F [ 3 ] * C(3, 2) * F [ 3 ] + S [ 3 ]; + answer(1, 4) = F [ 8 ] * C(5, 4) * F [ 0 ] + F [ 8 ] * C(5, 3) * F [ 5 ] + F [ 8 ] * C(5, 2) * F [ 4 ] + F [ 1 ] * C(1, 4) * F [ 0 ] + F [ 1 ] * C(1, 3) * F [ 5 ] + F [ 1 ] * C(1, 2) * F [ 4 ] + F [ 3 ] * C(3, 4) * F [ 0 ] + F [ 3 ] * C(3, 3) * F [ 5 ] + F [ 3 ] * C(3, 2) * F [ 4 ] + 0.0; + answer(1, 5) = F [ 8 ] * C(5, 5) * F [ 0 ] + F [ 8 ] * C(5, 1) * F [ 5 ] + F [ 8 ] * C(5, 3) * F [ 4 ] + F [ 1 ] * C(1, 5) * F [ 0 ] + F [ 1 ] * C(1, 1) * F [ 5 ] + F [ 1 ] * C(1, 3) * F [ 4 ] + F [ 3 ] * C(3, 5) * F [ 0 ] + F [ 3 ] * C(3, 1) * F [ 5 ] + F [ 3 ] * C(3, 3) * F [ 4 ] + 0.0; + answer(1, 6) = F [ 8 ] * C(5, 5) * F [ 7 ] + F [ 8 ] * C(5, 1) * F [ 6 ] + F [ 8 ] * C(5, 3) * F [ 2 ] + F [ 1 ] * C(1, 5) * F [ 7 ] + F [ 1 ] * C(1, 1) * F [ 6 ] + F [ 1 ] * C(1, 3) * F [ 2 ] + F [ 3 ] * C(3, 5) * F [ 7 ] + F [ 3 ] * C(3, 1) * F [ 6 ] + F [ 3 ] * C(3, 3) * F [ 2 ] + 0.0; + answer(1, 7) = F [ 8 ] * C(5, 0) * F [ 7 ] + F [ 8 ] * C(5, 5) * F [ 6 ] + F [ 8 ] * C(5, 4) * F [ 2 ] + F [ 1 ] * C(1, 0) * F [ 7 ] + F [ 1 ] * C(1, 5) * F [ 6 ] + F [ 1 ] * C(1, 4) * F [ 2 ] + F [ 3 ] * C(3, 0) * F [ 7 ] + F [ 3 ] * C(3, 5) * F [ 6 ] + F [ 3 ] * C(3, 4) * F [ 2 ] + 0.0; + answer(1, 8) = F [ 8 ] * C(5, 0) * F [ 8 ] + F [ 8 ] * C(5, 5) * F [ 1 ] + F [ 8 ] * C(5, 4) * F [ 3 ] + F [ 1 ] * C(1, 0) * F [ 8 ] + F [ 1 ] * C(1, 5) * F [ 1 ] + F [ 1 ] * C(1, 4) * F [ 3 ] + F [ 3 ] * C(3, 0) * F [ 8 ] + F [ 3 ] * C(3, 5) * F [ 1 ] + F [ 3 ] * C(3, 4) * F [ 3 ] + S [ 5 ]; + answer(2, 0) = F [ 7 ] * C(4, 0) * F [ 0 ] + F [ 7 ] * C(4, 5) * F [ 5 ] + F [ 7 ] * C(4, 4) * F [ 4 ] + F [ 6 ] * C(3, 0) * F [ 0 ] + F [ 6 ] * C(3, 5) * F [ 5 ] + F [ 6 ] * C(3, 4) * F [ 4 ] + F [ 2 ] * C(2, 0) * F [ 0 ] + F [ 2 ] * C(2, 5) * F [ 5 ] + F [ 2 ] * C(2, 4) * F [ 4 ] + 0.0; + answer(2, 1) = F [ 7 ] * C(4, 5) * F [ 8 ] + F [ 7 ] * C(4, 1) * F [ 1 ] + F [ 7 ] * C(4, 3) * F [ 3 ] + F [ 6 ] * C(3, 5) * F [ 8 ] + F [ 6 ] * C(3, 1) * F [ 1 ] + F [ 6 ] * C(3, 3) * F [ 3 ] + F [ 2 ] * C(2, 5) * F [ 8 ] + F [ 2 ] * C(2, 1) * F [ 1 ] + F [ 2 ] * C(2, 3) * F [ 3 ] + 0.0; + answer(2, 2) = F [ 7 ] * C(4, 4) * F [ 7 ] + F [ 7 ] * C(4, 3) * F [ 6 ] + F [ 7 ] * C(4, 2) * F [ 2 ] + F [ 6 ] * C(3, 4) * F [ 7 ] + F [ 6 ] * C(3, 3) * F [ 6 ] + F [ 6 ] * C(3, 2) * F [ 2 ] + F [ 2 ] * C(2, 4) * F [ 7 ] + F [ 2 ] * C(2, 3) * F [ 6 ] + F [ 2 ] * C(2, 2) * F [ 2 ] + S [ 2 ]; + answer(2, 3) = F [ 7 ] * C(4, 4) * F [ 8 ] + F [ 7 ] * C(4, 3) * F [ 1 ] + F [ 7 ] * C(4, 2) * F [ 3 ] + F [ 6 ] * C(3, 4) * F [ 8 ] + F [ 6 ] * C(3, 3) * F [ 1 ] + F [ 6 ] * C(3, 2) * F [ 3 ] + F [ 2 ] * C(2, 4) * F [ 8 ] + F [ 2 ] * C(2, 3) * F [ 1 ] + F [ 2 ] * C(2, 2) * F [ 3 ] + 0.0; + answer(2, 4) = F [ 7 ] * C(4, 4) * F [ 0 ] + F [ 7 ] * C(4, 3) * F [ 5 ] + F [ 7 ] * C(4, 2) * F [ 4 ] + F [ 6 ] * C(3, 4) * F [ 0 ] + F [ 6 ] * C(3, 3) * F [ 5 ] + F [ 6 ] * C(3, 2) * F [ 4 ] + F [ 2 ] * C(2, 4) * F [ 0 ] + F [ 2 ] * C(2, 3) * F [ 5 ] + F [ 2 ] * C(2, 2) * F [ 4 ] + 0.0; + answer(2, 5) = F [ 7 ] * C(4, 5) * F [ 0 ] + F [ 7 ] * C(4, 1) * F [ 5 ] + F [ 7 ] * C(4, 3) * F [ 4 ] + F [ 6 ] * C(3, 5) * F [ 0 ] + F [ 6 ] * C(3, 1) * F [ 5 ] + F [ 6 ] * C(3, 3) * F [ 4 ] + F [ 2 ] * C(2, 5) * F [ 0 ] + F [ 2 ] * C(2, 1) * F [ 5 ] + F [ 2 ] * C(2, 3) * F [ 4 ] + 0.0; + answer(2, 6) = F [ 7 ] * C(4, 5) * F [ 7 ] + F [ 7 ] * C(4, 1) * F [ 6 ] + F [ 7 ] * C(4, 3) * F [ 2 ] + F [ 6 ] * C(3, 5) * F [ 7 ] + F [ 6 ] * C(3, 1) * F [ 6 ] + F [ 6 ] * C(3, 3) * F [ 2 ] + F [ 2 ] * C(2, 5) * F [ 7 ] + F [ 2 ] * C(2, 1) * F [ 6 ] + F [ 2 ] * C(2, 3) * F [ 2 ] + S [ 3 ]; + answer(2, 7) = F [ 7 ] * C(4, 0) * F [ 7 ] + F [ 7 ] * C(4, 5) * F [ 6 ] + F [ 7 ] * C(4, 4) * F [ 2 ] + F [ 6 ] * C(3, 0) * F [ 7 ] + F [ 6 ] * C(3, 5) * F [ 6 ] + F [ 6 ] * C(3, 4) * F [ 2 ] + F [ 2 ] * C(2, 0) * F [ 7 ] + F [ 2 ] * C(2, 5) * F [ 6 ] + F [ 2 ] * C(2, 4) * F [ 2 ] + S [ 4 ]; + answer(2, 8) = F [ 7 ] * C(4, 0) * F [ 8 ] + F [ 7 ] * C(4, 5) * F [ 1 ] + F [ 7 ] * C(4, 4) * F [ 3 ] + F [ 6 ] * C(3, 0) * F [ 8 ] + F [ 6 ] * C(3, 5) * F [ 1 ] + F [ 6 ] * C(3, 4) * F [ 3 ] + F [ 2 ] * C(2, 0) * F [ 8 ] + F [ 2 ] * C(2, 5) * F [ 1 ] + F [ 2 ] * C(2, 4) * F [ 3 ] + 0.0; + answer(3, 0) = F [ 8 ] * C(4, 0) * F [ 0 ] + F [ 8 ] * C(4, 5) * F [ 5 ] + F [ 8 ] * C(4, 4) * F [ 4 ] + F [ 1 ] * C(3, 0) * F [ 0 ] + F [ 1 ] * C(3, 5) * F [ 5 ] + F [ 1 ] * C(3, 4) * F [ 4 ] + F [ 3 ] * C(2, 0) * F [ 0 ] + F [ 3 ] * C(2, 5) * F [ 5 ] + F [ 3 ] * C(2, 4) * F [ 4 ] + 0.0; + answer(3, 1) = F [ 8 ] * C(4, 5) * F [ 8 ] + F [ 8 ] * C(4, 1) * F [ 1 ] + F [ 8 ] * C(4, 3) * F [ 3 ] + F [ 1 ] * C(3, 5) * F [ 8 ] + F [ 1 ] * C(3, 1) * F [ 1 ] + F [ 1 ] * C(3, 3) * F [ 3 ] + F [ 3 ] * C(2, 5) * F [ 8 ] + F [ 3 ] * C(2, 1) * F [ 1 ] + F [ 3 ] * C(2, 3) * F [ 3 ] + S [ 3 ]; + answer(3, 2) = F [ 8 ] * C(4, 4) * F [ 7 ] + F [ 8 ] * C(4, 3) * F [ 6 ] + F [ 8 ] * C(4, 2) * F [ 2 ] + F [ 1 ] * C(3, 4) * F [ 7 ] + F [ 1 ] * C(3, 3) * F [ 6 ] + F [ 1 ] * C(3, 2) * F [ 2 ] + F [ 3 ] * C(2, 4) * F [ 7 ] + F [ 3 ] * C(2, 3) * F [ 6 ] + F [ 3 ] * C(2, 2) * F [ 2 ] + 0.0; + answer(3, 3) = F [ 8 ] * C(4, 4) * F [ 8 ] + F [ 8 ] * C(4, 3) * F [ 1 ] + F [ 8 ] * C(4, 2) * F [ 3 ] + F [ 1 ] * C(3, 4) * F [ 8 ] + F [ 1 ] * C(3, 3) * F [ 1 ] + F [ 1 ] * C(3, 2) * F [ 3 ] + F [ 3 ] * C(2, 4) * F [ 8 ] + F [ 3 ] * C(2, 3) * F [ 1 ] + F [ 3 ] * C(2, 2) * F [ 3 ] + S [ 2 ]; + answer(3, 4) = F [ 8 ] * C(4, 4) * F [ 0 ] + F [ 8 ] * C(4, 3) * F [ 5 ] + F [ 8 ] * C(4, 2) * F [ 4 ] + F [ 1 ] * C(3, 4) * F [ 0 ] + F [ 1 ] * C(3, 3) * F [ 5 ] + F [ 1 ] * C(3, 2) * F [ 4 ] + F [ 3 ] * C(2, 4) * F [ 0 ] + F [ 3 ] * C(2, 3) * F [ 5 ] + F [ 3 ] * C(2, 2) * F [ 4 ] + 0.0; + answer(3, 5) = F [ 8 ] * C(4, 5) * F [ 0 ] + F [ 8 ] * C(4, 1) * F [ 5 ] + F [ 8 ] * C(4, 3) * F [ 4 ] + F [ 1 ] * C(3, 5) * F [ 0 ] + F [ 1 ] * C(3, 1) * F [ 5 ] + F [ 1 ] * C(3, 3) * F [ 4 ] + F [ 3 ] * C(2, 5) * F [ 0 ] + F [ 3 ] * C(2, 1) * F [ 5 ] + F [ 3 ] * C(2, 3) * F [ 4 ] + 0.0; + answer(3, 6) = F [ 8 ] * C(4, 5) * F [ 7 ] + F [ 8 ] * C(4, 1) * F [ 6 ] + F [ 8 ] * C(4, 3) * F [ 2 ] + F [ 1 ] * C(3, 5) * F [ 7 ] + F [ 1 ] * C(3, 1) * F [ 6 ] + F [ 1 ] * C(3, 3) * F [ 2 ] + F [ 3 ] * C(2, 5) * F [ 7 ] + F [ 3 ] * C(2, 1) * F [ 6 ] + F [ 3 ] * C(2, 3) * F [ 2 ] + 0.0; + answer(3, 7) = F [ 8 ] * C(4, 0) * F [ 7 ] + F [ 8 ] * C(4, 5) * F [ 6 ] + F [ 8 ] * C(4, 4) * F [ 2 ] + F [ 1 ] * C(3, 0) * F [ 7 ] + F [ 1 ] * C(3, 5) * F [ 6 ] + F [ 1 ] * C(3, 4) * F [ 2 ] + F [ 3 ] * C(2, 0) * F [ 7 ] + F [ 3 ] * C(2, 5) * F [ 6 ] + F [ 3 ] * C(2, 4) * F [ 2 ] + 0.0; + answer(3, 8) = F [ 8 ] * C(4, 0) * F [ 8 ] + F [ 8 ] * C(4, 5) * F [ 1 ] + F [ 8 ] * C(4, 4) * F [ 3 ] + F [ 1 ] * C(3, 0) * F [ 8 ] + F [ 1 ] * C(3, 5) * F [ 1 ] + F [ 1 ] * C(3, 4) * F [ 3 ] + F [ 3 ] * C(2, 0) * F [ 8 ] + F [ 3 ] * C(2, 5) * F [ 1 ] + F [ 3 ] * C(2, 4) * F [ 3 ] + S [ 4 ]; + answer(4, 0) = F [ 0 ] * C(4, 0) * F [ 0 ] + F [ 0 ] * C(4, 5) * F [ 5 ] + F [ 0 ] * C(4, 4) * F [ 4 ] + F [ 5 ] * C(3, 0) * F [ 0 ] + F [ 5 ] * C(3, 5) * F [ 5 ] + F [ 5 ] * C(3, 4) * F [ 4 ] + F [ 4 ] * C(2, 0) * F [ 0 ] + F [ 4 ] * C(2, 5) * F [ 5 ] + F [ 4 ] * C(2, 4) * F [ 4 ] + S [ 4 ]; + answer(4, 1) = F [ 0 ] * C(4, 5) * F [ 8 ] + F [ 0 ] * C(4, 1) * F [ 1 ] + F [ 0 ] * C(4, 3) * F [ 3 ] + F [ 5 ] * C(3, 5) * F [ 8 ] + F [ 5 ] * C(3, 1) * F [ 1 ] + F [ 5 ] * C(3, 3) * F [ 3 ] + F [ 4 ] * C(2, 5) * F [ 8 ] + F [ 4 ] * C(2, 1) * F [ 1 ] + F [ 4 ] * C(2, 3) * F [ 3 ] + 0.0; + answer(4, 2) = F [ 0 ] * C(4, 4) * F [ 7 ] + F [ 0 ] * C(4, 3) * F [ 6 ] + F [ 0 ] * C(4, 2) * F [ 2 ] + F [ 5 ] * C(3, 4) * F [ 7 ] + F [ 5 ] * C(3, 3) * F [ 6 ] + F [ 5 ] * C(3, 2) * F [ 2 ] + F [ 4 ] * C(2, 4) * F [ 7 ] + F [ 4 ] * C(2, 3) * F [ 6 ] + F [ 4 ] * C(2, 2) * F [ 2 ] + 0.0; + answer(4, 3) = F [ 0 ] * C(4, 4) * F [ 8 ] + F [ 0 ] * C(4, 3) * F [ 1 ] + F [ 0 ] * C(4, 2) * F [ 3 ] + F [ 5 ] * C(3, 4) * F [ 8 ] + F [ 5 ] * C(3, 3) * F [ 1 ] + F [ 5 ] * C(3, 2) * F [ 3 ] + F [ 4 ] * C(2, 4) * F [ 8 ] + F [ 4 ] * C(2, 3) * F [ 1 ] + F [ 4 ] * C(2, 2) * F [ 3 ] + 0.0; + answer(4, 4) = F [ 0 ] * C(4, 4) * F [ 0 ] + F [ 0 ] * C(4, 3) * F [ 5 ] + F [ 0 ] * C(4, 2) * F [ 4 ] + F [ 5 ] * C(3, 4) * F [ 0 ] + F [ 5 ] * C(3, 3) * F [ 5 ] + F [ 5 ] * C(3, 2) * F [ 4 ] + F [ 4 ] * C(2, 4) * F [ 0 ] + F [ 4 ] * C(2, 3) * F [ 5 ] + F [ 4 ] * C(2, 2) * F [ 4 ] + S [ 2 ]; + answer(4, 5) = F [ 0 ] * C(4, 5) * F [ 0 ] + F [ 0 ] * C(4, 1) * F [ 5 ] + F [ 0 ] * C(4, 3) * F [ 4 ] + F [ 5 ] * C(3, 5) * F [ 0 ] + F [ 5 ] * C(3, 1) * F [ 5 ] + F [ 5 ] * C(3, 3) * F [ 4 ] + F [ 4 ] * C(2, 5) * F [ 0 ] + F [ 4 ] * C(2, 1) * F [ 5 ] + F [ 4 ] * C(2, 3) * F [ 4 ] + S [ 3 ]; + answer(4, 6) = F [ 0 ] * C(4, 5) * F [ 7 ] + F [ 0 ] * C(4, 1) * F [ 6 ] + F [ 0 ] * C(4, 3) * F [ 2 ] + F [ 5 ] * C(3, 5) * F [ 7 ] + F [ 5 ] * C(3, 1) * F [ 6 ] + F [ 5 ] * C(3, 3) * F [ 2 ] + F [ 4 ] * C(2, 5) * F [ 7 ] + F [ 4 ] * C(2, 1) * F [ 6 ] + F [ 4 ] * C(2, 3) * F [ 2 ] + 0.0; + answer(4, 7) = F [ 0 ] * C(4, 0) * F [ 7 ] + F [ 0 ] * C(4, 5) * F [ 6 ] + F [ 0 ] * C(4, 4) * F [ 2 ] + F [ 5 ] * C(3, 0) * F [ 7 ] + F [ 5 ] * C(3, 5) * F [ 6 ] + F [ 5 ] * C(3, 4) * F [ 2 ] + F [ 4 ] * C(2, 0) * F [ 7 ] + F [ 4 ] * C(2, 5) * F [ 6 ] + F [ 4 ] * C(2, 4) * F [ 2 ] + 0.0; + answer(4, 8) = F [ 0 ] * C(4, 0) * F [ 8 ] + F [ 0 ] * C(4, 5) * F [ 1 ] + F [ 0 ] * C(4, 4) * F [ 3 ] + F [ 5 ] * C(3, 0) * F [ 8 ] + F [ 5 ] * C(3, 5) * F [ 1 ] + F [ 5 ] * C(3, 4) * F [ 3 ] + F [ 4 ] * C(2, 0) * F [ 8 ] + F [ 4 ] * C(2, 5) * F [ 1 ] + F [ 4 ] * C(2, 4) * F [ 3 ] + 0.0; + answer(5, 0) = F [ 0 ] * C(5, 0) * F [ 0 ] + F [ 0 ] * C(5, 5) * F [ 5 ] + F [ 0 ] * C(5, 4) * F [ 4 ] + F [ 5 ] * C(1, 0) * F [ 0 ] + F [ 5 ] * C(1, 5) * F [ 5 ] + F [ 5 ] * C(1, 4) * F [ 4 ] + F [ 4 ] * C(3, 0) * F [ 0 ] + F [ 4 ] * C(3, 5) * F [ 5 ] + F [ 4 ] * C(3, 4) * F [ 4 ] + S [ 5 ]; + answer(5, 1) = F [ 0 ] * C(5, 5) * F [ 8 ] + F [ 0 ] * C(5, 1) * F [ 1 ] + F [ 0 ] * C(5, 3) * F [ 3 ] + F [ 5 ] * C(1, 5) * F [ 8 ] + F [ 5 ] * C(1, 1) * F [ 1 ] + F [ 5 ] * C(1, 3) * F [ 3 ] + F [ 4 ] * C(3, 5) * F [ 8 ] + F [ 4 ] * C(3, 1) * F [ 1 ] + F [ 4 ] * C(3, 3) * F [ 3 ] + 0.0; + answer(5, 2) = F [ 0 ] * C(5, 4) * F [ 7 ] + F [ 0 ] * C(5, 3) * F [ 6 ] + F [ 0 ] * C(5, 2) * F [ 2 ] + F [ 5 ] * C(1, 4) * F [ 7 ] + F [ 5 ] * C(1, 3) * F [ 6 ] + F [ 5 ] * C(1, 2) * F [ 2 ] + F [ 4 ] * C(3, 4) * F [ 7 ] + F [ 4 ] * C(3, 3) * F [ 6 ] + F [ 4 ] * C(3, 2) * F [ 2 ] + 0.0; + answer(5, 3) = F [ 0 ] * C(5, 4) * F [ 8 ] + F [ 0 ] * C(5, 3) * F [ 1 ] + F [ 0 ] * C(5, 2) * F [ 3 ] + F [ 5 ] * C(1, 4) * F [ 8 ] + F [ 5 ] * C(1, 3) * F [ 1 ] + F [ 5 ] * C(1, 2) * F [ 3 ] + F [ 4 ] * C(3, 4) * F [ 8 ] + F [ 4 ] * C(3, 3) * F [ 1 ] + F [ 4 ] * C(3, 2) * F [ 3 ] + 0.0; + answer(5, 4) = F [ 0 ] * C(5, 4) * F [ 0 ] + F [ 0 ] * C(5, 3) * F [ 5 ] + F [ 0 ] * C(5, 2) * F [ 4 ] + F [ 5 ] * C(1, 4) * F [ 0 ] + F [ 5 ] * C(1, 3) * F [ 5 ] + F [ 5 ] * C(1, 2) * F [ 4 ] + F [ 4 ] * C(3, 4) * F [ 0 ] + F [ 4 ] * C(3, 3) * F [ 5 ] + F [ 4 ] * C(3, 2) * F [ 4 ] + S [ 3 ]; + answer(5, 5) = F [ 0 ] * C(5, 5) * F [ 0 ] + F [ 0 ] * C(5, 1) * F [ 5 ] + F [ 0 ] * C(5, 3) * F [ 4 ] + F [ 5 ] * C(1, 5) * F [ 0 ] + F [ 5 ] * C(1, 1) * F [ 5 ] + F [ 5 ] * C(1, 3) * F [ 4 ] + F [ 4 ] * C(3, 5) * F [ 0 ] + F [ 4 ] * C(3, 1) * F [ 5 ] + F [ 4 ] * C(3, 3) * F [ 4 ] + S [ 1 ]; + answer(5, 6) = F [ 0 ] * C(5, 5) * F [ 7 ] + F [ 0 ] * C(5, 1) * F [ 6 ] + F [ 0 ] * C(5, 3) * F [ 2 ] + F [ 5 ] * C(1, 5) * F [ 7 ] + F [ 5 ] * C(1, 1) * F [ 6 ] + F [ 5 ] * C(1, 3) * F [ 2 ] + F [ 4 ] * C(3, 5) * F [ 7 ] + F [ 4 ] * C(3, 1) * F [ 6 ] + F [ 4 ] * C(3, 3) * F [ 2 ] + 0.0; + answer(5, 7) = F [ 0 ] * C(5, 0) * F [ 7 ] + F [ 0 ] * C(5, 5) * F [ 6 ] + F [ 0 ] * C(5, 4) * F [ 2 ] + F [ 5 ] * C(1, 0) * F [ 7 ] + F [ 5 ] * C(1, 5) * F [ 6 ] + F [ 5 ] * C(1, 4) * F [ 2 ] + F [ 4 ] * C(3, 0) * F [ 7 ] + F [ 4 ] * C(3, 5) * F [ 6 ] + F [ 4 ] * C(3, 4) * F [ 2 ] + 0.0; + answer(5, 8) = F [ 0 ] * C(5, 0) * F [ 8 ] + F [ 0 ] * C(5, 5) * F [ 1 ] + F [ 0 ] * C(5, 4) * F [ 3 ] + F [ 5 ] * C(1, 0) * F [ 8 ] + F [ 5 ] * C(1, 5) * F [ 1 ] + F [ 5 ] * C(1, 4) * F [ 3 ] + F [ 4 ] * C(3, 0) * F [ 8 ] + F [ 4 ] * C(3, 5) * F [ 1 ] + F [ 4 ] * C(3, 4) * F [ 3 ] + 0.0; + answer(6, 0) = F [ 7 ] * C(5, 0) * F [ 0 ] + F [ 7 ] * C(5, 5) * F [ 5 ] + F [ 7 ] * C(5, 4) * F [ 4 ] + F [ 6 ] * C(1, 0) * F [ 0 ] + F [ 6 ] * C(1, 5) * F [ 5 ] + F [ 6 ] * C(1, 4) * F [ 4 ] + F [ 2 ] * C(3, 0) * F [ 0 ] + F [ 2 ] * C(3, 5) * F [ 5 ] + F [ 2 ] * C(3, 4) * F [ 4 ] + 0.0; + answer(6, 1) = F [ 7 ] * C(5, 5) * F [ 8 ] + F [ 7 ] * C(5, 1) * F [ 1 ] + F [ 7 ] * C(5, 3) * F [ 3 ] + F [ 6 ] * C(1, 5) * F [ 8 ] + F [ 6 ] * C(1, 1) * F [ 1 ] + F [ 6 ] * C(1, 3) * F [ 3 ] + F [ 2 ] * C(3, 5) * F [ 8 ] + F [ 2 ] * C(3, 1) * F [ 1 ] + F [ 2 ] * C(3, 3) * F [ 3 ] + 0.0; + answer(6, 2) = F [ 7 ] * C(5, 4) * F [ 7 ] + F [ 7 ] * C(5, 3) * F [ 6 ] + F [ 7 ] * C(5, 2) * F [ 2 ] + F [ 6 ] * C(1, 4) * F [ 7 ] + F [ 6 ] * C(1, 3) * F [ 6 ] + F [ 6 ] * C(1, 2) * F [ 2 ] + F [ 2 ] * C(3, 4) * F [ 7 ] + F [ 2 ] * C(3, 3) * F [ 6 ] + F [ 2 ] * C(3, 2) * F [ 2 ] + S [ 3 ]; + answer(6, 3) = F [ 7 ] * C(5, 4) * F [ 8 ] + F [ 7 ] * C(5, 3) * F [ 1 ] + F [ 7 ] * C(5, 2) * F [ 3 ] + F [ 6 ] * C(1, 4) * F [ 8 ] + F [ 6 ] * C(1, 3) * F [ 1 ] + F [ 6 ] * C(1, 2) * F [ 3 ] + F [ 2 ] * C(3, 4) * F [ 8 ] + F [ 2 ] * C(3, 3) * F [ 1 ] + F [ 2 ] * C(3, 2) * F [ 3 ] + 0.0; + answer(6, 4) = F [ 7 ] * C(5, 4) * F [ 0 ] + F [ 7 ] * C(5, 3) * F [ 5 ] + F [ 7 ] * C(5, 2) * F [ 4 ] + F [ 6 ] * C(1, 4) * F [ 0 ] + F [ 6 ] * C(1, 3) * F [ 5 ] + F [ 6 ] * C(1, 2) * F [ 4 ] + F [ 2 ] * C(3, 4) * F [ 0 ] + F [ 2 ] * C(3, 3) * F [ 5 ] + F [ 2 ] * C(3, 2) * F [ 4 ] + 0.0; + answer(6, 5) = F [ 7 ] * C(5, 5) * F [ 0 ] + F [ 7 ] * C(5, 1) * F [ 5 ] + F [ 7 ] * C(5, 3) * F [ 4 ] + F [ 6 ] * C(1, 5) * F [ 0 ] + F [ 6 ] * C(1, 1) * F [ 5 ] + F [ 6 ] * C(1, 3) * F [ 4 ] + F [ 2 ] * C(3, 5) * F [ 0 ] + F [ 2 ] * C(3, 1) * F [ 5 ] + F [ 2 ] * C(3, 3) * F [ 4 ] + 0.0; + answer(6, 6) = F [ 7 ] * C(5, 5) * F [ 7 ] + F [ 7 ] * C(5, 1) * F [ 6 ] + F [ 7 ] * C(5, 3) * F [ 2 ] + F [ 6 ] * C(1, 5) * F [ 7 ] + F [ 6 ] * C(1, 1) * F [ 6 ] + F [ 6 ] * C(1, 3) * F [ 2 ] + F [ 2 ] * C(3, 5) * F [ 7 ] + F [ 2 ] * C(3, 1) * F [ 6 ] + F [ 2 ] * C(3, 3) * F [ 2 ] + S [ 1 ]; + answer(6, 7) = F [ 7 ] * C(5, 0) * F [ 7 ] + F [ 7 ] * C(5, 5) * F [ 6 ] + F [ 7 ] * C(5, 4) * F [ 2 ] + F [ 6 ] * C(1, 0) * F [ 7 ] + F [ 6 ] * C(1, 5) * F [ 6 ] + F [ 6 ] * C(1, 4) * F [ 2 ] + F [ 2 ] * C(3, 0) * F [ 7 ] + F [ 2 ] * C(3, 5) * F [ 6 ] + F [ 2 ] * C(3, 4) * F [ 2 ] + S [ 5 ]; + answer(6, 8) = F [ 7 ] * C(5, 0) * F [ 8 ] + F [ 7 ] * C(5, 5) * F [ 1 ] + F [ 7 ] * C(5, 4) * F [ 3 ] + F [ 6 ] * C(1, 0) * F [ 8 ] + F [ 6 ] * C(1, 5) * F [ 1 ] + F [ 6 ] * C(1, 4) * F [ 3 ] + F [ 2 ] * C(3, 0) * F [ 8 ] + F [ 2 ] * C(3, 5) * F [ 1 ] + F [ 2 ] * C(3, 4) * F [ 3 ] + 0.0; + answer(7, 0) = F [ 7 ] * C(0, 0) * F [ 0 ] + F [ 7 ] * C(0, 5) * F [ 5 ] + F [ 7 ] * C(0, 4) * F [ 4 ] + F [ 6 ] * C(5, 0) * F [ 0 ] + F [ 6 ] * C(5, 5) * F [ 5 ] + F [ 6 ] * C(5, 4) * F [ 4 ] + F [ 2 ] * C(4, 0) * F [ 0 ] + F [ 2 ] * C(4, 5) * F [ 5 ] + F [ 2 ] * C(4, 4) * F [ 4 ] + 0.0; + answer(7, 1) = F [ 7 ] * C(0, 5) * F [ 8 ] + F [ 7 ] * C(0, 1) * F [ 1 ] + F [ 7 ] * C(0, 3) * F [ 3 ] + F [ 6 ] * C(5, 5) * F [ 8 ] + F [ 6 ] * C(5, 1) * F [ 1 ] + F [ 6 ] * C(5, 3) * F [ 3 ] + F [ 2 ] * C(4, 5) * F [ 8 ] + F [ 2 ] * C(4, 1) * F [ 1 ] + F [ 2 ] * C(4, 3) * F [ 3 ] + 0.0; + answer(7, 2) = F [ 7 ] * C(0, 4) * F [ 7 ] + F [ 7 ] * C(0, 3) * F [ 6 ] + F [ 7 ] * C(0, 2) * F [ 2 ] + F [ 6 ] * C(5, 4) * F [ 7 ] + F [ 6 ] * C(5, 3) * F [ 6 ] + F [ 6 ] * C(5, 2) * F [ 2 ] + F [ 2 ] * C(4, 4) * F [ 7 ] + F [ 2 ] * C(4, 3) * F [ 6 ] + F [ 2 ] * C(4, 2) * F [ 2 ] + S [ 4 ]; + answer(7, 3) = F [ 7 ] * C(0, 4) * F [ 8 ] + F [ 7 ] * C(0, 3) * F [ 1 ] + F [ 7 ] * C(0, 2) * F [ 3 ] + F [ 6 ] * C(5, 4) * F [ 8 ] + F [ 6 ] * C(5, 3) * F [ 1 ] + F [ 6 ] * C(5, 2) * F [ 3 ] + F [ 2 ] * C(4, 4) * F [ 8 ] + F [ 2 ] * C(4, 3) * F [ 1 ] + F [ 2 ] * C(4, 2) * F [ 3 ] + 0.0; + answer(7, 4) = F [ 7 ] * C(0, 4) * F [ 0 ] + F [ 7 ] * C(0, 3) * F [ 5 ] + F [ 7 ] * C(0, 2) * F [ 4 ] + F [ 6 ] * C(5, 4) * F [ 0 ] + F [ 6 ] * C(5, 3) * F [ 5 ] + F [ 6 ] * C(5, 2) * F [ 4 ] + F [ 2 ] * C(4, 4) * F [ 0 ] + F [ 2 ] * C(4, 3) * F [ 5 ] + F [ 2 ] * C(4, 2) * F [ 4 ] + 0.0; + answer(7, 5) = F [ 7 ] * C(0, 5) * F [ 0 ] + F [ 7 ] * C(0, 1) * F [ 5 ] + F [ 7 ] * C(0, 3) * F [ 4 ] + F [ 6 ] * C(5, 5) * F [ 0 ] + F [ 6 ] * C(5, 1) * F [ 5 ] + F [ 6 ] * C(5, 3) * F [ 4 ] + F [ 2 ] * C(4, 5) * F [ 0 ] + F [ 2 ] * C(4, 1) * F [ 5 ] + F [ 2 ] * C(4, 3) * F [ 4 ] + 0.0; + answer(7, 6) = F [ 7 ] * C(0, 5) * F [ 7 ] + F [ 7 ] * C(0, 1) * F [ 6 ] + F [ 7 ] * C(0, 3) * F [ 2 ] + F [ 6 ] * C(5, 5) * F [ 7 ] + F [ 6 ] * C(5, 1) * F [ 6 ] + F [ 6 ] * C(5, 3) * F [ 2 ] + F [ 2 ] * C(4, 5) * F [ 7 ] + F [ 2 ] * C(4, 1) * F [ 6 ] + F [ 2 ] * C(4, 3) * F [ 2 ] + S [ 5 ]; + answer(7, 7) = F [ 7 ] * C(0, 0) * F [ 7 ] + F [ 7 ] * C(0, 5) * F [ 6 ] + F [ 7 ] * C(0, 4) * F [ 2 ] + F [ 6 ] * C(5, 0) * F [ 7 ] + F [ 6 ] * C(5, 5) * F [ 6 ] + F [ 6 ] * C(5, 4) * F [ 2 ] + F [ 2 ] * C(4, 0) * F [ 7 ] + F [ 2 ] * C(4, 5) * F [ 6 ] + F [ 2 ] * C(4, 4) * F [ 2 ] + S [ 0 ]; + answer(7, 8) = F [ 7 ] * C(0, 0) * F [ 8 ] + F [ 7 ] * C(0, 5) * F [ 1 ] + F [ 7 ] * C(0, 4) * F [ 3 ] + F [ 6 ] * C(5, 0) * F [ 8 ] + F [ 6 ] * C(5, 5) * F [ 1 ] + F [ 6 ] * C(5, 4) * F [ 3 ] + F [ 2 ] * C(4, 0) * F [ 8 ] + F [ 2 ] * C(4, 5) * F [ 1 ] + F [ 2 ] * C(4, 4) * F [ 3 ] + 0.0; + answer(8, 0) = F [ 8 ] * C(0, 0) * F [ 0 ] + F [ 8 ] * C(0, 5) * F [ 5 ] + F [ 8 ] * C(0, 4) * F [ 4 ] + F [ 1 ] * C(5, 0) * F [ 0 ] + F [ 1 ] * C(5, 5) * F [ 5 ] + F [ 1 ] * C(5, 4) * F [ 4 ] + F [ 3 ] * C(4, 0) * F [ 0 ] + F [ 3 ] * C(4, 5) * F [ 5 ] + F [ 3 ] * C(4, 4) * F [ 4 ] + 0.0; + answer(8, 1) = F [ 8 ] * C(0, 5) * F [ 8 ] + F [ 8 ] * C(0, 1) * F [ 1 ] + F [ 8 ] * C(0, 3) * F [ 3 ] + F [ 1 ] * C(5, 5) * F [ 8 ] + F [ 1 ] * C(5, 1) * F [ 1 ] + F [ 1 ] * C(5, 3) * F [ 3 ] + F [ 3 ] * C(4, 5) * F [ 8 ] + F [ 3 ] * C(4, 1) * F [ 1 ] + F [ 3 ] * C(4, 3) * F [ 3 ] + S [ 5 ]; + answer(8, 2) = F [ 8 ] * C(0, 4) * F [ 7 ] + F [ 8 ] * C(0, 3) * F [ 6 ] + F [ 8 ] * C(0, 2) * F [ 2 ] + F [ 1 ] * C(5, 4) * F [ 7 ] + F [ 1 ] * C(5, 3) * F [ 6 ] + F [ 1 ] * C(5, 2) * F [ 2 ] + F [ 3 ] * C(4, 4) * F [ 7 ] + F [ 3 ] * C(4, 3) * F [ 6 ] + F [ 3 ] * C(4, 2) * F [ 2 ] + 0.0; + answer(8, 3) = F [ 8 ] * C(0, 4) * F [ 8 ] + F [ 8 ] * C(0, 3) * F [ 1 ] + F [ 8 ] * C(0, 2) * F [ 3 ] + F [ 1 ] * C(5, 4) * F [ 8 ] + F [ 1 ] * C(5, 3) * F [ 1 ] + F [ 1 ] * C(5, 2) * F [ 3 ] + F [ 3 ] * C(4, 4) * F [ 8 ] + F [ 3 ] * C(4, 3) * F [ 1 ] + F [ 3 ] * C(4, 2) * F [ 3 ] + S [ 4 ]; + answer(8, 4) = F [ 8 ] * C(0, 4) * F [ 0 ] + F [ 8 ] * C(0, 3) * F [ 5 ] + F [ 8 ] * C(0, 2) * F [ 4 ] + F [ 1 ] * C(5, 4) * F [ 0 ] + F [ 1 ] * C(5, 3) * F [ 5 ] + F [ 1 ] * C(5, 2) * F [ 4 ] + F [ 3 ] * C(4, 4) * F [ 0 ] + F [ 3 ] * C(4, 3) * F [ 5 ] + F [ 3 ] * C(4, 2) * F [ 4 ] + 0.0; + answer(8, 5) = F [ 8 ] * C(0, 5) * F [ 0 ] + F [ 8 ] * C(0, 1) * F [ 5 ] + F [ 8 ] * C(0, 3) * F [ 4 ] + F [ 1 ] * C(5, 5) * F [ 0 ] + F [ 1 ] * C(5, 1) * F [ 5 ] + F [ 1 ] * C(5, 3) * F [ 4 ] + F [ 3 ] * C(4, 5) * F [ 0 ] + F [ 3 ] * C(4, 1) * F [ 5 ] + F [ 3 ] * C(4, 3) * F [ 4 ] + 0.0; + answer(8, 6) = F [ 8 ] * C(0, 5) * F [ 7 ] + F [ 8 ] * C(0, 1) * F [ 6 ] + F [ 8 ] * C(0, 3) * F [ 2 ] + F [ 1 ] * C(5, 5) * F [ 7 ] + F [ 1 ] * C(5, 1) * F [ 6 ] + F [ 1 ] * C(5, 3) * F [ 2 ] + F [ 3 ] * C(4, 5) * F [ 7 ] + F [ 3 ] * C(4, 1) * F [ 6 ] + F [ 3 ] * C(4, 3) * F [ 2 ] + 0.0; + answer(8, 7) = F [ 8 ] * C(0, 0) * F [ 7 ] + F [ 8 ] * C(0, 5) * F [ 6 ] + F [ 8 ] * C(0, 4) * F [ 2 ] + F [ 1 ] * C(5, 0) * F [ 7 ] + F [ 1 ] * C(5, 5) * F [ 6 ] + F [ 1 ] * C(5, 4) * F [ 2 ] + F [ 3 ] * C(4, 0) * F [ 7 ] + F [ 3 ] * C(4, 5) * F [ 6 ] + F [ 3 ] * C(4, 4) * F [ 2 ] + 0.0; + answer(8, 8) = F [ 8 ] * C(0, 0) * F [ 8 ] + F [ 8 ] * C(0, 5) * F [ 1 ] + F [ 8 ] * C(0, 4) * F [ 3 ] + F [ 1 ] * C(5, 0) * F [ 8 ] + F [ 1 ] * C(5, 5) * F [ 1 ] + F [ 1 ] * C(5, 4) * F [ 3 ] + F [ 3 ] * C(4, 0) * F [ 8 ] + F [ 3 ] * C(4, 5) * F [ 1 ] + F [ 3 ] * C(4, 4) * F [ 3 ] + S [ 0 ]; #else - ///@todo Experimental - added 110814 by JB - // Conversion expressed in index form. Seems a tiny bit slower than that above but easier to debug. - FloatMatrix I(3, 3); - I.beUnitMatrix(); - - //I_ik * S_jl + F_im F_kn C_mjnl - answer.resize(9, 9); - for ( int i = 1; i <= 3; i++ ) { - for ( int j = 1; j <= 3; j++ ) { - for ( int k = 1; k <= 3; k++ ) { - for ( int l = 1; l <= 3; l++ ) { - for ( int m = 1; m <= 3; m++ ) { - for ( int n = 1; n <= 3; n++ ) { - answer.at( giveVI(i, j), giveVI(k, l) ) += I.at(i, k) * S.at( giveSymVI(j, l) ) + F.at( giveVI(i, m) ) * F.at( giveVI(k, n) ) * C.at( giveSymVI(m, j), giveSymVI(n, l) ); - } + ///@todo Experimental - added 110814 by JB + // Conversion expressed in index form. Seems a tiny bit slower than that above but easier to debug. + auto I = eye< 3 >(); + + //I_ik * S_jl + F_im F_kn C_mjnl + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + for ( int k = 1; k <= 3; k++ ) { + for ( int l = 1; l <= 3; l++ ) { + for ( int m = 1; m <= 3; m++ ) { + for ( int n = 1; n <= 3; n++ ) { + answer.at(giveVI(i, j), giveVI(k, l) ) += I.at(i, k) * S.at(giveSymVI(j, l) ) + F.at(giveVI(i, m) ) * F.at(giveVI(k, n) ) * C.at(giveSymVI(m, j), giveSymVI(n, l) ); } } } } } - -#endif - } else if ( matMode == _PlaneStress ) { - // Save terms associated with H = [du/dx dv/dy du/dy dv/dx] - - answer.resize(4, 4); - answer(0, 0) = F(0) * C(0, 0) * F(0) + F(0) * C(0, 2) * F(2) + F(2) * C(2, 0) * F(0) + F(2) * C(2, 2) * F(2) + S(0); - answer(0, 1) = F(0) * C(0, 2) * F(3) + F(0) * C(0, 1) * F(1) + F(2) * C(2, 2) * F(3) + F(2) * C(2, 1) * F(1) + 0.0; - answer(0, 2) = F(0) * C(0, 2) * F(0) + F(0) * C(0, 1) * F(2) + F(2) * C(2, 2) * F(0) + F(2) * C(2, 1) * F(2) + S(2); - answer(0, 3) = F(0) * C(0, 0) * F(3) + F(0) * C(0, 2) * F(1) + F(2) * C(2, 0) * F(3) + F(2) * C(2, 2) * F(1) + 0.0; - answer(1, 0) = F(3) * C(2, 0) * F(0) + F(3) * C(2, 2) * F(2) + F(1) * C(1, 0) * F(0) + F(1) * C(1, 2) * F(2) + 0.0; - answer(1, 1) = F(3) * C(2, 2) * F(3) + F(3) * C(2, 1) * F(1) + F(1) * C(1, 2) * F(3) + F(1) * C(1, 1) * F(1) + S(1); - answer(1, 2) = F(3) * C(2, 2) * F(0) + F(3) * C(2, 1) * F(2) + F(1) * C(1, 2) * F(0) + F(1) * C(1, 1) * F(2) + 0.0; - answer(1, 3) = F(3) * C(2, 0) * F(3) + F(3) * C(2, 2) * F(1) + F(1) * C(1, 0) * F(3) + F(1) * C(1, 2) * F(1) + S(2); - answer(2, 0) = F(0) * C(2, 0) * F(0) + F(0) * C(2, 2) * F(2) + F(2) * C(1, 0) * F(0) + F(2) * C(1, 2) * F(2) + S(2); - answer(2, 1) = F(0) * C(2, 2) * F(3) + F(0) * C(2, 1) * F(1) + F(2) * C(1, 2) * F(3) + F(2) * C(1, 1) * F(1) + 0.0; - answer(2, 2) = F(0) * C(2, 2) * F(0) + F(0) * C(2, 1) * F(2) + F(2) * C(1, 2) * F(0) + F(2) * C(1, 1) * F(2) + S(1); - answer(2, 3) = F(0) * C(2, 0) * F(3) + F(0) * C(2, 2) * F(1) + F(2) * C(1, 0) * F(3) + F(2) * C(1, 2) * F(1) + 0.0; - answer(3, 0) = F(3) * C(0, 0) * F(0) + F(3) * C(0, 2) * F(2) + F(1) * C(2, 0) * F(0) + F(1) * C(2, 2) * F(2) + 0.0; - answer(3, 1) = F(3) * C(0, 2) * F(3) + F(3) * C(0, 1) * F(1) + F(1) * C(2, 2) * F(3) + F(1) * C(2, 1) * F(1) + S(2); - answer(3, 2) = F(3) * C(0, 2) * F(0) + F(3) * C(0, 1) * F(2) + F(1) * C(2, 2) * F(0) + F(1) * C(2, 1) * F(2) + 0.0; - answer(3, 3) = F(3) * C(0, 0) * F(3) + F(3) * C(0, 2) * F(1) + F(1) * C(2, 0) * F(3) + F(1) * C(2, 2) * F(1) + S(0); - } else if ( matMode == _PlaneStrain ) { - //Save terms associated with H = [du/dx, dv/dy, dw/dz, du/dy, dv/dx] //@todo not fully checked - - answer.resize(5, 5); - answer(0, 0) = F(0) * C(0, 0) * F(0) + F(0) * C(0, 3) * F(3) + F(3) * C(3, 0) * F(0) + F(3) * C(3, 3) * F(3) + S(0); - answer(0, 1) = F(0) * C(0, 3) * F(4) + F(0) * C(0, 1) * F(1) + F(3) * C(3, 3) * F(4) + F(3) * C(3, 1) * F(1) + 0.0; - answer(0, 2) = F(0) * C(0, 2) * F(2) + F(3) * C(3, 2) * F(2) + 0.0; - answer(0, 3) = F(0) * C(0, 3) * F(0) + F(0) * C(0, 1) * F(3) + F(3) * C(3, 3) * F(0) + F(3) * C(3, 1) * F(3) + S(3); - answer(0, 4) = F(0) * C(0, 0) * F(4) + F(0) * C(0, 3) * F(1) + F(3) * C(3, 0) * F(4) + F(3) * C(3, 3) * F(1) + 0.0; - answer(1, 0) = F(4) * C(3, 0) * F(0) + F(4) * C(3, 3) * F(3) + F(1) * C(1, 0) * F(0) + F(1) * C(1, 3) * F(3) + 0.0; - answer(1, 1) = F(4) * C(3, 3) * F(4) + F(4) * C(3, 1) * F(1) + F(1) * C(1, 3) * F(4) + F(1) * C(1, 1) * F(1) + S(1); - answer(1, 2) = F(4) * C(3, 2) * F(2) + F(1) * C(1, 2) * F(2) + 0.0; - answer(1, 3) = F(4) * C(3, 3) * F(0) + F(4) * C(3, 1) * F(3) + F(1) * C(1, 3) * F(0) + F(1) * C(1, 1) * F(3) + 0.0; - answer(1, 4) = F(4) * C(3, 0) * F(4) + F(4) * C(3, 3) * F(1) + F(1) * C(1, 0) * F(4) + F(1) * C(1, 3) * F(1) + S(3); - answer(2, 0) = F(2) * C(2, 0) * F(0) + F(2) * C(2, 3) * F(3) + 0.0; - answer(2, 1) = F(2) * C(2, 3) * F(4) + F(2) * C(2, 1) * F(1) + 0.0; - answer(2, 2) = F(2) * C(2, 2) * F(2) + S(2); - answer(2, 3) = F(2) * C(2, 3) * F(0) + F(2) * C(2, 1) * F(3) + 0.0; - answer(2, 4) = F(2) * C(2, 0) * F(4) + F(2) * C(2, 3) * F(1) + 0.0; - answer(3, 0) = F(0) * C(3, 0) * F(0) + F(0) * C(3, 3) * F(3) + F(3) * C(1, 0) * F(0) + F(3) * C(1, 3) * F(3) + S(3); - answer(3, 1) = F(0) * C(3, 3) * F(4) + F(0) * C(3, 1) * F(1) + F(3) * C(1, 3) * F(4) + F(3) * C(1, 1) * F(1) + 0.0; - answer(3, 2) = F(0) * C(3, 2) * F(2) + F(3) * C(1, 2) * F(2) + 0.0; - answer(3, 3) = F(0) * C(3, 3) * F(0) + F(0) * C(3, 1) * F(3) + F(3) * C(1, 3) * F(0) + F(3) * C(1, 1) * F(3) + S(1); - answer(3, 4) = F(0) * C(3, 0) * F(4) + F(0) * C(3, 3) * F(1) + F(3) * C(1, 0) * F(4) + F(3) * C(1, 3) * F(1) + 0.0; - answer(4, 0) = F(4) * C(0, 0) * F(0) + F(4) * C(0, 3) * F(3) + F(1) * C(3, 0) * F(0) + F(1) * C(3, 3) * F(3) + 0.0; - answer(4, 1) = F(4) * C(0, 3) * F(4) + F(4) * C(0, 1) * F(1) + F(1) * C(3, 3) * F(4) + F(1) * C(3, 1) * F(1) + S(3); - answer(4, 2) = F(4) * C(0, 2) * F(2) + F(1) * C(3, 2) * F(2) + 0.0; - answer(4, 3) = F(4) * C(0, 3) * F(0) + F(4) * C(0, 1) * F(3) + F(1) * C(3, 3) * F(0) + F(1) * C(3, 1) * F(3) + 0.0; - answer(4, 4) = F(4) * C(0, 0) * F(4) + F(4) * C(0, 3) * F(1) + F(1) * C(3, 0) * F(4) + F(1) * C(3, 3) * F(1) + S(0); - } else if ( matMode == _1dMat ) { - //Save terms associated with H = [du/dx] - /// @todo is this really correct?? - - answer.resize(1, 1); - answer(0, 0) = F(0) * C(0, 0) * F(0) + S(0); } -} - -void -StructuralMaterial :: giveEshelbyStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedF, TimeStep *tStep) +#endif + return answer; +} + +FloatMatrixF< 5, 5 > +StructuralMaterial::convert_dSdE_2_dPdF_PlaneStrain(const FloatMatrixF< 4, 4 > &C, const FloatArrayF< 4 > &S, const FloatArrayF< 5 > &F) +{ + //Save terms associated with H = [du/dx, dv/dy, dw/dz, du/dy, dv/dx] //@todo not fully checked + FloatMatrixF< 5, 5 >answer; + answer(0, 0) = F [ 0 ] * C(0, 0) * F [ 0 ] + F [ 0 ] * C(0, 3) * F [ 3 ] + F [ 3 ] * C(3, 0) * F [ 0 ] + F [ 3 ] * C(3, 3) * F [ 3 ] + S [ 0 ]; + answer(0, 1) = F [ 0 ] * C(0, 3) * F [ 4 ] + F [ 0 ] * C(0, 1) * F [ 1 ] + F [ 3 ] * C(3, 3) * F [ 4 ] + F [ 3 ] * C(3, 1) * F [ 1 ] + 0.0; + answer(0, 2) = F [ 0 ] * C(0, 2) * F [ 2 ] + F [ 3 ] * C(3, 2) * F [ 2 ] + 0.0; + answer(0, 3) = F [ 0 ] * C(0, 3) * F [ 0 ] + F [ 0 ] * C(0, 1) * F [ 3 ] + F [ 3 ] * C(3, 3) * F [ 0 ] + F [ 3 ] * C(3, 1) * F [ 3 ] + S [ 3 ]; + answer(0, 4) = F [ 0 ] * C(0, 0) * F [ 4 ] + F [ 0 ] * C(0, 3) * F [ 1 ] + F [ 3 ] * C(3, 0) * F [ 4 ] + F [ 3 ] * C(3, 3) * F [ 1 ] + 0.0; + answer(1, 0) = F [ 4 ] * C(3, 0) * F [ 0 ] + F [ 4 ] * C(3, 3) * F [ 3 ] + F [ 1 ] * C(1, 0) * F [ 0 ] + F [ 1 ] * C(1, 3) * F [ 3 ] + 0.0; + answer(1, 1) = F [ 4 ] * C(3, 3) * F [ 4 ] + F [ 4 ] * C(3, 1) * F [ 1 ] + F [ 1 ] * C(1, 3) * F [ 4 ] + F [ 1 ] * C(1, 1) * F [ 1 ] + S [ 1 ]; + answer(1, 2) = F [ 4 ] * C(3, 2) * F [ 2 ] + F [ 1 ] * C(1, 2) * F [ 2 ] + 0.0; + answer(1, 3) = F [ 4 ] * C(3, 3) * F [ 0 ] + F [ 4 ] * C(3, 1) * F [ 3 ] + F [ 1 ] * C(1, 3) * F [ 0 ] + F [ 1 ] * C(1, 1) * F [ 3 ] + 0.0; + answer(1, 4) = F [ 4 ] * C(3, 0) * F [ 4 ] + F [ 4 ] * C(3, 3) * F [ 1 ] + F [ 1 ] * C(1, 0) * F [ 4 ] + F [ 1 ] * C(1, 3) * F [ 1 ] + S [ 3 ]; + answer(2, 0) = F [ 2 ] * C(2, 0) * F [ 0 ] + F [ 2 ] * C(2, 3) * F [ 3 ] + 0.0; + answer(2, 1) = F [ 2 ] * C(2, 3) * F [ 4 ] + F [ 2 ] * C(2, 1) * F [ 1 ] + 0.0; + answer(2, 2) = F [ 2 ] * C(2, 2) * F [ 2 ] + S [ 2 ]; + answer(2, 3) = F [ 2 ] * C(2, 3) * F [ 0 ] + F [ 2 ] * C(2, 1) * F [ 3 ] + 0.0; + answer(2, 4) = F [ 2 ] * C(2, 0) * F [ 4 ] + F [ 2 ] * C(2, 3) * F [ 1 ] + 0.0; + answer(3, 0) = F [ 0 ] * C(3, 0) * F [ 0 ] + F [ 0 ] * C(3, 3) * F [ 3 ] + F [ 3 ] * C(1, 0) * F [ 0 ] + F [ 3 ] * C(1, 3) * F [ 3 ] + S [ 3 ]; + answer(3, 1) = F [ 0 ] * C(3, 3) * F [ 4 ] + F [ 0 ] * C(3, 1) * F [ 1 ] + F [ 3 ] * C(1, 3) * F [ 4 ] + F [ 3 ] * C(1, 1) * F [ 1 ] + 0.0; + answer(3, 2) = F [ 0 ] * C(3, 2) * F [ 2 ] + F [ 3 ] * C(1, 2) * F [ 2 ] + 0.0; + answer(3, 3) = F [ 0 ] * C(3, 3) * F [ 0 ] + F [ 0 ] * C(3, 1) * F [ 3 ] + F [ 3 ] * C(1, 3) * F [ 0 ] + F [ 3 ] * C(1, 1) * F [ 3 ] + S [ 1 ]; + answer(3, 4) = F [ 0 ] * C(3, 0) * F [ 4 ] + F [ 0 ] * C(3, 3) * F [ 1 ] + F [ 3 ] * C(1, 0) * F [ 4 ] + F [ 3 ] * C(1, 3) * F [ 1 ] + 0.0; + answer(4, 0) = F [ 4 ] * C(0, 0) * F [ 0 ] + F [ 4 ] * C(0, 3) * F [ 3 ] + F [ 1 ] * C(3, 0) * F [ 0 ] + F [ 1 ] * C(3, 3) * F [ 3 ] + 0.0; + answer(4, 1) = F [ 4 ] * C(0, 3) * F [ 4 ] + F [ 4 ] * C(0, 1) * F [ 1 ] + F [ 1 ] * C(3, 3) * F [ 4 ] + F [ 1 ] * C(3, 1) * F [ 1 ] + S [ 3 ]; + answer(4, 2) = F [ 4 ] * C(0, 2) * F [ 2 ] + F [ 1 ] * C(3, 2) * F [ 2 ] + 0.0; + answer(4, 3) = F [ 4 ] * C(0, 3) * F [ 0 ] + F [ 4 ] * C(0, 1) * F [ 3 ] + F [ 1 ] * C(3, 3) * F [ 0 ] + F [ 1 ] * C(3, 1) * F [ 3 ] + 0.0; + answer(4, 4) = F [ 4 ] * C(0, 0) * F [ 4 ] + F [ 4 ] * C(0, 3) * F [ 1 ] + F [ 1 ] * C(3, 0) * F [ 4 ] + F [ 1 ] * C(3, 3) * F [ 1 ] + S [ 0 ]; + return answer; +} + +FloatMatrixF< 4, 4 > +StructuralMaterial::convert_dSdE_2_dPdF_PlaneStress(const FloatMatrixF< 3, 3 > &C, const FloatArrayF< 3 > &S, const FloatArrayF< 4 > &F) +{ + // Save terms associated with H = [du/dx dv/dy du/dy dv/dx] + FloatMatrixF< 4, 4 >answer; + answer(0, 0) = F [ 0 ] * C(0, 0) * F [ 0 ] + F [ 0 ] * C(0, 2) * F [ 2 ] + F [ 2 ] * C(2, 0) * F [ 0 ] + F [ 2 ] * C(2, 2) * F [ 2 ] + S [ 0 ]; + answer(0, 1) = F [ 0 ] * C(0, 2) * F [ 3 ] + F [ 0 ] * C(0, 1) * F [ 1 ] + F [ 2 ] * C(2, 2) * F [ 3 ] + F [ 2 ] * C(2, 1) * F [ 1 ] + 0.0; + answer(0, 2) = F [ 0 ] * C(0, 2) * F [ 0 ] + F [ 0 ] * C(0, 1) * F [ 2 ] + F [ 2 ] * C(2, 2) * F [ 0 ] + F [ 2 ] * C(2, 1) * F [ 2 ] + S [ 2 ]; + answer(0, 3) = F [ 0 ] * C(0, 0) * F [ 3 ] + F [ 0 ] * C(0, 2) * F [ 1 ] + F [ 2 ] * C(2, 0) * F [ 3 ] + F [ 2 ] * C(2, 2) * F [ 1 ] + 0.0; + answer(1, 0) = F [ 3 ] * C(2, 0) * F [ 0 ] + F [ 3 ] * C(2, 2) * F [ 2 ] + F [ 1 ] * C(1, 0) * F [ 0 ] + F [ 1 ] * C(1, 2) * F [ 2 ] + 0.0; + answer(1, 1) = F [ 3 ] * C(2, 2) * F [ 3 ] + F [ 3 ] * C(2, 1) * F [ 1 ] + F [ 1 ] * C(1, 2) * F [ 3 ] + F [ 1 ] * C(1, 1) * F [ 1 ] + S [ 1 ]; + answer(1, 2) = F [ 3 ] * C(2, 2) * F [ 0 ] + F [ 3 ] * C(2, 1) * F [ 2 ] + F [ 1 ] * C(1, 2) * F [ 0 ] + F [ 1 ] * C(1, 1) * F [ 2 ] + 0.0; + answer(1, 3) = F [ 3 ] * C(2, 0) * F [ 3 ] + F [ 3 ] * C(2, 2) * F [ 1 ] + F [ 1 ] * C(1, 0) * F [ 3 ] + F [ 1 ] * C(1, 2) * F [ 1 ] + S [ 2 ]; + answer(2, 0) = F [ 0 ] * C(2, 0) * F [ 0 ] + F [ 0 ] * C(2, 2) * F [ 2 ] + F [ 2 ] * C(1, 0) * F [ 0 ] + F [ 2 ] * C(1, 2) * F [ 2 ] + S [ 2 ]; + answer(2, 1) = F [ 0 ] * C(2, 2) * F [ 3 ] + F [ 0 ] * C(2, 1) * F [ 1 ] + F [ 2 ] * C(1, 2) * F [ 3 ] + F [ 2 ] * C(1, 1) * F [ 1 ] + 0.0; + answer(2, 2) = F [ 0 ] * C(2, 2) * F [ 0 ] + F [ 0 ] * C(2, 1) * F [ 2 ] + F [ 2 ] * C(1, 2) * F [ 0 ] + F [ 2 ] * C(1, 1) * F [ 2 ] + S [ 1 ]; + answer(2, 3) = F [ 0 ] * C(2, 0) * F [ 3 ] + F [ 0 ] * C(2, 2) * F [ 1 ] + F [ 2 ] * C(1, 0) * F [ 3 ] + F [ 2 ] * C(1, 2) * F [ 1 ] + 0.0; + answer(3, 0) = F [ 3 ] * C(0, 0) * F [ 0 ] + F [ 3 ] * C(0, 2) * F [ 2 ] + F [ 1 ] * C(2, 0) * F [ 0 ] + F [ 1 ] * C(2, 2) * F [ 2 ] + 0.0; + answer(3, 1) = F [ 3 ] * C(0, 2) * F [ 3 ] + F [ 3 ] * C(0, 1) * F [ 1 ] + F [ 1 ] * C(2, 2) * F [ 3 ] + F [ 1 ] * C(2, 1) * F [ 1 ] + S [ 2 ]; + answer(3, 2) = F [ 3 ] * C(0, 2) * F [ 0 ] + F [ 3 ] * C(0, 1) * F [ 2 ] + F [ 1 ] * C(2, 2) * F [ 0 ] + F [ 1 ] * C(2, 1) * F [ 2 ] + 0.0; + answer(3, 3) = F [ 3 ] * C(0, 0) * F [ 3 ] + F [ 3 ] * C(0, 2) * F [ 1 ] + F [ 1 ] * C(2, 0) * F [ 3 ] + F [ 1 ] * C(2, 2) * F [ 1 ] + S [ 0 ]; + return answer; +} + +FloatMatrixF< 1, 1 > +StructuralMaterial::convert_dSdE_2_dPdF_1D(const FloatMatrixF< 1, 1 > &C, const FloatArrayF< 1 > &S, const FloatArrayF< 1 > &F) +{ + //Save terms associated with H = [du/dx] + /// @todo is this really correct?? + FloatMatrixF< 1, 1 >answer; + answer(0, 0) = F [ 0 ] * C(0, 0) * F [ 0 ] + S [ 0 ]; + return answer; +} + + +void +StructuralMaterial::giveEshelbyStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedF, TimeStep *tStep) { OOFEM_ERROR("not implemented ") } -void -StructuralMaterial :: give_dPdF_from(const FloatMatrix &dSdE, FloatMatrix &answer, GaussPoint *gp) -{ - // Default implementation for converting dSdE to dPdF. This includes updating the - // state variables of P and F. - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - FloatArray reducedvF, reducedvP, reducedvS; - const FloatArray &vF = status->giveTempFVector(); - const FloatArray &vP = status->giveTempPVector(); - const FloatArray &vS = status->giveTempStressVector(); - - MaterialMode matMode = gp->giveMaterialMode(); - ///@todo This is unnecessary and inefficient, just a hack for now (it will be changed when everything is in working order!) - StructuralMaterial :: giveReducedVectorForm(reducedvF, vF, matMode); - StructuralMaterial :: giveReducedVectorForm(reducedvP, vP, matMode); - StructuralMaterial :: giveReducedSymVectorForm(reducedvS, vS, matMode); - //this->convert_P_2_S(reducedvS, reducedvP, reducedvF, matMode); - this->convert_dSdE_2_dPdF(answer, dSdE, reducedvS, reducedvF, matMode); -} - void -StructuralMaterial :: giveStiffnessMatrix(FloatMatrix &answer, - MatResponseMode rMode, - GaussPoint *gp, TimeStep *tStep) +StructuralMaterial::giveStiffnessMatrix(FloatMatrix &answer, + MatResponseMode rMode, + GaussPoint *gp, TimeStep *tStep) // // Returns characteristic material stiffness matrix of the receiver // @@ -645,92 +614,111 @@ StructuralMaterial :: giveStiffnessMatrix(FloatMatrix &answer, MaterialMode mMode = gp->giveMaterialMode(); switch ( mMode ) { case _3dMat: - this->give3dMaterialStiffnessMatrix(answer, rMode, gp, tStep); + answer = this->give3dMaterialStiffnessMatrix(rMode, gp, tStep); break; case _PlaneStress: - this->givePlaneStressStiffMtrx(answer, rMode, gp, tStep); + answer = this->givePlaneStressStiffMtrx(rMode, gp, tStep); break; case _PlaneStrain: - this->givePlaneStrainStiffMtrx(answer, rMode, gp, tStep); + answer = this->givePlaneStrainStiffMtrx(rMode, gp, tStep); break; case _1dMat: - this->give1dStressStiffMtrx(answer, rMode, gp, tStep); + answer = this->give1dStressStiffMtrx(rMode, gp, tStep); break; - case _PlateLayer: - this->givePlateLayerStiffMtrx(answer, rMode, gp, tStep); + answer = this->givePlateLayerStiffMtrx(rMode, gp, tStep); break; case _2dBeamLayer: - this->give2dBeamLayerStiffMtrx(answer, rMode, gp, tStep); + answer = this->give2dBeamLayerStiffMtrx(rMode, gp, tStep); break; case _Fiber: - this->giveFiberStiffMtrx(answer, rMode, gp, tStep); + answer = this->giveFiberStiffMtrx(rMode, gp, tStep); break; case _Warping: - answer.resize(2, 2); - answer.beUnitMatrix(); + answer = eye< 2 >(); break; - case _2dLattice: - this->give2dLatticeStiffMtrx(answer, rMode, gp, tStep); + default: + OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mMode) ); + } +} + + + + +void +StructuralMaterial::giveStiffnessMatrix_dPdF(FloatMatrix &answer, + MatResponseMode rMode, + GaussPoint *gp, TimeStep *tStep) +// +// Returns characteristic material stiffness matrix of the receiver +// +{ + MaterialMode mMode = gp->giveMaterialMode(); + switch ( mMode ) { + case _3dMat: + answer = this->give3dMaterialStiffnessMatrix_dPdF(rMode, gp, tStep); break; - case _3dLattice: - this->give3dLatticeStiffMtrx(answer, rMode, gp, tStep); + case _PlaneStress: + answer = this->givePlaneStressStiffnessMatrix_dPdF(rMode, gp, tStep); + break; + case _PlaneStrain: + answer = this->givePlaneStrainStiffnessMatrix_dPdF(rMode, gp, tStep); + break; + case _1dMat: + answer = this->give1dStressStiffnessMatrix_dPdF(rMode, gp, tStep); break; - default: - OOFEM_ERROR( "unknown mode (%s)", __MaterialModeToString(mMode) ); + OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mMode) ); } } -void -StructuralMaterial :: give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) + +FloatMatrixF< 9, 9 > +StructuralMaterial::give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, + GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix dSdE; - this->give3dMaterialStiffnessMatrix(dSdE, mode, gp, tStep); - this->give_dPdF_from(dSdE, answer, gp); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + const auto &vF = status->giveTempFVector(); + const auto &vS = status->giveTempStressVector(); + auto dSdE = this->give3dMaterialStiffnessMatrix(mode, gp, tStep); + return convert_dSdE_2_dPdF_3D(dSdE, vS, vF); } -void -StructuralMaterial :: givePlaneStressStiffMtrx_dPdF(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 5, 5 > +StructuralMaterial::givePlaneStrainStiffnessMatrix_dPdF(MatResponseMode mode, + GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix dSdE; - this->givePlaneStressStiffMtrx(dSdE, mode, gp, tStep); - this->give_dPdF_from(dSdE, answer, gp); + auto m3d = this->give3dMaterialStiffnessMatrix_dPdF(mode, gp, tStep); + return m3d({ 0, 1, 2, 5, 8 }, { 0, 1, 2, 5, 8 }); } -void -StructuralMaterial :: givePlaneStrainStiffMtrx_dPdF(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 4, 4 > +StructuralMaterial::givePlaneStressStiffnessMatrix_dPdF(MatResponseMode mode, + GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix dSdE; - this->givePlaneStrainStiffMtrx(dSdE, mode, gp, tStep); - this->give_dPdF_from(dSdE, answer, gp); + auto m3d = this->give3dMaterialStiffnessMatrix_dPdF(mode, gp, tStep); + auto c3d = inv(m3d); + return inv(c3d({ 0, 1, 5, 8 }, { 0, 1, 5, 8 }) ); } -void -StructuralMaterial :: give1dStressStiffMtrx_dPdF(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) +FloatMatrixF< 1, 1 > +StructuralMaterial::give1dStressStiffnessMatrix_dPdF(MatResponseMode mode, + GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix dSdE; - this->give1dStressStiffMtrx(dSdE, mode, gp, tStep); - this->give_dPdF_from(dSdE, answer, gp); + auto m3d = this->give3dMaterialStiffnessMatrix(mode, gp, tStep); + auto c3d = inv(m3d); + return { 1. / c3d.at(1, 1) }; } void -StructuralMaterial :: give3dMaterialStiffnessMatrix_dCde(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) +StructuralMaterial::give3dMaterialStiffnessMatrix_dCde(FloatMatrix &answer, + MatResponseMode mode, + GaussPoint *gp, TimeStep *tStep) { ///@todo what should be default implementaiton? OOFEM_ERROR("There is no default implementation"); @@ -738,59 +726,43 @@ StructuralMaterial :: give3dMaterialStiffnessMatrix_dCde(FloatMatrix &answer, void -StructuralMaterial :: givePlaneStressStiffMtrx_dCde(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) +StructuralMaterial::givePlaneStressStiffMtrx_dCde(FloatMatrix &answer, + MatResponseMode mode, + GaussPoint *gp, TimeStep *tStep) { OOFEM_ERROR("There is no default implementation"); } void -StructuralMaterial :: givePlaneStrainStiffMtrx_dCde(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) +StructuralMaterial::givePlaneStrainStiffMtrx_dCde(FloatMatrix &answer, + MatResponseMode mode, + GaussPoint *gp, TimeStep *tStep) { OOFEM_ERROR("There is no default implementation"); } void -StructuralMaterial :: give1dStressStiffMtrx_dCde(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep) +StructuralMaterial::give1dStressStiffMtrx_dCde(FloatMatrix &answer, + MatResponseMode mode, + GaussPoint *gp, TimeStep *tStep) { OOFEM_ERROR("There is no default implementation"); } void -StructuralMaterial :: giveStressDependentPartOfStrainVector(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrainVector, - TimeStep *tStep, ValueModeType mode) +StructuralMaterial::giveStressDependentPartOfStrainVector(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrainVector, + TimeStep *tStep, ValueModeType mode) const { /* * This functions subtract from reducedStrainVector its stress independent part * caused by temperature, shrinkage and possibly by other phenomena. */ - FloatArray epsilonTemperature; - - answer = reducedStrainVector; - this->computeStressIndependentStrainVector(epsilonTemperature, gp, tStep, mode); - if ( epsilonTemperature.giveSize() ) { - answer.subtract(epsilonTemperature); - } -} - -void -StructuralMaterial :: giveStressDependentPartOfStrainVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrainVector, - TimeStep *tStep, ValueModeType mode) -{ - FloatArray epsilonTemperature; - answer = reducedStrainVector; - this->computeStressIndependentStrainVector_3d(epsilonTemperature, gp, tStep, mode); + auto epsilonTemperature = this->computeStressIndependentStrainVector(gp, tStep, mode); if ( epsilonTemperature.giveSize() ) { answer.subtract(epsilonTemperature); } @@ -798,37 +770,37 @@ StructuralMaterial :: giveStressDependentPartOfStrainVector_3d(FloatArray &answe int -StructuralMaterial :: giveSizeOfVoigtSymVector(MaterialMode mode) +StructuralMaterial::giveSizeOfVoigtSymVector(MaterialMode mode) { IntArray indx; - StructuralMaterial :: giveVoigtSymVectorMask(indx, mode); + StructuralMaterial::giveVoigtSymVectorMask(indx, mode); return indx.giveSize(); } int -StructuralMaterial :: giveSizeOfVoigtVector(MaterialMode mode) +StructuralMaterial::giveSizeOfVoigtVector(MaterialMode mode) { IntArray indx; - StructuralMaterial :: giveVoigtVectorMask(indx, mode); + StructuralMaterial::giveVoigtVectorMask(indx, mode); return indx.giveSize(); } void -StructuralMaterial :: giveInvertedVoigtVectorMask(IntArray &answer, MaterialMode mmode) +StructuralMaterial::giveInvertedVoigtVectorMask(IntArray &answer, MaterialMode mmode) { IntArray mask; - answer.resize( StructuralMaterial :: giveVoigtSymVectorMask(mask, mmode) ); + answer.resize(StructuralMaterial::giveVoigtSymVectorMask(mask, mmode) ); answer.zero(); for ( int i = 1; i <= mask.giveSize(); i++ ) { - answer.at( mask.at(i) ) = i; + answer.at(mask.at(i) ) = i; } } int -StructuralMaterial :: giveVoigtSymVectorMask(IntArray &answer, MaterialMode mmode) +StructuralMaterial::giveVoigtSymVectorMask(IntArray &answer, MaterialMode mmode) { // The same as giveVoigtVectorMask but returns a mask corresponding to a symmetric // second order tensor. @@ -924,6 +896,10 @@ StructuralMaterial :: giveVoigtSymVectorMask(IntArray &answer, MaterialMode mmod answer.enumerate(8); return 8; + case _3dShellRot: + answer.enumerate(9); + return 9; + case _PlaneStressRot: answer = { 1, 2, 6, 7 @@ -948,12 +924,8 @@ StructuralMaterial :: giveVoigtSymVectorMask(IntArray &answer, MaterialMode mmod }; return 3; + case _1dLattice: case _2dLattice: - answer = { - 1, 2, 3 - }; - return 3; - case _3dLattice: answer = { 1, 2, 3, 4, 5, 6 @@ -976,8 +948,9 @@ StructuralMaterial :: giveVoigtSymVectorMask(IntArray &answer, MaterialMode mmod 1, 5, 6, 7, 8, 9 }; return 12; + #endif - + case _Unknown: answer.clear(); return 0; @@ -989,7 +962,7 @@ StructuralMaterial :: giveVoigtSymVectorMask(IntArray &answer, MaterialMode mmod int -StructuralMaterial :: giveVoigtVectorMask(IntArray &answer, MaterialMode mmode) +StructuralMaterial::giveVoigtVectorMask(IntArray &answer, MaterialMode mmode) { // Returns a mask of the vector indices corresponding to components in a general // (non-symmetric) second order tensor of some stress/strain/deformation measure that @@ -1038,230 +1011,86 @@ StructuralMaterial :: giveVoigtVectorMask(IntArray &answer, MaterialMode mmode) } -void -StructuralMaterial :: givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -// -// returns Mat stiffness for PlaneStress -// -{ - FloatMatrix m3d, invMat3d, invAnswer; - - this->give3dMaterialStiffnessMatrix(m3d, mode, gp, tStep); - - invMat3d.beInverseOf(m3d); - - invAnswer.resize(3, 3); - //invAnswer.beSubMatrixOf(invMat3d, indx, indx); - - invAnswer.at(1, 1) = invMat3d.at(1, 1); - invAnswer.at(1, 2) = invMat3d.at(1, 2); - invAnswer.at(1, 3) = invMat3d.at(1, 6); - - invAnswer.at(2, 1) = invMat3d.at(2, 1); - invAnswer.at(2, 2) = invMat3d.at(2, 2); - invAnswer.at(2, 3) = invMat3d.at(2, 6); - - invAnswer.at(3, 1) = invMat3d.at(6, 1); - invAnswer.at(3, 2) = invMat3d.at(6, 2); - invAnswer.at(3, 3) = invMat3d.at(6, 6); - - answer.beInverseOf(invAnswer); -} - -void -StructuralMaterial :: givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -// -// return material stiffness matrix for PlaneStrain mode -// +FloatMatrixF< 3, 3 > +StructuralMaterial::givePlaneStressStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const { - FloatMatrix m3d; - - this->give3dMaterialStiffnessMatrix(m3d, mode, gp, tStep); - - answer.resize(4, 4); - answer.zero(); - //answer.beSubMatrixOf(m3d, indx, indx); - - answer.at(1, 1) = m3d.at(1, 1); - answer.at(1, 2) = m3d.at(1, 2); - answer.at(1, 4) = m3d.at(1, 6); - - answer.at(2, 1) = m3d.at(2, 1); - answer.at(2, 2) = m3d.at(2, 2); - answer.at(2, 4) = m3d.at(2, 6); - - answer.at(3, 1) = m3d.at(3, 1); - answer.at(3, 2) = m3d.at(3, 2); - answer.at(3, 4) = m3d.at(3, 6); - - answer.at(4, 1) = m3d.at(6, 1); - answer.at(4, 2) = m3d.at(6, 2); - answer.at(4, 4) = m3d.at(6, 6); + auto m3d = this->give3dMaterialStiffnessMatrix(mode, gp, tStep); + auto c3d = inv(m3d); + return inv(c3d({ 0, 1, 5 }, { 0, 1, 5 }) ); } -void -StructuralMaterial :: give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -// -// return material stiffness matrix for 1d stress strain mode -// +FloatMatrixF< 4, 4 > +StructuralMaterial::givePlaneStrainStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const { - FloatMatrix m3d, invMat3d; - double val11; - - this->give3dMaterialStiffnessMatrix(m3d, mode, gp, tStep); - - invMat3d.beInverseOf(m3d); - val11 = invMat3d.at(1, 1); - answer.resize(1, 1); - answer.at(1, 1) = 1. / val11; + auto m3d = this->give3dMaterialStiffnessMatrix(mode, gp, tStep); + return m3d({ 0, 1, 2, 5 }, { 0, 1, 2, 5 }); } - -void -StructuralMaterial :: give2dBeamLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -// -// return material stiffness matrix for2dBeamLayer mode -// +FloatMatrixF< 1, 1 > +StructuralMaterial::give1dStressStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const { - FloatMatrix m3d, invMat3d, invMatLayer(2, 2); - - this->give3dMaterialStiffnessMatrix(m3d, mode, gp, tStep); - - invMat3d.beInverseOf(m3d); - - invMatLayer.at(1, 1) = invMat3d.at(1, 1); - invMatLayer.at(1, 2) = invMat3d.at(1, 5); - invMatLayer.at(2, 1) = invMat3d.at(5, 1); - invMatLayer.at(2, 2) = invMat3d.at(5, 5); - - answer.beInverseOf(invMatLayer); + auto m3d = this->give3dMaterialStiffnessMatrix(mode, gp, tStep); + auto c3d = inv(m3d); + return { + 1. / c3d.at(1, 1) + }; } -void -StructuralMaterial :: givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -// -// return material stiffness matrix for 2dPlateLayer -// +FloatMatrixF< 2, 2 > +StructuralMaterial::give2dBeamLayerStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const { - FloatMatrix m3d, invMat3d, invMatLayer(5, 5); - - this->give3dMaterialStiffnessMatrix(m3d, mode, gp, tStep); - - invMat3d.beInverseOf(m3d); - //invMatLayer.beSubMatrixOf(invMat3d, indx, indx); - - for ( int i = 1; i <= 2; i++ ) { - for ( int j = 1; j <= 2; j++ ) { - invMatLayer.at(i, j) = invMat3d.at(i, j); - } - } - - for ( int i = 4; i <= 6; i++ ) { - for ( int j = 4; j <= 6; j++ ) { - invMatLayer.at(i - 1, j - 1) = invMat3d.at(i, j); - } - } - - for ( int i = 1; i <= 2; i++ ) { - for ( int j = 4; j <= 6; j++ ) { - invMatLayer.at(i, j - 1) = invMat3d.at(i, j); - invMatLayer.at(j - 1, i) = invMat3d.at(j, i); - } - } - - answer.beInverseOf(invMatLayer); + auto m3d = this->give3dMaterialStiffnessMatrix(mode, gp, tStep); + auto c3d = inv(m3d); + return inv(c3d({ 0, 4 }, { 0, 4 }) ); } -void -StructuralMaterial :: giveFiberStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -// -// return material stiffness matrix for 2dPlateLayer -// -{ - FloatMatrix m3d, invMat3d, invMatLayer(3, 3); - - this->give3dMaterialStiffnessMatrix(m3d, mode, gp, tStep); - invMat3d.beInverseOf(m3d); - - invMatLayer.at(1, 1) = invMat3d.at(1, 1); - invMatLayer.at(1, 2) = invMat3d.at(1, 5); - invMatLayer.at(1, 3) = invMat3d.at(1, 6); - invMatLayer.at(2, 1) = invMat3d.at(5, 1); - invMatLayer.at(2, 2) = invMat3d.at(5, 5); - invMatLayer.at(2, 3) = invMat3d.at(5, 6); - invMatLayer.at(3, 1) = invMat3d.at(6, 1); - invMatLayer.at(3, 2) = invMat3d.at(6, 5); - invMatLayer.at(3, 3) = invMat3d.at(6, 6); - - answer.beInverseOf(invMatLayer); -} - -void -StructuralMaterial :: give2dLatticeStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -// -// return material stiffness matrix for 2dlattice -// +FloatMatrixF< 5, 5 > +StructuralMaterial::givePlateLayerStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const { - OOFEM_ERROR("No general implementation provided"); + auto m3d = this->give3dMaterialStiffnessMatrix(mode, gp, tStep); + auto c3d = inv(m3d); + return inv(c3d({ 0, 1, 3, 4, 5 }, { 0, 1, 3, 4, 5 }) ); } -void -StructuralMaterial :: give3dLatticeStiffMtrx(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -// -// return material stiffness matrix for 2dlattice -// +FloatMatrixF< 3, 3 > +StructuralMaterial::giveFiberStiffMtrx(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const { - OOFEM_ERROR("No general implementation provided"); + auto m3d = this->give3dMaterialStiffnessMatrix(mode, gp, tStep); + auto c3d = inv(m3d); + return inv(c3d({ 0, 4, 5 }, { 0, 4, 5 }) ); } -void -StructuralMaterial :: give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF< 3, 3 > +StructuralMaterial::give2dPlateSubSoilStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("No general implementation provided"); + return FloatMatrixF< 3, 3 >(); } -void -StructuralMaterial :: give3dBeamSubSoilStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF< 6, 6 > +StructuralMaterial::give3dBeamSubSoilStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("No general implementation provided"); + return FloatMatrixF< 6, 6 >(); } - - - void -StructuralMaterial :: computePrincipalValues(FloatArray &answer, const FloatArray &s, stressStrainPrincMode mode) +StructuralMaterial::computePrincipalValues(FloatArray &answer, const FloatArray &s, stressStrainPrincMode mode) // // This function computes the principal values of strains or stresses. // Strains/stresses are stored in vector form in array s. @@ -1303,7 +1132,7 @@ StructuralMaterial :: computePrincipalValues(FloatArray &answer, const FloatArra answer.resize(size - 1); for ( int i = 1; i <= size; i++ ) { - if ( fabs( s.at(i) ) > 1.e-20 ) { + if ( fabs(s.at(i) ) > 1.e-20 ) { nonzeroFlag = 1; } } @@ -1338,7 +1167,7 @@ StructuralMaterial :: computePrincipalValues(FloatArray &answer, const FloatArra double I1 = 0.0, I2 = 0.0, I3 = 0.0, help, s1, s2, s3; for ( int i = 1; i <= size; i++ ) { - if ( fabs( s.at(i) ) > 1.e-20 ) { + if ( fabs(s.at(i) ) > 1.e-20 ) { nonzeroFlag = 1; } } @@ -1381,7 +1210,7 @@ StructuralMaterial :: computePrincipalValues(FloatArray &answer, const FloatArra * This allows to overcome various rounding errors when solving general cubic equation. */ int n; - if ( solve ){ + if ( solve ) { cubic3r( ( double ) -1., I1, -I2, I3, & s1, & s2, & s3, & n ); if ( n > 0 ) { answer.at(1) = s1; @@ -1397,16 +1226,15 @@ StructuralMaterial :: computePrincipalValues(FloatArray &answer, const FloatArra #if 0 //Check NaN - if (answer.at(1) != answer.at(1)) { + if ( answer.at(1) != answer.at(1) ) { s.pY(); printf("%.10e %.10e %.10e\n", I1, I2, I3); exit(0); } #endif } - } - + //sort the results for ( int i = 1; i < answer.giveSize(); i++ ) { for ( int j = 1; j < answer.giveSize(); j++ ) { @@ -1419,8 +1247,80 @@ StructuralMaterial :: computePrincipalValues(FloatArray &answer, const FloatArra } } + +FloatArrayF< 3 > +StructuralMaterial::computePrincipalValues(const FloatMatrixF< 3, 3 > &s) +{ + double I1 = s(0, 0) + s(1, 1) + s(2, 2); + double I2 = s(0, 0) * s(1, 1) + s(1, 1) * s(2, 2) + s(2, 2) * s(0, 0) - + ( s(0, 1) * s(1, 0) + s(0, 2) * s(2, 0) + s(1, 2) * s(2, 1) ); + double I3 = s(0, 0) * s(1, 1) * s(2, 2) + s(0, 1) * s(0, 2) * s(1, 2) + s(1, 0) * s(2, 0) * s(2, 1) - + ( s(0, 0) * s(1, 2) * s(2, 1) + s(1, 1) * s(0, 2) * s(2, 0) + s(2, 2) * s(0, 1) * s(1, 0) ); + + return computePrincipalValues(I1, I2, I3); +} + + +FloatArrayF< 3 > +StructuralMaterial::computePrincipalValues(double I1, double I2, double I3) +{ + double CUBIC_ZERO = 1e-100; + double q = ( I1 * I1 - 3.0 * I2 ) / 9.0; + double r = ( -2.0 * I1 * I1 * I1 + 9.0 * I1 * I2 - 27.0 * I3 ) / 54.0; + double a3 = I1 / 3.0; + + //Hydrostatic case, in such a case q=r=0 + if ( ( fabs(q) < CUBIC_ZERO ) && ( fabs(r) < CUBIC_ZERO ) ) { + return { + a3, a3, a3 + }; + } + + // three real roots (clamping to prevent rounding errors + double help = clamp(r / sqrt(q * q * q), -1., 1.); + double phi = acos(help) / 3.0; + double p = 2.0 * sqrt(q); + + FloatArrayF< 3 >v = { + a3 - p * cos(phi - 2. * M_PI / 3.), + a3 - p * cos(phi), + a3 - p * cos(phi + 2. * M_PI / 3.), + }; + if ( v [ 0 ] > v [ 1 ] ) { + std::swap(v [ 0 ], v [ 1 ]); + } + if ( v [ 1 ] > v [ 2 ] ) { + std::swap(v [ 1 ], v [ 2 ]); + } + if ( v [ 0 ] > v [ 1 ] ) { + std::swap(v [ 0 ], v [ 1 ]); + } + return v; +} + + +std::pair< FloatArrayF< 3 >, FloatMatrixF< 3, 3 > > +StructuralMaterial::computePrincipalValDir(const FloatMatrixF< 3, 3 > &s) +{ + //auto [eigVal, eigVec] = eig(s, 10); + auto tmp = eig(s, 10); + // Sort by largest eigenvalue + for ( int ii = 0; ii < 2; ii++ ) { + for ( int jj = 0; jj < 2; jj++ ) { + if ( tmp.first [ jj + 1 ] > tmp.first [ jj ] ) { + std::swap(tmp.first [ jj ], tmp.first [ jj + 1 ]); + for ( int kk = 0; kk < 3; kk++ ) { + std::swap(tmp.second(kk, jj), tmp.second(kk, jj + 1) ); + } + } + } + } + return tmp; +} + + void -StructuralMaterial :: computePrincipalValDir(FloatArray &answer, FloatMatrix &dir, const FloatArray &s, stressStrainPrincMode mode) +StructuralMaterial::computePrincipalValDir(FloatArray &answer, FloatMatrix &dir, const FloatArray &s, stressStrainPrincMode mode) // // This function computes the principal values & directions corresponding to principal values // of strains or streses. @@ -1473,7 +1373,7 @@ StructuralMaterial :: computePrincipalValDir(FloatArray &answer, FloatMatrix &di dir.resize(2, 2); for ( int i = 1; i <= size; i++ ) { - if ( fabs( s.at(i) ) > 1.e-20 ) { + if ( fabs(s.at(i) ) > 1.e-20 ) { nonzeroFlag = 1; } } @@ -1503,7 +1403,7 @@ StructuralMaterial :: computePrincipalValDir(FloatArray &answer, FloatMatrix &di dir.resize(3, 3); for ( int i = 1; i <= size; i++ ) { - if ( fabs( s.at(i) ) > 1.e-20 ) { + if ( fabs(s.at(i) ) > 1.e-20 ) { nonzeroFlag = 1; } } @@ -1571,147 +1471,158 @@ StructuralMaterial :: computePrincipalValDir(FloatArray &answer, FloatMatrix &di } -double -StructuralMaterial :: computeDeviatoricVolumetricSplit(FloatArray &dev, const FloatArray &s) +std::pair< FloatArrayF< 6 >, double > +StructuralMaterial::computeDeviatoricVolumetricSplit(const FloatArrayF< 6 > &s) { - double vol = s[0] + s[1] + s[2]; + double vol = s [ 0 ] + s [ 1 ] + s [ 2 ]; double mean = vol / 3.0; - dev = s; + auto dev = s; dev.at(1) -= mean; dev.at(2) -= mean; dev.at(3) -= mean; - return mean; + return { + dev, mean + }; } -void -StructuralMaterial :: computeDeviatoricVolumetricSum(FloatArray &s, const FloatArray &dev, double mean) +FloatArrayF< 6 > +StructuralMaterial::computeDeviator(const FloatArrayF< 6 > &s) { - s = dev; - s[0] += mean; - s[1] += mean; - s[2] += mean; + double vol = s [ 0 ] + s [ 1 ] + s [ 2 ]; + double mean = vol / 3.0; + FloatArrayF< 6 >dev = s; + dev.at(1) -= mean; + dev.at(2) -= mean; + dev.at(3) -= mean; + return dev; } -void -StructuralMaterial :: applyDeviatoricElasticCompliance(FloatArray &strain, const FloatArray &stress, double EModulus, double nu) +FloatArrayF< 6 > +StructuralMaterial::computeDeviatoricVolumetricSum(const FloatArrayF< 6 > &dev, double mean) { - applyDeviatoricElasticCompliance( strain, stress, EModulus / 2. / ( 1. + nu ) ); + auto s = dev; + s [ 0 ] += mean; + s [ 1 ] += mean; + s [ 2 ] += mean; + return s; } -void -StructuralMaterial :: applyDeviatoricElasticCompliance(FloatArray &strain, const FloatArray &stress, double GModulus) +FloatArrayF< 6 > +StructuralMaterial::applyDeviatoricElasticCompliance(const FloatArrayF< 6 > &stress, double EModulus, double nu) +{ + return applyDeviatoricElasticCompliance(stress, EModulus / 2. / ( 1. + nu ) ); +} + +FloatArrayF< 6 > +StructuralMaterial::applyDeviatoricElasticCompliance(const FloatArrayF< 6 > &stress, double GModulus) { - strain.resize(6); - strain[0] = 1. / ( 2. * GModulus ) * stress [ 0 ]; - strain[1] = 1. / ( 2. * GModulus ) * stress [ 1 ]; - strain[2] = 1. / ( 2. * GModulus ) * stress [ 2 ]; - strain[3] = 1. / GModulus * stress [ 3 ]; - strain[4] = 1. / GModulus * stress [ 4 ]; - strain[5] = 1. / GModulus * stress [ 5 ]; + return { + 1. / ( 2. * GModulus ) * stress [ 0 ], + 1. / ( 2. * GModulus ) * stress [ 1 ], + 1. / ( 2. * GModulus ) * stress [ 2 ], + 1. / GModulus * stress [ 3 ], + 1. / GModulus * stress [ 4 ], + 1. / GModulus * stress [ 5 ], + }; } -void -StructuralMaterial :: applyDeviatoricElasticStiffness(FloatArray &stress, const FloatArray &strain, double EModulus, double nu) +FloatArrayF< 6 > +StructuralMaterial::applyDeviatoricElasticStiffness(const FloatArrayF< 6 > &strain, double EModulus, double nu) { - applyDeviatoricElasticStiffness( stress, strain, EModulus / ( 2. * ( 1. + nu ) ) ); + return applyDeviatoricElasticStiffness(strain, EModulus / ( 2. * ( 1. + nu ) ) ); } -void -StructuralMaterial :: applyDeviatoricElasticStiffness(FloatArray &stress, const FloatArray &strain, double GModulus) +FloatArrayF< 6 > +StructuralMaterial::applyDeviatoricElasticStiffness(const FloatArrayF< 6 > &strain, double GModulus) { - stress.resize(6); - stress[0] = 2. * GModulus * strain [ 0 ]; - stress[1] = 2. * GModulus * strain [ 1 ]; - stress[2] = 2. * GModulus * strain [ 2 ]; - stress[3] = GModulus * strain [ 3 ]; - stress[4] = GModulus * strain [ 4 ]; - stress[5] = GModulus * strain [ 5 ]; + return { + 2. * GModulus * strain [ 0 ], + 2. * GModulus * strain [ 1 ], + 2. * GModulus * strain [ 2 ], + GModulus *strain [ 3 ], + GModulus *strain [ 4 ], + GModulus *strain [ 5 ], + }; } -void -StructuralMaterial :: applyElasticStiffness(FloatArray &stress, const FloatArray &strain, double EModulus, double nu) +FloatArrayF< 6 > +StructuralMaterial::applyElasticStiffness(const FloatArrayF< 6 > &strain, double EModulus, double nu) { double factor = EModulus / ( ( 1. + nu ) * ( 1. - 2. * nu ) ); - - stress.resize(6); - stress[0] = factor * ( ( 1. - nu ) * strain [ 0 ] + nu * strain [ 1 ] + nu * strain [ 2 ] ); - stress[1] = factor * ( nu * strain [ 0 ] + ( 1. - nu ) * strain [ 1 ] + nu * strain [ 2 ] ); - stress[2] = factor * ( nu * strain [ 0 ] + nu * strain [ 1 ] + ( 1. - nu ) * strain [ 2 ] ); - stress[3] = factor * ( ( ( 1. - 2. * nu ) / 2. ) * strain [ 3 ] ); - stress[4] = factor * ( ( ( 1. - 2. * nu ) / 2. ) * strain [ 4 ] ); - stress[5] = factor * ( ( ( 1. - 2. * nu ) / 2. ) * strain [ 5 ] ); + + return { + factor *( ( 1. - nu ) * strain [ 0 ] + nu * strain [ 1 ] + nu * strain [ 2 ] ), + factor *( nu * strain [ 0 ] + ( 1. - nu ) * strain [ 1 ] + nu * strain [ 2 ] ), + factor *( nu * strain [ 0 ] + nu * strain [ 1 ] + ( 1. - nu ) * strain [ 2 ] ), + factor *( ( ( 1. - 2. * nu ) / 2. ) * strain [ 3 ] ), + factor *( ( ( 1. - 2. * nu ) / 2. ) * strain [ 4 ] ), + factor *( ( ( 1. - 2. * nu ) / 2. ) * strain [ 5 ] ), + }; } -void -StructuralMaterial :: applyElasticCompliance(FloatArray &strain, const FloatArray &stress, double EModulus, double nu) +FloatArrayF< 6 > +StructuralMaterial::applyElasticCompliance(const FloatArrayF< 6 > &stress, double EModulus, double nu) { - strain.resize(6); - strain[0] = ( stress [ 0 ] - nu * stress [ 1 ] - nu * stress [ 2 ] ) / EModulus; - strain[1] = ( -nu * stress [ 0 ] + stress [ 1 ] - nu * stress [ 2 ] ) / EModulus; - strain[2] = ( -nu * stress [ 0 ] - nu * stress [ 1 ] + stress [ 2 ] ) / EModulus; - strain[3] = ( 2. * ( 1. + nu ) * stress [ 3 ] ) / EModulus; - strain[4] = ( 2. * ( 1. + nu ) * stress [ 4 ] ) / EModulus; - strain[5] = ( 2. * ( 1. + nu ) * stress [ 5 ] ) / EModulus; + return { + ( stress [ 0 ] - nu * stress [ 1 ] - nu * stress [ 2 ] ) / EModulus, + ( -nu * stress [ 0 ] + stress [ 1 ] - nu * stress [ 2 ] ) / EModulus, + ( -nu * stress [ 0 ] - nu * stress [ 1 ] + stress [ 2 ] ) / EModulus, + ( 2. * ( 1. + nu ) * stress [ 3 ] ) / EModulus, + ( 2. * ( 1. + nu ) * stress [ 4 ] ) / EModulus, + ( 2. * ( 1. + nu ) * stress [ 5 ] ) / EModulus, + }; } double -StructuralMaterial :: computeStressNorm(const FloatArray &s) +StructuralMaterial::computeStressNorm(const FloatArrayF< 6 > &s) { - if ( s.giveSize() == 1 ) { - return fabs(s [ 0 ]); - } - return sqrt(s [ 0 ] * s [ 0 ] + s [ 1 ] * s [ 1 ] + s [ 2 ] * s [ 2 ] + 2. * s [ 3 ] * s [ 3 ] + 2. * s [ 4 ] * s [ 4 ] + 2. * s [ 5 ] * s [ 5 ]); } double -StructuralMaterial :: computeFirstInvariant(const FloatArray &s) +StructuralMaterial::computeFirstInvariant(const FloatArrayF< 6 > &s) { - if ( s.giveSize() == 1 ) { - return s [ 0 ]; - } - return s [ 0 ] + s [ 1 ] + s [ 2 ]; } double -StructuralMaterial :: computeSecondStressInvariant(const FloatArray &s) +StructuralMaterial::computeSecondStressInvariant(const FloatArrayF< 6 > &s) { return .5 * ( s [ 0 ] * s [ 0 ] + s [ 1 ] * s [ 1 ] + s [ 2 ] * s [ 2 ] ) + - s [ 3 ] * s [ 3 ] + s [ 4 ] * s [ 4 ] + s [ 5 ] * s [ 5 ]; + s [ 3 ] * s [ 3 ] + s [ 4 ] * s [ 4 ] + s [ 5 ] * s [ 5 ]; } double -StructuralMaterial :: computeThirdStressInvariant(const FloatArray &s) +StructuralMaterial::computeThirdStressInvariant(const FloatArrayF< 6 > &s) { return ( 1. / 3. ) * ( s [ 0 ] * s [ 0 ] * s [ 0 ] + 3. * s [ 0 ] * s [ 5 ] * s [ 5 ] + - 3. * s [ 0 ] * s [ 4 ] * s [ 4 ] + 6. * s [ 3 ] * s [ 5 ] * s [ 4 ] + - 3. * s [ 1 ] * s [ 5 ] * s [ 5 ] + 3 * s [ 2 ] * s [ 4 ] * s [ 4 ] + - s [ 1 ] * s [ 1 ] * s [ 1 ] + 3. * s [ 1 ] * s [ 3 ] * s [ 3 ] + - 3. * s [ 2 ] * s [ 3 ] * s [ 3 ] + s [ 2 ] * s [ 2 ] * s [ 2 ] ); + 3. * s [ 0 ] * s [ 4 ] * s [ 4 ] + 6. * s [ 3 ] * s [ 5 ] * s [ 4 ] + + 3. * s [ 1 ] * s [ 5 ] * s [ 5 ] + 3 * s [ 2 ] * s [ 4 ] * s [ 4 ] + + s [ 1 ] * s [ 1 ] * s [ 1 ] + 3. * s [ 1 ] * s [ 3 ] * s [ 3 ] + + 3. * s [ 2 ] * s [ 3 ] * s [ 3 ] + s [ 2 ] * s [ 2 ] * s [ 2 ] ); } double -StructuralMaterial :: computeFirstCoordinate(const FloatArray &s) +StructuralMaterial::computeFirstCoordinate(const FloatArrayF< 6 > &s) { // This function computes the first Haigh-Westergaard coordinate return computeFirstInvariant(s) / sqrt(3.); } double -StructuralMaterial :: computeSecondCoordinate(const FloatArray &s) +StructuralMaterial::computeSecondCoordinate(const FloatArrayF< 6 > &s) { // This function computes the second Haigh-Westergaard coordinate // from the deviatoric stress state - return sqrt( 2. * computeSecondStressInvariant(s) ); + return sqrt(2. * computeSecondStressInvariant(s) ); } double -StructuralMaterial :: computeThirdCoordinate(const FloatArray &s) +StructuralMaterial::computeThirdCoordinate(const FloatArrayF< 6 > &s) { // This function computes the third Haigh-Westergaard coordinate // from the deviatoric stress state @@ -1719,7 +1630,7 @@ StructuralMaterial :: computeThirdCoordinate(const FloatArray &s) if ( computeSecondStressInvariant(s) == 0. ) { c1 = 0.0; } else { - c1 = ( 3. * sqrt(3.) / 2. ) * computeThirdStressInvariant(s) / ( pow( computeSecondStressInvariant(s), ( 3. / 2. ) ) ); + c1 = ( 3. * sqrt(3.) / 2. ) * computeThirdStressInvariant(s) / ( pow(computeSecondStressInvariant(s), ( 3. / 2. ) ) ); } if ( c1 > 1.0 ) { @@ -1733,50 +1644,55 @@ StructuralMaterial :: computeThirdCoordinate(const FloatArray &s) return 1. / 3. * acos(c1); } + double -StructuralMaterial :: computeVonMisesStress(const FloatArray *currentStress) +StructuralMaterial::computeVonMisesStress(const FloatArray &stress) { - double J2; - double v1, v2, v3; + if ( stress.giveSize() == 3 ) { + return computeVonMisesStress_PlaneStress(stress); + } else if ( stress.giveSize() == 4 ) { + // Plane strain + double v1 = ( ( stress.at(1) - stress.at(2) ) * ( stress.at(1) - stress.at(2) ) ); + double v2 = ( ( stress.at(2) - stress.at(3) ) * ( stress.at(2) - stress.at(3) ) ); + double v3 = ( ( stress.at(3) - stress.at(1) ) * ( stress.at(3) - stress.at(1) ) ); - if ( currentStress == NULL ) { + double J2 = ( 1. / 6. ) * ( v1 + v2 + v3 ) + stress.at(4) * stress.at(4); + + return sqrt(3 * J2); + } else if ( stress.giveSize() == 6 ) { + return computeVonMisesStress_3D(stress); + } else { return 0.0; } +} - if ( currentStress->giveSize() == 3 ) { - // Plane stress - return sqrt( currentStress->at(1) * currentStress->at(1) + currentStress->at(2) * currentStress->at(2) - - currentStress->at(1) * currentStress->at(2) + 3 * currentStress->at(3) * currentStress->at(3) ); - } else if ( currentStress->giveSize() == 4 ) { - // Plane strain - v1 = ( ( currentStress->at(1) - currentStress->at(2) ) * ( currentStress->at(1) - currentStress->at(2) ) ); - v2 = ( ( currentStress->at(2) - currentStress->at(3) ) * ( currentStress->at(2) - currentStress->at(3) ) ); - v3 = ( ( currentStress->at(3) - currentStress->at(1) ) * ( currentStress->at(3) - currentStress->at(1) ) ); +double +StructuralMaterial::computeVonMisesStress_PlaneStress(const FloatArrayF< 3 > &stress) +{ + return sqrt(stress.at(1) * stress.at(1) + stress.at(2) * stress.at(2) + - stress.at(1) * stress.at(2) + 3 * stress.at(3) * stress.at(3) ); +} - J2 = ( 1. / 6. ) * ( v1 + v2 + v3 ) + currentStress->at(4) * currentStress->at(4); - return sqrt(3 * J2); - } else if ( currentStress->giveSize() == 6 ) { - // 3D - v1 = ( ( currentStress->at(1) - currentStress->at(2) ) * ( currentStress->at(1) - currentStress->at(2) ) ); - v2 = ( ( currentStress->at(2) - currentStress->at(3) ) * ( currentStress->at(2) - currentStress->at(3) ) ); - v3 = ( ( currentStress->at(3) - currentStress->at(1) ) * ( currentStress->at(3) - currentStress->at(1) ) ); +double +StructuralMaterial::computeVonMisesStress_3D(const FloatArrayF< 6 > &stress) +{ + double v1 = ( ( stress.at(1) - stress.at(2) ) * ( stress.at(1) - stress.at(2) ) ); + double v2 = ( ( stress.at(2) - stress.at(3) ) * ( stress.at(2) - stress.at(3) ) ); + double v3 = ( ( stress.at(3) - stress.at(1) ) * ( stress.at(3) - stress.at(1) ) ); - J2 = ( 1. / 6. ) * ( v1 + v2 + v3 ) + currentStress->at(4) * currentStress->at(4) + - currentStress->at(5) * currentStress->at(5) + currentStress->at(6) * currentStress->at(6); + double J2 = ( 1. / 6. ) * ( v1 + v2 + v3 ) + stress.at(4) * stress.at(4) + + stress.at(5) * stress.at(5) + stress.at(6) * stress.at(6); - return sqrt(3 * J2); - } else { - return 0.0; - } + return sqrt(3 * J2); } -void -StructuralMaterial :: giveStrainVectorTranformationMtrx(FloatMatrix &answer, - const FloatMatrix &base, - bool transpose) + +FloatMatrixF< 6, 6 > +StructuralMaterial::giveStrainVectorTranformationMtrx(const FloatMatrixF< 3, 3 > &base, + bool trans) // // returns transformation matrix for 3d - strains to another system of axes, // given by base. @@ -1786,16 +1702,9 @@ StructuralMaterial :: giveStrainVectorTranformationMtrx(FloatMatrix &answer, // If transpose == 1 we transpose base matrix before transforming // { - FloatMatrix t; - answer.resize(6, 6); - answer.zero(); - - if ( transpose ) { - t.beTranspositionOf(base); - } else { - t = base; - } + auto t = trans ? transpose(base) : base; + FloatMatrixF< 6, 6 >answer; answer.at(1, 1) = t.at(1, 1) * t.at(1, 1); answer.at(1, 2) = t.at(2, 1) * t.at(2, 1); answer.at(1, 3) = t.at(3, 1) * t.at(3, 1); @@ -1837,13 +1746,14 @@ StructuralMaterial :: giveStrainVectorTranformationMtrx(FloatMatrix &answer, answer.at(6, 4) = ( t.at(2, 1) * t.at(3, 2) + t.at(3, 1) * t.at(2, 2) ); answer.at(6, 5) = ( t.at(1, 1) * t.at(3, 2) + t.at(3, 1) * t.at(1, 2) ); answer.at(6, 6) = ( t.at(1, 1) * t.at(2, 2) + t.at(2, 1) * t.at(1, 2) ); + + return answer; } -void -StructuralMaterial :: give2DStrainVectorTranformationMtrx(FloatMatrix &answer, - const FloatMatrix &base, - bool transpose) +FloatMatrixF< 3, 3 > +StructuralMaterial::give2DStrainVectorTranformationMtrx(const FloatMatrixF< 2, 2 > &base, + bool trans) // // returns transformation matrix for 2d - strains to another system of axes, // given by base. @@ -1853,16 +1763,8 @@ StructuralMaterial :: give2DStrainVectorTranformationMtrx(FloatMatrix &answer, // If transpose == 1 we transpose base matrix before transforming // { - FloatMatrix t; - answer.resize(3, 3); - answer.zero(); - - if ( transpose ) { - t.beTranspositionOf(base); - } else { - t = base; - } - + auto t = trans ? transpose(base) : base; + FloatMatrixF< 3, 3 >answer; answer.at(1, 1) = t.at(1, 1) * t.at(1, 1); answer.at(1, 2) = t.at(2, 1) * t.at(2, 1); answer.at(1, 3) = t.at(1, 1) * t.at(2, 1); @@ -1874,13 +1776,13 @@ StructuralMaterial :: give2DStrainVectorTranformationMtrx(FloatMatrix &answer, answer.at(3, 1) = 2.0 * t.at(1, 1) * t.at(1, 2); answer.at(3, 2) = 2.0 * t.at(2, 1) * t.at(2, 2); answer.at(3, 3) = ( t.at(1, 1) * t.at(2, 2) + t.at(2, 1) * t.at(1, 2) ); + return answer; } - -void -StructuralMaterial :: giveStressVectorTranformationMtrx(FloatMatrix &answer, - const FloatMatrix &base, - bool transpose) + +FloatMatrixF< 6, 6 > +StructuralMaterial::giveStressVectorTranformationMtrx(const FloatMatrixF< 3, 3 > &base, + bool trans) // // returns transformation matrix for 3d - stress to another system of axes, // given by base. @@ -1890,16 +1792,9 @@ StructuralMaterial :: giveStressVectorTranformationMtrx(FloatMatrix &answer, // If transpose == 1 we transpose base matrix before transforming // { - FloatMatrix t; - answer.resize(6, 6); - answer.zero(); - - if ( transpose ) { - t.beTranspositionOf(base); - } else { - t = base; - } + auto t = trans ? transpose(base) : base; + FloatMatrixF< 6, 6 >answer; answer.at(1, 1) = t.at(1, 1) * t.at(1, 1); answer.at(1, 2) = t.at(2, 1) * t.at(2, 1); answer.at(1, 3) = t.at(3, 1) * t.at(3, 1); @@ -1941,13 +1836,14 @@ StructuralMaterial :: giveStressVectorTranformationMtrx(FloatMatrix &answer, answer.at(6, 4) = ( t.at(2, 1) * t.at(3, 2) + t.at(3, 1) * t.at(2, 2) ); answer.at(6, 5) = ( t.at(1, 1) * t.at(3, 2) + t.at(3, 1) * t.at(1, 2) ); answer.at(6, 6) = ( t.at(1, 1) * t.at(2, 2) + t.at(2, 1) * t.at(1, 2) ); + + return answer; } -void -StructuralMaterial :: givePlaneStressVectorTranformationMtrx(FloatMatrix &answer, - const FloatMatrix &base, - bool transpose) +FloatMatrixF< 3, 3 > +StructuralMaterial::givePlaneStressVectorTranformationMtrx(const FloatMatrixF< 2, 2 > &base, + bool trans) // // returns transformation matrix for 2d - stress to another system of axes, // given by base. @@ -1957,16 +1853,9 @@ StructuralMaterial :: givePlaneStressVectorTranformationMtrx(FloatMatrix &answer // If transpose == 1 we transpose base matrix before transforming // { - FloatMatrix t; - answer.resize(3, 3); - answer.zero(); - - if ( transpose ) { - t.beTranspositionOf(base); - } else { - t = base; - } + auto t = trans ? transpose(base) : base; + FloatMatrixF< 3, 3 >answer; answer.at(1, 1) = t.at(1, 1) * t.at(1, 1); answer.at(1, 2) = t.at(2, 1) * t.at(2, 1); answer.at(1, 3) = 2.0 * t.at(1, 1) * t.at(2, 1); @@ -1978,12 +1867,13 @@ StructuralMaterial :: givePlaneStressVectorTranformationMtrx(FloatMatrix &answer answer.at(3, 1) = t.at(1, 1) * t.at(1, 2); answer.at(3, 2) = t.at(2, 1) * t.at(2, 2); answer.at(3, 3) = t.at(1, 1) * t.at(2, 2) + t.at(2, 1) * t.at(1, 2); + return answer; } -void -StructuralMaterial :: transformStrainVectorTo(FloatArray &answer, const FloatMatrix &base, - const FloatArray &strainVector, bool transpose) +FloatArrayF< 6 > +StructuralMaterial::transformStrainVectorTo(const FloatMatrixF< 3, 3 > &base, + const FloatArrayF< 6 > &strain, bool transpose) // // performs transformation of 3d-strain vector to another system of axes, // given by base. @@ -1993,16 +1883,14 @@ StructuralMaterial :: transformStrainVectorTo(FloatArray &answer, const FloatMat // // If transpose == 1 we transpose base matrix before transforming { - FloatMatrix tt; - - StructuralMaterial :: giveStrainVectorTranformationMtrx(tt, base, transpose); - answer.beProductOf(tt, strainVector); + auto tt = StructuralMaterial::giveStrainVectorTranformationMtrx(base, transpose); + return dot(tt, strain); } -void -StructuralMaterial :: transformStressVectorTo(FloatArray &answer, const FloatMatrix &base, - const FloatArray &stressVector, bool transpose) +FloatArrayF< 6 > +StructuralMaterial::transformStressVectorTo(const FloatMatrixF< 3, 3 > &base, + const FloatArrayF< 6 > &stress, bool transpose) // // // performs transformation of 3d-stress vector to another system of axes, @@ -2012,18 +1900,15 @@ StructuralMaterial :: transformStressVectorTo(FloatArray &answer, const FloatMat // be expressed in the same coordinate system as strainVector // If transpose == 1 we transpose base matrix before transforming // - { - FloatMatrix tt; - - StructuralMaterial :: giveStressVectorTranformationMtrx(tt, base, transpose); - answer.beProductOf(tt, stressVector); + auto tt = StructuralMaterial::giveStressVectorTranformationMtrx(base, transpose); + return dot(tt, stress); } void -StructuralMaterial :: sortPrincDirAndValCloseTo(FloatArray *pVal, FloatMatrix *pDir, - FloatMatrix *toPDir) +StructuralMaterial::sortPrincDirAndValCloseTo(FloatArray &pVal, FloatMatrix &pDir, + const FloatMatrix &toPDir) // // this method sorts newly computed principal values (pVal) and // corresponding principal directions (pDir) to be closed to @@ -2033,37 +1918,19 @@ StructuralMaterial :: sortPrincDirAndValCloseTo(FloatArray *pVal, FloatMatrix *p // and normalized. // { - int maxJ = 0, size; - double cosine, maxCosine, swap; - -#ifdef DEBUG - if ( ( !pDir->isSquare() ) || ( !toPDir->isSquare() ) ) { - OOFEM_SERROR("Not square matrix"); - } - - if ( pDir->giveNumberOfRows() != toPDir->giveNumberOfRows() ) { - OOFEM_SERROR("Incompatible matrices"); - } - - if ( pDir->giveNumberOfRows() != pVal->giveSize() ) { - OOFEM_SERROR("Incompatible pVal Array size"); - } - -#endif - // // compute cosine matrix, where member i,j is cosine of angle // between toPDir i th eigen vector and j th pDir eigen vector // // sort pVal and pDir - size = pDir->giveNumberOfRows(); - for ( int i = 1; i <= size - 1; i++ ) { + int maxJ = 0; + for ( int i = 1; i <= 3 - 1; i++ ) { // find closest pDir vector to toPDir i-th vector - maxCosine = 0.0; - for ( int j = i; j <= size; j++ ) { - cosine = 0.; - for ( int k = 1; k <= size; k++ ) { - cosine += toPDir->at(k, i) * pDir->at(k, j); + double maxCosine = 0.0; + for ( int j = i; j <= 3; j++ ) { + double cosine = 0.; + for ( int k = 1; k <= 3; k++ ) { + cosine += toPDir.at(k, i) * pDir.at(k, j); } cosine = fabs(cosine); @@ -2076,13 +1943,13 @@ StructuralMaterial :: sortPrincDirAndValCloseTo(FloatArray *pVal, FloatMatrix *p // swap entries if ( maxJ != i ) { // swap eigenVectors and values - swap = pVal->at(maxJ); - pVal->at(maxJ) = pVal->at(i); - pVal->at(i) = swap; - for ( int k = 1; k <= size; k++ ) { - swap = pDir->at(k, maxJ); - pDir->at(k, maxJ) = pDir->at(k, i); - pDir->at(k, i) = swap; + double swap = pVal.at(maxJ); + pVal.at(maxJ) = pVal.at(i); + pVal.at(i) = swap; + for ( int k = 1; k <= 3; k++ ) { + double swap = pDir.at(k, maxJ); + pDir.at(k, maxJ) = pDir.at(k, i); + pDir.at(k, i) = swap; } } } @@ -2090,7 +1957,7 @@ StructuralMaterial :: sortPrincDirAndValCloseTo(FloatArray *pVal, FloatMatrix *p int -StructuralMaterial :: setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type) +StructuralMaterial::setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type) { StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); if ( type == IST_StressTensor ) { @@ -2112,11 +1979,11 @@ StructuralMaterial :: setIPValue(const FloatArray &value, GaussPoint *gp, Intern int -StructuralMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +StructuralMaterial::giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); if ( type == IST_StressTensor ) { - StructuralMaterial :: giveFullSymVectorForm( answer, status->giveStressVector(), gp->giveMaterialMode() ); + StructuralMaterial::giveFullSymVectorForm(answer, status->giveStressVector(), gp->giveMaterialMode() ); return 1; } else if ( type == IST_StressTensor_Reduced ) { answer = status->giveStressVector(); @@ -2124,11 +1991,15 @@ StructuralMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalSt } else if ( type == IST_vonMisesStress ) { ///@todo What about the stress meassure in large deformations here? The internal state type should specify "Cauchy" or something. answer.resize(1); - answer.at(1) = this->computeVonMisesStress( & status->giveStressVector() ); + if ( status->giveStressVector().giveSize() == 6 ) { + answer.at(1) = this->computeVonMisesStress_3D(status->giveStressVector() ); + } else { + answer.at(1) = this->computeVonMisesStress(status->giveStressVector() ); + } return 1; } else if ( type == IST_StrainTensor ) { ///@todo Fill in correct full form values here! This just adds zeros! - StructuralMaterial :: giveFullSymVectorForm( answer, status->giveStrainVector(), gp->giveMaterialMode() ); + StructuralMaterial::giveFullSymVectorForm(answer, status->giveStrainVector(), gp->giveMaterialMode() ); /* commented out by Milan - this evaluation of the out-of-plane strain would be correct for elastic material only * and for other materials can lead to misleading values * if ( gp->giveMaterialMode() == _PlaneStress) { @@ -2146,21 +2017,21 @@ StructuralMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalSt return 1; } else if ( type == IST_StressTensorTemp ) { ///@todo Fill in correct full form values here! This just adds zeros! - StructuralMaterial :: giveFullSymVectorForm( answer, status->giveTempStressVector(), gp->giveMaterialMode() ); + StructuralMaterial::giveFullSymVectorForm(answer, status->giveTempStressVector(), gp->giveMaterialMode() ); return 1; } else if ( type == IST_StrainTensorTemp ) { ///@todo Fill in correct full form values here! This just adds zeros! - StructuralMaterial :: giveFullSymVectorForm( answer, status->giveTempStrainVector(), gp->giveMaterialMode() ); + StructuralMaterial::giveFullSymVectorForm(answer, status->giveTempStrainVector(), gp->giveMaterialMode() ); return 1; } else if ( type == IST_PrincipalStressTensor || type == IST_PrincipalStressTempTensor ) { FloatArray s; if ( type == IST_PrincipalStressTensor ) { ///@todo Fill in correct full form values here! This just adds zeros! - StructuralMaterial :: giveFullSymVectorForm( s, status->giveStressVector(), gp->giveMaterialMode() ); + StructuralMaterial::giveFullSymVectorForm(s, status->giveStressVector(), gp->giveMaterialMode() ); } else { ///@todo Fill in correct full form values here! This just adds zeros! - StructuralMaterial :: giveFullSymVectorForm( s, status->giveTempStressVector(), gp->giveMaterialMode() ); + StructuralMaterial::giveFullSymVectorForm(s, status->giveTempStressVector(), gp->giveMaterialMode() ); } this->computePrincipalValues(answer, s, principal_stress); @@ -2170,10 +2041,10 @@ StructuralMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalSt if ( type == IST_PrincipalStrainTensor ) { ///@todo Fill in correct full form values here! This just adds zeros! - StructuralMaterial :: giveFullSymVectorForm( s, status->giveStrainVector(), gp->giveMaterialMode() ); + StructuralMaterial::giveFullSymVectorForm(s, status->giveStrainVector(), gp->giveMaterialMode() ); } else { ///@todo Fill in correct full form values here! This just adds zeros! - StructuralMaterial :: giveFullSymVectorForm( s, status->giveTempStrainVector(), gp->giveMaterialMode() ); + StructuralMaterial::giveFullSymVectorForm(s, status->giveTempStrainVector(), gp->giveMaterialMode() ); } this->computePrincipalValues(answer, s, principal_strain); @@ -2182,12 +2053,22 @@ StructuralMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalSt FloatArray arrAnswer; FloatMatrix dir; this->computePrincipalValDir(arrAnswer, dir, status->giveStressVector(), principal_stress); - if ( type == IST_PrincStressVector1 ){ - answer.beColumnOf(dir,1); - } else if ( type == IST_PrincStressVector2 ){ - if (dir.giveNumberOfColumns()>=2) answer.beColumnOf(dir,2); else {answer.beColumnOf(dir,1); answer.zero();} + if ( type == IST_PrincStressVector1 ) { + answer.beColumnOf(dir, 1); + } else if ( type == IST_PrincStressVector2 ) { + if ( dir.giveNumberOfColumns() >= 2 ) { + answer.beColumnOf(dir, 2); + } else { + answer.beColumnOf(dir, 1); + answer.zero(); + } } else { - if (dir.giveNumberOfColumns()>=3) answer.beColumnOf(dir,3); else {answer.beColumnOf(dir,1); answer.zero();} + if ( dir.giveNumberOfColumns() >= 3 ) { + answer.beColumnOf(dir, 3); + } else { + answer.beColumnOf(dir, 1); + answer.zero(); + } } return 1; } else if ( type == IST_Temperature ) { @@ -2198,7 +2079,7 @@ StructuralMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalSt if ( ( tf = fm->giveField(FT_Temperature) ) ) { // temperature field registered FloatArray gcoords, et2; - static_cast< StructuralElement * >( gp->giveElement() )->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); + static_cast< StructuralElement * >( gp->giveElement() )->computeGlobalCoordinates(gcoords, gp->giveNaturalCoordinates() ); if ( ( err = tf->evaluateAt(answer, gcoords, VM_Total, tStep) ) ) { OOFEM_ERROR("tf->evaluateAt failed, element %d, error code %d", gp->giveElement()->giveNumber(), err); } @@ -2211,8 +2092,8 @@ StructuralMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalSt } else if ( type == IST_CylindricalStressTensor || type == IST_CylindricalStrainTensor ) { FloatArray gc, val = status->giveStressVector(); FloatMatrix base(3, 3); - static_cast< StructuralElement * >( gp->giveElement() )->computeGlobalCoordinates( gc, gp->giveNaturalCoordinates() ); - double l = sqrt( gc.at(1) * gc.at(1) + gc.at(2) * gc.at(2) ); + static_cast< StructuralElement * >( gp->giveElement() )->computeGlobalCoordinates(gc, gp->giveNaturalCoordinates() ); + double l = sqrt(gc.at(1) * gc.at(1) + gc.at(2) * gc.at(2) ); if ( l > 1.e-4 ) { base.at(1, 1) = gc.at(1) / l; base.at(2, 1) = gc.at(2) / l; @@ -2227,22 +2108,22 @@ StructuralMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalSt base.at(3, 3) = 1.0; if ( type == IST_CylindricalStressTensor ) { - this->transformStressVectorTo(answer, base, val, false); + answer = this->transformStressVectorTo(base, val, false); } else { - this->transformStrainVectorTo(answer, base, val, false); + answer = this->transformStrainVectorTo(base, val, false); } } else { answer = val; } return 1; - } else if (type == IST_PlasticStrainTensor ) { - StructuralMaterial :: giveFullSymVectorForm( answer, status->giveStrainVector(), gp->giveMaterialMode() ); + } else if ( type == IST_PlasticStrainTensor ) { + StructuralMaterial::giveFullSymVectorForm(answer, status->giveStrainVector(), gp->giveMaterialMode() ); answer.zero(); return 1; - } else if (type == IST_MaxEquivalentStrainLevel ) { + } else if ( type == IST_MaxEquivalentStrainLevel ) { answer.resize(1); - answer.at(1)=0.; + answer.at(1) = 0.; return 1; } else if ( type == IST_DeformationGradientTensor ) { answer = status->giveFVector(); @@ -2253,36 +2134,32 @@ StructuralMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalSt } else if ( type == IST_EigenStrainTensor ) { FloatArray eigenstrain; StructuralElement *selem = dynamic_cast< StructuralElement * >( gp->giveElement() ); - selem->computeResultingIPEigenstrainAt(eigenstrain, tStep, gp, VM_Total ); - StructuralMaterial :: giveFullSymVectorForm( answer, eigenstrain, gp->giveMaterialMode() ); + selem->computeResultingIPEigenstrainAt(eigenstrain, tStep, gp, VM_Total); + StructuralMaterial::giveFullSymVectorForm(answer, eigenstrain, gp->giveMaterialMode() ); return 1; } else if ( type == IST_ShellForceTensor ) { answer.resize(6); answer.zero(); return 1; } else { - return Material :: giveIPValue(answer, gp, type, tStep); + return Material::giveIPValue(answer, gp, type, tStep); } } -void -StructuralMaterial :: computeStressIndependentStrainVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +FloatArray +StructuralMaterial::computeStressIndependentStrainVector(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const { FloatArray et, eigenstrain; if ( gp->giveIntegrationRule() == NULL ) { ///@todo Hack for loose gausspoints. We shouldn't ask for "gp->giveElement()". FIXME - answer.clear(); - return; + return FloatArray(); } Element *elem = gp->giveElement(); StructuralElement *selem = dynamic_cast< StructuralElement * >( gp->giveElement() ); - answer.clear(); if ( tStep->giveIntrinsicTime() < this->castingTime ) { - answer.zero(); - return; + return FloatArray(); } //sum up all prescribed temperatures over an element @@ -2296,8 +2173,8 @@ StructuralMaterial :: computeStressIndependentStrainVector(FloatArray &answer, selem->computeResultingIPEigenstrainAt(eigenstrain, tStep, gp, mode); } - if ( eigenstrain.giveSize() != 0 && eigenstrain.giveSize() != giveSizeOfVoigtSymVector(gp->giveMaterialMode()) ) { - OOFEM_ERROR( "Number of given eigenstrain components %d is different than required %d by element %d", eigenstrain.giveSize(), giveSizeOfVoigtSymVector(gp->giveMaterialMode()), elem->giveNumber() ); + if ( eigenstrain.giveSize() != 0 && eigenstrain.giveSize() != giveSizeOfVoigtSymVector(gp->giveMaterialMode() ) ) { + OOFEM_ERROR("Number of given eigenstrain components %d is different than required %d by element %d", eigenstrain.giveSize(), giveSizeOfVoigtSymVector(gp->giveMaterialMode() ), elem->giveNumber() ); } /* add external source, if provided */ @@ -2308,7 +2185,7 @@ StructuralMaterial :: computeStressIndependentStrainVector(FloatArray &answer, // temperature field registered FloatArray gcoords, et2; int err; - elem->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); + elem->computeGlobalCoordinates(gcoords, gp->giveNaturalCoordinates() ); if ( ( err = tf->evaluateAt(et2, gcoords, mode, tStep) ) ) { OOFEM_ERROR("tf->evaluateAt failed, element %d, error code %d", elem->giveNumber(), err); } @@ -2322,30 +2199,21 @@ StructuralMaterial :: computeStressIndependentStrainVector(FloatArray &answer, } } - + FloatArray answer; if ( et.giveSize() ) { //found temperature boundary conditions or prescribed field - FloatArray fullAnswer, e0; - - this->giveThermalDilatationVector(e0, gp, tStep); - - if ( e0.giveSize() ) { - fullAnswer = e0; - if ( mode == VM_Total ) { - fullAnswer.times(et.at(1) - this->referenceTemperature); - } else { - fullAnswer.times( et.at(1) ); - } + auto e0 = this->giveThermalDilatationVector(gp, tStep); - StructuralMaterial :: giveReducedSymVectorForm( answer, fullAnswer, gp->giveMaterialMode() ); - //answer = fullAnswer; - } + double scale = mode == VM_Total ? ( et.at(1) - this->referenceTemperature ) : et.at(1); + FloatArray fullAnswer = e0 * scale; + StructuralMaterial::giveReducedSymVectorForm(answer, fullAnswer, gp->giveMaterialMode() ); + //answer = fullAnswer; } //join temperature and eigenstrain vectors, compare vector sizes if ( answer.giveSize() ) { if ( eigenstrain.giveSize() ) { if ( answer.giveSize() != eigenstrain.giveSize() ) { - OOFEM_ERROR( "Vector of temperature strains has the size %d which is different with the size of eigenstrain vector %d, element %d", answer.giveSize(), eigenstrain.giveSize(), elem->giveNumber() ); + OOFEM_ERROR("Vector of temperature strains has the size %d which is different with the size of eigenstrain vector %d, element %d", answer.giveSize(), eigenstrain.giveSize(), elem->giveNumber() ); } answer.add(eigenstrain); @@ -2355,30 +2223,27 @@ StructuralMaterial :: computeStressIndependentStrainVector(FloatArray &answer, answer = eigenstrain; } } + return answer; } -void -StructuralMaterial :: computeStressIndependentStrainVector_3d(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +FloatArrayF< 6 > +StructuralMaterial::computeStressIndependentStrainVector_3d(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const { - FloatArray et, eigenstrain; if ( gp->giveIntegrationRule() == NULL ) { ///@todo Hack for loose gausspoints. We shouldn't ask for "gp->giveElement()". FIXME - answer.clear(); - return; + return zeros< 6 >(); } - Element *elem = gp->giveElement(); - StructuralElement *selem = dynamic_cast< StructuralElement * >( gp->giveElement() ); - - answer.clear(); if ( tStep->giveIntrinsicTime() < this->castingTime ) { - return; + return zeros< 6 >(); } //sum up all prescribed temperatures over an element //elem->computeResultingIPTemperatureAt(et, tStep, gp, mode); + FloatArray et, eigenstrain; + Element *elem = gp->giveElement(); + StructuralElement *selem = dynamic_cast< StructuralElement * >( gp->giveElement() ); if ( selem ) { selem->computeResultingIPTemperatureAt(et, tStep, gp, mode); } @@ -2391,12 +2256,11 @@ StructuralMaterial :: computeStressIndependentStrainVector_3d(FloatArray &answer /* add external source, if provided */ FieldManager *fm = domain->giveEngngModel()->giveContext()->giveFieldManager(); FieldPtr tf = fm->giveField(FT_Temperature); - if ( tf ) { // temperature field registered FloatArray gcoords, et2; + elem->computeGlobalCoordinates(gcoords, gp->giveNaturalCoordinates() ); int err; - elem->computeGlobalCoordinates( gcoords, gp->giveNaturalCoordinates() ); if ( ( err = tf->evaluateAt(et2, gcoords, mode, tStep) ) ) { OOFEM_ERROR("tf->evaluateAt failed, element %d, error code %d", elem->giveNumber(), err); } @@ -2411,49 +2275,28 @@ StructuralMaterial :: computeStressIndependentStrainVector_3d(FloatArray &answer } + FloatArrayF< 6 >answer; if ( et.giveSize() ) { //found temperature boundary conditions or prescribed field - FloatArray fullAnswer, e0; - - this->giveThermalDilatationVector(e0, gp, tStep); - - if ( e0.giveSize() ) { - fullAnswer = e0; - if ( mode == VM_Total ) { - fullAnswer.times(et.at(1) - this->referenceTemperature); - } else { - fullAnswer.times( et.at(1) ); - } - - answer = fullAnswer; - } + auto e0 = this->giveThermalDilatationVector(gp, tStep); + double scale = mode == VM_Total ? ( et.at(1) - this->referenceTemperature ) : et.at(1); + answer = e0 * scale; } - - //join temperature and eigenstrain vectors, compare vector sizes - if ( answer.giveSize() ) { - if ( eigenstrain.giveSize() ) { - if ( answer.giveSize() != eigenstrain.giveSize() ) { - OOFEM_ERROR( "Vector of temperature strains has the size %d which is different with the size of eigenstrain vector %d, element %d", answer.giveSize(), eigenstrain.giveSize(), elem->giveNumber() ); - } - - answer.add(eigenstrain); - } - } else { - if ( eigenstrain.giveSize() ) { - answer = eigenstrain; - } + if ( eigenstrain.giveSize() ) { + answer += FloatArrayF< 6 >(eigenstrain); } + return answer; } void -StructuralMaterial :: giveFullSymVectorForm(FloatArray &answer, const FloatArray &vec, MaterialMode matMode) +StructuralMaterial::giveFullSymVectorForm(FloatArray &answer, const FloatArray &vec, MaterialMode matMode) { if ( vec.giveSize() == 6 ) { // If we use default 3D implementation to treat e.g. plane strain. answer = vec; } else { IntArray indx; - answer.resize( StructuralMaterial :: giveVoigtSymVectorMask(indx, matMode) ); + answer.resize(StructuralMaterial::giveVoigtSymVectorMask(indx, matMode) ); answer.zero(); answer.assemble(vec, indx); } @@ -2461,43 +2304,53 @@ StructuralMaterial :: giveFullSymVectorForm(FloatArray &answer, const FloatArray void -StructuralMaterial :: giveFullVectorForm(FloatArray &answer, const FloatArray &vec, MaterialMode matMode) +StructuralMaterial::giveFullVectorForm(FloatArray &answer, const FloatArray &vec, MaterialMode matMode) { - IntArray indx; - answer.resize( StructuralMaterial :: giveVoigtVectorMask(indx, matMode) ); - answer.zero(); - answer.assemble(vec, indx); + if ( vec.giveSize() == 9 ) { + // If we use default 3D implementation to treat e.g. plane strain. + answer = vec; + } else { + IntArray indx; + answer.resize(StructuralMaterial::giveVoigtVectorMask(indx, matMode) ); + answer.zero(); + answer.assemble(vec, indx); + } } void -StructuralMaterial :: giveFullVectorFormF(FloatArray &answer, const FloatArray &vec, MaterialMode matMode) +StructuralMaterial::giveFullVectorFormF(FloatArray &answer, const FloatArray &vec, MaterialMode matMode) { - IntArray indx; - answer.resize(9); - answer.at(1) = answer.at(2) = answer.at(3) = 1.0; // set diagonal terms + if ( vec.giveSize() == 9 ) { + // If we use default 3D implementation to treat e.g. plane strain. + answer = vec; + } else { + IntArray indx; + answer.resize(9); + answer.at(1) = answer.at(2) = answer.at(3) = 1.0; // set diagonal terms - StructuralMaterial :: giveVoigtVectorMask(indx, matMode); - for ( int i = 1; i <= indx.giveSize(); i++ ) { - answer.at( indx.at(i) ) = vec.at(i); + StructuralMaterial::giveVoigtVectorMask(indx, matMode); + for ( int i = 1; i <= indx.giveSize(); i++ ) { + answer.at(indx.at(i) ) = vec.at(i); + } } } void -StructuralMaterial :: giveReducedVectorForm(FloatArray &answer, const FloatArray &vec, MaterialMode matMode) +StructuralMaterial::giveReducedVectorForm(FloatArray &answer, const FloatArray &vec, MaterialMode matMode) { IntArray indx; - StructuralMaterial :: giveVoigtVectorMask(indx, matMode); + StructuralMaterial::giveVoigtVectorMask(indx, matMode); answer.beSubArrayOf(vec, indx); } void -StructuralMaterial :: giveReducedSymVectorForm(FloatArray &answer, const FloatArray &vec, MaterialMode matMode) +StructuralMaterial::giveReducedSymVectorForm(FloatArray &answer, const FloatArray &vec, MaterialMode matMode) { IntArray indx; - StructuralMaterial :: giveVoigtSymVectorMask(indx, matMode); + StructuralMaterial::giveVoigtSymVectorMask(indx, matMode); if ( indx.giveSize() == vec.giveSize() ) { answer = vec; @@ -2508,10 +2361,10 @@ StructuralMaterial :: giveReducedSymVectorForm(FloatArray &answer, const FloatAr void -StructuralMaterial :: giveFullSymMatrixForm(FloatMatrix &answer, const FloatMatrix &red, MaterialMode matMode) +StructuralMaterial::giveFullSymMatrixForm(FloatMatrix &answer, const FloatMatrix &red, MaterialMode matMode) { IntArray indx; - int size = StructuralMaterial :: giveVoigtSymVectorMask(indx, matMode); + int size = StructuralMaterial::giveVoigtSymVectorMask(indx, matMode); answer.resize(size, size); answer.zero(); answer.assemble(red, indx, indx); @@ -2519,62 +2372,69 @@ StructuralMaterial :: giveFullSymMatrixForm(FloatMatrix &answer, const FloatMatr void -StructuralMaterial :: giveReducedMatrixForm(FloatMatrix &answer, const FloatMatrix &full, MaterialMode matMode) +StructuralMaterial::giveReducedMatrixForm(FloatMatrix &answer, const FloatMatrix &full, MaterialMode matMode) { IntArray indx; - StructuralMaterial :: giveVoigtVectorMask(indx, matMode); + StructuralMaterial::giveVoigtVectorMask(indx, matMode); answer.beSubMatrixOf(full, indx, indx); } void -StructuralMaterial :: giveReducedSymMatrixForm(FloatMatrix &answer, const FloatMatrix &full, MaterialMode matMode) +StructuralMaterial::giveReducedSymMatrixForm(FloatMatrix &answer, const FloatMatrix &full, MaterialMode matMode) { IntArray indx; - StructuralMaterial :: giveVoigtSymVectorMask(indx, matMode); + StructuralMaterial::giveVoigtSymVectorMask(indx, matMode); answer.beSubMatrixOf(full, indx, indx); } -void -StructuralMaterial::giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +FloatArrayF< 6 > +StructuralMaterial::giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const { double alpha = this->give(tAlpha, gp); - if (alpha > 0.0) { - answer.resize(6); - answer.zero(); - answer.at(1) = alpha; - answer.at(2) = alpha; - answer.at(3) = alpha; - } else { - answer.clear(); - } + return { + alpha, + alpha, + alpha, + 0., + 0., + 0., + }; } -IRResultType -StructuralMaterial :: initializeFrom(InputRecord *ir) +void +StructuralMaterial::initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Material::initializeFrom(ir); referenceTemperature = 0.0; IR_GIVE_OPTIONAL_FIELD(ir, referenceTemperature, _IFT_StructuralMaterial_referencetemperature); double alpha = 0.0; IR_GIVE_OPTIONAL_FIELD(ir, alpha, _IFT_StructuralMaterial_talpha); - if (alpha > 0.0 && !propertyDictionary.includes(tAlpha)) { - // put isotropic thermal expansion coeff into dictionary, if provided - // and not previosly defined - propertyDictionary.add(tAlpha, alpha); - + if ( !propertyDictionary.includes(tAlpha) ) { + // if (alpha > 0.0 && !propertyDictionary.includes(tAlpha)) { + // put isotropic thermal expansion coeff into dictionary, if provided + // and not previosly defined + propertyDictionary.add(tAlpha, alpha); } + int stiffmode = 0; + IR_GIVE_OPTIONAL_FIELD(ir, stiffmode, _IFT_StructuralMaterial_StressControl_stiffmode); + this->SCStiffMode = ( MatResponseMode ) stiffmode; - return Material :: initializeFrom(ir); + IR_GIVE_OPTIONAL_FIELD(ir, this->SCRelTol, _IFT_StructuralMaterial_StressControl_reltol); + IR_GIVE_OPTIONAL_FIELD(ir, this->SCAbsTol, _IFT_StructuralMaterial_StressControl_abstol); + IR_GIVE_OPTIONAL_FIELD(ir, this->SCMaxiter, _IFT_StructuralMaterial_StressControl_maxiter); } void -StructuralMaterial :: giveInputRecord(DynamicInputRecord &input) +StructuralMaterial::giveInputRecord(DynamicInputRecord &input) { - Material :: giveInputRecord(input); + Material::giveInputRecord(input); input.setField(this->referenceTemperature, _IFT_StructuralMaterial_referencetemperature); + input.setField( ( int ) this->SCStiffMode, _IFT_StructuralMaterial_StressControl_stiffmode ); + input.setField(this->SCRelTol, _IFT_StructuralMaterial_StressControl_reltol); + input.setField(this->SCAbsTol, _IFT_StructuralMaterial_StressControl_abstol); } } // end namespace oofem diff --git a/src/sm/Materials/structuralmaterial.h b/src/sm/Materials/structuralmaterial.h index 82b700548..5ee1bddb0 100644 --- a/src/sm/Materials/structuralmaterial.h +++ b/src/sm/Materials/structuralmaterial.h @@ -38,9 +38,12 @@ #include "material.h" #include "floatarray.h" #include "floatmatrix.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" +#include "mathfem.h" #include "matconst.h" #include "matstatus.h" -#include "stressstrainprincmode.h" +#include "../stressstrainprincmode.h" #include "valuemodetype.h" #include @@ -48,6 +51,10 @@ //@{ #define _IFT_StructuralMaterial_referencetemperature "referencetemperature" #define _IFT_StructuralMaterial_talpha "talpha" +#define _IFT_StructuralMaterial_StressControl_stiffmode "scstiffmode" +#define _IFT_StructuralMaterial_StressControl_reltol "screltol" +#define _IFT_StructuralMaterial_StressControl_abstol "scabstol" +#define _IFT_StructuralMaterial_StressControl_maxiter "maxiter" //@} namespace oofem { @@ -110,21 +117,29 @@ class GaussPoint; * @author Jim Brouzoulis * @author Mikael Öhman */ -class StructuralMaterial : public Material +class OOFEM_EXPORT StructuralMaterial : public Material { protected: /// Reference temperature (temperature, when material has been built into structure). - double referenceTemperature; + double referenceTemperature = 0.; + /// stifness mode used in stress control + MatResponseMode SCStiffMode = TangentStiffness; // tangent + /// relative tolerance for stress control + double SCRelTol = 1.e-3; // relative stress control tolerance + /// absolute stress tolerance for stress control + double SCAbsTol = 1.e-12; + /// maximum iterations for stress-control + int SCMaxiter = 100000; public: /// Voigt index map - static std::vector< std::vector > vIindex; + static std::array< std::array< int, 3 >, 3 >vIindex; /// Symmetric Voigt index map - static std::vector< std::vector > svIndex; + static std::array< std::array< int, 3 >, 3 >svIndex; - static int giveSymVI(int ind1, int ind2) { return svIndex[ind1-1][ind2-1]; } - static int giveVI(int ind1, int ind2) { return vIindex[ind1-1][ind2-1]; } + static int giveSymVI(int ind1, int ind2) { return svIndex [ ind1 - 1 ] [ ind2 - 1 ]; } + static int giveVI(int ind1, int ind2) { return vIindex [ ind1 - 1 ] [ ind2 - 1 ]; } /** * Constructor. Creates material with given number, belonging to given domain. @@ -132,14 +147,12 @@ class StructuralMaterial : public Material * @param d Domain to which new material will belong. */ StructuralMaterial(int n, Domain *d); - /// Destructor. - virtual ~StructuralMaterial() { } - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual const char *giveClassName() const { return "StructuralMaterial"; } + bool hasMaterialModeCapability(MaterialMode mode) const override; + const char *giveClassName() const override { return "StructuralMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; /** * Computes the stiffness matrix for giveRealStressVector of receiver in given integration point, respecting its history. @@ -171,29 +184,29 @@ class StructuralMaterial : public Material virtual void giveRealStressVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrain, TimeStep *tStep); /// Default implementation relies on giveRealStressVector for second Piola-Kirchoff stress - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); + virtual FloatArrayF< 6 >giveRealStressVector_3d(const FloatArrayF< 6 > &strain, GaussPoint *gp, TimeStep *tStep) const; /// Default implementation relies on giveRealStressVector_3d - virtual void giveRealStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); + virtual FloatArrayF< 4 >giveRealStressVector_PlaneStrain(const FloatArrayF< 4 > &strain, GaussPoint *gp, TimeStep *tStep) const; /// Iteratively calls giveRealStressVector_3d to find the stress controlled equal to zero· - virtual void giveRealStressVector_StressControl(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, const IntArray &strainControl, TimeStep *tStep); - virtual void giveRealStressVector_ShellStressControl(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, const IntArray &strainControl, TimeStep *tStep); + virtual FloatArray giveRealStressVector_StressControl(const FloatArray &reducedE, const IntArray &strainControl, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatArray giveRealStressVector_ShellStressControl(const FloatArray &reducedE, const IntArray &strainControl, GaussPoint *gp, TimeStep *tStep) const; /// Default implementation relies on giveRealStressVector_StressControl - virtual void giveRealStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); + virtual FloatArrayF< 3 >giveRealStressVector_PlaneStress(const FloatArrayF< 3 > &reducedE, GaussPoint *gp, TimeStep *tStep) const; /// Default implementation relies on giveRealStressVector_StressControl - virtual void giveRealStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); + virtual FloatArrayF< 1 >giveRealStressVector_1d(const FloatArrayF< 1 > &reducedE, GaussPoint *gp, TimeStep *tStep) const; + /// Default implementation relies on giveRealStressVector_StressControl - virtual void giveRealStressVector_Warping(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); + virtual FloatArrayF< 2 >giveRealStressVector_Warping(const FloatArrayF< 2 > &reducedE, GaussPoint *gp, TimeStep *tStep) const; /// Default implementation relies on giveRealStressVector_StressControl - virtual void giveRealStressVector_2dBeamLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); + virtual FloatArrayF< 2 >giveRealStressVector_2dBeamLayer(const FloatArrayF< 2 > &reducedE, GaussPoint *gp, TimeStep *tStep) const; /// Default implementation relies on giveRealStressVector_StressControl - virtual void giveRealStressVector_PlateLayer(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); + virtual FloatArrayF< 5 >giveRealStressVector_PlateLayer(const FloatArrayF< 5 > &reducedE, GaussPoint *gp, TimeStep *tStep) const; /// Default implementation relies on giveRealStressVector_StressControl - virtual void giveRealStressVector_Fiber(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - virtual void giveRealStressVector_Lattice2d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - virtual void giveRealStressVector_Lattice3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); + virtual FloatArrayF< 3 >giveRealStressVector_Fiber(const FloatArrayF< 3 > &reducedE, GaussPoint *gp, TimeStep *tStep) const; + /// Default implementation is not provided - virtual void giveRealStressVector_2dPlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - virtual void giveRealStressVector_3dBeamSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); + virtual FloatArrayF< 3 >giveRealStressVector_2dPlateSubSoil(const FloatArrayF< 3 > &reducedE, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatArrayF< 6 >giveRealStressVector_3dBeamSubSoil(const FloatArrayF< 6 > &reducedE, GaussPoint *gp, TimeStep *tStep) const; /** * @name Methods associated with the First PK stress tensor. @@ -214,13 +227,15 @@ class StructuralMaterial : public Material */ //@{ /// Default implementation relies on giveRealStressVector for second Piola-Kirchoff stress - virtual void giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedF, TimeStep *tStep); - /// Default implementation relies on giveFirstPKStressVector_3d - virtual void giveFirstPKStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedF, TimeStep *tStep); - /// Default implementation relies on giveFirstPKStressVector_3d - virtual void giveFirstPKStressVector_PlaneStress(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedF, TimeStep *tStep); + virtual FloatArrayF< 9 >giveFirstPKStressVector_3d(const FloatArrayF< 9 > &vF, GaussPoint *gp, TimeStep *tStep) const; /// Default implementation relies on giveFirstPKStressVector_3d - virtual void giveFirstPKStressVector_1d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedF, TimeStep *tStep); + virtual FloatArrayF< 5 >giveFirstPKStressVector_PlaneStrain(const FloatArrayF< 5 > &vF, GaussPoint *gp, TimeStep *tStep) const; + /// Iteratively calls giveRealStressVector_3d to find the stress controlled equal to zero· + virtual FloatArray giveFirstPKStressVector_StressControl(const FloatArray &reducedvF, const IntArray &FControl, GaussPoint *gp, TimeStep *tStep) const; + /// Default implementation relies on giveFirstPKStressVector_StressControl + virtual FloatArrayF< 4 >giveFirstPKStressVector_PlaneStress(const FloatArrayF< 4 > &vF, GaussPoint *gp, TimeStep *tStep) const; + /// Default implementation relies on giveFirstPKStressVector_StressControl + virtual FloatArrayF< 1 >giveFirstPKStressVector_1d(const FloatArrayF< 1 > &vF, GaussPoint *gp, TimeStep *tStep) const; //@} /** @@ -257,8 +272,10 @@ class StructuralMaterial : public Material */ virtual void giveEshelbyStressVector_PlaneStrain(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedF, TimeStep *tStep); - void give_dPdF_from(const FloatMatrix &dSdE, FloatMatrix &answer, GaussPoint *gp); - void convert_dSdE_2_dPdF(FloatMatrix &answer, const FloatMatrix &dSdE, const FloatArray &S, const FloatArray &F, MaterialMode matMode); + static FloatMatrixF< 9, 9 >convert_dSdE_2_dPdF_3D(const FloatMatrixF< 6, 6 > &dSdE, const FloatArrayF< 6 > &S, const FloatArrayF< 9 > &F); + static FloatMatrixF< 5, 5 >convert_dSdE_2_dPdF_PlaneStrain(const FloatMatrixF< 4, 4 > &dSdE, const FloatArrayF< 4 > &S, const FloatArrayF< 5 > &F); + static FloatMatrixF< 4, 4 >convert_dSdE_2_dPdF_PlaneStress(const FloatMatrixF< 3, 3 > &dSdE, const FloatArrayF< 3 > &S, const FloatArrayF< 4 > &F); + static FloatMatrixF< 1, 1 >convert_dSdE_2_dPdF_1D(const FloatMatrixF< 1, 1 > &dSdE, const FloatArrayF< 1 > &S, const FloatArrayF< 1 > &F); /** * Returns a vector of coefficients of thermal dilatation in direction of each material principal (local) axis. @@ -266,7 +283,7 @@ class StructuralMaterial : public Material * @param gp Integration point. * @param tStep Time step (most models are able to respond only when tStep is current time step). */ - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + virtual FloatArrayF< 6 >giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const; /** * Returns the reference temperature of receiver. */ @@ -281,10 +298,8 @@ class StructuralMaterial : public Material * @param tStep Time step (most models are able to respond only when tStep is current time step). * @param mode Determines response mode (Total or incremental). */ - virtual void computeStressIndependentStrainVector(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep, ValueModeType mode); - virtual void computeStressIndependentStrainVector_3d(FloatArray &answer, - GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + virtual FloatArray computeStressIndependentStrainVector(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const; + FloatArrayF< 6 >computeStressIndependentStrainVector_3d(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const; /// Common functions for convenience //@{ /** @@ -294,6 +309,22 @@ class StructuralMaterial : public Material * @param mode Stress strain principal mode.. */ static void computePrincipalValues(FloatArray &answer, const FloatArray &s, stressStrainPrincMode mode); + /** + * Compute principal values of a stress/strain matrix. Matrix must be symmetric. + * @param answer Computed principal values. + * @param s Symmetric matrix. + * @return Sorted eigenvalues. + */ + static FloatArrayF< 3 >computePrincipalValues(const FloatMatrixF< 3, 3 > &s); + + /** + * Compute principal values from invariants. + * @param I1 First invariant + * @param I2 Second invariant + * @param I3 Third invariant + * @return Sorted list of principal values. + */ + static FloatArrayF< 3 >computePrincipalValues(double I1, double I2, double I3); /** * Computes principal values and directions of stress or strain vector. * @param answer Computed principal values. @@ -301,8 +332,14 @@ class StructuralMaterial : public Material * @param s Stress/strain vector. * @param mode Stress strain principal mode. */ - static void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir, const FloatArray &s, - stressStrainPrincMode mode); + static void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir, const FloatArray &s, stressStrainPrincMode mode); + /** + * Computes principal values and directions of stress or strain matrix (must be symmetric). + * @param dir Principal directions (stored column wise). + * @param s Stress/strain matrix. + * @return Computed principal values. + */ + static std::pair< FloatArrayF< 3 >, FloatMatrixF< 3, 3 > >computePrincipalValDir(const FloatMatrixF< 3, 3 > &s); /** * Computes split of receiver into deviatoric and volumetric part. @@ -310,27 +347,28 @@ class StructuralMaterial : public Material * @param s Input vector * @return Volumetric part (diagonal components divided by 3). */ - static double computeDeviatoricVolumetricSplit(FloatArray &dev, const FloatArray &s); - static void computeDeviatoricVolumetricSum(FloatArray &s, const FloatArray &dev, double mean); + static FloatArrayF< 6 >computeDeviator(const FloatArrayF< 6 > &s); + static std::pair< FloatArrayF< 6 >, double >computeDeviatoricVolumetricSplit(const FloatArrayF< 6 > &s); + static FloatArrayF< 6 >computeDeviatoricVolumetricSum(const FloatArrayF< 6 > &dev, double mean); - static void applyDeviatoricElasticCompliance(FloatArray &strain, const FloatArray &stress, double EModulus, double nu); - static void applyDeviatoricElasticCompliance(FloatArray &strain, const FloatArray &stress, double GModulus); + static FloatArrayF< 6 >applyDeviatoricElasticCompliance(const FloatArrayF< 6 > &stress, double EModulus, double nu); + static FloatArrayF< 6 >applyDeviatoricElasticCompliance(const FloatArrayF< 6 > &stress, double GModulus); - static void applyDeviatoricElasticStiffness(FloatArray &stress, const FloatArray &strain, double EModulus, double nu); - static void applyDeviatoricElasticStiffness(FloatArray &stress, const FloatArray &strain, double GModulus); - - static void applyElasticStiffness(FloatArray &stress, const FloatArray &strain, double EModulus, double nu); - static void applyElasticCompliance(FloatArray &strain, const FloatArray &stress, double EModulus, double nu); + static FloatArrayF< 6 >applyDeviatoricElasticStiffness(const FloatArrayF< 6 > &strain, double EModulus, double nu); + static FloatArrayF< 6 >applyDeviatoricElasticStiffness(const FloatArrayF< 6 > &strain, double GModulus); - static double computeStressNorm(const FloatArray &stress); + static FloatArrayF< 6 >applyElasticStiffness(const FloatArrayF< 6 > &strain, double EModulus, double nu); + static FloatArrayF< 6 >applyElasticCompliance(const FloatArrayF< 6 > &stress, double EModulus, double nu); - static double computeFirstInvariant(const FloatArray &s); - static double computeSecondStressInvariant(const FloatArray &s); - static double computeThirdStressInvariant(const FloatArray &s); + static double computeStressNorm(const FloatArrayF< 6 > &stress); - static double computeFirstCoordinate(const FloatArray &s); - static double computeSecondCoordinate(const FloatArray &s); - static double computeThirdCoordinate(const FloatArray &s); + static double computeFirstInvariant(const FloatArrayF< 6 > &s); + static double computeSecondStressInvariant(const FloatArrayF< 6 > &s); + static double computeThirdStressInvariant(const FloatArrayF< 6 > &s); + + static double computeFirstCoordinate(const FloatArrayF< 6 > &s); + static double computeSecondCoordinate(const FloatArrayF< 6 > &s); + static double computeThirdCoordinate(const FloatArrayF< 6 > &s); //@} /** @@ -341,16 +379,29 @@ class StructuralMaterial : public Material * @param gp Integration point. * @param tStep Time step (most models are able to respond only when tStep is current time step). */ - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) + virtual FloatMatrixF< 6, 6 >give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("not implemented "); } - virtual void give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, TimeStep *tStep); + /** + * Computes the large strain stiffness matrix for giveFirstPKStressVector of receiver in given integration point, respecting its history. + * The algorithm should use temporary or equilibrium history variables stored in integration point status + * to compute and return required result. + * @param answer Contains result. + * @param mode Material response mode. + * @param gp Integration point. + * @param tStep Time step (most models are able to respond only when tStep is current time step). + */ + virtual void giveStiffnessMatrix_dPdF(FloatMatrix &answer, + MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep); + + + + + virtual FloatMatrixF< 9, 9 >give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, + GaussPoint *gp, TimeStep *tStep) const; virtual void give3dMaterialStiffnessMatrix_dCde(FloatMatrix &answer, MatResponseMode mode, @@ -437,12 +488,10 @@ class StructuralMaterial : public Material * @param mode Determines value mode. */ void giveStressDependentPartOfStrainVector(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrainVector, - TimeStep *tStep, ValueModeType mode); - void giveStressDependentPartOfStrainVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedStrainVector, - TimeStep *tStep, ValueModeType mode); + TimeStep *tStep, ValueModeType mode) const; - virtual int setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type); - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int setIPValue(const FloatArray &value, GaussPoint *gp, InternalStateType type) override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; /** * Method for computing plane stress stiffness matrix of receiver. @@ -457,13 +506,8 @@ class StructuralMaterial : public Material * @param tStep Time step (most models are able to respond only when tStep is current time step). */ //@{ - virtual void givePlaneStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); - - virtual void givePlaneStressStiffMtrx_dPdF(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); + virtual FloatMatrixF< 3, 3 >givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatMatrixF< 4, 4 >givePlaneStressStiffnessMatrix_dPdF(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const; virtual void givePlaneStressStiffMtrx_dCde(FloatMatrix &answer, MatResponseMode mmode, GaussPoint *gp, @@ -488,13 +532,8 @@ class StructuralMaterial : public Material * @param tStep Time step (most models are able to respond only when tStep is current time step). */ //@{ - virtual void givePlaneStrainStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); - - virtual void givePlaneStrainStiffMtrx_dPdF(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); + virtual FloatMatrixF< 4, 4 >givePlaneStrainStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatMatrixF< 5, 5 >givePlaneStrainStiffnessMatrix_dPdF(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const; virtual void givePlaneStrainStiffMtrx_dCde(FloatMatrix &answer, MatResponseMode mmode, GaussPoint *gp, @@ -508,19 +547,14 @@ class StructuralMaterial : public Material * However, this reduction is quite time consuming and if it is possible, * it is recommended to overload this method and provide direct method for computing * particular stiffness matrix. - * @param answer Stiffness matrix. * @param mmode Material response mode. * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). + * @return Stiffness matrix. */ //@{ - virtual void give1dStressStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); - - virtual void give1dStressStiffMtrx_dPdF(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); + virtual FloatMatrixF< 1, 1 >give1dStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const; + virtual FloatMatrixF< 1, 1 >give1dStressStiffnessMatrix_dPdF(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const; virtual void give1dStressStiffMtrx_dCde(FloatMatrix &answer, MatResponseMode mmode, GaussPoint *gp, @@ -539,9 +573,7 @@ class StructuralMaterial : public Material * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). */ - virtual void give2dBeamLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); + virtual FloatMatrixF< 2, 2 >give2dBeamLayerStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const; /** * Method for computing 2d plate layer stiffness matrix of receiver. * Default implementation computes 3d stiffness matrix using give3dMaterialStiffnessMatrix and @@ -554,9 +586,7 @@ class StructuralMaterial : public Material * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). */ - virtual void givePlateLayerStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); + virtual FloatMatrixF< 5, 5 >givePlateLayerStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const; /** * Method for computing 1d fiber stiffness matrix of receiver. * Default implementation computes 3d stiffness matrix using give3dMaterialStiffnessMatrix and @@ -569,56 +599,26 @@ class StructuralMaterial : public Material * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). */ - virtual void giveFiberStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); - - - /** - * Method for computing 2d lattice stiffness matrix of receiver. - * @param answer Stiffness matrix. - * @param mmode Material response mode. - * @param gp Integration point, which load history is used. - * @param tStep Time step (most models are able to respond only when tStep is current time step). - */ - virtual void give2dLatticeStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); - - /** - * Method for computing 3d lattice stiffness matrix of receiver. - * @param answer Stiffness matrix. - * @param mmode Material response mode. - * @param gp Integration point, which load history is used. - * @param tStep Time step (most models are able to respond only when tStep is current time step). - */ - virtual void give3dLatticeStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); - + virtual FloatMatrixF< 3, 3 >giveFiberStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const; /** * Method for computing stiffness matrix of plate subsoil model. * Default method is emty; the implementation should be provided by the particular model. - * @param answer Stiffness matrix. * @param mmode Material response mode. * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). + * @return Stiffness matrix. */ - virtual void give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); + virtual FloatMatrixF< 3, 3 >give2dPlateSubSoilStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const; /** * Method for computing stiffness matrix of beam3d subsoil model. * Default method is emty; the implementation should be provided by the particular model. - * @param answer Stiffness matrix. * @param mmode Material response mode. * @param gp Integration point, which load history is used. * @param tStep Time step (most models are able to respond only when tStep is current time step). + * @return Stiffness matrix. */ - virtual void give3dBeamSubSoilStiffMtrx(FloatMatrix &answer, - MatResponseMode mmode, GaussPoint *gp, - TimeStep *tStep); + virtual FloatMatrixF< 6, 6 >give3dBeamSubSoilStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const; /** * Transforms 3d strain vector into another coordinate system. * @param answer Transformed strain vector @@ -628,8 +628,8 @@ class StructuralMaterial : public Material * @param strainVector 3d strain. * @param transpose Determines if we transpose matrix before transforming. */ - static void transformStrainVectorTo(FloatArray &answer, const FloatMatrix &base, - const FloatArray &strainVector, bool transpose = false); + static FloatArrayF< 6 >transformStrainVectorTo(const FloatMatrixF< 3, 3 > &base, + const FloatArrayF< 6 > &strain, bool transpose = false); /** * Transforms 3d stress vector into another coordinate system. * @param answer Transformed stress vector. @@ -639,53 +639,50 @@ class StructuralMaterial : public Material * @param stressVector Transformed 3d strain. * @param transpose Determines if we transpose matrix before transforming. */ - static void transformStressVectorTo(FloatArray &answer, const FloatMatrix &base, - const FloatArray &stressVector, bool transpose = false); - + static FloatArrayF< 6 >transformStressVectorTo(const FloatMatrixF< 3, 3 > &base, + const FloatArrayF< 6 > &stress, bool transpose = false); /** * Computes equivalent of von Mises stress. Returns 0 if six stress components do not exist on the material. * @param currentStress Stress vector given by 6 components. */ - static double computeVonMisesStress(const FloatArray *currentStress); + static double computeVonMisesStress(const FloatArray ¤tStress); + static double computeVonMisesStress_3D(const FloatArrayF< 6 > &stress); + static double computeVonMisesStress_PlaneStress(const FloatArrayF< 3 > &stress); /** * Computes 3d strain vector transformation matrix from standard vector transformation matrix. - * @param answer Transformation matrix for strain vector. * @param base A (3,3) matrix, where on each column are stored unit direction vectors of * local coordinate axes to which we do transformation. * @param transpose Determines if we transpose matrix before transforming. + * @returns Transformation matrix for strain vector. */ - static void giveStrainVectorTranformationMtrx(FloatMatrix &answer, const FloatMatrix &base, - bool transpose = false); + static FloatMatrixF< 6, 6 >giveStrainVectorTranformationMtrx(const FloatMatrixF< 3, 3 > &base, bool transpose = false); /** * Computes 2d strain vector transformation matrix from standard vector transformation matrix. - * @param answer Transformation matrix for strain vector. * @param base A (2,2) matrix, where on each column are stored unit direction vectors of * local coordinate axes to which we do transformation. * @param transpose Determines if we transpose matrix before transforming. + * @returns Transformation matrix for strain vector. */ - static void give2DStrainVectorTranformationMtrx(FloatMatrix &answer, const FloatMatrix &base, - bool transpose = false); - + static FloatMatrixF< 3, 3 >give2DStrainVectorTranformationMtrx(const FloatMatrixF< 2, 2 > &base, bool transpose = false); + /** * Computes 3d stress vector transformation matrix from standard vector transformation matrix. - * @param answer Transformation matrix for stress vector. * @param base A (3,3) matrix, where on each column are stored unit direction vectors of * local coordinate axes to which we do transformation. * @param transpose Determines if we transpose matrix before transforming. + * @returns Transformation matrix for stress vector. */ - static void giveStressVectorTranformationMtrx(FloatMatrix &answer, const FloatMatrix &base, - bool transpose = false); + static FloatMatrixF< 6, 6 >giveStressVectorTranformationMtrx(const FloatMatrixF< 3, 3 > &base, bool transpose = false); /** * Computes 2d stress vector transformation matrix from standard vector transformation matrix. - * @param answer Transformation matrix for stress vector. * @param base A (2,2) matrix, where on each column are stored unit direction vectors of * local coordinate axes to which we do transformation. * @param transpose Determines if we transpose matrix before transforming. + * @return Transformation matrix for stress vector. */ - static void givePlaneStressVectorTranformationMtrx(FloatMatrix &answer, const FloatMatrix &base, - bool transpose = false); + static FloatMatrixF< 3, 3 >givePlaneStressVectorTranformationMtrx(const FloatMatrixF< 2, 2 > &base, bool transpose = false); /** * Method for sorting newly computed principal values (pVal) and * corresponding principal directions (pDir) to be closed @@ -695,7 +692,7 @@ class StructuralMaterial : public Material * @param pDir New eigenvectors. * @param toPDir Old eigenvector. */ - static void sortPrincDirAndValCloseTo(FloatArray *pVal, FloatMatrix *pDir, FloatMatrix *toPDir); + static void sortPrincDirAndValCloseTo(FloatArray &pVal, FloatMatrix &pDir, const FloatMatrix &toPDir); friend class CrossSection; friend class StructuralCrossSection; diff --git a/src/sm/Materials/structuralms.C b/src/sm/Materials/structuralms.C index d240e1a64..68d198080 100644 --- a/src/sm/Materials/structuralms.C +++ b/src/sm/Materials/structuralms.C @@ -32,15 +32,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Materials/structuralms.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" #include "contextioerr.h" -#include "../sm/Elements/nlstructuralelement.h" +#include "sm/Elements/nlstructuralelement.h" #include "gausspoint.h" namespace oofem { -StructuralMaterialStatus :: StructuralMaterialStatus(int n, Domain *d, GaussPoint *g) : - MaterialStatus(n, d, g), strainVector(), stressVector(), +StructuralMaterialStatus :: StructuralMaterialStatus(GaussPoint *g) : + MaterialStatus(g), strainVector(), stressVector(), tempStressVector(), tempStrainVector(), FVector(), tempFVector() { int rsize = StructuralMaterial :: giveSizeOfVoigtSymVector( gp->giveMaterialMode() ); @@ -56,38 +56,51 @@ StructuralMaterialStatus :: StructuralMaterialStatus(int n, Domain *d, GaussPoin return; } if ( NLStructuralElement * el = dynamic_cast< NLStructuralElement * >( gp->giveElement() ) ) { - if ( el->giveGeometryMode() == 1 ) { // if large def, initialize F and P - PVector.resize(9); - FVector.resize(9); - FVector.at(1) = FVector.at(2) = FVector.at(3) = 1.; - } - tempPVector = PVector; - tempFVector = FVector; + if ( el->giveGeometryMode() == 1 ) { // if large def, initialize F and P + PVector.resize(9); + FVector.resize(9); + FVector.at(1) = FVector.at(2) = FVector.at(3) = 1.; + tempPVector = PVector; + tempFVector = FVector; + + } } -} - -StructuralMaterialStatus :: ~StructuralMaterialStatus() { } +} -void StructuralMaterialStatus :: printOutputAt(FILE *File, TimeStep *tStep) +void StructuralMaterialStatus :: printOutputAt(FILE *File, TimeStep *tStep) const // Prints the strains and stresses on the data file. { FloatArray helpVec; MaterialStatus :: printOutputAt(File, tStep); - - fprintf(File, " strains "); - StructuralMaterial :: giveFullSymVectorForm( helpVec, strainVector, gp->giveMaterialMode() ); - for ( auto &var : helpVec ) { - fprintf( File, " %.4e", var ); - } - - fprintf(File, "\n stresses"); - StructuralMaterial :: giveFullSymVectorForm( helpVec, stressVector, gp->giveMaterialMode() ); - - for ( auto &var : helpVec ) { - fprintf( File, " %.4e", var ); + NLStructuralElement * el = static_cast< NLStructuralElement * >( gp->giveElement()); + if ( el->giveGeometryMode() == 1) { + fprintf(File, " F "); + StructuralMaterial :: giveFullVectorFormF( helpVec, FVector, gp->giveMaterialMode() ); + for ( auto &var : helpVec ) { + fprintf( File, " %+.4e", var ); + } + + fprintf(File, "\n P"); + StructuralMaterial :: giveFullVectorForm( helpVec, PVector, gp->giveMaterialMode() ); + for ( auto &var : helpVec ) { + fprintf( File, " %+.4e", var ); + } + } else { + fprintf(File, " strains "); + StructuralMaterial :: giveFullSymVectorForm( helpVec, strainVector, gp->giveMaterialMode() ); + for ( auto &var : helpVec ) { + fprintf( File, " %+.4e", var ); + } + + fprintf(File, "\n stresses"); + StructuralMaterial :: giveFullSymVectorForm( helpVec, stressVector, gp->giveMaterialMode() ); + + for ( auto &var : helpVec ) { + fprintf( File, " %+.4e", var ); + } } fprintf(File, "\n"); } @@ -129,18 +142,12 @@ void StructuralMaterialStatus :: initTempStatus() } -contextIOResultType -StructuralMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full ms context (saves state variables, that completely describe -// current state) +void +StructuralMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = MaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + MaterialStatus :: saveContext(stream, mode); + contextIOResultType iores; if ( ( iores = strainVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -148,24 +155,15 @@ StructuralMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, vo if ( ( iores = stressVector.storeYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } -contextIOResultType -StructuralMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full material context (saves state variables, that completely describe -// current state) -// +void +StructuralMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = MaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + MaterialStatus :: restoreContext(stream, mode); + contextIOResultType iores; if ( ( iores = strainVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } @@ -173,14 +171,11 @@ StructuralMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, if ( ( iores = stressVector.restoreYourself(stream) ) != CIO_OK ) { THROW_CIOERR(iores); } - - return CIO_OK; } void StructuralMaterialStatus :: copyStateVariables(const MaterialStatus &iStatus) { - MaterialStatus &tmpStat = const_cast< MaterialStatus & >(iStatus); - const StructuralMaterialStatus &structStatus = dynamic_cast< StructuralMaterialStatus & >(tmpStat); + const StructuralMaterialStatus &structStatus = static_cast< const StructuralMaterialStatus & >(iStatus); strainVector = structStatus.giveStrainVector(); stressVector = structStatus.giveStressVector(); diff --git a/src/sm/Materials/structuralms.h b/src/sm/Materials/structuralms.h index d4e9387d9..a3ccdfc4d 100644 --- a/src/sm/Materials/structuralms.h +++ b/src/sm/Materials/structuralms.h @@ -62,7 +62,7 @@ class Domain; * - printingYourself() * - updating Yourself after a new equilibrium state has been reached. */ -class StructuralMaterialStatus : public MaterialStatus, public MaterialStatusMapperInterface +class OOFEM_EXPORT StructuralMaterialStatus : public MaterialStatus, public MaterialStatusMapperInterface { protected: /// Equilibrated strain vector in reduced form @@ -88,18 +88,16 @@ class StructuralMaterialStatus : public MaterialStatus, public MaterialStatusMap FloatArray tempFVector; public: - /// Constructor. Creates new StructuralMaterialStatus with number n, belonging to domain d and IntegrationPoint g. - StructuralMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~StructuralMaterialStatus(); + /// Constructor. Creates new StructuralMaterialStatus with IntegrationPoint g. + StructuralMaterialStatus(GaussPoint * g); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; /// Returns the const pointer to receiver's strain vector. const FloatArray &giveStrainVector() const { return strainVector; } @@ -142,11 +140,11 @@ class StructuralMaterialStatus : public MaterialStatus, public MaterialStatusMap /// Assigns tempFVector to given vector v void letTempFVectorBe(const FloatArray &v) { tempFVector = v; } - virtual const char *giveClassName() const { return "StructuralMaterialStatus"; } + const char *giveClassName() const override { return "StructuralMaterialStatus"; } /// Functions for MaterialStatusMapperInterface - virtual void copyStateVariables(const MaterialStatus &iStatus); - virtual void addStateVariables(const MaterialStatus &iStatus); + void copyStateVariables(const MaterialStatus &iStatus) override; + void addStateVariables(const MaterialStatus &iStatus) override; }; } // end namespace oofem #endif // structuralms_h diff --git a/src/sm/Materials/structuralnonlocalmaterialext.h b/src/sm/Materials/structuralnonlocalmaterialext.h index 87c2049e3..9206b4065 100644 --- a/src/sm/Materials/structuralnonlocalmaterialext.h +++ b/src/sm/Materials/structuralnonlocalmaterialext.h @@ -83,7 +83,7 @@ class StructuralNonlocalMaterialExtensionInterface : public NonlocalMaterialExte * @param gp Integration point to update. * @param tStep Solution step indicating time of update. */ - virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) = 0; + virtual void updateBeforeNonlocAverage(const FloatArray &strainVector, GaussPoint *gp, TimeStep *tStep) const = 0; }; } // end namespace oofem #endif // structuralnonlocalmaterialext_h diff --git a/src/sm/Materials/structuralpythonmaterial.C b/src/sm/Materials/structuralpythonmaterial.C index edbe1f6b3..9c1f0bcc9 100644 --- a/src/sm/Materials/structuralpythonmaterial.C +++ b/src/sm/Materials/structuralpythonmaterial.C @@ -44,30 +44,19 @@ REGISTER_Material(StructuralPythonMaterial); StructuralPythonMaterial :: StructuralPythonMaterial(int n, Domain *d) : StructuralMaterial(n, d) -#if 0 - smallDef(NULL), - smallDefTangent(NULL), - largeDef(NULL), - largeDefTangent(NULL) -#endif {} -StructuralPythonMaterial :: ~StructuralPythonMaterial() -{ -/// if ( mpModule ) Py_DECREF(mpModule); -} -IRResultType StructuralPythonMaterial :: initializeFrom(InputRecord *ir) +void StructuralPythonMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; - - result = StructuralMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + StructuralMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->moduleName, _IFT_StructuralPythonMaterial_moduleName); - module=bp::import(moduleName.c_str()); - if(!module){ OOFEM_WARNING("Module %s not importable.",moduleName.c_str()); return IRRT_BAD_FORMAT; } + module = bp::import(moduleName.c_str()); + if ( !module ) { + throw ValueInputException(ir, _IFT_StructuralPythonMaterial_moduleName, "Module not importable."); + } // lambda for finding function and checking that it is callable // returns true (OK) if the function was not found, or was found and it callable // returns false (not OK) if the function was found but is not callable @@ -79,44 +68,16 @@ IRResultType StructuralPythonMaterial :: initializeFrom(InputRecord *ir) return true; }; // try to find all necessary functions; false means the function is not callable, in which case warning was already printed above - if(!(tryDef("computeStress",smallDef) && tryDef("computePK1Stress",largeDef) && tryDef("computeStressTangent",smallDefTangent) && tryDef("computePK1StressTangent",largeDefTangent))){ return IRRT_BAD_FORMAT; } - if(!smallDefTangent && !!smallDef){ OOFEM_WARNING("Using numerical tangent for small deformations."); } - if(!largeDefTangent && !!largeDef){ OOFEM_WARNING("Using numerical tangent for large deformations."); } - if(!smallDef && !largeDef){ OOFEM_WARNING("No functions for small/large deformations found."); return IRRT_BAD_FORMAT; } - - - - -#if 0 - // Import Python file - PyObject *mpName = PyString_FromString( this->moduleName.c_str() ); - this->mpModule = PyImport_Import(mpName); - Py_DECREF(mpName); - - if ( mpModule != NULL ) { - // Load and call Python function - smallDef = PyObject_GetAttrString(mpModule, "computeStress"); - largeDef = PyObject_GetAttrString(mpModule, "computePK1Stress"); - smallDefTangent = PyObject_GetAttrString(mpModule, "computeStressTangent"); - largeDefTangent = PyObject_GetAttrString(mpModule, "computePK1StressTangent"); - if ( smallDefTangent == NULL && smallDef != NULL) { - OOFEM_WARNING("Using numerical tangent for small deformations"); - } - if ( largeDefTangent == NULL && largeDef != NULL) { - OOFEM_WARNING("Using numerical tangent for large deformations"); - } - if ( smallDef == NULL && largeDef == NULL ) { - OOFEM_WARNING("No functions for either small or large deformations supplied. Are you sure the functions are named correctly?"); - return IRRT_BAD_FORMAT; - } - } else { - OOFEM_WARNING("mpModule == NULL for module name %s", this->moduleName.c_str()); - return IRRT_BAD_FORMAT; + if ( !(tryDef("computeStress",smallDef) && tryDef("computePK1Stress",largeDef) && tryDef("computeStressTangent",smallDefTangent) && tryDef("computePK1StressTangent",largeDefTangent))) { + throw ValueInputException(ir, _IFT_StructuralPythonMaterial_moduleName, "missing functions"); + } + if ( !smallDefTangent && !!smallDef ){ OOFEM_WARNING("Using numerical tangent for small deformations."); } + if ( !largeDefTangent && !!largeDef ){ OOFEM_WARNING("Using numerical tangent for large deformations."); } + if ( !smallDef && !largeDef ) { + throw ValueInputException(ir, _IFT_StructuralPythonMaterial_moduleName, "No functions for small/large deformations found."); } -#endif - pert = 1e-12; - return IRRT_OK; + pert = 1e-12; } void StructuralPythonMaterial :: giveInputRecord(DynamicInputRecord &input) @@ -128,109 +89,19 @@ void StructuralPythonMaterial :: giveInputRecord(DynamicInputRecord &input) MaterialStatus *StructuralPythonMaterial :: CreateStatus(GaussPoint *gp) const { - return new StructuralPythonMaterialStatus(this->giveDomain(), gp); + return new StructuralPythonMaterialStatus(gp); } -void StructuralPythonMaterial :: callStressFunction(bp::object func, const FloatArray &oldStrain, const FloatArray &oldStress, const FloatArray &strain, FloatArray &stress, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const +FloatArray StructuralPythonMaterial :: callStressFunction(bp::object func, const FloatArray &oldStrain, const FloatArray &oldStress, const FloatArray &strain, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const { // pass mutable args via bp::ref // pass "const" args without, which by default results in a new copy, ensuring the original won't be modified - func(oldStrain,oldStress,strain,stress,stateDict,tempStateDict,tStep->giveTargetTime()); - -#if 0 - if ( !PyCallable_Check(func) ) { - OOFEM_ERROR("Python function is not callable."); - } - - // Build the argument list; - double size = strain.giveSize(); - PyObject *pArgs = PyTuple_New(5); - - PyObject *pArgOldStrain = PyList_New(size); - PyObject *pArgOldStress = PyList_New(size); - PyObject *pArgStrain = PyList_New(size); - - for ( int i = 0; i < size; i++ ) { - PyList_SET_ITEM( pArgOldStrain, i, PyFloat_FromDouble( oldStrain[i] ) ); - PyList_SET_ITEM( pArgOldStress, i, PyFloat_FromDouble( oldStress[i] ) ); - PyList_SET_ITEM( pArgStrain, i, PyFloat_FromDouble( strain[i] ) ); - } - - // PyTuple_SetItem takes over responsibility for objects passed to it -> no DECREF - PyTuple_SetItem(pArgs, 0, pArgOldStrain); - PyTuple_SetItem(pArgs, 1, pArgOldStress); - PyTuple_SetItem(pArgs, 2, pArgStrain); - // Internal state variables - Py_INCREF(stateDict); ///@todo Verify this; we don't want pArgs to take over ownership, so is this the right thing to do? / Mikael - PyTuple_SetItem(pArgs, 3, stateDict); - Py_INCREF(tempStateDict); - PyTuple_SetItem(pArgs, 4, tempStateDict); - // Time - PyTuple_SetItem(pArgs, 5, PyFloat_FromDouble( tStep->giveTargetTime() )); - // Call the function; - PyObject *retVal = PyObject_CallObject(func, pArgs); - - // Convert function output back to C++ form: - stress.resize(size); - for ( int i = 0; i < size; i++ ) { - PyObject *val = PyList_GET_ITEM(retVal, i); - stress[i] = PyFloat_AS_DOUBLE(val); - //Py_DECREF(val); - } - - Py_DECREF(retVal); - Py_DECREF(pArgs); -#endif + return bp::extract(func(oldStrain, oldStress, strain, stateDict, tempStateDict, tStep->giveTargetTime())); } -void StructuralPythonMaterial :: callTangentFunction(FloatMatrix &answer, bp::object func, const FloatArray &strain, const FloatArray &stress, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const +FloatMatrix StructuralPythonMaterial :: callTangentFunction(bp::object func, const FloatArray &oldStrain, const FloatArray &oldStress, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const { - answer=bp::extract(func(strain,stress,stateDict,tempStateDict,tStep->giveTargetTime())); -#if 0 - if ( !PyCallable_Check(func) ) { - OOFEM_ERROR("Python function is not callable."); - } - - // Build the argument list; - double size = strain.giveSize(); - PyObject *pArgs = PyTuple_New(4); - - PyObject *pArgStrain = PyList_New(size); - PyObject *pArgStress = PyList_New(size); - - for ( int i = 0; i < size; i++ ) { - PyList_SET_ITEM( pArgStrain, i, PyFloat_FromDouble( strain[i] ) ); - PyList_SET_ITEM( pArgStress, i, PyFloat_FromDouble( stress[i] ) ); - } - // PyTuple_SetItem takes over responsibility for objects passed to it -> no DECREF - PyTuple_SetItem(pArgs, 0, pArgStrain); - PyTuple_SetItem(pArgs, 1, pArgStress); - // Internal state variables - Py_INCREF(stateDict); ///@todo Verify this; we don't want pArgs to take over ownership, so is this the right thing to do? / Mikael - PyTuple_SetItem(pArgs, 2, stateDict); - Py_INCREF(tempStateDict); ///@todo Verify this; we don't want pArgs to take over ownership, so is this the right thing to do? / Mikael - PyTuple_SetItem(pArgs, 3, tempStateDict); - // Time - PyTuple_SetItem(pArgs, 4, PyFloat_FromDouble( tStep->giveTargetTime() )); - // Call the function; - PyObject *retVal = PyObject_CallObject(func, pArgs); - - if ( retVal == NULL ) { - OOFEM_ERROR("bad return value (null) from PyObject_CallObject"); - } - // Convert function output back to C++ form: - answer.resize(size, size); - for ( int i = 0; i < size; i++ ) { - PyObject *row = PyList_GET_ITEM(retVal, i); // Get item just borrows the reference, don't DECREF - for ( int j = 0; j < size; j++ ) { - PyObject *val = PyList_GET_ITEM(row, j); - answer(i, j) = PyFloat_AS_DOUBLE(val); - } - } - - Py_DECREF(retVal); - Py_DECREF(pArgs); -#endif + return bp::extract(func(oldStrain, oldStress, stateDict, tempStateDict, tStep->giveTargetTime())); } void StructuralPythonMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) @@ -238,11 +109,12 @@ void StructuralPythonMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answ StructuralPythonMaterialStatus *ms = dynamic_cast< StructuralPythonMaterialStatus * >( this->giveStatus(gp) ); if ( this->smallDefTangent ) { - this->callTangentFunction(answer, this->smallDefTangent, ms->giveTempStrainVector(), ms->giveTempStressVector(), ms->giveStateDictionary(), ms->giveTempStateDictionary(), tStep); + answer = this->callTangentFunction(this->smallDefTangent, ms->giveTempStrainVector(), ms->giveTempStressVector(), ms->giveStateDictionary(), ms->giveTempStateDictionary(), tStep); } else { - FloatArray vE, vE_h, stress, stressh; - vE = ms->giveTempStrainVector(); - stress = ( ( StructuralMaterialStatus * ) gp->giveMaterialStatus() )->giveTempStressVector(); + FloatArray vE_h, stress, stressh; + const auto &vE = ms->giveTempStrainVector(); +// const auto &stress = ms->giveTempStressVector(); + stress = ms->giveTempStressVector(); answer.resize(6, 6); for ( int i = 1; i <= 6; ++i ) { vE_h = vE; @@ -259,28 +131,27 @@ void StructuralPythonMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answ } -void StructuralPythonMaterial :: give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<9,9> StructuralPythonMaterial :: give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { StructuralPythonMaterialStatus *ms = dynamic_cast< StructuralPythonMaterialStatus * >( this->giveStatus(gp) ); if ( this->largeDefTangent ) { - this->callTangentFunction(answer, this->largeDefTangent, ms->giveTempFVector(), ms->giveTempPVector(), ms->giveStateDictionary(), ms->giveTempStateDictionary(), tStep); + return this->callTangentFunction(this->largeDefTangent, ms->giveTempFVector(), ms->giveTempPVector(), ms->giveStateDictionary(), ms->giveTempStateDictionary(), tStep); } else { - FloatArray vF, vF_h, stress, stressh; - vF = ms->giveTempFVector(); - stress = ( ( StructuralMaterialStatus * ) gp->giveMaterialStatus() )->giveTempPVector(); - answer.resize(9, 9); + const FloatArrayF<9> vF = ms->giveTempFVector(); + const FloatArrayF<9> vP = ms->giveTempPVector(); + FloatMatrixF<9,9> tangent; for ( int i = 1; i <= 9; ++i ) { - vF_h = vF; + auto vF_h = vF; vF_h.at(i) += pert; - this->giveFirstPKStressVector_3d(stressh, gp, vF_h, tStep); - stressh.subtract(stress); - stressh.times(1.0 / pert); - answer.setColumn(stressh, i); + auto vPh = this->giveFirstPKStressVector_3d(vF_h, gp, tStep); + auto dvP = (vPh - vP) / pert; + tangent.setColumn(dvP, i); } // Reset the internal variables - this->giveFirstPKStressVector_3d(stress, gp, vF, tStep); + this->giveFirstPKStressVector_3d(vF, gp, tStep); + return tangent; } } @@ -288,13 +159,12 @@ void StructuralPythonMaterial :: give3dMaterialStiffnessMatrix_dPdF(FloatMatrix void StructuralPythonMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &strain, TimeStep *tStep) { - StructuralPythonMaterialStatus *ms = static_cast< StructuralPythonMaterialStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< StructuralPythonMaterialStatus * >( this->giveStatus(gp) ); ms->reinitTempStateDictionary(); - this->callStressFunction(this->smallDef, - ms->giveStrainVector(), ms->giveStressVector(), - strain, answer, + answer = this->callStressFunction(this->smallDef, + ms->giveStrainVector(), ms->giveStressVector(), strain, ms->giveStateDictionary(), ms->giveTempStateDictionary(), tStep); ms->letTempStrainVectorBe(strain); @@ -302,76 +172,53 @@ void StructuralPythonMaterial :: giveRealStressVector_3d(FloatArray &answer, Gau } -void StructuralPythonMaterial :: giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &vF, TimeStep *tStep) +FloatArrayF<9> StructuralPythonMaterial :: giveFirstPKStressVector_3d(const FloatArrayF<9> &vF, GaussPoint *gp, TimeStep *tStep) const { - StructuralPythonMaterialStatus *ms = static_cast< StructuralPythonMaterialStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< StructuralPythonMaterialStatus * >( this->giveStatus(gp) ); ms->reinitTempStateDictionary(); // Resets the temp dictionary to the equilibrated values - this->callStressFunction(this->smallDef, - ms->giveFVector(), ms->givePVector(), - vF, answer, + auto vP = this->callStressFunction(this->smallDef, + ms->giveFVector(), ms->givePVector(), vF, ms->giveStateDictionary(), ms->giveTempStateDictionary(), tStep); - FloatArray vE, vS; - FloatMatrix F, Finv, E, S; - F.beMatrixForm(vF); - Finv.beInverseOf(F); - // Compute Green-Lagrange strain - E.beTProductOf(F, F); - E.at(1, 1) -= 1.0; - E.at(2, 2) -= 1.0; - E.at(3, 3) -= 1.0; - E.times(0.5); - vE.beSymVectorFormOfStrain(E); + auto F = from_voigt_form(vF); + auto Finv = inv(F); + auto E = 0.5 * (Tdot(F, F) - eye<3>()); + auto vE = to_voigt_strain(E); // Convert from P to S - S.beProductOf(Finv, answer); - vS.beSymVectorForm(S); + auto P = from_voigt_form(vP); + auto S = dot(Finv, P); + auto vS = to_voigt_stress(S); ms->letTempStrainVectorBe(vE); ms->letTempStressVectorBe(vS); - ms->letTempPVectorBe(answer); + ms->letTempPVectorBe(vP); ms->letTempFVectorBe(vF); + + return vF;//TODO - Check what is returned } int StructuralPythonMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - StructuralPythonMaterialStatus *ms = static_cast< StructuralPythonMaterialStatus * >( this->giveStatus(gp) ); - bp::object val=ms->giveStateDictionary()[std::to_string(type).c_str()]; + auto ms = static_cast< StructuralPythonMaterialStatus * >( this->giveStatus(gp) ); + bp::object val = ms->giveStateDictionary()[std::to_string(type).c_str()]; // call parent if we don't have this type in our records - if(!val) return StructuralMaterial::giveIPValue(answer,gp,type,tStep); + if ( !val ) { + return StructuralMaterial::giveIPValue(answer, gp, type, tStep); + } bp::extract exNum(val); bp::extract exMat(val); - if(exNum.check()){ answer=FloatArray{exNum()}; return 1; } - else if(exMat.check()){ answer=exMat(); return 1;} + if ( exNum.check() ) { + answer = FloatArray{exNum()}; + return 1; + } else if ( exMat.check() ) { + answer=exMat(); + return 1; + } OOFEM_WARNING("Dictionary entry of material state not float or something convertible to FloatArray"); return 0; -#if 0 - std :: string s = std :: to_string( type ); - PyObject *val = PyDict_GetItemString(ms->giveStateDictionary(), s.c_str()); - if ( val ) { - - if ( PyFloat_Check(val) != 0 ) { - answer = FloatArray{PyFloat_AS_DOUBLE(val)}; - } else if ( PyList_Check(val) != 0 ) { - // Convert function output back to C++ form: - int size = PyList_Size(val); - answer.resize(size); - for ( int i = 0; i < size; i++ ) { - PyObject *val = PyList_GET_ITEM(val, i); - answer[i] = PyFloat_AS_DOUBLE(val); - //Py_DECREF(val); - } - return 1; - } else { - OOFEM_WARNING("Dictionary entry of material state is not a list (only lists supported for now)"); - return 0; - } - } - return StructuralMaterial :: giveIPValue(answer, gp, type, tStep); -#endif } @@ -385,39 +232,23 @@ void StructuralPythonMaterialStatus :: initTempStatus() } -StructuralPythonMaterialStatus :: StructuralPythonMaterialStatus(Domain *d, GaussPoint *gp) : - StructuralMaterialStatus(0, d, gp) +StructuralPythonMaterialStatus :: StructuralPythonMaterialStatus(GaussPoint *gp) : + StructuralMaterialStatus(gp) { -#if 0 - this->stateDict = PyDict_New(); - this->tempStateDict = PyDict_New(); -#endif } -StructuralPythonMaterialStatus :: ~StructuralPythonMaterialStatus() -{ -#if 0 - Py_DECREF(this->stateDict); - Py_DECREF(this->tempStateDict); -#endif -} void StructuralPythonMaterialStatus :: updateYourself(TimeStep *tStep) { StructuralMaterialStatus :: updateYourself(tStep); // Copy the temp dict to the equilibrated one this->stateDict = this->tempStateDict.copy(); ///@todo Does this suffice? I'm not sure about what happens to references into the dictionary itself. I want a deep copy. / Mikael -#if 0 - Py_DECREF(oldDict); -#endif } void StructuralPythonMaterialStatus :: reinitTempStateDictionary() { - //Py_DECREF(this->tempStateDict); - //this->tempStateDict = PyDict_Copy(this->stateDict); - tempStateDict=stateDict.copy(); + tempStateDict = stateDict.copy(); } diff --git a/src/sm/Materials/structuralpythonmaterial.h b/src/sm/Materials/structuralpythonmaterial.h index 900f9b6ae..f2385b906 100644 --- a/src/sm/Materials/structuralpythonmaterial.h +++ b/src/sm/Materials/structuralpythonmaterial.h @@ -38,15 +38,9 @@ #include namespace bp=boost::python; -#include "../sm/Materials/structuralmaterial.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" -#if 0 -#ifndef PyObject_HEAD -struct _object; -typedef _object PyObject; -#endif -#endif ///@name Input fields for StructuralPythonMaterial //@{ @@ -83,51 +77,40 @@ class StructuralPythonMaterial : public StructuralMaterial bp::object smallDef, smallDefTangent; // callables for large deformations bp::object largeDef, largeDefTangent; -#if 0 - /// Compiled function for small deformations - PyObject *smallDef; - PyObject *smallDefTangent; - - /// Compiled function for large deformations - PyObject *largeDef; - PyObject *largeDefTangent; -#endif /// Numerical pertubation for numerical tangents - double pert; + double pert = 1e-12; public: /// Constructor. StructuralPythonMaterial(int n, Domain * d); - /// Destructor. - virtual ~StructuralPythonMaterial(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - void callStressFunction(bp::object func, const FloatArray &oldStrain, const FloatArray &oldStress, const FloatArray &strain, FloatArray &stress, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const; - void callTangentFunction(FloatMatrix &answer, bp::object func, const FloatArray &strain, const FloatArray &stress, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const; + FloatArray callStressFunction(bp::object func, const FloatArray &oldStrain, const FloatArray &oldStress, const FloatArray &strain, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const; + + FloatMatrix callTangentFunction(bp::object func, const FloatArray &oldStrain, const FloatArray &oldStress, bp::object stateDict, bp::object tempStateDict, TimeStep *tStep) const; + + - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, - MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + void give3dMaterialStiffnessMatrix(FloatMatrix &answer, + MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); //TODO check override - virtual void give3dMaterialStiffnessMatrix_dPdF(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatMatrixF<9,9> give3dMaterialStiffnessMatrix_dPdF(MatResponseMode mode, GaussPoint *gp, + TimeStep *tStep) const override; - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedStrain, TimeStep *tStep); + void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, + const FloatArray &reducedStrain, TimeStep *tStep); //TODO check override - virtual void giveFirstPKStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &reducedF, TimeStep *tStep); + FloatArrayF<9> giveFirstPKStressVector_3d(const FloatArrayF<9> &vF, GaussPoint *gp, + TimeStep *tStep) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual int hasNonLinearBehaviour() { return true; } - virtual const char *giveClassName() const { return "StructuralPythonMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_StructuralPythonMaterial_Name; } + const char *giveClassName() const override { return "StructuralPythonMaterial"; } + const char *giveInputRecordName() const override { return _IFT_StructuralPythonMaterial_Name; } }; class StructuralPythonMaterialStatus : public StructuralMaterialStatus @@ -135,25 +118,19 @@ class StructuralPythonMaterialStatus : public StructuralMaterialStatus protected: /// Internal state variables bp::dict stateDict, tempStateDict; -#if 0 - PyObject *stateDict; - PyObject *tempStateDict; -#endif public: /// Constructor. - StructuralPythonMaterialStatus(Domain * d, GaussPoint * gp); - /// Destructor. - virtual ~StructuralPythonMaterialStatus(); + StructuralPythonMaterialStatus(GaussPoint * gp); - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; void reinitTempStateDictionary(); bp::object giveStateDictionary() { return stateDict; } bp::object giveTempStateDictionary() { return tempStateDict; } - virtual const char *giveClassName() const { return "StructuralPythonMaterialStatus"; } + const char *giveClassName() const override { return "StructuralPythonMaterialStatus"; } }; } // end namespace oofem #endif // structuralpythonmaterial_h diff --git a/src/sm/Materials/structuralslipfe2material.C b/src/sm/Materials/structuralslipfe2material.C new file mode 100644 index 000000000..cba49d1d6 --- /dev/null +++ b/src/sm/Materials/structuralslipfe2material.C @@ -0,0 +1,521 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "structuralslipfe2material.h" +#include "gausspoint.h" +#include "engngm.h" +#include "oofemtxtdatareader.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "dynamicinputrecord.h" +#include "classfactory.h" +#include "util.h" +#include "contextioerr.h" +#include "generalboundarycondition.h" +#include "prescribeddispsliphomogenization.h" +#include "exportmodulemanager.h" +#include "vtkxmlexportmodule.h" +#include "nummet.h" +#include "sm/EngineeringModels/xfemsolverinterface.h" +#include "sm/EngineeringModels/staticstructural.h" +#include "unknownnumberingscheme.h" +#include "xfem/xfemstructuremanager.h" +#include "mathfem.h" + +#include "dynamicdatareader.h" + +#include + +namespace oofem { +REGISTER_Material(StructuralSlipFE2Material); + +StructuralSlipFE2Material :: StructuralSlipFE2Material(int n, Domain *d) : StructuralFE2Material(n, d) +{} + + +void +StructuralSlipFE2Material :: initializeFrom(InputRecord &ir) +{ + StructuralFE2Material :: initializeFrom(ir); + + useExtStiff = ir.hasField(_IFT_StructuralSlipFE2Material_useExternalStiffness); + allGPRes = ir.hasField(_IFT_StructuralSlipFE2Material_allGPResults); + IR_GIVE_OPTIONAL_FIELD(ir, outputSelected, _IFT_StructuralSlipFE2Material_outputSelectedResults); + IR_GIVE_OPTIONAL_FIELD(ir, givendStressdEpsTangent, _IFT_StructuralSlipFE2Material_dStressdEps); + IR_GIVE_OPTIONAL_FIELD(ir, givendStressdEpsTangent, _IFT_StructuralSlipFE2Material_dStressdEps); + IR_GIVE_OPTIONAL_FIELD(ir, givendBStressdEpsTangent, _IFT_StructuralSlipFE2Material_dBStressdEps); + IR_GIVE_OPTIONAL_FIELD(ir, givendRStressdEpsTangent, _IFT_StructuralSlipFE2Material_dRStressdEps); + IR_GIVE_OPTIONAL_FIELD(ir, givendStressdSTangent, _IFT_StructuralSlipFE2Material_dStressdS); + IR_GIVE_OPTIONAL_FIELD(ir, givendBStressdSTangent, _IFT_StructuralSlipFE2Material_dBStressdS); + IR_GIVE_OPTIONAL_FIELD(ir, givendRStressdSTangent, _IFT_StructuralSlipFE2Material_dRStressdS); + IR_GIVE_OPTIONAL_FIELD(ir, givendStressdGTangent, _IFT_StructuralSlipFE2Material_dStressdG); + IR_GIVE_OPTIONAL_FIELD(ir, givendBStressdGTangent, _IFT_StructuralSlipFE2Material_dBStressdG); + IR_GIVE_OPTIONAL_FIELD(ir, givendRStressdGTangent, _IFT_StructuralSlipFE2Material_dRStressdG); +} + + +void +StructuralSlipFE2Material :: giveInputRecord(DynamicInputRecord &input) +{ + StructuralFE2Material :: giveInputRecord(input); + + if ( useExtStiff ) { + input.setField(_IFT_StructuralSlipFE2Material_useExternalStiffness); + input.setField(givendStressdEpsTangent, _IFT_StructuralSlipFE2Material_dStressdEps); + } + + input.setField(allGPRes, _IFT_StructuralSlipFE2Material_allGPResults); + input.setField(outputSelected, _IFT_StructuralSlipFE2Material_outputSelectedResults); +} + + +MaterialStatus * +StructuralSlipFE2Material :: CreateStatus(GaussPoint *gp) const +{ + int rank = -1; + auto emodel = this->domain->giveEngngModel(); + if ( emodel->isParallel() && emodel->giveNumberOfProcesses() > 1 ) { + rank = emodel->giveRank(); + } + + if ( !(outputSelected.giveSize()==0) ) { + std::vector gpArray; + gpArray.resize(outputSelected.giveSize()/2); + for (int i = 1; i <= outputSelected.giveSize()/2; i++) { + GaussPoint* gpOut = domain->giveGlobalElement(outputSelected.at(i*2-1))->giveIntegrationRule(0)->getIntegrationPoint(outputSelected.at(i*2) - 1); + gpArray[i - 1] = gpOut; + } + + if ( std::find(gpArray.begin(), gpArray.end(), gp) != gpArray.end() ) { + int nel = gp->giveElement()->giveGlobalNumber(); + int gpn = gp->giveNumber(); + return new StructuralSlipFE2MaterialStatus(rank, gp, this->inputfile, nel, gpn); + } else { + return new StructuralSlipFE2MaterialStatus(rank, gp, this->inputfile, 1, 1); + } + } else if ( allGPRes ) { + int nel = gp->giveElement()->giveGlobalNumber(); + int gpn = gp->giveNumber(); + return new StructuralSlipFE2MaterialStatus(rank, gp, this->inputfile, nel, gpn); + } else { + return new StructuralSlipFE2MaterialStatus(rank, gp, this->inputfile, 1, 1); + } + +} + +FloatMatrixF<3, 3> +StructuralSlipFE2Material::givePlaneStressStiffMtrx( MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep ) const +{ + if (useExtStiff) { + auto status = static_cast(this->giveStatus(gp)); + FloatMatrixF<3,3> answer; + answer = this->givendStressdEpsTangent; + status->setdStressdEpsTangent(answer); + return answer; + } else if (useNumTangent) { + return StructuralFE2Material::givePlaneStressStiffMtrx(rMode, gp, tStep); + } else { + auto status = static_cast(this->giveStatus(gp)); + FloatMatrix tangent; + status->computeTangent(tStep); //implemented by BC + tangent.beSubMatrixOf(status->givedStressdEpsTangent(), {1,2,3}, {1,2,3}); + FloatMatrixF<3,3> answer; + answer = tangent; + return answer; + + } +} + + +FloatArrayF<3> StructuralSlipFE2Material::giveRealStressVector_PlaneStress( const FloatArrayF<3> &strain, GaussPoint *gp, TimeStep *tStep ) const +{ + auto ms = static_cast( this->giveStatus(gp) ); + + ms->setTimeStep(tStep); + ms->giveBC()->setDispGradient(strain); + // Solve subscale problem + ms->giveRVE()->solveYourselfAt(tStep); + // Post-process the stress + FloatArray stress; + ms->giveBC()->computeStress(stress, tStep); + + FloatArrayF<6> updateStress; + updateStress = {stress[0], stress[1], 0., 0., 0., 0.5*(stress[2]+stress[3])}; + + FloatArrayF<6> updateStrain; + updateStrain = {strain[0], strain[1], 0., 0., 0., strain[2]}; + + FloatArrayF<3> answer; + answer = {stress[0], stress[1], 0.5*(stress[2]+stress[3])}; + + // Update the material status variables + ms->letTempStressVectorBe(updateStress); + ms->letTempStrainVectorBe(updateStrain); + ms->markOldTangent(); // Mark this so that tangent is reevaluated if they are needed. + + return answer; +} + + +void StructuralSlipFE2Material::giveHomogenizedFields( FloatArray &stress, FloatArray &bStress, FloatArray &rStress, const FloatArray &strain, const FloatArray &slip, const FloatArray &slipGradient, GaussPoint *gp, TimeStep *tStep ) +{ + StructuralSlipFE2MaterialStatus *ms = static_cast( this->giveStatus(gp) ); + + ms->setTimeStep(tStep); + //Set input + ms->giveBC()->setDispGradient(strain); + ms->giveBC()->setSlipField(slip); + ms->giveBC()->setSlipGradient(slipGradient); +// Solve subscale problem +// OOFEM_LOG_INFO("Solving subscale problem at element %d, gp %d.\n Applied strain is %10.6e, %10.6e, %10.6e \n Applied slip is %10.6e, %10.6e \n Applied slip gradient is %10.6e, %10.6e, %10.6e, %10.6e \n", gp->giveElement()->giveGlobalNumber(), gp->giveNumber(), strain.at(1), strain.at(2), strain.at(3), slip.at(1), slip.at(2), slipGradient.at(1), slipGradient.at(2), slipGradient.at(3), slipGradient.at(4) ); + ms->giveRVE()->solveYourselfAt(tStep); +// OOFEM_LOG_INFO("Solution of RVE problem @ element %d, gp %d OK. \n", gp->giveElement()->giveGlobalNumber(), gp->giveNumber() ); + //Homogenize fields + FloatArray stress4; + ms->giveBC()->computeStress(stress4, tStep); + ms->giveBC()->computeTransferStress(bStress, tStep); + ms->giveBC()->computeReinfStress(rStress, tStep); +// OOFEM_LOG_INFO("Stress is %10.6e, %10.6e, %10.6e \n Transfer stress is %10.6e, %10.6e \n Reinforcement membrane stress is %10.6e, %10.6e, %10.6e, %10.6e \n", stress4.at(1), stress4.at(2), stress4.at(3), bStress.at(1), bStress.at(2), rStress.at(1), rStress.at(2), rStress.at(3), rStress.at(4) ); + + if (stress4.giveSize() == 4 ) { + stress = {stress4[0], stress4[1], 0.5*(stress4[2]+stress4[3])}; + } else { + OOFEM_ERROR("Only 2D plane stress mode supported"); + } + + // Update the material status variables + ms->letTempStressVectorBe(stress); + ms->letTempStrainVectorBe(strain); + ms->letTempTransferStressVectorBe(bStress); + ms->letTempSlipVectorBe(slip); + ms->letTempReinfStressVectorBe(rStress); + ms->letTempSlipGradVectorBe(slipGradient); + ms->markOldTangent(); // Mark this so that tangent is reevaluated if they are needed. +} + + +void StructuralSlipFE2Material::giveSensitivities( FloatMatrix &dStressdEps, FloatMatrix &dStressdS, FloatMatrix &dStressdG, FloatMatrix &dBStressdEps, FloatMatrix &dBStressdS, + FloatMatrix &dBStressdG, FloatMatrix &dRStressdEps, FloatMatrix &dRStressdS, FloatMatrix &dRStressdG, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep ) +{ + if ( useNumTangent ) { + //Numerical tangent + StructuralSlipFE2MaterialStatus *status = static_cast( this->giveStatus( gp ) ); + double h = 1.0e-9; + + //get current values from material status + const FloatArray &epsRed = status->giveTempStrainVector(); + const FloatArray &slipRed = status->giveTempSlipVector(); + const FloatArray &slipGradRed = status->giveTempSlipGradVector(); + + FloatArray eps; + if ( epsRed.giveSize() != 3 ) { + eps = { epsRed[0], epsRed[1], epsRed[5] }; + } else { + eps = epsRed; + } + FloatArray slip=slipRed; + FloatArray slipGrad=slipGradRed; + + int dim1 = eps.giveSize(); + int dim2 = slip.giveSize(); + int dim3 = slipGrad.giveSize(); + dStressdEps.resize(dim1,dim1); dStressdEps.zero(); + dBStressdEps.resize(dim2,dim1); dBStressdEps.zero(); + dRStressdEps.resize(dim3,dim1); dRStressdEps.zero(); + dStressdS.resize(dim1,dim2); dStressdS.zero(); + dBStressdS.resize(dim2,dim2); dBStressdS.zero(); + dRStressdS.resize(dim3,dim2); dRStressdS.zero(); + dStressdG.resize(dim1,dim3); dStressdG.zero(); + dBStressdG.resize(dim2,dim3); dBStressdG.zero(); + dRStressdG.resize(dim3,dim3); dRStressdG.zero(); + + FloatArray sig, sigPert, epsPert; + FloatArray bsig, bsigPert, slipPert; + FloatArray rsig, rsigPert, slipGradPert; + + for(int i = 1; i <= dim1; i++) { + // Add a small perturbation to the strain + epsPert = eps; + epsPert.at(i) += h; + + giveHomogenizedFields( sigPert, bsigPert, rsigPert, epsPert, slip, slipGrad, gp, tStep ); + dStressdEps.setColumn( sigPert, i); + dBStressdEps.setColumn( bsigPert, i); + dRStressdEps.setColumn( rsigPert, i); + } + + for(int i = 1; i <= dim2; i++) { + // Add a small perturbation to the slip + slipPert = slip; + slipPert.at(i) += h; + + giveHomogenizedFields( sigPert, bsigPert, rsigPert, eps, slipPert, slipGrad, gp, tStep ); + dStressdS.setColumn( sigPert, i ); + dBStressdS.setColumn( bsigPert, i); + dRStressdS.setColumn( rsigPert, i); + } + + for(int i = 1; i <= dim3; i++) { + // Add a small perturbation to slip gradient + slipGradPert = slipGrad; + slipGradPert.at(i) += h; + + giveHomogenizedFields( sigPert, bsigPert, rsigPert, eps, slip, slipGradPert, gp, tStep ); + dStressdG.setColumn( sigPert, i); + dBStressdG.setColumn( bsigPert, i); + dRStressdG.setColumn( rsigPert, i); + } + + giveHomogenizedFields( sig, bsig, rsig, eps, slip, slipGrad, gp, tStep); + + for(int i = 1; i <= dim1; i++) { + for(int j = 1; j <= dim1; j++) { + dStressdEps.at(j,i) -= sig.at(j); + dStressdEps.at(j,i) /= h; + } + for(int j = 1; j <= dim2; j++) { + dBStressdEps.at(j,i) -= bsig.at(j); + dBStressdEps.at(j,i) /= h; + } + for(int j = 1; j <= dim3; j++) { + dRStressdEps.at(j,i) -= rsig.at(j); + dRStressdEps.at(j,i) /= h; + } + } + + for(int i = 1; i <= dim2; i++) { + for(int j = 1; j <= dim1; j++) { + dStressdS.at(j,i) -= sig.at(j); + dStressdS.at(j,i) /= h; + } + for(int j = 1; j <= dim2; j++) { + dBStressdS.at(j,i) -= bsig.at(j); + dBStressdS.at(j,i) /= h; + } + for(int j = 1; j <= dim3; j++) { + dRStressdS.at(j,i) -= rsig.at(j); + dRStressdS.at(j,i) /= h; + } + } + + for(int i = 1; i <= dim3; i++) { + for(int j = 1; j <= dim1; j++) { + dStressdG.at(j,i) -= sig.at(j); + dStressdG.at(j,i) /= h; + } + for(int j = 1; j <= dim2; j++) { + dBStressdG.at(j,i) -= bsig.at(j); + dBStressdG.at(j,i) /= h; + } + for(int j = 1; j <= dim3; j++) { + dRStressdG.at(j,i) -= rsig.at(j); + dRStressdG.at(j,i) /= h; + } + } + + status->setdStressdEpsTangent(dStressdEps); + status->setdBStressdEpsTangent(dBStressdEps); + status->setdRStressdEpsTangent(dRStressdEps); + status->setdStressdSTangent(dStressdS); + status->setdBStressdSTangent(dBStressdS); + status->setdRStressdSTangent(dRStressdS); + status->setdStressdGTangent(dStressdG); + status->setdBStressdGTangent(dBStressdG); + status->setdRStressdGTangent(dRStressdG); + + } else if ( useExtStiff) { + StructuralSlipFE2MaterialStatus *ms = static_cast( this->giveStatus(gp) ); + + dStressdEps = this->givendStressdEpsTangent; + dBStressdEps = this->givendBStressdEpsTangent; + dRStressdEps = this->givendRStressdEpsTangent; + dStressdS = this->givendStressdSTangent; + dBStressdS = this->givendBStressdSTangent; + dRStressdS = this->givendRStressdSTangent; + dStressdG = this->givendStressdGTangent; + dBStressdG = this->givendBStressdGTangent; + dRStressdG = this->givendRStressdGTangent; + + ms->setdStressdEpsTangent(dStressdEps); + ms->setdBStressdEpsTangent(dBStressdEps); + ms->setdRStressdEpsTangent(dRStressdEps); + ms->setdStressdSTangent(dStressdS); + ms->setdBStressdSTangent(dBStressdS); + ms->setdRStressdSTangent(dRStressdS); + ms->setdStressdGTangent(dStressdG); + ms->setdBStressdGTangent(dBStressdG); + ms->setdRStressdGTangent(dRStressdG); + } else { + OOFEM_ERROR("Exact tangent not implemented. Either use_num_tangent or use_ext_stiffness"); + } +} + +//============================================================================= + + +StructuralSlipFE2MaterialStatus :: StructuralSlipFE2MaterialStatus( int rank, GaussPoint * g, const std :: string & inputfile, int el, int gp ) : + StructuralMaterialStatus(g), + mInputFile(inputfile) +{ + if ( !this->createRVE(inputfile, rank, el, gp) ) { + OOFEM_ERROR("Couldn't create RVE"); + } + stressVector.resize(6); + strainVector.resize(6); + tempStressVector.resize(6); + tempStrainVector.resize(6); + + //this is now hardcoded for 2d plane stress + slipVector.resize(2); + bStressVector.resize(2); + tempSlipVector.resize(2); + tempBStressVector.resize(2); + + slipGradVector.resize(4); + rStressVector.resize(4); + tempSlipGradVector.resize(4); + tempRStressVector.resize(4); +} + + +PrescribedDispSlipHomogenization* StructuralSlipFE2MaterialStatus::giveBC() +{ + this->bc = dynamic_cast< PrescribedDispSlipHomogenization * >( this->rve->giveDomain(1)->giveBc(1) ); + return this->bc; +} + + +bool StructuralSlipFE2MaterialStatus :: createRVE(const std :: string &inputfile, int rank, int el, int gp) +{ + OOFEMTXTDataReader dr( inputfile ); + this->rve = InstanciateProblem(dr, _processor, 0); // Everything but nrsolver is updated. + dr.finish(); + this->rve->setProblemScale(microScale); + this->rve->checkProblemConsistency(); + this->rve->initMetaStepAttributes( this->rve->giveMetaStep(1) ); + this->rve->giveNextStep(); // Makes sure there is a timestep (which we will modify before solving a step) + this->rve->init(); + + std :: ostringstream name; + name << this->rve->giveOutputBaseFileName() << "_el" << el << "_gp" << gp; + if ( rank >= 0 ) { + name << "." << rank; + } + + this->rve->letOutputBaseFileNameBe( name.str() ); + + bc = this->giveBC(); + if ( !bc ) { + OOFEM_ERROR("RVE doesn't have necessary boundary condition; should have a type of PrescribedDispSlipHomogenization as first b.c."); + } + + return true; +} + +void StructuralSlipFE2MaterialStatus :: setTimeStep(TimeStep *tStep) +{ + TimeStep *rveTStep = this->rve->giveCurrentStep(); // Should i create a new one if it is empty? + rveTStep->setNumber( tStep->giveNumber() ); + rveTStep->setTime( tStep->giveTargetTime() ); + rveTStep->setTimeIncrement( tStep->giveTimeIncrement() ); +} + +void StructuralSlipFE2MaterialStatus :: initTempStatus() +{ + StructuralMaterialStatus :: initTempStatus(); + + // see if vectors describing reached equilibrium are defined + if ( this->giveSlipVector().giveSize() == 0 ) { + slipVector.resize(2); + } + + if ( this->giveTransferStressVector().giveSize() == 0) { + bStressVector.resize(2); + } + + if (this->giveSlipGradVector().giveSize() == 0) { + slipGradVector.resize(4); + } + + if (this->giveReinfStressVector().giveSize() == 0) { + rStressVector.resize(4); + } + + // reset temp vars. + tempSlipVector = slipVector; + tempBStressVector = bStressVector; + tempSlipGradVector = slipGradVector; + tempRStressVector = rStressVector; +} + + +void StructuralSlipFE2MaterialStatus :: computeTangent(TimeStep *tStep) +{ + if ( !tStep->isTheCurrentTimeStep() ) { + OOFEM_ERROR("Only current timestep supported."); + } + + if ( this->olddSdETangent ) { + bc->computeTangent(this->givedStressdEpsTangent(), tStep); + } + + this->olddSdETangent = false; +} + +void StructuralSlipFE2MaterialStatus :: updateYourself(TimeStep *tStep) +{ + StructuralMaterialStatus :: updateYourself(tStep); + this->rve->updateYourself(tStep); + this->rve->terminate(tStep); + + slipVector = tempSlipVector; + bStressVector = tempBStressVector; + slipGradVector = tempSlipGradVector; + rStressVector = tempRStressVector; +} + +void StructuralSlipFE2MaterialStatus::markOldTangent() +{ + this->olddSdETangent = true; + this->olddBSdETangent = true; + this->olddRSdETangent = true; + this->olddSdSTangent = true; + this->olddBSdSTangent = true; + this->olddRSdSTangent = true; + this->olddSdGTangent = true; + this->olddBSdGTangent = true; + this->olddRSdGTangent = true; +} + +} // end namespace oofem diff --git a/src/sm/Materials/structuralslipfe2material.h b/src/sm/Materials/structuralslipfe2material.h new file mode 100644 index 000000000..baf32d24f --- /dev/null +++ b/src/sm/Materials/structuralslipfe2material.h @@ -0,0 +1,215 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef structuralslipfe2material_h +#define structuralslipfe2material_h + +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/structuralfe2material.h" +#include "prescribeddispsliphomogenization.h" + +#include + +///@name Input fields for StructuralSlipFE2Material +//@{ +#define _IFT_StructuralSlipFE2Material_Name "structslipfe2material" +#define _IFT_StructuralSlipFE2Material_useExternalStiffness "use_ext_stiffness" +#define _IFT_StructuralSlipFE2Material_allGPResults "export_all_gps" +#define _IFT_StructuralSlipFE2Material_outputSelectedResults "output_selected_el_gps" +#define _IFT_StructuralSlipFE2Material_dStressdEps "dsde" +#define _IFT_StructuralSlipFE2Material_dBStressdEps "dbsde" +#define _IFT_StructuralSlipFE2Material_dRStressdEps "drsde" +#define _IFT_StructuralSlipFE2Material_dStressdS "dsds" +#define _IFT_StructuralSlipFE2Material_dBStressdS "dbsds" +#define _IFT_StructuralSlipFE2Material_dRStressdS "drsds" +#define _IFT_StructuralSlipFE2Material_dStressdG "dsdg" +#define _IFT_StructuralSlipFE2Material_dBStressdG "dbsdg" +#define _IFT_StructuralSlipFE2Material_dRStressdG "drsdg" + +//@} + +namespace oofem { +class EngngModel; +class PrescribedGradientHomogenization; +class PrescribedDispSlipHomogenization; + +class StructuralSlipFE2MaterialStatus : public StructuralMaterialStatus +{ +protected: + /// The RVE + std :: unique_ptr< EngngModel > rve; + /// Boundary condition in RVE that performs the computational homogenization. + PrescribedDispSlipHomogenization *bc = nullptr; + + std :: string mInputFile; + + int nel=1; //macroscopic element number + int gpn=1; //gauss point number + + //Tangents wrt to strain, slip and slip gradient + FloatMatrix dStressdEpsTangent, dBStressdEpsTangent, dRStressdEpsTangent; + bool olddSdETangent = true, olddBSdETangent = true, olddRSdETangent =true; + + FloatMatrix dStressdSTangent, dBStressdSTangent, dRStressdSTangent; + bool olddSdSTangent = true, olddBSdSTangent = true, olddRSdSTangent = true; + + FloatMatrix dStressdGTangent, dBStressdGTangent, dRStressdGTangent; + bool olddSdGTangent = true, olddBSdGTangent = true, olddRSdGTangent = true; + + FloatArray slipVector; + FloatArray bStressVector; + FloatArray tempSlipVector; + FloatArray tempBStressVector; + + FloatArray slipGradVector; + FloatArray rStressVector; + FloatArray tempSlipGradVector; + FloatArray tempRStressVector; + +public: + StructuralSlipFE2MaterialStatus(int rank, GaussPoint * g, const std :: string & inputfile, int el, int gp); + + EngngModel *giveRVE() const { return this->rve.get(); } + PrescribedDispSlipHomogenization *giveBC(); + + bool createRVE(const std :: string &inputfile, int rank, int el, int gp); + void setTimeStep(TimeStep *tStep); + + void markOldTangent(); + void computeTangent(TimeStep *tStep); + + void initTempStatus() override; + + void updateYourself(TimeStep *tStep) override; + + const char *giveClassName() const override { return "StructuralSlipFE2MaterialStatus"; } + + /// Setters and getters + FloatMatrix &givedStressdEpsTangent() { return dStressdEpsTangent; } + void setdStressdEpsTangent(const FloatMatrix &iTangent) {dStressdEpsTangent = iTangent; olddSdETangent = false;} + void setdBStressdEpsTangent(const FloatMatrix &iTangent) {dBStressdEpsTangent = iTangent; olddBSdETangent = false;} + void setdRStressdEpsTangent(const FloatMatrix &iTangent) {dRStressdEpsTangent = iTangent; olddRSdETangent = false;} + + void setdStressdSTangent(const FloatMatrix &iTangent) {dStressdSTangent = iTangent; olddSdSTangent = false;} + void setdBStressdSTangent(const FloatMatrix &iTangent) {dBStressdSTangent = iTangent; olddBSdSTangent = false;} + void setdRStressdSTangent(const FloatMatrix &iTangent) {dRStressdSTangent = iTangent; olddRSdSTangent = false;} + + void setdStressdGTangent(const FloatMatrix &iTangent) {dStressdGTangent = iTangent; olddSdGTangent = false;} + void setdBStressdGTangent(const FloatMatrix &iTangent) {dBStressdGTangent = iTangent; olddBSdGTangent = false;} + void setdRStressdGTangent(const FloatMatrix &iTangent) {dRStressdGTangent = iTangent; olddRSdGTangent = false;} + + const FloatArray &giveSlipVector() const { return slipVector; } + const FloatArray &giveTransferStressVector() const { return bStressVector; } + const FloatArray &giveTempSlipVector() const { return tempSlipVector; } + void letTempTransferStressVectorBe(const FloatArray &v) { tempBStressVector = v; } + void letTempSlipVectorBe(const FloatArray &v) { tempSlipVector = v; } + + const FloatArray &giveSlipGradVector() const { return slipGradVector; } + const FloatArray &giveReinfStressVector() const { return rStressVector; } + const FloatArray &giveTempSlipGradVector() const { return tempSlipGradVector; } + void letTempReinfStressVectorBe(const FloatArray &v) { tempRStressVector = v; } + void letTempSlipGradVectorBe(const FloatArray &v) { tempSlipGradVector = v; } +}; + + +/** + * Multiscale constitutive model for structural problems on reinforced concrete structures. + * At the macroscale, both the displacement and reinforcement slip can be treated as variables. + * Currently, only plane stress mode is supported. + * + * This material uses the PrescribedDispSlip boundary conditions to perform computational homogenization. + * The requirement for the supplied subscale problem is: + * - It must have a PrescribedDispSlip boundary condition. + * - It must be the first boundary condition + * + * The following boundary conditions on the RVE are supported (must use PrescribedDispSlipHomogenization class): + * - PrescribedDispSlipBCDirichletRC (macroscopic displacement gradient, slip and slip gradient prescribed with Dirichlet BCs on concrete and optionally on reinforcement) + * - PrescribedDispSlipBCNeumannRC (macroscopic displacement gradient, slip and slip gradient prescribed with Neumann BCs on concrete and optionally on reinforcement) + * - PrescribedDispSlipMultiple (for combining more than one PrescribedDispSlip boundary condition on the RVE) + * Input fields slip and slipGrad are optional. If left unspecified, the BCs work then as usual PrescribedGradient BCs (PrescribedGradient, PrescribedGradientBCNeumann) + * + * refs: Sciegaj, A., Larsson, F., Lundgren, K., Nilenius, F., & Runesson, K. (2018). Twoâ€scale finite element modelling of reinforced concrete structures: Effective response and subscale fracture development. International Journal for Numerical Methods in Engineering, 114(10), 1074–1102. https://doi.org/10.1002/nme.5776 + * Sciegaj, A., Larsson, F., Lundgren, K., Nilenius, F., & Runesson, K. (2019). A multiscale model for reinforced concrete with macroscopic variation of reinforcement slip. Computational Mechanics, 63(2), 139–158. https://doi.org/10.1007/s00466-018-1588-3 + * Sciegaj, A., Larsson, F., Lundgren, K., & Runesson, K. (2020). On a volume averaged measure of macroscopic reinforcement slip in two-scale modeling of reinforced concrete. International Journal for Numerical Methods in Engineering, 121(8), 1822–1846. https://doi.org/10.1002/nme.6288 + * + * @author Adam Sciegaj + */ +class StructuralSlipFE2Material : public StructuralFE2Material +{ +protected: + bool useExtStiff = false; + bool allGPRes = false; + /** + * FloatArray that contains element and Gauss point number for the desired results to be exported. + * The syntax in the input file should follow: + * output_selected_el_gp size elNumber gpNumber + * e.g. output_selected_el_gp 6 22 4 21 2 20 3 will export Gauss point 4 from el 22, Gauss point 2 from el 21 etc. + */ + IntArray outputSelected; + + //sensitivities + FloatMatrix givendStressdEpsTangent; //3x3 stiffness matrix (plane stress) + FloatMatrix givendBStressdEpsTangent, givendRStressdEpsTangent; + FloatMatrix givendStressdSTangent, givendBStressdSTangent, givendRStressdSTangent; + FloatMatrix givendStressdGTangent, givendBStressdGTangent, givendRStressdGTangent; + +public: + StructuralSlipFE2Material(int n, Domain * d); + + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + const char *giveInputRecordName() const override { return _IFT_StructuralSlipFE2Material_Name; } + const char *giveClassName() const override { return "StructuralSlipFE2Material"; } + + FloatMatrixF<3,3> givePlaneStressStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<3> giveRealStressVector_PlaneStress(const FloatArrayF< 3 > &strain, GaussPoint *gp, TimeStep *tStep) const override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override; + + /** + * Computes the homogenized stress, homogenized bond stress and reinforcement stress for the createRVE + */ + virtual void giveHomogenizedFields(FloatArray &stress, FloatArray &bStress, FloatArray &rStress, const FloatArray &strain, const FloatArray &slip, + const FloatArray &slipGradient, GaussPoint *gp, TimeStep *tStep); + /** + * Computes the sensitivity matrices for the RVE. Necessary for building the stiffness matrix. + */ + virtual void giveSensitivities(FloatMatrix &dStressdEps, FloatMatrix &dStressdS, FloatMatrix &dStressdG, FloatMatrix &dBStressdEps, FloatMatrix &dBStressdS, + FloatMatrix &dBStressdG, FloatMatrix &dRStressdEps, FloatMatrix &dRStressdS, FloatMatrix &dRStressdG, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + +}; + +} // end namespace oofem +#endif // structuralslipfe2material_h diff --git a/src/sm/Materials/tutorialmaterial.C b/src/sm/Materials/tutorialmaterial.C index 0b7f5fa62..3be937f9a 100644 --- a/src/sm/Materials/tutorialmaterial.C +++ b/src/sm/Materials/tutorialmaterial.C @@ -38,7 +38,7 @@ #include "floatarray.h" #include "dynamicinputrecord.h" #include "classfactory.h" -#include "Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "mathfem.h" namespace oofem { @@ -47,22 +47,15 @@ REGISTER_Material(TutorialMaterial); TutorialMaterial :: TutorialMaterial(int n, Domain *d) : StructuralMaterial(n, d), D(n, d) {} -TutorialMaterial :: ~TutorialMaterial() -{} -IRResultType -TutorialMaterial :: initializeFrom(InputRecord *ir) +void +TutorialMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralMaterial :: initializeFrom(ir); - result = D.initializeFrom(ir); - if ( result != IRRT_OK ) return result; - + D.initializeFrom(ir); IR_GIVE_FIELD(ir, this->sig0, _IFT_TutorialMaterial_yieldstress); - IR_GIVE_FIELD(ir, this->H, _IFT_TutorialMaterial_hardeningmoduli); - - return StructuralMaterial :: initializeFrom(ir); } @@ -71,7 +64,6 @@ TutorialMaterial :: giveInputRecord(DynamicInputRecord &ir) { StructuralMaterial :: giveInputRecord(ir); D.giveInputRecord(ir); - ir.setField(this->sig0, _IFT_TutorialMaterial_yieldstress); ir.setField(this->H, _IFT_TutorialMaterial_hardeningmoduli); } @@ -80,151 +72,102 @@ TutorialMaterial :: giveInputRecord(DynamicInputRecord &ir) MaterialStatus * TutorialMaterial :: CreateStatus(GaussPoint *gp) const { - return new TutorialMaterialStatus(1, this->giveDomain(), gp); + return new TutorialMaterialStatus(gp); } -void -TutorialMaterial :: giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, - const FloatArray &totalStrain, TimeStep *tStep) +FloatArrayF<6> +TutorialMaterial :: giveRealStressVector_3d(const FloatArrayF<6> &totalStrain, GaussPoint *gp, TimeStep *tStep) const { - FloatArray strain; - TutorialMaterialStatus *status = static_cast< TutorialMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TutorialMaterialStatus * >( this->giveStatus(gp) ); // subtract stress thermal expansion - this->giveStressDependentPartOfStrainVector_3d(strain, gp, totalStrain, tStep, VM_Total); - - FloatArray trialElastStrain; - trialElastStrain.beDifferenceOf(strain, status->givePlasticStrain()); + auto thermalStrain = this->computeStressIndependentStrainVector_3d(gp, tStep, VM_Total); + auto strain = totalStrain - thermalStrain; + + auto trialElastStrain = strain - status->givePlasticStrain(); // Compute trial stress = sig_tr = sig_old + E*delta_eps - FloatMatrix elasticStiffness; - D.give3dMaterialStiffnessMatrix(elasticStiffness, TangentStiffness, gp, tStep); - FloatArray trialStress; - trialStress.beProductOf(elasticStiffness, trialElastStrain); + const auto &elasticStiffness = D.giveTangent(); + auto trialStress = dot(elasticStiffness, trialElastStrain); + + //auto [devTrialStress, meanTrialStress] = computeDeviatoricVolumetricSplit(); // c++17 + auto tmp = computeDeviatoricVolumetricSplit(trialStress); + auto devTrialStress = tmp.first; + auto meanTrialStress = tmp.second; - FloatArray sphTrialStress, devTrialStress; - computeSphDevPartOf(trialStress, sphTrialStress, devTrialStress); - double J2 = this->computeSecondStressInvariant(devTrialStress); double effectiveTrialStress = sqrt(3 * J2); -#if 1 - double temperatureScaling = 1.0; -#else - double temperature; - FloatArray et; - static_cast< StructuralElement *>(gp->giveIntegrationRule()->giveElement())->computeResultingIPTemperatureAt(et, tStep, gp, VM_Total); - temperature = et.at(1) + 800; - - double temperatureScaling = temperature <= 400 ? 1.0 : 1.0 - (temperature - 400) * 0.5 / 400; -#endif - // evaluate the yield surface double k = status->giveK(); - double phiTrial = effectiveTrialStress - ( temperatureScaling * this->sig0 + temperatureScaling * H * k ); - + double phiTrial = effectiveTrialStress - ( this->sig0 + H * k ); + + FloatArrayF<6> stress; if ( phiTrial < 0.0 ) { // elastic - answer = trialStress; + stress = trialStress; status->letTempPlasticStrainBe(status->givePlasticStrain()); } else { // plastic loading double G = D.giveShearModulus(); - double mu = phiTrial / ( 3.0 * G + temperatureScaling * H ); // plastic multiplier - answer = devTrialStress * ( 1.0 - 3.0*G*mu/effectiveTrialStress); // radial return - answer.add(sphTrialStress); + double mu = phiTrial / ( 3.0 * G + H ); // plastic multiplier + // radial return + auto devStress = ( 1.0 - 3.0*G*mu/effectiveTrialStress) * devTrialStress; + stress = computeDeviatoricVolumetricSum(devStress, meanTrialStress); k += mu; - FloatArray plasticStrain = status->givePlasticStrain(); - FloatArray dPlStrain; - applyDeviatoricElasticCompliance(dPlStrain, devTrialStress, 0.5); - plasticStrain.add(mu * 3. / (2. * effectiveTrialStress), dPlStrain); + auto plasticStrain = status->givePlasticStrain(); + auto dPlStrain = applyDeviatoricElasticCompliance(devTrialStress, 0.5); + plasticStrain += (mu * 3. / (2. * effectiveTrialStress)) * dPlStrain; status->letTempPlasticStrainBe(plasticStrain); } - + // Store the temporary values for the given iteration status->letTempStrainVectorBe(totalStrain); - status->letTempStressVectorBe(answer); + status->letTempStressVectorBe(stress); status->letTempKBe(k); status->letTempDevTrialStressBe(devTrialStress); + return stress; } -void -TutorialMaterial :: computeSphDevPartOf(const FloatArray &sigV, FloatArray &sigSph, FloatArray &sigDev) +FloatMatrixF<6,6> +TutorialMaterial :: give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - double volumetricPart = ( sigV.at(1) + sigV.at(2) + sigV.at(3) ) / 3.0; - sigSph = {volumetricPart, volumetricPart, volumetricPart, 0.0, 0.0, 0.0}; - sigDev.beDifferenceOf(sigV, sigSph); -} - - -void -TutorialMaterial :: giveDeviatoricProjectionMatrix(FloatMatrix &answer) -{ - answer.resize(6,6); - answer.zero(); - answer.at(1,1) = answer.at(2,2) = answer.at(3,3) = 2.0/3.0; - answer.at(1,2) = answer.at(1,3) = answer.at(2,3) = -1.0/3.0; - answer.at(2,1) = answer.at(3,1) = answer.at(3,2) = -1.0/3.0; - answer.at(4,4) = answer.at(5,5) = answer.at(6,6) = 1.0/2.0; -} - - -void -TutorialMaterial :: give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - TutorialMaterialStatus *status = static_cast< TutorialMaterialStatus * >( this->giveStatus(gp) ); - FloatArray devTrialStress = status->giveTempDevTrialStress(); + auto status = static_cast< TutorialMaterialStatus * >( this->giveStatus(gp) ); + const auto &devTrialStress = status->giveTempDevTrialStress(); double J2 = this->computeSecondStressInvariant(devTrialStress); double effectiveTrialStress = sqrt(3 * J2); -#if 1 - double temperatureScaling = 1.0; -#else - double temperature; - FloatArray et; - static_cast< StructuralElement *>(gp->giveIntegrationRule()->giveElement())->computeResultingIPTemperatureAt(et, tStep, gp, VM_Total); - temperature = et.at(1) + 800; - - double temperatureScaling = temperature <= 400 ? 1.0 : 1.0 - (temperature - 400) * 0.5 / 400; -#endif - // evaluate the yield surface double k = status->giveK(); - double phiTrial = effectiveTrialStress - ( temperatureScaling * this->sig0 + temperatureScaling * H * k ); + double phiTrial = effectiveTrialStress - ( this->sig0 + H * k ); - FloatMatrix elasticStiffness; - D.give3dMaterialStiffnessMatrix(elasticStiffness, ElasticStiffness, gp, tStep); + const auto &elasticStiffness = D.giveTangent(); if ( phiTrial < 0.0 ) { // elastic - answer = elasticStiffness; + return elasticStiffness; } else { // plastic loading double G = D.giveShearModulus(); // E_t = elasticStiffness - correction // correction = 2.0 * G * ( 2.0 * G / h *( sig0 + kappa ) / sigtre *openProd(nu,nu) + mu*3*G/sigtre *Idev); - double h = 3.0 * G + temperatureScaling * H; + double h = 3.0 * G + H; double mu = phiTrial / h; // plasic multiplier - - FloatArray nu = (3.0/2.0 / effectiveTrialStress ) * devTrialStress; - FloatMatrix Idev, correction; - giveDeviatoricProjectionMatrix(Idev); - - correction.plusDyadUnsym(nu, nu, 2.0 * G / h * ( temperatureScaling * this->sig0 + temperatureScaling * H * k )); - correction.add(mu * 3.0 * G, Idev); - correction.times(2.0 * G / effectiveTrialStress); - answer = elasticStiffness; - answer.subtract(correction); + auto nu = ( 3.0/2.0 / effectiveTrialStress ) * devTrialStress; + + auto correction = dyad(nu, nu) * (2.0 * G / h * ( this->sig0 + H * k )); + correction += (mu * 3.0 * G) * I_dev6; + correction *= 2.0 * G / effectiveTrialStress; + return elasticStiffness - correction; } } -void -TutorialMaterial :: giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +FloatArrayF<6> +TutorialMaterial :: giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const { - double alpha = D.give(tAlpha, gp); - answer = {alpha, alpha, alpha, 0., 0., 0.}; + return D.giveAlpha(); } @@ -244,11 +187,8 @@ TutorialMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStat //============================================================================= -TutorialMaterialStatus :: TutorialMaterialStatus(int n, Domain * d, GaussPoint * g) : - StructuralMaterialStatus(n, d, g), - tempPlasticStrain(6), plasticStrain(6), - tempDevTrialStress(6), - tempK(0.), k(0.) +TutorialMaterialStatus :: TutorialMaterialStatus(GaussPoint * g) : + StructuralMaterialStatus(g) { strainVector.resize(6); stressVector.resize(6); @@ -270,8 +210,7 @@ TutorialMaterialStatus :: initTempStatus() tempPlasticStrain = plasticStrain; tempK = k; - tempDevTrialStress.resize(6); - tempDevTrialStress.zero(); + tempDevTrialStress = zeros<6>(); } diff --git a/src/sm/Materials/tutorialmaterial.h b/src/sm/Materials/tutorialmaterial.h index 61823a8d0..c953dc779 100644 --- a/src/sm/Materials/tutorialmaterial.h +++ b/src/sm/Materials/tutorialmaterial.h @@ -35,9 +35,9 @@ #ifndef tutorialmaterial_h #define tutorialmaterial_h -#include "Materials/structuralmaterial.h" -#include "Materials/structuralms.h" -#include "Materials/isolinearelasticmaterial.h" +#include "sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/isolinearelasticmaterial.h" ///@name Input fields for TutorialMaterial //@{ @@ -57,81 +57,71 @@ class TutorialMaterial : public StructuralMaterial { protected: /// Hardening modulus. - double H; + double H = 0.; /// Initial (uniaxial) yield stress. - double sig0; - + double sig0 = 0.; + IsotropicLinearElasticMaterial D; public: TutorialMaterial(int n, Domain * d); - virtual ~TutorialMaterial(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &ir); - virtual const char *giveInputRecordName() const { return _IFT_TutorialMaterial_Name; } - virtual const char *giveClassName() const { return "TutorialMaterial"; } - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) { return true; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_TutorialMaterial_Name; } + const char *giveClassName() const override { return "TutorialMaterial"; } + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override { return true; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; - // stress computation methods - virtual void giveRealStressVector_3d(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - - virtual void give3dMaterialStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + FloatArrayF<6> giveRealStressVector_3d(const FloatArrayF<6> &strain, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveThermalDilatationVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + FloatMatrixF<6,6> give3dMaterialStiffnessMatrix(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; -protected: - static void giveDeviatoricProjectionMatrix(FloatMatrix &answer); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - static void computeSphDevPartOf(const FloatArray &sigV, FloatArray &sigSph, FloatArray &sigDev); + FloatArrayF<6> giveThermalDilatationVector(GaussPoint *gp, TimeStep *tStep) const override; }; - class TutorialMaterialStatus : public StructuralMaterialStatus { protected: /// Temporary plastic strain (the given iteration) - FloatArray tempPlasticStrain; - + FloatArrayF<6> tempPlasticStrain; + /// Last equilibriated plastic strain (end of last time step) - FloatArray plasticStrain; - - FloatArray tempDevTrialStress; + FloatArrayF<6> plasticStrain; - double tempK; - double k; + FloatArrayF<6> tempDevTrialStress; + + double tempK = 0.; + double k = 0.; public: - TutorialMaterialStatus(int n, Domain * d, GaussPoint * g); - virtual ~TutorialMaterialStatus() {} + TutorialMaterialStatus(GaussPoint * g); - const FloatArray &givePlasticStrain() { return plasticStrain; } + const FloatArrayF<6> &givePlasticStrain() const { return plasticStrain; } - void letTempPlasticStrainBe(const FloatArray &values) { tempPlasticStrain = values; } + void letTempPlasticStrainBe(const FloatArrayF<6> &values) { tempPlasticStrain = values; } - double giveK() { return this->k; } + double giveK() const { return this->k; } void letTempKBe(double value) { tempK = value; } - - void letTempDevTrialStressBe(const FloatArray &values) { tempDevTrialStress = values; } - const FloatArray &giveTempDevTrialStress() { return tempDevTrialStress; } - - virtual const char *giveClassName() const { return "TutorialMaterialStatus"; } - - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void letTempDevTrialStressBe(const FloatArrayF<6> &values) { tempDevTrialStress = values; } + const FloatArrayF<6> &giveTempDevTrialStress() const { return tempDevTrialStress; } + + const char *giveClassName() const override { return "TutorialMaterialStatus"; } + + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; // semi optional methods - //virtual void printOutputAt(FILE *file, TimeStep *tStep); - - //virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - //virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + //void printOutputAt(FILE *file, TimeStep *tStep) override; + //void saveContext(DataStream &stream, ContextMode mode) override; + //void restoreContext(DataStream &stream, ContextMode mode) override; }; } // end namespace oofem diff --git a/src/sm/Materials/winklermodel.C b/src/sm/Materials/winklermodel.C index 19e38ce38..19bfdc359 100644 --- a/src/sm/Materials/winklermodel.C +++ b/src/sm/Materials/winklermodel.C @@ -33,7 +33,7 @@ */ #include "winklermodel.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "floatmatrix.h" #include "gausspoint.h" #include "classfactory.h" @@ -45,21 +45,17 @@ REGISTER_Material(WinklerMaterial); WinklerMaterial:: WinklerMaterial (int n, Domain* d): StructuralMaterial(n, d) { } -WinklerMaterial::~WinklerMaterial() -{ } -IRResultType -WinklerMaterial :: initializeFrom(InputRecord *ir) +void +WinklerMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, c1, _IFT_WinklerMaterial_C1); globalFromulation = true; int var=1; IR_GIVE_OPTIONAL_FIELD(ir, var, _IFT_WinklerMaterial_globalFlag); globalFromulation=var; - - return StructuralMaterial :: initializeFrom(ir); } @@ -72,81 +68,79 @@ WinklerMaterial :: giveInputRecord(DynamicInputRecord &input) } -void -WinklerMaterial::giveRealStressVector_2dPlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) +FloatArrayF<3> +WinklerMaterial::giveRealStressVector_2dPlateSubSoil(const FloatArrayF<3> &reducedE, GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix tangent; - this->give2dPlateSubSoilStiffMtrx(tangent, ElasticStiffness, gp, tStep); - answer.beProductOf(tangent, reducedE); + auto tangent = this->give2dPlateSubSoilStiffMtrx(ElasticStiffness, gp, tStep); + auto answer = dot(tangent, reducedE); - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); status->letTempStrainVectorBe(reducedE); status->letTempStressVectorBe(answer); + return answer; } -void -WinklerMaterial::giveRealStressVector_3dBeamSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) +FloatArrayF<6> +WinklerMaterial::giveRealStressVector_3dBeamSubSoil(const FloatArrayF<6> &reducedE, GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix tangent; - this->give3dBeamSubSoilStiffMtrx(tangent, ElasticStiffness, gp, tStep); - answer.beProductOf(tangent, reducedE); + auto tangent = this->give3dBeamSubSoilStiffMtrx(ElasticStiffness, gp, tStep); + auto answer = dot(tangent, reducedE); - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); status->letTempStrainVectorBe(reducedE); status->letTempStressVectorBe(answer); + return answer; } -void -WinklerMaterial :: give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +WinklerMaterial :: give2dPlateSubSoilStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - answer.resize(3, 3); - answer.zero(); - + FloatMatrixF<3,3> answer; answer.at(1, 1) = c1.at(1); //answer.at(2, 2) = c2; //answer.at(3, 3) = c2; + return answer; } -void -WinklerMaterial::give3dBeamSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<6,6> +WinklerMaterial::give3dBeamSubSoilStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const { - - if (this->c1.giveSize() == 6) { - answer.beDiagonal(this->c1); - - if (globalFromulation) { - Beam3dSubsoilMaterialInterface *ei = (Beam3dSubsoilMaterialInterface*) gp->giveElement()->giveInterface(Beam3dSubsoilMaterialInterfaceType); - FloatMatrix T; - if (ei) { - ei->B3SSMI_getUnknownsGtoLRotationMatrix (T); - answer.rotatedWith(T, 't'); - } else { - OOFEM_ERROR("Beam3dSubsoilMaterialInterface required from element"); - } + if ( this->c1.giveSize() == 6 ) { + auto answer = diag(FloatArrayF<6>(this->c1)); + + if (globalFromulation) { + auto ei = static_cast(gp->giveElement()->giveInterface(Beam3dSubsoilMaterialInterfaceType)); + if (ei) { + auto T = ei->B3SSMI_getUnknownsGtoLRotationMatrix(); + answer = unrotate(answer, T); + } else { + OOFEM_ERROR("Beam3dSubsoilMaterialInterface required from element"); + } + } + return answer; + } else { + OOFEM_ERROR ("C1 attribute size error (shouldequal to 6 for 3dBeamSubsoil mode)"); + return FloatMatrixF<6,6>(); } - - } else { - OOFEM_ERROR ("C1 attribute size error (shouldequal to 6 for 3dBeamSubsoil mode)"); - } } MaterialStatus * WinklerMaterial :: CreateStatus(GaussPoint *gp) const { - return new StructuralMaterialStatus(1, this->giveDomain(), gp); + return new StructuralMaterialStatus(gp); } -int -WinklerMaterial :: hasMaterialModeCapability(MaterialMode mode) +bool +WinklerMaterial :: hasMaterialModeCapability(MaterialMode mode) const // // returns whether receiver supports given mode // { - return ((mode == _2dPlateSubSoil) || (mode == _3dBeamSubSoil)); + return mode == _2dPlateSubSoil || mode == _3dBeamSubSoil; } diff --git a/src/sm/Materials/winklermodel.h b/src/sm/Materials/winklermodel.h index a956067cc..d3d87aeb2 100644 --- a/src/sm/Materials/winklermodel.h +++ b/src/sm/Materials/winklermodel.h @@ -35,13 +35,13 @@ #ifndef winklermodel_h #define winklermodel_h -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "floatarray.h" #include "floatmatrix.h" #include "matconst.h" #include "matstatus.h" #include "interface.h" -#include "stressstrainprincmode.h" +#include "../stressstrainprincmode.h" ///@name Input fields for WinklerMaterial //@{ @@ -55,11 +55,11 @@ namespace oofem { class GaussPoint; /** * Implementation of 1D/2D winkler model for plate (and potentiaonnaly beam) subsoil model. - For plates the only C1 spring constant for deflection DOF is needed - (C1 array should have size equal to 1). - - For beams the elastic constants can be an array of spring stifnesses for each individual DOF. - These stifnesses may be given in global or element coordinate system. + * For plates the only C1 spring constant for deflection DOF is needed + * (C1 array should have size equal to 1). + * + * For beams the elastic constants can be an array of spring stifnesses for each individual DOF. + * These stifnesses may be given in global or element coordinate system. */ class WinklerMaterial : public StructuralMaterial { @@ -67,7 +67,7 @@ class WinklerMaterial : public StructuralMaterial /// C1 constant, defined as $\int_0^hE_{oed}(z)\left\(d\Psi(z)\over dz\right\)^2\ dz$ FloatArray c1; /// Flag indicating whether subsoil model defined in global or element local c.s. - bool globalFromulation; + bool globalFromulation = false; public: /** @@ -76,40 +76,37 @@ class WinklerMaterial : public StructuralMaterial * @param d Domain to which new material will belong. */ WinklerMaterial(int n, Domain * d); - /// Destructor. - virtual ~WinklerMaterial(); - // identification and auxiliary functions + bool hasMaterialModeCapability(MaterialMode mode) const override; + const char *giveClassName() const override { return "WinklerMaterial"; } + const char *giveInputRecordName() const override { return _IFT_WinklerMaterial_Name; } - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual const char *giveClassName() const { return "WinklerMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_WinklerMaterial_Name; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + FloatArrayF<3> giveRealStressVector_2dPlateSubSoil(const FloatArrayF<3> &reducedE, GaussPoint *gp, TimeStep *tStep) const override; + FloatArrayF<6> giveRealStressVector_3dBeamSubSoil(const FloatArrayF<6> &reducedE, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveRealStressVector_2dPlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - virtual void giveRealStressVector_3dBeamSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - - virtual void give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep); - virtual void give3dBeamSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep); - virtual MaterialStatus * CreateStatus(GaussPoint *gp) const; + FloatMatrixF<3,3> give2dPlateSubSoilStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<6,6> give3dBeamSubSoilStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + MaterialStatus * CreateStatus(GaussPoint *gp) const override; }; - /** - Interface defining required functionality from associated element. - The method for computing transformation matrix from global to local element c.s. is required. - */ - class OOFEM_EXPORT Beam3dSubsoilMaterialInterface : public Interface - { - public: +/** + * Interface defining required functionality from associated element. + * The method for computing transformation matrix from global to local element c.s. is required. + */ +class OOFEM_EXPORT Beam3dSubsoilMaterialInterface : public Interface +{ +public: /// Constructor - Beam3dSubsoilMaterialInterface() {}; + Beam3dSubsoilMaterialInterface() { } + virtual ~Beam3dSubsoilMaterialInterface() { } /// Evaluate transformation matrix for reciver unknowns - virtual void B3SSMI_getUnknownsGtoLRotationMatrix (FloatMatrix &answer) = 0; - }; - + virtual FloatMatrixF<6,6> B3SSMI_getUnknownsGtoLRotationMatrix() const = 0; +}; + } // end namespace oofem #endif // winklermodel_h diff --git a/src/sm/Materials/winklerpasternak.C b/src/sm/Materials/winklerpasternak.C index 6e6ed73c9..0a12dd51b 100644 --- a/src/sm/Materials/winklerpasternak.C +++ b/src/sm/Materials/winklerpasternak.C @@ -33,7 +33,7 @@ */ #include "winklerpasternak.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "floatmatrix.h" #include "gausspoint.h" #include "classfactory.h" @@ -45,16 +45,14 @@ REGISTER_Material(WinklerPasternakMaterial); WinklerPasternakMaterial:: WinklerPasternakMaterial (int n, Domain* d): StructuralMaterial(n, d) { } -WinklerPasternakMaterial::~WinklerPasternakMaterial() -{ } -IRResultType -WinklerPasternakMaterial :: initializeFrom(InputRecord *ir) +void +WinklerPasternakMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + StructuralMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, c1, _IFT_WinklerPasternakMaterial_C1); - if (ir->hasField(_IFT_WinklerPasternakMaterial_C2)) { + if ( ir.hasField(_IFT_WinklerPasternakMaterial_C2)) { // isotropic case IR_GIVE_FIELD(ir, c2x, _IFT_WinklerPasternakMaterial_C2); c2y = c2x; @@ -62,8 +60,6 @@ WinklerPasternakMaterial :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, c2x, _IFT_WinklerPasternakMaterial_C2X); IR_GIVE_FIELD(ir, c2y, _IFT_WinklerPasternakMaterial_C2Y); } - - return StructuralMaterial :: initializeFrom(ir); } @@ -78,41 +74,36 @@ WinklerPasternakMaterial :: giveInputRecord(DynamicInputRecord &input) } -void -WinklerPasternakMaterial::giveRealStressVector_2dPlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep) +FloatArrayF<3> +WinklerPasternakMaterial::giveRealStressVector_2dPlateSubSoil(const FloatArrayF<3> &reducedE, GaussPoint *gp, TimeStep *tStep) const { - FloatMatrix tangent; - this->give2dPlateSubSoilStiffMtrx(tangent, ElasticStiffness, gp, tStep); - answer.beProductOf(tangent, reducedE); + auto tangent = this->give2dPlateSubSoilStiffMtrx(ElasticStiffness, gp, tStep); + auto answer = dot(tangent, reducedE); + + auto status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - StructuralMaterialStatus *status = static_cast< StructuralMaterialStatus * >( this->giveStatus(gp) ); - status->letTempStrainVectorBe(reducedE); status->letTempStressVectorBe(answer); + return answer; } -void -WinklerPasternakMaterial :: give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +WinklerPasternakMaterial :: give2dPlateSubSoilStiffMtrx(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - answer.resize(3, 3); - answer.zero(); - - answer.at(1, 1) = c1; - answer.at(2, 2) = c2x; - answer.at(3, 3) = c2y; + return diag<3>({c1, c2x, c2y}); } MaterialStatus * WinklerPasternakMaterial :: CreateStatus(GaussPoint *gp) const { - return new StructuralMaterialStatus(1, this->giveDomain(), gp); + return new StructuralMaterialStatus(gp); } -int -WinklerPasternakMaterial :: hasMaterialModeCapability(MaterialMode mode) +bool +WinklerPasternakMaterial :: hasMaterialModeCapability(MaterialMode mode) const // // returns whether receiver supports given mode // diff --git a/src/sm/Materials/winklerpasternak.h b/src/sm/Materials/winklerpasternak.h index 5559e61a2..fbae36545 100644 --- a/src/sm/Materials/winklerpasternak.h +++ b/src/sm/Materials/winklerpasternak.h @@ -35,7 +35,7 @@ #ifndef winklerpasternak_h #define winklerpasternak_h -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "floatarray.h" #include "floatmatrix.h" #include "matconst.h" @@ -61,9 +61,9 @@ class WinklerPasternakMaterial : public StructuralMaterial { protected: /// C1 constant, defined as $\int_0^hE_{oed}(z)\left\(d\Psi(z)\over dz\right\)^2\ dz$ - double c1; + double c1 = 0.; /// C2 constants in x and y directions, defined as $\int_0^hG_{x,y}(z)Psi^2(z)\ dz$ - double c2x, c2y; + double c2x = 0., c2y = 0.; public: /** @@ -72,21 +72,17 @@ class WinklerPasternakMaterial : public StructuralMaterial * @param d Domain to which new material will belong. */ WinklerPasternakMaterial(int n, Domain * d); - /// Destructor. - virtual ~WinklerPasternakMaterial(); - // identification and auxiliary functions + bool hasMaterialModeCapability(MaterialMode mode) const override; + const char *giveClassName() const override { return "WinklerPasternakMaterial"; } + const char *giveInputRecordName() const override { return _IFT_WinklerPasternakMaterial_Name; } - virtual int hasMaterialModeCapability(MaterialMode mode); - virtual const char *giveClassName() const { return "WinklerPasternakMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_WinklerPasternakMaterial_Name; } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - - virtual void giveRealStressVector_2dPlateSubSoil(FloatArray &answer, GaussPoint *gp, const FloatArray &reducedE, TimeStep *tStep); - virtual void give2dPlateSubSoilStiffMtrx(FloatMatrix &answer, MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep); - virtual MaterialStatus * CreateStatus(GaussPoint *gp) const; + FloatArrayF<3> giveRealStressVector_2dPlateSubSoil(const FloatArrayF<3> &reducedE, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> give2dPlateSubSoilStiffMtrx(MatResponseMode mmode, GaussPoint *gp, TimeStep *tStep) const override; + MaterialStatus * CreateStatus(GaussPoint *gp) const override; }; } // end namespace oofem #endif // winklerpasternak_h diff --git a/src/sm/Quasicontinuum/fullsolveddomain.C b/src/sm/Quasicontinuum/fullsolveddomain.C index e5f19787e..c998dce20 100644 --- a/src/sm/Quasicontinuum/fullsolveddomain.C +++ b/src/sm/Quasicontinuum/fullsolveddomain.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Quasicontinuum/fullsolveddomain.h" +#include "sm/Quasicontinuum/fullsolveddomain.h" #include "nummet.h" #include "timestep.h" @@ -58,11 +58,9 @@ QCFullsolveddomain :: ~QCFullsolveddomain() // Destructor { } -IRResultType -QCFullsolveddomain :: initializeFrom(InputRecord *ir) +void +QCFullsolveddomain :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_OPTIONAL_FIELD(ir, FullSolvedDomainNodes, _IFT_FullSolvedDomain_nodes); IR_GIVE_OPTIONAL_FIELD(ir, FullSolvedDomainElements, _IFT_FullSolvedDomain_elements); IR_GIVE_OPTIONAL_FIELD(ir, FullSolvedDomainRadius, _IFT_FullSolvedDomain_radius); @@ -76,8 +74,6 @@ QCFullsolveddomain :: initializeFrom(InputRecord *ir) OOFEM_ERROR("invalid format of FullSolvedDomainBox"); } #endif - - return IRRT_OK; } void @@ -90,7 +86,7 @@ QCFullsolveddomain :: updateYourself() bool QCFullsolveddomain :: isNodeInside(Node *n) { - FloatArray *coordinates = n->giveCoordinates(); + const auto &coordinates = n->giveCoordinates(); // is tested node in FullSolvedDomainNodes if ( FullSolvedDomainNodes.giveSize() != 0 ) { for ( int i = 1; i <= FullSolvedDomainNodes.giveSize(); i++ ) { @@ -112,11 +108,10 @@ QCFullsolveddomain :: isNodeInside(Node *n) // is tested node in FullSolvedDomainRadius if ( FullSolvedDomainRadius.giveSize() != 0 ) { for ( int i = 0; i <= FullSolvedDomainRadius.giveSize() / 4 - 1; i++ ) { - FloatArray vector; - vector.resize(3); - vector.at(1) = coordinates->at(1) - FullSolvedDomainRadius.at(4 * i + 1); - vector.at(2) = coordinates->at(2) - FullSolvedDomainRadius.at(4 * i + 2); - vector.at(3) = coordinates->at(3) - FullSolvedDomainRadius.at(4 * i + 3); + FloatArray vector(3); + vector.at(1) = coordinates.at(1) - FullSolvedDomainRadius.at(4 * i + 1); + vector.at(2) = coordinates.at(2) - FullSolvedDomainRadius.at(4 * i + 2); + vector.at(3) = coordinates.at(3) - FullSolvedDomainRadius.at(4 * i + 3); if ( vector.computeNorm() <= FullSolvedDomainRadius.at(4 * i + 4) ) { diff --git a/src/sm/Quasicontinuum/fullsolveddomain.h b/src/sm/Quasicontinuum/fullsolveddomain.h old mode 100755 new mode 100644 index 2effb7c4f..d5d8eb554 --- a/src/sm/Quasicontinuum/fullsolveddomain.h +++ b/src/sm/Quasicontinuum/fullsolveddomain.h @@ -66,7 +66,7 @@ class QCFullsolveddomain QCFullsolveddomain(); virtual ~QCFullsolveddomain(); - virtual IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); virtual void updateYourself(); @@ -75,7 +75,7 @@ class QCFullsolveddomain // identification //virtual const char *giveInputRecordName() const { return _IFT_QCFullsolveddomain_Name; } - virtual const char *giveClassName() const { return "QCFullsolveddomain"; } + virtual const char *giveClassName() const { return "QCFullsolveddomain"; } diff --git a/src/sm/Quasicontinuum/geometrygenerator.C b/src/sm/Quasicontinuum/geometrygenerator.C index 09bd686e5..660eda540 100644 --- a/src/sm/Quasicontinuum/geometrygenerator.C +++ b/src/sm/Quasicontinuum/geometrygenerator.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Quasicontinuum/geometrygenerator.h" +#include "sm/Quasicontinuum/geometrygenerator.h" #include #include @@ -47,17 +47,14 @@ GeometryGenerator :: ~GeometryGenerator() // Destructor { } -IRResultType -GeometryGenerator :: initializeParticleGenerator(InputRecord *ir) +void +GeometryGenerator :: initializeParticleGenerator(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, maxNumOfParticles, _IFT_GeometryGenerator_numOfParticles); IR_GIVE_FIELD(ir, maxNumOfIterations, _IFT_GeometryGenerator_numOfIterations); IR_GIVE_FIELD(ir, maxNumOfItOnePar, _IFT_GeometryGenerator_numOfItOnePar); IR_GIVE_FIELD(ir, ParticleRadius, _IFT_GeometryGenerator_particleRadius); - //... // check input format @@ -68,8 +65,6 @@ GeometryGenerator :: initializeParticleGenerator(InputRecord *ir) * } */ #endif - - return IRRT_OK; } void @@ -153,7 +148,7 @@ GeometryGenerator :: CheckDistances(double R, FloatArray coords, int n) double R2 = R * R; for ( int i = 1; i <= n; i++ ) { - double distance2 = coords.distance_square(Particles [ i - 1 ]); + double distance2 = distance_square(coords, Particles [ i - 1 ]); if ( distance2 < R2 ) { return false; } @@ -167,12 +162,9 @@ void GeometryGenerator :: loadParticles() {} -IRResultType -GeometryGenerator :: initializeLinkGenerator(InputRecord *ir) +void +GeometryGenerator :: initializeLinkGenerator(InputRecord &ir) { - //IRResultType result; // Required by IR_GIVE_FIELD macro - return IRRT_OK; - } void diff --git a/src/sm/Quasicontinuum/geometrygenerator.h b/src/sm/Quasicontinuum/geometrygenerator.h old mode 100755 new mode 100644 index f5a24f85b..8a6b7c7c1 --- a/src/sm/Quasicontinuum/geometrygenerator.h +++ b/src/sm/Quasicontinuum/geometrygenerator.h @@ -52,39 +52,36 @@ namespace oofem { * */ class GeometryGenerator - { protected: -// global - int nop; // number of particles - int nol; // number of links - std::vector Particles; - std::vector Links; + // global + int nop; // number of particles + int nol; // number of links + std::vector Particles; + std::vector Links; -// particleGenerator - double ParticleRadius; // minimal distance of two particles - int maxNumOfParticles; // maximal number of generated particles - int maxNumOfIterations; // maximal number of iterations during generation - int maxNumOfItOnePar; // maximal number of generation of one particle + // particleGenerator + double ParticleRadius; // minimal distance of two particles + int maxNumOfParticles; // maximal number of generated particles + int maxNumOfIterations; // maximal number of iterations during generation + int maxNumOfItOnePar; // maximal number of generation of one particle public: GeometryGenerator(); virtual ~GeometryGenerator(); - IRResultType initializeParticleGenerator(InputRecord *ir); + void initializeParticleGenerator(InputRecord &ir); void generateParticles(); void loadParticles(); bool CheckDistances(double R, FloatArray coords, int n); - IRResultType initializeLinkGenerator(InputRecord *ir); + void initializeLinkGenerator(InputRecord &ir); void generateLinks(); void loadLinks(); - virtual const char *giveClassName() const { return "QCFullsolveddomain"; } - }; } // end namespace oofem #endif // geometrygenerator_h diff --git a/src/sm/Quasicontinuum/quasicontinuum.C b/src/sm/Quasicontinuum/quasicontinuum.C index c5409709c..888432537 100644 --- a/src/sm/Quasicontinuum/quasicontinuum.C +++ b/src/sm/Quasicontinuum/quasicontinuum.C @@ -32,30 +32,29 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "../sm/Quasicontinuum/quasicontinuum.h" -#include "../sm/EngineeringModels/qclinearstatic.h" +#include "sm/Quasicontinuum/quasicontinuum.h" +#include "sm/EngineeringModels/qclinearstatic.h" #include "qcnode.h" #include "element.h" #include "mathfem.h" #include "classfactory.h" #include "dynamicinputrecord.h" -#include "../sm/CrossSections/simplecrosssection.h" -#include "../sm/Materials/isolinearelasticmaterial.h" -#include "../sm/Materials/anisolinearelasticmaterial.h" +#include "sm/CrossSections/simplecrosssection.h" +#include "sm/Materials/isolinearelasticmaterial.h" +#include "sm/Materials/anisolinearelasticmaterial.h" #include "interfacetype.h" -#include "../sm/Materials/qcmaterialextensioninterface.h" +#include "sm/Materials/qcmaterialextensioninterface.h" namespace oofem { //REGISTER_Quasicontinuum(QCFullsolveddomain); Quasicontinuum :: Quasicontinuum() -// Constructor. {} + Quasicontinuum :: ~Quasicontinuum() -// Destructor {} @@ -73,7 +72,7 @@ Quasicontinuum :: setNoDimensions(Domain *d) void -Quasicontinuum :: setupInterpolationMesh(Domain *d, int generateInterpolationElements, int interpolationElementsMaterialNumber, std :: vector< IntArray > *newMeshNodes) +Quasicontinuum :: setupInterpolationMesh(Domain *d, int generateInterpolationElements, int interpolationElementsMaterialNumber, std :: vector< IntArray > &newMeshNodes) // rewrite existing interpolation mesh { int noNewEl = 0; @@ -84,11 +83,11 @@ Quasicontinuum :: setupInterpolationMesh(Domain *d, int generateInterpolationEle this->interpolationElementNumbers = d->giveElementsWithMaterialNum(interpolationElementsMaterialNumber); } else if ( ( generateInterpolationElements == 1 ) || ( generateInterpolationElements == 2 ) ) { // nodes were (generated and ) loaded from t3d output file - this->interpolationMeshNodes = * newMeshNodes; + this->interpolationMeshNodes = newMeshNodes; // elements will be placed in the end of element list this->interpolationElementNumbers.clear(); int noEl = d->giveNumberOfElements(); - noNewEl = newMeshNodes->size(); + noNewEl = newMeshNodes.size(); this->interpolationElementNumbers.resize(noNewEl); for ( int i = 1; i <= noNewEl; i++ ) { this->interpolationElementNumbers.at(i) = noEl + i; @@ -104,7 +103,6 @@ Quasicontinuum :: setupInterpolationMesh(Domain *d, int generateInterpolationEle } - void Quasicontinuum :: createInterpolationElements(Domain *d) // create new elements. Material will be defined after post initialization @@ -133,9 +131,9 @@ Quasicontinuum :: createInterpolationElements(Domain *d) */ // add interpolation elements (with new CS and no mat) - const char *elemType; if ( interpolationMeshNodes.size() != 0 ) { // for 2d + const char *elemType; if ( nDimensions == 2 ) { //elemType = "TrPlaneStrain"; elemType = "TrPlaneStress2d"; @@ -143,49 +141,45 @@ Quasicontinuum :: createInterpolationElements(Domain *d) } else { elemType = "LTRSpace"; } - } - int nelem = d->giveNumberOfElements(); - int elemNumber; - Element *elem; - DynamicInputRecord irEl; - // over interpolation elements - for ( int i = 1; i <= ninterpelem; i++ ) { - elemNumber = nelem + i; - d->resizeElements(elemNumber); - elem = classFactory.createElement(elemType, elemNumber, d); - irEl.setField(interpolationMeshNodes [ i - 1 ], _IFT_Element_nodes); - //irEl.setField( ncrosssect, _IFT_Element_crosssect); - //irEl.setField( nmat, _IFT_Element_mat); - elem->initializeFrom(& irEl); - elem->setGlobalNumber(elemNumber); - d->setElement(elemNumber, elem); + int nelem = d->giveNumberOfElements(); + DynamicInputRecord irEl; + // over interpolation elements + for ( int i = 1; i <= ninterpelem; i++ ) { + int elemNumber = nelem + i; + d->resizeElements(elemNumber); + auto elem = classFactory.createElement(elemType, elemNumber, d); + irEl.setField(interpolationMeshNodes [ i - 1 ], _IFT_Element_nodes); + //irEl.setField( ncrosssect, _IFT_Element_crosssect); + //irEl.setField( nmat, _IFT_Element_mat); + elem->initializeFrom(irEl); + elem->setGlobalNumber(elemNumber); + d->setElement(elemNumber, std::move(elem)); + } } } + void Quasicontinuum :: addCrosssectionToInterpolationElements(Domain *d) { // new crosssection - int ncrosssect = d->giveNumberOfCrossSectionModels() + 1; + int ncrosssect = d->giveNumberOfCrossSectionModels() + 1; d->resizeCrossSectionModels(ncrosssect); - CrossSection *crossSection; - crossSection = classFactory.createCrossSection("SimpleCS", ncrosssect, d); + auto crossSection = classFactory.createCrossSection("SimpleCS", ncrosssect, d); DynamicInputRecord irCS; irCS.setField(1.0, _IFT_SimpleCrossSection_thick); irCS.setField(1.0, _IFT_SimpleCrossSection_width); - crossSection->initializeFrom(& irCS); - d->setCrossSection(ncrosssect, crossSection); + crossSection->initializeFrom(irCS); + d->setCrossSection(ncrosssect, std::move(crossSection)); - int elNum; for ( int i = 1; i <= interpolationElementNumbers.giveSize(); i++ ) { - elNum = interpolationElementNumbers.at(i); + int elNum = interpolationElementNumbers.at(i); d->giveElement(elNum)->setCrossSection(ncrosssect); } } - void Quasicontinuum :: applyApproach1(Domain *d) // Approach 1 --- Hangingnodes (interpolation elementss with zero stiffnes) @@ -193,28 +187,27 @@ Quasicontinuum :: applyApproach1(Domain *d) // new material with zero stiffness int nmat = d->giveNumberOfMaterialModels() + 1; d->resizeMaterials(nmat); - Material *mat; - mat = classFactory.createMaterial("IsoLE", nmat, d); + auto mat = classFactory.createMaterial("IsoLE", nmat, d); DynamicInputRecord irMat; irMat.setField(1.e-20, _IFT_IsotropicLinearElasticMaterial_e); irMat.setField(0.0, _IFT_IsotropicLinearElasticMaterial_n); irMat.setField(0.0, _IFT_IsotropicLinearElasticMaterial_talpha); irMat.setField(0.0, _IFT_Material_density); - mat->initializeFrom(& irMat); - d->setMaterial(nmat, mat); + mat->initializeFrom(irMat); + d->setMaterial(nmat, std::move(mat)); // add material and CS to interpolation elements int ninterpelem = interpolationElementNumbers.giveSize(); - int elNum; int matNum = nmat; // over interpolation elements for ( int i = 1; i <= ninterpelem; i++ ) { - elNum = interpolationElementNumbers.at(i); + int elNum = interpolationElementNumbers.at(i); d->giveElement(elNum)->setMaterial(matNum); } } + void Quasicontinuum :: applyApproach2(Domain *d, int homMtrxType, double volumeOfInterpolationMesh) // Approach 2 --- Global homogenization @@ -315,11 +308,9 @@ Quasicontinuum :: applyApproach2(Domain *d, int homMtrxType, double volumeOfInte } - // global homogenization double S0; - FloatMatrix DisoMatrix(6, 6); - FloatMatrix *Diso = & DisoMatrix; + FloatMatrix Diso(6, 6); createGlobalStiffnesMatrix(Diso, S0, d, homMtrxType, volumeOfInterpolationMesh); double homogenizedE, homogenizedNu; @@ -329,7 +320,7 @@ Quasicontinuum :: applyApproach2(Domain *d, int homMtrxType, double volumeOfInte // new material with homogenized stiffness int nmat = d->giveNumberOfMaterialModels() + 1; d->resizeMaterials(nmat); - Material *mat; + std::unique_ptr mat; DynamicInputRecord irMat; // isotropic if ( homMtrxType == 1 ) { @@ -347,17 +338,17 @@ Quasicontinuum :: applyApproach2(Domain *d, int homMtrxType, double volumeOfInte alpha.zero(); if ( nDimensions == 2 ) { stiff = { - Diso->at(1, 1), Diso->at(1, 2), 0, 0, 0, Diso->at(1, 6), \ - Diso->at(2, 2), 0, 0, 0, Diso->at(2, 6), 33, 0, 0, 0, 44, \ - 0, 0, 55, 0, Diso->at(6, 6) + Diso.at(1, 1), Diso.at(1, 2), 0, 0, 0, Diso.at(1, 6), \ + Diso.at(2, 2), 0, 0, 0, Diso.at(2, 6), 33, 0, 0, 0, 44, \ + 0, 0, 55, 0, Diso.at(6, 6) }; } else if ( nDimensions == 3 ) { stiff = { - Diso->at(1, 1), Diso->at(1, 2), Diso->at(1, 3), Diso->at(1, 4), Diso->at(1, 5), Diso->at(1, 6), \ - Diso->at(2, 2), Diso->at(2, 3), Diso->at(2, 4), Diso->at(2, 5), Diso->at(2, 6), \ - Diso->at(3, 3), Diso->at(3, 4), Diso->at(3, 5), Diso->at(3, 6), \ - Diso->at(4, 4), Diso->at(4, 5), Diso->at(4, 6), \ - Diso->at(5, 5), Diso->at(5, 6), Diso->at(6, 6) + Diso.at(1, 1), Diso.at(1, 2), Diso.at(1, 3), Diso.at(1, 4), Diso.at(1, 5), Diso.at(1, 6), \ + Diso.at(2, 2), Diso.at(2, 3), Diso.at(2, 4), Diso.at(2, 5), Diso.at(2, 6), \ + Diso.at(3, 3), Diso.at(3, 4), Diso.at(3, 5), Diso.at(3, 6), \ + Diso.at(4, 4), Diso.at(4, 5), Diso.at(4, 6), \ + Diso.at(5, 5), Diso.at(5, 6), Diso.at(6, 6) }; } else { OOFEM_ERROR("Invalid number of dimensions. Only 2d and 3d domains are supported in QC simulation. \n"); @@ -368,17 +359,16 @@ Quasicontinuum :: applyApproach2(Domain *d, int homMtrxType, double volumeOfInte } else { OOFEM_ERROR("Invalid homMtrxType"); } - mat->initializeFrom(& irMat); - d->setMaterial(nmat, mat); + mat->initializeFrom(irMat); + d->setMaterial(nmat, std::move(mat)); // add material to interpolation elements int ninterpelem = interpolationElementNumbers.giveSize(); - int elNum; int matNum = nmat; // over interpolation elements for ( int i = 1; i <= ninterpelem; i++ ) { - elNum = interpolationElementNumbers.at(i); + int elNum = interpolationElementNumbers.at(i); d->giveElement(elNum)->setMaterial(matNum); } } @@ -401,16 +391,10 @@ Quasicontinuum :: applyApproach3(Domain *d, int homMtrxType) double s0Of1Link; int noIntEl = interpolationElementNumbers.giveSize(); - std :: vector< FloatMatrix * >individualStiffnessMatrices; - std :: vector< FloatMatrix * >individualStiffnessTensors; - individualStiffnessMatrices.resize(noIntEl); - individualStiffnessTensors.resize(noIntEl); - for ( int i = 0; i <= noIntEl - 1; i++ ) { - individualStiffnessTensors [ i ] = new FloatMatrix(9, 9); - individualStiffnessTensors [ i ]->zero(); - individualStiffnessMatrices [ i ] = new FloatMatrix(6, 6); - individualStiffnessMatrices [ i ]->zero(); - } + std :: vector< FloatMatrix > individualStiffnessMatrices; + std :: vector< FloatMatrix > individualStiffnessTensors; + individualStiffnessMatrices.resize(noIntEl, FloatMatrix(6, 6)); + individualStiffnessTensors.resize(noIntEl, FloatMatrix(9, 9)); FloatArray individualS0; individualS0.resize(noIntEl); @@ -475,7 +459,7 @@ Quasicontinuum :: applyApproach3(Domain *d, int homMtrxType) } else { // stiffness of link is assigned to masterElement computeStiffnessTensorOf1Link(stfTensorOf1Link, s0Of1Link, e, d); - individualStiffnessTensors [ interpolationElementIndices.at(masterElem) - 1 ]->add(stfTensorOf1Link); + individualStiffnessTensors [ interpolationElementIndices.at(masterElem) - 1 ].add(stfTensorOf1Link); individualS0 [ interpolationElementIndices.at(masterElem) - 1 ] += s0Of1Link; } @@ -494,7 +478,7 @@ Quasicontinuum :: applyApproach3(Domain *d, int homMtrxType) } else { // stiffness of link is assigned to masterElement computeStiffnessTensorOf1Link(stfTensorOf1Link, s0Of1Link, e, d); - individualStiffnessTensors [ interpolationElementIndices.at(masterElem) - 1 ]->add(stfTensorOf1Link); + individualStiffnessTensors [ interpolationElementIndices.at(masterElem) - 1 ].add(stfTensorOf1Link); individualS0 [ interpolationElementIndices.at(masterElem) - 1 ] += s0Of1Link; } @@ -518,23 +502,22 @@ Quasicontinuum :: applyApproach3(Domain *d, int homMtrxType) th = d->giveElement( interpolationElementNumbers.at(i) )->giveCrossSection()->give(CS_Thickness, NULL); volumeofEl = volumeofEl / th; } - individualStiffnessMatrices [ i - 1 ]->times(1 / volumeofEl); + individualStiffnessMatrices [ i - 1 ].times(1 / volumeofEl); } // ... - // deactivate homogenized nodes for ( int i = 1; i <= d->giveNumberOfDofManagers(); i++ ) { - if ( !nodeList(i) ) { - /// d->giveNode(i)->deactivateYourself(); + if ( !nodeList.at(i) ) { + // d->giveNode(i)->deactivateYourself(); } } // deactivate homogenized elements for ( int i = 1; i <= d->giveNumberOfElements(); i++ ) { - if ( !elemList(i) ) { - /// d->giveElement(i)->deactivateYourself(); + if ( !elemList.at(i) ) { + // d->giveElement(i)->deactivateYourself(); } } @@ -548,13 +531,10 @@ Quasicontinuum :: applyApproach3(Domain *d, int homMtrxType) } - - // new materials with homogenized stiffness int originalNumberOfMaterials = d->giveNumberOfMaterialModels(); d->resizeMaterials(originalNumberOfMaterials + noIntEl); int nmat = originalNumberOfMaterials; - Material *mat; DynamicInputRecord irMat; // isotropic @@ -563,26 +543,24 @@ Quasicontinuum :: applyApproach3(Domain *d, int homMtrxType) for ( int i = 1; i <= noIntEl; i++ ) { nmat++; homogenizationOfStiffMatrix(homogenizedE, homogenizedNu, individualStiffnessMatrices [ i - 1 ]); - mat = classFactory.createMaterial("IsoLE", nmat, d); + auto mat = classFactory.createMaterial("IsoLE", nmat, d); irMat.setField(homogenizedE, _IFT_IsotropicLinearElasticMaterial_e); irMat.setField(homogenizedNu, _IFT_IsotropicLinearElasticMaterial_n); irMat.setField(0.0, _IFT_IsotropicLinearElasticMaterial_talpha); irMat.setField(0.0, _IFT_Material_density); - mat->initializeFrom(& irMat); - d->setMaterial(nmat, mat); + mat->initializeFrom(irMat); + d->setMaterial(nmat, std::move(mat)); } // anisotropic } else if ( homMtrxType == 2 ) { - FloatMatrix Da; for ( int i = 1; i <= noIntEl; i++ ) { - Da = * individualStiffnessMatrices [ i - 1 ]; + FloatMatrix &Da = individualStiffnessMatrices [ i - 1 ]; nmat++; - mat = classFactory.createMaterial("AnisoLE", nmat, d); + auto mat = classFactory.createMaterial("AnisoLE", nmat, d); FloatArray stiff; FloatArray alpha(6); - alpha.zero(); if ( nDimensions == 2 ) { stiff = { Da.at(1, 1), Da.at(1, 2), 0, 0, 0, Da.at(1, 6), \ @@ -604,8 +582,8 @@ Quasicontinuum :: applyApproach3(Domain *d, int homMtrxType) irMat.setField(alpha, _IFT_AnisotropicLinearElasticMaterial_talpha); irMat.setField(0.0, _IFT_Material_density); - mat->initializeFrom(& irMat); - d->setMaterial(nmat, mat); + mat->initializeFrom(irMat); + d->setMaterial(nmat, std::move(mat)); } } else { OOFEM_ERROR("Invalid homMtrxType"); @@ -621,32 +599,19 @@ Quasicontinuum :: applyApproach3(Domain *d, int homMtrxType) elNum = interpolationElementNumbers.at(i); d->giveElement(elNum)->setMaterial(matNum); } - - - - // delete - for ( unsigned int i = 0; i <= individualStiffnessTensors.size() - 1; i++ ) { - delete individualStiffnessTensors [ i ]; - delete individualStiffnessMatrices [ i ]; - } - - for ( unsigned int i = 0; i <= connectivityTable.size() - 1; i++ ) { - delete connectivityTable [ i ]; - } } - void -Quasicontinuum :: homogenizationOfStiffMatrix(double &homogenizedE, double &homogenizedNu, FloatMatrix *Diso) +Quasicontinuum :: homogenizationOfStiffMatrix(double &homogenizedE, double &homogenizedNu, const FloatMatrix &Diso) // identification of E and Nu from isotropic stiffness matrix { // for 2d (planme stress only) if ( this->nDimensions == 2 ) { - double a = Diso->at(1, 1); - double b = Diso->at(1, 2); - double d = Diso->at(2, 2); - double f = Diso->at(6, 6); // xy stiff is in last column + double a = Diso.at(1, 1); + double b = Diso.at(1, 2); + double d = Diso.at(2, 2); + double f = Diso.at(6, 6); // xy stiff is in last column // Norma A - using eigen vectors - not implemented in 3D if ( 33 * a + 2 * b + 33 * d + 4 * f == 0 ) { // zero matrix = empty interpolation element -> zero stiffness homogenizedE = 1.0e-20; @@ -672,8 +637,8 @@ Quasicontinuum :: homogenizationOfStiffMatrix(double &homogenizedE, double &homo //- not implemented in 3D // Norma B - sum of squares of differences (with weight functions) - double a = Diso->at(1, 1) + Diso->at(2, 2) + Diso->at(3, 3); - double b = Diso->at(4, 4) + Diso->at(5, 5) + Diso->at(6, 6); + double a = Diso.at(1, 1) + Diso.at(2, 2) + Diso.at(3, 3); + double b = Diso.at(4, 4) + Diso.at(5, 5) + Diso.at(6, 6); if ( 5 * a + 13 * b == 0 ) { // zero matrix = empty interpolation element -> zero stiffness homogenizedE = 1.0e-20; @@ -697,14 +662,12 @@ Quasicontinuum :: computeStiffnessTensorOf1Link(FloatMatrix &D1, double &S0, Ele S0 = 0.; - double Etruss = 0.; - double Ry = 0.; QCMaterialExtensionInterface *qcmei = static_cast< QCMaterialExtensionInterface * >( e->giveMaterial()->giveInterface(QCMaterialExtensionInterfaceType) ); if ( !qcmei ) { OOFEM_ERROR("Material doesn't implement the required QC interface!"); } - Etruss = qcmei->giveQcElasticParamneter(); - Ry = qcmei->giveQcPlasticParamneter(); + double Etruss = qcmei->giveQcElasticParamneter(); + double Ry = qcmei->giveQcPlasticParamneter(); double area = 0.; SimpleCrossSection *cs = dynamic_cast< SimpleCrossSection * >( e->giveCrossSection() ); @@ -714,23 +677,22 @@ Quasicontinuum :: computeStiffnessTensorOf1Link(FloatMatrix &D1, double &S0, Ele OOFEM_ERROR( "Invalid CrossSection of link %d. simpleCS is only supported CS of links in QC simulation. \n", e->giveGlobalNumber() ); } - double x1 = e->giveDofManager(1)->giveCoordinates()->at(1); - double y1 = e->giveDofManager(1)->giveCoordinates()->at(2); - double z1 = e->giveDofManager(1)->giveCoordinates()->at(3); - double x2 = e->giveDofManager(2)->giveCoordinates()->at(1); - double y2 = e->giveDofManager(2)->giveCoordinates()->at(2); - double z2 = e->giveDofManager(2)->giveCoordinates()->at(3); + double x1 = e->giveDofManager(1)->giveCoordinate(1); + double y1 = e->giveDofManager(1)->giveCoordinate(2); + double z1 = e->giveDofManager(1)->giveCoordinate(3); + double x2 = e->giveDofManager(2)->giveCoordinate(1); + double y2 = e->giveDofManager(2)->giveCoordinate(2); + double z2 = e->giveDofManager(2)->giveCoordinate(3); double TrussLength = sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) + ( z2 - z1 ) * ( z2 - z1 ) ); double n [ 3 ]; n [ 0 ] = ( x2 - x1 ) / TrussLength; n [ 1 ] = ( y2 - y1 ) / TrussLength; n [ 2 ] = ( z2 - z1 ) / TrussLength; // create stiffness tensor - int i, j, k, l; - for ( i = 1; i <= 3; i++ ) { - for ( j = 1; j <= 3; j++ ) { - for ( k = 1; k <= 3; k++ ) { - for ( l = 1; l <= 3; l++ ) { + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + for ( int k = 1; k <= 3; k++ ) { + for ( int l = 1; l <= 3; l++ ) { D1.at(3 * ( i - 1 ) + k, 3 * ( j - 1 ) + l) = TrussLength * Etruss * n [ i - 1 ] * n [ j - 1 ] * n [ k - 1 ] * n [ l - 1 ]; } } @@ -744,44 +706,33 @@ Quasicontinuum :: computeStiffnessTensorOf1Link(FloatMatrix &D1, double &S0, Ele } - void -Quasicontinuum :: createGlobalStiffnesMatrix(FloatMatrix *D, double &S0, Domain *d, int homMtrxType, double volumeOfInterpolationMesh) -// +Quasicontinuum :: createGlobalStiffnesMatrix(FloatMatrix &D, double &S0, Domain *d, int homMtrxType, double volumeOfInterpolationMesh) { - int i, j, k, l, t; int noe = d->giveNumberOfElements(); - S0 = 0; //double StiffessTensor[81]; // stiffness tensor 3^4 represented by 9x9 mtrx - FloatMatrix StiffTens; - FloatMatrix *StiffnessTensor = & StiffTens; - StiffnessTensor->resize(9, 9); - StiffnessTensor->zero(); + FloatMatrix StiffnessTensor(9, 9); //double D1[81]; // stiffness tensor 3^4 of 1 link represented by 9x9 mtrx FloatMatrix D1(9, 9); - D1.zero(); - double TrussLength, x1, x2, y1, y2, z1, z2; double n [ 3 ]; // over all elements - for ( t = 1; t <= noe; t++ ) { + for ( int t = 1; t <= noe; t++ ) { // ??km?? TO DO: use list of interpolation elements instead of skipping... if ( d->giveElement(t)->giveNumberOfDofManagers() > 2 ) { continue; // skip interpolation elements } // TO DO: function "computeStiffnessMatrixOf1Link" can be used here - double Etruss = 0.; - double Ry = 0.; QCMaterialExtensionInterface *qcmei = static_cast< QCMaterialExtensionInterface * >( d->giveElement(t)->giveMaterial()->giveInterface(QCMaterialExtensionInterfaceType) ); if ( !qcmei ) { OOFEM_ERROR("Material doesn't implement the required QC interface!"); } - Etruss = qcmei->giveQcElasticParamneter(); - Ry = qcmei->giveQcPlasticParamneter(); + double Etruss = qcmei->giveQcElasticParamneter(); + double Ry = qcmei->giveQcPlasticParamneter(); double area = 0.; SimpleCrossSection *cs = dynamic_cast< SimpleCrossSection * >( d->giveElement(t)->giveCrossSection() ); @@ -791,28 +742,28 @@ Quasicontinuum :: createGlobalStiffnesMatrix(FloatMatrix *D, double &S0, Domain OOFEM_ERROR( "Invalid CrossSection of link %d. simpleCS is only supported CS of links in QC simulation. \n", d->giveElement(t)->giveGlobalNumber() ); } - x1 = d->giveElement(t)->giveDofManager(1)->giveCoordinates()->at(1); - y1 = d->giveElement(t)->giveDofManager(1)->giveCoordinates()->at(2); - z1 = d->giveElement(t)->giveDofManager(1)->giveCoordinates()->at(3); - x2 = d->giveElement(t)->giveDofManager(2)->giveCoordinates()->at(1); - y2 = d->giveElement(t)->giveDofManager(2)->giveCoordinates()->at(2); - z2 = d->giveElement(t)->giveDofManager(2)->giveCoordinates()->at(3); - TrussLength = sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) + ( z2 - z1 ) * ( z2 - z1 ) ); + double x1 = d->giveElement(t)->giveDofManager(1)->giveCoordinate(1); + double y1 = d->giveElement(t)->giveDofManager(1)->giveCoordinate(2); + double z1 = d->giveElement(t)->giveDofManager(1)->giveCoordinate(3); + double x2 = d->giveElement(t)->giveDofManager(2)->giveCoordinate(1); + double y2 = d->giveElement(t)->giveDofManager(2)->giveCoordinate(2); + double z2 = d->giveElement(t)->giveDofManager(2)->giveCoordinate(3); + double TrussLength = sqrt( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) + ( z2 - z1 ) * ( z2 - z1 ) ); n [ 0 ] = ( x2 - x1 ) / TrussLength; n [ 1 ] = ( y2 - y1 ) / TrussLength; n [ 2 ] = ( z2 - z1 ) / TrussLength; // stiffness tensor - for ( i = 1; i <= 3; i++ ) { - for ( j = 1; j <= 3; j++ ) { - for ( k = 1; k <= 3; k++ ) { - for ( l = 1; l <= 3; l++ ) { + for ( int i = 1; i <= 3; i++ ) { + for ( int j = 1; j <= 3; j++ ) { + for ( int k = 1; k <= 3; k++ ) { + for ( int l = 1; l <= 3; l++ ) { D1.at(3 * ( i - 1 ) + k, 3 * ( j - 1 ) + l) = TrussLength * Etruss * n [ i - 1 ] * n [ j - 1 ] * n [ k - 1 ] * n [ l - 1 ]; } } } } - StiffnessTensor->add(D1); // add stfMtrX of 1 link to global stfMtrx + StiffnessTensor.add(D1); // add stfMtrX of 1 link to global stfMtrx if ( !std :: isinf(Ry) ) { S0 += TrussLength * area * Ry / 3; @@ -820,7 +771,7 @@ Quasicontinuum :: createGlobalStiffnesMatrix(FloatMatrix *D, double &S0, Domain } // for t=1:note // divide by volume of element - StiffnessTensor->times(1 / volumeOfInterpolationMesh); + StiffnessTensor.times(1 / volumeOfInterpolationMesh); S0 = S0 / volumeOfInterpolationMesh; transformStiffnessTensorToMatrix(D, StiffnessTensor); @@ -828,26 +779,15 @@ Quasicontinuum :: createGlobalStiffnesMatrix(FloatMatrix *D, double &S0, Domain bool -Quasicontinuum :: stiffnessAssignment(std :: vector< FloatMatrix * > &individualStiffnessTensors, FloatArray &individualS0, Domain *d, Element *e, qcNode *qn1, qcNode *qn2) +Quasicontinuum :: stiffnessAssignment(std :: vector< FloatMatrix > &individualStiffnessTensors, FloatArray &individualS0, Domain *d, Element *e, qcNode *qn1, qcNode *qn2) { - register int i; - FloatMatrix stfTensorOf1Link(9, 9), contribution(9, 9); + FloatMatrix stfTensorOf1Link(9, 9); double s0Of1Link; - int nel, indx; - // numbers of elements containing ending nodes int end1 = qn1->giveMasterElementNumber(); int end2 = qn2->giveMasterElementNumber(); - // Coords and length - FloatArray *coords1 = qn1->giveCoordinates(); - FloatArray *coords2 = qn2->giveCoordinates(); - //coordsDif->subtract(*coords1); - FloatArray coordsDif(2); - coordsDif.beDifferenceOf(* coords1, * coords2); - double totalLength = coordsDif.computeNorm(); - /* * if ( (end1==0) && (end2==0) ) { // both ends are located outside * // this case is solved explicitly before StiffnessAssignment @@ -859,17 +799,15 @@ Quasicontinuum :: stiffnessAssignment(std :: vector< FloatMatrix * > &individual if ( end1 == end2 ) { // both ends are in the same el. // stiffness of link is assigned to this el. computeStiffnessTensorOf1Link(stfTensorOf1Link, s0Of1Link, e, d); - nel = end1; // number of interp element - indx = interpolationElementIndices.at(nel); // number in list of interp elem - individualStiffnessTensors [ indx - 1 ]->add(stfTensorOf1Link); + int nel = end1; // number of interp element + int indx = interpolationElementIndices.at(nel); // number in list of interp elem + individualStiffnessTensors [ indx - 1 ].add(stfTensorOf1Link); individualS0 [ indx - 1 ] += s0Of1Link; return true; } else { // ends are located in different elements -> all intersected el needs to be found IntArray intersected; // to store numbers of intersected elem FloatArray lengths; // to store lengths ofintersections - intersected.clear(); - lengths.clear(); computeIntersectionsOfLinkWithInterpElements(intersected, lengths, d, e, qn1, qn2); @@ -882,26 +820,20 @@ Quasicontinuum :: stiffnessAssignment(std :: vector< FloatMatrix * > &individual // check: is stiff. assigned to all parts of the link? // TO DO: the same check is done in "computeIntersectionsOfLinkWith...". // Use only return value here + double totalLength = distance(qn1->giveCoordinates(), qn2->giveCoordinates()); lengths.times(1 / totalLength); // it is better to use relative lengths - double sumLength = 0.0; - for ( int i = 1; i <= noIntersected; i++ ) { - sumLength += lengths [ i - 1 ]; - } - if ( sumLength > 1.0001 ) { - return false; - } else if ( sumLength < 0.9999 ) { + double sumLength = lengths.sum(); + if ( (sumLength < 0.9999) || (sumLength > 1.0001) ) { return false; } // if check OK ( sumLength == 1 ) computeStiffnessTensorOf1Link(stfTensorOf1Link, s0Of1Link, e, d); - for ( i = 1; i <= noIntersected; i++ ) { // add stiff to all intersected elem - nel = intersected [ i - 1 ]; // number of element - indx = interpolationElementIndices.at(nel); // number in list of interp elem - contribution = stfTensorOf1Link; - contribution.times( lengths.at(i) ); - individualStiffnessTensors [ indx - 1 ]->add(contribution); + for ( int i = 1; i <= noIntersected; i++ ) { // add stiff to all intersected elem + int nel = intersected [ i - 1 ]; // number of element + int indx = interpolationElementIndices.at(nel); // number in list of interp elem + individualStiffnessTensors [ indx - 1 ].add(lengths.at(i), stfTensorOf1Link); individualS0 [ indx - 1 ] += lengths.at(i) * s0Of1Link; } return true; @@ -924,44 +856,42 @@ Quasicontinuum :: computeIntersectionsOfLinkWithInterpElements(IntArray &interse } } + bool Quasicontinuum :: computeIntersectionsOfLinkWith2DTringleElements(IntArray &intersected, FloatArray &lengths, Domain *d, Element *e, qcNode *qn1, qcNode *qn2) { intersected.clear(); lengths.clear(); - // coordinates of ending nodes - FloatArray *X1 = qn1->giveCoordinates(); - FloatArray *X2 = qn2->giveCoordinates(); - - double TotalLength = sqrt( ( X2->at(1) - X1->at(1) ) * ( X2->at(1) - X1->at(1) ) + ( X2->at(2) - X1->at(2) ) * ( X2->at(2) - X1->at(2) ) ); - // numbers of elements containing ending nodes int end1 = qn1->giveMasterElementNumber(); int end2 = qn2->giveMasterElementNumber(); if ( end2 < end1 ) { // swap? - X2 = qn1->giveCoordinates(); - X1 = qn2->giveCoordinates(); - end2 = qn1->giveMasterElementNumber(); - end1 = qn2->giveMasterElementNumber(); + std::swap(end1, end2); + std::swap(qn1, qn2); } + // coordinates of ending nodes + const auto &X1 = qn1->giveCoordinates(); + const auto &X2 = qn2->giveCoordinates(); + + double TotalLength = distance(X2, X1); + int numberOfIntersected = 0; // number of intersected elements - FloatArray *A, *B, *C, vector(2); - FloatArray intersectCoordsX, intersectCoordsY; + FloatArray vector(2); + std::vector intersectCoords; double iLen, sumLength = 0.0; - register int nn, ii, i; // ftiffness assignment for starting element (end1) int iel = end1; FloatArray iLens; - A = d->giveElement(iel)->giveNode(1)->giveCoordinates(); - B = d->giveElement(iel)->giveNode(2)->giveCoordinates(); - C = d->giveElement(iel)->giveNode(3)->giveCoordinates(); - numberOfIntersected = intersectionTestSegmentTriangle2D(intersectCoordsX, intersectCoordsY, A, B, C, X1, X2); + const auto &A = d->giveElement(iel)->giveNode(1)->giveCoordinates(); + const auto &B = d->giveElement(iel)->giveNode(2)->giveCoordinates(); + const auto &C = d->giveElement(iel)->giveNode(3)->giveCoordinates(); + numberOfIntersected = intersectionTestSegmentTriangle2D(intersectCoords, A, B, C, X1, X2); switch ( numberOfIntersected ) { case 0: // no intersection with this element @@ -969,9 +899,7 @@ Quasicontinuum :: computeIntersectionsOfLinkWith2DTringleElements(IntArray &inte intersected.followedBy(iel); // cislo elementu break; case 1: // link starts in this element - vector.at(1) = intersectCoordsX.at(1) - X1->at(1); - vector.at(2) = intersectCoordsY.at(1) - X1->at(2); - iLen = vector.computeNorm(); + iLen = distance(X1, intersectCoords[0]); if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible lengths.push_back(iLen); intersected.followedBy(iel); @@ -985,9 +913,7 @@ Quasicontinuum :: computeIntersectionsOfLinkWith2DTringleElements(IntArray &inte //lengths of all possible cobmination of intersection points iLens.resize(numberOfIntersected); for ( int nn = 1; nn <= numberOfIntersected; nn++ ) { - vector.at(1) = intersectCoordsX.at(nn) - X1->at(1); - vector.at(2) = intersectCoordsY.at(nn) - X1->at(2); - iLens.at(nn) = vector.computeNorm(); + iLens.at(nn) = distance(X1, intersectCoords[nn - 1]); } iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximal one if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible @@ -1002,7 +928,6 @@ Quasicontinuum :: computeIntersectionsOfLinkWith2DTringleElements(IntArray &inte // ftiffness assignment for the rest of the link - bool breakFor = false; IntArray neighboursList, alreadyTestedElemList; alreadyTestedElemList.clear(); @@ -1010,27 +935,25 @@ Quasicontinuum :: computeIntersectionsOfLinkWith2DTringleElements(IntArray &inte //bool secondEndReached = false; int nextElement = end1; - int nel, index, m; - register int k; - for ( ii = 1; ii <= nome; ii++ ) { // searching for nex intersected element - nel = nextElement; // previous element number + for ( int ii = 1; ii <= nome; ii++ ) { // searching for nex intersected element + int nel = nextElement; // previous element number nextElement = 0; // next element number (to be found) // list of connected elements - neighboursList = * connectivityTable [ interpolationElementIndices.at(nel) - 1 ]; + neighboursList = connectivityTable [ interpolationElementIndices.at(nel) - 1 ]; // delete already intersected elements - for ( k = 1; k <= intersected.giveSize(); k++ ) { - index = neighboursList.findFirstIndexOf( intersected.at(k) ); + for ( int k = 1; k <= intersected.giveSize(); k++ ) { + int index = neighboursList.findFirstIndexOf( intersected.at(k) ); if ( index != 0 ) { neighboursList.erase(index); } } // delete already tested elements - for ( k = 1; k <= alreadyTestedElemList.giveSize(); k++ ) { - index = neighboursList.findFirstIndexOf( alreadyTestedElemList.at(k) ); + for ( int k = 1; k <= alreadyTestedElemList.giveSize(); k++ ) { + int index = neighboursList.findFirstIndexOf( alreadyTestedElemList.at(k) ); if ( index != 0 ) { neighboursList.erase(index); } @@ -1042,24 +965,22 @@ Quasicontinuum :: computeIntersectionsOfLinkWith2DTringleElements(IntArray &inte break; // ends searching for nex intersected element } - for ( k = 1; k <= neighboursList.giveSize(); k++ ) { // testing of neighbouring elements + for ( int k = 1; k <= neighboursList.giveSize(); k++ ) { // testing of neighbouring elements iel = neighboursList.at(k); - A = d->giveElement(iel)->giveNode(1)->giveCoordinates(); - B = d->giveElement(iel)->giveNode(2)->giveCoordinates(); - C = d->giveElement(iel)->giveNode(3)->giveCoordinates(); - numberOfIntersected = intersectionTestSegmentTriangle2D(intersectCoordsX, intersectCoordsY, A, B, C, X1, X2); + const auto &A = d->giveElement(iel)->giveNode(1)->giveCoordinates(); + const auto &B = d->giveElement(iel)->giveNode(2)->giveCoordinates(); + const auto &C = d->giveElement(iel)->giveNode(3)->giveCoordinates(); + numberOfIntersected = intersectionTestSegmentTriangle2D(intersectCoords, A, B, C, X1, X2); - breakFor = false; // go to next element? + bool breakFor = false; // go to next element? switch ( numberOfIntersected ) { case 0: // no intersection with (iel) element -> go to next element alreadyTestedElemList.followedBy(iel); continue; case 1: // link ends here or there in only fake intersection if ( iel == end2 ) { // end of the link in in this element - vector.at(1) = intersectCoordsX.at(1) - X2->at(1); - vector.at(2) = intersectCoordsY.at(1) - X2->at(2); - iLen = vector.computeNorm(); + iLen = distance(X2, intersectCoords[0]); if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible lengths.push_back(iLen); intersected.followedBy(iel); @@ -1078,9 +999,7 @@ Quasicontinuum :: computeIntersectionsOfLinkWith2DTringleElements(IntArray &inte //lengths of all possible cobmination of intersection points iLens.resize(numberOfIntersected); for ( int nn = 1; nn <= numberOfIntersected; nn++ ) { - vector.at(1) = intersectCoordsX.at(nn) - X2->at(1); - vector.at(2) = intersectCoordsY.at(nn) - X2->at(2); - iLens.at(nn) = vector.computeNorm(); + iLens.at(nn) = distance(X2, intersectCoords[nn - 1]); } iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximal if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible @@ -1096,13 +1015,11 @@ Quasicontinuum :: computeIntersectionsOfLinkWith2DTringleElements(IntArray &inte } else { // end of the link is NOT inthis elem iLens.resize(3); // combinations: 12 13 23 iLens.zero(); - m = 0; - for ( nn = 1; nn < numberOfIntersected; nn++ ) { - for ( ii = nn + 1; ii <= numberOfIntersected; ii++ ) { + int m = 0; + for ( int nn = 1; nn < numberOfIntersected; nn++ ) { + for ( int ii = nn + 1; ii <= numberOfIntersected; ii++ ) { m += 1; - vector.at(1) = intersectCoordsX.at(nn) - intersectCoordsX.at(ii); - vector.at(2) = intersectCoordsY.at(nn) - intersectCoordsY.at(ii); - iLens.at(m) = vector.computeNorm(); + iLens.at(m) = distance(intersectCoords[ii - 1], intersectCoords[nn - 1]); } } iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximum @@ -1126,10 +1043,7 @@ Quasicontinuum :: computeIntersectionsOfLinkWith2DTringleElements(IntArray &inte // check: all length of link is assembles - sumLength = 0.0; - for ( i = 1; i <= lengths.giveSize(); i++ ) { - sumLength += lengths.at(i); - } + sumLength = lengths.sum(); if ( ( fabs(sumLength / TotalLength - 1) ) <= ( 0.0001 ) ) { return true; } @@ -1144,51 +1058,42 @@ Quasicontinuum :: computeIntersectionsOfLinkWith2DTringleElements(IntArray &inte } - - - bool Quasicontinuum :: computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &intersected, FloatArray &lengths, Domain *d, Element *e, qcNode *qn1, qcNode *qn2) { intersected.clear(); lengths.clear(); - // coordinates of ending nodes - FloatArray *X1 = qn1->giveCoordinates(); - FloatArray *X2 = qn2->giveCoordinates(); - - double TotalLength = sqrt( ( X2->at(1) - X1->at(1) ) * ( X2->at(1) - X1->at(1) ) + ( X2->at(2) - X1->at(2) ) * ( X2->at(2) - X1->at(2) ) + ( X2->at(3) - X1->at(3) ) * ( X2->at(3) - X1->at(3) ) ); - // numbers of elements containing ending nodes int end1 = qn1->giveMasterElementNumber(); int end2 = qn2->giveMasterElementNumber(); if ( end2 < end1 ) { // swap? - X2 = qn1->giveCoordinates(); - X1 = qn2->giveCoordinates(); - end2 = qn1->giveMasterElementNumber(); - end1 = qn2->giveMasterElementNumber(); + std::swap(end1, end2); + std::swap(qn1, qn2); } - int numberOfIntersected = 0; // number of intersected elements + // coordinates of ending nodes + const auto &X1 = qn1->giveCoordinates(); + const auto &X2 = qn2->giveCoordinates(); - FloatArray *A, *B, *C, *D, vector(3); - FloatArray intersectCoordsX, intersectCoordsY, intersectCoordsZ; - double iLen, sumLength = 0.0; - register int nn, ii, i; + double TotalLength = distance(X2, X1); + int numberOfIntersected = 0; // number of intersected elements + std::vector intersectCoords; + double iLen, sumLength = 0.0; // ftiffness assignment for starting element (end1) int iel = end1; FloatArray iLens; - A = d->giveElement(iel)->giveNode(1)->giveCoordinates(); - B = d->giveElement(iel)->giveNode(2)->giveCoordinates(); - C = d->giveElement(iel)->giveNode(3)->giveCoordinates(); - D = d->giveElement(iel)->giveNode(4)->giveCoordinates(); - numberOfIntersected = intersectionTestSegmentTetrahedra3D(intersectCoordsX, intersectCoordsY, intersectCoordsZ, A, B, C, D, X1, X2); + const auto &A = d->giveElement(iel)->giveNode(1)->giveCoordinates(); + const auto &B = d->giveElement(iel)->giveNode(2)->giveCoordinates(); + const auto &C = d->giveElement(iel)->giveNode(3)->giveCoordinates(); + const auto &D = d->giveElement(iel)->giveNode(4)->giveCoordinates(); + numberOfIntersected = intersectionTestSegmentTetrahedra3D(intersectCoords, A, B, C, D, X1, X2); switch ( numberOfIntersected ) { case 0: // no intersection with this element @@ -1196,10 +1101,7 @@ Quasicontinuum :: computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &i intersected.followedBy(iel); // cislo elementu break; case 1: // link starts in this element - vector.at(1) = intersectCoordsX.at(1) - X1->at(1); - vector.at(2) = intersectCoordsY.at(1) - X1->at(2); - vector.at(3) = intersectCoordsZ.at(1) - X1->at(3); - iLen = vector.computeNorm(); + iLen = distance(X1, intersectCoords[0]); if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible lengths.push_back(iLen); intersected.followedBy(iel); @@ -1213,10 +1115,7 @@ Quasicontinuum :: computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &i //lengths of all possible cobmination of intersection points iLens.resize(numberOfIntersected); for ( int nn = 1; nn <= numberOfIntersected; nn++ ) { - vector.at(1) = intersectCoordsX.at(nn) - X1->at(1); - vector.at(2) = intersectCoordsY.at(nn) - X1->at(2); - vector.at(3) = intersectCoordsZ.at(nn) - X1->at(3); - iLens.at(nn) = vector.computeNorm(); + iLens.at(nn) = distance(X1, intersectCoords[nn - 1]); } iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximal one if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible @@ -1229,8 +1128,6 @@ Quasicontinuum :: computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &i break; } - - // ftiffness assignment for the rest of the link bool breakFor = false; @@ -1241,46 +1138,43 @@ Quasicontinuum :: computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &i //bool secondEndReached = false; int nextElement = end1; - int nel, index, m; - register int k; - for ( ii = 1; ii <= nome; ii++ ) { // searching for nex intersected element - nel = nextElement; // previous element number + for ( int ii = 1; ii <= nome; ii++ ) { // searching for nex intersected element + int nel = nextElement; // previous element number nextElement = 0; // next element number (to be found) // list of connected elements - neighboursList = * connectivityTable [ interpolationElementIndices.at(nel) - 1 ]; + neighboursList = connectivityTable [ interpolationElementIndices.at(nel) - 1 ]; // delete already intersected elements - for ( k = 1; k <= intersected.giveSize(); k++ ) { - index = neighboursList.findFirstIndexOf( intersected.at(k) ); + for ( int k = 1; k <= intersected.giveSize(); k++ ) { + int index = neighboursList.findFirstIndexOf( intersected.at(k) ); if ( index != 0 ) { neighboursList.erase(index); } } // delete already tested elements - for ( k = 1; k <= alreadyTestedElemList.giveSize(); k++ ) { - index = neighboursList.findFirstIndexOf( alreadyTestedElemList.at(k) ); + for ( int k = 1; k <= alreadyTestedElemList.giveSize(); k++ ) { + int index = neighboursList.findFirstIndexOf( alreadyTestedElemList.at(k) ); if ( index != 0 ) { neighboursList.erase(index); } } - if ( neighboursList.giveSize() == 0 ) { // no elements to continue //secondEndReached = false; break; // ends searching for nex intersected element } - for ( k = 1; k <= neighboursList.giveSize(); k++ ) { // testing of neighbouring elements - iel = neighboursList.at(k); + for ( int k = 1; k <= neighboursList.giveSize(); k++ ) { // testing of neighbouring elements + int iel = neighboursList.at(k); - A = d->giveElement(iel)->giveNode(1)->giveCoordinates(); - B = d->giveElement(iel)->giveNode(2)->giveCoordinates(); - C = d->giveElement(iel)->giveNode(3)->giveCoordinates(); - D = d->giveElement(iel)->giveNode(4)->giveCoordinates(); - numberOfIntersected = intersectionTestSegmentTetrahedra3D(intersectCoordsX, intersectCoordsY, intersectCoordsZ, A, B, C, D, X1, X2); + const auto &A = d->giveElement(iel)->giveNode(1)->giveCoordinates(); + const auto &B = d->giveElement(iel)->giveNode(2)->giveCoordinates(); + const auto &C = d->giveElement(iel)->giveNode(3)->giveCoordinates(); + const auto &D = d->giveElement(iel)->giveNode(4)->giveCoordinates(); + int numberOfIntersected = intersectionTestSegmentTetrahedra3D(intersectCoords, A, B, C, D, X1, X2); breakFor = false; // go to next interp elem @@ -1290,10 +1184,7 @@ Quasicontinuum :: computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &i continue; // zadna tuhost se prvku neprirazuje case 1: // link ends here or there in only fake intersection if ( iel == end2 ) { // end of the link in in this element - vector.at(1) = intersectCoordsX.at(1) - X2->at(1); - vector.at(2) = intersectCoordsY.at(1) - X2->at(2); - vector.at(3) = intersectCoordsZ.at(1) - X2->at(3); - iLen = vector.computeNorm(); + iLen = distance(X2, intersectCoords[0]); if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible lengths.push_back(iLen); intersected.followedBy(iel); @@ -1312,10 +1203,7 @@ Quasicontinuum :: computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &i //lengths of all possible cobmination of intersection points iLens.resize(numberOfIntersected); for ( int nn = 1; nn <= numberOfIntersected; nn++ ) { - vector.at(1) = intersectCoordsX.at(nn) - X2->at(1); - vector.at(2) = intersectCoordsY.at(nn) - X2->at(2); - vector.at(3) = intersectCoordsZ.at(nn) - X2->at(3); - iLens.at(nn) = vector.computeNorm(); + iLens.at(nn) = distance(X2, intersectCoords[nn - 1]); } iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximal if ( iLen / TotalLength >= 1.e-6 ) { // intersection is not negligible @@ -1331,14 +1219,11 @@ Quasicontinuum :: computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &i } else { // end of the link is NOT inthis elem iLens.resize(6); // combinations: 12 13 14 23 24 34 iLens.zero(); - m = 0; - for ( nn = 1; nn <= numberOfIntersected; nn++ ) { - for ( ii = nn + 1; ii <= numberOfIntersected; ii++ ) { + int m = 0; + for ( int nn = 1; nn <= numberOfIntersected; nn++ ) { + for ( int ii = nn + 1; ii <= numberOfIntersected; ii++ ) { m += 1; - vector.at(1) = intersectCoordsX.at(nn) - intersectCoordsX.at(ii); - vector.at(2) = intersectCoordsY.at(nn) - intersectCoordsY.at(ii); - vector.at(3) = intersectCoordsZ.at(nn) - intersectCoordsZ.at(ii); - iLens.at(m) = vector.computeNorm(); + iLens.at(m) = distance(intersectCoords[ii - 1], intersectCoords[nn - 1]); } } iLen = iLens.at( iLens.giveIndexMaxElem() ); // real length is maximum @@ -1362,10 +1247,7 @@ Quasicontinuum :: computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &i // check: all length of link is assembles - sumLength = 0.0; - for ( i = 1; i <= lengths.giveSize(); i++ ) { - sumLength += lengths.at(i); - } + sumLength = lengths.sum(); if ( ( fabs(sumLength / TotalLength - 1) ) <= ( 0.0001 ) ) { return true; } @@ -1379,42 +1261,38 @@ Quasicontinuum :: computeIntersectionsOfLinkWith3DTetrahedraElements(IntArray &i return false; } + void Quasicontinuum :: initializeConnectivityTableForInterpolationElements(Domain *d) { // for each element save elements with shared node (edge, face,,,) - register int i, j, k, l; int nome = interpolationElementNumbers.giveSize(); - int elNum1, elNum2, noVertices1, noVertices2; - Element *e1, *e2; + int noVertices1, noVertices2; IntArray vertices1; connectivityTable.clear(); connectivityTable.resize(nome); - - - for ( j = 1; j <= nome; j++ ) { // all interpolation elements - connectivityTable [ j - 1 ] = new IntArray(); - elNum1 = interpolationElementNumbers.at(j); - e1 = d->giveElement(elNum1); + for ( int j = 1; j <= nome; j++ ) { // all interpolation elements + int elNum1 = interpolationElementNumbers.at(j); + Element *e1 = d->giveElement(elNum1); // vector of vertices numbers of el j noVertices1 = e1->giveNumberOfNodes(); vertices1.resize(noVertices1); - for ( k = 1; k <= noVertices1; k++ ) { // fill in vector + for ( int k = 1; k <= noVertices1; k++ ) { // fill in vector vertices1.at(k) = e1->giveNode(k)->giveNumber(); } - for ( i = 1; i <= nome; i++ ) { + for ( int i = 1; i <= nome; i++ ) { if ( i == j ) { continue; } // is not itself neighbour // vector of vertices numbers of el j - elNum2 = interpolationElementNumbers.at(i); - e2 = d->giveElement(elNum2); + int elNum2 = interpolationElementNumbers.at(i); + Element *e2 = d->giveElement(elNum2); noVertices2 = e2->giveNumberOfNodes(); - for ( l = 1; l <= noVertices2; l++ ) { // fill in vector + for ( int l = 1; l <= noVertices2; l++ ) { // fill in vector if ( vertices1.contains( e2->giveNode(l)->giveNumber() ) ) { - connectivityTable [ j - 1 ]->followedBy(elNum2); // add number of neighbour + connectivityTable [ j - 1 ].followedBy(elNum2); // add number of neighbour break; } } @@ -1423,48 +1301,46 @@ Quasicontinuum :: initializeConnectivityTableForInterpolationElements(Domain *d) } - - bool -Quasicontinuum :: intersectionTestSegmentTrianglePlucker3D(FloatArray &intersectCoords, FloatArray *A, FloatArray *B, FloatArray *C, FloatArray *X1, FloatArray *X2) +Quasicontinuum :: intersectionTestSegmentTrianglePlucker3D(FloatArray &intersectCoords, const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &X1, const FloatArray &X2) { // test if line (X2-X1) intersects tringle ABC (for 3D!) intersectCoords.clear(); // directional vektor - double L = sqrt( ( X2->at(1) - X1->at(1) ) * ( X2->at(1) - X1->at(1) ) + ( X2->at(2) - X1->at(2) ) * ( X2->at(2) - X1->at(2) ) + ( X2->at(3) - X1->at(3) ) * ( X2->at(3) - X1->at(3) ) ); - double Ur1 = ( X2->at(1) - X1->at(1) ) / L; - double Ur2 = ( X2->at(2) - X1->at(2) ) / L; - double Ur3 = ( X2->at(3) - X1->at(3) ) / L; + double L = distance(X2, X1); + double Ur1 = ( X2.at(1) - X1.at(1) ) / L; + double Ur2 = ( X2.at(2) - X1.at(2) ) / L; + double Ur3 = ( X2.at(3) - X1.at(3) ) / L; // cross product (needed for Plucker. coords) - double Vr1 = Ur2 * X1->at(3) - Ur3 *X1->at(2); - double Vr2 = Ur3 * X1->at(1) - Ur1 *X1->at(3); - double Vr3 = Ur1 * X1->at(2) - Ur2 *X1->at(1); + double Vr1 = Ur2 * X1.at(3) - Ur3 *X1.at(2); + double Vr2 = Ur3 * X1.at(1) - Ur1 *X1.at(3); + double Vr3 = Ur1 * X1.at(2) - Ur2 *X1.at(1); // Plucker. coords of line {U,UxX1} // Pr = [Ur, Vr]; // vectors of edges: (order is important!) FloatArray U1(3), U2(3), U3(3); for ( int i = 1; i <= 3; i++ ) { - U1.at(i) = B->at(i) - A->at(i); - U2.at(i) = C->at(i) - B->at(i); - U3.at(i) = A->at(i) - C->at(i); + U1.at(i) = B.at(i) - A.at(i); + U2.at(i) = C.at(i) - B.at(i); + U3.at(i) = A.at(i) - C.at(i); } // cross product (needed for Plucker. coords) FloatArray V1(3), V2(3), V3(3); // cross(U1,A); - V1.at(1) = U1.at(2) * A->at(3) - U1.at(3) * A->at(2); - V1.at(2) = U1.at(3) * A->at(1) - U1.at(1) * A->at(3); - V1.at(3) = U1.at(1) * A->at(2) - U1.at(2) * A->at(1); + V1.at(1) = U1.at(2) * A.at(3) - U1.at(3) * A.at(2); + V1.at(2) = U1.at(3) * A.at(1) - U1.at(1) * A.at(3); + V1.at(3) = U1.at(1) * A.at(2) - U1.at(2) * A.at(1); // cross(U2,B); - V2.at(1) = U2.at(2) * B->at(3) - U2.at(3) * B->at(2); - V2.at(2) = U2.at(3) * B->at(1) - U2.at(1) * B->at(3); - V2.at(3) = U2.at(1) * B->at(2) - U2.at(2) * B->at(1); + V2.at(1) = U2.at(2) * B.at(3) - U2.at(3) * B.at(2); + V2.at(2) = U2.at(3) * B.at(1) - U2.at(1) * B.at(3); + V2.at(3) = U2.at(1) * B.at(2) - U2.at(2) * B.at(1); // cross(U3,C); - V3.at(1) = U3.at(2) * C->at(3) - U3.at(3) * C->at(2); - V3.at(2) = U3.at(3) * C->at(1) - U3.at(1) * C->at(3); - V3.at(3) = U3.at(1) * C->at(2) - U3.at(2) * C->at(1); + V3.at(1) = U3.at(2) * C.at(3) - U3.at(3) * C.at(2); + V3.at(2) = U3.at(3) * C.at(1) - U3.at(1) * C.at(3); + V3.at(3) = U3.at(1) * C.at(2) - U3.at(2) * C.at(1); // permuted inner products Pr(.)P1 = Ur.V1 + U1.Vr @@ -1504,22 +1380,22 @@ Quasicontinuum :: intersectionTestSegmentTrianglePlucker3D(FloatArray &intersec double u3 = S3 / S; // to cartesian // Px = [x y z] = u1*C + u2*A +u3*B; // multiple by opposite vertex - double x = u1 * C->at(1) + u2 *A->at(1) + u3 *B->at(1); - double y = u1 * C->at(2) + u2 *A->at(2) + u3 *B->at(2); - double z = u1 * C->at(3) + u2 *A->at(3) + u3 *B->at(3); + double x = u1 * C.at(1) + u2 *A.at(1) + u3 *B.at(1); + double y = u1 * C.at(2) + u2 *A.at(2) + u3 *B.at(2); + double z = u1 * C.at(3) + u2 *A.at(3) + u3 *B.at(3); // is interection on line segment // intersection parameter double t; // Pk = [x y z] = X1 + t*(X2-X1) - if ( ( X2->at(1) - X1->at(1) ) != 0 ) { // x-coord will be used - t = ( x - X1->at(1) ) / ( X2->at(1) - X1->at(1) ); // parameter on segment + if ( ( X2.at(1) - X1.at(1) ) != 0 ) { // x-coord will be used + t = ( x - X1.at(1) ) / ( X2.at(1) - X1.at(1) ); // parameter on segment } else { - if ( ( X2->at(2) - X1->at(2) ) != 0 ) { // y-coord will be used - t = ( y - X1->at(2) ) / ( X2->at(2) - X1->at(2) ); // parameter on segment + if ( ( X2.at(2) - X1.at(2) ) != 0 ) { // y-coord will be used + t = ( y - X1.at(2) ) / ( X2.at(2) - X1.at(2) ); // parameter on segment } else { // z-coord will be used - t = ( z - X1->at(3) ) / ( X2->at(3) - X1->at(3) ); // parameter on segment + t = ( z - X1.at(3) ) / ( X2.at(3) - X1.at(3) ); // parameter on segment } } @@ -1542,109 +1418,78 @@ Quasicontinuum :: intersectionTestSegmentTrianglePlucker3D(FloatArray &intersec } - - int -Quasicontinuum :: intersectionTestSegmentTetrahedra3D(FloatArray &intersectCoordsX, FloatArray &intersectCoordsY, FloatArray &intersectCoordsZ, FloatArray *A, FloatArray *B, FloatArray *C, FloatArray *D, FloatArray *X1, FloatArray *X2) { +Quasicontinuum :: intersectionTestSegmentTetrahedra3D(std::vector &intersectCoords, + const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &D, const FloatArray &X1, const FloatArray &X2) +{ // test if line (X2-X1) intersects tetrahedra ABCD (for 3D!) - - bool test; - int numberOfIntersections = 0; - intersectCoordsX.clear(); - intersectCoordsY.clear(); - intersectCoordsZ.clear(); - FloatArray intersectCoords; + intersectCoords.clear(); + FloatArray intersectCoord; // face 1 - test = intersectionTestSegmentTrianglePlucker3D(intersectCoords, A, B, C, X1, X2); - if ( test ) { - numberOfIntersections += 1; - intersectCoordsX.push_back( intersectCoords.at(1) ); - intersectCoordsY.push_back( intersectCoords.at(2) ); - intersectCoordsZ.push_back( intersectCoords.at(3) ); + if ( intersectionTestSegmentTrianglePlucker3D(intersectCoord, A, B, C, X1, X2) ) { + intersectCoords.push_back(intersectCoord); } // face 2 - test = intersectionTestSegmentTrianglePlucker3D(intersectCoords, A, D, B, X1, X2); - if ( test ) { - numberOfIntersections += 1; - intersectCoordsX.push_back( intersectCoords.at(1) ); - intersectCoordsY.push_back( intersectCoords.at(2) ); - intersectCoordsZ.push_back( intersectCoords.at(3) ); + if ( intersectionTestSegmentTrianglePlucker3D(intersectCoord, A, D, B, X1, X2) ) { + intersectCoords.push_back(intersectCoord); } // face 3 - test = intersectionTestSegmentTrianglePlucker3D(intersectCoords, B, D, C, X1, X2); - if ( test ) { - numberOfIntersections += 1; - intersectCoordsX.push_back( intersectCoords.at(1) ); - intersectCoordsY.push_back( intersectCoords.at(2) ); - intersectCoordsZ.push_back( intersectCoords.at(3) ); + if ( intersectionTestSegmentTrianglePlucker3D(intersectCoord, B, D, C, X1, X2) ) { + intersectCoords.push_back(intersectCoord); } // face 4 - test = intersectionTestSegmentTrianglePlucker3D(intersectCoords, A, C, D, X1, X2); - if ( test ) { - numberOfIntersections += 1; - intersectCoordsX.push_back( intersectCoords.at(1) ); - intersectCoordsY.push_back( intersectCoords.at(2) ); - intersectCoordsZ.push_back( intersectCoords.at(3) ); + if ( intersectionTestSegmentTrianglePlucker3D(intersectCoord, A, C, D, X1, X2) ) { + intersectCoords.push_back(intersectCoord); } - return numberOfIntersections; + return (int)intersectCoords.size(); } - int -Quasicontinuum :: intersectionTestSegmentTriangle2D(FloatArray &intersectCoordsX, FloatArray &intersectCoordsY, FloatArray *A, FloatArray *B, FloatArray *C, FloatArray *U1, FloatArray *U2) { +Quasicontinuum :: intersectionTestSegmentTriangle2D(std::vector &intersectCoords, + const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &U1, const FloatArray &U2) +{ // test if line (X2-X1) intersects tringle ABC (for 2D!) - bool test; - int numberOfIntersections = 0; - intersectCoordsX.clear(); - intersectCoordsY.clear(); - FloatArray intersectCoords; + intersectCoords.clear(); + FloatArray intersectCoord; // edge 1 - test = intersectionTestSegmentSegment2D(intersectCoords, A, B, U1, U2); - if ( test ) { - numberOfIntersections += 1; - intersectCoordsX.push_back( intersectCoords.at(1) ); - intersectCoordsY.push_back( intersectCoords.at(2) ); + if ( intersectionTestSegmentSegment2D(intersectCoord, A, B, U1, U2) ) { + intersectCoords.push_back(intersectCoord); } // edge 2 - test = intersectionTestSegmentSegment2D(intersectCoords, B, C, U1, U2); - if ( test ) { - numberOfIntersections += 1; - intersectCoordsX.push_back( intersectCoords.at(1) ); - intersectCoordsY.push_back( intersectCoords.at(2) ); + if ( intersectionTestSegmentSegment2D(intersectCoord, B, C, U1, U2) ) { + intersectCoords.push_back(intersectCoord); } // edge 3 - test = intersectionTestSegmentSegment2D(intersectCoords, A, C, U1, U2); - if ( test ) { - numberOfIntersections += 1; - intersectCoordsX.push_back( intersectCoords.at(1) ); - intersectCoordsY.push_back( intersectCoords.at(2) ); + if ( intersectionTestSegmentSegment2D(intersectCoord, A, C, U1, U2) ) { + intersectCoords.push_back(intersectCoord); } - return numberOfIntersections; + return (int)intersectCoords.size(); } bool -Quasicontinuum :: intersectionTestSegmentSegment2D(FloatArray &intersectCoords, FloatArray *A1, FloatArray *A2, FloatArray *B1, FloatArray *B2) { +Quasicontinuum :: intersectionTestSegmentSegment2D(FloatArray &intersectCoords, const FloatArray &A1, const FloatArray &A2, const FloatArray &B1, const FloatArray &B2) +{ //intersectionTest of 2 segments A1-A2 B1-B2 (2D only) - double a1x = A1->at(1); - double a1y = A1->at(2); - double a2x = A2->at(1); - double a2y = A2->at(2); - double b1x = B1->at(1); - double b1y = B1->at(2); - double b2x = B2->at(1); - double b2y = B2->at(2); + double a1x = A1.at(1); + double a1y = A1.at(2); + double a2x = A2.at(1); + double a2y = A2.at(2); + double b1x = B1.at(1); + double b1y = B1.at(2); + double b2x = B2.at(1); + double b2y = B2.at(2); // y=f*x+g double f1 = std :: numeric_limits< float > :: infinity(); @@ -1713,9 +1558,7 @@ Quasicontinuum :: intersectionTestSegmentSegment2D(FloatArray &intersectCoords, // test double EPS = 1e-10; if ( ( x1 <= x + EPS ) && ( x <= x2 + EPS ) && ( x3 <= x + EPS ) && ( x <= x4 + EPS ) && ( y1 <= y + EPS ) && ( y <= y2 + EPS ) && ( y3 <= y + EPS ) && ( y <= y4 + EPS ) ) { - intersectCoords.resize(2); - intersectCoords.at(1) = x; - intersectCoords.at(2) = y; + intersectCoords = {x, y}; return true; } else { intersectCoords.clear(); @@ -1724,35 +1567,24 @@ Quasicontinuum :: intersectionTestSegmentSegment2D(FloatArray &intersectCoords, } - - void -Quasicontinuum :: transformStiffnessTensorToMatrix(FloatMatrix *matrix, FloatMatrix *tensor) { +Quasicontinuum :: transformStiffnessTensorToMatrix(FloatMatrix &matrix, const FloatMatrix &tensor) +{ // transform stiff. tensor 9x9 to stiff. matrix 6x6 (universal for 3D and 2D) - IntArray indicesI, indicesJ, indicesK, indicesL; - indicesI = { - 1, 2, 3, 2, 1, 1 - }; - indicesJ = { - 1, 2, 3, 3, 3, 2 - }; - indicesK = { - 1, 2, 3, 2, 1, 1 - }; - indicesL = { - 1, 2, 3, 3, 3, 2 - }; - int ii, jj, i, j, k, l; - - for ( ii = 1; ii <= 6; ii++ ) { - for ( jj = 1; jj <= 6; jj++ ) { - i = indicesI.at(ii); - j = indicesJ.at(ii); - - k = indicesK.at(jj); - l = indicesL.at(jj); - - matrix->at(ii, jj) = tensor->at(3 * ( i - 1 ) + k, 3 * ( j - 1 ) + l); + IntArray indicesI = {1, 2, 3, 2, 1, 1}; + IntArray indicesJ = {1, 2, 3, 3, 3, 2}; + IntArray indicesK = {1, 2, 3, 2, 1, 1}; + IntArray indicesL = {1, 2, 3, 3, 3, 2}; + + for ( int ii = 1; ii <= 6; ii++ ) { + for ( int jj = 1; jj <= 6; jj++ ) { + int i = indicesI.at(ii); + int j = indicesJ.at(ii); + + int k = indicesK.at(jj); + int l = indicesL.at(jj); + + matrix.at(ii, jj) = tensor.at(3 * ( i - 1 ) + k, 3 * ( j - 1 ) + l); } } } diff --git a/src/sm/Quasicontinuum/quasicontinuum.h b/src/sm/Quasicontinuum/quasicontinuum.h old mode 100755 new mode 100644 index ebe0c71c6..b07dccb30 --- a/src/sm/Quasicontinuum/quasicontinuum.h +++ b/src/sm/Quasicontinuum/quasicontinuum.h @@ -40,43 +40,39 @@ #include "node.h" #include "qcnode.h" - namespace oofem { /** * General simplification for Quasicontinuum simulation. - * */ class Quasicontinuum - { protected: std::vector interpolationMeshNodes; IntArray interpolationElementNumbers; IntArray interpolationElementIndices; - std::vector connectivityTable; + std::vector connectivityTable; int nDimensions; IntArray elemList; IntArray nodeList; - public: Quasicontinuum(); virtual ~Quasicontinuum(); void setNoDimensions(Domain *d); - void setupInterpolationMesh(Domain *d, int generateInterpolationElements, int interpolationElementsMaterialNumber, std::vector *newMeshNodes); + void setupInterpolationMesh(Domain *d, int generateInterpolationElements, int interpolationElementsMaterialNumber, std::vector &newMeshNodes); void createInterpolationElements(Domain *d); void addCrosssectionToInterpolationElements(Domain *d); void applyApproach1(Domain *d); void applyApproach2(Domain *d, int homMtrxType, double volumeOfInterpolationMesh); void applyApproach3(Domain *d, int homMtrxType); - - void homogenizationOfStiffMatrix(double &homogenizedE, double &homogenizedNu, FloatMatrix *Diso ); - void createGlobalStiffnesMatrix(FloatMatrix *Diso, double &S0, Domain *d, int homMtrxType, double volumeOfInterpolationMesh); + + void homogenizationOfStiffMatrix(double &homogenizedE, double &homogenizedNu, const FloatMatrix &Diso ); + void createGlobalStiffnesMatrix(FloatMatrix &Diso, double &S0, Domain *d, int homMtrxType, double volumeOfInterpolationMesh); void computeStiffnessTensorOf1Link(FloatMatrix &D1, double &S0, Element *e, Domain *d); - bool stiffnessAssignment( std::vector &individualStiffnessTensors, FloatArray &individialS0, Domain *d, Element *e, qcNode *qn1, qcNode *qn2 ); + bool stiffnessAssignment( std::vector &individualStiffnessTensors, FloatArray &individialS0, Domain *d, Element *e, qcNode *qn1, qcNode *qn2 ); void computeIntersectionsOfLinkWithInterpElements( IntArray &intersected, FloatArray &lengths, Domain *d, Element *e, qcNode *qn1, qcNode *qn2); bool computeIntersectionsOfLinkWith2DTringleElements( IntArray &intersected, FloatArray &lengths, Domain *d, Element *e, qcNode *qn1, qcNode *qn2); @@ -84,16 +80,15 @@ class Quasicontinuum void initializeConnectivityTableForInterpolationElements( Domain *d ); - bool intersectionTestSegmentTrianglePlucker3D (FloatArray &intersectCoords, FloatArray *A, FloatArray *B, FloatArray *C, FloatArray *X1, FloatArray *X2 ); + bool intersectionTestSegmentTrianglePlucker3D(FloatArray &intersectCoords, const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &X1, const FloatArray &X2 ); - int intersectionTestSegmentTetrahedra3D (FloatArray &intersectCoordsX, FloatArray &intersectCoordsY, FloatArray &intersectCoordsZ, FloatArray *A, FloatArray *B, FloatArray *C, FloatArray *D, FloatArray *X1, FloatArray *X2 ); + int intersectionTestSegmentTetrahedra3D(std::vector &intersectCoords, const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &D, const FloatArray &X1, const FloatArray &X2 ); - bool intersectionTestSegmentSegment2D (FloatArray &intersectCoords, FloatArray *A1, FloatArray *A2, FloatArray *B1, FloatArray *B2 ); + bool intersectionTestSegmentSegment2D(FloatArray &intersectCoords, const FloatArray &A1, const FloatArray &A2, const FloatArray &B1, const FloatArray &B2 ); - int intersectionTestSegmentTriangle2D (FloatArray &intersectCoordsX, FloatArray &intersectCoordsY, FloatArray *A, FloatArray *B, FloatArray *C, FloatArray *U1, FloatArray *U2 ); + int intersectionTestSegmentTriangle2D(std::vector &intersectCoords, const FloatArray &A, const FloatArray &B, const FloatArray &C, const FloatArray &U1, const FloatArray &U2 ); - void transformStiffnessTensorToMatrix (FloatMatrix *matrix, FloatMatrix *tensor ); - + void transformStiffnessTensorToMatrix(FloatMatrix &matrix, const FloatMatrix &tensor ); }; } // end namespace oofem #endif // quasicontinuum_h diff --git a/src/sm/Quasicontinuum/quasicontinuumnumberingscheme.C b/src/sm/Quasicontinuum/quasicontinuumnumberingscheme.C index e51a0e580..33e00f9b1 100644 --- a/src/sm/Quasicontinuum/quasicontinuumnumberingscheme.C +++ b/src/sm/Quasicontinuum/quasicontinuumnumberingscheme.C @@ -43,11 +43,6 @@ QuasicontinuumNumberingscheme :: QuasicontinuumNumberingscheme() : , isInitialized(false) { } -QuasicontinuumNumberingscheme :: ~QuasicontinuumNumberingscheme() -{ - delete equationMap; -} - void QuasicontinuumNumberingscheme :: init(Domain *domain, std :: vector< bool >activatedNodeList, TimeStep *tStep) { @@ -67,58 +62,53 @@ QuasicontinuumNumberingscheme :: init(Domain *domain, std :: vector< bool >activ */ this->selectedNodes.resize( activatedNodeList.size() ); selectedNodes.zero(); - for ( int i = 1; i <= ( int ) activatedNodeList.size(); i++ ) { - if ( activatedNodeList [ i - 1 ] ) { - selectedNodes.at(i) = 1; + for ( int i = 0; i < ( int ) activatedNodeList.size(); i++ ) { + if ( activatedNodeList [ i ] ) { + selectedNodes[i] = 1; } } //int nnode = domain->giveNumberOfDofManagers(); //int nnode = 0; - DofManager *idofman; - // this->dofEquationNumbers.resize(nnode); - equationMap = new std :: map< int, std :: map< int, int > >(); - + equationMap.clear(); for ( int inode = 1; inode <= selectedNodes.giveSize(); inode++ ) { if ( selectedNodes.at(inode) == 1 ) { - std :: map< int, int > *dof2EquationMap = new std :: map< int, int >(); - idofman = domain->giveDofManager(inode); + std :: map< int, int > dof2EquationMap; + auto idofman = domain->giveDofManager(inode); IntArray dofIDArray; idofman->giveCompleteMasterDofIDArray(dofIDArray); if ( !idofman->hasAnySlaveDofs() ) { - for ( int k = 1; k <= dofIDArray.giveSize(); k++ ) { - if ( idofman->giveDofWithID( dofIDArray.at(k) )->hasBc(tStep) ) { - ( * dof2EquationMap ) [ dofIDArray.at(k) ] = --pres_neq; + for ( auto &dofid : dofIDArray ) { + if ( idofman->giveDofWithID( dofid )->hasBc(tStep) ) { + dof2EquationMap [ dofid ] = --pres_neq; } else { - ( * dof2EquationMap ) [ dofIDArray.at(k) ] = ++neq; + dof2EquationMap [ dofid ] = ++neq; } } } else { - /* - * IntArray masterDofIDArray, masterDofMans; - * //idofman->giveMasterDofIDArray({D_u, D_v},masterDofIDArray); - * idofman->giveMasterDofMans(masterDofMans); - * DofManager *mdofman; - * for (int m = 1; m <= masterDofMans.giveSize(); m++ ) { - * mdofman = domain->giveDofManager(masterDofMans.at(m)); - * mdofman->giveCompleteMasterDofIDArray(dofIDArray); - * for (int k = 1; k <= dofIDArray.giveSize(); k++) { - * if(mdofman->giveDofWithID(dofIDArray.at(k))->hasBc(tStep)) { - * ( *dof2EquationMap ) [ dofIDArray.at(k) ] = --pres_neq; - * } else { - * ( *dof2EquationMap ) [ dofIDArray.at(k) ] = ++neq; - * } - * } - * } - */ +#if 0 + IntArray masterDofIDArray, masterDofMans; + //idofman->giveMasterDofIDArray({D_u, D_v},masterDofIDArray); + idofman->giveMasterDofMans(masterDofMans); + for (int m = 1; m <= masterDofMans.giveSize(); m++ ) { + auto mdofman = domain->giveDofManager(masterDofMans.at(m)); + mdofman->giveCompleteMasterDofIDArray(dofIDArray); + for ( auto &dofid : dofIDArray ) { + if(mdofman->giveDofWithID(dofid)->hasBc(tStep)) { + dof2EquationMap [ dofid ] = --pres_neq; + } else { + dof2EquationMap [ dofid ] = ++neq; + } + } + } +#endif } - ( * this->equationMap ) [ inode ] = * dof2EquationMap; - delete dof2EquationMap; + this->equationMap.insert( {inode, std::move(dof2EquationMap)} ); } } } @@ -133,13 +123,10 @@ QuasicontinuumNumberingscheme :: reset() int QuasicontinuumNumberingscheme :: giveDofEquationNumber(Dof *dof) const { - //std::map map = (equationMap->find(dof->giveDofManNumber())->second)->find((int)dof->giveDofID)->second; - - int dofEqNum = 0; if ( selectedNodes.at( dof->giveDofManNumber() ) == 1 ) { - dofEqNum = ( equationMap->find( dof->giveDofManNumber() )->second ).find( dof->giveDofID() )->second; + dofEqNum = ( equationMap.find( dof->giveDofManNumber() )->second ).find( dof->giveDofID() )->second; } else { dofEqNum = 0; } diff --git a/src/sm/Quasicontinuum/quasicontinuumnumberingscheme.h b/src/sm/Quasicontinuum/quasicontinuumnumberingscheme.h index ccafa054b..53640d6c9 100644 --- a/src/sm/Quasicontinuum/quasicontinuumnumberingscheme.h +++ b/src/sm/Quasicontinuum/quasicontinuumnumberingscheme.h @@ -61,22 +61,22 @@ class QuasicontinuumNumberingscheme : public UnknownNumberingScheme /// Flag controlling wether the numbering has been initialized or not bool isInitialized; /// map form dofid to equation number - std::map> *equationMap; + std::map> equationMap; public: /// Constructor QuasicontinuumNumberingscheme(); /// Destructor - virtual ~QuasicontinuumNumberingscheme(); + virtual ~QuasicontinuumNumberingscheme() {} /** * Initializes the receiver */ - virtual void init(Domain *domain, std::vector activatedNodeList, TimeStep *tStep); - virtual bool isDefault() const { return true; } - virtual int giveDofEquationNumber(Dof *dof) const; - virtual int giveRequiredNumberOfDomainEquation() const; + void init(Domain *domain, std::vector activatedNodeList, TimeStep *tStep); + bool isDefault() const override { return true; } + int giveDofEquationNumber(Dof *dof) const override; + int giveRequiredNumberOfDomainEquation() const override; /// Returns total number of equations virtual int giveTotalNumberOfEquations() const; diff --git a/src/sm/Quasicontinuum/quasicontinuumvtkxmlexportmodule.C b/src/sm/Quasicontinuum/quasicontinuumvtkxmlexportmodule.C index 1fb97ee79..44bddff61 100644 --- a/src/sm/Quasicontinuum/quasicontinuumvtkxmlexportmodule.C +++ b/src/sm/Quasicontinuum/quasicontinuumvtkxmlexportmodule.C @@ -61,43 +61,39 @@ QuasicontinuumVTKXMLExportModule :: ~QuasicontinuumVTKXMLExportModule() {} -IRResultType -QuasicontinuumVTKXMLExportModule :: initializeFrom(InputRecord *ir) +void +QuasicontinuumVTKXMLExportModule :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + VTKXMLExportModule :: initializeFrom(ir); deactivatedElementsExportFlag = 0; IR_GIVE_OPTIONAL_FIELD(ir, deactivatedElementsExportFlag, _IFT_QuasicontinuumVTKXMLExportModule_ExportDeactivatedElements); // Macro - - return VTKXMLExportModule :: initializeFrom(ir); } void -QuasicontinuumVTKXMLExportModule :: setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, int region) +QuasicontinuumVTKXMLExportModule :: setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, Set & region) { // Stores all neccessary data (of a region) in a VTKPiece so it can be exported later. Domain *d = emodel->giveDomain(1); Element *elem; - FloatArray *coords; - - this->giveSmoother(); // make sure smoother is created - - // output nodes Region By Region - int numNodes, numRegionEl; - IntArray mapG2L, mapL2G; // Assemble local->global and global->local region map and get number of // single cells to process, the composite cells exported individually. - this->initRegionNodeNumbering(mapG2L, mapL2G, numNodes, numRegionEl, d, tStep, region); + this->initRegionNodeNumbering(vtkPiece, d, tStep, region); + const IntArray& mapG2L = vtkPiece.getMapG2L(); + const IntArray& mapL2G = vtkPiece.getMapL2G(); + const int numNodes = vtkPiece.giveNumberOfNodes(); + const int numRegionEl = vtkPiece.giveNumberOfCells(); + if ( numNodes > 0 && numRegionEl > 0 ) { // Export nodes as vtk vertices vtkPiece.setNumberOfNodes(numNodes); for ( int inode = 1; inode <= numNodes; inode++ ) { - coords = d->giveNode( mapL2G.at(inode) )->giveCoordinates(); - vtkPiece.setNodeCoords(inode, * coords); + const auto &coords = d->giveNode( mapL2G.at(inode) )->giveCoordinates(); + vtkPiece.setNodeCoords(inode, coords); } @@ -109,7 +105,7 @@ QuasicontinuumVTKXMLExportModule :: setupVTKPiece(VTKPiece &vtkPiece, TimeStep * int offset = 0; int cellNum = 0; - IntArray elems = this->giveRegionSet(region)->giveElementList(); + IntArray elems = region.giveElementList(); for ( int ei = 1; ei <= elems.giveSize(); ei++ ) { int elNum = elems.at(ei); elem = d->giveElement(elNum); @@ -157,13 +153,14 @@ QuasicontinuumVTKXMLExportModule :: setupVTKPiece(VTKPiece &vtkPiece, TimeStep * vtkPiece.setOffset(cellNum, offset); } + NodalRecoveryModel *smoother = giveSmoother(); + NodalRecoveryModel *primVarSmoother = givePrimVarSmoother(); // Export primary, internal and XFEM variables as nodal quantities - this->exportPrimaryVars(vtkPiece, mapG2L, mapL2G, region, tStep); - this->exportIntVars(vtkPiece, mapG2L, mapL2G, region, tStep); - this->exportExternalForces(vtkPiece, mapG2L, mapL2G, region, tStep); - - this->exportCellVars(vtkPiece, elems, tStep); + this->exportPrimaryVars(this->defaultVTKPiece, region, primaryVarsToExport, *primVarSmoother, tStep); + this->exportIntVars(this->defaultVTKPiece, region, internalVarsToExport, *smoother, tStep); + this->exportExternalForces(this->defaultVTKPiece, region, externalForcesToExport, tStep); + this->exportCellVars(this->defaultVTKPiece, region, cellVarsToExport, tStep); } // end of default piece for simple geometry elements } @@ -172,11 +169,8 @@ QuasicontinuumVTKXMLExportModule :: setupVTKPiece(VTKPiece &vtkPiece, TimeStep * int -QuasicontinuumVTKXMLExportModule :: initRegionNodeNumbering(IntArray ®ionG2LNodalNumbers, - IntArray ®ionL2GNodalNumbers, - int ®ionDofMans, - int ®ionSingleCells, - Domain *domain, TimeStep *tStep, int reg) +QuasicontinuumVTKXMLExportModule :: initRegionNodeNumbering(VTKPiece& piece, + Domain *domain, TimeStep *tStep, Set& region) { // regionG2LNodalNumbers is array with mapping from global numbering to local region numbering. // The i-th value contains the corresponding local region number (or zero, if global numbar is not in region). @@ -191,12 +185,15 @@ QuasicontinuumVTKXMLExportModule :: initRegionNodeNumbering(IntArray ®ionG2LN int currOffset = 1; Element *element; + IntArray ®ionG2LNodalNumbers = piece.getMapG2L(); + IntArray ®ionL2GNodalNumbers = piece.getMapL2G(); + regionG2LNodalNumbers.resize(nnodes); regionG2LNodalNumbers.zero(); - regionDofMans = 0; - regionSingleCells = 0; + int regionDofMans = 0; + int regionSingleCells = 0; - IntArray elements = this->giveRegionSet(reg)->giveElementList(); + const IntArray& elements = region.giveElementList(); for ( int ie = 1; ie <= elements.giveSize(); ie++ ) { int ielem = elements.at(ie); element = domain->giveElement(ielem); @@ -242,6 +239,9 @@ QuasicontinuumVTKXMLExportModule :: initRegionNodeNumbering(IntArray ®ionG2LN } } + piece.setNumberOfCells(regionSingleCells); + piece.setNumberOfNodes(regionDofMans); + regionL2GNodalNumbers.resize(regionDofMans); for ( int i = 1; i <= nnodes; i++ ) { diff --git a/src/sm/Quasicontinuum/quasicontinuumvtkxmlexportmodule.h b/src/sm/Quasicontinuum/quasicontinuumvtkxmlexportmodule.h index e6ddb63d3..75ffe4452 100644 --- a/src/sm/Quasicontinuum/quasicontinuumvtkxmlexportmodule.h +++ b/src/sm/Quasicontinuum/quasicontinuumvtkxmlexportmodule.h @@ -71,20 +71,20 @@ class OOFEM_EXPORT QuasicontinuumVTKXMLExportModule : public VTKXMLExportModule IntArray primaryVarsToExport; /// List of cell data to export. IntArray cellVarsToExport; - + public: /// Constructor. Creates empty Output Manager. By default all components are selected. QuasicontinuumVTKXMLExportModule(int n, EngngModel * e); /// Destructor virtual ~QuasicontinuumVTKXMLExportModule(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - protected: +protected: // // Exports single internal variable by smoothing. // - virtual void setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, int region); + void setupVTKPiece(VTKPiece &vtkPiece, TimeStep *tStep, Set& region) override; /** * Assembles the region node map. Also computes the total number of nodes in region. * The region are numbered starting from offset+1. @@ -93,10 +93,8 @@ class OOFEM_EXPORT QuasicontinuumVTKXMLExportModule : public VTKXMLExportModule * If mode == 1 then regionNodalNumbers is array with mapping from local to global numbering. * The i-th value contains the corresponding global node number. */ - virtual int initRegionNodeNumbering(IntArray &mapG2L, IntArray &mapL2G, - int ®ionDofMans, - int &totalcells, - Domain *domain, TimeStep *tStep, int reg); + int initRegionNodeNumbering(VTKPiece& p, + Domain *domain, TimeStep *tStep, Set& region) override; }; } // end namespace oofem #endif // quasicontinuumvtkxmlexportmodule_h diff --git a/src/sm/export/crackexportmodule.C b/src/sm/export/crackexportmodule.C index 18f7f00e1..1279ae1d7 100644 --- a/src/sm/export/crackexportmodule.C +++ b/src/sm/export/crackexportmodule.C @@ -40,7 +40,7 @@ #include "timestep.h" #include "engngm.h" #include "classfactory.h" -#include "Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "crosssection.h" #include "floatarray.h" @@ -63,18 +63,14 @@ CrackExportModule :: ~CrackExportModule() } -IRResultType -CrackExportModule :: initializeFrom(InputRecord *ir) +void +CrackExportModule :: initializeFrom(InputRecord &ir) { - const char *__proc = "initializeFrom"; // Required by IR_GIVE_FIELD macro - IRResultType result; // Required by IR_GIVE_FIELD macro - + ExportModule :: initializeFrom(ir); IR_GIVE_FIELD(ir, crossSections, _IFT_CrackExportModule_cs); this->threshold = 0.; IR_GIVE_OPTIONAL_FIELD(ir, threshold, _IFT_CrackExportModule_threshold); - - return ExportModule :: initializeFrom(ir); } diff --git a/src/sm/export/crackexportmodule.h b/src/sm/export/crackexportmodule.h index 6b9dcfeb1..b2d2a1b59 100644 --- a/src/sm/export/crackexportmodule.h +++ b/src/sm/export/crackexportmodule.h @@ -54,8 +54,8 @@ namespace oofem { class CrackExportModule : public ExportModule { protected: - IntArray crossSections; - double threshold; + IntArray crossSections; + double threshold; public: /// Constructor. @@ -63,12 +63,12 @@ class CrackExportModule : public ExportModule /// Destructor virtual ~CrackExportModule(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void doOutput(TimeStep *tStep, bool forcedOutput); - virtual void initialize(); - virtual void terminate(); - virtual const char *giveClassName() const { return "CrackExportModule"; } - virtual const char *giveInputRecordName() const { return _IFT_CrackExportModule_Name; } + void initializeFrom(InputRecord &ir) override; + void doOutput(TimeStep *tStep, bool forcedOutput) override; + void initialize() override; + void terminate() override; + const char *giveClassName() const override { return "CrackExportModule"; } + const char *giveInputRecordName() const { return _IFT_CrackExportModule_Name; } static void writeToOutputFile(const std :: string &iName, const std :: vector< FloatArray > &iPoints); }; diff --git a/src/sm/export/dmexportmodule.C b/src/sm/export/dmexportmodule.C index 9b40b5d76..3598351f7 100644 --- a/src/sm/export/dmexportmodule.C +++ b/src/sm/export/dmexportmodule.C @@ -40,7 +40,7 @@ #include "classfactory.h" #include "domain.h" -#include "../sm/EngineeringModels/structengngmodel.h" // JB +#include "sm/EngineeringModels/structengngmodel.h" // JB namespace oofem { REGISTER_ExportModule(DofManExportModule) @@ -55,15 +55,13 @@ DofManExportModule :: ~DofManExportModule() { } -IRResultType -DofManExportModule :: initializeFrom(InputRecord *ir) +void +DofManExportModule :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + ExportModule :: initializeFrom(ir); // Read in dofMan's to export - defaults to all IR_GIVE_OPTIONAL_FIELD(ir, this->dofManList, _IFT_DofManExportModule_dmlist); - - return ExportModule :: initializeFrom(ir); } diff --git a/src/sm/export/dmexportmodule.h b/src/sm/export/dmexportmodule.h index ea59c6cd8..ed343fe32 100644 --- a/src/sm/export/dmexportmodule.h +++ b/src/sm/export/dmexportmodule.h @@ -63,10 +63,10 @@ class DofManExportModule : public ExportModule /// Destructor virtual ~DofManExportModule(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void doOutput(TimeStep *tStep, bool forcedOutput = false); - virtual const char *giveClassName() const { return "DofManExportModuleClass"; } - virtual const char *giveInputRecordName() const { return _IFT_DofManExportModule_Name; } + void initializeFrom(InputRecord &ir) override; + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; + const char *giveClassName() const override { return "DofManExportModuleClass"; } + const char *giveInputRecordName() const { return _IFT_DofManExportModule_Name; } protected: FILE *giveOutputStream(TimeStep *tStep); diff --git a/src/sm/export/gnuplotexportmodule.C b/src/sm/export/gnuplotexportmodule.C index ef2399c27..ef69721e2 100644 --- a/src/sm/export/gnuplotexportmodule.C +++ b/src/sm/export/gnuplotexportmodule.C @@ -42,13 +42,13 @@ #include "gnuplotexportmodule.h" #include "classfactory.h" #include "valuemodetype.h" -#include "../sm/EngineeringModels/structengngmodel.h" +#include "sm/EngineeringModels/structengngmodel.h" #include "outputmanager.h" #include "dofmanager.h" #include "boundarycondition.h" #include "xfem/enrichmentitem.h" #include "xfem/xfemmanager.h" -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" #include "xfem/XFEMDebugTools.h" #include "prescribedgradient.h" #include "prescribedgradientbcneumann.h" @@ -60,8 +60,8 @@ #include "dofmanager.h" #include "xfem/matforceevaluator.h" #include "function.h" -#include "Elements/Interfaces/structuralinterfaceelement.h" -#include "Materials/structuralfe2material.h" +#include "sm/Elements/Interfaces/structuralinterfaceelement.h" +#include "sm/Materials/structuralfe2material.h" #include @@ -84,22 +84,22 @@ GnuplotExportModule::GnuplotExportModule(int n, EngngModel *e): GnuplotExportModule::~GnuplotExportModule() {} -IRResultType GnuplotExportModule::initializeFrom(InputRecord *ir) +void GnuplotExportModule::initializeFrom(InputRecord &ir) { - mExportReactionForces = ir->hasField(_IFT_GnuplotExportModule_ReactionForces); - mExportBoundaryConditions = ir->hasField(_IFT_GnuplotExportModule_BoundaryConditions); - mExportBoundaryConditionsExtra = ir->hasField(_IFT_GnuplotExportModule_BoundaryConditionsExtra); - mExportMesh = ir->hasField(_IFT_GnuplotExportModule_mesh); - mExportXFEM = ir->hasField(_IFT_GnuplotExportModule_xfem); - mExportCrackLength = ir->hasField(_IFT_GnuplotExportModule_cracklength); - mExportInterfaceEl = ir->hasField(_IFT_GnuplotExportModule_interface_el); + ExportModule::initializeFrom(ir); - ir->giveOptionalField(mMonitorNodeIndex, _IFT_GnuplotExportModule_monitornode); + mExportReactionForces = ir.hasField(_IFT_GnuplotExportModule_ReactionForces); + mExportBoundaryConditions = ir.hasField(_IFT_GnuplotExportModule_BoundaryConditions); + mExportBoundaryConditionsExtra = ir.hasField(_IFT_GnuplotExportModule_BoundaryConditionsExtra); + mExportMesh = ir.hasField(_IFT_GnuplotExportModule_mesh); + mExportXFEM = ir.hasField(_IFT_GnuplotExportModule_xfem); + mExportCrackLength = ir.hasField(_IFT_GnuplotExportModule_cracklength); + mExportInterfaceEl = ir.hasField(_IFT_GnuplotExportModule_interface_el); - ir->giveOptionalField(mMatForceRadii, _IFT_GnuplotExportModule_materialforceradii); -// printf("mMatForceRadii: "); mMatForceRadii.printYourself(); + ir.giveOptionalField(mMonitorNodeIndex, _IFT_GnuplotExportModule_monitornode); - return ExportModule::initializeFrom(ir); + ir.giveOptionalField(mMatForceRadii, _IFT_GnuplotExportModule_materialforceradii); +// printf("mMatForceRadii: "); mMatForceRadii.printYourself(); } void GnuplotExportModule::doOutput(TimeStep *tStep, bool forcedOutput) @@ -771,7 +771,7 @@ void GnuplotExportModule::outputBoundaryCondition(PrescribedGradientBCWeak &iBC, // Boundary points and displacements - IntArray boundaries, bNodes; + IntArray boundaries; iBC.giveBoundaries(boundaries); std::vector< std::vector > bndNodes; @@ -781,13 +781,13 @@ void GnuplotExportModule::outputBoundaryCondition(PrescribedGradientBCWeak &iBC, Element *e = iBC.giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); int boundary = boundaries.at(pos * 2); - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); std::vector bndSegNodes; // Add the start and end nodes of the segment - DofManager *startNode = e->giveDofManager( bNodes[0] ); - FloatArray xS = *(startNode->giveCoordinates()); + DofManager *startNode = e->giveDofManager( bNodes[0] ); + FloatArray xS = startNode->giveCoordinates(); Dof *dSu = startNode->giveDofWithID(D_u); double dU = dSu->giveUnknown(VM_Total, tStep); @@ -799,8 +799,8 @@ void GnuplotExportModule::outputBoundaryCondition(PrescribedGradientBCWeak &iBC, bndSegNodes.push_back(xS); - DofManager *endNode = e->giveDofManager( bNodes[1] ); - FloatArray xE = *(endNode->giveCoordinates()); + DofManager *endNode = e->giveDofManager( bNodes[1] ); + FloatArray xE = endNode->giveCoordinates(); Dof *dEu = endNode->giveDofWithID(D_u); dU = dEu->giveUnknown(VM_Total, tStep); @@ -861,15 +861,14 @@ void GnuplotExportModule::outputMesh(Domain &iDomain) for ( int edgeIndex = 1; edgeIndex <= numEdges; edgeIndex++ ) { std::vector points; - IntArray bNodes; - el->giveInterpolation()->boundaryGiveNodes(bNodes, edgeIndex); + const auto &bNodes = el->giveInterpolation()->boundaryGiveNodes(edgeIndex); int niLoc = bNodes.at(1); - const FloatArray &xS = *(el->giveNode(niLoc)->giveCoordinates() ); + const auto &xS = el->giveNode(niLoc)->giveCoordinates(); points.push_back(xS); int njLoc = bNodes.at( bNodes.giveSize() ); - const FloatArray &xE = *(el->giveNode(njLoc)->giveCoordinates() ); + const auto &xE = el->giveNode(njLoc)->giveCoordinates(); points.push_back(xE); pointArray.push_back(points); diff --git a/src/sm/export/gnuplotexportmodule.h b/src/sm/export/gnuplotexportmodule.h index 7d55970b3..49607c326 100644 --- a/src/sm/export/gnuplotexportmodule.h +++ b/src/sm/export/gnuplotexportmodule.h @@ -89,13 +89,13 @@ class OOFEM_EXPORT GnuplotExportModule : public ExportModule GnuplotExportModule(int n, EngngModel *e); virtual ~GnuplotExportModule(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void doOutput(TimeStep *tStep, bool forcedOutput = false); - virtual void initialize(); - virtual void terminate(); + void initializeFrom(InputRecord &ir) override; + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; + void initialize() override; + void terminate() override; - virtual const char *giveClassName() const { return "GnuplotExportModule"; } - virtual const char *giveInputRecordName() const { return _IFT_GnuplotExportModule_Name; } + const char *giveClassName() const override { return "GnuplotExportModule"; } + const char *giveInputRecordName() const { return _IFT_GnuplotExportModule_Name; } /** * XFEM output diff --git a/src/sm/export/poiexportmodule.C b/src/sm/export/poiexportmodule.C index 64b9c3fdc..ece685523 100644 --- a/src/sm/export/poiexportmodule.C +++ b/src/sm/export/poiexportmodule.C @@ -62,10 +62,11 @@ POIExportModule :: ~POIExportModule() } -IRResultType -POIExportModule :: initializeFrom(InputRecord *ir) +void +POIExportModule :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + ExportModule :: initializeFrom(ir); + int val; IR_GIVE_OPTIONAL_FIELD(ir, internalVarsToExport, _IFT_POIExportModule_vars); @@ -78,8 +79,6 @@ POIExportModule :: initializeFrom(InputRecord *ir) std :: string poiFileName; IR_GIVE_OPTIONAL_FIELD(ir, poiFileName, _IFT_POIExportModule_poifilename); this->readPOIFile(poiFileName); // parse poi file - - return ExportModule :: initializeFrom(ir); } void @@ -90,7 +89,7 @@ POIExportModule :: readPOIFile(const std :: string &poiFileName) // Open the file; std :: ifstream file(poiFileName.c_str(), std :: ios :: in); if ( !file.is_open() ) { - OOFEM_ERROR("Failed to open time data file: %s\n", poiFileName.c_str() ); + OOFEM_ERROR("Failed to open POI data file: %s\n. Did you specify poifilename?", poiFileName.c_str() ); } file >> nPOI; // Not actually needed. @@ -210,11 +209,11 @@ POIExportModule :: giveMapper() { if ( !this->mapper ) { if ( this->mtype == POI_CPT ) { - this->mapper.reset( new MMAClosestIPTransfer() ); + this->mapper = std::make_unique(); } else if ( this->mtype == POI_SFT ) { - this->mapper.reset( new MMAShapeFunctProjection() ); + this->mapper = std::make_unique(); } else if ( this->mtype == POI_LST ) { - this->mapper.reset( new MMALeastSquareProjection() ); + this->mapper = std::make_unique(); } else { OOFEM_ERROR("unsupported smoother type ID"); } @@ -274,6 +273,7 @@ POIExportModule :: exportPrimVarAs(UnknownType valID, FILE *stream, TimeStep *tS // loop over POIs for ( auto &poi: POIList ) { coords.at(1) = poi.x; + coords.at(2) = poi.y; coords.at(3) = poi.z; //region = poi.region; diff --git a/src/sm/export/poiexportmodule.h b/src/sm/export/poiexportmodule.h index bbe05a7c6..1c91ce604 100644 --- a/src/sm/export/poiexportmodule.h +++ b/src/sm/export/poiexportmodule.h @@ -89,13 +89,13 @@ class POIExportModule : public ExportModule /// Destructor virtual ~POIExportModule(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void doOutput(TimeStep *tStep, bool forcedOutput = false); - virtual void initialize(); - virtual void terminate(); - virtual const char *giveInputRecordName() const { return _IFT_POIExportModule_Name; } - virtual const char *giveClassName() const { return "POIExportModule"; } + void doOutput(TimeStep *tStep, bool forcedOutput = false) override; + void initialize() override; + void terminate() override; + const char *giveClassName() const override { return "POIExportModule"; } + const char *giveInputRecordName() const { return _IFT_POIExportModule_Name; } protected: void readPOIFile(const std :: string &poiFileName); diff --git a/src/sm/gpinitmodule.C b/src/sm/gpinitmodule.C index 0c752123c..7df333f34 100644 --- a/src/sm/gpinitmodule.C +++ b/src/sm/gpinitmodule.C @@ -57,10 +57,10 @@ GPInitModule :: ~GPInitModule() { } -IRResultType -GPInitModule :: initializeFrom(InputRecord *ir) +void +GPInitModule :: initializeFrom(InputRecord &ir) { - return InitModule :: initializeFrom(ir); + InitModule :: initializeFrom(ir); } @@ -82,7 +82,6 @@ GPInitModule :: doInit() // loop over Gauss points for ( auto &gp: *elem->giveDefaultIntegrationRulePtr() ) { Material *mat = elem->giveCrossSection()->giveMaterial(gp); - MaterialStatus *status = static_cast< MaterialStatus * >( gp->giveMaterialStatus() ); if ( fscanf(initStream, "%d %d", & ie, & ig) != 2 ) { OOFEM_ERROR("initStream reading error"); } @@ -123,7 +122,7 @@ GPInitModule :: doInit() mat->setIPValue(value, gp, vartype); } // restore consistency (compute dependent internal variables) - status->restoreConsistency(); + mat->restoreConsistency(gp); } } diff --git a/src/sm/gpinitmodule.h b/src/sm/gpinitmodule.h index 8d94995c0..362bf6033 100644 --- a/src/sm/gpinitmodule.h +++ b/src/sm/gpinitmodule.h @@ -56,9 +56,9 @@ class GPInitModule : public InitModule /// Destructor virtual ~GPInitModule(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void doInit(); - virtual const char *giveClassName() const { return "GPInitModule"; } + void initializeFrom(InputRecord &ir) override; + void doInit() override; + const char *giveClassName() const override { return "GPInitModule"; } }; } // namespace oofem #endif diff --git a/src/sm/mappers/primvarmapper.C b/src/sm/mappers/primvarmapper.C index 7053f0b02..98fbced82 100644 --- a/src/sm/mappers/primvarmapper.C +++ b/src/sm/mappers/primvarmapper.C @@ -36,7 +36,7 @@ #include "domain.h" #include "dofmanager.h" #include "linsystsolvertype.h" -#include "../sm/Elements/structuralelement.h" +#include "sm/Elements/structuralelement.h" #include "engngm.h" #include "gausspoint.h" #include "feinterpol.h" @@ -89,11 +89,11 @@ void LSPrimaryVariableMapper :: mapPrimaryVariables(FloatArray &oU, Domain &iOld std :: unique_ptr< SparseMtrx > K; std :: unique_ptr< SparseLinearSystemNM > solver; - solver.reset( classFactory.createSparseLinSolver(ST_Petsc, & iOldDom, engngMod) ); + solver = classFactory.createSparseLinSolver(ST_Petsc, & iOldDom, engngMod); if (!solver) { - solver.reset( classFactory.createSparseLinSolver(ST_Direct, & iOldDom, engngMod) ); + solver = classFactory.createSparseLinSolver(ST_Direct, & iOldDom, engngMod); } - K.reset( classFactory.createSparseMtrx(solver->giveRecommendedMatrix(true)) ); + K = classFactory.createSparseMtrx(solver->giveRecommendedMatrix(true)); K->buildInternalStructure( engngMod, iNewDom.giveNumber(), num ); diff --git a/src/sm/microplane.h b/src/sm/microplane.h deleted file mode 100644 index 3fd9b1f63..000000000 --- a/src/sm/microplane.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef microplane_h -#define microplane_h - -#include "gausspoint.h" -#include "Materials/microplanematerial.h" -#include "floatarray.h" -#include "element.h" -#include "matstatus.h" - -namespace oofem { -class Element; -class Material; -class LayeredCrossSection; - -/** - * Class representing microplane integration point in finite element program. - * Microplane always belongs to macro integration point and - * represents micro material level. Microplanes are created by particular microplane - * material model. - * Because all corresponding microplanes in all macro integration points - * subjected to particular material share the same properties (same normals, - * same integration weights), these are stored only once at material model level. - * Thus requests for microplane integration weights and normal are forwarded - * to corresponding material model. - * - * Generally, every integration point must hold - * its own copy of history variables (which are related to corresponding - * material model used). These material type dependent history variables - * are stored in material type related material status, which can be - * managed by integration point. - * Each material model class should introduce related material status class - * (derived from material status class or from its children), where necessary - * history variables are kept and can be accessed by material. - * Material class then creates unique copy of related status in all necessary - * integration points. Because integration point is compulsory parameter of - * all member functions of material class, particular material then can - * easily access its associated status from integration point and therefore its - * history variables for particular integration point. - */ -class Microplane : public GaussPoint -{ -public: - /** - * Creates microplane integration point belonging - * to given element, with given number, integration weight, coordinates and material mode. - * @param ir Integration rule to which integration point belongs to. - * @param n Integration point number. - * @param mode Material mode. - */ - Microplane(IntegrationRule * ir, int n, MaterialMode mode); - /// Destructor - virtual ~Microplane(); - - virtual IRResultType initializeFrom(InputRecord *ir) { return IRRT_OK; } - - double giveWeight() - { return static_cast< MicroplaneMaterial * >( this->giveMaterial() )->giveMicroplaneIntegrationWeight(this); } - /// Returns normal of microplane. - void giveMicroplaneNormal(FloatArray &answer) - { static_cast< MicroplaneMaterial * >( this->giveMaterial() )->giveMicroplaneNormal(answer, this); } - - virtual void printOutputAt(FILE *file, TimeStep *tStep); - - virtual const char *giveClassName() const { return "Microplane"; } -}; -} // end namespace oofem -#endif // microplane_h diff --git a/src/sm/particle.C b/src/sm/particle.C index 94c4ef771..ff228226f 100644 --- a/src/sm/particle.C +++ b/src/sm/particle.C @@ -35,6 +35,7 @@ #include "particle.h" #include "classfactory.h" #include "error.h" +#include "floatmatrix.h" namespace oofem { REGISTER_DofManager(Particle); @@ -44,17 +45,14 @@ Particle :: Particle(int n, Domain *aDomain) : Node(n, aDomain) { } -IRResultType -Particle :: initializeFrom(InputRecord *ir) +void +Particle :: initializeFrom(InputRecord &ir) { - IRResultType result; + Node :: initializeFrom(ir); IR_GIVE_FIELD(ir, radius, _IFT_Particle_rad); if ( radius < 0.0 ) { - OOFEM_WARNING("negative radius"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Particle_rad, "must be positive"); } - - return Node :: initializeFrom(ir); } } // namespace oofem diff --git a/src/sm/particle.h b/src/sm/particle.h index af853572a..1af0bee4b 100644 --- a/src/sm/particle.h +++ b/src/sm/particle.h @@ -67,9 +67,9 @@ class Particle : public Node */ virtual ~Particle(void) { } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual const char *giveInputRecordName() const { return _IFT_Particle_Name; } - virtual const char *giveClassName() const { return "Particle"; } + void initializeFrom(InputRecord &ir) override; + const char *giveInputRecordName() const override { return _IFT_Particle_Name; } + const char *giveClassName() const override { return "Particle"; } /// Returns the radius of the particle. double giveRadius() const { return radius; } diff --git a/src/sm/polylinenonlocalbarrier.C b/src/sm/polylinenonlocalbarrier.C index a21761281..7f885e2d8 100644 --- a/src/sm/polylinenonlocalbarrier.C +++ b/src/sm/polylinenonlocalbarrier.C @@ -58,8 +58,8 @@ PolylineNonlocalBarrier :: ~PolylineNonlocalBarrier() void -PolylineNonlocalBarrier :: applyConstraint(const FloatArray &c1, const FloatArray &c2, double &weight, - bool &shieldFlag, NonlocalMaterialExtensionInterface *nei) +PolylineNonlocalBarrier :: applyConstraint(const double cl, const FloatArray &c1, const FloatArray &c2, double &weight, + bool &shieldFlag, const NonlocalMaterialExtensionInterface &nei) { if ( this->isActivated(c1, c2) ) { weight = 0.0; @@ -180,11 +180,9 @@ PolylineNonlocalBarrier :: giveDistancePointLine(const FloatArray &coordsA, cons } -IRResultType -PolylineNonlocalBarrier :: initializeFrom(InputRecord *ir) +void +PolylineNonlocalBarrier :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - IR_GIVE_FIELD(ir, vertexNodes, _IFT_PolylineNonlocalBarrier_vertexnodes); // default: polyline in xy plane @@ -193,7 +191,5 @@ PolylineNonlocalBarrier :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, localXCoordIndx, _IFT_PolylineNonlocalBarrier_xcoordindx); IR_GIVE_OPTIONAL_FIELD(ir, localYCoordIndx, _IFT_PolylineNonlocalBarrier_ycoordindx); - - return IRRT_OK; } } // end namespace oofem diff --git a/src/sm/polylinenonlocalbarrier.h b/src/sm/polylinenonlocalbarrier.h index 74a07edf6..8f872eae4 100644 --- a/src/sm/polylinenonlocalbarrier.h +++ b/src/sm/polylinenonlocalbarrier.h @@ -84,12 +84,12 @@ class PolylineNonlocalBarrier : public NonlocalBarrier virtual bool isActivated(const FloatArray &c1, const FloatArray &c2); - virtual void applyConstraint(const FloatArray &c1, const FloatArray &c2, double &weight, - bool &shieldFlag, NonlocalMaterialExtensionInterface *nei); + void applyConstraint(const double cl, const FloatArray &c1, const FloatArray &c2, double &weight, + bool &shieldFlag, const NonlocalMaterialExtensionInterface &nei) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual double calculateMinimumDistanceFromBoundary(const FloatArray &coords); + double calculateMinimumDistanceFromBoundary(const FloatArray &coords) override; /** * This function computes the length of the normal to the line defined by 2 vertices that passes through @@ -101,8 +101,8 @@ class PolylineNonlocalBarrier : public NonlocalBarrier */ double giveDistancePointLine(const FloatArray &coordsA, const FloatArray &coordsB, const FloatArray &coordsGP); - virtual const char *giveInputRecordName() const { return _IFT_PolylineNonlocalBarrier_Name; } - virtual const char *giveClassName() const { return "PolylineNonlocalBarrier"; } + const char *giveInputRecordName() const override { return _IFT_PolylineNonlocalBarrier_Name; } + const char *giveClassName() const override { return "PolylineNonlocalBarrier"; } }; } // end namespace oofem #endif // polylinenonlocalbarrier_h diff --git a/src/sm/prescribeddispslipbcdirichletrc.C b/src/sm/prescribeddispslipbcdirichletrc.C new file mode 100644 index 000000000..8d8e519b1 --- /dev/null +++ b/src/sm/prescribeddispslipbcdirichletrc.C @@ -0,0 +1,496 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "prescribeddispslipbcdirichletrc.h" +#include "dofiditem.h" +#include "dofmanager.h" +#include "dof.h" +#include "valuemodetype.h" +#include "floatarray.h" +#include "floatmatrix.h" +#include "function.h" +#include "engngm.h" +#include "set.h" +#include "node.h" +#include "element.h" +#include "classfactory.h" +#include "dynamicinputrecord.h" +#include "feinterpol.h" +#include "unknownnumberingscheme.h" +#include "sparsemtrx.h" +#include "sparselinsystemnm.h" +#include "assemblercallback.h" +#include "mathfem.h" +#include "floatarrayf.h" +#include "crosssection.h" + +namespace oofem { +REGISTER_BoundaryCondition(PrescribedDispSlipBCDirichletRC); + +double PrescribedDispSlipBCDirichletRC :: give(Dof *dof, ValueModeType mode, double time) +{ + DofIDItem id = dof->giveDofID(); + const auto &coords = dof->giveDofManager()->giveCoordinates(); + + double factor = 0; + if ( mode == VM_Total ) { + factor = this->giveTimeFunction()->evaluateAtTime(time); + } else if ( mode == VM_Velocity ) { + factor = this->giveTimeFunction()->evaluateVelocityAtTime(time); + } else if ( mode == VM_Acceleration ) { + factor = this->giveTimeFunction()->evaluateAccelerationAtTime(time); + } else { + OOFEM_ERROR("Should not be called for value mode type then total, velocity, or acceleration."); + } + + FloatArray dx; + dx.beDifferenceOf(coords, this->mCenterCoord); + + dispGradient.resizeWithData(coords.giveSize(), coords.giveSize()); + dispField.resizeWithValues(coords.giveSize()); + slipField.resizeWithValues(coords.giveSize()); + slipGradient.resizeWithData(coords.giveSize(), coords.giveSize()); + + FloatArray u; + u.beProductOf(dispGradient, dx); + u.at(1) += dispField.at(1); + u.at(2) += dispField.at(2); + u.times( factor ); + + + FloatArray us; + us.beProductOf(slipGradient, dx); + us.at(1) += slipField.at(1); + us.at(2) += slipField.at(2); + us.times( factor ); + + int pos = this->dofs.findFirstIndexOf(id); + + bool onConcrete = true; + bool onSteel = false; + + if ( reinfXBound && reinfYBound ) { + Set* setx = domain->giveSet(reinfXBound); + Set* sety = domain->giveSet(reinfYBound); + + if ( setx->giveNodeList().contains( dof->giveDofManGlobalNumber() ) || sety->giveNodeList().contains( dof->giveDofManGlobalNumber() ) ) { + onConcrete = false; + onSteel = true; + } + } + + if ( onConcrete ) { //node on concrete + return this->giveOnConcrete(dof, pos, u); + } else if ( onSteel ) { //node on steel + return this->giveOnSteel(dof, pos, u, us); + } else { + return 0.0; + } + +} + + +double PrescribedDispSlipBCDirichletRC::giveOnConcrete( Dof *dof, int pos, const FloatArray u ) +{ + if ( pos > 0 && pos <= u.giveSize() ) { + return u.at(pos); + } else { + return 0.0; + } + +} + + +double PrescribedDispSlipBCDirichletRC::giveOnSteel( Dof *dof, int pos, const FloatArray u, const FloatArray us ) +{ + bool isXReinf = false; + bool isYReinf = false; + + domain->giveSet(reinfXBound)->giveNodeList().contains( dof->giveDofManager()->giveGlobalNumber() ) ? isXReinf = true : isXReinf = false; + domain->giveSet(reinfYBound)->giveNodeList().contains( dof->giveDofManager()->giveGlobalNumber() ) ? isYReinf = true : isYReinf = false; + + if ( isXReinf ) { + if ( pos == 1 ) { + return u.at(pos) + us.at(pos); + } else if ( pos == 2 ) { + return u.at(pos); + } else if ( pos == 3 ) { + return -dispGradient.at(2,1); + } else { + return 0.0; + } + } else if ( isYReinf ) { + if ( pos == 1 ) { + return u.at(pos); + } else if ( pos == 2 ) { + return u.at(pos) + us.at(pos); + } else if ( pos == 3 ) { + return dispGradient.at(2,1); + } else { + return 0.0; + } + } else { + return 0.0; + } +} + + +void PrescribedDispSlipBCDirichletRC::updateCoefficientMatrix( FloatMatrix &C ) +{ +// This is written in a very general way, supporting both fm and sm problems. +// v_prescribed = C.d = (x-xbar).d; +// Modified by ES. +// C = [x 0 0 y] +// [0 y x 0] +// [ ... ] in 2D, voigt form [d_11, d_22, d_12 d_21] +//Modified by AS: +//Include end moments from the reinforcement. +//\sum (R_L e_l + R_perp e_{\perp} ) \outerp (x-\bar{x}) already included in C^T.R_c (in computeField) +//Added term \sum R_M e_{\perp} \outerp e_l +// C = [x 0 0 y ] +// [0 y y 0 ] +// [ePerp1*eL1 ePerp2*eL2 ePerp1*eL2 ePerp2*eL1] +// for DofManagers with rotational degrees of freedom. + Domain *domain = this->giveDomain(); + + int nsd = domain->giveNumberOfSpatialDimensions(); + int npeq = domain->giveEngngModel()->giveNumberOfDomainEquations( domain->giveNumber(), EModelDefaultPrescribedEquationNumbering() ); + C.resize(npeq, nsd * nsd); + C.zero(); + + FloatArray &cCoords = this->giveCenterCoordinate(); + double xbar = cCoords.at(1), ybar = cCoords.at(2); + + for ( auto &n : domain->giveDofManagers() ) { + const auto &coords = n->giveCoordinates(); + Dof *d1 = n->giveDofWithID( this->dofs[0] ); + Dof *d2 = n->giveDofWithID( this->dofs[1] ); + int k1 = d1->__givePrescribedEquationNumber(); + int k2 = d2->__givePrescribedEquationNumber(); + int k3 = 0; + FloatArrayF<2> eL = { 0., 0. }; + FloatArrayF<2> ePerp = { 0., 0. }; + if ( (reinfXBound && reinfYBound) && n->giveNumberOfDofs() == 3 ) { + Dof *d3 = n->giveDofWithID( this->dofs[2] ); + k3 = d3->__givePrescribedEquationNumber(); + Set* setX = domain->giveSet(reinfXBound); + Set* setY = domain->giveSet(reinfYBound); + if ( setX->giveNodeList().contains( n->giveGlobalNumber() ) ) { + eL = { 1., 0.}; + ePerp = { 0., 1.}; + } else if ( setY->giveNodeList().contains( n->giveGlobalNumber() ) ) { + eL = { 0., 1.}; + ePerp = { -1., 0.}; + } + } + if ( nsd == 2 ) { + if ( k1 ) { + C.at(k1, 1) = coords.at(1) - xbar; + C.at(k1, 4) = coords.at(2) - ybar; + } + + if ( k2 ) { + C.at(k2, 2) = coords.at(2) - ybar; + C.at(k2, 3) = coords.at(1) - xbar; + } + + if ( k3 ) { + C.at(k3, 1) = ePerp.at(1) * eL.at(1); + C.at(k3, 2) = ePerp.at(2) * eL.at(2); + C.at(k3, 3) = ePerp.at(1) * eL.at(2); + C.at(k3, 4) = ePerp.at(2) * eL.at(1); + } + } else { + OOFEM_ERROR("Only 2D mode supported.\n"); + } + } + +} + + + +void PrescribedDispSlipBCDirichletRC :: computeStress(FloatArray &sigma, TimeStep *tStep) +{ + if ( dispGradON ) { + EngngModel *emodel = this->domain->giveEngngModel(); + int npeq = emodel->giveNumberOfDomainEquations( this->giveDomain()->giveNumber(), EModelDefaultPrescribedEquationNumbering() ); + FloatArray R_c( npeq ), R_ext( npeq ); + + R_c.zero(); + R_ext.zero(); + emodel->assembleVector( R_c, tStep, InternalForceAssembler(), VM_Total, + EModelDefaultPrescribedEquationNumbering(), this->giveDomain() ); + emodel->assembleVector( R_ext, tStep, ExternalForceAssembler(), VM_Total, + EModelDefaultPrescribedEquationNumbering(), this->giveDomain() ); + R_c.subtract( R_ext ); + + // Condense it; + FloatMatrix C; + this->updateCoefficientMatrix( C ); + sigma.beTProductOf( C, R_c ); + double volRVE = this->domainSize( this->giveDomain(), this->giveSetNumber() ); + sigma.times( 1. / volRVE ); + } +} + +void PrescribedDispSlipBCDirichletRC::computeTransferStress( FloatArray &bStress, TimeStep *tStep ) +{ + //According to 1/(\Omega_\Box) * \sum R_L \be{l} + // [ tau_bxx, tau_byy ] + // only compute when applied to reinforcement + + if ( slipON ) { + EngngModel *emodel = this->domain->giveEngngModel(); + Domain *domain = this->giveDomain(); + + int nsd = domain->giveNumberOfSpatialDimensions(); + int npeq = domain->giveEngngModel()->giveNumberOfDomainEquations( domain->giveNumber(), EModelDefaultPrescribedEquationNumbering() ); + + FloatArray R_c(npeq), R_ext(npeq); + + R_c.zero(); + R_ext.zero(); + emodel->assembleVector( R_c, tStep, InternalForceAssembler(), VM_Total, + EModelDefaultPrescribedEquationNumbering(), this->giveDomain() ); + //R_c contains reactions at the boundary - coming from concrete tractions, beam end forces (normal and shear) and end moments + + emodel->assembleVector( R_ext, tStep, ExternalForceAssembler(), VM_Total, + EModelDefaultPrescribedEquationNumbering(), this->giveDomain() ); + + R_c.subtract(R_ext); + + //taking contribution only from end nodes of the reinforcement + IntArray nodesX = domain->giveSet(reinfXBound)->giveNodeList(); + IntArray nodesY = domain->giveSet(reinfYBound)->giveNodeList(); + FloatArray eL; + double R_L; + eL.resize(nsd); eL.zero(); + bStress.resize(nsd); bStress.zero(); + + for (int i=1; i<=nodesX.giveSize(); i++) { + DofManager *d1 = domain->giveDofManager( nodesX.at(i) ); + eL.at(1) = 1; + eL.at(2) = 0; + R_L = R_c.at( d1->giveDofWithID(1)->__givePrescribedEquationNumber() ); + bStress.at(1) += R_L*eL.at(1); + bStress.at(2) += R_L*eL.at(2); + } + + for (int i=1; i<=nodesY.giveSize(); i++) { + DofManager *d2 = domain->giveDofManager( nodesY.at(i) ); + eL.at(1) = 0; + eL.at(2) = 1; + R_L = R_c.at( d2->giveDofWithID(2)->__givePrescribedEquationNumber() ); + bStress.at(1) += R_L*eL.at(1); + bStress.at(2) += R_L*eL.at(2); + } + + double volRVE = this->domainSize( this->giveDomain(), this->giveSetNumber() ); + bStress.times( 1. / volRVE ); + } +} + + +void PrescribedDispSlipBCDirichletRC::computeReinfStress( FloatArray &rStress, TimeStep *tStep ) +{ + //According to 1/(\Omega_\Box) * \sum R_L \be{l} \outerp [x - \bar{x} ] + //order: sxx, syy, sxy, syx + // only compute when applied to reinforcement + + if ( slipGradON ) { + EngngModel *emodel = this->domain->giveEngngModel(); + Domain *domain = this->giveDomain(); + + int nsd = domain->giveNumberOfSpatialDimensions(); + int npeq = domain->giveEngngModel()->giveNumberOfDomainEquations( domain->giveNumber(), EModelDefaultPrescribedEquationNumbering() ); + + FloatArray R_c(npeq), R_ext(npeq); + + R_c.zero(); + R_ext.zero(); + emodel->assembleVector( R_c, tStep, InternalForceAssembler(), VM_Total, + EModelDefaultPrescribedEquationNumbering(), this->giveDomain() ); + //R_c contains reactions at the boundary - coming from concrete tractions, beam end forces (normal and shear) and end moments + + emodel->assembleVector( R_ext, tStep, ExternalForceAssembler(), VM_Total, + EModelDefaultPrescribedEquationNumbering(), this->giveDomain() ); + + R_c.subtract(R_ext); + + //taking contribution only from end nodes of the reinforcement + IntArray nodesX = domain->giveSet(reinfXBound)->giveNodeList(); + IntArray nodesY = domain->giveSet(reinfYBound)->giveNodeList(); + FloatArray eL, cCoords = this->giveCenterCoordinate(); + double xbar=cCoords.at(1), ybar=cCoords.at(2), R_L; + eL.resize(nsd); eL.zero(); + rStress.resize(nsd*2); rStress.zero(); + + for (int i=1; i<=nodesX.giveSize(); i++) { + DofManager *d1 = domain->giveDofManager( nodesX.at(i) ); + const auto &coords = d1->giveCoordinates(); + eL.at(1) = 1; + eL.at(2) = 0; + R_L = R_c.at( d1->giveDofWithID(1)->__givePrescribedEquationNumber() ); + rStress.at(1) += R_L*eL.at(1) * (coords.at(1) - xbar); + rStress.at(2) += R_L*eL.at(2) * (coords.at(2) - ybar); + rStress.at(3) += R_L*eL.at(1) * (coords.at(2) - ybar); + rStress.at(4) += R_L*eL.at(2) * (coords.at(1) - xbar); + } + + for (int i=1; i<=nodesY.giveSize(); i++) { + DofManager *d2 = domain->giveDofManager( nodesY.at(i) ); + const auto &coords = d2->giveCoordinates(); + eL.at(1) = 0; + eL.at(2) = 1; + R_L = R_c.at( d2->giveDofWithID(2)->__givePrescribedEquationNumber() ); + rStress.at(1) += R_L*eL.at(1) * (coords.at(1) - xbar); + rStress.at(2) += R_L*eL.at(2) * (coords.at(2) - ybar); + rStress.at(3) += R_L*eL.at(1) * (coords.at(2) - ybar); + rStress.at(4) += R_L*eL.at(2) * (coords.at(1) - xbar); + } + + double volRVE = this->domainSize( this->giveDomain(), this->giveSetNumber() ); + rStress.times( 1. / volRVE ); + } +} + + +void PrescribedDispSlipBCDirichletRC :: computeTangent(FloatMatrix &tangent, TimeStep *tStep) +// a = [a_c; a_f]; +// K.a = [R_c,0]; +// [K_cc, K_cf; K_fc, K_ff].[a_c;a_f] = [R_c; 0]; +// a_c = d.[x-x_b] = [x-x_b].d = C.d +// E = C'.(K_cc - K_cf.K_ff^(-1).K_fc).C +// = C'.(K_cc.C - K_cf.(K_ff^(-1).(K_fc.C))) +// = C'.(K_cc.C - K_cf.a) +// = C'.X +{ + if ( dispGradON && !slipON && !slipGradON ) { + // Fetch some information from the engineering model + EngngModel *rve = this->giveDomain()->giveEngngModel(); + std ::unique_ptr solver( classFactory.createSparseLinSolver( ST_Petsc, this->domain, this->domain->giveEngngModel() ) ); // = rve->giveLinearSolver(); + SparseMtrxType stype = solver->giveRecommendedMatrix( true ); + EModelDefaultEquationNumbering fnum; + EModelDefaultPrescribedEquationNumbering pnum; + + // Set up and assemble tangent FE-matrix which will make up the sensitivity analysis for the macroscopic material tangent. + std ::unique_ptr Kff( classFactory.createSparseMtrx( stype ) ); + std ::unique_ptr Kfp( classFactory.createSparseMtrx( stype ) ); + std ::unique_ptr Kpf( classFactory.createSparseMtrx( stype ) ); + std ::unique_ptr Kpp( classFactory.createSparseMtrx( stype ) ); + if ( !Kff ) { + OOFEM_ERROR( "Couldn't create sparse matrix of type %d\n", stype ); + } + Kff->buildInternalStructure( rve, 1, fnum ); + Kfp->buildInternalStructure( rve, 1, fnum, pnum ); + Kpf->buildInternalStructure( rve, 1, pnum, fnum ); + Kpp->buildInternalStructure( rve, 1, pnum ); + rve->assemble( *Kff, tStep, TangentAssembler( TangentStiffness ), fnum, this->domain ); + rve->assemble( *Kfp, tStep, TangentAssembler( TangentStiffness ), fnum, pnum, this->domain ); + rve->assemble( *Kpf, tStep, TangentAssembler( TangentStiffness ), pnum, fnum, this->domain ); + rve->assemble( *Kpp, tStep, TangentAssembler( TangentStiffness ), pnum, this->domain ); + + FloatMatrix C, X, Kpfa, KfpC, a; + + this->updateCoefficientMatrix( C ); + Kpf->timesT( C, KfpC ); + solver->solve( *Kff, KfpC, a ); + Kpp->times( C, X ); + Kpf->times( a, Kpfa ); + X.subtract( Kpfa ); + tangent.beTProductOf( C, X ); + tangent.times( 1. / this->domainSize( this->giveDomain(), this->giveSetNumber() ) ); + } +} + +void PrescribedDispSlipBCDirichletRC :: initializeFrom(InputRecord &ir) +{ + GeneralBoundaryCondition :: initializeFrom(ir); + PrescribedDispSlipHomogenization::initializeFrom(ir); + IR_GIVE_FIELD(ir, conBoundSet, _IFT_PrescribedDispSlipBCDirichletRC_ConcreteBoundary); + + if ( this->dispGradient.isNotEmpty() ) { + this->dispGradON = true; + } + + if ( this->slipField.isNotEmpty() ) { + this->slipON = true; + } + + if ( this->slipGradient.isNotEmpty() ) { + this->slipGradON = true; + } + + if ( slipON || slipGradON) { + IR_GIVE_OPTIONAL_FIELD( ir, reinfXBound, _IFT_PrescribedDispSlipBCDirichletRC_ReinfXBound ); + IR_GIVE_OPTIONAL_FIELD( ir, reinfYBound, _IFT_PrescribedDispSlipBCDirichletRC_ReinfYBound ); + } +} + + +void PrescribedDispSlipBCDirichletRC :: giveInputRecord(DynamicInputRecord &input) +{ + GeneralBoundaryCondition :: giveInputRecord(input); + PrescribedDispSlipHomogenization :: giveInputRecord(input); +} + + +void PrescribedDispSlipBCDirichletRC::scale( double s ) +{ + dispField.times(s); + slipField.times(s); + dispGradient.times(s); + slipGradient.times(s); +} + +double PrescribedDispSlipBCDirichletRC::domainSize( Domain *d, int set ) +{ + double omegaBox = PrescribedDispSlipHomogenization::domainSize(d, conBoundSet); + + if ( this->giveDomain()->giveNumberOfSpatialDimensions() == 2 ) { + //assuming that the RVE thickness is constant in 2D + Element *e = this->giveDomain()->giveElement( this->giveDomain()->giveSet(conBoundSet)->giveBoundaryList().at(1) ); + std::unique_ptr ir = e->giveInterpolation()->giveIntegrationRule( e->giveInterpolation()->giveInterpolationOrder() ); + CrossSection *cs = e->giveCrossSection(); + GaussPoint *gp = ir->getIntegrationPoint(0); + double thickness = cs->give(CS_Thickness, gp); + return omegaBox * thickness; + } else { + return omegaBox; + } + +} + + +} // end namespace oofem diff --git a/src/sm/prescribeddispslipbcdirichletrc.h b/src/sm/prescribeddispslipbcdirichletrc.h new file mode 100644 index 000000000..073a0e459 --- /dev/null +++ b/src/sm/prescribeddispslipbcdirichletrc.h @@ -0,0 +1,117 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef prescribeddispslipbcdirichletrc_h +#define prescribeddispslipbcdirichletrc_h + +#include "prescribeddispsliphomogenization.h" +#include "boundarycondition.h" +#include "dof.h" +#include "bctype.h" +#include "valuemodetype.h" +#include "floatarray.h" +#include "floatmatrix.h" + +///@name Input fields for PrescribedDispSlipBCDirichletRC +//@{ +#define _IFT_PrescribedDispSlipBCDirichletRC_Name "prescribeddispslipbcdirichletrc" +#define _IFT_PrescribedDispSlipBCDirichletRC_ConcreteBoundary "conboundset" +#define _IFT_PrescribedDispSlipBCDirichletRC_ReinfXBound "reinfxbound" +#define _IFT_PrescribedDispSlipBCDirichletRC_ReinfYBound "reinfybound" +//@} + +namespace oofem { +/** + * Prescribes macroscopic displacement gradient, reinforcement slip field and slip gradient + * on the reinforced concrete RVE using Dirichlet boundary conditions, cf. + * Sciegaj, A., Larsson, F., Lundgren, K., Nilenius, F., & Runesson, K. (2019). A multiscale model for reinforced concrete with macroscopic variation of reinforcement slip. Computational Mechanics, 63(2), 139–158. https://doi.org/10.1007/s00466-018-1588-3 + * Macroscopic slip and slip gradient fields are optional (see PrescribedDispSlipHomogenization). + * If not specified, this BC will prescribe only the displacement gradient, i.e., it will work the same was as a PrescribedGradient bc. + * Works with 2D RVEs comprising solid elements (concrete), reinforcement (beam/truss elements) and interface elements in between. + * Used in multiscale analyses of reinforced concrete structures. Currently, only orthogonal reinforcement in X and Y direction is supported. + * + * This BC can be applied to the set of: + * - nodes lying at the concrete boundary. In order to prescribe macroscopic displacement gradient on both concrete and steel, + * the node set this BC is applied to must include the end (boundary) nodes of the reinforcement bars as well. conboundset should contain only elementboundaries of concrete elements, e.g. + * PrescribedDispSlipBCDirichletRC 1 loadTimeFunction 1 dofs 2 1 2 ccoord 3 0.0 0.0 0.0 dispGrad 2 2 {0 0; 0 0} set 5 conboundset 6 + * where set 5 contains all boundary nodes (concrete+steel) and set 6 contains boundary of concrete elements + * - elementboundaries of concrete elements. In this case displacement gradient is not prescribed on the reinforcement. + * PrescribedDispSlipBCDirichletRC 1 loadTimeFunction 1 dofs 2 1 2 ccoord 3 0.0 0.0 0.0 dispGrad 2 2 {0 0; 0 0} set 5 conboundset 5 + * where set 5 contains boundary of concrete elements + * + * If the macroscopic slip/slip gradient field is to be prescribed onto the RVE, the optional node sets reinfxbound and reinfybound must be specified. + * These node sets contain the boundary nodes of the horizontal and vertical reinforcement, respectively. + * + * @author Adam Sciegaj + */ +class OOFEM_EXPORT PrescribedDispSlipBCDirichletRC : public BoundaryCondition, public PrescribedDispSlipHomogenization +{ +public: + PrescribedDispSlipBCDirichletRC(int n, Domain *d) : BoundaryCondition(n, d) { } + virtual ~PrescribedDispSlipBCDirichletRC() { } + + double give(Dof *dof, ValueModeType mode, double time) override; + + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + + virtual void updateCoefficientMatrix(FloatMatrix &C); + double domainSize(Domain *d, int set) override; + + void computeStress(FloatArray &sigma, TimeStep *tStep) override; + void computeTransferStress(FloatArray &bStress, TimeStep *tStep) override; + void computeReinfStress(FloatArray &rStress, TimeStep *tStep) override; + + void computeTangent(FloatMatrix &tangent, TimeStep *tStep) override; + + void scale(double s) override; + + const char *giveClassName() const override { return "PrescribedDispSlipBCDirichletRC"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedDispSlipBCDirichletRC_Name; } + +protected: + bool dispGradON = false; /// on/off flag specifying whether the displacement gradient should be applied via Neumann BCs + bool slipON = false; /// on/off flag specifying whether the slip field should be applied via Neumann BCs + bool slipGradON = false; /// on/off flag specifying whether the slip gradient should be applied via Neumann BCs + + int conBoundSet; //element boundaries set for the concrete solid + int reinfXBound=0; //set containing end (boundary) nodes of horizontal rebars + int reinfYBound=0; //set containing end (boundary) nodes of vertical rebars + + double giveOnConcrete(Dof *dof, int pos, const FloatArray u); + double giveOnSteel(Dof *dof, int pos, const FloatArray u, const FloatArray us); +}; +} // end namespace oofem + +#endif // prescribeddispslipbcdirichletrc_h diff --git a/src/sm/prescribeddispslipbcneumannrc.C b/src/sm/prescribeddispslipbcneumannrc.C new file mode 100644 index 000000000..431f05c54 --- /dev/null +++ b/src/sm/prescribeddispslipbcneumannrc.C @@ -0,0 +1,1161 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "prescribeddispslipbcneumannrc.h" +#include "classfactory.h" +#include "node.h" +#include "masterdof.h" +#include "element.h" +#include "feinterpol.h" +#include "feinterpol2d.h" +#include "gausspoint.h" +#include "sparsemtrx.h" +#include "timestep.h" +#include "function.h" +#include "sparselinsystemnm.h" +#include "unknownnumberingscheme.h" +#include "engngm.h" +#include "mathfem.h" +#include "crosssection.h" +#include "Elements/structuralelement.h" + + +namespace oofem { +REGISTER_BoundaryCondition(PrescribedDispSlipBCNeumannRC); + +PrescribedDispSlipBCNeumannRC :: PrescribedDispSlipBCNeumannRC(int n, Domain *d) : + ActiveBoundaryCondition(n, d), + PrescribedDispSlipHomogenization(), + mpSigmaHom( new Node(0, d) ), + lmTauHom( new Node(0, d) ), + lmSigmaSHom( new Node(0, d) ) +{ + int nsd = d->giveNumberOfSpatialDimensions(); + for ( int i = 0; i < nsd * nsd; i++ ) { + // Just putting in X_i id-items since they don't matter. + int dofId = d->giveNextFreeDofID(); + mSigmaIds.followedBy(dofId); + mpSigmaHom->appendDof( new MasterDof( mpSigmaHom.get(), ( DofIDItem ) ( dofId ) ) ); + } + + for ( int i = 0; i < nsd; i++ ) { + // Just putting in X_i id-items since they don't matter. + int dofId = d->giveNextFreeDofID(); + lmTauIds.followedBy(dofId); + lmTauHom->appendDof( new MasterDof( lmTauHom.get(), ( DofIDItem ) ( dofId ) ) ); + } + + for ( int i = 0; i < nsd ; i++ ) { + // Just putting in X_i id-items since they don't matter. + int dofId = d->giveNextFreeDofID(); + lmSigmaSIds.followedBy(dofId); + lmSigmaSHom->appendDof( new MasterDof( lmSigmaSHom.get(), ( DofIDItem ) ( dofId ) ) ); + } +} + +PrescribedDispSlipBCNeumannRC :: ~PrescribedDispSlipBCNeumannRC() +{ +} + + +void PrescribedDispSlipBCNeumannRC :: initializeFrom(InputRecord &ir) +{ + ActiveBoundaryCondition :: initializeFrom(ir); + PrescribedDispSlipHomogenization :: initializeFrom(ir); + + if ( this->dispGradient.isNotEmpty() ) { + this->dispGradON = true; + } + + if ( this->slipField.isNotEmpty() ) { + this->slipON = true; + } + + if ( this->slipGradient.isNotEmpty() ) { + this->slipGradON = true; + } + + if ( slipON || slipGradON) { //either slip or slip gradient (or both) will be prescribed weakly + IR_GIVE_OPTIONAL_FIELD( ir, concreteVolSet, _IFT_PrescribedDispSlipBCNeumannRC_ConcreteVolSet ); + IR_GIVE_OPTIONAL_FIELD( ir, rebarSets, _IFT_PrescribedDispSlipBCNeumannRC_RebarSets ); + } +} + + +void PrescribedDispSlipBCNeumannRC :: giveInputRecord(DynamicInputRecord &input) +{ + ActiveBoundaryCondition :: giveInputRecord(input); + PrescribedDispSlipHomogenization :: giveInputRecord(input); + + if ( slipON || slipGradON ) { + input.setField(this->concreteVolSet, _IFT_PrescribedDispSlipBCNeumannRC_ConcreteVolSet); + input.setField(this->rebarSets, _IFT_PrescribedDispSlipBCNeumannRC_RebarSets); + } +} + + +int PrescribedDispSlipBCNeumannRC::giveNumberOfInternalDofManagers() +{ + int lmTot = (int)dispGradON + (int)slipON + (int)slipGradON; + return lmTot; +} + +DofManager *PrescribedDispSlipBCNeumannRC :: giveInternalDofManager(int i) +{ + if ( this->giveNumberOfInternalDofManagers() == 3 ) { + if ( i == 1 ) { return mpSigmaHom.get(); } + else if ( i == 2 ) { return lmTauHom.get(); } + else if ( i == 3) { return lmSigmaSHom.get(); } + } else if ( this->giveNumberOfInternalDofManagers() == 2) { + if ( dispGradON && slipON ) { + if ( i == 1 ) { return mpSigmaHom.get(); } + else if ( i == 2 ) { return lmTauHom.get(); } + } else if ( dispGradON && slipGradON ) { + if ( i == 1 ) { return mpSigmaHom.get(); } + else if ( i ==2 ) { return lmSigmaSHom.get(); } + } else if ( slipON && slipGradON ) { + if ( i == 1 ) { return lmTauHom.get(); } + else if ( i == 2 ) { return lmSigmaSHom.get(); } + } + } else if ( this->giveNumberOfInternalDofManagers() == 1 ) { + if ( dispGradON ) { return mpSigmaHom.get(); } + else if ( slipON ) { return lmTauHom.get(); } + else if ( slipGradON ) {return lmSigmaSHom.get(); } + } + + return nullptr; +} + +void PrescribedDispSlipBCNeumannRC :: scale(double s) +{ + this->dispGradient.times(s); + this->slipField.times(s); + this->slipGradient.times(s); +} + + +void PrescribedDispSlipBCNeumannRC :: assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, + FloatArray *eNorm, + void* lock) +{ + if ( dispGradON ) { + this->assembleVectorStress( answer, tStep, type, mode, s, eNorm ); + } + + if ( slipON ) { + this->assembleVectorBStress(answer, tStep, type, mode, s); + } + + if ( slipGradON ) { + this->assembleVectorRStress( answer, tStep, type, mode, s); + } +} + + +void PrescribedDispSlipBCNeumannRC::assembleVectorStress( FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorm ) +{ + IntArray sigma_loc; // For the displacements and stress respectively + mpSigmaHom->giveLocationArray(mSigmaIds, sigma_loc, s); + + if ( type == ExternalForcesVector ) { + // The external forces have two contributions. On the additional equations for sigma, the load is simply the prescribed gradient. + double rve_size = PrescribedDispSlipHomogenization::domainSize(this->giveDomain(), this->giveSetNumber()); + FloatArray stressLoad; + FloatArray dispGrad; + giveDispGradient(dispGrad); + + double loadLevel = this->giveTimeFunction()->evaluateAtTime(tStep->giveTargetTime()); + stressLoad.beScaled(-rve_size*loadLevel, dispGrad); + + answer.assemble(stressLoad, sigma_loc); + } else if ( type == InternalForcesVector ) { + FloatMatrix Ke; + FloatArray fe_v, fe_s; + FloatArray sigmaHom, e_u; + IntArray loc, masterDofIDs, sigmaMasterDofIDs; + + // Fetch the current values of the stress; + mpSigmaHom->giveUnknownVector(sigmaHom, mSigmaIds, mode, tStep); + // and the master dof ids for sigmadev used for the internal norms + mpSigmaHom->giveMasterDofIDArray(mSigmaIds, sigmaMasterDofIDs); + + // Assemble + Set *setPointer = this->giveDomain()->giveSet(this->set); + const IntArray &boundaries = setPointer->giveBoundaryList(); + for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { + Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); + int boundary = boundaries.at(pos * 2); + + // Fetch the element information; + e->giveLocationArray(loc, s, & masterDofIDs); + e->computeVectorOf(mode, tStep, e_u); + this->integrateTangentStress(Ke, e, boundary); + + // We just use the tangent, less duplicated code (the addition of sigmaDev is linear). + fe_v.beProductOf(Ke, e_u); + fe_s.beTProductOf(Ke, sigmaHom); + + // Note: The terms appear negative in the equations: + fe_v.negated(); + fe_s.negated(); + + answer.assemble(fe_s, loc); // Contributions to delta_v equations + answer.assemble(fe_v, sigma_loc); // Contribution to delta_s_i equations + if ( eNorm != NULL ) { + eNorm->assembleSquared(fe_s, masterDofIDs); + eNorm->assembleSquared(fe_v, sigmaMasterDofIDs); + } + } + } +} + + +void PrescribedDispSlipBCNeumannRC::assembleVectorBStress( FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s ) +{ + IntArray tau_loc; + lmTauHom->giveLocationArray(lmTauIds, tau_loc, s); + + if ( type == ExternalForcesVector ) { + // The external forces have two contributions. On the additional equations for tau, the load is equal to the prescribed slip value. + FloatArray bStressLoad; + FloatArray slipVec; + this->giveSlipField(slipVec); + + double loadLevel = this->giveTimeFunction()->evaluateAtTime(tStep->giveTargetTime()); + bStressLoad.beScaled(loadLevel, slipVec); + + answer.assemble(bStressLoad, tau_loc); + } else if ( type == InternalForcesVector ) { + FloatMatrix Ktau, Ktau_el; + FloatArray fe_tau, fe_u; + FloatArray tau, u_s, u_c; + IntArray loc, loc_s, loc_c, masterDofIDs; + + // Fetch the current values of the Lagrange multiplier; + lmTauHom->giveUnknownVector(tau, lmTauIds, mode, tStep); + + // CONTRIBUTION FROM REINFORCEMENT + FloatMatrix C; + double gammaBoxInt = computeInterfaceLength(rebarSets); + this->computeWeightMatrix(C, rebarSets); + Ktau.clear(); + Ktau_el.clear(); + fe_tau.clear(); + fe_u.clear(); + + for (int i = 0; i < rebarSets.giveSize(); ++i) { + Set *steelSet = this->giveDomain()->giveSet(rebarSets.at(i+1)); + + for (int pos = 1; pos <= steelSet->giveElementList().giveSize(); ++pos) { + Element *es = this->giveDomain()->giveElement( steelSet->giveElementList().at(pos) ); + + // Fetch the element information; + es->giveLocationArray(loc_s, s, &masterDofIDs); + + // Fetch the nodal displacements + // since computeVectorOf gives the unknown vector in local coordinate system, it needs to be rotated to global coordinates + FloatMatrix G2L; + es->computeGtoLRotationMatrix(G2L); + es->computeVectorOf(mode, tStep, u_s); + u_s.rotatedWith(G2L, 't'); + + //Compute the stiffness matrix expansion + this->integrateTangentBStressSteel(Ktau_el, es, rebarSets.at(i+1)); + Ktau.beTProductOf(C, Ktau_el); + Ktau.times(1/gammaBoxInt); + + //Compute the contribution to internal force vector + fe_u.beTProductOf(Ktau, tau); + fe_tau.beProductOf(Ktau, u_s); + + //Assemble + answer.assemble(fe_u, loc_s); + answer.assemble(fe_tau, tau_loc); + } + } + Ktau.clear(); + fe_tau.clear(); + fe_u.clear(); + + // CONTRIBUTION FROM CONCRETE + Set *concreteSet = this->giveDomain()->giveSet(concreteVolSet); + double omegaBox = PrescribedDispSlipHomogenization::domainSize(this->giveDomain(), this->giveSetNumber()); + + for ( int pos = 1; pos <= concreteSet->giveElementList().giveSize(); ++pos) { + Element* ec = this->giveDomain()->giveElement( concreteSet->giveElementList().at(pos) ); + + // Fetch the element information; + ec->giveLocationArray(loc_c, s, &masterDofIDs); + + // Fetch the nodal displacements + ec->computeVectorOf(mode, tStep, u_c); + + //Compute the stiffness matrix expansion + this->integrateTangentBStressConcrete(Ktau, ec); + Ktau.times(1/omegaBox); + + //Compute the contribution to internal force vector + fe_u.beTProductOf(Ktau, tau); + fe_tau.beProductOf(Ktau, u_c); + + // Note: The terms appear negative in the equations: + fe_u.negated(); + fe_tau.negated(); + + //Assemble + answer.assemble(fe_u, loc_c); + answer.assemble(fe_tau, tau_loc); + } + } +} + + +void PrescribedDispSlipBCNeumannRC::assembleVectorRStress( FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s ) +{ + IntArray sigmaS_loc; + lmSigmaSHom->giveLocationArray(lmSigmaSIds, sigmaS_loc, s); + + if ( type == ExternalForcesVector ) { + // The external forces have two contributions. On the additional equations for sigmaS, the load is equal to the prescribed slip gradient value. + FloatArray rStressLoad; + FloatArray slipGrad; + this->giveSlipGradient(slipGrad); + slipGrad.resizeWithValues(2); + + double loadLevel = this->giveTimeFunction()->evaluateAtTime(tStep->giveTargetTime()); + rStressLoad.beScaled(loadLevel, slipGrad); + + answer.assemble(rStressLoad, sigmaS_loc); + } else if ( type == InternalForcesVector ) { + FloatMatrix Ksig, Ksig_el; + FloatArray fe_sig, fe_u; + FloatArray sigmaS, u_s, u_c; + IntArray loc, loc_s, loc_c, masterDofIDs; + + // Fetch the current values of the Lagrange multiplier; + lmSigmaSHom->giveUnknownVector(sigmaS, lmSigmaSIds, mode, tStep); + + // CONTRIBUTION FROM REINFORCEMENT + FloatMatrix C; + double gammaBoxInt = computeInterfaceLength(rebarSets); + this->computeWeightMatrix(C, rebarSets); +// C.resizeWithData(4,4); + Ksig.clear(); + Ksig_el.clear(); + fe_sig.clear(); + fe_u.clear(); + + for ( int i = 0; i < rebarSets.giveSize(); ++i ) { + Set *steelSet = this->giveDomain()->giveSet(rebarSets.at(i+1)); + + for (int pos = 1; pos <= steelSet->giveElementList().giveSize(); ++pos) { + Element *es = this->giveDomain()->giveElement( steelSet->giveElementList().at(pos) ); + + // Fetch the element information; + es->giveLocationArray(loc_s, s, &masterDofIDs); + + // Fetch the nodal displacements + // since computeVectorOf gives the unknown vector in local coordinate system, it needs to be rotated to global coordinates + FloatMatrix G2L; + es->computeGtoLRotationMatrix(G2L); + es->computeVectorOf(mode, tStep, u_s); + u_s.rotatedWith(G2L, 't'); + + //Compute the stiffness matrix expansion + this->integrateTangentRStressSteel(Ksig_el, es, rebarSets.at(i+1)); + Ksig.beTProductOf(C, Ksig_el); + Ksig.times(1/gammaBoxInt); + + //Compute the contribution to internal force vector + fe_u.beTProductOf(Ksig, sigmaS); + fe_sig.beProductOf(Ksig, u_s); + + //Assemble + answer.assemble(fe_u, loc_s); + answer.assemble(fe_sig, sigmaS_loc); + } + } + + Ksig.clear(); + fe_sig.clear(); + fe_u.clear(); + + // CONTRIBUTION FROM CONCRETE + double omegaBox = PrescribedDispSlipHomogenization::domainSize(this->giveDomain(), this->giveSetNumber()); + Set *concreteBoundSet = this->giveDomain()->giveSet(this->set); + const IntArray &boundaries = concreteBoundSet->giveBoundaryList(); + + for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { + Element *ec = this->giveDomain()->giveElement( boundaries.at(pos*2-1) ); + int boundary = boundaries.at(pos*2); + + // Fetch the element information; + ec->giveLocationArray(loc_c, s, &masterDofIDs); + + // Fetch the nodal displacements + ec->computeVectorOf(mode, tStep, u_c); + + //Compute the stiffness matrix expansion + this->integrateTangentRStressConcrete(Ksig, ec, boundary); + Ksig.times(1/omegaBox); + + //Compute the contribution to internal force vector + fe_u.beTProductOf(Ksig, sigmaS); + fe_sig.beProductOf(Ksig, u_c); + + // Note: The terms appear negative in the equations: + fe_u.negated(); + fe_sig.negated(); + + //Assemble + answer.assemble(fe_u, loc_c); + answer.assemble(fe_sig, sigmaS_loc); + } + } +} + +void PrescribedDispSlipBCNeumannRC :: assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, + const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, + double scale, + void* lock) +{ + if ( type == TangentStiffnessMatrix || type == SecantStiffnessMatrix || type == ElasticStiffnessMatrix ) { + if ( dispGradON ) { + this->assembleOnStress(answer, r_s, c_s, scale ); + } + + if ( slipON ) { + this->assembleOnTransferStress(answer, r_s, c_s, scale); + } + + if ( slipGradON ) { + this->assembleOnReinfStress(answer, r_s, c_s, scale); + } + } else { + OOFEM_LOG_DEBUG("Skipping assembly in PrescribedDispSlipBCNeumann::assemble()."); + } +} + + + +void PrescribedDispSlipBCNeumannRC :: giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) +{ + int i = 0; + if ( dispGradON ) { + IntArray loc_r, loc_c, sigma_loc_r, sigma_loc_c; + + // Fetch the columns/rows for the stress contributions; + mpSigmaHom->giveLocationArray( mSigmaIds, sigma_loc_r, r_s ); + mpSigmaHom->giveLocationArray( mSigmaIds, sigma_loc_c, c_s ); + + Set *set = this->giveDomain()->giveSet( this->set ); + const IntArray &boundaries = set->giveBoundaryList(); + + rows.resize( boundaries.giveSize() ); + cols.resize( boundaries.giveSize() ); + for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { + Element *e = this->giveDomain()->giveElement( boundaries.at( pos * 2 - 1 ) ); + + // Here, we could use only the nodes actually located on the boundary, but we don't. + // Instead, we use all nodes belonging to the element, which is allowed because the + // basis functions related to the interior nodes will be zero on the boundary. + // Obviously, this is less efficient, so why do we want to do it this way? + // Because it is easier when XFEM enrichments are present. /ES + e->giveLocationArray( loc_r, r_s ); + e->giveLocationArray( loc_c, c_s ); + + // For most uses, loc_r == loc_c, and sigma_loc_r == sigma_loc_c. + rows[i] = loc_r; + cols[i] = sigma_loc_c; + i++; + // and the symmetric part (usually the transpose of above) + rows[i] = sigma_loc_r; + cols[i] = loc_c; + i++; + } + } + + if ( slipON ) { + IntArray loc_r, loc_c, tau_loc_r, tau_loc_c; + + // Fetch the columns/rows for the transfer stress contributions; + lmTauHom->giveLocationArray(lmTauIds, tau_loc_r, r_s); + lmTauHom->giveLocationArray(lmTauIds, tau_loc_c, c_s); + + Set *concreteSet = this->giveDomain()->giveSet(this->concreteVolSet); + const IntArray &conEl = concreteSet->giveElementList(); + IntArray steelEl; + + for ( int j = 1; j <= this->rebarSets.giveSize(); ++j ) { + steelEl.followedBy(this->giveDomain()->giveSet(rebarSets.at(j))->giveElementList()); + } + + rows.resize( 2*steelEl.giveSize() + 2*conEl.giveSize() + i); + cols.resize( 2*steelEl.giveSize() + 2*conEl.giveSize() + i); + //Contribution from steel + for ( int pos = 1; pos <= steelEl.giveSize(); ++pos ) { + Element *e = this->giveDomain()->giveElement(steelEl.at(pos)); + + e->giveLocationArray(loc_r, r_s); + e->giveLocationArray(loc_c, c_s); + + // For most uses, loc_r == loc_c, and tau_loc_r == tau_loc_c. + rows [ i ] = loc_r; + cols [ i ] = tau_loc_c; + i++; + // and the symmetric part (usually the transpose of above) + rows [ i ] = tau_loc_r; + cols [ i ] = loc_c; + i++; + } + + //Contribution from concrete + for ( int pos = 1; pos <= conEl.giveSize(); ++pos ) { + Element *e = this->giveDomain()->giveElement(conEl.at(pos)); + + e->giveLocationArray(loc_r, r_s); + e->giveLocationArray(loc_c, c_s); + + // For most uses, loc_r == loc_c, and tau_loc_r == tau_loc_c. + rows [ i ] = loc_r; + cols [ i ] = tau_loc_c; + i++; + // and the symmetric part (usually the transpose of above) + rows [ i ] = tau_loc_r; + cols [ i ] = loc_c; + i++; + } + } + + if ( slipGradON ) { + IntArray loc_r, loc_c, sigmaS_loc_r, sigmaS_loc_c; + + // Fetch the columns/rows for the reinforcement stress contributions; + lmSigmaSHom->giveLocationArray(lmSigmaSIds, sigmaS_loc_r, r_s); + lmSigmaSHom->giveLocationArray(lmSigmaSIds, sigmaS_loc_c, c_s); + + Set *concreteSet = this->giveDomain()->giveSet(this->set); + const IntArray &boundaries = concreteSet->giveBoundaryList(); + IntArray steelEl; + + for ( int i = 1; i <= this->rebarSets.giveSize(); ++i ) { + steelEl.followedBy(this->giveDomain()->giveSet(rebarSets.at(i))->giveElementList()); + } + + rows.resize( 2*steelEl.giveSize() + boundaries.giveSize() + i ); + cols.resize( 2*steelEl.giveSize() + boundaries.giveSize() + i ); + //Contribution from steel + for ( int pos = 1; pos <= steelEl.giveSize(); ++pos ) { + Element *e = this->giveDomain()->giveElement(steelEl.at(pos)); + + e->giveLocationArray(loc_r, r_s); + e->giveLocationArray(loc_c, c_s); + + // For most uses, loc_r == loc_c, and sigmaS_loc_r == sigmaS_loc_c. + rows [ i ] = loc_r; + cols [ i ] = sigmaS_loc_c; + i++; + // and the symmetric part (usually the transpose of above) + rows [ i ] = sigmaS_loc_r; + cols [ i ] = loc_c; + i++; + } + + //Contribution from concrete + for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { + Element *e = this->giveDomain()->giveElement( boundaries.at(pos*2-1) ); + + e->giveLocationArray(loc_r, r_s); + e->giveLocationArray(loc_c, c_s); + + // For most uses, loc_r == loc_c, and sigmaS_loc_r == sigmaS_loc_c. + rows [ i ] = loc_r; + cols [ i ] = sigmaS_loc_c; + i++; + // and the symmetric part (usually the transpose of above) + rows [ i ] = sigmaS_loc_r; + cols [ i ] = loc_c; + i++; + } + } +} + +void PrescribedDispSlipBCNeumannRC :: computeStress(FloatArray &sigma, TimeStep *tStep) +{ + if ( dispGradON ) { + double volRVE = this->domainSize( this->giveDomain(), this->giveSetNumber() ); + double areaRVE = PrescribedDispSlipHomogenization::domainSize( this->giveDomain(), this->giveSetNumber() ); + double thick = volRVE / areaRVE; + mpSigmaHom->giveUnknownVector( sigma, mSigmaIds, VM_Total, tStep ); + sigma.times( 1 / thick ); + } +} + + +void PrescribedDispSlipBCNeumannRC::computeTransferStress( FloatArray &bStress, TimeStep *tStep ) +{ + if ( slipON ) { + double volRVE = this->domainSize( this->giveDomain(), this->giveSetNumber() ); + lmTauHom->giveUnknownVector( bStress, lmTauIds, VM_Total, tStep ); + bStress.times( -1 / volRVE ); + } +} + + +void PrescribedDispSlipBCNeumannRC::computeReinfStress( FloatArray &rStress, TimeStep *tStep ) +{ + if ( slipGradON ) { + double volRVE = this->domainSize( this->giveDomain(), this->giveSetNumber() ); + lmSigmaSHom->giveUnknownVector( rStress, lmSigmaSIds, VM_Total, tStep ); + rStress.resizeWithValues(4); + rStress.times( -1 / volRVE ); + } +} + + +void PrescribedDispSlipBCNeumannRC :: computeTangent(FloatMatrix &tangent, TimeStep *tStep) +{ + OOFEM_ERROR("Tangent not implemented") +} + + +void PrescribedDispSlipBCNeumannRC :: integrateTangentStress(FloatMatrix &oTangent, Element *e, int iBndIndex) +{ + FloatArray normal, n; + FloatMatrix nMatrix, E_n; + FloatMatrix contrib; + + FEInterpolation *interp = e->giveInterpolation(); // Geometry interpolation + + int nsd = e->giveDomain()->giveNumberOfSpatialDimensions(); + + // Interpolation order + int order = interp->giveInterpolationOrder(); + std :: unique_ptr< IntegrationRule > ir; + + ir = interp->giveBoundaryIntegrationRule(order, iBndIndex); + + oTangent.clear(); + + for ( auto &gp: *ir ) { + const FloatArray &lcoords = gp->giveNaturalCoordinates(); + FEIElementGeometryWrapper cellgeo(e); + + // Evaluate the normal; + double detJ = interp->boundaryEvalNormal(normal, iBndIndex, lcoords, cellgeo); + + // Compute global coordinates of Gauss point + FloatArray globalCoord; + interp->boundaryLocal2Global(globalCoord, iBndIndex, lcoords, cellgeo); + + // Compute local coordinates on the element + FloatArray bulkElLocCoords; + e->computeLocalCoordinates(bulkElLocCoords, globalCoord); + + // Evaluate the velocity/displacement coefficients + interp->evalN(n, bulkElLocCoords, cellgeo); + nMatrix.beNMatrixOf(n, nsd); + + E_n.resize(nsd*nsd, nsd); + E_n.zero(); + + if ( nsd == 3 ) { + E_n.at(1, 1) = normal.at(1); + E_n.at(2, 2) = normal.at(2); + E_n.at(3, 3) = normal.at(3); + E_n.at(4, 1) = normal.at(2); + E_n.at(5, 1) = normal.at(3); + E_n.at(6, 2) = normal.at(3); + E_n.at(7, 2) = normal.at(1); + E_n.at(8, 3) = normal.at(1); + E_n.at(9, 3) = normal.at(2); + } else if ( nsd == 2 ) { + E_n.at(1, 1) = normal.at(1); + E_n.at(2, 2) = normal.at(2); + E_n.at(3, 1) = normal.at(2); + E_n.at(4, 2) = normal.at(1); + } else { + E_n.at(1, 1) = normal.at(1); + } + + contrib.beProductOf(E_n, nMatrix); + + oTangent.add(detJ * gp->giveWeight(), contrib); + } +} + + +void PrescribedDispSlipBCNeumannRC::integrateTangentBStressSteel( FloatMatrix &oTangent, Element *e, const int &rebarSet ) +{ + FloatMatrix Nstau, Ns, contrib; + double Ss; + IntArray DofMask; + + //Get number of DOFs per DofManager + e->giveDofManDofIDMask(1, DofMask); + int ndof = DofMask.giveSize(); + + FEInterpolation *interp = e->giveInterpolation(); + int order = interp->giveInterpolationOrder(); + std :: unique_ptr< IntegrationRule > ir; + ir = interp->giveIntegrationRule(order); + + oTangent.clear(); + + for ( auto &gp : *ir ) { + const FloatArray &lcoords = gp->giveNaturalCoordinates(); + FEIElementGeometryWrapper cellgeo(e); + + //Compute shape functions + FloatArray nu; + interp->evalN(nu, lcoords, cellgeo); + Ns.beNMatrixOf(nu, ndof); + + //Constant traction interpolation + this->computeRebarDyad(Nstau, rebarSet); + Nstau.resizeWithData(3,2); + + //Compute rebar perimeter + CrossSection *cs = e->giveCrossSection(); + Ss = sqrt(4 * cs->give(CS_Area, gp) * M_PI); + + //Compute the integral + contrib.beTProductOf(Nstau, Ns); + contrib.times(Ss); + double detJ = interp->giveTransformationJacobian(lcoords, cellgeo); + oTangent.add(detJ * gp->giveWeight(), contrib); + } +} + + +void PrescribedDispSlipBCNeumannRC::integrateTangentBStressConcrete( FloatMatrix &oTangent, Element *e ) +{ + FloatMatrix Nctau, Nc, contrib; + IntArray DofMask; + + //Get number of DOFs per DofManager + e->giveDofManDofIDMask(1, DofMask); + int ndof = DofMask.giveSize(); + + FEInterpolation *interp = e->giveInterpolation(); + int order = interp->giveInterpolationOrder(); + std :: unique_ptr< IntegrationRule > ir; + ir = interp->giveIntegrationRule(order); + + oTangent.clear(); + Nctau.resize(ndof,ndof); + + for ( auto &gp : *ir ) { + const FloatArray &lcoords = gp->giveNaturalCoordinates(); + FEIElementGeometryWrapper cellgeo(e); + + //Compute shape functions + FloatArray nu; + interp->evalN(nu, lcoords, cellgeo); + Nc.beNMatrixOf(nu, ndof); + + //Constant traction interpolation + Nctau.beUnitMatrix(); + + //Compute the integral + contrib.beTProductOf(Nctau, Nc); + double detJ = interp->giveTransformationJacobian(lcoords, cellgeo); + oTangent.add(detJ * gp->giveWeight(), contrib); + } +} + + +void PrescribedDispSlipBCNeumannRC::integrateTangentRStressSteel( FloatMatrix &oTangent, Element *e, const int &rebarSet ) +{ + FloatMatrix Nssig, Bs, contrib; + double Ss; + IntArray DofMask; + + //Get number of DOFs per DofManager + e->giveDofManDofIDMask(1, DofMask); + + FEInterpolation *interp = e->giveInterpolation(); + int order = interp->giveInterpolationOrder(); + std :: unique_ptr< IntegrationRule > ir; + ir = interp->giveIntegrationRule(order); + //Cast into StructuralElement + StructuralElement *se = dynamic_cast(e); + + oTangent.clear(); + + for ( auto &gp : *ir ) { + const FloatArray &lcoords = gp->giveNaturalCoordinates(); + FEIElementGeometryWrapper cellgeo(e); + + //Compute shape function derivatives + FloatMatrix b; + se->computeBmatrixAt(gp, b); + //TODO: make it element independent; now hardcoded for libeam2d elements + Bs.resize(2,6); + Bs.at(1,1) = b.at(1,1); + Bs.at(2,2) = b.at(1,1); + Bs.at(1,4) = b.at(1,4); + Bs.at(2,5) = b.at(1,4); + + //Constant traction interpolation + this->computeRebarDyad(Nssig, rebarSet); +// Nssig.resizeWithData(2,4); + + //Compute rebar perimeter + CrossSection *cs = e->giveCrossSection(); + Ss = sqrt(4 * cs->give(CS_Area, gp) * M_PI); + + //Compute the integral + contrib.beTProductOf(Nssig, Bs); + contrib.times(Ss); + double detJ = interp->giveTransformationJacobian(lcoords, cellgeo); + oTangent.add(detJ * gp->giveWeight(), contrib); + } +} + + +void PrescribedDispSlipBCNeumannRC::integrateTangentRStressConcrete( FloatMatrix &oTangent, Element *e, int iBndIndex ) +{ + FloatArray normal, n; + FloatMatrix nMatrix, E_n; + FloatMatrix contrib; + + FEInterpolation *interp = e->giveInterpolation(); + + int nsd = e->giveDomain()->giveNumberOfSpatialDimensions(); + + //Interpolation order + int order = interp->giveInterpolationOrder(); + std :: unique_ptr< IntegrationRule > ir = interp->giveBoundaryEdgeIntegrationRule(order, iBndIndex); + + oTangent.clear(); + + for ( auto &gp : *ir ) { + const FloatArray &lcoords = gp->giveNaturalCoordinates(); + FEIElementGeometryWrapper cellgeo(e); + + //Evaluate the normal + double detJ = interp->boundaryEvalNormal(normal, iBndIndex, lcoords, cellgeo); + + //Compute global coordinates of Gauss point + FloatArray globalCoord; + interp->boundaryLocal2Global(globalCoord, iBndIndex, lcoords, cellgeo); + + //Compute local coordinates on the element + FloatArray bulkElLocCoords; + e->computeLocalCoordinates(bulkElLocCoords, globalCoord); + + //Evaluate the shape functions + interp->evalN(n, bulkElLocCoords, cellgeo); + nMatrix.beNMatrixOf(n, nsd); + + E_n.resize(nsd, nsd); + E_n.zero(); + if ( nsd == 3 ) { + E_n.at(1, 1) = normal.at(1); + E_n.at(2, 2) = normal.at(2); + E_n.at(3, 3) = normal.at(3); + } else if ( nsd == 2 ) { + E_n.at(1, 1) = normal.at(1); + E_n.at(2,2) = normal.at(2); + } else { + E_n.at(1, 1) = normal.at(1); + } + + contrib.beProductOf(E_n, nMatrix); + + oTangent.add(detJ * gp->giveWeight(), contrib); + } + +} + + +void PrescribedDispSlipBCNeumannRC::assembleOnStress( SparseMtrx &answer, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale ) +{ + FloatMatrix Ke, KeT; + IntArray loc_r, loc_c, sigma_loc_r, sigma_loc_c; + Set *set = this->giveDomain()->giveSet(this->set); + const IntArray &boundaries = set->giveBoundaryList(); + + // Fetch the columns/rows for the stress contributions; + mpSigmaHom->giveLocationArray(mSigmaIds, sigma_loc_r, r_s); + mpSigmaHom->giveLocationArray(mSigmaIds, sigma_loc_c, c_s); + + + for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { + Element *e = this->giveDomain()->giveElement( boundaries.at(pos * 2 - 1) ); + int boundary = boundaries.at(pos * 2); + + e->giveLocationArray(loc_r, r_s); + e->giveLocationArray(loc_c, c_s); + + this->integrateTangentStress(Ke, e, boundary); + + Ke.negated(); + Ke.times(scale); + KeT.beTranspositionOf(Ke); + + answer.assemble(sigma_loc_r, loc_c, Ke); // Contribution to delta_s_i equations + answer.assemble(loc_r, sigma_loc_c, KeT); // Contributions to delta_v equations + } +} + + +void PrescribedDispSlipBCNeumannRC::assembleOnTransferStress( SparseMtrx &answer, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale ) +{ + FloatMatrix Ke, KeT; + FloatMatrix Ktau; + IntArray loc_r, loc_c, tau_loc_r, tau_loc_c; + + // Fetch the columns/rows for transferr stress contributions; + lmTauHom->giveLocationArray(lmTauIds, tau_loc_r, r_s); + lmTauHom->giveLocationArray(lmTauIds, tau_loc_c, c_s); + + //Contribution from reinforcement + FloatMatrix C; + double gammaBoxInt = computeInterfaceLength(rebarSets); + this->computeWeightMatrix(C, rebarSets); + + for ( int i = 0; i < rebarSets.giveSize(); ++i ) { + Set *steelSet = this->giveDomain()->giveSet(rebarSets.at(i+1)); + + for ( int pos = 1; pos <= steelSet->giveElementList().giveSize(); ++pos ) { + Element *es = this->giveDomain()->giveElement( steelSet->giveElementList().at(pos) ); + + es->giveLocationArray(loc_r, r_s); + es->giveLocationArray(loc_c, c_s); + + this->integrateTangentBStressSteel(Ktau, es, rebarSets.at(i+1)); + Ke.beTProductOf(C, Ktau); + Ke.times(1/gammaBoxInt); + KeT.beTranspositionOf(Ke); + + answer.assemble(tau_loc_r, loc_c, Ke); + answer.assemble(loc_r, tau_loc_c, KeT); + } + } + + Ktau.clear(); + Ke.clear(); + KeT.clear(); + + //Contribution from concrete + Set *concreteSet = this->giveDomain()->giveSet(concreteVolSet); + double omegaBox = PrescribedDispSlipHomogenization::domainSize(this->giveDomain(), this->giveSetNumber()); + + for ( int pos = 1; pos <= concreteSet->giveElementList().giveSize(); ++pos ) { + Element *ec = this->giveDomain()->giveElement( concreteSet->giveElementList().at(pos) ); + + ec->giveLocationArray(loc_r, r_s); + ec->giveLocationArray(loc_c, c_s); + + this->integrateTangentBStressConcrete(Ke, ec); + Ke.times(1/omegaBox); + Ke.negated(); + KeT.beTranspositionOf(Ke); + + answer.assemble(tau_loc_r, loc_c, Ke); + answer.assemble(loc_r, tau_loc_c, KeT); + } +} + + +void PrescribedDispSlipBCNeumannRC::assembleOnReinfStress( SparseMtrx &answer, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale ) +{ + FloatMatrix Ke, KeT; + FloatMatrix Ksig; + IntArray loc_r, loc_c, sigmaS_loc_r, sigmaS_loc_c; + + // Fetch the columns/rows for the stress contributions; + lmSigmaSHom->giveLocationArray(lmSigmaSIds, sigmaS_loc_r, r_s); + lmSigmaSHom->giveLocationArray(lmSigmaSIds, sigmaS_loc_c, c_s); + + //Contribution from reinforcement + FloatMatrix C; + double gammaBoxInt = computeInterfaceLength(rebarSets); + this->computeWeightMatrix(C, rebarSets); +// C.resizeWithData(4,4); + + for ( int i = 0; i < rebarSets.giveSize(); ++i ) { + Set *steelSet = this->giveDomain()->giveSet(rebarSets.at(i+1)); + + for ( int pos = 1; pos <= steelSet->giveElementList().giveSize(); ++pos ) { + Element *es = this->giveDomain()->giveElement( steelSet->giveElementList().at(pos) ); + + es->giveLocationArray(loc_r, r_s); + es->giveLocationArray(loc_c, c_s); + + this->integrateTangentRStressSteel(Ksig, es, rebarSets.at(i+1)); + Ke.beTProductOf(C, Ksig); + Ke.times(1/gammaBoxInt); + KeT.beTranspositionOf(Ke); + + answer.assemble(sigmaS_loc_r, loc_c, Ke); + answer.assemble(loc_r, sigmaS_loc_c, KeT); + } + } + + Ksig.clear(); + Ke.clear(); + KeT.clear(); + + //Contribution from concrete + Set *concreteBoundSet = this->giveDomain()->giveSet(this->set); + const IntArray &boundaries = concreteBoundSet->giveBoundaryList(); + double omegaBox = PrescribedDispSlipHomogenization::domainSize(this->giveDomain(), this->giveSetNumber()); + + for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { + Element *ec = this->giveDomain()->giveElement( boundaries.at(pos*2-1) ); + int boundary = boundaries.at(pos*2); + + ec->giveLocationArray(loc_r, r_s); + ec->giveLocationArray(loc_c, c_s); + + this->integrateTangentRStressConcrete(Ke, ec, boundary); + + Ke.times(1/omegaBox); + Ke.negated(); + KeT.beTranspositionOf(Ke); + + answer.assemble(sigmaS_loc_r, loc_c, Ke); + answer.assemble(loc_r, sigmaS_loc_c, KeT); + } +} + + +void PrescribedDispSlipBCNeumannRC::computeWeightMatrix( FloatMatrix &C, const IntArray &reinfSets ) +{ + ///Assumption: the rebars cross the entire RVE, i.e. they do not end within the RVE + /// - the rebars have circular cross section + double gammaBoxInt = computeInterfaceLength(reinfSets); + FloatMatrix dyadMatrix; + for ( int i = 0; i < reinfSets.giveSize(); ++i ) { + FloatMatrix dya; + double perimeterCoeff = 0; + + Set *set = this->giveDomain()->giveSet(reinfSets.at(i+1)); + for ( int j = 0; j < set->giveElementList().giveSize(); ++j ) { + Element *e = this->giveDomain()->giveElement(set->giveElementList().at(j+1)); + FEInterpolation *interp = e->giveInterpolation(); + int order = interp->giveInterpolationOrder(); + std :: unique_ptr< IntegrationRule > ir; + ir = interp->giveIntegrationRule(order); + + for ( auto &gp : *ir ) { + const FloatArray &lcoords = gp->giveNaturalCoordinates(); + FEIElementGeometryWrapper cellgeo(e); + double detJ = interp->giveTransformationJacobian(lcoords, cellgeo); + CrossSection *cs = e->giveCrossSection(); + double perim = sqrt(4 * cs->give(CS_Area, gp) * M_PI); + perimeterCoeff = perimeterCoeff + perim * detJ * gp->giveWeight(); + } + } + + this->computeRebarDyad(dya, reinfSets.at(i+1)); + dyadMatrix.add(perimeterCoeff, dya); + } + + C.beInverseOf(dyadMatrix); + C.times(gammaBoxInt); +} + + +void PrescribedDispSlipBCNeumannRC::computeRebarDyad( FloatMatrix &dyad, const int &reinfSet ) +{ + ///Assuming that the reinforcement bar remains straight throughout the RVE + ///it is then enough to compute the tangent vector for the first element + + FloatArray e_l; + Set *set = this->giveDomain()->giveSet(reinfSet); + IntArray ellist = set->giveElementList(); + Element *element = this->giveDomain()->giveElement(ellist.at(1)); + FEIElementGeometryWrapper cellgeo(element); + + e_l.resize(2); + e_l.at(1) = cellgeo.giveVertexCoordinates(2).at(1) - cellgeo.giveVertexCoordinates(1).at(1); + e_l.at(2) = cellgeo.giveVertexCoordinates(2).at(2) - cellgeo.giveVertexCoordinates(1).at(2); + e_l.normalize(); + + dyad.beDyadicProductOf(e_l,e_l); +} + + +double PrescribedDispSlipBCNeumannRC::computeInterfaceLength( const IntArray &reinfSets ) +{ + double gamma = 0.; + for ( int i=0; i < reinfSets.giveSize(); ++i ) { + Set *set = this->giveDomain()->giveSet(reinfSets.at(i+1)); + for ( int j=0; j < set->giveElementList().giveSize(); ++j ) { + Element *e = this->giveDomain()->giveElement(set->giveElementList().at(j+1)); + FEInterpolation *interp = e->giveInterpolation(); + int order = interp->giveInterpolationOrder(); + std :: unique_ptr< IntegrationRule > ir; + ir = interp->giveIntegrationRule(order); + + for ( auto &gp : *ir ) { + const FloatArray &lcoords = gp->giveNaturalCoordinates(); + FEIElementGeometryWrapper cellgeo(e); + double detJ = interp->giveTransformationJacobian(lcoords, cellgeo); + gamma = gamma + detJ * gp->giveWeight(); + } + } + } + + return gamma; +} + + +double PrescribedDispSlipBCNeumannRC::domainSize( Domain *d, int set ) +{ + double omegaBox = PrescribedDispSlipHomogenization::domainSize(d, this->giveSetNumber()); + + if ( this->giveDomain()->giveNumberOfSpatialDimensions() == 2 ) { + //assuming that the RVE thickness is constant in 2D + Element *e = this->giveDomain()->giveElement( this->giveDomain()->giveSet( this->giveSetNumber() )->giveBoundaryList().at(1) ); + std::unique_ptr ir = e->giveInterpolation()->giveIntegrationRule( e->giveInterpolation()->giveInterpolationOrder() ); + CrossSection *cs = e->giveCrossSection(); + GaussPoint *gp = ir->getIntegrationPoint(0); + double thickness = cs->give(CS_Thickness, gp); + return omegaBox * thickness; + } else { + return omegaBox; + } +} + +} /* namespace oofem */ diff --git a/src/sm/prescribeddispslipbcneumannrc.h b/src/sm/prescribeddispslipbcneumannrc.h new file mode 100644 index 000000000..fc0e451cf --- /dev/null +++ b/src/sm/prescribeddispslipbcneumannrc.h @@ -0,0 +1,147 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef PRESCRIBEDDISPSLIPBCNEUMANN_H_ +#define PRESCRIBEDDISPSLIPBCNEUMANN_H_ + +#include "prescribeddispsliphomogenization.h" +#include "activebc.h" +#include "dynamicinputrecord.h" + +#include + +#define _IFT_PrescribedDispSlipBCNeumannRC_Name "prescribeddispslipbcneumannrc" +#define _IFT_PrescribedDispSlipBCNeumannRC_ConcreteVolSet "concretevolset" +#define _IFT_PrescribedDispSlipBCNeumannRC_RebarSets "rebarsets" + +namespace oofem { +class Node; +class Element; +/** + * Prescribes macroscopic displacement gradient, reinforcement slip field and slip gradient + * on the reinforced concrete RVE using Neumann boundary conditions, cf. + * Sciegaj, A., Larsson, F., Lundgren, K., Nilenius, F., & Runesson, K. (2019). A multiscale model for reinforced concrete with macroscopic variation of reinforcement slip. Computational Mechanics, 63(2), 139–158. https://doi.org/10.1007/s00466-018-1588-3 + * Macroscopic slip and slip gradient fields are optional (see PrescribedDispSlipHomogenization). + * If not specified, this BC will prescribe only the displacement gradient, i.e., it will work the same was as a PrescribedGradient bc. + * Works with 2D RVEs comprising solid elements (concrete), reinforcement (beam/truss elements) and interface elements in between. + * Used in multiscale analyses of reinforced concrete structures. Currently, only orthogonal reinforcement in X and Y direction is supported. + * + * For the optional slip and slip gradient, input fields concretevolset and rebarsets must be specified. concretevolset is the element set containing + * all concrete elements. rebarsets is an array of sets, each containing all reinforcement bars in one direction. + * + * + * @author Adam Sciegaj + * + */ +class OOFEM_EXPORT PrescribedDispSlipBCNeumannRC : public ActiveBoundaryCondition, public PrescribedDispSlipHomogenization +{ +public: + PrescribedDispSlipBCNeumannRC(int n, Domain *d); + virtual ~PrescribedDispSlipBCNeumannRC(); + + int giveNumberOfInternalDofManagers() override; + DofManager *giveInternalDofManager(int i) override; + + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + + bcType giveType() const override { return UnknownBT; } + + void scale(double s) override; + + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorm=nullptr, void* lock=nullptr) override; + + void assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, + double scale = 1.0, void* lock=nullptr) override; + + void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) override; + + const char *giveClassName() const override { return "PrescribedDispSlipBCNeumannRC"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedDispSlipBCNeumannRC_Name; } + + void computeStress(FloatArray &sigma, TimeStep *tStep) override; + void computeTransferStress(FloatArray &bStress, TimeStep *tStep) override; + void computeReinfStress(FloatArray &rStress, TimeStep *tStep) override; + + void computeTangent(FloatMatrix &tangent, TimeStep *tStep) override; + +protected: + bool dispGradON = false; /// on/off flag specifying whether the displacement gradient should be applied via Neumann BCs + bool slipON = false; /// on/off flag specifying whether the slip field should be applied via Neumann BCs + bool slipGradON = false; /// on/off flag specifying whether the slip gradient should be applied via Neumann BCs + + /// DofManager for effective stress + std :: unique_ptr< Node > mpSigmaHom; + IntArray mSigmaIds; + + /// DofManager for effective transfer stress + std :: unique_ptr< Node > lmTauHom; + IntArray lmTauIds; + + /// DofManager for effective reinforcement membrane stress + std :: unique_ptr< Node > lmSigmaSHom; + IntArray lmSigmaSIds; + + /// Element set containing concrete elements (in the volume of RVE) + int concreteVolSet=0; + /// IntArray containing sets of individual reinforcement bars + IntArray rebarSets; + + void integrateTangentStress(FloatMatrix &oTangent, Element *e, int iBndIndex); + void assembleVectorStress(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorm); + void assembleOnStress(SparseMtrx &answer, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale); + + void integrateTangentBStressSteel(FloatMatrix &oTangent, Element *e, const int &rebarSet); + void integrateTangentBStressConcrete(FloatMatrix &oTangent, Element *e); + void assembleVectorBStress(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s); + void assembleOnTransferStress(SparseMtrx &answer, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale); + + void integrateTangentRStressSteel(FloatMatrix &oTangent, Element *e, const int &rebarSet); + void integrateTangentRStressConcrete(FloatMatrix &oTangent, Element *e, int iBndIndex); + void assembleVectorRStress(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, const UnknownNumberingScheme &s); + void assembleOnReinfStress(SparseMtrx &answer, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale); + + void computeWeightMatrix(FloatMatrix &C, const IntArray &reinfSets); + void computeRebarDyad(FloatMatrix &dyad, const int &reinfSet); + double computeInterfaceLength(const IntArray &reinfSets); + + virtual double domainSize(Domain *d, int set) override; +}; +} /* namespace oofem */ + +#endif /* PRESCRIBEDDISPSLIPBCNEUMANN_H_ */ diff --git a/src/sm/prescribeddispsliphomogenization.C b/src/sm/prescribeddispsliphomogenization.C new file mode 100644 index 000000000..4c84368fe --- /dev/null +++ b/src/sm/prescribeddispsliphomogenization.C @@ -0,0 +1,186 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "prescribeddispsliphomogenization.h" +#include "domain.h" +#include "dynamicinputrecord.h" +#include "set.h" +#include "feinterpol.h" +#include "element.h" +#include "mathfem.h" + +namespace oofem { + +void PrescribedDispSlipHomogenization::initializeFrom(InputRecord &ir) +{ + mCenterCoord.resize( dispGradient.giveNumberOfColumns() ); + mCenterCoord.zero(); + dispField.resize( dispGradient.giveNumberOfColumns() ); + dispField.zero(); // prescribed displacement field results only in rigid body motion, no reason to require this input + + IR_GIVE_OPTIONAL_FIELD(ir, dispField, _IFT_PrescribedDispSlipHomogenization_dispField); + IR_GIVE_OPTIONAL_FIELD(ir, dispGradient, _IFT_PrescribedDispSlipHomogenization_dispGrad); + IR_GIVE_OPTIONAL_FIELD(ir, slipField, _IFT_PrescribedDispSlipHomogenization_slipField); + IR_GIVE_OPTIONAL_FIELD(ir, slipGradient, _IFT_PrescribedDispSlipHomogenization_slipGrad); + IR_GIVE_OPTIONAL_FIELD(ir, mCenterCoord, _IFT_PrescribedDispSlipHomogenization_centercoords) +} + +void PrescribedDispSlipHomogenization::giveInputRecord(DynamicInputRecord &input) +{ + input.setField(dispField, _IFT_PrescribedDispSlipHomogenization_dispField); + input.setField(slipField, _IFT_PrescribedDispSlipHomogenization_slipField); + input.setField(dispGradient, _IFT_PrescribedDispSlipHomogenization_dispGrad); + input.setField(slipGradient, _IFT_PrescribedDispSlipHomogenization_slipGrad); + input.setField(mCenterCoord, _IFT_PrescribedDispSlipHomogenization_centercoords); +} + + +void PrescribedDispSlipHomogenization::setDispField( const FloatArray &t ) +{ + int n = t.giveSize(); + if ( n == 2 ) { // Then 2D + this->dispField.resize(2); + this->dispField.at(1) = t.at(1); + this->dispField.at(2) = t.at(2); + } else { + OOFEM_ERROR("Field is in strange format. Should be 2 or 3."); + } +} + + +void PrescribedDispSlipHomogenization::setSlipField( const FloatArray &t ) +{ + int n = t.giveSize(); + if ( n == 2 ) { // Then 2D + this->slipField.resize(2); + this->slipField.at(1) = t.at(1); + this->slipField.at(2) = t.at(2); + } else { + OOFEM_ERROR("Field is in strange format. Should be 2 or 3."); + } +} + + +void PrescribedDispSlipHomogenization::setDispGradient(const FloatArray &t) +{ + int n = t.giveSize(); + if ( n == 3 ) { // Then 2D + this->dispGradient.resize(2, 2); + this->dispGradient.at(1, 1) = t.at(1); + this->dispGradient.at(2, 2) = t.at(2); + // In voigt form, assuming the use of gamma_12 instead of eps_12 + this->dispGradient.at(1, 2) = this->dispGradient.at(2, 1) = t.at(3) * 0.5; + } else { + OOFEM_ERROR("Tensor is in strange voigt format. Should be 3."); + } +} + + +void PrescribedDispSlipHomogenization::setSlipGradient( const FloatArray &t ) +{ + int n = t.giveSize(); + if ( n == 4 ) { // Then 2D + this->slipGradient.resize(2, 2); + this->slipGradient.at(1, 1) = t.at(1); + this->slipGradient.at(2, 2) = t.at(2); + this->slipGradient.at(1, 2) = t.at(3); + this->slipGradient.at(2,1) = t.at(4); + } else { + OOFEM_ERROR("Tensor is in strange voigt format. Should be 4."); + } + +} + + +void PrescribedDispSlipHomogenization::giveDispField( FloatArray &oField ) const +{ + int size = dispField.giveSize(); + if ( size == 2 ) { + oField = { dispField.at(1), dispField.at(2) }; + } else { + OOFEM_ERROR("PrescribedDispSlipHomogenization :: giveDispField not implemented for 3D.\n"); + } +} + + +void PrescribedDispSlipHomogenization::giveSlipField( FloatArray &oField ) const +{ + int size = slipField.giveSize(); + if ( size == 2 ) { + oField = { slipField.at(1), slipField.at(2) }; + } else { + OOFEM_ERROR("PrescribedDispSlipHomogenization :: giveSlipField not implemented for 3D.\n"); + } +} + + +void PrescribedDispSlipHomogenization::giveDispGradient( FloatArray &oGradient ) const +{ + int numRows = dispGradient.giveNumberOfRows(); + if ( numRows == 2 ) { + oGradient = { dispGradient.at(1, 1), dispGradient.at(2, 2), dispGradient.at(1, 2), dispGradient.at(2, 1) }; + } else { + OOFEM_ERROR("PrescribedDispSlipHomogenization :: giveDispGradient not implemented for 3D.\n"); + } +} + + +void PrescribedDispSlipHomogenization::giveSlipGradient( FloatArray &oGradient ) const +{ + int numRows = slipGradient.giveNumberOfRows(); + if ( numRows == 2 ) { + oGradient = { slipGradient.at(1, 1), slipGradient.at(2, 2), slipGradient.at(1, 2), slipGradient.at(2, 1) }; + } else { + OOFEM_ERROR("PrescribedDispSlipHomogenization :: giveSlipGradient not implemented for 3D.\n"); + } +} + + +double PrescribedDispSlipHomogenization::domainSize(Domain *d, int setNum) +{ + int nsd = d->giveNumberOfSpatialDimensions(); + double domain_size = 0.0; + // This requires the boundary to be consistent and ordered correctly. + Set *set = d->giveSet(setNum); + const IntArray &boundaries = set->giveBoundaryList(); + + for ( int pos = 1; pos <= boundaries.giveSize() / 2; ++pos ) { + Element *e = d->giveElement( boundaries.at(pos * 2 - 1) ); + int boundary = boundaries.at(pos * 2); + FEInterpolation *fei = e->giveInterpolation(); + domain_size += fei->evalNXIntegral( boundary, FEIElementGeometryWrapper(e) ); + } + return fabs(domain_size / nsd); +} +} /* namespace oofem */ diff --git a/src/sm/prescribeddispsliphomogenization.h b/src/sm/prescribeddispsliphomogenization.h new file mode 100644 index 000000000..5c6b38768 --- /dev/null +++ b/src/sm/prescribeddispsliphomogenization.h @@ -0,0 +1,112 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef prescribeddispsliphomogenization_h +#define prescribeddispsliphomogenization_h + +#include "inputrecord.h" +#include "floatarray.h" +#include "floatmatrix.h" + +#include "error.h" + + +///@name Input fields for PrescribedDispSlipHomogenization +//@{ +#define _IFT_PrescribedDispSlipHomogenization_dispField "disp" +#define _IFT_PrescribedDispSlipHomogenization_dispGrad "dispgrad" +#define _IFT_PrescribedDispSlipHomogenization_slipField "slip" +#define _IFT_PrescribedDispSlipHomogenization_slipGrad "slipgrad" +#define _IFT_PrescribedDispSlipHomogenization_centercoords "ccoord" +//@} + +namespace oofem { +class TimeStep; +class DynamicInputRecord; +class Domain; + +/** + * Class for homogenization of multiple applied gradients and fields. + * Specifically, applied to boundary conditions in multiscale analysis of reinfoced concrete structure + * with displacement and reinforcement slip fields at the macroscale. + * Currently implemented only for 2D problems. + * + * @author Adam Sciegaj + */ +class OOFEM_EXPORT PrescribedDispSlipHomogenization +{ +protected: + /// Prescribed gradients + FloatMatrix dispGradient; + FloatMatrix slipGradient; + + /// Prescribed fields + FloatArray dispField; + FloatArray slipField; + + /// Center coordinates + FloatArray mCenterCoord; + +public: + PrescribedDispSlipHomogenization() { } + virtual ~PrescribedDispSlipHomogenization() { } + + virtual void initializeFrom(InputRecord &ir); + virtual void giveInputRecord(DynamicInputRecord &input); + + // Methods for field homogenization implemented by respective BCs + virtual void computeStress(FloatArray &stress, TimeStep *tStep) = 0; + virtual void computeTransferStress(FloatArray &bStress, TimeStep *tStep) = 0; + virtual void computeReinfStress(FloatArray &rStress, TimeStep *tStep) = 0; + + virtual void computeTangent(FloatMatrix &tangent, TimeStep *tStep) = 0; + + virtual void setDispField(const FloatArray &t); + virtual void setSlipField(const FloatArray &t); + virtual void setDispGradient(const FloatArray &t); + virtual void setSlipGradient(const FloatArray &t); + + void giveDispField(FloatArray &oField) const; + void giveSlipField(FloatArray &oField) const; + void giveDispGradient(FloatArray &oGradient) const; + void giveSlipGradient(FloatArray &oGradient) const; + + virtual void setCenterCoordinate(FloatArray &x) { mCenterCoord = x; } + FloatArray &giveCenterCoordinate() { return mCenterCoord; } + + virtual double domainSize(Domain *d, int set); +}; +} // end namespace oofem + +#endif // prescribeddispsliphomogenization_h diff --git a/src/sm/prescribeddispslipmultiple.C b/src/sm/prescribeddispslipmultiple.C new file mode 100644 index 000000000..702adab65 --- /dev/null +++ b/src/sm/prescribeddispslipmultiple.C @@ -0,0 +1,186 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "prescribeddispslipmultiple.h" +#include "classfactory.h" +#include "node.h" +#include "masterdof.h" +#include "element.h" +#include "feinterpol.h" +#include "feinterpol2d.h" +#include "gausspoint.h" +#include "sparsemtrx.h" +#include "xfem/xfemelementinterface.h" +#include "xfem/integrationrules/discsegintegrationrule.h" +#include "timestep.h" +#include "function.h" +#include "sparselinsystemnm.h" +#include "unknownnumberingscheme.h" +#include "engngm.h" +#include "mathfem.h" +#include "dynamicinputrecord.h" + + +namespace oofem { +REGISTER_BoundaryCondition(PrescribedDispSlipMultiple); + +PrescribedDispSlipMultiple :: PrescribedDispSlipMultiple(int n, Domain *d) : + ActiveBoundaryCondition(n, d), + PrescribedDispSlipHomogenization() +{ +} + +PrescribedDispSlipMultiple :: ~PrescribedDispSlipMultiple() +{ +} + + +void PrescribedDispSlipMultiple :: initializeFrom(InputRecord &ir) +{ + ActiveBoundaryCondition :: initializeFrom(ir); + PrescribedDispSlipHomogenization :: initializeFrom(ir); + IR_GIVE_FIELD(ir, bcs, _IFT_PrescribedDispSlipMultiple_BCs); +} + + +void PrescribedDispSlipMultiple :: giveInputRecord(DynamicInputRecord &input) +{ + ActiveBoundaryCondition :: giveInputRecord(input); + PrescribedDispSlipHomogenization :: giveInputRecord(input); + input.setField(this->bcs, _IFT_PrescribedDispSlipMultiple_BCs); +} + + +void PrescribedDispSlipMultiple::setSlipField( const FloatArray &t ) +{ + this->slipField = t; + for ( int i : this->bcs ) { + auto bc = dynamic_cast(this->giveDomain()->giveBc(i)); + bc->setSlipField(t); + } +} + + +void PrescribedDispSlipMultiple::setDispGradient( const FloatArray &t ) +{ + this->slipGradient = t; + for ( int i : this->bcs ) { + auto bc = dynamic_cast(this->giveDomain()->giveBc(i)); + bc->setDispGradient(t); + } +} + + +void PrescribedDispSlipMultiple::setSlipGradient( const FloatArray &t ) +{ + this->slipGradient = t; + for ( int i : this->bcs ) { + auto bc = dynamic_cast(this->giveDomain()->giveBc(i)); + bc->setSlipGradient(t); + } +} + + +void PrescribedDispSlipMultiple::setCenterCoordinate( FloatArray &x ) +{ + this->mCenterCoord = x; + for ( int i : this->bcs ) { + auto bc = dynamic_cast(this->giveDomain()->giveBc(i)); + bc->setCenterCoordinate(x); + } +} + + +DofManager *PrescribedDispSlipMultiple::giveInternalDofManager( int i ) +{ + for ( int j: this->bcs ) { + auto bc = dynamic_cast(this->giveDomain()->giveBc(j)); + if ( bc != nullptr ) { + return bc->giveInternalDofManager(i); + } + } + return nullptr; +} + + +void PrescribedDispSlipMultiple :: scale(double s) +{ + this->dispField.times(s); + this->dispGradient.times(s); + this->slipField.times(s); + this->slipGradient.times(s); +} + + +void PrescribedDispSlipMultiple :: computeStress(FloatArray &sigma, TimeStep *tStep) +{ + sigma.clear(); + for ( int i : this->bcs ) { + FloatArray tmp; + auto bc = dynamic_cast(this->giveDomain()->giveBc(i)); + bc->computeStress(tmp, tStep); + sigma.add(tmp); + } +} + + +void PrescribedDispSlipMultiple::computeTransferStress( FloatArray &bStress, TimeStep *tStep ) +{ + bStress.clear(); + for ( int i : this->bcs ) { + FloatArray tmp; + auto bc = dynamic_cast(this->giveDomain()->giveBc(i)); + bc->computeTransferStress(tmp, tStep); + bStress.add(tmp); + } +} + + +void PrescribedDispSlipMultiple::computeReinfStress( FloatArray &rStress, TimeStep *tStep ) +{ + rStress.clear(); + for ( int i : this->bcs ) { + FloatArray tmp; + auto bc = dynamic_cast(this->giveDomain()->giveBc(i)); + bc->computeReinfStress(tmp, tStep); + rStress.add(tmp); + } +} + + +void PrescribedDispSlipMultiple :: computeTangent(FloatMatrix &tangent, TimeStep *tStep) +{ + OOFEM_ERROR("Not implemented") +} +} /* namespace oofem */ diff --git a/src/sm/prescribeddispslipmultiple.h b/src/sm/prescribeddispslipmultiple.h new file mode 100644 index 000000000..17610cd02 --- /dev/null +++ b/src/sm/prescribeddispslipmultiple.h @@ -0,0 +1,87 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef PRESCRIBEDDISPSLIPBCMULTIPLE_H_ +#define PRESCRIBEDDISPSLIPBCMULTIPLE_H_ + +#include "prescribeddispsliphomogenization.h" +#include "activebc.h" + +#include + +#define _IFT_PrescribedDispSlipMultiple_Name "prescribeddispslipmultiple" +#define _IFT_PrescribedDispSlipMultiple_BCs "bcs" + +namespace oofem { +class Node; +class Element; +/** + * Allows for imposing multiple boundary conditions of type PrescribedDispSlip on + * the RVE + * + * @author Adam Sciegaj + */ +class OOFEM_EXPORT PrescribedDispSlipMultiple : public ActiveBoundaryCondition, public PrescribedDispSlipHomogenization +{ +public: + PrescribedDispSlipMultiple(int n, Domain *d); + virtual ~PrescribedDispSlipMultiple(); + + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + + bcType giveType() const override { return UnknownBT; } + DofManager *giveInternalDofManager(int i) override; + + void setSlipField(const FloatArray &t) override; + void setDispGradient(const FloatArray &t) override; + void setSlipGradient(const FloatArray &t) override; + void setCenterCoordinate(FloatArray &x) override; + void scale(double s) override; + + const char *giveClassName() const override { return "PrescribedDispSlipMultiple"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedDispSlipMultiple_Name; } + + void computeStress(FloatArray &stress, TimeStep *tStep) override; + void computeTransferStress(FloatArray &bStress, TimeStep *tStep) override; + void computeReinfStress(FloatArray &rStress, TimeStep *tStep) override; + + void computeTangent(FloatMatrix &tangent, TimeStep *tStep) override; + +protected: + IntArray bcs; +}; +} /* namespace oofem */ + +#endif /* PRESCRIBEDDISPSLIPBCMULTIPLE_H_ */ diff --git a/src/sm/prescribedgradientmultiple.C b/src/sm/prescribedgradientmultiple.C new file mode 100644 index 000000000..3048d39d5 --- /dev/null +++ b/src/sm/prescribedgradientmultiple.C @@ -0,0 +1,153 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "prescribedgradientmultiple.h" +#include "classfactory.h" +#include "node.h" +#include "masterdof.h" +#include "element.h" +#include "feinterpol.h" +#include "feinterpol2d.h" +#include "gausspoint.h" +#include "sparsemtrx.h" +#include "xfem/xfemelementinterface.h" +#include "xfem/integrationrules/discsegintegrationrule.h" +#include "timestep.h" +#include "function.h" +#include "sparselinsystemnm.h" +#include "unknownnumberingscheme.h" +#include "engngm.h" +#include "mathfem.h" +#include "dynamicinputrecord.h" + +#ifdef _OPENMP +#include +#endif + +namespace oofem { +REGISTER_BoundaryCondition(PrescribedGradientMultiple); + +PrescribedGradientMultiple :: PrescribedGradientMultiple(int n, Domain *d) : + ActiveBoundaryCondition(n, d), + PrescribedGradientHomogenization() +{ +} + +PrescribedGradientMultiple :: ~PrescribedGradientMultiple() +{ +} + + +void PrescribedGradientMultiple :: initializeFrom(InputRecord &ir) +{ + ActiveBoundaryCondition :: initializeFrom(ir); + PrescribedGradientHomogenization :: initializeFrom(ir); + IR_GIVE_FIELD(ir, bcs, _IFT_PrescribedGradientMultiple_BCs); +} + + +void PrescribedGradientMultiple :: giveInputRecord(DynamicInputRecord &input) +{ + ActiveBoundaryCondition :: giveInputRecord(input); + PrescribedGradientHomogenization :: giveInputRecord(input); + input.setField(this->bcs, _IFT_PrescribedGradientMultiple_BCs); +} + + +void PrescribedGradientMultiple :: setPrescribedGradient( const FloatMatrix &t ) +{ + this->mGradient = t; + for ( int i : this->bcs ) { + auto bc = dynamic_cast(this->giveDomain()->giveBc(i)); + bc->setPrescribedGradient(t); + } +} + + +void PrescribedGradientMultiple :: setPrescribedGradientVoigt( const FloatArray &t ) +{ + PrescribedGradientHomogenization :: setPrescribedGradientVoigt(t); + for ( int i : this->bcs ) { + auto bc = dynamic_cast(this->giveDomain()->giveBc(i)); + bc->setPrescribedGradientVoigt(t); + } +} + + +void PrescribedGradientMultiple::setCenterCoordinate( FloatArray &x ) +{ + this->mCenterCoord = x; + for ( int i : this->bcs ) { + auto bc = dynamic_cast(this->giveDomain()->giveBc(i)); + bc->setCenterCoordinate(x); + } +} + + +DofManager *PrescribedGradientMultiple::giveInternalDofManager( int i ) +{ + for ( int j: this->bcs ) { + auto bc = dynamic_cast(this->giveDomain()->giveBc(j)); + if ( bc != nullptr ) { + return bc->giveInternalDofManager(i); + } + } + return nullptr; +} + + +void PrescribedGradientMultiple :: scale(double s) +{ + this->mGradient.times(s); +} + + +void PrescribedGradientMultiple :: computeField(FloatArray &sigma, TimeStep *tStep) +{ + FloatArray tmp; + sigma.clear(); + for ( int i : this->bcs ) { + auto bc = dynamic_cast(this->giveDomain()->giveBc(i)); + bc->computeField(tmp, tStep); + sigma.add(tmp); + } +} + + +void PrescribedGradientMultiple :: computeTangent(FloatMatrix &tangent, TimeStep *tStep) +{ + OOFEM_ERROR("Not implemented") +} + +} /* namespace oofem */ diff --git a/src/sm/prescribedgradientmultiple.h b/src/sm/prescribedgradientmultiple.h new file mode 100644 index 000000000..016d77a72 --- /dev/null +++ b/src/sm/prescribedgradientmultiple.h @@ -0,0 +1,83 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef PRESCRIBEDGRADIENTBCMULTIPLE_H_ +#define PRESCRIBEDGRADIENTBCMULTIPLE_H_ + +#include "prescribedgradienthomogenization.h" +#include "activebc.h" + +#include + +#define _IFT_PrescribedGradientMultiple_Name "prescribedgradientmultiple" +#define _IFT_PrescribedGradientMultiple_BCs "bcs" + +namespace oofem { +class Node; +class Element; +/** + * Allows for imposing multiple boundary conditions of type PrescribedGradient on + * the RVE + * + * @author Adam Sciegaj + */ +class OOFEM_EXPORT PrescribedGradientMultiple : public ActiveBoundaryCondition, public PrescribedGradientHomogenization +{ +public: + PrescribedGradientMultiple(int n, Domain *d); + virtual ~PrescribedGradientMultiple(); + + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + + bcType giveType() const override { return UnknownBT; } + DofManager *giveInternalDofManager(int i) override; + + void setPrescribedGradient(const FloatMatrix &t) override; + void setPrescribedGradientVoigt(const FloatArray &t) override; + void setCenterCoordinate(FloatArray &x) override; + void scale(double s) override; + + const char *giveClassName() const override { return "PrescribedGradientMultiple"; } + const char *giveInputRecordName() const override { return _IFT_PrescribedGradientMultiple_Name; } + + void computeField(FloatArray &sigma, TimeStep *tStep) override; + void computeTangent(FloatMatrix &tangent, TimeStep *tStep) override; + +protected: + IntArray bcs; +}; +} /* namespace oofem */ + +#endif /* PRESCRIBEDGRADIENTBCMULTIPLE_H_ */ diff --git a/src/sm/strainvector.h b/src/sm/strainvector.h index 1ad173e02..5eb7cd496 100644 --- a/src/sm/strainvector.h +++ b/src/sm/strainvector.h @@ -56,14 +56,14 @@ class OOFEM_EXPORT StrainVector : public StressStrainBaseVector * Computes the principal values of the receiver. * @param answer Principal values. */ - void computePrincipalValues(FloatArray &answer) const; + void computePrincipalValues(FloatArray &answer) const override; /** * Computes the principal values and principal directions of the receiver. * The principal values are ordered from the largest to the smallest. * @param answer Principal values. * @param dir Principal directions (first index refers to component, second index to eigenvalue number). */ - void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir) const; + void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir) const override; /** * Computes the principal direction of the receiver * associated with the maximum principal value. @@ -85,7 +85,7 @@ class OOFEM_EXPORT StrainVector : public StressStrainBaseVector /** * Prints receiver on stdout, useful for debugging */ - void printYourself() const; + void printYourself() const override; /** * Computes the change of volume. * @return @f$ \epsilon_v = \epsilon_1 + \epsilon_2 + \epsilon_3 @f$. @@ -119,7 +119,7 @@ class OOFEM_EXPORT StrainVector : public StressStrainBaseVector protected: void giveTranformationMtrx(FloatMatrix &answer, const FloatMatrix &base, - int transpose = 0) const; + int transpose = 0) const override; }; } // end namespace oofem #endif // strainvector_h diff --git a/src/sm/stressstrainbasevector.C b/src/sm/stressstrainbasevector.C index 0b6be898b..7903ba05a 100644 --- a/src/sm/stressstrainbasevector.C +++ b/src/sm/stressstrainbasevector.C @@ -38,7 +38,7 @@ #include "error.h" #include "datastream.h" #include "materialmode.h" -#include "../sm/Materials/structuralmaterial.h" +#include "sm/Materials/structuralmaterial.h" #include "datastream.h" namespace oofem { diff --git a/src/sm/stressvector.h b/src/sm/stressvector.h index 08e08c7c1..5f376326b 100644 --- a/src/sm/stressvector.h +++ b/src/sm/stressvector.h @@ -58,13 +58,13 @@ class OOFEM_EXPORT StressVector : public StressStrainBaseVector * Member function that computes principal values of receiver (stress vector). * @param answer computed principal values (sorted) */ - void computePrincipalValues(FloatArray &answer) const; + void computePrincipalValues(FloatArray &answer) const override; /** * Computes principal values and directions of receiver vector. * @param answer Computed principal values (sorted). * @param dir Principal directions (stored column wise). */ - void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir) const; + void computePrincipalValDir(FloatArray &answer, FloatMatrix &dir) const override; /** * Computes split of receiver into deviatoric and volumetric part. * @param dev Computed deviatoric part. @@ -79,7 +79,7 @@ class OOFEM_EXPORT StressVector : public StressStrainBaseVector */ void computeDeviatoricVolumetricSum(StressVector &answer, double vol) const; /// Prints receiver on stdout, useful for debugging. - void printYourself() const; + void printYourself() const override; /** * Computes the first invariant I1 of the stress. * @return First invariant. @@ -153,7 +153,7 @@ class OOFEM_EXPORT StressVector : public StressStrainBaseVector protected: void giveTranformationMtrx(FloatMatrix &answer, const FloatMatrix &base, - int transpose = 0) const; + int transpose = 0) const override; }; } // end namespace oofem #endif // stressvector_h diff --git a/src/sm/symmetrybarrier.C b/src/sm/symmetrybarrier.C index f9cc8124a..0d337549b 100644 --- a/src/sm/symmetrybarrier.C +++ b/src/sm/symmetrybarrier.C @@ -52,8 +52,8 @@ SymmetryBarrier :: ~SymmetryBarrier() { } void -SymmetryBarrier :: applyConstraint(const FloatArray &c1, const FloatArray &c2, double &weight, - bool &shieldFlag, NonlocalMaterialExtensionInterface *nei) +SymmetryBarrier :: applyConstraint(const double cl, const FloatArray &c1, const FloatArray &c2, double &weight, + bool &shieldFlag, const NonlocalMaterialExtensionInterface &nei) { // compute node coordinates in barrrier lcs FloatArray mc2(3), help(3); @@ -82,7 +82,7 @@ SymmetryBarrier :: applyConstraint(const FloatArray &c1, const FloatArray &c2, d } // compute weight of mirrored source - weight += nei->computeWeightFunction(c1, mc2); + weight += nei.computeWeightFunction(cl, c1, mc2); } } @@ -104,7 +104,7 @@ SymmetryBarrier :: applyConstraint(const FloatArray &c1, const FloatArray &c2, d } // compute weight of mirrored source - weight += nei->computeWeightFunction(c1, mc2); + weight += nei.computeWeightFunction(cl, c1, mc2); } } @@ -116,15 +116,13 @@ SymmetryBarrier :: applyConstraint(const FloatArray &c1, const FloatArray &c2, d } // compute weight of mirrored source - weight += nei->computeWeightFunction(c1, mc2); + weight += nei.computeWeightFunction(cl, c1, mc2); } } -IRResultType -SymmetryBarrier :: initializeFrom(InputRecord *ir) +void +SymmetryBarrier :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - FloatArray normals; IR_GIVE_FIELD(ir, origin, _IFT_SymmetryBarrier_origin); @@ -165,10 +163,7 @@ SymmetryBarrier :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, mask, _IFT_SymmetryBarrier_activemask); if ( mask.giveSize() != 3 ) { - OOFEM_WARNING("activemask size should be 3"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_SymmetryBarrier_activemask, "size must be 3"); } - - return IRRT_OK; } } // end namespace oofem diff --git a/src/sm/symmetrybarrier.h b/src/sm/symmetrybarrier.h index e3a496525..b1ac75dc4 100644 --- a/src/sm/symmetrybarrier.h +++ b/src/sm/symmetrybarrier.h @@ -73,13 +73,13 @@ class SymmetryBarrier : public NonlocalBarrier /// Destructor. virtual ~SymmetryBarrier(); - virtual void applyConstraint(const FloatArray &c1, const FloatArray &c2, double &weight, - bool &shieldFlag, NonlocalMaterialExtensionInterface *nei); - virtual double calculateMinimumDistanceFromBoundary(const FloatArray &coords) { return 1.e10; } - virtual IRResultType initializeFrom(InputRecord *ir); + void applyConstraint(const double cl, const FloatArray &c1, const FloatArray &c2, double &weight, + bool &shieldFlag, const NonlocalMaterialExtensionInterface &nei) override; + double calculateMinimumDistanceFromBoundary(const FloatArray &coords) override { return 1.e10; } + void initializeFrom(InputRecord &ir) override; - virtual const char *giveInputRecordName() const { return _IFT_SymmetryBarrier_Name; } - virtual const char *giveClassName() const { return "SymmetryBarrier"; } + const char *giveInputRecordName() const override { return _IFT_SymmetryBarrier_Name; } + const char *giveClassName() const override { return "SymmetryBarrier"; } }; } // end namespace oofem #endif // symmetrybarrier_h diff --git a/src/sm/transversereinfconstraint.C b/src/sm/transversereinfconstraint.C new file mode 100644 index 000000000..c1150450a --- /dev/null +++ b/src/sm/transversereinfconstraint.C @@ -0,0 +1,407 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "transversereinfconstraint.h" +#include "classfactory.h" +#include "node.h" +#include "masterdof.h" +#include "element.h" +#include "feinterpol.h" +#include "gausspoint.h" +#include "sparsemtrx.h" +#include "xfem/xfemelementinterface.h" +#include "xfem/integrationrules/discsegintegrationrule.h" +#include "timestep.h" +#include "function.h" +#include "sparselinsystemnm.h" +#include "unknownnumberingscheme.h" +#include "engngm.h" +#include "mathfem.h" + +namespace oofem { +REGISTER_BoundaryCondition(TransverseReinfConstraint); + +TransverseReinfConstraint :: TransverseReinfConstraint(int n, Domain *d) : + ActiveBoundaryCondition(n, d), + lmLambda( new Node(0, d) ) +{ + int dofId = d->giveNextFreeDofID(); + lmLambdaIds.followedBy(dofId); + lmLambda->appendDof( new MasterDof( lmLambda.get(), ( DofIDItem ) ( dofId ) ) ); +} + +TransverseReinfConstraint :: ~TransverseReinfConstraint() +{ +} + + +void TransverseReinfConstraint :: initializeFrom(InputRecord &ir) +{ + IR_GIVE_FIELD(ir, steelElSet, _IFT_TransverseReinfConstraint_SteelElSet); + IR_GIVE_FIELD(ir, conElBoundSet, _IFT_TransverseReinfConstraint_ConElBoundSet); + + return ActiveBoundaryCondition :: initializeFrom(ir); +} + + +void TransverseReinfConstraint :: giveInputRecord(DynamicInputRecord &input) +{ + ActiveBoundaryCondition :: giveInputRecord(input); +} + + +DofManager *TransverseReinfConstraint :: giveInternalDofManager(int i) +{ + return lmLambda.get(); +} + + +void TransverseReinfConstraint :: assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, + FloatArray *eNorm, + void* lock) +{ + IntArray lambda_loc; + lmLambda->giveLocationArray(lmLambdaIds, lambda_loc, s); + + if ( type == ExternalForcesVector ) { + // The external forces have two contributions. On the additional equations for lambda, the load is simply zero. + FloatArray stressLoad = {0}; + answer.assemble(stressLoad, lambda_loc); + } else if ( type == InternalForcesVector ) { + FloatMatrix Klam; + FloatArray fe_lam, fe_u; + FloatArray lambda, u_s, u_c, u; + IntArray loc, loc_s, loc_c, masterDofIDs; + + // Fetch the current values of the Lagrange multiplier; + lmLambda->giveUnknownVector(lambda, lmLambdaIds, mode, tStep); + + // Assemble + Set *steelSet = this->giveDomain()->giveSet(steelElSet); + const IntArray &elements = steelSet->giveElementList(); + + Set *concreteSet = this->giveDomain()->giveSet(conElBoundSet); + const IntArray &boundaries = concreteSet->giveBoundaryList(); + + if ( boundaries.giveSize() == elements.giveSize()*2 ) { + for ( int pos = 1; pos <= elements.giveSize(); ++pos) { + Element *es = this->giveDomain()->giveElement( elements.at(pos) ); + Element *ec = this->giveDomain()->giveElement( boundaries.at(2*pos - 1) ); + int boundary = boundaries.at(2*pos); + + // Fetch the element information; + es->giveLocationArray(loc_s, s); + + // Fetch the nodal displacements + // since computeVectorOf gives the unknown vector in local coordinate system, it needs to be rotated to global coordinates + FloatMatrix G2L; + es->computeGtoLRotationMatrix(G2L); + es->computeVectorOf(mode, tStep, u_s); + u_s.rotatedWith(G2L, 't'); + + //Fetch boundary information + IntArray bndNodes; + bndNodes = ec->giveBoundaryEdgeNodes(boundary); + ec->giveBoundaryLocationArray(loc_c, bndNodes, s, &masterDofIDs); + masterDofIDs.resizeWithValues(2); //hack to get corresponding masterDofIDs in computeBoundaryVectorOf + ec->computeBoundaryVectorOf(bndNodes, masterDofIDs, mode, tStep, u_c); + + //Assemble the location and u arrays + loc=loc_s; + loc.followedBy(loc_c); + + u=u_s; + u.append(u_c); + + //Compute the stiffness matrix expansion + this->integrateTangent(Klam, es, ec, boundary); + + //Compute the contribution to internal force vector + fe_lam.beProductOf(Klam, u); + fe_u.beTProductOf(Klam, lambda); + + //Negate the terms for symmetry + fe_lam.negated(); + fe_u.negated(); + + //Assemble + answer.assemble(fe_u, loc); + answer.assemble(fe_lam, lambda_loc); + } + } else { + OOFEM_ERROR("Steel/concrete element mismatch") + } + } +} + +void TransverseReinfConstraint :: assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, + const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, + double scale, + void* lock) +{ + if ( type == TangentStiffnessMatrix || type == SecantStiffnessMatrix || type == ElasticStiffnessMatrix ) { + FloatMatrix Klam, KlamT; + IntArray loc_r, loc_c, lambda_loc_r, lambda_loc_c; + IntArray loc_us_r, loc_us_c, loc_uc_r, loc_uc_c; + IntArray masterDofIDs; + + //Fetch the rows/columns for the Lagrange multiplier contributions + lmLambda->giveLocationArray(lmLambdaIds, lambda_loc_r, r_s); + lmLambda->giveLocationArray(lmLambdaIds, lambda_loc_c, c_s); + + //Contributions from steel + Set *steelSet = this->giveDomain()->giveSet(steelElSet); + const IntArray &elements = steelSet->giveElementList(); + + //Contributions from concrete + Set *concreteSet = this->giveDomain()->giveSet(conElBoundSet); + const IntArray &boundaries = concreteSet->giveBoundaryList(); + + if ( boundaries.giveSize() == elements.giveSize()*2 ) { + for ( int pos = 1; pos <= elements.giveSize(); ++pos) { + Element *es = this->giveDomain()->giveElement( elements.at(pos) ); + Element *ec = this->giveDomain()->giveElement( boundaries.at(2*pos - 1) ); + int boundary = boundaries.at(2*pos); + + // Fetch the element information; + es->giveLocationArray(loc_us_r, r_s); + es->giveLocationArray(loc_us_c, c_s); + + //Fetch boundary information + IntArray bndNodes; + bndNodes = ec->giveBoundaryEdgeNodes(boundary); + ec->giveBoundaryLocationArray(loc_uc_r, bndNodes, r_s, &masterDofIDs); + ec->giveBoundaryLocationArray(loc_uc_c, bndNodes, c_s, &masterDofIDs); + + //Assemble the location arrays + loc_c=loc_us_c; + loc_c.followedBy(loc_uc_c); + loc_r=loc_us_r; + loc_r.followedBy(loc_uc_r); + + //Compute the stiffness matrix expansion + this->integrateTangent(Klam, es, ec, boundary); + + Klam.negated(); + KlamT.beTranspositionOf(Klam); + + answer.assemble(lambda_loc_r, loc_c, Klam); + answer.assemble(loc_r, lambda_loc_c, KlamT); + } + } else { + OOFEM_ERROR("Steel/concrete element mismatch") + } + } else { + OOFEM_LOG_DEBUG("Skipping assembly in TransverseReinfConstraint::assemble().\n"); + } +} + +void TransverseReinfConstraint :: giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) +{ + IntArray loc_us_r, loc_us_c, loc_uc_r, loc_uc_c; + IntArray loc_r, loc_c, lambda_loc_r, lambda_loc_c; + IntArray masterDofIDs; + + // Fetch the columns/rows for the stress contributions; + lmLambda->giveLocationArray(lmLambdaIds, lambda_loc_r, r_s); + lmLambda->giveLocationArray(lmLambdaIds, lambda_loc_c, c_s); + + //Contributions from steel + Set *steelSet = this->giveDomain()->giveSet(steelElSet); + const IntArray &selements = steelSet->giveElementList(); + + //Contributions from concrete + Set *concreteSet = this->giveDomain()->giveSet(conElBoundSet); + const IntArray &boundaries = concreteSet->giveBoundaryList(); + + if ( boundaries.giveSize() == selements.giveSize()*2 ) { + rows.resize( boundaries.giveSize() + 2*selements.giveSize() ); + cols.resize( boundaries.giveSize() + 2*selements.giveSize() ); + + int i=0; + for ( int pos = 1; pos <= selements.giveSize(); ++pos) { + Element *es = this->giveDomain()->giveElement( selements.at(pos) ); + Element *ec = this->giveDomain()->giveElement( boundaries.at(2*pos - 1) ); + int boundary = boundaries.at(2*pos); + + // Fetch the element information; + es->giveLocationArray(loc_us_r, r_s); + es->giveLocationArray(loc_us_c, c_s); + + //Fetch boundary information + IntArray bndNodes; + bndNodes = ec->giveBoundaryEdgeNodes(boundary); + ec->giveBoundaryLocationArray(loc_uc_r, bndNodes, r_s, &masterDofIDs); + ec->giveBoundaryLocationArray(loc_uc_c, bndNodes, c_s, &masterDofIDs); + + loc_c=loc_us_c; + loc_c.followedBy(loc_uc_c); + loc_r=loc_us_r; + loc_r.followedBy(loc_uc_r); + + // For most uses, loc_us_r == loc_us_c, and lambda_loc_r == lambda_loc_c. + rows [ i ] = loc_r; + cols [ i ] = lambda_loc_c; + i++; + // and the symmetric part (usually the transpose of above) + rows [ i ] = lambda_loc_r; + cols [ i ] = loc_c; + i++; + } + } else { + OOFEM_ERROR("Steel/concrete element mismatch") + } +} + +void TransverseReinfConstraint :: computeField(FloatArray &lambda, TimeStep *tStep) +{ + lmLambda->giveUnknownVector(lambda, lmLambdaIds, VM_Total, tStep); +} + + + +void TransverseReinfConstraint :: integrateTangent(FloatMatrix& oTangent, Element* es, Element* ec, int iBndIndex) +{ + FloatMatrix Kslam, Kclam; + int nslam, nclam, nsd=1; + + //Compute contributions from steel and concrete + this->integrateTangentOnSteel(Kslam, es); + this->integrateTangentOnConcrete(Kclam, ec, iBndIndex); + nslam = Kslam.giveNumberOfColumns(); + nclam = Kclam.giveNumberOfColumns(); + + //Assemble the tangent contribution + oTangent.resize(nsd,nslam + nclam); + for (int i=1; i <= nsd; ++i) { + for (int j=1; j <= nslam; ++j) { + oTangent.at(i,j) = Kslam.at(i,j); + } + for (int j=nslam+1; j <= nslam+nclam; ++j) { + oTangent.at(i,j) = Kclam.at(i,j-nslam); + } + } +} + +void TransverseReinfConstraint :: integrateTangentOnSteel(FloatMatrix& oTangent, Element* e) +{ + //reminder: Kslam must be 1x6 + FloatArray normal; + FloatMatrix Ns, contrib; + IntArray DofMask; + + e->giveDofManDofIDMask(1, DofMask); + int ndof = DofMask.giveSize(); + + FEInterpolation *interp = e->giveInterpolation(); + int order = interp->giveInterpolationOrder(); + std :: unique_ptr< IntegrationRule > ir; + ir = interp->giveIntegrationRule(order); + + oTangent.clear(); + + for (auto &gp : *ir ) { + const FloatArray &lcoords = gp->giveNaturalCoordinates(); + FEIElementGeometryWrapper cellgeo(e); + + FloatArray nu; + interp->evalN(nu, lcoords, cellgeo); + double detJ = interp->boundaryEvalNormal(normal, 1, lcoords, cellgeo); + + //Constant traction interpolation + FloatMatrix Nlam(ndof,1); + // Note: this works only if the reinforcement is horizontal/vertical! + // Regardless of interpolation and direction of normal vector taking an absolute value gives + // consistent direction of Lagrange multiplier in this case. + // Otherwise the order of nodes for the line elements would make a difference (inward/outward pointing normal). + // Ideally, it shouldn't matter in which direction (bottom->up, top->down) the reinforcement elements are defined. + Nlam(0,0) = fabs(normal.at(1)); //x component of LM + Nlam(1,0) = fabs(normal.at(2)); //y component of LM + Nlam(2,0) = 0.; //rotation component of LM + + Ns.beNMatrixOf(nu, ndof); + + contrib.beTProductOf(Nlam,Ns); + oTangent.add(detJ * gp->giveWeight(), contrib); + } +} + +void TransverseReinfConstraint :: integrateTangentOnConcrete(FloatMatrix &oTangent, Element *e, int iBndIndex) +{ + //reminder: Kclam must be 1x4 + FloatArray normal; + FloatMatrix Nc, contrib; + IntArray DofMask; + + e->giveDofManDofIDMask(1, DofMask); + int ndof = DofMask.giveSize(); + + FEInterpolation *interp = e->giveInterpolation(); + int order = interp->giveInterpolationOrder(); + std :: unique_ptr< IntegrationRule > ir; + ir = interp->giveBoundaryIntegrationRule(order, iBndIndex); + + oTangent.clear(); + + for (auto &gp : *ir ) { + const FloatArray &lcoords = gp->giveNaturalCoordinates(); + FEIElementGeometryWrapper cellgeo(e); + + FloatArray nu; + interp->boundaryEvalN(nu, iBndIndex, lcoords, cellgeo); + double detJ = interp->boundaryEvalNormal(normal, iBndIndex, lcoords, cellgeo); + + //Constant traction interpolation + FloatMatrix Nlam(ndof,1); + // Note: this works only if the reinforcement is horizontal/vertical! + // Regardless of interpolation and direction of normal vector taking an absolute value gives + // consistent direction of Lagrange multiplier in this case. + // Otherwise it would make a difference on which side of the reinforcement bar the solid elements are located, + // but it shouldn't matter. + Nlam(0,0) = fabs(normal.at(1)); //x component of LM + Nlam(1,0) = fabs(normal.at(2)); //y component of LM + + Nc.beNMatrixOf(nu, ndof); + + contrib.beTProductOf(Nlam,Nc); + oTangent.add(detJ * gp->giveWeight(), contrib); + oTangent.negated(); //this term is negative in the formulation + } +} +} /* namespace oofem */ diff --git a/src/sm/transversereinfconstraint.h b/src/sm/transversereinfconstraint.h new file mode 100644 index 000000000..f1b47251f --- /dev/null +++ b/src/sm/transversereinfconstraint.h @@ -0,0 +1,107 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2021 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef TRANSVERSEREINFCONSTRAINT_H_ +#define TRANSVERSEREINFCONSTRAINT_H_ + +#include "activebc.h" + +#include + +#define _IFT_TransverseReinfConstraint_Name "transversereinforcementconstraint" +#define _IFT_TransverseReinfConstraint_SteelElSet "steelelset" +#define _IFT_TransverseReinfConstraint_ConElBoundSet "conelboundset" + +namespace oofem { +class Node; +class Element; +/** + * Imposes transverse constraint (only tangential interface jump) on the reinforcement weakly. + * Support for plane stress concrete elements and beam element reinforcement. + * + * Required input fields: + * steelElSet - set number of the reinforcement elements - one per rebar + * conElBoundSet - set number of concrete element boundaries along that rebar + * it doesn't matter if elements left/right from the rebar are chosen + * + * @author Adam Sciegaj + */ +class OOFEM_EXPORT TransverseReinfConstraint : public ActiveBoundaryCondition +{ +public: + TransverseReinfConstraint(int n, Domain *d); + virtual ~TransverseReinfConstraint(); + + int giveNumberOfInternalDofManagers() override { return 1; } + DofManager *giveInternalDofManager(int i) override; + + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + + bcType giveType() const override { return UnknownBT; } + + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorm, void* lock) override; + + void assemble(SparseMtrx &answer, TimeStep *tStep, + CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, + double scale, void* lock) override; + + void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) override; + + const char *giveClassName() const override { return "TransverseReinfConstraint"; } + const char *giveInputRecordName() const override { return _IFT_TransverseReinfConstraint_Name; } + + void computeField(FloatArray &lambda, TimeStep *tStep); + +protected: + /// DOF-manager containing the unknown Lagrange multiplier + std :: unique_ptr< Node > lmLambda; + IntArray lmLambdaIds; + + /// Reinforcement bar element set + int steelElSet = 0; + /// Set of element boundaries along the reinforcement + int conElBoundSet = 0; + + /// Help functions that integrate the tangent contribution from steel and concrete elements. + void integrateTangent(FloatMatrix &oTangent, Element *es, Element *ec, int iBndIndex); + void integrateTangentOnSteel(FloatMatrix &oTangent, Element *e); + void integrateTangentOnConcrete(FloatMatrix &oTangent, Element *e, int iBndIndex); +}; +} /* namespace oofem */ + +#endif /* TRANSVERSEREINFCONSTRAINT_H_ */ diff --git a/src/sm/xfem/enrichmentitems/crack.C b/src/sm/xfem/enrichmentitems/crack.C index 9b8b0218a..d1991ce97 100644 --- a/src/sm/xfem/enrichmentitems/crack.C +++ b/src/sm/xfem/enrichmentitems/crack.C @@ -33,13 +33,13 @@ */ #include "crack.h" #include "classfactory.h" -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" -#include "export/gnuplotexportmodule.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "sm/export/gnuplotexportmodule.h" #include "gausspoint.h" #include "geometry.h" #include "engngm.h" -#include "Materials/structuralfe2material.h" +#include "sm/Materials/structuralfe2material.h" namespace oofem { REGISTER_EnrichmentItem(Crack) @@ -51,9 +51,9 @@ Crack :: Crack(int n, XfemManager *xm, Domain *aDomain) : HybridEI(n, xm, aDomai }; } -IRResultType Crack :: initializeFrom(InputRecord *ir) +void Crack :: initializeFrom(InputRecord &ir) { - return EnrichmentItem :: initializeFrom(ir); + EnrichmentItem :: initializeFrom(ir); } void Crack :: AppendCohesiveZoneGaussPoint(GaussPoint *ipGP) diff --git a/src/sm/xfem/enrichmentitems/crack.h b/src/sm/xfem/enrichmentitems/crack.h index 03bda333b..896f13e3c 100644 --- a/src/sm/xfem/enrichmentitems/crack.h +++ b/src/sm/xfem/enrichmentitems/crack.h @@ -56,14 +56,14 @@ class OOFEM_EXPORT Crack : public HybridEI public: Crack(int n, XfemManager *xm, Domain *aDomain); - virtual const char *giveClassName() const { return "Crack"; } - virtual const char *giveInputRecordName() const { return _IFT_Crack_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "Crack"; } + const char *giveInputRecordName() const override { return _IFT_Crack_Name; } + void initializeFrom(InputRecord &ir) override; void AppendCohesiveZoneGaussPoint(GaussPoint *ipGP); void ClearCohesiveZoneGaussPoints() {mCohesiveZoneGaussPoints.clear(); mCohesiveZoneArcPositions.clear();} - virtual void callGnuplotExportModule(GnuplotExportModule &iExpMod, TimeStep *tStep); + void callGnuplotExportModule(GnuplotExportModule &iExpMod, TimeStep *tStep) override; const std :: vector< GaussPoint * > &giveCohesiveZoneGaussPoints() const { return mCohesiveZoneGaussPoints; } const std :: vector< double > &giveCohesiveZoneArcPositions() const { return mCohesiveZoneArcPositions; } @@ -71,7 +71,7 @@ class OOFEM_EXPORT Crack : public HybridEI void computeCrackIntersectionPoints(Crack &iCrack, std :: vector< FloatArray > &oIntersectionPoints, std :: vector< double > &oArcPositions); void computeArcPoints(const std :: vector< FloatArray > &iIntersectionPoints, std :: vector< double > &oArcPositions); double computeLength(); - virtual int giveDofPoolSize() const; + int giveDofPoolSize() const override; protected: /** diff --git a/src/sm/xfem/enrichmentitems/delamination.C b/src/sm/xfem/enrichmentitems/delamination.C index 1805d886b..aa52fcc17 100644 --- a/src/sm/xfem/enrichmentitems/delamination.C +++ b/src/sm/xfem/enrichmentitems/delamination.C @@ -37,14 +37,14 @@ #include "fracturemanager.h" #include "element.h" #include "dof.h" -#include "../sm/CrossSections/layeredcrosssection.h" +#include "sm/CrossSections/layeredcrosssection.h" #include "dynamicinputrecord.h" #include "dynamicdatareader.h" #include "xfem/enrichmentfunction.h" #include "xfem/propagationlaw.h" #include "xfem/xfemmanager.h" #include "xfem/enrichmentfronts/enrichmentfrontdonothing.h" -#include "Elements/Shells/shell7basexfem.h" +#include "sm/Elements/Shells/shell7basexfem.h" #include "spatiallocalizer.h" namespace oofem { @@ -69,66 +69,62 @@ Delamination :: Delamination(int n, XfemManager *xm, Domain *aDomain) : ListBase this->recoverStresses = true; // default is to recover transverse stresses } -int Delamination :: instanciateYourself(DataReader *dr) +int Delamination :: instanciateYourself(DataReader &dr) { - IRResultType result; // Required by IR_GIVE_FIELD macro std :: string name; // Instantiate enrichment function - InputRecord *mir = dr->giveInputRecord(DataReader :: IR_enrichFuncRec, 1); - result = mir->giveRecordKeywordField(name); + { + auto &mir = dr.giveInputRecord(DataReader :: IR_enrichFuncRec, 1); + mir.giveRecordKeywordField(name); - if ( result != IRRT_OK ) { - mir->report_error(this->giveClassName(), __func__, "", result, __FILE__, __LINE__); - } - - mpEnrichmentFunc = classFactory.createEnrichmentFunction( name.c_str(), 1, this->giveDomain() ); - if ( mpEnrichmentFunc != NULL ) { - mpEnrichmentFunc->initializeFrom(mir); - } else { - OOFEM_ERROR( "failed to create enrichment function (%s)", name.c_str() ); + mpEnrichmentFunc = classFactory.createEnrichmentFunction( name.c_str(), 1, this->giveDomain() ); + if ( mpEnrichmentFunc ) { + mpEnrichmentFunc->initializeFrom(mir); + } else { + OOFEM_ERROR( "failed to create enrichment function (%s)", name.c_str() ); + } } // Instantiate enrichment domain - mir = dr->giveInputRecord(DataReader :: IR_geoRec, 1); - result = mir->giveRecordKeywordField(name); - if ( result != IRRT_OK ) { - mir->report_error(this->giveClassName(), __func__, "", result, __FILE__, __LINE__); - } + { + auto &mir = dr.giveInputRecord(DataReader :: IR_geoRec, 1); + mir.giveRecordKeywordField(name); + + IntArray idList; + IR_GIVE_FIELD(mir, idList, _IFT_ListBasedEI_list); + for ( int i = 1; i <= idList.giveSize(); i++ ) { + this->dofManList.push_back( idList.at(i) ); + } - IntArray idList; - IR_GIVE_FIELD(mir, idList, _IFT_ListBasedEI_list); - for ( int i = 1; i <= idList.giveSize(); i++ ) { - this->dofManList.push_back( idList.at(i) ); + std :: sort( dofManList.begin(), this->dofManList.end() ); + //IR_GIVE_FIELD(ir, this->xi, _IFT_DofManList_DelaminationLevel); } - std :: sort( dofManList.begin(), this->dofManList.end() ); - //IR_GIVE_FIELD(ir, this->xi, _IFT_DofManList_DelaminationLevel); - // Instantiate EnrichmentFront if ( mEnrFrontIndex == 0 ) { - mpEnrichmentFrontStart = new EnrFrontDoNothing(this->giveNumber()); - mpEnrichmentFrontEnd = new EnrFrontDoNothing(this->giveNumber()); + mpEnrichmentFrontStart = std::make_unique(this->giveNumber()); + mpEnrichmentFrontEnd = std::make_unique(this->giveNumber()); } else { std :: string enrFrontNameStart, enrFrontNameEnd; - InputRecord *enrFrontStartIr = dr->giveInputRecord(DataReader :: IR_enrichFrontRec, mEnrFrontIndex); - result = enrFrontStartIr->giveRecordKeywordField(enrFrontNameStart); + auto &enrFrontStartIr = dr.giveInputRecord(DataReader :: IR_enrichFrontRec, mEnrFrontIndex); + enrFrontStartIr.giveRecordKeywordField(enrFrontNameStart); mpEnrichmentFrontStart = classFactory.createEnrichmentFront( enrFrontNameStart.c_str() ); - if ( mpEnrichmentFrontStart != NULL ) { + if ( mpEnrichmentFrontStart ) { mpEnrichmentFrontStart->initializeFrom(enrFrontStartIr); //printf("EnrichmentFrontStart : %s \n", mpEnrichmentFrontStart->giveClassName()); } else { OOFEM_ERROR( "Failed to create enrichment front (%s)", enrFrontNameStart.c_str() ); } - InputRecord *enrFrontEndIr = dr->giveInputRecord(DataReader :: IR_enrichFrontRec, mEnrFrontIndex); - result = enrFrontEndIr->giveRecordKeywordField(enrFrontNameEnd); + auto &enrFrontEndIr = dr.giveInputRecord(DataReader :: IR_enrichFrontRec, mEnrFrontIndex); + enrFrontEndIr.giveRecordKeywordField(enrFrontNameEnd); mpEnrichmentFrontEnd = classFactory.createEnrichmentFront( enrFrontNameEnd.c_str() ); - if ( mpEnrichmentFrontEnd != NULL ) { + if ( mpEnrichmentFrontEnd ) { mpEnrichmentFrontEnd->initializeFrom(enrFrontEndIr); //printf("EnrichmentFrontEnd : %s \n", mpEnrichmentFrontEnd->giveClassName()); } else { @@ -139,15 +135,15 @@ int Delamination :: instanciateYourself(DataReader *dr) // Instantiate PropagationLaw if ( mPropLawIndex == 0 ) { - mpPropagationLaw = new PLDoNothing(); + mpPropagationLaw = std::make_unique(); } else { std :: string propLawName; - InputRecord *propLawir = dr->giveInputRecord(DataReader :: IR_propagationLawRec, mPropLawIndex); - result = propLawir->giveRecordKeywordField(propLawName); + auto &propLawir = dr.giveInputRecord(DataReader :: IR_propagationLawRec, mPropLawIndex); + propLawir.giveRecordKeywordField(propLawName); mpPropagationLaw = classFactory.createPropagationLaw( propLawName.c_str() ); - if ( mpPropagationLaw != NULL ) { + if ( mpPropagationLaw ) { mpPropagationLaw->initializeFrom(propLawir); } else { OOFEM_ERROR( "Failed to create propagation law (%s)", propLawName.c_str() ); @@ -158,18 +154,20 @@ int Delamination :: instanciateYourself(DataReader *dr) int xDofPoolAllocSize = this->giveDofPoolSize(); this->startOfDofIdPool = this->giveDomain()->giveNextFreeDofID(xDofPoolAllocSize); this->endOfDofIdPool = this->startOfDofIdPool + xDofPoolAllocSize - 1; + + //writeVtkDebug(); + return 1; +} +void Delamination :: postInitialize() { XfemManager *xMan = this->giveDomain()->giveXfemManager(); // mpEnrichmentDomain->CallNodeEnrMarkerUpdate(* this, * xMan); this->updateNodeEnrMarker(* xMan); - - writeVtkDebug(); - - return 1; } + #if 0 void Delamination :: updateGeometry(FailureCriteriaStatus *fc, TimeStep *tStep) @@ -219,10 +217,10 @@ Delamination :: updateGeometry(FailureCriteriaStatus *fc, TimeStep *tStep) bool Delamination :: hasInitiationCriteria() { - if (this->initiationFactor < 1e6 ) { // less than default + if ( this->initiationFactor < 1e6 ) { // less than default return true; } - + return false; } @@ -310,9 +308,9 @@ Delamination :: findInitiationFronts(bool &failureChecked, const IntArray &CSnum for (int iDF : shellElt->giveDofManArray() ) { //printf("element node %d \n",iDF); if ( this->initiationRadius > 0.0 ) { - const FloatArray gCoords = this->giveDomain()->giveNode(iDF)->giveNodeCoordinates(); + const auto &gCoords = this->giveDomain()->giveNode(iDF)->giveCoordinates(); std :: list< int > nodeList; - localizer->giveAllNodesWithinBox(nodeList,gCoords,initiationRadius); + localizer->giveAllNodesWithinBox(nodeList, gCoords, initiationRadius); for ( int jNode : nodeList ) { //printf("nodeList node %d \n",jNode); @@ -350,17 +348,14 @@ void Delamination :: evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const } -IRResultType Delamination :: initializeFrom(InputRecord *ir) +void Delamination :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = EnrichmentItem :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + EnrichmentItem :: initializeFrom(ir); // Compute the delamination xi-coord IR_GIVE_FIELD(ir, this->interfaceNum, _IFT_Delamination_interfacenum); // interface number from the bottom IR_GIVE_FIELD(ir, this->crossSectionNum, _IFT_Delamination_csnum); - if ( ir->hasField(_IFT_Delamination_averageStresses) ) { + if ( ir.hasField(_IFT_Delamination_averageStresses) ) { this->recoverStresses = false; //printf("averageStresses"); } @@ -373,43 +368,37 @@ IRResultType Delamination :: initializeFrom(InputRecord *ir) int numberOfLayers(0); for (int iCS : this->crossSectionNum) { LayeredCrossSection *layeredCS = dynamic_cast< LayeredCrossSection * >( this->giveDomain()->giveCrossSection(iCS) ); - if ( layeredCS == NULL ) { - OOFEM_WARNING("Delamination EI requires a valid layered cross section number input: see record '%s'.", _IFT_Delamination_csnum); - return IRRT_BAD_FORMAT; + if ( !layeredCS ) { + throw ValueInputException(ir, _IFT_Delamination_csnum, "Delamination EI requires a valid layered cross section number input"); } else if ( this->interfaceNum.giveSize() < 1 || this->interfaceNum.giveSize() > 2 ) { - OOFEM_WARNING("Size of record 'interfacenum' must be 1 or 2"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Delamination_interfacenum, "Size must be 1 or 2"); } // check that interface numbers are valid //interfaceNum.printYourself("interface num"); for ( int i = 1; i <= this->interfaceNum.giveSize(); i++ ) { if ( this->interfaceNum.at(i) < 1 || this->interfaceNum.at(i) >= layeredCS->giveNumberOfLayers() ) { - OOFEM_WARNING( "Cross section does not contain the interface number (%d) specified in the record '%s' since number of layers is %d.", this->interfaceNum.at(i), _IFT_Delamination_interfacenum, layeredCS->giveNumberOfLayers() ); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Delamination_interfacenum, "Cross section does not contain the interface number"); } } if (checkCS) { - if ( layeredCS->give(CS_Thickness, FloatArray(), NULL, false) != totalThickness ) { - OOFEM_WARNING("Delamination cross section have different totalThickness: see record '%s'.", _IFT_Delamination_csnum); - return IRRT_BAD_FORMAT; + if ( layeredCS->give(CS_Thickness, FloatArray(), nullptr, false) != totalThickness ) { + throw ValueInputException(ir, _IFT_Delamination_csnum, "Delamination cross section have different totalThickness"); } if ( layeredCS->giveNumberOfLayers() != numberOfLayers ) { - OOFEM_WARNING("Delamination cross section have different number of layers: see record '%s'.", _IFT_Delamination_csnum); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Delamination_csnum, "Delamination cross section have different number of layers"); } } else numberOfLayers = layeredCS->giveNumberOfLayers(); - totalThickness = layeredCS->give(CS_Thickness, FloatArray(), NULL, false); // no position available + totalThickness = layeredCS->give(CS_Thickness, FloatArray(), nullptr, false); // no position available for ( int i = 1 ; i <= numberOfLayers ; i++) { double layerThickness = layeredCS->giveLayerThickness(i); if (checkCS) { if ( layerThickness != layerThicknesses.at(i) ) { - OOFEM_WARNING("Delamination cross section have different layer thicknesses: see record '%s'.", _IFT_Delamination_csnum); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Delamination_csnum, "Delamination cross section have different layer thicknesses"); } layerThicknesses.at(i) = layerThickness; } else { @@ -427,8 +416,7 @@ IRResultType Delamination :: initializeFrom(InputRecord *ir) if ( this->interfaceNum.giveSize() == 2 ) { if ( this->interfaceNum.at(1) >= this->interfaceNum.at(2) ) { - OOFEM_WARNING("second intercfacenum must be greater than the first one"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Delamination_interfacenum, "second intercfacenum must be greater than the first one"); } this->xiTop = -1.0; for ( int i = 1; i <= this->interfaceNum.at(2); i++ ) { @@ -442,26 +430,23 @@ IRResultType Delamination :: initializeFrom(InputRecord *ir) #else // old csnum (int version). NB: this was a bug since element nodes that where not part of the cross section could be enriched. LayeredCrossSection *layeredCS = dynamic_cast< LayeredCrossSection * >( this->giveDomain()->giveCrossSection(this->crossSectionNum) ); - if ( layeredCS == NULL ) { - OOFEM_WARNING("Delamination EI requires a valid layered cross section number input: see record '%s'.", _IFT_Delamination_csnum); - return IRRT_BAD_FORMAT; + if ( !layeredCS ) { + throw ValueInputException(ir, _IFT_Delamination_csnum, "Delamination EI requires a valid layered cross section number input"); } else if ( this->interfaceNum.giveSize() < 1 || this->interfaceNum.giveSize() > 2 ) { - OOFEM_WARNING("Size of record 'interfacenum' must be 1 or 2"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Delamination_interfacenum, "size must be 1 or 2"); } // check that interface numbers are valid //interfaceNum.printYourself("interface num"); for ( int i = 1; i <= this->interfaceNum.giveSize(); i++ ) { if ( this->interfaceNum.at(i) < 1 || this->interfaceNum.at(i) >= layeredCS->giveNumberOfLayers() ) { - OOFEM_WARNING( "Cross section does not contain the interface number (%d) specified in the record '%s' since number of layers is %d.", this->interfaceNum.at(i), _IFT_Delamination_interfacenum, layeredCS->giveNumberOfLayers() ); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Delamination_interfacenum, "Cross section does not contain the interface number"); } } // compute xi-coord of the delamination this->delamXiCoord = -1.0; - double totalThickness = layeredCS->give(CS_Thickness, FloatArray(), NULL, false); // no position available + double totalThickness = layeredCS->give(CS_Thickness, FloatArray(), nullptr, false); // no position available for ( int i = 1; i <= this->interfaceNum.at(1); i++ ) { this->delamXiCoord += layeredCS->giveLayerThickness(i) / totalThickness * 2.0; this->xiBottom += layeredCS->giveLayerThickness(i) / totalThickness * 2.0; @@ -469,8 +454,7 @@ IRResultType Delamination :: initializeFrom(InputRecord *ir) if ( this->interfaceNum.giveSize() == 2 ) { if ( this->interfaceNum.at(1) >= this->interfaceNum.at(2) ) { - OOFEM_WARNING("second intercfacenum must be greater than the first one"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, "second intercfacenum must be greater than the first one"); } for ( int i = 1; i <= this->interfaceNum.at(2); i++ ) { this->xiTop += layeredCS->giveLayerThickness(i) / totalThickness * 2.0; @@ -480,7 +464,6 @@ IRResultType Delamination :: initializeFrom(InputRecord *ir) } #endif - IR_GIVE_OPTIONAL_FIELD(ir, this->matNum, _IFT_Delamination_CohesiveZoneMaterial); if ( this->matNum > 0 ) { this->mat = this->giveDomain()->giveMaterial(this->matNum); @@ -488,18 +471,13 @@ IRResultType Delamination :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, this->initiationFactor, _IFT_Delamination_initiationFactor); if ( this->initiationFactor <= 0 ) { - OOFEM_ERROR("initiation scale factor must be greater than 0."); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Delamination_initiationFactor, "must be positive"); } IR_GIVE_OPTIONAL_FIELD(ir, this->initiationRadius, _IFT_Delamination_initiationRadius); if ( this->initiationRadius < 0 ) { - OOFEM_ERROR("initiation radius must be greater or equal than 0."); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_Delamination_initiationRadius, "must be positive"); } - - - return IRRT_OK; } @@ -508,7 +486,7 @@ void Delamination :: appendInputRecords(DynamicDataReader &oDR) { ///@todo almost everything is copied from EnrichmentItem :: giveInputRecord, should be written in a better way - DynamicInputRecord *eiRec = new DynamicInputRecord(); + auto eiRec = std::make_unique(); FEMComponent :: giveInputRecord(* eiRec); eiRec->setField(mEnrFrontIndex, _IFT_EnrichmentItem_front); @@ -525,17 +503,17 @@ Delamination :: appendInputRecords(DynamicDataReader &oDR) } - oDR.insertInputRecord(DataReader :: IR_enrichItemRec, eiRec); + oDR.insertInputRecord(DataReader :: IR_enrichItemRec, std::move(eiRec)); // Enrichment function - DynamicInputRecord *efRec = new DynamicInputRecord(); + auto efRec = std::make_unique(); mpEnrichmentFunc->giveInputRecord(* efRec); - oDR.insertInputRecord(DataReader :: IR_enrichFuncRec, efRec); + oDR.insertInputRecord(DataReader :: IR_enrichFuncRec, std::move(efRec)); // Enrichment domain - DynamicInputRecord *geoRec = new DynamicInputRecord(); + auto geoRec = std::make_unique(); geoRec->setRecordKeywordField(this->giveInputRecordName(), 1); IntArray idList; @@ -546,24 +524,24 @@ Delamination :: appendInputRecords(DynamicDataReader &oDR) geoRec->setField(idList, _IFT_ListBasedEI_list); - oDR.insertInputRecord(DataReader :: IR_geoRec, geoRec); + oDR.insertInputRecord(DataReader :: IR_geoRec, std::move(geoRec)); // Enrichment front if ( mEnrFrontIndex != 0 ) { - DynamicInputRecord *efrRecStart = new DynamicInputRecord(); + auto efrRecStart = std::make_unique(); mpEnrichmentFrontStart->giveInputRecord(* efrRecStart); - oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, efrRecStart); + oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, std::move(efrRecStart)); - DynamicInputRecord *efrRecEnd = new DynamicInputRecord(); + auto efrRecEnd = std::make_unique(); mpEnrichmentFrontEnd->giveInputRecord(* efrRecEnd); - oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, efrRecEnd); + oDR.insertInputRecord(DataReader :: IR_enrichFrontRec, std::move(efrRecEnd)); } if ( mPropLawIndex != 0 ) { // Propagation law - DynamicInputRecord *plRec = new DynamicInputRecord(); + auto plRec = std::make_unique(); this->mpPropagationLaw->giveInputRecord(* plRec); - oDR.insertInputRecord(DataReader :: IR_propagationLawRec, plRec); + oDR.insertInputRecord(DataReader :: IR_propagationLawRec, std::move(plRec)); } } diff --git a/src/sm/xfem/enrichmentitems/delamination.h b/src/sm/xfem/enrichmentitems/delamination.h index 92cb6f275..7dffdee2b 100644 --- a/src/sm/xfem/enrichmentitems/delamination.h +++ b/src/sm/xfem/enrichmentitems/delamination.h @@ -73,39 +73,42 @@ class OOFEM_EXPORT Delamination : public ListBasedEI double initiationFactor; // knock-down factor on initiation values, (0,1] //JF double initiationRadius; // radius around around newlye initiated element nodes to be included //JF bool recoverStresses; // recover tranverse stresses using momentum balance (default). //JF + public: Delamination(int n, XfemManager *xm, Domain *aDomain); + virtual ~Delamination() { } - virtual int instanciateYourself(DataReader *dr); + void initializeFrom(InputRecord &ir) override; + int instanciateYourself(DataReader &dr) override; + void postInitialize() override; + void appendInputRecords(DynamicDataReader &oDR) override; - virtual const char *giveClassName() const { return "Delamination"; } - virtual const char *giveInputRecordName() const { return _IFT_Delamination_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void appendInputRecords(DynamicDataReader &oDR); + const char *giveClassName() const override { return "Delamination"; } + const char *giveInputRecordName() const override { return _IFT_Delamination_Name; } double giveDelamXiCoord() const { return xiBottom; } // coord where the delamination is defined double giveBoundingDelamXiCoord() const { return xiTop; } // coord where the delamination enrichment should stop, default is the shell surface int giveDelamInterfaceNum() const { return interfaceNum.at(1); } IntArray giveDelamCrossSectionNum() const { return crossSectionNum; } double giveInitiationFactor() const { return initiationFactor; } - //virtual void updateGeometry(FailureCriteriaStatus *fc, TimeStep *tStep); - virtual bool hasPropagatingFronts() const { return true; } - virtual bool hasInitiationCriteria(); - - virtual void propagateFronts(bool &oFrontsHavePropagated); - virtual void findInitiationFronts(bool &failureChecked, const IntArray &CSnumbers, std :: vector< IntArray > &CSinterfaceNumbers, std :: vector< IntArray > &CSDofManNumbers, std :: vector< FloatArray > &initiationFactors, TimeStep *tStep); + //void updateGeometry(FailureCriteriaStatus *fc, TimeStep *tStep) override; + bool hasPropagatingFronts() const override { return true; } + bool hasInitiationCriteria() override; + + void propagateFronts(bool &oFrontsHavePropagated) override; + void findInitiationFronts(bool &failureChecked, const IntArray &CSnumbers, std :: vector< IntArray > &CSinterfaceNumbers, std :: vector< IntArray > &CSDofManNumbers, std :: vector< FloatArray > &initiationFactors, TimeStep *tStep); - virtual void evaluateEnrFuncInNode(std :: vector< double > &oEnrFunc, const Node &iNode) const { OOFEM_ERROR("Not implemented.") } + void evaluateEnrFuncInNode(std :: vector< double > &oEnrFunc, const Node &iNode) const override { OOFEM_ERROR("Not implemented.") } - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const; - virtual void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl, const FloatArray &iN, const IntArray &iElNodes) const; + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const override; + void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl, const FloatArray &iN, const IntArray &iElNodes) const override; - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const { OOFEM_ERROR("Not implemented."); } - virtual void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl, const FloatArray &iN, const FloatMatrix &idNdX, const IntArray &iElNodes) const { OOFEM_ERROR("Not implemented."); } + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl) const override { OOFEM_ERROR("Not implemented."); } + void evaluateEnrFuncDerivAt(std :: vector< FloatArray > &oEnrFuncDeriv, const FloatArray &iGlobalCoord, const FloatArray &iLocalCoord, int iNodeInd, const Element &iEl, const FloatArray &iN, const FloatMatrix &idNdX, const IntArray &iElNodes) const override { OOFEM_ERROR("Not implemented."); } - virtual void evalLevelSetNormal(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const; - virtual void evalLevelSetTangential(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const { OOFEM_ERROR("Not implemented."); } - virtual void evalGradLevelSetNormal(FloatArray &oGradLevelSet, const FloatArray &iGlobalCoord, const FloatMatrix &idNdX, const IntArray &iNodeInd) const { OOFEM_ERROR("Not implemented."); } + void evalLevelSetNormal(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const override; + void evalLevelSetTangential(double &oLevelSet, const FloatArray &iGlobalCoord, const FloatArray &iN, const IntArray &iNodeInd) const override { OOFEM_ERROR("Not implemented."); } + void evalGradLevelSetNormal(FloatArray &oGradLevelSet, const FloatArray &iGlobalCoord, const FloatMatrix &idNdX, const IntArray &iNodeInd) const override { OOFEM_ERROR("Not implemented."); } void evaluateEnrFuncAt(std :: vector< double > &oEnrFunc, const FloatArray &iPos, const double &iLevelSet) const; }; diff --git a/src/sm/xfem/enrichmentitems/shellcrack.C b/src/sm/xfem/enrichmentitems/shellcrack.C index fa5c8eb19..ff9c238fd 100644 --- a/src/sm/xfem/enrichmentitems/shellcrack.C +++ b/src/sm/xfem/enrichmentitems/shellcrack.C @@ -31,7 +31,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "xfem/enrichmentitems/shellcrack.h" +#include "shellcrack.h" #include "classfactory.h" namespace oofem { @@ -46,14 +46,13 @@ ShellCrack :: ShellCrack(int n, XfemManager *xm, Domain *aDomain) : Crack(n, xm, } - -IRResultType ShellCrack :: initializeFrom(InputRecord *ir) +void ShellCrack :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Crack :: initializeFrom(ir); + this->xiBottom = 0.0; this->xiTop = 0.0; IR_GIVE_FIELD(ir, this->xiBottom, _IFT_ShellCrack_xiBottom); IR_GIVE_FIELD(ir, this->xiTop, _IFT_ShellCrack_xiTop); - return Crack :: initializeFrom(ir); } } // end namespace oofem diff --git a/src/sm/xfem/enrichmentitems/shellcrack.h b/src/sm/xfem/enrichmentitems/shellcrack.h index 1f5e8b2f2..48ab9953e 100644 --- a/src/sm/xfem/enrichmentitems/shellcrack.h +++ b/src/sm/xfem/enrichmentitems/shellcrack.h @@ -58,9 +58,9 @@ class OOFEM_EXPORT ShellCrack : public Crack public: ShellCrack(int n, XfemManager *xm, Domain *aDomain); - virtual const char *giveClassName() const { return "ShellCrack"; } - virtual const char *giveInputRecordName() const { return _IFT_ShellCrack_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveClassName() const override { return "ShellCrack"; } + const char *giveInputRecordName() const override { return _IFT_ShellCrack_Name; } + void initializeFrom(InputRecord &ir) override; double xiBottom; double xiTop; diff --git a/src/sm/xfem/matforceevaluator.C b/src/sm/xfem/matforceevaluator.C index fc65e35a6..4ce77fc4c 100644 --- a/src/sm/xfem/matforceevaluator.C +++ b/src/sm/xfem/matforceevaluator.C @@ -36,12 +36,12 @@ #include "xfem/tipinfo.h" #include "domain.h" #include "spatiallocalizer.h" -#include "Elements/nlstructuralelement.h" +#include "sm/Elements/nlstructuralelement.h" #include "dofmanager.h" #include "integrationrule.h" #include "feinterpol.h" #include "gausspoint.h" -#include "CrossSections/structuralcrosssection.h" +#include "sm/CrossSections/structuralcrosssection.h" #include #include @@ -71,8 +71,8 @@ void MaterialForceEvaluator::computeMaterialForce(FloatArray &oMatForce, Domain FloatArray lcoords, closest; Element *closestEl = localizer->giveElementClosestToPoint(lcoords, closest, iTipInfo.mGlobalCoord); - if ( closestEl != NULL ) { - if ( closest.distance(iTipInfo.mGlobalCoord) < 1.0e-9 ) { + if ( closestEl != nullptr ) { + if ( distance(closest, iTipInfo.mGlobalCoord) < 1.0e-9 ) { int elInd = closestEl->giveGlobalNumber(); int elPlaceInArray = iDomain.giveElementPlaceInArray(elInd); elList.insertSortedOnce( elPlaceInArray ); @@ -93,7 +93,7 @@ void MaterialForceEvaluator::computeMaterialForce(FloatArray &oMatForce, Domain for ( int nodeInd : elNodes ) { DofManager *dMan = iDomain.giveDofManager(nodeInd); - weightInNodes[nodeInd] = computeWeightFunctionInPoint( *(dMan->giveCoordinates()), iTipInfo.mGlobalCoord, iRadius); + weightInNodes[nodeInd] = computeWeightFunctionInPoint( dMan->giveCoordinates(), iTipInfo.mGlobalCoord, iRadius); } } @@ -103,7 +103,7 @@ void MaterialForceEvaluator::computeMaterialForce(FloatArray &oMatForce, Domain // int elPlaceInArray = iDomain.giveElementPlaceInArray(elIndex); NLStructuralElement *el = dynamic_cast( iDomain.giveElement(elIndex) ); - if ( el == NULL ) { + if ( el == nullptr ) { OOFEM_ERROR("Could not cast to NLStructuralElement.") } @@ -140,7 +140,7 @@ void MaterialForceEvaluator::computeMaterialForce(FloatArray &oMatForce, Domain // Compute Eshelby stress StructuralCrossSection *cs = dynamic_cast( gp->giveCrossSection() ); - if (cs != NULL) { + if (cs != nullptr) { FloatArray Fv; el->computeDeformationGradientVector(Fv, gp, tStep); @@ -183,15 +183,11 @@ void MaterialForceEvaluator::computeMaterialForce(FloatArray &oMatForce, Domain double MaterialForceEvaluator::computeWeightFunctionInPoint(const FloatArray &iCoord, const FloatArray &iTipCoord, const double &iRadius) const { double weight = 0.0; - - double r = iTipCoord.distance(iCoord); - + double r = distance(iTipCoord, iCoord); // if(r <= iRadius) { weight = 1.0 - r/iRadius; // } - // printf("r: %e weight: %e\n", r, weight); - return weight; } diff --git a/src/sm/xfem/matforceevaluator.h b/src/sm/xfem/matforceevaluator.h index e2b5a8031..79519e99b 100644 --- a/src/sm/xfem/matforceevaluator.h +++ b/src/sm/xfem/matforceevaluator.h @@ -32,13 +32,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* - * matforceevaluator.h - * - * Created on: Nov 12, 2014 - * Author: svennine - */ - #ifndef MATFORCEEVALUATOR_H_ #define MATFORCEEVALUATOR_H_ diff --git a/src/sm/xfem/nucleationcriteria/ncprincipalstrain.C b/src/sm/xfem/nucleationcriteria/ncprincipalstrain.C index 75480df30..aa6b09b8a 100644 --- a/src/sm/xfem/nucleationcriteria/ncprincipalstrain.C +++ b/src/sm/xfem/nucleationcriteria/ncprincipalstrain.C @@ -40,8 +40,8 @@ #include "element.h" #include "gausspoint.h" -#include "Materials/structuralms.h" -#include "Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" #include "xfem/enrichmentitems/crack.h" #include "xfem/xfemmanager.h" @@ -186,51 +186,43 @@ std::vector> NCPrincipalStrain::nucleateEnrichme } for(const auto &x: center_coord_inserted_cracks) { - if( x.distance(pc) < 2.0*mInitialCrackLength) { + if( distance(x, pc) < 2.0*mInitialCrackLength) { insertionAllowed = false; - break; printf("Preventing insertion.\n"); + break; } } if(insertionAllowed) { int n = xMan->giveNumberOfEnrichmentItems() + 1; - std::unique_ptr crack(new Crack(n, xMan, mpDomain)); + std::unique_ptr crack = std::make_unique(n, xMan, mpDomain); // Geometry - std::unique_ptr geom = std::unique_ptr(new PolygonLine()); + std::unique_ptr geom = std::make_unique(); geom->insertVertexBack(ps); geom->insertVertexBack(pc); geom->insertVertexBack(pe); crack->setGeometry(std::move(geom)); // Enrichment function - EnrichmentFunction *ef = new HeavisideFunction(1, mpDomain); - crack->setEnrichmentFunction(ef); + crack->setEnrichmentFunction(std::make_unique(1, mpDomain)); // Enrichment fronts -// EnrichmentFront *efStart = new EnrFrontLinearBranchFuncOneEl(); - EnrichmentFront *efStart = new EnrFrontCohesiveBranchFuncOneEl(); - crack->setEnrichmentFrontStart(efStart); - -// EnrichmentFront *efEnd = new EnrFrontLinearBranchFuncOneEl(); - EnrichmentFront *efEnd = new EnrFrontCohesiveBranchFuncOneEl(); - crack->setEnrichmentFrontEnd(efEnd); - - + crack->setEnrichmentFrontStart(std::make_unique()); + crack->setEnrichmentFrontEnd(std::make_unique()); /////////////////////////////////////// // Propagation law // Options - PLPrincipalStrain *pl = new PLPrincipalStrain(); + auto pl = std::make_unique(); pl->setRadius(0.1*mIncrementLength); pl->setIncrementLength(mIncrementLength); pl->setStrainThreshold(mPropStrainThreshold); - crack->setPropagationLaw(pl); + crack->setPropagationLaw(std::move(pl)); crack->updateDofIdPool(); @@ -251,13 +243,13 @@ std::vector> NCPrincipalStrain::nucleateEnrichme } - return std::move( eiList ); + return eiList; } -IRResultType NCPrincipalStrain::initializeFrom(InputRecord *ir) { - - IRResultType result; // Required by IR_GIVE_FIELD macro +void NCPrincipalStrain::initializeFrom(InputRecord &ir) +{ + NucleationCriterion::initializeFrom(ir); IR_GIVE_FIELD(ir, mStrainThreshold, _IFT_NCPrincipalStrain_StrainThreshold); printf("mStrainThreshold: %e\n", mStrainThreshold); @@ -270,13 +262,11 @@ IRResultType NCPrincipalStrain::initializeFrom(InputRecord *ir) { IR_GIVE_FIELD(ir, mPropStrainThreshold, _IFT_NCPrincipalStrain_PropStrainThreshold); printf("mPropStrainThreshold: %e\n", mPropStrainThreshold); - - return NucleationCriterion::initializeFrom(ir); } void NCPrincipalStrain :: appendInputRecords(DynamicDataReader &oDR) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); ir->setRecordKeywordField( this->giveInputRecordName(), 1 ); @@ -285,12 +275,12 @@ void NCPrincipalStrain :: appendInputRecords(DynamicDataReader &oDR) ir->setField(mIncrementLength, _IFT_NCPrincipalStrain_IncrementLength); ir->setField(mPropStrainThreshold, _IFT_NCPrincipalStrain_PropStrainThreshold); - oDR.insertInputRecord(DataReader :: IR_crackNucleationRec, ir); + oDR.insertInputRecord(DataReader :: IR_crackNucleationRec, std::move(ir)); // Enrichment function - DynamicInputRecord *efRec = new DynamicInputRecord(); + auto efRec = std::make_unique(); mpEnrichmentFunc->giveInputRecord(* efRec); - oDR.insertInputRecord(DataReader :: IR_enrichFuncRec, efRec); + oDR.insertInputRecord(DataReader :: IR_enrichFuncRec, std::move(efRec)); } } /* namespace oofem */ diff --git a/src/sm/xfem/nucleationcriteria/ncprincipalstrain.h b/src/sm/xfem/nucleationcriteria/ncprincipalstrain.h index a7b05009b..fe835657e 100644 --- a/src/sm/xfem/nucleationcriteria/ncprincipalstrain.h +++ b/src/sm/xfem/nucleationcriteria/ncprincipalstrain.h @@ -47,21 +47,20 @@ namespace oofem { -class NCPrincipalStrain : public NucleationCriterion { +class NCPrincipalStrain : public NucleationCriterion +{ public: - NCPrincipalStrain(Domain *ipDomain); - virtual ~NCPrincipalStrain(); + NCPrincipalStrain(Domain *ipDomain); + virtual ~NCPrincipalStrain(); - virtual std::vector> nucleateEnrichmentItems(); + std::vector> nucleateEnrichmentItems() override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void appendInputRecords(DynamicDataReader &oDR); + void appendInputRecords(DynamicDataReader &oDR) override; - /// @return Class name of the receiver. - virtual const char *giveClassName() const {return "NCPrincipalStrain";} - /// @return Input record name of the receiver. - virtual const char *giveInputRecordName() const {return _IFT_NCPrincipalStrain_Name;}; + const char *giveClassName() const override { return "NCPrincipalStrain"; } + const char *giveInputRecordName() const override { return _IFT_NCPrincipalStrain_Name; } protected: double mStrainThreshold; diff --git a/src/sm/xfem/nucleationcriteria/ncprincipalstress.C b/src/sm/xfem/nucleationcriteria/ncprincipalstress.C index ccd2ebfbc..255f6d571 100644 --- a/src/sm/xfem/nucleationcriteria/ncprincipalstress.C +++ b/src/sm/xfem/nucleationcriteria/ncprincipalstress.C @@ -39,8 +39,8 @@ #include "element.h" #include "gausspoint.h" -#include "Materials/structuralms.h" -#include "Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" #include "xfem/enrichmentitems/crack.h" #include "xfem/xfemmanager.h" @@ -62,25 +62,20 @@ namespace oofem { REGISTER_NucleationCriterion(NCPrincipalStress) NCPrincipalStress::NCPrincipalStress(Domain *ipDomain): -NucleationCriterion(ipDomain), -mStressThreshold(0.0), -mInitialCrackLength(0.0), -mMatForceRadius(0.0), -mIncrementLength(0.0), -mCrackPropThreshold(0.0), -mCutOneEl(false), -mCrossSectionInd(2) + NucleationCriterion(ipDomain), + mStressThreshold(0.0), + mInitialCrackLength(0.0), + mMatForceRadius(0.0), + mIncrementLength(0.0), + mCrackPropThreshold(0.0), + mCutOneEl(false), + mCrossSectionInd(2) +{ } + +NCPrincipalStress::~NCPrincipalStress() { } + +std::vector> NCPrincipalStress::nucleateEnrichmentItems() { - -} - -NCPrincipalStress::~NCPrincipalStress() { - -} - -std::vector> NCPrincipalStress::nucleateEnrichmentItems() { - - SpatialLocalizer *octree = this->mpDomain->giveSpatialLocalizer(); XfemManager *xMan = mpDomain->giveXfemManager(); @@ -91,9 +86,7 @@ std::vector> NCPrincipalStress::nucleateEnrichme // Loop over all elements and all bulk GP. for(auto &el : mpDomain->giveElements() ) { - int numIR = el->giveNumberOfIntegrationRules(); - int csNum = el->giveCrossSection()->giveNumber(); if(csNum == mCrossSectionInd || true) { @@ -101,8 +94,6 @@ std::vector> NCPrincipalStress::nucleateEnrichme for(int irInd = 0; irInd < numIR; irInd++) { IntegrationRule *ir = el->giveIntegrationRule(irInd); - - int numGP = ir->giveNumberOfIntegrationPoints(); for(int gpInd = 0; gpInd < numGP; gpInd++) { @@ -114,7 +105,7 @@ std::vector> NCPrincipalStress::nucleateEnrichme StructuralMaterialStatus *ms = dynamic_cast(gp->giveMaterialStatus()); - if(ms != NULL) { + if ( ms ) { const FloatArray &stress = ms->giveTempStressVector(); @@ -122,7 +113,7 @@ std::vector> NCPrincipalStress::nucleateEnrichme FloatMatrix principalDirs; StructuralMaterial::computePrincipalValDir(principalVals, principalDirs, stress, principal_stress); - if(principalVals[0] > mStressThreshold) { + if ( principalVals[0] > mStressThreshold ) { @@ -150,7 +141,7 @@ std::vector> NCPrincipalStress::nucleateEnrichme FloatArray pe = pc; pe.add(0.5*mInitialCrackLength, crackTangent); - if(mCutOneEl) { + if ( mCutOneEl ) { // If desired, ensure that the crack cuts exactly one element. Line line(ps, pe); std::vector intersecPoints; @@ -173,11 +164,10 @@ std::vector> NCPrincipalStress::nucleateEnrichme // printf("intersecPoints.size(): %lu\n", intersecPoints.size()); - if(intersecPoints.size() == 2) { + if ( intersecPoints.size() == 2 ) { ps = std::move(intersecPoints[0]); pe = std::move(intersecPoints[1]); - } - else { + } else { OOFEM_ERROR("intersecPoints.size() != 2") } } @@ -197,58 +187,53 @@ std::vector> NCPrincipalStress::nucleateEnrichme bool insertionAllowed = true; Element *el_s = octree->giveElementContainingPoint(ps); - if(el_s) { - if( xMan->isElementEnriched(el_s) ) { + if ( el_s ) { + if ( xMan->isElementEnriched(el_s) ) { insertionAllowed = false; } } Element *el_c = octree->giveElementContainingPoint(pc); - if(el_c) { - if( xMan->isElementEnriched(el_c) ) { + if ( el_c ) { + if ( xMan->isElementEnriched(el_c) ) { insertionAllowed = false; } } Element *el_e = octree->giveElementContainingPoint(pe); - if(el_e) { - if( xMan->isElementEnriched(el_e) ) { + if ( el_e ) { + if ( xMan->isElementEnriched(el_e) ) { insertionAllowed = false; } } - for(const auto &x: center_coord_inserted_cracks) { - if( x.distance(pc) < 2.0*mInitialCrackLength) { + for ( const auto &x: center_coord_inserted_cracks ) { + if ( distance(x, pc) < 2.0*mInitialCrackLength ) { insertionAllowed = false; - break; printf("Preventing insertion.\n"); + break; } } - if(insertionAllowed) { + if ( insertionAllowed ) { int n = xMan->giveNumberOfEnrichmentItems() + 1; - std::unique_ptr crack(new Crack(n, xMan, mpDomain)); + std::unique_ptr crack = std::make_unique(n, xMan, mpDomain); // Geometry - std::unique_ptr geom = std::unique_ptr(new PolygonLine()); + std::unique_ptr geom = std::make_unique(); geom->insertVertexBack(ps); geom->insertVertexBack(pc); geom->insertVertexBack(pe); crack->setGeometry(std::move(geom)); // Enrichment function - EnrichmentFunction *ef = new HeavisideFunction(1, mpDomain); - crack->setEnrichmentFunction(ef); + crack->setEnrichmentFunction(std::make_unique(1, mpDomain)); // Enrichment fronts -// EnrichmentFront *efStart = new EnrFrontLinearBranchFuncOneEl(); - EnrichmentFront *efStart = new EnrFrontCohesiveBranchFuncOneEl(); - crack->setEnrichmentFrontStart(efStart); + crack->setEnrichmentFrontStart(std::make_unique()); -// EnrichmentFront *efEnd = new EnrFrontLinearBranchFuncOneEl(); - EnrichmentFront *efEnd = new EnrFrontCohesiveBranchFuncOneEl(); - crack->setEnrichmentFrontEnd(efEnd); + crack->setEnrichmentFrontEnd(std::make_unique()); @@ -269,14 +254,14 @@ std::vector> NCPrincipalStress::nucleateEnrichme // PLDoNothing *pl = new PLDoNothing(); - PLMaterialForce *pl = new PLMaterialForce(); + auto pl = std::make_unique(); pl->setRadius(mMatForceRadius); pl->setIncrementLength(mIncrementLength); // pl->setIncrementLength(0.25); // pl->setCrackPropThreshold(0.25); pl->setCrackPropThreshold(mCrackPropThreshold); - crack->setPropagationLaw(pl); + crack->setPropagationLaw(std::move(pl)); crack->updateDofIdPool(); @@ -298,13 +283,13 @@ std::vector> NCPrincipalStress::nucleateEnrichme } - return std::move( eiList ); + return eiList; } -IRResultType NCPrincipalStress::initializeFrom(InputRecord *ir) { - - IRResultType result; // Required by IR_GIVE_FIELD macro +void NCPrincipalStress::initializeFrom(InputRecord &ir) +{ + NucleationCriterion::initializeFrom(ir); IR_GIVE_FIELD(ir, mStressThreshold, _IFT_NCPrincipalStress_StressThreshold); // printf("mStressThreshold: %e\n", mStressThreshold); @@ -322,12 +307,11 @@ IRResultType NCPrincipalStress::initializeFrom(InputRecord *ir) { // printf("mCrackPropThreshold: %e\n", mCrackPropThreshold); - return NucleationCriterion::initializeFrom(ir); } void NCPrincipalStress :: appendInputRecords(DynamicDataReader &oDR) { - DynamicInputRecord *ir = new DynamicInputRecord(); + auto ir = std::make_unique(); ir->setRecordKeywordField( this->giveInputRecordName(), 1 ); @@ -337,12 +321,12 @@ void NCPrincipalStress :: appendInputRecords(DynamicDataReader &oDR) ir->setField(mIncrementLength, _IFT_NCPrincipalStress_IncrementLength); ir->setField(mCrackPropThreshold, _IFT_NCPrincipalStress_CrackPropThreshold); - oDR.insertInputRecord(DataReader :: IR_crackNucleationRec, ir); + oDR.insertInputRecord(DataReader :: IR_crackNucleationRec, std::move(ir)); // Enrichment function - DynamicInputRecord *efRec = new DynamicInputRecord(); + auto efRec = std::make_unique(); mpEnrichmentFunc->giveInputRecord(* efRec); - oDR.insertInputRecord(DataReader :: IR_enrichFuncRec, efRec); + oDR.insertInputRecord(DataReader :: IR_enrichFuncRec, std::move(efRec)); } } /* namespace oofem */ diff --git a/src/sm/xfem/nucleationcriteria/ncprincipalstress.h b/src/sm/xfem/nucleationcriteria/ncprincipalstress.h index 6091f0a51..bc14930e5 100644 --- a/src/sm/xfem/nucleationcriteria/ncprincipalstress.h +++ b/src/sm/xfem/nucleationcriteria/ncprincipalstress.h @@ -48,21 +48,20 @@ namespace oofem { -class NCPrincipalStress : public NucleationCriterion { +class NCPrincipalStress : public NucleationCriterion +{ public: - NCPrincipalStress(Domain *ipDomain); - virtual ~NCPrincipalStress(); + NCPrincipalStress(Domain *ipDomain); + virtual ~NCPrincipalStress(); - virtual std::vector> nucleateEnrichmentItems(); + std::vector> nucleateEnrichmentItems() override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void appendInputRecords(DynamicDataReader &oDR); + void appendInputRecords(DynamicDataReader &oDR) override; - /// @return Class name of the receiver. - virtual const char *giveClassName() const {return "NCPrincipalStress";} - /// @return Input record name of the receiver. - virtual const char *giveInputRecordName() const {return _IFT_NCPrincipalStress_Name;}; + const char *giveClassName() const override { return "NCPrincipalStress"; } + const char *giveInputRecordName() const override {return _IFT_NCPrincipalStress_Name;}; protected: double mStressThreshold; diff --git a/src/sm/xfem/propagationlaws/plczdamageradius.C b/src/sm/xfem/propagationlaws/plczdamageradius.C index 659c5dbcb..cd47fda49 100644 --- a/src/sm/xfem/propagationlaws/plczdamageradius.C +++ b/src/sm/xfem/propagationlaws/plczdamageradius.C @@ -34,10 +34,10 @@ #include "xfem/propagationlaws/plczdamageradius.h" #include "xfem/enrichmentitems/delamination.h" -#include "Elements/Shells/shell7basexfem.h" -#include "Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" -#include -#include +#include "sm/Elements/Shells/shell7basexfem.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" +#include "sm/Materials/structuralms.h" #include "xfem/propagationlaw.h" #include "xfem/tipinfo.h" @@ -54,15 +54,11 @@ namespace oofem { REGISTER_PropagationLaw(PLCZdamageRadius) ///////////////////////////////////////////// -IRResultType PLCZdamageRadius :: initializeFrom(InputRecord *ir) +void PLCZdamageRadius :: initializeFrom(InputRecord &ir) { - IRResultType result; - IR_GIVE_FIELD(ir, mIncrementRadius, _IFT_PLCZdamageRadius_IncRadius); IR_GIVE_FIELD(ir, mDamageThreshold, _IFT_PLCZdamageRadius_DamageThreshold); IR_GIVE_OPTIONAL_FIELD(ir, this->mPropCS, _IFT_PLCZdamageRadius_PropagationCS); - - return IRRT_OK; } void PLCZdamageRadius :: giveInputRecord(DynamicInputRecord &input) @@ -181,10 +177,10 @@ bool PLCZdamageRadius :: propagateInterface(Domain &iDomain, EnrichmentFront &iE for ( int i = 1 ; i <= propagationDF.giveSize() ; i++ ) { Node *iNode = iDomain.giveNode(propagationDF.at(i)); - const FloatArray gCoords = iNode->giveNodeCoordinates(); + const auto &gCoords = iNode->giveCoordinates(); std :: list< int > nodeList; - localizer->giveAllNodesWithinBox(nodeList,gCoords,mIncrementRadius); + localizer->giveAllNodesWithinBox(nodeList, gCoords, mIncrementRadius); for ( int jNode : nodeList ) { //printf("nodeList node %d \n",jNode); oTipProp.mPropagationDofManNumbers.insertSortedOnce(jNode); diff --git a/src/sm/xfem/propagationlaws/plczdamageradius.h b/src/sm/xfem/propagationlaws/plczdamageradius.h index a0debd5f6..3cf5a0898 100644 --- a/src/sm/xfem/propagationlaws/plczdamageradius.h +++ b/src/sm/xfem/propagationlaws/plczdamageradius.h @@ -63,18 +63,18 @@ class OOFEM_EXPORT PLCZdamageRadius : public PropagationLaw PLCZdamageRadius() : mIncrementRadius(0.0), mDamageThreshold(0.0), mPropCS(0) { } virtual ~PLCZdamageRadius() { } - virtual const char *giveClassName() const { return "PLCZdamageRadius"; } - virtual const char *giveInputRecordName() const { return _IFT_PLCZdamageRadius_Name; } + const char *giveClassName() const override { return "PLCZdamageRadius"; } + const char *giveInputRecordName() const override { return _IFT_PLCZdamageRadius_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual bool hasPropagation() const { return mIncrementRadius > 0.; } ///@todo Could this be done smarter? / Mikael - virtual bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp); + bool hasPropagation() const override { return mIncrementRadius > 0.; } ///@todo Could this be done smarter? / Mikael + bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) override; + + void setIncrementRadius(double iIncrementRadius) { mIncrementRadius = iIncrementRadius; } + void setdamageThreshold(double idamageThreshold) { mDamageThreshold = idamageThreshold; } - void setIncrementRadius(double iIncrementRadius) {mIncrementRadius = std::move(iIncrementRadius);} - void setdamageThreshold(double idamageThreshold) {mDamageThreshold = std::move(idamageThreshold);} - IntArray givePropagationCrossSections() {return this->mPropCS;} protected: diff --git a/src/sm/xfem/propagationlaws/plhoopstresscirc.C b/src/sm/xfem/propagationlaws/plhoopstresscirc.C index 3f9425614..ed7c4cb02 100644 --- a/src/sm/xfem/propagationlaws/plhoopstresscirc.C +++ b/src/sm/xfem/propagationlaws/plhoopstresscirc.C @@ -42,7 +42,7 @@ #include "spatiallocalizer.h" #include "floatmatrix.h" #include "gausspoint.h" -#include "../sm/Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "xfem/enrichmentitem.h" #include "feinterpol.h" #include "xfem/xfemmanager.h" @@ -53,10 +53,8 @@ namespace oofem { REGISTER_PropagationLaw(PLHoopStressCirc) ///////////////////////////////////////////// -IRResultType PLHoopStressCirc :: initializeFrom(InputRecord *ir) +void PLHoopStressCirc :: initializeFrom(InputRecord &ir) { - IRResultType result; - IR_GIVE_FIELD(ir, mRadius, _IFT_PLHoopStressCirc_Radius); IR_GIVE_FIELD(ir, mAngleInc, _IFT_PLHoopStressCirc_AngleInc); IR_GIVE_FIELD(ir, mIncrementLength, _IFT_PLHoopStressCirc_IncLength); @@ -67,8 +65,6 @@ IRResultType PLHoopStressCirc :: initializeFrom(InputRecord *ir) if ( useRadialBasisFunc == 1 ) { mUseRadialBasisFunc = true; } - - return IRRT_OK; } void PLHoopStressCirc :: giveInputRecord(DynamicInputRecord &input) @@ -142,9 +138,9 @@ bool PLHoopStressCirc :: propagateInterface(Domain &iDomain, EnrichmentFront &iE // crack tip multiplied by a constant factor. // ( This choice implies that we hope that the element has reasonable // aspect ratio.) - const FloatArray &x1 = * ( el->giveDofManager(1)->giveCoordinates() ); - const FloatArray &x2 = * ( el->giveDofManager(2)->giveCoordinates() ); - const double l = 1.0 * x1.distance(x2); + const auto &x1 = el->giveDofManager(1)->giveCoordinates(); + const auto &x2 = el->giveDofManager(2)->giveCoordinates(); + const double l = 1.0 * distance(x1, x2); // Use the octree to get all elements that have // at least one Gauss point in a certain region around the tip. @@ -189,7 +185,7 @@ bool PLHoopStressCirc :: propagateInterface(Domain &iDomain, EnrichmentFront &iE inFrontOfCrack = false; } - double r = circPoints [ pointIndex ].distance(globalCoord); + double r = distance(circPoints [ pointIndex ], globalCoord); if ( r < l && inFrontOfCrack ) { double w = ( ( l - r ) / ( pow(2.0 * M_PI, 1.5) * pow(l, 3) ) ) * exp( -0.5 * pow(r, 2) / pow(l, 2) ); diff --git a/src/sm/xfem/propagationlaws/plhoopstresscirc.h b/src/sm/xfem/propagationlaws/plhoopstresscirc.h index e2770095c..f2af1d852 100644 --- a/src/sm/xfem/propagationlaws/plhoopstresscirc.h +++ b/src/sm/xfem/propagationlaws/plhoopstresscirc.h @@ -78,14 +78,14 @@ class OOFEM_EXPORT PLHoopStressCirc : public PropagationLaw PLHoopStressCirc() : mRadius(0.0), mAngleInc(0.0), mIncrementLength(0.0), mHoopStressThreshold(0.0), mUseRadialBasisFunc(false) { } virtual ~PLHoopStressCirc() { } - virtual const char *giveClassName() const { return "PLHoopStressCirc"; } - virtual const char *giveInputRecordName() const { return _IFT_PLHoopStressCirc_Name; } + const char *giveClassName() const override { return "PLHoopStressCirc"; } + const char *giveInputRecordName() const override { return _IFT_PLHoopStressCirc_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual bool hasPropagation() const { return mIncrementLength > 0.; } ///@todo Could this be done smarter? / Mikael - virtual bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp); + bool hasPropagation() const override { return mIncrementLength > 0.; } ///@todo Could this be done smarter? / Mikael + bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) override; void setRadius(double iRadius) {mRadius = std::move(iRadius);} void setAngleInc(double iAngleInc) {mAngleInc = std::move(iAngleInc);} diff --git a/src/sm/xfem/propagationlaws/plmaterialforce.C b/src/sm/xfem/propagationlaws/plmaterialforce.C index 23f3f1679..492c53415 100644 --- a/src/sm/xfem/propagationlaws/plmaterialforce.C +++ b/src/sm/xfem/propagationlaws/plmaterialforce.C @@ -15,7 +15,7 @@ #include "spatiallocalizer.h" #include "floatmatrix.h" #include "gausspoint.h" -#include "Materials/structuralms.h" +#include "sm/Materials/structuralms.h" #include "xfem/enrichmentitem.h" #include "feinterpol.h" #include "xfem/xfemmanager.h" @@ -36,15 +36,11 @@ PLMaterialForce :: PLMaterialForce(): PLMaterialForce :: ~PLMaterialForce() {} -IRResultType PLMaterialForce :: initializeFrom(InputRecord *ir) +void PLMaterialForce :: initializeFrom(InputRecord &ir) { - IRResultType result; - IR_GIVE_FIELD(ir, mRadius, _IFT_PLMaterialForce_Radius); IR_GIVE_FIELD(ir, mIncrementLength, _IFT_PLMaterialForce_IncLength); IR_GIVE_OPTIONAL_FIELD(ir, mCrackPropThreshold, _IFT_PLMaterialForce_CrackPropThreshold); - - return IRRT_OK; } void PLMaterialForce :: giveInputRecord(DynamicInputRecord &input) @@ -72,13 +68,13 @@ bool PLMaterialForce :: propagateInterface(Domain &iDomain, EnrichmentFront &iEn SpatialLocalizer *localizer = iDomain.giveSpatialLocalizer(); FloatArray lCoords, closest; // printf("tipInfo.mGlobalCoord: \n"); tipInfo.mGlobalCoord.printYourself(); - if( tipInfo.mGlobalCoord.giveSize() == 0 ) { - return false; + if ( tipInfo.mGlobalCoord.giveSize() == 0 ) { + return false; } localizer->giveElementClosestToPoint(lCoords, closest, tipInfo.mGlobalCoord); - if(closest.distance(tipInfo.mGlobalCoord) > 1.0e-9) { + if ( distance(closest, tipInfo.mGlobalCoord) > 1.0e-9 ) { // printf("Tip is outside all elements.\n"); return false; } @@ -110,7 +106,7 @@ bool PLMaterialForce :: propagateInterface(Domain &iDomain, EnrichmentFront &iEn // printf("dir: "); dir.printYourself(); const double cosAngTol = 1.0/sqrt(2.0); - if(tipInfo.mTangDir.dotProduct(dir) < cosAngTol) { + if ( tipInfo.mTangDir.dotProduct(dir) < cosAngTol ) { // Do not allow sharper turns than 45 degrees if( tipInfo.mNormalDir.dotProduct(dir) > 0.0 ) { diff --git a/src/sm/xfem/propagationlaws/plmaterialforce.h b/src/sm/xfem/propagationlaws/plmaterialforce.h index 20c68f5b7..3f7379773 100644 --- a/src/sm/xfem/propagationlaws/plmaterialforce.h +++ b/src/sm/xfem/propagationlaws/plmaterialforce.h @@ -65,14 +65,14 @@ class OOFEM_EXPORT PLMaterialForce : public PropagationLaw PLMaterialForce(); virtual ~PLMaterialForce(); - virtual const char *giveClassName() const { return "PLMaterialForce"; } - virtual const char *giveInputRecordName() const { return _IFT_PLMaterialForce_Name; } + const char *giveClassName() const override { return "PLMaterialForce"; } + const char *giveInputRecordName() const override { return _IFT_PLMaterialForce_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual bool hasPropagation() const { return mIncrementLength > 0.; } ///@todo Could this be done smarter? / Mikael - virtual bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp); + bool hasPropagation() const override { return mIncrementLength > 0.; } ///@todo Could this be done smarter? / Mikael + bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) override; void setRadius(const double &iRadius) {mRadius = iRadius;} void setIncrementLength(const double &iIncrementLength) {mIncrementLength = iIncrementLength;} diff --git a/src/sm/xfem/propagationlaws/plprincipalstrain.C b/src/sm/xfem/propagationlaws/plprincipalstrain.C index 5442025d3..a26359e2e 100644 --- a/src/sm/xfem/propagationlaws/plprincipalstrain.C +++ b/src/sm/xfem/propagationlaws/plprincipalstrain.C @@ -45,8 +45,8 @@ #include "feinterpol.h" #include "xfem/xfemmanager.h" -#include "Materials/structuralms.h" -#include "Materials/structuralmaterial.h" +#include "sm/Materials/structuralms.h" +#include "sm/Materials/structuralmaterial.h" #include "xfem/XFEMDebugTools.h" @@ -63,10 +63,8 @@ PLPrincipalStrain::~PLPrincipalStrain() { } -IRResultType PLPrincipalStrain :: initializeFrom(InputRecord *ir) +void PLPrincipalStrain :: initializeFrom(InputRecord &ir) { - IRResultType result; - IR_GIVE_FIELD(ir, mRadius, _IFT_PLPrincipalStrain_Radius); IR_GIVE_FIELD(ir, mIncrementLength, _IFT_PLPrincipalStrain_IncLength); IR_GIVE_FIELD(ir, mStrainThreshold, _IFT_PLPrincipalStrain_StrainThreshold); @@ -76,8 +74,6 @@ IRResultType PLPrincipalStrain :: initializeFrom(InputRecord *ir) if ( useRadialBasisFunc == 1 ) { mUseRadialBasisFunc = true; } - - return IRRT_OK; } void PLPrincipalStrain :: giveInputRecord(DynamicInputRecord &input) @@ -113,7 +109,7 @@ bool PLPrincipalStrain :: propagateInterface(Domain &iDomain, EnrichmentFront &i // It is meaningless to propagate a tip that is not inside any element Element *el = localizer->giveElementContainingPoint(tipInfo.mGlobalCoord); - if ( el != NULL ) { + if ( el != nullptr ) { @@ -134,9 +130,9 @@ bool PLPrincipalStrain :: propagateInterface(Domain &iDomain, EnrichmentFront &i // crack tip multiplied by a constant factor. // ( This choice implies that we hope that the element has reasonable // aspect ratio.) - const FloatArray &x1 = * ( el->giveDofManager(1)->giveCoordinates() ); - const FloatArray &x2 = * ( el->giveDofManager(2)->giveCoordinates() ); - const double l = 1.0 * x1.distance(x2); + const auto &x1 = el->giveDofManager(1)->giveCoordinates(); + const auto &x2 = el->giveDofManager(2)->giveCoordinates(); + const double l = 1.0 * distance(x1, x2); // Use the octree to get all elements that have // at least one Gauss point in a certain region around the tip. @@ -152,7 +148,7 @@ bool PLPrincipalStrain :: propagateInterface(Domain &iDomain, EnrichmentFront &i for ( int elIndex: elIndices ) { Element *gpEl = iDomain.giveElement(elIndex); - for ( GaussPoint *gp_i: *gpEl->giveDefaultIntegrationRulePtr() ) { + for ( auto &gp_i: *gpEl->giveDefaultIntegrationRulePtr() ) { //////////////////////////////////////// // Compute global gp coordinates FloatArray N; @@ -181,7 +177,7 @@ bool PLPrincipalStrain :: propagateInterface(Domain &iDomain, EnrichmentFront &i inFrontOfCrack = false; } - double r = x.distance(globalCoord); + double r = distance(x, globalCoord); if ( r < l && inFrontOfCrack ) { double w = ( ( l - r ) / ( pow(2.0 * M_PI, 1.5) * pow(l, 3) ) ) * exp( -0.5 * pow(r, 2) / pow(l, 2) ); @@ -191,7 +187,7 @@ bool PLPrincipalStrain :: propagateInterface(Domain &iDomain, EnrichmentFront &i // Get stress StructuralMaterialStatus *ms = dynamic_cast< StructuralMaterialStatus * >( gp_i->giveMaterialStatus() ); - if ( ms == NULL ) { + if ( ms == nullptr ) { OOFEM_ERROR("failed to fetch MaterialStatus."); } @@ -223,7 +219,7 @@ bool PLPrincipalStrain :: propagateInterface(Domain &iDomain, EnrichmentFront &i // Compute strain StructuralMaterialStatus *ms = dynamic_cast< StructuralMaterialStatus * >( gp.giveMaterialStatus() ); - if ( ms == NULL ) { + if ( ms == nullptr ) { OOFEM_ERROR("failed to fetch MaterialStatus."); } @@ -238,7 +234,7 @@ bool PLPrincipalStrain :: propagateInterface(Domain &iDomain, EnrichmentFront &i // Compute stresses StructuralMaterialStatus *ms = dynamic_cast< StructuralMaterialStatus * >( gp.giveMaterialStatus() ); - if ( ms == NULL ) { + if ( ms == nullptr ) { OOFEM_ERROR("failed to fetch MaterialStatus."); } diff --git a/src/sm/xfem/propagationlaws/plprincipalstrain.h b/src/sm/xfem/propagationlaws/plprincipalstrain.h index 2d80686f7..1fec091b1 100644 --- a/src/sm/xfem/propagationlaws/plprincipalstrain.h +++ b/src/sm/xfem/propagationlaws/plprincipalstrain.h @@ -51,17 +51,17 @@ class DynamicInputRecord; class OOFEM_EXPORT PLPrincipalStrain : public PropagationLaw { public: - PLPrincipalStrain(); - virtual ~PLPrincipalStrain(); + PLPrincipalStrain(); + virtual ~PLPrincipalStrain(); - virtual const char *giveClassName() const { return "PLPrincipalStrain"; } - virtual const char *giveInputRecordName() const { return _IFT_PLPrincipalStrain_Name; } + const char *giveClassName() const override { return "PLPrincipalStrain"; } + const char *giveInputRecordName() const override { return _IFT_PLPrincipalStrain_Name; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual bool hasPropagation() const { return mIncrementLength > 0.; } - virtual bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp); + bool hasPropagation() const override { return mIncrementLength > 0.; } + bool propagateInterface(Domain &iDomain, EnrichmentFront &iEnrFront, TipPropagation &oTipProp) override; void setRadius(double iRadius) {mRadius = std::move(iRadius);} void setIncrementLength(double iIncrementLength) {mIncrementLength = std::move(iIncrementLength);} diff --git a/src/sm/xfem/xfemstructuralelementinterface.C b/src/sm/xfem/xfemstructuralelementinterface.C index f27c6782c..44fb7a54a 100644 --- a/src/sm/xfem/xfemstructuralelementinterface.C +++ b/src/sm/xfem/xfemstructuralelementinterface.C @@ -33,20 +33,20 @@ */ #include "xfemstructuralelementinterface.h" -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" -#include "../sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" -#include "../sm/Elements/structuralelement.h" -#include "../sm/CrossSections/structuralcrosssection.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerial.h" +#include "sm/Materials/InterfaceMaterials/structuralinterfacematerialstatus.h" +#include "sm/Elements/structuralelement.h" +#include "sm/CrossSections/structuralcrosssection.h" #include "gaussintegrationrule.h" #include "gausspoint.h" #include "dynamicinputrecord.h" #include "feinterpol.h" #include "spatiallocalizer.h" #include "engngm.h" -#include "Elements/nlstructuralelement.h" +#include "sm/Elements/nlstructuralelement.h" #include "mathfem.h" -#include "Materials/structuralfe2material.h" +#include "sm/Materials/structuralfe2material.h" #include "prescribedgradienthomogenization.h" #include "xfem/patchintegrationrule.h" @@ -78,18 +78,8 @@ namespace oofem { XfemStructuralElementInterface :: XfemStructuralElementInterface(Element *e) : - XfemElementInterface(e), - mpCZMat(NULL), - mCZMaterialNum(-1), - mCSNumGaussPoints(4), - mIncludeBulkJump(true), - mIncludeBulkCorr(true) -{ - - -} - -XfemStructuralElementInterface :: ~XfemStructuralElementInterface() {} + XfemElementInterface(e) +{} bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRule() { @@ -98,7 +88,7 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul bool partitionSucceeded = false; - if ( mpCZMat != NULL ) { + if ( mpCZMat != nullptr ) { mpCZIntegrationRules_tmp.clear(); mpCZExtraIntegrationRules_tmp.clear(); mIntRule_tmp.clear(); @@ -108,7 +98,7 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul XfemManager *xMan = this->element->giveDomain()->giveXfemManager(); if ( xMan->isElementEnriched(element) ) { - if ( mpCZMat == NULL && mCZMaterialNum > 0 ) { + if ( mpCZMat == nullptr && mCZMaterialNum > 0 ) { initializeCZMaterial(); } @@ -144,15 +134,15 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul firstIntersection = false; // Use XfemElementInterface_partitionElement to subdivide the element - for ( int i = 0; i < int ( pointPartitions.size() ); i++ ) { + for ( auto &partition : pointPartitions ) { // Triangulate the subdivisions - this->XfemElementInterface_partitionElement(mSubTri, pointPartitions [ i ]); + this->XfemElementInterface_partitionElement(mSubTri, partition); } - if ( mpCZMat != NULL ) { + if ( mpCZMat != nullptr ) { Crack *crack = dynamic_cast< Crack * >( xMan->giveEnrichmentItem(eiIndex) ); - if ( crack == NULL ) { + if ( crack == nullptr ) { OOFEM_ERROR("Cohesive zones are only available for cracks.") } @@ -166,10 +156,10 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) { int czRuleNum = 1; - mpCZIntegrationRules_tmp.emplace_back( new GaussIntegrationRule(czRuleNum, element) ); + mpCZIntegrationRules_tmp.push_back( std::make_unique(czRuleNum, element) ); - if(mIncludeBulkCorr) { - mpCZExtraIntegrationRules_tmp.emplace_back( new GaussIntegrationRule(czRuleNum, element) ); + if ( mIncludeBulkCorr ) { + mpCZExtraIntegrationRules_tmp.push_back( std::make_unique(czRuleNum, element) ); } size_t cz_rule_ind = mpCZIntegrationRules_tmp.size() - 1; @@ -187,30 +177,28 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul if ( crackTang.computeSquaredNorm() > tol2 ) { crackTang.normalize(); - } - else { - // Oops, we got a segment of length zero. - // These Gauss weights will be zero, so we can - // set the tangent to anything reasonable - crackTang = {0.0, 1.0}; - + } else { + // Oops, we got a segment of length zero. + // These Gauss weights will be zero, so we can + // set the tangent to anything reasonable + crackTang = {0.0, 1.0}; } FloatArray crackNormal = { - -crackTang.at(2), crackTang.at(1) + -crackTang.at(2), crackTang.at(1), 0. }; mpCZIntegrationRules_tmp [ cz_rule_ind ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode, crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]); - if(mIncludeBulkCorr) { - mpCZExtraIntegrationRules_tmp [ cz_rule_ind ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode, + if ( mIncludeBulkCorr ) { + mpCZExtraIntegrationRules_tmp [ cz_rule_ind ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode, crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]); } - for ( GaussPoint *gp: *mpCZIntegrationRules_tmp [ cz_rule_ind ] ) { + for ( auto &gp: *mpCZIntegrationRules_tmp [ cz_rule_ind ] ) { double gw = gp->giveWeight(); - double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]); + double segLength = distance(crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]); gw *= 0.5 * segLength; gp->setWeight(gw); @@ -218,92 +206,82 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); if ( ms ) { ms->letNormalBe(crackNormal); - } - else { - StructuralFE2MaterialStatus *fe2ms = dynamic_cast( mpCZMat->giveStatus(gp) ); + } else { + StructuralFE2MaterialStatus *fe2ms = dynamic_cast( mpCZMat->giveStatus(gp) ); - if(fe2ms) { - fe2ms->letNormalBe(crackNormal); + if ( fe2ms ) { + fe2ms->letNormalBe(crackNormal); - PrescribedGradientBCWeak *bc = dynamic_cast( fe2ms->giveBC() ); + PrescribedGradientBCWeak *bc = dynamic_cast( fe2ms->giveBC() ); - if(bc) { - FloatArray periodicityNormal = crackNormal; + if ( bc ) { + FloatArray periodicityNormal = crackNormal; - periodicityNormal.normalize(); + periodicityNormal.normalize(); - if( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) { - // Rotate 90 degrees (works equally well for periodicity) - periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)}; - } + if ( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) { + // Rotate 90 degrees (works equally well for periodicity) + periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)}; + } - bc->setPeriodicityNormal(periodicityNormal); - bc->recomputeTractionMesh(); - } - } - else { - OOFEM_ERROR("Failed to fetch material status."); - } + bc->setPeriodicityNormal(periodicityNormal); + bc->recomputeTractionMesh(); + } + } else { + OOFEM_ERROR("Failed to fetch material status."); + } } - // Give Gauss point reference to the enrichment item // to simplify post processing. crack->AppendCohesiveZoneGaussPoint(gp); } - if(mIncludeBulkCorr) { - - for ( GaussPoint *gp: *mpCZExtraIntegrationRules_tmp [ cz_rule_ind ] ) { - double gw = gp->giveWeight(); - double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]); - gw *= 0.5 * segLength; - gp->setWeight(gw); - - // Fetch material status and set normal - StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( gp->giveMaterialStatus() ); - if ( ms ) { - ms->letNormalBe(crackNormal); - } - else { - StructuralFE2MaterialStatus *fe2ms = dynamic_cast( gp->giveMaterialStatus() ); - - if(fe2ms) { - fe2ms->letNormalBe(crackNormal); + if ( mIncludeBulkCorr ) { + for ( auto &gp: *mpCZExtraIntegrationRules_tmp [ cz_rule_ind ] ) { + double gw = gp->giveWeight(); + double segLength = distance(crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]); + gw *= 0.5 * segLength; + gp->setWeight(gw); - PrescribedGradientBCWeak *bc = dynamic_cast( fe2ms->giveBC() ); + // Fetch material status and set normal + StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( gp->giveMaterialStatus() ); + if ( ms ) { + ms->letNormalBe(crackNormal); + } else { + StructuralFE2MaterialStatus *fe2ms = dynamic_cast( gp->giveMaterialStatus() ); - if(bc) { - FloatArray periodicityNormal = crackNormal; - periodicityNormal.normalize(); + if ( fe2ms ) { + fe2ms->letNormalBe(crackNormal); - if( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) { - // Rotate 90 degrees (works equally well for periodicity) - periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)}; - } + PrescribedGradientBCWeak *bc = dynamic_cast( fe2ms->giveBC() ); - bc->setPeriodicityNormal(periodicityNormal); - bc->recomputeTractionMesh(); + if ( bc) { + FloatArray periodicityNormal = crackNormal; + periodicityNormal.normalize(); - } - } - else { - // Macroscale material model: nothing needs to be done. - } - } + if ( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) { + // Rotate 90 degrees (works equally well for periodicity) + periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)}; + } - } + bc->setPeriodicityNormal(periodicityNormal); + bc->recomputeTractionMesh(); + } + } else { + // Macroscale material model: nothing needs to be done. + } + } + } } - } } partitionSucceeded = true; } - } // if(firstIntersection) - else { + } else { // if ( firstIntersection ) // Loop over triangles std :: vector< Triangle >allTriCopy; for ( size_t triIndex = 0; triIndex < mSubTri.size(); triIndex++ ) { @@ -322,9 +300,9 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul // Add cohesive zone Gauss points - if ( mpCZMat != NULL ) { + if ( mpCZMat != nullptr ) { Crack *crack = dynamic_cast< Crack * >( xMan->giveEnrichmentItem(eiIndex) ); - if ( crack == NULL ) { + if ( crack == nullptr ) { OOFEM_ERROR("Cohesive zones are only available for cracks.") } @@ -336,10 +314,10 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul for ( int segIndex = 0; segIndex < numSeg; segIndex++ ) { int czRuleNum = 1; - mpCZIntegrationRules_tmp.emplace_back( new GaussIntegrationRule(czRuleNum, element) ); + mpCZIntegrationRules_tmp.emplace_back( std::make_unique(czRuleNum, element) ); - if(mIncludeBulkCorr) { - mpCZExtraIntegrationRules_tmp.emplace_back( new GaussIntegrationRule(czRuleNum, element) ); + if ( mIncludeBulkCorr ) { + mpCZExtraIntegrationRules_tmp.emplace_back( std::make_unique(czRuleNum, element) ); } size_t newRuleInd = mpCZIntegrationRules_tmp.size() - 1; @@ -353,30 +331,26 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul if ( crackTang.computeSquaredNorm() > tol2 ) { crackTang.normalize(); + } else { + // Oops, we got a segment of length zero. + // These Gauss weights will be zero, so we can + // set the tangent to anything reasonable + crackTang = {0.0, 1.0}; } - else { - // Oops, we got a segment of length zero. - // These Gauss weights will be zero, so we can - // set the tangent to anything reasonable - crackTang = {0.0, 1.0}; - } - - FloatArray crackNormal = { - -crackTang.at(2), crackTang.at(1) - }; + FloatArrayF<3> crackNormal = { -crackTang.at(2), crackTang.at(1), 0.}; mpCZIntegrationRules_tmp [ newRuleInd ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode, crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]); - if(mIncludeBulkCorr) { - mpCZExtraIntegrationRules_tmp [ newRuleInd ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode, + if ( mIncludeBulkCorr ) { + mpCZExtraIntegrationRules_tmp [ newRuleInd ]->SetUpPointsOn2DEmbeddedLine(mCSNumGaussPoints, matMode, crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]); } - for ( GaussPoint *gp: *mpCZIntegrationRules_tmp [ newRuleInd ] ) { + for ( auto &gp: *mpCZIntegrationRules_tmp [ newRuleInd ] ) { double gw = gp->giveWeight(); - double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]); + double segLength = distance(crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]); gw *= 0.5 * segLength; gp->setWeight(gw); @@ -384,86 +358,80 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); if ( ms ) { ms->letNormalBe(crackNormal); - } - else { - StructuralFE2MaterialStatus *fe2ms = dynamic_cast( mpCZMat->giveStatus(gp) ); + } else { + StructuralFE2MaterialStatus *fe2ms = dynamic_cast( mpCZMat->giveStatus(gp) ); - if(fe2ms) { - fe2ms->letNormalBe(crackNormal); + if ( fe2ms ) { + fe2ms->letNormalBe(crackNormal); - PrescribedGradientBCWeak *bc = dynamic_cast( fe2ms->giveBC() ); + PrescribedGradientBCWeak *bc = dynamic_cast( fe2ms->giveBC() ); - if(bc) { - FloatArray periodicityNormal = crackNormal; + if ( bc ) { + FloatArray periodicityNormal = crackNormal; - periodicityNormal.normalize(); + periodicityNormal.normalize(); - if( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) { - // Rotate 90 degrees (works equally well for periodicity) - periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)}; - } + if ( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) { + // Rotate 90 degrees (works equally well for periodicity) + periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)}; + } - bc->setPeriodicityNormal(periodicityNormal); - bc->recomputeTractionMesh(); - } - } - else { - OOFEM_ERROR("Failed to fetch material status."); - } + bc->setPeriodicityNormal(periodicityNormal); + bc->recomputeTractionMesh(); + } + } else { + OOFEM_ERROR("Failed to fetch material status."); + } } - // Give Gauss point reference to the enrichment item // to simplify post processing. crack->AppendCohesiveZoneGaussPoint(gp); } - if(mIncludeBulkCorr) { - - for ( GaussPoint *gp: *mpCZExtraIntegrationRules_tmp [ newRuleInd ] ) { - double gw = gp->giveWeight(); - double segLength = crackPolygon [ segIndex ].distance(crackPolygon [ segIndex + 1 ]); - gw *= 0.5 * segLength; - gp->setWeight(gw); + if ( mIncludeBulkCorr ) { + for ( auto &gp: *mpCZExtraIntegrationRules_tmp [ newRuleInd ] ) { + double gw = gp->giveWeight(); + double segLength = distance(crackPolygon [ segIndex ], crackPolygon [ segIndex + 1 ]); + gw *= 0.5 * segLength; + gp->setWeight(gw); - // Fetch material status and set normal - StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); - if ( ms ) { - ms->letNormalBe(crackNormal); - } - else { - StructuralFE2MaterialStatus *fe2ms = dynamic_cast( mpCZMat->giveStatus(gp) ); - if(fe2ms) { - fe2ms->letNormalBe(crackNormal); + // Fetch material status and set normal + StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); + if ( ms ) { + ms->letNormalBe(crackNormal); + } else { + StructuralFE2MaterialStatus *fe2ms = dynamic_cast( mpCZMat->giveStatus(gp) ); - PrescribedGradientBCWeak *bc = dynamic_cast( fe2ms->giveBC() ); + if ( fe2ms ) { + fe2ms->letNormalBe(crackNormal); - if(bc) { - FloatArray periodicityNormal = crackNormal; + PrescribedGradientBCWeak *bc = dynamic_cast( fe2ms->giveBC() ); - periodicityNormal.normalize(); + if ( bc ) { + FloatArray periodicityNormal = crackNormal; - if( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) { - // Rotate 90 degrees (works equally well for periodicity) - periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)}; - } + periodicityNormal.normalize(); - bc->setPeriodicityNormal(periodicityNormal); - bc->recomputeTractionMesh(); - } - } - else { - OOFEM_ERROR("Failed to fetch material status."); - } - } + if ( periodicityNormal(0) < 0.0 && periodicityNormal(1) < 0.0 ) { + // Rotate 90 degrees (works equally well for periodicity) + periodicityNormal = {periodicityNormal(1), -periodicityNormal(0)}; + } + bc->setPeriodicityNormal(periodicityNormal); + bc->recomputeTractionMesh(); + } + } else { + OOFEM_ERROR("Failed to fetch material status."); + } + } - // Give Gauss point reference to the enrichment item - // to simplify post processing. - crack->AppendCohesiveZoneGaussPoint(gp); - } + // Give Gauss point reference to the enrichment item + // to simplify post processing. + crack->AppendCohesiveZoneGaussPoint(gp); + } } } } @@ -479,14 +447,11 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul // Refine triangles if desired int numRefs = xMan->giveNumTriRefs(); - for(int i = 0; i < numRefs; i++) { - + for ( int i = 0; i < numRefs; i++ ) { std :: vector< Triangle > triRef; - - for(const Triangle &tri : mSubTri) { + for ( const auto &tri : mSubTri ) { Triangle::refineTriangle(triRef, tri); } - mSubTri = triRef; } @@ -515,7 +480,7 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul if ( partitionSucceeded ) { std :: vector< std :: unique_ptr< IntegrationRule > >intRule; - mIntRule_tmp.emplace_back( new PatchIntegrationRule(ruleNum, element, mSubTri) ); + mIntRule_tmp.push_back( std::make_unique(ruleNum, element, mSubTri) ); mIntRule_tmp [ 0 ]->SetUpPointsOnTriangle(xMan->giveNumGpPerTri(), matMode); } @@ -527,7 +492,7 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul std :: vector< FloatArray >czGPCoord; for ( size_t czRulInd = 0; czRulInd < mpCZIntegrationRules_tmp.size(); czRulInd++ ) { - for ( GaussPoint *gp: *mpCZIntegrationRules_tmp [ czRulInd ] ) { + for ( auto &gp: *mpCZIntegrationRules_tmp [ czRulInd ] ) { czGPCoord.push_back( gp->giveGlobalCoordinates() ); } } @@ -535,11 +500,11 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul double time = 0.0; Domain *dom = element->giveDomain(); - if ( dom != NULL ) { + if ( dom != nullptr ) { EngngModel *em = dom->giveEngngModel(); - if ( em != NULL ) { + if ( em != nullptr ) { TimeStep *ts = em->giveCurrentStep(); - if ( ts != NULL ) { + if ( ts != nullptr ) { time = ts->giveTargetTime(); } } @@ -555,185 +520,156 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul } - bool map_state_variables = true; - if(map_state_variables) { + if ( map_state_variables ) { //////////////////////////////////////////////////////////////////////// - // Copy bulk GPs - int num_ir_new = mIntRule_tmp.size(); - for( int i = 0; i < num_ir_new; i++ ) { + // Copy bulk GPs + int num_ir_new = mIntRule_tmp.size(); + for ( int i = 0; i < num_ir_new; i++ ) { + + for ( auto &gp_new : *mIntRule_tmp[i] ) { + + + // Fetch new material status. Create it if it does not exist. + MaterialStatus *ms_new = dynamic_cast( gp_new->giveMaterialStatus() ); + if ( !ms_new ) { + StructuralElement *s_el = dynamic_cast(element); + StructuralCrossSection *cs = s_el->giveStructuralCrossSection(); + cs->createMaterialStatus(*gp_new); + ms_new = dynamic_cast( gp_new->giveMaterialStatus() ); + } - for(GaussPoint *gp_new : *(mIntRule_tmp[i]) ) { + // Find closest old GP. + double closest_dist = 0.0; + MaterialStatus *ms_old = giveClosestGP_MatStat( closest_dist, element->giveIntegrationRulesArray() , gp_new->giveGlobalCoordinates()); + if ( ms_old ) { + // Copy state variables. + MaterialStatusMapperInterface *mapper_interface = dynamic_cast( ms_new ); - // Fetch new material status. Create it if it does not exist. - MaterialStatus *ms_new = dynamic_cast( gp_new->giveMaterialStatus() ); - if(!ms_new) { - StructuralElement *s_el = dynamic_cast(element); - StructuralCrossSection *cs = s_el->giveStructuralCrossSection(); - cs->createMaterialStatus(*gp_new); - ms_new = dynamic_cast( gp_new->giveMaterialStatus() ); - } + if ( mapper_interface ) { + //printf("Successfully casted to MaterialStatusMapperInterface.\n"); + mapper_interface->copyStateVariables(*ms_old); + } else { + OOFEM_ERROR("Failed casting to MaterialStatusMapperInterface.") + } + } + } + } - // Find closest old GP. - double closest_dist = 0.0; - MaterialStatus *ms_old = giveClosestGP_MatStat( closest_dist, element->giveIntegrationRulesArray() , gp_new->giveGlobalCoordinates()); + //////////////////////////////////////////////////////////////////////// + // Copy CZ GPs + if ( mCZMaterialNum > 0 ) { - if(ms_old) { + num_ir_new = mpCZIntegrationRules_tmp.size(); + for ( int i = 0; i < num_ir_new; i++ ) { - // Copy state variables. - MaterialStatusMapperInterface *mapper_interface = dynamic_cast( ms_new ); + for ( auto &gp_new : *(mpCZIntegrationRules_tmp[i]) ) { - if(mapper_interface) { -// printf("Successfully casted to MaterialStatusMapperInterface.\n"); - mapper_interface->copyStateVariables(*ms_old); - } - else { - OOFEM_ERROR("Failed casting to MaterialStatusMapperInterface.") - } - } + // Fetch new material status. Create it if it does not exist. + MaterialStatus *ms_new = mpCZMat->giveStatus(gp_new); - } + // Find closest old GP. + double closest_dist_cz = 0.0; + MaterialStatus *ms_old = giveClosestGP_MatStat(closest_dist_cz, mpCZIntegrationRules , gp_new->giveGlobalCoordinates()); - } - //////////////////////////////////////////////////////////////////////// + // If we are using the nonstandard cz formulation, we + // also consider mapping from bulk GPs. + XfemStructureManager *xsMan = dynamic_cast( element->giveDomain()->giveXfemManager() ); + bool non_std_cz = false; + if ( xsMan ) { + non_std_cz = xsMan->giveUseNonStdCz(); + } + + if ( non_std_cz ) { + double closest_dist_bulk = 0.0; + MaterialStatus *ms_old_bulk = giveClosestGP_MatStat(closest_dist_bulk, element->giveIntegrationRulesArray() , gp_new->giveGlobalCoordinates()); + if ( closest_dist_bulk < closest_dist_cz ) { + printf("Bulk is closest. Dist: %e\n", closest_dist_bulk); + ms_old = ms_old_bulk; + } + } + if ( ms_old ) { + // Copy state variables. + MaterialStatusMapperInterface *mapper_interface = dynamic_cast( ms_new ); - //////////////////////////////////////////////////////////////////////// - // Copy CZ GPs - if( mCZMaterialNum > 0 ) { - - num_ir_new = mpCZIntegrationRules_tmp.size(); - for( int i = 0; i < num_ir_new; i++ ) { - - for(GaussPoint *gp_new : *(mpCZIntegrationRules_tmp[i]) ) { - - // Fetch new material status. Create it if it does not exist. - MaterialStatus *ms_new = dynamic_cast( gp_new->giveMaterialStatus() ); - if(!ms_new) { - ms_new = mpCZMat->CreateStatus(gp_new); - } - - // Find closest old GP. - double closest_dist_cz = 0.0; - MaterialStatus *ms_old = giveClosestGP_MatStat(closest_dist_cz, mpCZIntegrationRules , gp_new->giveGlobalCoordinates()); - - // If we are using the nonstandard cz formulation, we - // also consider mapping from bulk GPs. - XfemStructureManager *xsMan = dynamic_cast( element->giveDomain()->giveXfemManager() ); - bool non_std_cz = false; - if(xsMan) { - non_std_cz = xsMan->giveUseNonStdCz(); - } - - if(non_std_cz) { - double closest_dist_bulk = 0.0; - MaterialStatus *ms_old_bulk = giveClosestGP_MatStat(closest_dist_bulk, element->giveIntegrationRulesArray() , gp_new->giveGlobalCoordinates()); - if( closest_dist_bulk < closest_dist_cz ) { - printf("Bulk is closest. Dist: %e\n", closest_dist_bulk); - ms_old = ms_old_bulk; - } - } - - if(ms_old) { - - // Copy state variables. - MaterialStatusMapperInterface *mapper_interface = dynamic_cast( ms_new ); - - if(mapper_interface) { - mapper_interface->copyStateVariables(*ms_old); - } - else { - OOFEM_ERROR("Failed casting to MaterialStatusMapperInterface.") - } - } - - } - } - } + if ( mapper_interface ) { + mapper_interface->copyStateVariables(*ms_old); + } else { + OOFEM_ERROR("Failed casting to MaterialStatusMapperInterface.") + } + } + + } + } + } //////////////////////////////////////////////////////////////////////// + // Copy "extra" CZ GPs (Used for non-standard CZ model) + if ( mCZMaterialNum > 0 && mIncludeBulkCorr ) { + num_ir_new = mpCZExtraIntegrationRules_tmp.size(); + for ( int i = 0; i < num_ir_new; i++ ) { + for ( auto &gp_new : *(mpCZExtraIntegrationRules_tmp[i]) ) { + // Fetch new material status. Create it if it does not exist. + MaterialStatus *ms_new = mpCZMat->giveStatus(gp_new); - //////////////////////////////////////////////////////////////////////// - // Copy "extra" CZ GPs (Used for non-standard CZ model) - if( mCZMaterialNum > 0 && mIncludeBulkCorr ) { - - num_ir_new = mpCZExtraIntegrationRules_tmp.size(); - for( int i = 0; i < num_ir_new; i++ ) { - - for(GaussPoint *gp_new : *(mpCZExtraIntegrationRules_tmp[i]) ) { - - // Fetch new material status. Create it if it does not exist. - MaterialStatus *ms_new = dynamic_cast( gp_new->giveMaterialStatus() ); - if(!ms_new) { - ms_new = mpCZMat->CreateStatus(gp_new); - } - - // Find closest old GP. - double closest_dist_cz = 0.0; - MaterialStatus *ms_old = giveClosestGP_MatStat(closest_dist_cz, mpCZExtraIntegrationRules , gp_new->giveGlobalCoordinates()); - - // If we are using the nonstandard cz formulation, we - // also consider mapping from bulk GPs. - XfemStructureManager *xsMan = dynamic_cast( element->giveDomain()->giveXfemManager() ); - bool non_std_cz = false; - if(xsMan) { - non_std_cz = xsMan->giveUseNonStdCz(); - } - - if(non_std_cz) { - double closest_dist_bulk = 0.0; - MaterialStatus *ms_old_bulk = giveClosestGP_MatStat(closest_dist_bulk, element->giveIntegrationRulesArray() , gp_new->giveGlobalCoordinates()); - if( closest_dist_bulk < closest_dist_cz ) { - printf("Bulk is closest. Dist: %e\n", closest_dist_bulk); - ms_old = ms_old_bulk; - } - } - - if(ms_old) { - - // Copy state variables. - MaterialStatusMapperInterface *mapper_interface = dynamic_cast( ms_new ); - - if(mapper_interface) { - mapper_interface->copyStateVariables(*ms_old); - } - else { - OOFEM_ERROR("Failed casting to MaterialStatusMapperInterface.") - } - } - - } - } - } - else { -// printf("No extra CZ GPs to map.\n"); - } + // Find closest old GP. + double closest_dist_cz = 0.0; + MaterialStatus *ms_old = giveClosestGP_MatStat(closest_dist_cz, mpCZExtraIntegrationRules , gp_new->giveGlobalCoordinates()); - //////////////////////////////////////////////////////////////////////// + // If we are using the nonstandard cz formulation, we + // also consider mapping from bulk GPs. + XfemStructureManager *xsMan = dynamic_cast( element->giveDomain()->giveXfemManager() ); + bool non_std_cz = false; + if ( xsMan ) { + non_std_cz = xsMan->giveUseNonStdCz(); + } + if ( non_std_cz ) { + double closest_dist_bulk = 0.0; + MaterialStatus *ms_old_bulk = giveClosestGP_MatStat(closest_dist_bulk, element->giveIntegrationRulesArray() , gp_new->giveGlobalCoordinates()); + if ( closest_dist_bulk < closest_dist_cz ) { + printf("Bulk is closest. Dist: %e\n", closest_dist_bulk); + ms_old = ms_old_bulk; + } + } - } + if ( ms_old ) { + // Copy state variables. + MaterialStatusMapperInterface *mapper_interface = dynamic_cast( ms_new ); - } + if ( mapper_interface ) { + mapper_interface->copyStateVariables(*ms_old); + } else { + OOFEM_ERROR("Failed casting to MaterialStatusMapperInterface.") + } + } + } + } + } else { + //printf("No extra CZ GPs to map.\n"); + } + } + } if ( partitionSucceeded ) { - mpCZIntegrationRules = std::move(mpCZIntegrationRules_tmp); + mpCZIntegrationRules = std::move(mpCZIntegrationRules_tmp); - if(mIncludeBulkCorr) { - mpCZExtraIntegrationRules = std::move(mpCZExtraIntegrationRules_tmp); - } + if ( mIncludeBulkCorr ) { + mpCZExtraIntegrationRules = std::move(mpCZExtraIntegrationRules_tmp); + } - element->setIntegrationRules( std :: move(mIntRule_tmp) ); + element->setIntegrationRules( std :: move(mIntRule_tmp) ); } return partitionSucceeded; @@ -741,64 +677,61 @@ bool XfemStructuralElementInterface :: XfemElementInterface_updateIntegrationRul MaterialStatus* XfemStructuralElementInterface :: giveClosestGP_MatStat(double &oClosestDist, std :: vector< std :: unique_ptr< IntegrationRule > > &iRules, const FloatArray &iCoord) { + double min_dist2 = std::numeric_limits::max(); + MaterialStatus *closest_ms = nullptr; - double min_dist2 = std::numeric_limits::max(); - MaterialStatus *closest_ms = NULL; + for ( size_t i = 0; i < iRules.size(); i++ ) { + for ( auto &gp : *(iRules[i]) ) { - for(size_t i = 0; i < iRules.size(); i++) { - for(GaussPoint *gp : *(iRules[i]) ) { - - const FloatArray &x = gp->giveGlobalCoordinates(); - if( x.distance_square(iCoord) < min_dist2 ) { - min_dist2 = x.distance_square(iCoord); -// printf("min_dist2: %e\n", min_dist2 ); - closest_ms = dynamic_cast( gp->giveMaterialStatus() ); - } + const FloatArray &x = gp->giveGlobalCoordinates(); + double d2 = distance_square(x, iCoord); + if ( d2 < min_dist2 ) { + min_dist2 = d2; + closest_ms = dynamic_cast( gp->giveMaterialStatus() ); + } - } - } + } + } - oClosestDist = sqrt(min_dist2); - return closest_ms; + oClosestDist = sqrt(min_dist2); + return closest_ms; } double XfemStructuralElementInterface :: computeEffectiveSveSize(StructuralFE2MaterialStatus *iFe2Ms) { #if 0 - return 1.0*sqrt( iFe2Ms->giveBC()->domainSize() ); -// return 2.0*sqrt( iFe2Ms->giveBC()->domainSize() ); + //return 1.0*sqrt( iFe2Ms->giveBC()->domainSize() ); + //return 2.0*sqrt( iFe2Ms->giveBC()->domainSize() ); #else - // TODO: Cover also angle < 0 and angle > 90. + // TODO: Cover also angle < 0 and angle > 90. - const FloatArray &n = iFe2Ms->giveNormal(); - double l_box = sqrt( iFe2Ms->giveBC()->domainSize() ); + const FloatArray &n = iFe2Ms->giveNormal(); + double l_box = sqrt( iFe2Ms->giveBC()->domainSize() ); - const FloatArray t = {n(1), -n(0)}; - double angle = atan2( t(1), t(0) ); + const FloatArray t = {n(1), -n(0)}; + double angle = atan2( t(1), t(0) ); - if( angle < 0.25*M_PI ){ - // angle < 45 degrees + if ( angle < 0.25*M_PI ) { + // angle < 45 degrees - double l_s = l_box*(cos(angle)); - return l_s; - } - else { - // angle >= 45 degrees + double l_s = l_box*(cos(angle)); + return l_s; + } else { + // angle >= 45 degrees - double l_s = l_box*(sin(angle)); - return l_s; - } + double l_s = l_box*(sin(angle)); + return l_s; + } #endif - } void XfemStructuralElementInterface :: XfemElementInterface_computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) { if ( element->giveDomain()->hasXfemManager() ) { XfemManager *xMan = element->giveDomain()->giveXfemManager(); - CrossSection *cs = NULL; + CrossSection *cs = nullptr; const std :: vector< int > &materialModifyingEnrItemIndices = xMan->giveMaterialModifyingEnrItemIndices(); for ( size_t i = 0; i < materialModifyingEnrItemIndices.size(); i++ ) { @@ -807,11 +740,11 @@ void XfemStructuralElementInterface :: XfemElementInterface_computeConstitutiveM if ( ei.isMaterialModified(* gp, * element, cs) ) { StructuralCrossSection *structCS = dynamic_cast< StructuralCrossSection * >( cs ); - if ( structCS != NULL ) { + if ( structCS != nullptr ) { if ( mUsePlaneStrain ) { - structCS->giveStiffnessMatrix_PlaneStrain(answer, rMode, gp, tStep); + answer = structCS->giveStiffnessMatrix_PlaneStrain(rMode, gp, tStep); } else { - structCS->giveStiffnessMatrix_PlaneStress(answer, rMode, gp, tStep); + answer = structCS->giveStiffnessMatrix_PlaneStress(rMode, gp, tStep); } return; } else { @@ -823,38 +756,38 @@ void XfemStructuralElementInterface :: XfemElementInterface_computeConstitutiveM // If no enrichment modifies the material, // compute stiffness based on the bulk material. - StructuralCrossSection *cs = dynamic_cast< StructuralCrossSection * >( element->giveCrossSection() ); + auto cs = dynamic_cast< StructuralCrossSection * >( element->giveCrossSection() ); if ( mUsePlaneStrain ) { - cs->giveStiffnessMatrix_PlaneStrain(answer, rMode, gp, tStep); + answer = cs->giveStiffnessMatrix_PlaneStrain(rMode, gp, tStep); } else { - cs->giveStiffnessMatrix_PlaneStress(answer, rMode, gp, tStep); + answer = cs->giveStiffnessMatrix_PlaneStress(rMode, gp, tStep); } } void XfemStructuralElementInterface :: XfemElementInterface_computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) { - StructuralCrossSection *cs = dynamic_cast< StructuralCrossSection * >( element->giveCrossSection() ); - if ( cs == NULL ) { - OOFEM_ERROR("cs == NULL."); + auto cs = dynamic_cast< StructuralCrossSection * >( element->giveCrossSection() ); + if ( cs == nullptr ) { + OOFEM_ERROR("cs == nullptr."); } if ( element->giveDomain()->hasXfemManager() ) { XfemManager *xMan = element->giveDomain()->giveXfemManager(); - CrossSection *csInclusion = NULL; + CrossSection *csInclusion = nullptr; const std :: vector< int > &materialModifyingEnrItemIndices = xMan->giveMaterialModifyingEnrItemIndices(); for ( size_t i = 0; i < materialModifyingEnrItemIndices.size(); i++ ) { EnrichmentItem &ei = * ( xMan->giveEnrichmentItem(materialModifyingEnrItemIndices [ i ]) ); if ( ei.isMaterialModified(* gp, * element, csInclusion) ) { - StructuralCrossSection *structCSInclusion = dynamic_cast< StructuralCrossSection * >( csInclusion ); + auto structCSInclusion = dynamic_cast< StructuralCrossSection * >( csInclusion ); - if ( structCSInclusion != NULL ) { + if ( structCSInclusion != nullptr ) { if ( mUsePlaneStrain ) { - structCSInclusion->giveRealStress_PlaneStrain(answer, gp, strain, tStep); + answer = structCSInclusion->giveRealStress_PlaneStrain(strain, gp, tStep); } else { - structCSInclusion->giveRealStress_PlaneStress(answer, gp, strain, tStep); + answer = structCSInclusion->giveRealStress_PlaneStress(strain, gp, tStep); } return; @@ -867,627 +800,584 @@ void XfemStructuralElementInterface :: XfemElementInterface_computeStressVector( // If no enrichment modifies the material: if ( mUsePlaneStrain ) { - cs->giveRealStress_PlaneStrain(answer, gp, strain, tStep); + answer = cs->giveRealStress_PlaneStrain(strain, gp, tStep); } else { - cs->giveRealStress_PlaneStress(answer, gp, strain, tStep); + answer = cs->giveRealStress_PlaneStress(strain, gp, tStep); } } void XfemStructuralElementInterface :: computeCohesiveForces(FloatArray &answer, TimeStep *tStep) { - if(!useNonStdCz()) { - - if ( hasCohesiveZone() ) { - FloatArray solVec; - element->computeVectorOf(VM_Total, tStep, solVec); - - size_t numSeg = mpCZIntegrationRules.size(); - for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) { - for ( GaussPoint *gp: *mpCZIntegrationRules [ segIndex ] ) { - //////////////////////////////////////////////////////// - // Compute a (slightly modified) N-matrix - - FloatMatrix NMatrix; - computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]); - //////////////////////////////////////////////////////// - + if ( !useNonStdCz() ) { - // Traction - FloatArray T2D; + if ( hasCohesiveZone() ) { + FloatArray solVec; + element->computeVectorOf(VM_Total, tStep, solVec); + size_t numSeg = mpCZIntegrationRules.size(); + for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) { + for ( auto &gp: *mpCZIntegrationRules [ segIndex ] ) { + //////////////////////////////////////////////////////// + // Compute a (slightly modified) N-matrix - // Fetch material status and get normal - StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); - if ( ms == NULL ) { - OOFEM_ERROR("Failed to fetch material status."); - } - - ms->setNewlyInserted(false); //TODO: Do this in a better place. /ES - - FloatArray crackNormal( ms->giveNormal() ); - - // Compute jump vector - FloatArray jump2D; - computeDisplacementJump(* gp, jump2D, solVec, NMatrix); + FloatMatrix NMatrix; + computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]); + //////////////////////////////////////////////////////// - computeGlobalCohesiveTractionVector(T2D, jump2D, crackNormal, NMatrix, * gp, tStep); + // Traction + FloatArray T2D; - // Add to internal force - FloatArray NTimesT; - NTimesT.beTProductOf(NMatrix, T2D); - CrossSection *cs = element->giveCrossSection(); - double thickness = cs->give(CS_Thickness, gp); - double dA = thickness * gp->giveWeight(); - answer.add(dA, NTimesT); - } - } - } - } - else { - // Non-standard cz formulation. -// printf("Using non-standard cz formulation.\n"); + // Fetch material status and get normal + StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); + if ( ms == nullptr ) { + OOFEM_ERROR("Failed to fetch material status."); + } - if ( hasCohesiveZone() ) { - FloatArray solVec; - element->computeVectorOf(VM_Total, tStep, solVec); + ms->setNewlyInserted(false); //TODO: Do this in a better place. /ES - StructuralFE2Material *fe2Mat = dynamic_cast(mpCZMat); - if(!fe2Mat) { - OOFEM_ERROR("Failed to cast StructuralFE2Material*.") - } + FloatArray crackNormal( ms->giveNormal() ); + // Compute jump vector + FloatArray jump2D; + computeDisplacementJump(* gp, jump2D, solVec, NMatrix); - size_t numSeg = mpCZIntegrationRules.size(); - for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) { - for(int gpInd = 0; gpInd < mpCZIntegrationRules[ segIndex ]->giveNumberOfIntegrationPoints(); gpInd++) { - GaussPoint *gp = mpCZIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd); + computeGlobalCohesiveTractionVector(T2D, jump2D, crackNormal, NMatrix, * gp, tStep); - GaussPoint *bulk_gp = NULL; - if(mIncludeBulkCorr) { - bulk_gp = mpCZExtraIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd); - } + // Add to internal force + FloatArray NTimesT; - StructuralMaterial *bulkMat = dynamic_cast( element->giveCrossSection()->giveMaterial(bulk_gp) ); - if(!bulkMat) { - OOFEM_ERROR("Failed to fetch bulk material.") - } + NTimesT.beTProductOf(NMatrix, T2D); + CrossSection *cs = element->giveCrossSection(); + double thickness = cs->give(CS_Thickness, gp); + double dA = thickness * gp->giveWeight(); + answer.add(dA, NTimesT); + } + } + } + } else { + // Non-standard cz formulation. + //printf("Using non-standard cz formulation.\n"); - StructuralFE2MaterialStatus *fe2ms = dynamic_cast ( gp->giveMaterialStatus() ); + if ( hasCohesiveZone() ) { + FloatArray solVec; + element->computeVectorOf(VM_Total, tStep, solVec); - if(fe2ms == NULL) { - OOFEM_ERROR("The material status is not of an allowed type.") - } + StructuralFE2Material *fe2Mat = dynamic_cast(mpCZMat); + if ( !fe2Mat ) { + OOFEM_ERROR("Failed to cast StructuralFE2Material*.") + } - //////////////////////////////////////////////////////// - // Compute jump + size_t numSeg = mpCZIntegrationRules.size(); + for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) { + for ( int gpInd = 0; gpInd < mpCZIntegrationRules[ segIndex ]->giveNumberOfIntegrationPoints(); gpInd++ ) { - // Compute a (slightly modified) N-matrix - FloatMatrix NMatrix; - computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]); + GaussPoint *gp = mpCZIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd); - FloatArray jump2D; - computeDisplacementJump(* gp, jump2D, solVec, NMatrix); + GaussPoint *bulk_gp = nullptr; + if ( mIncludeBulkCorr ) { + bulk_gp = mpCZExtraIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd); + } - //////////////////////////////////////////////////////// - // Fetch normal - FloatArray crackNormal( fe2ms->giveNormal() ); + StructuralMaterial *bulkMat = dynamic_cast( element->giveCrossSection()->giveMaterial(bulk_gp) ); + if ( !bulkMat ) { + OOFEM_ERROR("Failed to fetch bulk material.") + } + StructuralFE2MaterialStatus *fe2ms = dynamic_cast ( gp->giveMaterialStatus() ); - //////////////////////////////////////////////////////// - // Fetch L_s - double l_s = computeEffectiveSveSize( fe2ms ); + if ( fe2ms == nullptr ) { + OOFEM_ERROR("The material status is not of an allowed type.") + } + //////////////////////////////////////////////////////// + // Compute jump - //////////////////////////////////////////////////////// - // Construct strain (only consider the smeared jump for now) - FloatArray smearedJumpStrain = {jump2D(0)*crackNormal(0)/l_s, jump2D(1)*crackNormal(1)/l_s, 0.0, 0.0, 0.0, (1.0/l_s)*( jump2D(0)*crackNormal(1) + jump2D(1)*crackNormal(0) )}; + // Compute a (slightly modified) N-matrix + FloatMatrix NMatrix; + computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]); - FloatArray smearedBulkStrain(6); - smearedBulkStrain.zero(); - FloatMatrix BAvg; + FloatArray jump2D; + computeDisplacementJump(* gp, jump2D, solVec, NMatrix); - if(mIncludeBulkJump) { - //////////////////////////////////////////////////////// - // Bulk contribution to SVE strain + //////////////////////////////////////////////////////// + // Fetch normal + FloatArray crackNormal( fe2ms->giveNormal() ); - // Crack gp coordinates - const FloatArray &xC = gp->giveGlobalCoordinates(); - // For now, we will just perturb the coordinates of the GP to compute B^- and B^+ numerically. - double eps = 1.0e-6; - FloatArray xPert = xC; + //////////////////////////////////////////////////////// + // Fetch L_s + double l_s = computeEffectiveSveSize( fe2ms ); - xPert.add(eps, crackNormal); - FloatArray locCoordPert; - element->computeLocalCoordinates(locCoordPert, xPert); - FloatMatrix BPlus; - this->ComputeBOrBHMatrix(BPlus, *gp, *element, false, locCoordPert); + //////////////////////////////////////////////////////// + // Construct strain (only consider the smeared jump for now) + FloatArray smearedJumpStrain = {jump2D(0)*crackNormal(0)/l_s, jump2D(1)*crackNormal(1)/l_s, 0.0, 0.0, 0.0, (1.0/l_s)*( jump2D(0)*crackNormal(1) + jump2D(1)*crackNormal(0) )}; - xPert = xC; - xPert.add(-eps, crackNormal); - element->computeLocalCoordinates(locCoordPert, xPert); + FloatArray smearedBulkStrain(6); + smearedBulkStrain.zero(); + FloatMatrix BAvg; - FloatMatrix BMinus; - this->ComputeBOrBHMatrix(BMinus, *gp, *element, false, locCoordPert); + if ( mIncludeBulkJump ) { + //////////////////////////////////////////////////////// + // Bulk contribution to SVE strain - BAvg = BPlus; - BAvg.add(1.0, BMinus); - BAvg.times(0.5); + // Crack gp coordinates + const FloatArray &xC = gp->giveGlobalCoordinates(); - smearedBulkStrain.beProductOf(BAvg, solVec); + // For now, we will just perturb the coordinates of the GP to compute B^- and B^+ numerically. + double eps = 1.0e-6; + FloatArray xPert = xC; - if( smearedBulkStrain.giveSize() == 4 ) { - smearedBulkStrain = {smearedBulkStrain(0), smearedBulkStrain(1), smearedBulkStrain(2), 0.0, 0.0, smearedBulkStrain(3)}; - } + xPert.add(eps, crackNormal); + FloatArray locCoordPert; + element->computeLocalCoordinates(locCoordPert, xPert); - FloatArray smearedJumpStrainTemp = smearedJumpStrain; + FloatMatrix BPlus; + this->ComputeBOrBHMatrix(BPlus, *gp, *element, false, locCoordPert); - smearedJumpStrain.add(smearedBulkStrain); - } + xPert = xC; + xPert.add(-eps, crackNormal); + element->computeLocalCoordinates(locCoordPert, xPert); + FloatMatrix BMinus; + this->ComputeBOrBHMatrix(BMinus, *gp, *element, false, locCoordPert); - //////////////////////////////////////////////////////// - // Compute homogenized stress - StructuralElement *se = dynamic_cast(this->element); - if(!se) { - OOFEM_ERROR("Failed to cast StructuralElement.") - } + BAvg = BPlus; + BAvg.add(1.0, BMinus); + BAvg.times(0.5); - FloatArray stressVec; + smearedBulkStrain.beProductOf(BAvg, solVec); - fe2Mat->giveRealStressVector_3d(stressVec, gp, smearedJumpStrain, tStep); -// printf("stressVec: "); stressVec.printYourself(); + if ( smearedBulkStrain.giveSize() == 4 ) { + smearedBulkStrain = {smearedBulkStrain(0), smearedBulkStrain(1), smearedBulkStrain(2), 0.0, 0.0, smearedBulkStrain(3)}; + } + FloatArray smearedJumpStrainTemp = smearedJumpStrain; - FloatArray trac = {stressVec(0)*crackNormal(0)+stressVec(5)*crackNormal(1), stressVec(5)*crackNormal(0)+stressVec(1)*crackNormal(1)}; + smearedJumpStrain.add(smearedBulkStrain); + } - //////////////////////////////////////////////////////// - // Standard part - // Add to internal force - FloatArray NTimesT; + //////////////////////////////////////////////////////// + // Compute homogenized stress + StructuralElement *se = dynamic_cast(this->element); + if ( !se ) { + OOFEM_ERROR("Failed to cast StructuralElement.") + } - NTimesT.beTProductOf(NMatrix, trac); - CrossSection *cs = element->giveCrossSection(); - double thickness = cs->give(CS_Thickness, gp); - double dA = thickness * gp->giveWeight(); - answer.add(dA, NTimesT); + auto stressVec = fe2Mat->giveRealStressVector_3d(smearedJumpStrain, gp, tStep); + //printf("stressVec: "); stressVec.printYourself(); + FloatArray trac = {stressVec[0]*crackNormal[0]+stressVec[5]*crackNormal[1], stressVec[5]*crackNormal[0]+stressVec[1]*crackNormal[1]}; - if(mIncludeBulkCorr) { + //////////////////////////////////////////////////////// + // Standard part - FloatArray stressVecBulk; - bulkMat->giveRealStressVector_3d(stressVecBulk, bulk_gp, smearedBulkStrain, tStep); + // Add to internal force + FloatArray NTimesT; - //////////////////////////////////////////////////////// - // Non-standard jump part - FloatArray stressV4 = {stressVec(0)-stressVecBulk(0), stressVec(1)-stressVecBulk(1), stressVec(2)-stressVecBulk(2), stressVec(5)-stressVecBulk(5)}; - FloatArray BTimesT; - BTimesT.beTProductOf(BAvg, stressV4); - answer.add(1.0*dA*l_s, BTimesT); - } + NTimesT.beTProductOf(NMatrix, trac); + CrossSection *cs = element->giveCrossSection(); + double thickness = cs->give(CS_Thickness, gp); + double dA = thickness * gp->giveWeight(); + answer.add(dA, NTimesT); - } - } - } + if ( mIncludeBulkCorr ) { + auto stressVecBulk = bulkMat->giveRealStressVector_3d(smearedBulkStrain, bulk_gp, tStep); - } + //////////////////////////////////////////////////////// + // Non-standard jump part + FloatArray stressV4 = {stressVec[0]-stressVecBulk[0], stressVec[1]-stressVecBulk[1], stressVec[2]-stressVecBulk[2], stressVec[5]-stressVecBulk[5]}; + FloatArray BTimesT; + BTimesT.beTProductOf(BAvg, stressV4); + answer.add(1.0*dA*l_s, BTimesT); + } + } + } + } + } } void XfemStructuralElementInterface :: computeGlobalCohesiveTractionVector(FloatArray &oT, const FloatArray &iJump, const FloatArray &iCrackNormal, const FloatMatrix &iNMatrix, GaussPoint &iGP, TimeStep *tStep) { - FloatMatrix F; - F.resize(3, 3); - F.beUnitMatrix(); // TODO: Compute properly + auto F = eye<3>(); // TODO: Compute properly + FloatArrayF<3> jump3D = {iJump.at(1), iJump.at(2), 0.0}; - FloatArray jump3D = { - iJump.at(1), iJump.at(2), 0.0 - }; + FloatArrayF<3> crackNormal3D = {iCrackNormal.at(1), iCrackNormal.at(2), 0.0}; + FloatArrayF<3> ez = {0.0, 0.0, 1.0}; + auto crackTangent3D = cross(crackNormal3D, ez); - FloatArray crackNormal3D = { - iCrackNormal.at(1), iCrackNormal.at(2), 0.0 - }; + FloatMatrixF<3,3> locToGlob; + locToGlob.setColumn(crackTangent3D, 0); + locToGlob.setColumn(crackNormal3D, 1); + locToGlob.setColumn(ez, 2); - FloatArray ez = { - 0.0, 0.0, 1.0 - }; - FloatArray crackTangent3D; - crackTangent3D.beVectorProductOf(crackNormal3D, ez); + FloatArrayF<3> jump3DLoc = Tdot(locToGlob, jump3D); - FloatMatrix locToGlob(3, 3); - locToGlob.setColumn(crackTangent3D, 1); - locToGlob.setColumn(crackNormal3D, 2); - locToGlob.setColumn(ez, 3); - - FloatArray TLoc, jump3DLoc, TLocRenumbered(3); - jump3DLoc.beTProductOf(locToGlob, jump3D); - - FloatArray jump3DLocRenumbered = { - jump3DLoc.at(3), jump3DLoc.at(1), jump3DLoc.at(2) - }; + FloatArrayF<3> jump3DLocRenumbered = {jump3DLoc.at(3), jump3DLoc.at(1), jump3DLoc.at(2)}; StructuralInterfaceMaterial *intMat = dynamic_cast(mpCZMat); - if(intMat) { - intMat->giveFirstPKTraction_3d(TLocRenumbered, & iGP, jump3DLocRenumbered, F, tStep); + if ( intMat == nullptr ) { + OOFEM_ERROR("Failed to cast StructuralInterfaceMaterial*.") } - else { - OOFEM_ERROR("Failed to cast StructuralInterfaceMaterial*.") - } - - TLoc = { - TLocRenumbered.at(2), TLocRenumbered.at(3), TLocRenumbered.at(1) - }; + auto TLocRenumbered = intMat->giveFirstPKTraction_3d(jump3DLocRenumbered, F, & iGP, tStep); + FloatArrayF<3> TLoc = {TLocRenumbered.at(2), TLocRenumbered.at(3), TLocRenumbered.at(1)}; - FloatArray T; - T.beProductOf(locToGlob, TLoc); + auto T = dot(locToGlob, TLoc); - oT = { - T.at(1), T.at(2) - }; + oT = {T.at(1), T.at(2)}; } void XfemStructuralElementInterface :: computeCohesiveTangent(FloatMatrix &answer, TimeStep *tStep) { + if ( !useNonStdCz() ) { - if(!useNonStdCz()) { + if ( hasCohesiveZone() ) { + FloatArray solVec; + element->computeVectorOf(VM_Total, tStep, solVec); - if ( hasCohesiveZone() ) { - FloatArray solVec; - element->computeVectorOf(VM_Total, tStep, solVec); + size_t numSeg = mpCZIntegrationRules.size(); - size_t numSeg = mpCZIntegrationRules.size(); - - StructuralInterfaceMaterial *intMat = dynamic_cast(mpCZMat); - if(!intMat) { - OOFEM_ERROR("Failed to cast StructuralInterfaceMaterial*.") - } - - - for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) { - for ( GaussPoint *gp: *mpCZIntegrationRules [ segIndex ] ) { - //////////////////////////////////////////////////////// - // Compute a (slightly modified) N-matrix - - FloatMatrix NMatrix; - computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]); + StructuralInterfaceMaterial *intMat = dynamic_cast(mpCZMat); + if ( !intMat ) { + OOFEM_ERROR("Failed to cast StructuralInterfaceMaterial*.") + } - //////////////////////////////////////////////////////// - // Compute jump vector - FloatArray jump2D; - computeDisplacementJump(* gp, jump2D, solVec, NMatrix); + for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) { + for ( auto &gp: *mpCZIntegrationRules [ segIndex ] ) { + //////////////////////////////////////////////////////// + // Compute a (slightly modified) N-matrix - FloatArray jump3D = { - 0.0, jump2D.at(1), jump2D.at(2) - }; + FloatMatrix NMatrix; + computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]); - // Compute traction - FloatMatrix F; - F.resize(3, 3); - F.beUnitMatrix(); // TODO: Compute properly + //////////////////////////////////////////////////////// + // Compute jump vector + FloatArray jump2D; + computeDisplacementJump(* gp, jump2D, solVec, NMatrix); - FloatMatrix K3DRenumbered, K3DGlob; + FloatArray jump3D = { + 0.0, jump2D.at(1), jump2D.at(2) + }; + // Compute traction + FloatMatrix F; + F.resize(3, 3); + F.beUnitMatrix(); // TODO: Compute properly - FloatMatrix K2D; - K2D.resize(2, 2); - K2D.zero(); + FloatMatrix K3DGlob; - if ( intMat->hasAnalyticalTangentStiffness() ) { - /////////////////////////////////////////////////// - // Analytical tangent + FloatMatrix K2D; + K2D.resize(2, 2); + K2D.zero(); - FloatMatrix K3D; - intMat->give3dStiffnessMatrix_dTdj(K3DRenumbered, TangentStiffness, gp, tStep); + if ( intMat->hasAnalyticalTangentStiffness() ) { + /////////////////////////////////////////////////// + // Analytical tangent - K3D.resize(3, 3); - K3D.zero(); - K3D.at(1, 1) = K3DRenumbered.at(2, 2); - K3D.at(1, 2) = K3DRenumbered.at(2, 3); - K3D.at(1, 3) = K3DRenumbered.at(2, 1); + auto K3DRenumbered = intMat->give3dStiffnessMatrix_dTdj(TangentStiffness, gp, tStep); - K3D.at(2, 1) = K3DRenumbered.at(3, 2); - K3D.at(2, 2) = K3DRenumbered.at(3, 3); - K3D.at(2, 3) = K3DRenumbered.at(3, 1); + FloatMatrix K3D(3,3); + K3D.at(1, 1) = K3DRenumbered.at(2, 2); + K3D.at(1, 2) = K3DRenumbered.at(2, 3); + K3D.at(1, 3) = K3DRenumbered.at(2, 1); - K3D.at(3, 1) = K3DRenumbered.at(1, 2); - K3D.at(3, 2) = K3DRenumbered.at(1, 3); - K3D.at(3, 3) = K3DRenumbered.at(1, 1); + K3D.at(2, 1) = K3DRenumbered.at(3, 2); + K3D.at(2, 2) = K3DRenumbered.at(3, 3); + K3D.at(2, 3) = K3DRenumbered.at(3, 1); + K3D.at(3, 1) = K3DRenumbered.at(1, 2); + K3D.at(3, 2) = K3DRenumbered.at(1, 3); + K3D.at(3, 3) = K3DRenumbered.at(1, 1); - // Fetch material status and get normal - StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); - if ( ms == NULL ) { - OOFEM_ERROR("Failed to fetch material status."); - } - FloatArray crackNormal( ms->giveNormal() ); + // Fetch material status and get normal + StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); + if ( ms == nullptr ) { + OOFEM_ERROR("Failed to fetch material status."); + } - FloatArray crackNormal3D = { - crackNormal.at(1), crackNormal.at(2), 0.0 - }; + FloatArray crackNormal( ms->giveNormal() ); - FloatArray ez = { - 0.0, 0.0, 1.0 - }; - FloatArray crackTangent3D; - crackTangent3D.beVectorProductOf(crackNormal3D, ez); + FloatArray crackNormal3D = { + crackNormal.at(1), crackNormal.at(2), 0.0 + }; - FloatMatrix locToGlob(3, 3); - locToGlob.setColumn(crackTangent3D, 1); - locToGlob.setColumn(crackNormal3D, 2); - locToGlob.setColumn(ez, 3); + FloatArray ez = { + 0.0, 0.0, 1.0 + }; + FloatArray crackTangent3D; + crackTangent3D.beVectorProductOf(crackNormal3D, ez); + FloatMatrix locToGlob(3, 3); + locToGlob.setColumn(crackTangent3D, 1); + locToGlob.setColumn(crackNormal3D, 2); + locToGlob.setColumn(ez, 3); - FloatMatrix tmp3(3, 3); - tmp3.beProductTOf(K3D, locToGlob); - K3DGlob.beProductOf(locToGlob, tmp3); - K2D.at(1, 1) = K3DGlob.at(1, 1); - K2D.at(1, 2) = K3DGlob.at(1, 2); - K2D.at(2, 1) = K3DGlob.at(2, 1); - K2D.at(2, 2) = K3DGlob.at(2, 2); - } else { - /////////////////////////////////////////////////// - // Numerical tangent - double eps = 1.0e-9; + FloatMatrix tmp3(3, 3); + tmp3.beProductTOf(K3D, locToGlob); + K3DGlob.beProductOf(locToGlob, tmp3); - FloatArray T, TPert; + K2D.at(1, 1) = K3DGlob.at(1, 1); + K2D.at(1, 2) = K3DGlob.at(1, 2); + K2D.at(2, 1) = K3DGlob.at(2, 1); + K2D.at(2, 2) = K3DGlob.at(2, 2); + } else { + /////////////////////////////////////////////////// + // Numerical tangent + double eps = 1.0e-9; - // Fetch material status and get normal - StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); - if ( ms == NULL ) { - OOFEM_ERROR("Failed to fetch material status."); - } + FloatArray T, TPert; - FloatArray crackNormal( ms->giveNormal() ); + // Fetch material status and get normal + StructuralInterfaceMaterialStatus *ms = dynamic_cast< StructuralInterfaceMaterialStatus * >( mpCZMat->giveStatus(gp) ); + if ( ms == nullptr ) { + OOFEM_ERROR("Failed to fetch material status."); + } - computeGlobalCohesiveTractionVector(T, jump2D, crackNormal, NMatrix, * gp, tStep); + FloatArray crackNormal( ms->giveNormal() ); + computeGlobalCohesiveTractionVector(T, jump2D, crackNormal, NMatrix, * gp, tStep); - FloatArray jump2DPert; + FloatArray jump2DPert; - jump2DPert = jump2D; - jump2DPert.at(1) += eps; - computeGlobalCohesiveTractionVector(TPert, jump2DPert, crackNormal, NMatrix, * gp, tStep); - K2D.at(1, 1) = ( TPert.at(1) - T.at(1) ) / eps; - K2D.at(2, 1) = ( TPert.at(2) - T.at(2) ) / eps; + jump2DPert = jump2D; + jump2DPert.at(1) += eps; + computeGlobalCohesiveTractionVector(TPert, jump2DPert, crackNormal, NMatrix, * gp, tStep); - jump2DPert = jump2D; - jump2DPert.at(2) += eps; - computeGlobalCohesiveTractionVector(TPert, jump2DPert, crackNormal, NMatrix, * gp, tStep); + K2D.at(1, 1) = ( TPert.at(1) - T.at(1) ) / eps; + K2D.at(2, 1) = ( TPert.at(2) - T.at(2) ) / eps; - K2D.at(1, 2) = ( TPert.at(1) - T.at(1) ) / eps; - K2D.at(2, 2) = ( TPert.at(2) - T.at(2) ) / eps; + jump2DPert = jump2D; + jump2DPert.at(2) += eps; + computeGlobalCohesiveTractionVector(TPert, jump2DPert, crackNormal, NMatrix, * gp, tStep); - computeGlobalCohesiveTractionVector(T, jump2D, crackNormal, NMatrix, * gp, tStep); - } + K2D.at(1, 2) = ( TPert.at(1) - T.at(1) ) / eps; + K2D.at(2, 2) = ( TPert.at(2) - T.at(2) ) / eps; - FloatMatrix tmp, tmp2; - tmp.beProductOf(K2D, NMatrix); - tmp2.beTProductOf(NMatrix, tmp); + computeGlobalCohesiveTractionVector(T, jump2D, crackNormal, NMatrix, * gp, tStep); + } - CrossSection *cs = element->giveCrossSection(); - double thickness = cs->give(CS_Thickness, gp); - double dA = thickness * gp->giveWeight(); - answer.add(dA, tmp2); - } - } - } - } - else { - // Non-standard cz formulation. + FloatMatrix tmp, tmp2; + tmp.beProductOf(K2D, NMatrix); + tmp2.beTProductOf(NMatrix, tmp); + CrossSection *cs = element->giveCrossSection(); + double thickness = cs->give(CS_Thickness, gp); + double dA = thickness * gp->giveWeight(); + answer.add(dA, tmp2); + } + } + } + } else { + // Non-standard cz formulation. - FloatArray solVec; - element->computeVectorOf(VM_Total, tStep, solVec); - size_t numSeg = mpCZIntegrationRules.size(); + FloatArray solVec; + element->computeVectorOf(VM_Total, tStep, solVec); - StructuralFE2Material *fe2Mat = dynamic_cast(mpCZMat); - if(!fe2Mat) { - OOFEM_ERROR("Failed to cast StructuralFE2Material*.") - } + size_t numSeg = mpCZIntegrationRules.size(); - for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) { -// for ( GaussPoint *gp: *mpCZIntegrationRules [ segIndex ] ) { - for(int gpInd = 0; gpInd < mpCZIntegrationRules[ segIndex ]->giveNumberOfIntegrationPoints(); gpInd++) { + StructuralFE2Material *fe2Mat = dynamic_cast(mpCZMat); + if ( !fe2Mat ) { + OOFEM_ERROR("Failed to cast StructuralFE2Material*.") + } - GaussPoint *gp = mpCZIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd); + for ( size_t segIndex = 0; segIndex < numSeg; segIndex++ ) { + //for ( auto &gp: *mpCZIntegrationRules [ segIndex ] ) { + for ( int gpInd = 0; gpInd < mpCZIntegrationRules[ segIndex ]->giveNumberOfIntegrationPoints(); gpInd++ ) { - GaussPoint *bulk_gp = NULL; - StructuralMaterial *bulkMat = NULL; - if(mIncludeBulkCorr) { - bulk_gp = mpCZExtraIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd); - bulkMat = dynamic_cast( element->giveCrossSection()->giveMaterial(bulk_gp) ); + GaussPoint *gp = mpCZIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd); - if(!bulkMat) { - OOFEM_ERROR("Failed to fetch bulk material.") - } + GaussPoint *bulk_gp = nullptr; + StructuralMaterial *bulkMat = nullptr; + if ( mIncludeBulkCorr ) { + bulk_gp = mpCZExtraIntegrationRules[ segIndex ]->getIntegrationPoint(gpInd); + bulkMat = dynamic_cast( element->giveCrossSection()->giveMaterial(bulk_gp) ); - } + if ( !bulkMat ) { + OOFEM_ERROR("Failed to fetch bulk material.") + } + } - StructuralFE2MaterialStatus *fe2ms = dynamic_cast ( gp->giveMaterialStatus() ); - if(fe2ms == NULL) { - OOFEM_ERROR("The material status is not of an allowed type.") - } + StructuralFE2MaterialStatus *fe2ms = dynamic_cast ( gp->giveMaterialStatus() ); - //////////////////////////////////////////////////////// - // Compute a (slightly modified) N-matrix + if ( fe2ms == nullptr ) { + OOFEM_ERROR("The material status is not of an allowed type.") + } - FloatMatrix NMatrix; - computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]); + //////////////////////////////////////////////////////// + // Compute a (slightly modified) N-matrix + FloatMatrix NMatrix; + computeNCohesive(NMatrix, * gp, mCZEnrItemIndices [ segIndex ], mCZTouchingEnrItemIndices [ segIndex ]); - //////////////////////////////////////////////////////// - // Fetch normal - FloatArray n( fe2ms->giveNormal() ); - // Traction part of tangent - FloatMatrix C; - fe2Mat->give3dMaterialStiffnessMatrix(C, TangentStiffness, gp, tStep); + //////////////////////////////////////////////////////// + // Fetch normal + FloatArray n( fe2ms->giveNormal() ); - FloatMatrix CBulk; - if(mIncludeBulkCorr) { - bulkMat->give3dMaterialStiffnessMatrix(CBulk, TangentStiffness, bulk_gp, tStep); - } + // Traction part of tangent + auto C = fe2Mat->give3dMaterialStiffnessMatrix(TangentStiffness, gp, tStep); + //////////////////////////////////////////////////////// + // Fetch L_s + double l_s = computeEffectiveSveSize( fe2ms ); - //////////////////////////////////////////////////////// - // Fetch L_s - double l_s = computeEffectiveSveSize( fe2ms ); + FloatMatrix Ka(2,2); + double a1 = 1.0; + double a2 = 1.0; + double a3 = 1.0; + Ka(0,0) = (0.5/l_s)*( C(0,0)*n(0)*n(0) + a2*C(0,5)*n(0)*n(1) + a1*C(5,0)*n(1)*n(0) + a3*C(5,5)*n(1)*n(1) ) + + (0.5/l_s)*( C(0,0)*n(0)*n(0) + a2*C(0,5)*n(0)*n(1) + a1*C(5,0)*n(1)*n(0) + a3*C(5,5)*n(1)*n(1) ); - FloatMatrix Ka(2,2); - double a1 = 1.0; - double a2 = 1.0; - double a3 = 1.0; - Ka(0,0) = (0.5/l_s)*( C(0,0)*n(0)*n(0) + a2*C(0,5)*n(0)*n(1) + a1*C(5,0)*n(1)*n(0) + a3*C(5,5)*n(1)*n(1) ) + - (0.5/l_s)*( C(0,0)*n(0)*n(0) + a2*C(0,5)*n(0)*n(1) + a1*C(5,0)*n(1)*n(0) + a3*C(5,5)*n(1)*n(1) ); + Ka(0,1) = (0.5/l_s)*( a2*C(0,5)*n(0)*n(0) + C(0,1)*n(0)*n(1) + a3*C(5,5)*n(1)*n(0) + a1*C(5,1)*n(1)*n(1) ) + + (0.5/l_s)*( a2*C(0,5)*n(0)*n(0) + C(0,1)*n(0)*n(1) + a3*C(5,5)*n(1)*n(0) + a1*C(5,1)*n(1)*n(1) ); - Ka(0,1) = (0.5/l_s)*( a2*C(0,5)*n(0)*n(0) + C(0,1)*n(0)*n(1) + a3*C(5,5)*n(1)*n(0) + a1*C(5,1)*n(1)*n(1) ) + - (0.5/l_s)*( a2*C(0,5)*n(0)*n(0) + C(0,1)*n(0)*n(1) + a3*C(5,5)*n(1)*n(0) + a1*C(5,1)*n(1)*n(1) ); + Ka(1,0) = (0.5/l_s)*( a1*C(5,0)*n(0)*n(0) + a3*C(5,5)*n(0)*n(1) + C(1,0)*n(1)*n(0) + a2*C(1,5)*n(1)*n(1) ) + + (0.5/l_s)*( a1*C(5,0)*n(0)*n(0) + a3*C(5,5)*n(0)*n(1) + C(1,0)*n(1)*n(0) + a2*C(1,5)*n(1)*n(1) ); - Ka(1,0) = (0.5/l_s)*( a1*C(5,0)*n(0)*n(0) + a3*C(5,5)*n(0)*n(1) + C(1,0)*n(1)*n(0) + a2*C(1,5)*n(1)*n(1) ) + - (0.5/l_s)*( a1*C(5,0)*n(0)*n(0) + a3*C(5,5)*n(0)*n(1) + C(1,0)*n(1)*n(0) + a2*C(1,5)*n(1)*n(1) ); + Ka(1,1) = (0.5/l_s)*( a3*C(5,5)*n(0)*n(0) + a1*C(5,1)*n(0)*n(1) + a2*C(1,5)*n(1)*n(0) + C(1,1)*n(1)*n(1) ) + + (0.5/l_s)*( a3*C(5,5)*n(0)*n(0) + a1*C(5,1)*n(0)*n(1) + a2*C(1,5)*n(1)*n(0) + C(1,1)*n(1)*n(1) ); - Ka(1,1) = (0.5/l_s)*( a3*C(5,5)*n(0)*n(0) + a1*C(5,1)*n(0)*n(1) + a2*C(1,5)*n(1)*n(0) + C(1,1)*n(1)*n(1) ) + - (0.5/l_s)*( a3*C(5,5)*n(0)*n(0) + a1*C(5,1)*n(0)*n(1) + a2*C(1,5)*n(1)*n(0) + C(1,1)*n(1)*n(1) ); + FloatMatrix tmp, tmp2; + tmp.beProductOf(Ka, NMatrix); + tmp2.beTProductOf(NMatrix, tmp); - FloatMatrix tmp, tmp2; - tmp.beProductOf(Ka, NMatrix); - tmp2.beTProductOf(NMatrix, tmp); + CrossSection *cs = element->giveCrossSection(); + double thickness = cs->give(CS_Thickness, gp); + double dA = thickness * gp->giveWeight(); + answer.add(dA, tmp2); - CrossSection *cs = element->giveCrossSection(); - double thickness = cs->give(CS_Thickness, gp); - double dA = thickness * gp->giveWeight(); - answer.add(dA, tmp2); + FloatMatrix BAvg; - FloatMatrix BAvg; + if ( mIncludeBulkJump ) { + //////////////////////////////////////////////////////// + // Bulk contribution to SVE strain - if(mIncludeBulkJump) { - //////////////////////////////////////////////////////// - // Bulk contribution to SVE strain + // Crack gp coordinates + const FloatArray &xC = gp->giveGlobalCoordinates(); - // Crack gp coordinates - const FloatArray &xC = gp->giveGlobalCoordinates(); + // For now, we will just perturb the coordinates of the GP to compute B^- and B^+ numerically. + double eps = 1.0e-6; + FloatArray xPert = xC; - // For now, we will just perturb the coordinates of the GP to compute B^- and B^+ numerically. - double eps = 1.0e-6; - FloatArray xPert = xC; + xPert.add(eps, n); + FloatArray locCoordPert; + element->computeLocalCoordinates(locCoordPert, xPert); - xPert.add(eps, n); - FloatArray locCoordPert; - element->computeLocalCoordinates(locCoordPert, xPert); + FloatMatrix BPlus; + this->ComputeBOrBHMatrix(BPlus, *gp, *element, false, locCoordPert); - FloatMatrix BPlus; - this->ComputeBOrBHMatrix(BPlus, *gp, *element, false, locCoordPert); + xPert = xC; + xPert.add(-eps, n); + element->computeLocalCoordinates(locCoordPert, xPert); - xPert = xC; - xPert.add(-eps, n); - element->computeLocalCoordinates(locCoordPert, xPert); + FloatMatrix BMinus; + this->ComputeBOrBHMatrix(BMinus, *gp, *element, false, locCoordPert); - FloatMatrix BMinus; - this->ComputeBOrBHMatrix(BMinus, *gp, *element, false, locCoordPert); + BAvg = BPlus; + BAvg.add(1.0, BMinus); + BAvg.times(0.5); - BAvg = BPlus; - BAvg.add(1.0, BMinus); - BAvg.times(0.5); + FloatMatrix Kb(2,4); // Implicitly assumes plane strain. Fix later. - FloatMatrix Kb(2,4); // Implicitly assumes plane strain. Fix later. + Kb(0,0) = C(0,0)*n(0) + C(5,0)*n(1); + Kb(0,1) = C(0,1)*n(0) + C(5,1)*n(1); + Kb(0,3) = C(0,5)*n(0) + C(5,5)*n(1); - Kb(0,0) = C(0,0)*n(0) + C(5,0)*n(1); - Kb(0,1) = C(0,1)*n(0) + C(5,1)*n(1); - Kb(0,3) = C(0,5)*n(0) + C(5,5)*n(1); + Kb(1,0) = C(5,0)*n(0) + C(1,0)*n(1); + Kb(1,1) = C(5,1)*n(0) + C(1,1)*n(1); + Kb(1,3) = C(5,5)*n(0) + C(1,5)*n(1); - Kb(1,0) = C(5,0)*n(0) + C(1,0)*n(1); - Kb(1,1) = C(5,1)*n(0) + C(1,1)*n(1); - Kb(1,3) = C(5,5)*n(0) + C(1,5)*n(1); + tmp.beProductOf(Kb, BAvg); + tmp2.beTProductOf(NMatrix, tmp); + answer.add(dA, tmp2); + } - tmp.beProductOf(Kb, BAvg); - tmp2.beTProductOf(NMatrix, tmp); - answer.add(dA, tmp2); - } + //////////////////////////////////////////////////////// + // Non-standard bulk contribution - //////////////////////////////////////////////////////// - // Non-standard bulk contribution + if ( mIncludeBulkCorr ) { - if(mIncludeBulkCorr) { + auto CBulk = bulkMat->give3dMaterialStiffnessMatrix(TangentStiffness, bulk_gp, tStep); - tmp.beTranspositionOf(tmp2); - answer.add(1.0*dA, tmp); + tmp.beTranspositionOf(tmp2); + answer.add(1.0*dA, tmp); - FloatMatrix C4(4,4); - C4(0,0) = C(0,0); - C4(0,1) = C(0,1); - C4(0,2) = C(0,2); - C4(0,3) = C(0,5); + FloatMatrix C4(4,4); + C4(0,0) = C(0,0); + C4(0,1) = C(0,1); + C4(0,2) = C(0,2); + C4(0,3) = C(0,5); - C4(1,0) = C(1,0); - C4(1,1) = C(1,1); - C4(1,2) = C(1,2); - C4(1,3) = C(1,5); + C4(1,0) = C(1,0); + C4(1,1) = C(1,1); + C4(1,2) = C(1,2); + C4(1,3) = C(1,5); - C4(2,0) = C(2,0); - C4(2,1) = C(2,1); - C4(2,2) = C(2,2); - C4(2,3) = C(2,5); + C4(2,0) = C(2,0); + C4(2,1) = C(2,1); + C4(2,2) = C(2,2); + C4(2,3) = C(2,5); - C4(3,0) = C(5,0); - C4(3,1) = C(5,1); - C4(3,2) = C(5,2); - C4(3,3) = C(5,5); + C4(3,0) = C(5,0); + C4(3,1) = C(5,1); + C4(3,2) = C(5,2); + C4(3,3) = C(5,5); - tmp.beProductOf(C4, BAvg); - tmp2.beTProductOf(BAvg, tmp); - answer.add(1.0*dA*l_s, tmp2); + tmp.beProductOf(C4, BAvg); + tmp2.beTProductOf(BAvg, tmp); + answer.add(1.0*dA*l_s, tmp2); - FloatMatrix C4Bulk(4,4); - C4Bulk(0,0) = CBulk(0,0); - C4Bulk(0,1) = CBulk(0,1); - C4Bulk(0,2) = CBulk(0,2); - C4Bulk(0,3) = CBulk(0,5); + FloatMatrix C4Bulk(4,4); + C4Bulk(0,0) = CBulk(0,0); + C4Bulk(0,1) = CBulk(0,1); + C4Bulk(0,2) = CBulk(0,2); + C4Bulk(0,3) = CBulk(0,5); - C4Bulk(1,0) = CBulk(1,0); - C4Bulk(1,1) = CBulk(1,1); - C4Bulk(1,2) = CBulk(1,2); - C4Bulk(1,3) = CBulk(1,5); + C4Bulk(1,0) = CBulk(1,0); + C4Bulk(1,1) = CBulk(1,1); + C4Bulk(1,2) = CBulk(1,2); + C4Bulk(1,3) = CBulk(1,5); - C4Bulk(2,0) = CBulk(2,0); - C4Bulk(2,1) = CBulk(2,1); - C4Bulk(2,2) = CBulk(2,2); - C4Bulk(2,3) = CBulk(2,5); + C4Bulk(2,0) = CBulk(2,0); + C4Bulk(2,1) = CBulk(2,1); + C4Bulk(2,2) = CBulk(2,2); + C4Bulk(2,3) = CBulk(2,5); - C4Bulk(3,0) = CBulk(5,0); - C4Bulk(3,1) = CBulk(5,1); - C4Bulk(3,2) = CBulk(5,2); - C4Bulk(3,3) = CBulk(5,5); + C4Bulk(3,0) = CBulk(5,0); + C4Bulk(3,1) = CBulk(5,1); + C4Bulk(3,2) = CBulk(5,2); + C4Bulk(3,3) = CBulk(5,5); - tmp.beProductOf(C4Bulk, BAvg); - tmp2.beTProductOf(BAvg, tmp); - answer.add(-1.0*dA*l_s, tmp2); - } + tmp.beProductOf(C4Bulk, BAvg); + tmp2.beTProductOf(BAvg, tmp); + answer.add(-1.0*dA*l_s, tmp2); + } - } - } + } + } - } + } } void XfemStructuralElementInterface :: computeCohesiveTangentAt(FloatMatrix &answer, TimeStep *tStep) @@ -1500,7 +1390,7 @@ void XfemStructuralElementInterface :: computeCohesiveTangentAt(FloatMatrix &ans void XfemStructuralElementInterface :: XfemElementInterface_computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity) { StructuralElement *structEl = dynamic_cast< StructuralElement * >( element ); - if ( structEl == NULL ) { + if ( structEl == nullptr ) { OOFEM_ERROR("Not a structural element"); } @@ -1519,11 +1409,11 @@ void XfemStructuralElementInterface :: XfemElementInterface_computeConsistentMas mass = 0.; - for ( GaussPoint *gp: *element->giveIntegrationRule(0) ) { + for ( auto &gp: *element->giveIntegrationRule(0) ) { structEl->computeNmatrixAt(gp->giveNaturalCoordinates(), n); density = structEl->giveStructuralCrossSection()->give('d', gp); - if ( ipDensity != NULL ) { + if ( ipDensity != nullptr ) { // Override density if desired density = * ipDensity; } @@ -1564,11 +1454,9 @@ void XfemStructuralElementInterface :: XfemElementInterface_computeConsistentMas } } -IRResultType -XfemStructuralElementInterface :: initializeCZFrom(InputRecord *ir) +void +XfemStructuralElementInterface :: initializeCZFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - int material = -1; IR_GIVE_OPTIONAL_FIELD(ir, material, _IFT_XfemElementInterface_CohesiveZoneMaterial); mCZMaterialNum = material; @@ -1583,8 +1471,6 @@ XfemStructuralElementInterface :: initializeCZFrom(InputRecord *ir) if ( planeStrainFlag == 1 ) { mUsePlaneStrain = true; } - - return IRRT_OK; } void XfemStructuralElementInterface :: giveCZInputRecord(DynamicInputRecord &input) @@ -1606,7 +1492,7 @@ void XfemStructuralElementInterface :: initializeCZMaterial() mpCZMat = this->element->giveDomain()->giveMaterial(mCZMaterialNum); - if ( mpCZMat == NULL ) { + if ( mpCZMat == nullptr ) { OOFEM_ERROR("Failed to fetch pointer for mpCZMat."); } } @@ -1614,26 +1500,22 @@ void XfemStructuralElementInterface :: initializeCZMaterial() bool XfemStructuralElementInterface :: useNonStdCz() { - if(element->giveDomain()->hasXfemManager()) - { - XfemManager *xMan = this->element->giveDomain()->giveXfemManager(); - XfemStructureManager *xsMan = dynamic_cast( xMan ); - - if(xsMan) { - if(xsMan->giveUseNonStdCz()) { - return true; - } - else { - return false; - } - } - else { - return false; - } - } - else { - return false; - } + if ( element->giveDomain()->hasXfemManager() ) { + XfemManager *xMan = this->element->giveDomain()->giveXfemManager(); + XfemStructureManager *xsMan = dynamic_cast( xMan ); + + if ( xsMan ) { + if ( xsMan->giveUseNonStdCz() ) { + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } } void XfemStructuralElementInterface :: XfemElementInterface_computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) @@ -1688,7 +1570,7 @@ void XfemStructuralElementInterface :: giveIntersectionsTouchingCrack(std :: vec // Check start tip EnrFrontIntersection *efStart = dynamic_cast< EnrFrontIntersection * >( eiCandidate->giveEnrichmentFrontStart() ); - if ( efStart != NULL ) { + if ( efStart != nullptr ) { const TipInfo &tipInfo = efStart->giveTipInfo(); if ( ei->tipIsTouchingEI(tipInfo) ) { @@ -1699,7 +1581,7 @@ void XfemStructuralElementInterface :: giveIntersectionsTouchingCrack(std :: vec // Check end tip EnrFrontIntersection *efEnd = dynamic_cast< EnrFrontIntersection * >( eiCandidate->giveEnrichmentFrontEnd() ); - if ( efEnd != NULL ) { + if ( efEnd != nullptr ) { const TipInfo &tipInfo = efEnd->giveTipInfo(); if ( ei->tipIsTouchingEI(tipInfo) ) { @@ -1750,7 +1632,7 @@ void XfemStructuralElementInterface :: giveSubtriangulationCompositeExportData(s // Export nodal variables from primary fields - vtkPieces [ 0 ].setNumberOfPrimaryVarsToExport(primaryVarsToExport.giveSize(), numTotalNodes); + vtkPieces [ 0 ].setNumberOfPrimaryVarsToExport(primaryVarsToExport, numTotalNodes); for ( int fieldNum = 1; fieldNum <= primaryVarsToExport.giveSize(); fieldNum++ ) { UnknownType type = ( UnknownType ) primaryVarsToExport.at(fieldNum); @@ -1765,9 +1647,9 @@ void XfemStructuralElementInterface :: giveSubtriangulationCompositeExportData(s triCenter.times(1.0 / 3.0); double meanEdgeLength = 0.0; - meanEdgeLength += ( 1.0 / 3.0 ) * tri.giveVertex(1).distance( tri.giveVertex(2) ); - meanEdgeLength += ( 1.0 / 3.0 ) * tri.giveVertex(2).distance( tri.giveVertex(3) ); - meanEdgeLength += ( 1.0 / 3.0 ) * tri.giveVertex(3).distance( tri.giveVertex(1) ); + meanEdgeLength += ( 1.0 / 3.0 ) * distance(tri.giveVertex(1), tri.giveVertex(2) ); + meanEdgeLength += ( 1.0 / 3.0 ) * distance(tri.giveVertex(2), tri.giveVertex(3) ); + meanEdgeLength += ( 1.0 / 3.0 ) * distance(tri.giveVertex(3), tri.giveVertex(1) ); const double relPertLength = XfemTolerances :: giveRelLengthTolTight(); @@ -1828,7 +1710,7 @@ void XfemStructuralElementInterface :: giveSubtriangulationCompositeExportData(s bool evaluationSucceeded = true; for ( int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++ ) { DofManager *dMan = element->giveDofManager(elNodeInd); - const FloatArray &nodeCoord = * ( dMan->giveCoordinates() ); + const auto &nodeCoord = dMan->giveCoordinates(); if ( !ei->evalLevelSetTangInNode(levelSetInNode, dMan->giveGlobalNumber(), nodeCoord) ) { evaluationSucceeded = false; @@ -1844,13 +1726,13 @@ void XfemStructuralElementInterface :: giveSubtriangulationCompositeExportData(s double tangSignDist = levelSetTang, arcPos = 0.0; GeometryBasedEI *geoEI = dynamic_cast< GeometryBasedEI * >( ei ); - if ( geoEI != NULL ) { + if ( geoEI != nullptr ) { // TODO: Consider removing this special treatment. /ES geoEI->giveGeometry()->computeTangentialSignDist(tangSignDist, x, arcPos); } - if(!evaluationSucceeded) { + if ( !evaluationSucceeded ) { // printf("!evaluationSucceeded.\n"); } @@ -1887,7 +1769,7 @@ void XfemStructuralElementInterface :: giveSubtriangulationCompositeExportData(s FloatArray valuearray = u; - vtkPieces [ 0 ].setPrimaryVarInNode(fieldNum, nodesPassed, valuearray); + vtkPieces [ 0 ].setPrimaryVarInNode(type, nodesPassed, valuearray); } else { // TODO: Implement printf("fieldNum: %d\n", fieldNum); @@ -1900,10 +1782,10 @@ void XfemStructuralElementInterface :: giveSubtriangulationCompositeExportData(s // Export nodal variables from internal fields - vtkPieces [ 0 ].setNumberOfInternalVarsToExport(0, numTotalNodes); + vtkPieces [ 0 ].setNumberOfInternalVarsToExport(internalVarsToExport, numTotalNodes); - vtkPieces [ 0 ].setNumberOfCellVarsToExport(cellVarsToExport.giveSize(), numCells); + vtkPieces [ 0 ].setNumberOfCellVarsToExport(cellVarsToExport, numCells); for ( int i = 1; i <= cellVarsToExport.giveSize(); i++ ) { InternalStateType type = ( InternalStateType ) cellVarsToExport.at(i); @@ -1913,14 +1795,14 @@ void XfemStructuralElementInterface :: giveSubtriangulationCompositeExportData(s IntegrationRule *iRule = element->giveIntegrationRule(0); computeIPAverageInTriangle(average, iRule, element, type, tStep, mSubTri[triInd-1]); - if(average.giveSize() == 0) { + if ( average.giveSize() == 0 ) { VTKXMLExportModule :: computeIPAverage(average, iRule, element, type, tStep); } FloatArray averageVoigt; - if( average.giveSize() == 6 ) { + if ( average.giveSize() == 6 ) { averageVoigt.resize(9); @@ -1930,15 +1812,14 @@ void XfemStructuralElementInterface :: giveSubtriangulationCompositeExportData(s averageVoigt.at(6) = averageVoigt.at(8) = average.at(4); averageVoigt.at(3) = averageVoigt.at(7) = average.at(5); averageVoigt.at(2) = averageVoigt.at(4) = average.at(6); - } - else { - if(average.giveSize() == 1) { + } else { + if ( average.giveSize() == 1 ) { averageVoigt.resize(1); averageVoigt.at(1) = average.at(1); } } - vtkPieces [ 0 ].setCellVar(i, triInd, averageVoigt); + vtkPieces [ 0 ].setCellVar(type, triInd, averageVoigt); } } @@ -1974,7 +1855,7 @@ void XfemStructuralElementInterface :: giveSubtriangulationCompositeExportData(s for ( int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++ ) { DofManager *dMan = element->giveDofManager(elNodeInd); - const FloatArray &nodeCoord = * ( dMan->giveCoordinates() ); + const auto &nodeCoord = dMan->giveCoordinates(); ei->evalLevelSetNormalInNode(levelSetInNode, dMan->giveGlobalNumber(), nodeCoord); levelSet += N.at(elNodeInd) * levelSetInNode; @@ -1990,7 +1871,7 @@ void XfemStructuralElementInterface :: giveSubtriangulationCompositeExportData(s for ( int elNodeInd = 1; elNodeInd <= nDofMan; elNodeInd++ ) { DofManager *dMan = element->giveDofManager(elNodeInd); - const FloatArray &nodeCoord = * ( dMan->giveCoordinates() ); + const auto &nodeCoord = dMan->giveCoordinates(); ei->evalLevelSetTangInNode(levelSetInNode, dMan->giveGlobalNumber(), nodeCoord); levelSet += N.at(elNodeInd) * levelSetInNode; @@ -2036,7 +1917,7 @@ void XfemStructuralElementInterface :: computeIPAverageInTriangle(FloatArray &an FloatArray globCoord = ip->giveGlobalCoordinates(); // globCoord.resizeWithValues(2); - if( iTri.pointIsInTriangle(globCoord) ) { + if ( iTri.pointIsInTriangle(globCoord) ) { elem->giveIPValue(temp, ip, isType, tStep); gptot += ip->giveWeight(); answer.add(ip->giveWeight(), temp); diff --git a/src/sm/xfem/xfemstructuralelementinterface.h b/src/sm/xfem/xfemstructuralelementinterface.h index cce84f62a..19aceece7 100644 --- a/src/sm/xfem/xfemstructuralelementinterface.h +++ b/src/sm/xfem/xfemstructuralelementinterface.h @@ -51,10 +51,9 @@ class OOFEM_EXPORT XfemStructuralElementInterface : public XfemElementInterface { public: XfemStructuralElementInterface(Element *e); - virtual ~XfemStructuralElementInterface(); /// Updates integration rule based on the triangulation. - virtual bool XfemElementInterface_updateIntegrationRule(); + bool XfemElementInterface_updateIntegrationRule() override; MaterialStatus *giveClosestGP_MatStat(double &oClosestDist, std :: vector< std :: unique_ptr< IntegrationRule > > &iRules, const FloatArray &iCoord); @@ -63,7 +62,7 @@ class OOFEM_EXPORT XfemStructuralElementInterface : public XfemElementInterface virtual void XfemElementInterface_computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *, TimeStep *tStep); virtual void XfemElementInterface_computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep); - virtual bool hasCohesiveZone() const { return ( mpCZMat != NULL && mpCZIntegrationRules.size() > 0 ); } + virtual bool hasCohesiveZone() const { return ( mpCZMat != nullptr && mpCZIntegrationRules.size() > 0 ); } virtual void computeCohesiveForces(FloatArray &answer, TimeStep *tStep); virtual void computeGlobalCohesiveTractionVector(FloatArray &oT, const FloatArray &iJump, const FloatArray &iCrackNormal, const FloatMatrix &iNMatrix, GaussPoint &iGP, TimeStep *tStep); @@ -73,7 +72,7 @@ class OOFEM_EXPORT XfemStructuralElementInterface : public XfemElementInterface virtual void XfemElementInterface_computeConsistentMassMatrix(FloatMatrix &answer, TimeStep *tStep, double &mass, const double *ipDensity = NULL); - virtual IRResultType initializeCZFrom(InputRecord *ir); + virtual void initializeCZFrom(InputRecord &ir); virtual void giveCZInputRecord(DynamicInputRecord &input); virtual void initializeCZMaterial(); @@ -90,13 +89,13 @@ class OOFEM_EXPORT XfemStructuralElementInterface : public XfemElementInterface void giveIntersectionsTouchingCrack(std :: vector< int > &oTouchingEnrItemIndices, const std :: vector< int > &iCandidateIndices, int iEnrItemIndex, XfemManager &iXMan); // Cohesive Zone variables - Material *mpCZMat; - int mCZMaterialNum; - int mCSNumGaussPoints; + Material *mpCZMat = nullptr; + int mCZMaterialNum = -1; + int mCSNumGaussPoints = 4; // Options for nonstandard cohesive zone model - bool mIncludeBulkJump; - bool mIncludeBulkCorr; + bool mIncludeBulkJump = true; + bool mIncludeBulkCorr = true; // Store element subdivision for postprocessing std :: vector< Triangle >mSubTri; diff --git a/src/sm/xfem/xfemstructuremanager.C b/src/sm/xfem/xfemstructuremanager.C index b6a662fc9..426298e1f 100644 --- a/src/sm/xfem/xfemstructuremanager.C +++ b/src/sm/xfem/xfemstructuremanager.C @@ -39,7 +39,7 @@ #include "datareader.h" #include "mathfem.h" -#include "xfem/enrichmentitems/crack.h" +#include "sm/xfem/enrichmentitems/crack.h" #include "xfem/enrichmentfronts/enrichmentfrontintersection.h" #include "geometry.h" @@ -51,18 +51,19 @@ REGISTER_XfemManager(XfemStructureManager) XfemStructureManager :: XfemStructureManager(Domain *domain) : XfemManager(domain), mSplitCracks(false), - mNonstandardCz(false), - mMinCrackLength(0.0), - mCrackMergeTol(0.0), + mNonstandardCz(false), + mMinCrackLength(0.0), + mCrackMergeTol(0.0), mpMatForceEvaluator( new MaterialForceEvaluator() ) {} XfemStructureManager :: ~XfemStructureManager() {} -IRResultType XfemStructureManager :: initializeFrom(InputRecord *ir) +void XfemStructureManager :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + XfemManager :: initializeFrom(ir); + int splitCracks = 0; IR_GIVE_OPTIONAL_FIELD(ir, splitCracks, _IFT_XfemStructureManager_splitCracks); if ( splitCracks == 1 ) { @@ -72,22 +73,33 @@ IRResultType XfemStructureManager :: initializeFrom(InputRecord *ir) int nonStdCz = 0; IR_GIVE_OPTIONAL_FIELD(ir, nonStdCz, _IFT_XfemStructureManager_nonstandardCZ); if ( nonStdCz == 1 ) { - mNonstandardCz = true; + mNonstandardCz = true; } IR_GIVE_OPTIONAL_FIELD(ir, mMinCrackLength, _IFT_XfemStructureManager_minCrackLength); -// if(mMinCrackLength < 1.0e-12) { -// printf("mMinCrackLength: %e\n", mMinCrackLength); -// } +#if 0 + if ( mMinCrackLength < 1.0e-12 ) { + printf("mMinCrackLength: %e\n", mMinCrackLength); + } +#endif IR_GIVE_OPTIONAL_FIELD(ir, mCrackMergeTol, _IFT_XfemStructureManager_crackMergeTol); - if(mCrackMergeTol > 1.0e-12) { - printf("mCrackMergeTol: %e\n", mCrackMergeTol); + if ( mCrackMergeTol > 1.0e-12 ) { + printf("mCrackMergeTol: %e\n", mCrackMergeTol); } +} + +void XfemStructureManager :: postInitialize() { + XfemManager :: postInitialize(); + + if ( mSplitCracks ) { + splitCracks(); + } + mergeCloseCracks(); + updateNodeEnrichmentItemMap(); - return XfemManager :: initializeFrom(ir); } void XfemStructureManager :: giveInputRecord(DynamicInputRecord &input) @@ -102,23 +114,16 @@ void XfemStructureManager :: giveInputRecord(DynamicInputRecord &input) input.setField(mCrackMergeTol, _IFT_XfemStructureManager_crackMergeTol); - if( mNonstandardCz ) { + if ( mNonstandardCz ) { input.setField(1, _IFT_XfemStructureManager_nonstandardCZ); } } -int XfemStructureManager :: instanciateYourself(DataReader *dr) +int XfemStructureManager :: instanciateYourself(DataReader &dr) { int result = XfemManager :: instanciateYourself(dr); - if ( mSplitCracks ) { - splitCracks(); - } - - mergeCloseCracks(); - - updateNodeEnrichmentItemMap(); - + return result; } @@ -131,7 +136,7 @@ void XfemStructureManager :: propagateFronts(bool &oAnyFronHasPropagated) bool eiHasPropagated = false; ei->propagateFronts(eiHasPropagated); - if(eiHasPropagated) { + if ( eiHasPropagated ) { oAnyFronHasPropagated = true; } } @@ -187,41 +192,38 @@ void XfemStructureManager :: splitCracks() if ( fabs(arcPositions_i [ k ] - arcPositions_i [ k - 1 ]) > arcLengthTol ) { //printf("arcPositions.size(): %lu\n", arcPositions.size() ); - DynamicDataReader dataReader; + DynamicDataReader dataReader("xfem-crack"); crack_i->appendInputRecords(dataReader); // ... split crack i at the intersection and add intersection enrichment // fronts at the newly detected intersections. int n1 = this->giveNumberOfEnrichmentItems() + 1; // EnrichmentItem *newEI_1 = new Crack(n1, this, this->giveDomain() ); - Crack *newCrack = new Crack( n1, this, this->giveDomain() ); - std :: unique_ptr< EnrichmentItem >newEI_1(newCrack); + auto newCrack = std::make_unique( n1, this, this->giveDomain() ); - InputRecord *ir = dataReader.giveInputRecord(DataReader :: IR_enrichItemRec, i); - newEI_1->initializeFrom(ir); - newEI_1->instanciateYourself(& dataReader); + auto &ir = dataReader.giveInputRecord(DataReader :: IR_enrichItemRec, i); + newCrack->initializeFrom(ir); + newCrack->instanciateYourself(dataReader); PolygonLine *new_pl = dynamic_cast< PolygonLine * >( newCrack->giveGeometry() ); // EDCrack *ed = dynamic_cast( newEI_1->giveEnrichmentDomain() ); - if ( new_pl == NULL ) { + if ( !new_pl ) { OOFEM_ERROR("Failed to cast PolygonLine *new_pl.") - } - - if ( new_pl != NULL ) { + } else { //printf("arcPositions_i[k-1]: %e arcPositions_i[k]: %e\n", arcPositions_i[k-1], arcPositions_i[k] ); new_pl->cropPolygon(arcPositions_i [ k - 1 ], arcPositions_i [ k ]); PolygonLine *polygonLine_j = dynamic_cast< PolygonLine * >( crack_j->giveGeometry() ); - if ( polygonLine_j == NULL ) { + if ( !polygonLine_j ) { OOFEM_ERROR("Failed to cast PolygonLine *polygonLine_j.") } PolygonLine *polygonLine_i = dynamic_cast< PolygonLine * >( crack_i->giveGeometry() ); - if ( polygonLine_i == NULL ) { + if ( !polygonLine_i ) { OOFEM_ERROR("Failed to cast PolygonLine *polygonLine_i.") } @@ -257,14 +259,13 @@ void XfemStructureManager :: splitCracks() polygonLine_i->giveTangent(crackTangent1, arcPositions_i [ k - 1 ]); crackTangent1.times(-1.0); - EnrFrontIntersection *ef = new EnrFrontIntersection(); - if ( frontTangent1.dotProduct(crackTangent1) < 0.0 ) { frontTangent1.times(-1.0); } + auto ef = std::make_unique(); ef->setTangent(frontTangent1); - newEI_1->setEnrichmentFrontStart(ef); + newCrack->setEnrichmentFrontStart(std::move(ef)); } if ( k < int( arcPositions_i.size() ) - 1 ) { @@ -274,21 +275,21 @@ void XfemStructureManager :: splitCracks() FloatArray crackTangent1; polygonLine_i->giveTangent(crackTangent1, arcPositions_i [ k ]); - EnrFrontIntersection *ef = new EnrFrontIntersection(); if ( frontTangent1.dotProduct(crackTangent1) < 0.0 ) { frontTangent1.times(-1.0); } + auto ef = std::make_unique(); ef->setTangent(frontTangent1); - newEI_1->setEnrichmentFrontEnd(ef); + newCrack->setEnrichmentFrontEnd(std::move(ef)); } } //this->enrichmentItemList[i-1] = std :: move(ei); - this->enrichmentItemList.push_back(NULL); - newEI_1->updateGeometry(); - this->enrichmentItemList [ enrichmentItemList.size() - 1 ] = std :: move(newEI_1); + this->enrichmentItemList.push_back(nullptr); + newCrack->updateGeometry(); + this->enrichmentItemList [ enrichmentItemList.size() - 1 ] = std :: move(newCrack); splittedCrack = true; @@ -309,8 +310,7 @@ void XfemStructureManager :: splitCracks() numberOfEnrichmentItems = giveNumberOfEnrichmentItems(); -// printf("After splitting: Number of ei: %d\n", giveNumberOfEnrichmentItems() ); - + //printf("After splitting: Number of ei: %d\n", giveNumberOfEnrichmentItems() ); removeShortCracks(); @@ -318,90 +318,80 @@ void XfemStructureManager :: splitCracks() enrichmentItemList [ i ]->setNumber(i + 1); } - for ( size_t i = 0; i < enrichmentItemList.size(); i++ ) { enrichmentItemList [ i ]->updateGeometry(); } - - } void XfemStructureManager :: removeShortCracks() { -// printf("Entering XfemStructureManager :: removeShortCracks()\n"); + //printf("Entering XfemStructureManager :: removeShortCracks()\n"); -// printf("Number of ei before removal: %d\n", giveNumberOfEnrichmentItems()); + //printf("Number of ei before removal: %d\n", giveNumberOfEnrichmentItems()); - double l_tol = mMinCrackLength; + double l_tol = mMinCrackLength; for ( int i = 1; i <= giveNumberOfEnrichmentItems(); i++ ) { Crack *crack = dynamic_cast< Crack * >( this->giveEnrichmentItem(i) ); if ( crack ) { - double l = crack->computeLength(); + double l = crack->computeLength(); - if(l < l_tol) { - printf("Removing short crack with l: %e\n", l); + if ( l < l_tol ) { + printf("Removing short crack with l: %e\n", l); - // Explicitly erasing things is a mess... -// crack->removeEnrichedDofs(); -// enrichmentItemList.erase(enrichmentItemList.begin() + i - 1); -// i--; + // Explicitly erasing things is a mess... + //crack->removeEnrichedDofs(); + //enrichmentItemList.erase(enrichmentItemList.begin() + i - 1); + //i--; - // ...therefore, just remove the geometry. + // ...therefore, just remove the geometry. PolygonLine *polygonLine = dynamic_cast< PolygonLine * >( crack->giveGeometry() ); polygonLine->clear(); -// FloatArray tmp = {0.0, 0.0, 0.0}; - FloatArray tmp = {-1.0e3, -1.0e3, -1.0e3}; - polygonLine->insertVertexBack(tmp); + //FloatArray tmp = {0.0, 0.0, 0.0}; + FloatArray tmp = {-1.0e3, -1.0e3, -1.0e3}; + polygonLine->insertVertexBack(tmp); - } + } } } -// printf("Number of ei after removal: %d\n", giveNumberOfEnrichmentItems()); + //printf("Number of ei after removal: %d\n", giveNumberOfEnrichmentItems()); } bool XfemStructureManager :: tipsHaveOppositeDirection(EnrichmentFront *iEf1, EnrichmentFront *iEf2) { - const TipInfo &t1 = iEf1->giveTipInfo(); - const TipInfo &t2 = iEf2->giveTipInfo(); - - if( t1.mTangDir.dotProduct( t2.mTangDir ) > 0.0 ) { - return false; - } - else { - return true; - } + const TipInfo &t1 = iEf1->giveTipInfo(); + const TipInfo &t2 = iEf2->giveTipInfo(); + return t1.mTangDir.dotProduct( t2.mTangDir ) <= 0.0; } void XfemStructureManager :: mergeCloseCracks() { -// printf("Entering XfemStructureManager :: mergeCloseCracks().\n"); + //printf("Entering XfemStructureManager :: mergeCloseCracks().\n"); - const double &dist_tol = mCrackMergeTol; + const double &dist_tol = mCrackMergeTol; - // Loop over cracks and check if two crack tips are closer to - // each other than a predefined distance. If so, merge the cracks. + // Loop over cracks and check if two crack tips are closer to + // each other than a predefined distance. If so, merge the cracks. // Loop over cracks - for ( int i = 1; i <= giveNumberOfEnrichmentItems(); i++ ) { + for ( int i = 1; i <= giveNumberOfEnrichmentItems(); i++ ) { Crack *crack_i = dynamic_cast< Crack * >( this->giveEnrichmentItem(i) ); if ( crack_i ) { + BasicGeometry *bg_i = crack_i->giveGeometry(); + TipInfo startTip_i, endTip_i; + bg_i->giveTips(startTip_i, endTip_i) ; - BasicGeometry *bg_i = crack_i->giveGeometry(); - TipInfo startTip_i, endTip_i; - bg_i->giveTips(startTip_i, endTip_i) ; - - const FloatArray &ps_i =startTip_i.mGlobalCoord; - const FloatArray &pe_i =endTip_i.mGlobalCoord; + const FloatArray &ps_i =startTip_i.mGlobalCoord; + const FloatArray &pe_i =endTip_i.mGlobalCoord; PolygonLine *polygonLine_i = dynamic_cast< PolygonLine * >( crack_i->giveGeometry() ); - if ( polygonLine_i == NULL ) { - OOFEM_ERROR("Failed to cast PolygonLine *polygonLine_i.") - } + if ( !polygonLine_i ) { + OOFEM_ERROR("Failed to cast PolygonLine *polygonLine_i.") + } for ( int j = i+1; j <= giveNumberOfEnrichmentItems(); j++ ) { // TODO: To improve performance, we may wish to use @@ -410,176 +400,162 @@ void XfemStructureManager :: mergeCloseCracks() Crack *crack_j = dynamic_cast< Crack * >( this->giveEnrichmentItem(j) ); - if( crack_i->computeLength() < 1.0e-18 || crack_j->computeLength() < 1.0e-18 ) { - continue; + if ( crack_i->computeLength() < 1.0e-18 || crack_j->computeLength() < 1.0e-18 ) { + continue; } if ( crack_j ) { - BasicGeometry *bg_j = crack_j->giveGeometry(); - TipInfo startTip_j, endTip_j; - bg_j->giveTips(startTip_j, endTip_j) ; + BasicGeometry *bg_j = crack_j->giveGeometry(); + TipInfo startTip_j, endTip_j; + bg_j->giveTips(startTip_j, endTip_j) ; - const FloatArray &ps_j =startTip_j.mGlobalCoord; - const FloatArray &pe_j =endTip_j.mGlobalCoord; + const FloatArray &ps_j =startTip_j.mGlobalCoord; + const FloatArray &pe_j =endTip_j.mGlobalCoord; PolygonLine *polygonLine_j = dynamic_cast< PolygonLine * >( crack_j->giveGeometry() ); - if ( polygonLine_j == NULL ) { - OOFEM_ERROR("Failed to cast PolygonLine *polygonLine_j.") - } - - + if ( !polygonLine_j ) { + OOFEM_ERROR("Failed to cast PolygonLine *polygonLine_j.") + } //////////////////////////////////////////////////////////////// - if(ps_i.distance(ps_j) < dist_tol) { - printf("ps_i.distance(ps_j) < dist_tol\n"); - - // Merging is not reasonable if the tips are close to parallel - if( !tipsHaveOppositeDirection(crack_i->giveEnrichmentFrontStart(), crack_j->giveEnrichmentFrontStart()) ) { - printf("Preventing merge due to parallel tips.\n"); - } - else { - - // Append points to the start of polygonLine_i - int n = polygonLine_j->giveNrVertices(); - for(int k = 1; k <= n; k++) { - polygonLine_i->insertVertexFront( polygonLine_j->giveVertex(k) ); - } + if ( distance(ps_i, ps_j) < dist_tol ) { + printf("distance(ps_i, ps_j) < dist_tol\n"); + + // Merging is not reasonable if the tips are close to parallel + if ( !tipsHaveOppositeDirection(crack_i->giveEnrichmentFrontStart(), crack_j->giveEnrichmentFrontStart()) ) { + printf("Preventing merge due to parallel tips.\n"); + } else { + // Append points to the start of polygonLine_i + int n = polygonLine_j->giveNrVertices(); + for (int k = 1; k <= n; k++) { + polygonLine_i->insertVertexFront( polygonLine_j->giveVertex(k) ); + } - polygonLine_i->removeDuplicatePoints(1.0e-18); + polygonLine_i->removeDuplicatePoints(1.0e-18); - polygonLine_j->clear(); - // FloatArray tmp = { 0.0, 0.0, 0.0}; - FloatArray tmp = {-1.0e3, -1.0e3, -1.0e3}; - polygonLine_j->insertVertexBack(tmp); + polygonLine_j->clear(); + //FloatArray tmp = { 0.0, 0.0, 0.0}; + FloatArray tmp = {-1.0e3, -1.0e3, -1.0e3}; + polygonLine_j->insertVertexBack(tmp); - // Fix tips - EnrichmentFront *ef_tmp = crack_i->giveEnrichmentFrontStart(); - crack_i->setEnrichmentFrontStart( crack_j->giveEnrichmentFrontEnd(), false ); - crack_j->setEnrichmentFrontEnd(ef_tmp, false); + // Fix tips + EnrichmentFront *ef_tmp = crack_i->giveEnrichmentFrontStart(); + crack_i->setEnrichmentFrontStart(std::unique_ptr(crack_j->giveEnrichmentFrontEnd()), false ); + crack_j->setEnrichmentFrontEnd(std::unique_ptr(ef_tmp), false); -// mergedCrack = true; - break; - } + //mergedCrack = true; + break; + } - } + } //////////////////////////////////////////////////////////////// - if(ps_i.distance(pe_j) < dist_tol) { - printf("ps_i.distance(pe_j) < dist_tol\n"); + if ( distance(ps_i, pe_j) < dist_tol ) { + printf("distance(ps_i, pe_j) < dist_tol\n"); #if 1 - if( !tipsHaveOppositeDirection(crack_i->giveEnrichmentFrontStart(), crack_j->giveEnrichmentFrontEnd()) ) { - printf("Preventing merge due to parallel tips.\n"); - } - else { - - // Append points to the start of polygonLine_i - int n = polygonLine_j->giveNrVertices(); - for(int k = n; k > 0; k--) { - polygonLine_i->insertVertexFront( polygonLine_j->giveVertex(k) ); - } - - polygonLine_i->removeDuplicatePoints(1.0e-18); - + if ( !tipsHaveOppositeDirection(crack_i->giveEnrichmentFrontStart(), crack_j->giveEnrichmentFrontEnd()) ) { + printf("Preventing merge due to parallel tips.\n"); + } else { + + // Append points to the start of polygonLine_i + int n = polygonLine_j->giveNrVertices(); + for(int k = n; k > 0; k--) { + polygonLine_i->insertVertexFront( polygonLine_j->giveVertex(k) ); + } - polygonLine_j->clear(); - // FloatArray tmp = {0.0, 0.0, 0.0}; - FloatArray tmp = {-1.0e3, -1.0e3, -1.0e3}; - polygonLine_j->insertVertexBack(tmp); + polygonLine_i->removeDuplicatePoints(1.0e-18); - // Fix tips - EnrichmentFront *ef_tmp = crack_i->giveEnrichmentFrontStart(); - crack_i->setEnrichmentFrontStart( crack_j->giveEnrichmentFrontStart(), false ); - crack_j->setEnrichmentFrontStart(ef_tmp, false); + polygonLine_j->clear(); + //FloatArray tmp = {0.0, 0.0, 0.0}; + FloatArray tmp = {-1.0e3, -1.0e3, -1.0e3}; + polygonLine_j->insertVertexBack(tmp); + // Fix tips + ///@todo Quite ugly; come up with bettermethods for swapping without releasing from the ptrs. + EnrichmentFront *ef_tmp = crack_i->giveEnrichmentFrontStart(); + crack_i->setEnrichmentFrontStart(std::unique_ptr(crack_j->giveEnrichmentFrontStart()), false ); + crack_j->setEnrichmentFrontStart(std::unique_ptr(ef_tmp), false); -// mergedCrack = true; - break; - } + //mergedCrack = true; + break; + } #endif - } + } //////////////////////////////////////////////////////////////// - if(pe_i.distance(ps_j) < dist_tol) { - printf("pe_i.distance(ps_j) < dist_tol\n"); - + if ( distance(pe_i, ps_j) < dist_tol ) { + printf("distance(pe_i, ps_j) < dist_tol\n"); - if( !tipsHaveOppositeDirection(crack_i->giveEnrichmentFrontEnd(), crack_j->giveEnrichmentFrontStart()) ) { - printf("Preventing merge due to parallel tips.\n"); - } - else { + if ( !tipsHaveOppositeDirection(crack_i->giveEnrichmentFrontEnd(), crack_j->giveEnrichmentFrontStart()) ) { + printf("Preventing merge due to parallel tips.\n"); + } else { - // Append points to the end of polygonLine_i - int n = polygonLine_j->giveNrVertices(); - for(int k = 1; k <= n; k++) { - polygonLine_i->insertVertexBack( polygonLine_j->giveVertex(k) ); - } - - polygonLine_i->removeDuplicatePoints(1.0e-18); + // Append points to the end of polygonLine_i + int n = polygonLine_j->giveNrVertices(); + for(int k = 1; k <= n; k++) { + polygonLine_i->insertVertexBack( polygonLine_j->giveVertex(k) ); + } + polygonLine_i->removeDuplicatePoints(1.0e-18); - polygonLine_j->clear(); - // FloatArray tmp = {0.0, 0.0, 0.0}; - FloatArray tmp = {-1.0e3, -1.0e3, -1.0e3}; - polygonLine_j->insertVertexBack(tmp); + polygonLine_j->clear(); + //FloatArray tmp = {0.0, 0.0, 0.0}; + FloatArray tmp = {-1.0e3, -1.0e3, -1.0e3}; + polygonLine_j->insertVertexBack(tmp); - // Fix tips - EnrichmentFront *ef_tmp = crack_i->giveEnrichmentFrontEnd(); - crack_i->setEnrichmentFrontEnd( crack_j->giveEnrichmentFrontEnd(), false ); - crack_j->setEnrichmentFrontEnd(ef_tmp, false); + // Fix tips + EnrichmentFront *ef_tmp = crack_i->giveEnrichmentFrontEnd(); + crack_i->setEnrichmentFrontEnd(std::unique_ptr(crack_j->giveEnrichmentFrontEnd()), false ); + crack_j->setEnrichmentFrontEnd(std::unique_ptr(ef_tmp), false); -// mergedCrack = true; - break; - } - } + //mergedCrack = true; + break; + } + } //////////////////////////////////////////////////////////////// - if(pe_i.distance(pe_j) < dist_tol) { - printf("pe_i.distance(pe_j) < dist_tol\n"); - - if( !tipsHaveOppositeDirection(crack_i->giveEnrichmentFrontEnd(), crack_j->giveEnrichmentFrontEnd()) ) { - printf("Preventing merge due to parallel tips.\n"); - } - else { - - // Append points to the end of polygonLine_i - int n = polygonLine_j->giveNrVertices(); - for(int k = n; k > 0; k--) { - polygonLine_i->insertVertexBack( polygonLine_j->giveVertex(k) ); - } - - polygonLine_i->removeDuplicatePoints(1.0e-18); + if ( distance(pe_i, pe_j) < dist_tol ) { + printf("distance(pe_i, pe_j) < dist_tol\n"); + if ( !tipsHaveOppositeDirection(crack_i->giveEnrichmentFrontEnd(), crack_j->giveEnrichmentFrontEnd()) ) { + printf("Preventing merge due to parallel tips.\n"); + } else { - polygonLine_j->clear(); - // FloatArray tmp = {0.0, 0.0, 0.0}; - FloatArray tmp = {-1.0e3, -1.0e3, -1.0e3}; - polygonLine_j->insertVertexBack(tmp); + // Append points to the end of polygonLine_i + int n = polygonLine_j->giveNrVertices(); + for(int k = n; k > 0; k--) { + polygonLine_i->insertVertexBack( polygonLine_j->giveVertex(k) ); + } + polygonLine_i->removeDuplicatePoints(1.0e-18); - // Fix tips - EnrichmentFront *ef_tmp = crack_i->giveEnrichmentFrontEnd(); - crack_i->setEnrichmentFrontEnd( crack_j->giveEnrichmentFrontStart(), false ); - crack_j->setEnrichmentFrontStart(ef_tmp, false); + polygonLine_j->clear(); + //FloatArray tmp = {0.0, 0.0, 0.0}; + FloatArray tmp = {-1.0e3, -1.0e3, -1.0e3}; + polygonLine_j->insertVertexBack(tmp); -// mergedCrack = true; - break; - } - } + // Fix tips + EnrichmentFront *ef_tmp = crack_i->giveEnrichmentFrontEnd(); + crack_i->setEnrichmentFrontEnd(std::unique_ptr(crack_j->giveEnrichmentFrontStart()), false ); + crack_j->setEnrichmentFrontStart(std::unique_ptr(ef_tmp), false); + //mergedCrack = true; + break; + } + } } } } - } - + } removeShortCracks(); @@ -599,12 +575,12 @@ void XfemStructureManager :: mergeCloseCracks() double XfemStructureManager :: computeTotalCrackLength() { - double l_tot = 0.0; + double l_tot = 0.0; for ( int i = 1; i <= giveNumberOfEnrichmentItems(); i++ ) { - Crack *crack = dynamic_cast< Crack * >( this->giveEnrichmentItem(i) ); + auto crack = dynamic_cast< Crack * >( this->giveEnrichmentItem(i) ); if ( crack ) { - l_tot += crack->computeLength(); + l_tot += crack->computeLength(); } } diff --git a/src/sm/xfem/xfemstructuremanager.h b/src/sm/xfem/xfemstructuremanager.h index db14e256e..bc854e906 100644 --- a/src/sm/xfem/xfemstructuremanager.h +++ b/src/sm/xfem/xfemstructuremanager.h @@ -66,19 +66,20 @@ class OOFEM_EXPORT XfemStructureManager : public XfemManager virtual ~XfemStructureManager(); /// Initializes receiver according to object description stored in input record. - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; - virtual int instanciateYourself(DataReader *dr); - virtual const char *giveClassName() const { return "XfemStructureManager"; } - virtual const char *giveInputRecordName() const { return _IFT_XfemStructureManager_Name; } + int instanciateYourself(DataReader &dr) override; + const char *giveClassName() const override { return "XfemStructureManager"; } + const char *giveInputRecordName() const override { return _IFT_XfemStructureManager_Name; } + virtual void postInitialize() override; - virtual void propagateFronts(bool &oAnyFronHasPropagated); + void propagateFronts(bool &oAnyFronHasPropagated) override; /** * Update enrichment items (level sets). */ - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; void splitCracks(); @@ -87,7 +88,7 @@ class OOFEM_EXPORT XfemStructureManager : public XfemManager bool tipsHaveOppositeDirection(EnrichmentFront *iEf1, EnrichmentFront *iEf2); void mergeCloseCracks(); - bool giveUseNonStdCz() const {return mNonstandardCz;} + bool giveUseNonStdCz() const { return mNonstandardCz; } /// Compute the total length of all cracks in the domain. double computeTotalCrackLength(); diff --git a/src/tm/gravitypressure.C b/src/tm/BoundaryCondition/gravitypressure.C similarity index 93% rename from src/tm/gravitypressure.C rename to src/tm/BoundaryCondition/gravitypressure.C index baa1b2f2e..ec2582306 100644 --- a/src/tm/gravitypressure.C +++ b/src/tm/BoundaryCondition/gravitypressure.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "gravitypressure.h" +#include "tm/BoundaryCondition/gravitypressure.h" #include "load.h" #include "floatarray.h" #include "floatmatrix.h" @@ -41,10 +41,10 @@ namespace oofem { REGISTER_BoundaryCondition(GravityPressure); -IRResultType -GravityPressure :: initializeFrom(InputRecord *ir) +void +GravityPressure :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Load :: initializeFrom(ir); normalVector.resize(3); normalVector.zero(); @@ -53,8 +53,6 @@ GravityPressure :: initializeFrom(InputRecord *ir) zeroLevel = 0; IR_GIVE_OPTIONAL_FIELD(ir, zeroLevel, _IFT_GravityPressure_zerolevel); - - return Load :: initializeFrom(ir); } void diff --git a/src/tm/gravitypressure.h b/src/tm/BoundaryCondition/gravitypressure.h similarity index 83% rename from src/tm/gravitypressure.h rename to src/tm/BoundaryCondition/gravitypressure.h index b08790e47..45b830ed8 100644 --- a/src/tm/gravitypressure.h +++ b/src/tm/BoundaryCondition/gravitypressure.h @@ -62,21 +62,19 @@ namespace oofem { class GravityPressure : public BodyLoad { protected: - - double zeroLevel; + double zeroLevel = 0.; FloatArray normalVector; public: - /// Constructor GravityPressure(int i, Domain * d) : BodyLoad(i, d) { } - virtual bcGeomType giveBCGeoType() const { return GravityPressureBGT; } - virtual void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode); + bcGeomType giveBCGeoType() const override { return GravityPressureBGT; } + void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual const char *giveClassName() const { return "GravityPressure"; } - virtual const char *giveInputRecordName() const { return _IFT_GravityPressure_Name; } + const char *giveClassName() const override { return "GravityPressure"; } + const char *giveInputRecordName() const override { return _IFT_GravityPressure_Name; } }; } // end namespace oofem diff --git a/src/tm/transportgradientdirichlet.C b/src/tm/BoundaryCondition/transportgradientdirichlet.C similarity index 94% rename from src/tm/transportgradientdirichlet.C rename to src/tm/BoundaryCondition/transportgradientdirichlet.C index 228300392..af3456bef 100644 --- a/src/tm/transportgradientdirichlet.C +++ b/src/tm/BoundaryCondition/transportgradientdirichlet.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "transportgradientdirichlet.h" +#include "tm/BoundaryCondition/transportgradientdirichlet.h" #include "dofiditem.h" #include "dofmanager.h" #include "dof.h" @@ -53,7 +53,7 @@ #include "mathfem.h" #include "feinterpol.h" #include "feinterpol3d.h" -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "gausspoint.h" #include "sparselinsystemnm.h" @@ -62,26 +62,26 @@ #include #include #include +#include namespace oofem { REGISTER_BoundaryCondition(TransportGradientDirichlet); -IRResultType TransportGradientDirichlet :: initializeFrom(InputRecord *ir) +void TransportGradientDirichlet :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + GeneralBoundaryCondition :: initializeFrom(ir); + IR_GIVE_FIELD(ir, mGradient, _IFT_TransportGradientDirichlet_gradient); mCenterCoord.resize(3); IR_GIVE_OPTIONAL_FIELD(ir, mCenterCoord, _IFT_TransportGradientDirichlet_centerCoords); - this->tractionControl = ir->hasField(_IFT_TransportGradientDirichlet_tractionControl); + this->tractionControl = ir.hasField(_IFT_TransportGradientDirichlet_tractionControl); if ( this->tractionControl ) { IR_GIVE_FIELD(ir, surfSets, _IFT_TransportGradientDirichlet_surfSets); //IR_GIVE_FIELD(ir, edgeSets, _IFT_TransportGradientDirichlet_edgeSets); } - - return GeneralBoundaryCondition :: initializeFrom(ir); } @@ -109,9 +109,9 @@ void TransportGradientDirichlet :: postInitialize() double TransportGradientDirichlet :: give(Dof *dof, ValueModeType mode, double time) { - FloatArray *coords = dof->giveDofManager()->giveCoordinates(); + const auto &coords = dof->giveDofManager()->giveCoordinates(); - if ( coords->giveSize() != this->mCenterCoord.giveSize() ) { + if ( coords.giveSize() != this->mCenterCoord.giveSize() ) { OOFEM_ERROR("Size of coordinate system different from center coordinate in b.c."); } @@ -127,8 +127,7 @@ double TransportGradientDirichlet :: give(Dof *dof, ValueModeType mode, double t } // Reminder: u_i = g_i . (x_i - xc_i + xi_i) - FloatArray dx; - dx.beDifferenceOf(* coords, this->mCenterCoord); + auto dx = coords - this->mCenterCoord; // Add "xi" if it is defined. Classical Dirichlet b.c. is retained if this isn't defined (or set to zero). if ( !xis.empty() ) { dx.add(xis[dof->giveDofManager()->giveNumber()]); @@ -181,8 +180,8 @@ void TransportGradientDirichlet :: computeCoefficientMatrix(FloatMatrix &C) C.zero(); for ( auto &n : domain->giveDofManagers() ) { - FloatArray *coords = n->giveCoordinates(); - Dof *d1 = n->giveDofWithID( this->dofs(0) ); + const auto &coords = n->giveCoordinates(); + Dof *d1 = n->giveDofWithID( this->dofs[0] ); int k1 = d1->__givePrescribedEquationNumber(); if ( k1 ) { // Add "xi" if it is defined. Classical Dirichlet b.c. is retained if this isn't defined (or set to zero). @@ -191,7 +190,7 @@ void TransportGradientDirichlet :: computeCoefficientMatrix(FloatMatrix &C) xi = xis[n->giveNumber()]; } for ( int i = 1; i <= nsd; ++i ) { - C.at(k1, i) = coords->at(i) - mCenterCoord.at(i) + xi.at(i); + C.at(k1, i) = coords.at(i) - mCenterCoord.at(i) + xi.at(i); } //printf("C.at(%d, :) = %e, %e, %e\n", k1, C.at(k1, 1), C.at(k1, 2), C.at(k1, 3)); } @@ -317,11 +316,11 @@ void TransportGradientDirichlet :: computeTangent(FloatMatrix &tangent, TimeStep sol.resize(KfpC.giveNumberOfRows(), KfpC.giveNumberOfColumns()); int nsd = domain->giveNumberOfSpatialDimensions(); for ( auto &n : domain->giveDofManagers() ) { - int k1 = n->giveDofWithID( this->dofs(0) )->__giveEquationNumber(); + int k1 = n->giveDofWithID( this->dofs[0] )->__giveEquationNumber(); if ( k1 ) { - FloatArray *coords = n->giveCoordinates(); + const auto &coords = n->giveCoordinates(); for ( int i = 1; i <= nsd; ++i ) { - sol.at(k1, i) = -(coords->at(i) - mCenterCoord.at(i)); + sol.at(k1, i) = -(coords.at(i) - mCenterCoord.at(i)); } } } @@ -384,7 +383,7 @@ void TransportGradientDirichlet :: computeXi() for ( int j = i+1; j < this->surfSets.giveSize(); ++j ) { std :: vector< std :: tuple< int, int > > ijEdgeSet; std :: set_intersection(surfedges[i].begin(), surfedges[i].end(), - surfedges[j].begin(), surfedges[j].end(), back_inserter(ijEdgeSet)); + surfedges[j].begin(), surfedges[j].end(), std::back_inserter(ijEdgeSet)); IntArray edgelist; edgelist.preallocate(ijEdgeSet.size() * 2); for ( auto &edge : ijEdgeSet ) { @@ -447,8 +446,7 @@ void TransportGradientDirichlet :: computeXi() FloatArray b; FEInterpolation3d *interp = static_cast< FEInterpolation3d* >( e->giveInterpolation() ); - IntArray bNodes; - interp->boundaryEdgeGiveNodes(bNodes, edge); + const auto &bNodes = interp->boundaryEdgeGiveNodes(edge); int order = interp->giveInterpolationOrder(); std :: unique_ptr< IntegrationRule > ir( interp->giveBoundaryEdgeIntegrationRule(order, edge) ); static_cast< TransportElement* >(e)->computeConstitutiveMatrixAt(D, Capacity, e->giveDefaultIntegrationRulePtr()->getIntegrationPoint(1), tStep); @@ -469,7 +467,7 @@ void TransportGradientDirichlet :: computeXi() #if 1 FloatArray t; for ( int i = 1; i <= b.giveSize(); ++i ) { - t.add(b.at(i), *e->giveNode(bNodes.at(i))->giveCoordinates()); + t.add(b.at(i), e->giveNode(bNodes.at(i))->giveCoordinates()); } t.normalize(); FloatArray tmp; @@ -489,7 +487,7 @@ void TransportGradientDirichlet :: computeXi() for ( int i = 1; i <= bNodes.giveSize(); ++i ) { int enode = bNodes.at(i); Node *n = e->giveNode(enode); - const FloatArray &x = *n->giveCoordinates(); + const auto &x = n->giveCoordinates(); cvec.at(i, 1) = x.at(1); cvec.at(i, 2) = x.at(2); cvec.at(i, 3) = x.at(3); @@ -587,14 +585,13 @@ void TransportGradientDirichlet :: computeXi() } Ke.symmetrized(); - IntArray bNodes; - interp->boundaryGiveNodes(bNodes, surf); + const auto &bNodes = interp->boundaryGiveNodes(surf); IntArray loc(bNodes.giveSize()); FloatMatrix cvec(bNodes.giveSize(), 3); for ( int i = 1; i <= bNodes.giveSize(); ++i ) { int enode = bNodes.at(i); Node *n = e->giveNode(enode); - FloatArray x = *n->giveCoordinates() + this->xis[n->giveNumber()]; + auto x = n->giveCoordinates() + this->xis[n->giveNumber()]; cvec.at(i, 1) = x.at(1); cvec.at(i, 2) = x.at(2); cvec.at(i, 3) = x.at(3); diff --git a/src/tm/transportgradientdirichlet.h b/src/tm/BoundaryCondition/transportgradientdirichlet.h similarity index 83% rename from src/tm/transportgradientdirichlet.h rename to src/tm/BoundaryCondition/transportgradientdirichlet.h index 11654cc95..21605b88b 100644 --- a/src/tm/transportgradientdirichlet.h +++ b/src/tm/BoundaryCondition/transportgradientdirichlet.h @@ -76,29 +76,21 @@ class OOFEM_EXPORT TransportGradientDirichlet : public BoundaryCondition FloatArray mGradient; FloatArray mCenterCoord; - bool tractionControl; + bool tractionControl = false; /// Stores one "psi" value for each node std :: map< int, FloatArray > xis; IntArray surfSets; public: - /** - * Creates boundary condition with given number, belonging to given domain. - * @param n Boundary condition number. - * @param d Domain to which new object will belongs. - */ TransportGradientDirichlet(int n, Domain *d) : BoundaryCondition(n, d) { } - /// Destructor - virtual ~TransportGradientDirichlet() { } + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void postInitialize() override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void postInitialize(); + double give(Dof *dof, ValueModeType mode, double time) override; - virtual double give(Dof *dof, ValueModeType mode, double time); - - virtual bcType giveType() const { return DirichletBT; } + bcType giveType() const override { return DirichletBT; } double domainSize(); /** @@ -122,13 +114,13 @@ class OOFEM_EXPORT TransportGradientDirichlet : public BoundaryCondition * @param tStep Active time step. */ virtual void computeTangent(FloatMatrix &tangent, TimeStep *tStep); - + /// Computes the offset values for "improved" Dirichlet. See class description. void computeXi(); - virtual void scale(double s) { mGradient.times(s); } + void scale(double s) override { mGradient.times(s); } - virtual const char *giveClassName() const { return "TransportGradientDirichlet"; } - virtual const char *giveInputRecordName() const { return _IFT_TransportGradientDirichlet_Name; } + const char *giveClassName() const override { return "TransportGradientDirichlet"; } + const char *giveInputRecordName() const override { return _IFT_TransportGradientDirichlet_Name; } }; } // end namespace oofem diff --git a/src/tm/transportgradientneumann.C b/src/tm/BoundaryCondition/transportgradientneumann.C similarity index 90% rename from src/tm/transportgradientneumann.C rename to src/tm/BoundaryCondition/transportgradientneumann.C index 47ef9117c..5627fc827 100644 --- a/src/tm/transportgradientneumann.C +++ b/src/tm/BoundaryCondition/transportgradientneumann.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "transportgradientneumann.h" +#include "tm/BoundaryCondition/transportgradientneumann.h" #include "classfactory.h" #include "node.h" #include "masterdof.h" @@ -50,7 +50,11 @@ #include "engngm.h" #include "mathfem.h" #include "dynamicinputrecord.h" -#include "transportelement.h" +#include "tm/Elements/transportelement.h" + +#ifdef _OPENMP +#include +#endif namespace oofem { REGISTER_BoundaryCondition(TransportGradientNeumann); @@ -58,7 +62,7 @@ REGISTER_BoundaryCondition(TransportGradientNeumann); TransportGradientNeumann :: TransportGradientNeumann(int n, Domain *d) : ActiveBoundaryCondition(n, d), //PrescribedGradientHomogenization(), - mpFluxHom( new Node(0, d) ) + mpFluxHom( std::make_unique(0, d) ) { int nsd = d->giveNumberOfSpatialDimensions(); for ( int i = 0; i < nsd; i++ ) { @@ -69,14 +73,10 @@ TransportGradientNeumann :: TransportGradientNeumann(int n, Domain *d) : } } -TransportGradientNeumann :: ~TransportGradientNeumann() -{ -} - -IRResultType TransportGradientNeumann :: initializeFrom(InputRecord *ir) +void TransportGradientNeumann :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + ActiveBoundaryCondition :: initializeFrom(ir); IR_GIVE_FIELD(ir, mGradient, _IFT_TransportGradientNeumann_gradient); @@ -84,9 +84,7 @@ IRResultType TransportGradientNeumann :: initializeFrom(InputRecord *ir) this->mCenterCoord.clear(); IR_GIVE_OPTIONAL_FIELD(ir, mCenterCoord, _IFT_TransportGradientNeumann_centerCoords) - this->dispControl = ir->hasField(_IFT_TransportGradientNeumann_dispControl); - - return ActiveBoundaryCondition :: initializeFrom(ir); + this->dispControl = ir.hasField(_IFT_TransportGradientNeumann_dispControl); } @@ -138,7 +136,9 @@ double TransportGradientNeumann :: domainSize() void TransportGradientNeumann :: assembleVector(FloatArray &answer, TimeStep *tStep, CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm) + const UnknownNumberingScheme &s, + FloatArray *eNorm, + void* lock) { IntArray flux_loc; // For the displacements and flux respectively mpFluxHom->giveLocationArray(mFluxIds, flux_loc, s); @@ -150,13 +150,18 @@ void TransportGradientNeumann :: assembleVector(FloatArray &answer, TimeStep *tS double loadLevel = this->giveTimeFunction()->evaluateAtTime(tStep->giveTargetTime()); fluxLoad.beScaled(-rve_size*loadLevel, mGradient); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(fluxLoad, flux_loc); +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } else if ( type == InternalForcesVector ) { FloatMatrix Ke; FloatArray fe_v, fe_s; FloatArray fluxHom, e_u; - IntArray loc, masterDofIDs, fluxMasterDofIDs, bNodes; + IntArray loc, masterDofIDs, fluxMasterDofIDs; // Fetch the current values of the flux; mpFluxHom->giveUnknownVector(fluxHom, mFluxIds, mode, tStep); @@ -173,7 +178,7 @@ void TransportGradientNeumann :: assembleVector(FloatArray &answer, TimeStep *tS int boundary = boundaries[pos * 2 + 1]; // Fetch the element information; - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc, bNodes, this->dofs, s, & masterDofIDs); e->computeBoundaryVectorOf(bNodes, this->dofs, mode, tStep, e_u); this->integrateTangent(Ke, e, boundary, i, pos); @@ -185,24 +190,31 @@ void TransportGradientNeumann :: assembleVector(FloatArray &answer, TimeStep *tS // Note: The terms appear negative in the equations: fe_v.negated(); fe_s.negated(); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(fe_s, loc); // Contributions to delta_v equations answer.assemble(fe_v, flux_loc); // Contribution to delta_s_i equations if ( eNorm != NULL ) { eNorm->assembleSquared(fe_s, masterDofIDs); eNorm->assembleSquared(fe_v, fluxMasterDofIDs); } +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } } } void TransportGradientNeumann :: assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale) + CharType type, const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, double scale, + void* lock) { if ( type == TangentStiffnessMatrix || type == SecantStiffnessMatrix || type == ElasticStiffnessMatrix ) { FloatMatrix Ke, KeT; - IntArray loc_r, loc_c, flux_loc_r, flux_loc_c, bNodes; + IntArray loc_r, loc_c, flux_loc_r, flux_loc_c; // Fetch the columns/rows for the flux contributions; mpFluxHom->giveLocationArray(mFluxIds, flux_loc_r, r_s); @@ -216,16 +228,21 @@ void TransportGradientNeumann :: assemble(SparseMtrx &answer, TimeStep *tStep, Element *e = this->giveDomain()->giveElement( boundaries[pos * 2] ); int boundary = boundaries[pos * 2 + 1]; - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc_r, bNodes, this->dofs, r_s); e->giveBoundaryLocationArray(loc_c, bNodes, this->dofs, c_s); this->integrateTangent(Ke, e, boundary, i, pos); Ke.times(-scale); KeT.beTranspositionOf(Ke); - +#ifdef _OPENMP + if (lock) omp_set_lock(static_cast(lock)); +#endif answer.assemble(flux_loc_r, loc_c, Ke); // Contribution to delta_s_i equations answer.assemble(loc_r, flux_loc_c, KeT); // Contributions to delta_v equations +#ifdef _OPENMP + if (lock) omp_unset_lock(static_cast(lock)); +#endif } } } else { @@ -236,7 +253,7 @@ void TransportGradientNeumann :: assemble(SparseMtrx &answer, TimeStep *tStep, void TransportGradientNeumann :: giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) { - IntArray loc_r, loc_c, flux_loc_r, flux_loc_c, bNodes; + IntArray loc_r, loc_c, flux_loc_r, flux_loc_c; // Fetch the columns/rows for the flux contributions; mpFluxHom->giveLocationArray(mFluxIds, flux_loc_r, r_s); @@ -256,7 +273,7 @@ void TransportGradientNeumann :: giveLocationArrays(std :: vector< IntArray > &r Element *e = this->giveDomain()->giveElement( boundaries[pos * 2] ); int boundary = boundaries[pos * 2 + 1]; - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc_r, bNodes, this->dofs, r_s); e->giveBoundaryLocationArray(loc_c, bNodes, this->dofs, c_s); @@ -318,11 +335,11 @@ void TransportGradientNeumann :: computeTangent(FloatMatrix &tangent, TimeStep * } } - std :: unique_ptr< SparseMtrx > Kuu(Kff->giveSubMatrix(loc_u, loc_u)); + std :: unique_ptr< SparseMtrx > Kuu = Kff->giveSubMatrix(loc_u, loc_u); FloatMatrix KusD; #if 0 // NOTE: Kus is actually a dense matrix, but we have to make it a dense matrix first - std :: unique_ptr< SparseMtrx > Kus(Kff->giveSubMatrix(loc_u, loc_s)); + std :: unique_ptr< SparseMtrx > Kus = Kff->giveSubMatrix(loc_u, loc_s); Kus->toFloatMatrix(KusD); Kus.reset(); #else @@ -330,7 +347,7 @@ void TransportGradientNeumann :: computeTangent(FloatMatrix &tangent, TimeStep * // PETSc doesn't allow you to take non-symmetric submatrices from a SBAIJ-matrix. // Which means extracting "Kus" puts limitations on Kuu. FloatMatrix Ke, KeT; - IntArray loc_r, bNodes; + IntArray loc_r; KusD.resize(neq - loc_s.giveSize(), loc_s.giveSize()); for ( int i = 0; i < this->surfSets.giveSize(); ++i ) { @@ -341,7 +358,7 @@ void TransportGradientNeumann :: computeTangent(FloatMatrix &tangent, TimeStep * Element *e = this->giveDomain()->giveElement( boundaries[pos * 2] ); int boundary = boundaries[pos * 2 + 1]; - e->giveInterpolation()->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = e->giveInterpolation()->boundaryGiveNodes(boundary); e->giveBoundaryLocationArray(loc_r, bNodes, this->dofs, fnum); this->integrateTangent(Ke, e, boundary, i, pos); @@ -378,11 +395,11 @@ void TransportGradientNeumann :: computeTangent(FloatMatrix &tangent, TimeStep * #endif us.resize(KusD.giveNumberOfRows(), KusD.giveNumberOfColumns()); for ( auto &n : domain->giveDofManagers() ) { - int k1 = n->giveDofWithID( this->dofs(0) )->__giveEquationNumber(); + int k1 = n->giveDofWithID( this->dofs[0] )->__giveEquationNumber(); if ( k1 ) { - FloatArray *coords = n->giveCoordinates(); + const auto &coords = n->giveCoordinates(); for ( int i = 1; i <= nsd; ++i ) { - us.at(k1, i) += -(coords->at(i) - mCenterCoord.at(i)); + us.at(k1, i) += -(coords.at(i) - mCenterCoord.at(i)); } } } @@ -529,7 +546,7 @@ void TransportGradientNeumann :: integrateTangent(FloatMatrix &oTangent, Element FloatArray normal, n; FEInterpolation *interp = e->giveInterpolation(); // Geometry interpolation - //FEInterpolation *interpUnknown = e->giveInterpolation(this->dofs(0)); + //FEInterpolation *interpUnknown = e->giveInterpolation(this->dofs[0]); int order = interp->giveInterpolationOrder(); std :: unique_ptr< IntegrationRule > ir( interp->giveBoundaryIntegrationRule(order, boundary) ); diff --git a/src/tm/transportgradientneumann.h b/src/tm/BoundaryCondition/transportgradientneumann.h similarity index 72% rename from src/tm/transportgradientneumann.h rename to src/tm/BoundaryCondition/transportgradientneumann.h index 7788dab4a..88f2e0fb6 100644 --- a/src/tm/transportgradientneumann.h +++ b/src/tm/BoundaryCondition/transportgradientneumann.h @@ -62,33 +62,32 @@ class OOFEM_EXPORT TransportGradientNeumann : public ActiveBoundaryCondition //, { public: TransportGradientNeumann(int n, Domain *d); - virtual ~TransportGradientNeumann(); - virtual int giveNumberOfInternalDofManagers() { return 1; } - virtual DofManager *giveInternalDofManager(int i); + int giveNumberOfInternalDofManagers() override { return 1; } + DofManager *giveInternalDofManager(int i) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void postInitialize(); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void postInitialize() override; - virtual bcType giveType() const { return UnknownBT; } + bcType giveType() const override { return UnknownBT; } + + void scale(double s) override; - virtual void scale(double s); - double domainSize(); - virtual void assembleVector(FloatArray &answer, TimeStep *tStep, - CharType type, ValueModeType mode, - const UnknownNumberingScheme &s, FloatArray *eNorm = NULL); + void assembleVector(FloatArray &answer, TimeStep *tStep, + CharType type, ValueModeType mode, + const UnknownNumberingScheme &s, FloatArray *eNorm=nullptr, void*lock=nullptr) override; - virtual void assemble(SparseMtrx &answer, TimeStep *tStep, - CharType type, const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s, double scale = 1.0); + void assemble(SparseMtrx &answer, TimeStep *tStep, CharType type, const UnknownNumberingScheme &r_s, + const UnknownNumberingScheme &c_s, double scale=1.0, void*lock=nullptr) override; - virtual void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, - const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s); + void giveLocationArrays(std :: vector< IntArray > &rows, std :: vector< IntArray > &cols, CharType type, + const UnknownNumberingScheme &r_s, const UnknownNumberingScheme &c_s) override; - virtual const char *giveClassName() const { return "TransportGradientNeumann"; } - virtual const char *giveInputRecordName() const { return _IFT_TransportGradientNeumann_Name; } + const char *giveClassName() const override { return "TransportGradientNeumann"; } + const char *giveInputRecordName() const override { return _IFT_TransportGradientNeumann_Name; } virtual void computeField(FloatArray &flux, TimeStep *tStep); virtual void computeTangent(FloatMatrix &tangent, TimeStep *tStep); diff --git a/src/tm/transportgradientperiodic.C b/src/tm/BoundaryCondition/transportgradientperiodic.C similarity index 92% rename from src/tm/transportgradientperiodic.C rename to src/tm/BoundaryCondition/transportgradientperiodic.C index b44eeba78..8171abea6 100644 --- a/src/tm/transportgradientperiodic.C +++ b/src/tm/BoundaryCondition/transportgradientperiodic.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "transportgradientperiodic.h" +#include "tm/BoundaryCondition/transportgradientperiodic.h" #include "dofiditem.h" #include "node.h" #include "dofmanager.h" @@ -77,11 +77,6 @@ TransportGradientPeriodic :: TransportGradientPeriodic(int n, Domain *d) : Activ } -TransportGradientPeriodic :: ~TransportGradientPeriodic() -{ -} - - int TransportGradientPeriodic :: giveNumberOfInternalDofManagers() { return 1; @@ -115,23 +110,25 @@ void TransportGradientPeriodic :: findSlaveToMasterMap() jumps.emplace_back(FloatArray{0., jump.at(2), 0.}); jumps.emplace_back(FloatArray{0., 0., jump.at(3)}); + double maxdist = jump.computeNorm()*1e-5; + this->slavemap.clear(); for ( int inode : nodes ) { - Node *masterNode = NULL; + Node *masterNode = nullptr; Node *node = this->domain->giveNode(inode); - const FloatArray &masterCoord = *node->giveCoordinates(); + const auto &masterCoord = node->giveCoordinates(); //printf("node %d\n", node->giveLabel()); masterCoord.printYourself(); // The difficult part, what offset to subtract to find the master side; for ( FloatArray &testJump : jumps ) { coord.beDifferenceOf(masterCoord, testJump); - masterNode = sl->giveNodeClosestToPoint(coord, fabs(jump.at(1))*1e-5); - if ( masterNode != NULL ) { + masterNode = sl->giveNodeClosestToPoint(coord, maxdist); + if ( masterNode ) { //printf("Found master (%d) to node %d (distance = %e)\n", masterNode->giveNumber(), node->giveNumber(), - // masterNode->giveCoordinates()->distance(coord)); + // distance(*masterNode->giveCoordinates(), coord)); break; } } - if ( masterNode != NULL ) { + if ( masterNode ) { this->slavemap.insert({node->giveNumber(), masterNode->giveNumber()}); } else { OOFEM_ERROR("Couldn't find master node!"); @@ -170,7 +167,7 @@ int TransportGradientPeriodic :: giveNumberOfMasterDofs(ActiveDof *dof) Dof *TransportGradientPeriodic :: giveMasterDof(ActiveDof *dof, int mdof) { if ( this->isGradDof(dof) ) { - return NULL; + return nullptr; } if ( mdof == 1 ) { int node = this->slavemap[dof->giveDofManager()->giveNumber()]; @@ -221,7 +218,7 @@ void TransportGradientPeriodic :: computeTangent(FloatMatrix &k, TimeStep *tStep Kpp->buildInternalStructure(rve, this->domain->giveNumber(), pnum); //Kfp->buildInternalStructure(rve, neq, nsd, {}, {}); //Kpp->buildInternalStructure(rve, nsd, nsd, {}, {}); -#if 0 +#if 1 rve->assemble(*Kff, tStep, TangentAssembler(TangentStiffness), fnum, this->domain); rve->assemble(*Kfp, tStep, TangentAssembler(TangentStiffness), fnum, pnum, this->domain); rve->assemble(*Kpp, tStep, TangentAssembler(TangentStiffness), pnum, this->domain); @@ -292,15 +289,15 @@ void TransportGradientPeriodic :: computeTangent(FloatMatrix &k, TimeStep *tStep // Initial guess (Taylor assumption) helps KSP-iterations for ( auto &n : domain->giveDofManagers() ) { - int k1 = n->giveDofWithID( this->dofs(0) )->__giveEquationNumber(); + int k1 = n->giveDofWithID( this->dofs[0] )->__giveEquationNumber(); if ( k1 ) { - FloatArray *coords = n->giveCoordinates(); + const auto &coords = n->giveCoordinates(); for ( int i = 1; i <= nsd; ++i ) { - sol.at(k1, i) = -(coords->at(i) - mCenterCoord.at(i)); + sol.at(k1, i) = -(coords.at(i) - mCenterCoord.at(i)); } } } - + if ( solver->solve(*Kff, rhs, sol) & NM_NoSuccess ) { OOFEM_ERROR("Failed to solve Kff"); } @@ -321,11 +318,10 @@ void TransportGradientPeriodic :: computeTangent(FloatMatrix &k, TimeStep *tStep void TransportGradientPeriodic :: computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs) { DofManager *master = this->domain->giveDofManager(this->slavemap[dof->giveDofManager()->giveNumber()]); - FloatArray *coords = dof->giveDofManager()->giveCoordinates(); - FloatArray *masterCoords = master->giveCoordinates(); + const auto &coords = dof->giveDofManager()->giveCoordinates(); + const auto &masterCoords = master->giveCoordinates(); - FloatArray dx; - dx.beDifferenceOf(* coords, * masterCoords ); + auto dx = coords - masterCoords; masterContribs.resize(dx.giveSize() + 1); @@ -340,7 +336,7 @@ double TransportGradientPeriodic :: giveUnknown(double val, ValueModeType mode, { DofManager *master = this->domain->giveDofManager(this->slavemap[dof->giveDofManager()->giveNumber()]); FloatArray dx, g; - dx.beDifferenceOf(* dof->giveDofManager()->giveCoordinates(), * master->giveCoordinates()); + dx.beDifferenceOf(dof->giveDofManager()->giveCoordinates(), master->giveCoordinates()); this->grad->giveUnknownVector(g, this->grad_ids, mode, tStep); return val + g.dotProduct(dx); } @@ -402,9 +398,10 @@ bool TransportGradientPeriodic :: isGradDof(Dof *dof) } -IRResultType TransportGradientPeriodic :: initializeFrom(InputRecord *ir) +void TransportGradientPeriodic :: initializeFrom(InputRecord &ir) { - IRResultType result; + ActiveBoundaryCondition :: initializeFrom(ir); + //PrescribedGradientHomogenization::initializeFrom(ir); IR_GIVE_FIELD(ir, this->mGradient, _IFT_TransportGradientPeriodic_gradient) this->mCenterCoord = {0., 0., 0.}; @@ -412,9 +409,6 @@ IRResultType TransportGradientPeriodic :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, this->masterSet, _IFT_TransportGradientPeriodic_masterSet) IR_GIVE_FIELD(ir, this->jump, _IFT_TransportGradientPeriodic_jump) - - return ActiveBoundaryCondition :: initializeFrom(ir); - //return PrescribedGradientHomogenization::initializeFrom(ir); } diff --git a/src/tm/transportgradientperiodic.h b/src/tm/BoundaryCondition/transportgradientperiodic.h similarity index 72% rename from src/tm/transportgradientperiodic.h rename to src/tm/BoundaryCondition/transportgradientperiodic.h index 73d906eb1..251cafb91 100644 --- a/src/tm/transportgradientperiodic.h +++ b/src/tm/BoundaryCondition/transportgradientperiodic.h @@ -32,7 +32,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - #ifndef transportgradientperiodic_h_ #define transportgradientperiodic_h_ @@ -70,45 +69,44 @@ class OOFEM_EXPORT TransportGradientPeriodic : public ActiveBoundaryCondition // std :: map< int, int > slavemap; FloatArray jump; - - int masterSet; + + int masterSet = 0; /** * This is the central support function, which finds the corresponding slave nodes for each master node. */ void findSlaveToMasterMap(); - + virtual double domainSize(Domain *d, int setNum); public: TransportGradientPeriodic(int n, Domain *d); - virtual ~TransportGradientPeriodic(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); - virtual void postInitialize(); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; + void postInitialize() override; - virtual int giveNumberOfInternalDofManagers(); - virtual DofManager *giveInternalDofManager(int i); + int giveNumberOfInternalDofManagers() override; + DofManager *giveInternalDofManager(int i) override; - virtual int giveNumberOfMasterDofs(ActiveDof *dof); - virtual Dof *giveMasterDof(ActiveDof *dof, int mdof); + int giveNumberOfMasterDofs(ActiveDof *dof) override; + Dof *giveMasterDof(ActiveDof *dof, int mdof) override; - virtual void computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs); + void computeDofTransformation(ActiveDof *dof, FloatArray &masterContribs) override; virtual void computeField(FloatArray &sigma, TimeStep *tStep); virtual void computeTangent(FloatMatrix &E, TimeStep *tStep); double giveUnknown(double val, ValueModeType mode, TimeStep *tStep, ActiveDof *dof); - virtual double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof); - virtual double giveUnknown(ValueModeType mode, TimeStep *tStep, ActiveDof *dof); - virtual bool isPrimaryDof(ActiveDof *dof); - virtual double giveBcValue(Dof *dof, ValueModeType mode, TimeStep *tStep); - virtual bool hasBc(Dof *dof, TimeStep *tStep); + double giveUnknown(PrimaryField &field, ValueModeType mode, TimeStep *tStep, ActiveDof *dof) override; + double giveUnknown(ValueModeType mode, TimeStep *tStep, ActiveDof *dof) override; + bool isPrimaryDof(ActiveDof *dof) override; + double giveBcValue(Dof *dof, ValueModeType mode, TimeStep *tStep) override; + bool hasBc(Dof *dof, TimeStep *tStep) override; bool isGradDof(Dof *dof); - virtual bool requiresActiveDofs() { return true; } + bool requiresActiveDofs() override { return true; } - virtual const char *giveClassName() const { return "TransportGradientPeriodic"; } - virtual const char *giveInputRecordName() const { return _IFT_TransportGradientPeriodic_Name; } + const char *giveClassName() const override { return "TransportGradientPeriodic"; } + const char *giveInputRecordName() const override { return _IFT_TransportGradientPeriodic_Name; } }; } // end namespace oofem diff --git a/src/tm/CMakeLists.txt b/src/tm/CMakeLists.txt index 23f17bad1..7110066e9 100644 --- a/src/tm/CMakeLists.txt +++ b/src/tm/CMakeLists.txt @@ -1,65 +1,65 @@ if (USE_CEMHYD) set (tm_cemhyd - cemhyd/cemhydmat.C + Materials/cemhyd/cemhydmat.C ) endif () set (tm_emodel - stationarytransportproblem.C - nonstationarytransportproblem.C - nltransienttransportproblem.C - darcyflow.C - transienttransportproblem.C + EngineeringModels/nltransienttransportproblem.C + EngineeringModels/nonstationarytransportproblem.C + EngineeringModels/stationarytransportproblem.C + EngineeringModels/transienttransportproblem.C ) set (tm_element - transportelement.C - quad1_ht.C - tr1_ht.C - quadaxisym1_ht.C - traxisym1_ht.C - brick1_ht.C - qbrick1_ht.C - wedge_ht.C - qwedge_ht.C - tetrah1_ht.C - tr1darcy.C - latticetransportelement.C - lattice2d_mt.C + Elements/transportelement.C + Elements/line1_ht.C + Elements/quad1_ht.C + Elements/qquad1_ht.C + Elements/tr1_ht.C + Elements/quadaxisym1_ht.C + Elements/traxisym1_ht.C + Elements/brick1_ht.C + Elements/qbrick1_ht.C + Elements/wedge_ht.C + Elements/qwedge_ht.C + Elements/tetrah1_ht.C + Elements/tr1darcy.C + Elements/LatticeElements/latticetransportelement.C + Elements/LatticeElements/lattice2d_mt.C + Elements/LatticeElements/lattice3d_mt.C ) set (tm_boundary - gravitypressure.C - transportgradientneumann.C - transportgradientdirichlet.C - transportgradientperiodic.C + BoundaryCondition/gravitypressure.C + BoundaryCondition/transportgradientneumann.C + BoundaryCondition/transportgradientdirichlet.C + BoundaryCondition/transportgradientperiodic.C ) set (tm_cs simpletransportcrosssection.C ) -set (tm_status - transportmaterial.C - latticetransmat.C - ) - set (tm_material - hydram.C - hydratingisoheatmat.C - hydratinghemomat.C - hydratingconcretemat.C - hemotkmat.C - hemokunzelmat.C - hemobaznajmat.C - isoheatmat.C - isomoisturemat.C - isolinmoisturemat.C - bazantnajjarmat.C - nlisomoisturemat.C - nonlinearmassmat.C - anisomassmat.C - rvestokesflow.C + Materials/anisomassmat.C + Materials/bazantnajjarmat.C + Materials/hemobaznajmat.C + Materials/hemokunzelmat.C + Materials/hemotkmat.C + Materials/hydram.C + Materials/hydratingconcretemat.C + Materials/hydratinghemomat.C + Materials/hydratingisoheatmat.C + Materials/isoheatmat.C + Materials/isolinmoisturemat.C + Materials/isomoisturemat.C + Materials/LatticeMaterials/latticetransmat.C + Materials/nlisomoisturemat.C + Materials/nonlinearmassmat.C + Materials/rvestokesflow.C + Materials/transportmaterial.C + Materials/twophasemat.C ) set (tm @@ -67,7 +67,6 @@ set (tm ${tm_element} ${tm_material} ${tm_cs} - ${tm_status} ${tm_new} ${tm_cemhyd} ${tm_hydram} diff --git a/src/tm/lattice2d_mt.C b/src/tm/Elements/LatticeElements/lattice2d_mt.C similarity index 72% rename from src/tm/lattice2d_mt.C rename to src/tm/Elements/LatticeElements/lattice2d_mt.C index b1a45d2d6..94930f477 100644 --- a/src/tm/lattice2d_mt.C +++ b/src/tm/Elements/LatticeElements/lattice2d_mt.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "lattice2d_mt.h" -#include "transportmaterial.h" -#include "latticetransmat.h" +#include "tm/Elements/LatticeElements/lattice2d_mt.h" +#include "tm/Materials/transportmaterial.h" +#include "tm/Materials/LatticeMaterials/latticetransmat.h" #include "node.h" #include "material.h" #include "crosssection.h" @@ -59,33 +59,18 @@ REGISTER_Element(Lattice2d_mt); Lattice2d_mt :: Lattice2d_mt(int n, Domain *aDomain, ElementMode em) : LatticeTransportElement(n, aDomain, em) - // Constructor. { numberOfDofMans = 2; - area = -1.0; - length = 0.0; - couplingFlag = 0; - couplingNumbers.zero(); - crackWidths.zero(); - crackLengths.zero(); } -Lattice2d_mt :: ~Lattice2d_mt() -// Destructor -{ } - double Lattice2d_mt :: giveLength() -// Returns the length of the receiver. { - double dx, dy; - Node *nodeA, *nodeB; - if ( length == 0. ) { - nodeA = this->giveNode(1); - nodeB = this->giveNode(2); - dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); - dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); - length = sqrt(dx * dx + dy * dy); + Node *nodeA = this->giveNode(1); + Node *nodeB = this->giveNode(2); + double dx = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); + double dy = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); + length = sqrt(dx * dx + dy * dy); } return length; @@ -94,11 +79,9 @@ double Lattice2d_mt :: giveLength() double Lattice2d_mt :: givePressure() { - LatticeTransportMaterialStatus *status; IntegrationRule *iRule = this->giveDefaultIntegrationRulePtr(); GaussPoint *gp = iRule->getIntegrationPoint(0); - - status = static_cast< LatticeTransportMaterialStatus * >( gp->giveMaterialStatus() ); + auto status = static_cast< LatticeTransportMaterialStatus * >( gp->giveMaterialStatus() ); return status->givePressure(); } @@ -106,11 +89,9 @@ Lattice2d_mt :: givePressure() double Lattice2d_mt :: giveOldPressure() { - LatticeTransportMaterialStatus *status; IntegrationRule *iRule = this->giveDefaultIntegrationRulePtr(); GaussPoint *gp = iRule->getIntegrationPoint(0); - - status = static_cast< LatticeTransportMaterialStatus * >( gp->giveMaterialStatus() ); + auto status = static_cast< LatticeTransportMaterialStatus * >( gp->giveMaterialStatus() ); return status->giveOldPressure(); } @@ -119,17 +100,13 @@ Lattice2d_mt :: giveOldPressure() double Lattice2d_mt :: giveMass() { - LatticeTransportMaterialStatus *status; - IntegrationRule *iRule = this->giveDefaultIntegrationRulePtr(); GaussPoint *gp = iRule->getIntegrationPoint(0); + auto status = static_cast< LatticeTransportMaterialStatus * >( gp->giveMaterialStatus() ); - status = static_cast< LatticeTransportMaterialStatus * >( gp->giveMaterialStatus() ); - double mass = 0; - mass = status->giveMass(); + double mass = status->giveMass(); //multiply with volume mass *= this->length * this->width / 2.; - return mass; } @@ -137,12 +114,9 @@ Lattice2d_mt :: giveMass() void Lattice2d_mt :: computeNSubMatrixAt(FloatMatrix &answer, const FloatArray &coords) { - double ksi, n1, n2; - //FloatMatrix* answer ; - - ksi = coords.at(1); - n1 = ( 1. - ksi ) * 0.5; - n2 = ( 1. + ksi ) * 0.5; + double ksi = coords.at(1); + double n1 = ( 1. - ksi ) * 0.5; + double n2 = ( 1. + ksi ) * 0.5; answer.resize(1, 2); answer.zero(); @@ -174,7 +148,6 @@ Lattice2d_mt :: computeGradientMatrixAt(FloatMatrix &answer, const FloatArray &l void Lattice2d_mt :: updateInternalState(TimeStep *tStep) -// Updates the receiver at end of step. { FloatArray f, r; FloatMatrix n; @@ -182,9 +155,9 @@ Lattice2d_mt :: updateInternalState(TimeStep *tStep) // force updating ip values for ( auto &iRule: integrationRulesArray ) { - for ( GaussPoint *gp: *iRule ) { - this->computeNmatrixAt( n, gp->giveNaturalCoordinates() ); - this->computeVectorOf({P_f}, VM_Total, tStep, r); + for ( auto &gp: * iRule ) { + this->computeNmatrixAt(n, gp->giveNaturalCoordinates() ); + this->computeVectorOf({ P_f }, VM_Total, tStep, r); f.beProductOf(n, r); mat->updateInternalState(f, gp, tStep); } @@ -194,27 +167,23 @@ Lattice2d_mt :: updateInternalState(TimeStep *tStep) void Lattice2d_mt :: computeGaussPoints() -// Sets up the array containing the four Gauss points of the receiver. { - integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std :: make_unique< GaussIntegrationRule >(1, this, 1, 2); integrationRulesArray [ 0 ]->SetUpPointsOnLine(1, _2dMTLattice); } void Lattice2d_mt :: giveDofManDofIDMask(int inode, IntArray &answer) const { - answer = {P_f}; + answer = { P_f }; } -IRResultType -Lattice2d_mt :: initializeFrom(InputRecord *ir) +void +Lattice2d_mt :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - // first call parent - result = LatticeTransportElement :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + LatticeTransportElement :: initializeFrom(ir); dimension = 2.; IR_GIVE_OPTIONAL_FIELD(ir, dimension, _IFT_Lattice2DMT_dim); @@ -224,7 +193,7 @@ Lattice2d_mt :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, width, _IFT_Lattice2DMT_width); crackLengths.resize(1); crackLengths.at(1) = width; - + IR_GIVE_FIELD(ir, gpCoords, _IFT_Lattice2DMT_gpcoords); @@ -234,36 +203,27 @@ Lattice2d_mt :: initializeFrom(InputRecord *ir) couplingFlag = 0; IR_GIVE_OPTIONAL_FIELD(ir, couplingFlag, _IFT_Lattice2DMT_couplingflag); - + couplingNumbers.resize(1); couplingNumbers.zero(); if ( couplingFlag == 1 ) { - IR_GIVE_OPTIONAL_FIELD(ir, couplingNumbers.at(1), _IFT_Lattice2DMT_couplingnumber); + IR_GIVE_OPTIONAL_FIELD(ir, couplingNumbers.at(1), _IFT_Lattice2DMT_couplingnumber); } numberOfGaussPoints = 1; - - return IRRT_OK; } double Lattice2d_mt :: computeVolumeAround(GaussPoint *gp) -// Returns the portion of the receiver which is attached to gp. { - return this->width *this->thickness *this->giveLength(); + return this->width * this->thickness * this->giveLength(); } void Lattice2d_mt :: computeConductivityMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) { - double dV; - FloatMatrix b, d, db; - GaussPoint *gp; - std :: unique_ptr< IntegrationRule >&iRule = integrationRulesArray [ 0 ]; - gp = iRule->getIntegrationPoint(0); - - double length = giveLength(); - double k; + std :: unique_ptr< IntegrationRule > &iRule = integrationRulesArray [ 0 ]; + GaussPoint *gp = iRule->getIntegrationPoint(0); answer.resize(2, 2); answer.zero(); @@ -272,8 +232,9 @@ Lattice2d_mt :: computeConductivityMatrix(FloatMatrix &answer, MatResponseMode r answer.at(2, 1) = -1; answer.at(2, 2) = 1.; - k = static_cast< TransportMaterial * >( this->giveMaterial() )->giveCharacteristicValue(Conductivity, gp, tStep); - dV = this->computeVolumeAround(gp); + double k = static_cast< TransportMaterial * >( this->giveMaterial() )->giveCharacteristicValue(Conductivity, gp, tStep); + double dV = this->computeVolumeAround(gp); + double length = giveLength(); double temp = k * dV / pow(length, 2.); answer.times(temp); } @@ -282,8 +243,6 @@ Lattice2d_mt :: computeConductivityMatrix(FloatMatrix &answer, MatResponseMode r void Lattice2d_mt :: computeCapacityMatrix(FloatMatrix &answer, TimeStep *tStep) { - double dV, c; - FloatMatrix n; GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); answer.resize(2, 2); answer.zero(); @@ -291,8 +250,8 @@ Lattice2d_mt :: computeCapacityMatrix(FloatMatrix &answer, TimeStep *tStep) answer.at(1, 2) = 1.; answer.at(2, 1) = 1.; answer.at(2, 2) = 2.; - c = static_cast< TransportMaterial * >( this->giveMaterial() )->giveCharacteristicValue(Capacity, gp, tStep); - dV = this->computeVolumeAround(gp) / ( 6.0 * this->dimension ); + double c = static_cast< TransportMaterial * >( this->giveMaterial() )->giveCharacteristicValue(Capacity, gp, tStep); + double dV = this->computeVolumeAround(gp) / ( 6.0 * this->dimension ); answer.times(c * dV); } @@ -301,32 +260,25 @@ Lattice2d_mt :: computeCapacityMatrix(FloatMatrix &answer, TimeStep *tStep) void Lattice2d_mt :: computeInternalSourceRhsVectorAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode) { - int n, nLoads; - double dV; - bcGeomType ltype; - Load *load; std :: unique_ptr< IntegrationRule > &iRule = integrationRulesArray [ 0 ]; - Node *nodeA, *nodeB; - FloatArray deltaX(3); FloatArray val, helpLoadVector, globalIPcoords; FloatMatrix nm; - double k; answer.clear(); FloatArray gravityHelp(2); - nLoads = this->giveBodyLoadArray()->giveSize(); + int nLoads = this->giveBodyLoadArray()->giveSize(); for ( int i = 1; i <= nLoads; i++ ) { - n = bodyLoadArray.at(i); - load = domain->giveLoad(n); - ltype = load->giveBCGeoType(); + int n = bodyLoadArray.at(i); + auto load = domain->giveLoad(n); + auto ltype = load->giveBCGeoType(); if ( ltype == GravityPressureBGT ) { //Compute change of coordinates - nodeA = this->giveNode(1); - nodeB = this->giveNode(2); + Node *nodeA = this->giveNode(1); + Node *nodeB = this->giveNode(2); deltaX.at(1) = nodeB->giveCoordinate(1) - nodeA->giveCoordinate(1); deltaX.at(2) = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); deltaX.at(3) = nodeB->giveCoordinate(2) - nodeA->giveCoordinate(2); @@ -337,10 +289,10 @@ Lattice2d_mt :: computeInternalSourceRhsVectorAt(FloatArray &answer, TimeStep *t gravityHelp.at(1) = 1.; gravityHelp.at(2) = -1.; - dV = this->computeVolumeAround(gp); + double dV = this->computeVolumeAround(gp); load->computeValueAt(val, tStep, deltaX, mode); - k = static_cast< TransportMaterial * >( this->giveMaterial() )->giveCharacteristicValue(Conductivity, gp, tStep); + double k = static_cast< TransportMaterial * >( this->giveMaterial() )->giveCharacteristicValue(Conductivity, gp, tStep); double helpFactor = val.at(1) * k * dV; @@ -348,7 +300,7 @@ Lattice2d_mt :: computeInternalSourceRhsVectorAt(FloatArray &answer, TimeStep *t gravityHelp.times(helpFactor); if ( helpLoadVector.isEmpty() ) { - helpLoadVector.resize( gravityHelp.giveSize() ); + helpLoadVector.resize(gravityHelp.giveSize() ); } for ( int j = 1; j <= gravityHelp.giveSize(); j++ ) { @@ -420,7 +372,7 @@ void Lattice2d_mt :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) } EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getElementColor() ); + EASValsSetColor(gc.getElementColor() ); EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); @@ -446,7 +398,7 @@ void Lattice2d_mt :: drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tSt } EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); - EASValsSetColor( gc.getCrossSectionColor() ); + EASValsSetColor(gc.getCrossSectionColor() ); EASValsSetLayer(OOFEG_RAW_CROSSSECTION_LAYER); FloatArray coords; @@ -468,19 +420,15 @@ void Lattice2d_mt :: drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tSt void Lattice2d_mt :: giveCrossSectionCoordinates(FloatArray &coords) { - double x1, y1, x2, y2; - x1 = this->giveNode(1)->giveCoordinate(1); - y1 = this->giveNode(1)->giveCoordinate(2); - x2 = this->giveNode(2)->giveCoordinate(1); - y2 = this->giveNode(2)->giveCoordinate(2); + double x1 = this->giveNode(1)->giveCoordinate(1); + double y1 = this->giveNode(1)->giveCoordinate(2); + double x2 = this->giveNode(2)->giveCoordinate(1); + double y2 = this->giveNode(2)->giveCoordinate(2); //Compute normal and shear direction - FloatArray normalDirection; - FloatArray shearDirection; - normalDirection.resize(2); - normalDirection.zero(); - shearDirection.resize(2); - shearDirection.zero(); + FloatArray normalDirection(2); + FloatArray shearDirection(2); + normalDirection.at(1) = x2 - x1; normalDirection.at(2) = y2 - y1; normalDirection.normalize(); @@ -489,8 +437,7 @@ Lattice2d_mt :: giveCrossSectionCoordinates(FloatArray &coords) shearDirection.at(2) = 1.; } else { shearDirection.at(1) = 1.0; - shearDirection.at(2) = - -normalDirection.at(1) / normalDirection.at(2); + shearDirection.at(2) = -normalDirection.at(1) / normalDirection.at(2); } shearDirection.normalize(); @@ -504,9 +451,5 @@ Lattice2d_mt :: giveCrossSectionCoordinates(FloatArray &coords) coords.at(6) = 0.; } - - - - #endif } // end namespace oofem diff --git a/src/tm/Elements/LatticeElements/lattice2d_mt.h b/src/tm/Elements/LatticeElements/lattice2d_mt.h new file mode 100644 index 000000000..10f669463 --- /dev/null +++ b/src/tm/Elements/LatticeElements/lattice2d_mt.h @@ -0,0 +1,147 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef lattice2d_mt_h +#define lattice2d_mt_h + +#include "tm/Elements/LatticeElements/latticetransportelement.h" +#include "spatiallocalizer.h" + +///@name Input fields for Lattice2d_mt +//@{ +#define _IFT_Lattice2d_mt_Name "latticemt2d" +#define _IFT_Lattice2DMT_dim "dim" +#define _IFT_Lattice2DMT_thick "thick" +#define _IFT_Lattice2DMT_width "width" +#define _IFT_Lattice2DMT_gpcoords "gpcoords" +#define _IFT_Lattice2DMT_crackwidth "crackwidth" +#define _IFT_Lattice2DMT_couplingflag "couplingflag" +#define _IFT_Lattice2DMT_couplingnumber "couplingnumber" +//@} + + +namespace oofem { +/** + * This class implements a 2-dimensional lattice mass transport element + */ + +class Lattice2d_mt : public LatticeTransportElement +{ +protected: + double area = -1.; + double length = 0.; + + int couplingFlag = 0; + IntArray couplingNumbers; + FloatArray crackWidths; + FloatArray crackLengths; + + double dimension = 0., width = 0., thickness = 0.; + FloatArray gpCoords; + + double crackWidth = 0.; + +public: + Lattice2d_mt(int, Domain *, ElementMode em = HeatTransferEM); + + /** Computes the contribution to balance equation(s) due to internal sources */ + void computeInternalSourceRhsVectorAt(FloatArray &answer, TimeStep *, ValueModeType mode) override; + double computeVolumeAround(GaussPoint *) override; + + int giveCouplingFlag() override { return this->couplingFlag; } + + void giveCouplingNumbers(IntArray &numbers) override { numbers = this->couplingNumbers; } + + void giveCrackLengths(FloatArray &lengths) override { lengths = this->crackLengths; } + + void giveCrackWidths(FloatArray &widths) override { widths = crackWidths; } + + + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; + + void computeConductivityMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override; + + void computeCapacityMatrix(FloatMatrix &answer, TimeStep *tStep) override; + + const char *giveInputRecordName() const override { return _IFT_Lattice2d_mt_Name; } + const char *giveClassName() const override { return "Lattice2d_mtElement"; } + + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + + double giveWidth() { return width; } + int computeNumberOfDofs() override { return 2; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + void initializeFrom(InputRecord &ir) override; + + void updateInternalState(TimeStep *tStep) override; + +#ifdef __OOFEG + // Graphics output + void drawYourself(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tStep); + void giveCrossSectionCoordinates(FloatArray &coords); +#endif + +protected: + void computeGaussPoints() override; + + void computeBmatrixAt(FloatMatrix &answer, const FloatArray &lcoords) override { this->computeGradientMatrixAt(answer, lcoords); } + void computeGradientMatrixAt(FloatMatrix &answer, const FloatArray &lcoords) override; + void computeNmatrixAt(FloatMatrix &n, const FloatArray &) override; + + double givePressure() override; + + double giveOldPressure() override; + + double giveMass() override; + + /* computes the submatrix of interpolation matrix cooresponding to single unknown. + */ + void computeNSubMatrixAt(FloatMatrix &n, const FloatArray &); + + double giveLength() override; + + double giveArea() override { return width * thickness; } + + void giveGpCoordinates(FloatArray &coords) override; + + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override { return 0; } + + int giveApproxOrder(int unknownIndx) override { return 1; } +}; +} // end namespace oofem +#endif diff --git a/src/tm/Elements/LatticeElements/lattice3d_mt.C b/src/tm/Elements/LatticeElements/lattice3d_mt.C new file mode 100644 index 000000000..523ada527 --- /dev/null +++ b/src/tm/Elements/LatticeElements/lattice3d_mt.C @@ -0,0 +1,813 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "tm/Elements/LatticeElements/lattice3d_mt.h" +#include "tm/Materials/transportmaterial.h" +#include "tm/Materials/LatticeMaterials/latticetransmat.h" +#include "node.h" +#include "material.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "domain.h" +#include "mathfem.h" +#include "engngm.h" +#include "load.h" +#include "classfactory.h" + +#ifdef __OOFEG + #include "oofeggraphiccontext.h" + #include "connectivitytable.h" +#endif + +namespace oofem { +REGISTER_Element(Lattice3d_mt); + +Lattice3d_mt :: Lattice3d_mt(int n, Domain *aDomain, ElementMode em) : + LatticeTransportElement(n, aDomain, em) +{ + this->numberOfDofMans = 2; +} + +double Lattice3d_mt :: giveLength() +{ + if ( this->geometryFlag == 0 ) { + computeGeometryProperties(); + } + + return this->length; +} + +void Lattice3d_mt :: giveCrackLengths(FloatArray &lengths) +{ + if ( this->geometryFlag == 0 ) { + computeGeometryProperties(); + } + + lengths = this->crackLengths; +} + + +double +Lattice3d_mt :: giveArea() +{ + if ( this->geometryFlag == 0 ) { + computeGeometryProperties(); + } + + return this->area; +} + +void +Lattice3d_mt :: computeNmatrixAt(FloatMatrix &answer, const FloatArray &coords) +{ + this->computeNSubMatrixAt(answer, coords); +} + + +void +Lattice3d_mt :: computeNSubMatrixAt(FloatMatrix &answer, const FloatArray &coords) +{ + double ksi = coords.at(1); + double n1 = ( 1. - ksi ) * 0.5; + double n2 = ( 1. + ksi ) * 0.5; + + answer.resize(1, 2); + answer.zero(); + + answer.at(1, 1) = n1; + answer.at(1, 2) = n2; +} + + +void +Lattice3d_mt :: computeGradientMatrixAt(FloatMatrix &answer, const FloatArray &lcoords) +{ + double l = giveLength(); + + answer.resize(1, 2); + answer.zero(); + answer.at(1, 1) = -1.; + answer.at(1, 2) = 1.; + + answer.times(1. / l); +} + + +void +Lattice3d_mt :: updateInternalState(TimeStep *tStep) +{ + FloatArray f, r; + FloatMatrix n; + TransportMaterial *mat = static_cast< TransportMaterial * >( this->giveMaterial() ); + + // force updating ip values + for ( auto &iRule: integrationRulesArray ) { + for ( auto &gp: * iRule ) { + this->computeNmatrixAt(n, gp->giveNaturalCoordinates() ); + this->computeVectorOf({ P_f }, VM_Total, tStep, r); + f.beProductOf(n, r); + mat->updateInternalState(f, gp, tStep); + } + } +} + + +void +Lattice3d_mt :: computeGaussPoints() +{ + integrationRulesArray.resize(1); + integrationRulesArray [ 0 ] = std :: make_unique< GaussIntegrationRule >(1, this, 1, 2); + integrationRulesArray [ 0 ]->SetUpPointsOnLine(1, _3dMTLattice); +} + +void +Lattice3d_mt :: giveDofManDofIDMask(int inode, IntArray &answer) const +{ + answer = { P_f }; +} + +void +Lattice3d_mt :: initializeFrom(InputRecord &ir) +{ + this->Element :: initializeFrom(ir); + + numberOfGaussPoints = 1; + + minLength = 1.e-20; + IR_GIVE_OPTIONAL_FIELD(ir, minLength, _IFT_Lattice3DMT_mlength); + + dimension = 3.; + IR_GIVE_OPTIONAL_FIELD(ir, dimension, _IFT_Lattice3DMT_dim); + + + IR_GIVE_OPTIONAL_FIELD(ir, area, _IFT_Lattice3DMT_area); + + + polygonCoords.resize(0); + IR_GIVE_OPTIONAL_FIELD(ir, polygonCoords, _IFT_Lattice3DMT_polycoords); + numberOfPolygonVertices = polygonCoords.giveSize() / 3.; + + crackWidths.resize(numberOfPolygonVertices); + crackWidths.zero(); + IR_GIVE_OPTIONAL_FIELD(ir, crackWidths, _IFT_Lattice3DMT_crackwidths); + + couplingFlag = 0; + IR_GIVE_OPTIONAL_FIELD(ir, couplingFlag, _IFT_Lattice3DMT_couplingflag); + + couplingNumbers.resize(numberOfPolygonVertices); + if ( couplingFlag == 1 ) { + IR_GIVE_OPTIONAL_FIELD(ir, couplingNumbers, _IFT_Lattice3DMT_couplingnumber); + } + + this->computeGaussPoints(); +} + +void +Lattice3d_mt :: computeFlow(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) +{ + FloatArray r; + IntArray dofid; + double dV; + double length = giveLength(); + double k; + answer.resize(1); + + k = static_cast< TransportMaterial * >( this->giveMaterial() )->giveCharacteristicValue(Conductivity, gp, tStep); + dV = this->computeVolumeAround(gp); + + this->giveElementDofIDMask(dofid); + this->computeVectorOf(dofid, VM_Total, tStep, r); + double flow; + double dP; + + dP = r.at(2) - r.at(1); + flow = k * ( dP ) * dV / pow(length, 2.); + answer.at(1) = fabs(flow); + + if ( !isActivated(tStep) ) { + answer.zero(); + } +} + +double +Lattice3d_mt :: computeVolumeAround(GaussPoint *aGaussPoint) +{ + return this->giveArea() * this->giveLength(); +} + + +void +Lattice3d_mt :: computeGeometryProperties() +{ + //coordinates of the two nodes + Node *nodeA, *nodeB; + FloatArray coordsA(3), coordsB(3); + + nodeA = this->giveNode(1); + nodeB = this->giveNode(2); + + for ( int i = 0; i < 3; i++ ) { + coordsA.at(i + 1) = nodeA->giveCoordinate(i + 1); + coordsB.at(i + 1) = nodeB->giveCoordinate(i + 1); + } + + //Construct an initial temporary local coordinate system + FloatArray s(3), t(3); + + //Calculate normal vector + this->normal.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) = coordsB.at(i + 1) - coordsA.at(i + 1); + } + + // Compute midpoint + this->midPoint.resize(3); + for ( int i = 0; i < 3; i++ ) { + this->midPoint.at(i + 1) = 0.5 * ( coordsB.at(i + 1) + coordsA.at(i + 1) ); + } + + this->length = sqrt(pow(normal.at(1), 2.) + pow(normal.at(2), 2.) + pow(normal.at(3), 2.) ); + + if ( this->length < this->minLength ) { + this->length = this->minLength; + printf("Length could be zero. Might not be possible to create local coordinate system. Need to calculate area differently. Crack lengths need to approximated.\n"); + //This will only work for cross-sections with three points at the moment. + computeSpecialCrossSectionProperties(); + this->geometryFlag = 1; + return; + } + + for ( int i = 0; i < 3; i++ ) { + this->normal.at(i + 1) /= length; + } + + computeCrossSectionProperties(); + + this->geometryFlag = 1; + + return; +} + +void +Lattice3d_mt :: computeSpecialCrossSectionProperties() +{ + if ( this->numberOfPolygonVertices != 3 ) { + return; + } + + //Here, the area of the cross-section is calculated from the global vertex points without the generation of a local coordinate system. + + FloatArray pointOne(3); + FloatArray pointTwo(3); + FloatArray crackPoint(3); + + FloatArray l(3); + this->crackLengths.resize(3); + this->crackLengths.zero(); + + for ( int m = 0; m < numberOfPolygonVertices; m++ ) { + if ( m < numberOfPolygonVertices - 1 ) { + for ( int n = 0; n < 3; n++ ) { + pointOne.at(n + 1) = polygonCoords.at(3 * m + n + 1); + pointTwo.at(n + 1) = polygonCoords.at(3 * ( m + 1 ) + n + 1); + } + } else { + for ( int n = 0; n < 3; n++ ) { + pointOne.at(n + 1) = polygonCoords.at(3 * m + n + 1); + pointTwo.at(n + 1) = polygonCoords.at(n + 1); + } + } + l.at(m + 1) = sqrt(pow(pointOne.at(1) - pointTwo.at(1), 2.) + pow(pointOne.at(2) - pointTwo.at(2), 2.) + pow(pointOne.at(3) - pointTwo.at(3), 2.) ); + } + + double s = ( l.at(1) + l.at(2) + l.at(3) ) / 2.; + this->area = sqrt(s * ( s - l.at(1) ) * ( s - l.at(2) ) * ( s - l.at(3) ) ); + + printf("area = %e, length = %e\n", area, length); + + if ( this->area < pow(this->minLength, 2.) ) { + this->area = pow(this->minLength, 2.); + printf("small area fixed in special calculation\n"); + } + + //Approximate crack lengths assuming + //an equilateral triangle of the same area as real triangle has. + for ( int m = 0; m < numberOfPolygonVertices; m++ ) { + this->crackLengths.at(m + 1) = pow(3, 0.25) * sqrt(this->area); + } + + return; +} + + + +// void +// Lattice3d_mt :: computeHomogenisedInternalForcesVectorAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode, FloatArray &unknowns) +// { +// IntArray dofids; +// FloatArray tmp; + +// FloatMatrix s; +// this->giveElementDofIDMask(dofids); + +// ///@todo Integrate and compute as a nonlinear problem instead of doing this tangent. +// this->computeConductivityMatrix(s, Conductivity, tStep); +// answer.beProductOf(s, unknowns); + +// this->computeInternalSourceRhsVectorAt(tmp, tStep, mode); +// answer.subtract(tmp); + +// FloatMatrix bc_tangent; +// this->computeBCMtrxAt(bc_tangent, tStep, VM_Total); +// if ( bc_tangent.isNotEmpty() ) { +// tmp.beProductOf(bc_tangent, unknowns); +// answer.add(tmp); +// } +// } + + +void +Lattice3d_mt :: computeCrossSectionProperties() { + if ( this->numberOfPolygonVertices < 3 ) { + return; + } + + //Construct two perpendicular axis so that n is normal to the plane which they create + //Check, if one of the components of the normal-direction is zero + FloatArray s(3), t(3); + if ( this->normal.at(1) == 0 ) { + s.at(1) = 0.; + s.at(2) = this->normal.at(3); + s.at(3) = -this->normal.at(2); + } else if ( this->normal.at(2) == 0 ) { + s.at(1) = this->normal.at(3); + s.at(2) = 0.; + s.at(3) = -this->normal.at(1); + } else { + s.at(1) = this->normal.at(2); + s.at(2) = -this->normal.at(1); + s.at(3) = 0.; + } + + s.normalize(); + + t.beVectorProductOf(this->normal, s); + t.normalize(); + + //Set up rotation matrix + FloatMatrix lcs(3, 3); + + for ( int i = 1; i <= 3; i++ ) { + lcs.at(1, i) = this->normal.at(i); + lcs.at(2, i) = s.at(i); + lcs.at(3, i) = t.at(i); + } + + + //Calculate the local coordinates of the polygon vertices + FloatArray help(3), test(3); + FloatArray lpc(3 * numberOfPolygonVertices); + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + for ( int n = 0; n < 3; n++ ) { + help(n) = polygonCoords(3 * k + n); + } + + test.beProductOf(lcs, help); + for ( int n = 0; n < 3; n++ ) { + lpc(3 * k + n) = test(n); + } + } + + this->area = 0.; + + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + if ( k < numberOfPolygonVertices - 1 ) { + this->area += lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2); + } else { //Back to zero for n+1 + this->area += lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2); + } + } + + this->area *= 0.5; + + FloatArray tempCoords(3 * numberOfPolygonVertices); + if ( this->area < 0 ) { //Set area to a positive value and rearrange the coordinate entries + this->area *= -1.; + + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + for ( int m = 0; m < 3; m++ ) { + tempCoords.at(3 * k + m + 1) = polygonCoords.at(3 * ( numberOfPolygonVertices - k - 1 ) + m + 1); + } + } + + polygonCoords = tempCoords; + + // Calculate again local co-ordinate system for different order + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + for ( int n = 0; n < 3; n++ ) { + help(n) = polygonCoords(3 * k + n); + } + + test.beProductOf(lcs, help); + for ( int n = 0; n < 3; n++ ) { + lpc(3 * k + n) = test(n); + } + } + } + + if ( this->area < pow(minLength, 2.) ) { + this->area = pow(minLength, 2.); + printf("Small area fixed.\n"); + } + + //Calculate centroids + centroid.resize(3); + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + if ( k < numberOfPolygonVertices - 1 ) { + centroid.at(2) += ( lpc(3 * k + 1) + lpc(3 * ( k + 1 ) + 1) ) * ( lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2) ); + centroid.at(3) += ( lpc(3 * k + 2) + lpc(3 * ( k + 1 ) + 2) ) * ( lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2) ); + } else { //Back to zero for n+1 + centroid.at(2) += ( lpc(3 * k + 1) + lpc(1) ) * ( lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2) ); + centroid.at(3) += ( lpc(3 * k + 2) + lpc(2) ) * ( lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2) ); + } + } + + centroid.times(1. / ( 6. * this->area ) ); + + centroid.at(1) = lpc.at(1); //The first component of all lpcs should be the same + + //Shift coordinates to centroi + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + for ( int l = 0; l < 3; l++ ) { + lpc(3 * k + l) -= centroid(l); + } + } + + //Compute second moments of area. + + //This is for the temporary coordinate system + double Ixx = 0.; + double Iyy = 0.; + double Ixy = 0.; + double a; + + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + if ( k < numberOfPolygonVertices - 1 ) { + a = lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2); + + Ixx += ( ( pow(lpc(3 * k + 2), 2.) + lpc(3 * k + 2) * lpc(3 * ( k + 1 ) + 2) + pow(lpc(3 * ( k + 1 ) + 2), 2.) ) * a ) / 12.; + + Iyy += ( ( pow(lpc(3 * k + 1), 2.) + lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 1) + pow(lpc(3 * ( k + 1 ) + 1), 2.) ) * a ) / 12.; + + Ixy += ( ( lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) + 2. * lpc(3 * k + 1) * lpc(3 * k + 2) + + 2 * lpc(3 * ( k + 1 ) + 1) * lpc(3 * ( k + 1 ) + 2) + lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2) ) * a ) / 24.; + } else { //Back to zero for n+1 + a = lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2); + + Ixx += ( ( pow(lpc(3 * k + 2), 2.) + lpc(3 * k + 2) * lpc(2) + pow(lpc(2), 2.) ) * a ) / 12.; + + Iyy += ( ( pow(lpc(3 * k + 1), 2.) + lpc(3 * k + 1) * lpc(1) + pow(lpc(1), 2.) ) * a ) / 12.; + + Ixy += ( ( lpc(3 * k + 1) * lpc(2) + 2. * lpc(3 * k + 1) * lpc(3 * k + 2) + + 2 * lpc(1) * lpc(2) + lpc(1) * lpc(3 * k + 2) ) * a ) / 24.; + } + } + + //Compute main axis of the cross-section + double angleChange = 0.; + double sum = fabs(Ixx + Iyy); + double pi = 3.14159265; + if ( ( fabs(Ixx - Iyy) / sum > 1.e-6 ) && fabs(Ixy) / sum > 1.e-6 ) { + angleChange = 0.5 * atan(-2 * Ixy / ( Ixx - Iyy ) ); + } else if ( ( fabs(Ixx - Iyy) / sum < 1.e-6 ) && fabs(Ixy) / sum > 1.e-6 ) { + angleChange = pi / 4.; + } + + if ( Iyy > Ixx ) { + angleChange = angleChange + pi / 2.; + } + + //Moment of inertias saved in the element + + this->I1 = ( Ixx + Iyy ) / 2. + sqrt(pow( ( Ixx - Iyy ) / 2., 2. ) + pow(Ixy, 2.) ); + this->I2 = ( Ixx + Iyy ) / 2. - sqrt(pow( ( Ixx - Iyy ) / 2., 2. ) + pow(Ixy, 2.) ); + + this->Ip = I1 + I2; + + //Rotation around normal axis by angleChange + + FloatMatrix rotationChange(3, 3); + rotationChange.zero(); + + rotationChange.at(1, 1) = 1.; + rotationChange.at(2, 2) = cos(angleChange); + rotationChange.at(2, 3) = -sin(angleChange); + + rotationChange.at(3, 2) = sin(angleChange); + rotationChange.at(3, 3) = cos(angleChange); + + this->localCoordinateSystem.beProductOf(rotationChange, lcs); + + //Calculate the polygon vertices in the new coordinate system + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + for ( int n = 0; n < 3; n++ ) { + help(n) = polygonCoords(3 * k + n); + } + + test.beProductOf(this->localCoordinateSystem, help); + for ( int n = 0; n < 3; n++ ) { + lpc(3 * k + n) = test(n); + } + } + + //Calculate centroid again in local coordinate system + centroid.zero(); + for ( int k = 0; k < numberOfPolygonVertices; k++ ) { + if ( k < numberOfPolygonVertices - 1 ) { + centroid.at(2) += ( lpc(3 * k + 1) + lpc(3 * ( k + 1 ) + 1) ) * ( lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2) ); + centroid.at(3) += ( lpc(3 * k + 2) + lpc(3 * ( k + 1 ) + 2) ) * ( lpc(3 * k + 1) * lpc(3 * ( k + 1 ) + 2) - lpc(3 * ( k + 1 ) + 1) * lpc(3 * k + 2) ); + } else { //Back to zero for n+1 + centroid.at(2) += ( lpc(3 * k + 1) + lpc(1) ) * ( lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2) ); + centroid.at(3) += ( lpc(3 * k + 2) + lpc(2) ) * ( lpc(3 * k + 1) * lpc(2) - lpc(1) * lpc(3 * k + 2) ); + } + } + + centroid.times(1. / ( 6. * area ) ); + + centroid.at(1) = lpc.at(1); //The first component of all lpcs should be the same + + /*Express midpoint in local coordinate system. + * Note that this point does not have to lie in the same plane as the cross-section. + * However, we do not use the first componnent of the coordinate */ + FloatArray midPointLocal(3); + midPointLocal.beProductOf(this->localCoordinateSystem, midPoint); + + //eccentricities stored in the element + this->eccS = centroid.at(2) - midPointLocal.at(2); + this->eccT = centroid.at(3) - midPointLocal.at(3); + + FloatMatrix transposeLCS; + transposeLCS.beTranspositionOf(this->localCoordinateSystem); + + globalCentroid.beProductOf(transposeLCS, centroid); + + crackLengths.resize(numberOfPolygonVertices); + double crackPointOne, crackPointTwo; + for ( int m = 0; m < numberOfPolygonVertices; m++ ) { + if ( m < numberOfPolygonVertices - 1 ) { + crackPointOne = ( lpc(3 * ( m + 1 ) + 1) + lpc(3 * ( m ) + 1) ) / 2.; + crackPointTwo = ( lpc(3 * ( m + 1 ) + 2) + lpc(3 * ( m ) + 2) ) / 2.; + } else { + crackPointOne = ( lpc(1) + lpc(3 * ( m ) + 1) ) / 2.; + crackPointTwo = ( lpc(2) + lpc(3 * ( m ) + 2) ) / 2.; + } + + crackLengths.at(m + 1) = sqrt(pow(crackPointOne - midPointLocal.at(2), 2.) + pow(crackPointTwo - midPointLocal.at(3), 2.) ); + } + + return; +} + +void +Lattice3d_mt :: computeConductivityMatrix(FloatMatrix &answer, MatResponseMode rmode, TimeStep *tStep) +{ + GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + + answer.resize(2, 2); + answer.zero(); + answer.at(1, 1) = 1.; + answer.at(1, 2) = -1.; + answer.at(2, 1) = -1; + answer.at(2, 2) = 1.; + + double length = giveLength(); + double k = static_cast< TransportMaterial * >( this->giveMaterial() )->giveCharacteristicValue(Conductivity, gp, tStep); + double dV = this->computeVolumeAround(gp); + double temp = k * dV / pow(length, 2.); + answer.times(temp); + + return; +} + + +void +Lattice3d_mt :: computeCapacityMatrix(FloatMatrix &answer, TimeStep *tStep) +{ + GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + answer.resize(2, 2); + answer.zero(); + answer.at(1, 1) = 2.; + answer.at(1, 2) = 1.; + answer.at(2, 1) = 1.; + answer.at(2, 2) = 2.; + double c = static_cast< TransportMaterial * >( this->giveMaterial() )->giveCharacteristicValue(Capacity, gp, tStep); + double dV = this->computeVolumeAround(gp) / ( 6.0 * this->dimension ); + answer.times(c * dV); +} + + + +void +Lattice3d_mt :: computeInternalSourceRhsVectorAt(FloatArray &answer, TimeStep *atTime, ValueModeType mode) +{ + int i, j, n, nLoads; + double dV; + bcGeomType ltype; + Load *load; + GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + + FloatArray deltaX(3), normalVector(3); + FloatArray val, helpLoadVector, globalIPcoords; + FloatMatrix nm; + answer.resize(0); + + FloatArray gravityHelp(2); + + nLoads = this->giveBodyLoadArray()->giveSize(); + for ( i = 1; i <= nLoads; i++ ) { + n = bodyLoadArray.at(i); + load = ( Load * ) domain->giveLoad(n); + ltype = load->giveBCGeoType(); + + if ( ltype == GravityPressureBGT ) { + //Compute change of coordinates + + if ( this->geometryFlag == 0 ) { + computeGeometryProperties(); + } + + deltaX.at(1) = this->normal.at(1) * this->length; + deltaX.at(2) = this->normal.at(2) * this->length; + deltaX.at(3) = this->normal.at(3) * this->length; + + gravityHelp.at(1) = 1.; + gravityHelp.at(2) = -1.; + + dV = this->computeVolumeAround(gp); + load->computeValueAt(val, atTime, deltaX, mode); + + double k = static_cast< TransportMaterial * >( this->giveMaterial() )->giveCharacteristicValue(Conductivity, gp, atTime); + + double helpFactor = val.at(1) * k * dV; + + helpFactor /= pow(this->giveLength(), 2.); + gravityHelp.times(helpFactor); + + if ( helpLoadVector.isEmpty() ) { + helpLoadVector.resize(gravityHelp.giveSize() ); + } + + for ( j = 1; j <= gravityHelp.giveSize(); j++ ) { + helpLoadVector.at(j) += gravityHelp.at(j); + } + } + + + + answer.add(helpLoadVector); + } + + return; +} + +int +Lattice3d_mt :: computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) +{ + if ( geometryFlag == 0 ) { + computeGeometryProperties(); + } + + answer.resize(3); + answer = midPoint; + + return 1; +} + +bool +Lattice3d_mt :: computeLocalCoordinates(FloatArray &answer, const FloatArray &coords) +{ + answer.resize(1); + answer.at(1) = 0.; + + return 1; +} + + +#ifdef __OOFEG + +void +Lattice3d_mt :: drawYourself(oofegGraphicContext &gc, TimeStep *tStep) +{ + OGC_PlotModeType mode = gc.giveIntVarPlotMode(); + + if ( mode == OGC_rawGeometry ) { + this->drawRawGeometry(gc, tStep); + this->drawRawCrossSections(gc, tStep); + } else { + OOFEM_ERROR("drawYourself : unsupported mode"); + } +} + + +void Lattice3d_mt :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + WCRec p [ 2 ]; /* points */ + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getElementColor() ); + EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER); + + p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1); + p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2); + p [ 0 ].z = ( FPNum ) this->giveNode(1)->giveCoordinate(3); + p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1); + p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2); + p [ 1 ].z = ( FPNum ) this->giveNode(2)->giveCoordinate(3); + + go = CreateLine3D(p); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); +} + + +void Lattice3d_mt :: drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tStep) +{ + GraphicObj *go; + + // if (!go) { // create new one + //Create as many points as we have polygon vertices + WCRec p [ numberOfPolygonVertices ]; /* poin */ + + if ( !gc.testElementGraphicActivity(this) ) { + return; + } + + EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH); + EASValsSetColor(gc.getElementColor() ); + EASValsSetLayer(OOFEG_RAW_CROSSSECTION_LAYER); + + for ( int i = 0; i < numberOfPolygonVertices; i++ ) { + p [ i ].x = ( FPNum ) polygonCoords(3 * i); + p [ i ].y = ( FPNum ) polygonCoords(3 * i + 1); + p [ i ].z = ( FPNum ) polygonCoords(3 * i + 2); + } + + WCRec pTemp [ 2 ]; /* points */ + for ( int i = 0; i < numberOfPolygonVertices; i++ ) { + if ( i < numberOfPolygonVertices - 1 ) { + pTemp [ 0 ] = p [ i ]; + pTemp [ 1 ] = p [ i + 1 ]; + } else { + pTemp [ 0 ] = p [ i ]; + pTemp [ 1 ] = p [ 0 ]; + } + + go = CreateLine3D(pTemp); + EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | LAYER_MASK, go); + EGAttachObject(go, ( EObjectP ) this); + EMAddGraphicsToModel(ESIModel(), go); + } +} +#endif +} // end namespace oofem diff --git a/src/tm/Elements/LatticeElements/lattice3d_mt.h b/src/tm/Elements/LatticeElements/lattice3d_mt.h new file mode 100644 index 000000000..1622a76d2 --- /dev/null +++ b/src/tm/Elements/LatticeElements/lattice3d_mt.h @@ -0,0 +1,150 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2019 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef lattice3d_mt_h +#define lattice3d_mt_h + +#include "tm/Elements/LatticeElements/latticetransportelement.h" +#include "spatiallocalizer.h" + +///@name Input fields for Lattice3d_mt +//@{ +#define _IFT_Lattice3d_mt_Name "latticemt3d" +#define _IFT_Lattice3DMT_polycoords "polycoords" +#define _IFT_Lattice3DMT_crackwidths "crackwidths" +#define _IFT_Lattice3DMT_couplingflag "couplingflag" +#define _IFT_Lattice3DMT_couplingnumber "couplingnumber" +#define _IFT_Lattice3DMT_dim "dim" +#define _IFT_Lattice3DMT_area "area" +#define _IFT_Lattice3DMT_ranarea "ranarea" +#define _IFT_Lattice3DMT_mlength "mlength" +//@} + + +namespace oofem { +/** + * This class implements a 3-dimensional lattice mass transport element + */ + +class Lattice3d_mt : public LatticeTransportElement +{ +protected: + + double minLength = 0.; + double length = 0.; + double I1 = 0., I2 = 0., Ip = 0.; + FloatArray polygonCoords; + int numberOfPolygonVertices; + FloatMatrix localCoordinateSystem; + double eccS = 0., eccT = 0., area = 0.; + FloatArray midPoint, centroid, globalCentroid; + int geometryFlag = 0; + FloatArray normal; + + int couplingFlag = 0; + IntArray couplingNumbers; + FloatArray crackWidths; + FloatArray crackLengths; + + double dimension = 0.; + +public: + Lattice3d_mt(int, Domain *, ElementMode em = HeatTransferEM); + + void computeInternalSourceRhsVectorAt(FloatArray &answer, TimeStep *, ValueModeType mode) override; + double computeVolumeAround(GaussPoint *) override; + + int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords) override; + + bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords) override; + + void computeConductivityMatrix(FloatMatrix &answer, MatResponseMode rmode, TimeStep *tStep) override; + + void computeGeometryProperties(); + + void computeCrossSectionProperties(); + + void computeSpecialCrossSectionProperties(); + + void computeCapacityMatrix(FloatMatrix &answer, TimeStep *tStep) override; + + const char *giveInputRecordName() const override { return _IFT_Lattice3d_mt_Name; } + const char *giveClassName() const override { return "Lattice3d_mt"; } + + Element_Geometry_Type giveGeometryType() const override { return EGT_line_1; } + + int computeNumberOfDofs() override { return 2; } + void giveDofManDofIDMask(int inode, IntArray &) const override; + void initializeFrom(InputRecord &ir) override; + void updateInternalState(TimeStep *tStep) override; + + double giveLength() override; + double giveArea() override; + int giveCouplingFlag() override { return this->couplingFlag; } + void giveCouplingNumbers(IntArray &numbers) override { numbers = this->couplingNumbers; } + void giveCrackWidths(FloatArray &widths) override { widths = crackWidths; } + void giveCrackLengths(FloatArray &lengths) override; + + void giveCrossSectionCoordinates(FloatArray &coords) override { coords = polygonCoords; } + int giveNumberOfCrossSectionNodes() override { return numberOfPolygonVertices; } + + void computeFlow(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override; + +#ifdef __OOFEG + + void drawYourself(oofegGraphicContext &gc, TimeStep *tStep) override; + + void drawRawGeometry(oofegGraphicContext &, TimeStep *tStep) override; + + void drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tStep) ; + +#endif + +protected: + void computeGaussPoints() override; + + void computeGradientMatrixAt(FloatMatrix &answer, const FloatArray &lcoords) override; + + void computeBmatrixAt(FloatMatrix &answer, const FloatArray &lcoords) override { this->computeGradientMatrixAt(answer, lcoords); } + + void computeNmatrixAt(FloatMatrix &n, const FloatArray &) override; + + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override { return 0; } + + void computeNSubMatrixAt(FloatMatrix &n, const FloatArray &); + + int giveApproxOrder(int unknownIndx) override { return 1; } +}; +} // end namespace oofem +#endif diff --git a/src/tm/latticetransportelement.C b/src/tm/Elements/LatticeElements/latticetransportelement.C similarity index 88% rename from src/tm/latticetransportelement.C rename to src/tm/Elements/LatticeElements/latticetransportelement.C index 1e20c846a..a4bbd1002 100644 --- a/src/tm/latticetransportelement.C +++ b/src/tm/Elements/LatticeElements/latticetransportelement.C @@ -33,22 +33,16 @@ */ #include "latticetransportelement.h" -#include "transportmaterial.h" +#include "tm/Materials/transportmaterial.h" namespace oofem { LatticeTransportElement :: LatticeTransportElement(int n, Domain *aDomain, ElementMode em) : TransportElement(n, aDomain, em) { } -LatticeTransportElement :: ~LatticeTransportElement() -{ } - -IRResultType -LatticeTransportElement :: initializeFrom(InputRecord *ir) +void +LatticeTransportElement :: initializeFrom(InputRecord &ir) { - return TransportElement :: initializeFrom(ir); + TransportElement :: initializeFrom(ir); } - - - } // end namespace oofem diff --git a/src/tm/latticetransportelement.h b/src/tm/Elements/LatticeElements/latticetransportelement.h similarity index 77% rename from src/tm/latticetransportelement.h rename to src/tm/Elements/LatticeElements/latticetransportelement.h index f96cc7b7f..f20c03683 100644 --- a/src/tm/latticetransportelement.h +++ b/src/tm/Elements/LatticeElements/latticetransportelement.h @@ -36,7 +36,7 @@ #ifndef latticetransportelement_h #define latticetransportelement_h -#include "transportelement.h" +#include "tm/Elements/transportelement.h" /** * This class implements the base of a special transport lattice element following @@ -49,11 +49,9 @@ namespace oofem { class LatticeTransportElement : public TransportElement { public: - LatticeTransportElement(int, Domain *, ElementMode); // constructor + LatticeTransportElement(int, Domain *, ElementMode); - ~LatticeTransportElement(); // destructor - - IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; /** * Returns the cross-sectional area of the lattice element. @@ -65,7 +63,7 @@ class LatticeTransportElement : public TransportElement * Returns the radius of the lattice element. * @return radius. */ - virtual double giveRadius(){return 0;} + virtual double giveRadius() { return 0; } /** * Returns the element length @@ -90,43 +88,50 @@ class LatticeTransportElement : public TransportElement * @return mass. */ virtual double giveMass() { return 0; } - + /** * Returns the coupling flag * @return couplingFlag. */ - virtual int giveCouplingFlag(){return 0;} + virtual int giveCouplingFlag() { return 0; } /** * Returns the coupling numbers * @return couplingNumbers. */ - virtual void giveCouplingNumbers(IntArray &numbers){return;} + virtual void giveCouplingNumbers(IntArray &numbers) { } /** * Returns the crack lengths * @return crackLengths. */ - virtual void giveCrackLengths(FloatArray &lengths){return;} + virtual void giveCrackLengths(FloatArray &lengths) { } /** * Returns the crack widths * @return crackWidths. */ - virtual void giveCrackWidths(FloatArray &widths) {return;} - + virtual void giveCrackWidths(FloatArray &widths) { } /** * Gives the GP coordinates */ - virtual void giveGpCoordinates(FloatArray &coords) { return; } + virtual void giveGpCoordinates(FloatArray &coords) { } /** * Returns the real volume */ - virtual double computeLatticeVolumeAroundIt() {return 0;} - + virtual double computeLatticeVolumeAroundIt() { return 0; } + /** + * Returns the number of crossSection nodes + * @return Number of crosssection nodes. + */ + virtual int giveNumberOfCrossSectionNodes() { return 0; } + /** + * This function gives the cross-section coordinates. + */ + virtual void giveCrossSectionCoordinates(FloatArray &coords) {; } }; } // end namespace oofem #endif diff --git a/src/tm/brick1_ht.C b/src/tm/Elements/brick1_ht.C similarity index 86% rename from src/tm/brick1_ht.C rename to src/tm/Elements/brick1_ht.C index 49fec64a0..887fde3bd 100644 --- a/src/tm/brick1_ht.C +++ b/src/tm/Elements/brick1_ht.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "brick1_ht.h" +#include "tm/Elements/brick1_ht.h" #include "fei3dhexalin.h" #include "node.h" #include "gausspoint.h" @@ -74,9 +74,6 @@ Brick1_mt :: Brick1_mt(int n, Domain *aDomain) : Brick1_ht(n, aDomain) emode = Mass1TransferEM; } -Brick1_ht :: ~Brick1_ht() -{ } - FEInterpolation * Brick1_ht :: giveInterpolation() const { return & interpolation; } @@ -85,31 +82,27 @@ Brick1_ht :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } -IRResultType -Brick1_ht :: initializeFrom(InputRecord *ir) +void +Brick1_ht :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 8; - return TransportElement :: initializeFrom(ir); + TransportElement :: initializeFrom(ir); } double Brick1_ht :: computeVolumeAround(GaussPoint *gp) -// Returns the portion of the receiver which is attached to gp. { - double determinant, weight, volume; - determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), + double determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); - volume = determinant * weight; - return volume; + return determinant * gp->giveWeight(); } @@ -122,24 +115,11 @@ Brick1_ht :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) } -IntegrationRule * -Brick1_ht :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Square, approxOrder); - iRule->SetUpPointsOnSquare(npoints, _Unknown); - return iRule; -} - - double Brick1_ht :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { - double determinant, weight, volume; - determinant = fabs( interpolation.surfaceGiveTransformationJacobian( iSurf, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); - volume = determinant * weight; - return volume; + double determinant = fabs( interpolation.surfaceGiveTransformationJacobian( iSurf, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + return determinant * gp->giveWeight(); } @@ -156,7 +136,7 @@ Brick1_ht :: giveInterface(InterfaceType interface) return static_cast< SPRNodalRecoveryModelInterface * >(this); } - return NULL; + return nullptr; } void diff --git a/src/tm/brick1_ht.h b/src/tm/Elements/brick1_ht.h similarity index 56% rename from src/tm/brick1_ht.h rename to src/tm/Elements/brick1_ht.h index a7e9e2ebb..a757141e7 100644 --- a/src/tm/brick1_ht.h +++ b/src/tm/Elements/brick1_ht.h @@ -35,7 +35,7 @@ #ifndef brick1_ht_h #define brick1_ht_h -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "spatiallocalizer.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -58,42 +58,39 @@ class Brick1_ht : public TransportElement, public SpatialLocalizerInterface, pub public: Brick1_ht(int n, Domain * d); - virtual ~Brick1_ht(); - virtual double computeVolumeAround(GaussPoint *gp); - virtual FEInterpolation *giveInterpolation() const; + double computeVolumeAround(GaussPoint *gp) override; + FEInterpolation *giveInterpolation() const override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Brick1_ht_Name; } - virtual const char *giveClassName() const { return "Brick1_ht"; } + const char *giveInputRecordName() const override { return _IFT_Brick1_ht_Name; } + const char *giveClassName() const override { return "Brick1_ht"; } - virtual int computeNumberOfDofs() { return 8; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode() { return _3dHeat; } + int computeNumberOfDofs() override { return 8; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _3dHeat; } - virtual Interface *giveInterface(InterfaceType t); - virtual int testElementExtension(ElementExtension ext) + Interface *giveInterface(InterfaceType t) override; + int testElementExtension(ElementExtension ext) override { return ( ext == Element_EdgeLoadSupport ) || ( ext == Element_SurfaceLoadSupport ); } - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); - + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; #ifdef __OOFEG // Graphics output - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - //virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) {} - //virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) {} + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + //void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override {} + //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override {} #endif protected: - virtual void computeGaussPoints(); - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual IntegrationRule *GetSurfaceIntegrationRule(int approxOrder); - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iEdge); + void computeGaussPoints() override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + double computeSurfaceVolumeAround(GaussPoint *gp, int iEdge) override; }; /** @@ -104,10 +101,10 @@ class Brick1_hmt : public Brick1_ht public: Brick1_hmt(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_Brick1_hmt_Name; } - virtual const char *giveClassName() const { return "Brick1_hmt"; } - virtual int computeNumberOfDofs() { return 16; } - virtual MaterialMode giveMaterialMode() { return _3dHeMo; } + const char *giveInputRecordName() const override { return _IFT_Brick1_hmt_Name; } + const char *giveClassName() const override { return "Brick1_hmt"; } + int computeNumberOfDofs() override { return 16; } + MaterialMode giveMaterialMode() override { return _3dHeMo; } }; /** @@ -118,10 +115,10 @@ class Brick1_mt : public Brick1_ht public: Brick1_mt(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_Brick1_mt_Name; } - virtual const char *giveClassName() const { return "Brick1_mt"; } - virtual int computeNumberOfDofs() { return 8; } - virtual MaterialMode giveMaterialMode() { return _3dHeat; } + const char *giveInputRecordName() const override { return _IFT_Brick1_mt_Name; } + const char *giveClassName() const override { return "Brick1_mt"; } + int computeNumberOfDofs() override { return 8; } + MaterialMode giveMaterialMode() override { return _3dHeat; } }; } // end namespace oofem #endif // brick1_ht_h diff --git a/src/tm/Elements/line1_ht.C b/src/tm/Elements/line1_ht.C new file mode 100644 index 000000000..81b14472d --- /dev/null +++ b/src/tm/Elements/line1_ht.C @@ -0,0 +1,117 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "tm/Elements/line1_ht.h" +#include "fei3dlinelin.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_Element(Line1_ht); +REGISTER_Element(Line1_hmt); +REGISTER_Element(Line1_mt); + +FEI3dLineLin Line1_ht :: interp; + +Line1_ht :: Line1_ht(int n, Domain *aDomain) : + TransportElement(n, aDomain, HeatTransferEM), SpatialLocalizerInterface(this), ZZNodalRecoveryModelInterface(this) +{ + numberOfDofMans = 2; + numberOfGaussPoints = 1; +} + +Line1_hmt :: Line1_hmt(int n, Domain *aDomain) : Line1_ht(n, aDomain) +{ + emode = HeatMass1TransferEM; +} + +Line1_mt :: Line1_mt(int n, Domain *aDomain) : Line1_ht(n, aDomain) +{ + emode = Mass1TransferEM; +} + + +FEInterpolation * +Line1_ht :: giveInterpolation() const { return & this->interp; } + +void +Line1_ht :: computeGaussPoints() +{ + if ( integrationRulesArray.size() == 0 ) { + integrationRulesArray.resize( 1 ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 1); + this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); + } +} + + +void +Line1_ht :: initializeFrom(InputRecord &ir) +{ + numberOfGaussPoints = 1; + TransportElement :: initializeFrom(ir); +} + + +double +Line1_ht :: computeVolumeAround(GaussPoint *gp) +{ + double determinant = fabs( this->interp.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double weight = gp->giveWeight(); + return determinant * weight * this->giveCrossSection()->give(CS_Area, gp); +} + + +Interface * +Line1_ht :: giveInterface(InterfaceType interface) +{ + if ( interface == SpatialLocalizerInterfaceType ) { + return static_cast< SpatialLocalizerInterface * >(this); + } else if ( interface == EIPrimaryFieldInterfaceType ) { + return static_cast< EIPrimaryFieldInterface * >(this); + } else if ( interface == ZZNodalRecoveryModelInterfaceType ) { + return static_cast< ZZNodalRecoveryModelInterface * >(this); + } + + return nullptr; +} + +} // end namespace oofem diff --git a/src/tm/Elements/line1_ht.h b/src/tm/Elements/line1_ht.h new file mode 100644 index 000000000..2e9e31c3d --- /dev/null +++ b/src/tm/Elements/line1_ht.h @@ -0,0 +1,111 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef line1_ht_h +#define line1_ht_h + +#include "tm/Elements/transportelement.h" +#include "spatiallocalizer.h" +#include "zznodalrecoverymodel.h" + +#define _IFT_Line1_hmt_Name "line1hmt" +#define _IFT_Line1_ht_Name "line1ht" +#define _IFT_Line1_mt_Name "line1mt" + +namespace oofem { +class FEI3dLineLin; + +/** + * Two node element for heat or moisture transport with linear interpolation. + */ +class Line1_ht : public TransportElement, public SpatialLocalizerInterface, public ZZNodalRecoveryModelInterface +{ +protected: + static FEI3dLineLin interp; + +public: + Line1_ht(int n, Domain * d); + + double computeVolumeAround(GaussPoint *gp) override; + + // definition + const char *giveInputRecordName() const override { return _IFT_Line1_ht_Name; } + const char *giveClassName() const override { return "Line1_htElement"; } + + int computeNumberOfDofs() override { return ( emode == HeatMass1TransferEM ) ? 4 : 2; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _3dHeat; } + + Interface *giveInterface(InterfaceType t) override; + + FEInterpolation *giveInterpolation() const override; + +#ifdef __OOFEG + // Graphics output + //void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override {} + //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override {} +#endif + +protected: + void computeGaussPoints() override; +}; + +/** + * Class for mass transfer. + */ +class Line1_mt : public Line1_ht +{ +public: + Line1_mt(int n, Domain * d); + + const char *giveInputRecordName() const override { return _IFT_Line1_mt_Name; } + const char *giveClassName() const override { return "Line1_mt"; } + MaterialMode giveMaterialMode() override { return _3dHeat; } +}; + + +/** + * Class for heat and mass transfer. + */ +class Line1_hmt : public Line1_ht +{ +public: + Line1_hmt(int n, Domain * d); + + const char *giveInputRecordName() const override { return _IFT_Line1_hmt_Name; } + const char *giveClassName() const override { return "Line1_hmt"; } + MaterialMode giveMaterialMode() override { return _3dHeMo; } +}; +} // end namespace oofem +#endif // line1_ht_h diff --git a/src/tm/qbrick1_ht.C b/src/tm/Elements/qbrick1_ht.C similarity index 79% rename from src/tm/qbrick1_ht.C rename to src/tm/Elements/qbrick1_ht.C index 9581eba48..a2f066d3f 100644 --- a/src/tm/qbrick1_ht.C +++ b/src/tm/Elements/qbrick1_ht.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "qbrick1_ht.h" +#include "tm/Elements/qbrick1_ht.h" #include "fei3dhexaquad.h" #include "node.h" #include "gausspoint.h" @@ -49,6 +49,7 @@ namespace oofem { REGISTER_Element(QBrick1_ht); REGISTER_Element(QBrick1_hmt); +REGISTER_Element(QBrick1_mt); FEI3dHexaQuad QBrick1_ht :: interpolation; @@ -63,8 +64,10 @@ QBrick1_hmt :: QBrick1_hmt(int n, Domain *aDomain) : QBrick1_ht(n, aDomain) emode = HeatMass1TransferEM; } -QBrick1_ht :: ~QBrick1_ht() -{ } +QBrick1_mt :: QBrick1_mt(int n, Domain *aDomain) : QBrick1_ht(n, aDomain) +{ + emode = Mass1TransferEM; +} FEInterpolation * @@ -73,35 +76,30 @@ QBrick1_ht :: giveInterpolation() const { return & interpolation; } void QBrick1_ht :: computeGaussPoints() -// Sets up the array containing the four Gauss points of the receiver. { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } -IRResultType -QBrick1_ht :: initializeFrom(InputRecord *ir) +void +QBrick1_ht :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 27; - return TransportElement :: initializeFrom(ir); + TransportElement :: initializeFrom(ir); } double QBrick1_ht :: computeVolumeAround(GaussPoint *gp) -// Returns the portion of the receiver which is attached to gp. { - double determinant, weight, volume; - determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), + double determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); - volume = determinant * weight; - return volume; + return determinant * gp->giveWeight(); } @@ -114,24 +112,11 @@ QBrick1_ht :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) } -IntegrationRule * -QBrick1_ht :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Square, approxOrder); - iRule->SetUpPointsOnSquare(npoints, _Unknown); - return iRule; -} - - double QBrick1_ht :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { - double determinant, weight, volume; - determinant = fabs( interpolation.surfaceGiveTransformationJacobian( iSurf, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); - volume = determinant * weight; - return volume; + double determinant = fabs( interpolation.surfaceGiveTransformationJacobian( iSurf, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + return determinant * gp->giveWeight(); } @@ -148,7 +133,7 @@ QBrick1_ht :: giveInterface(InterfaceType interface) return static_cast< SPRNodalRecoveryModelInterface * >(this); } - return NULL; + return nullptr; } void diff --git a/src/tm/qbrick1_ht.h b/src/tm/Elements/qbrick1_ht.h similarity index 56% rename from src/tm/qbrick1_ht.h rename to src/tm/Elements/qbrick1_ht.h index 4dfb5735c..d97d43ed6 100644 --- a/src/tm/qbrick1_ht.h +++ b/src/tm/Elements/qbrick1_ht.h @@ -35,7 +35,7 @@ #ifndef qbrick1_ht_h #define qbrick1_ht_h -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "spatiallocalizer.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -43,6 +43,8 @@ #define _IFT_QBrick1_ht_Name "qbrick1ht" #define _IFT_QBrick1_hmt_Name "qbrick1hmt" +#define _IFT_QBrick1_mt_Name "qbrick1mt" + namespace oofem { class FEI3dHexaQuad; @@ -58,32 +60,30 @@ class QBrick1_ht : public TransportElement, public SpatialLocalizerInterface, pu public: QBrick1_ht(int n, Domain * d); - virtual ~QBrick1_ht(); - virtual double computeVolumeAround(GaussPoint *gp); - virtual FEInterpolation *giveInterpolation() const; + double computeVolumeAround(GaussPoint *gp) override; + FEInterpolation *giveInterpolation() const override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QBrick1_ht_Name; } - virtual const char *giveClassName() const { return "QBrick1_ht"; } + const char *giveInputRecordName() const override { return _IFT_QBrick1_ht_Name; } + const char *giveClassName() const override { return "QBrick1_ht"; } - virtual int computeNumberOfDofs() { return ( emode == HeatTransferEM ) ? 20 : 40; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode() { return _3dHeat; } + int computeNumberOfDofs() override { return ( emode == HeatTransferEM ) ? 20 : 40; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _3dHeat; } - virtual Interface *giveInterface(InterfaceType t); - virtual int testElementExtension(ElementExtension ext) { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } + Interface *giveInterface(InterfaceType t) override; + int testElementExtension(ElementExtension ext) override { return ( ( ext == Element_SurfaceLoadSupport ) ? 1 : 0 ); } - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; protected: - virtual void computeGaussPoints(); - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual IntegrationRule *GetSurfaceIntegrationRule(int approxOrder); - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iEdge); + void computeGaussPoints() override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + double computeSurfaceVolumeAround(GaussPoint *gp, int iEdge) override; }; class QBrick1_hmt : public QBrick1_ht @@ -91,9 +91,22 @@ class QBrick1_hmt : public QBrick1_ht public: QBrick1_hmt(int n, Domain * d); - virtual MaterialMode giveMaterialMode() { return _3dHeMo; } - virtual const char *giveInputRecordName() const { return _IFT_QBrick1_hmt_Name; } - virtual const char *giveClassName() const { return "QBrick1_hmt"; } + MaterialMode giveMaterialMode() override { return _3dHeMo; } + const char *giveInputRecordName() const override { return _IFT_QBrick1_hmt_Name; } + const char *giveClassName() const override { return "QBrick1_hmt"; } +}; + +/** + * Class for mass transfer. + */ +class QBrick1_mt : public QBrick1_ht +{ +public: + QBrick1_mt(int n, Domain * d); + + const char *giveInputRecordName() const override { return _IFT_QBrick1_mt_Name; } + const char *giveClassName() const override { return "QBrick1_mt"; } + MaterialMode giveMaterialMode() override { return _3dHeat; } }; } // end namespace oofem #endif // qbrick1_ht_h diff --git a/src/tm/Elements/qquad1_ht.C b/src/tm/Elements/qquad1_ht.C new file mode 100644 index 000000000..08ad69970 --- /dev/null +++ b/src/tm/Elements/qquad1_ht.C @@ -0,0 +1,192 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "tm/Elements/qquad1_ht.h" +#include "fei2dquadquad.h" +#include "crosssection.h" +#include "gausspoint.h" +#include "gaussintegrationrule.h" +#include "floatmatrix.h" +#include "floatarray.h" +#include "intarray.h" +#include "mathfem.h" +#include "classfactory.h" + + +namespace oofem { +REGISTER_Element(QQuad1_ht); +REGISTER_Element(QQuad1_hmt); +REGISTER_Element(QQuad1_mt); + +FEI2dQuadQuad QQuad1_ht :: interpolation(1, 2); + +QQuad1_ht :: QQuad1_ht(int n, Domain *aDomain) : TransportElement(n, aDomain, HeatTransferEM), SpatialLocalizerInterface(this), ZZNodalRecoveryModelInterface(this), SPRNodalRecoveryModelInterface() +{ + numberOfDofMans = 8; + numberOfGaussPoints = 4; +} + +QQuad1_hmt :: QQuad1_hmt(int n, Domain *aDomain) : QQuad1_ht(n, aDomain) +{ + emode = HeatMass1TransferEM; +} + +QQuad1_mt :: QQuad1_mt(int n, Domain *aDomain) : QQuad1_ht(n, aDomain) +{ + emode = Mass1TransferEM; +} + + +FEInterpolation * +QQuad1_ht :: giveInterpolation() const { return & interpolation; } + +void +QQuad1_ht :: computeGaussPoints() +{ + if ( integrationRulesArray.size() == 0 ) { + integrationRulesArray.resize( 1 ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); + this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); + } +} + + +void +QQuad1_ht :: initializeFrom(InputRecord &ir) +{ + //numberOfGaussPoints = 4; + TransportElement :: initializeFrom(ir); +} + + +double +QQuad1_ht :: computeVolumeAround(GaussPoint *gp) +{ + double determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), + FEIElementGeometryWrapper(this) ) ); + double thickness = this->giveCrossSection()->give(CS_Thickness, gp); // 't' + return determinant * gp->giveWeight() * thickness; +} + + +double +QQuad1_ht :: giveThicknessAt(const FloatArray &gcoords) +{ + return this->giveCrossSection()->give(CS_Thickness, gcoords, this, false); +} + + +double +QQuad1_ht :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) +{ + double result = this->interpolation.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), + FEIElementGeometryWrapper(this) ); + FloatArray gc; + this->interpolation.edgeLocal2global( gc, iEdge, gp->giveNaturalCoordinates(), + FEIElementGeometryWrapper(this) ); + // temporary gauss point on element (not edge) to evaluate thickness + GaussPoint _gp( NULL, 1, gc, 1.0, gp->giveMaterialMode() ); + double thick = this->giveCrossSection()->give(CS_Thickness, & _gp); // 't' + return result *thick *gp->giveWeight(); +} + +Interface * +QQuad1_ht :: giveInterface(InterfaceType interface) +{ + if ( interface == SpatialLocalizerInterfaceType ) { + return static_cast< SpatialLocalizerInterface * >(this); + } else if ( interface == EIPrimaryFieldInterfaceType ) { + return static_cast< EIPrimaryFieldInterface * >(this); + } else if ( interface == ZZNodalRecoveryModelInterfaceType ) { + return static_cast< ZZNodalRecoveryModelInterface * >(this); + } else if ( interface == SPRNodalRecoveryModelInterfaceType ) { + return static_cast< SPRNodalRecoveryModelInterface * >(this); + } + + return nullptr; +} + +void +QQuad1_ht :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) +{ + pap.resize(8); + for ( int i = 1; i <= 8; i++ ) { + pap.at(i) = this->giveNode(i)->giveNumber(); + } +} + +void +QQuad1_ht :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) +{ + int found = 0; + answer.resize(1); + + for ( int i = 1; i <= 8; i++ ) { + if ( this->giveNode(i)->giveNumber() == pap ) { + found = 1; + } + } + + if ( found ) { + answer.at(1) = pap; + } else { + OOFEM_ERROR("unknown node number %d", pap); + } +} + +int +QQuad1_ht :: SPRNodalRecoveryMI_giveNumberOfIP() +{ + return numberOfGaussPoints; +} + + +SPRPatchType +QQuad1_ht :: SPRNodalRecoveryMI_givePatchType() +{ + return SPRPatchType_2dquadratic; +} + + +void +QQuad1_ht :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) +{ + answer.clear(); + OOFEM_WARNING("IP values will not be transferred to nodes. Use ZZNodalRecovery instead (parameter stype 1)"); +} + + + + +} // end namespace oofem diff --git a/src/tm/Elements/qquad1_ht.h b/src/tm/Elements/qquad1_ht.h new file mode 100644 index 000000000..352e7ae3b --- /dev/null +++ b/src/tm/Elements/qquad1_ht.h @@ -0,0 +1,114 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef qquad1_ht_h +#define qquad1_ht_h + +#include "tm/Elements/transportelement.h" +#include "spatiallocalizer.h" +#include "zznodalrecoverymodel.h" +#include "sprnodalrecoverymodel.h" +#include "nodalaveragingrecoverymodel.h" + +#define _IFT_QQuad1_ht_Name "qquad1ht" +#define _IFT_QQuad1_hmt_Name "qquad1hmt" +#define _IFT_QQuad1_mt_Name "qquad1mt" + +namespace oofem { +class FEI2dQuadQuad; + +/** + * Quadratic (2d) element with quadratic approximation for heat transfer. + */ +class QQuad1_ht : public TransportElement, public SpatialLocalizerInterface, public ZZNodalRecoveryModelInterface, public SPRNodalRecoveryModelInterface, public NodalAveragingRecoveryModelInterface +{ +protected: + static FEI2dQuadQuad interpolation; + +public: + QQuad1_ht(int n, Domain * d); + + FEInterpolation *giveInterpolation() const override; + double computeVolumeAround(GaussPoint *gp) override; + + const char *giveInputRecordName() const override { return _IFT_QQuad1_ht_Name; } + const char *giveClassName() const override { return "QQuad1_ht"; } + + int computeNumberOfDofs() override { return 4; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _2dHeat; } + double giveThicknessAt(const FloatArray &gcoords) override; + + Interface *giveInterface(InterfaceType t) override; + + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; + +protected: + void computeGaussPoints() override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; +}; + +/** + * Class for heat and mass transfer. + */ +class QQuad1_hmt : public QQuad1_ht +{ +public: + QQuad1_hmt(int n, Domain * d); + + const char *giveInputRecordName() const override { return _IFT_QQuad1_hmt_Name; } + const char *giveClassName() const override { return "QQuad1_hmt"; } + int computeNumberOfDofs() override { return 8; } + MaterialMode giveMaterialMode() override { return _2dHeMo; } +}; + +/** + * Class for mass transfer. + */ +class QQuad1_mt : public QQuad1_ht +{ +public: + QQuad1_mt(int n, Domain * d); + + const char *giveInputRecordName() const override { return _IFT_QQuad1_mt_Name; } + const char *giveClassName() const override { return "QQuad1_mt"; } + int computeNumberOfDofs() override { return 4; } + MaterialMode giveMaterialMode() override { return _2dHeat; } +}; +} // end namespace oofem +#endif // quad1_ht_h diff --git a/src/tm/quad1_ht.C b/src/tm/Elements/quad1_ht.C similarity index 92% rename from src/tm/quad1_ht.C rename to src/tm/Elements/quad1_ht.C index 2710fdcc0..1ddf508a2 100644 --- a/src/tm/quad1_ht.C +++ b/src/tm/Elements/quad1_ht.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "quad1_ht.h" +#include "tm/Elements/quad1_ht.h" #include "fei2dquadlin.h" #include "crosssection.h" #include "gausspoint.h" @@ -71,8 +71,6 @@ Quad1_mt :: Quad1_mt(int n, Domain *aDomain) : Quad1_ht(n, aDomain) emode = Mass1TransferEM; } -Quad1_ht :: ~Quad1_ht() -{ } FEInterpolation * Quad1_ht :: giveInterpolation() const { return & interpolation; } @@ -82,32 +80,27 @@ Quad1_ht :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } -IRResultType -Quad1_ht :: initializeFrom(InputRecord *ir) +void +Quad1_ht :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 4; - return TransportElement :: initializeFrom(ir); + TransportElement :: initializeFrom(ir); } double Quad1_ht :: computeVolumeAround(GaussPoint *gp) -// Returns the portion of the receiver which is attached to gp. { - double determinant, weight, thickness, volume; - determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), + double determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); - thickness = this->giveCrossSection()->give(CS_Thickness, gp); // 't' - volume = determinant * weight * thickness; - - return volume; + double thickness = this->giveCrossSection()->give(CS_Thickness, gp); // 't' + return determinant * gp->giveWeight() * thickness; } @@ -143,7 +136,7 @@ Quad1_ht :: giveInterface(InterfaceType interface) return static_cast< ZZNodalRecoveryModelInterface * >(this); } - return NULL; + return nullptr; } diff --git a/src/tm/quad1_ht.h b/src/tm/Elements/quad1_ht.h similarity index 57% rename from src/tm/quad1_ht.h rename to src/tm/Elements/quad1_ht.h index 95261feeb..dd5c99aa6 100644 --- a/src/tm/quad1_ht.h +++ b/src/tm/Elements/quad1_ht.h @@ -35,7 +35,7 @@ #ifndef quad1_ht_h #define quad1_ht_h -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "spatiallocalizer.h" #include "zznodalrecoverymodel.h" @@ -56,33 +56,32 @@ class Quad1_ht : public TransportElement, public SpatialLocalizerInterface, publ public: Quad1_ht(int n, Domain * d); - virtual ~Quad1_ht(); - virtual FEInterpolation *giveInterpolation() const; - virtual double computeVolumeAround(GaussPoint *gp); + FEInterpolation *giveInterpolation() const override; + double computeVolumeAround(GaussPoint *gp) override; - virtual const char *giveInputRecordName() const { return _IFT_Quad1_ht_Name; } - virtual const char *giveClassName() const { return "Quad1_ht"; } + const char *giveInputRecordName() const override { return _IFT_Quad1_ht_Name; } + const char *giveClassName() const override { return "Quad1_ht"; } - // virtual int computeNumberOfDofs() { return ( emode == HeatTransferEM ) ? 4 : 8; } - virtual int computeNumberOfDofs() { return 4; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode() { return _2dHeat; } - virtual double giveThicknessAt(const FloatArray &gcoords); + //int computeNumberOfDofs() override { return ( emode == HeatTransferEM ) ? 4 : 8; } + int computeNumberOfDofs() override { return 4; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _2dHeat; } + double giveThicknessAt(const FloatArray &gcoords) override; - virtual Interface *giveInterface(InterfaceType t); + Interface *giveInterface(InterfaceType t) override; #ifdef __OOFEG // Graphics output - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - //virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) {} - //virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) {} + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + //void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override {} + //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override {} #endif protected: - virtual void computeGaussPoints(); - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); + void computeGaussPoints() override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; }; /** @@ -93,10 +92,10 @@ class Quad1_hmt : public Quad1_ht public: Quad1_hmt(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_Quad1_hmt_Name; } - virtual const char *giveClassName() const { return "Quad1_hmt"; } - virtual int computeNumberOfDofs() { return 8; } - virtual MaterialMode giveMaterialMode() { return _2dHeMo; } + const char *giveInputRecordName() const override { return _IFT_Quad1_hmt_Name; } + const char *giveClassName() const override { return "Quad1_hmt"; } + int computeNumberOfDofs() override { return 8; } + MaterialMode giveMaterialMode() override { return _2dHeMo; } }; /** @@ -107,10 +106,10 @@ class Quad1_mt : public Quad1_ht public: Quad1_mt(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_Quad1_mt_Name; } - virtual const char *giveClassName() const { return "Quad1_mt"; } - virtual int computeNumberOfDofs() { return 4; } - virtual MaterialMode giveMaterialMode() { return _2dHeat; } + const char *giveInputRecordName() const override { return _IFT_Quad1_mt_Name; } + const char *giveClassName() const override { return "Quad1_mt"; } + int computeNumberOfDofs() override { return 4; } + MaterialMode giveMaterialMode() override { return _2dHeat; } }; } // end namespace oofem #endif // quad1_ht_h diff --git a/src/tm/quadaxisym1_ht.C b/src/tm/Elements/quadaxisym1_ht.C similarity index 79% rename from src/tm/quadaxisym1_ht.C rename to src/tm/Elements/quadaxisym1_ht.C index 5e34b0b2f..25d364c09 100644 --- a/src/tm/quadaxisym1_ht.C +++ b/src/tm/Elements/quadaxisym1_ht.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "quadaxisym1_ht.h" +#include "tm/Elements/quadaxisym1_ht.h" #include "fei2dquadlin.h" #include "gausspoint.h" #include "mathfem.h" @@ -61,22 +61,14 @@ QuadAxisym1_mt :: QuadAxisym1_mt(int n, Domain *aDomain) : QuadAxisym1_ht(n, aDo this->emode = Mass1TransferEM; } -QuadAxisym1_ht :: ~QuadAxisym1_ht() -// Destructor -{ } - double QuadAxisym1_ht :: computeVolumeAround(GaussPoint *gp) -// Returns the portion of the receiver which is attached to gp. { - double determinant, weight, volume; - determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), + double determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); - volume = determinant * weight * this->computeRadiusAt(gp); - - return volume; + double weight = gp->giveWeight(); + return determinant * weight * this->computeRadiusAt(gp); } double @@ -88,10 +80,9 @@ QuadAxisym1_ht :: giveThicknessAt(const FloatArray &gcoords) double QuadAxisym1_ht :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { - double radius; FloatArray gcoords; this->interpolation.edgeLocal2global( gcoords, iEdge, gp->giveSubPatchCoordinates(), FEIElementGeometryWrapper(this) ); - radius = gcoords.at(1); + double radius = gcoords.at(1); double detJ = fabs( this->interpolation.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); @@ -106,16 +97,15 @@ QuadAxisym1_ht :: computeRadiusAt(GaussPoint *gp) return gcoords.at(1); } -IntegrationRule* -QuadAxisym1_ht :: giveBoundaryEdgeIntegrationRule (int order, int boundary) +std::unique_ptr +QuadAxisym1_ht :: giveBoundaryEdgeIntegrationRule(int order, int boundary) { - return this->giveInterpolation()->giveBoundaryEdgeIntegrationRule(order+1, boundary); - + return this->giveInterpolation()->giveBoundaryEdgeIntegrationRule(order+1, boundary); } -IntegrationRule* -QuadAxisym1_ht :: giveBoundarySurfaceIntegrationRule (int order, int boundary) +std::unique_ptr +QuadAxisym1_ht :: giveBoundarySurfaceIntegrationRule(int order, int boundary) { - return this->giveInterpolation()->giveBoundarySurfaceIntegrationRule(order+1, boundary); + return this->giveInterpolation()->giveBoundarySurfaceIntegrationRule(order+1, boundary); } } // end namespace oofem diff --git a/src/tm/quadaxisym1_ht.h b/src/tm/Elements/quadaxisym1_ht.h similarity index 73% rename from src/tm/quadaxisym1_ht.h rename to src/tm/Elements/quadaxisym1_ht.h index 90a782afd..81ad052cc 100644 --- a/src/tm/quadaxisym1_ht.h +++ b/src/tm/Elements/quadaxisym1_ht.h @@ -35,7 +35,7 @@ #ifndef quadaxisym1_ht_h #define quadaxisym1_ht_h -#include "quad1_ht.h" +#include "tm/Elements/quad1_ht.h" #define _IFT_QuadAxisym1_ht_Name "quadaxisym1ht" #define _IFT_QuadAxisym1_hmt_Name "quadaxisym1hmt" @@ -50,19 +50,18 @@ class QuadAxisym1_ht : public Quad1_ht { public: QuadAxisym1_ht(int n, Domain * d); - virtual ~QuadAxisym1_ht(); - virtual double computeVolumeAround(GaussPoint *gp); - virtual double giveThicknessAt(const FloatArray &gcoords); + double computeVolumeAround(GaussPoint *gp) override; + double giveThicknessAt(const FloatArray &gcoords) override; + + const char *giveClassName() const override { return "QuadAxisym1_ht"; } + std::unique_ptr giveBoundaryEdgeIntegrationRule(int order, int boundary) override; + std::unique_ptr giveBoundarySurfaceIntegrationRule(int order, int boundary) override; - virtual const char *giveClassName() const { return "QuadAxisym1_ht"; } - virtual IntegrationRule* giveBoundaryEdgeIntegrationRule (int order, int boundary); - virtual IntegrationRule* giveBoundarySurfaceIntegrationRule (int order, int boundary); - protected: - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual double computeRadiusAt(GaussPoint *gp); - virtual int giveApproxOrder(int unknownIndx) { return 2; } + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + double computeRadiusAt(GaussPoint *gp); + int giveApproxOrder(int unknownIndx) override { return 2; } }; /** @@ -73,7 +72,7 @@ class QuadAxisym1_hmt : public QuadAxisym1_ht public: QuadAxisym1_hmt(int n, Domain * d); - virtual const char *giveClassName() const { return "QuadAxisym1_hmt"; } + const char *giveClassName() const override { return "QuadAxisym1_hmt"; } }; @@ -84,7 +83,7 @@ class QuadAxisym1_mt : public QuadAxisym1_ht { public: QuadAxisym1_mt(int n, Domain * d); - virtual const char *giveClassName() const { return "QuadAxisym1_mt"; } + const char *giveClassName() const override { return "QuadAxisym1_mt"; } }; } // end namespace oofem #endif // quadaxisym1_ht_h diff --git a/src/tm/qwedge_ht.C b/src/tm/Elements/qwedge_ht.C similarity index 89% rename from src/tm/qwedge_ht.C rename to src/tm/Elements/qwedge_ht.C index cc3c9988b..c8d9ac24b 100644 --- a/src/tm/qwedge_ht.C +++ b/src/tm/Elements/qwedge_ht.C @@ -33,7 +33,7 @@ */ -#include "qwedge_ht.h" +#include "tm/Elements/qwedge_ht.h" #include "fei3dwedgequad.h" #include "node.h" #include "gausspoint.h" @@ -53,7 +53,6 @@ REGISTER_Element(QWedge_ht); FEI3dWedgeQuad QWedge_ht :: interpolation; QWedge_ht :: QWedge_ht(int n, Domain *aDomain) : TransportElement(n, aDomain, HeatTransferEM), SpatialLocalizerInterface(this), ZZNodalRecoveryModelInterface(this), SPRNodalRecoveryModelInterface() - // Constructor. { numberOfDofMans = 15; } @@ -69,11 +68,11 @@ QWedge_mt :: QWedge_mt(int n, Domain *aDomain) : QWedge_ht(n, aDomain) } -IRResultType -QWedge_ht :: initializeFrom(InputRecord *ir) +void +QWedge_ht :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 6; - return TransportElement :: initializeFrom(ir); + TransportElement :: initializeFrom(ir); } @@ -83,7 +82,7 @@ QWedge_ht :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } @@ -91,15 +90,11 @@ QWedge_ht :: computeGaussPoints() double QWedge_ht :: computeVolumeAround(GaussPoint *gp) -// Returns the portion of the receiver which is attached to gp. { - double determinant, weight, volume; - determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), + double determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); - volume = determinant * weight; - return volume; + return determinant * gp->giveWeight(); } @@ -109,7 +104,7 @@ QWedge_ht :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { double result = this->interpolation.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - return result *gp->giveWeight(); + return result * gp->giveWeight(); } @@ -133,7 +128,7 @@ QWedge_ht :: giveInterface(InterfaceType interface) } OOFEM_LOG_INFO("Interface on Lwedge element not supported"); - return NULL; + return nullptr; } void diff --git a/src/tm/qwedge_ht.h b/src/tm/Elements/qwedge_ht.h similarity index 59% rename from src/tm/qwedge_ht.h rename to src/tm/Elements/qwedge_ht.h index e288fc391..ea330b7fc 100644 --- a/src/tm/qwedge_ht.h +++ b/src/tm/Elements/qwedge_ht.h @@ -37,7 +37,7 @@ #define qwedge_ht_h -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "spatiallocalizer.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" @@ -62,35 +62,31 @@ class FEI3dWedgeQuad; public: QWedge_ht(int, Domain *); - virtual ~QWedge_ht() { } - - virtual double computeVolumeAround(GaussPoint *gp); - virtual FEInterpolation *giveInterpolation() const; + double computeVolumeAround(GaussPoint *gp) override; + FEInterpolation *giveInterpolation() const override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_QWedge_ht_Name; } - virtual const char *giveClassName() const { return "QWedge_ht"; } + const char *giveInputRecordName() const override { return _IFT_QWedge_ht_Name; } + const char *giveClassName() const override { return "QWedge_ht"; } - virtual int computeNumberOfDofs() { return 15; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode() { return _3dHeat; } + int computeNumberOfDofs() override { return 15; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _3dHeat; } - virtual Interface *giveInterface(InterfaceType t); - virtual int testElementExtension(ElementExtension ext) + Interface *giveInterface(InterfaceType t) override; + int testElementExtension(ElementExtension ext) override { return ( ext == Element_EdgeLoadSupport );} - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; protected: - virtual void computeGaussPoints(); - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - - + void computeGaussPoints() override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; }; @@ -103,10 +99,10 @@ class QWedge_hmt : public QWedge_ht public: QWedge_hmt(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_QWedge_hmt_Name; } - virtual const char *giveClassName() const { return "QWedge_hmt"; } - virtual int computeNumberOfDofs() { return 24; } - virtual MaterialMode giveMaterialMode() { return _3dHeMo; } + const char *giveInputRecordName() const override { return _IFT_QWedge_hmt_Name; } + const char *giveClassName() const override { return "QWedge_hmt"; } + int computeNumberOfDofs() override { return 24; } + MaterialMode giveMaterialMode() override { return _3dHeMo; } }; /** @@ -117,10 +113,10 @@ class QWedge_mt : public QWedge_ht public: QWedge_mt(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_QWedge_mt_Name; } - virtual const char *giveClassName() const { return "QWedge_mt"; } - virtual int computeNumberOfDofs() { return 15; } - virtual MaterialMode giveMaterialMode() { return _3dHeat; } + const char *giveInputRecordName() const override { return _IFT_QWedge_mt_Name; } + const char *giveClassName() const override { return "QWedge_mt"; } + int computeNumberOfDofs() override { return 15; } + MaterialMode giveMaterialMode() override { return _3dHeat; } }; diff --git a/src/tm/tetrah1_ht.C b/src/tm/Elements/tetrah1_ht.C similarity index 83% rename from src/tm/tetrah1_ht.C rename to src/tm/Elements/tetrah1_ht.C index 1cb17d382..584c4ab39 100644 --- a/src/tm/tetrah1_ht.C +++ b/src/tm/Elements/tetrah1_ht.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "tetrah1_ht.h" +#include "tm/Elements/tetrah1_ht.h" #include "gausspoint.h" #include "gaussintegrationrule.h" #include "floatmatrix.h" @@ -65,9 +65,6 @@ Tetrah1_hmt :: Tetrah1_hmt(int n, Domain *aDomain) : Tetrah1_ht(n, aDomain) this->emode = HeatMass1TransferEM; // This could be done in a better way. } -Tetrah1_ht :: ~Tetrah1_ht() -{ } - FEInterpolation * Tetrah1_ht :: giveInterpolation() const @@ -78,35 +75,31 @@ Tetrah1_ht :: giveInterpolation() const void Tetrah1_ht :: computeGaussPoints() -// Sets up the array containing the four Gauss points of the receiver. { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } -IRResultType -Tetrah1_ht :: initializeFrom(InputRecord *ir) +void +Tetrah1_ht :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 1; - return TransportElement :: initializeFrom(ir); + TransportElement :: initializeFrom(ir); } double Tetrah1_ht :: computeVolumeAround(GaussPoint *gp) -// Returns the portion of the receiver which is attached to gp. { - double determinant, weight, volume; - determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), + double determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); - volume = determinant * weight; - return volume; + double weight = gp->giveWeight(); + return determinant * weight; } @@ -114,29 +107,17 @@ double Tetrah1_ht :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { double result = this->interpolation.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), - FEIElementGeometryWrapper(this) ); - return result *gp->giveWeight(); -} - - -IntegrationRule * -Tetrah1_ht :: GetSurfaceIntegrationRule(int approxOrder) -{ - IntegrationRule *iRule = new GaussIntegrationRule(1, this, 1, 1); - int npoints = iRule->getRequiredNumberOfIntegrationPoints(_Triangle, approxOrder); - iRule->SetUpPointsOnTriangle(npoints, _Unknown); - return iRule; + FEIElementGeometryWrapper(this) ); + return result * gp->giveWeight(); } double Tetrah1_ht :: computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { - double detJ, weight; - detJ = fabs( interpolation.surfaceGiveTransformationJacobian( iSurf, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - - weight = gp->giveWeight(); - return detJ * weight; + double detJ = fabs( interpolation.surfaceGiveTransformationJacobian( iSurf, gp->giveNaturalCoordinates(), + FEIElementGeometryWrapper(this) ) ); + return detJ * gp->giveWeight(); } @@ -151,7 +132,7 @@ Tetrah1_ht :: giveInterface(InterfaceType interface) return static_cast< ZZNodalRecoveryModelInterface * >(this); } - return NULL; + return nullptr; } diff --git a/src/tm/tetrah1_ht.h b/src/tm/Elements/tetrah1_ht.h similarity index 60% rename from src/tm/tetrah1_ht.h rename to src/tm/Elements/tetrah1_ht.h index 1c49422fe..cf0a27c2b 100644 --- a/src/tm/tetrah1_ht.h +++ b/src/tm/Elements/tetrah1_ht.h @@ -35,7 +35,7 @@ #ifndef tetrah1_ht_h #define tetrah1_ht_h -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "spatiallocalizer.h" #include "zznodalrecoverymodel.h" @@ -55,37 +55,35 @@ class Tetrah1_ht : public TransportElement, public SpatialLocalizerInterface, pu public: Tetrah1_ht(int n, Domain * d); - virtual ~Tetrah1_ht(); - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; // definition - virtual const char *giveInputRecordName() const { return _IFT_Tetrah1_ht_Name; } - virtual const char *giveClassName() const { return "Tetrah1_ht"; } + const char *giveInputRecordName() const override { return _IFT_Tetrah1_ht_Name; } + const char *giveClassName() const override { return "Tetrah1_ht"; } - virtual int computeNumberOfDofs() { return ( emode == HeatTransferEM ) ? 4 : 8; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode() { return _3dHeat; } + int computeNumberOfDofs() override { return ( emode == HeatTransferEM ) ? 4 : 8; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _3dHeat; } - virtual Interface *giveInterface(InterfaceType t); - virtual int testElementExtension(ElementExtension ext) + Interface *giveInterface(InterfaceType t) override; + int testElementExtension(ElementExtension ext) override { return ( ( ( ext == Element_EdgeLoadSupport ) || ( ext == Element_SurfaceLoadSupport ) ) ? 1 : 0 ); } #ifdef __OOFEG // Graphics output - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawScalar(oofegGraphicContext &gc, TimeStep *tStep); - //virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) {} - //virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) {} + void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override; + void drawScalar(oofegGraphicContext &gc, TimeStep *tStep) override; + //void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override {} + //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override {} #endif protected: - virtual void computeGaussPoints(); - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual IntegrationRule *GetSurfaceIntegrationRule(int approxOrder); - virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iEdge); + void computeGaussPoints() override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + double computeSurfaceVolumeAround(GaussPoint *gp, int iEdge) override; }; class Tetrah1_hmt : public Tetrah1_ht @@ -93,9 +91,9 @@ class Tetrah1_hmt : public Tetrah1_ht public: Tetrah1_hmt(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_Tetrah1_hmt_Name; } - virtual const char *giveClassName() const { return "Tetrah1_hmt"; } - virtual MaterialMode giveMaterialMode() { return _3dHeMo; } + const char *giveInputRecordName() const override { return _IFT_Tetrah1_hmt_Name; } + const char *giveClassName() const override { return "Tetrah1_hmt"; } + MaterialMode giveMaterialMode() override { return _3dHeMo; } }; } // end namespace oofem #endif // tetrah1_ht_h diff --git a/src/tm/tr1_ht.C b/src/tm/Elements/tr1_ht.C similarity index 82% rename from src/tm/tr1_ht.C rename to src/tm/Elements/tr1_ht.C index bccedca69..1f6a1aaca 100644 --- a/src/tm/tr1_ht.C +++ b/src/tm/Elements/tr1_ht.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "tr1_ht.h" +#include "tm/Elements/tr1_ht.h" #include "fei2dtrlin.h" #include "crosssection.h" #include "gausspoint.h" @@ -53,7 +53,6 @@ FEI2dTrLin Tr1_ht :: interp(1, 2); Tr1_ht :: Tr1_ht(int n, Domain *aDomain) : TransportElement(n, aDomain, HeatTransferEM), SpatialLocalizerInterface(this), ZZNodalRecoveryModelInterface(this) - // Constructor. { numberOfDofMans = 3; numberOfGaussPoints = 1; @@ -75,34 +74,29 @@ Tr1_ht :: giveInterpolation() const { return & this->interp; } void Tr1_ht :: computeGaussPoints() -// Sets up the array containing the four Gauss points of the receiver. { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } -IRResultType -Tr1_ht :: initializeFrom(InputRecord *ir) +void +Tr1_ht :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 1; - return TransportElement :: initializeFrom(ir); + TransportElement :: initializeFrom(ir); } double Tr1_ht :: computeVolumeAround(GaussPoint *gp) -// Returns the portion of the receiver which is attached to gp. { - double determinant, weight, volume; - determinant = fabs( this->interp.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); - volume = determinant * weight * this->giveCrossSection()->give(CS_Thickness, gp); - - return volume; + double determinant = fabs( this->interp.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double weight = gp->giveWeight(); + return determinant * weight * this->giveCrossSection()->give(CS_Thickness, gp); } @@ -119,7 +113,7 @@ Tr1_ht :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) double determinant = fabs( this->interp.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); FloatArray gc; double thick = this->giveCrossSection()->give(CS_Thickness, gp->giveNaturalCoordinates(), NULL); // 't' - return determinant *thick *gp->giveWeight(); + return determinant * thick * gp->giveWeight(); } @@ -134,7 +128,7 @@ Tr1_ht :: giveInterface(InterfaceType interface) return static_cast< ZZNodalRecoveryModelInterface * >(this); } - return NULL; + return nullptr; } } // end namespace oofem diff --git a/src/tm/tr1_ht.h b/src/tm/Elements/tr1_ht.h similarity index 62% rename from src/tm/tr1_ht.h rename to src/tm/Elements/tr1_ht.h index fc406fcc8..f3e43f2ae 100644 --- a/src/tm/tr1_ht.h +++ b/src/tm/Elements/tr1_ht.h @@ -35,7 +35,7 @@ #ifndef tr1_ht_h #define tr1_ht_h -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "spatiallocalizer.h" #include "zznodalrecoverymodel.h" @@ -57,32 +57,31 @@ class Tr1_ht : public TransportElement, public SpatialLocalizerInterface, public public: Tr1_ht(int n, Domain * d); - //virtual ~Tr1_ht(); - virtual double computeVolumeAround(GaussPoint *gp); + double computeVolumeAround(GaussPoint *gp) override; // definition - virtual const char *giveInputRecordName() const { return _IFT_Tr1_ht_Name; } - virtual const char *giveClassName() const { return "Tr1_htElement"; } + const char *giveInputRecordName() const override { return _IFT_Tr1_ht_Name; } + const char *giveClassName() const override { return "Tr1_htElement"; } - virtual int computeNumberOfDofs() { return ( emode == HeatMass1TransferEM ) ? 6 : 3; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode() { return _2dHeat; } - virtual double giveThicknessAt(const FloatArray &gcoords); + int computeNumberOfDofs() override { return ( emode == HeatMass1TransferEM ) ? 6 : 3; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _2dHeat; } + double giveThicknessAt(const FloatArray &gcoords) override; - virtual Interface *giveInterface(InterfaceType t); + Interface *giveInterface(InterfaceType t) override; - virtual FEInterpolation *giveInterpolation() const; + FEInterpolation *giveInterpolation() const override; #ifdef __OOFEG // Graphics output - //virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) {} - //virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) {} + //void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override {} + //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override {} #endif protected: - virtual void computeGaussPoints(); - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); + void computeGaussPoints() override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; }; /** @@ -93,9 +92,9 @@ class Tr1_mt : public Tr1_ht public: Tr1_mt(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_Tr1_mt_Name; } - virtual const char *giveClassName() const { return "Tr1_mt"; } - virtual MaterialMode giveMaterialMode() { return _2dHeat; } + const char *giveInputRecordName() const override { return _IFT_Tr1_mt_Name; } + const char *giveClassName() const override { return "Tr1_mt"; } + MaterialMode giveMaterialMode() override { return _2dHeat; } }; @@ -107,9 +106,9 @@ class Tr1_hmt : public Tr1_ht public: Tr1_hmt(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_Tr1_hmt_Name; } - virtual const char *giveClassName() const { return "Tr1_hmt"; } - virtual MaterialMode giveMaterialMode() { return _2dHeMo; } + const char *giveInputRecordName() const override { return _IFT_Tr1_hmt_Name; } + const char *giveClassName() const override { return "Tr1_hmt"; } + MaterialMode giveMaterialMode() override { return _2dHeMo; } }; } // end namespace oofem #endif // tr1_ht_h diff --git a/src/tm/tr1darcy.C b/src/tm/Elements/tr1darcy.C similarity index 69% rename from src/tm/tr1darcy.C rename to src/tm/Elements/tr1darcy.C index d2c4c9ff2..971a15766 100644 --- a/src/tm/tr1darcy.C +++ b/src/tm/Elements/tr1darcy.C @@ -33,19 +33,23 @@ */ -#include "tr1darcy.h" +#include "tm/Elements/tr1darcy.h" #include "fei2dtrlin.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "gaussintegrationrule.h" #include "gausspoint.h" #include "bcgeomtype.h" #include "generalboundarycondition.h" -#include "transportmaterial.h" +#include "tm/Materials/transportmaterial.h" #include "load.h" #include "boundaryload.h" #include "mathfem.h" #include "crosssection.h" #include "classfactory.h" +#include "iostream" + namespace oofem { REGISTER_Element(Tr1Darcy); @@ -56,13 +60,10 @@ Tr1Darcy :: Tr1Darcy(int n, Domain *aDomain) : TransportElement(n, aDomain) numberOfDofMans = 3; } -Tr1Darcy :: ~Tr1Darcy() -{ } - -IRResultType Tr1Darcy :: initializeFrom(InputRecord *ir) +void Tr1Darcy :: initializeFrom(InputRecord &ir) { this->numberOfGaussPoints = 1; - return TransportElement :: initializeFrom(ir); + TransportElement :: initializeFrom(ir); } FEInterpolation * @@ -75,34 +76,26 @@ void Tr1Darcy :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 3) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 3); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } void Tr1Darcy :: computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep) { - /* - * Return Ke = integrate(B^T K B) - */ - - FloatMatrix B, BT, K, KB; + auto mat = static_cast< TransportMaterial * >( this->giveMaterial() ); - TransportMaterial *mat = static_cast< TransportMaterial * >( this->giveMaterial() ); + FloatMatrixF<3,3> Ke; + for ( auto &gp: *integrationRulesArray [ 0 ] ) { + // auto [detJ, B] = evaldNdx(lcoords, FEIElementGeometryWrapper(this)); + auto x = this->interpolation_lin.evaldNdx(FEIElementGeometryWrapper(this)); + auto detJ = x.first; + auto B = x.second; - answer.clear(); - - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { - const FloatArray &lcoords = gp->giveNaturalCoordinates(); - ///@todo Should we make it return the transpose instead? - double detJ = fabs( this->interpolation_lin.evaldNdx( BT, lcoords, FEIElementGeometryWrapper(this) ) ); - - mat->giveCharacteristicMatrix(K, mode, gp, tStep); - - B.beTranspositionOf(BT); - KB.beProductOf(K, B); - answer.plusProductUnsym( B, KB, detJ * gp->giveWeight() ); // Symmetric part is just a single value, not worth it. + auto D = mat->computeTangent2D(mode, gp, tStep); + Ke += detJ * gp->giveWeight() * Tdot(B, dot(D, B)); } + answer = Ke; } void Tr1Darcy :: giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, TimeStep *tStep) @@ -118,33 +111,32 @@ void Tr1Darcy :: giveCharacteristicVector(FloatArray &answer, CharType mtrx, Val void Tr1Darcy :: computeInternalForcesVector(FloatArray &answer, TimeStep *tStep) { - FloatArray w, a, gradP, P(1), n; - FloatMatrix B, BT; - - TransportMaterial *mat = static_cast< TransportMaterial * >( this->giveMaterial() ); + auto mat = static_cast< TransportMaterial * >( this->giveMaterial() ); - this->computeVectorOf(VM_Total, tStep, a); + FloatArray a_tmp; + this->computeVectorOf(VM_Total, tStep, a_tmp); + FloatArrayF<3> a = a_tmp; - answer.resize(3); - answer.zero(); - - for ( GaussPoint *gp: *integrationRulesArray [ 0 ] ) { - const FloatArray &lcoords = gp->giveNaturalCoordinates(); + FloatArrayF<3> fe; + for ( auto &gp: *integrationRulesArray [ 0 ] ) { + const FloatArrayF<2> lcoords = gp->giveNaturalCoordinates(); - double detJ = fabs( this->interpolation_lin.giveTransformationJacobian( lcoords, FEIElementGeometryWrapper(this) ) ); - this->interpolation_lin.evaldNdx( BT, lcoords, FEIElementGeometryWrapper(this) ); - this->interpolation_lin.evalN( n, lcoords, FEIElementGeometryWrapper(this) ); - B.beTranspositionOf(BT); - P.at(1) = n.dotProduct(a); // Evaluates the field at this point. + // auto [detJ, B] = evaldNdx(lcoords, FEIElementGeometryWrapper(this)); + auto x = this->interpolation_lin.evaldNdx(FEIElementGeometryWrapper(this)); + auto detJ = x.first; + auto B = x.second; + auto n = this->interpolation_lin.evalN(lcoords); - gradP.beProductOf(B, a); + auto p = dot(n, a); + auto gradp = dot(B, a); + auto w = mat->computeFlux2D(gradp, p, gp, tStep); - mat->giveFluxVector(w, gp, gradP, P, tStep); - - answer.plusProduct(B, w, -gp->giveWeight() * detJ); + fe += -gp->giveWeight() * detJ * Tdot(B, w); } + answer = fe; } + void Tr1Darcy :: computeExternalForcesVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode) { // TODO: Implement support for body forces @@ -155,17 +147,12 @@ void Tr1Darcy :: computeExternalForcesVector(FloatArray &answer, TimeStep *tStep answer.zero(); // Compute characteristic vector for Neumann boundary conditions. - int load_number, load_id; - Load *load; - bcGeomType ltype; - int nLoads = boundaryLoadArray.giveSize() / 2; - for ( int i = 1; i <= nLoads; i++ ) { // For each Neumann boundary condition .... - load_number = boundaryLoadArray.at(2 * i - 1); - load_id = boundaryLoadArray.at(2 * i); - load = domain->giveLoad(load_number); - ltype = load->giveBCGeoType(); + int load_number = boundaryLoadArray.at(2 * i - 1); + int load_id = boundaryLoadArray.at(2 * i); + auto load = domain->giveLoad(load_number); + auto ltype = load->giveBCGeoType(); if ( ltype == EdgeLoadBGT ) { this->computeEdgeBCSubVectorAt(vec, load, load_id, tStep, mode, 0); @@ -188,21 +175,17 @@ void Tr1Darcy :: computeEdgeBCSubVectorAt(FloatArray &answer, Load *load, int iE answer.zero(); if ( load->giveType() == TransmissionBC ) { // Neumann boundary conditions (traction) - BoundaryLoad *boundaryLoad; - boundaryLoad = static_cast< BoundaryLoad * >(load); + auto boundaryLoad = static_cast< BoundaryLoad * >(load); int numberOfEdgeIPs; numberOfEdgeIPs = ( int ) ceil( ( boundaryLoad->giveApproxOrder() + 1. ) / 2. ) * 2; GaussIntegrationRule iRule(1, this, 1, 1); - FloatArray N, loadValue, reducedAnswer; - reducedAnswer.resize(3); - reducedAnswer.zero(); - IntArray mask; + FloatArray N, loadValue, reducedAnswer(3); iRule.SetUpPointsOnLine(numberOfEdgeIPs, _Unknown); - for ( GaussPoint *gp: iRule ) { + for ( auto &gp: iRule ) { const FloatArray &lcoords = gp->giveNaturalCoordinates(); this->interpolation_lin.edgeEvalN( N, iEdge, lcoords, FEIElementGeometryWrapper(this) ); double dV = this->computeEdgeVolumeAround(gp, iEdge); @@ -218,7 +201,7 @@ void Tr1Darcy :: computeEdgeBCSubVectorAt(FloatArray &answer, Load *load, int iE reducedAnswer.add(loadValue.at(1) * dV, N); } - this->interpolation_lin.computeLocalEdgeMapping(mask, iEdge); + const auto &mask = this->interpolation_lin.computeLocalEdgeMapping(iEdge); answer.assemble(reducedAnswer, mask); } } @@ -238,9 +221,6 @@ double Tr1Darcy :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) void Tr1Darcy :: giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) { - /* - * Compute characteristic matrix for this element. The only option is the stiffness matrix... - */ if ( mtrx == ConductivityMatrix || mtrx == TangentStiffnessMatrix ) { this->computeStiffnessMatrix(answer, TangentStiffness, tStep); } else { @@ -257,10 +237,9 @@ void Tr1Darcy :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) { - CrossSection *cs = this->giveCrossSection(); ///@todo Write support function for getting the closest gp given local c.s. and use that here - GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); - cs->giveIPValue(answer, gp, type, tStep); + auto gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0); + this->giveCrossSection()->giveIPValue(answer, gp, type, tStep); } Interface * @@ -270,7 +249,7 @@ Tr1Darcy :: giveInterface(InterfaceType interface) return static_cast< NodalAveragingRecoveryModelInterface * >(this); } - return NULL; + return nullptr; } int diff --git a/src/tm/tr1darcy.h b/src/tm/Elements/tr1darcy.h similarity index 58% rename from src/tm/tr1darcy.h rename to src/tm/Elements/tr1darcy.h index 159548237..e818b4ea9 100644 --- a/src/tm/tr1darcy.h +++ b/src/tm/Elements/tr1darcy.h @@ -35,7 +35,7 @@ #ifndef tr1darcy_h_ #define tr1darcy_h_ -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "nodalaveragingrecoverymodel.h" #define _IFT_Tr1Darcy_Name "tr1darcy" @@ -55,33 +55,32 @@ class Tr1Darcy : public TransportElement, public NodalAveragingRecoveryModelInte public: Tr1Darcy(int, Domain *); - virtual ~Tr1Darcy(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual FEInterpolation *giveInterpolation() const; + void initializeFrom(InputRecord &ir) override; - virtual MaterialMode giveMaterialMode() { return _2dHeat; } ///@todo This isn't actually correct. + FEInterpolation *giveInterpolation() const override; - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; - virtual void giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, TimeStep *tStep); - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep); - virtual void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); + MaterialMode giveMaterialMode() override { return _2dHeat; } ///@todo This isn't actually correct. - virtual void computeGaussPoints(); - virtual int computeNumberOfDofs(); + void giveDofManDofIDMask(int inode, IntArray &answer) const override; + void giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode, TimeStep *tStep) override; + void giveCharacteristicMatrix(FloatMatrix &answer, CharType mtrx, TimeStep *tStep) override; + void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode mode, TimeStep *tStep); - virtual void computeExternalForcesVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode); + void computeGaussPoints() override; + int computeNumberOfDofs() override; + + void computeExternalForcesVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode) override; void computeEdgeBCSubVectorAt(FloatArray &answer, Load *load, int iEdge, TimeStep *tStep, ValueModeType mode, int indx); - virtual void computeInternalForcesVector(FloatArray &answer, TimeStep *tStep); + void computeInternalForcesVector(FloatArray &answer, TimeStep *tStep) override; - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual double giveThicknessAt(const FloatArray &gcoords); + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + double giveThicknessAt(const FloatArray &gcoords) override; - // From NodalAveragingRecoveryModelInterface - virtual const char *giveInputRecordName() const { return _IFT_Tr1Darcy_Name; } - virtual const char *giveClassName() const { return "Tr1Darcy"; } - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); - virtual Interface *giveInterface(InterfaceType interface); + const char *giveInputRecordName() const override { return _IFT_Tr1Darcy_Name; } + const char *giveClassName() const override { return "Tr1Darcy"; } + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; + Interface *giveInterface(InterfaceType interface) override; }; } diff --git a/src/tm/transportelement.C b/src/tm/Elements/transportelement.C similarity index 94% rename from src/tm/transportelement.C rename to src/tm/Elements/transportelement.C index e5cb8c069..dacfe2fe3 100644 --- a/src/tm/transportelement.C +++ b/src/tm/Elements/transportelement.C @@ -32,9 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "domain.h" -#include "transportmaterial.h" +#include "tm/Materials/transportmaterial.h" #include "load.h" #include "bodyload.h" #include "boundaryload.h" @@ -48,13 +48,14 @@ #include "crosssection.h" #include "transportcrosssection.h" #include "feinterpol.h" +#include "feinterpol1d.h" #include "feinterpol2d.h" #include "feinterpol3d.h" #include "dof.h" -#include "stationarytransportproblem.h" +#include "tm/EngineeringModels/stationarytransportproblem.h" #include "function.h" #ifdef __CEMHYD_MODULE - #include "cemhyd/cemhydmat.h" + #include "tm/Materials/cemhyd/cemhydmat.h" #endif @@ -72,8 +73,13 @@ TransportElement :: TransportElement(int n, Domain *aDomain, ElementMode em) : } -TransportElement :: ~TransportElement() -{ } +void +TransportElement :: initializeFrom(InputRecord &ir) +{ + Element::initializeFrom(ir); + this->vofFunction = 0; + IR_GIVE_OPTIONAL_FIELD(ir, vofFunction, _IFT_TransportElement_vof_function); +} void @@ -287,13 +293,12 @@ TransportElement :: giveEdgeDofMapping(IntArray &answer, int iEdge) { FEInterpolation *interp = this->giveInterpolation(); if ( dynamic_cast< FEInterpolation2d * >(interp) ) { - dynamic_cast< FEInterpolation2d * >(interp)->computeLocalEdgeMapping(answer, iEdge); + answer = dynamic_cast< FEInterpolation2d * >(interp)->computeLocalEdgeMapping(iEdge); } else if ( dynamic_cast< FEInterpolation3d * >(interp) ) { - dynamic_cast< FEInterpolation3d * >(interp)->computeLocalEdgeMapping(answer, iEdge); + answer = dynamic_cast< FEInterpolation3d * >(interp)->computeLocalEdgeMapping(iEdge); } } - void TransportElement :: computeSurfaceNAt(FloatArray &answer, int iSurf, const FloatArray &lcoord) { @@ -308,7 +313,7 @@ TransportElement :: giveSurfaceDofMapping(IntArray &answer, int iSurf) { FEInterpolation *interp = this->giveInterpolation(); if ( dynamic_cast< FEInterpolation3d * >(interp) ) { - dynamic_cast< FEInterpolation3d * >(interp)->computeLocalSurfaceMapping(answer, iSurf); + answer = dynamic_cast< FEInterpolation3d * >(interp)->computeLocalSurfaceMapping(iSurf); } } @@ -616,8 +621,7 @@ TransportElement :: computeBoundarySurfaceLoadVector(FloatArray &answer, Boundar std :: unique_ptr< IntegrationRule > iRule( this->giveBoundarySurfaceIntegrationRule(load->giveApproxOrder() + interp->giveInterpolationOrder(), boundary) ); if ( load->giveType() == ConvectionBC || load->giveType() == RadiationBC ) { - IntArray bNodes; - interp->boundaryGiveNodes(bNodes, boundary); + const auto &bNodes = interp->boundaryGiveNodes(boundary); this->computeBoundaryVectorOf(bNodes, dofid, VM_TotalIntrinsic, tStep, unknowns); } @@ -690,8 +694,8 @@ TransportElement :: computeTangentFromSurfaceLoad(FloatMatrix &answer, SurfaceLo if ( unknownsPerNode != 1 ) { OOFEM_ERROR("Load property multexpr not implemented for coupled fields"); } - IntArray dofid, bNodes; - interp->boundaryGiveNodes(bNodes, boundary); + IntArray dofid; + const auto &bNodes = interp->boundaryGiveNodes(boundary); this->giveElementDofIDMask(dofid); this->computeBoundaryVectorOf(bNodes, dofid, VM_TotalIntrinsic, tStep, unknowns); } @@ -738,9 +742,9 @@ TransportElement :: computeTangentFromEdgeLoad(FloatMatrix &answer, EdgeLoad *lo std :: unique_ptr< IntegrationRule > iRule( this->giveBoundaryEdgeIntegrationRule(load->giveApproxOrder() + interp->giveInterpolationOrder(), boundary) ); if ( load->propertyMultExpr.isDefined() ) { - IntArray bNodes, dofid; + IntArray dofid; this->giveElementDofIDMask(dofid); - interp->boundaryEdgeGiveNodes(bNodes, boundary); + const auto &bNodes = interp->boundaryEdgeGiveNodes(boundary); this->giveElementDofIDMask(dofid); this->computeBoundaryVectorOf(bNodes, dofid, VM_TotalIntrinsic, tStep, unknowns); } @@ -800,9 +804,9 @@ TransportElement :: computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLo // get solution vector for InternalForcesVector (Convention or radiation) if ( load->giveType() == ConvectionBC || load->giveType() == RadiationBC ) { - IntArray bNodes, dofid; + IntArray dofid; this->giveElementDofIDMask(dofid); - interp->boundaryEdgeGiveNodes(bNodes, boundary); + const auto &bNodes = interp->boundaryEdgeGiveNodes(boundary); this->computeBoundaryVectorOf(bNodes, dofid, VM_TotalIntrinsic, tStep, unknowns); } @@ -819,10 +823,12 @@ TransportElement :: computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLo FieldPtr tf = domain->giveEngngModel()->giveContext()->giveFieldManager()->giveField(FT_TemperatureAmbient); if ( tf ) { + interp->boundaryLocal2Global( gcoords, boundary, lcoords, FEIElementGeometryWrapper(this) ); tf->evaluateAt(val, gcoords, VM_TotalIntrinsic, tStep); } else if ( load->giveFormulationType() == Load :: FT_Entity ) { load->computeValueAt(val, tStep, lcoords, mode); } else { + interp->boundaryLocal2Global( gcoords, boundary, lcoords, FEIElementGeometryWrapper(this) ); load->computeValueAt(val, tStep, gcoords, mode); } @@ -1038,6 +1044,7 @@ void TransportElement :: computeSurfaceBCSubVectorAt(FloatArray &answer, Load *load, int iSurf, TimeStep *tStep, ValueModeType mode, int indx) { + // OOFEM_ERROR("STOP"); if ( !this->testElementExtension(Element_SurfaceLoadSupport) ) { OOFEM_ERROR("no surface load support"); } @@ -1050,11 +1057,11 @@ TransportElement :: computeSurfaceBCSubVectorAt(FloatArray &answer, Load *load, answer.resize( this->giveNumberOfDofManagers() ); answer.zero(); - double coeff=0.; - int approxOrder = surfLoad->giveApproxOrder() + this->giveApproxOrder(indx); + double coeff = 0.; + int approxOrder = surfLoad->giveApproxOrder(); - std :: unique_ptr< IntegrationRule > iRule( this->GetSurfaceIntegrationRule(approxOrder) ); - for ( GaussPoint *gp: *iRule ) { + auto iRule = this->giveBoundarySurfaceIntegrationRule(approxOrder, iSurf); + for ( auto &gp: *iRule ) { if ( load->giveType() == TransmissionBC ) { coeff = -1.0; } else if ( load->giveType() == ConvectionBC ) { @@ -1085,15 +1092,15 @@ TransportElement :: computeSurfaceBCSubVectorAt(FloatArray &answer, Load *load, double dV = this->computeSurfaceVolumeAround(gp, iSurf); FieldPtr tf; - if (tf = domain->giveEngngModel()->giveContext()->giveFieldManager()->giveField(FT_TemperatureAmbient)){ - //this->computeSurfIpGlobalCoords(gcoords, gp->giveNaturalCoordinates(), iSurf); - this->giveInterpolation()->boundarySurfaceLocal2global(gcoords, iSurf, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this)); + if ( (tf = domain->giveEngngModel()->giveContext()->giveFieldManager()->giveField(FT_TemperatureAmbient)) ) { + //this->computeSurfIpGlobalCoords(gcoords, gp->giveNaturalCoordinates(), iSurf); + this->giveInterpolation()->boundarySurfaceLocal2global(gcoords, iSurf, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this)); tf->evaluateAt(val, gcoords, VM_TotalIntrinsic, tStep); } else if ( surfLoad->giveFormulationType() == Load :: FT_Entity ) { surfLoad->computeValueAt(val, tStep, gp->giveNaturalCoordinates(), mode); } else { - //this->computeSurfIpGlobalCoords(gcoords, gp->giveNaturalCoordinates(), iSurf); - this->giveInterpolation()->boundarySurfaceLocal2global(gcoords, iSurf, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this)); + //this->computeSurfIpGlobalCoords(gcoords, gp->giveNaturalCoordinates(), iSurf); + this->giveInterpolation()->boundarySurfaceLocal2global(gcoords, iSurf, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this)); surfLoad->computeValueAt(val, tStep, gcoords, mode); } @@ -1178,9 +1185,8 @@ TransportElement :: computeBCSubMtrxAt(FloatMatrix &answer, TimeStep *tStep, Val } defined = 1; - int approxOrder = 2 * this->giveApproxOrder(indx); - std :: unique_ptr< IntegrationRule > iRule( this->GetSurfaceIntegrationRule(approxOrder) ); - + int approxOrder = 2; + auto iRule = this->giveBoundarySurfaceIntegrationRule(approxOrder, id); for ( auto &gp: *iRule ) { this->computeSurfaceNAt( n, id, gp->giveNaturalCoordinates() ); double dV = this->computeSurfaceVolumeAround(gp, id); @@ -1314,8 +1320,8 @@ TransportElement :: computeFlow(FloatArray &answer, GaussPoint *gp, TimeStep *tS void TransportElement :: updateInternalState(TimeStep *tStep) -// Updates the receiver at the end of a solution step { + ///@todo This method should only used when applying IC (but nltransienttransport and nonstationarytransport uses it wrong, and they should be removed) FloatArray stateVector, r; #if 0 FloatArray gradient, flux; @@ -1330,13 +1336,17 @@ TransportElement :: updateInternalState(TimeStep *tStep) CemhydMat *cem = dynamic_cast< CemhydMat * >( mat ); cem->initMaterial(this); //create microstructures and statuses on specific GPs } -#endif //__CEMHYD_MODULE - +#endif //__CEMHYD_MODULE + this->giveElementDofIDMask(dofid); - this->computeVectorOf(dofid, VM_TotalIntrinsic, tStep, r); + if ( tStep->isIcApply() ) { + this->computeVectorOf(dofid, VM_Total, tStep, r); + } else { + this->computeVectorOf(dofid, VM_TotalIntrinsic, tStep, r); + } // force updating ip values for ( auto &iRule: integrationRulesArray ) { - for ( GaussPoint *gp: *iRule ) { + for ( auto &gp: *iRule ) { ///@todo Why is the state vector the unknown solution at the gauss point? / Mikael this->computeNmatrixAt( n, gp->giveNaturalCoordinates() ); @@ -1351,7 +1361,6 @@ TransportElement :: updateInternalState(TimeStep *tStep) #endif } } - } int @@ -1413,6 +1422,15 @@ TransportElement :: giveMaterial() return static_cast< TransportCrossSection* >( this->giveCrossSection() )->giveMaterial(); } +double +TransportElement::computeVof(TimeStep *tStep) +{ + if ( this->vofFunction ) { + return this->giveDomain()->giveFunction(this->vofFunction)->evaluateAtTime(tStep->giveTargetTime()); + } else { + return 1.0; + } +} #ifdef __OOFEG int diff --git a/src/tm/transportelement.h b/src/tm/Elements/transportelement.h similarity index 86% rename from src/tm/transportelement.h rename to src/tm/Elements/transportelement.h index 89aa92fc9..26d252db7 100644 --- a/src/tm/transportelement.h +++ b/src/tm/Elements/transportelement.h @@ -40,6 +40,8 @@ #include "primaryfield.h" #include "matresponsemode.h" +#define _IFT_TransportElement_vof_function "voffunction" + namespace oofem { class TransportCrossSection; @@ -57,15 +59,16 @@ class TransportElement : public Element, public EIPrimaryFieldInterface ElementMode emode; /// Stefan–Boltzmann constant W/m2/K4 static const double stefanBoltzmann; + /// Fuction determining the relative volume of reference material in element + int vofFunction = 0; public: TransportElement(int n, Domain * d, ElementMode em = HeatTransferEM); - virtual ~TransportElement(); - virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep); - virtual void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep); + void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep) override; + void giveCharacteristicVector(FloatArray &answer, CharType type, ValueModeType mode, TimeStep *tStep) override; - virtual void giveDofManDofIDMask(int inode, IntArray &answer) const; + void giveDofManDofIDMask(int inode, IntArray &answer) const override; virtual void computeInternalForcesVector(FloatArray &answer, TimeStep *tStep); virtual void computeExternalForcesVector(FloatArray &answer, TimeStep *tStep, ValueModeType mode); @@ -73,20 +76,22 @@ class TransportElement : public Element, public EIPrimaryFieldInterface virtual void computeLumpedCapacityVector(FloatArray &answer, TimeStep *tStep); //Compute volumetric load from element - virtual void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep); + void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override; //Boundary load by prescribed flux, convection, or radiation over surface - virtual void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true); + void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true) override; //Contribution to conductivity matrix from convection - virtual void computeTangentFromSurfaceLoad(FloatMatrix &answer, SurfaceLoad *load, int boundary, MatResponseMode rmode, TimeStep *tStep); - virtual void computeTangentFromEdgeLoad(FloatMatrix &answer, EdgeLoad *load, int boundary, MatResponseMode rmode, TimeStep *tStep); + void computeTangentFromSurfaceLoad(FloatMatrix &answer, SurfaceLoad *load, int boundary, MatResponseMode rmode, TimeStep *tStep) override; + void computeTangentFromEdgeLoad(FloatMatrix &answer, EdgeLoad *load, int boundary, MatResponseMode rmode, TimeStep *tStep) override; //Boundary load by prescribed flux, convection, or radiation over length - virtual void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int edge, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true); + void computeBoundaryEdgeLoadVector(FloatArray &answer, BoundaryLoad *load, int edge, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true) override; - virtual void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer); + void computeField(ValueModeType mode, TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer) override; TransportCrossSection * giveTransportCrossSection(); - virtual Material * giveMaterial(); - + Material * giveMaterial() override; + void initializeFrom(InputRecord &ir) override; + const char *giveClassName() const override { return "TransportElement"; } + /** * Gives the thickness at some global coordinate. * For solid elements, the value returned is 1.0 (which is the default implementation). @@ -117,21 +122,27 @@ class TransportElement : public Element, public EIPrimaryFieldInterface * @param tStep Time step. */ virtual void computeFlow(FloatArray &answer, GaussPoint *gp, TimeStep *tStep); + /** + * Computes the relative volume of reference material in element. + * Default implementation uses user provided function. + * @param tStep Time step + */ + virtual double computeVof(TimeStep *tStep); // time step termination - virtual void updateInternalState(TimeStep *tStep); - virtual int checkConsistency(); + void updateInternalState(TimeStep *tStep) override; + int checkConsistency() override; virtual int EIPrimaryFieldI_evaluateFieldVectorAt(FloatArray &answer, PrimaryField &pf, const FloatArray &coords, IntArray &dofId, ValueModeType mode, - TimeStep *tStep); + TimeStep *tStep) override; #ifdef __OOFEG int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, - int node, TimeStep *tStep); + int node, TimeStep *tStep) override; // Graphics output - //virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) {} - //virtual void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) {} + //void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep) override {} + //void drawDeformedGeometry(oofegGraphicContext &gc, TimeStep *tStep, UnknownType) override {} #endif /** @@ -244,9 +255,8 @@ class TransportElement : public Element, public EIPrimaryFieldInterface /** * Computes the length around a integration point on a edge. */ - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) = 0; + virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { return 0.; } - virtual IntegrationRule *GetSurfaceIntegrationRule(int approxOrder) { return NULL; } virtual void computeSurfaceNAt(FloatArray &answer, int iSurf, const FloatArray &lcoord); virtual double computeSurfaceVolumeAround(GaussPoint *gp, int iSurf) { return 0.; } virtual void giveSurfaceDofMapping(IntArray &mask, int iSurf); diff --git a/src/tm/traxisym1_ht.C b/src/tm/Elements/traxisym1_ht.C similarity index 76% rename from src/tm/traxisym1_ht.C rename to src/tm/Elements/traxisym1_ht.C index 6918233af..a8bf224e1 100644 --- a/src/tm/traxisym1_ht.C +++ b/src/tm/Elements/traxisym1_ht.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "traxisym1_ht.h" +#include "tm/Elements/traxisym1_ht.h" #include "fei2dtrlin.h" #include "gausspoint.h" #include "floatarray.h" @@ -46,21 +46,29 @@ namespace oofem { REGISTER_Element(TrAxisym1_ht); +REGISTER_Element(TrAxisym1_hmt); +REGISTER_Element(TrAxisym1_mt); TrAxisym1_ht :: TrAxisym1_ht(int n, Domain *aDomain) : Tr1_ht(n, aDomain) - // Constructor. { } -TrAxisym1_ht :: ~TrAxisym1_ht() -// Destructor -{ } +TrAxisym1_hmt :: TrAxisym1_hmt(int n, Domain *aDomain) : TrAxisym1_ht(n, aDomain) +{ + this->emode = HeatMass1TransferEM; // This could be done in a better way. +} + +TrAxisym1_mt :: TrAxisym1_mt(int n, Domain *aDomain) : TrAxisym1_ht(n, aDomain) +{ + this->emode = Mass1TransferEM; +} + + double TrAxisym1_ht :: computeVolumeAround(GaussPoint *gp) { - double determinant, weight; - determinant = fabs( this->interp.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); + double determinant = fabs( this->interp.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double weight = gp->giveWeight(); return determinant *weight *this->computeRadiusAt(gp); ///@todo What about 2*pi ? } @@ -74,11 +82,9 @@ double TrAxisym1_ht :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { FloatArray gcoords; - double determinant, radius; - - determinant = fabs( this->interp.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); + double determinant = fabs( this->interp.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); this->interp.edgeLocal2global( gcoords, iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - radius = gcoords.at(1); + double radius = gcoords.at(1); return determinant *radius *gp->giveWeight(); } diff --git a/src/tm/traxisym1_ht.h b/src/tm/Elements/traxisym1_ht.h similarity index 64% rename from src/tm/traxisym1_ht.h rename to src/tm/Elements/traxisym1_ht.h index 44a8b76f0..1e12e4a2f 100644 --- a/src/tm/traxisym1_ht.h +++ b/src/tm/Elements/traxisym1_ht.h @@ -35,9 +35,11 @@ #ifndef traxisym1_ht_h #define traxisym1_ht_h -#include "tr1_ht.h" +#include "tm/Elements/tr1_ht.h" #define _IFT_TrAxisym1_ht_Name "traxisym1ht" +#define _IFT_TrAxisym1_hmt_Name "traxisym1hmt" +#define _IFT_TrAxisym1_mt_Name "traxisym1mt" namespace oofem { /** @@ -47,18 +49,38 @@ class TrAxisym1_ht : public Tr1_ht { public: TrAxisym1_ht(int n, Domain * d); - virtual ~TrAxisym1_ht(); - virtual double computeVolumeAround(GaussPoint *gp); - virtual const char *giveInputRecordName() const { return _IFT_TrAxisym1_ht_Name; } - virtual const char *giveClassName() const { return "TrAxisym1_htElement"; } + double computeVolumeAround(GaussPoint *gp) override; + const char *giveInputRecordName() const override { return _IFT_TrAxisym1_ht_Name; } + const char *giveClassName() const override { return "TrAxisym1_htElement"; } - virtual double giveThicknessAt(const FloatArray &gcoords); + double giveThicknessAt(const FloatArray &gcoords) override; protected: double computeRadiusAt(GaussPoint *gp); - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - virtual int giveApproxOrder(int unknownIndx) { return 2; } + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; + int giveApproxOrder(int unknownIndx) override { return 2; } +}; +/** + * Same as TrAxisym1_ht but for heat+mass transfer. + */ +class TrAxisym1_hmt : public TrAxisym1_ht +{ +public: + TrAxisym1_hmt(int n, Domain * d); + + const char *giveClassName() const override { return "TrAxisym1_hmt"; } +}; + + +/** + * Class for mass transfer. + */ +class TrAxisym1_mt : public TrAxisym1_ht +{ +public: + TrAxisym1_mt(int n, Domain * d); + const char *giveClassName() const override { return "TrAxisym1_mt"; } }; } // end namespace oofem #endif // traxisym1_ht_h diff --git a/src/tm/wedge_ht.C b/src/tm/Elements/wedge_ht.C similarity index 89% rename from src/tm/wedge_ht.C rename to src/tm/Elements/wedge_ht.C index f3ea5fea4..40c2f85c7 100644 --- a/src/tm/wedge_ht.C +++ b/src/tm/Elements/wedge_ht.C @@ -33,7 +33,7 @@ */ -#include "wedge_ht.h" +#include "tm/Elements/wedge_ht.h" #include "fei3dwedgelin.h" #include "node.h" #include "gausspoint.h" @@ -53,7 +53,6 @@ REGISTER_Element(Wedge_ht); FEI3dWedgeLin Wedge_ht :: interpolation; Wedge_ht :: Wedge_ht(int n, Domain *aDomain) : TransportElement(n, aDomain, HeatTransferEM), SpatialLocalizerInterface(this), ZZNodalRecoveryModelInterface(this), SPRNodalRecoveryModelInterface() - // Constructor. { numberOfDofMans = 6; } @@ -69,11 +68,11 @@ Wedge_mt :: Wedge_mt(int n, Domain *aDomain) : Wedge_ht(n, aDomain) } -IRResultType -Wedge_ht :: initializeFrom(InputRecord *ir) +void +Wedge_ht :: initializeFrom(InputRecord &ir) { numberOfGaussPoints = 6; - return TransportElement :: initializeFrom(ir); + TransportElement :: initializeFrom(ir); } @@ -83,7 +82,7 @@ Wedge_ht :: computeGaussPoints() { if ( integrationRulesArray.size() == 0 ) { integrationRulesArray.resize( 1 ); - integrationRulesArray [ 0 ].reset( new GaussIntegrationRule(1, this, 1, 2) ); + integrationRulesArray [ 0 ] = std::make_unique(1, this, 1, 2); this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], numberOfGaussPoints, this); } } @@ -91,15 +90,12 @@ Wedge_ht :: computeGaussPoints() double Wedge_ht :: computeVolumeAround(GaussPoint *gp) -// Returns the portion of the receiver which is attached to gp. { - double determinant, weight, volume; - determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), + double determinant = fabs( this->interpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) ); - weight = gp->giveWeight(); - volume = determinant * weight; - return volume; + double weight = gp->giveWeight(); + return determinant * weight; } @@ -109,7 +105,7 @@ Wedge_ht :: computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { double result = this->interpolation.edgeGiveTransformationJacobian( iEdge, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ); - return result *gp->giveWeight(); + return result * gp->giveWeight(); } @@ -133,7 +129,7 @@ Wedge_ht :: giveInterface(InterfaceType interface) } OOFEM_LOG_INFO("Interface on Lwedge element not supported"); - return NULL; + return nullptr; } void diff --git a/src/tm/wedge_ht.h b/src/tm/Elements/wedge_ht.h similarity index 59% rename from src/tm/wedge_ht.h rename to src/tm/Elements/wedge_ht.h index 6dbad3624..d0ce61440 100644 --- a/src/tm/wedge_ht.h +++ b/src/tm/Elements/wedge_ht.h @@ -32,18 +32,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - #ifndef wedge_ht_h #define wedge_ht_h - -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "spatiallocalizer.h" #include "zznodalrecoverymodel.h" #include "sprnodalrecoverymodel.h" #include "nodalaveragingrecoverymodel.h" - #define _IFT_Wedge_ht_Name "wedgeht" #define _IFT_Wedge_hmt_Name "wedgehmt" #define _IFT_Wedge_mt_Name "wedgemt" @@ -61,39 +58,34 @@ class FEI3dWedgeLin; public: Wedge_ht(int, Domain *); - virtual ~Wedge_ht() { } - - virtual double computeVolumeAround(GaussPoint *gp); - virtual FEInterpolation *giveInterpolation() const; + double computeVolumeAround(GaussPoint *gp) override; + FEInterpolation *giveInterpolation() const override; // definition & identification - virtual const char *giveInputRecordName() const { return _IFT_Wedge_ht_Name; } - virtual const char *giveClassName() const { return "Wedge_ht"; } + const char *giveInputRecordName() const override { return _IFT_Wedge_ht_Name; } + const char *giveClassName() const override { return "Wedge_ht"; } - virtual int computeNumberOfDofs() { return 6; } - virtual IRResultType initializeFrom(InputRecord *ir); - virtual MaterialMode giveMaterialMode() { return _3dHeat; } + int computeNumberOfDofs() override { return 6; } + void initializeFrom(InputRecord &ir) override; + MaterialMode giveMaterialMode() override { return _3dHeat; } - virtual Interface *giveInterface(InterfaceType t); - virtual int testElementExtension(ElementExtension ext) + Interface *giveInterface(InterfaceType t) override; + int testElementExtension(ElementExtension ext) override { return ( ext == Element_EdgeLoadSupport );} - virtual void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap); - virtual void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap); - virtual int SPRNodalRecoveryMI_giveNumberOfIP(); - virtual SPRPatchType SPRNodalRecoveryMI_givePatchType(); - virtual void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep); + void SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap) override; + void SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap) override; + int SPRNodalRecoveryMI_giveNumberOfIP() override; + SPRPatchType SPRNodalRecoveryMI_givePatchType() override; + void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override; protected: - virtual void computeGaussPoints(); - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge); - - + void computeGaussPoints() override; + double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) override; }; - /** * Class for heat and mass transfer. */ @@ -102,10 +94,10 @@ class Wedge_hmt : public Wedge_ht public: Wedge_hmt(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_Wedge_hmt_Name; } - virtual const char *giveClassName() const { return "Wedge_hmt"; } - virtual int computeNumberOfDofs() { return 12; } - virtual MaterialMode giveMaterialMode() { return _3dHeMo; } + const char *giveInputRecordName() const override { return _IFT_Wedge_hmt_Name; } + const char *giveClassName() const override { return "Wedge_hmt"; } + int computeNumberOfDofs() override { return 12; } + MaterialMode giveMaterialMode() override { return _3dHeMo; } }; /** @@ -116,12 +108,11 @@ class Wedge_mt : public Wedge_ht public: Wedge_mt(int n, Domain * d); - virtual const char *giveInputRecordName() const { return _IFT_Wedge_mt_Name; } - virtual const char *giveClassName() const { return "Wedge_mt"; } - virtual int computeNumberOfDofs() { return 6; } - virtual MaterialMode giveMaterialMode() { return _3dHeat; } + const char *giveInputRecordName() const override { return _IFT_Wedge_mt_Name; } + const char *giveClassName() const override { return "Wedge_mt"; } + int computeNumberOfDofs() override { return 6; } + MaterialMode giveMaterialMode() override { return _3dHeat; } }; - } // end namespace oofem #endif diff --git a/src/tm/nltransienttransportproblem.C b/src/tm/EngineeringModels/nltransienttransportproblem.C similarity index 96% rename from src/tm/nltransienttransportproblem.C rename to src/tm/EngineeringModels/nltransienttransportproblem.C index 8a4f5ad58..3ac255324 100644 --- a/src/tm/nltransienttransportproblem.C +++ b/src/tm/EngineeringModels/nltransienttransportproblem.C @@ -32,13 +32,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "nltransienttransportproblem.h" +#include "tm/EngineeringModels/nltransienttransportproblem.h" #include "timestep.h" #include "element.h" #include "dofmanager.h" #include "dof.h" #include "verbose.h" -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "classfactory.h" #include "mathfem.h" #include "assemblercallback.h" @@ -47,23 +47,14 @@ namespace oofem { REGISTER_EngngModel(NLTransientTransportProblem); -NLTransientTransportProblem :: NLTransientTransportProblem(int i, EngngModel *_master = NULL) : NonStationaryTransportProblem(i, _master) +NLTransientTransportProblem :: NLTransientTransportProblem(int i, EngngModel *_master = nullptr) : NonStationaryTransportProblem(i, _master) { - //constructor } -NLTransientTransportProblem :: ~NLTransientTransportProblem() -{ - //destructor -} - -IRResultType -NLTransientTransportProblem :: initializeFrom(InputRecord *ir) +void +NLTransientTransportProblem :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = NonStationaryTransportProblem :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + NonStationaryTransportProblem :: initializeFrom(ir); int val = 30; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_NLTransientTransportProblem_nsmax); @@ -79,8 +70,6 @@ NLTransientTransportProblem :: initializeFrom(InputRecord *ir) } else { NR_Mode = nrsolverModifiedNRM; } - - return IRRT_OK; } TimeStep * @@ -110,7 +99,7 @@ void NLTransientTransportProblem :: solveYourselfAt(TimeStep *tStep) //Delete lhs matrix and create a new one. This is necessary due to growing/decreasing number of equations. if ( tStep->isTheFirstStep() || this->changingProblemSize ) { - conductivityMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + conductivityMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( !conductivityMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } @@ -124,7 +113,7 @@ void NLTransientTransportProblem :: solveYourselfAt(TimeStep *tStep) //create previous solution from IC or from previous tStep if ( tStep->isTheFirstStep() ) { if ( !stepWhenIcApply ) { - stepWhenIcApply.reset( new TimeStep( *tStep->givePreviousStep() ) ); + stepWhenIcApply = std::make_unique( *tStep->givePreviousStep() ); } this->applyIC(stepWhenIcApply.get()); //insert solution to hash=1(previous), if changes in equation numbering } diff --git a/src/tm/nltransienttransportproblem.h b/src/tm/EngineeringModels/nltransienttransportproblem.h similarity index 71% rename from src/tm/nltransienttransportproblem.h rename to src/tm/EngineeringModels/nltransienttransportproblem.h index 0cae76ccc..a54429d82 100644 --- a/src/tm/nltransienttransportproblem.h +++ b/src/tm/EngineeringModels/nltransienttransportproblem.h @@ -35,7 +35,7 @@ #ifndef nltransienttransportproblem_h #define nltransienttransportproblem_h -#include "nonstationarytransportproblem.h" +#include "tm/EngineeringModels/nonstationarytransportproblem.h" #include "sparselinsystemnm.h" #include "sparsemtrx.h" @@ -61,39 +61,36 @@ class NLTransientTransportProblem : public NonStationaryTransportProblem protected: enum nlttp_ModeType { nrsolverModifiedNRM, nrsolverFullNRM, nrsolverAccelNRM }; - double rtol; - int nsmax; - nlttp_ModeType NR_Mode; - int MANRMSteps; - int currentIterations; + double rtol = 0.; + int nsmax = 0; + nlttp_ModeType NR_Mode = nrsolverModifiedNRM; + int MANRMSteps = 0; + int currentIterations = 0; public: - /// Constructor. NLTransientTransportProblem(int i, EngngModel * _master); - /// Destructor. - virtual ~NLTransientTransportProblem(); - virtual TimeStep* giveNextStep(); - virtual void solveYourselfAt(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); - virtual double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof); + TimeStep* giveNextStep() override; + void solveYourselfAt(TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override; + double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; // identification - virtual const char *giveInputRecordName() const { return _IFT_NLTransientTransportProblem_Name; } - virtual const char *giveClassName() const { return "NLTransientTransportProblem"; } - virtual fMode giveFormulation() { return nonLinFormulation; } - virtual int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep); - virtual void updateDofUnknownsDictionary(DofManager *dman, TimeStep *tStep); + const char *giveInputRecordName() const { return _IFT_NLTransientTransportProblem_Name; } + const char *giveClassName() const override { return "NLTransientTransportProblem"; } + fMode giveFormulation() override { return nonLinFormulation; } + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override; + void updateDofUnknownsDictionary(DofManager *dman, TimeStep *tStep) override; - virtual int giveCurrentNumberOfIterations() {return currentIterations;} + int giveCurrentNumberOfIterations() override { return currentIterations; } protected: - virtual void updateInternalState(TimeStep *tStep); - virtual void applyIC(TimeStep *tStep); + void updateInternalState(TimeStep *tStep) override; + void applyIC(TimeStep *tStep) override; void createPreviousSolutionInDofUnknownsDictionary(TimeStep *tStep); - void assembleAlgorithmicPartOfRhs(FloatArray &rhs, const UnknownNumberingScheme &s, TimeStep *tStep); + void assembleAlgorithmicPartOfRhs(FloatArray &rhs, const UnknownNumberingScheme &s, TimeStep *tStep) override; }; } // end namespace oofem #endif // nltransienttransportproblem_h diff --git a/src/tm/nonstationarytransportproblem.C b/src/tm/EngineeringModels/nonstationarytransportproblem.C similarity index 86% rename from src/tm/nonstationarytransportproblem.C rename to src/tm/EngineeringModels/nonstationarytransportproblem.C index d7ebf4a4f..255269689 100644 --- a/src/tm/nonstationarytransportproblem.C +++ b/src/tm/EngineeringModels/nonstationarytransportproblem.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "nonstationarytransportproblem.h" -#include "stationarytransportproblem.h" +#include "tm/EngineeringModels/nonstationarytransportproblem.h" +#include "tm/EngineeringModels/stationarytransportproblem.h" #include "nummet.h" #include "timestep.h" #include "element.h" @@ -41,7 +41,7 @@ #include "dof.h" #include "maskedprimaryfield.h" #include "verbose.h" -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "classfactory.h" #include "datastream.h" #include "contextioerr.h" @@ -50,7 +50,7 @@ #include "unknownnumberingscheme.h" #ifdef __CEMHYD_MODULE - #include "cemhyd/cemhydmat.h" + #include "tm/Materials/cemhyd/cemhydmat.h" #endif namespace oofem { @@ -87,19 +87,7 @@ void IntSourceLHSAssembler :: matrixFromElement(FloatMatrix &answer, Element &el } -NonStationaryTransportProblem :: NonStationaryTransportProblem(int i, EngngModel *_master = NULL) : StationaryTransportProblem(i, _master) -{ - ndomains = 1; - lumpedCapacityStab = 0; - initT = 0.; - deltaT = 0.; - dtFunction = 0; - internalVarUpdateStamp = 0; - changingProblemSize = false; - solverType = ST_Direct; -} - -NonStationaryTransportProblem :: ~NonStationaryTransportProblem() +NonStationaryTransportProblem :: NonStationaryTransportProblem(int i, EngngModel *_master = nullptr) : StationaryTransportProblem(i, _master) { } @@ -107,10 +95,9 @@ NonStationaryTransportProblem :: ~NonStationaryTransportProblem() NumericalMethod *NonStationaryTransportProblem :: giveNumericalMethod(MetaStep *mStep) // only one has reason for LinearStatic // - SolutionOfLinearEquations - { - if (!linSolver) { - linSolver.reset( classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this) ); + if ( !linSolver ) { + linSolver = classFactory.createSparseLinSolver(solverType, this->giveDomain(1), this); if ( !linSolver ) { OOFEM_ERROR("linear solver creation failed for lstype %d", solverType); } @@ -118,27 +105,23 @@ NumericalMethod *NonStationaryTransportProblem :: giveNumericalMethod(MetaStep * return linSolver.get(); } -IRResultType -NonStationaryTransportProblem :: initializeFrom(InputRecord *ir) +void +NonStationaryTransportProblem :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = EngngModel :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + EngngModel :: initializeFrom(ir); - if ( ir->hasField(_IFT_NonStationaryTransportProblem_initt) ) { + if ( ir.hasField(_IFT_NonStationaryTransportProblem_initt) ) { IR_GIVE_FIELD(ir, initT, _IFT_NonStationaryTransportProblem_initt); } - if ( ir->hasField(_IFT_NonStationaryTransportProblem_deltat) ) { + if ( ir.hasField(_IFT_NonStationaryTransportProblem_deltat) ) { IR_GIVE_FIELD(ir, deltaT, _IFT_NonStationaryTransportProblem_deltat); - } else if ( ir->hasField(_IFT_NonStationaryTransportProblem_deltatfunction) ) { + } else if ( ir.hasField(_IFT_NonStationaryTransportProblem_deltatfunction) ) { IR_GIVE_FIELD(ir, dtFunction, _IFT_NonStationaryTransportProblem_deltatfunction); - } else if ( ir->hasField(_IFT_NonStationaryTransportProblem_prescribedtimes) ) { + } else if ( ir.hasField(_IFT_NonStationaryTransportProblem_prescribedtimes) ) { IR_GIVE_FIELD(ir, discreteTimes, _IFT_NonStationaryTransportProblem_prescribedtimes); } else { - OOFEM_WARNING("Time step not defined"); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, "none", "Time step not defined"); } IR_GIVE_FIELD(ir, alpha, _IFT_NonStationaryTransportProblem_alpha); @@ -146,16 +129,16 @@ NonStationaryTransportProblem :: initializeFrom(InputRecord *ir) * if (this->giveNumericalMethod (giveCurrentStep())) nMethod -> instanciateFrom (ir); */ // read lumped capacity stabilization flag - if ( ir->hasField(_IFT_NonStationaryTransportProblem_lumpedcapa) ) { + if ( ir.hasField(_IFT_NonStationaryTransportProblem_lumpedcapa) ) { lumpedCapacityStab = 1; } //secure equation renumbering, otherwise keep efficient algorithms - if ( ir->hasField(_IFT_NonStationaryTransportProblem_changingproblemsize) ) { + if ( ir.hasField(_IFT_NonStationaryTransportProblem_changingproblemsize) ) { changingProblemSize = true; - UnknownsField.reset( new DofDistributedPrimaryField(this, 1, FT_TransportProblemUnknowns, 1) ); + UnknownsField = std::make_unique(this, 1, FT_TransportProblemUnknowns, 1); } else { - UnknownsField.reset( new PrimaryField(this, 1, FT_TransportProblemUnknowns, 1) ); + UnknownsField = std::make_unique(this, 1, FT_TransportProblemUnknowns, 1); } //read other input data from StationaryTransportProblem @@ -164,9 +147,6 @@ NonStationaryTransportProblem :: initializeFrom(InputRecord *ir) int val = 0; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_lstype); solverType = ( LinSystSolverType ) val; - - - return IRRT_OK; } @@ -211,8 +191,8 @@ NonStationaryTransportProblem :: giveSolutionStepWhenIcApply(bool force) return master->giveSolutionStepWhenIcApply(); } else { if ( !stepWhenIcApply ) { - stepWhenIcApply.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, this->initT - giveDeltaT ( giveNumberOfFirstStep() ), giveDeltaT ( giveNumberOfFirstStep() ), 0) ); - //stepWhenIcApply.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, -deltaT, deltaT, 0) ); + stepWhenIcApply = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 0, this->initT - giveDeltaT( giveNumberOfFirstStep() ), giveDeltaT( giveNumberOfFirstStep() ), 0); + //stepWhenIcApply = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 0, -deltaT, deltaT, 0); } return stepWhenIcApply.get(); @@ -275,11 +255,11 @@ NonStationaryTransportProblem :: giveNextStep() counter = currentStep->giveSolutionStateCounter() + 1; } else { // first step -> generate initial step - currentStep.reset( new TimeStep( *giveSolutionStepWhenIcApply() ) ); + currentStep = std::make_unique( *giveSolutionStepWhenIcApply() ); } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(istep, this, 1, totalTime, this->giveDeltaT ( istep ), counter) ); + currentStep = std::make_unique(istep, this, 1, totalTime, this->giveDeltaT ( istep ), counter); //set intrinsic time to time of integration intrinsicTime = currentStep->giveTargetTime(); // intrinsicTime = previousStep->giveTargetTime() + this->alpha *this->giveDeltaT(istep); @@ -328,7 +308,7 @@ void NonStationaryTransportProblem :: solveYourselfAt(TimeStep *tStep) //Create a new lhs matrix if necessary if ( tStep->isTheFirstStep() || this->changingProblemSize ) { - conductivityMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + conductivityMatrix = classFactory.createSparseMtrx(sparseMtrxType); if ( !conductivityMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } @@ -473,63 +453,20 @@ NonStationaryTransportProblem :: updateInternalState(TimeStep *tStep) } } -contextIOResultType + +void NonStationaryTransportProblem :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = EngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = UnknownsField->saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + EngngModel :: saveContext(stream, mode); + UnknownsField->saveContext(stream); } - -contextIOResultType -NonStationaryTransportProblem :: restoreContext(DataStream *stream, ContextMode mode, void *obj) -// -// restore state variable - displacement vector -// +void +NonStationaryTransportProblem :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - int closeFlag = 0; - int istep, iversion; - FILE *file = NULL; - - this->resolveCorrespondingStepNumber(istep, iversion, obj); - - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - - if ( ( iores = EngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = UnknownsField->restoreContext(*stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } - - // ensure consistent records - - return CIO_OK; + EngngModel :: restoreContext(stream, mode); + UnknownsField->restoreContext(stream); } diff --git a/src/tm/nonstationarytransportproblem.h b/src/tm/EngineeringModels/nonstationarytransportproblem.h similarity index 76% rename from src/tm/nonstationarytransportproblem.h rename to src/tm/EngineeringModels/nonstationarytransportproblem.h index 97f8c0475..7f04c9485 100644 --- a/src/tm/nonstationarytransportproblem.h +++ b/src/tm/EngineeringModels/nonstationarytransportproblem.h @@ -39,8 +39,8 @@ #include "sparsemtrx.h" #include "primaryfield.h" #include "dofdistributedprimaryfield.h" -#include "transportmaterial.h" -#include "stationarytransportproblem.h" +#include "tm/Materials/transportmaterial.h" +#include "tm/EngineeringModels/stationarytransportproblem.h" #include "linsystsolvertype.h" ///@name Input fields for NonStationaryTransportProblem @@ -67,10 +67,10 @@ namespace oofem { class TransportExternalForceAssembler : public VectorAssembler { public: - virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const; + void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const override; }; - + /** * Callback class for assembling mid point effective tangents * @author Mikael Öhman @@ -83,7 +83,7 @@ class MidpointLhsAssembler : public MatrixAssembler public: MidpointLhsAssembler(bool lumped, double alpha); - virtual void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const; + void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const override; }; @@ -94,7 +94,7 @@ class MidpointLhsAssembler : public MatrixAssembler class IntSourceLHSAssembler : public MatrixAssembler { public: - virtual void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const; + void matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const override; }; @@ -111,63 +111,60 @@ class NonStationaryTransportProblem : public StationaryTransportProblem */ StateCounterType internalVarUpdateStamp; - LinSystSolverType solverType; ///@todo Remove this and use nonlinear methods. + LinSystSolverType solverType = ST_Direct; ///@todo Remove this and use nonlinear methods. std :: unique_ptr< SparseLinearSystemNM > linSolver; ///@todo Remove this and use nonlinear methods. /// Right hand side vector from boundary conditions. FloatArray bcRhs; /// Initial time from which the computation runs. Default is zero. - double initT; + double initT = 0.; /// Length of time step. - double deltaT; - double alpha; + double deltaT = 0.; + double alpha = 0.; /// If set then stabilization using lumped capacity will be used. - int lumpedCapacityStab; + int lumpedCapacityStab = 0; /// Associated time function for time step increment. - int dtFunction; + int dtFunction = 0; /// Specified times where the problem is solved FloatArray discreteTimes; /// Determines if there are change in the problem size (no application/removal of Dirichlet boundary conditions). - bool changingProblemSize; + bool changingProblemSize = false; public: - /// Constructor. NonStationaryTransportProblem(int i, EngngModel * _master); - /// Destructor. - virtual ~NonStationaryTransportProblem(); - virtual void solveYourselfAt(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); - virtual double giveUnknownComponent(ValueModeType, TimeStep *, Domain *, Dof *); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void solveYourselfAt(TimeStep *tStep) override; + void updateYourself(TimeStep *tStep) override; + double giveUnknownComponent(ValueModeType, TimeStep *tStep, Domain *d, Dof *dof) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void updateDomainLinks(); + void updateDomainLinks() override; - virtual TimeStep *giveNextStep(); - virtual TimeStep *giveSolutionStepWhenIcApply(bool force = false); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + TimeStep *giveNextStep() override; + TimeStep *giveSolutionStepWhenIcApply(bool force = false) override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int checkConsistency(); + void initializeFrom(InputRecord &ir) override; + int checkConsistency() override; // identification - virtual const char *giveInputRecordName() const { return _IFT_NonStationaryTransportProblem_Name; } - virtual const char *giveClassName() const { return "NonStationaryTransportProblem"; } - virtual fMode giveFormulation() { return TL; } + const char *giveInputRecordName() const { return _IFT_NonStationaryTransportProblem_Name; } + const char *giveClassName() const override { return "NonStationaryTransportProblem"; } + fMode giveFormulation() override { return TL; } /// Allows to change number of equations during solution. - virtual int requiresUnknownsDictionaryUpdate() { return changingProblemSize; } - virtual bool requiresEquationRenumbering(TimeStep *) { return changingProblemSize; } + int requiresUnknownsDictionaryUpdate() override { return changingProblemSize; } + bool requiresEquationRenumbering(TimeStep *tStep) override { return changingProblemSize; } //Store solution vector to involved DoFs - //virtual void updateDofUnknownsDictionary(DofManager *dman, TimeStep *tStep); + //void updateDofUnknownsDictionary(DofManager *dman, TimeStep *tStep) override; - virtual int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep); + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override; /** * Returns time function for time step increment. diff --git a/src/tm/stationarytransportproblem.C b/src/tm/EngineeringModels/stationarytransportproblem.C similarity index 74% rename from src/tm/stationarytransportproblem.C rename to src/tm/EngineeringModels/stationarytransportproblem.C index 92e2c72a1..740f33e95 100644 --- a/src/tm/stationarytransportproblem.C +++ b/src/tm/EngineeringModels/stationarytransportproblem.C @@ -32,15 +32,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "stationarytransportproblem.h" +#include "tm/EngineeringModels/stationarytransportproblem.h" #include "nummet.h" #include "timestep.h" #include "element.h" #include "dof.h" #include "maskedprimaryfield.h" -#include "intvarfield.h" #include "verbose.h" -#include "transportelement.h" +#include "tm/Elements/transportelement.h" #include "classfactory.h" #include "datastream.h" #include "contextioerr.h" @@ -51,41 +50,33 @@ namespace oofem { REGISTER_EngngModel(StationaryTransportProblem); -StationaryTransportProblem :: StationaryTransportProblem(int i, EngngModel *_master = NULL) : EngngModel(i, _master) +StationaryTransportProblem :: StationaryTransportProblem(int i, EngngModel *_master = nullptr) : EngngModel(i, _master), + nMethod(nullptr) { ndomains = 1; - nMethod = NULL; } -StationaryTransportProblem :: ~StationaryTransportProblem() -{ - delete nMethod; -} NumericalMethod *StationaryTransportProblem :: giveNumericalMethod(MetaStep *mStep) { - if ( nMethod ) { - return nMethod; + if ( !nMethod ) { + nMethod = std::make_unique(this->giveDomain(1), this); } - - nMethod = new NRSolver(this->giveDomain(1), this); - return nMethod; + return nMethod.get(); } -IRResultType -StationaryTransportProblem :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - result = EngngModel :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; +void +StationaryTransportProblem :: initializeFrom(InputRecord &ir) +{ + EngngModel :: initializeFrom(ir); int val = SMT_Skyline; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_smtype); this->sparseMtrxType = ( SparseMtrxType ) val; ///@todo Combine this option with structural problems, where it is possible to keep the secant tangent elastic tangent (or generally, the initial tangent) etc. One option should fit all common needs here. - this->keepTangent = ir->hasField(_IFT_StationaryTransportProblem_keepTangent); + this->keepTangent = ir.hasField(_IFT_StationaryTransportProblem_keepTangent); // read field export flag IntArray exportFields; @@ -104,11 +95,9 @@ StationaryTransportProblem :: initializeFrom(InputRecord *ir) } if ( !UnknownsField ) { // can exist from nonstationary transport problem - //UnknownsField.reset( new DofDistributedPrimaryField(this, 1, FT_TransportProblemUnknowns, 0) ); - UnknownsField.reset( new PrimaryField(this, 1, FT_TransportProblemUnknowns, 0) ); + //UnknownsField = std::make_unique(this, 1, FT_TransportProblemUnknowns, 0); + UnknownsField = std::make_unique(this, 1, FT_TransportProblemUnknowns, 0); } - - return IRRT_OK; } @@ -158,7 +147,7 @@ TimeStep *StationaryTransportProblem :: giveNextStep() } previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(istep, this, 1, ( double ) istep, 0., counter) ); + currentStep = std::make_unique(istep, this, 1, ( double ) istep, 0., counter); return currentStep.get(); } @@ -180,8 +169,8 @@ void StationaryTransportProblem :: solveYourselfAt(TimeStep *tStep) solutionVector->resize(neq); solutionVector->zero(); - conductivityMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); - if ( conductivityMatrix == NULL ) { + conductivityMatrix = classFactory.createSparseMtrx(sparseMtrxType); + if ( !conductivityMatrix ) { OOFEM_ERROR("sparse matrix creation failed"); } @@ -194,14 +183,15 @@ void StationaryTransportProblem :: solveYourselfAt(TimeStep *tStep) } Domain *domain = this->giveDomain(1); - // update element state according to given ic - for ( auto &elem : domain->giveElements() ) { - TransportElement *element = static_cast< TransportElement * >( elem.get() ); - element->updateInternalState(tStep); - element->updateYourself(tStep); + if ( tStep->isTheFirstStep() ) { + // update element state according to given ic + for ( auto &elem : domain->giveElements() ) { + TransportElement *element = static_cast< TransportElement * >( elem.get() ); + element->updateInternalState(tStep); + element->updateYourself(tStep); + } } - internalForces.resize(neq); #ifdef VERBOSE @@ -236,13 +226,33 @@ void StationaryTransportProblem :: solveYourselfAt(TimeStep *tStep) //nMethod->solve( *conductivityMatrix, rhsVector, *UnknownsField->giveSolutionVector(tStep) ); } + void -StationaryTransportProblem :: updateYourself(TimeStep *tStep) +StationaryTransportProblem :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) { - this->updateInternalState(tStep); - EngngModel :: updateYourself(tStep); + // No-op: currently uses "PrimaryField" and passes along the reference + ///@todo this->field->update(VM_Total, tStep, solutionVector, EModelDefaultEquationNumbering()); } + +void +StationaryTransportProblem :: updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) +{ + answer.zero(); + this->assembleVector(answer, tStep, InternalForceAssembler(), VM_Total, + EModelDefaultEquationNumbering(), this->giveDomain(1), eNorm); + this->updateSharedDofManagers(answer, EModelDefaultEquationNumbering(), InternalForcesExchangeTag); +} + + +void +StationaryTransportProblem :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) +{ + mat.zero(); + this->assemble(mat, tStep, TangentAssembler(TangentStiffness), EModelDefaultEquationNumbering(), this->giveDomain(1) ); +} + + void StationaryTransportProblem :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) { @@ -265,64 +275,19 @@ StationaryTransportProblem :: updateComponent(TimeStep *tStep, NumericalCmpn cmp } } -contextIOResultType +void StationaryTransportProblem :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = EngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = UnknownsField->saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + EngngModel :: saveContext(stream, mode); + UnknownsField->saveContext(stream); } - -contextIOResultType -StationaryTransportProblem :: restoreContext(DataStream *stream, ContextMode mode, void *obj) -// -// restore state variable - displacement vector -// +void +StationaryTransportProblem :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - int closeFlag = 0; - int istep, iversion; - FILE *file = NULL; - - this->resolveCorrespondingStepNumber(istep, iversion, obj); - - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override - } - - stream = new FileDataStream(file); - closeFlag = 1; - } - - if ( ( iores = EngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = UnknownsField->restoreContext(*stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } - - // ensure consistent records - - return CIO_OK; + EngngModel :: restoreContext(stream, mode); + UnknownsField->restoreContext(stream); } @@ -350,16 +315,4 @@ StationaryTransportProblem :: updateDomainLinks() this->giveNumericalMethod( this->giveCurrentMetaStep() )->setDomain( this->giveDomain(1) ); } - -void -StationaryTransportProblem :: updateInternalState(TimeStep *tStep) -{ - ///@todo Remove this, unnecessary with solving as a nonlinear problem (left for now, since nonstationary problems might still need it) - for ( auto &domain: domainList ) { - for ( auto &elem : domain->giveElements() ) { - elem->updateInternalState(tStep); - } - } -} - } // end namespace oofem diff --git a/src/tm/stationarytransportproblem.h b/src/tm/EngineeringModels/stationarytransportproblem.h similarity index 65% rename from src/tm/stationarytransportproblem.h rename to src/tm/EngineeringModels/stationarytransportproblem.h index 1495a07c7..0169854ba 100644 --- a/src/tm/stationarytransportproblem.h +++ b/src/tm/EngineeringModels/stationarytransportproblem.h @@ -37,6 +37,7 @@ #include "engngm.h" #include "sparselinsystemnm.h" +#include "sparsenonlinsystemnm.h" #include "sparsemtrx.h" #include "primaryfield.h" @@ -48,7 +49,6 @@ //@} namespace oofem { -class SparseNonLinearSystemNM; /** * This class represents stationary transport problem. @@ -57,7 +57,7 @@ class SparseNonLinearSystemNM; class StationaryTransportProblem : public EngngModel { protected: - SparseMtrxType sparseMtrxType; + SparseMtrxType sparseMtrxType = SMT_Skyline; /// This field stores solution vector. For fixed size of problem, the PrimaryField is used, for growing/decreasing size, DofDistributedPrimaryField applies. std :: unique_ptr< PrimaryField > UnknownsField; @@ -66,44 +66,36 @@ class StationaryTransportProblem : public EngngModel FloatArray eNorm; /// Numerical method used to solve the problem - SparseNonLinearSystemNM *nMethod; + std::unique_ptr nMethod; - bool keepTangent; + bool keepTangent = false; public: - /// Constructor. StationaryTransportProblem(int i, EngngModel * _master); - /// Destructor. - virtual ~StationaryTransportProblem(); - virtual void solveYourselfAt(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); - virtual void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d); - virtual double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof); - virtual FieldPtr giveField (FieldType key, TimeStep *); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); + void solveYourselfAt(TimeStep *tStep) override; + void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) override; + void updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) override; + void updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) override; + void updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) override; + double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) override; + FieldPtr giveField (FieldType key, TimeStep *) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - virtual void updateDomainLinks(); + void updateDomainLinks() override; - virtual TimeStep *giveNextStep(); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + TimeStep *giveNextStep() override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual int checkConsistency(); + int checkConsistency() override; // identification - virtual const char *giveInputRecordName() const { return _IFT_StationaryTransportProblem_Name; } - virtual const char *giveClassName() const { return "StationaryTransportProblem"; } - virtual fMode giveFormulation() { return TL; } - -protected: - /** - * Updates IP values on elements - * @param tStep Solution step. - */ - virtual void updateInternalState(TimeStep *tStep); + const char *giveInputRecordName() const { return _IFT_StationaryTransportProblem_Name; } + const char *giveClassName() const override { return "StationaryTransportProblem"; } + fMode giveFormulation() override { return TL; } }; } // end namespace oofem #endif // stationarytransportproblem_h diff --git a/src/tm/transienttransportproblem.C b/src/tm/EngineeringModels/transienttransportproblem.C similarity index 61% rename from src/tm/transienttransportproblem.C rename to src/tm/EngineeringModels/transienttransportproblem.C index a4ee69091..c5e166e69 100644 --- a/src/tm/transienttransportproblem.C +++ b/src/tm/EngineeringModels/transienttransportproblem.C @@ -32,11 +32,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "transienttransportproblem.h" +#include "tm/EngineeringModels/transienttransportproblem.h" #include "timestep.h" #include "dofdistributedprimaryfield.h" #include "maskedprimaryfield.h" -#include "transportelement.h" +#include "intvarfield.h" +#include "tm/Elements/transportelement.h" #include "classfactory.h" #include "datastream.h" #include "contextioerr.h" @@ -49,37 +50,30 @@ #include "generalboundarycondition.h" #include "boundarycondition.h" #include "activebc.h" +#include "outputmanager.h" namespace oofem { REGISTER_EngngModel(TransientTransportProblem); -TransientTransportProblem :: TransientTransportProblem(int i, EngngModel *_master = NULL) : EngngModel(i, _master), - alpha(0.5), - dtFunction(0), - prescribedTimes(), - deltaT(1.), - keepTangent(false), - lumped(false) +TransientTransportProblem :: TransientTransportProblem(int i, EngngModel *master) : EngngModel(i, master) { ndomains = 1; } -TransientTransportProblem :: ~TransientTransportProblem() {} - NumericalMethod *TransientTransportProblem :: giveNumericalMethod(MetaStep *mStep) { if ( !nMethod ) { - nMethod.reset( new NRSolver(this->giveDomain(1), this) ); + nMethod = std::make_unique(this->giveDomain(1), this); } return nMethod.get(); } -IRResultType -TransientTransportProblem :: initializeFrom(InputRecord *ir) +void +TransientTransportProblem :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + EngngModel :: initializeFrom(ir); int val = SMT_Skyline; IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_smtype); @@ -87,21 +81,25 @@ TransientTransportProblem :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, this->alpha, _IFT_TransientTransportProblem_alpha); + if ( ir.hasField(_IFT_TransientTransportProblem_initt) ) { + IR_GIVE_FIELD(ir, initT, _IFT_TransientTransportProblem_initt); + } + prescribedTimes.clear(); dtFunction = 0; - if ( ir->hasField(_IFT_TransientTransportProblem_dtFunction) ) { + if ( ir.hasField(_IFT_TransientTransportProblem_dtFunction) ) { IR_GIVE_FIELD(ir, this->dtFunction, _IFT_TransientTransportProblem_dtFunction); - } else if ( ir->hasField(_IFT_TransientTransportProblem_prescribedTimes) ) { + } else if ( ir.hasField(_IFT_TransientTransportProblem_prescribedTimes) ) { IR_GIVE_FIELD(ir, this->prescribedTimes, _IFT_TransientTransportProblem_prescribedTimes); } else { IR_GIVE_FIELD(ir, this->deltaT, _IFT_TransientTransportProblem_deltaT); } - this->keepTangent = ir->hasField(_IFT_TransientTransportProblem_keepTangent); + this->keepTangent = ir.hasField(_IFT_TransientTransportProblem_keepTangent); - this->lumped = ir->hasField(_IFT_TransientTransportProblem_lumped); + this->lumped = ir.hasField(_IFT_TransientTransportProblem_lumped); - field.reset( new DofDistributedPrimaryField(this, 1, FT_TransportProblemUnknowns, 0) ); + field = std::make_unique(this, 1, FT_TransportProblemUnknowns, 2, this->alpha); // read field export flag exportFields.clear(); @@ -118,30 +116,14 @@ TransientTransportProblem :: initializeFrom(InputRecord *ir) } } } - - return EngngModel :: initializeFrom(ir); + +// InternalVariableField(IST_HydrationDegree, FT_Unknown, MMA_ClosestPoint, this->giveDomain(1)); } double TransientTransportProblem :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) { - //return this->field->giveUnknownValue(dof, mode, tStep); - double val1 = field->giveUnknownValue(dof, VM_Total, tStep); - double val0 = field->giveUnknownValue(dof, VM_Total, tStep->givePreviousStep()); - if ( mode == VM_Total ) { - //return this->alpha * val1 + (1.-this->alpha) * val0; - return val1;//The output should be given always at the end of the time step, regardless of alpha - } else if ( mode == VM_TotalIntrinsic) { - return this->alpha * val1 + (1.-this->alpha) * val0; - //return val1; - } else if ( mode == VM_Velocity ) { - return (val1 - val0) / tStep->giveTimeIncrement(); - } else if ( mode == VM_Incremental ) { - return val1 - val0; - } else { - OOFEM_ERROR("Unknown value mode requested"); - return 0; - } + return this->field->giveUnknownValue(dof, mode, tStep); } @@ -163,7 +145,7 @@ TransientTransportProblem :: giveDiscreteTime(int iStep) if ( iStep > 0 && iStep <= this->prescribedTimes.giveSize() ) { return ( this->prescribedTimes.at(iStep) ); } else if ( iStep == 0 ) { - return 0.0; + return initT; } OOFEM_ERROR("invalid iStep"); @@ -175,12 +157,12 @@ TimeStep *TransientTransportProblem :: giveNextStep() { if ( !currentStep ) { // first step -> generate initial step - currentStep.reset( new TimeStep( *giveSolutionStepWhenIcApply() ) ); + currentStep = std::make_unique( *giveSolutionStepWhenIcApply() ); } double dt = this->giveDeltaT(currentStep->giveNumber()+1); previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(*previousStep, dt) ); + currentStep = std::make_unique(*previousStep, dt); currentStep->setIntrinsicTime(previousStep->giveTargetTime() + alpha * dt); return currentStep.get(); } @@ -193,7 +175,7 @@ TimeStep *TransientTransportProblem :: giveSolutionStepWhenIcApply(bool force) } else { if ( !stepWhenIcApply ) { double dt = this->giveDeltaT(1); - stepWhenIcApply.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 0, 0., dt, 0) ); + stepWhenIcApply = std::make_unique(giveNumberOfTimeStepWhenIcApply(), this, 0, this->initT, dt, 0); // The initial step goes from [-dt, 0], so the intrinsic time is at: -deltaT + alpha*dt stepWhenIcApply->setIntrinsicTime(-dt + alpha * dt); } @@ -205,7 +187,7 @@ TimeStep *TransientTransportProblem :: giveSolutionStepWhenIcApply(bool force) void TransientTransportProblem :: solveYourselfAt(TimeStep *tStep) { - OOFEM_LOG_INFO( "Solving [step number %5d, time %e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); + OOFEM_LOG_INFO( "\nSolving [step number %5d, time %e]\n", tStep->giveNumber(), tStep->giveTargetTime() ); Domain *d = this->giveDomain(1); int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); @@ -215,40 +197,13 @@ void TransientTransportProblem :: solveYourselfAt(TimeStep *tStep) } field->advanceSolution(tStep); - -#if 1 - // This is what advanceSolution should be doing, but it can't be there yet - // (backwards compatibility issues due to inconsistencies in other solvers). - TimeStep *prev = tStep->givePreviousStep(); - for ( auto &dman : d->giveDofManagers() ) { - static_cast< DofDistributedPrimaryField* >(field.get())->setInitialGuess(*dman, tStep, prev);//copy total values into new tStep - } - - for ( auto &elem : d->giveElements() ) { - int ndman = elem->giveNumberOfInternalDofManagers(); - for ( int i = 1; i <= ndman; i++ ) { - static_cast< DofDistributedPrimaryField* >(field.get())->setInitialGuess(*elem->giveInternalDofManager(i), tStep, prev); - } - } - - for ( auto &bc : d->giveBcs() ) { - int ndman = bc->giveNumberOfInternalDofManagers(); - for ( int i = 1; i <= ndman; i++ ) { - static_cast< DofDistributedPrimaryField* >(field.get())->setInitialGuess(*bc->giveInternalDofManager(i), tStep, prev); - } - } -#endif - - field->applyBoundaryCondition(tStep); field->initialize(VM_Total, tStep, solution, EModelDefaultEquationNumbering()); - if ( !effectiveMatrix ) { - effectiveMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); + effectiveMatrix = classFactory.createSparseMtrx(sparseMtrxType); effectiveMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); } - OOFEM_LOG_INFO("Assembling external forces\n"); FloatArray externalForces(neq); externalForces.zero(); @@ -264,10 +219,10 @@ void TransientTransportProblem :: solveYourselfAt(TimeStep *tStep) FloatArray incrementOfSolution; double loadLevel; int currentIterations; - this->updateComponent(tStep, InternalRhs, d); // @todo Hack to ensure that internal RHS is evaluated before the tangent. This is not ideal, causing this to be evaluated twice for a linearproblem. We have to find a better way to handle this. + this->updateInternalRHS(this->internalForces, tStep, this->giveDomain(1), &this->eNorm); /// @todo Hack to ensure that internal RHS is evaluated before the tangent. This is not ideal, causing this to be evaluated twice for a linearproblem. We have to find a better way to handle this. this->nMethod->solve(*this->effectiveMatrix, externalForces, - NULL, // ignore + nullptr, // ignore this->solution, incrementOfSolution, this->internalForces, @@ -279,6 +234,56 @@ void TransientTransportProblem :: solveYourselfAt(TimeStep *tStep) } +void +TransientTransportProblem :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) +{ + ///@todo NRSolver should report when the solution changes instead of doing it this way. + this->field->update(VM_Total, tStep, solutionVector, EModelDefaultEquationNumbering()); + ///@todo Need to reset the boundary conditions properly since some "update" is doing strange + /// things such as applying the (wrong) boundary conditions. This call will be removed when that code can be removed. + this->field->applyBoundaryCondition(tStep); +} + + +void +TransientTransportProblem :: updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) +{ + // F_eff = F(T^(k)) + C * dT/dt^(k) + answer.zero(); + this->assembleVector(answer, tStep, InternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), d, eNorm); + this->updateSharedDofManagers(answer, EModelDefaultEquationNumbering(), InternalForcesExchangeTag); + if ( lumped ) { + // Note, inertia contribution cannot be computed on element level when lumped mass matrices are used. + FloatArray oldSolution, vel; + this->field->initialize(VM_Total, tStep->givePreviousStep(), oldSolution, EModelDefaultEquationNumbering()); + vel.beDifferenceOf(solution, oldSolution); + vel.times( 1./tStep->giveTimeIncrement() ); + FloatArray capacityDiag(vel.giveSize()); + this->assembleVector( capacityDiag, tStep, LumpedMassVectorAssembler(), VM_Total, EModelDefaultEquationNumbering(), d ); + for ( int i = 0; i < vel.giveSize(); ++i ) { + answer[i] += capacityDiag[i] * vel[i]; + } + } else { + FloatArray tmp; + this->assembleVector(answer, tStep, InertiaForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), d, & tmp); + eNorm->add(tmp); ///@todo Fix this, assembleVector shouldn't zero eNorm inside the functions. / Mikael + } +} + + +void +TransientTransportProblem :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) +{ + // K_eff = (a*K + C/dt) + if ( !this->keepTangent || !this->hasTangent ) { + mat.zero(); + this->assemble(mat, tStep, EffectiveTangentAssembler(TangentStiffness, lumped, this->alpha, 1./tStep->giveTimeIncrement()), + EModelDefaultEquationNumbering(), d ); + this->hasTangent = true; + } +} + + void TransientTransportProblem :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) { @@ -343,8 +348,7 @@ TransientTransportProblem :: applyIC() this->field->applyDefaultInitialCondition(); - ///@todo It's rather strange that the models need the initial values. - // update element state according to given ic + // set initial field IP values (needed by some nonlinear materials) TimeStep *s = this->giveSolutionStepWhenIcApply(); for ( auto &elem : domain->giveElements() ) { TransportElement *element = static_cast< TransportElement * >( elem.get() ); @@ -380,70 +384,112 @@ TransientTransportProblem :: requiresEquationRenumbering(TimeStep *tStep) int TransientTransportProblem :: forceEquationNumbering() { - this->effectiveMatrix.reset(NULL); + this->effectiveMatrix = nullptr; return EngngModel :: forceEquationNumbering(); } -void -TransientTransportProblem :: updateYourself(TimeStep *tStep) -{ - EngngModel :: updateYourself(tStep); -} -contextIOResultType -TransientTransportProblem :: saveContext(DataStream &stream, ContextMode mode) +void +TransientTransportProblem :: printOutputAt(FILE *file, TimeStep *tStep) { - contextIOResultType iores; - - if ( ( iores = EngngModel :: saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = field->saveContext(stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); + if ( !this->giveDomain(1)->giveOutputManager()->testTimeStepOutput(tStep) ) { + return; // Do not print even Solution step header } - return CIO_OK; -} - - -contextIOResultType -TransientTransportProblem :: restoreContext(DataStream *stream, ContextMode mode, void *obj) -{ - contextIOResultType iores; - int closeFlag = 0; - int istep, iversion; - FILE *file = NULL; - - this->resolveCorrespondingStepNumber(istep, iversion, obj); - - if ( stream == NULL ) { - if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { - THROW_CIOERR(CIO_IOERR); // override + EngngModel :: printOutputAt(file, tStep); + + // computes and prints reaction forces in all supported or restrained dofs + fprintf(file, "\n\n\tR E A C T I O N S O U T P U T:\n\t_______________________________\n\n\n"); + + IntArray restrDofMans, restrDofs, eqn; + int di=1; + //from StructuralEngngModel :: buildReactionTable(dofManMap, dofidMap, eqnMap, tStep, 1); + // determine number of restrained dofs + Domain *domain = this->giveDomain(di); + int numRestrDofs = this->giveNumberOfDomainEquations( di, EModelDefaultPrescribedEquationNumbering() ); + int ndofMan = domain->giveNumberOfDofManagers(); + int rindex, count = 0; + + // initialize corresponding dofManagers and dofs for each restrained dof + restrDofMans.resize(numRestrDofs); + restrDofs.resize(numRestrDofs); + eqn.resize(numRestrDofs); + + for ( int i = 1; i <= ndofMan; i++ ) { + DofManager *inode = domain->giveDofManager(i); + for ( Dof *jdof: *inode ) { + if ( jdof->isPrimaryDof() && ( jdof->hasBc(tStep) ) ) { // skip slave dofs + rindex = jdof->__givePrescribedEquationNumber(); + if ( rindex ) { + count++; + restrDofMans.at(count) = i; + restrDofs.at(count) = jdof->giveDofID(); + eqn.at(count) = rindex; + } else { + // NullDof has no equation number and no prescribed equation number + //_error("No prescribed equation number assigned to supported DOF"); + } + } } - - stream = new FileDataStream(file); - closeFlag = 1; } - - if ( ( iores = EngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); + // Trim to size. + restrDofMans.resizeWithValues(count); + restrDofs.resizeWithValues(count); + eqn.resizeWithValues(count); + + //restrDofMans.printYourself(); + //restrDofs.printYourself(); + //eqn.printYourself(); + + //from StructuralEngngModel :: computeReaction() + FloatArray internal, external; + internal.resize( this->giveNumberOfDomainEquations( di, EModelDefaultPrescribedEquationNumbering() ) ); + internal.zero(); + + // Add internal forces + this->assembleVector( internal, tStep, InternalForceAssembler(), VM_Total, + EModelDefaultPrescribedEquationNumbering(), this->giveDomain(di), &this->eNorm ); + // Subtract external loading + external.resize(internal.giveSize()); + this->assembleVector( external, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultPrescribedEquationNumbering(), this->giveDomain(di), &this->eNorm ); + + internal.subtract(external); + //internal.printYourself(); + + // + // loop over reactions and print them + // + for ( int i = 1; i <= restrDofMans.giveSize(); i++ ) { + if ( domain->giveOutputManager()->testDofManOutput(restrDofMans.at(i), tStep) ) { + fprintf(file, "\tNode %8d iDof %2d reaction % .4e [bc-id: %d]\n", + domain->giveDofManager( restrDofMans.at(i) )->giveLabel(), + restrDofs.at(i), internal.at( eqn.at(i) ), + domain->giveDofManager( restrDofMans.at(i) )->giveDofWithID( restrDofs.at(i) )->giveBcId() ); + } } + +} - if ( ( iores = field->restoreContext(*stream, mode) ) != CIO_OK ) { - THROW_CIOERR(iores); - } +void +TransientTransportProblem :: updateYourself(TimeStep *tStep) +{ + EngngModel :: updateYourself(tStep); +} - if ( closeFlag ) { - fclose(file); - delete stream; - stream = NULL; - } +void +TransientTransportProblem :: saveContext(DataStream &stream, ContextMode mode) +{ + EngngModel :: saveContext(stream, mode); + field->saveContext(stream); +} - // ensure consistent records - return CIO_OK; +void +TransientTransportProblem :: restoreContext(DataStream &stream, ContextMode mode) +{ + EngngModel :: restoreContext(stream, mode); + field->restoreContext(stream); } @@ -482,7 +528,8 @@ TransientTransportProblem :: updateDomainLinks() this->giveNumericalMethod( this->giveCurrentMetaStep() )->setDomain( this->giveDomain(1) ); } -FieldPtr TransientTransportProblem::giveField (FieldType key, TimeStep *tStep) + +FieldPtr TransientTransportProblem::giveField(FieldType key, TimeStep *tStep) { /* Note: the current implementation uses MaskedPrimaryField, that is automatically updated with the model progress, so the returned field always refers to active solution step. @@ -492,11 +539,9 @@ FieldPtr TransientTransportProblem::giveField (FieldType key, TimeStep *tStep) OOFEM_ERROR("Unable to return field representation for non-current time step"); } if ( key == FT_Temperature ) { - FieldPtr _ptr ( new MaskedPrimaryField ( key, this->field.get(), {T_f} ) ); - return _ptr; + return std::make_shared( key, this->field.get(), IntArray{T_f} ); } else if ( key == FT_HumidityConcentration ) { - FieldPtr _ptr ( new MaskedPrimaryField ( key, this->field.get(), {C_1} ) ); - return _ptr; + return std::make_shared( key, this->field.get(), IntArray{C_1} ); } else { return FieldPtr(); } diff --git a/src/tm/transienttransportproblem.h b/src/tm/EngineeringModels/transienttransportproblem.h similarity index 59% rename from src/tm/transienttransportproblem.h rename to src/tm/EngineeringModels/transienttransportproblem.h index 1558aa773..28afd06f7 100644 --- a/src/tm/transienttransportproblem.h +++ b/src/tm/EngineeringModels/transienttransportproblem.h @@ -38,6 +38,7 @@ #include "engngm.h" #include "sparselinsystemnm.h" #include "sparsemtrx.h" +#include "sparsenonlinsystemnm.h" #include @@ -46,6 +47,7 @@ #define _IFT_TransientTransportProblem_Name "transienttransport" #define _IFT_TransientTransportProblem_alpha "alpha" ///< Defines the time discretization of the value: @f$ u = u_n (1-\alpha) + u_{n+1} \alpha @f$. #define _IFT_TransientTransportProblem_deltaT "deltat" ///< Fixed timestep. +#define _IFT_TransientTransportProblem_initt "initt" ///< Initial time #define _IFT_TransientTransportProblem_dtFunction "dtfunction" ///< Function that determines size of time step. #define _IFT_TransientTransportProblem_prescribedTimes "prescribedtimes" ///< Discrete times for each time step. #define _IFT_TransientTransportProblem_keepTangent "keeptangent" ///< Fixes the tangent to be reused on each step. @@ -54,8 +56,7 @@ //@} namespace oofem { -class SparseNonLinearSystemNM; -class PrimaryField; +class DofDistributedPrimaryField; class Function; /** @@ -65,8 +66,8 @@ class Function; class TransientTransportProblem : public EngngModel { protected: - SparseMtrxType sparseMtrxType; - std :: unique_ptr< PrimaryField > field; + SparseMtrxType sparseMtrxType = SMT_Skyline; + std :: unique_ptr< DofDistributedPrimaryField > field; std :: unique_ptr< SparseMtrx > effectiveMatrix; @@ -77,54 +78,59 @@ class TransientTransportProblem : public EngngModel /// Numerical method used to solve the problem std :: unique_ptr< SparseNonLinearSystemNM > nMethod; - double alpha; - int dtFunction; + double alpha = 0.5; + int dtFunction = 0; FloatArray prescribedTimes; - double deltaT; - bool keepTangent, hasTangent; - bool lumped; + /// Initial time from which the computation runs. Default is zero. + double initT = 0.; + double deltaT = 1.; + bool keepTangent = false, hasTangent = false; + bool lumped = false; IntArray exportFields; public: - /// Constructor. - TransientTransportProblem(int i, EngngModel * _master); - /// Destructor. - virtual ~TransientTransportProblem(); - - virtual void solveYourselfAt(TimeStep *tStep); - virtual void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d); - virtual double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode); - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL); - + TransientTransportProblem(int i, EngngModel *master=nullptr); + + void solveYourselfAt(TimeStep *tStep) override; + void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) override; + bool newDofHandling() override { return true; } + void updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d) override; + void updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorm) override; + void updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d) override; + double giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + virtual void applyIC(); - virtual int requiresUnknownsDictionaryUpdate(); - virtual int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep); - virtual void updateDomainLinks(); + int requiresUnknownsDictionaryUpdate() override; + int giveUnknownDictHashIndx(ValueModeType mode, TimeStep *tStep) override; + void updateDomainLinks() override; Function *giveDtFunction(); double giveDeltaT(int n); double giveDiscreteTime(int iStep); - virtual TimeStep *giveNextStep(); - virtual TimeStep *giveSolutionStepWhenIcApply(bool force = false); - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); + TimeStep *giveNextStep() override; + TimeStep *giveSolutionStepWhenIcApply(bool force = false) override; + NumericalMethod *giveNumericalMethod(MetaStep *mStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual bool requiresEquationRenumbering(TimeStep *tStep); - virtual int forceEquationNumbering(); + bool requiresEquationRenumbering(TimeStep *tStep) override; + int forceEquationNumbering() override; - virtual void updateYourself(TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) override; + + void updateYourself(TimeStep *tStep) override; - virtual int checkConsistency(); - virtual FieldPtr giveField (FieldType key, TimeStep *); + int checkConsistency() override; + FieldPtr giveField (FieldType key, TimeStep *tStep) override; // identification - virtual const char *giveInputRecordName() const { return _IFT_TransientTransportProblem_Name; } - virtual const char *giveClassName() const { return "TransientTransportProblem"; } - virtual fMode giveFormulation() { return TL; } + const char *giveInputRecordName() const { return _IFT_TransientTransportProblem_Name; } + const char *giveClassName() const override { return "TransientTransportProblem"; } + fMode giveFormulation() override { return TL; } }; } // end namespace oofem #endif // transienttransportproblem_h diff --git a/src/tm/latticetransmat.C b/src/tm/Materials/LatticeMaterials/latticetransmat.C similarity index 72% rename from src/tm/latticetransmat.C rename to src/tm/Materials/LatticeMaterials/latticetransmat.C index 016544e92..b70b8eb5e 100644 --- a/src/tm/latticetransmat.C +++ b/src/tm/Materials/LatticeMaterials/latticetransmat.C @@ -32,24 +32,24 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "latticetransmat.h" +#include "tm/Materials/LatticeMaterials/latticetransmat.h" #include "domain.h" #include "gausspoint.h" -#include "latticetransportelement.h" +#include "tm/Elements/LatticeElements/latticetransportelement.h" #include "mathfem.h" #include "staggeredproblem.h" #include "classfactory.h" #ifdef __SM_MODULE - #include "Elements/latticestructuralelement.h" + #include "sm/Elements/LatticeElements/latticestructuralelement.h" #endif namespace oofem { REGISTER_Material(LatticeTransportMaterial); -IRResultType -LatticeTransportMaterial :: initializeFrom(InputRecord *ir) +void +LatticeTransportMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Material :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->viscosity, _IFT_LatticeTransportMaterial_vis); @@ -64,10 +64,9 @@ LatticeTransportMaterial :: initializeFrom(InputRecord *ir) conType = 0; IR_GIVE_OPTIONAL_FIELD(ir, this->conType, _IFT_LatticeTransportMaterial_contype); this->capacity = 0; - if(conType == 0){ - IR_GIVE_OPTIONAL_FIELD(ir, this->capacity, _IFT_LatticeTransportMaterial_c); - } - else if ( conType == 1 ) { + if ( conType == 0 ) { + IR_GIVE_OPTIONAL_FIELD(ir, this->capacity, _IFT_LatticeTransportMaterial_c); + } else if ( conType == 1 ) { IR_GIVE_FIELD(ir, this->paramM, _IFT_LatticeTransportMaterial_m); IR_GIVE_FIELD(ir, this->paramA, _IFT_LatticeTransportMaterial_a); @@ -88,10 +87,9 @@ LatticeTransportMaterial :: initializeFrom(InputRecord *ir) if ( suctionAirEntry == 0. ) { suctionAirEntry = paramA * pow( ( pow( ( thetaS - thetaR ) / ( thetaM - thetaR ), -1. / paramM ) - 1. ), ( 1 - paramM ) ); } else { - thetaM = ( thetaS - thetaR ) * pow(1. + pow( suctionAirEntry / paramA, 1. / ( 1. - paramM ) ), paramM) + thetaR; + thetaM = ( thetaS - thetaR ) * pow(1. + pow(suctionAirEntry / paramA, 1. / ( 1. - paramM ) ), paramM) + thetaR; } - } //end of contype condition - else if ( conType != 0 && conType != 1 ) { + } else if ( conType != 0 && conType != 1 ) { OOFEM_ERROR("unknown conType mode"); } @@ -100,24 +98,25 @@ LatticeTransportMaterial :: initializeFrom(InputRecord *ir) crackLimit = -1.; IR_GIVE_OPTIONAL_FIELD(ir, this->crackLimit, _IFT_LatticeTransportMaterial_clim); - - return Material :: initializeFrom(ir); } -void -LatticeTransportMaterial :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) +FloatArrayF< 3 > +LatticeTransportMaterial :: computeFlux3D(const FloatArrayF< 3 > &grad, double field, GaussPoint *gp, TimeStep *tStep) const { - LatticeTransportMaterialStatus *status = static_cast< LatticeTransportMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< LatticeTransportMaterialStatus * >( this->giveStatus(gp) ); + status->setTempGradient(grad); status->setTempField(field); - double suction = field.at(1); - double c = this->computeConductivity(suction, gp, tStep); - answer.beScaled(-c, grad); + + double c = this->computeConductivity(field, gp, tStep); + auto flux = -c * grad; + status->setTempFlux(flux); + return flux; } double -LatticeTransportMaterial :: give(int aProperty, GaussPoint *gp) +LatticeTransportMaterial :: give(int aProperty, GaussPoint *gp) const { if ( aProperty == 'k' ) { return permeability; @@ -132,10 +131,10 @@ LatticeTransportMaterial :: give(int aProperty, GaussPoint *gp) double LatticeTransportMaterial :: giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - LatticeTransportMaterialStatus *status = static_cast< LatticeTransportMaterialStatus * >( this->giveStatus(gp) ); - double suction = status->giveTempField().at(1); + auto status = static_cast< LatticeTransportMaterialStatus * >( this->giveStatus(gp) ); + double suction = status->giveTempField(); if ( mode == Capacity ) { return computeCapacity(suction, gp); @@ -152,13 +151,11 @@ LatticeTransportMaterial :: giveCharacteristicValue(MatResponseMode mode, double LatticeTransportMaterial :: computeConductivity(double suction, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { - LatticeTransportMaterialStatus *status = static_cast< LatticeTransportMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< LatticeTransportMaterialStatus * >( this->giveStatus(gp) ); - matMode = gp->giveMaterialMode(); - - this->density = this->give('d', gp); + double density = this->give('d', gp); double relativePermeability = 0.; double conductivity = 0.; @@ -168,7 +165,7 @@ LatticeTransportMaterial :: computeConductivity(double suction, saturation = 1.; relativePermeability = 1.; } else { - partOne = pow( suction / this->paramA, 1. / ( 1. - this->paramM ) ); + partOne = pow(suction / this->paramA, 1. / ( 1. - this->paramM ) ); saturation = ( this->thetaM - this->thetaR ) / ( this->thetaS - this->thetaR ) * pow(1. + partOne, -this->paramM); @@ -181,7 +178,7 @@ LatticeTransportMaterial :: computeConductivity(double suction, } //Calculate mass for postprocessing - double mass = ( saturation * ( this->thetaS - this->thetaR ) + this->thetaR ) * this->density; + double mass = ( saturation * ( this->thetaS - this->thetaR ) + this->thetaR ) * density; status->setMass(mass); @@ -190,29 +187,24 @@ LatticeTransportMaterial :: computeConductivity(double suction, //add crack contribution; - //Read in crack lengths - FloatArray crackLengths; - - static_cast< LatticeTransportElement * >( gp->giveElement())->giveCrackLengths(crackLengths); - + static_cast< LatticeTransportElement * >( gp->giveElement() )->giveCrackLengths(crackLengths); FloatArray crackWidths; - crackWidths.resize(crackLengths.giveSize()); + crackWidths.resize(crackLengths.giveSize() ); #ifdef __SM_MODULE IntArray coupledModels; if ( domain->giveEngngModel()->giveMasterEngngModel() ) { - (static_cast< StaggeredProblem *>(domain->giveEngngModel()->giveMasterEngngModel()))->giveCoupledModels(coupledModels); + ( static_cast< StaggeredProblem * >( domain->giveEngngModel()->giveMasterEngngModel() ) )->giveCoupledModels(coupledModels); int couplingFlag = ( static_cast< LatticeTransportElement * >( gp->giveElement() ) )->giveCouplingFlag(); if ( couplingFlag == 1 && coupledModels.at(1) != 0 && !tStep->isTheFirstStep() ) { IntArray couplingNumbers; - - static_cast< LatticeTransportElement * >( gp->giveElement())->giveCouplingNumbers(couplingNumbers); - for (int i = 1; i <= crackLengths.giveSize(); i++) { + static_cast< LatticeTransportElement * >( gp->giveElement() )->giveCouplingNumbers(couplingNumbers); + for ( int i = 1; i <= crackLengths.giveSize(); i++ ) { if ( couplingNumbers.at(i) != 0 ) { - crackWidths.at(i) = static_cast< LatticeStructuralElement* >( domain->giveEngngModel()->giveMasterEngngModel()->giveSlaveProblem( coupledModels.at(1) )->giveDomain(1)->giveElement(couplingNumbers.at(i)))->giveCrackWidth(); + crackWidths.at(i) = static_cast< LatticeStructuralElement * >( domain->giveEngngModel()->giveMasterEngngModel()->giveSlaveProblem(coupledModels.at(1) )->giveDomain(1)->giveElement(couplingNumbers.at(i) ) )->giveCrackWidth(); } else { crackWidths.at(i) = 0.; } @@ -220,16 +212,14 @@ LatticeTransportMaterial :: computeConductivity(double suction, } } #endif - //Read in crack widths from transport element if ( !domain->giveEngngModel()->giveMasterEngngModel() ) { static_cast< LatticeTransportElement * >( gp->giveElement() )->giveCrackWidths(crackWidths); } - //Use crack width and apply cubic law double crackContribution = 0.; - for (int i = 1; i <= crackLengths.giveSize(); i++) { + for ( int i = 1; i <= crackLengths.giveSize(); i++ ) { if ( crackWidths.at(i) < this->crackLimit || this->crackLimit < 0. ) { crackContribution += pow(crackWidths.at(i), 3.) / crackLengths.at(i); } else { @@ -238,57 +228,49 @@ LatticeTransportMaterial :: computeConductivity(double suction, } } - crackContribution *= this->crackTortuosity * relativePermeability/ (12. * this->viscosity ); - + crackContribution *= this->crackTortuosity * relativePermeability / ( 12. * this->viscosity ); conductivity += crackContribution; - - return this->density * conductivity; + return density * conductivity; } - double -LatticeTransportMaterial :: computeCapacity(double suction, GaussPoint *gp) +LatticeTransportMaterial :: computeCapacity(double suction, GaussPoint *gp) const { double cap = 0.; - this->density = this->give('d', gp); + double density = this->give('d', gp); if ( conType == 0 ) { cap = this->capacity; } else { - if ( suction < this->suctionAirEntry) { + if ( suction < this->suctionAirEntry ) { cap = 0.; } else { double partOne = this->paramM / ( this->paramA * ( 1. - this->paramM ) ); - double partTwo = pow( suction / this->paramA, this->paramM / ( 1. - this->paramM ) ); - double partThree = pow(1. + pow( suction / this->paramA, 1. / ( 1. - this->paramM ) ), -this->paramM - 1.); + double partTwo = pow(suction / this->paramA, this->paramM / ( 1. - this->paramM ) ); + double partThree = pow(1. + pow(suction / this->paramA, 1. / ( 1. - this->paramM ) ), -this->paramM - 1.); cap = ( this->thetaM - this->thetaR ) * partOne * partTwo * partThree; } } - return this->density * cap; + return density * cap; } MaterialStatus * LatticeTransportMaterial :: CreateStatus(GaussPoint *gp) const { - return new LatticeTransportMaterialStatus(1, LatticeTransportMaterial :: domain, gp); + return new LatticeTransportMaterialStatus(gp); } void -LatticeTransportMaterialStatus :: printOutputAt(FILE *File, TimeStep *tStep) +LatticeTransportMaterialStatus :: printOutputAt(FILE *File, TimeStep *tStep) const { MaterialStatus :: printOutputAt(File, tStep); - fprintf(File, " state"); - - for ( auto &val : field ) { - fprintf( File, " %.4e", val ); - } - + fprintf(File, " state %.4e", field); fprintf(File, " mass %.8e", mass); fprintf(File, "\n"); } @@ -304,12 +286,12 @@ void LatticeTransportMaterialStatus :: initTempStatus() { TransportMaterialStatus :: initTempStatus(); - oldPressure = field.at(1); + oldPressure = field; } -LatticeTransportMaterialStatus :: LatticeTransportMaterialStatus(int n, Domain *d, GaussPoint *g) : - TransportMaterialStatus(n, d, g) +LatticeTransportMaterialStatus :: LatticeTransportMaterialStatus(GaussPoint *g) : + TransportMaterialStatus(g) { mass = 0.; } diff --git a/src/tm/latticetransmat.h b/src/tm/Materials/LatticeMaterials/latticetransmat.h similarity index 55% rename from src/tm/latticetransmat.h rename to src/tm/Materials/LatticeMaterials/latticetransmat.h index 212dd3b7f..75f8aa322 100644 --- a/src/tm/latticetransmat.h +++ b/src/tm/Materials/LatticeMaterials/latticetransmat.h @@ -35,10 +35,10 @@ #ifndef latticetransmat_h #define latticetransmat_h -#include "transportmaterial.h" +#include "tm/Materials/transportmaterial.h" #include "dictionary.h" -#include "floatarray.h" -#include "floatmatrix.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "cltypes.h" #include "matstatus.h" @@ -67,33 +67,31 @@ class LatticeTransportMaterialStatus : public TransportMaterialStatus { protected: /// Liquid mass in element - double mass; - double oldPressure; + double mass = 0.; + double oldPressure = 0.; public: ///Constructor - LatticeTransportMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~LatticeTransportMaterialStatus() { } + LatticeTransportMaterialStatus(GaussPoint *g); - void printOutputAt(FILE *, TimeStep *); + void printOutputAt(FILE *, TimeStep *) const override; /// Returns pressure - double givePressure() { return field.at(1); } + double givePressure() const { return field; } - double giveOldPressure() { return oldPressure; } + double giveOldPressure() const { return oldPressure; } /// Sets the mass void setMass(double input) { this->mass = input; } /// Returns mass - double giveMass() { return this->mass; } + double giveMass() const { return this->mass; } - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual void initTempStatus(); + void initTempStatus() override; - virtual const char *giveClassName() const { return "LatticeTransportMaterialStatus"; } + const char *giveClassName() const override { return "LatticeTransportMaterialStatus"; } }; /** @@ -102,67 +100,61 @@ class LatticeTransportMaterialStatus : public TransportMaterialStatus class LatticeTransportMaterial : public TransportMaterial { protected: - ///Viscosity of fluid - double viscosity; + /// Viscosity of fluid + double viscosity = 0.; - ///Parameter of van Genuchten law - double paramM; + /// Parameter of van Genuchten law + double paramM = 0.; - ///Parameter of van Genuchten law - double paramA; + /// Parameter of van Genuchten law + double paramA = 0.; - ///Intrinsic permeability of porous material - double permeability; + /// Intrinsic permeability of porous material + double permeability = 0.; - ///Porosity of porous material - double porosity; + /// Porosity of porous material + double porosity = 0.; - ///Density of fluid - double density; + /// Density of fluid + double density = 0.; - ///Type of conductivity and capcity laws. - int conType; + /// Type of conductivity and capcity laws. + int conType = 0.; - ///Type of conductivity and capcity laws. - int capacity; + /// Type of conductivity and capcity laws. + int capacity = 0.; - ///Relative saturated water content - double thetaS; + /// Relative saturated water content + double thetaS = 0.; - ///Residual water content - double thetaR; + /// Residual water content + double thetaR = 0.; - ///modified water content - double thetaM; + /// Modified water content + double thetaM = 0.; - ///crack tortuosity - double crackTortuosity; + /// Crack tortuosity + double crackTortuosity = 0.; - ///crack limit - double crackLimit; + /// Crack limit + double crackLimit = 0.; + /// Suction air entry value + double suctionAirEntry = 0.; - ///suction air entry value - double suctionAirEntry; - - /// Material mode for convenient access. - MaterialMode matMode; public: - LatticeTransportMaterial(int n, Domain * d) : TransportMaterial(n, d) { } + LatticeTransportMaterial(int n, Domain *d) : TransportMaterial(n, d) { } - virtual ~LatticeTransportMaterial() { } + void initializeFrom(InputRecord &ir) override; - virtual void giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep); + FloatArrayF< 3 >computeFlux3D(const FloatArrayF< 3 > &grad, double field, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) {; } + FloatMatrixF< 3, 3 >computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override { return {}; } - virtual double giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + double giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const override; /** * Computes the conductivity. @@ -170,14 +162,14 @@ class LatticeTransportMaterial : public TransportMaterial * @param gp Integration point. * @param tStep Time step. */ - double computeConductivity(double suction, GaussPoint *gp, TimeStep *tStep); + double computeConductivity(double suction, GaussPoint *gp, TimeStep *tStep) const; /** * Computes the capacity. * @param suction Capillary stress * @param gp Integration point. */ - double computeCapacity(double suction, GaussPoint *gp); + double computeCapacity(double suction, GaussPoint *gp) const; /** * Computes the mass. @@ -185,16 +177,14 @@ class LatticeTransportMaterial : public TransportMaterial * @param gp Integration point. */ - double computeMass(FloatArray &stateVector, GaussPoint *gp); - - virtual const char *giveInputRecordName() const { return _IFT_LatticeTransportMaterial_Name; } - virtual const char *giveClassName() const { return "LatticeTransportMaterial"; } + double computeMass(FloatArray &stateVector, GaussPoint *gp) const; - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_LatticeTransportMaterial_Name; } + const char *giveClassName() const override { return "LatticeTransportMaterial"; } - virtual double give(int, GaussPoint *gp); + double give(int, GaussPoint *gp) const override; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; }; } // end namespace oofem #endif diff --git a/src/tm/anisomassmat.C b/src/tm/Materials/anisomassmat.C similarity index 56% rename from src/tm/anisomassmat.C rename to src/tm/Materials/anisomassmat.C index 61282c13e..c9a207d29 100644 --- a/src/tm/anisomassmat.C +++ b/src/tm/Materials/anisomassmat.C @@ -32,8 +32,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "anisomassmat.h" +#include "tm/Materials/anisomassmat.h" #include "floatmatrix.h" +#include "floatmatrixf.h" #include "gausspoint.h" #include "classfactory.h" @@ -42,61 +43,41 @@ namespace oofem { REGISTER_Material(AnisotropicMassTransferMaterial); -IRResultType -AnisotropicMassTransferMaterial :: initializeFrom(InputRecord *ir) +void +AnisotropicMassTransferMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - - ///@todo Why hardcode this for 2d ? Just take the whole matrix as the input instead and not worry about it. -#if 0 - IR_GIVE_FIELD(ir, k, _IFT_AnisotropicMassTransferMaterial_c); // Read permeability matrix c from input file -#else - FloatArray temp; - IR_GIVE_FIELD(ir, temp, _IFT_AnisotropicMassTransferMaterial_c); // Read permeability matrix c from input file - k.resize(2, 2); - k.at(1, 1) = temp.at(1); - k.at(1, 2) = temp.at(2); - k.at(2, 1) = temp.at(3); - k.at(2, 2) = temp.at(4); -#endif + TransportMaterial :: initializeFrom(ir); - return Material :: initializeFrom(ir); + FloatMatrix c; + IR_GIVE_FIELD(ir, c, _IFT_AnisotropicMassTransferMaterial_c); // Read permeability matrix c from input file + if ( c.giveNumberOfColumns() != 3 && c.giveNumberOfRows() != 3 ) { + throw ValueInputException(ir, _IFT_AnisotropicMassTransferMaterial_c, "c must be a 3x3"); + } + k = c; } -void -AnisotropicMassTransferMaterial :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) +FloatArrayF<3> +AnisotropicMassTransferMaterial :: computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const { - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - - answer.beProductOf(k, grad); - answer.negated(); - + auto ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); + auto answer = - dot(k, grad); ms->setTempField(field); ms->setTempGradient(grad); ms->setTempFlux(answer); + return answer; } -void -AnisotropicMassTransferMaterial :: giveCharacteristicMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +AnisotropicMassTransferMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - MaterialMode mMode = gp->giveMaterialMode(); - switch ( mMode ) { - case _1dHeat: - case _2dHeat: - case _3dHeat: - answer = k; - return; - - default: - OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mMode) ); - } + return k; } double -AnisotropicMassTransferMaterial :: giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +AnisotropicMassTransferMaterial :: giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { OOFEM_ERROR("unknown mode (%s)", __MatResponseModeToString(mode) ); diff --git a/src/tm/anisomassmat.h b/src/tm/Materials/anisomassmat.h similarity index 70% rename from src/tm/anisomassmat.h rename to src/tm/Materials/anisomassmat.h index fdb8c533a..047f21fdb 100644 --- a/src/tm/anisomassmat.h +++ b/src/tm/Materials/anisomassmat.h @@ -35,10 +35,8 @@ #ifndef anisomassmat_h #define anisomassmat_h -#include "transportmaterial.h" -#include "dictionary.h" -#include "floatarray.h" -#include "floatmatrix.h" +#include "tm/Materials/transportmaterial.h" +#include "floatmatrixf.h" ///@name Input fields for AnisotropicMassTransferMaterial //@{ @@ -60,22 +58,20 @@ namespace oofem { class AnisotropicMassTransferMaterial : public TransportMaterial { protected: - FloatMatrix k; ///< Conductivity/permeability matrix. This matrix is read from the input file and should be given row-wise as a vector of 4, eg "C 4 1 0 0 1". + FloatMatrixF<3,3> k; ///< Conductivity/permeability matrix. public: AnisotropicMassTransferMaterial(int n, Domain * d) : TransportMaterial(n, d) { } - virtual ~AnisotropicMassTransferMaterial() { } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual void giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep); + FloatArrayF<3> computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveCharacteristicMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + double giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual double giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - - virtual const char *giveInputRecordName() const { return _IFT_AnisotropicMassTransferMaterial_Name; } - virtual const char *giveClassName() const { return "AnisotropicMassTransferMaterial"; } + const char *giveInputRecordName() const override { return _IFT_AnisotropicMassTransferMaterial_Name; } + const char *giveClassName() const override { return "AnisotropicMassTransferMaterial"; } }; } // end namespace oofem #endif // anisomassmat_h diff --git a/src/tm/bazantnajjarmat.C b/src/tm/Materials/bazantnajjarmat.C similarity index 74% rename from src/tm/bazantnajjarmat.C rename to src/tm/Materials/bazantnajjarmat.C index 42251c94e..b4eb747f1 100644 --- a/src/tm/bazantnajjarmat.C +++ b/src/tm/Materials/bazantnajjarmat.C @@ -32,8 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "bazantnajjarmat.h" -#include "floatmatrix.h" +#include "tm/Materials/bazantnajjarmat.h" #include "gausspoint.h" #include "mathfem.h" #include "classfactory.h" @@ -41,10 +40,10 @@ namespace oofem { REGISTER_Material(BazantNajjarMoistureTransferMaterial); -IRResultType -BazantNajjarMoistureTransferMaterial :: initializeFrom(InputRecord *ir) +void +BazantNajjarMoistureTransferMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + IsotropicMoistureTransferMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, C1, _IFT_BazantNajjarMoistureTransferMaterial_c1); IR_GIVE_FIELD(ir, n, _IFT_BazantNajjarMoistureTransferMaterial_n); @@ -53,37 +52,29 @@ BazantNajjarMoistureTransferMaterial :: initializeFrom(InputRecord *ir) this->moistureCapacity = 1.; IR_GIVE_OPTIONAL_FIELD(ir, moistureCapacity, _IFT_BazantNajjarMoistureTransferMaterial_capa); - - return IsotropicMoistureTransferMaterial :: initializeFrom(ir); } double -BazantNajjarMoistureTransferMaterial :: giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep) +BazantNajjarMoistureTransferMaterial :: giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep) const { return this->moistureCapacity; } double -BazantNajjarMoistureTransferMaterial :: givePermeability(GaussPoint *gp, TimeStep *tStep) +BazantNajjarMoistureTransferMaterial :: givePermeability(GaussPoint *gp, TimeStep *tStep) const { - double permeability; - double humidity = this->giveHumidity(gp, VM_Total); - - humidity = max(humidity, 0.0); - humidity = min(humidity, 1.0); - - permeability = C1 * ( alpha0 + ( 1. - alpha0 ) / ( 1. + pow( ( 1. - humidity ) / ( 1. - hC ), n ) ) ); - return permeability; + double humidity = clamp(this->giveHumidity(gp, VM_Total), 0., 1.); + return C1 * ( alpha0 + ( 1. - alpha0 ) / ( 1. + pow( ( 1. - humidity ) / ( 1. - hC ), n ) ) ); } double -BazantNajjarMoistureTransferMaterial :: giveHumidity(GaussPoint *gp, ValueModeType mode) +BazantNajjarMoistureTransferMaterial :: giveHumidity(GaussPoint *gp, ValueModeType mode) const { - FloatArray tempState = static_cast< TransportMaterialStatus * >( giveStatus(gp) )->giveTempField(); - if ( ( tempState.at(1) > 1.0 ) || ( tempState.at(1) < 0.0 ) ) { - OOFEM_WARNING("Relative humidity %.5f is out of range 0.0 - 1.0", tempState.at(1) ); + auto field = static_cast< TransportMaterialStatus * >( giveStatus(gp) )->giveTempField(); + if ( ( field > 1.0 ) || ( field < 0.0 ) ) { + OOFEM_WARNING("Relative humidity %.5f is out of range 0.0 - 1.0", field ); } - return tempState.at(1); + return field; } } // end namespace oofem diff --git a/src/tm/bazantnajjarmat.h b/src/tm/Materials/bazantnajjarmat.h similarity index 80% rename from src/tm/bazantnajjarmat.h rename to src/tm/Materials/bazantnajjarmat.h index 130cece04..7b55b2b29 100644 --- a/src/tm/bazantnajjarmat.h +++ b/src/tm/Materials/bazantnajjarmat.h @@ -35,7 +35,7 @@ #ifndef bazantnajjarmat_h #define bazantnajjarmat_h -#include "isomoisturemat.h" +#include "tm/Materials/isomoisturemat.h" #include "floatarray.h" #include "floatmatrix.h" @@ -58,32 +58,31 @@ class BazantNajjarMoistureTransferMaterial : public IsotropicMoistureTransferMat { protected: /// sorption isotherm derivative [kg/m^3] - double moistureCapacity; + double moistureCapacity = 0.; /// maximal permeability [kg/ m s] - double C1; + double C1 = 0.; /// exponent in nonlinear permeability function [-] - double n; + double n = 0.; /// fraction minimal/maximal permeability [-] - double alpha0; + double alpha0 = 0.; /// nonlinear threshold [-] - double hC; + double hC = 0.; public: BazantNajjarMoistureTransferMaterial(int n, Domain * d) : IsotropicMoistureTransferMaterial(n, d) { } - virtual ~BazantNajjarMoistureTransferMaterial() { } /// evaluates permeability according to Bazant - Najjar function for diffusivity - virtual double givePermeability(GaussPoint *gp, TimeStep *tStep); + double givePermeability(GaussPoint *gp, TimeStep *tStep) const override; /// evaluates slope of the sorption isotherm - virtual double giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep); + double giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep) const override; - virtual const char *giveInputRecordName() const { return _IFT_BazantNajjarMoistureTransferMaterial_Name; } - virtual const char *giveClassName() const { return "BazantNajjarMoistureTransferMaterial"; } + const char *giveInputRecordName() const override { return _IFT_BazantNajjarMoistureTransferMaterial_Name; } + const char *giveClassName() const override { return "BazantNajjarMoistureTransferMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - virtual double giveHumidity(GaussPoint *gp, ValueModeType mode); + double giveHumidity(GaussPoint *gp, ValueModeType mode) const override; }; } // end namespace oofem #endif // bazantnajjarmat_h diff --git a/src/tm/cemhyd/cemhydmat.C b/src/tm/Materials/cemhyd/cemhydmat.C similarity index 99% rename from src/tm/cemhyd/cemhydmat.C rename to src/tm/Materials/cemhyd/cemhydmat.C index 57eee5388..36ec40331 100644 --- a/src/tm/cemhyd/cemhydmat.C +++ b/src/tm/Materials/cemhyd/cemhydmat.C @@ -51,6 +51,7 @@ #include #include +//#include "tm/Materials/cemhyd/cemhydmat.h" #include "cemhydmat.h" #include "homogenize.h" #include "mathfem.h" @@ -94,15 +95,12 @@ REGISTER_Material(CemhydMat); CemhydMat :: CemhydMat(int n, Domain *d) : IsotropicHeatTransferMaterial(n, d) { - MasterCemhydMatStatus = NULL; + MasterCemhydMatStatus = nullptr; } -CemhydMat :: ~CemhydMat() -{ } - //returns hydration power [W/m3 of concrete] void -CemhydMat :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +CemhydMat :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const { double averageTemperature; CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); @@ -134,7 +132,7 @@ CemhydMat :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeSt int CemhydMat :: giveCycleNumber(GaussPoint *gp) { - CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); if ( MasterCemhydMatStatus ) { ms = MasterCemhydMatStatus; } @@ -144,7 +142,7 @@ int CemhydMat :: giveCycleNumber(GaussPoint *gp) double CemhydMat :: giveTimeOfCycle(GaussPoint *gp) { - CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); if ( MasterCemhydMatStatus ) { ms = MasterCemhydMatStatus; } @@ -156,7 +154,7 @@ double CemhydMat :: giveTimeOfCycle(GaussPoint *gp) double CemhydMat :: giveDoHActual(GaussPoint *gp) { - CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); if ( MasterCemhydMatStatus ) { ms = MasterCemhydMatStatus; } @@ -165,9 +163,9 @@ double CemhydMat :: giveDoHActual(GaussPoint *gp) } //standard units are [Wm-1K-1] -double CemhydMat :: giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) +double CemhydMat :: giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) const { - CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); double conduct = 0.0; if ( MasterCemhydMatStatus ) { @@ -196,9 +194,9 @@ double CemhydMat :: giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) } //normally it returns J/kg/K of concrete -double CemhydMat :: giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep) +double CemhydMat :: giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep) const { - CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); double capacityConcrete = 0.0; if ( MasterCemhydMatStatus ) { @@ -227,9 +225,9 @@ double CemhydMat :: giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep) return capacityConcrete; } -double CemhydMat :: giveConcreteDensity(GaussPoint *gp, TimeStep *tStep) +double CemhydMat :: giveConcreteDensity(GaussPoint *gp, TimeStep *tStep) const { - CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); double concreteBulkDensity = 0.0; if ( MasterCemhydMatStatus ) { @@ -257,15 +255,15 @@ double CemhydMat :: giveConcreteDensity(GaussPoint *gp, TimeStep *tStep) } double -CemhydMat :: giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +CemhydMat :: giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { if ( mode == Capacity ) { return ( giveConcreteCapacity(gp, tStep) * giveConcreteDensity(gp, tStep) ); } else if ( mode == IntSource ) { //for nonlinear solver, return dHeat/dTemperature - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); //it suffices to compute derivative of Arrhenius equation //double actualTemperature = status->giveTempField().at(1); - double lastEquilibratedTemperature = status->giveField().at(1); + double lastEquilibratedTemperature = status->giveField(); //double dt = tStep->giveTimeIncrement(); double krate, EaOverR, val; CemhydMatStatus *ms = static_cast< CemhydMatStatus * >( this->giveStatus(gp) ); @@ -356,16 +354,16 @@ CemhydMat :: initMaterial(Element *element) for ( GaussPoint *gp: *element->giveDefaultIntegrationRulePtr() ) { CemhydMatStatus *ms; if ( !MasterCemhydMatStatus && !eachGP ) { - ms = new CemhydMatStatus(1, domain, gp, NULL, this, 1); + ms = new CemhydMatStatus(gp, NULL, this, 1); MasterCemhydMatStatus = ms; } else if ( eachGP ) { - ms = new CemhydMatStatus(1, domain, gp, MasterCemhydMatStatus, this, 1); + ms = new CemhydMatStatus(gp, MasterCemhydMatStatus, this, 1); } else { - ms = new CemhydMatStatus(1, domain, gp, NULL, this, 0); + ms = new CemhydMatStatus(gp, nullptr, this, 0); } // if(!gp->giveMaterialStatus()){ - gp->setMaterialStatus( ms, this->giveNumber() ); + gp->setMaterialStatus( ms ); // } } @@ -404,13 +402,11 @@ void CemhydMat :: averageTemperature() } } -IRResultType CemhydMat :: initializeFrom(InputRecord *ir) +void CemhydMat :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro castingTime = 0.; - result = IsotropicHeatTransferMaterial :: initializeFrom(ir); //read d,k,c - if ( result != IRRT_OK ) return result; + IsotropicHeatTransferMaterial :: initializeFrom(ir); //read d,k,c conductivityType = 0; capacityType = 0; @@ -441,8 +437,6 @@ IRResultType CemhydMat :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, reinforcementDegree, _IFT_CemhydMat_reinforcementDegree); IR_GIVE_FIELD(ir, XMLfileName, _IFT_CemhydMat_inputFileName); - - return IRRT_OK; } @@ -456,7 +450,8 @@ CemhydMat :: CreateStatus(GaussPoint *gp) const //constructor allowing to copy a microstructure from another CemhydMatStatus //particular instance of CemhydMat in an integration point -CemhydMatStatus :: CemhydMatStatus(int n, Domain *d, GaussPoint *gp, CemhydMatStatus *CemStat, CemhydMat *cemhydmat, bool withMicrostructure) : TransportMaterialStatus(n, d, gp) +CemhydMatStatus :: CemhydMatStatus(GaussPoint *gp, CemhydMatStatus *CemStat, CemhydMat *cemhydmat, bool withMicrostructure) : + TransportMaterialStatus(gp) { int i, j, k; PartHeat = 0.; @@ -4655,7 +4650,7 @@ int CemhydMatStatus :: countboxc(int boxsize, int qx, int qy, int qz) void CemhydMatStatus :: makeinert(long int ndesire) { - struct togo *headtogo, *tailtogo, *newtogo, *lasttogo, *onetogo; + struct togo *headtogo, *tailtogo, *newtogo = nullptr, *lasttogo, *onetogo; long int idesire; int px, py, pz, placed, cntpore, cntmax; @@ -14393,7 +14388,7 @@ double CemhydMatStatus :: giveAverageTemperature() if ( !cemhydmat->eachGP ) { ret = cemhydmat->MasterCemhydMatStatus->averageTemperature; } else { - ret = ms->giveField().at(1); + ret = ms->giveField(); } return ret; @@ -14401,13 +14396,10 @@ double CemhydMatStatus :: giveAverageTemperature() void -CemhydMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) +CemhydMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { CemhydMat *cemhydmat = static_cast< CemhydMat * >( this->gp->giveMaterial() ); - CemhydMatStatus *ms = this; - if ( cemhydmat->MasterCemhydMatStatus ) { - ms = cemhydmat->MasterCemhydMatStatus; - } + const auto ms = cemhydmat->MasterCemhydMatStatus ? cemhydmat->MasterCemhydMatStatus : this; TransportMaterialStatus :: printOutputAt(file, tStep); fprintf(file, " status {"); diff --git a/src/tm/cemhyd/cemhydmat.h b/src/tm/Materials/cemhyd/cemhydmat.h similarity index 96% rename from src/tm/cemhyd/cemhydmat.h rename to src/tm/Materials/cemhyd/cemhydmat.h index d21c17eeb..f98345f89 100644 --- a/src/tm/cemhyd/cemhydmat.h +++ b/src/tm/Materials/cemhyd/cemhydmat.h @@ -51,7 +51,7 @@ using namespace tinyxml2; #ifdef __TM_MODULE //OOFEM transport module #include "domain.h" - #include "../isoheatmat.h" + #include "tm/Materials/isoheatmat.h" #endif ///@name Input fields for CemhydMat @@ -94,14 +94,12 @@ class CemhydMat : public IsotropicHeatTransferMaterial public: /// Constructor CemhydMat(int n, Domain * d); - /// Destructor - virtual ~CemhydMat(); /// Returns input record name of the receiver. - virtual const char *giveInputRecordName() const { return _IFT_CemhydMat_Name; } - virtual const char *giveClassName() const { return "CemhydMat"; } + const char *giveInputRecordName() const override { return _IFT_CemhydMat_Name; } + const char *giveClassName() const override { return "CemhydMat"; } - virtual int hasInternalSource() { return 1; } - virtual void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + bool hasInternalSource() const override { return true; } + void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; /// Returns cycle number at the closest cycle after the target time virtual int giveCycleNumber(GaussPoint *gp); /// Returns time of the CEMHYD3D at the first cycle after the target time @@ -109,17 +107,17 @@ class CemhydMat : public IsotropicHeatTransferMaterial /// Returns DoH of the closest CEMHYD3D cycle after the target time virtual double giveDoHActual(GaussPoint *gp); /// Returns concrete heat conductivity depending on chosen type - virtual double giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep); + double giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) const override; /// Returns concrete thermal capacity depending on chosen type - virtual double giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep); + virtual double giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep) const; /// Returns concrete density depending on chosen type - virtual double giveConcreteDensity(GaussPoint *gp, TimeStep *tStep); + virtual double giveConcreteDensity(GaussPoint *gp, TimeStep *tStep) const; /// Compute heat thermal capacity per volume. - virtual double giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); + double giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual int initMaterial(Element *element); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + int initMaterial(Element *element) override; /// Clear temperatures multiplied with volume around GPs - need before temperature averaging. virtual void clearWeightTemperatureProductVolume(Element *element); /// Store temperatures multiplied with volume around GPs - need before temperature averaging. @@ -127,7 +125,7 @@ class CemhydMat : public IsotropicHeatTransferMaterial /// Perform averaging on a master CemhydMatStatus. virtual void averageTemperature(); - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; /// Use different methods to evaluate material parameters int conductivityType, capacityType, densityType; /// Array containing warnings supression for density, conductivity, capacity, high temperature. @@ -140,7 +138,7 @@ class CemhydMat : public IsotropicHeatTransferMaterial int eachGP; /// XML input file name for CEMHYD3D. std :: string XMLfileName; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; /** * Pointer to master CemhydMatStatus, which is shared among related integration points (on element, for example). * When Cemhyd3D runs seperately in each GP, MasterCemhydMatStatus belongs to the first instance, from which the microstructure is copied to the rest of integration points. @@ -163,12 +161,12 @@ class CemhydMatStatus : public TransportMaterialStatus * @param CemStat A pointer to existing microstructure, from which the 3D image is copied. * @param withMicrostructure Creates also 3D microstructure representation at the integration point. */ - CemhydMatStatus(int n, Domain * d, GaussPoint * gp, CemhydMatStatus * CemStat, CemhydMat * cemhydmat, bool withMicrostructure); + CemhydMatStatus(GaussPoint * gp, CemhydMatStatus * CemStat, CemhydMat * cemhydmat, bool withMicrostructure); virtual ~CemhydMatStatus(); - //virtual Interface *giveInterface(InterfaceType); - virtual const char *giveClassName() const { return "CemhydMatStatus"; } - virtual void updateYourself(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); + //Interface *giveInterface(InterfaceType) override; + const char *giveClassName() const override { return "CemhydMatStatus"; } + void updateYourself(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) const override; #elif CEMPY #define OUTFILES #define IMAGEFILES @@ -176,8 +174,8 @@ class CemhydMatStatus : public TransportMaterialStatus class CemhydMatStatus { public: - CemhydMatStatus(void); - ~CemhydMatStatus(void); + CemhydMatStatus(); + ~CemhydMatStatus(); void InitializePy(const char *inp); #endif FILE *in; diff --git a/src/tm/Materials/hemobaznajmat.C b/src/tm/Materials/hemobaznajmat.C new file mode 100644 index 000000000..cd6c2771c --- /dev/null +++ b/src/tm/Materials/hemobaznajmat.C @@ -0,0 +1,199 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "tm/Materials/hemobaznajmat.h" +#include "floatmatrixf.h" +#include "gausspoint.h" +#include "mathfem.h" +#include "classfactory.h" + +namespace oofem { + +REGISTER_Material( HeMoBazNajMaterial ); + +bool +HeMoBazNajMaterial :: hasMaterialModeCapability(MaterialMode mode) const +{ + return mode == _2dHeMo || mode == _3dHeMo; +} + + +void +HeMoBazNajMaterial :: initializeFrom(InputRecord &ir) +{ + Material :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, C1, _IFT_HeMoBazNajMaterial_c1); + IR_GIVE_FIELD(ir, n, _IFT_HeMoBazNajMaterial_n); + IR_GIVE_FIELD(ir, alpha0, _IFT_HeMoBazNajMaterial_alpha0); + IR_GIVE_FIELD(ir, hC, _IFT_HeMoBazNajMaterial_hc); + + this->moistureCapacity = 1.; + IR_GIVE_OPTIONAL_FIELD(ir, moistureCapacity, _IFT_HeMoBazNajMaterial_capa); + + IR_GIVE_FIELD(ir, heatConductivity, _IFT_HeMoBazNajMaterial_k); + IR_GIVE_FIELD(ir, heatCapacity, _IFT_HeMoBazNajMaterial_c); +} + + +double +HeMoBazNajMaterial :: give(int aProperty, GaussPoint *gp) const +{ + return this->Material :: give(aProperty, gp); +} + + +std::pair, FloatArrayF<3>> +HeMoBazNajMaterial :: computeHeMoFlux3D(const FloatArrayF<3> &grad_t, const FloatArrayF<3> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const +{ + auto ms = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + + auto ans_w = perm_mm(h, t) * grad_w + perm_mh(h, t) * grad_t; + auto ans_t = perm_hm(h, t) * grad_w + perm_hh(h, t) * grad_t; + + ms->setTempTemperature(t); + ms->setTempTemperatureGradient(grad_t); + ms->setTempHeatFlux(ans_t); + ms->setTempHumidity(h); + ms->setTempHumidityGradient(grad_w); + ms->setTempHumidityFlux(ans_w); + + return {ans_t, ans_w}; +} + + +FloatMatrixF<3,3> +HeMoBazNajMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto status = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + + double t = status->giveTempTemperature(); + double h = status->giveTempHumidity(); + + double k = 0.0; + if ( mode == Conductivity_ww ) { + k = perm_mm(h, t); + } else if ( mode == Conductivity_wh ) { + k = perm_mh(h, t); + } else if ( mode == Conductivity_hw ) { + k = perm_hm(h, t); + } else if ( mode == Conductivity_hh ) { + k = perm_hh(h, t); + } else { + OOFEM_ERROR("Unknown MatResponseMode"); + } + + return k * eye<3>(); +} + + +double +HeMoBazNajMaterial :: giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *atTime) const +{ + return this->computeCapacityCoeff(mode, gp, atTime); +} + + +double HeMoBazNajMaterial :: computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) const +{ + if ( mode == Capacity_ww ) { + return this->moistureCapacity; + + } else if ( mode == Capacity_wh ) { + return 0.0; + + } else if ( mode == Capacity_hw ) { + return 0.0; + + } else if ( mode == Capacity_hh ) { + return this->heatCapacity; + + } else { + OOFEM_ERROR("Unknown MatResponseMode"); + return 0.; + } +} + + +double +HeMoBazNajMaterial :: perm_mm(double h, double T) const +{ + return C1 * ( alpha0 + ( 1. - alpha0 ) / ( 1. + pow( ( 1. - h ) / ( 1. - hC ), n ) ) ); +} + +double +HeMoBazNajMaterial :: perm_mh(double h, double T) const +{ + return 0.; +} + +double +HeMoBazNajMaterial :: perm_hm(double h, double T) const +{ + return 0.; +} + +double +HeMoBazNajMaterial :: perm_hh(double h, double T) const +{ + return this->heatConductivity; +} + +bool +HeMoBazNajMaterial :: isCharacteristicMtrxSymmetric(MatResponseMode mode) const +{ + if ( mode == Conductivity_ww || mode == Conductivity_hh || mode == Conductivity_hw || mode == Conductivity_wh ) { + return true; + } else { + OOFEM_ERROR( "isCharacteristicMtrxSymmetric : unknown mode (%s)", __MatResponseModeToString(mode) ); + } + + return false; // to make compiler happy +} + +int +HeMoBazNajMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime) +// IST_Humidity overriden to use inverse_sorption_isotherm +{ + if ( type == IST_Humidity ) { + answer.resize(1); + answer.at(1) = giveHumidity(gp, VM_Velocity); // VM_Previous = equilibrated value of humidity + return 1; + } else { + return TransportMaterial :: giveIPValue(answer, gp, type, atTime); + } +} +} // end namespace oofem diff --git a/src/tm/hemobaznajmat.h b/src/tm/Materials/hemobaznajmat.h similarity index 56% rename from src/tm/hemobaznajmat.h rename to src/tm/Materials/hemobaznajmat.h index cd25e2320..a13c56110 100644 --- a/src/tm/hemobaznajmat.h +++ b/src/tm/Materials/hemobaznajmat.h @@ -35,7 +35,7 @@ #ifndef hemobaznajmat_h #define hemobaznajmat_h -#include "transportmaterial.h" +#include "tm/Materials/transportmaterial.h" ///@name Input fields for HeMoBazNajMaterial //@{ @@ -55,73 +55,55 @@ namespace oofem { class HeMoBazNajMaterial : public TransportMaterial { protected: - /// sorption isotherm derivative [kg/m^3] - double moistureCapacity; + double moistureCapacity = 0.; /// maximal permeability [kg/ m s] - double C1; + double C1 = 0.; /// exponent in nonlinear permeability function [-] - double n; + double n = 0.; /// fraction minimal/maximal permeability [-] - double alpha0; + double alpha0 = 0.; /// nonlinear threshold [-] - double hC; - - double heatConductivity; ///< Conductivity (k in input file). - double heatCapacity; ///< Capacity (c in input file). + double hC = 0.; + double heatConductivity = 0.; ///< Conductivity (k in input file). + double heatCapacity = 0.; ///< Capacity (c in input file). public: - /** * Constructor. Creates material with given number, belonging to given domain. * @param n Material number. * @param d Domain to which new material will belong. */ HeMoBazNajMaterial(int n, Domain *d) : TransportMaterial(n, d) { } - /// Destructor. - virtual ~HeMoBazNajMaterial() { } - virtual void giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep); + std::pair, FloatArrayF<3>> computeHeMoFlux3D(const FloatArrayF<3> &grad_t, const FloatArrayF<3> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *atTime); + double giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual double giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *atTime); + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override; - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode); + void initializeFrom(InputRecord &ir) override; - virtual IRResultType initializeFrom(InputRecord *ir); + double give(int aProperty, GaussPoint *gp) const override; - virtual double give(int aProperty, GaussPoint *gp); + bool hasMaterialModeCapability(MaterialMode mode) const override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual int hasMaterialModeCapability(MaterialMode mode); + const char *giveInputRecordName() const override { return _IFT_HeMoBazNajMaterial_Name; } + const char *giveClassName() const override { return "HeMoBazNajMaterial"; } - // identification - virtual const char *giveInputRecordName() const { return _IFT_HeMoBazNajMaterial_Name; } - virtual const char *giveClassName() const { return "HeMoBazNajMaterial"; } + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new HeMoTransportMaterialStatus(gp); } protected: - void computeConductivityMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *atTime); - void matcond1d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime); - void matcond2d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime); - void matcond3d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime); - - double computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *atTime); - - double perm_mm(double h, double T); - double perm_mh(double h, double T); - double perm_hm(double h, double T); - double perm_hh(double h, double T); - + double computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; - // post-processing, poi export - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime); + double perm_mm(double h, double T) const; + double perm_mh(double h, double T) const; + double perm_hm(double h, double T) const; + double perm_hh(double h, double T) const; }; } // end namespace oofem #endif // hemobaznajmat_h diff --git a/src/tm/Materials/hemokunzelmat.C b/src/tm/Materials/hemokunzelmat.C new file mode 100644 index 000000000..474555263 --- /dev/null +++ b/src/tm/Materials/hemokunzelmat.C @@ -0,0 +1,421 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "tm/Materials/hemokunzelmat.h" +#include "floatmatrixf.h" +#include "gausspoint.h" +#include "mathfem.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(HeMoKunzelMaterial); + +bool +HeMoKunzelMaterial :: hasMaterialModeCapability(MaterialMode mode) const +{ + return mode == _2dHeMo || mode == _3dHeMo; +} + + +void +HeMoKunzelMaterial :: initializeFrom(InputRecord &ir) +{ + Material :: initializeFrom(ir); + + int type = 0; + IR_GIVE_OPTIONAL_FIELD(ir, type, _IFT_HeMoKunzelMaterial_iso_type); + this->Isotherm = ( isothermType ) type; + + if ( this->Isotherm == Hansen ) { + IR_GIVE_FIELD(ir, iso_wh, _IFT_HeMoKunzelMaterial_iso_wh); + IR_GIVE_FIELD(ir, iso_n, _IFT_HeMoKunzelMaterial_iso_n); + IR_GIVE_FIELD(ir, iso_a, _IFT_HeMoKunzelMaterial_iso_a); + } else if ( this->Isotherm == Kunzeliso ) { + IR_GIVE_FIELD(ir, iso_wh, _IFT_HeMoKunzelMaterial_iso_wh); + IR_GIVE_FIELD(ir, iso_b, _IFT_HeMoKunzelMaterial_iso_b); + } else { + OOFEM_ERROR("Unknown Isotherm type"); + } + + + IR_GIVE_FIELD(ir, type, _IFT_HeMoKunzelMaterial_permeability_type); + + if ( type >= 3 ) { + OOFEM_ERROR("initializeFrom: isothermType must be equal to 0, 1, 2"); + } + + this->Permeability = ( permeabilityType ) type; + + if ( this->Permeability == Multilin_h ) { + IR_GIVE_FIELD(ir, perm_h, _IFT_HeMoKunzelMaterial_perm_h); + IR_GIVE_FIELD(ir, perm_Dwh, _IFT_HeMoKunzelMaterial_perm_dwh); + + if ( !( perm_h.giveSize() == perm_Dwh.giveSize() ) ) { + OOFEM_ERROR("initializeFrom: the size of 'perm_h' and 'perm_dw(h)' must be the same"); + } + + for ( int i = 1; i < perm_h.giveSize(); i++ ) { + if ( ( perm_h.at(i) < 0. ) || ( perm_h.at(i) > 1. ) ) { + OOFEM_ERROR("initializeFrom: perm_h must be in the range <0; 1>"); + } + } + } else if ( this->Permeability == Multilin_wV ) { + IR_GIVE_FIELD(ir, perm_wV, _IFT_HeMoKunzelMaterial_perm_wv); + IR_GIVE_FIELD(ir, perm_DwwV, _IFT_HeMoKunzelMaterial_perm_dwwv); + + if ( !( perm_wV.giveSize() == perm_DwwV.giveSize() ) ) { + OOFEM_ERROR("initializeFrom: the size of 'perm_h' and 'perm_dw(h)' must be the same"); + } + + for ( int i = 1; i < perm_wV.giveSize(); i++ ) { + if ( ( perm_wV.at(i) < 0. ) || ( perm_wV.at(i) > 1. ) ) { + OOFEM_ERROR("initializeFrom: perm_wv must be in the range <0; 1>"); + } + } + } else if ( this->Permeability == Kunzelperm ) { + IR_GIVE_FIELD(ir, A, _IFT_HeMoKunzelMaterial_a); + } else { + OOFEM_ERROR("initializeFrom: permeabilityType must be equal to 0, 1 or 2"); + } + + IR_GIVE_FIELD(ir, mu, _IFT_HeMoKunzelMaterial_mu); + + PL = 101325.; + IR_GIVE_OPTIONAL_FIELD(ir, PL, _IFT_HeMoKunzelMaterial_pl); + + rhoH2O = 1000.; + IR_GIVE_OPTIONAL_FIELD(ir, rhoH2O, _IFT_HeMoKunzelMaterial_rhoh2o); + + IR_GIVE_FIELD(ir, lambda0, _IFT_HeMoKunzelMaterial_lambda0); + IR_GIVE_FIELD(ir, b, _IFT_HeMoKunzelMaterial_b); + IR_GIVE_FIELD(ir, cs, _IFT_HeMoKunzelMaterial_cs); + + // cw = 4.1813e3; + cw = 4183.; + IR_GIVE_OPTIONAL_FIELD(ir, cw, _IFT_HeMoKunzelMaterial_cw); + + hv = 2.5e6; + IR_GIVE_OPTIONAL_FIELD(ir, hv, _IFT_HeMoKunzelMaterial_hv); +} + + +double +HeMoKunzelMaterial :: give(int aProperty, GaussPoint *gp) const +{ + return Material :: give(aProperty, gp); +} + + +std::pair, FloatArrayF<3>> +HeMoKunzelMaterial :: computeHeMoFlux3D(const FloatArrayF<3> &grad_t, const FloatArrayF<3> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const +{ + auto ms = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + + ms->setTempTemperature(t); + ms->setTempHumidity(h); + + ms->setTempTemperatureGradient(grad_t); + ms->setTempHumidityGradient(grad_w); + + auto ans_t = -perm_hm(h, t) * grad_w - perm_hh(h, t) * grad_t; + auto ans_w = -perm_mm(h, t) * grad_w - perm_mh(h, t) * grad_t; + + ms->setTempHeatFlux(ans_t); + ms->setTempHumidityFlux(ans_w); + + return {ans_t, ans_w}; +} + + +FloatMatrixF<3,3> +HeMoKunzelMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto status = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + + double t = status->giveTempTemperature(); + double h = status->giveTempHumidity(); + + double k = 0.0; + if ( mode == Conductivity_ww ) { + k = perm_mm(h, t); + } else if ( mode == Conductivity_wh ) { + k = perm_mh(h, t); + } else if ( mode == Conductivity_hw ) { + k = perm_hm(h, t); + } else if ( mode == Conductivity_hh ) { + k = perm_hh(h, t); + } else { + OOFEM_ERROR("Unknown MatResponseMode"); + } + + return k * eye<3>(); +} + + +double +HeMoKunzelMaterial :: giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const +{ + return this->computeCapacityCoeff(mode, gp, tStep); +} + + +double HeMoKunzelMaterial :: computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + // if (gp->giveElement()->giveNumber() == 4) + // double bzzz = 20; + + if ( mode == Capacity_ww ) { + auto status = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + + double h = status->giveTempHumidity(); + return this->giveMoistureContentDerivative(h); + } else if ( mode == Capacity_wh ) { + return 0.0; + } else if ( mode == Capacity_hw ) { + return 0.0; + } else if ( mode == Capacity_hh ) { + auto status = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + + double h = status->giveTempHumidity(); + double w = this->giveMoistureContent(h); + + double dHs_dT = cs * give('d', nullptr); + double dHw_dT = cw * w; + + return dHs_dT + dHw_dT; + + // CONSTANT return 1.7e6; + } else { + OOFEM_ERROR("Unknown MatResponseMode"); + } + + return 0.0; // to make compiler happy +} + + +double +HeMoKunzelMaterial :: giveMoistureContent(double h) const +{ + if ( h < 0.0 || h > 1.00 ) { + OOFEM_ERROR("HeMoKunzelMaterial :: giveMoistureContent : Relative humidity %.3f is out of range", h); + } + + if ( this->Isotherm == Hansen ) { + return iso_wh * pow( ( 1.0 - log(h) / iso_a ), ( -1.0 / iso_n ) ); + } else if ( this->Isotherm == Kunzeliso ) { + return iso_wh * ( iso_b - 1. ) * h / ( iso_b - h ); + } else { + OOFEM_ERROR("Unknown Isotherm type"); + return 0.; + } +} + +double +HeMoKunzelMaterial :: giveMoistureContentDerivative(double h) const +{ + if ( h < 0.0 || h > 1.00 ) { + OOFEM_ERROR("HeMoKunzelMaterial :: giveMoistureContentDerivative : Relative humidity %.3f is out of range", h); + } + + if ( this->Isotherm == Hansen ) { + return iso_wh / ( iso_n * iso_a * h ) * pow( ( 1.0 - log(h) / iso_a ), ( -( 1.0 + iso_n ) / iso_n ) ); + } else if ( this->Isotherm == Kunzeliso ) { + return iso_wh * ( iso_b - 1. ) * iso_b / ( ( iso_b - h ) * ( iso_b - h ) ); + } else { + OOFEM_ERROR("Unknown Isotherm type"); + return 0.; + } +} + + +double +HeMoKunzelMaterial :: computeWaterVaporPerm(double T) const +{ + // vapor diffusion coefficient in air [kg m^-1 s^-1 Pa^-1] + double delta = 2.0 * 1.e-7 * pow(T, 0.81) / PL; + return delta / mu; +} + +double +HeMoKunzelMaterial :: computeSatVaporPressure(double T) const +{ + double T_C = T - 273.15; + + double T0, a; + if ( T_C < 0. ) { + a = 22.44; + T0 = 272.44; + } else { + a = 17.08; + T0 = 234.18; + } + + return 611. * exp( a * T_C / ( T0 + T_C ) ); +} + +double +HeMoKunzelMaterial :: computeSatVaporPressureDerivative(double T) const +{ + double T_C = T - 273.15; + + double T0, a; + if ( T_C < 0. ) { + a = 22.44; + T0 = 272.44; + } else { + a = 17.08; + T0 = 234.18; + } + + return 611. *a *T0 *exp( a *T_C / ( T0 + T_C ) ) / ( ( T0 + T_C ) * ( T0 + T_C ) ); +} + + +double +HeMoKunzelMaterial :: computeDw(double h) const +{ + if ( this->Permeability == Multilin_h ) { + double tol = 1.e-10; + for ( int i = 1; i <= perm_h.giveSize(); i++ ) { + if ( ( h - perm_h.at(i) ) < tol ) { + return perm_Dwh.at(i - 1) + ( perm_Dwh.at(i) - perm_Dwh.at(i - 1) ) * ( h - perm_h.at(i - 1) ) / ( perm_h.at(i) - perm_h.at(i - 1) ); + } + } + } else if ( this->Permeability == Multilin_wV ) { + double wV = this->giveMoistureContent(h) / rhoH2O; + double tol = 1.e-10; + for ( int i = 1; i <= perm_wV.giveSize(); i++ ) { + if ( ( wV - perm_wV.at(i) ) < tol ) { + return perm_DwwV.at(i - 1) + ( perm_DwwV.at(i) - perm_DwwV.at(i - 1) ) * ( wV - perm_wV.at(i - 1) ) / ( perm_wV.at(i) - perm_wV.at(i - 1) ); + } + } + } else if ( this->Permeability == Kunzelperm ) { + double w; + w = this->giveMoistureContent(h); + return 3.8 * ( A / iso_wh ) * ( A / iso_wh ) * pow(1000., w / iso_wh - 1.); + } else { + OOFEM_ERROR("initializeFrom: permeabilityType must be equal to 0, 1 or 2"); + } + + return 0.; +} + + +double +HeMoKunzelMaterial :: perm_mm(double h, double T) const +{ + // Function calculates permability relative humidity - relative humidity (k_mm) + // h ... relative humidity + // Dw ... capillary transport coefficient [m^2/s] + // dw_dh ... derivative of moisture storage function [kg/m^3] + // p_sat ... saturation water vapor pressure + + double dw_dh = this->giveMoistureContentDerivative(h); + + double Dw = this->computeDw(h); + + double deltap = this->computeWaterVaporPerm(T); + double p_sat = this->computeSatVaporPressure(T); + + return Dw * dw_dh + deltap * p_sat; +} + +double +HeMoKunzelMaterial :: perm_mh(double h, double T) const +{ + // Function calculates permeability relative humidity-temperature (k_mh) + // deltap ... water vapor permeability + // dpsat_dt ... differentiation of saturation water vapor presssure with respect to temperature + double delta_p = computeWaterVaporPerm(T); + double dpsat_dT = computeSatVaporPressureDerivative(T); + + return delta_p * h * dpsat_dT; +} + + +double +HeMoKunzelMaterial :: perm_hm(double h, double T) const +{ + // Function calculates permability temperature-relative humidity (k_hm) + double deltap = this->computeWaterVaporPerm(T); + double p_sat = this->computeSatVaporPressure(T); + return hv * deltap * p_sat; +} + +double +HeMoKunzelMaterial :: perm_hh(double h, double T) const +{ + // Function calculates permability water temperature-temperature (k_hh) + + double w = this->giveMoistureContent(h); + double lambda = lambda0 * ( 1. + b * w / give('d', nullptr) ); + double deltap = this->computeWaterVaporPerm(T); + double dpsat_dT = computeSatVaporPressureDerivative(T); + + return lambda + hv * deltap * h * dpsat_dT; +} + +bool +HeMoKunzelMaterial :: isCharacteristicMtrxSymmetric(MatResponseMode mode) const +{ + if ( mode == Conductivity_ww || mode == Conductivity_hh || mode == Conductivity_hw || mode == Conductivity_wh ) { + return false; + } else { + OOFEM_ERROR( "isCharacteristicMtrxSymmetric : unknown mode (%s)", __MatResponseModeToString(mode) ); + } + + return false; // to make compiler happy +} + +int +HeMoKunzelMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +// IST_Humidity overriden to use inverse_sorption_isotherm +{ + double humidity = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) )->giveHumidity(); + if ( type == IST_Humidity ) { + answer.resize(1); + answer.at(1) = humidity; + return 1; + } else if ( type == IST_MoistureContent ) { + answer.resize(1); + answer.at(1) = giveMoistureContent(humidity); + return 1; + } else { + return TransportMaterial :: giveIPValue(answer, gp, type, tStep); + } +} + +} // end namespace oofem diff --git a/src/tm/hemokunzelmat.h b/src/tm/Materials/hemokunzelmat.h similarity index 51% rename from src/tm/hemokunzelmat.h rename to src/tm/Materials/hemokunzelmat.h index 0eb457a06..ce84e5fd3 100644 --- a/src/tm/hemokunzelmat.h +++ b/src/tm/Materials/hemokunzelmat.h @@ -35,7 +35,7 @@ #ifndef hemokunzelmat_h #define hemokunzelmat_h -#include "transportmaterial.h" +#include "tm/Materials/transportmaterial.h" ///@name Input fields for HeMoKunzelMaterial //@{ @@ -67,7 +67,6 @@ namespace oofem { class HeMoKunzelMaterial : public TransportMaterial { protected: - enum isothermType { Hansen, Kunzeliso } Isotherm; enum permeabilityType { Multilin_h, Multilin_wV, Kunzelperm } Permeability; @@ -77,91 +76,70 @@ class HeMoKunzelMaterial : public TransportMaterial FloatArray perm_wV; FloatArray perm_DwwV; - double A; ///< water absorption coefficient [kg m^-2 s^-0.5] - - double iso_wh; ///< Parameter of Hansen's/Kunzel's isotherm - max. adsorbed water content [kg/m^3] - double iso_n; ///< Parameter of Hansen's isotherm - exponent - double iso_a; ///< Parameter of Hansen's isotherm - double iso_b; ///< Parameter of Kunzel's isotherm - - double mu; ///< water vapor diffusion resistance [-] - double PL; ///< ambient atmospheric pressure [Pa] - - double lambda0; ///< thermal conductivity [W m^-1 K^-1] - double b; ///< thermal conductivity supplement [-] - double rho; ///< bulk density of dry building material [kg m^-3] - double rhoH2O; ///< water density [kg m^-3] - double cs; ///< specific heat capacity of the building material [J kg^-1 K^-1] - double cw; ///< specific heat capacity of liquid water [J kg^-1 K^-1] - double hv; ///< latent heat of phase change/evaporation enthalpy of pure water [J/kg] - + double A = 0.; ///< water absorption coefficient [kg m^-2 s^-0.5] + double iso_wh = 0.; ///< Parameter of Hansen's/Kunzel's isotherm - max. adsorbed water content [kg/m^3] + double iso_n = 0.; ///< Parameter of Hansen's isotherm - exponent + double iso_a = 0.; ///< Parameter of Hansen's isotherm + double iso_b = 0.; ///< Parameter of Kunzel's isotherm + double mu = 0.; ///< water vapor diffusion resistance [-] + double PL = 0.; ///< ambient atmospheric pressure [Pa] + double lambda0 = 0.; ///< thermal conductivity [W m^-1 K^-1] + double b = 0.; ///< thermal conductivity supplement [-] + double rho = 0.; ///< bulk density of dry building material [kg m^-3] + double rhoH2O = 0.; ///< water density [kg m^-3] + double cs = 0.; ///< specific heat capacity of the building material [J kg^-1 K^-1] + double cw = 0.; ///< specific heat capacity of liquid water [J kg^-1 K^-1] + double hv = 0.; ///< latent heat of phase change/evaporation enthalpy of pure water [J/kg] public: - /** * Constructor. Creates material with given number, belonging to given domain. * @param n Material number. * @param d Domain to which new material will belong. */ HeMoKunzelMaterial(int n, Domain *d) : TransportMaterial(n, d) { } - /// Destructor. - virtual ~HeMoKunzelMaterial() { } - - virtual void giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep); - virtual void giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *atTime); + std::pair, FloatArrayF<3>> computeHeMoFlux3D(const FloatArrayF<3> &grad_t, const FloatArrayF<3> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + double giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) const override; - virtual double giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *atTime); + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override; - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode); + void initializeFrom(InputRecord &ir) override; - virtual IRResultType initializeFrom(InputRecord *ir); + double give(int aProperty, GaussPoint *gp) const override; - virtual double give(int aProperty, GaussPoint *gp); + bool hasMaterialModeCapability(MaterialMode mode) const override; - virtual int hasMaterialModeCapability(MaterialMode mode); + const char *giveInputRecordName() const override { return _IFT_HeMoKunzelMaterial_Name; } + const char *giveClassName() const override { return "HeMoKunzelMaterial"; } - // identification - virtual const char *giveInputRecordName() const { return _IFT_HeMoKunzelMaterial_Name; } - virtual const char *giveClassName() const { return "HeMoKunzelMaterial"; } + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime) override; /// returns water content (in kg/m^3) - double giveMoistureContent(double h); + double giveMoistureContent(double h) const; /// computes derivative of the moisture storage function (sorption isotherm) with respect to relative humidity - double giveMoistureContentDerivative(double h); + double giveMoistureContentDerivative(double h) const; - double computeWaterVaporPerm(double T); - double computeSatVaporPressure(double T); - double computeSatVaporPressureDerivative(double T); - double computeDw(double h); + double computeWaterVaporPerm(double T) const; + double computeSatVaporPressure(double T) const; + double computeSatVaporPressureDerivative(double T) const; + double computeDw(double h) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new HeMoTransportMaterialStatus(gp); } protected: - void computeConductivityMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *atTime); - void matcond1d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime); - void matcond2d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime); - void matcond3d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime); - - double computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *atTime); - - double perm_mm(double h, double T); - double perm_mh(double h, double T); - double perm_hm(double h, double T); - double perm_hh(double h, double T); + double computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) const; + double perm_mm(double h, double T) const; + double perm_mh(double h, double T) const; + double perm_hm(double h, double T) const; + double perm_hh(double h, double T) const; - // post-processing, poi export - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime); - virtual double giveHumidity(GaussPoint *gp, ValueModeType mode); }; } // end namespace oofem #endif // hemokunzelmat_h diff --git a/src/tm/Materials/hemotkmat.C b/src/tm/Materials/hemotkmat.C new file mode 100644 index 000000000..2a7d13656 --- /dev/null +++ b/src/tm/Materials/hemotkmat.C @@ -0,0 +1,375 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "tm/Materials/hemotkmat.h" +#include "floatmatrixf.h" +#include "gausspoint.h" +#include "mathfem.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(HeMoTKMaterial); + +bool +HeMoTKMaterial :: hasMaterialModeCapability(MaterialMode mode) const +{ + return mode == _2dHeMo || mode == _3dHeMo; +} + + +void +HeMoTKMaterial :: initializeFrom(InputRecord &ir) +{ + Material :: initializeFrom(ir); + + IR_GIVE_FIELD(ir, a_0, _IFT_HeMoTKMaterial_a_0); + IR_GIVE_FIELD(ir, nn, _IFT_HeMoTKMaterial_nn); + IR_GIVE_FIELD(ir, phi_c, _IFT_HeMoTKMaterial_phi_c); + IR_GIVE_FIELD(ir, delta_wet, _IFT_HeMoTKMaterial_delta_wet); + + IR_GIVE_FIELD(ir, w_h, _IFT_HeMoTKMaterial_w_h); + IR_GIVE_FIELD(ir, n, _IFT_HeMoTKMaterial_n); + IR_GIVE_FIELD(ir, a, _IFT_HeMoTKMaterial_a); + + IR_GIVE_FIELD(ir, latent, _IFT_HeMoTKMaterial_latent); + IR_GIVE_FIELD(ir, c, _IFT_HeMoTKMaterial_c); + IR_GIVE_FIELD(ir, rho, _IFT_HeMoTKMaterial_rho); + IR_GIVE_FIELD(ir, chi_eff, _IFT_HeMoTKMaterial_chi_eff); + + IR_GIVE_FIELD(ir, por, _IFT_HeMoTKMaterial_por); + IR_GIVE_FIELD(ir, rho_gws, _IFT_HeMoTKMaterial_rho_gws); +} + + +double +HeMoTKMaterial :: give(int aProperty, GaussPoint *gp) const +{ + return Material :: give(aProperty, gp); +} + + +std::pair, FloatArrayF<3>> +HeMoTKMaterial :: computeHeMoFlux3D(const FloatArrayF<3> &grad_t, const FloatArrayF<3> &grad_w, double t, double w, GaussPoint *gp, TimeStep *tStep) const +{ + auto ms = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + + auto ans_w = perm_ww(w, t) * grad_w + perm_wt(w, t) * grad_t; + auto ans_t = perm_ww(w, t) * get_latent(w, t) * grad_w + (get_chi(w, t) + get_latent(w, t) * perm_wt(w, t)) * grad_t; + + ms->setTempTemperature(t); + ms->setTempTemperatureGradient(grad_t); + ms->setTempHeatFlux(ans_t); + + ms->setTempHumidity(w); + ms->setTempHumidityGradient(grad_w); + ms->setTempHumidityFlux(ans_w); + + return {ans_t, ans_w}; +} + +FloatMatrixF<3,3> +HeMoTKMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto status = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + + double t = status->giveTempTemperature(); + double w = status->giveTempHumidity(); + + double k = 0.0; + if ( mode == Conductivity_ww ) { + k = perm_ww(w, t); + } else if ( mode == Conductivity_wh ) { + k = perm_wt(w, t); + } else if ( mode == Conductivity_hw ) { + k = perm_ww(w, t) * get_latent(w, t); + } else if ( mode == Conductivity_hh ) { + k = get_chi(w, t) + get_latent(w, t) * perm_wt(w, t); + } else { + OOFEM_ERROR("Unknown MatResponseMode"); + } + + return k * eye<3>(); +} + + +double +HeMoTKMaterial :: giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const +{ + return this->computeCapacityCoeff(mode, gp, tStep); +} + + +double HeMoTKMaterial :: computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + if ( mode == Capacity_ww ) { + return 1.0 * rho; + } else if ( mode == Capacity_wh ) { + return 0.0; + } else if ( mode == Capacity_hw ) { + auto status = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + + double t = status->giveTempTemperature(); + double w = status->giveTempHumidity(); + return get_b(w, t) * get_latent(w, t); + } else if ( mode == Capacity_hh ) { + auto status = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + + double t = status->giveTempTemperature(); + double w = status->giveTempHumidity(); + return get_ceff(w, t); + } else { + OOFEM_ERROR("Unknown MatResponseMode"); + } + + return 0.0; // to make compiler happy +} + + +double +HeMoTKMaterial :: giveHumidity(GaussPoint *gp, ValueModeType mode) const +{ + auto status = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + + double w = status->giveHumidity(); + double tempw = status->giveTempHumidity(); + + if ( mode == VM_Total ) { + return inverse_sorption_isotherm( tempw ); + } else if ( mode == VM_Incremental ) { + return inverse_sorption_isotherm( tempw ) - inverse_sorption_isotherm( w ); + } else if ( mode == VM_Velocity ) { // VM_Previous + return inverse_sorption_isotherm( w ); + } + + return 1.; +} + + +double +HeMoTKMaterial :: perm_ww(double w, double t) const +{ + // Function calculates permability water content-water content (k_ww) + // phi ... relative humidity + // delta_gw ... water vapor permeability + // dphi_dw ... differentiation of relative with respect to water content + // p_gws ... saturation water vapor pressure + double phi = inverse_sorption_isotherm(w); + double delta_gw = give_delta_gw(phi); + double dphi_dw = give_dphi_dw(w); + double p_gws = give_p_gws(t); + + return delta_gw * p_gws * dphi_dw; +} + +double +HeMoTKMaterial :: perm_wt(double w, double t) const +{ + // Function calculates permability water content-temperature (k_wt) + // delta_gw ... water vapor permeability + // d_pgw_d_t ... differentiation of water vapor presssure with respect to temperature + double phi = inverse_sorption_isotherm(w); + double delta_gw = give_delta_gw(phi); + double dpgw_dt = give_dpgw_dt(t, phi); + + return delta_gw * dpgw_dt; +} + + +double +HeMoTKMaterial :: give_delta_gw(double phi) const +// Function calculates the water vapor permeability delta_gw. Relative humidity (phi) is from range 0.2 - 0.98 !!! +// delta_gw ... by Z. P. Bazant and L. J. Najjar (1972), Nonlinear water diffusion in nonsaturated concrete, +// MATERIAUX ET CONSTRUCTIONS, Vol. 5, No. 25, pp. 3 -20. +// phi ... relative humidity +// a_0, nn, phi_c, delta_wet ... constants obtained from experiments +{ + if ( phi < 0.2 || phi > 0.98 ) { + OOFEM_ERROR("Relative humidity is out of range"); + } + + // water vapor permeability + return delta_wet * ( a_0 + ( 1.0 - a_0 ) / ( 1.0 + pow( ( 1.0 - phi ) / ( 1.0 - phi_c ), nn ) ) ); +} + + +double +HeMoTKMaterial :: sorption_isotherm(double phi) const +// Function calculates water content in medium from relative humidity. Relative humidity (phi) is from range 0.2 - 0.98 !!! +// sorption isotherm by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, +// PhD-thesis, Technical University of Denmark, Lingby. +// w (kg/kg) ... water content +// phi ... relative humidity +// w_h, n, a ... constants obtained from experiments +{ + if ( phi < 0.2 || phi > 0.98 ) { + OOFEM_ERROR("Relative humidity %.3f is out of range", phi); + } + + // water content + return w_h * pow( ( 1.0 - log(phi) / a ), ( -1.0 / n ) ); +} + + +double +HeMoTKMaterial :: inverse_sorption_isotherm(double w) const +// Function calculates relative humidity from water content (inverse relation form sorption isotherm). +// Relative humidity (phi) is from range 0.2 - 0.98 !!! +// sorption isotherm by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, +// PhD-thesis, Technical University of Denmark, Lingby. +// w (kg/kg) ... water content +// phi ... relative humidity +// w_h, n, a ... constants obtained from experiments +{ + // relative humidity + double phi = exp( a * ( 1.0 - pow( ( w_h / w ), ( n ) ) ) ); + + if ( phi < 0.2 || phi > 0.98 ) { + OOFEM_ERROR("Relative humidity %.3f is out of range", phi); + } + + return phi; +} + + +double +HeMoTKMaterial :: give_dphi_dw(double w) const +// Function calculates differentiation of relative humidity with respect to water content (inverse relation form sorption isotherm). +// Relative humidity (phi) is from range 0.2 - 0.98 !!! +// sorption isotherm by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, +// PhD-thesis, Technical University of Denmark, Lingby. +// w (kg/kg) ... water content +// phi ... relative humidity +// w_h, n, a ... constants obtained from experiments +{ + // diferentiation of realative humidity with respect to water content + return exp( a * ( 1.0 - pow( ( w_h / w ), n ) ) ) * a * n * pow(w_h, n) * pow( w, ( -1.0 - n ) ); +} + +double +HeMoTKMaterial :: give_dpgw_dt(double t, double phi) const +// Function calculates differentiation of water vapor pressure with respect to temperature +// saturation water vapor pressure by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, +// PhD-thesis, Technical University of Denmark, Lingby. +// t ... temperature [K] +// phi ... relative humidity +{ + //differentiation of saturation water vapor pressure (analytical expression) with respect to temperature + double dp_gws_dt = exp( 23.5771 - 4042.9 / ( t - 37.58 ) ) * 4042.9 / ( t - 37.58 ) / ( t - 37.58 ); + double dp_gw_dt = phi * dp_gws_dt; + return dp_gw_dt; +} + + +double +HeMoTKMaterial :: give_p_gws(double t) const +// Function calculates saturation water vapor pressure +// saturation water vapor pressure by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, +// PhD-thesis, Technical University of Denmark, Lingby. +// t ... temperature [K] +// phi ... relative humidity +{ + //saturation water vapor pressure ... analytical expression + return exp( 23.5771 - 4042.9 / ( t - 37.58 ) ); +} + +double +HeMoTKMaterial :: get_latent(double w, double t) const +{ + // Function calculates latent heat of evaporation + return latent; //zatim!!!! +} + +double +HeMoTKMaterial :: get_b(double w, double t) const +{ + // Function calculates coefficient b + // sat ... degree of saturation + double phi = inverse_sorption_isotherm(w); + double dphi_dw = give_dphi_dw(w); + double sat = get_sat(w, t); + + return por * rho_gws * ( phi + ( 1 - sat ) * dphi_dw ); +} + + +double +HeMoTKMaterial :: get_sat(double w, double t) const +{ + // Function calculates degree of saturation + // sat ... degree of saturation + return 1.0; //zatim!!!! +} + +double +HeMoTKMaterial :: get_ceff(double w, double t) const +{ + // Function calculates effective thermal capacity + return c * rho; //zatim!!!! +} + + +double +HeMoTKMaterial :: get_chi(double w, double t) const +{ + // Function calculates effective thermal conductivity + return chi_eff; //zatim!!!! +} + +bool +HeMoTKMaterial :: isCharacteristicMtrxSymmetric(MatResponseMode mode) const +{ + if ( mode == Conductivity_ww || mode == Conductivity_hh || mode == Conductivity_hw || mode == Conductivity_wh ) { + return false; + } else { + OOFEM_ERROR("unknown mode (%s)", __MatResponseModeToString(mode) ); + } + + return false; // to make compiler happy +} + +int +HeMoTKMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +// IST_Humidity overriden to use inverse_sorption_isotherm +{ + if ( type == IST_Humidity ) { + answer.resize(1); + answer.at(1) = giveHumidity(gp, VM_Velocity); // VM_Previous = equilibrated value of humidity + return 1; + } else { + return TransportMaterial :: giveIPValue(answer, gp, type, tStep); + } +} +} // end namespace oofem diff --git a/src/tm/Materials/hemotkmat.h b/src/tm/Materials/hemotkmat.h new file mode 100644 index 000000000..a9070c53f --- /dev/null +++ b/src/tm/Materials/hemotkmat.h @@ -0,0 +1,138 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef hemotkmat_h +#define hemotkmat_h + +#include "tm/Materials/transportmaterial.h" + +///@name Input fields for HeMoTKMaterial +//@{ +#define _IFT_HeMoTKMaterial_Name "hemotk" +#define _IFT_HeMoTKMaterial_a_0 "a_0" +#define _IFT_HeMoTKMaterial_nn "nn" +#define _IFT_HeMoTKMaterial_phi_c "phi_c" +#define _IFT_HeMoTKMaterial_delta_wet "delta_wet" +#define _IFT_HeMoTKMaterial_w_h "w_h" +#define _IFT_HeMoTKMaterial_n "n" +#define _IFT_HeMoTKMaterial_a "a" +#define _IFT_HeMoTKMaterial_latent "latent" +#define _IFT_HeMoTKMaterial_c "c" +#define _IFT_HeMoTKMaterial_rho "rho" +#define _IFT_HeMoTKMaterial_chi_eff "chi_eff" +#define _IFT_HeMoTKMaterial_por "por" +#define _IFT_HeMoTKMaterial_rho_gws "rho_gws" +//@} + +namespace oofem { +/** + * This class implements a coupled heat and mass transfer material model. It computes conductivity and capacity + * matrices for coupled heat and moisture transfer. + * Assumptions: Water vapor is the only driving mechanism; relative humidity is from range 0.2 - 0.98 (I and II region). + * @author Tomas Krejci + * Source: T.K. Doctoral Thesis; Bazant and Najjar, 1972; Pedersen, 1990. + */ +class HeMoTKMaterial : public TransportMaterial +{ +protected: + double a_0 = 0.; ///< Constant (obtained from experiments) [Bazant and Najjar, 1972] + double nn = 0.; ///< Constant-exponent (obtained from experiments) [Bazant and Najjar, 1972] + double phi_c = 0.; ///< Constant-relative humidity (obtained from experiments) [Bazant and Najjar, 1972] + double delta_wet = 0.; ///< Constant-water vapor permeability (obtained from experiments) [Bazant and Najjar, 1972] + + double w_h = 0.; ///< Constant water content (obtained from experiments) [Pedersen, 1990] + double n = 0.; ///< Constant-exponent (obtained from experiments) [Pedersen, 1990] + double a = 0.; ///< Constant (obtained from experiments) [Pedersen, 1990] + + double latent = 0.; ///< Latent heat of evaporation. + double c = 0.; ///< Thermal capacity. + double rho = 0.; ///< Volume density. + double chi_eff = 0.; ///< Effective thermal conductivity. + + double por = 0.; ///< Porosity. + double rho_gws = 0.; ///< Saturation volume density. + +public: + /** + * Constructor. Creates material with given number, belonging to given domain. + * @param n Material number. + * @param d Domain to which new material will belong. + */ + HeMoTKMaterial(int n, Domain * d) : TransportMaterial(n, d) { } + + std::pair, FloatArrayF<3>> computeHeMoFlux3D(const FloatArrayF<3> &grad_t, const FloatArrayF<3> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + double giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override; + + void initializeFrom(InputRecord &ir) override; + + double give(int aProperty, GaussPoint *gp) const override; + + bool hasMaterialModeCapability(MaterialMode mode) const override; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + + // identification + const char *giveInputRecordName() const override { return _IFT_HeMoTKMaterial_Name; } + const char *giveClassName() const override { return "HeMoTKMaterial"; } + + double sorption_isotherm(double phi) const; + double inverse_sorption_isotherm(double w) const; + double give_dphi_dw(double w) const; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new HeMoTransportMaterialStatus(gp); } + +protected: + double computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; + /** + * Returns positive value of humidity, use VM_Velocity for previous (equilibrated) value + */ + double giveHumidity(GaussPoint *gp, ValueModeType mode) const override; + + double get_latent(double w, double t) const; + double get_ceff(double w, double t) const; + double get_chi(double w, double t) const; + + double perm_wt(double w, double t) const; + double perm_ww(double w, double t) const; + double give_delta_gw(double phi) const; + double give_dpgw_dt(double t, double phi) const; + + double get_b(double w, double t) const; + double get_sat(double w, double t) const; + double give_p_gws(double t) const; +}; +} // end namespace oofem +#endif // hemotkmat_h diff --git a/src/tm/hydram.C b/src/tm/Materials/hydram.C similarity index 81% rename from src/tm/hydram.C rename to src/tm/Materials/hydram.C index 94d40e18e..2457a5b0b 100644 --- a/src/tm/hydram.C +++ b/src/tm/Materials/hydram.C @@ -25,7 +25,7 @@ * */ -#include "hydram.h" +#include "tm/Materials/hydram.h" #include "gausspoint.h" #include "datastream.h" #include "mathfem.h" @@ -35,14 +35,10 @@ namespace oofem { // ======= class HydrationModelStatus implementation ======= -HydrationModelStatus :: HydrationModelStatus(int n, Domain *d, GaussPoint *g) : MaterialStatus(n, d, g) -{ - hydrationDegree = 0; - tempHydrationDegree = 0; -} +HydrationModelStatus :: HydrationModelStatus(GaussPoint *g) : MaterialStatus(g) { } void -HydrationModelStatus :: printOutputAt(FILE *file, TimeStep *tStep) +HydrationModelStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { fprintf(file, " ksi %.5f", hydrationDegree); } @@ -72,41 +68,35 @@ HydrationModelStatus :: updateYourself(TimeStep *tStep) } //modified_zh 25.6.2004 obj = NULL is set in .h -contextIOResultType -HydrationModelStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// saves current context(state) into stream +void +HydrationModelStatus :: saveContext(DataStream &stream, ContextMode mode) { if ( !stream.write(hydrationDegree) ) { THROW_CIOERR(CIO_IOERR); } - - return CIO_OK; } //modified_zh 25.6.2004 obj = NULL is set in .h -contextIOResultType -HydrationModelStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// restores current context(state) from stream +void +HydrationModelStatus :: restoreContext(DataStream &stream, ContextMode mode) { if ( !stream.read(hydrationDegree) ) { THROW_CIOERR(CIO_IOERR); } tempHydrationDegree = hydrationDegree; // for oofeg - return CIO_OK; } // ======= class HydrationModel implementation ======= // default constructor - Lafarge mixture -HydrationModel :: HydrationModel() : Material(0, NULL) +HydrationModel :: HydrationModel() : Material(0, nullptr) { setMixture(mtLafarge); useFindRoot = frMixed; } -// constructor -HydrationModel :: HydrationModel(MixtureType mix, FindRootMethod usefr) : Material(0, NULL) +HydrationModel :: HydrationModel(MixtureType mix, FindRootMethod usefr) : Material(0, nullptr) { setMixture(mix); if ( ( usefr ) && ( usefr <= frMixed ) ) { @@ -116,10 +106,9 @@ HydrationModel :: HydrationModel(MixtureType mix, FindRootMethod usefr) : Materi } } -IRResultType -HydrationModel :: initializeFrom(InputRecord *ir) +void +HydrationModel :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro double value; //hydration>0 -> initial hydration degree @@ -128,11 +117,10 @@ HydrationModel :: initializeFrom(InputRecord *ir) if ( initialHydrationDegree >= 0. ) { OOFEM_LOG_INFO("HydrationModel: Hydration from %.2f.", initialHydrationDegree); } else { - OOFEM_WARNING("Hydration degree input incorrect, use 0..1 to set initial material hydration degree."); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_HydrationModel_hydration, "must be between 0 and 1"); } - if ( ir->hasField(_IFT_HydrationModel_c60mix) ) { + if ( ir.hasField(_IFT_HydrationModel_c60mix) ) { OOFEM_LOG_INFO("HydrationModel: Model parameters for Skanska C60/75 mixture."); setMixture(mtC60); } @@ -171,8 +159,6 @@ HydrationModel :: initializeFrom(InputRecord *ir) if ( cv || ( value >= 0 ) ) { OOFEM_LOG_INFO("HydrationModel: Water consumption for hydration set to %.0f kg/m3", we); } - - return IRRT_OK; } void @@ -200,7 +186,7 @@ HydrationModel :: setMixture(MixtureType mix) e0 = 0.10; // ksi_0 } // Skanska C60/75 mixture - else if ( ( mix == mtC60 ) || ( mix == mtC100 ) ) { // used for C100 too + else if ( mix == mtC60 || mix == mtC100 ) { // used for C100 too aa = 8.5; ba = 5.0; ca = 300; @@ -222,42 +208,39 @@ HydrationModel :: setMixture(MixtureType mix) // === Material functions === double -HydrationModel :: affinity(double ksi) +HydrationModel :: affinity(double ksi) const // Returns the normalized chemical affinity A~(ksi) [1/s] { if ( ksi < e0 ) { ksi = e0; } - return ( aa * ( 1 - exp(-ba * ksi) ) / ( 1 + ca * pow(ksi, da) ) ); + return aa * ( 1 - exp(-ba * ksi) ) / ( 1 + ca * pow(ksi, da) ); } double -HydrationModel :: dAdksi(double ksi) +HydrationModel :: dAdksi(double ksi) const // Returns the derivation of chemical affinity dA~/dksi(ksi) { - double ksinad, enaksi; - if ( ksi < e0 ) { - return ( 0 ); + return 0; } - ksinad = pow(ksi, da); - enaksi = exp(-ba * ksi); + double ksinad = pow(ksi, da); + double enaksi = exp(-ba * ksi); - return ( aa * ( ca * da * ksinad * ( enaksi - 1 ) / ksi + ba * enaksi * ( ca * ksinad + 1 ) ) / - pow(1 + ca * ksinad, 2) ); + return aa * ( ca * da * ksinad * ( enaksi - 1 ) / ksi + ba * enaksi * ( ca * ksinad + 1 ) ) / pow(1 + ca * ksinad, 2); } double -HydrationModel :: localResidual(double dks) // G(dksi) 4.12 +HydrationModel :: localResidual(double dks) const // G(dksi) 4.12 // !!! uses auxiliary ksi, dt, T in hydration model instance { - return ( dks - auxdt * affinity(auxksi + dks) * exp(-ear / auxT) * ( 1. + auxh * auxh ) / 2. ); + return dks - auxdt * affinity(auxksi + dks) * exp(-ear / auxT) * ( 1. + auxh * auxh ) / 2.; } double -HydrationModel :: dksidT(double ksi, double T, double h, double dt) +HydrationModel :: dksidT(double ksi, double T, double h, double dt) const /* * !!! should use state vector to enable adding state variables, but is OK on the level of dIntSource/dState * G = dksi - dt * aff(ksi) * exp(-ear/T) * (1+h^2)/2 = 0 @@ -267,24 +250,20 @@ HydrationModel :: dksidT(double ksi, double T, double h, double dt) * dh/dT, dh/dksi uz nejde, od toho je iterace ksi(h,T) */ { - double aux; - aux = dt * exp(-ear / T) * ( 1 + h * h ) / 2; - return ( aux * affinity(ksi) * ear / ( T * T ) ) / - ( 1 - aux * dAdksi(ksi) ); + double aux = dt * exp(-ear / T) * ( 1 + h * h ) / 2; + return ( aux * affinity(ksi) * ear / ( T * T ) ) / ( 1 - aux * dAdksi(ksi) ); } double -HydrationModel :: dksidh(double ksi, double T, double h, double dt) +HydrationModel :: dksidh(double ksi, double T, double h, double dt) const /* * G = dks - dt * aff(ksi) * exp(-ear/T) * (1+h^2)/2 = 0 * dksi/dh = - dG/dh / dG/dksi * = - -dt*aff(ksi) *exp(-ear/T) * h / (1 - dt*daff/dksi * exp(-ear/T) * (1+h^2)/2) */ { - double aux; - aux = dt * exp(-ear / T); - return ( aux * affinity(ksi) * h ) / - ( 1 - aux * dAdksi(ksi) * ( 1 + h * h ) / 2 ); + double aux = dt * exp(-ear / T); + return ( aux * affinity(ksi) * h ) / ( 1 - aux * dAdksi(ksi) * ( 1 + h * h ) / 2 ); } MaterialStatus * @@ -295,7 +274,7 @@ HydrationModel :: giveStatus(GaussPoint *gp) const */ { HydrationModelStatusInterface *hmi = static_cast< HydrationModelStatusInterface * >( this->giveStatus(gp)->giveInterface(HydrationModelStatusInterfaceType) ); - HydrationModelStatus *status = NULL; + HydrationModelStatus *status = nullptr; if ( hmi ) { status = hmi->giveHydrationModelStatus(); if ( !status ) { @@ -310,7 +289,7 @@ HydrationModel :: giveStatus(GaussPoint *gp) const } void -HydrationModel :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +HydrationModel :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const /* * Returns the hydration heat generated in gp during time step tStep. * Can be overriden to return also water consumption as second component of the internal source vector. @@ -324,23 +303,17 @@ HydrationModel :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, T } double -HydrationModel :: giveCharacteristicValue(const FloatArray &vec, MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep) +HydrationModel :: giveCharacteristicValue(double T, double h, MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep) const // Transport status needs to be obtained from master status, it's better to pass as a parameter // to enable usage from structural material { - double answer = 0; - - if ( ( rmode == IntSource ) || ( rmode == IntSource_hh ) || ( rmode == IntSource_ww ) || ( rmode == IntSource_wh ) || ( rmode == IntSource_hw ) ) { - if ( vec.isEmpty() ) { - OOFEM_ERROR("undefined state vector."); - } - - answer = computeIntSource(vec, gp, tStep, rmode); + if ( rmode == IntSource || rmode == IntSource_hh || rmode == IntSource_ww || rmode == IntSource_wh || rmode == IntSource_hw ) { + return computeIntSource(T, h, gp, tStep, rmode); } else { OOFEM_ERROR("wrong MatResponseMode."); } - return answer; + return 0.; } double @@ -379,11 +352,11 @@ HydrationModel :: computeHydrationDegreeIncrement(double ksi, double T, double h result = 0.; } - return ( result ); + return result; } double -HydrationModel :: computeIntSource(const FloatArray &vec, GaussPoint *gp, TimeStep *tStep, MatResponseMode rmode) +HydrationModel :: computeIntSource(double T, double h, GaussPoint *gp, TimeStep *tStep, MatResponseMode rmode) const /* * Computes and returns the derivatives of the material-generated Internal Source with respect to the tm state vector. * Used in IntSourceLHS matrix for quadratic convergency of global iteration. @@ -397,12 +370,9 @@ HydrationModel :: computeIntSource(const FloatArray &vec, GaussPoint *gp, TimeSt */ { // prepare ksi, T, h, dt - double ksi, T, h, dt; - ksi = giveHydrationDegree(gp, tStep, VM_Total); - T = vec(0); - h = vec(1); + double ksi = giveHydrationDegree(gp, tStep, VM_Total); // !!! timeScale - dt = tStep->giveTimeIncrement() * timeScale; + double dt = tStep->giveTimeIncrement() * timeScale; if ( ksi < 1.0 ) { switch ( rmode ) { @@ -425,7 +395,7 @@ HydrationModel :: computeIntSource(const FloatArray &vec, GaussPoint *gp, TimeSt // === public services === double -HydrationModel :: giveHydrationDegree(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +HydrationModel :: giveHydrationDegree(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const // returns the hydration degree in integration point gp { HydrationModelStatus *status = static_cast< HydrationModelStatus * >( giveStatus(gp) ); @@ -445,7 +415,7 @@ HydrationModel :: updateInternalState(const FloatArray &vec, GaussPoint *gp, Tim * caller should ensure that this is called only when state vector is changed */ { - double ksi, dksi, T = 0., h = 1.; + double dksi, T = 0., h = 1.; // get hydration model status associated with integration point HydrationModelStatus *status = static_cast< HydrationModelStatus * >( giveStatus(gp) ); @@ -460,7 +430,7 @@ HydrationModel :: updateInternalState(const FloatArray &vec, GaussPoint *gp, Tim OOFEM_ERROR("undefined state vector."); } - ksi = status->giveHydrationDegree(); + double ksi = status->giveHydrationDegree(); if ( !ksi && initialHydrationDegree ) { ksi = initialHydrationDegree; status->setHydrationDegree(ksi); @@ -479,7 +449,7 @@ HydrationModel :: updateInternalState(const FloatArray &vec, GaussPoint *gp, Tim // === Auxiliary functions === (root finding) double -HydrationModel :: regulafindroot() +HydrationModel :: regulafindroot() const { double x0, y0, yl, xl = 0., xr = 1.; @@ -498,11 +468,11 @@ HydrationModel :: regulafindroot() #endif } while ( fabs(y0) > ROOT_PRECISION_DKSI ); - return ( x0 ); + return x0; } double -HydrationModel :: bintreefindroot() +HydrationModel :: bintreefindroot() const { double xl = 0., xr = 1., x0, y0; @@ -520,23 +490,23 @@ HydrationModel :: bintreefindroot() #endif } while ( fabs(y0) > ROOT_PRECISION_DKSI ); - return ( x0 ); + return x0; } double -HydrationModel :: mixedfindroot() +HydrationModel :: mixedfindroot() const { - double x0 = 0., y0, yl, xl = 0., xr = 1.; - int jcount, done = 0; + double x0 = 0., y0, xl = 0., xr = 1.; + bool done = false; do { - for ( jcount = 0; ( jcount < BINARY_TREE_STEPS ); jcount++ ) { + for ( int jcount = 0; ( jcount < BINARY_TREE_STEPS ); jcount++ ) { x0 = ( xl + xr ) / 2; y0 = localResidual(x0); if ( fabs(y0) < ROOT_PRECISION_DKSI ) { - done = 1; + done = true; break; } @@ -548,14 +518,13 @@ HydrationModel :: mixedfindroot() } if ( !done ) { - yl = localResidual(xl); + double yl = localResidual(xl); x0 = yl * ( xl - xr ) / ( localResidual(xr) - yl ) + xl; y0 = localResidual(x0); if ( fabs(y0) < ROOT_PRECISION_DKSI ) { break; - } else - if ( y0 < 0 ) { + } else if ( y0 < 0 ) { xl = x0; } else { xr = x0; @@ -567,13 +536,13 @@ HydrationModel :: mixedfindroot() } } while ( !done ); - return ( x0 ); + return x0; } MaterialStatus * HydrationModel :: CreateStatus(GaussPoint *gp) const { - return new HydrationModelStatus(1, this->giveDomain(), gp); + return new HydrationModelStatus(gp); } // ======= HydrationModelStatusInterface implementation ======= @@ -586,7 +555,7 @@ HydrationModelStatusInterface :: updateYourself(TimeStep *tStep) } void -HydrationModelStatusInterface :: printOutputAt(FILE *file, TimeStep *tStep) +HydrationModelStatusInterface :: printOutputAt(FILE *file, TimeStep *tStep) const { if ( hydrationModelStatus ) { hydrationModelStatus->printOutputAt(file, tStep); @@ -595,10 +564,9 @@ HydrationModelStatusInterface :: printOutputAt(FILE *file, TimeStep *tStep) // ======= HydrationModelInterface implementation ======= -IRResultType -HydrationModelInterface :: initializeFrom(InputRecord *ir) +void +HydrationModelInterface :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro double value; // !!! should use separate field, e.g. hydramname #hydramnumber @@ -608,10 +576,9 @@ HydrationModelInterface :: initializeFrom(InputRecord *ir) IR_GIVE_OPTIONAL_FIELD(ir, value, _IFT_HydrationModelInterface_hydration); if ( value >= 0. ) { OOFEM_LOG_INFO("HydratingMaterial: creating HydrationModel."); - hydrationModel.reset( new HydrationModel() ); + hydrationModel = std::make_unique(); if ( !hydrationModel ) { - OOFEM_WARNING("Could not create HydrationModel instance."); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_HydrationModelInterface_hydration, "Could not create HydrationModel instance."); } hydrationModel->initializeFrom(ir); @@ -621,8 +588,7 @@ HydrationModelInterface :: initializeFrom(InputRecord *ir) constantHydrationDegree = -value; OOFEM_LOG_INFO("HydratingMaterial: Hydration degree set to %.2f.", -value); } else { - OOFEM_WARNING("Hydration degree input incorrect, use -1..<0 for constant hydration degree, 0..1 to set initial material hydration degree."); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_HydrationModelInterface_hydration, "must be between 0 and 1"); } // Material cast time - start of hydration @@ -632,8 +598,6 @@ HydrationModelInterface :: initializeFrom(InputRecord *ir) if ( castAt >= 0. ) { OOFEM_LOG_INFO("HydratingMaterial: Hydration starts at time %.2g.", castAt); } - - return IRRT_OK; } void @@ -657,7 +621,7 @@ HydrationModelInterface :: updateInternalState(const FloatArray &vec, GaussPoint } double -HydrationModelInterface :: giveHydrationDegree(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +HydrationModelInterface :: giveHydrationDegree(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const { if ( hydrationModel ) { return hydrationModel->giveHydrationDegree(gp, tStep, mode); diff --git a/src/tm/hydram.h b/src/tm/Materials/hydram.h similarity index 80% rename from src/tm/hydram.h rename to src/tm/Materials/hydram.h index 7bd1da848..ccd12a386 100644 --- a/src/tm/hydram.h +++ b/src/tm/Materials/hydram.h @@ -117,30 +117,28 @@ class HydrationModelStatus : public MaterialStatus { protected: // hydration degree at beginning of current time step - double hydrationDegree; + double hydrationDegree = 0.; // hydration degree at end of current time step (or during equilibrium iteration) - double tempHydrationDegree; + double tempHydrationDegree = 0.; public: - HydrationModelStatus(int n, Domain * d, GaussPoint * g); - virtual ~HydrationModelStatus() { } + HydrationModelStatus(GaussPoint * g); /// Returns the temp hydration degree. - double giveTempHydrationDegree() { return tempHydrationDegree; } + double giveTempHydrationDegree() const { return tempHydrationDegree; } /// Returns the non-temp hydration degree. Used for step restart and postprocessing. - double giveHydrationDegree() { return hydrationDegree; } + double giveHydrationDegree() const { return hydrationDegree; } void setHydrationDegree(double v) { hydrationDegree = v; } void setTempHydrationDegree(double v) { tempHydrationDegree = v; } - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; - virtual void printOutputAt(FILE *file, TimeStep *tStep); - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void printOutputAt(FILE *file, TimeStep *tStep) const override; + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - // --- identification and auxiliary functions --- - virtual const char *giveClassName() const { return "HydrationModelStatus"; } + const char *giveClassName() const override { return "HydrationModelStatus"; } }; @@ -156,46 +154,46 @@ class HydrationModel : public Material /// Used concrete mixture MixtureType mixture; /// Time step lenghts at zero and complete hydration - double hydrationStartMaxStep, hydrationEndMaxStep; + double hydrationStartMaxStep = 0., hydrationEndMaxStep = 0.; //!!! initial hydration degree - set in initialize From, but not used - double initialHydrationDegree; + double initialHydrationDegree = 0.; /// time scale - used for time input in other units than seconds - double timeScale; + double timeScale = 0.; // === Material parameters === - double aa, ///< Normalized chemical affinity regression function coefficients. - ba, - ca, - da, + double aa = 0., ///< Normalized chemical affinity regression function coefficients. + ba = 0., + ca = 0., + da = 0., - e0, ///< ksi_0. - ear, ///< Activation term [K]. - le, ///< Latent heat [kJ/m3]. - cv, ///< Input cement content kg/m3 for evaluation of total water consumption. - we; ///< Total water consumption for hydration [kg/m3]. + e0 = 0., ///< ksi_0. + ear = 0., ///< Activation term [K]. + le = 0., ///< Latent heat [kJ/m3]. + cv = 0., ///< Input cement content kg/m3 for evaluation of total water consumption. + we = 0.; ///< Total water consumption for hydration [kg/m3]. // === Hydration degree increment evaluation === // auxiliary values to enable external root finding method without passing them as parameters in each call //!!! possible problem for parallel computation, performance??? double auxksi, auxdt, auxT, auxh; - double localResidual(double dks); // G(dksi) 4.12 + double localResidual(double dks) const; // G(dksi) 4.12 // Auxiliary functions - root finding /// - double regulafindroot(); - double bintreefindroot(); - double mixedfindroot(); + double regulafindroot() const; + double bintreefindroot() const; + double mixedfindroot() const; // === Material functions === /// Returns the normalized chemical affinity A~(ksi) [1/s]. - double affinity(double ksi); + double affinity(double ksi) const; /// Returns the derivation of chemical affinity dA~/dksi(ksi). - double dAdksi(double ksi); - double dksidT(double ksi, double T, double h, double dt); - double dksidh(double ksi, double T, double h, double dt); + double dAdksi(double ksi) const; + double dksidT(double ksi, double T, double h, double dt) const; + double dksidh(double ksi, double T, double h, double dt) const; /// Computes and returns the derivatives of the material-generated Internal Source with respect to the tm state vector. - double computeIntSource(const FloatArray &vec, GaussPoint *gp, TimeStep *tStep, MatResponseMode rmode); + double computeIntSource(double T, double h, GaussPoint *gp, TimeStep *tStep, MatResponseMode rmode) const; /** * Computes and returns hydration degree increment for given ksi, T [K], dt [s]. * Called by updateInternalState(val, gp, tStep) @@ -209,9 +207,6 @@ class HydrationModel : public Material HydrationModel(); /// Constructor setting the mixture type and root-finding method HydrationModel(MixtureType mix, FindRootMethod usefr); - /// Destructor - virtual ~HydrationModel() { } - // === Hydration model services === @@ -225,7 +220,7 @@ class HydrationModel : public Material * Not a standard material - initializes from master material record, doesn't call parent initializeFrom * Use hm_ prefix in parameter names to avoid confusion with master material parameters */ - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; /** * Returns the hydration degree at end of TimeStep tStep in given integraion point. @@ -235,7 +230,7 @@ class HydrationModel : public Material * @param mode value mode VM_Incremental or VM_Total * @return hydration degree or increment in given gp */ - double giveHydrationDegree(GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + double giveHydrationDegree(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const; // how to determine whether hydration degree is uptodate? // - in tm, this can be ensured by calling computeHydrationDegreeIncrement when updateInternalState is used @@ -259,20 +254,19 @@ class HydrationModel : public Material * point gp. * @return hydration model status associated with given integration point. */ - virtual MaterialStatus *giveStatus(GaussPoint *gp) const; + MaterialStatus *giveStatus(GaussPoint *gp) const override; /// Returns generated heat for given gp [kJ/m3], eventually water consumption - void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const; // } end new 5.1.2004 /// Returns coefficients for LHS contribution from internal sources (dHeat/dT, dWaterSource/dw) for given temp state vector. - virtual double giveCharacteristicValue(const FloatArray &vec, MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep); + virtual double giveCharacteristicValue(double T, double h, MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep) const; // --- identification and auxiliary functions --- - virtual const char *giveInputRecordName() const { return _IFT_HydrationModel_Name; } - virtual const char *giveClassName() const { return "HydrationModel"; } + const char *giveInputRecordName() const override { return _IFT_HydrationModel_Name; } + const char *giveClassName() const override { return "HydrationModel"; } -protected: /// Creates and returns new HydrationModelStatus instance - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; }; // =========== Interfaces for materials using the hydration model ============ @@ -281,11 +275,10 @@ class HydrationModelStatusInterface : public Interface protected: /// Reference to associated hydration model status std :: unique_ptr< HydrationModelStatus > hydrationModelStatus; + public: /// Constructor. Nulls the hydrationModelStatus pointer. HydrationModelStatusInterface() {} - /// Destructor. Deletes the associated hydration model status. - virtual ~HydrationModelStatusInterface() {} /// Returns the associated hydration model status. HydrationModelStatus *giveHydrationModelStatus() { return hydrationModelStatus.get(); } @@ -295,7 +288,7 @@ class HydrationModelStatusInterface : public Interface /// Updates the equilibrium variables to temporary values. void updateYourself(TimeStep *tStep); /// Outputs the status variables - void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const; }; class HydrationModelInterface : public Interface @@ -305,36 +298,30 @@ class HydrationModelInterface : public Interface /// Reference to the associated hydrationModel instance std :: unique_ptr< HydrationModel > hydrationModel; /// Material cast time - start of hydration - double castAt; + double castAt = 0.; /// Constant hydration degree for analysis without hydration model - double constantHydrationDegree; + double constantHydrationDegree = 0.; public: /// Returns the associated hydration model. HydrationModel *giveHydrationModel() { return hydrationModel.get(); } - /// Destructor. Deletes the associated hydration model. - virtual ~HydrationModelInterface() {} /** * Creates and initializes the hydration model according to object description stored in input record. * The parent class instanciateFrom method is not called here. */ - IRResultType initializeFrom(InputRecord *ir); + virtual void initializeFrom(InputRecord &ir); - contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL) + void saveContext(DataStream &stream, ContextMode mode) { if ( hydrationModel ) { - hydrationModel->saveContext(stream, mode, obj); + hydrationModel->saveContext(stream, mode); } - - return CIO_OK; } - contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL) + void restoreContext(DataStream &stream, ContextMode mode) { if ( hydrationModel ) { - hydrationModel->restoreContext(stream, mode, obj); + hydrationModel->restoreContext(stream, mode); } - - return CIO_OK; } /** @@ -353,7 +340,7 @@ class HydrationModelInterface : public Interface * @param mode Value mode VM_Incremental or VM_Total. * @return Hydration degree or increment in given gp. */ - double giveHydrationDegree(GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + double giveHydrationDegree(GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const; }; } // end namespace oofem #endif // hydram_h diff --git a/src/tm/hydratingconcretemat.C b/src/tm/Materials/hydratingconcretemat.C similarity index 57% rename from src/tm/hydratingconcretemat.C rename to src/tm/Materials/hydratingconcretemat.C index be326de06..1dd1a0003 100644 --- a/src/tm/hydratingconcretemat.C +++ b/src/tm/Materials/hydratingconcretemat.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "hydratingconcretemat.h" +#include "tm/Materials/hydratingconcretemat.h" #include "gausspoint.h" #include "timestep.h" #include "mathfem.h" @@ -41,36 +41,21 @@ namespace oofem { REGISTER_Material(HydratingConcreteMat); -HydratingConcreteMat :: HydratingConcreteMat(int n, Domain *d) : IsotropicHeatTransferMaterial(n, d) -{ - // constructor - maxModelIntegrationTime = 0.; - minModelTimeStepIntegrations = 0; - P1 = 0.; -} - - -HydratingConcreteMat :: ~HydratingConcreteMat() -{ - // destructor -} - - -IRResultType -HydratingConcreteMat :: initializeFrom(InputRecord *ir) +HydratingConcreteMat :: HydratingConcreteMat(int n, Domain *d) : IsotropicHeatTransferMaterial(n, d){ } + +void +HydratingConcreteMat :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro - // set conductivity k and capacity c - result = IsotropicHeatTransferMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + IsotropicHeatTransferMaterial :: initializeFrom(ir); - referenceTemperature = 25.; - IR_GIVE_OPTIONAL_FIELD(ir, referenceTemperature, _IFT_HydratingConcreteMat_referenceTemperature); + activationEnergy = 38400; //J/mol/K + referenceTemperature = 25.;//C + IR_GIVE_OPTIONAL_FIELD(ir, activationEnergy, _IFT_HydratingConcreteMat_activationEnergy); IR_GIVE_FIELD(ir, hydrationModelType, _IFT_HydratingConcreteMat_hydrationModelType); - /*hydrationModelType==1:exponential hydration model, summarized in A.K. Schindler and K.J. Folliard: Heat of Hydration Models for Cementitious + /*hydrationModelType==1: exponential hydration model, summarized in A.K. Schindler and K.J. Folliard: Heat of Hydration Models for Cementitious * Materials, ACI Materials Journal, 2005 * hydrationModelType==2: affinity hydration model inspired by Miguel Cervera and Javier Oliver and Tomas Prato:Thermo-chemo-mechanical model * for concrete. I: Hydration and aging, Journal of Engineering Mechanics ASCE, 125(9), 1018-1027, 1999 @@ -86,9 +71,49 @@ HydratingConcreteMat :: initializeFrom(InputRecord *ir) IR_GIVE_FIELD(ir, DoHInf, _IFT_HydratingConcreteMat_DoHInf); IR_GIVE_OPTIONAL_FIELD(ir, DoH1, _IFT_HydratingConcreteMat_DoH1); IR_GIVE_OPTIONAL_FIELD(ir, P1, _IFT_HydratingConcreteMat_P1); + } else if ( hydrationModelType == 3 ) { //Saeed Rahimi-Aghdam, Zdeněk P. Bažant, Gianluca Cusatis: Extended Microprestress-Solidification Theory (XMPS) for Long-Term Creep and Diffusion Size Effect in Concrete at Variable Environment, JEM-ASCE, 2019. Appendix A. + referenceTemperature = 20.;//according to the authors + IR_GIVE_FIELD(ir, wc, _IFT_HydratingConcreteMat_wc); + IR_GIVE_FIELD(ir, ac, _IFT_HydratingConcreteMat_ac); + rhoCem = 3150.; //kg/m3 + IR_GIVE_OPTIONAL_FIELD(ir, rhoCem, _IFT_HydratingConcreteMat_rhoCem); + rhoAgg = 1600.; //kg/m3 + IR_GIVE_OPTIONAL_FIELD(ir, rhoAgg, _IFT_HydratingConcreteMat_rhoAgg); + Vc0 = rhoAgg*1000./(rhoAgg*1000.+rhoCem*1000.*ac+rhoCem*rhoAgg*wc); + Vw0 = rhoAgg*rhoCem*wc/(rhoAgg*1000.+rhoCem*1000.*ac+rhoCem*rhoAgg*wc); + + double Blaine=350.;//m2/kg + IR_GIVE_OPTIONAL_FIELD(ir, Blaine, _IFT_HydratingConcreteMat_Blaine); + this->a0 = 6.5e-6*350/Blaine; + this->ng = Vc0/(4./3*M_PI*a0*a0*a0); + + double alphaSet0 = 0.05; + IR_GIVE_OPTIONAL_FIELD(ir, alphaSet0, _IFT_HydratingConcreteMat_alphaSet0); + + timeSet = 3*3600; //s + IR_GIVE_OPTIONAL_FIELD(ir, timeSet, _IFT_HydratingConcreteMat_timeSet); + + + double alphaCrit0 = 0.36; + IR_GIVE_OPTIONAL_FIELD(ir, alphaCrit0, _IFT_HydratingConcreteMat_alphaCrit0); + + this->B0 = 1.1e-11/3600./24.; //m2/s + IR_GIVE_OPTIONAL_FIELD(ir, this->B0, _IFT_HydratingConcreteMat_B0); + + double f1 = 6.5e-6/a0; + double f2 = 1+2.5*(wc-0.3); + double f3 = exp( this->activationEnergy / 8.314 * ( 1. / ( 273.15 + 20. ) - 1. / ( 273.15 + this->referenceTemperature ) ) ); + alphaCrit = alphaCrit0 * f1 * f2 * f3; + if (alphaCrit>0.65) { alphaCrit = 0.65; } + alphaSet = alphaSet0 * alphaCrit / alphaCrit0; + + VCemSet = (1-alphaSet)*Vc0; + VCHSet = 0.59*alphaSet*Vc0; //CH vol. per unit vol. of cement + VGelSet = 1.52*alphaSet*Vc0; //Gel vol. per unit vol. of cement + this->aSet = pow( VCemSet/(4./3.*M_PI*ng), 1./3.); + this->zSet = pow( (VCemSet+VGelSet)/(4./3.*M_PI*ng), 1./3.); } else { - OOFEM_WARNING("Unknown hdyration model type %d", hydrationModelType); - return IRRT_BAD_FORMAT; + throw ValueInputException(ir, _IFT_HydratingConcreteMat_hydrationModelType, "Unknown hdyration model"); } IR_GIVE_FIELD(ir, Qpot, _IFT_HydratingConcreteMat_qpot); // [1/s] @@ -100,8 +125,9 @@ HydratingConcreteMat :: initializeFrom(InputRecord *ir) minModelTimeStepIntegrations = 30.; IR_GIVE_OPTIONAL_FIELD(ir, minModelTimeStepIntegrations, _IFT_HydratingConcreteMat_minModelTimeStepIntegrations); - - + + IR_GIVE_OPTIONAL_FIELD(ir, referenceTemperature, _IFT_HydratingConcreteMat_referenceTemperature); + conductivityType = 0; IR_GIVE_OPTIONAL_FIELD(ir, conductivityType, _IFT_HydratingConcreteMat_conductivitytype); capacityType = 0; @@ -109,21 +135,20 @@ HydratingConcreteMat :: initializeFrom(InputRecord *ir) densityType = 0; IR_GIVE_OPTIONAL_FIELD(ir, densityType, _IFT_HydratingConcreteMat_densitytype); - activationEnergy = 38400; //J/mol/K - IR_GIVE_OPTIONAL_FIELD(ir, activationEnergy, _IFT_HydratingConcreteMat_activationEnergy); - reinforcementDegree = 0.; IR_GIVE_OPTIONAL_FIELD(ir, reinforcementDegree, _IFT_HydratingConcreteMat_reinforcementDegree); - - return IRRT_OK; + + timeToSeconds = 1.; + IR_GIVE_OPTIONAL_FIELD(ir, timeToSeconds, _IFT_HydratingConcreteMat_timeToSeconds); + } // returns hydration power [W/m3 of concrete] void -HydratingConcreteMat :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +HydratingConcreteMat :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const { val.resize(1); - if (( mode == VM_Total) || (mode == VM_TotalIntrinsic)) { + if ( mode == VM_Total || mode == VM_TotalIntrinsic ) { val.at(1) = this->GivePower(tStep, gp, mode); } else { OOFEM_ERROR("Undefined mode %s\n", __ValueModeTypeToString(mode) ); @@ -132,15 +157,15 @@ HydratingConcreteMat :: computeInternalSourceVector(FloatArray &val, GaussPoint double -HydratingConcreteMat :: giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) +HydratingConcreteMat :: giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { if ( mode == Capacity ) { return ( giveConcreteCapacity(gp, tStep) * giveConcreteDensity(gp, tStep) ); } else if ( mode == IntSource ) { //for nonlinear solver, return dHeat/dTemperature HydratingConcreteMatStatus *ms = static_cast< HydratingConcreteMatStatus * >( this->giveStatus(gp) ); //it suffices to compute derivative of scaling Arrhenius equation with respect to temporary temperature - double stateVec = ms->giveField().at(1) + 273.15; - double tempStateVec = ms->giveTempField().at(1) + 273.15; + double stateVec = ms->giveField() + 273.15; + double tempStateVec = ms->giveTempField() + 273.15; return this->activationEnergy / ( 8.314 * tempStateVec * tempStateVec ) * exp(1. / stateVec - 1. / tempStateVec); } else { OOFEM_ERROR("unknown mode (%s)\n", __MatResponseModeToString(mode) ); @@ -150,9 +175,9 @@ HydratingConcreteMat :: giveCharacteristicValue(MatResponseMode mode, GaussPoint } -double HydratingConcreteMat :: giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) +double HydratingConcreteMat :: giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) const { - HydratingConcreteMatStatus *ms = static_cast< HydratingConcreteMatStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< HydratingConcreteMatStatus * >( this->giveStatus(gp) ); double conduct; if ( conductivityType == 0 ) { //given from input file @@ -175,7 +200,7 @@ double HydratingConcreteMat :: giveIsotropicConductivity(GaussPoint *gp, TimeSte } //normally it returns J/kg/K of concrete -double HydratingConcreteMat :: giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep) +double HydratingConcreteMat :: giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep) const { double capacityConcrete; @@ -200,7 +225,7 @@ double HydratingConcreteMat :: giveConcreteCapacity(GaussPoint *gp, TimeStep *tS } -double HydratingConcreteMat :: giveConcreteDensity(GaussPoint *gp, TimeStep *tStep) +double HydratingConcreteMat :: giveConcreteDensity(GaussPoint *gp, TimeStep *tStep) const { double concreteBulkDensity; @@ -230,11 +255,16 @@ HydratingConcreteMat :: giveIPValue(FloatArray &answer, GaussPoint *gp, Internal { // printf ("IP %d::giveIPValue, IST %d", giveNumber(), type); if ( type == IST_HydrationDegree ) { - HydratingConcreteMatStatus *status = static_cast< HydratingConcreteMatStatus * >( this->giveStatus(gp) ); + auto status = static_cast< HydratingConcreteMatStatus * >( this->giveStatus(gp) ); answer.resize(1); answer.at(1) = status->giveDoHActual(); //else answer.at(1) = 0; return 1; + } else if (type == IST_EquivalentTime) { + auto status = static_cast< HydratingConcreteMatStatus * >( this->giveStatus(gp) ); + answer.resize(1); + answer.at(1) = status->equivalentTime; + return 1; } else { return TransportMaterial :: giveIPValue(answer, gp, type, tStep); } @@ -244,32 +274,18 @@ HydratingConcreteMat :: giveIPValue(FloatArray &answer, GaussPoint *gp, Internal MaterialStatus * HydratingConcreteMat :: CreateStatus(GaussPoint *gp) const { - return new HydratingConcreteMatStatus(1, domain, gp); + return new HydratingConcreteMatStatus(gp); } -HydratingConcreteMatStatus :: HydratingConcreteMatStatus(int n, Domain *d, GaussPoint *g) : TransportMaterialStatus(n, d, g) -{ - //constructor - power = 0.; - lastEvalTime = -1.e20; //start from begining (set to -1.e6 s) - degreeOfHydration = 0.; - lastDegreeOfHydration = 0.; - lastEquivalentTime = 0.; - equivalentTime = 0.; -} +HydratingConcreteMatStatus :: HydratingConcreteMatStatus(GaussPoint *g) : TransportMaterialStatus(g) { } -HydratingConcreteMatStatus :: ~HydratingConcreteMatStatus() -{ - //destructor -} - //linear solver (NonStationaryTransportProblem) IntrinsicTime = TargetTime //nonlinear solver (NLTransientTransportProblem) IntrinsicTime depends on alpha -double HydratingConcreteMat :: GivePower(TimeStep *tStep, GaussPoint *gp, ValueModeType mode) +double HydratingConcreteMat :: GivePower(TimeStep *tStep, GaussPoint *gp, ValueModeType mode) const { - HydratingConcreteMatStatus *ms = static_cast< HydratingConcreteMatStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< HydratingConcreteMatStatus * >( this->giveStatus(gp) ); double castingTime = this->giveCastingTime(); double evalTime = tStep->giveIntrinsicTime(); double targTime = tStep->giveTargetTime(); @@ -283,7 +299,6 @@ double HydratingConcreteMat :: GivePower(TimeStep *tStep, GaussPoint *gp, ValueM ms->power = 0.; return 0.; } - //return computed power (homexportmodule) if ( evalTime == ms->lastEvalTime ) { return ms->power; @@ -296,32 +311,121 @@ double HydratingConcreteMat :: GivePower(TimeStep *tStep, GaussPoint *gp, ValueM //printf("%f %f %f %f\n", equivalentTime, this->lastEquivalentTime, evalTime, lastEvalTime); } } else if ( this->hydrationModelType == 2 ) { //affinity hydration model inspired by Miguel Cervera et al. - //determine timeStep for integration + //determine dTime for integration double alphaTrialOld, alphaTrialNew = 0.0; double time = ms->lastEvalTime; - double timeStep = ( evalTime - time ) / this->minModelTimeStepIntegrations; - if ( timeStep > this->maxModelIntegrationTime ) { - timeStep = this->maxModelIntegrationTime; + double dTime = ( evalTime - time ) / this->minModelTimeStepIntegrations; + if ( dTime > this->maxModelIntegrationTime ) { + dTime = this->maxModelIntegrationTime; } ms->degreeOfHydration = ms->lastDegreeOfHydration; //integration loop through hydration model at a given TimeStep while ( time < evalTime ) { - if ( time + timeStep > evalTime ) { - timeStep = evalTime - time; + if ( time + dTime > evalTime ) { + dTime = evalTime - time; } else { - time += timeStep; + time += dTime; } //printf("%f %f %f %f\n", time, affinity, scaleTemperature(), degreeOfHydration); - alphaTrialOld = ms->degreeOfHydration + scaleTemperature(gp) * affinity25(ms->degreeOfHydration) * timeStep; //predictor + alphaTrialOld = ms->degreeOfHydration + scaleTemperature(gp) * affinity25(ms->degreeOfHydration) * dTime; //predictor //http://en.wikipedia.org/wiki/Predictor%E2%80%93corrector_method //corrector - integration through trapezoidal rule //3 loops normally suffices for ( int i = 0; i < 4; i++ ) { - alphaTrialNew = ms->degreeOfHydration + scaleTemperature(gp) * timeStep / 2. * ( affinity25(ms->degreeOfHydration) + affinity25(alphaTrialOld) ); + alphaTrialNew = ms->degreeOfHydration + scaleTemperature(gp) * dTime / 2. * ( affinity25(ms->degreeOfHydration) + affinity25(alphaTrialOld) ); alphaTrialOld = alphaTrialNew; } ms->degreeOfHydration = alphaTrialNew; } + + } else if ( this->hydrationModelType == 3 ) { //Rahimi-Aghdam's model, still unfinished + double RH=0.99;//ToDo - relative humidity in pore checking from registered fields + double hStar = 0.88; + double cf = 0.; + double nh = 8.; + + double time = ms->lastEvalTime; + double dTime = ( evalTime - time ) / this->minModelTimeStepIntegrations; + + if ( dTime > this->maxModelIntegrationTime ) { + dTime = this->maxModelIntegrationTime; + } + + ms->degreeOfHydration = ms->lastDegreeOfHydration; + ms->zShell = ms->lastZShell; + ms->aCement = ms->lastACement; + ms->VCem = ms->lastVCem; + ms->VGel = ms->lastVGel; + ms->VCH = ms->lastVCH; + + while ( time < evalTime ) { + if ( time + dTime > evalTime ) { + dTime = evalTime - time; + } else { + time += dTime; + } + + if ( ms->degreeOfHydration < alphaSet ){//treat first dormant period + //assume constant rate + ms->degreeOfHydration += scaleTemperature(gp) * (alphaSet/timeSet ) * dTime; + ms->VCem = (1.-ms->degreeOfHydration)*Vc0; + ms->VCH = VCHSet * ms->degreeOfHydration/alphaSet; + ms->VGel = VGelSet * ms->degreeOfHydration/alphaSet; + } else { + double f0, f4; + + if (ms->zShell==0.){//setting time + ms->zShell = this->zSet; + ms->aCement = this->aSet; + ms->VCem=VCemSet; + ms->VGel=VGelSet; + ms->VCH=VCHSet; + } + + f0 = cf + (1.-cf)/(1. + pow((1.-RH)/(1.-hStar) , nh) ); + if ( ms->degreeOfHydration > 0.75*alphaCrit ) { + double beta = ms->degreeOfHydration - 0.75*alphaCrit + 0.75*alphaCrit*0.30/(alphaCrit/2.); + double p = pow(beta/0.30, 1.8); + f4 = p * exp(-p);//error in the original article? + } else { + double gamma = pow(ms->degreeOfHydration/(alphaCrit/2.), 1.8); + f4 = gamma * exp (-gamma); + } + + double Beff = B0 * f0 * f4; + // radius of the equivalent contact-free C-S-H shells + double zShellWedge = ms->zShell / (1.+pow((ms->zShell-this->a0)/(this->a0/6.4),5.)); + double alphaU = 0.46 + 0.95*pow(wc-0.17,0.6); + alphaU = min(alphaU,1.0); +// double hc= 0.77 + 0.22*pow(wc-0.17,0.5) + 0.15*(alphaU/ms->degreeOfHydration-1.); +// hc = min(hc,0.99); //wrong numbers + double hc=0.78; + + double Qt1 = 4*M_PI*ms->aCement*ms->zShell*Beff*(RH-hc)/(ms->zShell - ms->aCement) * zShellWedge*zShellWedge / (ms->zShell*ms->zShell); + + double xsi_gc=1.21, xsi_CHc=0.59, xsi_wc=(1.21+1.13)/2.;//assuming half + double xsi_cw=1/xsi_wc; + double xsi_gw=xsi_gc*xsi_cw; + double xsi_CHw = xsi_CHc*xsi_cw; + + double dVCem = -ng*Qt1*xsi_cw * dTime; + ms->VCem += dVCem; + double dVGel = ng*Qt1*xsi_gw * dTime; + ms->VGel += dVGel; + ms->VCH += ng*Qt1*xsi_CHw * dTime; + + ms->aCement += 1./(4.*M_PI*a0*a0*ng)*dVCem; + ms->degreeOfHydration -= 3./(4.*M_PI*a0*a0*a0*ng)*dVCem; + +// if (ms->degreeOfHydration > alphaCrit) { + ms->zShell += (dVGel+dVCem)/(4.*M_PI*ng*zShellWedge*zShellWedge);//error in article, missing ng? +// } + //ToDo relative humidity decrement, saturation degree + } + } + + + } else { OOFEM_ERROR("Unknown hydration model type %d", this->hydrationModelType); } @@ -334,15 +438,15 @@ double HydratingConcreteMat :: GivePower(TimeStep *tStep, GaussPoint *gp, ValueM } -double HydratingConcreteMat :: scaleTemperature(GaussPoint *gp) +double HydratingConcreteMat :: scaleTemperature(GaussPoint *gp) const { - HydratingConcreteMatStatus *ms = static_cast< HydratingConcreteMatStatus * >( this->giveStatus(gp) ); - return exp( this->activationEnergy / 8.314 * ( 1. / ( 273.15 + this->referenceTemperature ) - 1. / ( 273.15 + ms->giveTempField().at(1) ) ) ); + auto ms = static_cast< HydratingConcreteMatStatus * >( this->giveStatus(gp) ); + return exp( this->activationEnergy / 8.314 * ( 1. / ( 273.15 + this->referenceTemperature ) - 1. / ( 273.15 + ms->giveTempField() ) ) ); } -double HydratingConcreteMat :: affinity25(double DoH) +double HydratingConcreteMat :: affinity25(double DoH) const { - double result = this->B1 * ( this->B2 / this->DoHInf + DoH ) * ( this->DoHInf - DoH ) * exp(-this->eta * DoH / this->DoHInf); + double result = this->B1 *timeToSeconds* ( this->B2 / this->DoHInf + DoH ) * ( this->DoHInf - DoH ) * exp(-this->eta * DoH / this->DoHInf); if ( result < 0. ) { //numerical instabilities return 0.; } @@ -354,7 +458,7 @@ double HydratingConcreteMat :: affinity25(double DoH) return result; } -double HydratingConcreteMatStatus :: giveDoHActual() +double HydratingConcreteMatStatus :: giveDoHActual() const { return degreeOfHydration; } @@ -367,21 +471,27 @@ HydratingConcreteMatStatus :: updateYourself(TimeStep *tStep) this->lastEvalTime = tStep->giveIntrinsicTime(); //where heat power was evaluated in the last equilibrium this->lastEquivalentTime = this->equivalentTime; this->lastDegreeOfHydration = this->degreeOfHydration; + this->lastZShell = this->zShell; + this->lastACement = this->aCement; + this->lastVCem = this->VCem; + this->lastVGel = this->VGel; + this->lastVCH = this->VCH; + //average from last and current temperatures, in C*hour if ( !tStep->isIcApply() && mat->giveCastingTime() < tStep->giveIntrinsicTime() ) { - this->maturity += ( ( this->giveField().at(1) + this->giveTempField().at(1) ) / 2. - mat->giveMaturityT0() ) * tStep->giveTimeIncrement() / 3600.; + this->maturity += ( ( this->giveField() + this->giveTempField() ) / 2. - mat->giveMaturityT0() ) * tStep->giveTimeIncrement() / 3600.; } TransportMaterialStatus :: updateYourself(tStep); } void -HydratingConcreteMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) +HydratingConcreteMatStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { HydratingConcreteMat *mat = static_cast< HydratingConcreteMat * >( this->gp->giveMaterial() ); TransportMaterialStatus :: printOutputAt(file, tStep); fprintf(file, " status {"); - fprintf( file, "EvaluatingTime %e DoH %f HeatPower %f [W/m3 of concrete] Temperature %f conductivity %f capacity %f density %f", tStep->giveIntrinsicTime(), this->giveDoHActual(), this->power, this->giveTempField().at(1), mat->giveIsotropicConductivity(this->gp, tStep), mat->giveConcreteCapacity(this->gp, tStep), mat->giveConcreteDensity(this->gp, tStep) ); + fprintf( file, "EvaluatingTime %e DoH %f HeatPower %f [W/m3 of concrete] Temperature %f conductivity %f capacity %f density %f", tStep->giveIntrinsicTime(), this->giveDoHActual(), this->power, this->giveTempField(), mat->giveIsotropicConductivity(this->gp, tStep), mat->giveConcreteCapacity(this->gp, tStep), mat->giveConcreteDensity(this->gp, tStep) ); fprintf(file, "}\n"); } } // end namespace oofem diff --git a/src/tm/hydratingconcretemat.h b/src/tm/Materials/hydratingconcretemat.h similarity index 55% rename from src/tm/hydratingconcretemat.h rename to src/tm/Materials/hydratingconcretemat.h index 3657e128e..3dafbe695 100644 --- a/src/tm/hydratingconcretemat.h +++ b/src/tm/Materials/hydratingconcretemat.h @@ -35,8 +35,8 @@ #ifndef hydratingconcretemat_h #define hydratingconcretemat_h -#include "isoheatmat.h" -#include "hydratingisoheatmat.h" +#include "tm/Materials/isoheatmat.h" +#include "tm/Materials/hydratingisoheatmat.h" ///@name Input fields for HydratingConcreteMat //@{ @@ -61,6 +61,18 @@ #define _IFT_HydratingConcreteMat_DoH1 "doh1" #define _IFT_HydratingConcreteMat_P1 "p1" #define _IFT_HydratingConcreteMat_qpot "qpot" +#define _IFT_HydratingConcreteMat_wc "w/c" +#define _IFT_HydratingConcreteMat_ac "a/c" +#define _IFT_HydratingConcreteMat_rhoCem "rhocem" +#define _IFT_HydratingConcreteMat_rhoAgg "rhoagg" +#define _IFT_HydratingConcreteMat_Blaine "blaine" +#define _IFT_HydratingConcreteMat_alphaSet0 "alphaset0" +#define _IFT_HydratingConcreteMat_timeSet "timeset" +#define _IFT_HydratingConcreteMat_alphaCrit0 "alphacrit0" +#define _IFT_HydratingConcreteMat_B0 "b0" +#define _IFT_HydratingConcreteMat_timeToSeconds "timetoseconds" + + //@} namespace oofem { @@ -73,63 +85,93 @@ class HydratingConcreteMat : public IsotropicHeatTransferMaterial { public: HydratingConcreteMat(int n, Domain * d); - virtual ~HydratingConcreteMat(); - virtual int hasInternalSource() { return 1; } - virtual void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); + bool hasInternalSource() const override { return true; } + bool hasCastingTimeSupport() const override { return true; } + void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; - virtual double giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + double giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const override; - // identification and auxiliary functions - virtual const char *giveClassName() const { return "HydratingConcreteMat"; } + const char *giveClassName() const override { return "HydratingConcreteMat"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; // post-processing - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual double giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep); - virtual double giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep); - virtual double giveConcreteDensity(GaussPoint *gp, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + double giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) const override; + virtual double giveConcreteCapacity(GaussPoint *gp, TimeStep *tStep) const; + virtual double giveConcreteDensity(GaussPoint *gp, TimeStep *tStep) const; + /// Type of hydration model, e.g. exponential curve, Cervera's model. - int hydrationModelType; - double maxModelIntegrationTime; + int hydrationModelType = 0; + double maxModelIntegrationTime = 0.; /// Minimum number of integration steps for hydration model within a given timeStep. - double minModelTimeStepIntegrations; + double minModelTimeStepIntegrations = 0.; /// Potential heat of hydration, for ordinary Portland cement approximately 500 J/g. - double Qpot; + double Qpot = 0.; /// Mass of cement in kg per 1m3 of concrete. - double massCement; + double massCement = 0.; /// Activation energy of concrete (default 38400 J/mol/K). - double activationEnergy; + double activationEnergy = 0.; /// Reference temperature for hydration model. - double referenceTemperature; + double referenceTemperature = 0.; /** * Parameters for exponential affinity hydration model summarized in A.K. Schindler and K.J. Folliard: * Heat of Hydration Models for Cementitious Materials, ACI Materials Journal, 2005. */ - double tau, beta; + double tau = 0., beta = 0.; /** * Parameters for affinity hydration model inspired by Cervera et al. * Journal of Engineering Mechanics ASCE, 125(9), 1018-1027, 1999. */ - double B1, B2, eta, DoHInf; + double B1 = 0., B2 = 0., eta = 0., DoHInf = 0.; ///Optional extension to slag-rich, high-blended cements - double DoH1, P1; + + double DoH1 = 0., P1=0.; + /** + * Parameters for hydration model Saeed Rahimi-Aghdam, Zdeněk P. Bažant, Gianluca Cusatis: Extended Microprestress-Solidification Theory (XMPS) for Long-Term Creep and Diffusion Size Effect in Concrete at Variable Environment, JEM-ASCE, 2019. Appendix A. + */ + ///Water/cement ratio and aggregate/cement ratio + double wc, ac; + ///Density of cement and aggregates (weighted average from fine and coarse aggregates + double rhoCem, rhoAgg; + ///Initial volume fraction of cement and water + double Vc0, Vw0; + ///Volume fractions at setting time + double VCemSet, VCHSet, VGelSet; + ///Average cement particle radius (m) + double a0; + ///Number of cement particles in a unit volume + double ng; + ///Degree of hydration for setting time + double alphaSet; + ///Time at setting + double timeSet; + ///Radius of cement particle at setting time + double aSet; + ///Radius of gel barrier at setting time + double zSet; + ///Degree of hydration at which the gel barrier will be completed + double alphaCrit; + ///Basic diffusivity (about 1.1e-11 m2/day for Portland cements) + double B0; + ///timeToSeconds, =1 when running in seconds (default), =86400 when time in days + double timeToSeconds; protected: - double GivePower(TimeStep *tStep, GaussPoint *gp, ValueModeType mode); - double scaleTemperature(GaussPoint *gp); + double GivePower(TimeStep *tStep, GaussPoint *gp, ValueModeType mode) const; + double scaleTemperature(GaussPoint *gp) const; /// Return affinity scaled to 25C. - double affinity25(double alpha); + double affinity25(double alpha) const; /// Use different methods to evaluate material conductivity, capacity, or density int conductivityType, capacityType, densityType; /// Degree of reinforcement, if defined, reinforcement effect for conductivity and capacity is accounted for. Isotropic case. double reinforcementDegree; - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; }; /** @@ -138,15 +180,20 @@ class HydratingConcreteMat : public IsotropicHeatTransferMaterial class HydratingConcreteMatStatus : public TransportMaterialStatus { public: - HydratingConcreteMatStatus(int n, Domain * d, GaussPoint * g); - virtual ~HydratingConcreteMatStatus(); + HydratingConcreteMatStatus(GaussPoint * g); /// Returns actual degree of hydration at last known equilibrium. - double giveDoHActual(); - virtual void updateYourself(TimeStep *tStep); - virtual void printOutputAt(FILE *file, TimeStep *tStep); - double power; - double lastEvalTime; - double lastEquivalentTime, equivalentTime, degreeOfHydration, lastDegreeOfHydration; + double giveDoHActual() const; + void updateYourself(TimeStep *tStep) override; + void printOutputAt(FILE *file, TimeStep *tStep) const override; + double power = 0.; + double lastEvalTime = -1.e20; + double lastEquivalentTime = 0., equivalentTime = 0., degreeOfHydration = 0., lastDegreeOfHydration = 0.; + /// Radius of the equivalent contact-free C-S-H shells + double zShell = 0., lastZShell = 0.; + // Radius of cement particle + double aCement = 0., lastACement = 0.; + // Volume fractions of cement, gel, CH; + double VCem = 0., lastVCem = 0., VGel = 0., lastVGel = 0., VCH = 0., lastVCH = 0.; }; } // end namespace oofem #endif // hydratingconcretemat_h diff --git a/src/tm/hydratinghemomat.C b/src/tm/Materials/hydratinghemomat.C similarity index 73% rename from src/tm/hydratinghemomat.C rename to src/tm/Materials/hydratinghemomat.C index bd23e078e..aece67788 100644 --- a/src/tm/hydratinghemomat.C +++ b/src/tm/Materials/hydratinghemomat.C @@ -32,8 +32,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "hydratinghemomat.h" -#include "hydratingisoheatmat.h" +#include "tm/Materials/hydratinghemomat.h" +#include "tm/Materials/hydratingisoheatmat.h" #include "gausspoint.h" #include "timestep.h" #include "contextioerr.h" @@ -44,34 +44,27 @@ namespace oofem { REGISTER_Material(HydratingHeMoMaterial); -IRResultType -HydratingHeMoMaterial :: initializeFrom(InputRecord *ir) +void +HydratingHeMoMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro int value; double dvalue; // set k, c - necessary; rc beton Hellmich 2428 kJ/m3 - result = HeMoTKMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + HeMoTKMaterial :: initializeFrom(ir); // setup hydration model - result = HydrationModelInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + HydrationModelInterface :: initializeFrom(ir); dvalue = -2.; IR_GIVE_OPTIONAL_FIELD(ir, dvalue, _IFT_HydratingHeMoMaterial_hydration); - if ( dvalue >= 0. ) { - hydration = 1; - } else { - hydration = 0; - } + hydration = dvalue >= 0.; /* if (ir->hasField("tout")) { - * teplotaOut = 1; + * teplotaOut = true; * printf("HydratingHeMoMat %d: additional teplota.out output selected.\n", giveNumber()); * } else */ - teplotaOut = 0; + teplotaOut = false; if ( hydration ) { // mixture type: 1 - mtLafarge, 2 - mtHuber, 3 - mtC60 @@ -84,28 +77,26 @@ HydratingHeMoMaterial :: initializeFrom(InputRecord *ir) setMixture( ( MixtureType ) value ); printf("\nHydratingHeMoMat %d: using mixture %d.\n", giveNumber(), value); - if ( ir->hasField(_IFT_HydratingHeMoMaterial_noHeat) ) { - hydrationHeat = 0; + if ( ir.hasField(_IFT_HydratingHeMoMaterial_noHeat) ) { + hydrationHeat = false; printf( "HydratingHeMoMat %d: hydration heat neglected.\n", giveNumber() ); } else { - hydrationHeat = 1; + hydrationHeat = true; } if ( hydrationHeat ) { // include hydration internal source in LHS? - if ( ir->hasField(_IFT_HydratingHeMoMaterial_noLHS) ) { - hydrationLHS = 0; + if ( ir.hasField(_IFT_HydratingHeMoMaterial_noLHS) ) { + hydrationLHS = false; printf( "HydratingHeMoMat %d: hydration heat not included in LHS.\n", giveNumber() ); } else { - hydrationLHS = 1; + hydrationLHS = true; } } } else { hydrationHeat = false; hydrationLHS = false; } - - return IRRT_OK; } void @@ -119,19 +110,14 @@ HydratingHeMoMaterial :: setMixture(MixtureType mix) } } -int -HydratingHeMoMaterial :: hasInternalSource() -// return true if hydration heat source is present +bool +HydratingHeMoMaterial :: hasInternalSource() const { - if ( hydrationHeat ) { - return 1; - } else { - return 0; - } + return hydrationHeat; } void -HydratingHeMoMaterial :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +HydratingHeMoMaterial :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const // returns in val the hydration heat computed by the hydration model for given hydration degree increment // current hydration model returns heat in (k)J/m3. // maybe??? element expects J/kg -> would have to divide by density here @@ -157,10 +143,10 @@ HydratingHeMoMaterial :: computeInternalSourceVector(FloatArray &val, GaussPoint void HydratingHeMoMaterial :: updateInternalState(const FloatArray &vec, GaussPoint *gp, TimeStep *tStep) { - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray aux; + auto ms = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); if ( ms ) { - ms->letTempStateVectorBe(vec); + ms->setTempTemperature(vec[0]); + ms->setTempHumidity(vec[1]); if ( hydration ) { /* OBSOLETE * FloatArray s = ms->giveStateVector (); @@ -189,6 +175,7 @@ HydratingHeMoMaterial :: updateInternalState(const FloatArray &vec, GaussPoint * // additional file output !!! if ( teplotaOut && ( gp->giveNumber() == 1 ) && giveStatus(gp) ) { FILE *vyst = fopen("teplota.out", "a"); + FloatArray aux; computeInternalSourceVector(aux, gp, tStep, VM_Incremental); if ( aux.isEmpty() ) { aux.resize(1); @@ -206,32 +193,27 @@ HydratingHeMoMaterial :: updateInternalState(const FloatArray &vec, GaussPoint * } double -HydratingHeMoMaterial :: giveCharacteristicValue(MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep) +HydratingHeMoMaterial :: giveCharacteristicValue(MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep) const { double answer = 0; - if ( ( rmode >= Capacity_ww ) && ( rmode <= Capacity_wh ) ) { // standard HeMoTK values + if ( rmode >= Capacity_ww && rmode <= Capacity_wh ) { // standard HeMoTK values answer = HeMoTKMaterial :: giveCharacteristicValue(rmode, gp, tStep); if ( castAt && ( tStep->giveTargetTime() < castAt ) ) { answer *= PRECAST_CAPACITY_COEFF; // ~Zero capacity before cast } - } else if ( ( rmode >= IntSource_ww ) && ( rmode <= IntSource_wh ) ) { // Internal source values + } else if ( rmode >= IntSource_ww && rmode <= IntSource_wh ) { // Internal source values if ( !hydrationLHS ) { answer = 0; } else if ( hydrationModel ) { //!!! better via HydrationModelInterface - FloatArray vec = static_cast< TransportMaterialStatus * >( giveStatus(gp) )->giveTempField(); - - if ( vec.giveSize() < 2 ) { - vec.resize(2); - vec.at(2) = 1.0; // saturated if undefined - } else { - vec.at(2) = inverse_sorption_isotherm( vec.at(2) ); // compute relative humidity - } - - answer = hydrationModel->giveCharacteristicValue(vec, rmode, gp, tStep) - / tStep->giveTimeIncrement(); - if ( ( rmode == IntSource_ww ) || ( rmode == IntSource_hw ) ) { - answer *= give_dphi_dw( vec.at(2) ); + auto status = static_cast< HeMoTransportMaterialStatus * >( giveStatus(gp) ); + + double t = status->giveTempTemperature(); + double h = status->giveTempHumidity(); + h = inverse_sorption_isotherm( h ); // compute relative humidity + answer = hydrationModel->giveCharacteristicValue(t, h, rmode, gp, tStep) / tStep->giveTimeIncrement(); + if ( rmode == IntSource_ww || rmode == IntSource_hw ) { + answer *= give_dphi_dw( h ); } } } else { @@ -241,43 +223,22 @@ HydratingHeMoMaterial :: giveCharacteristicValue(MatResponseMode rmode, GaussPoi return answer; } -contextIOResultType +void HydratingHeMoMaterial :: saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -// saves full status for this material, also invokes saving -// for sub-objects of this. { - contextIOResultType iores; - - // write parent data - if ( ( iores = TransportMaterial :: saveIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + TransportMaterial :: saveIPContext(stream, mode, gp); // save hydration model data - maybe should check hydration option? - if ( ( iores = HydrationModelInterface :: saveContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + HydrationModelInterface :: saveContext(stream, mode); } -contextIOResultType +void HydratingHeMoMaterial :: restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -// restores full status for this material, also invokes restoring for sub-objects of this. { - contextIOResultType iores; - - // read parent data - if ( ( iores = TransportMaterial :: restoreIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + TransportMaterial :: restoreIPContext(stream, mode, gp); // read hydration model data - maybe should check hydration option? - if ( ( iores = HydrationModelInterface :: restoreContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + HydrationModelInterface :: restoreContext(stream, mode); } int @@ -300,6 +261,6 @@ HydratingHeMoMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, Interna MaterialStatus * HydratingHeMoMaterial :: CreateStatus(GaussPoint *gp) const { - return new HydratingTransportMaterialStatus(1, domain, gp); + return new HydratingTransportMaterialStatus(gp); } } // end namespace oofem diff --git a/src/tm/hydratinghemomat.h b/src/tm/Materials/hydratinghemomat.h similarity index 64% rename from src/tm/hydratinghemomat.h rename to src/tm/Materials/hydratinghemomat.h index 6d967aad8..1c69f5ef1 100644 --- a/src/tm/hydratinghemomat.h +++ b/src/tm/Materials/hydratinghemomat.h @@ -35,8 +35,8 @@ #ifndef hydratinghemomat_h #define hydratinghemomat_h -#include "hemotkmat.h" -#include "hydram.h" +#include "tm/Materials/hemotkmat.h" +#include "tm/Materials/hydram.h" ///@name Input fields for HydratingHeMoMaterial //@{ @@ -54,37 +54,35 @@ namespace oofem { class HydratingHeMoMaterial : public HeMoTKMaterial, public HydrationModelInterface { protected: - int hydration, hydrationHeat, hydrationLHS, teplotaOut; + bool hydration = false, hydrationHeat = false, hydrationLHS = false, teplotaOut = false; public: HydratingHeMoMaterial(int n, Domain * d) : HeMoTKMaterial(n, d), HydrationModelInterface() { } - virtual ~HydratingHeMoMaterial() { } void setMixture(MixtureType mix); - virtual int hasInternalSource(); // return true if hydration heat source is present - virtual void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); - virtual void updateInternalState(const FloatArray &state, GaussPoint *gp, TimeStep *tStep); + bool hasInternalSource() const override; + void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; + void updateInternalState(const FloatArray &state, GaussPoint *gp, TimeStep *tStep) override; - virtual double giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + double giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const override; // saves current context(state) into stream - virtual contextIOResultType saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); - virtual contextIOResultType restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); + void saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override; + void restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override; // identification and auxiliary functions - virtual const char *giveInputRecordName() const { return _IFT_HydratingHeMoMaterial_Name; } - virtual const char *giveClassName() const { return "HydratingHeMoMaterial"; } + const char *giveInputRecordName() const override { return _IFT_HydratingHeMoMaterial_Name; } + const char *giveClassName() const override { return "HydratingHeMoMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; // post-processing - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; -protected: - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; }; } // end namespace oofem #endif // hydratinghemomat_h diff --git a/src/tm/hydratingisoheatmat.C b/src/tm/Materials/hydratingisoheatmat.C similarity index 73% rename from src/tm/hydratingisoheatmat.C rename to src/tm/Materials/hydratingisoheatmat.C index 0337e2517..46483d8bf 100644 --- a/src/tm/hydratingisoheatmat.C +++ b/src/tm/Materials/hydratingisoheatmat.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "hydratingisoheatmat.h" +#include "tm/Materials/hydratingisoheatmat.h" #include "gausspoint.h" #include "timestep.h" #include "contextioerr.h" @@ -41,28 +41,21 @@ namespace oofem { REGISTER_Material(HydratingIsoHeatMaterial); -IRResultType -HydratingIsoHeatMaterial :: initializeFrom(InputRecord *ir) +void +HydratingIsoHeatMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro int value; double dvalue; // set k, c - necessary; rc beton Hellmich 2428 kJ/m3 - result = IsotropicHeatTransferMaterial :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + IsotropicHeatTransferMaterial :: initializeFrom(ir); // setup hydration model - result = HydrationModelInterface :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; + HydrationModelInterface :: initializeFrom(ir); dvalue = -2.; IR_GIVE_OPTIONAL_FIELD(ir, dvalue, _IFT_HydratingIsoHeatMaterial_hydration); - if ( dvalue >= 0. ) { - hydration = 1; - } else { - hydration = 0; - } + hydration = dvalue >= 0.; if ( hydration ) { // mixture type: 1 - mtLafarge, 2 - mtHuber, 3 - mtC60 @@ -75,25 +68,23 @@ HydratingIsoHeatMaterial :: initializeFrom(InputRecord *ir) setMixture( ( MixtureType ) value ); printf("\nHydratingHeatMat %d: using mixture %d.\n", giveNumber(), value); - if ( ir->hasField(_IFT_HydratingIsoHeatMaterial_noHeat) ) { - hydrationHeat = 0; + if ( ir.hasField(_IFT_HydratingIsoHeatMaterial_noHeat) ) { + hydrationHeat = false; printf( "HydratingHeatMat %d: hydration heat neglected.\n", giveNumber() ); } else { - hydrationHeat = 1; + hydrationHeat = true; } if ( hydrationHeat ) { // include hydration internal source in LHS? - if ( ir->hasField(_IFT_HydratingIsoHeatMaterial_noLHS) ) { - hydrationLHS = 0; + if ( ir.hasField(_IFT_HydratingIsoHeatMaterial_noLHS) ) { + hydrationLHS = false; printf( "HydratingHeatMat %d: hydration heat not included in LHS.\n", giveNumber() ); } else { - hydrationLHS = 1; + hydrationLHS = true; } } } - - return IRRT_OK; } void @@ -107,19 +98,14 @@ HydratingIsoHeatMaterial :: setMixture(MixtureType mix) } } -int -HydratingIsoHeatMaterial :: hasInternalSource() -// return true if hydration heat source is present +bool +HydratingIsoHeatMaterial :: hasInternalSource() const { - if ( hydrationHeat ) { - return 1; - } else { - return 0; - } + return hydrationHeat; } void -HydratingIsoHeatMaterial :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) +HydratingIsoHeatMaterial :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const // returns in val the hydration heat computed by the hydration model for given hydration degree increment // current hydration model returns heat in (k)J/m3. // maybe??? element expects J/kg -> would have to divide by density here @@ -146,9 +132,9 @@ void HydratingIsoHeatMaterial :: updateInternalState(const FloatArray &vec, GaussPoint *gp, TimeStep *tStep) { TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray aux; if ( ms ) { - ms->letTempStateVectorBe(vec); + ms->setTempField(vec[0]); + if ( hydration ) { /* OBSOLETE * FloatArray s = ms->giveStateVector (); @@ -164,8 +150,9 @@ HydratingIsoHeatMaterial :: updateInternalState(const FloatArray &vec, GaussPoin HydrationModelInterface :: updateInternalState(vec, gp, tStep); // additional file output !!! - if ( ( gp->giveNumber() == 1 ) && giveStatus(gp) ) { + if ( gp->giveNumber() == 1 && giveStatus(gp) ) { FILE *vyst = fopen("teplota.out", "a"); + FloatArray aux; computeInternalSourceVector(aux, gp, tStep, VM_Incremental); if ( aux.isEmpty() ) { aux.resize(1); @@ -183,72 +170,44 @@ HydratingIsoHeatMaterial :: updateInternalState(const FloatArray &vec, GaussPoin } double -HydratingIsoHeatMaterial :: giveCharacteristicValue(MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep) +HydratingIsoHeatMaterial :: giveCharacteristicValue(MatResponseMode rmode, GaussPoint *gp, TimeStep *tStep) const { - double answer = 0; - FloatArray vec; - if ( rmode == Capacity ) { if ( castAt && ( tStep->giveTargetTime() < castAt ) ) { - answer = this->give('c', gp, tStep) * this->give('d', gp, tStep) / 1000; // Zero capacity before cast + return this->give('c', gp, tStep) * this->give('d', gp, tStep) / 1000; // Zero capacity before cast } else { - answer = this->give('c', gp, tStep) * this->give('d', gp, tStep); + return this->give('c', gp, tStep) * this->give('d', gp, tStep); } } else if ( !hydrationLHS ) { - answer = 0; + return 0; } else if ( hydrationModel ) { //!!! better via HydrationModelInterface - vec = static_cast< TransportMaterialStatus * >( giveStatus(gp) )->giveTempField(); - if ( vec.giveSize() < 2 ) { - vec.resize(2); - vec.at(2) = 1.; // saturated if undefined - } + auto status = static_cast< HeMoTransportMaterialStatus * >( giveStatus(gp) ); + double t = status->giveTempTemperature(); + double h = status->giveTempHumidity(); // TODO CHECK - answer = hydrationModel->giveCharacteristicValue(vec, rmode, gp, tStep) - / tStep->giveTimeIncrement(); + return hydrationModel->giveCharacteristicValue(t, h, rmode, gp, tStep) / tStep->giveTimeIncrement(); } else { OOFEM_ERROR("unknown MatResponseMode (%s)", __MatResponseModeToString(rmode) ); + return 0.; } - - return answer; } -contextIOResultType +void HydratingIsoHeatMaterial :: saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -// saves full status for this material, also invokes saving -// for sub-objects of this. { - contextIOResultType iores; - - // write parent data - if ( ( iores = TransportMaterial :: saveIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + TransportMaterial :: saveIPContext(stream, mode, gp); // save hydration model data - maybe should check hydration option? - if ( ( iores = HydrationModelInterface :: saveContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + HydrationModelInterface :: saveContext(stream, mode); } -contextIOResultType +void HydratingIsoHeatMaterial :: restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) -// restores full status for this material, also invokes restoring for sub-objects of this. { - contextIOResultType iores; - - // read parent data - if ( ( iores = TransportMaterial :: restoreIPContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } + TransportMaterial :: restoreIPContext(stream, mode, gp); // read hydration model data - maybe should check hydration option? - if ( ( iores = HydrationModelInterface :: restoreContext(stream, mode, gp) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + HydrationModelInterface :: restoreContext(stream, mode); } int @@ -270,12 +229,12 @@ HydratingIsoHeatMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, Inte MaterialStatus * HydratingIsoHeatMaterial :: CreateStatus(GaussPoint *gp) const { - return new HydratingTransportMaterialStatus(1, domain, gp); + return new HydratingTransportMaterialStatus(gp); } void -HydratingTransportMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) +HydratingTransportMaterialStatus :: printOutputAt(FILE *file, TimeStep *tStep) const { fprintf(file, " status "); HydrationModelStatusInterface :: printOutputAt(file, tStep); @@ -289,7 +248,7 @@ HydratingTransportMaterialStatus :: giveInterface(InterfaceType type) if ( type == HydrationModelStatusInterfaceType ) { return static_cast< HydrationModelStatusInterface * >(this); } else { - return NULL; + return nullptr; } } } // end namespace oofem diff --git a/src/tm/hydratingisoheatmat.h b/src/tm/Materials/hydratingisoheatmat.h similarity index 62% rename from src/tm/hydratingisoheatmat.h rename to src/tm/Materials/hydratingisoheatmat.h index 1170eee49..33b55005c 100644 --- a/src/tm/hydratingisoheatmat.h +++ b/src/tm/Materials/hydratingisoheatmat.h @@ -35,8 +35,8 @@ #ifndef hydratingisoheatmat_h #define hydratingisoheatmat_h -#include "isoheatmat.h" -#include "hydram.h" +#include "tm/Materials/isoheatmat.h" +#include "tm/Materials/hydram.h" ///@name Input fields for HydratingIsoHeatMaterial //@{ @@ -54,17 +54,16 @@ namespace oofem { class HydratingTransportMaterialStatus : public TransportMaterialStatus, public HydrationModelStatusInterface { public: - HydratingTransportMaterialStatus(int n, Domain * d, GaussPoint * g) : TransportMaterialStatus(n, d, g), HydrationModelStatusInterface() { } - virtual ~HydratingTransportMaterialStatus() { } + HydratingTransportMaterialStatus(GaussPoint * g) : TransportMaterialStatus(g), HydrationModelStatusInterface() { } - virtual Interface *giveInterface(InterfaceType t); - virtual const char *giveClassName() const { return "HydratingTransportMaterialStatus"; } + Interface *giveInterface(InterfaceType t) override; + const char *giveClassName() const override { return "HydratingTransportMaterialStatus"; } - virtual void updateYourself(TimeStep *tStep) { + void updateYourself(TimeStep *tStep) override { HydrationModelStatusInterface :: updateYourself(tStep); TransportMaterialStatus :: updateYourself(tStep); } - virtual void printOutputAt(FILE *file, TimeStep *tStep); + void printOutputAt(FILE *file, TimeStep *tStep) const override; }; /** @@ -75,37 +74,33 @@ class HydratingTransportMaterialStatus : public TransportMaterialStatus, public class HydratingIsoHeatMaterial : public IsotropicHeatTransferMaterial, public HydrationModelInterface { protected: - int hydration, hydrationHeat, hydrationLHS; + bool hydration = false, hydrationHeat = false, hydrationLHS = false; public: HydratingIsoHeatMaterial(int n, Domain * d) : IsotropicHeatTransferMaterial(n, d), HydrationModelInterface() { } - virtual ~HydratingIsoHeatMaterial() { } void setMixture(MixtureType mix); /// Return true if hydration heat source is present. - virtual int hasInternalSource(); - virtual void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); - virtual void updateInternalState(const FloatArray &state, GaussPoint *gp, TimeStep *tStep); + bool hasInternalSource() const override; + void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; + void updateInternalState(const FloatArray &state, GaussPoint *gp, TimeStep *tStep) override; - virtual double giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + double giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const override; - virtual contextIOResultType saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); - virtual contextIOResultType restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp); + void saveIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override; + void restoreIPContext(DataStream &stream, ContextMode mode, GaussPoint *gp) override; // identification and auxiliary functions - virtual const char *giveInputRecordName() const { return _IFT_HydratingIsoHeatMaterial_Name; } - virtual const char *giveClassName() const { return "HydratingIsoHeatMaterial"; } + const char *giveInputRecordName() const override { return _IFT_HydratingIsoHeatMaterial_Name; } + const char *giveClassName() const override { return "HydratingIsoHeatMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); + void initializeFrom(InputRecord &ir) override; - // post-processing - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - -protected: - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; }; } // end namespace oofem #endif // hydratingisoheatmat_h diff --git a/src/tm/isoheatmat.C b/src/tm/Materials/isoheatmat.C similarity index 65% rename from src/tm/isoheatmat.C rename to src/tm/Materials/isoheatmat.C index 4290c593e..3f7d25954 100644 --- a/src/tm/isoheatmat.C +++ b/src/tm/Materials/isoheatmat.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "isoheatmat.h" +#include "tm/Materials/isoheatmat.h" #include "floatmatrix.h" #include "function.h" #include "gausspoint.h" @@ -42,34 +42,22 @@ namespace oofem { REGISTER_Material(IsotropicHeatTransferMaterial); -IsotropicHeatTransferMaterial :: IsotropicHeatTransferMaterial(int n, Domain *d) : TransportMaterial(n, d) -{ - // constructor - maturityT0 = 0.; -} +IsotropicHeatTransferMaterial :: IsotropicHeatTransferMaterial(int n, Domain *d) : TransportMaterial(n, d) { } -IsotropicHeatTransferMaterial :: ~IsotropicHeatTransferMaterial() { - // destructor -} -IRResultType -IsotropicHeatTransferMaterial :: initializeFrom(InputRecord *ir) +void +IsotropicHeatTransferMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Material :: initializeFrom(ir); IR_GIVE_FIELD(ir, conductivity, _IFT_IsotropicHeatTransferMaterial_k); IR_GIVE_FIELD(ir, capacity, _IFT_IsotropicHeatTransferMaterial_c); IR_GIVE_OPTIONAL_FIELD(ir, maturityT0, _IFT_IsotropicHeatTransferMaterial_maturityT0); IR_GIVE_OPTIONAL_FIELD(ir, density, _IFT_IsotropicHeatTransferMaterial_d); - - return Material :: initializeFrom(ir); } double -IsotropicHeatTransferMaterial :: give(int aProperty, GaussPoint *gp, TimeStep *tStep) -// -// Returns the value of the property aProperty (e.g. 'k' the conductivity of the receiver). -// +IsotropicHeatTransferMaterial :: give(int aProperty, GaussPoint *gp, TimeStep *tStep) const { if ( aProperty == 'k' ) { //thermal conductivity [W/m/K] return conductivity.eval( { { "te", giveTemperature(gp) }, { "t", tStep->giveIntrinsicTime() } }, this->giveDomain(), gp, giveTemperature(gp) ); @@ -85,64 +73,39 @@ IsotropicHeatTransferMaterial :: give(int aProperty, GaussPoint *gp, TimeStep *t } -void -IsotropicHeatTransferMaterial :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) +FloatArrayF<3> +IsotropicHeatTransferMaterial :: computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const { - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); ms->setTempField(field); ms->setTempGradient(grad); ///@todo Shouldn't the conductivity typically depend on the primary field and/or its gradient? - answer.beScaled(-this->giveIsotropicConductivity(gp, tStep), grad); - + auto answer = -this->giveIsotropicConductivity(gp, tStep) * grad; ms->setTempFlux(answer); + return answer; } -void -IsotropicHeatTransferMaterial :: giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) +FloatMatrixF<3,3> +IsotropicHeatTransferMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - /* - * returns constitutive (conductivity) matrix of receiver - */ - MaterialMode mMode = gp->giveMaterialMode(); double cond = this->giveIsotropicConductivity(gp, tStep); - - switch ( mMode ) { - case _1dHeat: - answer.resize(1, 1); - answer.at(1, 1) = cond; - case _2dHeat: - answer.resize(2, 2); - answer.at(1, 1) = cond; - answer.at(2, 2) = cond; - return; - - case _3dHeat: - answer.resize(3, 3); - answer.at(1, 1) = cond; - answer.at(2, 2) = cond; - answer.at(3, 3) = cond; - return; - - default: - OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mMode) ); - } + return cond * eye<3>(); } + double -IsotropicHeatTransferMaterial :: giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) { +IsotropicHeatTransferMaterial :: giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) const +{ return give('k', gp, tStep); } double IsotropicHeatTransferMaterial :: giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { if ( mode == Capacity ) { return ( this->give('c', gp, tStep) * this->give('d', gp, tStep) ); @@ -183,34 +146,10 @@ IsotropicHeatTransferMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, return TransportMaterial :: giveIPValue(answer, gp, type, tStep); } - -MaterialStatus * -IsotropicHeatTransferMaterial :: CreateStatus(GaussPoint *gp) const -{ - return new IsotropicHeatTransferMaterialStatus(1, domain, gp); -} - -IsotropicHeatTransferMaterialStatus :: IsotropicHeatTransferMaterialStatus(int n, Domain *d, GaussPoint *g) : TransportMaterialStatus(n, d, g) -{ - //constructor -} - - -IsotropicHeatTransferMaterialStatus :: ~IsotropicHeatTransferMaterialStatus() -{ - //destructor -} - -void -IsotropicHeatTransferMaterialStatus :: updateYourself(TimeStep *tStep) -{ - TransportMaterialStatus :: updateYourself(tStep); -} - -double IsotropicHeatTransferMaterial :: giveTemperature(GaussPoint *gp) +double IsotropicHeatTransferMaterial :: giveTemperature(GaussPoint *gp) const { - IsotropicHeatTransferMaterialStatus *ms = static_cast< IsotropicHeatTransferMaterialStatus * >( this->giveStatus(gp) ); - return ms->giveTempField().at(1); + auto ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); + return ms->giveTempField(); } } // end namespace oofem diff --git a/src/tm/isoheatmat.h b/src/tm/Materials/isoheatmat.h similarity index 61% rename from src/tm/isoheatmat.h rename to src/tm/Materials/isoheatmat.h index 100ea6e1e..98bcf6c90 100644 --- a/src/tm/isoheatmat.h +++ b/src/tm/Materials/isoheatmat.h @@ -35,10 +35,11 @@ #ifndef isoheatmat_h #define isoheatmat_h -#include "transportmaterial.h" +#include "tm/Materials/transportmaterial.h" #include "floatarray.h" #include "floatmatrix.h" #include "scalarfunction.h" +#include "floatmatrixf.h" ///@name Input fields for IsotropicHeatTransferMaterial //@{ @@ -61,45 +62,31 @@ class IsotropicHeatTransferMaterial : public TransportMaterial ScalarFunction conductivity; ///< Conductivity (k in input file). ScalarFunction capacity; ///< Capacity (c in input file). ScalarFunction density; ///< Density (td in input file). - double maturityT0; ///< Baseline for maturity mathod + double maturityT0 = 0.; ///< Baseline for maturity mathod public: IsotropicHeatTransferMaterial(int n, Domain * d); - virtual ~IsotropicHeatTransferMaterial(); - virtual void giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep); + FloatArrayF<3> computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + virtual double giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep) const; - virtual double giveIsotropicConductivity(GaussPoint *gp, TimeStep *tStep); + double giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const override; - virtual double giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + virtual double giveMaturityT0() const { return maturityT0; } - virtual double giveMaturityT0() { return maturityT0; } + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + const char *giveInputRecordName() const override { return _IFT_IsotropicHeatTransferMaterial_Name; } + const char *giveClassName() const override { return "IsotropicHeatTransferMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_IsotropicHeatTransferMaterial_Name; } - virtual const char *giveClassName() const { return "IsotropicHeatTransferMaterial"; } + void initializeFrom(InputRecord &ir) override; - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual double give(int aProperty, GaussPoint *gp, TimeStep *tStep); - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; - double giveTemperature(GaussPoint *gp); -}; - -class IsotropicHeatTransferMaterialStatus : public TransportMaterialStatus -{ -public: - IsotropicHeatTransferMaterialStatus(int n, Domain * d, GaussPoint * g); - virtual ~IsotropicHeatTransferMaterialStatus(); - virtual void updateYourself(TimeStep *tStep); + double give(int aProperty, GaussPoint *gp, TimeStep *tStep) const; + double giveTemperature(GaussPoint *gp) const; }; } // end namespace oofem diff --git a/src/tm/isolinmoisturemat.C b/src/tm/Materials/isolinmoisturemat.C similarity index 88% rename from src/tm/isolinmoisturemat.C rename to src/tm/Materials/isolinmoisturemat.C index adfba4068..3d085146a 100644 --- a/src/tm/isolinmoisturemat.C +++ b/src/tm/Materials/isolinmoisturemat.C @@ -32,7 +32,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "isolinmoisturemat.h" +#include "tm/Materials/isolinmoisturemat.h" #include "floatmatrix.h" #include "gausspoint.h" #include "classfactory.h" @@ -40,26 +40,24 @@ namespace oofem { REGISTER_Material(IsotropicLinMoistureTransferMaterial); -IRResultType -IsotropicLinMoistureTransferMaterial :: initializeFrom(InputRecord *ir) +void +IsotropicLinMoistureTransferMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + IsotropicMoistureTransferMaterial :: initializeFrom(ir); IR_GIVE_FIELD(ir, permeability, _IFT_IsotropicLinMoistureTransferMaterial_perm); IR_GIVE_FIELD(ir, moistureCapacity, _IFT_IsotropicLinMoistureTransferMaterial_capa); - - return IsotropicMoistureTransferMaterial :: initializeFrom(ir); } double -IsotropicLinMoistureTransferMaterial :: giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep) +IsotropicLinMoistureTransferMaterial :: giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep) const { return this->moistureCapacity; } double -IsotropicLinMoistureTransferMaterial :: givePermeability(GaussPoint *gp, TimeStep *tStep) +IsotropicLinMoistureTransferMaterial :: givePermeability(GaussPoint *gp, TimeStep *tStep) const { return this->permeability; } diff --git a/src/tm/isolinmoisturemat.h b/src/tm/Materials/isolinmoisturemat.h similarity index 80% rename from src/tm/isolinmoisturemat.h rename to src/tm/Materials/isolinmoisturemat.h index d48422101..be9039103 100644 --- a/src/tm/isolinmoisturemat.h +++ b/src/tm/Materials/isolinmoisturemat.h @@ -35,7 +35,7 @@ #ifndef isolinmoisturemat_h #define isolinmoisturemat_h -#include "isomoisturemat.h" +#include "tm/Materials/isomoisturemat.h" #include "floatarray.h" #include "floatmatrix.h" @@ -54,20 +54,18 @@ namespace oofem { class IsotropicLinMoistureTransferMaterial : public IsotropicMoistureTransferMaterial { protected: - double moistureCapacity; - double permeability; + double moistureCapacity = 0.; + double permeability = 0.; public: IsotropicLinMoistureTransferMaterial(int n, Domain * d) : IsotropicMoistureTransferMaterial(n, d) { } - virtual ~IsotropicLinMoistureTransferMaterial() { } - virtual double givePermeability(GaussPoint *gp, TimeStep *tStep); - virtual double giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep); + void initializeFrom(InputRecord &ir) override; + double givePermeability(GaussPoint *gp, TimeStep *tStep) const override; + double giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep) const override; - virtual const char *giveInputRecordName() const { return _IFT_IsotropicLinMoistureTransferMaterial_Name; } - virtual const char *giveClassName() const { return "IsotropicLinMoistureTransferMaterial"; } - - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_IsotropicLinMoistureTransferMaterial_Name; } + const char *giveClassName() const override { return "IsotropicLinMoistureTransferMaterial"; } }; } // end namespace oofem #endif // isolinmoisturemat_h diff --git a/src/tm/isomoisturemat.C b/src/tm/Materials/isomoisturemat.C similarity index 65% rename from src/tm/isomoisturemat.C rename to src/tm/Materials/isomoisturemat.C index 9170c58e3..5aa2d9b3f 100644 --- a/src/tm/isomoisturemat.C +++ b/src/tm/Materials/isomoisturemat.C @@ -32,73 +32,43 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "isomoisturemat.h" +#include "tm/Materials/isomoisturemat.h" #include "floatmatrix.h" #include "gausspoint.h" namespace oofem { -IRResultType -IsotropicMoistureTransferMaterial :: initializeFrom(InputRecord *ir) -{ - return Material :: initializeFrom(ir); -} - void -IsotropicMoistureTransferMaterial :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) +IsotropicMoistureTransferMaterial :: initializeFrom(InputRecord &ir) { - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); + Material :: initializeFrom(ir); +} - ///@todo Shouldn't the permeability typically depend on the primary field and/or its gradient? - answer.beScaled(-this->givePermeability(gp, tStep), grad); - ms->setTempField(field); +FloatArrayF<3> +IsotropicMoistureTransferMaterial :: computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const +{ + auto ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); ms->setTempGradient(grad); + ms->setTempField(field); + + auto answer = -this->givePermeability(gp, tStep) * grad; ms->setTempFlux(answer); + return answer; } -void -IsotropicMoistureTransferMaterial :: giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -{ - /* - * returns constitutive (conductivity) matrix of receiver - */ - - double permeability; - permeability = this->givePermeability(gp, tStep); - - MaterialMode mMode = gp->giveMaterialMode(); - switch ( mMode ) { - case _1dHeat: - answer.resize(1, 1); - answer.at(1, 1) = permeability; - case _2dHeat: - answer.resize(2, 2); - answer.at(1, 1) = permeability; - answer.at(2, 2) = permeability; - return; - case _3dHeat: - answer.resize(3, 3); - answer.at(1, 1) = permeability; - answer.at(2, 2) = permeability; - answer.at(3, 3) = permeability; - return; - - default: - OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mMode) ); - } - - return; +FloatMatrixF<3,3> +IsotropicMoistureTransferMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + double permeability = this->givePermeability(gp, tStep); + return permeability * eye<3>(); } double IsotropicMoistureTransferMaterial :: giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { if ( mode == Capacity ) { return this->giveMoistureCapacity(gp, tStep); @@ -124,7 +94,6 @@ IsotropicMoistureTransferMaterial :: giveIPValue(FloatArray &answer, GaussPoint answer.at(1) = giveMoistureContent(humidity.at(1)); return 1; } - /* else if ( type == IST_Humidity ) { * FloatArray state = static_cast< TransportMaterialStatus * >( giveStatus(gp) )->giveStateVector(); diff --git a/src/tm/isomoisturemat.h b/src/tm/Materials/isomoisturemat.h similarity index 66% rename from src/tm/isomoisturemat.h rename to src/tm/Materials/isomoisturemat.h index cc15da331..736996f08 100644 --- a/src/tm/isomoisturemat.h +++ b/src/tm/Materials/isomoisturemat.h @@ -35,9 +35,9 @@ #ifndef isomoisturemat_h #define isomoisturemat_h -#include "transportmaterial.h" -#include "floatarray.h" -#include "floatmatrix.h" +#include "tm/Materials/transportmaterial.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" namespace oofem { /** @@ -48,28 +48,22 @@ class IsotropicMoistureTransferMaterial : public TransportMaterial { public: IsotropicMoistureTransferMaterial(int n, Domain * d) : TransportMaterial(n, d) { } - virtual ~IsotropicMoistureTransferMaterial() { } - virtual void giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep); + void initializeFrom(InputRecord &ir) override; - virtual void giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + FloatArrayF<3> computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual double giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + double giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual double givePermeability(GaussPoint *gp, TimeStep *tStep) = 0; - virtual double giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep) = 0; + virtual double givePermeability(GaussPoint *gp, TimeStep *tStep) const = 0; + virtual double giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep) const = 0; //sorption isotherm, return total water mass [kg/m3] - virtual double giveMoistureContent(double humidity) {return 0.;}; + virtual double giveMoistureContent(double humidity) const { return 0.; } - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - virtual const char *giveClassName() const { return "IsotropicMoistureTransferMaterial"; } + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + const char *giveClassName() const override { return "IsotropicMoistureTransferMaterial"; } - virtual IRResultType initializeFrom(InputRecord *ir); }; } // end namespace oofem #endif // isomoisturemat_h diff --git a/src/tm/Materials/nlisomoisturemat.C b/src/tm/Materials/nlisomoisturemat.C new file mode 100644 index 000000000..6931b4780 --- /dev/null +++ b/src/tm/Materials/nlisomoisturemat.C @@ -0,0 +1,452 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "tm/Materials/nlisomoisturemat.h" +#include "gausspoint.h" +#include "mathfem.h" +#include "classfactory.h" + +namespace oofem { +REGISTER_Material(NlIsoMoistureMaterial); + +void +NlIsoMoistureMaterial::initializeFrom(InputRecord &ir) +{ + IsotropicMoistureTransferMaterial::initializeFrom(ir); + + int type = 0; + IR_GIVE_FIELD(ir, type, _IFT_NlIsoMoistureMaterial_isothermtype); + + if ( type > 7 ) { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_isothermtype, "must be equal to 0, 1, 2 ... 7"); + } + + this->Isotherm = ( isothermType ) type; + + IR_GIVE_FIELD(ir, type, _IFT_NlIsoMoistureMaterial_permeabilitytype); + + if ( type >= 4 ) { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_permeabilitytype, "must be equal to 0, 1, 2, 3"); + } + + this->Permeability = ( permeabilityType ) type; + + if ( Permeability == KunzelPerm ) { + IR_GIVE_FIELD(ir, type, _IFT_NlIsoMoistureMaterial_capillarytransporttype); + this->CapillaryTransport = ( capillaryTransportType ) type; + if ( type >= 3 ) { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_capillarytransporttype, "must be equal to 0, 1, 2"); + } + } + + if ( this->Isotherm == linear ) { // linear isotherm = type 0 + IR_GIVE_FIELD(ir, moistureCapacity, _IFT_NlIsoMoistureMaterial_capa); + this->iso_offset = 0.; + IR_GIVE_OPTIONAL_FIELD(ir, iso_offset, _IFT_NlIsoMoistureMaterial_iso_offset); + } else if ( this->Isotherm == multilinear ) { // multilinear isotherm = type 1 + IR_GIVE_FIELD(ir, iso_h, _IFT_NlIsoMoistureMaterial_iso_h); + IR_GIVE_FIELD(ir, iso_wh, _IFT_NlIsoMoistureMaterial_iso_wh); + + if ( iso_h.giveSize() != iso_wh.giveSize() ) { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_iso_h, "the size of 'iso_h' and 'iso_w(h)' must be the same"); + } + + for ( int i = 1; i < iso_h.giveSize(); i++ ) { + if ( ( iso_h.at(i) < 0. ) || ( iso_h.at(i) > 1. ) ) { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_iso_h, "iso_h must be in the range <0; 1>"); + } + } + } else if ( this->Isotherm == Ricken ) { // reference mentioned in Kuenzel isotherm = type 2 + IR_GIVE_FIELD(ir, dd, _IFT_NlIsoMoistureMaterial_dd); + } else if ( this->Isotherm == Kuenzel ) { // isotherm = type 3 + IR_GIVE_FIELD(ir, wf, _IFT_NlIsoMoistureMaterial_wf); + IR_GIVE_FIELD(ir, b, _IFT_NlIsoMoistureMaterial_b); + } else if ( this->Isotherm == Hansen ) { // isotherm = type 4 + IR_GIVE_FIELD(ir, uh, _IFT_NlIsoMoistureMaterial_uh); + IR_GIVE_FIELD(ir, A, _IFT_NlIsoMoistureMaterial_a); + IR_GIVE_FIELD(ir, nn, _IFT_NlIsoMoistureMaterial_nn); + IR_GIVE_FIELD(ir, rhodry, _IFT_NlIsoMoistureMaterial_rhodry); + } else if ( this->Isotherm == BSB ) { // isotherm = type 5 + IR_GIVE_FIELD(ir, c, _IFT_NlIsoMoistureMaterial_c); + IR_GIVE_FIELD(ir, k, _IFT_NlIsoMoistureMaterial_k); + IR_GIVE_FIELD(ir, Vm, _IFT_NlIsoMoistureMaterial_vm); + IR_GIVE_FIELD(ir, rhodry, _IFT_NlIsoMoistureMaterial_rhodry); + } else if ( this->Isotherm == bilinear ) { // bilinear isotherm = type 6 + IR_GIVE_FIELD(ir, moistureCapacity, _IFT_NlIsoMoistureMaterial_capa); + IR_GIVE_FIELD(ir, wf, _IFT_NlIsoMoistureMaterial_wf); + IR_GIVE_FIELD(ir, hx, _IFT_NlIsoMoistureMaterial_hx); + IR_GIVE_FIELD(ir, dx, _IFT_NlIsoMoistureMaterial_dx); + + this->iso_offset = 0.; + IR_GIVE_OPTIONAL_FIELD(ir, iso_offset, _IFT_NlIsoMoistureMaterial_iso_offset); + + this->capa2 = ( wf - hx * moistureCapacity - iso_offset ) / ( 1 - hx ); + double wa = ( hx - dx ) * moistureCapacity + iso_offset; + double wb = hx * moistureCapacity + dx * capa2 + iso_offset; + + this->c1 = ( moistureCapacity * ( 2 * dx ) + capa2 * ( 2 * dx ) + 2 * wa - 2 * wb ) / ( 8 * dx * dx * dx ); + this->c2 = ( -3 * c1 * ( 2 * dx ) * ( 2 * dx ) - moistureCapacity + capa2 ) / ( 2 * ( 2 * dx ) ); + } else if ( this->Isotherm == vanGenuchten ) { // isotherm = type 7 + IR_GIVE_FIELD(ir, wf, _IFT_NlIsoMoistureMaterial_wf); + IR_GIVE_FIELD(ir, vG_b, _IFT_NlIsoMoistureMaterial_vg_b); + IR_GIVE_FIELD(ir, vG_m, _IFT_NlIsoMoistureMaterial_vg_m); + } else { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_isothermtype, "unknown isotherm type"); + } + + if ( this->Permeability == multilin ) { + IR_GIVE_FIELD(ir, perm_h, _IFT_NlIsoMoistureMaterial_perm_h); + IR_GIVE_FIELD(ir, perm_ch, _IFT_NlIsoMoistureMaterial_perm_ch); + + if ( perm_h.giveSize() != perm_ch.giveSize() ) { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_perm_ch, "the size of 'perm_h' and 'perm_c(h)' must be the same"); + } + + for ( int i = 1; i < perm_h.giveSize(); i++ ) { + if ( ( perm_h.at(i) < 0. ) || ( perm_h.at(i) > 1. ) ) { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_perm_h, "must be in the range <0; 1>"); + } + } + } else if ( this->Permeability == Bazant ) { + IR_GIVE_FIELD(ir, C1, _IFT_NlIsoMoistureMaterial_c1); + IR_GIVE_FIELD(ir, n, _IFT_NlIsoMoistureMaterial_n); + IR_GIVE_FIELD(ir, alpha0, _IFT_NlIsoMoistureMaterial_alpha0); + IR_GIVE_FIELD(ir, hC, _IFT_NlIsoMoistureMaterial_hc); + } else if ( this->Permeability == Xi ) { + IR_GIVE_FIELD(ir, alphah, _IFT_NlIsoMoistureMaterial_alphah); + IR_GIVE_FIELD(ir, betah, _IFT_NlIsoMoistureMaterial_betah); + IR_GIVE_FIELD(ir, gammah, _IFT_NlIsoMoistureMaterial_gammah); + } else if ( this->Permeability == KunzelPerm ) { + IR_GIVE_FIELD(ir, mu, _IFT_NlIsoMoistureMaterial_mu); + + // read temperature - either constant or time-dependent + if ( ir.hasField(_IFT_NlIsoMoistureMaterial_ttf) ) { + IR_GIVE_FIELD(ir, T_TF, _IFT_NlIsoMoistureMaterial_ttf); + } else { + IR_GIVE_FIELD(ir, T, _IFT_NlIsoMoistureMaterial_t); + } + + IR_GIVE_OPTIONAL_FIELD(ir, capillary_transport_coef, _IFT_NlIsoMoistureMaterial_capil_coef); + + IR_GIVE_OPTIONAL_FIELD(ir, PL, _IFT_NlIsoMoistureMaterial_pl); + + IR_GIVE_OPTIONAL_FIELD(ir, timeScale, _IFT_NlIsoMoistureMaterial_timescale); + + + if ( CapillaryTransport == Multilin_h ) { + IR_GIVE_FIELD(ir, capPerm_h, _IFT_NlIsoMoistureMaterial_capperm_h); + IR_GIVE_FIELD(ir, capPerm_Dwh, _IFT_NlIsoMoistureMaterial_capperm_dwh); + + if ( !( capPerm_h.giveSize() == capPerm_Dwh.giveSize() ) ) { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_capperm_dwh, "size of 'capPerm_h' and 'capPerm_dw(h)' must be the same"); + } + + for ( int i = 1; i < capPerm_h.giveSize(); i++ ) { + if ( ( capPerm_h.at(i) < 0. ) || ( capPerm_h.at(i) > 1. ) ) { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_capperm_h, "must be in the range <0; 1>"); + } + } + } else if ( this->CapillaryTransport == Multilin_wV ) { + rhoH2O = 1000.; + IR_GIVE_OPTIONAL_FIELD(ir, rhoH2O, _IFT_NlIsoMoistureMaterial_rhoh2o); + + IR_GIVE_FIELD(ir, capPerm_wV, _IFT_NlIsoMoistureMaterial_capperm_wv); + IR_GIVE_FIELD(ir, capPerm_DwwV, _IFT_NlIsoMoistureMaterial_capperm_dwwv); + + if ( !( capPerm_wV.giveSize() == capPerm_DwwV.giveSize() ) ) { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_capperm_dwwv, "size of 'capPerm_wV' and 'capPerm_Dw(wV)' must be the same"); + } + + for ( int i = 1; i < capPerm_wV.giveSize(); i++ ) { + if ( ( capPerm_wV.at(i) < 0. ) || ( capPerm_wV.at(i) > 1. ) ) { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_capperm_wv, "must be in the range <0; 1>"); + } + } + } else { // according to Kunzel + if ( this->Isotherm == Hansen ) { + this->wf = rhodry * uh; + } else { + IR_GIVE_FIELD(ir, wf, _IFT_NlIsoMoistureMaterial_wf); + } + IR_GIVE_FIELD(ir, Abs, _IFT_NlIsoMoistureMaterial_abs); + } + } else { + throw ValueInputException(ir, _IFT_NlIsoMoistureMaterial_permeabilitytype, "unknown permeability type"); + } + + wn = 0.; + IR_GIVE_OPTIONAL_FIELD(ir, wn, _IFT_NlIsoMoistureMaterial_wn); + IR_GIVE_OPTIONAL_FIELD(ir, alpha, _IFT_NlIsoMoistureMaterial_alpha); +} + +double +NlIsoMoistureMaterial::giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep) const +{ + double humidity = this->giveHumidity(gp, VM_Total); + + if ( this->Isotherm == linear ) { + return moistureCapacity; + } else if ( this->Isotherm == multilinear ) { + double tol = 1.e-10; + for ( int i = 2; i <= iso_h.giveSize(); i++ ) { + if ( ( humidity - iso_h.at(i) ) < tol ) { + return ( iso_wh.at(i) - iso_wh.at(i - 1) ) / ( iso_h.at(i) - iso_h.at(i - 1) ); + } + } + } else if ( this->Isotherm == Ricken ) { + return 1. / ( dd * ( 1. - humidity ) ); + } else if ( this->Isotherm == Kuenzel ) { + return wf * ( b - 1. ) * b / ( ( b - humidity ) * ( b - humidity ) ); + } else if ( this->Isotherm == Hansen ) { + return rhodry * uh / ( A * nn * humidity * pow( ( 1 - log(humidity) / A ), ( 1 / nn + 1 ) ) ); + } else if ( this->Isotherm == BSB ) { + double nominator, denominator; + nominator = c * k * Vm * rhodry * ( 1. + k * k * humidity * humidity * c - k * k * humidity * humidity ); + denominator = ( 1. - k * humidity ) * ( 1. - k * humidity ) * ( 1. + ( c - 1. ) * k * humidity ) * ( 1. + ( c - 1. ) * k * humidity ); + return nominator / denominator; + } else if ( this->Isotherm == bilinear ) { + if ( humidity <= ( hx - dx ) ) { + return moistureCapacity; + } else if ( humidity >= ( hx + dx ) ) { + return capa2; + } else { + return moistureCapacity + 2 * c2 * ( humidity - hx + dx ) + 3 * c1 * pow(humidity - hx + dx, 2); + } + } else if ( this->Isotherm == vanGenuchten ) { + return wf * vG_m * vG_b / humidity * pow( ( pow( ( -vG_b * log(humidity) ), ( 1. / ( 1. - vG_m ) ) ) + 1. ), ( -vG_m - 1 ) ) * ( 1. / ( 1. - vG_m ) * pow( ( -vG_b * log(humidity) ), ( vG_m / ( 1. - vG_m ) ) ) ); + } else { + OOFEM_ERROR("unknown isotherm type"); + } + + return 0.; +} + +double +NlIsoMoistureMaterial::giveMoistureContent(double humidity) const +{ + if ( this->Isotherm == linear ) { + return max(moistureCapacity * humidity + iso_offset, 0.); + } else if ( this->Isotherm == multilinear ) { + double tol = 1.e-10; + for ( int i = 1; i <= iso_h.giveSize(); i++ ) { + if ( ( humidity - iso_h.at(i) ) < tol ) { + return iso_wh.at(i - 1) + ( iso_wh.at(i) - iso_wh.at(i - 1) ) / ( iso_h.at(i) - iso_h.at(i - 1) ) * ( humidity - iso_h.at(i - 1) ); + } + } + } else if ( this->Isotherm == Ricken ) { + return wf - log(1. - humidity) / dd; + } else if ( this->Isotherm == Kuenzel ) { + return wf * ( b - 1. ) * humidity / ( b - humidity ); + } else if ( this->Isotherm == Hansen ) { + return rhodry * uh * pow( ( 1. - log(humidity) / A ), ( -1. / nn ) ); + } else if ( this->Isotherm == BSB ) { + return rhodry * c * k * Vm * humidity / ( ( 1. - k * humidity ) * ( c - 1. ) * k * humidity ); + } else if ( this->Isotherm == bilinear ) { + if ( humidity <= ( hx - dx ) ) { + return max(moistureCapacity * humidity + iso_offset, 0.); + } else if ( humidity >= ( hx + dx ) ) { + return hx * moistureCapacity + ( humidity - hx ) * capa2 + iso_offset; + } else { + return ( hx - dx ) * moistureCapacity + moistureCapacity * ( humidity - hx + dx ) + c2 * pow(humidity - hx + dx, 2) + c1 * pow(humidity - hx + dx, 3) + iso_offset; + } + } else if ( this->Isotherm == vanGenuchten ) { + return wf * pow( ( pow( ( -vG_b * log(humidity) ), ( 1. / ( 1. - vG_m ) ) ) + 1. ), -vG_m); + } else { + OOFEM_ERROR("unknown isotherm type"); + } + + return 0.; +} + +double +NlIsoMoistureMaterial::givePermeability(GaussPoint *gp, TimeStep *tStep) const +{ + double humidity = this->giveHumidity(gp, VM_Total); + + if ( this->Permeability == multilin ) { + double tol = 1.e-10; + for ( int i = 1; i <= perm_h.giveSize(); i++ ) { + if ( ( humidity - perm_h.at(i) ) < tol ) { + return perm_ch.at(i - 1) + ( perm_ch.at(i) - perm_ch.at(i - 1) ) * ( humidity - perm_h.at(i - 1) ) / ( perm_h.at(i) - perm_h.at(i - 1) ); + } + } + } else if ( this->Permeability == Bazant ) { + return C1 * ( alpha0 + ( 1. - alpha0 ) / ( 1. + pow( ( 1. - humidity ) / ( 1. - hC ), n ) ) ); + } else if ( this->Permeability == Xi ) { + double power = pow( 10., gammah * ( humidity - 1. ) ); + return alphah + betah * ( 1. - pow(2., -power) ); + } else if ( this->Permeability == KunzelPerm ) { + // [kg/m^3] + double dw_dh = this->giveMoistureCapacity(gp, tStep); + // capillary transport coefficient [m^2/s] + double Dw = this->computeCapTranspCoeff(humidity); + + double temper_factor = this->computeTemperatureEffectOnViscosity(gp, tStep); + double p_sat = this->computeSaturationWaterVaporPressure(gp, tStep); + double deltap = this->computeVaporDiffusionCoeff(gp, tStep); + + return temper_factor * Dw * dw_dh + deltap * p_sat; + } else { + OOFEM_ERROR("unknown permeability type"); + } + + return 0.; +} + + +double +NlIsoMoistureMaterial::computeCapTranspCoeff(double humidity) const +{ + double Dw = 0.; + + if ( this->CapillaryTransport == Multilin_h ) { + double tol = 1.e-10; + for ( int i = 1; i <= capPerm_h.giveSize(); i++ ) { + if ( ( humidity - capPerm_h.at(i) ) < tol ) { + Dw = capPerm_Dwh.at(i - 1) + ( capPerm_Dwh.at(i) - capPerm_Dwh.at(i - 1) ) * ( humidity - capPerm_h.at(i - 1) ) / ( capPerm_h.at(i) - capPerm_h.at(i - 1) ); + break; + } + } + } else if ( this->CapillaryTransport == Multilin_wV ) { + double wV = this->giveMoistureContent(humidity) / rhoH2O; + double tol = 1.e-10; + for ( int i = 1; i <= capPerm_wV.giveSize(); i++ ) { + if ( ( wV - capPerm_wV.at(i) ) < tol ) { + Dw = capPerm_DwwV.at(i - 1) + ( capPerm_DwwV.at(i) - capPerm_DwwV.at(i - 1) ) * ( wV - capPerm_wV.at(i - 1) ) / ( capPerm_wV.at(i) - capPerm_wV.at(i - 1) ); + break; + } + } + } else if ( this->CapillaryTransport == KunzelCT ) { + double w = this->giveMoistureContent(humidity); + Dw = 3.8 * ( Abs / wf ) * ( Abs / wf ) * pow(this->capillary_transport_coef, w / wf - 1.); + } else { + OOFEM_ERROR("unknown capillary transport type"); + } + + + + + return Dw; +} + + +double +NlIsoMoistureMaterial::computeVaporDiffusionCoeff(GaussPoint *gp, TimeStep *tStep) const +{ + double temperature = this->giveTemperature(gp, tStep); + + double delta = this->timeScale * 2.0 * 1.e-7 * pow(temperature, 0.81) / this->PL; + return delta / this->mu; +} + + +double +NlIsoMoistureMaterial::computeSaturationWaterVaporPressure(GaussPoint *gp, TimeStep *tStep) const +{ + double temperature = this->giveTemperature(gp, tStep); + + temperature -= 273.15; + double T0, a; + + if ( temperature < 0. ) { + a = 22.44; + T0 = 272.44; + } else { + a = 17.08; + T0 = 234.18; + } + + return 611. * exp( a * temperature / ( T0 + temperature ) ); +} + + +double +NlIsoMoistureMaterial::computeTemperatureEffectOnViscosity(GaussPoint *gp, TimeStep *tStep) const +{ + double temperature = this->giveTemperature(gp, tStep); + + // ratio of water viscosity at given temperature and reference temperature, taken as 20 C + // viscosity is comptued according to Gawin + // eta(T) = 0.6612 * (T-229)**-1.532 + return pow(64. / ( temperature - 229. ), -1.532); +} + + +double +NlIsoMoistureMaterial::giveTemperature(GaussPoint *gp, TimeStep *tStep) const +{ + double temperature; + + if ( this->T_TF != 0 ) { + temperature = domain->giveFunction(this->T_TF)->evaluateAtTime(tStep->giveTargetTime() ); + } else { + temperature = this->T; + } + + return temperature; +} + + + + + +double +NlIsoMoistureMaterial::giveHumidity(GaussPoint *gp, ValueModeType mode) const +{ + auto tempState = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) )->giveTempField(); + if ( tempState > 1.0 || tempState < 0.0 ) { + OOFEM_ERROR("Relative humidity %.3f is out of range", tempState); + return 0.0; + } else { + return tempState; + } +} + +bool +NlIsoMoistureMaterial::hasInternalSource() const +{ + return this->wn != 0.; +} + +void +NlIsoMoistureMaterial::computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const +{ + val.resize(1); + if ( mode == VM_Total || mode == VM_TotalIntrinsic ) { + val.at(1) = -wn * ( this->alpha.eval( { { "t", tStep->giveTargetTime() } }, this->giveDomain() ) - this->alpha.eval( { { "t", tStep->giveTargetTime() - tStep->giveTimeIncrement() } }, this->giveDomain() ) ) / tStep->giveTimeIncrement(); + } else { + OOFEM_ERROR("Undefined mode %s\n", __ValueModeTypeToString(mode) ); + } +} +} // end namespace oofem diff --git a/src/tm/nlisomoisturemat.h b/src/tm/Materials/nlisomoisturemat.h similarity index 62% rename from src/tm/nlisomoisturemat.h rename to src/tm/Materials/nlisomoisturemat.h index 9a9f79d2c..ceabbc588 100644 --- a/src/tm/nlisomoisturemat.h +++ b/src/tm/Materials/nlisomoisturemat.h @@ -35,7 +35,7 @@ #ifndef nlisomoisturemat_h #define nlisomoisturemat_h -#include "isomoisturemat.h" +#include "tm/Materials/isomoisturemat.h" #include "floatarray.h" #include "scalarfunction.h" #include "function.h" @@ -50,7 +50,7 @@ #define _IFT_NlIsoMoistureMaterial_capa "capa" #define _IFT_NlIsoMoistureMaterial_hx "hx" #define _IFT_NlIsoMoistureMaterial_dx "dx" -#define _IFT_NlIsoMoistureMaterial_iso_offset "isoOffset" +#define _IFT_NlIsoMoistureMaterial_iso_offset "isooffset" #define _IFT_NlIsoMoistureMaterial_iso_h "iso_h" #define _IFT_NlIsoMoistureMaterial_iso_wh "iso_w(h)" #define _IFT_NlIsoMoistureMaterial_dd "dd" @@ -79,11 +79,14 @@ #define _IFT_NlIsoMoistureMaterial_abs "abs" #define _IFT_NlIsoMoistureMaterial_pl "pl" #define _IFT_NlIsoMoistureMaterial_mu "mu" -#define _IFT_NlIsoMoistureMaterial_t "t" #define _IFT_NlIsoMoistureMaterial_timescale "timescale" #define _IFT_NlIsoMoistureMaterial_wn "wn" #define _IFT_NlIsoMoistureMaterial_alpha "alpha" - +#define _IFT_NlIsoMoistureMaterial_capil_coef "capil_coef" +#define _IFT_NlIsoMoistureMaterial_t "t" +#define _IFT_NlIsoMoistureMaterial_ttf "ttf" +#define _IFT_NlIsoMoistureMaterial_vg_b "vg_b" +#define _IFT_NlIsoMoistureMaterial_vg_m "vg_m" //@} namespace oofem { @@ -93,41 +96,43 @@ namespace oofem { class NlIsoMoistureMaterial : public IsotropicMoistureTransferMaterial { protected: - enum isothermType { linear, multilinear, Ricken, Kuenzel, Hansen, BSB, bilinear } Isotherm; + enum isothermType { linear, multilinear, Ricken, Kuenzel, Hansen, BSB, bilinear, vanGenuchten } Isotherm; /// density of the dry solid phase - double rhodry; + double rhodry = 0.; /// values of the linear isotherm - double moistureCapacity; + double moistureCapacity = 0.; /// values of the multilinear isotherm FloatArray iso_h; FloatArray iso_wh; /// parameters of the Ricken isotherm - double dd; + double dd = 0.; /// parameters of the Kuenzel isotherm - double wf, b; + double wf = 0., b = 0.; /// parameters of the isotherm proposed by P. Freiesleben Hansen (Coupled moisture/heat transport in cross sections of structures, Beton og Konstruktionsinstituttet, 1985) - double uh, A, nn; + double uh = 0., A = 0., nn = 0.; /// parameters of the BSB isotherm - double c, k, Vm; + double c = 0., k = 0., Vm = 0.; /// values of the bilinear isotherm - double hx, dx; - double iso_offset; - double c1, c2, capa2; - + double hx = 0., dx = 0.; + double iso_offset = 0.; + double c1 = 0., c2 = 0., capa2 = 0.; + + /// parameters of vanGenuchten isotherm + double vG_b = 0., vG_m = 0.; + /// Nonevaporable water content per m3 of concrete at complete hydration - double wn; - + double wn = 0.; + /// Function of degree of hydration ScalarFunction alpha; - enum permeabilityType { multilin, Bazant, Xi, KunzelPerm } Permeability; @@ -136,42 +141,68 @@ class NlIsoMoistureMaterial : public IsotropicMoistureTransferMaterial FloatArray perm_ch; /// "permeability" according to Bazant - double C1, n, alpha0, hC; + double C1 = 0., n = 0., alpha0 = 0., hC = 0.; /// permeability parameters according to Xi, Bazant & Jennings - double alphah, betah, gammah; + double alphah = 0., betah = 0., gammah = 0.; + + enum capillaryTransportType { Multilin_h, Multilin_wV, KunzelCT } CapillaryTransport; + /// water absorption coefficient [kg m^-2 s^-0.5] + double Abs = 0.; + + /// water vapor diffusion resistance [-] + double mu = 0.; + + /// ambient atmospheric pressure [Pa] + double PL = 101325.; + + /// = 1 for analysis in seconds, = 86400 for analysis in days, etc. + double timeScale = 1.; + + /// parameter in liquid conduction + double capillary_transport_coef = 1000.; + + /// constant temperature [K] + double T = 0.; + /// explicitly prescribed evolution of temperature by a time function (e.g. piecewise-linear dfined externally) in [K] + int T_TF = 0; - /// permeability parameters according to Kunzel - double deltap, p_sat; // permation - enum capillaryTransportType {Multilin_h, Multilin_wV, KunzelCT} CapillaryTransport; - double Abs; ///< water absorption coefficient [kg m^-2 s^-0.5] /// values of the multilinear capillary transport function FloatArray capPerm_h; FloatArray capPerm_Dwh; FloatArray capPerm_wV; FloatArray capPerm_DwwV; - double rhoH2O; + double rhoH2O = 0.; public: - NlIsoMoistureMaterial(int n, Domain * d) : IsotropicMoistureTransferMaterial(n, d) { } - virtual ~NlIsoMoistureMaterial() { } + NlIsoMoistureMaterial(int n, Domain *d) : IsotropicMoistureTransferMaterial(n, d) { } + + void initializeFrom(InputRecord &ir) override; /// evaluates slope of the sorption isotherm - virtual double giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep); - virtual double giveMoistureContent(double humidity); - virtual double givePermeability(GaussPoint *gp, TimeStep *tStep); - virtual double computeCapTranspCoeff(double humidity); + double giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep) const override; + double giveMoistureContent(double humidity) const override; + double givePermeability(GaussPoint *gp, TimeStep *tStep) const override; + double computeCapTranspCoeff(double humidity) const; + + /// compute vapor diffusion coefficient in air [kg m^-1 s^-1 Pa^-1] + double computeVaporDiffusionCoeff(GaussPoint *gp, TimeStep *tStep) const; + /// compute saturation water vapor pressure + double computeSaturationWaterVaporPressure(GaussPoint *gp, TimeStep *tStep) const; + /// evaluate temperature effect on water viscosity - liquid water capillary conduction + double computeTemperatureEffectOnViscosity(GaussPoint *gp, TimeStep *tStep) const; + /// returns temperature in [K] + double giveTemperature(GaussPoint *gp, TimeStep *tStep) const; + + const char *giveInputRecordName() const override { return _IFT_NlIsoMoistureMaterial_Name; } + const char *giveClassName() const override { return "NlIsoMoistureMaterial"; } - virtual const char *giveInputRecordName() const { return _IFT_NlIsoMoistureMaterial_Name; } - virtual const char *giveClassName() const { return "NlIsoMoistureMaterial"; } + double giveHumidity(GaussPoint *gp, ValueModeType mode) const override; - virtual double giveHumidity(GaussPoint *gp, ValueModeType mode); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual int hasInternalSource(); - virtual void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode); - + bool hasInternalSource() const override; + void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const override; }; } // end namespace oofem #endif // nlisomoisturemat_h diff --git a/src/tm/nonlinearmassmat.C b/src/tm/Materials/nonlinearmassmat.C similarity index 57% rename from src/tm/nonlinearmassmat.C rename to src/tm/Materials/nonlinearmassmat.C index 2d3a2a3c8..be1dfc4cf 100644 --- a/src/tm/nonlinearmassmat.C +++ b/src/tm/Materials/nonlinearmassmat.C @@ -32,90 +32,63 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "nonlinearmassmat.h" +#include "tm/Materials/nonlinearmassmat.h" #include "floatmatrix.h" #include "gausspoint.h" #include "mathfem.h" #include "classfactory.h" +#include namespace oofem { REGISTER_Material(NonlinearMassTransferMaterial); -IRResultType -NonlinearMassTransferMaterial :: initializeFrom(InputRecord *ir) +void +NonlinearMassTransferMaterial :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + Material :: initializeFrom(ir); IR_GIVE_FIELD(ir, C, _IFT_NonlinearMassTransferMaterial_c); IR_GIVE_FIELD(ir, alpha, _IFT_NonlinearMassTransferMaterial_alpha); - - return Material :: initializeFrom(ir); -} - -void -NonlinearMassTransferMaterial :: giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -{ - MaterialMode mMode = gp->giveMaterialMode(); - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - const FloatArray &eps = status->giveTempGradient(); - double gradPNorm; - FloatMatrix t1, t2; - - gradPNorm = eps.computeNorm(); - - t1.beDyadicProductOf(eps, eps); - if ( gradPNorm != 0.0 ) { - t1.times( C * alpha * pow(gradPNorm, alpha - 2) ); - } - - switch ( mMode ) { - case _1dHeat: - t2.resize(1, 1); - break; - case _2dHeat: - t2.resize(2, 2); - break; - case _3dHeat: - t2.resize(3, 3); - break; - default: - OOFEM_ERROR("unknown mode (%s)", __MaterialModeToString(mMode)); - } - t2.beUnitMatrix(); - - answer.clear(); - answer.add(t1); - answer.add(1 + C * pow(gradPNorm, alpha), t2); } double NonlinearMassTransferMaterial :: giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, - TimeStep *tStep) + TimeStep *tStep) const { return 0.; } -void -NonlinearMassTransferMaterial :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) +FloatArrayF<3> +NonlinearMassTransferMaterial :: computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const { - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - - double gradPNorm = grad.computeNorm(); - answer.beScaled(-( 1. + C * pow(gradPNorm, alpha) ), grad); - + auto ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); ms->setTempGradient(grad); ms->setTempField(field); + + double gradPNorm = norm(grad); + auto answer = -( 1. + C * pow(gradPNorm, alpha) ) * grad; ms->setTempFlux(answer); + return answer; +} + + +FloatMatrixF<3,3> +NonlinearMassTransferMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); + const auto &eps = ms->giveTempGradient(); + double gradPNorm = norm(eps); + + auto scale = gradPNorm != 0. ? C * alpha * pow(gradPNorm, alpha - 2) : 1.; + auto t1 = scale * dyad(eps, eps); + return t1 + (1 + C * pow(gradPNorm, alpha)) * eye<3>(); } int NonlinearMassTransferMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); + auto ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); switch ( type ) { case IST_Velocity: diff --git a/src/tm/nonlinearmassmat.h b/src/tm/Materials/nonlinearmassmat.h similarity index 69% rename from src/tm/nonlinearmassmat.h rename to src/tm/Materials/nonlinearmassmat.h index 3d11b50ed..4f52c40c0 100644 --- a/src/tm/nonlinearmassmat.h +++ b/src/tm/Materials/nonlinearmassmat.h @@ -35,7 +35,7 @@ #ifndef nonlinearheatmat_h #define nonlinearheatmat_h -#include "transportmaterial.h" +#include "tm/Materials/transportmaterial.h" ///@name Input fields for NonlinearMassTransferMaterial //@{ @@ -60,32 +60,26 @@ class NonlinearMassTransferMaterial : public TransportMaterial { protected: /// Indicates the level of nonlinearity in the model - double C; + double C = 0.; /// Indicates the level of nonlinearity in the model - double alpha; + double alpha = 0.; public: - NonlinearMassTransferMaterial(int n, Domain * d) : TransportMaterial(n, d) { } - virtual ~NonlinearMassTransferMaterial() { } - - virtual void giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - virtual double giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); + void initializeFrom(InputRecord &ir) override; - virtual void giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep); + double giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + FloatArrayF<3> computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual const char *giveInputRecordName() const { return _IFT_NonlinearMassTransferMaterial_Name; } - virtual const char *giveClassName() const { return "NonlinearMassTransferMaterial"; } + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual IRResultType initializeFrom(InputRecord *ir); + const char *giveInputRecordName() const override { return _IFT_NonlinearMassTransferMaterial_Name; } + const char *giveClassName() const override { return "NonlinearMassTransferMaterial"; } }; } // end namespace oofem #endif // nonlinearheatmat_h diff --git a/src/tm/rvestokesflow.C b/src/tm/Materials/rvestokesflow.C similarity index 62% rename from src/tm/rvestokesflow.C rename to src/tm/Materials/rvestokesflow.C index 52c303652..198251d2f 100644 --- a/src/tm/rvestokesflow.C +++ b/src/tm/Materials/rvestokesflow.C @@ -32,10 +32,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "rvestokesflow.h" +#include "tm/Materials/rvestokesflow.h" #include "util.h" #include "oofemtxtdatareader.h" -#include "../fm/stokesflowvelocityhomogenization.h" +#include "fm/stokesflowvelocityhomogenization.h" #include "engngm.h" #include "contextioerr.h" #include "gausspoint.h" @@ -46,31 +46,32 @@ #include #include +#ifdef __FM_MODULE + namespace oofem { REGISTER_Material(RVEStokesFlow); int RVEStokesFlow :: n = 1; -RVEStokesFlowMaterialStatus :: RVEStokesFlowMaterialStatus(int n, Domain *d, GaussPoint *g, const std :: string &inputfile) : - TransportMaterialStatus(n, d, g), oldTangent(true) +RVEStokesFlowMaterialStatus :: RVEStokesFlowMaterialStatus(int n, int rank, GaussPoint *g, const std :: string &inputfile) : + TransportMaterialStatus(g), oldTangent(true) { OOFEM_LOG_INFO( "************************** Instanciating microproblem from file %s\n", inputfile.c_str() ); OOFEMTXTDataReader dr( inputfile.c_str() ); - EngngModel *e = InstanciateProblem(& dr, _processor, 0); + auto e = InstanciateProblem(dr, _processor, 0); dr.finish(); - if ( dynamic_cast< StokesFlowVelocityHomogenization* >(e) ) { - this->rve.reset( dynamic_cast< StokesFlowVelocityHomogenization* >(e) ); + if ( dynamic_cast< StokesFlowVelocityHomogenization* >(e.get()) ) { + this->rve.reset( dynamic_cast< StokesFlowVelocityHomogenization* >(e.release()) ); } else { - delete e; OOFEM_ERROR("Unexpected RVE engineering model"); } std :: ostringstream name; name << this->rve->giveOutputBaseFileName() << "-gp" << n; - if ( this->domain->giveEngngModel()->isParallel() && this->domain->giveEngngModel()->giveNumberOfProcesses() > 1 ) { - name << "." << this->domain->giveEngngModel()->giveRank(); + if ( rank >= 0 ) { + name << "." << rank; } this->rve->letOutputBaseFileNameBe( name.str() ); @@ -83,10 +84,6 @@ RVEStokesFlowMaterialStatus :: RVEStokesFlowMaterialStatus(int n, Domain *d, Gau OOFEM_LOG_INFO("************************** Microproblem at %p instanciated \n", rve.get()); } -RVEStokesFlowMaterialStatus :: ~RVEStokesFlowMaterialStatus() -{ -} - void RVEStokesFlowMaterialStatus :: setTimeStep(TimeStep *tStep) { @@ -113,76 +110,53 @@ RVEStokesFlowMaterialStatus :: updateYourself(TimeStep *tStep) } -contextIOResultType -RVEStokesFlowMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) +void +RVEStokesFlowMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = TransportMaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + TransportMaterialStatus :: saveContext(stream, mode); } -contextIOResultType -RVEStokesFlowMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) +void +RVEStokesFlowMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) { - contextIOResultType iores; - - if ( ( iores = TransportMaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; + TransportMaterialStatus :: restoreContext(stream, mode); } + RVEStokesFlow :: RVEStokesFlow(int n, Domain *d) : TransportMaterial(n, d) { } -IRResultType RVEStokesFlow :: initializeFrom(InputRecord *ir) -{ - IRResultType result; +void RVEStokesFlow :: initializeFrom(InputRecord &ir) +{ IR_GIVE_FIELD(ir, this->rveFilename, _IFT_RVEStokesFlow_fileName); - - SupressRVEoutput = 0; - - IR_GIVE_OPTIONAL_FIELD(ir, SupressRVEoutput, _IFT_RVEStokesFlow_supressoutput); - - return IRRT_OK; } int RVEStokesFlow :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) { - RVEStokesFlowMaterialStatus *thisMaterialStatus; - thisMaterialStatus = static_cast< RVEStokesFlowMaterialStatus * >( this->giveStatus(gp) ); - FloatMatrix temp; + auto status = static_cast< RVEStokesFlowMaterialStatus * >( this->giveStatus(gp) ); answer.clear(); switch ( type ) { case IST_Velocity: - answer.copySubVector(thisMaterialStatus->giveFlux(), 1); + answer = status->giveFlux(); return 1; case IST_PressureGradient: - answer.copySubVector(thisMaterialStatus->giveGradient(), 1); + answer = status->giveGradient(); return 1; case IST_TangentNorm: - temp = thisMaterialStatus->giveTangentMatrix(); answer.resize(1); - answer.at(1) = temp.computeFrobeniusNorm(); + answer.at(1) = frobeniusNorm(status->giveTangentMatrix()); return 1; case IST_Tangent: - temp = thisMaterialStatus->giveTangentMatrix(); - answer.resize(4); - answer.at(1) = temp.at(1, 1); - answer.at(2) = temp.at(1, 2); - answer.at(3) = temp.at(2, 1); - answer.at(4) = temp.at(2, 2); + { + const auto &temp = status->giveTangentMatrix(); + answer = {temp(0,0), temp(0,1), temp(0,2), temp(1,0), temp(1,1), temp(1,2), temp(2,0), temp(2,1), temp(2,2)}; return 1; + } default: return TransportMaterial :: giveIPValue(answer, gp, type, tStep); } @@ -190,88 +164,69 @@ RVEStokesFlow :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateTy return 0; } -void -RVEStokesFlow :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) -{ - - this->suppressStdout(); +FloatArrayF<3> +RVEStokesFlow :: computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const +{ OOFEM_LOG_DEBUG("\n****** Enter giveFluxVector ********************** Element number %u, Gauss point %u\n", gp->giveElement()->giveGlobalNumber(), gp->giveNumber()); - RVEStokesFlowMaterialStatus *status = static_cast< RVEStokesFlowMaterialStatus * >( this->giveStatus(gp) ); - StokesFlowVelocityHomogenization *rveE = status->giveRVE(); + auto status = static_cast< RVEStokesFlowMaterialStatus * >( this->giveStatus(gp) ); + auto rveE = status->giveRVE(); - OOFEM_LOG_DEBUG( "Solve RVE problem for macroscale pressure gradient gradP=[%f, %f, %f]\n ", - grad.at(1), grad.at(2), grad.giveSize() == 3 ? grad.at(3) : 0. ); + OOFEM_LOG_DEBUG( "Solve RVE problem for macroscale pressure gradient gradP=[%f, %f, %f]\n ", grad[0], grad[1], grad[2] ); // Compute seepage velocity rveE->applyPressureGradient(grad); status->setTimeStep(tStep); rveE->solveYourselfAt(rveE->giveCurrentStep()); + FloatArray answer; rveE->computeSeepage(answer, tStep); + answer.resizeWithValues(3); OOFEM_LOG_DEBUG( "Pressure gradient gradP=[%f %f] yields velocity vector [%f %f]\n", grad.at(1), grad.at(2), answer.at(1), answer.at(2) ); - status->setTempGradient(grad); status->setTempFlux(answer); status->oldTangent = true; OOFEM_LOG_DEBUG("****** Exit giveFluxVector **************************************** \n"); - - this->enableStdout(); + return answer; } -void -RVEStokesFlow :: giveCharacteristicMatrix(FloatMatrix &answer, MatResponseMode, GaussPoint *gp, TimeStep *tStep) +FloatMatrixF<3,3> +RVEStokesFlow :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const { - this->suppressStdout(); - OOFEM_LOG_DEBUG("\n****** Enter giveDeviatoricStiffnessMatrix **********************\n"); - RVEStokesFlowMaterialStatus *status = static_cast< RVEStokesFlowMaterialStatus * >( this->giveStatus(gp) ); + auto status = static_cast< RVEStokesFlowMaterialStatus * >( this->giveStatus(gp) ); if ( status->oldTangent ) { // Compute tangent + FloatMatrix answer; status->giveRVE()->computeTangent(answer, tStep); + answer.resizeWithData(3, 3); status->letTempTangentMatrixBe(answer); status->oldTangent = false; + return answer; } else { - answer = status->giveTempTangentMatrix(); + return status->giveTempTangentMatrix(); } OOFEM_LOG_DEBUG("****** Exit giveDeviatoricStiffnessMatrix **************************************** \n"); - - this->enableStdout(); } + MaterialStatus * RVEStokesFlow :: CreateStatus(GaussPoint *gp) const { - return new RVEStokesFlowMaterialStatus(n++, this->giveDomain(), gp, this->rveFilename); -} - -void -RVEStokesFlow :: suppressStdout() -{ - // if (SupressRVEoutput) { - // fgetpos(stdout, &stdoutPos); - // stdoutFID=dup(fileno(stdout)); - // freopen(this->rveLogFilename.c_str(), "a", stdout); - // } -} - -void RVEStokesFlow :: enableStdout() -{ - // if (SupressRVEoutput) { - // fflush(stdout); - // dup2(stdoutFID, fileno(stdout)); - // close (stdoutFID); - // clearerr(stdout); - // fsetpos(stdout, &stdoutPos); /* for C9X */ - // } + int rank = -1; + if ( this->domain->giveEngngModel()->isParallel() && this->domain->giveEngngModel()->giveNumberOfProcesses() > 1 ) { + rank = this->domain->giveEngngModel()->giveRank(); + } + return new RVEStokesFlowMaterialStatus(n++, rank, gp, this->rveFilename); } } +#endif // ifdef __FM_MODULE diff --git a/src/tm/rvestokesflow.h b/src/tm/Materials/rvestokesflow.h similarity index 60% rename from src/tm/rvestokesflow.h rename to src/tm/Materials/rvestokesflow.h index a989efb47..1d8c5cd0b 100644 --- a/src/tm/rvestokesflow.h +++ b/src/tm/Materials/rvestokesflow.h @@ -35,8 +35,10 @@ #ifndef rvestokesflow_h #define rvestokesflow_h -#include "floatarray.h" -#include "floatmatrix.h" +#ifdef __FM_MODULE + +#include "floatarrayf.h" +#include "floatmatrixf.h" #include "transportmaterial.h" #include "stokesflowvelocityhomogenization.h" @@ -45,7 +47,6 @@ #define _IFT_RVEStokesFlow_Name "rvestokesflow" #define _IFT_RVEStokesFlow_fileName "file" #define _IFT_RVEStokesFlow_bctype "bctype" -#define _IFT_RVEStokesFlow_supressoutput "supressoutput" namespace oofem { /** @@ -57,32 +58,30 @@ namespace oofem { class RVEStokesFlowMaterialStatus : public TransportMaterialStatus { protected: - FloatMatrix temp_TangentMatrix, tangentMatrix; + FloatMatrixF<3,3> temp_TangentMatrix, tangentMatrix; std :: unique_ptr< StokesFlowVelocityHomogenization > rve; public: - RVEStokesFlowMaterialStatus(int n, Domain * d, GaussPoint * g, const std :: string &inputfile); - - virtual ~RVEStokesFlowMaterialStatus(); + RVEStokesFlowMaterialStatus(int n, int rank, GaussPoint * g, const std :: string &inputfile); void setTimeStep(TimeStep *tStep); - virtual void initTempStatus(); + void initTempStatus() override; - virtual void updateYourself(TimeStep *tStep); + void updateYourself(TimeStep *tStep) override; - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; - const FloatMatrix &giveTangentMatrix() { return tangentMatrix; } - const FloatMatrix &giveTempTangentMatrix() { return temp_TangentMatrix; } - void letTempTangentMatrixBe(const FloatMatrix &K) { temp_TangentMatrix = K; } + const FloatMatrixF<3,3> &giveTangentMatrix() const { return tangentMatrix; } + const FloatMatrixF<3,3> &giveTempTangentMatrix() const { return temp_TangentMatrix; } + void letTempTangentMatrixBe(const FloatMatrixF<3,3> &K) { temp_TangentMatrix = K; } StokesFlowVelocityHomogenization *giveRVE() { return rve.get(); } bool oldTangent; - virtual const char *giveClassName() const { return "RVEStokesFlowMaterialStatus"; } + const char *giveClassName() const override { return "RVEStokesFlowMaterialStatus"; } }; @@ -103,29 +102,24 @@ class RVEStokesFlow : public TransportMaterial std :: string rveFilename; std :: string rveLogFilename; - int SupressRVEoutput; - - void suppressStdout(); - void enableStdout(); - public: RVEStokesFlow(int n, Domain * d); - virtual ~RVEStokesFlow() { } + void initializeFrom(InputRecord &ir) override; - virtual IRResultType initializeFrom(InputRecord *ir); + FloatArrayF<3> computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; - virtual void giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep); - virtual void giveCharacteristicMatrix(FloatMatrix &answer, MatResponseMode, GaussPoint *gp, TimeStep *tStep); - virtual double giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) { return 0.0; } + double giveCharacteristicValue(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override { return 0.0; } - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const; + MaterialStatus *CreateStatus(GaussPoint *gp) const override; - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; - virtual const char *giveClassName() const { return "RVEStokesFlow"; } - virtual const char *giveInputRecordName() const { return _IFT_RVEStokesFlow_Name; } + const char *giveClassName() const override { return "RVEStokesFlow"; } + const char *giveInputRecordName() const override { return _IFT_RVEStokesFlow_Name; } }; } +#endif // ifdef __FM_MODULE #endif // rvestokesflow_h diff --git a/src/tm/Materials/transportmaterial.C b/src/tm/Materials/transportmaterial.C new file mode 100644 index 000000000..52fd53dae --- /dev/null +++ b/src/tm/Materials/transportmaterial.C @@ -0,0 +1,426 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "tm/Materials/transportmaterial.h" +#include "gausspoint.h" +#include "contextioerr.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" +#include "datastream.h" + +namespace oofem { + +TransportMaterialStatus :: TransportMaterialStatus(GaussPoint *g) : + MaterialStatus(g) +{ } + +void TransportMaterialStatus :: printOutputAt(FILE *File, TimeStep *tStep) const +{ + MaterialStatus :: printOutputAt(File, tStep); + + fprintf(File, " state %.4e", field); + + fprintf(File, " flow"); + for ( auto &flow : flux ) { + fprintf( File, " %.4e", flow ); + } + + fprintf(File, "\n"); +} + + +void +TransportMaterialStatus :: updateYourself(TimeStep *tStep) +{ + MaterialStatus :: updateYourself(tStep); + gradient = temp_gradient; + field = temp_field; + flux = temp_flux; +} + + +void +TransportMaterialStatus :: initTempStatus() +{ + MaterialStatus :: initTempStatus(); + temp_gradient = gradient; + temp_field = field; + temp_flux = flux; +} + + +void +TransportMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) +{ + MaterialStatus :: saveContext(stream, mode); + + contextIOResultType iores; + if ( ( iores = gradient.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( stream.read(field) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( ( iores = flux.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } +} + + +void +TransportMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) +{ + MaterialStatus :: restoreContext(stream, mode); + + contextIOResultType iores; + if ( ( iores = gradient.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + if ( !stream.read(field) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( ( iores = flux.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } +} + + + +HeMoTransportMaterialStatus :: HeMoTransportMaterialStatus(GaussPoint *g) : + MaterialStatus(g) +{ } + + +void +HeMoTransportMaterialStatus :: printOutputAt(FILE *File, TimeStep *tStep) const +{ + MaterialStatus :: printOutputAt(File, tStep); + + fprintf(File, " temperature %.4e", temperature); + + fprintf(File, " t_flux"); + for ( auto &flow : t_flux ) { + fprintf( File, " %.4e", flow ); + } + + fprintf(File, " humidity %.4e", humidity); + + fprintf(File, " h_flux"); + for ( auto &flow : h_flux ) { + fprintf( File, " %.4e", flow ); + } + + fprintf(File, "\n"); +} + + +void +HeMoTransportMaterialStatus :: updateYourself(TimeStep *tStep) +{ + MaterialStatus :: updateYourself(tStep); + + t_gradient = temp_t_gradient; + temperature = temp_temperature; + t_flux = temp_t_flux; + + h_gradient = temp_h_gradient; + humidity = temp_humidity; + h_flux = temp_h_flux; +} + + +void +HeMoTransportMaterialStatus :: initTempStatus() +{ + MaterialStatus :: initTempStatus(); + + temp_t_gradient = t_gradient; + temp_temperature = temperature; + temp_t_flux = t_flux; + + temp_h_gradient = h_gradient; + temp_humidity = humidity; + temp_h_flux = h_flux; +} + + +void +HeMoTransportMaterialStatus :: saveContext(DataStream &stream, ContextMode mode) +{ + MaterialStatus :: saveContext(stream, mode); + + contextIOResultType iores; + if ( ( iores = t_gradient.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( stream.read(temperature) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( ( iores = t_flux.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = h_gradient.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( stream.read(humidity) ) { + THROW_CIOERR(CIO_IOERR); + } + + if ( ( iores = h_flux.storeYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } +} + + +void +HeMoTransportMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode) +{ + MaterialStatus :: restoreContext(stream, mode); + + contextIOResultType iores; + if ( ( iores = t_gradient.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + if ( !stream.read(temperature) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( ( iores = t_flux.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + + if ( ( iores = h_gradient.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } + if ( !stream.read(humidity) ) { + THROW_CIOERR(CIO_IOERR); + } + if ( ( iores = h_flux.restoreYourself(stream) ) != CIO_OK ) { + THROW_CIOERR(iores); + } +} + + + +void +TransportMaterial :: updateInternalState(const FloatArray &stateVec, GaussPoint *gp, TimeStep *) +{ + if ( stateVec.giveSize() == 1 ) { + auto ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); + if ( ms ) { + ms->setTempField(stateVec[0]); + } + } else if ( stateVec.giveSize() == 2 ) { + auto ms = static_cast< HeMoTransportMaterialStatus * >( this->giveStatus(gp) ); + if ( ms ) { + ms->setTempTemperature(stateVec[0]); + ms->setTempHumidity(stateVec[1]); + } + } +} + + +void +TransportMaterial :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) const +{ + if ( field.giveSize() == 1 ) { + if ( grad.giveSize() == 3 ) { + answer = computeFlux3D(grad, field[0], gp, tStep); + } else if ( grad.giveSize() == 2 ) { + answer = computeFlux2D(grad, field[0], gp, tStep); + } else { + answer = computeFlux1D(grad, field[0], gp, tStep); + } + } else { + // Has to be a HeMo-model: + double t = field.at(1); + double h = field.at(2); + + int size = grad.giveSize() / 2; + FloatArrayF<3> grad_w, grad_t; + for (int i = 0; i < size; ++i) { + grad_t[i] = grad[i]; + } + for (int i = 0; i < size; ++i) { + grad_w[i] = grad[i+size]; + } + + auto grads = computeHeMoFlux3D(grad_t, grad_w, t, h, gp, tStep); + + answer.resize(size * 2); + for (int i = 0; i < size; ++i) { + answer[i] = grads.first[i]; + } + + for (int i = 0; i < size; ++i) { + answer[i+size] = grads.second[i]; + } + } +} + +void +TransportMaterial :: giveCharacteristicMatrix(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + MaterialMode mmode = gp->giveMaterialMode(); + if ( mmode == _3dHeat || mmode == _3dMTLattice ) { + answer = computeTangent3D(mode, gp, tStep); + } else if ( mmode == _2dHeat || mmode == _2dMTLattice ) { + answer = computeTangent2D(mode, gp, tStep); + } else if ( mmode == _1dHeat ) { + answer = computeTangent1D(mode, gp, tStep); + } else if ( mmode == _3dHeMo ) { + answer = computeTangent3D(mode, gp, tStep); + } else if ( mmode == _2dHeMo ) { + answer = computeTangent2D(mode, gp, tStep); + } else if ( mmode == _1dHeMo ) { + answer = computeTangent1D(mode, gp, tStep); + } +} + + +FloatArrayF<3> +TransportMaterial :: computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Method not overloaded"); +} + + +FloatArrayF<2> +TransportMaterial :: computeFlux2D(const FloatArrayF<2> &grad, double field, GaussPoint *gp, TimeStep *tStep) const +{ + auto ans = this->computeFlux3D({grad[0], grad[1], 0.}, field, gp, tStep); + return {ans[0], ans[1]}; +} + + +FloatArrayF<1> +TransportMaterial :: computeFlux1D(const FloatArrayF<1> &grad, double field, GaussPoint *gp, TimeStep *tStep) const +{ + auto ans = this->computeFlux3D({grad[0], 0., 0.}, field, gp, tStep); + return {ans[0]}; +} + + +std::pair, FloatArrayF<3>> +TransportMaterial :: computeHeMoFlux3D(const FloatArrayF<3> &grad_t, const FloatArrayF<3> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const +{ + OOFEM_ERROR("Method is only validfor heat+moisture coupled materials."); +} + +std::pair, FloatArrayF<2>> +TransportMaterial :: computeHeMoFlux2D(const FloatArrayF<2> &grad_t, const FloatArrayF<2> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const +{ + auto grads = computeHeMoFlux3D({grad_t[0], grad_t[1], 0.}, {grad_w[0], grad_w[1], 0.}, t, h, gp, tStep); + return {{grads.first[0], grads.first[1]}, {grads.second[0], grads.second[1]}}; +} + + +std::pair, FloatArrayF<1>> +TransportMaterial :: computeHeMoFlux1D(const FloatArrayF<1> &grad_t, const FloatArrayF<1> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const +{ + auto grads = computeHeMoFlux3D({grad_t[0], 0., 0.}, {grad_w[0], 0., 0.}, t, h, gp, tStep); + return {{grads.first[0]}, {grads.second[0]}}; +} + + +FloatMatrixF<2,2> +TransportMaterial :: computeTangent2D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto x = this->computeTangent3D(mode, gp, tStep); + return { + x(0, 0), x(1, 0), + x(0, 1), x(1, 1), + }; +} + + +FloatMatrixF<1,1> +TransportMaterial :: computeTangent1D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + auto x = this->computeTangent3D(mode, gp, tStep); + return {x(0, 0)}; +} + + + +int +TransportMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) +// IST_Humidity must be overriden! +{ + TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); + if ( type == IST_Temperature || type == IST_MassConcentration_1 || type == IST_Humidity ) { + answer = FloatArray{ms->giveField()}; + return 1; + } else if ( type == IST_TemperatureFlow ) { + TransportElement *transpElem = static_cast< TransportElement * >( gp->giveElement() ); + transpElem->computeFlow(answer, gp, tStep); + return 1; + } else if ( type == IST_Velocity ) { ///@todo Shouldn't be named velocity.. instead, "MassFlow" or something suitable like that. + answer = ms->giveFlux(); + answer.resizeWithValues(3); + return 1; + } else if ( type == IST_PressureGradient ) { + answer = ms->giveGradient(); + answer.resizeWithValues(3); + return 1; + } else if ( type == IST_Density ) { + answer = FloatArray{ this->give('d', gp) }; + return 1; + } else if ( type == IST_HeatCapacity ) { + answer = FloatArray{ this->give('c', gp) }; + return 1; + } else if ( type == IST_ThermalConductivityIsotropic ) { + answer = FloatArray{ this->give('k', gp) }; + return 1; + } else if ( type == IST_Maturity ) { + answer = FloatArray{ ms->giveMaturity() }; + return 1; + } else if ( type == IST_InternalSource ) { + if(hasInternalSource()){ + computeInternalSourceVector(answer, gp, tStep, VM_Total); + } else { + answer.resize(1); + answer.zero(); + } + return 1; + } + + return Material :: giveIPValue(answer, gp, type, tStep); +} +} // end namespace oofem diff --git a/src/tm/Materials/transportmaterial.h b/src/tm/Materials/transportmaterial.h new file mode 100644 index 000000000..604ba3005 --- /dev/null +++ b/src/tm/Materials/transportmaterial.h @@ -0,0 +1,286 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef transportmaterial_h +#define transportmaterial_h + +#include "material.h" +#include "floatarray.h" +#include "floatarrayf.h" +#include "floatmatrix.h" +#include "matconst.h" +#include "matstatus.h" +#include "tm/Elements/transportelement.h" + +namespace oofem { +/** + * This class implements a transport material status information. + * When needed, new materials should specialized a derived class from this base. + * It is attribute of a Gauss point. + * + * @see MaterialStatus For general description of material status, and its role. + */ +class TransportMaterialStatus : public MaterialStatus +{ +protected: + double field = 0.; ///< General field (temperature, concentration, etc.). + FloatArrayF<3> gradient; ///< General gradient. + FloatArrayF<3> flux; ///< General flux (energy flux, mass flow, etc.) + + double temp_field = 0.; ///< Temp. Primary field. + FloatArrayF<3> temp_gradient; ///< Temp. Gradient + FloatArrayF<3> temp_flux; ///< Vector containing the last computed flux. + + double maturity = 0.; ///< A scalar containing maturity (integration of temperature over time) + +public: + TransportMaterialStatus(GaussPoint * g); + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + + const char *giveClassName() const override { return "TransportMaterialStatus"; } + + /// Set gradient. + void setTempGradient(const FloatArrayF<3> &newGradient) { temp_gradient = newGradient; } + /// Set field. + void setTempField(double newField) { temp_field = newField; } + /// Set flux. + void setTempFlux(const FloatArrayF<3> &newFlux) { temp_flux = newFlux; } + + /// Return last gradient. + const FloatArrayF<3> &giveGradient() const { return gradient; } + /// Return last field. + double giveField() const { return field; } + /// Returns last flux. + const FloatArrayF<3> &giveFlux() const { return flux; } + + /// Return last gradient. + const FloatArrayF<3> &giveTempGradient() const { return temp_gradient; } + /// Return last field. + double giveTempField() const { return temp_field; } + /// Returns last flux. + const FloatArrayF<3> &giveTempFlux() const { return temp_flux; } + /// Returns maturity. + double giveMaturity() const { return maturity; } +}; + +/** + * The temperature is stored im the general "field" value, and this adds the additional humidity field. + */ +class HeMoTransportMaterialStatus : public MaterialStatus +{ +protected: + double temperature = 0.; ///< Temperature. + FloatArrayF<3> t_gradient; ///< Temperature gradient. + FloatArrayF<3> t_flux; ///< Heat flux. + + double humidity = 0.; ///< Humidity. + FloatArrayF<3> h_gradient; ///< Humidity gradient. + FloatArrayF<3> h_flux; ///< Humidity flux. + + double temp_temperature = 0.; ///< Temp temperature. + FloatArrayF<3> temp_t_gradient; ///< Temp temperature gradient. + FloatArrayF<3> temp_t_flux; ///< Temp heat flux. + + double temp_humidity = 0.; ///< Temp humidity. + FloatArrayF<3> temp_h_gradient; ///< Temp humidity gradient. + FloatArrayF<3> temp_h_flux; ///< Temp humidity flux. + +public: + HeMoTransportMaterialStatus(GaussPoint * g); + + void printOutputAt(FILE *file, TimeStep *tStep) const override; + + void initTempStatus() override; + void updateYourself(TimeStep *tStep) override; + + void saveContext(DataStream &stream, ContextMode mode) override; + void restoreContext(DataStream &stream, ContextMode mode) override; + + const char *giveClassName() const override { return "TransportMaterialStatus"; } + + /// Set gradient. + void setTempTemperatureGradient(const FloatArrayF<3> &newGradient) { temp_t_gradient = newGradient; } + /// Set field. + void setTempTemperature(double newField) { temp_temperature = newField; } + /// Set flux. + void setTempHeatFlux(const FloatArrayF<3> &newFlux) { temp_t_flux = newFlux; } + + /// Return last gradient. + const FloatArrayF<3> &giveTemperatureGradient() const { return t_gradient; } + /// Return last field. + double giveTemperature() const { return temperature; } + /// Returns last flux. + const FloatArrayF<3> &giveHeatFlux() const { return t_flux; } + + /// Return last gradient. + const FloatArrayF<3> &giveTempTemperatureGradient() const { return temp_t_gradient; } + /// Return last field. + double giveTempTemperature() const { return temp_temperature; } + /// Returns last flux. + const FloatArrayF<3> &giveTempHeatFlux() const { return temp_t_flux; } + + + /// Set gradient. + void setTempHumidityGradient(const FloatArrayF<3> &newGradient) { temp_h_gradient = newGradient; } + /// Set field. + void setTempHumidity(double newField) { temp_humidity = newField; } + /// Set flux. + void setTempHumidityFlux(const FloatArrayF<3> &newFlux) { temp_h_flux = newFlux; } + + /// Return last gradient. + const FloatArrayF<3> &giveHumidityGradient() const { return h_gradient; } + /// Return last field. + double giveHumidity() const { return humidity; } + /// Returns last flux. + const FloatArrayF<3> &giveHumidityFlux() const { return h_flux; } + + /// Return last gradient. + const FloatArrayF<3> &giveTempHumidityGradient() const { return temp_h_gradient; } + /// Return last field. + double giveTempHumidity() const { return temp_humidity; } + /// Returns last flux. + const FloatArrayF<3> &giveTempHumidityFlux() const { return temp_h_flux; } +}; + + +/** + * Abstract base class for all constitutive models for transport problems. It declares common services provided + * by all structural material models. The implementation of these services is partly left on derived classes, + * which will implement constitutive model dependent part. + * Some general purpose services are implemented on this level. For details, how to store + * material model related history variables in integration points, see base class @ref Material documentation. + */ +class TransportMaterial : public Material +{ +public: + /** + * Constructor. Creates material with given number, belonging to given domain. + * @param n Material number. + * @param d Domain to which new material will belong. + */ + TransportMaterial(int n, Domain * d) : Material(n, d) { } + + /** + * Returns the flux for the field and its gradient. + * @todo { Should the field variable just be a scalar? This might change when we rethink the coupled-fields approach. + * Now its either just [temperature], or [temperature, concentration] so to cover both cases there is a floatarray. } + * @param answer The flux. + * @param gp Gauss point. + * @param grad Gradient of the primary field, usually the main input. + * @param field The value of the field itself. + * @param tStep Active time step. + */ + virtual void giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) const; + virtual FloatArrayF<3> computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const; + FloatArrayF<2> computeFlux2D(const FloatArrayF<2> &grad, double field, GaussPoint *gp, TimeStep *tStep) const; + FloatArrayF<1> computeFlux1D(const FloatArrayF<1> &grad, double field, GaussPoint *gp, TimeStep *tStep) const; + + // HeMo: + virtual std::pair, FloatArrayF<3>> computeHeMoFlux3D(const FloatArrayF<3> &grad_t, const FloatArrayF<3> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const; + std::pair, FloatArrayF<2>> computeHeMoFlux2D(const FloatArrayF<2> &grad_t, const FloatArrayF<2> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const; + std::pair, FloatArrayF<1>> computeHeMoFlux1D(const FloatArrayF<1> &grad_t, const FloatArrayF<1> &grad_w, double t, double h, GaussPoint *gp, TimeStep *tStep) const; + + //virtual FloatMatrixF<3,3> computeHeMoTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; + //virtual FloatMatrixF<2,2> computeHeMoTangent2D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; + //virtual FloatMatrixF<1,1> computeHeMoTangent1D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; + + /** + * Computes characteristic matrix of receiver in given integration point. + * The algorithm should use temporary or equilibrium history variables stored in integration point status + * to compute and return required result. + * @param answer Contains result. + * @param mode Material response mode. + * @param gp Integration point. + * @param tStep Time step (most models are able to respond only when tStep is current time step). + */ + virtual void giveCharacteristicMatrix(FloatMatrix &answer, + MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const; + + virtual FloatMatrixF<3,3> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const = 0; + FloatMatrixF<2,2> computeTangent2D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; + FloatMatrixF<1,1> computeTangent1D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const; + + /** + * Computes the characteristic value of receiver in given integration point, respecting its history. + * The algorithm should use temporary or equilibrium history variables stored in integration point status + * to compute and return required result. + * @param mode Material response mode. + * @param gp Integration point. + * @param tStep Time step (most models are able to respond only when tStep is current time step). + */ + virtual double giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const = 0; + + /** + * Updates internal state of material according to new state vector. + * @param state New state vector. + * @param gp Integration point. + * @param tStep Solution step. + */ + virtual void updateInternalState(const FloatArray &state, GaussPoint *gp, TimeStep *tStep); + + /** + * Returns nonzero if receiver generates internal source of state variable(s), zero otherwise. + */ + virtual bool hasInternalSource() const { return false; } + /** + * Computes the internal source vector of receiver. + * @param val Contains response. + * @param gp Integration point. + * @param tStep Solution step. + * @param mode Determines response mode. + */ + virtual void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) const + { val.clear(); } + /** + * Returns positive value of humidity if implemented and enabled in derived material, -1 otherwise. + */ + virtual double giveHumidity(GaussPoint *gp, ValueModeType mode) const { return -1.0; } + + int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override; + + MaterialStatus *CreateStatus(GaussPoint *gp) const override { return new TransportMaterialStatus(gp); } +}; +} // end namespace oofem +#endif // transportmaterial_h diff --git a/src/tm/Materials/twophasemat.C b/src/tm/Materials/twophasemat.C new file mode 100644 index 000000000..002767add --- /dev/null +++ b/src/tm/Materials/twophasemat.C @@ -0,0 +1,104 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "tm/Materials/twophasemat.h" +#include "floatmatrix.h" +#include "function.h" +#include "gausspoint.h" +#include "classfactory.h" +#include "engngm.h" + +namespace oofem { +REGISTER_Material(TwoPhaseMaterial); + +void +TwoPhaseMaterial :: initializeFrom(InputRecord &ir) +{ + IR_GIVE_FIELD(ir, this->slaveMaterial, _IFT_TwoPhaseMaterial_mat); + if ( this->slaveMaterial.giveSize() != 2 ) { + throw ValueInputException(ir, _IFT_TwoPhaseMaterial_mat, "must have two values"); + } +} + + +FloatArrayF<3> +TwoPhaseMaterial :: computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const +{ + auto ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); + ms->setTempField(field); + ms->setTempGradient(grad); + + double vof = this->giveVof(gp, tStep); + auto v0 = this->giveMaterial(0)->computeFlux3D(grad, field, gp, tStep); + auto v1 = this->giveMaterial(1)->computeFlux3D(grad, field, gp, tStep); + auto answer = (1.0 - vof) * v0 + vof * v1; + ms->setTempFlux(answer); + return answer; +} + + +FloatMatrixF<3,3> +TwoPhaseMaterial :: computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const +{ + double vof = this->giveVof(gp, tStep); + auto v0 = this->giveMaterial(0)->computeTangent3D(mode, gp, tStep); + auto v1 = this->giveMaterial(1)->computeTangent3D(mode, gp, tStep); + return (1.0 - vof) * v0 + vof * v1; +} + +double +TwoPhaseMaterial :: giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const +{ + double vof = this->giveVof(gp, tStep); + auto v0 = this->giveMaterial(0)->giveCharacteristicValue(mode, gp, tStep); + auto v1 = this->giveMaterial(1)->giveCharacteristicValue(mode, gp, tStep); + return (1.0 - vof) * v0 + vof * v1; +} + +TransportMaterial * +TwoPhaseMaterial :: giveMaterial(int i) const +{ + return static_cast< TransportMaterial * >( domain->giveMaterial( slaveMaterial[i] ) ); +} + +double +TwoPhaseMaterial :: giveVof (GaussPoint* gp, TimeStep* tStep) const +{ + return static_cast< TransportElement * >(gp->giveElement()) ->computeVof(tStep); +} + + +} // end namespace oofem diff --git a/src/tm/Materials/twophasemat.h b/src/tm/Materials/twophasemat.h new file mode 100644 index 000000000..2c0bd295d --- /dev/null +++ b/src/tm/Materials/twophasemat.h @@ -0,0 +1,82 @@ +/* + * + * ##### ##### ###### ###### ### ### + * ## ## ## ## ## ## ## ### ## + * ## ## ## ## #### #### ## # ## + * ## ## ## ## ## ## ## ## + * ## ## ## ## ## ## ## ## + * ##### ##### ## ###### ## ## + * + * + * OOFEM : Object Oriented Finite Element Code + * + * Copyright (C) 1993 - 2013 Borek Patzak + * + * + * + * Czech Technical University, Faculty of Civil Engineering, + * Department of Structural Mechanics, 166 29 Prague, Czech Republic + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef twophasemat_h +#define twophasemat_h + +#include "tm/Materials/transportmaterial.h" +#include "floatarrayf.h" +#include "floatmatrixf.h" +#include "scalarfunction.h" + +///@name Input fields for IsotropicHeatTransferMaterial +//@{ +#define _IFT_TwoPhaseMaterial_Name "twophasemat" +#define _IFT_TwoPhaseMaterial_mat "mat" /// Array of individual materials (void material, reference material) +//@} + +namespace oofem { + +/** + * This class implements an isotropic linear heat material. A material + * is an attribute of a domain. It is usually also attribute of many elements. + */ +class TwoPhaseMaterial : public TransportMaterial +{ +protected: + IntArray slaveMaterial; + +public: + TwoPhaseMaterial(int n, Domain *d) : TransportMaterial(n, d) { } + + void initializeFrom(InputRecord &ir) override; + + FloatArrayF<3> computeFlux3D(const FloatArrayF<3> &grad, double field, GaussPoint *gp, TimeStep *tStep) const override; + FloatMatrixF<3,3> computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const override; + + double giveCharacteristicValue(MatResponseMode mode, + GaussPoint *gp, + TimeStep *tStep) const override; + + //virtual double giveMaturityT0() const { return maturityT0; } +protected: + TransportMaterial *giveMaterial(int i) const; + double giveVof (GaussPoint* gp, TimeStep* tStep) const; + const char *giveClassName() const override { return "TwoPhaseMaterial"; } + const char *giveInputRecordName() const override { return _IFT_TwoPhaseMaterial_mat; } + +}; + +} // end namespace oofem +#endif // twophasemat_h diff --git a/src/tm/darcyflow.C b/src/tm/darcyflow.C deleted file mode 100644 index 359e48927..000000000 --- a/src/tm/darcyflow.C +++ /dev/null @@ -1,232 +0,0 @@ -/* - * DarcyFlow.C - * - * Created on: Feb 25, 2010 - * Author: carl - */ - -#include "darcyflow.h" -#include "element.h" -#include "inputrecord.h" -#include "timestep.h" -#include "classfactory.h" -#include "sparselinsystemnm.h" -#include "mathfem.h" -#include "sparsemtrx.h" -#include "nrsolver.h" -#include "primaryfield.h" -#include "unknownnumberingscheme.h" - -#include -#include -#include - -namespace oofem { -REGISTER_EngngModel(DarcyFlow); - -DarcyFlow :: DarcyFlow(int i, EngngModel *_master) : EngngModel(i, _master) -{ - this->ndomains = 1; - this->hasAdvanced = false; -} - -DarcyFlow :: ~DarcyFlow() -{ -} - -IRResultType DarcyFlow :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - result = EngngModel :: initializeFrom(ir); - if ( result != IRRT_OK ) return result; - - int val = 0; - IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_lstype); - solverType = ( LinSystSolverType ) val; - - val = 0; - IR_GIVE_OPTIONAL_FIELD(ir, val, _IFT_EngngModel_smtype); - sparseMtrxType = ( SparseMtrxType ) val; - - // Create solution space for pressure field - PressureField.reset( new PrimaryField(this, 1, FT_Pressure, 1) ); - return IRRT_OK; -} - -void DarcyFlow :: solveYourselfAt(TimeStep *tStep) -{ - /* - * Assemble and solve system of equations as given timestep tStep. - * - */ - - OOFEM_LOG_INFO("Parallelflag: %u\n", parallelFlag); - - FloatArray *solutionVector = NULL; - int neq = this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); - - // Move solution space to current timestep - if ( !hasAdvanced ) { - PressureField->advanceSolution(tStep); - hasAdvanced = true; - } - - // Point pointer SolutionVector to current solution in VelocityPressureField - solutionVector = PressureField->giveSolutionVector(tStep); - solutionVector->resize(neq); - solutionVector->zero(); - - // Create "stiffness matrix" - if ( !this->stiffnessMatrix ) { - this->stiffnessMatrix.reset( classFactory.createSparseMtrx(sparseMtrxType) ); - this->stiffnessMatrix->buildInternalStructure( this, 1, EModelDefaultEquationNumbering() ); - } - - - // Build initial/external load (LoadVector) - this->externalForces.resize(neq); - this->externalForces.zero(); - this->assembleVectorFromElements( this->externalForces, tStep, ExternalForceAssembler(), VM_Total, - EModelDefaultEquationNumbering(), this->giveDomain(1) ); - this->updateSharedDofManagers(this->externalForces, EModelDefaultEquationNumbering(), LoadExchangeTag); - - this->incrementOfSolution.resize(neq); - this->internalForces.resize(neq); - - this->giveNumericalMethod( this->giveCurrentMetaStep() ); - double loadLevel; - int currentIterations; - this->updateComponent( tStep, InternalRhs, this->giveDomain(1) ); - this->updateComponent( tStep, NonLinearLhs, this->giveDomain(1) ); - - NM_Status status = this->nMethod->solve(*this->stiffnessMatrix, - this->externalForces, - NULL, - * solutionVector, - this->incrementOfSolution, - this->internalForces, - this->ebeNorm, - loadLevel, // Only relevant for incrementalBCLoadVector? - SparseNonLinearSystemNM :: rlm_total, // Why this naming scheme? Should be RLM_Total, and ReferenceLoadInputModeType - currentIterations, - tStep); - - if ( status & NM_NoSuccess ) { - OOFEM_ERROR("couldn't solve for time step %d\n", tStep->giveNumber() ); - } - -#define DUMPMATRICES 0 -#if DUMPMATRICES - FloatMatrix LHS_backup; - lhs->toFloatMatrix(LHS_backup); - DumpMatricesToFile(& LHS_backup, & rhs, NULL); -#endif -} - - -void DarcyFlow :: DumpMatricesToFile(FloatMatrix *LHS, FloatArray *RHS, FloatArray *SolutionVector) -{ - FILE *rhsFile = fopen("RHS.txt", "w"); - // rhs.printYourself(); - - for ( int i = 1; i <= RHS->giveSize(); i++ ) { - fprintf( rhsFile, "%0.15e\n", RHS->at(i) ); - } - fclose(rhsFile); - - FILE *lhsFile = fopen("LHS.txt", "w"); - - for ( int i = 1; i <= this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); i++ ) { - for ( int j = 1; j <= this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering() ); j++ ) { - fprintf( lhsFile, "%0.15e\t", LHS->at(i, j) ); - } - fprintf(lhsFile, "\n"); - } - - fclose(lhsFile); - - if ( SolutionVector == NULL ) { - return; - } - - FILE *SolutionFile = fopen("SolutionVector.txt", "w"); - for ( int i = 1; i <= SolutionVector->giveSize(); i++ ) { - fprintf( SolutionFile, "%0.15e\n", SolutionVector->at(i) ); - } - fclose(SolutionFile); -} - -void DarcyFlow :: updateYourself(TimeStep *tStep) -{ - EngngModel :: updateYourself(tStep); -} - -double DarcyFlow :: giveUnknownComponent(ValueModeType mode, TimeStep *tStep, Domain *d, Dof *dof) -{ - return PressureField->giveUnknownValue(dof, mode, tStep); -} - -void DarcyFlow :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) -{ - switch ( cmpn ) { - case InternalRhs: - this->internalForces.zero(); - this->assembleVector(this->internalForces, tStep, InternalForceAssembler(), VM_Total, - EModelDefaultEquationNumbering(), d, & this->ebeNorm); - this->updateSharedDofManagers(this->internalForces, EModelDefaultEquationNumbering(), InternalForcesExchangeTag); - break; - - case NonLinearLhs: - - this->stiffnessMatrix->zero(); - this->assemble( *this->stiffnessMatrix, tStep, TangentAssembler(TangentStiffness), - EModelDefaultEquationNumbering(), this->giveDomain(1) ); - break; - - default: - OOFEM_ERROR("Unknown component id (%d)", ( int ) cmpn); - } -} - -int DarcyFlow :: forceEquationNumbering(int id) // Is this really needed???!? -{ - int neq = EngngModel :: forceEquationNumbering(id); - - this->equationNumberingCompleted = false; - this->stiffnessMatrix.reset(NULL); - - return neq; -} - -NumericalMethod *DarcyFlow :: giveNumericalMethod(MetaStep *mStep) -{ - /* - * Returns pointer to NumericalMethod object. The solver used for StokesFlow is SparseLinearSystemNM. - * If no solver has bee initialized, create one, otherwise, return the existing solver. - */ - - if ( !this->nMethod ) { - this->nMethod.reset( new NRSolver(this->giveDomain(1), this) ); - if ( !nMethod ) { - OOFEM_ERROR("numerical method creation failed"); - } - } - - return this->nMethod.get(); -} - -TimeStep *DarcyFlow :: giveNextStep() -{ - if ( !currentStep ) { - // first step -> generate initial step - //currentStep.reset( new TimeStep(*giveSolutionStepWhenIcApply()) ); - currentStep.reset( new TimeStep(giveNumberOfTimeStepWhenIcApply(), this, 1, 0., 1.0, 0) ); - } - previousStep = std :: move(currentStep); - currentStep.reset( new TimeStep(*previousStep, 1.0) ); - - return currentStep.get(); -} - -} diff --git a/src/tm/darcyflow.h b/src/tm/darcyflow.h deleted file mode 100644 index 637b0bd8e..000000000 --- a/src/tm/darcyflow.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * DarcyFlow.h - * - * Created on: Feb 25, 2010 - * Author: carl - */ - -#ifndef darcyflow_h -#define darcyflow_h - -#include "engngm.h" -#include "inputrecord.h" -#include "sparsemtrxtype.h" -#include "linsystsolvertype.h" -#include "sparselinsystemnm.h" -#include "sparsenonlinsystemnm.h" -#include "primaryfield.h" - -#define _IFT_DarcyFlow_Name "darcyflow" - -namespace oofem { -class CommunicatorBuff; -class ProblemCommunicator; - -/** - * Class describing an extended Darcy flow. A Darcy flow is a linear relation between the seepage velocity and the pressure gradient. By 'extended', - * we imply that there is a possibility for a nonlinear relation. - * @author Carl Sandström - */ -class DarcyFlow : public EngngModel -{ -private: - LinSystSolverType solverType; - -protected: - std :: unique_ptr< PrimaryField > PressureField; - SparseMtrxType sparseMtrxType; - std :: unique_ptr< SparseNonLinearSystemNM > nMethod; - - std :: unique_ptr< SparseMtrx > stiffnessMatrix; - FloatArray internalForces; - FloatArray externalForces; - FloatArray incrementOfSolution; - - int currentIterations; - FloatArray ebeNorm; - FloatArray incrementOfDisplacement; - FloatArray incrementalBCLoadVector; - FloatArray incrementalLoadVector; - FloatArray initialLoad; - SparseNonLinearSystemNM :: referenceLoadInputModeType refLoadInputMode; - bool hasAdvanced; - -public: - DarcyFlow(int i, EngngModel * _master); - virtual ~DarcyFlow(); - - virtual void solveYourselfAt(TimeStep *tStep); - virtual void updateYourself(TimeStep *tStep); - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode) { return CIO_IOERR; } - virtual contextIOResultType restoreContext(DataStream *stream, ContextMode mode, void *obj = NULL) { return CIO_IOERR; } - virtual int checkConsistency() { return 1; } - virtual fMode giveFormulation() { return TL; } - - virtual void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d); - - virtual double giveUnknownComponent(ValueModeType, TimeStep *, Domain *, Dof *); - - virtual IRResultType initializeFrom(InputRecord *ir); - void DumpMatricesToFile(FloatMatrix *LHS, FloatArray *RHS, FloatArray *SolutionVector); - - virtual NumericalMethod *giveNumericalMethod(MetaStep *mStep); - virtual TimeStep *giveNextStep(); - - virtual int forceEquationNumbering(int id); - - virtual const char *giveInputRecordName() const { return _IFT_DarcyFlow_Name; } - virtual const char *giveClassName() const { return "DarcyFlow"; } -}; -} - -#endif // darcyflow_h diff --git a/src/tm/hemobaznajmat.C b/src/tm/hemobaznajmat.C deleted file mode 100644 index 69e2d471e..000000000 --- a/src/tm/hemobaznajmat.C +++ /dev/null @@ -1,343 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "hemobaznajmat.h" -#include "floatmatrix.h" -#include "gausspoint.h" -#include "mathfem.h" -#include "classfactory.h" - -namespace oofem { - -REGISTER_Material( HeMoBazNajMaterial ); - -int -HeMoBazNajMaterial :: hasMaterialModeCapability(MaterialMode mode) -{ - if ( ( mode == _2dHeMo ) || ( mode == _3dHeMo ) ) { - return 1; - } - - return 0; -} - - -IRResultType -HeMoBazNajMaterial :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - IR_GIVE_FIELD(ir, C1, _IFT_HeMoBazNajMaterial_c1); - IR_GIVE_FIELD(ir, n, _IFT_HeMoBazNajMaterial_n); - IR_GIVE_FIELD(ir, alpha0, _IFT_HeMoBazNajMaterial_alpha0); - IR_GIVE_FIELD(ir, hC, _IFT_HeMoBazNajMaterial_hc); - - this->moistureCapacity = 1.; - IR_GIVE_OPTIONAL_FIELD(ir, moistureCapacity, _IFT_HeMoBazNajMaterial_capa); - - IR_GIVE_FIELD(ir, heatConductivity, _IFT_HeMoBazNajMaterial_k); - IR_GIVE_FIELD(ir, heatCapacity, _IFT_HeMoBazNajMaterial_c); - - return Material :: initializeFrom(ir); -} - - -double -HeMoBazNajMaterial :: give(int aProperty, GaussPoint *gp) -// -// Returns the value of the property aProperty (e.g. the Young's modulus -// 'E') of the receiver. -// -{ - return this->Material :: give(aProperty, gp); -} - - -void -HeMoBazNajMaterial :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) -{ - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - - FloatArray s; - s = ms->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("undefined state vector"); - } - double h = s.at(2); - double t = s.at(1); - - FloatArray ans_w, ans_t; - int size = grad.giveSize() / 2; - FloatArray grad_w(size), grad_t(size); - for (int i = 1; i <= size; ++i) { - grad_w.at(i) = grad.at(i); - } - for (int i = 1; i <= size; ++i) { - grad_t.at(i) = grad.at(i+size); - } - - ans_w.beScaled(perm_mm(h, t), grad_w); - ans_w.beScaled(perm_mh(h, t), grad_t); - ans_t.beScaled(perm_hm(h, t), grad_w); - ans_t.beScaled(perm_hh(h, t), grad_t); - - answer.resize(size * 2); - answer.zero(); - answer.addSubVector(ans_w, 1); - answer.addSubVector(ans_t, size+1); - - ms->setTempField(field); - ms->setTempGradient(grad); - ms->setTempFlux(answer); -} - - -void -HeMoBazNajMaterial :: giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *atTime) -{ - /* - * returns constitutive matrix of receiver - */ - if ( ( mode == Conductivity_ww ) || ( mode == Conductivity_hh ) || ( mode == Conductivity_hw ) || ( mode == Conductivity_wh ) ) { - this->computeConductivityMtrx(answer, mode, gp, atTime); - } else { - OOFEM_ERROR( "giveCharacteristicMatrix : unknown mode (%s)", __MatResponseModeToString(mode) ); - } -} - - -double -HeMoBazNajMaterial :: giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *atTime) -{ - return this->computeCapacityCoeff(mode, gp, atTime); -} - - -void HeMoBazNajMaterial :: computeConductivityMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) -{ - MaterialMode mmode = gp->giveMaterialMode(); - switch ( mmode ) { - case _2dHeMo: - this->matcond2d(answer, gp, mode, atTime); - return; - - case _3dHeMo: - this->matcond3d(answer, gp, mode, atTime); - return; - - default: - OOFEM_ERROR("Unsupported MaterialMode"); - } -} - - -void -HeMoBazNajMaterial :: matcond1d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime) -{ - double k = 0.0, h = 0.0, t = 0.0; - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - - FloatArray s; - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("undefined state vector"); - } - h = s.at(2); - t = s.at(1); - - - if ( mode == Conductivity_ww ) { - k = perm_mm(h, t); - } else if ( mode == Conductivity_wh ) { - k = perm_mh(h, t); - } else if ( mode == Conductivity_hw ) { - k = perm_hm(h, t); - } else if ( mode == Conductivity_hh ) { - k = perm_hh(h, t); - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - d.resize(1, 1); - d.at(1, 1) = k; -} - -void -HeMoBazNajMaterial :: matcond2d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime) -{ - double k = 0.0, h = 0.0, t = 0.0; - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - - FloatArray s; - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("undefined state vector"); - } - h = s.at(2); - t = s.at(1); - - if ( mode == Conductivity_ww ) { - k = perm_mm(h, t); - } else if ( mode == Conductivity_wh ) { - k = perm_mh(h, t); - } else if ( mode == Conductivity_hw ) { - k = perm_hm(h, t); - } else if ( mode == Conductivity_hh ) { - k = perm_hh(h, t); - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - d.resize(2, 2); - d.at(1, 1) = k; - d.at(1, 2) = 0.0; - d.at(2, 1) = 0.0; - d.at(2, 2) = k; -} - -void -HeMoBazNajMaterial :: matcond3d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime) -{ - double k = 0.0, h = 0.0, t = 0.0; - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - - FloatArray s; - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("undefined state vector"); - } - h = s.at(2); - t = s.at(1); - - if ( mode == Conductivity_ww ) { - k = perm_mm(h, t); - } else if ( mode == Conductivity_wh ) { - k = perm_mh(h, t); - } else if ( mode == Conductivity_hw ) { - k = perm_hm(h, t); - } else if ( mode == Conductivity_hh ) { - k = perm_hh(h, t); - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - d.resize(3, 3); - d.at(1, 1) = k; - d.at(1, 2) = 0.0; - d.at(1, 3) = 0.0; - d.at(2, 1) = 0.0; - d.at(2, 2) = k; - d.at(2, 3) = 0.0; - d.at(3, 1) = 0.0; - d.at(3, 2) = 0.0; - d.at(3, 3) = k; -} - - -double HeMoBazNajMaterial :: computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) -{ - if ( mode == Capacity_ww ) { - return this->moistureCapacity; - - } else if ( mode == Capacity_wh ) { - return 0.0; - - } else if ( mode == Capacity_hw ) { - return 0.0; - - } else if ( mode == Capacity_hh ) { - return this->heatCapacity; - - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - return 0.0; // to make compiler happy -} - - -double -HeMoBazNajMaterial :: perm_mm(double h, double T) -{ - return ( C1 * ( alpha0 + ( 1. - alpha0 ) / ( 1. + pow( ( 1. - h ) / ( 1. - hC ), n ) ) ) ); -} - -double -HeMoBazNajMaterial :: perm_mh(double h, double T) -{ - return (0.); -} - -double -HeMoBazNajMaterial :: perm_hm(double h, double T) -{ - return (0.); -} - -double -HeMoBazNajMaterial :: perm_hh(double h, double T) -{ - return this->heatConductivity; -} - -bool -HeMoBazNajMaterial :: isCharacteristicMtrxSymmetric(MatResponseMode mode) -{ - if ( ( mode == Conductivity_ww ) || ( mode == Conductivity_hh ) || ( mode == Conductivity_hw ) || ( mode == Conductivity_wh ) ) { - return true; - } else { - OOFEM_ERROR( "isCharacteristicMtrxSymmetric : unknown mode (%s)", __MatResponseModeToString(mode) ); - } - - return false; // to make compiler happy -} - -int -HeMoBazNajMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime) -// IST_Humidity overriden to use inverse_sorption_isotherm -{ - if ( type == IST_Humidity ) { - answer.resize(1); - answer.at(1) = giveHumidity(gp, VM_Velocity); // VM_Previous = equilibrated value of humidity - return 1; - } else { - return TransportMaterial :: giveIPValue(answer, gp, type, atTime); - } -} -} // end namespace oofem diff --git a/src/tm/hemokunzelmat.C b/src/tm/hemokunzelmat.C deleted file mode 100644 index 514036725..000000000 --- a/src/tm/hemokunzelmat.C +++ /dev/null @@ -1,671 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "hemokunzelmat.h" -#include "floatmatrix.h" -#include "gausspoint.h" -#include "mathfem.h" -#include "classfactory.h" - -namespace oofem { -REGISTER_Material(HeMoKunzelMaterial); - -int -HeMoKunzelMaterial :: hasMaterialModeCapability(MaterialMode mode) -{ - if ( ( mode == _2dHeMo ) || ( mode == _3dHeMo ) ) { - return 1; - } - - return 0; -} - - -IRResultType -HeMoKunzelMaterial :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - int type = 0; - IR_GIVE_OPTIONAL_FIELD(ir, type, _IFT_HeMoKunzelMaterial_iso_type); - this->Isotherm = ( isothermType ) type; - - if ( this->Isotherm == Hansen ) { - IR_GIVE_FIELD(ir, iso_wh, _IFT_HeMoKunzelMaterial_iso_wh); - IR_GIVE_FIELD(ir, iso_n, _IFT_HeMoKunzelMaterial_iso_n); - IR_GIVE_FIELD(ir, iso_a, _IFT_HeMoKunzelMaterial_iso_a); - } else if ( this->Isotherm == Kunzeliso ) { - IR_GIVE_FIELD(ir, iso_wh, _IFT_HeMoKunzelMaterial_iso_wh); - IR_GIVE_FIELD(ir, iso_b, _IFT_HeMoKunzelMaterial_iso_b); - } else { - OOFEM_ERROR("Unknown Isotherm type"); - } - - - IR_GIVE_FIELD(ir, type, _IFT_HeMoKunzelMaterial_permeability_type); - - if ( type >= 3 ) { - OOFEM_ERROR("initializeFrom: isothermType must be equal to 0, 1, 2"); - } - - this->Permeability = ( permeabilityType ) type; - - if ( this->Permeability == Multilin_h ) { - IR_GIVE_FIELD(ir, perm_h, _IFT_HeMoKunzelMaterial_perm_h); - IR_GIVE_FIELD(ir, perm_Dwh, _IFT_HeMoKunzelMaterial_perm_dwh); - - if ( !( perm_h.giveSize() == perm_Dwh.giveSize() ) ) { - OOFEM_ERROR("initializeFrom: the size of 'perm_h' and 'perm_dw(h)' must be the same"); - } - - for ( int i = 1; i < perm_h.giveSize(); i++ ) { - if ( ( perm_h.at(i) < 0. ) || ( perm_h.at(i) > 1. ) ) { - OOFEM_ERROR("initializeFrom: perm_h must be in the range <0; 1>"); - } - } - } else if ( this->Permeability == Multilin_wV ) { - IR_GIVE_FIELD(ir, perm_wV, _IFT_HeMoKunzelMaterial_perm_wv); - IR_GIVE_FIELD(ir, perm_DwwV, _IFT_HeMoKunzelMaterial_perm_dwwv); - - if ( !( perm_wV.giveSize() == perm_DwwV.giveSize() ) ) { - OOFEM_ERROR("initializeFrom: the size of 'perm_h' and 'perm_dw(h)' must be the same"); - } - - for ( int i = 1; i < perm_wV.giveSize(); i++ ) { - if ( ( perm_wV.at(i) < 0. ) || ( perm_wV.at(i) > 1. ) ) { - OOFEM_ERROR("initializeFrom: perm_wv must be in the range <0; 1>"); - } - } - } else if ( this->Permeability == Kunzelperm ) { - IR_GIVE_FIELD(ir, A, _IFT_HeMoKunzelMaterial_a); - } else { - OOFEM_ERROR("initializeFrom: permeabilityType must be equal to 0, 1 or 2"); - } - - - - IR_GIVE_FIELD(ir, mu, _IFT_HeMoKunzelMaterial_mu); - - PL = 101325.; - IR_GIVE_OPTIONAL_FIELD(ir, PL, _IFT_HeMoKunzelMaterial_pl); - - rhoH2O = 1000.; - IR_GIVE_OPTIONAL_FIELD(ir, rhoH2O, _IFT_HeMoKunzelMaterial_rhoh2o); - - IR_GIVE_FIELD(ir, lambda0, _IFT_HeMoKunzelMaterial_lambda0); - IR_GIVE_FIELD(ir, b, _IFT_HeMoKunzelMaterial_b); - IR_GIVE_FIELD(ir, cs, _IFT_HeMoKunzelMaterial_cs); - - // cw = 4.1813e3; - cw = 4183.; - IR_GIVE_OPTIONAL_FIELD(ir, cw, _IFT_HeMoKunzelMaterial_cw); - - hv = 2.5e6; - IR_GIVE_OPTIONAL_FIELD(ir, hv, _IFT_HeMoKunzelMaterial_hv); - - - return Material :: initializeFrom(ir); -} - - -double -HeMoKunzelMaterial :: give(int aProperty, GaussPoint *gp) -// -// Returns the value of the property aProperty (e.g. the Young's modulus -// 'E') of the receiver. -// -{ - return Material :: give(aProperty, gp); -} - - -void -HeMoKunzelMaterial :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) -{ - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - - ms->setTempField(field); - ms->setTempGradient(grad); - - double h = field.at(2); - double t = field.at(1); - - int size = grad.giveSize() / 2; - FloatArray ans_h, ans_m; - FloatArray grad_h(size), grad_m(size); - for ( int i = 1; i <= size; ++i ) { - grad_h.at(i) = grad.at(i); - } - for ( int i = 1; i <= 2; ++i ) { - grad_m.at(i) = grad.at(i+size); - } - - ans_m.add(-perm_mm(h, t), grad_m); - ans_m.add(-perm_mh(h, t), grad_h); - ans_h.add(-perm_hm(h, t), grad_m); - ans_h.add(-perm_hh(h, t), grad_h); - - answer.resize(size * 2); - answer.zero(); - answer.addSubVector(ans_h, 1); - answer.addSubVector(ans_m, size + 1); - - ms->setTempFlux(answer); -} - - -void -HeMoKunzelMaterial :: giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *atTime) -{ - /* - * returns constitutive matrix of receiver - */ - if ( ( mode == Conductivity_ww ) || ( mode == Conductivity_hh ) || ( mode == Conductivity_hw ) || ( mode == Conductivity_wh ) ) { - this->computeConductivityMtrx(answer, mode, gp, atTime); - } else { - OOFEM_ERROR( "giveCharacteristicMatrix : unknown mode (%s)", __MatResponseModeToString(mode) ); - } -} - - -double -HeMoKunzelMaterial :: giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *atTime) -{ - return this->computeCapacityCoeff(mode, gp, atTime); -} - - -void HeMoKunzelMaterial :: computeConductivityMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) -{ - MaterialMode mmode = gp->giveMaterialMode(); - switch ( mmode ) { - case _2dHeMo: - this->matcond2d(answer, gp, mode, atTime); - return; - - case _3dHeMo: - this->matcond3d(answer, gp, mode, atTime); - return; - - default: - OOFEM_ERROR("Unsupported MaterialMode"); - } -} - - -void -HeMoKunzelMaterial :: matcond1d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime) -{ - double k = 0.0, h = 0.0, t = 0.0; - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray s; - - // s = status->giveTempStateVector(); - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("matcond1d: undefined state vector"); - } - - h = s.at(2); - t = s.at(1); - - if ( mode == Conductivity_ww ) { - k = perm_mm(h, t); - } else if ( mode == Conductivity_wh ) { - k = perm_mh(h, t); - } else if ( mode == Conductivity_hw ) { - k = perm_hm(h, t); - } else if ( mode == Conductivity_hh ) { - k = perm_hh(h, t); - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - d.resize(1, 1); - d.at(1, 1) = k; -} - -void -HeMoKunzelMaterial :: matcond2d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime) -{ - double k = 0.0, h = 0.0, t = 0.0; - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray s; - - // s = status->giveTempStateVector(); - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("matcond2d: undefined state vector"); - } - - h = s.at(2); - t = s.at(1); - - // if (gp->giveElement()->giveNumber() == 4) - // double bzzz = 20; - - if ( mode == Conductivity_ww ) { - k = perm_mm(h, t); - } else if ( mode == Conductivity_wh ) { - k = perm_mh(h, t); - } else if ( mode == Conductivity_hw ) { - k = perm_hm(h, t); - } else if ( mode == Conductivity_hh ) { - k = perm_hh(h, t); - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - d.resize(2, 2); - d.at(1, 1) = k; - d.at(1, 2) = 0.0; - d.at(2, 1) = 0.0; - d.at(2, 2) = k; -} - -void -HeMoKunzelMaterial :: matcond3d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *atTime) -{ - double k = 0.0, h = 0.0, t = 0.0; - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray s; - - - // s = status->giveTempStateVector(); - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("matcond3d: undefined state vector"); - } - - h = s.at(2); - t = s.at(1); - - if ( mode == Conductivity_ww ) { - k = perm_mm(h, t); - } else if ( mode == Conductivity_wh ) { - k = perm_mh(h, t); - } else if ( mode == Conductivity_hw ) { - k = perm_hm(h, t); - } else if ( mode == Conductivity_hh ) { - k = perm_hh(h, t); - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - d.resize(3, 3); - d.at(1, 1) = k; - d.at(1, 2) = 0.0; - d.at(1, 3) = 0.0; - d.at(2, 1) = 0.0; - d.at(2, 2) = k; - d.at(2, 3) = 0.0; - d.at(3, 1) = 0.0; - d.at(3, 2) = 0.0; - d.at(3, 3) = k; -} - - -double HeMoKunzelMaterial :: computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *atTime) -{ - // if (gp->giveElement()->giveNumber() == 4) - // double bzzz = 20; - - - if ( mode == Capacity_ww ) { - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray s; - double h; - double dw_dh; - - // s = status->giveTempStateVector(); - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("computeCapacityCoeff: undefined state vector"); - } - - h = s.at(2); - dw_dh = this->giveMoistureContentDerivative(h); - - return dw_dh; - - // CONSTANT - //return 10.; - } else if ( mode == Capacity_wh ) { - return 0.0; - } else if ( mode == Capacity_hw ) { - return 0.0; - } else if ( mode == Capacity_hh ) { - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray s; - double h, w; - double dHs_dT, dHw_dT; - - //s = status->giveTempStateVector(); - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("computeCapacityCoeff: undefined state vector"); - } - - h = s.at(2); - - w = this->giveMoistureContent(h); - - dHs_dT = cs * give('d', NULL); - dHw_dT = cw * w; - - return ( dHs_dT + dHw_dT ); - - // CONSTANT return 1.7e6; - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - return 0.0; // to make compiler happy -} - - -double -HeMoKunzelMaterial :: giveMoistureContent(double h) -{ - double w = 0.; - - if ( ( h < 0.0 ) || ( h > 1.00 ) ) { - OOFEM_ERROR("HeMoKunzelMaterial :: giveMoistureContent : Relative humidity %.3f is out of range", h); - } - - if ( this->Isotherm == Hansen ) { - w = iso_wh * pow( ( 1.0 - log(h) / iso_a ), ( -1.0 / iso_n ) ); - } else if ( this->Isotherm == Kunzeliso ) { - w = iso_wh * ( iso_b - 1. ) * h / ( iso_b - h ); - } else { - OOFEM_ERROR("Unknown Isotherm type"); - } - - return ( w ); -} - -double -HeMoKunzelMaterial :: giveMoistureContentDerivative(double h) -{ - double dw_dh = 0.; - - if ( ( h < 0.0 ) || ( h > 1.00 ) ) { - OOFEM_ERROR("HeMoKunzelMaterial :: giveMoistureContentDerivative : Relative humidity %.3f is out of range", h); - } - - if ( this->Isotherm == Hansen ) { - dw_dh = iso_wh / ( iso_n * iso_a * h ) * pow( ( 1.0 - log(h) / iso_a ), ( -( 1.0 + iso_n ) / iso_n ) ); - } else if ( this->Isotherm == Kunzeliso ) { - dw_dh = iso_wh * ( iso_b - 1. ) * iso_b / ( ( iso_b - h ) * ( iso_b - h ) ); - } else { - OOFEM_ERROR("Unknown Isotherm type"); - } - - return ( dw_dh ); -} - - -double -HeMoKunzelMaterial :: computeWaterVaporPerm(double T) -{ - /// vapor diffusion coefficient in air [kg m^-1 s^-1 Pa^-1] - double delta; - double deltap; - - delta = 2.0 * 1.e-7 * pow(T, 0.81) / PL; - deltap = delta / mu; - - return ( deltap ); -} - -double -HeMoKunzelMaterial :: computeSatVaporPressure(double T) -{ - double p_sat; - double T0, a; - double T_C = T - 273.15; - - if ( T_C < 0. ) { - a = 22.44; - T0 = 272.44; - } else { - a = 17.08; - T0 = 234.18; - } - - p_sat = 611. * exp( a * T_C / ( T0 + T_C ) ); - - return p_sat; -} - -double -HeMoKunzelMaterial :: computeSatVaporPressureDerivative(double T) -{ - double dpsat_dT; - double T0, a; - double T_C = T - 273.15; - - if ( T_C < 0. ) { - a = 22.44; - T0 = 272.44; - } else { - a = 17.08; - T0 = 234.18; - } - - dpsat_dT = 611. *a *T0 *exp( a *T_C / ( T0 + T_C ) ) / ( ( T0 + T_C ) * ( T0 + T_C ) ); - - return dpsat_dT; -} - - -double -HeMoKunzelMaterial :: computeDw(double h) -{ - double Dw = 0.; - - if ( this->Permeability == Multilin_h ) { - double tol = 1.e-10; - for ( int i = 1; i <= perm_h.giveSize(); i++ ) { - if ( ( h - perm_h.at(i) ) < tol ) { - Dw = perm_Dwh.at(i - 1) + ( perm_Dwh.at(i) - perm_Dwh.at(i - 1) ) * ( h - perm_h.at(i - 1) ) / ( perm_h.at(i) - perm_h.at(i - 1) ); - break; - } - } - } else if ( this->Permeability == Multilin_wV ) { - double wV = this->giveMoistureContent(h) / rhoH2O; - double tol = 1.e-10; - for ( int i = 1; i <= perm_wV.giveSize(); i++ ) { - if ( ( wV - perm_wV.at(i) ) < tol ) { - Dw = perm_DwwV.at(i - 1) + ( perm_DwwV.at(i) - perm_DwwV.at(i - 1) ) * ( wV - perm_wV.at(i - 1) ) / ( perm_wV.at(i) - perm_wV.at(i - 1) ); - break; - } - } - } else if ( this->Permeability == Kunzelperm ) { - double w; - w = this->giveMoistureContent(h); - Dw = 3.8 * ( A / iso_wh ) * ( A / iso_wh ) * pow(1000., w / iso_wh - 1.); - } else { - OOFEM_ERROR("initializeFrom: permeabilityType must be equal to 0, 1 or 2"); - } - - return Dw; -} - - -double -HeMoKunzelMaterial :: perm_mm(double h, double T) -{ - // Function calculates permability relative humidity - relative humidity (k_mm) - // h ... relative humidity - // Dw ... capillary transport coefficient [m^2/s] - // dw_dh ... derivative of moisture storage function [kg/m^3] - // p_sat ... saturation water vapor pressure - - double k_mm; - double dw_dh, Dw; - double deltap, p_sat; - - dw_dh = this->giveMoistureContentDerivative(h); - - Dw = this->computeDw(h); - - deltap = this->computeWaterVaporPerm(T); - p_sat = this->computeSatVaporPressure(T); - - k_mm = Dw * dw_dh + deltap * p_sat; - - return ( k_mm ); - - //return 5.e-8; -} - -double -HeMoKunzelMaterial :: perm_mh(double h, double T) -{ - // Function calculates permeability relative humidity-temperature (k_mh) - // deltap ... water vapor permeability - // dpsat_dt ... differentiation of saturation water vapor presssure with respect to temperature - - double k_mh; - double delta_p, dpsat_dT; - - delta_p = computeWaterVaporPerm(T); - dpsat_dT = computeSatVaporPressureDerivative(T); - - k_mh = delta_p * h * dpsat_dT; - - // return 2.e-7; - - return k_mh; -} - - -double -HeMoKunzelMaterial :: perm_hm(double h, double T) -{ - // Function calculates permability temperature-relative humidity (k_hm) - - double k_hm; - double deltap, p_sat; - - deltap = this->computeWaterVaporPerm(T); - p_sat = this->computeSatVaporPressure(T); - - k_hm = hv * deltap * p_sat; - - return ( k_hm ); - - // return 0.1; - // return 0.; -} - -double -HeMoKunzelMaterial :: perm_hh(double h, double T) -{ - // Function calculates permability water temperature-temperature (k_hh) - - double k_hh; - double lambda, deltap, dpsat_dT, w; - - w = this->giveMoistureContent(h); - lambda = lambda0 * ( 1. + b * w / give('d', NULL) ); - deltap = this->computeWaterVaporPerm(T); - dpsat_dT = computeSatVaporPressureDerivative(T); - - k_hh = lambda + hv * deltap * h * dpsat_dT; - - return ( k_hh ); - - // return 2.; -} - -bool -HeMoKunzelMaterial :: isCharacteristicMtrxSymmetric(MatResponseMode mode) -{ - if ( ( mode == Conductivity_ww ) || ( mode == Conductivity_hh ) || ( mode == Conductivity_hw ) || ( mode == Conductivity_wh ) ) { - return false; - } else { - OOFEM_ERROR( "isCharacteristicMtrxSymmetric : unknown mode (%s)", __MatResponseModeToString(mode) ); - } - - return false; // to make compiler happy -} - -int -HeMoKunzelMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *atTime) -// IST_Humidity overriden to use inverse_sorption_isotherm -{ - if ( type == IST_Humidity ) { - answer.resize(1); - answer.at(1) = giveHumidity(gp, VM_Velocity); // VM_Previous = equilibrated value of humidity - return 1; - } else if ( type == IST_MoistureContent ) { - double humidity = giveHumidity(gp, VM_Velocity);; - answer.resize(1); - answer.at(1) = giveMoistureContent(humidity); - } else { - return TransportMaterial :: giveIPValue(answer, gp, type, atTime); - } -} - -double -HeMoKunzelMaterial :: giveHumidity(GaussPoint *gp, ValueModeType mode) -{ - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - const FloatArray &tempState = ms->giveTempField(); - if ( tempState.giveSize() < 2 ) { - OOFEM_ERROR("Undefined moisture status"); - } - - const FloatArray &state = ms->giveField(); - - if ( mode == VM_Total ) { - return tempState.at(2); - } else if ( mode == VM_Incremental ) { - return tempState.at(2) - state.at(2); - } else if ( mode == VM_Velocity ) { // VM_Previous - return state.at(2); - } else { - OOFEM_ERROR("Undefined moisture mode"); - } - - return 1.; -} -} // end namespace oofem diff --git a/src/tm/hemotkmat.C b/src/tm/hemotkmat.C deleted file mode 100644 index 3ba9fc3de..000000000 --- a/src/tm/hemotkmat.C +++ /dev/null @@ -1,615 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "hemotkmat.h" -#include "floatmatrix.h" -#include "gausspoint.h" -#include "mathfem.h" -#include "classfactory.h" - -namespace oofem { -REGISTER_Material(HeMoTKMaterial); - -int -HeMoTKMaterial :: hasMaterialModeCapability(MaterialMode mode) -{ - if ( ( mode == _2dHeMo ) || ( mode == _3dHeMo ) ) { - return 1; - } - - return 0; -} - - -IRResultType -HeMoTKMaterial :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - IR_GIVE_FIELD(ir, a_0, _IFT_HeMoTKMaterial_a_0); - IR_GIVE_FIELD(ir, nn, _IFT_HeMoTKMaterial_nn); - IR_GIVE_FIELD(ir, phi_c, _IFT_HeMoTKMaterial_phi_c); - IR_GIVE_FIELD(ir, delta_wet, _IFT_HeMoTKMaterial_delta_wet); - - IR_GIVE_FIELD(ir, w_h, _IFT_HeMoTKMaterial_w_h); - IR_GIVE_FIELD(ir, n, _IFT_HeMoTKMaterial_n); - IR_GIVE_FIELD(ir, a, _IFT_HeMoTKMaterial_a); - - IR_GIVE_FIELD(ir, latent, _IFT_HeMoTKMaterial_latent); - IR_GIVE_FIELD(ir, c, _IFT_HeMoTKMaterial_c); - IR_GIVE_FIELD(ir, rho, _IFT_HeMoTKMaterial_rho); - IR_GIVE_FIELD(ir, chi_eff, _IFT_HeMoTKMaterial_chi_eff); - - IR_GIVE_FIELD(ir, por, _IFT_HeMoTKMaterial_por); - IR_GIVE_FIELD(ir, rho_gws, _IFT_HeMoTKMaterial_rho_gws); - - return Material :: initializeFrom(ir); -} - - -double -HeMoTKMaterial :: give(int aProperty, GaussPoint *gp) -// -// Returns the value of the property aProperty (e.g. the Young's modulus -// 'E') of the receiver. -// -{ - return Material :: give(aProperty, gp); -} - - -void -HeMoTKMaterial :: giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) -{ - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - - double w = field.at(2); - double t = field.at(1); - - FloatArray ans_w, ans_t; - FloatArray grad_w, grad_t; - int size = grad.giveSize() / 2; - for ( int i = 1; i <= size; ++i ) { - grad_w.at(i) = grad.at(i); - } - for ( int i = size + 1; i <= size * 2; ++i ) { - grad_t.at(i) = grad.at(i); - } - ans_w.beScaled(perm_ww(w, t), grad_w); - ans_w.beScaled(perm_wt(w, t), grad_t); - ans_t.beScaled(perm_ww(w, t) * get_latent(w, t), grad_w); - ans_t.beScaled(get_chi(w, t) + get_latent(w, t) * perm_wt(w, t), grad_t); - - answer.resize(size * 2); - answer.zero(); - answer.addSubVector(ans_w, 1); - answer.addSubVector(ans_t, size + 1); - - ms->setTempField(field); - ms->setTempGradient(grad); - ms->setTempFlux(answer); -} - - -void -HeMoTKMaterial :: giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -{ - /* - * returns constitutive matrix of receiver - */ - if ( ( mode == Conductivity_ww ) || ( mode == Conductivity_hh ) || ( mode == Conductivity_hw ) || ( mode == Conductivity_wh ) ) { - this->computeConductivityMtrx(answer, mode, gp, tStep); - } else { - OOFEM_ERROR("unknown mode (%s)", __MatResponseModeToString(mode) ); - } -} - - -double -HeMoTKMaterial :: giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) -{ - return this->computeCapacityCoeff(mode, gp, tStep); -} - - -void HeMoTKMaterial :: computeConductivityMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - MaterialMode mmode = gp->giveMaterialMode(); - switch ( mmode ) { - case _2dHeMo: - this->matcond2d(answer, gp, mode, tStep); - return; - - case _3dHeMo: - this->matcond3d(answer, gp, mode, tStep); - return; - - default: - OOFEM_ERROR("Unsupported MaterialMode"); - } -} - - -void -HeMoTKMaterial :: matcond1d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *tStep) -// function creates conductivity matrix of the -// isotropic heat material for 1D problems -// -// d - conductivity matrix of the material -// 25.9.2001 -{ - double k = 0.0, w = 0.0, t = 0.0; - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray s; - - - // w = Tm->ip[ipp].av[0]; - // t = Tm->ip[ipp].av[1]; - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("undefined state vector"); - } - - w = s.at(2); - t = s.at(1); - - if ( mode == Conductivity_ww ) { - k = perm_ww(w, t); - } else if ( mode == Conductivity_wh ) { - k = perm_wt(w, t); - } else if ( mode == Conductivity_hw ) { - k = perm_ww(w, t) * get_latent(w, t); - } else if ( mode == Conductivity_hh ) { - k = get_chi(w, t) + get_latent(w, t) * perm_wt(w, t); - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - d.resize(1, 1); - d.at(1, 1) = k; -} - -void -HeMoTKMaterial :: matcond2d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *tStep) -// function creates conductivity matrix of the -// isotropic heat material for 2D problems -// -// d - conductivity matrix of the material -// 25.9.2001 -{ - double k = 0.0, w = 0.0, t = 0.0; - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray s; - - - // w = Tm->ip[ipp].av[0]; - // t = Tm->ip[ipp].av[1]; - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("undefined state vector"); - } - - w = s.at(2); - t = s.at(1); - - if ( mode == Conductivity_ww ) { - k = perm_ww(w, t); - } else if ( mode == Conductivity_wh ) { - k = perm_wt(w, t); - } else if ( mode == Conductivity_hw ) { - k = perm_ww(w, t) * get_latent(w, t); - } else if ( mode == Conductivity_hh ) { - k = get_chi(w, t) + get_latent(w, t) * perm_wt(w, t); - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - d.resize(2, 2); - d.at(1, 1) = k; - d.at(1, 2) = 0.0; - d.at(2, 1) = 0.0; - d.at(2, 2) = k; -} - -void -HeMoTKMaterial :: matcond3d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *tStep) -// function creates conductivity matrix of the -// isotropic heat material for 3D problems -// -// d - conductivity matrix of the material -// 25.9.2001 -{ - double k = 0.0, w = 0.0, t = 0.0; - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray s; - - - // w = Tm->ip[ipp].av[0]; - // t = Tm->ip[ipp].av[1]; - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("undefined state vector"); - } - - w = s.at(2); - t = s.at(1); - - if ( mode == Conductivity_ww ) { - k = perm_ww(w, t); - } else if ( mode == Conductivity_wh ) { - k = perm_wt(w, t); - } else if ( mode == Conductivity_hw ) { - k = perm_ww(w, t) * get_latent(w, t); - } else if ( mode == Conductivity_hh ) { - k = get_chi(w, t) + get_latent(w, t) * perm_wt(w, t); - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - d.resize(3, 3); - d.at(1, 1) = k; - d.at(1, 2) = 0.0; - d.at(1, 3) = 0.0; - d.at(2, 1) = 0.0; - d.at(2, 2) = k; - d.at(2, 3) = 0.0; - d.at(3, 1) = 0.0; - d.at(3, 2) = 0.0; - d.at(3, 3) = k; -} - - -double HeMoTKMaterial :: computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) -{ - if ( mode == Capacity_ww ) { - return 1.0 * rho; - } else if ( mode == Capacity_wh ) { - return 0.0; - } else if ( mode == Capacity_hw ) { - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray s; - double w, t; - - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("undefined state vector"); - } - - w = s.at(2); - t = s.at(1); - return get_b(w, t) * get_latent(w, t); - } else if ( mode == Capacity_hh ) { - TransportMaterialStatus *status = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - FloatArray s; - double w, t; - - s = status->giveTempField(); - if ( s.isEmpty() ) { - OOFEM_ERROR("undefined state vector"); - } - - w = s.at(2); - t = s.at(1); - return get_ceff(w, t); - } else { - OOFEM_ERROR("Unknown MatResponseMode"); - } - - return 0.0; // to make compiler happy -} - - -double -HeMoTKMaterial :: giveHumidity(GaussPoint *gp, ValueModeType mode) -{ - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - const FloatArray &tempState = ms->giveTempField(); - if ( tempState.giveSize() < 2 ) { - OOFEM_ERROR("undefined moisture status!"); - } - - const FloatArray &state = ms->giveField(); - - if ( mode == VM_Total ) { - return inverse_sorption_isotherm( tempState.at(2) ); - } else if ( mode == VM_Incremental ) { - return inverse_sorption_isotherm( tempState.at(2) ) - inverse_sorption_isotherm( state.at(2) ); - } else if ( mode == VM_Velocity ) { // VM_Previous - return inverse_sorption_isotherm( state.at(2) ); - } - - return 1.; -} - - - - -double -HeMoTKMaterial :: perm_ww(double w, double t) -{ - // Function calculates permability water content-water content (k_ww) - // phi ... relative humidity - // delta_gw ... water vapor permeability - // dphi_dw ... differentiation of relative with respect to water content - // p_gws ... saturation water vapor pressure - double k_ww, phi, delta_gw, dphi_dw, p_gws; - - phi = inverse_sorption_isotherm(w); - delta_gw = give_delta_gw(phi); - dphi_dw = give_dphi_dw(w); - p_gws = give_p_gws(t); - - k_ww = delta_gw * p_gws * dphi_dw; - - return ( k_ww ); -} - -double -HeMoTKMaterial :: perm_wt(double w, double t) -{ - // Function calculates permability water content-temperature (k_wt) - // delta_gw ... water vapor permeability - // d_pgw_d_t ... differentiation of water vapor presssure with respect to temperature - double k_wt, phi, delta_gw, dpgw_dt; - - phi = inverse_sorption_isotherm(w); - delta_gw = give_delta_gw(phi); - dpgw_dt = give_dpgw_dt(t, phi); - - k_wt = delta_gw * dpgw_dt; - - return ( k_wt ); -} - - -double -HeMoTKMaterial :: give_delta_gw(double phi) -// Function calculates the water vapor permeability delta_gw. Relative humidity (phi) is from range 0.2 - 0.98 !!! -// delta_gw ... by Z. P. Bazant and L. J. Najjar (1972), Nonlinear water diffusion in nonsaturated concrete, -// MATERIAUX ET CONSTRUCTIONS, Vol. 5, No. 25, pp. 3 -20. -// phi ... relative humidity -// a_0, nn, phi_c, delta_wet ... constants obtained from experiments -{ - double delta_gw; - - if ( ( phi < 0.2 ) || ( phi > 0.98 ) ) { - OOFEM_ERROR("Relative humidity is out of range"); - } - - // water vapor permeability - delta_gw = delta_wet * ( a_0 + ( 1.0 - a_0 ) / ( 1.0 + pow( ( 1.0 - phi ) / ( 1.0 - phi_c ), nn ) ) ); - - return ( delta_gw ); -} - - - -double -HeMoTKMaterial :: sorption_isotherm(double phi) -// Function calculates water content in medium from relative humidity. Relative humidity (phi) is from range 0.2 - 0.98 !!! -// sorption isotherm by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, -// PhD-thesis, Technical University of Denmark, Lingby. -// w (kg/kg) ... water content -// phi ... relative humidity -// w_h, n, a ... constants obtained from experiments -{ - double w; - - if ( ( phi < 0.2 ) || ( phi > 0.98 ) ) { - OOFEM_ERROR("Relative humidity %.3f is out of range", phi); - } - - // water content - w = w_h * pow( ( 1.0 - log(phi) / a ), ( -1.0 / n ) ); - - return ( w ); -} - - - -double -HeMoTKMaterial :: inverse_sorption_isotherm(double w) -// Function calculates relative humidity from water content (inverse relation form sorption isotherm). -// Relative humidity (phi) is from range 0.2 - 0.98 !!! -// sorption isotherm by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, -// PhD-thesis, Technical University of Denmark, Lingby. -// w (kg/kg) ... water content -// phi ... relative humidity -// w_h, n, a ... constants obtained from experiments -{ - double phi; - - // relative humidity - phi = exp( a * ( 1.0 - pow( ( w_h / w ), ( n ) ) ) ); - - if ( ( phi < 0.2 ) || ( phi > 0.98 ) ) { - OOFEM_ERROR("Relative humidity %.3f is out of range", phi); - } - - return ( phi ); -} - - - -double -HeMoTKMaterial :: give_dphi_dw(double w) -// Function calculates differentiation of relative humidity with respect to water content (inverse relation form sorption isotherm). -// Relative humidity (phi) is from range 0.2 - 0.98 !!! -// sorption isotherm by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, -// PhD-thesis, Technical University of Denmark, Lingby. -// w (kg/kg) ... water content -// phi ... relative humidity -// w_h, n, a ... constants obtained from experiments -{ - double dphi_dw; - - // diferentiation of realative humidity with respect to water content - dphi_dw = exp( a * ( 1.0 - pow( ( w_h / w ), n ) ) ) * a * n * pow(w_h, n) * pow( w, ( -1.0 - n ) ); - - return ( dphi_dw ); -} - -double -HeMoTKMaterial :: give_dpgw_dt(double t, double phi) -// Function calculates differentiation of water vapor pressure with respect to temperature -// saturation water vapor pressure by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, -// PhD-thesis, Technical University of Denmark, Lingby. -// t ... temperature [K] -// phi ... relative humidity -{ - double dp_gw_dt, dp_gws_dt; - - //differentiation of saturation water vapor pressure (analytical expression) with respect to temperature - dp_gws_dt = exp( 23.5771 - 4042.9 / ( t - 37.58 ) ) * 4042.9 / ( t - 37.58 ) / ( t - 37.58 ); - - dp_gw_dt = phi * dp_gws_dt; - - return ( dp_gw_dt ); -} - - -double -HeMoTKMaterial :: give_p_gws(double t) -// Function calculates saturation water vapor pressure -// saturation water vapor pressure by C. R. Pedersen (1990), Combined heat and moisture transfer in building constructions, -// PhD-thesis, Technical University of Denmark, Lingby. -// t ... temperature [K] -// phi ... relative humidity -{ - double p_gws; - - //saturation water vapor pressure ... analytical expression - p_gws = exp( 23.5771 - 4042.9 / ( t - 37.58 ) ); - - return ( p_gws ); -} - -double -HeMoTKMaterial :: get_latent(double w, double t) -{ - // Function calculates latent heat of evaporation - - double l; - - l = latent; //zatim!!!! - - return ( l ); -} - -double -HeMoTKMaterial :: get_b(double w, double t) -{ - // Function calculates coefficient b - // sat ... degree of saturation - - double b, sat, phi, dphi_dw; - - phi = inverse_sorption_isotherm(w); - dphi_dw = give_dphi_dw(w); - sat = get_sat(w, t); - - b = por * rho_gws * ( phi + ( 1 - sat ) * dphi_dw ); - - return ( b ); -} - - -double -HeMoTKMaterial :: get_sat(double w, double t) -{ - // Function calculates degree of saturation - // sat ... degree of saturation - - double sat; - - sat = 1.0; //zatim!!!! - - return ( sat ); -} - -double -HeMoTKMaterial :: get_ceff(double w, double t) -{ - // Function calculates effective thermal capacity - - double ceff; - - ceff = c * rho; //zatim!!!! - - return ( ceff ); -} - - -double -HeMoTKMaterial :: get_chi(double w, double t) -{ - // Function calculates effective thermal conductivity - - double chi; - - chi = chi_eff; //zatim!!!! - - return ( chi ); -} - -bool -HeMoTKMaterial :: isCharacteristicMtrxSymmetric(MatResponseMode mode) -{ - if ( ( mode == Conductivity_ww ) || ( mode == Conductivity_hh ) || ( mode == Conductivity_hw ) || ( mode == Conductivity_wh ) ) { - return false; - } else { - OOFEM_ERROR("unknown mode (%s)", __MatResponseModeToString(mode) ); - } - - return false; // to make compiler happy -} - -int -HeMoTKMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) -// IST_Humidity overriden to use inverse_sorption_isotherm -{ - if ( type == IST_Humidity ) { - answer.resize(1); - answer.at(1) = giveHumidity(gp, VM_Velocity); // VM_Previous = equilibrated value of humidity - return 1; - } else { - return TransportMaterial :: giveIPValue(answer, gp, type, tStep); - } -} -} // end namespace oofem diff --git a/src/tm/hemotkmat.h b/src/tm/hemotkmat.h deleted file mode 100644 index 1c5e16b77..000000000 --- a/src/tm/hemotkmat.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef hemotkmat_h -#define hemotkmat_h - -#include "transportmaterial.h" - -///@name Input fields for HeMoTKMaterial -//@{ -#define _IFT_HeMoTKMaterial_Name "hemotk" -#define _IFT_HeMoTKMaterial_a_0 "a_0" -#define _IFT_HeMoTKMaterial_nn "nn" -#define _IFT_HeMoTKMaterial_phi_c "phi_c" -#define _IFT_HeMoTKMaterial_delta_wet "delta_wet" -#define _IFT_HeMoTKMaterial_w_h "w_h" -#define _IFT_HeMoTKMaterial_n "n" -#define _IFT_HeMoTKMaterial_a "a" -#define _IFT_HeMoTKMaterial_latent "latent" -#define _IFT_HeMoTKMaterial_c "c" -#define _IFT_HeMoTKMaterial_rho "rho" -#define _IFT_HeMoTKMaterial_chi_eff "chi_eff" -#define _IFT_HeMoTKMaterial_por "por" -#define _IFT_HeMoTKMaterial_rho_gws "rho_gws" -//@} - -namespace oofem { -/** - * This class implements a coupled heat and mass transfer material model. It computes conductivity and capacity - * matrices for coupled heat and moisture transfer. - * Assumptions: Water vapor is the only driving mechanism; relative humidity is from range 0.2 - 0.98 (I and II region). - * @author Tomas Krejci - * Source: T.K. Doctoral Thesis; Bazant and Najjar, 1972; Pedersen, 1990. - */ -class HeMoTKMaterial : public TransportMaterial -{ -protected: - double a_0; ///< Constant (obtained from experiments) [Bazant and Najjar, 1972] - double nn; ///< Constant-exponent (obtained from experiments) [Bazant and Najjar, 1972] - double phi_c; ///< Constant-relative humidity (obtained from experiments) [Bazant and Najjar, 1972] - double delta_wet; ///< Constant-water vapor permeability (obtained from experiments) [Bazant and Najjar, 1972] - - double w_h; ///< Constant water content (obtained from experiments) [Pedersen, 1990] - double n; ///< Constant-exponent (obtained from experiments) [Pedersen, 1990] - double a; ///< Constant (obtained from experiments) [Pedersen, 1990] - - double latent; ///< Latent heat of evaporation. - double c; ///< Thermal capacity. - double rho; ///< Volume density. - double chi_eff; ///< Effective thermal conductivity. - - double por; ///< Porosity. - double rho_gws; ///< Saturation volume density. - -public: - - /** - * Constructor. Creates material with given number, belonging to given domain. - * @param n Material number. - * @param d Domain to which new material will belong. - */ - HeMoTKMaterial(int n, Domain * d) : TransportMaterial(n, d) { } - /// Destructor. - virtual ~HeMoTKMaterial() { } - - virtual void giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep); - - virtual void giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - - virtual double giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep); - - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode); - - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual double give(int aProperty, GaussPoint *gp); - - virtual int hasMaterialModeCapability(MaterialMode mode); - - // identification - virtual const char *giveInputRecordName() const { return _IFT_HeMoTKMaterial_Name; } - virtual const char *giveClassName() const { return "HeMoTKMaterial"; } - - double sorption_isotherm(double phi); - double inverse_sorption_isotherm(double w); - double give_dphi_dw(double w); - -protected: - void computeConductivityMtrx(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - void matcond1d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *tStep); - void matcond2d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *tStep); - void matcond3d(FloatMatrix &d, GaussPoint *gp, MatResponseMode mode, TimeStep *tStep); - - double computeCapacityCoeff(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep); - /** - * Returns positive value of humidity, use VM_Velocity for previous (equilibrated) value - */ - double giveHumidity(GaussPoint *gp, ValueModeType mode); - - double get_latent(double w, double t); - double get_ceff(double w, double t); - double get_chi(double w, double t); - - double perm_wt(double w, double t); - double perm_ww(double w, double t); - double give_delta_gw(double phi); - double give_dpgw_dt(double t, double phi); - - double get_b(double w, double t); - double get_sat(double w, double t); - double give_p_gws(double t); - - // post-processing, poi export - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); -}; -} // end namespace oofem -#endif // hemotkmat_h diff --git a/src/tm/lattice2d_mt.h b/src/tm/lattice2d_mt.h deleted file mode 100644 index e4ddeaa17..000000000 --- a/src/tm/lattice2d_mt.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef lattice2d_mt_h -#define lattice2d_mt_h - -#include "latticetransportelement.h" -#include "spatiallocalizer.h" - -///@name Input fields for Lattice2d_mt -//@{ -#define _IFT_Lattice2d_mt_Name "latticemt2d" -#define _IFT_Lattice2DMT_dim "dim" -#define _IFT_Lattice2DMT_thick "thick" -#define _IFT_Lattice2DMT_width "width" -#define _IFT_Lattice2DMT_gpcoords "gpcoords" -#define _IFT_Lattice2DMT_crackwidth "crackwidth" -#define _IFT_Lattice2DMT_couplingflag "couplingflag" -#define _IFT_Lattice2DMT_couplingnumber "couplingnumber" -//@} - - -namespace oofem { -/** - * This class implements a 2-dimensional lattice mass transport element - */ - -class Lattice2d_mt : public LatticeTransportElement -{ -protected: - double area; - double length; - - int couplingFlag; - IntArray couplingNumbers; - FloatArray crackWidths; - FloatArray crackLengths; - - double dimension, width, thickness; - FloatArray gpCoords; - - double crackWidth; - -public: - // constructor - Lattice2d_mt(int, Domain *, ElementMode em = HeatTransferEM); - virtual ~Lattice2d_mt(); - - /** Computes the contribution to balance equation(s) due to internal sources */ - virtual void computeInternalSourceRhsVectorAt(FloatArray &answer, TimeStep *, ValueModeType mode); - virtual double computeVolumeAround(GaussPoint *); - - virtual int giveCouplingFlag(){ return this->couplingFlag;} - - virtual void giveCouplingNumbers(IntArray &numbers){ numbers = this->couplingNumbers;} - - virtual void giveCrackLengths(FloatArray &lengths){ lengths = this->crackLengths;} - - virtual void giveCrackWidths(FloatArray &widths){ widths = crackWidths;} - - - virtual int computeGlobalCoordinates(FloatArray &answer, const FloatArray &lcoords); - - virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords); - - virtual void computeConductivityMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep); - - virtual void computeCapacityMatrix(FloatMatrix &answer, TimeStep *tStep); - - virtual const char *giveInputRecordName() const { return _IFT_Lattice2d_mt_Name; } - virtual const char *giveClassName() const { return "Lattice2d_mtElement"; } - - virtual Element_Geometry_Type giveGeometryType() const { return EGT_line_1; } - - virtual double giveWidth() { return width; } - virtual int computeNumberOfDofs() { return 2; } - virtual void giveDofManDofIDMask(int inode, IntArray &) const; - virtual IRResultType initializeFrom(InputRecord *ir); - - virtual void updateInternalState(TimeStep *tStep); - -#ifdef __OOFEG - // Graphics output - virtual void drawYourself(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep); - virtual void drawRawCrossSections(oofegGraphicContext &gc, TimeStep *tStep); - virtual void giveCrossSectionCoordinates(FloatArray &coords); -#endif - -protected: - virtual void computeGaussPoints(); - - virtual void computeBmatrixAt(FloatMatrix &answer, const FloatArray &lcoords) { this->computeGradientMatrixAt(answer, lcoords); } - virtual void computeGradientMatrixAt(FloatMatrix &answer, const FloatArray &lcoords); - virtual void computeNmatrixAt(FloatMatrix &n, const FloatArray &); - - virtual double givePressure(); - - virtual double giveOldPressure(); - - virtual double giveMass(); - - - /* computes the submatrix of interpolation matrix cooresponding to single unknown. - */ - virtual void computeNSubMatrixAt(FloatMatrix &n, const FloatArray &); - - virtual double giveLength(); - - virtual double giveArea() { return width * thickness; } - - - virtual void giveGpCoordinates(FloatArray &coords); - - virtual double computeEdgeVolumeAround(GaussPoint *gp, int iEdge) { return 0; } - - virtual int giveApproxOrder(int unknownIndx) { return 1; } -}; -} // end namespace oofem -#endif diff --git a/src/tm/nlisomoisturemat.C b/src/tm/nlisomoisturemat.C deleted file mode 100644 index e82c7f748..000000000 --- a/src/tm/nlisomoisturemat.C +++ /dev/null @@ -1,424 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "nlisomoisturemat.h" -#include "gausspoint.h" -#include "mathfem.h" -#include "classfactory.h" - -namespace oofem { -REGISTER_Material(NlIsoMoistureMaterial); - -IRResultType -NlIsoMoistureMaterial :: initializeFrom(InputRecord *ir) -{ - IRResultType result; // Required by IR_GIVE_FIELD macro - - int type = 0; - IR_GIVE_FIELD(ir, type, _IFT_NlIsoMoistureMaterial_isothermtype); - - if ( type >= 7 ) { - OOFEM_WARNING("isothermType must be equal to 0, 1, 2 ... 6"); - return IRRT_BAD_FORMAT; - } - - this->Isotherm = ( isothermType ) type; - - IR_GIVE_FIELD ( ir, type, _IFT_NlIsoMoistureMaterial_permeabilitytype ); - - if ( type >= 4 ) { - OOFEM_ERROR ( "permeabilityType must be equal to 0, 1, 2, 3" ); - } - - this->Permeability = ( permeabilityType ) type; - - if (Permeability == KunzelPerm) { - IR_GIVE_FIELD ( ir, type, _IFT_NlIsoMoistureMaterial_capillarytransporttype ); - this->CapillaryTransport = ( capillaryTransportType ) type; - if ( type >= 3 ) { - OOFEM_ERROR ( "capillaryTransportType must be equal to 0, 1, 2" ); - } - } - - if ( this->Isotherm == linear ) { // linear isotherm = type 0 - IR_GIVE_FIELD(ir, moistureCapacity, _IFT_NlIsoMoistureMaterial_capa); - } else if ( this->Isotherm == multilinear ) { // multilinear isotherm = type 1 - IR_GIVE_FIELD(ir, iso_h, _IFT_NlIsoMoistureMaterial_iso_h); - IR_GIVE_FIELD(ir, iso_wh, _IFT_NlIsoMoistureMaterial_iso_wh); - - if ( iso_h.giveSize() != iso_wh.giveSize() ) { - OOFEM_WARNING("the size of 'iso_h' and 'iso_w(h)' must be the same"); - return IRRT_BAD_FORMAT; - } - - for ( int i = 1; i < iso_h.giveSize(); i++ ) { - if ( ( iso_h.at(i) < 0. ) || ( iso_h.at(i) > 1. ) ) { - OOFEM_WARNING("iso_h must be in the range <0; 1>"); - return IRRT_BAD_FORMAT; - } - } - } else if ( this->Isotherm == Ricken ) { // reference mentioned in Kuenzel isotherm = type 2 - IR_GIVE_FIELD(ir, dd, _IFT_NlIsoMoistureMaterial_dd); - } else if ( this->Isotherm == Kuenzel ) { // isotherm = type 3 - IR_GIVE_FIELD(ir, wf, _IFT_NlIsoMoistureMaterial_wf); - IR_GIVE_FIELD(ir, b, _IFT_NlIsoMoistureMaterial_b); - } else if ( this->Isotherm == Hansen ) { // isotherm = type 4 - IR_GIVE_FIELD(ir, uh, _IFT_NlIsoMoistureMaterial_uh); - IR_GIVE_FIELD(ir, A, _IFT_NlIsoMoistureMaterial_a); - IR_GIVE_FIELD(ir, nn, _IFT_NlIsoMoistureMaterial_nn); - IR_GIVE_FIELD(ir, rhodry, _IFT_NlIsoMoistureMaterial_rhodry); - } else if ( this->Isotherm == BSB ) { // isotherm = type 5 - IR_GIVE_FIELD(ir, c, _IFT_NlIsoMoistureMaterial_c); - IR_GIVE_FIELD(ir, k, _IFT_NlIsoMoistureMaterial_k); - IR_GIVE_FIELD(ir, Vm, _IFT_NlIsoMoistureMaterial_vm); - IR_GIVE_FIELD(ir, rhodry, _IFT_NlIsoMoistureMaterial_rhodry); - } else if ( this->Isotherm == bilinear ) { // bilinear isotherm = type 6 - IR_GIVE_FIELD ( ir, moistureCapacity, _IFT_NlIsoMoistureMaterial_capa ); - IR_GIVE_FIELD ( ir, wf, _IFT_NlIsoMoistureMaterial_wf ); - IR_GIVE_FIELD ( ir, hx, _IFT_NlIsoMoistureMaterial_hx ); - IR_GIVE_FIELD ( ir, dx, _IFT_NlIsoMoistureMaterial_dx ); - - this->iso_offset = 0.; - IR_GIVE_OPTIONAL_FIELD ( ir, iso_offset, _IFT_NlIsoMoistureMaterial_iso_offset ); - - this->capa2 = (wf-hx*moistureCapacity-iso_offset)/(1-hx); - double wa = (hx-dx)*moistureCapacity + iso_offset; - double wb = hx*moistureCapacity + dx*capa2 + iso_offset; - - this->c1 = (moistureCapacity*(2*dx)+capa2*(2*dx)+2*wa-2*wb)/(8*dx*dx*dx); - this->c2 = (-3*c1*(2*dx)*(2*dx)-moistureCapacity+capa2)/(2*(2*dx)); - } else { - OOFEM_ERROR("unknown isotherm type"); - } - - if ( this->Permeability == multilin ) { - IR_GIVE_FIELD(ir, perm_h, _IFT_NlIsoMoistureMaterial_perm_h); - IR_GIVE_FIELD(ir, perm_ch, _IFT_NlIsoMoistureMaterial_perm_ch); - - if ( perm_h.giveSize() != perm_ch.giveSize() ) { - OOFEM_WARNING("the size of 'perm_h' and 'perm_c(h)' must be the same"); - return IRRT_BAD_FORMAT; - } - - for ( int i = 1; i < perm_h.giveSize(); i++ ) { - if ( ( perm_h.at(i) < 0. ) || ( perm_h.at(i) > 1. ) ) { - OOFEM_WARNING("perm_h must be in the range <0; 1>"); - return IRRT_BAD_FORMAT; - } - } - } else if ( this->Permeability == Bazant ) { - IR_GIVE_FIELD(ir, C1, _IFT_NlIsoMoistureMaterial_c1); - IR_GIVE_FIELD(ir, n, _IFT_NlIsoMoistureMaterial_n); - IR_GIVE_FIELD(ir, alpha0, _IFT_NlIsoMoistureMaterial_alpha0); - IR_GIVE_FIELD(ir, hC, _IFT_NlIsoMoistureMaterial_hc); - } else if ( this->Permeability == Xi ) { - IR_GIVE_FIELD(ir, alphah, _IFT_NlIsoMoistureMaterial_alphah); - IR_GIVE_FIELD(ir, betah, _IFT_NlIsoMoistureMaterial_betah); - IR_GIVE_FIELD(ir, gammah, _IFT_NlIsoMoistureMaterial_gammah); - } else if ( this->Permeability == KunzelPerm ) { - - // compute vapor diffusion coefficient in air [kg m^-1 s^-1 Pa^-1] - double delta; - double PL; // ambient atmospheric pressure [Pa] - double mu; // water vapor diffusion resistance [-] - double T; // temperature [K] - - PL = 101325.; - IR_GIVE_OPTIONAL_FIELD(ir, PL, _IFT_NlIsoMoistureMaterial_pl); - IR_GIVE_FIELD(ir, mu, _IFT_NlIsoMoistureMaterial_mu); - IR_GIVE_FIELD(ir, T, _IFT_NlIsoMoistureMaterial_t); - - double timeScale = 1.; // = 1 for analysis in seconds, = 86400 for analysis in days, etc. - IR_GIVE_OPTIONAL_FIELD(ir, timeScale, _IFT_NlIsoMoistureMaterial_timescale); - delta = timeScale * 2.0 * 1.e-7 * pow(T,0.81) / PL; - - this->deltap = delta / mu; - - // compute saturation water vapor pressure - double T0, a; - double T_C = T - 273.15; - - if (T_C < 0.) { - a = 22.44; - T0 = 272.44; - } else { - a = 17.08; - T0 = 234.18; - } - this->p_sat = 611. * exp( a * T_C / (T0 + T_C) ); - - - if (CapillaryTransport == Multilin_h) { - IR_GIVE_FIELD ( ir, capPerm_h, _IFT_NlIsoMoistureMaterial_capperm_h ); - IR_GIVE_FIELD ( ir, capPerm_Dwh, _IFT_NlIsoMoistureMaterial_capperm_dwh ); - - if ( ! ( capPerm_h.giveSize() == capPerm_Dwh.giveSize() ) ) - OOFEM_ERROR ( "size of 'capPerm_h' and 'capPerm_dw(h)' must be the same" ); - - for ( int i = 1; i < capPerm_h.giveSize(); i++ ) { - if ( ( capPerm_h.at ( i ) < 0. ) || ( capPerm_h.at ( i ) > 1. ) ) - OOFEM_ERROR ( "capPerm_h must be in the range <0; 1>" ); - } - - } else if (this->CapillaryTransport == Multilin_wV) { - - rhoH2O = 1000.; - IR_GIVE_OPTIONAL_FIELD(ir, rhoH2O, _IFT_NlIsoMoistureMaterial_rhoh2o); - - IR_GIVE_FIELD ( ir, capPerm_wV, _IFT_NlIsoMoistureMaterial_capperm_wv ); - IR_GIVE_FIELD ( ir, capPerm_DwwV, _IFT_NlIsoMoistureMaterial_capperm_dwwv ); - - if ( ! ( capPerm_wV.giveSize() == capPerm_DwwV.giveSize() ) ) - OOFEM_ERROR ( "size of 'capPerm_wV' and 'capPerm_Dw(wV)' must be the same" ); - - for ( int i = 1; i < capPerm_wV.giveSize(); i++ ) { - if ( ( capPerm_wV.at ( i ) < 0. ) || ( capPerm_wV.at ( i ) > 1. ) ) - OOFEM_ERROR ( "capPerm_wv must be in the range <0; 1>" ); - } - - } else { // according to Kunzel - - if ( this->Isotherm == Hansen ) { - this->wf = rhodry*uh; - } else { - IR_GIVE_FIELD ( ir, wf, _IFT_NlIsoMoistureMaterial_wf ); - } - IR_GIVE_FIELD ( ir, Abs, _IFT_NlIsoMoistureMaterial_abs ); - } - - } else { - OOFEM_ERROR("unknown permeability type"); - } - - wn=0.; - IR_GIVE_OPTIONAL_FIELD(ir, wn, _IFT_NlIsoMoistureMaterial_wn); - IR_GIVE_OPTIONAL_FIELD(ir, alpha, _IFT_NlIsoMoistureMaterial_alpha); - - - return IsotropicMoistureTransferMaterial :: initializeFrom(ir); -} - -double -NlIsoMoistureMaterial :: giveMoistureCapacity(GaussPoint *gp, TimeStep *tStep) -{ - double humidity = this->giveHumidity(gp, VM_Total); - - if ( this->Isotherm == linear ) { - return moistureCapacity; - } else if ( this->Isotherm == multilinear ) { - double tol = 1.e-10; - for ( int i = 2; i <= iso_h.giveSize(); i++ ) { - if ( ( humidity - iso_h.at(i) ) < tol ) { - return ( iso_wh.at(i) - iso_wh.at(i - 1) ) / ( iso_h.at(i) - iso_h.at(i - 1) ); - } - } - } else if ( this->Isotherm == Ricken ) { - return 1. / ( dd * ( 1. - humidity ) ); - } else if ( this->Isotherm == Kuenzel ) { - return wf * ( b - 1. ) * b / ( ( b - humidity ) * ( b - humidity ) ); - } else if ( this->Isotherm == Hansen ) { - return rhodry * uh / ( A * nn * humidity * pow( ( 1 - log(humidity) / A ), ( 1 / nn + 1 ) ) ); - } else if ( this->Isotherm == BSB ) { - double nominator, denominator; - nominator = c * k * Vm * rhodry * ( 1. + k * k * humidity * humidity * c - k * k * humidity * humidity ); - denominator = ( 1. - k * humidity ) * ( 1. - k * humidity ) * ( 1. + ( c - 1. ) * k * humidity ) * ( 1. + ( c - 1. ) * k * humidity ); - return nominator / denominator; - } else if ( this->Isotherm == bilinear ) { - if( humidity <= (hx-dx) ) { - return moistureCapacity; - } else if (humidity >= (hx + dx) ) { - return capa2; - } else { - return moistureCapacity + 2*c2*(humidity-hx+dx) + 3*c1*pow(humidity-hx+dx,2); - } - } else { - OOFEM_ERROR("unknown isotherm type"); - } - - return 0.; -} - -double -NlIsoMoistureMaterial :: giveMoistureContent(double humidity) -{ - if ( this->Isotherm == linear ) { - return moistureCapacity*humidity; - - } else if ( this->Isotherm == multilinear ) { - double tol = 1.e-10; - for (int i = 1; i <= iso_h.giveSize(); i++) { - if ( ( humidity - iso_h.at(i) ) < tol ) { - return iso_wh.at(i-1) + (iso_wh.at(i)-iso_wh.at(i-1))/(iso_h.at(i)-iso_h.at(i-1)) * (humidity-iso_h.at(i-1)) ; - } - } - - } else if ( this->Isotherm == Ricken ) { - return wf - log(1.-humidity)/dd ; - - } else if ( this->Isotherm == Kuenzel ) { - return wf * (b-1.) * humidity / (b-humidity); - - } else if ( this->Isotherm == Hansen ) { - return rhodry*uh * pow( (1.-log(humidity)/A), (-1./nn) ) ; - - } else if ( this->Isotherm == BSB ) { - return rhodry*c*k*Vm*humidity/( (1.-k*humidity) * (c-1.)*k*humidity ); - - } else if ( this->Isotherm == bilinear ) { - - if( humidity <= (hx-dx) ) { - return moistureCapacity*humidity + iso_offset; - - } else if (humidity >= (hx + dx) ) { - return hx*moistureCapacity + (humidity-hx)*capa2 + iso_offset; - - } else { - return (hx-dx)*moistureCapacity + moistureCapacity*(humidity-hx+dx) + c2 * pow(humidity-hx+dx,2) + c1 * pow(humidity-hx+dx,3) + iso_offset; - } - - } else { - OOFEM_ERROR("unknown isotherm type"); - } - - return 0.; -} - -double -NlIsoMoistureMaterial :: givePermeability(GaussPoint *gp, TimeStep *tStep) -{ - double permeability = 0.; - double humidity = this->giveHumidity(gp, VM_Total); - - if ( this->Permeability == multilin ) { - double tol = 1.e-10; - for ( int i = 1; i <= perm_h.giveSize(); i++ ) { - if ( ( humidity - perm_h.at(i) ) < tol ) { - permeability = perm_ch.at(i - 1) + ( perm_ch.at(i) - perm_ch.at(i - 1) ) * ( humidity - perm_h.at(i - 1) ) / ( perm_h.at(i) - perm_h.at(i - 1) ); - break; - } - } - } else if ( this->Permeability == Bazant ) { - permeability = C1 * ( alpha0 + ( 1. - alpha0 ) / ( 1. + pow( ( 1. - humidity ) / ( 1. - hC ), n ) ) ); - } else if ( this->Permeability == Xi ) { - double power = pow( 10., gammah * ( humidity - 1. ) ); - permeability = alphah + betah * ( 1. - pow(2., -power) ); - } else if (this->Permeability == KunzelPerm) { - - double dw_dh; //[kg/m^3] - double Dw; // capillary transport coefficient [m^2/s] - - dw_dh = this->giveMoistureCapacity(gp, tStep); - Dw = this->computeCapTranspCoeff(humidity); - - permeability = Dw * dw_dh + deltap * p_sat; - - } else { - OOFEM_ERROR("unknown permeability type"); - } - - return permeability; -} - - -double -NlIsoMoistureMaterial :: computeCapTranspCoeff(double humidity) -{ - double Dw = 0.; - - if ( this->CapillaryTransport == Multilin_h ) { - double tol = 1.e-10; - for (int i = 1; i <= capPerm_h.giveSize(); i++) { - if ((humidity - capPerm_h.at(i))CapillaryTransport == Multilin_wV ) { - double wV = this->giveMoistureContent(humidity) / rhoH2O; - double tol = 1.e-10; - for (int i = 1; i <= capPerm_wV.giveSize(); i++) { - if ((wV - capPerm_wV.at(i))CapillaryTransport == KunzelCT ){ - double w; - w = this->giveMoistureContent(humidity); - Dw = 3.8 * (Abs/wf)*(Abs/wf) * pow(1000., w/wf -1.); - - } else { - OOFEM_ERROR("unknown capillary transport type"); - } - - return Dw; -} - - -double -NlIsoMoistureMaterial :: giveHumidity(GaussPoint *gp, ValueModeType mode) -{ - const FloatArray &tempState = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) )->giveTempField(); - if ( ( tempState.at(1) > 1.0 ) || ( tempState.at(1) < 0.0 ) ) { - OOFEM_ERROR("Relative humidity %.3f is out of range", tempState.at(1) ); - return 0.0; - } else { - return tempState.at(1); - } -} - -int -NlIsoMoistureMaterial :: hasInternalSource() -{ - if (this->wn !=0.){ - return 1; - } -return 0; -} - -void -NlIsoMoistureMaterial :: computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) -{ - val.resize(1); - if (( mode == VM_Total) || (mode == VM_TotalIntrinsic)) { - val.at(1) = -wn*(this->alpha.eval( {{ "t", tStep->giveTargetTime() }}, this->giveDomain() ) - this->alpha.eval( {{ "t", tStep->giveTargetTime()-tStep->giveTimeIncrement()}} , this->giveDomain() ) ) / tStep->giveTimeIncrement(); - } else { - OOFEM_ERROR("Undefined mode %s\n", __ValueModeTypeToString(mode) ); - } -} - - -} // end namespace oofem diff --git a/src/tm/simpletransportcrosssection.C b/src/tm/simpletransportcrosssection.C index 711253f93..aaefa008c 100644 --- a/src/tm/simpletransportcrosssection.C +++ b/src/tm/simpletransportcrosssection.C @@ -33,7 +33,7 @@ */ #include "simpletransportcrosssection.h" -#include "transportmaterial.h" +#include "tm/Materials/transportmaterial.h" #include "dynamicinputrecord.h" #include "classfactory.h" @@ -42,23 +42,24 @@ REGISTER_CrossSection(SimpleTransportCrossSection); SimpleTransportCrossSection :: SimpleTransportCrossSection(int n, Domain *d) : TransportCrossSection(n, d) { } -SimpleTransportCrossSection :: ~SimpleTransportCrossSection() { } - -IRResultType -SimpleTransportCrossSection :: initializeFrom(InputRecord *ir) +void +SimpleTransportCrossSection :: initializeFrom(InputRecord &ir) { - IRResultType result; // Required by IR_GIVE_FIELD macro + TransportCrossSection :: initializeFrom(ir); IR_GIVE_FIELD(ir, this->matNumber, _IFT_SimpleTransportCrossSection_material); this->propertyDictionary.clear(); - if ( ir->hasField(_IFT_SimpleTransportCrossSection_thickness) ) { + if ( ir.hasField(_IFT_SimpleTransportCrossSection_thickness) ) { double thickness; IR_GIVE_FIELD(ir, thickness, _IFT_SimpleTransportCrossSection_thickness); this->propertyDictionary.add(CS_Thickness, thickness); } - - return TransportCrossSection :: initializeFrom(ir); + double area = 0.0; + if ( ir.hasField(_IFT_SimpleTransportCrossSection_area) ) { + IR_GIVE_FIELD(ir, area, _IFT_SimpleTransportCrossSection_area); + } + propertyDictionary.add(CS_Area, area); } @@ -83,13 +84,13 @@ SimpleTransportCrossSection :: checkConsistency() TransportMaterial * -SimpleTransportCrossSection :: giveMaterial() +SimpleTransportCrossSection :: giveMaterial() const { return dynamic_cast< TransportMaterial * >( this->domain->giveMaterial(this->matNumber) ); } Material * -SimpleTransportCrossSection :: giveMaterial(IntegrationPoint *ip) +SimpleTransportCrossSection :: giveMaterial(IntegrationPoint *ip) const { return this->domain->giveMaterial(this->matNumber); } @@ -103,7 +104,7 @@ SimpleTransportCrossSection :: giveIPValue(FloatArray &answer, GaussPoint *ip, I bool -SimpleTransportCrossSection :: isCharacteristicMtrxSymmetric(MatResponseMode rMode) +SimpleTransportCrossSection :: isCharacteristicMtrxSymmetric(MatResponseMode rMode) const { return this->domain->giveMaterial(this->matNumber)->isCharacteristicMtrxSymmetric(rMode); } diff --git a/src/tm/simpletransportcrosssection.h b/src/tm/simpletransportcrosssection.h index 82dfb7a8c..9dbbd3309 100644 --- a/src/tm/simpletransportcrosssection.h +++ b/src/tm/simpletransportcrosssection.h @@ -40,6 +40,9 @@ #define _IFT_SimpleTransportCrossSection_Name "simpletransportcs" #define _IFT_SimpleTransportCrossSection_material "mat" #define _IFT_SimpleTransportCrossSection_thickness "thickness" +#define _IFT_SimpleTransportCrossSection_area "area" + + namespace oofem { class TransportMaterial; @@ -53,8 +56,8 @@ class TransportMaterial; class OOFEM_EXPORT SimpleTransportCrossSection : public TransportCrossSection { protected: - int matNumber; - double thickness; + int matNumber = 0; + double thickness = 0.; public: /** @@ -63,27 +66,25 @@ class OOFEM_EXPORT SimpleTransportCrossSection : public TransportCrossSection * @param d Domain for cross section. */ SimpleTransportCrossSection(int n, Domain * d); - /// Destructor. - virtual ~SimpleTransportCrossSection(); - virtual IRResultType initializeFrom(InputRecord *ir); - virtual void giveInputRecord(DynamicInputRecord &input); + void initializeFrom(InputRecord &ir) override; + void giveInputRecord(DynamicInputRecord &input) override; /// Temporary function that hands out the material. Must be removed for future layered support, but input files will still look the same. - virtual TransportMaterial *giveMaterial(); - virtual Material *giveMaterial(IntegrationPoint *ip); + TransportMaterial *giveMaterial() const override; + Material *giveMaterial(IntegrationPoint *ip) const override; - virtual bool isCharacteristicMtrxSymmetric(MatResponseMode rMode); - virtual int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep); + bool isCharacteristicMtrxSymmetric(MatResponseMode rMode) const override; + int giveIPValue(FloatArray &answer, GaussPoint *ip, InternalStateType type, TimeStep *tStep) override; - virtual int checkConsistency(); + int checkConsistency() override; - virtual int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp); - virtual int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp); - virtual int estimatePackSize(DataStream &buff, GaussPoint *gp); + int packUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) override; + int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep, GaussPoint *gp) override; + int estimatePackSize(DataStream &buff, GaussPoint *gp) override; - virtual const char *giveClassName() const { return "SimpleTransportCrossSection"; } - virtual const char *giveInputRecordName() const { return _IFT_SimpleTransportCrossSection_Name; } + const char *giveClassName() const override { return "SimpleTransportCrossSection"; } + const char *giveInputRecordName() const override { return _IFT_SimpleTransportCrossSection_Name; } }; } // end namespace oofem #endif // simpletransportcrosssection_h diff --git a/src/tm/transportcrosssection.h b/src/tm/transportcrosssection.h index 8a2306ff4..9e42d76b8 100644 --- a/src/tm/transportcrosssection.h +++ b/src/tm/transportcrosssection.h @@ -56,11 +56,8 @@ class OOFEM_EXPORT TransportCrossSection : public CrossSection */ TransportCrossSection(int n, Domain * d) : CrossSection(n, d) { } - /// Destructor. - virtual ~TransportCrossSection() { } - /// @todo Temporary function that hands out the material. Must be removed for future layered support, but input files will still look the same. - virtual TransportMaterial *giveMaterial() = 0; + virtual TransportMaterial *giveMaterial() const = 0; }; } // end namespace oofem #endif // transportcrosssection_h diff --git a/src/tm/transportmaterial.C b/src/tm/transportmaterial.C deleted file mode 100644 index 086858b0d..000000000 --- a/src/tm/transportmaterial.C +++ /dev/null @@ -1,213 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "transportmaterial.h" -#include "gausspoint.h" -#include "contextioerr.h" - -namespace oofem { -void -TransportMaterialStatus :: setTempGradient(FloatArray grad) -{ - this->temp_gradient = std :: move(grad); -} - -void -TransportMaterialStatus :: setTempField(FloatArray newField) -{ - this->temp_field = std :: move(newField); -} - -void -TransportMaterialStatus :: setTempFlux(FloatArray w) -{ - this->temp_flux = std :: move(w); -} - -void -TransportMaterial :: updateInternalState(const FloatArray &stateVec, GaussPoint *gp, TimeStep *) -{ - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - if ( ms ) { - ms->letTempStateVectorBe(stateVec); - } -} - - -TransportMaterialStatus :: TransportMaterialStatus(int n, Domain *d, GaussPoint *g) : - MaterialStatus(n, d, g), temp_field(), temp_gradient(), temp_flux(), field(), gradient(), flux(), maturity(0.) -{ } - -void TransportMaterialStatus :: printOutputAt(FILE *File, TimeStep *tStep) -// Print the state variable and the flow vector on the data file. -{ - FloatArray flowVec; - TransportElement *transpElem = static_cast< TransportElement * >( gp->giveElement() ); - - MaterialStatus :: printOutputAt(File, tStep); - - fprintf(File, " state"); - - for ( auto &val : field ) { - fprintf( File, " %.4e", val ); - } - - transpElem->computeFlow(flowVec, gp, tStep); - - fprintf(File, " flow"); - for ( auto &flow : flowVec ) { - fprintf( File, " %.4e", flow ); - } - - fprintf(File, "\n"); -} - - -void -TransportMaterialStatus :: updateYourself(TimeStep *tStep) -// Performs end-of-step updates. -{ - MaterialStatus :: updateYourself(tStep); - gradient = temp_gradient; - field = temp_field; - flux = temp_flux; -} - - -void -TransportMaterialStatus :: initTempStatus() -// -// initialize record at the beginning of new load step -// -{ - MaterialStatus :: initTempStatus(); - temp_gradient = gradient; - temp_field = field; - temp_flux = flux; -} - - -contextIOResultType -TransportMaterialStatus :: saveContext(DataStream &stream, ContextMode mode, void *obj) -// -// saves full ms context (saves state variables, that completely describe -// current state) -{ - contextIOResultType iores; - - if ( ( iores = MaterialStatus :: saveContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = gradient.storeYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = field.storeYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = flux.storeYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; -} - - -contextIOResultType -TransportMaterialStatus :: restoreContext(DataStream &stream, ContextMode mode, void *obj) -// -// restores full material context (saves state variables, that completely describe -// current state) -// -{ - contextIOResultType iores; - - if ( ( iores = MaterialStatus :: restoreContext(stream, mode, obj) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - if ( ( iores = gradient.restoreYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( ( iores = field.restoreYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - if ( ( iores = flux.restoreYourself(stream) ) != CIO_OK ) { - THROW_CIOERR(iores); - } - - return CIO_OK; -} - - -int -TransportMaterial :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) -// IST_Humidity must be overriden! -{ - TransportMaterialStatus *ms = static_cast< TransportMaterialStatus * >( this->giveStatus(gp) ); - if ( type == IST_Temperature || type == IST_MassConcentration_1 || type == IST_Humidity ) { - const FloatArray &vec = ms->giveField(); -// answer = FloatArray{vec.at( ( type == IST_Temperature ) ? 1 : 2 ) }; - answer = FloatArray{vec.at( 1 ) }; - return 1; - } else if ( type == IST_TemperatureFlow ) { - TransportElement *transpElem = static_cast< TransportElement * >( gp->giveElement() ); - transpElem->computeFlow(answer, gp, tStep); - return 1; - } else if ( type == IST_Velocity ) { ///@todo Shouldn't be named velocity.. instead, "MassFlow" or something suitable like that. - answer = ms->giveFlux(); - answer.resizeWithValues(3); - return 1; - } else if ( type == IST_PressureGradient ) { - answer = ms->giveGradient(); - answer.resizeWithValues(3); - return 1; - } else if ( type == IST_Density ) { - answer = FloatArray{ this->give('d', gp) }; - return 1; - } else if ( type == IST_HeatCapacity ) { - answer = FloatArray{ this->give('c', gp) }; - return 1; - } else if ( type == IST_ThermalConductivityIsotropic ) { - answer = FloatArray{ this->give('k', gp) }; - return 1; - } else if ( type == IST_Maturity ) { - answer = FloatArray{ ms->giveMaturity() }; - return 1; - } - return Material :: giveIPValue(answer, gp, type, tStep); -} -} // end namespace oofem diff --git a/src/tm/transportmaterial.h b/src/tm/transportmaterial.h deleted file mode 100644 index 7f6ac85e3..000000000 --- a/src/tm/transportmaterial.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * - * ##### ##### ###### ###### ### ### - * ## ## ## ## ## ## ## ### ## - * ## ## ## ## #### #### ## # ## - * ## ## ## ## ## ## ## ## - * ## ## ## ## ## ## ## ## - * ##### ##### ## ###### ## ## - * - * - * OOFEM : Object Oriented Finite Element Code - * - * Copyright (C) 1993 - 2013 Borek Patzak - * - * - * - * Czech Technical University, Faculty of Civil Engineering, - * Department of Structural Mechanics, 166 29 Prague, Czech Republic - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef transportmaterial_h -#define transportmaterial_h - -#include "material.h" -#include "floatarray.h" -#include "floatmatrix.h" -#include "matconst.h" -#include "matstatus.h" -#include "transportelement.h" - -namespace oofem { -/** - * This class implements a transport material status information. - * When needed, new materials should specialized a derived class from this base. - * It is attribute of a Gauss point. - * - * @see MaterialStatus For general description of material status, and its role. - */ -class TransportMaterialStatus : public MaterialStatus -{ -protected: - FloatArray temp_field; ///< Vector containing the last used field. - FloatArray temp_gradient; ///< Vector containing the last used gradient. - FloatArray temp_flux; ///< Vector containing the last computed flux. - - FloatArray field; ///< Vector containing the last equilibrated field. The physical meaning corresponds to temperature, concentration etc. - FloatArray gradient; ///< Vector containing the last equilibrated gradient. It is the spatial gradient of the field. - FloatArray flux; ///< Vector containing the last equilibrated flux. The physical meaning corresponds to energy flux, mass flow, etc. - - /// A scalar containing maturity (integration of temperature over time) - double maturity; - -public: - /// Constructor - creates new TransportMaterialStatus with number n, belonging to domain d and IntegrationPoint g. - TransportMaterialStatus(int n, Domain * d, GaussPoint * g); - /// Destructor - virtual ~TransportMaterialStatus() { } - - virtual void printOutputAt(FILE *file, TimeStep *tStep); - - virtual void initTempStatus(); - virtual void updateYourself(TimeStep *tStep); - - virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj = NULL); - virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj = NULL); - - ///@todo REMOVE THESE: - /// Assigns temporary state vector from a given vector v. - void letTempStateVectorBe(FloatArray v) { temp_field = std :: move(v); } - - virtual const char *giveClassName() const { return "TransportMaterialStatus"; } - - /// Set gradient. - void setTempGradient(FloatArray grad); - /// Set field. - void setTempField(FloatArray newField); - /// Set flux. - void setTempFlux(FloatArray w); - - /// Return last gradient. - const FloatArray &giveGradient() { return gradient; } - /// Return last field. - const FloatArray &giveField() { return field; } - /// Returns last flux. - const FloatArray &giveFlux() { return flux; } - - /// Return last gradient. - const FloatArray &giveTempGradient() { return temp_gradient; } - /// Return last field. - const FloatArray &giveTempField() { return temp_field; } - /// Returns last flux. - const FloatArray &giveTempFlux() { return temp_flux; } - /// Returns maturity. - double giveMaturity() { return maturity; } -}; - - -/** - * Abstract base class for all constitutive models for transport problems. It declares common services provided - * by all structural material models. The implementation of these services is partly left on derived classes, - * which will implement constitutive model dependent part. - * Some general purpose services are implemented on this level. For details, how to store - * material model related history variables in integration points, see base class @ref Material documentation. - */ -class TransportMaterial : public Material -{ -public: - /** - * Constructor. Creates material with given number, belonging to given domain. - * @param n Material number. - * @param d Domain to which new material will belong. - */ - TransportMaterial(int n, Domain * d) : Material(n, d) { } - /// Destructor. - virtual ~TransportMaterial() { } - - /** - * Returns the flux for the field and its gradient. - * @todo { Should the field variable just be a scalar? This might change when we rethink the coupled-fields approach. - * Now its either just [temperature], or [temperature, concentration] so to cover both cases there is a floatarray. } - * @param answer The flux. - * @param gp Gauss point. - * @param grad Gradient of the primary field, usually the main input. - * @param field The value of the field itself. - * @param tStep Active time step. - */ - virtual void giveFluxVector(FloatArray &answer, GaussPoint *gp, const FloatArray &grad, const FloatArray &field, TimeStep *tStep) = 0; - - /** - * Computes characteristic matrix of receiver in given integration point. - * The algorithm should use temporary or equilibrium history variables stored in integration point status - * to compute and return required result. - * @param answer Contains result. - * @param mode Material response mode. - * @param gp Integration point. - * @param tStep Time step (most models are able to respond only when tStep is current time step). - */ - virtual void giveCharacteristicMatrix(FloatMatrix &answer, - MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) = 0; - - /** - * Computes the characteristic value of receiver in given integration point, respecting its history. - * The algorithm should use temporary or equilibrium history variables stored in integration point status - * to compute and return required result. - * @param mode Material response mode. - * @param gp Integration point. - * @param tStep Time step (most models are able to respond only when tStep is current time step). - */ - virtual double giveCharacteristicValue(MatResponseMode mode, - GaussPoint *gp, - TimeStep *tStep) = 0; - - /** - * Updates internal state of material according to new state vector. - * @param state New state vector. - * @param gp Integration point. - * @param tStep Solution step. - */ - virtual void updateInternalState(const FloatArray &state, GaussPoint *gp, TimeStep *tStep); - - /** - * Returns nonzero if receiver generates internal source of state variable(s), zero otherwise. - */ - virtual int hasInternalSource() { return 0; } - /** - * Computes the internal source vector of receiver. - * @param val Contains response. - * @param gp Integration point. - * @param tStep Solution step. - * @param mode Determines response mode. - */ - virtual void computeInternalSourceVector(FloatArray &val, GaussPoint *gp, TimeStep *tStep, ValueModeType mode) - { val.clear(); } - /** - * Returns positive value of humidity if implemented and enabled in derived material, -1 otherwise. - */ - virtual double giveHumidity(GaussPoint *gp, ValueModeType mode) { return -1.0; } - - // post-processing - virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep); - - virtual MaterialStatus *CreateStatus(GaussPoint *gp) const { return new TransportMaterialStatus(1, domain, gp); } -}; -} // end namespace oofem -#endif // transportmaterial_h diff --git a/tests/benchmark/sm/tr2shell7XFEM_CZ.in b/tests/benchmark/obsolete/tr2shell7XFEM_CZ.in similarity index 100% rename from tests/benchmark/sm/tr2shell7XFEM_CZ.in rename to tests/benchmark/obsolete/tr2shell7XFEM_CZ.in diff --git a/tests/benchmark/sm/concrete_3point.in b/tests/benchmark/sm/concrete_3point.in index 250005537..0bc842f4d 100644 --- a/tests/benchmark/sm/concrete_3point.in +++ b/tests/benchmark/sm/concrete_3point.in @@ -1,6 +1,5 @@ concrete_3point.out Test: 3-point bending, triangular elements, 1 loaded point -#NonLinearStatic nsteps 20 stepLength 0.025 rtolf 1e-4 Psi 0.0 MaxIter 200 reqIterations 80 HPC 2 1 2 stiffmode 1 nmodules 1 StaticStructural nsteps 20 solverType "calm" stepLength 0.025 rtolf 1e-4 Psi 0.0 MaxIter 200 reqIterations 80 HPC 2 1 2 stiffmode 1 nmodules 1 errorcheck domain 2dPlaneStress diff --git a/tests/benchmark/sm/eigendyn_cct.in b/tests/benchmark/sm/eigendyn_cct.in index 50d9387c9..785934b9c 100644 --- a/tests/benchmark/sm/eigendyn_cct.in +++ b/tests/benchmark/sm/eigendyn_cct.in @@ -1157,14 +1157,14 @@ CCTPlate 717 nodes 3 398 399 388 CCTPlate 718 nodes 3 388 399 389 CCTPlate 719 nodes 3 399 400 389 CCTPlate 720 nodes 3 389 400 390 -SimpleCS 1 thick 1.0 material 1 set 1 -#HMH 1 Ry 4.0 -IsoLE 1 d 2500. E 30.e9 n 0.15 tAlpha 0.000012 -BoundaryCondition 1 loadTimeFunction 1 dofs 2 3 4 values 2 0. 0. set 2 -ConstantFunction 1 f(t) 1.0 Set 1 elementranges {(1 720)} Set 2 nodes 16 1 2 3 5 7 8 11 12 390 400 409 416 423 427 430 432 # +SimpleCS 1 thick 1.0 material 1 set 1 +#HMH 1 Ry 4.0 +IsoLE 1 d 2500. E 30.e9 n 0.15 tAlpha 0.000012 +BoundaryCondition 1 loadTimeFunction 1 dofs 2 3 4 values 2 0. 0. set 2 +ConstantFunction 1 f(t) 1.0 # #%BEGIN_CHECK% tolerance 1.e-4 ## check eigen values diff --git a/tests/benchmark/sm/frcfcmnl_tension.in b/tests/benchmark/sm/frcfcmnl_tension.in index b3e69bf23..e9f547ac7 100644 --- a/tests/benchmark/sm/frcfcmnl_tension.in +++ b/tests/benchmark/sm/frcfcmnl_tension.in @@ -1,7 +1,7 @@ frcfcmnl_tension.out tension of one row finite elements with nonuniform width # -NonLinearStatic nsteps 231 rtolf 1e-6 MaxIter 10000 stiffmode 1 controlmode 1 renumber 1 manrmsteps 20 nmodules 1 +NonLinearStatic nsteps 200 rtolf 1e-6 MaxIter 10000 stiffmode 1 controlmode 1 renumber 1 manrmsteps 20 nmodules 1 # errorcheck # @@ -110,7 +110,7 @@ PiecewiseLinFunction 2 t 4 0. 29. 30. 2000.0 f(t) 4 0.1 0.1 0.002 0.0001 #NODE tStep 120 number 44 dof 1 unknown d value 1.360514e-04 #NODE tStep 140 number 44 dof 1 unknown d value 1.434162e-04 #NODE tStep 160 number 44 dof 1 unknown d value 1.515530e-04 -#NODE tStep 180 number 44 dof 1 unknown d value 1.577575e-04 -#NODE tStep 200 number 44 dof 1 unknown d value 1.658578e-04 +#NODE tStep 180 number 44 dof 1 unknown d value 1.577404e-04 +#NODE tStep 200 number 44 dof 1 unknown d value 1.657939e-04 #%END_CHECK% # diff --git a/tests/benchmark/tmsmdssiml/MPS_bench01_in.sm b/tests/benchmark/tmsmdssiml/MPS_bench01_in.sm index 32f9dbf48..1bed651a6 100644 --- a/tests/benchmark/tmsmdssiml/MPS_bench01_in.sm +++ b/tests/benchmark/tmsmdssiml/MPS_bench01_in.sm @@ -2,7 +2,7 @@ MPS_bench01_out.sm OOFEM input file for structural analysis, automatically generated, test for ConTemp, a brick with size x=3 y=0.5 z=0.5. Damage happens at time step 9 due to temperature profile. Mesh is slightly distorted to localize damage. # nonlinearstatic nsteps 10 deltaT 1. rtolv 1.e-3 MaxIter 1000 controllmode 1 stiffMode 2 renumber 1 updateelasticstiffnessflag lstype 4 smtype 8 miniter 3 nmodules 2 -#StaticStructural nsteps 10 deltaT 1. lstype 4 smtype 8 nmodules 2 +#StaticStructural nsteps 10 deltaT 1. lstype 4 smtype 8 stiffmode 2 miniter 3 nmodules 2 #vtkxml tstep_step 1 domain_all vars 11 1 2 112 111 4 106 109 110 52 90 114 primvars 1 1 cellvars 2 90 82 stype 1 regionsets 1 1 timescale 2.77777e-4 #vtkxml tstep_step 1 domain_all vars 5 1 2 4 27 28 primvars 1 1 stype 1 regionsets 2 2 3 timescale 2.77777e-4 hom tstep_all ists 1 52 regionsets 1 1 timescale 2.77777e-4 @@ -192,12 +192,13 @@ simpleCS 1 material 1 set 1 # MATERIALS # # concrete (bricks): -MPSdamMat 1 d 0.00240324 n 0.2 talpha 0.000010 mode 0 fc 25.000000 cc 280.000000 w/c 0.500000 a/c 7.085714 stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 300. endoftimeofinterest 864.e4 relMatAge 10800.000000 CoupledAnalysisType 3 t0 10800.000000 k3 35. p 1000. kTm 0.5 timeDepFracturing fib_s 0.250000 eps_cas0 0.000070 Ft28 1.8 Gf28 8e-05 isotropic temperInCelsius castingTime 21600.000000 checkSnapBack 1 +MPSdamMat 1 d 0.00240324 n 0.2 talpha 0.000010 mode 0 fc 25.000000 cc 280.000000 w/c 0.500000 a/c 7.085714 stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 300. endoftimeofinterest 864.e4 relMatAge 10800.000000 CoupledAnalysisType 3 k3 35. p 1000. kTm 0.5 timeDepFracturing fib_s 0.250000 eps_cas0 0.000070 Ft28 1.8 Gf28 8e-05 isotropic temperInCelsius castingTime 21600.000000 checkSnapBack 1 # # BOUNDARY CONDITIONS # BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0. DeadWeight 2 loadTimeFunction 2 components 3 0. 0. -1. set 1 +#DeadWeight 2 loadTimeFunction 2 components 3 0. 0. -1. set 1 reference # # # diff --git a/tests/benchmark/tmsmdssiml/MPS_bench02_in.sm b/tests/benchmark/tmsmdssiml/MPS_bench02_in.sm index e6887127a..dfc41f4da 100644 --- a/tests/benchmark/tmsmdssiml/MPS_bench02_in.sm +++ b/tests/benchmark/tmsmdssiml/MPS_bench02_in.sm @@ -2,7 +2,7 @@ MPS_bench02_out.sm OOFEM input file for structural analysis, automatically generated, test for ConTemp, a brick with size x=3 y=0.5 z=0.5. The same geometry as MPS_block01_in.out.sm with different BC. No damage happens in the simulation. Test mainly for stress relaxation. Mesh is slightly distorted (it would localize damage). # nonlinearstatic nsteps 10 deltaT 1. rtolv 1.e-3 MaxIter 1000 controllmode 1 stiffMode 2 renumber 1 updateelasticstiffnessflag lstype 4 smtype 8 miniter 3 nmodules 2 -#StaticStructural nsteps 10 deltaT 1. lstype 4 smtype 8 nmodules 2 +#StaticStructural nsteps 10 deltaT 1. lstype 4 smtype 8 nmodules 2 stiffmode 2 rtolf 1e-5 miniter 3 #vtkxml tstep_step 1 domain_all vars 11 1 2 112 111 4 106 109 110 52 90 114 primvars 1 1 cellvars 2 90 82 stype 1 regionsets 1 1 timescale 2.77777e-4 #vtkxml tstep_step 1 domain_all vars 5 1 2 4 27 28 primvars 1 1 stype 1 regionsets 2 2 3 timescale 2.77777e-4 hom tstep_all ists 1 52 regionsets 1 1 timescale 2.77777e-4 @@ -190,7 +190,7 @@ simpleCS 1 material 1 set 1 # MATERIALS # # concrete (bricks): -MPSdamMat 1 d 0.00240324 n 0.2 talpha 0.000010 mode 0 fc 25.000000 cc 280.000000 w/c 0.500000 a/c 7.085714 stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 300. endoftimeofinterest 864.e4 relMatAge 10800.000000 CoupledAnalysisType 3 t0 10800.000000 k3 35. p 1000. kTm 0.5 timeDepFracturing fib_s 0.250000 eps_cas0 0.000070 Ft28 1.8 Gf28 8e-05 isotropic temperInCelsius castingTime 21600.000000 checkSnapBack 1 +MPSdamMat 1 d 0.00240324 n 0.2 talpha 0.000010 mode 0 fc 25.000000 cc 280.000000 w/c 0.500000 a/c 7.085714 stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 300. endoftimeofinterest 864.e4 relMatAge 10800.000000 CoupledAnalysisType 3 k3 35. p 1000. kTm 0.5 timeDepFracturing fib_s 0.250000 eps_cas0 0.000070 Ft28 1.8 Gf28 8e-05 isotropic temperInCelsius castingTime 21600.000000 checkSnapBack 1 # # BOUNDARY CONDITIONS # diff --git a/tests/benchmark/tmsmdssiml/MPS_bench02_in.tm b/tests/benchmark/tmsmdssiml/MPS_bench02_in.tm index 69eeb6c49..28ec73c9a 100644 --- a/tests/benchmark/tmsmdssiml/MPS_bench02_in.tm +++ b/tests/benchmark/tmsmdssiml/MPS_bench02_in.tm @@ -1,126 +1,124 @@ MPS_bench02_out.tm OOFEM input file for thermal analysis, automatically generated, test for ConTemp, a brick with size x=3 y=0.5 z=0.5 TransientTransport nsteps 10 deltat 7200 rtolv 1.e-4 alpha 0.6 lstype 1 lstol 1e-5 lsiter 200 lsprecond 1 renumber 1 exportfields 1 5 nmodules 1 +#TransientTransport nsteps 10 deltat 7200 alpha 0.6 exportfields 1 5 rtolf 1.e-5 lstype 1 lstol 1e-5 lsiter 200 lsprecond 1 nmodules 1 #vtkxml tstep_all domain_all primvars 1 6 vars 3 39 56 95 stype 2 timescale 2.77777e-4 errorcheck domain HeatTransfer OutputManager tstep_all dofman_output { 21 } -ndofman 72 nelem 28 ncrosssect 1 nmat 1 nbc 12 nic 1 nltf 7 -node 1 coords 3 0 0 0 ic 1 1 bc 1 1 -node 2 coords 3 0.428571 0 0 ic 1 1 -node 3 coords 3 0.857143 0 0 ic 1 1 -node 4 coords 3 1.28571 0 0 ic 1 1 -node 5 coords 3 1.71429 0 0 ic 1 1 -node 6 coords 3 2.14286 0 0 ic 1 1 -node 7 coords 3 2.57143 0 0 ic 1 1 -node 8 coords 3 3 0 0 ic 1 1 -node 9 coords 3 0 0.25 0 ic 1 1 bc 1 1 -node 10 coords 3 0.428571 0.25 0 ic 1 1 -node 11 coords 3 0.857143 0.25 0 ic 1 1 -node 12 coords 3 1.28571 0.25 0 ic 1 1 -node 13 coords 3 1.71429 0.25 0 ic 1 1 -node 14 coords 3 2.14286 0.25 0 ic 1 1 -node 15 coords 3 2.57143 0.25 0 ic 1 1 -node 16 coords 3 3 0.25 0 ic 1 1 -node 17 coords 3 0 0.5 0 ic 1 1 bc 1 1 -node 18 coords 3 0.428571 0.5 0 ic 1 1 -node 19 coords 3 0.857143 0.5 0 ic 1 1 -node 20 coords 3 1.28571 0.5 0 ic 1 1 -node 21 coords 3 1.71429 0.5 0 ic 1 1 -node 22 coords 3 2.14286 0.5 0 ic 1 1 -node 23 coords 3 2.57143 0.5 0 ic 1 1 -node 24 coords 3 3 0.5 0 ic 1 1 -node 25 coords 3 0 0 0.25 ic 1 1 bc 1 1 -node 26 coords 3 0.428571 0 0.25 ic 1 1 -node 27 coords 3 0.857143 0 0.25 ic 1 1 -node 28 coords 3 1.28571 0 0.25 ic 1 1 -node 29 coords 3 1.71429 0 0.25 ic 1 1 -node 30 coords 3 2.14286 0 0.25 ic 1 1 -node 31 coords 3 2.57143 0 0.25 ic 1 1 -node 32 coords 3 3 0 0.25 ic 1 1 -node 33 coords 3 0 0.25 0.25 ic 1 1 bc 1 1 -node 34 coords 3 0.428571 0.25 0.25 ic 1 1 -node 35 coords 3 0.857143 0.25 0.25 ic 1 1 -node 36 coords 3 1.28571 0.25 0.25 ic 1 1 -node 37 coords 3 1.71429 0.25 0.25 ic 1 1 -node 38 coords 3 2.14286 0.25 0.25 ic 1 1 -node 39 coords 3 2.57143 0.25 0.25 ic 1 1 -node 40 coords 3 3 0.25 0.25 ic 1 1 -node 41 coords 3 0 0.5 0.25 ic 1 1 bc 1 1 -node 42 coords 3 0.428571 0.5 0.25 ic 1 1 -node 43 coords 3 0.857143 0.5 0.25 ic 1 1 -node 44 coords 3 1.28571 0.5 0.25 ic 1 1 -node 45 coords 3 1.71429 0.5 0.25 ic 1 1 -node 46 coords 3 2.14286 0.5 0.25 ic 1 1 -node 47 coords 3 2.57143 0.5 0.25 ic 1 1 -node 48 coords 3 3 0.5 0.25 ic 1 1 -node 49 coords 3 0 0 0.5 ic 1 1 bc 1 1 -node 50 coords 3 0.428571 0 0.5 ic 1 1 -node 51 coords 3 0.857143 0 0.5 ic 1 1 -node 52 coords 3 1.28571 0 0.5 ic 1 1 -node 53 coords 3 1.71429 0 0.5 ic 1 1 -node 54 coords 3 2.14286 0 0.5 ic 1 1 -node 55 coords 3 2.57143 0 0.5 ic 1 1 -node 56 coords 3 3 0 0.5 ic 1 1 -node 57 coords 3 0 0.25 0.5 ic 1 1 bc 1 1 -node 58 coords 3 0.428571 0.25 0.5 ic 1 1 -node 59 coords 3 0.857143 0.25 0.5 ic 1 1 -node 60 coords 3 1.28571 0.25 0.5 ic 1 1 -node 61 coords 3 1.71429 0.25 0.5 ic 1 1 -node 62 coords 3 2.14286 0.25 0.5 ic 1 1 -node 63 coords 3 2.57143 0.25 0.5 ic 1 1 -node 64 coords 3 3 0.25 0.5 ic 1 1 -node 65 coords 3 0 0.5 0.5 ic 1 1 bc 1 1 -node 66 coords 3 0.428571 0.5 0.5 ic 1 1 -node 67 coords 3 0.857143 0.5 0.5 ic 1 1 -node 68 coords 3 1.28571 0.5 0.5 ic 1 1 -node 69 coords 3 1.71429 0.5 0.5 ic 1 1 -node 70 coords 3 2.14286 0.5 0.5 ic 1 1 -node 71 coords 3 2.57143 0.5 0.5 ic 1 1 -node 72 coords 3 3 0.5 0.5 ic 1 1 -Brick1ht 1 nodes 8 25 33 34 26 1 9 10 2 mat 1 crosssect 1 BoundaryLoads 2 9 6 -Brick1ht 2 nodes 8 26 34 35 27 2 10 11 3 mat 1 crosssect 1 BoundaryLoads 2 9 6 -Brick1ht 3 nodes 8 27 35 36 28 3 11 12 4 mat 1 crosssect 1 BoundaryLoads 2 9 6 -Brick1ht 4 nodes 8 28 36 37 29 4 12 13 5 mat 1 crosssect 1 BoundaryLoads 2 9 6 -Brick1ht 5 nodes 8 29 37 38 30 5 13 14 6 mat 1 crosssect 1 BoundaryLoads 2 9 6 -Brick1ht 6 nodes 8 30 38 39 31 6 14 15 7 mat 1 crosssect 1 BoundaryLoads 2 9 6 -Brick1ht 7 nodes 8 31 39 40 32 7 15 16 8 mat 1 crosssect 1 BoundaryLoads 4 8 5 9 6 -Brick1ht 8 nodes 8 33 41 42 34 9 17 18 10 mat 1 crosssect 1 BoundaryLoads 0 -Brick1ht 9 nodes 8 34 42 43 35 10 18 19 11 mat 1 crosssect 1 BoundaryLoads 0 -Brick1ht 10 nodes 8 35 43 44 36 11 19 20 12 mat 1 crosssect 1 BoundaryLoads 0 -Brick1ht 11 nodes 8 36 44 45 37 12 20 21 13 mat 1 crosssect 1 BoundaryLoads 0 -Brick1ht 12 nodes 8 37 45 46 38 13 21 22 14 mat 1 crosssect 1 BoundaryLoads 0 -Brick1ht 13 nodes 8 38 46 47 39 14 22 23 15 mat 1 crosssect 1 BoundaryLoads 0 -Brick1ht 14 nodes 8 39 47 48 40 15 23 24 16 mat 1 crosssect 1 BoundaryLoads 2 8 5 -Brick1ht 15 nodes 8 49 57 58 50 25 33 34 26 mat 1 crosssect 1 BoundaryLoads 4 9 6 12 1 -Brick1ht 16 nodes 8 50 58 59 51 26 34 35 27 mat 1 crosssect 1 BoundaryLoads 4 9 6 12 1 -Brick1ht 17 nodes 8 51 59 60 52 27 35 36 28 mat 1 crosssect 1 BoundaryLoads 4 9 6 12 1 -Brick1ht 18 nodes 8 52 60 61 53 28 36 37 29 mat 1 crosssect 1 BoundaryLoads 4 9 6 12 1 -Brick1ht 19 nodes 8 53 61 62 54 29 37 38 30 mat 1 crosssect 1 BoundaryLoads 4 9 6 12 1 -Brick1ht 20 nodes 8 54 62 63 55 30 38 39 31 mat 1 crosssect 1 BoundaryLoads 4 9 6 12 1 -Brick1ht 21 nodes 8 55 63 64 56 31 39 40 32 mat 1 crosssect 1 BoundaryLoads 6 8 5 9 6 12 1 -Brick1ht 22 nodes 8 57 65 66 58 33 41 42 34 mat 1 crosssect 1 BoundaryLoads 2 12 1 -Brick1ht 23 nodes 8 58 66 67 59 34 42 43 35 mat 1 crosssect 1 BoundaryLoads 2 12 1 -Brick1ht 24 nodes 8 59 67 68 60 35 43 44 36 mat 1 crosssect 1 BoundaryLoads 2 12 1 -Brick1ht 25 nodes 8 60 68 69 61 36 44 45 37 mat 1 crosssect 1 BoundaryLoads 2 12 1 -Brick1ht 26 nodes 8 61 69 70 62 37 45 46 38 mat 1 crosssect 1 BoundaryLoads 2 12 1 -Brick1ht 27 nodes 8 62 70 71 63 38 46 47 39 mat 1 crosssect 1 BoundaryLoads 2 12 1 -Brick1ht 28 nodes 8 63 71 72 64 39 47 48 40 mat 1 crosssect 1 BoundaryLoads 4 8 5 12 1 -SimpleCS 1 +ndofman 72 nelem 28 ncrosssect 1 nmat 1 nbc 7 nic 1 nltf 7 nset 2 +node 1 coords 3 0 0 0 +node 2 coords 3 0.428571 0 0 +node 3 coords 3 0.857143 0 0 +node 4 coords 3 1.28571 0 0 +node 5 coords 3 1.71429 0 0 +node 6 coords 3 2.14286 0 0 +node 7 coords 3 2.57143 0 0 +node 8 coords 3 3 0 0 +node 9 coords 3 0 0.25 0 +node 10 coords 3 0.428571 0.25 0 +node 11 coords 3 0.857143 0.25 0 +node 12 coords 3 1.28571 0.25 0 +node 13 coords 3 1.71429 0.25 0 +node 14 coords 3 2.14286 0.25 0 +node 15 coords 3 2.57143 0.25 0 +node 16 coords 3 3 0.25 0 +node 17 coords 3 0 0.5 0 +node 18 coords 3 0.428571 0.5 0 +node 19 coords 3 0.857143 0.5 0 +node 20 coords 3 1.28571 0.5 0 +node 21 coords 3 1.71429 0.5 0 +node 22 coords 3 2.14286 0.5 0 +node 23 coords 3 2.57143 0.5 0 +node 24 coords 3 3 0.5 0 +node 25 coords 3 0 0 0.25 +node 26 coords 3 0.428571 0 0.25 +node 27 coords 3 0.857143 0 0.25 +node 28 coords 3 1.28571 0 0.25 +node 29 coords 3 1.71429 0 0.25 +node 30 coords 3 2.14286 0 0.25 +node 31 coords 3 2.57143 0 0.25 +node 32 coords 3 3 0 0.25 +node 33 coords 3 0 0.25 0.25 +node 34 coords 3 0.428571 0.25 0.25 +node 35 coords 3 0.857143 0.25 0.25 +node 36 coords 3 1.28571 0.25 0.25 +node 37 coords 3 1.71429 0.25 0.25 +node 38 coords 3 2.14286 0.25 0.25 +node 39 coords 3 2.57143 0.25 0.25 +node 40 coords 3 3 0.25 0.25 +node 41 coords 3 0 0.5 0.25 +node 42 coords 3 0.428571 0.5 0.25 +node 43 coords 3 0.857143 0.5 0.25 +node 44 coords 3 1.28571 0.5 0.25 +node 45 coords 3 1.71429 0.5 0.25 +node 46 coords 3 2.14286 0.5 0.25 +node 47 coords 3 2.57143 0.5 0.25 +node 48 coords 3 3 0.5 0.25 +node 49 coords 3 0 0 0.5 +node 50 coords 3 0.428571 0 0.5 +node 51 coords 3 0.857143 0 0.5 +node 52 coords 3 1.28571 0 0.5 +node 53 coords 3 1.71429 0 0.5 +node 54 coords 3 2.14286 0 0.5 +node 55 coords 3 2.57143 0 0.5 +node 56 coords 3 3 0 0.5 +node 57 coords 3 0 0.25 0.5 +node 58 coords 3 0.428571 0.25 0.5 +node 59 coords 3 0.857143 0.25 0.5 +node 60 coords 3 1.28571 0.25 0.5 +node 61 coords 3 1.71429 0.25 0.5 +node 62 coords 3 2.14286 0.25 0.5 +node 63 coords 3 2.57143 0.25 0.5 +node 64 coords 3 3 0.25 0.5 +node 65 coords 3 0 0.5 0.5 +node 66 coords 3 0.428571 0.5 0.5 +node 67 coords 3 0.857143 0.5 0.5 +node 68 coords 3 1.28571 0.5 0.5 +node 69 coords 3 1.71429 0.5 0.5 +node 70 coords 3 2.14286 0.5 0.5 +node 71 coords 3 2.57143 0.5 0.5 +node 72 coords 3 3 0.5 0.5 +Brick1ht 1 nodes 8 25 33 34 26 1 9 10 2 BoundaryLoads 2 4 6 +Brick1ht 2 nodes 8 26 34 35 27 2 10 11 3 BoundaryLoads 2 4 6 +Brick1ht 3 nodes 8 27 35 36 28 3 11 12 4 BoundaryLoads 2 4 6 +Brick1ht 4 nodes 8 28 36 37 29 4 12 13 5 BoundaryLoads 2 4 6 +Brick1ht 5 nodes 8 29 37 38 30 5 13 14 6 BoundaryLoads 2 4 6 +Brick1ht 6 nodes 8 30 38 39 31 6 14 15 7 BoundaryLoads 2 4 6 +Brick1ht 7 nodes 8 31 39 40 32 7 15 16 8 BoundaryLoads 4 3 5 4 6 +Brick1ht 8 nodes 8 33 41 42 34 9 17 18 10 +Brick1ht 9 nodes 8 34 42 43 35 10 18 19 11 +Brick1ht 10 nodes 8 35 43 44 36 11 19 20 12 +Brick1ht 11 nodes 8 36 44 45 37 12 20 21 13 +Brick1ht 12 nodes 8 37 45 46 38 13 21 22 14 +Brick1ht 13 nodes 8 38 46 47 39 14 22 23 15 +Brick1ht 14 nodes 8 39 47 48 40 15 23 24 16 BoundaryLoads 2 3 5 +Brick1ht 15 nodes 8 49 57 58 50 25 33 34 26 BoundaryLoads 4 4 6 7 1 +Brick1ht 16 nodes 8 50 58 59 51 26 34 35 27 BoundaryLoads 4 4 6 7 1 +Brick1ht 17 nodes 8 51 59 60 52 27 35 36 28 BoundaryLoads 4 4 6 7 1 +Brick1ht 18 nodes 8 52 60 61 53 28 36 37 29 BoundaryLoads 4 4 6 7 1 +Brick1ht 19 nodes 8 53 61 62 54 29 37 38 30 BoundaryLoads 4 4 6 7 1 +Brick1ht 20 nodes 8 54 62 63 55 30 38 39 31 BoundaryLoads 4 4 6 7 1 +Brick1ht 21 nodes 8 55 63 64 56 31 39 40 32 BoundaryLoads 6 3 5 4 6 7 1 +Brick1ht 22 nodes 8 57 65 66 58 33 41 42 34 BoundaryLoads 2 7 1 +Brick1ht 23 nodes 8 58 66 67 59 34 42 43 35 BoundaryLoads 2 7 1 +Brick1ht 24 nodes 8 59 67 68 60 35 43 44 36 BoundaryLoads 2 7 1 +Brick1ht 25 nodes 8 60 68 69 61 36 44 45 37 BoundaryLoads 2 7 1 +Brick1ht 26 nodes 8 61 69 70 62 37 45 46 38 BoundaryLoads 2 7 1 +Brick1ht 27 nodes 8 62 70 71 63 38 46 47 39 BoundaryLoads 2 7 1 +Brick1ht 28 nodes 8 63 71 72 64 39 47 48 40 BoundaryLoads 4 3 5 7 1 +Set 1 elementranges {(1 28)} +Set 2 nodes 9 1 9 17 25 33 41 49 57 65 +SimpleTransportCS 1 mat 1 set 1 HydratingConcreteMat 1 d 2403.24 k 1.471 c 961.929 hydrationmodeltype 2 Qpot 471.15 masscement 279.904 b1 0.0001624 b2 0.0014 eta 7 dohinf 0.85 activationenergy 38300 castingTime 0. DoH1 0 P1 0 -BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 20 -BoundaryCondition 2 loadTimeFunction 1 prescribedvalue 0 -BoundaryCondition 3 loadTimeFunction 1 prescribedvalue 0 -BoundaryCondition 4 loadTimeFunction 1 prescribedvalue 0 -BoundaryCondition 5 loadTimeFunction 1 prescribedvalue 0 -BoundaryCondition 6 loadTimeFunction 1 prescribedvalue 0 -ConstantSurfaceLoad 7 loadTimeFunction 1 ndofs 1 components 1 20 properties 1 a 0 loadtype 3 -ConstantSurfaceLoad 8 loadTimeFunction 1 ndofs 1 components 1 20 properties 1 a 15 loadtype 3 -ConstantSurfaceLoad 9 loadTimeFunction 1 ndofs 1 components 1 20 properties 1 a 15 loadtype 3 -ConstantSurfaceLoad 10 loadTimeFunction 1 ndofs 1 components 1 0 properties 1 a 0 loadtype 3 -ConstantSurfaceLoad 11 loadTimeFunction 1 ndofs 1 components 1 0 properties 1 a 0 loadtype 3 -ConstantSurfaceLoad 12 loadTimeFunction 1 ndofs 1 components 1 20 properties 1 a 15 loadtype 3 -InitialCondition 1 Conditions 1 u 20 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 10 values 1 20 set 2 +ConstantSurfaceLoad 2 loadTimeFunction 1 components 1 20 properties 1 a 0 loadtype 3 +ConstantSurfaceLoad 3 loadTimeFunction 1 components 1 20 properties 1 a 15 loadtype 3 +ConstantSurfaceLoad 4 loadTimeFunction 1 components 1 20 properties 1 a 15 loadtype 3 +ConstantSurfaceLoad 5 loadTimeFunction 1 components 1 0 properties 1 a 0 loadtype 3 +ConstantSurfaceLoad 6 loadTimeFunction 1 components 1 0 properties 1 a 0 loadtype 3 +ConstantSurfaceLoad 7 loadTimeFunction 1 components 1 20 properties 1 a 15 loadtype 3 +InitialCondition 1 dofs 1 10 conditions 1 u 20 set 1 ConstantFunction 1 f(t) 1.0 UsrDefLTF 2 f(t) 20+(0)*sin(2*3.14159*(t+28800-28800)/86400.)+h(-1.e+30*sin(2*3.14159*(t+28800-28800)/86400.))*(0)*sin(2*3.14159*(t+28800-28800)/86400.) UsrDefLTF 3 f(t) 20+(0)*sin(2*3.14159*(t+28800-28800)/86400.)+h(-1.e+30*sin(2*3.14159*(t+28800-28800)/86400.))*(0)*sin(2*3.14159*(t+28800-28800)/86400.) diff --git a/tests/fm/patch02.in b/tests/fm/cbs1.in similarity index 85% rename from tests/fm/patch02.in rename to tests/fm/cbs1.in index 1f22d0e73..38810189a 100644 --- a/tests/fm/patch02.in +++ b/tests/fm/cbs1.in @@ -1,4 +1,4 @@ -patch02.out +cbs1.out pipe test, inlet velocity (constant), outlet: pressure, no friction cbs nsteps 10 lstype 0 smtype 0 deltaT 0.01 cmflag 0 theta1 0.5 theta2 0.5 nmodules 1 errorcheck @@ -22,21 +22,21 @@ tr1cbs 5 nodes 3 4 7 5 bsides 1 1 bcodes 1 6 tr1cbs 6 nodes 3 8 5 7 bsides 1 3 bcodes 1 8 tr1cbs 7 nodes 3 5 8 6 bsides 0 tr1cbs 8 nodes 3 9 6 8 bsides 2 1 3 bcodes 2 6 8 +Set 1 nodes 3 1 2 3 +Set 2 nodes 6 1 3 4 6 7 9 +Set 3 nodes 3 7 8 9 +Set 4 elementranges {(1 8)} fluidcs 1 mat 1 set 4 newtonianfluid 1 d 1.0 mu 1.0 #prescribed inlet velocity v = 1m/s -BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 1.0 valtype 5 set 1 dofs 1 7 +BoundaryCondition 1 loadTimeFunction 1 values 1 1.0 valtype 5 set 1 dofs 1 7 #zero velocity (wall) condition -BoundaryCondition 2 loadTimeFunction 1 prescribedvalue 0.0 valtype 5 set 2 dofs 1 8 +BoundaryCondition 2 loadTimeFunction 1 values 1 0.0 valtype 5 set 2 dofs 1 8 #pressure -BoundaryCondition 3 loadTimeFunction 1 prescribedvalue 0.0 valtype 3 set 3 dofs 1 11 +BoundaryCondition 3 loadTimeFunction 1 values 1 0.0 valtype 3 set 3 dofs 1 11 # ic for velocity at inlet InitialCondition 1 conditions 1 u 1.0 valtype 5 Piecewiselinfunction 1 t 3 0. 6e-3 2. f(t) 3 0. 1. 1. -Set 1 nodes 3 1 2 3 -Set 2 nodes 6 1 3 4 6 7 9 -Set 3 nodes 3 7 8 9 -Set 4 elementranges {(1 8)} #%BEGIN_CHECK% diff --git a/tests/fm/patch03.in b/tests/fm/cbs2.in similarity index 85% rename from tests/fm/patch03.in rename to tests/fm/cbs2.in index bd008e8bd..a39c9c4b6 100644 --- a/tests/fm/patch03.in +++ b/tests/fm/cbs2.in @@ -1,4 +1,4 @@ -patch03.out +cbs2.out pipe test, the nondimensional version of patch02.in cbs nsteps 10 lstype 0 smtype 0 deltaT 0.01 cmflag 0 theta1 0.5 theta2 0.5 scaleflag 1 lscale 3.0 uscale 2.0 dscale 0.3 nmodules 1 errorcheck @@ -22,21 +22,21 @@ tr1cbs 5 nodes 3 4 7 5 bsides 1 1 bcodes 1 6 tr1cbs 6 nodes 3 8 5 7 bsides 1 3 bcodes 1 8 tr1cbs 7 nodes 3 5 8 6 bsides 0 tr1cbs 8 nodes 3 9 6 8 bsides 2 1 3 bcodes 2 6 8 +Set 1 nodes 3 1 2 3 +Set 2 nodes 6 1 3 4 6 7 9 +Set 3 nodes 3 7 8 9 +Set 4 elementranges {(1 8)} fluidcs 1 mat 1 set 4 newtonianfluid 1 d 1.0 mu 1.0 #prescribed inlet velocity v = 1m/s -BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 1.0 valtype 5 set 1 dofs 1 7 +BoundaryCondition 1 loadTimeFunction 1 values 1 1.0 valtype 5 set 1 dofs 1 7 #zero velocity (wall) condition -BoundaryCondition 2 loadTimeFunction 1 prescribedvalue 0.0 valtype 5 set 2 dofs 1 8 +BoundaryCondition 2 loadTimeFunction 1 values 1 0.0 valtype 5 set 2 dofs 1 8 #pressure -BoundaryCondition 3 loadTimeFunction 1 prescribedvalue 0.0 valtype 3 set 3 dofs 1 11 +BoundaryCondition 3 loadTimeFunction 1 values 1 0.0 valtype 3 set 3 dofs 1 11 # ic for velocity at inlet InitialCondition 1 conditions 1 u 1.0 valtype 5 Piecewiselinfunction 1 t 3 0. 4e-3 2. f(t) 3 0. 1. 1. -Set 1 nodes 3 1 2 3 -Set 2 nodes 6 1 3 4 6 7 9 -Set 3 nodes 3 7 8 9 -Set 4 elementranges {(1 8)} ## Note: tests checks unscaled variables! #%BEGIN_CHECK% diff --git a/tests/fm/patch05.in b/tests/fm/cbs3.in similarity index 85% rename from tests/fm/patch05.in rename to tests/fm/cbs3.in index aae0c3cad..3ecb831e5 100644 --- a/tests/fm/patch05.in +++ b/tests/fm/cbs3.in @@ -1,4 +1,4 @@ -patch05.out +cbs3.out pipe test, with friction on pipe surface cbs nsteps 10 lstype 0 smtype 0 deltaT 0.01 cmflag 0 theta1 0.5 theta2 0.5 nmodules 1 errorcheck @@ -22,21 +22,21 @@ tr1cbs 5 nodes 3 4 7 5 bsides 1 1 bcodes 1 2 tr1cbs 6 nodes 3 8 5 7 bsides 1 3 bcodes 1 8 tr1cbs 7 nodes 3 5 8 6 bsides 0 tr1cbs 8 nodes 3 9 6 8 bsides 2 1 3 bcodes 2 2 8 +Set 1 nodes 1 2 +Set 2 nodes 6 1 3 4 6 7 9 +Set 3 nodes 3 7 8 9 +Set 4 elementranges {(1 8)} fluidcs 1 mat 1 set 4 newtonianfluid 1 d 1.0 mu 1.0 #prescribed inlet velocity v = 1m/s -BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 1.0 set 1 dofs 1 7 +BoundaryCondition 1 loadTimeFunction 1 values 1 1.0 set 1 dofs 1 7 #zero velocity (wall) condition -BoundaryCondition 2 loadTimeFunction 1 prescribedvalue 0.0 set 2 dofs 2 7 8 +BoundaryCondition 2 loadTimeFunction 1 values 2 0.0 0.0 set 2 dofs 2 7 8 #pressure -BoundaryCondition 3 loadTimeFunction 1 prescribedvalue 0.0 set 3 dofs 1 11 +BoundaryCondition 3 loadTimeFunction 1 values 1 0.0 set 3 dofs 1 11 # ic for velocity at inlet InitialCondition 1 conditions 1 u 1.0 Piecewiselinfunction 1 t 3 0. 6e-3 2. f(t) 3 0. 1. 1. -Set 1 nodes 1 2 -Set 2 nodes 6 1 3 4 6 7 9 -Set 3 nodes 3 7 8 9 -Set 4 elementranges {(1 8)} #%BEGIN_CHECK% #NODE tStep 10 number 5 dof 7 unknown d value 9.51117852e-01 diff --git a/tests/fm/simpleNonlinearStokes.in b/tests/fm/simpleNonlinearStokes.in index 10f2fa55b..310f334e2 100644 --- a/tests/fm/simpleNonlinearStokes.in +++ b/tests/fm/simpleNonlinearStokes.in @@ -1,6 +1,6 @@ simpleNonlinearStokes.out Test for stokes flow on triangular Taylor-Hood element -stokesflow nsteps 1 rtolf 1e-5 lstype 0 smtype 0 linesearch 0 maxiter 1000 nmodules 1 +stokesflow nsteps 1 rtolf 1e-5 lstype 0 smtype 0 linesearch 0 maxiter 50 nmodules 1 errorcheck # vtkxml tstep_all domain_all primvars 2 4 5 domain 2dIncompFlow @@ -17,14 +17,14 @@ node 8 coords 3 1.0 0.5 0.0 node 9 coords 3 0.5 1.0 0.0 tr21stokes 1 nodes 6 1 2 4 5 6 7 tr21stokes 2 nodes 6 2 3 4 8 9 6 +Set 1 nodes 2 2 3 +Set 2 nodes 2 1 4 +Set 3 elementranges {(1 2)} fluidcs 1 mat 1 set 3 nonlinearfluid 1 mu 1.000000 d 1.000000 C 1 alpha 0.5 BoundaryCondition 1 loadTimeFunction 1 values 3 1. 1. 1. dofs 3 7 8 11 set 1 BoundaryCondition 2 loadTimeFunction 1 values 1 0. dofs 1 7 set 2 ConstantFunction 1 f(t) 1.0 -Set 1 nodes 2 2 3 -Set 2 nodes 2 1 4 -Set 3 elementranges {(1 2)} #%BEGIN_CHECK% #NODE tStep 1 number 4 dof 8 unknown d value 6.939245e-01 diff --git a/tests/mpm/mp03.in b/tests/mpm/mp03.in new file mode 100644 index 000000000..2a3a5c3b0 --- /dev/null +++ b/tests/mpm/mp03.in @@ -0,0 +1,47 @@ +mp03.out +Test of mpm uptetra21 element +mpmproblem nsteps 1 deltat 0.1 alpha 0.5 rtol 1.e-6 +domain HeatTransfer +outputmanager tstep_all dofman_all element_all +ndofman 18 nelem 3 nbc 2 ncrosssect 0 nic 1 nltf 1 nmat 1 nset 4 +node 1 coords 3 0 0 0 +node 2 coords 3 1 0 0 +node 3 coords 3 0 1 0 +node 4 coords 3 0 0 1 +node 5 coords 3 1 0 1 +node 6 coords 3 0 1 1 +# +node 7 coords 3 0.5 0 0 +node 8 coords 3 0.5 0.5 0 +node 9 coords 3 0 0.5 0 +# +node 10 coords 3 0.5 0 1 +node 11 coords 3 0.5 0.5 1 +node 12 coords 3 0 0.5 1 +# +node 13 coords 3 0 0 0.5 +node 14 coords 3 1 0 0.5 +node 15 coords 3 0 1 0.5 +# +node 16 coords 3 0.5 0 0.5 +node 17 coords 3 0 0.5 0.5 +node 18 coords 3 0.5 0.5 0.5 +# +uptetra21 1 nodes 10 1 2 3 4 7 8 9 13 16 17 crosssect 0 mat 1 +uptetra21 2 nodes 10 4 5 2 3 10 14 16 17 18 8 crosssect 0 mat 1 +uptetra21 3 nodes 10 4 6 5 3 12 11 10 17 15 18 crosssect 0 mat 1 +# +upm 1 +# +# displacement bottom +boundarycondition 1 loadtimefunction 1 set 2 values 3 0 0 0 dofs 3 1 2 3 +# pressure top +boundarycondition 2 loadtimefunction 1 set 3 values 1 0.0 dofs 1 11 +## +InitialCondition 1 Conditions 1 u 0.0 dofs 1 11 set 4 +# +constantfunction 1 f(t) 1 +set 1 elements 3 1 2 3 +set 2 nodes 6 1 2 3 7 8 9 +set 3 nodes 3 4 5 6 +set 4 nodes 6 1 2 3 4 5 6 \ No newline at end of file diff --git a/tests/mpm/mp04.in b/tests/mpm/mp04.in new file mode 100644 index 000000000..35da61792 --- /dev/null +++ b/tests/mpm/mp04.in @@ -0,0 +1,50 @@ +mp04.out +Test of mpm uptetra21 element +mpmproblem nsteps 1 deltat 0.1 alpha 0.5 rtol 1.e-6 +domain HeatTransfer +outputmanager tstep_all dofman_all element_all +ndofman 18 nelem 3 nbc 3 ncrosssect 0 nic 1 nltf 1 nmat 1 nset 5 +node 1 coords 3 0 0 0 +node 2 coords 3 1 0 0 +node 3 coords 3 0 1 0 +node 4 coords 3 0 0 1 +node 5 coords 3 1 0 1 +node 6 coords 3 0 1 1 +# +node 7 coords 3 0.5 0 0 +node 8 coords 3 0.5 0.5 0 +node 9 coords 3 0 0.5 0 +# +node 10 coords 3 0.5 0 1 +node 11 coords 3 0.5 0.5 1 +node 12 coords 3 0 0.5 1 +# +node 13 coords 3 0 0 0.5 +node 14 coords 3 1 0 0.5 +node 15 coords 3 0 1 0.5 +# +node 16 coords 3 0.5 0 0.5 +node 17 coords 3 0 0.5 0.5 +node 18 coords 3 0.5 0.5 0.5 +# +uptetra21 1 nodes 10 1 2 3 4 7 8 9 13 16 17 crosssect 0 mat 1 +uptetra21 2 nodes 10 4 5 2 3 10 14 16 17 18 8 crosssect 0 mat 1 +uptetra21 3 nodes 10 4 6 5 3 12 11 10 17 15 18 crosssect 0 mat 1 +# +upm 1 +# +# displacement bottom +boundarycondition 1 loadtimefunction 1 set 2 values 3 0 0 0 dofs 3 1 2 3 +# pressure top +boundarycondition 2 loadtimefunction 1 set 3 values 1 0.0 dofs 1 11 +# load on top +nodalload 3 loadtimefunction 1 set 5 dofs 1 3 Components 1 2.0 +## +InitialCondition 1 Conditions 1 u 0.0 dofs 1 11 set 4 +# +constantfunction 1 f(t) 1 +set 1 elements 3 1 2 3 +set 2 nodes 6 1 2 3 7 8 9 +set 3 nodes 3 4 5 6 +set 4 nodes 6 1 2 3 4 5 6 +set 5 nodes 6 4 5 6 10 11 12 \ No newline at end of file diff --git a/tests/mpm/mp05.in b/tests/mpm/mp05.in new file mode 100644 index 000000000..d504f1b90 --- /dev/null +++ b/tests/mpm/mp05.in @@ -0,0 +1,39 @@ +mp05.out +Test of mpm uptetra21 element +mpmproblem nsteps 1 deltat 0.1 alpha 0.5 rtol 1.e-6 +domain HeatTransfer +outputmanager tstep_all dofman_all element_all +ndofman 10 nelem 1 nbc 3 ncrosssect 0 nic 1 nltf 1 nmat 1 nset 5 +node 1 coords 3 0 0 0 +node 2 coords 3 1 0 0 +node 3 coords 3 0 1 0 +node 4 coords 3 0 0 1 +# +node 5 coords 3 0.5 0 0 +node 6 coords 3 0.5 0.5 0 +node 7 coords 3 0 0.5 0 +# +# +node 8 coords 3 0 0 0.5 +node 9 coords 3 0.5 0 0.5 +node 10 coords 3 0 0.5 0.5 +# +uptetra21 1 nodes 10 1 2 3 4 5 6 7 8 9 10 crosssect 0 mat 1 +# +upm 1 +# +# displacement bottom +boundarycondition 1 loadtimefunction 1 set 2 values 3 0 0 0 dofs 3 1 2 3 +# pressure bottom +boundarycondition 2 loadtimefunction 1 set 3 values 1 0.0 dofs 1 11 +# load on top +nodalload 3 loadtimefunction 1 set 5 dofs 1 3 Components 1 2.0 +## +InitialCondition 1 Conditions 1 u 0.0 dofs 1 11 set 4 +# +constantfunction 1 f(t) 1 +set 1 elements 1 1 +set 2 nodes 6 1 2 3 5 6 7 +set 3 nodes 3 1 2 3 +set 4 nodes 4 1 2 3 4 +set 5 nodes 1 4 \ No newline at end of file diff --git a/tests/mpm/mpbrick11_01.in b/tests/mpm/mpbrick11_01.in new file mode 100644 index 000000000..d34683551 --- /dev/null +++ b/tests/mpm/mpbrick11_01.in @@ -0,0 +1,36 @@ +mpbrick11_01.out +Test of mpm upbrick11 element +mpmproblem nsteps 1 deltat 0.1 alpha 0.5 rtol 1.e-6 nmodules 1 +vtkxml tstep_all primvars 2 1 5 +domain HeatTransfer +outputmanager tstep_all dofman_all element_all +ndofman 8 nelem 1 nbc 3 ncrosssect 1 nic 1 nltf 1 nmat 1 nset 5 +node 1 coords 3 0 0 0 +node 2 coords 3 1 0 0 +node 3 coords 3 1 1 0 +node 4 coords 3 0 1 0 +node 5 coords 3 0 0 2 +node 6 coords 3 1 0 2 +node 7 coords 3 1 1 2 +node 8 coords 3 0 1 2 +# +upbrick11 1 nodes 8 1 2 3 4 5 6 7 8 crosssect 0 mat 1 +# +dummycs 1 mat 1 +upm 1 +# +# displacement bottom +boundarycondition 1 loadtimefunction 1 set 2 values 3 0 0 0 dofs 3 1 2 3 +# pressure bottom +boundarycondition 2 loadtimefunction 1 set 3 values 1 0.0 dofs 1 11 +# load on top +nodalload 3 loadtimefunction 1 set 5 dofs 1 3 Components 1 2.0 +## +InitialCondition 1 Conditions 1 u 0.0 dofs 1 11 set 4 +# +constantfunction 1 f(t) 1 +set 1 elements 1 1 +set 2 nodes 4 1 2 3 4 +set 3 nodes 4 1 2 3 4 +set 4 nodes 8 1 2 3 4 5 6 7 8 +set 5 nodes 4 5 6 7 8 \ No newline at end of file diff --git a/tests/partests/bar/bar.ctrl b/tests/partests/bar/bar.ctrl index 8edb7bfad..4840058ea 100644 --- a/tests/partests/bar/bar.ctrl +++ b/tests/partests/bar/bar.ctrl @@ -4,12 +4,14 @@ bar.oofem.out # note this example cannot be processed by run_problem # because imperfection must be made in input file # -nonlinearstatic nsteps 15 rtolv 0.0001 MaxIter 200 reqIterations 80 manrmsteps 10 stiffMode 1 controlmode 0 psi 0.0 renumber 0 hpcmode 1 hpc 2 2 1 stepLength 1.0 lstype 3 smtype 7 nmodules 1 +staticstructural nsteps 15 nmodules 1 \ +rtolf 1e-4 MaxIter 200 reqIterations 80 manrmsteps 10 solverType "calm" psi 0.0 hpcmode 1 hpc 2 2 1 stepLength 1.0 smtype 7 lstype 3 errorcheck filename "bar.oofem.in" domain 1dTruss OutputManager tstep_all dofman_all element_all 1 2 2 0 2 -SimpleCS 1 thick 1.0 width 1.0 +SimpleCS 1 thick 1.0 width 1.0 material 1 set 1 +SimpleCS 1 thick 1.0 width 1.0 material 2 set 2 idm1 1 d 1.0 E 1.0 n 0.2 e0 1.0 wf 5.0 equivstraintype 1 talpha 0.0 idm1 2 d 1.0 E 1.0 n 0.2 e0 0.97 wf 5.0 equivstraintype 1 talpha 0.0 BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 @@ -17,9 +19,13 @@ NodalLoad 2 loadTimeFunction 1 components 1 1.0 ConstantFunction 1 f(t) 1.0 PiecewiseLinFunction 2 nPoints 2 t 2 0.0 1000.0 f(t) 2 1.0 1001.0 -#%BEGIN_CHECK% tolerance 1.e-3 -#NODE number 2 dof 1 unknown d -#REACTION comNumber 1 dof 1 +#%BEGIN_CHECK% tolerance 1.e-5 +#NODE tStep 15 number 2 dof 1 unknown d value 15.0 +#REACTION tStep 15 number 1 dof 1 value -5.4439e-02 +#ELEMENT tStep 15 number 2 gp 1 keyword 4 component 1 value 5.4439e-02 +#ELEMENT tStep 15 number 2 gp 1 keyword 1 component 1 value 5.4439e-02 +#ELEMENT tStep 15 number 3 gp 1 keyword 4 component 1 value 1.44556051e+01 +#ELEMENT tStep 15 number 3 gp 1 keyword 1 component 1 value 5.4438e-02 #%END_CHECK% vertex 1 diff --git a/tests/partests/bar/bar.oofem.in b/tests/partests/bar/bar.oofem.in index b81b39462..13d66f520 100644 --- a/tests/partests/bar/bar.oofem.in +++ b/tests/partests/bar/bar.oofem.in @@ -4,7 +4,8 @@ bar.oofem.out # note this example cannot be processed by run_problem # because imperfection must be made in input file # -nonlinearstatic nsteps 15 rtolf 1e-4 MaxIter 200 reqIterations 80 manrmsteps 10 stiffMode 1 controlmode 0 psi 0.0 renumber 0 hpcmode 1 hpc 2 2 1 stepLength 1.0 nmodules 1 +staticstructural nsteps 15 nmodules 1 \ +rtolf 1e-4 MaxIter 200 reqIterations 80 manrmsteps 10 solverType "calm" psi 0.0 hpcmode 1 hpc 2 2 1 stepLength 1.0 smtype 7 lstype 3 errorcheck filename "bar.oofem.in" domain 1dTruss OutputManager tstep_all dofman_all element_all @@ -41,7 +42,7 @@ SimpleCS 2 thick 1.0 width 1.0 material 2 set 2 idm1 1 d 1.0 E 1.0 n 0.2 e0 1.0 wf 5.0 equivstraintype 1 talpha 0.0 idm1 2 d 1.0 E 1.0 n 0.2 e0 0.97 wf 5.0 equivstraintype 1 talpha 0.0 BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 3 -NodalLoad 2 loadTimeFunction 1 dofs 1 1 components 1 1.0 set 4 +NodalLoad 2 loadTimeFunction 1 dofs 1 1 components 1 1.0 set 4 reference ConstantFunction 1 f(t) 1.0 PiecewiseLinFunction 2 t 2 0.0 1000.0 f(t) 2 1.0 1001.0 diff --git a/tests/partests/bar/bar.oofem.in.0 b/tests/partests/bar/bar.oofem.in.0 index 0a774f9f0..6897ba1f8 100644 --- a/tests/partests/bar/bar.oofem.in.0 +++ b/tests/partests/bar/bar.oofem.in.0 @@ -4,7 +4,8 @@ bar.oofem.out.0 # note this example cannot be processed by run_problem # because imperfection must be made in input file # -nonlinearstatic nsteps 15 rtolv 0.0001 MaxIter 200 reqIterations 80 manrmsteps 10 stiffMode 1 controlmode 0 psi 0.0 renumber 0 hpcmode 1 hpc 2 2 1 stepLength 1.0 lstype 3 smtype 7 nmodules 1 +staticstructural nsteps 15 nmodules 1 \ +rtolf 1e-4 MaxIter 200 reqIterations 80 manrmsteps 10 solverType "calm" psi 0.0 hpcmode 1 hpc 2 2 1 stepLength 1.0 lstype 3 smtype 7 errorcheck filename "bar.oofem.in" domain 1dTruss OutputManager tstep_all dofman_all element_all @@ -18,6 +19,6 @@ SimpleCS 1 thick 1.0 width 1.0 idm1 1 d 1.0 E 1.0 n 0.2 e0 1.0 wf 5.0 equivstraintype 1 talpha 0.0 idm1 2 d 1.0 E 1.0 n 0.2 e0 0.97 wf 5.0 equivstraintype 1 talpha 0.0 BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 -NodalLoad 2 loadTimeFunction 1 components 1 1.0 +NodalLoad 2 loadTimeFunction 1 components 1 1.0 reference ConstantFunction 1 f(t) 1.0 PiecewiseLinFunction 2 nPoints 2 t 2 0.0 1000.0 f(t) 2 1.0 1001.0 diff --git a/tests/partests/bar/bar.oofem.in.1 b/tests/partests/bar/bar.oofem.in.1 index befc9d7cc..5bab9933e 100644 --- a/tests/partests/bar/bar.oofem.in.1 +++ b/tests/partests/bar/bar.oofem.in.1 @@ -4,7 +4,8 @@ bar.oofem.out.1 # note this example cannot be processed by run_problem # because imperfection must be made in input file # -nonlinearstatic nsteps 15 rtolv 0.0001 MaxIter 200 reqIterations 80 manrmsteps 10 stiffMode 1 controlmode 0 psi 0.0 renumber 0 hpcmode 1 hpc 2 2 1 stepLength 1.0 lstype 3 smtype 7 nmodules 1 +staticstructural nsteps 15 nmodules 1 \ +rtolf 1e-4 MaxIter 200 reqIterations 80 manrmsteps 10 solverType "calm" psi 0.0 hpcmode 1 hpc 2 2 1 stepLength 1.0 lstype 3 smtype 7 errorcheck filename "bar.oofem.in" domain 1dTruss OutputManager tstep_all dofman_all element_all @@ -20,6 +21,6 @@ SimpleCS 1 thick 1.0 width 1.0 idm1 1 d 1.0 E 1.0 n 0.2 e0 1.0 wf 5.0 equivstraintype 1 talpha 0.0 idm1 2 d 1.0 E 1.0 n 0.2 e0 0.97 wf 5.0 equivstraintype 1 talpha 0.0 BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 -NodalLoad 2 loadTimeFunction 1 components 1 1.0 +NodalLoad 2 loadTimeFunction 1 components 1 1.0 reference ConstantFunction 1 f(t) 1.0 PiecewiseLinFunction 2 nPoints 2 t 2 0.0 1000.0 f(t) 2 1.0 1001.0 diff --git a/tests/partests/bar/bar.oofem.in.2 b/tests/partests/bar/bar.oofem.in.2 index 311433fb6..53822dc56 100644 --- a/tests/partests/bar/bar.oofem.in.2 +++ b/tests/partests/bar/bar.oofem.in.2 @@ -4,7 +4,8 @@ bar.oofem.out.2 # note this example cannot be processed by run_problem # because imperfection must be made in input file # -nonlinearstatic nsteps 15 rtolv 0.0001 MaxIter 200 reqIterations 80 manrmsteps 10 stiffMode 1 controlmode 0 psi 0.0 renumber 0 hpcmode 1 hpc 2 2 1 stepLength 1.0 lstype 3 smtype 7 nmodules 1 +staticstructural nsteps 15 nmodules 1 \ +rtolf 1e-4 MaxIter 200 reqIterations 80 manrmsteps 10 solverType "calm" psi 0.0 hpcmode 1 hpc 2 2 1 stepLength 1.0 lstype 3 smtype 7 errorcheck filename "bar.oofem.in" domain 1dTruss OutputManager tstep_all dofman_all element_all @@ -20,6 +21,6 @@ SimpleCS 1 thick 1.0 width 1.0 idm1 1 d 1.0 E 1.0 n 0.2 e0 1.0 wf 5.0 equivstraintype 1 talpha 0.0 idm1 2 d 1.0 E 1.0 n 0.2 e0 0.97 wf 5.0 equivstraintype 1 talpha 0.0 BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 -NodalLoad 2 loadTimeFunction 1 components 1 1.0 +NodalLoad 2 loadTimeFunction 1 components 1 1.0 reference ConstantFunction 1 f(t) 1.0 PiecewiseLinFunction 2 nPoints 2 t 2 0.0 1000.0 f(t) 2 1.0 1001.0 diff --git a/tests/partests/bar/bar.oofem.in.3 b/tests/partests/bar/bar.oofem.in.3 index c6ed4016f..fb2ccd1e1 100644 --- a/tests/partests/bar/bar.oofem.in.3 +++ b/tests/partests/bar/bar.oofem.in.3 @@ -4,7 +4,8 @@ bar.oofem.out.3 # note this example cannot be processed by run_problem # because imperfection must be made in input file # -nonlinearstatic nsteps 15 rtolv 0.0001 MaxIter 200 reqIterations 80 manrmsteps 10 stiffMode 1 controlmode 0 psi 0.0 renumber 0 hpcmode 1 hpc 2 2 1 stepLength 1.0 lstype 3 smtype 7 nmodules 1 +staticstructural nsteps 15 nmodules 1 \ +rtolf 1e-4 MaxIter 200 reqIterations 80 manrmsteps 10 solverType "calm" psi 0.0 hpcmode 1 hpc 2 2 1 stepLength 1.0 lstype 3 smtype 7 errorcheck filename "bar.oofem.in" domain 1dTruss OutputManager tstep_all dofman_all element_all @@ -20,7 +21,7 @@ SimpleCS 1 thick 1.0 width 1.0 idm1 1 d 1.0 E 1.0 n 0.2 e0 1.0 wf 5.0 equivstraintype 1 talpha 0.0 idm1 2 d 1.0 E 1.0 n 0.2 e0 0.97 wf 5.0 equivstraintype 1 talpha 0.0 BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 -NodalLoad 2 loadTimeFunction 1 components 1 1.0 +NodalLoad 2 loadTimeFunction 1 components 1 1.0 reference ConstantFunction 1 f(t) 1.0 PiecewiseLinFunction 2 nPoints 2 t 2 0.0 1000.0 f(t) 2 1.0 1001.0 diff --git a/tests/partests/barnl/barnl.oofem.in b/tests/partests/barnl/barnl.oofem.in index 582e1ba33..6a81949d6 100644 --- a/tests/partests/barnl/barnl.oofem.in +++ b/tests/partests/barnl/barnl.oofem.in @@ -4,7 +4,7 @@ barnl.oofem.out # note this example cannot be processed by run_problem # because imperfection must be made in input file # -nonlinearstatic nsteps 15 rtolf 1e-4 MaxIter 200 reqIterations 80 manrmsteps 10 stiffMode 1 controlmode 0 psi 0.0 renumber 0 hpcmode 1 hpc 2 2 1 stepLength 1.0 nmodules 1 +nonlinearstatic nsteps 15 rtolf 1e-6 MinIter 199 MaxIter 200 reqIterations 80 manrmsteps 10 stiffMode 1 controlmode 0 psi 0.0 renumber 0 hpcmode 1 hpc 2 2 1 stepLength 1.0 nmodules 1 errorcheck filename "barnl.oofem.in" domain 1dTruss OutputManager tstep_all dofman_all element_all diff --git a/tests/partests/brazil_2d_nl2/brazil_2d_nl.ctrl b/tests/partests/brazil_2d_nl2/brazil_2d_nl.ctrl index c50aa39bc..8877ec73a 100644 --- a/tests/partests/brazil_2d_nl2/brazil_2d_nl.ctrl +++ b/tests/partests/brazil_2d_nl2/brazil_2d_nl.ctrl @@ -1,21 +1,11 @@ brazil_2d_nl.oofem.out 2D brazilian splitting test -#linearstatic nsteps 1 renumber 1 -# -#nonlinearstatic nsteps 100 renumber 1 stiffMode 1 controlmode 0 psi 0.0 steplength 0.0001 initialsteplength 0.0002 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 nonlocalext lstype 3 smtype 7 -# nonlinearstatic nsteps 1 nmsteps 5 renumber 0 profileopt 1 nonlocalext lstype 4 smtype 7 nmodules 1 errocheck "brazil_2d_nl.oofem.in" -# -#metastep 1 nsteps 4 stiffMode 2 controlmode 0 psi 0.0 steplength 0.0001 initialsteplength 0.0002 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 2 nsteps 3 stiffMode 2 controlmode 0 psi 0.0 steplength 0.00002 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 3 nsteps 4 stiffMode 2 controlmode 0 psi 0.0 steplength 0.00001 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 4 nsteps 9 stiffMode 2 controlmode 0 psi 0.0 steplength 0.0001 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 5 nsteps 10 stiffMode 2 controlmode 0 psi 0.0 steplength 0.001 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 # domain PlaneStrain diff --git a/tests/partests/brazil_2d_nl2/brazil_2d_nl.oofem.in b/tests/partests/brazil_2d_nl2/brazil_2d_nl.oofem.in index 239c20cc9..ffc6e6545 100644 --- a/tests/partests/brazil_2d_nl2/brazil_2d_nl.oofem.in +++ b/tests/partests/brazil_2d_nl2/brazil_2d_nl.oofem.in @@ -1,23 +1,14 @@ brazil_2d_nl.oofem.out 2D brazilian splitting test -#linearstatic nsteps 1 renumber 1 -# -#nonlinearstatic nsteps 100 renumber 1 contextOutputStep 1 stiffMode 2 controlmode 0 psi 0.0 steplength 0.0001 initialsteplength 0.0002 rtolf 1e-4 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 -# -nonlinearstatic nsteps 1 nmsteps 5 nmodules 1 -# -#metastep 1 -nsteps 4 stiffMode 2 controlmode 0 psi 0.0 steplength 0.0001 initialsteplength 0.0002 rtolf 1e-4 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll -#metastep 2 -nsteps 3 stiffMode 2 controlmode 0 psi 0.0 steplength 0.00002 rtolf 1e-4 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll -#metastep 3 -nsteps 4 stiffMode 2 controlmode 0 psi 0.0 steplength 0.00001 rtolf 1e-4 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll -#metastep 4 -nsteps 9 stiffMode 2 controlmode 0 psi 0.0 steplength 0.0001 rtolf 1e-4 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll -#metastep 5 -nsteps 10 stiffMode 2 controlmode 0 psi 0.0 steplength 0.001 rtolf 1e-4 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll -# -errorcheck "brazil_2d_nl.oofem.in" +staticstructural nsteps 1 nmsteps 6 nmodules 1 +nsteps 1 stiffMode 2 solverType "calm" psi 0.0 steplength 0.0002 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 3 stiffMode 2 solverType "calm" psi 0.0 steplength 0.0001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 3 stiffMode 2 solverType "calm" psi 0.0 steplength 0.00002 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 4 stiffMode 2 solverType "calm" psi 0.0 steplength 0.00001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 9 stiffMode 2 solverType "calm" psi 0.0 steplength 0.0001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 10 stiffMode 2 solverType "calm" psi 0.0 steplength 0.001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +errorcheck filename "brazil_2d_errorcheck" +#vtkxml tstep_all vars 3 1 2 4 primvars 1 1 stype 2 domain PlaneStrain OutputManager tstep_all dofman_all element_all ndofman 427 nelem 386 ncrosssect 2 nmat 2 nbc 3 nltf 1 nic 0 nset 5 @@ -819,18 +810,18 @@ Quad1PlaneStrain 368 nodes 4 419 404 400 401 mat 1 Quad1PlaneStrain 369 nodes 4 390 418 392 391 mat 1 Quad1PlaneStrain 370 nodes 4 369 419 401 402 mat 1 Quad1PlaneStrain 371 nodes 4 229 230 281 329 mat 1 -Quad1PlaneStrain 372 nodes 4 4 80 420 38 mat 2 -Quad1PlaneStrain 373 nodes 4 80 81 421 420 mat 2 -Quad1PlaneStrain 374 nodes 4 81 6 82 421 mat 2 -Quad1PlaneStrain 375 nodes 4 82 83 422 421 mat 2 -Quad1PlaneStrain 376 nodes 4 83 84 423 422 mat 2 -Quad1PlaneStrain 377 nodes 4 84 8 424 423 mat 2 -Quad1PlaneStrain 378 nodes 4 8 7 85 424 mat 2 -Quad1PlaneStrain 379 nodes 4 85 86 425 424 mat 2 -Quad1PlaneStrain 380 nodes 4 86 5 41 425 mat 2 -Quad1PlaneStrain 381 nodes 4 41 40 426 425 mat 2 -Quad1PlaneStrain 382 nodes 4 40 39 427 426 mat 2 -Quad1PlaneStrain 383 nodes 4 39 38 420 427 mat 2 +Quad1PlaneStrain 372 nodes 4 4 80 420 38 mat 2 +Quad1PlaneStrain 373 nodes 4 80 81 421 420 mat 2 +Quad1PlaneStrain 374 nodes 4 81 6 82 421 mat 2 +Quad1PlaneStrain 375 nodes 4 82 83 422 421 mat 2 +Quad1PlaneStrain 376 nodes 4 83 84 423 422 mat 2 +Quad1PlaneStrain 377 nodes 4 84 8 424 423 mat 2 +Quad1PlaneStrain 378 nodes 4 8 7 85 424 mat 2 +Quad1PlaneStrain 379 nodes 4 85 86 425 424 mat 2 +Quad1PlaneStrain 380 nodes 4 86 5 41 425 mat 2 +Quad1PlaneStrain 381 nodes 4 41 40 426 425 mat 2 +Quad1PlaneStrain 382 nodes 4 40 39 427 426 mat 2 +Quad1PlaneStrain 383 nodes 4 39 38 420 427 mat 2 Quad1PlaneStrain 384 nodes 4 420 421 422 427 mat 2 Quad1PlaneStrain 385 nodes 4 422 423 426 427 mat 2 Quad1PlaneStrain 386 nodes 4 423 424 425 426 mat 2 @@ -839,19 +830,13 @@ Set 2 elementranges {(372 386)} Set 3 noderanges {1 5 7 (42 79) 85 86} Set 4 noderanges {(1 3) (9 22)} Set 5 elementboundaries 2 378 1 -SimpleCS 1 thick 1.0 set 1 -SimpleCS 2 thick 1.0 set 2 +SimpleCS 1 thick 1.0 set 1 material 1 +SimpleCS 2 thick 1.0 set 2 material 2 idmnl1 1 d 1.0 E 37.7e3 n 0.2 talpha 0.0 e0 6.75e-5 ef 3.0e-4 R 5.0 equivstraintype 1 regionMap 2 0 1 IsoLE 2 d 1.0 E 300.e3 n 0.2 talpha 0.0 ##idmnl1 1 d 1.0 E 30.e3 n 0.18 talpha 0.0 e0 0.00011666666667 ef 0.0059953333333 R 5.0 equivstraintype 1 regionMap 2 0 1 ##IsoLE 2 d 1.0 E 210.e3 n 0.3 talpha 0.0 BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 3 BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0.0 set 4 -ConstantEdgeLoad 3 loadTimeFunction 1 dofs 2 1 2 components 2 0 -1.0 loadType 3 set 5 +ConstantEdgeLoad 3 loadTimeFunction 1 dofs 2 1 2 components 2 0 -1.0 loadType 3 set 5 reference ConstantFunction 1 f(t) 1.0 - -#%BEGIN_CHECK% tolerance 1.e-5 -#LOADLEVEL tStep 30 value 110.857521 -#NODE tStep 30 number 7 dof 2 unknown d value -1.08831150e-02 -#NODE tStep 30 number 3 dof 1 unknown d value 1.33260159e-03 -#%END_CHECK% diff --git a/tests/partests/brazil_2d_nl2/brazil_2d_nl2.oofem.in.0 b/tests/partests/brazil_2d_nl2/brazil_2d_nl2.oofem.in.0 index 701f020b2..5c32b6293 100644 --- a/tests/partests/brazil_2d_nl2/brazil_2d_nl2.oofem.in.0 +++ b/tests/partests/brazil_2d_nl2/brazil_2d_nl2.oofem.in.0 @@ -1,26 +1,17 @@ brazil_2d_nl2.oofem.out.0 2D brazilian splitting test -#linearstatic nsteps 1 renumber 1 -# -#nonlinearstatic nsteps 100 renumber 1 stiffMode 1 controlmode 0 psi 0.0 steplength 0.0001 initialsteplength 0.0002 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 nonlocalext lstype 3 smtype 7 -# -nonlinearstatic nsteps 1 nmsteps 5 renumber 0 profileopt 1 nonlocalext lstype 4 smtype 7 nmodules 1 -# -#metastep 1 -nsteps 4 stiffMode 2 controlmode 0 psi 0.0 steplength 0.0001 initialsteplength 0.0002 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 2 -nsteps 3 stiffMode 2 controlmode 0 psi 0.0 steplength 0.00002 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 3 -nsteps 4 stiffMode 2 controlmode 0 psi 0.0 steplength 0.00001 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 4 -nsteps 9 stiffMode 2 controlmode 0 psi 0.0 steplength 0.0001 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 5 -nsteps 10 stiffMode 2 controlmode 0 psi 0.0 steplength 0.001 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -# -errorcheck "brazil_2d_nl.oofem.in" +staticstructural nsteps 1 nmsteps 6 nmodules 1 +nsteps 1 stiffMode 2 solverType "calm" psi 0.0 steplength 0.0002 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 3 stiffMode 2 solverType "calm" psi 0.0 steplength 0.0001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 3 stiffMode 2 solverType "calm" psi 0.0 steplength 0.00002 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 4 stiffMode 2 solverType "calm" psi 0.0 steplength 0.00001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 9 stiffMode 2 solverType "calm" psi 0.0 steplength 0.0001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 10 stiffMode 2 solverType "calm" psi 0.0 steplength 0.001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +errorcheck "brazil_2d_errorcheck" +#vtkxml tstep_all vars 3 1 2 4 primvars 1 1 stype 2 domain PlaneStrain OutputManager tstep_all dofman_all element_all -ndofman 287 nelem 257 ncrosssect 2 nmat 2 nbc 2 nic 0 nltf 1 +ndofman 287 nelem 257 ncrosssect 2 nmat 2 nbc 2 nic 0 nltf 1 nset 5 node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 2 1 1 node 3 coords 3 5.000000e+00 0.000000e+00 0.000000e+00 bc 2 0 1 node 9 coords 3 1.000000e+00 0.000000e+00 0.000000e+00 bc 2 0 1 @@ -565,6 +556,11 @@ Quad1PlaneStrain 368 nodes 4 419 404 400 401 mat 1 crossSect 1 Quad1PlaneStrain 369 nodes 4 390 418 392 391 mat 1 crossSect 1 Quad1PlaneStrain 370 nodes 4 369 419 401 402 mat 1 crossSect 1 Quad1PlaneStrain 371 nodes 4 229 230 281 329 Remote partitions 1 1 mat 1 crossSect 1 +Set 1 elementranges {(1 371)} +Set 2 elementranges {(372 386)} +Set 3 noderanges {1 5 7 (42 79) 85 86} +Set 4 noderanges {(1 3) (9 22)} +Set 5 elementboundaries 2 378 1 SimpleCS 1 thick 1.0 SimpleCS 2 thick 1.0 idmnl1 1 d 1.0 E 37.7e3 n 0.2 talpha 0.0 e0 6.75e-5 ef 3.0e-4 R 5.0 equivstraintype 1 regionMap 2 0 1 @@ -572,5 +568,5 @@ IsoLE 2 d 1.0 E 300.e3 n 0.2 talpha 0.0 ##idmnl1 1 d 1.0 E 30.e3 n 0.18 talpha 0.0 e0 0.00011666666667 ef 0.0059953333333 R 5.0 equivstraintype 1 regionMap 2 0 1 ##IsoLE 2 d 1.0 E 210.e3 n 0.3 talpha 0.0 BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 -ConstantEdgeLoad 2 loadTimeFunction 1 components 2 0 -1.0 loadType 3 +ConstantEdgeLoad 3 loadTimeFunction 1 dofs 2 1 2 components 2 0 -1.0 loadType 3 set 5 reference ConstantFunction 1 f(t) 1.0 diff --git a/tests/partests/brazil_2d_nl2/brazil_2d_nl2.oofem.in.1 b/tests/partests/brazil_2d_nl2/brazil_2d_nl2.oofem.in.1 index 6f77345fb..93db7242e 100644 --- a/tests/partests/brazil_2d_nl2/brazil_2d_nl2.oofem.in.1 +++ b/tests/partests/brazil_2d_nl2/brazil_2d_nl2.oofem.in.1 @@ -1,26 +1,17 @@ brazil_2d_nl2.oofem.out.1 2D brazilian splitting test -#linearstatic nsteps 1 renumber 1 -# -#nonlinearstatic nsteps 100 renumber 1 stiffMode 1 controlmode 0 psi 0.0 steplength 0.0001 initialsteplength 0.0002 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 nonlocalext lstype 3 smtype 7 -# -nonlinearstatic nsteps 1 nmsteps 5 renumber 0 profileopt 1 nonlocalext lstype 4 smtype 7 nmodules 1 -# -#metastep 1 -nsteps 4 stiffMode 2 controlmode 0 psi 0.0 steplength 0.0001 initialsteplength 0.0002 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 2 -nsteps 3 stiffMode 2 controlmode 0 psi 0.0 steplength 0.00002 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 3 -nsteps 4 stiffMode 2 controlmode 0 psi 0.0 steplength 0.00001 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 4 -nsteps 9 stiffMode 2 controlmode 0 psi 0.0 steplength 0.0001 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -#metastep 5 -nsteps 10 stiffMode 2 controlmode 0 psi 0.0 steplength 0.001 rtolv 0.0001 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 keepll lstype 3 -# -errorcheck "brazil_2d_nl.oofem.in" +staticstructural nsteps 1 nmsteps 6 nmodules 1 +nsteps 1 stiffMode 2 solverType "calm" psi 0.0 steplength 0.0002 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 3 stiffMode 2 solverType "calm" psi 0.0 steplength 0.0001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 3 stiffMode 2 solverType "calm" psi 0.0 steplength 0.00002 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 4 stiffMode 2 solverType "calm" psi 0.0 steplength 0.00001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 9 stiffMode 2 solverType "calm" psi 0.0 steplength 0.0001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +nsteps 10 stiffMode 2 solverType "calm" psi 0.0 steplength 0.001 rtolf 1e-6 MaxIter 200 reqIterations 30 manrmsteps 10 hpcmode 1 hpc 2 3 1 initialguess 0 +errorcheck "brazil_2d_errorcheck" +#vtkxml tstep_all vars 3 1 2 4 primvars 1 1 stype 2 domain PlaneStrain OutputManager tstep_all dofman_all element_all -ndofman 315 nelem 276 ncrosssect 2 nmat 2 nbc 2 nic 0 nltf 1 +ndofman 315 nelem 276 ncrosssect 2 nmat 2 nbc 2 nic 0 nltf 1 nset 5 node 2 coords 3 4.000000e+01 0.000000e+00 0.000000e+00 bc 2 0 1 node 4 coords 3 5.000000e+00 3.968627e+01 0.000000e+00 node 5 coords 3 0.000000e+00 3.968627e+01 0.000000e+00 bc 2 1 0 @@ -612,6 +603,11 @@ Quad1PlaneStrain 383 nodes 4 39 38 420 427 mat 2 crossSect 2 Quad1PlaneStrain 384 nodes 4 420 421 422 427 mat 2 crossSect 2 Quad1PlaneStrain 385 nodes 4 422 423 426 427 mat 2 crossSect 2 Quad1PlaneStrain 386 nodes 4 423 424 425 426 mat 2 crossSect 2 +Set 1 elementranges {(1 371)} +Set 2 elementranges {(372 386)} +Set 3 noderanges {1 5 7 (42 79) 85 86} +Set 4 noderanges {(1 3) (9 22)} +Set 5 elementboundaries 2 378 1 SimpleCS 1 thick 1.0 SimpleCS 2 thick 1.0 idmnl1 1 d 1.0 E 37.7e3 n 0.2 talpha 0.0 e0 6.75e-5 ef 3.0e-4 R 5.0 equivstraintype 1 regionMap 2 0 1 @@ -619,5 +615,5 @@ IsoLE 2 d 1.0 E 300.e3 n 0.2 talpha 0.0 ##idmnl1 1 d 1.0 E 30.e3 n 0.18 talpha 0.0 e0 0.00011666666667 ef 0.0059953333333 R 5.0 equivstraintype 1 regionMap 2 0 1 ##IsoLE 2 d 1.0 E 210.e3 n 0.3 talpha 0.0 BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 -ConstantEdgeLoad 2 loadTimeFunction 1 components 2 0 -1.0 loadType 3 +ConstantEdgeLoad 3 loadTimeFunction 1 dofs 2 1 2 components 2 0 -1.0 loadType 3 set 5 reference ConstantFunction 1 f(t) 1.0 diff --git a/tests/partests/dyn_bar03/bar03.statics.oofem.in b/tests/partests/dyn_bar03/bar03.statics.oofem.in index fe3759182..41f46f7f9 100644 --- a/tests/partests/dyn_bar03/bar03.statics.oofem.in +++ b/tests/partests/dyn_bar03/bar03.statics.oofem.in @@ -1,6 +1,7 @@ bar03.statics.oofem.out dynamic relaxation of a spring 0.01 -NonLinearStatic nsteps 10 stepLength 0.01 minStepLength 0.01 rtolv 0.01 Psi 0.0 MaxIter 120 HPC 2 2 1 stiffmode 1 nmodules 1 +StaticStructural nsteps 10 stepLength 0.01 minStepLength 0.01 rtolf 1e-5 Psi 0.0 MaxIter 120 HPC 2 2 1 stiffmode 1 nmodules 1 +#NonLinearStatic nsteps 10 stepLength 0.01 minStepLength 0.01 rtolv 0.01 Psi 0.0 MaxIter 120 HPC 2 2 1 stiffmode 1 nmodules 1 #nldeidynamic nsteps 1000 deltat 0.01 dumpcoef 0.0 drflag 1 tau 10.0 py 0.0666666666667 errorcheck domain 3d diff --git a/tests/partests/lb01/lb01.oofem.in b/tests/partests/lb01/lb01.oofem.in index 80717a573..495f66f20 100644 --- a/tests/partests/lb01/lb01.oofem.in +++ b/tests/partests/lb01/lb01.oofem.in @@ -1,6 +1,7 @@ lb01.out Patch test of PlaneStress2d elements -> pure compression in x direction -NonLinearStatic nsteps 3 controlmode 1 rtolv 1.e-3 refloadmode 0 nmodules 1 +NonLinearStatic nsteps 3 controlmode 1 rtolv 1.e-3 refloadmode 1 nmodules 1 +#StaticStructural nsteps 3 nmodules 1 errorcheck filename "lb01.oofem.in" domain 2dPlaneStress OutputManager tstep_all dofman_all element_all @@ -41,8 +42,9 @@ SimpleCS 1 thick 0.15 width 1.0 material 1 set 1 IsoLE 1 d 0. E 15.0 n 0.25 tAlpha 0.000012 BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 2 BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0.0 set 3 -NodalLoad 3 loadTimeFunction 1 dofs 2 1 2 Components 2 -2.5 0.0 set 4 +NodalLoad 3 loadTimeFunction 2 dofs 2 1 2 components 2 -2.5 0.0 set 4 ConstantFunction 1 f(t) 1.0 +PieceWiseLinFunction 2 t 2 0.0 3.0 f(t) 2 0.0 3.0 # # # diff --git a/tests/partests/lb01/lb01.oofem.in.0 b/tests/partests/lb01/lb01.oofem.in.0 index 09fea0923..c6a3dfd65 100644 --- a/tests/partests/lb01/lb01.oofem.in.0 +++ b/tests/partests/lb01/lb01.oofem.in.0 @@ -1,25 +1,33 @@ lb01.out.0 Patch test of PlaneStress2d elements -> pure compression in x direction -NonLinearStatic nsteps 3 controllmode 1 rtolv 1.e-3 refloadmode 0 lstype 3 smtype 7 lbflag 1 forcelb1 1 lbperturbedsteps {1} lbperturbfactor 0.5 nmodules 1 +NonLinearStatic nsteps 3 controlmode 1 rtolv 1.e-3 refloadmode 1 lstype 3 smtype 7 lbflag 1 forcelb1 1 lbperturbedsteps {1} lbperturbfactor 0.5 nmodules 1 +#StaticStructural nsteps 3 lstype 3 smtype 7 lbflag 1 forcelb1 1 lbperturbedsteps {1} lbperturbfactor 0.5 nmodules 1 errorcheck filename "lb01.oofem.in" domain 2dPlaneStress OutputManager tstep_all dofman_all element_all -ndofman 9 nelem 4 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 -node 1 coords 3 0.0 0.0 0.0 bc 2 1 1 -node 2 coords 3 0.0 1.0 0.0 bc 2 1 0 -node 3 coords 3 0.0 2.0 0.0 bc 2 1 0 -node 4 coords 3 1.0 0.0 0.0 bc 2 0 0 -node 5 coords 3 1.0 1.0 0.0 bc 2 0 0 -node 6 coords 3 1.0 2.0 0.0 bc 2 0 0 -node 7 coords 3 2.0 0.0 0.0 bc 2 0 0 Shared partitions 1 1 -node 8 coords 3 2.0 1.0 0.0 bc 2 0 0 Shared partitions 1 1 -node 9 coords 3 2.0 2.0 0.0 bc 2 0 0 Shared partitions 1 1 -PlaneStress2d 1 nodes 4 1 4 5 2 crossSect 1 mat 1 -PlaneStress2d 2 nodes 4 2 5 6 3 crossSect 1 mat 1 -PlaneStress2d 3 nodes 4 4 7 8 5 crossSect 1 mat 1 -PlaneStress2d 4 nodes 4 5 8 9 6 crossSect 1 mat 1 -SimpleCS 1 thick 0.15 width 1.0 +ndofman 9 nelem 4 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 2 nset 4 +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.0 1.0 0.0 +node 3 coords 3 0.0 2.0 0.0 +node 4 coords 3 1.0 0.0 0.0 +node 5 coords 3 1.0 1.0 0.0 +node 6 coords 3 1.0 2.0 0.0 +node 7 coords 3 2.0 0.0 0.0 Shared partitions 1 1 +node 8 coords 3 2.0 1.0 0.0 Shared partitions 1 1 +node 9 coords 3 2.0 2.0 0.0 Shared partitions 1 1 +PlaneStress2d 1 nodes 4 1 4 5 2 +PlaneStress2d 2 nodes 4 2 5 6 3 +PlaneStress2d 3 nodes 4 4 7 8 5 +PlaneStress2d 4 nodes 4 5 8 9 6 +Set 1 elementranges {(1 4)} +Set 2 nodes 3 1 2 3 +Set 3 nodes 1 1 +Set 4 nodes 0 +SimpleCS 1 thick 0.15 width 1.0 material 1 set 1 IsoLE 1 d 0. E 15.0 n 0.25 tAlpha 0.000012 -BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 -NodalLoad 2 loadTimeFunction 1 Components 2 -2.5 0.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0.0 set 3 +NodalLoad 3 loadTimeFunction 2 dofs 2 1 2 components 2 -2.5 0.0 +# set 4 ConstantFunction 1 f(t) 1.0 +PieceWiseLinFunction 2 t 2 0.0 3.0 f(t) 2 0.0 3.0 diff --git a/tests/partests/lb01/lb01.oofem.in.1 b/tests/partests/lb01/lb01.oofem.in.1 index 78fd98d70..396469282 100644 --- a/tests/partests/lb01/lb01.oofem.in.1 +++ b/tests/partests/lb01/lb01.oofem.in.1 @@ -1,53 +1,38 @@ lb01.out.1 Patch test of PlaneStress2d elements -> pure compression in x direction -NonLinearStatic nsteps 3 controllmode 1 rtolv 1.e-3 refloadmode 0 lstype 3 smtype 7 lbflag 1 forcelb1 1 nmodules 1 +NonLinearStatic nsteps 3 controlmode 1 rtolv 1.e-3 refloadmode 0 lstype 3 smtype 7 lbflag 1 forcelb1 1 nmodules 1 +#StaticStructural nsteps 3 lstype 3 smtype 7 lbflag 1 forcelb1 1 nmodules 1 errorcheck filename "lb01.oofem.in" domain 2dPlaneStress OutputManager tstep_all dofman_all element_all -ndofman 12 nelem 6 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 -node 7 coords 3 2.0 0.0 0.0 bc 2 0 0 Shared partitions 1 0 -node 8 coords 3 2.0 1.0 0.0 bc 2 0 0 Shared partitions 1 0 -node 9 coords 3 2.0 2.0 0.0 bc 2 0 0 Shared partitions 1 0 -node 10 coords 3 3.0 0.0 0.0 bc 2 0 0 -node 11 coords 3 3.0 1.0 0.0 bc 2 0 0 -node 12 coords 3 3.0 2.0 0.0 bc 2 0 0 -node 13 coords 3 4.0 0.0 0.0 bc 2 0 0 -node 14 coords 3 4.0 1.0 0.0 bc 2 0 0 -node 15 coords 3 4.0 2.0 0.0 bc 2 0 0 -node 16 coords 3 5.0 0.0 0.0 bc 2 0 0 load 1 2 -node 17 coords 3 5.0 1.0 0.0 bc 2 0 0 load 1 2 -node 18 coords 3 5.0 2.0 0.0 bc 2 0 0 load 1 2 -PlaneStress2d 5 nodes 4 7 10 11 8 crossSect 1 mat 1 -PlaneStress2d 6 nodes 4 8 11 12 9 crossSect 1 mat 1 -PlaneStress2d 7 nodes 4 10 13 14 11 crossSect 1 mat 1 -PlaneStress2d 8 nodes 4 11 14 15 12 crossSect 1 mat 1 -PlaneStress2d 9 nodes 4 13 16 17 14 crossSect 1 mat 1 -PlaneStress2d 10 nodes 4 14 17 18 15 crossSect 1 mat 1 -SimpleCS 1 thick 0.15 width 1.0 +ndofman 12 nelem 6 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 2 nset 4 +node 7 coords 3 2.0 0.0 0.0 Shared partitions 1 0 +node 8 coords 3 2.0 1.0 0.0 Shared partitions 1 0 +node 9 coords 3 2.0 2.0 0.0 Shared partitions 1 0 +node 10 coords 3 3.0 0.0 0.0 +node 11 coords 3 3.0 1.0 0.0 +node 12 coords 3 3.0 2.0 0.0 +node 13 coords 3 4.0 0.0 0.0 +node 14 coords 3 4.0 1.0 0.0 +node 15 coords 3 4.0 2.0 0.0 +node 16 coords 3 5.0 0.0 0.0 load 1 3 +node 17 coords 3 5.0 1.0 0.0 load 1 3 +node 18 coords 3 5.0 2.0 0.0 load 1 3 +PlaneStress2d 5 nodes 4 7 10 11 8 +PlaneStress2d 6 nodes 4 8 11 12 9 +PlaneStress2d 7 nodes 4 10 13 14 11 +PlaneStress2d 8 nodes 4 11 14 15 12 +PlaneStress2d 9 nodes 4 13 16 17 14 +PlaneStress2d 10 nodes 4 14 17 18 15 +Set 1 elementranges {(5 10)} +Set 2 nodes 0 +Set 3 nodes 0 +Set 4 nodes 3 16 17 18 +SimpleCS 1 thick 0.15 width 1.0 material 1 set 1 IsoLE 1 d 0. E 15.0 n 0.25 tAlpha 0.000012 -BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 -NodalLoad 2 loadTimeFunction 1 Components 2 -2.5 0.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0.0 set 3 +NodalLoad 3 loadTimeFunction 2 dofs 2 1 2 components 2 -2.5 0.0 +# set 4 ConstantFunction 1 f(t) 1.0 -# -# -# -#%BEGIN_CHECK% tolerance 1.e-4 error_when_missing 0 -## check reactions -#REACTION tStep 2 number 1 dof 1 value 5.6243 -#REACTION tStep 2 number 1 dof 2 value 0.0 -#REACTION tStep 1 number 2 dof 1 value 11.251 -#REACTION tStep 1 number 3 dof 1 value 5.6243 -## check nodes -#NODE tStep 2 number 18 dof 1 unknown d value -27.7756346 -#NODE tStep 2 number 18 dof 2 unknown d value 3.91744535 -#NODE tStep 2 number 10 dof 1 unknown d value -1.49018399e+01 -#NODE tStep 2 number 8 dof 1 unknown d value -9.99470307e+00 -#NODE tStep 2 number 12 dof 1 unknown d value -1.49018399e+01 -#NODE tStep 2 number 6 dof 1 unknown d value -5.00246140e+00 -## check elements -#ELEMENT tStep 2 number 1 gp 1 keyword 4 component 1 value -4.9978e+00 -#ELEMENT tStep 2 number 3 gp 1 keyword 4 component 1 value -5.0000e+00 -#ELEMENT tStep 2 number 5 gp 1 keyword 4 component 1 value -5.0723e+00 -#ELEMENT tStep 2 number 7 gp 1 keyword 4 component 1 value -4.7865e+00 -#ELEMENT tStep 2 number 9 gp 1 keyword 4 component 1 value -3.5410e+00 -#%END_CHECK% +PieceWiseLinFunction 2 t 2 0.0 3.0 f(t) 2 0.0 3.0 diff --git a/tests/partests/lb02/lb02.oofem.in b/tests/partests/lb02/lb02.oofem.in index 43ffeb590..7c2b181bf 100644 --- a/tests/partests/lb02/lb02.oofem.in +++ b/tests/partests/lb02/lb02.oofem.in @@ -1,6 +1,7 @@ lb02.out Test of PlaneStress2d elements -> pure compression in x direction NonLinearStatic nsteps 2 controlmode 1 rtolv 1.e-3 refloadmode 0 lstype 3 smtype 7 lbflag 1 nmodules 1 +#StaticStructural nsteps 2 lstype 3 smtype 7 lbflag 1 nmodules 1 errorcheck filename "lb02.oofem.in" domain 2dPlaneStress OutputManager tstep_all dofman_all element_all diff --git a/tests/partests/lb02/lb02.oofem.in.0 b/tests/partests/lb02/lb02.oofem.in.0 index d2384f52a..6e221af13 100644 --- a/tests/partests/lb02/lb02.oofem.in.0 +++ b/tests/partests/lb02/lb02.oofem.in.0 @@ -1,6 +1,7 @@ lb02.out.0 Test of PlaneStress2d elements -> pure compression in x direction -NonLinearStatic nsteps 2 controllmode 1 rtolv 1.e-3 refloadmode 0 lstype 3 smtype 7 lbflag 1 forcelb1 1 lbperturbedsteps {1} lbperturbfactor 0.5 nmodules 1 +NonLinearStatic nsteps 2 controlmode 1 rtolv 1.e-3 refloadmode 0 lstype 3 smtype 7 lbflag 1 forcelb1 1 lbperturbedsteps {1} lbperturbfactor 0.5 nmodules 1 +#StaticStructural nsteps 2 lstype 3 smtype 7 lbflag 1 forcelb1 1 lbperturbedsteps {1} lbperturbfactor 0.5 nmodules 1 errorcheck filename "lb02.oofem.in" domain 2dPlaneStress OutputManager tstep_all dofman_all element_all diff --git a/tests/partests/lb02/lb02.oofem.in.1 b/tests/partests/lb02/lb02.oofem.in.1 index 4c792476e..63ac9bac7 100644 --- a/tests/partests/lb02/lb02.oofem.in.1 +++ b/tests/partests/lb02/lb02.oofem.in.1 @@ -1,6 +1,7 @@ lb02.out.1 Test of PlaneStress2d elements -> pure compression in x direction -NonLinearStatic nsteps 2 controllmode 1 rtolv 1.e-3 refloadmode 0 lstype 3 smtype 7 lbflag 1 forcelb1 1 nmodules 1 +NonLinearStatic nsteps 2 controlmode 1 rtolv 1.e-3 refloadmode 0 lstype 3 smtype 7 lbflag 1 forcelb1 1 nmodules 1 +#StaticStructural nsteps 2 lstype 3 smtype 7 lbflag 1 forcelb1 1 nmodules 1 errorcheck filename "lb02.oofem.in" domain 2dPlaneStress OutputManager tstep_all dofman_all element_all diff --git a/tests/partests/lb02/lb02.oofem.in.2 b/tests/partests/lb02/lb02.oofem.in.2 index 245117cae..64aa5e873 100644 --- a/tests/partests/lb02/lb02.oofem.in.2 +++ b/tests/partests/lb02/lb02.oofem.in.2 @@ -1,6 +1,7 @@ lb02.out.2 Test of PlaneStress2d elements -> pure compression in x direction -NonLinearStatic nsteps 2 controllmode 1 rtolv 1.e-3 refloadmode 0 lstype 3 smtype 7 lbflag 1 forcelb1 1 nmodules 1 +NonLinearStatic nsteps 2 controlmode 1 rtolv 1.e-3 refloadmode 0 lstype 3 smtype 7 lbflag 1 forcelb1 1 nmodules 1 +#StaticStructural nsteps 2 lstype 3 smtype 7 lbflag 1 forcelb1 1 nmodules 1 errorcheck filename "lb02.oofem.in" domain 2dPlaneStress OutputManager tstep_all dofman_all element_all diff --git a/tests/partests/planestress/planestress.oofem.in b/tests/partests/planestress/planestress.oofem.in index fef9fc0c9..b306be470 100644 --- a/tests/partests/planestress/planestress.oofem.in +++ b/tests/partests/planestress/planestress.oofem.in @@ -1,6 +1,6 @@ planestress.oofem.out 1D PETSc test -linearstatic nsteps 1 nmodules 1 +StaticStructural nsteps 1 nmodules 1 errorcheck filename "planestress.oofem.in" domain 2dPlaneStress OutputManager tstep_all dofman_all element_all diff --git a/tests/sm/Buckling01.in b/tests/sm/Buckling01.in new file mode 100644 index 000000000..59aeb329e --- /dev/null +++ b/tests/sm/Buckling01.in @@ -0,0 +1,75 @@ +Buckling01.out +Euler buckling of a 2D beam, hinges on both supports. Rectangular cross section 160/40 mm, length 10 m, bending around more compliant axis. Initial imperfection as a sine wave with the amplitude 19 mm. The critical force is 210e+3*8.533e-07*pi^2/10^2=0.017656 MN. The reference node must be far away so the local coordination system is uninfluenced with node displacements. +StaticStructural nsteps 50 solverType "calm" forcedInitialStepLength 1.e-8 stepLength 1.e-2 minStepLength 1.e-3 reqiterations 10 rtolv 1e-4 Psi 0.0 manrmsteps 1 hpc 4 17 1 5 3 hpcw 2 1000. 1. nmodules 1 +errorcheck +#Note: hpc helps with the speed of convergence, it takes 1000*vertical displacement plus horizontal mid-span deflection +#vtkxml tstep_all domain_all primvars 1 1 vars 1 7 stype 1 +domain 3dBeam +OutputManager tstep_all dofman_output {1 9 17} element_output { } +ndofman 18 nelem 16 ncrosssect 1 nmat 1 nbc 5 nic 0 nltf 1 nset 5 +node 1 coords 3 0.000 0. 0. +node 2 coords 3 0.625 0. 0.003 +node 3 coords 3 1.25 0. 0.007 +node 4 coords 3 1.875 0. 0.011 +node 5 coords 3 2.500 0. 0.013 +node 6 coords 3 3.125 0. 0.016 +node 7 coords 3 3.750 0. 0.017 +node 8 coords 3 4.375 0. 0.019 +node 9 coords 3 5.000 0. 0.019 +node 10 coords 3 5.625 0. 0.019 +node 11 coords 3 6.250 0. 0.017 +node 12 coords 3 6.875 0. 0.016 +node 13 coords 3 7.500 0. 0.013 +node 14 coords 3 8.125 0. 0.011 +node 15 coords 3 8.750 0. 0.007 +node 16 coords 3 9.375 0. 0.003 +node 17 coords 3 10.00 0. 0. +# common reference node, large y coordinate necessary to eliminate rotation of local coordinate system on displacements +node 18 coords 3 5.0 10000. 0. +# +LIBeam3dNL 1 nodes 2 1 2 refnode 18 nlgeo 1 +LIBeam3dNL 2 nodes 2 2 3 refnode 18 nlgeo 1 +LIBeam3dNL 3 nodes 2 3 4 refnode 18 nlgeo 1 +LIBeam3dNL 4 nodes 2 4 5 refnode 18 nlgeo 1 +LIBeam3dNL 5 nodes 2 5 6 refnode 18 nlgeo 1 +LIBeam3dNL 6 nodes 2 6 7 refnode 18 nlgeo 1 +LIBeam3dNL 7 nodes 2 7 8 refnode 18 nlgeo 1 +LIBeam3dNL 8 nodes 2 8 9 refnode 18 nlgeo 1 +LIBeam3dNL 9 nodes 2 9 10 refnode 18 nlgeo 1 +LIBeam3dNL 10 nodes 2 10 11 refnode 18 nlgeo 1 +LIBeam3dNL 11 nodes 2 11 12 refnode 18 nlgeo 1 +LIBeam3dNL 12 nodes 2 12 13 refnode 18 nlgeo 1 +LIBeam3dNL 13 nodes 2 13 14 refnode 18 nlgeo 1 +LIBeam3dNL 14 nodes 2 14 15 refnode 18 nlgeo 1 +LIBeam3dNL 15 nodes 2 15 16 refnode 18 nlgeo 1 +LIBeam3dNL 16 nodes 2 16 17 refnode 18 nlgeo 1 +# +SimpleCS 1 area 0.0064 Iy 8.533e-07 Iz 100. Ik 100. beamShearCoeff 1.0 material 1 set 1 +IsoLE 1 d 1.0 E 210e+3 n 0.2 tAlpha 12e-6 +#Restrain y-displacement, x-rotation, z-rotation on all nodes +BoundaryCondition 1 loadTimeFunction 1 dofs 3 2 4 6 values 3 0. 0. 0. set 2 +#Bottom node +BoundaryCondition 2 loadTimeFunction 1 dofs 2 1 3 values 2 0. 0. set 3 +#Top node +BoundaryCondition 3 loadTimeFunction 1 dofs 1 3 values 1 0 set 4 +#Restrain of a reference node in all displacements and rotations +BoundaryCondition 4 loadTimeFunction 1 dofs 6 1 2 3 4 5 6 values 6 0. 0. 0. 0. 0. 0. set 5 +#Vertical load +NodalLoad 5 loadTimeFunction 1 dofs 1 1 Components 1 -1. set 4 reference +ConstantFunction 1 f(t) 1. +Set 1 elementranges {(1 16)} +Set 2 noderanges {(1 18)} +Set 3 nodes 1 1 +Set 4 nodes 1 17 +Set 5 nodes 1 18 +# +#%BEGIN_CHECK% +## +#NODE tStep 2 number 17 dof 1 unknown d value -2.28811670e-05 +#NODE tStep 2 number 9 dof 3 unknown d value 1.41580209e-03 +#REACTION tStep 2 number 1 dof 1 value 1.2384e-03 +## +#NODE tStep 50 number 17 dof 1 unknown d value -1.00266125e-01 +#NODE tStep 50 number 9 dof 3 unknown d value 6.17462816e-01 +#REACTION tStep 50 number 1 dof 1 value 1.7369e-02 +#%END_CHECK% diff --git a/tests/sm/EC2creep_casting.in b/tests/sm/EC2creep_casting.in index 93288412c..a1659d853 100644 --- a/tests/sm/EC2creep_casting.in +++ b/tests/sm/EC2creep_casting.in @@ -36,7 +36,7 @@ SimpleCS 1 thick 1.0 width 1.0 material 1 # # MATERIAL # -EC2CreepMat 1 d 0. n 0.2 fcm28 30 stiffnessFactor 1.e6 relMatAge -3. t0 7. timeFactor 1. cemType 2 henv 0.5 h0 100. shType 0 begOfTimeOfInterest 10. endOfTimeOfInterest 10. spectrum castingTime 10. preCastingTimeMat 2 +EC2CreepMat 1 d 0. n 0.2 fcm28 30 stiffnessFactor 1.e6 relMatAge 7. t0 7. timeFactor 1. cemType 2 henv 0.5 h0 100. shType 0 begOfTimeOfInterest 10. endOfTimeOfInterest 10. spectrum castingTime 10. preCastingTimeMat 2 # IsoLE 2 d 0. n 0.2 E 1.e-6 talpha 0. # diff --git a/tests/sm/EC2creep_casting_tmp.in b/tests/sm/EC2creep_casting_tmp.in deleted file mode 100644 index 47a80ed7d..000000000 --- a/tests/sm/EC2creep_casting_tmp.in +++ /dev/null @@ -1,67 +0,0 @@ -EC2creep_casting.out -# -Test on material casting. Before casting time the material is characterized by properties of "preCastingTimeMaterial" -# -#IncrLinearStatic endOfTimeOfInterest 10000.00000 prescribedTimes 40 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 10.0001 10.0002 10.0005 10.001 10.002 10.005 10.01 10.02 10.05 10.1 10.2 10.5 11. 12. 15. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. nmodules 1 -StaticStructural nsteps 40 prescribedTimes 40 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 10.0001 10.0002 10.0005 10.001 10.002 10.005 10.01 10.02 10.05 10.1 10.2 10.5 11. 12. 15. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. nmodules 1 miniter 1 maxiter 1 -# -errorcheck -# vtkxml tstep_step 1 domain_all vars 2 1 4 primvars 1 1 -# -domain 2dPlaneStress -# -OutputManager tstep_all dofman_all element_all -ndofman 4 nelem 1 ncrosssect 1 nmat 2 nbc 4 nic 0 nltf 2 nset 3 -# -# -# NODES -# -node 1 coords 3 0.0 0.0 0.0 -node 2 coords 3 0.1 0.0 0.0 -node 3 coords 3 0.0 0.1 0.0 -node 4 coords 3 0.1 0.1 0.0 -# -# -# ELEMENTS -# -planestress2d 1 nodes 4 1 2 4 3 crossSect 1 -# -Set 1 nodes 1 1 -Set 2 nodes 1 3 -Set 3 nodes 2 2 4 -# -# CROSSECTION -# -SimpleCS 1 thick 1.0 width 1.0 material 1 -# -# -# MATERIAL -# -EC2CreepMat 1 d 0. n 0.2 fcm28 30 stiffnessFactor 1.e6 relMatAge -3. t0 7. timeFactor 1. cemType 2 henv 0.5 h0 100. shType 0 begOfTimeOfInterest 10. endOfTimeOfInterest 10. spectrum castingTime 10. preCastingTimeMat 2 -# -IsoLE 2 d 0. n 0.2 E 1.e-6 talpha 0. -# -# -# -# -BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 1 -BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0. set 2 -NodalLoad 3 loadTimeFunction 1 dofs 2 1 2 components 2 0.05e-9 0. set 3 -NodalLoad 4 loadTimeFunction 2 dofs 2 1 2 components 2 0.05 0. set 3 -# -# -# TIME FUNCTION -# -ConstantFunction 1 f(t) 1.0 -HeavisideLTF 2 origin 10.0 value 1.0 -# -#_#%BEGIN_CHECK% -#TIME -#NODE number 4 dof 1 unknown d -#_#%END_CHECK% -# -#%BEGIN_CHECK% tolerance 1e-9 -#NODE tStep 17 number 4 dof 1 unknown d value 1.047935e-04 -#NODE tStep 25 number 4 dof 1 unknown d value 1.048435e-04 -#NODE tStep 40 number 4 dof 1 unknown d value 1.131202e-04 -#%END_CHECK% diff --git a/tests/sm/EC2shrinkage.in b/tests/sm/EC2shrinkage.in index b52409993..95157c8e8 100644 --- a/tests/sm/EC2shrinkage.in +++ b/tests/sm/EC2shrinkage.in @@ -45,10 +45,10 @@ SimpleCS 2 thick 1.0 width 1.0 material 2 # MATERIAL # # autogenous shrinkage only -EC2CreepMat 1 d 0. n 0.2 fcm28 30 stiffnessFactor 1.e6 relMatAge -10. t0 2. timeFactor 1. cemType 2 henv 0.5 h0 100. shType 3 begOfTimeOfInterest 10. endOfTimeOfInterest 1000. castingTime 10. +EC2CreepMat 1 d 0. n 0.2 fcm28 30 stiffnessFactor 1.e6 relMatAge 0. t0 2. timeFactor 1. cemType 2 henv 0.5 h0 100. shType 3 begOfTimeOfInterest 10. endOfTimeOfInterest 1000. castingTime 10. # # drying shrinkage only -EC2CreepMat 2 d 0. n 0.2 fcm28 30 stiffnessFactor 1.e6 relMatAge -10. t0 2. timeFactor 1. cemType 2 henv 0.5 h0 100. shType 2 begOfTimeOfInterest 10. endOfTimeOfInterest 1000. castingTime 10. +EC2CreepMat 2 d 0. n 0.2 fcm28 30 stiffnessFactor 1.e6 relMatAge 0. t0 2. timeFactor 1. cemType 2 henv 0.5 h0 100. shType 2 begOfTimeOfInterest 10. endOfTimeOfInterest 1000. castingTime 10. # # BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 1 diff --git a/tests/sm/InterfaceEL_Point2D_01.in b/tests/sm/InterfaceEL_Point2D_01.in index 702072e36..8502ebaea 100644 --- a/tests/sm/InterfaceEL_Point2D_01.in +++ b/tests/sm/InterfaceEL_Point2D_01.in @@ -12,7 +12,7 @@ node 3 coords 3 0 1. 0 node 4 coords 3 0.5 1. 0 node 5 coords 3 0.5 1. 0 PlaneStress2D 1 nodes 4 1 2 4 3 crosssect 1 -IntELPoint 2 nodes 2 4 5 normal 2 1. 0. +IntELPoint 2 nodes 2 4 5 normal 3 1. 0. 0. SimpleCS 1 thick 0.1 material 1 InterfaceCS 2 material 2 set 4 IsoLe 1 d 2500. E 40.e+3 n 0.15 talpha 2.40e-6 diff --git a/tests/sm/InterfaceEL_SurfQuad1.in b/tests/sm/InterfaceEL_SurfQuad1.in new file mode 100644 index 000000000..b043576a2 --- /dev/null +++ b/tests/sm/InterfaceEL_SurfQuad1.in @@ -0,0 +1,105 @@ +InterfaceEL_SurfQuad1.out +Patch test for a interface element with a linear quad surface +StaticStructural nsteps 1 rtold 1e-5 manrmsteps 1 nmodules 1 +#vtkxml tstep_step 1 domain_all primvars 1 1 cellvars 1 103 vars 2 1 4 stype 1 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 16 nelem 3 ncrosssect 2 nmat 2 nbc 4 nic 0 nltf 1 nset 6 +node 1 coords 3 0.2 0. 0. +node 2 coords 3 0.2 0.2 0. +node 3 coords 3 0. 0.2 0. +node 4 coords 3 0. 0. 0. +node 5 coords 3 0.2 0. 0.2 +node 6 coords 3 0.2 0.2 0.2 +node 7 coords 3 0. 0.2 0.2 +node 8 coords 3 0. 0. 0.2 +# +node 9 coords 3 0.2 0.2 0. +node 10 coords 3 0.2 0.4 0. +node 11 coords 3 0. 0.4 0. +node 12 coords 3 0. 0.2 0. +node 13 coords 3 0.2 0.2 0.2 +node 14 coords 3 0.2 0.4 0.2 +node 15 coords 3 0. 0.4 0.2 +node 16 coords 3 0. 0.2 0.2 +# +LSpace 1 nodes 8 1 2 3 4 5 6 7 8 +LSpace 2 nodes 8 9 10 11 12 13 14 15 16 +# +IntElSurfQuad1 3 nodes 8 2 3 7 6 9 12 16 13 +# +SimpleCS 1 thick 1.0 material 1 set 1 +InterfaceCS 2 material 2 set 2 +IsoLE 1 d 0.0 E 15.0 n 0.25 tAlpha 0.000012 +IntMatIsoDamage 2 kn 10.e3 ks 15.e3 ft 10.0 gf 20.0 +#CohInt 2 kn 10.e3 ks 20.e3 stiffcoeffkn 0.03 transitionopening 0.0 +#IntMatCoulombContact 2 kn 1.e+4 frictCoeff 1.0 stiffcoeff 0.2 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 4 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0.0 set 5 +BoundaryCondition 3 loadTimeFunction 1 dofs 1 3 values 1 0.0 set 6 +ConstantSurfaceLoad 4 loadType 2 dofs 3 1 2 3 Components 3 0.0 1.0 0.0 loadTimeFunction 1 set 3 +ConstantFunction 1 f(t) 1.0 +Set 1 elementranges {(1 2)} +Set 2 elements 1 3 +Set 3 elementboundaries 2 2 4 +Set 4 nodes 2 4 8 +Set 5 nodes 4 1 4 5 8 +Set 6 nodes 2 1 4 +# +# +# +#%BEGIN_CHECK% tolerance 2.e-4 +## +## +## check reactions +#REACTION tStep 1 number 1 dof 2 value -1.0e-02 +#REACTION tStep 1 number 4 dof 2 value -1.0e-02 +#REACTION tStep 1 number 5 dof 2 value -1.0e-02 +#REACTION tStep 1 number 8 dof 2 value -1.0e-02 +#REACTION tStep 1 number 1 dof 3 value 0.0 +#REACTION tStep 1 number 4 dof 1 value 0.0 +#REACTION tStep 1 number 4 dof 3 value 0.0 +#REACTION tStep 1 number 8 dof 1 value 0.0 +## check all nodes +#NODE tStep 1 number 1 dof 1 unknown d value -3.33333333e-03 +#NODE tStep 1 number 2 dof 1 unknown d value -3.33333333e-03 +#NODE tStep 1 number 2 dof 2 unknown d value 1.33333333e-02 +#NODE tStep 1 number 2 dof 3 unknown d value 0.0 +#NODE tStep 1 number 3 dof 1 unknown d value 0.0 +#NODE tStep 1 number 3 dof 2 unknown d value 1.33333333e-02 +#NODE tStep 1 number 3 dof 3 unknown d value 0.0 +#NODE tStep 1 number 5 dof 1 unknown d value -3.33333333e-03 +#NODE tStep 1 number 5 dof 3 unknown d value -3.33333333e-03 +#NODE tStep 1 number 6 dof 1 unknown d value -3.33333333e-03 +#NODE tStep 1 number 6 dof 2 unknown d value 1.33333333e-02 +#NODE tStep 1 number 6 dof 3 unknown d value -3.33333333e-03 +#NODE tStep 1 number 7 dof 1 unknown d value 0.0 +#NODE tStep 1 number 7 dof 2 unknown d value 1.33333333e-02 +#NODE tStep 1 number 7 dof 3 unknown d value -3.33333333e-03 +#NODE tStep 1 number 8 dof 3 unknown d value -3.33333333e-03 +#NODE tStep 1 number 9 dof 1 unknown d value -3.33333333e-03 +#NODE tStep 1 number 9 dof 2 unknown d value 1.34333333e-02 +#NODE tStep 1 number 9 dof 3 unknown d value 0.0 +#NODE tStep 1 number 10 dof 1 unknown d value -3.33333333e-03 +#NODE tStep 1 number 10 dof 2 unknown d value 2.67666667e-02 +#NODE tStep 1 number 10 dof 3 unknown d value 0.0 +#NODE tStep 1 number 11 dof 1 unknown d value 0.0 +#NODE tStep 1 number 11 dof 2 unknown d value 2.67666667e-02 +#NODE tStep 1 number 11 dof 3 unknown d value 0.0 +#NODE tStep 1 number 12 dof 1 unknown d value 0.0 +#NODE tStep 1 number 12 dof 2 unknown d value 1.34333333e-02 +#NODE tStep 1 number 12 dof 3 unknown d value 0.0 +#NODE tStep 1 number 13 dof 1 unknown d value -3.33333333e-03 +#NODE tStep 1 number 13 dof 2 unknown d value 1.34333333e-02 +#NODE tStep 1 number 13 dof 3 unknown d value -3.33333333e-03 +#NODE tStep 1 number 14 dof 1 unknown d value -3.33333333e-03 +#NODE tStep 1 number 14 dof 2 unknown d value 2.67666667e-02 +#NODE tStep 1 number 14 dof 3 unknown d value -3.33333333e-03 +#NODE tStep 1 number 15 dof 1 unknown d value 0.0 +#NODE tStep 1 number 15 dof 2 unknown d value 2.67666667e-02 +#NODE tStep 1 number 15 dof 3 unknown d value -3.33333333e-03 +#NODE tStep 1 number 16 dof 1 unknown d value 0.0 +#NODE tStep 1 number 16 dof 2 unknown d value 1.34333333e-02 +#NODE tStep 1 number 16 dof 3 unknown d value -3.33333333e-03 +#%END_CHECK% diff --git a/tests/sm/InterfaceEL_SurfQuad2.in b/tests/sm/InterfaceEL_SurfQuad2.in new file mode 100644 index 000000000..b7b2b6af2 --- /dev/null +++ b/tests/sm/InterfaceEL_SurfQuad2.in @@ -0,0 +1,78 @@ +InterfaceEL_SurfQuad2.out +Patch test for a interface element with a linear quad surface in shear +StaticStructural nsteps 1 rtold 1e-5 manrmsteps 1 nmodules 1 +#vtkxml tstep_step 1 domain_all primvars 1 1 cellvars 1 103 vars 2 1 4 stype 1 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 16 nelem 3 ncrosssect 2 nmat 2 nbc 4 nic 0 nltf 1 nset 6 +node 1 coords 3 0.2 0. 0. +node 2 coords 3 0.2 0.2 0. +node 3 coords 3 0. 0.2 0. +node 4 coords 3 0. 0. 0. +node 5 coords 3 0.2 0. 0.2 +node 6 coords 3 0.2 0.2 0.2 +node 7 coords 3 0. 0.2 0.2 +node 8 coords 3 0. 0. 0.2 +# +node 9 coords 3 0.2 0.2 0. +node 10 coords 3 0.2 0.4 0. +node 11 coords 3 0. 0.4 0. +node 12 coords 3 0. 0.2 0. +node 13 coords 3 0.2 0.2 0.2 +node 14 coords 3 0.2 0.4 0.2 +node 15 coords 3 0. 0.4 0.2 +node 16 coords 3 0. 0.2 0.2 +# +LSpace 1 nodes 8 1 2 3 4 5 6 7 8 +LSpace 2 nodes 8 9 10 11 12 13 14 15 16 +# +IntElSurfQuad1 3 nodes 8 2 3 7 6 9 12 16 13 +# +SimpleCS 1 thick 1.0 material 1 set 1 +InterfaceCS 2 material 2 set 2 +IsoLE 1 d 0.0 E 15.0 n 0.25 tAlpha 0.000012 +IntMatIsoDamage 2 kn 10.e3 ks 15.e3 ft 10.0 gf 20.0 +#CohInt 2 kn 10.e3 ks 20.e3 stiffcoeffkn 0.03 transitionopening 0.0 +#IntMatCoulombContact 2 kn 1.e+4 frictCoeff 1.0 stiffcoeff 0.2 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 4 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0.0 set 5 +BoundaryCondition 3 loadTimeFunction 1 dofs 1 3 values 1 0.0 set 6 +ConstantSurfaceLoad 4 loadType 2 dofs 3 1 2 3 Components 3 1.0 0.0 0.0 loadTimeFunction 1 set 3 +ConstantFunction 1 f(t) 1.0 +Set 1 elementranges {(1 2)} +Set 2 elements 1 3 +Set 3 elementboundaries 2 2 4 +Set 4 nodes 4 1 4 5 8 +Set 5 noderanges {(1 16)} +Set 6 nodes 4 1 4 5 8 +# +# +# +#%BEGIN_CHECK% tolerance 2.e-4 +## +## +## check reactions +#REACTION tStep 1 number 1 dof 1 value -1.0e-02 +#REACTION tStep 1 number 4 dof 1 value -1.0e-02 +#REACTION tStep 1 number 5 dof 1 value -1.0e-02 +#REACTION tStep 1 number 8 dof 1 value -1.0e-02 +## check all nodes +#NODE tStep 1 number 1 dof 1 unknown d value 0.0 +#NODE tStep 1 number 2 dof 1 unknown d value 3.33333333e-02 +#NODE tStep 1 number 3 dof 1 unknown d value 3.33333333e-02 +#NODE tStep 1 number 4 dof 1 unknown d value 0.0 +#NODE tStep 1 number 5 dof 1 unknown d value 0.0 +#NODE tStep 1 number 6 dof 1 unknown d value 3.33333333e-02 +#NODE tStep 1 number 7 dof 1 unknown d value 3.33333333e-02 +#NODE tStep 1 number 8 dof 1 unknown d value 0.0 +## +#NODE tStep 1 number 9 dof 1 unknown d value 3.34e-02 +#NODE tStep 1 number 10 dof 1 unknown d value 6.67333333e-02 +#NODE tStep 1 number 11 dof 1 unknown d value 6.67333333e-02 +#NODE tStep 1 number 12 dof 1 unknown d value 3.34e-02 +#NODE tStep 1 number 13 dof 1 unknown d value 3.34e-02 +#NODE tStep 1 number 14 dof 1 unknown d value 6.67333333e-02 +#NODE tStep 1 number 15 dof 1 unknown d value 6.67333333e-02 +#NODE tStep 1 number 16 dof 1 unknown d value 3.34e-02 +#%END_CHECK% diff --git a/tests/sm/MPS_01_casting_sm.in b/tests/sm/MPS_01_casting_sm.in new file mode 100644 index 000000000..2e430b741 --- /dev/null +++ b/tests/sm/MPS_01_casting_sm.in @@ -0,0 +1,76 @@ +MPS_01_casting_sm.out +basic creep in tension, test includes prediction of paramters q1-q4 based on concrete composition, casting time set to 14 days. Results are identical to test MPS_01_sm.in +# +StaticStructural nsteps 28 prescribedTimes 28 0. 13. 14. 14.0001 14.0002 14.0005 14.001 14.002 14.005 14.01 14.02 14.05 14.1 14.2 14.5 15. 16. 19. 24. 34. 64. 114. 214. 514. 1014. 2014. 5014. 10014. nmodules 1 +# +errorcheck +# vtkxml tstep_step 1 domain_all vars 2 1 4 primvars 1 1 +# +domain 2dPlaneStress +# +OutputManager tstep_all dofman_all element_all +ndofman 8 nelem 2 ncrosssect 2 nmat 3 nbc 3 nic 0 nltf 2 nset 3 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.1 0.0 0.0 +node 3 coords 3 0.0 0.1 0.0 +node 4 coords 3 0.1 0.1 0.0 +# +node 5 coords 3 0.0 0.2 0.0 +node 6 coords 3 0.1 0.2 0.0 +node 7 coords 3 0.0 0.3 0.0 +node 8 coords 3 0.1 0.3 0.0 +# +# +# ELEMENTS +# +planestress2d 1 nodes 4 1 2 4 3 crossSect 1 +# +planestress2d 2 nodes 4 5 6 8 7 crossSect 2 +# +# +# CROSSECTION +# +SimpleCS 1 thick 1.0 width 1.0 material 1 +SimpleCS 2 thick 1.0 width 1.0 material 2 +# +# +# MATERIAL +# +mps 1 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 0 castingTime 14. preCastingTimeMat 3 +# +mps 2 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 1 q1 23.13994709e-6 q2 162.4555762e-6 q3 2.944507318e-6 q4 5.791488024e-6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 0 castingTime 14. preCastingTimeMat 3 +# +# +IsoLE 3 d 0. n 0.2 E 1.e-6 talpha 0. +# +BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0. set 2 +NodalLoad 3 loadTimeFunction 2 dofs 2 1 2 Components 2 0.05 0. set 3 +# +# +# TIME FUNCTION +# +ConstantFunction 1 f(t) 1.0 +# ConstantFunction 2 f(t) 1.0 +HeavisideLTF 2 origin 14. value 1.0 +# +Set 1 nodes 2 1 5 +Set 2 nodes 2 3 7 +Set 3 nodes 4 2 4 6 8 +# +#%BEGIN_CHECK% tolerance 1.e-11 +#NODE tStep 7 number 2 dof 1 unknown d value 4.925232e-06 +#NODE tStep 13 number 2 dof 1 unknown d value 6.091198e-06 +#NODE tStep 19 number 2 dof 1 unknown d value 7.907595e-06 +#NODE tStep 25 number 2 dof 1 unknown d value 1.073072e-05 +#NODE tStep 28 number 2 dof 1 unknown d value 1.208951e-05 +#NODE tStep 7 number 6 dof 1 unknown d value 4.925232e-06 +#NODE tStep 13 number 6 dof 1 unknown d value 6.091198e-06 +#NODE tStep 19 number 6 dof 1 unknown d value 7.907595e-06 +#NODE tStep 25 number 6 dof 1 unknown d value 1.073072e-05 +#NODE tStep 28 number 6 dof 1 unknown d value 1.208951e-05 +#%END_CHECK% diff --git a/tests/sm/Mises02.in b/tests/sm/Mises02.in new file mode 100644 index 000000000..07ad1f880 --- /dev/null +++ b/tests/sm/Mises02.in @@ -0,0 +1,29 @@ +Mises02.out +Test of Mises plasticity model with multilinear hardening/softening +StaticStructural nsteps 10 rtolf 1e-4 maxiter 20 nmodules 1 +errorcheck +#vtkxml tstep_all domain_all primvars 1 1 +domain 1dtruss +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 2 nltf 2 nic 0 nset 3 +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.5 0.0 0.0 +truss1d 1 nodes 2 1 2 +SimpleCS 1 thick 1.0 width 10.0 material 1 set 1 +MisesMat 1 d 1.0 tAlpha 0.0 E 1. n 0.2 htype 1 h_eps 3 0. 3. 25. h(eps) 3 1. 2. 1. +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 2 +BoundaryCondition 2 loadTimeFunction 2 dofs 1 1 values 1 1.0 set 3 +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 t 2 0. 11.0 f(t) 2 0.0 12.0 +Set 1 elementranges {1} +Set 2 nodes 1 1 +Set 3 nodes 1 2 +### +### Used for Extractor + +#%BEGIN_CHECK% tolerance 1.e-4 +#ELEMENT tStep 3 number 1 gp 1 keyword 4 component 1 value 6.5455e+00 +#ELEMENT tStep 3 number 1 gp 1 keyword 1 component 1 value 1.9264e+00 +#ELEMENT tStep 20 number 1 gp 1 keyword 4 component 1 value 2.1818e+01 +#ELEMENT tStep 20 number 1 gp 1 keyword 1 component 1 value 1.1991e+00 +#%END_CHECK% diff --git a/tests/sm/beam3d_rve_1.in b/tests/sm/beam3d_rve_1.in new file mode 100644 index 000000000..16ac6d68e --- /dev/null +++ b/tests/sm/beam3d_rve_1.in @@ -0,0 +1,37 @@ +beam3d_rve_1.out +Beam element test +StaticStructural nsteps 1 nmodules 1 initialguess 1 lstype 0 smtype 1 stiffmode 1 rtolv 1.e-3 maxiter 10000 +vtkxmlperiodic tstep_all primvars 1 1 vars 2 4 1 stype 0 regionsets 1 1 +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 12 nelem 10 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 3 +node 1 coords 3 0. 0. 0.5 +node 2 coords 3 0.1 0. 0.5 +node 3 coords 3 0.2 0. 0.5 +node 4 coords 3 0.3 0. 0.5 +node 5 coords 3 0.4 0. 0.5 +node 6 coords 3 0.5 0. 0.5 +node 7 coords 3 0.6 0. 0.5 +node 8 coords 3 0.7 0. 0.5 +node 9 coords 3 0.8 0. 0.5 +node 10 coords 3 0.9 0. 0.5 +node 11 coords 3 0. 0.1 0.5 +node 12 coords 3 1.0 1.0 1.0 +libeam3d 1 nodes 2 1 2 refnode 11 +libeam3d 2 nodes 2 2 3 refnode 11 +libeam3d 3 nodes 2 3 4 refnode 11 +libeam3d 4 nodes 2 4 5 refnode 11 +libeam3d 5 nodes 2 5 6 refnode 11 +libeam3d 6 nodes 2 6 7 refnode 11 +libeam3d 7 nodes 2 7 8 refnode 11 +libeam3d 8 nodes 2 8 9 refnode 11 +libeam3d 9 nodes 2 9 10 refnode 11 +libeam3dboundaryplate 10 nodes 3 10 1 12 refnode 11 location 2 0 22 +FiberedCS 1 fibermaterials 16 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 thicks 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 widths 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 fiberycentrecoords 16 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 fiberzcentrecoords 16 -0.0015 -0.0015 -0.0015 -0.0015 -0.00375 -0.0045 -0.0045 -0.00375 0.0015 0.0015 0.0015 0.0015 0.00375 0.0045 0.0045 0.00375 thick 0.012 width 0.012 set 1 +isole 1 d 1.0 E 2e11 n 0.3 talpha 0.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 5 1 2 3 4 6 values 5 0. 0. 0. 0. 0. set 3 +BoundaryCondition 2 loadTimeFunction 1 dofs 10 1 2 4 5 7 8 10 11 12 13 values 10 0 0 0 0 0 0 1. 0 0 0 set 2 +PiecewiseLinFunction 1 nPoints 2 t 2 0. 1. f(t) 2 0. 1. +set 1 elements 10 1 2 3 4 5 6 7 8 9 10 +set 2 nodes 1 12 +set 3 nodes 1 2 diff --git a/tests/sm/beam3d_rve_2.in b/tests/sm/beam3d_rve_2.in new file mode 100644 index 000000000..eb460632d --- /dev/null +++ b/tests/sm/beam3d_rve_2.in @@ -0,0 +1,37 @@ +beam3d_rve_2.out +Beam element test +StaticStructural nsteps 1 nmodules 1 initialguess 1 lstype 0 smtype 1 stiffmode 1 rtolv 1.e-3 maxiter 10000 +vtkxmlperiodic tstep_all primvars 1 1 vars 2 4 1 stype 0 regionsets 1 1 +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 12 nelem 10 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 3 +node 1 coords 3 0. 0. 0. +node 2 coords 3 0. 0.1 0. +node 3 coords 3 0. 0.2 0. +node 4 coords 3 0. 0.3 0. +node 5 coords 3 0. 0.4 0. +node 6 coords 3 0. 0.5 0. +node 7 coords 3 0. 0.6 0. +node 8 coords 3 0. 0.7 0. +node 9 coords 3 0. 0.8 0. +node 10 coords 3 0. 0.9 0. +node 11 coords 3 0.1 0. 0. +node 12 coords 3 1.0 1.0 1.0 +libeam3d 1 nodes 2 1 2 refnode 11 +libeam3d 2 nodes 2 2 3 refnode 11 +libeam3d 3 nodes 2 3 4 refnode 11 +libeam3d 4 nodes 2 4 5 refnode 11 +libeam3d 5 nodes 2 5 6 refnode 11 +libeam3d 6 nodes 2 6 7 refnode 11 +libeam3d 7 nodes 2 7 8 refnode 11 +libeam3d 8 nodes 2 8 9 refnode 11 +libeam3d 9 nodes 2 9 10 refnode 11 +libeam3dboundaryplate 10 nodes 3 10 1 12 refnode 11 location 2 0 16 +FiberedCS 1 fibermaterials 16 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 thicks 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 widths 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 fiberycentrecoords 16 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 fiberzcentrecoords 16 -0.0015 -0.0015 -0.0015 -0.0015 -0.00375 -0.0045 -0.0045 -0.00375 0.0015 0.0015 0.0015 0.0015 0.00375 0.0045 0.0045 0.00375 thick 0.012 width 0.012 set 1 +isole 1 d 1.0 E 2e11 n 0.3 talpha 0.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 5 1 2 3 5 6 values 5 0 0 0 0 0 set 3 +BoundaryCondition 2 loadTimeFunction 1 dofs 10 1 2 4 5 7 8 10 11 12 13 values 10 0 0 0 0 0 0 0. 1. 0. 0 set 2 +PiecewiseLinFunction 1 nPoints 2 t 2 0. 1. f(t) 2 0. 1. +set 1 elements 10 1 2 3 4 5 6 7 8 9 10 +set 2 nodes 1 12 +set 3 nodes 1 2 diff --git a/tests/sm/beam3d_rve_3.in b/tests/sm/beam3d_rve_3.in new file mode 100644 index 000000000..5578e0bb2 --- /dev/null +++ b/tests/sm/beam3d_rve_3.in @@ -0,0 +1,37 @@ +beam3d_rve_3.out +Beam element test +StaticStructural nsteps 1 nmodules 1 initialguess 1 lstype 0 smtype 1 stiffmode 1 rtolv 1.e-3 maxiter 10000 +vtkxmlperiodic tstep_all primvars 1 1 vars 2 4 1 stype 0 regionsets 1 1 +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 12 nelem 10 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 3 +node 1 coords 3 0. 0. 0.5 +node 2 coords 3 0.1 0. 0.5 +node 3 coords 3 0.2 0. 0.5 +node 4 coords 3 0.3 0. 0.5 +node 5 coords 3 0.4 0. 0.5 +node 6 coords 3 0.5 0. 0.5 +node 7 coords 3 0.6 0. 0.5 +node 8 coords 3 0.7 0. 0.5 +node 9 coords 3 0.8 0. 0.5 +node 10 coords 3 0.9 0. 0.5 +node 11 coords 3 0. 0.1 0.5 +node 12 coords 3 1.0 1.0 1.0 +libeam3d 1 nodes 2 1 2 refnode 11 +libeam3d 2 nodes 2 2 3 refnode 11 +libeam3d 3 nodes 2 3 4 refnode 11 +libeam3d 4 nodes 2 4 5 refnode 11 +libeam3d 5 nodes 2 5 6 refnode 11 +libeam3d 6 nodes 2 6 7 refnode 11 +libeam3d 7 nodes 2 7 8 refnode 11 +libeam3d 8 nodes 2 8 9 refnode 11 +libeam3d 9 nodes 2 9 10 refnode 11 +libeam3dboundarybeam 10 nodes 3 10 1 12 refnode 11 location 2 0 22 +FiberedCS 1 fibermaterials 16 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 thicks 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 widths 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 fiberycentrecoords 16 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 fiberzcentrecoords 16 -0.0015 -0.0015 -0.0015 -0.0015 -0.00375 -0.0045 -0.0045 -0.00375 0.0015 0.0015 0.0015 0.0015 0.00375 0.0045 0.0045 0.00375 thick 0.012 width 0.012 set 1 +isole 1 d 1.0 E 2e11 n 0.3 talpha 0.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 5 1 2 3 4 6 values 5 0. 0. 0. 0. 0. set 3 +BoundaryCondition 2 loadTimeFunction 1 dofs 10 1 2 4 5 7 8 10 11 12 13 values 10 0 0 0 0 0 0 1. 0 0 0 set 2 +PiecewiseLinFunction 1 nPoints 2 t 2 0. 1. f(t) 2 0. 1. +set 1 elements 10 1 2 3 4 5 6 7 8 9 10 +set 2 nodes 1 12 +set 3 nodes 1 2 diff --git a/tests/sm/blatzko1.in b/tests/sm/blatzko1.in new file mode 100644 index 000000000..e0de89019 --- /dev/null +++ b/tests/sm/blatzko1.in @@ -0,0 +1,77 @@ +testBlatzKo.out +uniaxial tension test of blatz-ko material model +########################################### +NonLinearStatic nsteps 1 renumber 1 nmodules 1 controllmode 1 rtolv 1.e-6 stiffMode 0 manrmsteps 1 maxiter 300 initialGuess 0 +errorcheck +########################################### +domain 3d +OutputManager tstep_all dofman_all element_all +################################################################### +ndofman 8 nelem 1 ncrosssect 1 nmat 1 nbc 4 nic 0 nltf 2 nset 4 +#########################---Nodes---############################### +node 1 coords 3 0.000000 0.000000 0.000000 +node 2 coords 3 1.000000 0.000000 0.000000 +node 3 coords 3 1.000000 1.000000 0.000000 +node 4 coords 3 0.000000 1.000000 0.000000 +node 5 coords 3 0.000000 0.000000 1.000000 +node 6 coords 3 1.000000 0.000000 1.000000 +node 7 coords 3 1.000000 1.000000 1.000000 +node 8 coords 3 0.000000 1.000000 1.000000 +########################---Elements---############################# +LSpace 1 nodes 8 1 2 3 4 5 6 7 8 mat 1 crossSect 1 nlgeo 1 +####################---Cross-Sections---########################### +SimpleCS 1 thick 1.0 +#######################---Materials---############################# +BlatzKoMat 1 mu 1. d 0. +#######################---Boundary cond.---######################## +BoundaryCondition 1 loadTimeFunction 1 values 1 0.000 dofs 1 1 set 1 +BoundaryCondition 2 loadTimeFunction 1 values 1 0.000 dofs 1 2 set 2 +BoundaryCondition 3 loadTimeFunction 1 values 1 0.000 dofs 1 3 set 3 +BoundaryCondition 4 loadTimeFunction 2 values 1 0.001 dofs 1 3 set 4 +#######################---Time functions---######################## +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 nPoints 2 t 2 0. 2000. f(t) 2 100. 2000. +###########################---Sets---############################## +Set 1 nodes 4 1 4 5 8 +Set 2 nodes 4 1 2 5 6 +Set 3 nodes 4 1 2 3 4 +Set 4 nodes 4 5 6 7 8 +################################################################### +#%BEGIN_CHECK% tolerance 1.e-6 +## check reactions +#REACTION tStep 1 number 1 dof 3 value -5.0537e-02 +#REACTION tStep 1 number 2 dof 3 value -5.0537e-02 +#REACTION tStep 1 number 3 dof 3 value -5.0537e-02 +#REACTION tStep 1 number 4 dof 3 value -5.0537e-02 +#REACTION tStep 1 number 5 dof 3 value 5.05369471e-02 +#REACTION tStep 1 number 6 dof 3 value 5.05369471e-02 +#REACTION tStep 1 number 7 dof 3 value 5.05369471e-02 +#REACTION tStep 1 number 8 dof 3 value 5.05369471e-02 +################################################################### +## check all nodes +#NODE tStep 1 number 2 dof 1 unknown d value -2.35459103e-02 +#NODE tStep 1 number 3 dof 2 unknown d value -2.35459103e-02 +#NODE tStep 1 number 7 dof 1 unknown d value -2.35459103e-02 +#NODE tStep 1 number 7 dof 2 unknown d value -2.35459103e-02 +#NODE tStep 1 number 7 dof 3 unknown d value 0.1000000e+00 +## check element deformation gradient +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 1 value 9.76454090e-01 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 2 value 9.76454090e-01 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 3 value 1.1000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 4 value 0.0000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 5 value 0.0000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 6 value 0.0000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 7 value 0.0000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 8 value 0.0000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 9 value 0.0000e+00 +## check element first Piola-Kirchhoff stress +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 1 value 0.00000+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 2 value 0.00000+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 3 value 2.02147788e-01 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 4 value 0.0000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 5 value 0.0000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 6 value 0.0000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 7 value 0.0000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 8 value 0.0000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 9 value 0.0000e+00 +#%END_CHECK% diff --git a/tests/sm/bond_link_1.in b/tests/sm/bond_link_1.in new file mode 100644 index 000000000..95bbcabb9 --- /dev/null +++ b/tests/sm/bond_link_1.in @@ -0,0 +1,57 @@ +bond_link_1.out +Bond test +StaticStructural nsteps 1 nmodules 2 initialguess 1 lstype 0 smtype 1 stiffmode 2 rtolv 1.e-3 +vtkxmlperiodic tstep_all primvars 1 1 vars 2 4 1 stype 0 regionsets 1 1 +vtkxmlperiodic tstep_all primvars 1 1 vars 2 4 1 stype 0 regionsets 1 3 +#matlab tstep_all mesh data reactionforces integrationpoints internalvars 7 4 1 12 7 8 98 99 +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 16 nelem 14 ncrosssect 2 nmat 2 nbc 2 nic 0 nltf 1 nset 4 +node 1 coords 3 0. 0. 0. +node 2 coords 3 0.1 0. 0. +node 3 coords 3 0.2 0. 0. +#Four solid nodes for beam node 1 +node 4 coords 3 0.005 0.01 0.01 +node 5 coords 3 -0.001 -0.008 0.012 +node 6 coords 3 0.01 0.02 -0.008 +node 7 coords 3 0.002 0.001 0.001 +#Four solid nodes for beam node 2 +node 8 coords 3 0.1 0.01 0.01 +node 9 coords 3 0.104 -0.01 0.05 +node 10 coords 3 0.09 -0.03 0.03 +node 11 coords 3 0.12 0.01 0.01 +#Four solid nodes for beam node 3 +node 12 coords 3 0.21 0.01 0.01 +node 13 coords 3 0.19 -0.01 0.01 +node 14 coords 3 0.22 0.03 -0.01 +node 15 coords 3 0.195 -0.02 0.01 +#Reference node for beams +node 16 coords 3 0. 0.01 0. +libeam3d2 1 nodes 2 1 2 refnode 16 +libeam3d2 2 nodes 2 2 3 refnode 16 +#links for first node +bondlink3d 3 nodes 2 1 4 length 0.05 diameter 1.e-2 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.0125 +bondlink3d 4 nodes 2 1 5 length 0.1 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.0125 +bondlink3d 5 nodes 2 1 6 length 0.1 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.0125 +bondlink3d 6 nodes 2 1 7 length 0.05 diameter 1.e-2 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.0125 +#links for second node +bondlink3d 7 nodes 2 2 8 length 0.1 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.025 +bondlink3d 8 nodes 2 2 9 length 0.1 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.025 +bondlink3d 9 nodes 2 2 10 length 0.05 diameter 1.e-2 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.025 +bondlink3d 10 nodes 2 2 11 length 0.1 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.025 +#links for third node +bondlink3d 11 nodes 2 3 12 length 0.1 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.0125 +bondlink3d 12 nodes 2 3 13 length 0.05 diameter 1.e-2 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.0125 +bondlink3d 13 nodes 2 3 14 length 0.1 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.0125 +bondlink3d 14 nodes 2 3 15 length 0.1 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.0125 +FiberedCS 1 fibermaterials 16 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 thicks 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 widths 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 fiberycentrecoords 16 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 fiberzcentrecoords 16 -0.0015 -0.0015 -0.0015 -0.0015 -0.00375 -0.0045 -0.0045 -0.00375 0.0015 0.0015 0.0015 0.0015 0.00375 0.0045 0.0045 0.00375 thick 0.012 width 0.012 set 1 +InterfaceCS 2 material 2 set 3 +isole 1 d 0. e 2e11 n 0.3 talpha 0. +linkslip 2 kn 30.e9 kl 30.e12 t0 3.e6 +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 2 3 values 3 0. 0. 0. set 4 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0.001 set 2 +PiecewiseLinFunction 1 nPoints 2 t 2 0. 1. f(t) 2 0. 1. +set 1 elements 2 1 2 +set 2 nodes 1 3 +set 3 elements 12 3 4 5 6 7 8 9 10 11 12 13 14 +set 4 nodes 12 4 5 6 7 8 9 10 11 12 13 14 15 \ No newline at end of file diff --git a/tests/sm/bond_link_2.in b/tests/sm/bond_link_2.in new file mode 100644 index 000000000..0f7941769 --- /dev/null +++ b/tests/sm/bond_link_2.in @@ -0,0 +1,41 @@ +bond_link_2.out +Bond test +StaticStructural nsteps 1 nmodules 2 initialguess 1 lstype 0 smtype 1 stiffmode 2 rtolv 1.e-3 +vtkxmlperiodic tstep_all primvars 1 1 vars 2 4 1 stype 0 regionsets 1 1 +vtkxmlperiodic tstep_all primvars 1 1 vars 2 4 1 stype 0 regionsets 1 3 +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 7 nelem 5 ncrosssect 2 nmat 2 nbc 3 nic 0 nltf 1 nset 5 +node 1 coords 3 0. 0. 0. +node 2 coords 3 0.1 0. 0. +node 3 coords 3 0.2 0. 0. +#Four solid nodes for beam node 1 +node 4 coords 3 0.005 0.01 0.01 +#Four solid nodes for beam node 2 +node 5 coords 3 0.1 0.01 0.01 +#Four solid nodes for beam node 3 +node 6 coords 3 0.21 0.01 0.01 +#Reference node for beams +node 7 coords 3 0. 0.01 0. +libeam3d2 1 nodes 2 1 2 refnode 7 +libeam3d2 2 nodes 2 2 3 refnode 7 +#links for first node +bondlink3d 3 nodes 2 1 4 length 0.05 diameter 1.e-2 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.0125 +#links for second node +bondlink3d 4 nodes 2 2 5 length 0.1 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.025 +#links for third node +bondlink3d 5 nodes 2 3 6 length 0.1 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 0.0125 +FiberedCS 1 fibermaterials 16 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 thicks 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 widths 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 fiberycentrecoords 16 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 fiberzcentrecoords 16 -0.0015 -0.0015 -0.0015 -0.0015 -0.00375 -0.0045 -0.0045 -0.00375 0.0015 0.0015 0.0015 0.0015 0.00375 0.0045 0.0045 0.00375 thick 0.012 width 0.012 set 1 +interfacecs 2 material 2 set 3 +#isole 1 d 0. e 2e11 n 0.3 talpha 0. +MisesMat 1 d 1.0 e 2e11 n 0.3 sig0 500.e20 H 1.e9 omega_crit 0 a 0 tAlpha 1.0 +linkslip 2 kn 30.e9 kl 30.e12 t0 1.e20 +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 2 3 values 3 0. 0. 0. set 4 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0.001 set 2 +BoundaryCondition 3 loadTimeFunction 1 dofs 1 4 values 1 0. set 5 +PiecewiseLinFunction 1 nPoints 2 t 2 0. 1. f(t) 2 0. 1. +set 1 elements 2 1 2 +set 2 nodes 1 3 +set 3 elements 3 3 4 5 +set 4 nodes 3 4 5 6 +set 5 nodes 1 1 \ No newline at end of file diff --git a/tests/sm/bond_link_3.in b/tests/sm/bond_link_3.in new file mode 100644 index 000000000..2999135a4 --- /dev/null +++ b/tests/sm/bond_link_3.in @@ -0,0 +1,27 @@ +bond_link_3.out +Bond test +StaticStructural nsteps 10 nmodules 2 initialguess 1 lstype 0 smtype 1 stiffmode 2 rtolv 1.e-3 +vtkxmlperiodic tstep_all primvars 1 1 vars 2 4 1 stype 0 regionsets 1 1 +vtkxmlperiodic tstep_all primvars 1 1 vars 2 4 1 stype 0 regionsets 1 3 +#matlab tstep_all mesh data reactionforces integrationpoints internalvars 7 4 1 12 7 8 98 99 +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 3 +node 1 coords 3 0. 0. 0. +node 2 coords 3 0. 0.1 0. +bondlink3d 1 nodes 2 1 2 length 0.01 diameter 1.200000e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 length_end 2. +interfacecs 1 material 1 set 1 +linkslip 1 kn 30.e12 kl 30.e15 type 2 t0 10.e6 tf 3.e6 s1 5.e-5 s2 1.e-4 s3 1.5e-4 alpha 0.5 +BoundaryCondition 1 loadTimeFunction 1 dofs 6 1 2 3 4 5 6 values 6 2.e-4 0. 0. 0. 0. 0. set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 3 1 2 3 values 3 0. 0. 0. set 3 +PiecewiseLinFunction 1 nPoints 2 t 2 0. 10. f(t) 2 0. 1. +set 1 elements 1 1 +set 2 nodes 1 1 +set 3 nodes 1 2 +#%BEGIN_CHECK% +##NODE number 1 dof 1 unknown d +##REACTION number 1 dof 1 +#ELEMENT number 1 gp 1 keyword "jump" component 1 +#ELEMENT number 1 gp 1 keyword "traction" component 1 +#TIME +#%END_CHECK% diff --git a/tests/sm/bondceb01.in b/tests/sm/bondceb01.in new file mode 100644 index 000000000..2bd24b432 --- /dev/null +++ b/tests/sm/bondceb01.in @@ -0,0 +1,51 @@ +bondceb01.out +Test case for BondCEB interface material - rebar pull-out. Added by Adam Sciegaj +StaticStructural nsteps 20 deltat 1.0 rtolf 1.0e-4 MaxIter 20 initialguess 1 nmodules 1 +errorcheck +#vtkxml tstep_all domain_all vars 2 98 99 stype 0 regionsets 1 3 +domain 2dPlaneStress +OutputManager tstep_all dofman_all element_all +ndofman 8 nelem 4 ncrosssect 3 nmat 3 nbc 3 nic 0 nltf 1 nset 6 +node 1 coords 3 -0.1 0.1 0.0 +node 2 coords 3 0.1 0.1 0.0 +node 3 coords 3 -0.1 0.0 0.0 +node 4 coords 3 0.1 0.0 0.0 +node 5 coords 3 -0.1 -0.1 0.0 +node 6 coords 3 0.1 -0.1 0.0 +node 7 coords 3 -0.1 0.0 0.0 +node 8 coords 3 0.1 0.0 0.0 +planestress2d 1 nodes 4 1 3 4 2 +planestress2d 2 nodes 4 3 5 6 4 +truss2d 3 nodes 2 7 8 cs 1 +IntElLine1 4 nodes 4 3 4 7 8 +Set 1 elements 2 1 2 +Set 2 elements 1 3 +Set 3 elements 1 4 +Set 4 nodes 1 5 +Set 5 nodes 2 5 6 +Set 6 nodes 1 8 +SimpleCS 1 thick 0.2 material 1 set 1 +SimpleCS 2 area 3.1416e-4 material 2 set 2 +InterfaceCS 3 thickness 6.28319e-2 material 3 set 3 +IsoLE 1 d 1.0 E 3.36e10 n 0.2 tAlpha 1.0 +IsoLE 2 d 1.0 E 2e11 n 0.3 tAlpha 1.0 +bondceb 3 kn 6e12 ks 6.135e10 s1 0.001 s2 0.002 s3 0.0065 taumax 1.541e7 tauf 6.164e6 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 4 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0.0 set 5 +BoundaryCondition 3 loadTimeFunction 1 dofs 1 1 values 1 8e-3 set 6 +PiecewiseLinFunction 1 t 2 0.0 20.0 f(t) 2 0.0 1.0 + +#%BEGIN_CHECK% tolerance 1.e-3 +##Bond stress - slip values check +#ELEMENT tStep 1 number 4 gp 3 keyword 98 component 2 value 2.917817920790832e-04 +#ELEMENT tStep 1 number 4 gp 3 keyword 99 component 2 value 9.415121170265339e+06 +#ELEMENT tStep 5 number 4 gp 4 keyword 98 component 2 value 1.895957776946900e-03 +#ELEMENT tStep 5 number 4 gp 4 keyword 99 component 2 value 1.541000000000000e+07 +#ELEMENT tStep 8 number 4 gp 2 keyword 98 component 2 value 2.933106041747347e-03 +#ELEMENT tStep 8 number 4 gp 2 keyword 99 component 2 value 1.349277811955645e+07 +#ELEMENT tStep 15 number 4 gp 1 keyword 98 component 2 value 5.809200067464972e-03 +#ELEMENT tStep 15 number 4 gp 1 keyword 99 component 2 value 7.583363594715305e+06 +#ELEMENT tStep 19 number 4 gp 4 keyword 98 component 2 value 7.558381673745631e-03 +#ELEMENT tStep 19 number 4 gp 4 keyword 99 component 2 value 6.164000000000000e+06 +## +#%END_CHECK% diff --git a/tests/sm/bondceb02.in b/tests/sm/bondceb02.in new file mode 100644 index 000000000..41d75d46c --- /dev/null +++ b/tests/sm/bondceb02.in @@ -0,0 +1,56 @@ +bondceb02.out +Test case for BondCEB interface material - rebar pull-out in 3D. Added by Adam Sciegaj +StaticStructural nsteps 20 deltat 1.0 rtolf 1.0e-3 MaxIter 50 initialguess 1 nmodules 1 +errorcheck +#vtkxml tstep_all domain_all primvars 1 1 +#vtkxml tstep_all domain_all ipvars 2 98 99 regionsets 1 3 +#matlab tstep_all integrationpoints internalvars 2 98 99 +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 14 nelem 5 ncrosssect 3 nmat 3 nbc 4 nic 0 nltf 1 nset 6 +node 1 coords 3 -0.1 -0.1 0.1 +node 2 coords 3 -0.1 0.0 0.1 +node 3 coords 3 0.1 0.0 0.1 +node 4 coords 3 0.1 -0.1 0.1 +node 5 coords 3 -0.1 -0.1 -0.1 +node 6 coords 3 -0.1 0.0 -0.1 +node 7 coords 3 0.1 0.0 -0.1 +node 8 coords 3 0.1 -0.1 -0.1 +node 9 coords 3 -0.1 0.1 0.1 +node 10 coords 3 0.1 0.1 0.1 +node 11 coords 3 -0.1 0.1 -0.1 +node 12 coords 3 0.1 0.1 -0.1 +node 13 coords 3 -0.1 0.0 0.1 dofidmask 6 1 2 3 4 5 6 +node 14 coords 3 0.1 0.0 0.1 dofidmask 6 1 2 3 4 5 6 +lspace 1 nodes 8 1 2 3 4 5 6 7 8 +lspace 2 nodes 8 2 9 10 3 6 11 12 7 +libeam3d 3 nodes 2 13 14 refnode 9 +IntELPoint 4 nodes 2 2 13 normal 3 0 0 1 length 0.1 +IntElPoint 5 nodes 2 3 14 normal 3 0 0 1 length 0.1 +Set 1 elements 2 1 2 +Set 2 elements 1 3 +Set 3 elements 2 4 5 +Set 4 nodes 1 1 +Set 5 nodes 2 1 4 +Set 6 nodes 1 14 +SimpleCS 1 material 1 set 1 +SimpleCS 2 area 3.1416e-4 material 2 set 2 +InterfaceCS 3 thickness 6.28319e-2 material 3 set 3 +IsoLE 1 d 1.0 E 3.36e10 n 0.2 tAlpha 1.0 +IsoLE 2 d 1.0 E 2e11 n 0.3 tAlpha 1.0 +bondceb 3 kn 6e12 ks 6.135e10 s1 0.001 s2 0.002 s3 0.0065 taumax 1.541e7 tauf 6.164e6 +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 2 3 values 3 0 0 0 set 4 +BoundaryCondition 2 loadTimeFunction 1 dofs 2 2 3 values 2 0 0 set 5 +BoundaryCondition 3 loadTimeFunction 1 dofs 3 4 5 6 values 3 0 0 0 set 2 +BoundaryCondition 4 loadTimeFunction 1 dofs 1 1 values 1 8e-3 set 6 +PiecewiseLinFunction 1 t 2 0.0 20.0 f(t) 2 0.0 1.0 + +#%BEGIN_CHECK% tolerance 1.e1 +##Bond stress values check +#ELEMENT tStep 1 number 5 gp 1 keyword 99 component 2 value 9.01726573e+06 +#ELEMENT tStep 5 number 5 gp 1 keyword 99 component 2 value 1.54100000e+07 +#ELEMENT tStep 8 number 5 gp 1 keyword 99 component 2 value 1.342479552e+07 +#ELEMENT tStep 15 number 5 gp 1 keyword 99 component 2 value 7.45817170e+06 +#ELEMENT tStep 19 number 5 gp 1 keyword 99 component 2 value 6.16400000e+06 +## +#%END_CHECK% diff --git a/tests/sm/cantilever_Qspace.in b/tests/sm/cantilever_Qspace.in index 49eadf382..dd4394bc9 100644 --- a/tests/sm/cantilever_Qspace.in +++ b/tests/sm/cantilever_Qspace.in @@ -1,11 +1,12 @@ cantilever_Qspace.out Cantilever 'beam' test from 3 Qspace elements -#If considered as a beam, cross section width=2m, depth=1m, length=12m. -#End deflection=FL3/3EI=345.6*F -#Second step with end deflection 1.0m gives F=0.002893518 N, M(x=0m)=0.0347222 NM, sig_max(x=2m)=0.104166 Pa -StaticStructural nsteps 3 nmodules 2 +#If considered as a beam, cross section width=2m, height=1.2m, length=12m. +#End deflection=FL3/3EI=200*F +#Second step with end deflection 1.0 m gives F=0.005 N, M(x=0m)=0.06 Nm, sig_max(x=0 m)=0.125 Pa, strain energy 2.5e-3 J (only sig_x, small contribution from shear) +StaticStructural nsteps 3 nmodules 3 errorcheck vtkxml tstep_all domain_all primvars 1 1 vars 3 1 2 4 stype 2 +hom tstep_all ists 2 1 4 strain_energy domain 3d OutputManager tstep_all dofman_all element_all ndofman 44 nelem 3 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 2 nset 3 diff --git a/tests/sm/con1dpm1.in b/tests/sm/con1dpm1.in new file mode 100644 index 000000000..b804d4611 --- /dev/null +++ b/tests/sm/con1dpm1.in @@ -0,0 +1,39 @@ +con1dpm1.out +# +Concrete Plasticity Uniaxial Tension (CDPM1 by Grassl and Jirasek) +StaticStructural nsteps 5 solverType "calm" initialguess 0 rtolf 2.e-3 reqIterations 10 stiffMode 2 maxiter 10 stepLength 1.e-4 minsteplength 1.e-4 Psi 0. hpcmode 2 hpc 2 2 1 hpcw 1 1. nmodules 1 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +# +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 5 nltf 1 nic 0 nset 5 +node 1 coords 3 0. 0. 0. +node 2 coords 3 1. 0. 0. +node 3 coords 3 0. 1. 0. +node 4 coords 3 0. 0. 1. +# +ltrspace 1 nodes 4 1 2 3 4 +# +SimpleCS 1 material 1 set 1 +# +ConcreteDPM 1 d 0. E 30.e9 n 0.2 talpha 0. fc 30.e6 ft 3.e6 ecc 0.525 Ahard 8.e-2 Bhard 3.e-3 Chard 2. Dhard 1.e-6 Asoft 35. dilation -0.85 yieldtol 1.e-8 newtoniter 300 wf 300.e-6 +# +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 2 3 values 3 0. 0. 0. set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 2 2 3 values 2 0. 0. set 3 +BoundaryCondition 3 loadTimeFunction 1 dofs 2 1 3 values 2 0. 0. set 4 +BoundaryCondition 4 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 5 +NodalLoad 5 loadTimeFunction 1 dofs 3 1 2 3 Components 3 1.e6 0. 0. set 3 reference +# +ConstantFunction 1 f(t) 1. +Set 1 elementranges {1} +Set 2 nodes 1 1 +Set 3 nodes 1 2 +Set 4 nodes 1 3 +Set 5 nodes 1 4 + +#%BEGIN_CHECK% +#ELEMENT tStep 1 number 1 gp 1 keyword 4 component 1 value 1e-04 tolerance 1e-10 +#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value 2.94847927e+06 tolerance 1e-2 +#ELEMENT tStep 5 number 1 gp 1 keyword 4 component 1 value 5e-04 tolerance 1e-10 +#ELEMENT tStep 5 number 1 gp 1 keyword 1 component 1 value 6.21765727e+05 tolerance 1e-2 +#%END_CHECK% diff --git a/tests/sm/con1dpm2.in b/tests/sm/con1dpm2.in new file mode 100644 index 000000000..3ebf52c84 --- /dev/null +++ b/tests/sm/con1dpm2.in @@ -0,0 +1,41 @@ +con1dpm2.out +# +Concrete Plasticity Uniaxial Compression (CDPM1 by Grassl and Jirasek) +StaticStructural nsteps 10 solverType "calm" initialguess 0 rtolf 2.e-3 reqIterations 100 stiffMode 1 maxiter 100 stepLength 5.e-4 minsteplength 5.e-4 Psi 0. hpcmode 2 hpc 2 2 1 hpcw 1 -1. nmodules 1 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +# +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 5 nltf 1 nic 0 nset 5 +node 1 coords 3 0. 0. 0. +node 2 coords 3 1. 0. 0. +node 3 coords 3 0. 1. 0. +node 4 coords 3 0. 0. 1. +# +ltrspace 1 nodes 4 1 2 3 4 +# +SimpleCS 1 material 1 set 1 +# +ConcreteDPM 1 d 0. E 30.e9 n 0.2 talpha 0. fc 30.e6 ft 3.e6 ecc 0.525 Ahard 8.e-2 Bhard 3.e-3 Chard 2. Dhard 1.e-6 Asoft 35. dilation -0.85 yieldtol 1.e-8 newtoniter 300 wf 300.e-6 +# +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 2 3 values 3 0. 0. 0. set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 2 2 3 values 2 0. 0. set 3 +BoundaryCondition 3 loadTimeFunction 1 dofs 2 1 3 values 2 0. 0. set 4 +BoundaryCondition 4 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 5 +NodalLoad 5 loadTimeFunction 1 dofs 3 1 2 3 Components 3 1.e6 0. 0. set 3 reference +# +ConstantFunction 1 f(t) 1. +Set 1 elementranges {1} +Set 2 nodes 1 1 +Set 3 nodes 1 2 +Set 4 nodes 1 3 +Set 5 nodes 1 4 + +#%BEGIN_CHECK% +#ELEMENT tStep 1 number 1 gp 1 keyword 4 component 1 value -5e-04 tolerance 1e-10 +#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value -1.40303082e+07 tolerance 1e-1 +#ELEMENT tStep 5 number 1 gp 1 keyword 4 component 1 value -2.5e-03 tolerance 1e-10 +#ELEMENT tStep 5 number 1 gp 1 keyword 1 component 1 value -2.99825545e+07 tolerance 1e-1 +#ELEMENT tStep 10 number 1 gp 1 keyword 4 component 1 value -5.0e-03 tolerance 1e-10 +#ELEMENT tStep 10 number 1 gp 1 keyword 1 component 1 value -2.62968729e+07 tolerance 1e-1 +#%END_CHECK% diff --git a/tests/sm/con1dpm3.in b/tests/sm/con1dpm3.in new file mode 100644 index 000000000..5e9e1d420 --- /dev/null +++ b/tests/sm/con1dpm3.in @@ -0,0 +1,39 @@ +con1dpm3.out +# +Concrete Plasticity Triaxial Compression (CDPM1 by Grassl and Jirasek) +StaticStructural nsteps 5 solverType "calm" rtolf 2.e-3 reqIterations 100 stiffMode 2 maxiter 100 stepLength 5.e-4 minsteplength 5.e-4 Psi 0. hpcmode 2 hpc 2 2 1 hpcw 1 -1. nmodules 1 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +# +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 7 nltf 1 nic 0 nset 5 +node 1 coords 3 0. 0. 0. +node 2 coords 3 1. 0. 0. +node 3 coords 3 0. 1. 0. +node 4 coords 3 0. 0. 1. +# +ltrspace 1 nodes 4 1 2 3 4 +# +SimpleCS 1 material 1 set 1 +# +ConcreteDPM 1 d 0. E 30.e9 n 0.2 talpha 0. fc 30.e6 ft 3.e6 ecc 0.525 Ahard 8.e-2 Bhard 3.e-3 Chard 2. Dhard 1.e-6 Asoft 35. dilation -0.85 yieldtol 1.e-8 newtoniter 300 wf 300.e-6 +# +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 2 3 values 3 0. 0. 0. set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 2 2 3 values 2 0. 0. set 3 +BoundaryCondition 3 loadTimeFunction 1 dofs 2 1 3 values 2 0. 0. set 4 +BoundaryCondition 4 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 5 +NodalLoad 5 loadTimeFunction 1 dofs 3 1 2 3 Components 3 1.e6 0. 0. set 3 reference +NodalLoad 6 loadTimeFunction 1 dofs 3 1 2 3 Components 3 0. 1.e6 0. set 4 reference +NodalLoad 7 loadTimeFunction 1 dofs 3 1 2 3 Components 3 0. 0. 1.e6 set 5 reference +# +ConstantFunction 1 f(t) 1. +Set 1 elementranges {1} +Set 2 nodes 1 1 +Set 3 nodes 1 2 +Set 4 nodes 1 3 +Set 5 nodes 1 4 + +#%BEGIN_CHECK% tolerance 20 +#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value -1.86961133e+07 +#ELEMENT tStep 5 number 1 gp 1 keyword 1 component 1 value -4.26938378e+07 +#%END_CHECK% diff --git a/tests/sm/con2dpm1.in b/tests/sm/con2dpm1.in index ed25de296..84f739c98 100644 --- a/tests/sm/con2dpm1.in +++ b/tests/sm/con2dpm1.in @@ -33,7 +33,7 @@ Set 5 nodes 1 4 #%BEGIN_CHECK% tolerance 1e-3 #ELEMENT tStep 1 number 1 gp 1 keyword 4 component 1 value 1e-04 -#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value 9.88809403e+05 +#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value 9.88709340e+05 #ELEMENT tStep 5 number 1 gp 1 keyword 4 component 1 value 5e-04 -#ELEMENT tStep 5 number 1 gp 1 keyword 1 component 1 value 7.86386138e+05 +#ELEMENT tStep 5 number 1 gp 1 keyword 1 component 1 value 7.86315482e+05 #%END_CHECK% diff --git a/tests/sm/con2dpm10.in b/tests/sm/con2dpm10.in new file mode 100644 index 000000000..a4bdaa535 --- /dev/null +++ b/tests/sm/con2dpm10.in @@ -0,0 +1,30 @@ +con2dpm10.out +# +CDPM2 (Concretedpm2) Test of strain rate effect in tension first slope +NonLinearStatic nmsteps 1 nsteps 1 contextOutputStep 1000 nmodules 1 +nsteps 10 rtolv 1.e-3 reqIterations 4000 stiffMode 2 maxiter 4000 controllmode 0 stepLength 5.e-4 minsteplength 5.e-4 Psi 0. hpcmode 2 hpc 2 3 2 hpcw 1 1. donotfixload +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 4 nltf 1 nic 0 +node 1 coords 3 0. 0. 0. bc 3 1 1 1 +node 2 coords 3 1. 0. 0. bc 3 0 1 1 load 1 2 +node 3 coords 3 0. 1. 0. bc 3 0 0 1 load 1 3 +node 4 coords 3 0. 0. 1. bc 3 1 1 0 load 1 4 +# +ltrspace 1 nodes 4 1 2 3 4 mat 1 crossSect 1 +# +SimpleCS 1 +# +con2dpm 1 d 0 E 30.e9 n 0.15 talpha 0. wf 9.3755e-5 fc 47.4e6 ft 4.74e6 hp 0.5 yieldtol 1.e-10 asoft 15. stype 2 helem 0.1 sratetype 1 eratetype 2 deltat 1.e-3 +# +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +NodalLoad 2 loadTimeFunction 1 Components 3 0.e6 0. 0. +NodalLoad 3 loadTimeFunction 1 Components 3 0. 1.e6 0. +NodalLoad 4 loadTimeFunction 1 Components 3 0. 0. 0.e6 +# +ConstantFunction 1 f(t) 1. +#%BEGIN_CHECK% tolerance 1e-1 +#ELEMENT tStep 3 number 1 gp 1 keyword 4 component 2 value 1.5e-3 +#ELEMENT tStep 3 number 1 gp 1 keyword 1 component 2 value 1.79449874e+06 +#%END_CHECK% diff --git a/tests/sm/con2dpm11.in b/tests/sm/con2dpm11.in new file mode 100644 index 000000000..857cbad19 --- /dev/null +++ b/tests/sm/con2dpm11.in @@ -0,0 +1,30 @@ +con2dpm11.out +# +CDPM2 (Concretedpm2) Test of strain rate effect in tension type 2 +NonLinearStatic nmsteps 1 nsteps 1 contextOutputStep 1000 nmodules 1 +nsteps 10 rtolv 1.e-3 reqIterations 4000 stiffMode 2 maxiter 4000 controllmode 0 stepLength 5.e-4 minsteplength 5.e-4 Psi 0. hpcmode 2 hpc 2 3 2 hpcw 1 1. donotfixload +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 4 nltf 1 nic 0 +node 1 coords 3 0. 0. 0. bc 3 1 1 1 +node 2 coords 3 1. 0. 0. bc 3 0 1 1 load 1 2 +node 3 coords 3 0. 1. 0. bc 3 0 0 1 load 1 3 +node 4 coords 3 0. 0. 1. bc 3 1 1 0 load 1 4 +# +ltrspace 1 nodes 4 1 2 3 4 mat 1 crossSect 1 +# +SimpleCS 1 +# +con2dpm 1 d 0 E 30.e9 n 0.15 talpha 0. wf 9.3755e-5 fc 47.4e6 ft 4.74e6 hp 0.5 yieldtol 1.e-10 asoft 15. stype 2 helem 0.1 sratetype 2 eratetype 1 deltat 1.e-6 +# +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +NodalLoad 2 loadTimeFunction 1 Components 3 0.e6 0. 0. +NodalLoad 3 loadTimeFunction 1 Components 3 0. 1.e6 0. +NodalLoad 4 loadTimeFunction 1 Components 3 0. 0. 0.e6 +# +ConstantFunction 1 f(t) 1. +#%BEGIN_CHECK% tolerance 1e-1 +#ELEMENT tStep 3 number 1 gp 1 keyword 4 component 2 value 1.5e-3 +#ELEMENT tStep 3 number 1 gp 1 keyword 1 component 2 value 5.93757318e+06 +#%END_CHECK% diff --git a/tests/sm/con2dpm12.in b/tests/sm/con2dpm12.in new file mode 100644 index 000000000..3e6d30313 --- /dev/null +++ b/tests/sm/con2dpm12.in @@ -0,0 +1,30 @@ +con2dpm12.out +# +CDPM2 (Concretedpm2) Test of strain rate effect in tension type 3 +NonLinearStatic nmsteps 1 nsteps 1 contextOutputStep 1000 nmodules 1 +nsteps 10 rtolv 1.e-3 reqIterations 4000 stiffMode 2 maxiter 4000 controllmode 0 stepLength 5.e-4 minsteplength 5.e-4 Psi 0. hpcmode 2 hpc 2 3 2 hpcw 1 1. donotfixload +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 4 nltf 1 nic 0 +node 1 coords 3 0. 0. 0. bc 3 1 1 1 +node 2 coords 3 1. 0. 0. bc 3 0 1 1 load 1 2 +node 3 coords 3 0. 1. 0. bc 3 0 0 1 load 1 3 +node 4 coords 3 0. 0. 1. bc 3 1 1 0 load 1 4 +# +ltrspace 1 nodes 4 1 2 3 4 mat 1 crossSect 1 +# +SimpleCS 1 +# +con2dpm 1 d 0 E 30.e9 n 0.15 talpha 0. wf 9.3755e-5 fc 47.4e6 ft 4.74e6 hp 0.5 yieldtol 1.e-10 asoft 15. stype 2 helem 0.1 sratetype 2 eratetype 0 deltat 1.e-6 +# +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +NodalLoad 2 loadTimeFunction 1 Components 3 0.e6 0. 0. +NodalLoad 3 loadTimeFunction 1 Components 3 0. 1.e6 0. +NodalLoad 4 loadTimeFunction 1 Components 3 0. 0. 0.e6 +# +ConstantFunction 1 f(t) 1. +#%BEGIN_CHECK% tolerance 1e-1 +#ELEMENT tStep 3 number 1 gp 1 keyword 4 component 2 value 1.5e-3 +#ELEMENT tStep 3 number 1 gp 1 keyword 1 component 2 value 9.84709014e+03 +#%END_CHECK% diff --git a/tests/sm/con2dpm2.in b/tests/sm/con2dpm2.in index db9838720..e1a93290f 100644 --- a/tests/sm/con2dpm2.in +++ b/tests/sm/con2dpm2.in @@ -35,5 +35,5 @@ Set 5 nodes 1 4 #ELEMENT tStep 1 number 1 gp 1 keyword 4 component 1 value -5e-04 #ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value -2.54481363e+06 #ELEMENT tStep 5 number 1 gp 1 keyword 4 component 1 value 2.5e-03 -#ELEMENT tStep 5 number 1 gp 1 keyword 1 component 1 value -1.68219235e+06 +#ELEMENT tStep 5 number 1 gp 1 keyword 1 component 1 value -1.68202554e+06 #%END_CHECK% diff --git a/tests/sm/con2dpm4.in b/tests/sm/con2dpm4.in index ea2c3ae1e..45bdd008a 100644 --- a/tests/sm/con2dpm4.in +++ b/tests/sm/con2dpm4.in @@ -1,7 +1,7 @@ con2dpm4.out # Concrete Plasticity Triaxial Tension -StaticStructural nsteps 2 solverType "calm" rtolf 2.e-3 reqIterations 100 stiffMode 2 maxiter 100 stepLength 5.e-4 minsteplength 5.e-4 Psi 0. hpcmode 2 hpc 2 2 1 hpcw 1 1. nmodules 1 +StaticStructural nsteps 2 solverType "calm" rtolf 2.e-3 reqIterations 100 stiffMode 1 maxiter 100 stepLength 5.e-4 minsteplength 5.e-4 Psi 0. hpcmode 2 hpc 2 2 1 hpcw 1 1. nmodules 1 errorcheck domain 3d OutputManager tstep_all dofman_all element_all @@ -34,6 +34,6 @@ Set 4 nodes 1 3 Set 5 nodes 1 4 #%BEGIN_CHECK% tolerance 5e-4 -#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value 7.34037449e+05 +#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value 7.33978289e+05 #ELEMENT tStep 2 number 1 gp 1 keyword 1 component 1 value 3.23305980e+05 #%END_CHECK% diff --git a/tests/sm/con2dpm5.in b/tests/sm/con2dpm5.in new file mode 100644 index 000000000..761fbcec5 --- /dev/null +++ b/tests/sm/con2dpm5.in @@ -0,0 +1,21 @@ +con2dpm5.out +Test of 1D CDPM2 on a 1D truss element +NonLinearStatic nmsteps 1 nsteps 50 contextOutputStep 10000000 nmodules 0 +nsteps 3 rtolv 1.e-3 controllmode 0 stepLength 5.e-5 minsteplength 1.e-5 Psi 0. hpcmode 2 hpc 2 2 1 hpcw 1 1. reqIterations 100000 stiffMode 1 maxiter 100000 donotfixload +domain 1DTruss +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 2 nltf 1 nic 0 +node 1 coords 3 0.0 0.0 0.0 bc 1 1 +node 2 coords 3 0.25000 0.0 0.0 load 1 2 +truss1d 1 nodes 2 1 2 mat 1 crossSect 1 +SimpleCS 1 thick 1.0 width 0.10 +con2dpm 1 d 0 E 20.e9 n 0.2 talpha 0. wf 800.e-6 fc 35e6 ft 2.e6 hp 0.025 yieldtol 1.e-10 asoft 7. stype 2 damflag 3 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +NodalLoad 2 loadTimeFunction 1 components 1 1.0 +ConstantFunction 1 f(t) 1.0 +###### Used for Extractor +### +#%BEGIN_CHECK% +#NODE number 2 dof 1 unknown d +#LOADLEVEL +#%END_CHECK% \ No newline at end of file diff --git a/tests/sm/con2dpm6.in b/tests/sm/con2dpm6.in new file mode 100644 index 000000000..9e0ba26df --- /dev/null +++ b/tests/sm/con2dpm6.in @@ -0,0 +1,37 @@ +con2dpm6.out +# +Concrete Plasticity 2 Thermal Loading +StaticStructural nsteps 1 initialguess 1 rtolf 1.e-3 stiffMode 2 maxiter 1000 nmodules 1 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +# +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 5 nltf 1 nic 0 nset 5 +node 1 coords 3 0. 0. 0. +node 2 coords 3 1. 0. 0. +node 3 coords 3 0. 1. 0. +node 4 coords 3 0. 0. 1. +# +ltrspace 1 nodes 4 1 2 3 4 +# +SimpleCS 1 material 1 set 1 +# +con2dpm 1 d 0 E 30.e9 n 0.15 talpha 0.1 wf 9.3755e-4 fc 3.e6 ft 1.e6 hp 0.01 yieldtol 1.e-5 asoft 5. stype 1 helem 0.1 kinit 0.3 +# +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 2 3 values 3 0. 0. 0. set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 2 2 3 values 2 0. 0. set 3 +BoundaryCondition 3 loadTimeFunction 1 dofs 2 1 3 values 2 0. 0. set 4 +BoundaryCondition 4 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 5 +StructTemperatureLoad 5 loadTimeFunction 1 Components 2 1.0 0.0 set 1 +# +ConstantFunction 1 f(t) 1. +Set 1 elementranges {1} +Set 2 nodes 1 1 +Set 3 nodes 1 2 +Set 4 nodes 1 3 +Set 5 nodes 1 4 + +#%BEGIN_CHECK% tolerance 1.e-3 +#ELEMENT tStep 1 number 1 gp 1 keyword 4 component 1 value 0.1 +#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value 0.0 +#%END_CHECK% diff --git a/tests/sm/con2dpm7.in b/tests/sm/con2dpm7.in new file mode 100644 index 000000000..a8676e25c --- /dev/null +++ b/tests/sm/con2dpm7.in @@ -0,0 +1,37 @@ +con2dpm7.out +# +Concrete Plasticity 2 Thermal Loading +StaticStructural nsteps 1 initialguess 1 rtolf 1.e-3 stiffMode 2 maxiter 1000 nmodules 1 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +# +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 5 nltf 1 nic 0 nset 5 +node 1 coords 3 0. 0. 0. +node 2 coords 3 1. 0. 0. +node 3 coords 3 0. 1. 0. +node 4 coords 3 0. 0. 1. +# +ltrspace 1 nodes 4 1 2 3 4 +# +SimpleCS 1 material 1 set 1 +# +con2dpm 1 d 0 E 30.e9 n 0.15 talpha 0.0001 wf 9.3755e-4 fc 3.e6 ft 1.e6 hp 0.01 yieldtol 1.e-5 asoft 5. stype 1 helem 0.1 kinit 0.3 +# +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 2 3 values 3 0. 0. 0. set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 3 1 2 3 values 3 0. 0. 0. set 3 +BoundaryCondition 3 loadTimeFunction 1 dofs 2 1 3 values 2 0. 0. set 4 +BoundaryCondition 4 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 5 +StructTemperatureLoad 5 loadTimeFunction 1 Components 2 -1.0 0.0 set 1 +# +ConstantFunction 1 f(t) 1. +Set 1 elementranges {1} +Set 2 nodes 1 1 +Set 3 nodes 1 2 +Set 4 nodes 1 3 +Set 5 nodes 1 4 + +#%BEGIN_CHECK% tolerance 1.e-3 +#ELEMENT tStep 1 number 1 gp 1 keyword 4 component 1 value 0.0 +#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value 9.88739801e+05 +#%END_CHECK% diff --git a/tests/sm/con2dpm8.in b/tests/sm/con2dpm8.in new file mode 100644 index 000000000..a181e975c --- /dev/null +++ b/tests/sm/con2dpm8.in @@ -0,0 +1,16 @@ +con2dpm8.out +Test of thermal strain for 1D CDPM2 +StaticStructural nsteps 1 initialguess 1 rtolf 1.e-3 stiffMode 2 maxiter 1000 nmodules 0 +#errorcheck +domain 1DTruss +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 2 nltf 1 nic 0 nset 1 +node 1 coords 3 0.0 0.0 0.0 bc 1 1 +node 2 coords 3 0.25000 0.0 0.0 bc 1 1 +truss1d 1 nodes 2 1 2 mat 1 crossSect 1 +SimpleCS 1 thick 1.0 width 0.10 +con2dpm 1 d 0 E 20.e9 n 0.2 talpha 0.0001 wf 800.e-6 fc 35e6 ft 2.e6 hp 0.025 yieldtol 1.e-10 asoft 7. stype 2 damflag 3 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +StructTemperatureLoad 2 loadTimeFunction 1 Components 2 -2.0 0.0 set 1 +ConstantFunction 1 f(t) 1.0 +Set 1 elementranges {1} diff --git a/tests/sm/con2dpm9.in b/tests/sm/con2dpm9.in new file mode 100644 index 000000000..590ddf016 --- /dev/null +++ b/tests/sm/con2dpm9.in @@ -0,0 +1,30 @@ +con2dpm9.out +# +CDPM2 (Concretedpm2) Test of strain rate effect in tension second slope +NonLinearStatic nmsteps 1 nsteps 1 contextOutputStep 1000 nmodules 1 +nsteps 10 rtolv 1.e-3 reqIterations 4000 stiffMode 2 maxiter 4000 controllmode 0 stepLength 5.e-4 minsteplength 5.e-4 Psi 0. hpcmode 2 hpc 2 3 2 hpcw 1 1. donotfixload +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 4 nltf 1 nic 0 +node 1 coords 3 0. 0. 0. bc 3 1 1 1 +node 2 coords 3 1. 0. 0. bc 3 0 1 1 load 1 2 +node 3 coords 3 0. 1. 0. bc 3 0 0 1 load 1 3 +node 4 coords 3 0. 0. 1. bc 3 1 1 0 load 1 4 +# +ltrspace 1 nodes 4 1 2 3 4 mat 1 crossSect 1 +# +SimpleCS 1 +# +con2dpm 1 d 0 E 30.e9 n 0.15 talpha 0. wf 9.3755e-5 fc 47.4e6 ft 4.74e6 hp 0.5 yieldtol 1.e-10 asoft 15. stype 2 helem 0.1 sratetype 2 eratetype 2 deltat 1.e-6 +# +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +NodalLoad 2 loadTimeFunction 1 Components 3 0.e6 0. 0. +NodalLoad 3 loadTimeFunction 1 Components 3 0. 1.e6 0. +NodalLoad 4 loadTimeFunction 1 Components 3 0. 0. 0.e6 +# +ConstantFunction 1 f(t) 1. +#%BEGIN_CHECK% tolerance 1e-1 +#ELEMENT tStep 3 number 1 gp 1 keyword 4 component 2 value 1.5e-3 +#ELEMENT tStep 3 number 1 gp 1 keyword 1 component 2 value 1.94788450e+07 +#%END_CHECK% diff --git a/tests/sm/concrete_fcm_visco.in b/tests/sm/concrete_fcm_visco.in new file mode 100644 index 000000000..60ee7e850 --- /dev/null +++ b/tests/sm/concrete_fcm_visco.in @@ -0,0 +1,64 @@ +concrete_fcm_visco.out +# +Single element creep test +# +nonlinearstatic nsteps 25 rtolv 1.e-8 MaxIter 5000 controllmode 1 stiffMode 0 updateelasticstiffnessflag manrmsteps 1 deltatfunction 3 nmodules 1 +#vtkxml tstep_all domain_all primvars 1 1 vars 3 1 4 114 stype 2 +# +errorcheck +# +domain 2dPlaneStress +# +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 1 ncrosssect 1 nmat 2 nbc 3 nic 0 nltf 3 nset 3 +# +node 1 coords 2 0.0 0.0 +node 2 coords 2 0.1 0.0 +node 3 coords 2 0.0 0.1 +node 4 coords 2 0.1 0.1 +# +# +# ELEMENTS +# +planestress2d 1 nodes 4 1 2 4 3 crossSect 1 +# +# CROSSECTION +# +SimpleCS 1 thick 1.0 material 2 +# +# +# MATERIAL +# +# +mps 1 d 0. n 0.2 talpha 0. referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1000. relMatAge 28. CoupledAnalysisType 0 +# +ConcreteFcmViscoelastic 2 d 0.0 talpha 0. E 1. n 0.2 Gf 150.e-6 ft 3. softtype 1 sheartype 2 sf 20. multiplecrackshear shearstrengthtype 1 ncracks 2 shearCoeffNumer 0.001 normalCoeffNumer 0.001 viscomat 1 +# +# BOUNDARY CONDITIONS +# +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0. set 2 +BoundaryCondition 3 loadTimeFunction 2 dofs 1 1 values 1 1.e-3 set 3 +# +# +# TIME FUNCTION +# +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 nPoints 3 t 4 0. 0.1 100. 1.e4 f(t) 4 0. 0.015 0.03 0.03 +PiecewiseLinfunction 3 npoints 25 t 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 f(t) 25 0.0001 0.0002 0.0003 0.0005 0.001 0.003 0.005 0.01 0.03 0.05 0.1 0.3 0.5 1 3 5 10 30 50 100 300 500 1000 3000 5000 +# +Set 1 nodes 2 1 3 +Set 2 nodes 1 1 +Set 3 nodes 2 2 4 +# +#TIME +#ELEMENT number 1 gp 1 keyword stresses component 1 +#ELEMENT number 1 gp 1 keyword strains component 1 +#%BEGIN_CHECK% +#ELEMENT tStep 10 number 1 gp 1 keyword 1 component 1 value 2.80973766e+00 tolerance 1.e-6 +#ELEMENT tStep 13 number 1 gp 1 keyword 1 component 1 value 2.59407647e+00 tolerance 1.e-6 +#ELEMENT tStep 16 number 1 gp 1 keyword 1 component 1 value 2.58931208e+00 tolerance 1.e-6 +#ELEMENT tStep 19 number 1 gp 1 keyword 1 component 1 value 2.20529122e+00 tolerance 1.e-6 +#ELEMENT tStep 22 number 1 gp 1 keyword 1 component 1 value 1.94566183e+00 tolerance 1.e-6 +#ELEMENT tStep 25 number 1 gp 1 keyword 1 component 1 value 1.70116204e+00 tolerance 1.e-6 +#%END_CHECK% diff --git a/tests/sm/context01.in.0 b/tests/sm/context01.in.0 new file mode 100644 index 000000000..6b6738f6b --- /dev/null +++ b/tests/sm/context01.in.0 @@ -0,0 +1,103 @@ +context01.out.0 +Patch test of PlaneStress2d elements -> pure compression in x direction +nonlinearstatic nsteps 2 nmodules 1 controllmode 1 +errorcheck +domain 2dPlaneStress +OutputManager tstep_all dofman_all element_all +ndofman 8 nelem 5 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 2 nset 4 +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.0 4.0 0.0 +node 3 coords 3 2.0 2.0 0.0 +node 4 coords 3 3.0 1.0 0.0 +node 5 coords 3 8.0 0.8 0.0 +node 6 coords 3 7.0 3.0 0.0 +node 7 coords 3 9.0 0.0 0.0 +node 8 coords 3 9.0 4.0 0.0 +PlaneStress2d 1 nodes 4 1 4 3 2 +PlaneStress2d 2 nodes 4 1 7 5 4 +PlaneStress2d 3 nodes 4 4 5 6 3 +PlaneStress2d 4 nodes 4 3 6 8 2 +PlaneStress2d 5 nodes 4 5 7 8 6 +SimpleCS 1 thick 0.15 material 1 set 1 +IsoLE 1 d 0. E 15.0 n 0.25 tAlpha 0.000012 +BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0.0 0.0 set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0.0 set 3 +NodalLoad 3 loadTimeFunction 2 dofs 2 1 2 Components 2 -2.5 0.0 set 4 +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 1.0 +#PiecewiseLinFunction 2 t 2 0. 101. f(t) 2 1. 102. +Set 1 elementranges {(1 5)} +Set 2 nodes 2 1 2 +Set 3 nodes 6 3 4 5 6 7 8 +Set 4 nodes 2 7 8 +# +# +# +##%BEGIN_CHECK% tolerance 1.e-4 +## check reactions +#REACTION tStep 1 number 1 dof 1 value 2.5 +#REACTION tStep 1 number 1 dof 2 value 1.40625 +#REACTION tStep 1 number 2 dof 1 value 2.5 +#REACTION tStep 1 number 2 dof 2 value -1.40625 +#REACTION tStep 1 number 7 dof 2 value 1.40625 +#REACTION tStep 1 number 8 dof 2 value -1.40625 +## check all nodes +#NODE tStep 1 number 3 dof 1 unknown d value -1.041666666 +#NODE tStep 1 number 4 dof 1 unknown d value -1.5625 +#NODE tStep 1 number 5 dof 1 unknown d value -4.166666666 +#NODE tStep 1 number 6 dof 1 unknown d value -3.645833333 +#NODE tStep 1 number 7 dof 1 unknown d value -4.6875 +#NODE tStep 1 number 8 dof 1 unknown d value -4.6875 +## check element no. 1 strain vector +#ELEMENT tStep 1 number 1 gp 1 keyword 4 component 1 value -0.520833333 +#ELEMENT tStep 1 number 1 gp 1 keyword 4 component 2 value 0.0 +#ELEMENT tStep 1 number 1 gp 1 keyword 4 component 6 value 0.0 +## check element no. 1 stress vector +#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value -8.333333333 +#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 2 value -2.083333333 +#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 6 value 0.0 +## +#ELEMENT tStep 1 number 2 gp 2 keyword 4 component 1 value -0.520833333 +#ELEMENT tStep 1 number 2 gp 2 keyword 4 component 2 value 0.0 +#ELEMENT tStep 1 number 2 gp 2 keyword 4 component 6 value 0.0 +#ELEMENT tStep 1 number 2 gp 2 keyword 1 component 1 value -8.333333333 +#ELEMENT tStep 1 number 2 gp 2 keyword 1 component 2 value -2.083333333 +#ELEMENT tStep 1 number 2 gp 2 keyword 1 component 6 value 0.0 +## +#ELEMENT tStep 1 number 3 gp 3 keyword 4 component 1 value -0.520833333 +#ELEMENT tStep 1 number 3 gp 3 keyword 4 component 2 value 0.0 +#ELEMENT tStep 1 number 3 gp 3 keyword 4 component 6 value 0.0 +#ELEMENT tStep 1 number 3 gp 3 keyword 1 component 1 value -8.333333333 +#ELEMENT tStep 1 number 3 gp 3 keyword 1 component 2 value -2.083333333 +#ELEMENT tStep 1 number 3 gp 3 keyword 1 component 6 value 0.0 +## +#ELEMENT tStep 1 number 4 gp 4 keyword 4 component 1 value -0.520833333 +#ELEMENT tStep 1 number 4 gp 4 keyword 4 component 2 value 0.0 +#ELEMENT tStep 1 number 4 gp 4 keyword 4 component 6 value 0.0 +#ELEMENT tStep 1 number 4 gp 4 keyword 1 component 1 value -8.333333333 +#ELEMENT tStep 1 number 4 gp 4 keyword 1 component 2 value -2.083333333 +#ELEMENT tStep 1 number 4 gp 4 keyword 1 component 6 value 0.0 +## +## step 2 +## +## check reactions +#REACTION tStep 2 number 1 dof 1 value 5.0 +#REACTION tStep 2 number 1 dof 2 value 2.8125 +#REACTION tStep 2 number 2 dof 1 value 5.0 +#REACTION tStep 2 number 2 dof 2 value -2.8125 +#REACTION tStep 2 number 7 dof 2 value 2.8125 +#REACTION tStep 2 number 8 dof 2 value -2.8125 +## check all nodes +#NODE tStep 2 number 3 dof 1 unknown d value -2.083333332 +#NODE tStep 2 number 4 dof 1 unknown d value -3.125 +#NODE tStep 2 number 5 dof 1 unknown d value -8.333333332 +#NODE tStep 2 number 6 dof 1 unknown d value -7.291666666 +#NODE tStep 2 number 7 dof 1 unknown d value -9.375 +#NODE tStep 2 number 8 dof 1 unknown d value -9.375 +#ELEMENT tStep 2 number 1 gp 1 keyword 4 component 1 value -1.041666666 +#ELEMENT tStep 2 number 1 gp 1 keyword 4 component 2 value 0.0 +#ELEMENT tStep 2 number 1 gp 1 keyword 4 component 6 value 0.0 +##%END_CHECK% +# +# + diff --git a/tests/sm/context01.sh b/tests/sm/context01.sh new file mode 100644 index 000000000..07b66b1f2 --- /dev/null +++ b/tests/sm/context01.sh @@ -0,0 +1,14 @@ +# +# this test check basic save/restore context functionality +# +OOFEM=$1 +echo "target executable: $OOFEM" +pwd + +echo "Command: $OOFEM -f context01.in.0 -c" +# run target on input and store context file +$OOFEM -f context01.in.0 -c +echo "Command: $OOFEM -f context01.in.0 -r 1" +# run target on the same file, but restarting from step 2 +$OOFEM -f context01.in.0 -r 1 + diff --git a/tests/sm/deactivate_1.in b/tests/sm/deactivate_1.in index 0ddb9dfe4..584eadc5b 100644 --- a/tests/sm/deactivate_1.in +++ b/tests/sm/deactivate_1.in @@ -1,6 +1,7 @@ deactivate_1.out Patch test of Truss2d elements -> simple structure with activated and deactivated element L IncrLinearStatic endOfTimeOfInterest 5.0 prescribedTimes 5 0.0 1.0 2.0 3.0 4.0 nmodules 1 +#StaticStructural nsteps 5 prescribedTimes 5 0.0 1.0 2.0 3.0 4.0 nmodules 1 errorcheck domain 2dTruss OutputManager tstep_all dofman_all element_all diff --git a/tests/sm/deactivate_2.in b/tests/sm/deactivate_2.in index 2e2abaa5a..4c25087df 100644 --- a/tests/sm/deactivate_2.in +++ b/tests/sm/deactivate_2.in @@ -1,6 +1,7 @@ deactivate_2.out Patch test of Truss2d elements -> simple structure with activated and deactivated element -nonlinearstatic nsteps 5 controlmode 1 rtolf 1.e-8 nmodules 1 +nonlinearstatic nsteps 3 controlmode 1 rtolf 1.e-8 nmodules 1 +#staticstructural nsteps 3 rtolf 1.e-8 nmodules 1 errorcheck domain 2dTruss OutputManager tstep_all dofman_all element_all @@ -16,15 +17,16 @@ SimpleCS 1 thick 0.1 width 1.0 material 1 set 1 IsoLE 1 d 1. E 10.0 n 0.2 tAlpha 0.000012 BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 1 BoundaryCondition 2 loadTimeFunction 1 dofs 1 3 values 1 0.0 set 3 -NodalLoad 3 loadTimeFunction 2 dofs 2 1 3 Components 2 0.0 1.0 set 2 +NodalLoad 3 loadTimeFunction 2 dofs 1 3 components 1 1.0 set 2 ConstantFunction 1 f(t) 1.0 PiecewiseLinFunction 2 t 5 0.0 1.0 2.0 3.0 4.0 f(t) 5 0.0 1.0 0.0 1.0 0.0 PiecewiseLinFunction 3 t 5 0.0 1.0 2.0 3.0 4.0 f(t) 5 1.0 0.0 1.0 1.0 0.0 +#PiecewiseLinFunction 2 t 6 0.0 1.0 2.0 3.0 4.0 5.0 f(t) 6 0.0 0.0 1.0 0.0 1.0 0.0 +#PiecewiseLinFunction 3 t 6 0.0 1.0 2.0 3.0 4.0 5.0 f(t) 6 0.0 1.0 0.0 1.0 1.0 0.0 Set 1 elementranges {(1 3)} Set 2 nodes 1 2 Set 3 nodes 2 1 4 # -# #%BEGIN_CHECK% tolerance 1.e-4 ## check nodal displacements #NODE tStep 1 number 2 dof 3 unknown d value 0.0 @@ -37,6 +39,7 @@ Set 3 nodes 2 1 4 #NODE tStep 4 number 3 dof 3 unknown d value 0.333333333334 #NODE tStep 5 number 2 dof 3 unknown d value 2.0 #NODE tStep 5 number 3 dof 3 unknown d value 0.0 +#%END_CHECK% ## element stresses and strains #ELEMENT tStep 1 number 1 gp 1 keyword 4 component 1 value 0.0 #ELEMENT tStep 1 number 2 gp 1 keyword 4 component 1 value 0.0 diff --git a/tests/sm/deepbeamFE2_01.in b/tests/sm/deepbeamFE2_01.in new file mode 100644 index 000000000..459efc62f --- /dev/null +++ b/tests/sm/deepbeamFE2_01.in @@ -0,0 +1,112 @@ +deepbeamFE2_01.out +FE2 analysis of a reinforced concrete deep beam - Dirichlet-Dirichlet BC. Added by Adam Sciegaj +StaticStructural nsteps 2 deltat 1.0 constrainednrminiter 5 rtolf 1.0e-3 MaxIter 20 minIter 1 initialguess 1 nmodules 1 +errorcheck +#vtkxml tstep_all domain_all vars 4 1 4 5 12 cellvars 1 47 stype 2 +#vtkxml tstep_all domain_all vars 4 1 4 5 12 ipvars 3 1 4 5 +#matlab tstep_all mesh data specials reactionforces integrationpoints internalvars 2 1 4 +domain 2dplanestress +OutputManager tstep_all dofman_all element_all +ndofman 58 nelem 23 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 2 nset 4 +rigidarmnode 1 coords 3 3.32 4.0 0.0 master 19 dofidmask 3 1 2 6 doftype 3 2 2 2 masterMask 3 1 1 1 +rigidarmnode 2 coords 3 4.08 4.0 0.0 master 19 dofidmask 3 1 2 6 doftype 3 2 2 2 masterMask 3 1 1 1 +node 3 coords 3 5.7 4.0 0.0 +node 4 coords 3 5.7 0.0 0.0 +rigidarmnode 5 coords 3 0.9 0.0 0.0 master 11 dofidmask 3 1 2 6 doftype 3 2 2 2 masterMask 3 1 1 1 +rigidarmnode 6 coords 3 0.0 0.0 0.0 master 11 dofidmask 3 1 2 6 doftype 3 2 2 2 masterMask 3 1 1 1 +node 7 coords 3 0.0 4.0 0.0 +node 8 coords 3 0.0 2.0 0.0 +node 9 coords 3 0.0 3.0 0.0 +node 10 coords 3 0.0 1.0 0.0 +node 11 coords 3 0.45 0.0 0.0 dofidmask 3 1 2 6 +node 12 coords 3 3.3 0.0 0.0 +node 13 coords 3 2.1 0.0 0.0 +node 14 coords 3 4.5 0.0 0.0 +node 15 coords 3 5.7 2.0 0.0 +node 16 coords 3 5.7 1.0 0.0 +node 17 coords 3 5.7 3.0 0.0 +node 18 coords 3 4.89 4.0 0.0 +node 19 coords 3 3.7 4.0 0.0 dofidmask 3 1 2 6 +node 20 coords 3 1.66 4.0 0.0 +node 21 coords 3 2.49 4.0 0.0 +node 22 coords 3 0.83 4.0 0.0 +node 23 coords 3 0.903826 1.23156 0.0 +node 24 coords 3 4.23313 1.48258 0.0 +node 25 coords 3 3.60783 2.82575 0.0 +node 26 coords 3 2.43967 1.44487 0.0 +node 27 coords 3 1.30010 2.53433 0.0 +node 28 coords 3 2.55749 3.04749 0.0 +node 29 coords 3 4.65873 2.91318 0.0 +node 30 coords 3 3.46391 3.41287 0.0 +node 31 coords 3 2.93875 3.52375 0.0 +node 32 coords 3 3.84391 3.41287 0.0 +node 33 coords 3 4.36937 3.45659 0.0 +node 34 coords 3 5.17937 3.45659 0.0 +node 35 coords 3 4.96656 0.741292 0.0 +node 36 coords 3 0.901913 0.61578 0.0 +node 37 coords 3 1.66983 0.722433 0.0 +node 38 coords 3 0.451913 0.61578 0.0 +node 39 coords 3 0.650049 3.26717 0.0 +node 40 coords 3 0.451913 1.61578 0.0 +node 41 coords 3 0.650049 2.26717 0.0 +node 42 coords 3 3.76656 0.741292 0.0 +node 43 coords 3 2.86983 0.722433 0.0 +node 44 coords 3 4.96656 1.74129 0.0 +node 45 coords 3 5.17937 2.45659 0.0 +node 46 coords 3 1.48005 3.26717 0.0 +node 47 coords 3 2.10875 3.52375 0.0 +node 48 coords 3 1.67175 1.33821 0.0 +node 49 coords 3 1.10196 1.88295 0.0 +node 50 coords 3 3.92048 2.15417 0.0 +node 51 coords 3 3.33640 1.46372 0.0 +node 52 coords 3 4.44593 2.19788 0.0 +node 53 coords 3 3.02375 2.13531 0.0 +node 54 coords 3 3.08266 2.93662 0.0 +node 55 coords 3 4.13328 2.86947 0.0 +node 56 coords 3 1.86988 1.98960 0.0 +node 57 coords 3 2.49858 2.24618 0.0 +node 58 coords 3 1.92879 2.79091 0.0 +qtrplstr 1 nodes 6 8 27 7 41 39 9 +qtrplstr 2 nodes 6 29 25 24 55 50 52 +qtrplstr 3 nodes 6 29 15 3 45 17 34 +qtrplstr 4 nodes 6 27 8 23 41 40 49 +qtrplstr 5 nodes 6 25 2 1 32 19 30 +qtrplstr 6 nodes 6 28 1 20 31 21 47 +qtrplstr 7 nodes 6 28 20 27 47 46 58 +qtrplstr 8 nodes 6 28 27 26 58 56 57 +qtrplstr 9 nodes 6 26 12 24 43 42 51 +qtrplstr 10 nodes 6 28 25 1 54 30 31 +qtrplstr 11 nodes 6 26 24 25 51 50 53 +qtrplstr 12 nodes 6 24 4 15 35 16 44 +qtrplstr 13 nodes 6 29 3 2 34 18 33 +qtrplstr 14 nodes 6 23 5 26 36 37 48 +qtrplstr 15 nodes 6 29 2 25 33 32 55 +qtrplstr 16 nodes 6 23 8 6 40 10 38 +qtrplstr 17 nodes 6 23 6 5 38 11 36 +qtrplstr 18 nodes 6 23 26 27 48 56 49 +qtrplstr 19 nodes 6 27 20 7 46 22 39 +qtrplstr 20 nodes 6 24 12 4 42 14 35 +qtrplstr 21 nodes 6 29 24 15 52 44 45 +qtrplstr 22 nodes 6 26 5 12 37 13 43 +qtrplstr 23 nodes 6 28 26 25 57 53 54 +Set 1 elementranges { (1 23) } +#support +Set 2 nodes 1 11 +#point load +Set 3 nodes 1 19 +#symmetry line nodes +Set 4 nodes 5 3 4 15 16 17 +SimpleCS 1 thick 0.2 material 1 set 1 +structslipfe2material 1 d 1.0 filename deepbeamfe2_01.in.rve use_ext_stiffness dSdE 3 3 {3.625158673e+10 6.935152559e+9 2.470103608e+4; 6.935152559e+9 3.492710863e+10 2.987504531e+4; 2.470103608e+4 2.987504531e+4 1.387079737e+10} output_selected_el_gps 6 22 4 21 2 20 3 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 4 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0.0 set 2 +Boundarycondition 3 loadTimeFunction 2 dofs 1 2 values 1 -1e-4 set 3 +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 t 2 1.0 3.0 f(t) 2 1.0 3.0 + +#%BEGIN_CHECK% tolerance 1.e-2 +#NODE tStep 1 number 19 dof 2 unknown d value -1.00000e-4 +#REACTION tStep 1 number 19 dof 2 value -7.29535322e+04 +#NODE tStep 2 number 19 dof 2 unknown d value -2.00000e-4 +#REACTION tStep 2 number 19 dof 2 value -1.45907064e+05 +#%END_CHECK% diff --git a/tests/sm/deepbeamfe2_01.in.rve b/tests/sm/deepbeamfe2_01.in.rve new file mode 100644 index 000000000..63f433613 --- /dev/null +++ b/tests/sm/deepbeamfe2_01.in.rve @@ -0,0 +1,102 @@ +deepbeamFE2_01_rve.out +Reinforced concrete RVE - Dirichlet-Dirichelt BCs +StaticStructural nsteps 1 deltat 1.0 constrainednrminiter 5 rtolf 1.0e-3 MaxIter 30 minIter 1 stiffmode 0 initialguess 1 nmodules 0 suppress_output +#vtkxml tstep_all domain_all vars 5 1 4 5 12 52 ipvars 6 1 4 5 12 52 90 stype 1 regionsets 1 1 +#vtkxml tstep_all domain_all vars 1 12 ipvars 3 7 8 81 stype 1 regionsets 2 9 10 +#vtkxml tstep_all domain_all vars 2 98 99 ipvars 2 98 99 stype 0 regionsets 2 11 12 +domain 2dplanestress +OutputManager +ndofman 35 nelem 32 ncrosssect 8 nmat 4 nbc 1 nic 0 nltf 1 nset 12 nxfemman 0 +node 1 coords 3 -0.1 -0.1 0 +node 2 coords 3 0 -0.1 0 +node 3 coords 3 0.1 -0.1 0 +node 4 coords 3 0.1 0 0 +node 5 coords 3 0.1 0.1 0 +node 6 coords 3 0 0.1 0 +node 7 coords 3 -0.1 0.1 0 +node 8 coords 3 -0.1 0 0 +node 9 coords 3 -0.05 -0.1 0 +node 10 coords 3 0.05 -0.1 0 +node 11 coords 3 0.1 -0.05 0 +node 12 coords 3 0.1 0.05 0 +node 13 coords 3 0.05 0.1 0 +node 14 coords 3 -0.05 0.1 0 +node 15 coords 3 -0.1 0.05 0 +node 16 coords 3 -0.1 -0.05 0 +node 17 coords 3 -0.05 -0.05 0 +node 18 coords 3 -0.05 0 0 +node 19 coords 3 -0.05 0.05 0 +node 20 coords 3 0 -0.05 0 +node 21 coords 3 0 0 0 +node 22 coords 3 0 0.05 0 +node 23 coords 3 0.05 -0.05 0 +node 24 coords 3 0.05 0 0 +node 25 coords 3 0.05 0.05 0 +node 26 coords 3 -0.1 0 0 +node 27 coords 3 -0.05 0 0 dofidmask 3 1 2 6 doftype 3 0 1 0 mastermask 3 0 18 0 +node 28 coords 3 0 0 0 dofidmask 3 1 2 6 doftype 3 0 1 0 mastermask 3 0 21 0 +node 29 coords 3 0.05 0 0 dofidmask 3 1 2 6 doftype 3 0 1 0 mastermask 3 0 24 0 +node 30 coords 3 0.1 0 0 +node 31 coords 3 0 -0.1 0 +node 32 coords 3 0 -0.05 0 dofidmask 3 1 2 6 doftype 3 1 0 0 mastermask 3 20 0 0 +node 33 coords 3 0 0 0 dofidmask 3 1 2 6 doftype 3 1 0 0 mastermask 3 21 0 0 +node 34 coords 3 0 0.05 0 dofidmask 3 1 2 6 doftype 3 1 0 0 mastermask 3 22 0 0 +node 35 coords 3 0 0.1 0 +LIBeam2D 17 nodes 2 26 27 xy +LIBeam2D 18 nodes 2 27 28 xy +LIBeam2D 19 nodes 2 28 29 xy +LIBeam2D 20 nodes 2 29 30 xy +LIBeam2D 21 nodes 2 31 32 xy +LIBeam2D 22 nodes 2 32 33 xy +LIBeam2D 23 nodes 2 33 34 xy +LIBeam2D 24 nodes 2 34 35 xy +PlaneStress2D 25 nodes 4 1 9 17 16 +PlaneStress2D 26 nodes 4 16 17 18 8 +PlaneStress2D 27 nodes 4 8 18 19 15 +PlaneStress2D 28 nodes 4 15 19 14 7 +PlaneStress2D 29 nodes 4 9 2 20 17 +PlaneStress2D 30 nodes 4 17 20 21 18 +PlaneStress2D 31 nodes 4 18 21 22 19 +PlaneStress2D 32 nodes 4 19 22 6 14 +PlaneStress2D 33 nodes 4 2 10 23 20 +PlaneStress2D 34 nodes 4 20 23 24 21 +PlaneStress2D 35 nodes 4 21 24 25 22 +PlaneStress2D 36 nodes 4 22 25 13 6 +PlaneStress2D 37 nodes 4 10 3 11 23 +PlaneStress2D 38 nodes 4 23 11 4 24 +PlaneStress2D 39 nodes 4 24 4 12 25 +PlaneStress2D 40 nodes 4 25 12 5 13 +IntElLine1 41 nodes 4 8 18 26 27 +IntElLine1 42 nodes 4 18 21 27 28 +IntElLine1 43 nodes 4 21 24 28 29 +IntElLine1 44 nodes 4 24 4 29 30 +IntElLine1 45 nodes 4 2 20 31 32 +IntElLine1 46 nodes 4 20 21 32 33 +IntElLine1 47 nodes 4 21 22 33 34 +IntElLine1 48 nodes 4 22 6 34 35 +SimpleCS 1 thick 2.0000000000e-01 material 1 set 1 +SimpleCS 2 thick 1.9899469035e-01 material 1 set 2 +SimpleCS 3 thick 1.9371681469e-01 material 1 set 3 +SimpleCS 4 thick 1.9271150504e-01 material 1 set 4 +LayeredCS 5 nLayers 1 LayerMaterials 1 2 Thicks 1 7.08914634e-3 Widths 1 7.08914634e-3 midSurf 3.544573317e-3 set 9 +LayeredCS 6 nLayers 1 LayerMaterials 1 2 Thicks 1 17.72455923e-3 Widths 1 17.72455923e-3 midSurf 8.862279616e-3 set 10 +InterfaceCS 7 thickness 6.2831853072e-02 material 3 set 11 +InterfaceCS 8 thickness 2.5132741229e-02 material 4 set 12 +MazarsModel 1 d 1.0 E 3.36e10 n 0.2 version 1 e0 8.63e-5 ac 2.6 bc 800 ef 0.0025 tAlpha 1.0 maxOmega 0.9999 +MisesMat 2 d 1.0 E 2e11 n 0.3 sig0 500e6 H 8.456659619e8 omega_crit 0 a 0 tAlpha 1.0 +bondceb 3 kn 6e12 ks 6.135e10 s1 0.001 s2 0.002 s3 0.0065 taumax 1.541e7 tauf 6.164e6 +bondceb 4 kn 6e12 ks 6.135e10 s1 0.001 s2 0.002 s3 0.004 taumax 1.541e7 tauf 6.164e6 +PrescribedDispSlipBCDirichletRC 1 loadTimeFunction 1 dofs 3 1 2 6 ccoord 3 0.0 0.0 0.0 dispGrad 2 2 {0 0; 0 0} set 5 conboundset 6 +ConstantFunction 1 f(t) 1.0 +set 1 elements 16 32 33 34 35 36 37 38 39 40 25 26 27 28 29 30 31 +set 2 elements 3 33 35 36 +set 3 elements 3 38 26 30 +set 4 elements 1 34 +set 5 nodes 20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 26 30 31 35 +set 6 elementboundaries 32 25 1 29 1 33 1 37 1 37 2 38 2 39 2 40 2 40 3 36 3 32 3 28 3 28 4 27 4 26 4 25 4 +set 7 nodes 2 35 31 +set 8 nodes 2 26 30 +set 9 elements 4 24 21 22 23 +set 10 elements 4 17 18 19 20 +set 11 elements 4 41 42 43 44 +set 12 elements 4 48 45 46 47 diff --git a/tests/sm/eigen02_beam3d.in b/tests/sm/eigen02_beam3d.in new file mode 100644 index 000000000..2ec898364 --- /dev/null +++ b/tests/sm/eigen02_beam3d.in @@ -0,0 +1,21 @@ +eigen02_beam3d.out +Test of json interface +eigenvaluedynamic nroot 2 smtype 0 stype 1 rtolv 1e-008 +domain 3dShell +dofman_all element_all tstep_all +nbc 2 ncrosssect 1 ndofman 2 nelem 1 nic 0 nltf 1 nmat 1 nset 1 +node 1 coords 3 -1000 0 0 load 0 +node 2 coords 3 0 0 0 +beam3d 1 crosssect 1 mat 1 zaxis 3 0 0 -1 bodyloads 1 2 boundaryloads 0 dofstocondense 0 nodes 2 1 2 +simplecs 1 material 1 area 692.67374207 beamshearcoeff 0.56 ik 553293.9663 iy 276646.9832 iz 276646.9832 thick 60.3 width 60.3 +isole 1 d 7.85e-006 e 2.03395e+008 n 0.3 talpha 1.15e-005 +boundarycondition 1 loadtimefunction 1 set 1 values 6 0 0 0 0 0 0 dofs 6 1 2 3 4 5 6 +deadweight 2 loadtimefunction 1 components 6 0 -9.81 0 0 0 0 +constantfunction 1 f(t) 1 +set 1 nodes 1 1 +# +#%BEGIN_CHECK% tolerance 1.e-4 +## check eigen values +#EIGVAL tStep 1 EigNum 1 value 1.28195811e+05 +#EIGVAL tStep 1 EigNum 2 value 1.28195811e+05 +#%END_CHECK% diff --git a/tests/sm/eigen_beam2d.in b/tests/sm/eigen_beam2d.in index 7afba7f82..4ca565abb 100644 --- a/tests/sm/eigen_beam2d.in +++ b/tests/sm/eigen_beam2d.in @@ -41,13 +41,13 @@ Beam2d 14 nodes 2 14 15 Beam2d 15 nodes 2 15 16 Beam2d 16 nodes 2 16 17 # +Set 1 elementranges {(1 16)} +Set 2 nodes 2 1 17 +# SimpleCS 1 area 0.06 Iy 0.00045 beamShearCoeff 1.e60 material 1 set 1 IsoLE 1 d 25.0 E 25.e6 n 0.2 tAlpha 1.2e-5 BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 3 values 2 0. 0. set 2 ConstantFunction 1 f(t) 1. -Set 1 elementranges {(1 16)} -Set 2 nodes 2 1 17 -# # #%BEGIN_CHECK% tolerance 1.e-3 ## check eigen values diff --git a/tests/sm/eigen_beam3d.in b/tests/sm/eigen_beam3d.in index b47baa1d0..92074751a 100644 --- a/tests/sm/eigen_beam3d.in +++ b/tests/sm/eigen_beam3d.in @@ -5,34 +5,34 @@ errorcheck domain 3dShell OutputManager tstep_all dofman_all element_all ndofman 18 nelem 16 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 1 nset 2 -node 1 coords 3 0. 0. 0.00 -node 2 coords 3 0. 0.0 0.25 -node 3 coords 3 0. 0.0 0.50 -node 4 coords 3 0.0 0.0 0.75 -node 5 coords 3 0. 0.0 1.00 -node 6 coords 3 0. 0.0 1.25 -node 7 coords 3 0. 0.0 1.50 -node 8 coords 3 0.0 0.0 1.75 -node 9 coords 3 0. 0.0 2.00 -node 10 coords 3 0. 0.0 2.25 -node 11 coords 3 0. 0.0 2.50 -node 12 coords 3 0.0 0.0 2.75 -node 13 coords 3 0. 0.0 3.00 -node 14 coords 3 0. 0.0 3.25 -node 15 coords 3 0. 0.0 3.50 -node 16 coords 3 0.0 0.0 3.75 -node 17 coords 3 0. 0.0 4.00 -node 18 coords 3 1.0 0.0 0.00 +node 1 coords 3 0. 0. 0.00 +node 2 coords 3 0. 0. 0.25 +node 3 coords 3 0. 0. 0.50 +node 4 coords 3 0. 0. 0.75 +node 5 coords 3 0. 0. 1.00 +node 6 coords 3 0. 0. 1.25 +node 7 coords 3 0. 0. 1.50 +node 8 coords 3 0. 0. 1.75 +node 9 coords 3 0. 0. 2.00 +node 10 coords 3 0. 0. 2.25 +node 11 coords 3 0. 0. 2.50 +node 12 coords 3 0. 0. 2.75 +node 13 coords 3 0. 0. 3.00 +node 14 coords 3 0. 0. 3.25 +node 15 coords 3 0. 0. 3.50 +node 16 coords 3 0. 0. 3.75 +node 17 coords 3 0. 0. 4.00 +node 18 coords 3 1. 0. 0.00 # -Beam3d 1 nodes 2 1 2 refNode 18 -Beam3d 2 nodes 2 2 3 refNode 18 -Beam3d 3 nodes 2 3 4 refNode 18 -Beam3d 4 nodes 2 4 5 refNode 18 -Beam3d 5 nodes 2 5 6 refNode 18 -Beam3d 6 nodes 2 6 7 refNode 18 -Beam3d 7 nodes 2 7 8 refNode 18 -Beam3d 8 nodes 2 8 9 refNode 18 -Beam3d 9 nodes 2 9 10 refNode 18 +Beam3d 1 nodes 2 1 2 refNode 18 +Beam3d 2 nodes 2 2 3 refNode 18 +Beam3d 3 nodes 2 3 4 refNode 18 +Beam3d 4 nodes 2 4 5 refNode 18 +Beam3d 5 nodes 2 5 6 refNode 18 +Beam3d 6 nodes 2 6 7 refNode 18 +Beam3d 7 nodes 2 7 8 refNode 18 +Beam3d 8 nodes 2 8 9 refNode 18 +Beam3d 9 nodes 2 9 10 refNode 18 Beam3d 10 nodes 2 10 11 refNode 18 Beam3d 11 nodes 2 11 12 refNode 18 Beam3d 12 nodes 2 12 13 refNode 18 @@ -41,20 +41,19 @@ Beam3d 14 nodes 2 14 15 refNode 18 Beam3d 15 nodes 2 15 16 refNode 18 Beam3d 16 nodes 2 16 17 refNode 18 # +Set 1 elementranges {(1 16)} +Set 2 nodes 2 1 17 # SimpleCS 1 area 0.06 Iy 0.00045 Iz 0.0002 Ik 0.000498461 beamShearCoeff 1.e60 material 1 set 1 IsoLE 1 d 25.0 E 25.e6 n 0.15 tAlpha 1.2e-5 BoundaryCondition 1 loadTimeFunction 1 dofs 4 1 2 3 6 values 4 0. 0. 0. 0. set 2 ConstantFunction 1 f(t) 1. -Set 1 elementranges {(1 16)} -Set 2 nodes 2 1 17 -# # -#%BEGIN_CHECK% tolerance 1.e-2 +#%BEGIN_CHECK% tolerance 1.e-4 ## check eigen values -#EIGVAL tStep 1 EigNum 1 value 1.28049596e+03 +#EIGVAL tStep 1 EigNum 1 value 1.26835015e+03 #EIGVAL tStep 1 EigNum 2 value 2.85378786e+03 -#EIGVAL tStep 1 EigNum 3 value 2.10785640e+04 +#EIGVAL tStep 1 EigNum 3 value 2.02942280e+04 #%END_CHECK% diff --git a/tests/sm/ex3d-nurbs-01.in b/tests/sm/ex3d-nurbs-01.in index 85407c23c..fe4b94842 100644 --- a/tests/sm/ex3d-nurbs-01.in +++ b/tests/sm/ex3d-nurbs-01.in @@ -5,15 +5,15 @@ errorcheck domain 3d OutputManager tstep_all dofman_all element_all ndofman 8 nelem 1 ncrosssect 1 nmat 1 nbc 4 nic 0 nltf 1 nset 4 -node 1 coords 4 0 0 0 1 -node 2 coords 4 4 0 0 1 -node 3 coords 4 0 3 0 1 -node 4 coords 4 4 3 0 1 -node 5 coords 4 0 0 5 1 -node 6 coords 4 4 0 5 1 -node 7 coords 4 0 3 5 1 -node 8 coords 4 4 3 5 1 -nurbs3delement 1 nodes 8 1 2 3 4 5 6 7 8 crossSect 1 knotvectoru 2 0 1 knotmultiplicityu 2 2 2 knotvectorv 2 0 1 knotmultiplicityv 2 2 2 knotvectorw 2 0 1 knotmultiplicityw 2 2 2 degree 3 1 1 1 nip 8 +node 1 coords 3 0 0 0 +node 2 coords 3 4 0 0 +node 3 coords 3 0 3 0 +node 4 coords 3 4 3 0 +node 5 coords 3 0 0 5 +node 6 coords 3 4 0 5 +node 7 coords 3 0 3 5 +node 8 coords 3 4 3 5 +nurbs3delement 1 crossSect 1 nodes 8 1 2 3 4 5 6 7 8 knotvectoru 2 0 1 weights 8 1 1 1 1 1 1 1 1 knotmultiplicityu 2 2 2 knotvectorv 2 0 1 knotmultiplicityv 2 2 2 knotvectorw 2 0 1 knotmultiplicityw 2 2 2 degree 3 1 1 1 nip 8 # SimpleCS 1 material 1 # diff --git a/tests/sm/ex3d-nurbs-02.in b/tests/sm/ex3d-nurbs-02.in index 7fc97bb2d..b6777a69a 100644 --- a/tests/sm/ex3d-nurbs-02.in +++ b/tests/sm/ex3d-nurbs-02.in @@ -5,37 +5,37 @@ errorcheck domain 3d OutputManager tstep_all dofman_all element_all ndofman 27 nelem 1 ncrosssect 1 nmat 1 nbc 4 nic 0 nltf 1 nset 4 -node 1 coords 4 0 0 0 1 -node 2 coords 4 2 0 0 1 -node 3 coords 4 4 0 0 1 -node 4 coords 4 0 1.5 0 1 -node 5 coords 4 2 1.5 0 1 -node 6 coords 4 4 1.5 0 1 -node 7 coords 4 0 3 0 1 -node 8 coords 4 2 3 0 1 -node 9 coords 4 4 3 0 1 +node 1 coords 3 0 0 0 +node 2 coords 3 2 0 0 +node 3 coords 3 4 0 0 +node 4 coords 3 0 1.5 0 +node 5 coords 3 2 1.5 0 +node 6 coords 3 4 1.5 0 +node 7 coords 3 0 3 0 +node 8 coords 3 2 3 0 +node 9 coords 3 4 3 0 # -node 10 coords 4 0 0 2.5 1 -node 11 coords 4 2 0 2.5 1 -node 12 coords 4 4 0 2.5 1 -node 13 coords 4 0 1.5 2.5 1 -node 14 coords 4 2 1.5 2.5 1 -node 15 coords 4 4 1.5 2.5 1 -node 16 coords 4 0 3 2.5 1 -node 17 coords 4 2 3 2.5 1 -node 18 coords 4 4 3 2.5 1 +node 10 coords 3 0 0 2.5 +node 11 coords 3 2 0 2.5 +node 12 coords 3 4 0 2.5 +node 13 coords 3 0 1.5 2.5 +node 14 coords 3 2 1.5 2.5 +node 15 coords 3 4 1.5 2.5 +node 16 coords 3 0 3 2.5 +node 17 coords 3 2 3 2.5 +node 18 coords 3 4 3 2.5 # -node 19 coords 4 0 0 5 1 -node 20 coords 4 2 0 5 1 -node 21 coords 4 4 0 5 1 -node 22 coords 4 0 1.5 5 1 -node 23 coords 4 2 1.5 5 1 -node 24 coords 4 4 1.5 5 1 -node 25 coords 4 0 3 5 1 -node 26 coords 4 2 3 5 1 -node 27 coords 4 4 3 5 1 +node 19 coords 3 0 0 5 +node 20 coords 3 2 0 5 +node 21 coords 3 4 0 5 +node 22 coords 3 0 1.5 5 +node 23 coords 3 2 1.5 5 +node 24 coords 3 4 1.5 5 +node 25 coords 3 0 3 5 +node 26 coords 3 2 3 5 +node 27 coords 3 4 3 5 # -nurbs3delement 1 nodes 27 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 crossSect 1 knotvectoru 2 0 1 knotmultiplicityu 2 3 3 knotvectorv 2 0 1 knotmultiplicityv 2 3 3 knotvectorw 2 0 1 knotmultiplicityw 2 3 3 degree 3 2 2 2 nip 64 +nurbs3delement 1 crossSect 1 nodes 27 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 weights 27 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 knotvectoru 2 0 1 knotmultiplicityu 2 3 3 knotvectorv 2 0 1 knotmultiplicityv 2 3 3 knotvectorw 2 0 1 knotmultiplicityw 2 3 3 degree 3 2 2 2 nip 64 # SimpleCS 1 material 1 # diff --git a/tests/sm/ex3d-nurbs-03.in b/tests/sm/ex3d-nurbs-03.in index 27921fdf6..8488c0d2c 100644 --- a/tests/sm/ex3d-nurbs-03.in +++ b/tests/sm/ex3d-nurbs-03.in @@ -5,15 +5,15 @@ errorcheck domain 3d OutputManager tstep_all dofman_all element_all ndofman 8 nelem 1 ncrosssect 1 nmat 1 nbc 5 nic 0 nltf 1 nset 5 -node 1 coords 4 0 0 0 1 -node 2 coords 4 4 0 0 1 -node 3 coords 4 0 3 0 1 -node 4 coords 4 4 3 0 1 -node 5 coords 4 0 0 5 1 -node 6 coords 4 4 0 5 1 -node 7 coords 4 0 3 5 1 -node 8 coords 4 4 3 5 1 lcs 6 0 0 1 0 1 0 -nurbs3delement 1 nodes 8 1 2 3 4 5 6 7 8 crossSect 1 knotvectoru 2 0 1 knotmultiplicityu 2 2 2 knotvectorv 2 0 1 knotmultiplicityv 2 2 2 knotvectorw 2 0 1 knotmultiplicityw 2 2 2 degree 3 1 1 1 nip 8 +node 1 coords 3 0 0 0 +node 2 coords 3 4 0 0 +node 3 coords 3 0 3 0 +node 4 coords 3 4 3 0 +node 5 coords 3 0 0 5 +node 6 coords 3 4 0 5 +node 7 coords 3 0 3 5 +node 8 coords 3 4 3 5 lcs 6 0 0 1 0 1 0 +nurbs3delement 1 crossSect 1 nodes 8 1 2 3 4 5 6 7 8 weights 8 1 1 1 1 1 1 1 1 knotvectoru 2 0 1 knotmultiplicityu 2 2 2 knotvectorv 2 0 1 knotmultiplicityv 2 2 2 knotvectorw 2 0 1 knotmultiplicityw 2 2 2 degree 3 1 1 1 nip 8 # SimpleCS 1 material 1 # diff --git a/tests/sm/fe2structuralmaterial2.in b/tests/sm/fe2structuralmaterial2.in new file mode 100644 index 000000000..965ff9bf5 --- /dev/null +++ b/tests/sm/fe2structuralmaterial2.in @@ -0,0 +1,44 @@ +test.out +Test for multiscale modeling using fe2structuralmaterial - plane stress. +StaticStructural nsteps 1 nmodules 1 +#vtkxml tstep_all domain_all primvars 1 1 cellvars 1 1 +errorcheck +domain 2dplanestress +OutputManager tstep_all dofman_all element_all +ndofman 12 nelem 5 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 3 nxfemman 0 +node 1 coords 3 0 0 0 +node 2 coords 3 1 0 0 +node 3 coords 3 1 0.2 0 +node 4 coords 3 0 0.2 0 +node 5 coords 3 0.2 0 0 +node 6 coords 3 0.4 0 0 +node 7 coords 3 0.6 0 0 +node 8 coords 3 0.8 0 0 +node 9 coords 3 0.8 0.2 0 +node 10 coords 3 0.6 0.2 0 +node 11 coords 3 0.4 0.2 0 +node 12 coords 3 0.2 0.2 0 +planestress2d 13 nodes 4 1 5 12 4 +planestress2d 14 nodes 4 5 6 11 12 +planestress2d 15 nodes 4 6 7 10 11 +planestress2d 16 nodes 4 7 8 9 10 +planestress2d 17 nodes 4 8 2 3 9 +Set 1 elementranges {(13 17)} +Set 2 nodes 2 1 4 +Set 3 nodes 2 2 3 +# +SimpleCS 1 thick 1.0 material 1 set 1 +# Linear elasticity +structfe2material 1 d 1.0 filename fe2structuralmaterial2.in.rve use_num_tangent +# +BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0 0 set 2 +NodalLoad 2 loadTimeFunction 1 dofs 2 1 2 components 2 0.0 -0.5e6 set 3 +ConstantFunction 1 f(t) 1.0 +# +#%BEGIN_CHECK% tolerance 1.e-4 +## check selected nodes +#NODE tStep 1 number 2 dof 1 unknown d value -3.25000000e-04 +#NODE tStep 1 number 2 dof 2 unknown d value -2.20690476e-03 +## +#%END_CHECK% + diff --git a/tests/sm/fe2structuralmaterial2.in.rve b/tests/sm/fe2structuralmaterial2.in.rve new file mode 100644 index 000000000..46422cd93 --- /dev/null +++ b/tests/sm/fe2structuralmaterial2.in.rve @@ -0,0 +1,20 @@ +rvesmall.out +Small RVE for automatic test. +StaticStructural nsteps 1 deltat 1.0 rtolv 1.0e-6 MaxIter 40 minIter 2 nmodules 0 manrmsteps 1 +#vtkxml tstep_all domain_all primvars 1 1 cellvars 1 1 +domain 2dplanestress +OutputManager +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 1 nset 1 nxfemman 0 +node 1 coords 3 0 0 0 +node 2 coords 3 0.01 0 0 +node 3 coords 3 0.01 0.01 0 +node 4 coords 3 0 0.01 0 +planestress2d 1 nodes 4 1 2 3 4 crosssect 1 +SimpleCS 1 thick 1.0 material 1 +# +#Linear elasticity +IsoLE 1 d 1.0 E 210.0e9 n 0.3 tAlpha 0.0 +PrescribedGradient 1 dofs 2 1 2 set 1 loadTimeFunction 1 ccoord 3 0.0 0.0 0.0 gradient 3 3 {1.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 0.0} +# +ConstantFunction 1 f(t) 1.0 +set 1 elementboundaries 8 1 1 1 2 1 3 1 4 diff --git a/tests/sm/fiberedcs01.in b/tests/sm/fiberedcs01.in new file mode 100644 index 000000000..948f3b38c --- /dev/null +++ b/tests/sm/fiberedcs01.in @@ -0,0 +1,24 @@ +fibered01.out +Simple Beam Structure - free torsion +StaticStructural nsteps 1 nmodules 0 +domain 3dBeam +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 2 ncrosssect 2 nmat 1 nbc 2 nic 0 nltf 1 nset 4 +node 1 coords 3 0. 0. 0. +node 2 coords 3 3.0 0. 0. +node 3 coords 3 0. 0. 0. +node 4 coords 3 3.0 0. 0. +# +Beam3d 1 nodes 2 1 2 zaxis 3 0 0 1 +Beam3d 2 nodes 2 3 4 zaxis 3 0 0 1 +# +SimpleCS 1 area 0.02 Iy 2.0e-4 Iz 1.25e-5 Ik 2.125e-4 beamShearCoeff 1.e18 thick 0.54 material 1 set 1 +FiberedCS 2 fibermaterials 4 1 1 1 1 thicks 4 0.1 0.1 0.1 0.1 widths 4 0.05 0.05 0.05 0.05 thick 0.2 width 0.1 fiberycentrecoords 4 -0.025 0.025 -0.025 0.025 fiberzcentrecoords 4 0.1 0.1 -0.1 -0.1 set 2 +IsoLE 1 d 1. E 30. n 0.2 tAlpha 1.2e-5 +BoundaryCondition 1 loadTimeFunction 1 dofs 6 1 2 3 4 5 6 values 6 0 0 0 0 0 0 set 3 +NodalLoad 2 loadTimeFunction 1 dofs 2 2 4 Components 2 0.0 10.0 set 4 +PeakFunction 1 t 1.0 f(t) 1. +Set 1 elements 1 1 +Set 2 elements 1 2 +Set 3 nodes 2 1 3 +Set 4 nodes 2 2 4 \ No newline at end of file diff --git a/tests/sm/frcfcm_tension.in b/tests/sm/frcfcm_tension.in index 64feaceb6..dba1bfa9f 100644 --- a/tests/sm/frcfcm_tension.in +++ b/tests/sm/frcfcm_tension.in @@ -152,8 +152,8 @@ set 13 elementranges {8} # #ELEMENT tStep 5 number 4 gp 1 keyword 1 component 1 value 8.000000e-01 tolerance 1.e-4 #ELEMENT tStep 15 number 4 gp 1 keyword 1 component 1 value 1.188800e+00 tolerance 1.e-4 -#ELEMENT tStep 25 number 4 gp 1 keyword 1 component 1 value 6.498400e-01 tolerance 1.e-4 -#ELEMENT tStep 35 number 4 gp 1 keyword 1 component 1 value 3.785700e-01 tolerance 1.e-4 +#ELEMENT tStep 25 number 4 gp 1 keyword 1 component 1 value 6.583240e-01 tolerance 1.e-4 +#ELEMENT tStep 35 number 4 gp 1 keyword 1 component 1 value 3.848863e-01 tolerance 1.e-4 #ELEMENT tStep 45 number 4 gp 1 keyword 1 component 1 value 3.235400e+00 tolerance 1.e-4 #ELEMENT tStep 55 number 4 gp 1 keyword 1 component 1 value 1.314200e+00 tolerance 1.e-4 #ELEMENT tStep 65 number 4 gp 1 keyword 1 component 1 value 2.454600e-01 tolerance 1.e-4 @@ -163,8 +163,8 @@ set 13 elementranges {8} # #ELEMENT tStep 5 number 5 gp 1 keyword 1 component 1 value 8.000000e-01 tolerance 1.e-4 #ELEMENT tStep 15 number 5 gp 1 keyword 1 component 1 value 1.188800e+00 tolerance 1.e-4 -#ELEMENT tStep 25 number 5 gp 1 keyword 1 component 1 value 6.498400e-01 tolerance 1.e-4 -#ELEMENT tStep 35 number 5 gp 1 keyword 1 component 1 value 3.785700e-01 tolerance 1.e-4 +#ELEMENT tStep 25 number 5 gp 1 keyword 1 component 1 value 6.583240e-01 tolerance 1.e-4 +#ELEMENT tStep 35 number 5 gp 1 keyword 1 component 1 value 3.848863e-01 tolerance 1.e-4 #ELEMENT tStep 45 number 5 gp 1 keyword 1 component 1 value 3.235400e+00 tolerance 1.e-4 #ELEMENT tStep 55 number 5 gp 1 keyword 1 component 1 value 1.314200e+00 tolerance 1.e-4 #ELEMENT tStep 65 number 5 gp 1 keyword 1 component 1 value 2.454600e-01 tolerance 1.e-4 @@ -174,8 +174,8 @@ set 13 elementranges {8} # #ELEMENT tStep 5 number 6 gp 1 keyword 1 component 1 value 8.000000e-01 tolerance 5.e-5 #ELEMENT tStep 15 number 6 gp 1 keyword 1 component 1 value 2.926100e+00 tolerance 5.e-5 -#ELEMENT tStep 25 number 6 gp 1 keyword 1 component 1 value 1.960000e+00 tolerance 5.e-5 -#ELEMENT tStep 35 number 6 gp 1 keyword 1 component 1 value 1.178100e+00 tolerance 5.e-5 +#ELEMENT tStep 25 number 6 gp 1 keyword 1 component 1 value 1.958498e+00 tolerance 5.e-5 +#ELEMENT tStep 35 number 6 gp 1 keyword 1 component 1 value 1.176897e+00 tolerance 5.e-5 #ELEMENT tStep 45 number 6 gp 1 keyword 1 component 1 value 4.186100e+00 tolerance 5.e-5 #ELEMENT tStep 55 number 6 gp 1 keyword 1 component 1 value 2.031900e+00 tolerance 5.e-5 #ELEMENT tStep 65 number 6 gp 1 keyword 1 component 1 value 7.592900e-01 tolerance 5.e-5 diff --git a/tests/sm/generalslavenode.in b/tests/sm/generalslavenode.in new file mode 100644 index 000000000..2c6a018fa --- /dev/null +++ b/tests/sm/generalslavenode.in @@ -0,0 +1,66 @@ +# INTRODUCTION +generalslavenode.out +Rectangle made of 9 elements and 16 nodes, some of them setup as general slave nodes leading to periodic boundary conditions +StaticStructural nsteps 1 nmodules 1 stiffmode 0 manrmsteps 1 rtolv 1.e-8 +errorcheck +Domain PlaneStrain +OutputManager tstep_all dofman_all element_all +ndofman 16 nelem 9 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 4 +##################################################### NODES ################################################################### +Node 1 coords 3 0. 0. 0. +Node 2 coords 3 1. 0. 0. +Node 3 coords 3 2. 0. 0. +Node 4 coords 3 3. 0. 0. +Node 5 coords 3 0. 1. 0. +Node 6 coords 3 1. 1. 0. +Node 7 coords 3 2. 1. 0. +GeneralSlaveNode 8 coords 3 3. 1. 0. dofType 2 2 2 MasterSizes 2 2 2 MasterList 8 5 1 4 1 5 2 4 2 MasterWeights 4 1 1 1 1 +Node 9 coords 3 0. 2. 0. +Node 10 coords 3 1. 2. 0. +Node 11 coords 3 2. 2. 0. +GeneralSlaveNode 12 coords 3 3. 2. 0. dofType 2 2 2 MasterSizes 2 2 2 MasterList 8 9 1 4 1 9 2 4 2 MasterWeights 4 1 1 1 1 +Node 13 coords 3 0. 3. 0. +GeneralSlaveNode 14 coords 3 1. 3. 0. dofType 2 2 2 MasterSizes 2 2 2 MasterList 8 2 1 13 1 2 2 13 2 MasterWeights 4 1 1 1 1 +GeneralSlaveNode 15 coords 3 2. 3. 0. dofType 2 2 2 MasterSizes 2 2 2 MasterList 8 3 1 13 1 3 2 13 2 MasterWeights 4 1 1 1 1 +GeneralSlaveNode 16 coords 3 3. 3. 0. dofType 2 2 2 MasterSizes 2 2 2 MasterList 8 4 1 13 1 4 2 13 2 MasterWeights 4 1 1 1 1 +#################################################### Elements #################################################################################### +quad1planestrain 1 nodes 4 1 2 6 5 crossSect 1 +quad1planestrain 2 nodes 4 2 3 7 6 crossSect 1 +quad1planestrain 3 nodes 4 3 4 8 7 crossSect 1 +quad1planestrain 4 nodes 4 5 6 10 9 crossSect 1 +quad1planestrain 5 nodes 4 6 7 11 10 crossSect 1 +quad1planestrain 6 nodes 4 7 8 12 11 crossSect 1 +quad1planestrain 7 nodes 4 9 10 14 13 crossSect 1 +quad1planestrain 8 nodes 4 10 11 15 14 crossSect 1 +quad1planestrain 9 nodes 4 11 12 16 15 crossSect 1 +# MATERIALS AND CROSS-SECTIONS +SimpleCS 1 thick 1 material 1 set 1 +IsoLE 1 d 1.0 E 500 n 0 tAlpha 1.e-6 +# BCS +BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0.0 0.0 set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 2 1 2 values 2 0.5 0.0 set 3 +BoundaryCondition 3 loadTimeFunction 1 dofs 2 1 2 values 2 0.1 0.2 set 4 +# LOAD TIME FUNCTIONS +PiecewiseLinFunction 1 nPoints 2 t 2 0 100 f(t) 2 0.0 100 +# SETS +Set 1 allElements +Set 2 nodes 1 1 +Set 3 nodes 1 4 +Set 4 nodes 1 13 +#%BEGIN_CHECK% tolerance 1.e-6 +## +#NODE tStep 1 number 8 dof 1 unknown d value 5.33333333e-01 +#NODE tStep 1 number 8 dof 2 unknown d value 6.66666667e-02 +## +#NODE tStep 1 number 12 dof 1 unknown d value 5.66666667e-01 +#NODE tStep 1 number 12 dof 2 unknown d value 1.33333333e-01 +## +#NODE tStep 1 number 14 dof 1 unknown d value 2.66666667e-01 +#NODE tStep 1 number 14 dof 2 unknown d value 2.00000000e-01 +## +#NODE tStep 1 number 15 dof 1 unknown d value 4.33333333e-01 +#NODE tStep 1 number 15 dof 2 unknown d value 2.00000000e-01 +## +#NODE tStep 1 number 16 dof 1 unknown d value 6.00000000e-01 +#NODE tStep 1 number 16 dof 2 unknown d value 2.00000000e-01 +#%END_CHECK% diff --git a/tests/sm/homog01.in b/tests/sm/homog01.in index f89339064..a2ae36ebd 100644 --- a/tests/sm/homog01.in +++ b/tests/sm/homog01.in @@ -1,10 +1,11 @@ homog01.out Elastic homogenization of 2x2 quad elements with periodic boundary conditions and shear eigenstrain load -LinearStatic nsteps 1 nmodules 2 +LinearStatic nsteps 1 nmodules 3 errorcheck #vtkxml tstep_all domain_all cellvars 1 46 primvars 1 1 vars 2 1 4 stype 1 -#hom tstep_all ists 2 4 1 -hom tstep_all ists 3 4 1 115 regionsets 2 1 2 +#hom tstep_all ists 2 1 4 +hom tstep_all ists 3 1 4 115 strain_energy regionsets 2 1 2 +hom tstep_all ists 2 2 5 strain_energy regionsets 2 1 2 domain 2dPlaneStress OutputManager tstep_all dofman_all element_all ndofman 9 nelem 4 ncrosssect 2 nmat 2 nbc 3 nic 0 nltf 1 nset 4 diff --git a/tests/sm/homog02.in b/tests/sm/homog02.in index c41c84ca2..24dc80f2b 100644 --- a/tests/sm/homog02.in +++ b/tests/sm/homog02.in @@ -3,7 +3,7 @@ Elastic homogenization of 2x2 quad elements with periodic boudnary conditions us LinearStatic nsteps 1 nmodules 2 errorcheck #vtkxml tstep_all domain_all cellvars 1 46 primvars 1 1 vars 2 1 4 stype 2 -hom tstep_all ists 2 4 1 +hom tstep_all ists 2 1 4 strain_energy domain 2dPlaneStress OutputManager tstep_all dofman_all element_all ndofman 9 nelem 4 ncrosssect 2 nmat 2 nbc 5 nic 0 nltf 1 nset 4 diff --git a/tests/sm/idm08.in b/tests/sm/idm08.in index defe455d9..8b77ffcd7 100644 --- a/tests/sm/idm08.in +++ b/tests/sm/idm08.in @@ -11,6 +11,7 @@ node 2 coords 3 2.0 0.0 0.0 node 3 coords 3 2.0 3.0 0.0 node 4 coords 3 0.0 3.0 0.0 PlaneStress2d 1 nodes 4 1 2 3 4 mat 1 +#L4axisymm 1 nodes 4 1 2 3 4 mat 1 SimpleCS 1 thick 0.15 material 1 set 1 idm1 1 d 1.0 E 10. n 0.2 e0 0.0001 gf 1.5 equivstraintype 7 griff_n 10. talpha 0.0 damlaw 1 BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 2 diff --git a/tests/sm/idm11.in b/tests/sm/idm11.in new file mode 100644 index 000000000..4b81ffb89 --- /dev/null +++ b/tests/sm/idm11.in @@ -0,0 +1,42 @@ +idm11.out +Test of PlaneStress2d element -> tensile test with subsequent load-unload cycles +NonLinearStatic nsteps 1 nmsteps 1 nmodules 1 +nsteps 100 rtolv 1.e-7 MaxIter 9000 steplength 0.000001 controlmode 1 +vtkxml tstep_all vars 3 1 4 13 primvars 1 1 stype 2 +domain 2dPlaneStress +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 2 +node 1 coords 2 0.0 0.0 bc 2 1 1 +node 2 coords 2 100.0 0.0 bc 2 2 1 +node 3 coords 2 100.0 100.0 bc 2 2 0 +node 4 coords 2 0.0 100.0 bc 2 1 0 +PlaneStress2d 1 nodes 4 1 2 3 4 crossSect 1 mat 1 +SimpleCS 1 thick 1.0 area 1.0 +idm1 1 d 0. E 20000.00 n 0.2 tAlpha 0. damlaw 11 e0 1.6e-4 w_k 0.07 w_r 1.65 w_f 6.0 f_k 0.57 f_r 1.2 equivstraintype 0 +BoundaryCondition 1 loadTimeFunction 1 d 0.0 +BoundaryCondition 2 loadTimeFunction 2 d 1.0 +ConstantFunction 1 f(t) 100.0 +PiecewiseLinFunction 2 nPoints 8 t 8 0.0 10.0 20.0 30.0 40.0 50.0 60.0 100.0 f(t) 8 0.0 0.7 0.0 2.0 0.0 4.0 0.0 7.0 +#%BEGIN_CHECK% tolerance 1.e-4 +#NODE tStep 10 number 2 dof 1 unknown d value 0.7 +#REACTION tStep 10 number 1 dof 1 value -40.978 +#REACTION tStep 10 number 4 dof 1 value -40.978 +#NODE tStep 20 number 2 dof 1 unknown d value 0.0 +#REACTION tStep 20 number 1 dof 1 value 0.0 +#REACTION tStep 20 number 4 dof 1 value 0.0 +#NODE tStep 28 number 2 dof 1 unknown d value 1.6 +#REACTION tStep 28 number 1 dof 1 value -58.886 +#REACTION tStep 28 number 4 dof 1 value -58.886 +#NODE tStep 40 number 2 dof 1 unknown d value 0.0 +#REACTION tStep 40 number 1 dof 1 value 0.0 +#REACTION tStep 40 number 4 dof 1 value 0.0 +#NODE tStep 50 number 2 dof 1 unknown d value 4.0 +#REACTION tStep 50 number 1 dof 1 value -27.624 +#REACTION tStep 50 number 4 dof 1 value -27.624 +#NODE tStep 60 number 2 dof 1 unknown d value 0.0 +#REACTION tStep 60 number 1 dof 1 value 0.0 +#REACTION tStep 60 number 4 dof 1 value 0.0 +#NODE tStep 95 number 2 dof 1 unknown d value 6.125 +#REACTION tStep 95 number 1 dof 1 value 0.0 +#REACTION tStep 95 number 4 dof 1 value 0.0 +#%END_CHECK% diff --git a/tests/sm/incrlinstatic_isimposed.in b/tests/sm/incrlinstatic_isimposed.in index 188b8b7dd..5244ecdc6 100644 --- a/tests/sm/incrlinstatic_isimposed.in +++ b/tests/sm/incrlinstatic_isimposed.in @@ -4,6 +4,7 @@ Test of proper handling of changes of static system during computation # supported only by some engng. models # IncrLinearStatic endOfTimeOfInterest 5.0 prescribedTimes 5 1. 2. 3. 4. 5. nmodules 1 +#StaticStructural nsteps 5 prescribedTimes 5 1. 2. 3. 4. 5. nmodules 1 errorcheck domain 2dTruss OutputManager tstep_all dofman_all element_all diff --git a/tests/sm/interface01.in b/tests/sm/interface01.in index bddb2cae6..f999ecc1f 100644 --- a/tests/sm/interface01.in +++ b/tests/sm/interface01.in @@ -16,7 +16,7 @@ Interface1d 2 nodes 2 4 5 normal 2 1. 0. SimpleCS 1 thick 0.1 material 1 InterfaceCS 2 thickness 0.1 material 2 set 4 IsoLe 1 d 2500. E 40.e+3 n 0.15 talpha 2.40e-6 -simpleintermat 2 kn 1.e+3 fc 1.0 stiffcoeff 0.2 +simpleintermat 2 kn 1.e+3 fc 1.0 stiffcoeff 0.2 regularized 0 BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 1 BoundaryCondition 2 loadTimeFunction 2 dofs 1 1 values 1 0.01 set 2 BoundaryCondition 3 loadTimeFunction 1 dofs 1 2 values 1 0.0 set 3 diff --git a/tests/sm/interface3d.in b/tests/sm/interface3d.in index fa11edcc0..c6f51b377 100644 --- a/tests/sm/interface3d.in +++ b/tests/sm/interface3d.in @@ -2,6 +2,7 @@ interface3d.out patch test of interface 3d elements LinearStatic nsteps 1 nmodules 1 errorcheck +#vtkxml tstep_all domain_all primvars 1 1 vars 2 1 4 stype 1 domain 3d OutputManager tstep_all dofman_all element_all ndofman 16 nelem 14 ncrosssect 2 nmat 2 nbc 4 nic 0 nltf 1 nset 6 diff --git a/tests/sm/isoasymm01.in b/tests/sm/isoasymm01.in new file mode 100644 index 000000000..9b0267aa9 --- /dev/null +++ b/tests/sm/isoasymm01.in @@ -0,0 +1,26 @@ +test1.out +Patch test of Truss1d elements -> temperature load +StaticStructural nsteps 1 nmodules 1 stiffmode 0 manrmsteps 5 +errorcheck +domain 1dtruss +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 3 +Node 1 coords 1 0. +Node 2 coords 1 2. +Truss1d 1 nodes 2 1 2 +SimpleCS 1 thick 0.1 width 10.0 material 1 set 1 +isoasymm1d 1 Et 1.0 Ec 15.0 tAlpha 0.000012 m 200 d 1.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0.0 set 2 +NodalLoad 2 loadTimeFunction 1 Components 1 -2.0 dofs 1 1 set 3 +ConstantFunction 1 f(t) 1.0 +Set 1 elements 1 1 +Set 2 nodes 1 1 +Set 3 nodes 1 2 +# +# +#%BEGIN_CHECK% tolerance 1.e-8 +#REACTION tStep 1 number 1 dof 1 value 2.0 +#NODE tStep 1 number 2 dof 1 unknown d value -2.69901345e-1 +#ELEMENT tStep 1 number 1 gp 1 keyword 4 component 1 value -1.34950677e-1 +#ELEMENT tStep 1 number 1 gp 1 keyword 1 component 1 value -2.0 +#%END_CHECK% diff --git a/tests/sm/lattice2dboundary1.in b/tests/sm/lattice2dboundary1.in new file mode 100644 index 000000000..5f31d4808 --- /dev/null +++ b/tests/sm/lattice2dboundary1.in @@ -0,0 +1,19 @@ +lattice2dboundary1.out +2D lattice boundary model +NonLinearStatic nmsteps 1 nsteps 1 contextOutputStep 1 nmodules 1 +nsteps 2 controllmode 1 rtolv 1.e-3 stiffMode 1 maxiter 200 ddm 2 2 31 ddv 1 1.e-3 ddltf 2 +vtkxmlperiodic tstep_all primvars 1 1 stype 0 +domain 2dlattice +OutputManager tstep_all dofman_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 2 +node 1 coords 2 0.5 0.5 bc 3 1 1 1 +node 2 coords 2 1.0 1.0 dofidmask 3 31 32 42 bc 3 0 0 1 +# +latticeboundary2D 1 nodes 3 1 1 2 crossSect 1 mat 1 thick 1.0 width 0.5 gpCoords 2 1. 1. location 2 +latticecs 1 material 1 +# +latticedamage 1 d 0. talpha 0. e 1. e0 1.e20 stype 1 wf 60.e-6 a1 0.6 randomtype 1 cov 0.2 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +NodalLoad 2 loadTimeFunction 1 Components 3 0. -1. 0. +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 nPoints 2 t 2 0. 1. f(t) 2 0. 1. \ No newline at end of file diff --git a/tests/sm/lattice2drandom.in b/tests/sm/lattice2drandom.in index edd52b729..8f75359f6 100644 --- a/tests/sm/lattice2drandom.in +++ b/tests/sm/lattice2drandom.in @@ -8,16 +8,15 @@ ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 2 nset 2 node 1 coords 2 0.0 0.0 node 2 coords 2 0.001 0.0 lattice2D 1 nodes 2 1 2 crossSect 1 mat 1 gpCoords 2 0.0005 0. width 0.001 thick 1.0 -simplecs 1 material 1 -latticedamage2d 1 d 0 talpha 0. e 30.e9 e0 100.e-6 wf 100.e-4 coh 2. ec 10. stype 1 randvars 1 800 randgen 1 2 +latticecs 1 material 1 +latticedamage 1 d 0 talpha 0. e 30.e9 e0 100.e-6 wf 100.e-4 coh 2. ec 10. stype 1 randvars 1 800 randgen 1 2 BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 2 6 values 3 0. 0. 0. set 1 BoundaryCondition 2 loadTimeFunction 1 dofs 1 6 values 1 0. set 2 NodalLoad 3 loadTimeFunction 1 dofs 3 1 2 6 Components 3 1. 0. 0. set 2 reference ConstantFunction 1 f(t) 1. -InterpolatingFunction 2 name lattice2drandom.dat +InterpolatingFunction 2 name lattice2drandom.dat Set 1 nodes 1 1 Set 2 nodes 1 2 - #%BEGIN_CHECK% tolerance 1.e-2 #LOADLEVEL tStep 1 value 2.931192e+03 #%END_CHECK% diff --git a/tests/sm/lattice3d1.in b/tests/sm/lattice3d1.in new file mode 100644 index 000000000..ea9e3eafd --- /dev/null +++ b/tests/sm/lattice3d1.in @@ -0,0 +1,44 @@ +lattice3d1.out +3d lattice model for periodic cell +StaticStructural nsteps 1 rtolv 1.e-10 nmodules 2 +vtkxmllattice tstep_all primvars 1 1 cross 1 cellvars 2 60 90 domain_all +errorcheck +domain 3dLattice +OutputManager tstep_all dofman_all element_all +ndofman 6 nelem 20 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 +node 1 coords 3 1.400000 1.400000 1.400000 bc 6 1 1 1 1 1 1 +node 2 coords 3 1.400000 2.100000 1.400000 +node 3 coords 3 1.750000 1.750000 1.750000 +node 4 coords 3 1.400000 1.400000 2.100000 +node 5 coords 3 1.400000 2.100000 2.100000 +node 6 coords 3 0.700000 0.700000 0.700000 dofidmask 6 31 32 33 40 41 42 bc 6 2 0 0 0 0 2 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 1.225000 1.750000 1.400000 1.400000 1.750000 1.225000 1.575000 1.750000 1.400000 1.400000 1.750000 1.575000 +lattice3D 2 nodes 2 1 3 crossSect 1 mat 1 polycoords 18 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.750000 1.400000 1.575000 1.750000 1.575000 1.400000 1.575000 1.750000 1.400000 1.400000 1.750000 1.575000 +lattice3D 3 nodes 2 1 4 crossSect 1 mat 1 polycoords 12 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.400000 1.225000 1.750000 1.225000 1.400000 1.750000 +lattice3Dboundary 4 nodes 3 1 5 6 crossSect 1 mat 1 polycoords 12 1.750000 1.225000 1.400000 1.750000 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.400000 1.225000 location 2 0 18 +lattice3dboundary 5 nodes 3 5 4 6 crossSect 1 mat 1 polycoords 12 2.275000 1.750000 1.400000 2.100000 1.750000 1.225000 1.925000 1.750000 1.400000 2.100000 1.750000 1.575000 location 2 18 24 +lattice3dboundary 6 nodes 3 5 3 6 crossSect 1 mat 1 polycoords 18 1.925000 1.750000 1.400000 1.750000 1.575000 1.400000 1.750000 1.400000 1.575000 1.925000 1.400000 1.750000 2.100000 1.575000 1.750000 2.100000 1.750000 1.575000 location 2 18 0 +lattice3dboundary 7 nodes 3 5 2 6 crossSect 1 mat 1 polycoords 12 2.275000 1.400000 1.750000 2.100000 1.225000 1.750000 1.925000 1.400000 1.750000 2.100000 1.575000 1.750000 location 2 18 20 +lattice3dboundary 8 nodes 3 2 4 6 crossSect 1 mat 1 polycoords 12 1.750000 2.100000 1.225000 1.750000 2.275000 1.400000 1.750000 2.100000 1.575000 1.750000 1.925000 1.400000 location 2 0 24 +lattice3D 9 nodes 2 2 3 crossSect 1 mat 1 polycoords 18 1.750000 2.100000 1.575000 1.575000 2.100000 1.750000 1.400000 1.925000 1.750000 1.400000 1.750000 1.575000 1.575000 1.750000 1.400000 1.750000 1.925000 1.400000 +lattice3D 10 nodes 2 2 5 crossSect 1 mat 1 polycoords 12 1.225000 2.100000 1.750000 1.400000 2.275000 1.750000 1.575000 2.100000 1.750000 1.400000 1.925000 1.750000 +lattice3dboundary 11 nodes 3 4 1 6 crossSect 1 mat 1 polycoords 12 2.275000 2.100000 1.750000 2.100000 2.275000 1.750000 1.925000 2.100000 1.750000 2.100000 1.925000 1.750000 location 2 24 26 +lattice3dboundary 12 nodes 3 4 3 6 crossSect 1 mat 1 polycoords 18 1.925000 2.100000 1.750000 1.750000 2.100000 1.575000 1.750000 1.925000 1.400000 1.925000 1.750000 1.400000 2.100000 1.750000 1.575000 2.100000 1.925000 1.750000 location 2 24 0 +lattice3D 13 nodes 2 3 5 crossSect 1 mat 1 polycoords 18 1.750000 1.925000 2.100000 1.750000 2.100000 1.925000 1.575000 2.100000 1.750000 1.400000 1.925000 1.750000 1.400000 1.750000 1.925000 1.575000 1.750000 2.100000 +lattice3D 14 nodes 2 3 4 crossSect 1 mat 1 polycoords 18 1.400000 1.750000 1.925000 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.750000 1.400000 1.925000 1.750000 1.575000 2.100000 1.575000 1.750000 2.100000 +lattice3dboundary 15 nodes 3 3 1 6 crossSect 1 mat 1 polycoords 18 1.750000 2.100000 1.925000 1.925000 2.100000 1.750000 2.100000 1.925000 1.750000 2.100000 1.750000 1.925000 1.925000 1.750000 2.100000 1.750000 1.925000 2.100000 location 2 0 26 +lattice3dboundary 16 nodes 3 3 2 6 crossSect 1 mat 1 polycoords 18 1.925000 1.400000 1.750000 1.750000 1.400000 1.925000 1.750000 1.575000 2.100000 1.925000 1.750000 2.100000 2.100000 1.750000 1.925000 2.100000 1.575000 1.750000 location 2 0 20 +lattice3D 17 nodes 2 4 5 crossSect 1 mat 1 polycoords 12 1.400000 1.750000 2.275000 1.225000 1.750000 2.100000 1.400000 1.750000 1.925000 1.575000 1.750000 2.100000 +lattice3dboundary 18 nodes 3 4 2 6 crossSect 1 mat 1 polycoords 12 1.750000 1.400000 2.275000 1.750000 1.225000 2.100000 1.750000 1.400000 1.925000 1.750000 1.575000 2.100000 location 2 0 20 +lattice3dboundary 19 nodes 3 2 1 6 crossSect 1 mat 1 polycoords 12 2.275000 1.750000 2.100000 2.100000 1.750000 2.275000 1.925000 1.750000 2.100000 2.100000 1.750000 1.925000 location 2 20 26 +lattice3dboundary 20 nodes 3 5 1 6 crossSect 1 mat 1 polycoords 12 1.750000 2.100000 2.275000 1.750000 2.275000 2.100000 1.750000 2.100000 1.925000 1.750000 1.925000 2.100000 location 2 0 26 +latticecs 1 material 1 +latticedamage 1 d 0 talpha 0. e 1. e0 1.e5 wf 1.e5 a1 1. a2 1 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 1 prescribedvalue 1.e-3 +ConstantFunction 1 f(t) 1. + +#%BEGIN_CHECK% tolerance 1.e-8 +#REACTION tStep 1 number 6 dof 31 value 7.18396160e-04 +#%END_CHECK% + diff --git a/tests/sm/lattice3d2.in b/tests/sm/lattice3d2.in new file mode 100644 index 000000000..7b955b7c6 --- /dev/null +++ b/tests/sm/lattice3d2.in @@ -0,0 +1,46 @@ +lattice3d2.out +Test of 3D Lattice Model +StaticStructural nsteps 1 rtolv 1.e-10 nmodules 1 +errorcheck +domain 3dLattice +OutputManager tstep_all dofman_all element_all +ndofman 9 nelem 20 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 +node 1 coords 3 1.400000 1.400000 1.400000 bc 6 1 1 1 1 1 1 +node 2 coords 3 2.100000 1.400000 1.400000 bc 6 2 0 0 0 0 0 +node 3 coords 3 1.400000 2.100000 1.400000 bc 6 1 0 0 0 0 0 +node 4 coords 3 2.100000 2.100000 1.400000 bc 6 2 0 0 0 0 0 +node 5 coords 3 1.750000 1.750000 1.750000 +node 6 coords 3 1.400000 1.400000 2.100000 bc 6 1 0 0 0 0 0 +node 7 coords 3 2.100000 1.400000 2.100000 bc 6 2 0 0 0 0 0 +node 8 coords 3 1.400000 2.100000 2.100000 bc 6 1 0 0 0 0 0 +node 9 coords 3 2.100000 2.100000 2.100000 bc 6 2 0 0 0 0 0 +lattice3D 1 nodes 2 1 3 crossSect 1 mat 1 polycoords 12 1.225000 1.750000 1.400000 1.400000 1.750000 1.225000 1.575000 1.750000 1.400000 1.400000 1.750000 1.575000 +lattice3D 2 nodes 2 1 5 crossSect 1 mat 1 polycoords 18 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.750000 1.400000 1.575000 1.750000 1.575000 1.400000 1.575000 1.750000 1.400000 1.400000 1.750000 1.575000 +lattice3D 3 nodes 2 1 6 crossSect 1 mat 1 polycoords 12 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.400000 1.225000 1.750000 1.225000 1.400000 1.750000 +lattice3D 4 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 1.750000 1.225000 1.400000 1.750000 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.400000 1.225000 +lattice3D 5 nodes 2 2 4 crossSect 1 mat 1 polycoords 12 2.275000 1.750000 1.400000 2.100000 1.750000 1.225000 1.925000 1.750000 1.400000 2.100000 1.750000 1.575000 +lattice3D 6 nodes 2 2 5 crossSect 1 mat 1 polycoords 18 1.925000 1.750000 1.400000 1.750000 1.575000 1.400000 1.750000 1.400000 1.575000 1.925000 1.400000 1.750000 2.100000 1.575000 1.750000 2.100000 1.750000 1.575000 +lattice3D 7 nodes 2 2 7 crossSect 1 mat 1 polycoords 12 2.275000 1.400000 1.750000 2.100000 1.225000 1.750000 1.925000 1.400000 1.750000 2.100000 1.575000 1.750000 +lattice3D 8 nodes 2 3 4 crossSect 1 mat 1 polycoords 12 1.750000 2.100000 1.225000 1.750000 2.275000 1.400000 1.750000 2.100000 1.575000 1.750000 1.925000 1.400000 +lattice3D 9 nodes 2 3 5 crossSect 1 mat 1 polycoords 18 1.750000 2.100000 1.575000 1.575000 2.100000 1.750000 1.400000 1.925000 1.750000 1.400000 1.750000 1.575000 1.575000 1.750000 1.400000 1.750000 1.925000 1.400000 +lattice3D 10 nodes 2 3 8 crossSect 1 mat 1 polycoords 12 1.225000 2.100000 1.750000 1.400000 2.275000 1.750000 1.575000 2.100000 1.750000 1.400000 1.925000 1.750000 +lattice3D 11 nodes 2 4 9 crossSect 1 mat 1 polycoords 12 2.275000 2.100000 1.750000 2.100000 2.275000 1.750000 1.925000 2.100000 1.750000 2.100000 1.925000 1.750000 +lattice3D 12 nodes 2 4 5 crossSect 1 mat 1 polycoords 18 1.925000 2.100000 1.750000 1.750000 2.100000 1.575000 1.750000 1.925000 1.400000 1.925000 1.750000 1.400000 2.100000 1.750000 1.575000 2.100000 1.925000 1.750000 +lattice3D 13 nodes 2 5 8 crossSect 1 mat 1 polycoords 18 1.750000 1.925000 2.100000 1.750000 2.100000 1.925000 1.575000 2.100000 1.750000 1.400000 1.925000 1.750000 1.400000 1.750000 1.925000 1.575000 1.750000 2.100000 +lattice3D 14 nodes 2 5 6 crossSect 1 mat 1 polycoords 18 1.400000 1.750000 1.925000 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.750000 1.400000 1.925000 1.750000 1.575000 2.100000 1.575000 1.750000 2.100000 +lattice3D 15 nodes 2 5 9 crossSect 1 mat 1 polycoords 18 1.750000 2.100000 1.925000 1.925000 2.100000 1.750000 2.100000 1.925000 1.750000 2.100000 1.750000 1.925000 1.925000 1.750000 2.100000 1.750000 1.925000 2.100000 +lattice3D 16 nodes 2 5 7 crossSect 1 mat 1 polycoords 18 1.925000 1.400000 1.750000 1.750000 1.400000 1.925000 1.750000 1.575000 2.100000 1.925000 1.750000 2.100000 2.100000 1.750000 1.925000 2.100000 1.575000 1.750000 +lattice3D 17 nodes 2 6 8 crossSect 1 mat 1 polycoords 12 1.400000 1.750000 2.275000 1.225000 1.750000 2.100000 1.400000 1.750000 1.925000 1.575000 1.750000 2.100000 +lattice3D 18 nodes 2 6 7 crossSect 1 mat 1 polycoords 12 1.750000 1.400000 2.275000 1.750000 1.225000 2.100000 1.750000 1.400000 1.925000 1.750000 1.575000 2.100000 +lattice3D 19 nodes 2 7 9 crossSect 1 mat 1 polycoords 12 2.275000 1.750000 2.100000 2.100000 1.750000 2.275000 1.925000 1.750000 2.100000 2.100000 1.750000 1.925000 +lattice3D 20 nodes 2 8 9 crossSect 1 mat 1 polycoords 12 1.750000 2.100000 2.275000 1.750000 2.275000 2.100000 1.750000 2.100000 1.925000 1.750000 1.925000 2.100000 +latticecs 1 material 1 +latticedamage 1 d 0 talpha 0. e 1. e0 1.e5 wf 100.e+4 a1 1. a2 1. +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 1 prescribedvalue 1.e-3 +ConstantFunction 1 f(t) 1. + +#%BEGIN_CHECK% tolerance 1.e-8 +#REACTION tStep 1 number 1 dof 1 value -2.2533e-04 +#%END_CHECK% + diff --git a/tests/sm/lattice3d3.in b/tests/sm/lattice3d3.in new file mode 100644 index 000000000..484c01bf4 --- /dev/null +++ b/tests/sm/lattice3d3.in @@ -0,0 +1,20 @@ +lattice3d3.out +Direct tension. 3D Model +StaticStructural nmsteps 2 nsteps 1 nmodules 1 +nsteps 5 rtolv 1.e-6 ddm 2 2 1 ddv 1 -4. ddltf 2 +nsteps 5 rtolv 1.e-6 ddm 2 2 1 ddv 1 -1. ddltf 2 +errorcheck +domain 3dlattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 2 +node 1 coords 3 1.111711e-02 7.114932e-03 4.692007e-02 bc 6 1 1 1 1 1 1 +node 2 coords 3 1.022527e-02 5.541532e-03 4.413610e-02 bc 6 0 0 0 0 0 0 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 21 9.052245e-03 7.130119e-03 4.559351e-02 9.147877e-03 7.231811e-03 4.550540e-02 9.476180e-03 7.416481e-03 4.529586e-02 1.157304e-02 6.652583e-03 4.505586e-02 1.187257e-02 6.018345e-03 4.531836e-02 1.190671e-02 5.897034e-03 4.537598e-02 1.012734e-02 5.606267e-03 4.611033e-02 +latticecs 1 material 1 +latticedamage 1 d 0 talpha 0. e 1. e0 3. wf 1. a2 1. +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 t 2 1. 100. f(t) 2 0. 1. +#%BEGIN_CHECK% tolerance 1.e-8 +#NODE tStep 8 number 2 dof 3 unknown d value 7.58260532e-02 +#%END_CHECK% diff --git a/tests/sm/lattice3d4.in b/tests/sm/lattice3d4.in new file mode 100644 index 000000000..8083f1fac --- /dev/null +++ b/tests/sm/lattice3d4.in @@ -0,0 +1,20 @@ +lattice3d4.out +Direct tension. 3D Model +StaticStructural nmsteps 2 nsteps 1 nmodules 1 +nsteps 5 rtolv 1.e-6 ddm 2 2 1 ddv 1 -4. ddltf 2 +nsteps 5 rtolv 1.e-6 ddm 2 2 1 ddv 1 -1. ddltf 2 +errorcheck +domain 3dlattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 2 +node 1 coords 3 1.111711e-02 7.114932e-03 4.692007e-02 bc 6 1 1 1 1 1 1 +node 2 coords 3 1.022527e-02 5.541532e-03 4.413610e-02 bc 6 0 0 0 0 0 0 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 21 9.052245e-03 7.130119e-03 4.559351e-02 9.147877e-03 7.231811e-03 4.550540e-02 9.476180e-03 7.416481e-03 4.529586e-02 1.157304e-02 6.652583e-03 4.505586e-02 1.187257e-02 6.018345e-03 4.531836e-02 1.190671e-02 5.897034e-03 4.537598e-02 1.012734e-02 5.606267e-03 4.611033e-02 pressures 7 -0.1 -0.1 -0.1 -0.1 -0.1 -0.1 -0.1 +latticecs 1 material 1 +latticedamage 1 d 0 talpha 0. e 1. e0 3. wf 1. a2 1. +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 t 2 1. 100. f(t) 2 0. 1. +#%BEGIN_CHECK% tolerance 1.e-8 +#NODE tStep 8 number 2 dof 3 unknown d value 7.53812473e-02 +#%END_CHECK% diff --git a/tests/sm/lattice3dbondplast1.in b/tests/sm/lattice3dbondplast1.in new file mode 100644 index 000000000..87333bd22 --- /dev/null +++ b/tests/sm/lattice3dbondplast1.in @@ -0,0 +1,22 @@ +lattice3dbondplast1.out +Direct Tension. 3D Bond Plasticity Model +NonLinearStatic nmsteps 1 nsteps 1 contextOutputStep 1000 nmodules 1 +nsteps 3 rtolv 1.e-6 stiffMode 1 controllmode 1 refloadmode 0 minsteplength 1.e-3 ddm 2 2 1 ddv 1 1.e-4 ddltf 2 +errorcheck +domain 3dLattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 2 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 6 1 1 1 1 1 1 +node 2 coords 3 0.00100000e+00 0.000000e+00 0.000000e+00 bc 6 0 0 1 1 1 1 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 0.00005 -0.05 -0.05 0.00005 0.05 -0.05 0.00005 0.05 0.05 0.00005 -0.05 0.05 +latticecs 1 material 1 +latticebondplast 1 d 0 talpha 0. e 40.e9 a1 0.175 a2 1. fc 130.e6 angle1 0.5 iter 100 tol 1.e-6 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 nPoints 2 t 2 0. 3. f(t) 2 0. 1. +#%BEGIN_CHECK% +#ELEMENT tStep 1 number 1 gp 1 keyword 138 component 1 value 0.0 tolerance 1.e-5 +#ELEMENT tStep 1 number 1 gp 1 keyword 139 component 1 value 0.0 tolerance 1.e-5 +#ELEMENT tStep 2 number 1 gp 1 keyword 138 component 1 value 3.3333e-2 tolerance 1.e-6 +#ELEMENT tStep 2 number 1 gp 1 keyword 139 component 1 value 0.0 tolerance 1.e-2 +#%END_CHECK% diff --git a/tests/sm/lattice3dbondplast2.in b/tests/sm/lattice3dbondplast2.in new file mode 100644 index 000000000..e0b6564b7 --- /dev/null +++ b/tests/sm/lattice3dbondplast2.in @@ -0,0 +1,26 @@ +lattice3dbondplast2.out +Direct Tension. 3D Bond Plasticity Model +NonLinearStatic nmsteps 1 nsteps 1 contextOutputStep 1000 nmodules 1 +nsteps 3 rtolv 1.e-6 stiffMode 1 controllmode 1 refloadmode 0 minsteplength 1.e-4 ddm 2 2 1 ddv 1 -1.e-4 ddltf 2 +errorcheck +domain 3dLattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 2 +node 1 coords 3 0.000 0.000000e+00 0.000000e+00 bc 6 1 1 1 1 1 1 +node 2 coords 3 0.001 0.000000e+00 0.000000e+00 bc 6 0 0 1 1 1 1 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 0.00005 -0.05 -0.05 0.00005 0.05 -0.05 0.00005 0.05 0.05 0.00005 -0.05 0.05 +latticecs 1 material 1 +latticebondplast 1 d 0 talpha 0. e 40.e9 a1 1. a2 0. fc 130.e6 angle1 0.2 iter 100 tol 1.e-12 ef 0.01 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 nPoints 2 t 2 0. 3. f(t) 2 0. 1. +##%BEGIN_CHECK% +##ELEMENT number 1 gp 1 record 0 keyword strains component 1 +##ELEMENT number 1 gp 1 record 1 keyword stresses component 1 +##%END_CHECK% +#%BEGIN_CHECK% +#ELEMENT tStep 1 number 1 gp 1 keyword 138 component 1 value 0.0 tolerance 1.e-5 +#ELEMENT tStep 1 number 1 gp 1 keyword 139 component 1 value 0.0 tolerance 1.e-5 +#ELEMENT tStep 2 number 1 gp 1 keyword 138 component 1 value -3.33333333e-2 tolerance 1.e-6 +#ELEMENT tStep 2 number 1 gp 1 keyword 139 component 1 value -7.95057558e8 tolerance 1. +#%END_CHECK% diff --git a/tests/sm/lattice3dboundarytruss.in b/tests/sm/lattice3dboundarytruss.in new file mode 100644 index 000000000..4c8f43ea4 --- /dev/null +++ b/tests/sm/lattice3dboundarytruss.in @@ -0,0 +1,51 @@ +lattice3dboundarytruss.out +3d lattice model for periodic cell representing truss (1DOF:EXX (31 in dofiditem.h)) +StaticStructural nsteps 1 rtolv 1.e-10 nmodules 2 +vtkxmllattice tstep_all primvars 1 1 cross 1 cellvars 2 60 90 domain_all +errorcheck +domain 3dLattice +OutputManager tstep_all dofman_all element_all +ndofman 6 nelem 20 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 +node 1 coords 3 1.400000 1.400000 1.400000 bc 6 1 1 1 1 1 1 +node 2 coords 3 1.400000 2.100000 1.400000 +node 3 coords 3 1.750000 1.750000 1.750000 +node 4 coords 3 1.400000 1.400000 2.100000 +node 5 coords 3 1.400000 2.100000 2.100000 +node 6 coords 3 0.700000 0.700000 0.700000 dofidmask 1 31 bc 1 2 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 1.225000 1.750000 1.400000 1.400000 1.750000 1.225000 1.575000 1.750000 1.400000 1.400000 1.750000 1.575000 +lattice3D 2 nodes 2 1 3 crossSect 1 mat 1 polycoords 18 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.750000 1.400000 1.575000 1.750000 1.575000 1.400000 1.575000 1.750000 1.400000 1.400000 1.750000 1.575000 +lattice3D 3 nodes 2 1 4 crossSect 1 mat 1 polycoords 12 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.400000 1.225000 1.750000 1.225000 1.400000 1.750000 +lattice3dboundarytruss 4 nodes 3 1 5 6 crossSect 1 mat 1 polycoords 12 1.750000 1.225000 1.400000 1.750000 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.400000 1.225000 location 2 0 18 +lattice3dboundarytruss 5 nodes 3 5 4 6 crossSect 1 mat 1 polycoords 12 2.275000 1.750000 1.400000 2.100000 1.750000 1.225000 1.925000 1.750000 1.400000 2.100000 1.750000 1.575000 location 2 18 24 +lattice3dboundarytruss 6 nodes 3 5 3 6 crossSect 1 mat 1 polycoords 18 1.925000 1.750000 1.400000 1.750000 1.575000 1.400000 1.750000 1.400000 1.575000 1.925000 1.400000 1.750000 2.100000 1.575000 1.750000 2.100000 1.750000 1.575000 location 2 18 0 +lattice3dboundarytruss 7 nodes 3 5 2 6 crossSect 1 mat 1 polycoords 12 2.275000 1.400000 1.750000 2.100000 1.225000 1.750000 1.925000 1.400000 1.750000 2.100000 1.575000 1.750000 location 2 18 20 +lattice3dboundarytruss 8 nodes 3 2 4 6 crossSect 1 mat 1 polycoords 12 1.750000 2.100000 1.225000 1.750000 2.275000 1.400000 1.750000 2.100000 1.575000 1.750000 1.925000 1.400000 location 2 0 24 +lattice3D 9 nodes 2 2 3 crossSect 1 mat 1 polycoords 18 1.750000 2.100000 1.575000 1.575000 2.100000 1.750000 1.400000 1.925000 1.750000 1.400000 1.750000 1.575000 1.575000 1.750000 1.400000 1.750000 1.925000 1.400000 +lattice3D 10 nodes 2 2 5 crossSect 1 mat 1 polycoords 12 1.225000 2.100000 1.750000 1.400000 2.275000 1.750000 1.575000 2.100000 1.750000 1.400000 1.925000 1.750000 +lattice3dboundarytruss 11 nodes 3 4 1 6 crossSect 1 mat 1 polycoords 12 2.275000 2.100000 1.750000 2.100000 2.275000 1.750000 1.925000 2.100000 1.750000 2.100000 1.925000 1.750000 location 2 24 26 +lattice3dboundarytruss 12 nodes 3 4 3 6 crossSect 1 mat 1 polycoords 18 1.925000 2.100000 1.750000 1.750000 2.100000 1.575000 1.750000 1.925000 1.400000 1.925000 1.750000 1.400000 2.100000 1.750000 1.575000 2.100000 1.925000 1.750000 location 2 24 0 +lattice3D 13 nodes 2 3 5 crossSect 1 mat 1 polycoords 18 1.750000 1.925000 2.100000 1.750000 2.100000 1.925000 1.575000 2.100000 1.750000 1.400000 1.925000 1.750000 1.400000 1.750000 1.925000 1.575000 1.750000 2.100000 +lattice3D 14 nodes 2 3 4 crossSect 1 mat 1 polycoords 18 1.400000 1.750000 1.925000 1.400000 1.575000 1.750000 1.575000 1.400000 1.750000 1.750000 1.400000 1.925000 1.750000 1.575000 2.100000 1.575000 1.750000 2.100000 +lattice3dboundarytruss 15 nodes 3 3 1 6 crossSect 1 mat 1 polycoords 18 1.750000 2.100000 1.925000 1.925000 2.100000 1.750000 2.100000 1.925000 1.750000 2.100000 1.750000 1.925000 1.925000 1.750000 2.100000 1.750000 1.925000 2.100000 location 2 0 26 +lattice3dboundarytruss 16 nodes 3 3 2 6 crossSect 1 mat 1 polycoords 18 1.925000 1.400000 1.750000 1.750000 1.400000 1.925000 1.750000 1.575000 2.100000 1.925000 1.750000 2.100000 2.100000 1.750000 1.925000 2.100000 1.575000 1.750000 location 2 0 20 +lattice3D 17 nodes 2 4 5 crossSect 1 mat 1 polycoords 12 1.400000 1.750000 2.275000 1.225000 1.750000 2.100000 1.400000 1.750000 1.925000 1.575000 1.750000 2.100000 +lattice3dboundarytruss 18 nodes 3 4 2 6 crossSect 1 mat 1 polycoords 12 1.750000 1.400000 2.275000 1.750000 1.225000 2.100000 1.750000 1.400000 1.925000 1.750000 1.575000 2.100000 location 2 0 20 +lattice3dboundarytruss 19 nodes 3 2 1 6 crossSect 1 mat 1 polycoords 12 2.275000 1.750000 2.100000 2.100000 1.750000 2.275000 1.925000 1.750000 2.100000 2.100000 1.750000 1.925000 location 2 20 26 +lattice3dboundarytruss 20 nodes 3 5 1 6 crossSect 1 mat 1 polycoords 12 1.750000 2.100000 2.275000 1.750000 2.275000 2.100000 1.750000 2.100000 1.925000 1.750000 1.925000 2.100000 location 2 0 26 +latticecs 1 material 1 +latticedamage 1 d 0 talpha 0. e 1. e0 1.e5 wf 1.e5 a1 1. a2 1 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 1 prescribedvalue 1.e-3 +ConstantFunction 1 f(t) 1. +#%BEGIN_CHECK% tolerance 1.e-8 +#REACTION tStep 1 number 6 dof 31 value 6.8942e-04 +#%END_CHECK% + + +#%BEGIN_CHECK% +#NODE number 6 dof 31 unknown d +#REACTION number 6 dof 31 +#LOADLEVEL +#TIME +#%END_CHECK% + diff --git a/tests/sm/lattice3ddamplast1.in b/tests/sm/lattice3ddamplast1.in new file mode 100644 index 000000000..a4784368c --- /dev/null +++ b/tests/sm/lattice3ddamplast1.in @@ -0,0 +1,24 @@ +lattice3d_damplast_1.out +Direct tension. 3D Plasticity Damage Model +NonLinearStatic nmsteps 1 nsteps 1 contextOutputStep 1000 nmodules 1 +nsteps 3 rtolv 1.e-6 stiffMode 1 controllmode 1 refloadmode 0 minsteplength 1.e-3 ddm 2 2 1 ddv 1 1.e-4 ddltf 2 +errorcheck +domain 3dLattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 2 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 6 1 1 1 1 1 1 +node 2 coords 3 0.00100000e+00 0.000000e+00 0.000000e+00 bc 6 0 0 1 1 1 1 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 0.00005 -0.05 -0.05 0.00005 0.05 -0.05 0.00005 0.05 0.05 0.00005 -0.05 0.05 +latticecs 1 material 1 +latticeplastdam 1 d 0 talpha 0. e 40.e9 a1 0.175 a2 1. ft 6.5e6 fc 130.e6 angle1 0.5 angle2 0.5 flow 0.25 wf 1.53e-5 ahard 1.e-3 iter 100 tol 1.e-6 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 nPoints 2 t 2 0. 3. f(t) 2 0. 1. +#%BEGIN_CHECK% +#ELEMENT tStep 1 number 1 gp 1 keyword 138 component 1 value 0.0 tolerance 1.e-5 +#ELEMENT tStep 1 number 1 gp 1 keyword 139 component 1 value 0.0 tolerance 1.e-5 +#ELEMENT tStep 2 number 1 gp 1 keyword 138 component 1 value 3.3333e-2 tolerance 1.e-6 +#ELEMENT tStep 2 number 1 gp 1 keyword 139 component 1 value 7.36649264e+05 tolerance 1.e-2 +#ELEMENT tStep 3 number 1 gp 1 keyword 138 component 1 value 6.6667e-2 tolerance 1.e-6 +#ELEMENT tStep 3 number 1 gp 1 keyword 139 component 1 value 8.32955448e+04 tolerance 1.e-2 +#%END_CHECK% diff --git a/tests/sm/lattice3ddamplast2.in b/tests/sm/lattice3ddamplast2.in new file mode 100644 index 000000000..04991f0f3 --- /dev/null +++ b/tests/sm/lattice3ddamplast2.in @@ -0,0 +1,25 @@ +lattice3ddamplast2.out +Confined shear. 3D Damage Plasticity Model +NonLinearStatic nmsteps 2 nsteps 1 contextOutputStep 100 nmodules 1 +nsteps 1 rtolv 1.e-4 stiffMode 1 maxiter 1000 controllmode 1 minsteplength 1.e-6 +nsteps 2 rtolv 1.e-4 maxiter 2000 stiffMode 1 controllmode 1 refloadmode 0 minsteplength 1.e-3 ddm 2 2 2 ddv 1 1.e-4 ddltf 3 +errorcheck +domain 3dLattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 3 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 6 1 1 1 1 1 1 +node 2 coords 3 0.100000e+00 0.000000e+00 0.000000e+00 bc 6 1 0 1 1 1 1 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 0.05 -0.5 -0.5 0.05 0.5 -0.5 0.05 0.5 0.5 0.05 -0.5 0.5 +latticecs 1 material 1 +latticeplastdam 1 d 0 talpha 0. e 40.e9 a1 0.175 a2 1. ft 6.5e6 fc 130.e6 angle1 0.5 angle2 0.5 flow 0.25 wf 1.53e-5 ahard 1.e-3 iter 100 tol 1.e-6 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 1 prescribedvalue 1.5 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 nPoints 4 t 4 0. 0.1 0.2 3. f(t) 4 1. 1. 0. 0. +PiecewiseLinFunction 3 nPoints 4 t 4 0. 0.1 0.2 3. f(t) 4 0. 0. 0. 10. +#%BEGIN_CHECK% +#ELEMENT tStep 1 number 1 gp 1 keyword 138 component 1 value 0.0 tolerance 1.e-5 +#ELEMENT tStep 1 number 1 gp 1 keyword 139 component 1 value 0.0 tolerance 1.e-5 +#ELEMENT tStep 2 number 1 gp 1 keyword 139 component 1 value -3.41108968e+05 tolerance 1.e-3 +#ELEMENT tStep 2 number 1 gp 1 keyword 139 component 3 value 1.06691367e+07 tolerance 1.e-1 +#%END_CHECK% diff --git a/tests/sm/lattice3ddamplast3.in b/tests/sm/lattice3ddamplast3.in new file mode 100644 index 000000000..becdd810f --- /dev/null +++ b/tests/sm/lattice3ddamplast3.in @@ -0,0 +1,21 @@ +lattice3ddamplast3.out +Direct tension. 3D Model +NonLinearStatic nmsteps 1 nsteps 1 contextOutputStep 100 nmodules 1 +nsteps 3 rtolv 1.e-4 maxiter 2000 stiffMode 1 controllmode 1 refloadmode 0 minsteplength 1.e-3 ddm 2 2 1 ddv 1 -1. ddltf 2 +errorcheck +domain 3dLattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 2 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 6 1 1 1 1 1 1 +node 2 coords 3 1.000000e+00 0.000000e+00 0.000000e+00 bc 6 0 0 1 1 1 1 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 0.5 -0.5 -0.5 0.5 0.5 -0.5 0.5 0.5 0.5 0.5 -0.5 0.5 +latticecs 1 material 1 +latticeplastdam 1 talpha 0. d 0. e 1. ft 1. fc 10. angle1 0.5 angle2 0.5 flow 0.5 wf 5. a1 1.0 ahard 1.e-3 tol 1.e-6 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 nPoints 5 t 5 0. 60 61 62 300. f(t) 5 0. 40. 18.8 40. 100. +#%BEGIN_CHECK% +#ELEMENT tStep 1 number 1 gp 1 keyword 138 component 1 value 0.0 tolerance 1.e-5 +#ELEMENT tStep 1 number 1 gp 1 keyword 139 component 1 value 0.0 tolerance 1.e-5 +#ELEMENT tStep 2 number 1 gp 1 keyword 139 component 1 value -6.66666667e-01 tolerance 1.e-5 +#%END_CHECK% diff --git a/tests/sm/lattice3delastic.in b/tests/sm/lattice3delastic.in new file mode 100644 index 000000000..f590834d3 --- /dev/null +++ b/tests/sm/lattice3delastic.in @@ -0,0 +1,23 @@ +lattice3delastic.out +Direct tension. 3D Model +StaticStructural nsteps 3 rtolv 1.e-6 ddm 2 2 1 ddv 1 1.e-4 ddltf 2 +domain 3dLattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 2 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 6 1 1 1 1 1 1 +node 2 coords 3 0.00100000e+00 0.000000e+00 0.000000e+00 bc 6 0 0 0 0 0 0 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 0.0005 -0.0005 -0.0005 0.0005 0.0005 -0.0005 0.0005 0.0005 0.0005 0.0005 -0.0005 0.0005 +latticecs 1 material 1 +latticelinearelastic 1 d 0 talpha 0. e 40.e9 a1 1. a2 1. +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 nPoints 2 t 2 1. 4. f(t) 2 0. 1. +#%BEGIN_CHECK% +#ELEMENT number 1 gp 1 record 0 keyword strains component 1 +#ELEMENT number 1 gp 1 record 0 keyword strains component 2 +#ELEMENT number 1 gp 1 record 0 keyword strains component 3 +#ELEMENT number 1 gp 1 record 1 keyword stresses component 1 +#ELEMENT number 1 gp 1 record 1 keyword stresses component 2 +#ELEMENT number 1 gp 1 record 1 keyword stresses component 3 +##TIME +#%END_CHECK% diff --git a/tests/sm/lattice3drandom.dat b/tests/sm/lattice3drandom.dat new file mode 100644 index 000000000..bc9faece5 --- /dev/null +++ b/tests/sm/lattice3drandom.dat @@ -0,0 +1,513 @@ +8 8 8 0.555556 0.555556 0.555556 +0 0 0 1.01637 +0 0 0.0015625 1.29876 +0 0 0.003125 0.946783 +0 0 0.0046875 0.788167 +0 0 0.00625 1.11702 +0 0 0.0078125 1.02495 +0 0 0.009375 0.919829 +0 0 0.0109375 0.888123 +0 0.0015625 0 1.06191 +0 0.0015625 0.0015625 1.08382 +0 0.0015625 0.003125 0.978685 +0 0.0015625 0.0046875 0.898556 +0 0.0015625 0.00625 0.828984 +0 0.0015625 0.0078125 1.01813 +0 0.0015625 0.009375 1.13042 +0 0.0015625 0.0109375 0.999494 +0 0.003125 0 1.00473 +0 0.003125 0.0015625 0.955421 +0 0.003125 0.003125 1.02185 +0 0.003125 0.0046875 1.06728 +0 0.003125 0.00625 1.13662 +0 0.003125 0.0078125 0.952837 +0 0.003125 0.009375 0.836795 +0 0.003125 0.0109375 1.02446 +0 0.0046875 0 1.09311 +0 0.0046875 0.0015625 1.00213 +0 0.0046875 0.003125 0.77107 +0 0.0046875 0.0046875 0.904897 +0 0.0046875 0.00625 1.06063 +0 0.0046875 0.0078125 0.948689 +0 0.0046875 0.009375 1.07518 +0 0.0046875 0.0109375 1.14429 +0 0.00625 0 0.963554 +0 0.00625 0.0015625 0.909737 +0 0.00625 0.003125 1.03556 +0 0.00625 0.0046875 1.10947 +0 0.00625 0.00625 0.805704 +0 0.00625 0.0078125 0.962372 +0 0.00625 0.009375 1.19518 +0 0.00625 0.0109375 1.01842 +0 0.0078125 0 0.856985 +0 0.0078125 0.0015625 0.840942 +0 0.0078125 0.003125 1.16625 +0 0.0078125 0.0046875 1.20563 +0 0.0078125 0.00625 1.02479 +0 0.0078125 0.0078125 0.978144 +0 0.0078125 0.009375 0.951974 +0 0.0078125 0.0109375 0.975283 +0 0.009375 0 1.01534 +0 0.009375 0.0015625 0.836084 +0 0.009375 0.003125 0.995801 +0 0.009375 0.0046875 1.03509 +0 0.009375 0.00625 0.940659 +0 0.009375 0.0078125 1.05984 +0 0.009375 0.009375 1.0482 +0 0.009375 0.0109375 1.06899 +0 0.0109375 0 0.987993 +0 0.0109375 0.0015625 1.07311 +0 0.0109375 0.003125 1.084 +0 0.0109375 0.0046875 0.990915 +0 0.0109375 0.00625 1.08559 +0 0.0109375 0.0078125 1.05504 +0 0.0109375 0.009375 0.84242 +0 0.0109375 0.0109375 0.880936 +0.0015625 0 0 0.934812 +0.0015625 0 0.0015625 1.11293 +0.0015625 0 0.003125 0.848425 +0.0015625 0 0.0046875 0.911706 +0.0015625 0 0.00625 1.09936 +0.0015625 0 0.0078125 1.04721 +0.0015625 0 0.009375 1.1174 +0.0015625 0 0.0109375 0.928154 +0.0015625 0.0015625 0 0.864663 +0.0015625 0.0015625 0.0015625 0.917776 +0.0015625 0.0015625 0.003125 0.909057 +0.0015625 0.0015625 0.0046875 1.0033 +0.0015625 0.0015625 0.00625 1.13088 +0.0015625 0.0015625 0.0078125 1.0984 +0.0015625 0.0015625 0.009375 1.0954 +0.0015625 0.0015625 0.0109375 0.980529 +0.0015625 0.003125 0 1.05182 +0.0015625 0.003125 0.0015625 0.80732 +0.0015625 0.003125 0.003125 1.02856 +0.0015625 0.003125 0.0046875 0.99527 +0.0015625 0.003125 0.00625 0.938515 +0.0015625 0.003125 0.0078125 1.20606 +0.0015625 0.003125 0.009375 0.981112 +0.0015625 0.003125 0.0109375 0.991352 +0.0015625 0.0046875 0 0.709635 +0.0015625 0.0046875 0.0015625 1.03751 +0.0015625 0.0046875 0.003125 1.24836 +0.0015625 0.0046875 0.0046875 1.07947 +0.0015625 0.0046875 0.00625 0.988559 +0.0015625 0.0046875 0.0078125 0.825776 +0.0015625 0.0046875 0.009375 1.05345 +0.0015625 0.0046875 0.0109375 1.05725 +0.0015625 0.00625 0 0.969241 +0.0015625 0.00625 0.0015625 0.94037 +0.0015625 0.00625 0.003125 1.03141 +0.0015625 0.00625 0.0046875 1.1857 +0.0015625 0.00625 0.00625 1.10859 +0.0015625 0.00625 0.0078125 0.817732 +0.0015625 0.00625 0.009375 0.890763 +0.0015625 0.00625 0.0109375 1.0562 +0.0015625 0.0078125 0 1.20302 +0.0015625 0.0078125 0.0015625 1.01152 +0.0015625 0.0078125 0.003125 0.755949 +0.0015625 0.0078125 0.0046875 0.8707 +0.0015625 0.0078125 0.00625 0.942563 +0.0015625 0.0078125 0.0078125 0.977883 +0.0015625 0.0078125 0.009375 1.09846 +0.0015625 0.0078125 0.0109375 1.13989 +0.0015625 0.009375 0 1.04413 +0.0015625 0.009375 0.0015625 1.13938 +0.0015625 0.009375 0.003125 1.09161 +0.0015625 0.009375 0.0046875 0.907322 +0.0015625 0.009375 0.00625 0.853534 +0.0015625 0.009375 0.0078125 0.928997 +0.0015625 0.009375 0.009375 1.01072 +0.0015625 0.009375 0.0109375 1.0243 +0.0015625 0.0109375 0 1.22268 +0.0015625 0.0109375 0.0015625 1.03319 +0.0015625 0.0109375 0.003125 1.08664 +0.0015625 0.0109375 0.0046875 1.04653 +0.0015625 0.0109375 0.00625 0.937997 +0.0015625 0.0109375 0.0078125 1.09794 +0.0015625 0.0109375 0.009375 0.752688 +0.0015625 0.0109375 0.0109375 0.822331 +0.003125 0 0 0.975299 +0.003125 0 0.0015625 0.748336 +0.003125 0 0.003125 0.852076 +0.003125 0 0.0046875 1.06625 +0.003125 0 0.00625 1.01129 +0.003125 0 0.0078125 1.11276 +0.003125 0 0.009375 1.16133 +0.003125 0 0.0109375 1.07266 +0.003125 0.0015625 0 0.992599 +0.003125 0.0015625 0.0015625 0.980334 +0.003125 0.0015625 0.003125 0.980116 +0.003125 0.0015625 0.0046875 1.12026 +0.003125 0.0015625 0.00625 1.05558 +0.003125 0.0015625 0.0078125 1.0051 +0.003125 0.0015625 0.009375 0.971705 +0.003125 0.0015625 0.0109375 0.894306 +0.003125 0.003125 0 1.05359 +0.003125 0.003125 0.0015625 1.13062 +0.003125 0.003125 0.003125 1.06763 +0.003125 0.003125 0.0046875 1.07225 +0.003125 0.003125 0.00625 0.952871 +0.003125 0.003125 0.0078125 0.907213 +0.003125 0.003125 0.009375 0.925918 +0.003125 0.003125 0.0109375 0.889917 +0.003125 0.0046875 0 1.01664 +0.003125 0.0046875 0.0015625 1.0248 +0.003125 0.0046875 0.003125 1.2389 +0.003125 0.0046875 0.0046875 0.977245 +0.003125 0.0046875 0.00625 0.868434 +0.003125 0.0046875 0.0078125 0.954973 +0.003125 0.0046875 0.009375 0.876025 +0.003125 0.0046875 0.0109375 1.04298 +0.003125 0.00625 0 1.10454 +0.003125 0.00625 0.0015625 0.846012 +0.003125 0.00625 0.003125 1.03778 +0.003125 0.00625 0.0046875 1.05211 +0.003125 0.00625 0.00625 1.12272 +0.003125 0.00625 0.0078125 1.03775 +0.003125 0.00625 0.009375 0.734954 +0.003125 0.00625 0.0109375 1.06412 +0.003125 0.0078125 0 1.12087 +0.003125 0.0078125 0.0015625 1.123 +0.003125 0.0078125 0.003125 0.83889 +0.003125 0.0078125 0.0046875 0.843408 +0.003125 0.0078125 0.00625 0.991665 +0.003125 0.0078125 0.0078125 0.956153 +0.003125 0.0078125 0.009375 1.04857 +0.003125 0.0078125 0.0109375 1.07744 +0.003125 0.009375 0 0.866572 +0.003125 0.009375 0.0015625 1.27503 +0.003125 0.009375 0.003125 1.04252 +0.003125 0.009375 0.0046875 0.809391 +0.003125 0.009375 0.00625 0.913114 +0.003125 0.009375 0.0078125 0.942272 +0.003125 0.009375 0.009375 1.1778 +0.003125 0.009375 0.0109375 0.973302 +0.003125 0.0109375 0 0.869887 +0.003125 0.0109375 0.0015625 0.871868 +0.003125 0.0109375 0.003125 0.942096 +0.003125 0.0109375 0.0046875 1.05909 +0.003125 0.0109375 0.00625 1.08432 +0.003125 0.0109375 0.0078125 1.08377 +0.003125 0.0109375 0.009375 1.1037 +0.003125 0.0109375 0.0109375 0.985273 +0.0046875 0 0 1.16862 +0.0046875 0 0.0015625 1.00217 +0.0046875 0 0.003125 0.907337 +0.0046875 0 0.0046875 1.04413 +0.0046875 0 0.00625 0.878305 +0.0046875 0 0.0078125 0.910131 +0.0046875 0 0.009375 1.04574 +0.0046875 0 0.0109375 1.04357 +0.0046875 0.0015625 0 1.06472 +0.0046875 0.0015625 0.0015625 0.994162 +0.0046875 0.0015625 0.003125 0.894505 +0.0046875 0.0015625 0.0046875 0.843819 +0.0046875 0.0015625 0.00625 1.06754 +0.0046875 0.0015625 0.0078125 1.17092 +0.0046875 0.0015625 0.009375 0.973242 +0.0046875 0.0015625 0.0109375 0.991101 +0.0046875 0.003125 0 0.779137 +0.0046875 0.003125 0.0015625 1.03093 +0.0046875 0.003125 0.003125 1.14462 +0.0046875 0.003125 0.0046875 1.10922 +0.0046875 0.003125 0.00625 1.19078 +0.0046875 0.003125 0.0078125 0.917208 +0.0046875 0.003125 0.009375 0.885465 +0.0046875 0.003125 0.0109375 0.942639 +0.0046875 0.0046875 0 1.0511 +0.0046875 0.0046875 0.0015625 1.08603 +0.0046875 0.0046875 0.003125 1.17819 +0.0046875 0.0046875 0.0046875 0.922744 +0.0046875 0.0046875 0.00625 0.958514 +0.0046875 0.0046875 0.0078125 1.05495 +0.0046875 0.0046875 0.009375 0.8122 +0.0046875 0.0046875 0.0109375 0.936277 +0.0046875 0.00625 0 1.02958 +0.0046875 0.00625 0.0015625 1.05259 +0.0046875 0.00625 0.003125 1.11193 +0.0046875 0.00625 0.0046875 0.924267 +0.0046875 0.00625 0.00625 0.987028 +0.0046875 0.00625 0.0078125 1.14579 +0.0046875 0.00625 0.009375 0.871464 +0.0046875 0.00625 0.0109375 0.877355 +0.0046875 0.0078125 0 0.964511 +0.0046875 0.0078125 0.0015625 0.914737 +0.0046875 0.0078125 0.003125 0.903316 +0.0046875 0.0078125 0.0046875 1.10736 +0.0046875 0.0078125 0.00625 0.992898 +0.0046875 0.0078125 0.0078125 0.963469 +0.0046875 0.0078125 0.009375 1.13927 +0.0046875 0.0078125 0.0109375 1.01443 +0.0046875 0.009375 0 1.02266 +0.0046875 0.009375 0.0015625 0.914309 +0.0046875 0.009375 0.003125 0.836119 +0.0046875 0.009375 0.0046875 0.922384 +0.0046875 0.009375 0.00625 0.943888 +0.0046875 0.009375 0.0078125 1.02687 +0.0046875 0.009375 0.009375 1.19733 +0.0046875 0.009375 0.0109375 1.13644 +0.0046875 0.0109375 0 0.919677 +0.0046875 0.0109375 0.0015625 1.00507 +0.0046875 0.0109375 0.003125 1.02399 +0.0046875 0.0109375 0.0046875 1.12608 +0.0046875 0.0109375 0.00625 0.981053 +0.0046875 0.0109375 0.0078125 0.810661 +0.0046875 0.0109375 0.009375 1.07528 +0.0046875 0.0109375 0.0109375 1.05819 +0.00625 0 0 1.2446 +0.00625 0 0.0015625 0.837149 +0.00625 0 0.003125 1.02901 +0.00625 0 0.0046875 1.11325 +0.00625 0 0.00625 0.694014 +0.00625 0 0.0078125 0.807318 +0.00625 0 0.009375 1.03237 +0.00625 0 0.0109375 1.24228 +0.00625 0.0015625 0 1.11275 +0.00625 0.0015625 0.0015625 0.918136 +0.00625 0.0015625 0.003125 0.899259 +0.00625 0.0015625 0.0046875 0.985982 +0.00625 0.0015625 0.00625 0.951326 +0.00625 0.0015625 0.0078125 0.855553 +0.00625 0.0015625 0.009375 1.03667 +0.00625 0.0015625 0.0109375 1.24033 +0.00625 0.003125 0 0.794164 +0.00625 0.003125 0.0015625 1.13046 +0.00625 0.003125 0.003125 1.09147 +0.00625 0.003125 0.0046875 0.925413 +0.00625 0.003125 0.00625 1.0337 +0.00625 0.003125 0.0078125 0.935181 +0.00625 0.003125 0.009375 1.08066 +0.00625 0.003125 0.0109375 1.00894 +0.00625 0.0046875 0 0.826367 +0.00625 0.0046875 0.0015625 1.18551 +0.00625 0.0046875 0.003125 1.12277 +0.00625 0.0046875 0.0046875 0.899589 +0.00625 0.0046875 0.00625 1.16428 +0.00625 0.0046875 0.0078125 1.06555 +0.00625 0.0046875 0.009375 0.886579 +0.00625 0.0046875 0.0109375 0.849358 +0.00625 0.00625 0 0.996222 +0.00625 0.00625 0.0015625 1.19409 +0.00625 0.00625 0.003125 0.911857 +0.00625 0.00625 0.0046875 0.898531 +0.00625 0.00625 0.00625 1.17817 +0.00625 0.00625 0.0078125 1.05316 +0.00625 0.00625 0.009375 0.913746 +0.00625 0.00625 0.0109375 0.854213 +0.00625 0.0078125 0 0.960435 +0.00625 0.0078125 0.0015625 0.826739 +0.00625 0.0078125 0.003125 0.972248 +0.00625 0.0078125 0.0046875 1.09324 +0.00625 0.0078125 0.00625 1.03189 +0.00625 0.0078125 0.0078125 1.11283 +0.00625 0.0078125 0.009375 1.03543 +0.00625 0.0078125 0.0109375 0.967184 +0.00625 0.009375 0 0.965016 +0.00625 0.009375 0.0015625 0.838296 +0.00625 0.009375 0.003125 0.967655 +0.00625 0.009375 0.0046875 1.06281 +0.00625 0.009375 0.00625 1.09411 +0.00625 0.009375 0.0078125 1.20434 +0.00625 0.009375 0.009375 0.973215 +0.00625 0.009375 0.0109375 0.89456 +0.00625 0.0109375 0 1.10045 +0.00625 0.0109375 0.0015625 1.06962 +0.00625 0.0109375 0.003125 1.00572 +0.00625 0.0109375 0.0046875 1.02119 +0.00625 0.0109375 0.00625 0.852504 +0.00625 0.0109375 0.0078125 0.966068 +0.00625 0.0109375 0.009375 1.04133 +0.00625 0.0109375 0.0109375 0.943129 +0.0078125 0 0 1.00408 +0.0078125 0 0.0015625 0.916479 +0.0078125 0 0.003125 0.975505 +0.0078125 0 0.0046875 1.11334 +0.0078125 0 0.00625 1.18199 +0.0078125 0 0.0078125 1.00322 +0.0078125 0 0.009375 0.838428 +0.0078125 0 0.0109375 0.966956 +0.0078125 0.0015625 0 0.996474 +0.0078125 0.0015625 0.0015625 0.996871 +0.0078125 0.0015625 0.003125 1.12875 +0.0078125 0.0015625 0.0046875 1.08624 +0.0078125 0.0015625 0.00625 0.884999 +0.0078125 0.0015625 0.0078125 0.707679 +0.0078125 0.0015625 0.009375 0.989775 +0.0078125 0.0015625 0.0109375 1.20921 +0.0078125 0.003125 0 1.0839 +0.0078125 0.003125 0.0015625 1.07957 +0.0078125 0.003125 0.003125 1.01745 +0.0078125 0.003125 0.0046875 0.947032 +0.0078125 0.003125 0.00625 0.814628 +0.0078125 0.003125 0.0078125 0.854222 +0.0078125 0.003125 0.009375 1.08402 +0.0078125 0.003125 0.0109375 1.11917 +0.0078125 0.0046875 0 1.18519 +0.0078125 0.0046875 0.0015625 0.841208 +0.0078125 0.0046875 0.003125 0.791089 +0.0078125 0.0046875 0.0046875 1.15745 +0.0078125 0.0046875 0.00625 0.983334 +0.0078125 0.0046875 0.0078125 1.01718 +0.0078125 0.0046875 0.009375 1.04039 +0.0078125 0.0046875 0.0109375 0.984163 +0.0078125 0.00625 0 0.990763 +0.0078125 0.00625 0.0015625 0.913692 +0.0078125 0.00625 0.003125 0.943505 +0.0078125 0.00625 0.0046875 0.897492 +0.0078125 0.00625 0.00625 0.971705 +0.0078125 0.00625 0.0078125 1.13756 +0.0078125 0.00625 0.009375 1.09403 +0.0078125 0.00625 0.0109375 1.05125 +0.0078125 0.0078125 0 0.866454 +0.0078125 0.0078125 0.0015625 1.05727 +0.0078125 0.0078125 0.003125 1.14439 +0.0078125 0.0078125 0.0046875 0.84297 +0.0078125 0.0078125 0.00625 1.1531 +0.0078125 0.0078125 0.0078125 1.1792 +0.0078125 0.0078125 0.009375 0.83605 +0.0078125 0.0078125 0.0109375 0.92055 +0.0078125 0.009375 0 0.921263 +0.0078125 0.009375 0.0015625 1.09026 +0.0078125 0.009375 0.003125 1.06354 +0.0078125 0.009375 0.0046875 1.04213 +0.0078125 0.009375 0.00625 1.03168 +0.0078125 0.009375 0.0078125 1.00499 +0.0078125 0.009375 0.009375 0.98352 +0.0078125 0.009375 0.0109375 0.862618 +0.0078125 0.0109375 0 0.951882 +0.0078125 0.0109375 0.0015625 1.10465 +0.0078125 0.0109375 0.003125 0.935764 +0.0078125 0.0109375 0.0046875 0.913341 +0.0078125 0.0109375 0.00625 0.978566 +0.0078125 0.0109375 0.0078125 1.09594 +0.0078125 0.0109375 0.009375 1.13379 +0.0078125 0.0109375 0.0109375 0.886076 +0.009375 0 0 0.763732 +0.009375 0 0.0015625 1.11576 +0.009375 0 0.003125 1.17213 +0.009375 0 0.0046875 1.03234 +0.009375 0 0.00625 1.17767 +0.009375 0 0.0078125 1.05497 +0.009375 0 0.009375 0.886467 +0.009375 0 0.0109375 0.796936 +0.009375 0.0015625 0 0.832745 +0.009375 0.0015625 0.0015625 1.01771 +0.009375 0.0015625 0.003125 1.14194 +0.009375 0.0015625 0.0046875 0.995205 +0.009375 0.0015625 0.00625 1.16411 +0.009375 0.0015625 0.0078125 1.12122 +0.009375 0.0015625 0.009375 0.861206 +0.009375 0.0015625 0.0109375 0.86587 +0.009375 0.003125 0 1.14752 +0.009375 0.003125 0.0015625 0.7835 +0.009375 0.003125 0.003125 0.819045 +0.009375 0.003125 0.0046875 0.935056 +0.009375 0.003125 0.00625 0.876812 +0.009375 0.003125 0.0078125 1.20477 +0.009375 0.003125 0.009375 1.15662 +0.009375 0.003125 0.0109375 1.07667 +0.009375 0.0046875 0 1.06388 +0.009375 0.0046875 0.0015625 0.787567 +0.009375 0.0046875 0.003125 0.867257 +0.009375 0.0046875 0.0046875 1.21827 +0.009375 0.0046875 0.00625 0.906651 +0.009375 0.0046875 0.0078125 1.03079 +0.009375 0.0046875 0.009375 1.16221 +0.009375 0.0046875 0.0109375 0.963372 +0.009375 0.00625 0 0.93568 +0.009375 0.00625 0.0015625 1.05016 +0.009375 0.00625 0.003125 1.0148 +0.009375 0.00625 0.0046875 0.939891 +0.009375 0.00625 0.00625 0.893401 +0.009375 0.00625 0.0078125 0.946711 +0.009375 0.00625 0.009375 1.15612 +0.009375 0.00625 0.0109375 1.06324 +0.009375 0.0078125 0 1.06171 +0.009375 0.0078125 0.0015625 1.20932 +0.009375 0.0078125 0.003125 1.02262 +0.009375 0.0078125 0.0046875 0.857718 +0.009375 0.0078125 0.00625 0.951651 +0.009375 0.0078125 0.0078125 0.952868 +0.009375 0.0078125 0.009375 0.964024 +0.009375 0.0078125 0.0109375 0.980096 +0.009375 0.009375 0 1.15307 +0.009375 0.009375 0.0015625 1.05059 +0.009375 0.009375 0.003125 0.994028 +0.009375 0.009375 0.0046875 1.09271 +0.009375 0.009375 0.00625 1.05211 +0.009375 0.009375 0.0078125 0.793551 +0.009375 0.009375 0.009375 0.800791 +0.009375 0.009375 0.0109375 1.06315 +0.009375 0.0109375 0 1.04167 +0.009375 0.0109375 0.0015625 0.985406 +0.009375 0.0109375 0.003125 0.968186 +0.009375 0.0109375 0.0046875 0.928809 +0.009375 0.0109375 0.00625 0.977588 +0.009375 0.0109375 0.0078125 0.895123 +0.009375 0.0109375 0.009375 1.01256 +0.009375 0.0109375 0.0109375 1.19066 +0.0109375 0 0 0.892489 +0.0109375 0 0.0015625 0.96842 +0.0109375 0 0.003125 1.26873 +0.0109375 0 0.0046875 0.930825 +0.0109375 0 0.00625 0.840347 +0.0109375 0 0.0078125 1.03943 +0.0109375 0 0.009375 0.998431 +0.0109375 0 0.0109375 1.06132 +0.0109375 0.0015625 0 1.07415 +0.0109375 0.0015625 0.0015625 1.09119 +0.0109375 0.0015625 0.003125 1.06769 +0.0109375 0.0015625 0.0046875 1.06665 +0.0109375 0.0015625 0.00625 0.916586 +0.0109375 0.0015625 0.0078125 1.023 +0.0109375 0.0015625 0.009375 0.941583 +0.0109375 0.0015625 0.0109375 0.81916 +0.0109375 0.003125 0 1.08515 +0.0109375 0.003125 0.0015625 1.08218 +0.0109375 0.003125 0.003125 0.809373 +0.0109375 0.003125 0.0046875 0.948476 +0.0109375 0.003125 0.00625 1.05608 +0.0109375 0.003125 0.0078125 1.02251 +0.0109375 0.003125 0.009375 1.0494 +0.0109375 0.003125 0.0109375 0.946837 +0.0109375 0.0046875 0 1.05408 +0.0109375 0.0046875 0.0015625 1.03526 +0.0109375 0.0046875 0.003125 0.782363 +0.0109375 0.0046875 0.0046875 0.840335 +0.0109375 0.0046875 0.00625 1.06959 +0.0109375 0.0046875 0.0078125 1.10209 +0.0109375 0.0046875 0.009375 1.09397 +0.0109375 0.0046875 0.0109375 1.02231 +0.0109375 0.00625 0 1.01041 +0.0109375 0.00625 0.0015625 1.09335 +0.0109375 0.00625 0.003125 0.913164 +0.0109375 0.00625 0.0046875 0.992539 +0.0109375 0.00625 0.00625 0.932676 +0.0109375 0.00625 0.0078125 0.898913 +0.0109375 0.00625 0.009375 1.14375 +0.0109375 0.00625 0.0109375 1.0152 +0.0109375 0.0078125 0 0.966011 +0.0109375 0.0078125 0.0015625 1.01647 +0.0109375 0.0078125 0.003125 1.19634 +0.0109375 0.0078125 0.0046875 1.17897 +0.0109375 0.0078125 0.00625 0.911438 +0.0109375 0.0078125 0.0078125 0.879444 +0.0109375 0.0078125 0.009375 0.926211 +0.0109375 0.0078125 0.0109375 0.925121 +0.0109375 0.009375 0 1.01195 +0.0109375 0.009375 0.0015625 0.856053 +0.0109375 0.009375 0.003125 1.00873 +0.0109375 0.009375 0.0046875 1.12816 +0.0109375 0.009375 0.00625 1.1709 +0.0109375 0.009375 0.0078125 1.03914 +0.0109375 0.009375 0.009375 0.808425 +0.0109375 0.009375 0.0109375 0.976645 +0.0109375 0.0109375 0 0.905764 +0.0109375 0.0109375 0.0015625 0.857085 +0.0109375 0.0109375 0.003125 0.953612 +0.0109375 0.0109375 0.0046875 0.914049 +0.0109375 0.0109375 0.00625 1.10238 +0.0109375 0.0109375 0.0078125 0.995461 +0.0109375 0.0109375 0.009375 1.03824 +0.0109375 0.0109375 0.0109375 1.2334 diff --git a/tests/sm/lattice3drandom.in b/tests/sm/lattice3drandom.in new file mode 100644 index 000000000..83e3ceaa0 --- /dev/null +++ b/tests/sm/lattice3drandom.in @@ -0,0 +1,21 @@ +lattice3drandom.out +Direct tension. 3D Model +StaticStructural nsteps 1 rtolv 1.e-6 ddm 2 2 1 ddv 1 1.e-4 ddltf 2 nmodules 1 +errorcheck +domain 3dLattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 3 +node 1 coords 3 0.0 0.0005 0.0005 bc 6 1 1 1 1 1 1 +node 2 coords 3 0.001 0.0005 0.0005 bc 6 0 0 1 1 1 1 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 0.0005 -0.0495 -0.0495 0.0005 0.0505 -0.0495 0.0005 0.0505 0.0505 0.0005 -0.0495 0.0505 +latticecs 1 material 1 +latticedamage 1 d 0 talpha 0. e 30.e9 e0 100.e-6 wf 100.e-4 randvars 1 800 randgen 1 3 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 t 1 1. f(t) 1 0.1 +InterpolatingFunction 3 name lattice3drandom.dat dim 3 + +#%BEGIN_CHECK% tolerance 1.e-3 +#REACTION tStep 1 number 1 dof 1 value -3.14823510e+04 +#%END_CHECK% + diff --git a/tests/sm/latticedamagevisco_mps_1.in b/tests/sm/latticedamagevisco_mps_1.in new file mode 100644 index 000000000..1863ce7ad --- /dev/null +++ b/tests/sm/latticedamagevisco_mps_1.in @@ -0,0 +1,44 @@ +latticedamagevisco_mps_1.out +Single element loaded in uniaxial tension. Nonuniform loading rate, damage initiation, partial relaxation, damage growth, end of loading, stress relaxation. MPS model used for viscoelasticity, basic creep only, no shrinkage. +nonlinearstatic nsteps 25 rtolv 1.e-8 MaxIter 5000 controllmode 1 stiffMode 1 renumber 1 updateelasticstiffnessflag manrmsteps 5 deltatfunction 4 nmodules 1 + errorcheck +# +domain 2dlattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 2 nbc 3 nic 0 nltf 4 nset 3 +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 100 0.0 0.0 +# +Lattice2D 1 nodes 2 1 2 crossSect 1 mat 2 gpCoords 2 50 0. width 1000.0 thick 1000.0 +# +latticecs 1 material 2 +# +mps 1 d 0. lattice a1 1. a2 1. talpha 0. referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1000. relMatAge 28. CoupledAnalysisType 0 +latticedamageviscoelastic 2 d 0. talpha 0. viscomat 1 a1 1. a2 1. e 20.e3 e0 150.e-6 wf 50.e-3 stype 3 timefactor 1. +# +BoundaryCondition 1 loadTimeFunction 1 dofs 2 2 6 values 2 0. 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0. set 2 +BoundaryCondition 3 loadTimeFunction 3 dofs 1 1 values 1 1. set 3 +# +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 1.0 +PiecewiseLinFunction 3 nPoints 3 t 4 0. 0.1 100. 1.e4 f(t) 4 0. 0.015 0.03 0.03 +PiecewiseLinfunction 4 npoints 25 t 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 f(t) 25 0.0001 0.0002 0.0003 0.0005 0.001 0.003 0.005 0.01 0.03 0.05 0.1 0.3 0.5 1 3 5 10 30 50 100 300 500 1000 3000 5000 +# +Set 1 nodes 2 1 2 +Set 2 nodes 1 1 +Set 3 nodes 1 2 +# +#TIME +#ELEMENT number 1 gp 1 keyword latticestress component 1 +#ELEMENT number 1 gp 1 keyword latticesrain component 1 +# +#%BEGIN_CHECK% +#ELEMENT tStep 10 number 1 gp 1 keyword 139 component 1 value 2.80973767e+00 tolerance 1.e-6 +#ELEMENT tStep 13 number 1 gp 1 keyword 139 component 1 value 2.59407647e+00 tolerance 1.e-6 +#ELEMENT tStep 16 number 1 gp 1 keyword 139 component 1 value 2.58931209e+00 tolerance 1.e-6 +#ELEMENT tStep 19 number 1 gp 1 keyword 139 component 1 value 2.20529126e+00 tolerance 1.e-6 +#ELEMENT tStep 22 number 1 gp 1 keyword 139 component 1 value 1.94566185e+00 tolerance 1.e-6 +#ELEMENT tStep 25 number 1 gp 1 keyword 139 component 1 value 1.70116204e+00 tolerance 1.e-6 +#%END_CHECK% diff --git a/tests/sm/latticedyn1.in b/tests/sm/latticedyn1.in new file mode 100644 index 000000000..ea70abc23 --- /dev/null +++ b/tests/sm/latticedyn1.in @@ -0,0 +1,23 @@ +latticedyn1.out +lattice3d to test nldeidynamic +NlDEIDynamic nsteps 1 nmodules 1 contextOutputStep 1000000 dumpcoef 0. deltat 0.0001 reduct 0.8 profileopt 1 +errorcheck +domain 3d +OutputManager tstep_all dofman_output { 1 3 } +ndofman 3 nelem 2 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 2 +node 1 coords 3 0.00 0. 0. bc 3 1 1 1 +node 2 coords 3 0.02 0. 0. +node 3 coords 3 0.04 0. 0. bc 3 2 1 1 +lattice3d 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 0.01 -0.01 -0.01 0.01 -0.01 0.01 0.01 0.01 0.01 0.01 0.01 -0.01 +lattice3d 2 nodes 2 2 3 crossSect 1 mat 1 polycoords 12 0.03 -0.01 -0.01 0.03 -0.01 0.01 0.03 0.01 0.01 0.03 0.01 -0.01 +LatticeCS 1 material 1 +latticelinearelastic 1 d 7600 e 200.00e9 talpha 0. +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 2 prescribedvalue 0.00015 +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 t 2 0. 0.1 f(t) 2 0.0 1.0 + +#%BEGIN_CHECK% +#NODE tStep 22 number 3 dof 3 unknown d value 6.61634340e-09 tolerance 1.e-12 +#REACTION tStep 22 number 1 dof 3 value 1.3303e+01 tolerance 1.e-3 +#%END_CHECK% \ No newline at end of file diff --git a/tests/sm/latticeframe3dnl.in b/tests/sm/latticeframe3dnl.in new file mode 100644 index 000000000..085905c77 --- /dev/null +++ b/tests/sm/latticeframe3dnl.in @@ -0,0 +1,42 @@ +latticeframe3dnl.out +Buckling3D. Model +NonlinearStatic nmsteps 1 nsteps 1 nmodules 1 +nsteps 100 stiffmode 0 rtolv 1.e-3 maxiter 20000 initialguess 1 controlmode 1 +errorcheck +#vtkxml tstep_step 1 primvars 1 1 cellvars 8 138 139 140 47 46 45 141 52 domain_all element_all +domain 3dLattice +OutputManager +ndofman 9 nelem 8 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 2 nset 0 +node 1 coords 3 0.0 0.0 0.0 bc 6 1 1 1 1 1 1 +node 2 coords 3 1.1775 0.0 0.0 +node 3 coords 3 2.355 0.0 0.0 +node 4 coords 3 3.5325 0.0 0.0 +node 5 coords 3 4.71 0.0 0.0 +node 6 coords 3 5.8875 0.0 0.0 +node 7 coords 3 7.065 0.0 0.0 +node 8 coords 3 8.2425 0.0 0.0 +node 9 coords 3 9.42 0.0 0.0 bc 6 0 0 0 0 0 2 +# +latticeframe3dnl 1 nodes 2 1 2 zaxis 3 0 0 1 crossSect 1 mat 1 +latticeframe3dnl 2 nodes 2 2 3 zaxis 3 0 0 1 crossSect 1 mat 1 +latticeframe3dnl 3 nodes 2 3 4 zaxis 3 0 0 1 crossSect 1 mat 1 +latticeframe3dnl 4 nodes 2 4 5 zaxis 3 0 0 1 crossSect 1 mat 1 +latticeframe3dnl 5 nodes 2 5 6 zaxis 3 0 0 1 crossSect 1 mat 1 +latticeframe3dnl 6 nodes 2 6 7 zaxis 3 0 0 1 crossSect 1 mat 1 +latticeframe3dnl 7 nodes 2 7 8 zaxis 3 0 0 1 crossSect 1 mat 1 +latticeframe3dnl 8 nodes 2 8 9 zaxis 3 0 0 1 crossSect 1 mat 1 +# +latticecs 1 material 1 iy 7.857e-9 iz 7.857e-9 ik 1.6e-8 shearCoeff 0.83 area 3.1416e-4 +latticeframeelastic 1 d 1. E 2.1e11 n 0.3 talpha 0 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 2 prescribedvalue 1. +ConstantFunction 1 f(t) 1 +PiecewiseLinFunction 2 t 3 -1. 0. 100 f(t) 3 0. 0. .1 +#%BEGIN_CHECK% tolerance 1.e-6 +#NODE tStep 100 number 1 dof 1 unknown d value 0.0 +#NODE tStep 100 number 1 dof 2 unknown d value 0.0 +#NODE tStep 100 number 5 dof 1 unknown d value -1.89407969e-03 +#NODE tStep 100 number 5 dof 2 unknown d value 1.16549434e-01 +#NODE tStep 100 number 9 dof 1 unknown d value -1.53218429e-02 +#NODE tStep 100 number 9 dof 2 unknown d value 4.65912214e-01 +#%END_CHECK% diff --git a/tests/sm/latticeframesteelplastic1.in b/tests/sm/latticeframesteelplastic1.in new file mode 100644 index 000000000..ad2600f99 --- /dev/null +++ b/tests/sm/latticeframesteelplastic1.in @@ -0,0 +1,22 @@ +latticeframesteelplastic1.out +Cantilever test with latticeframesteelplastic material model +NonLinearStatic nmsteps 1 nsteps 20 contextOutputStep 100 nmodules 1 +nsteps 20 rtolv 1.e-0 maxiter 2000 stiffMode 1 controllmode 1 refloadmode 1 minsteplength 1.e-3 ddm 2 3 6 ddv 1 2 ddltf 2 +errorcheck +domain 3dLattice +OutputManager tstep_all +ndofman 3 nelem 2 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 2 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 6 1 1 1 1 1 1 +node 2 coords 3 0.500000e+00 0.000000e+00 0.000000e+00 +node 3 coords 3 1.000000e+00 0.000000e+00 0.000000e+00 bc 6 0 0 0 0 0 0 +latticeframe3d 1 nodes 2 1 2 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 2 nodes 2 2 3 zaxis 3 0 0 1 crossSect 1 +latticecs 1 material 1 iy 0.083 iz 0.083 ik 0.167 shearCoeff 1. area 1. +latticeframesteelplastic 1 d 1. E 1. n 0.15 talpha 0 nx0 1 mx0 1 my0 1 mz0 1 tol 1.e-6 iter 100 sub 10 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 nPoints 2 t 2 0 20. f(t) 2 0. 2 +#%BEGIN_CHECK% +#NODE tStep 20 number 3 dof 2 unknown d value 1.90000118e+01 tolerance 1.e-4 +#NODE tStep 20 number 3 dof 6 unknown d value 3.80000237e+01 tolerance 1.e-4 +#%END_CHECK% diff --git a/tests/sm/latticeframesteelplastic2.in b/tests/sm/latticeframesteelplastic2.in new file mode 100644 index 000000000..4e82f2353 --- /dev/null +++ b/tests/sm/latticeframesteelplastic2.in @@ -0,0 +1,51 @@ +latticeframesteelplastic2.out +Toi 1993 plastic frame +NonLinearStatic nmsteps 1 nsteps 1 contextOutputStep 100 nmodules 1 +nsteps 10 rtolv 1.e-6 maxiter 100 stiffMode 1 controllmode 1 refloadmode 1 minsteplength 1.e-3 ddm 2 5 1 ddv 1 2e-1 ddltf 2 +#vtkxml tstep_step 1 primvars 1 1 domain_all element_all +errorcheck +domain 3dLattice +OutputManager +ndofman 13 nelem 12 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 2 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 6 1 1 1 1 1 1 +node 2 coords 3 0.000000e+00 250.000000e+00 0.000000e+00 +node 3 coords 3 0.000000e+00 500.000000e+00 0.000000e+00 +node 4 coords 3 0.000000e+00 750.000000e+00 0.000000e+00 +node 5 coords 3 0.000000e+00 1000.000e+00 0.000000e+00 +node 6 coords 3 250.0000e+00 1000.000e+00 0.000000e+00 +node 7 coords 3 500.0000e+00 1000.000e+00 0.000000e+00 +node 8 coords 3 750.0000e+00 1000.000e+00 0.000000e+00 +node 9 coords 3 1000.0000e+00 1000.000e+00 0.000000e+00 +node 10 coords 3 1000.000e+00 750.000e+00 0.000000e+00 +node 11 coords 3 1000.000e+00 500.000e+00 0.000000e+00 +node 12 coords 3 1000.000e+00 250.000e+00 0.000000e+00 +node 13 coords 3 1000.000e+00 0.000000e+00 0.000000e+00 bc 6 1 1 1 1 1 1 +latticeframe3d 1 nodes 2 1 2 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 2 nodes 2 2 3 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 3 nodes 2 3 4 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 4 nodes 2 4 5 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 5 nodes 2 5 6 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 6 nodes 2 6 7 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 7 nodes 2 7 8 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 8 nodes 2 8 9 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 9 nodes 2 9 10 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 10 nodes 2 10 11 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 11 nodes 2 11 12 zaxis 3 0 0 1 crossSect 1 +latticeframe3d 12 nodes 2 12 13 zaxis 3 0 0 1 crossSect 1 +latticecs 1 material 1 area 25281 iy 5.3e7 iz 5.3e7 ik 1e8 shearCoeff 0.833 +latticeframesteelplastic 1 d 1. E 2.1e4 n 0.3 talpha 0 nx0 6e5 mx0 3e7 my0 3e7 mz0 3e7 tol 1.e-6 iter 100 sub 10 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 nPoints 2 t 2 0 10. f(t) 2 0. 10 +#%BEGIN_CHECK% +#REACTION tStep 10 number 1 dof 1 value -7.13485006e+04 tolerance 1.e-3 +#REACTION tStep 10 number 1 dof 2 value -6.49983931e+04 tolerance 1.e-3 +#REACTION tStep 10 number 1 dof 6 value 3.87420101e+07 tolerance 1. +#REACTION tStep 10 number 13 dof 1 value -7.11033739e+04 tolerance 1.e-3 +#REACTION tStep 10 number 13 dof 2 value 6.49983991e+04 tolerance 1.e-3 +#REACTION tStep 10 number 13 dof 6 value 3.87113692e+07 tolerance 1. +#NODE tStep 10 number 5 dof 1 unknown d value 9.00000895e+00 tolerance 1.e-5 +#NODE tStep 10 number 5 dof 2 unknown d value 1.36093742e-01 tolerance 1.e-5 +#NODE tStep 10 number 5 dof 6 unknown d value -5.26397500e-03 tolerance 1.e-6 +#TIME +#%END_CHECK% diff --git a/tests/sm/latticelink1.in b/tests/sm/latticelink1.in new file mode 100644 index 000000000..00a2221b2 --- /dev/null +++ b/tests/sm/latticelink1.in @@ -0,0 +1,33 @@ +latticelink1.out +Bond test for lattice elements +StaticStructural nsteps 1 nmodules 0 initialguess 0 rtolv 1.e-3 +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 7 nelem 5 ncrosssect 2 nmat 2 nbc 2 nic 0 nltf 1 nset 4 +#Beam nodes +node 1 coords 3 0. 0. 0. +node 2 coords 3 0.1 0. 0. +node 3 coords 3 0.2 0. 0. +#Lattice nodes +node 4 coords 3 0.005 0.01 0.01 +node 5 coords 3 -0.001 -0.008 0.012 +node 6 coords 3 0.01 0.02 -0.008 +node 7 coords 3 0. 0.01 0. +#BeamElements +libeam3d2 1 nodes 2 1 2 refnode 7 +libeam3d2 2 nodes 2 2 3 refnode 7 +#links for first node +latticelink3d 3 nodes 2 1 4 crossSect 2 mat 2 length 0.05 diameter 1.e-2 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 l_end 0.2 +latticelink3d 4 nodes 2 2 5 crossSect 2 mat 2 length 0.1 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 l_end 0.15 +latticelink3d 5 nodes 2 3 6 crossSect 2 mat 2 length 0.05 diameter 1.e-02 dirvector 3 1.000000e+00 0.000000e+00 0.000000e+00 l_end 0.05 +FiberedCS 1 fibermaterials 16 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 thicks 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 widths 16 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 0.003 0.003 0.003 0.003 0.0015 0.003 0.003 0.0015 fiberycentrecoords 16 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 0.0045 0.0015 -0.0015 -0.0045 0.00375 0.0015 -0.0015 -0.00375 fiberzcentrecoords 16 -0.0015 -0.0015 -0.0015 -0.0015 -0.00375 -0.0045 -0.0045 -0.00375 0.0015 0.0015 0.0015 0.0015 0.00375 0.0045 0.0045 0.00375 thick 0.012 width 0.012 set 1 +latticecs 2 material 2 +isole 1 d 0 e 2e11 n 0.3 talpha 0. +latticeslip 2 talpha 0. d 0. e 30.e9 a1 1000 t0 1.e6 +BoundaryCondition 1 loadTimeFunction 1 dofs 6 1 2 3 4 5 6 values 6 0. 0. 0. 0. 0. 0. set 4 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0.001 set 2 +PiecewiseLinFunction 1 nPoints 2 t 2 0. 1. f(t) 2 0. 1. +set 1 elements 2 1 2 +set 2 nodes 1 3 +set 3 elements 3 3 4 5 +set 4 nodes 3 4 5 6 \ No newline at end of file diff --git a/tests/sm/latticeplastdam3drandom.dat b/tests/sm/latticeplastdam3drandom.dat new file mode 100644 index 000000000..bc9faece5 --- /dev/null +++ b/tests/sm/latticeplastdam3drandom.dat @@ -0,0 +1,513 @@ +8 8 8 0.555556 0.555556 0.555556 +0 0 0 1.01637 +0 0 0.0015625 1.29876 +0 0 0.003125 0.946783 +0 0 0.0046875 0.788167 +0 0 0.00625 1.11702 +0 0 0.0078125 1.02495 +0 0 0.009375 0.919829 +0 0 0.0109375 0.888123 +0 0.0015625 0 1.06191 +0 0.0015625 0.0015625 1.08382 +0 0.0015625 0.003125 0.978685 +0 0.0015625 0.0046875 0.898556 +0 0.0015625 0.00625 0.828984 +0 0.0015625 0.0078125 1.01813 +0 0.0015625 0.009375 1.13042 +0 0.0015625 0.0109375 0.999494 +0 0.003125 0 1.00473 +0 0.003125 0.0015625 0.955421 +0 0.003125 0.003125 1.02185 +0 0.003125 0.0046875 1.06728 +0 0.003125 0.00625 1.13662 +0 0.003125 0.0078125 0.952837 +0 0.003125 0.009375 0.836795 +0 0.003125 0.0109375 1.02446 +0 0.0046875 0 1.09311 +0 0.0046875 0.0015625 1.00213 +0 0.0046875 0.003125 0.77107 +0 0.0046875 0.0046875 0.904897 +0 0.0046875 0.00625 1.06063 +0 0.0046875 0.0078125 0.948689 +0 0.0046875 0.009375 1.07518 +0 0.0046875 0.0109375 1.14429 +0 0.00625 0 0.963554 +0 0.00625 0.0015625 0.909737 +0 0.00625 0.003125 1.03556 +0 0.00625 0.0046875 1.10947 +0 0.00625 0.00625 0.805704 +0 0.00625 0.0078125 0.962372 +0 0.00625 0.009375 1.19518 +0 0.00625 0.0109375 1.01842 +0 0.0078125 0 0.856985 +0 0.0078125 0.0015625 0.840942 +0 0.0078125 0.003125 1.16625 +0 0.0078125 0.0046875 1.20563 +0 0.0078125 0.00625 1.02479 +0 0.0078125 0.0078125 0.978144 +0 0.0078125 0.009375 0.951974 +0 0.0078125 0.0109375 0.975283 +0 0.009375 0 1.01534 +0 0.009375 0.0015625 0.836084 +0 0.009375 0.003125 0.995801 +0 0.009375 0.0046875 1.03509 +0 0.009375 0.00625 0.940659 +0 0.009375 0.0078125 1.05984 +0 0.009375 0.009375 1.0482 +0 0.009375 0.0109375 1.06899 +0 0.0109375 0 0.987993 +0 0.0109375 0.0015625 1.07311 +0 0.0109375 0.003125 1.084 +0 0.0109375 0.0046875 0.990915 +0 0.0109375 0.00625 1.08559 +0 0.0109375 0.0078125 1.05504 +0 0.0109375 0.009375 0.84242 +0 0.0109375 0.0109375 0.880936 +0.0015625 0 0 0.934812 +0.0015625 0 0.0015625 1.11293 +0.0015625 0 0.003125 0.848425 +0.0015625 0 0.0046875 0.911706 +0.0015625 0 0.00625 1.09936 +0.0015625 0 0.0078125 1.04721 +0.0015625 0 0.009375 1.1174 +0.0015625 0 0.0109375 0.928154 +0.0015625 0.0015625 0 0.864663 +0.0015625 0.0015625 0.0015625 0.917776 +0.0015625 0.0015625 0.003125 0.909057 +0.0015625 0.0015625 0.0046875 1.0033 +0.0015625 0.0015625 0.00625 1.13088 +0.0015625 0.0015625 0.0078125 1.0984 +0.0015625 0.0015625 0.009375 1.0954 +0.0015625 0.0015625 0.0109375 0.980529 +0.0015625 0.003125 0 1.05182 +0.0015625 0.003125 0.0015625 0.80732 +0.0015625 0.003125 0.003125 1.02856 +0.0015625 0.003125 0.0046875 0.99527 +0.0015625 0.003125 0.00625 0.938515 +0.0015625 0.003125 0.0078125 1.20606 +0.0015625 0.003125 0.009375 0.981112 +0.0015625 0.003125 0.0109375 0.991352 +0.0015625 0.0046875 0 0.709635 +0.0015625 0.0046875 0.0015625 1.03751 +0.0015625 0.0046875 0.003125 1.24836 +0.0015625 0.0046875 0.0046875 1.07947 +0.0015625 0.0046875 0.00625 0.988559 +0.0015625 0.0046875 0.0078125 0.825776 +0.0015625 0.0046875 0.009375 1.05345 +0.0015625 0.0046875 0.0109375 1.05725 +0.0015625 0.00625 0 0.969241 +0.0015625 0.00625 0.0015625 0.94037 +0.0015625 0.00625 0.003125 1.03141 +0.0015625 0.00625 0.0046875 1.1857 +0.0015625 0.00625 0.00625 1.10859 +0.0015625 0.00625 0.0078125 0.817732 +0.0015625 0.00625 0.009375 0.890763 +0.0015625 0.00625 0.0109375 1.0562 +0.0015625 0.0078125 0 1.20302 +0.0015625 0.0078125 0.0015625 1.01152 +0.0015625 0.0078125 0.003125 0.755949 +0.0015625 0.0078125 0.0046875 0.8707 +0.0015625 0.0078125 0.00625 0.942563 +0.0015625 0.0078125 0.0078125 0.977883 +0.0015625 0.0078125 0.009375 1.09846 +0.0015625 0.0078125 0.0109375 1.13989 +0.0015625 0.009375 0 1.04413 +0.0015625 0.009375 0.0015625 1.13938 +0.0015625 0.009375 0.003125 1.09161 +0.0015625 0.009375 0.0046875 0.907322 +0.0015625 0.009375 0.00625 0.853534 +0.0015625 0.009375 0.0078125 0.928997 +0.0015625 0.009375 0.009375 1.01072 +0.0015625 0.009375 0.0109375 1.0243 +0.0015625 0.0109375 0 1.22268 +0.0015625 0.0109375 0.0015625 1.03319 +0.0015625 0.0109375 0.003125 1.08664 +0.0015625 0.0109375 0.0046875 1.04653 +0.0015625 0.0109375 0.00625 0.937997 +0.0015625 0.0109375 0.0078125 1.09794 +0.0015625 0.0109375 0.009375 0.752688 +0.0015625 0.0109375 0.0109375 0.822331 +0.003125 0 0 0.975299 +0.003125 0 0.0015625 0.748336 +0.003125 0 0.003125 0.852076 +0.003125 0 0.0046875 1.06625 +0.003125 0 0.00625 1.01129 +0.003125 0 0.0078125 1.11276 +0.003125 0 0.009375 1.16133 +0.003125 0 0.0109375 1.07266 +0.003125 0.0015625 0 0.992599 +0.003125 0.0015625 0.0015625 0.980334 +0.003125 0.0015625 0.003125 0.980116 +0.003125 0.0015625 0.0046875 1.12026 +0.003125 0.0015625 0.00625 1.05558 +0.003125 0.0015625 0.0078125 1.0051 +0.003125 0.0015625 0.009375 0.971705 +0.003125 0.0015625 0.0109375 0.894306 +0.003125 0.003125 0 1.05359 +0.003125 0.003125 0.0015625 1.13062 +0.003125 0.003125 0.003125 1.06763 +0.003125 0.003125 0.0046875 1.07225 +0.003125 0.003125 0.00625 0.952871 +0.003125 0.003125 0.0078125 0.907213 +0.003125 0.003125 0.009375 0.925918 +0.003125 0.003125 0.0109375 0.889917 +0.003125 0.0046875 0 1.01664 +0.003125 0.0046875 0.0015625 1.0248 +0.003125 0.0046875 0.003125 1.2389 +0.003125 0.0046875 0.0046875 0.977245 +0.003125 0.0046875 0.00625 0.868434 +0.003125 0.0046875 0.0078125 0.954973 +0.003125 0.0046875 0.009375 0.876025 +0.003125 0.0046875 0.0109375 1.04298 +0.003125 0.00625 0 1.10454 +0.003125 0.00625 0.0015625 0.846012 +0.003125 0.00625 0.003125 1.03778 +0.003125 0.00625 0.0046875 1.05211 +0.003125 0.00625 0.00625 1.12272 +0.003125 0.00625 0.0078125 1.03775 +0.003125 0.00625 0.009375 0.734954 +0.003125 0.00625 0.0109375 1.06412 +0.003125 0.0078125 0 1.12087 +0.003125 0.0078125 0.0015625 1.123 +0.003125 0.0078125 0.003125 0.83889 +0.003125 0.0078125 0.0046875 0.843408 +0.003125 0.0078125 0.00625 0.991665 +0.003125 0.0078125 0.0078125 0.956153 +0.003125 0.0078125 0.009375 1.04857 +0.003125 0.0078125 0.0109375 1.07744 +0.003125 0.009375 0 0.866572 +0.003125 0.009375 0.0015625 1.27503 +0.003125 0.009375 0.003125 1.04252 +0.003125 0.009375 0.0046875 0.809391 +0.003125 0.009375 0.00625 0.913114 +0.003125 0.009375 0.0078125 0.942272 +0.003125 0.009375 0.009375 1.1778 +0.003125 0.009375 0.0109375 0.973302 +0.003125 0.0109375 0 0.869887 +0.003125 0.0109375 0.0015625 0.871868 +0.003125 0.0109375 0.003125 0.942096 +0.003125 0.0109375 0.0046875 1.05909 +0.003125 0.0109375 0.00625 1.08432 +0.003125 0.0109375 0.0078125 1.08377 +0.003125 0.0109375 0.009375 1.1037 +0.003125 0.0109375 0.0109375 0.985273 +0.0046875 0 0 1.16862 +0.0046875 0 0.0015625 1.00217 +0.0046875 0 0.003125 0.907337 +0.0046875 0 0.0046875 1.04413 +0.0046875 0 0.00625 0.878305 +0.0046875 0 0.0078125 0.910131 +0.0046875 0 0.009375 1.04574 +0.0046875 0 0.0109375 1.04357 +0.0046875 0.0015625 0 1.06472 +0.0046875 0.0015625 0.0015625 0.994162 +0.0046875 0.0015625 0.003125 0.894505 +0.0046875 0.0015625 0.0046875 0.843819 +0.0046875 0.0015625 0.00625 1.06754 +0.0046875 0.0015625 0.0078125 1.17092 +0.0046875 0.0015625 0.009375 0.973242 +0.0046875 0.0015625 0.0109375 0.991101 +0.0046875 0.003125 0 0.779137 +0.0046875 0.003125 0.0015625 1.03093 +0.0046875 0.003125 0.003125 1.14462 +0.0046875 0.003125 0.0046875 1.10922 +0.0046875 0.003125 0.00625 1.19078 +0.0046875 0.003125 0.0078125 0.917208 +0.0046875 0.003125 0.009375 0.885465 +0.0046875 0.003125 0.0109375 0.942639 +0.0046875 0.0046875 0 1.0511 +0.0046875 0.0046875 0.0015625 1.08603 +0.0046875 0.0046875 0.003125 1.17819 +0.0046875 0.0046875 0.0046875 0.922744 +0.0046875 0.0046875 0.00625 0.958514 +0.0046875 0.0046875 0.0078125 1.05495 +0.0046875 0.0046875 0.009375 0.8122 +0.0046875 0.0046875 0.0109375 0.936277 +0.0046875 0.00625 0 1.02958 +0.0046875 0.00625 0.0015625 1.05259 +0.0046875 0.00625 0.003125 1.11193 +0.0046875 0.00625 0.0046875 0.924267 +0.0046875 0.00625 0.00625 0.987028 +0.0046875 0.00625 0.0078125 1.14579 +0.0046875 0.00625 0.009375 0.871464 +0.0046875 0.00625 0.0109375 0.877355 +0.0046875 0.0078125 0 0.964511 +0.0046875 0.0078125 0.0015625 0.914737 +0.0046875 0.0078125 0.003125 0.903316 +0.0046875 0.0078125 0.0046875 1.10736 +0.0046875 0.0078125 0.00625 0.992898 +0.0046875 0.0078125 0.0078125 0.963469 +0.0046875 0.0078125 0.009375 1.13927 +0.0046875 0.0078125 0.0109375 1.01443 +0.0046875 0.009375 0 1.02266 +0.0046875 0.009375 0.0015625 0.914309 +0.0046875 0.009375 0.003125 0.836119 +0.0046875 0.009375 0.0046875 0.922384 +0.0046875 0.009375 0.00625 0.943888 +0.0046875 0.009375 0.0078125 1.02687 +0.0046875 0.009375 0.009375 1.19733 +0.0046875 0.009375 0.0109375 1.13644 +0.0046875 0.0109375 0 0.919677 +0.0046875 0.0109375 0.0015625 1.00507 +0.0046875 0.0109375 0.003125 1.02399 +0.0046875 0.0109375 0.0046875 1.12608 +0.0046875 0.0109375 0.00625 0.981053 +0.0046875 0.0109375 0.0078125 0.810661 +0.0046875 0.0109375 0.009375 1.07528 +0.0046875 0.0109375 0.0109375 1.05819 +0.00625 0 0 1.2446 +0.00625 0 0.0015625 0.837149 +0.00625 0 0.003125 1.02901 +0.00625 0 0.0046875 1.11325 +0.00625 0 0.00625 0.694014 +0.00625 0 0.0078125 0.807318 +0.00625 0 0.009375 1.03237 +0.00625 0 0.0109375 1.24228 +0.00625 0.0015625 0 1.11275 +0.00625 0.0015625 0.0015625 0.918136 +0.00625 0.0015625 0.003125 0.899259 +0.00625 0.0015625 0.0046875 0.985982 +0.00625 0.0015625 0.00625 0.951326 +0.00625 0.0015625 0.0078125 0.855553 +0.00625 0.0015625 0.009375 1.03667 +0.00625 0.0015625 0.0109375 1.24033 +0.00625 0.003125 0 0.794164 +0.00625 0.003125 0.0015625 1.13046 +0.00625 0.003125 0.003125 1.09147 +0.00625 0.003125 0.0046875 0.925413 +0.00625 0.003125 0.00625 1.0337 +0.00625 0.003125 0.0078125 0.935181 +0.00625 0.003125 0.009375 1.08066 +0.00625 0.003125 0.0109375 1.00894 +0.00625 0.0046875 0 0.826367 +0.00625 0.0046875 0.0015625 1.18551 +0.00625 0.0046875 0.003125 1.12277 +0.00625 0.0046875 0.0046875 0.899589 +0.00625 0.0046875 0.00625 1.16428 +0.00625 0.0046875 0.0078125 1.06555 +0.00625 0.0046875 0.009375 0.886579 +0.00625 0.0046875 0.0109375 0.849358 +0.00625 0.00625 0 0.996222 +0.00625 0.00625 0.0015625 1.19409 +0.00625 0.00625 0.003125 0.911857 +0.00625 0.00625 0.0046875 0.898531 +0.00625 0.00625 0.00625 1.17817 +0.00625 0.00625 0.0078125 1.05316 +0.00625 0.00625 0.009375 0.913746 +0.00625 0.00625 0.0109375 0.854213 +0.00625 0.0078125 0 0.960435 +0.00625 0.0078125 0.0015625 0.826739 +0.00625 0.0078125 0.003125 0.972248 +0.00625 0.0078125 0.0046875 1.09324 +0.00625 0.0078125 0.00625 1.03189 +0.00625 0.0078125 0.0078125 1.11283 +0.00625 0.0078125 0.009375 1.03543 +0.00625 0.0078125 0.0109375 0.967184 +0.00625 0.009375 0 0.965016 +0.00625 0.009375 0.0015625 0.838296 +0.00625 0.009375 0.003125 0.967655 +0.00625 0.009375 0.0046875 1.06281 +0.00625 0.009375 0.00625 1.09411 +0.00625 0.009375 0.0078125 1.20434 +0.00625 0.009375 0.009375 0.973215 +0.00625 0.009375 0.0109375 0.89456 +0.00625 0.0109375 0 1.10045 +0.00625 0.0109375 0.0015625 1.06962 +0.00625 0.0109375 0.003125 1.00572 +0.00625 0.0109375 0.0046875 1.02119 +0.00625 0.0109375 0.00625 0.852504 +0.00625 0.0109375 0.0078125 0.966068 +0.00625 0.0109375 0.009375 1.04133 +0.00625 0.0109375 0.0109375 0.943129 +0.0078125 0 0 1.00408 +0.0078125 0 0.0015625 0.916479 +0.0078125 0 0.003125 0.975505 +0.0078125 0 0.0046875 1.11334 +0.0078125 0 0.00625 1.18199 +0.0078125 0 0.0078125 1.00322 +0.0078125 0 0.009375 0.838428 +0.0078125 0 0.0109375 0.966956 +0.0078125 0.0015625 0 0.996474 +0.0078125 0.0015625 0.0015625 0.996871 +0.0078125 0.0015625 0.003125 1.12875 +0.0078125 0.0015625 0.0046875 1.08624 +0.0078125 0.0015625 0.00625 0.884999 +0.0078125 0.0015625 0.0078125 0.707679 +0.0078125 0.0015625 0.009375 0.989775 +0.0078125 0.0015625 0.0109375 1.20921 +0.0078125 0.003125 0 1.0839 +0.0078125 0.003125 0.0015625 1.07957 +0.0078125 0.003125 0.003125 1.01745 +0.0078125 0.003125 0.0046875 0.947032 +0.0078125 0.003125 0.00625 0.814628 +0.0078125 0.003125 0.0078125 0.854222 +0.0078125 0.003125 0.009375 1.08402 +0.0078125 0.003125 0.0109375 1.11917 +0.0078125 0.0046875 0 1.18519 +0.0078125 0.0046875 0.0015625 0.841208 +0.0078125 0.0046875 0.003125 0.791089 +0.0078125 0.0046875 0.0046875 1.15745 +0.0078125 0.0046875 0.00625 0.983334 +0.0078125 0.0046875 0.0078125 1.01718 +0.0078125 0.0046875 0.009375 1.04039 +0.0078125 0.0046875 0.0109375 0.984163 +0.0078125 0.00625 0 0.990763 +0.0078125 0.00625 0.0015625 0.913692 +0.0078125 0.00625 0.003125 0.943505 +0.0078125 0.00625 0.0046875 0.897492 +0.0078125 0.00625 0.00625 0.971705 +0.0078125 0.00625 0.0078125 1.13756 +0.0078125 0.00625 0.009375 1.09403 +0.0078125 0.00625 0.0109375 1.05125 +0.0078125 0.0078125 0 0.866454 +0.0078125 0.0078125 0.0015625 1.05727 +0.0078125 0.0078125 0.003125 1.14439 +0.0078125 0.0078125 0.0046875 0.84297 +0.0078125 0.0078125 0.00625 1.1531 +0.0078125 0.0078125 0.0078125 1.1792 +0.0078125 0.0078125 0.009375 0.83605 +0.0078125 0.0078125 0.0109375 0.92055 +0.0078125 0.009375 0 0.921263 +0.0078125 0.009375 0.0015625 1.09026 +0.0078125 0.009375 0.003125 1.06354 +0.0078125 0.009375 0.0046875 1.04213 +0.0078125 0.009375 0.00625 1.03168 +0.0078125 0.009375 0.0078125 1.00499 +0.0078125 0.009375 0.009375 0.98352 +0.0078125 0.009375 0.0109375 0.862618 +0.0078125 0.0109375 0 0.951882 +0.0078125 0.0109375 0.0015625 1.10465 +0.0078125 0.0109375 0.003125 0.935764 +0.0078125 0.0109375 0.0046875 0.913341 +0.0078125 0.0109375 0.00625 0.978566 +0.0078125 0.0109375 0.0078125 1.09594 +0.0078125 0.0109375 0.009375 1.13379 +0.0078125 0.0109375 0.0109375 0.886076 +0.009375 0 0 0.763732 +0.009375 0 0.0015625 1.11576 +0.009375 0 0.003125 1.17213 +0.009375 0 0.0046875 1.03234 +0.009375 0 0.00625 1.17767 +0.009375 0 0.0078125 1.05497 +0.009375 0 0.009375 0.886467 +0.009375 0 0.0109375 0.796936 +0.009375 0.0015625 0 0.832745 +0.009375 0.0015625 0.0015625 1.01771 +0.009375 0.0015625 0.003125 1.14194 +0.009375 0.0015625 0.0046875 0.995205 +0.009375 0.0015625 0.00625 1.16411 +0.009375 0.0015625 0.0078125 1.12122 +0.009375 0.0015625 0.009375 0.861206 +0.009375 0.0015625 0.0109375 0.86587 +0.009375 0.003125 0 1.14752 +0.009375 0.003125 0.0015625 0.7835 +0.009375 0.003125 0.003125 0.819045 +0.009375 0.003125 0.0046875 0.935056 +0.009375 0.003125 0.00625 0.876812 +0.009375 0.003125 0.0078125 1.20477 +0.009375 0.003125 0.009375 1.15662 +0.009375 0.003125 0.0109375 1.07667 +0.009375 0.0046875 0 1.06388 +0.009375 0.0046875 0.0015625 0.787567 +0.009375 0.0046875 0.003125 0.867257 +0.009375 0.0046875 0.0046875 1.21827 +0.009375 0.0046875 0.00625 0.906651 +0.009375 0.0046875 0.0078125 1.03079 +0.009375 0.0046875 0.009375 1.16221 +0.009375 0.0046875 0.0109375 0.963372 +0.009375 0.00625 0 0.93568 +0.009375 0.00625 0.0015625 1.05016 +0.009375 0.00625 0.003125 1.0148 +0.009375 0.00625 0.0046875 0.939891 +0.009375 0.00625 0.00625 0.893401 +0.009375 0.00625 0.0078125 0.946711 +0.009375 0.00625 0.009375 1.15612 +0.009375 0.00625 0.0109375 1.06324 +0.009375 0.0078125 0 1.06171 +0.009375 0.0078125 0.0015625 1.20932 +0.009375 0.0078125 0.003125 1.02262 +0.009375 0.0078125 0.0046875 0.857718 +0.009375 0.0078125 0.00625 0.951651 +0.009375 0.0078125 0.0078125 0.952868 +0.009375 0.0078125 0.009375 0.964024 +0.009375 0.0078125 0.0109375 0.980096 +0.009375 0.009375 0 1.15307 +0.009375 0.009375 0.0015625 1.05059 +0.009375 0.009375 0.003125 0.994028 +0.009375 0.009375 0.0046875 1.09271 +0.009375 0.009375 0.00625 1.05211 +0.009375 0.009375 0.0078125 0.793551 +0.009375 0.009375 0.009375 0.800791 +0.009375 0.009375 0.0109375 1.06315 +0.009375 0.0109375 0 1.04167 +0.009375 0.0109375 0.0015625 0.985406 +0.009375 0.0109375 0.003125 0.968186 +0.009375 0.0109375 0.0046875 0.928809 +0.009375 0.0109375 0.00625 0.977588 +0.009375 0.0109375 0.0078125 0.895123 +0.009375 0.0109375 0.009375 1.01256 +0.009375 0.0109375 0.0109375 1.19066 +0.0109375 0 0 0.892489 +0.0109375 0 0.0015625 0.96842 +0.0109375 0 0.003125 1.26873 +0.0109375 0 0.0046875 0.930825 +0.0109375 0 0.00625 0.840347 +0.0109375 0 0.0078125 1.03943 +0.0109375 0 0.009375 0.998431 +0.0109375 0 0.0109375 1.06132 +0.0109375 0.0015625 0 1.07415 +0.0109375 0.0015625 0.0015625 1.09119 +0.0109375 0.0015625 0.003125 1.06769 +0.0109375 0.0015625 0.0046875 1.06665 +0.0109375 0.0015625 0.00625 0.916586 +0.0109375 0.0015625 0.0078125 1.023 +0.0109375 0.0015625 0.009375 0.941583 +0.0109375 0.0015625 0.0109375 0.81916 +0.0109375 0.003125 0 1.08515 +0.0109375 0.003125 0.0015625 1.08218 +0.0109375 0.003125 0.003125 0.809373 +0.0109375 0.003125 0.0046875 0.948476 +0.0109375 0.003125 0.00625 1.05608 +0.0109375 0.003125 0.0078125 1.02251 +0.0109375 0.003125 0.009375 1.0494 +0.0109375 0.003125 0.0109375 0.946837 +0.0109375 0.0046875 0 1.05408 +0.0109375 0.0046875 0.0015625 1.03526 +0.0109375 0.0046875 0.003125 0.782363 +0.0109375 0.0046875 0.0046875 0.840335 +0.0109375 0.0046875 0.00625 1.06959 +0.0109375 0.0046875 0.0078125 1.10209 +0.0109375 0.0046875 0.009375 1.09397 +0.0109375 0.0046875 0.0109375 1.02231 +0.0109375 0.00625 0 1.01041 +0.0109375 0.00625 0.0015625 1.09335 +0.0109375 0.00625 0.003125 0.913164 +0.0109375 0.00625 0.0046875 0.992539 +0.0109375 0.00625 0.00625 0.932676 +0.0109375 0.00625 0.0078125 0.898913 +0.0109375 0.00625 0.009375 1.14375 +0.0109375 0.00625 0.0109375 1.0152 +0.0109375 0.0078125 0 0.966011 +0.0109375 0.0078125 0.0015625 1.01647 +0.0109375 0.0078125 0.003125 1.19634 +0.0109375 0.0078125 0.0046875 1.17897 +0.0109375 0.0078125 0.00625 0.911438 +0.0109375 0.0078125 0.0078125 0.879444 +0.0109375 0.0078125 0.009375 0.926211 +0.0109375 0.0078125 0.0109375 0.925121 +0.0109375 0.009375 0 1.01195 +0.0109375 0.009375 0.0015625 0.856053 +0.0109375 0.009375 0.003125 1.00873 +0.0109375 0.009375 0.0046875 1.12816 +0.0109375 0.009375 0.00625 1.1709 +0.0109375 0.009375 0.0078125 1.03914 +0.0109375 0.009375 0.009375 0.808425 +0.0109375 0.009375 0.0109375 0.976645 +0.0109375 0.0109375 0 0.905764 +0.0109375 0.0109375 0.0015625 0.857085 +0.0109375 0.0109375 0.003125 0.953612 +0.0109375 0.0109375 0.0046875 0.914049 +0.0109375 0.0109375 0.00625 1.10238 +0.0109375 0.0109375 0.0078125 0.995461 +0.0109375 0.0109375 0.009375 1.03824 +0.0109375 0.0109375 0.0109375 1.2334 diff --git a/tests/sm/latticeplastdam3drandom.in b/tests/sm/latticeplastdam3drandom.in new file mode 100644 index 000000000..2d432cb5d --- /dev/null +++ b/tests/sm/latticeplastdam3drandom.in @@ -0,0 +1,22 @@ +latticeplastdam3drandom.out +Direct tension. 3D Plastic Damage Lattice Model with random field +StaticStructural nsteps 1 rtolv 1.e-6 ddm 2 2 1 ddv 1 1.e-4 ddltf 2 nmodules 1 +errorcheck +domain 3dLattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 3 +node 1 coords 3 0.0 0.0 0.0 bc 6 1 1 1 1 1 1 +node 2 coords 3 0.001 0.0 0.0 bc 6 0 0 1 1 1 1 +lattice3D 1 nodes 2 1 2 crossSect 1 mat 1 polycoords 12 0.0005 -0.0495 -0.0495 0.0005 0.0505 -0.0495 0.0005 0.0505 0.0505 0.0005 -0.0495 0.0505 +latticecs 1 material 1 +latticeplastdam 1 d 0 talpha 0. e 40.e9 a1 0.175 a2 1. ft 6.5e6 fc 130.e6 angle1 0.5 angle2 0.5 flow 0.25 wf 1.53e-5 ahard 1.e-3 iter 100 tol 1.e-6 randvars 2 806 807 randgen 2 3 3 +#latticeplastdam 1 d 0 talpha 0. e 30.e9 e0 100.e-6 wf 100.e-4 randvars 2 800 randgen 2 3 3 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 t 1 1. f(t) 1 0.1 +InterpolatingFunction 3 name latticeplastdam3drandom.dat dim 3 +# +#%BEGIN_CHECK% tolerance 1.e-3 +#REACTION tStep 1 number 1 dof 1 value -3.57249608e+04 +#%END_CHECK% + diff --git a/tests/sm/latticeplastdamvisco3drandom.dat b/tests/sm/latticeplastdamvisco3drandom.dat new file mode 100644 index 000000000..4f4348b38 --- /dev/null +++ b/tests/sm/latticeplastdamvisco3drandom.dat @@ -0,0 +1,513 @@ +8 8 8 0.555556 0.555556 0.555556 +0 0 0 1.04757 +0 0 25 1.09919 +0 0 50 0.916212 +0 0 75 0.974669 +0 0 100 1.08411 +0 0 125 0.983772 +0 0 150 0.952107 +0 0 175 0.942369 +0 25 0 0.901045 +0 25 25 0.985663 +0 25 50 1.01856 +0 25 75 1.06015 +0 25 100 1.07713 +0 25 125 1.0083 +0 25 150 1.00327 +0 25 175 0.945887 +0 50 0 0.837221 +0 50 25 1.03743 +0 50 50 1.14722 +0 50 75 0.985226 +0 50 100 0.896707 +0 50 125 0.92747 +0 50 150 1.11885 +0 50 175 1.04988 +0 75 0 0.931057 +0 75 25 1.073 +0 75 50 0.981459 +0 75 75 0.893404 +0 75 100 1.04504 +0 75 125 1.04593 +0 75 150 1.04244 +0 75 175 0.987669 +0 100 0 0.957794 +0 100 25 0.947016 +0 100 50 1.03026 +0 100 75 1.06512 +0 100 100 1.03368 +0 100 125 0.9912 +0 100 150 0.97827 +0 100 175 0.996667 +0 125 0 1.0766 +0 125 25 0.907906 +0 125 50 0.978433 +0 125 75 1.04774 +0 125 100 0.850761 +0 125 125 0.990914 +0 125 150 1.09421 +0 125 175 1.05344 +0 150 0 1.15741 +0 150 25 0.916367 +0 150 50 0.906306 +0 150 75 0.974988 +0 150 100 0.985511 +0 150 125 1.09756 +0 150 150 0.950772 +0 150 175 1.01109 +0 175 0 1.0913 +0 175 25 1.03344 +0 175 50 1.02155 +0 175 75 0.998707 +0 175 100 1.02707 +0 175 125 0.954851 +0 175 150 0.860084 +0 175 175 1.01301 +25 0 0 0.988658 +25 0 25 0.948392 +25 0 50 0.835625 +25 0 75 0.94684 +25 0 100 1.01716 +25 0 125 1.03393 +25 0 150 1.15855 +25 0 175 1.07084 +25 25 0 0.976902 +25 25 25 0.936039 +25 25 50 1.02359 +25 25 75 0.976596 +25 25 100 0.964973 +25 25 125 1.01266 +25 25 150 1.03454 +25 25 175 1.07471 +25 50 0 0.906632 +25 50 25 1.0812 +25 50 50 1.09756 +25 50 75 1.10963 +25 50 100 1.09664 +25 50 125 0.858345 +25 50 150 0.899164 +25 50 175 0.950832 +25 75 0 0.976167 +25 75 25 1.15725 +25 75 50 0.933192 +25 75 75 0.932493 +25 75 100 1.04699 +25 75 125 1.13445 +25 75 150 1.04365 +25 75 175 0.775809 +25 100 0 0.979107 +25 100 25 1.02864 +25 100 50 1.07752 +25 100 75 0.849563 +25 100 100 0.999964 +25 100 125 1.0353 +25 100 150 0.943411 +25 100 175 1.0865 +25 125 0 1.06614 +25 125 25 0.94838 +25 125 50 1.05405 +25 125 75 0.898079 +25 125 100 0.947561 +25 125 125 0.973541 +25 125 150 0.932248 +25 125 175 1.18 +25 150 0 1.1256 +25 150 25 0.941778 +25 150 50 0.989293 +25 150 75 1.09397 +25 150 100 0.886233 +25 150 125 1.07243 +25 150 150 0.998871 +25 150 175 0.891824 +25 175 0 0.980795 +25 175 25 0.958329 +25 175 50 0.989165 +25 175 75 1.19283 +25 175 100 1.04048 +25 175 125 0.879356 +25 175 150 0.989562 +25 175 175 0.969483 +50 0 0 0.922904 +50 0 25 1.12043 +50 0 50 1.0302 +50 0 75 0.955998 +50 0 100 1.12774 +50 0 125 1.01674 +50 0 150 0.919155 +50 0 175 0.906837 +50 25 0 1.08045 +50 25 25 0.993279 +50 25 50 1.0746 +50 25 75 1.01113 +50 25 100 0.901879 +50 25 125 0.89094 +50 25 150 0.94307 +50 25 175 1.10465 +50 50 0 1.02994 +50 50 25 0.866018 +50 50 50 0.850884 +50 50 75 1.09594 +50 50 100 1.04605 +50 50 125 1.04731 +50 50 150 1.07312 +50 50 175 0.990736 +50 75 0 1.02711 +50 75 25 1.02592 +50 75 50 0.931961 +50 75 75 0.968181 +50 75 100 0.96008 +50 75 125 1.06161 +50 75 150 1.08085 +50 75 175 0.944292 +50 100 0 1.02742 +50 100 25 0.989233 +50 100 50 1.03495 +50 100 75 0.931628 +50 100 100 0.855903 +50 100 125 1.11004 +50 100 150 1.08172 +50 100 175 0.9691 +50 125 0 1.03034 +50 125 25 0.964296 +50 125 50 0.962996 +50 125 75 1.00271 +50 125 100 0.930263 +50 125 125 1.0583 +50 125 150 1.0764 +50 125 175 0.974697 +50 150 0 1.01973 +50 150 25 1.02432 +50 150 50 1.08397 +50 150 75 1.01644 +50 150 100 0.970301 +50 150 125 0.825914 +50 150 150 0.925997 +50 150 175 1.13333 +50 175 0 0.862103 +50 175 25 1.01651 +50 175 50 1.03044 +50 175 75 1.01798 +50 175 100 1.20778 +50 175 125 0.989152 +50 175 150 0.899678 +50 175 175 0.976357 +75 0 0 0.942927 +75 0 25 1.0296 +75 0 50 1.03376 +75 0 75 1.00429 +75 0 100 1.08841 +75 0 125 0.989717 +75 0 150 0.934909 +75 0 175 0.976393 +75 25 0 1.05069 +75 25 25 0.91476 +75 25 50 0.969355 +75 25 75 1.02374 +75 25 100 0.9657 +75 25 125 1.04702 +75 25 150 1.01425 +75 25 175 1.01448 +75 50 0 1.01819 +75 50 25 1.00113 +75 50 50 0.908964 +75 50 75 0.89172 +75 50 100 0.898644 +75 50 125 1.09129 +75 50 150 1.1742 +75 50 175 1.01587 +75 75 0 0.964351 +75 75 25 0.993159 +75 75 50 0.992319 +75 75 75 0.921414 +75 75 100 1.02243 +75 75 125 1.00013 +75 75 150 1.0209 +75 75 175 1.0853 +75 100 0 1.03456 +75 100 25 1.00784 +75 100 50 0.899245 +75 100 75 1.10502 +75 100 100 1.01865 +75 100 125 1.00695 +75 100 150 1.04754 +75 100 175 0.880186 +75 125 0 0.962738 +75 125 25 0.973898 +75 125 50 1.05805 +75 125 75 1.13426 +75 125 100 1.05364 +75 125 125 1.01912 +75 125 150 0.925581 +75 125 175 0.872723 +75 150 0 1.00432 +75 150 25 0.96144 +75 150 50 1.15803 +75 150 75 0.998965 +75 150 100 0.994296 +75 150 125 0.912041 +75 150 150 0.843352 +75 150 175 1.12755 +75 175 0 1.02222 +75 175 25 1.11818 +75 175 50 0.980281 +75 175 75 0.920585 +75 175 100 0.958232 +75 175 125 0.933728 +75 175 150 1.03927 +75 175 175 1.0275 +100 0 0 1.01887 +100 0 25 0.846681 +100 0 50 1.0095 +100 0 75 1.12246 +100 0 100 0.897355 +100 0 125 0.944134 +100 0 150 1.07428 +100 0 175 1.08673 +100 25 0 1.08262 +100 25 25 1.06378 +100 25 50 1.07051 +100 25 75 0.920693 +100 25 100 0.872081 +100 25 125 1.10935 +100 25 150 0.974794 +100 25 175 0.906187 +100 50 0 0.973374 +100 50 25 1.08474 +100 50 50 1.01457 +100 50 75 0.911744 +100 50 100 1.06937 +100 50 125 0.956977 +100 50 150 0.942687 +100 50 175 1.04654 +100 75 0 0.941548 +100 75 25 0.995049 +100 75 50 1.01568 +100 75 75 0.987321 +100 75 100 0.986539 +100 75 125 0.925489 +100 75 150 1.05623 +100 75 175 1.09214 +100 100 0 0.953307 +100 100 25 0.912816 +100 100 50 0.969104 +100 100 75 1.06089 +100 100 100 1.04973 +100 100 125 1.02732 +100 100 150 1.02786 +100 100 175 0.998975 +100 125 0 0.875305 +100 125 25 1.04457 +100 125 50 0.988522 +100 125 75 1.05582 +100 125 100 1.21316 +100 125 125 0.994225 +100 125 150 0.923014 +100 125 175 0.90538 +100 150 0 1.05445 +100 150 25 1.15577 +100 150 50 1.00683 +100 150 75 0.904908 +100 150 100 0.983544 +100 150 125 1.07157 +100 150 150 0.955176 +100 150 175 0.867753 +100 175 0 1.10053 +100 175 25 0.896603 +100 175 50 0.925287 +100 175 75 1.03617 +100 175 100 0.928221 +100 175 125 0.97094 +100 175 150 1.04596 +100 175 175 1.09629 +125 0 0 1.03862 +125 0 25 1.00947 +125 0 50 1.07981 +125 0 75 0.996209 +125 0 100 0.940909 +125 0 125 0.956653 +125 0 150 0.94066 +125 0 175 1.03767 +125 25 0 0.943135 +125 25 25 1.1593 +125 25 50 1.10695 +125 25 75 1.02523 +125 25 100 1.01551 +125 25 125 0.872861 +125 25 150 0.9344 +125 25 175 0.94261 +125 50 0 1.0296 +125 50 25 0.922191 +125 50 50 1.06368 +125 50 75 1.07965 +125 50 100 0.95299 +125 50 125 1.05849 +125 50 150 0.953729 +125 50 175 0.939668 +125 75 0 1.07221 +125 75 25 0.867785 +125 75 50 0.928472 +125 75 75 1.09968 +125 75 100 0.98833 +125 75 125 0.926594 +125 75 150 1.01098 +125 75 175 1.10594 +125 100 0 0.925916 +125 100 25 1.06182 +125 100 50 1.04757 +125 100 75 1.01977 +125 100 100 1.02724 +125 100 125 0.949716 +125 100 150 0.99928 +125 100 175 0.96869 +125 125 0 0.949486 +125 125 25 1.01516 +125 125 50 0.960737 +125 125 75 0.980114 +125 125 100 0.977469 +125 125 125 1.02773 +125 125 150 1.11231 +125 125 175 0.977003 +125 150 0 1.00587 +125 150 25 1.00652 +125 150 50 0.808938 +125 150 75 0.904369 +125 150 100 1.07886 +125 150 125 1.03514 +125 150 150 1.10633 +125 150 175 1.05397 +125 175 0 1.03516 +125 175 25 0.957759 +125 175 50 1.00384 +125 175 75 0.894976 +125 175 100 1.01869 +125 175 125 1.17282 +125 175 150 0.942307 +125 175 175 0.974448 +150 0 0 1.01066 +150 0 25 0.933702 +150 0 50 1.04409 +150 0 75 0.946878 +150 0 100 0.890794 +150 0 125 1.05536 +150 0 150 1.05446 +150 0 175 1.06407 +150 25 0 0.93589 +150 25 25 0.957282 +150 25 50 0.83633 +150 25 75 1.00803 +150 25 100 1.14891 +150 25 125 0.991411 +150 25 150 1.07887 +150 25 175 1.04327 +150 50 0 1.15947 +150 50 25 1.01182 +150 50 50 0.987326 +150 50 75 1.00709 +150 50 100 0.98787 +150 50 125 1.06825 +150 50 150 0.865338 +150 50 175 0.912844 +150 75 0 1.10029 +150 75 25 0.906039 +150 75 50 1.0709 +150 75 75 1.15109 +150 75 100 1.00834 +150 75 125 0.966969 +150 75 150 0.820479 +150 75 175 0.975898 +150 100 0 1.06148 +150 100 25 1.15093 +150 100 50 0.965685 +150 100 75 0.942362 +150 100 100 1.06069 +150 100 125 0.871445 +150 100 150 0.912147 +150 100 175 1.03526 +150 125 0 1.01776 +150 125 25 1.08323 +150 125 50 1.07005 +150 125 75 0.893726 +150 125 100 1.00582 +150 125 125 0.956564 +150 125 150 0.906375 +150 125 175 1.06649 +150 150 0 0.7684 +150 150 25 0.903546 +150 150 50 1.0029 +150 150 75 1.10367 +150 150 100 1.06064 +150 150 125 1.00495 +150 150 150 1.16806 +150 150 175 0.987832 +150 175 0 0.946065 +150 175 25 1.05345 +150 175 50 1.02272 +150 175 75 0.947145 +150 175 100 0.836935 +150 175 125 1.08506 +150 175 150 1.19428 +150 175 175 0.914344 +175 0 0 1.0298 +175 0 25 1.01255 +175 0 50 1.0508 +175 0 75 1.05266 +175 0 100 0.953522 +175 0 125 1.0197 +175 0 150 0.965877 +175 0 175 0.915093 +175 25 0 1.02927 +175 25 25 0.9899 +175 25 50 0.900103 +175 25 75 0.974435 +175 25 100 1.05382 +175 25 125 1.06746 +175 25 150 1.01681 +175 25 175 0.968207 +175 50 0 1.04558 +175 50 25 0.995488 +175 50 50 0.929792 +175 50 75 0.918999 +175 50 100 1.05173 +175 50 125 0.991879 +175 50 150 0.972904 +175 50 175 1.09363 +175 75 0 0.987268 +175 75 25 0.981804 +175 75 50 1.14602 +175 75 75 1.04641 +175 75 100 0.94225 +175 75 125 0.938831 +175 75 150 0.924465 +175 75 175 1.03295 +175 100 0 1.06041 +175 100 25 0.901701 +175 100 50 0.97567 +175 100 75 1.02565 +175 100 100 0.954144 +175 100 125 1.00803 +175 100 150 1.00977 +175 100 175 1.06462 +175 125 0 1.02164 +175 125 25 1.06257 +175 125 50 0.927163 +175 125 75 0.987547 +175 125 100 1.02133 +175 125 125 0.979612 +175 125 150 1.02986 +175 125 175 0.970274 +175 150 0 0.864209 +175 150 25 1.09027 +175 150 50 1.04374 +175 150 75 1.0027 +175 150 100 1.04061 +175 150 125 0.980387 +175 150 150 1.05145 +175 150 175 0.926651 +175 175 0 0.961821 +175 175 25 0.965729 +175 175 50 1.02672 +175 175 75 0.991606 +175 175 100 0.982599 +175 175 125 1.0141 +175 175 150 1.02886 +175 175 175 1.02857 diff --git a/tests/sm/latticeplastdamvisco3drandom.in b/tests/sm/latticeplastdamvisco3drandom.in new file mode 100644 index 000000000..14f0c2661 --- /dev/null +++ b/tests/sm/latticeplastdamvisco3drandom.in @@ -0,0 +1,45 @@ +latticeplastdamvisco3drandom.out +Single element loaded in uniaxial tension. Nonuniform loading rate, damage initiation, partial relaxation, damage growth, end of loading, stress relaxation. MPS model used for viscoelasticity, basic creep only, no shrinkage. With random material parameters +nonlinearstatic nsteps 25 rtolv 1.e-8 MaxIter 5000 controllmode 1 stiffMode 1 renumber 1 updateelasticstiffnessflag manrmsteps 5 deltatfunction 4 nmodules 1 +errorcheck +# +domain 2dlattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 2 nbc 3 nic 0 nltf 5 nset 3 +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 100 0.0 0.0 +# +Lattice2D 1 nodes 2 1 2 crossSect 1 mat 2 gpCoords 2 50 0. width 1000.0 thick 1000.0 +# +latticecs 1 material 2 +# +mps 1 d 0. lattice a1 1. a2 1. talpha 0. referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1000. relMatAge 28. CoupledAnalysisType 0 +latticeplasticitydamageviscoelastic 2 d 0 talpha 0. viscomat 1 e 20.e3 a1 1. a2 1. ft 3. fc 30. angle1 0.5 angle2 0.5 flow 0.25 wf 50.e-3 ahard 1.e-3 iter 100 tol 1.e-6 timefactor 1. randvars 2 806 807 randgen 2 5 5 +# +BoundaryCondition 1 loadTimeFunction 1 dofs 2 2 6 values 2 0. 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0. set 2 +BoundaryCondition 3 loadTimeFunction 3 dofs 1 1 values 1 1. set 3 +# +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 1.0 +PiecewiseLinFunction 3 nPoints 4 t 4 0. 0.1 100. 1.e4 f(t) 4 0. 0.015 0.03 0.03 +PiecewiseLinfunction 4 npoints 25 t 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 f(t) 25 0.0001 0.0002 0.0003 0.0005 0.001 0.003 0.005 0.01 0.03 0.05 0.1 0.3 0.5 1 3 5 10 30 50 100 300 500 1000 3000 5000 +InterpolatingFunction 5 name latticeplastdamvisco3drandom.dat dim 3 +# +Set 1 nodes 2 1 2 +Set 2 nodes 1 1 +Set 3 nodes 1 2 +# +#TIME +#ELEMENT number 1 gp 1 keyword "latticestrain" component 1 +#ELEMENT number 1 gp 1 keyword "latticestress" component 1 +# +#%BEGIN_CHECK% +#ELEMENT tStep 10 number 1 gp 1 keyword 139 component 1 value 2.53647629e+00 tolerance 1.e-6 +#ELEMENT tStep 13 number 1 gp 1 keyword 139 component 1 value 2.32538054e+00 tolerance 1.e-6 +#ELEMENT tStep 16 number 1 gp 1 keyword 139 component 1 value 2.34832514e+00 tolerance 1.e-6 +#ELEMENT tStep 19 number 1 gp 1 keyword 139 component 1 value 1.97660943e+00 tolerance 1.e-6 +#ELEMENT tStep 22 number 1 gp 1 keyword 139 component 1 value 1.57507356e+00 tolerance 1.e-6 +#ELEMENT tStep 25 number 1 gp 1 keyword 139 component 1 value 1.22398865e+00 tolerance 1.e-6 +#%END_CHECK% diff --git a/tests/sm/latticeplastdamvisco_mps_1.in b/tests/sm/latticeplastdamvisco_mps_1.in new file mode 100644 index 000000000..a0efb4561 --- /dev/null +++ b/tests/sm/latticeplastdamvisco_mps_1.in @@ -0,0 +1,44 @@ +latticeplastdamvisco_mps_1.out +Single element loaded in uniaxial tension. Nonuniform loading rate, damage initiation, partial relaxation, damage growth, end of loading, stress relaxation. MPS model used for viscoelasticity, basic creep only, no shrinkage. +nonlinearstatic nsteps 25 rtolv 1.e-8 MaxIter 5000 controllmode 1 stiffMode 1 renumber 1 updateelasticstiffnessflag manrmsteps 5 deltatfunction 4 nmodules 1 +errorcheck +# +domain 2dlattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 2 nbc 3 nic 0 nltf 4 nset 3 +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 100 0.0 0.0 +# +Lattice2D 1 nodes 2 1 2 crossSect 1 mat 2 gpCoords 2 50 0. width 1000.0 thick 1000.0 +# +latticecs 1 material 2 +# +mps 1 d 0. lattice a1 1. a2 1. talpha 0. referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1000. relMatAge 28. CoupledAnalysisType 0 +latticeplasticitydamageviscoelastic 2 d 0 talpha 0. viscomat 1 e 20.e3 a1 1. a2 1. ft 3. fc 30. angle1 0.5 angle2 0.5 flow 0.25 wf 50.e-3 ahard 1.e-3 iter 100 tol 1.e-6 timefactor 1. +# +BoundaryCondition 1 loadTimeFunction 1 dofs 2 2 6 values 2 0. 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0. set 2 +BoundaryCondition 3 loadTimeFunction 3 dofs 1 1 values 1 1. set 3 +# +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 1.0 +PiecewiseLinFunction 3 nPoints 3 t 4 0. 0.1 100. 1.e4 f(t) 4 0. 0.015 0.03 0.03 +PiecewiseLinfunction 4 npoints 25 t 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 f(t) 25 0.0001 0.0002 0.0003 0.0005 0.001 0.003 0.005 0.01 0.03 0.05 0.1 0.3 0.5 1 3 5 10 30 50 100 300 500 1000 3000 5000 +# +Set 1 nodes 2 1 2 +Set 2 nodes 1 1 +Set 3 nodes 1 2 +# +#TIME +#ELEMENT number 1 gp 1 keyword "latticestrain" component 1 +#ELEMENT number 1 gp 1 keyword "latticestress" component 1 +# +#%BEGIN_CHECK% +#ELEMENT tStep 10 number 1 gp 1 keyword 139 component 1 value 2.80973642e+00 tolerance 1.e-6 +#ELEMENT tStep 13 number 1 gp 1 keyword 139 component 1 value 2.55894185e+00 tolerance 1.e-6 +#ELEMENT tStep 16 number 1 gp 1 keyword 139 component 1 value 2.55834671e+00 tolerance 1.e-6 +#ELEMENT tStep 19 number 1 gp 1 keyword 139 component 1 value 2.20367783e+00 tolerance 1.e-6 +#ELEMENT tStep 22 number 1 gp 1 keyword 139 component 1 value 1.73687255e+00 tolerance 1.e-6 +#ELEMENT tStep 25 number 1 gp 1 keyword 139 component 1 value 1.33234290e+00 tolerance 1.e-6 +#%END_CHECK% \ No newline at end of file diff --git a/tests/sm/latticeplastdamvisco_mps_2.in b/tests/sm/latticeplastdamvisco_mps_2.in new file mode 100644 index 000000000..98b6d8f1f --- /dev/null +++ b/tests/sm/latticeplastdamvisco_mps_2.in @@ -0,0 +1,44 @@ +latticeplastdamvisco_mps_2.out +Single element loaded in uniaxial tension. Nonuniform loading rate, damage initiation, partial relaxation, damage growth, end of loading, stress relaxation. MPS model used for viscoelasticity, basic creep only, no shrinkage, with strength aging. +nonlinearstatic nsteps 25 rtolv 1.e-8 MaxIter 5000 controllmode 1 stiffMode 1 renumber 1 updateelasticstiffnessflag manrmsteps 5 deltatfunction 4 nmodules 1 +errorcheck +# +domain 2dlattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 2 nbc 3 nic 0 nltf 4 nset 3 +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 100 0.0 0.0 +# +Lattice2D 1 nodes 2 1 2 crossSect 1 mat 2 gpCoords 2 50 0. width 1000.0 thick 1000.0 +# +latticecs 1 material 2 +# +mps 1 d 0. lattice a1 1. a2 1. talpha 0. referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1000. relMatAge 28. CoupledAnalysisType 0 +latticeplasticitydamageviscoelastic 2 d 0 talpha 0. viscomat 1 e 20.e3 a1 1. a2 1. ft 3. fc 30. angle1 0.5 angle2 0.5 flow 0.25 wf 50.e-3 ahard 1.e-3 iter 100 tol 1.e-6 timefactor 1. timedepfracturing fcm28 30 fib_s 0.25 stiffnessfactor 1.e6 +# +BoundaryCondition 1 loadTimeFunction 1 dofs 2 2 6 values 2 0. 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0. set 2 +BoundaryCondition 3 loadTimeFunction 3 dofs 1 1 values 1 1. set 3 +# +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 1.0 +PiecewiseLinFunction 3 nPoints 3 t 4 0. 0.1 100. 1.e4 f(t) 4 0. 0.015 0.03 0.03 +PiecewiseLinfunction 4 npoints 25 t 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 f(t) 25 0.0001 0.0002 0.0003 0.0005 0.001 0.003 0.005 0.01 0.03 0.05 0.1 0.3 0.5 1 3 5 10 30 50 100 300 500 1000 3000 5000 +# +Set 1 nodes 2 1 2 +Set 2 nodes 1 1 +Set 3 nodes 1 2 +# +#TIME +#ELEMENT number 1 gp 1 keyword "latticestrain" component 1 +#ELEMENT number 1 gp 1 keyword "latticestress" component 1 +# +#%BEGIN_CHECK% +#ELEMENT tStep 10 number 1 gp 1 keyword 139 component 1 value 2.81084091e+00 tolerance 1.e-6 +#ELEMENT tStep 13 number 1 gp 1 keyword 139 component 1 value 2.55988215e+00 tolerance 1.e-6 +#ELEMENT tStep 16 number 1 gp 1 keyword 139 component 1 value 2.55918983e+00 tolerance 1.e-6 +#ELEMENT tStep 19 number 1 gp 1 keyword 139 component 1 value 2.52745758e+00 tolerance 1.e-6 +#ELEMENT tStep 22 number 1 gp 1 keyword 139 component 1 value 1.96393906e+00 tolerance 1.e-6 +#ELEMENT tStep 25 number 1 gp 1 keyword 139 component 1 value 1.48417766e+00 tolerance 1.e-6 +#%END_CHECK% \ No newline at end of file diff --git a/tests/sm/latticeplastdamvisco_mps_3.in b/tests/sm/latticeplastdamvisco_mps_3.in new file mode 100644 index 000000000..ad1ac9f29 --- /dev/null +++ b/tests/sm/latticeplastdamvisco_mps_3.in @@ -0,0 +1,44 @@ +latticeplastdamvisco_mps_3.out +Single element loaded in uniaxial tension. Nonuniform loading rate, damage initiation, partial relaxation, damage growth, end of loading, stress relaxation. MPS model used for viscoelasticity, basic creep only, no shrinkage. Check of deletion. +nonlinearstatic nsteps 25 rtolv 1.e-8 MaxIter 5000 controllmode 1 stiffMode 1 renumber 1 updateelasticstiffnessflag manrmsteps 5 deltatfunction 4 nmodules 1 +errorcheck +# +domain 2dlattice +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 2 nbc 3 nic 0 nltf 4 nset 3 +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 100 0.0 0.0 +# +Lattice2D 1 nodes 2 1 2 crossSect 1 mat 2 gpCoords 2 50 0. width 1000.0 thick 1000.0 +# +latticecs 1 material 2 +# +mps 1 d 0. lattice a1 1. a2 1. talpha 0. referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1000. relMatAge 28. CoupledAnalysisType 0 +latticeplasticitydamageviscoelastic 2 d 0 talpha 0. viscomat 1 e 20.e3 a1 1. a2 1. ft 3. fc 30. angle1 0.5 angle2 0.5 flow 0.25 wf 50.e-3 ahard 1.e-3 iter 100 tol 1.e-180 timefactor 1. +# +BoundaryCondition 1 loadTimeFunction 1 dofs 2 2 6 values 2 0. 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0. set 2 +BoundaryCondition 3 loadTimeFunction 3 dofs 1 1 values 1 1. set 3 +# +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 1.0 +PiecewiseLinFunction 3 nPoints 3 t 4 0. 0.1 100. 1.e4 f(t) 4 0. 0.015 0.03 0.03 +PiecewiseLinfunction 4 npoints 25 t 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 f(t) 25 0.0001 0.0002 0.0003 0.0005 0.001 0.003 0.005 0.01 0.03 0.05 0.1 0.3 0.5 1 3 5 10 30 50 100 300 500 1000 3000 5000 +# +Set 1 nodes 2 1 2 +Set 2 nodes 1 1 +Set 3 nodes 1 2 +# +#TIME +#ELEMENT number 1 gp 1 keyword "latticestrain" component 1 +#ELEMENT number 1 gp 1 keyword "latticestress" component 1 +# +#%BEGIN_CHECK% +#ELEMENT tStep 2 number 1 gp 1 keyword 139 component 1 value 8.77988160e-03 tolerance 1.e-6 +#ELEMENT tStep 13 number 1 gp 1 keyword 139 component 1 value 0.0 tolerance 1.e-6 +#ELEMENT tStep 16 number 1 gp 1 keyword 139 component 1 value 0.0 tolerance 1.e-6 +#ELEMENT tStep 19 number 1 gp 1 keyword 139 component 1 value 0.0 tolerance 1.e-6 +#ELEMENT tStep 22 number 1 gp 1 keyword 139 component 1 value 0.0 tolerance 1.e-6 +#ELEMENT tStep 25 number 1 gp 1 keyword 139 component 1 value 0.0 tolerance 1.e-6 +#%END_CHECK% \ No newline at end of file diff --git a/tests/sm/latticeviscoelastic_mps_1.in b/tests/sm/latticeviscoelastic_mps_1.in new file mode 100644 index 000000000..958145869 --- /dev/null +++ b/tests/sm/latticeviscoelastic_mps_1.in @@ -0,0 +1,59 @@ +latticeviscoelastic_mps_1.out +# +Test on a viscoelastic extension to lattice materials which supports all RheoChainMaterials. This particular test uses mps and computes a basic creep compliance function. Uses incremental linear statics which updates the incremental stiffness in each step. Please do not change to StaticStructural. +# +IncrLinearStatic endOfTimeOfInterest 10000.00000 prescribedTimes 25 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. nmodules 1 +# +errorcheck +# +# vtkxml tstep_step 1 domain_all vars 2 1 4 primvars 1 1 +# +domain 2dlattice +# +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 2 nbc 3 nic 0 nltf 2 nset 3 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.1 0.0 0.0 +# +# +# ELEMENTS +# +Lattice2D 1 nodes 2 1 2 crossSect 1 mat 2 gpCoords 2 0.05 0. width 1.0 thick 1.0 +# +# +# CROSSECTION +# +latticecs 1 material 2 +# +# MATERIAL +# +mps 1 d 0. lattice a1 1. a2 1. talpha 0. referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 0 +# +latticeviscoelastic 2 d 0. talpha 0. viscomat 1 a1 1. a2 1. e 1000. +# +# +BoundaryCondition 1 loadTimeFunction 1 dofs 2 2 6 values 2 0. 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0. set 2 +NodalLoad 3 loadTimeFunction 2 dofs 1 1 Components 1 1. set 3 +# +# +# TIME FUNCTION +# +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 1.0 +# +Set 1 nodes 2 1 2 +Set 2 nodes 1 1 +Set 3 nodes 1 2 +# +#%BEGIN_CHECK% tolerance 1.e-13 +#NODE tStep 4 number 2 dof 1 unknown d value 4.92523215e-06 +#NODE tStep 10 number 2 dof 1 unknown d value 6.09119806e-06 +#NODE tStep 16 number 2 dof 1 unknown d value 7.90759484e-06 +#NODE tStep 22 number 2 dof 1 unknown d value 1.07307196e-05 +#NODE tStep 25 number 2 dof 1 unknown d value 1.20895134e-05 +#%END_CHECK% diff --git a/tests/sm/layeredcs01.in b/tests/sm/layeredcs01.in new file mode 100644 index 000000000..83524662c --- /dev/null +++ b/tests/sm/layeredcs01.in @@ -0,0 +1,82 @@ +layeredcs01.out +Comparing plane stress response for integral and layered cs +# +NonLinearStatic nmodules 1 nmsteps 1 nsteps 1 profileopt 1 +nsteps 2 controllmode 1 rtolf 1e-3 rtold 1e-3 MaxIter 2000 refloadmode 1 +#linearstatic nsteps 1 nmodules 1 +# +errorcheck +# +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 12 nelem 8 ncrosssect 2 nmat 1 nbc 2 nic 0 nltf 2 nset 3 nxfemman 0 +# +node 1 coords 3 0.00 0. 0. +node 2 coords 3 0.50 0. 0. +node 3 coords 3 1.00 0. 0. load 1 2 +node 4 coords 3 0.00 0.2 0. +node 5 coords 3 0.50 0.2 0. +node 6 coords 3 1.00 0.2 0. load 1 2 +# +node 11 coords 3 0.00 0. 0. +node 12 coords 3 0.50 0. 0. +node 13 coords 3 1.00 0. 0. load 1 2 +node 14 coords 3 0.00 0.2 0. +node 15 coords 3 0.50 0.2 0. +node 16 coords 3 1.00 0.2 0. load 1 2 +# +trplanestress2d 1 nodes 3 1 2 5 +trplanestress2d 2 nodes 3 5 4 1 +trplanestress2d 3 nodes 3 2 3 6 +trplanestress2d 4 nodes 3 6 5 2 + +trplanestress2d 11 nodes 3 11 12 15 +trplanestress2d 12 nodes 3 15 14 11 +trplanestress2d 13 nodes 3 12 13 16 +trplanestress2d 14 nodes 3 16 15 12 +# +#CROSS SECTIONS +SimpleCS 1 thick 0.02 material 1 set 1 drillstiffness 1.0e+09 +LayeredCS 2 nlayers 2 layermaterials 2 1 1 widths 2 1 1 thicks 2 0.01 0.01 nintegrationpoints 2 set 2 +# +#MATERIALS +IsoLE 1 d 1. E 1e9 n 0.0 tAlpha 0. +# +#BOUNDARY CONDITIONS + BoundaryCondition 1 loadTimeFunction 1 dofs 6 1 2 3 4 5 6 values 6 0. 0. 0. 0. 0. 0. set 3 + nodalload 2 loadTimeFunction 2 components 2 0. 1.e3 +# +#FUNCTIONS + ConstantFunction 1 f(t) 1. + PiecewiseLinFunction 2 nPoints 3 t 3 -1. 0. 10. f(t) 3 0. 0. 10. +# +#SETS +Set 1 elementranges {(1 4)} +Set 2 elementranges {(11 14)} +Set 3 nodes 4 1 4 11 14 +# +#%BEGIN_CHECK% tolerance 1.e-10 +## check load levels +## check node displacement at final step +#NODE tStep 2 number 1 dof 2 unknown d value 0.0 +#NODE tStep 2 number 2 dof 2 unknown d value 1.66286569e-03 +#NODE tStep 2 number 3 dof 2 unknown d value 4.83735409e-03 +NODE tStep 2 number 11 dof 2 unknown d value 0.0 +#NODE tStep 2 number 12 dof 2 unknown d value 1.66286569e-03 +#NODE tStep 2 number 13 dof 2 unknown d value 4.83735409e-03 +## check some arbitrary element +#ELEMENT tStep 2 number 1 gp 1 keyword 1 component 1 value 9.18229549e+05 tolerance 1.e-2 +#ELEMENT tStep 2 number 2 gp 1 keyword 1 component 1 value -9.18229549e+05 tolerance 1.e-2 +#ELEMENT tStep 2 number 3 gp 1 keyword 1 component 1 value 3.03073976e+05 tolerance 1.e-2 +#ELEMENT tStep 2 number 4 gp 1 keyword 1 component 1 value -3.03073976e+05 tolerance 1.e-2 +#ELEMENT tStep 2 number 11 gp 1 keyword 1 component 1 value 9.18229549e+05 tolerance 1.e-2 +#ELEMENT tStep 2 number 12 gp 1 keyword 1 component 1 value -9.18229549e+05 tolerance 1.e-2 +#ELEMENT tStep 2 number 13 gp 1 keyword 1 component 1 value 3.03073976e+05 tolerance 1.e-2 +#ELEMENT tStep 2 number 14 gp 1 keyword 1 component 1 value -3.03073976e+05 tolerance 1.e-2 +## +#REACTION tStep 2 number 1 dof 2 value 1.26541636e+03 tolerance 1.e-4 +#REACTION tStep 2 number 4 dof 2 value -3.26541636e+03 tolerance 1.e-4 + +#%END_CHECK% + + diff --git a/tests/sm/layeredcs02.in b/tests/sm/layeredcs02.in new file mode 100644 index 000000000..a56ef66c2 --- /dev/null +++ b/tests/sm/layeredcs02.in @@ -0,0 +1,103 @@ +layeredcs02.out +Comparing tr_shell01 response (plate + plane_stress) for integral and layered cs +# +NonLinearStatic nmodules 1 nmsteps 1 nsteps 1 profileopt 1 +nsteps 2 controllmode 1 rtolf 1e-3 rtold 1e-3 MaxIter 2000 refloadmode 1 +#linearstatic nsteps 1 nmodules 1 +# +errorcheck +# +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 12 nelem 8 ncrosssect 2 nmat 1 nbc 2 nic 0 nltf 2 nset 3 nxfemman 0 +# +node 1 coords 3 0.00 0. 0. +node 2 coords 3 0.50 0. 0. +node 3 coords 3 1.00 0. 0. load 1 2 +node 4 coords 3 0.00 0.2 0. +node 5 coords 3 0.50 0.2 0. +node 6 coords 3 1.00 0.2 0. load 1 2 +# +node 11 coords 3 0.00 0. 0. +node 12 coords 3 0.50 0. 0. +node 13 coords 3 1.00 0. 0. load 1 2 +node 14 coords 3 0.00 0.2 0. +node 15 coords 3 0.50 0.2 0. +node 16 coords 3 1.00 0.2 0. load 1 2 +# +tr_shell01 1 nodes 3 1 2 5 nip 4 +tr_shell01 2 nodes 3 5 4 1 nip 4 +tr_shell01 3 nodes 3 2 3 6 nip 4 +tr_shell01 4 nodes 3 6 5 2 nip 4 + +tr_shell01 11 nodes 3 11 12 15 nip 4 +tr_shell01 12 nodes 3 15 14 11 nip 4 +tr_shell01 13 nodes 3 12 13 16 nip 4 +tr_shell01 14 nodes 3 16 15 12 nip 4 +# +#CROSS SECTIONS +SimpleCS 1 thick 0.02 material 1 set 1 drillstiffness 1.0e+09 +LayeredCS 2 nlayers 2 layermaterials 2 1 1 widths 2 1 1 thicks 2 0.01 0.01 nintegrationpoints 2 set 2 +# +#MATERIALS +IsoLE 1 d 1. E 1e9 n 0.0 tAlpha 0. +# +#BOUNDARY CONDITIONS + BoundaryCondition 1 loadTimeFunction 1 dofs 6 1 2 3 4 5 6 values 6 0. 0. 0. 0. 0. 0. set 3 + nodalload 2 loadTimeFunction 2 components 6 0. 1.e3 1.e3 0 0 0 +# +#FUNCTIONS + ConstantFunction 1 f(t) 1. + PiecewiseLinFunction 2 nPoints 3 t 3 -1. 0. 10. f(t) 3 0. 0. 10. +# +#SETS +Set 1 elementranges {(1 4)} +Set 2 elementranges {(11 14)} +Set 3 nodes 4 1 4 11 14 +# +#%BEGIN_CHECK% tolerance 1.e-8 +## check load levels +## check node displacement at final step +#NODE tStep 2 number 1 dof 2 unknown d value 0.0 +#NODE tStep 2 number 2 dof 2 unknown d value 5.89140445e-03 +#NODE tStep 2 number 3 dof 2 unknown d value 1.84651546e-02 +#NODE tStep 2 number 3 dof 3 unknown d value 4.68420501e+00 +#NODE tStep 2 number 3 dof 5 unknown d value -7.47621230e+00 +## +#NODE tStep 2 number 11 dof 2 unknown d value 0.0 +#NODE tStep 2 number 12 dof 2 unknown d value 5.89140445e-03 +#NODE tStep 2 number 13 dof 2 unknown d value 1.84651546e-02 +#NODE tStep 2 number 13 dof 3 unknown d value 4.68420501e+00 +#NODE tStep 2 number 13 dof 5 unknown d value -7.47621230e+00 +## check some arbitrary element +#ELEMENT tStep 2 number 1 gp 1 keyword 10 component 1 value 5.2896226e+04 tolerance 1.e-2 +#ELEMENT tStep 2 number 1 gp 1 keyword 10 component 2 value -6.766454e+03 tolerance 1.e-2 +#ELEMENT tStep 2 number 1 gp 1 keyword 10 component 4 value 5.4942e+03 tolerance 1.e-2 +#ELEMENT tStep 2 number 1 gp 1 keyword 10 component 5 value 1.63293101e+04 tolerance 1.e-2 +#ELEMENT tStep 2 number 1 gp 1 keyword 10 component 6 value -1.33521715e+04 tolerance 1.e-2 +# +#ELEMENT tStep 2 number 11 gp 1 keyword 10 component 1 value 5.2896226e+04 tolerance 1.e-2 +#ELEMENT tStep 2 number 11 gp 1 keyword 10 component 2 value -6.766454e+03 tolerance 1.e-2 +#ELEMENT tStep 2 number 11 gp 1 keyword 10 component 4 value 5.4942e+03 tolerance 1.e-2 +#ELEMENT tStep 2 number 11 gp 1 keyword 10 component 5 value 1.63293101e+04 tolerance 1.e-2 +#ELEMENT tStep 2 number 11 gp 1 keyword 10 component 6 value -1.33521715e+04 tolerance 1.e-2 +## +#ELEMENT tStep 2 number 1 gp 1 keyword 9 component 1 value -7.4927e+03 tolerance 1.e-2 +#ELEMENT tStep 2 number 1 gp 1 keyword 9 component 2 value -2.9910e+01 tolerance 1.e-2 +#ELEMENT tStep 2 number 1 gp 1 keyword 9 component 3 value 1.10925262e+06 tolerance 1.e-2 +#ELEMENT tStep 2 number 1 gp 1 keyword 9 component 6 value -1.4378e+01 tolerance 1.e-2 +# +#ELEMENT tStep 2 number 11 gp 1 keyword 9 component 1 value -7.4927e+03 tolerance 1.e-2 +#ELEMENT tStep 2 number 11 gp 1 keyword 9 component 2 value -2.9910e+01 tolerance 1.e-2 +#ELEMENT tStep 2 number 11 gp 1 keyword 9 component 3 value 1.10925262e+06 tolerance 1.e-2 +#ELEMENT tStep 2 number 11 gp 1 keyword 9 component 6 value -1.4378e+01 tolerance 1.e-2 +## +#REACTION tStep 2 number 1 dof 2 value 2.25964537e+02 tolerance 1.e-4 +#REACTION tStep 2 number 1 dof 3 value -5.24278057e+02 tolerance 1.e-4 +#REACTION tStep 2 number 4 dof 2 value -2.22596454e+03 tolerance 1.e-4 +#REACTION tStep 2 number 4 dof 3 value -1.47572194e+03 tolerance 1.e-4 +#REACTION tStep 2 number 11 dof 2 value 2.25964537e+02 tolerance 1.e-4 +#REACTION tStep 2 number 11 dof 3 value -5.24278057e+02 tolerance 1.e-4 +#REACTION tStep 2 number 14 dof 2 value -2.22596454e+03 tolerance 1.e-4 +#REACTION tStep 2 number 14 dof 3 value -1.47572194e+03 tolerance 1.e-4 +#%END_CHECK% diff --git a/tests/sm/layeredcs03.in b/tests/sm/layeredcs03.in new file mode 100644 index 000000000..430ab3482 --- /dev/null +++ b/tests/sm/layeredcs03.in @@ -0,0 +1,53 @@ +layeredcs03.out +Test of Beam2d elements -> cantilever loaded by end moment, comparing elastic integral and layered models +StaticStructural nsteps 2 nmodules 1 +#linearstatic nsteps 2 nmodules 1 +errorcheck +domain 2dBeam +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 2 ncrosssect 2 nmat 1 nbc 2 nic 0 nltf 1 nset 4 +node 1 coords 3 0. 0. 0. +node 2 coords 3 3. 0. 0. +node 11 coords 3 0 0 0 +node 12 coords 3 3. 0 0 +Beam2d 1 nodes 2 1 2 +Beam2d 11 nodes 2 11 12 +SimpleCS 1 thick 0.3 width 1.0 area 0.3 Iy 0.00225 beamShearCoeff 1.0 material 1 set 1 +LayeredCS 2 nLayers 2 LayerMaterials 2 1 1 Thicks 2 0.15 0.15 Widths 2 1. 1. midSurf 0.15 nintegrationpoints 2 set 2 +IsoLE 1 d 0. E 15000000.0 n 0.25 talpha 0.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 3 5 values 3 0 0 0 set 3 +NodalLoad 2 loadTimeFunction 1 dofs 1 3 Components 1 0.1 set 4 +ConstantFunction 1 f(t) 1.0 +Set 1 elements 1 1 +Set 2 elements 1 11 +Set 3 nodes 2 1 11 +Set 4 nodes 2 2 12 +# +# +# beam exact solution: +# load-level 1.0 -> end of elastic behaviour and begining of elasto- +# plastic behaviour +# +# at load-level 1.5 -> vycerpana unosnost -kolaps. +# +# +# +# +#%BEGIN_CHECK% tolerance 1.e-12 +## check load levels +## check node displacement at final step +#NODE tStep 1 number 2 dof 1 unknown d value 0.0 +#NODE tStep 1 number 2 dof 3 unknown d value 2.68333333e-05 +#NODE tStep 1 number 2 dof 5 unknown d value -1.33333333e-05 +#NODE tStep 1 number 12 dof 1 unknown d value 0.0 +#NODE tStep 1 number 12 dof 3 unknown d value 2.68333333e-05 +#NODE tStep 1 number 12 dof 5 unknown d value -1.33333333e-05 +## check elements +#REACTION tStep 1 number 1 dof 3 value -0.1 +#REACTION tStep 1 number 1 dof 5 value 0.3 +#REACTION tStep 1 number 11 dof 3 value -0.1 +#REACTION tStep 1 number 11 dof 5 value 0.3 +# +# +#%END_CHECK% + diff --git a/tests/sm/libeam3dboundary.in b/tests/sm/libeam3dboundary.in new file mode 100644 index 000000000..e4e6009a5 --- /dev/null +++ b/tests/sm/libeam3dboundary.in @@ -0,0 +1,46 @@ +libeam3dboundary.out +Reinforcement test case in 3D RVE - periodicity with LIBeam3dBoundary elements +StaticStructural nsteps 1 deltat 1.0 rtolf 1.0e-4 MaxIter 30 minIter 1 nmodules 1 initialguess 1 +#vtkxmlperiodic tstep_all domain_all primvars 1 1 vars 2 7 8 stype 0 +#vtkxmlperiodic tstep_all domain_all ipvars 2 7 8 +#matlab tstep_all mesh data reactionforces integrationpoints internalvars 2 7 8 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 11 nelem 8 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 2 nset 3 +node 1 coords 3 0.0 -0.2 0.0 +node 2 coords 3 0.0 -0.1 0.0 +node 3 coords 3 0.0 0.0 0.0 +node 4 coords 3 0.0 0.1 0.0 +node 5 coords 3 -0.2 0.0 0.0 +node 6 coords 3 -0.1 0.0 0.0 +node 7 coords 3 0.0 0.0 0.0 +node 8 coords 3 0.1 0.0 0.0 +node 9 coords 3 -0.1 0.0 0.0 +node 10 coords 3 0.0 0.1 0.0 +node 11 coords 3 0.4 0.4 0.4 +libeam3d 1 nodes 2 1 2 refnode 9 crossSect 1 +libeam3d 2 nodes 2 2 3 refnode 9 crossSect 1 +libeam3d 3 nodes 2 3 4 refnode 9 crossSect 1 +libeam3dboundary 4 nodes 3 4 1 11 refnode 6 crossSect 1 location 2 0 16 +libeam3d 5 nodes 2 5 6 refnode 10 crossSect 1 +libeam3d 6 nodes 2 6 7 refnode 10 crossSect 1 +libeam3d 7 nodes 2 7 8 refnode 10 crossSect 1 +libeam3dboundary 8 nodes 3 8 5 11 refnode 10 crossSect 1 location 2 0 22 +Set 1 elementranges { (1 8) } +Set 2 nodes 1 11 +Set 3 nodes 2 1 5 +FiberedCS 1 fibermaterials 1 1 thicks 1 17.72455923e-3 widths 1 17.72455923e-3 thick 17.72455923e-3 width 17.72455923e-3 fiberycentrecoords 1 8.862279616e-3 fiberzcentrecoords 1 8.862279616e-3 +MisesMat 1 d 1.0 E 2e11 n 0.3 sig0 500e6 H 8.456659619e8 omega_crit 0 a 0 tAlpha 1.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 6 1 2 3 4 5 6 values 6 0 0 0 0 0 0 set 3 +BoundaryCondition 2 loadTimeFunction 1 dofs 9 31 38 36 39 32 34 37 35 33 values 9 0.3e-5 0.4e-5 0 0.4e-5 -0.5e-5 0 0 0 0 set 2 +ConstantFunction 1 f(t) 1 +PiecewiseLinFunction 2 t 2 0.0 15.0 f(t) 2 0.0 1.5 + +#%BEGIN_CHECK% tolerance 1e-3 +#REACTION tStep 1 number 11 dof 31 value 7.540953415e+01 +#REACTION tStep 1 number 11 dof 32 value -1.256751341e+02 +#ELEMENT tStep 1 number 4 gp 1 keyword 7 component 1 value -3.141878e+02 +#ELEMENT tStep 1 number 8 gp 1 keyword 7 component 1 value 1.885238e+02 +##TIME +#%END_CHECK% diff --git a/tests/sm/linkslip01.in b/tests/sm/linkslip01.in new file mode 100644 index 000000000..4f4dc024e --- /dev/null +++ b/tests/sm/linkslip01.in @@ -0,0 +1,56 @@ +linkslip01.out +Test case for LinkSlip interface material - rebar pull-out in 3D. +StaticStructural nsteps 20 deltat 1.0 rtolf 1.0e-3 MaxIter 500 initialguess 1 nmodules 1 +errorcheck +#vtkxml tstep_all domain_all primvars 1 1 +#vtkxml tstep_all domain_all ipvars 2 98 99 regionsets 1 3 +#matlab tstep_all integrationpoints internalvars 2 98 99 +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 14 nelem 5 ncrosssect 3 nmat 3 nbc 4 nic 0 nltf 1 nset 6 +node 1 coords 3 -0.1 -0.1 0.1 +node 2 coords 3 -0.1 0.0 0.1 +node 3 coords 3 0.1 0.0 0.1 +node 4 coords 3 0.1 -0.1 0.1 +node 5 coords 3 -0.1 -0.1 -0.1 +node 6 coords 3 -0.1 0.0 -0.1 +node 7 coords 3 0.1 0.0 -0.1 +node 8 coords 3 0.1 -0.1 -0.1 +node 9 coords 3 -0.1 0.1 0.1 +node 10 coords 3 0.1 0.1 0.1 +node 11 coords 3 -0.1 0.1 -0.1 +node 12 coords 3 0.1 0.1 -0.1 +node 13 coords 3 -0.1 0.0 0.2 dofidmask 6 1 2 3 4 5 6 +node 14 coords 3 0.1 0.0 0.2 dofidmask 6 1 2 3 4 5 6 +lspace 1 nodes 8 1 2 3 4 5 6 7 8 +lspace 2 nodes 8 2 9 10 3 6 11 12 7 +libeam3d 3 nodes 2 13 14 refnode 9 +bondlink3d 4 nodes 2 13 2 dirvector 3 1 0 0 length 0.1 length_end 5.000000e-02 diameter 0.02 +bondlink3d 5 nodes 2 14 3 dirvector 3 1 0 0 length 0.1 length_end 7.161990e-02 diameter 0.02 +Set 1 elements 2 1 2 +Set 2 elements 1 3 +Set 3 elements 2 4 5 +Set 4 nodes 1 1 +Set 5 nodes 2 1 4 +Set 6 nodes 1 14 +SimpleCS 1 material 1 set 1 +SimpleCS 2 area 3.1416e-4 material 2 set 2 +interfacecs 3 material 3 set 3 +IsoLE 1 d 1.0 E 3.36e10 n 0.2 tAlpha 1.0 +IsoLE 2 d 1.0 E 2e11 n 0.3 tAlpha 1.0 +linkslip 3 kn 6.135e10 kl 6.135e13 type 2 alpha 0.4 s1 1.e-3 s2 2e-3 s3 6.5e-3 t0 1.541e7 tf 6.164e6 +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 2 3 values 3 0 0 0 set 4 +BoundaryCondition 2 loadTimeFunction 1 dofs 2 2 3 values 2 0 0 set 5 +BoundaryCondition 3 loadTimeFunction 1 dofs 3 4 5 6 values 3 0 0 0 set 2 +BoundaryCondition 4 loadTimeFunction 1 dofs 1 1 values 1 8e-3 set 6 +PiecewiseLinFunction 1 t 2 0.0 20.0 f(t) 2 0.0 1.0 + +#%BEGIN_CHECK% tolerance 1.e1 +##Bond stress values check +#ELEMENT tStep 1 number 5 gp 1 keyword 99 component 1 value 9.54332268e+06 +#ELEMENT tStep 5 number 5 gp 1 keyword 99 component 1 value 1.54100000e+07 +#ELEMENT tStep 8 number 5 gp 1 keyword 99 component 1 value 1.32375379e+07 +#ELEMENT tStep 15 number 5 gp 1 keyword 99 component 1 value 7.35417846e+06 +#ELEMENT tStep 19 number 5 gp 1 keyword 99 component 1 value 6.16400000e+06 +## +#%END_CHECK% diff --git a/tests/sm/linkslip02.in b/tests/sm/linkslip02.in new file mode 100644 index 000000000..ed2af8e95 --- /dev/null +++ b/tests/sm/linkslip02.in @@ -0,0 +1,56 @@ +linkslip02.out +Test case for LinkSlip interface material - truss rebar pull-out in 3D. +StaticStructural nsteps 20 deltat 1.0 rtolf 1.0e-3 MaxIter 500 initialguess 1 nmodules 1 +errorcheck +#vtkxml tstep_all domain_all primvars 1 1 +#vtkxml tstep_all domain_all ipvars 2 98 99 regionsets 1 3 +#matlab tstep_all integrationpoints internalvars 2 98 99 +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 14 nelem 5 ncrosssect 3 nmat 3 nbc 4 nic 0 nltf 1 nset 6 +node 1 coords 3 -0.1 -0.1 0.1 +node 2 coords 3 -0.1 0.0 0.1 +node 3 coords 3 0.1 0.0 0.1 +node 4 coords 3 0.1 -0.1 0.1 +node 5 coords 3 -0.1 -0.1 -0.1 +node 6 coords 3 -0.1 0.0 -0.1 +node 7 coords 3 0.1 0.0 -0.1 +node 8 coords 3 0.1 -0.1 -0.1 +node 9 coords 3 -0.1 0.1 0.1 +node 10 coords 3 0.1 0.1 0.1 +node 11 coords 3 -0.1 0.1 -0.1 +node 12 coords 3 0.1 0.1 -0.1 +node 13 coords 3 -0.1 0.0 0.1 +node 14 coords 3 0.1 0.0 0.1 +lspace 1 nodes 8 1 2 3 4 5 6 7 8 +lspace 2 nodes 8 2 9 10 3 6 11 12 7 +truss3d 3 nodes 2 13 14 +bondlink3dtruss 4 nodes 2 13 2 dirvector 3 1 0 0 length 0.1 diameter 0.02 +bondlink3dtruss 5 nodes 2 14 3 dirvector 3 1 0 0 length 0.1 diameter 0.02 +Set 1 elements 2 1 2 +Set 2 elements 1 3 +Set 3 elements 2 4 5 +Set 4 nodes 1 1 +Set 5 nodes 2 1 4 +Set 6 nodes 1 14 +SimpleCS 1 material 1 set 1 +SimpleCS 2 area 3.1416e-4 material 2 set 2 +interfacecs 3 material 3 set 3 +IsoLE 1 d 1.0 E 3.36e10 n 0.2 tAlpha 1.0 +IsoLE 2 d 1.0 E 2e11 n 0.3 tAlpha 1.0 +linkslip 3 kn 6.135e10 kl 6.135e13 type 2 alpha 0.4 s1 1.e-3 s2 2e-3 s3 6.5e-3 t0 1.541e7 tf 6.164e6 +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 2 3 values 3 0 0 0 set 4 +BoundaryCondition 2 loadTimeFunction 1 dofs 2 2 3 values 2 0 0 set 5 +BoundaryCondition 3 loadTimeFunction 1 dofs 3 4 5 6 values 3 0 0 0 set 2 +BoundaryCondition 4 loadTimeFunction 1 dofs 1 1 values 1 8e-3 set 6 +PiecewiseLinFunction 1 t 2 0.0 20.0 f(t) 2 0.0 1.0 + +#%BEGIN_CHECK% tolerance 1.e3 +##Bond stress values check +#ELEMENT tStep 1 number 5 gp 1 keyword 99 component 1 value 9.0173e+06 +#ELEMENT tStep 5 number 5 gp 1 keyword 99 component 1 value 1.54100000e+07 +#ELEMENT tStep 8 number 5 gp 1 keyword 99 component 1 value 1.3425e+07 +#ELEMENT tStep 15 number 5 gp 1 keyword 99 component 1 value 7.4582e+06 +#ELEMENT tStep 19 number 5 gp 1 keyword 99 component 1 value 6.16400000e+06 +## +#%END_CHECK% diff --git a/tests/sm/linstab_beam2d.in b/tests/sm/linstab_beam2d.in index 02a291310..7b976eb65 100644 --- a/tests/sm/linstab_beam2d.in +++ b/tests/sm/linstab_beam2d.in @@ -1,6 +1,6 @@ linstab_beam2d.out Linear stability of cantiliver -#LinearStatic 1 nsteps 1 +#StaticStructural 1 nsteps 1 LinearStability nroot 9 rtolv 1.e-8 nmodules 1 errorcheck domain 2dBeam @@ -15,15 +15,14 @@ Beam2d 1 nodes 2 1 2 Beam2d 2 nodes 2 2 3 Beam2d 3 nodes 2 3 4 # -SimpleCS 1 area 0.0054 Iy 85.e-6 beamShearCoeff 1.e60 material 1 set 1 -IsoLE 1 d 25.0 E 21.e7 n 0.2 tAlpha 1.2e-5 -BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 3 5 values 3 3 0 0 set 2 -NodalLoad 2 loadTimeFunction 1 dofs 3 1 3 5 Components 3 0.0 -1.0 0.0 set 3 -ConstantFunction 1 f(t) 1. Set 1 elementranges {(1 3)} Set 2 nodes 1 1 Set 3 nodes 1 4 -# +SimpleCS 1 area 0.0054 Iy 85.e-6 beamShearCoeff 1.e60 material 1 set 1 +IsoLE 1 d 25.0 E 21.e7 n 0.2 tAlpha 1.2e-5 +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 3 5 values 3 0 0 0 set 2 +NodalLoad 2 loadTimeFunction 1 dofs 3 1 3 5 Components 3 0.0 -1.0 0.0 set 3 +ConstantFunction 1 f(t) 1. # #%BEGIN_CHECK% tolerance 5.e-2 ## check eigen values diff --git a/tests/sm/ltrspaceboundary01.in b/tests/sm/ltrspaceboundary01.in new file mode 100644 index 000000000..53240114c --- /dev/null +++ b/tests/sm/ltrspaceboundary01.in @@ -0,0 +1,97 @@ +ltrspaceboundary01.out +3D RVE - periodic boundary conditions with LTRSpaceBoundaryTruss elements, periodicity in x +StaticStructural nsteps 1 initialguess 1 nmodules 1 +#vtkxmlperiodic primvars 1 1 vars 3 4 1 12 cellvars 1 46 tstep_all domain_all stype 0 +#vtkxmlperiodic ipvars 3 4 1 12 tstep_all domain_all +#gpexportmodule vars 3 4 1 12 tstep_all domain_all +#matlab tstep_all mesh data specials reactionforces integrationpoints internalvars 3 4 1 12 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 19 nelem 56 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 1 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 3 1 1 1 +node 4 coords 3 0.000000e+00 1.000000e-01 0.000000e+00 +node 5 coords 3 0.000000e+00 0.000000e+00 1.000000e-01 +node 8 coords 3 0.000000e+00 1.000000e-01 1.000000e-01 +node 9 coords 3 5.827886e-02 0.000000e+00 0.000000e+00 +node 12 coords 3 5.827886e-02 1.000000e-01 0.000000e+00 +node 15 coords 3 5.827886e-02 0.000000e+00 1.000000e-01 +node 18 coords 3 5.827886e-02 1.000000e-01 1.000000e-01 +node 24 coords 3 0.000000e+00 4.124619e-02 0.000000e+00 +node 30 coords 3 0.000000e+00 4.124619e-02 1.000000e-01 +node 33 coords 3 0.000000e+00 0.000000e+00 4.902652e-02 +node 39 coords 3 0.000000e+00 1.000000e-01 4.902652e-02 +node 45 coords 3 4.791257e-02 5.177834e-02 0.000000e+00 +node 54 coords 3 4.791257e-02 5.177834e-02 1.000000e-01 +node 63 coords 3 4.791257e-02 0.000000e+00 5.059616e-02 +node 72 coords 3 4.791257e-02 1.000000e-01 5.059616e-02 +node 90 coords 3 0.000000e+00 4.791257e-02 5.059616e-02 +node 99 coords 3 4.463697e-02 4.791257e-02 5.059616e-02 +node 126 coords 3 1.000000e-01 1.000000e-01 1.000000e-01 dofidmask 1 31 bc 1 2 +ltrspaceboundarytruss 14 nodes 5 99 18 54 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundarytruss 15 nodes 5 18 99 72 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspace 16 nodes 4 99 18 72 54 crossSect 1 mat 1 +ltrspaceboundarytruss 18 nodes 5 24 99 9 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarytruss 53 nodes 5 30 99 54 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarytruss 54 nodes 5 18 30 54 90 126 crossSect 1 mat 1 location 4 0 22 0 22 +ltrspaceboundarytruss 55 nodes 5 30 18 8 90 126 crossSect 1 mat 1 location 4 22 0 22 22 +ltrspace 57 nodes 4 90 99 54 30 crossSect 1 mat 1 +ltrspace 58 nodes 4 18 8 72 54 crossSect 1 mat 1 +ltrspace 59 nodes 4 8 90 54 30 crossSect 1 mat 1 +ltrspace 60 nodes 4 8 99 72 54 crossSect 1 mat 1 +ltrspace 61 nodes 4 8 90 99 54 crossSect 1 mat 1 +ltrspaceboundarytruss 72 nodes 5 45 24 99 9 126 crossSect 1 mat 1 location 4 0 22 0 0 +ltrspaceboundarytruss 73 nodes 5 24 45 99 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarytruss 136 nodes 5 15 30 99 54 126 crossSect 1 mat 1 location 4 0 22 0 0 +ltrspaceboundarytruss 140 nodes 5 30 15 99 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspace 176 nodes 4 45 24 90 4 crossSect 1 mat 1 +ltrspace 177 nodes 4 24 45 90 99 crossSect 1 mat 1 +ltrspace 178 nodes 4 39 8 99 72 crossSect 1 mat 1 +ltrspace 179 nodes 4 39 8 90 99 crossSect 1 mat 1 +ltrspace 180 nodes 4 45 39 99 72 crossSect 1 mat 1 +ltrspace 181 nodes 4 39 45 4 72 crossSect 1 mat 1 +ltrspace 182 nodes 4 45 39 90 99 crossSect 1 mat 1 +ltrspace 183 nodes 4 39 45 90 4 crossSect 1 mat 1 +ltrspaceboundarytruss 253 nodes 5 99 12 72 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundarytruss 254 nodes 5 45 12 99 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspace 255 nodes 4 12 45 99 72 crossSect 1 mat 1 +ltrspaceboundarytruss 256 nodes 5 12 45 24 90 126 crossSect 1 mat 1 location 4 0 0 22 22 +ltrspaceboundarytruss 257 nodes 5 4 12 24 90 126 crossSect 1 mat 1 location 4 22 0 22 22 +ltrspace 261 nodes 4 45 12 4 72 crossSect 1 mat 1 +ltrspaceboundarytruss 287 nodes 5 33 24 9 90 126 crossSect 1 mat 1 location 4 22 22 0 22 +ltrspaceboundarytruss 288 nodes 5 1 33 24 9 126 crossSect 1 mat 1 location 4 22 22 22 0 +ltrspaceboundarytruss 290 nodes 5 33 15 30 90 126 crossSect 1 mat 1 location 4 22 0 22 22 +ltrspaceboundarytruss 304 nodes 5 5 33 15 30 126 crossSect 1 mat 1 location 4 22 22 0 22 +ltrspace 415 nodes 4 33 24 90 99 crossSect 1 mat 1 +ltrspace 419 nodes 4 90 33 99 30 crossSect 1 mat 1 +ltrspaceboundarytruss 437 nodes 5 12 39 72 90 126 crossSect 1 mat 1 location 4 0 22 0 22 +ltrspaceboundarytruss 438 nodes 5 39 12 4 90 126 crossSect 1 mat 1 location 4 22 0 22 22 +ltrspaceboundarytruss 441 nodes 5 18 39 8 90 126 crossSect 1 mat 1 location 4 0 22 22 22 +ltrspaceboundarytruss 442 nodes 5 39 18 72 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarytruss 453 nodes 5 15 63 99 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundarytruss 454 nodes 5 33 63 15 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarytruss 455 nodes 5 99 63 9 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundarytruss 456 nodes 5 63 33 9 90 126 crossSect 1 mat 1 location 4 0 22 0 22 +ltrspace 458 nodes 4 33 63 24 99 crossSect 1 mat 1 +ltrspace 462 nodes 4 15 63 5 30 crossSect 1 mat 1 +ltrspace 463 nodes 4 63 33 5 30 crossSect 1 mat 1 +ltrspace 464 nodes 4 33 63 99 30 crossSect 1 mat 1 +ltrspace 468 nodes 4 63 45 99 9 crossSect 1 mat 1 +ltrspace 469 nodes 4 63 24 45 9 crossSect 1 mat 1 +ltrspace 470 nodes 4 24 63 45 99 crossSect 1 mat 1 +ltrspace 474 nodes 4 99 63 54 30 crossSect 1 mat 1 +ltrspace 475 nodes 4 63 15 54 30 crossSect 1 mat 1 +ltrspace 476 nodes 4 63 15 99 54 crossSect 1 mat 1 +ltrspace 537 nodes 4 63 1 24 9 crossSect 1 mat 1 +ltrspace 538 nodes 4 63 1 33 24 crossSect 1 mat 1 +simplecs 1 +isole 1 talpha 0. d 0. e 30.e9 n 0.2 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 31 values 1 0.3 set 1 +ConstantFunction 1 f(t) 1. +set 1 nodes 1 126 + +#%BEGIN_CHECK% tolerance 1e-3 +#REACTION tStep 1 number 126 dof 31 value 9.0000e+06 +##TIME +#%END_CHECK% diff --git a/tests/sm/ltrspaceboundary02.in b/tests/sm/ltrspaceboundary02.in new file mode 100644 index 000000000..83eada6b0 --- /dev/null +++ b/tests/sm/ltrspaceboundary02.in @@ -0,0 +1,93 @@ +ltrspaceboundary02.out +3D RVE - periodic boundary conditions with LTRSpaceBoundaryMembrane elements, periodicity in x y +StaticStructural nsteps 1 initialguess 1 nmodules 1 +#vtkxmlperiodic primvars 1 1 vars 3 4 1 12 cellvars 1 46 tstep_all domain_all stype 0 +#vtkxmlperiodic ipvars 3 4 1 12 tstep_all domain_all +#gpexportmodule vars 3 4 1 12 tstep_all domain_all +#matlab tstep_all mesh data specials reactionforces integrationpoints internalvars 3 4 1 12 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 13 nelem 56 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 1 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 3 1 1 1 +node 5 coords 3 0.000000e+00 0.000000e+00 1.000000e-01 +node 9 coords 3 5.827886e-02 0.000000e+00 0.000000e+00 +node 15 coords 3 5.827886e-02 0.000000e+00 1.000000e-01 +node 24 coords 3 0.000000e+00 4.124619e-02 0.000000e+00 +node 30 coords 3 0.000000e+00 4.124619e-02 1.000000e-01 +node 33 coords 3 0.000000e+00 0.000000e+00 4.902652e-02 +node 45 coords 3 4.791257e-02 5.177834e-02 0.000000e+00 +node 54 coords 3 4.791257e-02 5.177834e-02 1.000000e-01 +node 63 coords 3 4.791257e-02 0.000000e+00 5.059616e-02 +node 90 coords 3 0.000000e+00 4.791257e-02 5.059616e-02 +node 99 coords 3 4.463697e-02 4.791257e-02 5.059616e-02 +node 126 coords 3 1.000000e-01 1.000000e-01 1.000000e-01 dofidmask 4 31 38 39 32 bc 4 2 2 2 2 +ltrspaceboundarymembrane 14 nodes 5 99 15 54 90 126 crossSect 1 mat 1 location 4 0 16 0 22 +ltrspaceboundarymembrane 15 nodes 5 15 99 63 90 126 crossSect 1 mat 1 location 4 16 0 16 22 +ltrspaceboundarymembrane 16 nodes 5 99 15 63 54 126 crossSect 1 mat 1 location 4 0 16 16 0 +ltrspaceboundarymembrane 18 nodes 5 24 99 9 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarymembrane 53 nodes 5 30 99 54 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarymembrane 54 nodes 5 15 30 54 90 126 crossSect 1 mat 1 location 4 16 22 0 22 +ltrspaceboundarymembrane 55 nodes 5 30 15 5 90 126 crossSect 1 mat 1 location 4 22 16 25 22 +ltrspace 57 nodes 4 90 99 54 30 crossSect 1 mat 1 +ltrspaceboundarymembrane 58 nodes 5 15 5 63 54 126 crossSect 1 mat 1 location 4 16 16 16 0 +ltrspaceboundarymembrane 59 nodes 5 5 90 54 30 126 crossSect 1 mat 1 location 4 16 0 0 0 +ltrspaceboundarymembrane 60 nodes 5 5 99 63 54 126 crossSect 1 mat 1 location 4 16 0 16 0 +ltrspaceboundarymembrane 61 nodes 5 5 90 99 54 126 crossSect 1 mat 1 location 4 16 0 0 0 +ltrspaceboundarymembrane 72 nodes 5 45 24 99 9 126 crossSect 1 mat 1 location 4 0 22 0 0 +ltrspaceboundarymembrane 73 nodes 5 24 45 99 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarymembrane 136 nodes 5 15 30 99 54 126 crossSect 1 mat 1 location 4 0 22 0 0 +ltrspaceboundarymembrane 140 nodes 5 30 15 99 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarymembrane 176 nodes 5 45 24 90 1 126 crossSect 1 mat 1 location 4 0 0 0 16 +ltrspace 177 nodes 4 24 45 90 99 crossSect 1 mat 1 +ltrspaceboundarymembrane 178 nodes 5 33 5 99 63 126 crossSect 1 mat 1 location 4 16 16 0 16 +ltrspaceboundarymembrane 179 nodes 5 33 5 90 99 126 crossSect 1 mat 1 location 4 16 16 0 0 +ltrspaceboundarymembrane 180 nodes 5 45 33 99 63 126 crossSect 1 mat 1 location 4 0 16 0 16 +ltrspaceboundarymembrane 181 nodes 5 33 45 1 63 126 crossSect 1 mat 1 location 4 16 0 16 16 +ltrspaceboundarymembrane 182 nodes 5 45 33 90 99 126 crossSect 1 mat 1 location 4 0 16 0 0 +ltrspaceboundarymembrane 183 nodes 5 33 45 90 1 126 crossSect 1 mat 1 location 4 16 0 0 16 +ltrspaceboundarymembrane 253 nodes 5 99 9 63 90 126 crossSect 1 mat 1 location 4 0 16 16 22 +ltrspaceboundarymembrane 254 nodes 5 45 9 99 90 126 crossSect 1 mat 1 location 4 0 16 0 22 +ltrspaceboundarymembrane 255 nodes 5 9 45 99 63 126 crossSect 1 mat 1 location 4 16 0 0 16 +ltrspaceboundarymembrane 256 nodes 5 9 45 24 90 126 crossSect 1 mat 1 location 4 16 0 22 22 +ltrspaceboundarymembrane 257 nodes 5 1 9 24 90 126 crossSect 1 mat 1 location 4 25 16 22 22 +ltrspaceboundarymembrane 261 nodes 5 45 9 1 63 126 crossSect 1 mat 1 location 4 0 16 16 16 +ltrspaceboundarymembrane 287 nodes 5 33 24 9 90 126 crossSect 1 mat 1 location 4 22 22 0 22 +ltrspaceboundarymembrane 288 nodes 5 1 33 24 9 126 crossSect 1 mat 1 location 4 22 22 22 0 +ltrspaceboundarymembrane 290 nodes 5 33 15 30 90 126 crossSect 1 mat 1 location 4 22 0 22 22 +ltrspaceboundarymembrane 304 nodes 5 5 33 15 30 126 crossSect 1 mat 1 location 4 22 22 0 22 +ltrspace 415 nodes 4 33 24 90 99 crossSect 1 mat 1 +ltrspace 419 nodes 4 90 33 99 30 crossSect 1 mat 1 +ltrspaceboundarymembrane 437 nodes 5 9 33 63 90 126 crossSect 1 mat 1 location 4 16 25 16 22 +ltrspaceboundarymembrane 438 nodes 5 33 9 1 90 126 crossSect 1 mat 1 location 4 25 16 25 22 +ltrspaceboundarymembrane 441 nodes 5 15 33 5 90 126 crossSect 1 mat 1 location 4 16 25 25 22 +ltrspaceboundarymembrane 442 nodes 5 33 15 63 90 126 crossSect 1 mat 1 location 4 25 16 16 22 +ltrspaceboundarymembrane 453 nodes 5 15 63 99 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundarymembrane 454 nodes 5 33 63 15 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarymembrane 455 nodes 5 99 63 9 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundarymembrane 456 nodes 5 63 33 9 90 126 crossSect 1 mat 1 location 4 0 22 0 22 +ltrspace 458 nodes 4 33 63 24 99 crossSect 1 mat 1 +ltrspace 462 nodes 4 15 63 5 30 crossSect 1 mat 1 +ltrspace 463 nodes 4 63 33 5 30 crossSect 1 mat 1 +ltrspace 464 nodes 4 33 63 99 30 crossSect 1 mat 1 +ltrspace 468 nodes 4 63 45 99 9 crossSect 1 mat 1 +ltrspace 469 nodes 4 63 24 45 9 crossSect 1 mat 1 +ltrspace 470 nodes 4 24 63 45 99 crossSect 1 mat 1 +ltrspace 474 nodes 4 99 63 54 30 crossSect 1 mat 1 +ltrspace 475 nodes 4 63 15 54 30 crossSect 1 mat 1 +ltrspace 476 nodes 4 63 15 99 54 crossSect 1 mat 1 +ltrspace 537 nodes 4 63 1 24 9 crossSect 1 mat 1 +ltrspace 538 nodes 4 63 1 33 24 crossSect 1 mat 1 +simplecs 1 +isole 1 talpha 0. d 0. e 30.e9 n 0.2 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 1 dofs 4 31 38 39 32 values 4 0.3 0.2 0.6 -0.5 set 1 +ConstantFunction 1 f(t) 1. +set 1 nodes 1 126 + +#%BEGIN_CHECK% tolerance 1e-3 +#REACTION tStep 1 number 126 dof 31 value 6.2500e+06 +#REACTION tStep 1 number 126 dof 38 value 1.0000e+07 +#REACTION tStep 1 number 126 dof 32 value -1.3750e+07 +##TIME +#%END_CHECK% diff --git a/tests/sm/ltrspaceboundary03.in b/tests/sm/ltrspaceboundary03.in new file mode 100644 index 000000000..2a856e0ef --- /dev/null +++ b/tests/sm/ltrspaceboundary03.in @@ -0,0 +1,81 @@ +ltrspaceboundary03.out +3D RVE - periodic boundary conditions with LTRSpaceBoundaryVoigt elements, periodicity in x y z +StaticStructural nsteps 1 solverType "calm" stepLength 0.3 Psi 0 hpc 2 126 31 initialguess 1 nmodules 1 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 9 nelem 56 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 1 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 3 1 1 1 +node 9 coords 3 5.827886e-02 0.000000e+00 0.000000e+00 +node 24 coords 3 0.000000e+00 4.124619e-02 0.000000e+00 +node 33 coords 3 0.000000e+00 0.000000e+00 4.902652e-02 +node 45 coords 3 4.791257e-02 5.177834e-02 0.000000e+00 +node 63 coords 3 4.791257e-02 0.000000e+00 5.059616e-02 +node 90 coords 3 0.000000e+00 4.791257e-02 5.059616e-02 +node 99 coords 3 4.463697e-02 4.791257e-02 5.059616e-02 +node 126 coords 3 1.000000e-01 1.000000e-01 1.000000e-01 dofidmask 6 31 32 33 40 41 42 load 1 2 +ltrspaceboundaryvoigt 14 nodes 5 99 9 45 90 126 crossSect 1 mat 1 location 4 0 17 14 22 +ltrspaceboundaryvoigt 15 nodes 5 9 99 63 90 126 crossSect 1 mat 1 location 4 17 0 16 22 +ltrspaceboundaryvoigt 16 nodes 5 99 9 63 45 126 crossSect 1 mat 1 location 4 0 17 16 14 +ltrspaceboundaryvoigt 18 nodes 5 24 99 9 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundaryvoigt 53 nodes 5 24 99 45 90 126 crossSect 1 mat 1 location 4 23 0 14 22 +ltrspaceboundaryvoigt 54 nodes 5 9 24 45 90 126 crossSect 1 mat 1 location 4 17 23 14 22 +ltrspaceboundaryvoigt 55 nodes 5 24 9 1 90 126 crossSect 1 mat 1 location 4 23 17 26 22 +ltrspaceboundaryvoigt 57 nodes 5 90 99 45 24 126 crossSect 1 mat 1 location 4 0 0 14 14 +ltrspaceboundaryvoigt 58 nodes 5 9 1 63 45 126 crossSect 1 mat 1 location 4 17 17 16 14 +ltrspaceboundaryvoigt 59 nodes 5 1 90 45 24 126 crossSect 1 mat 1 location 4 17 0 14 14 +ltrspaceboundaryvoigt 60 nodes 5 1 99 63 45 126 crossSect 1 mat 1 location 4 17 0 16 14 +ltrspaceboundaryvoigt 61 nodes 5 1 90 99 45 126 crossSect 1 mat 1 location 4 17 0 0 14 +ltrspaceboundaryvoigt 72 nodes 5 45 24 99 9 126 crossSect 1 mat 1 location 4 0 22 0 0 +ltrspaceboundaryvoigt 73 nodes 5 24 45 99 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundaryvoigt 136 nodes 5 9 24 99 45 126 crossSect 1 mat 1 location 4 14 23 0 14 +ltrspaceboundaryvoigt 140 nodes 5 24 9 99 90 126 crossSect 1 mat 1 location 4 23 14 0 22 +ltrspaceboundaryvoigt 176 nodes 5 45 24 90 1 126 crossSect 1 mat 1 location 4 0 0 0 16 +ltrspace 177 nodes 4 24 45 90 99 crossSect 1 mat 1 +ltrspaceboundaryvoigt 178 nodes 5 33 1 99 63 126 crossSect 1 mat 1 location 4 16 17 0 16 +ltrspaceboundaryvoigt 179 nodes 5 33 1 90 99 126 crossSect 1 mat 1 location 4 16 17 0 0 +ltrspaceboundaryvoigt 180 nodes 5 45 33 99 63 126 crossSect 1 mat 1 location 4 0 16 0 16 +ltrspaceboundaryvoigt 181 nodes 5 33 45 1 63 126 crossSect 1 mat 1 location 4 16 0 16 16 +ltrspaceboundaryvoigt 182 nodes 5 45 33 90 99 126 crossSect 1 mat 1 location 4 0 16 0 0 +ltrspaceboundaryvoigt 183 nodes 5 33 45 90 1 126 crossSect 1 mat 1 location 4 16 0 0 16 +ltrspaceboundaryvoigt 253 nodes 5 99 9 63 90 126 crossSect 1 mat 1 location 4 0 16 16 22 +ltrspaceboundaryvoigt 254 nodes 5 45 9 99 90 126 crossSect 1 mat 1 location 4 0 16 0 22 +ltrspaceboundaryvoigt 255 nodes 5 9 45 99 63 126 crossSect 1 mat 1 location 4 16 0 0 16 +ltrspaceboundaryvoigt 256 nodes 5 9 45 24 90 126 crossSect 1 mat 1 location 4 16 0 22 22 +ltrspaceboundaryvoigt 257 nodes 5 1 9 24 90 126 crossSect 1 mat 1 location 4 25 16 22 22 +ltrspaceboundaryvoigt 261 nodes 5 45 9 1 63 126 crossSect 1 mat 1 location 4 0 16 16 16 +ltrspaceboundaryvoigt 287 nodes 5 33 24 9 90 126 crossSect 1 mat 1 location 4 22 22 0 22 +ltrspaceboundaryvoigt 288 nodes 5 1 33 24 9 126 crossSect 1 mat 1 location 4 22 22 22 0 +ltrspaceboundaryvoigt 290 nodes 5 33 9 24 90 126 crossSect 1 mat 1 location 4 22 14 23 22 +ltrspaceboundaryvoigt 304 nodes 5 1 33 9 24 126 crossSect 1 mat 1 location 4 23 22 14 23 +ltrspace 415 nodes 4 33 24 90 99 crossSect 1 mat 1 +ltrspaceboundaryvoigt 419 nodes 5 90 33 99 24 126 crossSect 1 mat 1 location 4 0 0 0 14 +ltrspaceboundaryvoigt 437 nodes 5 9 33 63 90 126 crossSect 1 mat 1 location 4 16 25 16 22 +ltrspaceboundaryvoigt 438 nodes 5 33 9 1 90 126 crossSect 1 mat 1 location 4 25 16 25 22 +ltrspaceboundaryvoigt 441 nodes 5 9 33 1 90 126 crossSect 1 mat 1 location 4 17 25 26 22 +ltrspaceboundaryvoigt 442 nodes 5 33 9 63 90 126 crossSect 1 mat 1 location 4 25 17 16 22 +ltrspaceboundaryvoigt 453 nodes 5 9 63 99 90 126 crossSect 1 mat 1 location 4 14 0 0 22 +ltrspaceboundaryvoigt 454 nodes 5 33 63 9 90 126 crossSect 1 mat 1 location 4 22 0 14 22 +ltrspaceboundaryvoigt 455 nodes 5 99 63 9 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundaryvoigt 456 nodes 5 63 33 9 90 126 crossSect 1 mat 1 location 4 0 22 0 22 +ltrspace 458 nodes 4 33 63 24 99 crossSect 1 mat 1 +ltrspaceboundaryvoigt 462 nodes 5 9 63 1 24 126 crossSect 1 mat 1 location 4 14 0 14 14 +ltrspaceboundaryvoigt 463 nodes 5 63 33 1 24 126 crossSect 1 mat 1 location 4 0 0 14 14 +ltrspaceboundaryvoigt 464 nodes 5 33 63 99 24 126 crossSect 1 mat 1 location 4 0 0 0 14 +ltrspace 468 nodes 4 63 45 99 9 crossSect 1 mat 1 +ltrspace 469 nodes 4 63 24 45 9 crossSect 1 mat 1 +ltrspace 470 nodes 4 24 63 45 99 crossSect 1 mat 1 +ltrspaceboundaryvoigt 474 nodes 5 99 63 45 24 126 crossSect 1 mat 1 location 4 0 0 14 14 +ltrspaceboundaryvoigt 475 nodes 5 63 9 45 24 126 crossSect 1 mat 1 location 4 0 14 14 14 +ltrspaceboundaryvoigt 476 nodes 5 63 9 99 45 126 crossSect 1 mat 1 location 4 0 14 0 14 +ltrspace 537 nodes 4 63 1 24 9 crossSect 1 mat 1 +ltrspace 538 nodes 4 63 1 33 24 crossSect 1 mat 1 +simplecs 1 +isole 1 talpha 0. d 0. e 30.e9 n 0.2 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +NodalLoad 2 loadTimeFunction 1 Components 6 1 -2.428585877 -0.285714 0. 0. 1.714285812 reference +ConstantFunction 1 f(t) 1. +set 1 nodes 1 126 +#%BEGIN_CHECK% tolerance 1e-3 +#LOADLEVEL tStep 1 value 5.8333226238e+06 +#%END_CHECK% diff --git a/tests/sm/ltrspaceboundary04.in b/tests/sm/ltrspaceboundary04.in new file mode 100644 index 000000000..386639e57 --- /dev/null +++ b/tests/sm/ltrspaceboundary04.in @@ -0,0 +1,90 @@ +ltrspaceboundary04.out +3D RVE - periodic boundary conditions with LTRSpaceBoundary elements, periodicity in x y z +StaticStructural nsteps 1 initialguess 1 nmodules 1 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 9 nelem 56 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 1 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 3 1 1 1 +node 9 coords 3 5.827886e-02 0.000000e+00 0.000000e+00 +node 24 coords 3 0.000000e+00 4.124619e-02 0.000000e+00 +node 33 coords 3 0.000000e+00 0.000000e+00 4.902652e-02 +node 45 coords 3 4.791257e-02 5.177834e-02 0.000000e+00 +node 63 coords 3 4.791257e-02 0.000000e+00 5.059616e-02 +node 90 coords 3 0.000000e+00 4.791257e-02 5.059616e-02 +node 99 coords 3 4.463697e-02 4.791257e-02 5.059616e-02 +node 126 coords 3 1.000000e-01 1.000000e-01 1.000000e-01 dofidmask 9 31 38 36 39 32 34 37 35 33 bc 9 2 2 2 2 2 2 2 2 2 +ltrspaceboundary 14 nodes 5 99 9 45 90 126 crossSect 1 mat 1 location 4 0 17 14 22 +ltrspaceboundary 15 nodes 5 9 99 63 90 126 crossSect 1 mat 1 location 4 17 0 16 22 +ltrspaceboundary 16 nodes 5 99 9 63 45 126 crossSect 1 mat 1 location 4 0 17 16 14 +ltrspaceboundary 18 nodes 5 24 99 9 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundary 53 nodes 5 24 99 45 90 126 crossSect 1 mat 1 location 4 23 0 14 22 +ltrspaceboundary 54 nodes 5 9 24 45 90 126 crossSect 1 mat 1 location 4 17 23 14 22 +ltrspaceboundary 55 nodes 5 24 9 1 90 126 crossSect 1 mat 1 location 4 23 17 26 22 +ltrspaceboundary 57 nodes 5 90 99 45 24 126 crossSect 1 mat 1 location 4 0 0 14 14 +ltrspaceboundary 58 nodes 5 9 1 63 45 126 crossSect 1 mat 1 location 4 17 17 16 14 +ltrspaceboundary 59 nodes 5 1 90 45 24 126 crossSect 1 mat 1 location 4 17 0 14 14 +ltrspaceboundary 60 nodes 5 1 99 63 45 126 crossSect 1 mat 1 location 4 17 0 16 14 +ltrspaceboundary 61 nodes 5 1 90 99 45 126 crossSect 1 mat 1 location 4 17 0 0 14 +ltrspaceboundary 72 nodes 5 45 24 99 9 126 crossSect 1 mat 1 location 4 0 22 0 0 +ltrspaceboundary 73 nodes 5 24 45 99 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundary 136 nodes 5 9 24 99 45 126 crossSect 1 mat 1 location 4 14 23 0 14 +ltrspaceboundary 140 nodes 5 24 9 99 90 126 crossSect 1 mat 1 location 4 23 14 0 22 +ltrspaceboundary 176 nodes 5 45 24 90 1 126 crossSect 1 mat 1 location 4 0 0 0 16 +ltrspace 177 nodes 4 24 45 90 99 crossSect 1 mat 1 +ltrspaceboundary 178 nodes 5 33 1 99 63 126 crossSect 1 mat 1 location 4 16 17 0 16 +ltrspaceboundary 179 nodes 5 33 1 90 99 126 crossSect 1 mat 1 location 4 16 17 0 0 +ltrspaceboundary 180 nodes 5 45 33 99 63 126 crossSect 1 mat 1 location 4 0 16 0 16 +ltrspaceboundary 181 nodes 5 33 45 1 63 126 crossSect 1 mat 1 location 4 16 0 16 16 +ltrspaceboundary 182 nodes 5 45 33 90 99 126 crossSect 1 mat 1 location 4 0 16 0 0 +ltrspaceboundary 183 nodes 5 33 45 90 1 126 crossSect 1 mat 1 location 4 16 0 0 16 +ltrspaceboundary 253 nodes 5 99 9 63 90 126 crossSect 1 mat 1 location 4 0 16 16 22 +ltrspaceboundary 254 nodes 5 45 9 99 90 126 crossSect 1 mat 1 location 4 0 16 0 22 +ltrspaceboundary 255 nodes 5 9 45 99 63 126 crossSect 1 mat 1 location 4 16 0 0 16 +ltrspaceboundary 256 nodes 5 9 45 24 90 126 crossSect 1 mat 1 location 4 16 0 22 22 +ltrspaceboundary 257 nodes 5 1 9 24 90 126 crossSect 1 mat 1 location 4 25 16 22 22 +ltrspaceboundary 261 nodes 5 45 9 1 63 126 crossSect 1 mat 1 location 4 0 16 16 16 +ltrspaceboundary 287 nodes 5 33 24 9 90 126 crossSect 1 mat 1 location 4 22 22 0 22 +ltrspaceboundary 288 nodes 5 1 33 24 9 126 crossSect 1 mat 1 location 4 22 22 22 0 +ltrspaceboundary 290 nodes 5 33 9 24 90 126 crossSect 1 mat 1 location 4 22 14 23 22 +ltrspaceboundary 304 nodes 5 1 33 9 24 126 crossSect 1 mat 1 location 4 23 22 14 23 +ltrspace 415 nodes 4 33 24 90 99 crossSect 1 mat 1 +ltrspaceboundary 419 nodes 5 90 33 99 24 126 crossSect 1 mat 1 location 4 0 0 0 14 +ltrspaceboundary 437 nodes 5 9 33 63 90 126 crossSect 1 mat 1 location 4 16 25 16 22 +ltrspaceboundary 438 nodes 5 33 9 1 90 126 crossSect 1 mat 1 location 4 25 16 25 22 +ltrspaceboundary 441 nodes 5 9 33 1 90 126 crossSect 1 mat 1 location 4 17 25 26 22 +ltrspaceboundary 442 nodes 5 33 9 63 90 126 crossSect 1 mat 1 location 4 25 17 16 22 +ltrspaceboundary 453 nodes 5 9 63 99 90 126 crossSect 1 mat 1 location 4 14 0 0 22 +ltrspaceboundary 454 nodes 5 33 63 9 90 126 crossSect 1 mat 1 location 4 22 0 14 22 +ltrspaceboundary 455 nodes 5 99 63 9 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundary 456 nodes 5 63 33 9 90 126 crossSect 1 mat 1 location 4 0 22 0 22 +ltrspace 458 nodes 4 33 63 24 99 crossSect 1 mat 1 +ltrspaceboundary 462 nodes 5 9 63 1 24 126 crossSect 1 mat 1 location 4 14 0 14 14 +ltrspaceboundary 463 nodes 5 63 33 1 24 126 crossSect 1 mat 1 location 4 0 0 14 14 +ltrspaceboundary 464 nodes 5 33 63 99 24 126 crossSect 1 mat 1 location 4 0 0 0 14 +ltrspace 468 nodes 4 63 45 99 9 crossSect 1 mat 1 +ltrspace 469 nodes 4 63 24 45 9 crossSect 1 mat 1 +ltrspace 470 nodes 4 24 63 45 99 crossSect 1 mat 1 +ltrspaceboundary 474 nodes 5 99 63 45 24 126 crossSect 1 mat 1 location 4 0 0 14 14 +ltrspaceboundary 475 nodes 5 63 9 45 24 126 crossSect 1 mat 1 location 4 0 14 14 14 +ltrspaceboundary 476 nodes 5 63 9 99 45 126 crossSect 1 mat 1 location 4 0 14 0 14 +ltrspace 537 nodes 4 63 1 24 9 crossSect 1 mat 1 +ltrspace 538 nodes 4 63 1 33 24 crossSect 1 mat 1 +simplecs 1 +isole 1 talpha 0. d 0. e 30.e9 n 0.2 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 1 dofs 9 31 38 36 39 32 34 37 35 33 values 9 0.3 0.2 0.05 0.6 -0.5 0.25 0.15 0.35 0.0 set 1 +ConstantFunction 1 f(t) 1. +set 1 nodes 1 126 + +#%BEGIN_CHECK% tolerance 1e-3 +#REACTION tStep 1 number 126 dof 31 value 5.8333333333333e+06 +#REACTION tStep 1 number 126 dof 38 value 1.0000e+07 +#REACTION tStep 1 number 126 dof 36 value 2.5000e+06 +#REACTION tStep 1 number 126 dof 39 value 1.0000e+07 +#REACTION tStep 1 number 126 dof 32 value -1.4166666666667e+07 +#REACTION tStep 1 number 126 dof 34 value 7.5000e+06 +#REACTION tStep 1 number 126 dof 37 value 2.5000e+06 +#REACTION tStep 1 number 126 dof 35 value 7.5000e+06 +#REACTION tStep 1 number 126 dof 33 value -1.6666666666667e+06 +#%END_CHECK% diff --git a/tests/sm/ltrspaceboundary05.in b/tests/sm/ltrspaceboundary05.in new file mode 100644 index 000000000..b35697358 --- /dev/null +++ b/tests/sm/ltrspaceboundary05.in @@ -0,0 +1,98 @@ +ltrspaceboundary05.out +3D RVE - periodic boundary conditions with LTRSpaceBoundaryBeam elements, periodicity in x +StaticStructural nsteps 1 initialguess 1 nmodules 1 +#vtkxmlperiodic primvars 1 1 vars 3 4 1 12 cellvars 1 46 tstep_all domain_all stype 0 +#vtkxmlperiodic ipvars 3 4 1 12 tstep_all domain_all +#gpexportmodule vars 3 4 1 12 tstep_all domain_all +#matlab tstep_all mesh data specials reactionforces integrationpoints internalvars 3 4 1 12 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 19 nelem 56 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 1 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 3 1 1 1 +node 4 coords 3 0.000000e+00 1.000000e-01 0.000000e+00 +node 5 coords 3 0.000000e+00 0.000000e+00 1.000000e-01 bc 3 0 1 0 +node 8 coords 3 0.000000e+00 1.000000e-01 1.000000e-01 +node 9 coords 3 5.827886e-02 0.000000e+00 0.000000e+00 +node 12 coords 3 5.827886e-02 1.000000e-01 0.000000e+00 +node 15 coords 3 5.827886e-02 0.000000e+00 1.000000e-01 +node 18 coords 3 5.827886e-02 1.000000e-01 1.000000e-01 +node 24 coords 3 0.000000e+00 4.124619e-02 0.000000e+00 +node 30 coords 3 0.000000e+00 4.124619e-02 1.000000e-01 +node 33 coords 3 0.000000e+00 0.000000e+00 4.902652e-02 +node 39 coords 3 0.000000e+00 1.000000e-01 4.902652e-02 +node 45 coords 3 4.791257e-02 5.177834e-02 0.000000e+00 +node 54 coords 3 4.791257e-02 5.177834e-02 1.000000e-01 +node 63 coords 3 4.791257e-02 0.000000e+00 5.059616e-02 +node 72 coords 3 4.791257e-02 1.000000e-01 5.059616e-02 +node 90 coords 3 0.000000e+00 4.791257e-02 5.059616e-02 +node 99 coords 3 4.463697e-02 4.791257e-02 5.059616e-02 +node 126 coords 3 1.000000e-01 1.000000e-01 1.000000e-01 dofidmask 3 31 37 43 bc 3 2 2 2 +ltrspaceboundarybeam 14 nodes 5 99 18 54 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundarybeam 15 nodes 5 18 99 72 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspace 16 nodes 4 99 18 72 54 crossSect 1 mat 1 +ltrspaceboundarybeam 18 nodes 5 24 99 9 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarybeam 53 nodes 5 30 99 54 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarybeam 54 nodes 5 18 30 54 90 126 crossSect 1 mat 1 location 4 0 22 0 22 +ltrspaceboundarybeam 55 nodes 5 30 18 8 90 126 crossSect 1 mat 1 location 4 22 0 22 22 +ltrspace 57 nodes 4 90 99 54 30 crossSect 1 mat 1 +ltrspace 58 nodes 4 18 8 72 54 crossSect 1 mat 1 +ltrspace 59 nodes 4 8 90 54 30 crossSect 1 mat 1 +ltrspace 60 nodes 4 8 99 72 54 crossSect 1 mat 1 +ltrspace 61 nodes 4 8 90 99 54 crossSect 1 mat 1 +ltrspaceboundarybeam 72 nodes 5 45 24 99 9 126 crossSect 1 mat 1 location 4 0 22 0 0 +ltrspaceboundarybeam 73 nodes 5 24 45 99 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarybeam 136 nodes 5 15 30 99 54 126 crossSect 1 mat 1 location 4 0 22 0 0 +ltrspaceboundarybeam 140 nodes 5 30 15 99 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspace 176 nodes 4 45 24 90 4 crossSect 1 mat 1 +ltrspace 177 nodes 4 24 45 90 99 crossSect 1 mat 1 +ltrspace 178 nodes 4 39 8 99 72 crossSect 1 mat 1 +ltrspace 179 nodes 4 39 8 90 99 crossSect 1 mat 1 +ltrspace 180 nodes 4 45 39 99 72 crossSect 1 mat 1 +ltrspace 181 nodes 4 39 45 4 72 crossSect 1 mat 1 +ltrspace 182 nodes 4 45 39 90 99 crossSect 1 mat 1 +ltrspace 183 nodes 4 39 45 90 4 crossSect 1 mat 1 +ltrspaceboundarybeam 253 nodes 5 99 12 72 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundarybeam 254 nodes 5 45 12 99 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspace 255 nodes 4 12 45 99 72 crossSect 1 mat 1 +ltrspaceboundarybeam 256 nodes 5 12 45 24 90 126 crossSect 1 mat 1 location 4 0 0 22 22 +ltrspaceboundarybeam 257 nodes 5 4 12 24 90 126 crossSect 1 mat 1 location 4 22 0 22 22 +ltrspace 261 nodes 4 45 12 4 72 crossSect 1 mat 1 +ltrspaceboundarybeam 287 nodes 5 33 24 9 90 126 crossSect 1 mat 1 location 4 22 22 0 22 +ltrspaceboundarybeam 288 nodes 5 1 33 24 9 126 crossSect 1 mat 1 location 4 22 22 22 0 +ltrspaceboundarybeam 290 nodes 5 33 15 30 90 126 crossSect 1 mat 1 location 4 22 0 22 22 +ltrspaceboundarybeam 304 nodes 5 5 33 15 30 126 crossSect 1 mat 1 location 4 22 22 0 22 +ltrspace 415 nodes 4 33 24 90 99 crossSect 1 mat 1 +ltrspace 419 nodes 4 90 33 99 30 crossSect 1 mat 1 +ltrspaceboundarybeam 437 nodes 5 12 39 72 90 126 crossSect 1 mat 1 location 4 0 22 0 22 +ltrspaceboundarybeam 438 nodes 5 39 12 4 90 126 crossSect 1 mat 1 location 4 22 0 22 22 +ltrspaceboundarybeam 441 nodes 5 18 39 8 90 126 crossSect 1 mat 1 location 4 0 22 22 22 +ltrspaceboundarybeam 442 nodes 5 39 18 72 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarybeam 453 nodes 5 15 63 99 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundarybeam 454 nodes 5 33 63 15 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundarybeam 455 nodes 5 99 63 9 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundarybeam 456 nodes 5 63 33 9 90 126 crossSect 1 mat 1 location 4 0 22 0 22 +ltrspace 458 nodes 4 33 63 24 99 crossSect 1 mat 1 +ltrspace 462 nodes 4 15 63 5 30 crossSect 1 mat 1 +ltrspace 463 nodes 4 63 33 5 30 crossSect 1 mat 1 +ltrspace 464 nodes 4 33 63 99 30 crossSect 1 mat 1 +ltrspace 468 nodes 4 63 45 99 9 crossSect 1 mat 1 +ltrspace 469 nodes 4 63 24 45 9 crossSect 1 mat 1 +ltrspace 470 nodes 4 24 63 45 99 crossSect 1 mat 1 +ltrspace 474 nodes 4 99 63 54 30 crossSect 1 mat 1 +ltrspace 475 nodes 4 63 15 54 30 crossSect 1 mat 1 +ltrspace 476 nodes 4 63 15 99 54 crossSect 1 mat 1 +ltrspace 537 nodes 4 63 1 24 9 crossSect 1 mat 1 +ltrspace 538 nodes 4 63 1 33 24 crossSect 1 mat 1 +simplecs 1 +isole 1 talpha 0. d 0. e 30.e9 n 0.2 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 1 dofs 3 31 37 43 values 3 0.3 0 1 set 1 +ConstantFunction 1 f(t) 1. +set 1 nodes 1 126 + +#%BEGIN_CHECK% tolerance 1e-2 +#REACTION tStep 1 number 126 dof 31 value 7.5000e+06 +#REACTION tStep 1 number 126 dof 43 value -3.15069385e+05 +##TIME +#%END_CHECK% diff --git a/tests/sm/ltrspaceboundary06.in b/tests/sm/ltrspaceboundary06.in new file mode 100644 index 000000000..41630578a --- /dev/null +++ b/tests/sm/ltrspaceboundary06.in @@ -0,0 +1,94 @@ +ltrspaceboundary06.out +3D RVE - periodic boundary conditions with LTRSpaceBoundaryPlate elements, periodicity in x y +StaticStructural nsteps 1 initialguess 1 nmodules 1 lstype 0 smtype 1 +#vtkxmlperiodic primvars 1 1 vars 3 4 1 12 cellvars 1 46 tstep_all domain_all stype 0 +#vtkxmlperiodic ipvars 3 4 1 12 tstep_all domain_all +#gpexportmodule vars 3 4 1 12 tstep_all domain_all +#matlab tstep_all mesh data specials reactionforces integrationpoints internalvars 3 4 1 12 +errorcheck +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 13 nelem 56 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 1 +node 1 coords 3 0.000000e+00 0.000000e+00 0.000000e+00 bc 3 1 1 1 +node 5 coords 3 0.000000e+00 0.000000e+00 1.000000e-01 +node 9 coords 3 5.827886e-02 0.000000e+00 0.000000e+00 +node 15 coords 3 5.827886e-02 0.000000e+00 1.000000e-01 +node 24 coords 3 0.000000e+00 4.124619e-02 0.000000e+00 +node 30 coords 3 0.000000e+00 4.124619e-02 1.000000e-01 +node 33 coords 3 0.000000e+00 0.000000e+00 4.902652e-02 +node 45 coords 3 4.791257e-02 5.177834e-02 0.000000e+00 +node 54 coords 3 4.791257e-02 5.177834e-02 1.000000e-01 +node 63 coords 3 4.791257e-02 0.000000e+00 5.059616e-02 +node 90 coords 3 0.000000e+00 4.791257e-02 5.059616e-02 +node 99 coords 3 4.463697e-02 4.791257e-02 5.059616e-02 +node 126 coords 3 1.000000e-01 1.000000e-01 1.000000e-01 dofidmask 10 31 38 39 32 37 35 43 44 49 50 bc 10 2 2 2 2 2 2 2 2 2 2 +ltrspaceboundaryplate 14 nodes 5 99 15 54 90 126 crossSect 1 mat 1 location 4 0 16 0 22 +ltrspaceboundaryplate 15 nodes 5 15 99 63 90 126 crossSect 1 mat 1 location 4 16 0 16 22 +ltrspaceboundaryplate 16 nodes 5 99 15 63 54 126 crossSect 1 mat 1 location 4 0 16 16 0 +ltrspaceboundaryplate 18 nodes 5 24 99 9 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundaryplate 53 nodes 5 30 99 54 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundaryplate 54 nodes 5 15 30 54 90 126 crossSect 1 mat 1 location 4 16 22 0 22 +ltrspaceboundaryplate 55 nodes 5 30 15 5 90 126 crossSect 1 mat 1 location 4 22 16 25 22 +ltrspace 57 nodes 4 90 99 54 30 crossSect 1 mat 1 +ltrspaceboundaryplate 58 nodes 5 15 5 63 54 126 crossSect 1 mat 1 location 4 16 16 16 0 +ltrspaceboundaryplate 59 nodes 5 5 90 54 30 126 crossSect 1 mat 1 location 4 16 0 0 0 +ltrspaceboundaryplate 60 nodes 5 5 99 63 54 126 crossSect 1 mat 1 location 4 16 0 16 0 +ltrspaceboundaryplate 61 nodes 5 5 90 99 54 126 crossSect 1 mat 1 location 4 16 0 0 0 +ltrspaceboundaryplate 72 nodes 5 45 24 99 9 126 crossSect 1 mat 1 location 4 0 22 0 0 +ltrspaceboundaryplate 73 nodes 5 24 45 99 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundaryplate 136 nodes 5 15 30 99 54 126 crossSect 1 mat 1 location 4 0 22 0 0 +ltrspaceboundaryplate 140 nodes 5 30 15 99 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundaryplate 176 nodes 5 45 24 90 1 126 crossSect 1 mat 1 location 4 0 0 0 16 +ltrspace 177 nodes 4 24 45 90 99 crossSect 1 mat 1 +ltrspaceboundaryplate 178 nodes 5 33 5 99 63 126 crossSect 1 mat 1 location 4 16 16 0 16 +ltrspaceboundaryplate 179 nodes 5 33 5 90 99 126 crossSect 1 mat 1 location 4 16 16 0 0 +ltrspaceboundaryplate 180 nodes 5 45 33 99 63 126 crossSect 1 mat 1 location 4 0 16 0 16 +ltrspaceboundaryplate 181 nodes 5 33 45 1 63 126 crossSect 1 mat 1 location 4 16 0 16 16 +ltrspaceboundaryplate 182 nodes 5 45 33 90 99 126 crossSect 1 mat 1 location 4 0 16 0 0 +ltrspaceboundaryplate 183 nodes 5 33 45 90 1 126 crossSect 1 mat 1 location 4 16 0 0 16 +ltrspaceboundaryplate 253 nodes 5 99 9 63 90 126 crossSect 1 mat 1 location 4 0 16 16 22 +ltrspaceboundaryplate 254 nodes 5 45 9 99 90 126 crossSect 1 mat 1 location 4 0 16 0 22 +ltrspaceboundaryplate 255 nodes 5 9 45 99 63 126 crossSect 1 mat 1 location 4 16 0 0 16 +ltrspaceboundaryplate 256 nodes 5 9 45 24 90 126 crossSect 1 mat 1 location 4 16 0 22 22 +ltrspaceboundaryplate 257 nodes 5 1 9 24 90 126 crossSect 1 mat 1 location 4 25 16 22 22 +ltrspaceboundaryplate 261 nodes 5 45 9 1 63 126 crossSect 1 mat 1 location 4 0 16 16 16 +ltrspaceboundaryplate 287 nodes 5 33 24 9 90 126 crossSect 1 mat 1 location 4 22 22 0 22 +ltrspaceboundaryplate 288 nodes 5 1 33 24 9 126 crossSect 1 mat 1 location 4 22 22 22 0 +ltrspaceboundaryplate 290 nodes 5 33 15 30 90 126 crossSect 1 mat 1 location 4 22 0 22 22 +ltrspaceboundaryplate 304 nodes 5 5 33 15 30 126 crossSect 1 mat 1 location 4 22 22 0 22 +ltrspace 415 nodes 4 33 24 90 99 crossSect 1 mat 1 +ltrspace 419 nodes 4 90 33 99 30 crossSect 1 mat 1 +ltrspaceboundaryplate 437 nodes 5 9 33 63 90 126 crossSect 1 mat 1 location 4 16 25 16 22 +ltrspaceboundaryplate 438 nodes 5 33 9 1 90 126 crossSect 1 mat 1 location 4 25 16 25 22 +ltrspaceboundaryplate 441 nodes 5 15 33 5 90 126 crossSect 1 mat 1 location 4 16 25 25 22 +ltrspaceboundaryplate 442 nodes 5 33 15 63 90 126 crossSect 1 mat 1 location 4 25 16 16 22 +ltrspaceboundaryplate 453 nodes 5 15 63 99 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundaryplate 454 nodes 5 33 63 15 90 126 crossSect 1 mat 1 location 4 22 0 0 22 +ltrspaceboundaryplate 455 nodes 5 99 63 9 90 126 crossSect 1 mat 1 location 4 0 0 0 22 +ltrspaceboundaryplate 456 nodes 5 63 33 9 90 126 crossSect 1 mat 1 location 4 0 22 0 22 +ltrspace 458 nodes 4 33 63 24 99 crossSect 1 mat 1 +ltrspace 462 nodes 4 15 63 5 30 crossSect 1 mat 1 +ltrspace 463 nodes 4 63 33 5 30 crossSect 1 mat 1 +ltrspace 464 nodes 4 33 63 99 30 crossSect 1 mat 1 +ltrspace 468 nodes 4 63 45 99 9 crossSect 1 mat 1 +ltrspace 469 nodes 4 63 24 45 9 crossSect 1 mat 1 +ltrspace 470 nodes 4 24 63 45 99 crossSect 1 mat 1 +ltrspace 474 nodes 4 99 63 54 30 crossSect 1 mat 1 +ltrspace 475 nodes 4 63 15 54 30 crossSect 1 mat 1 +ltrspace 476 nodes 4 63 15 99 54 crossSect 1 mat 1 +ltrspace 537 nodes 4 63 1 24 9 crossSect 1 mat 1 +ltrspace 538 nodes 4 63 1 33 24 crossSect 1 mat 1 +simplecs 1 +isole 1 talpha 0. d 0. e 30.e9 n 0.2 +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 1 dofs 10 31 38 39 32 37 35 43 44 49 50 values 10 0.3 0 0 -0.5 0 0 0.5 -1 0 0 set 1 +ConstantFunction 1 f(t) 1. +set 1 nodes 1 126 + +#%BEGIN_CHECK% tolerance 1e-2 +#REACTION tStep 1 number 126 dof 31 value 5.78125e+06 +#REACTION tStep 1 number 126 dof 32 value -1.234375e+07 +#REACTION tStep 1 number 126 dof 43 value -2.62941272e+05 +#REACTION tStep 1 number 126 dof 44 value 5.51449785e+05 +##TIME +#%END_CHECK% diff --git a/tests/sm/mooneyrivlin1.in b/tests/sm/mooneyrivlin1.in new file mode 100644 index 000000000..a8dc12f94 --- /dev/null +++ b/tests/sm/mooneyrivlin1.in @@ -0,0 +1,55 @@ +testMooneyRivlin1.out +test of Neo-Hookean Material usign Mooney-Rivlin material with C_1 = 10, C_2 = 0, and K = 0. See ogden1.in for the same case modeled by compressible Ogden material with C_2 = 0 +########################################### +NonLinearStatic nsteps 1 renumber 1 nmodules 1 controllmode 1 rtolv 1.e-11 stiffMode 0 manrmsteps 1 maxiter 10 +errorcheck +########################################### +Domain 3d +OutputManager tstep_all dofman_all element_all +################################################################### +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 2 nset 3 +#########################---Nodes---############################### +node 1 coords 2 0.0 0.0 +node 2 coords 2 1.0 0.0 +node 3 coords 2 1.0 1.0 +node 4 coords 2 0.0 1.0 +########################---Elements---############################# +quad1PlaneStrain 1 nodes 4 1 2 3 4 mat 1 crossSect 1 nlgeo 1 +####################---Cross-Sections---########################### +SimpleCS 1 thick 1.0 set 1 material 1 +#######################---Materials---############################# +MooneyRivlinCompressibleMat 1 d 1 C1 10 C2 0 K 0 +#######################---Boundary cond.---######################## +BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0 0 set 2 +BoundaryCondition 2 loadTimeFunction 2 dofs 1 2 values 1 0.3 set 3 +#######################---Time functions---######################## +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 nPoints 3 t 3 -1 0. 2000. f(t) 3 0. 1 2001. +###########################---Sets---############################## +Set 1 elementranges {(1 1)} +Set 2 nodes 2 1 2 +Set 3 nodes 2 3 4 +################################################################### +#%BEGIN_CHECK% tolerance 1.e-6 +## check reactions +#REACTION tStep 1 number 1 dof 1 value 1.32687871e+00 +#REACTION tStep 1 number 1 dof 2 value -2.34573944e+00 +#REACTION tStep 1 number 2 dof 1 value -1.32687871e+00 +#REACTION tStep 1 number 2 dof 2 value -2.34573944e+00 +#REACTION tStep 1 number 3 dof 2 value 2.34573944e+00 +#REACTION tStep 1 number 4 dof 2 value 2.34573944e+00 +################################################################### +## check all nodes +#NODE tStep 1 number 3 dof 1 unknown d value 1.02869813e-01 +#NODE tStep 1 number 4 dof 1 unknown d value -1.02869813e-01 +## check element deformation gradient +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 1 value 1.16226173e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 2 value 1.3000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 6 value 5.9392e-02 +## check element first Piola-Kirchhoff stress +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 1 value 3.5622e-02 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 2 value 3.99442062e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 3 value -5.28772644e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 6 value 9.0211e-01 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 9 value 8.04901071e-01 +#%END_CHECK% diff --git a/tests/sm/mooneyrivlin2.in b/tests/sm/mooneyrivlin2.in new file mode 100644 index 000000000..42c447612 --- /dev/null +++ b/tests/sm/mooneyrivlin2.in @@ -0,0 +1,55 @@ +testMooneyRivlin2.out +test of Mooney-Rivlin material with C_1 = 10, C_2 = 10, and K = 0. See ogden2.in for the same case modeled by compressible Ogden material with alpha_1 = 2, alpha_2 = -2, mu_1 = 20, and mu_2 = -20. +########################################### +NonLinearStatic nsteps 1 renumber 1 nmodules 1 controllmode 1 rtolv 1.e-11 stiffMode 0 manrmsteps 1 maxiter 10 +errorcheck +########################################### +Domain 3d +OutputManager tstep_all dofman_all element_all +################################################################### +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 2 nset 3 +#########################---Nodes---############################### +node 1 coords 2 0.0 0.0 +node 2 coords 2 1.0 0.0 +node 3 coords 2 1.0 1.0 +node 4 coords 2 0.0 1.0 +########################---Elements---############################# +quad1PlaneStrain 1 nodes 4 1 2 3 4 mat 1 crossSect 1 nlgeo 1 +####################---Cross-Sections---########################### +SimpleCS 1 thick 1.0 set 1 material 1 +#######################---Materials---############################# +MooneyRivlinCompressibleMat 1 d 1 C1 10 C2 10 K 0 +#######################---Boundary cond.---######################## +BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0 0 set 2 +BoundaryCondition 2 loadTimeFunction 2 dofs 1 2 values 1 0.3 set 3 +#######################---Time functions---######################## +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 nPoints 3 t 3 -1 0. 2000. f(t) 3 0. 1 2001. +###########################---Sets---############################## +Set 1 elementranges {(1 1)} +Set 2 nodes 2 1 2 +Set 3 nodes 2 3 4 +################################################################### +#%BEGIN_CHECK% tolerance 1.e-6 +## check reactions +#REACTION tStep 1 number 1 dof 1 value 2.33792828e+00 +#REACTION tStep 1 number 1 dof 2 value -4.52948909e+00 +#REACTION tStep 1 number 2 dof 1 value -2.33792828e+00 +#REACTION tStep 1 number 2 dof 2 value -4.52948909e+00 +#REACTION tStep 1 number 3 dof 2 value 4.52948909e+00 +#REACTION tStep 1 number 4 dof 2 value 4.52948909e+00 +################################################################### +## check all nodes +#NODE tStep 1 number 3 dof 1 unknown d value 9.23697895e-02 +#NODE tStep 1 number 4 dof 1 unknown d value -9.23697895e-02 +## check element deformation gradient +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 1 value 1.14569951e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 2 value 1.3000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 6 value 5.33297229e-02 +## check element first Piola-Kirchhoff stress +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 1 value 1.95440922e-01 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 2 value 8.03710241e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 3 value -1.07492050e+01 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 6 value 1.44488479e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 9 value 1.26536999e+00 +#%END_CHECK% diff --git a/tests/sm/nldeidynamic1.in b/tests/sm/nldeidynamic1.in new file mode 100644 index 000000000..f19e6b35e --- /dev/null +++ b/tests/sm/nldeidynamic1.in @@ -0,0 +1,23 @@ +nldeidynamic1.out +truss to test nldeidynamic +NlDEIDynamic nsteps 1 nmodules 1 contextOutputStep 1000000 dumpcoef 0. deltat 0.0001 reduct 0.8 profileopt 1 +errorcheck +domain 3d +OutputManager tstep_all dofman_output { 1 3 } +ndofman 3 nelem 2 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 2 +node 1 coords 3 5.000000e-02 5.000000e-02 0.000000e+00 bc 3 1 1 1 +node 2 coords 3 5.000000e-02 5.000000e-02 2.000000e-02 +node 3 coords 3 5.000000e-02 5.000000e-02 4.000000e-02 bc 3 1 1 2 +truss3d 1 nodes 2 1 2 crossSect 1 mat 1 +truss3d 2 nodes 2 2 3 crossSect 1 mat 1 +SimpleCS 1 area 2.0106e-4 +isole 1 d 7600 n 0.2 e 200.00e9 talpha 0. +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0.0 +BoundaryCondition 2 loadTimeFunction 2 prescribedvalue 0.00015 +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 t 2 0. 0.1 f(t) 2 0.0 1.0 + +#%BEGIN_CHECK% +#NODE tStep 22 number 3 dof 3 unknown d value 6.61634340e-09 tolerance 1.e-12 +#REACTION tStep 22 number 1 dof 3 value 1.3303e+01 tolerance 1.e-3 +#%END_CHECK% \ No newline at end of file diff --git a/tests/sm/nlstatic01.in b/tests/sm/nlstatic01.in new file mode 100644 index 000000000..5b3d63725 --- /dev/null +++ b/tests/sm/nlstatic01.in @@ -0,0 +1,34 @@ +nlstatic01.out +Test of LIbeam2d elements -> simply supported beam +StaticStructural nsteps 1 solverType "calm" stepLength 100 minStepLength 100 rtolf 1e-4 Psi 1 nmodules 1 +errorcheck +domain 2dBeam +OutputManager tstep_all dofman_all element_all +ndofman 3 nelem 2 ncrosssect 1 nmat 1 nbc 4 nic 0 nltf 1 nset 5 +node 1 coords 3 0. 0 0. +node 2 coords 3 5. 0 0. +node 3 coords 3 10. 0 0. +Beam2d 1 nodes 2 1 2 nip 4 +Beam2d 2 nodes 2 2 3 nip 4 +SimpleCS 1 area 0.3 Iy 2.25e-3 beamshearcoeff 1.e18 thick 0.3 material 1 set 1 +ISoLE 1 E 30.0e9 n 0.25 tAlpha 0.000012 d 0.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 3 values 2 0 0 set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 3 values 1 0 set 3 +ConstantEdgeLoad 3 loadTimeFunction 1 Components 3 0 100 0 loadtype 3 set 4 reference +ConstantEdgeLoad 4 loadTimeFunction 1 Components 3 0 100 0 loadtype 3 set 5 reference +ConstantFunction 1 f(t) 1.0 +Set 1 elementranges {(1 2)} +Set 2 nodes 1 1 +set 3 nodes 1 3 +Set 4 elementedges 2 1 1 +Set 5 elementedges 2 2 1 +# +#%BEGIN_CHECK% tolerance 1.e-6 +#LOADLEVEL tStep 1 value 1.723100e-01 +## check reactions +#REACTION tStep 1 number 1 dof 3 value -8.61549790e+01 +#REACTION tStep 1 number 3 dof 3 value -8.61549790e+01 +# +#NODE tStep 1 number 2 dof 3 unknown d value 3.32388036e-05 +# +#%END_CHECK% diff --git a/tests/sm/ogden1.in b/tests/sm/ogden1.in new file mode 100644 index 000000000..c02d6002a --- /dev/null +++ b/tests/sm/ogden1.in @@ -0,0 +1,55 @@ +testOgden1.out +test of Neo-Hookean Material usign Ogden material with alpha = 2, mu = 20, and K = 0. See thest mooneyrivlin1 for the same case modeled by compressible Mooney-Rivlin with C_2 = 0 +########################################### +NonLinearStatic nsteps 1 renumber 1 nmodules 1 controllmode 1 rtolv 1.e-11 stiffMode 0 manrmsteps 1 maxiter 10 +errorcheck +########################################### +Domain 3d +OutputManager tstep_all dofman_all element_all +################################################################### +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 2 nset 3 +#########################---Nodes---############################### +node 1 coords 2 0.0 0.0 +node 2 coords 2 1.0 0.0 +node 3 coords 2 1.0 1.0 +node 4 coords 2 0.0 1.0 +########################---Elements---############################# +quad1PlaneStrain 1 nodes 4 1 2 3 4 mat 1 crossSect 1 nlgeo 1 +####################---Cross-Sections---########################### +SimpleCS 1 thick 1.0 set 1 material 1 +#######################---Materials---############################# +OgdenCompressibleMat 1 d 1 alpha 1 2 mu 1 20 K 0 +#######################---Boundary cond.---######################## +BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0 0 set 2 +BoundaryCondition 2 loadTimeFunction 2 dofs 1 2 values 1 0.3 set 3 +#######################---Time functions---######################## +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 nPoints 3 t 3 -1 0. 2000. f(t) 3 0. 1 2001. +###########################---Sets---############################## +Set 1 elementranges {(1 1)} +Set 2 nodes 2 1 2 +Set 3 nodes 2 3 4 +################################################################### +#%BEGIN_CHECK% tolerance 1.e-6 +## check reactions +#REACTION tStep 1 number 1 dof 1 value 1.32687871e+00 +#REACTION tStep 1 number 1 dof 2 value -2.34573944e+00 +#REACTION tStep 1 number 2 dof 1 value -1.32687871e+00 +#REACTION tStep 1 number 2 dof 2 value -2.34573944e+00 +#REACTION tStep 1 number 3 dof 2 value 2.34573944e+00 +#REACTION tStep 1 number 4 dof 2 value 2.34573944e+00 +################################################################### +## check all nodes +#NODE tStep 1 number 3 dof 1 unknown d value 1.02869813e-01 +#NODE tStep 1 number 4 dof 1 unknown d value -1.02869813e-01 +## check element deformation gradient +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 1 value 1.16226173e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 2 value 1.3000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 6 value 5.9392e-02 +## check element first Piola-Kirchhoff stress +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 1 value 3.5622e-02 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 2 value 3.99442062e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 3 value -5.28772644e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 6 value 9.0211e-01 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 9 value 8.04901071e-01 +#%END_CHECK% diff --git a/tests/sm/ogden2.in b/tests/sm/ogden2.in new file mode 100644 index 000000000..88e19a202 --- /dev/null +++ b/tests/sm/ogden2.in @@ -0,0 +1,55 @@ +testOgden1.out +Ogden model with alpha_1 = 2, alpha_2 = -2, mu_1 = 20, and mu_2 = -20, K = 0. This setting of material parametes corresponds to the Mooney-Rivlin material with C_1 = 10, C_2 = 10, and K = 0. See thest mooneyrivlin1 for the same case. +########################################### +NonLinearStatic nsteps 1 renumber 1 nmodules 1 controllmode 1 rtolv 1.e-11 stiffMode 0 manrmsteps 1 maxiter 10 +errorcheck +########################################### +Domain 3d +OutputManager tstep_all dofman_all element_all +################################################################### +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 2 nset 3 +#########################---Nodes---############################### +node 1 coords 2 0.0 0.0 +node 2 coords 2 1.0 0.0 +node 3 coords 2 1.0 1.0 +node 4 coords 2 0.0 1.0 +########################---Elements---############################# +quad1PlaneStrain 1 nodes 4 1 2 3 4 mat 1 crossSect 1 nlgeo 1 +####################---Cross-Sections---########################### +SimpleCS 1 thick 1.0 set 1 material 1 +#######################---Materials---############################# +OgdenCompressibleMat 1 d 1 alpha 2 2 -2 mu 2 20 -20 K 0 +#######################---Boundary cond.---######################## +BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0 0 set 2 +BoundaryCondition 2 loadTimeFunction 2 dofs 1 2 values 1 0.3 set 3 +#######################---Time functions---######################## +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 nPoints 3 t 3 -1 0. 2000. f(t) 3 0. 1 2001. +###########################---Sets---############################## +Set 1 elementranges {(1 1)} +Set 2 nodes 2 1 2 +Set 3 nodes 2 3 4 +################################################################### +#%BEGIN_CHECK% tolerance 1.e-6 +## check reactions +#REACTION tStep 1 number 1 dof 1 value 2.33792828e+00 +#REACTION tStep 1 number 1 dof 2 value -4.52948909e+00 +#REACTION tStep 1 number 2 dof 1 value -2.33792828e+00 +#REACTION tStep 1 number 2 dof 2 value -4.52948909e+00 +#REACTION tStep 1 number 3 dof 2 value 4.52948909e+00 +#REACTION tStep 1 number 4 dof 2 value 4.52948909e+00 +################################################################### +## check all nodes +#NODE tStep 1 number 3 dof 1 unknown d value 9.23697895e-02 +#NODE tStep 1 number 4 dof 1 unknown d value -9.23697895e-02 +## check element deformation gradient +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 1 value 1.14569951e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 2 value 1.3000e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 91 component 6 value 5.33297229e-02 +## check element first Piola-Kirchhoff stress +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 1 value 1.95440922e-01 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 2 value 8.03710241e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 3 value -1.07492050e+01 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 6 value 1.44488479e+00 +#ELEMENT tStep 1 number 1 gp 1 keyword 92 component 9 value 1.26536999e+00 +#%END_CHECK% diff --git a/tests/sm/patch101.in b/tests/sm/patch101.in index 9136d7ac9..cc49a3944 100644 --- a/tests/sm/patch101.in +++ b/tests/sm/patch101.in @@ -1,7 +1,8 @@ patch101.out Patch test of PlaneStress2d elements -> pure compression in y direction -StaticStructural nsteps 1 nmodules 1 +StaticStructural nsteps 1 nmodules 2 errorcheck +hom tstep_all ists 2 1 4 strain_energy domain 2dPlaneStress OutputManager tstep_all dofman_all element_all ndofman 8 nelem 5 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 4 diff --git a/tests/sm/patch103.in b/tests/sm/patch103.in index a314d32c4..b0d5145cf 100644 --- a/tests/sm/patch103.in +++ b/tests/sm/patch103.in @@ -1,7 +1,8 @@ patch103.out Patch test of PlaneStress2d elements -> thermal load -StaticStructural nsteps 1 nmodules 1 +StaticStructural nsteps 1 nmodules 2 errorcheck +hom tstep_all ists 2 1 4 strain_energy domain 2dPlaneStress OutputManager tstep_all dofman_all element_all ndofman 6 nelem 2 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 3 diff --git a/tests/sm/patch106.in b/tests/sm/patch106.in index ba135a835..44686335b 100644 --- a/tests/sm/patch106.in +++ b/tests/sm/patch106.in @@ -22,7 +22,7 @@ SimpleCS 1 thick 0.15 material 1 set 1 IsoLE 1 d 0. E 15.0 n 0.25 tAlpha 0.000012 BoundaryCondition 1 loadTimeFunction 1 dofs 1 2 values 1 0 set 1 BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0 set 2 -ConstantEdgeLoad 3 loadTimeFunction 1 dofs 2 1 2 Components 2 0.0 1.25 loadType 3 csType 1 set 0 +ConstantEdgeLoad 3 loadTimeFunction 1 dofs 2 1 2 Components 2 0.0 -1.25 loadType 3 csType 1 set 0 ConstantFunction 1 f(t) 1.0 Set 1 elementranges {(1 5)} Set 2 nodes 2 1 2 diff --git a/tests/sm/patch130.in b/tests/sm/patch130.in index e7547a96b..5831a8c36 100644 --- a/tests/sm/patch130.in +++ b/tests/sm/patch130.in @@ -2,7 +2,7 @@ patch130.out Patch test of TrPlaneStress2d elements -> pure compression StaticStructural nsteps 1 nmodules 1 errorcheck -#hom tstep_all +#hom tstep_all ists 2 1 4 strain_energy regionsets 1 1 domain 2dPlaneStress OutputManager tstep_all dofman_all element_all ndofman 5 nelem 4 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 3 diff --git a/tests/sm/patch140.in b/tests/sm/patch140.in index f595833bd..933cf2022 100644 --- a/tests/sm/patch140.in +++ b/tests/sm/patch140.in @@ -2,7 +2,7 @@ patch140.out Patch test of QTrPlStr elements -> pure compression StaticStructural nsteps 1 nmodules 1 errorcheck -#vtkxml tstep_all domain_all primvars 1 1 vars 2 1 4 stype 2 +#vtkxml tstep_all domain_all externalforces 1 1 primvars 1 1 vars 2 1 4 stype 2 domain 2dPlaneStress2D OutputManager tstep_all dofman_all element_all ndofman 13 nelem 4 ncrosssect 1 nmat 1 nbc 4 nic 0 nltf 1 nset 4 diff --git a/tests/sm/patch_mitc4.in b/tests/sm/patch_mitc4.in index eccbd02b4..dd94d0abc 100644 --- a/tests/sm/patch_mitc4.in +++ b/tests/sm/patch_mitc4.in @@ -118,14 +118,14 @@ Set 8 nodes 5 23 24 25 26 27 #ELEMENT tStep 1 number 5 gp 7 keyword 1 component 1 value 4.3301e+02 #ELEMENT tStep 1 number 5 gp 8 keyword 1 component 1 value -4.3301e+02 # -#ELEMENT tStep 1 number 5 gp 1 keyword 1 component 6 value 0 -#ELEMENT tStep 1 number 5 gp 2 keyword 1 component 6 value 0 -#ELEMENT tStep 1 number 5 gp 3 keyword 1 component 6 value 0 -#ELEMENT tStep 1 number 5 gp 4 keyword 1 component 6 value 0 -#ELEMENT tStep 1 number 5 gp 5 keyword 1 component 6 value 0 -#ELEMENT tStep 1 number 5 gp 6 keyword 1 component 6 value 0 -#ELEMENT tStep 1 number 5 gp 7 keyword 1 component 6 value 0 -#ELEMENT tStep 1 number 5 gp 8 keyword 1 component 6 value 0 +#ELEMENT tStep 1 number 5 gp 1 keyword 1 component 4 value 0 +#ELEMENT tStep 1 number 5 gp 2 keyword 1 component 4 value 0 +#ELEMENT tStep 1 number 5 gp 3 keyword 1 component 4 value 0 +#ELEMENT tStep 1 number 5 gp 4 keyword 1 component 4 value 0 +#ELEMENT tStep 1 number 5 gp 5 keyword 1 component 4 value 0 +#ELEMENT tStep 1 number 5 gp 6 keyword 1 component 4 value 0 +#ELEMENT tStep 1 number 5 gp 7 keyword 1 component 4 value 0 +#ELEMENT tStep 1 number 5 gp 8 keyword 1 component 4 value 0 ## ## ## pure shear @@ -135,14 +135,14 @@ Set 8 nodes 5 23 24 25 26 27 #NODE tStep 1 number 17 dof 3 unknown d value 1.66666667e+01 #NODE tStep 1 number 18 dof 3 unknown d value 1.66666667e+01 ## -#ELEMENT tStep 1 number 15 gp 1 keyword 1 component 4 value 2.5e+01 -#ELEMENT tStep 1 number 15 gp 2 keyword 1 component 4 value 2.5e+01 -#ELEMENT tStep 1 number 15 gp 3 keyword 1 component 4 value 2.5e+01 -#ELEMENT tStep 1 number 15 gp 4 keyword 1 component 4 value 2.5e+01 -#ELEMENT tStep 1 number 15 gp 5 keyword 1 component 4 value 2.5e+01 -#ELEMENT tStep 1 number 15 gp 6 keyword 1 component 4 value 2.5e+01 -#ELEMENT tStep 1 number 15 gp 7 keyword 1 component 4 value 2.5e+01 -#ELEMENT tStep 1 number 15 gp 8 keyword 1 component 4 value 2.5e+01 +#ELEMENT tStep 1 number 15 gp 1 keyword 1 component 5 value 2.5e+01 +#ELEMENT tStep 1 number 15 gp 2 keyword 1 component 5 value 2.5e+01 +#ELEMENT tStep 1 number 15 gp 3 keyword 1 component 5 value 2.5e+01 +#ELEMENT tStep 1 number 15 gp 4 keyword 1 component 5 value 2.5e+01 +#ELEMENT tStep 1 number 15 gp 5 keyword 1 component 5 value 2.5e+01 +#ELEMENT tStep 1 number 15 gp 6 keyword 1 component 5 value 2.5e+01 +#ELEMENT tStep 1 number 15 gp 7 keyword 1 component 5 value 2.5e+01 +#ELEMENT tStep 1 number 15 gp 8 keyword 1 component 5 value 2.5e+01 # #ELEMENT tStep 1 number 15 gp 1 keyword 4 component 5 value 4.16666667e+00 #ELEMENT tStep 1 number 15 gp 2 keyword 4 component 5 value 4.16666667e+00 diff --git a/tests/sm/pdelta01.in b/tests/sm/pdelta01.in new file mode 100644 index 000000000..b98c3403f --- /dev/null +++ b/tests/sm/pdelta01.in @@ -0,0 +1,32 @@ +pdelta01.out +pdelta analysis of simple cantilever beam +#only momentum influence to the displacements is taken into account +#beamShearCoeff is artificially enlarged. +pdelta nsteps 1 nmodules 1 rtolv 1.e-3 maxiter 1 +errorcheck +domain 2dBeam +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 3 +node 1 coords 3 0. 0. 0. +node 2 coords 3 10. 0. 0. +Beam2d 1 nodes 2 1 2 +SimpleCS 1 area 1.e8 Iy 8.33e-6 beamShearCoeff 1.e18 thick 0.54 material 1 set 1 +IsoLE 1 d 1. E 205000000000 n 0.2 tAlpha 1.2e-5 +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 3 5 values 3 0.0 0.0 0.0 set 2 +NodalLoad 2 loadTimeFunction 1 dofs 3 1 3 5 Components 3 -50000.0 2000. 0. set 3 +PeakFunction 1 t 1.0 f(t) 1. +Set 1 elements 1 1 +Set 2 nodes 1 1 +Set 3 nodes 1 2 +# +# exact solution +# +#%BEGIN_CHECK% tolerance 5.e-3 +#NODE tStep 1 number 2 dof 3 unknown d value 7.71430584e-01 +#REACTION tStep 1 number 1 dof 1 value 5.0000e+04 +#REACTION tStep 1 number 1 dof 3 value -3.9520e+03 +#REACTION tStep 1 number 1 dof 5 value 3.9520e+04 +#%END_CHECK% + + + diff --git a/tests/sm/pdelta02.in b/tests/sm/pdelta02.in new file mode 100644 index 000000000..60bc482fc --- /dev/null +++ b/tests/sm/pdelta02.in @@ -0,0 +1,32 @@ +pdelta02.out +pdelta analysis of simple cantilever beam +#only momentum influence to the displacements is taken into account +#beamShearCoeff is artificially enlarged. +pdelta nsteps 1 nmodules 1 rtolv 1.e-3 maxiter 1 +errorcheck +domain 2dBeam +OutputManager tstep_all dofman_all element_all +ndofman 2 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 3 +node 1 coords 3 0. 0. 0. +node 2 coords 3 0. 0. 10. +Beam2d 1 nodes 2 1 2 +SimpleCS 1 area 1.e8 Iy 8.33e-6 beamShearCoeff 1.e18 thick 0.54 material 1 set 1 +IsoLE 1 d 1. E 205000000000 n 0.2 tAlpha 1.2e-5 +BoundaryCondition 1 loadTimeFunction 1 dofs 3 1 3 5 values 3 0.0 0.0 0.0 set 2 +NodalLoad 2 loadTimeFunction 1 dofs 3 1 3 5 Components 3 2000.0 -50000.0 0. set 3 +PeakFunction 1 t 1.0 f(t) 1. +Set 1 elements 1 1 +Set 2 nodes 1 1 +Set 3 nodes 1 2 +# +# exact solution +# +#%BEGIN_CHECK% tolerance 5.e-3 +#NODE tStep 1 number 2 dof 1 unknown d value 7.71430584e-01 +#REACTION tStep 1 number 1 dof 3 value 5.0000e+04 +#REACTION tStep 1 number 1 dof 1 value -3.9520e+03 +#REACTION tStep 1 number 1 dof 5 value -3.9520e+04 +#%END_CHECK% + + + diff --git a/tests/sm/pdelta03.in b/tests/sm/pdelta03.in new file mode 100644 index 000000000..2d1c70866 --- /dev/null +++ b/tests/sm/pdelta03.in @@ -0,0 +1,41 @@ +pdelta01.out +pdelta analysis of simple cantilever beam +#only momentum influence to the displacements is taken into account +#beamShearCoeff is artificially enlarged. +pdelta nsteps 1 nmodules 1 rtolv 1.e-3 maxiter 1 +errorcheck +domain 3dBeam +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 2 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 4 +node 1 coords 3 0. 0. 0. +node 2 coords 3 0. 10. 0. +node 3 coords 3 0. 0. 0. +node 4 coords 3 0. 10. 0. +Beam3d 1 nodes 2 1 2 zaxis 3 0 0 1 +Beam3d 2 nodes 2 3 4 zaxis 3 0 0 1 +SimpleCS 1 area 1.e8 Iy 8.33e-6 Iz 8.33e-6 Ik 0.003606447115384616 beamShearCoeff 1.e18 thick 0.54 material 1 set 1 +IsoLE 1 d 1. E 205000000000 n 0.2 tAlpha 1.2e-5 +BoundaryCondition 1 loadTimeFunction 1 dofs 6 1 2 3 4 5 6 values 6 0.0 0.0 0.0 0.0 0.0 0.0 set 2 +NodalLoad 2 loadTimeFunction 1 dofs 3 1 2 3 Components 3 2000. -50000.0 0. set 3 +NodalLoad 3 loadTimeFunction 1 dofs 3 1 2 3 Components 3 0. -50000.0 2000. set 4 +PeakFunction 1 t 1.0 f(t) 1. +Set 1 elements 2 1 2 +Set 2 nodes 2 1 3 +Set 3 nodes 1 2 +Set 4 nodes 1 4 +# +# exact solution +# +#%BEGIN_CHECK% tolerance 5.e-3 +#NODE tStep 1 number 2 dof 1 unknown d value 7.71430584e-01 +#REACTION tStep 1 number 1 dof 2 value 5.0000e+04 +#REACTION tStep 1 number 1 dof 1 value -3.9520e+03 +#REACTION tStep 1 number 1 dof 6 value 3.9520e+04 +#NODE tStep 1 number 4 dof 3 unknown d value 7.71430584e-01 +#REACTION tStep 1 number 3 dof 2 value 5.0000e+04 +#REACTION tStep 1 number 3 dof 3 value -3.9520e+03 +#REACTION tStep 1 number 3 dof 4 value -3.9520e+04 +#%END_CHECK% + + + diff --git a/tests/sm/qplanestress2dslip01.in b/tests/sm/qplanestress2dslip01.in new file mode 100644 index 000000000..fd31cc4f7 --- /dev/null +++ b/tests/sm/qplanestress2dslip01.in @@ -0,0 +1,42 @@ +qplanestress2dslip01.out +Test case for QPlaneStress2dSlip element +StaticStructural nsteps 1 deltat 1.0 constrainednrminiter 5 rtolf 1.0e-5 MaxIter 10 minIter 1 initialguess 1 nmodules 1 +errorcheck +#vtkxml tstep_all domain_all primvars 2 1 17 +#vtkxml tstep_all domain_all vars 6 4 1 141 142 143 144 ipvars 6 4 1 142 143 144 145 stype 1 +#matlab tstep_all mesh data specials reactionforces integrationpoints internalvars 6 4 1 142 143 144 145 +domain 2dplanestress +OutputManager tstep_all dofman_all element_all +ndofman 8 nelem 1 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 3 +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 2.0 0.0 0.0 +node 3 coords 3 2.0 1.0 0.0 +node 4 coords 3 0.0 1.0 0.0 +node 5 coords 3 1.0 0.0 0.0 +node 6 coords 3 2.0 0.5 0.0 +node 7 coords 3 1.0 1.0 0.0 +node 8 coords 3 0.0 0.5 0.0 +qplanestress2dslip 1 nodes 8 1 2 3 4 5 6 7 8 crossSect 1 nip 9 +Set 1 nodes 1 1 +Set 2 nodes 1 3 +Set 3 nodes 1 2 +SimpleCS 1 thick 0.2 material 1 set 1 +#structslipfe2material 1 d 1.0 filename rvedispslipdd.in.rve use_num_tangent +structslipfe2material 1 d 1.0 filename rvedispslipdd.in.rve use_ext_stiffness dSdE 3 3 { 3.625159e+10 6.935153e+09 2.470104e+04; 6.935153e+09 3.492711e+10 2.987505e+04; 2.470104e+04 2.987505e+04 1.387080e+10} dBSdE 2 3 { 2.186768e+06 4.329318e+05 -2.987933e+07; -8.444448e+05 -4.229045e+06 1.481353e+06 } dRSdE 4 3 { 1.570685e+09 1.351097e+05 -1.384174e+03 ; -6.032877e+04 2.509320e+08 -5.150497e+02 ; 0.000e+00 0.000e+00 0.000e+00 ; 0.000e+00 0.000e+00 0.000e+00 } dSdS 3 2 { 2.186768e+06 -8.444448e+05; 4.329318e+05 -4.229045e+06 ; -2.987933e+07 1.481357e+06} dBSdS 2 2 { 8.004712e+10 2.205447e+03 ; 2.205447e+03 2.676763e+10 } dRSdS 4 2 { -8.006231e+03 6.425644e+04 ; -1.236879e+04 7.187856e+03 ; 0.000e+00 0.000e+00 ; 0.000e+00 0.000e+00 } dSdG 3 4 { 1.570685e+09 -6.032877e+04 0.000000e+00 0.000000e+00 ; 1.351097e+05 2.509320e+08 0.000000e+00 0.000000e+00 ; -1.384174e+03 -5.150497e+02 0.000000e+00 0.000000e+00 } dBSdG 2 4 { -8.006231e+03 -1.236879e+04 0.000000e+00 0.000000e+00 ; 6.425644e+04 7.187856e+03 0.000000e+00 0.000000e+00 } dRSdG 4 4 { 1.881420e+09 1.173184e+05 0.000000e+00 0.000000e+00 ; 1.173184e+05 3.713261e+08 0.000000e+00 0.000000e+00; 0.000e+00 0.000e+00 0.000e+00 0.000e+00 ; 0.000e+00 0.000e+00 0.000e+00 0.000e+00 } +BoundaryCondition 1 loadTimeFunction 1 dofs 4 1 2 51 52 values 4 0.0 0.0 0.0 0.0 set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 3 1 51 52 values 3 0.0 0.0 0.0 set 2 +Boundarycondition 3 loadTimeFunction 1 dofs 4 1 2 51 52 values 4 1e-4 -2e-4 1e-5 3e-5 set 3 +ConstantFunction 1 f(t) 1.0 + +#%BEGIN_CHECK% tolerance 1.e-3 +#REACTION tStep 1 number 1 dof 2 value 8.90114055e+04 +#REACTION tStep 1 number 1 dof 52 value -2.76057675e+02 +#REACTION tStep 1 number 3 dof 1 value -1.78022811e+05 +#REACTION tStep 1 number 3 dof 51 value -6.39000517e+03 +#ELEMENT tStep 1 number 1 gp 1 keyword 143 component 1 value -4.67572651e+04 +#ELEMENT tStep 1 number 1 gp 1 keyword 143 component 2 value -9.07808236e+03 +#ELEMENT tStep 1 number 1 gp 1 keyword 145 component 1 value -1.42788019e+05 +#ELEMENT tStep 1 number 1 gp 1 keyword 145 component 2 value 1.06172543e+04 +#ELEMENT tStep 1 number 1 gp 1 keyword 145 component 3 value 0.0 +#ELEMENT tStep 1 number 1 gp 1 keyword 145 component 4 value 0.0 +#%END_CHECK% \ No newline at end of file diff --git a/tests/sm/qtrplstrslip01.in b/tests/sm/qtrplstrslip01.in new file mode 100644 index 000000000..daa49e426 --- /dev/null +++ b/tests/sm/qtrplstrslip01.in @@ -0,0 +1,39 @@ +qtrplstrslip01.out +Test case for QTrPlStrSlip element +StaticStructural nsteps 1 deltat 1.0 constrainednrminiter 5 rtolf 1.0e-5 MaxIter 10 minIter 1 initialguess 1 nmodules 1 +errorcheck +#vtkxml tstep_all domain_all primvars 2 1 17 +#matlab tstep_all mesh data specials reactionforces integrationpoints internalvars 6 4 1 142 143 144 145 +domain 2dplanestress +OutputManager tstep_all dofman_all element_all +ndofman 6 nelem 1 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 1 nset 3 +node 1 coords 3 0.0 2.0 0.0 +node 2 coords 3 1.30010 2.53433 0.0 +node 3 coords 3 0.0 4.0 0.0 +node 4 coords 3 0.650049 2.26717 0.0 +node 5 coords 3 0.650049 3.26717 0.0 +node 6 coords 3 0.0 3.0 0.0 +qtrplstrslip 1 nodes 6 1 2 3 4 5 6 crossSect 1 +Set 1 nodes 1 1 +Set 2 nodes 1 3 +Set 3 nodes 1 2 +SimpleCS 1 thick 0.2 material 1 set 1 +#structslipfe2material 1 d 1.0 filename rvedispslipdd.in.rve use_num_tangent +structslipfe2material 1 d 1.0 filename rvedispslipdd.in.rve use_ext_stiffness dSdE 3 3 { 3.625159e+10 6.935153e+09 2.470104e+04; 6.935153e+09 3.492711e+10 2.987505e+04; 2.470104e+04 2.987505e+04 1.387080e+10} dBSdE 2 3 { 2.186768e+06 4.329318e+05 -2.987933e+07; -8.444448e+05 -4.229045e+06 1.481353e+06 } dRSdE 4 3 { 1.570685e+09 1.351097e+05 -1.384174e+03 ; -6.032877e+04 2.509320e+08 -5.150497e+02 ; 0.000e+00 0.000e+00 0.000e+00 ; 0.000e+00 0.000e+00 0.000e+00 } dSdS 3 2 { 2.186768e+06 -8.444448e+05; 4.329318e+05 -4.229045e+06 ; -2.987933e+07 1.481357e+06} dBSdS 2 2 { 8.004712e+10 2.205447e+03 ; 2.205447e+03 2.676763e+10 } dRSdS 4 2 { -8.006231e+03 6.425644e+04 ; -1.236879e+04 7.187856e+03 ; 0.000e+00 0.000e+00 ; 0.000e+00 0.000e+00 } dSdG 3 4 { 1.570685e+09 -6.032877e+04 0.000000e+00 0.000000e+00 ; 1.351097e+05 2.509320e+08 0.000000e+00 0.000000e+00 ; -1.384174e+03 -5.150497e+02 0.000000e+00 0.000000e+00 } dBSdG 2 4 { -8.006231e+03 -1.236879e+04 0.000000e+00 0.000000e+00 ; 6.425644e+04 7.187856e+03 0.000000e+00 0.000000e+00 } dRSdG 4 4 { 1.881420e+09 1.173184e+05 0.000000e+00 0.000000e+00 ; 1.173184e+05 3.713261e+08 0.000000e+00 0.000000e+00; 0.000e+00 0.000e+00 0.000e+00 0.000e+00 ; 0.000e+00 0.000e+00 0.000e+00 0.000e+00 } +BoundaryCondition 1 loadTimeFunction 1 dofs 4 1 2 51 52 values 4 0.0 0.0 0.0 0.0 set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 2 1 51 values 2 0.0 0.0 set 2 +Boundarycondition 3 loadTimeFunction 1 dofs 4 1 2 51 52 values 4 1e-4 -2e-4 1e-5 3e-5 set 3 +ConstantFunction 1 f(t) 1.0 + +#%BEGIN_CHECK% tolerance 1.e-3 +#REACTION tStep 1 number 1 dof 2 value 6.73810164e+04 +#REACTION tStep 1 number 1 dof 52 value -2.10515553e+03 +#REACTION tStep 1 number 3 dof 1 value -6.83392776e+04 +#REACTION tStep 1 number 3 dof 51 value -2.46049126e+03 +#ELEMENT tStep 1 number 1 gp 1 keyword 143 component 1 value -6.73044804e+04 +#ELEMENT tStep 1 number 1 gp 1 keyword 143 component 2 value -2.93848813e+05 +#ELEMENT tStep 1 number 1 gp 1 keyword 145 component 1 value 1.32312923e+04 +#ELEMENT tStep 1 number 1 gp 1 keyword 145 component 2 value -6.81715957e+03 +#ELEMENT tStep 1 number 1 gp 1 keyword 145 component 3 value 0.0 +#ELEMENT tStep 1 number 1 gp 1 keyword 145 component 4 value 0.0 +#%END_CHECK% \ No newline at end of file diff --git a/tests/sm/rvedispslipdd.in.rve b/tests/sm/rvedispslipdd.in.rve new file mode 100644 index 000000000..2823f0f9b --- /dev/null +++ b/tests/sm/rvedispslipdd.in.rve @@ -0,0 +1,103 @@ +rveDispSlipDD +Reinforced concrete RVE - Dirichlet-Dirichelt BCs +StaticStructural nsteps 1 deltat 1.0 constrainednrminiter 5 rtolf 1.0e-3 MaxIter 30 minIter 1 stiffmode 0 initialguess 1 nmodules 0 suppress_output +#vtkxml tstep_all domain_all vars 5 1 4 5 12 52 ipvars 6 1 4 5 12 52 90 stype 1 regionsets 1 1 +#vtkxml tstep_all domain_all vars 1 12 ipvars 3 7 8 81 stype 1 regionsets 2 9 10 +#vtkxml tstep_all domain_all vars 2 98 99 ipvars 2 98 99 stype 0 regionsets 2 11 12 +#matlab tstep_all reactionforces specials +domain 2dplanestress +OutputManager +ndofman 35 nelem 32 ncrosssect 8 nmat 4 nbc 1 nic 0 nltf 1 nset 12 nxfemman 0 +node 1 coords 3 -0.1 -0.1 0 +node 2 coords 3 0 -0.1 0 +node 3 coords 3 0.1 -0.1 0 +node 4 coords 3 0.1 0 0 +node 5 coords 3 0.1 0.1 0 +node 6 coords 3 0 0.1 0 +node 7 coords 3 -0.1 0.1 0 +node 8 coords 3 -0.1 0 0 +node 9 coords 3 -0.05 -0.1 0 +node 10 coords 3 0.05 -0.1 0 +node 11 coords 3 0.1 -0.05 0 +node 12 coords 3 0.1 0.05 0 +node 13 coords 3 0.05 0.1 0 +node 14 coords 3 -0.05 0.1 0 +node 15 coords 3 -0.1 0.05 0 +node 16 coords 3 -0.1 -0.05 0 +node 17 coords 3 -0.05 -0.05 0 +node 18 coords 3 -0.05 0 0 +node 19 coords 3 -0.05 0.05 0 +node 20 coords 3 0 -0.05 0 +node 21 coords 3 0 0 0 +node 22 coords 3 0 0.05 0 +node 23 coords 3 0.05 -0.05 0 +node 24 coords 3 0.05 0 0 +node 25 coords 3 0.05 0.05 0 +node 26 coords 3 -0.1 0 0 +node 27 coords 3 -0.05 0 0 dofidmask 3 1 2 6 doftype 3 0 1 0 mastermask 3 0 18 0 +node 28 coords 3 0 0 0 dofidmask 3 1 2 6 doftype 3 0 1 0 mastermask 3 0 21 0 +node 29 coords 3 0.05 0 0 dofidmask 3 1 2 6 doftype 3 0 1 0 mastermask 3 0 24 0 +node 30 coords 3 0.1 0 0 +node 31 coords 3 0 -0.1 0 +node 32 coords 3 0 -0.05 0 dofidmask 3 1 2 6 doftype 3 1 0 0 mastermask 3 20 0 0 +node 33 coords 3 0 0 0 dofidmask 3 1 2 6 doftype 3 1 0 0 mastermask 3 21 0 0 +node 34 coords 3 0 0.05 0 dofidmask 3 1 2 6 doftype 3 1 0 0 mastermask 3 22 0 0 +node 35 coords 3 0 0.1 0 +LIBeam2D 17 nodes 2 26 27 xy +LIBeam2D 18 nodes 2 27 28 xy +LIBeam2D 19 nodes 2 28 29 xy +LIBeam2D 20 nodes 2 29 30 xy +LIBeam2D 21 nodes 2 31 32 xy +LIBeam2D 22 nodes 2 32 33 xy +LIBeam2D 23 nodes 2 33 34 xy +LIBeam2D 24 nodes 2 34 35 xy +PlaneStress2D 25 nodes 4 1 9 17 16 +PlaneStress2D 26 nodes 4 16 17 18 8 +PlaneStress2D 27 nodes 4 8 18 19 15 +PlaneStress2D 28 nodes 4 15 19 14 7 +PlaneStress2D 29 nodes 4 9 2 20 17 +PlaneStress2D 30 nodes 4 17 20 21 18 +PlaneStress2D 31 nodes 4 18 21 22 19 +PlaneStress2D 32 nodes 4 19 22 6 14 +PlaneStress2D 33 nodes 4 2 10 23 20 +PlaneStress2D 34 nodes 4 20 23 24 21 +PlaneStress2D 35 nodes 4 21 24 25 22 +PlaneStress2D 36 nodes 4 22 25 13 6 +PlaneStress2D 37 nodes 4 10 3 11 23 +PlaneStress2D 38 nodes 4 23 11 4 24 +PlaneStress2D 39 nodes 4 24 4 12 25 +PlaneStress2D 40 nodes 4 25 12 5 13 +IntElLine1 41 nodes 4 8 18 26 27 +IntElLine1 42 nodes 4 18 21 27 28 +IntElLine1 43 nodes 4 21 24 28 29 +IntElLine1 44 nodes 4 24 4 29 30 +IntElLine1 45 nodes 4 2 20 31 32 +IntElLine1 46 nodes 4 20 21 32 33 +IntElLine1 47 nodes 4 21 22 33 34 +IntElLine1 48 nodes 4 22 6 34 35 +SimpleCS 1 thick 2.0000000000e-01 material 1 set 1 +SimpleCS 2 thick 1.9899469035e-01 material 1 set 2 +SimpleCS 3 thick 1.9371681469e-01 material 1 set 3 +SimpleCS 4 thick 1.9271150504e-01 material 1 set 4 +LayeredCS 5 nLayers 1 LayerMaterials 1 2 Thicks 1 7.08914634e-3 Widths 1 7.08914634e-3 midSurf 3.544573317e-3 set 9 +LayeredCS 6 nLayers 1 LayerMaterials 1 2 Thicks 1 17.72455923e-3 Widths 1 17.72455923e-3 midSurf 8.862279616e-3 set 10 +InterfaceCS 7 thickness 6.2831853072e-02 material 3 set 11 +InterfaceCS 8 thickness 2.5132741229e-02 material 4 set 12 +MazarsModel 1 d 1.0 E 3.36e10 n 0.2 version 1 e0 8.63e-5 ac 2.6 bc 800 ef 0.0025 tAlpha 1.0 maxOmega 0.9999 +MisesMat 2 d 1.0 E 2e11 n 0.3 sig0 500e6 H 8.456659619e8 omega_crit 0 a 0 tAlpha 1.0 +bondceb 3 kn 6e12 ks 6.135e10 s1 0.001 s2 0.002 s3 0.0065 taumax 1.541e7 tauf 6.164e6 +bondceb 4 kn 6e12 ks 6.135e10 s1 0.001 s2 0.002 s3 0.004 taumax 1.541e7 tauf 6.164e6 +PrescribedDispSlipBCDirichletRC 1 loadTimeFunction 1 dofs 3 1 2 6 ccoord 3 0.0 0.0 0.0 dispGrad 2 2 {0.0 0.0; 0.0 0.0} slip 2 0.0 0.0 slipGrad 2 2 {0 0; 0 0} set 5 conboundset 6 reinfxbound 8 reinfybound 7 +ConstantFunction 1 f(t) 1.0 +set 1 elements 16 32 33 34 35 36 37 38 39 40 25 26 27 28 29 30 31 +set 2 elements 3 33 35 36 +set 3 elements 3 38 26 30 +set 4 elements 1 34 +set 5 nodes 20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 26 30 31 35 +set 6 elementboundaries 32 25 1 29 1 33 1 37 1 37 2 38 2 39 2 40 2 40 3 36 3 32 3 28 3 28 4 27 4 26 4 25 4 +set 7 nodes 2 35 31 +set 8 nodes 2 26 30 +set 9 elements 4 24 21 22 23 +set 10 elements 4 17 18 19 20 +set 11 elements 4 41 42 43 44 +set 12 elements 4 48 45 46 47 \ No newline at end of file diff --git a/tests/sm/scordelis_mitc4.in b/tests/sm/scordelis_mitc4.in index fb22e903a..af47bdd7b 100644 --- a/tests/sm/scordelis_mitc4.in +++ b/tests/sm/scordelis_mitc4.in @@ -78,8 +78,8 @@ Set 5 noderanges {(1 6) 10 11 15 16 20 21 25} #ELEMENT tStep 1 number 4 gp 1 keyword 1 component 1 value 1.4833e+03 #ELEMENT tStep 1 number 4 gp 1 keyword 1 component 2 value -4.0193e+01 #ELEMENT tStep 1 number 4 gp 1 keyword 1 component 3 value -1.5730e+01 -#ELEMENT tStep 1 number 4 gp 1 keyword 1 component 4 value -2.5054e+02 -#ELEMENT tStep 1 number 4 gp 1 keyword 1 component 5 value 3.6459e+02 -#ELEMENT tStep 1 number 4 gp 1 keyword 1 component 6 value 2.5304e+01 +#ELEMENT tStep 1 number 4 gp 1 keyword 1 component 4 value 2.5304e+01 +#ELEMENT tStep 1 number 4 gp 1 keyword 1 component 5 value -2.5054e+02 +#ELEMENT tStep 1 number 4 gp 1 keyword 1 component 6 value 3.6459e+02 ## #%END_CHECK% diff --git a/tests/sm/steelRelaxMat.in b/tests/sm/steelRelaxMat.in index b9b05aa8f..10472d04b 100644 --- a/tests/sm/steelRelaxMat.in +++ b/tests/sm/steelRelaxMat.in @@ -4,7 +4,7 @@ relaxation of prestressing reinforcement, all dofs fixed StaticStructural nsteps 25 prescribedTimes 25 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. nmodules 1 # errorcheck -# vtkxml tstep_step 1 domain_all vars 2 1 4 primvars 1 1 +#vtkxml tstep_step 1 domain_all vars 2 1 4 primvars 1 1 # domain 2dPlaneStress # @@ -67,8 +67,8 @@ ConstantFunction 1 f(t) 1.0 HeavisideLTF 2 origin 0.0 value 1.0 # #%BEGIN_CHECK% tolerance 5.e-3 -#ELEMENT tStep 10 number 1 gp 1 keyword 1 component 1 value 7.237900e+02 -#ELEMENT tStep 10 number 3 gp 1 keyword 1 component 1 value 7.349400e+02 -#ELEMENT tStep 25 number 1 gp 1 keyword 1 component 1 value 6.012400e+02 -#ELEMENT tStep 25 number 3 gp 1 keyword 1 component 1 value 6.171000e+02 +#ELEMENT tStep 10 number 1 gp 1 keyword 1 component 1 value 7.35062615e+02 +#ELEMENT tStep 10 number 3 gp 1 keyword 1 component 1 value 7.34992211e+02 +#ELEMENT tStep 25 number 1 gp 1 keyword 1 component 1 value 6.19512976e+02 +#ELEMENT tStep 25 number 3 gp 1 keyword 1 component 1 value 6.18253822e+02 #%END_CHECK% diff --git a/tests/sm/steelRelaxMat2.in b/tests/sm/steelRelaxMat2.in index 36c3246ac..0f1523e16 100644 --- a/tests/sm/steelRelaxMat2.in +++ b/tests/sm/steelRelaxMat2.in @@ -1,7 +1,7 @@ steelRelaxMat2.out relaxation of prestressing reinforcement, all dofs fixed # -StaticStructural nsteps 25 prescribedTimes 25 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. nmodules 1 +StaticStructural nsteps 25 prescribedTimes 25 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. nmodules 1 # errorcheck # @@ -52,8 +52,8 @@ HeavisideLTF 2 origin 0.0 value 1.0 # #TIME #%BEGIN_CHECK% tolerance 5.e-3 -#ELEMENT tStep 10 number 1 gp 1 keyword 1 component 1 value 7.702400e+02 -#ELEMENT tStep 10 number 2 gp 1 keyword 1 component 1 value 7.703100e+02 -#ELEMENT tStep 25 number 1 gp 1 keyword 1 component 1 value 6.326700e+02 -#ELEMENT tStep 25 number 2 gp 1 keyword 1 component 1 value 6.330400e+02 +#ELEMENT tStep 10 number 1 gp 1 keyword 1 component 1 value 7.70247029e+02 +#ELEMENT tStep 10 number 2 gp 1 keyword 1 component 1 value 7.70313864e+02 +#ELEMENT tStep 25 number 1 gp 1 keyword 1 component 1 value 6.32667344e+02 +#ELEMENT tStep 25 number 2 gp 1 keyword 1 component 1 value 6.33037535e+02 #%END_CHECK% diff --git a/tests/sm/test_wp.in b/tests/sm/test_wp1.in similarity index 97% rename from tests/sm/test_wp.in rename to tests/sm/test_wp1.in index 0a0cef775..8e88a400d 100644 --- a/tests/sm/test_wp.in +++ b/tests/sm/test_wp1.in @@ -1,5 +1,5 @@ -test_wp.out -"Winkler pasternak model: test of settlement profile" +test_wp1.out +Winkler pasternak model: test of settlement profile StaticStructural nsteps 1 nmodules 1 errorcheck #vtkxml tstep_all domain_all primvars 1 1 vars 4 1 2 4 10 stype 2 diff --git a/tests/sm/test_wp2.in b/tests/sm/test_wp2.in index 901f83bab..b35dfcb3a 100644 --- a/tests/sm/test_wp2.in +++ b/tests/sm/test_wp2.in @@ -1,5 +1,5 @@ test_wp2.out -"Winkler pasternak model: test of settlement profile, Tria1PlateSubSoil elements" +Winkler pasternak model: test of settlement profile, Tria1PlateSubSoil elements StaticStructural nsteps 1 nmodules 1 errorcheck #vtkxml tstep_all domain_all primvars 1 1 diff --git a/tests/sm/test_wp3.in b/tests/sm/test_wp3.in index 4dd8ed934..31f77c829 100644 --- a/tests/sm/test_wp3.in +++ b/tests/sm/test_wp3.in @@ -1,7 +1,7 @@ test_wp3.out -"Winkler pasternak model: test of settlement profile, Quadrilateral quadratic elements" -linearstatic nsteps 1 nmodules 1 -vtkxml tstep_step 1 domain_all primvars 1 1 vars 3 1 2 4 stype 1 +Winkler pasternak model: test of settlement profile, Quadrilateral quadratic elements +linearstatic nsteps 1 nmodules 0 +#vtkxml tstep_step 1 domain_all primvars 1 1 vars 3 1 2 4 stype 1 domain 2dMindlinPlate OutputManager tstep_all dofman_all element_all ndofman 58 nelem 11 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 1 nset 2 diff --git a/tests/sm/test_wp4.in b/tests/sm/test_wp4.in new file mode 100644 index 000000000..354ed118c --- /dev/null +++ b/tests/sm/test_wp4.in @@ -0,0 +1,40 @@ +test_wp4.out +Winkler pasternak model: test of settlement profile, quadratic triagle elements +linearstatic nsteps 1 nmodules 1 +errorcheck +#vtkxml tstep_step 1 domain_all primvars 1 1 vars 3 1 2 4 stype 2 +domain 2dMindlinPlate +OutputManager tstep_all dofman_all element_all +ndofman 13 nelem 4 ncrosssect 1 nmat 1 nbc 1 nic 0 nltf 1 nset 2 +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.0 4.0 0.0 +node 3 coords 3 3.0 1.0 0.0 +node 4 coords 3 9.0 0.0 0.0 +node 5 coords 3 9.0 4.0 0.0 +node 6 coords 3 0.0 2.0 0.0 +node 7 coords 3 1.5 0.5 0.0 +node 8 coords 3 1.5 2.5 0.0 +node 9 coords 3 4.5 0.0 0.0 +node 10 coords 3 4.5 4.0 0.0 +node 11 coords 3 6.0 0.5 0.0 +node 12 coords 3 6.0 2.5 0.0 +node 13 coords 3 9.0 2.0 0.0 +Tria2PlateSubSoil 1 nodes 6 1 3 2 7 8 6 +Tria2PlateSubSoil 2 nodes 6 1 4 3 9 11 7 +Tria2PlateSubSoil 3 nodes 6 2 3 5 8 12 10 +Tria2PlateSubSoil 4 nodes 6 3 4 5 11 13 12 +SimpleCS 1 thick 1.0 material 1 set 1 +winklerpasternak 1 d 2500. c1 1.0 c2 2.0 +#BoundaryCondition 1 loadTimeFunction 1 dofs 1 3 values 1 0.1 set 2 +NodalLoad 1 loadTimeFunction 1 dofs 1 3 Components 1 1.0 set 2 +ConstantFunction 1 f(t) 1.0 +Set 1 elementranges {(1 4)} +Set 2 nodes 1 3 +#1.27024637e-01 +#%BEGIN_CHECK% tolerance 5.e-4 +#NODE tStep 1 number 1 dof 3 unknown d value 4.02994362e-02 +#NODE tStep 1 number 2 dof 3 unknown d value 1.89744851e-02 +#NODE tStep 1 number 3 dof 3 unknown d value 1.27024637e-01 +#%END_CHECK% + + diff --git a/tests/sm/test_wp5.in b/tests/sm/test_wp5.in new file mode 100644 index 000000000..fe1d3a118 --- /dev/null +++ b/tests/sm/test_wp5.in @@ -0,0 +1,41 @@ +test_wp5.out +Winkler pasternak model: test of constant surface load in step 1 on linear elements. The same load applies in step 2, using equivalent nodal load instead. +StaticStructural nsteps 2 nmodules 1 +#vtkxml tstep_all domain_all primvars 1 1 vars 4 1 2 4 10 stype 2 +errorcheck +domain 2dMindlinPlate +OutputManager tstep_all dofman_all element_all +ndofman 8 nelem 4 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 2 nset 4 +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.3 0.0 0.0 +node 3 coords 3 0.8 0.0 0.0 +node 4 coords 3 1.3 0.0 0.0 +node 5 coords 3 0.0 0.5 0.0 +node 6 coords 3 0.3 0.5 0.0 +node 7 coords 3 0.8 0.5 0.0 +node 8 coords 3 1.3 0.5 0.0 +quad1platesubsoil 1 nodes 4 1 2 6 5 +tria1platesubsoil 2 nodes 3 2 3 6 +tria1platesubsoil 3 nodes 3 3 7 6 +quad1platesubsoil 4 nodes 4 3 4 8 7 +SimpleCS 1 thick 1.0 material 1 set 1 +winklerpasternak 1 d 2500. c1 3.0 c2 0.4 +ConstantSurfaceLoad 1 loadTimeFunction 1 dofs 1 3 Components 1 7.0 set 2 +NodalLoad 2 loadTimeFunction 2 dofs 1 3 Components 1 0.2625 set 3 +NodalLoad 3 loadTimeFunction 2 dofs 1 3 Components 1 0.29166666666 set 4 +PeakFunction 1 t 1.0 f(t) 1. +PeakFunction 2 t 2.0 f(t) 1. +Set 1 allelements +Set 2 elementboundaries 4 1 1 2 1 +Set 3 nodes 4 1 2 6 5 +Set 4 nodes 3 2 3 6 +#%BEGIN_CHECK% tolerance 5.e-4 +#NODE tStep 1 number 1 dof 3 unknown d value 1.82823013e+00 +#NODE tStep 1 number 2 dof 3 unknown d value 1.71134657e+00 +#NODE tStep 1 number 3 dof 3 unknown d value 6.75361433e-01 +#NODE tStep 1 number 4 dof 3 unknown d value 2.30473551e-01 +#NODE tStep 2 number 1 dof 3 unknown d value 1.82823013e+00 +#NODE tStep 2 number 2 dof 3 unknown d value 1.71134657e+00 +#NODE tStep 2 number 3 dof 3 unknown d value 6.75361433e-01 +#NODE tStep 2 number 4 dof 3 unknown d value 2.30473551e-01 +#%END_CHECK% diff --git a/tests/sm/test_wp6.in b/tests/sm/test_wp6.in new file mode 100644 index 000000000..75619bbc3 --- /dev/null +++ b/tests/sm/test_wp6.in @@ -0,0 +1,52 @@ +test_wp6.out +Winkler pasternak model: test of constant surface load in step 1 on quadratic elements. The same load applies in step 2, using equivalent nodal load instead. +StaticStructural nsteps 2 nmodules 1 +#vtkxml tstep_step 1 domain_all primvars 1 1 vars 3 1 2 4 stype 0 +errorcheck +domain 2dMindlinPlate +OutputManager tstep_all dofman_all element_all +ndofman 14 nelem 3 ncrosssect 1 nmat 1 nbc 4 nic 0 nltf 2 nset 5 +node 1 coords 3 0.00 0.0 0.0 +node 2 coords 3 0.15 0.0 0.0 +node 3 coords 3 0.30 0.0 0.0 +node 4 coords 3 0.55 0.0 0.0 +node 5 coords 3 0.80 0.0 0.0 +node 6 coords 3 0.00 0.5 0.0 +node 7 coords 3 0.15 0.5 0.0 +node 8 coords 3 0.30 0.5 0.0 +node 9 coords 3 0.55 0.5 0.0 +node 10 coords 3 0.80 0.5 0.0 +node 11 coords 3 0.00 0.25 0.0 +node 12 coords 3 0.30 0.25 0.0 +node 13 coords 3 0.55 0.25 0.0 +node 14 coords 3 0.80 0.25 0.0 +quad2platesubsoil 1 nodes 8 1 3 8 6 2 12 7 11 +Tria2PlateSubSoil 2 nodes 6 3 5 8 4 13 12 +Tria2PlateSubSoil 3 nodes 6 5 10 8 14 9 13 +SimpleCS 1 thick 1.0 material 1 set 1 +winklerpasternak 1 d 2500. c1 3.0 c2 0.4 +ConstantSurfaceLoad 1 loadTimeFunction 1 dofs 1 3 Components 1 7.0 set 2 +#Quadratic triangle - equivalent nodal load is just at mid-points of edges. Corver vertices have zero load. +NodalLoad 2 loadTimeFunction 2 dofs 1 3 Components 1 0.29166666666 set 3 +#Quadratic rectangle - equivalent nodal load at mid-nodes A*q/3 (total 4*A*q), at corner vertices -A*q/12 (total -A*q*3) +NodalLoad 3 loadTimeFunction 2 dofs 1 3 Components 1 0.35 set 4 +NodalLoad 4 loadTimeFunction 2 dofs 1 3 Components 1 -0.0875 set 5 +PeakFunction 1 t 1.0 f(t) 1. +PeakFunction 2 t 2.0 f(t) 1. +Set 1 allelements +Set 2 elementboundaries 4 1 1 2 1 +Set 3 nodes 3 4 13 12 +Set 4 nodes 4 2 12 7 11 +Set 5 nodes 4 1 3 8 6 +#%BEGIN_CHECK% tolerance 5.e-4 +#NODE tStep 1 number 1 dof 3 unknown d value 1.94199900e+00 +#NODE tStep 1 number 3 dof 3 unknown d value 1.79566126e+00 +#NODE tStep 1 number 4 dof 3 unknown d value 1.59531221e+00 +#NODE tStep 1 number 5 dof 3 unknown d value 1.38671935e+00 +#NODE tStep 1 number 8 dof 3 unknown d value 1.67031938e+00 +#NODE tStep 2 number 1 dof 3 unknown d value 1.94199900e+00 +#NODE tStep 2 number 3 dof 3 unknown d value 1.79566126e+00 +#NODE tStep 2 number 4 dof 3 unknown d value 1.59531221e+00 +#NODE tStep 2 number 5 dof 3 unknown d value 1.38671935e+00 +#NODE tStep 2 number 8 dof 3 unknown d value 1.67031938e+00 +#%END_CHECK% diff --git a/tests/sm/trshell11_1.in b/tests/sm/trshell11_1.in new file mode 100644 index 000000000..aa3a6d732 --- /dev/null +++ b/tests/sm/trshell11_1.in @@ -0,0 +1,113 @@ +trshell11_1.out +Cantilever beam, comparing two models (integral cross section and layared cross section) +# +NonLinearStatic nmodules 1 nmsteps 1 nsteps 2 profileopt 1 +nsteps 2 controllmode 1 rtolf 1e-3 rtold 1e-3 MaxIter 2000 refloadmode 1 +# +#vtkxml tstep_all domain_all primvars 1 1 vars 3 9 10 104 stype 1 +errorcheck +# +domain 3dShell +OutputManager tstep_all dofman_all element_all +#ndofman 4 nelem 2 ncrosssect 2 nmat 1 nbc 2 nic 0 nltf 2 nset 4 +ndofman 8 nelem 4 ncrosssect 2 nmat 1 nbc 2 nic 0 nltf 2 nset 4 +# +node 1 coords 3 0. 0.0 0. +node 2 coords 3 0. 0.5 0. +node 3 coords 3 1. 0.5 0. +node 4 coords 3 1. 0.0 0. +# +node 11 coords 3 0. 0.0 0. +node 12 coords 3 0. 0.5 0. +node 13 coords 3 1. 0.5 0. +node 14 coords 3 1. 0.0 0. +# +tr_shell11 1 nodes 3 1 2 3 +tr_shell11 2 nodes 3 1 3 4 +# +tr_shell11 11 nodes 3 11 12 13 +tr_shell11 12 nodes 3 11 13 14 +# +#CROSS SECTIONS +SimpleCS 1 thick 0.02 material 1 drillType 1 relDrillStiffness 0.01 drillstiffness 10.e9 set 1 +LayeredCS 2 nlayers 2 layermaterials 2 1 1 thicks 2 0.01 0.01 widths 2 1 1 nintegrationpoints 2 drillType 1 relDrillStiffness 0.01 set 2 drillstiffness 10.e9 +# +#MATERIALS +IsoLE 1 d 1. E 1e9 n 0.2 tAlpha 0. +#ConcreteDPM 1 d 0. E 30.e9 n 0.2 talpha 0. fc 30.e6 ft 3.e6 ecc 0.525 Ahard 8.e-2 Bhard 3.e-3 Chard 2. Dhard 1.e-6 Asoft 35. dilation -0.85 yieldtol 1.e-8 newtoniter 300 wf 300.e-6 +# +#BOUNDARY CONDITIONS +BoundaryCondition 1 loadTimeFunction 1 dofs 6 1 2 3 4 5 6 values 6 0. 0. 0. 0. 0. 0. set 3 +#BoundaryCondition 2 loadTimeFunction 2 dofs 2 4 5 values 2 0 0.05 set 4 +NodalLoad 2 loadtimeFunction 2 dofs 2 1 5 Components 2 1.0 1.0 set 4 +# +#FUNCTIONS +ConstantFunction 1 f(t) 1. +PiecewiseLinFunction 2 nPoints 3 t 3 -1. 0. 9. f(t) 3 0. 0. 1. +# +#SETS +Set 1 elements 2 1 2 +Set 2 elements 2 11 12 +#Set 2 +Set 3 nodes 4 1 2 11 12 +Set 4 nodes 4 3 4 13 14 +# +# +#%BEGIN_CHECK% tolerance 1.e-8 +#NODE tStep 2 number 3 dof 1 unknown d value 2.11247616e-08 tolerance 1.e-10 +#NODE tStep 2 number 3 dof 2 unknown d value -1.07008715e-09 tolerance 1.e-10 +#NODE tStep 2 number 3 dof 3 unknown d value -3.29602674e-04 tolerance 1.e-10 +#NODE tStep 2 number 3 dof 4 unknown d value 5.92956839e-07 tolerance 1.e-10 +#NODE tStep 2 number 3 dof 5 unknown d value 6.59199446e-04 tolerance 1.e-10 +# +#NODE tStep 2 number 4 dof 1 unknown d value 2.43231379e-08 tolerance 1.e-10 +#NODE tStep 2 number 4 dof 2 unknown d value 5.03243457e-09 tolerance 1.e-10 +#NODE tStep 2 number 4 dof 3 unknown d value -3.19019099e-04 tolerance 1.e-10 +#NODE tStep 2 number 4 dof 4 unknown d value -4.38462023e-05 tolerance 1.e-10 +#NODE tStep 2 number 4 dof 5 unknown d value 6.38576218e-04 tolerance 1.e-10 +# +#ELEMENT tStep 2 number 1 gp 1 keyword 104 component 1 value 2.0989e-08 tolerance 1.e-10 +#ELEMENT tStep 2 number 1 gp 1 keyword 104 component 4 value -9.8826e-08 tolerance 1.e-10 +#ELEMENT tStep 2 number 1 gp 1 keyword 11 component 1 value -6.5920e-04 tolerance 1.e-7 +#ELEMENT tStep 2 number 1 gp 1 keyword 11 component 6 value 5.9296e-07 tolerance 1.e-10 +#ELEMENT tStep 2 number 1 gp 1 keyword 10 component 1 value 8.7454e-03 tolerance 1.e-6 +#ELEMENT tStep 2 number 1 gp 1 keyword 10 component 2 value 1.7491e-03 tolerance 1.e-6 +#ELEMENT tStep 2 number 1 gp 1 keyword 10 component 4 value -6.8629e-01 tolerance 1.e-4 +#ELEMENT tStep 2 number 1 gp 1 keyword 10 component 5 value -3.6364e-01 tolerance 1.e-4 +#ELEMENT tStep 2 number 1 gp 1 keyword 9 component 1 value -4.5778e-01 tolerance 1.e-4 +#ELEMENT tStep 2 number 1 gp 1 keyword 9 component 2 value -9.1555e-02 tolerance 1.e-5 +## check reactions +##REACTION tStep 2 number 1 dof 1 value -9.0824e-02 tolerance 1.e-5 +##REACTION tStep 2 number 1 dof 2 value -3.4883e-02 tolerance 1.e-5 +##REACTION tStep 2 number 1 dof 3 value 2.5224e-01 tolerance 1.e-4 +##REACTION tStep 2 number 1 dof 4 value 1.2232e-01 tolerance 1.e-4 +##REACTION tStep 2 number 1 dof 5 value -1.3458e-01 tolerance 1.e-4 +##REACTION tStep 2 number 2 dof 1 value -1.3140e-01 tolerance 1.e-5 +##REACTION tStep 2 number 2 dof 2 value 3.4883e-02 tolerance 1.e-5 +##REACTION tStep 2 number 2 dof 3 value -2.5224e-01 tolerance 1.e-4 +##REACTION tStep 2 number 2 dof 4 value 3.7963e-03 tolerance 1.e-4 +##REACTION tStep 2 number 2 dof 5 value -8.7639e-02 tolerance 1.e-4 +###layered model +#NODE tStep 2 number 13 dof 1 unknown d value 2.11247616e-08 tolerance 1.e-10 +#NODE tStep 2 number 13 dof 2 unknown d value -1.07008715e-09 tolerance 1.e-10 +#NODE tStep 2 number 13 dof 3 unknown d value -3.29602674e-04 tolerance 1.e-10 +#NODE tStep 2 number 13 dof 4 unknown d value 5.92956839e-07 tolerance 1.e-10 +#NODE tStep 2 number 13 dof 5 unknown d value 6.59199446e-04 tolerance 1.e-10 +# +#NODE tStep 2 number 14 dof 1 unknown d value 2.43231379e-08 tolerance 1.e-10 +#NODE tStep 2 number 14 dof 2 unknown d value 5.03243457e-09 tolerance 1.e-10 +#NODE tStep 2 number 14 dof 3 unknown d value -3.19019099e-04 tolerance 1.e-10 +#NODE tStep 2 number 14 dof 4 unknown d value -4.38462023e-05 tolerance 1.e-10 +#NODE tStep 2 number 14 dof 5 unknown d value 6.38576218e-04 tolerance 1.e-10 +# +#ELEMENT tStep 2 number 11 gp 1 keyword 104 component 1 value 2.0989e-08 tolerance 1.e-10 +#ELEMENT tStep 2 number 11 gp 1 keyword 104 component 4 value -9.8826e-08 tolerance 1.e-10 +#ELEMENT tStep 2 number 11 gp 1 keyword 11 component 1 value -6.5920e-04 tolerance 1.e-7 +#ELEMENT tStep 2 number 11 gp 1 keyword 11 component 6 value 5.9296e-07 tolerance 1.e-10 +#ELEMENT tStep 2 number 11 gp 1 keyword 10 component 1 value 8.7454e-03 tolerance 1.e-6 +#ELEMENT tStep 2 number 11 gp 1 keyword 10 component 2 value 1.7491e-03 tolerance 1.e-6 +#ELEMENT tStep 2 number 11 gp 1 keyword 10 component 4 value -6.8629e-01 tolerance 1.e-4 +#ELEMENT tStep 2 number 11 gp 1 keyword 10 component 5 value -3.6364e-01 tolerance 1.e-4 +#ELEMENT tStep 2 number 11 gp 1 keyword 9 component 1 value -4.5778e-01 tolerance 1.e-4 +#ELEMENT tStep 2 number 11 gp 1 keyword 9 component 2 value -9.1555e-02 tolerance 1.e-5 +#%END_CHECK% diff --git a/tests/sm/xFemCrackValBranchCZ.in b/tests/sm/xFemCrackValBranchCZ.in index 582f0cc6b..3d52c8044 100644 --- a/tests/sm/xFemCrackValBranchCZ.in +++ b/tests/sm/xFemCrackValBranchCZ.in @@ -6,22 +6,22 @@ errorcheck domain 2dPlaneStress OutputManager tstep_all dofman_all element_all ndofman 16 nelem 9 ncrosssect 1 nmat 2 nbc 3 nic 0 nltf 1 nxfemman 1 nset 4 -node 1 coords 2 0 0 -node 2 coords 2 2 0 -node 3 coords 2 2 2 -node 4 coords 2 0 2 -node 5 coords 2 0.666667 0 -node 6 coords 2 1.33333 0 -node 7 coords 2 2 0.666667 -node 8 coords 2 2 1.33333 -node 9 coords 2 1.33333 2 -node 10 coords 2 0.666667 2 -node 11 coords 2 0 1.33333 -node 12 coords 2 0 0.666667 -node 13 coords 2 1.33333 0.666667 -node 14 coords 2 1.33333 1.33333 -node 15 coords 2 0.666667 0.66668 -node 16 coords 2 0.666667 1.33335 +node 1 coords 3 0 0 0 +node 2 coords 3 2 0 0 +node 3 coords 3 2 2 0 +node 4 coords 3 0 2 0 +node 5 coords 3 0.666667 0 0 +node 6 coords 3 1.33333 0 0 +node 7 coords 3 2 0.666667 0 +node 8 coords 3 2 1.33333 0 +node 9 coords 3 1.33333 2 0 +node 10 coords 3 0.666667 2 0 +node 11 coords 3 0 1.33333 0 +node 12 coords 3 0 0.666667 0 +node 13 coords 3 1.33333 0.666667 0 +node 14 coords 3 1.33333 1.33333 0 +node 15 coords 3 0.666667 0.66668 0 +node 16 coords 3 0.666667 1.33335 0 PlaneStress2DXfem 1 nodes 4 2 6 13 7 mat 1 nip 9 nlgeo 0 czmaterial 2 PlaneStress2DXfem 2 nodes 4 7 13 14 8 mat 1 nip 9 nlgeo 0 czmaterial 2 PlaneStress2DXfem 3 nodes 4 8 14 9 3 mat 1 nip 9 nlgeo 0 czmaterial 2 diff --git a/tests/smmfront/mfront01.in b/tests/smmfront/mfront01.in new file mode 100644 index 000000000..a6024aa02 --- /dev/null +++ b/tests/smmfront/mfront01.in @@ -0,0 +1,49 @@ +plasticity_mfront.out +test of MFront interface +# +StaticStructural nsteps 5 nmodules 1 maxiter 20 +# +errorcheck +# +#vtkxml tstep_step 1 domain_all vars 2 1 4 primvars 1 1 nsteps 5 +# +domain 3d +OutputManager tstep_all dofman_all element_all +ndofman 8 nelem 1 ncrosssect 1 nmat 1 nbc 5 nic 0 nltf 3 nset 5 +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 1.0 0.0 0.0 +node 3 coords 3 1.0 1.0 0.0 +node 4 coords 3 0.0 1.0 0.0 +node 5 coords 3 0.0 0.0 1.0 +node 6 coords 3 1.0 0.0 1.0 +node 7 coords 3 1.0 1.0 1.0 +node 8 coords 3 0.0 1.0 1.0 +lspace 1 nodes 8 1 2 3 4 5 6 7 8 crossSect 1 +SimpleCS 1 material 1 set 1 +# +mfrontusermaterial 1 d 0. modelname "IsotropicLinearHardeningPlasticity" libpath "./plasticity/src/libBehaviour.so" properties 0 +# +BoundaryCondition 1 loadTimeFunction 2 dofs 3 1 2 3 values 3 0.0 0.0 0.0 set 2 +BoundaryCondition 2 loadTimeFunction 2 dofs 3 1 2 3 values 3 0.0 0.0 0.0 set 3 +BoundaryCondition 3 loadTimeFunction 2 dofs 3 1 2 3 values 3 0.0 0.0 0.0 set 4 +BoundaryCondition 4 loadTimeFunction 2 dofs 3 1 2 3 values 3 0.0 0.0 0.0 set 5 +BoundaryCondition 5 loadTimeFunction 3 dofs 3 1 2 3 values 3 0.4 0.2 1.0 set 1 +# +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 0.0 +PiecewiseLinFunction 3 t 2 0. 1000. f(t) 2 0. 1. +Set 1 nodes 4 5 6 7 8 +Set 2 nodes 1 1 +Set 3 nodes 1 2 +Set 4 nodes 1 3 +Set 5 nodes 1 4 +# +# +#%BEGIN_CHECK% tolerance 1.e-5 +#REACTION tStep 1 number 1 dof 1 value -1.11111111e+00 +#REACTION tStep 1 number 1 dof 2 value -9.02777778e-01 +#REACTION tStep 1 number 1 dof 3 value -3.40277778e+00 +#REACTION tStep 5 number 1 dof 1 value -6.24620228e+00 +#REACTION tStep 5 number 1 dof 2 value -5.72252065e+00 +#REACTION tStep 5 number 1 dof 3 value -1.20067002e+01 +#%END_CHECK% \ No newline at end of file diff --git a/tests/smmfront/plasticity/IsotropicLinearHardeningPlasticity.mfront b/tests/smmfront/plasticity/IsotropicLinearHardeningPlasticity.mfront new file mode 100755 index 000000000..7de187a03 --- /dev/null +++ b/tests/smmfront/plasticity/IsotropicLinearHardeningPlasticity.mfront @@ -0,0 +1,78 @@ +@DSL DefaultDSL; +@Behaviour IsotropicLinearHardeningPlasticity; +@Author Thomas Helfer; +@Date 14/10/2016; + +@Description{ + An implicit implementation of a simple + isotropic plasticity behaviour with + isotropic linear hardening. + + The yield surface is defined by: + "\[" + " f(\sigmaeq,p) = \sigmaeq-s_{0}-H\,p" + "\]" +} + +@Parameter young = 10e3; +young.setGlossaryName("YoungModulus"); +@Parameter nu = 0.2; +nu.setGlossaryName("PoissonRatio"); +@Parameter H = 1e3; +H.setEntryName("HardeningSlope"); +@Parameter s0 = 20.; +s0.setGlossaryName("YieldStress"); + +@StateVariable StrainStensor eel; +eel.setGlossaryName("ElasticStrain"); +@StateVariable strain p; +p.setGlossaryName("EquivalentPlasticStrain"); + +/*! + * computation of the prediction operator: we only provide the elastic + * operator. + * + * We could also provide a tangent operator, but this would mean + * saving an auxiliary state variable stating if a plastic loading + * occured at the previous time step. + */ +@PredictionOperator{ + // silent "unused parameter" warning + static_cast(smt); + const auto lambda = computeLambda(young,nu); + const auto mu = computeMu(young,nu); + Dt = lambda*Stensor4::IxI()+2*mu*Stensor4::Id(); +} + +/*! + * behaviour integration using a fully implicit Euler-backwark scheme. + */ +@ProvidesSymmetricTangentOperator; +@Integrator{ + const auto lambda = computeLambda(young,nu); + const auto mu = computeMu(young,nu); + eel += deto; + const auto se = 2*mu*deviator(eel); + const auto seq_e = sigmaeq(se); + const auto b = seq_e-s0-H*p>stress{0}; + if(b){ + const auto iseq_e = 1/seq_e; + const auto n = eval(3*se/(2*seq_e)); + const auto cste = 1/(H+3*mu); + dp = (seq_e-s0-H*p)*cste; + eel -= dp*n; + if(computeTangentOperator_){ + if(smt==CONSISTENTTANGENTOPERATOR){ + Dt = (lambda*Stensor4::IxI()+2*mu*Stensor4::Id() + -4*mu*mu*(dp*iseq_e*(Stensor4::M()-(n^n))+cste*(n^n))); + } else { + Dt = lambda*Stensor4::IxI()+2*mu*Stensor4::Id(); + } + } + } else { + if(computeTangentOperator_){ + Dt = lambda*Stensor4::IxI()+2*mu*Stensor4::Id(); + } + } + sig = lambda*trace(eel)*Stensor::Id()+2*mu*eel; +} diff --git a/tests/smmfront/readme_install.txt b/tests/smmfront/readme_install.txt new file mode 100644 index 000000000..7b74e0518 --- /dev/null +++ b/tests/smmfront/readme_install.txt @@ -0,0 +1,34 @@ +# INSTALLATION OF ALL PARTS ON UBUNTU 20.04 + +# needs clang +sudo apt install clang + +# install tfel +mkdir TFEL && cd TFEL +git clone https://github.com/thelfer/tfel.git +mkdir build && cd build +cmake ../tfel -DUSE_PYTHON_EXTENSION="OFF" -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10 -DCMAKE_C_COMPILER=/usr/bin/clang-10 -Dlocal-castem-header=ON -DCMAKE_INSTALL_PREFIX=~/.local +make -j 8 +sudo make install + +# install MGIS +git clone https://github.com/thelfer/MFrontGenericInterfaceSupport.git +cd MFrontGenericInterfaceSupport +mkdir build && cd build +cmake .. -DCMAKE_BUILD_TYPE=Release -Denable-c-bindings=ON -Denable-fortran-bindings=ON -Denable-python-bindings=ON -DPython_ADDITIONAL_VERSIONS=3.8 +make -j 8 +sudo make install + +# install oofem +git clone https://github.com/oofem/oofem.git +cd oofem && mkdir build && cd build +cmake -DUSE_MFRONT=ON -DMFrontGenericInterface_DIR=/usr/local/share/mgis/cmake/ .. +make -j 8 +# go to the mfront test directory +cd ../tests/smmfront/plasticity +# create the mfront material shared library for generic interface +CC=clang CXX=clang++ mfront --obuild --interface=generic IsotropicLinearHardeningPlasticity.mfront +# go to the build directory +cd ../../../build +# run the tests +ctest \ No newline at end of file diff --git a/tests/tm/TwoStepCasting_01.in b/tests/tm/TwoStepCasting_01.in index 9a41bad65..1cf350d9f 100644 --- a/tests/tm/TwoStepCasting_01.in +++ b/tests/tm/TwoStepCasting_01.in @@ -1,12 +1,6 @@ TwoStepCasting_01.out -MAT1 is cast, MAT2 is cast after 10 hours +Simulates continuous casting of concrete with changing boundary conditions. # Geometrical representation -# HC is heat convection on corresponding surfaces -# MAT is corresponding hydrating material. MAT1 is cast with HC1 condition. After 10 hours, MAT2 is cast, HC1 cancelled -# and HC2 imposed. -# Nodes 5,6 need to be fixed with Dirichlet boundary condition until material becomes active. -# Initial conditions and boundary conditions on nodes 5,6 should be the same. In fact, they represent starting temperature -# of the second concrete. Also, elements associated with MAT2 needs to be inactivated, otherwise they conduct heat. # # 2 ------- 4 -------6 # | | | @@ -14,44 +8,49 @@ MAT1 is cast, MAT2 is cast after 10 hours # | | | # 1 ------- 3 -------5 # +# MAT1 is cast with HC1 condition. After 10 hours, MAT2 is cast, HC1 cancelled and HC2 imposed. +# Nodes 5,6 need to be fixed with Dirichlet boundary condition up 10 hours since MAT2 is inactive and +# there is zero capacity and zero conductivity. +# Boundary condition on nodes 5,6 represents in fact an initial condition once MAT2 appears. +# HC1 needs to be deactivated after inposing HC2. TransientTransport nsteps 10 deltat 7200 alpha 0.5 miniter 5 nmodules 1 errorcheck #vtkxml tstep_all domain_all primvars 1 6 vars 2 37 56 stype 1 domain HeatTransfer OutputManager tstep_all dofman_all element_all -ndofman 6 nelem 2 ncrosssect 2 nmat 2 nbc 3 nic 2 nltf 3 nset 5 +ndofman 6 nelem 2 ncrosssect 2 nmat 2 nbc 3 nic 1 nltf 3 nset 6 node 1 coords 3 0.0 0.0 0.0 node 2 coords 3 0.0 0.2 0.0 node 3 coords 3 0.4 0.0 0.0 node 4 coords 3 0.4 0.2 0.0 node 5 coords 3 0.8 0.0 0.0 node 6 coords 3 0.8 0.2 0.0 -quad1ht 1 nodes 4 1 3 4 2 crossSect 1 BoundaryLoads 2 1 2 -quad1ht 2 nodes 4 3 5 6 4 crossSect 2 BoundaryLoads 2 2 2 activityLTF 3 -SimpleTransportCS 1 mat 1 thickness 0.2 -SimpleTransportCS 2 mat 2 thickness 0.2 +quad1ht 1 nodes 4 1 3 4 2 +quad1ht 2 nodes 4 3 5 6 4 activityLTF 3 +SimpleTransportCS 1 mat 1 thickness 0.2 set 1 +SimpleTransportCS 2 mat 2 thickness 0.2 set 2 HydratingConcreteMat 1 d 2305. k 1.6 c 870. hydrationmodeltype 2 Qpot 518.37 masscement 285.0 b1 25.2778e-5 b2 7.0e-4 eta 6.7 dohinf 0.85 activationenergy 38300 castingTime 0.0 HydratingConcreteMat 2 d 2305. k 1.6 c 870. hydrationmodeltype 2 Qpot 518.37 masscement 285.0 b1 25.2778e-5 b2 7.0e-4 eta 6.7 dohinf 0.85 activationenergy 38300 castingTime 36000. -ConstantEdgeLoad 1 loadTimeFunction 1 components 1 25.0 properties 1 a 15.0 loadtype 3 isImposedTimeFunction 2 -ConstantEdgeLoad 2 loadTimeFunction 1 components 1 25.0 properties 1 a 15.0 loadtype 3 isImposedTimeFunction 3 -BoundaryCondition 3 loadTimeFunction 1 dofs 1 10 values 1 20.0 isImposedTimeFunction 2 set 3 -InitialCondition 1 Conditions 1 u 25.0 dofs 1 10 set 2 -InitialCondition 2 Conditions 1 u 20.0 dofs 1 10 set 3 +ConstantEdgeLoad 1 loadTimeFunction 1 components 1 25.0 properties 1 a 15.0 loadtype 3 isImposedTimeFunction 2 set 3 +ConstantEdgeLoad 2 loadTimeFunction 1 components 1 25.0 properties 1 a 15.0 loadtype 3 isImposedTimeFunction 3 set 4 +BoundaryCondition 3 loadTimeFunction 1 dofs 1 10 values 1 10.0 isImposedTimeFunction 2 set 5 +InitialCondition 1 Conditions 1 u 25.0 dofs 1 10 set 6 ConstantFunction 1 f(t) 1.0 UsrDefLTF 2 f(t) 1-h(36000.) UsrDefLTF 3 f(t) h(36000.) -Set 1 elementranges {(1 2)} -Set 2 nodes 4 1 2 3 4 -Set 3 nodes 2 5 6 -Set 4 elementboundaries 2 1 2 -Set 5 elementboundaries 2 2 2 +Set 1 elements 1 1 +Set 2 elements 1 2 +Set 3 elementedges 2 1 2 +Set 4 elementedges 2 2 2 +Set 5 nodes 2 5 6 +Set 6 nodes 4 1 2 3 4 #%BEGIN_CHECK% #NODE tStep 2 number 1 dof 10 unknown d value 2.63154331e+01 -#NODE tStep 2 number 6 dof 10 unknown d value 2.00000000e+01 +#NODE tStep 2 number 6 dof 10 unknown d value 1.00000000e+01 #ELEMENT tStep 2 number 2 gp 3 keyword 39 component 1 value 0.0 -#NODE tStep 10 number 1 dof 10 unknown d value 5.75730957e+01 -#NODE tStep 10 number 6 dof 10 unknown d value 4.20657949e+01 -#ELEMENT tStep 10 number 1 gp 3 keyword 39 component 1 value 5.06757250e-01 -#ELEMENT tStep 10 number 2 gp 3 keyword 39 component 1 value 3.84671388e-01 +#NODE tStep 10 number 1 dof 10 unknown d value 5.72302290e+01 +#NODE tStep 10 number 6 dof 10 unknown d value 3.96247063e+01 +#ELEMENT tStep 10 number 1 gp 3 keyword 39 component 1 value 5.05586458e-01 +#ELEMENT tStep 10 number 2 gp 3 keyword 39 component 1 value 3.50943937e-01 #%END_CHECK% diff --git a/tests/tm/bazantnajjar.in b/tests/tm/bazantnajjar.in index aca664fbf..addb8cb87 100644 --- a/tests/tm/bazantnajjar.in +++ b/tests/tm/bazantnajjar.in @@ -42,23 +42,24 @@ quadaxisym1mt 8 nodes 4 8 9 20 19 quadaxisym1mt 9 nodes 4 9 10 21 20 quadaxisym1mt 10 nodes 4 10 11 22 21 # +Set 1 elementranges {(1 10)} +Set 2 nodes 2 11 22 +# SimpleTransportCS 1 mat 1 set 1 bazantnajjarmoisturemat 1 d 2400. C1 3.1e-05 alpha0 0.02 hC 0.775 n 5 BoundaryCondition 1 loadTimeFunction 1 dofs 1 14 values 1 1.0 set 2 InitialCondition 1 Conditions 1 u 1.00 dofs 1 14 set 1 ConstantFunction 1 f(t) 0.5 #PieceWiseLinFunction 1 t 4 -1 0 0.01 10 f(t) 4 0 0 0.5 0.5 -Set 1 elementranges {(1 10)} -Set 2 nodes 2 11 22 ## ## # #%BEGIN_CHECK% tolerance 1.e-5 -#NODE tStep 4 number 1 dof 14 unknown d value 7.99174594e-01 -#NODE tStep 4 number 3 dof 14 unknown d value 7.93215521e-01 -#NODE tStep 4 number 5 dof 14 unknown d value 7.80840997e-01 -#NODE tStep 8 number 1 dof 14 unknown d value 6.21069014e-01 -#NODE tStep 8 number 3 dof 14 unknown d value 6.16643713e-01 -#NODE tStep 8 number 5 dof 14 unknown d value 6.05649077e-01 +#NODE tStep 4 number 1 dof 14 unknown d value 8.21898066e-01 +#NODE tStep 4 number 3 dof 14 unknown d value 8.16589267e-01 +#NODE tStep 4 number 5 dof 14 unknown d value 8.05355193e-01 +#NODE tStep 8 number 1 dof 14 unknown d value 6.38601781e-01 +#NODE tStep 8 number 3 dof 14 unknown d value 6.34189820e-01 +#NODE tStep 8 number 5 dof 14 unknown d value 6.21702020e-01 #%END_CHECK% diff --git a/tests/tm/hydratingConcreteMat02.in b/tests/tm/hydratingConcreteMat02.in index 93de2c033..1efe874d7 100644 --- a/tests/tm/hydratingConcreteMat02.in +++ b/tests/tm/hydratingConcreteMat02.in @@ -19,8 +19,10 @@ ConstantFunction 1 f(t) 1.0 Set 1 elements 1 1 #%BEGIN_CHECK% tolerance 1.e-3 +#TIME #NODE tStep 5 number 1 dof 10 unknown d value 3.59549990e+01 #NODE tStep 29 number 1 dof 10 unknown d value 1.04396706e+02 #ELEMENT tStep 5 number 1 gp 1 keyword 39 component 1 value 1.12531681e-01 #ELEMENT tStep 29 number 1 gp 1 keyword 39 component 1 value 8.15578417e-01 +#ELEMENT tStep 5 number 1 gp 1 keyword 135 component 1 value 2.22269086e+04 #%END_CHECK% diff --git a/tests/tm/hydratingConcreteMat06.in b/tests/tm/hydratingConcreteMat06.in new file mode 100644 index 000000000..fb2676cb9 --- /dev/null +++ b/tests/tm/hydratingConcreteMat06.in @@ -0,0 +1,27 @@ +hydratingConcreteMat06.out +Test of hydrating concrete material, one linear triangluar element, transient transport solver, isothermal conditions, Rahimi-Agham's model +TransientTransport nsteps 30 deltat 7200. alpha 0.5 nmodules 1 +errorcheck +#vtkxml tstep_step 1 domain_all primvars 1 6 vars 4 37 39 56 96 stype 1 +domain HeatTransfer +OutputManager tstep_all dofman_all element_all +ndofman 3 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 1 nltf 1 nset 1 +node 1 coords 3 1.0 0.0 0.0 +node 2 coords 3 2.2 0.0 0.0 +node 3 coords 3 1.0 1.0 0.0 +tr1ht 1 nodes 3 1 2 3 crossSect 1 +SimpleTransportCS 1 thickness 0.15 mat 1 +#Standard concrete k(conductivity)=1.7 W/m/K c(capacity)=870 J/kg/K +HydratingConcreteMat 1 d 2458. k 1.7 c 870.0 hydrationmodeltype 3 Qpot 509. masscement 400. w/c 0.50 a/c 5.0 castingTime 0. maturityT0 20. +BoundaryCondition 1 loadTimeFunction 1 dofs 1 10 values 1 20.0 set 1 +InitialCondition 1 Conditions 1 u 20.0 dofs 1 10 set 1 +ConstantFunction 1 f(t) 1.0 +Set 1 elements 1 1 + +#%BEGIN_CHECK% tolerance 1.e-3 +#TIME +#ELEMENT tStep 1 number 1 gp 1 keyword 39 component 1 value 0.05 +##ELEMENT tStep 30 number 1 gp 1 keyword 39 component 1 value 5.20334463e-01 +##ELEMENT tStep 6 number 2 gp 1 keyword 39 component 1 value 1.07180394e-01 +##ELEMENT tStep 30 number 2 gp 1 keyword 39 component 1 value 6.48537723e-01 +#%END_CHECK% diff --git a/tests/tm/hydratingConcreteMat07.in b/tests/tm/hydratingConcreteMat07.in new file mode 100644 index 000000000..ad8b9423e --- /dev/null +++ b/tests/tm/hydratingConcreteMat07.in @@ -0,0 +1,37 @@ +hydratingConcreteMat07.out +Test of hydrating concrete material, linear triangluar element with a heat source, transient linear solver, cooling with 1D element from one node, exponential model +TransientTransport nsteps 29 deltat 3600.0 alpha 1 rtolv 1e-5 lumped nmodules 1 +errorcheck +#vtkxml tstep_step 1 domain_all primvars 1 6 vars 3 37 39 56 stype 1 regionsets 1 1 +#vtkxml tstep_step 1 domain_all primvars 1 6 vars 1 56 stype 1 regionsets 1 2 +domain HeatTransfer +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 2 ncrosssect 2 nmat 2 nbc 1 nic 1 nltf 1 nset 4 +node 1 coords 3 1.0 0.0 0.0 +node 2 coords 3 1.5 0.0 0.0 +node 3 coords 3 1.0 0.5 0.0 +node 4 coords 3 1.0 0.5 0.0495 +tr1ht 1 nodes 3 1 2 3 +line1ht 2 nodes 2 3 4 +SimpleTransportCS 1 thickness 1.0 mat 1 set 1 +#Cooling pipe 3/4" PVC, k=0.2 W/m/K, effective circumference 0.0707 m, thickness 0.0035 m, if heat flux (W/m2) corresponds to dissipated power (W/m of length), thickness need to be extended to 0.0035/0.0707=0.0495 m +SimpleTransportCS 2 area 1.0 mat 2 set 2 +#Standard concrete k(conductivity)=1.7 W/m/K c(capacity)=870 J/kg/K +HydratingConcreteMat 1 d 2458. k 1.7 c 870.0 hydrationmodeltype 1 Qpot 509. masscement 409. referenceTemperature 25. tau 48600. beta 0.9 dohinf 0.85 activationenergy 38300 castingTime 0. +IsoHeat 2 d 0.1 k 0.2 c 1.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 10 values 1 20.0 set 4 +InitialCondition 1 Conditions 1 u 25.0 dofs 1 10 set 3 +ConstantFunction 1 f(t) 1.0 +Set 1 elements 1 1 +Set 2 elements 1 2 +Set 3 elements 2 1 2 +Set 4 nodes 1 4 + +#%BEGIN_CHECK% tolerance 1.e-3 +#TIME +#NODE tStep 5 number 1 dof 10 unknown d value 3.42225515e+01 +#NODE tStep 29 number 1 dof 10 unknown d value 7.85131416e+01 +#ELEMENT tStep 5 number 1 gp 1 keyword 39 component 1 value 9.82865410e-02 +#ELEMENT tStep 29 number 1 gp 1 keyword 39 component 1 value 7.70453997e-01 +#ELEMENT tStep 5 number 1 gp 1 keyword 135 component 1 value 2.06830003e+04 +#%END_CHECK% diff --git a/tests/tm/lattice3d_mt1.in b/tests/tm/lattice3d_mt1.in new file mode 100644 index 000000000..0ec8a8053 --- /dev/null +++ b/tests/tm/lattice3d_mt1.in @@ -0,0 +1,76 @@ +lattice3d_mt1.out +Test of 3d lattice mass transport elements +TransientTransport nsteps 2 deltat 20. rtolf 1.e-6 forcescale 1 0 forcescaledofs 1 11 alpha 1. contextOutputStep 100 nmodules 2 +vtkxmllattice tstep_all domain_all cross 1 +errorcheck +domain 3dMassLatticeTransport +OutputManager tstep_all dofman_all element_all +ndofman 24 nelem 36 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 +node 1 coords 3 1.5750000000000001e-04 1.7500000000000000e-04 2.1000000000000001e-04 +node 2 coords 3 1.7500000000000000e-04 1.9249999999999999e-04 2.1000000000000001e-04 +node 3 coords 3 2.1000000000000001e-04 1.9249999999999999e-04 1.7500000000000000e-04 bc 1 2 +node 4 coords 3 1.7500000000000000e-04 1.9249999999999999e-04 1.3999999999999999e-04 +node 5 coords 3 2.1000000000000001e-04 1.7500000000000000e-04 1.5750000000000001e-04 bc 1 2 +node 6 coords 3 1.9249999999999999e-04 1.7500000000000000e-04 1.3999999999999999e-04 +node 7 coords 3 1.3999999999999999e-04 1.9249999999999999e-04 1.7500000000000000e-04 bc 1 1 +node 8 coords 3 1.3999999999999999e-04 1.7500000000000000e-04 1.9249999999999999e-04 bc 1 1 +node 9 coords 3 1.7500000000000000e-04 2.1000000000000001e-04 1.9249999999999999e-04 +node 10 coords 3 1.5750000000000001e-04 2.1000000000000001e-04 1.7500000000000000e-04 +node 11 coords 3 1.9249999999999999e-04 2.1000000000000001e-04 1.7500000000000000e-04 +node 12 coords 3 1.7500000000000000e-04 2.1000000000000001e-04 1.5750000000000001e-04 +node 13 coords 3 2.1000000000000001e-04 1.5750000000000001e-04 1.7500000000000000e-04 bc 1 2 +node 14 coords 3 2.1000000000000001e-04 1.7500000000000000e-04 1.9249999999999999e-04 bc 1 2 +node 15 coords 3 1.9249999999999999e-04 1.7500000000000000e-04 2.1000000000000001e-04 +node 16 coords 3 1.7500000000000000e-04 1.5750000000000001e-04 2.1000000000000001e-04 +node 17 coords 3 1.7500000000000000e-04 1.3999999999999999e-04 1.9249999999999999e-04 +node 18 coords 3 1.9249999999999999e-04 1.3999999999999999e-04 1.7500000000000000e-04 +node 19 coords 3 1.3999999999999999e-04 1.7500000000000000e-04 1.5750000000000001e-04 bc 1 1 +node 20 coords 3 1.5750000000000001e-04 1.7500000000000000e-04 1.3999999999999999e-04 +node 21 coords 3 1.3999999999999999e-04 1.5750000000000001e-04 1.7500000000000000e-04 bc 1 1 +node 22 coords 3 1.5750000000000001e-04 1.3999999999999999e-04 1.7500000000000000e-04 +node 23 coords 3 1.7500000000000000e-04 1.5750000000000001e-04 1.3999999999999999e-04 +node 24 coords 3 1.7500000000000000e-04 1.3999999999999999e-04 1.5750000000000001e-04 +latticemt3D 1 nodes 2 20 4 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.0499999999999999e-04 1.3999999999999999e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 2 nodes 2 6 4 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.0499999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 3 nodes 2 6 23 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.0499999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.3999999999999999e-04 +latticemt3D 4 nodes 2 23 20 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.0499999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.3999999999999999e-04 1.3999999999999999e-04 1.3999999999999999e-04 +latticemt3D 5 nodes 2 21 19 crossSect 1 mat 1 polycoords 9 1.3999999999999999e-04 1.3999999999999999e-04 1.3999999999999999e-04 1.0499999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 6 nodes 2 20 19 crossSect 1 mat 1 polycoords 9 1.3999999999999999e-04 1.3999999999999999e-04 1.3999999999999999e-04 1.3999999999999999e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 7 nodes 2 21 22 crossSect 1 mat 1 polycoords 9 1.3999999999999999e-04 1.3999999999999999e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.3999999999999999e-04 1.3999999999999999e-04 2.0999999999999998e-04 +latticemt3D 8 nodes 2 22 24 crossSect 1 mat 1 polycoords 9 1.3999999999999999e-04 1.3999999999999999e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.0499999999999999e-04 1.7500000000000000e-04 +latticemt3D 9 nodes 2 24 23 crossSect 1 mat 1 polycoords 9 1.3999999999999999e-04 1.3999999999999999e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.3999999999999999e-04 +latticemt3D 10 nodes 2 6 5 crossSect 1 mat 1 polycoords 9 2.0999999999999998e-04 1.3999999999999999e-04 1.3999999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 11 nodes 2 13 5 crossSect 1 mat 1 polycoords 9 2.0999999999999998e-04 1.3999999999999999e-04 1.3999999999999999e-04 2.4499999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 12 nodes 2 24 18 crossSect 1 mat 1 polycoords 9 2.0999999999999998e-04 1.3999999999999999e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.0499999999999999e-04 1.7500000000000000e-04 +latticemt3D 13 nodes 2 18 13 crossSect 1 mat 1 polycoords 9 2.0999999999999998e-04 1.3999999999999999e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.0999999999999998e-04 1.3999999999999999e-04 2.0999999999999998e-04 +latticemt3D 14 nodes 2 12 4 crossSect 1 mat 1 polycoords 9 1.3999999999999999e-04 2.0999999999999998e-04 1.3999999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 15 nodes 2 12 10 crossSect 1 mat 1 polycoords 9 1.3999999999999999e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.4499999999999999e-04 1.7500000000000000e-04 +latticemt3D 16 nodes 2 10 7 crossSect 1 mat 1 polycoords 9 1.3999999999999999e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.3999999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 +latticemt3D 17 nodes 2 7 19 crossSect 1 mat 1 polycoords 9 1.3999999999999999e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.0499999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 18 nodes 2 11 3 crossSect 1 mat 1 polycoords 9 2.0999999999999998e-04 2.0999999999999998e-04 1.3999999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 2.0999999999999998e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 19 nodes 2 5 3 crossSect 1 mat 1 polycoords 9 2.0999999999999998e-04 2.0999999999999998e-04 1.3999999999999999e-04 2.4499999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 20 nodes 2 11 12 crossSect 1 mat 1 polycoords 9 2.0999999999999998e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.4499999999999999e-04 1.7500000000000000e-04 +latticemt3D 21 nodes 2 22 17 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.0499999999999999e-04 1.7500000000000000e-04 1.3999999999999999e-04 1.3999999999999999e-04 2.0999999999999998e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 22 nodes 2 17 18 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.0499999999999999e-04 1.7500000000000000e-04 2.0999999999999998e-04 1.3999999999999999e-04 2.0999999999999998e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 23 nodes 2 8 7 crossSect 1 mat 1 polycoords 9 1.0499999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.3999999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 24 nodes 2 21 8 crossSect 1 mat 1 polycoords 9 1.0499999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.3999999999999999e-04 1.3999999999999999e-04 2.0999999999999998e-04 +latticemt3D 25 nodes 2 2 9 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.3999999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 2.0999999999999998e-04 2.0999999999999998e-04 2.0999999999999998e-04 +latticemt3D 26 nodes 2 9 10 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.3999999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 1.7500000000000000e-04 2.4499999999999999e-04 1.7500000000000000e-04 +latticemt3D 27 nodes 2 8 1 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.3999999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 1.3999999999999999e-04 1.3999999999999999e-04 2.0999999999999998e-04 +latticemt3D 28 nodes 2 1 2 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.3999999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.4499999999999999e-04 +latticemt3D 29 nodes 2 2 15 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.4499999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 2.0999999999999998e-04 +latticemt3D 30 nodes 2 15 16 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.4499999999999999e-04 2.0999999999999998e-04 1.3999999999999999e-04 2.0999999999999998e-04 +latticemt3D 31 nodes 2 16 1 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.4499999999999999e-04 1.3999999999999999e-04 1.3999999999999999e-04 2.0999999999999998e-04 +latticemt3D 32 nodes 2 17 16 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 1.3999999999999999e-04 1.3999999999999999e-04 2.0999999999999998e-04 2.0999999999999998e-04 1.3999999999999999e-04 2.0999999999999998e-04 +latticemt3D 33 nodes 2 9 11 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.0999999999999998e-04 2.0999999999999998e-04 2.0999999999999998e-04 1.7500000000000000e-04 2.4499999999999999e-04 1.7500000000000000e-04 +latticemt3D 34 nodes 2 3 14 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.0999999999999998e-04 2.0999999999999998e-04 2.0999999999999998e-04 2.4499999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 +latticemt3D 35 nodes 2 14 15 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.0999999999999998e-04 2.0999999999999998e-04 2.0999999999999998e-04 2.0999999999999998e-04 1.3999999999999999e-04 2.0999999999999998e-04 +latticemt3D 36 nodes 2 13 14 crossSect 1 mat 1 polycoords 9 1.7500000000000000e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.4499999999999999e-04 1.7500000000000000e-04 1.7500000000000000e-04 2.0999999999999998e-04 1.3999999999999999e-04 2.0999999999999998e-04 +simpletransportcs 1 mat 1 +latticetransmat 1 d 1000. vis 0.001002 k 1. thetas 1. +BoundaryCondition 1 loadTimeFunction 1 prescribedvalue 0. +BoundaryCondition 2 loadTimeFunction 1 prescribedvalue -1. +ConstantFunction 1 f(t) 1. +#%BEGIN_CHECK% +#NODE tStep 1 number 2 dof 11 unknown d value -0.5 +#%END_CHECK% diff --git a/tests/tm/line01.in b/tests/tm/line01.in new file mode 100644 index 000000000..eac58e98c --- /dev/null +++ b/tests/tm/line01.in @@ -0,0 +1,28 @@ +line01.out +Patch test of Line1ht elements +StationaryProblem nsteps 1 nmodules 1 +#vtkxml tstep_all domain_all primvars 1 6 vars 2 37 56 stype 1 +errorcheck +domain HeatTransfer +OutputManager tstep_all dofman_all element_all +ndofman 3 nelem 2 ncrosssect 1 nmat 1 nbc 2 nic 0 nltf 1 nset 3 +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.0 1.0 0.0 +node 3 coords 3 0.0 4.0 0.0 +line1ht 1 nodes 2 1 2 +line1ht 2 nodes 2 2 3 +SimpleTransportCS 1 area 0.15 mat 1 set 1 +IsoHeat 1 d 0. k 2.0 c 1.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 10 values 1 10.0 set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 10 values 1 40.0 set 3 +ConstantFunction 1 f(t) 1.0 +Set 1 elementranges {(1 2)} +Set 2 nodes 1 1 +Set 3 nodes 1 3 + +#%BEGIN_CHECK% +#NODE tStep 1 number 2 dof 10 unknown d value 17.5 +#ELEMENT tStep 1 number 1 gp 1 keyword 56 component 2 value -15. +#ELEMENT tStep 1 number 2 gp 1 keyword 56 component 2 value -15. + +#%END_CHECK% diff --git a/tests/tm/line02.in b/tests/tm/line02.in new file mode 100644 index 000000000..661f416ee --- /dev/null +++ b/tests/tm/line02.in @@ -0,0 +1,30 @@ +line02.out +Line1_ht element in nonstationary problem +TransientTransport nsteps 20 deltat 3600 alpha 0.5 lumped nmodules 1 +#vtkxml tstep_all domain_all primvars 1 6 vars 1 56 stype 1 +errorcheck +domain HeatTransfer +OutputManager tstep_all dofman_all element_all +ndofman 3 nelem 2 ncrosssect 1 nmat 1 nbc 2 nic 1 nltf 1 nset 4 +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.0 1.0 0.0 +node 3 coords 3 0.0 4.0 0.0 +line1ht 1 nodes 2 1 2 +line1ht 2 nodes 2 2 3 +SimpleTransportCS 1 area 0.15 mat 1 set 1 +IsoHeat 1 d 24. k 2.0 c 900.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 10 values 1 10.0 set 2 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 10 values 1 40.0 set 3 +InitialCondition 1 Conditions 1 u 10.0 dofs 1 10 set 4 +ConstantFunction 1 f(t) 1.0 +Set 1 elementranges {(1 2)} +Set 2 nodes 1 1 +Set 3 nodes 1 3 +Set 4 nodes 1 2 + +#%BEGIN_CHECK% +#NODE tStep 20 number 2 dof 10 unknown d value 17.3883107 +#ELEMENT tStep 20 number 1 gp 1 keyword 56 component 2 value -14.7486991 +#ELEMENT tStep 20 number 2 gp 1 keyword 56 component 2 value -15.0837670 + +#%END_CHECK% diff --git a/tests/tm/nlisomoisture02.in b/tests/tm/nlisomoisture02.in index 139eb1a50..39b181fc6 100644 --- a/tests/tm/nlisomoisture02.in +++ b/tests/tm/nlisomoisture02.in @@ -42,23 +42,24 @@ quadaxisym1mt 8 nodes 4 8 9 20 19 quadaxisym1mt 9 nodes 4 9 10 21 20 quadaxisym1mt 10 nodes 4 10 11 22 21 # +Set 1 elementranges {(1 10)} +Set 2 nodes 2 11 22 +# SimpleTransportCS 1 mat 1 set 1 #moisture capacity 180 kg/m3, hydration takes maximum 70 kg/m3 nlisomoisturemat 1 d 2400. isothermtype 0 Capa 180. permeabilitytype 1 C1 1.5e-2 alpha0 0.05 hC 0.70 n 12. wn 70. alpha $1-exp(-t/1.2)$ BoundaryCondition 1 loadTimeFunction 1 dofs 1 14 values 1 1. set 2 InitialCondition 1 Conditions 1 u 1.00 dofs 1 14 set 1 ConstantFunction 1 f(t) 0.5 -Set 1 elementranges {(1 10)} -Set 2 nodes 2 11 22 ## ## # #%BEGIN_CHECK% tolerance 1.e-5 #TIME -#NODE tStep 2 number 1 dof 14 unknown d value 7.094815e-01 -#NODE tStep 2 number 3 dof 14 unknown d value 7.020422e-01 -#NODE tStep 2 number 5 dof 14 unknown d value 6.852221e-01 -#NODE tStep 6 number 1 dof 14 unknown d value 4.305701e-01 -#NODE tStep 6 number 3 dof 14 unknown d value 4.370362e-01 -#NODE tStep 6 number 5 dof 14 unknown d value 4.516013e-01 +#NODE tStep 2 number 1 dof 14 unknown d value 7.17107011e-01 +#NODE tStep 2 number 3 dof 14 unknown d value 7.10410246e-01 +#NODE tStep 2 number 5 dof 14 unknown d value 6.95300909e-01 +#NODE tStep 6 number 1 dof 14 unknown d value 4.37636005e-01 +#NODE tStep 6 number 3 dof 14 unknown d value 4.43648407e-01 +#NODE tStep 6 number 5 dof 14 unknown d value 4.57902853e-01 #%END_CHECK% diff --git a/tests/tm/nlisomoisture03.in b/tests/tm/nlisomoisture03.in new file mode 100644 index 000000000..8e74cc43d --- /dev/null +++ b/tests/tm/nlisomoisture03.in @@ -0,0 +1,61 @@ +nlisomoisture03.out +test of nonlinear isotropic material for moisture transport +# +TransientTransport nsteps 5 alpha 0.5 lumped forceScale 1 0 forceScaleDofs 1 14 rtolf 1e-5 prescribedtimes 5 0.01 0.1 0.2 0.3 0.4 nmodules 1 +# +errorcheck +# vtkxml tstep_all domain_all primvars 1 3 +# +domain mass1transfer +OutputManager tsteps_out {5} dofman_output {1 7} element_output {1} +# OutputManager tstep_all dofman_output {1 7} +ndofman 12 nelem 4 ncrosssect 2 nmat 2 nbc 1 nic 1 nltf 2 nset 2 +# +node 1 coords 3 0.000 0.000 0.0 +node 2 coords 3 0.001 0.000 0.0 +node 3 coords 3 0.002 0.000 0.0 +node 4 coords 3 0.000 0.001 0.0 +node 5 coords 3 0.001 0.001 0.0 +node 6 coords 3 0.002 0.001 0.0 +# +node 7 coords 3 0.000 0.002 0.0 +node 8 coords 3 0.001 0.002 0.0 +node 9 coords 3 0.002 0.002 0.0 +node 10 coords 3 0.000 0.003 0.0 +node 11 coords 3 0.001 0.003 0.0 +node 12 coords 3 0.002 0.003 0.0 +# +quad1mt 1 nodes 4 4 5 2 1 crossSect 1 +quad1mt 2 nodes 4 5 6 3 2 crossSect 1 +# +quad1mt 3 nodes 4 10 11 8 7 crossSect 2 +quad1mt 4 nodes 4 11 12 9 8 crossSect 2 +# +SimpleTransportCS 1 thickness 1.0 mat 1 +SimpleTransportCS 2 thickness 1.0 mat 2 +# +# +# vanGenuchten isotherm + Kunzel permeability + constant room temperature +nlisomoisturemat 1 d 0. isothermtype 7 wf 110. vG_b 6.126 vG_m 0.331 permeabilitytype 3 timescale 86400. capillarytransporttype 2 mu 400 Abs 1. capil_coef 1.e4 t 293.15 +# +# vanGenuchten isotherm + Kunzel permeability + variable elevated temperature +nlisomoisturemat 2 d 0. isothermtype 7 wf 110. vG_b 6.126 vG_m 0.331 permeabilitytype 3 timescale 86400. capillarytransporttype 2 mu 400 Abs 1. capil_coef 1.e4 ttf 2 +# +BoundaryCondition 1 loadTimeFunction 1 dofs 1 14 values 1 1. set 2 +# +InitialCondition 1 Conditions 1 u 0.99 dofs 1 14 set 1 +# +ConstantFunction 1 f(t) 0.5 +PiecewiseLinfunction 2 npoints 2 t 2 0 0.5 f(t) 2 323.15 303.15 +# +Set 1 noderanges {(1 12)} +Set 2 nodes 4 3 6 9 12 +# +# +# +# +#%BEGIN_CHECK% tolerance 1.e-7 +#NODE tStep 5 number 1 dof 14 unknown d value 6.17066259e-01 +#NODE tStep 5 number 7 dof 14 unknown d value 5.45874730e-01 +#%END_CHECK% + diff --git a/tests/tm/qquad01.in b/tests/tm/qquad01.in new file mode 100644 index 000000000..d51ffb44b --- /dev/null +++ b/tests/tm/qquad01.in @@ -0,0 +1,55 @@ +qquad01.out +Test of quadratic quadrilateral QQuad element, 1. step with internal source, exact solution is a quadratic profile in y direction, 2. step with heat flow prescribed on the top boundary +StationaryProblem nsteps 2 nmodules 1 +errorcheck +#vtkxml tstep_all domain_all primvars 1 6 vars 2 37 56 stype 2 +domain HeatTransfer +OutputManager tstep_all dofman_all element_all +ndofman 20 nelem 5 ncrosssect 1 nmat 1 nbc 3 nic 0 nltf 3 nset 3 +Node 1 coords 3 0.0 0.0 0.0 +Node 2 coords 3 0.0 4.0 0.0 +Node 3 coords 3 2.0 2.0 0.0 +Node 4 coords 3 3.0 1.0 0.0 +Node 5 coords 3 8.0 0.8 0.0 +Node 6 coords 3 7.0 3.0 0.0 +Node 7 coords 3 9.0 0.0 0.0 +Node 8 coords 3 9.0 4.0 0.0 +Node 9 coords 3 4.5 0.0 0.0 +Node 10 coords 3 1.5 0.5 0.0 +Node 11 coords 3 5.5 0.9 0.0 +Node 12 coords 3 0.0 2.0 0.0 +Node 13 coords 3 2.5 1.5 0.0 +Node 14 coords 3 1.0 3.0 0.0 +Node 15 coords 3 4.5 2.5 0.0 +Node 16 coords 3 4.5 4.0 0.0 +Node 17 coords 3 8.0 3.5 0.0 +Node 18 coords 3 7.5 1.9 0.0 +Node 19 coords 3 8.5 0.4 0.0 +Node 20 coords 3 9.0 2.0 0.0 +QQuad1ht 1 nodes 8 1 4 3 2 10 13 14 12 NIP 9 +QQuad1ht 2 nodes 8 1 7 5 4 9 19 11 10 NIP 9 +QQuad1ht 3 nodes 8 4 5 6 3 11 18 15 13 NIP 9 +QQuad1ht 4 nodes 8 3 6 8 2 15 17 16 14 NIP 9 +QQuad1ht 5 nodes 8 5 7 8 6 19 20 17 18 NIP 9 +SimpleTransportCS 1 mat 1 thickness 0.15 set 1 +IsoHeat 1 d 0. k 1.0 c 1.0 +BoundaryCondition 1 loadTimeFunction 1 dofs 1 10 values 1 0.0 set 2 +constantedgeload 2 loadTimeFunction 2 ndofs 1 components 1 -3.0 loadtype 2 set 3 +deadweight 3 loadTimeFunction 3 components 1 0.5 set 1 +ConstantFunction 1 f(t) 1.0 +PeakFunction 2 t 1.0 f(t) 1.0 +PeakFunction 3 t 2.0 f(t) 1.0 +Set 1 elementranges {(1 5)} +Set 2 nodes 3 1 7 9 +Set 3 elementedges 2 4 3 +#%BEGIN_CHECK% +#NODE tStep 1 number 2 dof 10 unknown d value 1.20000000e+01 +#NODE tStep 1 number 8 dof 10 unknown d value 1.20000000e+01 +#NODE tStep 1 number 16 dof 10 unknown d value 1.20000000e+01 +#NODE tStep 2 number 2 dof 10 unknown d value 4.03973323e+00 +#NODE tStep 2 number 8 dof 10 unknown d value 4.02274874e+00 +#NODE tStep 2 number 16 dof 10 unknown d value 3.98437951e+00 +#%END_CHECK% + + + diff --git a/tests/tm/simpleDarcy.in b/tests/tm/simpleDarcy.in index 11c90c8bf..5b042e023 100644 --- a/tests/tm/simpleDarcy.in +++ b/tests/tm/simpleDarcy.in @@ -16,7 +16,7 @@ tr1darcy 2 nodes 3 1 2 5 tr1darcy 3 nodes 3 2 3 5 tr1darcy 4 nodes 3 3 4 5 SimpleTransportCS 1 mat 1 set 1 -anisomass 1 d 1.000000 C 4 1.000000 0.000000 0.000000 1.000000 +anisomass 1 d 1.000000 C 3 3 {1 0 0; 0 1 0; 0 0 1} BoundaryCondition 1 loadTimeFunction 1 dofs 1 11 values 1 0.0 set 2 BoundaryCondition 2 loadTimeFunction 1 dofs 1 11 values 1 1.0 set 3 ConstantFunction 1 f(t) 1.0 diff --git a/tests/tmcemhyd/cemhyd02.in b/tests/tmcemhyd/cemhyd02.in index 86bf9aa04..f70f8d3fa 100644 --- a/tests/tmcemhyd/cemhyd02.in +++ b/tests/tmcemhyd/cemhyd02.in @@ -2,46 +2,48 @@ cemhyd02.out Test of CEMHYD3D hydration model, Q_pot = 534 J/g_cem, 300 kg cem/m3_con, i.e. max 160.2 kJ/m3_com; deltaT=160200/2.4/870=76.724 C #side YZ is kept at 20C and later released. Heat transport coefficient is assigned to opposite YZ side. The setup corresponds to 1D case. #8 independent CEMHYD3D models are used, for each integration point one instance. -TransientTransport nsteps 10 deltat 3600.0 alpha 0.5 nmodules 1 rtolf 1e-6 +TransientTransport nsteps 10 deltat 3600.0 alpha 0.5 rtolf 1e-8 nmodules 2 errorcheck -#vtkxml tstep_all domain_all vars 11 37 39 44 56 67 68 69 70 71 72 73 stype 1 +vtkxml tstep_all domain_all primvars 1 6 vars 11 37 39 44 56 67 68 69 70 71 72 73 stype 1 domain HeatTransfer OutputManager tstep_all dofman_all element_all -ndofman 8 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 1 nltf 2 nset 3 -node 1 coords 3 0.0 0.0 4.0 -node 2 coords 3 0.0 4.0 4.0 -node 3 coords 3 4.0 4.0 4.0 -node 4 coords 3 4.0 0.0 4.0 +ndofman 8 nelem 1 ncrosssect 1 nmat 1 nbc 2 nic 1 nltf 2 nset 4 +node 1 coords 3 0.0 0.0 0.4 +node 2 coords 3 0.0 0.4 0.4 +node 3 coords 3 0.4 0.4 0.4 +node 4 coords 3 0.4 0.0 0.4 node 5 coords 3 0.0 0.0 0.0 -node 6 coords 3 0.0 4.0 0.0 -node 7 coords 3 4.0 4.0 0.0 -node 8 coords 3 4.0 0.0 0.0 +node 6 coords 3 0.0 0.4 0.0 +node 7 coords 3 0.4 0.4 0.0 +node 8 coords 3 0.4 0.0 0.0 Brick1ht 1 nodes 8 1 2 3 4 5 6 7 8 #boundaryloads 2 2 5 SimpleTransportCS 1 mat 1 set 1 #Standard concrete k(conductivity)=1.7 W/m/K c(capacity)=870 J/kg/K CemhydMat 1 d 2400. k 1.7 c 870. file "cemhyd01_XML.src" eachGP 1 densityType 0 conductivityType 0 capacityType 0 castingtime 0. BoundaryCondition 1 loadTimeFunction 1 dofs 1 10 values 1 20.0 isImposedTimeFunction 2 set 2 -constantsurfaceload 2 loadTimeFunction 1 dofs 1 10 components 1 10.0 properties 1 a 50.0 loadtype 3 set 3 -InitialCondition 1 dofs 1 10 Conditions 1 u 20.0 set 1 +constantsurfaceload 2 loadTimeFunction 1 dofs 1 10 components 1 20.0 properties 1 a 5.0 loadtype 3 set 3 +InitialCondition 1 dofs 1 10 Conditions 1 u 20.0 set 4 ConstantFunction 1 f(t) 1.0 PiecewiseLinFunction 2 t 4 -1.e+5 15000 15001 1.e+7 f(t) 4 1.0 1.0 0.0 0.0 Set 1 elementranges {1} -Set 2 elementboundaries 2 1 3 +Set 2 nodes 4 1 2 5 6 Set 3 elementboundaries 2 1 5 +Set 4 noderanges {(1 8)} + #%BEGIN_CHECK% tolerance 1.e-3 ## TIME ## Check temperature #NODE tStep 2 number 1 dof 10 unknown d value 2.00000000e+01 -#NODE tStep 2 number 3 dof 10 unknown d value 2.02000723e+01 -#NODE tStep 10 number 1 dof 10 unknown d value 5.40281630e+01 -#NODE tStep 10 number 3 dof 10 unknown d value 4.12759083e+01 +#NODE tStep 2 number 3 dof 10 unknown d value 2.55030970e+01 +#NODE tStep 10 number 1 dof 10 unknown d value 5.87740182e+01 +#NODE tStep 10 number 3 dof 10 unknown d value 5.25887194e+01 ## Check degree of hydration -#ELEMENT tStep 2 number 1 gp 1 keyword 39 component 1 value 2.28292097e-02 -#ELEMENT tStep 2 number 1 gp 5 keyword 39 component 1 value 2.85766881e-02 -#ELEMENT tStep 10 number 1 gp 1 keyword 39 component 1 value 4.66584656e-01 -#ELEMENT tStep 10 number 1 gp 5 keyword 39 component 1 value 3.91491384e-01 +#ELEMENT tStep 2 number 1 gp 1 keyword 39 component 1 value 6.53565654e-02 +#ELEMENT tStep 2 number 1 gp 5 keyword 39 component 1 value 6.53620289e-02 +#ELEMENT tStep 10 number 1 gp 1 keyword 39 component 1 value 5.41535843e-01 +#ELEMENT tStep 10 number 1 gp 5 keyword 39 component 1 value 5.80581479e-01 #%END_CHECK% diff --git a/tests/tmfm/simpleRVEStokes.out-gp1 b/tests/tmfm/simpleRVEStokes.out-gp1 deleted file mode 100644 index db40e20a8..000000000 --- a/tests/tmfm/simpleRVEStokes.out-gp1 +++ /dev/null @@ -1,112 +0,0 @@ - -============================================================== -Output for time 1.00000000e+00 -============================================================== -Output for domain 1 - - -DofManager output: ------------------- -Node 1 ( 1): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 2 ( 2): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 3 ( 3): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 4 ( 4): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 5 ( 5): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 6 ( 6): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 7 ( 7): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 8 ( 8): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 9 ( 9): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - - - - -Element output: ---------------- -element 1 ( 1) : - GP 1.1 : GP 1.2 : GP 1.3 :element 2 ( 2) : - GP 1.1 : GP 1.2 : GP 1.3 : - - -============================================================== -Output for time 1.00000000e+00 -============================================================== -Output for domain 1 - - -DofManager output: ------------------- -Node 1 ( 1): - dof 7 d 1.80612496e-02 - dof 8 d 1.27713178e-01 - dof 11 d -2.74259451e-01 -Node 2 ( 2): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 3 ( 3): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 4 ( 4): - dof 7 d 1.26119692e-01 - dof 8 d 1.49219173e-01 - dof 11 d 1.25626730e-01 -Node 5 ( 5): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 6 ( 6): - dof 7 d 5.69029649e-02 - dof 8 d 5.06542287e-02 -Node 7 ( 7): - dof 7 d 8.13265057e-02 - dof 8 d 1.19543740e-01 -Node 8 ( 8): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 9 ( 9): - dof 7 d 1.13314256e-01 - dof 8 d 6.97671389e-02 - - - - -Element output: ---------------- -element 1 ( 1) : - GP 1.1 : - deviatoric stresses -1.3611e-01 1.5401e-01 -4.9632e-02 - GP 1.2 : - deviatoric stresses -6.8687e-02 4.4606e-02 -1.3034e-01 - GP 1.3 : - deviatoric stresses -9.8955e-02 1.7739e-01 1.1237e-01 -element 2 ( 2) : - GP 1.1 : - deviatoric stresses -6.2654e-02 8.2295e-02 7.4963e-03 - GP 1.2 : - deviatoric stresses -1.5476e-01 9.0123e-02 -4.7731e-02 - GP 1.3 : - deviatoric stresses -3.0519e-01 1.6534e-01 -8.5957e-02 - - diff --git a/tests/tmfm/simpleRVEStokes.out-gp2 b/tests/tmfm/simpleRVEStokes.out-gp2 deleted file mode 100644 index 881153cba..000000000 --- a/tests/tmfm/simpleRVEStokes.out-gp2 +++ /dev/null @@ -1,112 +0,0 @@ - -============================================================== -Output for time 1.00000000e+00 -============================================================== -Output for domain 1 - - -DofManager output: ------------------- -Node 1 ( 1): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 2 ( 2): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 3 ( 3): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 4 ( 4): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 5 ( 5): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 6 ( 6): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 7 ( 7): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 8 ( 8): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 9 ( 9): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - - - - -Element output: ---------------- -element 1 ( 1) : - GP 1.1 : GP 1.2 : GP 1.3 :element 2 ( 2) : - GP 1.1 : GP 1.2 : GP 1.3 : - - -============================================================== -Output for time 1.00000000e+00 -============================================================== -Output for domain 1 - - -DofManager output: ------------------- -Node 1 ( 1): - dof 7 d 1.38585411e-02 - dof 8 d 4.17468035e-02 - dof 11 d 9.84836012e-02 -Node 2 ( 2): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 3 ( 3): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 4 ( 4): - dof 7 d 2.28266620e-01 - dof 8 d 1.42451446e-01 - dof 11 d 3.68272239e-01 -Node 5 ( 5): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 6 ( 6): - dof 7 d 1.51597382e-01 - dof 8 d -2.22002616e-02 -Node 7 ( 7): - dof 7 d 1.30320834e-01 - dof 8 d 5.65290583e-02 -Node 8 ( 8): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 9 ( 9): - dof 7 d 2.32549252e-01 - dof 8 d -1.68049750e-03 - - - - -Element output: ---------------- -element 1 ( 1) : - GP 1.1 : - deviatoric stresses -5.0829e-04 1.2373e-01 2.9458e-02 - GP 1.2 : - deviatoric stresses 6.5165e-04 -1.9130e-02 1.4046e-01 - GP 1.3 : - deviatoric stresses 8.6918e-02 -1.3623e-01 2.9422e-01 -element 2 ( 2) : - GP 1.1 : - deviatoric stresses -5.8361e-02 8.3900e-02 -1.0108e-02 - GP 1.2 : - deviatoric stresses -4.4668e-01 2.3702e-01 1.6065e-01 - GP 1.3 : - deviatoric stresses -6.6255e-01 3.4496e-01 1.1961e-01 - - diff --git a/tests/tmfm/simpleRVEStokes.out-gp3 b/tests/tmfm/simpleRVEStokes.out-gp3 deleted file mode 100644 index 8d57dcac9..000000000 --- a/tests/tmfm/simpleRVEStokes.out-gp3 +++ /dev/null @@ -1,112 +0,0 @@ - -============================================================== -Output for time 1.00000000e+00 -============================================================== -Output for domain 1 - - -DofManager output: ------------------- -Node 1 ( 1): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 2 ( 2): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 3 ( 3): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 4 ( 4): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 5 ( 5): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 6 ( 6): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 7 ( 7): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 8 ( 8): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 9 ( 9): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - - - - -Element output: ---------------- -element 1 ( 1) : - GP 1.1 : GP 1.2 : GP 1.3 :element 2 ( 2) : - GP 1.1 : GP 1.2 : GP 1.3 : - - -============================================================== -Output for time 1.00000000e+00 -============================================================== -Output for domain 1 - - -DofManager output: ------------------- -Node 1 ( 1): - dof 7 d -5.19863485e-03 - dof 8 d -9.15327335e-02 - dof 11 d 3.79760024e-01 -Node 2 ( 2): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 3 ( 3): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 4 ( 4): - dof 7 d 9.17421075e-02 - dof 8 d -1.57294306e-02 - dof 11 d 2.28584225e-01 -Node 5 ( 5): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 6 ( 6): - dof 7 d 8.87244946e-02 - dof 8 d -7.40452421e-02 -Node 7 ( 7): - dof 7 d 4.27276892e-02 - dof 8 d -6.86829316e-02 -Node 8 ( 8): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 9 ( 9): - dof 7 d 1.09166088e-01 - dof 8 d -7.38459200e-02 - - - - -Element output: ---------------- -element 1 ( 1) : - GP 1.1 : - deviatoric stresses 1.4038e-01 -3.8916e-02 8.0055e-02 - GP 1.2 : - deviatoric stresses 7.1726e-02 -6.4795e-02 2.7167e-01 - GP 1.3 : - deviatoric stresses 1.8706e-01 -3.1625e-01 1.7020e-01 -element 2 ( 2) : - GP 1.1 : - deviatoric stresses 8.0177e-03 -3.4773e-03 -1.7602e-02 - GP 1.2 : - deviatoric stresses -2.7478e-01 1.3752e-01 2.0584e-01 - GP 1.3 : - deviatoric stresses -3.2929e-01 1.6478e-01 2.0544e-01 - - diff --git a/tests/tmfm/simpleRVEStokes.out-gp4 b/tests/tmfm/simpleRVEStokes.out-gp4 deleted file mode 100644 index 7a1f3fdf2..000000000 --- a/tests/tmfm/simpleRVEStokes.out-gp4 +++ /dev/null @@ -1,112 +0,0 @@ - -============================================================== -Output for time 1.00000000e+00 -============================================================== -Output for domain 1 - - -DofManager output: ------------------- -Node 1 ( 1): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 2 ( 2): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 3 ( 3): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 4 ( 4): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 5 ( 5): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 6 ( 6): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 7 ( 7): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 8 ( 8): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 9 ( 9): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - - - - -Element output: ---------------- -element 1 ( 1) : - GP 1.1 : GP 1.2 : GP 1.3 :element 2 ( 2) : - GP 1.1 : GP 1.2 : GP 1.3 : - - -============================================================== -Output for time 1.00000000e+00 -============================================================== -Output for domain 1 - - -DofManager output: ------------------- -Node 1 ( 1): - dof 7 d -9.95926380e-04 - dof 8 d -5.56635910e-03 - dof 11 d 7.01697158e-03 -Node 2 ( 2): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 3 ( 3): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 - dof 11 d 0.00000000e+00 -Node 4 ( 4): - dof 7 d -1.04048201e-02 - dof 8 d -8.96170321e-03 - dof 11 d -1.40612840e-02 -Node 5 ( 5): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 6 ( 6): - dof 7 d -5.96992274e-03 - dof 8 d -1.19075184e-03 -Node 7 ( 7): - dof 7 d -6.26663944e-03 - dof 8 d -5.66825035e-03 -Node 8 ( 8): - dof 7 d 0.00000000e+00 - dof 8 d 0.00000000e+00 -Node 9 ( 9): - dof 7 d -1.00689081e-02 - dof 8 d -2.39828357e-03 - - - - -Element output: ---------------- -element 1 ( 1) : - GP 1.1 : - deviatoric stresses 4.7783e-03 -8.6381e-03 9.6453e-04 - GP 1.2 : - deviatoric stresses 2.3875e-03 -1.0596e-03 8.7719e-04 - GP 1.3 : - deviatoric stresses 1.1835e-03 -2.6353e-03 -1.1654e-02 -element 2 ( 2) : - GP 1.1 : - deviatoric stresses 3.7247e-03 -5.0824e-03 2.8118e-06 - GP 1.2 : - deviatoric stresses 1.7139e-02 -9.3744e-03 -2.5446e-03 - GP 1.3 : - deviatoric stresses 2.8069e-02 -1.4840e-02 -1.2949e-04 - - diff --git a/tests/tmsm/MPS_02_casting_in.sm b/tests/tmsm/MPS_02_casting_in.sm new file mode 100644 index 000000000..326efddb0 --- /dev/null +++ b/tests/tmsm/MPS_02_casting_in.sm @@ -0,0 +1,138 @@ +MPS_02_casting_out.sm +# +drying creep of plane-stress elements in tension, casting at time = 14 days +# +# element 1: basic creep, staggered problem +# element 2: creep at decreased humidity, staggered problem +# element 3: drying creep, staggered problem, p = 2 (standard value) or equivalently \tilde{p} = 2, zero shrinkage +# element 4: drying creep, staggered problem, p = infinity (zero size effect) or quivalently \tilde{p} = 1, zero shrinkage +# element 5: drying creep, staggered problem, p = -1.5 (correct size effect) or quivalently \tilde{p} = 0.6, zero shrinkage +# element 6: shrinkage +# +StaticStructural nsteps 25 nsteps 25 prescribedTimes 25 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. nmodules 1 +# +errorcheck +# vtkxml tstep_step 1 domain_all vars 2 1 4 primvars 1 1 +# +domain 2dPlaneStress +# +OutputManager tstep_all dofman_all element_all +ndofman 24 nelem 6 ncrosssect 4 nmat 5 nbc 3 nic 0 nltf 2 nset 3 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.1 0.0 0.0 +node 3 coords 3 0.0 0.1 0.0 +node 4 coords 3 0.1 0.1 0.0 +# +node 5 coords 3 0.0 0.2 0.0 +node 6 coords 3 0.1 0.2 0.0 +node 7 coords 3 0.0 0.3 0.0 +node 8 coords 3 0.1 0.3 0.0 +# +node 9 coords 3 0.0 0.4 0.0 +node 10 coords 3 0.1 0.4 0.0 +node 11 coords 3 0.0 0.5 0.0 +node 12 coords 3 0.1 0.5 0.0 +# +node 13 coords 3 0.0 0.6 0.0 +node 14 coords 3 0.1 0.6 0.0 +node 15 coords 3 0.0 0.7 0.0 +node 16 coords 3 0.1 0.7 0.0 +# +node 17 coords 3 0.0 0.8 0.0 +node 18 coords 3 0.1 0.8 0.0 +node 19 coords 3 0.0 0.9 0.0 +node 20 coords 3 0.1 0.9 0.0 +# +node 21 coords 3 0.0 1.0 0.0 +node 22 coords 3 0.1 1.0 0.0 +node 23 coords 3 0.0 1.1 0.0 +node 24 coords 3 0.1 1.1 0.0 +# +# +# ELEMENTS +# +planestress2d 1 nodes 4 1 2 4 3 crossSect 1 +# +planestress2d 2 nodes 4 5 6 8 7 crossSect 1 +# +planestress2d 3 nodes 4 9 10 12 11 crossSect 1 +# +planestress2d 4 nodes 4 13 14 16 15 crossSect 2 +# +planestress2d 5 nodes 4 17 18 20 19 crossSect 3 +# +planestress2d 6 nodes 4 21 22 24 23 crossSect 4 +# +Set 1 nodes 6 1 5 9 13 17 21 +Set 2 nodes 6 3 7 11 15 19 23 +Set 3 nodes 12 2 4 6 8 10 12 14 16 18 20 22 24 +# +# CROSSECTION +# +SimpleCS 1 thick 1.0 material 1 +SimpleCS 2 thick 1.0 material 2 +SimpleCS 3 thick 1.0 material 3 +SimpleCS 4 thick 1.0 material 4 +# +# +# MATERIAL +# +mps 1 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 mus 5.e-6 castingTime 14. preCastingTimeMat 5 +# +mps 2 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 k3 35. p 1000. castingTime 14. preCastingTimeMat 5 +# +mps 3 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 mus 2.e-10 p -1.5 castingTime 14. preCastingTimeMat 5 +# +mps 4 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0025 mus 5.e-6 castingTime 14. preCastingTimeMat 5 +# +IsoLE 5 d 0. n 0.2 E 1.e-6 talpha 0. +# +# BOUNDARY CONDITIONS +# +BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 1 values 1 0. set 2 +NodalLoad 3 loadTimeFunction 2 dofs 2 1 2 components 2 0.05 0. set 3 +# +# +# TIME FUNCTION +# +ConstantFunction 1 f(t) 1.0 +HeavisideLTF 2 origin 14. value 1.0 +# +# +#%BEGIN_CHECK% tolerance 1.e-11 +#NODE tStep 7 number 2 dof 1 unknown d value 4.928538e-06 +#NODE tStep 13 number 2 dof 1 unknown d value 6.080910e-06 +#NODE tStep 19 number 2 dof 1 unknown d value 7.886156e-06 +#NODE tStep 25 number 2 dof 1 unknown d value 1.079582e-05 +#NODE tStep 28 number 2 dof 1 unknown d value 1.221882e-05 +#NODE tStep 7 number 6 dof 1 unknown d value 4.689125e-06 +#NODE tStep 13 number 6 dof 1 unknown d value 5.757860e-06 +#NODE tStep 19 number 6 dof 1 unknown d value 7.369494e-06 +#NODE tStep 25 number 6 dof 1 unknown d value 1.107454e-05 +#NODE tStep 28 number 6 dof 1 unknown d value 1.314412e-05 +#NODE tStep 7 number 10 dof 1 unknown d value 4.928538e-06 +#NODE tStep 13 number 10 dof 1 unknown d value 6.080910e-06 +#NODE tStep 19 number 10 dof 1 unknown d value 8.063393e-06 +#NODE tStep 25 number 10 dof 1 unknown d value 1.594227e-05 +#NODE tStep 28 number 10 dof 1 unknown d value 3.020580e-05 +#NODE tStep 7 number 14 dof 1 unknown d value 4.928538e-06 +#NODE tStep 13 number 14 dof 1 unknown d value 6.080910e-06 +#NODE tStep 19 number 14 dof 1 unknown d value 1.061499e-05 +#NODE tStep 25 number 14 dof 1 unknown d value 2.016076e-05 +#NODE tStep 28 number 14 dof 1 unknown d value 2.554121e-05 +#NODE tStep 7 number 18 dof 1 unknown d value 4.928538e-06 +#NODE tStep 13 number 18 dof 1 unknown d value 6.080910e-06 +#NODE tStep 19 number 18 dof 1 unknown d value 1.198810e-05 +#NODE tStep 25 number 18 dof 1 unknown d value 1.981528e-05 +#NODE tStep 28 number 18 dof 1 unknown d value 2.211433e-05 +#NODE tStep 7 number 22 dof 1 unknown d value 4.928538e-06 +#NODE tStep 13 number 22 dof 1 unknown d value 6.080910e-06 +#NODE tStep 19 number 22 dof 1 unknown d value -3.693661e-05 +#NODE tStep 25 number 22 dof 1 unknown d value -7.905773e-05 +#NODE tStep 28 number 22 dof 1 unknown d value -8.979420e-05 +#%END_CHECK% diff --git a/tests/tmsm/MPS_02_casting_in.tm b/tests/tmsm/MPS_02_casting_in.tm new file mode 100644 index 000000000..2d204d53d --- /dev/null +++ b/tests/tmsm/MPS_02_casting_in.tm @@ -0,0 +1,92 @@ +MPS_02_casting_out.tm +element 1 constant rh = 0.98, element 2 constant rh = 0.5, remaining elements drying from rh = 0.98 to 0.5, drying starts at 14 days +# +transienttransport nsteps 28 alpha 0.5 exportfields 1 6 prescribedtimes 28 1.e-10 13. 14. 14.0001 14.0002 14.0005 14.001 14.002 14.005 14.01 14.02 14.05 14.1 14.2 14.5 15. 16. 19. 24. 34. 64. 114. 214. 514. 1014. 2014. 5014. 10014. +# nmodules 1 +# +# vtkxml tstep_all domain_all primvars 1 3 +# +domain mass1transfer +# +OutputManager tstep_all dofman_all element_all +ndofman 24 nelem 6 ncrosssect 1 nmat 1 nbc 3 nic 2 nltf 3 nset 5 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.1 0.0 0.0 +node 3 coords 3 0.0 0.1 0.0 +node 4 coords 3 0.1 0.1 0.0 +# +node 5 coords 3 0.0 0.2 0.0 +node 6 coords 3 0.1 0.2 0.0 +node 7 coords 3 0.0 0.3 0.0 +node 8 coords 3 0.1 0.3 0.0 +# +node 9 coords 3 0.0 0.4 0.0 +node 10 coords 3 0.1 0.4 0.0 +node 11 coords 3 0.0 0.5 0.0 +node 12 coords 3 0.1 0.5 0.0 +# +node 13 coords 3 0.0 0.6 0.0 +node 14 coords 3 0.1 0.6 0.0 +node 15 coords 3 0.0 0.7 0.0 +node 16 coords 3 0.1 0.7 0.0 +# +node 17 coords 3 0.0 0.8 0.0 +node 18 coords 3 0.1 0.8 0.0 +node 19 coords 3 0.0 0.9 0.0 +node 20 coords 3 0.1 0.9 0.0 +# +node 21 coords 3 0.0 1.0 0.0 +node 22 coords 3 0.1 1.0 0.0 +node 23 coords 3 0.0 1.1 0.0 +node 24 coords 3 0.1 1.1 0.0 +# +# +# ELEMENTS +# +quad1mt 1 nodes 4 1 2 4 3 +# +quad1mt 2 nodes 4 5 6 8 7 +# +quad1mt 3 nodes 4 9 10 12 11 +# +quad1mt 4 nodes 4 13 14 16 15 +# +quad1mt 5 nodes 4 17 18 20 19 +# +quad1mt 6 nodes 4 21 22 24 23 +# +Set 1 elementranges {(1 6)} +Set 2 elements 1 1 +Set 3 elements 1 2 +Set 4 elements 4 3 4 5 6 +Set 5 elements 5 1 3 4 5 6 +# +# CROSSECTION +# +SimpleTransportCS 1 thickness 1.0 mat 1 set 1 +# +# +# MATERIAL +# +isolinmoisturemat 1 d 2400. perm 1.e-5 capa 1. +# +# +# BOUNDARY & INITIAL CONDITIONS +# +BoundaryCondition 1 loadTimeFunction 1 dofs 1 14 values 1 0.98 set 2 +BoundaryCondition 2 loadTimeFunction 2 dofs 1 14 values 1 1. set 3 +BoundaryCondition 3 loadTimeFunction 3 dofs 1 14 values 1 1. set 4 +# +InitialCondition 1 Conditions 1 u 0.98 dofs 1 14 set 5 +InitialCondition 2 Conditions 1 u 0.5 dofs 1 14 set 3 +# +# +# TIME FUNCTION +# +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 0.5 +PiecewiseLinfunction 3 npoints 8 t 8 -1.e6 14.0 14.1 15. 24. 114. 1014. 10014. f(t) 8 0.98 0.98 0.98 0.9 0.8 0.7 0.6 0.5 diff --git a/tests/tmsm/MPS_02_casting_tmsm.in b/tests/tmsm/MPS_02_casting_tmsm.in new file mode 100644 index 000000000..e29b636b1 --- /dev/null +++ b/tests/tmsm/MPS_02_casting_tmsm.in @@ -0,0 +1,3 @@ +MPS_02_casting_tmsm.out +tests on creep at variable relative humidity, structural material is cast at time = 14 days, the results correspond to MPS_02_tmsm.in +StaggeredProblem nsteps 28 prob1 "MPS_02_casting_in.tm" prob2 "MPS_02_casting_in.sm" prescribedtimes 28 0. 13.9999999999 14.0000000001 14.0001 14.0002 14.0005 14.001 14.002 14.005 14.01 14.02 14.05 14.1 14.2 14.5 15. 16. 19. 24. 34. 64. 114. 214. 514. 1014. 2014. 5014. 10014. diff --git a/tests/tmsm/MPS_02_in.sm b/tests/tmsm/MPS_02_in.sm index 36d022d32..d54563ec0 100644 --- a/tests/tmsm/MPS_02_in.sm +++ b/tests/tmsm/MPS_02_in.sm @@ -81,13 +81,13 @@ SimpleCS 4 thick 1.0 material 4 # # MATERIAL # -mps 1 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 t0 7. mus 5.e-6 +mps 1 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 mus 5.e-6 # -mps 2 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 t0 7. k3 35. p 1000. +mps 2 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 k3 35. p 1000. # -mps 3 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 t0 7. mus 2.e-10 p -1.5 +mps 3 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 mus 2.e-10 p -1.5 # -mps 4 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0025 t0 7. mus 5.e-6 +mps 4 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0025 mus 5.e-6 # # # BOUNDARY CONDITIONS diff --git a/tests/tmsm/MPS_02_sec_in.sm b/tests/tmsm/MPS_02_sec_in.sm index 47a7d7d08..f75443354 100644 --- a/tests/tmsm/MPS_02_sec_in.sm +++ b/tests/tmsm/MPS_02_sec_in.sm @@ -81,13 +81,13 @@ SimpleCS 4 thick 1.0 material 4 # # MATERIAL # -mps 1 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 2 ksh 0.0 t0 6.048e5 mus 5.787037e-11 +mps 1 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 2 ksh 0.0 mus 5.787037e-11 # -mps 2 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 2 ksh 0.0 t0 6.048e5 k3 35. p 1000. +mps 2 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 2 ksh 0.0 k3 35. p 1000. # -mps 3 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 2 ksh 0.0 t0 6.048e5 mus 2.314815e-15 p -1.5 +mps 3 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 2 ksh 0.0 mus 2.314815e-15 p -1.5 # -mps 4 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 2 ksh 0.0025 t0 6.048e5 mus 5.787037e-11 +mps 4 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 2 ksh 0.0025 mus 5.787037e-11 # # # BOUNDARY CONDITIONS diff --git a/tests/tmsm/MPS_02_tmsm.in b/tests/tmsm/MPS_02_tmsm.in index 2523c382c..0d2f1717f 100644 --- a/tests/tmsm/MPS_02_tmsm.in +++ b/tests/tmsm/MPS_02_tmsm.in @@ -1,3 +1,3 @@ MPS_02_tmsm.out tests on creep at variable relative humidity -StaggeredProblem nsteps 26 prob1 "MPS_02_in.tm" prob2 "MPS_02_in.sm" prescribedtimes 26 1.e-10 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. +StaggeredProblem nsteps 26 prob1 "MPS_02_in.tm" prob2 "MPS_02_in.sm" prescribedtimes 26 1.e-10 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. diff --git a/tests/tmsm/MPS_03_in.sm b/tests/tmsm/MPS_03_in.sm index a9d674636..63250d453 100644 --- a/tests/tmsm/MPS_03_in.sm +++ b/tests/tmsm/MPS_03_in.sm @@ -80,11 +80,11 @@ SimpleCS 3 thick 1.0 material 3 # # MATERIAL # -mps 1 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 1 ksh 0.0 t0 7. mus 5.e-6 +mps 1 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 1 ksh 0.0 mus 5.e-6 # -mps 2 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 1 ksh 0.0 t0 7. mus 5.e-6 kTm 0.0202 +mps 2 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 1 ksh 0.0 mus 5.e-6 kTm 0.0202 # -mps 3 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 1 ksh 0.0 t0 7. mus 5.e-6 kTm 0.0025 kTc 0.000125 +mps 3 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 1 ksh 0.0 mus 5.e-6 kTm 0.0025 kTc 0.000125 # # BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 1 diff --git a/tests/tmsm/MPS_03_sec_in.sm b/tests/tmsm/MPS_03_sec_in.sm index 4b8e95935..1a8044a91 100644 --- a/tests/tmsm/MPS_03_sec_in.sm +++ b/tests/tmsm/MPS_03_sec_in.sm @@ -80,11 +80,11 @@ SimpleCS 3 thick 1.0 material 3 # # MATERIAL # -mps 1 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 1 ksh 0.0 t0 6.048e5 mus 5.787037e-11 +mps 1 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 1 ksh 0.0 mus 5.787037e-11 # -mps 2 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 1 ksh 0.0 t0 6.048e5 mus 5.787037e-11 kTm 0.0202 +mps 2 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 1 ksh 0.0 mus 5.787037e-11 kTm 0.0202 # -mps 3 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 1 ksh 0.0 t0 6.048e5 mus 5.787037e-11 kTm 0.0025 kTc 0.000125 +mps 3 d 0. n 0.2 talpha 0.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 8.64e-2 endoftimeofinterest 8.64e8 relMatAge 6.048e5 CoupledAnalysisType 1 ksh 0.0 mus 5.787037e-11 kTm 0.0025 kTc 0.000125 # # BoundaryCondition 1 loadTimeFunction 1 dofs 2 1 2 values 2 0. 0. set 1 diff --git a/tests/tmsm/MPS_04_in.sm b/tests/tmsm/MPS_04_in.sm index 8b738ec4f..44d94eb9e 100644 --- a/tests/tmsm/MPS_04_in.sm +++ b/tests/tmsm/MPS_04_in.sm @@ -65,13 +65,13 @@ SimpleCS 4 thick 1.0 material 4 # # MATERIAL # -mps 1 d 0. n 0.2 talpha 0. referencetemperature 296. mode 0 fc 30. cc 340. w/c 0.523 a/c 5.28 stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 t0 7. k3 35. p 1000. +mps 1 d 0. n 0.2 talpha 0. referencetemperature 296. mode 0 fc 30. cc 340. w/c 0.523 a/c 5.28 stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 k3 35. p 1000. # -mpsdammat 2 d 0. n 0.2 talpha 0. mode 0 fc 30. cc 340. w/c 0.523 a/c 5.28 stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 t0 7. k3 35. p 1000. timeDepFracturing fib_s 0.25 +mpsdammat 2 d 0. n 0.2 talpha 0. mode 0 fc 30. cc 340. w/c 0.523 a/c 5.28 stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 k3 35. p 1000. timeDepFracturing fib_s 0.25 # -mpsdammat 3 d 0. n 0.2 talpha 0. mode 0 fc 30. cc 340. w/c 0.523 a/c 5.28 stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 t0 7. k3 35. p 1000. damlaw 0 ft 2.0 gf 80e-6 isotropic +mpsdammat 3 d 0. n 0.2 talpha 0. mode 0 fc 30. cc 340. w/c 0.523 a/c 5.28 stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 k3 35. p 1000. damlaw 0 ft 2.0 gf 80e-6 isotropic # -mpsdammat 4 d 0. n 0.2 talpha 0. mode 0 fc 30. cc 340. w/c 0.523 a/c 5.28 stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 t0 7. k3 35. p 1000. damlaw 0 ft28 2.0 gf28 80e-6 fib_s 0.25 isotropic timeDepFracturing +mpsdammat 4 d 0. n 0.2 talpha 0. mode 0 fc 30. cc 340. w/c 0.523 a/c 5.28 stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 k3 35. p 1000. damlaw 0 ft28 2.0 gf28 80e-6 fib_s 0.25 isotropic timeDepFracturing # # BOUNDARY CONDITIONS # diff --git a/tests/tmsm/MPS_05_in.sm b/tests/tmsm/MPS_05_in.sm index 1da62540f..2edd23286 100644 --- a/tests/tmsm/MPS_05_in.sm +++ b/tests/tmsm/MPS_05_in.sm @@ -80,13 +80,13 @@ SimpleCS 4 thick 1.0 material 4 # # MATERIAL # -mps 1 d 0. n 0.2 talpha 10.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 3 t0 7. mus 5.e-6 kTm 0.0202 +mps 1 d 0. n 0.2 talpha 10.e-6 referencetemperature 298. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 3 mus 5.e-6 kTm 0.0202 # -mps 2 d 0. n 0.2 talpha 10.e-6 referencetemperature 25. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 3 t0 7. mus 5.e-6 kTm 0.0202 temperInCelsius +mps 2 d 0. n 0.2 talpha 10.e-6 referencetemperature 25. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 3 mus 5.e-6 kTm 0.0202 temperInCelsius # -mps 3 d 0. n 0.2 talpha 0.e-6 referencetemperature 298.15 mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 3 t0 7. mus 5.e-6 kTm 0.0202 +mps 3 d 0. n 0.2 talpha 0.e-6 referencetemperature 298.15 mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 3 mus 5.e-6 kTm 0.0202 # -mps 4 d 0. n 0.2 talpha 0.e-6 referencetemperature 25. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 3 t0 7. mus 5.e-6 kTm 0.0202 temperInCelsius +mps 4 d 0. n 0.2 talpha 0.e-6 referencetemperature 25. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 3 mus 5.e-6 kTm 0.0202 temperInCelsius # # # diff --git a/tests/tmsm/MPS_06_casting_in.sm b/tests/tmsm/MPS_06_casting_in.sm new file mode 100644 index 000000000..d43feaff5 --- /dev/null +++ b/tests/tmsm/MPS_06_casting_in.sm @@ -0,0 +1,126 @@ +MPS_06_casting_out.sm +drying creep described of plane-stress elements in tension, casting at time = 14 days +# +# element 1: autogenous shrinkage - "fib prediction" +# element 2: autogenous shrinkage - specification +# element 3: drying shrinkage +# element 4: drying and autogenous shrinkage +# element 5: autogenous shrinkage - "B4 prediction" +# +StaticStructural nsteps 25 prescribedTimes 25 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. nmodules 1 miniter 1 +# +errorcheck +#vtkxml tstep_step 1 domain_all vars 2 1 4 primvars 1 1 +# +domain 2dPlaneStress +# +OutputManager tstep_all dofman_all element_all +ndofman 20 nelem 5 ncrosssect 5 nmat 6 nbc 2 nic 0 nltf 2 nset 3 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.1 0.0 0.0 +node 3 coords 3 0.0 0.1 0.0 +node 4 coords 3 0.1 0.1 0.0 +# +node 5 coords 3 0.0 0.2 0.0 +node 6 coords 3 0.1 0.2 0.0 +node 7 coords 3 0.0 0.3 0.0 +node 8 coords 3 0.1 0.3 0.0 +# +node 9 coords 3 0.0 0.4 0.0 +node 10 coords 3 0.1 0.4 0.0 +node 11 coords 3 0.0 0.5 0.0 +node 12 coords 3 0.1 0.5 0.0 +# +node 13 coords 3 0.0 0.6 0.0 +node 14 coords 3 0.1 0.6 0.0 +node 15 coords 3 0.0 0.7 0.0 +node 16 coords 3 0.1 0.7 0.0 +# +node 17 coords 3 0.0 0.8 0.0 +node 18 coords 3 0.1 0.8 0.0 +node 19 coords 3 0.0 0.9 0.0 +node 20 coords 3 0.1 0.9 0.0 +# +# +# ELEMENTS +# +planestress2d 1 nodes 4 1 2 4 3 crossSect 1 +# +planestress2d 2 nodes 4 5 6 8 7 crossSect 2 +# +planestress2d 3 nodes 4 9 10 12 11 crossSect 3 +# +planestress2d 4 nodes 4 13 14 16 15 crossSect 4 +# +planestress2d 5 nodes 4 17 18 20 19 crossSect 5 +# +Set 1 nodes 10 1 3 5 7 9 11 13 15 17 19 +Set 2 nodes 5 1 5 9 13 17 +Set 3 nodes 10 2 4 6 8 10 12 14 16 18 20 +# +# CROSSECTION +# +SimpleCS 1 thick 1.0 material 1 +SimpleCS 2 thick 1.0 material 2 +SimpleCS 3 thick 1.0 material 3 +SimpleCS 4 thick 1.0 material 4 +SimpleCS 5 thick 1.0 material 5 +# +# +# MATERIAL +# +mps 1 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 mus 5.e-6 alpha_as 700. castingTime 14. preCastingTimeMat 6 +# +mps 2 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 mus 5.e-6 eps_cas0 -100.e-6 castingTime 14. preCastingTimeMat 6 +# +mps 3 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.001 mus 5.e-6 castingTime 14. preCastingTimeMat 6 +# +mps 4 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.001 mus 5.e-6 eps_cas0 -100.e-6 castingTime 14. preCastingTimeMat 6 +# +mps 5 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 mus 5.e-6 b4_cem_type 0 castingTime 14. preCastingTimeMat 6 +# +IsoLE 6 d 0. n 0.2 E 1.e-6 talpha 0. +# +# BOUNDARY CONDITIONS +# +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0. set 2 +# +# +# TIME FUNCTION +# +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 1.0 +# +# +#%BEGIN_CHECK% tolerance 1e-11 +#NODE tStep 7 number 2 dof 1 unknown d value -1.327349e-09 +#NODE tStep 13 number 2 dof 1 unknown d value -1.088481e-07 +#NODE tStep 19 number 2 dof 1 unknown d value -1.835871e-06 +#NODE tStep 25 number 2 dof 1 unknown d value -4.207208e-06 +#NODE tStep 28 number 2 dof 1 unknown d value -4.215292e-06 +#NODE tStep 7 number 6 dof 1 unknown d value -2.955902e-09 +#NODE tStep 13 number 6 dof 1 unknown d value -2.423963e-07 +#NODE tStep 19 number 6 dof 1 unknown d value -4.088342e-06 +#NODE tStep 25 number 6 dof 1 unknown d value -9.369127e-06 +#NODE tStep 28 number 6 dof 1 unknown d value -9.387129e-06 +#NODE tStep 7 number 10 dof 1 unknown d value 0.000000e+00 +#NODE tStep 13 number 10 dof 1 unknown d value 0.000000e+00 +#NODE tStep 19 number 10 dof 1 unknown d value -1.800000e-05 +#NODE tStep 25 number 10 dof 1 unknown d value -3.800000e-05 +#NODE tStep 28 number 10 dof 1 unknown d value -4.800000e-05 +#NODE tStep 7 number 14 dof 1 unknown d value -2.955903e-09 +#NODE tStep 13 number 14 dof 1 unknown d value -2.423963e-07 +#NODE tStep 19 number 14 dof 1 unknown d value -2.020166e-05 +#NODE tStep 25 number 14 dof 1 unknown d value -4.231684e-05 +#NODE tStep 28 number 14 dof 1 unknown d value -5.428133e-05 +#NODE tStep 7 number 18 dof 1 unknown d value -4.076207e-15 +#NODE tStep 13 number 18 dof 1 unknown d value -3.641128e-12 +#NODE tStep 19 number 18 dof 1 unknown d value -4.435082e-06 +#NODE tStep 25 number 18 dof 1 unknown d value -8.024425e-06 +#NODE tStep 28 number 18 dof 1 unknown d value -8.035914e-06 +#%END_CHECK% diff --git a/tests/tmsm/MPS_06_casting_in.tm b/tests/tmsm/MPS_06_casting_in.tm new file mode 100644 index 000000000..6d8a9a291 --- /dev/null +++ b/tests/tmsm/MPS_06_casting_in.tm @@ -0,0 +1,85 @@ +MPS_06_casting_out.tm +element 1 constant rh = 0.98, element 2 constant rh = 0.5, remaining elements drying from rh = 0.98 to 0.5, drying starts at 14 days +# +transienttransport nsteps 26 alpha 0.5 exportfields 1 6 prescribedtimes 26 1.e-10 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. +# nmodules 1 +# +# vtkxml tstep_all domain_all primvars 1 3 +# +domain mass1transfer +# +OutputManager tstep_all dofman_all element_all +ndofman 20 nelem 5 ncrosssect 1 nmat 1 nbc 3 nic 2 nltf 3 nset 5 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.1 0.0 0.0 +node 3 coords 3 0.0 0.1 0.0 +node 4 coords 3 0.1 0.1 0.0 +# +node 5 coords 3 0.0 0.2 0.0 +node 6 coords 3 0.1 0.2 0.0 +node 7 coords 3 0.0 0.3 0.0 +node 8 coords 3 0.1 0.3 0.0 +# +node 9 coords 3 0.0 0.4 0.0 +node 10 coords 3 0.1 0.4 0.0 +node 11 coords 3 0.0 0.5 0.0 +node 12 coords 3 0.1 0.5 0.0 +# +node 13 coords 3 0.0 0.6 0.0 +node 14 coords 3 0.1 0.6 0.0 +node 15 coords 3 0.0 0.7 0.0 +node 16 coords 3 0.1 0.7 0.0 +# +node 17 coords 3 0.0 0.8 0.0 +node 18 coords 3 0.1 0.8 0.0 +node 19 coords 3 0.0 0.9 0.0 +node 20 coords 3 0.1 0.9 0.0 +# +# +# ELEMENTS +# +quad1mt 1 nodes 4 1 2 4 3 +# +quad1mt 2 nodes 4 5 6 8 7 +# +quad1mt 3 nodes 4 9 10 12 11 +# +quad1mt 4 nodes 4 13 14 16 15 +# +quad1mt 5 nodes 4 17 18 20 19 +# +# CROSSECTION +# +SimpleTransportCS 1 thickness 1.0 mat 1 set 1 +# +# +# MATERIAL +# +isolinmoisturemat 1 d 2400. perm 1.e-5 capa 1. +# +# +# BOUNDARY & INITIAL CONDITIONS +# +BoundaryCondition 1 loadTimeFunction 1 dofs 1 14 values 1 0.98 set 2 +BoundaryCondition 2 loadTimeFunction 2 dofs 1 14 values 1 1. set 0 +BoundaryCondition 3 loadTimeFunction 3 dofs 1 14 values 1 1. set 3 +# +InitialCondition 1 dofs 1 14 Conditions 1 u 0.98 set 4 +InitialCondition 2 dofs 1 14 Conditions 1 u 0.5 set 5 +# +# +# TIME FUNCTION +# +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 0.5 +PiecewiseLinfunction 3 npoints 8 t 8 -1.e6 14.0 14.1 15. 24. 114. 1014. 10014. f(t) 8 0.98 0.98 0.98 0.9 0.8 0.7 0.6 0.5 +# +Set 1 elementranges {(1 5)} +Set 2 elements 3 1 2 5 +Set 3 elements 2 3 4 +Set 4 elements 4 1 3 4 5 +Set 5 elements 1 2 diff --git a/tests/tmsm/MPS_06_casting_tmsm.in b/tests/tmsm/MPS_06_casting_tmsm.in new file mode 100644 index 000000000..258e209b7 --- /dev/null +++ b/tests/tmsm/MPS_06_casting_tmsm.in @@ -0,0 +1,3 @@ +MPS_06_casting_tmsm.out +tests on creep at variable relative humidity, structural material is cast at time = 14 days, the results correspond to MPS_06_casting_tmsm.in +StaggeredProblem nsteps 28 prob1 "MPS_06_casting_in.tm" prob2 "MPS_06_casting_in.sm" prescribedtimes 28 0. 13.9999999999 14.0000000001 14.0001 14.0002 14.0005 14.001 14.002 14.005 14.01 14.02 14.05 14.1 14.2 14.5 15. 16. 19. 24. 34. 64. 114. 214. 514. 1014. 2014. 5014. 10014. diff --git a/tests/tmsm/MPS_06_in.sm b/tests/tmsm/MPS_06_in.sm index 6c4db7744..59a82f5fd 100644 --- a/tests/tmsm/MPS_06_in.sm +++ b/tests/tmsm/MPS_06_in.sm @@ -73,15 +73,15 @@ SimpleCS 5 thick 1.0 material 5 # # MATERIAL # -mps 1 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 t0 7. mus 5.e-6 alpha_as 700. +mps 1 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 mus 5.e-6 alpha_as 700. # -mps 2 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 t0 7. mus 5.e-6 eps_cas0 -100.e-6 +mps 2 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 mus 5.e-6 eps_cas0 -100.e-6 # -mps 3 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.001 t0 7. mus 5.e-6 +mps 3 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.001 mus 5.e-6 # -mps 4 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.001 t0 7. mus 5.e-6 eps_cas0 -100.e-6 +mps 4 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.001 mus 5.e-6 eps_cas0 -100.e-6 # -mps 5 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 t0 7. mus 5.e-6 b4_cem_type 0 +mps 5 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 mus 5.e-6 b4_cem_type 0 # # BOUNDARY CONDITIONS # diff --git a/tests/tmsm/MPS_07_in.sm b/tests/tmsm/MPS_07_in.sm new file mode 100644 index 000000000..2738658a2 --- /dev/null +++ b/tests/tmsm/MPS_07_in.sm @@ -0,0 +1,96 @@ +MPS_07.out.sm +drying creep described of plane-stress elements in tension, testing tau_nano parameter, drying shrinkage set to zero +# +# element 1: reference case +# element 2: tau_nano = 10 days +# element 3: tau_nano = 100 days +# +StaticStructural nsteps 25 prescribedTimes 25 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. nmodules 1 miniter 1 +# +errorcheck +# vtkxml tstep_step 1 domain_all vars 2 1 4 primvars 1 1 +# +domain 2dPlaneStress +# +OutputManager tstep_all dofman_all element_all +ndofman 12 nelem 3 ncrosssect 3 nmat 3 nbc 3 nic 0 nltf 2 nset 3 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.1 0.0 0.0 +node 3 coords 3 0.0 0.1 0.0 +node 4 coords 3 0.1 0.1 0.0 +# +node 5 coords 3 0.0 0.2 0.0 +node 6 coords 3 0.1 0.2 0.0 +node 7 coords 3 0.0 0.3 0.0 +node 8 coords 3 0.1 0.3 0.0 +# +node 9 coords 3 0.0 0.4 0.0 +node 10 coords 3 0.1 0.4 0.0 +node 11 coords 3 0.0 0.5 0.0 +node 12 coords 3 0.1 0.5 0.0 +# +# +# ELEMENTS +# +planestress2d 1 nodes 4 1 2 4 3 crossSect 1 +# +planestress2d 2 nodes 4 5 6 8 7 crossSect 2 +# +planestress2d 3 nodes 4 9 10 12 11 crossSect 3 +# +# +Set 1 nodes 6 1 3 5 7 9 11 +Set 2 nodes 3 1 5 9 +Set 3 nodes 6 2 4 6 8 10 12 +# +# CROSSECTION +# +SimpleCS 1 thick 1.0 material 1 +SimpleCS 2 thick 1.0 material 2 +SimpleCS 3 thick 1.0 material 3 +# +# +# MATERIAL +# +mps 1 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 p 1000. k3 10. +# +mps 2 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 p 1000. k3 10. tau_nano 10. +# +mps 3 d 0. n 0.2 talpha 12.e-6 referencetemperature 296. mode 0 fc 30. cc 350. w/c 0.5 a/c 6. stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 0.1 CoupledAnalysisType 2 ksh 0.0 p 1000. k3 10. tau_nano 100. +# +# BOUNDARY CONDITIONS +# +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0. set 2 +NodalLoad 3 loadTimeFunction 2 dofs 2 1 2 components 2 1. 0. set 3 +# +# +# TIME FUNCTION +# +ConstantFunction 1 f(t) 1.0 +ConstantFunction 2 f(t) 0.05 +# +# +#%BEGIN_CHECK% tolerance 1e-11 +#TIME +#NODE tStep 5 number 2 dof 1 unknown d value 2.330264e-05 +#NODE tStep 11 number 2 dof 1 unknown d value 3.204497e-05 +#NODE tStep 17 number 2 dof 1 unknown d value 3.903845e-05 +#NODE tStep 20 number 2 dof 1 unknown d value 4.204069e-05 +#NODE tStep 23 number 2 dof 1 unknown d value 4.490697e-05 +#NODE tStep 5 number 6 dof 1 unknown d value 2.330264e-05 +#NODE tStep 11 number 6 dof 1 unknown d value 3.204497e-05 +#NODE tStep 17 number 6 dof 1 unknown d value 3.869937e-05 +#NODE tStep 20 number 6 dof 1 unknown d value 4.203854e-05 +#NODE tStep 23 number 6 dof 1 unknown d value 4.499970e-05 +#NODE tStep 5 number 10 dof 1 unknown d value 2.330264e-05 +#NODE tStep 11 number 10 dof 1 unknown d value 3.204497e-05 +#NODE tStep 17 number 10 dof 1 unknown d value 3.854607e-05 +#NODE tStep 20 number 10 dof 1 unknown d value 4.139412e-05 +#NODE tStep 23 number 10 dof 1 unknown d value 4.495340e-05 +#%END_CHECK% + diff --git a/tests/tmsm/MPS_07_in.tm b/tests/tmsm/MPS_07_in.tm new file mode 100644 index 000000000..e4ed7de5c --- /dev/null +++ b/tests/tmsm/MPS_07_in.tm @@ -0,0 +1,63 @@ +MPS_07.out.tm +drying from rh = 0.98 to 0.5 +# +transienttransport nsteps 26 alpha 0.5 exportfields 1 6 prescribedtimes 26 1.e-10 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. +# nmodules 1 +# +# vtkxml tstep_all domain_all primvars 1 3 +# +domain mass1transfer +# +OutputManager tstep_all dofman_all element_all +ndofman 12 nelem 3 ncrosssect 1 nmat 1 nbc 1 nic 1 nltf 1 nset 1 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.1 0.0 0.0 +node 3 coords 3 0.0 0.1 0.0 +node 4 coords 3 0.1 0.1 0.0 +# +node 5 coords 3 0.0 0.2 0.0 +node 6 coords 3 0.1 0.2 0.0 +node 7 coords 3 0.0 0.3 0.0 +node 8 coords 3 0.1 0.3 0.0 +# +node 9 coords 3 0.0 0.4 0.0 +node 10 coords 3 0.1 0.4 0.0 +node 11 coords 3 0.0 0.5 0.0 +node 12 coords 3 0.1 0.5 0.0 +# +# +# ELEMENTS +# +quad1mt 1 nodes 4 1 2 4 3 +# +quad1mt 2 nodes 4 5 6 8 7 +# +quad1mt 3 nodes 4 9 10 12 11 +# +# CROSSECTION +# +SimpleTransportCS 1 thickness 1.0 mat 1 set 1 +# +# +# MATERIAL +# +isolinmoisturemat 1 d 2400. perm 1.e-5 capa 1. +# +# +# BOUNDARY & INITIAL CONDITIONS +# +BoundaryCondition 1 loadTimeFunction 1 dofs 1 14 values 1 1. set 1 +# +InitialCondition 1 dofs 1 14 Conditions 1 u 0.98 set 1 +# +# +# TIME FUNCTION +# +PiecewiseLinfunction 1 npoints 8 t 8 -1.e6 0.0 0.1 1. 10. 100. 1000. 10000. f(t) 8 0.98 0.98 0.98 0.9 0.8 0.7 0.6 0.5 +# +Set 1 elementranges {(1 3)} + diff --git a/tests/tmsm/MPS_07_tmsm.in b/tests/tmsm/MPS_07_tmsm.in new file mode 100644 index 000000000..1da551ad1 --- /dev/null +++ b/tests/tmsm/MPS_07_tmsm.in @@ -0,0 +1,3 @@ +MPS_07_tmsm.out +drying creep without drying shrinkage; testing tau_nano parameter which enables to delay drying creep after shrinkage +StaggeredProblem nsteps 26 prob1 "MPS_07_in.tm" prob2 "MPS_07_in.sm" prescribedtimes 26 1.e-10 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. diff --git a/tests/tmsm/MPS_block01_in.sm b/tests/tmsm/MPS_block01_in.sm index f2d3b8951..13f062712 100644 --- a/tests/tmsm/MPS_block01_in.sm +++ b/tests/tmsm/MPS_block01_in.sm @@ -73,7 +73,7 @@ simpleCS 2 material 2 area 7.8540e-005 set 2 # # concrete (bricks): #Model for autogenous shrinkage is 0 -MPSdamMat 1 d 0.00244552 n 0.2 talpha 0.000010 mode 0 fc 40.000000 cc 200.000000 w/c 0.550000 a/c 10.680000 stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 300. endoftimeofinterest 864.e4 relMatAge 14400.000000 CoupledAnalysisType 3 t0 14400.000000 k3 35. p 1000. kTm 0.5 timeDepFracturing fib_s 0.200000 Ft28 1.9 Gf28 0.0001 b4_cem_type 0 b4_eps_au_infty -0.0018 isotropic temperInCelsius castingTime 28800.000000 checkSnapBack 1 +MPSdamMat 1 d 0.00244552 n 0.2 talpha 0.000010 mode 0 fc 40.000000 cc 200.000000 w/c 0.550000 a/c 10.680000 stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 300. endoftimeofinterest 864.e4 relMatAge 14400.000000 CoupledAnalysisType 3 k3 35. p 1000. kTm 0.5 timeDepFracturing fib_s 0.200000 Ft28 1.9 Gf28 0.0001 b4_cem_type 0 b4_eps_au_infty -0.0018 isotropic temperInCelsius castingTime 28800.000000 checkSnapBack 1 # springs (interfaces): # steel (single): Steel1 2 d 78.5e-3 E 200.e3 n 0.3 talpha 10e-6 Ry 550.000000 castingTime 28800.000000 diff --git a/tests/tmsm/MPS_block02_in.sm b/tests/tmsm/MPS_block02_in.sm index 2ae961e80..d2eaebaef 100644 --- a/tests/tmsm/MPS_block02_in.sm +++ b/tests/tmsm/MPS_block02_in.sm @@ -73,7 +73,7 @@ simpleCS 2 material 2 area 1.e-4 set 2 # # concrete (bricks): #Model for autogenous shrinkage is 0 -MPSdamMat 1 d 0.00244552 n 0.2 talpha 0.000010 mode 0 fc 40.000000 cc 200.000000 w/c 0.550000 a/c 10.680000 stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 300. endoftimeofinterest 864.e4 relMatAge 14400.000000 CoupledAnalysisType 3 t0 14400.000000 k3 35. p 1000. kTm 0.5 timeDepFracturing fib_s 0.200000 Ft28 1.3 Gf28 0.0001 b4_cem_type 0 b4_eps_au_infty -0.0018 isotropic temperInCelsius castingTime 28800.000000 checkSnapBack 1 +MPSdamMat 1 d 0.00244552 n 0.2 talpha 0.000010 mode 0 fc 40.000000 cc 200.000000 w/c 0.550000 a/c 10.680000 stiffnessfactor 1.e6 timefactor 1. lambda0 86400. begoftimeofinterest 300. endoftimeofinterest 864.e4 relMatAge 14400.000000 CoupledAnalysisType 3 k3 35. p 1000. kTm 0.5 timeDepFracturing fib_s 0.200000 Ft28 1.3 Gf28 0.0001 b4_cem_type 0 b4_eps_au_infty -0.0018 isotropic temperInCelsius castingTime 28800.000000 checkSnapBack 1 # springs (interfaces): # steel (single): Steel1 2 d 78.5e-3 E 200.e3 n 0.3 talpha 10e-6 Ry 550.000000 castingTime 28800.000000 diff --git a/tests/tmsm/concretefcmviscoelastic_in.sm b/tests/tmsm/concretefcmviscoelastic_in.sm new file mode 100644 index 000000000..3898df115 --- /dev/null +++ b/tests/tmsm/concretefcmviscoelastic_in.sm @@ -0,0 +1,103 @@ +concretefcmviscoelastic_out.sm +# +tests on creep (mps model) with tensile cracking (fcm model) +# +# +nonlinearstatic nsteps 500 deltaT 1. rtolv 1.e-8 MaxIter 5000 controllmode 1 stiffMode 0 renumber 1 updateelasticstiffnessflag manrmsteps 1 nmodules 1 +# +errorcheck +# vtkxml tstep_step 1 domain_all vars 2 1 4 primvars 1 1 +# +domain 2dPlaneStress +# +OutputManager tstep_all dofman_all element_all +ndofman 16 nelem 4 ncrosssect 4 nmat 4 nbc 3 nic 0 nltf 2 nset 3 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.1 0.0 0.0 +node 3 coords 3 0.0 0.1 0.0 +node 4 coords 3 0.1 0.1 0.0 +# +node 5 coords 3 0.0 0.2 0.0 +node 6 coords 3 0.1 0.2 0.0 +node 7 coords 3 0.0 0.3 0.0 +node 8 coords 3 0.1 0.3 0.0 +# +node 9 coords 3 0.0 0.4 0.0 +node 10 coords 3 0.1 0.4 0.0 +node 11 coords 3 0.0 0.5 0.0 +node 12 coords 3 0.1 0.5 0.0 +# +node 13 coords 3 0.0 0.6 0.0 +node 14 coords 3 0.1 0.6 0.0 +node 15 coords 3 0.0 0.7 0.0 +node 16 coords 3 0.1 0.7 0.0 +# +# +# ELEMENTS +# +planestress2d 1 nodes 4 1 2 4 3 crossSect 1 +# +planestress2d 2 nodes 4 5 6 8 7 crossSect 2 +# +planestress2d 3 nodes 4 9 10 12 11 crossSect 3 +# +planestress2d 4 nodes 4 13 14 16 15 crossSect 4 +# +# CROSSECTION +# +SimpleCS 1 thick 1.0 material 1 +SimpleCS 2 thick 1.0 material 2 +SimpleCS 3 thick 1.0 material 3 +SimpleCS 4 thick 1.0 material 4 +# +# +# MATERIAL +# +# viscoelastic material with constant Gf and Ft +ConcreteFcmViscoelastic 1 d 0.0 talpha 0. E 30000. n 0.2 Gf 100.e-6 ft 2. softtype 1 sheartype 2 sf 20. multiplecrackshear shearstrengthtype 1 ncracks 2 shearCoeffNumer 0.001 normalCoeffNumer 0.001 viscomat 4 +# +# material with evolving Gf and Ft according to fib prediction from fc28 +ConcreteFcmViscoelastic 2 d 0.0 talpha 0. E 30000. n 0.2 Gf 100.e-6 ft 2. softtype 1 sheartype 2 sf 20. multiplecrackshear shearstrengthtype 1 ncracks 2 shearCoeffNumer 0.001 normalCoeffNumer 0.001 viscomat 4 timeDepFracturing fib_s 0.20 fcm28 30. timeFactor 1. stiffnessFactor 1.e6 +# +# material with evolving Gf and Ft, evolution according to fib, user-defined 28-day tensile strength and fracture energy +ConcreteFcmViscoelastic 3 d 0.0 talpha 0. E 30000. n 0.2 Gf 100.e-6 ft 2. softtype 1 sheartype 2 sf 20. multiplecrackshear shearstrengthtype 1 ncracks 2 shearCoeffNumer 0.001 normalCoeffNumer 0.001 viscomat 4 timeDepFracturing fib_s 0.20 fcm28 30. timeFactor 1. stiffnessFactor 1.e6 ft28 2. gf28 100.e-6 +# +# pure viscoelastic material without tensile damage, auxiliary material for materials 1-3 +mps 4 d 0. n 0.2 talpha 0. referencetemperature 296. mode 0 fc 30. cc 340. w/c 0.523 a/c 5.28 stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 k3 35. p 1000. +# +# +# BOUNDARY CONDITIONS +# +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0. set 2 +BoundaryCondition 3 loadTimeFunction 2 dofs 1 1 values 1 5.e-5 set 3 +# +# +# TIME FUNCTION +# +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 npoints 5 t 5 -1.e7 0. 1.e2 1.e3 1.e4 f(t) 5 0.0 0.0 0.5 1. 1. +# +Set 1 nodes 8 1 3 5 7 9 11 13 15 +Set 2 nodes 4 1 5 9 13 +Set 3 nodes 8 2 4 6 8 10 12 14 16 +# +#%BEGIN_CHECK% +#REACTION tStep 25 number 2 dof 1 value 8.64341612e-02 tolerance 1.e-8 +#REACTION tStep 25 number 6 dof 1 value 9.43445779e-02 tolerance 1.e-8 +#REACTION tStep 25 number 10 dof 1 value 7.37768215e-02 tolerance 1.e-8 +#REACTION tStep 25 number 14 dof 1 value 1.24295973e-01 tolerance 1.e-8 +#REACTION tStep 35 number 2 dof 1 value 4.76909228e-02 tolerance 1.e-8 +#REACTION tStep 35 number 6 dof 1 value 5.44050636e-02 tolerance 1.e-8 +#REACTION tStep 35 number 10 dof 1 value 4.18889873e-02 tolerance 1.e-8 +#REACTION tStep 35 number 14 dof 1 value 7.38939904e-02 tolerance 1.e-8 +#%END_CHECK% +#TIME +#REACTION number 2 dof 1 +#REACTION number 6 dof 1 +#REACTION number 10 dof 1 +#REACTION number 14 dof 1 diff --git a/tests/tmsm/concretefcmviscoelastic_in.tm b/tests/tmsm/concretefcmviscoelastic_in.tm new file mode 100644 index 000000000..ce5cdb633 --- /dev/null +++ b/tests/tmsm/concretefcmviscoelastic_in.tm @@ -0,0 +1,53 @@ +concretefcmviscoelastic_out.tm +tests on creep with damage +# +transienttransport nsteps 26 alpha 0.5 exportfields 1 6 prescribedtimes 26 1.e-10 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. +# nmodules 1 +# +# vtkxml tstep_all domain_all primvars 1 3 +# +domain mass1transfer +# +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 1 nltf 1 nset 1 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 1.0 0.0 0.0 +node 3 coords 3 0.0 1.0 0.0 +node 4 coords 3 1.0 1.0 0.0 +# +# +# +# +# +# ELEMENTS +# +quad1mt 1 nodes 4 1 2 4 3 +# +# +# +Set 1 elements 1 1 +# +# CROSSECTION +# +SimpleTransportCS 1 thickness 1.0 mat 1 set 1 +# +# +# MATERIAL +# +isolinmoisturemat 1 d 2400. perm 1.e-5 capa 1. +# +# +# BOUNDARY AND INITIAL CONDITIONS +# +BoundaryCondition 1 loadTimeFunction 1 dofs 1 14 values 1 1.0 set 1 +# +InitialCondition 1 conditions 1 u 0.98 dofs 1 14 set 1 +# +# +# TIME FUNCTION +# +PiecewiseLinfunction 1 npoints 8 t 8 -1.e6 0.0 0.1 1. 10. 100. 1000. 10000. f(t) 8 0.98 0.98 0.98 0.9 0.8 0.7 0.6 0.5 diff --git a/tests/tmsm/concretefcmviscoelastic_tmsm.in b/tests/tmsm/concretefcmviscoelastic_tmsm.in new file mode 100644 index 000000000..17a0a47ad --- /dev/null +++ b/tests/tmsm/concretefcmviscoelastic_tmsm.in @@ -0,0 +1,3 @@ +concretefcmviscoelastic_tmsm.out +tests on concrete creep (mps) with damage (concretefcm) +StaggeredProblem nsteps 35 prob1 "concretefcmviscoelastic_in.tm" prob2 "concretefcmviscoelastic_in.sm" prescribedtimes 35 1.e-10 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 60. 70. 80. 90. 100. 200. 500. 600. 700. 800. 900. 1000. 1500. 2000. 5000. 10000. diff --git a/tests/tmsm/concretefcmviscoelasticcasting_in.sm b/tests/tmsm/concretefcmviscoelasticcasting_in.sm new file mode 100644 index 000000000..ff6b530d2 --- /dev/null +++ b/tests/tmsm/concretefcmviscoelasticcasting_in.sm @@ -0,0 +1,104 @@ +concretefcmviscoelasticcasting_out.sm +# +tests on creep (mps model) with tensile cracking (fcm model) +# +# +nonlinearstatic nsteps 500 deltaT 1. rtolv 1.e-8 MaxIter 5000 controllmode 1 stiffMode 0 renumber 1 updateelasticstiffnessflag manrmsteps 1 nmodules 1 +# +errorcheck +# vtkxml tstep_step 1 domain_all vars 2 1 4 primvars 1 1 +# +domain 2dPlaneStress +# +OutputManager tstep_all dofman_all element_all +ndofman 16 nelem 4 ncrosssect 4 nmat 5 nbc 3 nic 0 nltf 2 nset 3 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 0.1 0.0 0.0 +node 3 coords 3 0.0 0.1 0.0 +node 4 coords 3 0.1 0.1 0.0 +# +node 5 coords 3 0.0 0.2 0.0 +node 6 coords 3 0.1 0.2 0.0 +node 7 coords 3 0.0 0.3 0.0 +node 8 coords 3 0.1 0.3 0.0 +# +node 9 coords 3 0.0 0.4 0.0 +node 10 coords 3 0.1 0.4 0.0 +node 11 coords 3 0.0 0.5 0.0 +node 12 coords 3 0.1 0.5 0.0 +# +node 13 coords 3 0.0 0.6 0.0 +node 14 coords 3 0.1 0.6 0.0 +node 15 coords 3 0.0 0.7 0.0 +node 16 coords 3 0.1 0.7 0.0 +# +# +# ELEMENTS +# +planestress2d 1 nodes 4 1 2 4 3 crossSect 1 +# +planestress2d 2 nodes 4 5 6 8 7 crossSect 2 +# +planestress2d 3 nodes 4 9 10 12 11 crossSect 3 +# +planestress2d 4 nodes 4 13 14 16 15 crossSect 4 +# +# CROSSECTION +# +SimpleCS 1 thick 1.0 material 1 +SimpleCS 2 thick 1.0 material 2 +SimpleCS 3 thick 1.0 material 3 +SimpleCS 4 thick 1.0 material 4 +# +# +# MATERIAL +# +# viscoelastic material with constant Gf and Ft +ConcreteFcmViscoelastic 1 d 0.0 talpha 0. E 30000. n 0.2 Gf 100.e-6 ft 2. softtype 1 sheartype 2 sf 20. multiplecrackshear shearstrengthtype 1 ncracks 2 shearCoeffNumer 0.001 normalCoeffNumer 0.001 viscomat 4 castingTime 14. +# +# material with evolving Gf and Ft according to fib prediction from fc28 +ConcreteFcmViscoelastic 2 d 0.0 talpha 0. E 30000. n 0.2 Gf 100.e-6 ft 2. softtype 1 sheartype 2 sf 20. multiplecrackshear shearstrengthtype 1 ncracks 2 shearCoeffNumer 0.001 normalCoeffNumer 0.001 viscomat 4 timeDepFracturing fib_s 0.20 fcm28 30. timeFactor 1. stiffnessFactor 1.e6 castingTime 14. +# +# material with evolving Gf and Ft, evolution according to fib, user-defined 28-day tensile strength and fracture energy +ConcreteFcmViscoelastic 3 d 0.0 talpha 0. E 30000. n 0.2 Gf 100.e-6 ft 2. softtype 1 sheartype 2 sf 20. multiplecrackshear shearstrengthtype 1 ncracks 2 shearCoeffNumer 0.001 normalCoeffNumer 0.001 viscomat 4 timeDepFracturing fib_s 0.20 fcm28 30. timeFactor 1. stiffnessFactor 1.e6 ft28 2. gf28 100.e-6 castingTime 14. +# +# pure viscoelastic material without tensile damage, auxiliary material for materials 1-3 +mps 4 d 0. n 0.2 talpha 0. referencetemperature 296. mode 0 fc 30. cc 340. w/c 0.523 a/c 5.28 stiffnessfactor 1.e6 timefactor 1. lambda0 1. begoftimeofinterest 1.e-6 endoftimeofinterest 1.e4 relMatAge 7. CoupledAnalysisType 2 ksh 0.0 k3 35. p 1000. castingTime 14. preCastingTimeMat 5 +# +IsoLE 5 d 0. n 0.2 E 1.e-6 talpha 0. +# +# BOUNDARY CONDITIONS +# +BoundaryCondition 1 loadTimeFunction 1 dofs 1 1 values 1 0. set 1 +BoundaryCondition 2 loadTimeFunction 1 dofs 1 2 values 1 0. set 2 +BoundaryCondition 3 loadTimeFunction 2 dofs 1 1 values 1 5.e-5 set 3 +# +# +# TIME FUNCTION +# +ConstantFunction 1 f(t) 1.0 +PiecewiseLinFunction 2 npoints 5 t 5 -1.e7 14. 114. 1014. 10014. f(t) 5 0.0 0.0 0.5 1. 1. +# +Set 1 nodes 8 1 3 5 7 9 11 13 15 +Set 2 nodes 4 1 5 9 13 +Set 3 nodes 8 2 4 6 8 10 12 14 16 +# +#%BEGIN_CHECK% +#REACTION tStep 26 number 2 dof 1 value 8.64341612e-02 tolerance 1.e-8 +#REACTION tStep 26 number 6 dof 1 value 9.43445779e-02 tolerance 1.e-8 +#REACTION tStep 26 number 10 dof 1 value 7.37768215e-02 tolerance 1.e-8 +#REACTION tStep 26 number 14 dof 1 value 1.24295973e-01 tolerance 1.e-8 +#REACTION tStep 36 number 2 dof 1 value 4.76909228e-02 tolerance 1.e-8 +#REACTION tStep 36 number 6 dof 1 value 5.44050636e-02 tolerance 1.e-8 +#REACTION tStep 36 number 10 dof 1 value 4.18889873e-02 tolerance 1.e-8 +#REACTION tStep 36 number 14 dof 1 value 7.38939904e-02 tolerance 1.e-8 +#%END_CHECK% +#TIME +#REACTION number 2 dof 1 +#REACTION number 6 dof 1 +#REACTION number 10 dof 1 +#REACTION number 14 dof 1 diff --git a/tests/tmsm/concretefcmviscoelasticcasting_in.tm b/tests/tmsm/concretefcmviscoelasticcasting_in.tm new file mode 100644 index 000000000..e6ac7178c --- /dev/null +++ b/tests/tmsm/concretefcmviscoelasticcasting_in.tm @@ -0,0 +1,53 @@ +concretefcmviscoelasticcasting_out.tm +tests on creep with damage +# +transienttransport nsteps 26 alpha 0.5 exportfields 1 6 prescribedtimes 26 1.e-10 0.0001 0.0002 0.0005 0.001 0.002 0.005 0.01 0.02 0.05 0.1 0.2 0.5 1. 2. 5. 10. 20. 50. 100. 200. 500. 1000. 2000. 5000. 10000. +# nmodules 1 +# +# vtkxml tstep_all domain_all primvars 1 3 +# +domain mass1transfer +# +OutputManager tstep_all dofman_all element_all +ndofman 4 nelem 1 ncrosssect 1 nmat 1 nbc 1 nic 1 nltf 1 nset 1 +# +# +# NODES +# +node 1 coords 3 0.0 0.0 0.0 +node 2 coords 3 1.0 0.0 0.0 +node 3 coords 3 0.0 1.0 0.0 +node 4 coords 3 1.0 1.0 0.0 +# +# +# +# +# +# ELEMENTS +# +quad1mt 1 nodes 4 1 2 4 3 +# +# +# +Set 1 elements 1 1 +# +# CROSSECTION +# +SimpleTransportCS 1 thickness 1.0 mat 1 set 1 +# +# +# MATERIAL +# +isolinmoisturemat 1 d 2400. perm 1.e-5 capa 1. +# +# +# BOUNDARY AND INITIAL CONDITIONS +# +BoundaryCondition 1 loadTimeFunction 1 dofs 1 14 values 1 1.0 set 1 +# +InitialCondition 1 conditions 1 u 0.98 dofs 1 14 set 1 +# +# +# TIME FUNCTION +# +PiecewiseLinfunction 1 npoints 8 t 8 -1.e6 14.0 14.1 15. 24. 114. 1014. 10014. f(t) 8 0.98 0.98 0.98 0.9 0.8 0.7 0.6 0.5 diff --git a/tests/tmsm/concretefcmviscoelasticcasting_tmsm.in b/tests/tmsm/concretefcmviscoelasticcasting_tmsm.in new file mode 100644 index 000000000..6ecbacb45 --- /dev/null +++ b/tests/tmsm/concretefcmviscoelasticcasting_tmsm.in @@ -0,0 +1,3 @@ +concretefcmviscoelasticcasting_tmsm.out +tests on concrete creep (mps) with damage (concretefcm) +StaggeredProblem nsteps 36 prob1 "concretefcmviscoelasticcasting_in.tm" prob2 "concretefcmviscoelasticcasting_in.sm" prescribedtimes 36 13.9999999999 14.0000000001 14.0001 14.0002 14.0005 14.001 14.002 14.005 14.01 14.02 14.05 14.1 14.2 14.5 15. 16. 19. 24. 34. 64. 74. 84. 94. 104. 114. 214. 514. 614. 714. 814. 914. 1014. 1514. 2014. 5014. 10014. diff --git a/tools/extractor.py b/tools/extractor.py index ff48e325f..cac5fa2ab 100755 --- a/tools/extractor.py +++ b/tools/extractor.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # -*- coding: utf-8 -*- # # Extractor.py (c) 2009 Borek Patzak, www.oofem.org @@ -80,7 +80,7 @@ def __init__(self): dofMan_re = re.compile(r""" ^ # beginning of line - (?:Node|RigidArmNode|HangingNode)\s* # char string + (?:Node|RigidArmNode|HangingNode|SlaveNode)\s* # char string (\d+).* # node label """,re.X) @@ -123,7 +123,7 @@ def __init__(self): """, re.X) -gprecord_re = re.compile (r"""[ ]*(stresses|strains|status|element_status|curvatures|moments|jump|traction|{)\s*""",re.X) +gprecord_re = re.compile (r"""[ ]*(stresses|strains|status|element_status|curvatures|moments|remark|jump|traction|{)\s*""",re.X) #gpstrain_re = re.compile (r"""[ ]strains\s*([\s+-e\d]+)""",re.X) #gpstatus_re = re.compile (r"""status\s.*""", re.X) #gpelementstatus_re = re.compile (r"""element_status\s.*""", re.X) @@ -176,6 +176,7 @@ def __init__(self): def getKeywordValue (infilename, record, kwd, optional = None): match = re.search (kwd+'\s+\"*([\\\.\+\-,:\w]+)\"*', record) if match: + #print('\nFOUND', kwd, 'WITH', match.group(1)) return match.group(1) else: #issue an error if argument compulsory @@ -195,10 +196,20 @@ def elemKwdToString(kwd): return 'strains' elif (kwd == '13') : return 'damage' + elif (kwd == '56') : + return 'flow' + elif (kwd == '91') : + return 'F' + elif (kwd == '92') : + return 'P' + elif (kwd == '39') : + return 'DoH' elif (kwd == '98') : return 'jump' elif (kwd == '99') : return 'traction' + elif (kwd == '135') : + return 'equivalentTime' else: # keyword is something else -> allow to use the string directly return kwd; @@ -230,6 +241,7 @@ def parse_input_rec (context, recline): cmpn = int(getKeywordValue(context.infilename, recline, 'component')) value = float(getKeywordValue(context.infilename, recline, 'value', 0.0)) kwd = elemKwdToString(kwd) + if debug: print('er', tstep, number, irule, gp, kwd, cmpn, value) return ('er', tstep, number, irule, gp, kwd, cmpn, value) except ValueError: @@ -309,8 +321,8 @@ def check_element_rec (context, kwd, line): if ((rec[0]=='er') and timeflag and (context.recnumber == rec[2]) and (context.recirule==rec[3]) and (context.recgpnum == rec[4])): #print ( "Found er: looking for ",rec[5],"in ", line ) - - match=re.search(rec[5]+'\s*((([-]*\d+(\.\d+)?(e[+-]\d+)?)\s*)+)', line) + + match=re.search(rec[5]+'\s*((([+-]*\d+(\.\d+)?(e[+-]\d+)?)\s*)+)', line) if match: # print ( "match: ",match.group(1) ) context.recVal[irec]=re.split('\s+',match.group(1))[rec[6]-1] @@ -463,19 +475,19 @@ def match_gpsubrec (context, aline): ppmatch = gpDamage_re.search(aline) if ppmatch: check_element_rec (context, 'damage', aline) - if debug: print ( " damage rec %s" % aline ) + if debug: print ( " damage record %s" % aline ) return 1 #state variables in transport problems ppmatch = gpstate_re.search(aline) if ppmatch: check_element_rec (context, 'state', aline) - if debug: print ( " state rec %s" % aline ) + if debug: print ( " state record %s" % aline ) return 1 #flow vector in transport problems ppmatch = gpflow_re.search(aline) if ppmatch: check_element_rec (context, 'flow', aline) - if debug: print ( " flow rec %s" % aline ) + if debug: print ( " flow record %s" % aline ) return 1 #Degree of hydration in cement hydration models ppmatch = gpDoH_re.search(aline) @@ -496,7 +508,7 @@ def match_singlegprec (context, line): if match: context.recirule=int(match.group(1)) context.recgpnum=int(match.group(2)) - if debug: print ( " gp", context.recgpnum ) + if debug: print ( " gp", context.recirule,'.', context.recgpnum ) match_gpsubrec (context, line) for line in context.infile: match=gp_re.search(line) diff --git a/tools/rve_generator/hexagrid.py b/tools/rve_generator/hexagrid.py old mode 100755 new mode 100644 diff --git a/tools/unv2oofem/FEM.py b/tools/unv2oofem/FEM.py index 4cd9e9b9a..1a1d7ec05 100644 --- a/tools/unv2oofem/FEM.py +++ b/tools/unv2oofem/FEM.py @@ -44,7 +44,7 @@ def __init__(self,id,name): def Line2Float(line): """Convert a string into a list of Float""" - return [float(x) for x in line.split()] + return [float(x.replace('D', 'E')) for x in line.split()] # support for GMSH def Line2Int(line): """Convert a string into a list of Int""" diff --git a/tools/unv2oofem/oofemctrlreader.py b/tools/unv2oofem/oofemctrlreader.py index bdc55b4d5..4f9dc44d5 100644 --- a/tools/unv2oofem/oofemctrlreader.py +++ b/tools/unv2oofem/oofemctrlreader.py @@ -122,7 +122,7 @@ def parseGroup(self,FEM): lineSplit = line.split() if len(lineSplit) == 0: break; - #print "Line: ", line, + #print("Line: ", line) if lineSplit[0].lower() == 'nodeprop': if (lineSplit[-2].lower()=='set'): for igroup in groups: @@ -135,16 +135,23 @@ def parseGroup(self,FEM): __gr=self.getNodeGroup(FEM, igroup) __gr.oofem_properties=' '.join(lineSplit[1:-2]) str = "\t\tGroup of nodes \"%s\" has properties: %s" % (igroup, __gr.oofem_properties) + if igroup.startswith('OOFEM-Hanging'): + __gr.oofem_hangingNode = True + str += ' and are HANGING nodes' print (str) else: str = "WARNING: Group of nodes \"%s\" does not exist" % igroup print (str) else: for igroup in groups: + #print("igroup", igroup) __gr=self.getNodeGroup(FEM,igroup) if __gr: __gr.oofem_properties=' '.join(lineSplit[1:]) str = "\t\tGroup of nodes \"%s\" has properties: %s" % (igroup, __gr.oofem_properties) + if igroup.startswith('OOFEM-Hanging'): + __gr.oofem_hangingNode = True + str += ' and are HANGING nodes' print (str) else: str = "WARNING: Group of nodes \"%s\" does not exist" % igroup @@ -297,6 +304,7 @@ def parse(self, FEM): #init group properties on UNV data for igroup in FEM.nodesets:#defined in ctrl file igroup.oofem_properties="" + igroup.oofem_hangingNode = False igroup.oofem_sets=[] for igroup in FEM.elemsets:#defined in ctrl file igroup.oofem_properties="" diff --git a/tools/unv2oofem/unv2oofem.py b/tools/unv2oofem/unv2oofem.py index fa6e764e4..e5cd4b484 100755 --- a/tools/unv2oofem/unv2oofem.py +++ b/tools/unv2oofem/unv2oofem.py @@ -6,6 +6,7 @@ from oofemctrlreader import * import time import sys +import json from numpy.core.defchararray import splitlines @@ -55,12 +56,12 @@ """ % (sys.version_info.major, sys.version_info.minor) print (welcomeMsg) t1 = time.time() - if len(sys.argv)==4: + if (len(sys.argv)==4): unvfile=sys.argv[1] ctrlfile=sys.argv[2] oofemfile=sys.argv[3] of=open(oofemfile,'w') - + # read file in FEM object structure fileExtension = unvfile.split('.') if (fileExtension[-1].lower()=='unv'): # Salome output file @@ -71,18 +72,18 @@ print ("Unknown extension of input file %s" % fileExtension[-1].lower()) exit(0) - print ('Parsing mesh file %s' % sys.argv[1], end='') + print ('Parsing mesh file %s' % sys.argv[1], end=' ') FEM=Parser.parse() print ("done") - print ("Detected node groups:", end='') + print ("Detected node groups:", end=' ') for i in FEM.nodesets: - print (i.name.strip(), end='') + print (i.name.strip(), end=' ') print () - print ("Detected element groups:", end='') + print ("Detected element groups:", end=' ') for i in FEM.elemsets: - print (i.name.strip(), end='') + print (i.name.strip(), end=' ') print () # read oofem ctrl file @@ -110,6 +111,7 @@ for igroup in elem.oofem_groups: #print igroup.name properties+=igroup.oofem_properties + #print('Properties', properties) #Do output if oofem_elemtype resolved and not BoundaryLoads if ( elem.oofem_elemtype): if(CTRL.oofem_elemProp[elem.oofem_elemtype].name != 'RepresentsBoundaryLoad'): @@ -194,12 +196,19 @@ #write component record of.write('ndofman %d nelem %d ncrosssect %d nmat %d nbc %d nic %d nltf %d nset %d nxfemman %d\n' % (FEM.nnodes, len(elemNotBoundary), CTRL.ncrosssect, CTRL.nmat, CTRL.nbc, CTRL.nic, CTRL.nltf, CTRL.nset, CTRL.nxfemman)) + #write nodes for node in FEM.nodes: - #resolve nodal properties - outputLine="node %-5d coords %-2d" % (node.id, len(node.coords)) + hanging = False + for igroup in node.oofem_groups: + if (igroup.oofem_hangingNode): + hanging = True + + outputLine="%s %-5d coords %-2d" % ('hangingNode' if hanging else 'node', node.id, len(node.coords)) + for coord in node.coords: outputLine+= "% -8g " % coord + properties="" for igroup in node.oofem_groups: diff --git a/tools/unv2oofem/unv2x.py b/tools/unv2oofem/unv2x.py index cd793f7eb..4f558d6d4 100644 --- a/tools/unv2oofem/unv2x.py +++ b/tools/unv2oofem/unv2x.py @@ -11,6 +11,8 @@ # some datasets from UNV file and store them in a FEM object structure # To Do: add UNV data handler functions for other datasets (to be defined) # add your own code to write the model into your own file format +# For documentation see http://sdrl.uc.edu/sdrl/referenceinfo/universalfileformats/file-format-storehouse/universal-file-datasets-summary + import os import os.path import sys @@ -32,31 +34,33 @@ def __init__(self,filename): def mapping(self): """Returns mapping for .unv elements""" - # Table of element properties. It contains mapping of nodes, edges and faces between unv and OOFEM element. + #Table of element properties. It contains mapping of nodes, edges and faces between unv and OOFEM element. - # TODO: Use a linked list where each oofem element is linked to the type of element and use the linked list when mapping occurs. In that way, we only need to specify each type of element (descritization) once. + # TODO: Use a linked list where each oofem element is linked to the type of element and use the linked list when mapping occurs. In that way, we only need to specify each type of element (discretization) once. oofem_elemProp = [] oofem_elemProp.append(oofem_elementProperties("None", [0], [], []))#leave this line [0] as it is - oofem_elemProp.append(oofem_elementProperties("RepresentsBoundaryLoad", [],[],[]))#special element representing boundary load + oofem_elemProp.append(oofem_elementProperties("RepresentsBoundaryLoad", [],[],[]))#special element representing boundary load (edge or surface) oofem_elemProp.append(oofem_elementProperties("Truss1D", [0,1], [], [])) oofem_elemProp.append(oofem_elementProperties("Interface1d", oofem_elemProp[-1])) - oofem_elemProp.append(oofem_elementProperties("intelline1", [0,1,2,3], [], [])) oofem_elemProp.append(oofem_elementProperties("Truss2D", [0,1], [0,1],[])) oofem_elemProp.append(oofem_elementProperties("Truss3D",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("Beam2D",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("LIBeam2D",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("LIBeam2Dnl",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("Beam3D",oofem_elemProp[-1])) + oofem_elemProp.append(oofem_elementProperties("Line1ht",oofem_elemProp[-1])) + oofem_elemProp.append(oofem_elementProperties("Line1mt",oofem_elemProp[-1])) + oofem_elemProp.append(oofem_elementProperties("Line1hmt",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("LIBeam3D",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("LIBeam3D2",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("LIBeam3Dnl",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("LIBeam3Dnl2",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("IntELPoint",oofem_elemProp[-1])) #oofem_elemProp.append(oofem_elementProperties("TrPlaneStress2D", [0,2,1], [[0,2],[2,1],[1,0]],[])) #checked - current numbering of triangle nodes is anti-clockwise, the same orientation as in OOFEM. - oofem_elemProp.append(oofem_elementProperties("TrPlaneStress2D", [0,1,2], [[0,1],[1,2],[2,0]],[])) #old version of UNV export in SALOME, nodes on triangular elements are numbered clockwise + oofem_elemProp.append(oofem_elementProperties("TrPlaneStress2D", [0,1,2], [[0,1],[1,2],[2,0]],[])) #old version of UNV export in SALOME, nodes on triangular elements are numbered clockwise. oofem_elemProp.append(oofem_elementProperties("TrPlaneStress2DXFEM", oofem_elemProp[-1])) - oofem_elemProp.append(oofem_elementProperties("TrplaneStrain",oofem_elemProp[-1])) + oofem_elemProp.append(oofem_elementProperties("TrPlaneStrain",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("Axisymm3D",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("Tr1ht",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("Tr1hmt",oofem_elemProp[-1])) @@ -65,7 +69,10 @@ def mapping(self): oofem_elemProp.append(oofem_elementProperties("TrPlaneStrRot",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("CCTplate",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("CCTplate3D",oofem_elemProp[-1])) + oofem_elemProp.append(oofem_elementProperties("Tria1PlateSubSoil",oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("QTrPlStr", [2,0,4,1,5,3], [[2,1,0],[0,5,4],[4,3,2]],[]))#checked + oofem_elemProp.append(oofem_elementProperties("QTrPlStrSlip", [2,0,4,1,5,3], [[2,1,0],[0,5,4],[4,3,2]],[])) + oofem_elemProp.append(oofem_elementProperties("Tria2PlateSubSoil", oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("PlaneStress2D", [0,1,2,3], [[0,1],[1,2],[2,3],[3,0]],[]))#checked oofem_elemProp.append(oofem_elementProperties("PlaneStress2DXFEM", [0,1,2,3], [[0,1],[1,2],[2,3],[3,0]],[]))#checked oofem_elemProp.append(oofem_elementProperties("Quad1PlaneStrain", oofem_elemProp[-1])) @@ -75,7 +82,14 @@ def mapping(self): oofem_elemProp.append(oofem_elementProperties("Quadaxisym1ht", oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("Quadaxisym1hmt", oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("Quadaxisym1mt", oofem_elemProp[-1])) + oofem_elemProp.append(oofem_elementProperties("quad1platesubsoil", oofem_elemProp[-1])) + oofem_elemProp.append(oofem_elementProperties("Interface2dlin", [0,1,3,2], [[0,1],[],[3,2],[]], [])) + oofem_elemProp.append(oofem_elementProperties("IntElLine1", oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("QPlaneStress2D", [2,4,6,0,3,5,7,1], [[2,3,4],[4,5,6],[6,7,0],[0,1,2]],[]))#checked + oofem_elemProp.append(oofem_elementProperties("QPlaneStress2DSlip", [2,4,6,0,3,5,7,1], [[2,3,4],[4,5,6],[6,7,0],[0,1,2]],[])) + oofem_elemProp.append(oofem_elementProperties("QQuad1ht", oofem_elemProp[-1])) + oofem_elemProp.append(oofem_elementProperties("QQuad1mt", oofem_elemProp[-1])) + oofem_elemProp.append(oofem_elementProperties("QQuad1hmt", oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("Quad2plateSubsoil", oofem_elemProp[-1])) oofem_elemProp.append(oofem_elementProperties("LSpace", [4,7,6,5,0,3,2,1], [[4,7],[7,6],[6,5],[5,4],[4,0],[7,3],[6,2],[5,1],[0,3],[3,2],[2,0],[1,0]], [[4,7,6,5],[0,3,2,1],[4,0,3,7],[7,3,2,6],[6,2,1,5],[5,1,0,4]]))#checked oofem_elemProp.append(oofem_elementProperties("Brick1ht", oofem_elemProp[-1])) @@ -92,8 +106,10 @@ def mapping(self): oofem_elemProp.append(oofem_elementProperties("qtrspace", [9, 2, 0, 4, 7, 1, 6, 8, 3, 5], [], [[2,7,9,6,0,1],[2,3,4,8,9,7],[4,3,2,1,0,5],[0,6,9,8,5,4]])) oofem_elemProp.append(oofem_elementProperties("tet21ghostsolid", [9, 2, 0, 4, 7, 1, 6, 8, 3, 5], [], [[2,7,9,6,0,1],[2,3,4,8,9,7],[4,3,2,1,0,5],[0,6,9,8,5,4]])) oofem_elemProp.append(oofem_elementProperties("Tet1BubbleStokes", [0,1,2,3], [[0,1],[1,2],[2,0],[0,3],[1,3],[2,3]], [[0,1,2],[0,1,3],[1,2,3],[0,2,3]])) + oofem_elemProp.append(oofem_elementProperties("Qwedge", [0,2,4,9,11,13,1,3,5,10,12,14,6,7,8], [[0,1,2],[2,3,4],[4,5,0],[9,10,11],[11,12,13],[13,14,9],[0,6,9],[2,7,11],[4,8,13]], [[0,1,2,3,4,5],[9,10,11,12,13,14],[0,1,2,7,11,10,9,6],[2,3,4,8,13,12,11,7],[0,6,9,14,13,8,4,5]])) return oofem_elemProp + def scanfile(self): """ Read file & fill the section list""" loop=True @@ -150,10 +166,19 @@ def UNV2412Reader(self, file, FEM): else: dataline=Line2Int(line1) eltype=dataline[1] - if eltype==11 or eltype==22:# types of elements which are defined on 3 lines - # 1D elements have an additionnal line in their definition + if eltype==11 or eltype==21 or eltype==22:# types of elements which are defined on 3 lines + # 1D elements have an additional line in their definition line3=file.readline() cntvt=Line2Int(line3) + elif eltype==113:#Quadratic wedge has nodes on 2 lines + line3=file.readline() + cntvt = Line2Int(line2) + Line2Int(line3) + #print("Quadratic wedge", cntvt, type(cntvt)) + elif eltype==116:#Quadratic brick element have nodes on 3 lines + line3=file.readline() + line4=file.readline() + cntvt = Line2Int(line2) + Line2Int(line3) + Line2Int(line4) + #print(cntvt, type(cntvt)) elif eltype==118: # Quadratic tetrahedron has nodes on two lines line3=file.readline() cntvt=Line2Int(line2) + Line2Int(line3) @@ -162,13 +187,8 @@ def UNV2412Reader(self, file, FEM): FEM.nodes[cntvt[0]-1].quadratic=0 FEM.nodes[cntvt[4]-1].quadratic=0 # 9, 2, 0, 4 - elif eltype==116:#Quadratic brick element has data on 4 lines - line3=file.readline() - line4=file.readline() - cntvt = Line2Int(line2) + Line2Int(line3) + Line2Int(line4) - #print cntvt, type(cntvt) else: - # standard elements have their connectivities on second line + # standard elements have their connectivities on the second line cntvt=Line2Int(line2) if(len(dataline)<6): print ("I need at least 6 entries on dataline %s" % dataline) diff --git a/uncrustify.cfg b/uncrustify.cfg index b211f375a..dd07ac055 100644 --- a/uncrustify.cfg +++ b/uncrustify.cfg @@ -341,10 +341,10 @@ sp_try_brace = add # ignore/add/remove/force sp_getset_brace = add # ignore/add/remove/force # Add or remove space before the '::' operator -sp_before_dc = add # ignore/add/remove/force +sp_before_dc = remove # ignore/add/remove/force # Add or remove space after the '::' operator -sp_after_dc = add # ignore/add/remove/force +sp_after_dc = remove # ignore/add/remove/force # Add or remove around the D named array initializer ':' operator sp_d_array_colon = add # ignore/add/remove/force @@ -397,7 +397,7 @@ align_with_tabs = false # false/true align_on_tabstop = false # false/true # Whether to left-align numbers -align_number_left = false # false/true +#align_number_left = false # false/true # Align variable definitions in prototypes and functions align_func_params = false # false/true